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 <map>
|
||||||
#include "GlobalEvents.h"
|
#include "GlobalEvents.h"
|
||||||
#include "OutdoorPvPMgr.h"
|
#include "OutdoorPvPMgr.h"
|
||||||
|
#include "Transport.h"
|
||||||
#include "TargetedMovementGenerator.h" // for HandleNpcUnFollowCommand
|
#include "TargetedMovementGenerator.h" // for HandleNpcUnFollowCommand
|
||||||
#include "CreatureGroups.h"
|
#include "CreatureGroups.h"
|
||||||
|
|
||||||
@@ -1005,6 +1005,29 @@ bool ChatHandler::HandleNpcAddCommand(const char* args)
|
|||||||
float o = chr->GetOrientation();
|
float o = chr->GetOrientation();
|
||||||
Map *map = chr->GetMap();
|
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;
|
Creature* pCreature = new Creature;
|
||||||
if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0, (uint32)teamval, x, y, z, o))
|
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 "DBCEnums.h"
|
||||||
#include "ConditionMgr.h"
|
#include "ConditionMgr.h"
|
||||||
#include "DisableMgr.h"
|
#include "DisableMgr.h"
|
||||||
|
#include "Transport.h"
|
||||||
|
|
||||||
bool ChatHandler::HandleAHBotOptionsCommand(const char *args)
|
bool ChatHandler::HandleAHBotOptionsCommand(const char *args)
|
||||||
{
|
{
|
||||||
@@ -4801,6 +4802,10 @@ bool ChatHandler::HandleNpcPlayEmoteCommand(const char *args)
|
|||||||
return false;
|
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);
|
target->SetUInt32Value(UNIT_NPC_EMOTESTATE,emote);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -667,6 +667,8 @@ class Creature : public Unit, public GridObject<Creature>
|
|||||||
|
|
||||||
float m_SightDistance, m_CombatDistance;
|
float m_SightDistance, m_CombatDistance;
|
||||||
|
|
||||||
|
void SetGUIDTransport(uint32 guid) { guid_transport=guid; }
|
||||||
|
uint32 GetGUIDTransport() { return guid_transport; }
|
||||||
protected:
|
protected:
|
||||||
bool CreateFromProto(uint32 guidlow, uint32 Entry, uint32 vehId, uint32 team, const CreatureData *data = NULL);
|
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);
|
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;
|
CreatureData const* m_creatureData;
|
||||||
|
|
||||||
uint16 m_LootMode; // bitmask, default LOOT_MODE_DEFAULT, determines what loot will be lootable
|
uint16 m_LootMode; // bitmask, default LOOT_MODE_DEFAULT, determines what loot will be lootable
|
||||||
|
uint32 guid_transport;
|
||||||
private:
|
private:
|
||||||
//WaypointMovementGenerator vars
|
//WaypointMovementGenerator vars
|
||||||
uint32 m_waypointID;
|
uint32 m_waypointID;
|
||||||
|
|||||||
@@ -1151,6 +1151,7 @@ WorldObject::WorldObject()
|
|||||||
, m_name("")
|
, m_name("")
|
||||||
, m_notifyflags(0), m_executed_notifies(0)
|
, m_notifyflags(0), m_executed_notifies(0)
|
||||||
{
|
{
|
||||||
|
m_transport = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldObject::SetWorldObject(bool on)
|
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
|
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 dx = GetPositionX() - obj->GetPositionX();
|
||||||
float dy = GetPositionY() - obj->GetPositionY();
|
float dy = GetPositionY() - obj->GetPositionY();
|
||||||
float distsq = dx*dx + dy*dy;
|
float distsq = dx*dx + dy*dy;
|
||||||
@@ -1243,8 +1260,6 @@ bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool
|
|||||||
float dz = GetPositionZ() - obj->GetPositionZ();
|
float dz = GetPositionZ() - obj->GetPositionZ();
|
||||||
distsq += dz*dz;
|
distsq += dz*dz;
|
||||||
}
|
}
|
||||||
float sizefactor = GetObjectSize() + obj->GetObjectSize();
|
|
||||||
float maxdist = dist2compare + sizefactor;
|
|
||||||
|
|
||||||
return distsq < maxdist * maxdist;
|
return distsq < maxdist * maxdist;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,9 +115,46 @@ class Vehicle;
|
|||||||
class CreatureAI;
|
class CreatureAI;
|
||||||
class ZoneScript;
|
class ZoneScript;
|
||||||
class Unit;
|
class Unit;
|
||||||
|
class Transport;
|
||||||
|
|
||||||
typedef UNORDERED_MAP<Player*, UpdateData> UpdateDataMapType;
|
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
|
class Object
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -696,12 +733,21 @@ class WorldObject : public Object, public WorldLocation
|
|||||||
|
|
||||||
bool m_isWorldObject;
|
bool m_isWorldObject;
|
||||||
uint32 LastUsedScriptID;
|
uint32 LastUsedScriptID;
|
||||||
|
|
||||||
|
// Transports
|
||||||
|
Transport *GetTransport() const { return m_transport; }
|
||||||
|
void SetTransport(Transport *t) { m_transport = t; }
|
||||||
|
|
||||||
|
MovementInfo m_movementInfo;
|
||||||
protected:
|
protected:
|
||||||
explicit WorldObject();
|
explicit WorldObject();
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
bool m_isActive;
|
bool m_isActive;
|
||||||
ZoneScript *m_zoneScript;
|
ZoneScript *m_zoneScript;
|
||||||
|
|
||||||
|
// transports
|
||||||
|
Transport *m_transport;
|
||||||
|
|
||||||
//these functions are used mostly for Relocate() and Corpse/Player specific stuff...
|
//these functions are used mostly for Relocate() and Corpse/Player specific stuff...
|
||||||
//use them ONLY in LoadFromDB()/Create() funcs and nowhere else!
|
//use them ONLY in LoadFromDB()/Create() funcs and nowhere else!
|
||||||
//mapId/instanceId should be set in SetMap() function!
|
//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,
|
GetPositionX()+m_movementInfo.t_x,GetPositionY()+m_movementInfo.t_y,
|
||||||
GetPositionZ()+m_movementInfo.t_z,GetOrientation()+m_movementInfo.t_o) ||
|
GetPositionZ()+m_movementInfo.t_z,GetOrientation()+m_movementInfo.t_o) ||
|
||||||
// transport size limited
|
// 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.",
|
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,
|
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:
|
//If we someday decide to use the grid to track transports, here:
|
||||||
t->SetMap(sMapMgr.CreateMap(mapid, t, 0));
|
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;
|
++count;
|
||||||
} while (result->NextRow());
|
} 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()
|
Transport::Transport() : GameObject()
|
||||||
{
|
{
|
||||||
m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_ROTATION);
|
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->ResurrectPlayer(1.0);
|
||||||
}
|
}
|
||||||
plr->TeleportTo(newMapid, x, y, z, GetOrientation(), TELE_TO_NOT_LEAVE_TRANSPORT);
|
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...
|
//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...
|
//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();
|
ResetMap();
|
||||||
Map * newMap = sMapMgr.CreateMap(newMapid, this, 0);
|
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(oldMap);
|
||||||
UpdateForMap(newMap);
|
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)
|
bool Transport::AddPassenger(Player* passenger)
|
||||||
@@ -502,37 +561,9 @@ void Transport::Update(uint32 /*p_time*/)
|
|||||||
}
|
}
|
||||||
else
|
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;
|
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);
|
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 <set>
|
||||||
#include <string>
|
#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
|
class Transport : public GameObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -41,6 +53,12 @@ class Transport : public GameObject
|
|||||||
typedef std::set<Player*> PlayerSet;
|
typedef std::set<Player*> PlayerSet;
|
||||||
PlayerSet const& GetPassengers() const { return m_passengers; }
|
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:
|
private:
|
||||||
struct WayPoint
|
struct WayPoint
|
||||||
{
|
{
|
||||||
@@ -70,6 +88,7 @@ class Transport : public GameObject
|
|||||||
|
|
||||||
PlayerSet m_passengers;
|
PlayerSet m_passengers;
|
||||||
|
|
||||||
|
uint32 currenttguid;
|
||||||
public:
|
public:
|
||||||
WayPointMap m_WayPoints;
|
WayPointMap m_WayPoints;
|
||||||
uint32 m_nextNodeTime;
|
uint32 m_nextNodeTime;
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ static bool procPrepared = InitTriggerAuraData();
|
|||||||
Unit::Unit()
|
Unit::Unit()
|
||||||
: WorldObject(), i_motionMaster(this), m_ThreatManager(this), m_HostileRefManager(this)
|
: WorldObject(), i_motionMaster(this), m_ThreatManager(this), m_HostileRefManager(this)
|
||||||
, IsAIEnabled(false), NeedChangeAI(false)
|
, 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_ControlledByPlayer(false), m_procDeep(0), m_unitTypeMask(UNIT_MASK_NONE), m_vehicleKit(NULL)
|
||||||
, m_movedPlayer(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
|
enum UnitTypeMask
|
||||||
{
|
{
|
||||||
UNIT_MASK_NONE = 0x00000000,
|
UNIT_MASK_NONE = 0x00000000,
|
||||||
@@ -1936,7 +1900,6 @@ class Unit : public WorldObject
|
|||||||
Unit *GetMisdirectionTarget() { return m_misdirectionTargetGUID ? GetUnit(*this, m_misdirectionTargetGUID) : NULL; }
|
Unit *GetMisdirectionTarget() { return m_misdirectionTargetGUID ? GetUnit(*this, m_misdirectionTargetGUID) : NULL; }
|
||||||
|
|
||||||
bool IsAIEnabled, NeedChangeAI;
|
bool IsAIEnabled, NeedChangeAI;
|
||||||
MovementInfo m_movementInfo;
|
|
||||||
bool CreateVehicleKit(uint32 id);
|
bool CreateVehicleKit(uint32 id);
|
||||||
void RemoveVehicleKit();
|
void RemoveVehicleKit();
|
||||||
Vehicle *GetVehicleKit()const { return m_vehicleKit; }
|
Vehicle *GetVehicleKit()const { return m_vehicleKit; }
|
||||||
@@ -1959,10 +1922,6 @@ class Unit : public WorldObject
|
|||||||
void ExitVehicle();
|
void ExitVehicle();
|
||||||
void ChangeSeat(int8 seatId, bool next = true);
|
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;
|
void BuildMovementPacket(ByteBuffer *data) const;
|
||||||
|
|
||||||
bool isMoving() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_MOVING); }
|
bool isMoving() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_MOVING); }
|
||||||
@@ -1988,9 +1947,6 @@ class Unit : public WorldObject
|
|||||||
|
|
||||||
UnitAI *i_AI, *i_disabledAI;
|
UnitAI *i_AI, *i_disabledAI;
|
||||||
|
|
||||||
// Transports
|
|
||||||
Transport * m_transport;
|
|
||||||
|
|
||||||
void _UpdateSpells(uint32 time);
|
void _UpdateSpells(uint32 time);
|
||||||
void _DeleteRemovedAuras();
|
void _DeleteRemovedAuras();
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ MapManager::~MapManager()
|
|||||||
for (TransportSet::iterator i = m_Transports.begin(); i != m_Transports.end(); ++i)
|
for (TransportSet::iterator i = m_Transports.begin(); i != m_Transports.end(); ++i)
|
||||||
delete *i;
|
delete *i;
|
||||||
|
|
||||||
|
for (TransportNPCSet::iterator i = m_TransportNPCs.begin(); i != m_TransportNPCs.end(); ++i)
|
||||||
|
delete *i;
|
||||||
|
|
||||||
Map::DeleteStateMachine();
|
Map::DeleteStateMachine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "MapUpdater.h"
|
#include "MapUpdater.h"
|
||||||
|
|
||||||
class Transport;
|
class Transport;
|
||||||
|
struct TransportCreatureProto;
|
||||||
|
|
||||||
class MapManager
|
class MapManager
|
||||||
{
|
{
|
||||||
@@ -125,6 +126,7 @@ class MapManager
|
|||||||
void DoDelayedMovesAndRemoves();
|
void DoDelayedMovesAndRemoves();
|
||||||
|
|
||||||
void LoadTransports();
|
void LoadTransports();
|
||||||
|
void LoadTransportNPCs();
|
||||||
|
|
||||||
typedef std::set<Transport *> TransportSet;
|
typedef std::set<Transport *> TransportSet;
|
||||||
TransportSet m_Transports;
|
TransportSet m_Transports;
|
||||||
@@ -132,6 +134,11 @@ class MapManager
|
|||||||
typedef std::map<uint32, TransportSet> TransportMap;
|
typedef std::map<uint32, TransportSet> TransportMap;
|
||||||
TransportMap m_TransportsByMap;
|
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);
|
bool CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck = false);
|
||||||
void RemoveBonesFromMap(uint32 mapid, uint64 guid, float x, float y);
|
void RemoveBonesFromMap(uint32 mapid, uint64 guid, float x, float y);
|
||||||
uint32 GenerateInstanceId() { return ++i_MaxInstanceId; }
|
uint32 GenerateInstanceId() { return ++i_MaxInstanceId; }
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
#include "zlib.h"
|
#include "zlib.h"
|
||||||
#include "ScriptMgr.h"
|
#include "ScriptMgr.h"
|
||||||
#include "LFGMgr.h"
|
#include "LFGMgr.h"
|
||||||
|
#include "Transport.h"
|
||||||
|
|
||||||
/// WorldSession constructor
|
/// WorldSession constructor
|
||||||
WorldSession::WorldSession(uint32 id, WorldSocket *sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale) :
|
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_o;
|
||||||
data >> mi->t_time;
|
data >> mi->t_time;
|
||||||
data >> mi->t_seat;
|
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))
|
if ((mi->flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || (mi->unk1 & 0x20))
|
||||||
|
|||||||
@@ -1704,7 +1704,9 @@ void World::SetInitialWorldSettings()
|
|||||||
sLog.outString("Starting Outdoor PvP System");
|
sLog.outString("Starting Outdoor PvP System");
|
||||||
sOutdoorPvPMgr.InitOutdoorPvP();
|
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...");
|
sLog.outString("Loading Transports...");
|
||||||
sMapMgr.LoadTransports();
|
sMapMgr.LoadTransports();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user