diff options
-rw-r--r-- | src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp | 3 | ||||
-rw-r--r-- | src/server/game/Entities/Transport/Transport.cpp | 58 | ||||
-rw-r--r-- | src/server/game/Entities/Transport/Transport.h | 2 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 7 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.h | 2 | ||||
-rw-r--r-- | src/server/game/Maps/TransportMgr.cpp | 139 | ||||
-rw-r--r-- | src/server/game/Maps/TransportMgr.h | 3 | ||||
-rw-r--r-- | src/server/game/Movement/Spline/Spline.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Movement/Spline/Spline.h | 2 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_debug.cpp | 3 |
10 files changed, 123 insertions, 98 deletions
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp index 0b04d81bd5b..5ebef030518 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp @@ -397,6 +397,9 @@ bool BattlegroundIC::SetupBattleground() return false; } + gunshipHorde->EnableMovement(false); + gunshipAlliance->EnableMovement(false); + // setting correct factions for Keep Cannons for (uint8 i = BG_IC_NPC_KEEP_CANNON_1; i < BG_IC_NPC_KEEP_CANNON_12; ++i) GetBGCreature(i)->setFaction(BG_IC_Factions[0]); diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp index 860a84d5e83..04e388cc3ac 100644 --- a/src/server/game/Entities/Transport/Transport.cpp +++ b/src/server/game/Entities/Transport/Transport.cpp @@ -90,8 +90,7 @@ bool Transport::Create(uint32 guidlow, uint32 entry, uint32 mapid, float x, floa SetPeriod(tInfo->pathTime); SetEntry(goinfo->entry); SetDisplayId(goinfo->displayId); - SetGoState(GO_STATE_READY); - _pendingStop = goinfo->moTransport.canBeStopped != 0; + SetGoState(!goinfo->moTransport.canBeStopped ? GO_STATE_READY : GO_STATE_ACTIVE); SetGoType(GAMEOBJECT_TYPE_MO_TRANSPORT); SetGoAnimProgress(animprogress); SetName(goinfo->name); @@ -111,7 +110,8 @@ void Transport::Update(uint32 diff) if (GetKeyFrames().size() <= 1) return; - m_goValue.Transport.PathProgress += diff; + if (IsMoving() || !_pendingStop) + m_goValue.Transport.PathProgress += diff; uint32 timer = m_goValue.Transport.PathProgress % GetPeriod(); @@ -132,31 +132,23 @@ void Transport::Update(uint32 diff) if (timer < _currentFrame->DepartureTime) { SetMoving(false); - if (_pendingStop) + if (_pendingStop && GetGoState() != GO_STATE_READY) + { SetGoState(GO_STATE_READY); + m_goValue.Transport.PathProgress = (m_goValue.Transport.PathProgress / GetPeriod()); + m_goValue.Transport.PathProgress *= GetPeriod(); + m_goValue.Transport.PathProgress += _currentFrame->ArriveTime; + } break; // its a stop frame and we are waiting } } - if (_pendingStop && timer >= _currentFrame->DepartureTime && GetGoState() == GO_STATE_READY) - { - m_goValue.Transport.PathProgress = (m_goValue.Transport.PathProgress / GetPeriod()); - m_goValue.Transport.PathProgress *= GetPeriod(); - m_goValue.Transport.PathProgress += _currentFrame->ArriveTime; - break; - } - if (timer >= _currentFrame->DepartureTime && !_triggeredDepartureEvent) { DoEventIfAny(*_currentFrame, true); // departure event _triggeredDepartureEvent = true; } - if (timer >= _currentFrame->DepartureTime && timer < _currentFrame->NextArriveTime) - break; // found current waypoint - - MoveToNextWaypoint(); - // not waiting anymore SetMoving(true); @@ -164,13 +156,18 @@ void Transport::Update(uint32 diff) if (GetGOInfo()->moTransport.canBeStopped) SetGoState(GO_STATE_ACTIVE); + if (timer >= _currentFrame->DepartureTime && timer < _currentFrame->NextArriveTime) + break; // found current waypoint + + MoveToNextWaypoint(); + sScriptMgr->OnRelocate(this, _currentFrame->Node->index, _currentFrame->Node->mapid, _currentFrame->Node->x, _currentFrame->Node->y, _currentFrame->Node->z); TC_LOG_DEBUG("entities.transport", "Transport %u (%s) moved to node %u %u %f %f %f", GetEntry(), GetName().c_str(), _currentFrame->Node->index, _currentFrame->Node->mapid, _currentFrame->Node->x, _currentFrame->Node->y, _currentFrame->Node->z); // Departure event if (_currentFrame->IsTeleportFrame()) - if (TeleportTransport(_nextFrame->Node->mapid, _nextFrame->Node->x, _nextFrame->Node->y, _nextFrame->Node->z)) + if (TeleportTransport(_nextFrame->Node->mapid, _nextFrame->Node->x, _nextFrame->Node->y, _nextFrame->Node->z, _nextFrame->InitialOrientation)) return; // Update more in new map thread } @@ -185,7 +182,18 @@ void Transport::Update(uint32 diff) G3D::Vector3 pos, dir; _currentFrame->Spline->evaluate_percent(_currentFrame->Index, t, pos); _currentFrame->Spline->evaluate_derivative(_currentFrame->Index, t, dir); - UpdatePosition(pos.x, pos.y, pos.z, atan2(dir.x, dir.y)); + UpdatePosition(pos.x, pos.y, pos.z, atan2(dir.y, dir.x) + M_PI); + } + else + { + /* There are four possible scenarios that trigger loading/unloading passengers: + 1. transport moves from inactive to active grid + 2. the grid that transport is currently in becomes active + 3. transport moves from active to inactive grid + 4. the grid that transport is currently in unloads + */ + if (_staticPassengers.empty() && GetMap()->IsGridLoaded(GetPositionX(), GetPositionY())) // 2. + LoadStaticPassengers(); } } @@ -314,7 +322,7 @@ void Transport::UpdatePosition(float x, float y, float z, float o) 3. transport moves from active to inactive grid 4. the grid that transport is currently in unloads */ - if (_staticPassengers.empty() && newActive) // 1. and 2. + if (_staticPassengers.empty() && newActive) // 1. LoadStaticPassengers(); else if (!_staticPassengers.empty() && !newActive && Cell(x, y).DiffGrid(Cell(GetPositionX(), GetPositionY()))) // 3. UnloadStaticPassengers(); @@ -404,7 +412,7 @@ float Transport::CalculateSegmentPos(float now) return segmentPos / frame.NextDistFromPrev; } -bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z) +bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z, float o) { Map const* oldMap = GetMap(); @@ -421,7 +429,7 @@ bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z) float destX, destY, destZ, destO; obj->m_movementInfo.transport.pos.GetPosition(destX, destY, destZ, destO); - TransportBase::CalculatePassengerPosition(destX, destY, destZ, &destO, x, y, z, GetOrientation()); + TransportBase::CalculatePassengerPosition(destX, destY, destZ, &destO, x, y, z, o); switch (obj->GetTypeId()) { @@ -447,7 +455,7 @@ bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z) } } - Relocate(x, y, z, GetOrientation()); + Relocate(x, y, z, o); GetMap()->AddToMap<Transport>(this); return true; } @@ -460,13 +468,13 @@ bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z) { float destX, destY, destZ, destO; (*itr)->m_movementInfo.transport.pos.GetPosition(destX, destY, destZ, destO); - TransportBase::CalculatePassengerPosition(destX, destY, destZ, &destO, x, y, z, GetOrientation()); + TransportBase::CalculatePassengerPosition(destX, destY, destZ, &destO, x, y, z, o); (*itr)->ToUnit()->NearTeleportTo(destX, destY, destZ, destO); } } - UpdatePosition(x, y, z, GetOrientation()); + UpdatePosition(x, y, z, o); return false; } } diff --git a/src/server/game/Entities/Transport/Transport.h b/src/server/game/Entities/Transport/Transport.h index e290a5d5e00..b0e80ea27b3 100644 --- a/src/server/game/Entities/Transport/Transport.h +++ b/src/server/game/Entities/Transport/Transport.h @@ -78,7 +78,7 @@ class Transport : public GameObject, public TransportBase private: void MoveToNextWaypoint(); float CalculateSegmentPos(float perc); - bool TeleportTransport(uint32 newMapid, float x, float y, float z); + bool TeleportTransport(uint32 newMapid, float x, float y, float z, float o); void UpdatePassengerPositions(std::set<WorldObject*>& passengers); void DoEventIfAny(KeyFrame const& node, bool departure); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index e4d20cbc391..38549a358a0 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -1601,7 +1601,8 @@ void ObjectMgr::LoadCreatures() continue; } - if (data.spawnMask & ~spawnMasks[data.mapid]) + // Skip spawnMask check for transport maps + if (!_transportMaps.count(data.mapid) && data.spawnMask & ~spawnMasks[data.mapid]) TC_LOG_ERROR("sql.sql", "Table `creature` have creature (GUID: %u) that have wrong spawn mask %u including not supported difficulty modes for map (Id: %u).", guid, data.spawnMask, data.mapid); bool ok = true; @@ -1936,7 +1937,7 @@ void ObjectMgr::LoadGameobjects() data.spawnMask = fields[14].GetUInt8(); - if (data.spawnMask & ~spawnMasks[data.mapid]) + if (!_transportMaps.count(data.mapid) && data.spawnMask & ~spawnMasks[data.mapid]) TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: %u Entry: %u) that has wrong spawn mask %u including not supported difficulty modes for map (Id: %u), skip", guid, data.id, data.spawnMask, data.mapid); data.phaseMask = fields[15].GetUInt32(); @@ -6480,6 +6481,8 @@ void ObjectMgr::LoadGameObjectTemplate() TC_LOG_ERROR("sql.sql", "GameObject (Entry: %u GoType: %u) have data0=%u but TaxiPath (Id: %u) not exist.", entry, got.type, got.moTransport.taxiPathId, got.moTransport.taxiPathId); } + if (uint32 transportMap = got.moTransport.mapID) + _transportMaps.insert(transportMap); break; } case GAMEOBJECT_TYPE_SUMMONING_RITUAL: //18 diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index bf835ed6c4e..a99140d4572 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -1384,6 +1384,8 @@ class ObjectMgr GO_TO_GO, GO_TO_CREATURE // GO is dependant on creature }; + + std::set<uint32> _transportMaps; // Helper container storing map ids that are for transports only, loaded from gameobject_template }; #define sObjectMgr ACE_Singleton<ObjectMgr, ACE_Null_Mutex>::instance() diff --git a/src/server/game/Maps/TransportMgr.cpp b/src/server/game/Maps/TransportMgr.cpp index 11798201397..8e768924eb8 100644 --- a/src/server/game/Maps/TransportMgr.cpp +++ b/src/server/game/Maps/TransportMgr.cpp @@ -87,28 +87,60 @@ void TransportMgr::LoadTransportTemplates() TC_LOG_INFO("server.loading", ">> Loaded %u transport templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } +class SplineRawInitializer +{ +public: + SplineRawInitializer(Movement::PointsArray& points) : _points(points) { } + + void operator()(uint8& mode, bool& cyclic, Movement::PointsArray& points, int& lo, int& hi) const + { + mode = Movement::SplineBase::ModeCatmullrom; + cyclic = false; + points.assign(_points.begin(), _points.end()); + lo = 1; + hi = points.size(); + } + + Movement::PointsArray& _points; +}; + void TransportMgr::GeneratePath(GameObjectTemplate const* goInfo, TransportTemplate* transport) { uint32 pathId = goInfo->moTransport.taxiPathId; TaxiPathNodeList const& path = sTaxiPathNodesByPath[pathId]; std::vector<KeyFrame>& keyFrames = transport->keyFrames; - Movement::PointsArray splinePath; + Movement::PointsArray splinePath, allPoints; bool mapChange = false; - bool cyclic = true; + for (size_t i = 0; i < path.size(); ++i) + allPoints.push_back(G3D::Vector3(path[i].x, path[i].y, path[i].z)); + + // Add extra points to allow derivative calculations for all path nodes + allPoints.insert(allPoints.begin(), allPoints.front().lerp(allPoints[1], -0.2f)); + allPoints.push_back(allPoints.back().lerp(allPoints[allPoints.size() - 2], -0.2f)); + allPoints.push_back(allPoints.back().lerp(allPoints[allPoints.size() - 2], -1.0f)); + + SplineRawInitializer initer(allPoints); + TransportSpline orientationSpline; + orientationSpline.init_spline_custom(initer); + orientationSpline.initLengths(); + for (size_t i = 0; i < path.size(); ++i) { if (!mapChange) { TaxiPathNodeEntry const& node_i = path[i]; - if (i != path.size() - 1 && (node_i.actionFlag == 1 || node_i.mapid != path[i + 1].mapid)) + if (i != path.size() - 1 && (node_i.actionFlag & 1 || node_i.mapid != path[i + 1].mapid)) { - cyclic = false; keyFrames.back().Teleport = true; mapChange = true; } else { KeyFrame k(node_i); + G3D::Vector3 h; + orientationSpline.evaluate_derivative(i + 1, 0.0f, h); + k.InitialOrientation = Position::NormalizeOrientation(atan2(h.y, h.x) + M_PI); + keyFrames.push_back(k); splinePath.push_back(G3D::Vector3(node_i.x, node_i.y, node_i.z)); transport->mapsUsed.insert(k.Node->mapid); @@ -118,16 +150,15 @@ void TransportMgr::GeneratePath(GameObjectTemplate const* goInfo, TransportTempl mapChange = false; } - // Not sure if data8 means the transport can be stopped or that its path in dbc does not contain extra spline points - if (!goInfo->moTransport.canBeStopped && splinePath.size() >= 2) + if (splinePath.size() >= 2) { // Remove special catmull-rom spline points - splinePath.erase(splinePath.begin()); - keyFrames.erase(keyFrames.begin()); - splinePath.pop_back(); - keyFrames.pop_back(); - // Cyclic spline has one more extra point - if (cyclic && !splinePath.empty()) + if (!keyFrames.front().IsStopFrame() && !keyFrames.front().Node->arrivalEventID && !keyFrames.front().Node->departureEventID) + { + splinePath.erase(splinePath.begin()); + keyFrames.erase(keyFrames.begin()); + } + if (!keyFrames.back().IsStopFrame() && !keyFrames.back().Node->arrivalEventID && !keyFrames.back().Node->departureEventID) { splinePath.pop_back(); keyFrames.pop_back(); @@ -170,67 +201,41 @@ void TransportMgr::GeneratePath(GameObjectTemplate const* goInfo, TransportTempl // find the rest of the distances between key points // Every path segment has its own spline - if (cyclic) - { - TransportSpline* spline = new TransportSpline(); - spline->init_cyclic_spline(&splinePath[0], splinePath.size(), Movement::SplineBase::ModeCatmullrom, 0); - spline->initLengths(); - keyFrames[0].DistFromPrev = spline->length(spline->last() - 2, spline->last() - 1); - keyFrames[0].Spline = spline; - for (size_t i = 0; i < keyFrames.size(); ++i) - { - keyFrames[i].Index = i + 1; - keyFrames[i].DistFromPrev = spline->length(i, i + 1); - if (i > 0) - keyFrames[i - 1].NextDistFromPrev = keyFrames[i].DistFromPrev; - keyFrames[i].Spline = spline; - if (keyFrames[i].IsStopFrame()) - { - // remember first stop frame - if (firstStop == -1) - firstStop = i; - lastStop = i; - } - } - } - else + size_t start = 0; + for (size_t i = 1; i < keyFrames.size(); ++i) { - size_t start = 0; - for (size_t i = 1; i < keyFrames.size(); ++i) + if (keyFrames[i - 1].Teleport || i + 1 == keyFrames.size()) { - if (keyFrames[i - 1].Teleport || i + 1 == keyFrames.size()) + size_t extra = !keyFrames[i - 1].Teleport ? 1 : 0; + TransportSpline* spline = new TransportSpline(); + spline->init_spline(&splinePath[start], i - start + extra, Movement::SplineBase::ModeCatmullrom); + spline->initLengths(); + for (size_t j = start; j < i + extra; ++j) { - size_t extra = !keyFrames[i - 1].Teleport ? 1 : 0; - TransportSpline* spline = new TransportSpline(); - spline->init_spline(&splinePath[start], i - start + extra, Movement::SplineBase::ModeCatmullrom); - spline->initLengths(); - for (size_t j = start; j < i + extra; ++j) - { - keyFrames[j].Index = j - start + 1; - keyFrames[j].DistFromPrev = spline->length(j - start, j + 1 - start); - if (j > 0) - keyFrames[j - 1].NextDistFromPrev = keyFrames[j].DistFromPrev; - keyFrames[j].Spline = spline; - } - - if (keyFrames[i - 1].Teleport) - { - keyFrames[i].Index = i - start + 1; - keyFrames[i].DistFromPrev = 0.0f; - keyFrames[i - 1].NextDistFromPrev = 0.0f; - keyFrames[i].Spline = spline; - } - - start = i; + keyFrames[j].Index = j - start + 1; + keyFrames[j].DistFromPrev = spline->length(j - start, j + 1 - start); + if (j > 0) + keyFrames[j - 1].NextDistFromPrev = keyFrames[j].DistFromPrev; + keyFrames[j].Spline = spline; } - if (keyFrames[i].IsStopFrame()) + if (keyFrames[i - 1].Teleport) { - // remember first stop frame - if (firstStop == -1) - firstStop = i; - lastStop = i; + keyFrames[i].Index = i - start + 1; + keyFrames[i].DistFromPrev = 0.0f; + keyFrames[i - 1].NextDistFromPrev = 0.0f; + keyFrames[i].Spline = spline; } + + start = i; + } + + if (keyFrames[i].IsStopFrame()) + { + // remember first stop frame + if (firstStop == -1) + firstStop = i; + lastStop = i; } } @@ -373,7 +378,7 @@ Transport* TransportMgr::CreateTransport(uint32 entry, uint32 guid /*= 0*/, Map* float x = startNode->x; float y = startNode->y; float z = startNode->z; - float o = 0.0f; + float o = tInfo->keyFrames.begin()->InitialOrientation; // initialize the gameobject base uint32 guidLow = guid ? guid : sObjectMgr->GenerateLowGuid(HIGHGUID_MO_TRANSPORT); diff --git a/src/server/game/Maps/TransportMgr.h b/src/server/game/Maps/TransportMgr.h index 205a614eabb..c2f82069b30 100644 --- a/src/server/game/Maps/TransportMgr.h +++ b/src/server/game/Maps/TransportMgr.h @@ -38,7 +38,7 @@ typedef UNORDERED_MAP<uint32, std::set<uint32> > TransportInstanceMap; struct KeyFrame { - explicit KeyFrame(TaxiPathNodeEntry const& _node) : Index(0), Node(&_node), + explicit KeyFrame(TaxiPathNodeEntry const& _node) : Index(0), Node(&_node), InitialOrientation(0.0f), DistSinceStop(-1.0f), DistUntilStop(-1.0f), DistFromPrev(-1.0f), TimeFrom(0.0f), TimeTo(0.0f), Teleport(false), ArriveTime(0), DepartureTime(0), Spline(NULL), NextDistFromPrev(0.0f), NextArriveTime(0) { @@ -46,6 +46,7 @@ struct KeyFrame uint32 Index; TaxiPathNodeEntry const* Node; + float InitialOrientation; float DistSinceStop; float DistUntilStop; float DistFromPrev; diff --git a/src/server/game/Movement/Spline/Spline.cpp b/src/server/game/Movement/Spline/Spline.cpp index 887541e2289..6424afc5d6e 100644 --- a/src/server/game/Movement/Spline/Spline.cpp +++ b/src/server/game/Movement/Spline/Spline.cpp @@ -156,7 +156,7 @@ float SplineBase::SegLengthLinear(index_type index) const return (points[index] - points[index+1]).length(); } -float SplineBase::SegLengthCatmullRom( index_type index ) const +float SplineBase::SegLengthCatmullRom(index_type index) const { ASSERT(index >= index_lo && index < index_hi); diff --git a/src/server/game/Movement/Spline/Spline.h b/src/server/game/Movement/Spline/Spline.h index dab31e957f1..1444b2872d1 100644 --- a/src/server/game/Movement/Spline/Spline.h +++ b/src/server/game/Movement/Spline/Spline.h @@ -118,7 +118,7 @@ public: /** As i can see there are a lot of ways how spline can be initialized would be no harm to have some custom initializers. */ - template<class Init> inline void init_spline(Init& initializer) + template<class Init> inline void init_spline_custom(Init& initializer) { initializer(m_mode, cyclic, points, index_lo, index_hi); } diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index d3e6f3e8430..433e8e5a66b 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -1382,7 +1382,10 @@ public: } else { + Position pos; + transport->GetPosition(&pos); handler->PSendSysMessage("Transport %s is %s", transport->GetName().c_str(), transport->GetGoState() == GO_STATE_READY ? "stopped" : "moving"); + handler->PSendSysMessage("Transport position: %s", pos.ToString().c_str()); return true; } |