Index: src/server/adminmanager.cpp =================================================================== --- src/server/adminmanager.cpp (revision 5627) +++ src/server/adminmanager.cpp (working copy) @@ -673,12 +673,14 @@ } else { + if(words[3][0] == '+' || words[3][0] == '-') + insert = true; value = words.GetInt(3); } } else { - value = -2; + help = true; } return true; } @@ -6650,9 +6652,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,15 +6681,16 @@ 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); + // use signed int as we're accepting relative values + int value = data.value; + // use the minimum here to not award values bigger than possible by setting single skill + int max = MIN(MAX_SKILL, MAX_STAT); if (data.skill == "all") { // if the value is out of range, send an error - if (data.value != -1 && (value < 0 || value > max)) + if (!data.insert && (value < 0 || value > max) || data.insert && (value < -max || value > max)) { - psserver->SendSystemError(me->clientnum, "Valid values are between 0 and %u", max); + psserver->SendSystemError(me->clientnum, "Valid values are between 0 and %d", max); return; } @@ -6696,9 +6699,7 @@ psSkillInfo * skill = CacheManager::GetSingleton().GetSkillByID(i); if (skill == NULL) continue; - unsigned int old_value = pchar->Skills().GetSkillRank(skill->id).Current(); - - if(data.value == -1) + if(data.insert && data.value == 0) { PSITEMSTATS_STAT stat = skillToStat(skill->id); if (stat != PSITEMSTATS_STAT_NONE) @@ -6707,32 +6708,49 @@ 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); + psserver->SendSystemInfo(me->clientnum, "Current '%s' of '%s' is %d", 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); + psserver->SendSystemInfo(me->clientnum, "Current '%s' of '%s' is %d (%d)", 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); + psserver->SendSystemInfo(me->clientnum, "Current '%s' of '%s' is %d", 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); + psserver->SendSystemInfo(me->clientnum, "Current '%s' of '%s' is %d (%d)", 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); + int old_value = pchar->Skills().GetSkillRank(skill->id).Current(); + int new_value; + if (data.insert) + { + if (value > 0) + new_value = old_value + value > max ? max : old_value + value; + else + new_value = old_value + value < 0 ? 0 : old_value + value; + } + else + { + new_value = value; + } + + pchar->SetSkillRank(skill->id, new_value); + psserver->SendSystemInfo(me->clientnum, "Changed '%s' of '%s' from %d to %d", skill->name.GetDataSafe(), target->GetName(), old_value, new_value); } } + + if (data.insert && data.value == 0) + return; - 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); + if (data.insert) + psserver->SendSystemOK(target->GetClientID(), "All your skills were adjusted by %d by a GM", value); + else + psserver->SendSystemOK(target->GetClientID(), "All your skills were set to %d by a GM", value); } } else if (data.skill == "copy") @@ -6764,8 +6782,7 @@ return; } - unsigned int old_value = pchar->Skills().GetSkillRank(skill->id).Current(); - if (data.value == -1) + if (data.insert && data.value == 0) { PSITEMSTATS_STAT stat = skillToStat(skill->id); if (stat != PSITEMSTATS_STAT_NONE) @@ -6774,37 +6791,44 @@ 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); + psserver->SendSystemInfo(me->clientnum, "Current '%s' of '%s' is %d", 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); + psserver->SendSystemInfo(me->clientnum, "Current '%s' of '%s' is %d (%d)", 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); + psserver->SendSystemInfo(me->clientnum, "Current '%s' of '%s' is %d", 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); + psserver->SendSystemInfo(me->clientnum, "Current '%s' of '%s' is %d (%d)", 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); + int old_value = pchar->Skills().GetSkillRank(skill->id).Current(); + int new_value; + if (data.insert) + new_value = old_value + value; + else + new_value = value; + if (skill->category == PSSKILLS_CATEGORY_STATS) + max = MAX_STAT; + else if (skill->category != PSSKILLS_CATEGORY_STATS) + max = MAX_SKILL; + + if (new_value > max) + new_value = max; + else if (new_value < 0) + new_value = 0; + + pchar->SetSkillRank(skill->id, new_value); + psserver->SendSystemInfo(me->clientnum, "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", data.skill.GetDataSafe(), new_value); } }