Guest User

Transport.cpp

a guest
Mar 16th, 2013
225
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 25.56 KB | None | 0 0
  1. /*
  2.  * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
  3.  * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify it
  6.  * under the terms of the GNU General Public License as published by the
  7.  * Free Software Foundation; either version 2 of the License, or (at your
  8.  * option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful, but WITHOUT
  11.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12.  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13.  * more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License along
  16.  * with this program. If not, see <http://www.gnu.org/licenses/>.
  17.  */
  18.  
  19. #include "Common.h"
  20. #include "Transport.h"
  21. #include "MapManager.h"
  22. #include "ObjectMgr.h"
  23. #include "Path.h"
  24. #include "ScriptMgr.h"
  25. #include "WorldPacket.h"
  26. #include "DBCStores.h"
  27. #include "World.h"
  28. #include "GameObjectAI.h"
  29. #include "Player.h"
  30.  
  31. void MapManager::LoadTransports()
  32. {
  33.     uint32 oldMSTime = getMSTime();
  34.  
  35.     QueryResult result = WorldDatabase.Query("SELECT guid, entry, name, period, ScriptName FROM transports");
  36.  
  37.     if (!result)
  38.     {
  39.         sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 transports. DB table `transports` is empty!");
  40.         return;
  41.     }
  42.  
  43.     uint32 count = 0;
  44.  
  45.     do
  46.     {
  47.  
  48.         Field* fields = result->Fetch();
  49.         uint32 lowguid = fields[0].GetUInt32();
  50.         uint32 entry = fields[1].GetUInt32();
  51.         std::string name = fields[2].GetString();
  52.         uint32 period = fields[3].GetUInt32();
  53.         uint32 scriptId = sObjectMgr->GetScriptId(fields[4].GetCString());
  54.  
  55.         GameObjectTemplate const* goinfo = sObjectMgr->GetGameObjectTemplate(entry);
  56.  
  57.         if (!goinfo)
  58.         {
  59.             sLog->outError(LOG_FILTER_SQL, "Transport ID:%u, Name: %s, will not be loaded, gameobject_template missing", entry, name.c_str());
  60.             continue;
  61.         }
  62.  
  63.         if (goinfo->type != GAMEOBJECT_TYPE_MO_TRANSPORT)
  64.         {
  65.             sLog->outError(LOG_FILTER_SQL, "Transport ID:%u, Name: %s, will not be loaded, gameobject_template type wrong", entry, name.c_str());
  66.             continue;
  67.         }
  68.  
  69.         // sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading transport %d between %s, %s", entry, name.c_str(), goinfo->name);
  70.  
  71.         std::set<uint32> mapsUsed;
  72.  
  73.         Transport* t = new Transport(period, scriptId);
  74.         if (!t->GenerateWaypoints(goinfo->moTransport.taxiPathId, mapsUsed))
  75.             // skip transports with empty waypoints list
  76.         {
  77.             sLog->outError(LOG_FILTER_SQL, "Transport (path id %u) path size = 0. Transport ignored, check DBC files or transport GO data0 field.", goinfo->moTransport.taxiPathId);
  78.             delete t;
  79.             continue;
  80.         }
  81.  
  82.         float x = t->m_WayPoints[0].x;
  83.         float y = t->m_WayPoints[0].y;
  84.         float z = t->m_WayPoints[0].z;
  85.         uint32 mapid = t->m_WayPoints[0].mapid;
  86.         float o = 1.0f;
  87.  
  88.          // creates the Gameobject
  89.         if (!t->Create(lowguid, entry, mapid, x, y, z, o, 255, 0))
  90.         {
  91.             delete t;
  92.             continue;
  93.         }
  94.  
  95.         m_Transports.insert(t);
  96.  
  97.         for (std::set<uint32>::const_iterator i = mapsUsed.begin(); i != mapsUsed.end(); ++i)
  98.             m_TransportsByMap[*i].insert(t);
  99.  
  100.         //If we someday decide to use the grid to track transports, here:
  101.         t->SetMap(sMapMgr->CreateBaseMap(mapid));
  102.         t->AddToWorld();
  103.  
  104.         ++count;
  105.     }
  106.     while (result->NextRow());
  107.  
  108.     // check transport data DB integrity
  109.     result = WorldDatabase.Query("SELECT gameobject.guid, gameobject.id, transports.name FROM gameobject, transports WHERE gameobject.id = transports.entry");
  110.     if (result)                                              // wrong data found
  111.     {
  112.         do
  113.         {
  114.             Field* fields = result->Fetch();
  115.  
  116.             uint32 guid  = fields[0].GetUInt32();
  117.             uint32 entry = fields[1].GetUInt32();
  118.             std::string name = fields[2].GetString();
  119.             sLog->outError(LOG_FILTER_SQL, "Transport %u '%s' have record (GUID: %u) in `gameobject`. Transports must not have any records in `gameobject` or its behavior will be unpredictable/bugged.", entry, name.c_str(), guid);
  120.         }
  121.         while (result->NextRow());
  122.     }
  123.  
  124.     sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u transports in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
  125. }
  126.  
  127. void MapManager::LoadTransportNPCs()
  128. {
  129.     uint32 oldMSTime = getMSTime();
  130.  
  131.     //                                                 0       1            2                3             4             5             6        7
  132.     QueryResult result = WorldDatabase.Query("SELECT guid, npc_entry, transport_entry, TransOffsetX, TransOffsetY, TransOffsetZ, TransOffsetO, emote FROM creature_transport");
  133.  
  134.     if (!result)
  135.     {
  136.         sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded 0 transport NPCs. DB table `creature_transport` is empty!");
  137.         return;
  138.     }
  139.  
  140.     uint32 count = 0;
  141.  
  142.     do
  143.     {
  144.         Field* fields = result->Fetch();
  145.         uint32 guid = fields[0].GetInt32();
  146.         uint32 entry = fields[1].GetInt32();
  147.         uint32 transportEntry = fields[2].GetInt32();
  148.         float tX = fields[3].GetFloat();
  149.         float tY = fields[4].GetFloat();
  150.         float tZ = fields[5].GetFloat();
  151.         float tO = fields[6].GetFloat();
  152.         uint32 anim = fields[7].GetInt32();
  153.  
  154.         for (MapManager::TransportSet::iterator itr = m_Transports.begin(); itr != m_Transports.end(); ++itr)
  155.         {
  156.             if ((*itr)->GetEntry() == transportEntry)
  157.             {
  158.                 (*itr)->AddNPCPassenger(guid, entry, tX, tY, tZ, tO, anim);
  159.                 break;
  160.             }
  161.         }
  162.  
  163.         ++count;
  164.     }
  165.     while (result->NextRow());
  166.  
  167.     sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u transport npcs in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
  168. }
  169.  
  170. Transport::Transport(uint32 period, uint32 script) : GameObject(), m_pathTime(0), m_timer(0),
  171. currenttguid(0), m_period(period), ScriptId(script), m_nextNodeTime(0)
  172. {
  173.     m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_LOWGUID | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_ROTATION);
  174. }
  175.  
  176. Transport::~Transport()
  177. {
  178.     for (CreatureSet::iterator itr = m_NPCPassengerSet.begin(); itr != m_NPCPassengerSet.end(); ++itr)
  179.     {
  180.         (*itr)->SetTransport(NULL);
  181.         GetMap()->AddObjectToRemoveList(*itr);
  182.     }
  183.  
  184.     m_NPCPassengerSet.clear();
  185.  
  186.     m_WayPoints.clear();
  187.     m_passengers.clear();
  188. }
  189.  
  190. bool Transport::Create(uint32 guidlow, uint32 entry, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress, uint32 dynflags)
  191. {
  192.     Relocate(x, y, z, ang);
  193.     // instance id and phaseMask isn't set to values different from std.
  194.  
  195.     if (!IsPositionValid())
  196.     {
  197.         sLog->outError(LOG_FILTER_TRANSPORTS, "Transport (GUID: %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)",
  198.             guidlow, x, y);
  199.         return false;
  200.     }
  201.  
  202.     Object::_Create(guidlow, 0, HIGHGUID_MO_TRANSPORT);
  203.  
  204.     GameObjectTemplate const* goinfo = sObjectMgr->GetGameObjectTemplate(entry);
  205.  
  206.     if (!goinfo)
  207.     {
  208.         sLog->outError(LOG_FILTER_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);
  209.         return false;
  210.     }
  211.  
  212.     m_goInfo = goinfo;
  213.  
  214.     SetObjectScale(goinfo->size);
  215.  
  216.     SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction);
  217.     SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags);
  218.     SetUInt32Value(GAMEOBJECT_LEVEL, m_period);
  219.     SetEntry(goinfo->entry);
  220.  
  221.     SetDisplayId(goinfo->displayId);
  222.  
  223.     SetGoState(GO_STATE_READY);
  224.     SetGoType(GameobjectTypes(goinfo->type));
  225.  
  226.     SetGoAnimProgress(animprogress);
  227.     if (dynflags)
  228.         SetUInt32Value(GAMEOBJECT_DYNAMIC, MAKE_PAIR32(0, dynflags));
  229.  
  230.     SetName(goinfo->name);
  231.  
  232.     SetZoneScript();
  233.  
  234.     return true;
  235. }
  236.  
  237. struct keyFrame
  238. {
  239.     explicit keyFrame(TaxiPathNodeEntry const& _node) : node(&_node),
  240.         distSinceStop(-1.0f), distUntilStop(-1.0f), distFromPrev(-1.0f), tFrom(0.0f), tTo(0.0f)
  241.         {
  242.         }
  243.  
  244.     TaxiPathNodeEntry const* node;
  245.  
  246.     float distSinceStop;
  247.     float distUntilStop;
  248.     float distFromPrev;
  249.     float tFrom, tTo;
  250. };
  251.  
  252. bool Transport::GenerateWaypoints(uint32 pathid, std::set<uint32> &mapids)
  253. {
  254.     if (pathid >= sTaxiPathNodesByPath.size())
  255.         return false;
  256.  
  257.     TaxiPathNodeList const& path = sTaxiPathNodesByPath[pathid];
  258.  
  259.     std::vector<keyFrame> keyFrames;
  260.     int mapChange = 0;
  261.     mapids.clear();
  262.     for (size_t i = 1; i < path.size() - 1; ++i)
  263.     {
  264.         if (mapChange == 0)
  265.         {
  266.             TaxiPathNodeEntry const& node_i = path[i];
  267.             if (node_i.mapid == path[i+1].mapid)
  268.             {
  269.                 keyFrame k(node_i);
  270.                 keyFrames.push_back(k);
  271.                 mapids.insert(k.node->mapid);
  272.             }
  273.             else
  274.             {
  275.                 mapChange = 1;
  276.             }
  277.         }
  278.         else
  279.         {
  280.             --mapChange;
  281.         }
  282.     }
  283.  
  284.     int lastStop = -1;
  285.     int firstStop = -1;
  286.  
  287.     // first cell is arrived at by teleportation :S
  288.     keyFrames[0].distFromPrev = 0;
  289.     if (keyFrames[0].node->actionFlag == 2)
  290.     {
  291.         lastStop = 0;
  292.     }
  293.  
  294.     // find the rest of the distances between key points
  295.     for (size_t i = 1; i < keyFrames.size(); ++i)
  296.     {
  297.         if ((keyFrames[i].node->actionFlag == 1) || (keyFrames[i].node->mapid != keyFrames[i-1].node->mapid))
  298.         {
  299.             keyFrames[i].distFromPrev = 0;
  300.         }
  301.         else
  302.         {
  303.             keyFrames[i].distFromPrev =
  304.                 sqrt(pow(keyFrames[i].node->x - keyFrames[i - 1].node->x, 2) +
  305.                     pow(keyFrames[i].node->y - keyFrames[i - 1].node->y, 2) +
  306.                     pow(keyFrames[i].node->z - keyFrames[i - 1].node->z, 2));
  307.         }
  308.         if (keyFrames[i].node->actionFlag == 2)
  309.         {
  310.             // remember first stop frame
  311.             if (firstStop == -1)
  312.                 firstStop = i;
  313.             lastStop = i;
  314.         }
  315.     }
  316.  
  317.     float tmpDist = 0;
  318.     for (size_t i = 0; i < keyFrames.size(); ++i)
  319.     {
  320.         int j = (i + lastStop) % keyFrames.size();
  321.         if (keyFrames[j].node->actionFlag == 2)
  322.             tmpDist = 0;
  323.         else
  324.             tmpDist += keyFrames[j].distFromPrev;
  325.         keyFrames[j].distSinceStop = tmpDist;
  326.     }
  327.  
  328.     for (int i = int(keyFrames.size()) - 1; i >= 0; i--)
  329.     {
  330.         int j = (i + (firstStop+1)) % keyFrames.size();
  331.         tmpDist += keyFrames[(j + 1) % keyFrames.size()].distFromPrev;
  332.         keyFrames[j].distUntilStop = tmpDist;
  333.         if (keyFrames[j].node->actionFlag == 2)
  334.             tmpDist = 0;
  335.     }
  336.  
  337.     for (size_t i = 0; i < keyFrames.size(); ++i)
  338.     {
  339.         if (keyFrames[i].distSinceStop < (30 * 30 * 0.5f))
  340.             keyFrames[i].tFrom = sqrt(2 * keyFrames[i].distSinceStop);
  341.         else
  342.             keyFrames[i].tFrom = ((keyFrames[i].distSinceStop - (30 * 30 * 0.5f)) / 30) + 30;
  343.  
  344.         if (keyFrames[i].distUntilStop < (30 * 30 * 0.5f))
  345.             keyFrames[i].tTo = sqrt(2 * keyFrames[i].distUntilStop);
  346.         else
  347.             keyFrames[i].tTo = ((keyFrames[i].distUntilStop - (30 * 30 * 0.5f)) / 30) + 30;
  348.  
  349.         keyFrames[i].tFrom *= 1000;
  350.         keyFrames[i].tTo *= 1000;
  351.     }
  352.  
  353.     //    for (int i = 0; i < keyFrames.size(); ++i) {
  354.     //        sLog->outInfo(LOG_FILTER_TRANSPORTS, "%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);
  355.     //    }
  356.  
  357.     // Now we're completely set up; we can move along the length of each waypoint at 100 ms intervals
  358.     // speed = max(30, t) (remember x = 0.5s^2, and when accelerating, a = 1 unit/s^2
  359.     int t = 0;
  360.     bool teleport = false;
  361.     if (keyFrames[keyFrames.size() - 1].node->mapid != keyFrames[0].node->mapid)
  362.         teleport = true;
  363.  
  364.     m_WayPoints[0] = WayPoint(keyFrames[0].node->mapid, keyFrames[0].node->x, keyFrames[0].node->y, keyFrames[0].node->z, teleport, 0,
  365.         keyFrames[0].node->arrivalEventID, keyFrames[0].node->departureEventID);
  366.  
  367.     t += keyFrames[0].node->delay * 1000;
  368.  
  369.     uint32 cM = keyFrames[0].node->mapid;
  370.     for (size_t i = 0; i < keyFrames.size() - 1; ++i)
  371.     {
  372.         float d = 0;
  373.         float tFrom = keyFrames[i].tFrom;
  374.         float tTo = keyFrames[i].tTo;
  375.  
  376.         // keep the generation of all these points; we use only a few now, but may need the others later
  377.         if (((d < keyFrames[i + 1].distFromPrev) && (tTo > 0)))
  378.         {
  379.             while ((d < keyFrames[i + 1].distFromPrev) && (tTo > 0))
  380.             {
  381.                 tFrom += 100;
  382.                 tTo -= 100;
  383.  
  384.                 if (d > 0)
  385.                 {
  386.                     float newX = keyFrames[i].node->x + (keyFrames[i + 1].node->x - keyFrames[i].node->x) * d / keyFrames[i + 1].distFromPrev;
  387.                     float newY = keyFrames[i].node->y + (keyFrames[i + 1].node->y - keyFrames[i].node->y) * d / keyFrames[i + 1].distFromPrev;
  388.                     float newZ = keyFrames[i].node->z + (keyFrames[i + 1].node->z - keyFrames[i].node->z) * d / keyFrames[i + 1].distFromPrev;
  389.  
  390.                     teleport = false;
  391.                     if (keyFrames[i].node->mapid != cM)
  392.                     {
  393.                         teleport = true;
  394.                         cM = keyFrames[i].node->mapid;
  395.                     }
  396.  
  397.                     //                    sLog->outInfo(LOG_FILTER_TRANSPORTS, "T: %d, D: %f, x: %f, y: %f, z: %f", t, d, newX, newY, newZ);
  398.                     if (teleport)
  399.                         m_WayPoints[t] = WayPoint(keyFrames[i].node->mapid, newX, newY, newZ, teleport, 0);
  400.                 }
  401.  
  402.                 if (tFrom < tTo)                            // caught in tFrom dock's "gravitational pull"
  403.                 {
  404.                     if (tFrom <= 30000)
  405.                     {
  406.                         d = 0.5f * (tFrom / 1000) * (tFrom / 1000);
  407.                     }
  408.                     else
  409.                     {
  410.                         d = 0.5f * 30 * 30 + 30 * ((tFrom - 30000) / 1000);
  411.                     }
  412.                     d = d - keyFrames[i].distSinceStop;
  413.                 }
  414.                 else
  415.                 {
  416.                     if (tTo <= 30000)
  417.                     {
  418.                         d = 0.5f * (tTo / 1000) * (tTo / 1000);
  419.                     }
  420.                     else
  421.                     {
  422.                         d = 0.5f * 30 * 30 + 30 * ((tTo - 30000) / 1000);
  423.                     }
  424.                     d = keyFrames[i].distUntilStop - d;
  425.                 }
  426.                 t += 100;
  427.             }
  428.             t -= 100;
  429.         }
  430.  
  431.         if (keyFrames[i + 1].tFrom > keyFrames[i + 1].tTo)
  432.             t += 100 - ((long)keyFrames[i + 1].tTo % 100);
  433.         else
  434.             t += (long)keyFrames[i + 1].tTo % 100;
  435.  
  436.         teleport = false;
  437.         if ((keyFrames[i + 1].node->actionFlag == 1) || (keyFrames[i + 1].node->mapid != keyFrames[i].node->mapid))
  438.         {
  439.             teleport = true;
  440.             cM = keyFrames[i + 1].node->mapid;
  441.         }
  442.  
  443.         m_WayPoints[t] = WayPoint(keyFrames[i + 1].node->mapid, keyFrames[i + 1].node->x, keyFrames[i + 1].node->y, keyFrames[i + 1].node->z, teleport,
  444.             0, keyFrames[i + 1].node->arrivalEventID, keyFrames[i + 1].node->departureEventID);
  445.         //        sLog->outInfo(LOG_FILTER_TRANSPORTS, "T: %d, x: %f, y: %f, z: %f, t:%d", t, pos.x, pos.y, pos.z, teleport);
  446.  
  447.         t += keyFrames[i + 1].node->delay * 1000;
  448.     }
  449.  
  450.     uint32 timer = t;
  451.  
  452.     //    sLog->outInfo(LOG_FILTER_TRANSPORTS, "    Generated %lu waypoints, total time %u.", (unsigned long)m_WayPoints.size(), timer);
  453.  
  454.     m_curr = m_WayPoints.begin();
  455.     m_next = GetNextWayPoint();
  456.     m_pathTime = timer;
  457.  
  458.     m_nextNodeTime = m_curr->first;
  459.  
  460.     return true;
  461. }
  462.  
  463. Transport::WayPointMap::const_iterator Transport::GetNextWayPoint()
  464. {
  465.     WayPointMap::const_iterator iter = m_curr;
  466.     ++iter;
  467.     if (iter == m_WayPoints.end())
  468.         iter = m_WayPoints.begin();
  469.     return iter;
  470. }
  471.  
  472. void Transport::TeleportTransport(uint32 newMapid, float x, float y, float z)
  473. {
  474.     Map const* oldMap = GetMap();
  475.     Relocate(x, y, z);
  476.  
  477.     for (PlayerSet::const_iterator itr = m_passengers.begin(); itr != m_passengers.end();)
  478.     {
  479.         Player* player = *itr;
  480.         ++itr;
  481.  
  482.         if (player->isDead() && !player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
  483.             player->ResurrectPlayer(1.0f);
  484.  
  485.         player->TeleportTo(newMapid, x, y, z, GetOrientation(), TELE_TO_NOT_LEAVE_TRANSPORT);
  486.     }
  487.  
  488.     //we need to create and save new Map object with 'newMapid' because if not done -> lead to invalid Map object reference...
  489.     //player far teleport would try to create same instance, but we need it NOW for transport...
  490.  
  491.     RemoveFromWorld();
  492.     ResetMap();
  493.     Map* newMap = sMapMgr->CreateBaseMap(newMapid);
  494.     SetMap(newMap);
  495.     ASSERT(GetMap());
  496.     AddToWorld();
  497.  
  498.     if (oldMap != newMap)
  499.     {
  500.         UpdateForMap(oldMap);
  501.         UpdateForMap(newMap);
  502.     }
  503.  
  504.     for (CreatureSet::iterator itr = m_NPCPassengerSet.begin(); itr != m_NPCPassengerSet.end(); ++itr)
  505.         (*itr)->FarTeleportTo(newMap, x, y, z, (*itr)->GetOrientation());
  506. }
  507.  
  508. bool Transport::AddPassenger(Player* passenger)
  509. {
  510.     if (m_passengers.insert(passenger).second)
  511.         sLog->outInfo(LOG_FILTER_TRANSPORTS, "Player %s boarded transport %s.", passenger->GetName().c_str(), GetName().c_str());
  512.  
  513.     sScriptMgr->OnAddPassenger(this, passenger);
  514.     return true;
  515. }
  516.  
  517. bool Transport::RemovePassenger(Player* passenger)
  518. {
  519.     if (m_passengers.erase(passenger))
  520.         sLog->outInfo(LOG_FILTER_TRANSPORTS, "Player %s removed from transport %s.", passenger->GetName().c_str(), GetName().c_str());
  521.  
  522.     sScriptMgr->OnRemovePassenger(this, passenger);
  523.     return true;
  524. }
  525.  
  526. void Transport::Update(uint32 p_diff)
  527. {
  528.     if (!AI())
  529.     {
  530.         if (!AIM_Initialize())
  531.             sLog->outError(LOG_FILTER_TRANSPORTS, "Could not initialize GameObjectAI for Transport");
  532.     } else
  533.         AI()->UpdateAI(p_diff);
  534.  
  535.     if (m_WayPoints.size() <= 1)
  536.         return;
  537.  
  538.     m_timer = getMSTime() % m_period;
  539.     while (((m_timer - m_curr->first) % m_pathTime) > ((m_next->first - m_curr->first) % m_pathTime))
  540.     {
  541.         DoEventIfAny(*m_curr, true);
  542.  
  543.         m_curr = GetNextWayPoint();
  544.         m_next = GetNextWayPoint();
  545.  
  546.         DoEventIfAny(*m_curr, false);
  547.  
  548.         // first check help in case client-server transport coordinates de-synchronization
  549.         if (m_curr->second.mapid != GetMapId() || m_curr->second.teleport)
  550.         {
  551.             TeleportTransport(m_curr->second.mapid, m_curr->second.x, m_curr->second.y, m_curr->second.z);
  552.         }
  553.         else
  554.         {
  555.             Relocate(m_curr->second.x, m_curr->second.y, m_curr->second.z, GetAngle(m_next->second.x, m_next->second.y) + float(M_PI));
  556.             UpdateNPCPositions(); // COME BACK MARKER
  557.         }
  558.  
  559.         sScriptMgr->OnRelocate(this, m_curr->first, m_curr->second.mapid, m_curr->second.x, m_curr->second.y, m_curr->second.z);
  560.  
  561.         m_nextNodeTime = m_curr->first;
  562.  
  563.         if (m_curr == m_WayPoints.begin())
  564.             sLog->outDebug(LOG_FILTER_TRANSPORTS, " ************ BEGIN ************** %s", m_name.c_str());
  565.  
  566.         sLog->outDebug(LOG_FILTER_TRANSPORTS, "%s moved to %d %f %f %f %d", m_name.c_str(), m_curr->second.id, m_curr->second.x, m_curr->second.y, m_curr->second.z, m_curr->second.mapid);
  567.     }
  568.  
  569.     sScriptMgr->OnTransportUpdate(this, p_diff);
  570. }
  571.  
  572. void Transport::UpdateForMap(Map const* targetMap)
  573. {
  574.     Map::PlayerList const& player = targetMap->GetPlayers();
  575.     if (player.isEmpty())
  576.         return;
  577.  
  578.     if (GetMapId() == targetMap->GetId())
  579.     {
  580.         for (Map::PlayerList::const_iterator itr = player.begin(); itr != player.end(); ++itr)
  581.         {
  582.             if (this != itr->getSource()->GetTransport())
  583.             {
  584.                 UpdateData transData;
  585.                 BuildCreateUpdateBlockForPlayer(&transData, itr->getSource());
  586.                 WorldPacket packet;
  587.                 transData.BuildPacket(&packet);
  588.                 itr->getSource()->SendDirectMessage(&packet);
  589.             }
  590.         }
  591.     }
  592.     else
  593.     {
  594.         UpdateData transData;
  595.         BuildOutOfRangeUpdateBlock(&transData);
  596.         WorldPacket out_packet;
  597.         transData.BuildPacket(&out_packet);
  598.  
  599.         for (Map::PlayerList::const_iterator itr = player.begin(); itr != player.end(); ++itr)
  600.             if (this != itr->getSource()->GetTransport())
  601.                 itr->getSource()->SendDirectMessage(&out_packet);
  602.     }
  603. }
  604.  
  605. void Transport::DoEventIfAny(WayPointMap::value_type const& node, bool departure)
  606. {
  607.     if (uint32 eventid = departure ? node.second.departureEventID : node.second.arrivalEventID)
  608.     {
  609.         sLog->outDebug(LOG_FILTER_MAPSCRIPTS, "Taxi %s event %u of node %u of %s path", departure ? "departure" : "arrival", eventid, node.first, GetName().c_str());
  610.         GetMap()->ScriptsStart(sEventScripts, eventid, this, this);
  611.         EventInform(eventid);
  612.     }
  613. }
  614.  
  615. void Transport::BuildStartMovePacket(Map const* targetMap)
  616. {
  617.     SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE);
  618.     SetGoState(GO_STATE_ACTIVE);
  619.     UpdateForMap(targetMap);
  620. }
  621.  
  622. void Transport::BuildStopMovePacket(Map const* targetMap)
  623. {
  624.     RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE);
  625.     SetGoState(GO_STATE_READY);
  626.     UpdateForMap(targetMap);
  627. }
  628.  
  629. uint32 Transport::AddNPCPassenger(uint32 tguid, uint32 entry, float x, float y, float z, float o, uint32 anim)
  630. {
  631.     Map* map = GetMap();
  632.     //make it world object so it will not be unloaded with grid
  633.     Creature* creature = new Creature(true);
  634.  
  635.     if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, GetPhaseMask(), entry, 0, GetGOInfo()->faction, 0, 0, 0, 0))
  636.     {
  637.         delete creature;
  638.         return 0;
  639.     }
  640.  
  641.     creature->SetTransport(this);
  642.     creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
  643.     creature->m_movementInfo.guid = GetGUID();
  644.     creature->m_movementInfo.t_pos.Relocate(x, y, z, o);
  645.  
  646.     if (anim)
  647.         creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, anim);
  648.  
  649.     creature->Relocate(
  650.         GetPositionX() + (x * std::cos(GetOrientation()) + y * std::sin(GetOrientation() + float(M_PI))),
  651.         GetPositionY() + (y * std::cos(GetOrientation()) + x * std::sin(GetOrientation())),
  652.         z + GetPositionZ(),
  653.         o + GetOrientation());
  654.  
  655.     creature->SetHomePosition(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetOrientation());
  656.     creature->SetTransportHomePosition(creature->m_movementInfo.t_pos);
  657.  
  658.     if (!creature->IsPositionValid())
  659.     {
  660.         sLog->outError(LOG_FILTER_TRANSPORTS, "Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)", creature->GetGUIDLow(), creature->GetEntry(), creature->GetPositionX(), creature->GetPositionY());
  661.         delete creature;
  662.         return 0;
  663.     }
  664.  
  665.     map->AddToMap(creature);
  666.     m_NPCPassengerSet.insert(creature);
  667.  
  668.     if (tguid == 0)
  669.     {
  670.         ++currenttguid;
  671.         tguid = currenttguid;
  672.     }
  673.     else
  674.         currenttguid = std::max(tguid, currenttguid);
  675.  
  676.     creature->SetGUIDTransport(tguid);
  677.     sScriptMgr->OnAddCreaturePassenger(this, creature);
  678.     return tguid;
  679. }
  680.  
  681. void Transport::UpdatePosition(MovementInfo* mi)
  682. {
  683.     float transport_o = mi->pos.GetOrientation() - mi->t_pos.GetOrientation();
  684.     float transport_x = mi->pos.m_positionX - (mi->t_pos.m_positionX * std::cos(transport_o) - mi->t_pos.m_positionY * std::sin(transport_o));
  685.     float transport_y = mi->pos.m_positionY - (mi->t_pos.m_positionY * std::cos(transport_o) + mi->t_pos.m_positionX * std::sin(transport_o));
  686.     float transport_z = mi->pos.m_positionZ - mi->t_pos.m_positionZ;
  687.  
  688.     Relocate(transport_x, transport_y, transport_z, transport_o);
  689.     UpdateNPCPositions();
  690. }
  691.  
  692. void Transport::UpdateNPCPositions()
  693. {
  694.     for (CreatureSet::iterator itr = m_NPCPassengerSet.begin(); itr != m_NPCPassengerSet.end(); ++itr)
  695.     {
  696.         Creature* npc = *itr;
  697.  
  698.         float x, y, z, o;
  699.         npc->m_movementInfo.t_pos.GetPosition(x, y, z, o);
  700.         CalculatePassengerPosition(x, y, z, o);
  701.         GetMap()->CreatureRelocation(npc, x, y, z, o, false);
  702.         npc->GetTransportHomePosition(x, y, z, o);
  703.         CalculatePassengerPosition(x, y, z, o);
  704.         npc->SetHomePosition(x, y, z, o);
  705.     }
  706. }
  707.  
  708. void Transport::CalculatePassengerPosition(float& x, float& y, float& z, float& o)
  709. {
  710.     float inx = x, iny = y, inz = z, ino = o;
  711.     o = GetOrientation() + ino;
  712.     x = GetPositionX() + inx * std::cos(GetOrientation()) - iny * std::sin(GetOrientation());
  713.     y = GetPositionY() + iny * std::cos(GetOrientation()) + inx * std::sin(GetOrientation());
  714.     z = GetPositionZ() + inz;
  715. }
  716.  
  717. void Transport::CalculatePassengerOffset(float& x, float& y, float& z, float& o)
  718. {
  719.     o -= GetOrientation();
  720.     z -= GetPositionZ();
  721.     y -= GetPositionY();    // y = searchedY * std::cos(o) + searchedX * std::sin(o)
  722.     x -= GetPositionX();    // x = searchedX * std::cos(o) + searchedY * std::sin(o + pi)
  723.     float inx = x, iny = y;
  724.     y = (iny - inx * tan(GetOrientation())) / (cos(GetOrientation()) + std::sin(GetOrientation()) * tan(GetOrientation()));
  725.     x = (inx + iny * tan(GetOrientation())) / (cos(GetOrientation()) + std::sin(GetOrientation()) * tan(GetOrientation()));
  726. }
Advertisement
Add Comment
Please, Sign In to add comment