From 54e201b8b97912b45f5ae942c5b71abb1cf58640 Mon Sep 17 00:00:00 2001 From: Odyssey Date: Mon, 8 Sep 2014 15:56:00 +0100 Subject: Scripts/Commands: Allow to set a custom duration to the Freeze command applied Aura - Allow to set a default duration for the Freeze Aura in worldserver.conf - Handle the .freeze and .unfreeze command custom effects through the Freeze AuraScript - Make players able to eventually unfreeze by themselves since the aura will expire without someone having to use .unfreeze - Make .freeze command usable with the following syntax: * .freeze (with a targeted player) * .freeze duration_in_seconds (with a targeted player) * .freeze playername duration (if duration is an invalid value it will be defaulted to the config one) * .freeze playername (in this case, duration will be defaulted to the config value) - Make .listfreeze command able to show the remaining freeze duration on all affected players Closes #12972 --- src/server/scripts/Commands/cs_misc.cpp | 150 ++++++++++++++++++++------------ 1 file changed, 93 insertions(+), 57 deletions(-) (limited to 'src/server/scripts/Commands') diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 80b7710cd21..3e7b242f3cc 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -2241,69 +2241,100 @@ public: static bool HandleFreezeCommand(ChatHandler* handler, char const* args) { - std::string name; - Player* player; - char const* TargetName = strtok((char*)args, " "); // get entered name - if (!TargetName) // if no name entered use target - { - player = handler->getSelectedPlayer(); - if (player) //prevent crash with creature as target - { - name = player->GetName(); - normalizePlayerName(name); - } - } - else // if name entered + Player* player = handler->getSelectedPlayer(); // Selected player, if any. Might be null. + uint32 freezeDuration = 0; // Freeze Duration (in seconds) + bool canApplyFreeze = false; // Determines if every possible argument is set so Freeze can be applied + bool getDurationFromConfig = false; // If there's no given duration, we'll retrieve the world cfg value later + + /* + Possible Freeze Command Scenarios: + case 1 - .freeze (without args and a selected player) + case 2 - .freeze duration (with a selected player) + case 3 - .freeze player duration + case 4 - .freeze player (without specifying duration) + */ + + // case 1: .freeze + if (!*args) { - name = TargetName; - normalizePlayerName(name); - player = sObjectAccessor->FindPlayerByName(name); + // Might have a selected player. We'll check it later + // Get the duration from world cfg + getDurationFromConfig = true; } - - if (!player) + else { - handler->SendSysMessage(LANG_COMMAND_FREEZE_WRONG); - return true; + // Get the args that we might have (up to 2) + char const* arg1 = strtok((char*)args, " "); + char const* arg2 = strtok(NULL, " "); + + // Analyze them to see if we got either a playerName or duration or both + if (arg1) + { + if (isNumeric(arg1)) + { + // case 2: .freeze duration + // We have a selected player. We'll check him later + freezeDuration = uint32(atoi(arg1)); + canApplyFreeze = true; + } + else + { + // case 3 or 4: .freeze player duration | .freeze player + // find the player + std::string name = arg1; + normalizePlayerName(name); + player = sObjectAccessor->FindPlayerByName(name); + // Check if we have duration set + if (arg2 && isNumeric(arg2)) + { + freezeDuration = uint32(atoi(arg2)); + canApplyFreeze = true; + } + else + getDurationFromConfig = true; + } + } } - if (player == handler->GetSession()->GetPlayer()) + // Check if duration needs to be retrieved from config + if (getDurationFromConfig) { - handler->SendSysMessage(LANG_COMMAND_FREEZE_ERROR); - return true; + freezeDuration = sWorld->getIntConfig(CONFIG_GM_FREEZE_DURATION); + canApplyFreeze = true; } - // effect - if (player && (player != handler->GetSession()->GetPlayer())) + // Player and duration retrieval is over + if (canApplyFreeze) { - handler->PSendSysMessage(LANG_COMMAND_FREEZE, name.c_str()); - - // stop combat + make player unattackable + duel stop + stop some spells - player->setFaction(35); - player->CombatStop(); - if (player->IsNonMeleeSpellCast(true)) - player->InterruptNonMeleeSpells(true); - player->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - // if player class = hunter || warlock remove pet if alive - if ((player->getClass() == CLASS_HUNTER) || (player->getClass() == CLASS_WARLOCK)) + if (!player) // can be null if some previous selection failed + { + handler->SendSysMessage(LANG_COMMAND_FREEZE_WRONG); + return true; + } + else if (player == handler->GetSession()->GetPlayer()) + { + // Can't freeze himself + handler->SendSysMessage(LANG_COMMAND_FREEZE_ERROR); + return true; + } + else // Apply the effect { - if (Pet* pet = player->GetPet()) + // Add the freeze aura and set the proper duration + // Player combat status and flags are now handled + // in Freeze Spell AuraScript (OnApply) + Aura* freeze = player->AddAura(9454, player); + if (freeze) { - pet->SavePetToDB(PET_SAVE_AS_CURRENT); - // not let dismiss dead pet - if (pet->IsAlive()) - player->RemovePet(pet, PET_SAVE_NOT_IN_SLOT); + if (freezeDuration) + freeze->SetDuration(freezeDuration * IN_MILLISECONDS); + handler->PSendSysMessage(LANG_COMMAND_FREEZE, player->GetName().c_str()); + // save player + player->SaveToDB(); + return true; } } - - if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(9454)) - Aura::TryRefreshStackOrCreate(spellInfo, MAX_EFFECT_MASK, player, player); - - // save player - player->SaveToDB(); } - - return true; + return false; } static bool HandleUnFreezeCommand(ChatHandler* handler, char const*args) @@ -2329,15 +2360,10 @@ public: { handler->PSendSysMessage(LANG_COMMAND_UNFREEZE, name.c_str()); - // Reset player faction + allow combat + allow duels - player->setFactionForRace(player->getRace()); - player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - // Remove Freeze spell (allowing movement and spells) + // Player Flags + Neutral faction removal is now + // handled on the Freeze Spell AuraScript (OnRemove) player->RemoveAurasDueToSpell(9454); - - // Save player - player->SaveToDB(); } else { @@ -2394,7 +2420,17 @@ public: { Field* fields = result->Fetch(); std::string player = fields[0].GetString(); - handler->PSendSysMessage(LANG_COMMAND_FROZEN_PLAYERS, player.c_str()); + int32 remaintime = fields[1].GetInt32(); + // Save the frozen player to update remaining time in case of future .listfreeze uses + // before the frozen state expires + if (Player* frozen = sObjectAccessor->FindPlayerByName(player)) + frozen->SaveToDB(); + // Notify the freeze duration + if (remaintime == -1) // Permanent duration + handler->PSendSysMessage(LANG_COMMAND_PERMA_FROZEN_PLAYER, player.c_str()); + else + // show time left (seconds) + handler->PSendSysMessage(LANG_COMMAND_TEMP_FROZEN_PLAYER, player.c_str(), remaintime / IN_MILLISECONDS); } while (result->NextRow()); -- cgit v1.2.3