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; i<PSSKILL_COUNT; i++) { psSkillInfo * skill = CacheManager::GetSingleton().GetSkillByID(i); if (skill == NULL) continue;-- 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);- }- }- 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);