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; @@ -75,6 +76,27 @@ GM_TESTER = 10 }; +struct psRewardData +{ + int expDelta; + + csString factionName; + int factionDelta; + + csString skillName; + int skillDelta; + unsigned int skillCap; + bool relativeSkill; + + csString moneyType; + int moneyCount; + + csString itemName; + unsigned short stackCount; + + psRewardData(); +}; + /** Admin manager that handles GM commands and general game control. */ class AdminManager : public MessageManager @@ -100,8 +122,10 @@ void AdminCreateNewNPC(csString& data); - void AwardExperienceToTarget(int gmClientnum, Client* target, csString recipient, int ppAward); + void AwardExperienceToTarget(int gmClientnum, Client* target, int ppAward); void AdjustFactionStandingOfTarget(int gmClientnum, Client* target, csString factionName, int standingDelta); + bool ApplySkill(int gmClientNum, Client* target, psSkillInfo* skill, int value, bool relative = false, unsigned int cap = 0); + void AwardToTarget(int gmClientNum, Client* target, psRewardData& data); /** Get sector and coordinates of starting point of a map. Returns success. */ bool GetStartOfMap(int clientnum, const csString & map, iSector * & targetSector, csVector3 & targetPoint); @@ -128,7 +152,7 @@ csString type,name; ///< Used by: /location csString sourceplayer; - int value, interval, random; + int value, value2, interval, random; int rainDrops, density, fade; unsigned int mins, hours, days; float amt, x, y, z, rot; @@ -348,6 +372,9 @@ /** Awards experience to a player, by a GM */ void AwardExperience(MsgEntry* me, psAdminCmdMessage& msg, AdminCmdData& data, Client* client, Client* target); + + /** Awards something to a player, by a GM */ + void Award(AdminCmdData& data, Client* client, Client* target); /** Transfers an item from one client to another */ void TransferItem(MsgEntry* me, psAdminCmdMessage& msg, AdminCmdData& data, Client* source, Client* target); Index: src/server/adminmanager.cpp =================================================================== --- src/server/adminmanager.cpp (revision 5627) +++ src/server/adminmanager.cpp (working copy) @@ -91,6 +91,17 @@ //----------------------------------------------------------------------------- +psRewardData::psRewardData() +{ + expDelta = 0; + factionDelta = 0; + skillDelta = 0; + skillCap = 0; + relativeSkill = false; + moneyCount = 0; + stackCount = 0; +} + /** This class asks user to confirm that he really wants to do the area target he/she requested */ class AreaTargetConfirm : public PendingQuestion { @@ -484,6 +495,68 @@ } return true; } + else if (command == "/award") + { + player = words[1]; + + if (words.GetCount() < 4) + { + help = true; + return true; + } + + // initialize PODs + value = 0; + stackCount = 0; + value2 = 0; + interval = 0; + random = 0; + density = 0; + + size_t index = 2; + size_t left; + // doesn't include a check for duplicate award types + while (index < words.GetCount()) + { + subCmd = words[index++]; + left = words.GetCount() - index; + if (subCmd == "exp" && left >= 1) + { + value = words.GetInt(index++); + } + else if (subCmd == "item" && left >= 2) + { + stackCount = words.GetInt(index++); + item = words[index++]; + } + else if (subCmd == "skill" && left >= 2) + { + skill = words[index++]; + if (words[index][0] == '+' || words[index][0] == '-') + insert = true; + value2 = words.GetInt(index++); + interval = words.GetInt(index); + if (interval) + index++; + } + else if (subCmd == "money" && left >= 2) + { + type = words[index++]; + random = words.GetInt(index++); + } + else if (subCmd == "faction" && left >= 2) + { + name = words[index++]; + density = words.GetInt(index++); + } + else + { + help = true; + break; + } + } + return true; + } else if (command == "/checkitem" ) { player = words[1]; @@ -673,12 +746,19 @@ } else { + if (words[3][0] == '+' || words[3][0] == '-') + insert = true; value = words.GetInt(3); + + if (words.GetCount() >= 5) + interval = words.GetInt(4); + else + interval = 0; } } else { - value = -2; + help = true; } return true; } @@ -916,56 +996,85 @@ } else if (subCmd == "reward") { - // "/event reward [range # | all | [player_name]] <#> item" - int rewardIndex = 3; - stackCount = 0; - - if (strspn(words[2].GetDataSafe(), "-0123456789") == words[2].Length()) + // "/event reward ['exp' value] ['item' count item] ['faction' faction value] + // ['skill' [+-]value [max]] ['money' ]" + size_t index = 3; + if (words[2] == "target") { - commandMod.Empty(); - stackCount = words.GetInt(2); - rangeSpecifier = INDIVIDUAL; // expecting a player by target + rangeSpecifier = INDIVIDUAL; } + else if (words[2] == "all") + { + commandMod = "all"; + rangeSpecifier = ALL; + } + else if (words[2] == "range") + { + commandMod = "range"; + rangeSpecifier = IN_RANGE; + range = words.GetFloat(index++); + } else { - commandMod = words[2]; // 'range' or 'all' - range = 0; - if (commandMod == "range") + rangeSpecifier = INDIVIDUAL; + player = words[2]; + } + + size_t left = words.GetCount() - index; + if (left < 2) + { + subCmd = "help"; + help = true; + } + + // initialize PODs + value = 0; + stackCount = 0; + value2 = 0; + interval = 0; + random = 0; + density = 0; + + // doesn't include a check for duplicate award types + while (index < words.GetCount() && !help) + { + subCmd = words[index++]; + left = words.GetCount() - index; + if (subCmd == "exp" && left >= 1) { - rangeSpecifier = IN_RANGE; - if (strspn(words[3].GetDataSafe(), "0123456789.") == words[3].Length()) - { - range = words.GetFloat(3); - rewardIndex = 4; - } + value = words.GetInt(index++); } - else if (commandMod == "all") + else if (subCmd == "item" && left >= 2) { - rangeSpecifier = ALL; + stackCount = words.GetInt(index++); + item = words[index++]; } - else + else if (subCmd == "skill" && left >= 2) { - rangeSpecifier = INDIVIDUAL; - player = words[2]; - commandMod.Empty(); + skill = words[index++]; + if (words[index][0] == '+' || words[index][0] == '-') + insert = true; + value2 = words.GetInt(index++); + interval = words.GetInt(index); + if (interval) + index++; } - - // next 'word' should be numeric: number of items. - if (strspn(words[rewardIndex].GetDataSafe(), "-0123456789") == words[rewardIndex].Length()) + else if (subCmd == "money" && left >= 2) { - stackCount = words.GetInt(rewardIndex); - rewardIndex++; + type = words[index++]; + random = words.GetInt(index++); } + else if (subCmd == "faction" && left >= 2) + { + name = words[index++]; + density = words.GetInt(index++); + } else { subCmd = "help"; help = true; - return true; } } - - // last bit is the item name itself! - item = words.GetTail(rewardIndex); } else if (subCmd == "remove") { @@ -1397,6 +1506,10 @@ { TransferItem(me, msg, data, targetclient, client); } + else if (data.command == "/award" ) + { + Award(data, client, targetclient); + } else if (data.command == "/checkitem" ) { CheckItem(me, msg, data, targetclient); @@ -6252,24 +6365,172 @@ psserver->GetCharManager()->UpdateItemViews(me->clientnum); } -void AdminManager::AwardExperience(MsgEntry* me, psAdminCmdMessage& msg, AdminCmdData& data, Client* client, Client* target) +void AdminManager::Award(AdminCmdData& data, Client* client, Client* target) { + if (data.help) + { + psserver->SendSystemInfo(client->GetClientNum(), "Syntax: \"/award \n" + "['exp' value] ['item' count item] ['skill' [+-]value [max]]\n" + "['money' ] ['faction' faction value]\""); + return; + } + + psRewardData rewardData; + rewardData.expDelta = data.value; + rewardData.itemName = data.item; + rewardData.stackCount = data.stackCount; + rewardData.factionName = data.name; + rewardData.factionDelta = data.density; + rewardData.skillName = data.skill; + rewardData.skillDelta = data.value2; + rewardData.skillCap = data.interval; + rewardData.relativeSkill = data.insert; + rewardData.moneyType = data.type; + rewardData.moneyCount = data.random; + + AwardToTarget(client->GetClientNum(), target, rewardData); +} + +void AdminManager::AwardToTarget(int gmClientNum, Client* target, psRewardData& data) +{ if (!target || !target->GetCharacterData()) { - psserver->SendSystemError(me->clientnum, "Invalid target to award experience to"); + psserver->SendSystemError(gmClientNum, "Invalid target to award"); return; } + psCharacter * pchar = target->GetCharacterData(); + if (pchar->IsNPC()) + { + psserver->SendSystemError(gmClientNum, "You can't use this command on npcs!"); + return; + } + + if (data.expDelta) // award exp + { + AwardExperienceToTarget(gmClientNum, target, data.expDelta); + } + + if (data.itemName && data.stackCount) // award item + { + csString text; + psItemStats* stats = CacheManager::GetSingleton().GetBasicItemStatsByName(data.itemName); + if (!stats) + { + psserver->SendSystemError(gmClientNum, "You have to specify a valid item name"); + } + else if (stats->IsMoney()) + { + psserver->SendSystemError(gmClientNum, "Use the 'money' award to award money, not the 'item' one."); + } + else if (stats->GetBuyPersonalise()) + { + psserver->SendSystemError(gmClientNum, "You cannot award personalized items."); + } + else if (data.stackCount > MAX_STACK_COUNT) + { + text.Format("The value for the stackCount has to be between 0 and %u", MAX_STACK_COUNT); + psserver->SendSystemError(gmClientNum, text); + } + else // create item + { + psItem* item = stats->InstantiateBasicItem(true); + item->SetStackCount(data.stackCount); + item->SetItemQuality(stats->GetQuality()); + item->SetLoaded(); + pchar->Inventory().AddOrDrop(item); + psserver->GetCharManager()->UpdateItemViews(target->GetClientNum()); + + text.Format("You have been awarded %d %s.", data.stackCount, data.itemName.GetDataSafe()); + psserver->SendSystemInfo(gmClientNum, text); + + text.Format("%s has been awarded %d %s.", target->GetName(), data.stackCount, data.itemName.GetDataSafe()); + psserver->SendSystemInfo(gmClientNum, text); + + Debug4(LOG_ADMIN, gmClientNum, "Created %d %s for %s\n", data.stackCount, data.itemName.GetDataSafe(), target->GetName()); + } + } + + if (data.factionName && data.factionDelta) // award faction + { + AdjustFactionStandingOfTarget(gmClientNum, target, data.factionName, data.factionDelta); + } + + if (data.skillName) // award skill + { + bool modified = false; + if (data.skillName == "all") + { + for (int i=0; iGetProgressionManager()->SendSkillList(target, false); + } + } + + if (data.moneyType) // award money + { + bool valid = true; + Money_Slots type; + if(data.moneyType == "trias") + type = MONEY_TRIAS; + else if(data.moneyType == "hexas") + type = MONEY_HEXAS; + else if(data.moneyType == "octas") + type = MONEY_OCTAS; + else if(data.moneyType == "circles") + type = MONEY_CIRCLES; + else + valid = false; + + if (valid) + { + int value; + if (data.moneyCount) + value = data.moneyCount; + else + value = psserver->rng->Get(INT_MAX-1)+1; + psMoney money; + money.Set(type, value); + pchar->AdjustMoney(money, false); + psserver->GetCharManager()->SendPlayerMoney(target); + + Debug4(LOG_ADMIN, gmClientNum, "Created %d %s for %s\n", value, data.moneyType.GetDataSafe(), pchar->GetCharName()); + } + else + { + psserver->SendSystemError(gmClientNum, "Invalid money type"); + } + } +} + +void AdminManager::AwardExperience(MsgEntry* me, psAdminCmdMessage& msg, AdminCmdData& data, Client* client, Client* target) +{ if (data.value == 0) { psserver->SendSystemError(me->clientnum, "Invalid experience specified"); return; } - AwardExperienceToTarget(me->clientnum, target, data.player, data.value); + psRewardData rewardData; + rewardData.expDelta = data.value; + + AwardToTarget(me->clientnum, target, rewardData); } -void AdminManager::AwardExperienceToTarget(int gmClientnum, Client* target, csString recipient, int ppAward) +void AdminManager::AwardExperienceToTarget(int gmClientnum, Client* target, int ppAward) { unsigned int pp = target->GetCharacterData()->GetProgressionPoints(); @@ -6307,7 +6568,7 @@ psserver->SendSystemInfo(target->GetClientNum(),"You lost %d progression points.", -ppAward); } - psserver->SendSystemInfo(gmClientnum, "You awarded %s %d progression points.", recipient.GetData(), ppAward); + psserver->SendSystemInfo(gmClientnum, "You awarded %s %d progression points.", target->GetName(), ppAward); } void AdminManager::AdjustFactionStandingOfTarget(int gmClientnum, Client* target, csString factionName, int standingDelta) @@ -6602,70 +6863,74 @@ void AdminManager::SetSkill(MsgEntry* me, psAdminCmdMessage& msg, AdminCmdData& data, Client* client, gemActor *target) { + if (data.skill.IsEmpty() || data.help) + { + psserver->SendSystemError(me->clientnum, "Syntax: /setskill [target] [skill|'all'] [+-][value] | [target] copy [source]"); + return; + } + + if (!target || target->GetClient() != client && !psserver->CheckAccess(client, "setskill others")) + { + psserver->SendSystemError(me->clientnum, "You have to specify a valid target"); + return; + } + + if (data.skill != "copy") + { + psRewardData rewardData; + rewardData.skillName = data.skill; + rewardData.skillDelta = data.value; + rewardData.relativeSkill = data.insert; + rewardData.skillCap = data.interval; + + AwardToTarget(me->clientnum, target->GetClient(), rewardData); + return; + } + Client* sourceclient = NULL; gemActor* source = NULL; gemObject* sourceobject = NULL; psCharacter * schar = NULL; - // Try to find the source of skills if we're doing a copy - if (data.skill == "copy") + // First try and find the source client by name + if (data.sourceplayer == "me") { - // First try and find the source client by name - if (data.sourceplayer == "me") - { - sourceclient = client; - } - else - { - sourceclient = FindPlayerClient(data.sourceplayer); - } + sourceclient = client; + } + else + { + sourceclient = FindPlayerClient(data.sourceplayer); + } - if (sourceclient) + if (sourceclient) + { + source = sourceclient->GetActor(); + } + // If a search by name didn't work, try and search by pid or eid + else + { + sourceobject = FindObjectByString(data.sourceplayer,client->GetActor()); + if (sourceobject) { - source = sourceclient->GetActor(); + source = sourceobject->GetActorPtr(); } - // If a search by name didn't work, try and search by pid or eid - else - { - sourceobject = FindObjectByString(data.sourceplayer,client->GetActor()); - if (sourceobject) - { - source = sourceobject->GetActorPtr(); - } - } + } - if (source == NULL) - { - psserver->SendSystemError(me->clientnum, "Invalid skill source"); - return; - } - else - { - schar = source->GetCharacterData(); - if (!schar) - { - psserver->SendSystemError(me->clientnum, "No source character data!"); - return; - } - } - } - // Not a copy, just proceed as normal - else if (data.skill.IsEmpty() || data.value == -2) + if (source == NULL) { - psserver->SendSystemError(me->clientnum, "Syntax: /setskill [target] [skill|'all'] [value|-1] | [target] copy [source]"); + psserver->SendSystemError(me->clientnum, "Invalid skill source"); return; } - - if (target == NULL) + else { - psserver->SendSystemError(me->clientnum, "Invalid target for setting skills"); - return; + schar = source->GetCharacterData(); + if (!schar) + { + psserver->SendSystemError(me->clientnum, "No source character data!"); + return; + } } - // Check the permission to set skills for other characters - if (target->GetClient() != client && !psserver->CheckAccess(client, "setskill others")) - return; - psCharacter * pchar = target->GetCharacterData(); if (!pchar) { @@ -6679,176 +6944,90 @@ 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); - if (data.skill == "all") + bool modified = false; + for (int i=0; i max)) - { - psserver->SendSystemError(me->clientnum, "Valid values are between 0 and %u", max); - return; - } + psSkillInfo * skill = CacheManager::GetSingleton().GetSkillByID(i); + if (skill == NULL) continue; + modified |= ApplySkill(me->clientnum, target->GetClient(), skill, schar->Skills().GetSkillRank(skill->id).Current()); + } - for (int i=0; iGetClient()) + psserver->GetProgressionManager()->SendSkillList(target->GetClient(), false); +} - 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); - } - } - - 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") +bool AdminManager::ApplySkill(int client, Client* target, psSkillInfo* skill, int value, bool relative, unsigned int cap) +{ + if (!skill) { - for (int i=0; iSkills().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); - } - } + psserver->SendSystemError(client, "Invalid Skill"); + return false; } - else + + if (!target || !client) + return false; + + psCharacter * pchar = target->GetCharacterData(); + + if (!pchar) + return false; + + if (relative && !value) { - psSkillInfo * skill = CacheManager::GetSingleton().GetSkillByName(data.skill); - if (skill == NULL) + int base, current; + if (skill->category == PSSKILLS_CATEGORY_STATS) { - 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; + base = pchar->Stats()[stat].Base(); + current = pchar->Stats()[stat].Current(); } - else if (skill->category == PSSKILLS_CATEGORY_STATS && (value < 0 || value > MAX_STAT)) + else { - psserver->SendSystemError(me->clientnum, "Stat values are between 0 and %u", MAX_STAT); - return; + base = pchar->Skills().GetSkillRank(skill->id).Base(); + current = pchar->Skills().GetSkillRank(skill->id).Current(); } - 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); - } - } - - // Send updated skill list to client - if(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) -{ - psCharacter* charData = player->GetCharacterData(); - unsigned int value = abs(data.value); - unsigned int max = MAX(MAX_SKILL, MAX_STAT); - - if(skillName == "all") - { + if (base == current) + psserver->SendSystemInfo(client, "Current '%s' of '%s' is %d", skill->name.GetDataSafe(), target->GetName(), base); + else + psserver->SendSystemInfo(client, "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 (target->GetClient() && target->GetClient() != client) + 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, "Changed '%s' of '%s' from %d to %d", skill->name.GetDataSafe(), target->GetName(), old_value, new_value); + + if (target && target->GetClientNum() != 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->GetClientNum(), "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) @@ -7699,7 +7878,7 @@ (data.gmeventName.Length() == 0 || data.gmeventDesc.Length() == 0)) || (data.subCmd == "register" && data.player.Length() == 0 && data.rangeSpecifier == INDIVIDUAL) || (data.subCmd == "remove" && data.player.Length() == 0) || - (data.subCmd == "reward" && data.item.Length() == 0 && data.stackCount == 0) || + (data.subCmd == "reward") || (data.subCmd == "control" && data.gmeventName.Length() == 0) || (data.subCmd == "discard" && data.gmeventName.Length() == 0)) { @@ -7712,7 +7891,9 @@ psserver->SendSystemInfo( me->clientnum, "/event help\n" "/event create \n" "/event register [range | ]\n" - "/event reward [all | range | ] # \n" + "/event reward | > ['skill' [+-]value [max]]\n" + "['exp' value] ['item' count item] ['money' ]\n" + "['faction' faction value]\n" "/event remove \n" "/event complete []\n" "/event list\n" @@ -7766,12 +7947,20 @@ // reward player(s) if (data.subCmd == "reward") { - gmeventResult = gmeventManager->RewardPlayersInGMEvent(client, - data.rangeSpecifier, - data.range, - target, - data.stackCount, - data.item); + psRewardData rewardData; + rewardData.expDelta = data.value; + rewardData.itemName = data.item; + rewardData.stackCount = data.stackCount; + rewardData.factionName = data.name; + rewardData.factionDelta = data.density; + rewardData.skillName = data.skill; + rewardData.skillDelta = data.value2; + rewardData.skillCap = data.interval; + rewardData.relativeSkill = data.insert; + rewardData.moneyType = data.type; + rewardData.moneyCount = data.random; + + gmeventResult = gmeventManager->RewardPlayersInGMEvent(client, data.rangeSpecifier, data.range, target, rewardData); return; } @@ -8426,13 +8615,12 @@ psserver->SendSystemInfo(client->GetClientNum(),"Syntax: \"/assignfaction [me/target/eid/pid/area/name] [factionname] [points]\""); return; } - if(!target) - { - psserver->SendSystemInfo(client->GetClientNum(),"Unable to find the player to assign faction points to."); - return; - } - - AdjustFactionStandingOfTarget(client->GetClientNum(), target, data.name, data.value); + + psRewardData rewardData; + rewardData.factionName = data.name; + rewardData.factionDelta = data.value; + + AwardToTarget(me->clientnum, target, rewardData); } void AdminManager::HandleServerQuit(MsgEntry* me, psAdminCmdMessage& msg, AdminCmdData& data, Client *client ) Index: src/server/gmeventmanager.cpp =================================================================== --- src/server/gmeventmanager.cpp (revision 5627) +++ src/server/gmeventmanager.cpp (working copy) @@ -422,13 +422,10 @@ RangeSpecifier rewardRecipient, float range, Client* target, - short stackCount, - csString itemName) + psRewardData& data) { GMEvent* gmEvent; int clientnum = client->GetClientNum(), zero = 0; - WordArray rewardDesc(itemName); - RewardType rewardType = REWARD_ITEM; PID gmID = client->GetPID(); // make sure GM is running (or assisting) an event @@ -450,50 +447,6 @@ return false; } - // identify reward type: experience, faction points or an item - if (rewardDesc[0] == "exp" && rewardDesc.GetCount() == 1) - rewardType = REWARD_EXPERIENCE; - else if (rewardDesc[0] == "faction" && rewardDesc.GetCount() > 1) - rewardType = REWARD_FACTION_POINTS; - - // retrieve base stats item - psItemStats *basestats; - if (rewardType == REWARD_ITEM) - { - basestats = CacheManager::GetSingleton().GetBasicItemStatsByName(itemName.GetDataSafe()); - if (basestats == NULL) - { - psserver->SendSystemInfo(clientnum, "Reward \'%s\' not recognised.", itemName.GetDataSafe()); - Error2("'%s' was not found as a valid base item.", itemName.GetDataSafe()); - return false; - } - - if (stackCount <= 0) - { - psserver->SendSystemInfo(clientnum, - "You must reward at least 1 item to participant(s)."); - return false; - } - - if (stackCount >= 65 && !basestats->IsMoney()) - { - psserver->SendSystemInfo(clientnum, - "You can't reward that amount of items to partecipant(s)."); - return false; - } - - // cant reward personalised or unique items - if (basestats->GetBuyPersonalise() || basestats->GetUnique()) - { - psserver->SendSystemInfo(clientnum, - "You cannot reward personalised / unique items."); - return false; - } - } - else - basestats = NULL; - - if (rewardRecipient == INDIVIDUAL) { if (!target) @@ -504,12 +457,7 @@ GMEvent* playersEvent = GetGMEventByPlayer(target->GetPID(), RUNNING, zero); if (playersEvent && playersEvent->id == gmEvent->id) { - if (rewardType == REWARD_EXPERIENCE) - psserver->GetAdminManager()->AwardExperienceToTarget(clientnum, target, target->GetName(), stackCount); - else if (rewardType == REWARD_FACTION_POINTS) - psserver->GetAdminManager()->AdjustFactionStandingOfTarget(clientnum, target, rewardDesc.GetTail(1), stackCount); - else - RewardPlayer(clientnum, target, stackCount, basestats); + psserver->GetAdminManager()->AwardToTarget(clientnum, target, data); } else { @@ -531,12 +479,7 @@ { if (rewardRecipient == ALL || clientActor->RangeTo(target->GetActor()) <= range) { - if (rewardType == REWARD_EXPERIENCE) - psserver->GetAdminManager()->AwardExperienceToTarget(clientnum, target, target->GetName(), stackCount); - else if (rewardType == REWARD_FACTION_POINTS) - psserver->GetAdminManager()->AdjustFactionStandingOfTarget(clientnum, target, rewardDesc.GetTail(1), stackCount); - else - RewardPlayer(clientnum, target, stackCount, basestats); + psserver->GetAdminManager()->AwardToTarget(clientnum, target, data); } } } @@ -981,51 +924,6 @@ return SIZET_NOT_FOUND; } -void GMEventManager::RewardPlayer(int clientnum, Client* target, short stackCount, psItemStats* basestats) -{ - // If it's money don't instantiate them just directly give them. - if(basestats->IsMoney()) - { - target->GetActor()->GetCharacterData()->SetMoney(basestats, stackCount); - psserver->SendSystemInfo(target->GetClientNum(), - "You have been rewarded %d %s%s for participating in this event.", - stackCount, basestats->GetName(), (stackCount>1)?"s":""); - psserver->SendSystemInfo(clientnum, "%s has been rewarded %d %s%s.", - target->GetName(), stackCount, - basestats->GetName(), (stackCount>1)?"s":""); - return; - } - - // generate the prize item - psItem* newitem = basestats->InstantiateBasicItem(true); - if (newitem == NULL) - { - Error1("Could not instantiate from base item."); - psserver->SendSystemInfo(clientnum, "%s has not been rewarded.", target->GetName()); - return; - } - newitem->SetItemQuality(basestats->GetQuality()); - newitem->SetStackCount(stackCount); - - // spawn the item into the recipients inventory - newitem->SetLoaded(); // Item is fully created - if (target->GetActor()->GetCharacterData()->Inventory().Add(newitem)) - { - // inform recipient of their prize - psserver->SendSystemInfo(target->GetClientNum(), - "You have been rewarded %d %s%s for participating in this event.", - stackCount, basestats->GetName(), (stackCount>1)?"s":""); - psserver->SendSystemInfo(clientnum, "%s has been rewarded %d %s%s.", - target->GetName(), stackCount, - basestats->GetName(), (stackCount>1)?"s":""); - return; - } - - // failed to stash item, so remove it - CacheManager::GetSingleton().RemoveInstance(newitem); - psserver->SendSystemInfo(clientnum, "%s has not been rewarded.", target->GetName()); -} - int GMEventManager::GetNextEventID(void) { // TODO this is just too simple Index: src/server/database/mysql/command_access.sql =================================================================== --- src/server/database/mysql/command_access.sql (revision 5627) +++ src/server/database/mysql/command_access.sql (working copy) @@ -100,6 +100,9 @@ INSERT INTO command_group_assignment VALUES( "/awardexp", 30 ); INSERT INTO command_group_assignment VALUES( "/awardexp", 25 ); INSERT INTO command_group_assignment VALUES( "/awardexp", 24 ); +INSERT INTO command_group_assignment VALUES( "/award", 30 ); +INSERT INTO command_group_assignment VALUES( "/award", 25 ); +INSERT INTO command_group_assignment VALUES( "/award", 24 ); INSERT INTO command_group_assignment VALUES( "quest change others", 30 ); INSERT INTO command_group_assignment VALUES( "quest change others", 25 ); INSERT INTO command_group_assignment VALUES( "quest change others", 24 ); Index: src/server/gmeventmanager.h =================================================================== --- src/server/gmeventmanager.h (revision 5627) +++ src/server/gmeventmanager.h (working copy) @@ -44,6 +44,7 @@ #define SUPPORT_GM_LEVEL GM_LEVEL_4 class psItemStats; +class psRewardData; enum GMEventStatus { @@ -138,16 +139,14 @@ * @param rewardRecipient: who will receive the reward. * @param range: required range of winners (NO_RANGE = all participants). * @param target: specific individual winner. - * @param stackCount: number of items to reward. - * @param itemName: name of the reward item. + * @param RewardData: struct holding the rewards. * @return bool: true = success, false = failed. */ bool RewardPlayersInGMEvent (Client* client, RangeSpecifier rewardRecipient, float range, Client *target, - short stackCount, - csString itemName); + psRewardData& data); /** @brief Returns all events for a player. * @@ -288,21 +287,6 @@ */ void SetEvalStatus(PID PlayerID, GMEvent *Event, bool NewStatus); - /** @brief Reward player in event. - * - * @param clientnum: GM client number. - * @param target: client pointer to recipient. - * @param stackCount: stack count # items in reward. - * @param basestats: base stats of reward item. - */ - void RewardPlayer(int clientnum, Client* target, short stackCount, psItemStats* basestats); - enum RewardType - { - REWARD_ITEM, - REWARD_EXPERIENCE, - REWARD_FACTION_POINTS - }; - /** Get next free event id number. */ int GetNextEventID(void); Index: data/help.xml =================================================================== --- data/help.xml (revision 5627) +++ data/help.xml (working copy) @@ -512,6 +512,9 @@ /awardexp target value Awards progression points to a player for the completion of a GM run event. (enter a negative value to take away PP) + /award [area:[players]:range|me|target|player|eid:EID|pid:PID] ['exp' value] ['item' count item] ['skill' [skill|'all'] [+-]value [max]] ['money' [circles|hexas|octas|trias] [value|'random']] ['faction' faction value] + +Awards progression points, items, money, skills and factions to specified target(s) /badtext [first entry] [last entry] Shows what was told to the targeted npc and couldn't be understand by it. @@ -576,10 +579,8 @@ /event complete To reward the participants (all of them, those within a specified range or an individual - by name or by target) of a current event: -/event reward [range 0-100 | all | player] # [item name] -[item name] can be "exp" (experience) where # Progression Points are awarded. -[item name] can be "faction [faction name]" to adjust the faction standing. -NOTE: Exp is in PP not in experience, differently from awardexp and givekillexp +/event reward [range 0-100 | all | player | target] ['skill' [skill|'all'] [+-]value [max]] ['exp' value] ['item' count item] ['money' [circles|hexas|octas|trias] [value|'random']] ['faction' faction value] +NOTE: Exp is in PP not in experience If a GM wants to assume control of an ongoing event, because the original GM character has been deleted, or has abandoned it and is offline, the GM can enter: /event control [name] @@ -813,7 +814,7 @@ /setquality [target/eid/area/name] [quality] [max quality] Allows changing the quality of the targeted item. Max quality is optional. - /setskill [target] [skill|'all'] [value|-1] + /setskill [target] [skill|'all'] [+-][value] [max] Set one of your or target's skills or stats to a specific value. Use 'all' as the name to set all skills and stats to the given value. Use -1 for value if you would like to view the current value of a skill or stat. If no value is given 100 will be used as default. /setstackable [on|off|reset|info]