Add basic support for NPCs on transports; DB data required.
Currently no support for combat while the transport is in motion. Based on a patch by Socolin. Fixes issue #168 --HG-- branch : trunk
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
CREATE TABLE IF NOT EXISTS `creature_transport` (
|
||||
`guid` int(16) NOT NULL AUTO_INCREMENT COMMENT 'GUID of NPC on transport - not the same as creature.guid',
|
||||
`transport_entry` int(8) NOT NULL COMMENT 'Transport entry',
|
||||
`npc_entry` int(8) NOT NULL COMMENT 'NPC entry',
|
||||
`TransOffsetX` float NOT NULL DEFAULT '0',
|
||||
`TransOffsetY` float NOT NULL DEFAULT '0',
|
||||
`TransOffsetZ` float NOT NULL DEFAULT '0',
|
||||
`TransOffsetO` float NOT NULL DEFAULT '0',
|
||||
`emote` int(16) NOT NULL,
|
||||
PRIMARY KEY (`transport_entry`,`guid`),
|
||||
UNIQUE KEY `entry` (`transport_entry`,`guid`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
|
||||
@@ -42,7 +42,7 @@
|
||||
#include <map>
|
||||
#include "GlobalEvents.h"
|
||||
#include "OutdoorPvPMgr.h"
|
||||
|
||||
#include "Transport.h"
|
||||
#include "TargetedMovementGenerator.h" // for HandleNpcUnFollowCommand
|
||||
#include "CreatureGroups.h"
|
||||
|
||||
@@ -1005,6 +1005,29 @@ bool ChatHandler::HandleNpcAddCommand(const char* args)
|
||||
float o = chr->GetOrientation();
|
||||
Map *map = chr->GetMap();
|
||||
|
||||
if (chr->GetTransport())
|
||||
{
|
||||
uint32 tguid = chr->GetTransport()->AddNPCPassenger(0, id, chr->GetTransOffsetX(), chr->GetTransOffsetY(), chr->GetTransOffsetZ(), chr->GetTransOffsetO());
|
||||
if (tguid > 0)
|
||||
{
|
||||
WorldDatabase.PQuery("INSERT INTO creature_transport (guid, npc_entry, transport_entry, TransOffsetX, TransOffsetY, TransOffsetZ, TransOffsetO) values (%u, %u, %f, %f, %f, %f, %u)", tguid, id, chr->GetTransport()->GetEntry(), chr->GetTransOffsetX(), chr->GetTransOffsetY(), chr->GetTransOffsetZ(), chr->GetTransOffsetO());
|
||||
|
||||
TransportCreatureProto *transportCreatureProto = new TransportCreatureProto;
|
||||
transportCreatureProto->guid = tguid;
|
||||
transportCreatureProto->npc_entry = id;
|
||||
uint32 transportEntry = chr->GetTransport()->GetEntry();
|
||||
transportCreatureProto->TransOffsetX = chr->GetTransOffsetX();
|
||||
transportCreatureProto->TransOffsetY = chr->GetTransOffsetY();
|
||||
transportCreatureProto->TransOffsetZ = chr->GetTransOffsetZ();
|
||||
transportCreatureProto->TransOffsetO = chr->GetTransOffsetO();
|
||||
transportCreatureProto->emote = 0;
|
||||
|
||||
sMapMgr.m_TransportNPCMap[transportEntry].insert(transportCreatureProto);
|
||||
sMapMgr.m_TransportNPCs.insert(transportCreatureProto);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Creature* pCreature = new Creature;
|
||||
if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, (uint32)teamval, x, y, z, o))
|
||||
{
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
#include "DBCEnums.h"
|
||||
#include "ConditionMgr.h"
|
||||
#include "DisableMgr.h"
|
||||
#include "Transport.h"
|
||||
|
||||
bool ChatHandler::HandleAHBotOptionsCommand(const char *args)
|
||||
{
|
||||
@@ -4801,6 +4802,10 @@ bool ChatHandler::HandleNpcPlayEmoteCommand(const char *args)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (target->GetTransport())
|
||||
if (target->GetGUIDTransport())
|
||||
WorldDatabase.PQuery("UPDATE creature_transport SET emote=%u WHERE transport_entry=%u AND guid=%u", emote, target->GetTransport()->GetEntry(), target->GetGUIDTransport());
|
||||
|
||||
target->SetUInt32Value(UNIT_NPC_EMOTESTATE,emote);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -667,6 +667,8 @@ class Creature : public Unit, public GridObject<Creature>
|
||||
|
||||
float m_SightDistance, m_CombatDistance;
|
||||
|
||||
void SetGUIDTransport(uint32 guid) { guid_transport=guid; }
|
||||
uint32 GetGUIDTransport() { return guid_transport; }
|
||||
protected:
|
||||
bool CreateFromProto(uint32 guidlow, uint32 Entry, uint32 vehId, uint32 team, const CreatureData *data = NULL);
|
||||
bool InitEntry(uint32 entry, uint32 team=ALLIANCE, const CreatureData* data=NULL);
|
||||
@@ -714,7 +716,7 @@ class Creature : public Unit, public GridObject<Creature>
|
||||
CreatureData const* m_creatureData;
|
||||
|
||||
uint16 m_LootMode; // bitmask, default LOOT_MODE_DEFAULT, determines what loot will be lootable
|
||||
|
||||
uint32 guid_transport;
|
||||
private:
|
||||
//WaypointMovementGenerator vars
|
||||
uint32 m_waypointID;
|
||||
|
||||
@@ -1151,6 +1151,7 @@ WorldObject::WorldObject()
|
||||
, m_name("")
|
||||
, m_notifyflags(0), m_executed_notifies(0)
|
||||
{
|
||||
m_transport = NULL;
|
||||
}
|
||||
|
||||
void WorldObject::SetWorldObject(bool on)
|
||||
@@ -1235,6 +1236,22 @@ float WorldObject::GetDistanceZ(const WorldObject* obj) const
|
||||
|
||||
bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D) const
|
||||
{
|
||||
float sizefactor = GetObjectSize() + obj->GetObjectSize();
|
||||
float maxdist = dist2compare + sizefactor;
|
||||
|
||||
if (m_transport && obj->GetTransport() && obj->GetTransport()->GetGUIDLow() == m_transport->GetGUIDLow())
|
||||
{
|
||||
float dtx = m_movementInfo.t_x - obj->m_movementInfo.t_x;
|
||||
float dty = m_movementInfo.t_y - obj->m_movementInfo.t_y;
|
||||
float disttsq = dtx * dtx + dty * dty;
|
||||
if (is3D)
|
||||
{
|
||||
float dtz = m_movementInfo.t_z - obj->m_movementInfo.t_z;
|
||||
disttsq += dtz * dtz;
|
||||
}
|
||||
return disttsq < (maxdist * maxdist);
|
||||
}
|
||||
|
||||
float dx = GetPositionX() - obj->GetPositionX();
|
||||
float dy = GetPositionY() - obj->GetPositionY();
|
||||
float distsq = dx*dx + dy*dy;
|
||||
@@ -1243,8 +1260,6 @@ bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool
|
||||
float dz = GetPositionZ() - obj->GetPositionZ();
|
||||
distsq += dz*dz;
|
||||
}
|
||||
float sizefactor = GetObjectSize() + obj->GetObjectSize();
|
||||
float maxdist = dist2compare + sizefactor;
|
||||
|
||||
return distsq < maxdist * maxdist;
|
||||
}
|
||||
|
||||
@@ -115,9 +115,46 @@ class Vehicle;
|
||||
class CreatureAI;
|
||||
class ZoneScript;
|
||||
class Unit;
|
||||
class Transport;
|
||||
|
||||
typedef UNORDERED_MAP<Player*, UpdateData> UpdateDataMapType;
|
||||
|
||||
struct MovementInfo
|
||||
{
|
||||
// common
|
||||
uint64 guid;
|
||||
uint32 flags;
|
||||
uint16 unk1;
|
||||
uint32 time;
|
||||
float x, y, z, o;
|
||||
// transport
|
||||
uint64 t_guid;
|
||||
float t_x, t_y, t_z, t_o;
|
||||
uint32 t_time;
|
||||
int8 t_seat;
|
||||
// swimming and unknown
|
||||
float s_pitch;
|
||||
// last fall time
|
||||
uint32 fallTime;
|
||||
// jumping
|
||||
float j_zspeed, j_sinAngle, j_cosAngle, j_xyspeed;
|
||||
// spline
|
||||
float u_unk1;
|
||||
|
||||
MovementInfo()
|
||||
{
|
||||
flags = 0;
|
||||
time = t_time = fallTime = 0;
|
||||
unk1 = 0;
|
||||
x = y = z = o = t_x = t_y = t_z = t_o = s_pitch = j_zspeed = j_sinAngle = j_cosAngle = j_xyspeed = u_unk1 = 0.0f;
|
||||
t_guid = 0;
|
||||
}
|
||||
|
||||
uint32 GetMovementFlags() { return flags; }
|
||||
void AddMovementFlag(uint32 flag) { flags |= flag; }
|
||||
bool HasMovementFlag(uint32 flag) const { return flags & flag; }
|
||||
};
|
||||
|
||||
class Object
|
||||
{
|
||||
public:
|
||||
@@ -696,12 +733,21 @@ class WorldObject : public Object, public WorldLocation
|
||||
|
||||
bool m_isWorldObject;
|
||||
uint32 LastUsedScriptID;
|
||||
|
||||
// Transports
|
||||
Transport *GetTransport() const { return m_transport; }
|
||||
void SetTransport(Transport *t) { m_transport = t; }
|
||||
|
||||
MovementInfo m_movementInfo;
|
||||
protected:
|
||||
explicit WorldObject();
|
||||
std::string m_name;
|
||||
bool m_isActive;
|
||||
ZoneScript *m_zoneScript;
|
||||
|
||||
// transports
|
||||
Transport *m_transport;
|
||||
|
||||
//these functions are used mostly for Relocate() and Corpse/Player specific stuff...
|
||||
//use them ONLY in LoadFromDB()/Create() funcs and nowhere else!
|
||||
//mapId/instanceId should be set in SetMap() function!
|
||||
|
||||
@@ -16093,7 +16093,7 @@ bool Player::LoadFromDB(uint32 guid, SqlQueryHolder *holder)
|
||||
GetPositionX()+m_movementInfo.t_x,GetPositionY()+m_movementInfo.t_y,
|
||||
GetPositionZ()+m_movementInfo.t_z,GetOrientation()+m_movementInfo.t_o) ||
|
||||
// transport size limited
|
||||
m_movementInfo.t_x > 50 || m_movementInfo.t_y > 50 || m_movementInfo.t_z > 50)
|
||||
m_movementInfo.t_x > 250 || m_movementInfo.t_y > 250 || m_movementInfo.t_z > 250)
|
||||
{
|
||||
sLog.outError("Player (guidlow %d) have invalid transport coordinates (X: %f Y: %f Z: %f O: %f). Teleport to default race/class locations.",
|
||||
guid,GetPositionX()+m_movementInfo.t_x,GetPositionY()+m_movementInfo.t_y,
|
||||
|
||||
@@ -108,7 +108,12 @@ void MapManager::LoadTransports()
|
||||
//If we someday decide to use the grid to track transports, here:
|
||||
t->SetMap(sMapMgr.CreateMap(mapid, t, 0));
|
||||
|
||||
//t->GetMap()->Add<GameObject>((GameObject *)t);
|
||||
for (TransportNPCSet::const_iterator i = m_TransportNPCMap[entry].begin(); i != m_TransportNPCMap[entry].end(); ++i)
|
||||
{
|
||||
TransportCreatureProto *proto = (*i);
|
||||
t->AddNPCPassenger(proto->guid, proto->npc_entry, proto->TransOffsetX, proto->TransOffsetY, proto->TransOffsetZ, proto->TransOffsetO, proto->emote);
|
||||
}
|
||||
|
||||
++count;
|
||||
} while (result->NextRow());
|
||||
|
||||
@@ -132,6 +137,48 @@ void MapManager::LoadTransports()
|
||||
}
|
||||
}
|
||||
|
||||
void MapManager::LoadTransportNPCs()
|
||||
{
|
||||
// Spawn NPCs linked to the transport
|
||||
// 0 1 2 3 4 5 6 7
|
||||
QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT guid, npc_entry, transport_entry, TransOffsetX, TransOffsetY, TransOffsetZ, TransOffsetO, emote FROM creature_transport");
|
||||
uint32 count = 0;
|
||||
|
||||
if (!result)
|
||||
{
|
||||
barGoLink bar(1);
|
||||
bar.step();
|
||||
|
||||
sLog.outString();
|
||||
sLog.outString(">> Loaded %u transport NPCs.", count);
|
||||
return;
|
||||
}
|
||||
|
||||
barGoLink bar(result->GetRowCount());
|
||||
|
||||
do
|
||||
{
|
||||
bar.step();
|
||||
Field *fields = result->Fetch();
|
||||
TransportCreatureProto *transportCreatureProto = new TransportCreatureProto;
|
||||
transportCreatureProto->guid = fields[0].GetUInt32();
|
||||
transportCreatureProto->npc_entry = fields[1].GetUInt32();
|
||||
uint32 transportEntry = fields[2].GetUInt32();
|
||||
transportCreatureProto->TransOffsetX = fields[3].GetFloat();
|
||||
transportCreatureProto->TransOffsetY = fields[4].GetFloat();
|
||||
transportCreatureProto->TransOffsetZ = fields[5].GetFloat();
|
||||
transportCreatureProto->TransOffsetO = fields[6].GetFloat();
|
||||
transportCreatureProto->emote = fields[7].GetUInt32();
|
||||
|
||||
m_TransportNPCs.insert(transportCreatureProto);
|
||||
m_TransportNPCMap[transportEntry].insert(transportCreatureProto);
|
||||
|
||||
count++;
|
||||
} while (result->NextRow());
|
||||
sLog.outString();
|
||||
sLog.outString(">> Loaded %u transport npcs", count);
|
||||
}
|
||||
|
||||
Transport::Transport() : GameObject()
|
||||
{
|
||||
m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_ROTATION);
|
||||
@@ -443,16 +490,22 @@ void Transport::TeleportTransport(uint32 newMapid, float x, float y, float z)
|
||||
plr->ResurrectPlayer(1.0);
|
||||
}
|
||||
plr->TeleportTo(newMapid, x, y, z, GetOrientation(), TELE_TO_NOT_LEAVE_TRANSPORT);
|
||||
|
||||
//WorldPacket data(SMSG_811, 4);
|
||||
//data << uint32(0);
|
||||
//plr->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
//we need to create and save new Map object with 'newMapid' because if not done -> lead to invalid Map object reference...
|
||||
//player far teleport would try to create same instance, but we need it NOW for transport...
|
||||
//correct me if I'm wrong O.o
|
||||
//yes, you're right
|
||||
|
||||
// Clear all NPCs on the transport
|
||||
for (std::set<uint64>::iterator itr = m_NPCPassengerSet.begin(); itr != m_NPCPassengerSet.end();)
|
||||
{
|
||||
std::set<uint64>::iterator it2 = itr;
|
||||
++itr;
|
||||
|
||||
uint64 guid = (*it2);
|
||||
if (Creature *npc = Creature::GetCreature(*this, guid))
|
||||
npc->AddObjectToRemoveList();
|
||||
}
|
||||
m_NPCPassengerSet.clear();
|
||||
|
||||
ResetMap();
|
||||
Map * newMap = sMapMgr.CreateMap(newMapid, this, 0);
|
||||
@@ -464,6 +517,12 @@ void Transport::TeleportTransport(uint32 newMapid, float x, float y, float z)
|
||||
UpdateForMap(oldMap);
|
||||
UpdateForMap(newMap);
|
||||
}
|
||||
|
||||
for (std::set<TransportCreatureProto *>::const_iterator i = sMapMgr.m_TransportNPCMap[GetEntry()].begin(); i != sMapMgr.m_TransportNPCMap[GetEntry()].end(); ++i)
|
||||
{
|
||||
TransportCreatureProto *proto = (*i);
|
||||
AddNPCPassenger(proto->guid, proto->npc_entry, proto->TransOffsetX, proto->TransOffsetY, proto->TransOffsetZ, proto->TransOffsetO, proto->emote);
|
||||
}
|
||||
}
|
||||
|
||||
bool Transport::AddPassenger(Player* passenger)
|
||||
@@ -502,37 +561,9 @@ void Transport::Update(uint32 /*p_time*/)
|
||||
}
|
||||
else
|
||||
{
|
||||
Relocate(m_curr->second.x, m_curr->second.y, m_curr->second.z);
|
||||
Relocate(m_curr->second.x, m_curr->second.y, m_curr->second.z, GetAngle(m_next->second.x,m_next->second.y) + 3.1415926f);
|
||||
UpdateNPCPositions(); // COME BACK MARKER
|
||||
}
|
||||
/*
|
||||
if (m_curr->second.delayed)
|
||||
{
|
||||
switch (GetEntry())
|
||||
{
|
||||
case 176495:
|
||||
case 164871:
|
||||
case 175080:
|
||||
SendPlaySound(11804, false); break; // ZeppelinDocked
|
||||
case 20808:
|
||||
case 181646:
|
||||
case 176231:
|
||||
case 176244:
|
||||
case 176310:
|
||||
case 177233:
|
||||
SendPlaySound(5495, false);break; // BoatDockingWarning
|
||||
default:
|
||||
SendPlaySound(5154, false); break; // ShipDocked
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*
|
||||
for (PlayerSet::const_iterator itr = m_passengers.begin(); itr != m_passengers.end();)
|
||||
{
|
||||
PlayerSet::const_iterator it2 = itr;
|
||||
++itr;
|
||||
//(*it2)->SetPosition(m_curr->second.x + (*it2)->GetTransOffsetX(), m_curr->second.y + (*it2)->GetTransOffsetY(), m_curr->second.z + (*it2)->GetTransOffsetZ(), (*it2)->GetTransOffsetO());
|
||||
}
|
||||
*/
|
||||
|
||||
m_nextNodeTime = m_curr->first;
|
||||
|
||||
@@ -585,3 +616,109 @@ void Transport::DoEventIfAny(WayPointMap::value_type const& node, bool departure
|
||||
GetMap()->ScriptsStart(sEventScripts, eventid, this, this);
|
||||
}
|
||||
}
|
||||
|
||||
void Transport::BuildStartMovePacket(Map const* targetMap)
|
||||
{
|
||||
SetByteValue(GAMEOBJECT_FLAGS ,0,41);
|
||||
SetByteValue(GAMEOBJECT_BYTES_1, 0, GO_STATE_ACTIVE);
|
||||
UpdateForMap(targetMap);
|
||||
}
|
||||
|
||||
void Transport::BuildStopMovePacket(Map const* targetMap)
|
||||
{
|
||||
SetByteValue(GAMEOBJECT_FLAGS ,0,40);
|
||||
UpdateForMap(targetMap);
|
||||
}
|
||||
|
||||
uint32 Transport::AddNPCPassenger(uint32 tguid, uint32 entry, float x, float y, float z, float o, uint32 anim)
|
||||
{
|
||||
Map* map = GetMap();
|
||||
Creature* pCreature = new Creature;
|
||||
|
||||
if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), GetMap(), this->GetPhaseMask(), entry, 0, (uint32)(this->GetGOInfo()->faction), 0, 0, 0, 0))
|
||||
{
|
||||
delete pCreature;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pCreature->SetTransport(this);
|
||||
pCreature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
|
||||
pCreature->m_movementInfo.guid = GetGUID();
|
||||
pCreature->m_movementInfo.t_x = x;
|
||||
pCreature->m_movementInfo.t_y = y;
|
||||
pCreature->m_movementInfo.t_z = z;
|
||||
pCreature->m_movementInfo.t_o = o;
|
||||
pCreature->setActive(true);
|
||||
|
||||
if (anim > 0)
|
||||
pCreature->SetUInt32Value(UNIT_NPC_EMOTESTATE,anim);
|
||||
|
||||
pCreature->Relocate(
|
||||
GetPositionX() + (x * cos(GetOrientation()) + y * sin(GetOrientation() + 3.14159f)),
|
||||
GetPositionY() + (y * cos(GetOrientation()) + x * sin(GetOrientation())),
|
||||
z + GetPositionZ() ,
|
||||
o + GetOrientation());
|
||||
|
||||
if(!pCreature->IsPositionValid())
|
||||
{
|
||||
sLog.outError("Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",pCreature->GetGUIDLow(),pCreature->GetEntry(),pCreature->GetPositionX(),pCreature->GetPositionY());
|
||||
delete pCreature;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pCreature->AIM_Initialize();
|
||||
|
||||
map->Add(pCreature);
|
||||
m_NPCPassengerSet.insert(pCreature->GetGUID());
|
||||
if (tguid == 0)
|
||||
{
|
||||
currenttguid++;
|
||||
tguid = currenttguid;
|
||||
}
|
||||
else
|
||||
currenttguid = std::max(tguid,currenttguid);
|
||||
|
||||
pCreature->SetGUIDTransport(tguid);
|
||||
return tguid;
|
||||
}
|
||||
|
||||
void Transport::UpdatePosition(MovementInfo* mi)
|
||||
{
|
||||
float transport_o = mi->o - mi->t_o;
|
||||
float transport_x = mi->x - (mi->t_x*cos(transport_o) - mi->t_y*sin(transport_o));
|
||||
float transport_y = mi->y - (mi->t_y*cos(transport_o) + mi->t_x*sin(transport_o));
|
||||
float transport_z = mi->z - mi->t_z;
|
||||
|
||||
Relocate(transport_x,transport_y,transport_z,transport_o);
|
||||
UpdateNPCPositions();
|
||||
}
|
||||
|
||||
void Transport::UpdateNPCPositions()
|
||||
{
|
||||
if (m_NPCPassengerSet.size() > 0)
|
||||
{
|
||||
// We update the positions of all NPCs
|
||||
for(std::set<uint64>::iterator itr = m_NPCPassengerSet.begin(); itr != m_NPCPassengerSet.end();)
|
||||
{
|
||||
std::set<uint64>::iterator it2 = itr;
|
||||
++itr;
|
||||
|
||||
uint64 guid = (*it2);
|
||||
if (Creature* npc = Creature::GetCreature(*this, guid))
|
||||
{
|
||||
float x, y, z, o;
|
||||
o = GetOrientation() + npc->m_movementInfo.t_o;
|
||||
x = GetPositionX() + (npc->m_movementInfo.t_x * cos(GetOrientation()) + npc->m_movementInfo.t_y * sin(GetOrientation() + 3.14159f));
|
||||
y = GetPositionY() + (npc->m_movementInfo.t_y * cos(GetOrientation()) + npc->m_movementInfo.t_x * sin(GetOrientation()));
|
||||
z = GetPositionZ() + npc->m_movementInfo.t_z;
|
||||
npc->SetPosition(x, y, z,o);
|
||||
npc->SetHomePosition(x,y,z,o);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_NPCPassengerSet.erase(guid);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,18 @@
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
struct TransportCreatureProto
|
||||
{
|
||||
uint32 guid;
|
||||
uint32 transport_entry;
|
||||
uint32 npc_entry;
|
||||
float TransOffsetX;
|
||||
float TransOffsetY;
|
||||
float TransOffsetZ;
|
||||
float TransOffsetO;
|
||||
uint32 emote;
|
||||
};
|
||||
|
||||
class Transport : public GameObject
|
||||
{
|
||||
public:
|
||||
@@ -41,6 +53,12 @@ class Transport : public GameObject
|
||||
typedef std::set<Player*> PlayerSet;
|
||||
PlayerSet const& GetPassengers() const { return m_passengers; }
|
||||
|
||||
mutable std::set<uint64> m_NPCPassengerSet;
|
||||
uint32 AddNPCPassenger(uint32 tguid, uint32 entry, float x, float y, float z, float o, uint32 anim=0);
|
||||
void UpdatePosition(MovementInfo *mi);
|
||||
void UpdateNPCPositions();
|
||||
void BuildStartMovePacket(Map const *targetMap);
|
||||
void BuildStopMovePacket(Map const *targetMap);
|
||||
private:
|
||||
struct WayPoint
|
||||
{
|
||||
@@ -70,6 +88,7 @@ class Transport : public GameObject
|
||||
|
||||
PlayerSet m_passengers;
|
||||
|
||||
uint32 currenttguid;
|
||||
public:
|
||||
WayPointMap m_WayPoints;
|
||||
uint32 m_nextNodeTime;
|
||||
|
||||
@@ -96,7 +96,7 @@ static bool procPrepared = InitTriggerAuraData();
|
||||
Unit::Unit()
|
||||
: WorldObject(), i_motionMaster(this), m_ThreatManager(this), m_HostileRefManager(this)
|
||||
, IsAIEnabled(false), NeedChangeAI(false)
|
||||
, i_AI(NULL), i_disabledAI(NULL), m_removedAurasCount(0), m_vehicle(NULL), m_transport(NULL)
|
||||
, i_AI(NULL), i_disabledAI(NULL), m_removedAurasCount(0), m_vehicle(NULL)
|
||||
, m_ControlledByPlayer(false), m_procDeep(0), m_unitTypeMask(UNIT_MASK_NONE), m_vehicleKit(NULL)
|
||||
, m_movedPlayer(NULL)
|
||||
{
|
||||
|
||||
@@ -722,42 +722,6 @@ enum MonsterMovementFlags
|
||||
};
|
||||
*/
|
||||
|
||||
struct MovementInfo
|
||||
{
|
||||
// common
|
||||
uint64 guid;
|
||||
uint32 flags;
|
||||
uint16 unk1;
|
||||
uint32 time;
|
||||
float x, y, z, o;
|
||||
// transport
|
||||
uint64 t_guid;
|
||||
float t_x, t_y, t_z, t_o;
|
||||
uint32 t_time;
|
||||
int8 t_seat;
|
||||
// swimming and unknown
|
||||
float s_pitch;
|
||||
// last fall time
|
||||
uint32 fallTime;
|
||||
// jumping
|
||||
float j_zspeed, j_sinAngle, j_cosAngle, j_xyspeed;
|
||||
// spline
|
||||
float u_unk1;
|
||||
|
||||
MovementInfo()
|
||||
{
|
||||
flags = 0;
|
||||
time = t_time = fallTime = 0;
|
||||
unk1 = 0;
|
||||
x = y = z = o = t_x = t_y = t_z = t_o = s_pitch = j_zspeed = j_sinAngle = j_cosAngle = j_xyspeed = u_unk1 = 0.0f;
|
||||
t_guid = 0;
|
||||
}
|
||||
|
||||
uint32 GetMovementFlags() { return flags; }
|
||||
void AddMovementFlag(uint32 flag) { flags |= flag; }
|
||||
bool HasMovementFlag(uint32 flag) const { return flags & flag; }
|
||||
};
|
||||
|
||||
enum UnitTypeMask
|
||||
{
|
||||
UNIT_MASK_NONE = 0x00000000,
|
||||
@@ -1936,7 +1900,6 @@ class Unit : public WorldObject
|
||||
Unit *GetMisdirectionTarget() { return m_misdirectionTargetGUID ? GetUnit(*this, m_misdirectionTargetGUID) : NULL; }
|
||||
|
||||
bool IsAIEnabled, NeedChangeAI;
|
||||
MovementInfo m_movementInfo;
|
||||
bool CreateVehicleKit(uint32 id);
|
||||
void RemoveVehicleKit();
|
||||
Vehicle *GetVehicleKit()const { return m_vehicleKit; }
|
||||
@@ -1959,10 +1922,6 @@ class Unit : public WorldObject
|
||||
void ExitVehicle();
|
||||
void ChangeSeat(int8 seatId, bool next = true);
|
||||
|
||||
// Transports
|
||||
Transport * GetTransport() const { return m_transport; }
|
||||
void SetTransport(Transport * t) { m_transport = t; }
|
||||
|
||||
void BuildMovementPacket(ByteBuffer *data) const;
|
||||
|
||||
bool isMoving() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_MOVING); }
|
||||
@@ -1988,9 +1947,6 @@ class Unit : public WorldObject
|
||||
|
||||
UnitAI *i_AI, *i_disabledAI;
|
||||
|
||||
// Transports
|
||||
Transport * m_transport;
|
||||
|
||||
void _UpdateSpells(uint32 time);
|
||||
void _DeleteRemovedAuras();
|
||||
|
||||
|
||||
@@ -52,6 +52,9 @@ MapManager::~MapManager()
|
||||
for (TransportSet::iterator i = m_Transports.begin(); i != m_Transports.end(); ++i)
|
||||
delete *i;
|
||||
|
||||
for (TransportNPCSet::iterator i = m_TransportNPCs.begin(); i != m_TransportNPCs.end(); ++i)
|
||||
delete *i;
|
||||
|
||||
Map::DeleteStateMachine();
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "MapUpdater.h"
|
||||
|
||||
class Transport;
|
||||
struct TransportCreatureProto;
|
||||
|
||||
class MapManager
|
||||
{
|
||||
@@ -125,6 +126,7 @@ class MapManager
|
||||
void DoDelayedMovesAndRemoves();
|
||||
|
||||
void LoadTransports();
|
||||
void LoadTransportNPCs();
|
||||
|
||||
typedef std::set<Transport *> TransportSet;
|
||||
TransportSet m_Transports;
|
||||
@@ -132,6 +134,11 @@ class MapManager
|
||||
typedef std::map<uint32, TransportSet> TransportMap;
|
||||
TransportMap m_TransportsByMap;
|
||||
|
||||
typedef std::set<TransportCreatureProto *> TransportNPCSet;
|
||||
TransportNPCSet m_TransportNPCs;
|
||||
typedef std::map<uint32, TransportNPCSet> TransportNPCMap;
|
||||
TransportNPCMap m_TransportNPCMap;
|
||||
|
||||
bool CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck = false);
|
||||
void RemoveBonesFromMap(uint32 mapid, uint64 guid, float x, float y);
|
||||
uint32 GenerateInstanceId() { return ++i_MaxInstanceId; }
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "zlib.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "LFGMgr.h"
|
||||
#include "Transport.h"
|
||||
|
||||
/// WorldSession constructor
|
||||
WorldSession::WorldSession(uint32 id, WorldSocket *sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale) :
|
||||
@@ -729,6 +730,10 @@ void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo *mi)
|
||||
data >> mi->t_o;
|
||||
data >> mi->t_time;
|
||||
data >> mi->t_seat;
|
||||
|
||||
if(mi->x != mi->t_x)
|
||||
if(GetPlayer()->GetTransport())
|
||||
GetPlayer()->GetTransport()->UpdatePosition(mi);
|
||||
}
|
||||
|
||||
if ((mi->flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || (mi->unk1 & 0x20))
|
||||
|
||||
@@ -1704,7 +1704,9 @@ void World::SetInitialWorldSettings()
|
||||
sLog.outString("Starting Outdoor PvP System");
|
||||
sOutdoorPvPMgr.InitOutdoorPvP();
|
||||
|
||||
//Not sure if this can be moved up in the sequence (with static data loading) as it uses MapManager
|
||||
sLog.outString("Loading Transport NPCs...");
|
||||
sMapMgr.LoadTransportNPCs();
|
||||
|
||||
sLog.outString("Loading Transports...");
|
||||
sMapMgr.LoadTransports();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user