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:
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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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)
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
+3
-3
@@ -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;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user