aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/master/2017_03_01_07_world_2016_09_20_00_world.sql21
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp13
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.cpp2
-rw-r--r--src/server/game/Movement/MotionMaster.cpp29
-rw-r--r--src/server/game/Movement/MotionMaster.h9
-rw-r--r--src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.cpp140
-rw-r--r--src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.h50
-rw-r--r--src/server/game/Movement/Spline/SplineChain.h47
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp1
-rw-r--r--src/server/game/Scripting/ScriptSystem.cpp84
-rw-r--r--src/server/game/Scripting/ScriptSystem.h25
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp1
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();