diff options
-rw-r--r-- | src/server/game/DataStores/DBCEnums.h | 16 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCStores.cpp | 245 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCStores.h | 4 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCStructure.h | 12 | ||||
-rw-r--r-- | src/server/game/DataStores/M2Stores.cpp | 266 | ||||
-rw-r--r-- | src/server/game/DataStores/M2Stores.h | 36 | ||||
-rw-r--r-- | src/server/game/DataStores/M2Structure.h | 133 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Entities/Player/CinematicMgr.cpp | 171 | ||||
-rw-r--r-- | src/server/game/Entities/Player/CinematicMgr.h | 60 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 143 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 27 | ||||
-rw-r--r-- | src/server/game/Handlers/MiscHandler.cpp | 4 | ||||
-rw-r--r-- | src/server/game/World/World.cpp | 5 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_debug.cpp | 1 | ||||
-rw-r--r-- | src/server/shared/DataStores/DBCStore.h | 115 | ||||
-rw-r--r-- | src/tools/map_extractor/System.cpp | 2 |
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"); |