diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Miscellaneous/Language.h | 4 | ||||
-rw-r--r-- | src/server/game/World/World.cpp | 1 | ||||
-rw-r--r-- | src/server/game/World/World.h | 1 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_misc.cpp | 150 | ||||
-rw-r--r-- | src/server/scripts/Spells/spell_generic.cpp | 74 | ||||
-rw-r--r-- | src/server/shared/Database/Implementation/CharacterDatabase.cpp | 2 | ||||
-rw-r--r-- | src/server/worldserver/worldserver.conf.dist | 8 |
7 files changed, 180 insertions, 60 deletions
diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index eceb0a8e7de..c1de3aae7cb 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -1054,7 +1054,7 @@ enum TrinityStrings LANG_COMMAND_UNFREEZE = 5003, LANG_COMMAND_NO_FROZEN_PLAYERS = 5004, LANG_COMMAND_LIST_FREEZE = 5005, - LANG_COMMAND_FROZEN_PLAYERS = 5006, + LANG_COMMAND_PERMA_FROZEN_PLAYER = 5006, LANG_INSTANCE_RAID_GROUP_ONLY = 5007, LANG_INSTANCE_CLOSED = 5008, LANG_COMMAND_PLAYED_TO_ALL = 5009, @@ -1068,7 +1068,7 @@ enum TrinityStrings LANG_ARENA = 5016, LANG_RAID = 5017, //= 5018, - //= 5019, + LANG_COMMAND_TEMP_FROZEN_PLAYER = 5019, LANG_NPCINFO_PHASEMASK = 5020, LANG_NPCINFO_ARMOR = 5021, LANG_CHANNEL_ENABLE_OWNERSHIP = 5022, diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 5c65055f3c0..58e3cffa8de 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -856,6 +856,7 @@ void World::LoadConfigSettings(bool reload) m_int_configs[CONFIG_GM_VISIBLE_STATE] = sConfigMgr->GetIntDefault("GM.Visible", 2); m_int_configs[CONFIG_GM_CHAT] = sConfigMgr->GetIntDefault("GM.Chat", 2); m_int_configs[CONFIG_GM_WHISPERING_TO] = sConfigMgr->GetIntDefault("GM.WhisperingTo", 2); + m_int_configs[CONFIG_GM_FREEZE_DURATION] = sConfigMgr->GetIntDefault("GM.FreezeAuraDuration", 0); m_int_configs[CONFIG_GM_LEVEL_IN_GM_LIST] = sConfigMgr->GetIntDefault("GM.InGMList.Level", SEC_ADMINISTRATOR); m_int_configs[CONFIG_GM_LEVEL_IN_WHO_LIST] = sConfigMgr->GetIntDefault("GM.InWhoList.Level", SEC_ADMINISTRATOR); diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 05bfcc21462..cc2078bc736 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -227,6 +227,7 @@ enum WorldIntConfigs CONFIG_GM_ACCEPT_TICKETS, CONFIG_GM_CHAT, CONFIG_GM_WHISPERING_TO, + CONFIG_GM_FREEZE_DURATION, CONFIG_GM_LEVEL_IN_GM_LIST, CONFIG_GM_LEVEL_IN_WHO_LIST, CONFIG_START_GM_LEVEL, 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()); diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 84e36b55c2c..e198a6a0c61 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -3609,6 +3609,79 @@ class spell_gen_eject_all_passengers : public SpellScriptLoader } }; +enum GMFreeze +{ + SPELL_GM_FREEZE = 9454 +}; + +class spell_gen_gm_freeze : public SpellScriptLoader +{ + public: + spell_gen_gm_freeze() : SpellScriptLoader("spell_gen_gm_freeze") { } + + class spell_gen_gm_freeze_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gen_gm_freeze_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_GM_FREEZE)) + return false; + return true; + } + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + // Do what was done before to the target in HandleFreezeCommand + if (Player* player = GetTarget()->ToPlayer()) + { + // 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 (Pet* pet = player->GetPet()) + { + pet->SavePetToDB(PET_SAVE_AS_CURRENT); + // not let dismiss dead pet + if (pet->IsAlive()) + player->RemovePet(pet, PET_SAVE_NOT_IN_SLOT); + } + } + } + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + // Do what was done before to the target in HandleUnfreezeCommand + if (Player* player = GetTarget()->ToPlayer()) + { + // Reset player faction + allow combat + allow duels + player->setFactionForRace(player->getRace()); + player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + // save player + player->SaveToDB(); + } + } + + void Register() override + { + OnEffectApply += AuraEffectApplyFn(spell_gen_gm_freeze_AuraScript::OnApply, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); + OnEffectRemove += AuraEffectRemoveFn(spell_gen_gm_freeze_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_gen_gm_freeze_AuraScript(); + } +}; + void AddSC_generic_spell_scripts() { new spell_gen_absorb0_hitlimit1(); @@ -3689,4 +3762,5 @@ void AddSC_generic_spell_scripts() new spell_gen_wg_water(); new spell_gen_whisper_gulch_yogg_saron_whisper(); new spell_gen_eject_all_passengers(); + new spell_gen_gm_freeze(); } diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index 0669d0b84f9..aa584d026fb 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -417,7 +417,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_DEL_CHARACTER_SOCIAL, "DELETE FROM character_social WHERE guid = ? AND friend = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_CHARACTER_SOCIAL_NOTE, "UPDATE character_social SET note = ? WHERE guid = ? AND friend = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_CHARACTER_POSITION, "UPDATE characters SET position_x = ?, position_y = ?, position_z = ?, orientation = ?, map = ?, zone = ?, trans_x = 0, trans_y = 0, trans_z = 0, transguid = 0, taxi_path = '' WHERE guid = ?", CONNECTION_ASYNC); - PrepareStatement(CHAR_SEL_CHARACTER_AURA_FROZEN, "SELECT characters.name FROM characters LEFT JOIN character_aura ON (characters.guid = character_aura.guid) WHERE character_aura.spell = 9454", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_CHARACTER_AURA_FROZEN, "SELECT characters.name, character_aura.remaintime FROM characters LEFT JOIN character_aura ON (characters.guid = character_aura.guid) WHERE character_aura.spell = 9454", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHARACTER_ONLINE, "SELECT name, account, map, zone FROM characters WHERE online > 0", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_DEL_INFO_BY_GUID, "SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL AND guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_DEL_INFO_BY_NAME, "SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL AND deleteInfos_Name LIKE CONCAT('%%', ?, '%%')", CONNECTION_SYNCH); diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index b49f9ebd9ec..3fec13684da 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -1548,6 +1548,14 @@ GM.Chat = 2 GM.WhisperingTo = 2 # +# GM.FreezeAuraDuration +# Description: Allows to set a default duration to the Freeze Aura +# applied on players when using the .freeze command +# Default: 0 - (Original aura duration. Lasts until the .unfreeze command is used) +# N - (Aura duration if unspecified in .freeze command, in seconds) +GM.FreezeAuraDuration = 0 + +# # GM.InGMList.Level # Description: Maximum GM level shown in GM list (if enabled) in non-GM state (.gm off). # Default: 3 - (Anyone) |