aboutsummaryrefslogtreecommitdiff
path: root/src/game/Transports.cpp
diff options
context:
space:
mode:
authormaximius <none@none>2009-10-17 15:51:44 -0700
committermaximius <none@none>2009-10-17 15:51:44 -0700
commite585187b248f48b3c6e9247b49fa07c6565d65e5 (patch)
tree637c5b7ddacf41040bef4ea4f75a97da64c6a9bc /src/game/Transports.cpp
parent26b5e033ffde3d161382fc9addbfa99738379641 (diff)
*Backed out changeset 3be01fb200a5
--HG-- branch : trunk
Diffstat (limited to 'src/game/Transports.cpp')
-rw-r--r--src/game/Transports.cpp96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/game/Transports.cpp b/src/game/Transports.cpp
index d55e50986b4..25248b7b9d2 100644
--- a/src/game/Transports.cpp
+++ b/src/game/Transports.cpp
@@ -17,51 +17,70 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+
#include "Common.h"
+
#include "Transports.h"
#include "MapManager.h"
#include "ObjectMgr.h"
#include "Path.h"
+
#include "WorldPacket.h"
#include "DBCStores.h"
#include "ProgressBar.h"
+
#include "World.h"
+
void MapManager::LoadTransports()
{
QueryResult *result = WorldDatabase.Query("SELECT entry, name, period FROM transports");
+
uint32 count = 0;
+
if( !result )
{
barGoLink bar( 1 );
bar.step();
+
sLog.outString();
sLog.outString( ">> Loaded %u transports", count );
return;
}
+
barGoLink bar( result->GetRowCount() );
+
do
{
bar.step();
+
Transport *t = new Transport;
+
Field *fields = result->Fetch();
+
uint32 entry = fields[0].GetUInt32();
std::string name = fields[1].GetCppString();
t->m_period = fields[2].GetUInt32();
+
const GameObjectInfo *goinfo = objmgr.GetGameObjectInfo(entry);
+
if(!goinfo)
{
sLog.outErrorDb("Transport ID:%u, Name: %s, will not be loaded, gameobject_template missing", entry, name.c_str());
delete t;
continue;
}
+
if(goinfo->type != GAMEOBJECT_TYPE_MO_TRANSPORT)
{
sLog.outErrorDb("Transport ID:%u, Name: %s, will not be loaded, gameobject_template type wrong", entry, name.c_str());
delete t;
continue;
}
+
// sLog.outString("Loading transport %d between %s, %s", entry, name.c_str(), goinfo->name);
+
std::set<uint32> mapsUsed;
+
if(!t->GenerateWaypoints(goinfo->moTransport.taxiPathId, mapsUsed))
// skip transports with empty waypoints list
{
@@ -69,26 +88,34 @@ void MapManager::LoadTransports()
delete t;
continue;
}
+
float x, y, z, o;
uint32 mapid;
x = t->m_WayPoints[0].x; y = t->m_WayPoints[0].y; z = t->m_WayPoints[0].z; mapid = t->m_WayPoints[0].mapid; o = 1;
+
// creates the Gameobject
if(!t->Create(entry, mapid, x, y, z, o, 100, 0))
{
delete t;
continue;
}
+
m_Transports.insert(t);
+
for (std::set<uint32>::const_iterator i = mapsUsed.begin(); i != mapsUsed.end(); ++i)
m_TransportsByMap[*i].insert(t);
+
//If we someday decide to use the grid to track transports, here:
t->SetMap(MapManager::Instance().CreateMap(mapid, t, 0));
+
//t->GetMap()->Add<GameObject>((GameObject *)t);
++count;
} while(result->NextRow());
delete result;
+
sLog.outString();
sLog.outString( ">> Loaded %u transports", count );
+
// check transport data DB integrity
result = WorldDatabase.Query("SELECT gameobject.guid,gameobject.id,transports.name FROM gameobject,transports WHERE gameobject.id = transports.entry");
if(result) // wrong data found
@@ -96,52 +123,69 @@ void MapManager::LoadTransports()
do
{
Field *fields = result->Fetch();
+
uint32 guid = fields[0].GetUInt32();
uint32 entry = fields[1].GetUInt32();
std::string name = fields[2].GetCppString();
sLog.outErrorDb("Transport %u '%s' have record (GUID: %u) in `gameobject`. Transports DON'T must have any records in `gameobject` or its behavior will be unpredictable/bugged.",entry,name.c_str(),guid);
}
while(result->NextRow());
+
delete result;
}
}
+
Transport::Transport() : GameObject()
{
m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_ROTATION);
}
+
bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress, uint32 dynflags)
{
Relocate(x,y,z,ang);
// instance id and phaseMask isn't set to values different from std.
+
if(!IsPositionValid())
{
sLog.outError("Transport (GUID: %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)",
guidlow,x,y);
return false;
}
+
Object::_Create(guidlow, 0, HIGHGUID_MO_TRANSPORT);
+
GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(guidlow);
+
if (!goinfo)
{
sLog.outErrorDb("Transport not created: entry in `gameobject_template` not found, guidlow: %u map: %u (X: %f Y: %f Z: %f) ang: %f",guidlow, mapid, x, y, z, ang);
return false;
}
+
m_goInfo = goinfo;
+
SetFloatValue(OBJECT_FIELD_SCALE_X, goinfo->size);
+
SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction);
//SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags);
SetUInt32Value(GAMEOBJECT_FLAGS, MAKE_PAIR32(0x28, 0x64));
SetUInt32Value(GAMEOBJECT_LEVEL, m_period);
SetEntry(goinfo->id);
+
SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId);
+
SetGoState(GO_STATE_READY);
SetGoType(GameobjectTypes(goinfo->type));
+
SetGoAnimProgress(animprogress);
if(dynflags)
SetUInt32Value(GAMEOBJECT_DYNAMIC, MAKE_PAIR32(0, dynflags));
+
SetName(goinfo->name);
+
return true;
}
+
struct keyFrame
{
keyFrame(float _x, float _y, float _z, uint32 _mapid, int _actionflag, int _delay)
@@ -149,6 +193,7 @@ struct keyFrame
x = _x; y = _y; z = _z; mapid = _mapid; actionflag = _actionflag; delay = _delay; distFromPrev = -1; distSinceStop = -1; distUntilStop = -1;
tFrom = 0; tTo = 0;
}
+
float x;
float y;
float z;
@@ -160,12 +205,15 @@ struct keyFrame
float distFromPrev;
float tFrom, tTo;
};
+
bool Transport::GenerateWaypoints(uint32 pathid, std::set<uint32> &mapids)
{
TransportPath path;
objmgr.GetTransportPathNodes(pathid, path);
+
if (path.Empty())
return false;
+
std::vector<keyFrame> keyFrames;
int mapChange = 0;
mapids.clear();
@@ -189,14 +237,17 @@ bool Transport::GenerateWaypoints(uint32 pathid, std::set<uint32> &mapids)
--mapChange;
}
}
+
int lastStop = -1;
int firstStop = -1;
+
// first cell is arrived at by teleportation :S
keyFrames[0].distFromPrev = 0;
if (keyFrames[0].actionflag == 2)
{
lastStop = 0;
}
+
// find the rest of the distances between key points
for (size_t i = 1; i < keyFrames.size(); ++i)
{
@@ -219,6 +270,7 @@ bool Transport::GenerateWaypoints(uint32 pathid, std::set<uint32> &mapids)
lastStop = i;
}
}
+
float tmpDist = 0;
for (size_t i = 0; i < keyFrames.size(); ++i)
{
@@ -229,6 +281,7 @@ bool Transport::GenerateWaypoints(uint32 pathid, std::set<uint32> &mapids)
tmpDist += keyFrames[j].distFromPrev;
keyFrames[j].distSinceStop = tmpDist;
}
+
for (int i = int(keyFrames.size()) - 1; i >= 0; i--)
{
int j = (i + (firstStop+1)) % keyFrames.size();
@@ -237,37 +290,45 @@ bool Transport::GenerateWaypoints(uint32 pathid, std::set<uint32> &mapids)
if (keyFrames[j].actionflag == 2)
tmpDist = 0;
}
+
for (size_t i = 0; i < keyFrames.size(); ++i)
{
if (keyFrames[i].distSinceStop < (30 * 30 * 0.5f))
keyFrames[i].tFrom = sqrt(2 * keyFrames[i].distSinceStop);
else
keyFrames[i].tFrom = ((keyFrames[i].distSinceStop - (30 * 30 * 0.5f)) / 30) + 30;
+
if (keyFrames[i].distUntilStop < (30 * 30 * 0.5f))
keyFrames[i].tTo = sqrt(2 * keyFrames[i].distUntilStop);
else
keyFrames[i].tTo = ((keyFrames[i].distUntilStop - (30 * 30 * 0.5f)) / 30) + 30;
+
keyFrames[i].tFrom *= 1000;
keyFrames[i].tTo *= 1000;
}
+
// for (int i = 0; i < keyFrames.size(); ++i) {
// sLog.outString("%f, %f, %f, %f, %f, %f, %f", keyFrames[i].x, keyFrames[i].y, keyFrames[i].distUntilStop, keyFrames[i].distSinceStop, keyFrames[i].distFromPrev, keyFrames[i].tFrom, keyFrames[i].tTo);
// }
+
// Now we're completely set up; we can move along the length of each waypoint at 100 ms intervals
// speed = max(30, t) (remember x = 0.5s^2, and when accelerating, a = 1 unit/s^2
int t = 0;
bool teleport = false;
if (keyFrames[keyFrames.size() - 1].mapid != keyFrames[0].mapid)
teleport = true;
+
WayPoint pos(keyFrames[0].mapid, keyFrames[0].x, keyFrames[0].y, keyFrames[0].z, teleport, 0);
m_WayPoints[0] = pos;
t += keyFrames[0].delay * 1000;
+
uint32 cM = keyFrames[0].mapid;
for (size_t i = 0; i < keyFrames.size() - 1; ++i)
{
float d = 0;
float tFrom = keyFrames[i].tFrom;
float tTo = keyFrames[i].tTo;
+
// keep the generation of all these points; we use only a few now, but may need the others later
if (((d < keyFrames[i + 1].distFromPrev) && (tTo > 0)))
{
@@ -275,23 +336,27 @@ bool Transport::GenerateWaypoints(uint32 pathid, std::set<uint32> &mapids)
{
tFrom += 100;
tTo -= 100;
+
if (d > 0)
{
float newX, newY, newZ;
newX = keyFrames[i].x + (keyFrames[i + 1].x - keyFrames[i].x) * d / keyFrames[i + 1].distFromPrev;
newY = keyFrames[i].y + (keyFrames[i + 1].y - keyFrames[i].y) * d / keyFrames[i + 1].distFromPrev;
newZ = keyFrames[i].z + (keyFrames[i + 1].z - keyFrames[i].z) * d / keyFrames[i + 1].distFromPrev;
+
bool teleport = false;
if (keyFrames[i].mapid != cM)
{
teleport = true;
cM = keyFrames[i].mapid;
}
+
// sLog.outString("T: %d, D: %f, x: %f, y: %f, z: %f", t, d, newX, newY, newZ);
WayPoint pos(keyFrames[i].mapid, newX, newY, newZ, teleport, i);
if (teleport)
m_WayPoints[t] = pos;
}
+
if (tFrom < tTo) // caught in tFrom dock's "gravitational pull"
{
if (tFrom <= 30000)
@@ -320,17 +385,21 @@ bool Transport::GenerateWaypoints(uint32 pathid, std::set<uint32> &mapids)
}
t -= 100;
}
+
if (keyFrames[i + 1].tFrom > keyFrames[i + 1].tTo)
t += 100 - ((long)keyFrames[i + 1].tTo % 100);
else
t += (long)keyFrames[i + 1].tTo % 100;
+
bool teleport = false;
if ((keyFrames[i + 1].actionflag == 1) || (keyFrames[i + 1].mapid != keyFrames[i].mapid))
{
teleport = true;
cM = keyFrames[i + 1].mapid;
}
+
WayPoint pos(keyFrames[i + 1].mapid, keyFrames[i + 1].x, keyFrames[i + 1].y, keyFrames[i + 1].z, teleport, i);
+
// sLog.outString("T: %d, x: %f, y: %f, z: %f, t:%d", t, pos.x, pos.y, pos.z, teleport);
/*
if(keyFrames[i+1].delay > 5)
@@ -338,18 +407,25 @@ bool Transport::GenerateWaypoints(uint32 pathid, std::set<uint32> &mapids)
*/
//if (teleport)
m_WayPoints[t] = pos;
+
t += keyFrames[i + 1].delay * 1000;
// sLog.outString("------");
}
+
uint32 timer = t;
+
// sLog.outDetail(" Generated %lu waypoints, total time %u.", (unsigned long)m_WayPoints.size(), timer);
+
m_curr = m_WayPoints.begin();
m_curr = GetNextWayPoint();
m_next = GetNextWayPoint();
m_pathTime = timer;
+
m_nextNodeTime = m_curr->first;
+
return true;
}
+
Transport::WayPointMap::const_iterator Transport::GetNextWayPoint()
{
WayPointMap::const_iterator iter = m_curr;
@@ -358,64 +434,77 @@ Transport::WayPointMap::const_iterator Transport::GetNextWayPoint()
iter = m_WayPoints.begin();
return iter;
}
+
void Transport::TeleportTransport(uint32 newMapid, float x, float y, float z)
{
Map const* oldMap = GetMap();
Relocate(x, y, z);
+
for(PlayerSet::const_iterator itr = m_passengers.begin(); itr != m_passengers.end();)
{
Player *plr = *itr;
++itr;
+
if (plr->isDead() && !plr->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
{
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
+
ResetMap();
Map * newMap = MapManager::Instance().CreateMap(newMapid, this, 0);
SetMap(newMap);
assert (GetMap());
+
if(oldMap != newMap)
{
UpdateForMap(oldMap);
UpdateForMap(newMap);
}
}
+
bool Transport::AddPassenger(Player* passenger)
{
if(m_passengers.insert(passenger).second)
sLog.outDetail("Player %s boarded transport %s.", passenger->GetName(), GetName());
return true;
}
+
bool Transport::RemovePassenger(Player* passenger)
{
if (m_passengers.erase(passenger))
sLog.outDetail("Player %s removed from transport %s.", passenger->GetName(), GetName());
return true;
}
+
void Transport::CheckForEvent(uint32 entry, uint32 wp_id)
{
uint32 key = entry*100+wp_id;
if(objmgr.TransportEventMap.find(key) != objmgr.TransportEventMap.end())
GetMap()->ScriptsStart(sEventScripts, objmgr.TransportEventMap[key], this, NULL);
}
+
void Transport::Update(uint32 /*p_time*/)
{
if (m_WayPoints.size() <= 1)
return;
+
m_timer = getMSTime() % m_period;
while (((m_timer - m_curr->first) % m_pathTime) > ((m_next->first - m_curr->first) % m_pathTime))
{
m_curr = GetNextWayPoint();
m_next = GetNextWayPoint();
+
// first check help in case client-server transport coordinates de-synchronization
if (m_curr->second.mapid != GetMapId() || m_curr->second.teleport)
{
@@ -454,20 +543,26 @@ void Transport::Update(uint32 /*p_time*/)
//(*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;
+
if (m_curr == m_WayPoints.begin() && (sLog.getLogFilter() & LOG_FILTER_TRANSPORT_MOVES)==0)
sLog.outDetail(" ************ BEGIN ************** %s", this->m_name.c_str());
+
if ((sLog.getLogFilter() & LOG_FILTER_TRANSPORT_MOVES)==0)
sLog.outDetail("%s moved to %d %f %f %f %d", this->m_name.c_str(), m_curr->second.id, m_curr->second.x, m_curr->second.y, m_curr->second.z, m_curr->second.mapid);
+
//Transport Event System
CheckForEvent(this->GetEntry(), m_curr->second.id);
}
}
+
void Transport::UpdateForMap(Map const* targetMap)
{
Map::PlayerList const& pl = targetMap->GetPlayers();
if(pl.isEmpty())
return;
+
if(GetMapId()==targetMap->GetId())
{
for(Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr)
@@ -488,6 +583,7 @@ void Transport::UpdateForMap(Map const* targetMap)
BuildOutOfRangeUpdateBlock(&transData);
WorldPacket out_packet;
transData.BuildPacket(&out_packet);
+
for(Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr)
if(this != itr->getSource()->GetTransport())
itr->getSource()->SendDirectMessage(&out_packet);