diff --git a/data/sql/updates/db_world/2022_10_25_00.sql b/data/sql/updates/db_world/2022_10_25_00.sql new file mode 100644 index 000000000..2c26db74f --- /dev/null +++ b/data/sql/updates/db_world/2022_10_25_00.sql @@ -0,0 +1,9 @@ +-- DB update 2022_10_23_02 -> 2022_10_25_00 +-- +DELETE FROM `acore_string` WHERE `entry` = 5083; +INSERT INTO `acore_string` (`entry`, `content_default`) VALUES +(5083, 'Character %s (%u) moved from account %s (%u) to account %s (%u).'); + +DELETE FROM `command` WHERE `name` = 'character changeaccount'; +INSERT INTO `command` (`name`, `security`, `help`) VALUES +('character changeaccount', 3, 'Syntax: .character changeaccount $NewAccountName $Name.\nMoves the specified character to the provided account. \nKicks the player if the character is online.'); diff --git a/data/sql/updates/db_world/2022_10_25_01.sql b/data/sql/updates/db_world/2022_10_25_01.sql new file mode 100644 index 000000000..8d5926864 --- /dev/null +++ b/data/sql/updates/db_world/2022_10_25_01.sql @@ -0,0 +1,3 @@ +-- DB update 2022_10_25_00 -> 2022_10_25_01 +-- +UPDATE `creature_formations` SET `groupAI` = 539 WHERE `leaderGUID` = 87648 AND `memberGUID` IN (87648, 87649, 87650, 87651); diff --git a/data/sql/updates/db_world/2022_10_25_02.sql b/data/sql/updates/db_world/2022_10_25_02.sql new file mode 100644 index 000000000..dca5b0586 --- /dev/null +++ b/data/sql/updates/db_world/2022_10_25_02.sql @@ -0,0 +1,5 @@ +-- DB update 2022_10_25_01 -> 2022_10_25_02 +-- +DELETE FROM `creature_template_movement` WHERE `creatureId` = 15589; +INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`, `Chase`, `Random`, `InteractionPauseTimer`) VALUES +(15589, 1, 0, 0, 1, 0, 0, 0); diff --git a/data/sql/updates/db_world/2022_10_25_03.sql b/data/sql/updates/db_world/2022_10_25_03.sql new file mode 100644 index 000000000..464193fe2 --- /dev/null +++ b/data/sql/updates/db_world/2022_10_25_03.sql @@ -0,0 +1,9 @@ +-- DB update 2022_10_25_02 -> 2022_10_25_03 +-- +UPDATE `spell_dbc` SET `MaxTargets`=0 WHERE `id`=24019; + +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=24071; + +DELETE FROM `spell_script_names` WHERE `spell_id`=24019; +INSERT INTO `spell_script_names` VALUES +(24019,'spell_axe_flurry'); diff --git a/data/sql/updates/db_world/2022_10_26_00.sql b/data/sql/updates/db_world/2022_10_26_00.sql new file mode 100644 index 000000000..57d32ca09 --- /dev/null +++ b/data/sql/updates/db_world/2022_10_26_00.sql @@ -0,0 +1,5 @@ +-- DB update 2022_10_25_03 -> 2022_10_26_00 +-- +DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_huhuran_poison_bolt' AND `spell_id` = 26180; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(26180, 'spell_huhuran_poison_bolt'); diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp index c131a8fd6..30f08c361 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp @@ -64,14 +64,14 @@ void SummonList::DespawnEntry(uint32 entry) } } -void SummonList::DespawnAll() +void SummonList::DespawnAll(uint32 delay /*= 0*/) { while (!storage_.empty()) { Creature* summon = ObjectAccessor::GetCreature(*me, storage_.front()); storage_.pop_front(); if (summon) - summon->DespawnOrUnsummon(); + summon->DespawnOrUnsummon(delay); } } diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.h b/src/server/game/AI/ScriptedAI/ScriptedCreature.h index bf6a86d4d..4f295a889 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h @@ -89,7 +89,7 @@ public: void Summon(Creature const* summon) { storage_.push_back(summon->GetGUID()); } void Despawn(Creature const* summon) { storage_.remove(summon->GetGUID()); } void DespawnEntry(uint32 entry); - void DespawnAll(); + void DespawnAll(uint32 delay = 0); bool IsAnyCreatureAlive() const; bool IsAnyCreatureWithEntryAlive(uint32 entry) const; bool IsAnyCreatureInCombat() const; diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index df6bf3d71..f907ddaf8 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -1146,6 +1146,8 @@ enum AcoreStrings LANG_CMD_GOQUEST_INVALID_SYNTAX = 5082, + LANG_CMD_CHAR_CHANGE_ACC_SUCCESS = 5083, + // Room for more strings 5083-9999 // Level requirement notifications diff --git a/src/server/scripts/Commands/cs_character.cpp b/src/server/scripts/Commands/cs_character.cpp index e720cda0d..bd34f10bb 100644 --- a/src/server/scripts/Commands/cs_character.cpp +++ b/src/server/scripts/Commands/cs_character.cpp @@ -72,6 +72,7 @@ public: { "customize", HandleCharacterCustomizeCommand, SEC_GAMEMASTER, Console::Yes }, { "changefaction", HandleCharacterChangeFactionCommand, SEC_GAMEMASTER, Console::Yes }, { "changerace", HandleCharacterChangeRaceCommand, SEC_GAMEMASTER, Console::Yes }, + { "changeaccount", HandleCharacterChangeAccountCommand, SEC_ADMINISTRATOR, Console::Yes }, { "check", characterCheckCommandTable }, { "erase", HandleCharacterEraseCommand, SEC_CONSOLE, Console::Yes }, { "deleted", characterDeletedCommandTable }, @@ -1061,6 +1062,55 @@ public: handler->PSendSysMessage("--------------------------------------"); return true; } + + static bool HandleCharacterChangeAccountCommand(ChatHandler* handler, std::string accountName, Optional player) + { + if (!player) + { + player = PlayerIdentifier::FromTargetOrSelf(handler); + } + + if (!player) + { + handler->SendSysMessage(LANG_PLAYER_NOT_FOUND); + handler->SetSentErrorMessage(true); + return false; + } + + if (uint32 accountId = AccountMgr::GetId(accountName)) + { + if (AccountMgr::GetCharactersCount(accountId) >= 10) + { + handler->PSendSysMessage(LANG_ACCOUNT_CHARACTER_LIST_FULL, accountName, accountId); + handler->SetSentErrorMessage(true); + return true; + } + + if (CharacterCacheEntry const* cache = sCharacterCache->GetCharacterCacheByName(player->GetName())) + { + std::string accName; + AccountMgr::GetName(cache->AccountId, accName); + handler->PSendSysMessage(LANG_CMD_CHAR_CHANGE_ACC_SUCCESS, player->GetName(), player->GetGUID().GetCounter(), accName, cache->AccountId, accountName, accountId); + } + + if (player->IsConnected()) + { + player->GetConnectedPlayer()->GetSession()->KickPlayer("CMD char changeaccount"); + } + + CharacterDatabase.Query("UPDATE characters SET account = {} WHERE guid = {}", accountId, player->GetGUID().GetCounter()); + sCharacterCache->UpdateCharacterAccountId(player->GetGUID(), accountId); + + } + else + { + handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName); + handler->SetSentErrorMessage(true); + return true; + } + + return true; + } }; void AddSC_character_commandscript() diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.cpp new file mode 100644 index 000000000..b8c390fe2 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.cpp @@ -0,0 +1,58 @@ +/* + * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by the + * Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "GridNotifiers.h" +#include "ScriptMgr.h" +#include "SpellScript.h" + +enum Spells +{ + SPELL_AXE_FLURRY_STUN = 24020 +}; + +class spell_axe_flurry : public SpellScript +{ + PrepareSpellScript(spell_axe_flurry); + + void FilterTargets(std::list& targets) + { + targets.remove_if(Acore::UnitAuraCheck(true, SPELL_AXE_FLURRY_STUN)); + Acore::Containers::RandomResize(targets, 1); + } + + void HandleEffect(SpellEffIndex /*effIndex*/) + { + if (Unit* caster = GetCaster()) + { + if (Unit* target = GetHitUnit()) + { + caster->CastSpell(target, SPELL_AXE_FLURRY_STUN, true); + } + } + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_axe_flurry::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_axe_flurry::HandleEffect, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +void AddSC_zulgurub() +{ + RegisterSpellScript(spell_axe_flurry); +} diff --git a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp index e8cf955c9..8bd3f42b9 100644 --- a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp +++ b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp @@ -141,6 +141,7 @@ void AddSC_boss_hazzarah(); void AddSC_boss_renataki(); void AddSC_boss_wushoolay(); void AddSC_instance_zulgurub(); +void AddSC_zulgurub(); // void AddSC_alterac_mountains(); void AddSC_arathi_highlands(); void AddSC_blasted_lands(); @@ -292,6 +293,7 @@ void AddEasternKingdomsScripts() AddSC_boss_renataki(); AddSC_boss_wushoolay(); AddSC_instance_zulgurub(); + AddSC_zulgurub(); //AddSC_alterac_mountains(); AddSC_arathi_highlands(); AddSC_blasted_lands(); diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_huhuran.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_huhuran.cpp index 882ccb7e9..18dbf9327 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_huhuran.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_huhuran.cpp @@ -156,6 +156,7 @@ class spell_huhuran_wyvern_sting : public AuraScript }; // 26052 - Poison Bolt +// 26180 - Wyvern Sting class spell_huhuran_poison_bolt : public SpellScript { PrepareSpellScript(spell_huhuran_poison_bolt); diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp index 4f887b83c..f12d58ff7 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp @@ -70,21 +70,10 @@ struct boss_sartura : public BossAI _Reset(); enraged = false; berserked = false; - MinionReset(); me->SetReactState(REACT_AGGRESSIVE); } - void MinionReset() - { - std::list royalGuards; - me->GetCreaturesWithEntryInRange(royalGuards, 200.0f, NPC_SARTURA_ROYAL_GUARD); - for (Creature* minion : royalGuards) - { - minion->Respawn(); - } - } - void EnterCombat(Unit* who) override { BossAI::EnterCombat(who); diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp index 058ac46d4..324cb884c 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp @@ -327,10 +327,7 @@ struct boss_veknilash : public boss_twinemperorsAI struct boss_veklor : public boss_twinemperorsAI { - boss_veklor(Creature* creature) : boss_twinemperorsAI(creature) - { - me->SetFloatValue(UNIT_FIELD_COMBATREACH, 45.f); - } + boss_veklor(Creature* creature) : boss_twinemperorsAI(creature) { } bool IAmVeklor() override { return true; } @@ -391,6 +388,19 @@ struct boss_veklor : public boss_twinemperorsAI } } } + + void AttackStart(Unit* who) override + { + if (who && who->isTargetableForAttack() && me->GetReactState() != REACT_PASSIVE) + { + // VL doesn't melee + if (me->Attack(who, false)) + { + me->GetMotionMaster()->MoveChase(who, 45.0f, 0); + me->AddThreat(who, 0.0f); + } + } + } }; class at_twin_emperors : public OnlyOnceAreaTriggerScript diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp index 49be214e0..5e5825ede 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp @@ -133,6 +133,17 @@ struct boss_viscidus : public BossAI me->RemoveAurasDueToSpell(SPELL_INVIS_SELF); } + void JustDied(Unit* /*killer*/) override + { + events.Reset(); + summons.DespawnAll(10 * IN_MILLISECONDS); + if (instance) + { + instance->SetBossState(DATA_VISCIDUS, DONE); + instance->SaveToDB(); + } + } + void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType effType, SpellSchoolMask spellSchoolMask) override { if (me->HealthBelowPct(5))