Index: src/server/adminmanager.cpp =================================================================== --- src/server/adminmanager.cpp (revision 5627) +++ src/server/adminmanager.cpp (working copy) @@ -673,12 +673,17 @@ } else { + if (words[3][0] == '+' || words[3][0] == '-') + insert = true; value = words.GetInt(3); + + if (words.GetCount() >= 5) + interval = words.GetInt(4); } } else { - value = -2; + help = true; } return true; } @@ -6650,9 +6655,9 @@ } } // Not a copy, just proceed as normal - else if (data.skill.IsEmpty() || data.value == -2) + else if (data.skill.IsEmpty() || data.help) { - psserver->SendSystemError(me->clientnum, "Syntax: /setskill [target] [skill|'all'] [value|-1] | [target] copy [source]"); + psserver->SendSystemError(me->clientnum, "Syntax: /setskill [target] [skill|'all'] [+-][value] | [target] copy [source]"); return; } @@ -6679,61 +6684,15 @@ return; } - // use unsigned int since skills are never negative (this also takes care of overflows) - unsigned int value = data.value; - unsigned int max = MAX(MAX_SKILL, MAX_STAT); + bool modified = false; if (data.skill == "all") { - // if the value is out of range, send an error - if (data.value != -1 && (value < 0 || value > max)) - { - psserver->SendSystemError(me->clientnum, "Valid values are between 0 and %u", max); - return; - } - for (int i=0; iSkills().GetSkillRank(skill->id).Current(); - - if(data.value == -1) - { - PSITEMSTATS_STAT stat = skillToStat(skill->id); - if (stat != PSITEMSTATS_STAT_NONE) - { - //Handle stats differently to pickup buffs/debuffs - int base = pchar->Stats()[stat].Base(); - int current = pchar->Stats()[stat].Current(); - if (base == current) - psserver->SendSystemInfo(me->clientnum, "Current '%s' of '%s' is %u", skill->name.GetDataSafe(), target->GetName(), base); - else - psserver->SendSystemInfo(me->clientnum, "Current '%s' of '%s' is %u (%u)", skill->name.GetDataSafe(), target->GetName(), base, current); - } else { - int base = pchar->Skills().GetSkillRank(skill->id).Base(); - int current = pchar->Skills().GetSkillRank(skill->id).Current(); - if (base == current) - psserver->SendSystemInfo(me->clientnum, "Current '%s' of '%s' is %u", skill->name.GetDataSafe(), target->GetName(), base); - else - psserver->SendSystemInfo(me->clientnum, "Current '%s' of '%s' is %u (%u)", skill->name.GetDataSafe(), target->GetName(), base, current); - } - } - else - { - pchar->SetSkillRank(skill->id, value); - psserver->SendSystemInfo(me->clientnum, "Changed '%s' of '%s' from %u to %u", skill->name.GetDataSafe(), target->GetName(), old_value,data.value); - } + modified |= ApplySkill(client, target, skill, data.value, data.insert, data.interval); } - - if(data.value != -1) - return; - - if (target->GetClient() && target->GetClient() != client) - { - // Inform the other player. - psserver->SendSystemOK(target->GetClientID(), "All your skills were set to %d by a GM", data.value); - } } else if (data.skill == "copy") { @@ -6741,114 +6700,91 @@ { psSkillInfo * skill = CacheManager::GetSingleton().GetSkillByID(i); if (skill == NULL) continue; - - unsigned int old_value = pchar->Skills().GetSkillRank(skill->id).Current(); - unsigned int new_value = schar->Skills().GetSkillRank(skill->id).Current(); - - pchar->SetSkillRank(skill->id, new_value); - psserver->SendSystemInfo(me->clientnum, "Changed '%s' of '%s' from %u to %u", skill->name.GetDataSafe(), target->GetName(), old_value, new_value); - - if (target->GetClient() && target->GetClient() != client) - { - // Inform the other player. - psserver->SendSystemOK(target->GetClientID(), "Your '%s' level was set to %d by a GM", data.skill.GetDataSafe(), new_value); - } + modified |= ApplySkill(client, target, skill, schar->Skills().GetSkillRank(skill->id).Current()); } } else { psSkillInfo * skill = CacheManager::GetSingleton().GetSkillByName(data.skill); - if (skill == NULL) - { - psserver->SendSystemError(me->clientnum, "Skill not found"); - return; - } - - unsigned int old_value = pchar->Skills().GetSkillRank(skill->id).Current(); - if (data.value == -1) - { - PSITEMSTATS_STAT stat = skillToStat(skill->id); - if (stat != PSITEMSTATS_STAT_NONE) - { - //Handle stats differently to pickup buffs/debuffs - int base = pchar->Stats()[stat].Base(); - int current = pchar->Stats()[stat].Current(); - if (base == current) - psserver->SendSystemInfo(me->clientnum, "Current '%s' of '%s' is %u", skill->name.GetDataSafe(), target->GetName(), base); - else - psserver->SendSystemInfo(me->clientnum, "Current '%s' of '%s' is %u (%u)", skill->name.GetDataSafe(), target->GetName(), base, current); - } else { - int base = pchar->Skills().GetSkillRank(skill->id).Base(); - int current = pchar->Skills().GetSkillRank(skill->id).Current(); - if (base == current) - psserver->SendSystemInfo(me->clientnum, "Current '%s' of '%s' is %u", skill->name.GetDataSafe(), target->GetName(), base); - else - psserver->SendSystemInfo(me->clientnum, "Current '%s' of '%s' is %u (%u)", skill->name.GetDataSafe(), target->GetName(), base, current); - } - return; - } - else if (skill->category == PSSKILLS_CATEGORY_STATS && (value < 0 || value > MAX_STAT)) - { - psserver->SendSystemError(me->clientnum, "Stat values are between 0 and %u", MAX_STAT); - return; - } - else if (skill->category != PSSKILLS_CATEGORY_STATS && (value < 0 || value > MAX_SKILL)) - { - psserver->SendSystemError(me->clientnum, "Skill values are between 0 and %u", MAX_SKILL); - return; - } - - pchar->SetSkillRank(skill->id, value); - psserver->SendSystemInfo(me->clientnum, "Changed '%s' of '%s' from %u to %u", skill->name.GetDataSafe(), target->GetName(), old_value,data.value); - - if (target->GetClient() && target->GetClient() != client) - { - // Inform the other player. - psserver->SendSystemOK(target->GetClientID(), "Your '%s' level was set to %d by a GM", data.skill.GetDataSafe(), data.value); - } + modified |= ApplySkill(client, target, skill, data.value, data.insert, data.interval); } // Send updated skill list to client - if(target->GetClient()) + if(modified && target->GetClient()) psserver->GetProgressionManager()->SendSkillList(target->GetClient(), false); } -/* -void AdminManager::AwardSkillToTarget(int gmClientnum, Client* target, csSring skillName, csString recipient, int levelAward, int limit, bool relative) + +bool AdminManager::ApplySkill(Client* client, gemActor* target, psSkillInfo* skill, int value, bool relative, unsigned int cap) { - psCharacter* charData = player->GetCharacterData(); - unsigned int value = abs(data.value); - unsigned int max = MAX(MAX_SKILL, MAX_STAT); + if (!skill) + { + psserver->SendSystemError(client->GetClientNum(), "Invalid Skill"); + return false; + } - if(skillName == "all") + if (!target || !client) + return false; + + psCharacter * pchar = target->GetCharacterData(); + + if (!pchar) + return false; + + if (relative && !value) { + int base, current; + if (skill->category == PSSKILLS_CATEGORY_STATS) + { + PSITEMSTATS_STAT stat = skillToStat(skill->id); + base = pchar->Stats()[stat].Base(); + current = pchar->Stats()[stat].Current(); + } + else + { + base = pchar->Skills().GetSkillRank(skill->id).Base(); + current = pchar->Skills().GetSkillRank(skill->id).Current(); + } + + if (base == current) + psserver->SendSystemInfo(client->GetClientNum(), "Current '%s' of '%s' is %d", skill->name.GetDataSafe(), target->GetName(), base); + else + psserver->SendSystemInfo(client->GetClientNum(), "Current '%s' of '%s' is %d (%d)", skill->name.GetDataSafe(), target->GetName(), base, current); + return false; } else { - psSkillInfo * skill = CacheManager::GetSingleton().GetSkillByName(skillName); - if (skill == NULL) - { - psserver->SendSystemError(me->clientnum, "Skill not found"); - return; - } - unsigned int oldValue = charData->Skills().GetSkillRank(skill->id).Current(); - charData->SetSkillRank(skill->id, value); - psserver->SendSystemInfo(me->clientnum, "Changed '%s' of '%s' from %u to %u", skill->name.GetDataSafe(), target->GetName(), old_value,data.value); + int old_value = pchar->Skills().GetSkillRank(skill->id).Current(); + int new_value = value; + int max = MAX_SKILL; + + if (relative) + new_value += old_value; + if (skill->category == PSSKILLS_CATEGORY_STATS) + max = MAX_STAT; + + if (cap && cap < max) + max = cap; + + if (new_value > max) + new_value = max; + else if (new_value < 0) + new_value = 0; + + pchar->SetSkillRank(skill->id, new_value); + psserver->SendSystemInfo(client->GetClientNum(), "Changed '%s' of '%s' from %d to %d", skill->name.GetDataSafe(), target->GetName(), old_value, new_value); + if (target->GetClient() && target->GetClient() != client) { // Inform the other player. - psserver->SendSystemOK(target->GetClientID(), "Your '%s' level was set to %d by a GM", data.skill.GetDataSafe(), data.value); + psserver->SendSystemOK(target->GetClientID(), "Your '%s' level was set to %d by a GM", skill->name.GetDataSafe(), new_value); } } - - // Send updated skill list to client - if(target->GetClient()) - psserver->GetProgressionManager()->SendSkillList(target->GetClient(), false); + return true; +} -}*/ - void AdminManager::UpdateRespawn(AdminCmdData& data, Client* client, gemActor* target) { if (!target) Index: src/server/adminmanager.h =================================================================== --- src/server/adminmanager.h (revision 5627) +++ src/server/adminmanager.h (working copy) @@ -51,6 +51,7 @@ class psAdminGameEvent; class psNPCDialog; class psItem; +class psSkillInfo; struct Result; class iResultSet; class Client; @@ -365,6 +366,8 @@ /// Changes the skill of the target void SetSkill(MsgEntry* me, psAdminCmdMessage& msg, AdminCmdData& data, Client* client, gemActor *target); + /// Changes a skill of the target. return true if the skill was changed. + bool ApplySkill(Client* client, gemActor* target, psSkillInfo* skill, int value, bool relative = false, unsigned int cap = 0); /// Temporarily changes the mesh for a player void Morph(MsgEntry* me, psAdminCmdMessage& msg, AdminCmdData& data, Client* client, Client *targetclient);