Core/Transports: ported transport refactoring

* this implements full support for stoppable transports as well as serverside transport position tracking
* fixed several vehicle related issues
* fixed gameobject passengers not being displayed as transport passengers
* pets, dynamic objects and other summons are not added as transport passengers and will now properly be displayed
Todo:
- Deeprun Tram visual issues needs to be resolved
- Lady Deathwhisper's elevator needs some additional research
This commit is contained in:
Ovahlord committed 2018-11-21 12:04:26 +01:00
1 parent d8bf3a3170
commit 5229a734dd
49 files changed
+1381 -602

No files matched your search

@@ -0,0 +1 @@
ALTER TABLE `characters` ADD COLUMN `trans_spawn_id` INT(11) UNSIGNED DEFAULT 0 NOT NULL AFTER `transguid`;
@@ -0,0 +1 @@
UPDATE `trinity_string` SET `content_default`='TransMapID: %i TransOffsetX: %f TransOffsetY: %f TransOffsetZ: %f TransOffsetO: %f (Transport ID: %u %s)' WHERE `entry`=186;
@@ -64,8 +64,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_CHARACTER, "SELECT c.guid, account, name, race, class, gender, level, xp, money, skin, face, hairStyle, hairColor, facialStyle, bankSlots, restState, playerFlags, "
"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 "
"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 "
"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);
@@ -383,17 +383,17 @@ 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, "
"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, "
"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=?,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=?,"
"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=?,"
"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=?,online=? WHERE guid=?", CONNECTION_ASYNC);
+22 -6
View File
@@ -30,6 +30,7 @@
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Transport.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include <G3D/g3dmath.h>
@@ -802,13 +803,28 @@ GameObject* Battlefield::SpawnGameObject(uint32 entry, Position const& pos, Quat
return nullptr;
// Create gameobject
GameObject* go = new GameObject;
if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, PHASEMASK_NORMAL, pos, rot, 255, GO_STATE_READY))
GameObject* go = nullptr;
if (sObjectMgr->GetGameObjectTypeByEntry(entry) == GAMEOBJECT_TYPE_TRANSPORT)
{
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;
go = new Transport();
if (!go->Create(map->GenerateLowGuid<HighGuid::Transport>(), entry, map, PHASEMASK_NORMAL, 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(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, PHASEMASK_NORMAL, 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;
}
}
// Add to world
+22 -7
View File
@@ -1470,13 +1470,28 @@ 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 = new GameObject;
if (!go->Create(GetBgMap()->GenerateLowGuid<HighGuid::GameObject>(), entry, GetBgMap(), PHASEMASK_NORMAL, Position(x, y, z, o), rot, 255, goState))
GameObject* go = nullptr;
if (sObjectMgr->GetGameObjectTypeByEntry(entry) == GAMEOBJECT_TYPE_TRANSPORT)
{
TC_LOG_ERROR("bg.battleground", "Battleground::AddObject: cannot create gameobject (entry: %u) for BG (map: %u, instance id: %u)!",
go = new Transport();
if (!go->Create(GetBgMap()->GenerateLowGuid<HighGuid::Transport>(), entry, GetBgMap(), PHASEMASK_NORMAL, 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;
delete go;
return false;
}
}
else
{
go = new GameObject();
if (!go->Create(GetBgMap()->GenerateLowGuid<HighGuid::GameObject>(), entry, GetBgMap(), PHASEMASK_NORMAL, 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;
}
}
/*
@@ -1592,7 +1607,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*/, Transport* transport)
Creature* Battleground::AddCreature(uint32 entry, uint32 type, float x, float y, float z, float o, TeamId /*teamId = TEAM_NEUTRAL*/, uint32 respawntime /*= 0*/, MapTransport* transport)
{
// If the assert is called, means that BgCreatures must be resized!
ASSERT(type < BgCreatures.size());
@@ -1646,7 +1661,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*/, Transport* transport)
Creature* Battleground::AddCreature(uint32 entry, uint32 type, Position const& pos, TeamId teamId /*= TEAM_NEUTRAL*/, uint32 respawntime /*= 0*/, MapTransport* transport)
{
return AddCreature(entry, type, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teamId, respawntime, transport);
}
+3 -3
View File
@@ -31,7 +31,7 @@ class Creature;
class GameObject;
class Group;
class Player;
class Transport;
class MapTransport;
class Unit;
class WorldObject;
class WorldPacket;
@@ -457,8 +457,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, Transport* transport = nullptr);
Creature* AddCreature(uint32 entry, uint32 type, Position const& pos, TeamId teamId = TEAM_NEUTRAL, uint32 respawntime = 0, Transport* transport = nullptr);
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);
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);
@@ -985,8 +985,8 @@ class BattlegroundIC : public Battleground
BG_IC_GateState GateStatus[6];
ICNodePoint nodePoint[7];
Transport* gunshipAlliance;
Transport* gunshipHorde;
MapTransport* gunshipAlliance;
MapTransport* gunshipHorde;
uint32 GetNextBanner(ICNodePoint* node, uint32 team, bool returnDefinitve);
@@ -26,6 +26,7 @@
#include "ObjectMgr.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "Transport.h"
#include "UpdateData.h"
#include "WorldPacket.h"
@@ -281,10 +282,9 @@ bool BattlegroundSA::ResetObjs()
UpdateWorldState(BG_SA_YELLOW_GATEWS, 1);
UpdateWorldState(BG_SA_ANCIENT_GATEWS, 1);
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);
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,23 +298,27 @@ void BattlegroundSA::StartShips()
if (ShipsStarted)
return;
DoorOpen(BG_SA_BOAT_ONE);
DoorOpen(BG_SA_BOAT_TWO);
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_ACTIVE);
for (int i = BG_SA_BOAT_ONE; i <= BG_SA_BOAT_TWO; i++)
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
{
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
if (Player* p = ObjectAccessor::FindPlayer(itr->first))
{
if (Player* p = ObjectAccessor::FindPlayer(itr->first))
{
UpdateData data(p->GetMapId());
WorldPacket pkt;
GetBGObject(i)->BuildValuesUpdateBlockForPlayer(&data, p);
data.BuildPacket(&pkt);
p->SendDirectMessage(&pkt);
}
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);
}
}
ShipsStarted = true;
}
@@ -92,8 +92,6 @@ 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();
}
@@ -165,7 +163,7 @@ void GameObject::AddToWorld()
bool toggledState = GetGoType() == GAMEOBJECT_TYPE_CHEST ? getLootState() == GO_READY : (GetGoState() == GO_STATE_READY || IsTransport());
if (m_model)
{
if (Transport* trans = ToTransport())
if (MapTransport* trans = ToMapTransport())
trans->SetDelayedAddModelToMap();
else
GetMap()->InsertGameObjectModel(*m_model);
@@ -235,9 +233,6 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, u
return false;
}
if (goinfo->type == GAMEOBJECT_TYPE_TRANSPORT)
m_updateFlag |= UPDATEFLAG_TRANSPORT;
Object::_Create(guidlow, goinfo->entry, HighGuid::GameObject);
m_goInfo = goinfo;
@@ -293,36 +288,6 @@ bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, u
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<uint32>();
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;
@@ -414,53 +379,6 @@ 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)
@@ -2314,48 +2232,6 @@ 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);
@@ -2454,7 +2330,6 @@ 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();
@@ -2498,16 +2373,12 @@ 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:
{
if (uint32 transportPeriod = GetTransportPeriod())
Transport const* transport = ToTransport();
if (uint32 transportPeriod = transport->GetTransportPeriod())
{
float timer = float(m_goValue.Transport.PathProgress % transportPeriod);
float timer = float(transport->GetPathProgress() % transportPeriod);
pathProgress = int16(timer / float(transportPeriod) * 65535.0f);
}
break;
@@ -2528,27 +2399,6 @@ 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
}
@@ -2631,3 +2481,72 @@ GameObjectModel* GameObject::CreateModel()
{
return GameObjectModel::Create(Trinity::make_unique<GameObjectModelOwnerImpl>(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<Transport*>(this);
return nullptr;
}
Transport const* GameObject::ToTransport() const
{
if (IsTransport())
return reinterpret_cast<Transport const*>(this);
return nullptr;
}
MapTransport* GameObject::ToMapTransport()
{
if (GetGOInfo()->type == GAMEOBJECT_TYPE_MO_TRANSPORT)
return reinterpret_cast<MapTransport*>(this);
return nullptr;
}
MapTransport const* GameObject::ToMapTransport() const
{
if (GetGOInfo()->type == GAMEOBJECT_TYPE_MO_TRANSPORT)
return reinterpret_cast<MapTransport const*>(this);
return nullptr;
}
@@ -42,9 +42,7 @@ union GameObjectValue
{
uint32 PathProgress;
TransportAnimation const* AnimationInfo;
uint32 CurrentSeg;
std::vector<uint32>* StopFrames;
uint32 StateUpdateTimer;
} Transport;
//25 GAMEOBJECT_TYPE_FISHINGHOLE
struct
@@ -91,7 +89,7 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
void RemoveFromWorld() override;
void CleanupsBeforeDelete(bool finalCleanup = true) override;
bool Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, uint32 phaseMask, Position const& pos, QuaternionData const& rotation, uint32 animprogress, GOState go_state, uint32 artKit = 0, bool dynamic = false, ObjectGuid::LowType spawnid = 0);
virtual bool Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, uint32 phaseMask, 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,8 +161,6 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
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); }
@@ -274,14 +270,17 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
GameObjectModel* m_model;
void GetRespawnPosition(float &x, float &y, float &z, float* ori = nullptr) const;
Transport* ToTransport() { if (GetGOInfo()->type == GAMEOBJECT_TYPE_MO_TRANSPORT) return reinterpret_cast<Transport*>(this); else return nullptr; }
Transport const* ToTransport() const { if (GetGOInfo()->type == GAMEOBJECT_TYPE_MO_TRANSPORT) return reinterpret_cast<Transport const*>(this); else return nullptr; }
Transport* ToTransport();
Transport const* ToTransport() const;
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); }
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 GetInteractionDistance() const;
@@ -290,6 +289,8 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
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
+69 -67
View File
@@ -164,41 +164,13 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
if (!target)
return;
uint8 updateType = UPDATETYPE_CREATE_OBJECT;
uint8 updateType = m_isNewObject ? UPDATETYPE_CREATE_OBJECT2 : UPDATETYPE_CREATE_OBJECT;
uint16 flags = m_updateFlag;
/** lower flag1 **/
if (target == this) // building packet for yourself
flags |= UPDATEFLAG_SELF;
if (m_isNewObject)
{
switch (GetGUID().GetHigh())
{
case HighGuid::Player:
case HighGuid::Pet:
case HighGuid::Corpse:
case HighGuid::DynamicObject:
updateType = UPDATETYPE_CREATE_OBJECT2;
break;
case HighGuid::Unit:
case HighGuid::Vehicle:
{
if (ToUnit()->IsSummon())
updateType = UPDATETYPE_CREATE_OBJECT2;
break;
}
case HighGuid::GameObject:
{
if (ToGameObject()->GetOwnerGUID().IsPlayer())
updateType = UPDATETYPE_CREATE_OBJECT2;
break;
}
default:
break;
}
}
if (WorldObject const* worldObject = dynamic_cast<WorldObject const*>(this))
{
if (!(flags & UPDATEFLAG_LIVING))
@@ -207,29 +179,17 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
if (worldObject->GetAIAnimKitId() || worldObject->GetMovementAnimKitId() || worldObject->GetMeleeAnimKitId())
flags |= UPDATEFLAG_ANIMKITS;
if (!worldObject->m_movementInfo.transport.guid.IsEmpty() && (ToGameObject() || ToDynObject()))
flags |= UPDATEFLAG_GO_TRANSPORT_POSITION;
}
if (flags & UPDATEFLAG_STATIONARY_POSITION)
{
// UPDATETYPE_CREATE_OBJECT2 dynamic objects, corpses...
if (isType(TYPEMASK_DYNAMICOBJECT | TYPEMASK_CORPSE | TYPEMASK_PLAYER))
updateType = UPDATETYPE_CREATE_OBJECT2;
// UPDATETYPE_CREATE_OBJECT2 for pets...
if (target->GetPetGUID() == GetGUID())
updateType = UPDATETYPE_CREATE_OBJECT2;
// UPDATETYPE_CREATE_OBJECT2 for some gameobject types...
if (isType(TYPEMASK_GAMEOBJECT))
{
switch (ToGameObject()->GetGoType())
{
case GAMEOBJECT_TYPE_TRAP:
case GAMEOBJECT_TYPE_DUEL_ARBITER:
case GAMEOBJECT_TYPE_FLAGSTAND:
case GAMEOBJECT_TYPE_FLAGDROP:
updateType = UPDATETYPE_CREATE_OBJECT2;
break;
case GAMEOBJECT_TYPE_TRANSPORT:
flags |= UPDATEFLAG_TRANSPORT;
break;
@@ -596,7 +556,7 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
if (flags & UPDATEFLAG_VEHICLE)
{
*data << float(self->GetOrientation());
*data << float(self->GetTransport() ? self->GetTransOffsetO() : self->GetOrientation());
*data << uint32(self->GetVehicleKit()->GetVehicleInfo()->m_ID);
}
@@ -605,20 +565,20 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
WorldObject const* self = static_cast<WorldObject const*>(this);
ObjectGuid transGuid = self->m_movementInfo.transport.guid;
data->WriteBit(transGuid[0]);
data->WriteBit(transGuid[5]);
data->WriteByteSeq(transGuid[0]);
data->WriteByteSeq(transGuid[5]);
if (hasVehicleId)
*data << uint32(self->m_movementInfo.transport.vehicleId);
data->WriteBit(transGuid[3]);
data->WriteByteSeq(transGuid[3]);
*data << float(self->GetTransOffsetX());
data->WriteBit(transGuid[4]);
data->WriteBit(transGuid[6]);
data->WriteBit(transGuid[1]);
data->WriteByteSeq(transGuid[4]);
data->WriteByteSeq(transGuid[6]);
data->WriteByteSeq(transGuid[1]);
*data << uint32(self->GetTransTime());
*data << float(self->GetTransOffsetY());
data->WriteBit(transGuid[2]);
data->WriteBit(transGuid[7]);
data->WriteByteSeq(transGuid[2]);
data->WriteByteSeq(transGuid[7]);
*data << float(self->GetTransOffsetZ());
*data << int8(self->GetTransSeat());
*data << float(self->GetTransOffsetO());
@@ -685,16 +645,13 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const
if (flags & UPDATEFLAG_TRANSPORT)
{
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());
if (GameObject const* go = ToGameObject())
{
if (go->IsDynTransport())
*data << uint32(go->ToTransport()->GetPathProgress());
else
*data << uint32(getMSTime());
}
}
}
@@ -2140,6 +2097,19 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert
return nullptr;
}
if (summon->GetTransGUID().IsEmpty() && summoner)
{
if (Transport* transport = 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);
}
}
// Set the summon to the summoner's phase
if (summoner)
PhasingHandler::InheritPhaseShift(summon, summoner);
@@ -2238,11 +2208,24 @@ GameObject* WorldObject::SummonGameObject(uint32 entry, Position const& pos, Qua
}
Map* map = GetMap();
GameObject* go = new GameObject();
if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, GetPhaseMask(), pos, rot, 255, GO_STATE_READY))
GameObject* go = nullptr;
if (goinfo->type == GAMEOBJECT_TYPE_TRANSPORT)
{
delete go;
return nullptr;
go = new Transport();
if (!go->Create(map->GenerateLowGuid<HighGuid::Transport>(), entry, map, GetPhaseMask(), pos, rot, 255, GO_STATE_READY))
{
delete go;
return nullptr;
}
}
else
{
go = new GameObject();
if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, GetPhaseMask(), pos, rot, 255, GO_STATE_READY))
{
delete go;
return nullptr;
}
}
PhasingHandler::InheritPhaseShift(go, this);
@@ -2253,6 +2236,17 @@ 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;
}
@@ -2756,6 +2750,14 @@ ObjectGuid WorldObject::GetTransGUID() const
return ObjectGuid::Empty;
}
MapTransport* WorldObject::GetMapTransport() const
{
if (GetTransport())
return GetTransport()->ToMapTransport();
return nullptr;
}
float WorldObject::GetFloorZ() const
{
if (!IsInWorld())
+3
View File
@@ -47,6 +47,7 @@ class Map;
class Player;
class TempSummon;
class Transport;
class MapTransport;
class Unit;
class UpdateData;
class WorldObject;
@@ -460,6 +461,8 @@ 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(); }
@@ -53,7 +53,6 @@ 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";
@@ -133,6 +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::Transport)
GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Instance)
GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Group)
+17 -11
View File
@@ -64,7 +64,6 @@ 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
@@ -72,7 +71,7 @@ enum class HighGuid
Corpse = 0xF101, // blizz F100
AreaTrigger = 0xF102,
BattleGround = 0x1F1,
Mo_Transport = 0x1FC, // blizz 1FC0 (for GAMEOBJECT_TYPE_MO_TRANSPORT)
Transport = 0x1FC, // blizz 1FC0
Instance = 0x1F4, // blizz 1F40
Group = 0x1F5,
Guild = 0x1FF
@@ -99,13 +98,11 @@ 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);
@@ -119,6 +116,18 @@ 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<HighGuid::Transport>
{
static bool const Global = true;
static bool const MapSpecific = true;
};
class ObjectGuid;
class PackedGuid;
@@ -139,8 +148,7 @@ class TC_GAME_API ObjectGuid
static typename std::enable_if<ObjectGuidTraits<type>::Global, ObjectGuid>::type Create(LowType counter) { return Global(type, counter); }
template<HighGuid type>
static typename std::enable_if<ObjectGuidTraits<type>::MapSpecific, ObjectGuid>::type Create(uint32 entry, LowType counter) { return MapSpecific(type, entry, counter); }
static typename std::enable_if<ObjectGuidTraits<type>::MapSpecific && type != HighGuid::Transport, ObjectGuid>::type Create(uint32 entry, LowType counter) { return MapSpecific(type, entry, counter); }
ObjectGuid() { _data._guid = UI64LIT(0); }
explicit ObjectGuid(uint64 guid) { _data._guid = guid; }
@@ -198,8 +206,7 @@ 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 IsMOTransport() const { return GetHigh() == HighGuid::Mo_Transport; }
bool IsAnyTypeGameObject() const { return IsGameObject() || IsTransport() || IsMOTransport(); }
bool IsAnyTypeGameObject() const { return IsGameObject() || IsTransport(); }
bool IsInstance() const { return GetHigh() == HighGuid::Instance; }
bool IsGroup() const { return GetHigh() == HighGuid::Group; }
bool IsGuild() const { return GetHigh() == HighGuid::Guild; }
@@ -217,7 +224,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::Mo_Transport: return TYPEID_GAMEOBJECT;
case HighGuid::Transport: return TYPEID_GAMEOBJECT;
case HighGuid::Vehicle: return TYPEID_UNIT;
// unknown
case HighGuid::Instance:
@@ -248,12 +255,11 @@ class TC_GAME_API ObjectGuid
case HighGuid::Player:
case HighGuid::DynamicObject:
case HighGuid::Corpse:
case HighGuid::Mo_Transport:
case HighGuid::Transport:
case HighGuid::Instance:
case HighGuid::Group:
return false;
case HighGuid::GameObject:
case HighGuid::Transport:
case HighGuid::Unit:
case HighGuid::Pet:
case HighGuid::Vehicle:
+45
View File
@@ -28,6 +28,7 @@
#include "SpellHistory.h"
#include "SpellAuras.h"
#include "SpellAuraEffects.h"
#include "Transport.h"
#include "Unit.h"
#include "Util.h"
#include "Group.h"
@@ -185,6 +186,17 @@ 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;
}
@@ -273,6 +285,17 @@ 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); (x, y, z, o);
transport->AddPassenger(this);
}
owner->SetMinion(this, true);
map->AddToMap(ToCreature());
@@ -748,6 +771,17 @@ 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;
}
@@ -761,6 +795,17 @@ 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;
}
+141 -48
View File
@@ -242,6 +242,7 @@ Player::Player(WorldSession* session): Unit(true)
m_bCanDelayTeleport = false;
m_bHasDelayedTeleport = false;
m_teleport_options = 0;
m_teleport_transport = nullptr;
m_trade = nullptr;
@@ -414,6 +415,8 @@ Player::Player(WorldSession* session): Unit(true)
_hasValidLFGLeavePoint = false;
_archaeology = new Archaeology(this);
m_petScalingSynchTimer.Reset(1000);
_transportSpawnID = 0;
}
Player::~Player()
@@ -1399,7 +1402,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);
TeleportTo(m_teleport_dest, m_teleport_options, m_teleport_transport);
}
@@ -1676,7 +1679,7 @@ uint8 Player::GetChatTag() const
return tag;
}
bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options)
bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options, Transport* transport)
{
if (!MapManager::IsValidMapCoord(mapid, x, y, z, orientation))
{
@@ -1755,6 +1758,7 @@ 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;
}
@@ -1771,10 +1775,12 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
// this will be used instead of the current location in SaveToDB
m_teleport_dest = WorldLocation(mapid, x, y, z, orientation);
SetFallInformation(0, GetPositionZ());
m_teleport_transport = transport;
// code for finish transfer called in WorldSession::HandleMovementOpcodes()
// at client packet CMSG_MOVE_TELEPORT_ACK
SetSemaphoreTeleportNear(true);
if (!GetTransport())
SetSemaphoreTeleportNear(true);
// near teleport, triggering send CMSG_MOVE_TELEPORT_ACK from client at landing
if (!GetSession()->PlayerLogout())
{
@@ -1817,6 +1823,7 @@ 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;
}
@@ -1883,6 +1890,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
oldmap->RemovePlayerFromMap(this, false);
m_teleport_dest = WorldLocation(mapid, x, y, z, orientation);
m_teleport_transport = transport;
SetFallInformation(0, GetPositionZ());
// if the player is saved before worldportack (at logout for example)
// this will be used instead of the current location in SaveToDB
@@ -1910,9 +1918,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*/)
bool Player::TeleportTo(WorldLocation const& loc, uint32 options /*= 0*/, Transport* transport /*=nullptr*/)
{
return TeleportTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), loc.GetOrientation(), options);
return TeleportTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), loc.GetOrientation(), options, transport);
}
bool Player::TeleportToBGEntryPoint()
@@ -17336,8 +17344,8 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder* holder)
//"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
//"knownTitles, actionBars, grantableLevels, fishing_steps FROM characters WHERE guid = '%u'", guid);
// 62 63 64 65 66
//"knownTitles, actionBars, grantableLevels, fishing_steps, trans_spawn_id FROM characters WHERE guid = '%u'", guid);
PreparedQueryResult result = holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_FROM);
if (!result)
@@ -17479,6 +17487,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder* holder)
// 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());
@@ -17593,45 +17602,119 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder* holder)
// currently we do not support transport in bg
else if (transLowGUID)
{
ObjectGuid transGUID(HighGuid::Mo_Transport, transLowGUID);
Transport* transport = nullptr;
if (Transport* go = HashMapHolder<Transport>::Find(transGUID))
transport = go;
if (transport)
// if transSpawnId presents, then search for static transport (e.g. elevator)
// else - needs motiontransport
if (transSpawnId)
{
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)
if (map = sMapMgr->CreateMap(mapId, this, instanceId))
{
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);
auto bounds = map->GetGameObjectBySpawnIdStore().equal_range(transSpawnId);
if (bounds.first != bounds.second)
m_transport = bounds.first->second->ToTransport();
}
m_movementInfo.transport.Reset();
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);
RelocateToHomebind();
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);
}
}
else
{
Relocate(x, y, z, o);
mapId = transport->GetMapId();
// 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();
transport->AddPassenger(this);
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.GetPositionX()) > 250.0f ||
std::fabs(m_movementInfo.transport.pos.GetPositionX()) > 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);
}
}
}
}
else
{
TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) has problems with transport guid (%u). Teleport to bind location.",
guid.ToString().c_str(), transLowGUID);
ObjectGuid transGUID = ObjectGuid::Create<HighGuid::Transport>(transLowGUID);
RelocateToHomebind();
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.GetPositionX()) > 250.0f ||
std::fabs(m_movementInfo.transport.pos.GetPositionX()) > 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();
}
}
}
// currently we do not support taxi in instance
@@ -19830,9 +19913,14 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setFloat(index++, finiteAlways(GetTransOffsetZ()));
stmt->setFloat(index++, finiteAlways(GetTransOffsetO()));
ObjectGuid::LowType transLowGUID = 0;
if (GetTransport())
transLowGUID = GetTransport()->GetGUID().GetCounter();
uint32 transSpawnId = 0;
if (Transport* transport = GetTransport())
{
transLowGUID = transport->GetGUID().GetCounter();
transSpawnId = transport->GetSpawnId();
}
stmt->setUInt32(index++, transLowGUID);
stmt->setUInt32(index++, transSpawnId);
std::ostringstream ss;
ss << m_taxi;
@@ -19965,9 +20053,14 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setFloat(index++, finiteAlways(GetTransOffsetZ()));
stmt->setFloat(index++, finiteAlways(GetTransOffsetO()));
ObjectGuid::LowType transLowGUID = 0;
if (GetTransport())
transLowGUID = GetTransport()->GetGUID().GetCounter();
uint32 transSpawnId = 0;
if (Transport* transport = GetTransport())
{
transLowGUID = transport->GetGUID().GetCounter();
transSpawnId = transport->GetSpawnId();
}
stmt->setUInt32(index++, transLowGUID);
stmt->setUInt32(index++, transSpawnId);
std::ostringstream ss;
ss << m_taxi;
@@ -23344,17 +23437,6 @@ 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<Unit*>& /*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<Unit*>& v)
{
@@ -28004,6 +28086,17 @@ 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:
+10 -2
View File
@@ -1035,8 +1035,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void SetObjectScale(float scale) override;
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options = 0);
bool TeleportTo(WorldLocation const& loc, uint32 options = 0);
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 TeleportToBGEntryPoint();
bool HasSummonPending() const;
@@ -1923,6 +1923,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void LearnSkillRewardedSpells(uint32 skillId, uint32 skillValue);
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; }
@@ -2378,6 +2380,9 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
// Mount Capabilites
void UpdateMountCapabilities();
uint32 GetTransportSpawnID() const { return _transportSpawnID; }
void SetTransportSpawnID(uint32 spawnId) { _transportSpawnID = spawnId; }
protected:
// Gamemaster whisper whitelist
GuidList WhisperList;
@@ -2717,6 +2722,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
// Current teleport data
WorldLocation m_teleport_dest;
uint32 m_teleport_options;
Transport* m_teleport_transport;
bool mSemaphoreTeleport_Near;
bool mSemaphoreTeleport_Far;
@@ -2758,6 +2764,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
std::vector<PlayerPetData*> PlayerPetDataStore;
TimeTrackerSmall m_petScalingSynchTimer;
uint32 _transportSpawnID;
};
TC_GAME_API void AddItemsSetItem(Player* player, Item* item);
+544 -125
View File
@@ -31,48 +31,541 @@
#include "Totem.h"
#include "UpdateData.h"
#include "Vehicle.h"
#include "ZoneScript.h"
Transport::Transport() : GameObject(),
_transportInfo(nullptr), _isMoving(true), _pendingStop(false),
_triggeredArrivalEvent(false), _triggeredDepartureEvent(false),
_passengerTeleportItr(_passengers.begin()), _delayedAddModel(false), _delayedTeleport(false)
_passengerTeleportItr(_passengers.begin()), _currentTransportTime(0), _destinationStopFrameTime(0),
_alignmentTransportTime(0), _lastStopFrameTime(0), _isDynamicTransport(false), _initialRelocate(false)
{
m_updateFlag = UPDATEFLAG_TRANSPORT | UPDATEFLAG_LOWGUID | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_ROTATION;
m_updateFlag |= UPDATEFLAG_TRANSPORT;
}
Transport::~Transport()
{
ASSERT(_passengers.empty());
UnloadStaticPassengers();
if (m_goInfo && m_goInfo->type == GAMEOBJECT_TYPE_TRANSPORT)
delete m_goValue.Transport.StopFrames;
}
bool Transport::Create(ObjectGuid::LowType guidlow, uint32 entry, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress)
void Transport::CleanupsBeforeDelete(bool finalCleanup /*= true*/)
{
Relocate(x, y, z, ang);
if (!IsPositionValid())
while (!_passengers.empty())
{
TC_LOG_ERROR("entities.transport", "Transport (GUID: %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)",
guidlow, x, y);
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 = GetPathProgress();
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, uint32 /*phaseMask*/, Position const& pos, QuaternionData const& rotation, uint32 animprogress, GOState go_state, uint32 artKit /*= 0*/, bool dynamic, ObjectGuid::LowType spawnid)
{
ASSERT(map);
SetMap(map);
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;
}
Object::_Create(guidlow, 0, HighGuid::Mo_Transport);
m_stationaryPosition.Relocate(pos);
GameObjectAddon const* gameObjectAddon = sObjectMgr->GetGameObjectAddon(GetSpawnId());
SetWorldRotation(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<uint32>();
if (m_goInfo->transport.Timeto2ndfloor > 0)
{
// If we have a stop frame we also need an additional one at 0ms
m_goValue.Transport.StopFrames->push_back(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);
_isDynamicTransport = m_goValue.Transport.StopFrames->empty();
uint32 pathProgress = getMSTime();
if (m_goValue.Transport.AnimationInfo)
pathProgress -= pathProgress % GetTransportPeriod();
uint32 stopTimer = 0;
if (m_goInfo->transport.startOpen)
{
SetGoState(GO_STATE_TRANSPORT_STOPPED);
stopTimer = m_goValue.Transport.StopFrames->at(m_goInfo->transport.startOpen - 1);
_initialRelocate = true;
}
else
SetGoState(GO_STATE_TRANSPORT_ACTIVE);
SetPathProgress(pathProgress + 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);
if (!IsPositionValid())
{
TC_LOG_ERROR("entities.transport", "Transport (GUID: %u) not created. Suggested coordinates isn't valid %s",
guidlow, pos.ToString().c_str());
return false;
}
Object::_Create(guidlow, 0, HighGuid::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, x, y, z, ang);
TC_LOG_ERROR("sql.sql", "Transport not created: entry in `gameobject_template` not found, guidlow: %u map: %u (Position: %s) ang: %f", guidlow, mapid, pos.ToString().c_str());
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())
{
SetPathProgress(GetPathProgress() + diff);
SetCurrentTransportTime(GetCurrentTransportTime() + diff);
if (GetCurrentTransportTime() >= GetTransportPeriod())
SetCurrentTransportTime(GetCurrentTransportTime() % GetTransportPeriod());
}
else
{
if (GetGoState() == GO_STATE_TRANSPORT_ACTIVE)
{
// waiting at it's destination for state change, do nothing
if (GetCurrentTransportTime() == GetDestinationStopFrameTime())
return;
SetPathProgress(GetPathProgress() + diff);
// GOState has changed before previous state was reached, move to new destination immediately
if (GetCurrentTransportTime() < GetDestinationStopFrameTime())
SetCurrentTransportTime(0);
else if (GetCurrentTransportTime() + diff < GetTransportPeriod())
SetCurrentTransportTime(GetCurrentTransportTime() + diff);
else
SetCurrentTransportTime(0);
}
else
{
// waiting at it's destination for state change, do nothing
if (GetCurrentTransportTime() == GetDestinationStopFrameTime())
return;
int32 currentTime = GetCurrentTransportTime();
int32 destinationTime = GetDestinationStopFrameTime();
bool backwardsMovement = destinationTime < currentTime;
SetPathProgress(GetPathProgress() + std::max(0, int32(backwardsMovement ? (diff * -1) : diff)));
if (!backwardsMovement)
{
// GOState has changed before previous state was reached, move to new destination immediately
if (currentTime > destinationTime)
SetCurrentTransportTime(destinationTime);
else if (int32(currentTime + diff) < destinationTime)
SetCurrentTransportTime(currentTime + diff);
else
{
SetCurrentTransportTime(destinationTime);
SetAlignmentTransportTime(0);
}
}
else
{
uint32 timeDiff = diff;
// Skipping multiple stop frames while moving to frame 0. Align the steps to the travel time.
if (uint32 alignmentTime = GetAlightmentTransportTime())
{
float alignmentPercentage = (float)alignmentTime / GetLastStopFrameTime();
timeDiff += diff * alignmentPercentage;
}
// GOState has changed before previous state was reached, move to new destination immediately
if (currentTime < destinationTime)
currentTime = destinationTime;
else if (int32(currentTime - timeDiff) > destinationTime)
currentTime -= timeDiff;
else
{
currentTime = destinationTime;
SetAlignmentTransportTime(0);
}
SetCurrentTransportTime(currentTime);
}
}
}
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->X, curr->Y, curr->Z);
// move by percentage of segment already passed
pos += G3D::Vector3(percPos * (next->X - curr->X), percPos * (next->Y - curr->Y), percPos * (next->Z - curr->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)
{
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;
// if spline enabled, position will be updated in Unit::UpdateSplinePosition
if (unit->IsSplineEnabled())
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:
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();
}
}
uint32 Transport::GetTransportPeriod() const
{
ASSERT(m_goInfo->type == GAMEOBJECT_TYPE_TRANSPORT);
if (m_goValue.Transport.AnimationInfo)
return m_goValue.Transport.AnimationInfo->TotalTime;
return 0;
}
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 backwardsTimer = 0;
if (state == GO_STATE_TRANSPORT_ACTIVE)
{
if (GetGoState() >= GO_STATE_TRANSPORT_STOPPED)
stopTimer = m_goValue.Transport.StopFrames->at(GetGoState() - GO_STATE_TRANSPORT_STOPPED);
SetUInt32Value(GAMEOBJECT_LEVEL, getMSTime() + stopTimer);
}
else
{
ASSERT(state < GOState(GO_STATE_TRANSPORT_STOPPED + MAX_GO_STATE_TRANSPORT_STOP_FRAMES));
ASSERT(stopFrame < m_goValue.Transport.StopFrames->size());
stopTimer = m_goValue.Transport.StopFrames->at(stopFrame);
// Handling backwards movement. According to retail tests, a transport that returns to stop frame 0 is using the time between frame 0 and 1
if (!stopTimer)
backwardsTimer = m_goValue.Transport.StopFrames->at(stopFrame + 1);
// forward movement. target frame time - current frame time
if (GetCurrentTransportTime() < stopTimer)
SetUInt32Value(GAMEOBJECT_LEVEL, getMSTime() + stopTimer - GetCurrentTransportTime());
else if (backwardsTimer)
SetUInt32Value(GAMEOBJECT_LEVEL, getMSTime() + backwardsTimer);
else
SetUInt32Value(GAMEOBJECT_LEVEL, getMSTime() + GetCurrentTransportTime() - stopTimer);
state = GOState(GO_STATE_TRANSPORT_STOPPED + stopFrame);
}
uint32 pathProgress = getMSTime();
if (m_goValue.Transport.AnimationInfo)
pathProgress -= pathProgress % GetTransportPeriod();
SetPathProgress(pathProgress + stopTimer + backwardsTimer);
SetDestinationStopFrameTime(stopTimer);
SetLastStopFrameTime(GetCurrentTransportTime());
if (GetCurrentTransportTime() > backwardsTimer)
SetAlignmentTransportTime(backwardsTimer);
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, goinfo->name.c_str());
TC_LOG_ERROR("sql.sql", "Transport %u (name: %s) will not be created, missing `transport_template` entry.", entry, m_goInfo->name.c_str());
return false;
}
@@ -84,21 +577,9 @@ bool Transport::Create(ObjectGuid::LowType guidlow, uint32 entry, uint32 mapid,
_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);
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);
SetGoState(!m_goInfo->moTransport.canBeStopped ? GO_STATE_READY : GO_STATE_ACTIVE);
SetWorldRotation(0.0f, 0.0f, 0.0f, 1.0f);
SetParentRotation(QuaternionData());
@@ -106,19 +587,14 @@ bool Transport::Create(ObjectGuid::LowType guidlow, uint32 entry, uint32 mapid,
return true;
}
void Transport::CleanupsBeforeDelete(bool finalCleanup /*= true*/)
void MapTransport::CleanupsBeforeDelete(bool finalCleanup /*= true*/)
{
UnloadStaticPassengers();
while (!_passengers.empty())
{
WorldObject* obj = *_passengers.begin();
RemovePassenger(obj);
}
GameObject::CleanupsBeforeDelete(finalCleanup);
Transport::CleanupsBeforeDelete(finalCleanup);
}
void Transport::Update(uint32 diff)
void MapTransport::Update(uint32 diff)
{
uint32 const positionUpdateDelay = 200;
@@ -238,7 +714,7 @@ void Transport::Update(uint32 diff)
sScriptMgr->OnTransportUpdate(this, diff);
}
void Transport::DelayedUpdate(uint32 /*diff*/)
void MapTransport::DelayedUpdate(uint32 /*diff*/)
{
if (GetKeyFrames().size() <= 1)
return;
@@ -246,23 +722,7 @@ void Transport::DelayedUpdate(uint32 /*diff*/)
DelayedTeleportTransport();
}
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)
void MapTransport::RemovePassenger(WorldObject* passenger)
{
bool erased = false;
if (_passengerTeleportItr != _passengers.end())
@@ -286,6 +746,12 @@ void Transport::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);
@@ -294,7 +760,7 @@ void Transport::RemovePassenger(WorldObject* passenger)
}
}
Creature* Transport::CreateNPCPassenger(ObjectGuid::LowType guid, CreatureData const* data)
Creature* MapTransport::CreateNPCPassenger(ObjectGuid::LowType guid, CreatureData const* data)
{
Map* map = GetMap();
if (map->GetCreatureRespawnTime(guid))
@@ -313,6 +779,7 @@ Creature* Transport::CreateNPCPassenger(ObjectGuid::LowType guid, CreatureData c
creature->SetTransport(this);
creature->m_movementInfo.transport.guid = GetGUID();
creature->m_movementInfo.transport.time = GetPathProgress();
creature->m_movementInfo.transport.pos.Relocate(x, y, z, o);
CalculatePassengerPosition(x, y, z, &o);
creature->Relocate(x, y, z, o);
@@ -344,13 +811,19 @@ Creature* Transport::CreateNPCPassenger(ObjectGuid::LowType guid, CreatureData c
return creature;
}
GameObject* Transport::CreateGOPassenger(ObjectGuid::LowType guid, GameObjectData const* data)
GameObject* MapTransport::CreateGOPassenger(ObjectGuid::LowType guid, GameObjectData const* data)
{
ASSERT(data);
Map* map = GetMap();
if (map->GetGORespawnTime(guid))
return nullptr;
GameObject* go = new GameObject();
GameObject* go = nullptr;
if (sObjectMgr->GetGameObjectTypeByEntry(data->id) == GAMEOBJECT_TYPE_TRANSPORT)
go = new Transport();
else
go = new GameObject();
if (!go->LoadFromDB(guid, map, false))
{
@@ -365,6 +838,7 @@ GameObject* Transport::CreateGOPassenger(ObjectGuid::LowType guid, GameObjectDat
go->SetTransport(this);
go->m_movementInfo.transport.guid = GetGUID();
go->m_movementInfo.transport.time = GetPathProgress();
go->m_movementInfo.transport.pos.Relocate(x, y, z, o);
CalculatePassengerPosition(x, y, z, &o);
go->Relocate(x, y, z, o);
@@ -390,7 +864,7 @@ GameObject* Transport::CreateGOPassenger(ObjectGuid::LowType guid, GameObjectDat
return go;
}
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*/)
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*/)
{
Map* map = FindMap();
if (!map)
@@ -479,6 +953,7 @@ TempSummon* Transport::SummonPassenger(uint32 entry, Position const& pos, TempSu
summon->SetTransport(this);
summon->m_movementInfo.transport.guid = GetGUID();
summon->m_movementInfo.transport.pos.Relocate(pos);
summon->m_movementInfo.transport.time = GetPathProgress();
summon->Relocate(x, y, z, o);
summon->SetHomePosition(x, y, z, o);
summon->SetTransportHomePosition(pos);
@@ -503,7 +978,7 @@ TempSummon* Transport::SummonPassenger(uint32 entry, Position const& pos, TempSu
return summon;
}
void Transport::UpdatePosition(float x, float y, float z, float o)
void MapTransport::UpdatePosition(float x, float y, float z, float o)
{
bool newActive = GetMap()->IsGridLoaded(x, y);
Cell oldCell(GetPositionX(), GetPositionY());
@@ -529,7 +1004,7 @@ void Transport::UpdatePosition(float x, float y, float z, float o)
// 4. is handed by grid unload
}
void Transport::LoadStaticPassengers()
void MapTransport::LoadStaticPassengers()
{
if (uint32 mapId = GetGOInfo()->moTransport.mapID)
{
@@ -550,7 +1025,7 @@ void Transport::LoadStaticPassengers()
}
}
void Transport::UnloadStaticPassengers()
void MapTransport::UnloadStaticPassengers()
{
while (!_staticPassengers.empty())
{
@@ -559,7 +1034,7 @@ void Transport::UnloadStaticPassengers()
}
}
void Transport::EnableMovement(bool enabled)
void MapTransport::EnableMovement(bool enabled)
{
if (!GetGOInfo()->moTransport.canBeStopped)
return;
@@ -567,7 +1042,7 @@ void Transport::EnableMovement(bool enabled)
_pendingStop = !enabled;
}
void Transport::MoveToNextWaypoint()
void MapTransport::MoveToNextWaypoint()
{
// Clear events flagging
_triggeredArrivalEvent = false;
@@ -579,7 +1054,7 @@ void Transport::MoveToNextWaypoint()
_nextFrame = GetKeyFrames().begin();
}
float Transport::CalculateSegmentPos(float now)
float MapTransport::CalculateSegmentPos(float now)
{
KeyFrame const& frame = *_currentFrame;
const float speed = float(m_goInfo->moTransport.moveSpeed);
@@ -610,7 +1085,7 @@ float Transport::CalculateSegmentPos(float now)
return segmentPos / frame.NextDistFromPrev;
}
bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z, float o)
bool MapTransport::TeleportTransport(uint32 newMapid, float x, float y, float z, float o)
{
Map const* oldMap = GetMap();
@@ -646,14 +1121,14 @@ bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z, fl
}
}
void Transport::DelayedTeleportTransport()
void MapTransport::DelayedTeleportTransport()
{
if (!_delayedTeleport)
return;
_delayedTeleport = false;
Map* newMap = sMapMgr->CreateBaseMap(_nextFrame->Node->MapID);
GetMap()->RemoveFromMap<Transport>(this, false);
GetMap()->RemoveFromMap<MapTransport>(this, false);
SetMap(newMap);
float x = _nextFrame->Node->LocX,
@@ -685,66 +1160,10 @@ void Transport::DelayedTeleportTransport()
}
Relocate(x, y, z, o);
GetMap()->AddToMap<Transport>(this);
GetMap()->AddToMap<MapTransport>(this);
}
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)
void MapTransport::DoEventIfAny(KeyFrame const& node, bool departure)
{
if (uint32 eventid = departure ? node.Node->DepartureEventID : node.Node->ArrivalEventID)
{
@@ -754,7 +1173,7 @@ void Transport::DoEventIfAny(KeyFrame const& node, bool departure)
}
}
void Transport::BuildUpdate(UpdateDataMapType& data_map)
void MapTransport::BuildUpdate(UpdateDataMapType& data_map)
{
Map::PlayerList const& players = GetMap()->GetPlayers();
if (players.isEmpty())
+71 -24
View File
@@ -27,15 +27,80 @@ 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<WorldObject*> PassengerSet;
Transport();
~Transport();
bool Create(ObjectGuid::LowType guidlow, uint32 entry, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress);
bool Create(ObjectGuid::LowType guidlow, uint32 entry, Map* map, uint32 /*phaseMask*/, 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 GetPathProgress() const { return GetGOValue()->Transport.PathProgress; }
void SetPathProgress(uint32 val) { m_goValue.Transport.PathProgress = val; }
virtual uint32 GetTransportPeriod() const;
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 SetAlignmentTransportTime(uint32 time) { _alignmentTransportTime = time; }
uint32 GetAlightmentTransportTime() const { return _alignmentTransportTime; }
void SetLastStopFrameTime(uint32 time) { _lastStopFrameTime = time; }
uint32 GetLastStopFrameTime() const { return _lastStopFrameTime; }
protected:
void UpdatePassengerPositions(PassengerSet& passengers);
PassengerSet _passengers;
PassengerSet::iterator _passengerTeleportItr;
uint32 _destinationStopFrameTime;
uint32 _currentTransportTime;
uint32 _alignmentTransportTime;
uint32 _lastStopFrameTime;
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);
void CleanupsBeforeDelete(bool finalCleanup = true) override;
void Update(uint32 diff) override;
@@ -43,15 +108,13 @@ class TC_GAME_API Transport : public GameObject, public TransportBase
void BuildUpdate(UpdateDataMapType& data_map) override;
void AddPassenger(WorldObject* passenger);
void RemovePassenger(WorldObject* passenger);
PassengerSet const& GetPassengers() const { return _passengers; }
void RemovePassenger(WorldObject* passenger) override;
Creature* CreateNPCPassenger(ObjectGuid::LowType guid, CreatureData const* data);
GameObject* CreateGOPassenger(ObjectGuid::LowType guid, GameObjectData const* data);
/**
* @fn bool Transport::SummonPassenger(uint64, Position const&, TempSummonType, SummonPropertiesEntry const*, uint32, Unit*, uint32, uint32)
* @fn bool Transport::SummonPassenger(uint32, Position const&, TempSummonType, SummonPropertiesEntry const*, uint32, Unit*, uint32, uint32)
*
* @brief Temporarily summons a creature as passenger on this transport.
*
@@ -68,21 +131,8 @@ class TC_GAME_API Transport : public GameObject, public TransportBase
*/
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; }
@@ -105,7 +155,6 @@ class TC_GAME_API Transport : public GameObject, public TransportBase
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
@@ -124,8 +173,6 @@ class TC_GAME_API Transport : public GameObject, public TransportBase
bool _triggeredArrivalEvent;
bool _triggeredDepartureEvent;
PassengerSet _passengers;
PassengerSet::iterator _passengerTeleportItr;
PassengerSet _staticPassengers;
bool _delayedAddModel;
+2 -2
View File
@@ -538,7 +538,7 @@ Vehicle* Vehicle::RemovePassenger(Unit* unit)
// Enable gravity for passenger when he did not have it active before entering the vehicle
if (seat->second.SeatInfo->HasFlag(VEHICLE_SEAT_FLAG_DISABLE_GRAVITY) && !seat->second.Passenger.IsGravityDisabled)
unit->SetDisableGravity(false);
unit->SetDisableGravity(false, true);
// Remove UNIT_FLAG_NOT_SELECTABLE if passenger did not have it before entering vehicle
if (seat->second.SeatInfo->HasFlag(VEHICLE_SEAT_FLAG_PASSENGER_NOT_SELECTABLE) && !seat->second.Passenger.IsUnselectable)
@@ -879,7 +879,7 @@ bool VehicleJoinEvent::Execute(uint64, uint32)
}
if (veSeat->HasFlag(VEHICLE_SEAT_FLAG_DISABLE_GRAVITY))
Passenger->SetDisableGravity(true);
Passenger->SetDisableGravity(true, true);
if (veSeat->HasFlag(VEHICLE_SEAT_FLAG_PASSENGER_NOT_SELECTABLE))
Passenger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
@@ -131,7 +131,6 @@ 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;
+6 -1
View File
@@ -29,6 +29,7 @@
#include "ObjectMgr.h"
#include "Player.h"
#include "PoolMgr.h"
#include "Transport.h"
#include "UnitAI.h"
#include "World.h"
#include "WorldPacket.h"
@@ -1287,7 +1288,11 @@ 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 = new GameObject;
GameObject* pGameobject = nullptr;
if (sObjectMgr->GetGameObjectTypeByEntry(data->id) == GAMEOBJECT_TYPE_TRANSPORT)
pGameobject = new Transport();
else
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))
+14 -6
View File
@@ -38,8 +38,8 @@ template<class T>
void HashMapHolder<T>::Insert(T* o)
{
static_assert(std::is_same<Player, T>::value
|| std::is_same<Transport, T>::value,
"Only Player and Transport can be registered in global HashMapHolder");
|| std::is_same<MapTransport, T>::value,
"Only Player and MapTransport can be registered in global HashMapHolder");
boost::unique_lock<boost::shared_mutex> lock(*GetLock());
@@ -83,7 +83,7 @@ HashMapHolder<Player>::MapType const& ObjectAccessor::GetPlayers()
}
template class TC_GAME_API HashMapHolder<Player>;
template class TC_GAME_API HashMapHolder<Transport>;
template class TC_GAME_API HashMapHolder<MapTransport>;
namespace PlayerNameMapHolder
{
@@ -117,7 +117,6 @@ 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);
@@ -142,7 +141,6 @@ 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);
@@ -182,11 +180,21 @@ GameObject* ObjectAccessor::GetGameObject(WorldObject const& u, ObjectGuid const
return u.GetMap()->GetGameObject(guid);
}
Transport* ObjectAccessor::GetTransport(WorldObject const& u, ObjectGuid const& guid)
Transport* ObjectAccessor::GetTransportOnMap(WorldObject const& u, ObjectGuid const& guid)
{
return u.GetMap()->GetTransport(guid);
}
MapTransport* ObjectAccessor::GetMapTransportOnMap(WorldObject const& u, ObjectGuid const& guid)
{
return u.GetMap()->GetMapTransport(guid);
}
MapTransport* ObjectAccessor::GetMapTransport(ObjectGuid const& guid)
{
return HashMapHolder<MapTransport>::Find(guid);
}
DynamicObject* ObjectAccessor::GetDynamicObject(WorldObject const& u, ObjectGuid const& guid)
{
return u.GetMap()->GetDynamicObject(guid);
+3 -1
View File
@@ -67,7 +67,9 @@ namespace ObjectAccessor
TC_GAME_API Object* GetObjectByTypeMask(WorldObject const&, ObjectGuid const&, uint32 typemask);
TC_GAME_API Corpse* GetCorpse(WorldObject const& u, ObjectGuid const& guid);
TC_GAME_API GameObject* GetGameObject(WorldObject const& u, ObjectGuid const& guid);
TC_GAME_API Transport* GetTransport(WorldObject const& u, ObjectGuid const& guid);
TC_GAME_API Transport* GetTransportOnMap(WorldObject const& u, ObjectGuid const& guid);
TC_GAME_API MapTransport* GetMapTransportOnMap(WorldObject const& u, ObjectGuid const& guid);
TC_GAME_API MapTransport* GetMapTransport(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);
+16 -2
View File
@@ -53,6 +53,7 @@
#include "SpellMgr.h"
#include "SpellScript.h"
#include "TemporarySummon.h"
#include "Transport.h"
#include "UpdateMask.h"
#include "Util.h"
#include "Vehicle.h"
@@ -2158,7 +2159,12 @@ ObjectGuid::LowType ObjectMgr::AddGameObjectData(uint32 entry, uint32 mapId, Pos
// We use spawn coords to spawn
if (!map->Instanceable() && map->IsGridLoaded(data.spawnPoint))
{
GameObject* go = new GameObject;
GameObject* go = nullptr;
if (goinfo->type == GAMEOBJECT_TYPE_TRANSPORT)
go = new Transport();
else
go = new GameObject();
if (!go->LoadFromDB(spawnId, map, true))
{
TC_LOG_ERROR("misc", "AddGameObjectData: cannot add gameobject entry %u to map", entry);
@@ -7076,7 +7082,7 @@ void ObjectMgr::SetHighestGuids()
result = WorldDatabase.Query("SELECT MAX(guid) FROM transports");
if (result)
GetGuidSequenceGenerator<HighGuid::Mo_Transport>().Set((*result)[0].GetUInt32() + 1);
GetGuidSequenceGenerator<HighGuid::Transport>().Set((*result)[0].GetUInt32() + 1);
result = CharacterDatabase.Query("SELECT MAX(id) FROM auctionhouse");
if (result)
@@ -10272,3 +10278,11 @@ void ObjectMgr::LoadCreatureQuestItems()
TC_LOG_INFO("server.loading", ">> Loaded %u creature quest items 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;
}
+2
View File
@@ -1553,6 +1553,8 @@ class TC_GAME_API ObjectMgr
void LoadMissingKeyChains();
uint32 GetGameObjectTypeByEntry(uint32 entry) const;
private:
// first free id for selected id type
uint32 _auctionId;
@@ -31,7 +31,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 (Transport* transport = i_player.GetTransport())
if (MapTransport* transport = i_player.GetMapTransport())
{
for (Transport::PassengerSet::const_iterator itr = transport->GetPassengers().begin(); itr != transport->GetPassengers().end(); ++itr)
{
@@ -27,6 +27,7 @@
#include "GameObject.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Transport.h"
#include "World.h"
#include "ScriptMgr.h"
@@ -166,6 +167,48 @@ void LoadHelper(CellGuidSet const& guid_set, CellCoord &cell, GridRefManager<T>
}
}
template <>
void LoadHelper(CellGuidSet const& guid_set, CellCoord &cell, GridRefManager<GameObject> &m, uint32 &count, Map* map)
{
for (CellGuidSet::const_iterator i_guid = guid_set.begin(); i_guid != guid_set.end(); ++i_guid)
{
uint32 guid = *i_guid;
GameObjectData const* data = sObjectMgr->GetGameObjectData(guid);
GameObject* obj = nullptr;
if (data && sObjectMgr->GetGameObjectTypeByEntry(data->id) == GAMEOBJECT_TYPE_TRANSPORT)
obj = new Transport();
else
obj = new GameObject();
// Don't spawn at all if there's a respawn time
if (obj->GetTypeId() == TYPEID_GAMEOBJECT && !map->GetGORespawnTime(*i_guid))
{
ObjectGuid::LowType guid = *i_guid;
if (obj->GetTypeId() == TYPEID_GAMEOBJECT)
{
// If gameobject in manual spawn group, don't spawn here, unless group is already active.
GameObjectData const* godata = sObjectMgr->GetGameObjectData(guid);
ASSERT(godata, "Tried to load gameobject with spawnId %u, but no such object exists.", guid);
if (!(godata->spawnGroupData->flags & SPAWNGROUP_FLAG_SYSTEM))
if (!map->IsSpawnGroupActive(godata->spawnGroupData->groupId))
{
delete obj;
continue;
}
}
}
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();
@@ -51,6 +51,7 @@
#include "ScriptMgr.h"
#include "SharedDefines.h"
#include "SocialMgr.h"
#include "Transport.h"
#include "World.h"
#include "WorldPacket.h"
@@ -962,6 +963,26 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
}
}
// 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->SendInitialPacketsAfterAddToMap();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_ONLINE);
+16 -6
View File
@@ -88,10 +88,14 @@ void WorldSession::HandleMoveWorldportAckOpcode()
return;
}
float x = loc.GetPositionX();
float y = loc.GetPositionY();
float z = loc.GetPositionZ();
float o = loc.GetOrientation();
if (GetPlayer()->HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
z += GetPlayer()->GetFloatValue(UNIT_FIELD_HOVERHEIGHT);
GetPlayer()->Relocate(loc.GetPositionX(), loc.GetPositionY(), z, loc.GetOrientation());
GetPlayer()->Relocate(x, y, z, o);
GetPlayer()->SetFallInformation(0, GetPlayer()->GetPositionZ());
GetPlayer()->ResetMap();
@@ -108,6 +112,16 @@ void WorldSession::HandleMoveWorldportAckOpcode()
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())
@@ -354,11 +368,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvPacket)
}
if (!mover->GetTransport() && !mover->GetVehicle())
{
GameObject* go = mover->GetMap()->GetGameObject(movementInfo.transport.guid);
if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT)
movementInfo.transport.guid.Clear();
}
movementInfo.transport.Reset();
}
else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave
plrMover->m_transport->RemovePassenger(plrMover);
+23 -12
View File
@@ -313,6 +313,8 @@ i_scriptLock(false), _respawnCheckTimer(0), _defaultLight(GetDefaultMapLight(id)
//lets initialize visibility distance for map
Map::InitVisibilityDistance();
GetGuidSequenceGenerator<HighGuid::Transport>().Set(sObjectMgr->GetGenerator<HighGuid::Transport>().GetNextAfterMaxUsed());
_weatherUpdateTimer.SetInterval(time_t(1 * IN_MILLISECONDS));
MMAP::MMapFactory::createOrGetMMapManager()->loadMapInstance(sWorld->GetDataPath(), GetId(), i_InstanceId);
@@ -493,7 +495,7 @@ void Map::DeleteFromWorld(Player* player)
}
template<>
void Map::DeleteFromWorld(Transport* transport)
void Map::DeleteFromWorld(MapTransport* transport)
{
ObjectAccessor::RemoveObject(transport);
delete transport;
@@ -692,7 +694,7 @@ bool Map::AddToMap(T* obj)
}
template<>
bool Map::AddToMap(Transport* obj)
bool Map::AddToMap(MapTransport* obj)
{
//TODO: Needs clean up. An object should not be added to map twice.
if (obj->IsInWorld())
@@ -713,7 +715,7 @@ bool Map::AddToMap(Transport* obj)
{
for (Map::PlayerList::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
{
if (itr->GetSource()->GetTransport() != obj)
if (itr->GetSource()->GetMapTransport() != obj)
{
UpdateData data(GetId());
obj->BuildCreateUpdateBlockForPlayer(&data, itr->GetSource());
@@ -1064,7 +1066,7 @@ void Map::RemoveFromMap(T *obj, bool remove)
}
template<>
void Map::RemoveFromMap(Transport* obj, bool remove)
void Map::RemoveFromMap(MapTransport* obj, bool remove)
{
obj->RemoveFromWorld();
@@ -1786,10 +1788,10 @@ void Map::UnloadAll()
for (TransportsContainer::iterator itr = _transports.begin(); itr != _transports.end();)
{
Transport* transport = *itr;
MapTransport* transport = *itr;
++itr;
RemoveFromMap<Transport>(transport, true);
RemoveFromMap<MapTransport>(transport, true);
}
for (auto& cellCorpsePair : _corpsesByCell)
@@ -2864,7 +2866,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 (Transport* transport = player->GetTransport())
if (MapTransport* transport = player->GetMapTransport())
for (WorldObject* passenger : transport->GetPassengers())
if (player != passenger && player->HaveAtClient(passenger))
passenger->BuildCreateUpdateBlockForPlayer(&data, player);
@@ -2880,7 +2882,7 @@ void Map::SendInitTransports(Player* player)
UpdateData transData(player->GetMapId());
for (Transport* transport : _transports)
{
if (transport != player->GetTransport() && player->IsInPhase(transport))
if (transport != player->GetMapTransport() && player->IsInPhase(transport))
{
transport->BuildCreateUpdateBlockForPlayer(&transData, player);
player->m_visibleTransports.insert(transport->GetGUID());
@@ -2898,7 +2900,7 @@ void Map::SendRemoveTransports(Player* player)
UpdateData transData(player->GetMapId());
for (Transport* transport : _transports)
{
if (transport != player->GetTransport())
if (transport != player->GetMapTransport())
{
transport->BuildOutOfRangeUpdateBlock(&transData);
player->m_visibleTransports.erase(transport->GetGUID());
@@ -3447,7 +3449,7 @@ void Map::DelayedUpdate(uint32 t_diff)
{
for (_transportsUpdateIter = _transports.begin(); _transportsUpdateIter != _transports.end();)
{
Transport* transport = *_transportsUpdateIter;
MapTransport* transport = *_transportsUpdateIter;
++_transportsUpdateIter;
if (!transport->IsInWorld())
@@ -3551,7 +3553,7 @@ void Map::RemoveAllObjectsInRemoveList()
case TYPEID_GAMEOBJECT:
{
GameObject* go = obj->ToGameObject();
if (Transport* transport = go->ToTransport())
if (MapTransport* transport = go->ToMapTransport())
RemoveFromMap(transport, true);
else
RemoveFromMap(go, true);
@@ -4327,13 +4329,22 @@ Pet* Map::GetPet(ObjectGuid const& guid)
Transport* Map::GetTransport(ObjectGuid const& guid)
{
if (!guid.IsMOTransport())
if (!guid.IsTransport())
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())
+3 -1
View File
@@ -47,6 +47,7 @@ class InstanceMap;
class InstanceSave;
class InstanceScript;
class MapInstanced;
class MapTransport;
class Object;
class PhaseShift;
class Player;
@@ -523,6 +524,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
WorldObject* GetWorldObjectBySpawnId(SpawnObjectType type, ObjectGuid::LowType spawnId) const { return (type == SPAWN_TYPE_GAMEOBJECT) ? reinterpret_cast<WorldObject*>(GetGameObjectBySpawnId(spawnId)) : reinterpret_cast<WorldObject*>(GetCreatureBySpawnId(spawnId)); }
Pet* GetPet(ObjectGuid const& guid);
Transport* GetTransport(ObjectGuid const& guid);
MapTransport* GetMapTransport(ObjectGuid const& guid);
MapStoredObjectTypesContainer& GetObjectsStore() { return _objectsStore; }
@@ -731,7 +733,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
ActiveNonPlayers::iterator m_activeNonPlayersIter;
// Objects that must update even in inactive grids without activating them
typedef std::set<Transport*> TransportsContainer;
typedef std::set<MapTransport*> TransportsContainer;
TransportsContainer _transports;
TransportsContainer::iterator _transportsUpdateIter;
-6
View File
@@ -316,9 +316,6 @@ 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());
@@ -348,9 +345,6 @@ 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());
+60 -17
View File
@@ -362,7 +362,7 @@ void TransportMgr::AddPathNodeToTransport(uint32 transportEntry, uint32 timeSeg,
animNode.Path[timeSeg] = node;
}
Transport* TransportMgr::CreateTransport(uint32 entry, ObjectGuid::LowType guid /*= 0*/, Map* map /*= nullptr*/, uint8 phaseUseFlags /*= 0*/, uint32 phaseId /*= 0*/, uint32 phaseGroupId /*= 0*/)
MapTransport* 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)
@@ -384,7 +384,7 @@ Transport* TransportMgr::CreateTransport(uint32 entry, ObjectGuid::LowType guid
}
// create transport...
Transport* trans = new Transport();
MapTransport* trans = new MapTransport();
// ...at first waypoint
TaxiPathNodeEntry const* startNode = tInfo->keyFrames.begin()->Node;
@@ -395,9 +395,9 @@ Transport* TransportMgr::CreateTransport(uint32 entry, ObjectGuid::LowType guid
float o = tInfo->keyFrames.begin()->InitialOrientation;
// initialize the gameobject base
ObjectGuid::LowType guidLow = guid ? guid : sObjectMgr->GetGenerator<HighGuid::Mo_Transport>().Generate();
ObjectGuid::LowType guidLow = guid ? guid : ASSERT_NOTNULL(map)->GenerateLowGuid<HighGuid::Transport>();
if (!trans->Create(guidLow, entry, mapId, x, y, z, o, 255))
if (!trans->CreateMapTransport(guidLow, entry, mapId, x, y, z, o, 255))
{
delete trans;
return nullptr;
@@ -418,11 +418,11 @@ Transport* TransportMgr::CreateTransport(uint32 entry, ObjectGuid::LowType guid
// use preset map for instances (need to know which instance)
trans->SetMap(map ? map : sMapMgr->CreateMap(mapId, nullptr));
if (map && map->IsDungeon())
trans->m_zoneScript = map->ToInstanceMap()->GetInstanceScript();
trans->SetZoneScript();
// Passengers will be loaded once a player is near
HashMapHolder<Transport>::Insert(trans);
trans->GetMap()->AddToMap<Transport>(trans);
HashMapHolder<MapTransport>::Insert(trans);
trans->GetMap()->AddToMap<MapTransport>(trans);
return trans;
}
@@ -508,20 +508,63 @@ void TransportMgr::CreateInstanceTransports(Map* map)
CreateTransport(*itr, 0, map);
}
TransportAnimationEntry const* TransportAnimation::GetAnimNode(uint32 time) const
bool TransportAnimation::GetAnimNode(uint32 time, TransportAnimationEntry const*& curr, TransportAnimationEntry const*& next, float& percPos) const
{
auto itr = Path.lower_bound(time);
if (itr != Path.end())
return itr->second;
if (Path.empty())
return false;
return nullptr;
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->TimeSeg) / float(next->TimeSeg - curr->TimeSeg);
return true;
}
return false;
}
TransportRotationEntry const* TransportAnimation::GetAnimRotation(uint32 time) const
void TransportAnimation::GetAnimRotation(uint32 time, QuaternionData& curr, QuaternionData& next, float& percRot) const
{
auto itr = Rotations.lower_bound(time);
if (itr != Rotations.end())
return itr->second;
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;
}
return nullptr;
for (TransportPathRotationContainer::const_reverse_iterator itr = Rotations.rbegin(); itr != Rotations.rend(); ++itr)
if (time >= itr->first)
{
uint32 currSeg = itr->second->TimeSeg;
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->TimeSeg;
}
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;
}
+4 -4
View File
@@ -25,7 +25,7 @@
struct KeyFrame;
struct GameObjectTemplate;
struct TransportTemplate;
class Transport;
class MapTransport;
class Map;
namespace Movement
@@ -94,8 +94,8 @@ struct TC_GAME_API TransportAnimation
TransportPathRotationContainer Rotations;
uint32 TotalTime;
TransportAnimationEntry const* GetAnimNode(uint32 time) const;
TransportRotationEntry const* GetAnimRotation(uint32 time) const;
bool GetAnimNode(uint32 time, TransportAnimationEntry const*& curr, TransportAnimationEntry const*& next, float& percPos) const;
void GetAnimRotation(uint32 time, QuaternionData& curr, QuaternionData& next, float& percRot) const;
};
typedef std::map<uint32, TransportAnimation> TransportAnimationContainer;
@@ -112,7 +112,7 @@ class TC_GAME_API TransportMgr
void LoadTransportAnimationAndRotation();
// 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);
MapTransport* 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();
@@ -1815,11 +1815,11 @@ 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,
GO_STATE_TRANSPORT_STOPPED = 25
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
};
#define MAX_GO_STATE 3
#define MAX_GO_STATE 3
#define MAX_GO_STATE_TRANSPORT_STOP_FRAMES 9
enum GameObjectDestructibleState
+6 -1
View File
@@ -22,6 +22,7 @@
#include "Log.h"
#include "MapManager.h"
#include "ObjectMgr.h"
#include "Transport.h"
////////////////////////////////////////////////////////////
// template class ActivePoolData
@@ -410,7 +411,11 @@ void PoolGroup<GameObject>::Spawn1Object(PoolObject* obj)
// We use current coords to unspawn, not spawn coords since creature can have changed grid
if (!map->Instanceable() && map->IsGridLoaded(data->spawnPoint))
{
GameObject* pGameobject = new GameObject;
GameObject* pGameobject = nullptr;
if (sObjectMgr->GetGameObjectTypeByEntry(data->id) == GAMEOBJECT_TYPE_TRANSPORT)
pGameobject = new Transport();
else
pGameobject = new GameObject();
//TC_LOG_DEBUG("pool", "Spawning gameobject %u", guid);
if (!pGameobject->LoadFromDB(obj->guid, map, false))
{
+28 -7
View File
@@ -58,6 +58,7 @@
#include "SpellMgr.h"
#include "TemporarySummon.h"
#include "Totem.h"
#include "Transport.h"
#include "Unit.h"
#include "UpdateMask.h"
#include "Util.h"
@@ -3166,7 +3167,11 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex)
uint32 gameobject_id = m_spellInfo->Effects[effIndex].MiscValue;
GameObject* pGameObj = new GameObject;
GameObject* pGameObj = nullptr;
if (sObjectMgr->GetGameObjectTypeByEntry(gameobject_id) == GAMEOBJECT_TYPE_TRANSPORT)
pGameObj = new Transport();
else
pGameObj = new GameObject();
WorldObject* target = focusObject;
if (!target)
@@ -4144,7 +4149,11 @@ void Spell::EffectSummonObject(SpellEffIndex effIndex)
m_caster->m_ObjectSlot[slot].Clear();
}
GameObject* go = new GameObject();
GameObject* go = nullptr;
if (sObjectMgr->GetGameObjectTypeByEntry(go_id) == GAMEOBJECT_TYPE_TRANSPORT)
go = new Transport();
else
go = new GameObject();
float x, y, z;
// If dest location if present
@@ -4870,12 +4879,24 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex)
QuaternionData rot = QuaternionData::fromEulerAnglesZYX(fo, 0.f, 0.f);
GameObject* pGameObj = new GameObject;
if (!pGameObj->Create(cMap->GenerateLowGuid<HighGuid::GameObject>(), name_id, cMap, 0, Position(fx, fy, fz, m_caster->GetOrientation()), rot, 255, GO_STATE_READY))
GameObject* pGameObj = nullptr;
if (goinfo->type == GAMEOBJECT_TYPE_TRANSPORT)
{
delete pGameObj;
return;
pGameObj = new Transport();
if (!pGameObj->Create(cMap->GenerateLowGuid<HighGuid::Transport>(), name_id, cMap, 0, Position(fx, fy, fz, m_caster->GetOrientation()), rot, 255, GO_STATE_READY))
{
delete pGameObj;
return;
}
}
else
{
pGameObj = new GameObject();
if (!pGameObj->Create(cMap->GenerateLowGuid<HighGuid::GameObject>(), name_id, cMap, 0, Position(fx, fy, fz, m_caster->GetOrientation()), rot, 255, GO_STATE_READY))
{
delete pGameObj;
return;
}
}
PhasingHandler::InheritPhaseShift(pGameObj, m_caster);
+1 -1
View File
@@ -1425,7 +1425,7 @@ public:
static bool HandleDebugTransportCommand(ChatHandler* handler, char const* args)
{
Transport* transport = handler->GetSession()->GetPlayer()->GetTransport();
MapTransport* transport = handler->GetSession()->GetPlayer()->GetMapTransport();
if (!transport)
return false;
+17 -3
View File
@@ -37,6 +37,7 @@ EndScriptData */
#include "Player.h"
#include "PoolMgr.h"
#include "RBAC.h"
#include "Transport.h"
#include "WorldSession.h"
// definitions are over in cs_npc.cpp
@@ -151,8 +152,18 @@ public:
Player* player = handler->GetSession()->GetPlayer();
Map* map = player->GetMap();
GameObject* object = new GameObject;
ObjectGuid::LowType guidLow = map->GenerateLowGuid<HighGuid::GameObject>();
GameObject* object = nullptr;
ObjectGuid::LowType guidLow = ObjectGuid::Empty;
if (objectInfo->type == GAMEOBJECT_TYPE_TRANSPORT)
{
object = new Transport();
ObjectGuid::LowType guidLow = map->GenerateLowGuid<HighGuid::Transport>();
}
else
{
object = new GameObject();
ObjectGuid::LowType guidLow = map->GenerateLowGuid<HighGuid::GameObject>();
}
if (!object->Create(guidLow, objectInfo->entry, map, 0, *player, QuaternionData(), 255, GO_STATE_READY))
{
@@ -176,7 +187,10 @@ public:
// this is required to avoid weird behavior and memory leaks
delete object;
object = new GameObject();
if (objectInfo->type == GAMEOBJECT_TYPE_TRANSPORT)
object = new Transport();
else
object = new GameObject();
// this will generate a new guid if the object is in an instance
if (!object->LoadFromDB(guidLow, map, true))
{
+2 -2
View File
@@ -154,8 +154,8 @@ public:
// before GM
float x, y, z;
gmPlayer->GetClosePoint(x, y, z, player->GetCombatReach());
player->TeleportTo(gmPlayer->GetMapId(), x, y, z, player->GetOrientation());
gmPlayer->GetPosition(x, y, z);
player->TeleportTo(gmPlayer->GetMapId(), x, y, z, player->GetOrientation(), 0, gmPlayer->GetTransport());
}
return true;
+15 -10
View File
@@ -281,13 +281,18 @@ public:
areaId, (areaEntry ? areaEntry->area_name : unknown),
object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), object->GetOrientation());
if (Transport* transport = object->GetTransport())
handler->PSendSysMessage(LANG_TRANSPORT_POSITION,
transport->GetGOInfo()->moTransport.mapID, object->GetTransOffsetX(), object->GetTransOffsetY(), object->GetTransOffsetZ(), object->GetTransOffsetO(),
transport->GetEntry(), transport->GetName().c_str());
handler->PSendSysMessage(LANG_GRID_POSITION,
cell.GridX(), cell.GridY(), cell.CellX(), cell.CellY(), object->GetInstanceId(),
zoneX, zoneY, groundZ, floorZ, haveMap, haveVMap, haveMMap);
{
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->GetEntry(), transport->GetName().c_str());
handler->PSendSysMessage(LANG_GRID_POSITION,
cell.GridX(), cell.GridY(), cell.CellX(), cell.CellY(), object->GetInstanceId(),
zoneX, zoneY, groundZ, floorZ, haveMap, haveVMap, haveMMap);
}
LiquidData liquidStatus;
ZLiquidStatus status = map->GetLiquidStatus(object->GetPhaseShift(), object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), MAP_ALL_LIQUIDS, &liquidStatus);
@@ -449,9 +454,9 @@ public:
// to point to see at target with same orientation
float x, y, z;
target->GetContactPoint(_player, x, y, z);
target->GetPosition(x, y, z);
_player->TeleportTo(target->GetMapId(), x, y, z, _player->GetAngle(target), TELE_TO_GM_MODE);
_player->TeleportTo(target->GetMapId(), x, y, z, _player->GetAngle(target), TELE_TO_GM_MODE, target->GetTransport());
PhasingHandler::InheritPhaseShift(_player, target);
_player->UpdateObjectVisibility();
}
@@ -581,8 +586,8 @@ public:
// before GM
float x, y, z;
_player->GetClosePoint(x, y, z, target->GetCombatReach());
target->TeleportTo(_player->GetMapId(), x, y, z, target->GetOrientation());
_player->GetPosition(x, y, z);
target->TeleportTo(_player->GetMapId(), x, y, z, target->GetOrientation(), 0, _player->GetTransport());
PhasingHandler::InheritPhaseShift(target, handler->GetSession()->GetPlayer());
target->UpdateObjectVisibility();
}
+1 -1
View File
@@ -347,7 +347,7 @@ public:
Player* chr = handler->GetSession()->GetPlayer();
Map* map = chr->GetMap();
if (Transport* trans = chr->GetTransport())
if (MapTransport* trans = chr->GetMapTransport())
{
ObjectGuid::LowType guid = map->GenerateLowGuid<HighGuid::Unit>();
CreatureData& data = sObjectMgr->NewOrExistCreatureData(guid);
@@ -26,6 +26,7 @@
#include "SpellAuraEffects.h"
#include "SpellScript.h"
#include "TemporarySummon.h"
#include "Transport.h"
#include "halls_of_origination.h"
enum Spells
@@ -103,11 +104,10 @@ struct go_hoo_the_makers_lift_controller : public GameObjectAI
return true;
// Handle elevator: gossip item index => stopFrame (floor index).
GameObject* elevator = instance->GetGameObject(DATA_LIFT_OF_THE_MAKERS);
Transport* elevator = ObjectAccessor::GetTransportOnMap(*me, instance->GetGuidData(DATA_LIFT_OF_THE_MAKERS));
if (!elevator)
return true;
elevator->SetTransportState(GO_STATE_TRANSPORT_ACTIVE, action);
elevator->SetTransportState(GO_STATE_TRANSPORT_STOPPED, action);
return true;
@@ -126,7 +126,7 @@ class instance_halls_of_origination : public InstanceMapScript
UpdateTransitDevice(go);
break;
case GO_LIFT_OF_THE_MAKERS:
go->SetTransportState(GO_STATE_TRANSPORT_STOPPED, 0);
//go->SetTransportState(GO_STATE_TRANSPORT_STOPPED, 0);
break;
case GO_VAULT_OF_LIGHTS_DOOR:
if (_vaultOfLightState != NOT_STARTED)
@@ -1126,7 +1126,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 (Transport* gunship = ObjectAccessor::GetTransport(*me, _instance->GetGuidData(DATA_GUNSHIP)))
if (MapTransport* gunship = ObjectAccessor::GetMapTransportOnMap(*me, _instance->GetGuidData(DATA_GUNSHIP)))
gunship->EnableMovement(true);
_instance->SetBossState(DATA_THE_LICH_KING_ESCAPE, DONE);
break;
@@ -1198,7 +1198,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 (Transport* gunship = ObjectAccessor::GetTransport(*me, _instance->GetGuidData(DATA_GUNSHIP)))
if (MapTransport* gunship = ObjectAccessor::GetMapTransportOnMap(*me, _instance->GetGuidData(DATA_GUNSHIP)))
gunship->EnableMovement(true);
break;
default:
@@ -391,7 +391,7 @@ class instance_halls_of_reflection : public InstanceMapScript
_teamInInstance = player->GetTeam();
}
if (Transport* gunship = sTransportMgr->CreateTransport(_teamInInstance == HORDE ? GO_ORGRIMS_HAMMER : GO_THE_SKYBREAKER, 0, instance))
if (MapTransport* gunship = sTransportMgr->CreateTransport(_teamInInstance == HORDE ? GO_ORGRIMS_HAMMER : GO_THE_SKYBREAKER, 0, instance))
gunship->EnableMovement(GetBossState(DATA_THE_LICH_KING_ESCAPE) == DONE);
}
@@ -637,7 +637,7 @@ class instance_halls_of_reflection : public InstanceMapScript
if (GetBossState(DATA_THE_LICH_KING_ESCAPE) == DONE)
break;
if (Transport* gunship = instance->GetTransport(GunshipGUID))
if (MapTransport* gunship = instance->GetMapTransport(GunshipGUID))
gunship->EnableMovement(false);
if (Creature* jainaOrSylvanas = instance->GetCreature(JainaOrSylvanasEscapeGUID))
@@ -655,7 +655,7 @@ class instance_halls_of_reflection : public InstanceMapScript
}
break;
case EVENT_GUNSHIP_ARRIVAL_2:
if (Transport* gunship = instance->GetTransport(GunshipGUID))
if (MapTransport* gunship = instance->GetMapTransport(GunshipGUID))
gunship->EnableMovement(false);
for (ObjectGuid guid : GunshipStairGUIDs)
@@ -384,7 +384,7 @@ public:
ResetSlots(HORDE);
}
void SetTransport(Transport* transport) { _transport = transport; }
void SetTransport(MapTransport* transport) { _transport = transport; }
void ResetSlots(uint32 team)
{
@@ -455,7 +455,7 @@ private:
return newPos;
}
Transport* _transport;
MapTransport* _transport;
ObjectGuid _controlledSlots[MAX_SLOTS];
time_t _respawnCooldowns[MAX_SLOTS];
Position const* _spawnPoint;
@@ -497,7 +497,7 @@ public:
_caster->CastSpell(_caster, _spellId, true);
_caster->GetTransport()->AddObjectToRemoveList();
if (Transport* go = HashMapHolder<Transport>::Find(_otherTransport))
if (MapTransport* go = ObjectAccessor::GetMapTransport(_otherTransport))
go->AddObjectToRemoveList();
return true;
@@ -776,10 +776,10 @@ class npc_gunship : public CreatureScript
if (isVictory)
{
if (Transport* otherTransport = HashMapHolder<Transport>::Find(instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE)))
otherTransport->EnableMovement(true);
if (MapTransport* trans = ObjectAccessor::GetMapTransport(instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE)))
trans->EnableMovement(true);
me->GetTransport()->EnableMovement(true);
me->GetMapTransport()->EnableMovement(true);
if (Creature* ship = me->FindNearestCreature(_teamInInstance == HORDE ? NPC_ORGRIMS_HAMMER : NPC_THE_SKYBREAKER, 200.0f))
{
@@ -855,7 +855,7 @@ class npc_high_overlord_saurfang_igb : public CreatureScript
_instance(creature->GetInstanceScript())
{
_controller.ResetSlots(HORDE);
_controller.SetTransport(creature->GetTransport());
_controller.SetTransport(creature->GetMapTransport());
me->setRegeneratingHealth(false);
me->m_CombatDistance = 70.0f;
_firstMageCooldown = time(nullptr) + 60;
@@ -970,7 +970,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->GetTransport()->EnableMovement(true);
me->GetMapTransport()->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);
@@ -1038,10 +1038,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 (Transport* orgrimsHammer = me->GetTransport())
if (MapTransport* orgrimsHammer = me->GetMapTransport())
orgrimsHammer->SummonPassenger(NPC_TELEPORT_PORTAL, OrgrimsHammerTeleportPortal, TEMPSUMMON_TIMED_DESPAWN, nullptr, 21000);
if (Transport* skybreaker = HashMapHolder<Transport>::Find(_instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE)))
if (MapTransport* skybreaker = ObjectAccessor::GetMapTransport(_instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE)))
skybreaker->SummonPassenger(NPC_TELEPORT_EXIT, SkybreakerTeleportExit, TEMPSUMMON_TIMED_DESPAWN, nullptr, 23000);
_events.ScheduleEvent(EVENT_ADDS_BOARD_YELL, 6000);
@@ -1124,7 +1124,7 @@ class npc_muradin_bronzebeard_igb : public CreatureScript
_instance(creature->GetInstanceScript())
{
_controller.ResetSlots(ALLIANCE);
_controller.SetTransport(creature->GetTransport());
_controller.SetTransport(creature->GetMapTransport());
me->setRegeneratingHealth(false);
me->m_CombatDistance = 70.0f;
_firstMageCooldown = time(nullptr) + 60;
@@ -1239,7 +1239,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->GetTransport()->EnableMovement(true);
me->GetMapTransport()->EnableMovement(true);
_events.SetPhase(PHASE_INTRO);
_events.ScheduleEvent(EVENT_INTRO_A_1, 5000);
_events.ScheduleEvent(EVENT_INTRO_A_2, 10000, 0, PHASE_INTRO);
@@ -1311,10 +1311,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 (Transport* skybreaker = me->GetTransport())
if (MapTransport* skybreaker = me->GetMapTransport())
skybreaker->SummonPassenger(NPC_TELEPORT_PORTAL, SkybreakerTeleportPortal, TEMPSUMMON_TIMED_DESPAWN, nullptr, 21000);
if (Transport* orgrimsHammer = HashMapHolder<Transport>::Find(_instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE)))
if (MapTransport* orgrimsHammer = ObjectAccessor::GetMapTransport(_instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE)))
orgrimsHammer->SummonPassenger(NPC_TELEPORT_EXIT, OrgrimsHammerTeleportExit, TEMPSUMMON_TIMED_DESPAWN, nullptr, 23000);
_events.ScheduleEvent(EVENT_ADDS_BOARD_YELL, 6000);
@@ -1460,7 +1460,7 @@ struct npc_gunship_boarding_addAI : public gunship_npc_AI
if (!myTransport)
return;
if (Transport* destTransport = HashMapHolder<Transport>::Find(Instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE)))
if (MapTransport* destTransport = ObjectAccessor::GetMapTransport(Instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE)))
destTransport->CalculatePassengerPosition(x, y, z, &o);
float angle = frand(0, float(M_PI) * 2.0f);
@@ -2336,7 +2336,7 @@ class spell_igb_gunship_fall_teleport : public SpellScriptLoader
void SelectTransport(WorldObject*& target)
{
if (InstanceScript* instance = target->GetInstanceScript())
target = HashMapHolder<Transport>::Find(instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE));
target = ObjectAccessor::GetMapTransport(instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE));
}
void RelocateDest(SpellEffIndex /*effIndex*/)
@@ -508,7 +508,8 @@ class instance_icecrown_citadel : public InstanceMapScript
case GO_LADY_DEATHWHISPER_ELEVATOR:
LadyDeathwisperElevatorGUID = go->GetGUID();
if (GetBossState(DATA_LADY_DEATHWHISPER) == DONE)
go->SetTransportState(GO_STATE_TRANSPORT_ACTIVE);
if (Transport* transport = go->ToTransport())
transport->SetTransportState(GO_STATE_TRANSPORT_ACTIVE);
break;
case GO_THE_SKYBREAKER_H:
case GO_ORGRIMS_HAMMER_A:
@@ -824,7 +825,7 @@ class instance_icecrown_citadel : public InstanceMapScript
if (GameObject* teleporter = instance->GetGameObject(TeleporterRampartsGUID))
SetTeleporterState(teleporter, true);
if (GameObject* elevator = instance->GetGameObject(LadyDeathwisperElevatorGUID))
if (Transport* elevator = instance->GetTransport(LadyDeathwisperElevatorGUID))
elevator->SetTransportState(GO_STATE_TRANSPORT_ACTIVE);
SpawnGunship();
@@ -1018,7 +1019,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 (Transport* gunship = sTransportMgr->CreateTransport(gunshipEntry, 0, instance))
if (MapTransport* gunship = sTransportMgr->CreateTransport(gunshipEntry, 0, instance))
GunshipGUID = gunship->GetGUID();
}
}
@@ -1403,7 +1404,7 @@ class instance_icecrown_citadel : public InstanceMapScript
case EVENT_PLAYERS_GUNSHIP_SPAWN:
case EVENT_PLAYERS_GUNSHIP_COMBAT:
if (GameObject* go = source->ToGameObject())
if (Transport* transport = go->ToTransport())
if (MapTransport* transport = go->ToMapTransport())
transport->EnableMovement(false);
break;
case EVENT_PLAYERS_GUNSHIP_SAURFANG:
@@ -1411,7 +1412,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 (Transport* transport = go->ToTransport())
if (MapTransport* transport = go->ToMapTransport())
transport->EnableMovement(false);
break;
}