diff options
Diffstat (limited to 'src/server/game/Movement')
4 files changed, 107 insertions, 143 deletions
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index b69322f5720..2bcb4aeb3b3 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -563,7 +563,8 @@ void MotionMaster::MoveTaxiFlight(uint32 path, uint32 pathnode) if (path < sTaxiPathNodesByPath.size()) { TC_LOG_DEBUG("misc", "%s taxi to (Path %u node %u)", _owner->GetName().c_str(), path, pathnode); - FlightPathMovementGenerator* mgen = new FlightPathMovementGenerator(sTaxiPathNodesByPath[path], pathnode); + FlightPathMovementGenerator* mgen = new FlightPathMovementGenerator(pathnode); + mgen->LoadPath(_owner->ToPlayer()); Mutate(mgen, MOTION_SLOT_CONTROLLED); } else diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp index f91fc1985d5..8c61c96dfdc 100755 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp @@ -245,17 +245,64 @@ bool WaypointMovementGenerator<Creature>::GetResetPos(Creature*, float& x, float uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const { - if (i_currentNode >= i_path->size()) - return i_path->size(); + if (i_currentNode >= i_path.size()) + return i_path.size(); - uint32 curMapId = (*i_path)[i_currentNode].MapID; - for (uint32 i = i_currentNode; i < i_path->size(); ++i) - { - if ((*i_path)[i].MapID != curMapId) + uint32 curMapId = i_path[i_currentNode]->MapID; + for (uint32 i = i_currentNode; i < i_path.size(); ++i) + if (i_path[i]->MapID != curMapId) return i; - } - return i_path->size(); + return i_path.size(); +} + +#define SKIP_SPLINE_POINT_DISTANCE_SQ (40.0f * 40.0f) + +bool IsNodeIncludedInShortenedPath(TaxiPathNodeEntry const* p1, TaxiPathNodeEntry const* p2) +{ + return p1->MapID != p2->MapID || std::pow(p1->LocX - p2->LocX, 2) + std::pow(p1->LocY - p2->LocY, 2) > SKIP_SPLINE_POINT_DISTANCE_SQ; +} + +void FlightPathMovementGenerator::LoadPath(Player* player) +{ + _pointsForPathSwitch.clear(); + std::deque<uint32> const& taxi = player->m_taxi.GetPath(); + for (uint32 src = 0, dst = 1; dst < taxi.size(); src = dst++) + { + uint32 path, cost; + sObjectMgr->GetTaxiPath(taxi[src], taxi[dst], path, cost); + if (path > sTaxiPathNodesByPath.size()) + return; + + TaxiPathNodeList const& nodes = sTaxiPathNodesByPath[path]; + if (!nodes.empty()) + { + TaxiPathNodeEntry const* start = nodes[0]; + TaxiPathNodeEntry const* end = nodes[nodes.size() - 1]; + bool passedPreviousSegmentProximityCheck = false; + for (uint32 i = 0; i < nodes.size(); ++i) + { + sMapMgr->CreateMap(nodes[i]->MapID, player)->SummonCreature(1, { nodes[i]->LocX, nodes[i]->LocY, nodes[i]->LocZ, 0.0f })->SetLevel(i ? i : 1); + + if (passedPreviousSegmentProximityCheck || !src || i_path.empty() || IsNodeIncludedInShortenedPath(i_path[i_path.size() - 1], nodes[i])) + { + if ((!src || (IsNodeIncludedInShortenedPath(start, nodes[i]) && i >= 2)) && + (dst == taxi.size() - 1 || (IsNodeIncludedInShortenedPath(end, nodes[i]) && i < nodes.size() - 1))) + { + passedPreviousSegmentProximityCheck = true; + i_path.push_back(nodes[i]); + } + } + else + { + i_path.pop_back(); + --_pointsForPathSwitch.back().PathIndex; + } + } + } + + _pointsForPathSwitch.push_back({ uint32(i_path.size() - 1), int32(cost) }); + } } void FlightPathMovementGenerator::DoInitialize(Player* player) @@ -296,7 +343,7 @@ void FlightPathMovementGenerator::DoReset(Player* player) uint32 end = GetPathAtMapEnd(); for (uint32 i = GetCurrentNode(); i != end; ++i) { - G3D::Vector3 vertice((*i_path)[i].LocX, (*i_path)[i].LocY, (*i_path)[i].LocZ); + G3D::Vector3 vertice(i_path[i]->LocX, i_path[i]->LocY, i_path[i]->LocZ); init.Path().push_back(vertice); } init.SetFirstPointId(GetCurrentNode()); @@ -313,9 +360,21 @@ bool FlightPathMovementGenerator::DoUpdate(Player* player, uint32 /*diff*/) bool departureEvent = true; do { - DoEventIfAny(player, (*i_path)[i_currentNode], departureEvent); + DoEventIfAny(player, i_path[i_currentNode], departureEvent); + while (!_pointsForPathSwitch.empty() && _pointsForPathSwitch.front().PathIndex <= i_currentNode) + { + _pointsForPathSwitch.pop_front(); + player->m_taxi.NextTaxiDestination(); + if (!_pointsForPathSwitch.empty()) + { + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, _pointsForPathSwitch.front().Cost); + player->ModifyMoney(-_pointsForPathSwitch.front().Cost); + } + } + if (pointId == i_currentNode) break; + if (i_currentNode == _preloadTargetNode) PreloadEndGrid(); i_currentNode += (uint32)departureEvent; @@ -324,18 +383,18 @@ bool FlightPathMovementGenerator::DoUpdate(Player* player, uint32 /*diff*/) while (true); } - return i_currentNode < (i_path->size()-1); + return i_currentNode < (i_path.size() - 1); } void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport() { - if (i_path->empty()) + if (i_path.empty() || i_currentNode >= i_path.size()) return; - uint32 map0 = (*i_path)[0].MapID; - for (size_t i = 1; i < i_path->size(); ++i) + uint32 map0 = i_path[i_currentNode]->MapID; + for (size_t i = i_currentNode + 1; i < i_path.size(); ++i) { - if ((*i_path)[i].MapID != map0) + if (i_path[i]->MapID != map0) { i_currentNode = i; return; @@ -343,19 +402,21 @@ void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport() } } -void FlightPathMovementGenerator::DoEventIfAny(Player* player, TaxiPathNodeEntry const& node, bool departure) +void FlightPathMovementGenerator::DoEventIfAny(Player* player, TaxiPathNodeEntry const* node, bool departure) { - if (uint32 eventid = departure ? node.DepartureEventID : node.ArrivalEventID) + if (uint32 eventid = departure ? node->DepartureEventID : node->ArrivalEventID) { - TC_LOG_DEBUG("maps.script", "Taxi %s event %u of node %u of path %u for player %s", departure ? "departure" : "arrival", eventid, node.NodeIndex, node.PathID, player->GetName().c_str()); + TC_LOG_DEBUG("maps.script", "Taxi %s event %u of node %u of path %u for player %s", departure ? "departure" : "arrival", eventid, node->NodeIndex, node->PathID, player->GetName().c_str()); player->GetMap()->ScriptsStart(sEventScripts, eventid, player, player); } } bool FlightPathMovementGenerator::GetResetPos(Player*, float& x, float& y, float& z) { - const TaxiPathNodeEntry& node = (*i_path)[i_currentNode]; - x = node.LocX; y = node.LocY; z = node.LocZ; + TaxiPathNodeEntry const* node = i_path[i_currentNode]; + x = node->LocX; + y = node->LocY; + z = node->LocZ; return true; } @@ -363,11 +424,11 @@ void FlightPathMovementGenerator::InitEndGridInfo() { /*! Storage to preload flightmaster grid at end of flight. For multi-stop flights, this will be reinitialized for each flightmaster at the end of each spline (or stop) in the flight. */ - uint32 nodeCount = (*i_path).size(); //! Number of nodes in path. - _endMapId = (*i_path)[nodeCount - 1].MapID; //! MapId of last node + uint32 nodeCount = i_path.size(); //! Number of nodes in path. + _endMapId = i_path[nodeCount - 1]->MapID; //! MapId of last node _preloadTargetNode = nodeCount - 3; - _endGridX = (*i_path)[nodeCount - 1].LocX; - _endGridY = (*i_path)[nodeCount - 1].LocY; + _endGridX = i_path[nodeCount - 1]->LocX; + _endGridY = i_path[nodeCount - 1]->LocY; } void FlightPathMovementGenerator::PreloadEndGrid() @@ -378,7 +439,7 @@ void FlightPathMovementGenerator::PreloadEndGrid() // Load the grid if (endMap) { - TC_LOG_DEBUG("misc", "Preloading rid (%f, %f) for map %u at node index %u/%u", _endGridX, _endGridY, _endMapId, _preloadTargetNode, (uint32)(i_path->size()-1)); + TC_LOG_DEBUG("misc", "Preloading rid (%f, %f) for map %u at node index %u/%u", _endGridX, _endGridY, _endMapId, _preloadTargetNode, (uint32)(i_path.size() - 1)); endMap->LoadGrid(_endGridX, _endGridY); } else diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h index eb8533159a9..6cddd68ec1c 100755 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h @@ -27,13 +27,8 @@ #include "MovementGenerator.h" #include "WaypointManager.h" -#include "Path.h" - #include "Player.h" -#include <vector> -#include <set> - #define FLIGHT_TRAVEL_UPDATE 100 #define STOP_TIME_FOR_PLAYER 3 * MINUTE * IN_MILLISECONDS // 3 Minutes #define TIMEDIFF_NEXT_WP 250 @@ -45,8 +40,6 @@ class PathMovementBase PathMovementBase() : i_path(NULL), i_currentNode(0) { } virtual ~PathMovementBase() { }; - // template pattern, not defined .. override required - void LoadPath(T &); uint32 GetCurrentNode() const { return i_currentNode; } protected: @@ -110,30 +103,30 @@ class WaypointMovementGenerator<Creature> : public MovementGeneratorMedium< Crea * and hence generates ground and activities for the player. */ class FlightPathMovementGenerator : public MovementGeneratorMedium< Player, FlightPathMovementGenerator >, - public PathMovementBase<Player, TaxiPathNodeList const*> + public PathMovementBase<Player, TaxiPathNodeList> { public: - explicit FlightPathMovementGenerator(TaxiPathNodeList const& pathnodes, uint32 startNode = 0) + explicit FlightPathMovementGenerator(uint32 startNode = 0) { - i_path = &pathnodes; i_currentNode = startNode; _endGridX = 0.0f; _endGridY = 0.0f; _endMapId = 0; _preloadTargetNode = 0; } + void LoadPath(Player* player); void DoInitialize(Player*); void DoReset(Player*); void DoFinalize(Player*); bool DoUpdate(Player*, uint32); MovementGeneratorType GetMovementGeneratorType() const override { return FLIGHT_MOTION_TYPE; } - TaxiPathNodeList const& GetPath() { return *i_path; } + TaxiPathNodeList const& GetPath() { return i_path; } uint32 GetPathAtMapEnd() const; - bool HasArrived() const { return (i_currentNode >= i_path->size()); } + bool HasArrived() const { return (i_currentNode >= i_path.size()); } void SetCurrentNodeAfterTeleport(); void SkipCurrentNode() { ++i_currentNode; } - void DoEventIfAny(Player* player, TaxiPathNodeEntry const& node, bool departure); + void DoEventIfAny(Player* player, TaxiPathNodeEntry const* node, bool departure); bool GetResetPos(Player*, float& x, float& y, float& z); @@ -141,9 +134,18 @@ class FlightPathMovementGenerator : public MovementGeneratorMedium< Player, Flig void PreloadEndGrid(); private: - float _endGridX; //! X coord of last node location - float _endGridY; //! Y coord of last node location - uint32 _endMapId; //! map Id of last node location - uint32 _preloadTargetNode; //! node index where preloading starts + + float _endGridX; //! X coord of last node location + float _endGridY; //! Y coord of last node location + uint32 _endMapId; //! map Id of last node location + uint32 _preloadTargetNode; //! node index where preloading starts + + struct TaxiNodeChangeInfo + { + uint32 PathIndex; + int32 Cost; + }; + + std::deque<TaxiNodeChangeInfo> _pointsForPathSwitch; //! node indexes and costs where TaxiPath changes }; #endif diff --git a/src/server/game/Movement/Waypoints/Path.h b/src/server/game/Movement/Waypoints/Path.h deleted file mode 100644 index bb8abc37eb3..00000000000 --- a/src/server/game/Movement/Waypoints/Path.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef TRINITYCORE_PATH_H -#define TRINITYCORE_PATH_H - -#include "Common.h" -#include <deque> - -struct PathNode -{ - PathNode(): x(0.0f), y(0.0f), z(0.0f) { } - PathNode(float _x, float _y, float _z): x(_x), y(_y), z(_z) { } - float x, y, z; -}; -template<typename PathElem, typename PathNode = PathElem> - -class Path -{ - public: - size_t size() const { return i_nodes.size(); } - bool empty() const { return i_nodes.empty(); } - void resize(unsigned int sz) { i_nodes.resize(sz); } - void clear() { i_nodes.clear(); } - void erase(uint32 idx) { i_nodes.erase(i_nodes.begin()+idx); } - void crop(unsigned int start, unsigned int end) - { - while (start && !i_nodes.empty()) - { - i_nodes.pop_front(); - --start; - } - - while (end && !i_nodes.empty()) - { - i_nodes.pop_back(); - --end; - } - } - - float GetTotalLength(uint32 start, uint32 end) const - { - float len = 0.0f; - for (uint32 idx=start+1; idx < end; ++idx) - { - PathNode const& node = i_nodes[idx]; - PathNode const& prev = i_nodes[idx-1]; - float xd = node.x - prev.x; - float yd = node.y - prev.y; - float zd = node.z - prev.z; - len += std::sqrt(xd*xd + yd*yd + zd*zd); - } - return len; - } - - float GetTotalLength() const { return GetTotalLength(0, size()); } - - float GetPassedLength(uint32 curnode, float x, float y, float z) const - { - float len = GetTotalLength(0, curnode); - - if (curnode > 0) - { - PathNode const& node = i_nodes[curnode-1]; - float xd = x - node.x; - float yd = y - node.y; - float zd = z - node.z; - len += std::sqrt(xd*xd + yd*yd + zd*zd); - } - - return len; - } - - PathNode& operator[](size_t idx) { return i_nodes[idx]; } - PathNode const& operator[](size_t idx) const { return i_nodes[idx]; } - - void set(size_t idx, PathElem elem) { i_nodes[idx] = elem; } - - protected: - std::deque<PathElem> i_nodes; -}; - -typedef Path<PathNode> SimplePath; - -#endif |
