aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorr00ty-tc <r00ty-tc@users.noreply.github.com>2016-05-11 10:51:15 +0100
committerr00ty-tc <r00ty-tc@users.noreply.github.com>2016-05-11 11:56:25 +0200
commitde918a0f644794beebff2234b53980b577b27e39 (patch)
tree54d21dce2d9014bf39380958f8c172a1f316a0ae /src
parent7e48a023989e50920fe2e115cb57d25095071a17 (diff)
Core/Maps - Improvements to Cinematic function
- Moves to own class for reading, storage and player subclass - Proper destruction handling for player (ensure cinematic is ended) - Timeout for cinematic if it reaches past the end without completing - boost::filesystem::path used for path/filename transform - Correct for assert trigger under certain circumstances - Other changes previously suggested
Diffstat (limited to 'src')
-rw-r--r--src/server/game/DataStores/DBCEnums.h16
-rw-r--r--src/server/game/DataStores/DBCStores.cpp245
-rw-r--r--src/server/game/DataStores/DBCStores.h4
-rw-r--r--src/server/game/DataStores/DBCStructure.h12
-rw-r--r--src/server/game/DataStores/M2Stores.cpp266
-rw-r--r--src/server/game/DataStores/M2Stores.h36
-rw-r--r--src/server/game/DataStores/M2Structure.h133
-rw-r--r--src/server/game/Entities/Object/Object.cpp4
-rw-r--r--src/server/game/Entities/Player/CinematicMgr.cpp171
-rw-r--r--src/server/game/Entities/Player/CinematicMgr.h60
-rw-r--r--src/server/game/Entities/Player/Player.cpp143
-rw-r--r--src/server/game/Entities/Player/Player.h27
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp4
-rw-r--r--src/server/game/World/World.cpp5
-rw-r--r--src/server/scripts/Commands/cs_debug.cpp1
-rw-r--r--src/server/shared/DataStores/DBCStore.h115
-rw-r--r--src/tools/map_extractor/System.cpp2
17 files changed, 712 insertions, 532 deletions
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index f0ea5b4a5f1..cb2f26e567f 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -19,6 +19,22 @@
#ifndef DBCENUMS_H
#define DBCENUMS_H
+#pragma pack(push, 1)
+
+struct DBCPosition2D
+{
+ float X;
+ float Y;
+};
+
+struct DBCPosition3D
+{
+ float X;
+ float Y;
+ float Z;
+};
+
+#pragma pack(pop)
enum LevelLimit
{
// Client expected level limitation, like as used in DBC item max levels for "until max player level"
diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp
index 5ede70da2a3..36ec418ed56 100644
--- a/src/server/game/DataStores/DBCStores.cpp
+++ b/src/server/game/DataStores/DBCStores.cpp
@@ -27,9 +27,6 @@
#include <boost/regex.hpp>
#include <map>
-#include <fstream>
-#include <iostream>
-#include <iomanip>
typedef std::map<uint16, uint32> AreaFlagByAreaID;
typedef std::map<uint32, uint32> AreaFlagByMapID;
@@ -221,8 +218,6 @@ DBCStorage <WorldMapAreaEntry> sWorldMapAreaStore(WorldMapAreaEntryfmt);
DBCStorage <WorldMapOverlayEntry> sWorldMapOverlayStore(WorldMapOverlayEntryfmt);
DBCStorage <WorldSafeLocsEntry> sWorldSafeLocsStore(WorldSafeLocsEntryfmt);
-std::unordered_map<uint32, FlyByCameraCollection> sFlyByCameraStore;
-
typedef std::list<std::string> StoreProblemList;
uint32 DBCFileCount = 0;
@@ -724,250 +719,10 @@ void LoadDBCStores(const std::string& dataPath)
exit(1);
}
- LoadM2Cameras(dataPath);
-
TC_LOG_INFO("server.loading", ">> Initialized %d data stores in %u ms", DBCFileCount, GetMSTimeDiffToNow(oldMSTime));
}
-// Convert the geomoetry from a spline value, to an actual WoW XYZ
-G3D::Vector3 TranslateLocation(G3D::Vector4 const* DBCPosition, G3D::Vector3 const* basePosition, G3D::Vector3 const* splineVector)
-{
- G3D::Vector3 work;
- float x = basePosition->x + splineVector->x;
- float y = basePosition->y + splineVector->y;
- float z = basePosition->z + splineVector->z;
- float const distance = sqrt((x * x) + (y * y));
- float angle = std::atan2(x, y) - DBCPosition->w;
-
- if (angle < 0)
- angle += 2 * float(M_PI);
-
- work.x = DBCPosition->x + (distance * sin(angle));
- work.y = DBCPosition->y + (distance * cos(angle));
- work.z = DBCPosition->z + z;
- return work;
-}
-
-// Number of cameras not used. Multiple cameras never used in 3.3.5
-bool readCamera(M2Camera const* cam, uint32 buffSize, M2Header const* header, CinematicCameraEntry const* dbcentry)
-{
- char const* buffer = reinterpret_cast<char const*>(header);
-
- FlyByCameraCollection cameras;
- FlyByCameraCollection targetcam;
-
- G3D::Vector4 DBCData;
- DBCData.x = dbcentry->base_x;
- DBCData.y = dbcentry->base_y;
- DBCData.z = dbcentry->base_z;
- DBCData.w = dbcentry->base_o;
-
- // Read target locations, only so that we can calculate orientation
- for (uint32 k = 0; k < cam->target_positions.timestamps.number; ++k)
- {
- // Extract Target positions
- if (cam->target_positions.timestamps.offset_elements + sizeof(M2Array) > buffSize)
- return false;
- M2Array const* targTsArray = reinterpret_cast<M2Array const*>(buffer + cam->target_positions.timestamps.offset_elements);
- if (targTsArray->offset_elements + sizeof(uint32) > buffSize || cam->target_positions.values.offset_elements + sizeof(M2Array) > buffSize)
- return false;
- uint32 const* targTimestamps = reinterpret_cast<uint32 const*>(buffer + targTsArray->offset_elements);
- M2Array const* targArray = reinterpret_cast<M2Array const*>(buffer + cam->target_positions.values.offset_elements);
-
- if (targArray->offset_elements + sizeof(M2SplineKey<G3D::Vector3>) > buffSize)
- return false;
- M2SplineKey<G3D::Vector3> const* targPositions = reinterpret_cast<M2SplineKey<G3D::Vector3> const*>(buffer + targArray->offset_elements);
-
- // Read the data for this set
- uint32 currPos = targArray->offset_elements;
- for (uint32 i = 0; i < targTsArray->number; ++i)
- {
- if (currPos + sizeof(M2SplineKey<G3D::Vector3>) > buffSize)
- return false;
- // Translate co-ordinates
- G3D::Vector3 newPos = TranslateLocation(&DBCData, &cam->target_position_base, &targPositions->p0);
-
- // Add to vector
- FlyByCamera thisCam;
- thisCam.timeStamp = targTimestamps[i];
- thisCam.locations.x = newPos.x;
- thisCam.locations.y = newPos.y;
- thisCam.locations.z = newPos.z;
- thisCam.locations.w = 0.0f;
- targetcam.push_back(thisCam);
- targPositions++;
- currPos += sizeof(M2SplineKey<G3D::Vector3>);
- }
- }
-
- // Read camera positions and timestamps (translating first position of 3 only, we don't need to translate the whole spline)
- for (uint32 k = 0; k < cam->positions.timestamps.number; ++k)
- {
- // Extract Camera positions for this set
- if (cam->positions.timestamps.offset_elements + sizeof(M2Array) > buffSize)
- return false;
- M2Array const* posTsArray = reinterpret_cast<M2Array const*>(buffer + cam->positions.timestamps.offset_elements);
- if (posTsArray->offset_elements + sizeof(uint32) > buffSize || cam->positions.values.offset_elements + sizeof(M2Array) > buffSize)
- return false;
- uint32 const* posTimestamps = reinterpret_cast<uint32 const*>(buffer + posTsArray->offset_elements);
- M2Array const* posArray = reinterpret_cast<M2Array const*>(buffer + cam->positions.values.offset_elements);
- if (posArray->offset_elements + sizeof(M2SplineKey<G3D::Vector3>) > buffSize)
- return false;
- M2SplineKey<G3D::Vector3> const* positions = reinterpret_cast<M2SplineKey<G3D::Vector3> const*>(buffer + posArray->offset_elements);
-
- // Read the data for this set
- uint32 currPos = posArray->offset_elements;
- for (uint32 i = 0; i < posTsArray->number; ++i)
- {
- if (currPos + sizeof(M2SplineKey<G3D::Vector3>) > buffSize)
- return false;
- // Translate co-ordinates
- G3D::Vector3 newPos = TranslateLocation(&DBCData, &cam->position_base, &positions->p0);
-
- // Add to vector
- FlyByCamera thisCam;
- thisCam.timeStamp = posTimestamps[i];
- thisCam.locations.x = newPos.x;
- thisCam.locations.y = newPos.y;
- thisCam.locations.z = newPos.z;
-
- if (targetcam.size() > 0)
- {
- // Find the target camera before and after this camera
- FlyByCamera lastTarget;
- FlyByCamera nextTarget;
-
- // Pre-load first item
- lastTarget = targetcam[0];
- nextTarget = targetcam[0];
- for (uint32 j = 0; j < targetcam.size(); ++j)
- {
- nextTarget = targetcam[j];
- if (targetcam[j].timeStamp > posTimestamps[i])
- break;
-
- lastTarget = targetcam[j];
- }
-
- float x = lastTarget.locations.x;
- float y = lastTarget.locations.y;
- float z = lastTarget.locations.z;
-
- // Now, the timestamps for target cam and position can be different. So, if they differ we interpolate
- if (lastTarget.timeStamp != posTimestamps[i])
- {
- uint32 timeDiffTarget = nextTarget.timeStamp - lastTarget.timeStamp;
- uint32 timeDiffThis = posTimestamps[i] - lastTarget.timeStamp;
- float xDiff = nextTarget.locations.x - lastTarget.locations.x;
- float yDiff = nextTarget.locations.y - lastTarget.locations.y;
- float zDiff = nextTarget.locations.z - lastTarget.locations.z;
- x = lastTarget.locations.x + (xDiff * (float(timeDiffThis) / float(timeDiffTarget)));
- y = lastTarget.locations.y + (yDiff * (float(timeDiffThis) / float(timeDiffTarget)));
- z = lastTarget.locations.z + (zDiff * (float(timeDiffThis) / float(timeDiffTarget)));
- }
- float xDiff = x - thisCam.locations.x;
- float yDiff = y - thisCam.locations.y;
- thisCam.locations.w = std::atan2(yDiff, xDiff);
-
- if (thisCam.locations.w < 0)
- thisCam.locations.w += 2 * float(M_PI);
- }
-
- cameras.push_back(thisCam);
- positions++;
- currPos += sizeof(M2SplineKey<G3D::Vector3>);
- }
- }
-
- sFlyByCameraStore[dbcentry->id] = cameras;
- return true;
-}
-
-void LoadM2Cameras(const std::string& dataPath)
-{
- sFlyByCameraStore.clear();
- TC_LOG_INFO("server.loading", ">> Loading Cinematic Camera files");
-
- uint32 oldMSTime = getMSTime();
- for (uint32 i = 0; i < sCinematicCameraStore.GetNumRows(); ++i)
- {
- if (CinematicCameraEntry const* dbcentry = sCinematicCameraStore.LookupEntry(i))
- {
- std::string filename = dataPath.c_str();
- filename.append(dbcentry->filename);
-
- // Replace slashes
- size_t loc = filename.find("\\");
- while (loc != std::string::npos)
- {
- filename.replace(loc, 1, "/");
- loc = filename.find("\\");
- }
-
- // Replace mdx to .m2
- loc = filename.find(".mdx");
- if (loc != std::string::npos)
- filename.replace(loc, 4, ".m2");
-
- std::ifstream m2file(filename.c_str(), std::ios::in | std::ios::binary);
- if (!m2file.is_open())
- continue;
-
- // Get file size
- m2file.seekg(0, std::ios::end);
- std::streamoff const fileSize = m2file.tellg();
-
- // Reject if not at least the size of the header
- if (static_cast<uint32 const>(fileSize) < sizeof(M2Header))
- {
- TC_LOG_ERROR("server.loading", "Camera file %s is damaged. File is smaller than header size", filename.c_str());
- m2file.close();
- continue;
- }
-
- // Read 4 bytes (signature)
- m2file.seekg(0, std::ios::beg);
- char fileCheck[5];
- m2file.read(fileCheck, 4);
- fileCheck[4] = 0;
-
- // Check file has correct magic (MD20)
- if (strcmp(fileCheck, "MD20"))
- {
- TC_LOG_ERROR("server.loading", "Camera file %s is damaged. File identifier not found", filename.c_str());
- m2file.close();
- continue;
- }
-
- // Now we have a good file, read it all into a vector of char's, then close the file.
- std::vector<char> buffer(fileSize);
- m2file.seekg(0, std::ios::beg);
- if (!m2file.read(buffer.data(), fileSize))
- {
- m2file.close();
- continue;
- }
- m2file.close();
-
- // Read header
- M2Header const* header = reinterpret_cast<M2Header const*>(buffer.data());
-
- if (header->ofsCameras + sizeof(M2Camera) > static_cast<uint32 const>(fileSize))
- {
- TC_LOG_ERROR("server.loading", "Camera file %s is damaged. Camera references position beyond file end", filename.c_str());
- continue;
- }
-
- // Get camera(s) - Main header, then dump them.
- M2Camera const* cam = reinterpret_cast<M2Camera const*>(buffer.data() + header->ofsCameras);
- if (!readCamera(cam, fileSize, header, dbcentry))
- TC_LOG_ERROR("server.loading", "Camera file %s is damaged. Camera references position beyond file end", filename.c_str());
- }
- }
- TC_LOG_INFO("server.loading", ">> Loaded %u cinematic waypoint sets in %u ms", (uint32)sFlyByCameraStore.size(), GetMSTimeDiffToNow(oldMSTime));
-}
-
SimpleFactionsList const* GetFactionTeamList(uint32 faction)
{
FactionTeamMap::const_iterator itr = sFactionTeamMap.find(faction);
diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h
index 6cad13fdf9a..00b4141555f 100644
--- a/src/server/game/DataStores/DBCStores.h
+++ b/src/server/game/DataStores/DBCStores.h
@@ -27,8 +27,6 @@
#include <list>
typedef std::list<uint32> SimpleFactionsList;
-typedef std::vector<FlyByCamera> FlyByCameraCollection;
-
TC_GAME_API SimpleFactionsList const* GetFactionTeamList(uint32 faction);
TC_GAME_API char* GetPetName(uint32 petfamily, uint32 dbclang);
@@ -196,9 +194,7 @@ TC_GAME_API extern DBCStorage <WMOAreaTableEntry> sWMOAreaTableStore;
//TC_GAME_API extern DBCStorage <WorldMapAreaEntry> sWorldMapAreaStore; -- use Zone2MapCoordinates and Map2ZoneCoordinates
TC_GAME_API extern DBCStorage <WorldMapOverlayEntry> sWorldMapOverlayStore;
TC_GAME_API extern DBCStorage <WorldSafeLocsEntry> sWorldSafeLocsStore;
-TC_GAME_API extern std::unordered_map<uint32, FlyByCameraCollection> sFlyByCameraStore;
TC_GAME_API void LoadDBCStores(const std::string& dataPath);
-TC_GAME_API void LoadM2Cameras(const std::string& dataPath);
#endif
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index 51b3dcbd38b..13f0198a5e7 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -727,13 +727,11 @@ struct ChrRacesEntry
struct CinematicCameraEntry
{
- uint32 id; // 0 index
- char* filename; // 1
- uint32 soundid; // 2 in SoundEntries.dbc or 0
- float base_x; // 3
- float base_y; // 4
- float base_z; // 5
- float base_o; // 6
+ uint32 ID; // 0
+ char const* Model; // 1 Model filename (translate .mdx to .m2)
+ uint32 SoundID; // 2 Sound ID (voiceover for cinematic)
+ DBCPosition3D Origin; // 3-5 Position in map used for basis for M2 co-ordinates
+ float OriginFacing; // 6 Orientation in map used for basis for M2 co-ordinates
};
struct CinematicSequencesEntry
diff --git a/src/server/game/DataStores/M2Stores.cpp b/src/server/game/DataStores/M2Stores.cpp
new file mode 100644
index 00000000000..5cff66e6107
--- /dev/null
+++ b/src/server/game/DataStores/M2Stores.cpp
@@ -0,0 +1,266 @@
+/*
+* 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 "DBCStores.h"
+#include "M2Structure.h"
+#include "M2Stores.h"
+#include "Common.h"
+#include "Containers.h"
+#include "Log.h"
+#include "World.h"
+#include <fstream>
+#include <iostream>
+#include <iomanip>
+#include <boost/filesystem/path.hpp>
+
+std::unordered_map<uint32, FlyByCameraCollection> sFlyByCameraStore;
+
+// Convert the geomoetry from a spline value, to an actual WoW XYZ
+G3D::Vector3 TranslateLocation(G3D::Vector4 const* DBCPosition, G3D::Vector3 const* basePosition, G3D::Vector3 const* splineVector)
+{
+ G3D::Vector3 work;
+ float x = basePosition->x + splineVector->x;
+ float y = basePosition->y + splineVector->y;
+ float z = basePosition->z + splineVector->z;
+ float const distance = sqrt((x * x) + (y * y));
+ float angle = std::atan2(x, y) - DBCPosition->w;
+
+ if (angle < 0)
+ angle += 2 * float(M_PI);
+
+ work.x = DBCPosition->x + (distance * sin(angle));
+ work.y = DBCPosition->y + (distance * cos(angle));
+ work.z = DBCPosition->z + z;
+ return work;
+}
+
+// Number of cameras not used. Multiple cameras never used in 3.3.5
+bool readCamera(M2Camera const* cam, uint32 buffSize, M2Header const* header, CinematicCameraEntry const* dbcentry)
+{
+ char const* buffer = reinterpret_cast<char const*>(header);
+
+ FlyByCameraCollection cameras;
+ FlyByCameraCollection targetcam;
+
+ G3D::Vector4 DBCData;
+ DBCData.x = dbcentry->Origin.X;
+ DBCData.y = dbcentry->Origin.Y;
+ DBCData.z = dbcentry->Origin.Z;
+ DBCData.w = dbcentry->OriginFacing;
+
+ // Read target locations, only so that we can calculate orientation
+ for (uint32 k = 0; k < cam->target_positions.timestamps.number; ++k)
+ {
+ // Extract Target positions
+ if (cam->target_positions.timestamps.offset_elements + sizeof(M2Array) > buffSize)
+ return false;
+ M2Array const* targTsArray = reinterpret_cast<M2Array const*>(buffer + cam->target_positions.timestamps.offset_elements);
+ if (targTsArray->offset_elements + sizeof(uint32) > buffSize || cam->target_positions.values.offset_elements + sizeof(M2Array) > buffSize)
+ return false;
+ uint32 const* targTimestamps = reinterpret_cast<uint32 const*>(buffer + targTsArray->offset_elements);
+ M2Array const* targArray = reinterpret_cast<M2Array const*>(buffer + cam->target_positions.values.offset_elements);
+
+ if (targArray->offset_elements + sizeof(M2SplineKey<G3D::Vector3>) > buffSize)
+ return false;
+ M2SplineKey<G3D::Vector3> const* targPositions = reinterpret_cast<M2SplineKey<G3D::Vector3> const*>(buffer + targArray->offset_elements);
+
+ // Read the data for this set
+ uint32 currPos = targArray->offset_elements;
+ for (uint32 i = 0; i < targTsArray->number; ++i)
+ {
+ if (currPos + sizeof(M2SplineKey<G3D::Vector3>) > buffSize)
+ return false;
+ // Translate co-ordinates
+ G3D::Vector3 newPos = TranslateLocation(&DBCData, &cam->target_position_base, &targPositions->p0);
+
+ // Add to vector
+ FlyByCamera thisCam;
+ thisCam.timeStamp = targTimestamps[i];
+ thisCam.locations.x = newPos.x;
+ thisCam.locations.y = newPos.y;
+ thisCam.locations.z = newPos.z;
+ thisCam.locations.w = 0.0f;
+ targetcam.push_back(thisCam);
+ targPositions++;
+ currPos += sizeof(M2SplineKey<G3D::Vector3>);
+ }
+ }
+
+ // Read camera positions and timestamps (translating first position of 3 only, we don't need to translate the whole spline)
+ for (uint32 k = 0; k < cam->positions.timestamps.number; ++k)
+ {
+ // Extract Camera positions for this set
+ if (cam->positions.timestamps.offset_elements + sizeof(M2Array) > buffSize)
+ return false;
+ M2Array const* posTsArray = reinterpret_cast<M2Array const*>(buffer + cam->positions.timestamps.offset_elements);
+ if (posTsArray->offset_elements + sizeof(uint32) > buffSize || cam->positions.values.offset_elements + sizeof(M2Array) > buffSize)
+ return false;
+ uint32 const* posTimestamps = reinterpret_cast<uint32 const*>(buffer + posTsArray->offset_elements);
+ M2Array const* posArray = reinterpret_cast<M2Array const*>(buffer + cam->positions.values.offset_elements);
+ if (posArray->offset_elements + sizeof(M2SplineKey<G3D::Vector3>) > buffSize)
+ return false;
+ M2SplineKey<G3D::Vector3> const* positions = reinterpret_cast<M2SplineKey<G3D::Vector3> const*>(buffer + posArray->offset_elements);
+
+ // Read the data for this set
+ uint32 currPos = posArray->offset_elements;
+ for (uint32 i = 0; i < posTsArray->number; ++i)
+ {
+ if (currPos + sizeof(M2SplineKey<G3D::Vector3>) > buffSize)
+ return false;
+ // Translate co-ordinates
+ G3D::Vector3 newPos = TranslateLocation(&DBCData, &cam->position_base, &positions->p0);
+
+ // Add to vector
+ FlyByCamera thisCam;
+ thisCam.timeStamp = posTimestamps[i];
+ thisCam.locations.x = newPos.x;
+ thisCam.locations.y = newPos.y;
+ thisCam.locations.z = newPos.z;
+
+ if (targetcam.size() > 0)
+ {
+ // Find the target camera before and after this camera
+ FlyByCamera lastTarget;
+ FlyByCamera nextTarget;
+
+ // Pre-load first item
+ lastTarget = targetcam[0];
+ nextTarget = targetcam[0];
+ for (uint32 j = 0; j < targetcam.size(); ++j)
+ {
+ nextTarget = targetcam[j];
+ if (targetcam[j].timeStamp > posTimestamps[i])
+ break;
+
+ lastTarget = targetcam[j];
+ }
+
+ float x = lastTarget.locations.x;
+ float y = lastTarget.locations.y;
+ float z = lastTarget.locations.z;
+
+ // Now, the timestamps for target cam and position can be different. So, if they differ we interpolate
+ if (lastTarget.timeStamp != posTimestamps[i])
+ {
+ uint32 timeDiffTarget = nextTarget.timeStamp - lastTarget.timeStamp;
+ uint32 timeDiffThis = posTimestamps[i] - lastTarget.timeStamp;
+ float xDiff = nextTarget.locations.x - lastTarget.locations.x;
+ float yDiff = nextTarget.locations.y - lastTarget.locations.y;
+ float zDiff = nextTarget.locations.z - lastTarget.locations.z;
+ x = lastTarget.locations.x + (xDiff * (float(timeDiffThis) / float(timeDiffTarget)));
+ y = lastTarget.locations.y + (yDiff * (float(timeDiffThis) / float(timeDiffTarget)));
+ z = lastTarget.locations.z + (zDiff * (float(timeDiffThis) / float(timeDiffTarget)));
+ }
+ float xDiff = x - thisCam.locations.x;
+ float yDiff = y - thisCam.locations.y;
+ thisCam.locations.w = std::atan2(yDiff, xDiff);
+
+ if (thisCam.locations.w < 0)
+ thisCam.locations.w += 2 * float(M_PI);
+ }
+
+ cameras.push_back(thisCam);
+ positions++;
+ currPos += sizeof(M2SplineKey<G3D::Vector3>);
+ }
+ }
+
+ sFlyByCameraStore[dbcentry->ID] = cameras;
+ return true;
+}
+
+void LoadM2Cameras(std::string const& dataPath)
+{
+ sFlyByCameraStore.clear();
+ TC_LOG_INFO("server.loading", ">> Loading Cinematic Camera files");
+
+ uint32 oldMSTime = getMSTime();
+ for (uint32 i = 0; i < sCinematicCameraStore.GetNumRows(); ++i)
+ {
+ if (CinematicCameraEntry const* dbcentry = sCinematicCameraStore.LookupEntry(i))
+ {
+ std::string filenameWork = dataPath.c_str();
+ filenameWork.append(dbcentry->Model);
+
+ // Replace slashes (always to forward slash, because boost!)
+ std::replace(filenameWork.begin(), filenameWork.end(), '\\', '/');
+
+ boost::filesystem::path filename = filenameWork;
+
+ // Convert to native format
+ filename.make_preferred();
+
+ // Replace mdx to .m2
+ filename.replace_extension("m2");
+
+ std::ifstream m2file(filename.string().c_str(), std::ios::in | std::ios::binary);
+ if (!m2file.is_open())
+ continue;
+
+ // Get file size
+ m2file.seekg(0, std::ios::end);
+ std::streamoff const fileSize = m2file.tellg();
+
+ // Reject if not at least the size of the header
+ if (static_cast<uint32 const>(fileSize) < sizeof(M2Header))
+ {
+ TC_LOG_ERROR("server.loading", "Camera file %s is damaged. File is smaller than header size", filename.string().c_str());
+ m2file.close();
+ continue;
+ }
+
+ // Read 4 bytes (signature)
+ m2file.seekg(0, std::ios::beg);
+ char fileCheck[5];
+ m2file.read(fileCheck, 4);
+ fileCheck[4] = 0;
+
+ // Check file has correct magic (MD20)
+ if (strcmp(fileCheck, "MD20"))
+ {
+ TC_LOG_ERROR("server.loading", "Camera file %s is damaged. File identifier not found", filename.string().c_str());
+ m2file.close();
+ continue;
+ }
+
+ // Now we have a good file, read it all into a vector of char's, then close the file.
+ std::vector<char> buffer(fileSize);
+ m2file.seekg(0, std::ios::beg);
+ if (!m2file.read(buffer.data(), fileSize))
+ {
+ m2file.close();
+ continue;
+ }
+ m2file.close();
+
+ // Read header
+ M2Header const* header = reinterpret_cast<M2Header const*>(buffer.data());
+
+ if (header->ofsCameras + sizeof(M2Camera) > static_cast<uint32 const>(fileSize))
+ {
+ TC_LOG_ERROR("server.loading", "Camera file %s is damaged. Camera references position beyond file end", filename.string().c_str());
+ continue;
+ }
+
+ // Get camera(s) - Main header, then dump them.
+ M2Camera const* cam = reinterpret_cast<M2Camera const*>(buffer.data() + header->ofsCameras);
+ if (!readCamera(cam, fileSize, header, dbcentry))
+ TC_LOG_ERROR("server.loading", "Camera file %s is damaged. Camera references position beyond file end", filename.string().c_str());
+ }
+ }
+ TC_LOG_INFO("server.loading", ">> Loaded %u cinematic waypoint sets in %u ms", (uint32)sFlyByCameraStore.size(), GetMSTimeDiffToNow(oldMSTime));
+}
diff --git a/src/server/game/DataStores/M2Stores.h b/src/server/game/DataStores/M2Stores.h
new file mode 100644
index 00000000000..97224475e5d
--- /dev/null
+++ b/src/server/game/DataStores/M2Stores.h
@@ -0,0 +1,36 @@
+/*
+* 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_M2STORES_H
+#define TRINITY_M2STORES_H
+
+#include "SharedDefines.h"
+#include "Common.h"
+
+struct FlyByCamera
+{
+ uint32 timeStamp;
+ G3D::Vector4 locations;
+};
+
+typedef std::vector<FlyByCamera> FlyByCameraCollection;
+
+TC_GAME_API extern std::unordered_map<uint32, FlyByCameraCollection> sFlyByCameraStore;
+
+TC_GAME_API void LoadM2Cameras(std::string const& dataPath);
+
+#endif \ No newline at end of file
diff --git a/src/server/game/DataStores/M2Structure.h b/src/server/game/DataStores/M2Structure.h
new file mode 100644
index 00000000000..43e8d008b9f
--- /dev/null
+++ b/src/server/game/DataStores/M2Structure.h
@@ -0,0 +1,133 @@
+/*
+* 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_M2STRUCTURE_H
+#define TRINITY_M2STRUCTURE_H
+
+#include <G3D/Vector3.h>
+#include <G3D/AABox.h>
+
+// Structures for M2 file. Source: https://wowdev.wiki
+#pragma pack(push, 1)
+template<typename T>
+struct M2SplineKey
+{
+ T p0;
+ T p1;
+ T p2;
+};
+
+struct M2Header
+{
+ char Magic[4]; // "MD20"
+ uint32 Version; // The version of the format.
+ uint32 lName; // Length of the model's name including the trailing \0
+ uint32 ofsName; // Offset to the name, it seems like models can get reloaded by this name.should be unique, i guess.
+ uint32 GlobalModelFlags; // 0x0001: tilt x, 0x0002: tilt y, 0x0008: add 2 fields in header, 0x0020: load .phys data (MoP+), 0x0080: has _lod .skin files (MoP?+), 0x0100: is camera related.
+ uint32 nGlobalSequences;
+ uint32 ofsGlobalSequences; // A list of timestamps.
+ uint32 nAnimations;
+ uint32 ofsAnimations; // Information about the animations in the model.
+ uint32 nAnimationLookup;
+ uint32 ofsAnimationLookup; // Mapping of global IDs to the entries in the Animation sequences block.
+ uint32 nBones; // MAX_BONES = 0x100
+ uint32 ofsBones; // Information about the bones in this model.
+ uint32 nKeyBoneLookup;
+ uint32 ofsKeyBoneLookup; // Lookup table for key skeletal bones.
+ uint32 nVertices;
+ uint32 ofsVertices; // Vertices of the model.
+ uint32 nViews; // Views (LOD) are now in .skins.
+ uint32 nSubmeshAnimations;
+ uint32 ofsSubmeshAnimations; // Submesh color and alpha animations definitions.
+ uint32 nTextures;
+ uint32 ofsTextures; // Textures of this model.
+ uint32 nTransparency;
+ uint32 ofsTransparency; // Transparency of textures.
+ uint32 nUVAnimation;
+ uint32 ofsUVAnimation;
+ uint32 nTexReplace;
+ uint32 ofsTexReplace; // Replaceable Textures.
+ uint32 nRenderFlags;
+ uint32 ofsRenderFlags; // Blending modes / render flags.
+ uint32 nBoneLookupTable;
+ uint32 ofsBoneLookupTable; // A bone lookup table.
+ uint32 nTexLookup;
+ uint32 ofsTexLookup; // The same for textures.
+ uint32 nTexUnits; // possibly removed with cata?!
+ uint32 ofsTexUnits; // And texture units. Somewhere they have to be too.
+ uint32 nTransLookup;
+ uint32 ofsTransLookup; // Everything needs its lookup. Here are the transparencies.
+ uint32 nUVAnimLookup;
+ uint32 ofsUVAnimLookup;
+ G3D::AABox BoundingBox; // min/max( [1].z, 2.0277779f ) - 0.16f seems to be the maximum camera height
+ float BoundingSphereRadius;
+ G3D::AABox CollisionBox;
+ float CollisionSphereRadius;
+ uint32 nBoundingTriangles;
+ uint32 ofsBoundingTriangles; // Our bounding volumes. Similar structure like in the old ofsViews.
+ uint32 nBoundingVertices;
+ uint32 ofsBoundingVertices;
+ uint32 nBoundingNormals;
+ uint32 ofsBoundingNormals;
+ uint32 nAttachments;
+ uint32 ofsAttachments; // Attachments are for weapons etc.
+ uint32 nAttachLookup;
+ uint32 ofsAttachLookup; // Of course with a lookup.
+ uint32 nEvents;
+ uint32 ofsEvents; // Used for playing sounds when dying and a lot else.
+ uint32 nLights;
+ uint32 ofsLights; // Lights are mainly used in loginscreens but in wands and some doodads too.
+ uint32 nCameras; // Format of Cameras changed with version 271!
+ uint32 ofsCameras; // The cameras are present in most models for having a model in the Character-Tab.
+ uint32 nCameraLookup;
+ uint32 ofsCameraLookup; // And lookup-time again.
+ uint32 nRibbonEmitters;
+ uint32 ofsRibbonEmitters; // Things swirling around. See the CoT-entrance for light-trails.
+ uint32 nParticleEmitters;
+ uint32 ofsParticleEmitters; // Spells and weapons, doodads and loginscreens use them. Blood dripping of a blade? Particles.
+ uint32 nBlendMaps; // This has to deal with blending. Exists IFF (flags & 0x8) != 0. When set, textures blending is overriden by the associated array. See M2/WotLK#Blend_mode_overrides
+ uint32 ofsBlendMaps; // Same as above. Points to an array of uint16 of nBlendMaps entries -- From WoD information.};
+};
+
+struct M2Array
+{
+ uint32_t number;
+ uint32 offset_elements;
+};
+struct M2Track
+{
+ uint16_t interpolation_type;
+ uint16_t global_sequence;
+ M2Array timestamps;
+ M2Array values;
+};
+
+struct M2Camera
+{
+ uint32_t type; // 0: portrait, 1: characterinfo; -1: else (flyby etc.); referenced backwards in the lookup table.
+ float fov; // No radians, no degrees. Multiply by 35 to get degrees.
+ float far_clip;
+ float near_clip;
+ M2Track positions; // How the camera's position moves. Should be 3*3 floats.
+ G3D::Vector3 position_base;
+ M2Track target_positions; // How the target moves. Should be 3*3 floats.
+ G3D::Vector3 target_position_base;
+ M2Track rolldata; // The camera can have some roll-effect. Its 0 to 2*Pi.
+};
+#pragma pack(pop)
+
+#endif \ No newline at end of file
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 45952ba51ac..a2f519a681c 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -1471,7 +1471,7 @@ float WorldObject::GetGridActivationRange() const
{
if (ToPlayer())
{
- if (ToPlayer()->IsOnCinematic())
+ if (ToPlayer()->GetCinematicMgr()->IsOnCinematic())
return DEFAULT_VISIBILITY_INSTANCE;
return GetMap()->GetVisibilityRange();
}
@@ -1504,7 +1504,7 @@ float WorldObject::GetSightRange(const WorldObject* target) const
{
if (target && target->isActiveObject() && !target->ToPlayer())
return MAX_VISIBILITY_DISTANCE;
- else if (ToPlayer()->IsOnCinematic())
+ else if (ToPlayer()->GetCinematicMgr()->IsOnCinematic())
return DEFAULT_VISIBILITY_INSTANCE;
else
return GetMap()->GetVisibilityRange();
diff --git a/src/server/game/Entities/Player/CinematicMgr.cpp b/src/server/game/Entities/Player/CinematicMgr.cpp
new file mode 100644
index 00000000000..07bf733c9ff
--- /dev/null
+++ b/src/server/game/Entities/Player/CinematicMgr.cpp
@@ -0,0 +1,171 @@
+/*
+* Copyright (C) 2008-2016 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/>.
+*/
+
+#include "CinematicMgr.h"
+#include "Creature.h"
+#include "Player.h"
+#include "TemporarySummon.h"
+
+CinematicMgr::CinematicMgr(Player* playerref)
+{
+ player = playerref;
+ m_cinematicDiff = 0;
+ m_lastCinematicCheck = 0;
+ m_activeCinematicCameraId = 0;
+ m_cinematicCamera = nullptr;
+ m_remoteSightPosition = Position(0.0f, 0.0f, 0.0f);
+ m_CinematicObject = nullptr;
+}
+
+CinematicMgr::~CinematicMgr()
+{
+ if (m_cinematicCamera && m_activeCinematicCameraId)
+ EndCinematic();
+}
+
+void CinematicMgr::BeginCinematic()
+{
+ // Sanity check for active camera set
+ if (m_activeCinematicCameraId == 0)
+ return;
+
+ auto itr = sFlyByCameraStore.find(m_activeCinematicCameraId);
+ if (itr != sFlyByCameraStore.end())
+ {
+ // Initialize diff, and set camera
+ m_cinematicDiff = 0;
+ m_cinematicCamera = &itr->second;
+
+ auto camitr = m_cinematicCamera->begin();
+ if (camitr != m_cinematicCamera->end())
+ {
+ Position pos(camitr->locations.x, camitr->locations.y, camitr->locations.z, camitr->locations.w);
+ if (!pos.IsPositionValid())
+ return;
+
+ player->GetMap()->LoadGrid(camitr->locations.x, camitr->locations.y);
+ m_CinematicObject = player->SummonCreature(VISUAL_WAYPOINT, pos.m_positionX, pos.m_positionY, pos.m_positionZ, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 5 * MINUTE * IN_MILLISECONDS);
+ if (m_CinematicObject)
+ {
+ m_CinematicObject->setActive(true);
+ player->SetViewpoint(m_CinematicObject, true);
+ }
+
+ // Get cinematic length
+ FlyByCameraCollection::const_reverse_iterator camrevitr = m_cinematicCamera->rbegin();
+ if (camrevitr != m_cinematicCamera->rend())
+ m_cinematicLength = camrevitr->timeStamp;
+ }
+ }
+}
+
+void CinematicMgr::EndCinematic()
+{
+ if (m_activeCinematicCameraId == 0)
+ return;
+
+ m_cinematicDiff = 0;
+ m_cinematicCamera = nullptr;
+ m_activeCinematicCameraId = 0;
+ if (m_CinematicObject)
+ {
+ if (WorldObject* vpObject = player->GetViewpoint())
+ if (vpObject == m_CinematicObject)
+ player->SetViewpoint(m_CinematicObject, false);
+
+ m_CinematicObject->AddObjectToRemoveList();
+ }
+}
+
+void CinematicMgr::UpdateCinematicLocation(uint32 /*diff*/)
+{
+ if (m_activeCinematicCameraId == 0 || !m_cinematicCamera || m_cinematicCamera->size() == 0)
+ return;
+
+ Position lastPosition;
+ uint32 lastTimestamp = 0;
+ Position nextPosition;
+ uint32 nextTimestamp = 0;
+
+ // Obtain direction of travel
+ for (FlyByCamera cam : *m_cinematicCamera)
+ {
+ if (cam.timeStamp > m_cinematicDiff)
+ {
+ nextPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w);
+ nextTimestamp = cam.timeStamp;
+ break;
+ }
+ lastPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w);
+ lastTimestamp = cam.timeStamp;
+ }
+ float angle = lastPosition.GetAngle(&nextPosition);
+ angle -= lastPosition.GetOrientation();
+ if (angle < 0)
+ angle += 2 * float(M_PI);
+
+ // Look for position around 2 second ahead of us.
+ int32 workDiff = m_cinematicDiff;
+
+ // Modify result based on camera direction (Humans for example, have the camera point behind)
+ workDiff += static_cast<int32>(float(CINEMATIC_LOOKAHEAD) * cos(angle));
+
+ // Get an iterator to the last entry in the cameras, to make sure we don't go beyond the end
+ FlyByCameraCollection::const_reverse_iterator endItr = m_cinematicCamera->rbegin();
+ if (endItr != m_cinematicCamera->rend() && workDiff > static_cast<int32>(endItr->timeStamp))
+ workDiff = endItr->timeStamp;
+
+ // Never try to go back in time before the start of cinematic!
+ if (workDiff < 0)
+ workDiff = m_cinematicDiff;
+
+ // Obtain the previous and next waypoint based on timestamp
+ for (FlyByCamera cam : *m_cinematicCamera)
+ {
+ if (static_cast<int32>(cam.timeStamp) >= workDiff)
+ {
+ nextPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w);
+ nextTimestamp = cam.timeStamp;
+ break;
+ }
+ lastPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w);
+ lastTimestamp = cam.timeStamp;
+ }
+
+ // Never try to go beyond the end of the cinematic
+ if (workDiff > static_cast<int32>(nextTimestamp))
+ workDiff = static_cast<int32>(nextTimestamp);
+
+ // Interpolate the position for this moment in time (or the adjusted moment in time)
+ uint32 timeDiff = nextTimestamp - lastTimestamp;
+ uint32 interDiff = workDiff - lastTimestamp;
+ float xDiff = nextPosition.m_positionX - lastPosition.m_positionX;
+ float yDiff = nextPosition.m_positionY - lastPosition.m_positionY;
+ float zDiff = nextPosition.m_positionZ - lastPosition.m_positionZ;
+ Position interPosition(lastPosition.m_positionX + (xDiff * (float(interDiff) / float(timeDiff))), lastPosition.m_positionY +
+ (yDiff * (float(interDiff) / float(timeDiff))), lastPosition.m_positionZ + (zDiff * (float(interDiff) / float(timeDiff))));
+
+ // Advance (at speed) to this position. The remote sight object is used
+ // to send update information to player in cinematic
+ if (m_CinematicObject && interPosition.IsPositionValid())
+ m_CinematicObject->MonsterMoveWithSpeed(interPosition.m_positionX, interPosition.m_positionY, interPosition.m_positionZ, 500.0f, false, true);
+
+ // If we never received an end packet 10 seconds after the final timestamp then force an end
+ if (m_cinematicDiff > m_cinematicLength + 10 * IN_MILLISECONDS)
+ EndCinematic();
+}
diff --git a/src/server/game/Entities/Player/CinematicMgr.h b/src/server/game/Entities/Player/CinematicMgr.h
new file mode 100644
index 00000000000..ab067afa042
--- /dev/null
+++ b/src/server/game/Entities/Player/CinematicMgr.h
@@ -0,0 +1,60 @@
+/*
+* Copyright (C) 2008-2016 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 CinematicMgr_h__
+#define CinematicMgr_h__
+
+#include "Define.h"
+#include "Object.h"
+#include "M2Stores.h"
+
+#define CINEMATIC_LOOKAHEAD (2 * IN_MILLISECONDS)
+#define CINEMATIC_UPDATEDIFF 500
+
+class Player;
+
+class TC_GAME_API CinematicMgr
+{
+ friend class Player;
+public:
+ explicit CinematicMgr(Player* playerref);
+ ~CinematicMgr();
+
+ // Cinematic camera data and remote sight functions
+ uint32 GetActiveCinematicCamera() const { return m_activeCinematicCameraId; }
+ void SetActiveCinematicCamera(uint32 cinematicCameraId = 0) { m_activeCinematicCameraId = cinematicCameraId; }
+ bool IsOnCinematic() const { return (m_cinematicCamera != nullptr); }
+ void BeginCinematic();
+ void EndCinematic();
+ void UpdateCinematicLocation(uint32 diff);
+
+private:
+ // Remote location information
+ Player* player;
+
+protected:
+ uint32 m_cinematicDiff;
+ uint32 m_lastCinematicCheck;
+ uint32 m_activeCinematicCameraId;
+ uint32 m_cinematicLength;
+ FlyByCameraCollection* m_cinematicCamera;
+ Position m_remoteSightPosition;
+ TempSummon* m_CinematicObject;
+};
+
+#endif \ No newline at end of file
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 281427a18f4..9ed101bf52e 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -96,9 +96,6 @@
#define SKILL_PERM_BONUS(x) int16(PAIR32_HIPART(x))
#define MAKE_SKILL_BONUS(t, p) MAKE_PAIR32(t, p)
-#define CINEMATIC_LOOKAHEAD (2 * IN_MILLISECONDS)
-#define CINEMATIC_UPDATEDIFF 500
-
enum CharacterFlags
{
CHARACTER_FLAG_NONE = 0x00000000,
@@ -529,12 +526,7 @@ Player::Player(WorldSession* session): Unit(true)
healthBeforeDuel = 0;
manaBeforeDuel = 0;
- m_cinematicDiff = 0;
- m_lastCinematicCheck = 0;
- m_activeCinematicCameraId = 0;
- m_cinematicCamera = nullptr;
- m_remoteSightPosition = Position(0.0f, 0.0f, 0.0f);
- m_CinematicObject = nullptr;
+ _cinematicMgr = new CinematicMgr(this);
m_achievementMgr = new AchievementMgr(this);
m_reputationMgr = new ReputationMgr(this);
@@ -1226,11 +1218,11 @@ void Player::Update(uint32 p_time)
}
// Update cinematic location, if 500ms have passed and we're doing a cinematic now.
- m_cinematicDiff += p_time;
- if (m_cinematicCamera && m_activeCinematicCameraId && GetMSTimeDiffToNow(m_lastCinematicCheck) > CINEMATIC_UPDATEDIFF)
+ _cinematicMgr->m_cinematicDiff += p_time;
+ if (_cinematicMgr->m_cinematicCamera && _cinematicMgr->m_activeCinematicCameraId && GetMSTimeDiffToNow(_cinematicMgr->m_lastCinematicCheck) > CINEMATIC_UPDATEDIFF)
{
- m_lastCinematicCheck = getMSTime();
- UpdateCinematicLocation(p_time);
+ _cinematicMgr->m_lastCinematicCheck = getMSTime();
+ _cinematicMgr->UpdateCinematicLocation(p_time);
}
//used to implement delayed far teleports
@@ -6398,13 +6390,13 @@ void Player::SendDirectMessage(WorldPacket const* data) const
m_session->SendPacket(data);
}
-void Player::SendCinematicStart(uint32 CinematicSequenceId)
+void Player::SendCinematicStart(uint32 CinematicSequenceId) const
{
WorldPacket data(SMSG_TRIGGER_CINEMATIC, 4);
data << uint32(CinematicSequenceId);
SendDirectMessage(&data);
- if (const CinematicSequencesEntry* sequence = sCinematicSequencesStore.LookupEntry(CinematicSequenceId))
- SetActiveCinematicCamera(sequence->cinematicCamera);
+ if (CinematicSequencesEntry const* sequence = sCinematicSequencesStore.LookupEntry(CinematicSequenceId))
+ _cinematicMgr->SetActiveCinematicCamera(sequence->cinematicCamera);
}
void Player::SendMovieStart(uint32 MovieId) const
@@ -26243,125 +26235,6 @@ float Player::GetCollisionHeight(bool mounted) const
}
}
-void Player::BeginCinematic()
-{
- // Sanity check for active camera set
- if (m_activeCinematicCameraId == 0)
- return;
-
- auto itr = sFlyByCameraStore.find(m_activeCinematicCameraId);
- if (itr != sFlyByCameraStore.end())
- {
- // Initialize diff, and set camera
- m_cinematicDiff = 0;
- m_cinematicCamera = &itr->second;
-
- auto camitr = m_cinematicCamera->begin();
- if (camitr != m_cinematicCamera->end())
- {
- Position pos(camitr->locations.x, camitr->locations.y, camitr->locations.z, camitr->locations.w);
- if (!pos.IsPositionValid())
- return;
-
- m_mapRef->LoadGrid(camitr->locations.x, camitr->locations.y);
- m_CinematicObject = SummonCreature(VISUAL_WAYPOINT, pos.m_positionX, pos.m_positionY, pos.m_positionZ, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 120000);
- if (m_CinematicObject)
- {
- m_CinematicObject->setActive(true);
- SetViewpoint(m_CinematicObject, true);
- }
- }
- }
-}
-
-void Player::EndCinematic()
-{
- m_cinematicDiff = 0;
- m_cinematicCamera = nullptr;
- m_activeCinematicCameraId = 0;
- if (m_CinematicObject)
- {
- if (m_seer && m_seer == m_CinematicObject)
- SetViewpoint(m_CinematicObject, false);
- m_CinematicObject->AddObjectToRemoveList();
- }
-}
-
-void Player::UpdateCinematicLocation(uint32 /*diff*/)
-{
- Position lastPosition;
- uint32 lastTimestamp = 0;
- Position nextPosition;
- uint32 nextTimestamp = 0;
-
- if (m_cinematicCamera->size() == 0)
- return;
-
- // Obtain direction of travel
- for (FlyByCamera cam : *m_cinematicCamera)
- {
- if (cam.timeStamp > m_cinematicDiff)
- {
- nextPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w);
- nextTimestamp = cam.timeStamp;
- break;
- }
- lastPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w);
- lastTimestamp = cam.timeStamp;
- }
- float angle = lastPosition.GetAngle(&nextPosition);
- angle -= lastPosition.GetOrientation();
- if (angle < 0)
- angle += 2 * float(M_PI);
-
- // Look for position around 2 second ahead of us.
- int32 workDiff = m_cinematicDiff;
-
- // Modify result based on camera direction (Humans for example, have the camera point behind)
- workDiff += static_cast<int32>(float(CINEMATIC_LOOKAHEAD) * cos(angle));
-
- // Get an iterator to the last entry in the cameras, to make sure we don't go beyond the end
- FlyByCameraCollection::const_reverse_iterator endItr = m_cinematicCamera->rbegin();
- if (endItr != m_cinematicCamera->rend() && workDiff > static_cast<int32>(endItr->timeStamp))
- workDiff = endItr->timeStamp;
-
- // Never try to go back in time before the start of cinematic!
- if (workDiff < 0)
- workDiff = m_cinematicDiff;
-
- // Obtain the previous and next waypoint based on timestamp
- for (FlyByCamera cam : *m_cinematicCamera)
- {
- if (static_cast<int32>(cam.timeStamp) >= workDiff)
- {
- nextPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w);
- nextTimestamp = cam.timeStamp;
- break;
- }
- lastPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w);
- lastTimestamp = cam.timeStamp;
- }
-
- // Never try to go beyond the end of the cinematic
- if (workDiff > static_cast<int32>(nextTimestamp))
- workDiff = static_cast<int32>(nextTimestamp);
-
- // Interpolate the position for this moment in time (or the adjusted moment in time)
- uint32 timeDiff = nextTimestamp - lastTimestamp;
- uint32 interDiff = workDiff - lastTimestamp;
- float xDiff = nextPosition.m_positionX - lastPosition.m_positionX;
- float yDiff = nextPosition.m_positionY - lastPosition.m_positionY;
- float zDiff = nextPosition.m_positionZ - lastPosition.m_positionZ;
- Position interPosition(lastPosition.m_positionX + (xDiff * (float(interDiff)/float(timeDiff))), lastPosition.m_positionY +
- (yDiff * (float(interDiff) / float(timeDiff))), lastPosition.m_positionZ + (zDiff * (float(interDiff) / float(timeDiff))));
-
- // Advance (at speed) to this position. The remote sight object is used
- // to send update information to player in cinematic
- if (m_CinematicObject && interPosition.IsPositionValid())
- m_CinematicObject->MonsterMoveWithSpeed(interPosition.m_positionX, interPosition.m_positionY, interPosition.m_positionZ, 200.0f, false, true);
-}
-
-
std::string Player::GetMapAreaAndZoneString() const
{
uint32 areaId = GetAreaId();
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 7657c0d4b7f..372a49b4f9d 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -30,6 +30,7 @@
#include "SpellHistory.h"
#include "Unit.h"
#include "TradeData.h"
+#include "CinematicMgr.h"
#include <limits>
#include <string>
@@ -1026,6 +1027,7 @@ struct ResurrectionData
class TC_GAME_API Player : public Unit, public GridObject<Player>
{
friend class WorldSession;
+ friend class CinematicMgr;
friend void Item::AddToUpdateQueueOf(Player* player);
friend void Item::RemoveFromUpdateQueueOf(Player* player);
public:
@@ -1274,6 +1276,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
TradeData* GetTradeData() const { return m_trade; }
void TradeCancel(bool sendback);
+ CinematicMgr* GetCinematicMgr() const { return _cinematicMgr; }
+
void UpdateEnchantTime(uint32 time);
void UpdateSoulboundTradeItems();
void AddTradeableItem(Item* item);
@@ -2129,7 +2133,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void ResummonPetTemporaryUnSummonedIfAny();
bool IsPetNeedBeTemporaryUnsummoned() const;
- void SendCinematicStart(uint32 CinematicSequenceId);
+ void SendCinematicStart(uint32 CinematicSequenceId) const;
void SendMovieStart(uint32 MovieId) const;
uint32 DoRandomRoll(uint32 minimum, uint32 maximum);
@@ -2267,17 +2271,6 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
std::string GetMapAreaAndZoneString() const;
std::string GetCoordsMapAreaAndZoneString() const;
- // Cinematic camera data and remote sight functions
- uint32 GetActiveCinematicCamera() const { return m_activeCinematicCameraId; }
- void SetActiveCinematicCamera(uint32 cinematicCameraId = 0) { m_activeCinematicCameraId = cinematicCameraId; }
- bool IsOnCinematic() const { return (m_cinematicCamera != nullptr); }
- void BeginCinematic();
- void EndCinematic();
- void UpdateCinematicLocation(uint32 diff);
-
- std::string GetMapAreaAndZoneString();
- std::string GetCoordsMapAreaAndZoneString();
-
protected:
// Gamemaster whisper whitelist
GuidList WhisperList;
@@ -2537,6 +2530,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
Item* _StoreItem(uint16 pos, Item* pItem, uint32 count, bool clone, bool update);
Item* _LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, Field* fields);
+ CinematicMgr* _cinematicMgr;
+
GuidSet m_refundableItems;
void SendRefundInfo(Item* item);
void RefundItem(Item* item);
@@ -2603,14 +2598,6 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
uint32 manaBeforeDuel;
WorldLocation _corpseLocation;
-
- // Remote location information
- uint32 m_cinematicDiff;
- uint32 m_lastCinematicCheck;
- uint32 m_activeCinematicCameraId;
- FlyByCameraCollection* m_cinematicCamera;
- Position m_remoteSightPosition;
- Creature* m_CinematicObject;
};
TC_GAME_API void AddItemsSetItem(Player* player, Item* item);
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index 629c6f42d15..52b36d80202 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -1057,13 +1057,13 @@ void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recvData)
void WorldSession::HandleCompleteCinematic(WorldPacket& /*recvData*/)
{
// If player has sight bound to visual waypoint NPC we should remove it
- GetPlayer()->EndCinematic();
+ GetPlayer()->GetCinematicMgr()->EndCinematic();
}
void WorldSession::HandleNextCinematicCamera(WorldPacket& /*recvData*/)
{
// Sent by client when cinematic actually begun. So we begin the server side process
- GetPlayer()->BeginCinematic();
+ GetPlayer()->GetCinematicMgr()->BeginCinematic();
}
void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket& recvData)
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 6bef94cc379..d84fe11383f 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -66,7 +66,7 @@
#include "WaypointMovementGenerator.h"
#include "WeatherMgr.h"
#include "WorldSession.h"
-
+#include "M2Stores.h"
TC_GAME_API std::atomic<bool> World::m_stopEvent(false);
TC_GAME_API uint8 World::m_ExitCode = SHUTDOWN_EXIT_CODE;
@@ -1404,6 +1404,9 @@ void World::SetInitialWorldSettings()
LoadDBCStores(m_dataPath);
DetectDBCLang();
+ // Load cinematic cameras
+ LoadM2Cameras(m_dataPath);
+
std::vector<uint32> mapIds;
for (uint32 mapId = 0; mapId < sMapStore.GetNumRows(); mapId++)
if (sMapStore.LookupEntry(mapId))
diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp
index b6120c3044f..ca4dd814e01 100644
--- a/src/server/scripts/Commands/cs_debug.cpp
+++ b/src/server/scripts/Commands/cs_debug.cpp
@@ -34,6 +34,7 @@ EndScriptData */
#include "Transport.h"
#include "Language.h"
#include "MapManager.h"
+#include "M2Stores.h"
#include <fstream>
diff --git a/src/server/shared/DataStores/DBCStore.h b/src/server/shared/DataStores/DBCStore.h
index 7c2cab1e36a..b93bbdaea12 100644
--- a/src/server/shared/DataStores/DBCStore.h
+++ b/src/server/shared/DataStores/DBCStore.h
@@ -25,121 +25,6 @@
#include "DatabaseWorkerPool.h"
#include "Implementation/WorldDatabase.h"
#include "DatabaseEnv.h"
-#include <G3D/Vector3.h>
-#include <G3D/AABox.h>
-
- // Structures for M4 file. Source: https://wowdev.wiki
-template<typename T>
-struct M2SplineKey
-{
- T p0;
- T p1;
- T p2;
-};
-
-struct M2Header
-{
- char Magic[4]; // "MD20"
- uint32 Version; // The version of the format.
- uint32 lName; // Length of the model's name including the trailing \0
- uint32 ofsName; // Offset to the name, it seems like models can get reloaded by this name.should be unique, i guess.
- uint32 GlobalModelFlags; // 0x0001: tilt x, 0x0002: tilt y, 0x0008: add 2 fields in header, 0x0020: load .phys data (MoP+), 0x0080: has _lod .skin files (MoP?+), 0x0100: is camera related.
- uint32 nGlobalSequences;
- uint32 ofsGlobalSequences; // A list of timestamps.
- uint32 nAnimations;
- uint32 ofsAnimations; // Information about the animations in the model.
- uint32 nAnimationLookup;
- uint32 ofsAnimationLookup; // Mapping of global IDs to the entries in the Animation sequences block.
- uint32 nBones; // MAX_BONES = 0x100
- uint32 ofsBones; // Information about the bones in this model.
- uint32 nKeyBoneLookup;
- uint32 ofsKeyBoneLookup; // Lookup table for key skeletal bones.
- uint32 nVertices;
- uint32 ofsVertices; // Vertices of the model.
- uint32 nViews; // Views (LOD) are now in .skins.
- uint32 nSubmeshAnimations;
- uint32 ofsSubmeshAnimations; // Submesh color and alpha animations definitions.
- uint32 nTextures;
- uint32 ofsTextures; // Textures of this model.
- uint32 nTransparency;
- uint32 ofsTransparency; // Transparency of textures.
- uint32 nUVAnimation;
- uint32 ofsUVAnimation;
- uint32 nTexReplace;
- uint32 ofsTexReplace; // Replaceable Textures.
- uint32 nRenderFlags;
- uint32 ofsRenderFlags; // Blending modes / render flags.
- uint32 nBoneLookupTable;
- uint32 ofsBoneLookupTable; // A bone lookup table.
- uint32 nTexLookup;
- uint32 ofsTexLookup; // The same for textures.
- uint32 nTexUnits; // possibly removed with cata?!
- uint32 ofsTexUnits; // And texture units. Somewhere they have to be too.
- uint32 nTransLookup;
- uint32 ofsTransLookup; // Everything needs its lookup. Here are the transparencies.
- uint32 nUVAnimLookup;
- uint32 ofsUVAnimLookup;
- G3D::AABox BoundingBox; // min/max( [1].z, 2.0277779f ) - 0.16f seems to be the maximum camera height
- float BoundingSphereRadius;
- G3D::AABox CollisionBox;
- float CollisionSphereRadius;
- uint32 nBoundingTriangles;
- uint32 ofsBoundingTriangles; // Our bounding volumes. Similar structure like in the old ofsViews.
- uint32 nBoundingVertices;
- uint32 ofsBoundingVertices;
- uint32 nBoundingNormals;
- uint32 ofsBoundingNormals;
- uint32 nAttachments;
- uint32 ofsAttachments; // Attachments are for weapons etc.
- uint32 nAttachLookup;
- uint32 ofsAttachLookup; // Of course with a lookup.
- uint32 nEvents;
- uint32 ofsEvents; // Used for playing sounds when dying and a lot else.
- uint32 nLights;
- uint32 ofsLights; // Lights are mainly used in loginscreens but in wands and some doodads too.
- uint32 nCameras; // Format of Cameras changed with version 271!
- uint32 ofsCameras; // The cameras are present in most models for having a model in the Character-Tab.
- uint32 nCameraLookup;
- uint32 ofsCameraLookup; // And lookup-time again.
- uint32 nRibbonEmitters;
- uint32 ofsRibbonEmitters; // Things swirling around. See the CoT-entrance for light-trails.
- uint32 nParticleEmitters;
- uint32 ofsParticleEmitters; // Spells and weapons, doodads and loginscreens use them. Blood dripping of a blade? Particles.
- uint32 nBlendMaps; // This has to deal with blending. Exists IFF (flags & 0x8) != 0. When set, textures blending is overriden by the associated array. See M2/WotLK#Blend_mode_overrides
- uint32 ofsBlendMaps; // Same as above. Points to an array of uint16 of nBlendMaps entries -- From WoD information.};
-};
-
-struct M2Array
-{
- uint32_t number;
- uint32 offset_elements;
-};
-struct M2Track
-{
- uint16_t interpolation_type;
- uint16_t global_sequence;
- M2Array timestamps;
- M2Array values;
-};
-
-struct M2Camera
-{
- uint32_t type; // 0: portrait, 1: characterinfo; -1: else (flyby etc.); referenced backwards in the lookup table.
- float fov; // No radians, no degrees. Multiply by 35 to get degrees.
- float far_clip;
- float near_clip;
- M2Track positions; // How the camera's position moves. Should be 3*3 floats.
- G3D::Vector3 position_base;
- M2Track target_positions; // How the target moves. Should be 3*3 floats.
- G3D::Vector3 target_position_base;
- M2Track rolldata; // The camera can have some roll-effect. Its 0 to 2*Pi.
-};
-
-struct FlyByCamera
-{
- uint32 timeStamp;
- G3D::Vector4 locations;
-};
struct SqlDbc
{
diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp
index 1d84fc75d27..9d3dc47bce0 100644
--- a/src/tools/map_extractor/System.cpp
+++ b/src/tools/map_extractor/System.cpp
@@ -1041,7 +1041,7 @@ void ExtractCameraFiles(int locale, bool basicLocale)
std::vector<std::string> camerafiles;
size_t cam_count = camdbc.getRecordCount();
- for (uint32 i = 0; i < cam_count; ++i)
+ for (size_t i = 0; i < cam_count; ++i)
{
std::string camFile(camdbc.getRecord(i).getString(1));
size_t loc = camFile.find(".mdx");