aboutsummaryrefslogtreecommitdiff
path: root/src/server/game
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2016-06-13 21:00:25 +0200
committerShauren <shauren.trinity@gmail.com>2016-06-13 21:00:25 +0200
commitd2733eb6f1f9a550ec6511b5fa696b67b11044b3 (patch)
tree92e101dba7e48661de4a02c93bfba5700a6f1bdf /src/server/game
parent3903482eb810625fce64c616a4edca3f06975e94 (diff)
parent2fe6fc63d79655a96ee2135a6b380ce353729088 (diff)
Merge branch '6.x' of https://github.com/TrinityCore/TrinityCore into legion
Diffstat (limited to 'src/server/game')
-rw-r--r--src/server/game/AI/CoreAI/GameObjectAI.h2
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp2
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.h2
-rw-r--r--src/server/game/AuctionHouse/AuctionHouseMgr.cpp6
-rw-r--r--src/server/game/Battlefield/Battlefield.cpp2
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp9
-rw-r--r--src/server/game/Battlegrounds/Battleground.h4
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp13
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAB.h7
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp13
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAV.h7
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp15
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundEY.h7
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp12
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundIC.h7
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp13
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundWS.h7
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp6
-rw-r--r--src/server/game/Conditions/ConditionMgr.h2
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp26
-rw-r--r--src/server/game/Entities/GameObject/GameObject.h2
-rw-r--r--src/server/game/Entities/Object/Object.cpp2
-rw-r--r--src/server/game/Entities/Object/ObjectGuid.h16
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp379
-rw-r--r--src/server/game/Entities/Pet/Pet.h18
-rw-r--r--src/server/game/Entities/Player/Player.cpp42
-rw-r--r--src/server/game/Entities/Player/Player.h4
-rw-r--r--src/server/game/Entities/Taxi/TaxiPathGraph.cpp5
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp2
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp132
-rw-r--r--src/server/game/Entities/Unit/Unit.h4
-rw-r--r--src/server/game/Garrison/Garrison.cpp5
-rw-r--r--src/server/game/Globals/ObjectAccessor.cpp13
-rw-r--r--src/server/game/Globals/ObjectAccessor.h3
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp19
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp5
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp32
-rw-r--r--src/server/game/Handlers/PetHandler.cpp17
-rw-r--r--src/server/game/Handlers/SpellHandler.cpp2
-rw-r--r--src/server/game/Maps/Map.cpp2
-rw-r--r--src/server/game/Maps/MapScripts.cpp8
-rw-r--r--src/server/game/Maps/TransportMgr.cpp2
-rw-r--r--src/server/game/Maps/ZoneScript.h2
-rw-r--r--src/server/game/Miscellaneous/Language.h2
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h264
-rw-r--r--src/server/game/Movement/PathGenerator.cpp3
-rw-r--r--src/server/game/Server/Packets/BattlenetPackets.h4
-rw-r--r--src/server/game/Server/Packets/BlackMarketPackets.h4
-rw-r--r--src/server/game/Server/Packets/GuildFinderPackets.cpp2
-rw-r--r--src/server/game/Server/Packets/MovementPackets.cpp23
-rw-r--r--src/server/game/Server/Packets/MovementPackets.h32
-rw-r--r--src/server/game/Server/Packets/PetPackets.cpp21
-rw-r--r--src/server/game/Server/Packets/PetPackets.h13
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp10
-rw-r--r--src/server/game/Server/WorldSession.cpp10
-rw-r--r--src/server/game/Server/WorldSession.h2
-rw-r--r--src/server/game/Spells/Auras/SpellAuraDefines.h31
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp107
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.h4
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp4
-rw-r--r--src/server/game/Spells/Spell.cpp24
-rw-r--r--src/server/game/Spells/SpellEffects.cpp26
-rw-r--r--src/server/game/Spells/SpellHistory.cpp25
-rw-r--r--src/server/game/Spells/SpellInfo.cpp5
-rw-r--r--src/server/game/World/World.cpp8
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()