mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
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
This commit is contained in:
17
sql/updates/world/2014_09_08_01_world_freeze_cmd.sql
Normal file
17
sql/updates/world/2014_09_08_01_world_freeze_cmd.sql
Normal file
@@ -0,0 +1,17 @@
|
||||
-- GM Freeze Spell Script
|
||||
DELETE FROM `spell_script_names` WHERE `spell_id`=9454;
|
||||
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES (9454, 'spell_gen_gm_freeze');
|
||||
|
||||
-- Update Command Help
|
||||
UPDATE `command` SET `help`='Syntax: .freeze [#player] [#duration]
|
||||
Freezes #player for #duration (seconds)
|
||||
Freezes the selected player if no arguments are given.
|
||||
Default duration: GM.FreezeAuraDuration (worldserver.conf)' WHERE `name`='freeze';
|
||||
|
||||
-- Add new string to show the duration on the freeze upon using .listfreeze
|
||||
DELETE FROM `trinity_string` WHERE `entry`=5019;
|
||||
INSERT INTO `trinity_string` (`entry`, `content_default`) VALUES
|
||||
(5019, '| %s - Status: %d seconds left');
|
||||
|
||||
-- Update old string to show if the duration is permanent
|
||||
UPDATE `trinity_string` SET `content_default`='| %s - Status: Permanently frozen' WHERE `entry`=5006;
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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* 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)
|
||||
{
|
||||
player = handler->getSelectedPlayer();
|
||||
if (player) //prevent crash with creature as target
|
||||
// Might have a selected player. We'll check it later
|
||||
// Get the duration from world cfg
|
||||
getDurationFromConfig = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
name = player->GetName();
|
||||
normalizePlayerName(name);
|
||||
}
|
||||
}
|
||||
else // if name entered
|
||||
{
|
||||
name = TargetName;
|
||||
normalizePlayerName(name);
|
||||
player = sObjectAccessor->FindPlayerByName(name);
|
||||
}
|
||||
|
||||
if (!player)
|
||||
{
|
||||
handler->SendSysMessage(LANG_COMMAND_FREEZE_WRONG);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player == handler->GetSession()->GetPlayer())
|
||||
{
|
||||
handler->SendSysMessage(LANG_COMMAND_FREEZE_ERROR);
|
||||
return true;
|
||||
}
|
||||
|
||||
// effect
|
||||
if (player && (player != handler->GetSession()->GetPlayer()))
|
||||
{
|
||||
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 (Pet* pet = player->GetPet())
|
||||
if (isNumeric(arg1))
|
||||
{
|
||||
pet->SavePetToDB(PET_SAVE_AS_CURRENT);
|
||||
// not let dismiss dead pet
|
||||
if (pet->IsAlive())
|
||||
player->RemovePet(pet, PET_SAVE_NOT_IN_SLOT);
|
||||
// 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 (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(9454))
|
||||
Aura::TryRefreshStackOrCreate(spellInfo, MAX_EFFECT_MASK, player, player);
|
||||
|
||||
// save player
|
||||
player->SaveToDB();
|
||||
}
|
||||
|
||||
return true;
|
||||
// Check if duration needs to be retrieved from config
|
||||
if (getDurationFromConfig)
|
||||
{
|
||||
freezeDuration = sWorld->getIntConfig(CONFIG_GM_FREEZE_DURATION);
|
||||
canApplyFreeze = true;
|
||||
}
|
||||
|
||||
// Player and duration retrieval is over
|
||||
if (canApplyFreeze)
|
||||
{
|
||||
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
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
if (freezeDuration)
|
||||
freeze->SetDuration(freezeDuration * IN_MILLISECONDS);
|
||||
handler->PSendSysMessage(LANG_COMMAND_FREEZE, player->GetName().c_str());
|
||||
// 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());
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1547,6 +1547,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).
|
||||
|
||||
Reference in New Issue
Block a user