normalizedEngine() === 'TFS_10');
// ---------------------------------------------------------------------------
// Save
// ---------------------------------------------------------------------------
if (isset($_POST['pid']) && intv($_POST['pid']) > 0) {
$pid = intv($_POST['pid']);
$backToName = trim((string)($_POST['name'] ?? ''));
$isOnline = $isTfs10 ? user_is_online_10($pid) : user_is_online($pid);
if ($isOnline) {
acp_flash_error(t('acp.skl.must_offline'));
} else {
$level = intv($_POST['level'] ?? 1);
$vocation = intv($_POST['vocation'] ?? 0);
// Base stats, derived exactly like character creation does.
$playercnf = $config['player'];
$statgain = $config['vocations_gain'][$vocation] ?? ['hp' => 0, 'mp' => 0, 'cap' => 0];
$levelsFromBase = $level - intv($playercnf['base']['level']);
$newHp = intv($playercnf['base']['health'] + ($statgain['hp'] * $levelsFromBase));
$newMp = intv($playercnf['base']['mana'] + ($statgain['mp'] * $levelsFromBase));
$newCap = intv($playercnf['base']['cap'] + ($statgain['cap'] * $levelsFromBase));
$fist = intv($_POST['fist'] ?? 0);
$club = intv($_POST['club'] ?? 0);
$sword = intv($_POST['sword'] ?? 0);
$axe = intv($_POST['axe'] ?? 0);
$dist = intv($_POST['dist'] ?? 0);
$shield = intv($_POST['shield'] ?? 0);
$fish = intv($_POST['fish'] ?? 0);
$magic = intv($_POST['magic'] ?? 0);
$db = db();
if (!$db->beginTransaction()) {
acp_flash_error('Could not start the database transaction.');
acp_redirect('skills', $backToName !== '' ? ['name' => $backToName] : []);
}
$ok = true;
if (!$isTfs10) {
// TFS 0.x keeps skills in their own table.
foreach ([0 => $fist, 1 => $club, 2 => $sword, 3 => $axe, 4 => $dist, 5 => $shield, 6 => $fish] as $skillId => $skillValue) {
$ok = $ok && $db->execute(
"UPDATE `player_skills` SET `value` = ? WHERE `player_id` = ? AND `skillid` = ? LIMIT 1;",
[$skillValue, $pid, $skillId]
);
}
$ok = $ok && $db->execute("
UPDATE `players`
SET `maglevel` = ?,
`vocation` = ?,
`level` = ?,
`experience` = ?,
`health` = ?,
`healthmax` = ?,
`mana` = ?,
`manamax` = ?,
`cap` = ?
WHERE `id` = ?
LIMIT 1;
", [$magic, $vocation, $level, level_to_experience($level), $newHp, $newHp, $newMp, $newMp, $newCap, $pid]);
} else {
$ok = $db->execute("
UPDATE `players`
SET `vocation` = ?,
`level` = ?,
`experience` = ?,
`health` = ?,
`healthmax` = ?,
`mana` = ?,
`manamax` = ?,
`cap` = ?,
`skill_fist` = ?,
`skill_club` = ?,
`skill_sword` = ?,
`skill_axe` = ?,
`skill_dist` = ?,
`skill_shielding` = ?,
`skill_fishing` = ?,
`maglevel` = ?
WHERE `id` = ?
LIMIT 1;
", [$vocation, $level, level_to_experience($level), $newHp, $newHp, $newMp, $newMp, $newCap, $fist, $club, $sword, $axe, $dist, $shield, $fish, $magic, $pid]);
}
if ($ok) {
$db->commit();
acp_log('player.update_skills', $backToName, [
'level' => $level, 'vocation' => $vocation, 'magic' => $magic,
'fist' => $fist, 'club' => $club, 'sword' => $sword, 'axe' => $axe,
'dist' => $dist, 'shield' => $shield, 'fish' => $fish,
]);
acp_flash_success(t('acp.skl.updated'));
} else {
$db->rollback();
acp_flash_error('Could not update character skills.');
}
}
acp_redirect('skills', $backToName !== '' ? ['name' => $backToName] : []);
}
// ---------------------------------------------------------------------------
// Load
// ---------------------------------------------------------------------------
$name = isset($_GET['name']) ? trim((string)$_GET['name']) : '';
$skills = null;
$pid = 0;
if ($name !== '') {
if (!user_character_exist($name)) {
acp_flash_error(t('acp.skl.not_found', ['name' => '' . h($name) . '']));
acp_redirect('skills');
}
$pid = (int)user_character_id($name);
if (!$isTfs10) {
$rows = db()->fetchAll("
SELECT `value` FROM `player_skills`
WHERE `player_id` = ?
ORDER BY `skillid` ASC
LIMIT 7;
", [$pid]);
// The character can exist without skill rows yet.
$skills = is_array($rows) ? $rows : [];
$player = db()->fetchOne("
SELECT `maglevel`, `level`, `vocation`
FROM `players`
WHERE `id` = ?
LIMIT 1;
", [$pid]);
if (!is_array($player)) {
$player = ['maglevel' => 0, 'level' => 0, 'vocation' => 0];
}
// Pad missing skill rows so indexes 0-6 always exist.
while (count($skills) < 7) {
$skills[] = ['value' => 0];
}
$skills[] = ['value' => $player['maglevel']];
$skills[] = ['value' => $player['level']];
$skills[] = ['value' => $player['vocation']];
} else {
$p = db()->fetchOne("
SELECT `skill_fist`, `skill_club`, `skill_sword`, `skill_axe`,
`skill_dist`, `skill_shielding`, `skill_fishing`,
`maglevel`, `level`, `vocation`
FROM `players`
WHERE `id` = ?
LIMIT 1;
", [$pid]);
if (!is_array($p)) {
$p = [];
}
$skills = [
['value' => $p['skill_fist'] ?? 0],
['value' => $p['skill_club'] ?? 0],
['value' => $p['skill_sword'] ?? 0],
['value' => $p['skill_axe'] ?? 0],
['value' => $p['skill_dist'] ?? 0],
['value' => $p['skill_shielding'] ?? 0],
['value' => $p['skill_fishing'] ?? 0],
['value' => $p['maglevel'] ?? 0],
['value' => $p['level'] ?? 0],
['value' => $p['vocation'] ?? 0],
];
}
}
$loaded = ($name !== '');
?>
= t('acp.skl.lookup_sub') ?>= t('acp.skl.lookup_title') ?>