From 6e9ec1a4bfba7712728170dc33416cb2cf1af0ee Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Sat, 18 Jun 2022 18:37:14 +0200 Subject: [PATCH] Core/Transports: undo all custom transport changes as preparation for cherry picks --- .../Implementation/CharacterDatabase.cpp | 8 +- src/server/game/Battlefield/Battlefield.cpp | 28 +- .../game/Battlegrounds/Battleground.cpp | 31 +- src/server/game/Battlegrounds/Battleground.h | 6 +- .../game/Battlegrounds/Zones/BattlegroundIC.h | 4 +- .../Battlegrounds/Zones/BattlegroundSA.cpp | 36 +- .../game/Entities/GameObject/GameObject.cpp | 233 ++++-- .../game/Entities/GameObject/GameObject.h | 25 +- src/server/game/Entities/Object/Object.cpp | 73 +- src/server/game/Entities/Object/Object.h | 3 - .../game/Entities/Object/ObjectGuid.cpp | 2 + src/server/game/Entities/Object/ObjectGuid.h | 27 +- src/server/game/Entities/Pet/Pet.cpp | 45 -- src/server/game/Entities/Player/Player.cpp | 189 ++--- src/server/game/Entities/Player/Player.h | 12 +- .../game/Entities/Transport/Transport.cpp | 669 ++++-------------- .../game/Entities/Transport/Transport.h | 99 +-- .../game/Entities/Vehicle/VehicleDefines.h | 1 + src/server/game/Events/GameEventMgr.cpp | 7 +- src/server/game/Globals/ObjectAccessor.cpp | 20 +- src/server/game/Globals/ObjectAccessor.h | 4 +- src/server/game/Globals/ObjectMgr.cpp | 17 +- src/server/game/Globals/ObjectMgr.h | 2 - .../game/Grids/Notifiers/GridNotifiers.cpp | 2 +- src/server/game/Grids/ObjectGridLoader.cpp | 28 - src/server/game/Handlers/CharacterHandler.cpp | 21 - src/server/game/Handlers/MovementHandler.cpp | 21 +- src/server/game/Maps/Map.cpp | 35 +- src/server/game/Maps/Map.h | 4 +- src/server/game/Maps/MapScripts.cpp | 6 + src/server/game/Maps/TransportMgr.cpp | 77 +- src/server/game/Maps/TransportMgr.h | 123 ++-- src/server/game/Miscellaneous/SharedDefines.h | 2 +- src/server/game/Pools/PoolMgr.cpp | 7 +- src/server/game/Spells/SpellEffects.cpp | 34 +- src/server/scripts/Commands/cs_debug.cpp | 2 +- src/server/scripts/Commands/cs_gobject.cpp | 22 +- src/server/scripts/Commands/cs_group.cpp | 4 +- src/server/scripts/Commands/cs_misc.cpp | 12 +- src/server/scripts/Commands/cs_npc.cpp | 2 +- .../halls_of_origination.cpp | 3 +- .../HallsOfReflection/halls_of_reflection.cpp | 4 +- .../instance_halls_of_reflection.cpp | 6 +- .../boss_icecrown_gunship_battle.cpp | 32 +- .../instance_icecrown_citadel.cpp | 33 +- .../scripts/World/world_map_scripts.cpp | 66 -- 46 files changed, 618 insertions(+), 1469 deletions(-) diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index bd042ae94e..562ef7b412 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp @@ -65,7 +65,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() "position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, " "resettalents_time, talentTree, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, instance_mode_mask, " "totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, health, power1, power2, power3, power4, power5, instance_id, talentGroupsCount, activeTalentGroup, " - "exploredZones, equipmentCache, knownTitles, actionBars, grantableLevels, fishingSteps, trans_spawn_id " + "exploredZones, equipmentCache, knownTitles, actionBars, grantableLevels, fishingSteps " "FROM characters c LEFT JOIN character_fishingsteps cfs ON c.guid = cfs.guid WHERE c.guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_GROUP_MEMBER, "SELECT guid FROM group_member WHERE memberGuid = ?", CONNECTION_BOTH); @@ -379,16 +379,16 @@ void CharacterDatabaseConnection::DoPrepareStatements() // Player saving PrepareStatement(CHAR_INS_CHARACTER, "INSERT INTO characters (guid, account, name, race, class, gender, level, xp, money, skin, face, hairStyle, hairColor, facialStyle, bankSlots, restState, playerFlags, " - "map, instance_id, instance_mode_mask, position_x, position_y, position_z, orientation, trans_x, trans_y, trans_z, trans_o, transguid, trans_spawn_id, " + "map, instance_id, instance_mode_mask, position_x, position_y, position_z, orientation, trans_x, trans_y, trans_z, trans_o, transguid, " "taximask, cinematic, " "totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, talentTree, " "extra_flags, stable_slots, at_login, zone, " "death_expire_time, taxi_path, totalKills, " "todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, health, power1, power2, power3, " "power4, power5, latency, talentGroupsCount, activeTalentGroup, exploredZones, equipmentCache, knownTitles, actionBars, grantableLevels, achievementPoints) VALUES " - "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", CONNECTION_ASYNC); + "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_CHARACTER, "UPDATE characters SET name=?,race=?,class=?,gender=?,level=?,xp=?,money=?,skin=?,face=?,hairStyle=?,hairColor=?,facialStyle=?,bankSlots=?,restState=?,playerFlags=?," - "map=?,instance_id=?,instance_mode_mask=?,position_x=?,position_y=?,position_z=?,orientation=?,trans_x=?,trans_y=?,trans_z=?,trans_o=?,transguid=?, trans_spawn_id=?,taximask=?,cinematic=?," + "map=?,instance_id=?,instance_mode_mask=?,position_x=?,position_y=?,position_z=?,orientation=?,trans_x=?,trans_y=?,trans_z=?,trans_o=?,transguid=?,taximask=?,cinematic=?," "totaltime=?,leveltime=?,rest_bonus=?,logout_time=?,is_logout_resting=?,resettalents_cost=?,resettalents_time=?,talentTree=?,extra_flags=?,stable_slots=?,at_login=?,zone=?,death_expire_time=?,taxi_path=?," "totalKills=?,todayKills=?,yesterdayKills=?,chosenTitle=?," "watchedFaction=?,drunk=?,health=?,power1=?,power2=?,power3=?,power4=?,power5=?,latency=?,talentGroupsCount=?,activeTalentGroup=?,exploredZones=?," diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp index 77532b4aa0..ba2adfc23b 100644 --- a/src/server/game/Battlefield/Battlefield.cpp +++ b/src/server/game/Battlefield/Battlefield.cpp @@ -32,7 +32,6 @@ #include "MiscPackets.h" #include "ObjectAccessor.h" #include "ObjectMgr.h" -#include "Transport.h" #include "WorldPacket.h" #include "WorldSession.h" #include @@ -787,28 +786,13 @@ Creature* Battlefield::SpawnCreature(uint32 entry, Position const& pos) GameObject* Battlefield::SpawnGameObject(uint32 entry, Position const& pos, QuaternionData const& rot) { // Create gameobject - GameObject* go = nullptr; - if (sObjectMgr->GetGameObjectTypeByEntry(entry) == GAMEOBJECT_TYPE_TRANSPORT) + GameObject* go = new GameObject; + if (!go->Create(m_Map->GenerateLowGuid(), entry, m_Map, pos, rot, 255, GO_STATE_READY)) { - go = new Transport(); - if (!go->Create(m_Map->GenerateLowGuid(), entry, m_Map, pos, rot, 255, GO_STATE_READY)) - { - TC_LOG_ERROR("bg.battlefield", "Battlefield::SpawnGameObject: Gameobject template %u could not be found in the database! Battlefield has not been created!", entry); - TC_LOG_ERROR("bg.battlefield", "Battlefield::SpawnGameObject: Could not create gameobject template %u! Battlefield has not been created!", entry); - delete go; - return nullptr; - } - } - else - { - go = new GameObject(); - if (!go->Create(m_Map->GenerateLowGuid(), entry, m_Map, pos, rot, 255, GO_STATE_READY)) - { - TC_LOG_ERROR("bg.battlefield", "Battlefield::SpawnGameObject: Gameobject template %u could not be found in the database! Battlefield has not been created!", entry); - TC_LOG_ERROR("bg.battlefield", "Battlefield::SpawnGameObject: Could not create gameobject template %u! Battlefield has not been created!", entry); - delete go; - return nullptr; - } + TC_LOG_ERROR("bg.battlefield", "Battlefield::SpawnGameObject: Gameobject template %u could not be found in the database! Battlefield has not been created!", entry); + TC_LOG_ERROR("bg.battlefield", "Battlefield::SpawnGameObject: Could not create gameobject template %u! Battlefield has not been created!", entry); + delete go; + return nullptr; } // Add to world diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index 22ffbbc28d..63419ae54b 100644 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -1457,28 +1457,13 @@ bool Battleground::AddObject(uint32 type, uint32 entry, float x, float y, float // Must be created this way, adding to godatamap would add it to the base map of the instance // 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 = nullptr; - if (sObjectMgr->GetGameObjectTypeByEntry(entry) == GAMEOBJECT_TYPE_TRANSPORT) + GameObject* go = new GameObject; + if (!go->Create(GetBgMap()->GenerateLowGuid(), entry, GetBgMap(), Position(x, y, z, o), rot, 255, goState)) { - go = new Transport(); - if (!go->Create(GetBgMap()->GenerateLowGuid(), entry, GetBgMap(), Position(x, y, z, o), rot, 255, goState)) - { - TC_LOG_ERROR("bg.battleground", "Battleground::AddObject: cannot create transport (entry: %u) for BG (map: %u, instance id: %u)!", - entry, m_MapId, m_InstanceID); - delete go; - return false; - } - } - else - { - go = new GameObject(); - if (!go->Create(GetBgMap()->GenerateLowGuid(), entry, GetBgMap(), Position(x, y, z, o), rot, 255, 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); - delete go; - return false; - } + TC_LOG_ERROR("bg.battleground", "Battleground::AddObject: cannot create gameobject (entry: %u) for BG (map: %u, instance id: %u)!", + entry, m_MapId, m_InstanceID); + delete go; + return false; } /* @@ -1594,7 +1579,7 @@ void Battleground::SpawnBGObject(uint32 type, uint32 respawntime) } } -Creature* Battleground::AddCreature(uint32 entry, uint32 type, float x, float y, float z, float o, TeamId /*teamId = TEAM_NEUTRAL*/, uint32 respawntime /*= 0*/, MapTransport* transport) +Creature* Battleground::AddCreature(uint32 entry, uint32 type, float x, float y, float z, float o, TeamId /*teamId = TEAM_NEUTRAL*/, uint32 respawntime /*= 0*/, Transport* transport) { // If the assert is called, means that BgCreatures must be resized! ASSERT(type < BgCreatures.size()); @@ -1648,7 +1633,7 @@ Creature* Battleground::AddCreature(uint32 entry, uint32 type, float x, float y, return creature; } -Creature* Battleground::AddCreature(uint32 entry, uint32 type, Position const& pos, TeamId teamId /*= TEAM_NEUTRAL*/, uint32 respawntime /*= 0*/, MapTransport* transport) +Creature* Battleground::AddCreature(uint32 entry, uint32 type, Position const& pos, TeamId teamId /*= TEAM_NEUTRAL*/, uint32 respawntime /*= 0*/, Transport* transport) { return AddCreature(entry, type, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teamId, respawntime, transport); } diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h index 6c5f60a318..f52e4ef218 100644 --- a/src/server/game/Battlegrounds/Battleground.h +++ b/src/server/game/Battlegrounds/Battleground.h @@ -30,7 +30,7 @@ class Creature; class GameObject; class Group; class Player; -class MapTransport; +class Transport; class Unit; class WorldObject; class WorldPacket; @@ -465,8 +465,8 @@ class TC_GAME_API Battleground void SpawnBGObject(uint32 type, uint32 respawntime); virtual bool AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime = 0, GOState goState = GO_STATE_READY); bool AddObject(uint32 type, uint32 entry, Position const& pos, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime = 0, GOState goState = GO_STATE_READY); - virtual Creature* AddCreature(uint32 entry, uint32 type, float x, float y, float z, float o, TeamId teamId = TEAM_NEUTRAL, uint32 respawntime = 0, MapTransport* transport = nullptr); - Creature* AddCreature(uint32 entry, uint32 type, Position const& pos, TeamId teamId = TEAM_NEUTRAL, uint32 respawntime = 0, MapTransport* transport = nullptr); + virtual Creature* AddCreature(uint32 entry, uint32 type, float x, float y, float z, float o, TeamId teamId = TEAM_NEUTRAL, uint32 respawntime = 0, Transport* transport = nullptr); + Creature* AddCreature(uint32 entry, uint32 type, Position const& pos, TeamId teamId = TEAM_NEUTRAL, uint32 respawntime = 0, Transport* transport = nullptr); bool DelCreature(uint32 type); bool DelObject(uint32 type); virtual bool AddSpiritGuide(uint32 type, float x, float y, float z, float o, TeamId teamId = TEAM_NEUTRAL); diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.h b/src/server/game/Battlegrounds/Zones/BattlegroundIC.h index 06203dcb35..ea5ad25a4f 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.h @@ -992,8 +992,8 @@ class BattlegroundIC : public Battleground BG_IC_GateState GateStatus[6]; ICNodePoint nodePoint[7]; - MapTransport* gunshipAlliance; - MapTransport* gunshipHorde; + Transport* gunshipAlliance; + Transport* gunshipHorde; uint32 GetNextBanner(ICNodePoint* node, uint32 team, bool returnDefinitve); diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp index 441ac41c38..3452db0a34 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp @@ -25,7 +25,6 @@ #include "ObjectMgr.h" #include "Player.h" #include "ScriptedCreature.h" -#include "Transport.h" #include "UpdateData.h" #include "WorldPacket.h" #include "WorldStatePackets.h" @@ -282,9 +281,10 @@ bool BattlegroundSA::ResetObjs() UpdateWorldState(BG_SA_YELLOW_GATEWS, 1); UpdateWorldState(BG_SA_ANCIENT_GATEWS, 1); - for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) - if (Player* player = ObjectAccessor::FindPlayer(itr->first)) - SendTransportInit(player); + for (int i = BG_SA_BOAT_ONE; i <= BG_SA_BOAT_TWO; i++) + for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) + if (Player* player = ObjectAccessor::FindPlayer(itr->first)) + SendTransportInit(player); // set status manually so preparation is cast correctly in 2nd round too SetStatus(STATUS_WAIT_JOIN); @@ -298,27 +298,23 @@ void BattlegroundSA::StartShips() if (ShipsStarted) return; - for (uint8 i = BG_SA_BOAT_ONE; i <= BG_SA_BOAT_TWO; ++i) - if (GameObject* obj = GetBGObject(i)) - if (Transport* transport = obj->ToTransport()) - transport->SetTransportState(GO_STATE_TRANSPORT_STOPPED, 1); + DoorOpen(BG_SA_BOAT_ONE); + DoorOpen(BG_SA_BOAT_TWO); - for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) + for (int i = BG_SA_BOAT_ONE; i <= BG_SA_BOAT_TWO; i++) { - if (Player* p = ObjectAccessor::FindPlayer(itr->first)) + for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) { - UpdateData data(GetMapId()); - - for (uint8 i = BG_SA_BOAT_ONE; i <= BG_SA_BOAT_TWO; ++i) - if (GameObject* obj = GetBGObject(i)) - obj->BuildValuesUpdateBlockForPlayer(&data, p); - - WorldPacket pkt; - data.BuildPacket(&pkt); - p->SendDirectMessage(&pkt); + if (Player* p = ObjectAccessor::FindPlayer(itr->first)) + { + UpdateData data(p->GetMapId()); + WorldPacket pkt; + GetBGObject(i)->BuildValuesUpdateBlockForPlayer(&data, p); + data.BuildPacket(&pkt); + p->SendDirectMessage(&pkt); + } } } - ShipsStarted = true; } diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 1fef4bc707..9cf04c8463 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -153,6 +153,8 @@ GameObject::~GameObject() { delete m_AI; delete m_model; + if (m_goInfo && m_goInfo->type == GAMEOBJECT_TYPE_TRANSPORT) + delete m_goValue.Transport.StopFrames; //if (m_uint32Values) // field array can be not exist if GameOBject not loaded // CleanupsBeforeDelete(); } @@ -224,7 +226,7 @@ void GameObject::AddToWorld() bool toggledState = GetGoType() == GAMEOBJECT_TYPE_CHEST ? getLootState() == GO_READY : (GetGoState() == GO_STATE_READY || IsTransport()); if (m_model) { - if (MapTransport* trans = ToMapTransport()) + if (Transport* trans = ToTransport()) trans->SetDelayedAddModelToMap(); else GetMap()->InsertGameObjectModel(*m_model); @@ -300,6 +302,9 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, P return false; } + if (goinfo->type == GAMEOBJECT_TYPE_TRANSPORT) + m_updateFlag |= UPDATEFLAG_TRANSPORT; + Object::_Create(guidlow, goinfo->entry, HighGuid::GameObject); m_goInfo = goinfo; @@ -356,6 +361,36 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, P SetGoAnimProgress(255); SetUInt32Value(GAMEOBJECT_PARENTROTATION, m_goInfo->building.destructibleData); break; + case GAMEOBJECT_TYPE_TRANSPORT: + { + m_goValue.Transport.AnimationInfo = sTransportMgr->GetTransportAnimInfo(goinfo->entry); + m_goValue.Transport.PathProgress = getMSTime(); + if (m_goValue.Transport.AnimationInfo) + m_goValue.Transport.PathProgress -= m_goValue.Transport.PathProgress % GetTransportPeriod(); // align to period + m_goValue.Transport.CurrentSeg = 0; + m_goValue.Transport.StateUpdateTimer = 0; + m_goValue.Transport.StopFrames = new std::vector(); + + if (goinfo->transport.Timeto2ndfloor > 0) + { + if (!goinfo->transport.startOpen) + m_goValue.Transport.StopFrames->push_back(0); + m_goValue.Transport.StopFrames->push_back(goinfo->transport.Timeto2ndfloor); + } + if (goinfo->transport.Timeto3rdfloor > 0) + m_goValue.Transport.StopFrames->push_back(goinfo->transport.Timeto3rdfloor); + if (goinfo->transport.Timeto4thfloor > 0) + m_goValue.Transport.StopFrames->push_back(goinfo->transport.Timeto4thfloor); + if (goinfo->transport.Timeto5thfloor > 0) + m_goValue.Transport.StopFrames->push_back(goinfo->transport.Timeto5thfloor); + if (goinfo->transport.startOpen) + SetTransportState(GO_STATE_TRANSPORT_STOPPED, goinfo->transport.startOpen - 1); + else + SetTransportState(GO_STATE_TRANSPORT_ACTIVE); + + SetGoAnimProgress(animprogress); + break; + } case GAMEOBJECT_TYPE_FISHINGNODE: SetGoAnimProgress(0); break; @@ -461,6 +496,53 @@ void GameObject::Update(uint32 diff) SetLootState(GO_READY); break; } + case GAMEOBJECT_TYPE_TRANSPORT: + { + if (!m_goValue.Transport.AnimationInfo) + break; + + if (GetGoState() == GO_STATE_TRANSPORT_ACTIVE) + { + m_goValue.Transport.PathProgress += diff; + /* TODO: Fix movement in unloaded grid - currently GO will just disappear + uint32 timer = m_goValue.Transport.PathProgress % GetTransportPeriod(); + TransportAnimationEntry const* node = m_goValue.Transport.AnimationInfo->GetAnimNode(timer); + if (node && m_goValue.Transport.CurrentSeg != node->TimeSeg) + { + m_goValue.Transport.CurrentSeg = node->TimeSeg; + + G3D::Quat rotation; + if (TransportRotationEntry const* rot = m_goValue.Transport.AnimationInfo->GetAnimRotation(timer)) + rotation = G3D::Quat(rot->X, rot->Y, rot->Z, rot->W); + + G3D::Vector3 pos = rotation.toRotationMatrix() + * G3D::Matrix3::fromEulerAnglesZYX(GetOrientation(), 0.0f, 0.0f) + * G3D::Vector3(node->X, node->Y, node->Z); + + pos += G3D::Vector3(GetStationaryX(), GetStationaryY(), GetStationaryZ()); + + G3D::Vector3 src(GetPositionX(), GetPositionY(), GetPositionZ()); + + TC_LOG_DEBUG("misc", "Src: %s Dest: %s", src.toString().c_str(), pos.toString().c_str()); + + GetMap()->GameObjectRelocation(this, pos.x, pos.y, pos.z, GetOrientation()); + } + */ + + if (!m_goValue.Transport.StopFrames->empty()) + { + uint32 visualStateBefore = (m_goValue.Transport.StateUpdateTimer / 20000) & 1; + m_goValue.Transport.StateUpdateTimer += diff; + uint32 visualStateAfter = (m_goValue.Transport.StateUpdateTimer / 20000) & 1; + if (visualStateBefore != visualStateAfter) + { + ForceValuesUpdateAtIndex(GAMEOBJECT_LEVEL); + ForceValuesUpdateAtIndex(GAMEOBJECT_BYTES_1); + } + } + } + break; + } case GAMEOBJECT_TYPE_FISHINGNODE: { // fishing code (bobber ready) @@ -1009,11 +1091,7 @@ bool GameObject::LoadFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap m_spawnId = spawnId; m_respawnCompatibilityMode = ((data->spawnGroupData->flags & SPAWNGROUP_FLAG_COMPATIBILITY_MODE) != 0); - - uint32 gameObjectType = sObjectMgr->GetGameObjectTypeByEntry(entry); - ObjectGuid::LowType lowGuid = gameObjectType == GAMEOBJECT_TYPE_TRANSPORT ? map->GenerateLowGuid() : map->GenerateLowGuid(); - - if (!Create(lowGuid, entry, map, data->spawnPoint, data->rotation, animprogress, go_state, artKit, !m_respawnCompatibilityMode)) + if (!Create(map->GenerateLowGuid(), entry, map, data->spawnPoint, data->rotation, animprogress, go_state, artKit, !m_respawnCompatibilityMode)) return false; PhasingHandler::InitDbPhaseShift(GetPhaseShift(), data->phaseUseFlags, data->phaseId, data->phaseGroup); @@ -2421,6 +2499,48 @@ void GameObject::SetGoState(GOState state) } } +uint32 GameObject::GetTransportPeriod() const +{ + ASSERT(GetGOInfo()->type == GAMEOBJECT_TYPE_TRANSPORT); + if (m_goValue.Transport.AnimationInfo) + return m_goValue.Transport.AnimationInfo->TotalTime; + + // return something that will nicely divide for GAMEOBJECT_DYNAMIC value calculation + return m_goValue.Transport.PathProgress; +} + +void GameObject::SetTransportState(GOState state, uint32 stopFrame /*= 0*/) +{ + if (GetGoState() == state) + return; + + ASSERT(GetGOInfo()->type == GAMEOBJECT_TYPE_TRANSPORT); + ASSERT(state >= GO_STATE_TRANSPORT_ACTIVE); + if (state == GO_STATE_TRANSPORT_ACTIVE) + { + m_goValue.Transport.StateUpdateTimer = 0; + m_goValue.Transport.PathProgress = getMSTime(); + if (GetGoState() >= GO_STATE_TRANSPORT_STOPPED) + m_goValue.Transport.PathProgress += m_goValue.Transport.StopFrames->at(GetGoState() - GO_STATE_TRANSPORT_STOPPED); + SetGoState(GO_STATE_TRANSPORT_ACTIVE); + } + else + { + ASSERT(state < GOState(GO_STATE_TRANSPORT_STOPPED + MAX_GO_STATE_TRANSPORT_STOP_FRAMES)); + ASSERT(stopFrame < m_goValue.Transport.StopFrames->size()); + + uint32 stopFrameTime = m_goValue.Transport.StopFrames->at(stopFrame); + if (!stopFrameTime) // returning to a previous stop frame that has no travel time (e.g. stop frame at 0ms) + stopFrameTime = m_goValue.Transport.StopFrames->at(stopFrame + 1); + + m_goValue.Transport.PathProgress = getMSTime() + stopFrameTime; + SetGoState(GOState(GO_STATE_TRANSPORT_STOPPED + stopFrame)); + } + + ForceValuesUpdateAtIndex(GAMEOBJECT_LEVEL); + ForceValuesUpdateAtIndex(GAMEOBJECT_BYTES_1); +} + void GameObject::SetDisplayId(uint32 displayid) { SetUInt32Value(GAMEOBJECT_DISPLAYID, displayid); @@ -2519,6 +2639,7 @@ void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* t if (!target) return; + bool isStoppableTransport = GetGoType() == GAMEOBJECT_TYPE_TRANSPORT && !m_goValue.Transport.StopFrames->empty(); bool forcedFlags = GetGoType() == GAMEOBJECT_TYPE_CHEST && GetGOInfo()->chest.groupLootRules && HasLootRecipient(); bool targetIsGM = target->IsGameMaster(); @@ -2561,12 +2682,16 @@ void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* t dynFlags |= GO_DYNFLAG_LO_SPARKLE; break; case GAMEOBJECT_TYPE_TRANSPORT: + { + float timer = float(m_goValue.Transport.PathProgress % GetTransportPeriod()); + pathProgress = int16(timer / float(GetTransportPeriod()) * 65535.0f); + break; + } case GAMEOBJECT_TYPE_MO_TRANSPORT: { - Transport const* transport = ToTransport(); - if (uint32 transportPeriod = transport->GetTransportPeriod()) + if (uint32 transportPeriod = GetTransportPeriod()) { - float timer = float(transport->GetTimer() % transportPeriod); + float timer = float(m_goValue.Transport.PathProgress % transportPeriod); pathProgress = int16(timer / float(transportPeriod) * 65535.0f); } break; @@ -2587,6 +2712,27 @@ void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* t fieldBuffer << goFlags; } + else if (index == GAMEOBJECT_LEVEL) + { + if (isStoppableTransport) + fieldBuffer << uint32(m_goValue.Transport.PathProgress); + else + fieldBuffer << m_uint32Values[index]; + } + else if (index == GAMEOBJECT_BYTES_1) + { + uint32 bytes1 = m_uint32Values[index]; + if (isStoppableTransport && GetGoState() == GO_STATE_TRANSPORT_ACTIVE) + { + if ((m_goValue.Transport.StateUpdateTimer / 20000) & 1) + { + bytes1 &= 0xFFFFFF00; + bytes1 |= GO_STATE_TRANSPORT_STOPPED; + } + } + + fieldBuffer << bytes1; + } else fieldBuffer << m_uint32Values[index]; // other cases } @@ -2687,75 +2833,6 @@ GameObjectModel* GameObject::CreateModel() return GameObjectModel::Create(Trinity::make_unique(this), sWorld->GetDataPath()); } -float GameObject::GetStationaryX() const -{ - if (GetGOInfo()->type == GAMEOBJECT_TYPE_MO_TRANSPORT) - return GetPositionX(); - - return m_stationaryPosition.GetPositionX(); -} - -float GameObject::GetStationaryY() const -{ - if (GetGOInfo()->type == GAMEOBJECT_TYPE_MO_TRANSPORT) - return GetPositionY(); - - return m_stationaryPosition.GetPositionY(); -} - -float GameObject::GetStationaryZ() const -{ - if (GetGOInfo()->type == GAMEOBJECT_TYPE_MO_TRANSPORT) - return GetPositionZ(); - - return m_stationaryPosition.GetPositionZ(); -} - -float GameObject::GetStationaryO() const -{ - if (IsTransport()) - return GetOrientation(); - - return m_stationaryPosition.GetOrientation(); -} - -void GameObject::RelocateStationaryPosition(float x, float y, float z, float o) -{ - m_stationaryPosition.Relocate(x, y, z, o); -} - -Transport* GameObject::ToTransport() -{ - if (IsTransport()) - return reinterpret_cast(this); - - return nullptr; -} - -Transport const* GameObject::ToTransport() const -{ - if (IsTransport()) - return reinterpret_cast(this); - - return nullptr; -} - -MapTransport* GameObject::ToMapTransport() -{ - if (GetGOInfo()->type == GAMEOBJECT_TYPE_MO_TRANSPORT) - return reinterpret_cast(this); - - return nullptr; -} - -MapTransport const* GameObject::ToMapTransport() const -{ - if (GetGOInfo()->type == GAMEOBJECT_TYPE_MO_TRANSPORT) - return reinterpret_cast(this); - - return nullptr; -} - bool GameObject::IsAtInteractDistance(Player const* player, SpellInfo const* spell) const { if (spell || (spell = GetSpellForLock(player))) diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index 3848b99405..afe49e8fc6 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -42,7 +42,9 @@ union GameObjectValue { uint32 PathProgress; TransportAnimation const* AnimationInfo; + uint32 CurrentSeg; std::vector* StopFrames; + uint32 StateUpdateTimer; } Transport; //25 GAMEOBJECT_TYPE_FISHINGHOLE struct @@ -89,7 +91,7 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject void RemoveFromWorld() override; void CleanupsBeforeDelete(bool finalCleanup = true) override; - virtual bool Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, Position const& pos, QuaternionData const& rotation, uint32 animprogress, GOState go_state, uint32 artKit = 0, bool dynamic = false, ObjectGuid::LowType spawnid = 0); + bool Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, Position const& pos, QuaternionData const& rotation, uint32 animprogress, GOState go_state, uint32 artKit = 0, bool dynamic = false, ObjectGuid::LowType spawnid = 0); void Update(uint32 p_time) override; GameObjectTemplate const* GetGOInfo() const { return m_goInfo; } GameObjectTemplateAddon const* GetTemplateAddon() const { return m_goTemplateAddon; } @@ -163,6 +165,8 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject void SetGoType(GameobjectTypes type) { SetByteValue(GAMEOBJECT_BYTES_1, 1, type); } GOState GetGoState() const { return GOState(GetByteValue(GAMEOBJECT_BYTES_1, 0)); } void SetGoState(GOState state); + virtual uint32 GetTransportPeriod() const; + void SetTransportState(GOState state, uint32 stopFrame = 0); uint8 GetGoArtKit() const { return GetByteValue(GAMEOBJECT_BYTES_1, 2); } void SetGoArtKit(uint8 artkit); uint8 GetGoAnimProgress() const { return GetByteValue(GAMEOBJECT_BYTES_1, 3); } @@ -275,17 +279,14 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject GameObjectModel* m_model; void GetRespawnPosition(float &x, float &y, float &z, float* ori = nullptr) const; - Transport* ToTransport(); - Transport const* ToTransport() const; + Transport* ToTransport() { if (GetGOInfo()->type == GAMEOBJECT_TYPE_MO_TRANSPORT) return reinterpret_cast(this); else return nullptr; } + Transport const* ToTransport() const { if (GetGOInfo()->type == GAMEOBJECT_TYPE_MO_TRANSPORT) return reinterpret_cast(this); else return nullptr; } - MapTransport* ToMapTransport(); - MapTransport const* ToMapTransport() const; - - float GetStationaryX() const override; - float GetStationaryY() const override; - float GetStationaryZ() const override; - float GetStationaryO() const override; - void RelocateStationaryPosition(float x, float y, float z, float o); + float GetStationaryX() const override { if (GetGOInfo()->type != GAMEOBJECT_TYPE_MO_TRANSPORT) return m_stationaryPosition.GetPositionX(); return GetPositionX(); } + float GetStationaryY() const override { if (GetGOInfo()->type != GAMEOBJECT_TYPE_MO_TRANSPORT) return m_stationaryPosition.GetPositionY(); return GetPositionY(); } + float GetStationaryZ() const override { if (GetGOInfo()->type != GAMEOBJECT_TYPE_MO_TRANSPORT) return m_stationaryPosition.GetPositionZ(); return GetPositionZ(); } + float GetStationaryO() const override { if (GetGOInfo()->type != GAMEOBJECT_TYPE_MO_TRANSPORT) return m_stationaryPosition.GetOrientation(); return GetOrientation(); } + void RelocateStationaryPosition(float x, float y, float z, float o) { m_stationaryPosition.Relocate(x, y, z, o); } float GetInteractionDistance() const; @@ -302,8 +303,6 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject void AIM_Destroy(); bool AIM_Initialize(); - void SetSpawnId(uint32 spawnId) { m_spawnId = spawnId; } - protected: GameObjectModel* CreateModel(); void UpdateModel(); // updates model in case displayId were changed diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index e53db7197a..3b6cca8b91 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -659,15 +659,16 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint32 flags) const if (flags & UPDATEFLAG_TRANSPORT) { - if (GameObject const* go = ToGameObject()) - { - if (MapTransport const* transport = go->ToMapTransport()) - *data << uint32(transport->GetTimer()); - else if (Transport const* transport = go->ToTransport()) - *data << uint32(transport->IsDynamicTransport() ? transport->GetTimer() : getMSTime()); - else - *data << uint32(getMSTime()); - } + GameObject const* go = ToGameObject(); + /** @TODO Use IsTransport() to also handle type 11 (TRANSPORT) + Currently grid objects are not updated if there are no nearby players, + this causes clients to receive different PathProgress + resulting in players seeing the object in a different position + */ + if (go && go->ToTransport()) + *data << uint32(go->GetGOValue()->Transport.PathProgress); + else + *data << uint32(GameTime::GetGameTimeMS()); } } @@ -2094,20 +2095,6 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonCreatur return nullptr; } - // Add summon to transport if summoner is on a transport as well - if (summon->GetTransGUID().IsEmpty() && summonArgs.Summoner) - { - if (Transport* transport = summonArgs.Summoner->GetTransport()) - { - float x, y, z, o; - pos.GetPosition(x, y, z, o); - transport->CalculatePassengerOffset(x, y, z, &o); - summon->m_movementInfo.transport.pos.Relocate(x, y, z, o); - - transport->AddPassenger(summon); - } - } - // Inherit summoner's Phaseshift if (summonArgs.Summoner) PhasingHandler::InheritPhaseShift(summon, summonArgs.Summoner); @@ -2221,24 +2208,11 @@ GameObject* WorldObject::SummonGameObject(uint32 entry, Position const& pos, Qua } Map* map = GetMap(); - GameObject* go = nullptr; - if (goinfo->type == GAMEOBJECT_TYPE_TRANSPORT) + GameObject* go = new GameObject(); + if (!go->Create(map->GenerateLowGuid(), entry, map, pos, rot, 255, GO_STATE_READY)) { - go = new Transport(); - if (!go->Create(map->GenerateLowGuid(), entry, map, pos, rot, 255, GO_STATE_READY)) - { - delete go; - return nullptr; - } - } - else - { - go = new GameObject(); - if (!go->Create(map->GenerateLowGuid(), entry, map, pos, rot, 255, GO_STATE_READY)) - { - delete go; - return nullptr; - } + delete go; + return nullptr; } PhasingHandler::InheritPhaseShift(go, this); @@ -2249,17 +2223,6 @@ GameObject* WorldObject::SummonGameObject(uint32 entry, Position const& pos, Qua else go->SetSpawnedByDefault(false); - Transport* transport = GetTransGUID().IsEmpty() ? GetTransport() : nullptr; - if (transport) - { - float x, y, z, o; - go->GetPosition(x, y, z, o); - transport->CalculatePassengerOffset(x, y, z, &o); - go->m_movementInfo.transport.pos.Relocate(x, y, z, o); - - transport->AddPassenger(go); - } - map->AddToMap(go); return go; } @@ -2789,14 +2752,6 @@ ObjectGuid WorldObject::GetTransGUID() const return ObjectGuid::Empty; } -MapTransport* WorldObject::GetMapTransport() const -{ - if (GetTransport()) - return GetTransport()->ToMapTransport(); - - return nullptr; -} - float WorldObject::GetFloorZ() const { if (!IsInWorld()) diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index e7e6aff6c8..19c71d60f8 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -47,7 +47,6 @@ class Map; class Player; class TempSummon; class Transport; -class MapTransport; class Unit; class UpdateData; class WorldObject; @@ -468,8 +467,6 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation virtual ObjectGuid GetTransGUID() const; void SetTransport(Transport* t) { m_transport = t; } - MapTransport* GetMapTransport() const; - MovementInfo m_movementInfo; virtual float GetStationaryX() const { return GetPositionX(); } diff --git a/src/server/game/Entities/Object/ObjectGuid.cpp b/src/server/game/Entities/Object/ObjectGuid.cpp index 7628a5ef86..c4520bda12 100644 --- a/src/server/game/Entities/Object/ObjectGuid.cpp +++ b/src/server/game/Entities/Object/ObjectGuid.cpp @@ -52,6 +52,7 @@ char const* ObjectGuid::GetTypeName(HighGuid high) case HighGuid::Corpse: return "Corpse"; case HighGuid::AreaTrigger: return "AreaTrigger"; case HighGuid::BattleGround: return "Battleground"; + case HighGuid::Mo_Transport: return "MoTransport"; case HighGuid::Instance: return "InstanceID"; case HighGuid::Group: return "Group"; case HighGuid::Guild: return "Guild"; @@ -131,5 +132,6 @@ GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Unit) GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Pet) GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Vehicle) GUID_TRAIT_INSTANTIATE_GUID(HighGuid::DynamicObject) +GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Mo_Transport) GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Instance) GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Group) diff --git a/src/server/game/Entities/Object/ObjectGuid.h b/src/server/game/Entities/Object/ObjectGuid.h index 18841f79ab..af892972c4 100644 --- a/src/server/game/Entities/Object/ObjectGuid.h +++ b/src/server/game/Entities/Object/ObjectGuid.h @@ -63,6 +63,7 @@ enum class HighGuid Container = 0x400, // blizz 4000 Player = 0x000, // blizz 0000 GameObject = 0xF11, // blizz F110 + Transport = 0xF12, // blizz F120 (for GAMEOBJECT_TYPE_TRANSPORT) Unit = 0xF13, // blizz F130 Pet = 0xF14, // blizz F140 Vehicle = 0xF15, // blizz F550 @@ -70,7 +71,7 @@ enum class HighGuid Corpse = 0xF101, // blizz F100 AreaTrigger = 0xF102, BattleGround = 0x1F1, - Transport = 0x1FC, // blizz 1FC0 + Mo_Transport = 0x1FC, // blizz 1FC0 (for GAMEOBJECT_TYPE_MO_TRANSPORT) Instance = 0x1F4, // blizz 1F40 Group = 0x1F5, Guild = 0x1FF @@ -97,11 +98,13 @@ struct ObjectGuidTraits static bool const MapSpecific = true; \ } +GUID_TRAIT_GLOBAL(HighGuid::Mo_Transport); GUID_TRAIT_GLOBAL(HighGuid::Group); GUID_TRAIT_GLOBAL(HighGuid::Instance); GUID_TRAIT_GLOBAL(HighGuid::BattleGround); GUID_TRAIT_GLOBAL(HighGuid::Player); GUID_TRAIT_GLOBAL(HighGuid::Item); +GUID_TRAIT_GLOBAL(HighGuid::Transport); GUID_TRAIT_GLOBAL(HighGuid::Guild); GUID_TRAIT_MAP_SPECIFIC(HighGuid::Unit); GUID_TRAIT_MAP_SPECIFIC(HighGuid::Vehicle); @@ -115,18 +118,6 @@ GUID_TRAIT_MAP_SPECIFIC(HighGuid::AreaTrigger); #undef GUID_TRAIT_REALM_SPECIFIC #undef GUID_TRAIT_MAP_SPECIFIC -// Special case -// Global transports are loaded from `transports` table, Global 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 -{ - static bool const Global = true; - static bool const MapSpecific = true; -}; - class ObjectGuid; class PackedGuid; @@ -147,7 +138,7 @@ class TC_GAME_API ObjectGuid static typename std::enable_if::Global, ObjectGuid>::type Create(LowType counter) { return Global(type, counter); } template - static typename std::enable_if::MapSpecific && type != HighGuid::Transport, ObjectGuid>::type Create(uint32 entry, LowType counter) { return MapSpecific(type, entry, counter); } + static typename std::enable_if::MapSpecific, ObjectGuid>::type Create(uint32 entry, LowType counter) { return MapSpecific(type, entry, counter); } ObjectGuid() { _data._guid = UI64LIT(0); } explicit ObjectGuid(uint64 guid) { _data._guid = guid; } @@ -205,7 +196,8 @@ class TC_GAME_API ObjectGuid bool IsAreaTrigger() const { return GetHigh() == HighGuid::AreaTrigger; } bool IsBattleground() const { return GetHigh() == HighGuid::BattleGround; } bool IsTransport() const { return GetHigh() == HighGuid::Transport; } - bool IsAnyTypeGameObject() const { return IsGameObject() || IsTransport(); } + bool IsMOTransport() const { return GetHigh() == HighGuid::Mo_Transport; } + bool IsAnyTypeGameObject() const { return IsGameObject() || IsTransport() || IsMOTransport(); } bool IsInstance() const { return GetHigh() == HighGuid::Instance; } bool IsGroup() const { return GetHigh() == HighGuid::Group; } bool IsGuild() const { return GetHigh() == HighGuid::Guild; } @@ -223,7 +215,7 @@ class TC_GAME_API ObjectGuid case HighGuid::DynamicObject: return TYPEID_DYNAMICOBJECT; case HighGuid::Corpse: return TYPEID_CORPSE; case HighGuid::AreaTrigger: return TYPEID_AREATRIGGER; - case HighGuid::Transport: return TYPEID_GAMEOBJECT; + case HighGuid::Mo_Transport: return TYPEID_GAMEOBJECT; case HighGuid::Vehicle: return TYPEID_UNIT; // unknown case HighGuid::Instance: @@ -254,11 +246,12 @@ class TC_GAME_API ObjectGuid case HighGuid::Player: case HighGuid::DynamicObject: case HighGuid::Corpse: - case HighGuid::Transport: + case HighGuid::Mo_Transport: case HighGuid::Instance: case HighGuid::Group: return false; case HighGuid::GameObject: + case HighGuid::Transport: case HighGuid::Unit: case HighGuid::Pet: case HighGuid::Vehicle: diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 0ab1389d6a..77b8cb24af 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -27,7 +27,6 @@ #include "SpellHistory.h" #include "SpellAuras.h" #include "SpellAuraEffects.h" -#include "Transport.h" #include "Unit.h" #include "Util.h" #include "Group.h" @@ -184,17 +183,6 @@ bool Pet::LoadPetData(Player* owner, uint32 petEntry, uint32 petnumber, bool cur return false; } - Transport* transport = GetTransGUID().IsEmpty() ? owner->GetTransport() : nullptr; - if (transport) - { - float x, y, z, o; - GetPosition(x, y, z, o); - transport->CalculatePassengerOffset(x, y, z, &o); - m_movementInfo.transport.pos.Relocate(x, y, z, o); - - transport->AddPassenger(this); - } - map->AddToMap(this->ToCreature()); return true; } @@ -282,17 +270,6 @@ bool Pet::LoadPetData(Player* owner, uint32 petEntry, uint32 petnumber, bool cur owner->SendMessageToSet(&data, true); } - Transport* transport = GetTransGUID().IsEmpty() ? owner->GetTransport() : nullptr; - if (transport) - { - float x, y, z, o; - GetPosition(x, y, z, o); - transport->CalculatePassengerOffset(x, y, z, &o); - m_movementInfo.transport.pos.Relocate(x, y, z, o); - - transport->AddPassenger(this); - } - owner->SetMinion(this, true); map->AddToMap(ToCreature()); @@ -689,17 +666,6 @@ bool Pet::CreateBaseAtCreature(Creature* creature) else SetName(creature->GetNameForLocaleIdx(sObjectMgr->GetDBCLocaleIndex())); - Transport* transport = GetTransGUID().IsEmpty() ? creature->GetTransport() : nullptr; - if (transport) - { - float x, y, z, o; - GetPosition(x, y, z, o); - transport->CalculatePassengerOffset(x, y, z, &o); - m_movementInfo.transport.pos.Relocate(x, y, z, o); - - transport->AddPassenger(this); - } - return true; } @@ -713,17 +679,6 @@ bool Pet::CreateBaseAtCreatureInfo(CreatureTemplate const* cinfo, Unit* owner) Relocate(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ(), owner->GetOrientation()); - Transport* transport = GetTransGUID().IsEmpty() ? owner->GetTransport() : nullptr; - if (transport) - { - float x, y, z, o; - GetPosition(x, y, z, o); - transport->CalculatePassengerOffset(x, y, z, &o); - m_movementInfo.transport.pos.Relocate(x, y, z, o); - - transport->AddPassenger(this); - } - return true; } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 1b198c4aa2..660af35cb9 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -211,7 +211,6 @@ Player::Player(WorldSession* session): Unit(true) m_bCanDelayTeleport = false; m_bHasDelayedTeleport = false; m_teleport_options = 0; - m_teleport_transport = nullptr; m_trade = nullptr; @@ -372,8 +371,6 @@ Player::Player(WorldSession* session): Unit(true) _archaeology = new Archaeology(this); m_petScalingSynchTimer.Reset(1000); m_groupUpdateTimer.Reset(5000); - - _transportSpawnID = 0; } Player::~Player() @@ -1337,7 +1334,7 @@ void Player::Update(uint32 p_time) //we should execute delayed teleports only for alive(!) players //because we don't want player's ghost teleported from graveyard if (IsHasDelayedTeleport() && IsAlive()) - TeleportTo(m_teleport_dest, m_teleport_options, m_teleport_transport); + TeleportTo(m_teleport_dest, m_teleport_options); } @@ -1420,7 +1417,7 @@ uint8 Player::GetChatTag() const return tag; } -bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options, Transport* transport) +bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options) { if (!MapManager::IsValidMapCoord(mapid, x, y, z, orientation)) { @@ -1499,7 +1496,6 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati //lets save teleport destination for player m_teleport_dest = WorldLocation(mapid, x, y, z, orientation); m_teleport_options = options; - m_teleport_transport = transport; return true; } @@ -1517,12 +1513,9 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati m_teleport_dest = WorldLocation(mapid, x, y, z, orientation); m_teleport_options = options; SetFallInformation(0, GetPositionZ()); - m_teleport_transport = transport; // code for finish transfer called in WorldSession::HandleMovementOpcodes() // at client packet CMSG_MOVE_TELEPORT_ACK - if (!GetTransport()) - SetSemaphoreTeleportNear(true); // near teleport, triggering send CMSG_MOVE_TELEPORT_ACK from client at landing if (!GetSession()->PlayerLogout()) { @@ -1563,7 +1556,6 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati //lets save teleport destination for player m_teleport_dest = WorldLocation(mapid, x, y, z, orientation); m_teleport_options = options; - m_teleport_transport = transport; return true; } @@ -1631,7 +1623,6 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati PurgeAndApplyPendingMovementChanges(false); m_teleport_dest = WorldLocation(mapid, x, y, z, orientation); - m_teleport_transport = transport; m_teleport_options = options; SetFallInformation(0, GetPositionZ()); // if the player is saved before worldportack (at logout for example) @@ -1655,9 +1646,9 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati return true; } -bool Player::TeleportTo(WorldLocation const& loc, uint32 options /*= 0*/, Transport* transport /*=nullptr*/) +bool Player::TeleportTo(WorldLocation const& loc, uint32 options /*= 0*/) { - return TeleportTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), loc.GetOrientation(), options, transport); + return TeleportTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), loc.GetOrientation(), options); } bool Player::TeleportToBGEntryPoint() @@ -17059,8 +17050,8 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol //"totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, " // 51 52 53 54 55 56 57 58 59 60 61 //"health, power1, power2, power3, power4, power5, instance_id, speccount, activespec, exploredZones, equipmentCache, " - // 62 63 64 65 66 - //"knownTitles, actionBars, grantableLevels, fishing_steps, trans_spawn_id FROM characters WHERE guid = '%u'", guid); + // 62 63 64 65 + //"knownTitles, actionBars, grantableLevels, fishing_steps FROM characters WHERE guid = '%u'", guid); PreparedQueryResult result = holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_FROM); if (!result) @@ -17203,7 +17194,6 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol // init saved position, and fix it later if problematic ObjectGuid::LowType transLowGUID = fields[36].GetUInt32(); - uint32 transSpawnId = fields[66].GetUInt32(); Relocate(fields[17].GetFloat(), fields[18].GetFloat(), fields[19].GetFloat(), fields[21].GetFloat()); @@ -17318,120 +17308,45 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol // currently we do not support transport in bg else if (transLowGUID) { - // if transSpawnId presents, then search for static transport (e.g. elevator) - // else - needs motiontransport - if (transSpawnId) + ObjectGuid transGUID(HighGuid::Mo_Transport, transLowGUID); + + Transport* transport = nullptr; + if (Transport* go = HashMapHolder::Find(transGUID)) + transport = go; + + if (transport) { - map = sMapMgr->CreateMap(mapId, this, instanceId); - if (map) + float x = fields[32].GetFloat(), y = fields[33].GetFloat(), z = fields[34].GetFloat(), o = fields[35].GetFloat(); + m_movementInfo.transport.pos.Relocate(x, y, z, o); + transport->CalculatePassengerPosition(x, y, z, &o); + + if (!Trinity::IsValidMapCoord(x, y, z, o) || + // transport size limited + std::fabs(m_movementInfo.transport.pos.GetPositionX()) > 250.0f || + std::fabs(m_movementInfo.transport.pos.GetPositionY()) > 250.0f || + std::fabs(m_movementInfo.transport.pos.GetPositionZ()) > 250.0f) { - auto bounds = map->GetGameObjectBySpawnIdStore().equal_range(transSpawnId); - if (bounds.first != bounds.second) - m_transport = bounds.first->second->ToTransport(); - } + TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) has invalid transport coordinates (X: %f Y: %f Z: %f O: %f). Teleport to bind location.", + guid.ToString().c_str(), x, y, z, o); - if (m_transport) - { - float x = fields[32].GetFloat(), y = fields[33].GetFloat(), z = fields[34].GetFloat(), o = fields[35].GetFloat(); - m_movementInfo.transport.pos.Relocate(x, y, z, o); - m_transport->CalculatePassengerPosition(x, y, z, &o); + m_movementInfo.transport.Reset(); - if (!Trinity::IsValidMapCoord(x, y, z, o) || - // transport size limited - std::fabs(m_movementInfo.transport.pos.GetPositionX()) > 250.0f || - std::fabs(m_movementInfo.transport.pos.GetPositionY()) > 250.0f || - std::fabs(m_movementInfo.transport.pos.GetPositionZ()) > 250.0f) - { - TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) has invalid transport coordinates (X: %f Y: %f Z: %f O: %f). Teleport to bind location.", - guid.ToString().c_str(), x, y, z, o); - - m_transport = nullptr; - m_movementInfo.transport.Reset(); - - RelocateToHomebind(); - } - else - { - Relocate(x, y, z, o); - mapId = m_transport->GetMapId(); - m_transport->AddPassenger(this); - } + RelocateToHomebind(); } else { - // transport not presents in world - just take go position from db - if (GameObjectData const* data = sObjectMgr->GetGameObjectData(transSpawnId)) - { - float dataX = data->spawnPoint.GetPositionX(); - float dataY = data->spawnPoint.GetPositionY(); - float dataZ = data->spawnPoint.GetPositionZ(); - float dataOrient = data->spawnPoint.GetOrientation(); + Relocate(x, y, z, o); + mapId = transport->GetMapId(); - float x = fields[32].GetFloat(), y = fields[33].GetFloat(), z = fields[34].GetFloat(), o = fields[35].GetFloat(); - m_movementInfo.transport.pos.Relocate(x, y, z, o); - TransportBase::CalculatePassengerPosition(x, y, z, &o, dataX, dataY, dataZ, dataOrient); - - if (!Trinity::IsValidMapCoord(x, y, z, o) || - // transport size limited - std::fabs(m_movementInfo.transport.pos.GetPositionX()) > 250.0f || - std::fabs(m_movementInfo.transport.pos.GetPositionY()) > 250.0f || - std::fabs(m_movementInfo.transport.pos.GetPositionZ()) > 250.0f) - { - TC_LOG_ERROR("entities.player", "Player (%s) have invalid transport coordinates (X: %f Y: %f Z: %f O: %f). Teleport to bind location.", - guid.ToString().c_str(), x, y, z, o); - - m_movementInfo.transport.Reset(); - RelocateToHomebind(); - } - else - { - Relocate(x, y, z, o); - SetTransportSpawnID(transSpawnId); - } - } + transport->AddPassenger(this); } } else { - ObjectGuid transGUID = ObjectGuid::Create(transLowGUID); + TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) has problems with transport guid (%u). Teleport to bind location.", + guid.ToString().c_str(), transLowGUID); - if (MapTransport* go = ObjectAccessor::GetMapTransport(transGUID)) - m_transport = go; - - if (m_transport) - { - float x = fields[32].GetFloat(), y = fields[33].GetFloat(), z = fields[34].GetFloat(), o = fields[35].GetFloat(); - m_movementInfo.transport.pos.Relocate(x, y, z, o); - m_transport->CalculatePassengerPosition(x, y, z, &o); - - if (!Trinity::IsValidMapCoord(x, y, z, o) || - // transport size limited - std::fabs(m_movementInfo.transport.pos.GetPositionX()) > 250.0f || - std::fabs(m_movementInfo.transport.pos.GetPositionY()) > 250.0f || - std::fabs(m_movementInfo.transport.pos.GetPositionZ()) > 250.0f) - { - TC_LOG_ERROR("entities.player", "Player (%s) have invalid transport coordinates (X: %f Y: %f Z: %f O: %f). Teleport to bind location.", - guid.ToString().c_str(), x, y, z, o); - - m_transport = nullptr; - m_movementInfo.transport.Reset(); - - RelocateToHomebind(); - } - else - { - Relocate(x, y, z, o); - mapId = m_transport->GetMapId(); - m_transport->AddPassenger(this); - } - } - else - { - TC_LOG_ERROR("entities.player", "Player (%s) have problems with transport guid (%u). Teleport to bind location.", - guid.ToString().c_str(), transLowGUID); - - RelocateToHomebind(); - } + RelocateToHomebind(); } } // currently we do not support taxi in instance @@ -19610,14 +19525,9 @@ void Player::SaveToDB(CharacterDatabaseTransaction trans, bool create /* = false stmt->setFloat(index++, finiteAlways(GetTransOffsetZ())); stmt->setFloat(index++, finiteAlways(GetTransOffsetO())); ObjectGuid::LowType transLowGUID = 0; - uint32 transSpawnId = 0; - if (Transport* transport = GetTransport()) - { - transLowGUID = transport->GetGUID().GetCounter(); - transSpawnId = transport->GetSpawnId(); - } + if (GetTransport()) + transLowGUID = GetTransport()->GetGUID().GetCounter(); stmt->setUInt32(index++, transLowGUID); - stmt->setUInt32(index++, transSpawnId); std::ostringstream ss; ss << m_taxi; @@ -19750,14 +19660,9 @@ void Player::SaveToDB(CharacterDatabaseTransaction trans, bool create /* = false stmt->setFloat(index++, finiteAlways(GetTransOffsetZ())); stmt->setFloat(index++, finiteAlways(GetTransOffsetO())); ObjectGuid::LowType transLowGUID = 0; - uint32 transSpawnId = 0; - if (Transport* transport = GetTransport()) - { - transLowGUID = transport->GetGUID().GetCounter(); - transSpawnId = transport->GetSpawnId(); - } + if (GetTransport()) + transLowGUID = GetTransport()->GetGUID().GetCounter(); stmt->setUInt32(index++, transLowGUID); - stmt->setUInt32(index++, transSpawnId); std::ostringstream ss; ss << m_taxi; @@ -23123,6 +23028,17 @@ inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, T* target, std::set s64.insert(target->GetGUID()); } +template<> +inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, GameObject* target, std::set& /*v*/) +{ + // @HACK: This is to prevent objects like deeprun tram from disappearing when player moves far from its spawn point while riding it + // But exclude stoppable elevators from this hack - they would be teleporting from one end to another + // if affected transports move so far horizontally that it causes them to run out of visibility range then you are out of luck + // fix visibility instead of adding hacks here + if (!target->IsDynTransport()) + s64.insert(target->GetGUID()); +} + template<> inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, Creature* target, std::set& v) { @@ -27935,17 +27851,6 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy SetMinion(pet, true); - Transport* transport = GetTransGUID().IsEmpty() ? GetTransport() : nullptr; - if (transport) - { - float x, y, z, o; - pet->GetPosition(x, y, z, o); - transport->CalculatePassengerOffset(x, y, z, &o); - pet->m_movementInfo.transport.pos.Relocate(x, y, z, o); - - transport->AddPassenger(pet); - } - switch (petType) { case SUMMON_PET: diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 7ea5d0536f..262f73c837 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1019,8 +1019,8 @@ class TC_GAME_API Player : public Unit, public GridObject void SetObjectScale(float scale) override; - bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options = 0, Transport* transport = nullptr); - bool TeleportTo(WorldLocation const& loc, uint32 options = 0, Transport* transport = nullptr); + bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options = 0); + bool TeleportTo(WorldLocation const& loc, uint32 options = 0); bool TeleportToBGEntryPoint(); bool HasSummonPending() const; @@ -1924,8 +1924,6 @@ class TC_GAME_API Player : public Unit, public GridObject void SetSkillPermBonus(uint8 pos, uint16 value); WorldLocation& GetTeleportDest() { return m_teleport_dest; } - Transport* GetTeleportTransport() const { return m_teleport_transport; } - void ResetTeleportTransport() { m_teleport_transport = nullptr; } bool IsBeingTeleported() const { return mSemaphoreTeleport_Near || mSemaphoreTeleport_Far; } bool IsBeingTeleportedNear() const { return mSemaphoreTeleport_Near; } bool IsBeingTeleportedFar() const { return mSemaphoreTeleport_Far; } @@ -2390,9 +2388,6 @@ class TC_GAME_API Player : public Unit, public GridObject void DeleteFromPlayerPetDataStore(uint32 petNumber); void AddToPlayerPetDataStore(PlayerPetData* playerPetData); - uint32 GetTransportSpawnID() const { return _transportSpawnID; } - void SetTransportSpawnID(uint32 spawnId) { _transportSpawnID = spawnId; } - protected: // Gamemaster whisper whitelist GuidList WhisperList; @@ -2728,7 +2723,6 @@ class TC_GAME_API Player : public Unit, public GridObject // Current teleport data WorldLocation m_teleport_dest; uint32 m_teleport_options; - Transport* m_teleport_transport; bool mSemaphoreTeleport_Near; bool mSemaphoreTeleport_Far; @@ -2766,8 +2760,6 @@ class TC_GAME_API Player : public Unit, public GridObject TimeTrackerSmall m_petScalingSynchTimer; TimeTrackerSmall m_groupUpdateTimer; - - uint32 _transportSpawnID; }; TC_GAME_API void AddItemsSetItem(Player* player, Item* item); diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp index 72d2daefe6..aa4198fe64 100644 --- a/src/server/game/Entities/Transport/Transport.cpp +++ b/src/server/game/Entities/Transport/Transport.cpp @@ -30,526 +30,48 @@ #include "Totem.h" #include "UpdateData.h" #include "Vehicle.h" -#include "ZoneScript.h" Transport::Transport() : GameObject(), - _passengerTeleportItr(_passengers.begin()), _destinationStopFrameTime(0), _currentTransportTime(0), - _lastStopFrameTime(0), _finalStopFrameTime(0), _isDynamicTransport(false), _initialRelocate(false) + _transportInfo(nullptr), _isMoving(true), _pendingStop(false), + _triggeredArrivalEvent(false), _triggeredDepartureEvent(false), + _passengerTeleportItr(_passengers.begin()), _delayedAddModel(false), _delayedTeleport(false) { - m_updateFlag |= UPDATEFLAG_TRANSPORT | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_ROTATION; + m_updateFlag = UPDATEFLAG_TRANSPORT | UPDATEFLAG_LOWGUID | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_ROTATION; } Transport::~Transport() { ASSERT(_passengers.empty()); - if (m_goInfo && m_goInfo->type == GAMEOBJECT_TYPE_TRANSPORT) - delete m_goValue.Transport.StopFrames; + UnloadStaticPassengers(); } -void Transport::CleanupsBeforeDelete(bool finalCleanup /*= true*/) +bool Transport::Create(ObjectGuid::LowType guidlow, uint32 entry, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress) { - while (!_passengers.empty()) - { - WorldObject* obj = *_passengers.begin(); - RemovePassenger(obj); - } - - GameObject::CleanupsBeforeDelete(finalCleanup); -} - -void Transport::AddPassenger(WorldObject* passenger) -{ - if (!IsInWorld()) - return; - - if (_passengers.insert(passenger).second) - { - passenger->SetTransport(this); - passenger->m_movementInfo.transport.guid = GetGUID(); - passenger->m_movementInfo.transport.time = GetTimer(); - - if (passenger->GetTypeId() == TYPEID_UNIT) - { - float x, y, z, o; - passenger->GetPosition(x, y, z, o); - TransportBase::CalculatePassengerOffset(x, y, z, &o, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation()); - passenger->m_movementInfo.transport.pos.Relocate(x, y, z, o); - - if (IsInWorld() && passenger->IsInWorld()) - UpdatePositionForPassenger(passenger); - } - - TC_LOG_DEBUG("entities.transport", "Object %s boarded transport %s.", passenger->GetName().c_str(), GetName().c_str()); - - if (Unit* unit = passenger->ToUnit()) - { - if (Guardian* guardian = unit->GetGuardianPet()) - { - if (!guardian->IsPet() || guardian->GetCharmInfo()->GetCommandState() == COMMAND_FOLLOW) - { - if (Transport* oldTransport = guardian->GetTransport()) - oldTransport->RemovePassenger(guardian); - - AddPassenger(guardian); - /// @HACK - transport models are not added to map's dynamic LoS calculations - /// because the current GameObjectModel cannot be moved without recreating - guardian->AddUnitState(UNIT_STATE_IGNORE_PATHFINDING); - } - } - } - - if (Player* plr = passenger->ToPlayer()) - { - sScriptMgr->OnAddPassenger(this, plr); - - if (GetGoType() == GAMEOBJECT_TYPE_TRANSPORT) - plr->SetTransportSpawnID(GetSpawnId()); - } - } -} - -void Transport::RemovePassenger(WorldObject* passenger) -{ - bool erased = false; - if (_passengerTeleportItr != _passengers.end()) - { - PassengerSet::iterator itr = _passengers.find(passenger); - if (itr != _passengers.end()) - { - if (itr == _passengerTeleportItr) - ++_passengerTeleportItr; - - _passengers.erase(itr); - erased = true; - } - } - else - erased = _passengers.erase(passenger) > 0; - - if (erased) - { - passenger->SetTransport(nullptr); - passenger->m_movementInfo.transport.Reset(); - TC_LOG_DEBUG("entities.transport", "Object %s removed from transport %s.", passenger->GetName().c_str(), GetName().c_str()); - - if (Unit* unit = passenger->ToUnit()) - { - if (Guardian* guardian = unit->GetGuardianPet()) - if (!guardian->IsPet() || guardian->GetCharmInfo()->GetCommandState() == COMMAND_FOLLOW) - { - if (guardian->GetTransGUID() == GetGUID()) - { - RemovePassenger(guardian); - /// @HACK - transport models are not added to map's dynamic LoS calculations - /// because the current GameObjectModel cannot be moved without recreating - guardian->ClearUnitState(UNIT_STATE_IGNORE_PATHFINDING); - } - } - } - - if (Player* plr = passenger->ToPlayer()) - { - sScriptMgr->OnRemovePassenger(this, plr); - plr->SetTransportSpawnID(0); - } - } -} - -bool Transport::Create(ObjectGuid::LowType guidlow, uint32 entry, Map* map, Position const& pos, QuaternionData const& rotation, uint32 animprogress, GOState /*go_state*/, uint32 artKit /*= 0*/, bool dynamic, ObjectGuid::LowType spawnid) -{ - ASSERT(map); - SetMap(map); - - UpdatePositionData(); - SetZoneScript(); - if (GetZoneScript()) - { - entry = GetZoneScript()->GetGameObjectEntry(m_spawnId, entry); - if (!entry) - return false; - } - - // Set if this object can handle dynamic spawns - if (!dynamic) - SetRespawnCompatibilityMode(); - - if (!Transport::CreateTransport(guidlow, entry, map->GetId(), pos, animprogress)) - return false; - - if (m_goInfo->type != GAMEOBJECT_TYPE_TRANSPORT) - { - TC_LOG_ERROR("entities.transport", "Transport (Spawn id: %u Entry: %u) not created.", GetSpawnId(), entry); - return false; - } - - m_stationaryPosition.Relocate(pos); - - GameObjectAddon const* gameObjectAddon = sObjectMgr->GetGameObjectAddon(GetSpawnId()); - - SetLocalRotation(rotation.x, rotation.y, rotation.z, rotation.w); - - // For most of gameobjects is (0, 0, 0, 1) quaternion, there are only some transports with not standard rotation - QuaternionData parentRotation; - if (gameObjectAddon) - parentRotation = gameObjectAddon->ParentRotation; - - SetParentRotation(parentRotation); - - SetGoArtKit(artKit); - - m_goValue.Transport.AnimationInfo = sTransportMgr->GetTransportAnimInfo(entry); - m_goValue.Transport.StopFrames = new std::vector(); - - if (m_goInfo->transport.Timeto2ndfloor > 0) - m_goValue.Transport.StopFrames->push_back(m_goInfo->transport.Timeto2ndfloor); - if (m_goInfo->transport.Timeto3rdfloor > 0) - m_goValue.Transport.StopFrames->push_back(m_goInfo->transport.Timeto3rdfloor); - if (m_goInfo->transport.Timeto4thfloor > 0) - m_goValue.Transport.StopFrames->push_back(m_goInfo->transport.Timeto4thfloor); - if (m_goInfo->transport.Timeto5thfloor > 0) - m_goValue.Transport.StopFrames->push_back(m_goInfo->transport.Timeto5thfloor); - - // Picking the final stop frame from transport animation store for return server side movement - uint32 finalStopFrameTime = 0; - for (TransportAnimationEntry const* animation : sTransportAnimationStore) - { - if (animation->TransportID != entry) - continue; - - if (animation->TimeIndex > finalStopFrameTime) - finalStopFrameTime = animation->TimeIndex; - } - - _finalStopFrameTime = finalStopFrameTime; - - _isDynamicTransport = m_goValue.Transport.StopFrames->empty(); - - uint32 stopTimer = 0; - - if (m_goInfo->transport.startOpen) - { - SetGoState(GO_STATE_TRANSPORT_STOPPED); - stopTimer = m_goValue.Transport.StopFrames->at(0); - _currentTransportTime = stopTimer; - _initialRelocate = true; - } - else - SetGoState(GO_STATE_TRANSPORT_ACTIVE); - - if (_isDynamicTransport) - { - m_goValue.Transport.PathProgress = getMSTime(); - if (m_goValue.Transport.AnimationInfo) - { - SetPeriod(m_goValue.Transport.AnimationInfo->TotalTime); - m_goValue.Transport.PathProgress -= m_goValue.Transport.PathProgress % GetTransportPeriod(); // align to period - } - } - else - { - SetPeriod(getMSTime() + stopTimer); - m_goValue.Transport.PathProgress = getMSTime() + stopTimer; - } - - SetDestinationStopFrameTime(stopTimer); - SetCurrentTransportTime(stopTimer); - - if (gameObjectAddon && gameObjectAddon->InvisibilityValue) - { - m_invisibility.AddFlag(gameObjectAddon->invisibilityType); - m_invisibility.AddValue(gameObjectAddon->invisibilityType, gameObjectAddon->InvisibilityValue); - } - - LastUsedScriptID = GetGOInfo()->ScriptId; - AIM_Initialize(); - - if (spawnid) - m_spawnId = spawnid; - - return true; -} - -bool Transport::CreateTransport(ObjectGuid::LowType guidlow, uint32 entry, uint32 mapid, Position const& pos, uint32 animprogress) -{ - Relocate(pos); + Relocate(x, y, z, ang); if (!IsPositionValid()) { - TC_LOG_ERROR("entities.transport", "Transport (GUID: %u) not created. Suggested coordinates isn't valid %s", - guidlow, pos.ToString().c_str()); + TC_LOG_ERROR("entities.transport", "Transport (GUID: %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)", + guidlow, x, y); return false; } - Object::_Create(guidlow, 0, HighGuid::Transport); + Object::_Create(guidlow, 0, HighGuid::Mo_Transport); GameObjectTemplate const* goinfo = sObjectMgr->GetGameObjectTemplate(entry); if (!goinfo) { - TC_LOG_ERROR("sql.sql", "Transport not created: entry in `gameobject_template` not found, guidlow: %u map: %u (X: %f Y: %f Z: %f) ang: %f", guidlow, mapid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()); + TC_LOG_ERROR("sql.sql", "Transport not created: entry in `gameobject_template` not found, guidlow: %u map: %u (X: %f Y: %f Z: %f) ang: %f", guidlow, mapid, x, y, z, ang); return false; } m_goInfo = goinfo; m_goTemplateAddon = sObjectMgr->GetGameObjectTemplateAddon(entry); - if (m_goTemplateAddon) - { - SetFaction(m_goTemplateAddon->faction); - SetUInt32Value(GAMEOBJECT_FLAGS, m_goTemplateAddon->flags); - } - - SetObjectScale(goinfo->size); - SetEntry(goinfo->entry); - SetDisplayId(goinfo->displayId); - SetGoType(GameobjectTypes(goinfo->type)); - SetGoAnimProgress(animprogress); - SetName(goinfo->name); - - m_model = CreateModel(); - return true; -} - -void Transport::Update(uint32 diff) -{ - GameObject::Update(diff); - - if (!IsInWorld()) - return; - - if (!m_goValue.Transport.AnimationInfo) - return; - - if (_initialRelocate) - { - RelocateToProgress(GetCurrentTransportTime()); - _initialRelocate = false; - } - - if (IsDynamicTransport()) - { - m_goValue.Transport.PathProgress += diff; - SetCurrentTransportTime(GetCurrentTransportTime() + diff); - if (GetCurrentTransportTime() >= GetTransportPeriod()) - SetCurrentTransportTime(GetCurrentTransportTime() % GetTransportPeriod()); - } - else - { - // Waiting at our last destination. Do nothing. - if (GetCurrentTransportTime() == GetDestinationStopFrameTime()) - return; - - uint32 lastStopFrameTime = GetLastStopFrameTime(); - uint32 currentTransportTime = GetCurrentTransportTime(); - uint32 destinationStopFrameTime = GetDestinationStopFrameTime(); - switch (GetGoState()) - { - case GO_STATE_ACTIVE: - case GO_STATE_READY: - case GO_STATE_ACTIVE_ALTERNATIVE: - break; - default: - { - /* - These states handle the stop frame movement of transports - Transports with GO_STATE_TRANSPORT_ACTIVE move to stop frame 0 clientside while using a special travel path - Transports with GO_STATE_TRANSPORT_STOPPED + frame index move to the provided stop frame using time diffs between - the last frame and the target frame to reach their destination - */ - - bool backwardsMovement = destinationStopFrameTime < lastStopFrameTime; - - uint32 transportTime = backwardsMovement ? - std::max(destinationStopFrameTime, currentTransportTime - diff) : - std::min(destinationStopFrameTime, currentTransportTime + diff); - - SetCurrentTransportTime(transportTime); - break; - } - } - } - - RelocateToProgress(GetCurrentTransportTime()); -} - -void Transport::RelocateToProgress(uint32 progress) -{ - TransportAnimationEntry const* curr = nullptr; - TransportAnimationEntry const* next = nullptr; - float percPos = 0.0f; - - if (m_goValue.Transport.AnimationInfo->GetAnimNode(progress, curr, next, percPos)) - { - // curr node offset - G3D::Vector3 pos = G3D::Vector3(curr->Pos.X, curr->Pos.Y, curr->Pos.Z); - - // move by percentage of segment already passed - pos += G3D::Vector3(percPos * (next->Pos.X - curr->Pos.X), percPos * (next->Pos.Y - curr->Pos.Y), percPos * (next->Pos.Z - curr->Pos.Z)); - - // rotate path by PathRotation - // PathRotation in db is only simple orientation rotation, so don't use sophisticated and not working code - // reminder: WorldRotation only influences model rotation, not the path - float sign = GetFloatValue(GAMEOBJECT_PARENTROTATION + 2) >= 0.0f ? 1.0f : -1.0f; - float pathRotAngle = sign * 2.0f * acos(GetFloatValue(GAMEOBJECT_PARENTROTATION + 3)); - float cs = cos(pathRotAngle), sn = sin(pathRotAngle); - float nx = pos.x * cs - pos.y * sn; - float ny = pos.x * sn + pos.y * cs; - - pos.x = nx; - pos.y = ny; - - // add stationary position to the calculated offset - pos += G3D::Vector3(GetStationaryX(), GetStationaryY(), GetStationaryZ()); - - // rotate by AnimRotation at current segment - // AnimRotation in dbc is only simple orientation rotation, so don't use sophisticated and not working code - QuaternionData currRot = QuaternionData(); - QuaternionData nextRot = QuaternionData(); - float percRot = 0.0f; - - m_goValue.Transport.AnimationInfo->GetAnimRotation(progress, currRot, nextRot, percRot); - - float signCurr = currRot.z >= 0.0f ? 1.0f : -1.0f; - float oriRotAngleCurr = signCurr * 2.0f * acos(currRot.w); - float signNext = nextRot.z >= 0.0f ? 1.0f : -1.0f; - float oriRotAngleNext = signNext * 2.0f * acos(nextRot.w); - float oriRotAngle = oriRotAngleCurr + percRot * (oriRotAngleNext - oriRotAngleCurr); - - // check if position is valid - if (!Trinity::IsValidMapCoord(pos.x, pos.y, pos.z)) - return; - - GetMap()->GameObjectRelocation(this, pos.x, pos.y, pos.z, NormalizeOrientation(GetStationaryO() + oriRotAngle)); - - UpdatePassengerPositions(_passengers); - } -} - -void Transport::UpdatePassengerPositions(PassengerSet& passengers) -{ - for (PassengerSet::iterator itr = passengers.begin(); itr != passengers.end(); ++itr) - UpdatePositionForPassenger(*itr); -} - -void Transport::UpdatePositionForPassenger(WorldObject* passenger) -{ - // transport teleported but passenger not yet (can happen for players) - if (passenger->GetMap() != GetMap()) - return; - - // if passenger is on vehicle we have to assume the vehicle is also on transport - // and its the vehicle that will be updating its passengers - if (Unit* unit = passenger->ToUnit()) - { - if (unit->GetVehicle()) - return; - - // if spline enabled, position will be updated in Unit::UpdateSplinePosition - if (unit->IsSplineEnabled()) - return; - } - - // Do not use Unit::UpdatePosition here, we don't want to remove auras - // as if regular movement occurred - float x, y, z, o; - passenger->m_movementInfo.transport.pos.GetPosition(x, y, z, o); - CalculatePassengerPosition(x, y, z, &o); - switch (passenger->GetTypeId()) - { - case TYPEID_UNIT: - { - Creature* creature = passenger->ToCreature(); - GetMap()->CreatureRelocation(creature, x, y, z, o, false); - creature->GetTransportHomePosition(x, y, z, o); - CalculatePassengerPosition(x, y, z, &o); - creature->SetHomePosition(x, y, z, o); - break; - } - case TYPEID_PLAYER: - GetMap()->PlayerRelocation(passenger->ToPlayer(), x, y, z, o); - break; - case TYPEID_GAMEOBJECT: - GetMap()->GameObjectRelocation(passenger->ToGameObject(), x, y, z, o, false); - passenger->ToGameObject()->RelocateStationaryPosition(x, y, z, o); - break; - case TYPEID_DYNAMICOBJECT: - GetMap()->DynamicObjectRelocation(passenger->ToDynObject(), x, y, z, o); - break; - default: - break; - } - - if (Unit* unit = passenger->ToUnit()) - if (Vehicle* vehicle = unit->GetVehicleKit()) - vehicle->RelocatePassengers(); // transport teleported but passenger not yet (can happen for players) -} - -void Transport::SetTransportState(GOState state, uint32 stopFrame /*= 0*/) -{ - // Do not change the transport state before reaching the last selected destination - if (GetCurrentTransportTime() != GetDestinationStopFrameTime()) - return; - - ASSERT(m_goInfo->type == GAMEOBJECT_TYPE_TRANSPORT); - - uint32 stopTimer = 0; - - uint32 currentStopFrameTime = GetCurrentTransportTime(); - if (GetGoState() == GO_STATE_TRANSPORT_ACTIVE) - { - currentStopFrameTime = 0; - SetCurrentTransportTime(currentStopFrameTime); - } - - if (state == GO_STATE_TRANSPORT_ACTIVE) - { - if (currentStopFrameTime) - { - // Returning to stop frame 0. Client expects travel time, server expects animation timestamp for special return movement - uint32 transportTravelTime = _finalStopFrameTime - currentStopFrameTime; - SetPeriod(getMSTime() + transportTravelTime); - SetDestinationStopFrameTime(_finalStopFrameTime); - } - } - else - { - ASSERT(state < GOState(GO_STATE_TRANSPORT_STOPPED + MAX_GO_STATE_TRANSPORT_STOP_FRAMES)); - ASSERT(stopFrame <= m_goValue.Transport.StopFrames->size()); - - // Moving between given stop frames - stopTimer = stopFrame ? m_goValue.Transport.StopFrames->at(stopFrame - 1) : 0; - bool backwards = stopTimer < currentStopFrameTime; - uint32 transportTravelTime = backwards ? currentStopFrameTime - stopTimer : stopTimer - currentStopFrameTime; - SetPeriod(getMSTime() + transportTravelTime); - SetDestinationStopFrameTime(stopTimer); - state = GOState(GO_STATE_TRANSPORT_ACTIVE + stopFrame); - } - - m_goValue.Transport.PathProgress = getMSTime() + stopTimer; - SetLastStopFrameTime(currentStopFrameTime); - SetGoState(state); -} - -MapTransport::MapTransport() : Transport(), - _transportInfo(nullptr), _isMoving(true), _pendingStop(false), - _triggeredArrivalEvent(false), _triggeredDepartureEvent(false), - _delayedAddModel(false), _delayedTeleport(false) -{ -} - -MapTransport::~MapTransport() -{ - UnloadStaticPassengers(); -} - -bool MapTransport::CreateMapTransport(ObjectGuid::LowType guidlow, uint32 entry, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress) -{ - if (!Transport::CreateTransport(guidlow, entry, mapid, Position(x, y, z, ang), animprogress)) - return false; - TransportTemplate const* tInfo = sTransportMgr->GetTransportTemplate(entry); if (!tInfo) { - TC_LOG_ERROR("sql.sql", "Transport %u (name: %s) will not be created, missing `transport_template` entry.", entry, m_goInfo->name.c_str()); + TC_LOG_ERROR("sql.sql", "Transport %u (name: %s) will not be created, missing `transport_template` entry.", entry, goinfo->name.c_str()); return false; } @@ -561,9 +83,21 @@ bool MapTransport::CreateMapTransport(ObjectGuid::LowType guidlow, uint32 entry, _triggeredArrivalEvent = false; _triggeredDepartureEvent = false; + if (m_goTemplateAddon) + { + SetFaction(m_goTemplateAddon->faction); + SetUInt32Value(GAMEOBJECT_FLAGS, m_goTemplateAddon->flags); + } + m_goValue.Transport.PathProgress = 0; + SetObjectScale(goinfo->size); SetPeriod(tInfo->pathTime); - SetGoState(!m_goInfo->moTransport.canBeStopped ? GO_STATE_READY : GO_STATE_ACTIVE); + SetEntry(goinfo->entry); + SetDisplayId(goinfo->displayId); + SetGoState(!goinfo->moTransport.canBeStopped ? GO_STATE_READY : GO_STATE_ACTIVE); + SetGoType(GAMEOBJECT_TYPE_MO_TRANSPORT); + SetGoAnimProgress(animprogress); + SetName(goinfo->name); SetLocalRotation(0.0f, 0.0f, 0.0f, 1.0f); SetParentRotation(QuaternionData()); @@ -571,14 +105,19 @@ bool MapTransport::CreateMapTransport(ObjectGuid::LowType guidlow, uint32 entry, return true; } -void MapTransport::CleanupsBeforeDelete(bool finalCleanup /*= true*/) +void Transport::CleanupsBeforeDelete(bool finalCleanup /*= true*/) { UnloadStaticPassengers(); + while (!_passengers.empty()) + { + WorldObject* obj = *_passengers.begin(); + RemovePassenger(obj); + } - Transport::CleanupsBeforeDelete(finalCleanup); + GameObject::CleanupsBeforeDelete(finalCleanup); } -void MapTransport::Update(uint32 diff) +void Transport::Update(uint32 diff) { uint32 const positionUpdateDelay = 200; @@ -698,7 +237,7 @@ void MapTransport::Update(uint32 diff) sScriptMgr->OnTransportUpdate(this, diff); } -void MapTransport::DelayedUpdate(uint32 /*diff*/) +void Transport::DelayedUpdate(uint32 /*diff*/) { if (GetKeyFrames().size() <= 1) return; @@ -706,7 +245,23 @@ void MapTransport::DelayedUpdate(uint32 /*diff*/) DelayedTeleportTransport(); } -void MapTransport::RemovePassenger(WorldObject* passenger) +void Transport::AddPassenger(WorldObject* passenger) +{ + if (!IsInWorld()) + return; + + if (_passengers.insert(passenger).second) + { + passenger->SetTransport(this); + passenger->m_movementInfo.transport.guid = GetGUID(); + TC_LOG_DEBUG("entities.transport", "Object %s boarded transport %s.", passenger->GetName().c_str(), GetName().c_str()); + + if (Player* plr = passenger->ToPlayer()) + sScriptMgr->OnAddPassenger(this, plr); + } +} + +void Transport::RemovePassenger(WorldObject* passenger) { bool erased = false; if (_passengerTeleportItr != _passengers.end()) @@ -730,12 +285,6 @@ void MapTransport::RemovePassenger(WorldObject* passenger) passenger->m_movementInfo.transport.Reset(); TC_LOG_DEBUG("entities.transport", "Object %s removed from transport %s.", passenger->GetName().c_str(), GetName().c_str()); - if (Unit* unit = passenger->ToUnit()) - if (Guardian* guardian = unit->GetGuardianPet()) - if (!guardian->IsPet() || guardian->GetCharmInfo()->GetCommandState() == COMMAND_FOLLOW) - if (guardian->GetTransGUID() == GetGUID()) - RemovePassenger(guardian); - if (Player* plr = passenger->ToPlayer()) { sScriptMgr->OnRemovePassenger(this, plr); @@ -744,7 +293,7 @@ void MapTransport::RemovePassenger(WorldObject* passenger) } } -Creature* MapTransport::CreateNPCPassenger(ObjectGuid::LowType guid, CreatureData const* data) +Creature* Transport::CreateNPCPassenger(ObjectGuid::LowType guid, CreatureData const* data) { Map* map = GetMap(); if (map->GetCreatureRespawnTime(guid)) @@ -763,7 +312,6 @@ Creature* MapTransport::CreateNPCPassenger(ObjectGuid::LowType guid, CreatureDat creature->SetTransport(this); creature->m_movementInfo.transport.guid = GetGUID(); - creature->m_movementInfo.transport.time = GetTimer(); creature->m_movementInfo.transport.pos.Relocate(x, y, z, o); CalculatePassengerPosition(x, y, z, &o); creature->Relocate(x, y, z, o); @@ -795,19 +343,13 @@ Creature* MapTransport::CreateNPCPassenger(ObjectGuid::LowType guid, CreatureDat return creature; } -GameObject* MapTransport::CreateGOPassenger(ObjectGuid::LowType guid, GameObjectData const* data) +GameObject* Transport::CreateGOPassenger(ObjectGuid::LowType guid, GameObjectData const* data) { - ASSERT(data); - Map* map = GetMap(); if (map->GetGORespawnTime(guid)) return nullptr; - GameObject* go = nullptr; - if (sObjectMgr->GetGameObjectTypeByEntry(data->id) == GAMEOBJECT_TYPE_TRANSPORT) - go = new Transport(); - else - go = new GameObject(); + GameObject* go = new GameObject(); if (!go->LoadFromDB(guid, map, false)) { @@ -822,7 +364,6 @@ GameObject* MapTransport::CreateGOPassenger(ObjectGuid::LowType guid, GameObject go->SetTransport(this); go->m_movementInfo.transport.guid = GetGUID(); - go->m_movementInfo.transport.time = GetTimer(); go->m_movementInfo.transport.pos.Relocate(x, y, z, o); CalculatePassengerPosition(x, y, z, &o); go->Relocate(x, y, z, o); @@ -848,7 +389,7 @@ GameObject* MapTransport::CreateGOPassenger(ObjectGuid::LowType guid, GameObject return go; } -TempSummon* MapTransport::SummonPassenger(uint32 entry, Position const& pos, TempSummonType summonType, SummonPropertiesEntry const* properties /*= nullptr*/, uint32 duration /*= 0*/, Unit* summoner /*= nullptr*/, uint32 spellId /*= 0*/, uint32 vehId /*= 0*/) +TempSummon* Transport::SummonPassenger(uint32 entry, Position const& pos, TempSummonType summonType, SummonPropertiesEntry const* properties /*= nullptr*/, uint32 duration /*= 0*/, Unit* summoner /*= nullptr*/, uint32 spellId /*= 0*/, uint32 vehId /*= 0*/) { Map* map = FindMap(); if (!map) @@ -937,7 +478,6 @@ TempSummon* MapTransport::SummonPassenger(uint32 entry, Position const& pos, Tem summon->SetTransport(this); summon->m_movementInfo.transport.guid = GetGUID(); summon->m_movementInfo.transport.pos.Relocate(pos); - summon->m_movementInfo.transport.time = GetTimer(); summon->Relocate(x, y, z, o); summon->SetHomePosition(x, y, z, o); summon->SetTransportHomePosition(pos); @@ -962,7 +502,7 @@ TempSummon* MapTransport::SummonPassenger(uint32 entry, Position const& pos, Tem return summon; } -void MapTransport::UpdatePosition(float x, float y, float z, float o) +void Transport::UpdatePosition(float x, float y, float z, float o) { bool newActive = GetMap()->IsGridLoaded(x, y); Cell oldCell(GetPositionX(), GetPositionY()); @@ -988,7 +528,7 @@ void MapTransport::UpdatePosition(float x, float y, float z, float o) // 4. is handed by grid unload } -void MapTransport::LoadStaticPassengers() +void Transport::LoadStaticPassengers() { if (uint32 mapId = GetGOInfo()->moTransport.mapID) { @@ -1009,7 +549,7 @@ void MapTransport::LoadStaticPassengers() } } -void MapTransport::UnloadStaticPassengers() +void Transport::UnloadStaticPassengers() { while (!_staticPassengers.empty()) { @@ -1018,7 +558,7 @@ void MapTransport::UnloadStaticPassengers() } } -void MapTransport::EnableMovement(bool enabled) +void Transport::EnableMovement(bool enabled) { if (!GetGOInfo()->moTransport.canBeStopped) return; @@ -1026,7 +566,7 @@ void MapTransport::EnableMovement(bool enabled) _pendingStop = !enabled; } -void MapTransport::MoveToNextWaypoint() +void Transport::MoveToNextWaypoint() { // Clear events flagging _triggeredArrivalEvent = false; @@ -1038,7 +578,7 @@ void MapTransport::MoveToNextWaypoint() _nextFrame = GetKeyFrames().begin(); } -float MapTransport::CalculateSegmentPos(float now) +float Transport::CalculateSegmentPos(float now) { KeyFrame const& frame = *_currentFrame; const float speed = float(m_goInfo->moTransport.moveSpeed); @@ -1069,7 +609,7 @@ float MapTransport::CalculateSegmentPos(float now) return segmentPos / frame.NextDistFromPrev; } -bool MapTransport::TeleportTransport(uint32 newMapid, float x, float y, float z, float o) +bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z, float o) { Map const* oldMap = GetMap(); @@ -1082,18 +622,37 @@ bool MapTransport::TeleportTransport(uint32 newMapid, float x, float y, float z, else { UpdatePosition(x, y, z, o); + + // Teleport players, they need to know it + for (PassengerSet::iterator itr = _passengers.begin(); itr != _passengers.end(); ++itr) + { + if ((*itr)->GetTypeId() == TYPEID_PLAYER) + { + // will be relocated in UpdatePosition of the vehicle + if (Unit* veh = (*itr)->ToUnit()->GetVehicleBase()) + if (veh->GetTransport() == this) + continue; + + float destX, destY, destZ, destO; + (*itr)->m_movementInfo.transport.pos.GetPosition(destX, destY, destZ, destO); + TransportBase::CalculatePassengerPosition(destX, destY, destZ, &destO, x, y, z, o); + + (*itr)->ToUnit()->NearTeleportTo(destX, destY, destZ, destO); + } + } + return false; } } -void MapTransport::DelayedTeleportTransport() +void Transport::DelayedTeleportTransport() { if (!_delayedTeleport) return; _delayedTeleport = false; Map* newMap = sMapMgr->CreateBaseMap(_nextFrame->Node->ContinentID); - GetMap()->RemoveFromMap(this, false); + GetMap()->RemoveFromMap(this, false); SetMap(newMap); float x = _nextFrame->Node->Loc.X, @@ -1125,10 +684,66 @@ void MapTransport::DelayedTeleportTransport() } Relocate(x, y, z, o); - GetMap()->AddToMap(this); + GetMap()->AddToMap(this); } -void MapTransport::DoEventIfAny(KeyFrame const& node, bool departure) +void Transport::UpdatePassengerPositions(PassengerSet& passengers) +{ + for (PassengerSet::iterator itr = passengers.begin(); itr != passengers.end(); ++itr) + { + WorldObject* passenger = *itr; + // transport teleported but passenger not yet (can happen for players) + if (passenger->GetMap() != GetMap()) + continue; + + // if passenger is on vehicle we have to assume the vehicle is also on transport + // and its the vehicle that will be updating its passengers + if (Unit* unit = passenger->ToUnit()) + if (unit->GetVehicle()) + continue; + + // Do not use Unit::UpdatePosition here, we don't want to remove auras + // as if regular movement occurred + float x, y, z, o; + passenger->m_movementInfo.transport.pos.GetPosition(x, y, z, o); + CalculatePassengerPosition(x, y, z, &o); + switch (passenger->GetTypeId()) + { + case TYPEID_UNIT: + { + Creature* creature = passenger->ToCreature(); + GetMap()->CreatureRelocation(creature, x, y, z, o, false); + creature->GetTransportHomePosition(x, y, z, o); + CalculatePassengerPosition(x, y, z, &o); + creature->SetHomePosition(x, y, z, o); + break; + } + case TYPEID_PLAYER: + //relocate only passengers in world and skip any player that might be still logging in/teleporting + if (passenger->IsInWorld() && !passenger->ToPlayer()->IsBeingTeleported()) + { + GetMap()->PlayerRelocation(passenger->ToPlayer(), x, y, z, o); + passenger->ToPlayer()->SetFallInformation(0, passenger->GetPositionZ()); + } + break; + case TYPEID_GAMEOBJECT: + GetMap()->GameObjectRelocation(passenger->ToGameObject(), x, y, z, o, false); + passenger->ToGameObject()->RelocateStationaryPosition(x, y, z, o); + break; + case TYPEID_DYNAMICOBJECT: + GetMap()->DynamicObjectRelocation(passenger->ToDynObject(), x, y, z, o); + break; + default: + break; + } + + if (Unit* unit = passenger->ToUnit()) + if (Vehicle* vehicle = unit->GetVehicleKit()) + vehicle->RelocatePassengers(); + } +} + +void Transport::DoEventIfAny(KeyFrame const& node, bool departure) { if (uint32 eventid = departure ? node.Node->DepartureEventID : node.Node->ArrivalEventID) { @@ -1138,7 +753,7 @@ void MapTransport::DoEventIfAny(KeyFrame const& node, bool departure) } } -void MapTransport::BuildUpdate(UpdateDataMapType& data_map) +void Transport::BuildUpdate(UpdateDataMapType& data_map) { Map::PlayerList const& players = GetMap()->GetPlayers(); if (players.isEmpty()) diff --git a/src/server/game/Entities/Transport/Transport.h b/src/server/game/Entities/Transport/Transport.h index 06738b70e4..5a65148de6 100644 --- a/src/server/game/Entities/Transport/Transport.h +++ b/src/server/game/Entities/Transport/Transport.h @@ -1,5 +1,6 @@ /* - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * Copyright (C) 2008-2018 TrinityCore + * Copyright (C) 2005-2009 MaNGOS * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -26,78 +27,15 @@ struct CreatureData; class TC_GAME_API Transport : public GameObject, public TransportBase { + friend Transport* TransportMgr::CreateTransport(uint32, ObjectGuid::LowType, Map*, uint8, uint32, uint32); + + Transport(); public: typedef std::set PassengerSet; - Transport(); ~Transport(); - bool Create(ObjectGuid::LowType guidlow, uint32 entry, Map* map, Position const& pos, QuaternionData const& rotation, uint32 animprogress, GOState go_state, uint32 artKit = 0, bool dynamic = false, ObjectGuid::LowType spawnid = 0) override; - bool CreateTransport(ObjectGuid::LowType guidlow, uint32 entry, uint32 mapid, Position const& pos, uint32 animprogress); - - void CleanupsBeforeDelete(bool finalCleanup = true) override; - - void AddPassenger(WorldObject* passenger); - virtual void RemovePassenger(WorldObject* passenger); - PassengerSet const& GetPassengers() const { return _passengers; } - - /// This method transforms supplied transport offsets into global coordinates - void CalculatePassengerPosition(float& x, float& y, float& z, float* o = nullptr) const override - { - TransportBase::CalculatePassengerPosition(x, y, z, o, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation()); - } - - /// This method transforms supplied global coordinates into local offsets - void CalculatePassengerOffset(float& x, float& y, float& z, float* o = nullptr) const override - { - TransportBase::CalculatePassengerOffset(x, y, z, o, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation()); - } - - void Update(uint32 diff) override; - - bool IsDynamicTransport() const { return _isDynamicTransport; } - - uint32 GetTransportPeriod() const { return GetUInt32Value(GAMEOBJECT_LEVEL); } - void SetPeriod(uint32 period) { SetUInt32Value(GAMEOBJECT_LEVEL, period); } - uint32 GetTimer() const { return GetGOValue()->Transport.PathProgress; } - - void SetTransportState(GOState state, uint32 stopFrame = 0); - - void RelocateToProgress(uint32 progress); - - void SetDestinationStopFrameTime(uint32 time) { _destinationStopFrameTime = time; } - uint32 GetDestinationStopFrameTime() const { return _destinationStopFrameTime; } - - void SetCurrentTransportTime(uint32 time) { _currentTransportTime = time; } - uint32 GetCurrentTransportTime() const { return _currentTransportTime; } - - void SetLastStopFrameTime(uint32 time) { _lastStopFrameTime = time; } - uint32 GetLastStopFrameTime() const { return _lastStopFrameTime; } - - protected: - void UpdatePassengerPositions(PassengerSet& passengers); - void UpdatePositionForPassenger(WorldObject* passenger); - - PassengerSet _passengers; - PassengerSet::iterator _passengerTeleportItr; - - uint32 _destinationStopFrameTime; - uint32 _currentTransportTime; - uint32 _lastStopFrameTime; - uint32 _finalStopFrameTime; - bool _isDynamicTransport; - bool _initialRelocate; -}; - -class TC_GAME_API MapTransport : public Transport -{ - friend MapTransport* TransportMgr::CreateTransport(uint32, ObjectGuid::LowType, Map*, uint8, uint32, uint32); - - MapTransport(); - public: - ~MapTransport(); - - bool CreateMapTransport(ObjectGuid::LowType guidlow, uint32 entry, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress); + bool Create(ObjectGuid::LowType guidlow, uint32 entry, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress); void CleanupsBeforeDelete(bool finalCleanup = true) override; void Update(uint32 diff) override; @@ -105,13 +43,15 @@ class TC_GAME_API MapTransport : public Transport void BuildUpdate(UpdateDataMapType& data_map) override; - void RemovePassenger(WorldObject* passenger) override; + void AddPassenger(WorldObject* passenger); + void RemovePassenger(WorldObject* passenger); + PassengerSet const& GetPassengers() const { return _passengers; } Creature* CreateNPCPassenger(ObjectGuid::LowType guid, CreatureData const* data); GameObject* CreateGOPassenger(ObjectGuid::LowType guid, GameObjectData const* data); /** - * @fn bool Transport::SummonPassenger(uint32, Position const&, TempSummonType, SummonPropertiesEntry const*, uint32, Unit*, uint32, uint32) + * @fn bool Transport::SummonPassenger(uint64, Position const&, TempSummonType, SummonPropertiesEntry const*, uint32, Unit*, uint32, uint32) * * @brief Temporarily summons a creature as passenger on this transport. * @@ -128,6 +68,22 @@ class TC_GAME_API MapTransport : public Transport */ TempSummon* SummonPassenger(uint32 entry, Position const& pos, TempSummonType summonType, SummonPropertiesEntry const* properties = nullptr, uint32 duration = 0, Unit* summoner = nullptr, uint32 spellId = 0, uint32 vehId = 0); + /// This method transforms supplied transport offsets into global coordinates + void CalculatePassengerPosition(float& x, float& y, float& z, float* o = nullptr) const override + { + TransportBase::CalculatePassengerPosition(x, y, z, o, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation()); + } + + /// This method transforms supplied global coordinates into local offsets + void CalculatePassengerOffset(float& x, float& y, float& z, float* o = nullptr) const override + { + TransportBase::CalculatePassengerOffset(x, y, z, o, GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation()); + } + + uint32 GetTransportPeriod() const override { return GetUInt32Value(GAMEOBJECT_LEVEL); } + void SetPeriod(uint32 period) { SetUInt32Value(GAMEOBJECT_LEVEL, period); } + uint32 GetTimer() const { return GetGOValue()->Transport.PathProgress; } + KeyFrameVec const& GetKeyFrames() const { return _transportInfo->keyFrames; } void UpdatePosition(float x, float y, float z, float o); @@ -149,6 +105,7 @@ class TC_GAME_API MapTransport : public Transport float CalculateSegmentPos(float perc); bool TeleportTransport(uint32 newMapid, float x, float y, float z, float o); void DelayedTeleportTransport(); + void UpdatePassengerPositions(PassengerSet& passengers); void DoEventIfAny(KeyFrame const& node, bool departure); //! Helpers to know if stop frame was reached @@ -167,6 +124,8 @@ class TC_GAME_API MapTransport : public Transport bool _triggeredArrivalEvent; bool _triggeredDepartureEvent; + PassengerSet _passengers; + PassengerSet::iterator _passengerTeleportItr; PassengerSet _staticPassengers; bool _delayedAddModel; diff --git a/src/server/game/Entities/Vehicle/VehicleDefines.h b/src/server/game/Entities/Vehicle/VehicleDefines.h index 2cbaf41b1c..981abe3004 100644 --- a/src/server/game/Entities/Vehicle/VehicleDefines.h +++ b/src/server/game/Entities/Vehicle/VehicleDefines.h @@ -157,6 +157,7 @@ public: /// This method transforms supplied global coordinates into local offsets virtual void CalculatePassengerOffset(float& x, float& y, float& z, float* o = nullptr) const = 0; +protected: static void CalculatePassengerPosition(float& x, float& y, float& z, float* o, float transX, float transY, float transZ, float transO) { float inx = x, iny = y, inz = z; diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp index a4a4c3e340..537b6fc7d2 100644 --- a/src/server/game/Events/GameEventMgr.cpp +++ b/src/server/game/Events/GameEventMgr.cpp @@ -28,7 +28,6 @@ #include "ObjectMgr.h" #include "Player.h" #include "PoolMgr.h" -#include "Transport.h" #include "UnitAI.h" #include "World.h" #include "WorldPacket.h" @@ -1302,11 +1301,7 @@ void GameEventMgr::GameEventSpawn(int16 event_id) // We use current coords to unspawn, not spawn coords since creature can have changed grid if (!map->Instanceable() && map->IsGridLoaded(data->spawnPoint)) { - GameObject* pGameobject = nullptr; - if (sObjectMgr->GetGameObjectTypeByEntry(data->id) == GAMEOBJECT_TYPE_TRANSPORT) - pGameobject = new Transport(); - else - pGameobject = new GameObject(); + GameObject* pGameobject = new GameObject; //TC_LOG_DEBUG("misc", "Spawning gameobject %u", *itr); /// @todo find out when it is add to map if (!pGameobject->LoadFromDB(*itr, map, false)) diff --git a/src/server/game/Globals/ObjectAccessor.cpp b/src/server/game/Globals/ObjectAccessor.cpp index 1caa59a625..684e0a0690 100644 --- a/src/server/game/Globals/ObjectAccessor.cpp +++ b/src/server/game/Globals/ObjectAccessor.cpp @@ -34,8 +34,8 @@ template void HashMapHolder::Insert(T* o) { static_assert(std::is_same::value - || std::is_same::value, - "Only Player and MapTransport can be registered in global HashMapHolder"); + || std::is_same::value, + "Only Player and Transport can be registered in global HashMapHolder"); std::unique_lock lock(*GetLock()); @@ -79,7 +79,7 @@ HashMapHolder::MapType const& ObjectAccessor::GetPlayers() } template class TC_GAME_API HashMapHolder; -template class TC_GAME_API HashMapHolder; +template class TC_GAME_API HashMapHolder; namespace PlayerNameMapHolder { @@ -113,6 +113,7 @@ WorldObject* ObjectAccessor::GetWorldObject(WorldObject const& p, ObjectGuid con { case HighGuid::Player: return GetPlayer(p, guid); case HighGuid::Transport: + case HighGuid::Mo_Transport: case HighGuid::GameObject: return GetGameObject(p, guid); case HighGuid::Vehicle: case HighGuid::Unit: return GetCreature(p, guid); @@ -137,6 +138,7 @@ Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const& p, ObjectGuid con return GetPlayer(p, guid); break; case HighGuid::Transport: + case HighGuid::Mo_Transport: case HighGuid::GameObject: if (typemask & TYPEMASK_GAMEOBJECT) return GetGameObject(p, guid); @@ -177,21 +179,11 @@ GameObject* ObjectAccessor::GetGameObject(WorldObject const& u, ObjectGuid const return u.GetMap()->GetGameObject(guid); } -Transport* ObjectAccessor::GetTransportOnMap(WorldObject const& u, ObjectGuid const& guid) +Transport* ObjectAccessor::GetTransport(WorldObject const& u, ObjectGuid const& guid) { return u.GetMap()->GetTransport(guid); } -MapTransport* ObjectAccessor::GetMapTransportOnMap(WorldObject const& u, ObjectGuid const& guid) -{ - return u.GetMap()->GetMapTransport(guid); -} - -MapTransport* ObjectAccessor::GetMapTransport(ObjectGuid const& guid) -{ - return HashMapHolder::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 1338bda3ec..521009529c 100644 --- a/src/server/game/Globals/ObjectAccessor.h +++ b/src/server/game/Globals/ObjectAccessor.h @@ -63,9 +63,7 @@ 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* GetTransportOnMap(WorldObject const& u, ObjectGuid const& guid); - TC_GAME_API MapTransport* GetMapTransportOnMap(WorldObject const& u, ObjectGuid const& guid); - TC_GAME_API MapTransport* GetMapTransport(ObjectGuid const& guid); + TC_GAME_API Transport* GetTransport(WorldObject const& u, 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/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 49cfc0f014..16b185f24b 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -55,7 +55,6 @@ #include "SpellMgr.h" #include "SpellScript.h" #include "TemporarySummon.h" -#include "Transport.h" #include "UpdateMask.h" #include "Util.h" #include "Vehicle.h" @@ -2279,11 +2278,7 @@ ObjectGuid::LowType ObjectMgr::AddGameObjectData(uint32 entry, uint32 mapId, Pos // We use spawn coords to spawn if (!map->Instanceable() && map->IsGridLoaded(data.spawnPoint)) { - GameObject* go = nullptr; - if (goinfo->type == GAMEOBJECT_TYPE_TRANSPORT) - go = new Transport(); - else - go = new GameObject(); + GameObject* go = new GameObject; if (!go->LoadFromDB(spawnId, map, true)) { @@ -6909,7 +6904,7 @@ void ObjectMgr::SetHighestGuids() result = WorldDatabase.Query("SELECT MAX(guid) FROM transports"); if (result) - GetGuidSequenceGenerator().Set((*result)[0].GetUInt32() + 1); + GetGuidSequenceGenerator().Set((*result)[0].GetUInt32() + 1); result = CharacterDatabase.Query("SELECT MAX(id) FROM auctionhouse"); if (result) @@ -10212,14 +10207,6 @@ void ObjectMgr::LoadTaxiNodeLevelData() TC_LOG_INFO("server.loading", ">> Loaded %u taxi node level definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } -uint32 ObjectMgr::GetGameObjectTypeByEntry(uint32 entry) const -{ - if (GameObjectTemplate const* goinfo = sObjectMgr->GetGameObjectTemplate(entry)) - return goinfo->type; - - return MAX_GAMEOBJECT_TYPE; -} - void ObjectMgr::InitializeQueriesData(QueryDataGroup mask) { uint32 oldMSTime = getMSTime(); diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 53efb49736..2bd7db72cc 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -1603,8 +1603,6 @@ class TC_GAME_API ObjectMgr bool IsTransportMap(uint32 mapId) const { return _transportMaps.count(mapId) != 0; } - uint32 GetGameObjectTypeByEntry(uint32 entry) const; - VehicleSeatAddon const* GetVehicleSeatAddon(uint32 seatId) const { VehicleSeatAddonContainer::const_iterator itr = _vehicleSeatAddonStore.find(seatId); diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.cpp b/src/server/game/Grids/Notifiers/GridNotifiers.cpp index 88d093de23..0899ade071 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.cpp +++ b/src/server/game/Grids/Notifiers/GridNotifiers.cpp @@ -30,7 +30,7 @@ void VisibleNotifier::SendToSelf() { // at this moment i_clientGUIDs have guids that not iterate at grid level checks // but exist one case when this possible and object not out of range: transports - if (MapTransport* transport = i_player.GetMapTransport()) + if (Transport* transport = i_player.GetTransport()) { for (Transport::PassengerSet::const_iterator itr = transport->GetPassengers().begin(); itr != transport->GetPassengers().end(); ++itr) { diff --git a/src/server/game/Grids/ObjectGridLoader.cpp b/src/server/game/Grids/ObjectGridLoader.cpp index d71c3c9ef7..23fcd54101 100644 --- a/src/server/game/Grids/ObjectGridLoader.cpp +++ b/src/server/game/Grids/ObjectGridLoader.cpp @@ -26,7 +26,6 @@ #include "GameObject.h" #include "ObjectAccessor.h" #include "ObjectMgr.h" -#include "Transport.h" #include "World.h" #include "ScriptMgr.h" @@ -136,33 +135,6 @@ void LoadHelper(CellGuidSet const& guid_set, CellCoord &cell, GridRefManager } } -template <> -void LoadHelper(CellGuidSet const& guid_set, CellCoord& cell, GridRefManager& m, uint32& count, Map* map) -{ - for (CellGuidSet::const_iterator i_guid = guid_set.begin(); i_guid != guid_set.end(); ++i_guid) - { - // Don't spawn at all if there's a respawn timer - ObjectGuid::LowType guid = *i_guid; - if (!map->ShouldBeSpawnedOnGridLoad(guid)) - continue; - - GameObject* obj = nullptr; - GameObjectData const* data = sObjectMgr->GetGameObjectData(guid); - if (data && sObjectMgr->GetGameObjectTypeByEntry(data->id) == GAMEOBJECT_TYPE_TRANSPORT) - obj = new Transport(); - else - obj = new GameObject(); - - //TC_LOG_INFO("misc", "DEBUG: LoadHelper from table: %s for (guid: %u) Loading", table, guid); - if (!obj->LoadFromDB(guid, map, false, false)) - { - delete obj; - continue; - } - AddObjectHelper(cell, m, count, map, obj); - } -} - void ObjectGridLoader::Visit(GameObjectMapType &m) { CellCoord cellCoord = i_cell.GetCellCoord(); diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index a6b86b9c7d..6e75fa7063 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -54,7 +54,6 @@ #include "SharedDefines.h" #include "SocialMgr.h" #include "SystemPackets.h" -#include "Transport.h" #include "World.h" #include "WorldPacket.h" #include "boost/asio/ip/address.hpp" @@ -931,26 +930,6 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder const& holder) loginVerifyWorld.Pos = pCurrChar->GetPosition(); SendPacket(loginVerifyWorld.Write()); - // check if player is on transport and not added earlier to transport - // e.g. in case of loading transport on grid load - if (pCurrChar->GetTransportSpawnID() && !pCurrChar->GetTransport()) - { - Transport* transport = nullptr; - - auto bounds = pCurrChar->GetMap()->GetGameObjectBySpawnIdStore().equal_range(pCurrChar->GetTransportSpawnID()); - if (bounds.first != bounds.second) - transport = bounds.first->second->ToTransport(); - - if (transport) - transport->AddPassenger(pCurrChar); - else - { - pCurrChar->SetTransport(nullptr); - pCurrChar->m_movementInfo.transport.Reset(); - pCurrChar->SetTransportSpawnID(0); - } - } - pCurrChar->UpdatePositionData(); pCurrChar->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Login); pCurrChar->SendInitialPacketsAfterAddToMap(); diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index bda470d9ef..23641859eb 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -93,12 +93,9 @@ void WorldSession::HandleMoveWorldportAck() return; } - float x = loc.GetPositionX(); - float y = loc.GetPositionY(); - float o = loc.GetOrientation(); float z = loc.GetPositionZ() + GetPlayer()->GetHoverOffset(); - GetPlayer()->Relocate(x, y, z, o); + GetPlayer()->Relocate(loc.GetPositionX(), loc.GetPositionY(), z, loc.GetOrientation()); GetPlayer()->SetFallInformation(0, GetPlayer()->GetPositionZ()); GetPlayer()->ResetMap(); @@ -115,16 +112,6 @@ void WorldSession::HandleMoveWorldportAck() return; } - if (Transport* transport = _player->GetTeleportTransport()) - { - transport->CalculatePassengerOffset(x, y, z, &o); - _player->m_movementInfo.transport.pos.Relocate(x, y, z, o); - - transport->AddPassenger(_player); - - _player->ResetTeleportTransport(); - } - // battleground state prepare (in case join to BG), at relogin/tele player not invited // only add to bg group and object, if the player was invited (else he entered through command) if (_player->InBattleground()) @@ -366,7 +353,11 @@ void WorldSession::HandleMovementOpcode(uint16 opcode, MovementInfo& movementInf } if (!mover->GetTransport() && !mover->GetVehicle()) - movementInfo.transport.Reset(); + { + GameObject* go = mover->GetMap()->GetGameObject(movementInfo.transport.guid); + if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT) + movementInfo.transport.guid.Clear(); + } } else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave plrMover->m_transport->RemovePassenger(plrMover); diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 7ae261a520..71ef08b881 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -362,8 +362,6 @@ i_scriptLock(false), _respawnCheckTimer(0) //lets initialize visibility distance for map Map::InitVisibilityDistance(); - GetGuidSequenceGenerator().Set(sObjectMgr->GetGenerator().GetNextAfterMaxUsed()); - _weatherUpdateTimer.SetInterval(time_t(1 * IN_MILLISECONDS)); MMAP::MMapFactory::createOrGetMMapManager()->loadMapInstance(sWorld->GetDataPath(), GetId(), i_InstanceId); @@ -549,7 +547,7 @@ void Map::DeleteFromWorld(Player* player) } template<> -void Map::DeleteFromWorld(MapTransport* transport) +void Map::DeleteFromWorld(Transport* transport) { ObjectAccessor::RemoveObject(transport); delete transport; @@ -763,7 +761,7 @@ bool Map::AddToMap(T* obj) } template<> -bool Map::AddToMap(MapTransport* obj) +bool Map::AddToMap(Transport* obj) { //TODO: Needs clean up. An object should not be added to map twice. if (obj->IsInWorld()) @@ -784,7 +782,7 @@ bool Map::AddToMap(MapTransport* obj) { for (Map::PlayerList::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) { - if (itr->GetSource()->GetMapTransport() != obj) + if (itr->GetSource()->GetTransport() != obj) { UpdateData data(GetId()); obj->BuildCreateUpdateBlockForPlayer(&data, itr->GetSource()); @@ -1123,7 +1121,7 @@ void Map::RemoveFromMap(T *obj, bool remove) } template<> -void Map::RemoveFromMap(MapTransport* obj, bool remove) +void Map::RemoveFromMap(Transport* obj, bool remove) { obj->RemoveFromWorld(); @@ -1735,10 +1733,10 @@ void Map::UnloadAll() for (TransportsContainer::iterator itr = _transports.begin(); itr != _transports.end();) { - MapTransport* transport = *itr; + Transport* transport = *itr; ++itr; - RemoveFromMap(transport, true); + RemoveFromMap(transport, true); } for (auto& cellCorpsePair : _corpsesByCell) @@ -2872,7 +2870,7 @@ void Map::SendInitSelf(Player* player) player->BuildCreateUpdateBlockForPlayer(&data, player); // build other passengers at transport also (they always visible and marked as visible and will not send at visibility update at add to map - if (MapTransport* transport = player->GetMapTransport()) + if (Transport* transport = player->GetTransport()) for (WorldObject* passenger : transport->GetPassengers()) if (player != passenger && player->HaveAtClient(passenger)) passenger->BuildCreateUpdateBlockForPlayer(&data, player); @@ -2888,7 +2886,7 @@ void Map::SendInitTransports(Player* player) UpdateData transData(player->GetMapId()); for (Transport* transport : _transports) { - if (transport != player->GetMapTransport() && player->IsInPhase(transport)) + if (transport != player->GetTransport() && player->IsInPhase(transport)) { transport->BuildCreateUpdateBlockForPlayer(&transData, player); player->m_visibleTransports.insert(transport->GetGUID()); @@ -2906,7 +2904,7 @@ void Map::SendRemoveTransports(Player* player) UpdateData transData(player->GetMapId()); for (Transport* transport : _transports) { - if (transport != player->GetMapTransport()) + if (transport != player->GetTransport()) { transport->BuildOutOfRangeUpdateBlock(&transData); player->m_visibleTransports.erase(transport->GetGUID()); @@ -3459,7 +3457,7 @@ void Map::DelayedUpdate(uint32 t_diff) { for (_transportsUpdateIter = _transports.begin(); _transportsUpdateIter != _transports.end();) { - MapTransport* transport = *_transportsUpdateIter; + Transport* transport = *_transportsUpdateIter; ++_transportsUpdateIter; if (!transport->IsInWorld()) @@ -3564,7 +3562,7 @@ void Map::RemoveAllObjectsInRemoveList() case TYPEID_GAMEOBJECT: { GameObject* go = obj->ToGameObject(); - if (MapTransport* transport = go->ToMapTransport()) + if (Transport* transport = go->ToTransport()) RemoveFromMap(transport, true); else RemoveFromMap(go, true); @@ -4340,22 +4338,13 @@ Pet* Map::GetPet(ObjectGuid const& guid) Transport* Map::GetTransport(ObjectGuid const& guid) { - if (!guid.IsTransport()) + if (!guid.IsMOTransport()) return nullptr; GameObject* go = GetGameObject(guid); return go ? go->ToTransport() : nullptr; } -MapTransport* Map::GetMapTransport(ObjectGuid const& guid) -{ - if (!guid.IsTransport()) - return nullptr; - - GameObject* go = GetGameObject(guid); - return go ? go->ToMapTransport() : nullptr; -} - void Map::UpdateIteratorBack(Player* player) { if (m_mapRefIter == player->GetMapRef()) diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 9e6e03f7a6..d92a5df28e 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -46,7 +46,6 @@ class InstanceMap; class InstanceSave; class InstanceScript; class MapInstanced; -class MapTransport; class Object; class PhaseShift; class Player; @@ -582,7 +581,6 @@ class TC_GAME_API Map : public GridRefManager } Pet* GetPet(ObjectGuid const& guid); Transport* GetTransport(ObjectGuid const& guid); - MapTransport* GetMapTransport(ObjectGuid const& guid); MapStoredObjectTypesContainer& GetObjectsStore() { return _objectsStore; } @@ -788,7 +786,7 @@ class TC_GAME_API Map : public GridRefManager ActiveNonPlayers::iterator m_activeNonPlayersIter; // Objects that must update even in inactive grids without activating them - typedef std::set TransportsContainer; + typedef std::set TransportsContainer; TransportsContainer _transports; TransportsContainer::iterator _transportsUpdateIter; diff --git a/src/server/game/Maps/MapScripts.cpp b/src/server/game/Maps/MapScripts.cpp index ac687da798..5389534f30 100644 --- a/src/server/game/Maps/MapScripts.cpp +++ b/src/server/game/Maps/MapScripts.cpp @@ -315,6 +315,9 @@ void Map::ScriptsProcess() case HighGuid::Corpse: source = GetCorpse(step.sourceGUID); break; + case HighGuid::Mo_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()); @@ -344,6 +347,9 @@ void Map::ScriptsProcess() case HighGuid::Corpse: target = GetCorpse(step.targetGUID); break; + case HighGuid::Mo_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 aecd6e0dd1..c6205d7c12 100644 --- a/src/server/game/Maps/TransportMgr.cpp +++ b/src/server/game/Maps/TransportMgr.cpp @@ -363,7 +363,7 @@ void TransportMgr::AddPathNodeToTransport(uint32 transportEntry, uint32 timeSeg, animNode.Path[timeSeg] = node; } -MapTransport* TransportMgr::CreateTransport(uint32 entry, ObjectGuid::LowType guid /*= 0*/, Map* map /*= nullptr*/, uint8 phaseUseFlags /*= 0*/, uint32 phaseId /*= 0*/, uint32 phaseGroupId /*= 0*/) +Transport* TransportMgr::CreateTransport(uint32 entry, ObjectGuid::LowType guid /*= 0*/, Map* map /*= nullptr*/, uint8 phaseUseFlags /*= 0*/, uint32 phaseId /*= 0*/, uint32 phaseGroupId /*= 0*/) { // instance case, execute GetGameObjectEntry hook if (map) @@ -385,7 +385,7 @@ MapTransport* TransportMgr::CreateTransport(uint32 entry, ObjectGuid::LowType gu } // create transport... - MapTransport* trans = new MapTransport(); + Transport* trans = new Transport(); // ...at first waypoint TaxiPathNodeEntry const* startNode = tInfo->keyFrames.begin()->Node; @@ -396,9 +396,9 @@ MapTransport* TransportMgr::CreateTransport(uint32 entry, ObjectGuid::LowType gu float o = tInfo->keyFrames.begin()->InitialOrientation; // initialize the gameobject base - ObjectGuid::LowType guidLow = guid ? guid : ASSERT_NOTNULL(map)->GenerateLowGuid(); + ObjectGuid::LowType guidLow = guid ? guid : sObjectMgr->GetGenerator().Generate(); - if (!trans->CreateMapTransport(guidLow, entry, mapId, x, y, z, o, 255)) + if (!trans->Create(guidLow, entry, mapId, x, y, z, o, 255)) { delete trans; return nullptr; @@ -419,11 +419,11 @@ MapTransport* TransportMgr::CreateTransport(uint32 entry, ObjectGuid::LowType gu // use preset map for instances (need to know which instance) trans->SetMap(map ? map : sMapMgr->CreateMap(mapId, nullptr)); if (map && map->IsDungeon()) - trans->SetZoneScript(); + trans->m_zoneScript = map->ToInstanceMap()->GetInstanceScript(); // Passengers will be loaded once a player is near - HashMapHolder::Insert(trans); - trans->GetMap()->AddToMap(trans); + HashMapHolder::Insert(trans); + trans->GetMap()->AddToMap(trans); return trans; } @@ -509,63 +509,20 @@ void TransportMgr::CreateInstanceTransports(Map* map) CreateTransport(*itr, 0, map); } -bool TransportAnimation::GetAnimNode(uint32 time, TransportAnimationEntry const*& curr, TransportAnimationEntry const*& next, float& percPos) const +TransportAnimationEntry const* TransportAnimation::GetAnimNode(uint32 time) const { - if (Path.empty()) - return false; + auto itr = Path.lower_bound(time); + if (itr != Path.end()) + return itr->second; - for (TransportPathContainer::const_reverse_iterator itr = Path.rbegin(); itr != Path.rend(); ++itr) - if (time >= itr->first) - { - curr = itr->second; - //ASSERT(itr != Path.rbegin()); - - --itr; - next = itr->second; - - percPos = float(time - curr->TimeIndex) / float(next->TimeIndex - curr->TimeIndex); - - return true; - } - - return false; + return nullptr; } -void TransportAnimation::GetAnimRotation(uint32 time, QuaternionData& curr, QuaternionData& next, float& percRot) const +TransportRotationEntry const* TransportAnimation::GetAnimRotation(uint32 time) const { - if (Rotations.empty()) - { - curr = QuaternionData(0.0f, 0.0f, 0.0f, 1.0f); - next = QuaternionData(0.0f, 0.0f, 0.0f, 1.0f); - percRot = 0.0f; - return; - } + auto itr = Rotations.lower_bound(time); + if (itr != Rotations.end()) + return itr->second; - for (TransportPathRotationContainer::const_reverse_iterator itr = Rotations.rbegin(); itr != Rotations.rend(); ++itr) - if (time >= itr->first) - { - uint32 currSeg = itr->second->TimeIndex; - uint32 nextSeg = 0; - - curr = QuaternionData(itr->second->X, itr->second->Y, itr->second->Z, itr->second->W); - if (itr != Rotations.rbegin()) - { - --itr; - next = QuaternionData(itr->second->X, itr->second->Y, itr->second->Z, itr->second->W); - nextSeg = itr->second->TimeIndex; - } - else - { - next = QuaternionData(Rotations.begin()->second->X, Rotations.begin()->second->Y, Rotations.begin()->second->Z, Rotations.begin()->second->W); - nextSeg = this->TotalTime; - } - - percRot = float(time - currSeg) / float(nextSeg - currSeg); - - return; - } - - curr = QuaternionData(0.0f, 0.0f, 0.0f, 1.0f); - next = QuaternionData(0.0f, 0.0f, 0.0f, 1.0f); - percRot = 0.0f; + return nullptr; } diff --git a/src/server/game/Maps/TransportMgr.h b/src/server/game/Maps/TransportMgr.h index d53cfef7f7..577f8e9d0f 100644 --- a/src/server/game/Maps/TransportMgr.h +++ b/src/server/game/Maps/TransportMgr.h @@ -1,5 +1,5 @@ /* - * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * Copyright (C) 2008-2018 TrinityCore * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -26,7 +26,6 @@ struct KeyFrame; struct GameObjectTemplate; struct TransportTemplate; class Transport; -class MapTransport; class Map; namespace Movement @@ -34,12 +33,12 @@ namespace Movement template class Spline; } -typedef Movement::Spline TransportSpline; -typedef std::vector KeyFrameVec; -typedef std::unordered_map TransportTemplates; -typedef std::set TransportSet; -typedef std::unordered_map TransportMap; -typedef std::unordered_map> TransportInstanceMap; +typedef Movement::Spline TransportSpline; +typedef std::vector KeyFrameVec; +typedef std::unordered_map TransportTemplates; +typedef std::set TransportSet; +typedef std::unordered_map TransportMap; +typedef std::unordered_map > TransportInstanceMap; struct KeyFrame { @@ -66,13 +65,21 @@ struct KeyFrame float NextDistFromPrev; uint32 NextArriveTime; - bool IsTeleportFrame() const { return Teleport; } - bool IsStopFrame() const { return Node->Flags == 2; } + bool IsTeleportFrame() const + { + return Teleport; + } + bool IsStopFrame() const + { + return Node->Flags == 2; + } }; struct TransportTemplate { - TransportTemplate() : inInstance(false), pathTime(0), accelTime(0.0f), accelDist(0.0f), entry(0) { } + TransportTemplate() : inInstance(false), pathTime(0), accelTime(0.0f), accelDist(0.0f), entry(0) + { + } ~TransportTemplate(); std::set mapsUsed; @@ -84,85 +91,85 @@ struct TransportTemplate uint32 entry; }; -struct QuaternionData; - typedef std::map TransportPathContainer; typedef std::map TransportPathRotationContainer; struct TC_GAME_API TransportAnimation { - TransportAnimation() : TotalTime(0) { } + TransportAnimation() : TotalTime(0) + { + } TransportPathContainer Path; TransportPathRotationContainer Rotations; uint32 TotalTime; - bool GetAnimNode(uint32 time, TransportAnimationEntry const*& curr, TransportAnimationEntry const*& next, float& percPos) const; - void GetAnimRotation(uint32 time, QuaternionData& curr, QuaternionData& next, float& percRot) const; + TransportAnimationEntry const* GetAnimNode(uint32 time) const; + TransportRotationEntry const* GetAnimRotation(uint32 time) const; }; typedef std::map TransportAnimationContainer; class TC_GAME_API TransportMgr { - public: - static TransportMgr* instance(); +public: + static TransportMgr* instance(); - void Unload(); + void Unload(); - void LoadTransportTemplates(); + void LoadTransportTemplates(); - void LoadTransportAnimationAndRotation(); + void LoadTransportAnimationAndRotation(); - // Creates a transport using given GameObject template entry - MapTransport* CreateTransport(uint32 entry, ObjectGuid::LowType guid = 0, Map* map = nullptr, uint8 phaseUseFlags = 0, uint32 phaseId = 0, uint32 phaseGroupId = 0); + // Creates a transport using given GameObject template entry + Transport* CreateTransport(uint32 entry, ObjectGuid::LowType guid = 0, Map* map = nullptr, uint8 phaseUseFlags = 0, uint32 phaseId = 0, uint32 phaseGroupId = 0); - // Spawns all continent transports, used at core startup - void SpawnContinentTransports(); + // Spawns all continent transports, used at core startup + void SpawnContinentTransports(); - // creates all transports for instance - void CreateInstanceTransports(Map* map); + // creates all transports for instance + void CreateInstanceTransports(Map* map); - TransportTemplate const* GetTransportTemplate(uint32 entry) const - { - TransportTemplates::const_iterator itr = _transportTemplates.find(entry); - if (itr != _transportTemplates.end()) - return &itr->second; - return nullptr; - } + TransportTemplate const* GetTransportTemplate(uint32 entry) const + { + TransportTemplates::const_iterator itr = _transportTemplates.find(entry); + if (itr != _transportTemplates.end()) + return &itr->second; + return nullptr; + } - TransportAnimation const* GetTransportAnimInfo(uint32 entry) const - { - TransportAnimationContainer::const_iterator itr = _transportAnimations.find(entry); - if (itr != _transportAnimations.end()) - return &itr->second; + TransportAnimation const* GetTransportAnimInfo(uint32 entry) const + { + TransportAnimationContainer::const_iterator itr = _transportAnimations.find(entry); + if (itr != _transportAnimations.end()) + return &itr->second; - return nullptr; - } + return nullptr; + } - private: - TransportMgr(); - ~TransportMgr(); - TransportMgr(TransportMgr const&) = delete; - TransportMgr& operator=(TransportMgr const&) = delete; +private: + TransportMgr(); + ~TransportMgr(); + TransportMgr(TransportMgr const&) = delete; + TransportMgr& operator=(TransportMgr const&) = delete; - // Generates and precaches a path for transport to avoid generation each time transport instance is created - void GeneratePath(GameObjectTemplate const* goInfo, TransportTemplate* transport); + // Generates and precaches a path for transport to avoid generation each time transport instance is created + void GeneratePath(GameObjectTemplate const* goInfo, TransportTemplate* transport); - void AddPathNodeToTransport(uint32 transportEntry, uint32 timeSeg, TransportAnimationEntry const* node); + void AddPathNodeToTransport(uint32 transportEntry, uint32 timeSeg, TransportAnimationEntry const* node); - void AddPathRotationToTransport(uint32 transportEntry, uint32 timeSeg, TransportRotationEntry const* node) - { - _transportAnimations[transportEntry].Rotations[timeSeg] = node; - } + void AddPathRotationToTransport(uint32 transportEntry, uint32 timeSeg, TransportRotationEntry const* node) + { + _transportAnimations[transportEntry].Rotations[timeSeg] = node; + } - // Container storing transport templates - TransportTemplates _transportTemplates; + // Container storing transport templates + TransportTemplates _transportTemplates; - // Container storing transport entries to create for instanced maps - TransportInstanceMap _instanceTransports; + // Container storing transport entries to create for instanced maps + TransportInstanceMap _instanceTransports; - TransportAnimationContainer _transportAnimations; + TransportAnimationContainer _transportAnimations; }; #define sTransportMgr TransportMgr::instance() diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 8fd75e7277..f376f1c55b 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -1870,7 +1870,7 @@ enum GOState : uint8 GO_STATE_ACTIVE = 0, // show in world as used and not reset (closed door open) GO_STATE_READY = 1, // show in world as ready (closed door close) GO_STATE_ACTIVE_ALTERNATIVE = 2, // show in world as used in alt way and not reset (closed door open by cannon fire) - GO_STATE_TRANSPORT_ACTIVE = 24, // transport exclusive: transport moves to first stop frame + GO_STATE_TRANSPORT_ACTIVE = 24, // transport exclusive: transport may always move GO_STATE_TRANSPORT_STOPPED = 25 // transport exclusive: transport is going to stop at provided stop frame }; diff --git a/src/server/game/Pools/PoolMgr.cpp b/src/server/game/Pools/PoolMgr.cpp index dbec6b0231..48bdb6ff47 100644 --- a/src/server/game/Pools/PoolMgr.cpp +++ b/src/server/game/Pools/PoolMgr.cpp @@ -21,7 +21,6 @@ #include "Log.h" #include "MapManager.h" #include "ObjectMgr.h" -#include "Transport.h" //////////////////////////////////////////////////////////// // template class ActivePoolData @@ -352,11 +351,7 @@ void PoolGroup::Spawn1Object(PoolObject* obj) // We use current coords to unspawn, not spawn coords since creature can have changed grid if (map && !map->Instanceable() && map->IsGridLoaded(data->spawnPoint)) { - GameObject* pGameobject = nullptr; - if (sObjectMgr->GetGameObjectTypeByEntry(data->id) == GAMEOBJECT_TYPE_TRANSPORT) - pGameobject = new Transport(); - else - pGameobject = new GameObject(); + GameObject* pGameobject = new GameObject; //TC_LOG_DEBUG("pool", "Spawning gameobject %u", guid); if (!pGameobject->LoadFromDB(obj->guid, map, false)) { diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index c05bbd678a..af7af3e8a1 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -2969,11 +2969,7 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex) uint32 gameobject_id = m_spellInfo->Effects[effIndex].MiscValue; - GameObject* pGameObj = nullptr; - if (sObjectMgr->GetGameObjectTypeByEntry(gameobject_id) == GAMEOBJECT_TYPE_TRANSPORT) - pGameObj = new Transport(); - else - pGameObj = new GameObject(); + GameObject* pGameObj = new GameObject; WorldObject* target = focusObject; if (!target) @@ -4032,11 +4028,7 @@ void Spell::EffectSummonObject(SpellEffIndex effIndex) m_caster->m_ObjectSlot[slot].Clear(); } - GameObject* go = nullptr; - if (sObjectMgr->GetGameObjectTypeByEntry(go_id) == GAMEOBJECT_TYPE_TRANSPORT) - go = new Transport(); - else - go = new GameObject(); + GameObject* go = new GameObject(); float x, y, z, o; // If dest location if present @@ -4847,24 +4839,12 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex) QuaternionData rot = QuaternionData::fromEulerAnglesZYX(fo, 0.f, 0.f); - GameObject* pGameObj = nullptr; - if (goinfo->type == GAMEOBJECT_TYPE_TRANSPORT) + GameObject* pGameObj = new GameObject; + + if (!pGameObj->Create(cMap->GenerateLowGuid(), name_id, cMap, Position(fx, fy, fz, m_caster->GetOrientation()), rot, 255, GO_STATE_READY)) { - pGameObj = new Transport(); - if (!pGameObj->Create(cMap->GenerateLowGuid(), name_id, cMap, Position(fx, fy, fz, fo), rot, 255, GO_STATE_READY)) - { - delete pGameObj; - return; - } - } - else - { - pGameObj = new GameObject(); - if (!pGameObj->Create(cMap->GenerateLowGuid(), name_id, cMap, Position(fx, fy, fz, fo), rot, 255, GO_STATE_READY)) - { - delete pGameObj; - return; - } + delete pGameObj; + return; } PhasingHandler::InheritPhaseShift(pGameObj, m_caster); diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index 7d0fae5de7..e59ff56316 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -1568,7 +1568,7 @@ public: static bool HandleDebugTransportCommand(ChatHandler* handler, char const* args) { - MapTransport* transport = handler->GetSession()->GetPlayer()->GetMapTransport(); + Transport* transport = handler->GetSession()->GetPlayer()->GetTransport(); if (!transport) return false; diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp index 05f73113b2..03e2bd271d 100644 --- a/src/server/scripts/Commands/cs_gobject.cpp +++ b/src/server/scripts/Commands/cs_gobject.cpp @@ -39,7 +39,6 @@ EndScriptData */ #include "Player.h" #include "PoolMgr.h" #include "RBAC.h" -#include "Transport.h" #include "WorldSession.h" // definitions are over in cs_npc.cpp @@ -154,19 +153,8 @@ public: Player* player = handler->GetSession()->GetPlayer(); Map* map = player->GetMap(); - GameObject* object = nullptr; - ObjectGuid::LowType guidLow = ObjectGuid::Empty; - if (objectInfo->type == GAMEOBJECT_TYPE_TRANSPORT) - { - object = new Transport(); - guidLow = map->GenerateLowGuid(); - } - else - { - object = new GameObject(); - guidLow = map->GenerateLowGuid(); - } - + GameObject* object = new GameObject; + ObjectGuid::LowType guidLow = map->GenerateLowGuid(); QuaternionData rotation = QuaternionData::fromEulerAnglesZYX(player->GetOrientation(), 0.f, 0.f); if (!object->Create(guidLow, objectInfo->entry, map, *player, rotation, 255, GO_STATE_READY)) { @@ -190,10 +178,8 @@ public: // this is required to avoid weird behavior and memory leaks delete object; - if (objectInfo->type == GAMEOBJECT_TYPE_TRANSPORT) - object = new Transport(); - else - object = new GameObject(); + object = new GameObject(); + // this will generate a new guid if the object is in an instance if (!object->LoadFromDB(guidLow, map, true)) { diff --git a/src/server/scripts/Commands/cs_group.cpp b/src/server/scripts/Commands/cs_group.cpp index 3e37e9df28..44479266b7 100644 --- a/src/server/scripts/Commands/cs_group.cpp +++ b/src/server/scripts/Commands/cs_group.cpp @@ -154,8 +154,8 @@ public: // before GM float x, y, z; - gmPlayer->GetPosition(x, y, z); - player->TeleportTo(gmPlayer->GetMapId(), x, y, z, player->GetOrientation(), 0, gmPlayer->GetTransport()); + gmPlayer->GetClosePoint(x, y, z, player->GetCombatReach()); + player->TeleportTo(gmPlayer->GetMapId(), x, y, z, player->GetOrientation()); } return true; diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index a0220e756d..6a85fb37db 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -283,12 +283,8 @@ public: object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), object->GetOrientation()); if (Transport* transport = object->GetTransport()) { - int32 transMapID = -1; - if (transport->GetGoType() == GAMEOBJECT_TYPE_MO_TRANSPORT) - transMapID = transport->GetGOInfo()->moTransport.mapID; - handler->PSendSysMessage(LANG_TRANSPORT_POSITION, - transMapID, object->GetTransOffsetX(), object->GetTransOffsetY(), object->GetTransOffsetZ(), object->GetTransOffsetO(), + transport->GetGOInfo()->moTransport.mapID, object->GetTransOffsetX(), object->GetTransOffsetY(), object->GetTransOffsetZ(), object->GetTransOffsetO(), transport->GetEntry(), transport->GetName().c_str()); } handler->PSendSysMessage(LANG_GRID_POSITION, @@ -456,9 +452,9 @@ public: // to point to see at target with same orientation float x, y, z; - target->GetPosition(x, y, z); + target->GetContactPoint(_player, x, y, z); - _player->TeleportTo(target->GetMapId(), x, y, z, _player->GetAngle(target), TELE_TO_GM_MODE, target->GetTransport()); + _player->TeleportTo(target->GetMapId(), x, y, z, _player->GetAngle(target), TELE_TO_GM_MODE); PhasingHandler::InheritPhaseShift(_player, target); _player->UpdateObjectVisibility(); } @@ -589,7 +585,7 @@ public: // before GM float x, y, z; _player->GetPosition(x, y, z); - target->TeleportTo(_player->GetMapId(), x, y, z, target->GetOrientation(), 0, _player->GetTransport()); + target->TeleportTo(_player->GetMapId(), x, y, z, target->GetOrientation()); PhasingHandler::InheritPhaseShift(target, handler->GetSession()->GetPlayer()); target->UpdateObjectVisibility(); } diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index 858d333155..fab9154934 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -349,7 +349,7 @@ public: Player* chr = handler->GetSession()->GetPlayer(); Map* map = chr->GetMap(); - if (MapTransport* trans = chr->GetMapTransport()) + if (Transport* trans = chr->GetTransport()) { ObjectGuid::LowType guid = sObjectMgr->GenerateCreatureSpawnId(); CreatureData& data = sObjectMgr->NewOrExistCreatureData(guid); diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.cpp index ddb14398e6..82faf37ca4 100644 --- a/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.cpp +++ b/src/server/scripts/Kalimdor/HallsOfOrigination/halls_of_origination.cpp @@ -31,7 +31,6 @@ #include "SpellMgr.h" #include "SpellScript.h" #include "TemporarySummon.h" -#include "Transport.h" #include "halls_of_origination.h" enum SunTouchedServant @@ -781,7 +780,7 @@ struct go_hoo_the_makers_lift_controller : public GameObjectAI return true; // Handle elevator: gossip item index => stopFrame (floor index). - Transport* elevator = ObjectAccessor::GetTransportOnMap(*me, instance->GetGuidData(DATA_LIFT_OF_THE_MAKERS)); + GameObject* elevator = instance->GetGameObject(DATA_LIFT_OF_THE_MAKERS); if (!elevator) return true; diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp index ef8571f52f..1cb228c194 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp @@ -1122,7 +1122,7 @@ class npc_jaina_or_sylvanas_escape_hor : public CreatureScript me->RemoveAurasDueToSpell(SPELL_HARVEST_SOUL); if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) Talk(SAY_JAINA_ESCAPE_9); - if (MapTransport* gunship = ObjectAccessor::GetMapTransportOnMap(*me, _instance->GetGuidData(DATA_GUNSHIP))) + if (Transport* gunship = ObjectAccessor::GetTransport(*me, _instance->GetGuidData(DATA_GUNSHIP))) gunship->EnableMovement(true); _instance->SetBossState(DATA_THE_LICH_KING_ESCAPE, DONE); break; @@ -1194,7 +1194,7 @@ class npc_the_lich_king_escape_hor : public CreatureScript if (Creature* target = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_ESCAPE_LEADER))) DoCast(target, SPELL_HARVEST_SOUL); - if (MapTransport* gunship = ObjectAccessor::GetMapTransportOnMap(*me, _instance->GetGuidData(DATA_GUNSHIP))) + if (Transport* gunship = ObjectAccessor::GetTransport(*me, _instance->GetGuidData(DATA_GUNSHIP))) gunship->EnableMovement(true); break; default: diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp index 6ec00aebd6..84f4a09842 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp @@ -393,7 +393,7 @@ class instance_halls_of_reflection : public InstanceMapScript _teamInInstance = player->GetTeam(); } - if (MapTransport* gunship = sTransportMgr->CreateTransport(_teamInInstance == HORDE ? GO_ORGRIMS_HAMMER : GO_THE_SKYBREAKER, 0, instance)) + if (Transport* gunship = sTransportMgr->CreateTransport(_teamInInstance == HORDE ? GO_ORGRIMS_HAMMER : GO_THE_SKYBREAKER, 0, instance)) gunship->EnableMovement(GetBossState(DATA_THE_LICH_KING_ESCAPE) == DONE); } @@ -640,7 +640,7 @@ class instance_halls_of_reflection : public InstanceMapScript if (GetBossState(DATA_THE_LICH_KING_ESCAPE) == DONE) break; - if (MapTransport* gunship = instance->GetMapTransport(GunshipGUID)) + if (Transport* gunship = instance->GetTransport(GunshipGUID)) gunship->EnableMovement(false); if (Creature* jainaOrSylvanas = instance->GetCreature(JainaOrSylvanasEscapeGUID)) @@ -658,7 +658,7 @@ class instance_halls_of_reflection : public InstanceMapScript } break; case EVENT_GUNSHIP_ARRIVAL_2: - if (MapTransport* gunship = instance->GetMapTransport(GunshipGUID)) + if (Transport* gunship = instance->GetTransport(GunshipGUID)) gunship->EnableMovement(false); for (ObjectGuid guid : GunshipStairGUIDs) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp index 6fb6b30d5a..acba0e519d 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp @@ -384,7 +384,7 @@ public: ResetSlots(HORDE); } - void SetTransport(MapTransport* transport) { _transport = transport; } + void SetTransport(Transport* transport) { _transport = transport; } void ResetSlots(uint32 team) { @@ -455,7 +455,7 @@ private: return newPos; } - MapTransport* _transport; + Transport* _transport; ObjectGuid _controlledSlots[MAX_SLOTS]; time_t _respawnCooldowns[MAX_SLOTS]; Position const* _spawnPoint; @@ -495,7 +495,7 @@ public: _caster->CastSpell(_caster, _spellId, true); _caster->GetTransport()->AddObjectToRemoveList(); - if (MapTransport* go = ObjectAccessor::GetMapTransport(_otherTransport)) + if (Transport* go = HashMapHolder::Find(_otherTransport)) go->AddObjectToRemoveList(); return true; @@ -765,10 +765,10 @@ class npc_gunship : public CreatureScript if (isVictory) { - if (MapTransport* trans = ObjectAccessor::GetMapTransport(instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) - trans->EnableMovement(true); + if (Transport* otherTransport = HashMapHolder::Find(instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) + otherTransport->EnableMovement(true); - me->GetMapTransport()->EnableMovement(true); + me->GetTransport()->EnableMovement(true); if (Creature* ship = me->FindNearestCreature(_teamInInstance == HORDE ? NPC_ORGRIMS_HAMMER : NPC_THE_SKYBREAKER, 200.0f)) { @@ -844,7 +844,7 @@ class npc_high_overlord_saurfang_igb : public CreatureScript _instance(creature->GetInstanceScript()) { _controller.ResetSlots(HORDE); - _controller.SetTransport(creature->GetMapTransport()); + _controller.SetTransport(creature->GetTransport()); me->setRegeneratingHealth(false); me->m_CombatDistance = 70.0f; _firstMageCooldown = GameTime::GetGameTime() + 60; @@ -954,7 +954,7 @@ class npc_high_overlord_saurfang_igb : public CreatureScript bool GossipSelect(Player* /*player*/, uint32 /*menuId*/, uint32 /*gossipListId*/) override { me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - me->GetMapTransport()->EnableMovement(true); + me->GetTransport()->EnableMovement(true); _events.SetPhase(PHASE_INTRO); _events.ScheduleEvent(EVENT_INTRO_H_1, 5000, 0, PHASE_INTRO); _events.ScheduleEvent(EVENT_INTRO_H_2, 16000, 0, PHASE_INTRO); @@ -1022,10 +1022,10 @@ class npc_high_overlord_saurfang_igb : public CreatureScript _controller.SummonCreatures(SLOT_MAGE_1, SLOT_MAGE_2); _controller.SummonCreatures(SLOT_MARINE_1, Is25ManRaid() ? SLOT_MARINE_4 : SLOT_MARINE_2); _controller.SummonCreatures(SLOT_SERGEANT_1, Is25ManRaid() ? SLOT_SERGEANT_2 : SLOT_SERGEANT_1); - if (MapTransport* orgrimsHammer = me->GetMapTransport()) + if (Transport* orgrimsHammer = me->GetTransport()) orgrimsHammer->SummonPassenger(NPC_TELEPORT_PORTAL, OrgrimsHammerTeleportPortal, TEMPSUMMON_TIMED_DESPAWN, nullptr, 21000); - if (MapTransport* skybreaker = ObjectAccessor::GetMapTransport(_instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) + if (Transport* skybreaker = HashMapHolder::Find(_instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) skybreaker->SummonPassenger(NPC_TELEPORT_EXIT, SkybreakerTeleportExit, TEMPSUMMON_TIMED_DESPAWN, nullptr, 23000); _events.ScheduleEvent(EVENT_ADDS_BOARD_YELL, 6000); @@ -1108,7 +1108,7 @@ class npc_muradin_bronzebeard_igb : public CreatureScript _instance(creature->GetInstanceScript()) { _controller.ResetSlots(ALLIANCE); - _controller.SetTransport(creature->GetMapTransport()); + _controller.SetTransport(creature->GetTransport()); me->setRegeneratingHealth(false); me->m_CombatDistance = 70.0f; _firstMageCooldown = GameTime::GetGameTime() + 60; @@ -1218,7 +1218,7 @@ class npc_muradin_bronzebeard_igb : public CreatureScript bool GossipSelect(Player* /*player*/, uint32 /*menuId*/, uint32 /*gossipListId*/) override { me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - me->GetMapTransport()->EnableMovement(true); + me->GetTransport()->EnableMovement(true); _events.SetPhase(PHASE_INTRO); _events.ScheduleEvent(EVENT_INTRO_A_1, 5000); _events.ScheduleEvent(EVENT_INTRO_A_2, 10000, 0, PHASE_INTRO); @@ -1290,10 +1290,10 @@ class npc_muradin_bronzebeard_igb : public CreatureScript _controller.SummonCreatures(SLOT_MAGE_1, SLOT_MAGE_2); _controller.SummonCreatures(SLOT_MARINE_1, Is25ManRaid() ? SLOT_MARINE_4 : SLOT_MARINE_2); _controller.SummonCreatures(SLOT_SERGEANT_1, Is25ManRaid() ? SLOT_SERGEANT_2 : SLOT_SERGEANT_1); - if (MapTransport* skybreaker = me->GetMapTransport()) + if (Transport* skybreaker = me->GetTransport()) skybreaker->SummonPassenger(NPC_TELEPORT_PORTAL, SkybreakerTeleportPortal, TEMPSUMMON_TIMED_DESPAWN, nullptr, 21000); - if (MapTransport* orgrimsHammer = ObjectAccessor::GetMapTransport(_instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) + if (Transport* orgrimsHammer = HashMapHolder::Find(_instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) orgrimsHammer->SummonPassenger(NPC_TELEPORT_EXIT, OrgrimsHammerTeleportExit, TEMPSUMMON_TIMED_DESPAWN, nullptr, 23000); _events.ScheduleEvent(EVENT_ADDS_BOARD_YELL, 6000); @@ -1439,7 +1439,7 @@ struct npc_gunship_boarding_addAI : public gunship_npc_AI if (!myTransport) return; - if (MapTransport* destTransport = ObjectAccessor::GetMapTransport(Instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) + if (Transport* destTransport = HashMapHolder::Find(Instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) destTransport->CalculatePassengerPosition(x, y, z, &o); float angle = frand(0, float(M_PI) * 2.0f); @@ -2288,7 +2288,7 @@ class spell_igb_gunship_fall_teleport : public SpellScriptLoader void SelectTransport(WorldObject*& target) { if (InstanceScript* instance = target->GetInstanceScript()) - target = ObjectAccessor::GetMapTransport(instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE)); + target = HashMapHolder::Find(instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE)); } void RelocateDest(SpellEffIndex /*effIndex*/) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp index 6fe3807570..fded4b0877 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp @@ -123,7 +123,6 @@ class instance_icecrown_citadel : public InstanceMapScript UpperSpireTeleporterActiveState = NOT_STARTED; BloodPrinceIntro = 1; SindragosaIntro = 1; - LadyDeathwhisperElevatorTimer = 3000; } // A function to help reduce the number of lines for teleporter management. @@ -436,8 +435,7 @@ class instance_icecrown_citadel : public InstanceMapScript case GO_LADY_DEATHWHISPER_ELEVATOR: LadyDeathwisperElevatorGUID = go->GetGUID(); if (GetBossState(DATA_LADY_DEATHWHISPER) == DONE) - if (Transport* transport = go->ToTransport()) - transport->SetTransportState(GO_STATE_TRANSPORT_ACTIVE); + go->SetTransportState(GO_STATE_TRANSPORT_ACTIVE); break; case GO_THE_SKYBREAKER_H: case GO_ORGRIMS_HAMMER_A: @@ -896,7 +894,7 @@ class instance_icecrown_citadel : public InstanceMapScript { SetBossState(DATA_ICECROWN_GUNSHIP_BATTLE, NOT_STARTED); uint32 gunshipEntry = TeamInInstance == HORDE ? GO_ORGRIMS_HAMMER_H : GO_THE_SKYBREAKER_A; - if (MapTransport* gunship = sTransportMgr->CreateTransport(gunshipEntry, 0, instance)) + if (Transport* gunship = sTransportMgr->CreateTransport(gunshipEntry, 0, instance)) GunshipGUID = gunship->GetGUID(); } } @@ -1167,28 +1165,6 @@ class instance_icecrown_citadel : public InstanceMapScript void Update(uint32 diff) override { - if (LadyDeathwhisperElevatorTimer <= diff) - { - LadyDeathwhisperElevatorTimer = 3000; - if (GetBossState(DATA_LADY_DEATHWHISPER) == DONE) - { - if (Transport* elevator = instance->GetTransport(LadyDeathwisperElevatorGUID)) - { - if (elevator->GetDestinationStopFrameTime() == elevator->GetCurrentTransportTime()) - { - if (!elevator->GetCurrentTransportTime()) - elevator->SetTransportState(GO_STATE_TRANSPORT_STOPPED, 1); - else - elevator->SetTransportState(GO_STATE_TRANSPORT_STOPPED, 0); - - LadyDeathwhisperElevatorTimer = 20000; - } - } - } - } - else - LadyDeathwhisperElevatorTimer -= diff; - if (GetBossState(DATA_THE_LICH_KING) != IN_PROGRESS && GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != FAIL) return; @@ -1244,7 +1220,7 @@ class instance_icecrown_citadel : public InstanceMapScript case EVENT_PLAYERS_GUNSHIP_SPAWN: case EVENT_PLAYERS_GUNSHIP_COMBAT: if (GameObject* go = source->ToGameObject()) - if (MapTransport* transport = go->ToMapTransport()) + if (Transport* transport = go->ToTransport()) transport->EnableMovement(false); break; case EVENT_PLAYERS_GUNSHIP_SAURFANG: @@ -1252,7 +1228,7 @@ class instance_icecrown_citadel : public InstanceMapScript if (Creature* captain = source->FindNearestCreature(TeamInInstance == HORDE ? NPC_IGB_HIGH_OVERLORD_SAURFANG : NPC_IGB_MURADIN_BRONZEBEARD, 100.0f)) captain->AI()->DoAction(ACTION_EXIT_SHIP); if (GameObject* go = source->ToGameObject()) - if (MapTransport* transport = go->ToMapTransport()) + if (Transport* transport = go->ToTransport()) transport->EnableMovement(false); break; } @@ -1353,7 +1329,6 @@ class instance_icecrown_citadel : public InstanceMapScript std::set RimefangTrash; uint8 BloodPrinceIntro; uint8 SindragosaIntro; - uint32 LadyDeathwhisperElevatorTimer; bool IsBonedEligible; bool IsOozeDanceEligible; bool IsNauseaEligible; diff --git a/src/server/scripts/World/world_map_scripts.cpp b/src/server/scripts/World/world_map_scripts.cpp index 35c1acecb4..ce339d84ce 100644 --- a/src/server/scripts/World/world_map_scripts.cpp +++ b/src/server/scripts/World/world_map_scripts.cpp @@ -26,71 +26,6 @@ #include "ObjectMgr.h" #include "SpellInfo.h" -enum DeeprunTram -{ - MAP_DEEPRUN_TRAM = 369, - - GO_SUBWAY = 176080, - MAX_SUBWAY_COUNT = 6 -}; - -Position const SubwaysPos[MAX_SUBWAY_COUNT] = -{ - { 4.580650f, 28.20970f, 7.01107f, 1.5708f }, - { 4.528070f, 8.435290f, 7.01107f, 1.5708f }, - { -45.4005f, 2492.790f, 6.98860f, 1.5708f }, - { -45.4007f, 2512.150f, 6.98860f, 1.5708f }, - { -45.3934f, 2472.930f, 6.98860f, 1.5708f }, - { 4.498830f, -11.3475f, 7.01107f, 1.5708f } -}; - -static QuaternionData worldRotation = QuaternionData(0.0f, 0.0f, 0.7071066f, 0.7071069f); -static QuaternionData parentRotation = QuaternionData(0.0f, 0.0f, 1.0f, -0.0000000437114f); - -class world_map_deeprun_tram: public WorldMapScript -{ - public: - world_map_deeprun_tram() : WorldMapScript("world_map_deeprun_tram", MAP_DEEPRUN_TRAM) - { - Initialize(); - } - - void Initialize() - { - _initializedTrams = false; - } - - void OnPlayerEnter(Map* map, Player* /*player*/) override - { - if (!_initializedTrams) - { - _initializedTrams = true; - - for (uint8 i = 0; i < MAX_SUBWAY_COUNT; ++i) - { - GameObject* transport = new Transport(); - - if (!transport->Create(map->GenerateLowGuid(), GO_SUBWAY + i, map, SubwaysPos[i], worldRotation, 255, GO_STATE_READY)) - { - delete transport; - continue; - } - - transport->SetParentRotation(parentRotation); - - uint32 spawnId = sObjectMgr->GenerateGameObjectSpawnId(); - transport->SetSpawnId(spawnId); - - transport->setActive(true); - transport->SetFarVisible(true); - map->AddToMap(transport); - } - } - } - private: - bool _initializedTrams; -}; - enum Gilneas { MAP_GILNEAS = 654, @@ -162,6 +97,5 @@ class world_map_gilneas: public WorldMapScript void AddSC_world_map_scripts() { - new world_map_deeprun_tram(); new world_map_gilneas(); }