mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-20 11:59:40 -06:00
Compare commits
3 Commits
add-messag
...
save-to-in
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d94f5f77c6 | ||
|
|
1413db26e3 | ||
|
|
0a4d05039c |
@@ -20,7 +20,6 @@ set(DCOMMON_SOURCES
|
||||
"TinyXmlUtils.cpp"
|
||||
"Sd0.cpp"
|
||||
"Lxfml.cpp"
|
||||
"LxfmlBugged.cpp"
|
||||
)
|
||||
|
||||
# Workaround for compiler bug where the optimized code could result in a memcpy of 0 bytes, even though that isnt possible.
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// C++
|
||||
#include <charconv>
|
||||
#include <cstdint>
|
||||
#include <cmath>
|
||||
#include <ctime>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
@@ -146,7 +145,7 @@ namespace GeneralUtils {
|
||||
template <typename... Bases>
|
||||
struct overload : Bases... {
|
||||
using is_transparent = void;
|
||||
using Bases::operator() ...;
|
||||
using Bases::operator() ... ;
|
||||
};
|
||||
|
||||
struct char_pointer_hash {
|
||||
@@ -203,7 +202,7 @@ namespace GeneralUtils {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
requires(!Numeric<T>)
|
||||
requires(!Numeric<T>)
|
||||
[[nodiscard]] std::optional<T> TryParse(std::string_view str);
|
||||
|
||||
#if !(__GNUC__ >= 11 || _MSC_VER >= 1924)
|
||||
@@ -222,7 +221,7 @@ namespace GeneralUtils {
|
||||
*/
|
||||
template <std::floating_point T>
|
||||
[[nodiscard]] std::optional<T> TryParse(std::string_view str) noexcept
|
||||
try {
|
||||
try {
|
||||
while (!str.empty() && std::isspace(str.front())) str.remove_prefix(1);
|
||||
|
||||
size_t parseNum;
|
||||
@@ -324,28 +323,4 @@ namespace GeneralUtils {
|
||||
|
||||
return GenerateRandomNumber<T>(std::numeric_limits<T>::min(), std::numeric_limits<T>::max());
|
||||
}
|
||||
|
||||
// https://www.quora.com/How-do-you-round-to-specific-increments-like-0-5-in-C
|
||||
// Rounds to the nearest floating point value specified.
|
||||
template <typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
|
||||
T RountToNearestEven(const T value, const T modulus) {
|
||||
const auto modulo = std::fmod(value, modulus);
|
||||
const auto abs_modulo_2 = std::abs(modulo * 2);
|
||||
const auto abs_modulus = std::abs(modulus);
|
||||
|
||||
bool round_away_from_zero = false;
|
||||
if (abs_modulo_2 > abs_modulus) {
|
||||
round_away_from_zero = true;
|
||||
} else if (abs_modulo_2 == abs_modulus) {
|
||||
const auto trunc_quot = std::floor(std::abs(value / modulus));
|
||||
const auto odd = std::fmod(trunc_quot, T{ 2 }) != 0;
|
||||
round_away_from_zero = odd;
|
||||
}
|
||||
|
||||
if (round_away_from_zero) {
|
||||
return value + (std::copysign(modulus, value) - modulo);
|
||||
} else {
|
||||
return value - modulo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include <ranges>
|
||||
|
||||
Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoint3& curPosition) {
|
||||
Lxfml::Result Lxfml::NormalizePosition(const std::string_view data) {
|
||||
Result toReturn;
|
||||
tinyxml2::XMLDocument doc;
|
||||
const auto err = doc.Parse(data.data());
|
||||
@@ -27,7 +27,7 @@ Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoin
|
||||
// First get all the positions of bricks
|
||||
for (const auto& brick : lxfml["Bricks"]) {
|
||||
const auto* part = brick.FirstChildElement("Part");
|
||||
while (part) {
|
||||
if (part) {
|
||||
const auto* bone = part->FirstChildElement("Bone");
|
||||
if (bone) {
|
||||
auto* transformation = bone->Attribute("transformation");
|
||||
@@ -36,7 +36,6 @@ Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoin
|
||||
if (refID) transformations[refID] = transformation;
|
||||
}
|
||||
}
|
||||
part = part->NextSiblingElement("Part");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,42 +43,29 @@ Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoin
|
||||
NiPoint3 lowest{ 10'000.0f, 10'000.0f, 10'000.0f };
|
||||
NiPoint3 highest{ -10'000.0f, -10'000.0f, -10'000.0f };
|
||||
|
||||
NiPoint3 delta = NiPoint3Constant::ZERO;
|
||||
if (curPosition == NiPoint3Constant::ZERO) {
|
||||
// Calculate the lowest and highest points on the entire model
|
||||
for (const auto& transformation : transformations | std::views::values) {
|
||||
auto split = GeneralUtils::SplitString(transformation, ',');
|
||||
if (split.size() < 12) {
|
||||
LOG("Not enough in the split?");
|
||||
continue;
|
||||
}
|
||||
|
||||
auto x = GeneralUtils::TryParse<float>(split[9]).value();
|
||||
auto y = GeneralUtils::TryParse<float>(split[10]).value();
|
||||
auto z = GeneralUtils::TryParse<float>(split[11]).value();
|
||||
if (x < lowest.x) lowest.x = x;
|
||||
if (y < lowest.y) lowest.y = y;
|
||||
if (z < lowest.z) lowest.z = z;
|
||||
|
||||
if (highest.x < x) highest.x = x;
|
||||
if (highest.y < y) highest.y = y;
|
||||
if (highest.z < z) highest.z = z;
|
||||
// Calculate the lowest and highest points on the entire model
|
||||
for (const auto& transformation : transformations | std::views::values) {
|
||||
auto split = GeneralUtils::SplitString(transformation, ',');
|
||||
if (split.size() < 12) {
|
||||
LOG("Not enough in the split?");
|
||||
continue;
|
||||
}
|
||||
|
||||
delta = (highest - lowest) / 2.0f;
|
||||
} else {
|
||||
lowest = curPosition;
|
||||
highest = curPosition;
|
||||
delta = NiPoint3Constant::ZERO;
|
||||
auto x = GeneralUtils::TryParse<float>(split[9]).value();
|
||||
auto y = GeneralUtils::TryParse<float>(split[10]).value();
|
||||
auto z = GeneralUtils::TryParse<float>(split[11]).value();
|
||||
if (x < lowest.x) lowest.x = x;
|
||||
if (y < lowest.y) lowest.y = y;
|
||||
if (z < lowest.z) lowest.z = z;
|
||||
|
||||
if (highest.x < x) highest.x = x;
|
||||
if (highest.y < y) highest.y = y;
|
||||
if (highest.z < z) highest.z = z;
|
||||
}
|
||||
|
||||
auto delta = (highest - lowest) / 2.0f;
|
||||
auto newRootPos = lowest + delta;
|
||||
|
||||
// Need to snap this chosen position to the nearest valid spot
|
||||
// on the LEGO grid
|
||||
newRootPos.x = GeneralUtils::RountToNearestEven(newRootPos.x, 0.8f);
|
||||
newRootPos.z = GeneralUtils::RountToNearestEven(newRootPos.z, 0.8f);
|
||||
|
||||
// Clamp the Y to the lowest point on the model
|
||||
newRootPos.y = lowest.y;
|
||||
|
||||
@@ -91,9 +77,9 @@ Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoin
|
||||
continue;
|
||||
}
|
||||
|
||||
auto x = GeneralUtils::TryParse<float>(split[9]).value() - newRootPos.x + curPosition.x;
|
||||
auto y = GeneralUtils::TryParse<float>(split[10]).value() - newRootPos.y + curPosition.y;
|
||||
auto z = GeneralUtils::TryParse<float>(split[11]).value() - newRootPos.z + curPosition.z;
|
||||
auto x = GeneralUtils::TryParse<float>(split[9]).value() - newRootPos.x;
|
||||
auto y = GeneralUtils::TryParse<float>(split[10]).value() - newRootPos.y;
|
||||
auto z = GeneralUtils::TryParse<float>(split[11]).value() - newRootPos.z;
|
||||
std::stringstream stream;
|
||||
for (int i = 0; i < 9; i++) {
|
||||
stream << split[i];
|
||||
@@ -106,7 +92,7 @@ Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoin
|
||||
// Finally write the new transformation back into the lxfml
|
||||
for (auto& brick : lxfml["Bricks"]) {
|
||||
auto* part = brick.FirstChildElement("Part");
|
||||
while (part) {
|
||||
if (part) {
|
||||
auto* bone = part->FirstChildElement("Bone");
|
||||
if (bone) {
|
||||
auto* transformation = bone->Attribute("transformation");
|
||||
@@ -117,7 +103,6 @@ Lxfml::Result Lxfml::NormalizePosition(const std::string_view data, const NiPoin
|
||||
}
|
||||
}
|
||||
}
|
||||
part = part->NextSiblingElement("Part");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,11 +17,7 @@ namespace Lxfml {
|
||||
|
||||
// Normalizes a LXFML model to be positioned relative to its local 0, 0, 0 rather than a game worlds 0, 0, 0.
|
||||
// Returns a struct of its new center and the updated LXFML containing these edits.
|
||||
[[nodiscard]] Result NormalizePosition(const std::string_view data, const NiPoint3& curPosition = NiPoint3Constant::ZERO);
|
||||
|
||||
// these are only for the migrations due to a bug in one of the implementations.
|
||||
[[nodiscard]] Result NormalizePositionOnlyFirstPart(const std::string_view data);
|
||||
[[nodiscard]] Result NormalizePositionAfterFirstPart(const std::string_view data, const NiPoint3& position);
|
||||
[[nodiscard]] Result NormalizePosition(const std::string_view data);
|
||||
};
|
||||
|
||||
#endif //!LXFML_H
|
||||
|
||||
@@ -1,210 +0,0 @@
|
||||
#include "Lxfml.h"
|
||||
|
||||
#include "GeneralUtils.h"
|
||||
#include "StringifiedEnum.h"
|
||||
#include "TinyXmlUtils.h"
|
||||
|
||||
#include <ranges>
|
||||
|
||||
// this file should not be touched
|
||||
|
||||
Lxfml::Result Lxfml::NormalizePositionOnlyFirstPart(const std::string_view data) {
|
||||
Result toReturn;
|
||||
tinyxml2::XMLDocument doc;
|
||||
const auto err = doc.Parse(data.data());
|
||||
if (err != tinyxml2::XML_SUCCESS) {
|
||||
LOG("Failed to parse xml %s.", StringifiedEnum::ToString(err).data());
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
TinyXmlUtils::DocumentReader reader(doc);
|
||||
std::map<std::string/* refID */, std::string> transformations;
|
||||
|
||||
auto lxfml = reader["LXFML"];
|
||||
if (!lxfml) {
|
||||
LOG("Failed to find LXFML element.");
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
// First get all the positions of bricks
|
||||
for (const auto& brick : lxfml["Bricks"]) {
|
||||
const auto* part = brick.FirstChildElement("Part");
|
||||
if (part) {
|
||||
const auto* bone = part->FirstChildElement("Bone");
|
||||
if (bone) {
|
||||
auto* transformation = bone->Attribute("transformation");
|
||||
if (transformation) {
|
||||
auto* refID = bone->Attribute("refID");
|
||||
if (refID) transformations[refID] = transformation;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// These points are well out of bounds for an actual player
|
||||
NiPoint3 lowest{ 10'000.0f, 10'000.0f, 10'000.0f };
|
||||
NiPoint3 highest{ -10'000.0f, -10'000.0f, -10'000.0f };
|
||||
|
||||
// Calculate the lowest and highest points on the entire model
|
||||
for (const auto& transformation : transformations | std::views::values) {
|
||||
auto split = GeneralUtils::SplitString(transformation, ',');
|
||||
if (split.size() < 12) {
|
||||
LOG("Not enough in the split?");
|
||||
continue;
|
||||
}
|
||||
|
||||
auto x = GeneralUtils::TryParse<float>(split[9]).value();
|
||||
auto y = GeneralUtils::TryParse<float>(split[10]).value();
|
||||
auto z = GeneralUtils::TryParse<float>(split[11]).value();
|
||||
if (x < lowest.x) lowest.x = x;
|
||||
if (y < lowest.y) lowest.y = y;
|
||||
if (z < lowest.z) lowest.z = z;
|
||||
|
||||
if (highest.x < x) highest.x = x;
|
||||
if (highest.y < y) highest.y = y;
|
||||
if (highest.z < z) highest.z = z;
|
||||
}
|
||||
|
||||
auto delta = (highest - lowest) / 2.0f;
|
||||
auto newRootPos = lowest + delta;
|
||||
|
||||
// Clamp the Y to the lowest point on the model
|
||||
newRootPos.y = lowest.y;
|
||||
|
||||
// Adjust all positions to account for the new origin
|
||||
for (auto& transformation : transformations | std::views::values) {
|
||||
auto split = GeneralUtils::SplitString(transformation, ',');
|
||||
if (split.size() < 12) {
|
||||
LOG("Not enough in the split?");
|
||||
continue;
|
||||
}
|
||||
|
||||
auto x = GeneralUtils::TryParse<float>(split[9]).value() - newRootPos.x;
|
||||
auto y = GeneralUtils::TryParse<float>(split[10]).value() - newRootPos.y;
|
||||
auto z = GeneralUtils::TryParse<float>(split[11]).value() - newRootPos.z;
|
||||
std::stringstream stream;
|
||||
for (int i = 0; i < 9; i++) {
|
||||
stream << split[i];
|
||||
stream << ',';
|
||||
}
|
||||
stream << x << ',' << y << ',' << z;
|
||||
transformation = stream.str();
|
||||
}
|
||||
|
||||
// Finally write the new transformation back into the lxfml
|
||||
for (auto& brick : lxfml["Bricks"]) {
|
||||
auto* part = brick.FirstChildElement("Part");
|
||||
if (part) {
|
||||
auto* bone = part->FirstChildElement("Bone");
|
||||
if (bone) {
|
||||
auto* transformation = bone->Attribute("transformation");
|
||||
if (transformation) {
|
||||
auto* refID = bone->Attribute("refID");
|
||||
if (refID) {
|
||||
bone->SetAttribute("transformation", transformations[refID].c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tinyxml2::XMLPrinter printer;
|
||||
doc.Print(&printer);
|
||||
|
||||
toReturn.lxfml = printer.CStr();
|
||||
toReturn.center = newRootPos;
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
Lxfml::Result Lxfml::NormalizePositionAfterFirstPart(const std::string_view data, const NiPoint3& position) {
|
||||
Result toReturn;
|
||||
tinyxml2::XMLDocument doc;
|
||||
const auto err = doc.Parse(data.data());
|
||||
if (err != tinyxml2::XML_SUCCESS) {
|
||||
LOG("Failed to parse xml %s.", StringifiedEnum::ToString(err).data());
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
TinyXmlUtils::DocumentReader reader(doc);
|
||||
std::map<std::string/* refID */, std::string> transformations;
|
||||
|
||||
auto lxfml = reader["LXFML"];
|
||||
if (!lxfml) {
|
||||
LOG("Failed to find LXFML element.");
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
// First get all the positions of bricks
|
||||
for (const auto& brick : lxfml["Bricks"]) {
|
||||
const auto* part = brick.FirstChildElement("Part");
|
||||
bool firstPart = true;
|
||||
while (part) {
|
||||
if (firstPart) {
|
||||
firstPart = false;
|
||||
} else {
|
||||
LOG("Found extra bricks");
|
||||
const auto* bone = part->FirstChildElement("Bone");
|
||||
if (bone) {
|
||||
auto* transformation = bone->Attribute("transformation");
|
||||
if (transformation) {
|
||||
auto* refID = bone->Attribute("refID");
|
||||
if (refID) transformations[refID] = transformation;
|
||||
}
|
||||
}
|
||||
}
|
||||
part = part->NextSiblingElement("Part");
|
||||
}
|
||||
}
|
||||
|
||||
auto newRootPos = position;
|
||||
|
||||
// Adjust all positions to account for the new origin
|
||||
for (auto& transformation : transformations | std::views::values) {
|
||||
auto split = GeneralUtils::SplitString(transformation, ',');
|
||||
if (split.size() < 12) {
|
||||
LOG("Not enough in the split?");
|
||||
continue;
|
||||
}
|
||||
|
||||
auto x = GeneralUtils::TryParse<float>(split[9]).value() - newRootPos.x;
|
||||
auto y = GeneralUtils::TryParse<float>(split[10]).value() - newRootPos.y;
|
||||
auto z = GeneralUtils::TryParse<float>(split[11]).value() - newRootPos.z;
|
||||
std::stringstream stream;
|
||||
for (int i = 0; i < 9; i++) {
|
||||
stream << split[i];
|
||||
stream << ',';
|
||||
}
|
||||
stream << x << ',' << y << ',' << z;
|
||||
transformation = stream.str();
|
||||
}
|
||||
|
||||
// Finally write the new transformation back into the lxfml
|
||||
for (auto& brick : lxfml["Bricks"]) {
|
||||
auto* part = brick.FirstChildElement("Part");
|
||||
bool firstPart = true;
|
||||
while (part) {
|
||||
if (firstPart) {
|
||||
firstPart = false;
|
||||
} else {
|
||||
auto* bone = part->FirstChildElement("Bone");
|
||||
if (bone) {
|
||||
auto* transformation = bone->Attribute("transformation");
|
||||
if (transformation) {
|
||||
auto* refID = bone->Attribute("refID");
|
||||
if (refID) {
|
||||
bone->SetAttribute("transformation", transformations[refID].c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
part = part->NextSiblingElement("Part");
|
||||
}
|
||||
}
|
||||
|
||||
tinyxml2::XMLPrinter printer;
|
||||
doc.Print(&printer);
|
||||
|
||||
toReturn.lxfml = printer.CStr();
|
||||
toReturn.center = newRootPos;
|
||||
return toReturn;
|
||||
}
|
||||
@@ -47,8 +47,6 @@ void MigrationRunner::RunMigrations() {
|
||||
std::string finalSQL = "";
|
||||
bool runSd0Migrations = false;
|
||||
bool runNormalizeMigrations = false;
|
||||
bool runNormalizeAfterFirstPartMigrations = false;
|
||||
bool runBrickBuildsNotOnGrid = false;
|
||||
for (const auto& entry : GeneralUtils::GetSqlFileNamesFromFolder((BinaryPathFinder::GetBinaryDir() / "./migrations/dlu/" / migrationFolder).string())) {
|
||||
auto migration = LoadMigration("dlu/" + migrationFolder + "/", entry);
|
||||
|
||||
@@ -63,10 +61,6 @@ void MigrationRunner::RunMigrations() {
|
||||
runSd0Migrations = true;
|
||||
} else if (migration.name.ends_with("_normalize_model_positions.sql")) {
|
||||
runNormalizeMigrations = true;
|
||||
} else if (migration.name.ends_with("_normalize_model_positions_after_first_part.sql")) {
|
||||
runNormalizeAfterFirstPartMigrations = true;
|
||||
} else if (migration.name.ends_with("_brickbuilds_not_on_grid.sql")) {
|
||||
runBrickBuildsNotOnGrid = true;
|
||||
} else {
|
||||
finalSQL.append(migration.data.c_str());
|
||||
}
|
||||
@@ -74,7 +68,7 @@ void MigrationRunner::RunMigrations() {
|
||||
Database::Get()->InsertMigration(migration.name);
|
||||
}
|
||||
|
||||
if (finalSQL.empty() && !runSd0Migrations && !runNormalizeMigrations && !runNormalizeAfterFirstPartMigrations && !runBrickBuildsNotOnGrid) {
|
||||
if (finalSQL.empty() && !runSd0Migrations && !runNormalizeMigrations) {
|
||||
LOG("Server database is up to date.");
|
||||
return;
|
||||
}
|
||||
@@ -102,14 +96,6 @@ void MigrationRunner::RunMigrations() {
|
||||
if (runNormalizeMigrations) {
|
||||
ModelNormalizeMigration::Run();
|
||||
}
|
||||
|
||||
if (runNormalizeAfterFirstPartMigrations) {
|
||||
ModelNormalizeMigration::RunAfterFirstPart();
|
||||
}
|
||||
|
||||
if (runBrickBuildsNotOnGrid) {
|
||||
ModelNormalizeMigration::RunBrickBuildGrid();
|
||||
}
|
||||
}
|
||||
|
||||
void MigrationRunner::RunSQLiteMigrations() {
|
||||
|
||||
@@ -14,7 +14,7 @@ void ModelNormalizeMigration::Run() {
|
||||
|
||||
Sd0 sd0(lxfmlData);
|
||||
const auto asStr = sd0.GetAsStringUncompressed();
|
||||
const auto [newLxfml, newCenter] = Lxfml::NormalizePositionOnlyFirstPart(asStr);
|
||||
const auto [newLxfml, newCenter] = Lxfml::NormalizePosition(asStr);
|
||||
if (newCenter == NiPoint3Constant::ZERO) {
|
||||
LOG("Failed to update model %llu due to failure reading xml.");
|
||||
continue;
|
||||
@@ -28,44 +28,3 @@ void ModelNormalizeMigration::Run() {
|
||||
}
|
||||
Database::Get()->SetAutoCommit(oldCommit);
|
||||
}
|
||||
|
||||
void ModelNormalizeMigration::RunAfterFirstPart() {
|
||||
const auto oldCommit = Database::Get()->GetAutoCommit();
|
||||
Database::Get()->SetAutoCommit(false);
|
||||
for (auto& [lxfmlData, id, modelID] : Database::Get()->GetAllUgcModels()) {
|
||||
const auto model = Database::Get()->GetModel(modelID);
|
||||
// only BBB models (lot 14) need to have their position fixed from the above blunder
|
||||
if (model.lot != 14) continue;
|
||||
|
||||
Sd0 sd0(lxfmlData);
|
||||
const auto asStr = sd0.GetAsStringUncompressed();
|
||||
const auto [newLxfml, newCenter] = Lxfml::NormalizePositionAfterFirstPart(asStr, model.position);
|
||||
|
||||
sd0.FromData(reinterpret_cast<const uint8_t*>(newLxfml.data()), newLxfml.size());
|
||||
auto asStream = sd0.GetAsStream();
|
||||
Database::Get()->UpdateModel(model.id, newCenter, model.rotation, model.behaviors);
|
||||
Database::Get()->UpdateUgcModelData(id, asStream);
|
||||
}
|
||||
Database::Get()->SetAutoCommit(oldCommit);
|
||||
}
|
||||
|
||||
void ModelNormalizeMigration::RunBrickBuildGrid() {
|
||||
const auto oldCommit = Database::Get()->GetAutoCommit();
|
||||
Database::Get()->SetAutoCommit(false);
|
||||
for (auto& [lxfmlData, id, modelID] : Database::Get()->GetAllUgcModels()) {
|
||||
const auto model = Database::Get()->GetModel(modelID);
|
||||
// only BBB models (lot 14) need to have their position fixed from the above blunder
|
||||
if (model.lot != 14) continue;
|
||||
|
||||
Sd0 sd0(lxfmlData);
|
||||
const auto asStr = sd0.GetAsStringUncompressed();
|
||||
const auto [newLxfml, newCenter] = Lxfml::NormalizePosition(asStr, model.position);
|
||||
|
||||
sd0.FromData(reinterpret_cast<const uint8_t*>(newLxfml.data()), newLxfml.size());
|
||||
LOG("Updated model %llu to have a center of %f %f %f", modelID, newCenter.x, newCenter.y, newCenter.z);
|
||||
auto asStream = sd0.GetAsStream();
|
||||
Database::Get()->UpdateModel(model.id, newCenter, model.rotation, model.behaviors);
|
||||
Database::Get()->UpdateUgcModelData(id, asStream);
|
||||
}
|
||||
Database::Get()->SetAutoCommit(oldCommit);
|
||||
}
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
|
||||
namespace ModelNormalizeMigration {
|
||||
void Run();
|
||||
void RunAfterFirstPart();
|
||||
void RunBrickBuildGrid();
|
||||
};
|
||||
|
||||
#endif //!MODELNORMALIZEMIGRATION_H
|
||||
|
||||
534
dGame/Entity.cpp
534
dGame/Entity.cpp
File diff suppressed because it is too large
Load Diff
@@ -34,6 +34,7 @@ namespace tinyxml2 {
|
||||
};
|
||||
|
||||
class Player;
|
||||
class EntityInfo;
|
||||
class User;
|
||||
class Spawner;
|
||||
class ScriptComponent;
|
||||
@@ -44,7 +45,6 @@ class Item;
|
||||
class Character;
|
||||
class EntityCallbackTimer;
|
||||
class PositionUpdate;
|
||||
struct EntityInfo;
|
||||
enum class eTriggerEventType;
|
||||
enum class eGameMasterLevel : uint8_t;
|
||||
enum class eReplicaComponentType : uint32_t;
|
||||
@@ -60,7 +60,7 @@ namespace CppScripts {
|
||||
*/
|
||||
class Entity {
|
||||
public:
|
||||
Entity(const LWOOBJID& objectID, const EntityInfo& info, User* parentUser = nullptr, Entity* parentEntity = nullptr);
|
||||
explicit Entity(const LWOOBJID& objectID, EntityInfo info, User* parentUser = nullptr, Entity* parentEntity = nullptr);
|
||||
~Entity();
|
||||
|
||||
void Initialize();
|
||||
@@ -113,7 +113,7 @@ public:
|
||||
|
||||
float GetDefaultScale() const;
|
||||
|
||||
NiPoint3 GetPosition() const;
|
||||
const NiPoint3& GetPosition() const;
|
||||
|
||||
const NiQuaternion& GetRotation() const;
|
||||
|
||||
@@ -146,9 +146,9 @@ public:
|
||||
|
||||
void SetRotation(const NiQuaternion& rotation);
|
||||
|
||||
void SetRespawnPos(const NiPoint3& position) const;
|
||||
void SetRespawnPos(const NiPoint3& position);
|
||||
|
||||
void SetRespawnRot(const NiQuaternion& rotation) const;
|
||||
void SetRespawnRot(const NiQuaternion& rotation);
|
||||
|
||||
void SetVelocity(const NiPoint3& velocity);
|
||||
|
||||
@@ -169,7 +169,7 @@ public:
|
||||
void AddComponent(eReplicaComponentType componentId, Component* component);
|
||||
|
||||
// This is expceted to never return nullptr, an assert checks this.
|
||||
CppScripts::Script* const GetScript() const;
|
||||
CppScripts::Script* const GetScript();
|
||||
|
||||
void Subscribe(LWOOBJID scriptObjId, CppScripts::Script* scriptToAdd, const std::string& notificationName);
|
||||
void Unsubscribe(LWOOBJID scriptObjId, const std::string& notificationName);
|
||||
@@ -182,8 +182,8 @@ public:
|
||||
void RemoveParent();
|
||||
|
||||
// Adds a timer to start next frame with the given name and time.
|
||||
void AddTimer(const std::string& name, float time);
|
||||
void AddCallbackTimer(float time, const std::function<void()> callback);
|
||||
void AddTimer(std::string name, float time);
|
||||
void AddCallbackTimer(float time, std::function<void()> callback);
|
||||
bool HasTimer(const std::string& name);
|
||||
void CancelCallbackTimers();
|
||||
void CancelAllTimers();
|
||||
@@ -195,7 +195,7 @@ public:
|
||||
std::unordered_map<eReplicaComponentType, Component*>& GetComponents() { return m_Components; } // TODO: Remove
|
||||
|
||||
void WriteBaseReplicaData(RakNet::BitStream& outBitStream, eReplicaPacketType packetType);
|
||||
void WriteComponents(RakNet::BitStream& outBitStream, eReplicaPacketType packetType) const;
|
||||
void WriteComponents(RakNet::BitStream& outBitStream, eReplicaPacketType packetType);
|
||||
void UpdateXMLDoc(tinyxml2::XMLDocument& doc);
|
||||
void Update(float deltaTime);
|
||||
|
||||
@@ -242,21 +242,21 @@ public:
|
||||
void AddDieCallback(const std::function<void()>& callback);
|
||||
void Resurrect();
|
||||
|
||||
void AddLootItem(const Loot::Info& info) const;
|
||||
void PickupItem(const LWOOBJID& objectID) const;
|
||||
void AddLootItem(const Loot::Info& info);
|
||||
void PickupItem(const LWOOBJID& objectID);
|
||||
|
||||
bool PickupCoins(uint64_t count) const;
|
||||
void RegisterCoinDrop(uint64_t count) const;
|
||||
bool CanPickupCoins(uint64_t count);
|
||||
void RegisterCoinDrop(uint64_t count);
|
||||
|
||||
void ScheduleKillAfterUpdate(Entity* murderer = nullptr);
|
||||
void TriggerEvent(eTriggerEventType event, Entity* optionalTarget = nullptr) const;
|
||||
void TriggerEvent(eTriggerEventType event, Entity* optionalTarget = nullptr);
|
||||
void ScheduleDestructionAfterUpdate() { m_ShouldDestroyAfterUpdate = true; }
|
||||
|
||||
const NiPoint3& GetRespawnPosition() const;
|
||||
const NiQuaternion& GetRespawnRotation() const;
|
||||
|
||||
void Sleep() const;
|
||||
void Wake() const;
|
||||
void Sleep();
|
||||
void Wake();
|
||||
bool IsSleeping() const;
|
||||
|
||||
/*
|
||||
@@ -266,7 +266,7 @@ public:
|
||||
* Retroactively corrects the model vault size due to incorrect initialization in a previous patch.
|
||||
*
|
||||
*/
|
||||
void RetroactiveVaultSize() const;
|
||||
void RetroactiveVaultSize();
|
||||
bool GetBoolean(const std::u16string& name) const;
|
||||
int32_t GetI32(const std::u16string& name) const;
|
||||
int64_t GetI64(const std::u16string& name) const;
|
||||
@@ -334,8 +334,7 @@ public:
|
||||
*/
|
||||
static Observable<Entity*, const PositionUpdate&> OnPlayerPositionUpdate;
|
||||
|
||||
private:
|
||||
void WriteLDFData(const std::vector<LDFBaseData*>& ldf, RakNet::BitStream& outBitStream) const;
|
||||
protected:
|
||||
LWOOBJID m_ObjectID;
|
||||
|
||||
LOT m_TemplateID;
|
||||
@@ -358,6 +357,7 @@ private:
|
||||
Entity* m_ParentEntity; //For spawners and the like
|
||||
std::vector<Entity*> m_ChildEntities;
|
||||
eGameMasterLevel m_GMLevel;
|
||||
uint16_t m_CollectibleID;
|
||||
std::vector<std::string> m_Groups;
|
||||
uint16_t m_NetworkID;
|
||||
std::vector<std::function<void()>> m_DieCallbacks;
|
||||
@@ -383,8 +383,6 @@ private:
|
||||
|
||||
bool m_IsParentChildDirty = true;
|
||||
|
||||
bool m_IsSleeping = false;
|
||||
|
||||
/*
|
||||
* Collision
|
||||
*/
|
||||
@@ -393,7 +391,7 @@ private:
|
||||
// objectID of receiver and map of notification name to script
|
||||
std::map<LWOOBJID, std::map<std::string, CppScripts::Script*>> m_Subscriptions;
|
||||
|
||||
std::unordered_multimap<MessageType::Game, std::function<bool(GameMessages::GameMsg&)>> m_MsgHandlers;
|
||||
std::multimap<MessageType::Game, std::function<bool(GameMessages::GameMsg&)>> m_MsgHandlers;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -394,7 +394,7 @@ void EntityManager::ConstructAllEntities(const SystemAddress& sysAddr) {
|
||||
}
|
||||
}
|
||||
|
||||
UpdateGhosting(PlayerManager::GetPlayer(sysAddr), true);
|
||||
UpdateGhosting(PlayerManager::GetPlayer(sysAddr));
|
||||
}
|
||||
|
||||
void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr) {
|
||||
@@ -417,7 +417,7 @@ void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr)
|
||||
|
||||
void EntityManager::SerializeEntity(Entity* entity) {
|
||||
if (!entity) return;
|
||||
|
||||
|
||||
EntityManager::SerializeEntity(*entity);
|
||||
}
|
||||
|
||||
@@ -463,7 +463,7 @@ void EntityManager::UpdateGhosting() {
|
||||
m_PlayersToUpdateGhosting.clear();
|
||||
}
|
||||
|
||||
void EntityManager::UpdateGhosting(Entity* player, const bool constructAll) {
|
||||
void EntityManager::UpdateGhosting(Entity* player) {
|
||||
if (!player) return;
|
||||
|
||||
auto* missionComponent = player->GetComponent<MissionComponent>();
|
||||
@@ -511,12 +511,9 @@ void EntityManager::UpdateGhosting(Entity* player, const bool constructAll) {
|
||||
|
||||
ghostComponent->ObserveEntity(id);
|
||||
|
||||
entity->SetObservers(entity->GetObservers() + 1);
|
||||
|
||||
// TODO: figure out if zone control should be ghosted at all
|
||||
if (constructAll && entity->GetObjectID() == GetZoneControlEntity()->GetObjectID()) continue;
|
||||
|
||||
ConstructEntity(entity, player->GetSystemAddress());
|
||||
|
||||
entity->SetObservers(entity->GetObservers() + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -605,14 +602,3 @@ void EntityManager::FireEventServerSide(Entity* origin, std::string args) {
|
||||
bool EntityManager::IsExcludedFromGhosting(LOT lot) {
|
||||
return std::find(m_GhostingExcludedLOTs.begin(), m_GhostingExcludedLOTs.end(), lot) != m_GhostingExcludedLOTs.end();
|
||||
}
|
||||
|
||||
bool EntityManager::SendMessage(GameMessages::GameMsg& msg) const {
|
||||
bool handled = false;
|
||||
const auto entityItr = m_Entities.find(msg.target);
|
||||
if (entityItr != m_Entities.end()) {
|
||||
auto* const entity = entityItr->second;
|
||||
if (entity) handled = entity->HandleMsg(msg);
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
@@ -9,15 +9,11 @@
|
||||
#include "dCommonVars.h"
|
||||
|
||||
class Entity;
|
||||
struct EntityInfo;
|
||||
class EntityInfo;
|
||||
class Player;
|
||||
class User;
|
||||
enum class eReplicaComponentType : uint32_t;
|
||||
|
||||
namespace GameMessages {
|
||||
struct GameMsg;
|
||||
}
|
||||
|
||||
struct SystemAddress;
|
||||
|
||||
class EntityManager {
|
||||
@@ -58,7 +54,7 @@ public:
|
||||
void SetGhostDistanceMin(float value);
|
||||
void QueueGhostUpdate(LWOOBJID playerID);
|
||||
void UpdateGhosting();
|
||||
void UpdateGhosting(Entity* player, const bool constructAll = false);
|
||||
void UpdateGhosting(Entity* player);
|
||||
void CheckGhosting(Entity* entity);
|
||||
Entity* GetGhostCandidate(LWOOBJID id) const;
|
||||
bool GetGhostingEnabled() const;
|
||||
@@ -76,9 +72,6 @@ public:
|
||||
const bool GetHardcoreDropinventoryOnDeath() { return m_HardcoreDropinventoryOnDeath; };
|
||||
const uint32_t GetHardcoreUscoreEnemiesMultiplier() { return m_HardcoreUscoreEnemiesMultiplier; };
|
||||
|
||||
// Messaging
|
||||
bool SendMessage(GameMessages::GameMsg& msg) const;
|
||||
|
||||
private:
|
||||
void SerializeEntities();
|
||||
void KillEntities();
|
||||
|
||||
@@ -526,7 +526,7 @@ void UserManager::LoginCharacter(const SystemAddress& sysAddr, uint32_t playerID
|
||||
ZoneInstanceManager::Instance()->RequestZoneTransfer(Game::server, zoneID, character->GetZoneClone(), false, [=](bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, std::string serverIP, uint16_t serverPort) {
|
||||
LOG("Transferring %s to Zone %i (Instance %i | Clone %i | Mythran Shift: %s) with IP %s and Port %i", character->GetName().c_str(), zoneID, zoneInstance, zoneClone, mythranShift == true ? "true" : "false", serverIP.c_str(), serverPort);
|
||||
if (character) {
|
||||
auto* entity = Game::entityManager->GetEntity(character->GetObjectID());
|
||||
auto* entity = character->GetEntity();
|
||||
if (entity) {
|
||||
auto* characterComponent = entity->GetComponent<CharacterComponent>();
|
||||
if (characterComponent) {
|
||||
|
||||
@@ -575,7 +575,7 @@ void ActivityInstance::RewardParticipant(Entity* participant) {
|
||||
maxCoins = currencyTable[0].maxvalue;
|
||||
}
|
||||
|
||||
Loot::DropLoot(participant, m_Parent->GetObjectID(), activityRewards[0].LootMatrixIndex, minCoins, maxCoins);
|
||||
Loot::DropLoot(participant, m_Parent, activityRewards[0].LootMatrixIndex, minCoins, maxCoins);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -755,18 +755,18 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType
|
||||
|
||||
auto* member = Game::entityManager->GetEntity(specificOwner);
|
||||
|
||||
if (member) Loot::DropLoot(member, m_Parent->GetObjectID(), lootMatrixId, GetMinCoins(), GetMaxCoins());
|
||||
if (member) Loot::DropLoot(member, m_Parent, 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->GetObjectID(), lootMatrixId, GetMinCoins(), GetMaxCoins());
|
||||
Loot::DropLoot(member, m_Parent, lootMatrixId, GetMinCoins(), GetMaxCoins());
|
||||
}
|
||||
}
|
||||
} else { // drop loot for non team user
|
||||
Loot::DropLoot(owner, m_Parent->GetObjectID(), GetLootMatrixID(), GetMinCoins(), GetMaxCoins());
|
||||
Loot::DropLoot(owner, m_Parent, GetLootMatrixID(), GetMinCoins(), GetMaxCoins());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -784,7 +784,7 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType
|
||||
|
||||
coinsTotal -= coinsToLose;
|
||||
|
||||
Loot::DropLoot(m_Parent, m_Parent->GetObjectID(), -1, coinsToLose, coinsToLose);
|
||||
Loot::DropLoot(m_Parent, m_Parent, -1, coinsToLose, coinsToLose);
|
||||
character->SetCoins(coinsTotal, eLootSourceType::PICKUP);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ bool ModelComponent::OnResetModelToDefaults(GameMessages::GameMsg& msg) {
|
||||
m_Parent->SetRotation(m_OriginalRotation);
|
||||
m_Parent->SetVelocity(NiPoint3Constant::ZERO);
|
||||
|
||||
m_Speed = 3.0f;
|
||||
m_NumListeningInteract = 0;
|
||||
m_NumActiveUnSmash = 0;
|
||||
m_Dirty = true;
|
||||
@@ -265,7 +264,7 @@ bool ModelComponent::TrySetVelocity(const NiPoint3& velocity) const {
|
||||
|
||||
// If we're currently moving on an axis, prevent the move so only 1 behavior can have control over an axis
|
||||
if (velocity != NiPoint3Constant::ZERO) {
|
||||
const auto [x, y, z] = velocity * m_Speed;
|
||||
const auto [x, y, z] = velocity;
|
||||
if (x != 0.0f) {
|
||||
if (currentVelocity.x != 0.0f) return false;
|
||||
currentVelocity.x = x;
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
*
|
||||
* @tparam Msg The message type to pass
|
||||
* @param args the arguments of the message to be deserialized
|
||||
*
|
||||
*
|
||||
* @return returns true if a new behaviorID is needed.
|
||||
*/
|
||||
template<typename Msg>
|
||||
@@ -145,8 +145,6 @@ public:
|
||||
void SetVelocity(const NiPoint3& velocity) const;
|
||||
|
||||
void OnChatMessageReceived(const std::string& sMessage);
|
||||
|
||||
void SetSpeed(const float newSpeed) { m_Speed = newSpeed; }
|
||||
private:
|
||||
|
||||
// Loads a behavior from the database.
|
||||
@@ -187,7 +185,4 @@ private:
|
||||
* The ID of the user that made the model
|
||||
*/
|
||||
LWOOBJID m_userModelID;
|
||||
|
||||
// The speed at which this model moves
|
||||
float m_Speed{ 3.0f };
|
||||
};
|
||||
|
||||
@@ -29,13 +29,6 @@ PhysicsComponent::PhysicsComponent(Entity* parent, int32_t componentId) : Compon
|
||||
}
|
||||
|
||||
if (m_Parent->HasVar(u"CollisionGroupID")) m_CollisionGroup = m_Parent->GetVar<int32_t>(u"CollisionGroupID");
|
||||
|
||||
RegisterMsg(MessageType::Game::GET_POSITION, this, &PhysicsComponent::OnGetPosition);
|
||||
}
|
||||
|
||||
bool PhysicsComponent::OnGetPosition(GameMessages::GameMsg& msg) {
|
||||
static_cast<GameMessages::GetPosition&>(msg).pos = GetPosition();
|
||||
return true;
|
||||
}
|
||||
|
||||
void PhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) {
|
||||
|
||||
@@ -20,7 +20,7 @@ public:
|
||||
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
|
||||
const NiPoint3& GetPosition() const noexcept { return m_Position; }
|
||||
const NiPoint3& GetPosition() const { return m_Position; }
|
||||
virtual void SetPosition(const NiPoint3& pos) { if (m_Position == pos) return; m_Position = pos; m_DirtyPosition = true; }
|
||||
|
||||
const NiQuaternion& GetRotation() const { return m_Rotation; }
|
||||
@@ -35,8 +35,6 @@ protected:
|
||||
|
||||
void SpawnVertices(dpEntity* entity) const;
|
||||
|
||||
bool OnGetPosition(GameMessages::GameMsg& msg);
|
||||
|
||||
NiPoint3 m_Position;
|
||||
|
||||
NiQuaternion m_Rotation;
|
||||
|
||||
@@ -459,7 +459,7 @@ void QuickBuildComponent::CompleteQuickBuild(Entity* const user) {
|
||||
auto* missionComponent = builder->GetComponent<MissionComponent>();
|
||||
if (missionComponent) missionComponent->Progress(eMissionTaskType::ACTIVITY, m_ActivityId);
|
||||
}
|
||||
Loot::DropActivityLoot(builder, m_Parent->GetObjectID(), m_ActivityId, 1);
|
||||
Loot::DropActivityLoot(builder, m_Parent, m_ActivityId, 1);
|
||||
}
|
||||
|
||||
// Notify scripts
|
||||
|
||||
@@ -393,7 +393,7 @@ void RacingControlComponent::HandleMessageBoxResponse(Entity* player, int32_t bu
|
||||
}
|
||||
|
||||
const auto score = playersRating * 10 + data->finished;
|
||||
Loot::GiveActivityLoot(player, m_Parent->GetObjectID(), m_ActivityID, score);
|
||||
Loot::GiveActivityLoot(player, m_Parent, m_ActivityID, score);
|
||||
|
||||
// Giving rewards
|
||||
GameMessages::SendNotifyRacingClient(
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
#include "EntityManager.h"
|
||||
#include "ScriptedActivityComponent.h"
|
||||
|
||||
ShootingGalleryComponent::ShootingGalleryComponent(Entity* parent, int32_t activityID) : ActivityComponent(parent, activityID) {
|
||||
ShootingGalleryComponent::ShootingGalleryComponent(Entity* parent) : Component(parent) {
|
||||
}
|
||||
|
||||
ShootingGalleryComponent::~ShootingGalleryComponent() = default;
|
||||
|
||||
void ShootingGalleryComponent::SetStaticParams(const StaticShootingGalleryParams& params) {
|
||||
m_StaticParams = params;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "Entity.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
#include "ActivityComponent.h"
|
||||
|
||||
/**
|
||||
* Parameters for the shooting gallery that change during playtime
|
||||
@@ -72,11 +71,12 @@ struct StaticShootingGalleryParams {
|
||||
* A very ancient component that was used to guide shooting galleries, it's still kind of used but a lot of logic is
|
||||
* also in the related scripts.
|
||||
*/
|
||||
class ShootingGalleryComponent final : public ActivityComponent {
|
||||
class ShootingGalleryComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::SHOOTING_GALLERY;
|
||||
|
||||
explicit ShootingGalleryComponent(Entity* parent, int32_t activityID);
|
||||
explicit ShootingGalleryComponent(Entity* parent);
|
||||
~ShootingGalleryComponent();
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool isInitialUpdate) override;
|
||||
|
||||
/**
|
||||
|
||||
@@ -158,10 +158,6 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const System
|
||||
|
||||
inv->AddItemSkills(item.lot);
|
||||
}
|
||||
|
||||
// Fixes a bug where testmapping too fast causes large item inventories to become invisible.
|
||||
// Only affects item inventory
|
||||
GameMessages::SendSetInventorySize(entity, eInventoryType::ITEMS, inv->GetInventory(eInventoryType::ITEMS)->GetSize());
|
||||
}
|
||||
|
||||
GameMessages::SendRestoreToPostLoadStats(entity, sysAddr);
|
||||
|
||||
@@ -5207,7 +5207,7 @@ void GameMessages::HandlePickupCurrency(RakNet::BitStream& inStream, Entity* ent
|
||||
if (currency == 0) return;
|
||||
|
||||
auto* ch = entity->GetCharacter();
|
||||
if (ch && entity->PickupCoins(currency)) {
|
||||
if (ch && entity->CanPickupCoins(currency)) {
|
||||
ch->SetCoins(ch->GetCoins() + currency, eLootSourceType::PICKUP);
|
||||
}
|
||||
}
|
||||
@@ -6312,10 +6312,6 @@ void GameMessages::SendUpdateInventoryUi(LWOOBJID objectId, const SystemAddress&
|
||||
}
|
||||
|
||||
namespace GameMessages {
|
||||
bool GameMsg::Send() {
|
||||
return Game::entityManager->SendMessage(*this);
|
||||
}
|
||||
|
||||
void GameMsg::Send(const SystemAddress& sysAddr) const {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
@@ -54,12 +54,6 @@ namespace GameMessages {
|
||||
GameMsg(MessageType::Game gmId, eGameMasterLevel lvl) : msgId{ gmId }, requiredGmLevel{ lvl } {}
|
||||
GameMsg(MessageType::Game gmId) : GameMsg(gmId, eGameMasterLevel::CIVILIAN) {}
|
||||
virtual ~GameMsg() = default;
|
||||
|
||||
// Sends a message to the entity manager to route to the target
|
||||
bool Send();
|
||||
|
||||
// Sends the message to the specified client or
|
||||
// all clients if UNASSIGNED_SYSTEM_ADDRESS is specified
|
||||
void Send(const SystemAddress& sysAddr) const;
|
||||
virtual void Serialize(RakNet::BitStream& bitStream) const {}
|
||||
virtual bool Deserialize(RakNet::BitStream& bitStream) { return true; }
|
||||
@@ -849,10 +843,5 @@ namespace GameMessages {
|
||||
LWOOBJID targetID;
|
||||
};
|
||||
|
||||
struct GetPosition : public GameMsg {
|
||||
GetPosition() : GameMsg(MessageType::Game::GET_POSITION) {}
|
||||
|
||||
NiPoint3 pos{};
|
||||
};
|
||||
};
|
||||
#endif // GAMEMESSAGES_H
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
#include "eUseItemResponse.h"
|
||||
#include "dZoneManager.h"
|
||||
#include "ChatPackets.h"
|
||||
#include "MissionComponent.h"
|
||||
#include "eMissionTaskType.h"
|
||||
|
||||
#include "CDBrickIDTableTable.h"
|
||||
#include "CDObjectSkillsTable.h"
|
||||
@@ -270,9 +268,9 @@ bool Item::IsEquipped() const {
|
||||
}
|
||||
|
||||
bool Item::Consume() {
|
||||
auto* const skillsTable = CDClientManager::GetTable<CDObjectSkillsTable>();
|
||||
auto* skillsTable = CDClientManager::GetTable<CDObjectSkillsTable>();
|
||||
|
||||
const auto skills = skillsTable->Query([this](const CDObjectSkills& entry) {
|
||||
auto skills = skillsTable->Query([this](const CDObjectSkills entry) {
|
||||
return entry.objectTemplate == static_cast<uint32_t>(lot);
|
||||
});
|
||||
|
||||
@@ -290,12 +288,7 @@ bool Item::Consume() {
|
||||
GameMessages::SendUseItemResult(inventory->GetComponent()->GetParent(), lot, success);
|
||||
|
||||
if (success) {
|
||||
// Save this because if this is the last item in the inventory
|
||||
// we may delete ourself (lol)
|
||||
const auto myLot = this->lot;
|
||||
inventory->GetComponent()->RemoveItem(lot, 1);
|
||||
auto* missionComponent = inventory->GetComponent()->GetParent()->GetComponent<MissionComponent>();
|
||||
if (missionComponent) missionComponent->Progress(eMissionTaskType::GATHER, myLot, LWOOBJID_EMPTY, "", -1);
|
||||
}
|
||||
|
||||
return success;
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "ChatPackets.h"
|
||||
#include "PropertyManagementComponent.h"
|
||||
#include "PlayerManager.h"
|
||||
#include "SimplePhysicsComponent.h"
|
||||
|
||||
#include "dChatFilter.h"
|
||||
|
||||
@@ -155,18 +154,16 @@ void Strip::ProcNormalAction(float deltaTime, ModelComponent& modelComponent) {
|
||||
if (nextActionType == "MoveRight" || nextActionType == "MoveLeft") {
|
||||
// X axis
|
||||
bool isMoveLeft = nextActionType == "MoveLeft";
|
||||
int negative = isMoveLeft ? -1 : 1;
|
||||
// Default velocity is 3 units per second.
|
||||
if (modelComponent.TrySetVelocity(NiPoint3Constant::UNIT_X * negative)) {
|
||||
if (modelComponent.TrySetVelocity(NiPoint3{ isMoveLeft ? -3.0f : 3.0f, 0.0f, 0.0f })) {
|
||||
m_PreviousFramePosition = entity.GetPosition();
|
||||
m_InActionMove.x = isMoveLeft ? -number : number;
|
||||
}
|
||||
} else if (nextActionType == "FlyUp" || nextActionType == "FlyDown") {
|
||||
// Y axis
|
||||
bool isFlyDown = nextActionType == "FlyDown";
|
||||
int negative = isFlyDown ? -1 : 1;
|
||||
// Default velocity is 3 units per second.
|
||||
if (modelComponent.TrySetVelocity(NiPoint3Constant::UNIT_Y * negative)) {
|
||||
if (modelComponent.TrySetVelocity(NiPoint3{ 0.0f, isFlyDown ? -3.0f : 3.0f, 0.0f })) {
|
||||
m_PreviousFramePosition = entity.GetPosition();
|
||||
m_InActionMove.y = isFlyDown ? -number : number;
|
||||
}
|
||||
@@ -174,21 +171,14 @@ void Strip::ProcNormalAction(float deltaTime, ModelComponent& modelComponent) {
|
||||
} else if (nextActionType == "MoveForward" || nextActionType == "MoveBackward") {
|
||||
// Z axis
|
||||
bool isMoveBackward = nextActionType == "MoveBackward";
|
||||
int negative = isMoveBackward ? -1 : 1;
|
||||
// Default velocity is 3 units per second.
|
||||
if (modelComponent.TrySetVelocity(NiPoint3Constant::UNIT_Z * negative)) {
|
||||
if (modelComponent.TrySetVelocity(NiPoint3{ 0.0f, 0.0f, isMoveBackward ? -3.0f : 3.0f })) {
|
||||
m_PreviousFramePosition = entity.GetPosition();
|
||||
m_InActionMove.z = isMoveBackward ? -number : number;
|
||||
}
|
||||
}
|
||||
/* END Move */
|
||||
|
||||
/* BEGIN Navigation */
|
||||
else if (nextActionType == "SetSpeed") {
|
||||
modelComponent.SetSpeed(number);
|
||||
}
|
||||
/* END Navigation */
|
||||
|
||||
/* BEGIN Action */
|
||||
else if (nextActionType == "Smash") {
|
||||
if (!modelComponent.IsUnSmashing()) {
|
||||
|
||||
@@ -24,8 +24,9 @@ namespace {
|
||||
}
|
||||
|
||||
void Loot::CacheMatrix(uint32_t matrixIndex) {
|
||||
if (CachedMatrices.contains(matrixIndex)) return;
|
||||
|
||||
if (CachedMatrices.find(matrixIndex) != CachedMatrices.end()) {
|
||||
return;
|
||||
}
|
||||
CachedMatrices.insert(matrixIndex);
|
||||
CDComponentsRegistryTable* componentsRegistryTable = CDClientManager::GetTable<CDComponentsRegistryTable>();
|
||||
CDItemComponentTable* itemComponentTable = CDClientManager::GetTable<CDItemComponentTable>();
|
||||
@@ -214,7 +215,7 @@ void Loot::GiveLoot(Entity* player, std::unordered_map<LOT, int32_t>& result, eL
|
||||
}
|
||||
}
|
||||
|
||||
void Loot::GiveActivityLoot(Entity* player, const LWOOBJID source, uint32_t activityID, int32_t rating) {
|
||||
void Loot::GiveActivityLoot(Entity* player, Entity* source, uint32_t activityID, int32_t rating) {
|
||||
CDActivityRewardsTable* activityRewardsTable = CDClientManager::GetTable<CDActivityRewardsTable>();
|
||||
std::vector<CDActivityRewards> activityRewards = activityRewardsTable->Query([activityID](CDActivityRewards entry) { return (entry.objectTemplate == activityID); });
|
||||
|
||||
@@ -248,7 +249,7 @@ void Loot::GiveActivityLoot(Entity* player, const LWOOBJID source, uint32_t acti
|
||||
character->SetCoins(character->GetCoins() + coins, eLootSourceType::ACTIVITY);
|
||||
}
|
||||
|
||||
void Loot::DropLoot(Entity* player, const LWOOBJID source, uint32_t matrixIndex, uint32_t minCoins, uint32_t maxCoins) {
|
||||
void Loot::DropLoot(Entity* player, Entity* killedObject, uint32_t matrixIndex, uint32_t minCoins, uint32_t maxCoins) {
|
||||
player = player->GetOwner(); // if the owner is overwritten, we collect that here
|
||||
|
||||
auto* inventoryComponent = player->GetComponent<InventoryComponent>();
|
||||
@@ -258,10 +259,10 @@ void Loot::DropLoot(Entity* player, const LWOOBJID source, uint32_t matrixIndex,
|
||||
|
||||
std::unordered_map<LOT, int32_t> result = RollLootMatrix(player, matrixIndex);
|
||||
|
||||
DropLoot(player, source, result, minCoins, maxCoins);
|
||||
DropLoot(player, killedObject, result, minCoins, maxCoins);
|
||||
}
|
||||
|
||||
void Loot::DropLoot(Entity* player, const LWOOBJID source, std::unordered_map<LOT, int32_t>& result, uint32_t minCoins, uint32_t maxCoins) {
|
||||
void Loot::DropLoot(Entity* player, Entity* killedObject, std::unordered_map<LOT, int32_t>& result, uint32_t minCoins, uint32_t maxCoins) {
|
||||
player = player->GetOwner(); // if the owner is overwritten, we collect that here
|
||||
|
||||
auto* inventoryComponent = player->GetComponent<InventoryComponent>();
|
||||
@@ -269,11 +270,9 @@ void Loot::DropLoot(Entity* player, const LWOOBJID source, std::unordered_map<LO
|
||||
if (!inventoryComponent)
|
||||
return;
|
||||
|
||||
GameMessages::GetPosition posMsg;
|
||||
posMsg.target = source;
|
||||
posMsg.Send();
|
||||
const auto spawnPosition = killedObject->GetPosition();
|
||||
|
||||
const auto spawnPosition = posMsg.pos;
|
||||
const auto source = killedObject->GetObjectID();
|
||||
|
||||
for (const auto& pair : result) {
|
||||
for (int i = 0; i < pair.second; ++i) {
|
||||
@@ -286,7 +285,7 @@ void Loot::DropLoot(Entity* player, const LWOOBJID source, std::unordered_map<LO
|
||||
GameMessages::SendDropClientLoot(player, source, LOT_NULL, coins, spawnPosition);
|
||||
}
|
||||
|
||||
void Loot::DropActivityLoot(Entity* player, const LWOOBJID source, uint32_t activityID, int32_t rating) {
|
||||
void Loot::DropActivityLoot(Entity* player, Entity* source, uint32_t activityID, int32_t rating) {
|
||||
CDActivityRewardsTable* activityRewardsTable = CDClientManager::GetTable<CDActivityRewardsTable>();
|
||||
std::vector<CDActivityRewards> activityRewards = activityRewardsTable->Query([activityID](CDActivityRewards entry) { return (entry.objectTemplate == activityID); });
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ namespace Loot {
|
||||
void CacheMatrix(const uint32_t matrixIndex);
|
||||
void GiveLoot(Entity* player, uint32_t matrixIndex, eLootSourceType lootSourceType = eLootSourceType::NONE);
|
||||
void GiveLoot(Entity* player, std::unordered_map<LOT, int32_t>& result, eLootSourceType lootSourceType = eLootSourceType::NONE);
|
||||
void GiveActivityLoot(Entity* player, const LWOOBJID source, uint32_t activityID, int32_t rating = 0);
|
||||
void DropLoot(Entity* player, const LWOOBJID source, uint32_t matrixIndex, uint32_t minCoins, uint32_t maxCoins);
|
||||
void DropLoot(Entity* player, const LWOOBJID source, std::unordered_map<LOT, int32_t>& result, uint32_t minCoins, uint32_t maxCoins);
|
||||
void DropActivityLoot(Entity* player, const LWOOBJID source, uint32_t activityID, int32_t rating = 0);
|
||||
void GiveActivityLoot(Entity* player, Entity* source, uint32_t activityID, int32_t rating = 0);
|
||||
void DropLoot(Entity* player, Entity* killedObject, uint32_t matrixIndex, uint32_t minCoins, uint32_t maxCoins);
|
||||
void DropLoot(Entity* player, Entity* killedObject, std::unordered_map<LOT, int32_t>& result, uint32_t minCoins, uint32_t maxCoins);
|
||||
void DropActivityLoot(Entity* player, Entity* source, uint32_t activityID, int32_t rating = 0);
|
||||
};
|
||||
|
||||
@@ -132,7 +132,6 @@ namespace Mail {
|
||||
} else {
|
||||
response.status = eSendResponse::SenderAccountIsMuted;
|
||||
}
|
||||
LOG("Finished send with status %s", StringifiedEnum::ToString(response.status).data());
|
||||
response.Send(sysAddr);
|
||||
}
|
||||
|
||||
@@ -159,7 +158,6 @@ namespace Mail {
|
||||
DataResponse response;
|
||||
response.playerMail = playerMail;
|
||||
response.Send(sysAddr);
|
||||
LOG("DataRequest");
|
||||
}
|
||||
|
||||
void DataResponse::Serialize(RakNet::BitStream& bitStream) const {
|
||||
@@ -198,7 +196,6 @@ namespace Mail {
|
||||
response.status = eAttachmentCollectResponse::Success;
|
||||
}
|
||||
}
|
||||
LOG("AttachmentCollectResponse %s", StringifiedEnum::ToString(response.status).data());
|
||||
response.Send(sysAddr);
|
||||
}
|
||||
|
||||
@@ -221,15 +218,14 @@ namespace Mail {
|
||||
response.mailID = mailID;
|
||||
|
||||
auto mailData = Database::Get()->GetMail(mailID);
|
||||
if (mailData && !(mailData->itemLOT > 0 && mailData->itemCount > 0)) {
|
||||
if (mailData && !(mailData->itemLOT != 0 && mailData->itemCount > 0)) {
|
||||
Database::Get()->DeleteMail(mailID);
|
||||
response.status = eDeleteResponse::Success;
|
||||
} else if (mailData && mailData->itemLOT > 0 && mailData->itemCount > 0) {
|
||||
} else if (mailData && mailData->itemLOT != 0 && mailData->itemCount > 0) {
|
||||
response.status = eDeleteResponse::HasAttachments;
|
||||
} else {
|
||||
response.status = eDeleteResponse::NotFound;
|
||||
}
|
||||
LOG("DeleteRequest status %s", StringifiedEnum::ToString(response.status).data());
|
||||
response.Send(sysAddr);
|
||||
}
|
||||
|
||||
@@ -253,9 +249,7 @@ namespace Mail {
|
||||
if (Database::Get()->GetMail(mailID)) {
|
||||
response.status = eReadResponse::Success;
|
||||
Database::Get()->MarkMailRead(mailID);
|
||||
}
|
||||
|
||||
LOG("ReadRequest %s", StringifiedEnum::ToString(response.status).data());
|
||||
}
|
||||
response.Send(sysAddr);
|
||||
}
|
||||
|
||||
@@ -273,8 +267,6 @@ namespace Mail {
|
||||
response.status = eNotificationResponse::NewMail;
|
||||
response.mailCount = unreadMailCount;
|
||||
}
|
||||
|
||||
LOG("NotificationRequest %s", StringifiedEnum::ToString(response.status).data());
|
||||
response.Send(sysAddr);
|
||||
}
|
||||
}
|
||||
@@ -296,7 +288,6 @@ void Mail::HandleMail(RakNet::BitStream& inStream, const SystemAddress& sysAddr,
|
||||
LOG_DEBUG("Error Reading Mail Request: %s", StringifiedEnum::ToString(data.messageID).data());
|
||||
return;
|
||||
}
|
||||
LOG("Received mail message %s", StringifiedEnum::ToString(data.messageID).data());
|
||||
request->Handle();
|
||||
} else {
|
||||
LOG_DEBUG("Unhandled Mail Request with ID: %i", data.messageID);
|
||||
|
||||
@@ -119,15 +119,12 @@ namespace Mail {
|
||||
struct SendRequest : public MailLUBitStream {
|
||||
MailInfo mailInfo;
|
||||
|
||||
SendRequest() : MailLUBitStream(eMessageID::SendRequest) {}
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
void Handle() override;
|
||||
};
|
||||
|
||||
struct SendResponse :public MailLUBitStream {
|
||||
eSendResponse status = eSendResponse::UnknownError;
|
||||
|
||||
SendResponse() : MailLUBitStream(eMessageID::SendResponse) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
};
|
||||
|
||||
@@ -140,7 +137,6 @@ namespace Mail {
|
||||
};
|
||||
|
||||
struct DataRequest : public MailLUBitStream {
|
||||
DataRequest() : MailLUBitStream(eMessageID::DataRequest) {}
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override { return true; };
|
||||
void Handle() override;
|
||||
};
|
||||
|
||||
@@ -1514,7 +1514,6 @@ namespace DEVGMCommands {
|
||||
}
|
||||
|
||||
if (!closest) return;
|
||||
LOG("%llu", closest->GetObjectID());
|
||||
|
||||
Game::entityManager->SerializeEntity(closest);
|
||||
|
||||
|
||||
@@ -58,7 +58,6 @@ bool MailInfo::Deserialize(RakNet::BitStream& bitStream) {
|
||||
bitStream.IgnoreBytes(4); // padding
|
||||
|
||||
DluAssert(bitStream.GetNumberOfUnreadBits() == 0);
|
||||
LOG_DEBUG("MailInfo: %llu, %s, %s, %s, %llu, %i, %llu, %i, %llu, %i", id, subject.GetAsString().c_str(), body.GetAsString().c_str(), recipientName.GetAsString().c_str(), itemID, itemLOT, itemSubkey, itemCount, timeSent, wasRead);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -33,10 +33,10 @@ void TreasureChestDragonServer::OnUse(Entity* self, Entity* user) {
|
||||
|
||||
if (memberObject == nullptr) continue;
|
||||
|
||||
Loot::DropActivityLoot(memberObject, self->GetObjectID(), scriptedActivityComponent->GetActivityID(), rating);
|
||||
Loot::DropActivityLoot(memberObject, self, scriptedActivityComponent->GetActivityID(), rating);
|
||||
}
|
||||
} else {
|
||||
Loot::DropActivityLoot(user, self->GetObjectID(), scriptedActivityComponent->GetActivityID(), rating);
|
||||
Loot::DropActivityLoot(user, self, scriptedActivityComponent->GetActivityID(), rating);
|
||||
}
|
||||
|
||||
self->Smash(self->GetObjectID());
|
||||
|
||||
@@ -45,7 +45,7 @@ BootyDigServer::OnFireEventServerSide(Entity* self, Entity* sender, std::string
|
||||
if (renderComponent != nullptr)
|
||||
renderComponent->PlayEffect(7730, u"cast", "bootyshine");
|
||||
|
||||
Loot::DropLoot(player, self->GetObjectID(), 231, 75, 75);
|
||||
Loot::DropLoot(player, self, 231, 75, 75);
|
||||
}
|
||||
}
|
||||
} else if (args == "ChestDead") {
|
||||
|
||||
@@ -22,7 +22,7 @@ void BaseInteractDropLootServer::BaseUse(Entity* self, Entity* user) {
|
||||
|
||||
self->SetNetworkVar(u"bInUse", true);
|
||||
|
||||
Loot::DropLoot(user, self->GetObjectID(), lootMatrix, 0, 0);
|
||||
Loot::DropLoot(user, self, lootMatrix, 0, 0);
|
||||
|
||||
self->AddCallbackTimer(cooldownTime, [this, self]() {
|
||||
self->SetNetworkVar(u"bInUse", false);
|
||||
|
||||
@@ -13,7 +13,7 @@ void GrowingFlower::OnSkillEventFired(Entity* self, Entity* target, const std::s
|
||||
const auto mission1 = self->GetVar<int32_t>(u"missionID");
|
||||
const auto mission2 = self->GetVar<int32_t>(u"missionID2");
|
||||
|
||||
Loot::DropActivityLoot(target, self->GetObjectID(), self->GetLOT(), 0);
|
||||
Loot::DropActivityLoot(target, self, self->GetLOT(), 0);
|
||||
|
||||
auto* missionComponent = target->GetComponent<MissionComponent>();
|
||||
if (missionComponent != nullptr) {
|
||||
|
||||
@@ -23,7 +23,7 @@ void WishingWellServer::OnUse(Entity* self, Entity* user) {
|
||||
|
||||
Loot::DropActivityLoot(
|
||||
user,
|
||||
self->GetObjectID(),
|
||||
self,
|
||||
static_cast<uint32_t>(scriptedActivity->GetActivityID()),
|
||||
GeneralUtils::GenerateRandomNumber<int32_t>(1, 1000)
|
||||
);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "eTerminateType.h"
|
||||
|
||||
void VeMissionConsole::OnUse(Entity* self, Entity* user) {
|
||||
Loot::DropActivityLoot(user, self->GetObjectID(), 12551);
|
||||
Loot::DropActivityLoot(user, self, 12551);
|
||||
|
||||
auto* inventoryComponent = user->GetComponent<InventoryComponent>();
|
||||
if (inventoryComponent != nullptr) {
|
||||
|
||||
@@ -14,6 +14,6 @@ void NjDragonEmblemChestServer::OnUse(Entity* self, Entity* user) {
|
||||
|
||||
auto* destroyable = self->GetComponent<DestroyableComponent>();
|
||||
if (destroyable != nullptr) {
|
||||
Loot::DropLoot(user, self->GetObjectID(), destroyable->GetLootMatrixID(), 0, 0);
|
||||
Loot::DropLoot(user, self, destroyable->GetLootMatrixID(), 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,8 +50,6 @@ void NjMonastryBossInstance::OnPlayerLoaded(Entity* self, Entity* player) {
|
||||
// Join the player in the activity
|
||||
UpdatePlayer(self, player->GetObjectID());
|
||||
|
||||
TakeActivityCost(self, player->GetObjectID());
|
||||
|
||||
// Buff the player
|
||||
auto* destroyableComponent = player->GetComponent<DestroyableComponent>();
|
||||
if (destroyableComponent != nullptr) {
|
||||
|
||||
@@ -27,7 +27,7 @@ void MinigameTreasureChestServer::OnUse(Entity* self, Entity* user) {
|
||||
|
||||
if (self->GetLOT() == frakjawChestId) activityRating = team->members.size();
|
||||
|
||||
Loot::DropActivityLoot(teamMember, self->GetObjectID(), sac->GetActivityID(), activityRating);
|
||||
Loot::DropActivityLoot(teamMember, self, sac->GetActivityID(), activityRating);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -35,7 +35,7 @@ void MinigameTreasureChestServer::OnUse(Entity* self, Entity* user) {
|
||||
|
||||
if (self->GetLOT() == frakjawChestId) activityRating = 1;
|
||||
|
||||
Loot::DropActivityLoot(user, self->GetObjectID(), sac->GetActivityID(), activityRating);
|
||||
Loot::DropActivityLoot(user, self, sac->GetActivityID(), activityRating);
|
||||
}
|
||||
|
||||
sac->PlayerRemove(user->GetObjectID());
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <algorithm>
|
||||
#include "Logger.h"
|
||||
#include "Loot.h"
|
||||
#include "ShootingGalleryComponent.h"
|
||||
|
||||
bool ActivityManager::IsPlayerInActivity(Entity* self, LWOOBJID playerID) {
|
||||
const auto* sac = self->GetComponent<ScriptedActivityComponent>();
|
||||
@@ -72,7 +71,7 @@ void ActivityManager::StopActivity(Entity* self, const LWOOBJID playerID, const
|
||||
SetActivityValue(self, playerID, 1, value1);
|
||||
SetActivityValue(self, playerID, 2, value2);
|
||||
|
||||
Loot::GiveActivityLoot(player, self->GetObjectID(), gameID, CalculateActivityRating(self, playerID));
|
||||
Loot::GiveActivityLoot(player, self, gameID, CalculateActivityRating(self, playerID));
|
||||
|
||||
if (sac != nullptr) {
|
||||
sac->PlayerRemove(player->GetObjectID());
|
||||
@@ -94,16 +93,15 @@ void ActivityManager::SaveScore(Entity* self, const LWOOBJID playerID, const flo
|
||||
}
|
||||
|
||||
bool ActivityManager::TakeActivityCost(const Entity* self, const LWOOBJID playerID) {
|
||||
ActivityComponent* activityComponent = self->GetComponent<ScriptedActivityComponent>();
|
||||
if (activityComponent == nullptr) {
|
||||
activityComponent = self->GetComponent<ShootingGalleryComponent>();
|
||||
}
|
||||
auto* sac = self->GetComponent<ScriptedActivityComponent>();
|
||||
if (sac == nullptr)
|
||||
return false;
|
||||
|
||||
auto* player = Game::entityManager->GetEntity(playerID);
|
||||
if (player == nullptr)
|
||||
return false;
|
||||
|
||||
return activityComponent->TakeCost(player);
|
||||
return sac->TakeCost(player);
|
||||
}
|
||||
|
||||
uint32_t ActivityManager::CalculateActivityRating(Entity* self, const LWOOBJID playerID) {
|
||||
|
||||
@@ -29,7 +29,7 @@ void ScriptedPowerupSpawner::OnTimerDone(Entity* self, std::string message) {
|
||||
renderComponent->PlayEffect(0, u"cast", "N_cast");
|
||||
}
|
||||
|
||||
Loot::DropLoot(owner, self->GetObjectID(), drops, 0, 0);
|
||||
Loot::DropLoot(owner, self, drops, 0, 0);
|
||||
}
|
||||
|
||||
// Increment the current cycle
|
||||
|
||||
@@ -11,7 +11,7 @@ void AgPicnicBlanket::OnUse(Entity* self, Entity* user) {
|
||||
self->SetVar<bool>(u"active", true);
|
||||
|
||||
auto lootTable = std::unordered_map<LOT, int32_t>{ {935, 3} };
|
||||
Loot::DropLoot(user, self->GetObjectID(), lootTable, 0, 0);
|
||||
Loot::DropLoot(user, self, lootTable, 0, 0);
|
||||
|
||||
self->AddCallbackTimer(5.0f, [self]() {
|
||||
self->SetVar<bool>(u"active", false);
|
||||
|
||||
@@ -572,7 +572,7 @@ void SGCannon::StopGame(Entity* self, bool cancel) {
|
||||
missionComponent->Progress(eMissionTaskType::ACTIVITY, m_CannonLot, 0, "", self->GetVar<int32_t>(TotalScoreVariable));
|
||||
}
|
||||
|
||||
Loot::GiveActivityLoot(player, self->GetObjectID(), GetGameID(self), self->GetVar<int32_t>(TotalScoreVariable));
|
||||
Loot::GiveActivityLoot(player, self, GetGameID(self), self->GetVar<int32_t>(TotalScoreVariable));
|
||||
|
||||
SaveScore(self, player->GetObjectID(),
|
||||
static_cast<float>(self->GetVar<int32_t>(TotalScoreVariable)), static_cast<float>(self->GetVar<uint32_t>(MaxStreakVariable)), percentage);
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
/* See ModelNormalizeMigration.cpp for details */
|
||||
@@ -1 +0,0 @@
|
||||
/* See ModelNormalizeMigration.cpp for details */
|
||||
@@ -1 +0,0 @@
|
||||
/* See ModelNormalizeMigration.cpp for details */
|
||||
@@ -1 +0,0 @@
|
||||
/* See ModelNormalizeMigration.cpp for details */
|
||||
Reference in New Issue
Block a user