diff options
12 files changed, 401 insertions, 21 deletions
diff --git a/sql/updates/world/master/2017_03_01_07_world_2016_09_20_00_world.sql b/sql/updates/world/master/2017_03_01_07_world_2016_09_20_00_world.sql new file mode 100644 index 00000000000..ae2caf249f9 --- /dev/null +++ b/sql/updates/world/master/2017_03_01_07_world_2016_09_20_00_world.sql @@ -0,0 +1,21 @@ +-- add tables for spline chain DB storage +DROP TABLE IF EXISTS `script_spline_chain_meta`; +CREATE TABLE `script_spline_chain_meta` ( + `entry` INT UNSIGNED NOT NULL, + `chainId` TINYINT UNSIGNED NOT NULL, + `splineId` TINYINT UNSIGNED NOT NULL, + `expectedDuration` INT UNSIGNED NOT NULL, + `msUntilNext` INT UNSIGNED NOT NULL, + PRIMARY KEY USING BTREE (`entry`,`chainId`,`splineId`) +); +DROP TABLE IF EXISTS `script_spline_chain_waypoints`; +CREATE TABLE `script_spline_chain_waypoints` ( + `entry` INT UNSIGNED NOT NULL, + `chainId` TINYINT UNSIGNED NOT NULL, + `splineId` TINYINT UNSIGNED NOT NULL, + `wpId` TINYINT UNSIGNED NOT NULL, + `x` FLOAT NOT NULL, + `y` FLOAT NOT NULL, + `z` FLOAT NOT NULL, + PRIMARY KEY USING BTREE (`entry`,`chainId`,`splineId`,`wpId`) +); diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp index 0fb832fdc46..abd3b90f69f 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp @@ -402,12 +402,11 @@ void npc_escortAI::AddWaypoint(uint32 id, float x, float y, float z, uint32 wait void npc_escortAI::FillPointMovementListForCreature() { - ScriptPointVector const& movePoints = sScriptSystemMgr->GetPointMoveList(me->GetEntry()); - if (movePoints.empty()) + ScriptPointVector const* movePoints = sScriptSystemMgr->GetPointMoveList(me->GetEntry()); + if (!movePoints) return; - ScriptPointVector::const_iterator itrEnd = movePoints.end(); - for (ScriptPointVector::const_iterator itr = movePoints.begin(); itr != itrEnd; ++itr) + for (ScriptPointVector::const_iterator itr = movePoints->begin(); itr != movePoints->end(); ++itr) { Escort_Waypoint point(itr->uiPointId, itr->fX, itr->fY, itr->fZ, itr->uiWaitTime); WaypointList.push_back(point); @@ -563,11 +562,11 @@ bool npc_escortAI::SetNextWaypoint(uint32 pointId, bool setPosition, bool resetW bool npc_escortAI::GetWaypointPosition(uint32 pointId, float& x, float& y, float& z) { - ScriptPointVector const& waypoints = sScriptSystemMgr->GetPointMoveList(me->GetEntry()); - if (waypoints.empty()) + ScriptPointVector const* waypoints = sScriptSystemMgr->GetPointMoveList(me->GetEntry()); + if (!waypoints) return false; - for (ScriptPointVector::const_iterator itr = waypoints.begin(); itr != waypoints.end(); ++itr) + for (ScriptPointVector::const_iterator itr = waypoints->begin(); itr != waypoints->end(); ++itr) { if (itr->uiPointId == pointId) { diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index ab6651cedd6..81b4a909e17 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -574,7 +574,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) } case SMART_EVENT_MOVEMENTINFORM: { - if (e.event.movementInform.type > NULL_MOTION_TYPE) + if (e.event.movementInform.type >= MAX_MOTION_TYPE) { TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u uses invalid Motion type %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.movementInform.type); return false; diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 22f06801640..79d7c1026d4 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -19,6 +19,7 @@ #include "MotionMaster.h" #include "CreatureAISelector.h" #include "Creature.h" +#include "ScriptSystem.h" #include "ConfusedMovementGenerator.h" #include "FleeingMovementGenerator.h" @@ -28,6 +29,7 @@ #include "TargetedMovementGenerator.h" #include "WaypointMovementGenerator.h" #include "RandomMovementGenerator.h" +#include "SplineChainMovementGenerator.h" #include "MoveSpline.h" #include "MoveSplineInit.h" @@ -479,6 +481,33 @@ void MotionMaster::MoveSmoothPath(uint32 pointId, Movement::PointsArray const& p //MovePoint(EVENT_CHARGE_PREPATH, pos, false); } +void MotionMaster::MoveAlongSplineChain(uint32 pointId, uint32 dbChainId, bool walk) +{ + Creature* owner = _owner->ToCreature(); + if (!owner) + { + TC_LOG_ERROR("misc", "MotionMaster::MoveAlongSplineChain: non-creature %s tried to walk along DB spline chain. Ignoring.", _owner->GetGUID().ToString().c_str()); + return; + } + SplineChain const* chain = sScriptSystemMgr->GetSplineChain(owner, dbChainId); + if (!chain) + { + TC_LOG_ERROR("misc", "MotionMaster::MoveAlongSplineChain: creature with entry %u tried to walk along non-existing spline chain with DB id %u.", owner->GetEntry(), dbChainId); + return; + } + MoveAlongSplineChain(pointId, *chain, walk); +} + +void MotionMaster::MoveAlongSplineChain(uint32 pointId, SplineChain const& chain, bool walk) +{ + Mutate(new SplineChainMovementGenerator(pointId, chain, walk), MOTION_SLOT_ACTIVE); +} + +void MotionMaster::ResumeSplineChain(SplineChainResumeInfo const& info) +{ + Mutate(new SplineChainMovementGenerator(info), MOTION_SLOT_ACTIVE); +} + void MotionMaster::MoveFall(uint32 id /*=0*/) { // use larger distance for vmap height search than in most other cases diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index 7e2d6a47e56..a36fab0e735 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -24,6 +24,7 @@ #include "SharedDefines.h" #include "Object.h" #include "MoveSplineInitArgs.h" +#include "SplineChain.h" class MovementGenerator; class Unit; @@ -57,7 +58,9 @@ enum MovementGeneratorType FOLLOW_MOTION_TYPE = 14, ROTATE_MOTION_TYPE = 15, EFFECT_MOTION_TYPE = 16, - NULL_MOTION_TYPE = 17 + NULL_MOTION_TYPE = 17, + SPLINE_CHAIN_MOTION_TYPE = 18, // SplineChainMovementGenerator.h + MAX_MOTION_TYPE // limit }; enum MovementSlot @@ -206,6 +209,10 @@ class TC_GAME_API MotionMaster //: private std::stack<MovementGenerator *> void MoveCirclePath(float x, float y, float z, float radius, bool clockwise, uint8 stepCount); void MoveSmoothPath(uint32 pointId, G3D::Vector3 const* pathPoints, size_t pathSize, bool walk); void MoveSmoothPath(uint32 pointId, Movement::PointsArray const& points, bool walk); + // Walk along spline chain stored in DB (script_spline_chain_meta and script_spline_chain_waypoints) + void MoveAlongSplineChain(uint32 pointId, uint32 dbChainId, bool walk); + void MoveAlongSplineChain(uint32 pointId, SplineChain const& chain, bool walk); + void ResumeSplineChain(SplineChainResumeInfo const& info); void MoveFall(uint32 id = 0); void MoveSeekAssistance(float x, float y, float z); diff --git a/src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.cpp new file mode 100644 index 00000000000..551bc3e0283 --- /dev/null +++ b/src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.cpp @@ -0,0 +1,140 @@ +/* +* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> +* +* 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/>. +*/ + +#include "SplineChainMovementGenerator.h" +#include "Creature.h" +#include "CreatureAI.h" +#include "MoveSplineInit.h" +#include "MoveSpline.h" +#include "Log.h" + +uint32 SplineChainMovementGenerator::SendPathSpline(Unit* me, Movement::PointsArray const& wp) const +{ + uint32 numWp = wp.size(); + ASSERT(numWp > 1 && "Every path must have source & destination"); + Movement::MoveSplineInit init(me); + if (numWp > 2) + init.MovebyPath(wp); + else + init.MoveTo(wp[1], false, true); + init.SetWalk(_walk); + return init.Launch(); +} + +void SplineChainMovementGenerator::SendSplineFor(Unit* me, uint32 index, uint32& toNext) +{ + ASSERT(index < _chainSize); + TC_LOG_DEBUG("movement.splinechain", "%s: Sending spline for %u.", me->GetGUID().ToString().c_str(), index); + + SplineChainLink const& thisLink = _chain[index]; + uint32 actualDuration = SendPathSpline(me, thisLink.Points); + if (actualDuration != thisLink.ExpectedDuration) + { + TC_LOG_DEBUG("movement.splinechain", "%s: Sent spline for %u, duration is %u ms. Expected was %u ms (delta %d ms). Adjusting.", me->GetGUID().ToString().c_str(), index, actualDuration, thisLink.ExpectedDuration, int32(actualDuration) - int32(thisLink.ExpectedDuration)); + toNext = uint32(double(actualDuration)/double(thisLink.ExpectedDuration) * toNext); + } + else + { + TC_LOG_DEBUG("movement.splinechain", "%s: Sent spline for %u, duration is %u ms.", me->GetGUID().ToString().c_str(), index, actualDuration); + } +} + +void SplineChainMovementGenerator::Initialize(Unit* me) +{ + if (_chainSize) + { + if (_nextFirstWP) // this is a resumed movegen that has to start with a partial spline + { + if (finished) + return; + SplineChainLink const& thisLink = _chain[_nextIndex]; + if (_nextFirstWP >= thisLink.Points.size()) + { + TC_LOG_ERROR("movement.splinechain", "%s: Attempted to resume spline chain from invalid resume state (%u, %u).", me->GetGUID().ToString().c_str(), _nextIndex, _nextFirstWP); + _nextFirstWP = thisLink.Points.size()-1; + } + Movement::PointsArray partial(thisLink.Points.begin() + (_nextFirstWP-1), thisLink.Points.end()); + SendPathSpline(me, partial); + TC_LOG_DEBUG("movement.splinechain", "%s: Resumed spline chain generator from resume state.", me->GetGUID().ToString().c_str()); + ++_nextIndex; + if (!_msToNext) + _msToNext = 1; + _nextFirstWP = 0; + } + else + { + _msToNext = std::max(_chain[_nextIndex].TimeToNext, 1u); + SendSplineFor(me, _nextIndex, _msToNext); + ++_nextIndex; + if (_nextIndex >= _chainSize) + _msToNext = 0; + } + } + else + { + TC_LOG_ERROR("movement", "SplineChainMovementGenerator::Initialize - empty spline chain passed for %s.", me->GetGUID().ToString().c_str()); + } +} + +void SplineChainMovementGenerator::Finalize(Unit* me) +{ + if (!finished) + return; + Creature* cMe = me->ToCreature(); + if (cMe && cMe->IsAIEnabled) + cMe->AI()->MovementInform(SPLINE_CHAIN_MOTION_TYPE, _id); +} + +bool SplineChainMovementGenerator::Update(Unit* me, uint32 diff) +{ + if (finished) + return false; + + // _msToNext being zero here means we're on the final spline + if (!_msToNext) + { + finished = me->movespline->Finalized(); + return !finished; + } + + if (_msToNext <= diff) + { + // Send next spline + TC_LOG_DEBUG("movement.splinechain", "%s: Should send spline %u (%u ms late).", me->GetGUID().ToString().c_str(), _nextIndex, diff - _msToNext); + _msToNext = std::max(_chain[_nextIndex].TimeToNext, 1u); + SendSplineFor(me, _nextIndex, _msToNext); + ++_nextIndex; + if (_nextIndex >= _chainSize) + { + // We have reached the final spline, once it finalizes we should also finalize the movegen (start checking on next update) + _msToNext = 0; + return true; + } + } + else + _msToNext -= diff; + return true; +} + +SplineChainResumeInfo SplineChainMovementGenerator::GetResumeInfo(Unit const* me) const +{ + if (!_nextIndex) + return SplineChainResumeInfo(_id, &_chain, _walk, 0, 0, _msToNext); + if (me->movespline->Finalized()) + return SplineChainResumeInfo(_id, &_chain, _walk, _nextIndex, 0, 1u); + return SplineChainResumeInfo(_id, &_chain, _walk, uint8(_nextIndex - 1), uint8(me->movespline->_currentSplineIdx()), _msToNext); +} diff --git a/src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.h b/src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.h new file mode 100644 index 00000000000..8d64bf14562 --- /dev/null +++ b/src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.h @@ -0,0 +1,50 @@ +/* +* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> +* +* 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 TRINITY_SPLINECHAINMOVEMENTGENERATOR_H +#define TRINITY_SPLINECHAINMOVEMENTGENERATOR_H + +#include "SplineChain.h" +#include "MovementGenerator.h" + +class TC_GAME_API SplineChainMovementGenerator : public MovementGenerator +{ + public: + explicit SplineChainMovementGenerator(uint32 id, SplineChain const& chain, bool walk = false) : _id(id), _chain(chain), _chainSize(chain.size()), _walk(walk), finished(false), _nextIndex(0), _nextFirstWP(0), _msToNext(0) { } + explicit SplineChainMovementGenerator(SplineChainResumeInfo const& info) : _id(info.PointID), _chain(*info.Chain), _chainSize(info.Chain->size()), _walk(info.IsWalkMode), finished(info.SplineIndex >= info.Chain->size()), _nextIndex(info.SplineIndex), _nextFirstWP(info.PointIndex), _msToNext(info.TimeToNext) { } + void Initialize(Unit* me) override; + void Finalize(Unit* me) override; + void Reset(Unit* /*me*/) override { }; + bool Update(Unit* me, uint32 diff) override; + MovementGeneratorType GetMovementGeneratorType() const override { return SPLINE_CHAIN_MOTION_TYPE; } + // Builds info that can later be used to resume this spline chain movement at the current position + SplineChainResumeInfo GetResumeInfo(Unit const* me) const; + + private: + void SendSplineFor(Unit* me, uint32 index, uint32& toNext); + uint32 SendPathSpline(Unit* me, Movement::PointsArray const& wp) const; + uint32 const _id; + SplineChain const& _chain; + uint8 const _chainSize; + bool const _walk; + bool finished; + uint8 _nextIndex; + uint8 _nextFirstWP; // only used for resuming + uint32 _msToNext; +}; + +#endif diff --git a/src/server/game/Movement/Spline/SplineChain.h b/src/server/game/Movement/Spline/SplineChain.h new file mode 100644 index 00000000000..bfb66eb7fee --- /dev/null +++ b/src/server/game/Movement/Spline/SplineChain.h @@ -0,0 +1,47 @@ +/* +* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> +* +* 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 TRINITY_SPLINECHAIN_H +#define TRINITY_SPLINECHAIN_H + +#include "MoveSplineInitArgs.h" + +struct TC_GAME_API SplineChainLink +{ + SplineChainLink(Movement::PointsArray const& points, uint32 expectedDuration, uint32 msToNext) : Points(points), ExpectedDuration(expectedDuration), TimeToNext(msToNext) { } + template <typename iteratorType> SplineChainLink(iteratorType begin, iteratorType end, uint32 expectedDuration, uint32 msToNext) : Points(begin, end), ExpectedDuration(expectedDuration), TimeToNext(msToNext) { } + SplineChainLink(uint32 expectedDuration, uint32 msToNext) : Points(), ExpectedDuration(expectedDuration), TimeToNext(msToNext) { } + Movement::PointsArray Points; + uint32 ExpectedDuration; + uint32 TimeToNext; +}; +typedef std::vector<SplineChainLink> SplineChain; + +struct TC_GAME_API SplineChainResumeInfo +{ + SplineChainResumeInfo() : PointID(0), Chain(nullptr), IsWalkMode(false), SplineIndex(0), PointIndex(0), TimeToNext(0) { } + SplineChainResumeInfo(uint32 id, SplineChain const* chain, bool walk, uint8 splineIndex, uint8 wpIndex, uint32 msToNext) : + PointID(id), Chain(chain), IsWalkMode(walk), SplineIndex(splineIndex), PointIndex(wpIndex), TimeToNext(msToNext) { } + uint32 PointID; + SplineChain const* Chain; + bool IsWalkMode; + uint8 SplineIndex; + uint8 PointIndex; + uint32 TimeToNext; +}; + +#endif diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index bba0310d17b..d9c5427247b 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -1177,6 +1177,7 @@ void ScriptMgr::Unload() void ScriptMgr::LoadDatabase() { sScriptSystemMgr->LoadScriptWaypoints(); + sScriptSystemMgr->LoadScriptSplineChains(); } void ScriptMgr::FillSpellSummary() diff --git a/src/server/game/Scripting/ScriptSystem.cpp b/src/server/game/Scripting/ScriptSystem.cpp index a9147dfc6e8..6cae097c8c4 100644 --- a/src/server/game/Scripting/ScriptSystem.cpp +++ b/src/server/game/Scripting/ScriptSystem.cpp @@ -20,8 +20,7 @@ #include "ObjectMgr.h" #include "DatabaseEnv.h" #include "ScriptMgr.h" - -TC_GAME_API ScriptPointVector const SystemMgr::_empty; +#include "Creature.h" SystemMgr* SystemMgr::instance() { @@ -53,7 +52,6 @@ void SystemMgr::LoadScriptWaypoints() TC_LOG_INFO("server.loading", ">> Loaded 0 Script Waypoints. DB table `script_waypoint` is empty."); return; } - uint32 count = 0; do @@ -62,7 +60,7 @@ void SystemMgr::LoadScriptWaypoints() ScriptPointMove temp; temp.uiCreatureEntry = pFields[0].GetUInt32(); - uint32 uiEntry = temp.uiCreatureEntry; + uint32 uiEntry = temp.uiCreatureEntry; temp.uiPointId = pFields[1].GetUInt32(); temp.fX = pFields[2].GetFloat(); temp.fY = pFields[3].GetFloat(); @@ -82,8 +80,82 @@ void SystemMgr::LoadScriptWaypoints() m_mPointMoveMap[uiEntry].push_back(temp); ++count; - } - while (result->NextRow()); + } while (result->NextRow()); TC_LOG_INFO("server.loading", ">> Loaded %u Script Waypoint nodes in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } + +void SystemMgr::LoadScriptSplineChains() +{ + uint32 oldMSTime = getMSTime(); + + m_mSplineChainsMap.clear(); + + // 0 1 2 3 4 + QueryResult resultMeta = WorldDatabase.Query("SELECT entry, chainId, splineId, expectedDuration, msUntilNext FROM script_spline_chain_meta ORDER BY entry asc, chainId asc, splineId asc"); + // 0 1 2 3 4 5 6 + QueryResult resultWP = WorldDatabase.Query("SELECT entry, chainId, splineId, wpId, x, y, z FROM script_spline_chain_waypoints ORDER BY entry asc, chainId asc, splineId asc, wpId asc"); + if (!resultMeta || !resultWP) + { + TC_LOG_INFO("server.loading", ">> Loaded spline chain data for 0 chains, consisting of 0 splines with 0 waypoints. DB tables `script_spline_chain_meta` and `script_spline_chain_waypoints` are empty."); + } + else + { + uint32 chainCount = 0, splineCount = 0, wpCount = 0; + do + { + Field* fieldsMeta = resultMeta->Fetch(); + uint32 entry = fieldsMeta[0].GetUInt32(); + uint8 chainId = fieldsMeta[1].GetUInt8(), splineId = fieldsMeta[2].GetUInt8(); + SplineChain& chain = m_mSplineChainsMap[{entry,chainId}]; + + if (splineId != chain.size()) + { + TC_LOG_WARN("server.loading", "Creature #%u: Chain %u has orphaned spline %u, skipped.", entry, chainId, splineId); + continue; + } + + uint32 expectedDuration = fieldsMeta[3].GetUInt32(), msUntilNext = fieldsMeta[4].GetUInt32(); + chain.push_back(SplineChainLink(expectedDuration, msUntilNext)); + + if (splineId == 0) + ++chainCount; + ++splineCount; + } while (resultMeta->NextRow()); + + do + { + Field* fieldsWP = resultWP->Fetch(); + uint32 entry = fieldsWP[0].GetUInt32(); + uint8 chainId = fieldsWP[1].GetUInt8(), splineId = fieldsWP[2].GetUInt8(), wpId = fieldsWP[3].GetUInt8(); + float posX = fieldsWP[4].GetFloat(), posY = fieldsWP[5].GetFloat(), posZ = fieldsWP[6].GetFloat(); + auto it = m_mSplineChainsMap.find({entry,chainId}); + if (it == m_mSplineChainsMap.end()) + { + TC_LOG_WARN("server.loading", "Creature #%u has waypoint data for spline chain %u. No such chain exists - entry skipped.", entry, chainId); + continue; + } + SplineChain& chain = it->second; + if (splineId >= chain.size()) + { + TC_LOG_WARN("server.loading", "Creature #%u has waypoint data for spline (%u,%u). The specified chain does not have a spline with this index - entry skipped.", entry, chainId, splineId); + continue; + } + SplineChainLink& spline = chain[splineId]; + if (wpId != spline.Points.size()) + { + TC_LOG_WARN("server.loading", "Creature #%u has orphaned waypoint data in spline (%u,%u) at index %u. Skipped.", entry, chainId, splineId, wpId); + continue; + } + spline.Points.emplace_back(posX, posY, posZ); + ++wpCount; + } while (resultWP->NextRow()); + + TC_LOG_INFO("server.loading", ">> Loaded spline chain data for %u chains, consisting of %u splines with %u waypoints in %u ms", chainCount, splineCount, wpCount, GetMSTimeDiffToNow(oldMSTime)); + } +} + +SplineChain const* SystemMgr::GetSplineChain(Creature const* who, uint8 id) const +{ + return GetSplineChain(who->GetEntry(), id); +} diff --git a/src/server/game/Scripting/ScriptSystem.h b/src/server/game/Scripting/ScriptSystem.h index b28b31a8b85..6086b10e2be 100644 --- a/src/server/game/Scripting/ScriptSystem.h +++ b/src/server/game/Scripting/ScriptSystem.h @@ -20,6 +20,9 @@ #define SC_SYSTEM_H #include "ScriptMgr.h" +#include "SplineChain.h" + +class Creature; #define TEXT_SOURCE_RANGE -1000000 //the amount of entries each text source has available @@ -72,22 +75,32 @@ class TC_GAME_API SystemMgr //Database void LoadScriptWaypoints(); + void LoadScriptSplineChains(); - ScriptPointVector const& GetPointMoveList(uint32 creatureEntry) const + ScriptPointVector const* GetPointMoveList(uint32 creatureEntry) const { PointMoveMap::const_iterator itr = m_mPointMoveMap.find(creatureEntry); if (itr == m_mPointMoveMap.end()) - return _empty; + return nullptr; + + return &itr->second; + } - return itr->second; + SplineChain const* GetSplineChain(uint32 entry, uint8 id) const + { + auto it = m_mSplineChainsMap.find({ entry, id }); + if (it == m_mSplineChainsMap.end()) + return nullptr; + return &it->second; } + SplineChain const* GetSplineChain(Creature const* who, uint8 id) const; + protected: PointMoveMap m_mPointMoveMap; //coordinates for waypoints - - private: - static ScriptPointVector const _empty; + typedef std::pair<uint32, uint8> ChainKeyType; // creature entry + chain ID + std::unordered_map<ChainKeyType, SplineChain> m_mSplineChainsMap; // spline chains }; #define sScriptSystemMgr SystemMgr::instance() diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp index 41bb7971635..9de4194c733 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp @@ -1272,6 +1272,7 @@ class npc_crate_helper : public CreatureScript } }; + void AddSC_culling_of_stratholme() { new npc_arthas(); |