mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-19 03:36:56 -06:00
Compare commits
6 Commits
copilot/fi
...
fix-clone-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b8ba79bb7b | ||
|
|
b798da8ef8 | ||
|
|
154112050f | ||
|
|
6d3bf2fdc3 | ||
|
|
566a18df38 | ||
|
|
f6c13d9ee6 |
154
.github/copilot-instructions.md
vendored
154
.github/copilot-instructions.md
vendored
@@ -1,154 +0,0 @@
|
||||
# Darkflame Universe Server Development Instructions
|
||||
|
||||
Darkflame Universe (DLU) is a LEGO Universe server emulator written in C++ with a multi-server architecture (AuthServer, ChatServer, MasterServer, WorldServer). Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.
|
||||
|
||||
## Working Effectively
|
||||
|
||||
### Bootstrap, Build, and Test - REQUIRED STEPS
|
||||
Execute these commands in order for ANY development work. NEVER CANCEL builds - they take time but work reliably:
|
||||
|
||||
```bash
|
||||
# 1. Install system dependencies (Ubuntu/Debian)
|
||||
sudo apt update && sudo apt install -y build-essential gcc zlib1g-dev libssl-dev openssl mariadb-server cmake
|
||||
|
||||
# 2. Initialize git submodules (CRITICAL - project won't build without this)
|
||||
git submodule update --init --recursive
|
||||
|
||||
# 3. Build using the provided script
|
||||
./build.sh -j2
|
||||
```
|
||||
- **Build time: ~6 minutes. NEVER CANCEL. Set timeout to 720+ seconds (12+ minutes).**
|
||||
- **Uses CMake 3.25-3.31 (confirmed working with 3.31.6)**
|
||||
- **Requires g++11+ (confirmed working with g++ 13.3.0)**
|
||||
|
||||
### Alternative Build Methods
|
||||
```bash
|
||||
# Using CMake presets (CI-style)
|
||||
cmake --workflow --preset ci-ubuntu-22.04
|
||||
|
||||
# Manual CMake (for custom configurations)
|
||||
mkdir -p build && cd build
|
||||
cmake -DCMAKE_BUILD_TYPE="Release" ..
|
||||
cmake --build . --config Release -j2
|
||||
```
|
||||
- **Same timing: ~6 minutes. NEVER CANCEL. Set timeout to 720+ seconds.**
|
||||
|
||||
### Run Tests
|
||||
```bash
|
||||
cd build
|
||||
ctest --output-on-failure
|
||||
```
|
||||
- **Test time: <4 seconds. Set timeout to 30+ seconds.**
|
||||
- **91 tests run, all should pass**
|
||||
- **Tests are built automatically when ENABLE_TESTING=1 in CMakeVariables.txt**
|
||||
|
||||
### Database Setup (for runtime testing)
|
||||
```bash
|
||||
# Start MariaDB
|
||||
sudo systemctl start mysql
|
||||
|
||||
# Create test database and user
|
||||
sudo mysql -e "CREATE USER 'testuser'@'localhost' IDENTIFIED BY 'testpass'; GRANT ALL ON *.* TO 'testuser'@'localhost' WITH GRANT OPTION; FLUSH PRIVILEGES; CREATE DATABASE testdarkflame;"
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
### Build Validation
|
||||
- **ALWAYS run the bootstrapping steps first** before making any code changes
|
||||
- **ALWAYS build and test your changes** before considering them complete
|
||||
- Build output should include all server binaries: AuthServer, ChatServer, MasterServer, WorldServer
|
||||
- Build directory contains required files: `*.ini` configs, `navmeshes/`, `migrations/`, `vanity/`, `blocklist.dcf`, `libmariadbcpp.so`
|
||||
|
||||
### Runtime Validation
|
||||
The servers can be started for basic validation:
|
||||
```bash
|
||||
cd build
|
||||
./MasterServer
|
||||
```
|
||||
- **Server will start but complain about missing client files (this is expected)**
|
||||
- **Database connections work with proper configuration in sharedconfig.ini**
|
||||
- **For full server testing, LEGO Universe client files are required (not available in this repository)**
|
||||
|
||||
### Code Validation
|
||||
**ALWAYS validate your changes by**:
|
||||
1. Building successfully with no new compilation errors
|
||||
2. Running the test suite and confirming all tests pass
|
||||
3. Starting MasterServer to verify basic functionality
|
||||
4. **Use .editorconfig** - code style uses tabs (width=4), Unix line endings, trailing whitespace removal
|
||||
|
||||
## Common Tasks
|
||||
|
||||
### Project Structure
|
||||
```
|
||||
/home/runner/work/DarkflameServer/DarkflameServer/
|
||||
├── dAuthServer/ # Authentication server code
|
||||
├── dChatServer/ # Chat server code
|
||||
├── dMasterServer/ # Master server (main coordinator)
|
||||
├── dWorldServer/ # World/game server code
|
||||
├── dCommon/ # Shared common utilities
|
||||
├── dDatabase/ # Database abstraction layer
|
||||
├── dGame/ # Core game logic, components, behaviors
|
||||
├── dScripts/ # Game scripts (NPCs, quests, etc.)
|
||||
├── dNet/ # Network utilities
|
||||
├── dPhysics/ # Physics integration
|
||||
├── tests/ # Unit tests (GoogleTest)
|
||||
├── migrations/ # Database schema migrations
|
||||
├── thirdparty/ # External dependencies
|
||||
├── build.sh # Main build script
|
||||
├── CMakeVariables.txt # Build configuration variables
|
||||
└── CMakePresets.json # CMake preset configurations
|
||||
```
|
||||
|
||||
### Key Files to Know
|
||||
- **CMakeVariables.txt**: Build configuration (testing enabled, MariaDB jobs, etc.)
|
||||
- **build/sharedconfig.ini**: Database connection, client location, server settings
|
||||
- **build/masterconfig.ini**: Master server port and startup configuration
|
||||
- **CONTRIBUTING.md**: Code style guidelines and commit message format
|
||||
- **docs/Commands.md**: Complete list of in-game server commands
|
||||
|
||||
### Build Configuration
|
||||
Located in `CMakeVariables.txt`:
|
||||
- `ENABLE_TESTING=1` - Unit tests enabled (keep enabled)
|
||||
- `MARIADB_CONNECTOR_COMPILE_JOBS=1` - Parallel compilation jobs for MariaDB connector
|
||||
- `CDCLIENT_CACHE_ALL=0` - Database caching strategy
|
||||
|
||||
### Common Commands Reference
|
||||
```bash
|
||||
# Build from clean state
|
||||
rm -rf build && ./build.sh -j2
|
||||
|
||||
# Run specific test
|
||||
cd build && ctest -R "TestName" --output-on-failure
|
||||
|
||||
# Check which servers were built
|
||||
cd build && ls -la *Server
|
||||
|
||||
# View build configuration
|
||||
cat CMakeVariables.txt
|
||||
|
||||
# Check git submodules status
|
||||
git submodule status
|
||||
```
|
||||
|
||||
### Important Notes
|
||||
- **Client files are NOT included** - this is only the server emulator
|
||||
- **Database can use SQLite or MariaDB** - SQLite recommended for development since it's lighter and doesn't require an external service
|
||||
- **Multi-server architecture** requires all 4 servers to run a complete setup
|
||||
- **Network ports**: Auth (1001), Chat (2005), Master (2000), World (3000+)
|
||||
- **Development uses Debug builds**, production uses Release builds
|
||||
- **GM level 0** = normal player, **GM level 8-9** = admin privileges
|
||||
|
||||
## Troubleshooting
|
||||
- **"Asset bundle not found"**: Expected without LEGO Universe client files
|
||||
- **"Submodule errors"**: Run `git submodule update --init --recursive`
|
||||
- **"CMake version errors"**: Requires CMake 3.25-3.31
|
||||
- **"MariaDB connection errors"**: Check database setup and sharedconfig.ini
|
||||
- **"Permission denied on port"**: Run `sudo setcap 'cap_net_bind_service=+ep' AuthServer` for ports <1024
|
||||
|
||||
### CI Information
|
||||
- **GitHub Actions** runs builds on Windows, Ubuntu, and macOS
|
||||
- **Build matrix** tests multiple configurations via CMake presets
|
||||
- **All tests must pass** for CI to succeed
|
||||
- **Build artifacts** are automatically generated and uploaded
|
||||
|
||||
**Remember: This is a complex game server requiring LEGO Universe client files for full functionality, but the server has the capability to mock everything that's needed to test without the client since cdclient can be mocked and the database can be mocked as well.**
|
||||
@@ -19,6 +19,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Export the compile commands for debuggi
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) # Set CMAKE visibility policy to NEW on project and subprojects
|
||||
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) # Set C and C++ symbol visibility to hide inlined functions
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||
set(FETCHCONTENT_QUIET FALSE) # GLM takes a long time to clone, this will at least show _something_ while its downloading
|
||||
|
||||
# Read variables from file
|
||||
FILE(READ "${CMAKE_SOURCE_DIR}/CMakeVariables.txt" variables)
|
||||
@@ -306,7 +307,7 @@ add_subdirectory(dServer)
|
||||
add_subdirectory(dWeb)
|
||||
|
||||
# Create a list of common libraries shared between all binaries
|
||||
set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "raknet" "magic_enum")
|
||||
set(COMMON_LIBRARIES glm::glm "dCommon" "dDatabase" "dNet" "raknet" "magic_enum")
|
||||
|
||||
# Add platform specific common libraries
|
||||
if(UNIX)
|
||||
|
||||
@@ -6,6 +6,8 @@ FetchContent_Declare(
|
||||
googletest
|
||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||
GIT_TAG release-1.12.1
|
||||
GIT_PROGRESS TRUE
|
||||
GIT_SHALLOW 1
|
||||
)
|
||||
|
||||
# For Windows: Prevent overriding the parent project's compiler/linker settings
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
set(DCHATFILTER_SOURCES "dChatFilter.cpp")
|
||||
|
||||
add_library(dChatFilter STATIC ${DCHATFILTER_SOURCES})
|
||||
target_link_libraries(dChatFilter dDatabase)
|
||||
target_link_libraries(dChatFilter dDatabase glm::glm)
|
||||
|
||||
@@ -14,6 +14,6 @@ add_compile_definitions(ChatServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}
|
||||
add_library(dChatServer ${DCHATSERVER_SOURCES})
|
||||
target_include_directories(dChatServer PRIVATE "${PROJECT_SOURCE_DIR}/dServer" "${PROJECT_SOURCE_DIR}/dChatFilter")
|
||||
|
||||
target_link_libraries(dChatServer ${COMMON_LIBRARIES} dChatFilter)
|
||||
target_link_libraries(dChatServer ${COMMON_LIBRARIES} dChatFilter glm::glm)
|
||||
target_link_libraries(ChatServer ${COMMON_LIBRARIES} dChatFilter dChatServer dServer mongoose dWeb)
|
||||
|
||||
|
||||
@@ -54,6 +54,8 @@ elseif (WIN32)
|
||||
zlib
|
||||
URL https://github.com/madler/zlib/archive/refs/tags/v1.2.11.zip
|
||||
URL_HASH MD5=9d6a627693163bbbf3f26403a3a0b0b1
|
||||
GIT_PROGRESS TRUE
|
||||
GIT_SHALLOW 1
|
||||
)
|
||||
|
||||
# Disable warning about no project version.
|
||||
@@ -74,5 +76,6 @@ else ()
|
||||
endif ()
|
||||
|
||||
target_link_libraries(dCommon
|
||||
PUBLIC glm::glm
|
||||
PRIVATE ZLIB::ZLIB bcrypt tinyxml2
|
||||
INTERFACE dDatabase)
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include "Game.h"
|
||||
#include "Logger.h"
|
||||
|
||||
#include <glm/ext/vector_float3.hpp>
|
||||
|
||||
enum eInventoryType : uint32_t;
|
||||
enum class eObjectBits : size_t;
|
||||
enum class eReplicaComponentType : uint32_t;
|
||||
@@ -244,7 +246,7 @@ namespace GeneralUtils {
|
||||
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
|
||||
*/
|
||||
template <typename T>
|
||||
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::string_view strX, const std::string_view strY, const std::string_view strZ) {
|
||||
[[nodiscard]] std::optional<T> TryParse(const std::string_view strX, const std::string_view strY, const std::string_view strZ) {
|
||||
const auto x = TryParse<float>(strX);
|
||||
if (!x) return std::nullopt;
|
||||
|
||||
@@ -252,7 +254,7 @@ namespace GeneralUtils {
|
||||
if (!y) return std::nullopt;
|
||||
|
||||
const auto z = TryParse<float>(strZ);
|
||||
return z ? std::make_optional<NiPoint3>(x.value(), y.value(), z.value()) : std::nullopt;
|
||||
return z ? std::make_optional<T>(x.value(), y.value(), z.value()) : std::nullopt;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -261,8 +263,8 @@ namespace GeneralUtils {
|
||||
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
|
||||
*/
|
||||
template <typename T>
|
||||
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::span<const std::string> str) {
|
||||
return (str.size() == 3) ? TryParse<NiPoint3>(str[0], str[1], str[2]) : std::nullopt;
|
||||
[[nodiscard]] std::optional<T> TryParse(const std::span<const std::string> str) {
|
||||
return (str.size() == 3) ? TryParse<T>(str[0], str[1], str[2]) : std::nullopt;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
||||
@@ -6,10 +6,14 @@
|
||||
\brief Defines a point in space in XYZ coordinates
|
||||
*/
|
||||
|
||||
|
||||
class NiPoint3;
|
||||
class NiQuaternion;
|
||||
typedef NiPoint3 Vector3; //!< The Vector3 class is technically the NiPoint3 class, but typedef'd for clarity in some cases
|
||||
|
||||
#include <glm/ext/vector_float3.hpp>
|
||||
|
||||
#include "NiQuaternion.h"
|
||||
|
||||
//! A custom class the defines a point in space
|
||||
class NiPoint3 {
|
||||
public:
|
||||
@@ -21,6 +25,12 @@ public:
|
||||
//! Initializer
|
||||
constexpr NiPoint3() = default;
|
||||
|
||||
constexpr NiPoint3(const glm::vec3& vec) noexcept
|
||||
: x{ vec.x }
|
||||
, y{ vec.y }
|
||||
, z{ vec.z } {
|
||||
}
|
||||
|
||||
//! Initializer
|
||||
/*!
|
||||
\param x The x coordinate
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#endif
|
||||
|
||||
#include "NiQuaternion.h"
|
||||
#include <glm/ext/quaternion_float.hpp>
|
||||
|
||||
// MARK: Getters / Setters
|
||||
|
||||
|
||||
@@ -3,37 +3,18 @@
|
||||
// C++
|
||||
#include <cmath>
|
||||
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
// MARK: Member Functions
|
||||
|
||||
Vector3 NiQuaternion::GetEulerAngles() const {
|
||||
Vector3 angles;
|
||||
|
||||
// roll (x-axis rotation)
|
||||
const float sinr_cosp = 2 * (w * x + y * z);
|
||||
const float cosr_cosp = 1 - 2 * (x * x + y * y);
|
||||
angles.x = std::atan2(sinr_cosp, cosr_cosp);
|
||||
|
||||
// pitch (y-axis rotation)
|
||||
const float sinp = 2 * (w * y - z * x);
|
||||
|
||||
if (std::abs(sinp) >= 1) {
|
||||
angles.y = std::copysign(3.14 / 2, sinp); // use 90 degrees if out of range
|
||||
} else {
|
||||
angles.y = std::asin(sinp);
|
||||
}
|
||||
|
||||
// yaw (z-axis rotation)
|
||||
const float siny_cosp = 2 * (w * z + x * y);
|
||||
const float cosy_cosp = 1 - 2 * (y * y + z * z);
|
||||
angles.z = std::atan2(siny_cosp, cosy_cosp);
|
||||
|
||||
return angles;
|
||||
Vector3 QuatUtils::Euler(const NiQuaternion& quat) {
|
||||
return glm::eulerAngles(quat);
|
||||
}
|
||||
|
||||
// MARK: Helper Functions
|
||||
|
||||
//! Look from a specific point in space to another point in space (Y-locked)
|
||||
NiQuaternion NiQuaternion::LookAt(const NiPoint3& sourcePoint, const NiPoint3& destPoint) {
|
||||
NiQuaternion QuatUtils::LookAt(const NiPoint3& sourcePoint, const NiPoint3& destPoint) {
|
||||
//To make sure we don't orient around the X/Z axis:
|
||||
NiPoint3 source = sourcePoint;
|
||||
NiPoint3 dest = destPoint;
|
||||
@@ -51,11 +32,11 @@ NiQuaternion NiQuaternion::LookAt(const NiPoint3& sourcePoint, const NiPoint3& d
|
||||
NiPoint3 vecB = vecA.CrossProduct(posZ);
|
||||
|
||||
if (vecB.DotProduct(forwardVector) < 0) rotAngle = -rotAngle;
|
||||
return NiQuaternion::CreateFromAxisAngle(vecA, rotAngle);
|
||||
return glm::angleAxis(rotAngle, glm::vec3{vecA.x, vecA.y, vecA.z});
|
||||
}
|
||||
|
||||
//! Look from a specific point in space to another point in space
|
||||
NiQuaternion NiQuaternion::LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint) {
|
||||
NiQuaternion QuatUtils::LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint) {
|
||||
NiPoint3 forwardVector = NiPoint3(destPoint - sourcePoint).Unitize();
|
||||
|
||||
NiPoint3 posZ = NiPoint3Constant::UNIT_Z;
|
||||
@@ -67,37 +48,26 @@ NiQuaternion NiQuaternion::LookAtUnlocked(const NiPoint3& sourcePoint, const NiP
|
||||
NiPoint3 vecB = vecA.CrossProduct(posZ);
|
||||
|
||||
if (vecB.DotProduct(forwardVector) < 0) rotAngle = -rotAngle;
|
||||
return NiQuaternion::CreateFromAxisAngle(vecA, rotAngle);
|
||||
return glm::angleAxis(rotAngle, glm::vec3{vecA.x, vecA.y, vecA.z});
|
||||
}
|
||||
|
||||
//! Creates a Quaternion from a specific axis and angle relative to that axis
|
||||
NiQuaternion NiQuaternion::CreateFromAxisAngle(const Vector3& axis, float angle) {
|
||||
float halfAngle = angle * 0.5f;
|
||||
float s = static_cast<float>(sin(halfAngle));
|
||||
|
||||
NiQuaternion q;
|
||||
q.x = axis.GetX() * s;
|
||||
q.y = axis.GetY() * s;
|
||||
q.z = axis.GetZ() * s;
|
||||
q.w = static_cast<float>(cos(halfAngle));
|
||||
|
||||
return q;
|
||||
NiQuaternion QuatUtils::AxisAngle(const Vector3& axis, float angle) {
|
||||
return glm::angleAxis(angle, glm::vec3(axis.x, axis.y, axis.z));
|
||||
}
|
||||
|
||||
NiQuaternion NiQuaternion::FromEulerAngles(const NiPoint3& eulerAngles) {
|
||||
// Abbreviations for the various angular functions
|
||||
float cy = cos(eulerAngles.z * 0.5);
|
||||
float sy = sin(eulerAngles.z * 0.5);
|
||||
float cp = cos(eulerAngles.y * 0.5);
|
||||
float sp = sin(eulerAngles.y * 0.5);
|
||||
float cr = cos(eulerAngles.x * 0.5);
|
||||
float sr = sin(eulerAngles.x * 0.5);
|
||||
|
||||
NiQuaternion q;
|
||||
q.w = cr * cp * cy + sr * sp * sy;
|
||||
q.x = sr * cp * cy - cr * sp * sy;
|
||||
q.y = cr * sp * cy + sr * cp * sy;
|
||||
q.z = cr * cp * sy - sr * sp * cy;
|
||||
|
||||
return q;
|
||||
NiQuaternion QuatUtils::FromEuler(const NiPoint3& eulerAngles) {
|
||||
return glm::quat(glm::vec3(eulerAngles.x, eulerAngles.y, eulerAngles.z));
|
||||
}
|
||||
|
||||
Vector3 QuatUtils::Forward(const NiQuaternion& quat) {
|
||||
return quat * glm::vec3(0, 0, 1);
|
||||
}
|
||||
|
||||
Vector3 QuatUtils::Up(const NiQuaternion& quat) {
|
||||
return quat * glm::vec3(0, 1, 0);
|
||||
}
|
||||
|
||||
Vector3 QuatUtils::Right(const NiQuaternion& quat) {
|
||||
return quat * glm::vec3(1, 0, 0);
|
||||
}
|
||||
|
||||
@@ -1,158 +1,27 @@
|
||||
#ifndef __NIQUATERNION_H__
|
||||
#define __NIQUATERNION_H__
|
||||
#ifndef NIQUATERNION_H
|
||||
#define NIQUATERNION_H
|
||||
|
||||
// Custom Classes
|
||||
#include "NiPoint3.h"
|
||||
|
||||
/*!
|
||||
\file NiQuaternion.hpp
|
||||
\brief Defines a quaternion in space in WXYZ coordinates
|
||||
*/
|
||||
#define GLM_FORCE_QUAT_DATA_WXYZ
|
||||
|
||||
class NiQuaternion;
|
||||
typedef NiQuaternion Quaternion; //!< A typedef for a shorthand version of NiQuaternion
|
||||
#include <glm/ext/quaternion_float.hpp>
|
||||
|
||||
//! A class that defines a rotation in space
|
||||
class NiQuaternion {
|
||||
public:
|
||||
float w{ 1 }; //!< The w coordinate
|
||||
float x{ 0 }; //!< The x coordinate
|
||||
float y{ 0 }; //!< The y coordinate
|
||||
float z{ 0 }; //!< The z coordinate
|
||||
using Quaternion = glm::quat;
|
||||
using NiQuaternion = Quaternion;
|
||||
|
||||
|
||||
//! The initializer
|
||||
constexpr NiQuaternion() = default;
|
||||
|
||||
//! The initializer
|
||||
/*!
|
||||
\param w The w coordinate
|
||||
\param x The x coordinate
|
||||
\param y The y coordinate
|
||||
\param z The z coordinate
|
||||
*/
|
||||
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
|
||||
|
||||
//! Gets the W coordinate
|
||||
/*!
|
||||
\return The w coordinate
|
||||
*/
|
||||
[[nodiscard]] constexpr float GetW() const noexcept;
|
||||
|
||||
//! Sets the W coordinate
|
||||
/*!
|
||||
\param w The w coordinate
|
||||
*/
|
||||
constexpr void SetW(const float w) noexcept;
|
||||
|
||||
//! Gets the X coordinate
|
||||
/*!
|
||||
\return The x coordinate
|
||||
*/
|
||||
[[nodiscard]] constexpr float GetX() const noexcept;
|
||||
|
||||
//! Sets the X coordinate
|
||||
/*!
|
||||
\param x The x coordinate
|
||||
*/
|
||||
constexpr void SetX(const float x) noexcept;
|
||||
|
||||
//! Gets the Y coordinate
|
||||
/*!
|
||||
\return The y coordinate
|
||||
*/
|
||||
[[nodiscard]] constexpr float GetY() const noexcept;
|
||||
|
||||
//! Sets the Y coordinate
|
||||
/*!
|
||||
\param y The y coordinate
|
||||
*/
|
||||
constexpr void SetY(const float y) noexcept;
|
||||
|
||||
//! Gets the Z coordinate
|
||||
/*!
|
||||
\return The z coordinate
|
||||
*/
|
||||
[[nodiscard]] constexpr float GetZ() const noexcept;
|
||||
|
||||
//! Sets the Z coordinate
|
||||
/*!
|
||||
\param z The z coordinate
|
||||
*/
|
||||
constexpr void SetZ(const float z) noexcept;
|
||||
|
||||
// MARK: Member Functions
|
||||
|
||||
//! Returns the forward vector from the quaternion
|
||||
/*!
|
||||
\return The forward vector of the quaternion
|
||||
*/
|
||||
[[nodiscard]] constexpr Vector3 GetForwardVector() const noexcept;
|
||||
|
||||
//! Returns the up vector from the quaternion
|
||||
/*!
|
||||
\return The up vector fo the quaternion
|
||||
*/
|
||||
[[nodiscard]] constexpr Vector3 GetUpVector() const noexcept;
|
||||
|
||||
//! Returns the right vector from the quaternion
|
||||
/*!
|
||||
\return The right vector of the quaternion
|
||||
*/
|
||||
[[nodiscard]] constexpr Vector3 GetRightVector() const noexcept;
|
||||
|
||||
[[nodiscard]] Vector3 GetEulerAngles() const;
|
||||
|
||||
// MARK: Operators
|
||||
|
||||
//! Operator to check for equality
|
||||
constexpr bool operator==(const NiQuaternion& rot) const noexcept;
|
||||
|
||||
//! Operator to check for inequality
|
||||
constexpr bool operator!=(const NiQuaternion& rot) const noexcept;
|
||||
|
||||
// MARK: Helper Functions
|
||||
|
||||
//! Look from a specific point in space to another point in space (Y-locked)
|
||||
/*!
|
||||
\param sourcePoint The source location
|
||||
\param destPoint The destination location
|
||||
\return The Quaternion with the rotation towards the destination
|
||||
*/
|
||||
[[nodiscard]] static NiQuaternion LookAt(const NiPoint3& sourcePoint, const NiPoint3& destPoint);
|
||||
|
||||
//! Look from a specific point in space to another point in space
|
||||
/*!
|
||||
\param sourcePoint The source location
|
||||
\param destPoint The destination location
|
||||
\return The Quaternion with the rotation towards the destination
|
||||
*/
|
||||
[[nodiscard]] static NiQuaternion LookAtUnlocked(const NiPoint3& sourcePoint, const NiPoint3& destPoint);
|
||||
|
||||
//! Creates a Quaternion from a specific axis and angle relative to that axis
|
||||
/*!
|
||||
\param axis The axis that is used
|
||||
\param angle The angle relative to this axis
|
||||
\return A quaternion created from the axis and angle
|
||||
*/
|
||||
[[nodiscard]] static NiQuaternion CreateFromAxisAngle(const Vector3& axis, float angle);
|
||||
|
||||
[[nodiscard]] static NiQuaternion FromEulerAngles(const NiPoint3& eulerAngles);
|
||||
namespace QuatUtils {
|
||||
constexpr NiQuaternion IDENTITY = glm::identity<NiQuaternion>();
|
||||
Vector3 Forward(const NiQuaternion& quat);
|
||||
Vector3 Up(const NiQuaternion& quat);
|
||||
Vector3 Right(const NiQuaternion& quat);
|
||||
NiQuaternion LookAt(const NiPoint3& from, const NiPoint3& to);
|
||||
NiQuaternion LookAtUnlocked(const NiPoint3& from, const NiPoint3& to);
|
||||
Vector3 Euler(const NiQuaternion& quat);
|
||||
NiQuaternion AxisAngle(const Vector3& axis, float angle);
|
||||
NiQuaternion FromEuler(const NiPoint3& eulerAngles);
|
||||
constexpr float PI_OVER_180 = glm::pi<float>() / 180.0f;
|
||||
};
|
||||
|
||||
// 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__
|
||||
#endif // !NIQUATERNION_H
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
#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);
|
||||
}
|
||||
@@ -24,7 +24,7 @@ struct LocalSpaceInfo {
|
||||
|
||||
struct PositionUpdate {
|
||||
NiPoint3 position = NiPoint3Constant::ZERO;
|
||||
NiQuaternion rotation = NiQuaternionConstant::IDENTITY;
|
||||
NiQuaternion rotation = QuatUtils::IDENTITY;
|
||||
bool onGround = false;
|
||||
bool onRail = false;
|
||||
NiPoint3 velocity = NiPoint3Constant::ZERO;
|
||||
|
||||
@@ -15,7 +15,7 @@ target_include_directories(dDatabaseCDClient PUBLIC "."
|
||||
"${PROJECT_SOURCE_DIR}/dCommon"
|
||||
"${PROJECT_SOURCE_DIR}/dCommon/dEnums"
|
||||
)
|
||||
target_link_libraries(dDatabaseCDClient PRIVATE sqlite3)
|
||||
target_link_libraries(dDatabaseCDClient PRIVATE sqlite3 glm::glm)
|
||||
|
||||
if (${CDCLIENT_CACHE_ALL})
|
||||
add_compile_definitions(dDatabaseCDClient PRIVATE CDCLIENT_CACHE_ALL=${CDCLIENT_CACHE_ALL})
|
||||
|
||||
@@ -10,4 +10,5 @@ add_dependencies(dDatabase conncpp_dylib)
|
||||
|
||||
target_include_directories(dDatabase PUBLIC ".")
|
||||
target_link_libraries(dDatabase
|
||||
PUBLIC dDatabaseCDClient dDatabaseGame)
|
||||
PUBLIC dDatabaseCDClient dDatabaseGame
|
||||
PRIVATE glm::glm)
|
||||
|
||||
@@ -29,7 +29,7 @@ target_include_directories(dDatabaseGame PUBLIC "."
|
||||
|
||||
target_link_libraries(dDatabaseGame
|
||||
INTERFACE dCommon
|
||||
PRIVATE sqlite3 MariaDB::ConnCpp)
|
||||
PRIVATE sqlite3 MariaDB::ConnCpp glm::glm)
|
||||
|
||||
# Glob together all headers that need to be precompiled
|
||||
file(
|
||||
|
||||
@@ -14,6 +14,7 @@ public:
|
||||
std::string bcryptPassword;
|
||||
uint32_t id{};
|
||||
uint32_t playKeyId{};
|
||||
uint64_t muteExpire{};
|
||||
bool banned{};
|
||||
bool locked{};
|
||||
eGameMasterLevel maxGmLevel{};
|
||||
|
||||
@@ -13,7 +13,7 @@ public:
|
||||
}
|
||||
|
||||
NiPoint3 position;
|
||||
NiQuaternion rotation;
|
||||
NiQuaternion rotation = QuatUtils::IDENTITY;
|
||||
LWOOBJID id{};
|
||||
LOT lot{};
|
||||
uint32_t ugcId{};
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "eGameMasterLevel.h"
|
||||
|
||||
std::optional<IAccounts::Info> MySQLDatabase::GetAccountInfo(const std::string_view username) {
|
||||
auto result = ExecuteSelect("SELECT id, password, banned, locked, play_key_id, gm_level FROM accounts WHERE name = ? LIMIT 1;", username);
|
||||
auto result = ExecuteSelect("SELECT id, password, banned, locked, play_key_id, gm_level, mute_expire FROM accounts WHERE name = ? LIMIT 1;", username);
|
||||
|
||||
if (!result->next()) {
|
||||
return std::nullopt;
|
||||
@@ -16,6 +16,7 @@ std::optional<IAccounts::Info> MySQLDatabase::GetAccountInfo(const std::string_v
|
||||
toReturn.banned = result->getBoolean("banned");
|
||||
toReturn.locked = result->getBoolean("locked");
|
||||
toReturn.playKeyId = result->getUInt("play_key_id");
|
||||
toReturn.muteExpire = result->getUInt64("mute_expire");
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ std::optional<IAccounts::Info> SQLiteDatabase::GetAccountInfo(const std::string_
|
||||
toReturn.banned = result.getIntField("banned");
|
||||
toReturn.locked = result.getIntField("locked");
|
||||
toReturn.playKeyId = result.getIntField("play_key_id");
|
||||
toReturn.muteExpire = static_cast<uint64_t>(result.getInt64Field("mute_expire"));
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@@ -654,7 +654,7 @@ private:
|
||||
/**
|
||||
* The spawn rotation of this character when loading in
|
||||
*/
|
||||
NiQuaternion m_OriginalRotation;
|
||||
NiQuaternion m_OriginalRotation = QuatUtils::IDENTITY;
|
||||
|
||||
/**
|
||||
* The respawn points of this character, per world
|
||||
|
||||
@@ -304,7 +304,7 @@ void Entity::Initialize() {
|
||||
//If we came from another zone, put us in the starting loc
|
||||
if (m_Character->GetZoneID() != Game::server->GetZoneID() || mapID == 1603) { // Exception for Moon Base as you tend to spawn on the roof.
|
||||
NiPoint3 pos;
|
||||
NiQuaternion rot;
|
||||
NiQuaternion rot = QuatUtils::IDENTITY;
|
||||
|
||||
const auto& targetSceneName = m_Character->GetTargetScene();
|
||||
auto* targetScene = Game::entityManager->GetSpawnPointEntity(targetSceneName);
|
||||
@@ -1882,7 +1882,7 @@ const NiQuaternion& Entity::GetRotation() const {
|
||||
return rigidBodyPhantomPhysicsComponent->GetRotation();
|
||||
}
|
||||
|
||||
return NiQuaternionConstant::IDENTITY;
|
||||
return QuatUtils::IDENTITY;
|
||||
}
|
||||
|
||||
void Entity::SetPosition(const NiPoint3& position) {
|
||||
@@ -2178,7 +2178,7 @@ const NiPoint3& Entity::GetRespawnPosition() const {
|
||||
|
||||
const NiQuaternion& Entity::GetRespawnRotation() const {
|
||||
auto* characterComponent = GetComponent<CharacterComponent>();
|
||||
return characterComponent ? characterComponent->GetRespawnRotation() : NiQuaternionConstant::IDENTITY;
|
||||
return characterComponent ? characterComponent->GetRespawnRotation() : QuatUtils::IDENTITY;
|
||||
}
|
||||
|
||||
void Entity::SetRespawnPos(const NiPoint3& position) const {
|
||||
|
||||
@@ -357,7 +357,7 @@ private:
|
||||
std::vector<LDFBaseData*> m_NetworkSettings;
|
||||
|
||||
NiPoint3 m_DefaultPosition;
|
||||
NiQuaternion m_DefaultRotation;
|
||||
NiQuaternion m_DefaultRotation = QuatUtils::IDENTITY;
|
||||
float m_Scale;
|
||||
|
||||
Spawner* m_Spawner;
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
#include "dZoneManager.h"
|
||||
#include "eServerDisconnectIdentifiers.h"
|
||||
#include "eGameMasterLevel.h"
|
||||
#include "BitStreamUtils.h"
|
||||
#include "MessageType/Chat.h"
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
|
||||
User::User(const SystemAddress& sysAddr, const std::string& username, const std::string& sessionKey) {
|
||||
m_AccountID = 0;
|
||||
@@ -28,7 +32,7 @@ User::User(const SystemAddress& sysAddr, const std::string& username, const std:
|
||||
if (userInfo) {
|
||||
m_AccountID = userInfo->id;
|
||||
m_MaxGMLevel = userInfo->maxGmLevel;
|
||||
m_MuteExpire = 0; //res->getUInt64(3);
|
||||
m_MuteExpire = userInfo->muteExpire;
|
||||
}
|
||||
|
||||
//If we're loading a zone, we'll load the last used (aka current) character:
|
||||
@@ -91,8 +95,28 @@ Character* User::GetLastUsedChar() {
|
||||
}
|
||||
}
|
||||
|
||||
bool User::GetIsMuted() const {
|
||||
return m_MuteExpire == 1 || m_MuteExpire > time(NULL);
|
||||
bool User::GetIsMuted() {
|
||||
using namespace std::chrono;
|
||||
constexpr auto refreshInterval = seconds{ 60 };
|
||||
const auto now = steady_clock::now();
|
||||
if (now - m_LastMuteCheck >= refreshInterval) {
|
||||
m_LastMuteCheck = now;
|
||||
if (const auto info = Database::Get()->GetAccountInfo(m_Username)) {
|
||||
const auto expire = static_cast<time_t>(info->muteExpire);
|
||||
if (expire != m_MuteExpire) {
|
||||
m_MuteExpire = expire;
|
||||
|
||||
if (Game::chatServer && m_LoggedInCharID != 0) {
|
||||
RakNet::BitStream bitStream;
|
||||
BitStreamUtils::WriteHeader(bitStream, ServiceType::CHAT, MessageType::Chat::GM_MUTE);
|
||||
bitStream.Write(m_LoggedInCharID);
|
||||
bitStream.Write(m_MuteExpire);
|
||||
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return m_MuteExpire == 1 || m_MuteExpire > std::time(nullptr);
|
||||
}
|
||||
|
||||
time_t User::GetMuteExpire() const {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
#include "RakNetTypes.h"
|
||||
#include "dCommonVars.h"
|
||||
|
||||
@@ -46,7 +47,7 @@ public:
|
||||
const std::unordered_map<std::string, bool>& GetIsBestFriendMap() { return m_IsBestFriendMap; }
|
||||
void UpdateBestFriendValue(const std::string_view playerName, const bool newValue);
|
||||
|
||||
bool GetIsMuted() const;
|
||||
bool GetIsMuted();
|
||||
|
||||
time_t GetMuteExpire() const;
|
||||
void SetMuteExpire(time_t value);
|
||||
@@ -72,7 +73,8 @@ private:
|
||||
bool m_LastChatMessageApproved = false;
|
||||
int m_AmountOfTimesOutOfSync = 0;
|
||||
const int m_MaxDesyncAllowed = 12;
|
||||
time_t m_MuteExpire;
|
||||
uint64_t m_MuteExpire;
|
||||
std::chrono::steady_clock::time_point m_LastMuteCheck{};
|
||||
};
|
||||
|
||||
#endif // USER_H
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include "BehaviorContext.h"
|
||||
#include "EntityManager.h"
|
||||
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
void ChangeOrientationBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
|
||||
Entity* sourceEntity;
|
||||
if (this->m_orientCaster) sourceEntity = Game::entityManager->GetEntity(context->originator);
|
||||
@@ -16,12 +18,12 @@ void ChangeOrientationBehavior::Calculate(BehaviorContext* context, RakNet::BitS
|
||||
if (!destinationEntity) return;
|
||||
|
||||
sourceEntity->SetRotation(
|
||||
NiQuaternion::LookAt(sourceEntity->GetPosition(), destinationEntity->GetPosition())
|
||||
QuatUtils::LookAt(sourceEntity->GetPosition(), destinationEntity->GetPosition())
|
||||
);
|
||||
} else if (this->m_toAngle){
|
||||
auto baseAngle = NiPoint3(0, 0, this->m_angle);
|
||||
if (this->m_relative) baseAngle += sourceEntity->GetRotation().GetForwardVector();
|
||||
sourceEntity->SetRotation(NiQuaternion::FromEulerAngles(baseAngle));
|
||||
if (this->m_relative) baseAngle += QuatUtils::Forward(sourceEntity->GetRotation());
|
||||
sourceEntity->SetRotation(glm::quat(glm::vec3(baseAngle.x, baseAngle.y, baseAngle.z)));
|
||||
} else return;
|
||||
Game::entityManager->SerializeEntity(sourceEntity);
|
||||
return;
|
||||
|
||||
@@ -48,7 +48,7 @@ void ForceMovementBehavior::Calculate(BehaviorContext* context, RakNet::BitStrea
|
||||
if (controllablePhysicsComponent != nullptr) {
|
||||
|
||||
if (m_Forward == 1) {
|
||||
controllablePhysicsComponent->SetVelocity(controllablePhysicsComponent->GetRotation().GetForwardVector() * 25);
|
||||
controllablePhysicsComponent->SetVelocity(QuatUtils::Forward(controllablePhysicsComponent->GetRotation()) * 25);
|
||||
}
|
||||
|
||||
Game::entityManager->SerializeEntity(casterEntity);
|
||||
|
||||
@@ -92,7 +92,7 @@ void ProjectileAttackBehavior::Calculate(BehaviorContext* context, RakNet::BitSt
|
||||
|
||||
const auto time = distance / this->m_projectileSpeed;
|
||||
|
||||
const auto rotation = NiQuaternion::LookAtUnlocked(position, other->GetPosition());
|
||||
const auto rotation = QuatUtils::LookAtUnlocked(position, other->GetPosition());
|
||||
|
||||
const auto targetPosition = other->GetPosition();
|
||||
|
||||
@@ -112,13 +112,13 @@ void ProjectileAttackBehavior::Calculate(BehaviorContext* context, RakNet::BitSt
|
||||
|
||||
bitStream.Write(id);
|
||||
|
||||
auto eulerAngles = rotation.GetEulerAngles();
|
||||
auto eulerAngles = QuatUtils::Euler(rotation);
|
||||
|
||||
eulerAngles.y += angle * (3.14 / 180);
|
||||
eulerAngles.y += angle * (glm::pi<float>() / 180.0f);
|
||||
|
||||
const auto angledRotation = NiQuaternion::FromEulerAngles(eulerAngles);
|
||||
const auto angledRotation = QuatUtils::FromEuler(eulerAngles);
|
||||
|
||||
const auto direction = angledRotation.GetForwardVector();
|
||||
const auto direction = QuatUtils::Forward(angledRotation);
|
||||
|
||||
const auto destination = position + direction * distance;
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ void SpawnBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStrea
|
||||
info.spawner = nullptr;
|
||||
info.spawnerID = context->originator;
|
||||
info.spawnerNodeID = 0;
|
||||
info.pos = info.pos + (info.rot.GetForwardVector() * m_Distance);
|
||||
info.pos = info.pos + (QuatUtils::Forward(info.rot) * m_Distance);
|
||||
|
||||
auto* entity = Game::entityManager->CreateEntity(
|
||||
info,
|
||||
|
||||
@@ -125,7 +125,7 @@ void TacArcBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitS
|
||||
if (targetPos.y > reference.y && heightDifference > this->m_upperBound || targetPos.y < reference.y && heightDifference > this->m_lowerBound)
|
||||
continue;
|
||||
|
||||
const auto forward = self->GetRotation().GetForwardVector();
|
||||
const auto forward = QuatUtils::Forward(self->GetRotation());
|
||||
|
||||
// forward is a normalized vector of where the caster is facing.
|
||||
// targetPos is the position of the target.
|
||||
|
||||
@@ -767,7 +767,7 @@ void BaseCombatAIComponent::LookAt(const NiPoint3& point) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_Parent->SetRotation(NiQuaternion::LookAt(m_Parent->GetPosition(), point));
|
||||
m_Parent->SetRotation(QuatUtils::LookAt(m_Parent->GetPosition(), point));
|
||||
}
|
||||
|
||||
void BaseCombatAIComponent::SetDisabled(bool value) {
|
||||
|
||||
@@ -77,4 +77,4 @@ target_include_directories(dComponents PUBLIC "."
|
||||
)
|
||||
target_precompile_headers(dComponents REUSE_FROM dGameBase)
|
||||
|
||||
target_link_libraries(dComponents INTERFACE dBehaviors)
|
||||
target_link_libraries(dComponents INTERFACE dBehaviors PRIVATE glm::glm)
|
||||
|
||||
@@ -622,7 +622,7 @@ private:
|
||||
|
||||
NiPoint3 m_respawnPos;
|
||||
|
||||
NiQuaternion m_respawnRot;
|
||||
NiQuaternion m_respawnRot = QuatUtils::IDENTITY;
|
||||
|
||||
std::map<LWOOBJID, Loot::Info> m_DroppedLoot;
|
||||
|
||||
|
||||
@@ -1279,7 +1279,7 @@ void InventoryComponent::SpawnPet(Item* item) {
|
||||
EntityInfo info{};
|
||||
info.lot = item->GetLot();
|
||||
info.pos = m_Parent->GetPosition();
|
||||
info.rot = NiQuaternionConstant::IDENTITY;
|
||||
info.rot = QuatUtils::IDENTITY;
|
||||
info.spawnerID = m_Parent->GetObjectID();
|
||||
|
||||
auto* pet = Game::entityManager->CreateEntity(info);
|
||||
|
||||
@@ -198,7 +198,7 @@ private:
|
||||
/**
|
||||
* The rotation original of the model
|
||||
*/
|
||||
NiQuaternion m_OriginalRotation;
|
||||
NiQuaternion m_OriginalRotation = QuatUtils::IDENTITY;
|
||||
|
||||
/**
|
||||
* The ID of the user that made the model
|
||||
|
||||
@@ -83,7 +83,7 @@ void MovementAIComponent::Resume() {
|
||||
m_Paused = false;
|
||||
SetVelocity(m_SavedVelocity);
|
||||
m_SavedVelocity = NiPoint3Constant::ZERO;
|
||||
SetRotation(NiQuaternion::LookAt(m_Parent->GetPosition(), m_NextWaypoint));
|
||||
SetRotation(QuatUtils::LookAt(m_Parent->GetPosition(), m_NextWaypoint));
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ void MovementAIComponent::Update(const float deltaTime) {
|
||||
m_TimeTravelled = 0.0f;
|
||||
m_TimeToTravel = length / speed;
|
||||
|
||||
SetRotation(NiQuaternion::LookAt(source, m_NextWaypoint));
|
||||
SetRotation(QuatUtils::LookAt(source, m_NextWaypoint));
|
||||
}
|
||||
} else {
|
||||
// Check if there are more waypoints in the queue, if so set our next destination to the next waypoint
|
||||
|
||||
@@ -168,7 +168,7 @@ void PetComponent::OnUse(Entity* originator) {
|
||||
|
||||
const auto originatorPosition = originator->GetPosition();
|
||||
|
||||
m_Parent->SetRotation(NiQuaternion::LookAt(petPosition, originatorPosition));
|
||||
m_Parent->SetRotation(QuatUtils::LookAt(petPosition, originatorPosition));
|
||||
|
||||
float interactionDistance = m_Parent->GetVar<float>(u"interaction_distance");
|
||||
if (interactionDistance <= 0) {
|
||||
@@ -177,7 +177,7 @@ void PetComponent::OnUse(Entity* originator) {
|
||||
|
||||
auto position = originatorPosition;
|
||||
|
||||
NiPoint3 forward = NiQuaternion::LookAt(m_Parent->GetPosition(), originator->GetPosition()).GetForwardVector();
|
||||
NiPoint3 forward = QuatUtils::Forward(QuatUtils::LookAt(m_Parent->GetPosition(), originator->GetPosition()));
|
||||
forward.y = 0;
|
||||
|
||||
if (dpWorld::IsLoaded()) {
|
||||
@@ -186,7 +186,7 @@ void PetComponent::OnUse(Entity* originator) {
|
||||
NiPoint3 nearestPoint = dpWorld::GetNavMesh()->NearestPoint(attempt);
|
||||
|
||||
while (std::abs(nearestPoint.y - petPosition.y) > 4 && interactionDistance > 10) {
|
||||
const NiPoint3 forward = m_Parent->GetRotation().GetForwardVector();
|
||||
const NiPoint3 forward = QuatUtils::Forward(m_Parent->GetRotation());
|
||||
|
||||
attempt = originatorPosition + forward * interactionDistance;
|
||||
|
||||
@@ -200,7 +200,7 @@ void PetComponent::OnUse(Entity* originator) {
|
||||
position = petPosition + forward * interactionDistance;
|
||||
}
|
||||
|
||||
auto rotation = NiQuaternion::LookAt(position, petPosition);
|
||||
auto rotation = QuatUtils::LookAt(position, petPosition);
|
||||
|
||||
GameMessages::SendNotifyPetTamingMinigame(
|
||||
originator->GetObjectID(),
|
||||
@@ -460,7 +460,7 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) {
|
||||
EntityInfo info{};
|
||||
info.lot = entry->puzzleModelLot;
|
||||
info.pos = position;
|
||||
info.rot = NiQuaternionConstant::IDENTITY;
|
||||
info.rot = QuatUtils::IDENTITY;
|
||||
info.spawnerID = tamer->GetObjectID();
|
||||
|
||||
auto* modelEntity = Game::entityManager->CreateEntity(info);
|
||||
@@ -522,7 +522,7 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) {
|
||||
ePetTamingNotifyType::NAMINGPET,
|
||||
NiPoint3Constant::ZERO,
|
||||
NiPoint3Constant::ZERO,
|
||||
NiQuaternionConstant::IDENTITY,
|
||||
QuatUtils::IDENTITY,
|
||||
UNASSIGNED_SYSTEM_ADDRESS
|
||||
);
|
||||
|
||||
@@ -601,7 +601,7 @@ void PetComponent::RequestSetPetName(std::u16string name) {
|
||||
ePetTamingNotifyType::SUCCESS,
|
||||
NiPoint3Constant::ZERO,
|
||||
NiPoint3Constant::ZERO,
|
||||
NiQuaternionConstant::IDENTITY,
|
||||
QuatUtils::IDENTITY,
|
||||
UNASSIGNED_SYSTEM_ADDRESS
|
||||
);
|
||||
|
||||
@@ -645,7 +645,7 @@ void PetComponent::ClientExitTamingMinigame(bool voluntaryExit) {
|
||||
ePetTamingNotifyType::QUIT,
|
||||
NiPoint3Constant::ZERO,
|
||||
NiPoint3Constant::ZERO,
|
||||
NiQuaternionConstant::IDENTITY,
|
||||
QuatUtils::IDENTITY,
|
||||
UNASSIGNED_SYSTEM_ADDRESS
|
||||
);
|
||||
|
||||
@@ -696,7 +696,7 @@ void PetComponent::ClientFailTamingMinigame() {
|
||||
ePetTamingNotifyType::FAILED,
|
||||
NiPoint3Constant::ZERO,
|
||||
NiPoint3Constant::ZERO,
|
||||
NiQuaternionConstant::IDENTITY,
|
||||
QuatUtils::IDENTITY,
|
||||
UNASSIGNED_SYSTEM_ADDRESS
|
||||
);
|
||||
|
||||
|
||||
@@ -175,5 +175,5 @@ private:
|
||||
/**
|
||||
* If this is a respawn volume, the exact rotation an entity will respawn
|
||||
*/
|
||||
NiQuaternion m_RespawnRot;
|
||||
NiQuaternion m_RespawnRot = QuatUtils::IDENTITY;
|
||||
};
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
PhysicsComponent::PhysicsComponent(Entity* parent, int32_t componentId) : Component(parent) {
|
||||
m_Position = NiPoint3Constant::ZERO;
|
||||
m_Rotation = NiQuaternionConstant::IDENTITY;
|
||||
m_Rotation = QuatUtils::IDENTITY;
|
||||
m_DirtyPosition = false;
|
||||
|
||||
CDPhysicsComponentTable* physicsComponentTable = CDClientManager::GetTable<CDPhysicsComponentTable>();
|
||||
@@ -81,10 +81,10 @@ dpEntity* PhysicsComponent::CreatePhysicsEntity(eReplicaComponentType type) {
|
||||
toReturn = new dpEntity(m_Parent->GetObjectID(), 1.0f, 12.5f, 20.0f); // Not sure what the real size is
|
||||
} else if (info->physicsAsset == "env\\NG_NinjaGo\\env_ng_gen_gate_chamber_puzzle_ceiling_tile_falling_phantom.hkx") {
|
||||
toReturn = new dpEntity(m_Parent->GetObjectID(), 18.0f, 5.0f, 15.0f);
|
||||
m_Position += m_Rotation.GetForwardVector() * 7.5f;
|
||||
m_Position += QuatUtils::Forward(m_Rotation) * 7.5f;
|
||||
} else if (info->physicsAsset == "env\\NG_NinjaGo\\ng_flamejet_brick_phantom.HKX") {
|
||||
toReturn = new dpEntity(m_Parent->GetObjectID(), 1.0f, 1.0f, 12.0f);
|
||||
m_Position += m_Rotation.GetForwardVector() * 6.0f;
|
||||
m_Position += QuatUtils::Forward(m_Rotation) * 6.0f;
|
||||
} else if (info->physicsAsset == "env\\Ring_Trigger.hkx") {
|
||||
toReturn = new dpEntity(m_Parent->GetObjectID(), 6.0f, 6.0f, 6.0f);
|
||||
} else if (info->physicsAsset == "env\\vfx_propertyImaginationBall.hkx") {
|
||||
|
||||
@@ -45,7 +45,7 @@ protected:
|
||||
|
||||
NiPoint3 m_Position;
|
||||
|
||||
NiQuaternion m_Rotation;
|
||||
NiQuaternion m_Rotation = QuatUtils::IDENTITY;
|
||||
|
||||
bool m_DirtyPosition;
|
||||
|
||||
|
||||
@@ -333,7 +333,7 @@ void PropertyManagementComponent::UpdateModelPosition(const LWOOBJID id, const N
|
||||
|
||||
const auto modelLOT = item->GetLot();
|
||||
|
||||
if (rotation != NiQuaternionConstant::IDENTITY) {
|
||||
if (rotation != QuatUtils::IDENTITY) {
|
||||
rotation = { rotation.w, rotation.z, rotation.y, rotation.x };
|
||||
}
|
||||
|
||||
@@ -516,7 +516,7 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet
|
||||
|
||||
GameMessages::SendGetModelsOnProperty(entity->GetObjectID(), GetModels(), UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
GameMessages::SendPlaceModelResponse(entity->GetObjectID(), entity->GetSystemAddress(), NiPoint3Constant::ZERO, LWOOBJID_EMPTY, 16, NiQuaternionConstant::IDENTITY);
|
||||
GameMessages::SendPlaceModelResponse(entity->GetObjectID(), entity->GetSystemAddress(), NiPoint3Constant::ZERO, LWOOBJID_EMPTY, 16, QuatUtils::IDENTITY);
|
||||
|
||||
if (spawner != nullptr) {
|
||||
Game::zoneManager->RemoveSpawner(spawner->m_Info.spawnerID);
|
||||
@@ -569,7 +569,7 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet
|
||||
|
||||
GameMessages::SendGetModelsOnProperty(entity->GetObjectID(), GetModels(), UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
GameMessages::SendPlaceModelResponse(entity->GetObjectID(), entity->GetSystemAddress(), NiPoint3Constant::ZERO, LWOOBJID_EMPTY, 16, NiQuaternionConstant::IDENTITY);
|
||||
GameMessages::SendPlaceModelResponse(entity->GetObjectID(), entity->GetSystemAddress(), NiPoint3Constant::ZERO, LWOOBJID_EMPTY, 16, QuatUtils::IDENTITY);
|
||||
|
||||
if (spawner != nullptr) {
|
||||
Game::zoneManager->RemoveSpawner(spawner->m_Info.spawnerID);
|
||||
|
||||
@@ -123,7 +123,7 @@ void RacingControlComponent::LoadPlayerVehicle(Entity* player,
|
||||
|
||||
auto spawnPointEntities = Game::entityManager->GetEntitiesByLOT(4843);
|
||||
auto startPosition = NiPoint3Constant::ZERO;
|
||||
auto startRotation = NiQuaternionConstant::IDENTITY;
|
||||
auto startRotation = QuatUtils::IDENTITY;
|
||||
const std::string placementAsString = std::to_string(positionNumber);
|
||||
for (auto entity : spawnPointEntities) {
|
||||
if (!entity) continue;
|
||||
|
||||
@@ -48,7 +48,7 @@ struct RacingPlayerInfo {
|
||||
/**
|
||||
* Rotation that the player will respawn at if they smash their car
|
||||
*/
|
||||
NiQuaternion respawnRotation;
|
||||
NiQuaternion respawnRotation = QuatUtils::IDENTITY;
|
||||
|
||||
/**
|
||||
* The index in the respawn point the player is now at
|
||||
|
||||
@@ -316,7 +316,7 @@ SkillExecutionResult SkillComponent::CalculateBehavior(
|
||||
start.originatorRot = originator->GetRotation();
|
||||
}
|
||||
|
||||
if (rotationOverride != NiQuaternionConstant::IDENTITY) {
|
||||
if (rotationOverride != QuatUtils::IDENTITY) {
|
||||
start.originatorRot = rotationOverride;
|
||||
}
|
||||
//start.optionalTargetID = target;
|
||||
|
||||
@@ -129,7 +129,7 @@ public:
|
||||
* @param optionalOriginatorID change the originator of the skill
|
||||
* @return if the case succeeded
|
||||
*/
|
||||
bool CastSkill(const uint32_t skillId, LWOOBJID target = LWOOBJID_EMPTY, const LWOOBJID optionalOriginatorID = LWOOBJID_EMPTY, const int32_t castType = 0, const NiQuaternion rotationOverride = NiQuaternionConstant::IDENTITY);
|
||||
bool CastSkill(const uint32_t skillId, LWOOBJID target = LWOOBJID_EMPTY, const LWOOBJID optionalOriginatorID = LWOOBJID_EMPTY, const int32_t castType = 0, const NiQuaternion rotationOverride = QuatUtils::IDENTITY);
|
||||
|
||||
/**
|
||||
* Initializes a server-side skill calculation.
|
||||
@@ -141,7 +141,7 @@ public:
|
||||
* @param originatorOverride an override for the originator of the skill calculation
|
||||
* @return the result of the skill calculation
|
||||
*/
|
||||
SkillExecutionResult CalculateBehavior(uint32_t skillId, uint32_t behaviorId, LWOOBJID target, bool ignoreTarget = false, bool clientInitalized = false, LWOOBJID originatorOverride = LWOOBJID_EMPTY, const int32_t castType = 0, const NiQuaternion rotationOverride = NiQuaternionConstant::IDENTITY);
|
||||
SkillExecutionResult CalculateBehavior(uint32_t skillId, uint32_t behaviorId, LWOOBJID target, bool ignoreTarget = false, bool clientInitalized = false, LWOOBJID originatorOverride = LWOOBJID_EMPTY, const int32_t castType = 0, const NiQuaternion rotationOverride = QuatUtils::IDENTITY);
|
||||
|
||||
/**
|
||||
* Register a server-side projectile.
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#include "EntityManager.h"
|
||||
#include "MovementAIComponent.h"
|
||||
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
TriggerComponent::TriggerComponent(Entity* parent, const std::string triggerInfo) : Component(parent) {
|
||||
m_Parent = parent;
|
||||
m_Trigger = nullptr;
|
||||
@@ -240,10 +242,9 @@ void TriggerComponent::HandleMoveObject(Entity* targetEntity, std::vector<std::s
|
||||
void TriggerComponent::HandleRotateObject(Entity* targetEntity, std::vector<std::string> argArray) {
|
||||
if (argArray.size() <= 2) return;
|
||||
|
||||
const NiPoint3 vector = GeneralUtils::TryParse<NiPoint3>(argArray).value_or(NiPoint3Constant::ZERO);
|
||||
const auto vector = GeneralUtils::TryParse<glm::vec3>(argArray).value_or(glm::zero<glm::vec3>());
|
||||
|
||||
NiQuaternion rotation = NiQuaternion::FromEulerAngles(vector);
|
||||
targetEntity->SetRotation(rotation);
|
||||
targetEntity->SetRotation(glm::quat(vector));
|
||||
}
|
||||
|
||||
void TriggerComponent::HandlePushObject(Entity* targetEntity, std::vector<std::string> argArray) {
|
||||
|
||||
@@ -33,7 +33,7 @@ struct EntityInfo {
|
||||
LWOOBJID id;
|
||||
LOT lot;
|
||||
NiPoint3 pos;
|
||||
NiQuaternion rot;
|
||||
NiQuaternion rot = QuatUtils::IDENTITY;
|
||||
std::vector<LDFBaseData*> settings;
|
||||
std::vector<LDFBaseData*> networkSettings;
|
||||
float scale;
|
||||
|
||||
@@ -15,11 +15,11 @@ public:
|
||||
iCastType = 0;
|
||||
lastClickedPosit = NiPoint3Constant::ZERO;
|
||||
optionalTargetID = LWOOBJID_EMPTY;
|
||||
originatorRot = NiQuaternionConstant::IDENTITY;
|
||||
originatorRot = QuatUtils::IDENTITY;
|
||||
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) {
|
||||
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 = QuatUtils::IDENTITY, uint32_t _uiSkillHandle = 0) {
|
||||
bUsedMouse = _bUsedMouse;
|
||||
fCasterLatency = _fCasterLatency;
|
||||
iCastType = _iCastType;
|
||||
@@ -58,8 +58,8 @@ public:
|
||||
stream.Write(optionalTargetID != LWOOBJID_EMPTY);
|
||||
if (optionalTargetID != LWOOBJID_EMPTY) stream.Write(optionalTargetID);
|
||||
|
||||
stream.Write(originatorRot != NiQuaternionConstant::IDENTITY);
|
||||
if (originatorRot != NiQuaternionConstant::IDENTITY) stream.Write(originatorRot);
|
||||
stream.Write(originatorRot != QuatUtils::IDENTITY);
|
||||
if (originatorRot != QuatUtils::IDENTITY) stream.Write(originatorRot);
|
||||
|
||||
uint32_t sBitStreamLength = sBitStream.length();
|
||||
stream.Write(sBitStreamLength);
|
||||
@@ -121,7 +121,7 @@ public:
|
||||
NiPoint3 lastClickedPosit;
|
||||
LWOOBJID optionalOriginatorID;
|
||||
LWOOBJID optionalTargetID;
|
||||
NiQuaternion originatorRot;
|
||||
NiQuaternion originatorRot = QuatUtils::IDENTITY;
|
||||
std::string sBitStream;
|
||||
TSkillID skillID;
|
||||
uint32_t uiSkillHandle;
|
||||
|
||||
@@ -389,7 +389,7 @@ void GameMessages::SendPlatformResync(Entity* entity, const SystemAddress& sysAd
|
||||
float fMoveTimeElapsed = 0.0f;
|
||||
float fPercentBetweenPoints = 0.0f;
|
||||
NiPoint3 ptUnexpectedLocation = NiPoint3Constant::ZERO;
|
||||
NiQuaternion qUnexpectedRotation = NiQuaternionConstant::IDENTITY;
|
||||
NiQuaternion qUnexpectedRotation = QuatUtils::IDENTITY;
|
||||
|
||||
bitStream.Write(bReverse);
|
||||
bitStream.Write(bStopAtDesiredWaypoint);
|
||||
@@ -406,8 +406,8 @@ void GameMessages::SendPlatformResync(Entity* entity, const SystemAddress& sysAd
|
||||
bitStream.Write(ptUnexpectedLocation.y);
|
||||
bitStream.Write(ptUnexpectedLocation.z);
|
||||
|
||||
bitStream.Write(qUnexpectedRotation != NiQuaternionConstant::IDENTITY);
|
||||
if (qUnexpectedRotation != NiQuaternionConstant::IDENTITY) {
|
||||
bitStream.Write(qUnexpectedRotation != QuatUtils::IDENTITY);
|
||||
if (qUnexpectedRotation != QuatUtils::IDENTITY) {
|
||||
bitStream.Write(qUnexpectedRotation.x);
|
||||
bitStream.Write(qUnexpectedRotation.y);
|
||||
bitStream.Write(qUnexpectedRotation.z);
|
||||
@@ -1181,7 +1181,7 @@ void GameMessages::SendPlayerReachedRespawnCheckpoint(Entity* entity, const NiPo
|
||||
bitStream.Write(position.y);
|
||||
bitStream.Write(position.z);
|
||||
|
||||
const bool bIsNotIdentity = rotation != NiQuaternionConstant::IDENTITY;
|
||||
const bool bIsNotIdentity = rotation != QuatUtils::IDENTITY;
|
||||
bitStream.Write(bIsNotIdentity);
|
||||
|
||||
if (bIsNotIdentity) {
|
||||
@@ -2129,8 +2129,8 @@ void GameMessages::SendPlaceModelResponse(LWOOBJID objectId, const SystemAddress
|
||||
bitStream.Write(response);
|
||||
}
|
||||
|
||||
bitStream.Write(rotation != NiQuaternionConstant::IDENTITY);
|
||||
if (rotation != NiQuaternionConstant::IDENTITY) {
|
||||
bitStream.Write(rotation != QuatUtils::IDENTITY);
|
||||
if (rotation != QuatUtils::IDENTITY) {
|
||||
bitStream.Write(response);
|
||||
}
|
||||
|
||||
@@ -2395,13 +2395,13 @@ void GameMessages::HandlePlacePropertyModel(RakNet::BitStream& inStream, Entity*
|
||||
|
||||
inStream.Read(model);
|
||||
|
||||
PropertyManagementComponent::Instance()->UpdateModelPosition(model, NiPoint3Constant::ZERO, NiQuaternionConstant::IDENTITY);
|
||||
PropertyManagementComponent::Instance()->UpdateModelPosition(model, NiPoint3Constant::ZERO, QuatUtils::IDENTITY);
|
||||
}
|
||||
|
||||
void GameMessages::HandleUpdatePropertyModel(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr) {
|
||||
LWOOBJID model;
|
||||
NiPoint3 position;
|
||||
NiQuaternion rotation = NiQuaternionConstant::IDENTITY;
|
||||
NiQuaternion rotation = QuatUtils::IDENTITY;
|
||||
|
||||
inStream.Read(model);
|
||||
inStream.Read(position);
|
||||
@@ -3400,7 +3400,7 @@ void GameMessages::SendNotifyPetTamingMinigame(LWOOBJID objectId, LWOOBJID petId
|
||||
bitStream.Write(petsDestPos);
|
||||
bitStream.Write(telePos);
|
||||
|
||||
const bool hasDefault = teleRot != NiQuaternionConstant::IDENTITY;
|
||||
const bool hasDefault = teleRot != QuatUtils::IDENTITY;
|
||||
bitStream.Write(hasDefault);
|
||||
if (hasDefault) bitStream.Write(teleRot);
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ class AMFBaseValue;
|
||||
class AMFArrayValue;
|
||||
class Entity;
|
||||
class Item;
|
||||
class NiQuaternion;
|
||||
class User;
|
||||
class Leaderboard;
|
||||
class PropertySelectQueryProperty;
|
||||
@@ -765,7 +764,7 @@ namespace GameMessages {
|
||||
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
||||
|
||||
NiPoint3 target{};
|
||||
NiQuaternion rotation{};
|
||||
NiQuaternion rotation = QuatUtils::IDENTITY;
|
||||
};
|
||||
|
||||
struct ChildLoaded : public GameMsg {
|
||||
|
||||
@@ -18,11 +18,11 @@ public:
|
||||
iCastType = 0;
|
||||
lastClickedPosit = NiPoint3Constant::ZERO;
|
||||
optionalTargetID = LWOOBJID_EMPTY;
|
||||
originatorRot = NiQuaternionConstant::IDENTITY;
|
||||
originatorRot = QuatUtils::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 = NiPoint3Constant::ZERO, LWOOBJID _optionalTargetID = LWOOBJID_EMPTY, NiQuaternion _originatorRot = NiQuaternionConstant::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 = QuatUtils::IDENTITY, uint32_t _uiSkillHandle = 0) {
|
||||
bUsedMouse = _bUsedMouse;
|
||||
consumableItemID = _consumableItemID;
|
||||
fCasterLatency = _fCasterLatency;
|
||||
@@ -65,8 +65,8 @@ public:
|
||||
stream.Write(optionalTargetID != LWOOBJID_EMPTY);
|
||||
if (optionalTargetID != LWOOBJID_EMPTY) stream.Write(optionalTargetID);
|
||||
|
||||
stream.Write(originatorRot != NiQuaternionConstant::IDENTITY);
|
||||
if (originatorRot != NiQuaternionConstant::IDENTITY) stream.Write(originatorRot);
|
||||
stream.Write(originatorRot != QuatUtils::IDENTITY);
|
||||
if (originatorRot != QuatUtils::IDENTITY) stream.Write(originatorRot);
|
||||
|
||||
uint32_t sBitStreamLength = sBitStream.length();
|
||||
stream.Write(sBitStreamLength);
|
||||
@@ -133,7 +133,7 @@ public:
|
||||
NiPoint3 lastClickedPosit{};
|
||||
LWOOBJID optionalOriginatorID{};
|
||||
LWOOBJID optionalTargetID{};
|
||||
NiQuaternion originatorRot{};
|
||||
NiQuaternion originatorRot = QuatUtils::IDENTITY;
|
||||
std::string sBitStream = "";
|
||||
TSkillID skillID = 0;
|
||||
uint32_t uiSkillHandle = 0;
|
||||
|
||||
@@ -138,7 +138,7 @@ void Strip::Spawn(LOT lot, Entity& entity) {
|
||||
EntityInfo info{};
|
||||
info.lot = lot;
|
||||
info.pos = entity.GetPosition();
|
||||
info.rot = NiQuaternionConstant::IDENTITY;
|
||||
info.rot = QuatUtils::IDENTITY;
|
||||
info.spawnerID = entity.GetObjectID();
|
||||
auto* const spawnedEntity = Game::entityManager->CreateEntity(info, nullptr, &entity);
|
||||
spawnedEntity->AddToGroup("SpawnedPropertyEnemies");
|
||||
|
||||
@@ -808,6 +808,15 @@ void SlashCommandHandler::Startup() {
|
||||
};
|
||||
RegisterCommand(DeleteInvenCommand);
|
||||
|
||||
Command ExecuteCommand{
|
||||
.help = "Execute commands with modified context (Minecraft-style)",
|
||||
.info = "Execute commands as different entities or from different positions. Usage: /execute <subcommand> ... run <command>. Subcommands: as <entity>, at <entity>, positioned <x> <y> <z>",
|
||||
.aliases = { "execute", "exec" },
|
||||
.handle = DEVGMCommands::Execute,
|
||||
.requiredLevel = eGameMasterLevel::DEVELOPER
|
||||
};
|
||||
RegisterCommand(ExecuteCommand);
|
||||
|
||||
// Register Greater Than Zero Commands
|
||||
|
||||
Command KickCommand{
|
||||
|
||||
@@ -559,23 +559,25 @@ namespace DEVGMCommands {
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<float> ParseRelativeAxis(const float sourcePos, const std::string& toParse) {
|
||||
if (toParse.empty()) return std::nullopt;
|
||||
|
||||
// relative offset from current position
|
||||
if (toParse[0] == '~') {
|
||||
if (toParse.size() == 1) return sourcePos;
|
||||
|
||||
if (toParse.size() < 3 || !(toParse[1] != '+' || toParse[1] != '-')) return std::nullopt;
|
||||
|
||||
const auto offset = GeneralUtils::TryParse<float>(toParse.substr(2));
|
||||
if (!offset.has_value()) return std::nullopt;
|
||||
|
||||
bool isNegative = toParse[1] == '-';
|
||||
return isNegative ? sourcePos - offset.value() : sourcePos + offset.value();
|
||||
// Parse coordinates with support for relative positioning (~)
|
||||
std::optional<float> ParseRelativeAxis(const float currentValue, const std::string& rawCoord) {
|
||||
if (rawCoord.empty()) return std::nullopt;
|
||||
std::string coord = rawCoord;
|
||||
// Remove any '+' characters to simplify parsing, since they don't affect the value
|
||||
coord.erase(std::remove(coord.begin(), coord.end(), '+'), coord.end());
|
||||
if (coord[0] == '~') {
|
||||
if (coord.length() == 1) {
|
||||
return currentValue;
|
||||
} else {
|
||||
auto offsetOpt = GeneralUtils::TryParse<float>(coord.substr(1));
|
||||
if (!offsetOpt) return std::nullopt;
|
||||
return currentValue + offsetOpt.value();
|
||||
}
|
||||
} else {
|
||||
auto absoluteOpt = GeneralUtils::TryParse<float>(coord);
|
||||
if (!absoluteOpt) return std::nullopt;
|
||||
return absoluteOpt.value();
|
||||
}
|
||||
|
||||
return GeneralUtils::TryParse<float>(toParse);
|
||||
}
|
||||
|
||||
void Teleport(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
||||
@@ -649,7 +651,7 @@ namespace DEVGMCommands {
|
||||
if (havokVehiclePhysicsComponent) {
|
||||
havokVehiclePhysicsComponent->SetPosition(pos);
|
||||
Game::entityManager->SerializeEntity(possassableEntity);
|
||||
} else GameMessages::SendTeleport(possassableEntity->GetObjectID(), pos, NiQuaternion(), sysAddr);
|
||||
} else GameMessages::SendTeleport(possassableEntity->GetObjectID(), pos, QuatUtils::IDENTITY, sysAddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -660,7 +662,7 @@ namespace DEVGMCommands {
|
||||
const auto characters = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::CHARACTER);
|
||||
|
||||
for (auto* character : characters) {
|
||||
GameMessages::SendTeleport(character->GetObjectID(), pos, NiQuaternion(), character->GetSystemAddress());
|
||||
GameMessages::SendTeleport(character->GetObjectID(), pos, QuatUtils::IDENTITY, character->GetSystemAddress());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -815,7 +817,7 @@ namespace DEVGMCommands {
|
||||
// Set the position to the generated random position plus the player position. This will
|
||||
// spawn the entity in a circle around the player. As you get further from the player, the angle chosen will get less accurate.
|
||||
info.pos = playerPosition + NiPoint3(cos(randomAngle) * randomRadius, 0.0f, sin(randomAngle) * randomRadius);
|
||||
info.rot = NiQuaternion();
|
||||
info.rot = QuatUtils::IDENTITY;
|
||||
|
||||
auto newEntity = Game::entityManager->CreateEntity(info);
|
||||
if (newEntity == nullptr) {
|
||||
@@ -1664,4 +1666,163 @@ namespace DEVGMCommands {
|
||||
LOG("Despawned entity (%llu)", target->GetObjectID());
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Despawned entity: " + GeneralUtils::to_u16string(target->GetObjectID()));
|
||||
}
|
||||
|
||||
void Execute(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
||||
if (args.empty()) {
|
||||
ChatPackets::SendSystemMessage(sysAddr,
|
||||
u"Usage: /execute <subcommand> ... run <command>\n"
|
||||
u"Subcommands:\n"
|
||||
u" as <playername> - Execute as different player\n"
|
||||
u" at <playername> - Execute from player's position\n"
|
||||
u" positioned <x> <y> <z> - Execute from coordinates (absolute or relative with ~)\n"
|
||||
u"Examples:\n"
|
||||
u" /execute as Player1 run pos\n"
|
||||
u" /execute at Player2 positioned 100 200 300 run spawn 1234\n"
|
||||
u" /execute positioned ~5 ~10 ~ run spawn 1234"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto splitArgs = GeneralUtils::SplitString(args, ' ');
|
||||
|
||||
// Prevent execute command recursion by checking if this is already an execute command
|
||||
for (const auto& arg : splitArgs) {
|
||||
if (arg == "execute" || arg == "exec") {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Error: Recursive execute commands are not allowed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Context variables for execution
|
||||
Entity* execEntity = entity; // Entity to execute as
|
||||
NiPoint3 execPosition = entity->GetPosition(); // Position to execute from
|
||||
bool positionOverridden = false;
|
||||
std::string finalCommand;
|
||||
|
||||
// Parse subcommands
|
||||
size_t i = 0;
|
||||
while (i < splitArgs.size()) {
|
||||
const std::string& subcommand = splitArgs[i];
|
||||
|
||||
if (subcommand == "as") {
|
||||
if (i + 1 >= splitArgs.size()) {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Error: 'as' requires a player name");
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string& targetName = splitArgs[i + 1];
|
||||
auto* targetPlayer = PlayerManager::GetPlayer(targetName);
|
||||
if (!targetPlayer) {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Error: Player '" + GeneralUtils::ASCIIToUTF16(targetName) + u"' not found");
|
||||
return;
|
||||
}
|
||||
|
||||
execEntity = targetPlayer;
|
||||
i += 2;
|
||||
|
||||
} else if (subcommand == "at") {
|
||||
if (i + 1 >= splitArgs.size()) {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Error: 'at' requires a player name");
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string& targetName = splitArgs[i + 1];
|
||||
auto* targetPlayer = PlayerManager::GetPlayer(targetName);
|
||||
if (!targetPlayer) {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Error: Player '" + GeneralUtils::ASCIIToUTF16(targetName) + u"' not found");
|
||||
return;
|
||||
}
|
||||
|
||||
execPosition = targetPlayer->GetPosition();
|
||||
positionOverridden = true;
|
||||
i += 2;
|
||||
|
||||
} else if (subcommand == "positioned") {
|
||||
if (i + 3 >= splitArgs.size()) {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Error: 'positioned' requires x, y, z coordinates");
|
||||
return;
|
||||
}
|
||||
|
||||
auto xOpt = ParseRelativeAxis(execPosition.x, splitArgs[i + 1]);
|
||||
auto yOpt = ParseRelativeAxis(execPosition.y, splitArgs[i + 2]);
|
||||
auto zOpt = ParseRelativeAxis(execPosition.z, splitArgs[i + 3]);
|
||||
|
||||
if (!xOpt || !yOpt || !zOpt) {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Error: Invalid coordinates for 'positioned'. Use numeric values or relative coordinates with ~.");
|
||||
return;
|
||||
}
|
||||
|
||||
execPosition = NiPoint3(xOpt.value(), yOpt.value(), zOpt.value());
|
||||
positionOverridden = true;
|
||||
|
||||
i += 4;
|
||||
|
||||
} else if (subcommand == "run") {
|
||||
// Everything after "run" is the command to execute
|
||||
if (i + 1 >= splitArgs.size()) {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Error: 'run' requires a command");
|
||||
return;
|
||||
}
|
||||
|
||||
// Reconstruct the command from remaining args
|
||||
for (size_t j = i + 1; j < splitArgs.size(); ++j) {
|
||||
if (!finalCommand.empty()) finalCommand += " ";
|
||||
finalCommand += splitArgs[j];
|
||||
}
|
||||
break;
|
||||
|
||||
} else {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Error: Unknown subcommand '" + GeneralUtils::ASCIIToUTF16(subcommand) + u"'");
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Valid subcommands: as, at, positioned, run");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (finalCommand.empty()) {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Error: No command specified to run. Use 'run <command>' at the end.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate that the command starts with a valid character
|
||||
if (finalCommand.empty() || finalCommand[0] == '/') {
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"Error: Command should not start with '/'. Just specify the command name.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Store original position if we need to restore it
|
||||
NiPoint3 originalPosition;
|
||||
bool needToRestore = false;
|
||||
|
||||
if (positionOverridden && execEntity == entity) {
|
||||
// If we're executing as ourselves but from a different position,
|
||||
// temporarily move the entity
|
||||
originalPosition = entity->GetPosition();
|
||||
needToRestore = true;
|
||||
|
||||
// Set the position temporarily for the command execution
|
||||
auto* controllable = entity->GetComponent<ControllablePhysicsComponent>();
|
||||
if (controllable) {
|
||||
controllable->SetPosition(execPosition);
|
||||
}
|
||||
}
|
||||
|
||||
// Provide feedback about what we're executing
|
||||
std::string execAsName = execEntity->GetCharacter() ? execEntity->GetCharacter()->GetName() : "Unknown";
|
||||
ChatPackets::SendSystemMessage(sysAddr, u"[Execute] Running as '" + GeneralUtils::ASCIIToUTF16(execAsName) +
|
||||
u"' from <" + GeneralUtils::to_u16string(execPosition.x) + u", " +
|
||||
GeneralUtils::to_u16string(execPosition.y) + u", " +
|
||||
GeneralUtils::to_u16string(execPosition.z) + u">: /" +
|
||||
GeneralUtils::ASCIIToUTF16(finalCommand));
|
||||
|
||||
// Execute the command through the slash command handler
|
||||
SlashCommandHandler::HandleChatCommand(GeneralUtils::ASCIIToUTF16("/" + finalCommand), execEntity, sysAddr);
|
||||
|
||||
// Restore original position if needed
|
||||
if (needToRestore) {
|
||||
auto* controllable = entity->GetComponent<ControllablePhysicsComponent>();
|
||||
if (controllable) {
|
||||
controllable->SetPosition(originalPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -76,6 +76,7 @@ namespace DEVGMCommands {
|
||||
void Shutdown(Entity* entity, const SystemAddress& sysAddr, const std::string args);
|
||||
void Barfight(Entity* entity, const SystemAddress& sysAddr, const std::string args);
|
||||
void Despawn(Entity* entity, const SystemAddress& sysAddr, const std::string args);
|
||||
void Execute(Entity* entity, const SystemAddress& sysAddr, const std::string args);
|
||||
}
|
||||
|
||||
#endif //!DEVGMCOMMANDS_H
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
struct VanityObjectLocation {
|
||||
float m_Chance = 1.0f;
|
||||
NiPoint3 m_Position;
|
||||
NiQuaternion m_Rotation;
|
||||
NiQuaternion m_Rotation = QuatUtils::IDENTITY;
|
||||
float m_Scale = 1.0f;
|
||||
};
|
||||
|
||||
|
||||
@@ -159,6 +159,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
MigrationRunner::RunMigrations();
|
||||
Database::Get()->Commit();
|
||||
const auto resServerPath = BinaryPathFinder::GetBinaryDir() / "resServer";
|
||||
std::filesystem::create_directories(resServerPath);
|
||||
const bool cdServerExists = std::filesystem::exists(resServerPath / "CDServer.sqlite");
|
||||
|
||||
@@ -10,7 +10,7 @@ set(DNET_SOURCES "AuthPackets.cpp"
|
||||
"ZoneInstanceManager.cpp")
|
||||
|
||||
add_library(dNet STATIC ${DNET_SOURCES})
|
||||
target_link_libraries(dNet PRIVATE bcrypt MD5)
|
||||
target_link_libraries(dNet PRIVATE bcrypt MD5 glm::glm)
|
||||
target_include_directories(dNet PRIVATE
|
||||
"${PROJECT_SOURCE_DIR}/dCommon"
|
||||
"${PROJECT_SOURCE_DIR}/dCommon/dEnums"
|
||||
|
||||
@@ -12,5 +12,5 @@ target_include_directories(dPhysics PUBLIC "."
|
||||
"${PROJECT_SOURCE_DIR}/dCommon/dEnums"
|
||||
)
|
||||
target_link_libraries(dPhysics
|
||||
PUBLIC Recast Detour
|
||||
PUBLIC Recast Detour glm::glm
|
||||
INTERFACE dNavigation dCommon)
|
||||
|
||||
@@ -68,7 +68,7 @@ private:
|
||||
bool m_IsStatic;
|
||||
|
||||
NiPoint3 m_Position;
|
||||
NiQuaternion m_Rotation;
|
||||
NiQuaternion m_Rotation = QuatUtils::IDENTITY;
|
||||
float m_Scale;
|
||||
|
||||
NiPoint3 m_Velocity;
|
||||
|
||||
@@ -88,7 +88,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 = NiQuaternionConstant::IDENTITY;
|
||||
NiQuaternion rot = QuatUtils::IDENTITY;
|
||||
|
||||
controllable->SetStatic(false);
|
||||
|
||||
@@ -405,7 +405,7 @@ void BossSpiderQueenEnemyServer::OnTimerDone(Entity* self, const std::string tim
|
||||
const auto withdrawn = self->GetBoolean(u"isWithdrawn");
|
||||
if (!withdrawn) return;
|
||||
|
||||
NiQuaternion rot = NiQuaternionConstant::IDENTITY;
|
||||
NiQuaternion rot = QuatUtils::IDENTITY;
|
||||
|
||||
//First rotate for anim
|
||||
controllable->SetStatic(false);
|
||||
@@ -600,12 +600,12 @@ void BossSpiderQueenEnemyServer::OnUpdate(Entity* self) {
|
||||
|
||||
if (!isWithdrawn) return;
|
||||
|
||||
if (controllable->GetRotation() == NiQuaternionConstant::IDENTITY) {
|
||||
if (controllable->GetRotation() == QuatUtils::IDENTITY) {
|
||||
return;
|
||||
}
|
||||
|
||||
controllable->SetStatic(false);
|
||||
controllable->SetRotation(NiQuaternionConstant::IDENTITY);
|
||||
controllable->SetRotation(QuatUtils::IDENTITY);
|
||||
controllable->SetStatic(true);
|
||||
|
||||
Game::entityManager->SerializeEntity(self);
|
||||
|
||||
@@ -52,7 +52,7 @@ private:
|
||||
ControllablePhysicsComponent* controllable = nullptr;
|
||||
BaseCombatAIComponent* combat = nullptr;
|
||||
|
||||
NiQuaternion originRotation;
|
||||
NiQuaternion originRotation = QuatUtils::IDENTITY;
|
||||
|
||||
int m_CurrentBossStage = 0;
|
||||
int m_DeathCounter = 0;
|
||||
|
||||
@@ -76,7 +76,7 @@ void AmDarklingDragon::OnHitOrHealResult(Entity* self, Entity* attacker, int32_t
|
||||
self->AddTimer("timeToStunLoop", 1.0f);
|
||||
|
||||
auto position = self->GetPosition();
|
||||
auto forward = self->GetRotation().GetForwardVector();
|
||||
auto forward = QuatUtils::Forward(self->GetRotation());
|
||||
auto backwards = forward * -1;
|
||||
|
||||
forward.x *= 10;
|
||||
|
||||
@@ -92,7 +92,7 @@ void FvMaelstromDragon::OnHitOrHealResult(Entity* self, Entity* attacker, int32_
|
||||
self->AddTimer("timeToStunLoop", 1.0f);
|
||||
|
||||
auto position = self->GetPosition();
|
||||
auto forward = self->GetRotation().GetForwardVector();
|
||||
auto forward = QuatUtils::Forward(self->GetRotation());
|
||||
auto backwards = forward * -1;
|
||||
|
||||
forward.x *= 10;
|
||||
|
||||
@@ -66,7 +66,7 @@ void BaseEnemyApe::OnTimerDone(Entity* self, std::string timerName) {
|
||||
const auto position = self->GetPosition();
|
||||
const auto rotation = self->GetRotation();
|
||||
|
||||
const auto backwardVector = rotation.GetForwardVector() * -1;
|
||||
const auto backwardVector = QuatUtils::Forward(rotation) * -1;
|
||||
const auto objectPosition = NiPoint3(
|
||||
position.GetX() - (backwardVector.GetX() * 8),
|
||||
position.GetY(),
|
||||
|
||||
@@ -93,7 +93,7 @@ void AmDrawBridge::MoveBridgeDown(Entity* self, Entity* bridge, bool down) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto forwardVect = simplePhysicsComponent->GetRotation().GetForwardVector();
|
||||
auto forwardVect = QuatUtils::Forward(simplePhysicsComponent->GetRotation());
|
||||
|
||||
auto degrees = down ? 90.0f : -90.0f;
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ void AmShieldGenerator::EnemyEnteredShield(Entity* self, Entity* intruder) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto dir = intruder->GetRotation().GetForwardVector() * -1;
|
||||
auto dir = QuatUtils::Forward(intruder->GetRotation()) * -1;
|
||||
dir.y += 15;
|
||||
dir.x *= 50;
|
||||
dir.z *= 50;
|
||||
|
||||
@@ -187,7 +187,7 @@ void AmShieldGeneratorQuickbuild::EnemyEnteredShield(Entity* self, Entity* intru
|
||||
return;
|
||||
}
|
||||
|
||||
auto dir = intruder->GetRotation().GetForwardVector() * -1;
|
||||
auto dir = QuatUtils::Forward(intruder->GetRotation()) * -1;
|
||||
dir.y += 15;
|
||||
dir.x *= 50;
|
||||
dir.z *= 50;
|
||||
|
||||
@@ -46,23 +46,23 @@ void AmSkullkinTower::SpawnLegs(Entity* self, const std::string& loc) {
|
||||
info.rot = newRot;
|
||||
|
||||
if (loc == "Right") {
|
||||
const auto dir = rot.GetForwardVector();
|
||||
const auto dir = QuatUtils::Forward(rot);
|
||||
pos.x += dir.x * offset;
|
||||
pos.z += dir.z * offset;
|
||||
info.pos = pos;
|
||||
} else if (loc == "Rear") {
|
||||
const auto dir = rot.GetRightVector();
|
||||
const auto dir = QuatUtils::Right(rot);
|
||||
pos.x += dir.x * offset;
|
||||
pos.z += dir.z * offset;
|
||||
info.pos = pos;
|
||||
} else if (loc == "Left") {
|
||||
const auto dir = rot.GetForwardVector() * -1;
|
||||
const auto dir = QuatUtils::Forward(rot) * -1;
|
||||
pos.x += dir.x * offset;
|
||||
pos.z += dir.z * offset;
|
||||
info.pos = pos;
|
||||
}
|
||||
|
||||
info.rot = NiQuaternion::LookAt(info.pos, self->GetPosition());
|
||||
info.rot = QuatUtils::LookAt(info.pos, self->GetPosition());
|
||||
|
||||
auto* entity = Game::entityManager->CreateEntity(info, nullptr, self);
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ void GfCaptainsCannon::OnUse(Entity* self, Entity* user) {
|
||||
);
|
||||
|
||||
auto position = self->GetPosition();
|
||||
auto forward = self->GetRotation().GetForwardVector();
|
||||
auto forward = QuatUtils::Forward(self->GetRotation());
|
||||
|
||||
position.x += forward.x * -3;
|
||||
position.z += forward.z * -3;
|
||||
|
||||
@@ -65,7 +65,7 @@ void MastTeleport::OnTimerDone(Entity* self, std::string timerName) {
|
||||
} else if (timerName == "PlayerAnimDone") {
|
||||
GameMessages::SendStopFXEffect(player, true, "hook");
|
||||
|
||||
auto forward = self->GetRotation().GetForwardVector();
|
||||
auto forward = QuatUtils::Forward(self->GetRotation());
|
||||
|
||||
const auto degrees = -25.0f;
|
||||
|
||||
@@ -81,7 +81,7 @@ void MastTeleport::OnTimerDone(Entity* self, std::string timerName) {
|
||||
|
||||
GameMessages::SendOrientToAngle(playerId, true, rads, player->GetSystemAddress());
|
||||
|
||||
GameMessages::SendTeleport(playerId, position, NiQuaternionConstant::IDENTITY, player->GetSystemAddress());
|
||||
GameMessages::SendTeleport(playerId, position, QuatUtils::IDENTITY, player->GetSystemAddress());
|
||||
|
||||
GameMessages::SendSetStunned(playerId, eStateChangeType::POP, player->GetSystemAddress(),
|
||||
LWOOBJID_EMPTY, true, true, true, true, true, true, true
|
||||
|
||||
@@ -45,13 +45,13 @@ void QbSpawner::OnTimerDone(Entity* self, std::string timerName) {
|
||||
if (!gate) return;
|
||||
|
||||
auto oPos = gate->GetPosition();
|
||||
auto oDir = gate->GetRotation().GetForwardVector();
|
||||
auto oDir = QuatUtils::Forward(gate->GetRotation());
|
||||
NiPoint3 newPos(
|
||||
oPos.x + (oDir.x * spawnDist),
|
||||
oPos.y,
|
||||
oPos.z + (oDir.z * spawnDist)
|
||||
);
|
||||
auto newRot = NiQuaternion::LookAt(newPos, oPos);
|
||||
auto newRot = QuatUtils::LookAt(newPos, oPos);
|
||||
|
||||
for (int i = 0; i < mobTable.size(); i++) {
|
||||
int posOffset = -10;
|
||||
|
||||
@@ -108,7 +108,7 @@ void NtCombatChallengeServer::OnChildLoaded(Entity& self, GameMessages::ChildLoa
|
||||
auto* const child = Game::entityManager->GetEntity(childLoaded.childID);
|
||||
|
||||
if (child) {
|
||||
child->SetRotation(NiQuaternion::FromEulerAngles(child->GetRotation().GetEulerAngles() += NiPoint3(0, PI, 0))); // rotate 180 degrees
|
||||
child->SetRotation(QuatUtils::FromEuler(QuatUtils::Euler(child->GetRotation()) += NiPoint3(0, PI, 0))); // rotate 180 degrees
|
||||
}
|
||||
|
||||
self.SetVar(u"currentTargetID", child->GetObjectID());
|
||||
|
||||
@@ -48,7 +48,7 @@ void NtParadoxPanelServer::OnUse(Entity* self, Entity* user) {
|
||||
|
||||
RenderComponent::PlayAnimation(user, shockAnim);
|
||||
|
||||
const auto dir = self->GetRotation().GetRightVector();
|
||||
const auto dir = QuatUtils::Right(self->GetRotation());
|
||||
|
||||
GameMessages::SendKnockback(user->GetObjectID(), self->GetObjectID(), self->GetObjectID(), 0, { dir.x * 15, 5, dir.z * 15 });
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ void NtSentinelWalkwayServer::OnStartup(Entity* self) {
|
||||
force = 115;
|
||||
}
|
||||
|
||||
const auto forward = self->GetRotation().GetRightVector() * -1;
|
||||
const auto forward = QuatUtils::Right(self->GetRotation()) * -1;
|
||||
|
||||
phantomPhysicsComponent->SetEffectType(ePhysicsEffectType::PUSH);
|
||||
phantomPhysicsComponent->SetDirectionalMultiplier(force);
|
||||
|
||||
@@ -27,7 +27,7 @@ void FlameJetServer::OnCollisionPhantom(Entity* self, Entity* target) {
|
||||
|
||||
skillComponent->CalculateBehavior(726, 11723, target->GetObjectID(), true);
|
||||
|
||||
auto dir = target->GetRotation().GetForwardVector();
|
||||
auto dir = QuatUtils::Forward(target->GetRotation());
|
||||
|
||||
dir.y = 25;
|
||||
dir.x = -dir.x * 15;
|
||||
|
||||
@@ -36,7 +36,7 @@ void AgSpiderBossMessage::OnCollisionPhantom(Entity* self, Entity* target) {
|
||||
|
||||
auto box = GetBox(self);
|
||||
// knockback the target
|
||||
auto forward = self->GetRotation().GetForwardVector();
|
||||
auto forward = QuatUtils::Forward(self->GetRotation());
|
||||
box.boxTarget = target->GetObjectID();
|
||||
GameMessages::SendPlayFXEffect(target->GetObjectID(), 1378, u"create", "pushBack");
|
||||
RenderComponent::PlayAnimation(target, "knockback-recovery");
|
||||
|
||||
@@ -10,8 +10,8 @@ void GfBanana::SpawnBanana(Entity* self) {
|
||||
const auto rotation = self->GetRotation();
|
||||
|
||||
position.y += 12;
|
||||
position.x -= rotation.GetRightVector().x * 5;
|
||||
position.z -= rotation.GetRightVector().z * 5;
|
||||
position.x -= QuatUtils::Right(rotation).x * 5;
|
||||
position.z -= QuatUtils::Right(rotation).z * 5;
|
||||
|
||||
EntityInfo info{};
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ struct SGEnemy {
|
||||
|
||||
struct SGConstants {
|
||||
Vector3 playerStartPosition;
|
||||
Quaternion playerStartRotation;
|
||||
Quaternion playerStartRotation = QuatUtils::IDENTITY;
|
||||
LOT cannonLot;
|
||||
uint32_t impactSkillID;
|
||||
LOT projectileLot;
|
||||
|
||||
@@ -273,7 +273,7 @@ void NsConcertInstrument::RepositionPlayer(Entity* self, Entity* player) {
|
||||
case Keyboard:
|
||||
position.SetX(position.GetX() - 0.45f);
|
||||
position.SetZ(position.GetZ() + 0.75f);
|
||||
rotation = NiQuaternion::CreateFromAxisAngle(position, -0.8f); // Slight rotation to make the animation sensible
|
||||
rotation = QuatUtils::AxisAngle(position, -0.8f); // Slight rotation to make the animation sensible
|
||||
break;
|
||||
case Drum:
|
||||
position.SetZ(position.GetZ() - 0.5f);
|
||||
|
||||
@@ -10,7 +10,7 @@ void WblRobotCitizen::OnStartup(Entity* self) {
|
||||
void WblRobotCitizen::OnUse(Entity* self, Entity* user) {
|
||||
auto movementAIComponent = self->GetComponent<MovementAIComponent>();
|
||||
if (movementAIComponent) movementAIComponent->Pause();
|
||||
auto face = NiQuaternion::LookAt(self->GetPosition(), user->GetPosition());
|
||||
auto face = QuatUtils::LookAt(self->GetPosition(), user->GetPosition());
|
||||
self->SetRotation(face);
|
||||
auto timer = RenderComponent::PlayAnimation(self, "wave", 0.4f);
|
||||
self->AddTimer("animation time", timer);
|
||||
|
||||
@@ -1048,7 +1048,7 @@ void HandlePacket(Packet* packet) {
|
||||
Game::entityManager->ConstructEntity(player, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
if (respawnPoint != NiPoint3Constant::ZERO) {
|
||||
GameMessages::SendPlayerReachedRespawnCheckpoint(player, respawnPoint, NiQuaternionConstant::IDENTITY);
|
||||
GameMessages::SendPlayerReachedRespawnCheckpoint(player, respawnPoint, QuatUtils::IDENTITY);
|
||||
}
|
||||
|
||||
Game::entityManager->ConstructAllEntities(packet->systemAddress);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
struct SpawnerNode {
|
||||
NiPoint3 position = NiPoint3Constant::ZERO;
|
||||
NiQuaternion rotation = NiQuaternionConstant::IDENTITY;
|
||||
NiQuaternion rotation = QuatUtils::IDENTITY;
|
||||
uint32_t nodeID = 0;
|
||||
uint32_t nodeMax = 1;
|
||||
std::vector<LWOOBJID> entities;
|
||||
|
||||
@@ -71,7 +71,7 @@ struct RacingPathWaypoint {
|
||||
|
||||
struct PathWaypoint {
|
||||
NiPoint3 position;
|
||||
NiQuaternion rotation; // not included in all, but it's more convenient here
|
||||
NiQuaternion rotation = QuatUtils::IDENTITY; // not included in all, but it's more convenient here
|
||||
MovingPlatformPathWaypoint movingPlatform;
|
||||
CameraPathWaypoint camera;
|
||||
RacingPathWaypoint racing;
|
||||
@@ -237,7 +237,7 @@ private:
|
||||
uint32_t m_CheckSum;
|
||||
uint32_t m_WorldID; //should be equal to the MapID
|
||||
NiPoint3 m_Spawnpoint;
|
||||
NiQuaternion m_SpawnpointRotation;
|
||||
NiQuaternion m_SpawnpointRotation = QuatUtils::IDENTITY;
|
||||
uint32_t m_SceneCount;
|
||||
|
||||
std::string m_ZonePath; //Path to the .luz's folder
|
||||
|
||||
@@ -11,7 +11,7 @@ struct SceneObject {
|
||||
uint32_t nodeType;
|
||||
uint32_t glomId;
|
||||
NiPoint3 position;
|
||||
NiQuaternion rotation;
|
||||
NiQuaternion rotation = QuatUtils::IDENTITY;
|
||||
float scale = 1.0f;
|
||||
//std::string settings;
|
||||
uint32_t value3;
|
||||
|
||||
@@ -116,6 +116,7 @@ These commands are primarily for development and testing. The usage of many of t
|
||||
|setrewardcode|`/setrewardcode <code>`|Sets the rewardcode for the account you are logged into if it's a valid rewardcode, See cdclient table `RewardCodes`|8|
|
||||
|barfight|`/barfight start`|Starts a barfight (turns everyones pvp on)|8|
|
||||
|despawn|`/despawn <objectID>`|Despawns the entity objectID IF it was spawned in through a slash command.|8|
|
||||
|execute|`/execute <subcommand> ... run <command>`|Execute commands with modified context (Minecraft-style). Subcommands: `as <playername>` (execute as different player), `at <playername>` (execute from player's position), `positioned <x> <y> <z>` (execute from coordinates - supports absolute coordinates like `100 200 300` or relative coordinates like `~5 ~10 ~` where `~` means current position). Example: `/execute as Player1 run pos`, `/execute positioned ~5 ~ ~-3 run spawn 1234`|8|
|
||||
|crash|`/crash`|Crashes the server.|9|
|
||||
|rollloot|`/rollloot <loot matrix index> <item id> <amount>`|Given a `loot matrix index`, look for `item id` in that matrix `amount` times and print to the chat box statistics of rolling that loot matrix.|9|
|
||||
|castskill|`/castskill <skill id>`|Casts the skill as the player|9|
|
||||
|
||||
@@ -30,7 +30,7 @@ class GameDependenciesTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUpDependencies() {
|
||||
info.pos = NiPoint3Constant::ZERO;
|
||||
info.rot = NiQuaternionConstant::IDENTITY;
|
||||
info.rot = QuatUtils::IDENTITY;
|
||||
info.scale = 1.0f;
|
||||
info.spawner = nullptr;
|
||||
info.lot = 999;
|
||||
|
||||
15
thirdparty/CMakeLists.txt
vendored
15
thirdparty/CMakeLists.txt
vendored
@@ -40,13 +40,16 @@ add_subdirectory(magic_enum)
|
||||
# Create our third party library objects
|
||||
add_subdirectory(raknet)
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
# Download Backtrace if configured
|
||||
if(UNIX AND NOT APPLE)
|
||||
include(FetchContent)
|
||||
if (${INCLUDE_BACKTRACE} AND ${COMPILE_BACKTRACE})
|
||||
FetchContent_Declare(
|
||||
backtrace
|
||||
GIT_REPOSITORY https://github.com/ianlancetaylor/libbacktrace.git
|
||||
GIT_PROGRESS TRUE
|
||||
GIT_SHALLOW 1
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(backtrace)
|
||||
@@ -64,6 +67,16 @@ if(UNIX AND NOT APPLE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
FetchContent_Declare(
|
||||
glm
|
||||
GIT_REPOSITORY https://github.com/g-truc/glm.git
|
||||
GIT_TAG bf71a834948186f4097caa076cd2663c69a10e1e #refs/tags/1.0.1
|
||||
GIT_PROGRESS TRUE
|
||||
GIT_SHALLOW 1
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(glm)
|
||||
|
||||
add_subdirectory(MD5)
|
||||
|
||||
add_subdirectory(mongoose)
|
||||
|
||||
Reference in New Issue
Block a user