diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index ed7c0c7b2..6fccdc161 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -2,9 +2,9 @@ name: CI on: push: - branches: [ main ] + branches: [ main, RemoveEntityPointers ] pull_request: - branches: [ main ] + branches: [ main, RemoveEntityPointers ] jobs: build-and-test: @@ -13,7 +13,7 @@ jobs: continue-on-error: true strategy: matrix: - os: [ windows-2022, ubuntu-22.04, macos-11 ] + os: [ windows-2022, ubuntu-22.04, macos-13 ] steps: - uses: actions/checkout@v3 @@ -25,9 +25,12 @@ jobs: with: vs-version: '[17,18)' msbuild-architecture: x64 - - name: Install libssl (Mac Only) - if: ${{ matrix.os == 'macos-11' }} - run: brew install openssl@3 + - name: Install libssl and switch to XCode 15.2 (Mac Only) + if: ${{ matrix.os == 'macos-13' }} + run: | + brew install openssl@3 + sudo xcode-select -s /Applications/Xcode_15.2.app/Contents/Developer + - name: cmake uses: lukka/run-cmake@v10 with: diff --git a/CMakeLists.txt b/CMakeLists.txt index 09cbac97e..1b6a775e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,7 @@ project(Darkflame) include(CTest) set(CMAKE_CXX_STANDARD 20) +set(CXX_STANDARD_REQUIRED ON) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") # Read variables from file diff --git a/CMakePresets.json b/CMakePresets.json index 77b8b2429..a68cc241b 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -20,10 +20,11 @@ "inherits": "default" }, { - "name": "ci-macos-11", + "name": "ci-macos-13", "displayName": "CI configure step for MacOS", "description": "Same as default, Used in GitHub actions workflow", "inherits": "default" + }, { "name": "ci-windows-2022", @@ -74,8 +75,8 @@ "jobs": 2 }, { - "name": "ci-macos-11", - "configurePreset": "ci-macos-11", + "name": "ci-macos-13", + "configurePreset": "ci-macos-13", "displayName": "MacOS CI Build", "description": "This preset is used by the CI build on MacOS", "jobs": 2 @@ -95,8 +96,8 @@ } }, { - "name": "ci-macos-11", - "configurePreset": "ci-macos-11", + "name": "ci-macos-13", + "configurePreset": "ci-macos-13", "displayName": "CI Tests on MacOS", "description": "Runs all tests on a Mac configuration", "execution": { diff --git a/dCommon/NiPoint3.cpp b/dCommon/NiPoint3.cpp index 3394deb7d..b8546fdda 100644 --- a/dCommon/NiPoint3.cpp +++ b/dCommon/NiPoint3.cpp @@ -1,210 +1,24 @@ #include "NiPoint3.h" -#include "NiQuaternion.h" // C++ #include -// Static Variables -const NiPoint3 NiPoint3::ZERO(0.0f, 0.0f, 0.0f); -const NiPoint3 NiPoint3::UNIT_X(1.0f, 0.0f, 0.0f); -const NiPoint3 NiPoint3::UNIT_Y(0.0f, 1.0f, 0.0f); -const NiPoint3 NiPoint3::UNIT_Z(0.0f, 0.0f, 1.0f); -const NiPoint3 NiPoint3::UNIT_ALL(1.0f, 1.0f, 1.0f); - -//! Initializer -NiPoint3::NiPoint3(void) { - this->x = 0; - this->y = 0; - this->z = 0; -} - -//! Initializer -NiPoint3::NiPoint3(float x, float y, float z) { - this->x = x; - this->y = y; - this->z = z; -} - -//! Copy Constructor -NiPoint3::NiPoint3(const NiPoint3& point) { - this->x = point.x; - this->y = point.y; - this->z = point.z; -} - -//! Destructor -NiPoint3::~NiPoint3(void) {} - -// MARK: Getters / Setters - -//! Gets the X coordinate -float NiPoint3::GetX(void) const { - return this->x; -} - -//! Sets the X coordinate -void NiPoint3::SetX(float x) { - this->x = x; -} - -//! Gets the Y coordinate -float NiPoint3::GetY(void) const { - return this->y; -} - -//! Sets the Y coordinate -void NiPoint3::SetY(float y) { - this->y = y; -} - -//! Gets the Z coordinate -float NiPoint3::GetZ(void) const { - return this->z; -} - -//! Sets the Z coordinate -void NiPoint3::SetZ(float z) { - this->z = z; -} - -// MARK: Functions +// MARK: Member Functions //! Gets the length of the vector -float NiPoint3::Length(void) const { - return sqrt(x * x + y * y + z * z); -} - -//! Gets the squared length of a vector -float NiPoint3::SquaredLength(void) const { - return (x * x + y * y + z * z); -} - -//! Returns the dot product of the vector dotted with another vector -float NiPoint3::DotProduct(const Vector3& vec) const { - return ((this->x * vec.x) + (this->y * vec.y) + (this->z * vec.z)); -} - -//! Returns the cross product of the vector crossed with another vector -Vector3 NiPoint3::CrossProduct(const Vector3& vec) const { - return Vector3(((this->y * vec.z) - (this->z * vec.y)), - ((this->z * vec.x) - (this->x * vec.z)), - ((this->x * vec.y) - (this->y * vec.x))); +float NiPoint3::Length() const { + return std::sqrt(x * x + y * y + z * z); } //! Unitize the vector -NiPoint3 NiPoint3::Unitize(void) const { +NiPoint3 NiPoint3::Unitize() const { float length = this->Length(); - return length != 0 ? *this / length : NiPoint3::ZERO; + return length != 0 ? *this / length : NiPoint3Constant::ZERO; } - -// MARK: Operators - -//! Operator to check for equality -bool NiPoint3::operator==(const NiPoint3& point) const { - return point.x == this->x && point.y == this->y && point.z == this->z; -} - -//! Operator to check for inequality -bool NiPoint3::operator!=(const NiPoint3& point) const { - return !(*this == point); -} - -//! Operator for subscripting -float& NiPoint3::operator[](int i) { - float* base = &x; - return base[i]; -} - -//! Operator for subscripting -const float& NiPoint3::operator[](int i) const { - const float* base = &x; - return base[i]; -} - -//! Operator for addition of vectors -NiPoint3 NiPoint3::operator+(const NiPoint3& point) const { - return NiPoint3(this->x + point.x, this->y + point.y, this->z + point.z); -} - -//! Operator for addition of vectors -NiPoint3& NiPoint3::operator+=(const NiPoint3& point) { - this->x += point.x; - this->y += point.y; - this->z += point.z; - return *this; -} - -NiPoint3& NiPoint3::operator*=(const float scalar) { - this->x *= scalar; - this->y *= scalar; - this->z *= scalar; - return *this; -} - -//! Operator for subtraction of vectors -NiPoint3 NiPoint3::operator-(const NiPoint3& point) const { - return NiPoint3(this->x - point.x, this->y - point.y, this->z - point.z); -} - -//! Operator for addition of a scalar on all vector components -NiPoint3 NiPoint3::operator+(float fScalar) const { - return NiPoint3(this->x + fScalar, this->y + fScalar, this->z + fScalar); -} - -//! Operator for subtraction of a scalar on all vector components -NiPoint3 NiPoint3::operator-(float fScalar) const { - return NiPoint3(this->x - fScalar, this->y - fScalar, this->z - fScalar); -} - -//! Operator for scalar multiplication of a vector -NiPoint3 NiPoint3::operator*(float fScalar) const { - return NiPoint3(this->x * fScalar, this->y * fScalar, this->z * fScalar); -} - -//! Operator for scalar division of a vector -NiPoint3 NiPoint3::operator/(float fScalar) const { - float retX = this->x != 0 ? this->x / fScalar : 0; - float retY = this->y != 0 ? this->y / fScalar : 0; - float retZ = this->z != 0 ? this->z / fScalar : 0; - return NiPoint3(retX, retY, retZ); -} - - // MARK: Helper Functions -//! Checks to see if the point (or vector) is with an Axis-Aligned Bounding Box -bool NiPoint3::IsWithinAxisAlignedBox(const NiPoint3& minPoint, const NiPoint3& maxPoint) { - if (this->x < minPoint.x) return false; - if (this->x > maxPoint.x) return false; - if (this->y < minPoint.y) return false; - if (this->y > maxPoint.y) return false; - - return (this->z < maxPoint.z && this->z > minPoint.z); -} - -//! Checks to see if the point (or vector) is within a sphere -bool NiPoint3::IsWithinSpehere(const NiPoint3& sphereCenter, float radius) { - Vector3 diffVec = Vector3(x - sphereCenter.GetX(), y - sphereCenter.GetY(), z - sphereCenter.GetZ()); - return (diffVec.SquaredLength() <= (radius * radius)); -} - -NiPoint3 NiPoint3::ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p) { - if (a == b) return a; - - const auto pa = p - a; - const auto ab = b - a; - - const auto t = pa.DotProduct(ab) / ab.SquaredLength(); - - if (t <= 0.0f) return a; - - if (t >= 1.0f) return b; - - return a + ab * t; -} - float NiPoint3::Angle(const NiPoint3& a, const NiPoint3& b) { const auto dot = a.DotProduct(b); const auto lenA = a.SquaredLength(); @@ -220,15 +34,7 @@ float NiPoint3::Distance(const NiPoint3& a, const NiPoint3& b) { return std::sqrt(dx * dx + dy * dy + dz * dz); } -float NiPoint3::DistanceSquared(const NiPoint3& a, const NiPoint3& b) { - const auto dx = a.x - b.x; - const auto dy = a.y - b.y; - const auto dz = a.z - b.z; - - return dx * dx + dy * dy + dz * dz; -} - -NiPoint3 NiPoint3::MoveTowards(const NiPoint3& current, const NiPoint3& target, float maxDistanceDelta) { +NiPoint3 NiPoint3::MoveTowards(const NiPoint3& current, const NiPoint3& target, const float maxDistanceDelta) { float dx = target.x - current.x; float dy = target.y - current.y; float dz = target.z - current.z; @@ -249,29 +55,3 @@ NiPoint3 NiPoint3::MoveTowards(const NiPoint3& current, const NiPoint3& target, float length = std::sqrt(lengthSquared); return NiPoint3(current.x + dx / length * maxDistanceDelta, current.y + dy / length * maxDistanceDelta, current.z + dz / length * maxDistanceDelta); } - -//This code is yoinked from the MS XNA code, so it should be right, even if it's horrible. -NiPoint3 NiPoint3::RotateByQuaternion(const NiQuaternion& rotation) { - Vector3 vector; - float num12 = rotation.x + rotation.x; - float num2 = rotation.y + rotation.y; - float num = rotation.z + rotation.z; - float num11 = rotation.w * num12; - float num10 = rotation.w * num2; - float num9 = rotation.w * num; - float num8 = rotation.x * num12; - float num7 = rotation.x * num2; - float num6 = rotation.x * num; - float num5 = rotation.y * num2; - float num4 = rotation.y * num; - float num3 = rotation.z * num; - - NiPoint3 value = *this; - float num15 = ((value.x * ((1.0f - num5) - num3)) + (value.y * (num7 - num9))) + (value.z * (num6 + num10)); - float num14 = ((value.x * (num7 + num9)) + (value.y * ((1.0f - num8) - num3))) + (value.z * (num4 - num11)); - float num13 = ((value.x * (num6 - num10)) + (value.y * (num4 + num11))) + (value.z * ((1.0f - num8) - num5)); - vector.x = num15; - vector.y = num14; - vector.z = num13; - return vector; -} diff --git a/dCommon/NiPoint3.h b/dCommon/NiPoint3.h index 44c3c3830..546fa0662 100644 --- a/dCommon/NiPoint3.h +++ b/dCommon/NiPoint3.h @@ -1,4 +1,5 @@ -#pragma once +#ifndef __NIPOINT3_H__ +#define __NIPOINT3_H__ /*! \file NiPoint3.hpp @@ -12,13 +13,13 @@ typedef NiPoint3 Vector3; //!< The Vector3 class is technically the NiPoin //! A custom class the defines a point in space class NiPoint3 { public: - float x; //!< The x position - float y; //!< The y position - float z; //!< The z position + float x{ 0 }; //!< The x position + float y{ 0 }; //!< The y position + float z{ 0 }; //!< The z position //! Initializer - NiPoint3(void); + constexpr NiPoint3() = default; //! Initializer /*! @@ -26,23 +27,21 @@ class NiPoint3 { \param y The y coordinate \param z The z coordinate */ - NiPoint3(float x, float y, float z); + constexpr NiPoint3(const float x, const float y, const float z) noexcept + : x{ x } + , y{ y } + , z{ z } { + } //! Copy Constructor /*! \param point The point to copy */ - NiPoint3(const NiPoint3& point); - - //! Destructor - ~NiPoint3(void); - - // MARK: Constants - static const NiPoint3 ZERO; //!< Point(0, 0, 0) - static const NiPoint3 UNIT_X; //!< Point(1, 0, 0) - static const NiPoint3 UNIT_Y; //!< Point(0, 1, 0) - static const NiPoint3 UNIT_Z; //!< Point(0, 0, 1) - static const NiPoint3 UNIT_ALL; //!< Point(1, 1, 1) + constexpr NiPoint3(const NiPoint3& point) noexcept + : x{ point.x } + , y{ point.y } + , z{ point.z } { + } // MARK: Getters / Setters @@ -50,38 +49,37 @@ class NiPoint3 { /*! \return The x coordinate */ - float GetX(void) const; + constexpr float GetX() const noexcept; //! Sets the X coordinate /*! \param x The x coordinate */ - void SetX(float x); + constexpr void SetX(const float x) noexcept; //! Gets the Y coordinate /*! \return The y coordinate */ - float GetY(void) const; + constexpr float GetY() const noexcept; //! Sets the Y coordinate /*! \param y The y coordinate */ - void SetY(float y); + constexpr void SetY(const float y) noexcept; //! Gets the Z coordinate /*! \return The z coordinate */ - float GetZ(void) const; + constexpr float GetZ() const noexcept; //! Sets the Z coordinate /*! \param z The z coordinate */ - void SetZ(float z); - + constexpr void SetZ(const float z) noexcept; // MARK: Member Functions @@ -89,72 +87,70 @@ class NiPoint3 { /*! \return The scalar length of the vector */ - float Length(void) const; + float Length() const; //! Gets the squared length of a vector /*! \return The squared length of a vector */ - float SquaredLength(void) const; + constexpr float SquaredLength() const noexcept; //! Returns the dot product of the vector dotted with another vector /*! \param vec The second vector \return The dot product of the two vectors */ - float DotProduct(const Vector3& vec) const; + constexpr float DotProduct(const Vector3& vec) const noexcept; //! Returns the cross product of the vector crossed with another vector /*! \param vec The second vector \return The cross product of the two vectors */ - Vector3 CrossProduct(const Vector3& vec) const; + constexpr Vector3 CrossProduct(const Vector3& vec) const noexcept; //! Unitize the vector /*! \returns The current vector */ - NiPoint3 Unitize(void) const; - + NiPoint3 Unitize() const; // MARK: Operators //! Operator to check for equality - bool operator==(const NiPoint3& point) const; + constexpr bool operator==(const NiPoint3& point) const noexcept; //! Operator to check for inequality - bool operator!=(const NiPoint3& point) const; + constexpr bool operator!=(const NiPoint3& point) const noexcept; //! Operator for subscripting - float& operator[](int i); + constexpr float& operator[](const int i) noexcept; //! Operator for subscripting - const float& operator[](int i) const; + constexpr const float& operator[](const int i) const noexcept; //! Operator for addition of vectors - NiPoint3 operator+(const NiPoint3& point) const; + constexpr NiPoint3 operator+(const NiPoint3& point) const noexcept; //! Operator for addition of vectors - NiPoint3& operator+=(const NiPoint3& point); + constexpr NiPoint3& operator+=(const NiPoint3& point) noexcept; - NiPoint3& operator*=(const float scalar); + constexpr NiPoint3& operator*=(const float scalar) noexcept; //! Operator for subtraction of vectors - NiPoint3 operator-(const NiPoint3& point) const; + constexpr NiPoint3 operator-(const NiPoint3& point) const noexcept; //! Operator for addition of a scalar on all vector components - NiPoint3 operator+(float fScalar) const; + constexpr NiPoint3 operator+(const float fScalar) const noexcept; //! Operator for subtraction of a scalar on all vector components - NiPoint3 operator-(float fScalar) const; + constexpr NiPoint3 operator-(const float fScalar) const noexcept; //! Operator for scalar multiplication of a vector - NiPoint3 operator*(float fScalar) const; + constexpr NiPoint3 operator*(const float fScalar) const noexcept; //! Operator for scalar division of a vector - NiPoint3 operator/(float fScalar) const; - + constexpr NiPoint3 operator/(const float fScalar) const noexcept; // MARK: Helper Functions @@ -164,14 +160,14 @@ class NiPoint3 { \param maxPoint The maximum point of the bounding box \return Whether or not this point lies within the box */ - bool IsWithinAxisAlignedBox(const NiPoint3& minPoint, const NiPoint3& maxPoint); + constexpr bool IsWithinAxisAlignedBox(const NiPoint3& minPoint, const NiPoint3& maxPoint) noexcept; //! Checks to see if the point (or vector) is within a sphere /*! \param sphereCenter The sphere center \param radius The radius */ - bool IsWithinSpehere(const NiPoint3& sphereCenter, float radius); + constexpr bool IsWithinSphere(const NiPoint3& sphereCenter, const float radius) noexcept; /*! \param a Start of line @@ -179,15 +175,30 @@ class NiPoint3 { \param p Refrence point \return The point of line AB which is closest to P */ - static NiPoint3 ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p); + static constexpr NiPoint3 ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p) noexcept; static float Angle(const NiPoint3& a, const NiPoint3& b); static float Distance(const NiPoint3& a, const NiPoint3& b); - static float DistanceSquared(const NiPoint3& a, const NiPoint3& b); + static constexpr float DistanceSquared(const NiPoint3& a, const NiPoint3& b) noexcept; - static NiPoint3 MoveTowards(const NiPoint3& current, const NiPoint3& target, float maxDistanceDelta); + static NiPoint3 MoveTowards(const NiPoint3& current, const NiPoint3& target, const float maxDistanceDelta); - NiPoint3 RotateByQuaternion(const NiQuaternion& rotation); + //This code is yoinked from the MS XNA code, so it should be right, even if it's horrible. + constexpr NiPoint3 RotateByQuaternion(const NiQuaternion& rotation) noexcept; }; + +// Static Variables +namespace NiPoint3Constant { + constexpr NiPoint3 ZERO(0.0f, 0.0f, 0.0f); + constexpr NiPoint3 UNIT_X(1.0f, 0.0f, 0.0f); + constexpr NiPoint3 UNIT_Y(0.0f, 1.0f, 0.0f); + constexpr NiPoint3 UNIT_Z(0.0f, 0.0f, 1.0f); + constexpr NiPoint3 UNIT_ALL(1.0f, 1.0f, 1.0f); +} + +// .inl file needed for code organization and to circumvent circular dependency issues +#include "NiPoint3.inl" + +#endif // !__NIPOINT3_H__ diff --git a/dCommon/NiPoint3.inl b/dCommon/NiPoint3.inl new file mode 100644 index 000000000..48aa3ae11 --- /dev/null +++ b/dCommon/NiPoint3.inl @@ -0,0 +1,196 @@ +#pragma once +#ifndef __NIPOINT3_H__ +#error "This should only be included inline in NiPoint3.h: Do not include directly!" +#endif + +#include "NiQuaternion.h" + +// MARK: Getters / Setters + +//! Gets the X coordinate +constexpr float NiPoint3::GetX() const noexcept { + return this->x; +} + +//! Sets the X coordinate +constexpr void NiPoint3::SetX(const float x) noexcept { + this->x = x; +} + +//! Gets the Y coordinate +constexpr float NiPoint3::GetY() const noexcept { + return this->y; +} + +//! Sets the Y coordinate +constexpr void NiPoint3::SetY(const float y) noexcept { + this->y = y; +} + +//! Gets the Z coordinate +constexpr float NiPoint3::GetZ() const noexcept { + return this->z; +} + +//! Sets the Z coordinate +constexpr void NiPoint3::SetZ(const float z) noexcept { + this->z = z; +} + +// MARK: Member Functions + +//! Gets the squared length of a vector +constexpr float NiPoint3::SquaredLength() const noexcept { + return (x * x + y * y + z * z); +} + +//! Returns the dot product of the vector dotted with another vector +constexpr float NiPoint3::DotProduct(const Vector3& vec) const noexcept { + return ((this->x * vec.x) + (this->y * vec.y) + (this->z * vec.z)); +} + +//! Returns the cross product of the vector crossed with another vector +constexpr Vector3 NiPoint3::CrossProduct(const Vector3& vec) const noexcept { + return Vector3(((this->y * vec.z) - (this->z * vec.y)), + ((this->z * vec.x) - (this->x * vec.z)), + ((this->x * vec.y) - (this->y * vec.x))); +} + +// MARK: Operators + +//! Operator to check for equality +constexpr bool NiPoint3::operator==(const NiPoint3& point) const noexcept { + return point.x == this->x && point.y == this->y && point.z == this->z; +} + +//! Operator to check for inequality +constexpr bool NiPoint3::operator!=(const NiPoint3& point) const noexcept { + return !(*this == point); +} + +//! Operator for subscripting +constexpr float& NiPoint3::operator[](const int i) noexcept { + float* base = &x; + return base[i]; +} + +//! Operator for subscripting +constexpr const float& NiPoint3::operator[](const int i) const noexcept { + const float* base = &x; + return base[i]; +} + +//! Operator for addition of vectors +constexpr NiPoint3 NiPoint3::operator+(const NiPoint3& point) const noexcept { + return NiPoint3(this->x + point.x, this->y + point.y, this->z + point.z); +} + +//! Operator for addition of vectors +constexpr NiPoint3& NiPoint3::operator+=(const NiPoint3& point) noexcept { + this->x += point.x; + this->y += point.y; + this->z += point.z; + return *this; +} + +constexpr NiPoint3& NiPoint3::operator*=(const float scalar) noexcept { + this->x *= scalar; + this->y *= scalar; + this->z *= scalar; + return *this; +} + +//! Operator for subtraction of vectors +constexpr NiPoint3 NiPoint3::operator-(const NiPoint3& point) const noexcept { + return NiPoint3(this->x - point.x, this->y - point.y, this->z - point.z); +} + +//! Operator for addition of a scalar on all vector components +constexpr NiPoint3 NiPoint3::operator+(const float fScalar) const noexcept { + return NiPoint3(this->x + fScalar, this->y + fScalar, this->z + fScalar); +} + +//! Operator for subtraction of a scalar on all vector components +constexpr NiPoint3 NiPoint3::operator-(const float fScalar) const noexcept { + return NiPoint3(this->x - fScalar, this->y - fScalar, this->z - fScalar); +} + +//! Operator for scalar multiplication of a vector +constexpr NiPoint3 NiPoint3::operator*(const float fScalar) const noexcept { + return NiPoint3(this->x * fScalar, this->y * fScalar, this->z * fScalar); +} + +//! Operator for scalar division of a vector +constexpr NiPoint3 NiPoint3::operator/(const float fScalar) const noexcept { + float retX = this->x != 0 ? this->x / fScalar : 0; + float retY = this->y != 0 ? this->y / fScalar : 0; + float retZ = this->z != 0 ? this->z / fScalar : 0; + return NiPoint3(retX, retY, retZ); +} + +// MARK: Helper Functions + +//! Checks to see if the point (or vector) is with an Axis-Aligned Bounding Box +constexpr bool NiPoint3::IsWithinAxisAlignedBox(const NiPoint3& minPoint, const NiPoint3& maxPoint) noexcept { + if (this->x < minPoint.x) return false; + if (this->x > maxPoint.x) return false; + if (this->y < minPoint.y) return false; + if (this->y > maxPoint.y) return false; + + return (this->z < maxPoint.z && this->z > minPoint.z); +} + +//! Checks to see if the point (or vector) is within a sphere +constexpr bool NiPoint3::IsWithinSphere(const NiPoint3& sphereCenter, const float radius) noexcept { + Vector3 diffVec = Vector3(x - sphereCenter.GetX(), y - sphereCenter.GetY(), z - sphereCenter.GetZ()); + return (diffVec.SquaredLength() <= (radius * radius)); +} + +constexpr NiPoint3 NiPoint3::ClosestPointOnLine(const NiPoint3& a, const NiPoint3& b, const NiPoint3& p) noexcept { + if (a == b) return a; + + const auto pa = p - a; + const auto ab = b - a; + + const auto t = pa.DotProduct(ab) / ab.SquaredLength(); + + if (t <= 0.0f) return a; + + if (t >= 1.0f) return b; + + return a + ab * t; +} + +constexpr float NiPoint3::DistanceSquared(const NiPoint3& a, const NiPoint3& b) noexcept { + const auto dx = a.x - b.x; + const auto dy = a.y - b.y; + const auto dz = a.z - b.z; + + return dx * dx + dy * dy + dz * dz; +} + +//This code is yoinked from the MS XNA code, so it should be right, even if it's horrible. +constexpr NiPoint3 NiPoint3::RotateByQuaternion(const NiQuaternion& rotation) noexcept { + Vector3 vector; + float num12 = rotation.x + rotation.x; + float num2 = rotation.y + rotation.y; + float num = rotation.z + rotation.z; + float num11 = rotation.w * num12; + float num10 = rotation.w * num2; + float num9 = rotation.w * num; + float num8 = rotation.x * num12; + float num7 = rotation.x * num2; + float num6 = rotation.x * num; + float num5 = rotation.y * num2; + float num4 = rotation.y * num; + float num3 = rotation.z * num; + + NiPoint3 value = *this; + float num15 = ((value.x * ((1.0f - num5) - num3)) + (value.y * (num7 - num9))) + (value.z * (num6 + num10)); + float num14 = ((value.x * (num7 + num9)) + (value.y * ((1.0f - num8) - num3))) + (value.z * (num4 - num11)); + float num13 = ((value.x * (num6 - num10)) + (value.y * (num4 + num11))) + (value.z * ((1.0f - num8) - num5)); + vector.x = num15; + vector.y = num14; + vector.z = num13; + return vector; +} diff --git a/dCommon/NiQuaternion.cpp b/dCommon/NiQuaternion.cpp index 33c5c9766..b12d39913 100644 --- a/dCommon/NiQuaternion.cpp +++ b/dCommon/NiQuaternion.cpp @@ -3,89 +3,8 @@ // C++ #include -// Static Variables -const NiQuaternion NiQuaternion::IDENTITY(1, 0, 0, 0); - -//! The initializer -NiQuaternion::NiQuaternion(void) { - this->w = 1; - this->x = 0; - this->y = 0; - this->z = 0; -} - -//! The initializer -NiQuaternion::NiQuaternion(float w, float x, float y, float z) { - this->w = w; - this->x = x; - this->y = y; - this->z = z; -} - -//! Destructor -NiQuaternion::~NiQuaternion(void) {} - - -// MARK: Setters / Getters - -//! Gets the W coordinate -float NiQuaternion::GetW(void) const { - return this->w; -} - -//! Sets the W coordinate -void NiQuaternion::SetW(float w) { - this->w = w; -} - -//! Gets the X coordinate -float NiQuaternion::GetX(void) const { - return this->x; -} - -//! Sets the X coordinate -void NiQuaternion::SetX(float x) { - this->x = x; -} - -//! Gets the Y coordinate -float NiQuaternion::GetY(void) const { - return this->y; -} - -//! Sets the Y coordinate -void NiQuaternion::SetY(float y) { - this->y = y; -} - -//! Gets the Z coordinate -float NiQuaternion::GetZ(void) const { - return this->z; -} - -//! Sets the Z coordinate -void NiQuaternion::SetZ(float z) { - this->z = z; -} - - // MARK: Member Functions -//! Returns the forward vector from the quaternion -Vector3 NiQuaternion::GetForwardVector(void) const { - return Vector3(2 * (x * z + w * y), 2 * (y * z - w * x), 1 - 2 * (x * x + y * y)); -} - -//! Returns the up vector from the quaternion -Vector3 NiQuaternion::GetUpVector(void) const { - return Vector3(2 * (x * y - w * z), 1 - 2 * (x * x + z * z), 2 * (y * z + w * x)); -} - -//! Returns the right vector from the quaternion -Vector3 NiQuaternion::GetRightVector(void) const { - return Vector3(1 - 2 * (y * y + z * z), 2 * (x * y + w * z), 2 * (x * z - w * y)); -} - Vector3 NiQuaternion::GetEulerAngles() const { Vector3 angles; @@ -111,22 +30,9 @@ Vector3 NiQuaternion::GetEulerAngles() const { return angles; } -// MARK: Operators - -//! Operator to check for equality -bool NiQuaternion::operator==(const NiQuaternion& rot) const { - return rot.x == this->x && rot.y == this->y && rot.z == this->z && rot.w == this->w; -} - -//! Operator to check for inequality -bool NiQuaternion::operator!=(const NiQuaternion& rot) const { - return !(*this == rot); -} - - // MARK: Helper Functions -//! Look from a specific point in space to another point in space +//! Look from a specific point in space to another point in space (Y-locked) NiQuaternion NiQuaternion::LookAt(const NiPoint3& sourcePoint, const NiPoint3& destPoint) { //To make sure we don't orient around the X/Z axis: NiPoint3 source = sourcePoint; @@ -136,7 +42,7 @@ NiQuaternion NiQuaternion::LookAt(const NiPoint3& sourcePoint, const NiPoint3& d NiPoint3 forwardVector = NiPoint3(dest - source).Unitize(); - NiPoint3 posZ = NiPoint3::UNIT_Z; + NiPoint3 posZ = NiPoint3Constant::UNIT_Z; NiPoint3 vecA = posZ.CrossProduct(forwardVector).Unitize(); float dot = posZ.DotProduct(forwardVector); @@ -148,10 +54,11 @@ NiQuaternion NiQuaternion::LookAt(const NiPoint3& sourcePoint, const NiPoint3& d return NiQuaternion::CreateFromAxisAngle(vecA, rotAngle); } +//! Look from a specific point in space to another point in space NiQuaternion NiQuaternion::LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint) { NiPoint3 forwardVector = NiPoint3(destPoint - sourcePoint).Unitize(); - NiPoint3 posZ = NiPoint3::UNIT_Z; + NiPoint3 posZ = NiPoint3Constant::UNIT_Z; NiPoint3 vecA = posZ.CrossProduct(forwardVector).Unitize(); float dot = posZ.DotProduct(forwardVector); diff --git a/dCommon/NiQuaternion.h b/dCommon/NiQuaternion.h index b7d60f4e4..391630ba1 100644 --- a/dCommon/NiQuaternion.h +++ b/dCommon/NiQuaternion.h @@ -1,4 +1,5 @@ -#pragma once +#ifndef __NIQUATERNION_H__ +#define __NIQUATERNION_H__ // Custom Classes #include "NiPoint3.h" @@ -14,14 +15,14 @@ typedef NiQuaternion Quaternion; //!< A typedef for a shorthand version o //! A class that defines a rotation in space class NiQuaternion { public: - float w; //!< The w coordinate - float x; //!< The x coordinate - float y; //!< The y coordinate - float z; //!< The z coordinate + float w{ 1 }; //!< The w coordinate + float x{ 0 }; //!< The x coordinate + float y{ 0 }; //!< The y coordinate + float z{ 0 }; //!< The z coordinate //! The initializer - NiQuaternion(void); + constexpr NiQuaternion() = default; //! The initializer /*! @@ -30,13 +31,12 @@ class NiQuaternion { \param y The y coordinate \param z The z coordinate */ - NiQuaternion(float w, float x, float y, float z); - - //! Destructor - ~NiQuaternion(void); - - // MARK: Constants - static const NiQuaternion IDENTITY; //!< Quaternion(1, 0, 0, 0) + constexpr NiQuaternion(const float w, const float x, const float y, const float z) noexcept + : w{ w } + , x{ x } + , y{ y } + , z{ z } { + } // MARK: Setters / Getters @@ -44,50 +44,49 @@ class NiQuaternion { /*! \return The w coordinate */ - float GetW(void) const; + constexpr float GetW() const noexcept; //! Sets the W coordinate /*! \param w The w coordinate */ - void SetW(float w); + constexpr void SetW(const float w) noexcept; //! Gets the X coordinate /*! \return The x coordinate */ - float GetX(void) const; + constexpr float GetX() const noexcept; //! Sets the X coordinate /*! \param x The x coordinate */ - void SetX(float x); + constexpr void SetX(const float x) noexcept; //! Gets the Y coordinate /*! \return The y coordinate */ - float GetY(void) const; + constexpr float GetY() const noexcept; //! Sets the Y coordinate /*! \param y The y coordinate */ - void SetY(float y); + constexpr void SetY(const float y) noexcept; //! Gets the Z coordinate /*! \return The z coordinate */ - float GetZ(void) const; + constexpr float GetZ() const noexcept; //! Sets the Z coordinate /*! \param z The z coordinate */ - void SetZ(float z); - + constexpr void SetZ(const float z) noexcept; // MARK: Member Functions @@ -95,31 +94,29 @@ class NiQuaternion { /*! \return The forward vector of the quaternion */ - Vector3 GetForwardVector(void) const; + constexpr Vector3 GetForwardVector() const noexcept; //! Returns the up vector from the quaternion /*! \return The up vector fo the quaternion */ - Vector3 GetUpVector(void) const; + constexpr Vector3 GetUpVector() const noexcept; //! Returns the right vector from the quaternion /*! \return The right vector of the quaternion */ - Vector3 GetRightVector(void) const; + constexpr Vector3 GetRightVector() const noexcept; Vector3 GetEulerAngles() const; - // MARK: Operators //! Operator to check for equality - bool operator==(const NiQuaternion& rot) const; + constexpr bool operator==(const NiQuaternion& rot) const noexcept; //! Operator to check for inequality - bool operator!=(const NiQuaternion& rot) const; - + constexpr bool operator!=(const NiQuaternion& rot) const noexcept; // MARK: Helper Functions @@ -149,3 +146,13 @@ class NiQuaternion { static NiQuaternion FromEulerAngles(const NiPoint3& eulerAngles); }; + +// Static Variables +namespace NiQuaternionConstant { + constexpr NiQuaternion IDENTITY(1, 0, 0, 0); +} + +// Include constexpr and inline function definitions in a seperate file for readability +#include "NiQuaternion.inl" + +#endif // !__NIQUATERNION_H__ diff --git a/dCommon/NiQuaternion.inl b/dCommon/NiQuaternion.inl new file mode 100644 index 000000000..9ed84ffc7 --- /dev/null +++ b/dCommon/NiQuaternion.inl @@ -0,0 +1,75 @@ +#pragma once +#ifndef __NIQUATERNION_H__ +#error "This should only be included inline in NiQuaternion.h: Do not include directly!" +#endif + +// MARK: Setters / Getters + +//! Gets the W coordinate +constexpr float NiQuaternion::GetW() const noexcept { + return this->w; +} + +//! Sets the W coordinate +constexpr void NiQuaternion::SetW(const float w) noexcept { + this->w = w; +} + +//! Gets the X coordinate +constexpr float NiQuaternion::GetX() const noexcept { + return this->x; +} + +//! Sets the X coordinate +constexpr void NiQuaternion::SetX(const float x) noexcept { + this->x = x; +} + +//! Gets the Y coordinate +constexpr float NiQuaternion::GetY() const noexcept { + return this->y; +} + +//! Sets the Y coordinate +constexpr void NiQuaternion::SetY(const float y) noexcept { + this->y = y; +} + +//! Gets the Z coordinate +constexpr float NiQuaternion::GetZ() const noexcept { + return this->z; +} + +//! Sets the Z coordinate +constexpr void NiQuaternion::SetZ(const float z) noexcept { + this->z = z; +} + +// MARK: Member Functions + +//! Returns the forward vector from the quaternion +constexpr Vector3 NiQuaternion::GetForwardVector() const noexcept { + return Vector3(2 * (x * z + w * y), 2 * (y * z - w * x), 1 - 2 * (x * x + y * y)); +} + +//! Returns the up vector from the quaternion +constexpr Vector3 NiQuaternion::GetUpVector() const noexcept { + return Vector3(2 * (x * y - w * z), 1 - 2 * (x * x + z * z), 2 * (y * z + w * x)); +} + +//! Returns the right vector from the quaternion +constexpr Vector3 NiQuaternion::GetRightVector() const noexcept { + return Vector3(1 - 2 * (y * y + z * z), 2 * (x * y + w * z), 2 * (x * z - w * y)); +} + +// MARK: Operators + +//! Operator to check for equality +constexpr bool NiQuaternion::operator==(const NiQuaternion& rot) const noexcept { + return rot.x == this->x && rot.y == this->y && rot.z == this->z && rot.w == this->w; +} + +//! Operator to check for inequality +constexpr bool NiQuaternion::operator!=(const NiQuaternion& rot) const noexcept { + return !(*this == rot); +} diff --git a/dCommon/PositionUpdate.h b/dCommon/PositionUpdate.h index 1b84e3717..4d591a97b 100644 --- a/dCommon/PositionUpdate.h +++ b/dCommon/PositionUpdate.h @@ -32,17 +32,17 @@ struct RemoteInputInfo { struct LocalSpaceInfo { LWOOBJID objectId = LWOOBJID_EMPTY; - NiPoint3 position = NiPoint3::ZERO; - NiPoint3 linearVelocity = NiPoint3::ZERO; + NiPoint3 position = NiPoint3Constant::ZERO; + NiPoint3 linearVelocity = NiPoint3Constant::ZERO; }; struct PositionUpdate { - NiPoint3 position = NiPoint3::ZERO; - NiQuaternion rotation = NiQuaternion::IDENTITY; + NiPoint3 position = NiPoint3Constant::ZERO; + NiQuaternion rotation = NiQuaternionConstant::IDENTITY; bool onGround = false; bool onRail = false; - NiPoint3 velocity = NiPoint3::ZERO; - NiPoint3 angularVelocity = NiPoint3::ZERO; + NiPoint3 velocity = NiPoint3Constant::ZERO; + NiPoint3 angularVelocity = NiPoint3Constant::ZERO; LocalSpaceInfo localSpaceInfo; RemoteInputInfo remoteInputInfo; }; diff --git a/dGame/Character.cpp b/dGame/Character.cpp index ee04710a6..eab7583f8 100644 --- a/dGame/Character.cpp +++ b/dGame/Character.cpp @@ -451,7 +451,7 @@ void Character::LoadXmlRespawnCheckpoints() { auto* r = points->FirstChildElement("r"); while (r != nullptr) { int32_t map = 0; - NiPoint3 point = NiPoint3::ZERO; + NiPoint3 point = NiPoint3Constant::ZERO; r->QueryAttribute("w", &map); r->QueryAttribute("x", &point.x); @@ -513,7 +513,7 @@ void Character::SetRespawnPoint(LWOMAPID map, const NiPoint3& point) { const NiPoint3& Character::GetRespawnPoint(LWOMAPID map) const { const auto& pair = m_WorldRespawnCheckpoints.find(map); - if (pair == m_WorldRespawnCheckpoints.end()) return NiPoint3::ZERO; + if (pair == m_WorldRespawnCheckpoints.end()) return NiPoint3Constant::ZERO; return pair->second; } diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 8b72a80c0..340a6cc22 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -96,6 +96,8 @@ #include "CDZoneTableTable.h" Entity::Entity(const LWOOBJID& objectID, EntityInfo info, Entity* parentEntity) { + Game::entityManager->AddEntity(objectID, this); // TODO: FIX TEST CASES SO THIS CAN BE REMOVED + m_ObjectID = objectID; m_TemplateID = info.lot; m_ParentEntity = parentEntity; @@ -177,7 +179,7 @@ void Entity::Initialize() { * Set ourselves as a child of our parent */ - if (m_ParentEntity != nullptr) { + if (m_ParentEntity) { m_ParentEntity->AddChild(this); } @@ -1863,7 +1865,7 @@ const NiPoint3& Entity::GetPosition() const { return vehicel->GetPosition(); } - return NiPoint3::ZERO; + return NiPoint3Constant::ZERO; } const NiQuaternion& Entity::GetRotation() const { @@ -1891,7 +1893,7 @@ const NiQuaternion& Entity::GetRotation() const { return vehicel->GetRotation(); } - return NiQuaternion::IDENTITY; + return NiQuaternionConstant::IDENTITY; } void Entity::SetPosition(const NiPoint3& position) { @@ -2074,6 +2076,7 @@ uint8_t Entity::GetCollectibleID() const { void Entity::ProcessPositionUpdate(PositionUpdate& update) { if (!IsPlayer()) return; + auto* controllablePhysicsComponent = GetComponent(); if (!controllablePhysicsComponent) return; @@ -2081,45 +2084,46 @@ void Entity::ProcessPositionUpdate(PositionUpdate& update) { bool updateChar = true; if (possessorComponent) { - auto* possassableEntity = Game::entityManager->GetEntity(possessorComponent->GetPossessable()); + const LWOOBJID possessableId = possessorComponent->GetPossessable(); + auto* possessableEntity = Game::entityManager->GetEntity(possessableId); - if (possassableEntity) { - auto* possessableComponent = possassableEntity->GetComponent(); + if (possessableEntity) { + auto* possessableComponent = possessableEntity->GetComponent(); // While possessing something, only update char if we are attached to the thing we are possessing updateChar = possessableComponent && possessableComponent->GetPossessionType() == ePossessionType::ATTACHED_VISIBLE; - auto* havokVehiclePhysicsComponent = possassableEntity->GetComponent(); + auto* havokVehiclePhysicsComponent = possessableEntity->GetComponent(); if (havokVehiclePhysicsComponent) { havokVehiclePhysicsComponent->SetPosition(update.position); havokVehiclePhysicsComponent->SetRotation(update.rotation); havokVehiclePhysicsComponent->SetIsOnGround(update.onGround); havokVehiclePhysicsComponent->SetIsOnRail(update.onRail); havokVehiclePhysicsComponent->SetVelocity(update.velocity); - havokVehiclePhysicsComponent->SetDirtyVelocity(update.velocity != NiPoint3::ZERO); + havokVehiclePhysicsComponent->SetDirtyVelocity(update.velocity != NiPoint3Constant::ZERO); havokVehiclePhysicsComponent->SetAngularVelocity(update.angularVelocity); - havokVehiclePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3::ZERO); + havokVehiclePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3Constant::ZERO); havokVehiclePhysicsComponent->SetRemoteInputInfo(update.remoteInputInfo); } else { // Need to get the mount's controllable physics - auto* possessedControllablePhysicsComponent = possassableEntity->GetComponent(); + auto* possessedControllablePhysicsComponent = possessableEntity->GetComponent(); if (!possessedControllablePhysicsComponent) return; possessedControllablePhysicsComponent->SetPosition(update.position); possessedControllablePhysicsComponent->SetRotation(update.rotation); possessedControllablePhysicsComponent->SetIsOnGround(update.onGround); possessedControllablePhysicsComponent->SetIsOnRail(update.onRail); possessedControllablePhysicsComponent->SetVelocity(update.velocity); - possessedControllablePhysicsComponent->SetDirtyVelocity(update.velocity != NiPoint3::ZERO); + possessedControllablePhysicsComponent->SetDirtyVelocity(update.velocity != NiPoint3Constant::ZERO); possessedControllablePhysicsComponent->SetAngularVelocity(update.angularVelocity); - possessedControllablePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3::ZERO); + possessedControllablePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3Constant::ZERO); } - Game::entityManager->SerializeEntity(possassableEntity); + Game::entityManager->SerializeEntity(possessableId); } } if (!updateChar) { - update.velocity = NiPoint3::ZERO; - update.angularVelocity = NiPoint3::ZERO; + update.velocity = NiPoint3Constant::ZERO; + update.angularVelocity = NiPoint3Constant::ZERO; } // Handle statistics @@ -2133,13 +2137,13 @@ void Entity::ProcessPositionUpdate(PositionUpdate& update) { controllablePhysicsComponent->SetIsOnGround(update.onGround); controllablePhysicsComponent->SetIsOnRail(update.onRail); controllablePhysicsComponent->SetVelocity(update.velocity); - controllablePhysicsComponent->SetDirtyVelocity(update.velocity != NiPoint3::ZERO); + controllablePhysicsComponent->SetDirtyVelocity(update.velocity != NiPoint3Constant::ZERO); controllablePhysicsComponent->SetAngularVelocity(update.angularVelocity); - controllablePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3::ZERO); + controllablePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3Constant::ZERO); auto* ghostComponent = GetComponent(); if (ghostComponent) ghostComponent->SetGhostReferencePoint(update.position); Game::entityManager->QueueGhostUpdate(GetObjectID()); - if (updateChar) Game::entityManager->SerializeEntity(this); + if (updateChar) Game::entityManager->SerializeEntity(m_ObjectID); } diff --git a/dGame/Entity.h b/dGame/Entity.h index 36621d5cc..fd0ff5764 100644 --- a/dGame/Entity.h +++ b/dGame/Entity.h @@ -59,7 +59,7 @@ class Entity { * Getters */ - const LWOOBJID& GetObjectID() const { return m_ObjectID; } + const LWOOBJID& GetObjectID() const noexcept { return m_ObjectID; } const LOT GetLOT() const { return m_TemplateID; } @@ -229,8 +229,8 @@ class Entity { void TriggerEvent(eTriggerEventType event, Entity* optionalTarget = nullptr); void ScheduleDestructionAfterUpdate() { m_ShouldDestroyAfterUpdate = true; } - virtual const NiPoint3& GetRespawnPosition() const { return NiPoint3::ZERO; } - virtual const NiQuaternion& GetRespawnRotation() const { return NiQuaternion::IDENTITY; } + virtual const NiPoint3& GetRespawnPosition() const { return NiPoint3Constant::ZERO; } + virtual const NiQuaternion& GetRespawnRotation() const { return NiQuaternionConstant::IDENTITY; } void Sleep(); void Wake(); @@ -528,14 +528,14 @@ inline ComponentType* Entity::AddComponent(VaArgs... args) { // If it doesn't exist, create it and forward the arguments to the constructor if (!componentToReturn) { - componentToReturn = new ComponentType(this, std::forward(args)...); + componentToReturn = new ComponentType(m_ObjectID, std::forward(args)...); } else { // In this case the block is already allocated and ready for use // so we use a placement new to construct the component again as was requested by the caller. // Placement new means we already have memory allocated for the object, so this just calls its constructor again. // This is useful for when we want to create a new object in the same memory location as an old one. componentToReturn->~Component(); - new(componentToReturn) ComponentType(this, std::forward(args)...); + new(componentToReturn) ComponentType(m_ObjectID, std::forward(args)...); } // Finally return the created or already existing component. @@ -543,3 +543,5 @@ inline ComponentType* Entity::AddComponent(VaArgs... args) { // To allow a static cast here instead of a dynamic one. return dynamic_cast(componentToReturn); } + +// TODO: Add a cast operator to convert to LWOOBJID: https://en.cppreference.com/w/cpp/language/cast_operator diff --git a/dGame/EntityManager.cpp b/dGame/EntityManager.cpp index 10655d250..f496b4dc5 100644 --- a/dGame/EntityManager.cpp +++ b/dGame/EntityManager.cpp @@ -86,7 +86,7 @@ Entity* EntityManager::CreateEntity(EntityInfo info, User* user, Entity* parentE } // For non player entites, we'll generate a new ID or set the appropiate flags - else if (user == nullptr || info.lot != 1) { + else if (!user || info.lot != 1) { // Entities with no ID already set, often spawned entities, we'll generate a new sequencial ID if (info.id == 0) { @@ -121,18 +121,18 @@ Entity* EntityManager::CreateEntity(EntityInfo info, User* user, Entity* parentE Entity* entity; // Check if the entitty if a player, in case use the extended player entity class - if (user != nullptr) { + if (user) { entity = new Player(id, info, user, parentEntity); } else { entity = new Entity(id, info, parentEntity); } - // Initialize the entity - entity->Initialize(); - // Add the entity to the entity map m_Entities.insert_or_assign(id, entity); + // Initialize the entity + entity->Initialize(); + // Set the zone control entity if the entity is a zone control object, this should only happen once if (controller) { m_ZoneControlEntity = entity; @@ -430,12 +430,16 @@ void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr) } } +void EntityManager::SerializeEntity(const LWOOBJID entityId) { + if (std::find(m_EntitiesToSerialize.begin(), m_EntitiesToSerialize.end(), entityId) == m_EntitiesToSerialize.end()) { + m_EntitiesToSerialize.push_back(entityId); + } +} + void EntityManager::SerializeEntity(Entity* entity) { if (!entity || entity->GetNetworkId() == 0) return; - if (std::find(m_EntitiesToSerialize.begin(), m_EntitiesToSerialize.end(), entity->GetObjectID()) == m_EntitiesToSerialize.end()) { - m_EntitiesToSerialize.push_back(entity->GetObjectID()); - } + EntityManager::SerializeEntity(entity->GetObjectID()); } void EntityManager::DestructAllEntities(const SystemAddress& sysAddr) { diff --git a/dGame/EntityManager.h b/dGame/EntityManager.h index 33d7aaff6..7ebd9877d 100644 --- a/dGame/EntityManager.h +++ b/dGame/EntityManager.h @@ -20,6 +20,13 @@ class EntityManager { public: void Initialize(); + /** + * Add entity to the entity lookup map + * @param objectId Object ID + * @param entityPtr Entity pointer + */ + void AddEntity(const LWOOBJID objectId, Entity* entityPtr) { m_Entities.insert_or_assign(objectId, entityPtr); }; + void UpdateEntities(float deltaTime); Entity* CreateEntity(EntityInfo info, User* user = nullptr, Entity* parentEntity = nullptr, bool controller = false, LWOOBJID explicitId = LWOOBJID_EMPTY); void DestroyEntity(const LWOOBJID& objectID); @@ -44,6 +51,8 @@ class EntityManager { void ConstructEntity(Entity* entity, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS, bool skipChecks = false); void DestructEntity(Entity* entity, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS); + + void SerializeEntity(const LWOOBJID entity); void SerializeEntity(Entity* entity); void ConstructAllEntities(const SystemAddress& sysAddr); diff --git a/dGame/dBehaviors/ProjectileAttackBehavior.cpp b/dGame/dBehaviors/ProjectileAttackBehavior.cpp index 732ff186c..504afc690 100644 --- a/dGame/dBehaviors/ProjectileAttackBehavior.cpp +++ b/dGame/dBehaviors/ProjectileAttackBehavior.cpp @@ -33,7 +33,7 @@ void ProjectileAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStrea } if (m_useMouseposit && !branch.isSync) { - NiPoint3 targetPosition = NiPoint3::ZERO; + NiPoint3 targetPosition = NiPoint3Constant::ZERO; if (!bitStream->Read(targetPosition)) { LOG("Unable to read targetPosition from bitStream, aborting Handle! %i", bitStream->GetNumberOfUnreadBits()); return; diff --git a/dGame/dComponents/ActivityComponent.cpp b/dGame/dComponents/ActivityComponent.cpp index aa6a4604d..fea4c21a1 100644 --- a/dGame/dComponents/ActivityComponent.cpp +++ b/dGame/dComponents/ActivityComponent.cpp @@ -29,7 +29,7 @@ #include "CDActivitiesTable.h" #include "LeaderboardManager.h" -ActivityComponent::ActivityComponent(Entity* parent, int32_t activityID) : Component(parent) { +ActivityComponent::ActivityComponent(const LWOOBJID& parentEntityId, int32_t activityID) : Component{ parentEntityId } { /* * This is precisely what the client does functionally * Use the component id as the default activity id and load its data from the database @@ -38,13 +38,14 @@ ActivityComponent::ActivityComponent(Entity* parent, int32_t activityID) : Compo m_ActivityID = activityID; LoadActivityData(activityID); - if (m_Parent->HasVar(u"activityID")) { - m_ActivityID = parent->GetVar(u"activityID"); + + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + if (parentEntity->HasVar(u"activityID")) { + m_ActivityID = parentEntity->GetVar(u"activityID"); LoadActivityData(m_ActivityID); } - auto* destroyableComponent = m_Parent->GetComponent(); - + auto* destroyableComponent = parentEntity->GetComponent(); if (destroyableComponent) { // First lookup the loot matrix id for this component id. CDActivityRewardsTable* activityRewardsTable = CDClientManager::Instance().GetTable(); @@ -70,6 +71,7 @@ ActivityComponent::ActivityComponent(Entity* parent, int32_t activityID) : Compo } } } + void ActivityComponent::LoadActivityData(const int32_t activityId) { CDActivitiesTable* activitiesTable = CDClientManager::Instance().GetTable(); std::vector activities = activitiesTable->Query([activityId](CDActivities entry) {return (entry.ActivityID == activityId); }); @@ -82,7 +84,7 @@ void ActivityComponent::LoadActivityData(const int32_t activityId) { m_ActivityInfo.minTeams = 1; } if (m_ActivityInfo.instanceMapID == -1) { - const auto& transferOverride = m_Parent->GetVarAsString(u"transferZoneID"); + const auto& transferOverride = Game::entityManager->GetEntity(m_Parent)->GetVarAsString(u"transferZoneID"); if (!transferOverride.empty()) { GeneralUtils::TryParse(transferOverride, m_ActivityInfo.instanceMapID); } @@ -141,7 +143,7 @@ void ActivityComponent::PlayerJoin(Entity* player) { } void ActivityComponent::PlayerJoinLobby(Entity* player) { - if (!m_Parent->HasComponent(eReplicaComponentType::QUICK_BUILD)) + if (!Game::entityManager->GetEntity(m_Parent)->HasComponent(eReplicaComponentType::QUICK_BUILD)) GameMessages::SendMatchResponse(player, player->GetSystemAddress(), 0); // tell the client they joined a lobby LobbyPlayer* newLobbyPlayer = new LobbyPlayer(); newLobbyPlayer->entityID = player->GetObjectID(); @@ -561,7 +563,7 @@ void ActivityInstance::RewardParticipant(Entity* participant) { maxCoins = currencyTable[0].maxvalue; } - Loot::DropLoot(participant, m_Parent, activityRewards[0].LootMatrixIndex, minCoins, maxCoins); + Loot::DropLoot(participant, Game::entityManager->GetEntity(m_Parent), activityRewards[0].LootMatrixIndex, minCoins, maxCoins); } } diff --git a/dGame/dComponents/ActivityComponent.h b/dGame/dComponents/ActivityComponent.h index de63b3434..92714146b 100644 --- a/dGame/dComponents/ActivityComponent.h +++ b/dGame/dComponents/ActivityComponent.h @@ -14,8 +14,7 @@ */ class ActivityInstance { public: - ActivityInstance(Entity* parent, CDActivities activityInfo) { m_Parent = parent; m_ActivityInfo = activityInfo; }; - //~ActivityInstance(); + ActivityInstance(LWOOBJID parent, CDActivities activityInfo) { m_Parent = parent; m_ActivityInfo = activityInfo; }; /** * Adds an entity to this activity @@ -80,7 +79,7 @@ class ActivityInstance { /** * The entity that owns this activity (the entity that has the ScriptedActivityComponent) */ - Entity* m_Parent; + LWOOBJID m_Parent; /** * All the participants of this activity @@ -150,7 +149,7 @@ struct ActivityPlayer { */ class ActivityComponent : public Component { public: - ActivityComponent(Entity* parent, int32_t activityID); + ActivityComponent(const LWOOBJID& parentEntityId, int32_t activityID); void LoadActivityData(const int32_t activityId); diff --git a/dGame/dComponents/BaseCombatAIComponent.cpp b/dGame/dComponents/BaseCombatAIComponent.cpp index 11dff20f6..06434c7f1 100644 --- a/dGame/dComponents/BaseCombatAIComponent.cpp +++ b/dGame/dComponents/BaseCombatAIComponent.cpp @@ -27,11 +27,13 @@ #include "CDPhysicsComponentTable.h" #include "dNavMesh.h" -BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id): Component(parent) { +BaseCombatAIComponent::BaseCombatAIComponent(const LWOOBJID& parentEntityId, const uint32_t id) : Component{ parentEntityId } { + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + m_Target = LWOOBJID_EMPTY; SetAiState(AiState::spawn); m_Timer = 1.0f; - m_StartPosition = parent->GetPosition(); + m_StartPosition = parentEntity->GetPosition(); m_MovementAI = nullptr; m_Disabled = false; m_SkillEntries = {}; @@ -65,19 +67,17 @@ BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id): // Get aggro and tether radius from settings and use this if it is present. Only overwrite the // radii if it is greater than the one in the database. - if (m_Parent) { - auto aggroRadius = m_Parent->GetVar(u"aggroRadius"); - m_AggroRadius = aggroRadius != 0 ? aggroRadius : m_AggroRadius; - auto tetherRadius = m_Parent->GetVar(u"tetherRadius"); - m_HardTetherRadius = tetherRadius != 0 ? tetherRadius : m_HardTetherRadius; - } + auto aggroRadius = parentEntity->GetVar(u"aggroRadius"); + m_AggroRadius = aggroRadius != 0 ? aggroRadius : m_AggroRadius; + auto tetherRadius = parentEntity->GetVar(u"tetherRadius"); + m_HardTetherRadius = tetherRadius != 0 ? tetherRadius : m_HardTetherRadius; /* * Find skills */ auto skillQuery = CDClientDatabase::CreatePreppedStmt( "SELECT skillID, cooldown, behaviorID FROM SkillBehavior WHERE skillID IN (SELECT skillID FROM ObjectSkills WHERE objectTemplate = ?);"); - skillQuery.bind(1, static_cast(parent->GetLOT())); + skillQuery.bind(1, static_cast(parentEntity->GetLOT())); auto result = skillQuery.execQuery(); @@ -108,7 +108,7 @@ BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id): int32_t collisionGroup = (COLLISION_GROUP_DYNAMIC | COLLISION_GROUP_ENEMY); CDComponentsRegistryTable* componentRegistryTable = CDClientManager::Instance().GetTable(); - auto componentID = componentRegistryTable->GetByIDAndType(parent->GetLOT(), eReplicaComponentType::CONTROLLABLE_PHYSICS); + auto componentID = componentRegistryTable->GetByIDAndType(parentEntity->GetLOT(), eReplicaComponentType::CONTROLLABLE_PHYSICS); CDPhysicsComponentTable* physicsComponentTable = CDClientManager::Instance().GetTable(); @@ -120,14 +120,14 @@ BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id): } //Create a phantom physics volume so we can detect when we're aggro'd. - m_dpEntity = new dpEntity(m_Parent->GetObjectID(), m_AggroRadius); - m_dpEntityEnemy = new dpEntity(m_Parent->GetObjectID(), m_AggroRadius, false); + m_dpEntity = new dpEntity(m_Parent, m_AggroRadius); + m_dpEntityEnemy = new dpEntity(m_Parent, m_AggroRadius, false); m_dpEntity->SetCollisionGroup(collisionGroup); m_dpEntityEnemy->SetCollisionGroup(collisionGroup); - m_dpEntity->SetPosition(m_Parent->GetPosition()); - m_dpEntityEnemy->SetPosition(m_Parent->GetPosition()); + m_dpEntity->SetPosition(parentEntity->GetPosition()); + m_dpEntityEnemy->SetPosition(parentEntity->GetPosition()); dpWorld::AddEntity(m_dpEntity); dpWorld::AddEntity(m_dpEntityEnemy); @@ -146,17 +146,18 @@ void BaseCombatAIComponent::Update(const float deltaTime) { //First, we need to process physics: if (!m_dpEntity) return; - m_dpEntity->SetPosition(m_Parent->GetPosition()); //make sure our position is synced with our dpEntity - m_dpEntityEnemy->SetPosition(m_Parent->GetPosition()); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + m_dpEntity->SetPosition(parentEntity->GetPosition()); //make sure our position is synced with our dpEntity + m_dpEntityEnemy->SetPosition(parentEntity->GetPosition()); //Process enter events for (auto en : m_dpEntity->GetNewObjects()) { - m_Parent->OnCollisionPhantom(en->GetObjectID()); + parentEntity->OnCollisionPhantom(en->GetObjectID()); } //Process exit events for (auto en : m_dpEntity->GetRemovedObjects()) { - m_Parent->OnCollisionLeavePhantom(en->GetObjectID()); + parentEntity->OnCollisionLeavePhantom(en->GetObjectID()); } // Check if we should stop the tether effect @@ -165,7 +166,7 @@ void BaseCombatAIComponent::Update(const float deltaTime) { const auto& info = m_MovementAI->GetInfo(); if (m_Target != LWOOBJID_EMPTY || (NiPoint3::DistanceSquared( m_StartPosition, - m_Parent->GetPosition()) < 20 * 20 && m_TetherTime <= 0) + parentEntity->GetPosition()) < 20 * 20 && m_TetherTime <= 0) ) { GameMessages::SendStopFXEffect(m_Parent, true, "tether"); m_TetherEffectActive = false; @@ -180,16 +181,16 @@ void BaseCombatAIComponent::Update(const float deltaTime) { m_SoftTimer -= deltaTime; } - if (m_Disabled || m_Parent->GetIsDead()) + if (m_Disabled || parentEntity->GetIsDead()) return; bool stunnedThisFrame = m_Stunned; CalculateCombat(deltaTime); // Putting this here for now - if (m_StartPosition == NiPoint3::ZERO) { - m_StartPosition = m_Parent->GetPosition(); + if (m_StartPosition == NiPoint3Constant::ZERO) { + m_StartPosition = parentEntity->GetPosition(); } - m_MovementAI = m_Parent->GetComponent(); + m_MovementAI = parentEntity->GetComponent(); if (m_MovementAI == nullptr) { return; @@ -243,21 +244,19 @@ void BaseCombatAIComponent::CalculateCombat(const float deltaTime) { bool hadRemainingDowntime = m_SkillTime > 0.0f; if (m_SkillTime > 0.0f) m_SkillTime -= deltaTime; - auto* rebuild = m_Parent->GetComponent(); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + auto* const quickBuild = parentEntity->GetComponent(); - if (rebuild != nullptr) { - const auto state = rebuild->GetState(); + if (quickBuild) { + const auto state = quickBuild->GetState(); if (state != eQuickBuildState::COMPLETED) { return; } } - auto* skillComponent = m_Parent->GetComponent(); - - if (skillComponent == nullptr) { - return; - } + auto* skillComponent = parentEntity->GetComponent(); + if (!skillComponent) return; skillComponent->CalculateUpdate(deltaTime); @@ -287,7 +286,7 @@ void BaseCombatAIComponent::CalculateCombat(const float deltaTime) { } if (!m_TetherEffectActive && m_OutOfCombat && (m_OutOfCombatTime -= deltaTime) <= 0) { - auto* destroyableComponent = m_Parent->GetComponent(); + auto* destroyableComponent = parentEntity->GetComponent(); if (destroyableComponent != nullptr && destroyableComponent->HasFaction(4)) { auto serilizationRequired = false; @@ -308,7 +307,7 @@ void BaseCombatAIComponent::CalculateCombat(const float deltaTime) { Game::entityManager->SerializeEntity(m_Parent); } - GameMessages::SendPlayFXEffect(m_Parent->GetObjectID(), 6270, u"tether", "tether"); + GameMessages::SendPlayFXEffect(m_Parent, 6270, u"tether", "tether"); m_TetherEffectActive = true; @@ -484,7 +483,7 @@ LWOOBJID BaseCombatAIComponent::FindTarget() { m_DirtyThreat = false; - if (optimalTarget == nullptr) { + if (!optimalTarget) { return LWOOBJID_EMPTY; } else { return optimalTarget->GetObjectID(); @@ -494,10 +493,11 @@ LWOOBJID BaseCombatAIComponent::FindTarget() { std::vector BaseCombatAIComponent::GetTargetWithinAggroRange() const { std::vector targets; - for (auto id : m_Parent->GetTargetsInPhantom()) { + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + for (auto id : parentEntity->GetTargetsInPhantom()) { auto* other = Game::entityManager->GetEntity(id); - const auto distance = Vector3::DistanceSquared(m_Parent->GetPosition(), other->GetPosition()); + const auto distance = Vector3::DistanceSquared(parentEntity->GetPosition(), other->GetPosition()); if (distance > m_AggroRadius * m_AggroRadius) continue; @@ -508,7 +508,7 @@ std::vector BaseCombatAIComponent::GetTargetWithinAggroRange() const { } bool BaseCombatAIComponent::IsMech() { - switch (m_Parent->GetLOT()) { + switch (Game::entityManager->GetEntity(m_Parent)->GetLOT()) { case 6253: return true; @@ -551,10 +551,10 @@ bool BaseCombatAIComponent::IsEnemy(LWOOBJID target) const { return false; } - auto* referenceDestroyable = m_Parent->GetComponent(); + auto* referenceDestroyable = Game::entityManager->GetEntity(m_Parent)->GetComponent(); - if (referenceDestroyable == nullptr) { - LOG("Invalid reference destroyable component on (%llu)!", m_Parent->GetObjectID()); + if (!referenceDestroyable) { + LOG("Invalid reference destroyable component on (%llu)!", m_Parent); return false; } @@ -594,9 +594,7 @@ Entity* BaseCombatAIComponent::GetTargetEntity() const { } void BaseCombatAIComponent::Taunt(LWOOBJID offender, float threat) { - // Can't taunt self - if (offender == m_Parent->GetObjectID()) - return; + if (offender == m_Parent) return; // Can't taunt self m_ThreatEntries[offender] += threat; m_DirtyThreat = true; @@ -786,7 +784,8 @@ void BaseCombatAIComponent::LookAt(const NiPoint3& point) { return; } - m_Parent->SetRotation(NiQuaternion::LookAt(m_Parent->GetPosition(), point)); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + parentEntity->SetRotation(NiQuaternion::LookAt(parentEntity->GetPosition(), point)); } void BaseCombatAIComponent::SetDisabled(bool value) { diff --git a/dGame/dComponents/BaseCombatAIComponent.h b/dGame/dComponents/BaseCombatAIComponent.h index 8ae046113..04d323784 100644 --- a/dGame/dComponents/BaseCombatAIComponent.h +++ b/dGame/dComponents/BaseCombatAIComponent.h @@ -47,9 +47,9 @@ struct AiSkillEntry */ class BaseCombatAIComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::BASE_COMBAT_AI; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::BASE_COMBAT_AI; - BaseCombatAIComponent(Entity* parentEntity, uint32_t id); + BaseCombatAIComponent(const LWOOBJID& parentEntityId, const uint32_t id); ~BaseCombatAIComponent() override; void Update(float deltaTime) override; diff --git a/dGame/dComponents/BouncerComponent.cpp b/dGame/dComponents/BouncerComponent.cpp index 78ee3637f..949a31110 100644 --- a/dGame/dComponents/BouncerComponent.cpp +++ b/dGame/dComponents/BouncerComponent.cpp @@ -9,19 +9,18 @@ #include "BitStream.h" #include "eTriggerEventType.h" -BouncerComponent::BouncerComponent(Entity* parent) : Component(parent) { +BouncerComponent::BouncerComponent(const LWOOBJID& parentEntityId) : Component{ parentEntityId } { + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + m_PetEnabled = false; m_PetBouncerEnabled = false; m_PetSwitchLoaded = false; - if (parent->GetLOT() == 7625) { + if (parentEntity->GetLOT() == 7625) { LookupPetSwitch(); } } -BouncerComponent::~BouncerComponent() { -} - void BouncerComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { outBitStream->Write(m_PetEnabled); if (m_PetEnabled) { @@ -30,7 +29,7 @@ void BouncerComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitia } Entity* BouncerComponent::GetParentEntity() const { - return m_Parent; + return Game::entityManager->GetEntity(m_Parent); } void BouncerComponent::SetPetEnabled(bool value) { @@ -42,15 +41,16 @@ void BouncerComponent::SetPetEnabled(bool value) { void BouncerComponent::SetPetBouncerEnabled(bool value) { m_PetBouncerEnabled = value; - GameMessages::SendBouncerActiveStatus(m_Parent->GetObjectID(), value, UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::SendBouncerActiveStatus(m_Parent, value, UNASSIGNED_SYSTEM_ADDRESS); Game::entityManager->SerializeEntity(m_Parent); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); if (value) { - m_Parent->TriggerEvent(eTriggerEventType::PET_ON_SWITCH, m_Parent); - GameMessages::SendPlayFXEffect(m_Parent->GetObjectID(), 1513, u"create", "PetOnSwitch", LWOOBJID_EMPTY, 1, 1, true); + parentEntity->TriggerEvent(eTriggerEventType::PET_ON_SWITCH, Game::entityManager->GetEntity(m_Parent)); + GameMessages::SendPlayFXEffect(m_Parent, 1513, u"create", "PetOnSwitch", LWOOBJID_EMPTY, 1, 1, true); } else { - m_Parent->TriggerEvent(eTriggerEventType::PET_OFF_SWITCH, m_Parent); + parentEntity->TriggerEvent(eTriggerEventType::PET_OFF_SWITCH, Game::entityManager->GetEntity(m_Parent)); GameMessages::SendStopFXEffect(m_Parent, true, "PetOnSwitch"); } @@ -65,7 +65,8 @@ bool BouncerComponent::GetPetBouncerEnabled() const { } void BouncerComponent::LookupPetSwitch() { - const auto& groups = m_Parent->GetGroups(); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + const auto& groups = parentEntity->GetGroups(); for (const auto& group : groups) { const auto& entities = Game::entityManager->GetEntitiesInGroup(group); @@ -89,7 +90,7 @@ void BouncerComponent::LookupPetSwitch() { if (!m_PetSwitchLoaded) { LOG("Failed to load pet bouncer"); - m_Parent->AddCallbackTimer(0.5f, [this]() { + parentEntity->AddCallbackTimer(0.5f, [this]() { LookupPetSwitch(); }); } diff --git a/dGame/dComponents/BouncerComponent.h b/dGame/dComponents/BouncerComponent.h index cb3d8df36..30327123a 100644 --- a/dGame/dComponents/BouncerComponent.h +++ b/dGame/dComponents/BouncerComponent.h @@ -12,10 +12,9 @@ */ class BouncerComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::BOUNCER; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::BOUNCER; - BouncerComponent(Entity* parentEntity); - ~BouncerComponent() override; + BouncerComponent(const LWOOBJID& parentEntityId); void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; diff --git a/dGame/dComponents/BuffComponent.cpp b/dGame/dComponents/BuffComponent.cpp index 10ac4ebbe..870bfa131 100644 --- a/dGame/dComponents/BuffComponent.cpp +++ b/dGame/dComponents/BuffComponent.cpp @@ -26,11 +26,7 @@ namespace { }; } -BuffComponent::BuffComponent(Entity* parent) : Component(parent) { -} - -BuffComponent::~BuffComponent() { -} +BuffComponent::BuffComponent(const LWOOBJID& parentEntityId) noexcept : Component{ parentEntityId } {} void BuffComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { if (!bIsInitialUpdate) return; @@ -54,7 +50,7 @@ void BuffComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUp auto* team = TeamManager::Instance()->GetTeam(buff.source); bool addedByTeammate = false; if (team) { - addedByTeammate = std::count(team->members.begin(), team->members.end(), m_Parent->GetObjectID()) > 0; + addedByTeammate = std::count(team->members.begin(), team->members.end(), m_Parent) > 0; } outBitStream->Write(addedByTeammate); // Added by teammate. If source is in the same team as the target, this is true. Otherwise, false. @@ -82,7 +78,7 @@ void BuffComponent::Update(float deltaTime) { buff.second.tickTime = buff.second.tick; buff.second.stacks--; - SkillComponent::HandleUnmanaged(buff.second.behaviorID, m_Parent->GetObjectID(), buff.second.source); + SkillComponent::HandleUnmanaged(buff.second.behaviorID, m_Parent, buff.second.source); } } @@ -123,7 +119,7 @@ void BuffComponent::ApplyBuffFx(uint32_t buffId, const BuffParameter& buff) { fxToPlay += std::to_string(buffId); LOG_DEBUG("Playing %s %i", fxToPlay.c_str(), buff.effectId); - GameMessages::SendPlayFXEffect(m_Parent->GetObjectID(), buff.effectId, u"cast", fxToPlay, LWOOBJID_EMPTY, 1.07f, 1.0f, false); + GameMessages::SendPlayFXEffect(m_Parent, buff.effectId, u"cast", fxToPlay, LWOOBJID_EMPTY, 1.07f, 1.0f, false); } void BuffComponent::RemoveBuffFx(uint32_t buffId, const BuffParameter& buff) { @@ -150,10 +146,10 @@ void BuffComponent::ApplyBuff(const int32_t id, const float duration, const LWOO auto* team = TeamManager::Instance()->GetTeam(source); bool addedByTeammate = false; if (team) { - addedByTeammate = std::count(team->members.begin(), team->members.end(), m_Parent->GetObjectID()) > 0; + addedByTeammate = std::count(team->members.begin(), team->members.end(), m_Parent) > 0; } - GameMessages::SendAddBuff(const_cast(m_Parent->GetObjectID()), source, static_cast(id), + GameMessages::SendAddBuff(const_cast(m_Parent), source, static_cast(id), static_cast(duration) * 1000, addImmunity, cancelOnDamaged, cancelOnDeath, cancelOnLogout, cancelOnRemoveBuff, cancelOnUi, cancelOnUnequip, cancelOnZone, addedByTeammate, applyOnTeammates); @@ -197,7 +193,7 @@ void BuffComponent::ApplyBuff(const int32_t id, const float duration, const LWOO auto* parent = GetParent(); if (!cancelOnDeath) return; - m_Parent->AddDieCallback([parent, id]() { + Game::entityManager->GetEntity(m_Parent)->AddDieCallback([parent, id]() { LOG_DEBUG("Removing buff %i because parent died", id); if (!parent) return; auto* buffComponent = parent->GetComponent(); @@ -324,7 +320,7 @@ void BuffComponent::ReApplyBuffs() { } Entity* BuffComponent::GetParent() const { - return m_Parent; + return Game::entityManager->GetEntity(m_Parent); } void BuffComponent::LoadFromXml(tinyxml2::XMLDocument* doc) { diff --git a/dGame/dComponents/BuffComponent.h b/dGame/dComponents/BuffComponent.h index 7f7b44d80..9991083d4 100644 --- a/dGame/dComponents/BuffComponent.h +++ b/dGame/dComponents/BuffComponent.h @@ -49,11 +49,9 @@ struct Buff { */ class BuffComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::BUFF; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::BUFF; - explicit BuffComponent(Entity* parent); - - ~BuffComponent(); + explicit BuffComponent(const LWOOBJID& parentEntityId) noexcept; Entity* GetParent() const; diff --git a/dGame/dComponents/BuildBorderComponent.cpp b/dGame/dComponents/BuildBorderComponent.cpp index 9e392e696..1217ebb35 100644 --- a/dGame/dComponents/BuildBorderComponent.cpp +++ b/dGame/dComponents/BuildBorderComponent.cpp @@ -9,17 +9,13 @@ #include "Item.h" #include "PropertyManagementComponent.h" -BuildBorderComponent::BuildBorderComponent(Entity* parent) : Component(parent) { -} - -BuildBorderComponent::~BuildBorderComponent() { -} +BuildBorderComponent::BuildBorderComponent(const LWOOBJID& parentEntityId) noexcept : Component{ parentEntityId } {} void BuildBorderComponent::OnUse(Entity* originator) { if (originator->GetCharacter()) { const auto& entities = Game::entityManager->GetEntitiesInGroup("PropertyPlaque"); - auto buildArea = m_Parent->GetObjectID(); + auto buildArea = m_Parent; if (!entities.empty()) { buildArea = entities[0]->GetObjectID(); @@ -28,16 +24,10 @@ void BuildBorderComponent::OnUse(Entity* originator) { } auto* inventoryComponent = originator->GetComponent(); - - if (inventoryComponent == nullptr) { - return; - } + if (!inventoryComponent) return; auto* thinkingHat = inventoryComponent->FindItemByLot(6086); - - if (thinkingHat == nullptr) { - return; - } + if (!thinkingHat) return; inventoryComponent->PushEquippedItems(); @@ -56,14 +46,14 @@ void BuildBorderComponent::OnUse(Entity* originator) { 4, 0, -1, - NiPoint3::ZERO, + NiPoint3Constant::ZERO, 0 ); } else { GameMessages::SendStartArrangingWithItem(originator, originator->GetSystemAddress(), true, buildArea, originator->GetPosition()); } - InventoryComponent* inv = m_Parent->GetComponent(); + InventoryComponent* inv = Game::entityManager->GetEntity(m_Parent)->GetComponent(); if (!inv) return; inv->PushEquippedItems(); // technically this is supposed to happen automatically... but it doesnt? so just keep this here } diff --git a/dGame/dComponents/BuildBorderComponent.h b/dGame/dComponents/BuildBorderComponent.h index 985c03885..310c1d7fb 100644 --- a/dGame/dComponents/BuildBorderComponent.h +++ b/dGame/dComponents/BuildBorderComponent.h @@ -18,8 +18,7 @@ class BuildBorderComponent : public Component { public: inline static const eReplicaComponentType ComponentType = eReplicaComponentType::BUILD_BORDER; - BuildBorderComponent(Entity* parent); - ~BuildBorderComponent() override; + BuildBorderComponent(const LWOOBJID& entityParentId) noexcept; /** * Causes the originator to start build with this entity as a reference point diff --git a/dGame/dComponents/CharacterComponent.cpp b/dGame/dComponents/CharacterComponent.cpp index 70eec0cf7..0b7d68364 100644 --- a/dGame/dComponents/CharacterComponent.cpp +++ b/dGame/dComponents/CharacterComponent.cpp @@ -24,7 +24,7 @@ #include "WorldPackets.h" #include -CharacterComponent::CharacterComponent(Entity* parent, Character* character) : Component(parent) { +CharacterComponent::CharacterComponent(const LWOOBJID& parentEntityId, Character* character) : Component{ parentEntityId } { m_Character = character; m_IsRacing = false; @@ -74,9 +74,6 @@ bool CharacterComponent::LandingAnimDisabled(int zoneID) { return false; } -CharacterComponent::~CharacterComponent() { -} - void CharacterComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { if (bIsInitialUpdate) { @@ -514,7 +511,7 @@ void CharacterComponent::TrackRaceCompleted(bool won) { } void CharacterComponent::TrackPositionUpdate(const NiPoint3& newPosition) { - const auto distance = NiPoint3::Distance(newPosition, m_Parent->GetPosition()); + const auto distance = NiPoint3::Distance(newPosition, Game::entityManager->GetEntity(m_Parent)->GetPosition()); if (m_IsRacing) { UpdatePlayerStatistic(DistanceDriven, static_cast(distance)); @@ -755,15 +752,13 @@ void CharacterComponent::RemoveVentureVisionEffect(std::string ventureVisionType } void CharacterComponent::UpdateClientMinimap(bool showFaction, std::string ventureVisionType) const { - if (!m_Parent) return; AMFArrayValue arrayToSend; arrayToSend.Insert(ventureVisionType, showFaction); - GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent ? m_Parent->GetSystemAddress() : UNASSIGNED_SYSTEM_ADDRESS, "SetFactionVisibility", arrayToSend); + GameMessages::SendUIMessageServerToSingleClient(m_Parent, Game::entityManager->GetEntity(m_Parent)->GetSystemAddress(), "SetFactionVisibility", arrayToSend); } void CharacterComponent::AwardClaimCodes() { - if (!m_Parent) return; - auto* user = m_Parent->GetParentUser(); + auto* user = Game::entityManager->GetEntity(m_Parent)->GetParentUser(); if (!user) return; auto rewardCodes = Database::Get()->GetRewardCodesByAccountID(user->GetAccountID()); @@ -785,12 +780,12 @@ void CharacterComponent::AwardClaimCodes() { subject << "%[RewardCodes_" << rewardCode << "_subjectText]"; std::ostringstream body; body << "%[RewardCodes_" << rewardCode << "_bodyText]"; - Mail::SendMail(LWOOBJID_EMPTY, "%[MAIL_SYSTEM_NOTIFICATION]", m_Parent, subject.str(), body.str(), attachmentLOT, 1); + Mail::SendMail(LWOOBJID_EMPTY, "%[MAIL_SYSTEM_NOTIFICATION]", Game::entityManager->GetEntity(m_Parent), subject.str(), body.str(), attachmentLOT, 1); } } void CharacterComponent::SendToZone(LWOMAPID zoneId, LWOCLONEID cloneId) const { - const auto objid = m_Parent->GetObjectID(); + const auto objid = Game::entityManager->GetEntity(m_Parent)->GetObjectID(); ZoneInstanceManager::Instance()->RequestZoneTransfer(Game::server, zoneId, cloneId, false, [objid](bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, std::string serverIP, uint16_t serverPort) { auto* entity = Game::entityManager->GetEntity(objid); diff --git a/dGame/dComponents/CharacterComponent.h b/dGame/dComponents/CharacterComponent.h index fae99dcbb..f4372394b 100644 --- a/dGame/dComponents/CharacterComponent.h +++ b/dGame/dComponents/CharacterComponent.h @@ -63,10 +63,9 @@ enum StatisticID { */ class CharacterComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::CHARACTER; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::CHARACTER; - CharacterComponent(Entity* parent, Character* character); - ~CharacterComponent() override; + CharacterComponent(const LWOOBJID& parentEntityId, Character* character); void LoadFromXml(tinyxml2::XMLDocument* doc) override; void UpdateXml(tinyxml2::XMLDocument* doc) override; diff --git a/dGame/dComponents/CollectibleComponent.h b/dGame/dComponents/CollectibleComponent.h index 3ff71c6fe..c34524fb0 100644 --- a/dGame/dComponents/CollectibleComponent.h +++ b/dGame/dComponents/CollectibleComponent.h @@ -6,13 +6,13 @@ class CollectibleComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::COLLECTIBLE; - CollectibleComponent(Entity* parentEntity, int32_t collectibleId) : Component(parentEntity), m_CollectibleId(collectibleId) {} + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::COLLECTIBLE; + CollectibleComponent(const LWOOBJID& parentEntityId, int16_t collectibleId) noexcept : Component{ parentEntityId }, m_CollectibleId{ collectibleId } {} int16_t GetCollectibleId() const { return m_CollectibleId; } void Serialize(RakNet::BitStream* outBitStream, bool isConstruction) override; private: - int16_t m_CollectibleId = 0; + const int16_t m_CollectibleId = 0; }; #endif //!__COLLECTIBLECOMPONENT__H__ diff --git a/dGame/dComponents/Component.cpp b/dGame/dComponents/Component.cpp index 1136456cf..acd6a45c9 100644 --- a/dGame/dComponents/Component.cpp +++ b/dGame/dComponents/Component.cpp @@ -1,34 +1,19 @@ #include "Component.h" +Component::Component(const LWOOBJID& parentEntityId) noexcept : m_Parent{ parentEntityId } {} -Component::Component(Entity* parent) { - m_Parent = parent; -} - -Component::~Component() { - -} +Component::~Component() {} Entity* Component::GetParent() const { - return m_Parent; -} - -void Component::Update(float deltaTime) { - + return Game::entityManager->GetEntity(m_Parent); //TEMP } -void Component::OnUse(Entity* originator) { +void Component::Update(float deltaTime) {} -} - -void Component::UpdateXml(tinyxml2::XMLDocument* doc) { +void Component::OnUse(Entity* originator) {} -} +void Component::UpdateXml(tinyxml2::XMLDocument* doc) {} -void Component::LoadFromXml(tinyxml2::XMLDocument* doc) { +void Component::LoadFromXml(tinyxml2::XMLDocument* doc) {} -} - -void Component::Serialize(RakNet::BitStream* outBitStream, bool isConstruction) { - -} +void Component::Serialize(RakNet::BitStream* outBitStream, bool isConstruction) {} diff --git a/dGame/dComponents/Component.h b/dGame/dComponents/Component.h index d1ad08600..57bba666c 100644 --- a/dGame/dComponents/Component.h +++ b/dGame/dComponents/Component.h @@ -10,8 +10,8 @@ class Entity; class Component { public: - Component(Entity* parent); - virtual ~Component(); + Component(const LWOOBJID& parentEntityId) noexcept; + virtual ~Component() = 0; /** * Gets the owner of this component @@ -43,12 +43,35 @@ class Component */ virtual void LoadFromXml(tinyxml2::XMLDocument* doc); + /** + * Serialize component + * @param outBitStream Raknet output bitstream + * @param isConstruction Boolean representing construction state + */ virtual void Serialize(RakNet::BitStream* outBitStream, bool isConstruction); protected: + /** + * Explicitly define default move and move-assignment constructors as + * definition of virtual destructor prevents their implicit generation + */ + Component(const Component& other) = delete; // Copy constructor (deleted) + Component(Component&& other) = default; // Move constructor + virtual Component& operator=(const Component& other) = delete; // Copy assignment constructor (deleted) + virtual Component& operator=(Component&& other) = default; // Move assignment constructor /** * The entity that owns this component */ - Entity* m_Parent; + LWOOBJID m_Parent; + + /** + * Helper function to check static assertions for derived classes + */ + template + consteval static void CheckComponentAssertions() { + //constexpr auto componentName = + static_assert(std::is_move_constructible(), "Component is not move-constructible!"); + static_assert(std::is_move_assignable(), "Component is not move-assignable!"); + } }; diff --git a/dGame/dComponents/ControllablePhysicsComponent.cpp b/dGame/dComponents/ControllablePhysicsComponent.cpp index be5227a00..3a357e5fe 100644 --- a/dGame/dComponents/ControllablePhysicsComponent.cpp +++ b/dGame/dComponents/ControllablePhysicsComponent.cpp @@ -15,7 +15,7 @@ #include "LevelProgressionComponent.h" #include "eStateChangeType.h" -ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity) : PhysicsComponent(entity) { +ControllablePhysicsComponent::ControllablePhysicsComponent(const LWOOBJID& parentEntityId) : PhysicsComponent{ parentEntityId } { m_Velocity = {}; m_AngularVelocity = {}; m_InJetpackMode = false; @@ -48,14 +48,15 @@ ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity) : Phy m_ImmuneToStunTurnCount = 0; m_ImmuneToStunUseItemCount = 0; - if (entity->GetLOT() != 1) // Other physics entities we care about will be added by BaseCombatAI + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + if (parentEntity->GetLOT() != 1) // Other physics entities we care about will be added by BaseCombatAI return; - if (entity->GetLOT() == 1) { + if (parentEntity->GetLOT() == 1) { LOG("Using patch to load minifig physics"); float radius = 1.5f; - m_dpEntity = new dpEntity(m_Parent->GetObjectID(), radius, false); + m_dpEntity = new dpEntity(m_Parent, radius, false); m_dpEntity->SetCollisionGroup(COLLISION_GROUP_DYNAMIC | COLLISION_GROUP_FRIENDLY); dpWorld::AddEntity(m_dpEntity); } @@ -165,7 +166,7 @@ void ControllablePhysicsComponent::LoadFromXml(tinyxml2::XMLDocument* doc) { return; } - m_Parent->GetCharacter()->LoadXmlRespawnCheckpoints(); + Game::entityManager->GetEntity(m_Parent)->GetCharacter()->LoadXmlRespawnCheckpoints(); character->QueryAttribute("lzx", &m_Position.x); character->QueryAttribute("lzy", &m_Position.y); @@ -300,7 +301,7 @@ void ControllablePhysicsComponent::RemoveSpeedboost(float value) { // Recalculate speedboost since we removed one m_SpeedBoost = 0.0f; if (m_ActiveSpeedBoosts.empty()) { // no active speed boosts left, so return to base speed - auto* levelProgressionComponent = m_Parent->GetComponent(); + auto* levelProgressionComponent = Game::entityManager->GetEntity(m_Parent)->GetComponent(); if (levelProgressionComponent) m_SpeedBoost = levelProgressionComponent->GetSpeedBase(); } else { // Used the last applied speedboost m_SpeedBoost = m_ActiveSpeedBoosts.back(); @@ -309,7 +310,7 @@ void ControllablePhysicsComponent::RemoveSpeedboost(float value) { Game::entityManager->SerializeEntity(m_Parent); } -void ControllablePhysicsComponent::ActivateBubbleBuff(eBubbleType bubbleType, bool specialAnims){ +void ControllablePhysicsComponent::ActivateBubbleBuff(eBubbleType bubbleType, bool specialAnims) { if (m_IsInBubble) { LOG("Already in bubble"); return; @@ -321,7 +322,7 @@ void ControllablePhysicsComponent::ActivateBubbleBuff(eBubbleType bubbleType, bo Game::entityManager->SerializeEntity(m_Parent); } -void ControllablePhysicsComponent::DeactivateBubbleBuff(){ +void ControllablePhysicsComponent::DeactivateBubbleBuff() { m_DirtyBubble = true; m_IsInBubble = false; Game::entityManager->SerializeEntity(m_Parent); @@ -336,9 +337,9 @@ void ControllablePhysicsComponent::SetStunImmunity( const bool bImmuneToStunJump, const bool bImmuneToStunMove, const bool bImmuneToStunTurn, - const bool bImmuneToStunUseItem){ + const bool bImmuneToStunUseItem) { - if (state == eStateChangeType::POP){ + if (state == eStateChangeType::POP) { if (bImmuneToStunAttack && m_ImmuneToStunAttackCount > 0) m_ImmuneToStunAttackCount -= 1; if (bImmuneToStunEquip && m_ImmuneToStunEquipCount > 0) m_ImmuneToStunEquipCount -= 1; if (bImmuneToStunInteract && m_ImmuneToStunInteractCount > 0) m_ImmuneToStunInteractCount -= 1; @@ -357,7 +358,7 @@ void ControllablePhysicsComponent::SetStunImmunity( } GameMessages::SendSetStunImmunity( - m_Parent->GetObjectID(), state, m_Parent->GetSystemAddress(), originator, + m_Parent, state, Game::entityManager->GetEntity(m_Parent)->GetSystemAddress(), originator, bImmuneToStunAttack, bImmuneToStunEquip, bImmuneToStunInteract, diff --git a/dGame/dComponents/ControllablePhysicsComponent.h b/dGame/dComponents/ControllablePhysicsComponent.h index e5c3f890d..a8ff13495 100644 --- a/dGame/dComponents/ControllablePhysicsComponent.h +++ b/dGame/dComponents/ControllablePhysicsComponent.h @@ -21,11 +21,17 @@ enum class eStateChangeType : uint32_t; */ class ControllablePhysicsComponent : public PhysicsComponent { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::CONTROLLABLE_PHYSICS; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::CONTROLLABLE_PHYSICS; - ControllablePhysicsComponent(Entity* entity); + ControllablePhysicsComponent(const LWOOBJID& parentEntityId); ~ControllablePhysicsComponent() override; + /** + * TODO: Defining move and move-assignment constructors as default as custom destructor + * disables implicit generation + */ + //ControllablePhysicsComponent(const ControllablePhysicsComponent&) = + void Update(float deltaTime) override; void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; void LoadFromXml(tinyxml2::XMLDocument* doc) override; diff --git a/dGame/dComponents/DestroyableComponent.cpp b/dGame/dComponents/DestroyableComponent.cpp index 64dca4f1d..cecb14f69 100644 --- a/dGame/dComponents/DestroyableComponent.cpp +++ b/dGame/dComponents/DestroyableComponent.cpp @@ -38,7 +38,11 @@ #include "CDComponentsRegistryTable.h" -DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) { +//DestroyableComponent::CheckComponentAssertions(); // Check static assertions + +DestroyableComponent::DestroyableComponent(const LWOOBJID& parentEntityId) : Component{ parentEntityId } { + CheckComponentAssertions(); + m_iArmor = 0; m_fMaxArmor = 0.0f; m_iImagination = 0; @@ -51,7 +55,7 @@ DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) { m_IsGMImmune = false; m_IsShielded = false; m_DamageToAbsorb = 0; - m_IsModuleAssembly = m_Parent->HasComponent(eReplicaComponentType::MODULE_ASSEMBLY); + m_IsModuleAssembly = Game::entityManager->GetEntity(m_Parent)->HasComponent(eReplicaComponentType::MODULE_ASSEMBLY); m_DirtyThreatList = false; m_HasThreats = false; m_ExplodeFactor = 1.0f; @@ -77,9 +81,6 @@ DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) { m_DamageCooldownTimer = 0.0f; } -DestroyableComponent::~DestroyableComponent() { -} - void DestroyableComponent::Reinitialize(LOT templateID) { CDComponentsRegistryTable* compRegistryTable = CDClientManager::Instance().GetTable(); @@ -192,7 +193,7 @@ void DestroyableComponent::LoadFromXml(tinyxml2::XMLDocument* doc) { return; } - auto* buffComponent = m_Parent->GetComponent(); + auto* buffComponent = Game::entityManager->GetEntity(m_Parent)->GetComponent(); if (buffComponent != nullptr) { buffComponent->LoadFromXml(doc); @@ -214,7 +215,8 @@ void DestroyableComponent::UpdateXml(tinyxml2::XMLDocument* doc) { return; } - auto* buffComponent = m_Parent->GetComponent(); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + auto* const buffComponent = parentEntity->GetComponent(); if (buffComponent != nullptr) { buffComponent->UpdateXml(doc); @@ -231,7 +233,7 @@ void DestroyableComponent::UpdateXml(tinyxml2::XMLDocument* doc) { void DestroyableComponent::SetHealth(int32_t value) { m_DirtyHealth = true; - auto* characterComponent = m_Parent->GetComponent(); + auto* characterComponent = Game::entityManager->GetEntity(m_Parent)->GetComponent(); if (characterComponent != nullptr) { characterComponent->TrackHealthDelta(value - m_iHealth); } @@ -251,13 +253,14 @@ void DestroyableComponent::SetMaxHealth(float value, bool playAnim) { if (playAnim) { // Now update the player bar - if (!m_Parent->GetParentUser()) return; + auto* const parentUser = Game::entityManager->GetEntity(m_Parent)->GetParentUser(); + if (!parentUser) return; AMFArrayValue args; args.Insert("amount", std::to_string(difference)); args.Insert("type", "health"); - GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent->GetParentUser()->GetSystemAddress(), "MaxPlayerBarUpdate", args); + GameMessages::SendUIMessageServerToSingleClient(m_Parent, parentUser->GetSystemAddress(), "MaxPlayerBarUpdate", args); } Game::entityManager->SerializeEntity(m_Parent); @@ -269,16 +272,18 @@ void DestroyableComponent::SetArmor(int32_t value) { // If Destroyable Component already has zero armor do not trigger the passive ability again. bool hadArmor = m_iArmor > 0; - auto* characterComponent = m_Parent->GetComponent(); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + + auto* const characterComponent = parentEntity->GetComponent(); if (characterComponent != nullptr) { characterComponent->TrackArmorDelta(value - m_iArmor); } m_iArmor = value; - auto* inventroyComponent = m_Parent->GetComponent(); - if (m_iArmor == 0 && inventroyComponent != nullptr && hadArmor) { - inventroyComponent->TriggerPassiveAbility(PassiveAbilityTrigger::SentinelArmor); + auto* const inventoryComponent = parentEntity->GetComponent(); + if (m_iArmor == 0 && inventoryComponent != nullptr && hadArmor) { + inventoryComponent->TriggerPassiveAbility(PassiveAbilityTrigger::SentinelArmor); } } @@ -292,13 +297,14 @@ void DestroyableComponent::SetMaxArmor(float value, bool playAnim) { if (playAnim) { // Now update the player bar - if (!m_Parent->GetParentUser()) return; + auto* const parentUser = Game::entityManager->GetEntity(m_Parent)->GetParentUser(); + if (!parentUser) return; AMFArrayValue args; args.Insert("amount", std::to_string(value)); args.Insert("type", "armor"); - GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent->GetParentUser()->GetSystemAddress(), "MaxPlayerBarUpdate", args); + GameMessages::SendUIMessageServerToSingleClient(m_Parent, parentUser->GetSystemAddress(), "MaxPlayerBarUpdate", args); } Game::entityManager->SerializeEntity(m_Parent); @@ -307,16 +313,18 @@ void DestroyableComponent::SetMaxArmor(float value, bool playAnim) { void DestroyableComponent::SetImagination(int32_t value) { m_DirtyHealth = true; - auto* characterComponent = m_Parent->GetComponent(); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + + auto* const characterComponent = parentEntity->GetComponent(); if (characterComponent != nullptr) { characterComponent->TrackImaginationDelta(value - m_iImagination); } m_iImagination = value; - auto* inventroyComponent = m_Parent->GetComponent(); - if (m_iImagination == 0 && inventroyComponent != nullptr) { - inventroyComponent->TriggerPassiveAbility(PassiveAbilityTrigger::AssemblyImagination); + auto* const inventoryComponent = parentEntity->GetComponent(); + if (m_iImagination == 0 && inventoryComponent != nullptr) { + inventoryComponent->TriggerPassiveAbility(PassiveAbilityTrigger::AssemblyImagination); } } @@ -332,13 +340,14 @@ void DestroyableComponent::SetMaxImagination(float value, bool playAnim) { if (playAnim) { // Now update the player bar - if (!m_Parent->GetParentUser()) return; + auto* const parentUser = Game::entityManager->GetEntity(m_Parent)->GetParentUser(); + if (!parentUser) return; AMFArrayValue args; args.Insert("amount", std::to_string(difference)); args.Insert("type", "imagination"); - GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent->GetParentUser()->GetSystemAddress(), "MaxPlayerBarUpdate", args); + GameMessages::SendUIMessageServerToSingleClient(m_Parent, parentUser->GetSystemAddress(), "MaxPlayerBarUpdate", args); } Game::entityManager->SerializeEntity(m_Parent); } @@ -415,8 +424,9 @@ void DestroyableComponent::AddFaction(const int32_t factionID, const bool ignore } bool DestroyableComponent::IsEnemy(const Entity* other) const { - if (m_Parent->IsPlayer() && other->IsPlayer()) { - auto* thisCharacterComponent = m_Parent->GetComponent(); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + if (parentEntity->IsPlayer() && other->IsPlayer()) { + auto* thisCharacterComponent = parentEntity->GetComponent(); if (!thisCharacterComponent) return false; auto* otherCharacterComponent = other->GetComponent(); if (!otherCharacterComponent) return false; @@ -475,8 +485,9 @@ bool DestroyableComponent::IsCooldownImmune() const { } bool DestroyableComponent::IsKnockbackImmune() const { - auto* characterComponent = m_Parent->GetComponent(); - auto* inventoryComponent = m_Parent->GetComponent(); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + auto* const characterComponent = parentEntity->GetComponent(); + auto* const inventoryComponent = parentEntity->GetComponent(); if (characterComponent != nullptr && inventoryComponent != nullptr && characterComponent->GetCurrentActivity() == eGameActivity::QUICKBUILDING) { const auto hasPassive = inventoryComponent->HasAnyPassive({ @@ -557,7 +568,7 @@ void DestroyableComponent::Damage(uint32_t damage, const LWOOBJID source, uint32 } if (IsImmune() || IsCooldownImmune()) { - LOG_DEBUG("Target targetEntity %llu is immune!", m_Parent->GetObjectID()); + LOG_DEBUG("Target targetEntity %llu is immune!", m_Parent); return; } @@ -599,25 +610,27 @@ void DestroyableComponent::Damage(uint32_t damage, const LWOOBJID source, uint32 SetHealth(health); SetIsShielded(absorb > 0); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + // Dismount on the possessable hit - auto possessable = m_Parent->GetComponent(); + auto possessable = parentEntity->GetComponent(); if (possessable && possessable->GetDepossessOnHit()) { possessable->Dismount(); } // Dismount on the possessor hit - auto possessor = m_Parent->GetComponent(); + auto possessor = parentEntity->GetComponent(); if (possessor) { auto possessableId = possessor->GetPossessable(); if (possessableId != LWOOBJID_EMPTY) { - auto possessable = Game::entityManager->GetEntity(possessableId); + auto* possessable = Game::entityManager->GetEntity(possessableId); if (possessable) { possessor->Dismount(possessable); } } } - if (m_Parent->GetLOT() != 1) { + if (parentEntity->GetLOT() != 1) { echo = true; } @@ -626,8 +639,8 @@ void DestroyableComponent::Damage(uint32_t damage, const LWOOBJID source, uint32 } auto* attacker = Game::entityManager->GetEntity(source); - m_Parent->OnHit(attacker); - m_Parent->OnHitOrHealResult(attacker, sourceDamage); + parentEntity->OnHit(attacker); + parentEntity->OnHitOrHealResult(attacker, sourceDamage); NotifySubscribers(attacker, sourceDamage); for (const auto& cb : m_OnHitCallbacks) { @@ -635,10 +648,10 @@ void DestroyableComponent::Damage(uint32_t damage, const LWOOBJID source, uint32 } if (health != 0) { - auto* combatComponent = m_Parent->GetComponent(); + auto* combatComponent = parentEntity->GetComponent(); if (combatComponent != nullptr) { - combatComponent->Taunt(source, sourceDamage * 10); // * 10 is arbatrary + combatComponent->Taunt(source, sourceDamage * 10); // * 10 is arbitrary } return; @@ -654,7 +667,7 @@ void DestroyableComponent::Damage(uint32_t damage, const LWOOBJID source, uint32 void DestroyableComponent::Subscribe(LWOOBJID scriptObjId, CppScripts::Script* scriptToAdd) { m_SubscribedScripts.insert(std::make_pair(scriptObjId, scriptToAdd)); - LOG_DEBUG("Added script %llu to entity %llu", scriptObjId, m_Parent->GetObjectID()); + LOG_DEBUG("Added script %llu to entity %llu", scriptObjId, m_Parent); LOG_DEBUG("Number of subscribed scripts %i", m_SubscribedScripts.size()); } @@ -662,16 +675,16 @@ void DestroyableComponent::Unsubscribe(LWOOBJID scriptObjId) { auto foundScript = m_SubscribedScripts.find(scriptObjId); if (foundScript != m_SubscribedScripts.end()) { m_SubscribedScripts.erase(foundScript); - LOG_DEBUG("Removed script %llu from entity %llu", scriptObjId, m_Parent->GetObjectID()); + LOG_DEBUG("Removed script %llu from entity %llu", scriptObjId, m_Parent); } else { - LOG_DEBUG("Tried to remove a script for Entity %llu but script %llu didnt exist", m_Parent->GetObjectID(), scriptObjId); + LOG_DEBUG("Tried to remove a script for Entity %llu but script %llu didnt exist", m_Parent, scriptObjId); } LOG_DEBUG("Number of subscribed scripts %i", m_SubscribedScripts.size()); } void DestroyableComponent::NotifySubscribers(Entity* attacker, uint32_t damage) { for (auto script : m_SubscribedScripts) { - script.second->NotifyHitOrHealResult(m_Parent, attacker, damage); + script.second->NotifyHitOrHealResult(Game::entityManager->GetEntity(m_Parent), attacker, damage); } } @@ -685,56 +698,53 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType m_KillerID = source; - auto* owner = Game::entityManager->GetEntity(source); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + auto* owner = Game::entityManager->GetEntity(source); if (owner != nullptr) { owner = owner->GetOwner(); // If the owner is overwritten, we collect that here - auto* team = TeamManager::Instance()->GetTeam(owner->GetObjectID()); - - const auto isEnemy = m_Parent->GetComponent() != nullptr; - - auto* inventoryComponent = owner->GetComponent(); + const auto isEnemy = parentEntity->GetComponent() != nullptr; + auto* const inventoryComponent = owner->GetComponent(); if (inventoryComponent != nullptr && isEnemy) { - inventoryComponent->TriggerPassiveAbility(PassiveAbilityTrigger::EnemySmashed, m_Parent); + inventoryComponent->TriggerPassiveAbility(PassiveAbilityTrigger::EnemySmashed, parentEntity); } auto* missions = owner->GetComponent(); if (missions != nullptr) { + auto* const team = TeamManager::Instance()->GetTeam(owner->GetObjectID()); if (team != nullptr) { for (const auto memberId : team->members) { auto* member = Game::entityManager->GetEntity(memberId); - - if (member == nullptr) continue; + if (!member) continue; auto* memberMissions = member->GetComponent(); + if (!memberMissions) continue; - if (memberMissions == nullptr) continue; - - memberMissions->Progress(eMissionTaskType::SMASH, m_Parent->GetLOT()); - memberMissions->Progress(eMissionTaskType::USE_SKILL, m_Parent->GetLOT(), skillID); + memberMissions->Progress(eMissionTaskType::SMASH, parentEntity->GetLOT()); + memberMissions->Progress(eMissionTaskType::USE_SKILL, parentEntity->GetLOT(), skillID); } } else { - missions->Progress(eMissionTaskType::SMASH, m_Parent->GetLOT()); - missions->Progress(eMissionTaskType::USE_SKILL, m_Parent->GetLOT(), skillID); + missions->Progress(eMissionTaskType::SMASH, parentEntity->GetLOT()); + missions->Progress(eMissionTaskType::USE_SKILL, parentEntity->GetLOT(), skillID); } } } - const auto isPlayer = m_Parent->IsPlayer(); + const auto isPlayer = parentEntity->IsPlayer(); - GameMessages::SendDie(m_Parent, source, source, true, killType, deathType, 0, 0, 0, isPlayer, false, 1); + GameMessages::SendDie(parentEntity, source, source, true, killType, deathType, 0, 0, 0, isPlayer, false, 1); //NANI?! if (!isPlayer) { if (owner != nullptr) { auto* team = TeamManager::Instance()->GetTeam(owner->GetObjectID()); - if (team != nullptr && m_Parent->GetComponent() != nullptr) { + if (team != nullptr && parentEntity->GetComponent() != nullptr) { LWOOBJID specificOwner = LWOOBJID_EMPTY; - auto* scriptedActivityComponent = m_Parent->GetComponent(); + auto* scriptedActivityComponent = parentEntity->GetComponent(); uint32_t teamSize = team->members.size(); uint32_t lootMatrixId = GetLootMatrixID(); @@ -747,24 +757,24 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType auto* member = Game::entityManager->GetEntity(specificOwner); - if (member) Loot::DropLoot(member, m_Parent, lootMatrixId, GetMinCoins(), GetMaxCoins()); + if (member) Loot::DropLoot(member, parentEntity, lootMatrixId, GetMinCoins(), GetMaxCoins()); } else { for (const auto memberId : team->members) { // Free for all auto* member = Game::entityManager->GetEntity(memberId); if (member == nullptr) continue; - Loot::DropLoot(member, m_Parent, lootMatrixId, GetMinCoins(), GetMaxCoins()); + Loot::DropLoot(member, parentEntity, lootMatrixId, GetMinCoins(), GetMaxCoins()); } } } else { // drop loot for non team user - Loot::DropLoot(owner, m_Parent, GetLootMatrixID(), GetMinCoins(), GetMaxCoins()); + Loot::DropLoot(owner, parentEntity, GetLootMatrixID(), GetMinCoins(), GetMaxCoins()); } } } else { //Check if this zone allows coin drops if (Game::zoneManager->GetPlayerLoseCoinOnDeath()) { - auto* character = m_Parent->GetCharacter(); + auto* character = parentEntity->GetCharacter(); uint64_t coinsTotal = character->GetCoins(); const uint64_t minCoinsToLose = Game::zoneManager->GetWorldConfig()->coinsLostOnDeathMin; if (coinsTotal >= minCoinsToLose) { @@ -776,27 +786,27 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType coinsTotal -= coinsToLose; - Loot::DropLoot(m_Parent, m_Parent, -1, coinsToLose, coinsToLose); + Loot::DropLoot(parentEntity, parentEntity, -1, coinsToLose, coinsToLose); character->SetCoins(coinsTotal, eLootSourceType::PICKUP); } } Entity* zoneControl = Game::entityManager->GetZoneControlEntity(); for (CppScripts::Script* script : CppScripts::GetEntityScripts(zoneControl)) { - script->OnPlayerDied(zoneControl, m_Parent); + script->OnPlayerDied(zoneControl, parentEntity); } std::vector scriptedActs = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::SCRIPTED_ACTIVITY); for (Entity* scriptEntity : scriptedActs) { if (scriptEntity->GetObjectID() != zoneControl->GetObjectID()) { // Don't want to trigger twice on instance worlds for (CppScripts::Script* script : CppScripts::GetEntityScripts(scriptEntity)) { - script->OnPlayerDied(scriptEntity, m_Parent); + script->OnPlayerDied(scriptEntity, parentEntity); } } } } - m_Parent->Kill(owner, killType); + parentEntity->Kill(owner, killType); } void DestroyableComponent::SetFaction(int32_t factionID, bool ignoreChecks) { @@ -842,7 +852,7 @@ void DestroyableComponent::SetStatusImmunity( } GameMessages::SendSetStatusImmunity( - m_Parent->GetObjectID(), state, m_Parent->GetSystemAddress(), + m_Parent, state, Game::entityManager->GetEntity(m_Parent)->GetSystemAddress(), bImmuneToBasicAttack, bImmuneToDamageOverTime, bImmuneToKnockback, @@ -958,19 +968,20 @@ void DestroyableComponent::AddOnHitCallback(const std::function& void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source) { //check if this is a player: - if (m_Parent->IsPlayer()) { + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + if (parentEntity->IsPlayer()) { //remove hardcore_lose_uscore_on_death_percent from the player's uscore: - auto* character = m_Parent->GetComponent(); + auto* character = parentEntity->GetComponent(); auto uscore = character->GetUScore(); auto uscoreToLose = uscore * (Game::entityManager->GetHardcoreLoseUscoreOnDeathPercent() / 100); character->SetUScore(uscore - uscoreToLose); - GameMessages::SendModifyLEGOScore(m_Parent, m_Parent->GetSystemAddress(), -uscoreToLose, eLootSourceType::MISSION); + GameMessages::SendModifyLEGOScore(parentEntity, parentEntity->GetSystemAddress(), -uscoreToLose, eLootSourceType::MISSION); if (Game::entityManager->GetHardcoreDropinventoryOnDeath()) { //drop all items from inventory: - auto* inventory = m_Parent->GetComponent(); + auto* inventory = parentEntity->GetComponent(); if (inventory) { //get the items inventory: auto items = inventory->GetInventory(eInventoryType::ITEMS); @@ -982,7 +993,7 @@ void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source) { if (!item.second) continue; // don't drop the thinkng cap if (item.second->GetLot() == 6086) continue; - GameMessages::SendDropClientLoot(m_Parent, source, item.second->GetLot(), 0, m_Parent->GetPosition(), item.second->GetCount()); + GameMessages::SendDropClientLoot(m_Parent, source, item.second->GetLot(), 0, parentEntity->GetPosition(), item.second->GetCount(), parentEntity->GetSystemAddress()); item.second->SetCount(0, false, false); } Game::entityManager->SerializeEntity(m_Parent); @@ -992,7 +1003,7 @@ void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source) { } //get character: - auto* chars = m_Parent->GetCharacter(); + auto* chars = parentEntity->GetCharacter(); if (chars) { auto coins = chars->GetCoins(); @@ -1000,13 +1011,13 @@ void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source) { chars->SetCoins(0, eLootSourceType::NONE); //drop all coins: - GameMessages::SendDropClientLoot(m_Parent, source, LOT_NULL, coins, m_Parent->GetPosition()); + GameMessages::SendDropClientLoot(m_Parent, source, LOT_NULL, coins, parentEntity->GetPosition(), 1, parentEntity->GetSystemAddress()); } // Reload the player since we can't normally reduce uscore from the server and we want the UI to update // do this last so we don't get killed.... again - Game::entityManager->DestructEntity(m_Parent); - Game::entityManager->ConstructEntity(m_Parent); + Game::entityManager->DestructEntity(parentEntity); + Game::entityManager->ConstructEntity(parentEntity); return; } diff --git a/dGame/dComponents/DestroyableComponent.h b/dGame/dComponents/DestroyableComponent.h index b81ab9f31..45c6df8af 100644 --- a/dGame/dComponents/DestroyableComponent.h +++ b/dGame/dComponents/DestroyableComponent.h @@ -19,10 +19,12 @@ enum class eStateChangeType : uint32_t; */ class DestroyableComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::DESTROYABLE; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::DESTROYABLE; - DestroyableComponent(Entity* parentEntity); - ~DestroyableComponent() override; + DestroyableComponent(const LWOOBJID& parentEntityId); + ~DestroyableComponent() override = default; + DestroyableComponent(DestroyableComponent&& other) = default; + DestroyableComponent& operator=(DestroyableComponent&& other) = default; void Update(float deltaTime) override; void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; diff --git a/dGame/dComponents/DonationVendorComponent.cpp b/dGame/dComponents/DonationVendorComponent.cpp index 6abc959ac..555cd14f5 100644 --- a/dGame/dComponents/DonationVendorComponent.cpp +++ b/dGame/dComponents/DonationVendorComponent.cpp @@ -1,18 +1,20 @@ #include "DonationVendorComponent.h" #include "Database.h" -DonationVendorComponent::DonationVendorComponent(Entity* parent) : VendorComponent(parent) { +DonationVendorComponent::DonationVendorComponent(const LWOOBJID& parentEntityId) : VendorComponent{ parentEntityId } { //LoadConfigData m_PercentComplete = 0.0; m_TotalDonated = 0; m_TotalRemaining = 0; + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + // custom attribute to calculate other values - m_Goal = m_Parent->GetVar(u"donationGoal"); + m_Goal = parentEntity->GetVar(u"donationGoal"); if (m_Goal == 0) m_Goal = INT32_MAX; // Default to the nexus tower jawbox activity and setup settings - m_ActivityId = m_Parent->GetVar(u"activityID"); + m_ActivityId = parentEntity->GetVar(u"activityID"); if ((m_ActivityId == 0) || (m_ActivityId == 117)) { m_ActivityId = 117; m_PercentComplete = 1.0; @@ -25,14 +27,14 @@ DonationVendorComponent::DonationVendorComponent(Entity* parent) : VendorCompone auto donationTotal = Database::Get()->GetDonationTotal(m_ActivityId); if (donationTotal) m_TotalDonated = donationTotal.value(); m_TotalRemaining = m_Goal - m_TotalDonated; - m_PercentComplete = m_TotalDonated/static_cast(m_Goal); + m_PercentComplete = m_TotalDonated / static_cast(m_Goal); } void DonationVendorComponent::SubmitDonation(uint32_t count) { if (count <= 0 && ((m_TotalDonated + count) > 0)) return; m_TotalDonated += count; m_TotalRemaining = m_Goal - m_TotalDonated; - m_PercentComplete = m_TotalDonated/static_cast(m_Goal); + m_PercentComplete = m_TotalDonated / static_cast(m_Goal); m_DirtyDonationVendor = true; } diff --git a/dGame/dComponents/DonationVendorComponent.h b/dGame/dComponents/DonationVendorComponent.h index d1743118d..1c8d34c4d 100644 --- a/dGame/dComponents/DonationVendorComponent.h +++ b/dGame/dComponents/DonationVendorComponent.h @@ -8,8 +8,8 @@ class Entity; class DonationVendorComponent final : public VendorComponent { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::DONATION_VENDOR; - DonationVendorComponent(Entity* parent); + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::DONATION_VENDOR; + DonationVendorComponent(const LWOOBJID& parentEntityId); void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; uint32_t GetActivityID() {return m_ActivityId;}; void SubmitDonation(uint32_t count); diff --git a/dGame/dComponents/GhostComponent.cpp b/dGame/dComponents/GhostComponent.cpp index 2978c9126..67516a8dc 100644 --- a/dGame/dComponents/GhostComponent.cpp +++ b/dGame/dComponents/GhostComponent.cpp @@ -1,8 +1,8 @@ #include "GhostComponent.h" -GhostComponent::GhostComponent(Entity* parent) : Component(parent) { - m_GhostReferencePoint = NiPoint3::ZERO; - m_GhostOverridePoint = NiPoint3::ZERO; +GhostComponent::GhostComponent(const LWOOBJID& parentEntityId) noexcept : Component{ parentEntityId } { + m_GhostReferencePoint = NiPoint3Constant::ZERO; + m_GhostOverridePoint = NiPoint3Constant::ZERO; m_GhostOverride = false; } @@ -38,7 +38,7 @@ void GhostComponent::ConstructLimboEntities() { auto* entity = Game::entityManager->GetEntity(objectId); if (!entity) continue; - Game::entityManager->ConstructEntity(entity, m_Parent->GetSystemAddress()); + Game::entityManager->ConstructEntity(entity, Game::entityManager->GetEntity(m_Parent)->GetSystemAddress()); } m_LimboConstructions.clear(); diff --git a/dGame/dComponents/GhostComponent.h b/dGame/dComponents/GhostComponent.h index 5ae308a40..ab8997b6d 100644 --- a/dGame/dComponents/GhostComponent.h +++ b/dGame/dComponents/GhostComponent.h @@ -10,7 +10,7 @@ class NiPoint3; class GhostComponent : public Component { public: static inline const eReplicaComponentType ComponentType = eReplicaComponentType::GHOST; - GhostComponent(Entity* parent); + GhostComponent(const LWOOBJID& parentEntityId) noexcept; ~GhostComponent() override; void SetGhostOverride(bool value) { m_GhostOverride = value; }; diff --git a/dGame/dComponents/HavokVehiclePhysicsComponent.cpp b/dGame/dComponents/HavokVehiclePhysicsComponent.cpp index 62e49a56b..1a462339f 100644 --- a/dGame/dComponents/HavokVehiclePhysicsComponent.cpp +++ b/dGame/dComponents/HavokVehiclePhysicsComponent.cpp @@ -1,9 +1,9 @@ #include "HavokVehiclePhysicsComponent.h" #include "EntityManager.h" -HavokVehiclePhysicsComponent::HavokVehiclePhysicsComponent(Entity* parent) : PhysicsComponent(parent) { - m_Velocity = NiPoint3::ZERO; - m_AngularVelocity = NiPoint3::ZERO; +HavokVehiclePhysicsComponent::HavokVehiclePhysicsComponent(const LWOOBJID& parentEntityId) : PhysicsComponent{ parentEntityId } { + m_Velocity = NiPoint3Constant::ZERO; + m_AngularVelocity = NiPoint3Constant::ZERO; m_IsOnGround = true; m_IsOnRail = false; m_DirtyPosition = true; diff --git a/dGame/dComponents/HavokVehiclePhysicsComponent.h b/dGame/dComponents/HavokVehiclePhysicsComponent.h index ba46f093f..5e1fb1691 100644 --- a/dGame/dComponents/HavokVehiclePhysicsComponent.h +++ b/dGame/dComponents/HavokVehiclePhysicsComponent.h @@ -11,9 +11,9 @@ */ class HavokVehiclePhysicsComponent : public PhysicsComponent { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::HAVOK_VEHICLE_PHYSICS; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::HAVOK_VEHICLE_PHYSICS; - HavokVehiclePhysicsComponent(Entity* parentEntity); + HavokVehiclePhysicsComponent(const LWOOBJID& parentEntityId); void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index 23d5c163b..10d98d62a 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -39,14 +39,16 @@ #include "CDObjectSkillsTable.h" #include "CDSkillBehaviorTable.h" -InventoryComponent::InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document) : Component(parent) { +InventoryComponent::InventoryComponent(const LWOOBJID& parentEntityId, tinyxml2::XMLDocument* document) : Component{ parentEntityId } { + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + this->m_Dirty = true; this->m_Equipped = {}; this->m_Pushed = {}; this->m_Consumable = LOT_NULL; this->m_Pets = {}; - const auto lot = parent->GetLOT(); + const auto lot = parentEntity->GetLOT(); if (lot == 1) { LoadXml(document); @@ -193,9 +195,11 @@ void InventoryComponent::AddItem( inventoryType = Inventory::FindInventoryTypeForLot(lot); } - auto* missions = static_cast(this->m_Parent->GetComponent(eReplicaComponentType::MISSION)); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); - auto* inventory = GetInventory(inventoryType); + auto* const missions = static_cast(parentEntity->GetComponent(eReplicaComponentType::MISSION)); + + auto* const inventory = GetInventory(inventoryType); if (!config.empty() || bound) { const auto slot = preferredSlot != -1 && inventory->IsSlotEmpty(preferredSlot) ? preferredSlot : inventory->FindEmptySlot(); @@ -269,12 +273,12 @@ void InventoryComponent::AddItem( switch (sourceType) { case 0: - Mail::SendMail(LWOOBJID_EMPTY, "Darkflame Universe", m_Parent, "Lost Reward", "You received an item and didn't have room for it.", lot, size); + Mail::SendMail(LWOOBJID_EMPTY, "Darkflame Universe", Game::entityManager->GetEntity(m_Parent), "Lost Reward", "You received an item and didn't have room for it.", lot, size); break; case 1: for (size_t i = 0; i < size; i++) { - GameMessages::SendDropClientLoot(this->m_Parent, this->m_Parent->GetObjectID(), lot, 0, this->m_Parent->GetPosition(), 1); + GameMessages::SendDropClientLoot(m_Parent, m_Parent, lot, 0, parentEntity->GetPosition(), 1, parentEntity->GetSystemAddress()); } break; @@ -364,7 +368,7 @@ void InventoryComponent::MoveItemToInventory(Item* item, const eInventoryType in item->SetCount(item->GetCount() - delta, false, false); } - auto* missionComponent = m_Parent->GetComponent(); + auto* missionComponent = Game::entityManager->GetEntity(m_Parent)->GetComponent(); if (missionComponent != nullptr) { if (IsTransferInventory(inventory)) { @@ -465,7 +469,7 @@ bool InventoryComponent::HasSpaceForLoot(const std::unordered_map& } if (slotsNeeded > 0) { - GameMessages::SendNotifyNotEnoughInvSpace(m_Parent->GetObjectID(), slotsNeeded, ITEMS, m_Parent->GetSystemAddress()); + GameMessages::SendNotifyNotEnoughInvSpace(m_Parent, slotsNeeded, ITEMS, Game::entityManager->GetEntity(m_Parent)->GetSystemAddress()); return false; } @@ -803,14 +807,15 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) { return; } - auto* character = m_Parent->GetCharacter(); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + auto* const character = parentEntity->GetCharacter(); if (character != nullptr && !skipChecks) { // Hacky proximity rocket if (item->GetLot() == 6416) { const auto rocketLauchPads = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::ROCKET_LAUNCH); - const auto position = m_Parent->GetPosition(); + const auto position = parentEntity->GetPosition(); for (auto* launchPad : rocketLauchPads) { if (!launchPad) continue; @@ -818,16 +823,16 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) { auto prereq = launchPad->GetVarAsString(u"rocketLaunchPreCondition"); if (!prereq.empty()) { PreconditionExpression expression(prereq); - if (!expression.Check(m_Parent)) continue; + if (!expression.Check(parentEntity)) continue; } if (Vector3::DistanceSquared(launchPad->GetPosition(), position) > 13 * 13) continue; - auto* characterComponent = m_Parent->GetComponent(); + auto* characterComponent = parentEntity->GetComponent(); if (characterComponent != nullptr) characterComponent->SetLastRocketItemID(item->GetId()); - launchPad->OnUse(m_Parent); + launchPad->OnUse(parentEntity); break; } @@ -843,7 +848,7 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) { if (!building && (item->GetLot() == 6086 || type == eItemType::LOOT_MODEL || type == eItemType::VEHICLE)) return; if (type != eItemType::LOOT_MODEL && type != eItemType::MODEL) { - if (!item->GetBound() && !item->GetPreconditionExpression()->Check(m_Parent)) { + if (!item->GetBound() && !item->GetPreconditionExpression()->Check(parentEntity)) { return; } } @@ -902,9 +907,10 @@ void InventoryComponent::UnEquipItem(Item* item) { Game::entityManager->SerializeEntity(m_Parent); // Trigger property event + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); if (PropertyManagementComponent::Instance() != nullptr && item->GetCount() > 0 && Inventory::FindInventoryTypeForLot(item->GetLot()) == MODELS) { - PropertyManagementComponent::Instance()->GetParent()->OnZonePropertyModelRemovedWhileEquipped(m_Parent); - Game::zoneManager->GetZoneControlObject()->OnZonePropertyModelRemovedWhileEquipped(m_Parent); + PropertyManagementComponent::Instance()->GetParent()->OnZonePropertyModelRemovedWhileEquipped(parentEntity); + Game::zoneManager->GetZoneControlObject()->OnZonePropertyModelRemovedWhileEquipped(parentEntity); } } @@ -912,38 +918,46 @@ void InventoryComponent::UnEquipItem(Item* item) { void InventoryComponent::EquipScripts(Item* equippedItem) { CDComponentsRegistryTable* compRegistryTable = CDClientManager::Instance().GetTable(); if (!compRegistryTable) return; + + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + int32_t scriptComponentID = compRegistryTable->GetByIDAndType(equippedItem->GetLot(), eReplicaComponentType::SCRIPT, -1); if (scriptComponentID > -1) { CDScriptComponentTable* scriptCompTable = CDClientManager::Instance().GetTable(); CDScriptComponent scriptCompData = scriptCompTable->GetByID(scriptComponentID); - auto* itemScript = CppScripts::GetScript(m_Parent, scriptCompData.script_name); + auto* const itemScript = CppScripts::GetScript(parentEntity, scriptCompData.script_name); if (!itemScript) { LOG("null script?"); } - itemScript->OnFactionTriggerItemEquipped(m_Parent, equippedItem->GetId()); + itemScript->OnFactionTriggerItemEquipped(parentEntity, equippedItem->GetId()); } } void InventoryComponent::UnequipScripts(Item* unequippedItem) { CDComponentsRegistryTable* compRegistryTable = CDClientManager::Instance().GetTable(); if (!compRegistryTable) return; + + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + int32_t scriptComponentID = compRegistryTable->GetByIDAndType(unequippedItem->GetLot(), eReplicaComponentType::SCRIPT, -1); if (scriptComponentID > -1) { CDScriptComponentTable* scriptCompTable = CDClientManager::Instance().GetTable(); CDScriptComponent scriptCompData = scriptCompTable->GetByID(scriptComponentID); - auto* itemScript = CppScripts::GetScript(m_Parent, scriptCompData.script_name); + auto* itemScript = CppScripts::GetScript(parentEntity, scriptCompData.script_name); if (!itemScript) { LOG("null script?"); } - itemScript->OnFactionTriggerItemUnequipped(m_Parent, unequippedItem->GetId()); + itemScript->OnFactionTriggerItemUnequipped(parentEntity, unequippedItem->GetId()); } } void InventoryComponent::HandlePossession(Item* item) { - auto* characterComponent = m_Parent->GetComponent(); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + + auto* characterComponent = parentEntity->GetComponent(); if (!characterComponent) return; - auto* possessorComponent = m_Parent->GetComponent(); + auto* possessorComponent = parentEntity->GetComponent(); if (!possessorComponent) return; // Don't do anything if we are busy dismounting @@ -958,22 +972,22 @@ void InventoryComponent::HandlePossession(Item* item) { return; } - GameMessages::SendSetStunned(m_Parent->GetObjectID(), eStateChangeType::PUSH, m_Parent->GetSystemAddress(), LWOOBJID_EMPTY, true, false, true, false, false, false, false, true, true, true, true, true, true, true, true, true); + GameMessages::SendSetStunned(m_Parent, eStateChangeType::PUSH, parentEntity->GetSystemAddress(), LWOOBJID_EMPTY, true, false, true, false, false, false, false, true, true, true, true, true, true, true, true, true); // Set the mount Item ID so that we know what were handling possessorComponent->SetMountItemID(item->GetId()); - GameMessages::SendSetMountInventoryID(m_Parent, item->GetId(), UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::SendSetMountInventoryID(parentEntity, item->GetId(), UNASSIGNED_SYSTEM_ADDRESS); // Create entity to mount - auto startRotation = m_Parent->GetRotation(); + auto startRotation = parentEntity->GetRotation(); EntityInfo info{}; info.lot = item->GetLot(); - info.pos = m_Parent->GetPosition(); + info.pos = parentEntity->GetPosition(); info.rot = startRotation; - info.spawnerID = m_Parent->GetObjectID(); + info.spawnerID = m_Parent; - auto* mount = Game::entityManager->CreateEntity(info, nullptr, m_Parent); + auto* mount = Game::entityManager->CreateEntity(info, nullptr, parentEntity); // Check to see if the mount is a vehicle, if so, flip it auto* vehicleComponent = mount->GetComponent(); @@ -989,13 +1003,13 @@ void InventoryComponent::HandlePossession(Item* item) { auto* possessableComponent = mount->GetComponent(); if (possessableComponent) { possessableComponent->SetIsItemSpawned(true); - possessableComponent->SetPossessor(m_Parent->GetObjectID()); + possessableComponent->SetPossessor(m_Parent); // Possess it possessorComponent->SetPossessable(mount->GetObjectID()); possessorComponent->SetPossessableType(possessableComponent->GetPossessionType()); } - GameMessages::SendSetJetPackMode(m_Parent, false); + GameMessages::SendSetJetPackMode(parentEntity, false); // Make it go to the client Game::entityManager->ConstructEntity(mount); @@ -1003,15 +1017,15 @@ void InventoryComponent::HandlePossession(Item* item) { Game::entityManager->SerializeEntity(m_Parent); // have to unlock the input so it vehicle can be driven - if (vehicleComponent) GameMessages::SendVehicleUnlockInput(mount->GetObjectID(), false, m_Parent->GetSystemAddress()); - GameMessages::SendMarkInventoryItemAsActive(m_Parent->GetObjectID(), true, eUnequippableActiveType::MOUNT, item->GetId(), m_Parent->GetSystemAddress()); + if (vehicleComponent) GameMessages::SendVehicleUnlockInput(mount->GetObjectID(), false, parentEntity->GetSystemAddress()); + GameMessages::SendMarkInventoryItemAsActive(m_Parent, true, eUnequippableActiveType::MOUNT, item->GetId(), parentEntity->GetSystemAddress()); } void InventoryComponent::ApplyBuff(Item* item) const { const auto buffs = FindBuffs(item, true); for (const auto buff : buffs) { - SkillComponent::HandleUnmanaged(buff, m_Parent->GetObjectID()); + SkillComponent::HandleUnmanaged(buff, m_Parent); } } @@ -1020,7 +1034,7 @@ void InventoryComponent::RemoveBuff(Item* item) const { const auto buffs = FindBuffs(item, false); for (const auto buff : buffs) { - SkillComponent::HandleUnCast(buff, m_Parent->GetObjectID()); + SkillComponent::HandleUnCast(buff, m_Parent); } } @@ -1055,7 +1069,7 @@ void InventoryComponent::PopEquippedItems() { m_Pushed.clear(); - auto destroyableComponent = m_Parent->GetComponent(); + auto destroyableComponent = Game::entityManager->GetEntity(m_Parent)->GetComponent(); // Reset stats to full if (destroyableComponent) { @@ -1161,14 +1175,16 @@ void InventoryComponent::RemoveItemSkills(const LOT lot) { const auto old = index->second; - GameMessages::SendRemoveSkill(m_Parent, old); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + + GameMessages::SendRemoveSkill(parentEntity, old); m_Skills.erase(slot); if (slot == BehaviorSlot::Primary) { m_Skills.insert_or_assign(BehaviorSlot::Primary, 1); - GameMessages::SendAddSkill(m_Parent, 1, BehaviorSlot::Primary); + GameMessages::SendAddSkill(parentEntity, 1, BehaviorSlot::Primary); } } @@ -1194,7 +1210,7 @@ bool InventoryComponent::HasAnyPassive(const std::vectorGetObjectID()); + auto* current = PetComponent::GetActivePet(m_Parent); if (current != nullptr) { current->Deactivate(); @@ -1202,7 +1218,7 @@ void InventoryComponent::DespawnPet() { } void InventoryComponent::SpawnPet(Item* item) { - auto* current = PetComponent::GetActivePet(m_Parent->GetObjectID()); + auto* current = PetComponent::GetActivePet(m_Parent); if (current != nullptr) { current->Deactivate(); @@ -1212,19 +1228,21 @@ void InventoryComponent::SpawnPet(Item* item) { } } + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + // First check if we can summon the pet. You need 1 imagination to do so. - auto destroyableComponent = m_Parent->GetComponent(); + auto destroyableComponent = parentEntity->GetComponent(); if (Game::config->GetValue("pets_take_imagination") == "1" && destroyableComponent && destroyableComponent->GetImagination() <= 0) { - GameMessages::SendUseItemRequirementsResponse(m_Parent->GetObjectID(), m_Parent->GetSystemAddress(), eUseItemResponse::NoImaginationForPet); + GameMessages::SendUseItemRequirementsResponse(m_Parent, parentEntity->GetSystemAddress(), eUseItemResponse::NoImaginationForPet); return; } EntityInfo info{}; info.lot = item->GetLot(); - info.pos = m_Parent->GetPosition(); - info.rot = NiQuaternion::IDENTITY; - info.spawnerID = m_Parent->GetObjectID(); + info.pos = parentEntity->GetPosition(); + info.rot = NiQuaternionConstant::IDENTITY; + info.spawnerID = m_Parent; auto* pet = Game::entityManager->CreateEntity(info); @@ -1306,7 +1324,7 @@ std::vector InventoryComponent::FindBuffs(Item* item, bool castOnEquip return entry.objectTemplate == static_cast(item->GetLot()); }); - auto* missions = static_cast(m_Parent->GetComponent(eReplicaComponentType::MISSION)); + auto* missions = static_cast(Game::entityManager->GetEntity(m_Parent)->GetComponent(eReplicaComponentType::MISSION)); for (const auto& result : results) { if (result.castOnType == 1) { @@ -1600,26 +1618,29 @@ void InventoryComponent::UpdatePetXml(tinyxml2::XMLDocument* document) { } -bool InventoryComponent::SetSkill(int32_t slot, uint32_t skillId){ +bool InventoryComponent::SetSkill(int32_t slot, uint32_t skillId) { BehaviorSlot behaviorSlot = BehaviorSlot::Invalid; - if (slot == 1 ) behaviorSlot = BehaviorSlot::Primary; - else if (slot == 2 ) behaviorSlot = BehaviorSlot::Offhand; - else if (slot == 3 ) behaviorSlot = BehaviorSlot::Neck; - else if (slot == 4 ) behaviorSlot = BehaviorSlot::Head; - else if (slot == 5 ) behaviorSlot = BehaviorSlot::Consumable; + if (slot == 1) behaviorSlot = BehaviorSlot::Primary; + else if (slot == 2) behaviorSlot = BehaviorSlot::Offhand; + else if (slot == 3) behaviorSlot = BehaviorSlot::Neck; + else if (slot == 4) behaviorSlot = BehaviorSlot::Head; + else if (slot == 5) behaviorSlot = BehaviorSlot::Consumable; else return false; return SetSkill(behaviorSlot, skillId); } -bool InventoryComponent::SetSkill(BehaviorSlot slot, uint32_t skillId){ +bool InventoryComponent::SetSkill(BehaviorSlot slot, uint32_t skillId) { if (skillId == 0) return false; + + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + const auto index = m_Skills.find(slot); if (index != m_Skills.end()) { const auto old = index->second; - GameMessages::SendRemoveSkill(m_Parent, old); + GameMessages::SendRemoveSkill(parentEntity, old); } - GameMessages::SendAddSkill(m_Parent, skillId, slot); + GameMessages::SendAddSkill(parentEntity, skillId, slot); m_Skills.insert_or_assign(slot, skillId); return true; } diff --git a/dGame/dComponents/InventoryComponent.h b/dGame/dComponents/InventoryComponent.h index f4d38d43a..a5fc163c4 100644 --- a/dGame/dComponents/InventoryComponent.h +++ b/dGame/dComponents/InventoryComponent.h @@ -38,8 +38,8 @@ enum class eItemType : int32_t; class InventoryComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::INVENTORY; - explicit InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document = nullptr); + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::INVENTORY; + explicit InventoryComponent(const LWOOBJID& parentEntityId, tinyxml2::XMLDocument* document = nullptr); void Update(float deltaTime) override; void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; diff --git a/dGame/dComponents/ItemComponent.h b/dGame/dComponents/ItemComponent.h index 3af6a91e1..f90c29447 100644 --- a/dGame/dComponents/ItemComponent.h +++ b/dGame/dComponents/ItemComponent.h @@ -6,9 +6,9 @@ class ItemComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::ITEM; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::ITEM; - ItemComponent(Entity* entity) : Component(entity) {} + ItemComponent(const LWOOBJID& parentEntityId) noexcept : Component{ parentEntityId } {} void Serialize(RakNet::BitStream* bitStream, bool isConstruction) override; }; diff --git a/dGame/dComponents/LUPExhibitComponent.h b/dGame/dComponents/LUPExhibitComponent.h index 47b13a177..c20328031 100644 --- a/dGame/dComponents/LUPExhibitComponent.h +++ b/dGame/dComponents/LUPExhibitComponent.h @@ -14,9 +14,9 @@ class LUPExhibitComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::LUP_EXHIBIT; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::LUP_EXHIBIT; - LUPExhibitComponent(Entity* parent) : Component(parent) {}; + LUPExhibitComponent(const LWOOBJID& parentEntityId) : Component{ parentEntityId } {}; void Update(float deltaTime) override; void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; void NextLUPExhibit(); diff --git a/dGame/dComponents/LevelProgressionComponent.cpp b/dGame/dComponents/LevelProgressionComponent.cpp index 3a18b19c8..28add55b1 100644 --- a/dGame/dComponents/LevelProgressionComponent.cpp +++ b/dGame/dComponents/LevelProgressionComponent.cpp @@ -6,8 +6,7 @@ #include "CDRewardsTable.h" -LevelProgressionComponent::LevelProgressionComponent(Entity* parent) : Component(parent) { - m_Parent = parent; +LevelProgressionComponent::LevelProgressionComponent(const LWOOBJID& parentEntityId) noexcept : Component{ parentEntityId } { m_Level = 1; m_SpeedBase = 500.0f; m_CharacterVersion = eCharacterVersion::LIVE; @@ -49,12 +48,13 @@ void LevelProgressionComponent::HandleLevelUp() { const auto& rewards = rewardsTable->GetByLevelID(m_Level); bool rewardingItem = rewards.size() > 0; - auto* inventoryComponent = m_Parent->GetComponent(); - auto* controllablePhysicsComponent = m_Parent->GetComponent(); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + auto* const inventoryComponent = parentEntity->GetComponent(); + auto* const controllablePhysicsComponent = parentEntity->GetComponent(); if (!inventoryComponent || !controllablePhysicsComponent) return; // Tell the client we beginning to send level rewards. - if (rewardingItem) GameMessages::NotifyLevelRewards(m_Parent->GetObjectID(), m_Parent->GetSystemAddress(), m_Level, rewardingItem); + if (rewardingItem) GameMessages::NotifyLevelRewards(m_Parent, parentEntity->GetSystemAddress(), m_Level, rewardingItem); for (const auto& reward : rewards) { switch (reward.rewardType) { @@ -79,11 +79,11 @@ void LevelProgressionComponent::HandleLevelUp() { } } // Tell the client we have finished sending level rewards. - if (rewardingItem) GameMessages::NotifyLevelRewards(m_Parent->GetObjectID(), m_Parent->GetSystemAddress(), m_Level, !rewardingItem); + if (rewardingItem) GameMessages::NotifyLevelRewards(m_Parent, parentEntity->GetSystemAddress(), m_Level, !rewardingItem); } void LevelProgressionComponent::SetRetroactiveBaseSpeed(){ if (m_Level >= 20) m_SpeedBase = 525.0f; - auto* controllablePhysicsComponent = m_Parent->GetComponent(); + auto* controllablePhysicsComponent = Game::entityManager->GetEntity(m_Parent)->GetComponent(); if (controllablePhysicsComponent) controllablePhysicsComponent->SetSpeedMultiplier(m_SpeedBase / 500.0f); } diff --git a/dGame/dComponents/LevelProgressionComponent.h b/dGame/dComponents/LevelProgressionComponent.h index 09ccec34c..8004ff232 100644 --- a/dGame/dComponents/LevelProgressionComponent.h +++ b/dGame/dComponents/LevelProgressionComponent.h @@ -13,13 +13,13 @@ class LevelProgressionComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::LEVEL_PROGRESSION; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::LEVEL_PROGRESSION; /** * Constructor for this component * @param parent parent that contains this component */ - LevelProgressionComponent(Entity* parent); + LevelProgressionComponent(const LWOOBJID& parentEntityId) noexcept; void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; diff --git a/dGame/dComponents/MiniGameControlComponent.h b/dGame/dComponents/MiniGameControlComponent.h index 06a9c24e5..9f6f9f4c5 100644 --- a/dGame/dComponents/MiniGameControlComponent.h +++ b/dGame/dComponents/MiniGameControlComponent.h @@ -6,9 +6,9 @@ class MiniGameControlComponent final : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MINI_GAME_CONTROL; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::MINI_GAME_CONTROL; - MiniGameControlComponent(Entity* parent) : Component(parent) {} + MiniGameControlComponent(const LWOOBJID& parentEntityId) : Component{ parentEntityId } {} void Serialize(RakNet::BitStream* outBitStream, bool isConstruction); }; diff --git a/dGame/dComponents/MissionComponent.cpp b/dGame/dComponents/MissionComponent.cpp index 7219589af..126930852 100644 --- a/dGame/dComponents/MissionComponent.cpp +++ b/dGame/dComponents/MissionComponent.cpp @@ -25,7 +25,7 @@ std::unordered_map> MissionComponent::m_AchievementCache = {}; //! Initializer -MissionComponent::MissionComponent(Entity* parent) : Component(parent) { +MissionComponent::MissionComponent(const LWOOBJID& parentEntityId) : Component{ parentEntityId } { m_LastUsedMissionOrderUID = Game::zoneManager->GetUniqueMissionIdStartingValue(); } @@ -103,9 +103,9 @@ void MissionComponent::AcceptMission(const uint32_t missionId, const bool skipCh if (missionId == 1728) { //Needs to send a mail - auto address = m_Parent->GetSystemAddress(); + auto address = Game::entityManager->GetEntity(m_Parent)->GetSystemAddress(); - Mail::HandleNotificationRequest(address, m_Parent->GetObjectID()); + Mail::HandleNotificationRequest(address, m_Parent); } } @@ -624,9 +624,10 @@ bool MissionComponent::HasMission(uint32_t missionId) { void MissionComponent::ResetMission(const int32_t missionId) { auto* mission = GetMission(missionId); - if (!mission) return; m_Missions.erase(missionId); - GameMessages::SendResetMissions(m_Parent, m_Parent->GetSystemAddress(), missionId); + + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + GameMessages::SendResetMissions(parentEntity, parentEntity->GetSystemAddress(), missionId); } diff --git a/dGame/dComponents/MissionComponent.h b/dGame/dComponents/MissionComponent.h index d53db64e2..f4bf16eee 100644 --- a/dGame/dComponents/MissionComponent.h +++ b/dGame/dComponents/MissionComponent.h @@ -27,9 +27,9 @@ class AchievementCacheKey; class MissionComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MISSION; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::MISSION; - explicit MissionComponent(Entity* parent); + explicit MissionComponent(const LWOOBJID& parentEntityId); ~MissionComponent() override; void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); void LoadFromXml(tinyxml2::XMLDocument* doc) override; diff --git a/dGame/dComponents/MissionOfferComponent.cpp b/dGame/dComponents/MissionOfferComponent.cpp index 25d4a7392..7d6af118f 100644 --- a/dGame/dComponents/MissionOfferComponent.cpp +++ b/dGame/dComponents/MissionOfferComponent.cpp @@ -39,7 +39,7 @@ bool OfferedMission::GetAcceptsMission() const { //------------------------ MissionOfferComponent below ------------------------ -MissionOfferComponent::MissionOfferComponent(Entity* parent, const LOT parentLot) : Component(parent) { +MissionOfferComponent::MissionOfferComponent(const LWOOBJID& parentEntityId, const LOT parentLot) : Component{ parentEntityId } { auto* compRegistryTable = CDClientManager::Instance().GetTable(); auto value = compRegistryTable->GetByIDAndType(parentLot, eReplicaComponentType::MISSION_OFFER, -1); @@ -87,21 +87,21 @@ void MissionOfferComponent::OfferMissions(Entity* entity, const uint32_t specifi } // First, check if we already have the mission - const auto missionId = offeredMission.GetMissionId(); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + const auto missionId = offeredMission.GetMissionId(); auto* mission = missionComponent->GetMission(missionId); - if (mission != nullptr) { if (specifiedMissionId <= 0) { // Handles the odd case where the offer object should not display the mission again - if (!mission->IsComplete() && mission->GetClientInfo().offer_objectID == m_Parent->GetLOT() && mission->GetClientInfo().target_objectID != m_Parent->GetLOT() && mission->IsFetchMission()) { + if (!mission->IsComplete() && mission->GetClientInfo().offer_objectID == parentEntity->GetLOT() && mission->GetClientInfo().target_objectID != parentEntity->GetLOT() && mission->IsFetchMission()) { continue; } } // We have the mission, if it is not complete, offer it if (mission->IsActive() || mission->IsReadyToComplete()) { - GameMessages::SendOfferMission(entity->GetObjectID(), entity->GetSystemAddress(), missionId, m_Parent->GetObjectID()); + GameMessages::SendOfferMission(entity->GetObjectID(), entity->GetSystemAddress(), missionId, m_Parent); continue; } @@ -138,7 +138,7 @@ void MissionOfferComponent::OfferMissions(Entity* entity, const uint32_t specifi const auto& iter = std::find(randomMissionPool.begin(), randomMissionPool.end(), specifiedMissionId); if (iter != randomMissionPool.end() && MissionPrerequisites::CanAccept(specifiedMissionId, missionComponent->GetMissions())) { - GameMessages::SendOfferMission(entity->GetObjectID(), entity->GetSystemAddress(), specifiedMissionId, m_Parent->GetObjectID()); + GameMessages::SendOfferMission(entity->GetObjectID(), entity->GetSystemAddress(), specifiedMissionId, m_Parent); return; } @@ -158,7 +158,7 @@ void MissionOfferComponent::OfferMissions(Entity* entity, const uint32_t specifi if (mission == nullptr || mission->IsAchievement()) continue; - GameMessages::SendOfferMission(entity->GetObjectID(), entity->GetSystemAddress(), sample, m_Parent->GetObjectID()); + GameMessages::SendOfferMission(entity->GetObjectID(), entity->GetSystemAddress(), sample, m_Parent); canAcceptPool.clear(); @@ -175,9 +175,9 @@ void MissionOfferComponent::OfferMissions(Entity* entity, const uint32_t specifi const auto selected = canAcceptPool[GeneralUtils::GenerateRandomNumber(0, canAcceptPool.size() - 1)]; - GameMessages::SendOfferMission(entity->GetObjectID(), entity->GetSystemAddress(), selected, m_Parent->GetObjectID()); + GameMessages::SendOfferMission(entity->GetObjectID(), entity->GetSystemAddress(), selected, m_Parent); } else if (offeredMission.GetOffersMission()) { - GameMessages::SendOfferMission(entity->GetObjectID(), entity->GetSystemAddress(), missionId, m_Parent->GetObjectID()); + GameMessages::SendOfferMission(entity->GetObjectID(), entity->GetSystemAddress(), missionId, m_Parent); } } } diff --git a/dGame/dComponents/MissionOfferComponent.h b/dGame/dComponents/MissionOfferComponent.h index 0f0d23ba2..701dbdfba 100644 --- a/dGame/dComponents/MissionOfferComponent.h +++ b/dGame/dComponents/MissionOfferComponent.h @@ -61,9 +61,9 @@ struct OfferedMission { */ class MissionOfferComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MISSION_OFFER; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::MISSION_OFFER; - MissionOfferComponent(Entity* parent, LOT parentLot); + MissionOfferComponent(const LWOOBJID& parentEntityId, LOT parentLot); /** * Handles the OnUse event triggered by some entity, determines which missions to show based on what they may diff --git a/dGame/dComponents/ModelComponent.cpp b/dGame/dComponents/ModelComponent.cpp index 3f8858c04..8cc5b4e4f 100644 --- a/dGame/dComponents/ModelComponent.cpp +++ b/dGame/dComponents/ModelComponent.cpp @@ -7,18 +7,20 @@ #include "BehaviorStates.h" #include "ControlBehaviorMsgs.h" -ModelComponent::ModelComponent(Entity* parent) : Component(parent) { - m_OriginalPosition = m_Parent->GetDefaultPosition(); - m_OriginalRotation = m_Parent->GetDefaultRotation(); +ModelComponent::ModelComponent(const LWOOBJID& parentEntityId) : Component{ parentEntityId } { + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); - m_userModelID = m_Parent->GetVarAs(u"userModelID"); + m_OriginalPosition = parentEntity->GetDefaultPosition(); + m_OriginalRotation = parentEntity->GetDefaultRotation(); + + m_userModelID = parentEntity->GetVarAs(u"userModelID"); } void ModelComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { // ItemComponent Serialization. Pets do not get this serialization. - if (!m_Parent->HasComponent(eReplicaComponentType::PET)) { + if (!Game::entityManager->GetEntity(m_Parent)->HasComponent(eReplicaComponentType::PET)) { outBitStream->Write1(); - outBitStream->Write(m_userModelID != LWOOBJID_EMPTY ? m_userModelID : m_Parent->GetObjectID()); + outBitStream->Write(m_userModelID != LWOOBJID_EMPTY ? m_userModelID : m_Parent); outBitStream->Write(0); outBitStream->Write0(); } @@ -41,7 +43,7 @@ void ModelComponent::UpdatePendingBehaviorId(const int32_t newId) { } void ModelComponent::SendBehaviorListToClient(AMFArrayValue& args) const { - args.Insert("objectID", std::to_string(m_Parent->GetObjectID())); + args.Insert("objectID", std::to_string(m_Parent)); auto* behaviorArray = args.InsertArray("behaviors"); for (auto& behavior : m_Behaviors) { @@ -56,7 +58,7 @@ void ModelComponent::VerifyBehaviors() { void ModelComponent::SendBehaviorBlocksToClient(int32_t behaviorToSend, AMFArrayValue& args) const { args.Insert("BehaviorID", std::to_string(behaviorToSend)); - args.Insert("objectID", std::to_string(m_Parent->GetObjectID())); + args.Insert("objectID", std::to_string(m_Parent)); for (auto& behavior : m_Behaviors) if (behavior.GetBehaviorId() == behaviorToSend) behavior.SendBehaviorBlocksToClient(args); } diff --git a/dGame/dComponents/ModelComponent.h b/dGame/dComponents/ModelComponent.h index a36328beb..2f1de9180 100644 --- a/dGame/dComponents/ModelComponent.h +++ b/dGame/dComponents/ModelComponent.h @@ -24,9 +24,9 @@ class MoveToInventoryMessage; */ class ModelComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MODEL; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::MODEL; - ModelComponent(Entity* parent); + ModelComponent(const LWOOBJID& parentEntityId); void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; diff --git a/dGame/dComponents/ModuleAssemblyComponent.cpp b/dGame/dComponents/ModuleAssemblyComponent.cpp index 5b7042dff..35cbcc101 100644 --- a/dGame/dComponents/ModuleAssemblyComponent.cpp +++ b/dGame/dComponents/ModuleAssemblyComponent.cpp @@ -1,15 +1,11 @@ #include "ModuleAssemblyComponent.h" -ModuleAssemblyComponent::ModuleAssemblyComponent(Entity* parent) : Component(parent) { +ModuleAssemblyComponent::ModuleAssemblyComponent(const LWOOBJID& parentEntityId) noexcept : Component{ parentEntityId } { m_SubKey = LWOOBJID_EMPTY; m_UseOptionalParts = false; m_AssemblyPartsLOTs = u""; } -ModuleAssemblyComponent::~ModuleAssemblyComponent() { - -} - void ModuleAssemblyComponent::SetSubKey(LWOOBJID value) { m_SubKey = value; } diff --git a/dGame/dComponents/ModuleAssemblyComponent.h b/dGame/dComponents/ModuleAssemblyComponent.h index 9e7301fed..0b5fd220f 100644 --- a/dGame/dComponents/ModuleAssemblyComponent.h +++ b/dGame/dComponents/ModuleAssemblyComponent.h @@ -12,10 +12,9 @@ */ class ModuleAssemblyComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MODULE_ASSEMBLY; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::MODULE_ASSEMBLY; - ModuleAssemblyComponent(Entity* parent); - ~ModuleAssemblyComponent() override; + ModuleAssemblyComponent(const LWOOBJID& parentEntityId) noexcept; void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; void Update(float deltaTime) override; diff --git a/dGame/dComponents/MovementAIComponent.cpp b/dGame/dComponents/MovementAIComponent.cpp index 25cafc45f..f8d65e36c 100644 --- a/dGame/dComponents/MovementAIComponent.cpp +++ b/dGame/dComponents/MovementAIComponent.cpp @@ -25,25 +25,25 @@ namespace { std::map m_PhysicsSpeedCache; } -MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) : Component(parent) { +MovementAIComponent::MovementAIComponent(const LWOOBJID& parentEntityId, MovementAIInfo info) : Component{ parentEntityId } { m_Info = info; m_AtFinalWaypoint = true; - m_BaseCombatAI = nullptr; + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); - m_BaseCombatAI = m_Parent->GetComponent(); + m_BaseCombatAI = parentEntity->GetComponent(); //Try and fix the insane values: if (m_Info.wanderRadius > 5.0f) m_Info.wanderRadius *= 0.5f; if (m_Info.wanderRadius > 8.0f) m_Info.wanderRadius = 8.0f; if (m_Info.wanderSpeed > 0.5f) m_Info.wanderSpeed *= 0.5f; - m_BaseSpeed = GetBaseSpeed(m_Parent->GetLOT()); + m_BaseSpeed = GetBaseSpeed(parentEntity->GetLOT()); - m_NextWaypoint = m_Parent->GetPosition(); + m_NextWaypoint = parentEntity->GetPosition(); m_Acceleration = 0.4f; m_PullingToPoint = false; - m_PullPoint = NiPoint3::ZERO; + m_PullPoint = NiPoint3Constant::ZERO; m_HaltDistance = 0; m_TimeToTravel = 0; m_TimeTravelled = 0; @@ -62,7 +62,7 @@ void MovementAIComponent::Update(const float deltaTime) { SetPosition(source + velocity); - if (Vector3::DistanceSquared(m_Parent->GetPosition(), m_PullPoint) < std::pow(2, 2)) { + if (Vector3::DistanceSquared(Game::entityManager->GetEntity(m_Parent)->GetPosition(), m_PullPoint) < std::pow(2, 2)) { m_PullingToPoint = false; } @@ -88,7 +88,7 @@ void MovementAIComponent::Update(const float deltaTime) { SetPosition(source); - NiPoint3 velocity = NiPoint3::ZERO; + NiPoint3 velocity = NiPoint3Constant::ZERO; if (m_Acceleration > 0 && m_BaseSpeed > 0 && AdvanceWaypointIndex()) // Do we have another waypoint to seek? { @@ -157,11 +157,11 @@ bool MovementAIComponent::AdvanceWaypointIndex() { } NiPoint3 MovementAIComponent::GetCurrentWaypoint() const { - return m_PathIndex >= m_InterpolatedWaypoints.size() ? m_Parent->GetPosition() : m_InterpolatedWaypoints[m_PathIndex]; + return m_PathIndex >= m_InterpolatedWaypoints.size() ? Game::entityManager->GetEntity(m_Parent)->GetPosition() : m_InterpolatedWaypoints[m_PathIndex]; } NiPoint3 MovementAIComponent::ApproximateLocation() const { - auto source = m_Parent->GetPosition(); + auto source = Game::entityManager->GetEntity(m_Parent)->GetPosition(); if (AtFinalWaypoint()) return source; @@ -203,7 +203,7 @@ void MovementAIComponent::Stop() { SetPosition(ApproximateLocation()); - SetVelocity(NiPoint3::ZERO); + SetVelocity(NiPoint3Constant::ZERO); m_TimeToTravel = 0; m_TimeTravelled = 0; @@ -271,24 +271,24 @@ float MovementAIComponent::GetBaseSpeed(LOT lot) { } void MovementAIComponent::SetPosition(const NiPoint3& value) { - m_Parent->SetPosition(value); + Game::entityManager->GetEntity(m_Parent)->SetPosition(value); } void MovementAIComponent::SetRotation(const NiQuaternion& value) { - if (!m_LockRotation) m_Parent->SetRotation(value); + if (!m_LockRotation) Game::entityManager->GetEntity(m_Parent)->SetRotation(value); } void MovementAIComponent::SetVelocity(const NiPoint3& value) { - auto* controllablePhysicsComponent = m_Parent->GetComponent(); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + auto* const controllablePhysicsComponent = parentEntity->GetComponent(); if (controllablePhysicsComponent != nullptr) { controllablePhysicsComponent->SetVelocity(value); return; } - auto* simplePhysicsComponent = m_Parent->GetComponent(); - + auto* const simplePhysicsComponent = parentEntity->GetComponent(); if (simplePhysicsComponent != nullptr) { simplePhysicsComponent->SetVelocity(value); } @@ -305,7 +305,7 @@ void MovementAIComponent::SetDestination(const NiPoint3& destination) { std::vector computedPath; if (dpWorld::IsLoaded()) { - computedPath = dpWorld::GetNavMesh()->GetPath(m_Parent->GetPosition(), destination, m_Info.wanderSpeed); + computedPath = dpWorld::GetNavMesh()->GetPath(Game::entityManager->GetEntity(m_Parent)->GetPosition(), destination, m_Info.wanderSpeed); } // Somehow failed @@ -346,7 +346,7 @@ void MovementAIComponent::SetDestination(const NiPoint3& destination) { } NiPoint3 MovementAIComponent::GetDestination() const { - return m_InterpolatedWaypoints.empty() ? m_Parent->GetPosition() : m_InterpolatedWaypoints.back(); + return m_InterpolatedWaypoints.empty() ? Game::entityManager->GetEntity(m_Parent)->GetPosition() : m_InterpolatedWaypoints.back(); } void MovementAIComponent::SetMaxSpeed(const float value) { diff --git a/dGame/dComponents/MovementAIComponent.h b/dGame/dComponents/MovementAIComponent.h index 0ae71dc6b..057769496 100644 --- a/dGame/dComponents/MovementAIComponent.h +++ b/dGame/dComponents/MovementAIComponent.h @@ -57,9 +57,9 @@ struct MovementAIInfo { */ class MovementAIComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MOVEMENT_AI; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::MOVEMENT_AI; - MovementAIComponent(Entity* parentEntity, MovementAIInfo info); + MovementAIComponent(const LWOOBJID& parentEntityId, MovementAIInfo info); void Update(float deltaTime) override; diff --git a/dGame/dComponents/MovingPlatformComponent.cpp b/dGame/dComponents/MovingPlatformComponent.cpp index 366bebd39..1eebe4af7 100644 --- a/dGame/dComponents/MovingPlatformComponent.cpp +++ b/dGame/dComponents/MovingPlatformComponent.cpp @@ -30,8 +30,6 @@ MoverSubComponent::MoverSubComponent(const NiPoint3& startPos) { mIdleTimeElapsed = 0.0f; } -MoverSubComponent::~MoverSubComponent() = default; - void MoverSubComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { outBitStream->Write(true); @@ -55,9 +53,9 @@ void MoverSubComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsIniti //------------- MovingPlatformComponent below -------------- -MovingPlatformComponent::MovingPlatformComponent(Entity* parent, const std::string& pathName) : Component(parent) { +MovingPlatformComponent::MovingPlatformComponent(const LWOOBJID& parentEntityId, const std::string& pathName) : Component{ parentEntityId } { m_MoverSubComponentType = eMoverSubComponentType::mover; - m_MoverSubComponent = new MoverSubComponent(m_Parent->GetDefaultPosition()); + m_MoverSubComponent = std::make_unique(Game::entityManager->GetEntity(m_Parent)->GetDefaultPosition()); m_PathName = GeneralUtils::ASCIIToUTF16(pathName); m_Path = Game::zoneManager->GetZone()->GetPath(pathName); m_NoAutoStart = false; @@ -67,10 +65,6 @@ MovingPlatformComponent::MovingPlatformComponent(Entity* parent, const std::stri } } -MovingPlatformComponent::~MovingPlatformComponent() { - delete static_cast(m_MoverSubComponent); -} - void MovingPlatformComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { // Here we don't serialize the moving platform to let the client simulate the movement @@ -106,7 +100,7 @@ void MovingPlatformComponent::Serialize(RakNet::BitStream* outBitStream, bool bI outBitStream->Write(hasPlatform); if (hasPlatform) { - auto* mover = static_cast(m_MoverSubComponent); + auto* mover = m_MoverSubComponent.get(); outBitStream->Write(m_MoverSubComponentType); if (m_MoverSubComponentType == eMoverSubComponentType::simpleMover) { @@ -129,7 +123,7 @@ void MovingPlatformComponent::OnCompleteQuickBuild() { } void MovingPlatformComponent::SetMovementState(eMovementPlatformState value) { - auto* subComponent = static_cast(m_MoverSubComponent); + auto* subComponent = m_MoverSubComponent.get(); subComponent->mState = value; @@ -137,7 +131,7 @@ void MovingPlatformComponent::SetMovementState(eMovementPlatformState value) { } void MovingPlatformComponent::GotoWaypoint(uint32_t index, bool stopAtWaypoint) { - auto* subComponent = static_cast(m_MoverSubComponent); + auto* subComponent = m_MoverSubComponent.get(); subComponent->mDesiredWaypointIndex = index; subComponent->mNextWaypointIndex = index; @@ -150,7 +144,8 @@ void MovingPlatformComponent::StartPathing() { //GameMessages::SendStartPathing(m_Parent); m_PathingStopped = false; - auto* subComponent = static_cast(m_MoverSubComponent); + auto* parentEntity = Game::entityManager->GetEntity(m_Parent); + auto* subComponent = m_MoverSubComponent.get(); subComponent->mShouldStopAtDesiredWaypoint = true; subComponent->mState = eMovementPlatformState::Stationary; @@ -167,14 +162,14 @@ void MovingPlatformComponent::StartPathing() { targetPosition = nextWaypoint.position; } else { - subComponent->mPosition = m_Parent->GetPosition(); + subComponent->mPosition = parentEntity->GetPosition(); subComponent->mSpeed = 1.0f; subComponent->mWaitTime = 2.0f; - targetPosition = m_Parent->GetPosition() + NiPoint3(0.0f, 10.0f, 0.0f); + targetPosition = parentEntity->GetPosition() + NiPoint3(0.0f, 10.0f, 0.0f); } - m_Parent->AddCallbackTimer(subComponent->mWaitTime, [this] { + parentEntity->AddCallbackTimer(subComponent->mWaitTime, [this] { SetMovementState(eMovementPlatformState::Moving); }); @@ -182,13 +177,14 @@ void MovingPlatformComponent::StartPathing() { const auto travelNext = subComponent->mWaitTime + travelTime; - m_Parent->AddCallbackTimer(travelTime, [subComponent, this] { - for (CppScripts::Script* script : CppScripts::GetEntityScripts(m_Parent)) { - script->OnWaypointReached(m_Parent, subComponent->mNextWaypointIndex); + //TODO: MAKE THESE TIMERS INDEPENDENT OF COMPONENENT POINTERS + parentEntity->AddCallbackTimer(travelTime, [subComponent, this] { + for (CppScripts::Script* script : CppScripts::GetEntityScripts(Game::entityManager->GetEntity(m_Parent))) { + script->OnWaypointReached(Game::entityManager->GetEntity(m_Parent), subComponent->mNextWaypointIndex); } }); - m_Parent->AddCallbackTimer(travelNext, [this] { + parentEntity->AddCallbackTimer(travelNext, [this] { ContinuePathing(); }); @@ -198,7 +194,9 @@ void MovingPlatformComponent::StartPathing() { } void MovingPlatformComponent::ContinuePathing() { - auto* subComponent = static_cast(m_MoverSubComponent); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + + auto* const subComponent = m_MoverSubComponent.get(); subComponent->mState = eMovementPlatformState::Stationary; @@ -222,17 +220,17 @@ void MovingPlatformComponent::ContinuePathing() { targetPosition = nextWaypoint.position; } else { - subComponent->mPosition = m_Parent->GetPosition(); + subComponent->mPosition = parentEntity->GetPosition(); subComponent->mSpeed = 1.0f; subComponent->mWaitTime = 2.0f; - targetPosition = m_Parent->GetPosition() + NiPoint3(0.0f, 10.0f, 0.0f); + targetPosition = parentEntity->GetPosition() + NiPoint3(0.0f, 10.0f, 0.0f); pathSize = 1; behavior = PathBehavior::Loop; } - if (m_Parent->GetLOT() == 9483) { + if (parentEntity->GetLOT() == 9483) { behavior = PathBehavior::Bounce; } else { return; @@ -280,27 +278,27 @@ void MovingPlatformComponent::ContinuePathing() { return; } - m_Parent->CancelCallbackTimers(); + parentEntity->CancelCallbackTimers(); - m_Parent->AddCallbackTimer(subComponent->mWaitTime, [this] { + parentEntity->AddCallbackTimer(subComponent->mWaitTime, [this] { SetMovementState(eMovementPlatformState::Moving); }); auto travelTime = Vector3::Distance(targetPosition, subComponent->mPosition) / subComponent->mSpeed + 1.5; - if (m_Parent->GetLOT() == 9483) { + if (parentEntity->GetLOT() == 9483) { travelTime += 20; } const auto travelNext = subComponent->mWaitTime + travelTime; - m_Parent->AddCallbackTimer(travelTime, [subComponent, this] { - for (CppScripts::Script* script : CppScripts::GetEntityScripts(m_Parent)) { - script->OnWaypointReached(m_Parent, subComponent->mNextWaypointIndex); + parentEntity->AddCallbackTimer(travelTime, [subComponent, this] { + for (CppScripts::Script* script : CppScripts::GetEntityScripts(Game::entityManager->GetEntity(m_Parent))) { + script->OnWaypointReached(Game::entityManager->GetEntity(m_Parent), subComponent->mNextWaypointIndex); } }); - m_Parent->AddCallbackTimer(travelNext, [this] { + parentEntity->AddCallbackTimer(travelNext, [this] { ContinuePathing(); }); @@ -308,9 +306,9 @@ void MovingPlatformComponent::ContinuePathing() { } void MovingPlatformComponent::StopPathing() { - //m_Parent->CancelCallbackTimers(); + //Game::entityManager->GetEntity(m_Parent)->CancelCallbackTimers(); - auto* subComponent = static_cast(m_MoverSubComponent); + auto& subComponent = m_MoverSubComponent; m_PathingStopped = true; @@ -338,8 +336,9 @@ void MovingPlatformComponent::SetNoAutoStart(const bool value) { void MovingPlatformComponent::WarpToWaypoint(size_t index) { const auto& waypoint = m_Path->pathWaypoints[index]; - m_Parent->SetPosition(waypoint.position); - m_Parent->SetRotation(waypoint.rotation); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + parentEntity->SetPosition(waypoint.position); + parentEntity->SetRotation(waypoint.rotation); Game::entityManager->SerializeEntity(m_Parent); } @@ -349,5 +348,5 @@ size_t MovingPlatformComponent::GetLastWaypointIndex() const { } MoverSubComponent* MovingPlatformComponent::GetMoverSubComponent() const { - return static_cast(m_MoverSubComponent); + return m_MoverSubComponent.get(); } diff --git a/dGame/dComponents/MovingPlatformComponent.h b/dGame/dComponents/MovingPlatformComponent.h index bb5821d45..4015df12f 100644 --- a/dGame/dComponents/MovingPlatformComponent.h +++ b/dGame/dComponents/MovingPlatformComponent.h @@ -36,7 +36,6 @@ enum class eMoverSubComponentType : uint32_t { class MoverSubComponent { public: MoverSubComponent(const NiPoint3& startPos); - ~MoverSubComponent(); void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate); @@ -106,10 +105,9 @@ class MoverSubComponent { */ class MovingPlatformComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MOVING_PLATFORM; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::MOVING_PLATFORM; - MovingPlatformComponent(Entity* parent, const std::string& pathName); - ~MovingPlatformComponent() override; + MovingPlatformComponent(const LWOOBJID& parentEntityId, const std::string& pathName); void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; @@ -212,7 +210,7 @@ class MovingPlatformComponent : public Component { /** * The mover sub component that belongs to this platform */ - void* m_MoverSubComponent; + std::unique_ptr m_MoverSubComponent; /** * Whether the platform shouldn't auto start diff --git a/dGame/dComponents/MultiZoneEntranceComponent.cpp b/dGame/dComponents/MultiZoneEntranceComponent.cpp index 7c2e2b790..3cbdef47a 100644 --- a/dGame/dComponents/MultiZoneEntranceComponent.cpp +++ b/dGame/dComponents/MultiZoneEntranceComponent.cpp @@ -3,9 +3,8 @@ #include "InventoryComponent.h" #include "CharacterComponent.h" -MultiZoneEntranceComponent::MultiZoneEntranceComponent(Entity* parent) : Component(parent) { - m_Parent = parent; - std::string zoneString = GeneralUtils::UTF16ToWTF8(m_Parent->GetVar(u"MultiZoneIDs")); +MultiZoneEntranceComponent::MultiZoneEntranceComponent(const LWOOBJID& parentEntityId) : Component{ parentEntityId } { + std::string zoneString = GeneralUtils::UTF16ToWTF8(Game::entityManager->GetEntity(m_Parent)->GetVar(u"MultiZoneIDs")); std::stringstream ss(zoneString); for (int i; ss >> i;) { m_LUPWorlds.push_back(i); @@ -14,18 +13,16 @@ MultiZoneEntranceComponent::MultiZoneEntranceComponent(Entity* parent) : Compone } } -MultiZoneEntranceComponent::~MultiZoneEntranceComponent() {} - void MultiZoneEntranceComponent::OnUse(Entity* originator) { auto* rocket = originator->GetComponent()->RocketEquip(originator); if (!rocket) return; // the LUP world menu is just the property menu, the client knows how to handle it - GameMessages::SendPropertyEntranceBegin(m_Parent->GetObjectID(), originator->GetSystemAddress()); + GameMessages::SendPropertyEntranceBegin(m_Parent, originator->GetSystemAddress()); } void MultiZoneEntranceComponent::OnSelectWorld(Entity* originator, uint32_t index) { - auto* rocketLaunchpadControlComponent = m_Parent->GetComponent(); + auto* rocketLaunchpadControlComponent = Game::entityManager->GetEntity(m_Parent)->GetComponent(); if (!rocketLaunchpadControlComponent) return; rocketLaunchpadControlComponent->Launch(originator, m_LUPWorlds[index], 0); diff --git a/dGame/dComponents/MultiZoneEntranceComponent.h b/dGame/dComponents/MultiZoneEntranceComponent.h index c65dc0fe3..891548092 100644 --- a/dGame/dComponents/MultiZoneEntranceComponent.h +++ b/dGame/dComponents/MultiZoneEntranceComponent.h @@ -10,14 +10,13 @@ */ class MultiZoneEntranceComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MULTI_ZONE_ENTRANCE; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::MULTI_ZONE_ENTRANCE; /** * Constructor for this component, builds the m_LUPWorlds vector * @param parent parent that contains this component */ - MultiZoneEntranceComponent(Entity* parent); - ~MultiZoneEntranceComponent() override; + MultiZoneEntranceComponent(const LWOOBJID& parentEntityId); /** * Handles an OnUse event from some entity, preparing it for launch to some other world diff --git a/dGame/dComponents/PetComponent.cpp b/dGame/dComponents/PetComponent.cpp index 7e515905b..414716cac 100644 --- a/dGame/dComponents/PetComponent.cpp +++ b/dGame/dComponents/PetComponent.cpp @@ -70,7 +70,7 @@ std::map PetComponent::petFlags = { { 13067, 838 }, // Skeleton dragon }; -PetComponent::PetComponent(Entity* parentEntity, uint32_t componentId) : Component{ parentEntity } { +PetComponent::PetComponent(const LWOOBJID& parentEntityId, uint32_t componentId) : Component{ parentEntityId } { m_PetInfo = CDClientManager::Instance().GetTable()->GetByID(componentId); // TODO: Make reference when safe m_ComponentId = componentId; @@ -84,12 +84,12 @@ PetComponent::PetComponent(Entity* parentEntity, uint32_t componentId) : Compone m_DatabaseId = LWOOBJID_EMPTY; m_Status = 67108866; // Tamable m_Ability = ePetAbilityType::Invalid; - m_StartPosition = NiPoint3::ZERO; + m_StartPosition = NiPoint3Constant::ZERO; m_MovementAI = nullptr; m_TresureTime = 0; m_Preconditions = nullptr; - std::string checkPreconditions = GeneralUtils::UTF16ToWTF8(parentEntity->GetVar(u"CheckPrecondition")); + std::string checkPreconditions = GeneralUtils::UTF16ToWTF8(Game::entityManager->GetEntity(m_Parent)->GetVar(u"CheckPrecondition")); if (!checkPreconditions.empty()) { SetPreconditions(checkPreconditions); @@ -152,25 +152,23 @@ void PetComponent::OnUse(Entity* originator) { m_Tamer = LWOOBJID_EMPTY; } - auto* inventoryComponent = originator->GetComponent(); + auto* const inventoryComponent = originator->GetComponent(); + if (!inventoryComponent) return; - if (inventoryComponent == nullptr) { - return; - } - - if (m_Preconditions != nullptr && !m_Preconditions->Check(originator, true)) { + if (m_Preconditions && !m_Preconditions->Check(originator, true)) { return; } - auto* movementAIComponent = m_Parent->GetComponent(); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); - if (movementAIComponent != nullptr) { + auto* const movementAIComponent = parentEntity->GetComponent(); + if (movementAIComponent) { movementAIComponent->Stop(); } inventoryComponent->DespawnPet(); - const auto& cached = buildCache.find(m_Parent->GetLOT()); + const auto& cached = buildCache.find(parentEntity->GetLOT()); int32_t imaginationCost = 0; std::string buildFile; @@ -178,7 +176,7 @@ void PetComponent::OnUse(Entity* originator) { if (cached == buildCache.end()) { auto query = CDClientDatabase::CreatePreppedStmt( "SELECT ValidPiecesLXF, PuzzleModelLot, Timelimit, NumValidPieces, imagCostPerBuild FROM TamingBuildPuzzles WHERE NPCLot = ?;"); - query.bind(1, static_cast(m_Parent->GetLOT())); + query.bind(1, static_cast(parentEntity->GetLOT())); auto result = query.execQuery(); @@ -205,7 +203,7 @@ void PetComponent::OnUse(Entity* originator) { if (data.timeLimit <= 0) data.timeLimit = 60; imaginationCost = data.imaginationCost; - buildCache[m_Parent->GetLOT()] = data; + buildCache[parentEntity->GetLOT()] = data; result.finalize(); } else { @@ -214,16 +212,10 @@ void PetComponent::OnUse(Entity* originator) { } auto* destroyableComponent = originator->GetComponent(); - - if (destroyableComponent == nullptr) { - return; - } + if (!destroyableComponent) return; auto imagination = destroyableComponent->GetImagination(); - - if (imagination < imaginationCost) { - return; - } + if (imagination < imaginationCost) return; const auto& bricks = BrickDatabase::GetBricks(buildFile); @@ -234,13 +226,13 @@ void PetComponent::OnUse(Entity* originator) { return; } - auto petPosition = m_Parent->GetPosition(); + auto petPosition = parentEntity->GetPosition(); auto originatorPosition = originator->GetPosition(); - m_Parent->SetRotation(NiQuaternion::LookAt(petPosition, originatorPosition)); + parentEntity->SetRotation(NiQuaternion::LookAt(petPosition, originatorPosition)); - float interactionDistance = m_Parent->GetVar(u"interaction_distance"); + float interactionDistance = parentEntity->GetVar(u"interaction_distance"); if (interactionDistance <= 0) { interactionDistance = 15; @@ -248,7 +240,7 @@ void PetComponent::OnUse(Entity* originator) { auto position = originatorPosition; - NiPoint3 forward = NiQuaternion::LookAt(m_Parent->GetPosition(), originator->GetPosition()).GetForwardVector(); + NiPoint3 forward = NiQuaternion::LookAt(parentEntity->GetPosition(), originator->GetPosition()).GetForwardVector(); forward.y = 0; if (dpWorld::IsLoaded()) { @@ -257,7 +249,7 @@ void PetComponent::OnUse(Entity* originator) { float y = dpWorld::GetNavMesh()->GetHeightAtPoint(attempt); while (std::abs(y - petPosition.y) > 4 && interactionDistance > 10) { - const NiPoint3 forward = m_Parent->GetRotation().GetForwardVector(); + const NiPoint3 forward = parentEntity->GetRotation().GetForwardVector(); attempt = originatorPosition + forward * interactionDistance; @@ -276,7 +268,7 @@ void PetComponent::OnUse(Entity* originator) { GameMessages::SendNotifyPetTamingMinigame( originator->GetObjectID(), - m_Parent->GetObjectID(), + m_Parent, LWOOBJID_EMPTY, true, ePetTamingNotifyType::BEGIN, @@ -287,7 +279,7 @@ void PetComponent::OnUse(Entity* originator) { ); GameMessages::SendNotifyPetTamingMinigame( - m_Parent->GetObjectID(), + m_Parent, LWOOBJID_EMPTY, originator->GetObjectID(), true, @@ -303,17 +295,19 @@ void PetComponent::OnUse(Entity* originator) { m_Tamer = originator->GetObjectID(); SetStatus(5); - currentActivities.insert_or_assign(m_Tamer, m_Parent->GetObjectID()); + currentActivities.insert_or_assign(m_Tamer, m_Parent); // Notify the start of a pet taming minigame - for (CppScripts::Script* script : CppScripts::GetEntityScripts(m_Parent)) { - script->OnNotifyPetTamingMinigame(m_Parent, originator, ePetTamingNotifyType::BEGIN); + for (CppScripts::Script* script : CppScripts::GetEntityScripts(parentEntity)) { + script->OnNotifyPetTamingMinigame(parentEntity, originator, ePetTamingNotifyType::BEGIN); } } void PetComponent::Update(float deltaTime) { - if (m_StartPosition == NiPoint3::ZERO) { - m_StartPosition = m_Parent->GetPosition(); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + + if (m_StartPosition == NiPoint3Constant::ZERO) { + m_StartPosition = parentEntity->GetPosition(); } if (m_Owner == LWOOBJID_EMPTY) { @@ -344,18 +338,14 @@ void PetComponent::Update(float deltaTime) { } auto* owner = GetOwner(); - - if (owner == nullptr) { - m_Parent->Kill(); + if (!owner) { + parentEntity->Kill(); return; } - m_MovementAI = m_Parent->GetComponent(); - - if (m_MovementAI == nullptr) { - return; - } + m_MovementAI = parentEntity->GetComponent(); + if (!m_MovementAI) return; if (m_TresureTime > 0) { auto* tresure = Game::entityManager->GetEntity(m_Interaction); @@ -371,9 +361,9 @@ void PetComponent::Update(float deltaTime) { m_MovementAI->Stop(); if (m_TresureTime <= 0) { - m_Parent->SetOwnerOverride(m_Owner); + parentEntity->SetOwnerOverride(m_Owner); - tresure->Smash(m_Parent->GetObjectID()); + tresure->Smash(m_Parent); m_Interaction = LWOOBJID_EMPTY; @@ -419,7 +409,7 @@ void PetComponent::Update(float deltaTime) { float distance = Vector3::DistanceSquared(position, switchPosition); if (distance < 3 * 3) { m_Interaction = closestSwitch->GetParentEntity()->GetObjectID(); - closestSwitch->EntityEnter(m_Parent); + closestSwitch->EntityEnter(parentEntity); } else if (distance < 20 * 20) { haltDistance = 1; @@ -438,7 +428,7 @@ void PetComponent::Update(float deltaTime) { if (closestTresure != nullptr && digUnlocked) { // Skeleton Dragon Pat special case for bone digging - if (closestTresure->GetLOT() == 12192 && m_Parent->GetLOT() != 13067) { + if (closestTresure->GetLOT() == 12192 && parentEntity->GetLOT() != 13067) { goto skipTresure; } @@ -447,7 +437,7 @@ void PetComponent::Update(float deltaTime) { if (distance < 5 * 5) { m_Interaction = closestTresure->GetObjectID(); - Command(NiPoint3::ZERO, LWOOBJID_EMPTY, 1, 202, true); + Command(NiPoint3Constant::ZERO, LWOOBJID_EMPTY, 1, 202, true); m_TresureTime = 2; } else if (distance < 10 * 10) { @@ -479,7 +469,7 @@ void PetComponent::TryBuild(uint32_t numBricks, bool clientFailed) { return; } - const auto& cached = buildCache.find(m_Parent->GetLOT()); + const auto& cached = buildCache.find(Game::entityManager->GetEntity(m_Parent)->GetLOT()); if (cached == buildCache.end()) return; @@ -511,15 +501,16 @@ void PetComponent::TryBuild(uint32_t numBricks, bool clientFailed) { void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) { if (m_Tamer == LWOOBJID_EMPTY) return; - auto* tamer = Game::entityManager->GetEntity(m_Tamer); - - if (tamer == nullptr) { + auto* const tamer = Game::entityManager->GetEntity(m_Tamer); + if (!tamer) { m_Tamer = LWOOBJID_EMPTY; return; } - const auto& cached = buildCache.find(m_Parent->GetLOT()); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + + const auto& cached = buildCache.find(parentEntity->GetLOT()); if (cached == buildCache.end()) { return; @@ -531,7 +522,7 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) { EntityInfo info{}; info.lot = cached->second.puzzleModelLot; info.pos = position; - info.rot = NiQuaternion::IDENTITY; + info.rot = NiQuaternionConstant::IDENTITY; info.spawnerID = tamer->GetObjectID(); auto* modelEntity = Game::entityManager->CreateEntity(info); @@ -542,7 +533,7 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) { GameMessages::SendNotifyTamingModelLoadedOnServer(m_Tamer, tamer->GetSystemAddress()); - GameMessages::SendPetResponse(m_Tamer, m_Parent->GetObjectID(), 0, 10, 0, tamer->GetSystemAddress()); + GameMessages::SendPetResponse(m_Tamer, m_Parent, 0, 10, 0, tamer->GetSystemAddress()); auto* inventoryComponent = tamer->GetComponent(); @@ -560,22 +551,20 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) { std::string petName = tamer->GetCharacter()->GetName(); petName += "'s Pet"; - GameMessages::SendAddPetToPlayer(m_Tamer, 0, GeneralUtils::UTF8ToUTF16(petName), petSubKey, m_Parent->GetLOT(), tamer->GetSystemAddress()); + GameMessages::SendAddPetToPlayer(m_Tamer, 0, GeneralUtils::UTF8ToUTF16(petName), petSubKey, parentEntity->GetLOT(), tamer->GetSystemAddress()); - GameMessages::SendRegisterPetID(m_Tamer, m_Parent->GetObjectID(), tamer->GetSystemAddress()); + GameMessages::SendRegisterPetID(m_Tamer, m_Parent, tamer->GetSystemAddress()); GameMessages::SendRegisterPetDBID(m_Tamer, petSubKey, tamer->GetSystemAddress()); - inventoryComponent->AddItem(m_Parent->GetLOT(), 1, eLootSourceType::ACTIVITY, eInventoryType::MODELS, {}, LWOOBJID_EMPTY, true, false, petSubKey); + inventoryComponent->AddItem(parentEntity->GetLOT(), 1, eLootSourceType::ACTIVITY, eInventoryType::MODELS, {}, LWOOBJID_EMPTY, true, false, petSubKey); auto* item = inventoryComponent->FindItemBySubKey(petSubKey, MODELS); - if (item == nullptr) { - return; - } + if (!item) return; DatabasePet databasePet{}; - databasePet.lot = m_Parent->GetLOT(); + databasePet.lot = parentEntity->GetLOT(); databasePet.moderationState = 1; databasePet.name = petName; @@ -591,27 +580,26 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) { LWOOBJID_EMPTY, false, ePetTamingNotifyType::NAMINGPET, - NiPoint3::ZERO, - NiPoint3::ZERO, - NiQuaternion::IDENTITY, + NiPoint3Constant::ZERO, + NiPoint3Constant::ZERO, + NiQuaternionConstant::IDENTITY, UNASSIGNED_SYSTEM_ADDRESS ); // Triggers the catch a pet missions - if (petFlags.find(m_Parent->GetLOT()) != petFlags.end()) { - tamer->GetCharacter()->SetPlayerFlag(petFlags.at(m_Parent->GetLOT()), true); + if (petFlags.find(parentEntity->GetLOT()) != petFlags.end()) { + tamer->GetCharacter()->SetPlayerFlag(petFlags.at(parentEntity->GetLOT()), true); } auto* missionComponent = tamer->GetComponent(); - - if (missionComponent != nullptr) { - missionComponent->Progress(eMissionTaskType::PET_TAMING, m_Parent->GetLOT()); + if (missionComponent) { + missionComponent->Progress(eMissionTaskType::PET_TAMING, parentEntity->GetLOT()); } SetStatus(1); auto* characterComponent = tamer->GetComponent(); - if (characterComponent != nullptr) { + if (characterComponent) { characterComponent->UpdatePlayerStatistic(PetsTamed); } } @@ -662,22 +650,22 @@ void PetComponent::RequestSetPetName(std::u16string name) { std::u16string u16ownerName = GeneralUtils::UTF8ToUTF16(m_OwnerName); GameMessages::SendSetPetName(m_Tamer, u16name, m_DatabaseId, tamer->GetSystemAddress()); GameMessages::SendSetPetName(m_Tamer, u16name, LWOOBJID_EMPTY, tamer->GetSystemAddress()); - GameMessages::SendPetNameChanged(m_Parent->GetObjectID(), m_ModerationStatus, u16name, u16ownerName, UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::SendPetNameChanged(m_Parent, m_ModerationStatus, u16name, u16ownerName, UNASSIGNED_SYSTEM_ADDRESS); GameMessages::SendSetPetNameModerated(m_Tamer, m_DatabaseId, m_ModerationStatus, tamer->GetSystemAddress()); GameMessages::SendNotifyPetTamingMinigame( m_Tamer, - m_Parent->GetObjectID(), + m_Parent, m_Tamer, false, ePetTamingNotifyType::SUCCESS, - NiPoint3::ZERO, - NiPoint3::ZERO, - NiQuaternion::IDENTITY, + NiPoint3Constant::ZERO, + NiPoint3Constant::ZERO, + NiQuaternionConstant::IDENTITY, UNASSIGNED_SYSTEM_ADDRESS ); - GameMessages::SendTerminateInteraction(m_Tamer, eTerminateType::FROM_INTERACTION, m_Parent->GetObjectID()); + GameMessages::SendTerminateInteraction(m_Tamer, eTerminateType::FROM_INTERACTION, m_Parent); auto* modelEntity = Game::entityManager->GetEntity(m_ModelId); @@ -690,8 +678,9 @@ void PetComponent::RequestSetPetName(std::u16string name) { m_Tamer = LWOOBJID_EMPTY; // Notify the end of a pet taming minigame - for (CppScripts::Script* script : CppScripts::GetEntityScripts(m_Parent)) { - script->OnNotifyPetTamingMinigame(m_Parent, tamer, ePetTamingNotifyType::SUCCESS); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + for (CppScripts::Script* script : CppScripts::GetEntityScripts(parentEntity)) { + script->OnNotifyPetTamingMinigame(parentEntity, tamer, ePetTamingNotifyType::SUCCESS); } } @@ -708,19 +697,19 @@ void PetComponent::ClientExitTamingMinigame(bool voluntaryExit) { GameMessages::SendNotifyPetTamingMinigame( m_Tamer, - m_Parent->GetObjectID(), + m_Parent, m_Tamer, false, ePetTamingNotifyType::QUIT, - NiPoint3::ZERO, - NiPoint3::ZERO, - NiQuaternion::IDENTITY, + NiPoint3Constant::ZERO, + NiPoint3Constant::ZERO, + NiQuaternionConstant::IDENTITY, UNASSIGNED_SYSTEM_ADDRESS ); GameMessages::SendNotifyTamingModelLoadedOnServer(m_Tamer, tamer->GetSystemAddress()); - GameMessages::SendTerminateInteraction(m_Tamer, eTerminateType::FROM_INTERACTION, m_Parent->GetObjectID()); + GameMessages::SendTerminateInteraction(m_Tamer, eTerminateType::FROM_INTERACTION, m_Parent); currentActivities.erase(m_Tamer); @@ -731,17 +720,16 @@ void PetComponent::ClientExitTamingMinigame(bool voluntaryExit) { Game::entityManager->SerializeEntity(m_Parent); // Notify the end of a pet taming minigame - for (CppScripts::Script* script : CppScripts::GetEntityScripts(m_Parent)) { - script->OnNotifyPetTamingMinigame(m_Parent, tamer, ePetTamingNotifyType::QUIT); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + for (CppScripts::Script* script : CppScripts::GetEntityScripts(Game::entityManager->GetEntity(m_Parent))) { + script->OnNotifyPetTamingMinigame(parentEntity, tamer, ePetTamingNotifyType::QUIT); } } void PetComponent::StartTimer() { - const auto& cached = buildCache.find(m_Parent->GetLOT()); + const auto& cached = buildCache.find(Game::entityManager->GetEntity(m_Parent)->GetLOT()); - if (cached == buildCache.end()) { - return; - } + if (cached == buildCache.end()) return; m_Timer = cached->second.timeLimit; } @@ -750,8 +738,7 @@ void PetComponent::ClientFailTamingMinigame() { if (m_Tamer == LWOOBJID_EMPTY) return; auto* tamer = Game::entityManager->GetEntity(m_Tamer); - - if (tamer == nullptr) { + if (!tamer) { m_Tamer = LWOOBJID_EMPTY; return; @@ -759,19 +746,19 @@ void PetComponent::ClientFailTamingMinigame() { GameMessages::SendNotifyPetTamingMinigame( m_Tamer, - m_Parent->GetObjectID(), + m_Parent, m_Tamer, false, ePetTamingNotifyType::FAILED, - NiPoint3::ZERO, - NiPoint3::ZERO, - NiQuaternion::IDENTITY, + NiPoint3Constant::ZERO, + NiPoint3Constant::ZERO, + NiQuaternionConstant::IDENTITY, UNASSIGNED_SYSTEM_ADDRESS ); GameMessages::SendNotifyTamingModelLoadedOnServer(m_Tamer, tamer->GetSystemAddress()); - GameMessages::SendTerminateInteraction(m_Tamer, eTerminateType::FROM_INTERACTION, m_Parent->GetObjectID()); + GameMessages::SendTerminateInteraction(m_Tamer, eTerminateType::FROM_INTERACTION, m_Parent); currentActivities.erase(m_Tamer); @@ -782,17 +769,16 @@ void PetComponent::ClientFailTamingMinigame() { Game::entityManager->SerializeEntity(m_Parent); // Notify the end of a pet taming minigame - for (CppScripts::Script* script : CppScripts::GetEntityScripts(m_Parent)) { - script->OnNotifyPetTamingMinigame(m_Parent, tamer, ePetTamingNotifyType::FAILED); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + for (CppScripts::Script* script : CppScripts::GetEntityScripts(parentEntity)) { + script->OnNotifyPetTamingMinigame(parentEntity, tamer, ePetTamingNotifyType::FAILED); } } void PetComponent::Wander() { - m_MovementAI = m_Parent->GetComponent(); + m_MovementAI = Game::entityManager->GetEntity(m_Parent)->GetComponent(); - if (m_MovementAI == nullptr || !m_MovementAI->AtFinalWaypoint()) { - return; - } + if (!m_MovementAI || !m_MovementAI->AtFinalWaypoint()) return; m_MovementAI->SetHaltDistance(0); @@ -878,7 +864,7 @@ void PetComponent::Activate(Item* item, bool registerPet, bool fromTaming) { GameMessages::SendMarkInventoryItemAsActive(m_Owner, true, eUnequippableActiveType::PET, m_ItemId, GetOwner()->GetSystemAddress()); - activePets[m_Owner] = m_Parent->GetObjectID(); + activePets[m_Owner] = m_Parent; m_Timer = 3; @@ -887,9 +873,9 @@ void PetComponent::Activate(Item* item, bool registerPet, bool fromTaming) { owner->GetCharacter()->SetPlayerFlag(ePlayerFlag::FIRST_MANUAL_PET_HIBERNATE, true); if (registerPet) { - GameMessages::SendAddPetToPlayer(m_Owner, 0, GeneralUtils::UTF8ToUTF16(m_Name), m_DatabaseId, m_Parent->GetLOT(), owner->GetSystemAddress()); + GameMessages::SendAddPetToPlayer(m_Owner, 0, GeneralUtils::UTF8ToUTF16(m_Name), m_DatabaseId, Game::entityManager->GetEntity(m_Parent)->GetLOT(), owner->GetSystemAddress()); - GameMessages::SendRegisterPetID(m_Owner, m_Parent->GetObjectID(), owner->GetSystemAddress()); + GameMessages::SendRegisterPetID(m_Owner, m_Parent, owner->GetSystemAddress()); GameMessages::SendRegisterPetDBID(m_Owner, m_DatabaseId, owner->GetSystemAddress()); } @@ -913,8 +899,12 @@ void PetComponent::AddDrainImaginationTimer(Item* item, bool fromTaming) { // Drain by 1 when you summon pet or when this method is called, but not when we have just tamed this pet. if (!fromTaming) playerDestroyableComponent->Imagine(-1); + const auto playerId = playerEntity->GetObjectID(); + // Set this to a variable so when this is called back from the player the timer doesn't fire off. - m_Parent->AddCallbackTimer(m_PetInfo.imaginationDrainRate, [playerDestroyableComponent, this, item]() { + Game::entityManager->GetEntity(m_Parent)->AddCallbackTimer(m_PetInfo.imaginationDrainRate, [playerId, this, item]() { + auto* const playerDestroyableComponent = Game::entityManager->GetEntity(playerId)->GetComponent(); + if (!playerDestroyableComponent) { LOG("No petComponent and/or no playerDestroyableComponent"); return; @@ -934,17 +924,16 @@ void PetComponent::AddDrainImaginationTimer(Item* item, bool fromTaming) { } void PetComponent::Deactivate() { - GameMessages::SendPlayFXEffect(m_Parent->GetObjectID(), -1, u"despawn", "", LWOOBJID_EMPTY, 1, 1, true); + GameMessages::SendPlayFXEffect(m_Parent, -1, u"despawn", "", LWOOBJID_EMPTY, 1, 1, true); GameMessages::SendMarkInventoryItemAsActive(m_Owner, false, eUnequippableActiveType::PET, m_ItemId, GetOwner()->GetSystemAddress()); activePets.erase(m_Owner); - m_Parent->Kill(); + Game::entityManager->GetEntity(m_Parent)->Kill(); auto* owner = GetOwner(); - - if (owner == nullptr) return; + if (!owner) return; GameMessages::SendAddPetToPlayer(m_Owner, 0, u"", LWOOBJID_EMPTY, LOT_NULL, owner->GetSystemAddress()); @@ -957,10 +946,7 @@ void PetComponent::Deactivate() { void PetComponent::Release() { auto* inventoryComponent = GetOwner()->GetComponent(); - - if (inventoryComponent == nullptr) { - return; - } + if (!inventoryComponent) return; Deactivate(); @@ -977,7 +963,7 @@ void PetComponent::Command(const NiPoint3& position, const LWOOBJID source, cons if (commandType == 1) { // Emotes - GameMessages::SendPlayEmote(m_Parent->GetObjectID(), typeId, owner->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::SendPlayEmote(m_Parent, typeId, owner->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS); } else if (commandType == 3) { // Follow me, ??? } else if (commandType == 6) { @@ -1037,8 +1023,7 @@ PetComponent* PetComponent::GetTamingPet(LWOOBJID tamer) { } auto* entity = Game::entityManager->GetEntity(pair->second); - - if (entity == nullptr) { + if (!entity) { currentActivities.erase(tamer); return nullptr; @@ -1055,8 +1040,7 @@ PetComponent* PetComponent::GetActivePet(LWOOBJID owner) { } auto* entity = Game::entityManager->GetEntity(pair->second); - - if (entity == nullptr) { + if (!entity) { activePets.erase(owner); return nullptr; @@ -1066,10 +1050,7 @@ PetComponent* PetComponent::GetActivePet(LWOOBJID owner) { } Entity* PetComponent::GetParentEntity() const { - return m_Parent; -} - -PetComponent::~PetComponent() { + return Game::entityManager->GetEntity(m_Parent); } void PetComponent::SetPetNameForModeration(const std::string& petName) { diff --git a/dGame/dComponents/PetComponent.h b/dGame/dComponents/PetComponent.h index 24ee157bd..67c1c9d63 100644 --- a/dGame/dComponents/PetComponent.h +++ b/dGame/dComponents/PetComponent.h @@ -16,10 +16,9 @@ class PetComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PET; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::PET; - explicit PetComponent(Entity* parentEntity, uint32_t componentId); - ~PetComponent() override; + explicit PetComponent(const LWOOBJID& parentEntityId, uint32_t componentId); void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; void Update(float deltaTime) override; diff --git a/dGame/dComponents/PhantomPhysicsComponent.cpp b/dGame/dComponents/PhantomPhysicsComponent.cpp index 45d08b97f..57cf2ed98 100644 --- a/dGame/dComponents/PhantomPhysicsComponent.cpp +++ b/dGame/dComponents/PhantomPhysicsComponent.cpp @@ -27,10 +27,12 @@ #include "dpShapeBox.h" #include "dpShapeSphere.h" -PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent) : PhysicsComponent(parent) { - m_Position = m_Parent->GetDefaultPosition(); - m_Rotation = m_Parent->GetDefaultRotation(); - m_Scale = m_Parent->GetDefaultScale(); +PhantomPhysicsComponent::PhantomPhysicsComponent(const LWOOBJID& parentEntityId) : PhysicsComponent{ parentEntityId } { + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + + m_Position = parentEntity->GetDefaultPosition(); + m_Rotation = parentEntity->GetDefaultRotation(); + m_Scale = parentEntity->GetDefaultScale(); m_dpEntity = nullptr; m_EffectInfoDirty = false; @@ -46,17 +48,17 @@ PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent) : PhysicsCompon m_IsDirectional = false; m_Direction = NiPoint3(); // * m_DirectionalMultiplier - if (m_Parent->GetVar(u"create_physics")) { + if (parentEntity->GetVar(u"create_physics")) { CreatePhysics(); } - if (m_Parent->GetVar(u"respawnVol")) { + if (parentEntity->GetVar(u"respawnVol")) { m_IsRespawnVolume = true; } if (m_IsRespawnVolume) { { - auto respawnString = std::stringstream(m_Parent->GetVarAsString(u"rspPos")); + auto respawnString = std::stringstream(parentEntity->GetVarAsString(u"rspPos")); std::string segment; std::vector seglist; @@ -69,7 +71,7 @@ PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent) : PhysicsCompon } { - auto respawnString = std::stringstream(m_Parent->GetVarAsString(u"rspRot")); + auto respawnString = std::stringstream(parentEntity->GetVarAsString(u"rspRot")); std::string segment; std::vector seglist; @@ -83,7 +85,7 @@ PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent) : PhysicsCompon } // HF - RespawnPoints. Legacy respawn entity. - if (m_Parent->GetLOT() == 4945) { + if (parentEntity->GetLOT() == 4945) { m_IsRespawnVolume = true; m_RespawnPos = m_Position; m_RespawnRot = m_Rotation; @@ -132,7 +134,7 @@ PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent) : PhysicsCompon } } - if (m_Parent->GetLOT() == 4945) // HF - RespawnPoints + if (parentEntity->GetLOT() == 4945) // HF - RespawnPoints { m_IsRespawnVolume = true; m_RespawnPos = m_Position; @@ -144,7 +146,7 @@ PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent) : PhysicsCompon if (!m_HasCreatedPhysics) { CDComponentsRegistryTable* compRegistryTable = CDClientManager::Instance().GetTable(); - auto componentID = compRegistryTable->GetByIDAndType(m_Parent->GetLOT(), eReplicaComponentType::PHANTOM_PHYSICS); + auto componentID = compRegistryTable->GetByIDAndType(parentEntity->GetLOT(), eReplicaComponentType::PHANTOM_PHYSICS); CDPhysicsComponentTable* physComp = CDClientManager::Instance().GetTable(); @@ -155,7 +157,7 @@ PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent) : PhysicsCompon //temp test if (info->physicsAsset == "miscellaneous\\misc_phys_10x1x5.hkx") { - m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 10.0f, 5.0f, 1.0f); + m_dpEntity = new dpEntity(m_Parent, 10.0f, 5.0f, 1.0f); m_dpEntity->SetScale(m_Scale); m_dpEntity->SetRotation(m_Rotation); @@ -164,9 +166,9 @@ PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent) : PhysicsCompon dpWorld::AddEntity(m_dpEntity); } else if (info->physicsAsset == "miscellaneous\\misc_phys_640x640.hkx") { // Move this down by 13.521004 units so it is still effectively at the same height as before - m_Position = m_Position - NiPoint3::UNIT_Y * 13.521004f; + m_Position = m_Position - NiPoint3Constant::UNIT_Y * 13.521004f; // TODO Fix physics simulation to do simulation at high velocities due to bullet through paper problem... - m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 1638.4f, 13.521004f * 2.0f, 1638.4f); + m_dpEntity = new dpEntity(m_Parent, 1638.4f, 13.521004f * 2.0f, 1638.4f); m_dpEntity->SetScale(m_Scale); m_dpEntity->SetRotation(m_Rotation); @@ -174,49 +176,49 @@ PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent) : PhysicsCompon dpWorld::AddEntity(m_dpEntity); } else if (info->physicsAsset == "env\\trigger_wall_tall.hkx") { - m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 10.0f, 25.0f, 1.0f); + m_dpEntity = new dpEntity(m_Parent, 10.0f, 25.0f, 1.0f); m_dpEntity->SetScale(m_Scale); m_dpEntity->SetRotation(m_Rotation); m_dpEntity->SetPosition(m_Position); dpWorld::AddEntity(m_dpEntity); } else if (info->physicsAsset == "env\\env_gen_placeholderphysics.hkx") { - m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 20.0f, 20.0f, 20.0f); + m_dpEntity = new dpEntity(m_Parent, 20.0f, 20.0f, 20.0f); m_dpEntity->SetScale(m_Scale); m_dpEntity->SetRotation(m_Rotation); m_dpEntity->SetPosition(m_Position); dpWorld::AddEntity(m_dpEntity); } else if (info->physicsAsset == "env\\POI_trigger_wall.hkx") { - m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 1.0f, 12.5f, 20.0f); // Not sure what the real size is + m_dpEntity = new dpEntity(m_Parent, 1.0f, 12.5f, 20.0f); // Not sure what the real size is m_dpEntity->SetScale(m_Scale); m_dpEntity->SetRotation(m_Rotation); m_dpEntity->SetPosition(m_Position); dpWorld::AddEntity(m_dpEntity); } else if (info->physicsAsset == "env\\NG_NinjaGo\\env_ng_gen_gate_chamber_puzzle_ceiling_tile_falling_phantom.hkx") { - m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 18.0f, 5.0f, 15.0f); + m_dpEntity = new dpEntity(m_Parent, 18.0f, 5.0f, 15.0f); m_dpEntity->SetScale(m_Scale); m_dpEntity->SetRotation(m_Rotation); m_dpEntity->SetPosition(m_Position + m_Rotation.GetForwardVector() * 7.5f); dpWorld::AddEntity(m_dpEntity); } else if (info->physicsAsset == "env\\NG_NinjaGo\\ng_flamejet_brick_phantom.HKX") { - m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 1.0f, 1.0f, 12.0f); + m_dpEntity = new dpEntity(m_Parent, 1.0f, 1.0f, 12.0f); m_dpEntity->SetScale(m_Scale); m_dpEntity->SetRotation(m_Rotation); m_dpEntity->SetPosition(m_Position + m_Rotation.GetForwardVector() * 6.0f); dpWorld::AddEntity(m_dpEntity); } else if (info->physicsAsset == "env\\Ring_Trigger.hkx") { - m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 6.0f, 6.0f, 6.0f); + m_dpEntity = new dpEntity(m_Parent, 6.0f, 6.0f, 6.0f); m_dpEntity->SetScale(m_Scale); m_dpEntity->SetRotation(m_Rotation); m_dpEntity->SetPosition(m_Position); dpWorld::AddEntity(m_dpEntity); } else if (info->physicsAsset == "env\\vfx_propertyImaginationBall.hkx") { - m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 4.5f); + m_dpEntity = new dpEntity(m_Parent, 4.5f); m_dpEntity->SetScale(m_Scale); m_dpEntity->SetRotation(m_Rotation); m_dpEntity->SetPosition(m_Position); dpWorld::AddEntity(m_dpEntity); } else if (info->physicsAsset == "env\\env_won_fv_gas-blocking-volume.hkx") { - m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 390.496826f, 111.467964f, 600.821534f, true); + m_dpEntity = new dpEntity(m_Parent, 390.496826f, 111.467964f, 600.821534f, true); m_dpEntity->SetScale(m_Scale); m_dpEntity->SetRotation(m_Rotation); m_Position.y -= (111.467964f * m_Scale) / 2; @@ -226,7 +228,7 @@ PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent) : PhysicsCompon //LOG("This one is supposed to have %s", info->physicsAsset.c_str()); //add fallback cube: - m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 2.0f, 2.0f, 2.0f); + m_dpEntity = new dpEntity(m_Parent, 2.0f, 2.0f, 2.0f); m_dpEntity->SetScale(m_Scale); m_dpEntity->SetRotation(m_Rotation); m_dpEntity->SetPosition(m_Position); @@ -254,22 +256,22 @@ void PhantomPhysicsComponent::CreatePhysics() { float width = 0.0f; //aka "radius" float height = 0.0f; - if (m_Parent->HasVar(u"primitiveModelType")) { - type = m_Parent->GetVar(u"primitiveModelType"); - x = m_Parent->GetVar(u"primitiveModelValueX"); - y = m_Parent->GetVar(u"primitiveModelValueY"); - z = m_Parent->GetVar(u"primitiveModelValueZ"); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + + if (parentEntity->HasVar(u"primitiveModelType")) { + type = parentEntity->GetVar(u"primitiveModelType"); + x = parentEntity->GetVar(u"primitiveModelValueX"); + y = parentEntity->GetVar(u"primitiveModelValueY"); + z = parentEntity->GetVar(u"primitiveModelValueZ"); } else { CDComponentsRegistryTable* compRegistryTable = CDClientManager::Instance().GetTable(); - auto componentID = compRegistryTable->GetByIDAndType(m_Parent->GetLOT(), eReplicaComponentType::PHANTOM_PHYSICS); + auto componentID = compRegistryTable->GetByIDAndType(parentEntity->GetLOT(), eReplicaComponentType::PHANTOM_PHYSICS); CDPhysicsComponentTable* physComp = CDClientManager::Instance().GetTable(); - - if (physComp == nullptr) return; + if (!physComp) return; auto info = physComp->GetByID(componentID); - - if (info == nullptr) return; + if (!info) return; type = info->pcShapeType; width = info->playerRadius; @@ -291,7 +293,7 @@ void PhantomPhysicsComponent::CreatePhysics() { boxSize = NiPoint3(width, height, width); } - m_dpEntity = new dpEntity(m_Parent->GetObjectID(), boxSize); + m_dpEntity = new dpEntity(m_Parent, boxSize); break; } } @@ -350,7 +352,7 @@ void ApplyCollisionEffect(const LWOOBJID& target, const ePhysicsEffectType effec GameMessages::SendSetGravityScale(target, effectScale, targetEntity->GetSystemAddress()); } } - // The other types are not handled by the server + // The other types are not handled by the server case ePhysicsEffectType::ATTRACT: case ePhysicsEffectType::FRICTION: case ePhysicsEffectType::PUSH: @@ -364,10 +366,11 @@ void PhantomPhysicsComponent::Update(float deltaTime) { if (!m_dpEntity) return; //Process enter events + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); for (auto en : m_dpEntity->GetNewObjects()) { if (!en) continue; ApplyCollisionEffect(en->GetObjectID(), m_EffectType, m_DirectionalMultiplier); - m_Parent->OnCollisionPhantom(en->GetObjectID()); + parentEntity->OnCollisionPhantom(en->GetObjectID()); //If we are a respawn volume, inform the client: if (m_IsRespawnVolume) { @@ -385,7 +388,7 @@ void PhantomPhysicsComponent::Update(float deltaTime) { for (auto en : m_dpEntity->GetRemovedObjects()) { if (!en) continue; ApplyCollisionEffect(en->GetObjectID(), m_EffectType, 1.0f); - m_Parent->OnCollisionLeavePhantom(en->GetObjectID()); + parentEntity->OnCollisionLeavePhantom(en->GetObjectID()); } } @@ -402,7 +405,7 @@ void PhantomPhysicsComponent::SetDirection(const NiPoint3& pos) { void PhantomPhysicsComponent::SpawnVertices() { if (!m_dpEntity) return; - LOG("%llu", m_Parent->GetObjectID()); + LOG("%llu", m_Parent); auto box = static_cast(m_dpEntity->GetShape()); for (auto vert : box->GetVertices()) { LOG("%f, %f, %f", vert.x, vert.y, vert.z); @@ -411,7 +414,7 @@ void PhantomPhysicsComponent::SpawnVertices() { info.lot = 33; info.pos = vert; info.spawner = nullptr; - info.spawnerID = m_Parent->GetObjectID(); + info.spawnerID = m_Parent; info.spawnerNodeID = 0; Entity* newEntity = Game::entityManager->CreateEntity(info, nullptr); diff --git a/dGame/dComponents/PhantomPhysicsComponent.h b/dGame/dComponents/PhantomPhysicsComponent.h index 5fcee004f..c41f8b114 100644 --- a/dGame/dComponents/PhantomPhysicsComponent.h +++ b/dGame/dComponents/PhantomPhysicsComponent.h @@ -27,9 +27,9 @@ enum class ePhysicsEffectType : uint32_t ; */ class PhantomPhysicsComponent : public PhysicsComponent { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PHANTOM_PHYSICS; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::PHANTOM_PHYSICS; - PhantomPhysicsComponent(Entity* parent); + PhantomPhysicsComponent(const LWOOBJID& parentEntityId); ~PhantomPhysicsComponent() override; void Update(float deltaTime) override; void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; diff --git a/dGame/dComponents/PhysicsComponent.cpp b/dGame/dComponents/PhysicsComponent.cpp index a66c422a1..2e4222494 100644 --- a/dGame/dComponents/PhysicsComponent.cpp +++ b/dGame/dComponents/PhysicsComponent.cpp @@ -1,8 +1,11 @@ #include "PhysicsComponent.h" -PhysicsComponent::PhysicsComponent(Entity* parent) : Component(parent) { - m_Position = NiPoint3::ZERO; - m_Rotation = NiQuaternion::IDENTITY; +PhysicsComponent::PhysicsComponent(const LWOOBJID& parentEntityId) : Component{ parentEntityId } { + CheckComponentAssertions(); + + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + m_Position = parentEntity->GetDefaultPosition(); + m_Rotation = parentEntity->GetDefaultRotation(); m_DirtyPosition = false; } diff --git a/dGame/dComponents/PhysicsComponent.h b/dGame/dComponents/PhysicsComponent.h index c1a7f34a9..638f0c755 100644 --- a/dGame/dComponents/PhysicsComponent.h +++ b/dGame/dComponents/PhysicsComponent.h @@ -11,9 +11,12 @@ namespace Raknet { class PhysicsComponent : public Component { public: - PhysicsComponent(Entity* parent); + PhysicsComponent(const LWOOBJID& parentEntityId); virtual ~PhysicsComponent() = default; + PhysicsComponent(PhysicsComponent&& other) = default; // Move constructor + PhysicsComponent& operator=(PhysicsComponent&& other) = default; // Move-assignment operator + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; const NiPoint3& GetPosition() const { return m_Position; } diff --git a/dGame/dComponents/PlayerForcedMovementComponent.cpp b/dGame/dComponents/PlayerForcedMovementComponent.cpp index d511ad782..b4584fd03 100644 --- a/dGame/dComponents/PlayerForcedMovementComponent.cpp +++ b/dGame/dComponents/PlayerForcedMovementComponent.cpp @@ -1,10 +1,6 @@ #include "PlayerForcedMovementComponent.h" -PlayerForcedMovementComponent::PlayerForcedMovementComponent(Entity* parent) : Component(parent) { - m_Parent = parent; -} - -PlayerForcedMovementComponent::~PlayerForcedMovementComponent() {} +PlayerForcedMovementComponent::PlayerForcedMovementComponent(const LWOOBJID& parentEntityId) noexcept : Component{ parentEntityId } {} void PlayerForcedMovementComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { outBitStream->Write(m_DirtyInfo || bIsInitialUpdate); diff --git a/dGame/dComponents/PlayerForcedMovementComponent.h b/dGame/dComponents/PlayerForcedMovementComponent.h index 810b727c5..94c0cbfa6 100644 --- a/dGame/dComponents/PlayerForcedMovementComponent.h +++ b/dGame/dComponents/PlayerForcedMovementComponent.h @@ -10,14 +10,13 @@ */ class PlayerForcedMovementComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PLAYER_FORCED_MOVEMENT; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::PLAYER_FORCED_MOVEMENT; /** * Constructor for this component * @param parent parent that contains this component */ - PlayerForcedMovementComponent(Entity* parent); - ~PlayerForcedMovementComponent() override; + PlayerForcedMovementComponent(const LWOOBJID& parentEntityId) noexcept; void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; diff --git a/dGame/dComponents/PossessableComponent.cpp b/dGame/dComponents/PossessableComponent.cpp index 509b1a07c..3297a59cb 100644 --- a/dGame/dComponents/PossessableComponent.cpp +++ b/dGame/dComponents/PossessableComponent.cpp @@ -4,9 +4,9 @@ #include "Inventory.h" #include "Item.h" -PossessableComponent::PossessableComponent(Entity* parent, uint32_t componentId) : Component(parent) { +PossessableComponent::PossessableComponent(const LWOOBJID& parentEntityId, uint32_t componentId) : Component{ parentEntityId } { m_Possessor = LWOOBJID_EMPTY; - CDItemComponent item = Inventory::FindItemComponent(m_Parent->GetLOT()); + CDItemComponent item = Inventory::FindItemComponent(Game::entityManager->GetEntity(m_Parent)->GetLOT()); m_AnimationFlag = static_cast(item.animationFlag); // Get the possession Type from the CDClient @@ -44,12 +44,12 @@ void PossessableComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsIn void PossessableComponent::Dismount() { SetPossessor(LWOOBJID_EMPTY); - if (m_ItemSpawned) m_Parent->ScheduleKillAfterUpdate(); + if (m_ItemSpawned) Game::entityManager->GetEntity(m_Parent)->ScheduleKillAfterUpdate(); } void PossessableComponent::OnUse(Entity* originator) { auto* possessor = originator->GetComponent(); if (possessor) { - possessor->Mount(m_Parent); + possessor->Mount(Game::entityManager->GetEntity(m_Parent)); } } diff --git a/dGame/dComponents/PossessableComponent.h b/dGame/dComponents/PossessableComponent.h index 9a767ba9a..44cbff1ac 100644 --- a/dGame/dComponents/PossessableComponent.h +++ b/dGame/dComponents/PossessableComponent.h @@ -14,9 +14,9 @@ */ class PossessableComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::POSSESSABLE; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::POSSESSABLE; - PossessableComponent(Entity* parentEntity, uint32_t componentId); + PossessableComponent(const LWOOBJID& parentEntityId, uint32_t componentId); void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; diff --git a/dGame/dComponents/PossessorComponent.cpp b/dGame/dComponents/PossessorComponent.cpp index 0cb649564..a83d6d3ae 100644 --- a/dGame/dComponents/PossessorComponent.cpp +++ b/dGame/dComponents/PossessorComponent.cpp @@ -7,7 +7,7 @@ #include "eControlScheme.h" #include "eStateChangeType.h" -PossessorComponent::PossessorComponent(Entity* parent) : Component(parent) { +PossessorComponent::PossessorComponent(const LWOOBJID& parentEntityId) : Component{ parentEntityId } { m_Possessable = LWOOBJID_EMPTY; } @@ -18,7 +18,7 @@ PossessorComponent::~PossessorComponent() { auto* possessable = mount->GetComponent(); if (possessable) { if (possessable->GetIsItemSpawned()) { - GameMessages::SendMarkInventoryItemAsActive(m_Parent->GetObjectID(), false, eUnequippableActiveType::MOUNT, GetMountItemID(), m_Parent->GetSystemAddress()); + GameMessages::SendMarkInventoryItemAsActive(m_Parent, false, eUnequippableActiveType::MOUNT, GetMountItemID(), Game::entityManager->GetEntity(m_Parent)->GetSystemAddress()); } possessable->Dismount(); } @@ -42,21 +42,23 @@ void PossessorComponent::Mount(Entity* mount) { // Don't do anything if we are busy dismounting if (GetIsDismounting() || !mount) return; - GameMessages::SendSetMountInventoryID(m_Parent, mount->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + + GameMessages::SendSetMountInventoryID(parentEntity, mount->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS); auto* possessableComponent = mount->GetComponent(); if (possessableComponent) { - possessableComponent->SetPossessor(m_Parent->GetObjectID()); + possessableComponent->SetPossessor(m_Parent); SetPossessable(mount->GetObjectID()); SetPossessableType(possessableComponent->GetPossessionType()); } - auto characterComponent = m_Parent->GetComponent(); + auto characterComponent = parentEntity->GetComponent(); if (characterComponent) characterComponent->SetIsRacing(true); // GM's to send - GameMessages::SendSetJetPackMode(m_Parent, false); - GameMessages::SendVehicleUnlockInput(mount->GetObjectID(), false, m_Parent->GetSystemAddress()); - GameMessages::SendSetStunned(m_Parent->GetObjectID(), eStateChangeType::PUSH, m_Parent->GetSystemAddress(), LWOOBJID_EMPTY, true, false, true, false, false, false, false, true, true, true, true, true, true, true, true, true); + GameMessages::SendSetJetPackMode(parentEntity, false); + GameMessages::SendVehicleUnlockInput(mount->GetObjectID(), false, parentEntity->GetSystemAddress()); + GameMessages::SendSetStunned(m_Parent, eStateChangeType::PUSH, parentEntity->GetSystemAddress(), LWOOBJID_EMPTY, true, false, true, false, false, false, false, true, true, true, true, true, true, true, true, true); Game::entityManager->SerializeEntity(m_Parent); Game::entityManager->SerializeEntity(mount); @@ -76,9 +78,9 @@ void PossessorComponent::Dismount(Entity* mount, bool forceDismount) { Game::entityManager->SerializeEntity(m_Parent); Game::entityManager->SerializeEntity(mount); - auto characterComponent = m_Parent->GetComponent(); + auto characterComponent = Game::entityManager->GetEntity(m_Parent)->GetComponent(); if (characterComponent) characterComponent->SetIsRacing(false); } // Make sure we don't have wacky controls - GameMessages::SendSetPlayerControlScheme(m_Parent, eControlScheme::SCHEME_A); + GameMessages::SendSetPlayerControlScheme(Game::entityManager->GetEntity(m_Parent), eControlScheme::SCHEME_A); } diff --git a/dGame/dComponents/PossessorComponent.h b/dGame/dComponents/PossessorComponent.h index c225766b4..87b017610 100644 --- a/dGame/dComponents/PossessorComponent.h +++ b/dGame/dComponents/PossessorComponent.h @@ -18,9 +18,9 @@ enum class ePossessionType : uint8_t { */ class PossessorComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::POSSESSOR; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::POSSESSOR; - PossessorComponent(Entity* parent); + PossessorComponent(const LWOOBJID& parentEntityId); ~PossessorComponent() override; void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; diff --git a/dGame/dComponents/PropertyComponent.cpp b/dGame/dComponents/PropertyComponent.cpp index 4f8df40cc..62ea85fe3 100644 --- a/dGame/dComponents/PropertyComponent.cpp +++ b/dGame/dComponents/PropertyComponent.cpp @@ -2,10 +2,8 @@ #include "GameMessages.h" #include "dZoneManager.h" -PropertyComponent::PropertyComponent(Entity* parent) : Component(parent) { - m_PropertyName = parent->GetVar(u"propertyName"); - m_PropertyState = new PropertyState(); +PropertyComponent::PropertyComponent(const LWOOBJID& parentEntityId) + : Component{ parentEntityId } + , m_PropertyName{ Game::entityManager->GetEntity(m_Parent)->GetVar(u"propertyName") } + , m_PropertyState{ std::make_unique() } { } - -PropertyComponent::~PropertyComponent() = default; - diff --git a/dGame/dComponents/PropertyComponent.h b/dGame/dComponents/PropertyComponent.h index 135a1d26e..b122fef3d 100644 --- a/dGame/dComponents/PropertyComponent.h +++ b/dGame/dComponents/PropertyComponent.h @@ -22,12 +22,11 @@ struct PropertyState { */ class PropertyComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY; - explicit PropertyComponent(Entity* parentEntity); - ~PropertyComponent() override; - [[nodiscard]] PropertyState* GetPropertyState() const { return m_PropertyState; }; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY; + explicit PropertyComponent(const LWOOBJID& parentEntityId); + [[nodiscard]] PropertyState* GetPropertyState() const { return m_PropertyState.get(); }; private: - PropertyState* m_PropertyState; + std::unique_ptr m_PropertyState; std::string m_PropertyName; }; diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 2bb6ea309..411b8eb69 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -15,7 +15,7 @@ #include "eObjectBits.h" #include "eGameMasterLevel.h" -PropertyEntranceComponent::PropertyEntranceComponent(Entity* parent, uint32_t componentID) : Component(parent) { +PropertyEntranceComponent::PropertyEntranceComponent(const LWOOBJID& parentEntityId, uint32_t componentID) : Component{ parentEntityId } { this->propertyQueries = {}; auto table = CDClientManager::Instance().GetTable(); @@ -32,7 +32,7 @@ void PropertyEntranceComponent::OnUse(Entity* entity) { auto* rocket = entity->GetComponent()->RocketEquip(entity); if (!rocket) return; - GameMessages::SendPropertyEntranceBegin(m_Parent->GetObjectID(), entity->GetSystemAddress()); + GameMessages::SendPropertyEntranceBegin(m_Parent, entity->GetSystemAddress()); AMFArrayValue args; @@ -63,11 +63,8 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, cloneId = query[index].CloneId; } - auto* launcher = m_Parent->GetComponent(); - - if (launcher == nullptr) { - return; - } + auto* launcher = Game::entityManager->GetEntity(m_Parent)->GetComponent(); + if (!launcher) return; launcher->SetSelectedCloneId(entity->GetObjectID(), cloneId); @@ -330,5 +327,5 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl delete propertiesLeft; propertiesLeft = nullptr; - GameMessages::SendPropertySelectQuery(m_Parent->GetObjectID(), startIndex, numberOfProperties - (startIndex + numResults) > 0, character->GetPropertyCloneID(), false, true, entries, sysAddr); + GameMessages::SendPropertySelectQuery(m_Parent, startIndex, numberOfProperties - (startIndex + numResults) > 0, character->GetPropertyCloneID(), false, true, entries, sysAddr); } diff --git a/dGame/dComponents/PropertyEntranceComponent.h b/dGame/dComponents/PropertyEntranceComponent.h index ef8f98103..b06a4ca7d 100644 --- a/dGame/dComponents/PropertyEntranceComponent.h +++ b/dGame/dComponents/PropertyEntranceComponent.h @@ -13,8 +13,8 @@ */ class PropertyEntranceComponent : public Component { public: - explicit PropertyEntranceComponent(Entity* parent, uint32_t componentID); - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_ENTRANCE; + explicit PropertyEntranceComponent(const LWOOBJID& parentEntityId, uint32_t componentID); + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_ENTRANCE; /** * Handles an OnUse request for some other entity, rendering the property browse menu diff --git a/dGame/dComponents/PropertyManagementComponent.cpp b/dGame/dComponents/PropertyManagementComponent.cpp index dff1e5daa..ca30b457d 100644 --- a/dGame/dComponents/PropertyManagementComponent.cpp +++ b/dGame/dComponents/PropertyManagementComponent.cpp @@ -28,7 +28,7 @@ PropertyManagementComponent* PropertyManagementComponent::instance = nullptr; -PropertyManagementComponent::PropertyManagementComponent(Entity* parent) : Component(parent) { +PropertyManagementComponent::PropertyManagementComponent(const LWOOBJID& parentEntityId) : Component{ parentEntityId } { this->owner = LWOOBJID_EMPTY; this->templateId = 0; this->propertyId = LWOOBJID_EMPTY; @@ -196,9 +196,9 @@ bool PropertyManagementComponent::Claim(const LWOOBJID playerId) { std::string name = zone->GetZoneName(); std::string description = ""; - auto prop_path = zone->GetPath(m_Parent->GetVarAsString(u"propertyName")); + auto prop_path = zone->GetPath(Game::entityManager->GetEntity(m_Parent)->GetVarAsString(u"propertyName")); - if (prop_path){ + if (prop_path) { if (!prop_path->property.displayName.empty()) name = prop_path->property.displayName; description = prop_path->property.displayDesc; } @@ -297,7 +297,7 @@ void PropertyManagementComponent::UpdateModelPosition(const LWOOBJID id, const N const auto modelLOT = item->GetLot(); - if (rotation != NiQuaternion::IDENTITY) { + if (rotation != NiQuaternionConstant::IDENTITY) { rotation = { rotation.w, rotation.z, rotation.y, rotation.x }; } @@ -372,7 +372,7 @@ void PropertyManagementComponent::UpdateModelPosition(const LWOOBJID id, const N models.insert_or_assign(model->GetObjectID(), spawnerId); - GameMessages::SendPlaceModelResponse(entity->GetObjectID(), entity->GetSystemAddress(), position, m_Parent->GetObjectID(), 14, originalRotation); + GameMessages::SendPlaceModelResponse(entity->GetObjectID(), entity->GetSystemAddress(), position, m_Parent, 14, originalRotation); GameMessages::SendUGCEquipPreCreateBasedOnEditMode(entity->GetObjectID(), entity->GetSystemAddress(), 0, spawnerId); @@ -414,7 +414,7 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet GameMessages::SendUGCEquipPostDeleteBasedOnEditMode(entity->GetObjectID(), entity->GetSystemAddress(), LWOOBJID_EMPTY, 0); // Need this to pop the user out of their current state - GameMessages::SendPlaceModelResponse(entity->GetObjectID(), entity->GetSystemAddress(), entity->GetPosition(), m_Parent->GetObjectID(), 14, entity->GetRotation()); + GameMessages::SendPlaceModelResponse(entity->GetObjectID(), entity->GetSystemAddress(), entity->GetPosition(), m_Parent, 14, entity->GetRotation()); return; } @@ -481,7 +481,7 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet GameMessages::SendGetModelsOnProperty(entity->GetObjectID(), GetModels(), UNASSIGNED_SYSTEM_ADDRESS); - GameMessages::SendPlaceModelResponse(entity->GetObjectID(), entity->GetSystemAddress(), NiPoint3::ZERO, LWOOBJID_EMPTY, 16, NiQuaternion::IDENTITY); + GameMessages::SendPlaceModelResponse(entity->GetObjectID(), entity->GetSystemAddress(), NiPoint3Constant::ZERO, LWOOBJID_EMPTY, 16, NiQuaternionConstant::IDENTITY); if (spawner != nullptr) { Game::zoneManager->RemoveSpawner(spawner->m_Info.spawnerID); @@ -534,7 +534,7 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet GameMessages::SendGetModelsOnProperty(entity->GetObjectID(), GetModels(), UNASSIGNED_SYSTEM_ADDRESS); - GameMessages::SendPlaceModelResponse(entity->GetObjectID(), entity->GetSystemAddress(), NiPoint3::ZERO, LWOOBJID_EMPTY, 16, NiQuaternion::IDENTITY); + GameMessages::SendPlaceModelResponse(entity->GetObjectID(), entity->GetSystemAddress(), NiPoint3Constant::ZERO, LWOOBJID_EMPTY, 16, NiQuaternionConstant::IDENTITY); if (spawner != nullptr) { Game::zoneManager->RemoveSpawner(spawner->m_Info.spawnerID); @@ -683,7 +683,7 @@ PropertyManagementComponent* PropertyManagementComponent::Instance() { void PropertyManagementComponent::OnQueryPropertyData(Entity* originator, const SystemAddress& sysAddr, LWOOBJID author) { if (author == LWOOBJID_EMPTY) { - author = m_Parent->GetObjectID(); + author = m_Parent; } const auto& worldId = Game::zoneManager->GetZone()->GetZoneID(); @@ -742,7 +742,7 @@ void PropertyManagementComponent::OnQueryPropertyData(Entity* originator, const void PropertyManagementComponent::OnUse(Entity* originator) { OnQueryPropertyData(originator, UNASSIGNED_SYSTEM_ADDRESS); - GameMessages::SendOpenPropertyManagment(m_Parent->GetObjectID(), originator->GetSystemAddress()); + GameMessages::SendOpenPropertyManagment(m_Parent, originator->GetSystemAddress()); } void PropertyManagementComponent::SetOwnerId(const LWOOBJID value) { diff --git a/dGame/dComponents/PropertyManagementComponent.h b/dGame/dComponents/PropertyManagementComponent.h index d38437c42..7888ac156 100644 --- a/dGame/dComponents/PropertyManagementComponent.h +++ b/dGame/dComponents/PropertyManagementComponent.h @@ -32,8 +32,8 @@ enum class PropertyPrivacyOption class PropertyManagementComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_MANAGEMENT; - PropertyManagementComponent(Entity* parent); + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_MANAGEMENT; + PropertyManagementComponent(const LWOOBJID& parentEntityId); static PropertyManagementComponent* Instance(); /** diff --git a/dGame/dComponents/PropertyVendorComponent.cpp b/dGame/dComponents/PropertyVendorComponent.cpp index 502888d56..8b40afbd8 100644 --- a/dGame/dComponents/PropertyVendorComponent.cpp +++ b/dGame/dComponents/PropertyVendorComponent.cpp @@ -10,7 +10,7 @@ #include "PropertyManagementComponent.h" #include "UserManager.h" -PropertyVendorComponent::PropertyVendorComponent(Entity* parent) : Component(parent) { +PropertyVendorComponent::PropertyVendorComponent(const LWOOBJID& parentEntityId) : Component{ parentEntityId } { } void PropertyVendorComponent::OnUse(Entity* originator) { @@ -21,7 +21,7 @@ void PropertyVendorComponent::OnUse(Entity* originator) { if (PropertyManagementComponent::Instance()->GetOwnerId() == LWOOBJID_EMPTY) { LOG("Property vendor opening!"); - GameMessages::SendOpenPropertyVendor(m_Parent->GetObjectID(), originator->GetSystemAddress()); + GameMessages::SendOpenPropertyVendor(m_Parent, originator->GetSystemAddress()); return; } @@ -30,7 +30,7 @@ void PropertyVendorComponent::OnUse(Entity* originator) { void PropertyVendorComponent::OnQueryPropertyData(Entity* originator, const SystemAddress& sysAddr) { if (PropertyManagementComponent::Instance() == nullptr) return; - PropertyManagementComponent::Instance()->OnQueryPropertyData(originator, sysAddr, m_Parent->GetObjectID()); + PropertyManagementComponent::Instance()->OnQueryPropertyData(originator, sysAddr, m_Parent); } void PropertyVendorComponent::OnBuyFromVendor(Entity* originator, const bool confirmed, const LOT lot, const uint32_t count) { @@ -41,11 +41,11 @@ void PropertyVendorComponent::OnBuyFromVendor(Entity* originator, const bool con return; } - GameMessages::SendPropertyRentalResponse(m_Parent->GetObjectID(), 0, 0, 0, 0, originator->GetSystemAddress()); + GameMessages::SendPropertyRentalResponse(m_Parent, 0, 0, 0, 0, originator->GetSystemAddress()); auto* controller = Game::zoneManager->GetZoneControlObject(); - controller->OnFireEventServerSide(m_Parent, "propertyRented"); + controller->OnFireEventServerSide(Game::entityManager->GetEntity(m_Parent), "propertyRented"); PropertyManagementComponent::Instance()->SetOwner(originator); diff --git a/dGame/dComponents/PropertyVendorComponent.h b/dGame/dComponents/PropertyVendorComponent.h index 0e6c6521c..29211a98e 100644 --- a/dGame/dComponents/PropertyVendorComponent.h +++ b/dGame/dComponents/PropertyVendorComponent.h @@ -10,8 +10,8 @@ class PropertyVendorComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_VENDOR; - explicit PropertyVendorComponent(Entity* parent); + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_VENDOR; + explicit PropertyVendorComponent(const LWOOBJID& parentEntityId); /** * Handles a use event from some entity, if the property is cleared this allows the entity to claim it diff --git a/dGame/dComponents/ProximityMonitorComponent.cpp b/dGame/dComponents/ProximityMonitorComponent.cpp index fbac8ddb2..f1f7c4eaf 100644 --- a/dGame/dComponents/ProximityMonitorComponent.cpp +++ b/dGame/dComponents/ProximityMonitorComponent.cpp @@ -7,7 +7,7 @@ const std::map ProximityMonitorComponent::m_EmptyObjectMap = {}; -ProximityMonitorComponent::ProximityMonitorComponent(Entity* parent, int radiusSmall, int radiusLarge) : Component(parent) { +ProximityMonitorComponent::ProximityMonitorComponent(const LWOOBJID& parentEntityId, int radiusSmall, int radiusLarge) : Component{ parentEntityId } { if (radiusSmall != -1 && radiusLarge != -1) { SetProximityRadius(radiusSmall, "rocketSmall"); SetProximityRadius(radiusLarge, "rocketLarge"); @@ -25,8 +25,8 @@ ProximityMonitorComponent::~ProximityMonitorComponent() { } void ProximityMonitorComponent::SetProximityRadius(float proxRadius, const std::string& name) { - dpEntity* en = new dpEntity(m_Parent->GetObjectID(), proxRadius); - en->SetPosition(m_Parent->GetPosition()); + dpEntity* en = new dpEntity(m_Parent, proxRadius); + en->SetPosition(Game::entityManager->GetEntity(m_Parent)->GetPosition()); dpWorld::AddEntity(en); m_ProximitiesData.insert(std::make_pair(name, en)); @@ -34,7 +34,7 @@ void ProximityMonitorComponent::SetProximityRadius(float proxRadius, const std:: void ProximityMonitorComponent::SetProximityRadius(dpEntity* entity, const std::string& name) { dpWorld::AddEntity(entity); - entity->SetPosition(m_Parent->GetPosition()); + entity->SetPosition(Game::entityManager->GetEntity(m_Parent)->GetPosition()); m_ProximitiesData.insert(std::make_pair(name, entity)); } @@ -65,14 +65,14 @@ void ProximityMonitorComponent::Update(float deltaTime) { if (!prox.second) continue; //Process enter events + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); for (auto* en : prox.second->GetNewObjects()) { - m_Parent->OnCollisionProximity(en->GetObjectID(), prox.first, "ENTER"); + parentEntity->OnCollisionProximity(en->GetObjectID(), prox.first, "ENTER"); } //Process exit events for (auto* en : prox.second->GetRemovedObjects()) { - m_Parent->OnCollisionProximity(en->GetObjectID(), prox.first, "LEAVE"); + parentEntity->OnCollisionProximity(en->GetObjectID(), prox.first, "LEAVE"); } } } - diff --git a/dGame/dComponents/ProximityMonitorComponent.h b/dGame/dComponents/ProximityMonitorComponent.h index 90ba7d544..906afaea3 100644 --- a/dGame/dComponents/ProximityMonitorComponent.h +++ b/dGame/dComponents/ProximityMonitorComponent.h @@ -19,9 +19,9 @@ */ class ProximityMonitorComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PROXIMITY_MONITOR; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::PROXIMITY_MONITOR; - ProximityMonitorComponent(Entity* parentEntity, int smallRadius = -1, int largeRadius = -1); + ProximityMonitorComponent(const LWOOBJID& parentEntityId, int smallRadius = -1, int largeRadius = -1); ~ProximityMonitorComponent() override; void Update(float deltaTime) override; diff --git a/dGame/dComponents/QuickBuildComponent.cpp b/dGame/dComponents/QuickBuildComponent.cpp index b8aec2bde..be2018270 100644 --- a/dGame/dComponents/QuickBuildComponent.cpp +++ b/dGame/dComponents/QuickBuildComponent.cpp @@ -23,8 +23,9 @@ #include "CppScripts.h" -QuickBuildComponent::QuickBuildComponent(Entity* entity) : Component(entity) { - std::u16string checkPreconditions = entity->GetVar(u"CheckPrecondition"); +QuickBuildComponent::QuickBuildComponent(const LWOOBJID& parentEntityId) : Component{ parentEntityId } { + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + std::u16string checkPreconditions = parentEntity->GetVar(u"CheckPrecondition"); if (!checkPreconditions.empty()) { m_Precondition = new PreconditionExpression(GeneralUtils::UTF16ToWTF8(checkPreconditions)); @@ -32,14 +33,14 @@ QuickBuildComponent::QuickBuildComponent(Entity* entity) : Component(entity) { // Should a setting that has the build activator position exist, fetch that setting here and parse it for position. // It is assumed that the user who sets this setting uses the correct character delimiter (character 31 or in hex 0x1F) - auto positionAsVector = GeneralUtils::SplitString(m_Parent->GetVarAsString(u"rebuild_activators"), 0x1F); + auto positionAsVector = GeneralUtils::SplitString(parentEntity->GetVarAsString(u"rebuild_activators"), 0x1F); if (positionAsVector.size() == 3 && GeneralUtils::TryParse(positionAsVector[0], m_ActivatorPosition.x) && GeneralUtils::TryParse(positionAsVector[1], m_ActivatorPosition.y) && GeneralUtils::TryParse(positionAsVector[2], m_ActivatorPosition.z)) { } else { - LOG("Failed to find activator position for lot %i. Defaulting to parents position.", m_Parent->GetLOT()); - m_ActivatorPosition = m_Parent->GetPosition(); + LOG("Failed to find activator position for lot %i. Defaulting to parents position.", Game::entityManager->GetEntity(m_Parent)->GetLOT()); + m_ActivatorPosition = parentEntity->GetPosition(); } SpawnActivator(); @@ -57,7 +58,7 @@ QuickBuildComponent::~QuickBuildComponent() { } void QuickBuildComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { - if (m_Parent->GetComponent(eReplicaComponentType::DESTROYABLE) == nullptr) { + if (Game::entityManager->GetEntity(m_Parent)->GetComponent(eReplicaComponentType::DESTROYABLE) == nullptr) { if (bIsInitialUpdate) { outBitStream->Write(false); } @@ -127,7 +128,7 @@ void QuickBuildComponent::Update(float deltaTime) { SpawnActivator(); m_TimeBeforeDrain = 0; - auto* spawner = m_Parent->GetSpawner(); + auto* spawner = Game::entityManager->GetEntity(m_Parent)->GetSpawner(); const bool isSmashGroup = spawner != nullptr ? spawner->GetIsSpawnSmashGroup() : false; if (isSmashGroup) { @@ -144,7 +145,7 @@ void QuickBuildComponent::Update(float deltaTime) { if (m_TimerIncomplete >= m_TimeBeforeSmash) { m_Builder = LWOOBJID_EMPTY; - GameMessages::SendDieNoImplCode(m_Parent, LWOOBJID_EMPTY, LWOOBJID_EMPTY, eKillType::VIOLENT, u"", 0.0f, 0.0f, 0.0f, false, true); + GameMessages::SendDieNoImplCode(Game::entityManager->GetEntity(m_Parent), LWOOBJID_EMPTY, LWOOBJID_EMPTY, eKillType::VIOLENT, u"", 0.0f, 0.0f, 0.0f, false, true); ResetQuickBuild(false); } @@ -168,7 +169,7 @@ void QuickBuildComponent::Update(float deltaTime) { if (m_Timer >= m_ResetTime) { - GameMessages::SendDieNoImplCode(m_Parent, LWOOBJID_EMPTY, LWOOBJID_EMPTY, eKillType::VIOLENT, u"", 0.0f, 0.0f, 0.0f, false, true); + GameMessages::SendDieNoImplCode(Game::entityManager->GetEntity(m_Parent), LWOOBJID_EMPTY, LWOOBJID_EMPTY, eKillType::VIOLENT, u"", 0.0f, 0.0f, 0.0f, false, true); ResetQuickBuild(false); } @@ -229,7 +230,7 @@ void QuickBuildComponent::Update(float deltaTime) { if (m_TimerIncomplete >= m_TimeBeforeSmash) { m_Builder = LWOOBJID_EMPTY; - GameMessages::SendDieNoImplCode(m_Parent, LWOOBJID_EMPTY, LWOOBJID_EMPTY, eKillType::VIOLENT, u"", 0.0f, 0.0f, 0.0f, false, true); + GameMessages::SendDieNoImplCode(Game::entityManager->GetEntity(m_Parent), LWOOBJID_EMPTY, LWOOBJID_EMPTY, eKillType::VIOLENT, u"", 0.0f, 0.0f, 0.0f, false, true); ResetQuickBuild(false); } @@ -253,15 +254,15 @@ void QuickBuildComponent::OnUse(Entity* originator) { } void QuickBuildComponent::SpawnActivator() { - if (!m_SelfActivator || m_ActivatorPosition != NiPoint3::ZERO) { + if (!m_SelfActivator || m_ActivatorPosition != NiPoint3Constant::ZERO) { if (!m_Activator) { EntityInfo info; info.lot = 6604; - info.spawnerID = m_Parent->GetObjectID(); - info.pos = m_ActivatorPosition == NiPoint3::ZERO ? m_Parent->GetPosition() : m_ActivatorPosition; + info.spawnerID = m_Parent; + info.pos = m_ActivatorPosition == NiPoint3Constant::ZERO ? Game::entityManager->GetEntity(m_Parent)->GetPosition() : m_ActivatorPosition; - m_Activator = Game::entityManager->CreateEntity(info, nullptr, m_Parent); + m_Activator = Game::entityManager->CreateEntity(info, nullptr, Game::entityManager->GetEntity(m_Parent)); if (m_Activator) { m_ActivatorId = m_Activator->GetObjectID(); Game::entityManager->ConstructEntity(m_Activator); @@ -403,37 +404,39 @@ void QuickBuildComponent::StartQuickBuild(Entity* user) { Game::entityManager->SerializeEntity(user); - GameMessages::SendQuickBuildNotifyState(m_Parent, m_State, eQuickBuildState::BUILDING, user->GetObjectID()); - GameMessages::SendEnableQuickBuild(m_Parent, true, false, false, eQuickBuildFailReason::NOT_GIVEN, 0.0f, user->GetObjectID()); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + + GameMessages::SendQuickBuildNotifyState(parentEntity, m_State, eQuickBuildState::BUILDING, user->GetObjectID()); + GameMessages::SendEnableQuickBuild(parentEntity, true, false, false, eQuickBuildFailReason::NOT_GIVEN, 0.0f, user->GetObjectID()); m_State = eQuickBuildState::BUILDING; m_StateDirty = true; Game::entityManager->SerializeEntity(m_Parent); - auto* movingPlatform = m_Parent->GetComponent(); - if (movingPlatform != nullptr) { + auto* movingPlatform = parentEntity->GetComponent(); + if (movingPlatform) { movingPlatform->OnQuickBuildInitilized(); } - for (auto* script : CppScripts::GetEntityScripts(m_Parent)) { - script->OnQuickBuildStart(m_Parent, user); + for (auto* script : CppScripts::GetEntityScripts(parentEntity)) { + script->OnQuickBuildStart(parentEntity, user); } // Notify scripts and possible subscribers - for (auto* script : CppScripts::GetEntityScripts(m_Parent)) - script->OnQuickBuildNotifyState(m_Parent, m_State); - for (const auto& cb : m_QuickBuildStateCallbacks) + for (auto* script : CppScripts::GetEntityScripts(parentEntity)) { + script->OnQuickBuildNotifyState(parentEntity, m_State); + } + for (const auto& cb : m_QuickBuildStateCallbacks) { cb(m_State); + } } } void QuickBuildComponent::CompleteQuickBuild(Entity* user) { - if (user == nullptr) { - return; - } + if (!user) return; auto* characterComponent = user->GetComponent(); - if (characterComponent != nullptr) { + if (characterComponent) { characterComponent->SetCurrentActivity(eGameActivity::NONE); characterComponent->TrackQuickBuildComplete(); } else { @@ -443,10 +446,12 @@ void QuickBuildComponent::CompleteQuickBuild(Entity* user) { Game::entityManager->SerializeEntity(user); - GameMessages::SendQuickBuildNotifyState(m_Parent, m_State, eQuickBuildState::COMPLETED, user->GetObjectID()); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + + GameMessages::SendQuickBuildNotifyState(parentEntity, m_State, eQuickBuildState::COMPLETED, user->GetObjectID()); GameMessages::SendPlayFXEffect(m_Parent, 507, u"create", "BrickFadeUpVisCompleteEffect", LWOOBJID_EMPTY, 0.4f, 1.0f, true); - GameMessages::SendEnableQuickBuild(m_Parent, false, false, true, eQuickBuildFailReason::NOT_GIVEN, m_ResetTime, user->GetObjectID()); - GameMessages::SendTerminateInteraction(user->GetObjectID(), eTerminateType::FROM_INTERACTION, m_Parent->GetObjectID()); + GameMessages::SendEnableQuickBuild(parentEntity, false, false, true, eQuickBuildFailReason::NOT_GIVEN, m_ResetTime, user->GetObjectID()); + GameMessages::SendTerminateInteraction(user->GetObjectID(), eTerminateType::FROM_INTERACTION, m_Parent); m_State = eQuickBuildState::COMPLETED; @@ -466,7 +471,7 @@ void QuickBuildComponent::CompleteQuickBuild(Entity* user) { DespawnActivator(); // Set owner override so that entities smashed by this quickbuild will result in the builder getting rewards. - m_Parent->SetOwnerOverride(user->GetObjectID()); + parentEntity->SetOwnerOverride(user->GetObjectID()); auto* builder = GetBuilder(); @@ -484,33 +489,34 @@ void QuickBuildComponent::CompleteQuickBuild(Entity* user) { auto* missionComponent = builder->GetComponent(); if (missionComponent) missionComponent->Progress(eMissionTaskType::ACTIVITY, m_ActivityId); } - Loot::DropActivityLoot(builder, m_Parent, m_ActivityId, 1); + Loot::DropActivityLoot(builder, parentEntity, m_ActivityId, 1); } // Notify scripts - for (auto* script : CppScripts::GetEntityScripts(m_Parent)) { - script->OnQuickBuildComplete(m_Parent, user); - script->OnQuickBuildNotifyState(m_Parent, m_State); + for (auto* script : CppScripts::GetEntityScripts(parentEntity)) { + script->OnQuickBuildComplete(parentEntity, user); + script->OnQuickBuildNotifyState(parentEntity, m_State); } // Notify subscribers - for (const auto& callback : m_QuickBuildStateCallbacks) + for (const auto& callback : m_QuickBuildStateCallbacks) { callback(m_State); - for (const auto& callback : m_QuickBuildCompleteCallbacks) + } + for (const auto& callback : m_QuickBuildCompleteCallbacks) { callback(user); + } - m_Parent->TriggerEvent(eTriggerEventType::REBUILD_COMPLETE, user); + parentEntity->TriggerEvent(eTriggerEventType::REBUILD_COMPLETE, user); - auto* movingPlatform = m_Parent->GetComponent(); - if (movingPlatform != nullptr) { + auto* movingPlatform = parentEntity->GetComponent(); + if (movingPlatform) { movingPlatform->OnCompleteQuickBuild(); } // Set flag auto* character = user->GetCharacter(); - - if (character != nullptr) { - const auto flagNumber = m_Parent->GetVar(u"quickbuild_single_build_player_flag"); + if (character) { + const auto flagNumber = parentEntity->GetVar(u"quickbuild_single_build_player_flag"); if (flagNumber != 0) { character->SetPlayerFlag(flagNumber, true); @@ -520,17 +526,19 @@ void QuickBuildComponent::CompleteQuickBuild(Entity* user) { } void QuickBuildComponent::ResetQuickBuild(bool failed) { + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + Entity* builder = GetBuilder(); if (m_State == eQuickBuildState::BUILDING && builder) { - GameMessages::SendEnableQuickBuild(m_Parent, false, false, failed, eQuickBuildFailReason::NOT_GIVEN, m_ResetTime, builder->GetObjectID()); + GameMessages::SendEnableQuickBuild(parentEntity, false, false, failed, eQuickBuildFailReason::NOT_GIVEN, m_ResetTime, builder->GetObjectID()); if (failed) { RenderComponent::PlayAnimation(builder, u"rebuild-fail"); } } - GameMessages::SendQuickBuildNotifyState(m_Parent, m_State, eQuickBuildState::RESETTING, LWOOBJID_EMPTY); + GameMessages::SendQuickBuildNotifyState(parentEntity, m_State, eQuickBuildState::RESETTING, LWOOBJID_EMPTY); m_State = eQuickBuildState::RESETTING; m_StateDirty = true; @@ -542,12 +550,14 @@ void QuickBuildComponent::ResetQuickBuild(bool failed) { Game::entityManager->SerializeEntity(m_Parent); // Notify scripts and possible subscribers - for (auto* script : CppScripts::GetEntityScripts(m_Parent)) - script->OnQuickBuildNotifyState(m_Parent, m_State); - for (const auto& cb : m_QuickBuildStateCallbacks) + for (auto* script : CppScripts::GetEntityScripts(parentEntity)) { + script->OnQuickBuildNotifyState(parentEntity, m_State); + } + for (const auto& cb : m_QuickBuildStateCallbacks) { cb(m_State); + } - m_Parent->ScheduleKillAfterUpdate(); + parentEntity->ScheduleKillAfterUpdate(); if (m_Activator) { m_Activator->ScheduleKillAfterUpdate(); @@ -561,30 +571,32 @@ void QuickBuildComponent::CancelQuickBuild(Entity* entity, eQuickBuildFailReason const auto entityID = entity != nullptr ? entity->GetObjectID() : LWOOBJID_EMPTY; + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + // Notify the client that a state has changed - GameMessages::SendQuickBuildNotifyState(m_Parent, m_State, eQuickBuildState::INCOMPLETE, entityID); - GameMessages::SendEnableQuickBuild(m_Parent, false, true, false, failReason, m_Timer, entityID); + GameMessages::SendQuickBuildNotifyState(parentEntity, m_State, eQuickBuildState::INCOMPLETE, entityID); + GameMessages::SendEnableQuickBuild(parentEntity, false, true, false, failReason, m_Timer, entityID); // Now terminate any interaction with the rebuild - GameMessages::SendTerminateInteraction(entityID, eTerminateType::FROM_INTERACTION, m_Parent->GetObjectID()); - GameMessages::SendTerminateInteraction(m_Parent->GetObjectID(), eTerminateType::FROM_INTERACTION, m_Parent->GetObjectID()); + GameMessages::SendTerminateInteraction(entityID, eTerminateType::FROM_INTERACTION, m_Parent); + GameMessages::SendTerminateInteraction(m_Parent, eTerminateType::FROM_INTERACTION, m_Parent); // Now update the component itself m_State = eQuickBuildState::INCOMPLETE; m_StateDirty = true; // Notify scripts and possible subscribers - for (auto* script : CppScripts::GetEntityScripts(m_Parent)) - script->OnQuickBuildNotifyState(m_Parent, m_State); - for (const auto& cb : m_QuickBuildStateCallbacks) + for (auto* script : CppScripts::GetEntityScripts(parentEntity)) { + script->OnQuickBuildNotifyState(parentEntity, m_State); + } + for (const auto& cb : m_QuickBuildStateCallbacks) { cb(m_State); + } Game::entityManager->SerializeEntity(m_Parent); } - if (entity == nullptr) { - return; - } + if (!entity) return; CharacterComponent* characterComponent = entity->GetComponent(); if (characterComponent) { diff --git a/dGame/dComponents/QuickBuildComponent.h b/dGame/dComponents/QuickBuildComponent.h index f1106a61c..c8808466f 100644 --- a/dGame/dComponents/QuickBuildComponent.h +++ b/dGame/dComponents/QuickBuildComponent.h @@ -22,11 +22,15 @@ enum class eQuickBuildFailReason : uint32_t; */ class QuickBuildComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::QUICK_BUILD; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::QUICK_BUILD; - QuickBuildComponent(Entity* entity); + QuickBuildComponent(const LWOOBJID& parentEntityId); ~QuickBuildComponent() override; + /** + * TODO: Need to define move and move-assign constructors + */ + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; void Update(float deltaTime) override; @@ -242,7 +246,7 @@ class QuickBuildComponent : public Component { /** * The position that the quickbuild activator is spawned at */ - NiPoint3 m_ActivatorPosition = NiPoint3::ZERO; + NiPoint3 m_ActivatorPosition = NiPoint3Constant::ZERO; /** * The entity that represents the quickbuild activator diff --git a/dGame/dComponents/RacingControlComponent.cpp b/dGame/dComponents/RacingControlComponent.cpp index 5e3d81f4e..7451cf0ce 100644 --- a/dGame/dComponents/RacingControlComponent.cpp +++ b/dGame/dComponents/RacingControlComponent.cpp @@ -32,8 +32,8 @@ #define M_PI 3.14159265358979323846264338327950288 #endif -RacingControlComponent::RacingControlComponent(Entity* parent) - : Component(parent) { +RacingControlComponent::RacingControlComponent(const LWOOBJID& parentEntityId) + : Component{ parentEntityId } { m_PathName = u"MainPath"; m_RemainingLaps = 3; m_LeadingPlayer = LWOOBJID_EMPTY; @@ -119,8 +119,8 @@ void RacingControlComponent::LoadPlayerVehicle(Entity* player, GeneralUtils::UTF16ToWTF8(m_PathName)); auto spawnPointEntities = Game::entityManager->GetEntitiesByLOT(4843); - auto startPosition = NiPoint3::ZERO; - auto startRotation = NiQuaternion::IDENTITY; + auto startPosition = NiPoint3Constant::ZERO; + auto startRotation = NiQuaternionConstant::IDENTITY; const std::string placementAsString = std::to_string(positionNumber); for (auto entity : spawnPointEntities) { if (!entity) continue; @@ -142,28 +142,27 @@ void RacingControlComponent::LoadPlayerVehicle(Entity* player, info.lot = 8092; info.pos = startPosition; info.rot = startRotation; - info.spawnerID = m_Parent->GetObjectID(); + info.spawnerID = m_Parent; - auto* carEntity = - Game::entityManager->CreateEntity(info, nullptr, m_Parent); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + auto* const carEntity = Game::entityManager->CreateEntity(info, nullptr, Game::entityManager->GetEntity(m_Parent)); // This is very gross // Make the vehicle a child of the racing controller. - m_Parent->AddChild(carEntity); + parentEntity->AddChild(carEntity); // As is this auto* destroyableComponent = carEntity->GetComponent(); // Setup the vehicle stats. - if (destroyableComponent != nullptr) { + if (destroyableComponent) { destroyableComponent->SetMaxImagination(60); destroyableComponent->SetImagination(0); } // Setup the vehicle as being possessed by the player. - auto* possessableComponent = - carEntity->GetComponent(); + auto* possessableComponent = carEntity->GetComponent(); - if (possessableComponent != nullptr) { + if (possessableComponent) { possessableComponent->SetPossessor(player->GetObjectID()); } @@ -186,7 +185,7 @@ void RacingControlComponent::LoadPlayerVehicle(Entity* player, // Setup the player as possessing the vehicle. auto* possessorComponent = player->GetComponent(); - if (possessorComponent != nullptr) { + if (possessorComponent) { possessorComponent->SetPossessable(carEntity->GetObjectID()); possessorComponent->SetPossessableType(ePossessionType::ATTACHED_VISIBLE); // for racing it's always Attached_Visible } @@ -194,7 +193,7 @@ void RacingControlComponent::LoadPlayerVehicle(Entity* player, // Set the player's current activity as racing. auto* characterComponent = player->GetComponent(); - if (characterComponent != nullptr) { + if (characterComponent) { characterComponent->SetIsRacing(true); } @@ -222,29 +221,28 @@ void RacingControlComponent::LoadPlayerVehicle(Entity* player, Game::entityManager->SerializeEntity(m_Parent); GameMessages::SendRacingSetPlayerResetInfo( - m_Parent->GetObjectID(), 0, 0, player->GetObjectID(), startPosition, 1, - UNASSIGNED_SYSTEM_ADDRESS); + m_Parent, 0, 0, player->GetObjectID(), startPosition, 1, + UNASSIGNED_SYSTEM_ADDRESS + ); const auto playerID = player->GetObjectID(); // Reset the player to the start position during downtime, in case something // went wrong. - m_Parent->AddCallbackTimer(1, [this, playerID]() { + parentEntity->AddCallbackTimer(1, [this, playerID]() { auto* player = Game::entityManager->GetEntity(playerID); - if (player == nullptr) { - return; - } + if (!player) return; GameMessages::SendRacingResetPlayerToLastReset( - m_Parent->GetObjectID(), playerID, UNASSIGNED_SYSTEM_ADDRESS); + m_Parent, playerID, UNASSIGNED_SYSTEM_ADDRESS); }); GameMessages::SendSetJetPackMode(player, false); // Set the vehicle's state. GameMessages::SendNotifyVehicleOfRacingObject(carEntity->GetObjectID(), - m_Parent->GetObjectID(), + m_Parent, UNASSIGNED_SYSTEM_ADDRESS); GameMessages::SendVehicleSetWheelLockState(carEntity->GetObjectID(), false, @@ -265,7 +263,7 @@ void RacingControlComponent::OnRacingClientReady(Entity* player) { if (racingPlayer.playerID != player->GetObjectID()) { if (racingPlayer.playerLoaded) { GameMessages::SendRacingPlayerLoaded( - m_Parent->GetObjectID(), racingPlayer.playerID, + m_Parent, racingPlayer.playerID, racingPlayer.vehicleID, UNASSIGNED_SYSTEM_ADDRESS); } @@ -275,7 +273,7 @@ void RacingControlComponent::OnRacingClientReady(Entity* player) { racingPlayer.playerLoaded = true; GameMessages::SendRacingPlayerLoaded( - m_Parent->GetObjectID(), racingPlayer.playerID, + m_Parent, racingPlayer.playerID, racingPlayer.vehicleID, UNASSIGNED_SYSTEM_ADDRESS); } @@ -312,15 +310,16 @@ void RacingControlComponent::OnRequestDie(Entity* player) { // Respawn the player in 2 seconds, as was done in live. Not sure if this value is in a setting somewhere else... vehicle->AddCallbackTimer(2.0f, [=, this]() { - if (!vehicle || !this->m_Parent) return; + if (!vehicle) return; GameMessages::SendRacingResetPlayerToLastReset( - m_Parent->GetObjectID(), racingPlayer.playerID, - UNASSIGNED_SYSTEM_ADDRESS); + m_Parent, racingPlayer.playerID, + UNASSIGNED_SYSTEM_ADDRESS + ); GameMessages::SendVehicleStopBoost(vehicle, player->GetSystemAddress(), true); GameMessages::SendRacingSetPlayerResetInfo( - m_Parent->GetObjectID(), racingPlayer.lap, + m_Parent, racingPlayer.lap, racingPlayer.respawnIndex, player->GetObjectID(), racingPlayer.respawnPosition, racingPlayer.respawnIndex + 1, UNASSIGNED_SYSTEM_ADDRESS); @@ -338,13 +337,15 @@ void RacingControlComponent::OnRequestDie(Entity* player) { } } else { GameMessages::SendRacingSetPlayerResetInfo( - m_Parent->GetObjectID(), racingPlayer.lap, + m_Parent, racingPlayer.lap, racingPlayer.respawnIndex, player->GetObjectID(), racingPlayer.respawnPosition, racingPlayer.respawnIndex + 1, - UNASSIGNED_SYSTEM_ADDRESS); + UNASSIGNED_SYSTEM_ADDRESS + ); GameMessages::SendRacingResetPlayerToLastReset( - m_Parent->GetObjectID(), racingPlayer.playerID, - UNASSIGNED_SYSTEM_ADDRESS); + m_Parent, racingPlayer.playerID, + UNASSIGNED_SYSTEM_ADDRESS + ); } } } @@ -357,12 +358,8 @@ void RacingControlComponent::OnRacingPlayerInfoResetFinished(Entity* player) { continue; } - auto* vehicle = - Game::entityManager->GetEntity(racingPlayer.vehicleID); - - if (vehicle == nullptr) { - return; - } + auto* vehicle = Game::entityManager->GetEntity(racingPlayer.vehicleID); + if (!vehicle) return; racingPlayer.noSmashOnReload = false; @@ -372,10 +369,7 @@ void RacingControlComponent::OnRacingPlayerInfoResetFinished(Entity* player) { void RacingControlComponent::HandleMessageBoxResponse(Entity* player, int32_t button, const std::string& id) { auto* data = GetPlayerData(player->GetObjectID()); - - if (data == nullptr) { - return; - } + if (!data) return; if (id == "rewardButton") { if (data->collectedRewards) return; @@ -389,11 +383,11 @@ void RacingControlComponent::HandleMessageBoxResponse(Entity* player, int32_t bu } const auto score = playersRating * 10 + data->finished; - Loot::GiveActivityLoot(player, m_Parent, m_ActivityID, score); + Loot::GiveActivityLoot(player, Game::entityManager->GetEntity(m_Parent), m_ActivityID, score); // Giving rewards GameMessages::SendNotifyRacingClient( - m_Parent->GetObjectID(), 2, 0, LWOOBJID_EMPTY, u"", + m_Parent, 2, 0, LWOOBJID_EMPTY, u"", player->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS); auto* missionComponent = player->GetComponent(); @@ -423,8 +417,9 @@ void RacingControlComponent::HandleMessageBoxResponse(Entity* player, int32_t bu // Exiting race GameMessages::SendNotifyRacingClient( - m_Parent->GetObjectID(), 3, 0, LWOOBJID_EMPTY, u"", - player->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS); + m_Parent, 3, 0, LWOOBJID_EMPTY, u"", + player->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS + ); auto* characterComponent = player->GetComponent(); @@ -644,7 +639,7 @@ void RacingControlComponent::Update(float deltaTime) { // Setup for racing if (m_StartTimer == 0) { GameMessages::SendNotifyRacingClient( - m_Parent->GetObjectID(), 1, 0, LWOOBJID_EMPTY, u"", + m_Parent, 1, 0, LWOOBJID_EMPTY, u"", LWOOBJID_EMPTY, UNASSIGNED_SYSTEM_ADDRESS); for (const auto& player : m_RacingPlayers) { @@ -728,8 +723,7 @@ void RacingControlComponent::Update(float deltaTime) { } // Start the race - GameMessages::SendActivityStart(m_Parent->GetObjectID(), - UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::SendActivityStart(m_Parent, UNASSIGNED_SYSTEM_ADDRESS); m_Started = true; @@ -766,8 +760,8 @@ void RacingControlComponent::Update(float deltaTime) { // If the player is this far below the map, safe to assume they should // be smashed by death plane if (vehiclePosition.y < -500) { - GameMessages::SendDie(vehicle, m_Parent->GetObjectID(), - LWOOBJID_EMPTY, true, eKillType::VIOLENT, u"", 0, 0, 0, + GameMessages::SendDie(vehicle, m_Parent, LWOOBJID_EMPTY, + true, eKillType::VIOLENT, u"", 0, 0, 0, true, false, 0); OnRequestDie(playerEntity); @@ -818,7 +812,7 @@ void RacingControlComponent::Update(float deltaTime) { // Some offset up to make they don't fall through the terrain on a // respawn, seems to fix itself to the track anyhow - player.respawnPosition = position + NiPoint3::UNIT_Y * 5; + player.respawnPosition = position + NiPoint3Constant::UNIT_Y * 5; player.respawnRotation = vehicle->GetRotation(); player.respawnIndex = respawnIndex; diff --git a/dGame/dComponents/RacingControlComponent.h b/dGame/dComponents/RacingControlComponent.h index 47341aaea..a2f275da1 100644 --- a/dGame/dComponents/RacingControlComponent.h +++ b/dGame/dComponents/RacingControlComponent.h @@ -105,9 +105,9 @@ struct RacingPlayerInfo { */ class RacingControlComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::RACING_CONTROL; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::RACING_CONTROL; - RacingControlComponent(Entity* parentEntity); + RacingControlComponent(const LWOOBJID& parentEntityId); ~RacingControlComponent(); void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; diff --git a/dGame/dComponents/RacingSoundTriggerComponent.h b/dGame/dComponents/RacingSoundTriggerComponent.h index 0f79c67f3..40b7edb2d 100644 --- a/dGame/dComponents/RacingSoundTriggerComponent.h +++ b/dGame/dComponents/RacingSoundTriggerComponent.h @@ -8,8 +8,8 @@ class Entity; class RacingSoundTriggerComponent : public SoundTriggerComponent { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::RACING_SOUND_TRIGGER; - RacingSoundTriggerComponent(Entity* parent) : SoundTriggerComponent(parent){}; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::RACING_SOUND_TRIGGER; + RacingSoundTriggerComponent(const LWOOBJID& parentEntityId) : SoundTriggerComponent(parentEntityId) {}; }; #endif //!__RACINGSOUNDTRIGGERCOMPONENT__H__ diff --git a/dGame/dComponents/RacingStatsComponent.h b/dGame/dComponents/RacingStatsComponent.h index 9349ce491..c9388eac8 100644 --- a/dGame/dComponents/RacingStatsComponent.h +++ b/dGame/dComponents/RacingStatsComponent.h @@ -6,9 +6,9 @@ class RacingStatsComponent final : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::RACING_STATS; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::RACING_STATS; - RacingStatsComponent(Entity* parent) : Component(parent) {} + RacingStatsComponent(const LWOOBJID& parentEntityId) : Component{ parentEntityId } {} }; #endif //!__RACINGSTATSCOMPONENT__H__ diff --git a/dGame/dComponents/RailActivatorComponent.cpp b/dGame/dComponents/RailActivatorComponent.cpp index e0eb035a6..e5d953e2a 100644 --- a/dGame/dComponents/RailActivatorComponent.cpp +++ b/dGame/dComponents/RailActivatorComponent.cpp @@ -11,13 +11,15 @@ #include "EntityManager.h" #include "eStateChangeType.h" -RailActivatorComponent::RailActivatorComponent(Entity* parent, int32_t componentID) : Component(parent) { +RailActivatorComponent::RailActivatorComponent(const LWOOBJID& parentEntityId, int32_t componentID) : Component{ parentEntityId } { m_ComponentID = componentID; const auto tableData = CDClientManager::Instance().GetTable()->GetEntryByID(componentID);; - m_Path = parent->GetVar(u"rail_path"); - m_PathDirection = parent->GetVar(u"rail_path_direction"); - m_PathStart = parent->GetVar(u"rail_path_start"); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + + m_Path = parentEntity->GetVar(u"rail_path"); + m_PathDirection = parentEntity->GetVar(u"rail_path_direction"); + m_PathStart = parentEntity->GetVar(u"rail_path_start"); m_StartSound = tableData.startSound; m_loopSound = tableData.loopSound; @@ -31,23 +33,21 @@ RailActivatorComponent::RailActivatorComponent(Entity* parent, int32_t component m_LoopEffect = tableData.loopEffectID; m_StopEffect = tableData.stopEffectID; - m_DamageImmune = parent->GetVar(u"rail_activator_damage_immune"); - m_NoAggro = parent->GetVar(u"rail_no_aggro"); - m_NotifyArrived = parent->GetVar(u"rail_notify_activator_arrived"); - m_ShowNameBillboard = parent->GetVar(u"rail_show_name_billboard"); - m_UseDB = parent->GetVar(u"rail_use_db"); + m_DamageImmune = parentEntity->GetVar(u"rail_activator_damage_immune"); + m_NoAggro = parentEntity->GetVar(u"rail_no_aggro"); + m_NotifyArrived = parentEntity->GetVar(u"rail_notify_activator_arrived"); + m_ShowNameBillboard = parentEntity->GetVar(u"rail_show_name_billboard"); + m_UseDB = parentEntity->GetVar(u"rail_use_db"); m_CameraLocked = tableData.cameraLocked; m_CollisionEnabled = tableData.playerCollision; } -RailActivatorComponent::~RailActivatorComponent() = default; - void RailActivatorComponent::OnUse(Entity* originator) { - auto* quickBuildComponent = m_Parent->GetComponent(); - if (quickBuildComponent != nullptr && quickBuildComponent->GetState() != eQuickBuildState::COMPLETED) + auto* quickBuildComponent = Game::entityManager->GetEntity(m_Parent)->GetComponent(); + if (quickBuildComponent && quickBuildComponent->GetState() != eQuickBuildState::COMPLETED) return; - if (quickBuildComponent != nullptr) { + if (quickBuildComponent) { // Don't want it to be destroyed while a player is using it quickBuildComponent->SetResetTime(quickBuildComponent->GetResetTime() + 10.0f); } @@ -67,7 +67,7 @@ void RailActivatorComponent::OnUse(Entity* originator) { const auto originatorID = originator->GetObjectID(); - m_Parent->AddCallbackTimer(animationLength, [originatorID, this]() { + Game::entityManager->GetEntity(m_Parent)->AddCallbackTimer(animationLength, [originatorID, this]() { auto* originator = Game::entityManager->GetEntity(originatorID); if (originator == nullptr) { @@ -78,7 +78,7 @@ void RailActivatorComponent::OnUse(Entity* originator) { m_loopSound, m_StopSound, originator->GetSystemAddress(), m_PathStart, m_PathDirection, m_DamageImmune, m_NoAggro, m_NotifyArrived, m_ShowNameBillboard, m_CameraLocked, m_CollisionEnabled, m_UseDB, m_ComponentID, - m_Parent->GetObjectID()); + m_Parent); }); } @@ -106,7 +106,7 @@ void RailActivatorComponent::OnRailMovementReady(Entity* originator) const { GameMessages::SendSetRailMovement(originator->GetObjectID(), m_PathDirection, m_Path, m_PathStart, originator->GetSystemAddress(), m_ComponentID, - m_Parent->GetObjectID()); + m_Parent); } } @@ -116,7 +116,7 @@ void RailActivatorComponent::OnCancelRailMovement(Entity* originator) { true, true, true, true, true, true, true ); - auto* quickBuildComponent = m_Parent->GetComponent(); + auto* quickBuildComponent = Game::entityManager->GetEntity(m_Parent)->GetComponent(); if (quickBuildComponent != nullptr) { // Set back reset time diff --git a/dGame/dComponents/RailActivatorComponent.h b/dGame/dComponents/RailActivatorComponent.h index 28b250734..91bfa129e 100644 --- a/dGame/dComponents/RailActivatorComponent.h +++ b/dGame/dComponents/RailActivatorComponent.h @@ -12,10 +12,9 @@ */ class RailActivatorComponent final : public Component { public: - explicit RailActivatorComponent(Entity* parent, int32_t componentID); - ~RailActivatorComponent() override; + explicit RailActivatorComponent(const LWOOBJID& parentEntityId, int32_t componentID); - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::RAIL_ACTIVATOR; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::RAIL_ACTIVATOR; /** * Handles the OnUse event from some entity, initiates the rail movement diff --git a/dGame/dComponents/RenderComponent.cpp b/dGame/dComponents/RenderComponent.cpp index 4d8ff667d..313ca9304 100644 --- a/dGame/dComponents/RenderComponent.cpp +++ b/dGame/dComponents/RenderComponent.cpp @@ -14,8 +14,8 @@ std::unordered_map RenderComponent::m_DurationCache{}; -RenderComponent::RenderComponent(Entity* parent, int32_t componentId): Component(parent) { - m_Effects = std::vector(); +RenderComponent::RenderComponent(const LWOOBJID& parentEntityId, const int32_t componentId): Component{ parentEntityId } { + m_Effects = std::vector>(); m_LastAnimationName = ""; if (componentId == -1) return; @@ -42,23 +42,12 @@ RenderComponent::RenderComponent(Entity* parent, int32_t componentId): Component result.finalize(); } -RenderComponent::~RenderComponent() { - for (Effect* eff : m_Effects) { - if (eff) { - delete eff; - eff = nullptr; - } - } - - m_Effects.clear(); -} - void RenderComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { if (!bIsInitialUpdate) return; outBitStream->Write(m_Effects.size()); - for (Effect* eff : m_Effects) { + for (auto& eff : m_Effects) { // we still need to write 0 as the size for name if it is a nullptr if (!eff) { outBitStream->Write(0); @@ -82,27 +71,29 @@ void RenderComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitial } Effect* RenderComponent::AddEffect(const int32_t effectId, const std::string& name, const std::u16string& type, const float priority) { - auto* eff = new Effect(); + auto eff = std::make_unique(); eff->effectID = effectId; eff->name = name; eff->type = type; eff->priority = priority; - m_Effects.push_back(eff); - return eff; + auto* nonOwningPtr = eff.get(); + m_Effects.push_back(std::move(eff)); + + return nonOwningPtr; } void RenderComponent::RemoveEffect(const std::string& name) { uint32_t index = -1; for (auto i = 0u; i < m_Effects.size(); ++i) { - auto* eff = m_Effects[i]; + auto& eff = m_Effects[i]; if (eff->name == name) { index = i; - delete eff; + eff.reset(); // Delete effect break; } @@ -118,7 +109,7 @@ void RenderComponent::RemoveEffect(const std::string& name) { void RenderComponent::Update(const float deltaTime) { std::vector dead; - for (auto* effect : m_Effects) { + for (auto& effect : m_Effects) { if (effect->time == 0) { continue; // Skip persistent effects } @@ -126,7 +117,7 @@ void RenderComponent::Update(const float deltaTime) { const auto result = effect->time - deltaTime; if (result <= 0) { - dead.push_back(effect); + dead.push_back(effect.get()); continue; } @@ -186,7 +177,7 @@ void RenderComponent::StopEffect(const std::string& name, const bool killImmedia RemoveEffect(name); } -std::vector& RenderComponent::GetEffects() { +std::vector>& RenderComponent::GetEffects() { return m_Effects; } diff --git a/dGame/dComponents/RenderComponent.h b/dGame/dComponents/RenderComponent.h index 74f39625a..434b77bbe 100644 --- a/dGame/dComponents/RenderComponent.h +++ b/dGame/dComponents/RenderComponent.h @@ -56,10 +56,10 @@ struct Effect { */ class RenderComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::RENDER; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::RENDER; - RenderComponent(Entity* entity, int32_t componentId = -1); - ~RenderComponent() override; + RenderComponent(const LWOOBJID& parentEntityId, const int32_t componentId = -1); + //~RenderComponent() override; void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; void Update(float deltaTime) override; @@ -103,7 +103,7 @@ class RenderComponent : public Component { * Returns the list of currently active effects * @return */ - std::vector& GetEffects(); + std::vector>& GetEffects(); /** * Verifies that an animation can be played on this entity by checking @@ -136,7 +136,7 @@ class RenderComponent : public Component { /** * List of currently active effects */ - std::vector m_Effects; + std::vector> m_Effects; std::vector m_animationGroupIds; diff --git a/dGame/dComponents/RigidbodyPhantomPhysicsComponent.cpp b/dGame/dComponents/RigidbodyPhantomPhysicsComponent.cpp index 414ce2e83..036254d19 100644 --- a/dGame/dComponents/RigidbodyPhantomPhysicsComponent.cpp +++ b/dGame/dComponents/RigidbodyPhantomPhysicsComponent.cpp @@ -6,9 +6,11 @@ #include "RigidbodyPhantomPhysicsComponent.h" #include "Entity.h" -RigidbodyPhantomPhysicsComponent::RigidbodyPhantomPhysicsComponent(Entity* parent) : PhysicsComponent(parent) { - m_Position = m_Parent->GetDefaultPosition(); - m_Rotation = m_Parent->GetDefaultRotation(); +RigidbodyPhantomPhysicsComponent::RigidbodyPhantomPhysicsComponent(const LWOOBJID& parentEntityId) : PhysicsComponent{ parentEntityId } { + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + + m_Position = parentEntity->GetDefaultPosition(); + m_Rotation = parentEntity->GetDefaultRotation(); } void RigidbodyPhantomPhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { diff --git a/dGame/dComponents/RigidbodyPhantomPhysicsComponent.h b/dGame/dComponents/RigidbodyPhantomPhysicsComponent.h index bc60c38e9..1e2ae644f 100644 --- a/dGame/dComponents/RigidbodyPhantomPhysicsComponent.h +++ b/dGame/dComponents/RigidbodyPhantomPhysicsComponent.h @@ -19,9 +19,9 @@ */ class RigidbodyPhantomPhysicsComponent : public PhysicsComponent { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS; - RigidbodyPhantomPhysicsComponent(Entity* parent); + RigidbodyPhantomPhysicsComponent(const LWOOBJID& parentEntityId); void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; }; diff --git a/dGame/dComponents/RocketLaunchpadControlComponent.cpp b/dGame/dComponents/RocketLaunchpadControlComponent.cpp index 5a3855465..77f377901 100644 --- a/dGame/dComponents/RocketLaunchpadControlComponent.cpp +++ b/dGame/dComponents/RocketLaunchpadControlComponent.cpp @@ -20,7 +20,7 @@ #include "eConnectionType.h" #include "eMasterMessageType.h" -RocketLaunchpadControlComponent::RocketLaunchpadControlComponent(Entity* parent, int rocketId) : Component(parent) { +RocketLaunchpadControlComponent::RocketLaunchpadControlComponent(const LWOOBJID& parentEntityId, int rocketId) : Component{ parentEntityId } { auto query = CDClientDatabase::CreatePreppedStmt( "SELECT targetZone, defaultZoneID, targetScene, altLandingPrecondition, altLandingSpawnPointName FROM RocketLaunchpadControlComponent WHERE id = ?;"); query.bind(1, rocketId); @@ -77,7 +77,7 @@ void RocketLaunchpadControlComponent::Launch(Entity* originator, LWOMAPID mapId, SetSelectedMapId(originator->GetObjectID(), zone); - GameMessages::SendFireEventClientSide(m_Parent->GetObjectID(), originator->GetSystemAddress(), u"RocketEquipped", rocket->GetId(), cloneId, -1, originator->GetObjectID()); + GameMessages::SendFireEventClientSide(m_Parent, originator->GetSystemAddress(), u"RocketEquipped", rocket->GetId(), cloneId, -1, originator->GetObjectID()); GameMessages::SendChangeObjectWorldState(rocket->GetId(), eObjectWorldState::ATTACHED, UNASSIGNED_SYSTEM_ADDRESS); @@ -89,21 +89,18 @@ void RocketLaunchpadControlComponent::OnUse(Entity* originator) { // instead we let their OnUse handlers do their things // which components of an Object have their OnUse called when using them // so we don't need to call it here - auto* propertyEntrance = m_Parent->GetComponent(); - if (propertyEntrance) { - return; - } + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); - auto* rocketLaunchLUP = m_Parent->GetComponent(); - if (rocketLaunchLUP) { - return; - } + auto* const propertyEntrance = parentEntity->GetComponent(); + if (propertyEntrance) return; + + auto* rocketLaunchLUP = Game::entityManager->GetEntity(m_Parent)->GetComponent(); + if (rocketLaunchLUP) return; // No rocket no launch auto* rocket = originator->GetComponent()->RocketEquip(originator); - if (!rocket) { - return; - } + if (!rocket) return; + Launch(originator); } diff --git a/dGame/dComponents/RocketLaunchpadControlComponent.h b/dGame/dComponents/RocketLaunchpadControlComponent.h index 06d97cd33..0caa156ae 100644 --- a/dGame/dComponents/RocketLaunchpadControlComponent.h +++ b/dGame/dComponents/RocketLaunchpadControlComponent.h @@ -18,9 +18,9 @@ class PreconditionExpression; */ class RocketLaunchpadControlComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::ROCKET_LAUNCH; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::ROCKET_LAUNCH; - RocketLaunchpadControlComponent(Entity* parent, int rocketId); + RocketLaunchpadControlComponent(const LWOOBJID& parentEntityId, int rocketId); ~RocketLaunchpadControlComponent() override; /** diff --git a/dGame/dComponents/ScriptedActivityComponent.h b/dGame/dComponents/ScriptedActivityComponent.h index 79a9593d5..3845c2830 100644 --- a/dGame/dComponents/ScriptedActivityComponent.h +++ b/dGame/dComponents/ScriptedActivityComponent.h @@ -8,8 +8,8 @@ class Entity; class ScriptedActivityComponent : public ActivityComponent { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::SCRIPTED_ACTIVITY; - ScriptedActivityComponent(Entity* parent, int activityID) : ActivityComponent(parent, activityID){}; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::SCRIPTED_ACTIVITY; + ScriptedActivityComponent(const LWOOBJID& parentEntityId, int activityID) : ActivityComponent(parentEntityId, activityID){}; }; #endif //!__SCRIPTEDACTIVITYCOMPONENT__H__ diff --git a/dGame/dComponents/ShootingGalleryComponent.cpp b/dGame/dComponents/ShootingGalleryComponent.cpp index 45cd93427..ffee2d8ae 100644 --- a/dGame/dComponents/ShootingGalleryComponent.cpp +++ b/dGame/dComponents/ShootingGalleryComponent.cpp @@ -2,7 +2,7 @@ #include "EntityManager.h" #include "ScriptedActivityComponent.h" -ShootingGalleryComponent::ShootingGalleryComponent(Entity* parent) : Component(parent) { +ShootingGalleryComponent::ShootingGalleryComponent(const LWOOBJID& parentEntityId) : Component{ parentEntityId } { } ShootingGalleryComponent::~ShootingGalleryComponent() = default; diff --git a/dGame/dComponents/ShootingGalleryComponent.h b/dGame/dComponents/ShootingGalleryComponent.h index 4024e99af..e3a9181a7 100644 --- a/dGame/dComponents/ShootingGalleryComponent.h +++ b/dGame/dComponents/ShootingGalleryComponent.h @@ -73,9 +73,9 @@ struct StaticShootingGalleryParams { */ class ShootingGalleryComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::SHOOTING_GALLERY; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::SHOOTING_GALLERY; - explicit ShootingGalleryComponent(Entity* parent); + explicit ShootingGalleryComponent(const LWOOBJID& parentEntityId); ~ShootingGalleryComponent(); void Serialize(RakNet::BitStream* outBitStream, bool isInitialUpdate) override; diff --git a/dGame/dComponents/SimplePhysicsComponent.cpp b/dGame/dComponents/SimplePhysicsComponent.cpp index 3d8165dd5..642ae557c 100644 --- a/dGame/dComponents/SimplePhysicsComponent.cpp +++ b/dGame/dComponents/SimplePhysicsComponent.cpp @@ -13,11 +13,12 @@ #include "Entity.h" -SimplePhysicsComponent::SimplePhysicsComponent(Entity* parent, uint32_t componentID) : PhysicsComponent(parent) { - m_Position = m_Parent->GetDefaultPosition(); - m_Rotation = m_Parent->GetDefaultRotation(); +SimplePhysicsComponent::SimplePhysicsComponent(const LWOOBJID& parentEntityId, const uint32_t componentID) : PhysicsComponent{ parentEntityId } { + CheckComponentAssertions(); // Check static assertions - const auto& climbable_type = m_Parent->GetVar(u"climbable"); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + + const auto& climbable_type = parentEntity->GetVar(u"climbable"); if (climbable_type == u"wall") { SetClimbableType(eClimbableType::CLIMBABLE_TYPE_WALL); } else if (climbable_type == u"ladder") { @@ -29,9 +30,6 @@ SimplePhysicsComponent::SimplePhysicsComponent(Entity* parent, uint32_t componen } } -SimplePhysicsComponent::~SimplePhysicsComponent() { -} - void SimplePhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { if (bIsInitialUpdate) { outBitStream->Write(m_ClimbableType != eClimbableType::CLIMBABLE_TYPE_NOT); diff --git a/dGame/dComponents/SimplePhysicsComponent.h b/dGame/dComponents/SimplePhysicsComponent.h index 752fef0ba..3a3b2f3d8 100644 --- a/dGame/dComponents/SimplePhysicsComponent.h +++ b/dGame/dComponents/SimplePhysicsComponent.h @@ -28,10 +28,9 @@ enum class eClimbableType : int32_t { */ class SimplePhysicsComponent : public PhysicsComponent { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::SIMPLE_PHYSICS; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::SIMPLE_PHYSICS; - SimplePhysicsComponent(Entity* parent, uint32_t componentID); - ~SimplePhysicsComponent() override; + SimplePhysicsComponent(const LWOOBJID& parentEntityId, const uint32_t componentID); void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; @@ -87,12 +86,12 @@ class SimplePhysicsComponent : public PhysicsComponent { /** * The current velocity of the entity */ - NiPoint3 m_Velocity = NiPoint3::ZERO; + NiPoint3 m_Velocity = NiPoint3Constant::ZERO; /** * The current angular velocity of the entity */ - NiPoint3 m_AngularVelocity = NiPoint3::ZERO; + NiPoint3 m_AngularVelocity = NiPoint3Constant::ZERO; /** * Whether or not the velocity has changed diff --git a/dGame/dComponents/SkillComponent.cpp b/dGame/dComponents/SkillComponent.cpp index b65c7d216..c6f565dff 100644 --- a/dGame/dComponents/SkillComponent.cpp +++ b/dGame/dComponents/SkillComponent.cpp @@ -32,9 +32,9 @@ ProjectileSyncEntry::ProjectileSyncEntry() { std::unordered_map SkillComponent::m_skillBehaviorCache = {}; bool SkillComponent::CastPlayerSkill(const uint32_t behaviorId, const uint32_t skillUid, RakNet::BitStream* bitStream, const LWOOBJID target, uint32_t skillID) { - auto* context = new BehaviorContext(this->m_Parent->GetObjectID()); + auto* context = new BehaviorContext(m_Parent); - context->caster = m_Parent->GetObjectID(); + context->caster = m_Parent; context->skillID = skillID; @@ -130,11 +130,13 @@ void SkillComponent::RegisterPlayerProjectile(const LWOOBJID projectileId, Behav } void SkillComponent::Update(const float deltaTime) { - if (!m_Parent->HasComponent(eReplicaComponentType::BASE_COMBAT_AI) && m_Parent->GetLOT() != 1) { + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + + if (!parentEntity->HasComponent(eReplicaComponentType::BASE_COMBAT_AI) && Game::entityManager->GetEntity(m_Parent)->GetLOT() != 1) { CalculateUpdate(deltaTime); } - if (m_Parent->IsPlayer()) { + if (parentEntity->IsPlayer()) { for (const auto& pair : this->m_managedBehaviors) pair.second->UpdatePlayerSyncs(deltaTime); } @@ -142,10 +144,7 @@ void SkillComponent::Update(const float deltaTime) { for (const auto& pair : this->m_managedBehaviors) { auto* context = pair.second; - - if (context == nullptr) { - continue; - } + if (!context) continue; if (context->clientInitalized) { context->CalculateUpdate(deltaTime); @@ -193,18 +192,18 @@ void SkillComponent::Reset() { void SkillComponent::Interrupt() { // TODO: need to check immunities on the destroyable component, but they aren't implemented - auto* combat = m_Parent->GetComponent(); - if (combat != nullptr && combat->GetStunImmune()) return; + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + auto* const combat = parentEntity->GetComponent(); + if (combat && combat->GetStunImmune()) return; for (const auto& behavior : this->m_managedBehaviors) { for (const auto& behaviorEndEntry : behavior.second->endEntries) { behaviorEndEntry.behavior->End(behavior.second, behaviorEndEntry.branchContext, behaviorEndEntry.second); } behavior.second->endEntries.clear(); - if (m_Parent->IsPlayer()) continue; + if (parentEntity->IsPlayer()) continue; behavior.second->Interrupt(); } - } void SkillComponent::RegisterCalculatedProjectile(const LWOOBJID projectileId, BehaviorContext* context, const BehaviorBranchContext& branch, const LOT lot, const float maxTime, @@ -256,9 +255,9 @@ SkillExecutionResult SkillComponent::CalculateBehavior(const uint32_t skillId, c auto* behavior = Behavior::CreateBehavior(behaviorId); - auto* context = new BehaviorContext(originatorOverride != LWOOBJID_EMPTY ? originatorOverride : this->m_Parent->GetObjectID(), true); + auto* context = new BehaviorContext(originatorOverride != LWOOBJID_EMPTY ? originatorOverride : m_Parent, true); - context->caster = m_Parent->GetObjectID(); + context->caster = m_Parent; context->skillID = skillId; @@ -268,8 +267,9 @@ SkillExecutionResult SkillComponent::CalculateBehavior(const uint32_t skillId, c behavior->Calculate(context, bitStream, { target, 0 }); - for (auto* script : CppScripts::GetEntityScripts(m_Parent)) { - script->OnSkillCast(m_Parent, skillId); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + for (auto* script : CppScripts::GetEntityScripts(parentEntity)) { + script->OnSkillCast(parentEntity, skillId); } if (!context->foundTarget) { @@ -305,7 +305,7 @@ SkillExecutionResult SkillComponent::CalculateBehavior(const uint32_t skillId, c RakNet::BitStream message; BitStreamUtils::WriteHeader(message, eConnectionType::CLIENT, eClientMessageType::GAME_MSG); - message.Write(this->m_Parent->GetObjectID()); + message.Write(m_Parent); start.Serialize(&message); Game::server->Send(&message, UNASSIGNED_SYSTEM_ADDRESS, true); @@ -431,14 +431,14 @@ void SkillComponent::SyncProjectileCalculation(const ProjectileSyncEntry& entry) DoClientProjectileImpact projectileImpact; projectileImpact.sBitStream.assign(reinterpret_cast(bitStream->GetData()), bitStream->GetNumberOfBytesUsed()); - projectileImpact.i64OwnerID = this->m_Parent->GetObjectID(); + projectileImpact.i64OwnerID = m_Parent; projectileImpact.i64OrgID = entry.id; projectileImpact.i64TargetID = entry.branchContext.target; RakNet::BitStream message; BitStreamUtils::WriteHeader(message, eConnectionType::CLIENT, eClientMessageType::GAME_MSG); - message.Write(this->m_Parent->GetObjectID()); + message.Write(m_Parent); projectileImpact.Serialize(&message); Game::server->Send(&message, UNASSIGNED_SYSTEM_ADDRESS, true); @@ -477,7 +477,7 @@ void SkillComponent::HandleUnCast(const uint32_t behaviorId, const LWOOBJID targ delete context; } -SkillComponent::SkillComponent(Entity* parent): Component(parent) { +SkillComponent::SkillComponent(const LWOOBJID& parentEntityId) : Component{ parentEntityId } { this->m_skillUid = 0; } diff --git a/dGame/dComponents/SkillComponent.h b/dGame/dComponents/SkillComponent.h index 2d8628ef4..2ec5541d9 100644 --- a/dGame/dComponents/SkillComponent.h +++ b/dGame/dComponents/SkillComponent.h @@ -59,9 +59,9 @@ struct SkillExecutionResult { */ class SkillComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::SKILL; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::SKILL; - explicit SkillComponent(Entity* parent); + explicit SkillComponent(const LWOOBJID& parentEntityId); ~SkillComponent() override; void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; diff --git a/dGame/dComponents/SoundTriggerComponent.cpp b/dGame/dComponents/SoundTriggerComponent.cpp index 34d2441ca..934b05a88 100644 --- a/dGame/dComponents/SoundTriggerComponent.cpp +++ b/dGame/dComponents/SoundTriggerComponent.cpp @@ -25,33 +25,34 @@ void MixerProgram::Serialize(RakNet::BitStream* outBitStream){ outBitStream->Write(name.c_str(), name.size()); outBitStream->Write(result); } -SoundTriggerComponent::SoundTriggerComponent(Entity* parent) : Component(parent) { +SoundTriggerComponent::SoundTriggerComponent(const LWOOBJID& parentEntityId) : Component{ parentEntityId } { + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); - const auto musicCueName = parent->GetVar(u"NDAudioMusicCue_Name"); + const auto musicCueName = parentEntity->GetVar(u"NDAudioMusicCue_Name"); if (!musicCueName.empty()) { auto newCue = MusicCue(musicCueName); - const auto musicCueBoredomTime = parent->GetVar(u"NDAudioMusicCue_BoredomTime"); + const auto musicCueBoredomTime = parentEntity->GetVar(u"NDAudioMusicCue_BoredomTime"); if (musicCueBoredomTime) newCue.boredomTime = musicCueBoredomTime; this->m_MusicCues.push_back(newCue); } - const auto musicParameterName = parent->GetVar(u"NDAudioMusicParameter_Name"); + const auto musicParameterName = parentEntity->GetVar(u"NDAudioMusicParameter_Name"); if (!musicParameterName.empty()) { auto newParams = MusicParameter(musicParameterName); - const auto musicParameterValue = parent->GetVar(u"NDAudioMusicParameter_Value"); + const auto musicParameterValue = parentEntity->GetVar(u"NDAudioMusicParameter_Value"); if (musicParameterValue) newParams.value = musicParameterValue; this->m_MusicParameters.push_back(newParams); } - const auto guidString = parent->GetVar(u"NDAudioEventGUID"); + const auto guidString = parentEntity->GetVar(u"NDAudioEventGUID"); if (!guidString.empty()) this->m_2DAmbientSounds.push_back(GUIDResults(guidString)); - const auto guid2String = parent->GetVar(u"NDAudioEventGUID2"); + const auto guid2String = parentEntity->GetVar(u"NDAudioEventGUID2"); if (!guid2String.empty()) this->m_3DAmbientSounds.push_back(GUIDResults(guid2String)); - const auto mixerName = parent->GetVar(u"NDAudioMixerProgram_Name"); + const auto mixerName = parentEntity->GetVar(u"NDAudioMixerProgram_Name"); if (!mixerName.empty()) this->m_MixerPrograms.push_back(MixerProgram(mixerName)); } diff --git a/dGame/dComponents/SoundTriggerComponent.h b/dGame/dComponents/SoundTriggerComponent.h index 56c71770b..1d7851196 100644 --- a/dGame/dComponents/SoundTriggerComponent.h +++ b/dGame/dComponents/SoundTriggerComponent.h @@ -58,8 +58,8 @@ struct MixerProgram{ class SoundTriggerComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::SOUND_TRIGGER; - explicit SoundTriggerComponent(Entity* parent); + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::SOUND_TRIGGER; + explicit SoundTriggerComponent(const LWOOBJID& parentEntityId); void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; void ActivateMusicCue(const std::string& name, float bordemTime = -1.0); void DeactivateMusicCue(const std::string& name); diff --git a/dGame/dComponents/SwitchComponent.cpp b/dGame/dComponents/SwitchComponent.cpp index 25f18a4df..757fe045a 100644 --- a/dGame/dComponents/SwitchComponent.cpp +++ b/dGame/dComponents/SwitchComponent.cpp @@ -5,12 +5,14 @@ std::vector SwitchComponent::petSwitches; -SwitchComponent::SwitchComponent(Entity* parent) : Component(parent) { +SwitchComponent::SwitchComponent(const LWOOBJID& parentEntityId) : Component{ parentEntityId } { m_Active = false; - m_ResetTime = m_Parent->GetVarAs(u"switch_reset_time"); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); - m_QuickBuild = m_Parent->GetComponent(); + m_ResetTime = parentEntity->GetVarAs(u"switch_reset_time"); + + m_QuickBuild = parentEntity->GetComponent(); } SwitchComponent::~SwitchComponent() { @@ -43,10 +45,12 @@ void SwitchComponent::EntityEnter(Entity* entity) { if (m_QuickBuild->GetState() != eQuickBuildState::COMPLETED) return; } m_Active = true; - if (!m_Parent) return; - m_Parent->TriggerEvent(eTriggerEventType::ACTIVATED, entity); - const auto grpName = m_Parent->GetVarAsString(u"grp_name"); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + + parentEntity->TriggerEvent(eTriggerEventType::ACTIVATED, entity); + + const auto grpName = parentEntity->GetVarAsString(u"grp_name"); if (!grpName.empty()) { const auto entities = Game::entityManager->GetEntitiesInGroup(grpName); @@ -59,8 +63,8 @@ void SwitchComponent::EntityEnter(Entity* entity) { m_Timer = m_ResetTime; if (m_PetBouncer != nullptr) { - GameMessages::SendPlayFXEffect(m_Parent->GetObjectID(), 2602, u"pettriggeractive", "BounceEffect", LWOOBJID_EMPTY, 1, 1, true); - RenderComponent::PlayAnimation(m_Parent, u"engaged"); + GameMessages::SendPlayFXEffect(m_Parent, 2602, u"pettriggeractive", "BounceEffect", LWOOBJID_EMPTY, 1, 1, true); + RenderComponent::PlayAnimation(parentEntity, u"engaged"); m_PetBouncer->SetPetBouncerEnabled(true); } else { Game::entityManager->SerializeEntity(m_Parent); @@ -79,10 +83,12 @@ void SwitchComponent::Update(float deltaTime) { if (m_Timer <= 0.0f) { m_Active = false; - if (!m_Parent) return; - m_Parent->TriggerEvent(eTriggerEventType::DEACTIVATED, m_Parent); - const auto grpName = m_Parent->GetVarAsString(u"grp_name"); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + + parentEntity->TriggerEvent(eTriggerEventType::DEACTIVATED, Game::entityManager->GetEntity(m_Parent)); + + const auto grpName = parentEntity->GetVarAsString(u"grp_name"); if (!grpName.empty()) { const auto entities = Game::entityManager->GetEntitiesInGroup(grpName); @@ -92,7 +98,7 @@ void SwitchComponent::Update(float deltaTime) { } } - if (m_PetBouncer != nullptr) { + if (m_PetBouncer) { m_PetBouncer->SetPetBouncerEnabled(false); } else { Game::entityManager->SerializeEntity(m_Parent); @@ -102,7 +108,7 @@ void SwitchComponent::Update(float deltaTime) { } Entity* SwitchComponent::GetParentEntity() const { - return m_Parent; + return Game::entityManager->GetEntity(m_Parent); } SwitchComponent* SwitchComponent::GetClosestSwitch(NiPoint3 position) { @@ -110,9 +116,9 @@ SwitchComponent* SwitchComponent::GetClosestSwitch(NiPoint3 position) { SwitchComponent* closest = nullptr; for (SwitchComponent* petSwitch : petSwitches) { - float distance = Vector3::DistanceSquared(petSwitch->m_Parent->GetPosition(), position); + float distance = Vector3::DistanceSquared(petSwitch->GetParent()->GetPosition(), position); - if (closest == nullptr || distance < closestDistance) { + if (!closest || distance < closestDistance) { closestDistance = distance; closest = petSwitch; } @@ -125,7 +131,7 @@ SwitchComponent* SwitchComponent::GetClosestSwitch(NiPoint3 position) { void SwitchComponent::SetPetBouncer(BouncerComponent* value) { m_PetBouncer = value; - if (value != nullptr) { + if (value) { m_PetBouncer->SetPetEnabled(true); petSwitches.push_back(this); } diff --git a/dGame/dComponents/SwitchComponent.h b/dGame/dComponents/SwitchComponent.h index 7f2c34987..b2b0012b6 100644 --- a/dGame/dComponents/SwitchComponent.h +++ b/dGame/dComponents/SwitchComponent.h @@ -16,9 +16,9 @@ */ class SwitchComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::SWITCH; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::SWITCH; - SwitchComponent(Entity* parent); + SwitchComponent(const LWOOBJID& parentEntityId); ~SwitchComponent() override; void Update(float deltaTime) override; diff --git a/dGame/dComponents/TriggerComponent.cpp b/dGame/dComponents/TriggerComponent.cpp index 6d7ce3dd2..0be4738a0 100644 --- a/dGame/dComponents/TriggerComponent.cpp +++ b/dGame/dComponents/TriggerComponent.cpp @@ -16,8 +16,7 @@ #include "PlayerManager.h" -TriggerComponent::TriggerComponent(Entity* parent, const std::string triggerInfo): Component(parent) { - m_Parent = parent; +TriggerComponent::TriggerComponent(const LWOOBJID& parentEntityId, const std::string triggerInfo) : Component{ parentEntityId } { m_Trigger = nullptr; std::vector tokens = GeneralUtils::SplitString(triggerInfo, ':'); @@ -45,7 +44,7 @@ void TriggerComponent::TriggerEvent(eTriggerEventType event, Entity* optionalTar } void TriggerComponent::HandleTriggerCommand(LUTriggers::Command* command, Entity* optionalTarget) { - auto argArray = GeneralUtils::SplitString(command->args, ','); + auto argArray = GeneralUtils::SplitString(command->args, ','); // determine targets std::vector targetEntities = GatherTargets(command, optionalTarget); @@ -57,107 +56,107 @@ void TriggerComponent::HandleTriggerCommand(LUTriggers::Command* command, Entity if (!targetEntity) continue; switch (command->id) { - case eTriggerCommandType::ZONE_PLAYER: break; - case eTriggerCommandType::FIRE_EVENT: - HandleFireEvent(targetEntity, command->args); - break; - case eTriggerCommandType::DESTROY_OBJ: - HandleDestroyObject(targetEntity, command->args); - break; - case eTriggerCommandType::TOGGLE_TRIGGER: - HandleToggleTrigger(targetEntity, command->args); - break; - case eTriggerCommandType::RESET_REBUILD: - HandleResetRebuild(targetEntity, command->args); - break; - case eTriggerCommandType::SET_PATH: break; - case eTriggerCommandType::SET_PICK_TYPE: break; - case eTriggerCommandType::MOVE_OBJECT: - HandleMoveObject(targetEntity, argArray); - break; - case eTriggerCommandType::ROTATE_OBJECT: - HandleRotateObject(targetEntity, argArray); - break; - case eTriggerCommandType::PUSH_OBJECT: - HandlePushObject(targetEntity, argArray); - break; - case eTriggerCommandType::REPEL_OBJECT: - HandleRepelObject(targetEntity, command->args); - break; - case eTriggerCommandType::SET_TIMER: - HandleSetTimer(targetEntity, argArray); - break; - case eTriggerCommandType::CANCEL_TIMER: - HandleCancelTimer(targetEntity, command->args); - break; - case eTriggerCommandType::PLAY_CINEMATIC: - HandlePlayCinematic(targetEntity, argArray); - break; - case eTriggerCommandType::TOGGLE_BBB: - HandleToggleBBB(targetEntity, command->args); - break; - case eTriggerCommandType::UPDATE_MISSION: - HandleUpdateMission(targetEntity, argArray); - break; - case eTriggerCommandType::SET_BOUNCER_STATE: break; - case eTriggerCommandType::BOUNCE_ALL_ON_BOUNCER: break; - case eTriggerCommandType::TURN_AROUND_ON_PATH: break; - case eTriggerCommandType::GO_FORWARD_ON_PATH: break; - case eTriggerCommandType::GO_BACKWARD_ON_PATH: break; - case eTriggerCommandType::STOP_PATHING: break; - case eTriggerCommandType::START_PATHING: break; - case eTriggerCommandType::LOCK_OR_UNLOCK_CONTROLS: break; - case eTriggerCommandType::PLAY_EFFECT: - HandlePlayEffect(targetEntity, argArray); - break; - case eTriggerCommandType::STOP_EFFECT: - GameMessages::SendStopFXEffect(targetEntity, true, command->args); - break; - case eTriggerCommandType::CAST_SKILL: - HandleCastSkill(targetEntity, command->args); - break; - case eTriggerCommandType::DISPLAY_ZONE_SUMMARY: - GameMessages::SendDisplayZoneSummary(targetEntity->GetObjectID(), targetEntity->GetSystemAddress(), false, command->args == "1", m_Parent->GetObjectID()); - break; - case eTriggerCommandType::SET_PHYSICS_VOLUME_EFFECT: - HandleSetPhysicsVolumeEffect(targetEntity, argArray); - break; - case eTriggerCommandType::SET_PHYSICS_VOLUME_STATUS: - HandleSetPhysicsVolumeStatus(targetEntity, command->args); - break; - case eTriggerCommandType::SET_MODEL_TO_BUILD: break; - case eTriggerCommandType::SPAWN_MODEL_BRICKS: break; - case eTriggerCommandType::ACTIVATE_SPAWNER_NETWORK: - HandleActivateSpawnerNetwork(command->args); - break; - case eTriggerCommandType::DEACTIVATE_SPAWNER_NETWORK: - HandleDeactivateSpawnerNetwork(command->args); - break; - case eTriggerCommandType::RESET_SPAWNER_NETWORK: - HandleResetSpawnerNetwork(command->args); - break; - case eTriggerCommandType::DESTROY_SPAWNER_NETWORK_OBJECTS: - HandleDestroySpawnerNetworkObjects(command->args); - break; - case eTriggerCommandType::GO_TO_WAYPOINT: break; - case eTriggerCommandType::ACTIVATE_PHYSICS: - HandleActivatePhysics(targetEntity, command->args); - break; + case eTriggerCommandType::ZONE_PLAYER: break; + case eTriggerCommandType::FIRE_EVENT: + HandleFireEvent(targetEntity, command->args); + break; + case eTriggerCommandType::DESTROY_OBJ: + HandleDestroyObject(targetEntity, command->args); + break; + case eTriggerCommandType::TOGGLE_TRIGGER: + HandleToggleTrigger(targetEntity, command->args); + break; + case eTriggerCommandType::RESET_REBUILD: + HandleResetRebuild(targetEntity, command->args); + break; + case eTriggerCommandType::SET_PATH: break; + case eTriggerCommandType::SET_PICK_TYPE: break; + case eTriggerCommandType::MOVE_OBJECT: + HandleMoveObject(targetEntity, argArray); + break; + case eTriggerCommandType::ROTATE_OBJECT: + HandleRotateObject(targetEntity, argArray); + break; + case eTriggerCommandType::PUSH_OBJECT: + HandlePushObject(targetEntity, argArray); + break; + case eTriggerCommandType::REPEL_OBJECT: + HandleRepelObject(targetEntity, command->args); + break; + case eTriggerCommandType::SET_TIMER: + HandleSetTimer(targetEntity, argArray); + break; + case eTriggerCommandType::CANCEL_TIMER: + HandleCancelTimer(targetEntity, command->args); + break; + case eTriggerCommandType::PLAY_CINEMATIC: + HandlePlayCinematic(targetEntity, argArray); + break; + case eTriggerCommandType::TOGGLE_BBB: + HandleToggleBBB(targetEntity, command->args); + break; + case eTriggerCommandType::UPDATE_MISSION: + HandleUpdateMission(targetEntity, argArray); + break; + case eTriggerCommandType::SET_BOUNCER_STATE: break; + case eTriggerCommandType::BOUNCE_ALL_ON_BOUNCER: break; + case eTriggerCommandType::TURN_AROUND_ON_PATH: break; + case eTriggerCommandType::GO_FORWARD_ON_PATH: break; + case eTriggerCommandType::GO_BACKWARD_ON_PATH: break; + case eTriggerCommandType::STOP_PATHING: break; + case eTriggerCommandType::START_PATHING: break; + case eTriggerCommandType::LOCK_OR_UNLOCK_CONTROLS: break; + case eTriggerCommandType::PLAY_EFFECT: + HandlePlayEffect(targetEntity, argArray); + break; + case eTriggerCommandType::STOP_EFFECT: + GameMessages::SendStopFXEffect(targetEntity, true, command->args); + break; + case eTriggerCommandType::CAST_SKILL: + HandleCastSkill(targetEntity, command->args); + break; + case eTriggerCommandType::DISPLAY_ZONE_SUMMARY: + GameMessages::SendDisplayZoneSummary(targetEntity->GetObjectID(), targetEntity->GetSystemAddress(), false, command->args == "1", m_Parent); + break; + case eTriggerCommandType::SET_PHYSICS_VOLUME_EFFECT: + HandleSetPhysicsVolumeEffect(targetEntity, argArray); + break; + case eTriggerCommandType::SET_PHYSICS_VOLUME_STATUS: + HandleSetPhysicsVolumeStatus(targetEntity, command->args); + break; + case eTriggerCommandType::SET_MODEL_TO_BUILD: break; + case eTriggerCommandType::SPAWN_MODEL_BRICKS: break; + case eTriggerCommandType::ACTIVATE_SPAWNER_NETWORK: + HandleActivateSpawnerNetwork(command->args); + break; + case eTriggerCommandType::DEACTIVATE_SPAWNER_NETWORK: + HandleDeactivateSpawnerNetwork(command->args); + break; + case eTriggerCommandType::RESET_SPAWNER_NETWORK: + HandleResetSpawnerNetwork(command->args); + break; + case eTriggerCommandType::DESTROY_SPAWNER_NETWORK_OBJECTS: + HandleDestroySpawnerNetworkObjects(command->args); + break; + case eTriggerCommandType::GO_TO_WAYPOINT: break; + case eTriggerCommandType::ACTIVATE_PHYSICS: + HandleActivatePhysics(targetEntity, command->args); + break; // DEPRECATED BLOCK START - case eTriggerCommandType::ACTIVATE_MUSIC_CUE: break; - case eTriggerCommandType::DEACTIVATE_MUSIC_CUE: break; - case eTriggerCommandType::FLASH_MUSIC_CUE: break; - case eTriggerCommandType::SET_MUSIC_PARAMETER: break; - case eTriggerCommandType::PLAY_2D_AMBIENT_SOUND: break; - case eTriggerCommandType::STOP_2D_AMBIENT_SOUND: break; - case eTriggerCommandType::PLAY_3D_AMBIENT_SOUND: break; - case eTriggerCommandType::STOP_3D_AMBIENT_SOUND: break; - case eTriggerCommandType::ACTIVATE_MIXER_PROGRAM: break; - case eTriggerCommandType::DEACTIVATE_MIXER_PROGRAM: break; + case eTriggerCommandType::ACTIVATE_MUSIC_CUE: break; + case eTriggerCommandType::DEACTIVATE_MUSIC_CUE: break; + case eTriggerCommandType::FLASH_MUSIC_CUE: break; + case eTriggerCommandType::SET_MUSIC_PARAMETER: break; + case eTriggerCommandType::PLAY_2D_AMBIENT_SOUND: break; + case eTriggerCommandType::STOP_2D_AMBIENT_SOUND: break; + case eTriggerCommandType::PLAY_3D_AMBIENT_SOUND: break; + case eTriggerCommandType::STOP_3D_AMBIENT_SOUND: break; + case eTriggerCommandType::ACTIVATE_MIXER_PROGRAM: break; + case eTriggerCommandType::DEACTIVATE_MIXER_PROGRAM: break; // DEPRECATED BLOCK END - default: - LOG_DEBUG("Event %i was not handled!", command->id); - break; + default: + LOG_DEBUG("Event %i was not handled!", command->id); + break; } } } @@ -165,9 +164,8 @@ void TriggerComponent::HandleTriggerCommand(LUTriggers::Command* command, Entity std::vector TriggerComponent::GatherTargets(LUTriggers::Command* command, Entity* optionalTarget) { std::vector entities = {}; - if (command->target == "self") entities.push_back(m_Parent); - else if (command->target == "zone") { /*TODO*/ } - else if (command->target == "target" && optionalTarget) entities.push_back(optionalTarget); + if (command->target == "self") entities.push_back(Game::entityManager->GetEntity(m_Parent)); + else if (command->target == "zone") { /*TODO*/ } else if (command->target == "target" && optionalTarget) entities.push_back(optionalTarget); else if (command->target == "targetTeam" && optionalTarget) { auto* team = TeamManager::Instance()->GetTeam(optionalTarget->GetObjectID()); for (const auto memberId : team->members) { @@ -186,17 +184,17 @@ std::vector TriggerComponent::GatherTargets(LUTriggers::Command* comman void TriggerComponent::HandleFireEvent(Entity* targetEntity, std::string args) { for (CppScripts::Script* script : CppScripts::GetEntityScripts(targetEntity)) { - script->OnFireEventServerSide(targetEntity, m_Parent, args, 0, 0, 0); + script->OnFireEventServerSide(targetEntity, Game::entityManager->GetEntity(m_Parent), args, 0, 0, 0); } } -void TriggerComponent::HandleDestroyObject(Entity* targetEntity, std::string args){ +void TriggerComponent::HandleDestroyObject(Entity* targetEntity, std::string args) { uint32_t killType; GeneralUtils::TryParse(args, killType); - targetEntity->Smash(m_Parent->GetObjectID(), static_cast(killType)); + targetEntity->Smash(m_Parent, static_cast(killType)); } -void TriggerComponent::HandleToggleTrigger(Entity* targetEntity, std::string args){ +void TriggerComponent::HandleToggleTrigger(Entity* targetEntity, std::string args) { auto* triggerComponent = targetEntity->GetComponent(); if (!triggerComponent) { LOG_DEBUG("Trigger component not found!"); @@ -205,7 +203,7 @@ void TriggerComponent::HandleToggleTrigger(Entity* targetEntity, std::string arg triggerComponent->SetTriggerEnabled(args == "1"); } -void TriggerComponent::HandleResetRebuild(Entity* targetEntity, std::string args){ +void TriggerComponent::HandleResetRebuild(Entity* targetEntity, std::string args) { auto* quickBuildComponent = targetEntity->GetComponent(); if (!quickBuildComponent) { LOG_DEBUG("Rebuild component not found!"); @@ -214,31 +212,31 @@ void TriggerComponent::HandleResetRebuild(Entity* targetEntity, std::string args quickBuildComponent->ResetQuickBuild(args == "1"); } -void TriggerComponent::HandleMoveObject(Entity* targetEntity, std::vector argArray){ +void TriggerComponent::HandleMoveObject(Entity* targetEntity, std::vector argArray) { if (argArray.size() <= 2) return; auto position = targetEntity->GetPosition(); - NiPoint3 offset = NiPoint3::ZERO; + NiPoint3 offset = NiPoint3Constant::ZERO; GeneralUtils::TryParse(argArray.at(0), argArray.at(1), argArray.at(2), offset); position += offset; targetEntity->SetPosition(position); } -void TriggerComponent::HandleRotateObject(Entity* targetEntity, std::vector argArray){ +void TriggerComponent::HandleRotateObject(Entity* targetEntity, std::vector argArray) { if (argArray.size() <= 2) return; - NiPoint3 vector = NiPoint3::ZERO; + NiPoint3 vector = NiPoint3Constant::ZERO; GeneralUtils::TryParse(argArray.at(0), argArray.at(1), argArray.at(2), vector); NiQuaternion rotation = NiQuaternion::FromEulerAngles(vector); targetEntity->SetRotation(rotation); } -void TriggerComponent::HandlePushObject(Entity* targetEntity, std::vector argArray){ +void TriggerComponent::HandlePushObject(Entity* targetEntity, std::vector argArray) { if (argArray.size() < 3) return; - auto* phantomPhysicsComponent = m_Parent->GetComponent(); + auto* phantomPhysicsComponent = Game::entityManager->GetEntity(m_Parent)->GetComponent(); if (!phantomPhysicsComponent) { LOG_DEBUG("Phantom Physics component not found!"); return; @@ -246,7 +244,7 @@ void TriggerComponent::HandlePushObject(Entity* targetEntity, std::vectorSetPhysicsEffectActive(true); phantomPhysicsComponent->SetEffectType(ePhysicsEffectType::PUSH); phantomPhysicsComponent->SetDirectionalMultiplier(1); - NiPoint3 direction = NiPoint3::ZERO; + NiPoint3 direction = NiPoint3Constant::ZERO; GeneralUtils::TryParse(argArray.at(0), argArray.at(1), argArray.at(2), direction); phantomPhysicsComponent->SetDirection(direction); @@ -254,8 +252,10 @@ void TriggerComponent::HandlePushObject(Entity* targetEntity, std::vectorGetComponent(); +void TriggerComponent::HandleRepelObject(Entity* targetEntity, std::string args) { + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + + auto* const phantomPhysicsComponent = Game::entityManager->GetEntity(m_Parent)->GetComponent(); if (!phantomPhysicsComponent) { LOG_DEBUG("Phantom Physics component not found!"); return; @@ -266,7 +266,7 @@ void TriggerComponent::HandleRepelObject(Entity* targetEntity, std::string args) phantomPhysicsComponent->SetEffectType(ePhysicsEffectType::REPULSE); phantomPhysicsComponent->SetDirectionalMultiplier(forceMultiplier); - auto triggerPos = m_Parent->GetPosition(); + auto triggerPos = parentEntity->GetPosition(); auto targetPos = targetEntity->GetPosition(); // normalize the vectors to get the direction @@ -278,18 +278,18 @@ void TriggerComponent::HandleRepelObject(Entity* targetEntity, std::string args) Game::entityManager->SerializeEntity(m_Parent); } -void TriggerComponent::HandleSetTimer(Entity* targetEntity, std::vector argArray){ +void TriggerComponent::HandleSetTimer(Entity* targetEntity, std::vector argArray) { if (argArray.size() != 2) { LOG_DEBUG("Not ehought variables!"); return; } float time = 0.0; GeneralUtils::TryParse(argArray.at(1), time); - m_Parent->AddTimer(argArray.at(0), time); + Game::entityManager->GetEntity(m_Parent)->AddTimer(argArray.at(0), time); } -void TriggerComponent::HandleCancelTimer(Entity* targetEntity, std::string args){ - m_Parent->CancelTimer(args); +void TriggerComponent::HandleCancelTimer(Entity* targetEntity, std::string args) { + Game::entityManager->GetEntity(m_Parent)->CancelTimer(args); } void TriggerComponent::HandlePlayCinematic(Entity* targetEntity, std::vector argArray) { @@ -336,7 +336,7 @@ void TriggerComponent::HandleUpdateMission(Entity* targetEntity, std::vectorGetComponent(); - if (!missionComponent){ + if (!missionComponent) { LOG_DEBUG("Mission component not found!"); return; } @@ -353,7 +353,7 @@ void TriggerComponent::HandlePlayEffect(Entity* targetEntity, std::vectorGetComponent(); if (!skillComponent) { LOG_DEBUG("Skill component not found!"); @@ -382,7 +382,7 @@ void TriggerComponent::HandleSetPhysicsVolumeEffect(Entity* targetEntity, std::v phantomPhysicsComponent->SetEffectType(effectType); phantomPhysicsComponent->SetDirectionalMultiplier(std::stof(argArray.at(1))); if (argArray.size() > 4) { - NiPoint3 direction = NiPoint3::ZERO; + NiPoint3 direction = NiPoint3Constant::ZERO; GeneralUtils::TryParse(argArray.at(2), argArray.at(3), argArray.at(4), direction); phantomPhysicsComponent->SetDirection(direction); } @@ -409,25 +409,25 @@ void TriggerComponent::HandleSetPhysicsVolumeStatus(Entity* targetEntity, std::s Game::entityManager->SerializeEntity(targetEntity); } -void TriggerComponent::HandleActivateSpawnerNetwork(std::string args){ +void TriggerComponent::HandleActivateSpawnerNetwork(std::string args) { for (auto* spawner : Game::zoneManager->GetSpawnersByName(args)) { if (spawner) spawner->Activate(); } } -void TriggerComponent::HandleDeactivateSpawnerNetwork(std::string args){ +void TriggerComponent::HandleDeactivateSpawnerNetwork(std::string args) { for (auto* spawner : Game::zoneManager->GetSpawnersByName(args)) { if (spawner) spawner->Deactivate(); } } -void TriggerComponent::HandleResetSpawnerNetwork(std::string args){ +void TriggerComponent::HandleResetSpawnerNetwork(std::string args) { for (auto* spawner : Game::zoneManager->GetSpawnersByName(args)) { if (spawner) spawner->Reset(); } } -void TriggerComponent::HandleDestroySpawnerNetworkObjects(std::string args){ +void TriggerComponent::HandleDestroySpawnerNetworkObjects(std::string args) { for (auto* spawner : Game::zoneManager->GetSpawnersByName(args)) { if (spawner) spawner->DestroyAllEntities(); } @@ -436,7 +436,7 @@ void TriggerComponent::HandleDestroySpawnerNetworkObjects(std::string args){ void TriggerComponent::HandleActivatePhysics(Entity* targetEntity, std::string args) { if (args == "true") { // TODO add physics entity if there isn't one - } else if (args == "false"){ + } else if (args == "false") { // TODO remove Phsyics entity if there is one } else { LOG_DEBUG("Invalid argument for ActivatePhysics Trigger: %s", args.c_str()); diff --git a/dGame/dComponents/TriggerComponent.h b/dGame/dComponents/TriggerComponent.h index 90ecc52c7..607c6ea6e 100644 --- a/dGame/dComponents/TriggerComponent.h +++ b/dGame/dComponents/TriggerComponent.h @@ -7,9 +7,9 @@ class TriggerComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::TRIGGER; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::TRIGGER; - explicit TriggerComponent(Entity* parent, const std::string triggerInfo); + explicit TriggerComponent(const LWOOBJID& parentEntityId, const std::string triggerInfo); void TriggerEvent(eTriggerEventType event, Entity* optionalTarget = nullptr); LUTriggers::Trigger* GetTrigger() const { return m_Trigger; } diff --git a/dGame/dComponents/VendorComponent.cpp b/dGame/dComponents/VendorComponent.cpp index dfea33df7..c80791b27 100644 --- a/dGame/dComponents/VendorComponent.cpp +++ b/dGame/dComponents/VendorComponent.cpp @@ -9,7 +9,7 @@ #include "CDLootTableTable.h" #include "CDItemComponentTable.h" -VendorComponent::VendorComponent(Entity* parent) : Component(parent) { +VendorComponent::VendorComponent(const LWOOBJID& parentEntityId) : Component{ parentEntityId } { m_HasStandardCostItems = false; m_HasMultiCostItems = false; SetupConstants(); @@ -26,8 +26,10 @@ void VendorComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitial } void VendorComponent::OnUse(Entity* originator) { - GameMessages::SendVendorOpenWindow(m_Parent, originator->GetSystemAddress()); - GameMessages::SendVendorStatusUpdate(m_Parent, originator->GetSystemAddress()); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + + GameMessages::SendVendorOpenWindow(parentEntity, originator->GetSystemAddress()); + GameMessages::SendVendorStatusUpdate(parentEntity, originator->GetSystemAddress()); } void VendorComponent::RefreshInventory(bool isCreation) { @@ -35,8 +37,10 @@ void VendorComponent::RefreshInventory(bool isCreation) { SetHasMultiCostItems(false); m_Inventory.clear(); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + // Custom code for Max vanity NPC and Mr.Ree cameras - if(isCreation && m_Parent->GetLOT() == 9749 && Game::server->GetZoneID() == 1201) { + if (isCreation && parentEntity->GetLOT() == 9749 && Game::server->GetZoneID() == 1201) { SetupMaxCustomVendor(); return; } @@ -57,7 +61,7 @@ void VendorComponent::RefreshInventory(bool isCreation) { if (!m_HasStandardCostItems || !m_HasMultiCostItems) { auto itemComponentID = compRegistryTable->GetByIDAndType(item.itemid, eReplicaComponentType::ITEM, -1); if (itemComponentID == -1) { - LOG("Attempted to add item %i with ItemComponent ID -1 to vendor %i inventory. Not adding item!", itemComponentID, m_Parent->GetLOT()); + LOG("Attempted to add item %i with ItemComponent ID -1 to vendor %i inventory. Not adding item!", itemComponentID, Game::entityManager->GetEntity(m_Parent)->GetLOT()); continue; } auto itemComponent = itemComponentTable->GetItemComponentByID(itemComponentID); @@ -77,7 +81,7 @@ void VendorComponent::RefreshInventory(bool isCreation) { if (!m_HasStandardCostItems || !m_HasMultiCostItems) { auto itemComponentID = compRegistryTable->GetByIDAndType(randomItem.itemid, eReplicaComponentType::ITEM, -1); if (itemComponentID == -1) { - LOG("Attempted to add item %i with ItemComponent ID -1 to vendor %i inventory. Not adding item!", itemComponentID, m_Parent->GetLOT()); + LOG("Attempted to add item %i with ItemComponent ID -1 to vendor %i inventory. Not adding item!", itemComponentID, Game::entityManager->GetEntity(m_Parent)->GetLOT()); continue; } auto itemComponent = itemComponentTable->GetItemComponentByID(itemComponentID); @@ -92,17 +96,17 @@ void VendorComponent::RefreshInventory(bool isCreation) { // Callback timer to refresh this inventory. if (m_RefreshTimeSeconds > 0.0) { - m_Parent->AddCallbackTimer(m_RefreshTimeSeconds, [this]() { + parentEntity->AddCallbackTimer(m_RefreshTimeSeconds, [this]() { RefreshInventory(); - }); + }); } Game::entityManager->SerializeEntity(m_Parent); - GameMessages::SendVendorStatusUpdate(m_Parent, UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::SendVendorStatusUpdate(parentEntity, UNASSIGNED_SYSTEM_ADDRESS); } void VendorComponent::SetupConstants() { auto* compRegistryTable = CDClientManager::Instance().GetTable(); - int componentID = compRegistryTable->GetByIDAndType(m_Parent->GetLOT(), eReplicaComponentType::VENDOR); + int componentID = compRegistryTable->GetByIDAndType(Game::entityManager->GetEntity(m_Parent)->GetLOT(), eReplicaComponentType::VENDOR); auto* vendorComponentTable = CDClientManager::Instance().GetTable(); std::vector vendorComps = vendorComponentTable->Query([=](CDVendorComponent entry) { return (entry.id == componentID); }); @@ -122,7 +126,7 @@ bool VendorComponent::SellsItem(const LOT item) const { } -void VendorComponent::SetupMaxCustomVendor(){ +void VendorComponent::SetupMaxCustomVendor() { SetHasStandardCostItems(true); m_Inventory.push_back(SoldItem(11909, 0)); // Top hat w frog m_Inventory.push_back(SoldItem(7785, 0)); // Flash bulb @@ -130,8 +134,8 @@ void VendorComponent::SetupMaxCustomVendor(){ m_Inventory.push_back(SoldItem(12241, 0)); // Hot cocoa (from fb) } -void VendorComponent::HandleMrReeCameras(){ - if (m_Parent->GetLOT() == 13569) { +void VendorComponent::HandleMrReeCameras() { + if (Game::entityManager->GetEntity(m_Parent)->GetLOT() == 13569) { SetHasStandardCostItems(true); auto randomCamera = GeneralUtils::GenerateRandomNumber(0, 2); diff --git a/dGame/dComponents/VendorComponent.h b/dGame/dComponents/VendorComponent.h index 7924a9285..1abead295 100644 --- a/dGame/dComponents/VendorComponent.h +++ b/dGame/dComponents/VendorComponent.h @@ -20,8 +20,8 @@ struct SoldItem { class VendorComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::VENDOR; - VendorComponent(Entity* parent); + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::VENDOR; + VendorComponent(const LWOOBJID& parentEntityId); void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; diff --git a/dGame/dEntity/Archetype.h b/dGame/dEntity/Archetype.h new file mode 100644 index 000000000..57ad874fc --- /dev/null +++ b/dGame/dEntity/Archetype.h @@ -0,0 +1,166 @@ +#ifndef __ARCHETYPE_H__ +#define __ARCHETYPE_H__ + +#include +#include +#include +#include +#include + +#include "Component.h" + +// Require the template type to be of component base class +template +concept ComponentType = std::derived_from; + +// Forward declaration of archetype class +template +class Archetype; + +// Container struct for storing component data +template +struct Container { + using type = T; // Alias to allow retrieval of entry type + + using storage_type = std::vector; //Alias for the archetype component container type + //using storage_type = std::array; + + storage_type entries; +}; + +/** + * Base class to allow pointer/reference resolution + * Contains less-performant versions of methods to allow runtime resolution of component types +*/ +class ArchetypeBase { +public: + /** + * Create an alias type for the Archetype ID + */ + using ArchetypeId = size_t; + ArchetypeId id{ 0 }; + + /** + * Check if a component type is contained by the archetype + * @returns Boolean value representing whether the component type is present in the archetype + */ + template + [[nodiscard]] bool HasComponent() noexcept { + return dynamic_cast&>(*this).template HasComponent(); // TODO: Change this method! + } + + /** + * Get component container by way of indirect pointer/reference + * @returns A reference to the component container + */ + template + [[nodiscard]] Container::storage_type& GetContainer() { // TODO: Try to avoid using this! + return dynamic_cast&>(*this).template Container::entries; + } + + virtual ~ArchetypeBase() = default; + +protected: + ArchetypeBase() = default; + + constexpr explicit ArchetypeBase(ArchetypeId id) noexcept : id{ id } {}; +}; + +/** + * The archetype class stores a variable number of entity component types TODO: EXPAND ON +*/ +template +class Archetype final : public ArchetypeBase, public Container... { +public: + /** + * Alias that extracts the type of the Nth element passed as a template argument + */ + template + using type_index = std::tuple_element>::type; + + /** + * Constructor + */ + constexpr explicit Archetype(ArchetypeId id) noexcept : ArchetypeBase{ id } { + // Reserve 16 KB of memory for the sum of all vectors ahead of time + constexpr size_t compBytes = (sizeof(CTypes) + ...); + constexpr size_t reservedBytes = 16000; + constexpr size_t reserveNumEntries = reservedBytes / compBytes; + (Container::entries.reserve(reserveNumEntries), ...); + } + + /** + * Get the size of the archetype (by taking the size of the first member container) + * @returns The size of the archetype's containers + */ + [[nodiscard]] constexpr size_t size() noexcept { + Container>::entries.size(); + return Container>::entries.size(); + } + + /** + * Get if the container is empty (by only checking the first member container) + * @returns Boolean representing whether the container is empty + */ + [[nodiscard]] constexpr bool empty() noexcept { + return Container>::entries.empty(); + } + + /** + * Creates the archetype's components at the end of the container. + * @param componentArgs Arguments to be forwarded to the component constructors + */ + constexpr void CreateComponents(CTypes&&... componentArgs) noexcept { + (Container::entries.emplace_back(std::forward(componentArgs)), ...); + } + + /** + * Delete's the archetype's components at a specified container index, then moves the last element in the container to it. + * @param index The archetype container index to delete + */ + constexpr void DeleteComponents(const size_t index) { + if (empty()) return; // Do not delete if the container is already empty + + ((Container::entries.at(index) = std::move(Container::entries.back()), + Container::entries.pop_back()), ...); + } + + /** + * Gets a single archetype component at a specified container index. + * @param index The archetype container index to get + * @returns A reference to the component type specified as a template argument + */ + template + [[nodiscard]] CType& GetComponent(const size_t index) { + return Container::entries.at(index); + } + + /** + * Static function that returns if an archetype contains a specified component + * @returns Boolean representing component's presence + */ + template + [[nodiscard]] static constexpr bool HasComponent() noexcept { + return std::disjunction_v...>; + } + + /** + * Contains the number of component types an archetype consists of + */ + static constexpr size_t num_types = sizeof...(CTypes); + + template + struct contains : std::disjunction...> {}; + + template + using contains_v = contains::value; + +private: + //std::unordered_map> edges; +}; + +#endif // !__ARCHETYPE_H__ + +// TODO: IMPLEMENT COMPILE-TIME TYPE ORDERING BY eReplicaType ENUM VALUE +// TODO: SEE WHICH FUNCTIONS CAN BE SAFELY MADE NOEXCEPT +// TODO: CREATE CUSTOM ITERATOR diff --git a/dGame/dEntity/EntitySystem.h b/dGame/dEntity/EntitySystem.h new file mode 100644 index 000000000..7fc64a340 --- /dev/null +++ b/dGame/dEntity/EntitySystem.h @@ -0,0 +1,191 @@ +#ifndef __ENTITYSYSTEM_H__ +#define __ENTITYSYSTEM_H__ + +#include +#include +#include +#include +#include +#include + +#include "Archetype.h" +#include "CharacterComponent.h" // TEMP +#include "DestroyableComponent.h" // TEMP +#include "SimplePhysicsComponent.h" // TEMP +#include "dCommonVars.h" +#include "ObjectIDManager.h" + +/** + * Archetype visitor structs (for use with std::visit) +*/ +namespace { + /** + * ComponentVisitor struct: Used to perform GetComponent function calls on an archetype using std::visit + */ + template + struct ComponentVisitor { + const size_t index; + + explicit constexpr ComponentVisitor(const size_t index) noexcept : index{ index } {} + + /** + * The operator() for the ComponentVisitor struct. Used to get components from an archetype + * @returns A const pointer to the component if it is present in the archetype, nullptr if it is not + */ + constexpr CType* const operator()(auto&& archetype) { + using ArchetypeType = std::remove_pointer_t>; // Needed to fix a MacOS issue + + if constexpr (ArchetypeType::template HasComponent()) { + return &archetype->template GetComponent(index); + } else { + return nullptr; + } + } + }; +} + +/** + * TODO: Class documentation +*/ +class EntitySystem final { +public: + /** + * Aliases + */ + using ArchetypeId = uint32_t; + using ArchetypeSet = std::unordered_set; + using ArchetypeVariantPtr = std::variant< + std::unique_ptr>, + std::unique_ptr>, + std::unique_ptr>, + + std::unique_ptr>, + std::unique_ptr>, + + std::unique_ptr> + >; // TODO: Figure out how to generate this automatically + using ComponentTypeId = std::type_index; + + struct ArchetypeVariants final { + std::vector data; + + auto begin() { + return data.begin(); + } + + auto end() { + return data.end(); + } + + }; + + /** + * Adds entity to the entity system + * @param explicitId Explicit object ID to provide to entity + * @param componentArgs Arguments to be forwarded to component constructors + */ + template + void CreateEntity(const LWOOBJID explicitId, CTypes&&... componentArgs) { + Archetype& archetype = GetArchetype(); + + // Need to handle entities with baked-in IDs in their info... but later + // In fact, need to review ALL the id code for later + // For now, just focusing on the archetype logic + + const size_t insertedIndex = archetype.size(); + archetype.CreateComponents(std::forward(componentArgs)...); // Create the components in the archetype + m_EntityIndex.try_emplace(explicitId, ArchetypeRecord{ archetype.id, insertedIndex }); // Create the corresponding pointers in the entity index + } + + /** + * Overload for non-specified object ID + * @param componentArgs Arguments to be forwarded to component constructors + */ + template + void CreateEntity(CTypes&&... componentArgs) { + CreateEntity(ObjectIDManager::GenerateObjectID(), std::forward(componentArgs)...); + } + + /** + * Mark an entity for deletion given a corresponding object ID TODO: IMPLEMENT + * @param entityId ID of the entity to mark for deletion + */ + void MarkForDeletion(const LWOOBJID entityId) { + //const auto& itToRemove = m_EntityIndex.find(entityId); //perform the search in m_EntityIndex only once + //m_EntitiesToDelete.emplace(entityId, std::move(itToRemove->second)); + //m_EntityIndex.erase(itToRemove); + + m_EntitiesToDelete.emplace(entityId); + } + + /** + * Determine if an entity is associated with an Object ID + * @returns A boolean representing whether the entity exists + */ + [[nodiscard]] bool EntityExists(const LWOOBJID entityId) noexcept { + return m_EntityIndex.count(entityId) != 0; + } + + /** + * Determine if an entity has a component + * @param entityId Object ID of the entity to check + * @returns Boolean value representing whether component is present + */ + template + [[nodiscard]] bool HasComponent(const LWOOBJID entityId) { + const ArchetypeRecord& record = m_EntityIndex[entityId]; + const auto& hasComponentVisitor = [](auto&& archetype) { return archetype->template HasComponent(); }; + + return std::visit(hasComponentVisitor, m_Archetypes[record.archetypeIndex]); // Using visitor pattern + } + + /** + * Get a pointer to an entity component + * @param entityId Object ID of the entity to check + * @returns The pointer if the component exists, or nullptr if it does not + */ + template + [[nodiscard]] CType* const GetComponent(const LWOOBJID entityId) { + const ArchetypeRecord& record = m_EntityIndex[entityId]; + + return std::visit(ComponentVisitor(record.componentIndex), m_Archetypes[record.archetypeIndex]); // Using visitor pattern + } + +protected: + /** + * Method to create an entity archetype (relies on copy elision) TODO: Change? + * @param archetypeId The ID to assign to the created archetype + */ + template + [[nodiscard]] const size_t CreateArchetype() { // TODO: Noexcept? + const size_t indexToInsert = m_Archetypes.size(); + m_Archetypes.emplace_back(std::make_unique>(indexToInsert)); + return indexToInsert; + } + + /** + * Method to get a reference to an entity archetype given the components it contains + */ + template + [[nodiscard]] Archetype& GetArchetype() { + static size_t archetypeIndex = CreateArchetype(); // TODO: Maybe split this out into some kind of 'register' function instead? + + return *std::get>>(m_Archetypes[archetypeIndex]); + } + +public: +//private: + std::vector m_Archetypes; + //ArchetypeVariants m_Archetypes; + + struct ArchetypeRecord { + size_t archetypeIndex; + size_t componentIndex; + }; + + std::unordered_map m_EntityIndex; + + std::unordered_set m_EntitiesToDelete; +}; + +#endif // !__ENTITYSYSTEM_H diff --git a/dGame/dGameMessages/EchoStartSkill.h b/dGame/dGameMessages/EchoStartSkill.h index f5dee816a..389a81e0e 100644 --- a/dGame/dGameMessages/EchoStartSkill.h +++ b/dGame/dGameMessages/EchoStartSkill.h @@ -13,13 +13,13 @@ class EchoStartSkill { bUsedMouse = false; fCasterLatency = 0.0f; iCastType = 0; - lastClickedPosit = NiPoint3::ZERO; + lastClickedPosit = NiPoint3Constant::ZERO; optionalTargetID = LWOOBJID_EMPTY; - originatorRot = NiQuaternion::IDENTITY; + originatorRot = NiQuaternionConstant::IDENTITY; uiSkillHandle = 0; } - EchoStartSkill(LWOOBJID _optionalOriginatorID, std::string _sBitStream, TSkillID _skillID, bool _bUsedMouse = false, float _fCasterLatency = 0.0f, int32_t _iCastType = 0, NiPoint3 _lastClickedPosit = NiPoint3::ZERO, LWOOBJID _optionalTargetID = LWOOBJID_EMPTY, NiQuaternion _originatorRot = NiQuaternion::IDENTITY, uint32_t _uiSkillHandle = 0) { + EchoStartSkill(LWOOBJID _optionalOriginatorID, std::string _sBitStream, TSkillID _skillID, bool _bUsedMouse = false, float _fCasterLatency = 0.0f, int32_t _iCastType = 0, NiPoint3 _lastClickedPosit = NiPoint3Constant::ZERO, LWOOBJID _optionalTargetID = LWOOBJID_EMPTY, NiQuaternion _originatorRot = NiQuaternionConstant::IDENTITY, uint32_t _uiSkillHandle = 0) { bUsedMouse = _bUsedMouse; fCasterLatency = _fCasterLatency; iCastType = _iCastType; @@ -50,16 +50,16 @@ class EchoStartSkill { stream->Write(iCastType != 0); if (iCastType != 0) stream->Write(iCastType); - stream->Write(lastClickedPosit != NiPoint3::ZERO); - if (lastClickedPosit != NiPoint3::ZERO) stream->Write(lastClickedPosit); + stream->Write(lastClickedPosit != NiPoint3Constant::ZERO); + if (lastClickedPosit != NiPoint3Constant::ZERO) stream->Write(lastClickedPosit); stream->Write(optionalOriginatorID); stream->Write(optionalTargetID != LWOOBJID_EMPTY); if (optionalTargetID != LWOOBJID_EMPTY) stream->Write(optionalTargetID); - stream->Write(originatorRot != NiQuaternion::IDENTITY); - if (originatorRot != NiQuaternion::IDENTITY) stream->Write(originatorRot); + stream->Write(originatorRot != NiQuaternionConstant::IDENTITY); + if (originatorRot != NiQuaternionConstant::IDENTITY) stream->Write(originatorRot); uint32_t sBitStreamLength = sBitStream.length(); stream->Write(sBitStreamLength); diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 8c935afef..0262064f7 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -385,8 +385,8 @@ void GameMessages::SendPlatformResync(Entity* entity, const SystemAddress& sysAd float fIdleTimeElapsed = 0.0f; float fMoveTimeElapsed = 0.0f; float fPercentBetweenPoints = 0.0f; - NiPoint3 ptUnexpectedLocation = NiPoint3::ZERO; - NiQuaternion qUnexpectedRotation = NiQuaternion::IDENTITY; + NiPoint3 ptUnexpectedLocation = NiPoint3Constant::ZERO; + NiQuaternion qUnexpectedRotation = NiQuaternionConstant::IDENTITY; bitStream.Write(bReverse); bitStream.Write(bStopAtDesiredWaypoint); @@ -403,8 +403,8 @@ void GameMessages::SendPlatformResync(Entity* entity, const SystemAddress& sysAd bitStream.Write(ptUnexpectedLocation.y); bitStream.Write(ptUnexpectedLocation.z); - bitStream.Write(qUnexpectedRotation != NiQuaternion::IDENTITY); - if (qUnexpectedRotation != NiQuaternion::IDENTITY) { + bitStream.Write(qUnexpectedRotation != NiQuaternionConstant::IDENTITY); + if (qUnexpectedRotation != NiQuaternionConstant::IDENTITY) { bitStream.Write(qUnexpectedRotation.x); bitStream.Write(qUnexpectedRotation.y); bitStream.Write(qUnexpectedRotation.z); @@ -607,11 +607,11 @@ void GameMessages::SendModifyLEGOScore(Entity* entity, const SystemAddress& sysA SEND_PACKET; } -void GameMessages::SendUIMessageServerToSingleClient(Entity* entity, const SystemAddress& sysAddr, const std::string& message, AMFBaseValue& args) { +void GameMessages::SendUIMessageServerToSingleClient(const LWOOBJID entityId, const SystemAddress& sysAddr, const std::string& message, AMFBaseValue& args) { CBITSTREAM; CMSGHEADER; - bitStream.Write(entity->GetObjectID()); + bitStream.Write(entityId); bitStream.Write(eGameMessageType::UI_MESSAGE_SERVER_TO_SINGLE_CLIENT); bitStream.Write(args); @@ -625,6 +625,11 @@ void GameMessages::SendUIMessageServerToSingleClient(Entity* entity, const Syste SEND_PACKET; } +// Compatibility shim +void GameMessages::SendUIMessageServerToSingleClient(Entity* entity, const SystemAddress& sysAddr, const std::string& message, AMFBaseValue& args) { + GameMessages::SendUIMessageServerToSingleClient(entity->GetObjectID(), entity->GetSystemAddress(), message, args); +} + void GameMessages::SendUIMessageServerToSingleClient(const std::string& message, AMFBaseValue& args, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -680,19 +685,20 @@ void GameMessages::SendPlayEmbeddedEffectOnAllClientsNearObject(Entity* entity, SEND_PACKET_BROADCAST; } +// Compatibility shim void GameMessages::SendPlayFXEffect(Entity* entity, int32_t effectID, const std::u16string& effectType, const std::string& name, LWOOBJID secondary, float priority, float scale, bool serialize) { SendPlayFXEffect(entity->GetObjectID(), effectID, effectType, name, secondary, priority, scale, serialize); } -void GameMessages::SendPlayFXEffect(const LWOOBJID& entity, int32_t effectID, const std::u16string& effectType, const std::string& name, LWOOBJID secondary, float priority, float scale, bool serialize) { +void GameMessages::SendPlayFXEffect(const LWOOBJID entityId, const int32_t effectId, const std::u16string& effectType, const std::string& name, const LWOOBJID secondary, const float priority, const float scale, const bool serialize) { CBITSTREAM; CMSGHEADER; - bitStream.Write(entity); + bitStream.Write(entityId); bitStream.Write(eGameMessageType::PLAY_FX_EFFECT); - bitStream.Write(effectID != -1); - if (effectID != -1) bitStream.Write(effectID); + bitStream.Write(effectId != -1); + if (effectId != -1) bitStream.Write(effectId); bitStream.Write(effectType.size()); for (const auto& k : effectType) { @@ -718,6 +724,20 @@ void GameMessages::SendPlayFXEffect(const LWOOBJID& entity, int32_t effectID, co SEND_PACKET_BROADCAST; } +void GameMessages::SendStopFXEffect(const LWOOBJID entityId, const bool killImmediate, const std::string& name) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(entityId); + bitStream.Write(eGameMessageType::STOP_FX_EFFECT); + + bitStream.Write(killImmediate); + bitStream.Write(name.size()); + bitStream.Write(name.c_str(), name.size()); + + SEND_PACKET_BROADCAST; +} + void GameMessages::SendStopFXEffect(Entity* entity, bool killImmediate, std::string name) { CBITSTREAM; CMSGHEADER; @@ -770,7 +790,7 @@ void GameMessages::SendSetCurrency(Entity* entity, int64_t currency, int lootTyp bitStream.Write(lootType != LOOTTYPE_NONE); if (lootType != LOOTTYPE_NONE) bitStream.Write(lootType); - bitStream.Write(NiPoint3::ZERO); + bitStream.Write(NiPoint3Constant::ZERO); bitStream.Write(sourceLOT != LOT_NULL); if (sourceLOT != LOT_NULL) bitStream.Write(sourceLOT); @@ -1055,21 +1075,29 @@ void GameMessages::SendSetNetworkScriptVar(Entity* entity, const SystemAddress& SEND_PACKET; } -void GameMessages::SendDropClientLoot(Entity* entity, const LWOOBJID& sourceID, LOT item, int currency, NiPoint3 spawnPos, int count) { - if (Game::config->GetValue("disable_drops") == "1" || !entity) { - return; - } +// Compatibility shim +void GameMessages::SendDropClientLoot(Entity* entity, const LWOOBJID sourceID, LOT item, int currency, NiPoint3 spawnPos, int count) { + if (!entity) return; + + const auto entityID = entity->GetObjectID(); + const auto sysAddr = entity->GetSystemAddress(); + + GameMessages::SendDropClientLoot(entityID, sourceID, item, currency, spawnPos, count, sysAddr); +} + +void GameMessages::SendDropClientLoot(const LWOOBJID entityId, const LWOOBJID sourceId, const LOT item, const int currency, const NiPoint3 spawnPos, const int count, const SystemAddress& sysAddr) { + if (Game::config->GetValue("disable_drops") == "1") return; bool bUsePosition = false; NiPoint3 finalPosition; - LWOOBJID lootID = LWOOBJID_EMPTY; - LWOOBJID owner = entity->GetObjectID(); + LWOOBJID lootId = LWOOBJID_EMPTY; + auto* const entity = Game::entityManager->GetEntity(entityId); if (item != LOT_NULL && item != 0) { - lootID = ObjectIDManager::GenerateObjectID(); + lootId = ObjectIDManager::GenerateObjectID(); Loot::Info info; - info.id = lootID; + info.id = lootId; info.count = count; info.lot = item; entity->AddLootItem(info); @@ -1079,15 +1107,15 @@ void GameMessages::SendDropClientLoot(Entity* entity, const LWOOBJID& sourceID, entity->RegisterCoinDrop(currency); } - if (spawnPos != NiPoint3::ZERO) { + if (spawnPos != NiPoint3Constant::ZERO) { bUsePosition = true; //Calculate where the loot will go: - uint16_t degree = GeneralUtils::GenerateRandomNumber(0, 360); + const uint16_t degree = GeneralUtils::GenerateRandomNumber(0, 360); - double rad = degree * 3.14 / 180; - double sin_v = sin(rad) * 4.2; - double cos_v = cos(rad) * 4.2; + const double rad = degree * 3.14 / 180; + const double sin_v = sin(rad) * 4.2; + const double cos_v = cos(rad) * 4.2; finalPosition = NiPoint3(static_cast(spawnPos.GetX() + sin_v), spawnPos.GetY(), static_cast(spawnPos.GetZ() + cos_v)); } @@ -1096,24 +1124,24 @@ void GameMessages::SendDropClientLoot(Entity* entity, const LWOOBJID& sourceID, CBITSTREAM; CMSGHEADER; - bitStream.Write(entity->GetObjectID()); + bitStream.Write(entityId); bitStream.Write(eGameMessageType::DROP_CLIENT_LOOT); bitStream.Write(bUsePosition); - bitStream.Write(finalPosition != NiPoint3::ZERO); - if (finalPosition != NiPoint3::ZERO) bitStream.Write(finalPosition); + bitStream.Write(finalPosition != NiPoint3Constant::ZERO); + if (finalPosition != NiPoint3Constant::ZERO) bitStream.Write(finalPosition); bitStream.Write(currency); bitStream.Write(item); - bitStream.Write(lootID); - bitStream.Write(owner); - bitStream.Write(sourceID); + bitStream.Write(lootId); + bitStream.Write(entityId); + bitStream.Write(sourceId); - bitStream.Write(spawnPos != NiPoint3::ZERO); - if (spawnPos != NiPoint3::ZERO) bitStream.Write(spawnPos); + bitStream.Write(spawnPos != NiPoint3Constant::ZERO); + if (spawnPos != NiPoint3Constant::ZERO) bitStream.Write(spawnPos); - auto* team = TeamManager::Instance()->GetTeam(owner); + auto* team = TeamManager::Instance()->GetTeam(entityId); // Currency and powerups should not sync if (team != nullptr && currency == 0) { @@ -1123,9 +1151,9 @@ void GameMessages::SendDropClientLoot(Entity* entity, const LWOOBJID& sourceID, if (object.type != "Powerup") { for (const auto memberId : team->members) { - auto* member = Game::entityManager->GetEntity(memberId); + auto* const member = Game::entityManager->GetEntity(memberId); - if (member == nullptr) continue; + if (!member) continue; SystemAddress sysAddr = member->GetSystemAddress(); SEND_PACKET; @@ -1135,7 +1163,6 @@ void GameMessages::SendDropClientLoot(Entity* entity, const LWOOBJID& sourceID, } } - SystemAddress sysAddr = entity->GetSystemAddress(); SEND_PACKET; } @@ -1170,7 +1197,7 @@ void GameMessages::SendPlayerReachedRespawnCheckpoint(Entity* entity, const NiPo bitStream.Write(position.y); bitStream.Write(position.z); - const bool bIsNotIdentity = rotation != NiQuaternion::IDENTITY; + const bool bIsNotIdentity = rotation != NiQuaternionConstant::IDENTITY; bitStream.Write(bIsNotIdentity); if (bIsNotIdentity) { @@ -1646,8 +1673,8 @@ void GameMessages::SendNotifyClientShootingGalleryScore(LWOOBJID objectId, const void GameMessages::HandleUpdateShootingGalleryRotation(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { float angle = 0.0f; - NiPoint3 facing = NiPoint3::ZERO; - NiPoint3 muzzlePos = NiPoint3::ZERO; + NiPoint3 facing = NiPoint3Constant::ZERO; + NiPoint3 muzzlePos = NiPoint3Constant::ZERO; inStream->Read(angle); inStream->Read(facing); inStream->Read(muzzlePos); @@ -2103,8 +2130,8 @@ void GameMessages::SendPlaceModelResponse(LWOOBJID objectId, const SystemAddress bitStream.Write(objectId); bitStream.Write(eGameMessageType::PLACE_MODEL_RESPONSE); - bitStream.Write(position != NiPoint3::ZERO); - if (position != NiPoint3::ZERO) { + bitStream.Write(position != NiPoint3Constant::ZERO); + if (position != NiPoint3Constant::ZERO) { bitStream.Write(position); } @@ -2118,8 +2145,8 @@ void GameMessages::SendPlaceModelResponse(LWOOBJID objectId, const SystemAddress bitStream.Write(response); } - bitStream.Write(rotation != NiQuaternion::IDENTITY); - if (rotation != NiQuaternion::IDENTITY) { + bitStream.Write(rotation != NiQuaternionConstant::IDENTITY); + if (rotation != NiQuaternionConstant::IDENTITY) { bitStream.Write(response); } @@ -2271,7 +2298,7 @@ void GameMessages::HandleSetBuildMode(RakNet::BitStream* inStream, Entity* entit bool modePaused{}; int modeValue = 1; LWOOBJID playerId{}; - NiPoint3 startPosition = NiPoint3::ZERO; + NiPoint3 startPosition = NiPoint3Constant::ZERO; inStream->Read(start); @@ -2290,7 +2317,7 @@ void GameMessages::HandleSetBuildMode(RakNet::BitStream* inStream, Entity* entit auto* player = Game::entityManager->GetEntity(playerId); - if (startPosition == NiPoint3::ZERO) { + if (startPosition == NiPoint3Constant::ZERO) { startPosition = player->GetPosition(); } @@ -2384,13 +2411,13 @@ void GameMessages::HandlePlacePropertyModel(RakNet::BitStream* inStream, Entity* inStream->Read(model); - PropertyManagementComponent::Instance()->UpdateModelPosition(model, NiPoint3::ZERO, NiQuaternion::IDENTITY); + PropertyManagementComponent::Instance()->UpdateModelPosition(model, NiPoint3Constant::ZERO, NiQuaternionConstant::IDENTITY); } void GameMessages::HandleUpdatePropertyModel(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { LWOOBJID model; NiPoint3 position; - NiQuaternion rotation = NiQuaternion::IDENTITY; + NiQuaternion rotation = NiQuaternionConstant::IDENTITY; inStream->Read(model); inStream->Read(position); @@ -2612,7 +2639,7 @@ void GameMessages::HandleBBBSaveRequest(RakNet::BitStream* inStream, Entity* ent IPropertyContents::Model model; model.id = newIDL; model.ugcId = blueprintIDSmall; - model.position = NiPoint3::ZERO; + model.position = NiPoint3Constant::ZERO; model.rotation = NiQuaternion(0.0f, 0.0f, 0.0f, 0.0f); model.lot = 14; Database::Get()->InsertNewPropertyModel(propertyId, model, "Objects_14_name"); @@ -3393,7 +3420,7 @@ void GameMessages::SendNotifyPetTamingMinigame(LWOOBJID objectId, LWOOBJID petId bitStream.Write(petsDestPos); bitStream.Write(telePos); - const bool hasDefault = teleRot != NiQuaternion::IDENTITY; + const bool hasDefault = teleRot != NiQuaternionConstant::IDENTITY; bitStream.Write(hasDefault); if (hasDefault) bitStream.Write(teleRot); @@ -3566,11 +3593,11 @@ void GameMessages::SendPlayEmote(LWOOBJID objectId, int32_t emoteID, LWOOBJID ta SEND_PACKET; } -void GameMessages::SendRemoveBuff(Entity* entity, bool fromUnEquip, bool removeImmunity, uint32_t buffId) { +void GameMessages::SendRemoveBuff(const LWOOBJID& entity, const bool fromUnEquip, const bool removeImmunity, const uint32_t buffId) { CBITSTREAM; CMSGHEADER; - bitStream.Write(entity->GetObjectID()); + bitStream.Write(entity); bitStream.Write(eGameMessageType::REMOVE_BUFF); bitStream.Write(false); // bFromRemoveBehavior but setting this to true makes the GM not do anything on the client? @@ -3581,6 +3608,11 @@ void GameMessages::SendRemoveBuff(Entity* entity, bool fromUnEquip, bool removeI SEND_PACKET_BROADCAST; } +// Compatibility shim +void GameMessages::SendRemoveBuff(Entity* entity, bool fromUnEquip, bool removeImmunity, uint32_t buffId) { + GameMessages::SendRemoveBuff(entity->GetObjectID(), fromUnEquip, removeImmunity, buffId); +} + void GameMessages::SendBouncerActiveStatus(LWOOBJID objectId, bool bActive, const SystemAddress& sysAddr) { CBITSTREAM; CMSGHEADER; @@ -4218,7 +4250,7 @@ void GameMessages::HandleVehicleNotifyHitImaginationServer(RakNet::BitStream* in LWOOBJID pickupObjID = LWOOBJID_EMPTY; LWOOBJID pickupSpawnerID = LWOOBJID_EMPTY; int32_t pickupSpawnerIndex = -1; - NiPoint3 vehiclePosition = NiPoint3::ZERO; + NiPoint3 vehiclePosition = NiPoint3Constant::ZERO; if (inStream->ReadBit()) inStream->Read(pickupObjID); if (inStream->ReadBit()) inStream->Read(pickupSpawnerID); diff --git a/dGame/dGameMessages/GameMessages.h b/dGame/dGameMessages/GameMessages.h index 68a8471a5..1d9eae0fc 100644 --- a/dGame/dGameMessages/GameMessages.h +++ b/dGame/dGameMessages/GameMessages.h @@ -55,14 +55,14 @@ namespace GameMessages { const SystemAddress& sysAddr, bool bFirstTime = true, const LWOOBJID& buildAreaID = LWOOBJID_EMPTY, - NiPoint3 buildStartPOS = NiPoint3::ZERO, + NiPoint3 buildStartPOS = NiPoint3Constant::ZERO, int sourceBAG = 0, const LWOOBJID& sourceID = LWOOBJID_EMPTY, LOT sourceLOT = 0, int sourceTYPE = 8, const LWOOBJID& targetID = 0, LOT targetLOT = 0, - NiPoint3 targetPOS = NiPoint3::ZERO, + NiPoint3 targetPOS = NiPoint3Constant::ZERO, int targetTYPE = 0 ); @@ -91,16 +91,23 @@ namespace GameMessages { void NotifyLevelRewards(LWOOBJID objectID, const SystemAddress& sysAddr, int level, bool sending_rewards); void SendModifyLEGOScore(Entity* entity, const SystemAddress& sysAddr, int64_t score, eLootSourceType sourceType); + + void SendUIMessageServerToSingleClient(const LWOOBJID entityId, const SystemAddress& sysAddr, const std::string& message, AMFBaseValue& args); void SendUIMessageServerToSingleClient(Entity* entity, const SystemAddress& sysAddr, const std::string& message, AMFBaseValue& args); // Specify sysAddr if you need to send a flash message to a client who you dont know the objectID of. void SendUIMessageServerToSingleClient(const std::string& message, AMFBaseValue& args, const SystemAddress& sysAddr); + void SendUIMessageServerToAllClients(const std::string& message, AMFBaseValue& args); void SendPlayEmbeddedEffectOnAllClientsNearObject(Entity* entity, std::u16string effectName, const LWOOBJID& fromObjectID, float radius); + void SendPlayFXEffect(Entity* entity, int32_t effectID, const std::u16string& effectType, const std::string& name, LWOOBJID secondary, float priority = 1, float scale = 1, bool serialize = true); - void SendPlayFXEffect(const LWOOBJID& entity, int32_t effectID, const std::u16string& effectType, const std::string& name, LWOOBJID secondary = LWOOBJID_EMPTY, float priority = 1, float scale = 1, bool serialize = true); + void SendPlayFXEffect(const LWOOBJID entityId, const int32_t effectId, const std::u16string& effectType, const std::string& name, const LWOOBJID secondary = LWOOBJID_EMPTY, const float priority = 1, const float scale = 1, const bool serialize = true); + void SendStopFXEffect(Entity* entity, bool killImmediate, std::string name); + void SendStopFXEffect(const LWOOBJID entityId, const bool killImmediate, const std::string& name); + void SendBroadcastTextToChatbox(Entity* entity, const SystemAddress& sysAddr, const std::u16string& attrs, const std::u16string& wsText); void SendSetCurrency(Entity* entity, int64_t currency, int lootType, const LWOOBJID& sourceID, const LOT& sourceLOT, int sourceTradeID, bool overrideCurrent, eLootSourceType sourceType); @@ -122,7 +129,9 @@ namespace GameMessages { void SendStop2DAmbientSound(Entity* entity, bool force, std::string audioGUID, bool result = false); void SendPlay2DAmbientSound(Entity* entity, std::string audioGUID, bool result = false); void SendSetNetworkScriptVar(Entity* entity, const SystemAddress& sysAddr, std::string data); - void SendDropClientLoot(Entity* entity, const LWOOBJID& sourceID, LOT item, int currency, NiPoint3 spawnPos = NiPoint3::ZERO, int count = 1); + + void SendDropClientLoot(Entity* entity, const LWOOBJID sourceID, LOT item, int currency, NiPoint3 spawnPos = NiPoint3Constant::ZERO, int count = 1); + void SendDropClientLoot(const LWOOBJID entityId, const LWOOBJID sourceId, const LOT item, const int currency, const NiPoint3 spawnPos, const int count, const SystemAddress& sysAddr); void SendSetPlayerControlScheme(Entity* entity, eControlScheme controlScheme); void SendPlayerReachedRespawnCheckpoint(Entity* entity, const NiPoint3& position, const NiQuaternion& rotation); @@ -239,7 +248,7 @@ namespace GameMessages { void SendLockNodeRotation(Entity* entity, std::string nodeName); - void SendSetBuildModeConfirmed(LWOOBJID objectId, const SystemAddress& sysAddr, bool start, bool warnVisitors, bool modePaused, int32_t modeValue, LWOOBJID playerId, NiPoint3 startPos = NiPoint3::ZERO); + void SendSetBuildModeConfirmed(LWOOBJID objectId, const SystemAddress& sysAddr, bool start, bool warnVisitors, bool modePaused, int32_t modeValue, LWOOBJID playerId, NiPoint3 startPos = NiPoint3Constant::ZERO); void SendGetModelsOnProperty(LWOOBJID objectId, std::map models, const SystemAddress& sysAddr); @@ -644,6 +653,7 @@ namespace GameMessages { void HandleReportBug(RakNet::BitStream* inStream, Entity* entity); + void SendRemoveBuff(const LWOOBJID& entity, const bool fromUnEquip, const bool removeImmunity, const uint32_t buffId); void SendRemoveBuff(Entity* entity, bool fromUnEquip, bool removeImmunity, uint32_t buffId); // bubble diff --git a/dGame/dGameMessages/StartSkill.h b/dGame/dGameMessages/StartSkill.h index 40bc210ff..6b0d267ac 100644 --- a/dGame/dGameMessages/StartSkill.h +++ b/dGame/dGameMessages/StartSkill.h @@ -16,13 +16,13 @@ class StartSkill { consumableItemID = LWOOBJID_EMPTY; fCasterLatency = 0.0f; iCastType = 0; - lastClickedPosit = NiPoint3::ZERO; + lastClickedPosit = NiPoint3Constant::ZERO; optionalTargetID = LWOOBJID_EMPTY; - originatorRot = NiQuaternion::IDENTITY; + originatorRot = NiQuaternionConstant::IDENTITY; uiSkillHandle = 0; } - StartSkill(LWOOBJID _optionalOriginatorID, std::string _sBitStream, TSkillID _skillID, bool _bUsedMouse = false, LWOOBJID _consumableItemID = LWOOBJID_EMPTY, float _fCasterLatency = 0.0f, int32_t _iCastType = 0, NiPoint3 _lastClickedPosit = NiPoint3::ZERO, LWOOBJID _optionalTargetID = LWOOBJID_EMPTY, NiQuaternion _originatorRot = NiQuaternion::IDENTITY, uint32_t _uiSkillHandle = 0) { + StartSkill(LWOOBJID _optionalOriginatorID, std::string _sBitStream, TSkillID _skillID, bool _bUsedMouse = false, LWOOBJID _consumableItemID = LWOOBJID_EMPTY, float _fCasterLatency = 0.0f, int32_t _iCastType = 0, NiPoint3 _lastClickedPosit = NiPoint3Constant::ZERO, LWOOBJID _optionalTargetID = LWOOBJID_EMPTY, NiQuaternion _originatorRot = NiQuaternionConstant::IDENTITY, uint32_t _uiSkillHandle = 0) { bUsedMouse = _bUsedMouse; consumableItemID = _consumableItemID; fCasterLatency = _fCasterLatency; @@ -57,16 +57,16 @@ class StartSkill { stream->Write(iCastType != 0); if (iCastType != 0) stream->Write(iCastType); - stream->Write(lastClickedPosit != NiPoint3::ZERO); - if (lastClickedPosit != NiPoint3::ZERO) stream->Write(lastClickedPosit); + stream->Write(lastClickedPosit != NiPoint3Constant::ZERO); + if (lastClickedPosit != NiPoint3Constant::ZERO) stream->Write(lastClickedPosit); stream->Write(optionalOriginatorID); stream->Write(optionalTargetID != LWOOBJID_EMPTY); if (optionalTargetID != LWOOBJID_EMPTY) stream->Write(optionalTargetID); - stream->Write(originatorRot != NiQuaternion::IDENTITY); - if (originatorRot != NiQuaternion::IDENTITY) stream->Write(originatorRot); + stream->Write(originatorRot != NiQuaternionConstant::IDENTITY); + if (originatorRot != NiQuaternionConstant::IDENTITY) stream->Write(originatorRot); uint32_t sBitStreamLength = sBitStream.length(); stream->Write(sBitStreamLength); diff --git a/dGame/dInventory/ItemSetPassiveAbility.cpp b/dGame/dInventory/ItemSetPassiveAbility.cpp index 3030904d6..048050de7 100644 --- a/dGame/dInventory/ItemSetPassiveAbility.cpp +++ b/dGame/dInventory/ItemSetPassiveAbility.cpp @@ -7,7 +7,7 @@ ItemSetPassiveAbility::ItemSetPassiveAbility(PassiveAbilityTrigger trigger, Entity* parent, ItemSet* itemSet) { m_Trigger = trigger; - m_Parent = parent; + m_Parent = parent->GetObjectID(); //TEMP m_ItemSet = itemSet; m_Cooldown = 0.0f; @@ -37,17 +37,15 @@ void ItemSetPassiveAbility::Activate(Entity* target) { return; } - auto* destroyableComponent = m_Parent->GetComponent(); - auto* skillComponent = m_Parent->GetComponent(); + auto* const playerEntity = Game::entityManager->GetEntity(m_Parent); + auto* const destroyableComponent = playerEntity->GetComponent(); + auto* const skillComponent = playerEntity->GetComponent(); - if (destroyableComponent == nullptr || skillComponent == nullptr) { - return; - } + if (!destroyableComponent || !skillComponent) return; Game::entityManager->SerializeEntity(m_Parent); const auto id = static_cast(m_ItemSet->GetID()); - const auto parentID = m_Parent->GetObjectID(); const auto equippedCount = m_ItemSet->GetEquippedCount(); switch (id) { @@ -57,7 +55,7 @@ void ItemSetPassiveAbility::Activate(Entity* target) { case eItemSetPassiveAbilityID::EngineerRank1: { if (equippedCount < 4) return; m_Cooldown = 11.0f; - skillComponent->CalculateBehavior(394, 4401, parentID); + skillComponent->CalculateBehavior(394, 4401, m_Parent); break; } case eItemSetPassiveAbilityID::InventorRank2: @@ -65,7 +63,7 @@ void ItemSetPassiveAbility::Activate(Entity* target) { case eItemSetPassiveAbilityID::EngineerRank2: { if (equippedCount < 4) return; m_Cooldown = 11.0f; - skillComponent->CalculateBehavior(581, 9433, parentID); + skillComponent->CalculateBehavior(581, 9433, m_Parent); break; } case eItemSetPassiveAbilityID::InventorRank3: @@ -73,65 +71,65 @@ void ItemSetPassiveAbility::Activate(Entity* target) { case eItemSetPassiveAbilityID::EngineerRank3: { if (equippedCount < 4) return; m_Cooldown = 11.0f; - skillComponent->CalculateBehavior(582, 9435, parentID); + skillComponent->CalculateBehavior(582, 9435, m_Parent); break; } - // Sentinel + // Sentinel case eItemSetPassiveAbilityID::KnightRank1: { if (equippedCount < 4) return; m_Cooldown = 11.0f; - skillComponent->CalculateBehavior(559, 8884, parentID); + skillComponent->CalculateBehavior(559, 8884, m_Parent); break; } case eItemSetPassiveAbilityID::KnightRank2: { if (equippedCount < 4) return; m_Cooldown = 11.0f; - skillComponent->CalculateBehavior(560, 8885, parentID); + skillComponent->CalculateBehavior(560, 8885, m_Parent); break; } case eItemSetPassiveAbilityID::KnightRank3: { if (equippedCount < 4) return; m_Cooldown = 11.0f; - skillComponent->CalculateBehavior(561, 8890, parentID); + skillComponent->CalculateBehavior(561, 8890, m_Parent); break; } case eItemSetPassiveAbilityID::SpaceRangerRank1: { if (equippedCount < 4) return; m_Cooldown = 11.0f; - skillComponent->CalculateBehavior(1101, 24612, parentID); + skillComponent->CalculateBehavior(1101, 24612, m_Parent); break; } case eItemSetPassiveAbilityID::SpaceRangerRank2: { if (equippedCount < 4) return; m_Cooldown = 11.0f; - skillComponent->CalculateBehavior(1102, 24617, parentID); + skillComponent->CalculateBehavior(1102, 24617, m_Parent); break; } case eItemSetPassiveAbilityID::SpaceRangerRank3: { if (equippedCount < 4) return; m_Cooldown = 11.0f; - skillComponent->CalculateBehavior(1103, 24622, parentID); + skillComponent->CalculateBehavior(1103, 24622, m_Parent); break; } case eItemSetPassiveAbilityID::SamuraiRank1: { if (equippedCount < 4) return; m_Cooldown = 11.0f; - skillComponent->CalculateBehavior(562, 8899, parentID); + skillComponent->CalculateBehavior(562, 8899, m_Parent); break; } case eItemSetPassiveAbilityID::SamuraiRank2: { if (equippedCount < 4) return; m_Cooldown = 11.0f; - skillComponent->CalculateBehavior(563, 8904, parentID); + skillComponent->CalculateBehavior(563, 8904, m_Parent); break; } case eItemSetPassiveAbilityID::SamuraiRank3: { if (equippedCount < 4) return; m_Cooldown = 11.0f; - skillComponent->CalculateBehavior(564, 8909, parentID); + skillComponent->CalculateBehavior(564, 8909, m_Parent); break; } @@ -158,7 +156,7 @@ std::vector ItemSetPassiveAbility::FindAbilities(uint32_t break; } - // Sentinel + // Sentinel case eItemSetPassiveAbilityID::KnightRank1: case eItemSetPassiveAbilityID::KnightRank2: case eItemSetPassiveAbilityID::KnightRank3: @@ -173,7 +171,7 @@ std::vector ItemSetPassiveAbility::FindAbilities(uint32_t break; } - // Paradox + // Paradox case eItemSetPassiveAbilityID::BatLord: case eItemSetPassiveAbilityID::SpaceMarauderRank1: case eItemSetPassiveAbilityID::SpaceMarauderRank2: @@ -196,8 +194,9 @@ std::vector ItemSetPassiveAbility::FindAbilities(uint32_t } void ItemSetPassiveAbility::OnEnemySmshed(Entity* target) { - auto* destroyableComponent = m_Parent->GetComponent(); - auto* skillComponent = m_Parent->GetComponent(); + auto* const parentEntity = Game::entityManager->GetEntity(m_Parent); + auto* const destroyableComponent = parentEntity->GetComponent(); + auto* const skillComponent = parentEntity->GetComponent(); if (destroyableComponent == nullptr || skillComponent == nullptr) { return; @@ -206,7 +205,6 @@ void ItemSetPassiveAbility::OnEnemySmshed(Entity* target) { Game::entityManager->SerializeEntity(m_Parent); const auto id = static_cast(m_ItemSet->GetID()); - const auto parentID = m_Parent->GetObjectID(); const auto equippedCount = m_ItemSet->GetEquippedCount(); switch (id) { @@ -216,7 +214,7 @@ void ItemSetPassiveAbility::OnEnemySmshed(Entity* target) { destroyableComponent->Heal(3); break; } - // Sentinel + // Sentinel case eItemSetPassiveAbilityID::KnightRank1: { if (equippedCount < 5) return; destroyableComponent->Repair(1); @@ -265,7 +263,7 @@ void ItemSetPassiveAbility::OnEnemySmshed(Entity* target) { break; } - // Paradox + // Paradox case eItemSetPassiveAbilityID::SpaceMarauderRank1: { if (equippedCount < 4) return; destroyableComponent->Imagine(1); diff --git a/dGame/dInventory/ItemSetPassiveAbility.h b/dGame/dInventory/ItemSetPassiveAbility.h index 8735e6959..4d66446af 100644 --- a/dGame/dInventory/ItemSetPassiveAbility.h +++ b/dGame/dInventory/ItemSetPassiveAbility.h @@ -57,7 +57,7 @@ class ItemSetPassiveAbility /** * The owner of this ability */ - Entity* m_Parent; + LWOOBJID m_Parent; /** * The item set this ability belongs to diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddStripMessage.cpp b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddStripMessage.cpp index 5e75f6c42..6f0741ddc 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddStripMessage.cpp +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddStripMessage.cpp @@ -22,3 +22,7 @@ AddStripMessage::AddStripMessage(AMFArrayValue* arguments) : BehaviorMessageBase } LOG_DEBUG("number of actions %i", actionsToAdd.size()); } + +std::vector AddStripMessage::GetActionsToAdd() const { + return actionsToAdd; +} diff --git a/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddStripMessage.h b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddStripMessage.h index 0b9a09e3d..5cceb5107 100644 --- a/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddStripMessage.h +++ b/dGame/dPropertyBehaviors/ControlBehaviorMessages/AddStripMessage.h @@ -21,7 +21,7 @@ class AddStripMessage : public BehaviorMessageBase { AddStripMessage(AMFArrayValue* arguments); StripUiPosition GetPosition() const { return position; }; ActionContext GetActionContext() const { return actionContext; }; - std::vector GetActionsToAdd() const { return actionsToAdd; }; + std::vector GetActionsToAdd() const; private: StripUiPosition position; ActionContext actionContext; diff --git a/dGame/dUtilities/Loot.cpp b/dGame/dUtilities/Loot.cpp index 25c81e749..972ac483a 100644 --- a/dGame/dUtilities/Loot.cpp +++ b/dGame/dUtilities/Loot.cpp @@ -254,8 +254,7 @@ void Loot::DropLoot(Entity* player, Entity* killedObject, uint32_t matrixIndex, auto* inventoryComponent = player->GetComponent(); - if (!inventoryComponent) - return; + if (!inventoryComponent) return; std::unordered_map result = RollLootMatrix(player, matrixIndex); @@ -267,8 +266,7 @@ void Loot::DropLoot(Entity* player, Entity* killedObject, std::unordered_mapGetComponent(); - if (!inventoryComponent) - return; + if (!inventoryComponent) return; const auto spawnPosition = killedObject->GetPosition(); diff --git a/dScripts/02_server/Enemy/AG/BossSpiderQueenEnemyServer.cpp b/dScripts/02_server/Enemy/AG/BossSpiderQueenEnemyServer.cpp index f85e0561b..a8edb14a8 100644 --- a/dScripts/02_server/Enemy/AG/BossSpiderQueenEnemyServer.cpp +++ b/dScripts/02_server/Enemy/AG/BossSpiderQueenEnemyServer.cpp @@ -85,7 +85,7 @@ void BossSpiderQueenEnemyServer::WithdrawSpider(Entity* self, const bool withdra GameMessages::SendNotifyClientObject(self->GetObjectID(), u"SetColGroup", 10, 0, 0, "", UNASSIGNED_SYSTEM_ADDRESS); //First rotate for anim - NiQuaternion rot = NiQuaternion::IDENTITY; + NiQuaternion rot = NiQuaternionConstant::IDENTITY; controllable->SetStatic(false); @@ -402,7 +402,7 @@ void BossSpiderQueenEnemyServer::OnTimerDone(Entity* self, const std::string tim const auto withdrawn = self->GetBoolean(u"isWithdrawn"); if (!withdrawn) return; - NiQuaternion rot = NiQuaternion::IDENTITY; + NiQuaternion rot = NiQuaternionConstant::IDENTITY; //First rotate for anim controllable->SetStatic(false); @@ -597,12 +597,12 @@ void BossSpiderQueenEnemyServer::OnUpdate(Entity* self) { if (!isWithdrawn) return; - if (controllable->GetRotation() == NiQuaternion::IDENTITY) { + if (controllable->GetRotation() == NiQuaternionConstant::IDENTITY) { return; } controllable->SetStatic(false); - controllable->SetRotation(NiQuaternion::IDENTITY); + controllable->SetRotation(NiQuaternionConstant::IDENTITY); controllable->SetStatic(true); Game::entityManager->SerializeEntity(self); diff --git a/dScripts/02_server/Map/AG/AgLaserSensorServer.cpp b/dScripts/02_server/Map/AG/AgLaserSensorServer.cpp index 7fcea9fa9..6e19922ab 100644 --- a/dScripts/02_server/Map/AG/AgLaserSensorServer.cpp +++ b/dScripts/02_server/Map/AG/AgLaserSensorServer.cpp @@ -13,7 +13,7 @@ void AgLaserSensorServer::OnStartup(Entity* self) { phantomPhysicsComponent->SetPhysicsEffectActive(true); phantomPhysicsComponent->SetEffectType(ePhysicsEffectType::REPULSE); phantomPhysicsComponent->SetDirectionalMultiplier(repelForce); - phantomPhysicsComponent->SetDirection(NiPoint3::UNIT_Y); + phantomPhysicsComponent->SetDirection(NiPoint3Constant::UNIT_Y); } diff --git a/dScripts/02_server/Map/AM/AmDrawBridge.cpp b/dScripts/02_server/Map/AM/AmDrawBridge.cpp index 11d52cd7d..cd42f196c 100644 --- a/dScripts/02_server/Map/AM/AmDrawBridge.cpp +++ b/dScripts/02_server/Map/AM/AmDrawBridge.cpp @@ -66,7 +66,7 @@ void AmDrawBridge::OnTimerDone(Entity* self, std::string timerName) { return; } - simplePhysicsComponent->SetAngularVelocity(NiPoint3::ZERO); + simplePhysicsComponent->SetAngularVelocity(NiPoint3Constant::ZERO); Game::entityManager->SerializeEntity(bridge); } diff --git a/dScripts/02_server/Map/GF/MastTeleport.cpp b/dScripts/02_server/Map/GF/MastTeleport.cpp index 5a40507d5..e181779ec 100644 --- a/dScripts/02_server/Map/GF/MastTeleport.cpp +++ b/dScripts/02_server/Map/GF/MastTeleport.cpp @@ -81,7 +81,7 @@ void MastTeleport::OnTimerDone(Entity* self, std::string timerName) { GameMessages::SendOrientToAngle(playerId, true, rads, player->GetSystemAddress()); - GameMessages::SendTeleport(playerId, position, NiQuaternion::IDENTITY, player->GetSystemAddress()); + GameMessages::SendTeleport(playerId, position, NiQuaternionConstant::IDENTITY, player->GetSystemAddress()); GameMessages::SendSetStunned(playerId, eStateChangeType::POP, player->GetSystemAddress(), LWOOBJID_EMPTY, true, true, true, true, true, true, true diff --git a/dScripts/02_server/Pets/PetFromDigServer.cpp b/dScripts/02_server/Pets/PetFromDigServer.cpp index 525f3e946..33bab32a7 100644 --- a/dScripts/02_server/Pets/PetFromDigServer.cpp +++ b/dScripts/02_server/Pets/PetFromDigServer.cpp @@ -40,6 +40,6 @@ void PetFromDigServer::OnNotifyPetTamingMinigame(Entity* self, Entity* tamer, eP return; // TODO: Remove custom group? // Command the pet to the player as it may otherwise go to its spawn point which is non existant - // petComponent->Command(NiPoint3::ZERO, LWOOBJID_EMPTY, 6, 202, true); + // petComponent->Command(NiPoint3Constant::ZERO, LWOOBJID_EMPTY, 6, 202, true); } } diff --git a/dScripts/ScriptComponent.cpp b/dScripts/ScriptComponent.cpp index 7c44ded37..610878686 100644 --- a/dScripts/ScriptComponent.cpp +++ b/dScripts/ScriptComponent.cpp @@ -6,20 +6,15 @@ #include "Entity.h" #include "ScriptComponent.h" -ScriptComponent::ScriptComponent(Entity* parent, std::string scriptName, bool serialized, bool client) : Component(parent) { - m_Serialized = serialized; - m_Client = client; - +ScriptComponent::ScriptComponent(const LWOOBJID& parentEntityId, const std::string& scriptName, const bool serialized, const bool client) noexcept : Component{ parentEntityId } + , m_Serialized{ serialized } + , m_Client{ client } { SetScript(scriptName); } -ScriptComponent::~ScriptComponent() { - -} - void ScriptComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) { if (bIsInitialUpdate) { - const auto& networkSettings = m_Parent->GetNetworkSettings(); + const auto& networkSettings = Game::entityManager->GetEntity(m_Parent)->GetNetworkSettings(); auto hasNetworkSettings = !networkSettings.empty(); outBitStream->Write(hasNetworkSettings); @@ -48,5 +43,5 @@ CppScripts::Script* ScriptComponent::GetScript() { void ScriptComponent::SetScript(const std::string& scriptName) { // Scripts are managed by the CppScripts class and are effecitvely singletons // and they may also be used by other script components so DON'T delete them. - m_Script = CppScripts::GetScript(m_Parent, scriptName); + m_Script = CppScripts::GetScript(Game::entityManager->GetEntity(m_Parent), scriptName); } diff --git a/dScripts/ScriptComponent.h b/dScripts/ScriptComponent.h index cabbf8bf0..73e8b58c8 100644 --- a/dScripts/ScriptComponent.h +++ b/dScripts/ScriptComponent.h @@ -19,10 +19,9 @@ class Entity; */ class ScriptComponent : public Component { public: - inline static const eReplicaComponentType ComponentType = eReplicaComponentType::SCRIPT; + constexpr static const eReplicaComponentType ComponentType = eReplicaComponentType::SCRIPT; - ScriptComponent(Entity* parent, std::string scriptName, bool serialized, bool client = false); - ~ScriptComponent() override; + ScriptComponent(const LWOOBJID& parent, const std::string& scriptName, const bool serialized, const bool client = false) noexcept; void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override; diff --git a/dScripts/ai/GF/GfBanana.cpp b/dScripts/ai/GF/GfBanana.cpp index 6bc5c179d..b06aae6f9 100644 --- a/dScripts/ai/GF/GfBanana.cpp +++ b/dScripts/ai/GF/GfBanana.cpp @@ -56,7 +56,7 @@ void GfBanana::OnHit(Entity* self, Entity* attacker) { return; } - bananaEntity->SetPosition(bananaEntity->GetPosition() - NiPoint3::UNIT_Y * 8); + bananaEntity->SetPosition(bananaEntity->GetPosition() - NiPoint3Constant::UNIT_Y * 8); auto* bananaDestroyable = bananaEntity->GetComponent(); diff --git a/dScripts/client/ai/PR/CrabServer.cpp b/dScripts/client/ai/PR/CrabServer.cpp index f30142ba0..6cdc2de8c 100644 --- a/dScripts/client/ai/PR/CrabServer.cpp +++ b/dScripts/client/ai/PR/CrabServer.cpp @@ -39,6 +39,6 @@ void CrabServer::OnNotifyPetTamingMinigame(Entity* self, Entity* tamer, ePetTami return; // TODO: Remove custom group? // Command the pet to the player as it may otherwise go to its spawn point which is non existant - // petComponent->Command(NiPoint3::ZERO, LWOOBJID_EMPTY, 6, 202, true); + // petComponent->Command(NiPoint3Constant::ZERO, LWOOBJID_EMPTY, 6, 202, true); } } diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index d704bfea3..6a8ed074d 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -1031,8 +1031,8 @@ void HandlePacket(Packet* packet) { Game::entityManager->ConstructEntity(player, UNASSIGNED_SYSTEM_ADDRESS, true); - if (respawnPoint != NiPoint3::ZERO) { - GameMessages::SendPlayerReachedRespawnCheckpoint(player, respawnPoint, NiQuaternion::IDENTITY); + if (respawnPoint != NiPoint3Constant::ZERO) { + GameMessages::SendPlayerReachedRespawnCheckpoint(player, respawnPoint, NiQuaternionConstant::IDENTITY); } Game::entityManager->ConstructAllEntities(packet->systemAddress); diff --git a/dZoneManager/Spawner.h b/dZoneManager/Spawner.h index 79ba40d1d..686c75881 100644 --- a/dZoneManager/Spawner.h +++ b/dZoneManager/Spawner.h @@ -12,8 +12,8 @@ #include "EntityInfo.h" struct SpawnerNode { - NiPoint3 position = NiPoint3::ZERO; - NiQuaternion rotation = NiQuaternion::IDENTITY; + NiPoint3 position = NiPoint3Constant::ZERO; + NiQuaternion rotation = NiQuaternionConstant::IDENTITY; uint32_t nodeID = 0; uint32_t nodeMax = 1; std::vector entities; diff --git a/tests/dCommonTests/TestNiPoint3.cpp b/tests/dCommonTests/TestNiPoint3.cpp index fbc98eb09..49814d152 100644 --- a/tests/dCommonTests/TestNiPoint3.cpp +++ b/tests/dCommonTests/TestNiPoint3.cpp @@ -8,9 +8,9 @@ */ TEST(dCommonTests, NiPoint3Test) { // Check that Unitize works - ASSERT_EQ(NiPoint3(3, 0, 0).Unitize(), NiPoint3::UNIT_X); + ASSERT_EQ(NiPoint3(3, 0, 0).Unitize(), NiPoint3Constant::UNIT_X); // Check what unitize does to a vector of length 0 - ASSERT_EQ(NiPoint3::ZERO.Unitize(), NiPoint3::ZERO); + ASSERT_EQ(NiPoint3Constant::ZERO.Unitize(), NiPoint3Constant::ZERO); } TEST(dCommonTests, NiPoint3OperatorTest) { diff --git a/tests/dGameTests/CMakeLists.txt b/tests/dGameTests/CMakeLists.txt index b1fdaa070..ddd90d264 100644 --- a/tests/dGameTests/CMakeLists.txt +++ b/tests/dGameTests/CMakeLists.txt @@ -5,6 +5,9 @@ set(DGAMETEST_SOURCES add_subdirectory(dComponentsTests) list(APPEND DGAMETEST_SOURCES ${DCOMPONENTS_TESTS}) +add_subdirectory(dEntitiesTests) +list(APPEND DGAMETEST_SOURCES ${DENTITIES_TESTS}) + add_subdirectory(dGameMessagesTests) list(APPEND DGAMETEST_SOURCES ${DGAMEMESSAGES_TESTS}) diff --git a/tests/dGameTests/GameDependencies.h b/tests/dGameTests/GameDependencies.h index 8aefaa3d5..11c320ba8 100644 --- a/tests/dGameTests/GameDependencies.h +++ b/tests/dGameTests/GameDependencies.h @@ -25,8 +25,8 @@ class dServerMock : public dServer { class GameDependenciesTest : public ::testing::Test { protected: void SetUpDependencies() { - info.pos = NiPoint3::ZERO; - info.rot = NiQuaternion::IDENTITY; + info.pos = NiPoint3Constant::ZERO; + info.rot = NiQuaternionConstant::IDENTITY; info.scale = 1.0f; info.spawner = nullptr; info.lot = 999; diff --git a/tests/dGameTests/dEntitiesTests/ArchetypeTests.cpp b/tests/dGameTests/dEntitiesTests/ArchetypeTests.cpp new file mode 100644 index 000000000..119cfa2f7 --- /dev/null +++ b/tests/dGameTests/dEntitiesTests/ArchetypeTests.cpp @@ -0,0 +1,373 @@ +#include "GameDependencies.h" +#include + +#include +#include +#include +#include + +#include "Logger.h" +#include "Game.h" +#include "BitStream.h" +#include "CharacterComponent.h" +#include "DestroyableComponent.h" +#include "SimplePhysicsComponent.h" +#include "Archetype.h" +#include "EntitySystem.h" +#include "ObjectIDManager.h" + +class ArchetypeTest : public GameDependenciesTest { +protected: + std::unique_ptr baseEntity; + std::unique_ptr newEntity; + std::unique_ptr> baseArchetype; + + std::unique_ptr logger = std::make_unique("./ArchetypeTests", true, true); + + CBITSTREAM + void SetUp() override { + SetUpDependencies(); + + Game::logger = logger.get(); + + baseEntity = std::make_unique(15, GameDependenciesTest::info); + newEntity = std::make_unique(16, GameDependenciesTest::info); + baseArchetype = std::make_unique>(0); + } + + void TearDown() override { + Game::logger = nullptr; + + TearDownDependencies(); + } +}; + +TEST_F(ArchetypeTest, PlacementNewAddArchetypeTest) { + ASSERT_NE(baseEntity.get(), nullptr); + ASSERT_NE(baseArchetype.get(), nullptr); + + // Create a destroyable component and simple physics component and test their parent entity was assigned correctly + const auto baseEntityId = baseEntity->GetObjectID(); + baseArchetype->CreateComponents(DestroyableComponent(baseEntityId), SimplePhysicsComponent(baseEntityId, 2)); + + auto& destroyableComponent = baseArchetype->GetComponent(0); + ASSERT_EQ(destroyableComponent.GetParent(), baseEntity.get()); + ASSERT_NO_THROW(destroyableComponent.GetArmor()); + + auto& simplePhysicsComponent = baseArchetype->GetComponent(0); + ASSERT_EQ(simplePhysicsComponent.GetParent(), baseEntity.get()); + + // Set and read some values + const NiPoint3 testPos{ -1.0, 1.0, 3.0 }; + ASSERT_NO_THROW(simplePhysicsComponent.SetPosition(testPos)); + ASSERT_EQ(simplePhysicsComponent.GetPosition(), testPos); + + // Add another entry to the archetype + const auto newEntityId = newEntity->GetObjectID(); + baseArchetype->CreateComponents(DestroyableComponent(newEntityId), SimplePhysicsComponent(newEntityId, 2)); + + auto& newDestroyableComponent = baseArchetype->GetComponent(1); + ASSERT_EQ(newDestroyableComponent.GetParent(), newEntity.get()); + ASSERT_NE(newDestroyableComponent.GetParent(), baseEntity.get()); + + auto& newSimplePhysicsComponent = baseArchetype->GetComponent(1); + ASSERT_EQ(newSimplePhysicsComponent.GetParent(), newEntity.get()); + ASSERT_NE(newSimplePhysicsComponent.GetParent(), baseEntity.get()); + + size_t destCompSize = sizeof(baseArchetype->GetComponent(1)); + LOG("Destroyable component is of %ul size!", destCompSize); + auto nEntries = baseArchetype->Container::entries.capacity(); + LOG("Archetype has %d entries!", nEntries); +} + +TEST_F(ArchetypeTest, ArchetypeDeleteTest) { + // Create a destroyable component and simple physics component and test their parent entity was assigned correctly + const auto baseEntityId = baseEntity->GetObjectID(); + baseArchetype->CreateComponents(DestroyableComponent(baseEntityId), SimplePhysicsComponent(baseEntityId, 2)); + + // Add another entry to the archetype + const auto newEntityId = newEntity->GetObjectID(); + baseArchetype->CreateComponents(DestroyableComponent(newEntityId), SimplePhysicsComponent(newEntityId, 2)); + + // Try deleting elements + ASSERT_NO_THROW(baseArchetype->DeleteComponents(0)); + ASSERT_NO_THROW(baseArchetype->DeleteComponents(0)); + ASSERT_NO_THROW(baseArchetype->DeleteComponents(0)); // This is deleting one more entry than exists which should fail harmlessly +} + +/*TEST_F(ArchetypeTest, ReadFromArchetypeTest) { + //auto& simplePhysicsContainer = baseArchetype->Container(); + //auto& destroyableContainer = baseArchetype->Container(); + auto entitySystem = std::make_unique(); + + std::vector> tempEntity; // Vector of temporary entities (so they die when this test goes out of scope) + + LOG("Number of entries per vector: %d", 1000); + srand(time(NULL)); + for (auto i = 0; i < 1000; ++i) { + tempEntity.emplace_back(std::make_unique(rand() + i, GameDependenciesTest::info)); // Create a new entity + + const auto tempEntityId = tempEntity[i]->GetObjectID(); + entitySystem->CreateEntity(tempEntityId, DestroyableComponent(tempEntityId), SimplePhysicsComponent(tempEntityId, 2)); + } + + // Benchmarking + constexpr uint32_t nLoops = 100; //1E6; + auto begin = std::chrono::high_resolution_clock::now(); + for (auto i = 0; i < nLoops; ++i) { + for (const auto& destComp : destroyableContainer) { + ASSERT_NE(destComp.GetParent(), nullptr); + } + + for (const auto& simplePhysComp : simplePhysicsContainer) { + ASSERT_NE(simplePhysComp.GetParent(), nullptr); + } + } + auto end = std::chrono::high_resolution_clock::now(); + auto time = std::chrono::duration_cast(end - begin).count(); + LOG("Total time: %lld μs", time); + LOG("Time per loop: %lld μs", time / nLoops); +}*/ + +/*TEST_F(ArchetypeTest, AddEntityTest) { + // Create the archetypes + std::array, 3> tempArchetype; + tempArchetype[0] = std::make_unique>(1); + tempArchetype[1] = std::make_unique>(2); + tempArchetype[2] = std::make_unique>(3); + + // Add the matching types to the component type index + componentTypeIndex[std::type_index(typeid(SimplePhysicsComponent))] = { 1, 2 }; // TODO: USE EMPLACE + componentTypeIndex[std::type_index(typeid(DestroyableComponent))] = { 2, 3 }; // TODO: USE EMPLACE + + // Validate + for (auto& tempArc : tempArchetype) { + ASSERT_NE(tempArc.get(), nullptr); + } + + std::array, 3> tempEntity; // Array of temporary entities (so they die when this test goes out of scope) + for (auto i = 0; i < 3; ++i) { + tempEntity[i] = std::make_unique(i, GameDependenciesTest::info); + } + + // Get object IDs + const LWOOBJID entityOneId = tempEntity[0]->GetObjectID(); + const LWOOBJID entityTwoId = tempEntity[1]->GetObjectID(); + const LWOOBJID entityThreeId = tempEntity[2]->GetObjectID(); + + // Assert no duplicates + ASSERT_NE(entityOneId, entityTwoId); + ASSERT_NE(entityTwoId, entityThreeId); + ASSERT_NE(entityOneId, entityThreeId); + + // Set component ids + uint32_t entitySPCompOneId = 10; + uint32_t entitySPCompTwoId = 11; + + // Create references to the unique archetype ptrs + auto& archetypeOne = static_cast&>(*tempArchetype[0].get()); + auto& archetypeTwo = static_cast&>(*tempArchetype[1].get()); + auto& archetypeThree = static_cast&>(*tempArchetype[2].get()); + + archetypeOne.CreateComponents(SimplePhysicsComponent(entityOneId, entitySPCompOneId)); + archetypeTwo.CreateComponents(DestroyableComponent(entityTwoId), SimplePhysicsComponent(entityTwoId, entitySPCompTwoId)); + archetypeThree.CreateComponents(DestroyableComponent(entityThreeId)); + + // Manually create the records + auto recordOne = ArchetypeRecord{ tempArchetype[0].get(), 0 }; + auto recordTwo = ArchetypeRecord{ tempArchetype[1].get(), 0 }; + auto recordThree = ArchetypeRecord{ tempArchetype[2].get(), 0 }; + + // Manually create the corresponding pointers in the entity index + entityIndex.insert({ entityOneId, ArchetypeRecord{ tempArchetype[0].get(), 0 }; }); + + entityIndex.insert({ entityOneId, recordOne }); + entityIndex.insert({ entityTwoId, recordTwo }); + entityIndex.insert({ entityThreeId, recordThree }); + + // Check that the newly-created pointers point to the same memory address as the pointers + ASSERT_NE(entityIndex[entityOneId].archetype, nullptr); + ASSERT_EQ(entityIndex[entityOneId].archetype, &archetypeOne); + ASSERT_EQ(entityIndex[entityTwoId].archetype, &archetypeTwo); + ASSERT_EQ(entityIndex[entityThreeId].archetype, &archetypeThree); + + auto* const gottenComponent = EntitySystem::GetComponent(entityOneId); + ASSERT_EQ(gottenComponent->GetParent()->GetObjectID(), entityOneId); + // Find the archetype containing entity one + // Find the indice within the archetype containing entity one + + ASSERT_FALSE(EntitySystem::HasComponent(entityOneId)); + ASSERT_TRUE(EntitySystem::HasComponent(entityOneId)); +} + +TEST_F(ArchetypeTest, GetArchetypeTest) { + auto& archetype = EntitySystem::GetArchetype(); + + const auto baseEntityId = baseEntity->GetObjectID(); + archetype.CreateComponents(DestroyableComponent(baseEntityId), SimplePhysicsComponent(baseEntityId, 2)); + + auto& sameArchetype = EntitySystem::GetArchetype(); + auto sameEntityId = sameArchetype.GetComponent(0).GetParent()->GetObjectID(); + ASSERT_EQ(sameEntityId, baseEntityId); +} + +TEST_F(ArchetypeTest, CreateArchetypesTest) { + EntitySystem::CreateArchetypes(); + + const auto baseEntityId = baseEntity->GetObjectID(); + EntitySystem::CreateComponents(baseEntityId, DestroyableComponent(baseEntityId), SimplePhysicsComponent(baseEntityId, 12)); + + const auto gottenEntityId = EntitySystem::GetArchetype().GetComponent(0).GetParent()->GetObjectID(); + ASSERT_EQ(gottenEntityId, baseEntityId); +}*/ + +TEST_F(ArchetypeTest, MoveArchetypeBaseTest) { + // Insert an entry into the base archetype and set one trait for each + const auto baseEntityId = baseEntity->GetObjectID(); + baseArchetype->CreateComponents(DestroyableComponent(baseEntityId), SimplePhysicsComponent(baseEntityId, 2)); + baseArchetype->Container::entries[0].SetMaxHealth(30); + baseArchetype->Container::entries[0].SetPosition(NiPoint3(1.0f, 2.0f, 3.0f)); + + // Move the archetype and compare the entry results, as well as checking the original is deleted + std::unique_ptr movedArchetype = std::move(baseArchetype); + ASSERT_FLOAT_EQ(movedArchetype->GetContainer()[0].GetMaxHealth(), 30); + ASSERT_EQ(movedArchetype->GetContainer()[0].GetPosition(), NiPoint3(1.0f, 2.0f, 3.0f)); + ASSERT_EQ(baseArchetype.get(), nullptr); +} + +TEST_F(ArchetypeTest, CreateEntityTest) { + auto entitySystem = std::make_unique(); + + const auto baseEntityId = baseEntity->GetObjectID(); + const auto newEntityId = newEntity->GetObjectID(); + + ASSERT_NO_FATAL_FAILURE(entitySystem->CreateEntity(baseEntityId, DestroyableComponent(baseEntityId), SimplePhysicsComponent(baseEntityId, 2))); +} + +TEST_F(ArchetypeTest, HasComponentTest) { + auto entitySystem = std::make_unique(); + + const auto baseEntityId = baseEntity->GetObjectID(); + const auto newEntityId = newEntity->GetObjectID(); + + entitySystem->CreateEntity(baseEntityId, DestroyableComponent(baseEntityId), SimplePhysicsComponent(baseEntityId, 2)); + + ASSERT_TRUE(entitySystem->HasComponent(baseEntityId)); + ASSERT_TRUE(entitySystem->HasComponent(baseEntityId)); + ASSERT_FALSE(entitySystem->HasComponent(baseEntityId)); +} + +TEST_F(ArchetypeTest, GetComponentTest) { + auto entitySystem = std::make_unique(); + + const auto baseEntityId = baseEntity->GetObjectID(); + const auto newEntityId = newEntity->GetObjectID(); + + entitySystem->CreateEntity(baseEntityId, DestroyableComponent(baseEntityId), SimplePhysicsComponent(baseEntityId, 2)); + + ASSERT_NE(entitySystem->GetComponent(baseEntityId), nullptr); + ASSERT_NE(entitySystem->GetComponent(baseEntityId), nullptr); + ASSERT_EQ(entitySystem->GetComponent(baseEntityId), nullptr); +} + +namespace { + template + struct TestContainerVisitor { + void operator()(auto&& archetype) { + using ArchetypeType = std::remove_pointer_t>; // Needed to fix a MacOS issue + + if constexpr (!ArchetypeType::template HasComponent()) return; + else for (auto& destComp : archetype->template Container()) { + const auto randNum = rand(); + destComp.SetArmor(randNum); + ASSERT_EQ(randNum, destComp.GetArmor()); + } + } + }; + + template + struct ContainerVisitor { + Container::storage_type* const operator()(auto&& archetype) { + using ArchetypeType = std::remove_pointer_t>; // Needed to fix a MacOS issue + + if constexpr (!ArchetypeType::template HasComponent()) return nullptr; + else return &archetype->template Container::entries; + } + }; +} + +TEST_F(ArchetypeTest, IterateOverArchetypesTest) { + auto entitySystem = std::make_unique(); + + const auto baseEntityId = baseEntity->GetObjectID(); + entitySystem->CreateEntity(baseEntityId, DestroyableComponent(baseEntityId), SimplePhysicsComponent(baseEntityId, 2)); + + const auto newEntityId = newEntity->GetObjectID(); + entitySystem->CreateEntity(newEntityId, DestroyableComponent(newEntityId), SimplePhysicsComponent(newEntityId, 1)); + + const auto it = std::ranges::find_if(entitySystem->m_Archetypes, [](auto&& archetypeVariantPtr) { + return std::visit([](auto&& archetype) { + return archetype->template HasComponent(); + }, archetypeVariantPtr); + }); + ASSERT_FALSE(it == entitySystem->m_Archetypes.end()); + +// ------------------- UPDATE LOOP TEST -------------- + std::vector> tempEntity; // Vector of temporary entities (so they die when this test goes out of scope) + + constexpr int32_t numEntries = 1000000; + + LOG("Number of entries per vector: %d", numEntries); + srand(time(NULL)); + for (auto i = 0; i < numEntries; ++i) { + tempEntity.emplace_back(std::make_unique(rand() + i, GameDependenciesTest::info)); // Create a new entity + + const auto tempEntityId = tempEntity[i]->GetObjectID(); + entitySystem->CreateEntity(tempEntityId, DestroyableComponent(tempEntityId), SimplePhysicsComponent(tempEntityId, 2)); + } + + //ContainerVisitor + const auto& archetypes = entitySystem->m_Archetypes; + + /*for (auto& archetypeVariantPtr : archetypes) { + std::visit(TestContainerVisitor(), archetypeVariantPtr); // Does the update loop test + }*/ + + for (const auto& archetypeVariantPtr : archetypes) { + auto&& destCompContainer = std::visit(ContainerVisitor(), archetypeVariantPtr); + if (!destCompContainer) continue; + + for (auto&& destComp : *destCompContainer) { + const auto randNum = rand(); + destComp.SetArmor(randNum); + ASSERT_EQ(randNum, destComp.GetArmor()); + } + } + // TODO: The outer foor loop can be simplified a little bit by grabbing the + // archetypes known to contain the correct component types ahead of time + + // Expanded version + /*for (auto it = archetypes.begin(), end = archetypes.end(); it != end; ++it) { + const auto& archetypeVariantPtr = *it; + + std::vector&& destCompCont = std::visit([](auto&& archetype){ return archetype->template Container(); }, archetypeVariantPtr); + + for (auto it = destCompCont.begin(), end = destCompCont.end(); it != end; ++it) { + const auto& destComp = *it; + + // Magic + } + }*/ + + // Notation I WANT + /*for (auto& archetype : archetypes) { + for (auto& destCompCont : archetype) { + for (auto& destComp : destCompCont) { + // MAGIC + } + } + }*/ + + ASSERT_NO_THROW(entitySystem->GetComponent(baseEntityId)->GetArmor()); + ASSERT_NO_THROW(entitySystem->GetComponent(newEntityId)->GetArmor()); +}; diff --git a/tests/dGameTests/dEntitiesTests/CMakeLists.txt b/tests/dGameTests/dEntitiesTests/CMakeLists.txt new file mode 100644 index 000000000..081c5ca40 --- /dev/null +++ b/tests/dGameTests/dEntitiesTests/CMakeLists.txt @@ -0,0 +1,10 @@ +set(DENTITIES_TESTS + "ArchetypeTests.cpp" +) + +# Get the folder name and prepend it to the files above +get_filename_component(thisFolderName ${CMAKE_CURRENT_SOURCE_DIR} NAME) +list(TRANSFORM DENTITIES_TESTS PREPEND "${thisFolderName}/") + +# Export to parent scope +set(DENTITIES_TESTS ${DENTITIES_TESTS} PARENT_SCOPE)