diff options
author | Shauren <shauren.trinity@gmail.com> | 2016-06-13 21:00:25 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2016-06-13 21:00:25 +0200 |
commit | d2733eb6f1f9a550ec6511b5fa696b67b11044b3 (patch) | |
tree | 92e101dba7e48661de4a02c93bfba5700a6f1bdf /src/server/game | |
parent | 3903482eb810625fce64c616a4edca3f06975e94 (diff) | |
parent | 2fe6fc63d79655a96ee2135a6b380ce353729088 (diff) |
Merge branch '6.x' of https://github.com/TrinityCore/TrinityCore into legion
Diffstat (limited to 'src/server/game')
65 files changed, 893 insertions, 609 deletions
diff --git a/src/server/game/AI/CoreAI/GameObjectAI.h b/src/server/game/AI/CoreAI/GameObjectAI.h index 7a2f23ac804..6d02f97e0ec 100644 --- a/src/server/game/AI/CoreAI/GameObjectAI.h +++ b/src/server/game/AI/CoreAI/GameObjectAI.h @@ -47,7 +47,7 @@ class TC_GAME_API GameObjectAI static int Permissible(GameObject const* go); - virtual bool GossipHello(Player* /*player*/) { return false; } + virtual bool GossipHello(Player* /*player*/, bool /*isUse*/) { return false; } virtual bool GossipSelect(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/) { return false; } virtual bool GossipSelectCode(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/, char const* /*code*/) { return false; } virtual bool QuestAccept(Player* /*player*/, Quest const* /*quest*/) { return false; } diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index 914a476cf7d..5cda5fce674 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -840,7 +840,7 @@ void SmartGameObjectAI::Reset() } // Called when a player opens a gossip dialog with the gameobject. -bool SmartGameObjectAI::GossipHello(Player* player) +bool SmartGameObjectAI::GossipHello(Player* player, bool /*isUse*/) { TC_LOG_DEBUG("scripts.ai", "SmartGameObjectAI::GossipHello"); GetScript()->ProcessEventsFor(SMART_EVENT_GOSSIP_HELLO, player, 0, 0, false, NULL, go); diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h index aa7c9ace0b3..67a7bd4c330 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.h +++ b/src/server/game/AI/SmartScripts/SmartAI.h @@ -242,7 +242,7 @@ class TC_GAME_API SmartGameObjectAI : public GameObjectAI SmartScript* GetScript() { return &mScript; } static int Permissible(const GameObject* g); - bool GossipHello(Player* player) override; + bool GossipHello(Player* player, bool isUse) override; bool GossipSelect(Player* player, uint32 sender, uint32 action) override; bool GossipSelectCode(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/, const char* /*code*/) override; bool QuestAccept(Player* player, Quest const* quest) override; diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp index 53cc4d57033..3b3be37b0b3 100644 --- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp +++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp @@ -442,11 +442,11 @@ void AuctionHouseMgr::PendingAuctionProcess(Player* player) totaldeposit = GetAuctionDeposit(itr->auctionHouseEntry, itr->etime, item, totalItems); uint32 depositremain = totaldeposit; - for (auto itr = thisAH->begin(); itr != thisAH->end(); ++itr) + for (auto itrAH = thisAH->begin(); itrAH != thisAH->end(); ++itrAH) { - AuctionEntry* AH = (*itr); + AuctionEntry* AH = (*itrAH); - if (next(itr) == thisAH->end()) + if (next(itrAH) == thisAH->end()) AH->deposit = depositremain; else { diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp index 58874e394e5..0db3ed09ef2 100644 --- a/src/server/game/Battlefield/Battlefield.cpp +++ b/src/server/game/Battlefield/Battlefield.cpp @@ -828,7 +828,7 @@ GameObject* Battlefield::SpawnGameObject(uint32 entry, float x, float y, float z // Create gameobject GameObject* go = new GameObject; - if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, PHASEMASK_NORMAL, x, y, z, o, 0, 0, 0, 0, 100, GO_STATE_READY)) + if (!go->Create(entry, map, PHASEMASK_NORMAL, x, y, z, o, 0, 0, 0, 0, 100, GO_STATE_READY)) { TC_LOG_ERROR("bg.battlefield", "Battlefield::SpawnGameObject: Could not create gameobject template %u! Battlefield has not been created!", entry); delete go; diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index 825a56820f2..449e614a900 100644 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -1076,6 +1076,12 @@ void Battleground::StartBattleground() TC_LOG_DEBUG("bg.arena", "Arena match type: %u for Team1Id: %u - Team2Id: %u started.", m_ArenaType, m_ArenaTeamIds[TEAM_ALLIANCE], m_ArenaTeamIds[TEAM_HORDE]); } +void Battleground::TeleportPlayerToExploitLocation(Player* player) +{ + if (WorldSafeLocsEntry const* loc = GetExploitTeleportLocation(Team(player->GetBGTeam()))) + player->TeleportTo(loc->MapID, loc->Loc.X, loc->Loc.Y, loc->Loc.Z, loc->Facing); +} + void Battleground::AddPlayer(Player* player) { // remove afk from player @@ -1455,8 +1461,7 @@ bool Battleground::AddObject(uint32 type, uint32 entry, float x, float y, float // and when loading it (in go::LoadFromDB()), a new guid would be assigned to the object, and a new object would be created // So we must create it specific for this instance GameObject* go = new GameObject; - if (!go->Create(GetBgMap()->GenerateLowGuid<HighGuid::GameObject>(), entry, GetBgMap(), - PHASEMASK_NORMAL, x, y, z, o, rotation0, rotation1, rotation2, rotation3, 100, goState)) + if (!go->Create(entry, GetBgMap(), PHASEMASK_NORMAL, x, y, z, o, rotation0, rotation1, rotation2, rotation3, 100, goState)) { TC_LOG_ERROR("bg.battleground", "Battleground::AddObject: cannot create gameobject (entry: %u) for BG (map: %u, instance id: %u)!", entry, m_MapId, m_InstanceID); diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h index 2ef7eca4aa1..4d2f5da1a24 100644 --- a/src/server/game/Battlegrounds/Battleground.h +++ b/src/server/game/Battlegrounds/Battleground.h @@ -438,6 +438,10 @@ class TC_GAME_API Battleground // Death related virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); + virtual WorldSafeLocsEntry const* GetExploitTeleportLocation(Team /*team*/) { return nullptr; } + // GetExploitTeleportLocation(TeamId) must be implemented in the battleground subclass. + void TeleportPlayerToExploitLocation(Player* player); + virtual void AddPlayer(Player* player); // must be implemented in BG subclass void AddOrSetPlayerToCorrectBgGroup(Player* player, uint32 team); diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp index 911fe259fc3..60e0a5f8db8 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp @@ -231,11 +231,13 @@ void BattlegroundAB::RemovePlayer(Player* /*player*/, ObjectGuid /*guid*/, uint3 void BattlegroundAB::HandleAreaTrigger(Player* player, uint32 trigger, bool entered) { - if (GetStatus() != STATUS_IN_PROGRESS) - return; - switch (trigger) { + case 6635: // Horde Start + case 6634: // Alliance Start + if (GetStatus() == STATUS_WAIT_JOIN && !entered) + TeleportPlayerToExploitLocation(player); + break; case 3948: // Arathi Basin Alliance Exit. if (player->GetTeam() != ALLIANCE) player->GetSession()->SendNotification("Only The Alliance can use that portal"); @@ -690,6 +692,11 @@ WorldSafeLocsEntry const* BattlegroundAB::GetClosestGraveYard(Player* player) return good_entry; } +WorldSafeLocsEntry const* BattlegroundAB::GetExploitTeleportLocation(Team team) +{ + return sWorldSafeLocsStore.LookupEntry(team == ALLIANCE ? AB_EXPLOIT_TELEPORT_LOCATION_ALLIANCE : AB_EXPLOIT_TELEPORT_LOCATION_HORDE); +} + bool BattlegroundAB::UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor) { if (!Battleground::UpdatePlayerScore(player, type, value, doAddHonor)) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.h b/src/server/game/Battlegrounds/Zones/BattlegroundAB.h index e4bdf2f16d6..c452ca6fa2f 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.h @@ -179,6 +179,12 @@ enum BG_AB_Objectives AB_OBJECTIVE_DEFEND_BASE = 123 }; +enum BG_AB_ExploitTeleportLocations +{ + AB_EXPLOIT_TELEPORT_LOCATION_ALLIANCE = 3705, + AB_EXPLOIT_TELEPORT_LOCATION_HORDE = 3706 +}; + #define BG_AB_NotABBGWeekendHonorTicks 260 #define BG_AB_ABBGWeekendHonorTicks 160 #define BG_AB_NotABBGWeekendReputationTicks 160 @@ -288,6 +294,7 @@ class BattlegroundAB : public Battleground void Reset() override; void EndBattleground(uint32 winner) override; WorldSafeLocsEntry const* GetClosestGraveYard(Player* player) override; + WorldSafeLocsEntry const* GetExploitTeleportLocation(Team team) override; /* Scorekeeping */ bool UpdatePlayerScore(Player* player, uint32 type, uint32 value, bool doAddHonor = true) override; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp index 59d01df8237..031228013ef 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp @@ -493,11 +493,13 @@ void BattlegroundAV::RemovePlayer(Player* player, ObjectGuid /*guid*/, uint32 /* void BattlegroundAV::HandleAreaTrigger(Player* player, uint32 trigger, bool entered) { - if (GetStatus() != STATUS_IN_PROGRESS) - return; - switch (trigger) { + case 6633: // Horde Start + case 6632: // Alliance Start + if (GetStatus() == STATUS_WAIT_JOIN && entered) + TeleportPlayerToExploitLocation(player); + break; case 95: case 2608: if (player->GetTeam() != ALLIANCE) @@ -1124,6 +1126,11 @@ WorldSafeLocsEntry const* BattlegroundAV::GetClosestGraveYard(Player* player) return pGraveyard; } +WorldSafeLocsEntry const* BattlegroundAV::GetExploitTeleportLocation(Team team) +{ + return sWorldSafeLocsStore.LookupEntry(team == ALLIANCE ? AV_EXPLOIT_TELEPORT_LOCATION_ALLIANCE: AV_EXPLOIT_TELEPORT_LOCATION_HORDE); +} + bool BattlegroundAV::SetupBattleground() { // Create starting objects diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h index 8bf97822426..eae03d83bc1 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h @@ -1536,6 +1536,12 @@ enum Texts TEXT_SNIVVLE_RANDOM = 0 }; +enum BG_AV_ExploitTeleportLocations +{ + AV_EXPLOIT_TELEPORT_LOCATION_ALLIANCE = 3664, + AV_EXPLOIT_TELEPORT_LOCATION_HORDE = 3665 +}; + struct BG_AV_NodeInfo { BG_AV_States State; @@ -1633,6 +1639,7 @@ class BattlegroundAV : public Battleground void EndBattleground(uint32 winner) override; WorldSafeLocsEntry const* GetClosestGraveYard(Player* player) override; + WorldSafeLocsEntry const* GetExploitTeleportLocation(Team team) override; // Achievement: Av perfection and Everything counts bool CheckAchievementCriteriaMeet(uint32 criteriaId, Player const* source, Unit const* target = nullptr, uint32 miscvalue1 = 0) override; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp index 461420fe962..8bcba2ca204 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp @@ -406,14 +406,16 @@ void BattlegroundEY::RemovePlayer(Player* player, ObjectGuid guid, uint32 /*team void BattlegroundEY::HandleAreaTrigger(Player* player, uint32 trigger, bool entered) { - if (GetStatus() != STATUS_IN_PROGRESS) - return; - if (!player->IsAlive()) //hack code, must be removed later return; switch (trigger) { + case 4530: // Horde Start + case 4531: // Alliance Start + if (GetStatus() == STATUS_WAIT_JOIN && !entered) + TeleportPlayerToExploitLocation(player); + break; case TR_BLOOD_ELF_POINT: if (m_PointState[BLOOD_ELF] == EY_POINT_UNDER_CONTROL && m_PointOwnedByTeam[BLOOD_ELF] == player->GetTeam()) if (m_FlagState && GetFlagPickerGUID() == player->GetGUID()) @@ -438,8 +440,6 @@ void BattlegroundEY::HandleAreaTrigger(Player* player, uint32 trigger, bool ente case 4515: case 4517: case 4519: - case 4530: - case 4531: case 4568: case 4569: case 4570: @@ -950,6 +950,11 @@ WorldSafeLocsEntry const* BattlegroundEY::GetClosestGraveYard(Player* player) return nearestEntry; } +WorldSafeLocsEntry const* BattlegroundEY::GetExploitTeleportLocation(Team team) +{ + return sWorldSafeLocsStore.LookupEntry(team == ALLIANCE ? EY_EXPLOIT_TELEPORT_LOCATION_ALLIANCE : EY_EXPLOIT_TELEPORT_LOCATION_HORDE); +} + bool BattlegroundEY::IsAllNodesControlledByTeam(uint32 team) const { uint32 count = 0; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.h b/src/server/game/Battlegrounds/Zones/BattlegroundEY.h index e25601f51b9..a1e63e356b8 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.h @@ -248,6 +248,12 @@ enum BG_EY_Objectives EY_OBJECTIVE_CAPTURE_FLAG = 183 }; +enum BG_EY_ExploitTeleportLocations +{ + EY_EXPLOIT_TELEPORT_LOCATION_ALLIANCE = 3773, + EY_EXPLOIT_TELEPORT_LOCATION_HORDE = 3772 +}; + struct BattlegroundEYPointIconsStruct { BattlegroundEYPointIconsStruct(uint32 _WorldStateControlIndex, uint32 _WorldStateAllianceControlledIndex, uint32 _WorldStateHordeControlledIndex) @@ -376,6 +382,7 @@ class BattlegroundEY : public Battleground void HandleAreaTrigger(Player* source, uint32 trigger, bool entered) override; void HandleKillPlayer(Player* player, Player* killer) override; WorldSafeLocsEntry const* GetClosestGraveYard(Player* player) override; + WorldSafeLocsEntry const* GetExploitTeleportLocation(Team team) override; bool SetupBattleground() override; void Reset() override; void UpdateTeamScore(uint32 Team); diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp index d31fd47819f..085da3d6b5a 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp @@ -263,11 +263,12 @@ void BattlegroundIC::RemovePlayer(Player* player, ObjectGuid /*guid*/, uint32 /* } } -void BattlegroundIC::HandleAreaTrigger(Player* player, uint32 trigger, bool /*entered*/) +void BattlegroundIC::HandleAreaTrigger(Player* player, uint32 trigger, bool entered) { // this is wrong way to implement these things. On official it done by gameobject spell cast. - if (GetStatus() != STATUS_IN_PROGRESS) - return; + if (GetStatus() == STATUS_WAIT_JOIN && !entered) + if (trigger == 9176 || trigger == 9178) + TeleportPlayerToExploitLocation(player); /// @hack: this spell should be cast by npc 22515 (World Trigger) and not by the player if (trigger == 5555 && player->GetTeamId() == TEAM_HORDE) @@ -884,6 +885,11 @@ WorldSafeLocsEntry const* BattlegroundIC::GetClosestGraveYard(Player* player) return good_entry; } +WorldSafeLocsEntry const * BattlegroundIC::GetExploitTeleportLocation(Team team) +{ + return sWorldSafeLocsStore.LookupEntry(team == ALLIANCE ? IC_EXPLOIT_TELEPORT_LOCATION_ALLIANCE : IC_EXPLOIT_TELEPORT_LOCATION_HORDE); +} + bool BattlegroundIC::IsAllNodesControlledByTeam(uint32 team) const { uint32 count = 0; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.h b/src/server/game/Battlegrounds/Zones/BattlegroundIC.h index f60d9324e48..d65b69e62f4 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.h @@ -468,6 +468,12 @@ enum BG_IC_MaxSpawns MAX_CAPTAIN_SPAWNS_PER_FACTION = 2, }; +enum BG_IC_ExploitTeleportLocations +{ + IC_EXPLOIT_TELEPORT_LOCATION_ALLIANCE = 3986, + IC_EXPLOIT_TELEPORT_LOCATION_HORDE = 3983 +}; + const ICNpc BG_IC_NpcSpawnlocs[MAX_NORMAL_NPCS_SPAWNS] = { {BG_IC_NPC_OVERLORD_AGMAR, NPC_OVERLORD_AGMAR, TEAM_HORDE, 1295.44f, -765.733f, 70.0541f, 0.0f}, //Overlord Agmar 1 @@ -940,6 +946,7 @@ class BattlegroundIC : public Battleground void DestroyGate(Player* player, GameObject* go) override; WorldSafeLocsEntry const* GetClosestGraveYard(Player* player) override; + WorldSafeLocsEntry const* GetExploitTeleportLocation(Team team) override; /* Scorekeeping */ void FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) override; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp index 0df4fd6f88e..37b39043e42 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp @@ -650,13 +650,15 @@ void BattlegroundWS::UpdateTeamScore(uint32 team) void BattlegroundWS::HandleAreaTrigger(Player* player, uint32 trigger, bool entered) { - if (GetStatus() != STATUS_IN_PROGRESS) - return; - //uint32 SpellId = 0; //uint64 buff_guid = 0; switch (trigger) { + case 8965: // Horde Start + case 8966: // Alliance Start + if (GetStatus() == STATUS_WAIT_JOIN && !entered) + TeleportPlayerToExploitLocation(player); + break; case 3686: // Alliance elixir of speed spawn. Trigger not working, because located inside other areatrigger, can be replaced by IsWithinDist(object, dist) in Battleground::Update(). //buff_guid = BgObjects[BG_WS_OBJECT_SPEEDBUFF_1]; break; @@ -851,6 +853,11 @@ WorldSafeLocsEntry const* BattlegroundWS::GetClosestGraveYard(Player* player) } } +WorldSafeLocsEntry const* BattlegroundWS::GetExploitTeleportLocation(Team team) +{ + return sWorldSafeLocsStore.LookupEntry(team == ALLIANCE ? WS_EXPLOIT_TELEPORT_LOCATION_ALLIANCE : WS_EXPLOIT_TELEPORT_LOCATION_HORDE); +} + void BattlegroundWS::FillInitialWorldStates(WorldPackets::WorldState::InitWorldStates& packet) { packet.Worldstates.emplace_back(uint32(BG_WS_FLAG_CAPTURES_ALLIANCE), int32(GetTeamScore(TEAM_ALLIANCE))); diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.h b/src/server/game/Battlegrounds/Zones/BattlegroundWS.h index 3561d6f2fc3..8731255cd32 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.h @@ -125,6 +125,12 @@ enum BG_WS_Graveyards WS_GRAVEYARD_MAIN_HORDE = 772 }; +enum BG_WS_ExploitTeleportLocations +{ + WS_EXPLOIT_TELEPORT_LOCATION_ALLIANCE = 3784, + WS_EXPLOIT_TELEPORT_LOCATION_HORDE = 3785 +}; + enum BG_WS_CreatureTypes { WS_SPIRIT_MAIN_ALLIANCE = 0, @@ -222,6 +228,7 @@ class BattlegroundWS : public Battleground void Reset() override; void EndBattleground(uint32 winner) override; WorldSafeLocsEntry const* GetClosestGraveYard(Player* player) override; + WorldSafeLocsEntry const* GetExploitTeleportLocation(Team team) override; void UpdateFlagState(uint32 team, uint32 value); void SetLastFlagCapture(uint32 team) { _lastFlagCaptureTeam = team; } diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index a052d4d44d4..dcc18fdf64a 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -446,7 +446,7 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo) const if (Unit* unit = object->ToUnit()) { if (ConditionValue1 == 0) - condMeets = (unit->GetStandState() == ConditionValue2); + condMeets = (unit->GetStandState() == UnitStandStateType(ConditionValue2)); else if (ConditionValue2 == 0) condMeets = unit->IsStandState(); else if (ConditionValue2 == 1) @@ -2368,7 +2368,7 @@ inline bool PlayerConditionLogic(uint32 logic, std::array<bool, N>& results) return result; } -bool ConditionMgr::IsPlayerMeetingCondition(Player* player, PlayerConditionEntry const* condition) +bool ConditionMgr::IsPlayerMeetingCondition(Player const* player, PlayerConditionEntry const* condition) { if (condition->MinLevel && player->getLevel() < condition->MinLevel) return false; @@ -2489,7 +2489,7 @@ bool ConditionMgr::IsPlayerMeetingCondition(Player* player, PlayerConditionEntry if (condition->PartyStatus) { - Group* group = player->GetGroup(); + Group const* group = player->GetGroup(); switch (condition->PartyStatus) { case 1: diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h index 7c61b4d2955..fb754ab5349 100644 --- a/src/server/game/Conditions/ConditionMgr.h +++ b/src/server/game/Conditions/ConditionMgr.h @@ -271,7 +271,7 @@ class TC_GAME_API ConditionMgr bool IsObjectMeetingSmartEventConditions(int64 entryOrGuid, uint32 eventId, uint32 sourceType, Unit* unit, WorldObject* baseObject) const; bool IsObjectMeetingVendorItemConditions(uint32 creatureId, uint32 itemId, Player* player, Creature* vendor) const; - static bool IsPlayerMeetingCondition(Player* player, PlayerConditionEntry const* condition); + static bool IsPlayerMeetingCondition(Player const* player, PlayerConditionEntry const* condition); struct ConditionTypeInfo { diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index c13c4f775ca..6ea2dfef591 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -176,7 +176,7 @@ void GameObject::RemoveFromWorld() } } -bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, uint32 /*phaseMask*/, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, GOState go_state, uint32 artKit) +bool GameObject::Create(uint32 name_id, Map* map, uint32 /*phaseMask*/, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, GOState go_state, uint32 artKit) { ASSERT(map); SetMap(map); @@ -185,14 +185,14 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, u m_stationaryPosition.Relocate(x, y, z, ang); if (!IsPositionValid()) { - TC_LOG_ERROR("misc", "Gameobject (GUID: " UI64FMTD " Spawn id: " UI64FMTD " Entry: %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)", guidlow, GetSpawnId(), name_id, x, y); + TC_LOG_ERROR("misc", "Gameobject (Spawn id: " UI64FMTD " Entry: %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)", GetSpawnId(), name_id, x, y); return false; } SetZoneScript(); if (m_zoneScript) { - name_id = m_zoneScript->GetGameObjectEntry(guidlow, name_id); + name_id = m_zoneScript->GetGameObjectEntry(m_spawnId, name_id); if (!name_id) return false; } @@ -200,26 +200,32 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, u GameObjectTemplate const* goinfo = sObjectMgr->GetGameObjectTemplate(name_id); if (!goinfo) { - TC_LOG_ERROR("sql.sql", "Gameobject (GUID: " UI64FMTD " Spawn id: " UI64FMTD " Entry: %u) not created: non-existing entry in `gameobject_template`. Map: %u (X: %f Y: %f Z: %f)", guidlow, GetSpawnId(), name_id, map->GetId(), x, y, z); + TC_LOG_ERROR("sql.sql", "Gameobject (Spawn id: " UI64FMTD " Entry: %u) not created: non-existing entry in `gameobject_template`. Map: %u (X: %f Y: %f Z: %f)", GetSpawnId(), name_id, map->GetId(), x, y, z); return false; } if (goinfo->type == GAMEOBJECT_TYPE_MAP_OBJ_TRANSPORT) { - TC_LOG_ERROR("sql.sql", "Gameobject (GUID: " UI64FMTD " Spawn id: " UI64FMTD " Entry: %u) not created: gameobject type GAMEOBJECT_TYPE_MAP_OBJ_TRANSPORT cannot be manually created.", guidlow, GetSpawnId(), name_id); + TC_LOG_ERROR("sql.sql", "Gameobject (Spawn id: " UI64FMTD " Entry: %u) not created: gameobject type GAMEOBJECT_TYPE_MAP_OBJ_TRANSPORT cannot be manually created.", GetSpawnId(), name_id); return false; } - if (goinfo->type == GAMEOBJECT_TYPE_TRANSPORT) + ObjectGuid guid; + if (goinfo->type != GAMEOBJECT_TYPE_TRANSPORT) + guid = ObjectGuid::Create<HighGuid::GameObject>(map->GetId(), goinfo->entry, map->GenerateLowGuid<HighGuid::GameObject>()); + else + { + guid = ObjectGuid::Create<HighGuid::Transport>(map->GenerateLowGuid<HighGuid::Transport>()); m_updateFlag |= UPDATEFLAG_TRANSPORT; + } - Object::_Create(ObjectGuid::Create<HighGuid::GameObject>(map->GetId(), goinfo->entry, guidlow)); + Object::_Create(guid); m_goInfo = goinfo; if (goinfo->type >= MAX_GAMEOBJECT_TYPE) { - TC_LOG_ERROR("sql.sql", "Gameobject (GUID: " UI64FMTD " Spawn id: " UI64FMTD " Entry: %u) not created: non-existing GO type '%u' in `gameobject_template`. It will crash client if created.", guidlow, GetSpawnId(), name_id, goinfo->type); + TC_LOG_ERROR("sql.sql", "Gameobject (%s Spawn id: " UI64FMTD " Entry: %u) not created: non-existing GO type '%u' in `gameobject_template`. It will crash client if created.", guid.ToString().c_str(), GetSpawnId(), name_id, goinfo->type); return false; } @@ -888,7 +894,7 @@ bool GameObject::LoadGameObjectFromDB(ObjectGuid::LowType spawnId, Map* map, boo uint32 artKit = data->artKit; m_spawnId = spawnId; - if (!Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, phaseMask, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state, artKit)) + if (!Create(entry, map, phaseMask, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state, artKit)) return false; if (data->phaseid) @@ -1250,7 +1256,7 @@ void GameObject::Use(Unit* user) if (sScriptMgr->OnGossipHello(playerUser, this)) return; - if (AI()->GossipHello(playerUser)) + if (AI()->GossipHello(playerUser, true)) return; } diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index a83b04e2a58..40e00531497 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -933,7 +933,7 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject> void RemoveFromWorld() override; void CleanupsBeforeDelete(bool finalCleanup = true) override; - bool Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, uint32 phaseMask, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, GOState go_state, uint32 artKit = 0); + bool Create(uint32 name_id, Map* map, uint32 phaseMask, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, GOState go_state, uint32 artKit = 0); void Update(uint32 p_time) override; GameObjectTemplate const* GetGOInfo() const { return m_goInfo; } GameObjectData const* GetGOData() const { return m_goData; } diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 47751548922..0522ef13095 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -2406,7 +2406,7 @@ GameObject* WorldObject::SummonGameObject(uint32 entry, float x, float y, float Map* map = GetMap(); GameObject* go = new GameObject(); - if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, GetPhaseMask(), x, y, z, ang, rotation0, rotation1, rotation2, rotation3, 100, GO_STATE_READY)) + if (!go->Create(entry, map, GetPhaseMask(), x, y, z, ang, rotation0, rotation1, rotation2, rotation3, 100, GO_STATE_READY)) { delete go; return NULL; diff --git a/src/server/game/Entities/Object/ObjectGuid.h b/src/server/game/Entities/Object/ObjectGuid.h index 000028ef852..aa7b4a4a23e 100644 --- a/src/server/game/Entities/Object/ObjectGuid.h +++ b/src/server/game/Entities/Object/ObjectGuid.h @@ -160,7 +160,6 @@ GUID_TRAIT_GLOBAL(HighGuid::CommerceObj) GUID_TRAIT_GLOBAL(HighGuid::ClientSession) GUID_TRAIT_REALM_SPECIFIC(HighGuid::Player) GUID_TRAIT_REALM_SPECIFIC(HighGuid::Item) // This is not exactly correct, there are 2 more unknown parts in highguid: (high >> 10 & 0xFF), (high >> 18 & 0xFFFFFF) -GUID_TRAIT_REALM_SPECIFIC(HighGuid::Transport) GUID_TRAIT_REALM_SPECIFIC(HighGuid::Guild) GUID_TRAIT_MAP_SPECIFIC(HighGuid::WorldTransaction) GUID_TRAIT_MAP_SPECIFIC(HighGuid::Conversation) @@ -183,6 +182,19 @@ GUID_TRAIT_MAP_SPECIFIC(HighGuid::AILock) GUID_TRAIT_MAP_SPECIFIC(HighGuid::AILockTicket) GUID_TRAIT_MAP_SPECIFIC(HighGuid::Cast) +// Special case +// Global transports are loaded from `transports` table, RealmSpecific part is used for them. +// after worldserver finishes loading, no more global transports can be created, only the ones existing within instances that never change maps +// here is where MapSpecific comes into play - each map takes over the responsibility to generate transport guids +// on top of this, regular elevators (GAMEOBJECT_TYPE_TRANSPORT) must also use Transport highguid type, otherwise client will reject seeing other players on them +template<> +struct ObjectGuidTraits<HighGuid::Transport> +{ + static bool const Global = false; + static bool const RealmSpecific = true; + static bool const MapSpecific = true; +}; + class ObjectGuid; class PackedGuid; @@ -207,7 +219,7 @@ class TC_GAME_API ObjectGuid static typename std::enable_if<ObjectGuidTraits<type>::RealmSpecific, ObjectGuid>::type Create(LowType counter) { return RealmSpecific(type, counter); } template<HighGuid type> - static typename std::enable_if<ObjectGuidTraits<type>::MapSpecific, ObjectGuid>::type Create(uint16 mapId, uint32 entry, LowType counter) { return MapSpecific(type, 0, mapId, 0, entry, counter); } + static typename std::enable_if<ObjectGuidTraits<type>::MapSpecific && type != HighGuid::Transport, ObjectGuid>::type Create(uint16 mapId, uint32 entry, LowType counter) { return MapSpecific(type, 0, mapId, 0, entry, counter); } template<HighGuid type> static typename std::enable_if<ObjectGuidTraits<type>::MapSpecific, ObjectGuid>::type Create(uint8 subType, uint16 mapId, uint32 entry, LowType counter) { return MapSpecific(type, subType, mapId, 0, entry, counter); } diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index fb7ba8f22b7..06036f5cbf7 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -37,9 +37,9 @@ #define PET_XP_FACTOR 0.05f Pet::Pet(Player* owner, PetType type) : - Guardian(NULL, owner, true), m_usedTalentCount(0), m_removed(false), + Guardian(NULL, owner, true), m_removed(false), m_petType(type), m_duration(0), m_loading(false), m_groupUpdateMask(0), - m_declinedname(NULL) + m_declinedname(NULL), m_petSpecialization(0) { ASSERT(GetOwner()); @@ -312,8 +312,6 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c owner->SetMinion(this, true); map->AddToMap(this->ToCreature()); - InitTalentForLevel(); // set original talents points before spell loading - uint32 timediff = uint32(time(NULL) - fields[13].GetUInt32()); _LoadAuras(timediff); @@ -323,23 +321,28 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c m_charmInfo->LoadPetActionBar(fields[12].GetString()); _LoadSpells(); - InitTalentForLevel(); // re-init to check talent count _LoadSpellCooldowns(); LearnPetPassives(); InitLevelupSpellsForLevel(); CastPetAuras(current); } - CleanupActionBar(); // remove unknown spells from action bar after load - TC_LOG_DEBUG("entities.pet", "New Pet has %s", GetGUID().ToString().c_str()); - owner->PetSpellInitialize(); + uint16 specId = fields[16].GetUInt16(); + if (ChrSpecializationEntry const* petSpec = sChrSpecializationStore.LookupEntry(specId)) + specId = sDB2Manager.GetChrSpecializationByIndex(owner->HasAuraType(SPELL_AURA_OVERRIDE_PET_SPECS) ? PET_SPEC_OVERRIDE_CLASS_INDEX : 0, petSpec->OrderIndex)->ID; - SetGroupUpdateFlag(GROUP_UPDATE_PET_FULL); + SetSpecialization(specId); - // TODO: 6.x remove/update pet talents - //owner->SendTalentsInfoData(true); + // The SetSpecialization function will run these functions if the pet's spec is not 0 + if (!GetSpecialization()) + { + CleanupActionBar(); // remove unknown spells from action bar after load + owner->PetSpellInitialize(); + } + + SetGroupUpdateFlag(GROUP_UPDATE_PET_FULL); if (getPetType() == HUNTER_PET) { @@ -415,8 +418,6 @@ void Pet::SavePetToDB(PetSaveMode mode) if (mode >= PET_SAVE_AS_CURRENT) { ObjectGuid::LowType ownerLowGUID = GetOwnerGUID().GetCounter(); - std::string name = m_name; - CharacterDatabase.EscapeString(name); trans = CharacterDatabase.BeginTransaction(); // remove current data @@ -445,34 +446,28 @@ void Pet::SavePetToDB(PetSaveMode mode) } // save pet - std::ostringstream ss; - ss << "INSERT INTO character_pet (id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, abdata, savetime, CreatedBySpell, PetType) " - << "VALUES (" - << m_charmInfo->GetPetNumber() << ',' - << GetEntry() << ',' - << ownerLowGUID << ',' - << GetNativeDisplayId() << ',' - << uint32(getLevel()) << ',' - << GetUInt32Value(UNIT_FIELD_PETEXPERIENCE) << ',' - << uint32(GetReactState()) << ',' - << uint32(mode) << ", '" - << name.c_str() << "', " - << uint32(HasByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED) ? 0 : 1) << ',' - << curhealth << ',' - << curmana << ", '"; - - for (uint32 i = ACTION_BAR_INDEX_START; i < ACTION_BAR_INDEX_END; ++i) - { - ss << uint32(m_charmInfo->GetActionBarEntry(i)->GetType()) << ' ' - << uint32(m_charmInfo->GetActionBarEntry(i)->GetAction()) << ' '; - }; - - ss << "', " - << time(NULL) << ',' - << GetUInt32Value(UNIT_CREATED_BY_SPELL) << ',' - << uint32(getPetType()) << ')'; + stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PET); + stmt->setUInt32(0, m_charmInfo->GetPetNumber()); + stmt->setUInt32(1, GetEntry()); + stmt->setUInt64(2, ownerLowGUID); + stmt->setUInt32(3, GetNativeDisplayId()); + stmt->setUInt8(4, getLevel()); + stmt->setUInt32(5, GetUInt32Value(UNIT_FIELD_PETEXPERIENCE)); + stmt->setUInt8(6, GetReactState()); + stmt->setInt16(7, mode); + stmt->setString(8, m_name); + stmt->setUInt8(9, HasByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED) ? 0 : 1); + stmt->setUInt32(10, curhealth); + stmt->setUInt32(11, curmana); + + stmt->setString(12, GenerateActionBarData()); + + stmt->setUInt32(13, time(NULL)); + stmt->setUInt32(14, GetUInt32Value(UNIT_CREATED_BY_SPELL)); + stmt->setUInt8(15, getPetType()); + stmt->setUInt16(16, m_petSpecialization); + trans->Append(stmt); - trans->Append(ss.str().c_str()); CharacterDatabase.CommitTransaction(trans); } // delete @@ -724,7 +719,6 @@ void Pet::GivePetLevel(uint8 level) InitStatsForLevel(level); InitLevelupSpellsForLevel(); - InitTalentForLevel(); } bool Pet::CreateBaseAtCreature(Creature* creature) @@ -1436,6 +1430,22 @@ bool Pet::learnSpell(uint32 spell_id) return true; } +void Pet::learnSpells(std::vector<uint32> const& spellIds) +{ + WorldPackets::Pet::PetLearnedSpells packet; + + for (uint32 spell : spellIds) + { + if (!addSpell(spell)) + continue; + + packet.Spells.push_back(spell); + } + + if (!m_loading) + GetOwner()->GetSession()->SendPacket(packet.Write()); +} + void Pet::InitLevelupSpellsForLevel() { uint8 level = getLevel(); @@ -1488,6 +1498,22 @@ bool Pet::unlearnSpell(uint32 spell_id, bool learn_prev, bool clear_ab) return false; } +void Pet::unlearnSpells(std::vector<uint32> const& spellIds, bool learn_prev, bool clear_ab) +{ + WorldPackets::Pet::PetUnlearnedSpells packet; + + for (uint32 spell : spellIds) + { + if (!removeSpell(spell, learn_prev, clear_ab)) + continue; + + packet.Spells.push_back(spell); + } + + if (!m_loading) + GetOwner()->GetSession()->SendPacket(packet.Write()); +} + bool Pet::removeSpell(uint32 spell_id, bool learn_prev, bool clear_ab) { PetSpellMap::iterator itr = m_spells.find(spell_id); @@ -1513,7 +1539,7 @@ bool Pet::removeSpell(uint32 spell_id, bool learn_prev, bool clear_ab) } // if remove last rank or non-ranked then update action bar at server and client if need - if (clear_ab && !learn_prev && m_charmInfo->RemoveSpellFromActionBar(spell_id)) + if (m_charmInfo->RemoveSpellFromActionBar(spell_id) && !learn_prev && clear_ab) { if (!m_loading) GetOwner()->PetSpellInitialize(); // need update action bar for last removed rank @@ -1549,182 +1575,6 @@ void Pet::InitPetCreateSpells() CastPetAuras(false); } -bool Pet::resetTalents() -{ - /* TODO: 6.x remove pet talents - Player* player = GetOwner(); - - // not need after this call - if (player->HasAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS)) - player->RemoveAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS, true); - - CreatureTemplate const* ci = GetCreatureTemplate(); - if (!ci) - return false; - // Check pet talent type - CreatureFamilyEntry const* pet_family = sCreatureFamilyStore.LookupEntry(ci->family); - if (!pet_family || pet_family->PetTalentType < 0) - return false; - - uint8 level = getLevel(); - uint32 talentPointsForLevel = GetMaxTalentPointsForLevel(level); - - if (m_usedTalentCount == 0) - { - SetFreeTalentPoints(talentPointsForLevel); - return false; - } - - for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i) - { - TalentEntry const* talentInfo = sTalentStore.LookupEntry(i); - - if (!talentInfo) - continue; - - TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab); - - if (!talentTabInfo) - continue; - - // unlearn only talents for pets family talent type - if (!((1 << pet_family->PetTalentType) & talentTabInfo->petTalentMask)) - continue; - - for (uint8 j = 0; j < MAX_TALENT_RANK; ++j) - { - for (PetSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end();) - { - if (itr->second.state == PETSPELL_REMOVED) - { - ++itr; - continue; - } - // remove learned spells (all ranks) - uint32 itrFirstId = sSpellMgr->GetFirstSpellInChain(itr->first); - - // unlearn if first rank is talent or learned by talent - if (itrFirstId == talentInfo->RankID[j] || sSpellMgr->IsSpellLearnToSpell(talentInfo->RankID[j], itrFirstId)) - { - unlearnSpell(itr->first, false); - itr = m_spells.begin(); - continue; - } - else - ++itr; - } - } - } - - SetFreeTalentPoints(talentPointsForLevel); - - if (!m_loading) - player->PetSpellInitialize();*/ - return true; -} - -void Pet::resetTalentsForAllPetsOf(Player* /*owner*/, Pet* /*onlinePet*/ /*= NULL*/) -{ - /* TODO: 6.x remove pet talents - // not need after this call - if (owner->HasAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS)) - owner->RemoveAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS, true); - - // reset for online - if (onlinePet) - onlinePet->resetTalents(); - - // now need only reset for offline pets (all pets except online case) - uint32 exceptPetNumber = onlinePet ? onlinePet->GetCharmInfo()->GetPetNumber() : 0; - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_PET); - stmt->setUInt64(0, owner->GetGUID().GetCounter()); - stmt->setUInt32(1, exceptPetNumber); - PreparedQueryResult resultPets = CharacterDatabase.Query(stmt); - - // no offline pets - if (!resultPets) - return; - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_SPELL_LIST); - stmt->setUInt64(0, owner->GetGUID().GetCounter()); - stmt->setUInt32(1, exceptPetNumber); - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (!result) - return; - - bool need_comma = false; - std::ostringstream ss; - ss << "DELETE FROM pet_spell WHERE guid IN ("; - - do - { - Field* fields = resultPets->Fetch(); - - uint32 id = fields[0].GetUInt32(); - - if (need_comma) - ss << ','; - - ss << id; - - need_comma = true; - } while (resultPets->NextRow()); - - ss << ") AND spell IN ("; - - bool need_execute = false; - do - { - Field* fields = result->Fetch(); - - uint32 spell = fields[0].GetUInt32(); - - if (!GetTalentSpellCost(spell)) - continue; - - if (need_execute) - ss << ','; - - ss << spell; - - need_execute = true; - } - while (result->NextRow()); - - if (!need_execute) - return; - - ss << ')'; - - CharacterDatabase.Execute(ss.str().c_str());*/ -} - -void Pet::InitTalentForLevel() -{ - /* TODO: 6.x remove/update pet talents - uint8 level = getLevel(); - uint32 talentPointsForLevel = GetMaxTalentPointsForLevel(level); - // Reset talents in case low level (on level down) or wrong points for level (hunter can unlearn TP increase talent) - if (talentPointsForLevel == 0 || m_usedTalentCount > talentPointsForLevel) - resetTalents(); // Remove all talent points - - SetFreeTalentPoints(talentPointsForLevel - m_usedTalentCount); - - if (!m_loading) - GetOwner()->SendTalentsInfoData(true); - */ -} - -uint8 Pet::GetMaxTalentPointsForLevel(uint8 level) const -{ - uint8 points = (level >= 20) ? ((level - 16) / 4) : 0; - // Mod points from owner SPELL_AURA_MOD_PET_TALENT_POINTS - points += GetOwner()->GetTotalAuraModifier(SPELL_AURA_MOD_PET_TALENT_POINTS); - return points; -} - void Pet::ToggleAutocast(SpellInfo const* spellInfo, bool apply) { ASSERT(spellInfo); @@ -1940,3 +1790,96 @@ void Pet::ResetGroupUpdateFlag() if (GetOwner()->GetGroup()) GetOwner()->RemoveGroupUpdateFlag(GROUP_UPDATE_FLAG_PET); } + +void Pet::LearnSpecializationSpells() +{ + std::vector<uint32> learnedSpells; + + if (std::vector<SpecializationSpellsEntry const*> const* specSpells = sDB2Manager.GetSpecializationSpells(m_petSpecialization)) + { + for (size_t j = 0; j < specSpells->size(); ++j) + { + SpecializationSpellsEntry const* specSpell = specSpells->at(j); + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(specSpell->SpellID); + if (!spellInfo || spellInfo->SpellLevel > getLevel()) + continue; + + learnedSpells.push_back(specSpell->SpellID); + } + } + + learnSpells(learnedSpells); +} + +void Pet::RemoveSpecializationSpells(bool clearActionBar) +{ + std::vector<uint32> unlearnedSpells; + + for (uint32 i = 0; i < MAX_SPECIALIZATIONS; ++i) + { + if (ChrSpecializationEntry const* specialization = sDB2Manager.GetChrSpecializationByIndex(0, i)) + { + if (std::vector<SpecializationSpellsEntry const*> const* specSpells = sDB2Manager.GetSpecializationSpells(specialization->ID)) + { + for (size_t j = 0; j < specSpells->size(); ++j) + { + SpecializationSpellsEntry const* specSpell = specSpells->at(j); + unlearnedSpells.push_back(specSpell->SpellID); + } + } + } + + if (ChrSpecializationEntry const* specialization = sDB2Manager.GetChrSpecializationByIndex(PET_SPEC_OVERRIDE_CLASS_INDEX, i)) + { + if (std::vector<SpecializationSpellsEntry const*> const* specSpells = sDB2Manager.GetSpecializationSpells(specialization->ID)) + { + for (size_t j = 0; j < specSpells->size(); ++j) + { + SpecializationSpellsEntry const* specSpell = specSpells->at(j); + unlearnedSpells.push_back(specSpell->SpellID); + } + } + } + } + + unlearnSpells(unlearnedSpells, true, clearActionBar); +} + +void Pet::SetSpecialization(uint16 spec) +{ + if (m_petSpecialization == spec) + return; + + // remove all the old spec's specalization spells, set the new spec, then add the new spec's spells + // clearActionBars is false because we'll be updating the pet actionbar later so we don't have to do it now + RemoveSpecializationSpells(false); + if (!sChrSpecializationStore.LookupEntry(spec)) + { + m_petSpecialization = 0; + return; + } + + m_petSpecialization = spec; + LearnSpecializationSpells(); + + // resend SMSG_PET_SPELLS_MESSAGE to remove old specialization spells from the pet action bar + CleanupActionBar(); + GetOwner()->PetSpellInitialize(); + + WorldPackets::Pet::SetPetSpecialization setPetSpecialization; + setPetSpecialization.SpecID = m_petSpecialization; + GetOwner()->GetSession()->SendPacket(setPetSpecialization.Write()); +} + +std::string Pet::GenerateActionBarData() const +{ + std::ostringstream ss; + + for (uint32 i = ACTION_BAR_INDEX_START; i < ACTION_BAR_INDEX_END; ++i) + { + ss << uint32(m_charmInfo->GetActionBarEntry(i)->GetType()) << ' ' + << uint32(m_charmInfo->GetActionBarEntry(i)->GetAction()) << ' '; + } + + return ss.str(); +} diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h index 170b881fa50..38d78ec181b 100644 --- a/src/server/game/Entities/Pet/Pet.h +++ b/src/server/game/Entities/Pet/Pet.h @@ -119,26 +119,24 @@ class TC_GAME_API Pet : public Guardian bool addSpell(uint32 spellId, ActiveStates active = ACT_DECIDE, PetSpellState state = PETSPELL_NEW, PetSpellType type = PETSPELL_NORMAL); bool learnSpell(uint32 spell_id); + void learnSpells(std::vector<uint32> const& spellIds); void learnSpellHighRank(uint32 spellid); void InitLevelupSpellsForLevel(); bool unlearnSpell(uint32 spell_id, bool learn_prev, bool clear_ab = true); + void unlearnSpells(std::vector<uint32> const& spellIds, bool learn_prev, bool clear_ab = true); bool removeSpell(uint32 spell_id, bool learn_prev, bool clear_ab = true); void CleanupActionBar(); + std::string GenerateActionBarData() const; PetSpellMap m_spells; AutoSpellList m_autospells; void InitPetCreateSpells(); - bool resetTalents(); - static void resetTalentsForAllPetsOf(Player* owner, Pet* online_pet = nullptr); - void InitTalentForLevel(); - - uint8 GetMaxTalentPointsForLevel(uint8 level) const; - uint8 GetFreeTalentPoints() const { return GetByteValue(UNIT_FIELD_BYTES_1, 1); } - void SetFreeTalentPoints(uint8 points) { SetByteValue(UNIT_FIELD_BYTES_1, 1, points); } - - uint32 m_usedTalentCount; + uint16 GetSpecialization() { return m_petSpecialization; } + void SetSpecialization(uint16 spec); + void LearnSpecializationSpells(); + void RemoveSpecializationSpells(bool clearActionBar); uint32 GetGroupUpdateFlag() const { return m_groupUpdateMask; } void SetGroupUpdateFlag(uint32 flag); @@ -159,6 +157,8 @@ class TC_GAME_API Pet : public Guardian DeclinedName *m_declinedname; + uint16 m_petSpecialization; + private: void SaveToDB(uint32, uint32, uint32) override // override of Creature::SaveToDB - must not be called { diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index e119c1d8199..c35e9bc99ca 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1220,7 +1220,7 @@ void Player::Update(uint32 p_time) m_zoneUpdateTimer -= p_time; } - if (m_timeSyncTimer > 0) + if (m_timeSyncTimer > 0 && !IsBeingTeleportedFar()) { if (p_time >= m_timeSyncTimer) SendTimeSync(); @@ -1635,18 +1635,10 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati if (!GetSession()->PlayerLogout()) { - if (mEntry->IsDungeon()) - { - WorldPackets::Instance::UpdateLastInstance updateLastInstance; - updateLastInstance.MapID = mapid; - SendDirectMessage(updateLastInstance.Write()); - } - - WorldPackets::Movement::NewWorld packet; - packet.MapID = mapid; - packet.Pos = static_cast<Position>(m_teleport_dest); - packet.Reason = !(options & TELE_TO_SEAMLESS) ? NEW_WORLD_NORMAL : NEW_WORLD_SEAMLESS; - SendDirectMessage(packet.Write()); + WorldPackets::Movement::SuspendToken suspendToken; + suspendToken.SequenceIndex = m_movementCounter; // not incrementing + suspendToken.Reason = options & TELE_TO_SEAMLESS ? 2 : 1; + SendDirectMessage(suspendToken.Write()); } // move packet sent by client always after far teleport @@ -20140,7 +20132,7 @@ void Player::PetSpellInitialize() WorldPackets::Pet::PetSpells petSpellsPacket; petSpellsPacket.PetGUID = pet->GetGUID(); petSpellsPacket._CreatureFamily = pet->GetCreatureTemplate()->family; // creature family (required for pet talents) - //petSpellsPacket.Specialization = pet->GetSpecialization(); NYI + petSpellsPacket.Specialization = pet->GetSpecialization(); petSpellsPacket.TimeLimit = pet->GetDuration(); petSpellsPacket.ReactState = pet->GetReactState(); petSpellsPacket.CommandState = charmInfo->GetCommandState(); @@ -21968,7 +21960,7 @@ void Player::UpdateTriggerVisibility() creature->BuildValuesUpdateBlockForPlayer(&udata, this); creature->RemoveFieldNotifyFlag(UF_FLAG_PUBLIC); } - else if (itr->IsGameObject()) + else if (itr->IsAnyTypeGameObject()) { GameObject* go = GetMap()->GetGameObject(*itr); if (!go) @@ -22186,6 +22178,14 @@ void Player::SetGroup(Group* group, int8 subgroup) void Player::SendInitialPacketsBeforeAddToMap() { + if (!(m_teleport_options & TELE_TO_SEAMLESS)) + { + m_movementCounter = 0; + ResetTimeSync(); + } + + SendTimeSync(); + /// Pass 'this' as argument because we're not stored in ObjectAccessor yet GetSocial()->SendSocialList(this, SOCIAL_FLAG_ALL); @@ -22275,9 +22275,6 @@ void Player::SendInitialPacketsAfterAddToMap() GetZoneAndAreaId(newzone, newarea); UpdateZone(newzone, newarea); // also call SendInitWorldStates(); - ResetTimeSync(); - SendTimeSync(); - GetSession()->SendLoadCUFProfiles(); CastSpell(this, 836, true); // LOGINEFFECT @@ -25581,14 +25578,6 @@ void Player::DeleteGarrison() } } -void Player::SendMovementSetCanTransitionBetweenSwimAndFly(bool apply) -{ - WorldPackets::Movement::MoveSetFlag packet(apply ? SMSG_MOVE_ENABLE_TRANSITION_BETWEEN_SWIM_AND_FLY : SMSG_MOVE_DISABLE_TRANSITION_BETWEEN_SWIM_AND_FLY); - packet.MoverGUID = GetGUID(); - packet.SequenceIndex = m_movementCounter++; - SendMessageToSet(packet.Write(), true); -} - void Player::SendMovementSetCollisionHeight(float height) { WorldPackets::Movement::MoveSetCollisionHeight setCollisionHeight; @@ -25746,7 +25735,6 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy { case SUMMON_PET: pet->InitPetCreateSpells(); - pet->InitTalentForLevel(); pet->SavePetToDB(PET_SAVE_AS_CURRENT); PetSpellInitialize(); break; diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index e46712d0580..4e4e116f65e 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2417,10 +2417,6 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void ValidateMovementInfo(MovementInfo* mi); - /*! These methods send different packets to the client in apply and unapply case. - These methods are only sent to the current unit. - */ - void SendMovementSetCanTransitionBetweenSwimAndFly(bool apply); void SendMovementSetCollisionHeight(float height); bool CanFly() const override { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY); } diff --git a/src/server/game/Entities/Taxi/TaxiPathGraph.cpp b/src/server/game/Entities/Taxi/TaxiPathGraph.cpp index 709a5debf4d..3ff288b0c50 100644 --- a/src/server/game/Entities/Taxi/TaxiPathGraph.cpp +++ b/src/server/game/Entities/Taxi/TaxiPathGraph.cpp @@ -184,8 +184,9 @@ uint32 TaxiPathGraph::EdgeCost::EvaluateDistance(Player const* player) const if (!(To->Flags & requireFlag)) return std::numeric_limits<uint16>::max(); - //if (To->ConditionID && !player->MeetsCondition(To->ConditionID)) - // return std::numeric_limits<uint16>::max(); + if (PlayerConditionEntry const* condition = sPlayerConditionStore.LookupEntry(To->ConditionID)) + if (!sConditionMgr->IsPlayerMeetingCondition(player, condition)) + return std::numeric_limits<uint16>::max(); return Distance; } diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index c3b8ef8e07e..035bc4d8703 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -301,7 +301,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged) float val2 = 0.0f; float level = float(getLevel()); - ChrClassesEntry const* entry = sChrClassesStore.LookupEntry(getClass()); + ChrClassesEntry const* entry = sChrClassesStore.AssertEntry(getClass()); UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER; uint16 index = UNIT_FIELD_ATTACK_POWER; diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index c473e4fb535..ab16b8275c9 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -9952,20 +9952,20 @@ void Unit::SetSpeedRate(UnitMoveType mtype, float rate) pet->SetSpeedRate(mtype, m_speed_rate[mtype]); } - if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->m_mover->GetTypeId() == TYPEID_PLAYER) + if (Player* playerMover = GetPlayerMover()) // unit controlled by a player. { // Send notification to self WorldPackets::Movement::MoveSetSpeed selfpacket(moveTypeToOpcode[mtype][1]); selfpacket.MoverGUID = GetGUID(); selfpacket.SequenceIndex = m_movementCounter++; selfpacket.Speed = GetSpeed(mtype); - ToPlayer()->GetSession()->SendPacket(selfpacket.Write()); + playerMover->GetSession()->SendPacket(selfpacket.Write()); // Send notification to other players WorldPackets::Movement::MoveUpdateSpeed packet(moveTypeToOpcode[mtype][2]); packet.movementInfo = &m_movementInfo; packet.Speed = GetSpeed(mtype); - SendMessageToSet(packet.Write(), false); + playerMover->SendMessageToSet(packet.Write(), false); } else { @@ -11535,6 +11535,20 @@ void CharmInfo::SetSpellAutocast(SpellInfo const* spellInfo, bool state) } } +Unit* Unit::GetMover() const +{ + if (Player const* player = ToPlayer()) + return player->m_mover; + return nullptr; +} + +Player* Unit::GetPlayerMover() const +{ + if (Unit* mover = GetMover()) + return mover->ToPlayer(); + return nullptr; +} + bool Unit::isFrozen() const { return HasAuraState(AURA_STATE_FROZEN); @@ -13417,12 +13431,16 @@ void Unit::SetRooted(bool apply, bool packetOnly /*= false*/) { SMSG_MOVE_SPLINE_ROOT, SMSG_MOVE_ROOT } }; - if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->m_mover->GetTypeId() == TYPEID_PLAYER) + if (Player* playerMover = GetPlayerMover()) // unit controlled by a player. { WorldPackets::Movement::MoveSetFlag packet(rootOpcodeTable[apply][1]); packet.MoverGUID = GetGUID(); packet.SequenceIndex = m_movementCounter++; - SendMessageToSet(packet.Write(), true); + playerMover->SendDirectMessage(packet.Write()); + + WorldPackets::Movement::MoveUpdate moveUpdate; + moveUpdate.movementInfo = &m_movementInfo; + SendMessageToSet(moveUpdate.Write(), playerMover); } else { @@ -14903,8 +14921,9 @@ void Unit::SendTeleportPacket(Position& pos) WorldPackets::Movement::MoveUpdateTeleport moveUpdateTeleport; moveUpdateTeleport.movementInfo = &m_movementInfo; + Unit* broadcastSource = this; - if (GetTypeId() == TYPEID_PLAYER) + if (Player* playerMover = GetPlayerMover()) { WorldPackets::Movement::MoveTeleport moveTeleport; moveTeleport.MoverGUID = GetGUID(); @@ -14914,7 +14933,9 @@ void Unit::SendTeleportPacket(Position& pos) moveTeleport.TransportGUID = GetTransGUID(); moveTeleport.Facing = pos.GetOrientation(); moveTeleport.SequenceIndex = m_movementCounter++; - ToPlayer()->SendDirectMessage(moveTeleport.Write()); + playerMover->SendDirectMessage(moveTeleport.Write()); + + broadcastSource = playerMover; } else { @@ -14926,7 +14947,7 @@ void Unit::SendTeleportPacket(Position& pos) } // Broadcast the packet to everyone except self. - SendMessageToSet(moveUpdateTeleport.Write(), false); + broadcastSource->SendMessageToSet(moveUpdateTeleport.Write(), false); } bool Unit::UpdatePosition(float x, float y, float z, float orientation, bool teleport) @@ -15307,14 +15328,16 @@ bool Unit::SetDisableGravity(bool disable, bool packetOnly /*= false*/) { SMSG_MOVE_SPLINE_DISABLE_GRAVITY, SMSG_MOVE_DISABLE_GRAVITY } }; - bool player = GetTypeId() == TYPEID_PLAYER && ToPlayer()->m_mover->GetTypeId() == TYPEID_PLAYER; - - if (player) + if (Player* playerMover = GetPlayerMover()) { WorldPackets::Movement::MoveSetFlag packet(gravityOpcodeTable[disable][1]); packet.MoverGUID = GetGUID(); packet.SequenceIndex = m_movementCounter++; - SendMessageToSet(packet.Write(), true); + playerMover->SendDirectMessage(packet.Write()); + + WorldPackets::Movement::MoveUpdate moveUpdate; + moveUpdate.movementInfo = &m_movementInfo; + SendMessageToSet(moveUpdate.Write(), playerMover); } else { @@ -15385,16 +15408,19 @@ bool Unit::SetCanFly(bool enable) { SMSG_MOVE_SPLINE_SET_FLYING, SMSG_MOVE_SET_CAN_FLY } }; - bool player = GetTypeId() == TYPEID_PLAYER && ToPlayer()->m_mover->GetTypeId() == TYPEID_PLAYER; - if (!enable && player) + if (!enable && GetTypeId() == TYPEID_PLAYER) ToPlayer()->SetFallInformation(0, GetPositionZ()); - if (player) + if (Player* playerMover = GetPlayerMover()) { WorldPackets::Movement::MoveSetFlag packet(flyOpcodeTable[enable][1]); packet.MoverGUID = GetGUID(); packet.SequenceIndex = m_movementCounter++; - SendMessageToSet(packet.Write(), true); + playerMover->SendDirectMessage(packet.Write()); + + WorldPackets::Movement::MoveUpdate moveUpdate; + moveUpdate.movementInfo = &m_movementInfo; + SendMessageToSet(moveUpdate.Write(), playerMover); } else { @@ -15425,14 +15451,16 @@ bool Unit::SetWaterWalking(bool enable, bool packetOnly /*= false */) { SMSG_MOVE_SPLINE_SET_WATER_WALK, SMSG_MOVE_SET_WATER_WALK } }; - bool player = GetTypeId() == TYPEID_PLAYER && ToPlayer()->m_mover->GetTypeId() == TYPEID_PLAYER; - - if (player) + if (Player* playerMover = GetPlayerMover()) { WorldPackets::Movement::MoveSetFlag packet(waterWalkingOpcodeTable[enable][1]); packet.MoverGUID = GetGUID(); packet.SequenceIndex = m_movementCounter++; - SendMessageToSet(packet.Write(), true); + playerMover->SendDirectMessage(packet.Write()); + + WorldPackets::Movement::MoveUpdate moveUpdate; + moveUpdate.movementInfo = &m_movementInfo; + SendMessageToSet(moveUpdate.Write(), playerMover); } else { @@ -15463,14 +15491,16 @@ bool Unit::SetFeatherFall(bool enable, bool packetOnly /*= false */) { SMSG_MOVE_SPLINE_SET_FEATHER_FALL, SMSG_MOVE_SET_FEATHER_FALL } }; - bool player = GetTypeId() == TYPEID_PLAYER && ToPlayer()->m_mover->GetTypeId() == TYPEID_PLAYER; - - if (player) + if (Player* playerMover = GetPlayerMover()) { WorldPackets::Movement::MoveSetFlag packet(featherFallOpcodeTable[enable][1]); packet.MoverGUID = GetGUID(); packet.SequenceIndex = m_movementCounter++; - SendMessageToSet(packet.Write(), true); + playerMover->SendDirectMessage(packet.Write()); + + WorldPackets::Movement::MoveUpdate moveUpdate; + moveUpdate.movementInfo = &m_movementInfo; + SendMessageToSet(moveUpdate.Write(), playerMover); } else { @@ -15516,14 +15546,16 @@ bool Unit::SetHover(bool enable, bool packetOnly /*= false*/) { SMSG_MOVE_SPLINE_SET_HOVER, SMSG_MOVE_SET_HOVERING } }; - bool player = GetTypeId() == TYPEID_PLAYER && ToPlayer()->m_mover->GetTypeId() == TYPEID_PLAYER; - - if (player) + if (Player* playerMover = GetPlayerMover()) { WorldPackets::Movement::MoveSetFlag packet(hoverOpcodeTable[enable][1]); packet.MoverGUID = GetGUID(); packet.SequenceIndex = m_movementCounter++; - SendMessageToSet(packet.Write(), true); + playerMover->SendDirectMessage(packet.Write()); + + WorldPackets::Movement::MoveUpdate moveUpdate; + moveUpdate.movementInfo = &m_movementInfo; + SendMessageToSet(moveUpdate.Write(), playerMover); } else { @@ -15551,14 +15583,16 @@ bool Unit::SetCollision(bool disable) { SMSG_MOVE_SPLINE_DISABLE_COLLISION, SMSG_MOVE_DISABLE_COLLISION } }; - bool player = GetTypeId() == TYPEID_PLAYER && ToPlayer()->m_mover->GetTypeId() == TYPEID_PLAYER; - - if (player) + if (Player* playerMover = GetPlayerMover()) { WorldPackets::Movement::MoveSetFlag packet(collisionOpcodeTable[disable][1]); packet.MoverGUID = GetGUID(); packet.SequenceIndex = m_movementCounter++; - SendMessageToSet(packet.Write(), true); + playerMover->SendDirectMessage(packet.Write()); + + WorldPackets::Movement::MoveUpdate moveUpdate; + moveUpdate.movementInfo = &m_movementInfo; + SendMessageToSet(moveUpdate.Write(), playerMover); } else { @@ -15570,6 +15604,40 @@ bool Unit::SetCollision(bool disable) return true; } +bool Unit::SetCanTransitionBetweenSwimAndFly(bool enable) +{ + if (GetTypeId() != TYPEID_PLAYER) + return false; + + if (enable == HasExtraUnitMovementFlag(MOVEMENTFLAG2_CAN_SWIM_TO_FLY_TRANS)) + return false; + + if (enable) + AddExtraUnitMovementFlag(MOVEMENTFLAG2_CAN_SWIM_TO_FLY_TRANS); + else + RemoveExtraUnitMovementFlag(MOVEMENTFLAG2_CAN_SWIM_TO_FLY_TRANS); + + static OpcodeServer const swimToFlyTransOpcodeTable[2] = + { + SMSG_MOVE_ENABLE_TRANSITION_BETWEEN_SWIM_AND_FLY, + SMSG_MOVE_DISABLE_TRANSITION_BETWEEN_SWIM_AND_FLY + }; + + if (Player* playerMover = GetPlayerMover()) + { + WorldPackets::Movement::MoveSetFlag packet(swimToFlyTransOpcodeTable[enable]); + packet.MoverGUID = GetGUID(); + packet.SequenceIndex = m_movementCounter++; + playerMover->SendDirectMessage(packet.Write()); + + WorldPackets::Movement::MoveUpdate moveUpdate; + moveUpdate.movementInfo = &m_movementInfo; + SendMessageToSet(moveUpdate.Write(), playerMover); + } + + return true; +} + void Unit::SendSetVehicleRecId(uint32 vehicleId) { if (Player* player = ToPlayer()) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 2032b8210d3..15792d4f543 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1686,6 +1686,7 @@ class TC_GAME_API Unit : public WorldObject bool SetFeatherFall(bool enable, bool packetOnly = false); bool SetHover(bool enable, bool packetOnly = false); bool SetCollision(bool disable); + bool SetCanTransitionBetweenSwimAndFly(bool enable); void SendSetVehicleRecId(uint32 vehicleId); void SetInFront(WorldObject const* target); @@ -1759,7 +1760,8 @@ class TC_GAME_API Unit : public WorldObject CharmInfo* InitCharmInfo(); void DeleteCharmInfo(); void UpdateCharmAI(); - //Player* GetMoverSource() const; + Unit* GetMover() const; + Player* GetPlayerMover() const; Player* m_movedPlayer; SharedVisionList const& GetSharedVisionList() { return m_sharedVision; } void AddPlayerToVision(Player* player); diff --git a/src/server/game/Garrison/Garrison.cpp b/src/server/game/Garrison/Garrison.cpp index 59315b7ffc7..233fc1fa311 100644 --- a/src/server/game/Garrison/Garrison.cpp +++ b/src/server/game/Garrison/Garrison.cpp @@ -715,8 +715,7 @@ GameObject* Garrison::Plot::CreateGameObject(Map* map, GarrisonFactionIndex fact Position const& pos = PacketInfo.PlotPos; GameObject* building = new GameObject(); - if (!building->Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, 0, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), - 0.0f, 0.0f, 0.0f, 0.0f, 255, GO_STATE_READY)) + if (!building->Create(entry, map, 0, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 255, GO_STATE_READY)) { delete building; return nullptr; @@ -728,7 +727,7 @@ GameObject* Garrison::Plot::CreateGameObject(Map* map, GarrisonFactionIndex fact { Position const& pos2 = finalizeInfo->FactionInfo[faction].Pos; GameObject* finalizer = new GameObject(); - if (finalizer->Create(map->GenerateLowGuid<HighGuid::GameObject>(), finalizeInfo->FactionInfo[faction].GameObjectId, map, 0, pos2.GetPositionX(), pos2.GetPositionY(), + if (finalizer->Create(finalizeInfo->FactionInfo[faction].GameObjectId, map, 0, pos2.GetPositionX(), pos2.GetPositionY(), pos2.GetPositionZ(), pos2.GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 255, GO_STATE_READY)) { // set some spell id to make the object delete itself after use diff --git a/src/server/game/Globals/ObjectAccessor.cpp b/src/server/game/Globals/ObjectAccessor.cpp index 7cb21321f04..553cf67cc3c 100644 --- a/src/server/game/Globals/ObjectAccessor.cpp +++ b/src/server/game/Globals/ObjectAccessor.cpp @@ -84,12 +84,12 @@ WorldObject* ObjectAccessor::GetWorldObject(WorldObject const& p, ObjectGuid con case HighGuid::Transport: case HighGuid::GameObject: return GetGameObject(p, guid); case HighGuid::Vehicle: - case HighGuid::Creature: return GetCreature(p, guid); + case HighGuid::Creature: return GetCreature(p, guid); case HighGuid::Pet: return GetPet(p, guid); case HighGuid::DynamicObject: return GetDynamicObject(p, guid); case HighGuid::AreaTrigger: return GetAreaTrigger(p, guid); case HighGuid::Corpse: return GetCorpse(p, guid); - default: return NULL; + default: return nullptr; } } @@ -132,7 +132,7 @@ Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const& p, ObjectGuid con break; } - return NULL; + return nullptr; } Corpse* ObjectAccessor::GetCorpse(WorldObject const& u, ObjectGuid const& guid) @@ -145,11 +145,16 @@ GameObject* ObjectAccessor::GetGameObject(WorldObject const& u, ObjectGuid const return u.GetMap()->GetGameObject(guid); } -Transport* ObjectAccessor::GetTransport(WorldObject const& u, ObjectGuid const& guid) +Transport* ObjectAccessor::GetTransportOnMap(WorldObject const& u, ObjectGuid const& guid) { return u.GetMap()->GetTransport(guid); } +Transport* ObjectAccessor::GetTransport(ObjectGuid const& guid) +{ + return HashMapHolder<Transport>::Find(guid); +} + DynamicObject* ObjectAccessor::GetDynamicObject(WorldObject const& u, ObjectGuid const& guid) { return u.GetMap()->GetDynamicObject(guid); diff --git a/src/server/game/Globals/ObjectAccessor.h b/src/server/game/Globals/ObjectAccessor.h index 83bbdf42239..4ac3b7a79d1 100644 --- a/src/server/game/Globals/ObjectAccessor.h +++ b/src/server/game/Globals/ObjectAccessor.h @@ -72,7 +72,8 @@ namespace ObjectAccessor TC_GAME_API Object* GetObjectByTypeMask(WorldObject const&, ObjectGuid const&, uint32 typemask); TC_GAME_API Corpse* GetCorpse(WorldObject const& u, ObjectGuid const& guid); TC_GAME_API GameObject* GetGameObject(WorldObject const& u, ObjectGuid const& guid); - TC_GAME_API Transport* GetTransport(WorldObject const& u, ObjectGuid const& guid); + TC_GAME_API Transport* GetTransportOnMap(WorldObject const& u, ObjectGuid const& guid); + TC_GAME_API Transport* GetTransport(ObjectGuid const& guid); TC_GAME_API DynamicObject* GetDynamicObject(WorldObject const& u, ObjectGuid const& guid); TC_GAME_API AreaTrigger* GetAreaTrigger(WorldObject const& u, ObjectGuid const& guid); TC_GAME_API Unit* GetUnit(WorldObject const&, ObjectGuid const& guid); diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 63431e7e4ad..b8c6072f60e 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -54,6 +54,7 @@ #include "World.h" #include "WorldPacket.h" #include "WorldSession.h" +#include "Metric.h" class LoginQueryHolder : public SQLQueryHolder { @@ -1079,7 +1080,17 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) // reset for all pets before pet loading if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS)) - Pet::resetTalentsForAllPetsOf(pCurrChar); + { + // Delete all of the player's pet spells + PreparedStatement* stmtSpells = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ALL_PET_SPELLS_BY_OWNER); + stmtSpells->setUInt64(0, pCurrChar->GetGUID().GetCounter()); + CharacterDatabase.Execute(stmtSpells); + + // Then reset all of the player's pet specualizations + PreparedStatement* stmtSpec = CharacterDatabase.GetPreparedStatement(CHAR_UPD_PET_SPECS_BY_OWNER); + stmtSpec->setUInt64(0, pCurrChar->GetGUID().GetCounter()); + CharacterDatabase.Execute(stmtSpec); + } // Load pet if any (if player not alive and in taxi flight or another then pet will remember as temporary unsummoned) pCurrChar->LoadPet(); @@ -1139,6 +1150,8 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) sScriptMgr->OnPlayerLogin(pCurrChar, firstLogin); + TC_METRIC_EVENT("player_events", "Login", pCurrChar->GetName()); + delete holder; } @@ -2166,8 +2179,8 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(PreparedQueryResult res uint32 title_alliance = it->first; uint32 title_horde = it->second; - CharTitlesEntry const* atitleInfo = sCharTitlesStore.LookupEntry(title_alliance); - CharTitlesEntry const* htitleInfo = sCharTitlesStore.LookupEntry(title_horde); + CharTitlesEntry const* atitleInfo = sCharTitlesStore.AssertEntry(title_alliance); + CharTitlesEntry const* htitleInfo = sCharTitlesStore.AssertEntry(title_horde); // new team if (newTeamId == TEAM_ALLIANCE) { diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 0d37806d170..afcced346df 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -485,7 +485,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPackets::Misc::AreaTrigger& pack return; } - if (!player->IsInAreaTriggerRadius(atEntry)) + if (packet.Entered && !player->IsInAreaTriggerRadius(atEntry)) { TC_LOG_DEBUG("network", "HandleAreaTriggerOpcode: Player '%s' (%s) too far, ignore Area Trigger ID: %u", player->GetName().c_str(), player->GetGUID().ToString().c_str(), packet.AreaTriggerID); @@ -535,8 +535,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPackets::Misc::AreaTrigger& pack } if (Battleground* bg = player->GetBattleground()) - if (bg->GetStatus() == STATUS_IN_PROGRESS) - bg->HandleAreaTrigger(player, packet.AreaTriggerID, packet.Entered); + bg->HandleAreaTrigger(player, packet.AreaTriggerID, packet.Entered); if (OutdoorPvP* pvp = player->GetOutdoorPvP()) if (pvp->HandleAreaTrigger(_player, packet.AreaTriggerID, packet.Entered)) diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 0349fad420a..9e11c044f3e 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -31,6 +31,7 @@ #include "InstanceSaveMgr.h" #include "ObjectMgr.h" #include "Vehicle.h" +#include "InstancePackets.h" #include "MovementPackets.h" #define MOVEMENT_PACKET_TIME_DELAY 0 @@ -95,6 +96,11 @@ void WorldSession::HandleMoveWorldportAckOpcode() GetPlayer()->ResetMap(); GetPlayer()->SetMap(newMap); + WorldPackets::Movement::ResumeToken resumeToken; + resumeToken.SequenceIndex = _player->m_movementCounter; + resumeToken.Reason = seamlessTeleport ? 2 : 1; + SendPacket(resumeToken.Write()); + if (!seamlessTeleport) GetPlayer()->SendInitialPacketsBeforeAddToMap(); @@ -214,6 +220,30 @@ void WorldSession::HandleMoveWorldportAckOpcode() GetPlayer()->ProcessDelayedOperations(); } +void WorldSession::HandleSuspendTokenResponse(WorldPackets::Movement::SuspendTokenResponse& /*suspendTokenResponse*/) +{ + if (!_player->IsBeingTeleportedFar()) + return; + + WorldLocation const& loc = GetPlayer()->GetTeleportDest(); + + if (sMapStore.AssertEntry(loc.GetMapId())->IsDungeon()) + { + WorldPackets::Instance::UpdateLastInstance updateLastInstance; + updateLastInstance.MapID = loc.GetMapId(); + SendPacket(updateLastInstance.Write()); + } + + WorldPackets::Movement::NewWorld packet; + packet.MapID = loc.GetMapId(); + packet.Pos.Relocate(loc); + packet.Reason = !_player->IsBeingTeleportedSeamlessly() ? NEW_WORLD_NORMAL : NEW_WORLD_SEAMLESS; + SendPacket(packet.Write()); + + if (_player->IsBeingTeleportedSeamlessly()) + HandleMoveWorldportAckOpcode(); +} + void WorldSession::HandleMoveTeleportAck(WorldPackets::Movement::MoveTeleportAck& packet) { TC_LOG_DEBUG("network", "CMSG_MOVE_TELEPORT_ACK: Guid: %s, Sequence: %u, Time: %u", packet.MoverGUID.ToString().c_str(), packet.AckIndex, packet.MoveTime); @@ -330,7 +360,7 @@ void WorldSession::HandleMovementOpcodes(WorldPackets::Movement::ClientPlayerMov { GameObject* go = mover->GetMap()->GetGameObject(movementInfo.transport.guid); if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT) - movementInfo.transport.guid.Clear(); + movementInfo.transport.Reset(); } } else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index faf13940eff..416ff57a6ab 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -515,10 +515,9 @@ void WorldSession::HandlePetSetAction(WorldPackets::Pet::PetSetAction& packet) void WorldSession::HandlePetRename(WorldPackets::Pet::PetRename& packet) { ObjectGuid petguid = packet.RenameData.PetGUID; - bool isdeclined = packet.RenameData.HasDeclinedNames; std::string name = packet.RenameData.NewName; - DeclinedName declinedname = packet.RenameData.DeclinedNames; + DeclinedName* declinedname = packet.RenameData.DeclinedNames.get_ptr(); Pet* pet = ObjectAccessor::GetPet(*_player, petguid); // check it! @@ -546,21 +545,21 @@ void WorldSession::HandlePetRename(WorldPackets::Pet::PetRename& packet) pet->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED); - if (isdeclined) + if (declinedname) { std::wstring wname; if (!Utf8toWStr(name, wname)) return; - if (!ObjectMgr::CheckDeclinedNames(wname, declinedname)) + if (!ObjectMgr::CheckDeclinedNames(wname, *declinedname)) { - SendPetNameInvalid(PET_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME, name, &declinedname); + SendPetNameInvalid(PET_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME, name, declinedname); return; } } SQLTransaction trans = CharacterDatabase.BeginTransaction(); - if (isdeclined) + if (declinedname) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_PET_DECLINEDNAME); stmt->setUInt32(0, pet->GetCharmInfo()->GetPetNumber()); @@ -571,7 +570,7 @@ void WorldSession::HandlePetRename(WorldPackets::Pet::PetRename& packet) stmt->setUInt64(1, _player->GetGUID().GetCounter()); for (uint8 i = 0; i < 5; i++) - stmt->setString(i + 2, declinedname.name[i]); + stmt->setString(i + 2, declinedname->name[i]); trans->Append(stmt); } @@ -721,8 +720,8 @@ void WorldSession::SendPetNameInvalid(uint32 error, const std::string& name, Dec WorldPackets::Pet::PetNameInvalid petNameInvalid; petNameInvalid.Result = error; petNameInvalid.RenameData.NewName = name; - for (int i = 0; i < MAX_DECLINED_NAME_CASES; i++) - petNameInvalid.RenameData.DeclinedNames.name[i] = declinedName[i].name[i]; + if (declinedName) + petNameInvalid.RenameData.DeclinedNames = *declinedName; SendPacket(petNameInvalid.Write()); } diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index 323dec31e5a..8ce4a88ef5a 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -234,7 +234,7 @@ void WorldSession::HandleGameobjectReportUse(WorldPackets::GameObject::GameObjRe if (GameObject* go = GetPlayer()->GetGameObjectIfCanInteractWith(packet.Guid)) { - if (go->AI()->GossipHello(_player)) + if (go->AI()->GossipHello(_player, false)) return; _player->UpdateCriteria(CRITERIA_TYPE_USE_GAMEOBJECT, go->GetEntry()); diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 37321344782..0b0868eddf4 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -255,6 +255,8 @@ i_scriptLock(false), _defaultLight(DB2Manager::GetDefaultMapLight(id)) //lets initialize visibility distance for map Map::InitVisibilityDistance(); + GetGuidSequenceGenerator<HighGuid::Transport>().Set(sObjectMgr->GetGenerator<HighGuid::Transport>().GetNextAfterMaxUsed()); + sScriptMgr->OnCreateMap(this); } diff --git a/src/server/game/Maps/MapScripts.cpp b/src/server/game/Maps/MapScripts.cpp index fd1f798d2d0..c60b4d8096d 100644 --- a/src/server/game/Maps/MapScripts.cpp +++ b/src/server/game/Maps/MapScripts.cpp @@ -322,14 +322,12 @@ void Map::ScriptsProcess() source = HashMapHolder<Player>::Find(step.sourceGUID); break; case HighGuid::GameObject: + case HighGuid::Transport: source = GetGameObject(step.sourceGUID); break; case HighGuid::Corpse: source = GetCorpse(step.sourceGUID); break; - case HighGuid::Transport: - source = GetTransport(step.sourceGUID); - break; default: TC_LOG_ERROR("scripts", "%s source with unsupported high guid %s.", step.script->GetDebugInfo().c_str(), step.sourceGUID.ToString().c_str()); @@ -353,14 +351,12 @@ void Map::ScriptsProcess() target = HashMapHolder<Player>::Find(step.targetGUID); break; case HighGuid::GameObject: + case HighGuid::Transport: target = GetGameObject(step.targetGUID); break; case HighGuid::Corpse: target = GetCorpse(step.targetGUID); break; - case HighGuid::Transport: - target = GetTransport(step.targetGUID); - break; default: TC_LOG_ERROR("scripts", "%s target with unsupported high guid %s.", step.script->GetDebugInfo().c_str(), step.targetGUID.ToString().c_str()); diff --git a/src/server/game/Maps/TransportMgr.cpp b/src/server/game/Maps/TransportMgr.cpp index 5de0133c342..4e695547c42 100644 --- a/src/server/game/Maps/TransportMgr.cpp +++ b/src/server/game/Maps/TransportMgr.cpp @@ -389,7 +389,7 @@ Transport* TransportMgr::CreateTransport(uint32 entry, ObjectGuid::LowType guid float o = tInfo->keyFrames.begin()->InitialOrientation; // initialize the gameobject base - ObjectGuid::LowType guidLow = guid ? guid : sObjectMgr->GetGenerator<HighGuid::Transport>().Generate(); + ObjectGuid::LowType guidLow = guid ? guid : ASSERT_NOTNULL(map)->GenerateLowGuid<HighGuid::Transport>(); if (!trans->Create(guidLow, entry, mapId, x, y, z, o, 255)) { delete trans; diff --git a/src/server/game/Maps/ZoneScript.h b/src/server/game/Maps/ZoneScript.h index e54c96dbb11..e83c6654912 100644 --- a/src/server/game/Maps/ZoneScript.h +++ b/src/server/game/Maps/ZoneScript.h @@ -30,7 +30,7 @@ class ZoneScript virtual ~ZoneScript() { } virtual uint32 GetCreatureEntry(ObjectGuid::LowType /*guidLow*/, CreatureData const* data) { return data->id; } - virtual uint32 GetGameObjectEntry(ObjectGuid::LowType /*guidLow*/, uint32 entry) { return entry; } + virtual uint32 GetGameObjectEntry(ObjectGuid::LowType /*spawnId*/, uint32 entry) { return entry; } virtual void OnCreatureCreate(Creature* ) { } virtual void OnCreatureRemove(Creature* ) { } diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index a4051c7e865..6f1f4cb2409 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -1069,7 +1069,7 @@ enum TrinityStrings LANG_COMMAND_NO_FROZEN_PLAYERS = 5004, LANG_COMMAND_LIST_FREEZE = 5005, LANG_COMMAND_PERMA_FROZEN_PLAYER = 5006, - // = 5007, unused + LANG_PHASE_NOTFOUND = 5007, LANG_INSTANCE_CLOSED = 5008, LANG_COMMAND_PLAYED_TO_ALL = 5009, LANG_NPCINFO_LINKGUID = 5010, diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index a1114c0e28c..7320119f739 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -717,138 +717,138 @@ enum SpellAttr9 enum SpellAttr10 { - SPELL_ATTR10_UNK0 = 0x00000001, // 0 - SPELL_ATTR10_UNK1 = 0x00000002, // 1 - SPELL_ATTR10_UNK2 = 0x00000004, // 2 - SPELL_ATTR10_UNK3 = 0x00000008, // 3 - SPELL_ATTR10_WATER_SPOUT = 0x00000010, // 4 - SPELL_ATTR10_UNK5 = 0x00000020, // 5 - SPELL_ATTR10_UNK6 = 0x00000040, // 6 - SPELL_ATTR10_TELEPORT_PLAYER = 0x00000080, // 7 4 Teleport Player spells - SPELL_ATTR10_UNK8 = 0x00000100, // 8 - SPELL_ATTR10_UNK9 = 0x00000200, // 9 - SPELL_ATTR10_UNK10 = 0x00000400, // 10 - SPELL_ATTR10_HERB_GATHERING_MINING = 0x00000800, // 11 Only Herb Gathering and Mining - SPELL_ATTR10_USE_SPELL_BASE_LEVEL_FOR_SCALING = 0x00001000, // 12 - SPELL_ATTR10_UNK13 = 0x00002000, // 13 - SPELL_ATTR10_UNK14 = 0x00004000, // 14 - SPELL_ATTR10_UNK15 = 0x00008000, // 15 - SPELL_ATTR10_UNK16 = 0x00010000, // 16 - SPELL_ATTR10_UNK17 = 0x00020000, // 17 - SPELL_ATTR10_UNK18 = 0x00040000, // 18 - SPELL_ATTR10_UNK19 = 0x00080000, // 19 - SPELL_ATTR10_UNK20 = 0x00100000, // 20 - SPELL_ATTR10_UNK21 = 0x00200000, // 21 - SPELL_ATTR10_UNK22 = 0x00400000, // 22 - SPELL_ATTR10_UNK23 = 0x00800000, // 23 - SPELL_ATTR10_UNK24 = 0x01000000, // 24 - SPELL_ATTR10_UNK25 = 0x02000000, // 25 - SPELL_ATTR10_UNK26 = 0x04000000, // 26 - SPELL_ATTR10_UNK27 = 0x08000000, // 27 - SPELL_ATTR10_UNK28 = 0x10000000, // 28 - SPELL_ATTR10_MOUNT_IS_NOT_ACCOUNT_WIDE = 0x20000000, // 29 This mount is stored per-character - SPELL_ATTR10_UNK30 = 0x40000000, // 30 - SPELL_ATTR10_UNK31 = 0x80000000 // 31 + SPELL_ATTR10_UNK0 = 0x00000001, // 0 + SPELL_ATTR10_UNK1 = 0x00000002, // 1 + SPELL_ATTR10_UNK2 = 0x00000004, // 2 + SPELL_ATTR10_UNK3 = 0x00000008, // 3 + SPELL_ATTR10_WATER_SPOUT = 0x00000010, // 4 + SPELL_ATTR10_UNK5 = 0x00000020, // 5 + SPELL_ATTR10_UNK6 = 0x00000040, // 6 + SPELL_ATTR10_TELEPORT_PLAYER = 0x00000080, // 7 4 Teleport Player spells + SPELL_ATTR10_UNK8 = 0x00000100, // 8 + SPELL_ATTR10_UNK9 = 0x00000200, // 9 + SPELL_ATTR10_UNK10 = 0x00000400, // 10 + SPELL_ATTR10_HERB_GATHERING_MINING = 0x00000800, // 11 Only Herb Gathering and Mining + SPELL_ATTR10_USE_SPELL_BASE_LEVEL_FOR_SCALING= 0x00001000, // 12 + SPELL_ATTR10_UNK13 = 0x00002000, // 13 + SPELL_ATTR10_UNK14 = 0x00004000, // 14 + SPELL_ATTR10_UNK15 = 0x00008000, // 15 + SPELL_ATTR10_UNK16 = 0x00010000, // 16 + SPELL_ATTR10_UNK17 = 0x00020000, // 17 + SPELL_ATTR10_UNK18 = 0x00040000, // 18 + SPELL_ATTR10_UNK19 = 0x00080000, // 19 + SPELL_ATTR10_UNK20 = 0x00100000, // 20 + SPELL_ATTR10_UNK21 = 0x00200000, // 21 + SPELL_ATTR10_UNK22 = 0x00400000, // 22 + SPELL_ATTR10_UNK23 = 0x00800000, // 23 + SPELL_ATTR10_UNK24 = 0x01000000, // 24 + SPELL_ATTR10_UNK25 = 0x02000000, // 25 + SPELL_ATTR10_UNK26 = 0x04000000, // 26 + SPELL_ATTR10_UNK27 = 0x08000000, // 27 + SPELL_ATTR10_UNK28 = 0x10000000, // 28 + SPELL_ATTR10_MOUNT_IS_NOT_ACCOUNT_WIDE = 0x20000000, // 29 This mount is stored per-character + SPELL_ATTR10_UNK30 = 0x40000000, // 30 + SPELL_ATTR10_UNK31 = 0x80000000 // 31 }; enum SpellAttr11 { - SPELL_ATTR11_UNK0 = 0x00000001, // 0 - SPELL_ATTR11_UNK1 = 0x00000002, // 1 - SPELL_ATTR11_SCALES_WITH_ITEM_LEVEL = 0x00000004, // 2 - SPELL_ATTR11_UNK3 = 0x00000008, // 3 - SPELL_ATTR11_UNK4 = 0x00000010, // 4 - SPELL_ATTR11_UNK5 = 0x00000020, // 5 - SPELL_ATTR11_UNK6 = 0x00000040, // 6 - SPELL_ATTR11_RANK_IGNORES_CASTER_LEVEL = 0x00000080, // 7 Spell_C_GetSpellRank returns SpellLevels->MaxLevel * 5 instead of std::min(SpellLevels->MaxLevel, caster->Level) * 5 - SPELL_ATTR11_UNK8 = 0x00000100, // 8 - SPELL_ATTR11_UNK9 = 0x00000200, // 9 - SPELL_ATTR11_UNK10 = 0x00000400, // 10 - SPELL_ATTR11_UNK11 = 0x00000800, // 11 - SPELL_ATTR11_UNK12 = 0x00001000, // 12 - SPELL_ATTR11_UNK13 = 0x00002000, // 13 - SPELL_ATTR11_UNK14 = 0x00004000, // 14 - SPELL_ATTR11_UNK15 = 0x00008000, // 15 - SPELL_ATTR11_NOT_USABLE_IN_CHALLENGE_MODE = 0x00010000, // 16 - SPELL_ATTR11_UNK17 = 0x00020000, // 17 - SPELL_ATTR11_UNK18 = 0x00040000, // 18 - SPELL_ATTR11_UNK19 = 0x00080000, // 19 - SPELL_ATTR11_UNK20 = 0x00100000, // 20 - SPELL_ATTR11_UNK21 = 0x00200000, // 21 - SPELL_ATTR11_UNK22 = 0x00400000, // 22 - SPELL_ATTR11_UNK23 = 0x00800000, // 23 - SPELL_ATTR11_UNK24 = 0x01000000, // 24 - SPELL_ATTR11_UNK25 = 0x02000000, // 25 - SPELL_ATTR11_UNK26 = 0x04000000, // 26 - SPELL_ATTR11_UNK27 = 0x08000000, // 27 - SPELL_ATTR11_UNK28 = 0x10000000, // 28 - SPELL_ATTR11_UNK29 = 0x20000000, // 29 - SPELL_ATTR11_UNK30 = 0x40000000, // 30 - SPELL_ATTR11_UNK31 = 0x80000000 // 31 + SPELL_ATTR11_UNK0 = 0x00000001, // 0 + SPELL_ATTR11_UNK1 = 0x00000002, // 1 + SPELL_ATTR11_SCALES_WITH_ITEM_LEVEL = 0x00000004, // 2 + SPELL_ATTR11_UNK3 = 0x00000008, // 3 + SPELL_ATTR11_UNK4 = 0x00000010, // 4 + SPELL_ATTR11_UNK5 = 0x00000020, // 5 + SPELL_ATTR11_UNK6 = 0x00000040, // 6 + SPELL_ATTR11_RANK_IGNORES_CASTER_LEVEL = 0x00000080, // 7 Spell_C_GetSpellRank returns SpellLevels->MaxLevel * 5 instead of std::min(SpellLevels->MaxLevel, caster->Level) * 5 + SPELL_ATTR11_UNK8 = 0x00000100, // 8 + SPELL_ATTR11_UNK9 = 0x00000200, // 9 + SPELL_ATTR11_UNK10 = 0x00000400, // 10 + SPELL_ATTR11_UNK11 = 0x00000800, // 11 + SPELL_ATTR11_UNK12 = 0x00001000, // 12 + SPELL_ATTR11_UNK13 = 0x00002000, // 13 + SPELL_ATTR11_UNK14 = 0x00004000, // 14 + SPELL_ATTR11_UNK15 = 0x00008000, // 15 + SPELL_ATTR11_NOT_USABLE_IN_CHALLENGE_MODE = 0x00010000, // 16 + SPELL_ATTR11_UNK17 = 0x00020000, // 17 + SPELL_ATTR11_UNK18 = 0x00040000, // 18 + SPELL_ATTR11_UNK19 = 0x00080000, // 19 + SPELL_ATTR11_UNK20 = 0x00100000, // 20 + SPELL_ATTR11_UNK21 = 0x00200000, // 21 + SPELL_ATTR11_UNK22 = 0x00400000, // 22 + SPELL_ATTR11_UNK23 = 0x00800000, // 23 + SPELL_ATTR11_UNK24 = 0x01000000, // 24 + SPELL_ATTR11_UNK25 = 0x02000000, // 25 + SPELL_ATTR11_UNK26 = 0x04000000, // 26 + SPELL_ATTR11_UNK27 = 0x08000000, // 27 + SPELL_ATTR11_UNK28 = 0x10000000, // 28 + SPELL_ATTR11_UNK29 = 0x20000000, // 29 + SPELL_ATTR11_UNK30 = 0x40000000, // 30 + SPELL_ATTR11_UNK31 = 0x80000000 // 31 }; enum SpellAttr12 { - SPELL_ATTR12_UNK0 = 0x00000001, // 0 - SPELL_ATTR12_UNK1 = 0x00000002, // 1 - SPELL_ATTR12_UNK2 = 0x00000004, // 2 - SPELL_ATTR12_UNK3 = 0x00000008, // 3 - SPELL_ATTR12_UNK4 = 0x00000010, // 4 - SPELL_ATTR12_UNK5 = 0x00000020, // 5 - SPELL_ATTR12_UNK6 = 0x00000040, // 6 - SPELL_ATTR12_UNK7 = 0x00000080, // 7 - SPELL_ATTR12_UNK8 = 0x00000100, // 8 - SPELL_ATTR12_UNK9 = 0x00000200, // 9 - SPELL_ATTR12_UNK10 = 0x00000400, // 10 - SPELL_ATTR12_UNK11 = 0x00000800, // 11 - SPELL_ATTR12_UNK12 = 0x00001000, // 12 - SPELL_ATTR12_UNK13 = 0x00002000, // 13 - SPELL_ATTR12_UNK14 = 0x00004000, // 14 - SPELL_ATTR12_UNK15 = 0x00008000, // 15 - SPELL_ATTR12_UNK16 = 0x00010000, // 16 - SPELL_ATTR12_UNK17 = 0x00020000, // 17 - SPELL_ATTR12_UNK18 = 0x00040000, // 18 - SPELL_ATTR12_UNK19 = 0x00080000, // 19 - SPELL_ATTR12_UNK20 = 0x00100000, // 20 - SPELL_ATTR12_UNK21 = 0x00200000, // 21 - SPELL_ATTR12_UNK22 = 0x00400000, // 22 - SPELL_ATTR12_UNK23 = 0x00800000, // 23 - SPELL_ATTR12_UNK24 = 0x01000000, // 24 - SPELL_ATTR12_UNK25 = 0x02000000, // 25 - SPELL_ATTR12_UNK26 = 0x04000000, // 26 - SPELL_ATTR12_IS_READINESS_SPELL = 0x08000000, // 27 - SPELL_ATTR12_UNK28 = 0x10000000, // 28 - SPELL_ATTR12_UNK29 = 0x20000000, // 29 - SPELL_ATTR12_UNK30 = 0x40000000, // 30 - SPELL_ATTR12_UNK31 = 0x80000000 // 31 + SPELL_ATTR12_UNK0 = 0x00000001, // 0 + SPELL_ATTR12_UNK1 = 0x00000002, // 1 + SPELL_ATTR12_UNK2 = 0x00000004, // 2 + SPELL_ATTR12_UNK3 = 0x00000008, // 3 + SPELL_ATTR12_UNK4 = 0x00000010, // 4 + SPELL_ATTR12_UNK5 = 0x00000020, // 5 + SPELL_ATTR12_UNK6 = 0x00000040, // 6 + SPELL_ATTR12_UNK7 = 0x00000080, // 7 + SPELL_ATTR12_UNK8 = 0x00000100, // 8 + SPELL_ATTR12_UNK9 = 0x00000200, // 9 + SPELL_ATTR12_UNK10 = 0x00000400, // 10 + SPELL_ATTR12_UNK11 = 0x00000800, // 11 + SPELL_ATTR12_UNK12 = 0x00001000, // 12 + SPELL_ATTR12_UNK13 = 0x00002000, // 13 + SPELL_ATTR12_UNK14 = 0x00004000, // 14 + SPELL_ATTR12_UNK15 = 0x00008000, // 15 + SPELL_ATTR12_UNK16 = 0x00010000, // 16 + SPELL_ATTR12_UNK17 = 0x00020000, // 17 + SPELL_ATTR12_UNK18 = 0x00040000, // 18 + SPELL_ATTR12_UNK19 = 0x00080000, // 19 + SPELL_ATTR12_UNK20 = 0x00100000, // 20 + SPELL_ATTR12_UNK21 = 0x00200000, // 21 + SPELL_ATTR12_UNK22 = 0x00400000, // 22 + SPELL_ATTR12_UNK23 = 0x00800000, // 23 + SPELL_ATTR12_IS_GARRISON_BUFF = 0x01000000, // 24 + SPELL_ATTR12_UNK25 = 0x02000000, // 25 + SPELL_ATTR12_UNK26 = 0x04000000, // 26 + SPELL_ATTR12_IS_READINESS_SPELL = 0x08000000, // 27 + SPELL_ATTR12_UNK28 = 0x10000000, // 28 + SPELL_ATTR12_UNK29 = 0x20000000, // 29 + SPELL_ATTR12_UNK30 = 0x40000000, // 30 + SPELL_ATTR12_UNK31 = 0x80000000 // 31 }; enum SpellAttr13 { - SPELL_ATTR13_UNK0 = 0x00000001, // 0 - SPELL_ATTR13_UNK1 = 0x00000002, // 1 - SPELL_ATTR13_UNK2 = 0x00000004, // 2 - SPELL_ATTR13_UNK3 = 0x00000008, // 3 - SPELL_ATTR13_UNK4 = 0x00000010, // 4 - SPELL_ATTR13_UNK5 = 0x00000020, // 5 - SPELL_ATTR13_UNK6 = 0x00000040, // 6 - SPELL_ATTR13_UNK7 = 0x00000080, // 7 - SPELL_ATTR13_UNK8 = 0x00000100, // 8 - SPELL_ATTR13_UNK9 = 0x00000200, // 9 - SPELL_ATTR13_UNK10 = 0x00000400, // 10 - SPELL_ATTR13_UNK11 = 0x00000800, // 11 - SPELL_ATTR13_UNK12 = 0x00001000, // 12 - SPELL_ATTR13_UNK13 = 0x00002000, // 13 - SPELL_ATTR13_UNK14 = 0x00004000, // 14 - SPELL_ATTR13_UNK15 = 0x00008000, // 15 - SPELL_ATTR13_UNK16 = 0x00010000, // 16 - SPELL_ATTR13_UNK17 = 0x00020000, // 17 - SPELL_ATTR13_ACTIVATES_REQUIRED_SHAPESHIFT = 0x00040000, // 18 - SPELL_ATTR13_UNK19 = 0x00080000, // 19 - SPELL_ATTR13_UNK20 = 0x00100000, // 20 - SPELL_ATTR13_UNK21 = 0x00200000, // 21 - SPELL_ATTR13_UNK22 = 0x00400000, // 22 - SPELL_ATTR13_UNK23 = 0x00800000 // 23 + SPELL_ATTR13_UNK0 = 0x00000001, // 0 + SPELL_ATTR13_UNK1 = 0x00000002, // 1 + SPELL_ATTR13_UNK2 = 0x00000004, // 2 + SPELL_ATTR13_UNK3 = 0x00000008, // 3 + SPELL_ATTR13_UNK4 = 0x00000010, // 4 + SPELL_ATTR13_UNK5 = 0x00000020, // 5 + SPELL_ATTR13_UNK6 = 0x00000040, // 6 + SPELL_ATTR13_UNK7 = 0x00000080, // 7 + SPELL_ATTR13_UNK8 = 0x00000100, // 8 + SPELL_ATTR13_UNK9 = 0x00000200, // 9 + SPELL_ATTR13_UNK10 = 0x00000400, // 10 + SPELL_ATTR13_UNK11 = 0x00000800, // 11 + SPELL_ATTR13_UNK12 = 0x00001000, // 12 + SPELL_ATTR13_UNK13 = 0x00002000, // 13 + SPELL_ATTR13_UNK14 = 0x00004000, // 14 + SPELL_ATTR13_UNK15 = 0x00008000, // 15 + SPELL_ATTR13_UNK16 = 0x00010000, // 16 + SPELL_ATTR13_UNK17 = 0x00020000, // 17 + SPELL_ATTR13_ACTIVATES_REQUIRED_SHAPESHIFT = 0x00040000, // 18 + SPELL_ATTR13_UNK19 = 0x00080000, // 19 + SPELL_ATTR13_UNK20 = 0x00100000, // 20 + SPELL_ATTR13_UNK21 = 0x00200000, // 21 + SPELL_ATTR13_UNK22 = 0x00400000, // 22 + SPELL_ATTR13_UNK23 = 0x00800000 // 23 }; #define MIN_TALENT_GROUP 0 @@ -1229,7 +1229,7 @@ enum SpellEffectName SPELL_EFFECT_203 = 203, SPELL_EFFECT_CHANGE_BATTLEPET_QUALITY = 204, SPELL_EFFECT_LAUNCH_QUEST_CHOICE = 205, - SPELL_EFFECT_206 = 206, + SPELL_EFFECT_ALTER_ITEM = 206, // NYI SPELL_EFFECT_LAUNCH_QUEST_TASK = 207, // Starts one of the "progress bar" quests SPELL_EFFECT_208 = 208, SPELL_EFFECT_209 = 209, @@ -2322,18 +2322,18 @@ enum GameobjectTypes : uint8 // (6.0.3.19103) enum GameObjectFlags { - GO_FLAG_IN_USE = 0x00000001, // disables interaction while animated - GO_FLAG_LOCKED = 0x00000002, // require key, spell, event, etc to be opened. Makes "Locked" appear in tooltip - GO_FLAG_INTERACT_COND = 0x00000004, // cannot interact (condition to interact - requires GO_DYNFLAG_LO_ACTIVATE to enable interaction clientside) - GO_FLAG_TRANSPORT = 0x00000008, // any kind of transport? Object can transport (elevator, boat, car) - GO_FLAG_NOT_SELECTABLE = 0x00000010, // not selectable even in GM mode - GO_FLAG_NODESPAWN = 0x00000020, // never despawn, typically for doors, they just change state - GO_FLAG_AI_OBSTACLE = 0x00000040, - GO_FLAG_FREEZE_ANIMATION = 0x00000080, - GO_FLAG_DAMAGED = 0x00000200, - GO_FLAG_DESTROYED = 0x00000400, + GO_FLAG_IN_USE = 0x00000001, // disables interaction while animated + GO_FLAG_LOCKED = 0x00000002, // require key, spell, event, etc to be opened. Makes "Locked" appear in tooltip + GO_FLAG_INTERACT_COND = 0x00000004, // cannot interact (condition to interact - requires GO_DYNFLAG_LO_ACTIVATE to enable interaction clientside) + GO_FLAG_TRANSPORT = 0x00000008, // any kind of transport? Object can transport (elevator, boat, car) + GO_FLAG_NOT_SELECTABLE = 0x00000010, // not selectable even in GM mode + GO_FLAG_NODESPAWN = 0x00000020, // never despawn, typically for doors, they just change state + GO_FLAG_AI_OBSTACLE = 0x00000040, // makes the client register the object in something called AIObstacleMgr, unknown what it does + GO_FLAG_FREEZE_ANIMATION = 0x00000080, + GO_FLAG_DAMAGED = 0x00000200, + GO_FLAG_DESTROYED = 0x00000400, GO_FLAG_INTERACT_DISTANCE_USES_TEMPLATE_MODEL = 0x00080000, // client checks interaction distance from model sent in SMSG_QUERY_GAMEOBJECT_RESPONSE instead of GAMEOBJECT_DISPLAYID - GO_FLAG_MAP_OBJECT = 0x00100000 // pre-7.0 model loading used to be controlled by file extension (wmo vs m2) + GO_FLAG_MAP_OBJECT = 0x00100000 // pre-7.0 model loading used to be controlled by file extension (wmo vs m2) }; enum GameObjectDynamicLowFlags diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index fe09aa26af2..39087269e54 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -26,6 +26,7 @@ #include "DisableMgr.h" #include "DetourCommon.h" #include "DetourNavMeshQuery.h" +#include "Metric.h" ////////////////// PathGenerator ////////////////// PathGenerator::PathGenerator(const Unit* owner) : @@ -62,6 +63,8 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo if (!Trinity::IsValidMapCoord(destX, destY, destZ) || !Trinity::IsValidMapCoord(x, y, z)) return false; + TC_METRIC_EVENT("mmap_events", "CalculatePath", ""); + G3D::Vector3 dest(destX, destY, destZ); SetEndPosition(dest); diff --git a/src/server/game/Server/Packets/BattlenetPackets.h b/src/server/game/Server/Packets/BattlenetPackets.h index f059b39b75f..76aa499799c 100644 --- a/src/server/game/Server/Packets/BattlenetPackets.h +++ b/src/server/game/Server/Packets/BattlenetPackets.h @@ -76,8 +76,8 @@ namespace WorldPackets WorldPacket const* Write() override; - uint32 Token; - bool Allow; + uint32 Token = 0; + bool Allow = false; ByteBuffer Ticket; }; diff --git a/src/server/game/Server/Packets/BlackMarketPackets.h b/src/server/game/Server/Packets/BlackMarketPackets.h index 1193a9f0147..19853a212a5 100644 --- a/src/server/game/Server/Packets/BlackMarketPackets.h +++ b/src/server/game/Server/Packets/BlackMarketPackets.h @@ -122,7 +122,7 @@ namespace WorldPackets int32 MarketID = 0; Item::ItemInstance Item; - int32 RandomPropertiesID; + int32 RandomPropertiesID = 0; }; class BlackMarketWon final : public ServerPacket @@ -134,7 +134,7 @@ namespace WorldPackets int32 MarketID = 0; Item::ItemInstance Item; - int32 RandomPropertiesID; + int32 RandomPropertiesID = 0; }; } } diff --git a/src/server/game/Server/Packets/GuildFinderPackets.cpp b/src/server/game/Server/Packets/GuildFinderPackets.cpp index 137b5f29986..eb2f1178925 100644 --- a/src/server/game/Server/Packets/GuildFinderPackets.cpp +++ b/src/server/game/Server/Packets/GuildFinderPackets.cpp @@ -92,8 +92,8 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::GuildFinder::LFGuildAppli WorldPacket const* WorldPackets::GuildFinder::LFGuildApplications::Write() { - _worldPacket << uint32(Application.size()); _worldPacket << int32(NumRemaining); + _worldPacket << uint32(Application.size()); for (LFGuildApplicationData const& application : Application) _worldPacket << application; diff --git a/src/server/game/Server/Packets/MovementPackets.cpp b/src/server/game/Server/Packets/MovementPackets.cpp index 16b3b98646f..ff8337c88c4 100644 --- a/src/server/game/Server/Packets/MovementPackets.cpp +++ b/src/server/game/Server/Packets/MovementPackets.cpp @@ -736,3 +736,26 @@ WorldPacket const* WorldPackets::Movement::SummonRequest::Write() return &_worldPacket; } + +WorldPacket const* WorldPackets::Movement::SuspendToken::Write() +{ + _worldPacket << uint32(SequenceIndex); + _worldPacket.WriteBits(Reason, 2); + _worldPacket.FlushBits(); + + return &_worldPacket; +} + +void WorldPackets::Movement::SuspendTokenResponse::Read() +{ + _worldPacket >> SequenceIndex; +} + +WorldPacket const* WorldPackets::Movement::ResumeToken::Write() +{ + _worldPacket << uint32(SequenceIndex); + _worldPacket.WriteBits(Reason, 2); + _worldPacket.FlushBits(); + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/MovementPackets.h b/src/server/game/Server/Packets/MovementPackets.h index 7b56074db28..1c21c034c86 100644 --- a/src/server/game/Server/Packets/MovementPackets.h +++ b/src/server/game/Server/Packets/MovementPackets.h @@ -504,6 +504,38 @@ namespace WorldPackets SummonReason Reason = SPELL; bool SkipStartingArea = false; }; + + class SuspendToken final : public ServerPacket + { + public: + SuspendToken() : ServerPacket(SMSG_SUSPEND_TOKEN, 4 + 1) { } + + WorldPacket const* Write() override; + + uint32 SequenceIndex = 1; + uint32 Reason = 1; + }; + + class SuspendTokenResponse final : public ClientPacket + { + public: + SuspendTokenResponse(WorldPacket&& packet) : ClientPacket(CMSG_SUSPEND_TOKEN_RESPONSE, std::move(packet)) { } + + void Read() override; + + uint32 SequenceIndex = 0; + }; + + class ResumeToken final : public ServerPacket + { + public: + ResumeToken() : ServerPacket(SMSG_RESUME_TOKEN, 4 + 1) { } + + WorldPacket const* Write() override; + + uint32 SequenceIndex = 1; + uint32 Reason = 1; + }; } ByteBuffer& operator<<(ByteBuffer& data, Movement::MonsterSplineFilterKey const& monsterSplineFilterKey); diff --git a/src/server/game/Server/Packets/PetPackets.cpp b/src/server/game/Server/Packets/PetPackets.cpp index b07a74dfb10..cb5593167f0 100644 --- a/src/server/game/Server/Packets/PetPackets.cpp +++ b/src/server/game/Server/Packets/PetPackets.cpp @@ -99,19 +99,19 @@ WorldPacket const* WorldPackets::Pet::PetNameInvalid::Write() _worldPacket << uint8(RenameData.NewName.length()); - _worldPacket.WriteBit(RenameData.HasDeclinedNames); + _worldPacket.WriteBit(RenameData.DeclinedNames.is_initialized()); _worldPacket.FlushBits(); - if (RenameData.HasDeclinedNames) + if (RenameData.DeclinedNames) { for (int32 i = 0; i < MAX_DECLINED_NAME_CASES; i++) { - _worldPacket.WriteBits(RenameData.DeclinedNames.name[i].length(), 7); + _worldPacket.WriteBits(RenameData.DeclinedNames->name[i].length(), 7); _worldPacket.FlushBits(); } for (int32 i = 0; i < MAX_DECLINED_NAME_CASES; i++) - _worldPacket << RenameData.DeclinedNames.name[i]; + _worldPacket << RenameData.DeclinedNames->name[i]; } _worldPacket.WriteString(RenameData.NewName); @@ -126,15 +126,15 @@ void WorldPackets::Pet::PetRename::Read() int8 nameLen = 0; _worldPacket >> nameLen; - RenameData.HasDeclinedNames = _worldPacket.ReadBit(); - if (RenameData.HasDeclinedNames) + if (_worldPacket.ReadBit()) { + RenameData.DeclinedNames = boost::in_place(); int32 count[MAX_DECLINED_NAME_CASES]; for (int32 i = 0; i < MAX_DECLINED_NAME_CASES; i++) count[i] = _worldPacket.ReadBits(7); for (int32 i = 0; i < MAX_DECLINED_NAME_CASES; i++) - RenameData.DeclinedNames.name[i] = _worldPacket.ReadString(count[i]); + RenameData.DeclinedNames->name[i] = _worldPacket.ReadString(count[i]); } RenameData.NewName = _worldPacket.ReadString(nameLen); @@ -185,3 +185,10 @@ void WorldPackets::Pet::PetCancelAura::Read() _worldPacket >> PetGUID; _worldPacket >> SpellID; } + +WorldPacket const* WorldPackets::Pet::SetPetSpecialization::Write() +{ + _worldPacket << uint16(SpecID); + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/PetPackets.h b/src/server/game/Server/Packets/PetPackets.h index 500fef3a249..813d82d4827 100644 --- a/src/server/game/Server/Packets/PetPackets.h +++ b/src/server/game/Server/Packets/PetPackets.h @@ -163,8 +163,7 @@ namespace WorldPackets ObjectGuid PetGUID; int32 PetNumber = 0; std::string NewName; - bool HasDeclinedNames = false; - DeclinedName DeclinedNames; + Optional<DeclinedName> DeclinedNames; }; class PetNameInvalid final : public ServerPacket @@ -226,6 +225,16 @@ namespace WorldPackets int32 SpellID = 0; }; + class SetPetSpecialization final : public ServerPacket + { + public: + SetPetSpecialization() : ServerPacket(SMSG_SET_PET_SPECIALIZATION, 2) { } + + WorldPacket const* Write() override; + + uint16 SpecID = 0; + }; + } } diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 8efd98c19f9..1f9badfbdef 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -714,7 +714,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_SET_PARTY_ASSIGNMENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Party::SetPartyAssignment, &WorldSession::HandleSetPartyAssignment); DEFINE_HANDLER(CMSG_SET_PARTY_LEADER, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Party::SetPartyLeader, &WorldSession::HandleSetPartyLeaderOpcode); DEFINE_HANDLER(CMSG_SET_PET_SLOT, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); - DEFINE_HANDLER(CMSG_SET_PLAYER_DECLINED_NAMES, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Character::SetPlayerDeclinedNames, &WorldSession::HandleSetPlayerDeclinedNames); + DEFINE_HANDLER(CMSG_SET_PLAYER_DECLINED_NAMES, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::SetPlayerDeclinedNames, &WorldSession::HandleSetPlayerDeclinedNames); DEFINE_HANDLER(CMSG_SET_PREFERRED_CEMETERY, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_SET_PVP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::SetPvP, &WorldSession::HandleSetPvP); DEFINE_HANDLER(CMSG_SET_RAID_DIFFICULTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::SetRaidDifficulty, &WorldSession::HandleSetRaidDifficultyOpcode); @@ -749,7 +749,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_SUPPORT_TICKET_SUBMIT_COMPLAINT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, WorldPackets::Ticket::SupportTicketSubmitComplaint, &WorldSession::HandleSupportTicketSubmitComplaint); DEFINE_HANDLER(CMSG_SUPPORT_TICKET_SUBMIT_SUGGESTION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Ticket::SupportTicketSubmitSuggestion, &WorldSession::HandleSupportTicketSubmitSuggestion); DEFINE_HANDLER(CMSG_SUSPEND_COMMS_ACK, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); - DEFINE_HANDLER(CMSG_SUSPEND_TOKEN_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL); + DEFINE_HANDLER(CMSG_SUSPEND_TOKEN_RESPONSE, STATUS_TRANSFER, PROCESS_THREADUNSAFE, WorldPackets::Movement::SuspendTokenResponse, &WorldSession::HandleSuspendTokenResponse); DEFINE_HANDLER(CMSG_SWAP_INV_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::SwapInvItem, &WorldSession::HandleSwapInvItemOpcode); DEFINE_HANDLER(CMSG_SWAP_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::SwapItem, &WorldSession::HandleSwapItem); DEFINE_HANDLER(CMSG_SWAP_SUB_GROUPS, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Party::SwapSubGroups, &WorldSession::HandleSwapSubGroupsOpcode); @@ -1576,7 +1576,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESPOND_INSPECT_ACHIEVEMENTS, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESUME_CAST_BAR, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESUME_COMMS, STATUS_NEVER, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESUME_TOKEN, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESUME_TOKEN, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESURRECT_REQUEST, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESYNC_RUNES, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_ROLE_CHANGED_INFORM, STATUS_NEVER, CONNECTION_TYPE_REALM); @@ -1628,7 +1628,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_MELEE_ANIM_KIT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_MOVEMENT_ANIM_KIT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_PCT_SPELL_MODIFIER, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_PET_SPECIALIZATION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_PET_SPECIALIZATION, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_PLAY_HOVER_ANIM, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_PROFICIENCY, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); @@ -1687,7 +1687,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUMMON_REQUEST, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUPERCEDED_SPELLS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUSPEND_COMMS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUSPEND_TOKEN, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUSPEND_TOKEN, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TALENTS_INVOLUNTARILY_RESET, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TAXI_NODE_STATUS, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TEXT_EMOTE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 5203cdc1f9b..937961ad571 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -51,6 +51,7 @@ #include "BattlePetMgr.h" #include "PacketUtilities.h" #include "CollectionMgr.h" +#include "Metric.h" #include <zlib.h> @@ -117,6 +118,7 @@ WorldSession::WorldSession(uint32 id, std::string&& name, uint32 battlenetAccoun _battlenetAccountId(battlenetAccountId), m_expansion(expansion), _os(os), + _battlenetRequestToken(0), _warden(NULL), _logoutTime(0), m_inQueue(false), @@ -334,10 +336,6 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) if (IsConnectionIdle()) m_Socket[CONNECTION_TYPE_REALM]->CloseSocket(); - if (updater.ProcessUnsafe()) - while (_player && _player->IsBeingTeleportedSeamlessly()) - HandleMoveWorldportAckOpcode(); - ///- Retrieve packets from the receive queue and call the appropriate handlers /// not process packets if socket already closed WorldPacket* packet = NULL; @@ -456,6 +454,8 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) break; } + TC_METRIC_VALUE("processed_packets", processedPackets); + _recvQueue.readd(requeuePackets.begin(), requeuePackets.end()); if (m_Socket[CONNECTION_TYPE_REALM] && m_Socket[CONNECTION_TYPE_REALM]->IsOpen() && _warden) @@ -614,6 +614,8 @@ void WorldSession::LogoutPlayer(bool save) //! Call script hook before deletion sScriptMgr->OnPlayerLogout(_player); + TC_METRIC_EVENT("player_events", "Logout", _player->GetName()); + //! Remove the player from the world // the player may not be in the world when logging out // e.g if he got disconnected during a transfer to another map diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 5b06c9ce03f..3093b05163c 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -439,6 +439,7 @@ namespace WorldPackets class MoveTimeSkipped; class SummonResponse; class MoveSplineDone; + class SuspendTokenResponse; } namespace NPC @@ -1232,6 +1233,7 @@ class TC_GAME_API WorldSession void HandleMoveWorldportAckOpcode(WorldPackets::Movement::WorldPortResponse& packet); void HandleMoveWorldportAckOpcode(); // for server-side calls + void HandleSuspendTokenResponse(WorldPackets::Movement::SuspendTokenResponse& suspendTokenResponse); void HandleMovementOpcodes(WorldPackets::Movement::ClientPlayerMovement& packet); void HandleSetActiveMoverOpcode(WorldPackets::Movement::SetActiveMover& packet); diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h index 5130ebd7876..9eb6ad5c864 100644 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -404,7 +404,7 @@ enum AuraType SPELL_AURA_MOD_AUTOATTACK_DAMAGE = 344, // NYI SPELL_AURA_BYPASS_ARMOR_FOR_CASTER = 345, SPELL_AURA_ENABLE_ALT_POWER = 346, // NYI - SPELL_AURA_MOD_SPELL_COOLDOWN_BY_HASTE = 347, // NYI + SPELL_AURA_MOD_SPELL_COOLDOWN_BY_HASTE = 347, SPELL_AURA_DEPOSIT_BONUS_MONEY_IN_GUILD_BANK_ON_LOOT = 348, SPELL_AURA_MOD_CURRENCY_GAIN = 349, SPELL_AURA_MOD_GATHERING_ITEMS_GAINED_PERCENT = 350, // NYI @@ -433,11 +433,11 @@ enum AuraType SPELL_AURA_373 = 373, SPELL_AURA_MODIFY_FALL_DAMAGE_PCT = 374, // NYI SPELL_AURA_375 = 375, - SPELL_AURA_MOD_CURRENCY_GAIN_2 = 376, // NYI + SPELL_AURA_MOD_CURRENCY_GAIN_FROM_SOURCE = 376, // NYI SPELL_AURA_CAST_WHILE_WALKING_2 = 377, // NYI SPELL_AURA_378 = 378, SPELL_AURA_379 = 379, - SPELL_AURA_380 = 380, + SPELL_AURA_MOD_GLOBAL_COOLDOWN_BY_HASTE = 380, // Allows melee abilities to benefit from haste GCD reduction SPELL_AURA_381 = 381, SPELL_AURA_MOD_PET_STAT_PCT = 382, // NYI SPELL_AURA_IGNORE_SPELL_COOLDOWN = 383, // NYI @@ -451,7 +451,7 @@ enum AuraType SPELL_AURA_391 = 391, SPELL_AURA_392 = 392, SPELL_AURA_393 = 393, - SPELL_AURA_394 = 394, + SPELL_AURA_SHOW_CONFIRMATION_PROMPT = 394, SPELL_AURA_AREA_TRIGGER = 395, // NYI SPELL_AURA_396 = 396, SPELL_AURA_397 = 397, @@ -473,8 +473,8 @@ enum AuraType SPELL_AURA_413 = 413, SPELL_AURA_414 = 414, SPELL_AURA_415 = 415, - SPELL_AURA_MOD_COOLDOWN_BY_HASTE_EFFECTS = 416, // NYI - SPELL_AURA_MOD_GLOBAL_COOLDOWN_BY_HASTE_EFFECTS = 417, // NYI + SPELL_AURA_MOD_COOLDOWN_BY_HASTE_REGEN = 416, + SPELL_AURA_MOD_GLOBAL_COOLDOWN_BY_HASTE_REGEN = 417, SPELL_AURA_MOD_MAX_POWER = 418, // NYI SPELL_AURA_MOD_BASE_MANA_PCT = 419, SPELL_AURA_MOD_BATTLE_PET_XP_PCT = 420, // NYI @@ -497,10 +497,10 @@ enum AuraType SPELL_AURA_437 = 437, SPELL_AURA_438 = 438, SPELL_AURA_439 = 439, - SPELL_AURA_440 = 440, - SPELL_AURA_441 = 441, - SPELL_AURA_442 = 442, - SPELL_AURA_443 = 443, + SPELL_AURA_MOD_MULTISTRIKE_DAMAGE = 440, // NYI + SPELL_AURA_MOD_MULTISTRIKE_CHANCE = 441, // NYI + SPELL_AURA_MOD_READINESS = 442, // NYI + SPELL_AURA_MOD_LEECH = 443, // NYI SPELL_AURA_444 = 444, SPELL_AURA_445 = 445, SPELL_AURA_446 = 446, @@ -508,7 +508,7 @@ enum AuraType SPELL_AURA_448 = 448, SPELL_AURA_449 = 449, SPELL_AURA_450 = 450, - SPELL_AURA_OVERRIDE_PET_SPECS = 451, // NYI + SPELL_AURA_OVERRIDE_PET_SPECS = 451, SPELL_AURA_452 = 452, SPELL_AURA_CHARGE_RECOVERY_MOD = 453, SPELL_AURA_CHARGE_RECOVERY_MULTIPLIER = 454, @@ -526,13 +526,14 @@ enum AuraType SPELL_AURA_MOD_BONUS_ARMOR_PCT = 466, // Affects bonus armor gain from all sources except base stats SPELL_AURA_MOD_STAT_BONUS_PCT = 467, // Affects stat gain from all sources except base stats SPELL_AURA_468 = 468, - SPELL_AURA_469 = 469, - SPELL_AURA_471 = 471, + SPELL_AURA_SHOW_CONFIRMATION_PROMPT_WITH_DIFFICULTY = 469, + SPELL_AURA_470 = 470, + SPELL_AURA_MOD_VERSATILITY = 471, // NYI SPELL_AURA_472 = 472, SPELL_AURA_PREVENT_DURABILITY_LOSS_FROM_COMBAT = 473, // Prevents durability loss from dealing/taking damage SPELL_AURA_474 = 474, - SPELL_AURA_475 = 475, - SPELL_AURA_476 = 476, + SPELL_AURA_ALLOW_USING_GAMEOBJECTS_WHILE_MOUNTED = 475, + SPELL_AURA_MOD_CURRENCY_GAIN_LOOTED = 476, SPELL_AURA_477 = 477, SPELL_AURA_478 = 478, SPELL_AURA_479 = 479, diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 9962a214f97..58375e3f0df 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -204,7 +204,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT &AuraEffect::HandleAuraModResistanceExclusive, //143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE &AuraEffect::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes - &AuraEffect::HandleAuraModPetTalentsPoints, //145 SPELL_AURA_MOD_PET_TALENT_POINTS + &AuraEffect::HandleNULL, //145 used by 5 spells in 6.2.4 dbc but the meaning of this aura changed (it's used by mind control spells but isn't the control itself) &AuraEffect::HandleNoImmediateEffect, //146 SPELL_AURA_ALLOW_TAME_PET_TYPE &AuraEffect::HandleModStateImmunityMask, //147 SPELL_AURA_MECHANIC_IMMUNITY_MASK &AuraEffect::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS @@ -406,7 +406,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNULL, //344 SPELL_AURA_MOD_AUTOATTACK_DAMAGE &AuraEffect::HandleNoImmediateEffect, //345 SPELL_AURA_BYPASS_ARMOR_FOR_CASTER &AuraEffect::HandleEnableAltPower, //346 SPELL_AURA_ENABLE_ALT_POWER - &AuraEffect::HandleNULL, //347 SPELL_AURA_MOD_SPELL_COOLDOWN_BY_HASTE + &AuraEffect::HandleNoImmediateEffect, //347 SPELL_AURA_MOD_SPELL_COOLDOWN_BY_HASTE implemented in SpellHistory::StartCooldown &AuraEffect::HandleNoImmediateEffect, //348 SPELL_AURA_DEPOSIT_BONUS_MONEY_IN_GUILD_BANK_ON_LOOT implemented in WorldSession::HandleLootMoneyOpcode &AuraEffect::HandleNoImmediateEffect, //349 SPELL_AURA_MOD_CURRENCY_GAIN implemented in Player::ModifyCurrency &AuraEffect::HandleNULL, //350 SPELL_AURA_MOD_GATHERING_ITEMS_GAINED_PERCENT @@ -435,11 +435,11 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNULL, //373 &AuraEffect::HandleNULL, //374 SPELL_AURA_MODIFY_FALL_DAMAGE_PCT &AuraEffect::HandleNULL, //375 - &AuraEffect::HandleNULL, //376 SPELL_AURA_MOD_CURRENCY_GAIN_2 + &AuraEffect::HandleNULL, //376 SPELL_AURA_MOD_CURRENCY_GAIN_FROM_SOURCE &AuraEffect::HandleNULL, //377 SPELL_AURA_CAST_WHILE_WALKING_2 &AuraEffect::HandleNULL, //378 &AuraEffect::HandleNULL, //379 - &AuraEffect::HandleNULL, //380 + &AuraEffect::HandleNoImmediateEffect, //380 SPELL_AURA_MOD_GLOBAL_COOLDOWN_BY_HASTE implemented in Spell::TriggerGlobalCooldown &AuraEffect::HandleNULL, //381 &AuraEffect::HandleNULL, //382 SPELL_AURA_MOD_PET_STAT_PCT &AuraEffect::HandleNULL, //383 SPELL_AURA_IGNORE_SPELL_COOLDOWN @@ -453,7 +453,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNULL, //391 &AuraEffect::HandleNULL, //392 &AuraEffect::HandleNULL, //393 - &AuraEffect::HandleNULL, //394 + &AuraEffect::HandleShowConfirmationPrompt, //394 SPELL_AURA_SHOW_CONFIRMATION_PROMPT &AuraEffect::HandleNULL, //395 SPELL_AURA_AREA_TRIGGER &AuraEffect::HandleNULL, //396 &AuraEffect::HandleNULL, //397 @@ -475,8 +475,8 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNULL, //413 &AuraEffect::HandleNULL, //414 &AuraEffect::HandleNULL, //415 - &AuraEffect::HandleNULL, //416 SPELL_AURA_MOD_COOLDOWN_BY_HASTE_EFFECTS - &AuraEffect::HandleNULL, //417 SPELL_AURA_MOD_GLOBAL_COOLDOWN_BY_HASTE_EFFECTS + &AuraEffect::HandleNoImmediateEffect, //416 SPELL_AURA_MOD_COOLDOWN_BY_HASTE_REGEN implemented in SpellHistory::StartCooldown + &AuraEffect::HandleNoImmediateEffect, //417 SPELL_AURA_MOD_GLOBAL_COOLDOWN_BY_HASTE_REGEN implemented in Spell::TriggerGlobalCooldown &AuraEffect::HandleNULL, //418 SPELL_AURA_MOD_MAX_POWER &AuraEffect::HandleAuraModIncreaseBaseManaPercent, //419 SPELL_AURA_MOD_BASE_MANA_PCT &AuraEffect::HandleNULL, //420 SPELL_AURA_MOD_BATTLE_PET_XP_PCT @@ -499,10 +499,10 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNULL, //437 &AuraEffect::HandleNULL, //438 &AuraEffect::HandleNULL, //439 - &AuraEffect::HandleNULL, //440 - &AuraEffect::HandleNULL, //441 - &AuraEffect::HandleNULL, //442 - &AuraEffect::HandleNULL, //443 + &AuraEffect::HandleNULL, //440 SPELL_AURA_MOD_MULTISTRIKE_DAMAGE + &AuraEffect::HandleNULL, //441 SPELL_AURA_MOD_MULTISTRIKE_CHANCE + &AuraEffect::HandleNULL, //442 SPELL_AURA_MOD_READINESS + &AuraEffect::HandleNULL, //443 SPELL_AURA_MOD_LEECH &AuraEffect::HandleNULL, //444 &AuraEffect::HandleNULL, //445 &AuraEffect::HandleNULL, //446 @@ -510,7 +510,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNULL, //448 &AuraEffect::HandleNULL, //449 &AuraEffect::HandleNULL, //450 - &AuraEffect::HandleNULL, //451 SPELL_AURA_OVERRIDE_PET_SPECS + &AuraEffect::HandleOverridePetSpecs, //451 SPELL_AURA_OVERRIDE_PET_SPECS &AuraEffect::HandleNULL, //452 &AuraEffect::HandleNoImmediateEffect, //453 SPELL_AURA_CHARGE_RECOVERY_MOD implemented in SpellHistory::GetChargeRecoveryTime &AuraEffect::HandleNoImmediateEffect, //454 SPELL_AURA_CHARGE_RECOVERY_MULTIPLIER implemented in SpellHistory::GetChargeRecoveryTime @@ -528,14 +528,14 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNULL, //466 SPELL_AURA_MOD_BONUS_ARMOR_PCT &AuraEffect::HandleModStatBonusPercent, //467 SPELL_AURA_MOD_STAT_BONUS_PCT &AuraEffect::HandleNULL, //468 - &AuraEffect::HandleNULL, //469 + &AuraEffect::HandleShowConfirmationPrompt, //469 SPELL_AURA_SHOW_CONFIRMATION_PROMPT_WITH_DIFFICULTY &AuraEffect::HandleNULL, //470 - &AuraEffect::HandleNULL, //471 + &AuraEffect::HandleNULL, //471 SPELL_AURA_MOD_VERSATILITY &AuraEffect::HandleNULL, //472 &AuraEffect::HandleNoImmediateEffect, //473 SPELL_AURA_PREVENT_DURABILITY_LOSS_FROM_COMBAT implemented in Player::DurabilityPointLossForEquipSlot &AuraEffect::HandleNULL, //474 - &AuraEffect::HandleNULL, //475 - &AuraEffect::HandleNULL, //476 + &AuraEffect::HandleAllowUsingGameobjectsWhileMounted, //475 SPELL_AURA_ALLOW_USING_GAMEOBJECTS_WHILE_MOUNTED + &AuraEffect::HandleNULL, //476 SPELL_AURA_MOD_CURRENCY_GAIN_LOOTED &AuraEffect::HandleNULL, //477 &AuraEffect::HandleNULL, //478 &AuraEffect::HandleNULL, //479 @@ -706,6 +706,11 @@ int32 AuraEffect::CalculateAmount(Unit* caster) break; } } + case SPELL_AURA_SHOW_CONFIRMATION_PROMPT_WITH_DIFFICULTY: + if (caster) + amount = caster->GetMap()->GetDifficultyID(); + m_canBeRecalculated = false; + break; default: break; } @@ -846,6 +851,9 @@ void AuraEffect::ChangeAmount(int32 newAmount, bool mark, bool onStackOrReapply) for (std::list<AuraApplication*>::const_iterator apptItr = effectApplications.begin(); apptItr != effectApplications.end(); ++apptItr) if ((*apptItr)->HasEffect(GetEffIndex())) HandleEffect(*apptItr, handleMask, true); + + if (GetSpellInfo()->HasAttribute(SPELL_ATTR8_AURA_SEND_AMOUNT)) + GetBase()->SetNeedClientUpdateForTargets(); } void AuraEffect::HandleEffect(AuraApplication * aurApp, uint8 mode, bool apply) @@ -2584,21 +2592,6 @@ void AuraEffect::HandleAuraUntrackable(AuraApplication const* aurApp, uint8 mode /*** SKILLS & TALENTS ***/ /****************************/ -void AuraEffect::HandleAuraModPetTalentsPoints(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const -{ - if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)) - return; - - Unit* target = aurApp->GetTarget(); - - if (target->GetTypeId() != TYPEID_PLAYER) - return; - - // Recalculate pet talent points - if (Pet* pet = target->ToPlayer()->GetPet()) - pet->InitTalentForLevel(); -} - void AuraEffect::HandleAuraModSkill(AuraApplication const* aurApp, uint8 mode, bool apply) const { if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_SKILL))) @@ -6603,3 +6596,55 @@ void AuraEffect::HandleModSpellCategoryCooldown(AuraApplication const* aurApp, u if (Player* player = aurApp->GetTarget()->ToPlayer()) player->SendSpellCategoryCooldowns(); } + +void AuraEffect::HandleShowConfirmationPrompt(AuraApplication const* aurApp, uint8 mode, bool apply) const +{ + if (!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Player* player = aurApp->GetTarget()->ToPlayer(); + if (!player) + return; + + if (apply) + player->AddTemporarySpell(_effectInfo->TriggerSpell); + else + player->RemoveTemporarySpell(_effectInfo->TriggerSpell); +} + +void AuraEffect::HandleOverridePetSpecs(AuraApplication const* aurApp, uint8 mode, bool apply) const +{ + if (!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Player* player = aurApp->GetTarget()->ToPlayer(); + if (!player) + return; + + if (player->getClass() != CLASS_HUNTER) + return; + + Pet* pet = player->GetPet(); + if (!pet) + return; + + ChrSpecializationEntry const* currSpec = sChrSpecializationStore.LookupEntry(pet->GetSpecialization()); + if (!currSpec) + return; + + pet->SetSpecialization(sDB2Manager.GetChrSpecializationByIndex(apply ? PET_SPEC_OVERRIDE_CLASS_INDEX : 0, currSpec->OrderIndex)->ID); +} + +void AuraEffect::HandleAllowUsingGameobjectsWhileMounted(AuraApplication const* aurApp, uint8 mode, bool apply) const +{ + if (!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + if (aurApp->GetTarget()->GetTypeId() != TYPEID_PLAYER) + return; + + if (apply) + aurApp->GetTarget()->SetFlag(PLAYER_FIELD_LOCAL_FLAGS, PLAYER_LOCAL_FLAG_CAN_USE_OBJECTS_MOUNTED); + else if (!aurApp->GetTarget()->HasAuraType(SPELL_AURA_ALLOW_USING_GAMEOBJECTS_WHILE_MOUNTED)) + aurApp->GetTarget()->RemoveFlag(PLAYER_FIELD_LOCAL_FLAGS, PLAYER_LOCAL_FLAG_CAN_USE_OBJECTS_MOUNTED); +} diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index 46a0ccdabc6..8df069df7f3 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.h +++ b/src/server/game/Spells/Auras/SpellAuraEffects.h @@ -174,7 +174,6 @@ class TC_GAME_API AuraEffect void HandleAuraModStalked(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleAuraUntrackable(AuraApplication const* aurApp, uint8 mode, bool apply) const; // skills & talents - void HandleAuraModPetTalentsPoints(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleAuraModSkill(AuraApplication const* aurApp, uint8 mode, bool apply) const; // movement void HandleAuraMounted(AuraApplication const* aurApp, uint8 mode, bool apply) const; @@ -304,6 +303,9 @@ class TC_GAME_API AuraEffect void HandleAuraForceWeather(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleEnableAltPower(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleModSpellCategoryCooldown(AuraApplication const* aurApp, uint8 mode, bool apply) const; + void HandleShowConfirmationPrompt(AuraApplication const* aurApp, uint8 mode, bool apply) const; + void HandleOverridePetSpecs(AuraApplication const* aurApp, uint8 mode, bool apply) const; + void HandleAllowUsingGameobjectsWhileMounted(AuraApplication const* aurApp, uint8 mode, bool apply) const; // aura effect periodic tick handlers void HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const; diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index ec060f253b9..d0af2af8f97 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -1760,6 +1760,10 @@ bool Aura::CanStackWith(Aura const* existingAura) const return true; // Empty seat available (skip rest) } + if (HasEffectType(SPELL_AURA_SHOW_CONFIRMATION_PROMPT) || HasEffectType(SPELL_AURA_SHOW_CONFIRMATION_PROMPT_WITH_DIFFICULTY)) + if (existingAura->HasEffectType(SPELL_AURA_SHOW_CONFIRMATION_PROMPT) || existingAura->HasEffectType(SPELL_AURA_SHOW_CONFIRMATION_PROMPT_WITH_DIFFICULTY)) + return false; + // spell of same spell rank chain if (m_spellInfo->IsRankOf(existingSpellInfo)) { diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 005d15d8291..d109667cd85 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -4187,13 +4187,11 @@ void Spell::UpdateSpellCastDataAmmo(WorldPackets::Spells::SpellAmmo& ammo) void Spell::SendSpellExecuteLog() { WorldPackets::CombatLog::SpellExecuteLog spellExecuteLog; - spellExecuteLog.Caster = m_caster->GetGUID(); spellExecuteLog.SpellID = m_spellInfo->Id; for (SpellEffectInfo const* effect : GetEffects()) { - WorldPackets::CombatLog::SpellExecuteLog::SpellLogEffect spellLogEffect; if (!effect) continue; @@ -4202,6 +4200,9 @@ void Spell::SendSpellExecuteLog() _tradeSkillTargets[effect->EffectIndex].empty() && _feedPetTargets[effect->EffectIndex].empty()) continue; + spellExecuteLog.Effects.emplace_back(); + + WorldPackets::CombatLog::SpellExecuteLog::SpellLogEffect& spellLogEffect = spellExecuteLog.Effects.back(); spellLogEffect.Effect = effect->Effect; spellLogEffect.PowerDrainTargets = std::move(_powerDrainTargets[effect->EffectIndex]); spellLogEffect.ExtraAttacksTargets = std::move(_extraAttacksTargets[effect->EffectIndex]); @@ -4209,8 +4210,6 @@ void Spell::SendSpellExecuteLog() spellLogEffect.GenericVictimTargets = std::move(_genericVictimTargets[effect->EffectIndex]); spellLogEffect.TradeSkillTargets = std::move(_tradeSkillTargets[effect->EffectIndex]); spellLogEffect.FeedPetTargets = std::move(_feedPetTargets[effect->EffectIndex]); - - spellExecuteLog.Effects.push_back(spellLogEffect); } if (!spellExecuteLog.Effects.empty()) @@ -7346,7 +7345,7 @@ bool Spell::HasGlobalCooldown() const void Spell::TriggerGlobalCooldown() { int32 gcd = m_spellInfo->StartRecoveryTime; - if (!gcd) + if (!gcd || !m_spellInfo->StartRecoveryCategory) return; // Only players or controlled units have global cooldown @@ -7366,12 +7365,17 @@ void Spell::TriggerGlobalCooldown() if (m_caster->GetTypeId() == TYPEID_PLAYER) m_caster->ToPlayer()->ApplySpellMod(m_spellInfo->Id, SPELLMOD_GLOBAL_COOLDOWN, gcd, this); + bool isMeleeOrRangedSpell = m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE || + m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED || + m_spellInfo->HasAttribute(SPELL_ATTR0_REQ_AMMO) || + m_spellInfo->HasAttribute(SPELL_ATTR0_ABILITY); + // Apply haste rating - gcd = int32(float(gcd) * m_caster->GetFloatValue(UNIT_MOD_CAST_SPEED)); - if (gcd < MIN_GCD) - gcd = MIN_GCD; - else if (gcd > MAX_GCD) - gcd = MAX_GCD; + if (gcd > MIN_GCD && ((m_spellInfo->StartRecoveryCategory == 133 && !isMeleeOrRangedSpell) || m_caster->HasAuraTypeWithAffectMask(SPELL_AURA_MOD_GLOBAL_COOLDOWN_BY_HASTE, m_spellInfo))) + gcd = std::min<int32>(std::max<int32>(int32(float(gcd) * m_caster->GetFloatValue(UNIT_MOD_CAST_HASTE)), MIN_GCD), MAX_GCD); + + if (gcd > MIN_GCD && m_caster->HasAuraTypeWithAffectMask(SPELL_AURA_MOD_GLOBAL_COOLDOWN_BY_HASTE_REGEN, m_spellInfo)) + gcd = std::min<int32>(std::max<int32>(int32(float(gcd) * m_caster->GetFloatValue(UNIT_FIELD_MOD_HASTE_REGEN)), MIN_GCD), MAX_GCD); } m_caster->GetSpellHistory()->AddGlobalCooldown(m_spellInfo, gcd); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 3e9dec9f485..11a92fd67b8 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -271,7 +271,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectNULL, //203 SPELL_EFFECT_203 &Spell::EffectNULL, //204 SPELL_EFFECT_CHANGE_BATTLEPET_QUALITY &Spell::EffectNULL, //205 SPELL_EFFECT_LAUNCH_QUEST_CHOICE - &Spell::EffectNULL, //206 SPELL_EFFECT_206 + &Spell::EffectNULL, //206 SPELL_EFFECT_ALTER_ITEM &Spell::EffectNULL, //207 SPELL_EFFECT_LAUNCH_QUEST_TASK &Spell::EffectNULL, //208 SPELL_EFFECT_208 &Spell::EffectNULL, //209 SPELL_EFFECT_209 @@ -1725,7 +1725,7 @@ void Spell::SendLoot(ObjectGuid guid, LootType loottype) if (sScriptMgr->OnGossipHello(player, gameObjTarget)) return; - if (gameObjTarget->AI()->GossipHello(player)) + if (gameObjTarget->AI()->GossipHello(player, true)) return; switch (gameObjTarget->GetGoType()) @@ -2728,8 +2728,6 @@ void Spell::EffectTameCreature(SpellEffIndex /*effIndex*/) // caster have pet now m_caster->SetMinion(pet, true); - pet->InitTalentForLevel(); - if (m_caster->GetTypeId() == TYPEID_PLAYER) { pet->SavePetToDB(PET_SAVE_AS_CURRENT); @@ -3170,8 +3168,7 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex) Map* map = target->GetMap(); - if (!pGameObj->Create(map->GenerateLowGuid<HighGuid::GameObject>(), gameobject_id, map, - m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) + if (!pGameObj->Create(gameobject_id, map, m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) { delete pGameObj; return; @@ -3197,8 +3194,7 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex) if (uint32 linkedEntry = pGameObj->GetGOInfo()->GetLinkedGameObjectEntry()) { GameObject* linkedGO = new GameObject; - if (linkedGO->Create(map->GenerateLowGuid<HighGuid::GameObject>(), linkedEntry, map, - m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) + if (linkedGO->Create(linkedEntry, map, m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) { linkedGO->CopyPhaseFrom(m_caster); @@ -3791,8 +3787,7 @@ void Spell::EffectDuel(SpellEffIndex effIndex) uint32 gameobject_id = effectInfo->MiscValue; Map* map = m_caster->GetMap(); - if (!pGameObj->Create(map->GenerateLowGuid<HighGuid::GameObject>(), gameobject_id, - map, 0, + if (!pGameObj->Create(gameobject_id, map, 0, m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2, m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2, m_caster->GetPositionZ(), @@ -4097,8 +4092,7 @@ void Spell::EffectSummonObject(SpellEffIndex effIndex) m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE); Map* map = m_caster->GetMap(); - if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), go_id, map, - 0, x, y, z, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY)) + if (!go->Create(go_id, map, 0, x, y, z, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY)) { delete go; return; @@ -4756,8 +4750,7 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex) GameObject* pGameObj = new GameObject; - if (!pGameObj->Create(cMap->GenerateLowGuid<HighGuid::GameObject>(), name_id, cMap, - 0, fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) + if (!pGameObj->Create(name_id, cMap, 0, fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) { delete pGameObj; return; @@ -4824,8 +4817,7 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex) if (uint32 linkedEntry = pGameObj->GetGOInfo()->GetLinkedGameObjectEntry()) { GameObject* linkedGO = new GameObject; - if (linkedGO->Create(cMap->GenerateLowGuid<HighGuid::GameObject>(), linkedEntry, cMap, - 0, fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) + if (linkedGO->Create(linkedEntry, cMap, 0, fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) { linkedGO->CopyPhaseFrom(m_caster); @@ -5178,8 +5170,6 @@ void Spell::EffectCreateTamedPet(SpellEffIndex /*effIndex*/) // unitTarget has pet now unitTarget->SetMinion(pet, true); - pet->InitTalentForLevel(); - if (unitTarget->GetTypeId() == TYPEID_PLAYER) { pet->SavePetToDB(PET_SAVE_AS_CURRENT); diff --git a/src/server/game/Spells/SpellHistory.cpp b/src/server/game/Spells/SpellHistory.cpp index bb991b66cf9..b6c7fdc17ec 100644 --- a/src/server/game/Spells/SpellHistory.cpp +++ b/src/server/game/Spells/SpellHistory.cpp @@ -330,7 +330,7 @@ void SpellHistory::WritePacket(WorldPackets::Spells::SendSpellCharges* sendSpell WorldPackets::Spells::SpellChargeEntry chargeEntry; chargeEntry.Category = p.first; chargeEntry.NextRecoveryTime = uint32(cooldownDuration.count()); - chargeEntry.ConsumedCharges = p.second.size(); + chargeEntry.ConsumedCharges = uint8(p.second.size()); sendSpellCharges->Entries.push_back(chargeEntry); } } @@ -359,6 +359,8 @@ void SpellHistory::WritePacket(WorldPackets::Pet::PetSpells* petSpells) const if (categoryDuration.count() > 0) petSpellCooldown.CategoryDuration = uint32(categoryDuration.count()); } + else + petSpellCooldown.CategoryDuration = 0x80000000; petSpells->Cooldowns.push_back(petSpellCooldown); } @@ -375,14 +377,13 @@ void SpellHistory::WritePacket(WorldPackets::Pet::PetSpells* petSpells) const WorldPackets::Pet::PetSpellHistory petChargeEntry; petChargeEntry.CategoryID = p.first; petChargeEntry.RecoveryTime = uint32(cooldownDuration.count()); - petChargeEntry.ConsumedCharges = p.second.size(); + petChargeEntry.ConsumedCharges = int8(p.second.size()); petSpells->SpellHistory.push_back(petChargeEntry); } } } - void SpellHistory::StartCooldown(SpellInfo const* spellInfo, uint32 itemId, Spell* spell /*= nullptr*/, bool onHold /*= false*/) { // init cooldown values @@ -421,6 +422,18 @@ void SpellHistory::StartCooldown(SpellInfo const* spellInfo, uint32 itemId, Spel modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, categoryCooldown, spell); } + if (_owner->HasAuraTypeWithAffectMask(SPELL_AURA_MOD_SPELL_COOLDOWN_BY_HASTE, spellInfo)) + { + cooldown = int32(cooldown * _owner->GetFloatValue(UNIT_MOD_CAST_HASTE)); + categoryCooldown = int32(categoryCooldown * _owner->GetFloatValue(UNIT_MOD_CAST_HASTE)); + } + + if (_owner->HasAuraTypeWithAffectMask(SPELL_AURA_MOD_COOLDOWN_BY_HASTE_REGEN, spellInfo)) + { + cooldown = int32(cooldown * _owner->GetFloatValue(UNIT_FIELD_MOD_HASTE_REGEN)); + categoryCooldown = int32(categoryCooldown * _owner->GetFloatValue(UNIT_FIELD_MOD_HASTE_REGEN)); + } + if (int32 cooldownMod = _owner->GetTotalAuraModifier(SPELL_AURA_MOD_COOLDOWN)) { // Apply SPELL_AURA_MOD_COOLDOWN only to own spells @@ -731,7 +744,7 @@ void SpellHistory::RestoreCharge(uint32 chargeCategoryId) setSpellCharges.Category = chargeCategoryId; if (!itr->second.empty()) setSpellCharges.NextRecoveryTime = uint32(std::chrono::duration_cast<std::chrono::milliseconds>(itr->second.front().RechargeEnd - Clock::now()).count()); - setSpellCharges.ConsumedCharges = itr->second.size(); + setSpellCharges.ConsumedCharges = uint8(itr->second.size()); setSpellCharges.IsPet = player != _owner; player->SendDirectMessage(setSpellCharges.Write()); @@ -802,7 +815,7 @@ int32 SpellHistory::GetChargeRecoveryTime(uint32 chargeCategoryId) const int32 recoveryTime = chargeCategoryEntry->ChargeRecoveryTime; recoveryTime += _owner->GetTotalAuraModifierByMiscValue(SPELL_AURA_CHARGE_RECOVERY_MOD, chargeCategoryId); - float recoveryTimeF = recoveryTime; + float recoveryTimeF = float(recoveryTime); recoveryTimeF *= _owner->GetTotalAuraMultiplierByMiscValue(SPELL_AURA_CHARGE_RECOVERY_MULTIPLIER, chargeCategoryId); if (_owner->HasAuraType(SPELL_AURA_CHARGE_RECOVERY_AFFECTED_BY_HASTE)) @@ -923,7 +936,7 @@ void SpellHistory::RestoreCooldownStateAfterDuel() for (auto const& c : _spellCooldowns) { Clock::time_point now = Clock::now(); - uint32 cooldownDuration = c.second.CooldownEnd > now ? std::chrono::duration_cast<std::chrono::milliseconds>(c.second.CooldownEnd - now).count() : 0; + uint32 cooldownDuration = uint32(c.second.CooldownEnd > now ? std::chrono::duration_cast<std::chrono::milliseconds>(c.second.CooldownEnd - now).count() : 0); // cooldownDuration must be between 0 and 10 minutes in order to avoid any visual bugs if (cooldownDuration <= 0 || cooldownDuration > 10 * MINUTE * IN_MILLISECONDS || c.second.OnHold) diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 6e8db741a3d..362d5e8df35 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -926,7 +926,7 @@ SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] = {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 203 SPELL_EFFECT_203 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 204 SPELL_EFFECT_CHANGE_BATTLEPET_QUALITY {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 205 SPELL_EFFECT_LAUNCH_QUEST_CHOICE - {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 206 SPELL_EFFECT_206 + {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 206 SPELL_EFFECT_ALTER_IETM {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 207 SPELL_EFFECT_LAUNCH_QUEST_TASK {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 208 SPELL_EFFECT_208 {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_NONE}, // 209 SPELL_EFFECT_209 @@ -2820,6 +2820,9 @@ inline float CalcPPMItemLevelMod(SpellProcsPerMinuteModEntry const* mod, int32 i float SpellInfo::CalcProcPPM(Unit* caster, int32 itemLevel) const { float ppm = ProcBasePPM; + if (!caster) + return ppm; + for (SpellProcsPerMinuteModEntry const* mod : ProcPPMMods) { switch (mod->Type) diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 4262cf11e27..bf536765901 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -64,6 +64,7 @@ #include "SkillDiscovery.h" #include "SkillExtraItems.h" #include "SmartAI.h" +#include "Metric.h" #include "SupportMgr.h" #include "TaxiPathGraph.h" #include "TransportMgr.h" @@ -438,6 +439,7 @@ void World::LoadConfigSettings(bool reload) return; } sLog->LoadFromConfig(); + sMetric->LoadFromConfigs(); } m_defaultDbcLocale = LocaleConstant(sConfigMgr->GetIntDefault("DBC.Locale", 0)); @@ -2124,6 +2126,8 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.worldserver", "World initialized in %u minutes %u seconds", (startupDuration / 60000), ((startupDuration % 60000) / 1000)); + TC_METRIC_EVENT("events", "World initialized", "World initialized in " + std::to_string(startupDuration / 60000) + " minutes " + std::to_string((startupDuration % 60000) / 1000) + " seconds"); + if (uint32 realmId = sConfigMgr->GetIntDefault("RealmID", 0)) // 0 reserved for auth sLog->SetRealmId(realmId); } @@ -2426,6 +2430,10 @@ void World::Update(uint32 diff) ProcessCliCommands(); sScriptMgr->OnWorldUpdate(diff); + + // Stats logger update + sMetric->Update(); + TC_METRIC_VALUE("update_time_diff", diff); } void World::ForceGameEventUpdate() |