diff --git a/sql/base/auth_database.sql b/sql/base/auth_database.sql index d90850cc9bb..bd52ab0edd4 100644 --- a/sql/base/auth_database.sql +++ b/sql/base/auth_database.sql @@ -1672,7 +1672,7 @@ INSERT INTO `rbac_permissions` VALUES (44,'Receive global GM messages/texts'), (45,'Join channels without announce'), (46,'Change channel settings without being channel moderator'), -(47,'Enables lower security than target check'), +(47,'Can ignore non-strong lower security checks if it\'s disabled in config'), (48,'Enable IP, Last Login and EMail output in pinfo'), (49,'Forces to enter the email for confirmation on password change'), (50,'Allow user to check his own email with .account'), @@ -2531,7 +2531,8 @@ INSERT INTO `updates` VALUES ('2024_08_28_01_auth.sql','BC5D74553AF2D92606F55C1C462D2700FE73BD34','ARCHIVED','2024-08-28 14:55:05',0), ('2024_08_30_00_auth.sql','BD76942F1C29AAA2450E051E7CA552672B5E331B','ARCHIVED','2024-08-30 19:24:30',0), ('2024_09_26_00_auth.sql','E37C3997FD7851EA360774AC568912846C448272','ARCHIVED','2024-09-26 18:27:26',0), -('2024_11_22_00_auth.sql','F2C1D1572A3968E9E9D778EF7DC82778DF3EF887','ARCHIVED','2024-11-22 23:18:14',0); +('2024_11_22_00_auth.sql','F2C1D1572A3968E9E9D778EF7DC82778DF3EF887','ARCHIVED','2024-11-22 23:18:14',0), +('2025_02_14_00_auth.sql','4A30E92FF519BB41C520CDBF90019291217C26A2','RELEASED','2025-02-14 17:20:00',0); /*!40000 ALTER TABLE `updates` ENABLE KEYS */; UNLOCK TABLES; diff --git a/sql/updates/auth/3.3.5/2025_02_14_00_auth.sql b/sql/updates/auth/3.3.5/2025_02_14_00_auth.sql new file mode 100644 index 00000000000..d147a6b499f --- /dev/null +++ b/sql/updates/auth/3.3.5/2025_02_14_00_auth.sql @@ -0,0 +1,2 @@ +-- +UPDATE `rbac_permissions` SET `name`='Can ignore non-strong lower security checks if it\'s disabled in config' WHERE `id`=47; diff --git a/sql/updates/world/3.3.5/2025_02_10_00_world.sql b/sql/updates/world/3.3.5/2025_02_10_00_world.sql new file mode 100644 index 00000000000..2fb1141b500 --- /dev/null +++ b/sql/updates/world/3.3.5/2025_02_10_00_world.sql @@ -0,0 +1,10 @@ +-- +DELETE FROM `spell_script_names` WHERE `ScriptName` IN ( + 'spell_gen_slow_roasted_turkey', + 'spell_gen_cranberry_chutney', + 'spell_gen_spice_bread_stuffing', + 'spell_gen_pumpkin_pie', + 'spell_gen_candied_sweet_potato' +); + +DELETE FROM `spell_linked_spell` WHERE `spell_effect` = 24870; diff --git a/sql/updates/world/3.3.5/2025_02_13_00_world.sql b/sql/updates/world/3.3.5/2025_02_13_00_world.sql new file mode 100644 index 00000000000..bd8b6a68863 --- /dev/null +++ b/sql/updates/world/3.3.5/2025_02_13_00_world.sql @@ -0,0 +1,4 @@ +-- +DELETE FROM `spell_proc` WHERE `SpellId`=70656; +INSERT INTO `spell_proc` (`SpellId`, `SchoolMask`, `SpellFamilyName`, `SpellFamilyMask0`, `SpellFamilyMask1`, `SpellFamilyMask2`, `ProcFlags`, `SpellTypeMask`, `SpellPhaseMask`, `HitMask`, `AttributesMask`, `DisableEffectsMask`, `ProcsPerMinute`, `Chance`, `Cooldown`, `Charges`) VALUES +(70656, 0, 15, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0); diff --git a/sql/updates/world/3.3.5/2025_02_13_01_world.sql b/sql/updates/world/3.3.5/2025_02_13_01_world.sql new file mode 100644 index 00000000000..771698389e7 --- /dev/null +++ b/sql/updates/world/3.3.5/2025_02_13_01_world.sql @@ -0,0 +1,2 @@ +-- DB/Spells: Fix Blade Barrier proc flags +UPDATE `spell_proc` SET `SpellPhaseMask`=1 WHERE `SpellId`=-49182; diff --git a/sql/updates/world/3.3.5/2025_02_13_02_world.sql b/sql/updates/world/3.3.5/2025_02_13_02_world.sql new file mode 100644 index 00000000000..76fc149481c --- /dev/null +++ b/sql/updates/world/3.3.5/2025_02_13_02_world.sql @@ -0,0 +1,25 @@ +-- Fix for Orb of Orahil chain, prevent hard locked + +-- Remove prev quest requirements from quests "Shard of a Felhound" (4962) and "Shard of an Infernal" (4963) +UPDATE `quest_template_addon` SET `PrevQuestID`=0 WHERE `ID` IN (4962,4963); + +-- Conditions +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=19 AND `SourceEntry` IN (4962,4963); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(19,0,4962,0,0,47,0,1799,74,0,0,0,0,"","Quest 'Shard of an Infernal' can only be taken if quest 'Fragments of the Orb of Orahil' is in progress, completed and rewarded"), +(19,0,4963,0,0,47,0,1799,74,0,0,0,0,"","Quest 'Shard of a Felhound' can only be taken if quest 'Fragments of the Orb of Orahil' is in progress, completed and rewarded"); + +-- Script updates +-- Spell visual more inline with what can be seen on live servers +UPDATE `smart_scripts` SET `action_param1`=16633, `comment`="Menara - On Script - Cast 'Create Item Visual'" WHERE `entryorguid`=626600 AND `id`=2; + +-- Timers +UPDATE `smart_scripts` SET `event_param1`=7000, `event_param2`=7000 WHERE `entryorguid`=626600 AND `id`=3; + +-- Comments +UPDATE `smart_scripts` SET `comment`="Menara Voidrender - On Script - Remove Npc Flag Questgiver+Gossip" WHERE `entryorguid`=626600 AND `id`=0; +UPDATE `smart_scripts` SET `comment`="Menara Voidrender - On Script - Say Line 1" WHERE `entryorguid`=626600 AND `id`=1; +UPDATE `smart_scripts` SET `comment`="Menara Voidrender - On Script - Say Line 2" WHERE `entryorguid`=626600 AND `id`=3; +UPDATE `smart_scripts` SET `comment`="Menara Voidrender - On Script - Complete Quest 'The Completed Orb of Noh'Orahil'" WHERE `entryorguid`=626600 AND `id`=4; +UPDATE `smart_scripts` SET `comment`="Menara Voidrender - On Script - Complete Quest 'The Completed Orb of Dar'Orahil'" WHERE `entryorguid`=626600 AND `id`=5; +UPDATE `smart_scripts` SET `comment`="Menara Voidrender - On Script - On Script - Add Npc Flag Questgiver+Gossip" WHERE `entryorguid`=626600 AND `id`=6; diff --git a/sql/updates/world/3.3.5/2025_02_13_03_world.sql b/sql/updates/world/3.3.5/2025_02_13_03_world.sql new file mode 100644 index 00000000000..74c5b5473e9 --- /dev/null +++ b/sql/updates/world/3.3.5/2025_02_13_03_world.sql @@ -0,0 +1,41 @@ +-- Fix for "Cleansing of the Orb of Orahil" quest event +-- Tabetha Script +DELETE FROM `smart_scripts` WHERE `entryorguid`=6546 AND `id`IN (0,11,12,13); +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (654600,654607,654608) AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(6546,0,0,0,19,0,100,0,4961,0,0,0,0,80,654600,0,0,0,0,0,1,0,0,0,0,0,0,0,0,"Tabetha - On Quest 'Cleansing of the Orb of Orahil' Taken - Run Script"), +(6546,0,11,12,40,0,100,0,4,6546,0,0,0,80,654607,2,0,0,0,0,1,0,0,0,0,0,0,0,0,"Tabetha - On Waypoint 4 Reached - Run Script"), +(6546,0,12,0,61,0,100,0,0,0,0,0,0,59,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,"Tabetha - On Link - Set Run On"), +(6546,0,13,0,40,0,100,0,9,6546,0,0,0,80,654608,2,0,0,0,0,1,0,0,0,0,0,0,0,0,"Tabetha - On Waypoint 9 Reached - Run Script"), + +-- Tabetha Timed List 1 +(654600,9,0,0,0,0,100,0,0,0,0,0,0,83,3,0,0,0,0,0,1,0,0,0,0,0,0,0,0,"Tabetha - On Script - Remove Npc Flag Questgiver+Gossip"), +(654600,9,1,0,0,0,100,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,"Tabetha - On Script - Say Line 0"), +(654600,9,2,0,0,0,100,0,0,0,0,0,0,53,0,6546,0,0,0,0,0,0,0,0,0,0,0,0,0,"Tabetha - On Script - Start Waypoint"), + +-- Tabetha Timed List 8 +(654607,9,0,0,0,0,100,0,0,0,0,0,0,54,6000,0,0,0,0,0,1,0,0,0,0,0,0,0,0,"Tabetha - On Script - Pause Waypoint"), +(654607,9,1,0,0,0,100,0,1000,1000,0,0,0,11,9097,0,0,0,0,0,1,0,0,0,0,0,0,0,0,"Tabetha - On Script - Cast Summon Demon of the Orb"), + +-- Tabetha Timed List 9 +(654608,9,0,0,0,0,100,0,1000,1000,0,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,0,2.0822,"Tabetha - On Script - Reset Orientation"), +(654608,9,1,0,0,0,100,0,1000,1000,0,0,0,82,3,0,0,0,0,0,1,0,0,0,0,0,0,0,0,"Tabetha - On Script - Add Npc Flag Questgiver+Gossip"); + +-- Waypoints +DELETE FROM `waypoints` WHERE `entry`=6546; +INSERT INTO `waypoints` (`entry`,`pointid`,`position_x`,`position_y`,`position_z`,`point_comment`) VALUES +(6546,1,-4037.934,-3380.369,37.811,''), +(6546,2,-4036.560,-3377.986,37.762,''), +(6546,3,-4029.500,-3376.984,38.132,''), +(6546,4,-4019.693,-3381.410,38.228,'Tabetha_SUMMON'), +(6546,5,-4029.500,-3376.984,38.132,''), +(6546,6,-4036.560,-3377.986,37.762,''), +(6546,7,-4037.934,-3380.369,37.811,''), +(6546,8,-4034.080,-3388.858,38.997,''), +(6546,9,-4031.560,-3392.970,38.997,'Tabetha_STOP'); + +-- Conditions to prevent Tabetha from stopping and summoning another Demon if one is already present +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=22 AND `SourceEntry`=654607 AND `SourceId`=9; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(22,1,654607,9,0,29,1,6549,100,0,1,0,0,"","Smart Event 1 for creature Tabetha only executes if creature 'Demon of the Orb' not near"), +(22,2,654607,9,0,29,1,6549,100,0,1,0,0,"","Smart Event 2 for creature Tabetha only executes if creature 'Demon of the Orb' not near"); diff --git a/sql/updates/world/3.3.5/2025_02_13_04_world.sql b/sql/updates/world/3.3.5/2025_02_13_04_world.sql new file mode 100644 index 00000000000..589644bcf8f --- /dev/null +++ b/sql/updates/world/3.3.5/2025_02_13_04_world.sql @@ -0,0 +1,18 @@ +-- Quest "The Completed Robe" Intro + +-- Quest flag +UPDATE `quest_template_addon` SET `SpecialFlags`=`SpecialFlags`|2 WHERE `ID`=4786; + +-- Menara Voidrender Script +DELETE FROM `smart_scripts` WHERE `entryorguid`=626601 AND `source_type`=9; +DELETE FROM `smart_scripts` WHERE `entryorguid`=6266 AND `id` IN (2,3); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES + +(6266,0,2,3,19,0,100,0,4786,0,0,0,0,64,1,0,0,0,0,0,7,0,0,0,0,0,0,0,0,"Menara Voidrender - On Quest 'The Completed Robe' Taken - Store Targetlist"), +(6266,0,3,0,61,0,100,0,0,0,0,0,0,80,626601,0,0,0,0,0,1,0,0,0,0,0,0,0,0,"Menara Voidrender - On Link - Run Script"), + +-- Menara Voidrender Timed List 1 +(626601,9,0,0,0,0,100,0,0,0,0,0,0,83,3,0,0,0,0,0,1,0,0,0,0,0,0,0,0,"Menara Voidrender - On Script - Remove Npc Flag Questgiver+Gossip"), +(626601,9,1,0,0,0,100,0,1000,1000,0,0,0,11,16633,0,0,0,0,0,1,0,0,0,0,0,0,0,0,"Menara Voidrender - On Script - Cast 'Create Item Visual'"), +(626601,9,2,0,0,0,100,0,7000,7000,0,0,0,15,4786,0,0,0,0,0,12,1,0,0,0,0,0,0,0,"Menara Voidrender - On Script - Complete Quest"), +(626601,9,3,0,0,0,100,0,0,0,0,0,0,82,3,0,0,0,0,0,1,0,0,0,0,0,0,0,0,"Menara Voidrender - On Script - Add Npc Flag Questgiver+Gossip"); diff --git a/sql/updates/world/3.3.5/2025_02_13_05_world.sql b/sql/updates/world/3.3.5/2025_02_13_05_world.sql new file mode 100644 index 00000000000..67757d87139 --- /dev/null +++ b/sql/updates/world/3.3.5/2025_02_13_05_world.sql @@ -0,0 +1,2 @@ +-- Fix model for creature 6546 (Tabetha) +UPDATE `creature_model_info` SET `DisplayID_Other_Gender`=0 WHERE `DisplayID`=5375; diff --git a/sql/updates/world/3.3.5/2025_02_14_00_world.sql b/sql/updates/world/3.3.5/2025_02_14_00_world.sql new file mode 100644 index 00000000000..6a675eace33 --- /dev/null +++ b/sql/updates/world/3.3.5/2025_02_14_00_world.sql @@ -0,0 +1,2 @@ +-- Update "Lessons Anew" Completion (RewardText) +UPDATE `quest_offer_reward` SET `RewardText`="Greetings young $c, I'm glad to see you ready and eager to learn about the curing of poisons.$B$BWhile most druids in the past were put through pre-planned trials, your work will involve no such thing. There has been a rash of animal poisonings in Auberdine, and the village there has been unable to cure it. To that end, a representative there has asked Moonglade for aid and we are sending you there to aid them. This is no exercise - the work you'll do is quite real. Bear this in mind." WHERE `ID`=6121; diff --git a/sql/updates/world/3.3.5/2025_02_14_01_world.sql b/sql/updates/world/3.3.5/2025_02_14_01_world.sql new file mode 100644 index 00000000000..779deef8ce8 --- /dev/null +++ b/sql/updates/world/3.3.5/2025_02_14_01_world.sql @@ -0,0 +1,2 @@ +-- Allow The Multiphase Survey quest for both sides +UPDATE `quest_template` SET `AllowableRaces`=0 WHERE `ID`=11880; diff --git a/src/common/Utilities/Duration.h b/src/common/Utilities/Duration.h index b4c3f17cb3e..f506467abda 100644 --- a/src/common/Utilities/Duration.h +++ b/src/common/Utilities/Duration.h @@ -18,12 +18,7 @@ #ifndef _DURATION_H_ #define _DURATION_H_ -// HACKS TERRITORY -#if __has_include(<__msvc_chrono.hpp>) -#include <__msvc_chrono.hpp> // skip all the formatting/istream/locale/mutex bloat -#else #include -#endif /// Milliseconds shorthand typedef. typedef std::chrono::milliseconds Milliseconds; diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index 3b6437c1bfe..5fdc0fe7c1d 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -97,7 +97,7 @@ enum RBACPermissions RBAC_PERM_RECEIVE_GLOBAL_GM_TEXTMESSAGE = 44, RBAC_PERM_SILENTLY_JOIN_CHANNEL = 45, RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR = 46, - RBAC_PERM_CHECK_FOR_LOWER_SECURITY = 47, + RBAC_PERM_CAN_IGNORE_LOWER_SECURITY_CHECK = 47, RBAC_PERM_COMMANDS_PINFO_CHECK_PERSONAL_DATA = 48, RBAC_PERM_EMAIL_CONFIRM_FOR_PASS_CHANGE = 49, RBAC_PERM_MAY_CHECK_OWN_EMAIL = 50, diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.h b/src/server/game/Battlegrounds/Zones/BattlegroundAB.h index a57c38e435f..d23b751b83f 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.h @@ -130,7 +130,7 @@ enum BG_AB_Timers enum BG_AB_Score { - BG_AB_WARNING_NEAR_VICTORY_SCORE = 1400, + BG_AB_WARNING_NEAR_VICTORY_SCORE = 1440, BG_AB_MAX_TEAM_SCORE = 1600 }; @@ -197,8 +197,8 @@ enum BG_AB_Sounds BG_AB_SOUND_NODE_CAPTURED_HORDE = 8213, BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE = 8212, BG_AB_SOUND_NODE_ASSAULTED_HORDE = 8174, - BG_AB_SOUND_NEAR_VICTORY_ALLIANCE = 8456, - BG_AB_SOUND_NEAR_VICTORY_HORDE = 8457 + BG_AB_SOUND_NEAR_VICTORY_ALLIANCE = 8457, + BG_AB_SOUND_NEAR_VICTORY_HORDE = 8456 }; enum BG_AB_Objectives diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index 427619d0533..31424d7ee43 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -77,7 +77,7 @@ bool ChatHandler::HasLowerSecurityAccount(WorldSession* target, uint32 target_ac return false; // ignore only for non-players for non strong checks (when allow apply command at least to same sec level) - if (m_session->HasPermission(rbac::RBAC_PERM_CHECK_FOR_LOWER_SECURITY) && !strong && !sWorld->getBoolConfig(CONFIG_GM_LOWER_SECURITY)) + if (m_session->HasPermission(rbac::RBAC_PERM_CAN_IGNORE_LOWER_SECURITY_CHECK) && !strong && !sWorld->getBoolConfig(CONFIG_GM_LOWER_SECURITY)) return false; if (target) diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index db28b515d04..4713ce9034d 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -2523,8 +2523,16 @@ void GameObject::SetLootState(LootState state, Unit* unit) AI()->OnLootStateChanged(state, unit); // Start restock timer if the chest is partially looted or not looted at all - if (GetGoType() == GAMEOBJECT_TYPE_CHEST && state == GO_ACTIVATED && GetGOInfo()->chest.chestRestockTime > 0 && m_restockTime == 0) - m_restockTime = GameTime::GetGameTime() + GetGOInfo()->chest.chestRestockTime; + if (GetGoType() == GAMEOBJECT_TYPE_CHEST && state == GO_ACTIVATED) + { + GameObjectTemplate const* goInfo = GetGOInfo(); + if (goInfo->chest.chestRestockTime > 0 && m_restockTime == 0) + m_restockTime = GameTime::GetGameTime() + goInfo->chest.chestRestockTime; + + // If world chests were opened, despawn them after 5 minutes + if (goInfo->chest.chestRestockTime == 0 && GetMap()->IsWorldMap()) + DespawnOrUnsummon(5min); + } if (GetGoType() == GAMEOBJECT_TYPE_DOOR) // only set collision for doors on SetGoState return; diff --git a/src/server/game/Entities/Pet/PetDefines.h b/src/server/game/Entities/Pet/PetDefines.h index 9f4683ef283..90150f3b0c6 100644 --- a/src/server/game/Entities/Pet/PetDefines.h +++ b/src/server/game/Entities/Pet/PetDefines.h @@ -67,18 +67,19 @@ enum PetSpellType PETSPELL_TALENT = 2 }; -enum ActionFeedback +enum class PetActionFeedback : uint8 { - FEEDBACK_NONE = 0, - FEEDBACK_PET_DEAD = 1, - FEEDBACK_NOTHING_TO_ATT = 2, - FEEDBACK_CANT_ATT_TARGET = 3 + None = 0, + Dead = 1, + NoTarget = 2, + InvalidTarget = 3, + NoPath = 4 }; -enum PetTalk +enum PetAction : int32 { - PET_TALK_SPECIAL_SPELL = 0, - PET_TALK_ATTACK = 1 + PET_ACTION_SPECIAL_SPELL = 0, + PET_ACTION_ATTACK = 1 }; #define PET_FOLLOW_DIST 1.0f diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index bac4222cf4d..123c3403ec0 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -58,6 +58,7 @@ #include "PassiveAI.h" #include "PetAI.h" #include "Pet.h" +#include "PetPackets.h" #include "Player.h" #include "PlayerAI.h" #include "QuestDef.h" @@ -10242,30 +10243,39 @@ void Unit::TriggerAurasProcOnEvent(ProcEventInfo& eventInfo, AuraApplicationProc } ///----------Pet responses methods----------------- -void Unit::SendPetActionFeedback(uint8 msg) +void Unit::SendPetActionFeedback(PetActionFeedback msg, uint32 spellId) const { Unit* owner = GetOwner(); if (!owner || owner->GetTypeId() != TYPEID_PLAYER) return; - WorldPacket data(SMSG_PET_ACTION_FEEDBACK, 1); - data << uint8(msg); - owner->ToPlayer()->SendDirectMessage(&data); + WorldPackets::Pet::PetActionFeedback petActionFeedback; + petActionFeedback.SpellID = spellId; + petActionFeedback.Response = msg; + owner->ToPlayer()->SendDirectMessage(petActionFeedback.Write()); } -void Unit::SendPetTalk(uint32 pettalk) +void Unit::SendPetActionSound(PetAction action) const { - Unit* owner = GetOwner(); - if (!owner || owner->GetTypeId() != TYPEID_PLAYER) + WorldPackets::Pet::PetActionSound petActionSound; + petActionSound.UnitGUID = GetGUID(); + petActionSound.Action = action; + SendMessageToSet(petActionSound.Write(), false); +} + +void Unit::SendPetDismissSound() const +{ + CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.LookupEntry(GetNativeDisplayId()); + if (!displayInfo) return; - WorldPacket data(SMSG_PET_ACTION_SOUND, 8 + 4); - data << uint64(GetGUID()); - data << uint32(pettalk); - owner->ToPlayer()->SendDirectMessage(&data); + WorldPackets::Pet::PetDismissSound petDismissSound; + petDismissSound.ModelId = displayInfo->ModelID; + petDismissSound.ModelPosition = GetPosition(); + SendMessageToSet(petDismissSound.Write(), false); } -void Unit::SendPetAIReaction(ObjectGuid guid) +void Unit::SendPetAIReaction(ObjectGuid guid) const { Unit* owner = GetOwner(); if (!owner || owner->GetTypeId() != TYPEID_PLAYER) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 5991b268b87..a0b232460d9 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -21,6 +21,7 @@ #include "Object.h" #include "CombatManager.h" #include "SpellAuraDefines.h" +#include "PetDefines.h" #include "ThreatManager.h" #include "Timer.h" #include "UnitDefines.h" @@ -1707,9 +1708,10 @@ class TC_GAME_API Unit : public WorldObject void ClearComboPointHolders(); ///----------Pet responses methods----------------- - void SendPetActionFeedback(uint8 msg); - void SendPetTalk(uint32 pettalk); - void SendPetAIReaction(ObjectGuid guid); + void SendPetActionFeedback(PetActionFeedback msg, uint32 spellId) const; + void SendPetActionSound(PetAction action) const; + void SendPetDismissSound() const; + void SendPetAIReaction(ObjectGuid guid) const; ///----------End of Pet responses methods---------- void PropagateSpeedChange(); diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index 12590139ea9..a0ff9c4bc51 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -212,8 +212,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe AI->AttackStart(TargetUnit); // 10% chance to play special pet attack talk, else growl - if (pet->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10) - pet->SendPetTalk((uint32)PET_TALK_ATTACK); + if (pet->IsPet() && pet->ToPet()->getPetType() == SUMMON_PET && pet != TargetUnit && roll_chance_i(10)) + pet->SendPetActionSound(PET_ACTION_ATTACK); else { // 90% chance for pet and 100% chance for charmed creature @@ -242,10 +242,13 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe ASSERT(pet->GetTypeId() == TYPEID_UNIT); if (pet->IsPet()) { - if (((Pet*)pet)->getPetType() == HUNTER_PET) - GetPlayer()->RemovePet((Pet*)pet, PET_SAVE_AS_DELETED); + if (pet->ToPet()->getPetType() == HUNTER_PET) + GetPlayer()->RemovePet(pet->ToPet(), PET_SAVE_AS_DELETED); else - GetPlayer()->RemovePet((Pet*)pet, PET_SAVE_NOT_IN_SLOT); + { + pet->SendPetDismissSound(); + GetPlayer()->RemovePet(pet->ToPet(), PET_SAVE_NOT_IN_SLOT); + } } else if (pet->HasUnitTypeMask(UNIT_MASK_MINION)) { @@ -342,8 +345,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe // 10% chance to play special pet attack talk, else growl // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell - if (pet->IsPet() && (((Pet*)pet)->getPetType() == SUMMON_PET) && (pet != unit_target) && (urand(0, 100) < 10)) - pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); + if (pet->IsPet() && pet->ToPet()->getPetType() == SUMMON_PET && pet != unit_target && roll_chance_i(10)) + pet->SendPetActionSound(PET_ACTION_SPECIAL_SPELL); else { pet->SendPetAIReaction(guid1); @@ -811,10 +814,10 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) { if (Pet* pet = creature->ToPet()) { - // 10% chance to play special pet attack talk, else growl + // 10% chance to play special pet attack sound, else growl // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell - if (pet->getPetType() == SUMMON_PET && (urand(0, 100) < 10)) - pet->SendPetTalk(PET_TALK_SPECIAL_SPELL); + if (pet->getPetType() == SUMMON_PET && roll_chance_i(10)) + pet->SendPetActionSound(PET_ACTION_SPECIAL_SPELL); else pet->SendPetAIReaction(guid); } diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index 56d99a85012..ee694f7d366 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -487,7 +487,7 @@ void WorldSession::HandlePetCancelAuraOpcode(WorldPackets::Spells::PetCancelAura if (!pet->IsAlive()) { - pet->SendPetActionFeedback(FEEDBACK_PET_DEAD); + pet->SendPetActionFeedback(PetActionFeedback::Dead, 0); return; } diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index ecc900b41bd..9ab7f63aabd 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -4226,6 +4226,11 @@ bool Map::Instanceable() const return i_mapEntry && i_mapEntry->Instanceable(); } +bool Map::IsWorldMap() const +{ + return i_mapEntry && i_mapEntry->IsWorldMap(); +} + bool Map::IsDungeon() const { return i_mapEntry && i_mapEntry->IsDungeon(); diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index dfe0ff4a37a..1f8ff20264f 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -419,6 +419,7 @@ class TC_GAME_API Map : public GridRefManager MapDifficulty const* GetMapDifficulty() const; bool Instanceable() const; + bool IsWorldMap() const; bool IsDungeon() const; bool IsNonRaidDungeon() const; bool IsRaid() const; diff --git a/src/server/game/Server/Packets/PetPackets.cpp b/src/server/game/Server/Packets/PetPackets.cpp index 7653e2a2328..c3d060eb9f6 100755 --- a/src/server/game/Server/Packets/PetPackets.cpp +++ b/src/server/game/Server/Packets/PetPackets.cpp @@ -50,3 +50,28 @@ WorldPacket const* WorldPackets::Pet::PetUnlearnedSpell::Write() _worldPacket << uint32(SpellID); return &_worldPacket; } + +WorldPacket const* WorldPackets::Pet::PetActionFeedback::Write() +{ + _worldPacket << uint8(Response); + if (Response == ::PetActionFeedback::NoTarget || Response == ::PetActionFeedback::InvalidTarget) + _worldPacket << int32(SpellID); + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Pet::PetActionSound::Write() +{ + _worldPacket << UnitGUID; + _worldPacket << int32(Action); + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Pet::PetDismissSound::Write() +{ + _worldPacket << int32(ModelId); + _worldPacket << ModelPosition; + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/PetPackets.h b/src/server/game/Server/Packets/PetPackets.h index cf175fb6f5a..ab9856d1dc1 100755 --- a/src/server/game/Server/Packets/PetPackets.h +++ b/src/server/game/Server/Packets/PetPackets.h @@ -19,6 +19,8 @@ #define PetPackets_h__ #include "Packet.h" +#include "PetDefines.h" +#include "Position.h" #include "ObjectGuid.h" namespace WorldPackets @@ -94,6 +96,39 @@ namespace WorldPackets void Read() override { } }; + + class PetActionFeedback final : public ServerPacket + { + public: + PetActionFeedback() : ServerPacket(SMSG_PET_ACTION_FEEDBACK, 4 + 1) { } + + WorldPacket const* Write() override; + + int32 SpellID = 0; + ::PetActionFeedback Response = ::PetActionFeedback::None; + }; + + class PetActionSound final : public ServerPacket + { + public: + PetActionSound() : ServerPacket(SMSG_PET_ACTION_SOUND, 8 + 4) { } + + WorldPacket const* Write() override; + + ObjectGuid UnitGUID; + int32 Action = 0; + }; + + class PetDismissSound final : public ServerPacket + { + public: + PetDismissSound() : ServerPacket(SMSG_PET_DISMISS_SOUND, 4 + 12) { } + + WorldPacket const* Write() override; + + int32 ModelId = 0; + TaggedPosition ModelPosition; + }; } } diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index a789836277e..3dfd8dc16e4 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -4912,6 +4912,52 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(5); // 40yd }); + // Pilgrim's Bounty - Candied Sweet Potato + ApplySpellFix({ 65418 }, [](SpellInfo* spellInfo) + { + spellInfo->_GetEffect(EFFECT_2).TriggerSpell = 65410; + }); + + // Pilgrim's Bounty - Spice Bread Stuffing + ApplySpellFix({ 65419 }, [](SpellInfo* spellInfo) + { + spellInfo->_GetEffect(EFFECT_2).TriggerSpell = 65416; + }); + + // Pilgrim's Bounty - Cranberry Chutney + ApplySpellFix({ 65420 }, [](SpellInfo* spellInfo) + { + spellInfo->_GetEffect(EFFECT_2).TriggerSpell = 65412; + }); + + // Pilgrim's Bounty - Pumpkin Pie + ApplySpellFix({ 65421 }, [](SpellInfo* spellInfo) + { + spellInfo->_GetEffect(EFFECT_2).TriggerSpell = 65415; + }); + + // Pilgrim's Bounty - Slow-Roasted Turkey + ApplySpellFix({ 65422 }, [](SpellInfo* spellInfo) + { + spellInfo->_GetEffect(EFFECT_2).TriggerSpell = 65414; + }); + + ApplySpellFix({ + 24869, // Bobbing Apple, Bread of the Dead, Winter Veil Cookie + 61874, // Noblegarden Chocolate + 71068, // Sweet Surprise + 71071, // Very Berry Cream + 71073, // Dark Desire + 71074 // Buttermilk Delight + }, [](SpellInfo* spellInfo) + { + spellInfo->_GetEffect(EFFECT_1).Effect = SPELL_EFFECT_APPLY_AURA; + spellInfo->_GetEffect(EFFECT_1).TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER); + spellInfo->_GetEffect(EFFECT_1).ApplyAuraName = SPELL_AURA_PERIODIC_TRIGGER_SPELL; + spellInfo->_GetEffect(EFFECT_1).Amplitude = 10 * IN_MILLISECONDS; + spellInfo->_GetEffect(EFFECT_1).TriggerSpell = 24870; + }); + for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i) { SpellInfo* spellInfo = mSpellInfoMap[i]; diff --git a/src/server/scripts/Events/pilgrims_bounty.cpp b/src/server/scripts/Events/pilgrims_bounty.cpp index b61bb81f6e0..b078fbf0d40 100644 --- a/src/server/scripts/Events/pilgrims_bounty.cpp +++ b/src/server/scripts/Events/pilgrims_bounty.cpp @@ -33,36 +33,6 @@ enum PilgrimsBountyBuffFood SPELL_WELL_FED_SPIRIT_TRIGGER = 65415 }; -class spell_pilgrims_bounty_buff_food : public AuraScript -{ - PrepareAuraScript(spell_pilgrims_bounty_buff_food); -private: - uint32 const _triggeredSpellId; - -public: - spell_pilgrims_bounty_buff_food(uint32 triggeredSpellId) : AuraScript(), _triggeredSpellId(triggeredSpellId) - { - _handled = false; - } - - void HandleTriggerSpell(AuraEffect const* /*aurEff*/) - { - PreventDefaultAction(); - if (_handled) - return; - - _handled = true; - GetTarget()->CastSpell(GetTarget(), _triggeredSpellId, true); - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_pilgrims_bounty_buff_food::HandleTriggerSpell, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL); - } - - bool _handled; -}; - enum FeastOnSpells { FEAST_ON_TURKEY = 61784, @@ -449,11 +419,6 @@ class spell_pilgrims_bounty_a_serving_of : public AuraScript void AddSC_event_pilgrims_bounty() { - RegisterSpellScriptWithArgs(spell_pilgrims_bounty_buff_food, "spell_gen_slow_roasted_turkey", SPELL_WELL_FED_AP_TRIGGER); - RegisterSpellScriptWithArgs(spell_pilgrims_bounty_buff_food, "spell_gen_cranberry_chutney", SPELL_WELL_FED_ZM_TRIGGER); - RegisterSpellScriptWithArgs(spell_pilgrims_bounty_buff_food, "spell_gen_spice_bread_stuffing", SPELL_WELL_FED_HIT_TRIGGER); - RegisterSpellScriptWithArgs(spell_pilgrims_bounty_buff_food, "spell_gen_pumpkin_pie", SPELL_WELL_FED_SPIRIT_TRIGGER); - RegisterSpellScriptWithArgs(spell_pilgrims_bounty_buff_food, "spell_gen_candied_sweet_potato", SPELL_WELL_FED_HASTE_TRIGGER); RegisterSpellScript(spell_pilgrims_bounty_feast_on); RegisterSpellScriptWithArgs(spell_pilgrims_bounty_well_fed, "spell_pilgrims_bounty_well_fed_turkey", SPELL_WELL_FED_AP_TRIGGER); RegisterSpellScriptWithArgs(spell_pilgrims_bounty_well_fed, "spell_pilgrims_bounty_well_fed_cranberry", SPELL_WELL_FED_ZM_TRIGGER); diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 971eebc6cf9..90df12387f3 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -2178,8 +2178,12 @@ GM.AllowInvite = 0 # # GM.LowerSecurity -# Description: Allow lower security levels to use commands on higher security level -# characters. +# Description: Disallow lower security levels to use commands on higher security level +# characters. Regardless of this value, lower security check is always +# enabled for accounts without RBAC_PERM_CAN_IGNORE_LOWER_SECURITY_CHECK. +# This option also does not affect "strong" checks, such as in +# certain .account and .rbac commands, which are always enabled. +# # Default: 0 - (Disabled) # 1 - (Enabled)