From d5263b0aee18b825ff7f46fb861094ff1836693e Mon Sep 17 00:00:00 2001 From: Knindza Date: Fri, 13 Sep 2024 02:43:34 +0200 Subject: [PATCH 01/17] fix(Battlegrounds/AlteracValley): Adding missing Tower Archers (#18746) Updating Alterac --- .../Battlegrounds/Zones/BattlegroundAV.cpp | 3 ++ .../game/Battlegrounds/Zones/BattlegroundAV.h | 28 +++++++++---------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp index dce3357b5..e8cccc8c9 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp @@ -325,6 +325,9 @@ Creature* BattlegroundAV::AddAVCreature(uint16 cinfoid, uint16 type) if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_A_CAPTAIN] || creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_H_CAPTAIN]) creature->SetRespawnDelay(RESPAWN_ONE_DAY); /// @todo: look if this can be done by database + also add this for the wingcommanders + if (creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_A_TOWERDEFENSE] || creature->GetEntry() == BG_AV_CreatureInfo[AV_NPC_H_TOWERDEFENSE]) + creature->SetUnitFlag(UNIT_FLAG_DISABLE_MOVE); + if ((isStatic && cinfoid >= 10 && cinfoid <= 14) || (!isStatic && ((cinfoid >= AV_NPC_A_GRAVEDEFENSE0 && cinfoid <= AV_NPC_A_GRAVEDEFENSE3) || (cinfoid >= AV_NPC_H_GRAVEDEFENSE0 && cinfoid <= AV_NPC_H_GRAVEDEFENSE3)))) { diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h index 1d62a96fd..0383af41b 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h @@ -1118,21 +1118,21 @@ const float BG_AV_CreaturePos[AV_CPLACE_MAX][4] = enum BG_AV_CreatureIds { - AV_NPC_A_TOWERDEFENSE = 0, // stormpike bowman - AV_NPC_A_GRAVEDEFENSE0 = 1, // stormpike Defender - AV_NPC_A_GRAVEDEFENSE1 = 2, // seasoned defender - AV_NPC_A_GRAVEDEFENSE2 = 3, // veteran defender - AV_NPC_A_GRAVEDEFENSE3 = 4, // champion defender - AV_NPC_A_CAPTAIN = 5, // balinda - AV_NPC_A_BOSS = 6, // vanndar + AV_NPC_A_GRAVEDEFENSE0 = 0, // Stormpike defender + AV_NPC_A_GRAVEDEFENSE1 = 1, // Seasoned defender + AV_NPC_A_GRAVEDEFENSE2 = 2, // Veteran defender + AV_NPC_A_GRAVEDEFENSE3 = 3, // Champion defender + AV_NPC_A_TOWERDEFENSE = 4, // Stormpike bowman + AV_NPC_A_CAPTAIN = 5, // Balinda + AV_NPC_A_BOSS = 6, // Vanndar - AV_NPC_H_TOWERDEFENSE = 7, // frostwolf bowman - AV_NPC_H_GRAVEDEFENSE0 = 8, // frostwolf guardian - AV_NPC_H_GRAVEDEFENSE1 = 9, // seasoned guardian - AV_NPC_H_GRAVEDEFENSE2 = 10, // veteran guardian - AV_NPC_H_GRAVEDEFENSE3 = 11, // champion guardian - AV_NPC_H_CAPTAIN = 12, // galvangar - AV_NPC_H_BOSS = 13, // drek thar + AV_NPC_H_GRAVEDEFENSE0 = 7, // Frostwolf guardian + AV_NPC_H_GRAVEDEFENSE1 = 8, // Seasoned guardian + AV_NPC_H_GRAVEDEFENSE2 = 9, // Veteran guardian + AV_NPC_H_GRAVEDEFENSE3 = 10, // Champion guardian + AV_NPC_H_TOWERDEFENSE = 11, // Frostwolf bowman + AV_NPC_H_CAPTAIN = 12, // Galvangar + AV_NPC_H_BOSS = 13, // Drek thar AV_NPC_A_MARSHAL_SOUTH = 14, AV_NPC_MARSHAL_NORTH = 15, From 8d7463c67007e58f41366ed4fc1dbc1e1290f465 Mon Sep 17 00:00:00 2001 From: Jelle Meeus Date: Fri, 13 Sep 2024 21:15:25 +0200 Subject: [PATCH 02/17] fix(Core/PlayerStorage): Equip OH, 2H, Titan's Grip weapon swapping (#19884) titan's grip, unequip with full bags --- src/server/game/Entities/Player/Player.cpp | 8 +++++ .../game/Entities/Player/PlayerStorage.cpp | 35 +++++++------------ 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 068eaa8d2..b53ef50cb 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -12426,6 +12426,14 @@ void Player::AutoUnequipOffhandIfNeed(bool force /*= false*/) if (!CanDualWield() && (offItem->GetTemplate()->InventoryType == INVTYPE_WEAPONOFFHAND || offItem->GetTemplate()->InventoryType == INVTYPE_WEAPON)) force = true; + // unequip offhand weapon if player main hand weapon is a polearm or staff or fishing pole + if (Item* mhWeapon = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND)) + if (ItemTemplate const* mhWeaponProto = mhWeapon->GetTemplate()) + if (mhWeaponProto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || + mhWeaponProto->SubClass == ITEM_SUBCLASS_WEAPON_STAFF || + mhWeaponProto->SubClass == ITEM_SUBCLASS_WEAPON_FISHING_POLE) + force = true; + // need unequip offhand for 2h-weapon without TitanGrip (in any from hands) if (!force && (CanTitanGrip() || (offItem->GetTemplate()->InventoryType != INVTYPE_2HWEAPON && !IsTwoHandUsed()))) { diff --git a/src/server/game/Entities/Player/PlayerStorage.cpp b/src/server/game/Entities/Player/PlayerStorage.cpp index 0211a5777..2716faaa9 100644 --- a/src/server/game/Entities/Player/PlayerStorage.cpp +++ b/src/server/game/Entities/Player/PlayerStorage.cpp @@ -201,28 +201,11 @@ uint8 Player::FindEquipSlot(ItemTemplate const* proto, uint32 slot, bool swap) c break; case INVTYPE_2HWEAPON: slots[0] = EQUIPMENT_SLOT_MAINHAND; - if (Item* mhWeapon = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND)) - { - if (ItemTemplate const* mhWeaponProto = mhWeapon->GetTemplate()) - { - if (mhWeaponProto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || mhWeaponProto->SubClass == ITEM_SUBCLASS_WEAPON_STAFF) - { - const_cast(this)->AutoUnequipOffhandIfNeed(true); - break; - } - } - } - - if (GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND)) - { - if (proto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || proto->SubClass == ITEM_SUBCLASS_WEAPON_STAFF) - { - const_cast(this)->AutoUnequipOffhandIfNeed(true); - break; - } - } if (CanDualWield() && CanTitanGrip() && proto->SubClass != ITEM_SUBCLASS_WEAPON_POLEARM && proto->SubClass != ITEM_SUBCLASS_WEAPON_STAFF && proto->SubClass != ITEM_SUBCLASS_WEAPON_FISHING_POLE) - slots[1] = EQUIPMENT_SLOT_OFFHAND; + if (Item* mhWeapon = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND)) + if (ItemTemplate const* mhWeaponProto = mhWeapon->GetTemplate()) + if (mhWeaponProto->SubClass != ITEM_SUBCLASS_WEAPON_POLEARM && mhWeaponProto->SubClass != ITEM_SUBCLASS_WEAPON_STAFF && mhWeaponProto->SubClass != ITEM_SUBCLASS_WEAPON_FISHING_POLE) + slots[1] = EQUIPMENT_SLOT_OFFHAND; break; case INVTYPE_TABARD: slots[0] = EQUIPMENT_SLOT_TABARD; @@ -1962,6 +1945,14 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16& dest, Item* pItem, bool return EQUIP_ERR_CANT_DUAL_WIELD; } + // Do not allow offhand with main hand polearm, staff or fishing pole + if (Item* mhWeapon = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND)) + if (ItemTemplate const* mhWeaponProto = mhWeapon->GetTemplate()) + if (mhWeaponProto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || + mhWeaponProto->SubClass == ITEM_SUBCLASS_WEAPON_STAFF || + mhWeaponProto->SubClass == ITEM_SUBCLASS_WEAPON_FISHING_POLE) + return EQUIP_ERR_CANT_EQUIP_WITH_TWOHANDED; + if (IsTwoHandUsed()) return EQUIP_ERR_CANT_EQUIP_WITH_TWOHANDED; } @@ -1977,7 +1968,7 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16& dest, Item* pItem, bool else if (eslot != EQUIPMENT_SLOT_MAINHAND) return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED; - if (!CanTitanGrip()) + if (!CanTitanGrip() || (pProto->SubClass == ITEM_SUBCLASS_WEAPON_POLEARM || pProto->SubClass == ITEM_SUBCLASS_WEAPON_STAFF || pProto->SubClass == ITEM_SUBCLASS_WEAPON_FISHING_POLE)) { // offhand item must can be stored in inventory for offhand item and it also must be unequipped Item* offItem = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); From 92ec34753fb31e109e7a23678e26185271df7734 Mon Sep 17 00:00:00 2001 From: Anton Popovichenko Date: Fri, 13 Sep 2024 19:23:05 +0000 Subject: [PATCH 03/17] =?UTF-8?q?fix(Core/Creature):=20Add=20support=20for?= =?UTF-8?q?=20CREATURE=5FFLAG=5FEXTRA=5FNO=5FPARRY=5FHAST=E2=80=A6=20(#199?= =?UTF-8?q?27)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/server/game/Entities/Unit/Unit.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 705c36e23..692e67fb5 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -1847,7 +1847,10 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss) if (damageInfo->blocked_amount && damageInfo->TargetState != VICTIMSTATE_BLOCKS) victim->HandleEmoteCommand(EMOTE_ONESHOT_PARRY_SHIELD); - if (damageInfo->TargetState == VICTIMSTATE_PARRY) + // Parry haste is enabled if it's not a creature or if the creature doesn't have the NO_PARRY_HASTEN flag. + bool isParryHasteEnabled = !victim->IsCreature() || + !victim->ToCreature()->GetCreatureTemplate()->HasFlagsExtra(CREATURE_FLAG_EXTRA_NO_PARRY_HASTEN); + if (damageInfo->TargetState == VICTIMSTATE_PARRY && isParryHasteEnabled) { // Get attack timers float offtime = float(victim->getAttackTimer(OFF_ATTACK)); From 8030ef4ba0ed7ee20b3647c58fe421f91c1e1274 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Fri, 13 Sep 2024 16:26:42 -0300 Subject: [PATCH 04/17] =?UTF-8?q?fix(Scripts/BlackTemple):=20Fix=20variabl?= =?UTF-8?q?e=20not=20being=20set=20to=20true=20when=20Ak=E2=80=A6=20(#1994?= =?UTF-8?q?7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix(Scripts/BlackTemple): Fix variable not being set to false when Akama dies --- src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp index 1f59b410e..69b8fad98 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp @@ -278,6 +278,7 @@ struct npc_akama_shade : public ScriptedAI } else if (damage >= me->GetHealth() && !_died) { + _died = true; damage = me->GetHealth() - 1; Talk(SAY_DEATH); if (Creature* shade = instance->GetCreature(DATA_SHADE_OF_AKAMA)) From bd40fef081daaa3b160b4609083599b42435eb79 Mon Sep 17 00:00:00 2001 From: Grimdhex <176165533+Grimdhex@users.noreply.github.com> Date: Sat, 14 Sep 2024 13:22:02 +0200 Subject: [PATCH 05/17] fix(Scripts/BlackTemple): fix blaze and flame bast casting for Flame of Azzinoth (#19967) fix(Scripts/Core): fix blaze and flame bast casting for Flame of Azzinoth --- .../scripts/Outland/BlackTemple/boss_illidan.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp index e4de895c3..60873db14 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp @@ -1298,12 +1298,21 @@ struct npc_flame_of_azzinoth : public ScriptedAI DoCastVictim(SPELL_FLAME_BLAST); me->m_Events.AddEventAtOffset([&] { - if (Unit* target = me->GetVictim()) - target->CastSpell(target, SPELL_BLAZE, true); + DoCastVictim(SPELL_BLAZE); }, 1s); }, 15s, 20s); } + void UpdateAI(uint32 diff) override + { + scheduler.Update(diff); + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + private: ObjectGuid _bladeGUID; }; From 4fc60bbbdfb6e40b4e174333065c8365f639dfef Mon Sep 17 00:00:00 2001 From: Grimdhex <176165533+Grimdhex@users.noreply.github.com> Date: Sat, 14 Sep 2024 13:39:03 +0200 Subject: [PATCH 06/17] fix(Core/Spells): Shadow demon - Allow to move while casting Paralyze (#19948) * fix(Scripts/BlackTemple): fix stationary shadow demons * optimization: use else if to stop the execution when a condition is reach * revert last changes and fix the spell to allow move while casting * . --- src/server/game/Spells/SpellInfoCorrections.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/server/game/Spells/SpellInfoCorrections.cpp b/src/server/game/Spells/SpellInfoCorrections.cpp index f88dfbdc9..9cf614e11 100644 --- a/src/server/game/Spells/SpellInfoCorrections.cpp +++ b/src/server/game/Spells/SpellInfoCorrections.cpp @@ -4831,6 +4831,12 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_3_YARDS); }); + // Paralyze + ApplySpellFix({ 41083 }, [](SpellInfo* spellInfo) + { + spellInfo->AttributesEx5 |= SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL; + }); + for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i) { SpellInfo* spellInfo = mSpellInfoMap[i]; From 99b39e50452e5a5f0362765860fc7c8280f251c0 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Sun, 15 Sep 2024 07:46:55 -0300 Subject: [PATCH 07/17] =?UTF-8?q?fix(Scripts/BlackTemple):=20Parasitic=20S?= =?UTF-8?q?hadowfiends=20should=20not=20target=20pl=E2=80=A6=20(#19944)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(Scripts/BlackTemple): Parasitic Shadowfiends should not target players affected with debuff * Update boss_illidan.cpp * Update src/server/scripts/Outland/BlackTemple/boss_illidan.cpp * make it simple --- .../Outland/BlackTemple/boss_illidan.cpp | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp index 60873db14..a181d6fba 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp @@ -1186,14 +1186,37 @@ struct npc_parasitic_shadowfiend : public ScriptedAI { npc_parasitic_shadowfiend(Creature* creature) : ScriptedAI(creature) { } + bool CanAIAttack(Unit const* who) const override + { + return !who->HasAura(SPELL_PARASITIC_SHADOWFIEND) && !who->HasAura(SPELL_PARASITIC_SHADOWFIEND_TRIGGER); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + me->DespawnOrUnsummon(); + } + void IsSummonedBy(WorldObject* /*summoner*/) override { // Simulate blizz-like AI delay to avoid extreme overpopulation of adds me->SetReactState(REACT_DEFENSIVE); - me->m_Events.AddEventAtOffset([&] { + + scheduler.Schedule(2400ms, [this](TaskContext context) + { me->SetReactState(REACT_AGGRESSIVE); me->SetInCombatWithZone(); - }, 2400ms); + context.Repeat(); + }); + } + + void UpdateAI(uint32 diff) override + { + scheduler.Update(diff); + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); } }; From 8b16f7d243d54a19e6e7d5bf79bf44427fa84bfe Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Sun, 15 Sep 2024 07:48:11 -0300 Subject: [PATCH 08/17] =?UTF-8?q?fix(Scripts/BlackTemple):=20Implement=20e?= =?UTF-8?q?motes=20when=20opening=20Najentus=20and=20=E2=80=A6=20(#19946)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(Scripts/BlackTemple): Implement emotes when opening Najentus and Den of Mortal Delights * only check if state is done --- .../rev_1726132179936077700.sql | 2 ++ src/server/game/Instances/InstanceScript.cpp | 18 ++++++++++ src/server/game/Instances/InstanceScript.h | 4 +++ .../Outland/BlackTemple/black_temple.h | 12 +++++-- .../BlackTemple/instance_black_temple.cpp | 34 +++++++++++++------ 5 files changed, 58 insertions(+), 12 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1726132179936077700.sql diff --git a/data/sql/updates/pending_db_world/rev_1726132179936077700.sql b/data/sql/updates/pending_db_world/rev_1726132179936077700.sql new file mode 100644 index 000000000..8851a0966 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1726132179936077700.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_text` SET `TextRange` = 3 WHERE `CreatureId` = 22984; diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp index 122257c15..593aab04a 100644 --- a/src/server/game/Instances/InstanceScript.cpp +++ b/src/server/game/Instances/InstanceScript.cpp @@ -761,6 +761,24 @@ void InstanceScript::LoadInstanceSavedGameobjectStateData() } } +bool InstanceScript::AllBossesDone() const +{ + for (auto const& boss : bosses) + if (boss.state != DONE) + return false; + + return true; +} + +bool InstanceScript::AllBossesDone(std::initializer_list bossIds) const +{ + for (auto const& bossId : bossIds) + if (!IsBossDone(bossId)) + return false; + + return true; +} + std::string InstanceScript::GetBossStateName(uint8 state) { // See enum EncounterState in InstanceScript.h diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h index d65bb0349..c5add7eb2 100644 --- a/src/server/game/Instances/InstanceScript.h +++ b/src/server/game/Instances/InstanceScript.h @@ -275,6 +275,10 @@ public: void LoadInstanceSavedGameobjectStateData(); + [[nodiscard]] bool IsBossDone(uint32 bossId) const { return GetBossState(bossId) == DONE; }; + [[nodiscard]] bool AllBossesDone() const; + [[nodiscard]] bool AllBossesDone(std::initializer_list bossIds) const; + TaskScheduler scheduler; protected: void SetHeaders(std::string const& dataHeaders); diff --git a/src/server/scripts/Outland/BlackTemple/black_temple.h b/src/server/scripts/Outland/BlackTemple/black_temple.h index 4b88eff27..ac876e1c7 100644 --- a/src/server/scripts/Outland/BlackTemple/black_temple.h +++ b/src/server/scripts/Outland/BlackTemple/black_temple.h @@ -42,7 +42,8 @@ enum DataTypes DATA_GATHIOS_THE_SHATTERER = 12, DATA_HIGH_NETHERMANCER_ZEREVOR = 13, DATA_LADY_MALANDE = 14, - DATA_VERAS_DARKSHADOW = 15 + DATA_VERAS_DARKSHADOW = 15, + DATA_BLACK_TEMPLE_TRIGGER = 16 }; enum CreatureIds @@ -82,7 +83,8 @@ enum CreatureIds NPC_ASHTONGUE_STALKER = 23374, NPC_STORM_FURY = 22848, - NPC_DRAGON_TURTLE = 22885 + NPC_DRAGON_TURTLE = 22885, + NPC_BLACK_TEMPLE_TRIGGER = 22984 }; enum GameObjectIds @@ -113,6 +115,12 @@ enum MiscIds SPELL_SUMMON_SHADOWFIENDS = 41159 }; +enum Texts +{ + EMOTE_NAJENTUS_DEFEATED = 0, + EMOTE_LOWER_TEMPLE_DEFEATED = 1 +}; + template inline AI* GetBlackTempleAI(T* obj) { diff --git a/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp b/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp index f324168f4..7a60d7a37 100644 --- a/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp +++ b/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp @@ -62,6 +62,7 @@ ObjectData const creatureData[] = { NPC_VERAS_DARKSHADOW, DATA_VERAS_DARKSHADOW }, { NPC_AKAMA_ILLIDAN, DATA_AKAMA_ILLIDAN }, { NPC_ILLIDAN_STORMRAGE, DATA_ILLIDAN_STORMRAGE }, + { NPC_BLACK_TEMPLE_TRIGGER, DATA_BLACK_TEMPLE_TRIGGER }, { 0, 0 } }; @@ -165,18 +166,31 @@ public: if (!InstanceScript::SetBossState(type, state)) return false; - if (type == DATA_SHADE_OF_AKAMA && state == DONE) + if (state == DONE) { - for (ObjectGuid const& guid : ashtongueGUIDs) - if (Creature* ashtongue = instance->GetCreature(guid)) - ashtongue->SetFaction(FACTION_ASHTONGUE_DEATHSWORN); - } - else if (type == DATA_ILLIDARI_COUNCIL && state == DONE) - { - if (Creature* akama = GetCreature(DATA_AKAMA_ILLIDAN)) - akama->AI()->DoAction(0); - } + switch (type) + { + case DATA_HIGH_WARLORD_NAJENTUS: + if (Creature* trigger = GetCreature(DATA_BLACK_TEMPLE_TRIGGER)) + trigger->AI()->Talk(EMOTE_NAJENTUS_DEFEATED); + break; + case DATA_SHADE_OF_AKAMA: + for (ObjectGuid const& guid : ashtongueGUIDs) + if (Creature* ashtongue = instance->GetCreature(guid)) + ashtongue->SetFaction(FACTION_ASHTONGUE_DEATHSWORN); + break; + case DATA_ILLIDARI_COUNCIL: + if (Creature* akama = GetCreature(DATA_AKAMA_ILLIDAN)) + akama->AI()->DoAction(0); + break; + default: + break; + } + if (AllBossesDone({ DATA_SHADE_OF_AKAMA, DATA_TERON_GOREFIEND, DATA_GURTOGG_BLOODBOIL, DATA_RELIQUARY_OF_SOULS })) + if (Creature* trigger = GetCreature(DATA_BLACK_TEMPLE_TRIGGER)) + trigger->AI()->Talk(EMOTE_LOWER_TEMPLE_DEFEATED); + } return true; } From d13b6963ea9962f03dfc358c286ed6c0f89051c8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 15 Sep 2024 10:49:06 +0000 Subject: [PATCH 09/17] chore(DB): import pending files Referenced commit(s): 8b16f7d243d54a19e6e7d5bf79bf44427fa84bfe --- .../rev_1726132179936077700.sql => db_world/2024_09_15_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1726132179936077700.sql => db_world/2024_09_15_00.sql} (62%) diff --git a/data/sql/updates/pending_db_world/rev_1726132179936077700.sql b/data/sql/updates/db_world/2024_09_15_00.sql similarity index 62% rename from data/sql/updates/pending_db_world/rev_1726132179936077700.sql rename to data/sql/updates/db_world/2024_09_15_00.sql index 8851a0966..b8b2dd8d2 100644 --- a/data/sql/updates/pending_db_world/rev_1726132179936077700.sql +++ b/data/sql/updates/db_world/2024_09_15_00.sql @@ -1,2 +1,3 @@ +-- DB update 2024_09_11_01 -> 2024_09_15_00 -- UPDATE `creature_text` SET `TextRange` = 3 WHERE `CreatureId` = 22984; From 04c8e85434daab642996146a243245ae73a7e858 Mon Sep 17 00:00:00 2001 From: Kitzunu <24550914+Kitzunu@users.noreply.github.com> Date: Sun, 15 Sep 2024 14:39:04 +0200 Subject: [PATCH 10/17] fix(Scripts/BT): correct illidari council enrage timer (#19975) * fix(Scripts/BT): correct illidari council enrage timer * wrong conversion from https://github.com/azerothcore/azerothcore-wotlk/commit/5ae1473e3064beb4adf666e33a38b6072639069a * redundant --- .../BlackTemple/boss_illidari_council.cpp | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidari_council.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidari_council.cpp index 016cbdba8..c3ff343ba 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_illidari_council.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_illidari_council.cpp @@ -147,11 +147,11 @@ struct boss_illidari_council : public BossAI bool spoken = false; - me->CastSpell(me, SPELL_EMPYREAL_BALANCE, true); + DoCastSelf(SPELL_EMPYREAL_BALANCE, true); ScheduleTimedEvent(3200ms, [&] { - me->CastSpell(me, SPELL_EMPYREAL_EQUIVALENCY, true); + DoCastSelf(SPELL_EMPYREAL_EQUIVALENCY, true); }, 3200ms); for (uint8 i = DATA_GATHIOS_THE_SHATTERER; i <= DATA_VERAS_DARKSHADOW; ++i) @@ -239,7 +239,7 @@ struct boss_illidari_council_memberAI : public ScriptedAI { if (param == ACTION_ENRAGE) { - me->CastSpell(me, SPELL_BERSERK, true); + DoCastSelf(SPELL_BERSERK, true); Talk(SAY_COUNCIL_ENRAGE); } } @@ -331,14 +331,14 @@ struct boss_gathios_the_shatterer : public boss_illidari_council_memberAI events.ScheduleEvent(EVENT_SPELL_BLESSING, 15s); break; case EVENT_SPELL_AURA: - me->CastSpell(me, _toggleAura ? SPELL_DEVOTION_AURA : SPELL_CHROMATIC_RESISTANCE_AURA); + DoCastSelf(_toggleAura ? SPELL_DEVOTION_AURA : SPELL_CHROMATIC_RESISTANCE_AURA); _toggleAura = !_toggleAura; events.ScheduleEvent(EVENT_SPELL_AURA, 60s); break; case EVENT_SPELL_CONSECRATION: if (roll_chance_i(50)) Talk(SAY_COUNCIL_SPECIAL); - me->CastSpell(me, SPELL_CONSECRATION, false); + DoCastSelf(SPELL_CONSECRATION); events.ScheduleEvent(EVENT_SPELL_AURA, 30s); break; case EVENT_SPELL_HAMMER_OF_JUSTICE: @@ -352,12 +352,12 @@ struct boss_gathios_the_shatterer : public boss_illidari_council_memberAI events.ScheduleEvent(EVENT_SPELL_HAMMER_OF_JUSTICE, 0s); break; case EVENT_SPELL_SEAL: - me->CastSpell(me, _toggleSeal ? SPELL_SEAL_OF_COMMAND : SPELL_SEAL_OF_BLOOD); + DoCastSelf(_toggleSeal ? SPELL_SEAL_OF_COMMAND : SPELL_SEAL_OF_BLOOD); _toggleSeal = !_toggleSeal; events.ScheduleEvent(EVENT_SPELL_SEAL, 20s); break; case EVENT_SPELL_JUDGEMENT: - me->CastSpell(me->GetVictim(), SPELL_JUDGEMENT, false); + me->CastSpell(me->GetVictim(), SPELL_JUDGEMENT); events.ScheduleEvent(EVENT_SPELL_JUDGEMENT, 16s, 20s); break; } @@ -511,22 +511,22 @@ struct boss_lady_malande : public boss_illidari_council_memberAI switch (events.ExecuteEvent()) { case EVENT_SPELL_CIRCLE_OF_HEALING: - me->CastSpell(me, SPELL_CIRCLE_OF_HEALING, false); + DoCastSelf(SPELL_CIRCLE_OF_HEALING); events.ScheduleEvent(EVENT_SPELL_CIRCLE_OF_HEALING, 20s); break; case EVENT_SPELL_REFLECTIVE_SHIELD: if (roll_chance_i(50)) Talk(SAY_COUNCIL_SPECIAL); - me->CastSpell(me, SPELL_REFLECTIVE_SHIELD, false); + DoCastSelf(SPELL_REFLECTIVE_SHIELD); events.ScheduleEvent(EVENT_SPELL_REFLECTIVE_SHIELD, 40s); break; case EVENT_SPELL_DIVINE_WRATH: if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f)) - me->CastSpell(target, SPELL_DIVINE_WRATH, false); + me->CastSpell(target, SPELL_DIVINE_WRATH); events.ScheduleEvent(EVENT_SPELL_DIVINE_WRATH, 20s); break; case EVENT_SPELL_EMPOWERED_SMITE: - me->CastSpell(me->GetVictim(), SPELL_EMPOWERED_SMITE, false); + me->CastSpell(me->GetVictim(), SPELL_EMPOWERED_SMITE); events.ScheduleEvent(EVENT_SPELL_EMPOWERED_SMITE, 3s); break; } @@ -542,7 +542,7 @@ struct boss_veras_darkshadow : public boss_illidari_council_memberAI me->SetCanDualWield(true); boss_illidari_council_memberAI::JustEngagedWith(who); events.ScheduleEvent(EVENT_SPELL_VANISH, 10s); - events.ScheduleEvent(EVENT_SPELL_ENRAGE, 90s); + events.ScheduleEvent(EVENT_SPELL_ENRAGE, 15min); } void JustSummoned(Creature* summon) override @@ -564,13 +564,13 @@ struct boss_veras_darkshadow : public boss_illidari_council_memberAI case EVENT_SPELL_VANISH: if (roll_chance_i(50)) Talk(SAY_COUNCIL_SPECIAL); - me->CastSpell(me, SPELL_DEADLY_STRIKE, false); - me->CastSpell(me, SPELL_VANISH, false); + DoCastSelf(SPELL_DEADLY_STRIKE); + DoCastSelf(SPELL_VANISH); events.ScheduleEvent(EVENT_SPELL_VANISH, 60s); events.ScheduleEvent(EVENT_SPELL_VANISH_OUT, 29s); break; case EVENT_SPELL_VANISH_OUT: - me->CastSpell(me, SPELL_VANISH_OUT, false); + DoCastSelf(SPELL_VANISH_OUT); break; case EVENT_SPELL_ENRAGE: DoResetThreatList(); From ee6e74eb3c7c02425dd564e22bbec6318f8bfc6a Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Sun, 15 Sep 2024 15:55:45 -0300 Subject: [PATCH 11/17] fix(Scripts/Commands): Fix level up achievements not being granted (#19969) --- src/server/game/Handlers/CharacterHandler.cpp | 8 ++++++-- src/server/scripts/Commands/cs_character.cpp | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 4021d541f..77fe6a4c1 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -987,8 +987,12 @@ void WorldSession::HandlePlayerLoginFromDB(LoginQueryHolder const& holder) if (pCurrChar->HasAtLoginFlag(AT_LOGIN_CHECK_ACHIEVS)) { - pCurrChar->RemoveAtLoginFlag(AT_LOGIN_CHECK_ACHIEVS, true); - pCurrChar->CheckAllAchievementCriteria(); + // If we process the check while players are loading they won't be notified of the changes. + pCurrChar->m_Events.AddEventAtOffset([pCurrChar] + { + pCurrChar->RemoveAtLoginFlag(AT_LOGIN_CHECK_ACHIEVS, true); + pCurrChar->CheckAllAchievementCriteria(); + }, 1s); } bool firstLogin = pCurrChar->HasAtLoginFlag(AT_LOGIN_FIRST); diff --git a/src/server/scripts/Commands/cs_character.cpp b/src/server/scripts/Commands/cs_character.cpp index fc479a383..8e5311a65 100644 --- a/src/server/scripts/Commands/cs_character.cpp +++ b/src/server/scripts/Commands/cs_character.cpp @@ -23,6 +23,7 @@ Category: commandscripts EndScriptData */ #include "AccountMgr.h" +#include "AchievementMgr.h" #include "Chat.h" #include "CommandScript.h" #include "DBCStores.h" @@ -272,6 +273,8 @@ public: stmt->SetData(1, playerGuid.GetCounter()); CharacterDatabase.Execute(stmt); + sAchievementMgr->UpdateAchievementCriteriaForOfflinePlayer(playerGuid.GetCounter(), ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL); + sCharacterCache->UpdateCharacterLevel(playerGuid, newLevel); } } From 1df989f7807d9d0e8cfb52a8fe1001dc62b19598 Mon Sep 17 00:00:00 2001 From: Kitzunu <24550914+Kitzunu@users.noreply.github.com> Date: Sun, 15 Sep 2024 21:11:24 +0200 Subject: [PATCH 12/17] chore(Core/Achievement): cleanup offline achievement (#19976) --- data/sql/updates/db_characters/2024_09_03_00.sql | 8 ++++++-- src/server/game/Achievements/AchievementMgr.cpp | 6 +++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/data/sql/updates/db_characters/2024_09_03_00.sql b/data/sql/updates/db_characters/2024_09_03_00.sql index b61491e17..d43d20b2e 100644 --- a/data/sql/updates/db_characters/2024_09_03_00.sql +++ b/data/sql/updates/db_characters/2024_09_03_00.sql @@ -1,11 +1,15 @@ -- DB update 2024_07_05_00 -> 2024_09_03_00 DROP TABLE IF EXISTS `character_achievement_offline_updates`; CREATE TABLE `character_achievement_offline_updates` ( - `guid` BIGINT UNSIGNED NOT NULL COMMENT 'Character\'s GUID', + `guid` INT UNSIGNED NOT NULL COMMENT 'Character\'s GUID', `update_type` TINYINT UNSIGNED NOT NULL COMMENT 'Supported types: 1 - COMPLETE_ACHIEVEMENT; 2 - UPDATE_CRITERIA', `arg1` INT UNSIGNED NOT NULL COMMENT 'For type 1: achievement ID; for type 2: ACHIEVEMENT_CRITERIA_TYPE', `arg2` INT UNSIGNED DEFAULT NULL COMMENT 'For type 2: miscValue1 for updating achievement criteria', `arg3` INT UNSIGNED DEFAULT NULL COMMENT 'For type 2: miscValue2 for updating achievement criteria', INDEX `idx_guid` (`guid`) ) -COMMENT = 'Stores updates to character achievements when the character was offline'; +COMMENT = 'Stores updates to character achievements when the character was offline' +CHARSET = utf8mb4 +COLLATE = utf8mb4_unicode_ci +ENGINE = InnoDB +; diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 9d3626e3d..a6b2f905f 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -2503,7 +2503,7 @@ void AchievementMgr::ProcessOfflineUpdate(AchievementOfflinePlayerUpdate const& { AchievementEntry const* achievement = sAchievementStore.LookupEntry(update.arg1); - ASSERT(achievement != NULL, "Not found achievement to complete for offline achievements update. Wrong arg1 ({}) value?", update.arg1); + ASSERT(achievement, "Not found achievement to complete for offline achievements update. Wrong arg1 ({}) value?", update.arg1); CompletedAchievement(achievement); break; @@ -3142,7 +3142,7 @@ void AchievementGlobalMgr::CompletedAchievementForOfflinePlayer(ObjectGuid::LowT { CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_ACHIEVEMENT_OFFLINE_UPDATES); stmt->SetData(0, playerLowGuid); - stmt->SetData(1, uint32(ACHIEVEMENT_OFFLINE_PLAYER_UPDATE_TYPE_COMPLETE_ACHIEVEMENT)); + stmt->SetData(1, ACHIEVEMENT_OFFLINE_PLAYER_UPDATE_TYPE_COMPLETE_ACHIEVEMENT); stmt->SetData(2, entry->ID); stmt->SetData(3, 0); stmt->SetData(4, 0); @@ -3153,7 +3153,7 @@ void AchievementGlobalMgr::UpdateAchievementCriteriaForOfflinePlayer(ObjectGuid: { CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_ACHIEVEMENT_OFFLINE_UPDATES); stmt->SetData(0, playerLowGuid); - stmt->SetData(1, uint32(ACHIEVEMENT_OFFLINE_PLAYER_UPDATE_TYPE_UPDATE_CRITERIA)); + stmt->SetData(1, ACHIEVEMENT_OFFLINE_PLAYER_UPDATE_TYPE_UPDATE_CRITERIA); stmt->SetData(2, type); stmt->SetData(3, miscValue1); stmt->SetData(4, miscValue2); From e2353a1c9f58a143581ed326e9b0600f90c24aeb Mon Sep 17 00:00:00 2001 From: sudlud Date: Sun, 15 Sep 2024 23:15:21 +0200 Subject: [PATCH 13/17] =?UTF-8?q?fix(Core/PlayerQuest):=20Introduce=20flag?= =?UTF-8?q?=20QUEST=5FSPECIAL=5FFLAGS=5FNO=5FLOREMAST=E2=80=A6=20(#19962)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(Core/PlayerQuest): Introduce flag QUEST_SPECIAL_FLAGS_NO_LOREMASTER_COUNT - this allows flagging quests so that they will not count towards Loremaster achievement - update Corrupted Flower Quests in Felwood accordingly as a first use case * load Specialflags as uint32 from DB --- .../pending_db_world/rev_1726231075608295100.sql | 7 +++++++ src/server/game/Achievements/AchievementMgr.cpp | 2 +- src/server/game/Quests/QuestDef.cpp | 2 +- src/server/game/Quests/QuestDef.h | 13 +++++++------ 4 files changed, 16 insertions(+), 8 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1726231075608295100.sql diff --git a/data/sql/updates/pending_db_world/rev_1726231075608295100.sql b/data/sql/updates/pending_db_world/rev_1726231075608295100.sql new file mode 100644 index 000000000..ed9f2d7e8 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1726231075608295100.sql @@ -0,0 +1,7 @@ +-- implement QUEST_SPECIAL_FLAGS_NO_LOREMASTER_COUNT +-- extend column datatype from tinyint to int +ALTER TABLE `quest_template_addon` MODIFY COLUMN `SpecialFlags` INT UNSIGNED DEFAULT 0 NOT NULL; + +-- add flag to Corrupted Flower Quests in Felwood +UPDATE `quest_template_addon` SET `SpecialFlags` = (`SpecialFlags` | 256) +WHERE (`ID` IN (996, 998, 1514, 2523, 2878, 3363, 4113, 4114, 4115, 4116, 4117, 4118, 4119, 4221, 4222, 4343, 4401, 4403, 4443, 4444, 4445, 4446, 4447, 4448, 4461, 4462, 4464, 4465, 4466, 4467)); diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index a6b2f905f..697dd05a3 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -1087,7 +1087,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui for (RewardedQuestSet::const_iterator itr = rewQuests.begin(); itr != rewQuests.end(); ++itr) { Quest const* quest = sObjectMgr->GetQuestTemplate(*itr); - if (quest && quest->GetZoneOrSort() >= 0 && uint32(quest->GetZoneOrSort()) == achievementCriteria->complete_quests_in_zone.zoneID) + if (quest && quest->GetZoneOrSort() >= 0 && uint32(quest->GetZoneOrSort()) == achievementCriteria->complete_quests_in_zone.zoneID && !(quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_NO_LOREMASTER_COUNT))) ++counter; } SetCriteriaProgress(achievementCriteria, counter); diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp index a4cf35b85..12edb29a2 100644 --- a/src/server/game/Quests/QuestDef.cpp +++ b/src/server/game/Quests/QuestDef.cpp @@ -187,7 +187,7 @@ void Quest::LoadQuestTemplateAddon(Field* fields) RequiredMaxRepValue = fields[14].Get(); StartItemCount = fields[15].Get(); RewardMailSenderEntry = fields[16].Get(); - SpecialFlags = fields[17].Get(); + SpecialFlags = fields[17].Get(); if ((SpecialFlags & QUEST_SPECIAL_FLAGS_AUTO_ACCEPT) && !sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_ACCEPT)) { diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h index 84bbec84b..247ac1ec2 100644 --- a/src/server/game/Quests/QuestDef.h +++ b/src/server/game/Quests/QuestDef.h @@ -165,17 +165,18 @@ enum QuestSpecialFlags QUEST_SPECIAL_FLAGS_CAST = 0x0020, // Set by 32 in SpecialFlags in DB if the quest requires RequiredOrNpcGo killcredit but NOT kill (a spell cast) QUEST_SPECIAL_FLAGS_NO_REP_SPILLOVER = 0x0040, // Set by 64 in SpecialFlags in DB if the quest does not share rewarded reputation with other allied factions QUEST_SPECIAL_FLAGS_CAN_FAIL_IN_ANY_STATE = 0x0080, // Set by 128 in SpecialFlags in DB if the quest is allowed to fail in Player::FailQuest() independant of its current state + QUEST_SPECIAL_FLAGS_NO_LOREMASTER_COUNT = 0x0100, // Set by 256 in SpecialFlags in DB if the quest should not count towards Loremaster Achievement // room for more custom flags QUEST_SPECIAL_FLAGS_DB_ALLOWED = QUEST_SPECIAL_FLAGS_REPEATABLE | QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT | QUEST_SPECIAL_FLAGS_AUTO_ACCEPT | QUEST_SPECIAL_FLAGS_DF_QUEST | QUEST_SPECIAL_FLAGS_MONTHLY | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_NO_REP_SPILLOVER | - QUEST_SPECIAL_FLAGS_CAN_FAIL_IN_ANY_STATE, + QUEST_SPECIAL_FLAGS_CAN_FAIL_IN_ANY_STATE | QUEST_SPECIAL_FLAGS_NO_LOREMASTER_COUNT, - QUEST_SPECIAL_FLAGS_DELIVER = 0x0100, // Internal flag computed only - QUEST_SPECIAL_FLAGS_SPEAKTO = 0x0200, // Internal flag computed only - QUEST_SPECIAL_FLAGS_KILL = 0x0400, // Internal flag computed only - QUEST_SPECIAL_FLAGS_TIMED = 0x0800, // Internal flag computed only - QUEST_SPECIAL_FLAGS_PLAYER_KILL = 0x1000 // Internal flag computed only + QUEST_SPECIAL_FLAGS_DELIVER = 0x0200, // Internal flag computed only + QUEST_SPECIAL_FLAGS_SPEAKTO = 0x0400, // Internal flag computed only + QUEST_SPECIAL_FLAGS_KILL = 0x0800, // Internal flag computed only + QUEST_SPECIAL_FLAGS_TIMED = 0x1000, // Internal flag computed only + QUEST_SPECIAL_FLAGS_PLAYER_KILL = 0x2000 // Internal flag computed only }; struct QuestLocale From 64c9e4a0a4d54ea24dce09d0ea5e762d92227fea Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 15 Sep 2024 21:16:14 +0000 Subject: [PATCH 14/17] chore(DB): import pending files Referenced commit(s): e2353a1c9f58a143581ed326e9b0600f90c24aeb --- .../rev_1726231075608295100.sql => db_world/2024_09_15_01.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/rev_1726231075608295100.sql => db_world/2024_09_15_01.sql} (92%) diff --git a/data/sql/updates/pending_db_world/rev_1726231075608295100.sql b/data/sql/updates/db_world/2024_09_15_01.sql similarity index 92% rename from data/sql/updates/pending_db_world/rev_1726231075608295100.sql rename to data/sql/updates/db_world/2024_09_15_01.sql index ed9f2d7e8..194915502 100644 --- a/data/sql/updates/pending_db_world/rev_1726231075608295100.sql +++ b/data/sql/updates/db_world/2024_09_15_01.sql @@ -1,3 +1,4 @@ +-- DB update 2024_09_15_00 -> 2024_09_15_01 -- implement QUEST_SPECIAL_FLAGS_NO_LOREMASTER_COUNT -- extend column datatype from tinyint to int ALTER TABLE `quest_template_addon` MODIFY COLUMN `SpecialFlags` INT UNSIGNED DEFAULT 0 NOT NULL; From 3bb5ec779d217e8beedf7e42f8f8146312d2c1db Mon Sep 17 00:00:00 2001 From: Benjamin Jackson <38561765+heyitsbench@users.noreply.github.com> Date: Mon, 16 Sep 2024 10:15:50 -0400 Subject: [PATCH 15/17] fix(Core/Spells): Revert triggered spell logic change. (#19983) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Revert "fix(Core/Spells): Resolve a case of triggered spells prolonging comba…" This reverts commit edd7e10dfc7651ed2657a09d5411771831c8ec1e. --- src/server/game/Entities/Unit/Unit.cpp | 12 +++++------- src/server/game/Spells/Spell.cpp | 3 +-- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 692e67fb5..3e552068e 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -20228,13 +20228,13 @@ void Unit::OutDebugInfo() const class AuraMunchingQueue : public BasicEvent { public: - AuraMunchingQueue(Unit& owner, ObjectGuid targetGUID, int32 basePoints, uint32 spellId, AuraEffect* aurEff) : _owner(owner), _targetGUID(targetGUID), _basePoints(basePoints), _spellId(spellId), _aurEff(aurEff) { } + AuraMunchingQueue(Unit& owner, ObjectGuid targetGUID, int32 basePoints, uint32 spellId) : _owner(owner), _targetGUID(targetGUID), _basePoints(basePoints), _spellId(spellId) { } bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) override { if (_owner.IsInWorld() && _owner.FindMap()) if (Unit* target = ObjectAccessor::GetUnit(_owner, _targetGUID)) - _owner.CastCustomSpell(_spellId, SPELLVALUE_BASE_POINT0, _basePoints, target, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_NO_PERIODIC_RESET), nullptr, _aurEff, _owner.GetGUID()); + _owner.CastCustomSpell(_spellId, SPELLVALUE_BASE_POINT0, _basePoints, target, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_NO_PERIODIC_RESET), nullptr, nullptr, _owner.GetGUID()); return true; } @@ -20244,15 +20244,13 @@ private: ObjectGuid _targetGUID; int32 _basePoints; uint32 _spellId; - AuraEffect* _aurEff; }; void Unit::CastDelayedSpellWithPeriodicAmount(Unit* caster, uint32 spellId, AuraType auraType, int32 addAmount, uint8 effectIndex) { - AuraEffect* aurEff = nullptr; for (AuraEffectList::iterator i = m_modAuras[auraType].begin(); i != m_modAuras[auraType].end(); ++i) { - aurEff = *i; + AuraEffect* aurEff = *i; if (aurEff->GetCasterGUID() != caster->GetGUID() || aurEff->GetId() != spellId || aurEff->GetEffIndex() != effectIndex || !aurEff->GetTotalTicks()) continue; @@ -20262,9 +20260,9 @@ void Unit::CastDelayedSpellWithPeriodicAmount(Unit* caster, uint32 spellId, Aura // xinef: delay only for casting on different unit if (this == caster || !sWorld->getBoolConfig(CONFIG_MUNCHING_BLIZZLIKE)) - caster->CastCustomSpell(spellId, SPELLVALUE_BASE_POINT0, addAmount, this, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_NO_PERIODIC_RESET), nullptr, aurEff, caster->GetGUID()); + caster->CastCustomSpell(spellId, SPELLVALUE_BASE_POINT0, addAmount, this, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_NO_PERIODIC_RESET), nullptr, nullptr, caster->GetGUID()); else - caster->m_Events.AddEvent(new AuraMunchingQueue(*caster, GetGUID(), addAmount, spellId, aurEff), caster->m_Events.CalculateQueueTime(400)); + caster->m_Events.AddEvent(new AuraMunchingQueue(*caster, GetGUID(), addAmount, spellId), caster->m_Events.CalculateQueueTime(400)); } void Unit::SendClearTarget() diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index e26a2a087..24d07cc94 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2931,8 +2931,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) { if (missInfo != SPELL_MISS_EVADE && !m_caster->IsFriendlyTo(effectUnit) && (!m_spellInfo->IsPositive() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL))) { - if (!m_triggeredByAuraSpell.spellInfo || (!(m_triggeredByAuraSpell.spellInfo->Effects[m_triggeredByAuraSpell.effectIndex].TriggerSpell == m_spellInfo->Id) && !(m_triggeredByAuraSpell.spellInfo->IsAuraEffectEqual(m_spellInfo)))) - m_caster->CombatStart(effectUnit, !(m_spellInfo->AttributesEx3 & SPELL_ATTR3_SUPRESS_TARGET_PROCS)); + m_caster->CombatStart(effectUnit, !(m_spellInfo->AttributesEx3 & SPELL_ATTR3_SUPRESS_TARGET_PROCS)); // Patch 3.0.8: All player spells which cause a creature to become aggressive to you will now also immediately cause the creature to be tapped. if (effectUnit->IsInCombatWith(m_caster)) From 07c54fe8c7c0eb32ba51d52e3f6bbc34005239ab Mon Sep 17 00:00:00 2001 From: Benjamin Jackson <38561765+heyitsbench@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:12:26 -0400 Subject: [PATCH 16/17] fix(DB/Command): Add help values for various commands. (#19984) Init. --- .../pending_db_world/command-syntax.sql | 171 ++++++++++++++++++ src/server/scripts/Commands/cs_debug.cpp | 2 +- src/server/scripts/Commands/cs_misc.cpp | 3 - 3 files changed, 172 insertions(+), 4 deletions(-) create mode 100644 data/sql/updates/pending_db_world/command-syntax.sql diff --git a/data/sql/updates/pending_db_world/command-syntax.sql b/data/sql/updates/pending_db_world/command-syntax.sql new file mode 100644 index 000000000..44690096d --- /dev/null +++ b/data/sql/updates/pending_db_world/command-syntax.sql @@ -0,0 +1,171 @@ +-- wp modify + +UPDATE `command` SET `help` = 'Syntax: .gobject set $subcommand +Type .gobject set to see the list of possible subcommands or .help gobject set $subcommand to see info on subcommands.' WHERE `name` = 'gobject set'; + +UPDATE `command` SET `help` = 'Syntax: .skirmish [arena] [XvX] [Nick1] [Nick2] ... [NickN] +[arena] can be \"all\" or comma-separated list of possible arenas (NA, BE, RL, DS, RV). +[XvX] can be 1v1, 2v2, 3v3, 5v5. After [XvX] specify enough nicknames for that mode.' WHERE `name` = 'skirmish'; + +UPDATE `command` SET `help` = 'Syntax: .bf $subcommand +Type .bf to see the list of possible subcommands or .help bf $subcommand to see info on subcommands.' WHERE `name` = 'bf'; + +UPDATE `command` SET `help` = 'Syntax: .debug entervehicle #entry #seatID +Enter the targeted or given vehicle ID in the given seat.' WHERE `name` = 'debug entervehicle'; + +UPDATE `command` SET `help` = 'Syntax: .debug getitemstate #itemState [unchanged/changed/new/removed/queue/check_all] +Returns all items in a given player''s inventory with a given item state.' WHERE `name` = 'debug getitemstate'; + +UPDATE `command` SET `help` = 'Syntax: .debug getitemvalue #GUID #index +Returns the value of the given index for the given item GUID.' WHERE `name` = 'debug getitemvalue'; + +UPDATE `command` SET `help` = 'Syntax: .debug getvalue #index #isInt +Returns either an integer or float value at a given index of your target.' WHERE `name` = 'debug getvalue'; + +UPDATE `command` SET `help` = 'Syntax: .debug hostile +Returns the hostile reference list of a given player.' WHERE `name` = 'debug hostile'; + +UPDATE `command` SET `help` = 'Syntax: .debug itemexpire #GUID +Destroy an item with the given GUID.' WHERE `name` = 'debug itemexpire'; + +UPDATE `command` SET `help` = 'Syntax: .debug lootrecipient +Returns the loot recipient of the targeted creature.' WHERE `name` = 'debug lootrecipient'; + +UPDATE `command` SET `help` = 'Syntax: .debug los +Returns line of sight status between you and your target.' WHERE `name` = 'debug los'; + +UPDATE `command` SET `help` = 'Syntax: .debug play $subcommand +Type .debug play to see the list of possible subcommands or .help debug play $subcommand to see info on subcommands.' WHERE `name` = 'debug play'; + +UPDATE `command` SET `help` = 'Syntax: .debug send $subcommand +Type .debug send to see the list of possible subcommands or .help debug send $subcommand to see info on subcommands.' WHERE `name` = 'debug send'; + +UPDATE `command` SET `help` = 'Syntax: .debug send buyerror #error +Sends the given buy error result.' WHERE `name` = 'debug send buyerror'; + +UPDATE `command` SET `help` = 'Syntax: .debug send channelnotify #type +Sends a channel notify message of the given type.' WHERE `name` = 'debug send channelnotify'; + +UPDATE `command` SET `help` = 'Syntax: .debug send chatmessage #type +Sends a chat message of the given type.', `name` = 'debug send chatmessage' WHERE `name` = 'debug send chatmmessage'; + +UPDATE `command` SET `help` = 'Syntax: .debug send equiperror #error +Sends the given equip error result.' WHERE `name` = 'debug send equiperror'; + +UPDATE `command` SET `help` = 'Syntax: .debug send largepacket +Sends a system message of 128 kilobytes.' WHERE `name` = 'debug send largepacket'; + +UPDATE `command` SET `help` = 'Syntax: .debug send opcode +Sends opcodes contained in "opcode.txt".' WHERE `name` = 'debug send opcode'; + +UPDATE `command` SET `help` = 'Syntax: .debug send qinvalidmsg #error +Sends the given quest error result.' WHERE `name` = 'debug send qinvalidmsg'; + +UPDATE `command` SET `help` = 'Syntax: .debug send qpartymsg #message +Sends the given party quest share message.' WHERE `name` = 'debug send qpartymsg'; + +UPDATE `command` SET `help` = 'Syntax: .debug send sellerror #error +Sends the given sell error result.' WHERE `name` = 'debug send sellerror'; + +UPDATE `command` SET `help` = 'Syntax: .debug send setphaseshift #phaseShift +Sends a phase shift message with the given phase shift value.' WHERE `name` = 'debug send setphaseshift'; + +UPDATE `command` SET `help` = 'Syntax: .debug send spellfail #result #failArgument1 #failArgument2 +Sends a spell failure message with the given result and argument values.' WHERE `name` = 'debug send spellfail'; + +UPDATE `command` SET `help` = 'Syntax: .debug setaurastate #state #apply +Sets the selected units aura state using the given apply value.' WHERE `name` = 'debug setaurastate'; + +UPDATE `command` SET `help` = 'Syntax: .debug setbit #index #bit +Sets the unsigned 32-bit integer value of the target at the given index to the given bit.' WHERE `name` = 'debug setbit'; + +UPDATE `command` SET `help` = 'Syntax: .debug setitemvalue #GUID #index #value +Sets the value of the given index for the given item GUID to the given value.' WHERE `name` = 'debug setitemvalue'; + +UPDATE `command` SET `help` = 'Syntax: .debug setvalue #index #value +Sets the unsigned 32-bit integer or float value of the target at the given index to the given value.' WHERE `name` = 'debug setvalue'; + +UPDATE `command` SET `help` = 'Syntax: .debug setvid #ID +Currently disabled. +Sets the given target''s vehicle ID to the given value.' WHERE `name` = 'debug setvid'; + +UPDATE `command` SET `help` = 'Syntax: .debug spawnvehicle #entry #ID +Creates a vehicle with the given ID.' WHERE `name` = 'debug spawnvehicle'; + +UPDATE `command` SET `help` = 'Syntax: .debug threat +Returns the threat list of a given creature.' WHERE `name` = 'debug threat'; + +UPDATE `command` SET `help` = 'Syntax: .debug update #index #value +Sets the unsigned 32-bit integer value of the target at the given index to the given bit.' WHERE `name` = 'debug update'; + +UPDATE `command` SET `help` = 'Syntax: .debug uws #variable #value +Sends a worldstate update for the given variable to the given value.' WHERE `name` = 'debug uws'; + +UPDATE `command` SET `help` = 'Syntax: .gobject set state #GUIDLow, #objectType, #objectState +Sets the byte value or sends a custom animation for a given gameobject GUID.' WHERE `name` = 'gobject set state'; + +UPDATE `command` SET `help` = 'Syntax: .learn all $subcommand +Type .learn all to see the list of possible subcommands or .help learn all $subcommand to see info on subcommands.' WHERE `name` = 'learn all'; + +UPDATE `command` SET `help` = 'Syntax: .learn all my $subcommand +Type .learn all my to see the list of possible subcommands or .help learn all my $subcommand to see info on subcommands.' WHERE `name` = 'learn all my'; + +UPDATE `command` SET `help` = 'Syntax: .lfg $subcommand +Type .lfg to see the list of possible subcommands or .help lfg $subcommand to see info on subcommands.' WHERE `name` = 'lfg'; + +UPDATE `command` SET `help` = 'Syntax: .lookup player $subcommand +Type .lookup player to see the list of possible subcommands or .help lookup player $subcommand to see info on subcommands.' WHERE `name` = 'lookup player'; + +UPDATE `command` SET `help` = 'Syntax: .npc near #distance +Returns all database creature spawns in a given distance.' WHERE `name` = 'npc near'; + +UPDATE `command` SET `help` = 'Syntax: .npc set $subcommand +Type .npc set to see the list of possible subcommands or .help npc set $subcommand to see info on subcommands.' WHERE `name` = 'npc set'; + +UPDATE `command` SET `help` = 'Syntax: .npc tame +Creates a player pet of the targeted creature.' WHERE `name` = 'npc tame'; + +UPDATE `command` SET `help` = 'Syntax: .reload npc_spellclick_spells +Reload npc_spellclick_spells table.' WHERE `name` = 'reload npc_spellclick_spells'; + +UPDATE `command` SET `help` = 'Syntax: .spect $subcommand +Type .spect to see the list of possible subcommands or .help spect $subcommand to see info on subcommands.' WHERE `name` = 'spect'; + +UPDATE `command` SET `help` = 'Syntax: .spect leave +Leave an arena you are spectating.' WHERE `name` = 'spect leave'; + +UPDATE `command` SET `help` = 'Syntax: .spect reset +Reset various values related to spectating.' WHERE `name` = 'spect reset'; + +UPDATE `command` SET `help` = 'Syntax: .spect spectate #name +Begin spectating the given player.' WHERE `name` = 'spect spectate'; + +UPDATE `command` SET `help` = 'Syntax: .spect version #version +Verify addon version for arena spectating.' WHERE `name` = 'spect version'; + +UPDATE `command` SET `help` = 'Syntax: .spect watch #name +Begin watching the given player.' WHERE `name` = 'spect watch'; + +UPDATE `command` SET `help` = 'Syntax: .ticket complete #ticketID +Mark a ticket of the given ID as complete.' WHERE `name` = 'ticket complete'; + +UPDATE `command` SET `help` = 'Syntax: .ticket escalate #ticketID +Add a ticket of the given ID to the escalation queue.' WHERE `name` = 'ticket escalate'; + +UPDATE `command` SET `help` = 'Syntax: .ticket escalatedlist +Return all open tickets in the escalation queue.' WHERE `name` = 'ticket escalatedlist'; + +UPDATE `command` SET `help` = 'Syntax: .ticket response $subcommand +Type .ticket response to see the list of possible subcommands or .help ticket response $subcommand to see info on subcommands.' WHERE `name` = 'ticket response'; + +UPDATE `command` SET `help` = 'Syntax: .ticket togglesystem +Toggle whether tickets are allowed or disallowed.' WHERE `name` = 'ticket togglesystem'; + +UPDATE `command` SET `help` = 'Syntax: .titles $subcommand +Type .titles to see the list of possible subcommands or .help titles $subcommand to see info on subcommands.' WHERE `name` = 'titles'; + +UPDATE `command` SET `help` = 'Syntax: .titles set $subcommand +Type .titles set to see the list of possible subcommands or .help titles set $subcommand to see info on subcommands.' WHERE `name` = 'titles set'; + +UPDATE `command` SET `help` = 'Syntax: .unban playeraccount #name +Unban accounts for character name pattern.' WHERE `name` = 'unban playeraccount'; diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index 93fe67cc3..b57ff6ccc 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -64,7 +64,7 @@ public: { { "buyerror", HandleDebugSendBuyErrorCommand, SEC_ADMINISTRATOR, Console::No }, { "channelnotify", HandleDebugSendChannelNotifyCommand, SEC_ADMINISTRATOR, Console::No }, - { "chatmmessage", HandleDebugSendChatMsgCommand, SEC_ADMINISTRATOR, Console::No }, + { "chatmessage", HandleDebugSendChatMsgCommand, SEC_ADMINISTRATOR, Console::No }, { "equiperror", HandleDebugSendEquipErrorCommand, SEC_ADMINISTRATOR, Console::No }, { "largepacket", HandleDebugSendLargePacketCommand, SEC_ADMINISTRATOR, Console::No }, { "opcode", HandleDebugSendOpcodeCommand, SEC_ADMINISTRATOR, Console::No }, diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index db29dcb36..94ccfb6eb 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -157,9 +157,6 @@ public: if (args.empty() || !tokens.size()) { - handler->PSendSysMessage("Usage: .skirmish [arena] [XvX] [Nick1] [Nick2] ... [NickN]"); - handler->PSendSysMessage("[arena] can be \"all\" or comma-separated list of possible arenas (NA, BE, RL, DS, RV)."); - handler->PSendSysMessage("[XvX] can be 1v1, 2v2, 3v3, 5v5. After [XvX] specify enough nicknames for that mode."); handler->SetSentErrorMessage(true); return false; } From a35f0c4ef61f20dd88fffff4ac5864830c4c0daf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 16 Sep 2024 15:13:36 +0000 Subject: [PATCH 17/17] chore(DB): import pending files Referenced commit(s): 07c54fe8c7c0eb32ba51d52e3f6bbc34005239ab --- .../command-syntax.sql => db_world/2024_09_16_00.sql} | 1 + 1 file changed, 1 insertion(+) rename data/sql/updates/{pending_db_world/command-syntax.sql => db_world/2024_09_16_00.sql} (99%) diff --git a/data/sql/updates/pending_db_world/command-syntax.sql b/data/sql/updates/db_world/2024_09_16_00.sql similarity index 99% rename from data/sql/updates/pending_db_world/command-syntax.sql rename to data/sql/updates/db_world/2024_09_16_00.sql index 44690096d..501e67711 100644 --- a/data/sql/updates/pending_db_world/command-syntax.sql +++ b/data/sql/updates/db_world/2024_09_16_00.sql @@ -1,3 +1,4 @@ +-- DB update 2024_09_15_01 -> 2024_09_16_00 -- wp modify UPDATE `command` SET `help` = 'Syntax: .gobject set $subcommand