From b529b7d3a0204ee12ac172579f6fb07fef226004 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 8 Jan 2022 00:00:27 -0800 Subject: [PATCH 001/251] Added UNIQUE for charInfo table Added UNIQUE for charInfo table. --- migrations/dlu/0_initial.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrations/dlu/0_initial.sql b/migrations/dlu/0_initial.sql index 16cb3e7e..3c07d888 100644 --- a/migrations/dlu/0_initial.sql +++ b/migrations/dlu/0_initial.sql @@ -15,7 +15,7 @@ DROP TABLE IF EXISTS charinfo; CREATE TABLE charinfo ( id BIGINT NOT NULL PRIMARY KEY, account_id INT NOT NULL REFERENCES accounts(id), - name VARCHAR(35) NOT NULL, + name VARCHAR(35) NOT NULL UNIQUE, pending_name VARCHAR(35) NOT NULL, needs_rename BOOLEAN NOT NULL DEFAULT FALSE, prop_clone_id BIGINT UNSIGNED AUTO_INCREMENT UNIQUE, From 03e2a855b1b1a19e69272384474768c82588d541 Mon Sep 17 00:00:00 2001 From: Felix Racz Date: Sun, 9 Jan 2022 01:25:45 +0100 Subject: [PATCH 002/251] Add handling of SIGTERM --- dMasterServer/MasterServer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/dMasterServer/MasterServer.cpp b/dMasterServer/MasterServer.cpp index cb968169..0def5967 100644 --- a/dMasterServer/MasterServer.cpp +++ b/dMasterServer/MasterServer.cpp @@ -62,6 +62,7 @@ int main(int argc, char** argv) { //Triggers the shutdown sequence at application exit std::atexit(ShutdownSequence); signal(SIGINT, [](int) { ShutdownSequence(); }); + signal(SIGTERM, [](int) { ShutdownSequence(); }); //Create all the objects we need to run our service: Game::logger = SetupLogger(); From 01230e2575be6b40124fe865a2ee4870b4411016 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 9 Jan 2022 00:09:27 -0800 Subject: [PATCH 003/251] Revert change in 0_initial.sql --- migrations/dlu/0_initial.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrations/dlu/0_initial.sql b/migrations/dlu/0_initial.sql index 3c07d888..16cb3e7e 100644 --- a/migrations/dlu/0_initial.sql +++ b/migrations/dlu/0_initial.sql @@ -15,7 +15,7 @@ DROP TABLE IF EXISTS charinfo; CREATE TABLE charinfo ( id BIGINT NOT NULL PRIMARY KEY, account_id INT NOT NULL REFERENCES accounts(id), - name VARCHAR(35) NOT NULL UNIQUE, + name VARCHAR(35) NOT NULL, pending_name VARCHAR(35) NOT NULL, needs_rename BOOLEAN NOT NULL DEFAULT FALSE, prop_clone_id BIGINT UNSIGNED AUTO_INCREMENT UNIQUE, From 150dec1cc24b944377f49289fc8b94d3eb80bdd0 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 9 Jan 2022 00:12:49 -0800 Subject: [PATCH 004/251] Added file to run on table charinfo to allow for unique names only Created a new file to run on the MySQL database to alter the MySQL table charinfo.names to only allow unique entries --- migrations/dlu/1_unique_charinfo_names.sql | 1 + 1 file changed, 1 insertion(+) create mode 100644 migrations/dlu/1_unique_charinfo_names.sql diff --git a/migrations/dlu/1_unique_charinfo_names.sql b/migrations/dlu/1_unique_charinfo_names.sql new file mode 100644 index 00000000..cdf2537c --- /dev/null +++ b/migrations/dlu/1_unique_charinfo_names.sql @@ -0,0 +1 @@ +ALTER TABLE charinfo ADD UNIQUE (name); \ No newline at end of file From 2221945dc85882b66214c00a251be5b599755d86 Mon Sep 17 00:00:00 2001 From: Felix Racz Date: Tue, 11 Jan 2022 22:47:29 +0100 Subject: [PATCH 005/251] Add handling of SIGTERM --- dWorldServer/WorldServer.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index 2a6cbaa5..8688dc1c 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -100,10 +100,8 @@ int main(int argc, char** argv) { // Triggers the shutdown sequence at application exit std::atexit(WorldShutdownSequence); - signal(SIGINT, [](int) - { - WorldShutdownSequence(); - }); + signal(SIGINT, [](int){ WorldShutdownSequence(); }); + signal(SIGTERM, [](int){ WorldShutdownSequence(); }); int zoneID = 1000; int cloneID = 0; From 67d5061416a6b253a11506428115e1e7ffac5a2a Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 19 Jan 2022 02:10:04 -0800 Subject: [PATCH 006/251] Implemented Dragon Smash Quick Build for Crux Prime Dragons Implemented a script for the crux prime dragons to spawn the Golem Quick Build that insta kills the Entity if the player hits the dragon after the golem is built. Tested on Local Ubuntu instance against 1 Crux Prime Maelstrom Dragon and 1 Butterscorch and had no issues building the quick build or with the enemy not smashing. Enemies also correctly reset to their default behavior after the stun period has expired. --- dScripts/AmDarklingDragon.cpp | 167 +++++++++++++++++++++++++++++ dScripts/AmDarklingDragon.h | 12 +++ dScripts/AmNamedDarklingDragon.cpp | 12 --- dScripts/AmNamedDarklingDragon.h | 8 -- dScripts/CppScripts.cpp | 7 +- 5 files changed, 182 insertions(+), 24 deletions(-) create mode 100644 dScripts/AmDarklingDragon.cpp create mode 100644 dScripts/AmDarklingDragon.h delete mode 100644 dScripts/AmNamedDarklingDragon.cpp delete mode 100644 dScripts/AmNamedDarklingDragon.h diff --git a/dScripts/AmDarklingDragon.cpp b/dScripts/AmDarklingDragon.cpp new file mode 100644 index 00000000..435fa68d --- /dev/null +++ b/dScripts/AmDarklingDragon.cpp @@ -0,0 +1,167 @@ +#include "AmDarklingDragon.h" +#include "BaseCombatAIComponent.h" +#include "DestroyableComponent.h" +#include "EntityManager.h" +#include "GameMessages.h" +#include "SkillComponent.h" +#include "BaseCombatAIComponent.h" + + +void AmDarklingDragon::OnStartup(Entity* self) { + self->SetVar(u"weakspot", 0); + + auto* baseCombatAIComponent = self->GetComponent(); + + if (baseCombatAIComponent != nullptr) { + baseCombatAIComponent->SetStunImmune(true); + } +} + +void AmDarklingDragon::OnDie(Entity* self, Entity* killer) { + if (self->GetVar(u"bDied")) { + return; + } + + self->SetVar(u"bDied", true); + + auto position = self->GetPosition(); + auto rotation = self->GetRotation(); + + auto golemId = self->GetVar(u"Golem"); + + auto* golem = EntityManager::Instance()->GetEntity(golemId); + + if (golem != nullptr) { + golem->Smash(self->GetObjectID()); + } +} + +void AmDarklingDragon::OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) { + GameMessages::SendPlayFXEffect(self, -1, u"gothit", "", LWOOBJID_EMPTY, 1, 1, true); + + if (true) { + auto weakpoint = self->GetVar(u"weakspot"); + + if (weakpoint == 1) + { + self->Smash(attacker->GetObjectID()); + } + } + + auto* destroyableComponent = self->GetComponent(); + + if (destroyableComponent != nullptr) { + Game::logger->Log("AmDarklingDragon", "Armor is %i\n", destroyableComponent->GetArmor()); + + if (destroyableComponent->GetArmor() > 0) return; + + auto weakpoint = self->GetVar(u"weakpoint"); + + if (weakpoint == 0) { + Game::logger->Log("AmDarklingDragon", "Activating weakpoint\n"); + + self->AddTimer("ReviveTimer", 12); + + auto* baseCombatAIComponent = self->GetComponent(); + auto* skillComponent = self->GetComponent(); + + if (baseCombatAIComponent != nullptr) { + baseCombatAIComponent->SetDisabled(true); + baseCombatAIComponent->SetStunned(true); + } + + if (skillComponent != nullptr) { + skillComponent->Interrupt(); + } + + self->SetVar(u"weakpoint", 2); + + GameMessages::SendPlayAnimation(self, u"stunstart", 1.7f); + + self->AddTimer("timeToStunLoop", 1); + + auto position = self->GetPosition(); + auto forward = self->GetRotation().GetForwardVector(); + auto backwards = forward * -1; + + forward.x *= 10; + forward.z *= 10; + + auto rotation = self->GetRotation(); + + auto objectPosition = NiPoint3(); + + objectPosition.y = position.y; + objectPosition.x = position.x - (backwards.x * 8); + objectPosition.z = position.z - (backwards.z * 8); + + auto golem = self->GetVar(u"DragonSmashingGolem"); + + EntityInfo info {}; + info.lot = golem != 0 ? golem : 8340; + info.pos = objectPosition; + info.rot = rotation; + info.spawnerID = self->GetObjectID(); + info.settings = { + new LDFData(u"rebuild_activators", + std::to_string(objectPosition.x + forward.x) + "\x1f" + + std::to_string(objectPosition.y) + "\x1f" + + std::to_string(objectPosition.z + forward.z) + ), + new LDFData(u"respawn", 100000), + new LDFData(u"rebuild_reset_time", 15), + new LDFData(u"no_timed_spawn", true), + new LDFData(u"Dragon", self->GetObjectID()) + }; + + auto* golemObject = EntityManager::Instance()->CreateEntity(info); + + EntityManager::Instance()->ConstructEntity(golemObject); + } + } +} + +void AmDarklingDragon::OnTimerDone(Entity* self, std::string timerName) { + if (timerName == "ReviveHeldTimer") { + self->AddTimer("backToAttack", 2.5); + } + else if (timerName == "ExposeWeakSpotTimer") { + self->SetVar(u"weakspot", 1); + } + else if (timerName == "timeToStunLoop") { + GameMessages::SendPlayAnimation(self, u"stunloop", 1.8f); + } + else if (timerName == "ReviveTimer") { + GameMessages::SendPlayAnimation(self, u"stunend", 2.0f); + self->AddTimer("backToAttack", 1); + } + else if (timerName == "backToAttack") { + auto* baseCombatAIComponent = self->GetComponent(); + auto* skillComponent = self->GetComponent(); + if (baseCombatAIComponent != nullptr) + { + baseCombatAIComponent->SetDisabled(false); + baseCombatAIComponent->SetStunned(false); + } + if (skillComponent != nullptr) + { + skillComponent->Interrupt(); + } + self->SetVar(u"weakspot", -1); + GameMessages::SendNotifyObject(self->GetObjectID(), self->GetObjectID(), u"DragonRevive", UNASSIGNED_SYSTEM_ADDRESS); + } +} + +void AmDarklingDragon::OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1, int32_t param2, int32_t param3) { + if (args != "rebuildDone") return; + + self->AddTimer("ExposeWeakSpotTimer", 3.8f); + + self->CancelTimer("ReviveTimer"); + + self->AddTimer("ReviveHeldTimer", 10.5f); + + self->SetVar(u"Golem", sender->GetObjectID()); + + GameMessages::SendPlayAnimation(self, u"quickbuildhold", 1.9f); +} \ No newline at end of file diff --git a/dScripts/AmDarklingDragon.h b/dScripts/AmDarklingDragon.h new file mode 100644 index 00000000..8c3617d2 --- /dev/null +++ b/dScripts/AmDarklingDragon.h @@ -0,0 +1,12 @@ +#pragma once +#include "CppScripts.h" + +class AmDarklingDragon : public CppScripts::Script +{ +public: + void OnStartup(Entity* self) override; + void OnDie(Entity* self, Entity* killer) override; + void OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) override; + void OnTimerDone(Entity* self, std::string timerName) override; + void OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1, int32_t param2, int32_t param3) override; +}; diff --git a/dScripts/AmNamedDarklingDragon.cpp b/dScripts/AmNamedDarklingDragon.cpp deleted file mode 100644 index c7f51cbd..00000000 --- a/dScripts/AmNamedDarklingDragon.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "AmNamedDarklingDragon.h" -#include "BaseCombatAIComponent.h" - -void AmNamedDarklingDragon::OnStartup(Entity* self) -{ - auto* baseCombatAIComponent = self->GetComponent(); - - if (baseCombatAIComponent != nullptr) - { - baseCombatAIComponent->SetStunImmune(true); - } -} diff --git a/dScripts/AmNamedDarklingDragon.h b/dScripts/AmNamedDarklingDragon.h deleted file mode 100644 index cad5c2ca..00000000 --- a/dScripts/AmNamedDarklingDragon.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include "CppScripts.h" - -class AmNamedDarklingDragon : public CppScripts::Script -{ -public: - void OnStartup(Entity* self) override; -}; diff --git a/dScripts/CppScripts.cpp b/dScripts/CppScripts.cpp index f6029076..7cbac5f3 100644 --- a/dScripts/CppScripts.cpp +++ b/dScripts/CppScripts.cpp @@ -219,7 +219,7 @@ #include "AmSkullkinDrill.h" #include "AmSkullkinDrillStand.h" #include "AmSkullkinTower.h" -#include "AmNamedDarklingDragon.h" +#include "AmDarklingDragon.h" #include "AmBlueX.h" // NJ Scripts @@ -675,11 +675,10 @@ CppScripts::Script* CppScripts::GetScript(Entity* parent, const std::string& scr script = new AmSkullkinDrillStand(); else if (scriptName == "scripts\\02_server\\Map\\AM\\L_SKULLKIN_TOWER.lua") script = new AmSkullkinTower(); - // This just makes them immune to stuns. TODO: Make seperate scripts else if (scriptName == "scripts\\02_server\\Enemy\\AM\\L_AM_NAMED_DARKLING_DRAGON.lua") - script = new AmNamedDarklingDragon(); + script = new AmDarklingDragon(); else if (scriptName == "scripts\\02_server\\Enemy\\AM\\L_AM_DARKLING_DRAGON.lua") - script = new AmNamedDarklingDragon(); + script = new AmDarklingDragon(); else if (scriptName == "scripts\\02_server\\Enemy\\AM\\L_AM_DARKLING_APE.lua") script = new BaseEnemyApe(); else if (scriptName == "scripts\\02_server\\Map\\AM\\L_BLUE_X.lua") From 097af41392cac4608a39cbf162b5ca8b90cbbd6c Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 19 Jan 2022 02:28:50 -0800 Subject: [PATCH 007/251] Deleted unused variables --- dScripts/AmDarklingDragon.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/dScripts/AmDarklingDragon.cpp b/dScripts/AmDarklingDragon.cpp index 435fa68d..be87f466 100644 --- a/dScripts/AmDarklingDragon.cpp +++ b/dScripts/AmDarklingDragon.cpp @@ -23,9 +23,6 @@ void AmDarklingDragon::OnDie(Entity* self, Entity* killer) { } self->SetVar(u"bDied", true); - - auto position = self->GetPosition(); - auto rotation = self->GetRotation(); auto golemId = self->GetVar(u"Golem"); From 46f375a58e37d60227ae13f07e126e1618b261e2 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 19 Jan 2022 02:31:22 -0800 Subject: [PATCH 008/251] Added comments to header file --- dScripts/AmDarklingDragon.h | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/dScripts/AmDarklingDragon.h b/dScripts/AmDarklingDragon.h index 8c3617d2..ea4c2a19 100644 --- a/dScripts/AmDarklingDragon.h +++ b/dScripts/AmDarklingDragon.h @@ -4,9 +4,45 @@ class AmDarklingDragon : public CppScripts::Script { public: + /** + * @brief When called, this function will make self immune to stuns and initialize a weakspot boolean to false. + * + * @param self The Entity that called this function. + */ void OnStartup(Entity* self) override; + /** + * @brief When called, this function will destroy the golem if it was alive, otherwise returns immediately. + * + * @param self The Entity that called this function. + * @param killer The Entity that killed self. + */ void OnDie(Entity* self, Entity* killer) override; + /** + * @brief When self is hit or healed, this function will check if self is at zero armor. If self is at zero armor, a golem Entity Quick Build + * is spawned that, when built, will reveal a weakpoint on the dragon that if hit will smash the dragon instantly. If at more than zero armor, + * this function returns early. + * + * @param self The Entity that was hit. + * @param attacker The Entity that attacked self. + * @param damage The amount of damage attacker did to self. + */ void OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) override; + /** + * @brief Called when self has a timer that ended. + * + * @param self The Entity who owns a timer that finished. + * @param timerName The name of a timer attacked to self that has ended. + */ void OnTimerDone(Entity* self, std::string timerName) override; + /** + * @brief When the Client has finished rebuilding the Golem for the dragon, this function exposes the weak spot for a set amount of time. + * + * @param self The Entity that called this script. + * @param sender The Entity that sent a fired event. + * @param args The argument that tells us what event has been fired off. + * @param param1 Unused in this script. + * @param param2 Unused in this script. + * @param param3 Unused in this script. + */ void OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1, int32_t param2, int32_t param3) override; }; From 4f1df372a2dd4ce3b058356bfae5724bcc284a67 Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Mon, 24 Jan 2022 21:52:11 +0100 Subject: [PATCH 009/251] Make some Docker Compose volumes read-only --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index db90bd21..4b997e53 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -45,8 +45,8 @@ services: - BUILD_THREADS=${BUILD_THREADS:-1} - BUILD_VERSION=${BUILD_VERSION:-171022} volumes: - - ${CLIENT_PATH:?missing_client_path}:/client - - shared_configs:/shared_configs + - ${CLIENT_PATH:?missing_client_path}:/client:ro + - shared_configs:/shared_configs:ro depends_on: - database ports: From 477b629fafc756f68e514b4d1efac472dc52ebdb Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Tue, 25 Jan 2022 00:14:21 +0100 Subject: [PATCH 010/251] Fix UserManager not logging chosen name properly --- dGame/UserManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/UserManager.cpp b/dGame/UserManager.cpp index 1535364c..770dfdf2 100644 --- a/dGame/UserManager.cpp +++ b/dGame/UserManager.cpp @@ -270,7 +270,7 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet) return; } - Game::logger->Log("UserManager", "AccountID: %i is creating a character with name: %s\n", u->GetAccountID(), name.c_str()); + Game::logger->Log("UserManager", "AccountID: %i is creating a character with name: %s\n", u->GetAccountID(), name != "" ? name.c_str() : predefinedName.c_str()); //Now that the name is ok, we can get an objectID from Master: ObjectIDManager::Instance()->RequestPersistentID([=](uint32_t objectID) { From 910448b0e79f386efd33a5f62774c50718eecc47 Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Tue, 25 Jan 2022 00:35:26 +0100 Subject: [PATCH 011/251] Fix MasterServer not always closing database connection on exit --- dMasterServer/MasterServer.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/dMasterServer/MasterServer.cpp b/dMasterServer/MasterServer.cpp index b6ccac63..eb8a7f0f 100644 --- a/dMasterServer/MasterServer.cpp +++ b/dMasterServer/MasterServer.cpp @@ -66,7 +66,7 @@ int main(int argc, char** argv) { //Create all the objects we need to run our service: Game::logger = SetupLogger(); - if (!Game::logger) return 0; + if (!Game::logger) return -1; Game::logger->Log("MasterServer", "Starting Master server...\n"); Game::logger->Log("MasterServer", "Version: %i.%i\n", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR); @@ -118,7 +118,7 @@ int main(int argc, char** argv) { Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password); } catch (sql::SQLException& ex) { Game::logger->Log("MasterServer", "Got an error while connecting to the database: %s\n", ex.what()); - return 0; + return -1; } //If the first command line argument is -a or --account then make the user @@ -166,6 +166,10 @@ int main(int argc, char** argv) { delete statement; std::cout << "Account created successfully!\n"; + + Database::Destroy(); + delete Game::logger; + return 0; } @@ -266,7 +270,8 @@ int main(int argc, char** argv) { //10m shutdown for universe kill command if (shouldShutdown) { if (framesSinceKillUniverseCommand >= 40000) { - std::exit(0); + //Break main loop and exit + break; } else framesSinceKillUniverseCommand++; From 4cd38f117461643f6d3dcec8501849022797ed95 Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Tue, 25 Jan 2022 00:41:35 +0100 Subject: [PATCH 012/251] Use exit code macros --- dMasterServer/MasterServer.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dMasterServer/MasterServer.cpp b/dMasterServer/MasterServer.cpp index eb8a7f0f..aa79b5df 100644 --- a/dMasterServer/MasterServer.cpp +++ b/dMasterServer/MasterServer.cpp @@ -66,7 +66,7 @@ int main(int argc, char** argv) { //Create all the objects we need to run our service: Game::logger = SetupLogger(); - if (!Game::logger) return -1; + if (!Game::logger) return EXIT_FAILURE; Game::logger->Log("MasterServer", "Starting Master server...\n"); Game::logger->Log("MasterServer", "Version: %i.%i\n", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR); @@ -83,7 +83,7 @@ int main(int argc, char** argv) { std::ifstream cdclient_fd(cdclient_path); if (!cdclient_fd.good()) { Game::logger->Log("WorldServer", "%s could not be opened\n", cdclient_path.c_str()); - return -1; + return EXIT_FAILURE; } cdclient_fd.close(); @@ -94,7 +94,7 @@ int main(int argc, char** argv) { Game::logger->Log("WorldServer", "Unable to connect to CDServer SQLite Database\n"); Game::logger->Log("WorldServer", "Error: %s\n", e.errorMessage()); Game::logger->Log("WorldServer", "Error Code: %i\n", e.errorCode()); - return -1; + return EXIT_FAILURE; } //Get CDClient initial information @@ -105,7 +105,7 @@ int main(int argc, char** argv) { Game::logger->Log("WorldServer", "May be caused by corrupted file: %s\n", cdclient_path.c_str()); Game::logger->Log("WorldServer", "Error: %s\n", e.errorMessage()); Game::logger->Log("WorldServer", "Error Code: %i\n", e.errorCode()); - return -1; + return EXIT_FAILURE; } //Connect to the MySQL Database @@ -118,7 +118,7 @@ int main(int argc, char** argv) { Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password); } catch (sql::SQLException& ex) { Game::logger->Log("MasterServer", "Got an error while connecting to the database: %s\n", ex.what()); - return -1; + return EXIT_FAILURE; } //If the first command line argument is -a or --account then make the user @@ -170,7 +170,7 @@ int main(int argc, char** argv) { Database::Destroy(); delete Game::logger; - return 0; + return EXIT_SUCCESS; } int maxClients = 999; @@ -324,7 +324,7 @@ int main(int argc, char** argv) { delete Game::server; delete Game::logger; - return 0; + return EXIT_SUCCESS; } dLogger* SetupLogger() { From 676611ed6f4b1f9966ff321f065557351d567eb0 Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Tue, 25 Jan 2022 03:13:34 +0100 Subject: [PATCH 013/251] Improve GitHub issue templates --- .github/ISSUE_TEMPLATE/bug_report.yaml | 10 +++++++++- .github/ISSUE_TEMPLATE/installation_issue.yaml | 8 ++++++++ .github/ISSUE_TEMPLATE/performance_issue.yaml | 16 ++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 1865c679..acee8898 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -18,6 +18,14 @@ body: - label: > I have pulled the latest version of the main branch of DarkflameServer and have confirmed that the issue exists there. required: true + - type: input + id: server-version + attributes: + label: DarkflameServer Version + description: > + DarkflameServer version or commit SHA + validations: + required: true - type: textarea id: problem attributes: @@ -29,7 +37,7 @@ body: - type: textarea id: reproduction attributes: - label: Reproduction steps + label: Reproduction Steps description: > Please provide a concise list of steps needed to reproduce this issue. validations: diff --git a/.github/ISSUE_TEMPLATE/installation_issue.yaml b/.github/ISSUE_TEMPLATE/installation_issue.yaml index 2fd9a84f..84478ea0 100644 --- a/.github/ISSUE_TEMPLATE/installation_issue.yaml +++ b/.github/ISSUE_TEMPLATE/installation_issue.yaml @@ -12,6 +12,14 @@ body: - label: > I have read the [installation guide](https://github.com/DarkflameUniverse/DarkflameServer/blob/main/README.md). required: true + - type: input + id: server-version + attributes: + label: DarkflameServer Version + description: > + DarkflameServer version or commit SHA + validations: + required: true - type: dropdown id: platform attributes: diff --git a/.github/ISSUE_TEMPLATE/performance_issue.yaml b/.github/ISSUE_TEMPLATE/performance_issue.yaml index 420a5381..8e712741 100644 --- a/.github/ISSUE_TEMPLATE/performance_issue.yaml +++ b/.github/ISSUE_TEMPLATE/performance_issue.yaml @@ -15,6 +15,22 @@ body: - label: > I have pulled the latest version of the main branch of DarkflameServer and have confirmed that the issue exists there. required: true + - type: input + id: server-version + attributes: + label: DarkflameServer Version + description: > + DarkflameServer version or commit SHA + validations: + required: true + - type: textarea + id: environment + attributes: + label: Environment + description: > + Please include the environment you're running DarkflameServer on (for example: Windows, macOS, Ubuntu, WSL, etc), available memory, number of CPU cores. + validations: + required: true - type: textarea id: example attributes: From 026654b0d0a5e10aa6a179922152e21183a77ea6 Mon Sep 17 00:00:00 2001 From: Avery Date: Mon, 31 Jan 2022 04:34:22 -0800 Subject: [PATCH 014/251] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 47f116db..42848839 100644 --- a/README.md +++ b/README.md @@ -245,7 +245,7 @@ The client script for the survival minigame has a bug in it which can cause the * Change `PlayerReady(self)` to `onPlayerReady(self)` * Save the file, overriding readonly mode if required -If you still experience the bug, try deleting/renaming `res/pack/scripts.pak`. +If you still experience the bug, try deleting/renaming `res/pack/scripts.pk`. ### Brick-By-Brick building From dac8ec621c7c20103ab70460dbb36de9f40bdfe8 Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 1 Feb 2022 08:48:23 -0800 Subject: [PATCH 015/251] Added stun immunity for bosses in Battle of Nimbus Station (#428) --- dScripts/WaveBossApe.cpp | 1 - dScripts/WaveBossHammerling.cpp | 1 - dScripts/WaveBossHorsemen.cpp | 1 - 3 files changed, 3 deletions(-) diff --git a/dScripts/WaveBossApe.cpp b/dScripts/WaveBossApe.cpp index c7fdccf2..e1860048 100644 --- a/dScripts/WaveBossApe.cpp +++ b/dScripts/WaveBossApe.cpp @@ -32,7 +32,6 @@ void WaveBossApe::OnFireEventServerSide(Entity *self, Entity *sender, std::strin auto* combatAIComponent = self->GetComponent(); if (combatAIComponent != nullptr) { combatAIComponent->SetDisabled(false); - combatAIComponent->SetStunImmune(false); } } else { BaseEnemyApe::OnFireEventServerSide(self, sender, args, param1, param2, param3); diff --git a/dScripts/WaveBossHammerling.cpp b/dScripts/WaveBossHammerling.cpp index cb161e94..6dce0ae3 100644 --- a/dScripts/WaveBossHammerling.cpp +++ b/dScripts/WaveBossHammerling.cpp @@ -19,7 +19,6 @@ void WaveBossHammerling::OnFireEventServerSide(Entity *self, Entity *sender, std auto* combatAIComponent = self->GetComponent(); if (combatAIComponent != nullptr) { combatAIComponent->SetDisabled(false); - combatAIComponent->SetStunImmune(false); } } } diff --git a/dScripts/WaveBossHorsemen.cpp b/dScripts/WaveBossHorsemen.cpp index 9f71867f..75bffa5b 100644 --- a/dScripts/WaveBossHorsemen.cpp +++ b/dScripts/WaveBossHorsemen.cpp @@ -20,7 +20,6 @@ WaveBossHorsemen::OnFireEventServerSide(Entity *self, Entity *sender, std::strin auto* combatAIComponent = self->GetComponent(); if (combatAIComponent != nullptr) { combatAIComponent->SetDisabled(false); - combatAIComponent->SetStunImmune(false); } } } From 13980c4133a45e1d2c0c8a37e72970296caac11c Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 2 Feb 2022 22:50:02 -0800 Subject: [PATCH 016/251] Added logic to Convert UScore to Coins for Level 45 Characters (#348) --- dCommon/dCommonVars.h | 3 +++ dGame/dComponents/CharacterComponent.cpp | 2 +- dGame/dGameMessages/GameMessages.cpp | 7 +++---- dGame/dGameMessages/GameMessages.h | 2 +- dGame/dMission/Mission.cpp | 22 ++++++++++++++-------- dGame/dUtilities/SlashCommandHandler.cpp | 4 ++-- dZoneManager/dZoneManager.cpp | 18 ++++++++++++++++++ dZoneManager/dZoneManager.h | 12 ++++++++++++ 8 files changed, 54 insertions(+), 16 deletions(-) diff --git a/dCommon/dCommonVars.h b/dCommon/dCommonVars.h index 4920249d..680c0c1e 100644 --- a/dCommon/dCommonVars.h +++ b/dCommon/dCommonVars.h @@ -469,6 +469,9 @@ enum eRebuildState : uint32_t { REBUILD_INCOMPLETE }; +/** + * The loot source's type. + */ enum eLootSourceType : int32_t { LOOT_SOURCE_NONE = 0, LOOT_SOURCE_CHEST, diff --git a/dGame/dComponents/CharacterComponent.cpp b/dGame/dComponents/CharacterComponent.cpp index 9337c324..c7a216f3 100644 --- a/dGame/dComponents/CharacterComponent.cpp +++ b/dGame/dComponents/CharacterComponent.cpp @@ -42,7 +42,7 @@ CharacterComponent::CharacterComponent(Entity* parent, Character* character) : C if (character->GetZoneID() != Game::server->GetZoneID()) { m_IsLanding = true; } - + if (LandingAnimDisabled(character->GetZoneID()) || LandingAnimDisabled(Game::server->GetZoneID()) || m_LastRocketConfig.empty()) { m_IsLanding = false; //Don't make us land on VE/minigames lol } diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 58a3d014..c327ab83 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -558,7 +558,7 @@ void GameMessages::SendNotifyMissionTask(Entity* entity, const SystemAddress& sy SEND_PACKET } -void GameMessages::SendModifyLEGOScore(Entity* entity, const SystemAddress& sysAddr, int64_t score, int sourceType) { +void GameMessages::SendModifyLEGOScore(Entity* entity, const SystemAddress& sysAddr, int64_t score, eLootSourceType sourceType) { CBITSTREAM CMSGHEADER @@ -566,9 +566,8 @@ void GameMessages::SendModifyLEGOScore(Entity* entity, const SystemAddress& sysA bitStream.Write((uint16_t)GAME_MSG_MODIFY_LEGO_SCORE); bitStream.Write(score); - //Stuff stolen from the old codebase, no idea why this works. The proper implementation didn't for some reason. - bitStream.Write((int32_t)129); - bitStream.Write((unsigned char)0); + bitStream.Write(sourceType != LOOT_SOURCE_NONE); + if (sourceType != LOOT_SOURCE_NONE) bitStream.Write(sourceType); SEND_PACKET } diff --git a/dGame/dGameMessages/GameMessages.h b/dGame/dGameMessages/GameMessages.h index 579d4ec3..430d48d9 100644 --- a/dGame/dGameMessages/GameMessages.h +++ b/dGame/dGameMessages/GameMessages.h @@ -69,7 +69,7 @@ namespace GameMessages { void SendNotifyMission(Entity * entity, const SystemAddress& sysAddr, int missionID, int missionState, bool sendingRewards); void SendNotifyMissionTask(Entity * entity, const SystemAddress& sysAddr, int missionID, int taskMask, std::vector updates); - void SendModifyLEGOScore(Entity* entity, const SystemAddress& sysAddr, int64_t score, int sourceType); + void SendModifyLEGOScore(Entity* entity, const SystemAddress& sysAddr, int64_t score, eLootSourceType sourceType); void SendUIMessageServerToSingleClient(Entity* entity, const SystemAddress& sysAddr, const std::string& message, NDGFxValue args); void SendUIMessageServerToAllClients(const std::string& message, NDGFxValue args); diff --git a/dGame/dMission/Mission.cpp b/dGame/dMission/Mission.cpp index f2f06e58..28f4b278 100644 --- a/dGame/dMission/Mission.cpp +++ b/dGame/dMission/Mission.cpp @@ -14,6 +14,7 @@ #include "dLocale.h" #include "dLogger.h" #include "dServer.h" +#include "dZoneManager.h" Mission::Mission(MissionComponent* missionComponent, const uint32_t missionId) { m_MissionComponent = missionComponent; @@ -421,11 +422,15 @@ void Mission::YieldRewards() { } } + int32_t coinsToSend = 0; if (info->LegoScore > 0) { - characterComponent->SetUScore(characterComponent->GetUScore() + info->LegoScore); - - if (info->isMission) { - GameMessages::SendModifyLEGOScore(entity, entity->GetSystemAddress(), info->LegoScore, 2); + eLootSourceType lootSource = info->isMission ? LOOT_SOURCE_MISSION : LOOT_SOURCE_ACHIEVEMENT; + if(characterComponent->GetLevel() >= dZoneManager::Instance()->GetMaxLevel()) { + // Since the character is at the level cap we reward them with coins instead of UScore. + coinsToSend += info->LegoScore * dZoneManager::Instance()->GetLevelCapCurrencyConversion(); + } else { + characterComponent->SetUScore(characterComponent->GetUScore() + info->LegoScore); + GameMessages::SendModifyLEGOScore(entity, entity->GetSystemAddress(), info->LegoScore, lootSource); } } @@ -455,8 +460,9 @@ void Mission::YieldRewards() { inventoryComponent->AddItem(pair.first, count); } - if (info->reward_currency_repeatable > 0) { - character->SetCoins(character->GetCoins() + info->reward_currency_repeatable, LOOT_SOURCE_MISSION); + if (info->reward_currency_repeatable > 0 || coinsToSend > 0) { + eLootSourceType lootSource = info->isMission ? LOOT_SOURCE_MISSION : LOOT_SOURCE_ACHIEVEMENT; + character->SetCoins(character->GetCoins() + info->reward_currency_repeatable + coinsToSend, lootSource); } return; @@ -487,9 +493,9 @@ void Mission::YieldRewards() { inventoryComponent->AddItem(pair.first, count); } - if (info->reward_currency > 0) { + if (info->reward_currency > 0 || coinsToSend > 0) { eLootSourceType lootSource = info->isMission ? LOOT_SOURCE_MISSION : LOOT_SOURCE_ACHIEVEMENT; - character->SetCoins(character->GetCoins() + info->reward_currency, lootSource); + character->SetCoins(character->GetCoins() + info->reward_currency + coinsToSend, lootSource); } if (info->reward_maxinventory > 0) { diff --git a/dGame/dUtilities/SlashCommandHandler.cpp b/dGame/dUtilities/SlashCommandHandler.cpp index 5779fe3f..66502645 100644 --- a/dGame/dUtilities/SlashCommandHandler.cpp +++ b/dGame/dUtilities/SlashCommandHandler.cpp @@ -1304,8 +1304,8 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit CharacterComponent* character = entity->GetComponent(); if (character) character->SetUScore(character->GetUScore() + uscore); - - GameMessages::SendModifyLEGOScore(entity, entity->GetSystemAddress(), uscore, LOOTTYPE_NONE); + // LOOT_SOURCE_MODERATION should work but it doesn't. Relog to see uscore changes + GameMessages::SendModifyLEGOScore(entity, entity->GetSystemAddress(), uscore, LOOT_SOURCE_MODERATION); } if (chatCommand == "pos" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { diff --git a/dZoneManager/dZoneManager.cpp b/dZoneManager/dZoneManager.cpp index d2188f4f..6f11e8e4 100644 --- a/dZoneManager/dZoneManager.cpp +++ b/dZoneManager/dZoneManager.cpp @@ -118,6 +118,24 @@ LWOZONEID dZoneManager::GetZoneID() const return m_ZoneID; } +uint32_t dZoneManager::GetMaxLevel() { + if (m_MaxLevel == 0) { + auto tableData = CDClientDatabase::ExecuteQuery("SELECT LevelCap FROM WorldConfig WHERE WorldConfigID = 1 LIMIT 1;"); + m_MaxLevel = tableData.getIntField(0, -1); + tableData.finalize(); + } + return m_MaxLevel; +} + +int32_t dZoneManager::GetLevelCapCurrencyConversion() { + if (m_CurrencyConversionRate == 0) { + auto tableData = CDClientDatabase::ExecuteQuery("SELECT LevelCapCurrencyConversion FROM WorldConfig WHERE WorldConfigID = 1 LIMIT 1;"); + m_CurrencyConversionRate = tableData.getIntField(0, -1); + tableData.finalize(); + } + return m_CurrencyConversionRate; +} + void dZoneManager::Update(float deltaTime) { for (auto spawner : m_Spawners) { spawner.second->Update(deltaTime); diff --git a/dZoneManager/dZoneManager.h b/dZoneManager/dZoneManager.h index f6da56cd..8eb04cca 100644 --- a/dZoneManager/dZoneManager.h +++ b/dZoneManager/dZoneManager.h @@ -33,6 +33,8 @@ public: void NotifyZone(const dZoneNotifier& notifier, const LWOOBJID& objectID); //Notifies the zone of a certain event or command. void AddSpawner(LWOOBJID id, Spawner* spawner); LWOZONEID GetZoneID() const; + uint32_t GetMaxLevel(); + int32_t GetLevelCapCurrencyConversion(); LWOOBJID MakeSpawner(SpawnerInfo info); Spawner* GetSpawner(LWOOBJID id); void RemoveSpawner(LWOOBJID id); @@ -42,6 +44,16 @@ public: Entity* GetZoneControlObject() { return m_ZoneControlObject; } private: + /** + * The maximum level of the world. + */ + uint32_t m_MaxLevel = 0; + + /** + * The ratio of LEGO Score to currency when the character has hit the max level. + */ + int32_t m_CurrencyConversionRate = 0; + static dZoneManager* m_Address; //Singleton Zone* m_pZone; LWOZONEID m_ZoneID; From 0d0949f5f08233681f329112ca9e32c334c00727 Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Thu, 3 Feb 2022 23:03:54 +0100 Subject: [PATCH 017/251] Adjust chosen character name logging --- dGame/UserManager.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dGame/UserManager.cpp b/dGame/UserManager.cpp index 770dfdf2..e8352fd2 100644 --- a/dGame/UserManager.cpp +++ b/dGame/UserManager.cpp @@ -244,7 +244,6 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet) uint32_t middleNameIndex = PacketUtils::ReadPacketU32(78, packet); uint32_t lastNameIndex = PacketUtils::ReadPacketU32(82, packet); std::string predefinedName = GetPredefinedName(firstNameIndex, middleNameIndex, lastNameIndex); - Game::logger->Log("UserManager", "Got predefined name: %s\n", predefinedName.c_str()); uint32_t shirtColor = PacketUtils::ReadPacketU32(95, packet); uint32_t shirtStyle = PacketUtils::ReadPacketU32(99, packet); @@ -261,16 +260,23 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet) LOT pantsLOT = FindCharPantsID(pantsColor); if (name != "" && !UserManager::IsNameAvailable(name)) { + Game::logger->Log("UserManager", "AccountID: %i chose unavailable name: %s\n", u->GetAccountID(), name.c_str()); WorldPackets::SendCharacterCreationResponse(sysAddr, CREATION_RESPONSE_CUSTOM_NAME_IN_USE); return; } if (!IsNameAvailable(predefinedName)) { + Game::logger->Log("UserManager", "AccountID: %i chose unavailable predefined name: %s\n", u->GetAccountID(), predefinedName.c_str()); WorldPackets::SendCharacterCreationResponse(sysAddr, CREATION_RESPONSE_PREDEFINED_NAME_IN_USE); return; } - Game::logger->Log("UserManager", "AccountID: %i is creating a character with name: %s\n", u->GetAccountID(), name != "" ? name.c_str() : predefinedName.c_str()); + if (name == "") { + Game::logger->Log("UserManager", "AccountID: %i is creating a character with predefined name: %s\n", u->GetAccountID(), predefinedName.c_str()); + } + else { + Game::logger->Log("UserManager", "AccountID: %i is creating a character with name: %s (temporary: %s)\n", u->GetAccountID(), name.c_str(), predefinedName.c_str()); + } //Now that the name is ok, we can get an objectID from Master: ObjectIDManager::Instance()->RequestPersistentID([=](uint32_t objectID) { From f0a4324bd456cfaf648d47ec58b2527df71c1d65 Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 3 Feb 2022 22:32:45 -0800 Subject: [PATCH 018/251] Fixed an issue where leave-zone was working outside of instanced zones (#431) --- dGame/dUtilities/SlashCommandHandler.cpp | 26 +++++++----------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/dGame/dUtilities/SlashCommandHandler.cpp b/dGame/dUtilities/SlashCommandHandler.cpp index 66502645..67336eb7 100644 --- a/dGame/dUtilities/SlashCommandHandler.cpp +++ b/dGame/dUtilities/SlashCommandHandler.cpp @@ -304,28 +304,16 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit if ((chatCommand == "leave-zone")) { const auto currentZone = dZoneManager::Instance()->GetZone()->GetZoneID().GetMapID(); - auto newZone = 1100; - - switch (currentZone) - { - case 1101: - newZone = 1100; - break; - case 1204: - newZone = 1200; - break; - default: - newZone = 1100; - break; - } - - if (currentZone == newZone) - { + auto newZone = 0; + if (currentZone % 100 == 0) { ChatPackets::SendSystemMessage(sysAddr, u"You are not in an instanced zone."); - return; + } else { + newZone = (currentZone / 100) * 100; } - + // If new zone would be inaccessible, then default to Avant Gardens. + if (!CheckIfAccessibleZone(newZone)) newZone = 1100; + ChatPackets::SendSystemMessage(sysAddr, u"Leaving zone..."); const auto objid = entity->GetObjectID(); From dc2bd76abae758bdf31a1e0262e44f219b901d59 Mon Sep 17 00:00:00 2001 From: wincent Date: Sat, 5 Feb 2022 12:27:24 +0100 Subject: [PATCH 019/251] Fixed scripted powerup spawners When applied this commit fixes scripted powerups --- dScripts/ScriptedPowerupSpawner.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dScripts/ScriptedPowerupSpawner.cpp b/dScripts/ScriptedPowerupSpawner.cpp index 5fc013c1..fe35dfed 100644 --- a/dScripts/ScriptedPowerupSpawner.cpp +++ b/dScripts/ScriptedPowerupSpawner.cpp @@ -15,6 +15,11 @@ void ScriptedPowerupSpawner::OnTimerDone(Entity *self, std::string message) { const auto itemLOT = self->GetVar(u"lootLOT"); + // Build drop table + std::unordered_map drops; + + drops.emplace(itemLOT, 1); + // Spawn the required number of powerups auto* owner = EntityManager::Instance()->GetEntity(self->GetSpawnerID()); if (owner != nullptr) { @@ -24,7 +29,7 @@ void ScriptedPowerupSpawner::OnTimerDone(Entity *self, std::string message) { renderComponent->PlayEffect(0, u"cast", "N_cast"); } - LootGenerator::Instance().DropLoot(owner, self, itemLOT, 0, 1); + LootGenerator::Instance().DropLoot(owner, self, drops, 0, 0); } // Increment the current cycle From c6f220ee31afb035a76eb9e98a3ee908d29203ee Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 5 Feb 2022 03:28:17 -0800 Subject: [PATCH 020/251] Implementing and Fixing All Racing Achievements (#366) * Grammatical changes in comments * Grammatical fixes in comments Small grammatical fixes found in comments throughout the code. * Added descriptions to functions Added descriptions to functions that didn't have them to keep the code well documented * Created RacingTaskParam.h Created RacingTaskParam so eliminate magic numbers in the original implementation of completing racing missions. * Updated magic numbers in Mission.cpp Updated magic numbers in Mission.cpp to a meaningful name. * Implemented racing smashable task progression Previously, races did not progress tasks for smashing Entities. Now all achievements tracking smashables track them correctly. This has been implemented in the three Entities that can be smashed in a race (imagination boxes, track specific smashables, Forbidden Valley dragon eggs). * Updated race imagination task progression Race imagination now no longer uses a magic number when passed to missionComponent. Instead we use a number defined in an enum located in RacingTaskParam.h * Updated Race task checks Racing tasks for completing races without smashing now no longer auto complete the whole chain of missions. Tasks that track placing on tracks and races overall now properly complete. Tasks that count how many missions in a zone are completed now function. Tasks that track race completions in multiple areas now function. * Updated RacingControlComponent.cpp Fixed any tasks that required 3 players to now require 3 or more players in a race to progress. This restriction is ignored if the world config opted in for solo racing to allow progression in solo worlds. Updated magic numbers sent into missionComponent->Progress to an enum created in this PR. Fixed some indentation. * Fixed a grammatical error in variable name Fixed a grammatical error in the enum for task params --- dGame/Entity.cpp | 2 +- dGame/EntityManager.cpp | 2 +- dGame/dComponents/RacingControlComponent.cpp | 46 +++++++++----------- dGame/dComponents/RacingControlComponent.h | 4 +- dGame/dMission/Mission.cpp | 5 +++ dGame/dMission/MissionTask.cpp | 23 +++++----- dGame/dMission/MissionTask.h | 2 +- dGame/dMission/MissionTaskType.h | 2 +- dGame/dMission/RacingTaskParam.h | 20 +++++++++ dScripts/FvRaceSmashEggImagineServer.cpp | 10 +++-- dScripts/RaceImagineCrateServer.cpp | 24 +++++----- dScripts/RaceImagineCrateServer.h | 6 +++ dScripts/RaceImaginePowerup.cpp | 15 +++---- dScripts/RaceSmashServer.cpp | 9 +++- dScripts/RaceSmashServer.h | 6 +++ 15 files changed, 109 insertions(+), 67 deletions(-) create mode 100644 dGame/dMission/RacingTaskParam.h diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index dd6df1d4..6515b9b4 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -346,7 +346,7 @@ void Entity::Initialize() } /** - * Multiple components require te destructible component. + * Multiple components require the destructible component. */ int buffComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, COMPONENT_TYPE_BUFF); diff --git a/dGame/EntityManager.cpp b/dGame/EntityManager.cpp index b9c8763b..8fb75fb2 100644 --- a/dGame/EntityManager.cpp +++ b/dGame/EntityManager.cpp @@ -45,7 +45,7 @@ std::vector EntityManager::m_GhostingExcludedLOTs = { 9524, 12408, - // AG - Fotrace + // AG - Footrace 4967 }; diff --git a/dGame/dComponents/RacingControlComponent.cpp b/dGame/dComponents/RacingControlComponent.cpp index bbd85672..27df339d 100644 --- a/dGame/dComponents/RacingControlComponent.cpp +++ b/dGame/dComponents/RacingControlComponent.cpp @@ -15,6 +15,7 @@ #include "Player.h" #include "PossessableComponent.h" #include "PossessorComponent.h" +#include "RacingTaskParam.h" #include "Spawner.h" #include "VehiclePhysicsComponent.h" #include "dServer.h" @@ -401,18 +402,18 @@ void RacingControlComponent::HandleMessageBoxResponse(Entity *player, auto *missionComponent = player->GetComponent(); - if (missionComponent != nullptr) { - missionComponent->Progress( - MissionTaskType::MISSION_TASK_TYPE_RACING, 0, 13); // Enter race - missionComponent->Progress( - MissionTaskType::MISSION_TASK_TYPE_RACING, data->finished, - 1); // Finish with rating, one track - missionComponent->Progress( - MissionTaskType::MISSION_TASK_TYPE_RACING, data->finished, - 15); // Finish with rating, multiple tracks - missionComponent->Progress( - MissionTaskType::MISSION_TASK_TYPE_RACING, data->smashedTimes, - 10); // Safe driver type missions + if (missionComponent == nullptr) return; + + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, 0, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_COMPETED_IN_RACE); // Progress task for competing in a race + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, data->smashedTimes, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_SAFE_DRIVER); // Finish a race without being smashed. + + // If solo racing is enabled OR if there are 3 players in the race, progress placement tasks. + if(m_SoloRacing || m_LoadedPlayers > 2) { + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, data->finished, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_FINISH_WITH_PLACEMENT); // Finish in 1st place on a race + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, data->finished, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_FIRST_PLACE_MULTIPLE_TRACKS); // Finish in 1st place on multiple tracks. + if(m_Finished != 1) return; + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, dZoneManager::Instance()->GetZone()->GetWorldID(), (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_WIN_RACE_IN_WORLD); // Finished first place in specific world. + } } else if (id == "ACT_RACE_EXIT_THE_RACE?" || id == "Exit") { auto *vehicle = EntityManager::Instance()->GetEntity(data->vehicleID); @@ -809,9 +810,7 @@ void RacingControlComponent::Update(float deltaTime) { // Reached the start point, lapped if (respawnIndex == 0) { - time_t lapTime = - std::time(nullptr) - - (player.lap == 1 ? m_StartTime : player.lapTime); + time_t lapTime = std::time(nullptr) - (player.lap == 1 ? m_StartTime : player.lapTime); // Cheating check if (lapTime < 40) { @@ -833,10 +832,9 @@ void RacingControlComponent::Update(float deltaTime) { playerEntity->GetComponent(); if (missionComponent != nullptr) { - // Lap time - missionComponent->Progress( - MissionTaskType::MISSION_TASK_TYPE_RACING, - (lapTime)*1000, 2); + + // Progress lap time tasks + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, (lapTime)*1000, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_LAP_TIME); if (player.lap == 3) { m_Finished++; @@ -852,15 +850,11 @@ void RacingControlComponent::Update(float deltaTime) { raceTime, raceTime * 1000); // Entire race time - missionComponent->Progress( - MissionTaskType::MISSION_TASK_TYPE_RACING, - (raceTime)*1000, 3); + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, (raceTime)*1000, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_TOTAL_TRACK_TIME); - auto *characterComponent = - playerEntity->GetComponent(); + auto *characterComponent = playerEntity->GetComponent(); if (characterComponent != nullptr) { - characterComponent->TrackRaceCompleted(m_Finished == - 1); + characterComponent->TrackRaceCompleted(m_Finished == 1); } // TODO: Figure out how to update the GUI leaderboard. diff --git a/dGame/dComponents/RacingControlComponent.h b/dGame/dComponents/RacingControlComponent.h index 0dbb9eaa..63d5b2e4 100644 --- a/dGame/dComponents/RacingControlComponent.h +++ b/dGame/dComponents/RacingControlComponent.h @@ -146,7 +146,7 @@ public: void HandleMessageBoxResponse(Entity* player, const std::string& id); /** - * Get the reacing data from a player's LWOOBJID. + * Get the racing data from a player's LWOOBJID. */ RacingPlayerInfo* GetPlayerData(LWOOBJID playerID); @@ -230,7 +230,7 @@ private: std::vector m_LobbyPlayers; /** - * The number of players that have fi nished the race + * The number of players that have finished the race */ uint32_t m_Finished; diff --git a/dGame/dMission/Mission.cpp b/dGame/dMission/Mission.cpp index 28f4b278..854782f9 100644 --- a/dGame/dMission/Mission.cpp +++ b/dGame/dMission/Mission.cpp @@ -11,6 +11,7 @@ #include "GameMessages.h" #include "Mail.h" #include "MissionComponent.h" +#include "RacingTaskParam.h" #include "dLocale.h" #include "dLogger.h" #include "dServer.h" @@ -314,6 +315,10 @@ void Mission::Complete(const bool yieldRewards) { missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_MISSION_COMPLETE, info->id); + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, info->id, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_COMPLETE_ANY_RACING_TASK); + + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, info->id, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_COMPLETE_TRACK_TASKS); + auto* missionEmailTable = CDClientManager::Instance()->GetTable("MissionEmail"); const auto missionId = GetMissionId(); diff --git a/dGame/dMission/MissionTask.cpp b/dGame/dMission/MissionTask.cpp index 423966c4..d90f7682 100644 --- a/dGame/dMission/MissionTask.cpp +++ b/dGame/dMission/MissionTask.cpp @@ -425,28 +425,27 @@ void MissionTask::Progress(int32_t value, LWOOBJID associate, const std::string& { if (parameters.empty()) break; - if (!InAllTargets(dZoneManager::Instance()->GetZone()->GetWorldID())) break; + if (!InAllTargets(dZoneManager::Instance()->GetZone()->GetWorldID()) && !(parameters[0] == 4 || parameters[0] == 5) && !InAllTargets(value)) break; if (parameters[0] != associate) break; - if (associate == 1 || associate == 15) + if (associate == 1 || associate == 15 || associate == 2 || associate == 3) { if (value > info->targetValue) break; - AddProgress(1); - } - else if (associate == 2 || associate == 3) - { - if (info->targetValue < value) break; - AddProgress(info->targetValue); } else if (associate == 10) { - if (info->targetValue > value) - { - AddProgress(info->targetValue); - } + // If the player did not crash during the race, progress this task by count. + if (value != 0) break; + + AddProgress(count); + } + else if (associate == 4 || associate == 5 || associate == 14) + { + if (!InAllTargets(value)) break; + AddProgress(count); } else { diff --git a/dGame/dMission/MissionTask.h b/dGame/dMission/MissionTask.h index 6cdc4039..b77b9c59 100644 --- a/dGame/dMission/MissionTask.h +++ b/dGame/dMission/MissionTask.h @@ -19,7 +19,7 @@ public: * Attempts to progress this task using the provided parameters. Note that the behavior of this method is different * for each mission task type. * @param value the value to progress by - * @param associate optional object ID of an entity that was related to the porgression + * @param associate optional object ID of an entity that was related to the progression * @param targets optional multiple targets that need to be met to progress * @param count a number that indicates the times to progress */ diff --git a/dGame/dMission/MissionTaskType.h b/dGame/dMission/MissionTaskType.h index 8519e0d9..6643d161 100644 --- a/dGame/dMission/MissionTaskType.h +++ b/dGame/dMission/MissionTaskType.h @@ -5,7 +5,7 @@ enum class MissionTaskType : int { MISSION_TASK_TYPE_UNKNOWN = -1, //!< The task type is unknown MISSION_TASK_TYPE_SMASH = 0, //!< A task for smashing something MISSION_TASK_TYPE_SCRIPT = 1, //!< A task handled by a server LUA script - MISSION_TASK_TYPE_ACTIVITY = 2, //!< A task for completing a quickbuild + MISSION_TASK_TYPE_ACTIVITY = 2, //!< A task for completing a quickbuild MISSION_TASK_TYPE_ENVIRONMENT = 3, //!< A task for something in the environment MISSION_TASK_TYPE_MISSION_INTERACTION = 4, //!< A task for interacting with a mission MISSION_TASK_TYPE_EMOTE = 5, //!< A task for playing an emote diff --git a/dGame/dMission/RacingTaskParam.h b/dGame/dMission/RacingTaskParam.h new file mode 100644 index 00000000..e85d9f91 --- /dev/null +++ b/dGame/dMission/RacingTaskParam.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +enum class RacingTaskParam : int32_t { + RACING_TASK_PARAM_FINISH_WITH_PLACEMENT = 1, //SerializeEntity(killer); } - // Crate is killed by the car + // get possessor to progress statistics and tasks. auto* possessableComponent = killer->GetComponent(); if (possessableComponent != nullptr) { auto* possessor = EntityManager::Instance()->GetEntity(possessableComponent->GetPossessor()); if (possessor != nullptr) { + auto* missionComponent = possessor->GetComponent(); auto* characterComponent = possessor->GetComponent(); if (characterComponent != nullptr) { characterComponent->UpdatePlayerStatistic(ImaginationPowerUpsCollected); characterComponent->UpdatePlayerStatistic(RacingSmashablesSmashed); } + if (missionComponent == nullptr) return; + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, self->GetLOT(), (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_SMASH_DRAGON_EGGS); } } diff --git a/dScripts/RaceImagineCrateServer.cpp b/dScripts/RaceImagineCrateServer.cpp index f233d408..166b3363 100644 --- a/dScripts/RaceImagineCrateServer.cpp +++ b/dScripts/RaceImagineCrateServer.cpp @@ -1,10 +1,11 @@ -#include "RaceImagineCrateServer.h" -#include "SkillComponent.h" -#include "GameMessages.h" -#include "EntityManager.h" -#include "DestroyableComponent.h" #include "CharacterComponent.h" +#include "DestroyableComponent.h" +#include "EntityManager.h" +#include "GameMessages.h" #include "PossessableComponent.h" +#include "RaceImagineCrateServer.h" +#include "RacingTaskParam.h" +#include "SkillComponent.h" void RaceImagineCrateServer::OnDie(Entity* self, Entity* killer) { @@ -13,8 +14,6 @@ void RaceImagineCrateServer::OnDie(Entity* self, Entity* killer) return; } - //GameMessages::SendPlayFXEffect(self, -1, u"pickup", "", LWOOBJID_EMPTY, 1, 1, true); - self->SetVar(u"bIsDead", true); if (killer == nullptr) @@ -38,21 +37,24 @@ void RaceImagineCrateServer::OnDie(Entity* self, Entity* killer) EntityManager::Instance()->SerializeEntity(killer); } - // Crate is killed by the car + // Find possessor of race car to progress missions and update stats. auto* possessableComponent = killer->GetComponent(); if (possessableComponent != nullptr) { auto* possessor = EntityManager::Instance()->GetEntity(possessableComponent->GetPossessor()); if (possessor != nullptr) { + auto* missionComponent = possessor->GetComponent(); auto* characterComponent = possessor->GetComponent(); + if (characterComponent != nullptr) { characterComponent->UpdatePlayerStatistic(RacingImaginationCratesSmashed); characterComponent->UpdatePlayerStatistic(RacingSmashablesSmashed); } + + // Progress racing smashable missions + if(missionComponent == nullptr) return; + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, 0, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_SMASHABLES); } } - - - //skillComponent->CalculateBehavior(586, 9450, killer->GetObjectID(), true); } diff --git a/dScripts/RaceImagineCrateServer.h b/dScripts/RaceImagineCrateServer.h index 9e8ffa5a..42f36b30 100644 --- a/dScripts/RaceImagineCrateServer.h +++ b/dScripts/RaceImagineCrateServer.h @@ -4,5 +4,11 @@ class RaceImagineCrateServer : public CppScripts::Script { public: +/** + * @brief When a boost smashable has been smashed, this function is called + * + * @param self The Entity that called this function. + * @param killer The Entity that killed this Entity. + */ void OnDie(Entity* self, Entity* killer) override; }; diff --git a/dScripts/RaceImaginePowerup.cpp b/dScripts/RaceImaginePowerup.cpp index 91354acf..43e20e9d 100644 --- a/dScripts/RaceImaginePowerup.cpp +++ b/dScripts/RaceImaginePowerup.cpp @@ -1,9 +1,10 @@ -#include "RaceImaginePowerup.h" -#include "DestroyableComponent.h" -#include "PossessorComponent.h" -#include "EntityManager.h" #include "CharacterComponent.h" +#include "DestroyableComponent.h" +#include "EntityManager.h" #include "PossessableComponent.h" +#include "PossessorComponent.h" +#include "RaceImaginePowerup.h" +#include "RacingTaskParam.h" void RaceImaginePowerup::OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1, @@ -36,9 +37,7 @@ void RaceImaginePowerup::OnFireEventServerSide(Entity *self, Entity *sender, std auto* missionComponent = sender->GetComponent(); - if (missionComponent != nullptr) - { - missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, self->GetLOT(), 12); - } + if (missionComponent == nullptr) return; + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, self->GetLOT(), (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_COLLECT_IMAGINATION); } } diff --git a/dScripts/RaceSmashServer.cpp b/dScripts/RaceSmashServer.cpp index 4fd09f19..059ac430 100644 --- a/dScripts/RaceSmashServer.cpp +++ b/dScripts/RaceSmashServer.cpp @@ -1,7 +1,8 @@ -#include "RaceSmashServer.h" #include "CharacterComponent.h" #include "EntityManager.h" #include "PossessableComponent.h" +#include "RaceSmashServer.h" +#include "RacingTaskParam.h" void RaceSmashServer::OnDie(Entity *self, Entity *killer) { // Crate is smashed by the car @@ -11,10 +12,16 @@ void RaceSmashServer::OnDie(Entity *self, Entity *killer) { auto* possessor = EntityManager::Instance()->GetEntity(possessableComponent->GetPossessor()); if (possessor != nullptr) { + auto* missionComponent = possessor->GetComponent(); auto* characterComponent = possessor->GetComponent(); + if (characterComponent != nullptr) { characterComponent->UpdatePlayerStatistic(RacingSmashablesSmashed); } + + // Progress racing smashable missions + if(missionComponent == nullptr) return; + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, 0, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_SMASHABLES); } } } diff --git a/dScripts/RaceSmashServer.h b/dScripts/RaceSmashServer.h index 750bc00a..7fa1441d 100644 --- a/dScripts/RaceSmashServer.h +++ b/dScripts/RaceSmashServer.h @@ -2,5 +2,11 @@ #include "CppScripts.h" class RaceSmashServer : public CppScripts::Script { + /** + * @brief When a smashable has been destroyed, this function is called. + * + * @param self The Entity that called this function. + * @param killer The Entity that killed this Entity. + */ void OnDie(Entity *self, Entity *killer) override; }; From fe178bf745b3d4b5c5b83191ae4043f21e16a3be Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 5 Feb 2022 03:54:12 -0800 Subject: [PATCH 021/251] Fully Implemented Shooting Gallery Mission and Achievement Fixes (#381) * Fixed tab indent * Fully implemented Achievement tracking for Shooting Gallery - Removed logging in MissionTask.cpp and moved the checks for mission progression to after checking the instance. - Implemented the achievement tracking in SGCannon as well as tracking of the maximum hit streak and progression of enemy smashes in the shooting gallery. --- dGame/dMission/MissionTask.cpp | 11 ++++------- dScripts/SGCannon.cpp | 16 ++++++++++++---- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/dGame/dMission/MissionTask.cpp b/dGame/dMission/MissionTask.cpp index d90f7682..12272008 100644 --- a/dGame/dMission/MissionTask.cpp +++ b/dGame/dMission/MissionTask.cpp @@ -338,9 +338,6 @@ void MissionTask::Progress(int32_t value, LWOOBJID associate, const std::string& case MissionTaskType::MISSION_TASK_TYPE_MINIGAME: { - if (targets != info->targetGroup || info->targetValue > value) - break; - auto* minigameManager = EntityManager::Instance()->GetEntity(associate); if (minigameManager == nullptr) break; @@ -356,10 +353,10 @@ void MissionTask::Progress(int32_t value, LWOOBJID associate, const std::string& break; } - Game::logger->Log("Minigame Task", "Progressing minigame with %s %d > %d (%d)\n", - targets.c_str(), value, info->targetValue, gameID); - SetProgress(info->target); - + if(info->targetGroup == targets && value >= info->targetValue) { + SetProgress(info->target); + break; + } break; } diff --git a/dScripts/SGCannon.cpp b/dScripts/SGCannon.cpp index a691443e..58e1d144 100644 --- a/dScripts/SGCannon.cpp +++ b/dScripts/SGCannon.cpp @@ -579,6 +579,8 @@ void SGCannon::StopGame(Entity *self, bool cancel) { self->GetObjectID(), "performact_score" ); + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_MINIGAME, self->GetVar(MaxStreakVariable), self->GetObjectID(), "performact_streak"); + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_ACTIVITY, m_CannonLot, 0, "", self->GetVar(TotalScoreVariable)); } LootGenerator::Instance().GiveActivityLoot(player, self, GetGameID(self), self->GetVar(TotalScoreVariable)); @@ -645,10 +647,6 @@ void SGCannon::RegisterHit(Entity* self, Entity* target, const std::string& time if (!self->GetVar(SuperChargeActiveVariable)) { self->SetVar(u"m_curStreak", self->GetVar(u"m_curStreak") + 1); - - if (self->GetVar(u"m_curStreak") > 12) { - self->SetVar(u"m_curStreak", 12); - } } } else { @@ -693,6 +691,14 @@ void SGCannon::RegisterHit(Entity* self, Entity* target, const std::string& time self->SetNetworkVar(u"updateScore", newScore); self->SetNetworkVar(u"beatHighScore", GeneralUtils::to_u16string(newScore)); + + auto* player = EntityManager::Instance()->GetEntity(self->GetVar(PlayerIDVariable)); + if (player == nullptr) return; + + auto missionComponent = player->GetComponent(); + if (missionComponent == nullptr) return; + + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_SMASH, spawnInfo.lot, self->GetObjectID()); } void SGCannon::UpdateStreak(Entity* self) @@ -722,6 +728,8 @@ void SGCannon::UpdateStreak(Entity* self) self->SetNetworkVar(u"UnMarkAll", true); } } + auto maxStreak = self->GetVar(MaxStreakVariable); + if (maxStreak < curStreak) self->SetVar(MaxStreakVariable, curStreak); } float_t SGCannon::GetCurrentBonus(Entity* self) From 6ba9eea9932124e2c042035e2de37208af1a2671 Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 5 Feb 2022 03:59:07 -0800 Subject: [PATCH 022/251] Added check to prevent accidental sentinel passive proc (#396) * Added check to prevent accidental sentinel passive proc Added a boolean to check if the player is at zero armor already and if so, do not trigger the passive ability. * Renamed variable and condensed armor check --- dGame/dComponents/DestroyableComponent.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dGame/dComponents/DestroyableComponent.cpp b/dGame/dComponents/DestroyableComponent.cpp index 2199ff18..8c56d4c1 100644 --- a/dGame/dComponents/DestroyableComponent.cpp +++ b/dGame/dComponents/DestroyableComponent.cpp @@ -245,6 +245,9 @@ void DestroyableComponent::SetMaxHealth(float value, bool playAnim) { void DestroyableComponent::SetArmor(int32_t value) { m_DirtyHealth = true; + // If Destroyable Component already has zero armor do not trigger the passive ability again. + bool hadArmor = m_iArmor > 0; + auto* characterComponent = m_Parent->GetComponent(); if (characterComponent != nullptr) { characterComponent->TrackArmorDelta(value - m_iArmor); @@ -253,7 +256,7 @@ void DestroyableComponent::SetArmor(int32_t value) { m_iArmor = value; auto* inventroyComponent = m_Parent->GetComponent(); - if (m_iArmor == 0 && inventroyComponent != nullptr) { + if (m_iArmor == 0 && inventroyComponent != nullptr && hadArmor) { inventroyComponent->TriggerPassiveAbility(PassiveAbilityTrigger::SentinelArmor); } } From 828c457614b3e672e5c146e345129613c605fa23 Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 5 Feb 2022 04:00:10 -0800 Subject: [PATCH 023/251] Added script for Friend of the Ninja mission (#406) * Added script for Friend of the Ninja mission * Added comments --- dScripts/CppScripts.cpp | 3 +++ dScripts/FvPassThroughWall.cpp | 17 +++++++++++++++++ dScripts/FvPassThroughWall.h | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 dScripts/FvPassThroughWall.cpp create mode 100644 dScripts/FvPassThroughWall.h diff --git a/dScripts/CppScripts.cpp b/dScripts/CppScripts.cpp index 1201af6d..ca8f95cc 100644 --- a/dScripts/CppScripts.cpp +++ b/dScripts/CppScripts.cpp @@ -145,6 +145,7 @@ #include "ImgBrickConsoleQB.h" #include "ActParadoxPipeFix.h" #include "FvNinjaGuard.h" +#include "FvPassThroughWall.h" #include "FvBounceOverWall.h" // FB Scripts @@ -557,6 +558,8 @@ CppScripts::Script* CppScripts::GetScript(Entity* parent, const std::string& scr script = new ActParadoxPipeFix(); else if (scriptName == "scripts\\ai\\FV\\L_FV_NINJA_GUARDS.lua") script = new FvNinjaGuard(); + else if (scriptName == "scripts\\ai\\FV\\L_ACT_PASS_THROUGH_WALL.lua") + script = new FvPassThroughWall(); else if (scriptName == "scripts\\ai\\FV\\L_ACT_BOUNCE_OVER_WALL.lua") script = new FvBounceOverWall(); diff --git a/dScripts/FvPassThroughWall.cpp b/dScripts/FvPassThroughWall.cpp new file mode 100644 index 00000000..66130a9f --- /dev/null +++ b/dScripts/FvPassThroughWall.cpp @@ -0,0 +1,17 @@ +#include "FvPassThroughWall.h" +#include "InventoryComponent.h" + +void FvPassThroughWall::OnCollisionPhantom(Entity* self, Entity* target) { + auto missionComponent = target->GetComponent(); + if (missionComponent == nullptr) return; + + //Because at the moment we do not have an ItemComponent component, we check to make sure a Maelstrom-Infused hood is equipped. There are only three in the game right now. + auto inventoryComponent = target->GetComponent(); + // If no inventory component is found then abort. + if (inventoryComponent == nullptr) return; + // If no Maelstrom hoods are equipped then abort. + if (!inventoryComponent->IsEquipped(WhiteMaelstromHood) && !inventoryComponent->IsEquipped(BlackMaelstromHood) && !inventoryComponent->IsEquipped(RedMaelstromHood)) return; + + // Progress mission Friend of the Ninja since all prerequisites are met. + missionComponent->ForceProgress(friendOfTheNinjaMissionId, friendOfTheNinjaMissionUid, 1); +} \ No newline at end of file diff --git a/dScripts/FvPassThroughWall.h b/dScripts/FvPassThroughWall.h new file mode 100644 index 00000000..4dacc74e --- /dev/null +++ b/dScripts/FvPassThroughWall.h @@ -0,0 +1,34 @@ +#pragma once +#include "CppScripts.h" + +class FvPassThroughWall : public CppScripts::Script +{ + /** + * @brief This method is called when there is a collision with self from target. + * + * @param self The Entity that called this method. + * @param target The Entity that self is targetting. + */ + void OnCollisionPhantom(Entity* self, Entity* target) override; +private: + /** + * Mission ID for Friend of the Ninjas. + */ + int32_t friendOfTheNinjaMissionId = 848; + /** + * Mission UID for Friend of the Ninjas. + */ + int32_t friendOfTheNinjaMissionUid = 1221; + /** + * Item LOT for Maelstrom-Infused White Ninja Hood + */ + int32_t WhiteMaelstromHood = 2641; + /** + * Item LOT for Maelstrom-Infused Black Ninja Hood + */ + int32_t BlackMaelstromHood = 2642; + /** + * Item LOT for Red Ninja Hood - Maelstrom Infused + */ + int32_t RedMaelstromHood = 1889; +}; \ No newline at end of file From 77459af1d3ce7a57bbd8dd8d79a3d6c02cbf76f8 Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 5 Feb 2022 04:07:30 -0800 Subject: [PATCH 024/251] Removed AI Stopping after they use a skill (#407) * Removed SkillTime from stopping AI * Reverted Downtime removal --- dGame/dComponents/BaseCombatAIComponent.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dGame/dComponents/BaseCombatAIComponent.cpp b/dGame/dComponents/BaseCombatAIComponent.cpp index ae929d57..858b129d 100644 --- a/dGame/dComponents/BaseCombatAIComponent.cpp +++ b/dGame/dComponents/BaseCombatAIComponent.cpp @@ -192,7 +192,7 @@ void BaseCombatAIComponent::Update(const float deltaTime) { return; } - if (m_Stunned || m_SkillTime > 0) { + if (m_Stunned) { m_MovementAI->Stop(); return; @@ -358,7 +358,7 @@ void BaseCombatAIComponent::CalculateCombat(const float deltaTime) { return; } - m_Downtime = 0.5f; // TODO: find out if this is necessary + m_Downtime = 0.5f; auto* target = GetTargetEntity(); From 933cdee414e6abad4df40186c4ce43748e64f55e Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 5 Feb 2022 04:08:40 -0800 Subject: [PATCH 025/251] Implemented Model Pickup and Reputation achievements (#413) * Implemented Model Pickup and Reputation achievements * Moved mission progression to placement * Changed name to place --- dGame/dComponents/PropertyManagementComponent.cpp | 3 +++ dGame/dMission/Mission.cpp | 3 ++- dGame/dMission/MissionTask.cpp | 7 ++++++- dGame/dMission/MissionTaskType.h | 2 ++ 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/dGame/dComponents/PropertyManagementComponent.cpp b/dGame/dComponents/PropertyManagementComponent.cpp index bf89eb22..506c1608 100644 --- a/dGame/dComponents/PropertyManagementComponent.cpp +++ b/dGame/dComponents/PropertyManagementComponent.cpp @@ -388,6 +388,9 @@ void PropertyManagementComponent::UpdateModelPosition(const LWOOBJID id, const N EntityManager::Instance()->GetZoneControlEntity()->OnZonePropertyModelPlaced(entity); }); + // Progress place model missions + auto missionComponent = entity->GetComponent(); + if (missionComponent != nullptr) missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_PLACE_MODEL, 0); } void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int deleteReason) diff --git a/dGame/dMission/Mission.cpp b/dGame/dMission/Mission.cpp index 854782f9..a054c605 100644 --- a/dGame/dMission/Mission.cpp +++ b/dGame/dMission/Mission.cpp @@ -516,7 +516,8 @@ void Mission::YieldRewards() { } if (info->reward_reputation > 0) { - // TODO: In case of reputation, write code + // TODO: Track reputation in the character and database. + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_EARN_REPUTATION, 0, 0L, "", info->reward_reputation); } if (info->reward_maxhealth > 0) { diff --git a/dGame/dMission/MissionTask.cpp b/dGame/dMission/MissionTask.cpp index 12272008..4c49327d 100644 --- a/dGame/dMission/MissionTask.cpp +++ b/dGame/dMission/MissionTask.cpp @@ -460,6 +460,7 @@ void MissionTask::Progress(int32_t value, LWOOBJID associate, const std::string& case MissionTaskType::MISSION_TASK_TYPE_SMASH: case MissionTaskType::MISSION_TASK_TYPE_ITEM_COLLECTION: case MissionTaskType::MISSION_TASK_TYPE_PLAYER_FLAG: + case MissionTaskType::MISSION_TASK_TYPE_EARN_REPUTATION: { if (!InAllTargets(value)) break; @@ -467,7 +468,11 @@ void MissionTask::Progress(int32_t value, LWOOBJID associate, const std::string& break; } - + case MissionTaskType::MISSION_TASK_TYPE_PLACE_MODEL: + { + AddProgress(count); + break; + } default: Game::logger->Log("MissionTask", "Invalid mission task type (%i)!\n", static_cast(type)); return; diff --git a/dGame/dMission/MissionTaskType.h b/dGame/dMission/MissionTaskType.h index 6643d161..263bf470 100644 --- a/dGame/dMission/MissionTaskType.h +++ b/dGame/dMission/MissionTaskType.h @@ -16,9 +16,11 @@ enum class MissionTaskType : int { MISSION_TASK_TYPE_MINIGAME = 14, //!< A task for doing something in a minigame MISSION_TASK_TYPE_NON_MISSION_INTERACTION = 15, //!< A task for interacting with a non-mission MISSION_TASK_TYPE_MISSION_COMPLETE = 16, //!< A task for completing a mission + MISSION_TASK_TYPE_EARN_REPUTATION = 17, //!< A task for earning reputation MISSION_TASK_TYPE_POWERUP = 21, //!< A task for collecting a powerup MISSION_TASK_TYPE_PET_TAMING = 22, //!< A task for taming a pet MISSION_TASK_TYPE_RACING = 23, //!< A task for racing MISSION_TASK_TYPE_PLAYER_FLAG = 24, //!< A task for setting a player flag + MISSION_TASK_TYPE_PLACE_MODEL = 25, //!< A task for picking up a model MISSION_TASK_TYPE_VISIT_PROPERTY = 30 //!< A task for visiting a property }; From 84cf79906b85904b406353a3af730be9088eabf4 Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 5 Feb 2022 04:11:58 -0800 Subject: [PATCH 026/251] Frakjaw Battle instance fixes (#409) * Update NjMonastryBossInstance.cpp * Changed spawn position to be 1. * Changed stored variable from vector to int Added clarifying comments --- dScripts/NjMonastryBossInstance.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/dScripts/NjMonastryBossInstance.cpp b/dScripts/NjMonastryBossInstance.cpp index faf92edd..17c4b296 100644 --- a/dScripts/NjMonastryBossInstance.cpp +++ b/dScripts/NjMonastryBossInstance.cpp @@ -47,9 +47,8 @@ void NjMonastryBossInstance::OnStartup(Entity *self) { void NjMonastryBossInstance::OnPlayerLoaded(Entity *self, Entity *player) { ActivityTimerStop(self, WaitingForPlayersTimer); - // Join the player in the activity and charge for joining + // Join the player in the activity UpdatePlayer(self, player->GetObjectID()); - TakeActivityCost(self, player->GetObjectID()); // Buff the player auto* destroyableComponent = player->GetComponent(); @@ -59,23 +58,22 @@ void NjMonastryBossInstance::OnPlayerLoaded(Entity *self, Entity *player) { destroyableComponent->SetImagination((int32_t) destroyableComponent->GetMaxImagination()); } - // Track the player ID + // Add player ID to instance auto totalPlayersLoaded = self->GetVar>(TotalPlayersLoadedVariable); - if (totalPlayersLoaded.empty() || std::find(totalPlayersLoaded.begin(), totalPlayersLoaded.end(), player->GetObjectID()) != totalPlayersLoaded.end()) { - totalPlayersLoaded.push_back(player->GetObjectID()); - } + totalPlayersLoaded.push_back(player->GetObjectID()); // Properly position the player self->SetVar>(TotalPlayersLoadedVariable, totalPlayersLoaded); - TeleportPlayer(player, totalPlayersLoaded.size()); + // This was always spawning all players at position one before and other values cause players to be invisible. + TeleportPlayer(player, 1); // Large teams face a tougher challenge - if (totalPlayersLoaded.size() > 2) + if (totalPlayersLoaded.size() >= 3) self->SetVar(LargeTeamVariable, true); // Start the game if all players in the team have loaded auto* team = TeamManager::Instance()->GetTeam(player->GetObjectID()); - if (team == nullptr || totalPlayersLoaded.size() >= team->members.size()) { + if (team == nullptr || totalPlayersLoaded.size() == team->members.size()) { StartFight(self); return; } @@ -93,6 +91,7 @@ void NjMonastryBossInstance::OnPlayerLoaded(Entity *self, Entity *player) { void NjMonastryBossInstance::OnPlayerExit(Entity *self, Entity *player) { UpdatePlayer(self, player->GetObjectID(), true); + //TODO: Add functionality to dynamically turn off the large team variable when enough players leave. GameMessages::SendNotifyClientObject(self->GetObjectID(), u"PlayerLeft", 0, 0, player->GetObjectID(), "", UNASSIGNED_SYSTEM_ADDRESS); } From f7009b499b644724cb7369fd73dd16475c23993d Mon Sep 17 00:00:00 2001 From: Nordegraf <57260460+Nordegraf@users.noreply.github.com> Date: Sat, 5 Feb 2022 13:19:25 +0100 Subject: [PATCH 027/251] added tracking of Pet Excavator achievement (#213) * added tracking of the Pet Excavator achievement * make Pet Extractor Progress Zone specific * added tracking of Pet Excavator Achievement using player flags --- dScripts/PetDigServer.cpp | 31 ++++++++++++++++++++++++------- dScripts/PetDigServer.h | 2 +- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/dScripts/PetDigServer.cpp b/dScripts/PetDigServer.cpp index 41dce8f2..a78c0881 100644 --- a/dScripts/PetDigServer.cpp +++ b/dScripts/PetDigServer.cpp @@ -39,7 +39,7 @@ const std::map PetDigServer::digInfoMap { {12192, DigInfo { 12192, -1, -1, true, false, false, false }}, }; -void PetDigServer::OnStartup(Entity* self) +void PetDigServer::OnStartup(Entity* self) { treasures.push_back(self->GetObjectID()); const auto digInfoIterator = digInfoMap.find(self->GetLOT()); @@ -64,7 +64,7 @@ void PetDigServer::OnStartup(Entity* self) } } -void PetDigServer::OnDie(Entity* self, Entity* killer) +void PetDigServer::OnDie(Entity* self, Entity* killer) { const auto iterator = std::find(treasures.begin(), treasures.end(), self->GetObjectID()); if (iterator != treasures.end()) @@ -91,7 +91,7 @@ void PetDigServer::OnDie(Entity* self, Entity* killer) PetDigServer::HandleBouncerDig(self, owner); } - PetDigServer::ProgressCanYouDigIt(owner); + PetDigServer::ProgressPetDigMissions(owner, self); self->SetNetworkVar(u"treasure_dug", true); // TODO: Reset other pets @@ -157,19 +157,36 @@ void PetDigServer::HandleBouncerDig(const Entity *self, const Entity *owner) { } /** - * Progresses the Can You Dig It mission if the player has never completed it yet + * Progresses the Can You Dig It mission and the Pet Excavator Achievement if the player has never completed it yet * \param owner the owner that just made a pet dig something up */ -void PetDigServer::ProgressCanYouDigIt(const Entity* owner) { +void PetDigServer::ProgressPetDigMissions(const Entity* owner, const Entity* chest) { auto* missionComponent = owner->GetComponent(); if (missionComponent != nullptr) { + // Can You Dig It progress const auto digMissionState = missionComponent->GetMissionState(843); if (digMissionState == MissionState::MISSION_STATE_ACTIVE) { missionComponent->ForceProgress(843, 1216, 1); } + + // Pet Excavator progress + const auto excavatorMissionState = missionComponent->GetMissionState(505); + if (excavatorMissionState == MissionState::MISSION_STATE_ACTIVE) + { + if (chest->HasVar(u"PetDig")) { + int32_t playerFlag = 1260 + chest->GetVarAs(u"PetDig"); + Character* player = owner->GetCharacter(); + + // check if player flag is set + if (!player->GetPlayerFlag(playerFlag)) { + missionComponent->ForceProgress(505, 767, 1); + player->SetPlayerFlag(playerFlag, 1); + } + } + } } } @@ -203,7 +220,7 @@ void PetDigServer::SpawnPet(Entity* self, const Entity* owner, const DigInfo dig EntityManager::Instance()->ConstructEntity(spawnedPet); } -Entity* PetDigServer::GetClosestTresure(NiPoint3 position) +Entity* PetDigServer::GetClosestTresure(NiPoint3 position) { float closestDistance = 0; Entity* closest = nullptr; @@ -215,7 +232,7 @@ Entity* PetDigServer::GetClosestTresure(NiPoint3 position) if (tresure == nullptr) continue; float distance = Vector3::DistanceSquared(tresure->GetPosition(), position); - + if (closest == nullptr || distance < closestDistance) { closestDistance = distance; diff --git a/dScripts/PetDigServer.h b/dScripts/PetDigServer.h index 22a96a46..968ca50d 100644 --- a/dScripts/PetDigServer.h +++ b/dScripts/PetDigServer.h @@ -20,7 +20,7 @@ public: static Entity* GetClosestTresure(NiPoint3 position); private: - static void ProgressCanYouDigIt(const Entity* owner); + static void ProgressPetDigMissions(const Entity* owner, const Entity* chest); static void SpawnPet(Entity* self, const Entity* owner, DigInfo digInfo); static void HandleXBuildDig(const Entity* self, Entity* owner, Entity* pet); static void HandleBouncerDig(const Entity* self, const Entity* owner); From 579cf590b4b0a1c2f78b7853ccc51d60ea68503f Mon Sep 17 00:00:00 2001 From: cooltrain7 Date: Sat, 5 Feb 2022 12:27:24 +0000 Subject: [PATCH 028/251] Implement CDZoneTable PlayerLoseCoinsOnDeath (#251) * Implement ZoneTable PlayerLoseCoinsOnDeath - Adds a check on death if the character should drop coins in the current zone * Refactored PlayerLoseCoinOnDeath into dZoneManager * Coin death drops use LootGenerator * Refactored again with use of CDZoneTableTable * Remove duplicate CDZone call during initialization --- dGame/dComponents/DestroyableComponent.cpp | 41 ++++++++++++---------- dZoneManager/dZoneManager.cpp | 21 +++++------ dZoneManager/dZoneManager.h | 2 ++ 3 files changed, 35 insertions(+), 29 deletions(-) diff --git a/dGame/dComponents/DestroyableComponent.cpp b/dGame/dComponents/DestroyableComponent.cpp index 8c56d4c1..31b3af19 100644 --- a/dGame/dComponents/DestroyableComponent.cpp +++ b/dGame/dComponents/DestroyableComponent.cpp @@ -26,6 +26,7 @@ #include "MissionComponent.h" #include "CharacterComponent.h" +#include "dZoneManager.h" DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) { m_iArmor = 0; @@ -796,32 +797,34 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType } else { - auto* character = m_Parent->GetCharacter(); - - uint64_t coinsTotal = character->GetCoins(); - - if (coinsTotal > 0) + //Check if this zone allows coin drops + if (dZoneManager::Instance()->GetPlayerLoseCoinOnDeath()) { - uint64_t coinsToLoose = 1; + auto* character = m_Parent->GetCharacter(); + uint64_t coinsTotal = character->GetCoins(); - if (coinsTotal >= 200) + if (coinsTotal > 0) { - float hundreth = (coinsTotal / 100.0f); - coinsToLoose = static_cast(hundreth); - } + uint64_t coinsToLoose = 1; - if (coinsToLoose > 10000) - { - coinsToLoose = 10000; - } + if (coinsTotal >= 200) + { + float hundreth = (coinsTotal / 100.0f); + coinsToLoose = static_cast(hundreth); + } - coinsTotal -= coinsToLoose; - - LootGenerator::Instance().DropLoot(m_Parent, m_Parent, -1, coinsToLoose, coinsToLoose); + if (coinsToLoose > 10000) + { + coinsToLoose = 10000; + } + + coinsTotal -= coinsToLoose; + + LootGenerator::Instance().DropLoot(m_Parent, m_Parent, -1, coinsToLoose, coinsToLoose); + character->SetCoins(coinsTotal, LOOT_SOURCE_PICKUP); + } } - character->SetCoins(coinsTotal, LOOT_SOURCE_PICKUP); - Entity* zoneControl = EntityManager::Instance()->GetZoneControlEntity(); for (CppScripts::Script* script : CppScripts::GetEntityScripts(zoneControl)) { script->OnPlayerDied(zoneControl, m_Parent); diff --git a/dZoneManager/dZoneManager.cpp b/dZoneManager/dZoneManager.cpp index 6f11e8e4..687c93f9 100644 --- a/dZoneManager/dZoneManager.cpp +++ b/dZoneManager/dZoneManager.cpp @@ -26,19 +26,20 @@ void dZoneManager::Initialize(const LWOZONEID& zoneID) { LOT zoneControlTemplate = 2365; - std::stringstream query; - auto result = CDClientDatabase::ExecuteQuery("SELECT zoneControlTemplate, ghostdistance_min, ghostdistance FROM ZoneTable WHERE zoneID = " + std::to_string(zoneID.GetMapID())); + CDZoneTableTable* zoneTable = CDClientManager::Instance()->GetTable("ZoneTable"); + if (zoneTable != nullptr){ + const CDZoneTable* zone = zoneTable->Query(zoneID.GetMapID()); - if (!result.eof()) { - zoneControlTemplate = result.getIntField("zoneControlTemplate", 2365); - const auto min = result.getIntField("ghostdistance_min", 100); - const auto max = result.getIntField("ghostdistance", 100); - EntityManager::Instance()->SetGhostDistanceMax(max + min); - EntityManager::Instance()->SetGhostDistanceMin(max); + if (zone != nullptr) { + zoneControlTemplate = zone->zoneControlTemplate != -1 ? zone->zoneControlTemplate : 2365; + const auto min = zone->ghostdistance_min != -1.0f ? zone->ghostdistance_min : 100; + const auto max = zone->ghostdistance != -1.0f ? zone->ghostdistance : 100; + EntityManager::Instance()->SetGhostDistanceMax(max + min); + EntityManager::Instance()->SetGhostDistanceMin(min); + m_PlayerLoseCoinsOnDeath = zone->PlayerLoseCoinsOnDeath; + } } - result.finalize(); - Game::logger->Log("dZoneManager", "Creating zone control object %i\n", zoneControlTemplate); // Create ZoneControl object diff --git a/dZoneManager/dZoneManager.h b/dZoneManager/dZoneManager.h index 8eb04cca..3171c81f 100644 --- a/dZoneManager/dZoneManager.h +++ b/dZoneManager/dZoneManager.h @@ -42,6 +42,7 @@ public: std::vector GetSpawnersInGroup(std::string group); void Update(float deltaTime); Entity* GetZoneControlObject() { return m_ZoneControlObject; } + bool GetPlayerLoseCoinOnDeath() { return m_PlayerLoseCoinsOnDeath; } private: /** @@ -57,6 +58,7 @@ private: static dZoneManager* m_Address; //Singleton Zone* m_pZone; LWOZONEID m_ZoneID; + bool m_PlayerLoseCoinsOnDeath; //Do players drop coins in this zone when smashed std::map m_Spawners; Entity* m_ZoneControlObject; From 42e20d6db5273e405df7f42e7f3ec28792ed0ed0 Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Sat, 5 Feb 2022 22:51:44 +0100 Subject: [PATCH 029/251] Explain in issue templates how to get Git commit SHA --- .github/ISSUE_TEMPLATE/bug_report.yaml | 2 +- .github/ISSUE_TEMPLATE/installation_issue.yaml | 2 +- .github/ISSUE_TEMPLATE/performance_issue.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index acee8898..b91a920d 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -23,7 +23,7 @@ body: attributes: label: DarkflameServer Version description: > - DarkflameServer version or commit SHA + DarkflameServer version or commit SHA (can be obtained with `git rev-parse --short HEAD`) validations: required: true - type: textarea diff --git a/.github/ISSUE_TEMPLATE/installation_issue.yaml b/.github/ISSUE_TEMPLATE/installation_issue.yaml index 84478ea0..43211e62 100644 --- a/.github/ISSUE_TEMPLATE/installation_issue.yaml +++ b/.github/ISSUE_TEMPLATE/installation_issue.yaml @@ -17,7 +17,7 @@ body: attributes: label: DarkflameServer Version description: > - DarkflameServer version or commit SHA + DarkflameServer version or commit SHA (can be obtained with `git rev-parse --short HEAD`) validations: required: true - type: dropdown diff --git a/.github/ISSUE_TEMPLATE/performance_issue.yaml b/.github/ISSUE_TEMPLATE/performance_issue.yaml index 8e712741..b5ec2bcb 100644 --- a/.github/ISSUE_TEMPLATE/performance_issue.yaml +++ b/.github/ISSUE_TEMPLATE/performance_issue.yaml @@ -20,7 +20,7 @@ body: attributes: label: DarkflameServer Version description: > - DarkflameServer version or commit SHA + DarkflameServer version or commit SHA (can be obtained with `git rev-parse --short HEAD`) validations: required: true - type: textarea From 6ac90f98d116c9b31e1dc4f2c67afb25b2976f39 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 5 Feb 2022 17:56:19 -0800 Subject: [PATCH 030/251] fixed ghosting issue --- dZoneManager/dZoneManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dZoneManager/dZoneManager.cpp b/dZoneManager/dZoneManager.cpp index 687c93f9..e5de1beb 100644 --- a/dZoneManager/dZoneManager.cpp +++ b/dZoneManager/dZoneManager.cpp @@ -35,7 +35,7 @@ void dZoneManager::Initialize(const LWOZONEID& zoneID) { const auto min = zone->ghostdistance_min != -1.0f ? zone->ghostdistance_min : 100; const auto max = zone->ghostdistance != -1.0f ? zone->ghostdistance : 100; EntityManager::Instance()->SetGhostDistanceMax(max + min); - EntityManager::Instance()->SetGhostDistanceMin(min); + EntityManager::Instance()->SetGhostDistanceMin(max); m_PlayerLoseCoinsOnDeath = zone->PlayerLoseCoinsOnDeath; } } From 72b38127164a926ab9562e7d0fc65ddef358059f Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 6 Feb 2022 14:28:15 -0800 Subject: [PATCH 031/251] fixed tab indent --- dGame/dMission/RacingTaskParam.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dMission/RacingTaskParam.h b/dGame/dMission/RacingTaskParam.h index e85d9f91..38f8dd8e 100644 --- a/dGame/dMission/RacingTaskParam.h +++ b/dGame/dMission/RacingTaskParam.h @@ -16,5 +16,5 @@ enum class RacingTaskParam : int32_t { RACING_TASK_PARAM_WIN_RACE_IN_WORLD = 14, // Date: Sun, 6 Feb 2022 14:28:27 -0800 Subject: [PATCH 032/251] Added associate for 17 --- dGame/dMission/MissionTask.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dGame/dMission/MissionTask.cpp b/dGame/dMission/MissionTask.cpp index 4c49327d..9bcbdc81 100644 --- a/dGame/dMission/MissionTask.cpp +++ b/dGame/dMission/MissionTask.cpp @@ -420,6 +420,7 @@ void MissionTask::Progress(int32_t value, LWOOBJID associate, const std::string& case MissionTaskType::MISSION_TASK_TYPE_RACING: { + // The meaning of associate can be found in RacingTaskParam.h if (parameters.empty()) break; if (!InAllTargets(dZoneManager::Instance()->GetZone()->GetWorldID()) && !(parameters[0] == 4 || parameters[0] == 5) && !InAllTargets(value)) break; @@ -444,6 +445,11 @@ void MissionTask::Progress(int32_t value, LWOOBJID associate, const std::string& if (!InAllTargets(value)) break; AddProgress(count); } + else if (associate == 17) + { + if (!InAllTargets(value)) break; + AddProgress(count); + } else { AddProgress(count); From 9cfb9a0de69060216fc1de0bf7a358cd5c744b88 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 6 Feb 2022 14:28:37 -0800 Subject: [PATCH 033/251] Added specific smashable mission progression --- dScripts/FvRaceSmashEggImagineServer.cpp | 4 +++- dScripts/RaceSmashServer.cpp | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/dScripts/FvRaceSmashEggImagineServer.cpp b/dScripts/FvRaceSmashEggImagineServer.cpp index 68faea04..8e0d0897 100644 --- a/dScripts/FvRaceSmashEggImagineServer.cpp +++ b/dScripts/FvRaceSmashEggImagineServer.cpp @@ -27,7 +27,9 @@ void FvRaceSmashEggImagineServer::OnDie(Entity *self, Entity *killer) { characterComponent->UpdatePlayerStatistic(RacingSmashablesSmashed); } if (missionComponent == nullptr) return; - missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, self->GetLOT(), (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_SMASH_DRAGON_EGGS); + // Dragon eggs have their own smash server so we handle mission progression for them here. + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, 0, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_SMASHABLES); + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, self->GetLOT(), (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_SMASH_SPECIFIC_SMASHABLE); } } diff --git a/dScripts/RaceSmashServer.cpp b/dScripts/RaceSmashServer.cpp index 059ac430..582a8ed3 100644 --- a/dScripts/RaceSmashServer.cpp +++ b/dScripts/RaceSmashServer.cpp @@ -22,6 +22,8 @@ void RaceSmashServer::OnDie(Entity *self, Entity *killer) { // Progress racing smashable missions if(missionComponent == nullptr) return; missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, 0, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_SMASHABLES); + // Progress missions that ask us to smash a specific smashable. + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, self->GetLOT(), (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_SMASH_SPECIFIC_SMASHABLE); } } } From 679f0777724503591ad6d619d3c55a61fa658771 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 6 Feb 2022 20:33:07 -0800 Subject: [PATCH 034/251] updated comment --- dGame/dComponents/InventoryComponent.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dGame/dComponents/InventoryComponent.h b/dGame/dComponents/InventoryComponent.h index 7082cfff..aaf9d23a 100644 --- a/dGame/dComponents/InventoryComponent.h +++ b/dGame/dComponents/InventoryComponent.h @@ -399,8 +399,8 @@ private: std::vector FindProxies(LWOOBJID parent); /** - * Returns if the provided ID is a valid proxy item (e.g. we have children for it) - * @param parent the parent item to check for + * Returns true if the provided LWOOBJID is the parent of this Item. + * @param parent the parent item to check for proxies * @return if the provided ID is a valid proxy item */ bool IsValidProxy(LWOOBJID parent); From a6ed4350381ec857a35853c3637cd2fef92aae39 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 6 Feb 2022 20:53:45 -0800 Subject: [PATCH 035/251] Added bounds check for proxies --- dGame/dComponents/InventoryComponent.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index 922b2de3..e7183da2 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -1010,7 +1010,7 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) UpdateSlot(item->GetInfo().equipLocation, { item->GetId(), item->GetLot(), item->GetCount(), item->GetSlot() }); - ApplyBuff(item->GetLot()); + if (item->GetParent() == LWOOBJID_EMPTY) ApplyBuff(item->GetLot()); AddItemSkills(item->GetLot()); @@ -1038,7 +1038,7 @@ void InventoryComponent::UnEquipItem(Item* item) set->OnUnEquip(lot); } - RemoveBuff(item->GetLot()); + if (item->GetParent() == LWOOBJID_EMPTY) RemoveBuff(item->GetLot()); RemoveItemSkills(item->GetLot()); @@ -1498,7 +1498,7 @@ std::vector InventoryComponent::GenerateProxies(Item* parent) auto* inventory = GetInventory(ITEM_SETS); - auto* proxy = new Item(lot, inventory, inventory->FindEmptySlot(), 1, {}, parent->GetId(), false); + auto* proxy = new Item(lot, inventory, inventory->FindEmptySlot(), 1, {}, parent->GetId(), false, parent->GetId()); EquipItem(proxy); From 3de2c3bfc63a44672c3ba3ea9eb29cd019e4bb40 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 6 Feb 2022 21:32:36 -0800 Subject: [PATCH 036/251] set faction of buff station to 6 --- dScripts/AgSurvivalBuffStation.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dScripts/AgSurvivalBuffStation.cpp b/dScripts/AgSurvivalBuffStation.cpp index 41a754d6..a9a4b75d 100644 --- a/dScripts/AgSurvivalBuffStation.cpp +++ b/dScripts/AgSurvivalBuffStation.cpp @@ -1,8 +1,13 @@ #include "AgSurvivalBuffStation.h" #include "SkillComponent.h" #include "dLogger.h" +#include "DestroyableComponent.h" void AgSurvivalBuffStation::OnRebuildComplete(Entity* self, Entity* target) { + auto destroyableComponent = self->GetComponent(); + + if (destroyableComponent != nullptr) destroyableComponent->SetFaction(6); + auto skillComponent = self->GetComponent(); if (skillComponent == nullptr) return; From f41e8292e82297c07b07dae74466539d97d571bf Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 6 Feb 2022 21:34:26 -0800 Subject: [PATCH 037/251] Clarified numbers and added comments --- dScripts/AgSurvivalBuffStation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dScripts/AgSurvivalBuffStation.cpp b/dScripts/AgSurvivalBuffStation.cpp index a9a4b75d..17f3335d 100644 --- a/dScripts/AgSurvivalBuffStation.cpp +++ b/dScripts/AgSurvivalBuffStation.cpp @@ -5,14 +5,14 @@ void AgSurvivalBuffStation::OnRebuildComplete(Entity* self, Entity* target) { auto destroyableComponent = self->GetComponent(); - + // We set the faction to 6 so that the buff station sees players as friendly targets if (destroyableComponent != nullptr) destroyableComponent->SetFaction(6); auto skillComponent = self->GetComponent(); if (skillComponent == nullptr) return; - skillComponent->CalculateBehavior(201, 1784, self->GetObjectID()); + skillComponent->CalculateBehavior(skillIdForBuffStation, behaviorIdForBuffStation, self->GetObjectID()); self->AddCallbackTimer(10.0f, [self]() { self->Smash(); From b297d21a8de2b134a6ef14c505ffe4f552eca53f Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 6 Feb 2022 22:15:32 -0800 Subject: [PATCH 038/251] Fully implemented buff station script --- dScripts/AgSurvivalBuffStation.cpp | 38 +++++++++++++++++++++++++----- dScripts/AgSurvivalBuffStation.h | 30 +++++++++++++++++++++++ 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/dScripts/AgSurvivalBuffStation.cpp b/dScripts/AgSurvivalBuffStation.cpp index 17f3335d..d5d2e442 100644 --- a/dScripts/AgSurvivalBuffStation.cpp +++ b/dScripts/AgSurvivalBuffStation.cpp @@ -1,20 +1,46 @@ #include "AgSurvivalBuffStation.h" +#include "DestroyableComponent.h" +#include "EntityManager.h" +#include "GameMessages.h" #include "SkillComponent.h" #include "dLogger.h" -#include "DestroyableComponent.h" void AgSurvivalBuffStation::OnRebuildComplete(Entity* self, Entity* target) { auto destroyableComponent = self->GetComponent(); - // We set the faction to 6 so that the buff station sees players as friendly targets + // We set the faction to 6 so that the buff station sees players as friendly targets to buff if (destroyableComponent != nullptr) destroyableComponent->SetFaction(6); auto skillComponent = self->GetComponent(); - if (skillComponent == nullptr) return; + if (skillComponent != nullptr) skillComponent->CalculateBehavior(skillIdForBuffStation, behaviorIdForBuffStation, self->GetObjectID()); - skillComponent->CalculateBehavior(skillIdForBuffStation, behaviorIdForBuffStation, self->GetObjectID()); - - self->AddCallbackTimer(10.0f, [self]() { + self->AddCallbackTimer(smashTimer, [self]() { self->Smash(); }); + self->AddTimer("DropArmor", dropArmorTimer); + self->AddTimer("DropLife", dropLifeTimer); + self->AddTimer("Dropimagination", dropImaginationTimer); + self->SetVar(u"PlayerId", target->GetObjectID()); } + +void AgSurvivalBuffStation::OnTimerDone(Entity* self, std::string timerName) { + auto targetID = self->GetVar(u"PlayerId"); + auto target = EntityManager::Instance()->GetEntity(targetID); + uint32_t powerupToDrop = lifePowerup; + if (timerName == "DropArmor") { + powerupToDrop = armorPowerup; + self->AddTimer("DropArmor", dropArmorTimer); + } + if (timerName == "DropLife") { + powerupToDrop = lifePowerup; + self->AddTimer("DropLife", dropLifeTimer); + } + if (timerName == "Dropimagination") { + powerupToDrop = imaginationPowerup; + self->AddTimer("Dropimagination", dropImaginationTimer); + } + if (target != nullptr) GameMessages::SendDropClientLoot(target, self->GetObjectID(), powerupToDrop, 0, self->GetPosition()); +} +void AgSurvivalBuffStation::OnDie(Entity* self, Entity* killer) { + //self->CancelAllTimers(); +} \ No newline at end of file diff --git a/dScripts/AgSurvivalBuffStation.h b/dScripts/AgSurvivalBuffStation.h index 0b4d1865..8d756c7d 100644 --- a/dScripts/AgSurvivalBuffStation.h +++ b/dScripts/AgSurvivalBuffStation.h @@ -11,6 +11,8 @@ public: * @param target The target of the self that called this script. */ void OnRebuildComplete(Entity* self, Entity* target) override; + void OnTimerDone(Entity* self, std::string timerName) override; + void OnDie(Entity* self, Entity* killer) override; private: /** * Skill ID for the buff station. @@ -20,4 +22,32 @@ private: * Behavior ID for the buff station. */ uint32_t behaviorIdForBuffStation = 1784; + /** + * Timer for dropping armor. + */ + float dropArmorTimer = 6.0f; + /** + * Timer for dropping life. + */ + float dropLifeTimer = 3.0f; + /** + * Timer for dropping imagination. + */ + float dropImaginationTimer = 4.0f; + /** + * Timer for smashing. + */ + float smashTimer = 25.0f; + /** + * LOT for armor powerup. + */ + LOT armorPowerup = 6431; + /** + * LOT for life powerup. + */ + LOT lifePowerup = 177; + /** + * LOT for imagination powerup. + */ + LOT imaginationPowerup = 935; }; \ No newline at end of file From 204f03fd2a5b51a4a5abf309c9ccc05bca2c5ceb Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 6 Feb 2022 22:19:23 -0800 Subject: [PATCH 039/251] removed extra function --- dScripts/AgSurvivalBuffStation.cpp | 3 --- dScripts/AgSurvivalBuffStation.h | 1 - 2 files changed, 4 deletions(-) diff --git a/dScripts/AgSurvivalBuffStation.cpp b/dScripts/AgSurvivalBuffStation.cpp index d5d2e442..c893d684 100644 --- a/dScripts/AgSurvivalBuffStation.cpp +++ b/dScripts/AgSurvivalBuffStation.cpp @@ -41,6 +41,3 @@ void AgSurvivalBuffStation::OnTimerDone(Entity* self, std::string timerName) { } if (target != nullptr) GameMessages::SendDropClientLoot(target, self->GetObjectID(), powerupToDrop, 0, self->GetPosition()); } -void AgSurvivalBuffStation::OnDie(Entity* self, Entity* killer) { - //self->CancelAllTimers(); -} \ No newline at end of file diff --git a/dScripts/AgSurvivalBuffStation.h b/dScripts/AgSurvivalBuffStation.h index 8d756c7d..b2beaba6 100644 --- a/dScripts/AgSurvivalBuffStation.h +++ b/dScripts/AgSurvivalBuffStation.h @@ -12,7 +12,6 @@ public: */ void OnRebuildComplete(Entity* self, Entity* target) override; void OnTimerDone(Entity* self, std::string timerName) override; - void OnDie(Entity* self, Entity* killer) override; private: /** * Skill ID for the buff station. From 417a1a7485d7e724676f4f0681b56cddaf6aa312 Mon Sep 17 00:00:00 2001 From: Xiphoseer Date: Mon, 7 Feb 2022 10:19:16 +0100 Subject: [PATCH 040/251] Improve logging Log when a WorldServer initiates shutdown because the master server connection went missing or wasn't established in the first place. --- dWorldServer/WorldServer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index 48d3e33a..bc7e1418 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -314,6 +314,7 @@ int main(int argc, char** argv) { framesSinceMasterDisconnect++; if (framesSinceMasterDisconnect >= 30) { + Game::logger->Log("WorldServer", "Game loop running but no connection to master for 30 frames, shutting down"); worldShutdownSequenceStarted = true; } } From a22e1bd53d53f824b53321399055510c91253d80 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 7 Feb 2022 03:43:09 -0800 Subject: [PATCH 041/251] Added new case in CppScripts --- dScripts/CppScripts.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dScripts/CppScripts.cpp b/dScripts/CppScripts.cpp index 53cbf425..4c6e1cde 100644 --- a/dScripts/CppScripts.cpp +++ b/dScripts/CppScripts.cpp @@ -177,6 +177,7 @@ #include "NtVentureCannonServer.h" #include "NtCombatChallengeServer.h" #include "NtCombatChallengeDummy.h" +#include "NtCombatChallengeExplodingDummy.h" #include "BaseInteractDropLootServer.h" #include "NtAssemblyTubeServer.h" #include "NtParadoxPanelServer.h" @@ -603,6 +604,8 @@ CppScripts::Script* CppScripts::GetScript(Entity* parent, const std::string& scr script = new NtCombatChallengeServer(); else if (scriptName == "scripts\\02_server\\Map\\NT\\L_NT_COMBAT_CHALLENGE_DUMMY.lua") script = new NtCombatChallengeDummy(); + else if (scriptName == "scripts\\02_server\\Map\\NT\\\\L_NT_COMBAT_EXPLODING_TARGET.lua") + script = new NtCombatChallengeExplodingDummy(); else if (scriptName == "scripts\\02_server\\Map\\General\\L_BASE_INTERACT_DROP_LOOT_SERVER.lua") script = new BaseInteractDropLootServer(); else if (scriptName == "scripts\\02_server\\Map\\NT\\L_NT_ASSEMBLYTUBE_SERVER.lua") From 0253a1fcb4472e8544889f0cb285c190c7534e27 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 7 Feb 2022 03:43:30 -0800 Subject: [PATCH 042/251] Added script for exploding asset --- dScripts/NtCombatChallengeExplodingDummy.cpp | 38 ++++++++++++++++++++ dScripts/NtCombatChallengeExplodingDummy.h | 8 +++++ 2 files changed, 46 insertions(+) create mode 100644 dScripts/NtCombatChallengeExplodingDummy.cpp create mode 100644 dScripts/NtCombatChallengeExplodingDummy.h diff --git a/dScripts/NtCombatChallengeExplodingDummy.cpp b/dScripts/NtCombatChallengeExplodingDummy.cpp new file mode 100644 index 00000000..a1b0b288 --- /dev/null +++ b/dScripts/NtCombatChallengeExplodingDummy.cpp @@ -0,0 +1,38 @@ +#include "NtCombatChallengeExplodingDummy.h" +#include "NtCombatChallengeDummy.h" +#include "EntityManager.h" +#include "SkillComponent.h" + +void NtCombatChallengeExplodingDummy::OnDie(Entity* self, Entity* killer) +{ + const auto challengeObjectID = self->GetVar(u"challengeObjectID"); + + auto* challengeObject = EntityManager::Instance()->GetEntity(challengeObjectID); + + if (challengeObject != nullptr) + { + for (CppScripts::Script* script : CppScripts::GetEntityScripts(challengeObject)) + { + script->OnDie(challengeObject, killer); + } + } +} + +void NtCombatChallengeExplodingDummy::OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) { + const auto challengeObjectID = self->GetVar(u"challengeObjectID"); + + auto* challengeObject = EntityManager::Instance()->GetEntity(challengeObjectID); + + if (challengeObject != nullptr) + { + for (CppScripts::Script* script : CppScripts::GetEntityScripts(challengeObject)) + { + script->OnHitOrHealResult(challengeObject, attacker, damage); + } + } + auto skillComponent = self->GetComponent(); + if (skillComponent != nullptr) { + skillComponent->CalculateBehavior(1338, 30875, attacker->GetObjectID()); + } + self->Smash(); +} \ No newline at end of file diff --git a/dScripts/NtCombatChallengeExplodingDummy.h b/dScripts/NtCombatChallengeExplodingDummy.h new file mode 100644 index 00000000..c1c5ef1c --- /dev/null +++ b/dScripts/NtCombatChallengeExplodingDummy.h @@ -0,0 +1,8 @@ +#pragma once +#include "CppScripts.h" + +class NtCombatChallengeExplodingDummy : public CppScripts::Script +{ + void OnDie(Entity* self, Entity* killer) override; + void OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) override; +}; \ No newline at end of file From d9874b452e1fa0f2bbc70334e8b0ae4089f84951 Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Mon, 7 Feb 2022 21:45:56 +0100 Subject: [PATCH 043/251] Fix Plunger Gun not being removed from inventory after mission (#444) --- dScripts/NpcCowboyServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dScripts/NpcCowboyServer.cpp b/dScripts/NpcCowboyServer.cpp index bfba3540..7ec031b9 100644 --- a/dScripts/NpcCowboyServer.cpp +++ b/dScripts/NpcCowboyServer.cpp @@ -26,7 +26,7 @@ void NpcCowboyServer::OnMissionDialogueOK(Entity* self, Entity* target, int miss inventoryComponent->AddItem(14378, 1); } } - else if (missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE || missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE) + else if (missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE || missionState == MissionState::MISSION_STATE_COMPLETE_READY_TO_COMPLETE) { inventoryComponent->RemoveItem(14378, 1); } From 1122f50c7c7b74195162a3fd4c93ac211f09b0cb Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 8 Feb 2022 01:55:25 -0800 Subject: [PATCH 044/251] Changed time when buff station spawns --- dScripts/BaseSurvivalServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dScripts/BaseSurvivalServer.cpp b/dScripts/BaseSurvivalServer.cpp index 1174f00b..dd9b9365 100644 --- a/dScripts/BaseSurvivalServer.cpp +++ b/dScripts/BaseSurvivalServer.cpp @@ -200,6 +200,7 @@ void BaseSurvivalServer::OnActivityTimerDone(Entity *self, const std::string &na ActivityTimerStop(self, SpawnTickTimer); ActivityTimerStart(self, CoolDownStopTimer, 1, constants.coolDownTime); + ActivateSpawnerNetwork(spawnerNetworks.rewardNetworks); SpawnerReset(spawnerNetworks.baseNetworks, false); SpawnerReset(spawnerNetworks.randomNetworks, false); } else if (name == CoolDownStopTimer) { @@ -302,7 +303,6 @@ void BaseSurvivalServer::StartWaves(Entity *self) { self->SetVar(FirstTimeDoneVariable, true); self->SetVar(MissionTypeVariable, state.players.size() == 1 ? "survival_time_solo" : "survival_time_team"); - ActivateSpawnerNetwork(spawnerNetworks.rewardNetworks); ActivateSpawnerNetwork(spawnerNetworks.smashNetworks); self->SetNetworkVar(WavesStartedVariable, true); self->SetNetworkVar(StartWaveMessageVariable, "Start!"); From e397ed310ed0bcdab1a5adbf38921b8e8a5bece4 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 8 Feb 2022 02:02:05 -0800 Subject: [PATCH 045/251] Updated script for teams Updated script to drop buffing items for all members in a team. --- dScripts/AgSurvivalBuffStation.cpp | 31 ++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/dScripts/AgSurvivalBuffStation.cpp b/dScripts/AgSurvivalBuffStation.cpp index c893d684..01fe3976 100644 --- a/dScripts/AgSurvivalBuffStation.cpp +++ b/dScripts/AgSurvivalBuffStation.cpp @@ -4,6 +4,7 @@ #include "GameMessages.h" #include "SkillComponent.h" #include "dLogger.h" +#include "TeamManager.h" void AgSurvivalBuffStation::OnRebuildComplete(Entity* self, Entity* target) { auto destroyableComponent = self->GetComponent(); @@ -20,12 +21,24 @@ void AgSurvivalBuffStation::OnRebuildComplete(Entity* self, Entity* target) { self->AddTimer("DropArmor", dropArmorTimer); self->AddTimer("DropLife", dropLifeTimer); self->AddTimer("Dropimagination", dropImaginationTimer); - self->SetVar(u"PlayerId", target->GetObjectID()); + // Since all survival players should be on the same team, we get the team. + auto team = TeamManager::Instance()->GetTeam(target->GetObjectID()); + + std::vector builderTeam; + // Not on a team + if (team == nullptr) { + builderTeam.push_back(target->GetObjectID()); + self->SetVar>(u"BuilderTeam", builderTeam); + return; + } + + for (auto memberID : team->members) { + builderTeam.push_back(memberID); + } + self->SetVar>(u"BuilderTeam", builderTeam); } void AgSurvivalBuffStation::OnTimerDone(Entity* self, std::string timerName) { - auto targetID = self->GetVar(u"PlayerId"); - auto target = EntityManager::Instance()->GetEntity(targetID); uint32_t powerupToDrop = lifePowerup; if (timerName == "DropArmor") { powerupToDrop = armorPowerup; @@ -39,5 +52,15 @@ void AgSurvivalBuffStation::OnTimerDone(Entity* self, std::string timerName) { powerupToDrop = imaginationPowerup; self->AddTimer("Dropimagination", dropImaginationTimer); } - if (target != nullptr) GameMessages::SendDropClientLoot(target, self->GetObjectID(), powerupToDrop, 0, self->GetPosition()); + auto team = self->GetVar>(u"BuilderTeam"); + for (auto memberID : team) { + auto member = EntityManager::Instance()->GetEntity(memberID); + if (member != nullptr && !member->GetIsDead()) { + GameMessages::SendDropClientLoot(member, self->GetObjectID(), powerupToDrop, 0, self->GetPosition()); + } else { + // If player left the team or left early erase them from the team variable. + team.erase(std::find(team.begin(), team.end(), memberID)); + self->SetVar>(u"BuilderTeam", team); + } + } } From cabd220a665b0eab60a2441c69bd442338c65fc6 Mon Sep 17 00:00:00 2001 From: Xiphoseer Date: Tue, 8 Feb 2022 17:25:14 +0100 Subject: [PATCH 046/251] Fix spam-log on master disconnect (#447) --- dWorldServer/WorldServer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index bc7e1418..ba6c6c71 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -313,8 +313,9 @@ int main(int argc, char** argv) { if (!Game::server->GetIsConnectedToMaster()) { framesSinceMasterDisconnect++; - if (framesSinceMasterDisconnect >= 30) { - Game::logger->Log("WorldServer", "Game loop running but no connection to master for 30 frames, shutting down"); + int framesToWaitForMaster = ready ? 10 : 200; + if (framesSinceMasterDisconnect >= framesToWaitForMaster && !worldShutdownSequenceStarted) { + Game::logger->Log("WorldServer", "Game loop running but no connection to master for %d frames, shutting down\n", framesToWaitForMaster); worldShutdownSequenceStarted = true; } } From d5a18af0e8efd9b51b9332b40bd983d6c6d30776 Mon Sep 17 00:00:00 2001 From: Unknown Date: Wed, 9 Feb 2022 10:38:09 +0100 Subject: [PATCH 047/251] Rehook dPhysics to main framerate Should fix bug causing double enter and exit events --- dWorldServer/PerformanceManager.cpp | 158 ++++++++++++---------------- dWorldServer/PerformanceManager.h | 29 +++-- dWorldServer/WorldServer.cpp | 12 +-- 3 files changed, 81 insertions(+), 118 deletions(-) diff --git a/dWorldServer/PerformanceManager.cpp b/dWorldServer/PerformanceManager.cpp index 7d459234..6809fec0 100644 --- a/dWorldServer/PerformanceManager.cpp +++ b/dWorldServer/PerformanceManager.cpp @@ -2,123 +2,99 @@ #include "UserManager.h" -#define HIGH 16 -#define MEDIUM 33 -#define LOW 66 +//Times are 1 / fps, in ms +#define HIGH 16 //60 fps +#define MEDIUM 33 //30 fps +#define LOW 66 //15 fps -#define SOCIAL { MEDIUM, LOW } -#define BATTLE { HIGH, MEDIUM } -#define BATTLE_INSTANCE { MEDIUM, LOW } -#define RACE { MEDIUM, LOW } -#define PROPERTY { LOW, LOW } +#define SOCIAL { LOW } +#define SOCIAL_HUB { MEDIUM } //Added to compensate for the large playercounts in NS and NT +#define BATTLE { HIGH } +#define BATTLE_INSTANCE { MEDIUM } +#define RACE { HIGH } +#define PROPERTY { LOW } PerformanceProfile PerformanceManager::m_CurrentProfile = SOCIAL; PerformanceProfile PerformanceManager::m_DefaultProfile = SOCIAL; -PerformanceProfile PerformanceManager::m_InactiveProfile = { LOW, LOW }; +PerformanceProfile PerformanceManager::m_InactiveProfile = { LOW }; -std::map PerformanceManager::m_Profiles = { - // VE - { 1000, SOCIAL }, +std::map PerformanceManager::m_Profiles = { + // VE + { 1000, SOCIAL }, - // AG - { 1100, BATTLE }, - { 1101, BATTLE_INSTANCE }, - { 1102, BATTLE_INSTANCE }, - { 1150, PROPERTY }, - { 1151, PROPERTY }, + // AG + { 1100, BATTLE }, + { 1101, BATTLE_INSTANCE }, + { 1102, BATTLE_INSTANCE }, + { 1150, PROPERTY }, + { 1151, PROPERTY }, - // NS - { 1200, SOCIAL }, - { 1201, SOCIAL }, - { 1203, RACE }, - { 1204, BATTLE_INSTANCE }, - { 1250, PROPERTY }, - { 1251, PROPERTY }, + // NS + { 1200, SOCIAL_HUB }, + { 1201, SOCIAL }, + { 1203, RACE }, + { 1204, BATTLE_INSTANCE }, + { 1250, PROPERTY }, + { 1251, PROPERTY }, - // GF - { 1300, BATTLE }, - { 1302, BATTLE_INSTANCE }, - { 1303, BATTLE_INSTANCE }, - { 1350, PROPERTY }, + // GF + { 1300, BATTLE }, + { 1302, BATTLE_INSTANCE }, + { 1303, BATTLE_INSTANCE }, + { 1350, PROPERTY }, - // FV - { 1400, BATTLE }, - { 1402, BATTLE_INSTANCE }, - { 1403, RACE }, - { 1450, PROPERTY }, + // FV + { 1400, BATTLE }, + { 1402, BATTLE_INSTANCE }, + { 1403, RACE }, + { 1450, PROPERTY }, - // LUP - { 1600, SOCIAL }, - { 1601, SOCIAL }, - { 1602, SOCIAL }, - { 1603, SOCIAL }, - { 1604, SOCIAL }, + // LUP + { 1600, SOCIAL }, + { 1601, SOCIAL }, + { 1602, SOCIAL }, + { 1603, SOCIAL }, + { 1604, SOCIAL }, - // LEGO Club - { 1700, SOCIAL }, + // LEGO Club + { 1700, SOCIAL }, - // AM - { 1800, BATTLE }, + // AM + { 1800, BATTLE }, - // NT - { 1900, SOCIAL }, + // NT + { 1900, SOCIAL_HUB }, - // NJ - { 2000, BATTLE }, - { 2001, BATTLE_INSTANCE }, + // NJ + { 2000, BATTLE }, + { 2001, BATTLE_INSTANCE }, }; -PerformanceManager::PerformanceManager() -{ +PerformanceManager::PerformanceManager() { } -PerformanceManager::~PerformanceManager() -{ +PerformanceManager::~PerformanceManager() { } -void PerformanceManager::SelectProfile(LWOMAPID mapID) -{ - const auto pair = m_Profiles.find(mapID); +void PerformanceManager::SelectProfile(LWOMAPID mapID) { + const auto pair = m_Profiles.find(mapID); - if (pair == m_Profiles.end()) - { - m_CurrentProfile = m_DefaultProfile; + if (pair == m_Profiles.end()) { + m_CurrentProfile = m_DefaultProfile; - return; - } + return; + } - m_CurrentProfile = pair->second; + m_CurrentProfile = pair->second; } -uint32_t PerformanceManager::GetServerFramerate() -{ - if (UserManager::Instance()->GetUserCount() == 0) - { - return m_InactiveProfile.serverFramerate; - } +uint32_t PerformanceManager::GetServerFramerate() { + if (UserManager::Instance()->GetUserCount() == 0) { + return m_InactiveProfile.serverFramerate; + } - return m_CurrentProfile.serverFramerate; -} - -uint32_t PerformanceManager::GetPhysicsFramerate() -{ - if (UserManager::Instance()->GetUserCount() == 0) - { - return m_InactiveProfile.physicsFramerate; - } - - return m_CurrentProfile.physicsFramerate; -} - -uint32_t PerformanceManager::GetPhysicsStepRate() -{ - if (UserManager::Instance()->GetUserCount() == 0) - { - return 10; // Row physics at a really low framerate if the server is empty - } - - return m_CurrentProfile.physicsFramerate / m_CurrentProfile.serverFramerate; -} + return m_CurrentProfile.serverFramerate; +} \ No newline at end of file diff --git a/dWorldServer/PerformanceManager.h b/dWorldServer/PerformanceManager.h index 2cd53718..b8a090e0 100644 --- a/dWorldServer/PerformanceManager.h +++ b/dWorldServer/PerformanceManager.h @@ -4,29 +4,24 @@ #include "dCommonVars.h" -struct PerformanceProfile -{ - uint32_t serverFramerate; - uint32_t physicsFramerate; +struct PerformanceProfile { + uint32_t serverFramerate; }; -class PerformanceManager -{ +class PerformanceManager { public: - ~PerformanceManager(); + ~PerformanceManager(); - static void SelectProfile(LWOMAPID mapID); + static void SelectProfile(LWOMAPID mapID); - static uint32_t GetServerFramerate(); - static uint32_t GetPhysicsFramerate(); - static uint32_t GetPhysicsStepRate(); + static uint32_t GetServerFramerate(); private: - PerformanceManager(); - - static PerformanceProfile m_CurrentProfile; - static PerformanceProfile m_DefaultProfile; - static PerformanceProfile m_InactiveProfile; - static std::map m_Profiles; + PerformanceManager(); + + static PerformanceProfile m_CurrentProfile; + static PerformanceProfile m_DefaultProfile; + static PerformanceProfile m_InactiveProfile; + static std::map m_Profiles; }; diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index ba6c6c71..c9b6b00b 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -223,9 +223,7 @@ int main(int argc, char** argv) { int framesSinceMasterStatus = 0; int framesSinceShutdownSequence = 0; int currentFramerate = highFrameRate; - int physicsFramerate = highFrameRate; - int physicsStepRate = 0; - int physicsStepCount = 0; + int ghostingStepCount = 0; auto ghostingLastTime = std::chrono::high_resolution_clock::now(); @@ -300,9 +298,6 @@ int main(int argc, char** argv) { { currentFramerate = PerformanceManager::GetServerFramerate(); } - - physicsFramerate = PerformanceManager::GetPhysicsFramerate(); - physicsStepRate = PerformanceManager::GetPhysicsStepRate(); //Warning if we ran slow if (deltaTime > currentFramerate) { @@ -338,10 +333,7 @@ int main(int argc, char** argv) { if (zoneID != 0 && deltaTime > 0.0f) { Metrics::StartMeasurement(MetricVariable::Physics); - if (physicsStepCount++ >= physicsStepRate) { - dpWorld::Instance().StepWorld(deltaTime); - physicsStepCount = 0; - } + dpWorld::Instance().StepWorld(deltaTime); Metrics::EndMeasurement(MetricVariable::Physics); Metrics::StartMeasurement(MetricVariable::UpdateEntities); From 42f6f2f10b5971dd13faa18e2018892ce21ce3c3 Mon Sep 17 00:00:00 2001 From: "Gie \"Max\" Vanommeslaeghe" Date: Wed, 9 Feb 2022 10:59:43 +0100 Subject: [PATCH 048/251] Bump patch version Should have been done quite a while ago, but ah well --- CMakeVariables.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeVariables.txt b/CMakeVariables.txt index 01e03d87..99742a07 100644 --- a/CMakeVariables.txt +++ b/CMakeVariables.txt @@ -1,6 +1,6 @@ PROJECT_VERSION_MAJOR=1 PROJECT_VERSION_MINOR=0 -PROJECT_VERSION_PATCH=0 +PROJECT_VERSION_PATCH=1 # LICENSE LICENSE=AGPL-3.0 # The network version. From 1607b506c86f9996225c89a4a486087c30860891 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 9 Feb 2022 16:42:03 -0800 Subject: [PATCH 049/251] bodgy bodge to fix minigame missions --- dGame/dMission/Mission.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dGame/dMission/Mission.cpp b/dGame/dMission/Mission.cpp index a054c605..7523dffe 100644 --- a/dGame/dMission/Mission.cpp +++ b/dGame/dMission/Mission.cpp @@ -109,7 +109,7 @@ void Mission::LoadFromXml(tinyxml2::XMLElement* element) { } else { const auto value = std::stoul(task->Attribute("v")); - m_Tasks[index]->SetProgress(value, false); + m_Tasks[index]->SetProgress(value, m_Tasks[index]->GetType() == MissionTaskType::MISSION_TASK_TYPE_MINIGAME); task = task->NextSiblingElement(); } @@ -356,7 +356,7 @@ void Mission::CheckCompletion() { return; } - SetMissionState(MissionState::MISSION_STATE_READY_TO_COMPLETE); + MakeReadyToComplete(); } void Mission::Catchup() { From b077bd937d960fb96afa894cd7fb377f8d27bfd7 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 9 Feb 2022 16:42:17 -0800 Subject: [PATCH 050/251] Fixed bugs with minigame progression --- dGame/dMission/MissionTask.cpp | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/dGame/dMission/MissionTask.cpp b/dGame/dMission/MissionTask.cpp index 4c49327d..8503e8bc 100644 --- a/dGame/dMission/MissionTask.cpp +++ b/dGame/dMission/MissionTask.cpp @@ -78,14 +78,7 @@ void MissionTask::SetProgress(const uint32_t value, const bool echo) std::vector updates; updates.push_back(static_cast(progress)); - - GameMessages::SendNotifyMissionTask( - entity, - entity->GetSystemAddress(), - static_cast(info->id), - static_cast(1 << (mask + 1)), - updates - ); + GameMessages::SendNotifyMissionTask(entity, entity->GetSystemAddress(), static_cast(info->id), static_cast(1 << (mask + 1)), updates); } @@ -190,15 +183,13 @@ bool MissionTask::InParameters(const uint32_t value) const bool MissionTask::IsComplete() const { - // Minigames are the only ones where the target value is a score they need to get but the actual target is the act ID - return GetType() == MissionTaskType::MISSION_TASK_TYPE_MINIGAME ? progress == info->target : progress >= info->targetValue; + return progress >= info->targetValue; } void MissionTask::Complete() { - // Minigames are the only ones where the target value is a score they need to get but the actual target is the act ID - SetProgress(GetType() == MissionTaskType::MISSION_TASK_TYPE_MINIGAME ? info->target : info->targetValue); + SetProgress(info->targetValue); } @@ -354,7 +345,7 @@ void MissionTask::Progress(int32_t value, LWOOBJID associate, const std::string& } if(info->targetGroup == targets && value >= info->targetValue) { - SetProgress(info->target); + SetProgress(info->targetValue); break; } break; From a60738f78ff02741b4797e2e5507a852bf4aa646 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 9 Feb 2022 16:42:31 -0800 Subject: [PATCH 051/251] cleaned up SGCannon --- dScripts/SGCannon.cpp | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/dScripts/SGCannon.cpp b/dScripts/SGCannon.cpp index 58e1d144..4b991253 100644 --- a/dScripts/SGCannon.cpp +++ b/dScripts/SGCannon.cpp @@ -61,8 +61,6 @@ void SGCannon::OnStartup(Entity *self) { void SGCannon::OnPlayerLoaded(Entity *self, Entity *player) { Game::logger->Log("SGCannon", "Player loaded\n"); self->SetVar(PlayerIDVariable, player->GetObjectID()); - /*GameMessages::SendSetStunned(player->GetObjectID(), PUSH, player->GetSystemAddress(), LWOOBJID_EMPTY, - true, true, true, true, true, true, true);*/ } void SGCannon::OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1, int32_t param2, @@ -561,32 +559,15 @@ void SGCannon::StopGame(Entity *self, bool cancel) { auto* missionComponent = player->GetComponent(); - if (self->GetVar(TotalScoreVariable) >= 25000) - { - // For some reason the client thinks this mission is not complete? - auto* mission = missionComponent->GetMission(229); - - if (mission != nullptr && !mission->IsComplete()) - { - mission->Complete(); - } - } - if (missionComponent != nullptr) { - missionComponent->Progress( - MissionTaskType::MISSION_TASK_TYPE_MINIGAME, - self->GetVar(TotalScoreVariable), - self->GetObjectID(), - "performact_score" - ); + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_MINIGAME, self->GetVar(TotalScoreVariable), self->GetObjectID(), "performact_score"); missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_MINIGAME, self->GetVar(MaxStreakVariable), self->GetObjectID(), "performact_streak"); missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_ACTIVITY, m_CannonLot, 0, "", self->GetVar(TotalScoreVariable)); } LootGenerator::Instance().GiveActivityLoot(player, self, GetGameID(self), self->GetVar(TotalScoreVariable)); - StopActivity(self, player->GetObjectID(), self->GetVar(TotalScoreVariable), - self->GetVar(MaxStreakVariable), percentage); + StopActivity(self, player->GetObjectID(), self->GetVar(TotalScoreVariable), self->GetVar(MaxStreakVariable), percentage); self->SetNetworkVar(AudioFinalWaveDoneVariable, true); // Give the player the model rewards they earned @@ -600,7 +581,6 @@ void SGCannon::StopGame(Entity *self, bool cancel) { self->SetNetworkVar(u"UI_Rewards", GeneralUtils::to_u16string(self->GetVar(TotalScoreVariable)) + u"_0_0_0_0_0_0" ); - self->SetVar(TotalScoreVariable, 0); GameMessages::SendRequestActivitySummaryLeaderboardData( player->GetObjectID(), @@ -612,9 +592,6 @@ void SGCannon::StopGame(Entity *self, bool cancel) { 0, false ); - - // The end menu is not in, just send them back to the main world - //static_cast(player)->SendToZone(1300); } GameMessages::SendActivityStop(self->GetObjectID(), false, cancel, player->GetSystemAddress()); From 6c5c6b7b8e8896105021e7abcfe0e1092ff232f1 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 9 Feb 2022 21:21:10 -0800 Subject: [PATCH 052/251] commit when car work --- dGame/dComponents/InventoryComponent.cpp | 64 ++++++++++++++++++++---- dGame/dComponents/InventoryComponent.h | 6 +++ 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index 922b2de3..359ea458 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -23,6 +23,7 @@ #include "CharacterComponent.h" #include "dZoneManager.h" #include "PropertyManagementComponent.h" +#include "DestroyableComponent.h" InventoryComponent::InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document) : Component(parent) { @@ -909,16 +910,34 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) const auto type = static_cast(item->GetInfo().itemType); - if (item->GetLot() == 8092 && m_Parent->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) + if (item->GetLot() == 8092 && m_Parent->GetGMLevel() >= GAME_MASTER_LEVEL_OPERATOR && hasCarEquipped == false) { + auto startPosition = m_Parent->GetPosition() + NiPoint3::UNIT_Y + 10; + + auto startRotation = NiQuaternion::LookAt(startPosition, startPosition + NiPoint3::UNIT_X); + auto angles = startRotation.GetEulerAngles(); + angles.y -= M_PI; + startRotation = NiQuaternion::FromEulerAngles(angles); + + GameMessages::SendTeleport(m_Parent->GetObjectID(), startPosition, startRotation, m_Parent->GetSystemAddress(), true, true); + EntityInfo info {}; info.lot = 8092; - info.pos = m_Parent->GetPosition(); - info.rot = m_Parent->GetRotation(); + info.pos = startPosition; + info.rot = startRotation; info.spawnerID = m_Parent->GetObjectID(); - auto* carEntity = EntityManager::Instance()->CreateEntity(info, nullptr, dZoneManager::Instance()->GetZoneControlObject()); - dZoneManager::Instance()->GetZoneControlObject()->AddChild(carEntity); + auto* carEntity = EntityManager::Instance()->CreateEntity(info, nullptr, m_Parent); + m_Parent->AddChild(carEntity); + + // auto *destroyableComponent = carEntity->GetComponent(); + + // // Setup the vehicle stats. + // if (destroyableComponent != nullptr) { + // destroyableComponent->SetMaxImagination(60); + // destroyableComponent->SetImagination(0); + // destroyableComponent->SetIsImmune(true); + // } auto* possessableComponent = carEntity->GetComponent(); @@ -929,7 +948,7 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) auto* moduleAssemblyComponent = carEntity->GetComponent(); - if (moduleAssemblyComponent) + if (moduleAssemblyComponent != nullptr) { moduleAssemblyComponent->SetSubKey(item->GetSubKey()); moduleAssemblyComponent->SetUseOptionalParts(false); @@ -960,14 +979,33 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) EntityManager::Instance()->ConstructEntity(carEntity); EntityManager::Instance()->SerializeEntity(m_Parent); - //EntityManager::Instance()->SerializeEntity(dZoneManager::Instance()->GetZoneControlObject()); + GameMessages::SendSetJetPackMode(m_Parent, false); - GameMessages::SendNotifyVehicleOfRacingObject(carEntity->GetObjectID(), dZoneManager::Instance()->GetZoneControlObject()->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::SendNotifyVehicleOfRacingObject(carEntity->GetObjectID(), m_Parent->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::SendRacingPlayerLoaded(m_Parent->GetObjectID(), m_Parent->GetObjectID(), carEntity->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS); GameMessages::SendRacingPlayerLoaded(m_Parent->GetObjectID(), m_Parent->GetObjectID(), carEntity->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS); GameMessages::SendVehicleUnlockInput(carEntity->GetObjectID(), false, UNASSIGNED_SYSTEM_ADDRESS); - //GameMessages::SendVehicleSetWheelLockState(carEntity->GetObjectID(), false, false, UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::SendTeleport(m_Parent->GetObjectID(), startPosition, startRotation, m_Parent->GetSystemAddress(), true, true); + GameMessages::SendTeleport(carEntity->GetObjectID(), startPosition, startRotation, m_Parent->GetSystemAddress(), true, true); + EntityManager::Instance()->SerializeEntity(m_Parent); + // m_Parent->AddDieCallback([item, this](){ + // this->UnEquipItem(item); + // this->EquipItem(item); + // }); + // carEntity->AddDieCallback([item, this](){ + // this->UnEquipItem(item); + // this->EquipItem(item); + // }); + hasCarEquipped = true; + equippedCarEntity = carEntity; return; + } else if (item->GetLot() == 8092 && m_Parent->GetGMLevel() >= GAME_MASTER_LEVEL_OPERATOR && hasCarEquipped == true) + { + // auto *playerInstance = dynamic_cast(m_Parent); + // playerInstance->SendToZone(1200); + + // equippedCarEntity->Kill(); } if (!building) @@ -1019,6 +1057,14 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) void InventoryComponent::UnEquipItem(Item* item) { + // if (item->GetLot() == 8092 && m_Parent->GetGMLevel() >= GAME_MASTER_LEVEL_OPERATOR && hasCarEquipped == true) + // { + // auto *playerInstance = dynamic_cast(m_Parent); + // playerInstance->SendToZone(1200); + + // equippedCarEntity->Kill(); + // return; + // } if (!item->IsEquipped()) { return; diff --git a/dGame/dComponents/InventoryComponent.h b/dGame/dComponents/InventoryComponent.h index 7082cfff..f337ae8b 100644 --- a/dGame/dComponents/InventoryComponent.h +++ b/dGame/dComponents/InventoryComponent.h @@ -15,6 +15,7 @@ #include "Component.h" #include "ItemSetPassiveAbility.h" #include "ItemSetPassiveAbilityID.h" +#include "PossessorComponent.h" class Entity; class ItemSet; @@ -384,6 +385,11 @@ private: */ LOT m_Consumable; + /** + * Currently has a car equipped + */ + bool hasCarEquipped = false; + Entity* equippedCarEntity = nullptr; /** * Creates all the proxy items (subitems) for a parent item * @param parent the parent item to generate all the subitems for From 9021c5209faf8ea23155a30ef616701d804ec66a Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 10 Feb 2022 01:03:51 -0800 Subject: [PATCH 053/251] backup commit with comments --- dGame/dComponents/InventoryComponent.cpp | 65 ++++++++++++++++++------ dGame/dComponents/InventoryComponent.h | 2 + 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index 359ea458..06f1d50e 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -911,8 +911,8 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) const auto type = static_cast(item->GetInfo().itemType); if (item->GetLot() == 8092 && m_Parent->GetGMLevel() >= GAME_MASTER_LEVEL_OPERATOR && hasCarEquipped == false) - { - auto startPosition = m_Parent->GetPosition() + NiPoint3::UNIT_Y + 10; + { // Spawn above current position so we dont fall through floor? + auto startPosition = m_Parent->GetPosition() + NiPoint3::UNIT_Y + 2; auto startRotation = NiQuaternion::LookAt(startPosition, startPosition + NiPoint3::UNIT_X); auto angles = startRotation.GetEulerAngles(); @@ -930,19 +930,19 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) auto* carEntity = EntityManager::Instance()->CreateEntity(info, nullptr, m_Parent); m_Parent->AddChild(carEntity); - // auto *destroyableComponent = carEntity->GetComponent(); - - // // Setup the vehicle stats. - // if (destroyableComponent != nullptr) { - // destroyableComponent->SetMaxImagination(60); - // destroyableComponent->SetImagination(0); - // destroyableComponent->SetIsImmune(true); - // } + auto *destroyableComponent = carEntity->GetComponent(); + // Setup the vehicle stats. + if (destroyableComponent != nullptr) { + destroyableComponent->SetIsSmashable(false); + destroyableComponent->SetIsImmune(true); + } + // #108 auto* possessableComponent = carEntity->GetComponent(); if (possessableComponent != nullptr) { + previousPossessableID = possessableComponent->GetPossessor(); possessableComponent->SetPossessor(m_Parent->GetObjectID()); } @@ -961,11 +961,12 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) } } } - + // #107 auto* possessorComponent = m_Parent->GetComponent(); if (possessorComponent != nullptr) { + previousPossessorID = possessorComponent->GetPossessable(); possessorComponent->SetPossessable(carEntity->GetObjectID()); } @@ -982,8 +983,7 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) GameMessages::SendSetJetPackMode(m_Parent, false); GameMessages::SendNotifyVehicleOfRacingObject(carEntity->GetObjectID(), m_Parent->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS); - GameMessages::SendRacingPlayerLoaded(m_Parent->GetObjectID(), m_Parent->GetObjectID(), carEntity->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS); - GameMessages::SendRacingPlayerLoaded(m_Parent->GetObjectID(), m_Parent->GetObjectID(), carEntity->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::SendRacingPlayerLoaded(LWOOBJID_EMPTY, m_Parent->GetObjectID(), carEntity->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS); GameMessages::SendVehicleUnlockInput(carEntity->GetObjectID(), false, UNASSIGNED_SYSTEM_ADDRESS); GameMessages::SendTeleport(m_Parent->GetObjectID(), startPosition, startRotation, m_Parent->GetSystemAddress(), true, true); GameMessages::SendTeleport(carEntity->GetObjectID(), startPosition, startRotation, m_Parent->GetSystemAddress(), true, true); @@ -1002,10 +1002,43 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) return; } else if (item->GetLot() == 8092 && m_Parent->GetGMLevel() >= GAME_MASTER_LEVEL_OPERATOR && hasCarEquipped == true) { - // auto *playerInstance = dynamic_cast(m_Parent); - // playerInstance->SendToZone(1200); + //GameMessages::SendTeleport(m_Parent->GetObjectID(), m_Parent->GetPosition(), m_Parent->GetRotation(), m_Parent->GetSystemAddress(), true, true); + // reset character component back to what it was + // auto* characterComponent = m_Parent->GetComponent(); - // equippedCarEntity->Kill(); + // if (characterComponent != nullptr) + // { + // characterComponent->SetIsRacing(false); + // characterComponent->SetVehicleObjectID(LWOOBJID_EMPTY); + // } + + // auto* possessableComponent = equippedCarEntity->GetComponent(); + + // if (possessableComponent != nullptr) + // { + // possessableComponent->SetPossessor(previousPossessableID); + // previousPossessableID = LWOOBJID_EMPTY; + // } + + // // #107 + // auto* possessorComponent = m_Parent->GetComponent(); + + // if (possessorComponent != nullptr) + // { + // possessorComponent->SetPossessable(previousPossessorID); + // previousPossessorID = LWOOBJID_EMPTY; + // } + GameMessages::SendNotifyRacingClient(LWOOBJID_EMPTY, 3, 0, LWOOBJID_EMPTY, u"", m_Parent->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS); + // GameMessages::SendNotifyVehicleOfRacingObject(equippedCarEntity->GetObjectID(), LWOOBJID_EMPTY, UNASSIGNED_SYSTEM_ADDRESS); + // GameMessages::SendRacingPlayerLoaded(LWOOBJID_EMPTY, m_Parent->GetObjectID(), LWOOBJID_EMPTY, UNASSIGNED_SYSTEM_ADDRESS); + //GameMessages::SendTeleport(m_Parent->GetObjectID(), equippedCarEntity->GetPosition(), equippedCarEntity->GetRotation(), m_Parent->GetSystemAddress(), true, true); + // EntityManager::Instance()->SerializeEntity(m_Parent); + auto player = dynamic_cast(m_Parent); + player->SendToZone(player->GetCharacter()->GetZoneID()); + equippedCarEntity->Kill(); + hasCarEquipped = false; + equippedCarEntity = nullptr; + return; } if (!building) diff --git a/dGame/dComponents/InventoryComponent.h b/dGame/dComponents/InventoryComponent.h index f337ae8b..7c62170d 100644 --- a/dGame/dComponents/InventoryComponent.h +++ b/dGame/dComponents/InventoryComponent.h @@ -390,6 +390,8 @@ private: */ bool hasCarEquipped = false; Entity* equippedCarEntity = nullptr; + LWOOBJID previousPossessableID = LWOOBJID_EMPTY; + LWOOBJID previousPossessorID = LWOOBJID_EMPTY; /** * Creates all the proxy items (subitems) for a parent item * @param parent the parent item to generate all the subitems for From 7c80c12b90a9149a2276caa09d8a31faf3708218 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 10 Feb 2022 01:40:57 -0800 Subject: [PATCH 054/251] Removed comments --- dGame/dComponents/InventoryComponent.cpp | 42 ++---------------------- 1 file changed, 2 insertions(+), 40 deletions(-) diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index 06f1d50e..cbf61544 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -911,8 +911,8 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) const auto type = static_cast(item->GetInfo().itemType); if (item->GetLot() == 8092 && m_Parent->GetGMLevel() >= GAME_MASTER_LEVEL_OPERATOR && hasCarEquipped == false) - { // Spawn above current position so we dont fall through floor? - auto startPosition = m_Parent->GetPosition() + NiPoint3::UNIT_Y + 2; + { + auto startPosition = m_Parent->GetPosition(); auto startRotation = NiQuaternion::LookAt(startPosition, startPosition + NiPoint3::UNIT_X); auto angles = startRotation.GetEulerAngles(); @@ -989,50 +989,12 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) GameMessages::SendTeleport(carEntity->GetObjectID(), startPosition, startRotation, m_Parent->GetSystemAddress(), true, true); EntityManager::Instance()->SerializeEntity(m_Parent); - // m_Parent->AddDieCallback([item, this](){ - // this->UnEquipItem(item); - // this->EquipItem(item); - // }); - // carEntity->AddDieCallback([item, this](){ - // this->UnEquipItem(item); - // this->EquipItem(item); - // }); hasCarEquipped = true; equippedCarEntity = carEntity; return; } else if (item->GetLot() == 8092 && m_Parent->GetGMLevel() >= GAME_MASTER_LEVEL_OPERATOR && hasCarEquipped == true) { - //GameMessages::SendTeleport(m_Parent->GetObjectID(), m_Parent->GetPosition(), m_Parent->GetRotation(), m_Parent->GetSystemAddress(), true, true); - // reset character component back to what it was - // auto* characterComponent = m_Parent->GetComponent(); - - // if (characterComponent != nullptr) - // { - // characterComponent->SetIsRacing(false); - // characterComponent->SetVehicleObjectID(LWOOBJID_EMPTY); - // } - - // auto* possessableComponent = equippedCarEntity->GetComponent(); - - // if (possessableComponent != nullptr) - // { - // possessableComponent->SetPossessor(previousPossessableID); - // previousPossessableID = LWOOBJID_EMPTY; - // } - - // // #107 - // auto* possessorComponent = m_Parent->GetComponent(); - - // if (possessorComponent != nullptr) - // { - // possessorComponent->SetPossessable(previousPossessorID); - // previousPossessorID = LWOOBJID_EMPTY; - // } GameMessages::SendNotifyRacingClient(LWOOBJID_EMPTY, 3, 0, LWOOBJID_EMPTY, u"", m_Parent->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS); - // GameMessages::SendNotifyVehicleOfRacingObject(equippedCarEntity->GetObjectID(), LWOOBJID_EMPTY, UNASSIGNED_SYSTEM_ADDRESS); - // GameMessages::SendRacingPlayerLoaded(LWOOBJID_EMPTY, m_Parent->GetObjectID(), LWOOBJID_EMPTY, UNASSIGNED_SYSTEM_ADDRESS); - //GameMessages::SendTeleport(m_Parent->GetObjectID(), equippedCarEntity->GetPosition(), equippedCarEntity->GetRotation(), m_Parent->GetSystemAddress(), true, true); - // EntityManager::Instance()->SerializeEntity(m_Parent); auto player = dynamic_cast(m_Parent); player->SendToZone(player->GetCharacter()->GetZoneID()); equippedCarEntity->Kill(); From 5fbb1e9cc2705aeac414d15df4448cfacec74e6f Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 10 Feb 2022 02:16:33 -0800 Subject: [PATCH 055/251] removed comments --- dGame/dComponents/InventoryComponent.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index cbf61544..a026fb09 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -1052,14 +1052,6 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) void InventoryComponent::UnEquipItem(Item* item) { - // if (item->GetLot() == 8092 && m_Parent->GetGMLevel() >= GAME_MASTER_LEVEL_OPERATOR && hasCarEquipped == true) - // { - // auto *playerInstance = dynamic_cast(m_Parent); - // playerInstance->SendToZone(1200); - - // equippedCarEntity->Kill(); - // return; - // } if (!item->IsEquipped()) { return; From 2bc9f8f66d5293dde77388f52512d83be4f8aa25 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 10 Feb 2022 03:08:47 -0800 Subject: [PATCH 056/251] Correctly set task value for shooting gallery --- dGame/dMission/Mission.cpp | 2 +- dGame/dMission/MissionTask.cpp | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/dGame/dMission/Mission.cpp b/dGame/dMission/Mission.cpp index 7523dffe..2719a6cf 100644 --- a/dGame/dMission/Mission.cpp +++ b/dGame/dMission/Mission.cpp @@ -109,7 +109,7 @@ void Mission::LoadFromXml(tinyxml2::XMLElement* element) { } else { const auto value = std::stoul(task->Attribute("v")); - m_Tasks[index]->SetProgress(value, m_Tasks[index]->GetType() == MissionTaskType::MISSION_TASK_TYPE_MINIGAME); + m_Tasks[index]->SetProgress(value, false); task = task->NextSiblingElement(); } diff --git a/dGame/dMission/MissionTask.cpp b/dGame/dMission/MissionTask.cpp index 8503e8bc..cb0371e5 100644 --- a/dGame/dMission/MissionTask.cpp +++ b/dGame/dMission/MissionTask.cpp @@ -343,7 +343,14 @@ void MissionTask::Progress(int32_t value, LWOOBJID associate, const std::string& if (info->target != gameID) { break; } - + // Lego Universe is a great game with very easy to understand mission progression. + // If we are progressing a mission for shooting gallery we need to set its + // completion to 1 and not the targetValue beacuse that makes sense + // compared to all other missions and tasks :) + if(info->targetGroup == targets && value >= info->targetValue && GetMission()->IsMission() && info->target == 1864 && info->targetGroup == "performact_score") { + SetProgress(1); + break; + } if(info->targetGroup == targets && value >= info->targetValue) { SetProgress(info->targetValue); break; From 352f654ede30b1278ce6cc1d00624b04a00c4153 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 12 Feb 2022 21:02:52 -0800 Subject: [PATCH 057/251] Added GM in GameMessages --- dGame/dGameMessages/GameMessages.cpp | 12 ++++++++++++ dGame/dGameMessages/GameMessages.h | 1 + dNet/dMessageIdentifiers.h | 1 + 3 files changed, 14 insertions(+) diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index c327ab83..971f1d81 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -1516,6 +1516,18 @@ void GameMessages::SendRequestActivityEnter(LWOOBJID objectId, const SystemAddre SEND_PACKET } +void GameMessages::NotifyLevelRewards(LWOOBJID objectID, const SystemAddress& sysAddr, uint32_t level, bool sending_rewards) { + CBITSTREAM + CMSGHEADER + + bitStream.Write(objectID); + bitStream.Write(GAME_MSG::GAME_MSG_NOTIFY_LEVEL_REWARDS); + + bitStream.Write(level); + bitStream.Write(sending_rewards); + + SEND_PACKET +} void GameMessages::SendSetShootingGalleryParams(LWOOBJID objectId, const SystemAddress& sysAddr, float cameraFOV, diff --git a/dGame/dGameMessages/GameMessages.h b/dGame/dGameMessages/GameMessages.h index 430d48d9..87e3fc94 100644 --- a/dGame/dGameMessages/GameMessages.h +++ b/dGame/dGameMessages/GameMessages.h @@ -68,6 +68,7 @@ namespace GameMessages { void SendOfferMission(const LWOOBJID& entity, const SystemAddress& sysAddr, int32_t missionID, const LWOOBJID& offererID); void SendNotifyMission(Entity * entity, const SystemAddress& sysAddr, int missionID, int missionState, bool sendingRewards); void SendNotifyMissionTask(Entity * entity, const SystemAddress& sysAddr, int missionID, int taskMask, std::vector updates); + void NotifyLevelRewards(LWOOBJID objectID, const SystemAddress& sysAddr, uint32_t level, bool sending_rewards); void SendModifyLEGOScore(Entity* entity, const SystemAddress& sysAddr, int64_t score, eLootSourceType sourceType); void SendUIMessageServerToSingleClient(Entity* entity, const SystemAddress& sysAddr, const std::string& message, NDGFxValue args); diff --git a/dNet/dMessageIdentifiers.h b/dNet/dMessageIdentifiers.h index d4f4e62b..36e85df2 100644 --- a/dNet/dMessageIdentifiers.h +++ b/dNet/dMessageIdentifiers.h @@ -532,6 +532,7 @@ enum GAME_MSG : unsigned short { GAME_MSG_RESPONSE_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1667, GAME_MSG_PLAYER_SET_CAMERA_CYCLING_MODE = 1676, GAME_MSG_NOTIFY_SERVER_LEVEL_PROCESSING_COMPLETE = 1734, + GAME_MSG_NOTIFY_LEVEL_REWARDS = 1735, GAME_MSG_MARK_INVENTORY_ITEM_AS_ACTIVE = 1767, END }; \ No newline at end of file From afa38ae890a428256736044ecf719b75590763fc Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 12 Feb 2022 21:03:04 -0800 Subject: [PATCH 058/251] Added call to GM in CharacterComponent --- dGame/dComponents/CharacterComponent.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/dGame/dComponents/CharacterComponent.cpp b/dGame/dComponents/CharacterComponent.cpp index c7a216f3..d7a41a8b 100644 --- a/dGame/dComponents/CharacterComponent.cpp +++ b/dGame/dComponents/CharacterComponent.cpp @@ -12,6 +12,7 @@ #include "EntityManager.h" #include "PossessorComponent.h" #include "VehiclePhysicsComponent.h" +#include "GameMessages.h" CharacterComponent::CharacterComponent(Entity* parent, Character* character) : Component(parent) { m_Character = character; @@ -191,6 +192,7 @@ void CharacterComponent::HandleLevelUp() auto* rewardsTable = CDClientManager::Instance()->GetTable("Rewards"); const auto& rewards = rewardsTable->GetByLevelID(m_Level); + bool rewardingItem = rewards.size() > 0; auto* parent = m_Character->GetEntity(); @@ -214,29 +216,23 @@ void CharacterComponent::HandleLevelUp() case 0: inventoryComponent->AddItem(reward->value, reward->count); break; - case 4: { auto* items = inventoryComponent->GetInventory(ITEMS); items->SetSize(items->GetSize() + reward->value); } break; - case 9: controllablePhysicsComponent->SetSpeedMultiplier(static_cast(reward->value) / 500.0f); break; - case 11: - break; - case 12: break; - default: break; } - } - + } + GameMessages::NotifyLevelRewards(parent->GetObjectID(), parent->GetSystemAddress(), m_Level, rewardingItem); } void CharacterComponent::SetGMLevel(int gmlevel) { From 4ef55083475e54f50592b6713574e95f91428844 Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Sat, 12 Feb 2022 18:43:34 +0100 Subject: [PATCH 059/251] Fetch zlib library over HTTPS --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 64bf5c22..9492abcb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,7 +53,7 @@ FetchContent_Declare( FetchContent_Declare( zlib - URL http://github.com/madler/zlib/archive/refs/tags/v1.2.11.zip + URL https://github.com/madler/zlib/archive/refs/tags/v1.2.11.zip URL_HASH MD5=9d6a627693163bbbf3f26403a3a0b0b1 ) From 78fbe3c7feb249b1793bb311fa20e6d32f72ed82 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 17 Feb 2022 03:17:41 -0800 Subject: [PATCH 060/251] Added support for Windows Native --- dGame/dComponents/InventoryComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index a026fb09..f1bd8db7 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -916,7 +916,7 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) auto startRotation = NiQuaternion::LookAt(startPosition, startPosition + NiPoint3::UNIT_X); auto angles = startRotation.GetEulerAngles(); - angles.y -= M_PI; + angles.y -= PI; startRotation = NiQuaternion::FromEulerAngles(angles); GameMessages::SendTeleport(m_Parent->GetObjectID(), startPosition, startRotation, m_Parent->GetSystemAddress(), true, true); From 1c43d7f38c96b777d0a98c54f267fee1406b783c Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 20 Feb 2022 19:23:03 -0800 Subject: [PATCH 061/251] GameMessage is correct --- dGame/dGameMessages/GameMessages.cpp | 4 ++-- dGame/dGameMessages/GameMessages.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 971f1d81..a6cf4ed3 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -1516,12 +1516,12 @@ void GameMessages::SendRequestActivityEnter(LWOOBJID objectId, const SystemAddre SEND_PACKET } -void GameMessages::NotifyLevelRewards(LWOOBJID objectID, const SystemAddress& sysAddr, uint32_t level, bool sending_rewards) { +void GameMessages::NotifyLevelRewards(LWOOBJID objectID, const SystemAddress& sysAddr, int level, bool sending_rewards) { CBITSTREAM CMSGHEADER bitStream.Write(objectID); - bitStream.Write(GAME_MSG::GAME_MSG_NOTIFY_LEVEL_REWARDS); + bitStream.Write((uint16_t)GAME_MSG::GAME_MSG_NOTIFY_LEVEL_REWARDS); bitStream.Write(level); bitStream.Write(sending_rewards); diff --git a/dGame/dGameMessages/GameMessages.h b/dGame/dGameMessages/GameMessages.h index 87e3fc94..671c3b3a 100644 --- a/dGame/dGameMessages/GameMessages.h +++ b/dGame/dGameMessages/GameMessages.h @@ -68,7 +68,7 @@ namespace GameMessages { void SendOfferMission(const LWOOBJID& entity, const SystemAddress& sysAddr, int32_t missionID, const LWOOBJID& offererID); void SendNotifyMission(Entity * entity, const SystemAddress& sysAddr, int missionID, int missionState, bool sendingRewards); void SendNotifyMissionTask(Entity * entity, const SystemAddress& sysAddr, int missionID, int taskMask, std::vector updates); - void NotifyLevelRewards(LWOOBJID objectID, const SystemAddress& sysAddr, uint32_t level, bool sending_rewards); + void NotifyLevelRewards(LWOOBJID objectID, const SystemAddress& sysAddr, int level, bool sending_rewards); void SendModifyLEGOScore(Entity* entity, const SystemAddress& sysAddr, int64_t score, eLootSourceType sourceType); void SendUIMessageServerToSingleClient(Entity* entity, const SystemAddress& sysAddr, const std::string& message, NDGFxValue args); From 1c116fb0c4e6248ed2dfb8cad626147906cda255 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 20 Feb 2022 19:23:17 -0800 Subject: [PATCH 062/251] Sending rewards works fully --- dGame/dComponents/CharacterComponent.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dGame/dComponents/CharacterComponent.cpp b/dGame/dComponents/CharacterComponent.cpp index d7a41a8b..3daa437e 100644 --- a/dGame/dComponents/CharacterComponent.cpp +++ b/dGame/dComponents/CharacterComponent.cpp @@ -208,6 +208,8 @@ void CharacterComponent::HandleLevelUp() { return; } + // Tell the client we beginning to send level rewards. + if(rewardingItem) GameMessages::NotifyLevelRewards(parent->GetObjectID(), parent->GetSystemAddress(), m_Level, rewardingItem); for (auto* reward : rewards) { @@ -232,7 +234,8 @@ void CharacterComponent::HandleLevelUp() break; } } - GameMessages::NotifyLevelRewards(parent->GetObjectID(), parent->GetSystemAddress(), m_Level, rewardingItem); + // Tell the client we have finished sending level rewards. + if(rewardingItem) GameMessages::NotifyLevelRewards(parent->GetObjectID(), parent->GetSystemAddress(), m_Level, !rewardingItem); } void CharacterComponent::SetGMLevel(int gmlevel) { From 5ffb57d92ca5fb50d1854d56a6d68bf12376c701 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 20 Feb 2022 19:51:21 -0800 Subject: [PATCH 063/251] Removed special case from GM --- dGame/dGameMessages/GameMessages.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index c327ab83..d89d3cf3 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -4980,17 +4980,6 @@ void GameMessages::HandleRequestUse(RakNet::BitStream* inStream, Entity* entity, missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_MISSION_INTERACTION, interactedObject->GetLOT(), interactedObject->GetObjectID()); missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_NON_MISSION_INTERACTION, interactedObject->GetLOT(), interactedObject->GetObjectID()); - - //Do mail stuff: - if (interactedObject->GetLOT() == 3964) { - AMFStringValue* value = new AMFStringValue(); - value->SetStringValue("Mail"); - - AMFArrayValue args; - args.InsertValue("state", value); - GameMessages::SendUIMessageServerToSingleClient(entity, sysAddr, "pushGameState", &args); - delete value; - } } void GameMessages::HandlePlayEmote(RakNet::BitStream* inStream, Entity* entity) { From 6905120ac64ad98eb37a349be8053ac29a517530 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 20 Feb 2022 19:51:35 -0800 Subject: [PATCH 064/251] Added MailBoxServer files --- dScripts/MailBoxServer.cpp | 12 ++++++++++++ dScripts/MailBoxServer.h | 15 +++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 dScripts/MailBoxServer.cpp create mode 100644 dScripts/MailBoxServer.h diff --git a/dScripts/MailBoxServer.cpp b/dScripts/MailBoxServer.cpp new file mode 100644 index 00000000..3e4e9687 --- /dev/null +++ b/dScripts/MailBoxServer.cpp @@ -0,0 +1,12 @@ +#include "MailBoxServer.h" +#include "AMFFormat.h" +#include "GameMessages.h" + +void MailBoxServer::OnUse(Entity* self, Entity* user) { + AMFStringValue* value = new AMFStringValue(); + value->SetStringValue("Mail"); + AMFArrayValue args; + args.InsertValue("state", value); + GameMessages::SendUIMessageServerToSingleClient(user, user->GetSystemAddress(), "pushGameState", &args); + delete value; +} \ No newline at end of file diff --git a/dScripts/MailBoxServer.h b/dScripts/MailBoxServer.h new file mode 100644 index 00000000..9cd93e24 --- /dev/null +++ b/dScripts/MailBoxServer.h @@ -0,0 +1,15 @@ +#pragma once + +#include "CppScripts.h" + +class MailBoxServer : public CppScripts::Script { +public: + /** + * When a mailbox is interacted with, this method updates the player game state + * to be in a mailbox. + * + * @param self The object that owns this script. + * @param user The user that interacted with this Entity. + */ + void OnUse(Entity* self, Entity* user) override; +}; \ No newline at end of file From 55def02c8f4f99f4554380c35fbca41478eda0ab Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 20 Feb 2022 19:51:54 -0800 Subject: [PATCH 065/251] Added script to CppScripts --- dScripts/CppScripts.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dScripts/CppScripts.cpp b/dScripts/CppScripts.cpp index ca8f95cc..3b9ce5f9 100644 --- a/dScripts/CppScripts.cpp +++ b/dScripts/CppScripts.cpp @@ -162,6 +162,7 @@ #include "GrowingFlower.h" #include "BaseFootRaceManager.h" #include "PropertyPlatform.h" +#include "MailBoxServer.h" // Racing Scripts #include "RaceImagineCrateServer.h" @@ -580,6 +581,8 @@ CppScripts::Script* CppScripts::GetScript(Entity* parent, const std::string& scr script = new PropertyPlatform(); else if (scriptName == "scripts\\02_server\\Map\\VE\\L_VE_BRICKSAMPLE_SERVER.lua") return new VeBricksampleServer(); + else if (scriptName == "scripts\\02_server\\Map\\General\\L_MAIL_BOX_SERVER.lua") + script = new MailBoxServer(); //Racing: else if (scriptName == "scripts\\ai\\RACING\\OBJECTS\\RACE_IMAGINE_CRATE_SERVER.lua") From 3d1283675f68848fa7e8c0f537df959b11ab0410 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 20 Feb 2022 20:00:56 -0800 Subject: [PATCH 066/251] Updated comment --- dGame/dMission/MissionTask.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/dGame/dMission/MissionTask.cpp b/dGame/dMission/MissionTask.cpp index cb0371e5..c732925c 100644 --- a/dGame/dMission/MissionTask.cpp +++ b/dGame/dMission/MissionTask.cpp @@ -343,10 +343,8 @@ void MissionTask::Progress(int32_t value, LWOOBJID associate, const std::string& if (info->target != gameID) { break; } - // Lego Universe is a great game with very easy to understand mission progression. - // If we are progressing a mission for shooting gallery we need to set its - // completion to 1 and not the targetValue beacuse that makes sense - // compared to all other missions and tasks :) + // This special case is for shooting gallery missions that want their + // progress value set to 1 instead of being set to the target value. if(info->targetGroup == targets && value >= info->targetValue && GetMission()->IsMission() && info->target == 1864 && info->targetGroup == "performact_score") { SetProgress(1); break; From 24d443537ab7539c704bcb31322baf4fd55a44b0 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 20 Feb 2022 20:01:55 -0800 Subject: [PATCH 067/251] Addressed spacing --- dGame/dMission/MissionTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dMission/MissionTask.cpp b/dGame/dMission/MissionTask.cpp index c732925c..2ef36fd0 100644 --- a/dGame/dMission/MissionTask.cpp +++ b/dGame/dMission/MissionTask.cpp @@ -78,7 +78,7 @@ void MissionTask::SetProgress(const uint32_t value, const bool echo) std::vector updates; updates.push_back(static_cast(progress)); - GameMessages::SendNotifyMissionTask(entity, entity->GetSystemAddress(), static_cast(info->id), static_cast(1 << (mask + 1)), updates); + GameMessages::SendNotifyMissionTask(entity, entity->GetSystemAddress(), static_cast(info->id), static_cast(1 << (mask + 1)), updates); } From 6be274b25939121ded64f2f8439b2684ac702caa Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 23 Feb 2022 17:38:25 -0800 Subject: [PATCH 068/251] fixed issue --- dScripts/NtCombatChallengeExplodingDummy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dScripts/NtCombatChallengeExplodingDummy.cpp b/dScripts/NtCombatChallengeExplodingDummy.cpp index a1b0b288..dd61817d 100644 --- a/dScripts/NtCombatChallengeExplodingDummy.cpp +++ b/dScripts/NtCombatChallengeExplodingDummy.cpp @@ -34,5 +34,5 @@ void NtCombatChallengeExplodingDummy::OnHitOrHealResult(Entity* self, Entity* at if (skillComponent != nullptr) { skillComponent->CalculateBehavior(1338, 30875, attacker->GetObjectID()); } - self->Smash(); + self->Kill(attacker); } \ No newline at end of file From 68c600facc1230d7c790ff4c2a6a196017c868b7 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 20 Mar 2022 20:28:26 -0700 Subject: [PATCH 069/251] Added better bug reports --- dGame/dGameMessages/GameMessages.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 53699f4e..221a4737 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -5900,6 +5900,13 @@ void GameMessages::HandleReportBug(RakNet::BitStream* inStream, Entity* entity) body.push_back(character); } + auto character = entity->GetCharacter(); + if (character) { + body.append(GeneralUtils::ASCIIToUTF16(" charID: ")); + body.append(GeneralUtils::ASCIIToUTF16(std::to_string(character->GetID()))); + body.push_back(' '); + } + uint32_t clientVersionLength; inStream->Read(clientVersionLength); for (unsigned int k = 0; k < clientVersionLength; k++) { @@ -5915,7 +5922,19 @@ void GameMessages::HandleReportBug(RakNet::BitStream* inStream, Entity* entity) inStream->Read(character); nOtherPlayerID.push_back(character); } - + // Convert other player id from LWOOBJID to the database id. + std::istringstream iss(nOtherPlayerID); + LWOOBJID nOtherPlayerLWOOBJID; + iss >> nOtherPlayerLWOOBJID; + if (nOtherPlayerLWOOBJID != LWOOBJID_EMPTY) { + auto otherPlayer = EntityManager::Instance()->GetEntity(nOtherPlayerLWOOBJID); + if (otherPlayer) { + auto character = otherPlayer->GetCharacter(); + if (character) { + nOtherPlayerID = std::to_string(character->GetID()); + } + } + } uint32_t selectionLength; inStream->Read(selectionLength); for (unsigned int k = 0; k < selectionLength; k++) { From 22a00de8cd7e1ad97dd821eba3f0fe2f20ff9c6a Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 20 Mar 2022 20:46:15 -0700 Subject: [PATCH 070/251] added char id column --- migrations/dlu/0_initial.sql | 1 + migrations/dlu/2_reporter_id.sql | 1 + 2 files changed, 2 insertions(+) create mode 100644 migrations/dlu/2_reporter_id.sql diff --git a/migrations/dlu/0_initial.sql b/migrations/dlu/0_initial.sql index 16cb3e7e..61380f76 100644 --- a/migrations/dlu/0_initial.sql +++ b/migrations/dlu/0_initial.sql @@ -150,6 +150,7 @@ CREATE TABLE activity_log ( DROP TABLE IF EXISTS bug_reports; CREATE TABLE bug_reports ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + reporter_id INT NOT NULL DEFAULT 0, body TEXT NOT NULL, client_version TEXT NOT NULL, other_player_id TEXT NOT NULL, diff --git a/migrations/dlu/2_reporter_id.sql b/migrations/dlu/2_reporter_id.sql new file mode 100644 index 00000000..26103342 --- /dev/null +++ b/migrations/dlu/2_reporter_id.sql @@ -0,0 +1 @@ +ALTER TABLE bug_reports ADD reporter_id INT NOT NULL DEFAULT 0; From e2bfdcd174f3bfb72b56c654ae2be51308926025 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 20 Mar 2022 20:46:34 -0700 Subject: [PATCH 071/251] moved char id storage --- dGame/dGameMessages/GameMessages.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 221a4737..297df424 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -5890,6 +5890,7 @@ void GameMessages::HandleReportBug(RakNet::BitStream* inStream, Entity* entity) std::string nOtherPlayerID; std::string selection; uint32_t messageLength; + int32_t reporterID; //Reading: inStream->Read(messageLength); @@ -5901,11 +5902,7 @@ void GameMessages::HandleReportBug(RakNet::BitStream* inStream, Entity* entity) } auto character = entity->GetCharacter(); - if (character) { - body.append(GeneralUtils::ASCIIToUTF16(" charID: ")); - body.append(GeneralUtils::ASCIIToUTF16(std::to_string(character->GetID()))); - body.push_back(' '); - } + if (character) reporterID = character->GetID(); uint32_t clientVersionLength; inStream->Read(clientVersionLength); @@ -5944,11 +5941,12 @@ void GameMessages::HandleReportBug(RakNet::BitStream* inStream, Entity* entity) } try { - sql::PreparedStatement* insertBug = Database::CreatePreppedStmt("INSERT INTO `bug_reports`(body, client_version, other_player_id, selection) VALUES (?, ?, ?, ?)"); + sql::PreparedStatement* insertBug = Database::CreatePreppedStmt("INSERT INTO `bug_reports`(body, client_version, other_player_id, selection, reporter_id) VALUES (?, ?, ?, ?, ?)"); insertBug->setString(1, GeneralUtils::UTF16ToWTF8(body)); insertBug->setString(2, clientVersion); insertBug->setString(3, nOtherPlayerID); insertBug->setString(4, selection); + insertBug->setInt(5, reporterID); insertBug->execute(); delete insertBug; } From b2c88bb6a750840d659939396e625079a39b9ed3 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 24 Mar 2022 00:09:18 -0700 Subject: [PATCH 072/251] working query --- dGame/UserManager.cpp | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/dGame/UserManager.cpp b/dGame/UserManager.cpp index 1535364c..d1e49cbb 100644 --- a/dGame/UserManager.cpp +++ b/dGame/UserManager.cpp @@ -6,6 +6,7 @@ #include "Database.h" #include "Game.h" +#include "dLogger.h" #include "User.h" #include #include "Character.h" @@ -572,28 +573,26 @@ uint32_t GetShirtColorId(uint32_t color) { auto colorId = std::find(shirtColorVector.begin(), shirtColorVector.end(), color); return color = std::distance(shirtColorVector.begin(), colorId); } - +// the correct query +/** + * select obj.id, obj.name, obj._internalnotes, icc.color1, icc.decal from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == "character create shirt"; + */ uint32_t FindCharShirtID(uint32_t shirtColor, uint32_t shirtStyle) { - - shirtStyle--; // to start at 0 instead of 1 - uint32_t stylesCount = 34; - uint32_t colorId = GetShirtColorId(shirtColor); - - uint32_t startID = 4049; // item ID of the shirt with color 0 (red) and style 0 (plain) - - // For some reason, if the shirt style is 34 - 39, - // The ID is different than the original... Was this because - // these shirts were added later? - if (shirtStyle >= 34) { - startID = 5730; // item ID of the shirt with color 0 (red) and style 34 (butterflies) - shirtStyle -= stylesCount; //change style from range 35-40 to range 0-5 - stylesCount = 6; + try { + std::string shirtQuery = "select obj.id from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == \"character create shirt\" AND icc.color1 == "; + shirtQuery += std::to_string(shirtColor); + shirtQuery += " AND icc.decal == "; + shirtQuery = shirtQuery + std::to_string(shirtStyle); + auto tableData = CDClientDatabase::ExecuteQuery(shirtQuery); + auto shirtLOT = tableData.getIntField(0, -1); + tableData.finalize(); + return shirtLOT; + } + catch (const std::exception&){ + Game::logger->Log("Character Create", "Failed to use query! Using backup..."); + // in case of no shirt found in CDServer, return problematic red vest. + return 4069; } - - // Get the final ID of the shirt - uint32_t shirtID = startID + (colorId * stylesCount) + shirtStyle; - - return shirtID; } uint32_t FindCharPantsID(uint32_t pantsColor) { From 4e2c352ab92530e016a40edc96dfb515799e2edc Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 24 Mar 2022 00:30:52 -0700 Subject: [PATCH 073/251] Changed pants query and removed extra comments --- dGame/UserManager.cpp | 114 ++++-------------------------------------- dGame/UserManager.h | 40 --------------- 2 files changed, 11 insertions(+), 143 deletions(-) diff --git a/dGame/UserManager.cpp b/dGame/UserManager.cpp index d1e49cbb..f67c0a4f 100644 --- a/dGame/UserManager.cpp +++ b/dGame/UserManager.cpp @@ -69,16 +69,6 @@ void UserManager::Initialize() { StripCR(line); m_PreapprovedNames.push_back(line); } - - //Load custom ones from MySQL too: - /*sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT name FROM approvedNames;"); - sql::ResultSet* res = stmt->executeQuery(); - while (res->next()) { - m_PreapprovedNames.push_back(res->getString(1)); - } - - delete res; - delete stmt;*/ } UserManager::~UserManager() { @@ -567,16 +557,6 @@ void UserManager::LoginCharacter(const SystemAddress& sysAddr, uint32_t playerID } } -uint32_t GetShirtColorId(uint32_t color) { - - // get the index of the color in shirtColorVector - auto colorId = std::find(shirtColorVector.begin(), shirtColorVector.end(), color); - return color = std::distance(shirtColorVector.begin(), colorId); -} -// the correct query -/** - * select obj.id, obj.name, obj._internalnotes, icc.color1, icc.decal from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == "character create shirt"; - */ uint32_t FindCharShirtID(uint32_t shirtColor, uint32_t shirtStyle) { try { std::string shirtQuery = "select obj.id from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == \"character create shirt\" AND icc.color1 == "; @@ -596,91 +576,19 @@ uint32_t FindCharShirtID(uint32_t shirtColor, uint32_t shirtStyle) { } uint32_t FindCharPantsID(uint32_t pantsColor) { - uint32_t pantsID = 2508; - - switch (pantsColor) { - case 0: { - pantsID = PANTS_BRIGHT_RED; - break; + try { + std::string shirtQuery = "select obj.id from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == \"cc pants\" AND icc.color1 == "; + shirtQuery += std::to_string(pantsColor); + auto tableData = CDClientDatabase::ExecuteQuery(shirtQuery); + auto pantsLOT = tableData.getIntField(0, -1); + tableData.finalize(); + return pantsLOT; } - - case 1: { - pantsID = PANTS_BRIGHT_BLUE; - break; + catch (const std::exception&){ + Game::logger->Log("Character Create", "Failed to use query! Using backup..."); + // in case of no pants color found in CDServer, return red pants. + return 2508; } - - case 3: { - pantsID = PANTS_DARK_GREEN; - break; - } - - case 5: { - pantsID = PANTS_BRIGHT_ORANGE; - break; - } - - case 6: { - pantsID = PANTS_BLACK; - break; - } - - case 7: { - pantsID = PANTS_DARK_STONE_GRAY; - break; - } - - case 8: { - pantsID = PANTS_MEDIUM_STONE_GRAY; - break; - } - - case 9: { - pantsID = PANTS_REDDISH_BROWN; - break; - } - - case 10: { - pantsID = PANTS_WHITE; - break; - } - - case 11: { - pantsID = PANTS_MEDIUM_BLUE; - break; - } - - case 13: { - pantsID = PANTS_DARK_RED; - break; - } - - case 14: { - pantsID = PANTS_EARTH_BLUE; - break; - } - - case 15: { - pantsID = PANTS_EARTH_GREEN; - break; - } - - case 16: { - pantsID = PANTS_BRICK_YELLOW; - break; - } - - case 84: { - pantsID = PANTS_SAND_BLUE; - break; - } - - case 96: { - pantsID = PANTS_SAND_GREEN; - break; - } - } - - return pantsID; } void UserManager::SaveAllActiveCharacters() { diff --git a/dGame/UserManager.h b/dGame/UserManager.h index b29cf501..a5db6979 100644 --- a/dGame/UserManager.h +++ b/dGame/UserManager.h @@ -44,7 +44,6 @@ public: private: static UserManager* m_Address; //Singleton - //std::vector m_Users; std::map m_Users; std::vector m_UsersToDelete; @@ -54,43 +53,4 @@ private: std::vector m_PreapprovedNames; }; -enum CharCreatePantsColor : uint32_t { - PANTS_BRIGHT_RED = 2508, - PANTS_BRIGHT_ORANGE = 2509, - PANTS_BRICK_YELLOW = 2511, - PANTS_MEDIUM_BLUE = 2513, - PANTS_SAND_GREEN = 2514, - PANTS_DARK_GREEN = 2515, - PANTS_EARTH_GREEN = 2516, - PANTS_EARTH_BLUE = 2517, - PANTS_BRIGHT_BLUE = 2519, - PANTS_SAND_BLUE = 2520, - PANTS_DARK_STONE_GRAY = 2521, - PANTS_MEDIUM_STONE_GRAY = 2522, - PANTS_WHITE = 2523, - PANTS_BLACK = 2524, - PANTS_REDDISH_BROWN = 2526, - PANTS_DARK_RED = 2527 -}; - -const std::vector shirtColorVector { - 0, // BRIGHT_RED - 1, // BRIGHT_BLUE - 2, // BRIGHT_YELLOW - 3, // DARK_GREEN - 5, // BRIGHT_ORANGE - 6, // BLACK - 7, // DARK_STONE_GRAY - 8, // MEDIUM_STONE_GRAY - 9, // REDDISH_BROWN - 10, // WHITE - 11, // MEDIUM_BLUE - 13, // DARK_RED - 14, // EARTH_BLUE - 15, // EARTH_GREEN - 16, // BRICK_YELLOW - 84, // SAND_BLUE - 96 // SAND_GREEN -}; - #endif // USERMANAGER_H From 819c58df7c17965465087bcbad5087708fce8208 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 24 Mar 2022 00:33:05 -0700 Subject: [PATCH 074/251] semantics --- dGame/UserManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dGame/UserManager.cpp b/dGame/UserManager.cpp index f67c0a4f..fa34eeaa 100644 --- a/dGame/UserManager.cpp +++ b/dGame/UserManager.cpp @@ -569,7 +569,7 @@ uint32_t FindCharShirtID(uint32_t shirtColor, uint32_t shirtStyle) { return shirtLOT; } catch (const std::exception&){ - Game::logger->Log("Character Create", "Failed to use query! Using backup..."); + Game::logger->Log("Character Create", "Failed to execute query! Using backup..."); // in case of no shirt found in CDServer, return problematic red vest. return 4069; } @@ -585,7 +585,7 @@ uint32_t FindCharPantsID(uint32_t pantsColor) { return pantsLOT; } catch (const std::exception&){ - Game::logger->Log("Character Create", "Failed to use query! Using backup..."); + Game::logger->Log("Character Create", "Failed to execute query! Using backup..."); // in case of no pants color found in CDServer, return red pants. return 2508; } From f83ad8bbe48ad23c92676a753fb81d71f857e22b Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 23 Mar 2022 18:08:09 -0700 Subject: [PATCH 075/251] fixed wrong stun removal Apes no longer stack their attacks Apes no longer stack their attacks and excess comments removed --- dScripts/BaseEnemyApe.cpp | 20 ++++---------------- dScripts/WaveBossApe.cpp | 1 + 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/dScripts/BaseEnemyApe.cpp b/dScripts/BaseEnemyApe.cpp index 88c846f6..3419b2c4 100644 --- a/dScripts/BaseEnemyApe.cpp +++ b/dScripts/BaseEnemyApe.cpp @@ -8,11 +8,6 @@ void BaseEnemyApe::OnStartup(Entity *self) { self->SetVar(u"timesStunned", 2); self->SetVar(u"knockedOut", false); - - auto* combatAIComponent = self->GetComponent(); - if (combatAIComponent != nullptr) { - combatAIComponent->SetStunImmune(true); - } } void BaseEnemyApe::OnDie(Entity *self, Entity *killer) { @@ -23,10 +18,8 @@ void BaseEnemyApe::OnDie(Entity *self, Entity *killer) { } void BaseEnemyApe::OnSkillCast(Entity *self, uint32_t skillID) { - const auto groundPoundSkill = self->GetVar(u"GroundPoundSkill") != 0 - ? self->GetVar(u"GroundPoundSkill") : 725; - const auto spawnQuickBuildTime = self->GetVar(u"spawnQBTime") != 0.0f - ? self->GetVar(u"spawnQBTime") : 5.0f; + const auto groundPoundSkill = self->GetVar(u"GroundPoundSkill") != 0 ? self->GetVar(u"GroundPoundSkill") : 725; + const auto spawnQuickBuildTime = self->GetVar(u"spawnQBTime") != 0.0f ? self->GetVar(u"spawnQBTime") : 5.0f; if (skillID == groundPoundSkill && self->GetVar(u"QB") == LWOOBJID_EMPTY) { self->AddTimer("spawnQBTime", spawnQuickBuildTime); @@ -61,9 +54,7 @@ void BaseEnemyApe::OnTimerDone(Entity *self, std::string timerName) { StunApe(self, false); } else if (timerName == "spawnQBTime" && self->GetVar(u"QB") == LWOOBJID_EMPTY) { - - // Spawns the QB, which can insta kill the ape - // Quick mafs to spawn the QB in the correct spot + // Spawn QB in front of ape. const auto position = self->GetPosition(); const auto rotation = self->GetRotation(); @@ -107,8 +98,6 @@ void BaseEnemyApe::OnTimerDone(Entity *self, std::string timerName) { auto* skillComponent = self->GetComponent(); if (skillComponent != nullptr) { - // We use a different behavior than the script here, the original one contains a TargetCaster behavior - // but as of writing we can't pass an optional originated to give the loot to the player skillComponent->CalculateBehavior(1273, 29446, self->GetObjectID(), true, false, player->GetObjectID()); } @@ -120,8 +109,7 @@ void BaseEnemyApe::OnFireEventServerSide(Entity *self, Entity *sender, std::stri int32_t param3) { if (args == "rebuildDone" && sender != nullptr) { self->SetVar(u"smasher", sender->GetObjectID()); - const auto anchorDamageDelayTime = self->GetVar(u"AnchorDamageDelayTime") != 0.0f - ? self->GetVar(u"AnchorDamageDelayTime") : 0.5f; + const auto anchorDamageDelayTime = self->GetVar(u"AnchorDamageDelayTime") != 0.0f ? self->GetVar(u"AnchorDamageDelayTime") : 0.5f; self->AddTimer("anchorDamageTimer", anchorDamageDelayTime); } } diff --git a/dScripts/WaveBossApe.cpp b/dScripts/WaveBossApe.cpp index e1860048..c7fdccf2 100644 --- a/dScripts/WaveBossApe.cpp +++ b/dScripts/WaveBossApe.cpp @@ -32,6 +32,7 @@ void WaveBossApe::OnFireEventServerSide(Entity *self, Entity *sender, std::strin auto* combatAIComponent = self->GetComponent(); if (combatAIComponent != nullptr) { combatAIComponent->SetDisabled(false); + combatAIComponent->SetStunImmune(false); } } else { BaseEnemyApe::OnFireEventServerSide(self, sender, args, param1, param2, param3); From 6499139a4949abed3a48195ee051d984befbc66b Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 24 Mar 2022 01:11:21 -0700 Subject: [PATCH 076/251] moved addition to new migration. --- migrations/dlu/0_initial.sql | 1 - 1 file changed, 1 deletion(-) diff --git a/migrations/dlu/0_initial.sql b/migrations/dlu/0_initial.sql index 61380f76..16cb3e7e 100644 --- a/migrations/dlu/0_initial.sql +++ b/migrations/dlu/0_initial.sql @@ -150,7 +150,6 @@ CREATE TABLE activity_log ( DROP TABLE IF EXISTS bug_reports; CREATE TABLE bug_reports ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, - reporter_id INT NOT NULL DEFAULT 0, body TEXT NOT NULL, client_version TEXT NOT NULL, other_player_id TEXT NOT NULL, From db3cd33bca9bdd97cf261fd85d86f2f9ee2e579b Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 24 Mar 2022 17:51:21 -0700 Subject: [PATCH 077/251] fixed incorrect variable name --- dGame/UserManager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dGame/UserManager.cpp b/dGame/UserManager.cpp index fa34eeaa..61de4ca7 100644 --- a/dGame/UserManager.cpp +++ b/dGame/UserManager.cpp @@ -577,9 +577,9 @@ uint32_t FindCharShirtID(uint32_t shirtColor, uint32_t shirtStyle) { uint32_t FindCharPantsID(uint32_t pantsColor) { try { - std::string shirtQuery = "select obj.id from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == \"cc pants\" AND icc.color1 == "; - shirtQuery += std::to_string(pantsColor); - auto tableData = CDClientDatabase::ExecuteQuery(shirtQuery); + std::string pantsQuery = "select obj.id from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == \"cc pants\" AND icc.color1 == "; + pantsQuery += std::to_string(pantsColor); + auto tableData = CDClientDatabase::ExecuteQuery(pantsQuery); auto pantsLOT = tableData.getIntField(0, -1); tableData.finalize(); return pantsLOT; From b459790b2ff299f3beae39df84dc0edaad1f06fa Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 27 Mar 2022 15:24:06 -0700 Subject: [PATCH 078/251] Fixed mission progression --- dGame/dComponents/InventoryComponent.cpp | 26 ++++++++++++------------ dGame/dComponents/InventoryComponent.h | 6 +++--- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index c5b4bec3..56bf26d8 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -1043,7 +1043,7 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) UpdateSlot(item->GetInfo().equipLocation, { item->GetId(), item->GetLot(), item->GetCount(), item->GetSlot() }); - if (item->GetParent() == LWOOBJID_EMPTY) ApplyBuff(item->GetLot()); + ApplyBuff(item); AddItemSkills(item->GetLot()); @@ -1071,7 +1071,7 @@ void InventoryComponent::UnEquipItem(Item* item) set->OnUnEquip(lot); } - if (item->GetParent() == LWOOBJID_EMPTY) RemoveBuff(item->GetLot()); + RemoveBuff(item); RemoveItemSkills(item->GetLot()); @@ -1089,9 +1089,9 @@ void InventoryComponent::UnEquipItem(Item* item) } } -void InventoryComponent::ApplyBuff(const LOT lot) const +void InventoryComponent::ApplyBuff(Item* item) const { - const auto buffs = FindBuffs(lot, true); + const auto buffs = FindBuffs(item, true); for (const auto buff : buffs) { @@ -1099,9 +1099,9 @@ void InventoryComponent::ApplyBuff(const LOT lot) const } } -void InventoryComponent::RemoveBuff(const LOT lot) const +void InventoryComponent::RemoveBuff(Item* item) const { - const auto buffs = FindBuffs(lot, false); + const auto buffs = FindBuffs(item, false); for (const auto buff : buffs) { @@ -1418,18 +1418,18 @@ uint32_t InventoryComponent::FindSkill(const LOT lot) return 0; } -std::vector InventoryComponent::FindBuffs(const LOT lot, bool castOnEquip) const +std::vector InventoryComponent::FindBuffs(Item* item, bool castOnEquip) const { + std::vector buffs; + if (item == nullptr) return buffs; auto* table = CDClientManager::Instance()->GetTable("ObjectSkills"); auto* behaviors = CDClientManager::Instance()->GetTable("SkillBehavior"); const auto results = table->Query([=](const CDObjectSkills& entry) { - return entry.objectTemplate == static_cast(lot); + return entry.objectTemplate == static_cast(item->GetLot()); }); - std::vector buffs; - auto* missions = static_cast(m_Parent->GetComponent(COMPONENT_TYPE_MISSION)); for (const auto& result : results) @@ -1449,8 +1449,8 @@ std::vector InventoryComponent::FindBuffs(const LOT lot, bool castOnEq { missions->Progress(MissionTaskType::MISSION_TASK_TYPE_SKILL, result.skillID); } - - buffs.push_back(static_cast(entry.behaviorID)); + // If item is not a proxy, add its buff to the added buffs. + if (item->GetParent() == LWOOBJID_EMPTY) buffs.push_back(static_cast(entry.behaviorID)); } } @@ -1531,7 +1531,7 @@ std::vector InventoryComponent::GenerateProxies(Item* parent) auto* inventory = GetInventory(ITEM_SETS); - auto* proxy = new Item(lot, inventory, inventory->FindEmptySlot(), 1, {}, parent->GetId(), false, parent->GetId()); + auto* proxy = new Item(lot, inventory, inventory->FindEmptySlot(), 1, {}, parent->GetId(), false); EquipItem(proxy); diff --git a/dGame/dComponents/InventoryComponent.h b/dGame/dComponents/InventoryComponent.h index 22143802..f754a7fb 100644 --- a/dGame/dComponents/InventoryComponent.h +++ b/dGame/dComponents/InventoryComponent.h @@ -195,13 +195,13 @@ public: * Adds a buff related to equipping a lot to the entity * @param lot the lot to find buffs for */ - void ApplyBuff(LOT lot) const; + void ApplyBuff(Item* item) const; /** * Removes buffs related to equipping a lot from the entity * @param lot the lot to find buffs for */ - void RemoveBuff(LOT lot) const; + void RemoveBuff(Item* item) const; /** * Saves the equipped items into a temp state @@ -244,7 +244,7 @@ public: * @param castOnEquip if true, the skill missions for these buffs will be progressed * @return the buffs related to the specified lot */ - std::vector FindBuffs(LOT lot, bool castOnEquip) const; + std::vector FindBuffs(Item* item, bool castOnEquip) const; /** * Initializes the equipped items with a list of items From e43517efe66f73bec80f2fd7744d8d245480a53c Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 27 Mar 2022 15:28:21 -0700 Subject: [PATCH 079/251] comments --- dGame/dComponents/InventoryComponent.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dGame/dComponents/InventoryComponent.h b/dGame/dComponents/InventoryComponent.h index f754a7fb..43fdb084 100644 --- a/dGame/dComponents/InventoryComponent.h +++ b/dGame/dComponents/InventoryComponent.h @@ -193,13 +193,13 @@ public: /** * Adds a buff related to equipping a lot to the entity - * @param lot the lot to find buffs for + * @param item the item to find buffs for */ void ApplyBuff(Item* item) const; /** * Removes buffs related to equipping a lot from the entity - * @param lot the lot to find buffs for + * @param item the item to find buffs for */ void RemoveBuff(Item* item) const; From a7cd2f4d9bd1cf0420d29b95031562f62487c3f7 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 27 Mar 2022 15:37:05 -0700 Subject: [PATCH 080/251] comments --- dGame/dComponents/InventoryComponent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dComponents/InventoryComponent.h b/dGame/dComponents/InventoryComponent.h index 43fdb084..0a4cfdb3 100644 --- a/dGame/dComponents/InventoryComponent.h +++ b/dGame/dComponents/InventoryComponent.h @@ -240,7 +240,7 @@ public: /** * Finds all the buffs related to a lot - * @param lot the lot to get the buffs for + * @param item the item to get the buffs for * @param castOnEquip if true, the skill missions for these buffs will be progressed * @return the buffs related to the specified lot */ From 0a7fd6f79ab57a224ae35710a8a4bbaac5e4eb98 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 27 Mar 2022 20:04:45 -0700 Subject: [PATCH 081/251] updates --- .../dComponents/PropertyEntranceComponent.cpp | 96 +++++++++++-------- dGame/dComponents/PropertyEntranceComponent.h | 7 ++ 2 files changed, 65 insertions(+), 38 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 9e286ffa..3736b6b8 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -7,6 +7,7 @@ #include "dLogger.h" #include "Database.h" #include "PropertyManagementComponent.h" +#include "UserManager.h" PropertyEntranceComponent::PropertyEntranceComponent(uint32_t componentID, Entity* parent) : Component(parent) { @@ -117,42 +118,40 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, sql::ResultSet* propertyEntry; sql::PreparedStatement* propertyLookup; + std::string orderBy = ""; + int32_t privacyType = 2; const auto moderating = entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR; - - if (!moderating) - { - propertyLookup = Database::CreatePreppedStmt( - "SELECT * FROM properties WHERE (name LIKE ? OR description LIKE ? OR " - "((SELECT name FROM charinfo WHERE prop_clone_id = clone_id) LIKE ?)) AND " - "(privacy_option = 2 AND mod_approved = true) OR (privacy_option >= 1 " - "AND (owner_id IN (SELECT friend_id FROM friends WHERE player_id = ?) OR owner_id IN (SELECT player_id FROM " - "friends WHERE friend_id = ?))) AND zone_id = ? LIMIT ? OFFSET ?;" - ); - - const std::string searchString = "%" + filterText + "%"; - Game::logger->Log("PropertyEntranceComponent", "%s\n", searchString.c_str()); - propertyLookup->setString(1, searchString.c_str()); - propertyLookup->setString(2, searchString.c_str()); - propertyLookup->setString(3, searchString.c_str()); - propertyLookup->setInt64(4, entity->GetObjectID()); - propertyLookup->setInt64(5, entity->GetObjectID()); - propertyLookup->setUInt(6, launchpadComponent->GetTargetZone()); - propertyLookup->setInt(7, numResults); - propertyLookup->setInt(8, startIndex); - - propertyEntry = propertyLookup->executeQuery(); + + // We change how we sort this query based on what the requested order is. + if (sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS) { + orderBy = "ci.name"; + privacyType = 1; } - else - { - propertyLookup = Database::CreatePreppedStmt( - "SELECT * FROM properties WHERE privacy_option = 2 AND mod_approved = false AND zone_id = ?;" - ); - - propertyLookup->setUInt(1, launchpadComponent->GetTargetZone()); - - propertyEntry = propertyLookup->executeQuery(); + else if (sortMethod == SORT_TYPE_RECENT) { + orderBy = "p.last_updated"; } + else if (sortMethod == SORT_TYPE_REPUTATION) { + orderBy = "p.reputation, p.last_updated"; + } + else { + orderBy = "p.last_updated"; + } + + propertyLookup = Database::CreatePreppedStmt("SELECT p.* FROM properties as p JOIN charinfo as ci ON ci.prop_clone_id = p.clone_id where p.zone_id = ? AND (p.description OR p.name OR ci.name LIKE ?) AND p.mod_approved >= ? AND p.privacy_option = ? ORDER BY ? DESC LIMIT ? OFFSET ?;"); + + const std::string searchString = "%" + filterText + "%"; + Game::logger->Log("PropertyEntranceComponent", "%s\n", searchString.c_str()); + propertyLookup->setUInt(1, launchpadComponent->GetTargetZone()); + propertyLookup->setString(2, searchString.c_str()); + propertyLookup->setInt(3, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR ? 0 : 1); + propertyLookup->setInt(4, privacyType); + propertyLookup->setString(5, orderBy); + propertyLookup->setInt(6, numResults); + propertyLookup->setInt(7, startIndex); + Game::logger->Log("PropertyEntranceComponent", "Querying target zone %i with search string %s and ordering by %s starting at index %i. Entity is %s.\n", launchpadComponent->GetTargetZone(), searchString.c_str(), orderBy.c_str(), startIndex, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR ? "a moderator" : "not a moderator"); + + propertyEntry = propertyLookup->executeQuery(); while (propertyEntry->next()) { @@ -162,6 +161,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, const auto name = propertyEntry->getString(5).asStdString(); const auto description = propertyEntry->getString(6).asStdString(); const auto privacyOption = propertyEntry->getInt(9); + const auto modApproved = propertyEntry->getBoolean(10); const auto reputation = propertyEntry->getInt(15); PropertySelectQueryProperty entry {}; @@ -182,11 +182,11 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, } else { - entry.IsOwner = owner == entity->GetObjectID(); + entry.IsOwner = owner == entity->GetCharacter()->GetID(); entry.OwnerName = nameResult->getString(1).asStdString(); } - if (!moderating) + if (modApproved) { entry.Name = name; entry.Description = description; @@ -196,12 +196,32 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, entry.Name = "[Awaiting approval] " + name; entry.Description = "[Awaiting approval] " + description; } - - entry.IsFriend = privacyOption == static_cast(PropertyPrivacyOption::Friends); + // Convert owner char id to LWOOBJID + LWOOBJID ownerObjId = owner; + ownerObjId = GeneralUtils::SetBit(ownerObjId, OBJECT_BIT_CHARACTER); + ownerObjId = GeneralUtils::SetBit(ownerObjId, OBJECT_BIT_PERSISTENT); + + auto friendCheck = Database::CreatePreppedStmt("SELECT * FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?)"); + + friendCheck->setInt64(1, entity->GetObjectID()); + friendCheck->setInt64(2, ownerObjId); + friendCheck->setInt64(3, ownerObjId); + friendCheck->setInt64(4, entity->GetObjectID()); + + auto friendResult = friendCheck->executeQuery(); + + // If we got a result than the two players are friends. + if (friendResult->next()) { + entry.IsFriend = true; + } + else { + entry.IsFriend = false; + } + entry.Reputation = reputation; entry.CloneId = cloneId; - entry.IsModeratorApproved = true; - entry.AccessType = 3; + entry.IsModeratorApproved = modApproved == true; + entry.AccessType = privacyOption; entries.push_back(entry); diff --git a/dGame/dComponents/PropertyEntranceComponent.h b/dGame/dComponents/PropertyEntranceComponent.h index 8e35fd91..0c043ed0 100644 --- a/dGame/dComponents/PropertyEntranceComponent.h +++ b/dGame/dComponents/PropertyEntranceComponent.h @@ -84,4 +84,11 @@ private: * The base map ID for this property (Avant Grove, etc). */ LWOMAPID m_MapID; + + enum ePropertySortType : int32_t { + SORT_TYPE_FRIENDS = 0, + SORT_TYPE_REPUTATION = 1, + SORT_TYPE_RECENT = 3, + SORT_TYPE_FEATURED = 5 + }; }; From 0a453e9dcae2a4d37fe4166325654d9594e08f26 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 27 Mar 2022 23:46:43 -0700 Subject: [PATCH 082/251] working state --- .../dComponents/PropertyEntranceComponent.cpp | 97 +++++++++++++++---- .../PropertySelectQueryProperty.cpp | 2 +- .../PropertySelectQueryProperty.h | 2 +- 3 files changed, 78 insertions(+), 23 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 3736b6b8..56317eb5 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -1,4 +1,5 @@ #include +#include #include "PropertyEntranceComponent.h" #include "PropertySelectQueryProperty.h" #include "RocketLaunchpadControlComponent.h" @@ -132,7 +133,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, orderBy = "p.last_updated"; } else if (sortMethod == SORT_TYPE_REPUTATION) { - orderBy = "p.reputation, p.last_updated"; + orderBy = "p.reputation DESC, p.last_updated"; } else { orderBy = "p.last_updated"; @@ -156,13 +157,13 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, while (propertyEntry->next()) { const auto propertyId = propertyEntry->getUInt64(1); - const auto owner = propertyEntry->getUInt64(2); + const auto owner = propertyEntry->getInt(2); const auto cloneId = propertyEntry->getUInt64(4); const auto name = propertyEntry->getString(5).asStdString(); const auto description = propertyEntry->getString(6).asStdString(); const auto privacyOption = propertyEntry->getInt(9); const auto modApproved = propertyEntry->getBoolean(10); - const auto reputation = propertyEntry->getInt(15); + const auto reputation = propertyEntry->getInt(14); PropertySelectQueryProperty entry {}; @@ -182,7 +183,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, } else { - entry.IsOwner = owner == entity->GetCharacter()->GetID(); + entry.IsOwned = owner == entity->GetCharacter()->GetID(); entry.OwnerName = nameResult->getString(1).asStdString(); } @@ -191,17 +192,13 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, entry.Name = name; entry.Description = description; } - else - { - entry.Name = "[Awaiting approval] " + name; - entry.Description = "[Awaiting approval] " + description; - } + // Convert owner char id to LWOOBJID LWOOBJID ownerObjId = owner; ownerObjId = GeneralUtils::SetBit(ownerObjId, OBJECT_BIT_CHARACTER); ownerObjId = GeneralUtils::SetBit(ownerObjId, OBJECT_BIT_PERSISTENT); - auto friendCheck = Database::CreatePreppedStmt("SELECT * FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?)"); + auto friendCheck = Database::CreatePreppedStmt("SELECT best_friend FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?)"); friendCheck->setInt64(1, entity->GetObjectID()); friendCheck->setInt64(2, ownerObjId); @@ -213,35 +210,93 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, // If we got a result than the two players are friends. if (friendResult->next()) { entry.IsFriend = true; + if (friendResult->getBoolean(1) == true) { + entry.IsBestFriend = true; + } else { + entry.IsBestFriend = false; + } } else { entry.IsFriend = false; + entry.IsBestFriend = false; } + // Game::logger->Log("FriendsQuery", "Friend OBJID %lu my OBJID %lu\n", ownerObjId, entity->GetObjectID()); + auto isAltQuery = Database::CreatePreppedStmt("SELECT id FROM charinfo where account_id in (SELECT account_id from charinfo WHERE id = ?) AND id = ?;"); + + isAltQuery->setInt(1, character->GetID()); + isAltQuery->setInt(2, owner); + + Game::logger->Log("PropertyEntranceComponent", "main character is %i with alt query being %i\n", character->GetID(), owner); + + auto isAltQueryResults = isAltQuery->executeQuery(); + + if (isAltQueryResults->next()) { + entry.IsAlt = true; + } else { + entry.IsAlt = false; + } + + delete isAltQuery; + isAltQuery = nullptr; + entry.Reputation = reputation; entry.CloneId = cloneId; entry.IsModeratorApproved = modApproved == true; entry.AccessType = privacyOption; entries.push_back(entry); - delete nameLookup; } delete propertyLookup; + Game::logger->Log("HELLO", "WE GOT TO HERE"); + // auto newpropertyLookup = Database::CreatePreppedStmt("SELECT * FROM properties WHERE owner_id = ? AND zone_id = ?"); - /* - const auto entriesSize = entries.size(); + // newpropertyLookup->setInt(1, character->GetID()); + // newpropertyLookup->setInt(2, launchpadComponent->GetTargetZone()); - if (startIndex != 0 && entriesSize > startIndex) - { - for (size_t i = 0; i < startIndex; i++) - { - entries.erase(entries.begin()); - } - } - */ + // auto results = propertyLookup->executeQuery(); + // PropertySelectQueryProperty entry {}; + + // entry.CloneId = character->GetPropertyCloneID(); + // entry.OwnerName = ""; + // entry.Name = ""; + // entry.Description = ""; + // entry.Reputation = 0; + // entry.IsBestFriend = true; + // entry.IsFriend = true; + // entry.IsModeratorApproved = false; + // entry.IsAlt = true; + // entry.IsOwned = false; + // entry.AccessType = 0; + // // entry.DatePublished = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + // // entry.DatePublished = 0; + // // entry.PerformanceCost = entity->GetObjectID(); + + // if (results->next()) { + // const auto propertyId = results->getUInt64(1); + // const auto owner = results->getUInt64(2); + // const auto cloneId = results->getUInt64(4); + // const auto name = results->getString(5).asStdString(); + // const auto description = results->getString(6).asStdString(); + // const auto privacyOption = results->getInt(9); + // const auto modApproved = results->getBoolean(10); + // const auto reputation = results->getInt(14); + + // // entry.CloneId = cloneId; + // // entry.OwnerName = character->GetName(); + // // entry.Name = name; + // // entry.Description = description; + // // entry.Reputation = reputation; + // // entry.IsBestFriend = true; + // // entry.IsFriend = true; + // entry.IsModeratorApproved = modApproved; + // entry.IsAlt = true; + // entry.IsOwned = true; + // } + // entries.insert(entries.begin(), entry); propertyQueries[entity->GetObjectID()] = entries; GameMessages::SendPropertySelectQuery( diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.cpp b/dGame/dGameMessages/PropertySelectQueryProperty.cpp index f32ce537..31a1699b 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.cpp +++ b/dGame/dGameMessages/PropertySelectQueryProperty.cpp @@ -27,7 +27,7 @@ void PropertySelectQueryProperty::Serialize(RakNet::BitStream& stream) const stream.Write(IsFriend); stream.Write(IsModeratorApproved); stream.Write(IsAlt); - stream.Write(IsOwner); + stream.Write(IsOwned); stream.Write(AccessType); stream.Write(DatePublished); stream.Write(PerformanceCost); diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.h b/dGame/dGameMessages/PropertySelectQueryProperty.h index 0aaab912..87efd4ca 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.h +++ b/dGame/dGameMessages/PropertySelectQueryProperty.h @@ -18,7 +18,7 @@ public: bool IsFriend = false; bool IsModeratorApproved = false; bool IsAlt = false; - bool IsOwner = false; + bool IsOwned = false; uint32_t AccessType = 0; uint32_t DatePublished = 0; uint64_t PerformanceCost = 0; From 54de6c6878af501df9eb6e963486a8171b18118a Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 03:24:49 -0700 Subject: [PATCH 083/251] FINALLY WORKING JESUS --- .../dComponents/PropertyEntranceComponent.cpp | 150 +++++++++--------- dGame/dComponents/PropertyEntranceComponent.h | 4 +- .../PropertySelectQueryProperty.cpp | 1 + .../PropertySelectQueryProperty.h | 2 +- 4 files changed, 83 insertions(+), 74 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 56317eb5..02bfd8c9 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -82,7 +82,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool playerOwn, bool updateUi, int32_t numResults, - int32_t reputation, + int32_t lReputationTime, int32_t sortMethod, int32_t startIndex, std::string filterText, @@ -94,7 +94,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, playerOwn, updateUi, numResults, - reputation, + lReputationTime, sortMethod, startIndex, filterText.c_str() @@ -106,15 +106,46 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, std::vector entries {}; PropertySelectQueryProperty playerEntry {}; - auto* character = entity->GetCharacter(); - playerEntry.OwnerName = character->GetName(); - playerEntry.Description = "No description."; - playerEntry.Name = "Your property!"; - playerEntry.IsModeratorApproved = true; - playerEntry.AccessType = 2; - playerEntry.CloneId = character->GetPropertyCloneID(); + auto newpropertyLookup = Database::CreatePreppedStmt("SELECT * FROM properties WHERE owner_id = ? AND zone_id = ?"); + + newpropertyLookup->setInt(1, character->GetID()); + newpropertyLookup->setInt(2, launchpadComponent->GetTargetZone()); + + auto results = newpropertyLookup->executeQuery(); + + playerEntry.CloneId = character->GetPropertyCloneID(); + playerEntry.OwnerName = ""; + playerEntry.Name = ""; + playerEntry.Description = ""; + playerEntry.Reputation = 0; + playerEntry.IsBestFriend = true; + playerEntry.IsFriend = true; + playerEntry.IsModeratorApproved = false; + playerEntry.IsAlt = true; + playerEntry.IsOwned = false; + playerEntry.AccessType = 0; + playerEntry.DatePublished = 0; + + if (results->next()) { + const auto propertyId = results->getUInt64(1); + const auto owner = results->getUInt64(2); + const auto cloneId = results->getUInt64(4); + const auto name = results->getString(5).asStdString(); + const auto description = results->getString(6).asStdString(); + const auto privacyOption = results->getInt(9); + const auto modApproved = results->getBoolean(10); + const auto dateUpdated = results->getInt64(11); + const auto reputation = results->getInt(14); + + playerEntry.Name = name; + playerEntry.Description = description; + playerEntry.DatePublished = dateUpdated; + playerEntry.IsModeratorApproved = modApproved; + playerEntry.IsAlt = true; + playerEntry.IsOwned = true; + } entries.push_back(playerEntry); sql::ResultSet* propertyEntry; @@ -124,32 +155,54 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, const auto moderating = entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR; + std::string baseQuery = "SELECT p.* FROM properties as p JOIN charinfo as ci ON ci.prop_clone_id = p.clone_id where p.zone_id = ? AND (p.description LIKE ? OR p.name LIKE ? OR ci.name LIKE ?) AND p.mod_approved >= ? AND p.privacy_option >= ? "; + + // In case the query is for friends. + std::string friendsList = " AND p.owner_id IN ("; // We change how we sort this query based on what the requested order is. if (sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS) { - orderBy = "ci.name"; + auto friendsListQuery = Database::CreatePreppedStmt("SELECT * FROM (SELECT CASE WHEN player_id = ? THEN friend_id WHEN friend_id = ? THEN player_id END AS requested_player FROM dlu.friends ) AS fr WHERE requested_player IS NOT NULL ORDER BY requested_player DESC;"); + + friendsListQuery->setInt64(1, entity->GetObjectID()); + friendsListQuery->setInt64(2, entity->GetObjectID()); + // friendsListQuery->setInt(3, numResults); + // friendsListQuery->setInt(4, startIndex); + + auto friendsListQueryResult = friendsListQuery->executeQuery(); + + while (friendsListQueryResult->next()) { + auto playerIDToConvert = friendsListQueryResult->getInt64(1); + playerIDToConvert = GeneralUtils::ClearBit(playerIDToConvert, OBJECT_BIT_CHARACTER); + playerIDToConvert = GeneralUtils::ClearBit(playerIDToConvert, OBJECT_BIT_PERSISTENT); + friendsList = friendsList + std::to_string(playerIDToConvert) + ","; + } + // Replace trailing comma with the closing parenthesis. + friendsList.replace(friendsList.size() - 1, 2, ") "); + orderBy = friendsList + "ORDER BY ci.name ASC "; privacyType = 1; } else if (sortMethod == SORT_TYPE_RECENT) { - orderBy = "p.last_updated"; + orderBy = "ORDER BY p.last_updated DESC "; } else if (sortMethod == SORT_TYPE_REPUTATION) { - orderBy = "p.reputation DESC, p.last_updated"; + orderBy = "ORDER BY p.reputation DESC, p.last_updated DESC "; } else { - orderBy = "p.last_updated"; + orderBy = "ORDER BY p.last_updated DESC "; } - - propertyLookup = Database::CreatePreppedStmt("SELECT p.* FROM properties as p JOIN charinfo as ci ON ci.prop_clone_id = p.clone_id where p.zone_id = ? AND (p.description OR p.name OR ci.name LIKE ?) AND p.mod_approved >= ? AND p.privacy_option = ? ORDER BY ? DESC LIMIT ? OFFSET ?;"); + auto finishedQuery = baseQuery + orderBy + "LIMIT ? OFFSET ?;"; + propertyLookup = Database::CreatePreppedStmt(finishedQuery); const std::string searchString = "%" + filterText + "%"; Game::logger->Log("PropertyEntranceComponent", "%s\n", searchString.c_str()); propertyLookup->setUInt(1, launchpadComponent->GetTargetZone()); propertyLookup->setString(2, searchString.c_str()); - propertyLookup->setInt(3, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR ? 0 : 1); - propertyLookup->setInt(4, privacyType); - propertyLookup->setString(5, orderBy); - propertyLookup->setInt(6, numResults); - propertyLookup->setInt(7, startIndex); + propertyLookup->setString(3, searchString.c_str()); + propertyLookup->setString(4, searchString.c_str()); + propertyLookup->setInt(5, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR || sortMethod == SORT_TYPE_FRIENDS ? 0 : 1); + propertyLookup->setInt(6, privacyType); + propertyLookup->setInt(7, numResults); + propertyLookup->setInt(8, startIndex); Game::logger->Log("PropertyEntranceComponent", "Querying target zone %i with search string %s and ordering by %s starting at index %i. Entity is %s.\n", launchpadComponent->GetTargetZone(), searchString.c_str(), orderBy.c_str(), startIndex, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR ? "a moderator" : "not a moderator"); propertyEntry = propertyLookup->executeQuery(); @@ -163,7 +216,10 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, const auto description = propertyEntry->getString(6).asStdString(); const auto privacyOption = propertyEntry->getInt(9); const auto modApproved = propertyEntry->getBoolean(10); - const auto reputation = propertyEntry->getInt(14); + const auto dateUpdated = propertyEntry->getInt(11); + const auto reputation = propertyEntry->getUInt(14); + + Game::logger->Log("PropertyEntranceComponent", "Property being loaded is %i with reputation %lu\n", owner, reputation); PropertySelectQueryProperty entry {}; @@ -221,14 +277,11 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, entry.IsBestFriend = false; } - // Game::logger->Log("FriendsQuery", "Friend OBJID %lu my OBJID %lu\n", ownerObjId, entity->GetObjectID()); auto isAltQuery = Database::CreatePreppedStmt("SELECT id FROM charinfo where account_id in (SELECT account_id from charinfo WHERE id = ?) AND id = ?;"); isAltQuery->setInt(1, character->GetID()); isAltQuery->setInt(2, owner); - Game::logger->Log("PropertyEntranceComponent", "main character is %i with alt query being %i\n", character->GetID(), owner); - auto isAltQueryResults = isAltQuery->executeQuery(); if (isAltQueryResults->next()) { @@ -239,64 +292,19 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, delete isAltQuery; isAltQuery = nullptr; - + entry.DatePublished = dateUpdated; entry.Reputation = reputation; entry.CloneId = cloneId; entry.IsModeratorApproved = modApproved == true; entry.AccessType = privacyOption; + entry.PerformanceCost = entity->GetObjectID(); entries.push_back(entry); delete nameLookup; } delete propertyLookup; - Game::logger->Log("HELLO", "WE GOT TO HERE"); - // auto newpropertyLookup = Database::CreatePreppedStmt("SELECT * FROM properties WHERE owner_id = ? AND zone_id = ?"); - // newpropertyLookup->setInt(1, character->GetID()); - // newpropertyLookup->setInt(2, launchpadComponent->GetTargetZone()); - - // auto results = propertyLookup->executeQuery(); - - // PropertySelectQueryProperty entry {}; - - // entry.CloneId = character->GetPropertyCloneID(); - // entry.OwnerName = ""; - // entry.Name = ""; - // entry.Description = ""; - // entry.Reputation = 0; - // entry.IsBestFriend = true; - // entry.IsFriend = true; - // entry.IsModeratorApproved = false; - // entry.IsAlt = true; - // entry.IsOwned = false; - // entry.AccessType = 0; - // // entry.DatePublished = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); - // // entry.DatePublished = 0; - // // entry.PerformanceCost = entity->GetObjectID(); - - // if (results->next()) { - // const auto propertyId = results->getUInt64(1); - // const auto owner = results->getUInt64(2); - // const auto cloneId = results->getUInt64(4); - // const auto name = results->getString(5).asStdString(); - // const auto description = results->getString(6).asStdString(); - // const auto privacyOption = results->getInt(9); - // const auto modApproved = results->getBoolean(10); - // const auto reputation = results->getInt(14); - - // // entry.CloneId = cloneId; - // // entry.OwnerName = character->GetName(); - // // entry.Name = name; - // // entry.Description = description; - // // entry.Reputation = reputation; - // // entry.IsBestFriend = true; - // // entry.IsFriend = true; - // entry.IsModeratorApproved = modApproved; - // entry.IsAlt = true; - // entry.IsOwned = true; - // } - // entries.insert(entries.begin(), entry); propertyQueries[entity->GetObjectID()] = entries; GameMessages::SendPropertySelectQuery( diff --git a/dGame/dComponents/PropertyEntranceComponent.h b/dGame/dComponents/PropertyEntranceComponent.h index 0c043ed0..dfc3f80a 100644 --- a/dGame/dComponents/PropertyEntranceComponent.h +++ b/dGame/dComponents/PropertyEntranceComponent.h @@ -38,7 +38,7 @@ public: * @param playerOwn only query properties owned by the entity * @param updateUi unused * @param numResults unused - * @param reputation unused + * @param lReputationTime unused * @param sortMethod unused * @param startIndex the minimum index to start the query off * @param filterText property names to search for @@ -50,7 +50,7 @@ public: bool playerOwn, bool updateUi, int32_t numResults, - int32_t reputation, + int32_t lReputationTime, int32_t sortMethod, int32_t startIndex, std::string filterText, diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.cpp b/dGame/dGameMessages/PropertySelectQueryProperty.cpp index 31a1699b..135dac1f 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.cpp +++ b/dGame/dGameMessages/PropertySelectQueryProperty.cpp @@ -1,4 +1,5 @@ #include "PropertySelectQueryProperty.h" +#include void PropertySelectQueryProperty::Serialize(RakNet::BitStream& stream) const { diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.h b/dGame/dGameMessages/PropertySelectQueryProperty.h index 87efd4ca..68f95548 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.h +++ b/dGame/dGameMessages/PropertySelectQueryProperty.h @@ -13,7 +13,7 @@ public: std::string OwnerName = ""; std::string Name = ""; std::string Description = ""; - uint32_t Reputation = 0; + uint32_t Reputation = 10; bool IsBestFriend = false; bool IsFriend = false; bool IsModeratorApproved = false; From c94f0918c9e8bd297adf9ea17bba8d7a47ca83f6 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 03:26:01 -0700 Subject: [PATCH 084/251] testing number reverted --- dGame/dGameMessages/PropertySelectQueryProperty.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.h b/dGame/dGameMessages/PropertySelectQueryProperty.h index 68f95548..87efd4ca 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.h +++ b/dGame/dGameMessages/PropertySelectQueryProperty.h @@ -13,7 +13,7 @@ public: std::string OwnerName = ""; std::string Name = ""; std::string Description = ""; - uint32_t Reputation = 10; + uint32_t Reputation = 0; bool IsBestFriend = false; bool IsFriend = false; bool IsModeratorApproved = false; From 148c177d2721b5227a990b840589ee150e0c2b0e Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 03:37:12 -0700 Subject: [PATCH 085/251] shortened method --- .../dComponents/PropertyEntranceComponent.cpp | 28 ++----------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 02bfd8c9..28840dd0 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -76,33 +76,9 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, launcher->Launch(entity, LWOOBJID_EMPTY, LWOMAPID_INVALID, cloneId); } -void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, - bool includeNullAddress, - bool includeNullDescription, - bool playerOwn, - bool updateUi, - int32_t numResults, - int32_t lReputationTime, - int32_t sortMethod, - int32_t startIndex, - std::string filterText, - const SystemAddress& sysAddr) -{ - Game::logger->Log("PropertyEntranceComponent", "On Sync %d %d %d %d %i %i %i %i %s\n", - includeNullAddress, - includeNullDescription, - playerOwn, - updateUi, - numResults, - lReputationTime, - sortMethod, - startIndex, - filterText.c_str() - ); - +void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool includeNullAddress, bool includeNullDescription, bool playerOwn, bool updateUi, int32_t numResults, int32_t lReputationTime, int32_t sortMethod, int32_t startIndex, std::string filterText, const SystemAddress& sysAddr){ auto* launchpadComponent = m_Parent->GetComponent(); - if (launchpadComponent == nullptr) - return; + if (launchpadComponent == nullptr) return; std::vector entries {}; PropertySelectQueryProperty playerEntry {}; From dc74b46e11f0abfc14db692f0177249b98302f05 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 03:58:40 -0700 Subject: [PATCH 086/251] off by one moment --- dGame/dComponents/PropertyManagementComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dComponents/PropertyManagementComponent.cpp b/dGame/dComponents/PropertyManagementComponent.cpp index 506c1608..cd99fd78 100644 --- a/dGame/dComponents/PropertyManagementComponent.cpp +++ b/dGame/dComponents/PropertyManagementComponent.cpp @@ -71,7 +71,7 @@ PropertyManagementComponent::PropertyManagementComponent(Entity* parent) : Compo this->propertyName = propertyEntry->getString(5).c_str(); this->propertyDescription = propertyEntry->getString(6).c_str(); this->privacyOption = static_cast(propertyEntry->getUInt(9)); - this->claimedTime = propertyEntry->getUInt64(13); + this->claimedTime = propertyEntry->getUInt64(12); Load(); } From 17f773c6cb693e79d02b8037638e5171cc7c9657 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 04:25:44 -0700 Subject: [PATCH 087/251] comment --- dGame/dMission/Mission.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dMission/Mission.cpp b/dGame/dMission/Mission.cpp index 2719a6cf..f841f2f1 100644 --- a/dGame/dMission/Mission.cpp +++ b/dGame/dMission/Mission.cpp @@ -516,7 +516,7 @@ void Mission::YieldRewards() { } if (info->reward_reputation > 0) { - // TODO: Track reputation in the character and database. + // TODO: Track reputation in the property table and in charxml missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_EARN_REPUTATION, 0, 0L, "", info->reward_reputation); } From 895bbec277f9fd9d8e3ddf52fa8f8e81e50eb266 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 19:58:15 -0700 Subject: [PATCH 088/251] clarified variable name --- dGame/dGameMessages/PropertySelectQueryProperty.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.h b/dGame/dGameMessages/PropertySelectQueryProperty.h index 87efd4ca..b136f5cd 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.h +++ b/dGame/dGameMessages/PropertySelectQueryProperty.h @@ -20,6 +20,6 @@ public: bool IsAlt = false; bool IsOwned = false; uint32_t AccessType = 0; - uint32_t DatePublished = 0; + uint32_t DateLastPublished = 0; uint64_t PerformanceCost = 0; }; From 17b0de80622f828dcd541d900d04b14487372c3d Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 19:58:23 -0700 Subject: [PATCH 089/251] clarified variable name --- dGame/dGameMessages/PropertySelectQueryProperty.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.cpp b/dGame/dGameMessages/PropertySelectQueryProperty.cpp index 135dac1f..78b7198d 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.cpp +++ b/dGame/dGameMessages/PropertySelectQueryProperty.cpp @@ -30,7 +30,7 @@ void PropertySelectQueryProperty::Serialize(RakNet::BitStream& stream) const stream.Write(IsAlt); stream.Write(IsOwned); stream.Write(AccessType); - stream.Write(DatePublished); + stream.Write(DateLastPublished); stream.Write(PerformanceCost); } From 965d4c7af00568a04a684e5de4e94ed33df919ab Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 19:58:50 -0700 Subject: [PATCH 090/251] cleaned up file and added helper functions --- .../dComponents/PropertyEntranceComponent.cpp | 165 +++++++++--------- dGame/dComponents/PropertyEntranceComponent.h | 34 ++-- 2 files changed, 98 insertions(+), 101 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 28840dd0..d2afd53c 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -1,5 +1,4 @@ #include -#include #include "PropertyEntranceComponent.h" #include "PropertySelectQueryProperty.h" #include "RocketLaunchpadControlComponent.h" @@ -51,6 +50,7 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, } else if (index >= 0) { + // Increment index once here because the first index of other player properties is 2 in the propertyQueries cache. index++; const auto& pair = propertyQueries.find(entity->GetObjectID()); @@ -64,6 +64,8 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, cloneId = query[index].CloneId; } + Game::logger->Log("PropertyEntranceComponent", "index is %i\n", index); + auto* launcher = m_Parent->GetComponent(); if (launcher == nullptr) @@ -73,76 +75,37 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, launcher->SetSelectedCloneId(entity->GetObjectID(), cloneId); - launcher->Launch(entity, LWOOBJID_EMPTY, LWOMAPID_INVALID, cloneId); + launcher->Launch(entity, LWOOBJID_EMPTY, launcher->GetTargetZone(), cloneId); } -void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool includeNullAddress, bool includeNullDescription, bool playerOwn, bool updateUi, int32_t numResults, int32_t lReputationTime, int32_t sortMethod, int32_t startIndex, std::string filterText, const SystemAddress& sysAddr){ - auto* launchpadComponent = m_Parent->GetComponent(); - if (launchpadComponent == nullptr) return; +PropertySelectQueryProperty PropertyEntranceComponent::SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId, std::string ownerName, std::string propertyName, std::string propertyDescription, + uint32_t reputation, bool isBFF, bool isFriend, bool isModeratorApproved, bool isAlt, bool isOwned, uint32_t privacyOption, uint32_t timeLastUpdated, uint64_t performanceCost) { + property.CloneId = cloneId; + property.OwnerName = ownerName; + property.Name = propertyName; + property.Description = propertyDescription; + property.Reputation = reputation; + property.IsBestFriend = isBFF; + property.IsFriend = isFriend; + property.IsModeratorApproved = isModeratorApproved; + property.IsAlt = isAlt; + property.IsOwned = isOwned; + property.AccessType = privacyOption; + property.DateLastPublished = timeLastUpdated; + property.PerformanceCost = performanceCost; - std::vector entries {}; - PropertySelectQueryProperty playerEntry {}; - auto* character = entity->GetCharacter(); + return property; +} - auto newpropertyLookup = Database::CreatePreppedStmt("SELECT * FROM properties WHERE owner_id = ? AND zone_id = ?"); - - newpropertyLookup->setInt(1, character->GetID()); - newpropertyLookup->setInt(2, launchpadComponent->GetTargetZone()); - - auto results = newpropertyLookup->executeQuery(); - - playerEntry.CloneId = character->GetPropertyCloneID(); - playerEntry.OwnerName = ""; - playerEntry.Name = ""; - playerEntry.Description = ""; - playerEntry.Reputation = 0; - playerEntry.IsBestFriend = true; - playerEntry.IsFriend = true; - playerEntry.IsModeratorApproved = false; - playerEntry.IsAlt = true; - playerEntry.IsOwned = false; - playerEntry.AccessType = 0; - playerEntry.DatePublished = 0; - - if (results->next()) { - const auto propertyId = results->getUInt64(1); - const auto owner = results->getUInt64(2); - const auto cloneId = results->getUInt64(4); - const auto name = results->getString(5).asStdString(); - const auto description = results->getString(6).asStdString(); - const auto privacyOption = results->getInt(9); - const auto modApproved = results->getBoolean(10); - const auto dateUpdated = results->getInt64(11); - const auto reputation = results->getInt(14); - - playerEntry.Name = name; - playerEntry.Description = description; - playerEntry.DatePublished = dateUpdated; - playerEntry.IsModeratorApproved = modApproved; - playerEntry.IsAlt = true; - playerEntry.IsOwned = true; - } - entries.push_back(playerEntry); - - sql::ResultSet* propertyEntry; - sql::PreparedStatement* propertyLookup; +std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMethod) { + auto base = baseQueryForProperties; std::string orderBy = ""; - int32_t privacyType = 2; - - const auto moderating = entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR; - - std::string baseQuery = "SELECT p.* FROM properties as p JOIN charinfo as ci ON ci.prop_clone_id = p.clone_id where p.zone_id = ? AND (p.description LIKE ? OR p.name LIKE ? OR ci.name LIKE ?) AND p.mod_approved >= ? AND p.privacy_option >= ? "; - - // In case the query is for friends. std::string friendsList = " AND p.owner_id IN ("; - // We change how we sort this query based on what the requested order is. - if (sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS) { + if (sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS) { auto friendsListQuery = Database::CreatePreppedStmt("SELECT * FROM (SELECT CASE WHEN player_id = ? THEN friend_id WHEN friend_id = ? THEN player_id END AS requested_player FROM dlu.friends ) AS fr WHERE requested_player IS NOT NULL ORDER BY requested_player DESC;"); friendsListQuery->setInt64(1, entity->GetObjectID()); friendsListQuery->setInt64(2, entity->GetObjectID()); - // friendsListQuery->setInt(3, numResults); - // friendsListQuery->setInt(4, startIndex); auto friendsListQueryResult = friendsListQuery->executeQuery(); @@ -155,7 +118,11 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl // Replace trailing comma with the closing parenthesis. friendsList.replace(friendsList.size() - 1, 2, ") "); orderBy = friendsList + "ORDER BY ci.name ASC "; - privacyType = 1; + + delete friendsListQueryResult; + friendsListQueryResult = nullptr; + delete friendsListQuery; + friendsListQuery = nullptr; } else if (sortMethod == SORT_TYPE_RECENT) { orderBy = "ORDER BY p.last_updated DESC "; @@ -166,20 +133,63 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl else { orderBy = "ORDER BY p.last_updated DESC "; } - auto finishedQuery = baseQuery + orderBy + "LIMIT ? OFFSET ?;"; - propertyLookup = Database::CreatePreppedStmt(finishedQuery); + return baseQueryForProperties + orderBy + "LIMIT ? OFFSET ?;"; +} + +void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool includeNullAddress, bool includeNullDescription, bool playerOwn, bool updateUi, int32_t numResults, int32_t lReputationTime, int32_t sortMethod, int32_t startIndex, std::string filterText, const SystemAddress& sysAddr){ + + std::vector entries {}; + PropertySelectQueryProperty playerEntry {}; + auto* character = entity->GetCharacter(); + if (!character) return; + // Player property goes in index 1 of the vector. This is how the client expects it. + auto playerPropertyLookup = Database::CreatePreppedStmt("SELECT * FROM properties WHERE owner_id = ? AND zone_id = ?"); + + playerPropertyLookup->setInt(1, character->GetID()); + playerPropertyLookup->setInt(2, this->m_MapID); + + auto playerPropertyLookupResults = playerPropertyLookup->executeQuery(); + + // If the player has a property this query will have a single result. + if (playerPropertyLookupResults->next()) { + const auto cloneId = playerPropertyLookupResults->getUInt64(4); + const auto name = playerPropertyLookupResults->getString(5).asStdString(); + const auto description = playerPropertyLookupResults->getString(6).asStdString(); + const auto privacyOption = playerPropertyLookupResults->getInt(9); + const auto modApproved = playerPropertyLookupResults->getBoolean(10); + const auto dateLastUpdated = playerPropertyLookupResults->getInt64(11); + const auto reputation = playerPropertyLookupResults->getInt(14); + + playerEntry = SetPropertyValues(playerEntry, cloneId, character->GetName(), name, description, reputation, true, true, modApproved, true, true, privacyOption, dateLastUpdated); + } else { + playerEntry = SetPropertyValues(playerEntry, character->GetPropertyCloneID(), character->GetName(), "", "", 0, true, true); + } + + delete playerPropertyLookupResults; + playerPropertyLookupResults = nullptr; + delete playerPropertyLookup; + playerPropertyLookup = nullptr; + + entries.push_back(playerEntry); + + sql::ResultSet* propertyEntry; + sql::PreparedStatement* propertyLookup; + + const auto query = BuildQuery(entity, sortMethod); + + propertyLookup = Database::CreatePreppedStmt(query); const std::string searchString = "%" + filterText + "%"; - Game::logger->Log("PropertyEntranceComponent", "%s\n", searchString.c_str()); - propertyLookup->setUInt(1, launchpadComponent->GetTargetZone()); + propertyLookup->setUInt(1, this->m_MapID); propertyLookup->setString(2, searchString.c_str()); propertyLookup->setString(3, searchString.c_str()); propertyLookup->setString(4, searchString.c_str()); propertyLookup->setInt(5, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR || sortMethod == SORT_TYPE_FRIENDS ? 0 : 1); - propertyLookup->setInt(6, privacyType); + propertyLookup->setInt(6, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? 1 : 2); propertyLookup->setInt(7, numResults); propertyLookup->setInt(8, startIndex); - Game::logger->Log("PropertyEntranceComponent", "Querying target zone %i with search string %s and ordering by %s starting at index %i. Entity is %s.\n", launchpadComponent->GetTargetZone(), searchString.c_str(), orderBy.c_str(), startIndex, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR ? "a moderator" : "not a moderator"); + + Game::logger->Log("PropertyEntranceComponent", "Property query is \n%s\n. Entity is %s.\n", query.c_str(), entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR ? "a moderator" : "not a moderator"); propertyEntry = propertyLookup->executeQuery(); @@ -195,8 +205,6 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl const auto dateUpdated = propertyEntry->getInt(11); const auto reputation = propertyEntry->getUInt(14); - Game::logger->Log("PropertyEntranceComponent", "Property being loaded is %i with reputation %lu\n", owner, reputation); - PropertySelectQueryProperty entry {}; auto* nameLookup = Database::CreatePreppedStmt("SELECT name FROM charinfo WHERE prop_clone_id = ?;"); @@ -268,12 +276,14 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl delete isAltQuery; isAltQuery = nullptr; - entry.DatePublished = dateUpdated; + entry.DateLastPublished = dateUpdated; + // Reputation not updated client side for listing? entry.Reputation = reputation; entry.CloneId = cloneId; entry.IsModeratorApproved = modApproved == true; entry.AccessType = privacyOption; - entry.PerformanceCost = entity->GetObjectID(); + // Client still reads performance cost as zero? + entry.PerformanceCost = 0; entries.push_back(entry); delete nameLookup; @@ -283,14 +293,5 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl propertyQueries[entity->GetObjectID()] = entries; - GameMessages::SendPropertySelectQuery( - m_Parent->GetObjectID(), - startIndex, - entries.size() >= numResults, - character->GetPropertyCloneID(), - false, - true, - entries, - sysAddr - ); + GameMessages::SendPropertySelectQuery(m_Parent->GetObjectID(), startIndex, entries.size() >= numResults, character->GetPropertyCloneID(), false, true, entries, sysAddr); } \ No newline at end of file diff --git a/dGame/dComponents/PropertyEntranceComponent.h b/dGame/dComponents/PropertyEntranceComponent.h index dfc3f80a..1cfb98dc 100644 --- a/dGame/dComponents/PropertyEntranceComponent.h +++ b/dGame/dComponents/PropertyEntranceComponent.h @@ -1,17 +1,17 @@ #pragma once +#include + +#include "Component.h" #include "Entity.h" #include "EntityManager.h" #include "GameMessages.h" -#include "Component.h" -#include /** * Represents the launch pad that's used to select and browse properties */ -class PropertyEntranceComponent : public Component -{ -public: +class PropertyEntranceComponent : public Component { + public: static const uint32_t ComponentType = COMPONENT_TYPE_PROPERTY_ENTRANCE; explicit PropertyEntranceComponent(uint32_t componentID, Entity* parent); @@ -24,11 +24,11 @@ public: /** * Handles the event triggered when the entity selects a property to visit and makes the entity to there * @param entity the entity that triggered the event - * @param index the clone ID of the property to visit + * @param index the index of the property property * @param returnToZone whether or not the entity wishes to go back to the launch zone * @param sysAddr the address to send gamemessage responses to */ - void OnEnterProperty(Entity* entity, uint32_t index, bool returnToZone, const SystemAddress &sysAddr); + void OnEnterProperty(Entity* entity, uint32_t index, bool returnToZone, const SystemAddress& sysAddr); /** * Handles a request for information on available properties when an entity lands on the property @@ -44,17 +44,7 @@ public: * @param filterText property names to search for * @param sysAddr the address to send gamemessage responses to */ - void OnPropertyEntranceSync(Entity* entity, - bool includeNullAddress, - bool includeNullDescription, - bool playerOwn, - bool updateUi, - int32_t numResults, - int32_t lReputationTime, - int32_t sortMethod, - int32_t startIndex, - std::string filterText, - const SystemAddress &sysAddr); + void OnPropertyEntranceSync(Entity* entity, bool includeNullAddress, bool includeNullDescription, bool playerOwn, bool updateUi, int32_t numResults, int32_t lReputationTime, int32_t sortMethod, int32_t startIndex, std::string filterText, const SystemAddress& sysAddr); /** * Returns the name of this property @@ -68,8 +58,12 @@ public: */ [[nodiscard]] LWOMAPID GetMapID() const { return m_MapID; }; -private: + PropertySelectQueryProperty SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId = LWOCLONEID_INVALID, std::string ownerName = "", std::string propertyName = "", std::string propertyDescription = "", + uint32_t reputation = 0, bool isBFF = false, bool isFriend = false, bool isModeratorApproved = false, bool isAlt = false, bool isOwned = false, uint32_t privacyOption = 0, uint32_t timeLastUpdated = 0, uint64_t performanceCost = 0); + std::string BuildQuery(Entity* entity, int32_t sortMethod); + + private: /** * Cache of property information that was queried for property launched, indexed by property ID */ @@ -91,4 +85,6 @@ private: SORT_TYPE_RECENT = 3, SORT_TYPE_FEATURED = 5 }; + + const std::string baseQueryForProperties = "SELECT p.* FROM properties as p JOIN charinfo as ci ON ci.prop_clone_id = p.clone_id where p.zone_id = ? AND (p.description LIKE ? OR p.name LIKE ? OR ci.name LIKE ?) AND p.mod_approved >= ? AND p.privacy_option >= ? "; }; From 19e82a5150ed57ece1fca0d1778af5064e28a3ca Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 20:51:15 -0700 Subject: [PATCH 091/251] more cleanup --- .../dComponents/PropertyEntranceComponent.cpp | 106 +++++++++++------- 1 file changed, 63 insertions(+), 43 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index d2afd53c..fb13d622 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -84,6 +84,7 @@ PropertySelectQueryProperty PropertyEntranceComponent::SetPropertyValues(Propert property.OwnerName = ownerName; property.Name = propertyName; property.Description = propertyDescription; + // Reputation not updated for client side listing? property.Reputation = reputation; property.IsBestFriend = isBFF; property.IsFriend = isFriend; @@ -140,8 +141,10 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl std::vector entries {}; PropertySelectQueryProperty playerEntry {}; - auto* character = entity->GetCharacter(); + + auto character = entity->GetCharacter(); if (!character) return; + // Player property goes in index 1 of the vector. This is how the client expects it. auto playerPropertyLookup = Database::CreatePreppedStmt("SELECT * FROM properties WHERE owner_id = ? AND zone_id = ?"); @@ -167,19 +170,17 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl delete playerPropertyLookupResults; playerPropertyLookupResults = nullptr; + delete playerPropertyLookup; playerPropertyLookup = nullptr; entries.push_back(playerEntry); - sql::ResultSet* propertyEntry; - sql::PreparedStatement* propertyLookup; - const auto query = BuildQuery(entity, sortMethod); - propertyLookup = Database::CreatePreppedStmt(query); + auto propertyLookup = Database::CreatePreppedStmt(query); - const std::string searchString = "%" + filterText + "%"; + const auto searchString = "%" + filterText + "%"; propertyLookup->setUInt(1, this->m_MapID); propertyLookup->setString(2, searchString.c_str()); propertyLookup->setString(3, searchString.c_str()); @@ -191,7 +192,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl Game::logger->Log("PropertyEntranceComponent", "Property query is \n%s\n. Entity is %s.\n", query.c_str(), entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR ? "a moderator" : "not a moderator"); - propertyEntry = propertyLookup->executeQuery(); + auto propertyEntry = propertyLookup->executeQuery(); while (propertyEntry->next()) { @@ -202,42 +203,52 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl const auto description = propertyEntry->getString(6).asStdString(); const auto privacyOption = propertyEntry->getInt(9); const auto modApproved = propertyEntry->getBoolean(10); - const auto dateUpdated = propertyEntry->getInt(11); - const auto reputation = propertyEntry->getUInt(14); + const auto dateLastUpdated = propertyEntry->getInt(11); + const auto reputation = propertyEntry->getUInt(14); PropertySelectQueryProperty entry {}; - - auto* nameLookup = Database::CreatePreppedStmt("SELECT name FROM charinfo WHERE prop_clone_id = ?;"); + + std::string ownerName = ""; + bool isOwned = true; + auto nameLookup = Database::CreatePreppedStmt("SELECT name FROM charinfo WHERE prop_clone_id = ?;"); nameLookup->setUInt64(1, cloneId); - auto* nameResult = nameLookup->executeQuery(); + auto nameResult = nameLookup->executeQuery(); - if (!nameResult->next()) - { + if (!nameResult->next()) { delete nameLookup; + nameLookup = nullptr; Game::logger->Log("PropertyEntranceComponent", "Failed to find property owner name for %llu!\n", cloneId); continue; } - else - { - entry.IsOwned = owner == entity->GetCharacter()->GetID(); - entry.OwnerName = nameResult->getString(1).asStdString(); - } - - if (modApproved) - { - entry.Name = name; - entry.Description = description; + else { + isOwned = cloneId == character->GetPropertyCloneID(); + ownerName = nameResult->getString(1).asStdString(); } + delete nameResult; + nameResult = nullptr; + + delete nameLookup; + nameLookup = nullptr; + + std::string propertyName = ""; + std::string propertyDescription = ""; + propertyName = name; + propertyDescription = description; + + bool isBestFriend = false; + bool isFriend = false; + // Convert owner char id to LWOOBJID LWOOBJID ownerObjId = owner; ownerObjId = GeneralUtils::SetBit(ownerObjId, OBJECT_BIT_CHARACTER); ownerObjId = GeneralUtils::SetBit(ownerObjId, OBJECT_BIT_PERSISTENT); + // Query to get friend and best friend fields auto friendCheck = Database::CreatePreppedStmt("SELECT best_friend FROM friends WHERE (player_id = ? AND friend_id = ?) OR (player_id = ? AND friend_id = ?)"); friendCheck->setInt64(1, entity->GetObjectID()); @@ -249,18 +260,29 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl // If we got a result than the two players are friends. if (friendResult->next()) { - entry.IsFriend = true; + isFriend = true; if (friendResult->getBoolean(1) == true) { - entry.IsBestFriend = true; - } else { - entry.IsBestFriend = false; + isBestFriend = true; } } - else { - entry.IsFriend = false; - entry.IsBestFriend = false; + + delete friendCheck; + friendCheck = nullptr; + + delete friendResult; + friendResult = nullptr; + + bool isModeratorApproved = propertyEntry->getBoolean(10); + + if (!isModeratorApproved && entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR) { + ownerName = "[AWAITING APPROVAL]"; + propertyName = "[AWAITING APPROVAL]"; + propertyDescription = "[AWAITING APPROVAL]"; + entry.IsModeratorApproved = true; } + bool isAlt = false; + // Query to determine whether this property is an alt of the entity. auto isAltQuery = Database::CreatePreppedStmt("SELECT id FROM charinfo where account_id in (SELECT account_id from charinfo WHERE id = ?) AND id = ?;"); isAltQuery->setInt(1, character->GetID()); @@ -269,27 +291,25 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl auto isAltQueryResults = isAltQuery->executeQuery(); if (isAltQueryResults->next()) { - entry.IsAlt = true; - } else { - entry.IsAlt = false; + isAlt = true; } + delete isAltQueryResults; + isAltQueryResults = nullptr; + delete isAltQuery; isAltQuery = nullptr; - entry.DateLastPublished = dateUpdated; - // Reputation not updated client side for listing? - entry.Reputation = reputation; - entry.CloneId = cloneId; - entry.IsModeratorApproved = modApproved == true; - entry.AccessType = privacyOption; - // Client still reads performance cost as zero? - entry.PerformanceCost = 0; + + entry = SetPropertyValues(entry, cloneId, ownerName, propertyName, propertyDescription, reputation, isBestFriend, isFriend, isModeratorApproved, isAlt, isOwned, privacyOption, dateLastUpdated); entries.push_back(entry); - delete nameLookup; } + delete propertyEntry; + propertyEntry = nullptr; + delete propertyLookup; + propertyLookup = nullptr; propertyQueries[entity->GetObjectID()] = entries; From 69ec1216dc999564df7bbc027eb8186cf64b1dd8 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 20:51:19 -0700 Subject: [PATCH 092/251] added comments --- .../PropertySelectQueryProperty.h | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.h b/dGame/dGameMessages/PropertySelectQueryProperty.h index b136f5cd..f8042bbf 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.h +++ b/dGame/dGameMessages/PropertySelectQueryProperty.h @@ -9,17 +9,17 @@ public: void Deserialize(RakNet::BitStream& stream) const; - LWOCLONEID CloneId = LWOCLONEID_INVALID; - std::string OwnerName = ""; - std::string Name = ""; - std::string Description = ""; - uint32_t Reputation = 0; - bool IsBestFriend = false; - bool IsFriend = false; - bool IsModeratorApproved = false; - bool IsAlt = false; - bool IsOwned = false; - uint32_t AccessType = 0; - uint32_t DateLastPublished = 0; - uint64_t PerformanceCost = 0; + LWOCLONEID CloneId = LWOCLONEID_INVALID; // The cloneID of the property + std::string OwnerName = ""; // The property owners name + std::string Name = ""; // The property name + std::string Description = ""; // The property description + uint32_t Reputation = 0; // The reputation of the property + bool IsBestFriend = false; // Whether or not the property belongs to a best friend + bool IsFriend = false; // Whether or not the property belongs to a friend + bool IsModeratorApproved = false; // Whether or not a moderator has approved this property + bool IsAlt = false; // Whether or not the property is owned by an alt of the account owner + bool IsOwned = false; // Whether or not the property is owned + uint32_t AccessType = 0; // The privacy option of the property + uint32_t DateLastPublished = 0; // The last day the property was published + uint64_t PerformanceCost = 0; // The performance cost of the property }; From 35e576a8398e110f7de86d99d55ab0a524bceff8 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 20:53:09 -0700 Subject: [PATCH 093/251] fixed moderator issue --- dGame/dComponents/PropertyEntranceComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index fb13d622..80c31d4a 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -278,7 +278,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl ownerName = "[AWAITING APPROVAL]"; propertyName = "[AWAITING APPROVAL]"; propertyDescription = "[AWAITING APPROVAL]"; - entry.IsModeratorApproved = true; + isModeratorApproved = true; } bool isAlt = false; From b0d499334428e88871b5ace22442069ba8bb993c Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 28 Mar 2022 21:02:46 -0700 Subject: [PATCH 094/251] owner name change --- dGame/dComponents/PropertyEntranceComponent.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 80c31d4a..504f2dc3 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -275,7 +275,6 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl bool isModeratorApproved = propertyEntry->getBoolean(10); if (!isModeratorApproved && entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR) { - ownerName = "[AWAITING APPROVAL]"; propertyName = "[AWAITING APPROVAL]"; propertyDescription = "[AWAITING APPROVAL]"; isModeratorApproved = true; From 0c41026df020d3065bcb96d01a64f564fab78da0 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 01:00:30 -0700 Subject: [PATCH 095/251] Fixed friendless crash --- dGame/dComponents/PropertyEntranceComponent.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 504f2dc3..fbbdb896 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -117,8 +117,14 @@ std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMe friendsList = friendsList + std::to_string(playerIDToConvert) + ","; } // Replace trailing comma with the closing parenthesis. - friendsList.replace(friendsList.size() - 1, 2, ") "); - orderBy = friendsList + "ORDER BY ci.name ASC "; + if (friendsList.at(friendsList.size() - 1) == ',') friendsList.erase(friendsList.size() - 1, 1); + friendsList += ") "; + if (friendsList.find("()") == std::string::npos) { + orderBy = friendsList; + } else { + friendsList = " AND p.owner_id IN (-1) "; + } + orderBy += friendsList + "ORDER BY ci.name ASC "; delete friendsListQueryResult; friendsListQueryResult = nullptr; From 7b536ee079185ebf02b708ccf76c0340770e922e Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 01:57:23 -0700 Subject: [PATCH 096/251] Best friends is 2 not 1 --- dGame/dComponents/PropertyEntranceComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index fbbdb896..5ee832fd 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -267,7 +267,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl // If we got a result than the two players are friends. if (friendResult->next()) { isFriend = true; - if (friendResult->getBoolean(1) == true) { + if (friendResult->getInt(1) == 2) { isBestFriend = true; } } From 9385c337299731a87764473010e40468b2d52718 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 02:33:15 -0700 Subject: [PATCH 097/251] grammar and new line --- dGame/dComponents/PropertyEntranceComponent.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 5ee832fd..4065c3fc 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -119,6 +119,8 @@ std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMe // Replace trailing comma with the closing parenthesis. if (friendsList.at(friendsList.size() - 1) == ',') friendsList.erase(friendsList.size() - 1, 1); friendsList += ") "; + + // If we have no friends then use a -1 for the query. if (friendsList.find("()") == std::string::npos) { orderBy = friendsList; } else { @@ -128,6 +130,7 @@ std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMe delete friendsListQueryResult; friendsListQueryResult = nullptr; + delete friendsListQuery; friendsListQuery = nullptr; } From ec9749ab852f1a7f24e7c946c184be0cd83249a8 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 03:50:41 -0700 Subject: [PATCH 098/251] flag for are more being worked on --- .../dComponents/PropertyEntranceComponent.cpp | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 4065c3fc..b3b78754 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -321,5 +321,24 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl propertyQueries[entity->GetObjectID()] = entries; - GameMessages::SendPropertySelectQuery(m_Parent->GetObjectID(), startIndex, entries.size() >= numResults, character->GetPropertyCloneID(), false, true, entries, sysAddr); + auto propertiesLeft = Database::CreatePreppedStmt("SELECT COUNT(*) FROM properties WHERE zone_id = ?;"); + + propertiesLeft->setInt(1, this->m_MapID); + + auto result = propertiesLeft->executeQuery(); + result->next(); + auto numberOfProperties = result->getInt(1); + + delete result; + result = nullptr; + + delete propertiesLeft; + propertiesLeft = nullptr; + + auto forFriends = query; + forFriends.replace(7, 3, "COUNT(*)"); + // if sort method is friends or featured do above query. + // do same maths below with resulting query + // else use default count. + GameMessages::SendPropertySelectQuery(m_Parent->GetObjectID(), startIndex, numberOfProperties - (startIndex + numResults) > 0, character->GetPropertyCloneID(), false, true, entries, sysAddr); } \ No newline at end of file From 75fd425ef69965cbb4bcfa660ac1aa3493aac3d8 Mon Sep 17 00:00:00 2001 From: Avery Date: Tue, 29 Mar 2022 13:06:28 -0700 Subject: [PATCH 099/251] Remove ability for gmlevel 0 to use /playanim (#391) --- dGame/dUtilities/SlashCommandHandler.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dGame/dUtilities/SlashCommandHandler.cpp b/dGame/dUtilities/SlashCommandHandler.cpp index 67336eb7..901bccbf 100644 --- a/dGame/dUtilities/SlashCommandHandler.cpp +++ b/dGame/dUtilities/SlashCommandHandler.cpp @@ -363,11 +363,6 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit } if (user->GetMaxGMLevel() == 0 || entity->GetGMLevel() >= 0) { - if ((chatCommand == "playanimation" || chatCommand == "playanim") && args.size() == 1) { - std::u16string anim = GeneralUtils::ASCIIToUTF16(args[0], args[0].size()); - GameMessages::SendPlayAnimation(entity, anim); - } - if (chatCommand == "die") { entity->Smash(entity->GetObjectID()); } @@ -446,6 +441,11 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit GameMessages::SendToggleGMInvis(entity->GetObjectID(), false, UNASSIGNED_SYSTEM_ADDRESS); // need to retoggle because it gets reenabled on creation of new character } + + if ((chatCommand == "playanimation" || chatCommand == "playanim") && args.size() == 1 && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { + std::u16string anim = GeneralUtils::ASCIIToUTF16(args[0], args[0].size()); + GameMessages::SendPlayAnimation(entity, anim); + } if (chatCommand == "list-spawns" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { for (const auto& pair : EntityManager::Instance()->GetSpawnPointEntities()) { From 82ebdccdb2f0019dbfc6955125d21be0ccea4bec Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 14:54:31 -0700 Subject: [PATCH 100/251] Reputation is sent as a float not an int --- dGame/dComponents/PropertyEntranceComponent.cpp | 6 +++--- dGame/dComponents/PropertyEntranceComponent.h | 2 +- dGame/dGameMessages/PropertySelectQueryProperty.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index b3b78754..4296dee4 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -79,7 +79,7 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, } PropertySelectQueryProperty PropertyEntranceComponent::SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId, std::string ownerName, std::string propertyName, std::string propertyDescription, - uint32_t reputation, bool isBFF, bool isFriend, bool isModeratorApproved, bool isAlt, bool isOwned, uint32_t privacyOption, uint32_t timeLastUpdated, uint64_t performanceCost) { + float reputation, bool isBFF, bool isFriend, bool isModeratorApproved, bool isAlt, bool isOwned, uint32_t privacyOption, uint32_t timeLastUpdated, uint64_t performanceCost) { property.CloneId = cloneId; property.OwnerName = ownerName; property.Name = propertyName; @@ -170,7 +170,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl const auto privacyOption = playerPropertyLookupResults->getInt(9); const auto modApproved = playerPropertyLookupResults->getBoolean(10); const auto dateLastUpdated = playerPropertyLookupResults->getInt64(11); - const auto reputation = playerPropertyLookupResults->getInt(14); + const auto reputation = playerPropertyLookupResults->getUInt(14); playerEntry = SetPropertyValues(playerEntry, cloneId, character->GetName(), name, description, reputation, true, true, modApproved, true, true, privacyOption, dateLastUpdated); } else { @@ -213,7 +213,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl const auto privacyOption = propertyEntry->getInt(9); const auto modApproved = propertyEntry->getBoolean(10); const auto dateLastUpdated = propertyEntry->getInt(11); - const auto reputation = propertyEntry->getUInt(14); + const float reputation = propertyEntry->getInt(14); PropertySelectQueryProperty entry {}; diff --git a/dGame/dComponents/PropertyEntranceComponent.h b/dGame/dComponents/PropertyEntranceComponent.h index 1cfb98dc..4ba7a74f 100644 --- a/dGame/dComponents/PropertyEntranceComponent.h +++ b/dGame/dComponents/PropertyEntranceComponent.h @@ -59,7 +59,7 @@ class PropertyEntranceComponent : public Component { [[nodiscard]] LWOMAPID GetMapID() const { return m_MapID; }; PropertySelectQueryProperty SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId = LWOCLONEID_INVALID, std::string ownerName = "", std::string propertyName = "", std::string propertyDescription = "", - uint32_t reputation = 0, bool isBFF = false, bool isFriend = false, bool isModeratorApproved = false, bool isAlt = false, bool isOwned = false, uint32_t privacyOption = 0, uint32_t timeLastUpdated = 0, uint64_t performanceCost = 0); + float reputation = 0, bool isBFF = false, bool isFriend = false, bool isModeratorApproved = false, bool isAlt = false, bool isOwned = false, uint32_t privacyOption = 0, uint32_t timeLastUpdated = 0, uint64_t performanceCost = 0); std::string BuildQuery(Entity* entity, int32_t sortMethod); diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.h b/dGame/dGameMessages/PropertySelectQueryProperty.h index f8042bbf..f451ae31 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.h +++ b/dGame/dGameMessages/PropertySelectQueryProperty.h @@ -13,7 +13,7 @@ public: std::string OwnerName = ""; // The property owners name std::string Name = ""; // The property name std::string Description = ""; // The property description - uint32_t Reputation = 0; // The reputation of the property + float Reputation = 0; // The reputation of the property bool IsBestFriend = false; // Whether or not the property belongs to a best friend bool IsFriend = false; // Whether or not the property belongs to a friend bool IsModeratorApproved = false; // Whether or not a moderator has approved this property From e79d4e66f385f84ff02accc28f6f1a5927ceae31 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 19:46:38 -0700 Subject: [PATCH 101/251] add performance cost column --- migrations/dlu/3_add_performance_cost.sql | 1 + 1 file changed, 1 insertion(+) create mode 100644 migrations/dlu/3_add_performance_cost.sql diff --git a/migrations/dlu/3_add_performance_cost.sql b/migrations/dlu/3_add_performance_cost.sql new file mode 100644 index 00000000..8d9bc6e9 --- /dev/null +++ b/migrations/dlu/3_add_performance_cost.sql @@ -0,0 +1 @@ +ALTER TABLE properties ADD COLUMN performance_cost DOUBLE(20, 15); \ No newline at end of file From af15cc60ebfa74529ca543bc839038f29901fff9 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 19:46:47 -0700 Subject: [PATCH 102/251] Add GM for performance cost --- dNet/dMessageIdentifiers.h | 1 + 1 file changed, 1 insertion(+) diff --git a/dNet/dMessageIdentifiers.h b/dNet/dMessageIdentifiers.h index 36e85df2..d2080248 100644 --- a/dNet/dMessageIdentifiers.h +++ b/dNet/dMessageIdentifiers.h @@ -527,6 +527,7 @@ enum GAME_MSG : unsigned short { GAME_MSG_VEHICLE_NOTIFY_HIT_IMAGINATION_SERVER = 1606, GAME_MSG_ADD_RUN_SPEED_MODIFIER = 1505, GAME_MSG_REMOVE_RUN_SPEED_MODIFIER = 1506, + GAME_MSG_UPDATE_PROPERTY_PERFORMANCE_COST = 1547, GAME_MSG_PROPERTY_ENTRANCE_BEGIN = 1553, GAME_MSG_REQUEST_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1666, GAME_MSG_RESPONSE_MOVE_ITEM_BETWEEN_INVENTORY_TYPES = 1667, From 9f162845953451272f71126dcd659b50b0cc1c52 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 19:47:15 -0700 Subject: [PATCH 103/251] tab spacing --- .../PropertySelectQueryProperty.cpp | 19 ++++++++++--------- .../PropertySelectQueryProperty.h | 3 ++- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.cpp b/dGame/dGameMessages/PropertySelectQueryProperty.cpp index 78b7198d..6a66554d 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.cpp +++ b/dGame/dGameMessages/PropertySelectQueryProperty.cpp @@ -23,15 +23,16 @@ void PropertySelectQueryProperty::Serialize(RakNet::BitStream& stream) const stream.Write(static_cast(description[i])); } - stream.Write(Reputation); - stream.Write(IsBestFriend); - stream.Write(IsFriend); - stream.Write(IsModeratorApproved); - stream.Write(IsAlt); - stream.Write(IsOwned); - stream.Write(AccessType); - stream.Write(DateLastPublished); - stream.Write(PerformanceCost); + stream.Write(Reputation); + stream.Write(IsBestFriend); + stream.Write(IsFriend); + stream.Write(IsModeratorApproved); + stream.Write(IsAlt); + stream.Write(IsOwned); + stream.Write(AccessType); + stream.Write(DateLastPublished); + stream.Write(PerformanceIndex); + stream.Write(PerformanceCost); } void PropertySelectQueryProperty::Deserialize(RakNet::BitStream& stream) const diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.h b/dGame/dGameMessages/PropertySelectQueryProperty.h index f451ae31..61fa7b86 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.h +++ b/dGame/dGameMessages/PropertySelectQueryProperty.h @@ -21,5 +21,6 @@ public: bool IsOwned = false; // Whether or not the property is owned uint32_t AccessType = 0; // The privacy option of the property uint32_t DateLastPublished = 0; // The last day the property was published - uint64_t PerformanceCost = 0; // The performance cost of the property + float PerformanceCost = 0; // The performance cost of the property + uint32_t PerformanceIndex = 0; // The performance index of the property? Always 0? }; From 1783904cb63ce791030d38d3f7e90fe97864268c Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 19:47:27 -0700 Subject: [PATCH 104/251] fixed __int64 in missions table --- dDatabase/Tables/CDMissionsTable.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/dDatabase/Tables/CDMissionsTable.h b/dDatabase/Tables/CDMissionsTable.h index c083bd31..c961bb80 100644 --- a/dDatabase/Tables/CDMissionsTable.h +++ b/dDatabase/Tables/CDMissionsTable.h @@ -3,6 +3,7 @@ // Custom Classes #include "CDTable.h" #include +#include /*! \file CDMissionsTable.hpp @@ -17,9 +18,9 @@ struct CDMissions { int UISortOrder; //!< The UI Sort Order for the mission int offer_objectID; //!< The LOT of the mission giver int target_objectID; //!< The LOT of the mission's target - __int64 reward_currency; //!< The amount of currency to reward the player + int64_t reward_currency; //!< The amount of currency to reward the player int LegoScore; //!< The amount of LEGO Score to reward the player - __int64 reward_reputation; //!< The reputation to award the player + int64_t reward_reputation; //!< The reputation to award the player bool isChoiceReward; //!< Whether or not the user has the option to choose their loot int reward_item1; //!< The first rewarded item int reward_item1_count; //!< The count of the first item to be rewarded @@ -40,7 +41,7 @@ struct CDMissions { int reward_maxwidget; //!< ??? int reward_maxwallet; //!< ??? bool repeatable; //!< Whether or not this mission can be repeated (for instance, is it a daily mission) - __int64 reward_currency_repeatable; //!< The repeatable reward + int64_t reward_currency_repeatable; //!< The repeatable reward int reward_item1_repeatable; //!< The first rewarded item int reward_item1_repeat_count; //!< The count of the first item to be rewarded int reward_item2_repeatable; //!< The second rewarded item @@ -55,7 +56,7 @@ struct CDMissions { std::string prereqMissionID; //!< A '|' seperated list of prerequisite missions bool localize; //!< Whether or not to localize the mission bool inMOTD; //!< In Match of the Day(?) - __int64 cooldownTime; //!< The mission cooldown time + int64_t cooldownTime; //!< The mission cooldown time bool isRandom; //!< ??? std::string randomPool; //!< ??? int UIPrereqID; //!< ??? From 06671b8d66ceeea4957ef5758ed8e049e103d855 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 19:48:34 -0700 Subject: [PATCH 105/251] performance cost is a float --- dGame/dComponents/PropertyEntranceComponent.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 4296dee4..3e3c3cc1 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -79,12 +79,11 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, } PropertySelectQueryProperty PropertyEntranceComponent::SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId, std::string ownerName, std::string propertyName, std::string propertyDescription, - float reputation, bool isBFF, bool isFriend, bool isModeratorApproved, bool isAlt, bool isOwned, uint32_t privacyOption, uint32_t timeLastUpdated, uint64_t performanceCost) { + float reputation, bool isBFF, bool isFriend, bool isModeratorApproved, bool isAlt, bool isOwned, uint32_t privacyOption, uint32_t timeLastUpdated, float performanceCost) { property.CloneId = cloneId; property.OwnerName = ownerName; property.Name = propertyName; property.Description = propertyDescription; - // Reputation not updated for client side listing? property.Reputation = reputation; property.IsBestFriend = isBFF; property.IsFriend = isFriend; @@ -171,8 +170,9 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl const auto modApproved = playerPropertyLookupResults->getBoolean(10); const auto dateLastUpdated = playerPropertyLookupResults->getInt64(11); const auto reputation = playerPropertyLookupResults->getUInt(14); + const auto performanceCost = (float)playerPropertyLookupResults->getDouble(16); - playerEntry = SetPropertyValues(playerEntry, cloneId, character->GetName(), name, description, reputation, true, true, modApproved, true, true, privacyOption, dateLastUpdated); + playerEntry = SetPropertyValues(playerEntry, cloneId, character->GetName(), name, description, reputation, true, true, modApproved, true, true, privacyOption, dateLastUpdated, performanceCost); } else { playerEntry = SetPropertyValues(playerEntry, character->GetPropertyCloneID(), character->GetName(), "", "", 0, true, true); } @@ -214,6 +214,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl const auto modApproved = propertyEntry->getBoolean(10); const auto dateLastUpdated = propertyEntry->getInt(11); const float reputation = propertyEntry->getInt(14); + const auto performanceCost = (float)propertyEntry->getDouble(16); PropertySelectQueryProperty entry {}; @@ -308,7 +309,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl delete isAltQuery; isAltQuery = nullptr; - entry = SetPropertyValues(entry, cloneId, ownerName, propertyName, propertyDescription, reputation, isBestFriend, isFriend, isModeratorApproved, isAlt, isOwned, privacyOption, dateLastUpdated); + entry = SetPropertyValues(entry, cloneId, ownerName, propertyName, propertyDescription, reputation, isBestFriend, isFriend, isModeratorApproved, isAlt, isOwned, privacyOption, dateLastUpdated, performanceCost); entries.push_back(entry); } From 94e0ef77a963d4075112f2de12a9a38449191adc Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 19:49:54 -0700 Subject: [PATCH 106/251] performance cost is still a float --- dGame/dComponents/PropertyEntranceComponent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.h b/dGame/dComponents/PropertyEntranceComponent.h index 4ba7a74f..fdb9240d 100644 --- a/dGame/dComponents/PropertyEntranceComponent.h +++ b/dGame/dComponents/PropertyEntranceComponent.h @@ -59,7 +59,7 @@ class PropertyEntranceComponent : public Component { [[nodiscard]] LWOMAPID GetMapID() const { return m_MapID; }; PropertySelectQueryProperty SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId = LWOCLONEID_INVALID, std::string ownerName = "", std::string propertyName = "", std::string propertyDescription = "", - float reputation = 0, bool isBFF = false, bool isFriend = false, bool isModeratorApproved = false, bool isAlt = false, bool isOwned = false, uint32_t privacyOption = 0, uint32_t timeLastUpdated = 0, uint64_t performanceCost = 0); + float reputation = 0, bool isBFF = false, bool isFriend = false, bool isModeratorApproved = false, bool isAlt = false, bool isOwned = false, uint32_t privacyOption = 0, uint32_t timeLastUpdated = 0, float performanceCost = 0.0f); std::string BuildQuery(Entity* entity, int32_t sortMethod); From fdd3e15b2f51e4ebfaf28c7201f0e12686c830f7 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 19:52:07 -0700 Subject: [PATCH 107/251] Added GM for reputation update --- dGame/dGameMessages/GameMessageHandler.cpp | 4 +++- dGame/dGameMessages/GameMessages.cpp | 25 ++++++++++++++++++++++ dGame/dGameMessages/GameMessages.h | 2 ++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/dGame/dGameMessages/GameMessageHandler.cpp b/dGame/dGameMessages/GameMessageHandler.cpp index 83187e2f..45760cc9 100644 --- a/dGame/dGameMessages/GameMessageHandler.cpp +++ b/dGame/dGameMessages/GameMessageHandler.cpp @@ -595,7 +595,9 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System case GAME_MSG_VEHICLE_NOTIFY_HIT_IMAGINATION_SERVER: GameMessages::HandleVehicleNotifyHitImaginationServer(inStream, entity, sysAddr); break; - + case GAME_MSG_UPDATE_PROPERTY_PERFORMANCE_COST: + GameMessages::HandleUpdatePropertyPerformanceCost(inStream, entity, sysAddr); + break; // SG case GAME_MSG_UPDATE_SHOOTING_GALLERY_ROTATION: GameMessages::HandleUpdateShootingGalleryRotation(inStream, entity, sysAddr); diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 53699f4e..6d70e105 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -4137,6 +4137,31 @@ void GameMessages::HandleRacingPlayerInfoResetFinished(RakNet::BitStream* inStre } } +void GameMessages::HandleUpdatePropertyPerformanceCost(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { + float performanceCost = 0.0f; + + if (inStream->ReadBit()) inStream->Read(performanceCost); + + Game::logger->Log("GameMessages", "new value is %f\n", performanceCost); + + if (performanceCost == 0.0f) return; + + auto zone = dZoneManager::Instance()->GetZone(); + const auto& worldId = zone->GetZoneID(); + const auto cloneId = worldId.GetCloneID(); + const auto zoneId = worldId.GetMapID(); + + auto updatePerformanceCostQuery = Database::CreatePreppedStmt("UPDATE properties SET performance_cost = ? WHERE clone_id = ? AND zone_id = ?"); + + updatePerformanceCostQuery->setDouble(1, performanceCost); + updatePerformanceCostQuery->setInt(2, cloneId); + updatePerformanceCostQuery->setInt(3, zoneId); + + updatePerformanceCostQuery->execute(); + + delete updatePerformanceCostQuery; + updatePerformanceCostQuery = nullptr; +} void GameMessages::HandleVehicleNotifyHitImaginationServer(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { diff --git a/dGame/dGameMessages/GameMessages.h b/dGame/dGameMessages/GameMessages.h index 671c3b3a..b2d9a6c9 100644 --- a/dGame/dGameMessages/GameMessages.h +++ b/dGame/dGameMessages/GameMessages.h @@ -386,6 +386,8 @@ namespace GameMessages { bool bUseLeaderboards ); + void HandleUpdatePropertyPerformanceCost(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr); + void SendNotifyClientShootingGalleryScore(LWOOBJID objectId, const SystemAddress& sysAddr, float addTime, int32_t score, From 258174d4e1290b1beda049fa39832828ebe78a2a Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 23:46:23 -0700 Subject: [PATCH 108/251] Added GameMessage for UpdateReputation --- dGame/dGameMessages/GameMessages.cpp | 14 ++++++++++++-- dGame/dGameMessages/GameMessages.h | 2 ++ dNet/dMessageIdentifiers.h | 1 + 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 6d70e105..e8973283 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -4137,13 +4137,23 @@ void GameMessages::HandleRacingPlayerInfoResetFinished(RakNet::BitStream* inStre } } +void GameMessages::SendUpdateReputation(const LWOOBJID objectId, const int64_t reputation, const SystemAddress& sysAddr) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write(objectId); + bitStream.Write(GAME_MSG::GAME_MSG_UPDATE_REPUTATION); + + bitStream.Write(reputation); + + SEND_PACKET; +} + void GameMessages::HandleUpdatePropertyPerformanceCost(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { float performanceCost = 0.0f; if (inStream->ReadBit()) inStream->Read(performanceCost); - Game::logger->Log("GameMessages", "new value is %f\n", performanceCost); - if (performanceCost == 0.0f) return; auto zone = dZoneManager::Instance()->GetZone(); diff --git a/dGame/dGameMessages/GameMessages.h b/dGame/dGameMessages/GameMessages.h index b2d9a6c9..ababed5f 100644 --- a/dGame/dGameMessages/GameMessages.h +++ b/dGame/dGameMessages/GameMessages.h @@ -397,6 +397,8 @@ namespace GameMessages { void HandleUpdateShootingGalleryRotation(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr); + void SendUpdateReputation(const LWOOBJID objectId, const int64_t reputation, const SystemAddress& sysAddr); + // Leaderboards void SendActivitySummaryLeaderboardData(const LWOOBJID& objectID, const Leaderboard* leaderboard, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS); diff --git a/dNet/dMessageIdentifiers.h b/dNet/dMessageIdentifiers.h index d2080248..eae3f88a 100644 --- a/dNet/dMessageIdentifiers.h +++ b/dNet/dMessageIdentifiers.h @@ -382,6 +382,7 @@ enum GAME_MSG : unsigned short { GAME_MSG_PROPERTY_EDITOR_END = 725, GAME_MSG_START_PATHING = 735, GAME_MSG_NOTIFY_CLIENT_ZONE_OBJECT = 737, + GAME_MSG_UPDATE_REPUTATION = 746, GAME_MSG_PROPERTY_RENTAL_RESPONSE = 750, GAME_MSG_REQUEST_PLATFORM_RESYNC = 760, GAME_MSG_PLATFORM_RESYNC = 761, From 36edbf393b4e68a3db969e73cd2e224726929993 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 23:46:56 -0700 Subject: [PATCH 109/251] Added support to update reputation --- dGame/dMission/Mission.cpp | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/dGame/dMission/Mission.cpp b/dGame/dMission/Mission.cpp index f841f2f1..c0fe60c0 100644 --- a/dGame/dMission/Mission.cpp +++ b/dGame/dMission/Mission.cpp @@ -16,6 +16,7 @@ #include "dLogger.h" #include "dServer.h" #include "dZoneManager.h" +#include "Database.h" Mission::Mission(MissionComponent* missionComponent, const uint32_t missionId) { m_MissionComponent = missionComponent; @@ -516,8 +517,41 @@ void Mission::YieldRewards() { } if (info->reward_reputation > 0) { - // TODO: Track reputation in the property table and in charxml missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_EARN_REPUTATION, 0, 0L, "", info->reward_reputation); + auto character = entity->GetCharacter(); + if (!character) return; + + auto charId = character->GetID(); + auto propertyCloneId = character->GetPropertyCloneID(); + + auto properties = Database::CreatePreppedStmt("SELECT reputation FROM properties WHERE owner_id = ? AND clone_id = ?"); + + properties->setInt(1, charId); + properties->setInt64(2, propertyCloneId); + + auto results = properties->executeQuery(); + + while (results->next()) { + const auto oldReputation = results->getInt(1); + + auto reputationUpdate = Database::CreatePreppedStmt("UPDATE properties SET reputation = ? where owner_id = ? AND clone_id = ?"); + + reputationUpdate->setInt64(1, oldReputation + info->reward_reputation); + reputationUpdate->setInt(2, charId); + reputationUpdate->setInt64(3, propertyCloneId); + + reputationUpdate->execute(); + + delete reputationUpdate; + reputationUpdate = nullptr; + } + delete results; + results = nullptr; + + delete properties; + properties = nullptr; + + GameMessages::SendUpdateReputation(entity->GetObjectID(), info->reward_reputation, entity->GetSystemAddress()); } if (info->reward_maxhealth > 0) { From e244fbccc2ac2ffe8ad077bab02bf369bb9d9ed6 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 23:49:04 -0700 Subject: [PATCH 110/251] General updates to the property manager clone id is correctly assigned, reputation now shows up, rejection verdict is sent correctly (not sure about where the reason goes if it even goes here). --- .../PropertyManagementComponent.cpp | 13 ++++++++-- .../dComponents/PropertyManagementComponent.h | 25 +++++++++++++++++++ dGame/dGameMessages/PropertyDataMessage.cpp | 18 +++++++++---- dGame/dGameMessages/PropertyDataMessage.h | 5 ++++ 4 files changed, 54 insertions(+), 7 deletions(-) diff --git a/dGame/dComponents/PropertyManagementComponent.cpp b/dGame/dComponents/PropertyManagementComponent.cpp index cd99fd78..a433aa56 100644 --- a/dGame/dComponents/PropertyManagementComponent.cpp +++ b/dGame/dComponents/PropertyManagementComponent.cpp @@ -68,10 +68,15 @@ PropertyManagementComponent::PropertyManagementComponent(Entity* parent) : Compo this->owner = propertyEntry->getUInt64(2); this->owner = GeneralUtils::SetBit(this->owner, OBJECT_BIT_CHARACTER); this->owner = GeneralUtils::SetBit(this->owner, OBJECT_BIT_PERSISTENT); + this->clone_Id = propertyEntry->getInt(2); this->propertyName = propertyEntry->getString(5).c_str(); this->propertyDescription = propertyEntry->getString(6).c_str(); this->privacyOption = static_cast(propertyEntry->getUInt(9)); + this->moderatorRequested = propertyEntry->getInt(10) == 0 && rejectionReason == "" && privacyOption == PropertyPrivacyOption::Public; + this->LastUpdatedTime = propertyEntry->getUInt64(11); this->claimedTime = propertyEntry->getUInt64(12); + this->rejectionReason = propertyEntry->getString(13); + this->reputation = propertyEntry->getUInt(14); Load(); } @@ -822,17 +827,21 @@ void PropertyManagementComponent::OnQueryPropertyData(Entity* originator, const claimed = claimedTime; privacy = static_cast(this->privacyOption); } - + message.moderatorRequested = moderatorRequested; + message.reputation = reputation; + message.LastUpdatedTime = LastUpdatedTime; message.OwnerId = ownerId; message.OwnerName = ownerName; message.Name = name; message.Description = description; message.ClaimedTime = claimed; message.PrivacyOption = privacy; - + message.cloneId = clone_Id; + message.rejectionReason = rejectionReason; message.Paths = GetPaths(); SendDownloadPropertyData(author, message, UNASSIGNED_SYSTEM_ADDRESS); + // send rejction here? } void PropertyManagementComponent::OnUse(Entity* originator) diff --git a/dGame/dComponents/PropertyManagementComponent.h b/dGame/dComponents/PropertyManagementComponent.h index bf577760..6aee8ed3 100644 --- a/dGame/dComponents/PropertyManagementComponent.h +++ b/dGame/dComponents/PropertyManagementComponent.h @@ -194,11 +194,36 @@ private: */ std::string propertyName = ""; + /** + * The clone ID of this property + */ + LWOCLONEID clone_Id = 0; + + /** + * Whether a moderator was requested + */ + bool moderatorRequested = false; + + /** + * The rejection reason for the property + */ + std::string rejectionReason = ""; + /** * The description of this property */ std::string propertyDescription = ""; + /** + * The reputation of this property + */ + uint32_t reputation = 0; + + /** + * The last time this property was updated + */ + uint32_t LastUpdatedTime = 0; + /** * Determines which players may visit this property */ diff --git a/dGame/dGameMessages/PropertyDataMessage.cpp b/dGame/dGameMessages/PropertyDataMessage.cpp index 9c3b6d3f..cbe3e67b 100644 --- a/dGame/dGameMessages/PropertyDataMessage.cpp +++ b/dGame/dGameMessages/PropertyDataMessage.cpp @@ -13,7 +13,7 @@ void GameMessages::PropertyDataMessage::Serialize(RakNet::BitStream& stream) con stream.Write(TemplateID); // - template id stream.Write(ZoneId); // - map id stream.Write(VendorMapId); // - vendor map id - stream.Write(1); + stream.Write(cloneId); // clone id const auto& name = GeneralUtils::ASCIIToUTF16(Name); stream.Write(uint32_t(name.size())); @@ -40,11 +40,12 @@ void GameMessages::PropertyDataMessage::Serialize(RakNet::BitStream& stream) con stream.Write(0); // - minimum price stream.Write(1); // - rent duration - stream.Write(ClaimedTime); // - timestamp + stream.Write(LastUpdatedTime); // - timestamp stream.Write(1); - stream.Write(0); + stream.Write(reputation); // Reputation + stream.Write(0); const auto& spawn = GeneralUtils::ASCIIToUTF16(SpawnName); stream.Write(uint32_t(spawn.size())); @@ -63,9 +64,16 @@ void GameMessages::PropertyDataMessage::Serialize(RakNet::BitStream& stream) con stream.Write(0); - stream.Write(1); + if (rejectionReason != "") stream.Write(2); + else if (moderatorRequested == true && rejectionReason == "") stream.Write(0); + else stream.Write(1); - stream.Write(0); // String length + const auto& rejectionReasonConverted = GeneralUtils::ASCIIToUTF16(rejectionReason); + stream.Write(uint32_t(rejectionReasonConverted.size())); + for (uint32_t i = 0; i < rejectionReasonConverted.size(); ++i) { + stream.Write(uint16_t(rejectionReasonConverted[i])); + std::cout << rejectionReason[i] << std::endl; + } stream.Write(0); diff --git a/dGame/dGameMessages/PropertyDataMessage.h b/dGame/dGameMessages/PropertyDataMessage.h index 219ac08d..a85702c4 100644 --- a/dGame/dGameMessages/PropertyDataMessage.h +++ b/dGame/dGameMessages/PropertyDataMessage.h @@ -28,8 +28,13 @@ namespace GameMessages std::string Name = ""; std::string Description = ""; + std::string rejectionReason = ""; + bool moderatorRequested = 0; + LWOCLONEID cloneId = 0; + uint32_t reputation = 0; uint64_t ClaimedTime = 0; + uint64_t LastUpdatedTime = 0; NiPoint3 ZonePosition = { 548.0f, 406.0f, 178.0f }; char PrivacyOption = 0; From c838f4f422a84350e5ac2e4523623528d7dc612d Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 29 Mar 2022 23:59:50 -0700 Subject: [PATCH 111/251] Added query for friends list next page --- .../dComponents/PropertyEntranceComponent.cpp | 47 ++++++++++++++----- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 3e3c3cc1..72ee2a70 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -322,22 +322,47 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl propertyQueries[entity->GetObjectID()] = entries; - auto propertiesLeft = Database::CreatePreppedStmt("SELECT COUNT(*) FROM properties WHERE zone_id = ?;"); + uint32_t numberOfProperties = 0; + if (sortMethod != SORT_TYPE_FRIENDS || sortMethod != SORT_TYPE_FEATURED) { + auto propertiesLeft = Database::CreatePreppedStmt("SELECT COUNT(*) FROM properties WHERE zone_id = ?;"); - propertiesLeft->setInt(1, this->m_MapID); + propertiesLeft->setInt(1, this->m_MapID); - auto result = propertiesLeft->executeQuery(); - result->next(); - auto numberOfProperties = result->getInt(1); + auto result = propertiesLeft->executeQuery(); + result->next(); + numberOfProperties = result->getInt(1); - delete result; - result = nullptr; + delete result; + result = nullptr; - delete propertiesLeft; - propertiesLeft = nullptr; + delete propertiesLeft; + propertiesLeft = nullptr; + } else { + auto forFriends = query; + forFriends.replace(7, 3, "COUNT(*)"); - auto forFriends = query; - forFriends.replace(7, 3, "COUNT(*)"); + auto friendsQuery = Database::CreatePreppedStmt(query); + + propertyLookup->setUInt(1, this->m_MapID); + propertyLookup->setString(2, searchString.c_str()); + propertyLookup->setString(3, searchString.c_str()); + propertyLookup->setString(4, searchString.c_str()); + propertyLookup->setInt(5, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR || sortMethod == SORT_TYPE_FRIENDS ? 0 : 1); + propertyLookup->setInt(6, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? 1 : 2); + propertyLookup->setInt(7, numResults); + propertyLookup->setInt(8, startIndex); + + auto result = friendsQuery->executeQuery(); + result->next(); + numberOfProperties = result->getInt(1); + + delete friendsQuery; + friendsQuery = nullptr; + + delete result; + result = nullptr; + } + // if sort method is friends or featured do above query. // do same maths below with resulting query // else use default count. From b676343b0215a51973a9582984739b93aad4f383 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 00:02:18 -0700 Subject: [PATCH 112/251] removed print and rejection send --- dGame/dGameMessages/PropertyDataMessage.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/dGame/dGameMessages/PropertyDataMessage.cpp b/dGame/dGameMessages/PropertyDataMessage.cpp index cbe3e67b..9a261a65 100644 --- a/dGame/dGameMessages/PropertyDataMessage.cpp +++ b/dGame/dGameMessages/PropertyDataMessage.cpp @@ -68,12 +68,13 @@ void GameMessages::PropertyDataMessage::Serialize(RakNet::BitStream& stream) con else if (moderatorRequested == true && rejectionReason == "") stream.Write(0); else stream.Write(1); - const auto& rejectionReasonConverted = GeneralUtils::ASCIIToUTF16(rejectionReason); - stream.Write(uint32_t(rejectionReasonConverted.size())); - for (uint32_t i = 0; i < rejectionReasonConverted.size(); ++i) { - stream.Write(uint16_t(rejectionReasonConverted[i])); - std::cout << rejectionReason[i] << std::endl; - } + // Does this go here??? + // const auto& rejectionReasonConverted = GeneralUtils::ASCIIToUTF16(rejectionReason); + // stream.Write(uint32_t(rejectionReasonConverted.size())); + // for (uint32_t i = 0; i < rejectionReasonConverted.size(); ++i) { + // stream.Write(uint16_t(rejectionReasonConverted[i])); + // } + stream.Write(0); stream.Write(0); From 17e9fb0d3c0c5cce9ecf7208428bb5d94ffc7e8a Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 00:20:04 -0700 Subject: [PATCH 113/251] Default time is now the current time rather than 0 --- dGame/dComponents/PropertyManagementComponent.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dGame/dComponents/PropertyManagementComponent.h b/dGame/dComponents/PropertyManagementComponent.h index 6aee8ed3..2184eed3 100644 --- a/dGame/dComponents/PropertyManagementComponent.h +++ b/dGame/dComponents/PropertyManagementComponent.h @@ -1,5 +1,6 @@ #pragma once +#include #include "Entity.h" #include "Component.h" @@ -182,7 +183,7 @@ private: /** * The time since this property was claimed */ - uint64_t claimedTime = 0; + uint64_t claimedTime = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); /** * The models that are placed on this property @@ -222,7 +223,7 @@ private: /** * The last time this property was updated */ - uint32_t LastUpdatedTime = 0; + uint32_t LastUpdatedTime = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); /** * Determines which players may visit this property From 69cc265fea45ec20186b0bf39cf7102651c696ab Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 00:20:15 -0700 Subject: [PATCH 114/251] added performance cost initializer --- dGame/dComponents/PropertyManagementComponent.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dGame/dComponents/PropertyManagementComponent.cpp b/dGame/dComponents/PropertyManagementComponent.cpp index a433aa56..f2f6e0eb 100644 --- a/dGame/dComponents/PropertyManagementComponent.cpp +++ b/dGame/dComponents/PropertyManagementComponent.cpp @@ -79,7 +79,7 @@ PropertyManagementComponent::PropertyManagementComponent(Entity* parent) : Compo this->reputation = propertyEntry->getUInt(14); Load(); - } + } delete propertyLookup; } @@ -209,8 +209,8 @@ void PropertyManagementComponent::Claim(const LWOOBJID playerId) auto* insertion = Database::CreatePreppedStmt( "INSERT INTO properties" - "(id, owner_id, template_id, clone_id, name, description, rent_amount, rent_due, privacy_option, last_updated, time_claimed, rejection_reason, reputation, zone_id)" - "VALUES (?, ?, ?, ?, ?, '', 0, 0, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), '', 0, ?)" + "(id, owner_id, template_id, clone_id, name, description, rent_amount, rent_due, privacy_option, last_updated, time_claimed, rejection_reason, reputation, zone_id, performance_cost)" + "VALUES (?, ?, ?, ?, ?, '', 0, 0, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), '', 0, ?, 0.0)" ); insertion->setUInt64(1, propertyId); insertion->setUInt64(2, (uint32_t) playerId); From fe334d87391f6c2cafbb8ad2cd854a6d30e1434e Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 00:20:26 -0700 Subject: [PATCH 115/251] clarified magic nums --- dGame/dComponents/PropertyEntranceComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 72ee2a70..bf63028b 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -195,7 +195,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl propertyLookup->setString(3, searchString.c_str()); propertyLookup->setString(4, searchString.c_str()); propertyLookup->setInt(5, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR || sortMethod == SORT_TYPE_FRIENDS ? 0 : 1); - propertyLookup->setInt(6, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? 1 : 2); + propertyLookup->setInt(6, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? (uint32_t)PropertyPrivacyOption::Friends : (uint32_t)PropertyPrivacyOption::Public); propertyLookup->setInt(7, numResults); propertyLookup->setInt(8, startIndex); From bd6bdddcdeb188f8e471a2cce2b717bcc2c3686b Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 00:33:31 -0700 Subject: [PATCH 116/251] clone ID now based on character data --- dGame/dComponents/PropertyManagementComponent.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dGame/dComponents/PropertyManagementComponent.cpp b/dGame/dComponents/PropertyManagementComponent.cpp index f2f6e0eb..a5e33667 100644 --- a/dGame/dComponents/PropertyManagementComponent.cpp +++ b/dGame/dComponents/PropertyManagementComponent.cpp @@ -199,12 +199,16 @@ void PropertyManagementComponent::Claim(const LWOOBJID playerId) const auto& worldId = zone->GetZoneID(); const auto zoneId = worldId.GetMapID(); - const auto cloneId = worldId.GetCloneID(); auto* entity = EntityManager::Instance()->GetEntity(playerId); auto* user = entity->GetParentUser(); + auto character = entity->GetCharacter(); + if (!character) return; + + const auto cloneId = character->GetPropertyCloneID(); + propertyId = ObjectIDManager::GenerateRandomObjectID(); auto* insertion = Database::CreatePreppedStmt( From 5c16dd11f4bdefa6d80f88fbe71540186f022462 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 00:37:36 -0700 Subject: [PATCH 117/251] altered table now has a default for performance cost --- migrations/dlu/3_add_performance_cost.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrations/dlu/3_add_performance_cost.sql b/migrations/dlu/3_add_performance_cost.sql index 8d9bc6e9..15da4470 100644 --- a/migrations/dlu/3_add_performance_cost.sql +++ b/migrations/dlu/3_add_performance_cost.sql @@ -1 +1 @@ -ALTER TABLE properties ADD COLUMN performance_cost DOUBLE(20, 15); \ No newline at end of file +ALTER TABLE properties ADD COLUMN performance_cost DOUBLE(20, 15) DEFAULT 0.0; \ No newline at end of file From 4edb4289544a6d5abda994a0adccf608ea1b92b1 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 16:12:42 -0700 Subject: [PATCH 118/251] next page query now works --- .../dComponents/PropertyEntranceComponent.cpp | 74 +++++++------------ 1 file changed, 27 insertions(+), 47 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index bf63028b..cfe39bed 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -97,8 +97,13 @@ PropertySelectQueryProperty PropertyEntranceComponent::SetPropertyValues(Propert return property; } -std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMethod) { - auto base = baseQueryForProperties; +std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMethod, std::string customQuery, bool wantLimits) { + std::string base; + if (customQuery == "") { + base = baseQueryForProperties; + } else { + base = customQuery; + } std::string orderBy = ""; std::string friendsList = " AND p.owner_id IN ("; if (sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS) { @@ -120,11 +125,8 @@ std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMe friendsList += ") "; // If we have no friends then use a -1 for the query. - if (friendsList.find("()") == std::string::npos) { - orderBy = friendsList; - } else { - friendsList = " AND p.owner_id IN (-1) "; - } + if (friendsList.find("()") != std::string::npos) friendsList = " AND p.owner_id IN (-1) "; + orderBy += friendsList + "ORDER BY ci.name ASC "; delete friendsListQueryResult; @@ -142,7 +144,7 @@ std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMe else { orderBy = "ORDER BY p.last_updated DESC "; } - return baseQueryForProperties + orderBy + "LIMIT ? OFFSET ?;"; + return base + orderBy + (wantLimits ? "LIMIT ? OFFSET ?;" : ";"); } void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool includeNullAddress, bool includeNullDescription, bool playerOwn, bool updateUi, int32_t numResults, int32_t lReputationTime, int32_t sortMethod, int32_t startIndex, std::string filterText, const SystemAddress& sysAddr){ @@ -322,49 +324,27 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl propertyQueries[entity->GetObjectID()] = entries; - uint32_t numberOfProperties = 0; - if (sortMethod != SORT_TYPE_FRIENDS || sortMethod != SORT_TYPE_FEATURED) { - auto propertiesLeft = Database::CreatePreppedStmt("SELECT COUNT(*) FROM properties WHERE zone_id = ?;"); + int32_t numberOfProperties = 0; - propertiesLeft->setInt(1, this->m_MapID); + auto buttonQuery = BuildQuery(entity, sortMethod, "SELECT COUNT(*) FROM properties as p JOIN charinfo as ci ON ci.prop_clone_id = p.clone_id where p.zone_id = ? AND (p.description LIKE ? OR p.name LIKE ? OR ci.name LIKE ?) AND p.mod_approved >= ? AND p.privacy_option >= ? ", false); + auto propertiesLeft = Database::CreatePreppedStmt(buttonQuery); - auto result = propertiesLeft->executeQuery(); - result->next(); - numberOfProperties = result->getInt(1); + propertiesLeft->setUInt(1, this->m_MapID); + propertiesLeft->setString(2, searchString.c_str()); + propertiesLeft->setString(3, searchString.c_str()); + propertiesLeft->setString(4, searchString.c_str()); + propertiesLeft->setInt(5, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR || sortMethod == SORT_TYPE_FRIENDS ? 0 : 1); + propertiesLeft->setInt(6, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? 1 : 2); - delete result; - result = nullptr; + auto result = propertiesLeft->executeQuery(); + result->next(); + numberOfProperties = result->getInt(1); - delete propertiesLeft; - propertiesLeft = nullptr; - } else { - auto forFriends = query; - forFriends.replace(7, 3, "COUNT(*)"); - - auto friendsQuery = Database::CreatePreppedStmt(query); - - propertyLookup->setUInt(1, this->m_MapID); - propertyLookup->setString(2, searchString.c_str()); - propertyLookup->setString(3, searchString.c_str()); - propertyLookup->setString(4, searchString.c_str()); - propertyLookup->setInt(5, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR || sortMethod == SORT_TYPE_FRIENDS ? 0 : 1); - propertyLookup->setInt(6, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? 1 : 2); - propertyLookup->setInt(7, numResults); - propertyLookup->setInt(8, startIndex); - - auto result = friendsQuery->executeQuery(); - result->next(); - numberOfProperties = result->getInt(1); - - delete friendsQuery; - friendsQuery = nullptr; - - delete result; - result = nullptr; - } + delete result; + result = nullptr; - // if sort method is friends or featured do above query. - // do same maths below with resulting query - // else use default count. + delete propertiesLeft; + propertiesLeft = nullptr; + GameMessages::SendPropertySelectQuery(m_Parent->GetObjectID(), startIndex, numberOfProperties - (startIndex + numResults) > 0, character->GetPropertyCloneID(), false, true, entries, sysAddr); } \ No newline at end of file From 5fa0a16302554446b9a1f58dee02c51ae5442485 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 16:13:01 -0700 Subject: [PATCH 119/251] more options in BuildQuery method --- dGame/dComponents/PropertyEntranceComponent.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.h b/dGame/dComponents/PropertyEntranceComponent.h index fdb9240d..67b97ef2 100644 --- a/dGame/dComponents/PropertyEntranceComponent.h +++ b/dGame/dComponents/PropertyEntranceComponent.h @@ -61,7 +61,7 @@ class PropertyEntranceComponent : public Component { PropertySelectQueryProperty SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId = LWOCLONEID_INVALID, std::string ownerName = "", std::string propertyName = "", std::string propertyDescription = "", float reputation = 0, bool isBFF = false, bool isFriend = false, bool isModeratorApproved = false, bool isAlt = false, bool isOwned = false, uint32_t privacyOption = 0, uint32_t timeLastUpdated = 0, float performanceCost = 0.0f); - std::string BuildQuery(Entity* entity, int32_t sortMethod); + std::string BuildQuery(Entity* entity, int32_t sortMethod, std::string customQuery = "", bool wantLimits = true); private: /** @@ -86,5 +86,5 @@ class PropertyEntranceComponent : public Component { SORT_TYPE_FEATURED = 5 }; - const std::string baseQueryForProperties = "SELECT p.* FROM properties as p JOIN charinfo as ci ON ci.prop_clone_id = p.clone_id where p.zone_id = ? AND (p.description LIKE ? OR p.name LIKE ? OR ci.name LIKE ?) AND p.mod_approved >= ? AND p.privacy_option >= ? "; + std::string baseQueryForProperties = "SELECT p.* FROM properties as p JOIN charinfo as ci ON ci.prop_clone_id = p.clone_id where p.zone_id = ? AND (p.description LIKE ? OR p.name LIKE ? OR ci.name LIKE ?) AND p.mod_approved >= ? AND p.privacy_option >= ? "; }; From 04852ac1d93c08f112038656636cafffa35ae726 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 16:13:21 -0700 Subject: [PATCH 120/251] Removed const --- dGame/dComponents/PropertyManagementComponent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dComponents/PropertyManagementComponent.h b/dGame/dComponents/PropertyManagementComponent.h index 2184eed3..fd208b63 100644 --- a/dGame/dComponents/PropertyManagementComponent.h +++ b/dGame/dComponents/PropertyManagementComponent.h @@ -41,7 +41,7 @@ public: * @param sysAddr the address to send game message responses to * @param author optional explicit ID for the property, if not set defaults to the originator */ - void OnQueryPropertyData(Entity* originator, const SystemAddress& sysAddr, LWOOBJID author = LWOOBJID_EMPTY) const; + void OnQueryPropertyData(Entity* originator, const SystemAddress& sysAddr, LWOOBJID author = LWOOBJID_EMPTY); /** * Handles an OnUse event, telling the client who owns this property, etc. From 0bf2f0e92abffe661992bb634c4a491b4db5b303 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 16:14:24 -0700 Subject: [PATCH 121/251] Added enum for rejection statuses --- dGame/dGameMessages/PropertyDataMessage.cpp | 19 ++++++++++--------- dGame/dGameMessages/PropertyDataMessage.h | 6 ++++++ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/dGame/dGameMessages/PropertyDataMessage.cpp b/dGame/dGameMessages/PropertyDataMessage.cpp index 9a261a65..d763399d 100644 --- a/dGame/dGameMessages/PropertyDataMessage.cpp +++ b/dGame/dGameMessages/PropertyDataMessage.cpp @@ -64,17 +64,18 @@ void GameMessages::PropertyDataMessage::Serialize(RakNet::BitStream& stream) con stream.Write(0); - if (rejectionReason != "") stream.Write(2); - else if (moderatorRequested == true && rejectionReason == "") stream.Write(0); - else stream.Write(1); + if (rejectionReason != "") stream.Write(REJECTION_STATUS_REJECTED); + else if (moderatorRequested == true && rejectionReason == "") stream.Write(REJECTION_STATUS_PENDING); + else stream.Write(REJECTION_STATUS_APPROVED); // Does this go here??? - // const auto& rejectionReasonConverted = GeneralUtils::ASCIIToUTF16(rejectionReason); - // stream.Write(uint32_t(rejectionReasonConverted.size())); - // for (uint32_t i = 0; i < rejectionReasonConverted.size(); ++i) { - // stream.Write(uint16_t(rejectionReasonConverted[i])); - // } - stream.Write(0); + const auto& rejectionReasonConverted = GeneralUtils::ASCIIToUTF16(rejectionReason); + stream.Write(uint32_t(rejectionReasonConverted.size())); + for (uint32_t i = 0; i < rejectionReasonConverted.size(); ++i) { + stream.Write(uint16_t(rejectionReasonConverted[i])); + } + + // stream.Write(0); stream.Write(0); diff --git a/dGame/dGameMessages/PropertyDataMessage.h b/dGame/dGameMessages/PropertyDataMessage.h index a85702c4..5b5d7d0f 100644 --- a/dGame/dGameMessages/PropertyDataMessage.h +++ b/dGame/dGameMessages/PropertyDataMessage.h @@ -40,5 +40,11 @@ namespace GameMessages char PrivacyOption = 0; float MaxBuildHeight = 128.0f; std::vector Paths = {}; + private: + enum RejectionStatus : uint32_t { + REJECTION_STATUS_APPROVED = 0, + REJECTION_STATUS_PENDING = 1, + REJECTION_STATUS_REJECTED = 2 + }; }; } \ No newline at end of file From b79ebf1d407fe3c75292664eb132a64eb85c2522 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 18:25:32 -0700 Subject: [PATCH 122/251] Corrected faction for Buff Station --- dScripts/AgSurvivalBuffStation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dScripts/AgSurvivalBuffStation.cpp b/dScripts/AgSurvivalBuffStation.cpp index 01fe3976..31db8797 100644 --- a/dScripts/AgSurvivalBuffStation.cpp +++ b/dScripts/AgSurvivalBuffStation.cpp @@ -9,7 +9,7 @@ void AgSurvivalBuffStation::OnRebuildComplete(Entity* self, Entity* target) { auto destroyableComponent = self->GetComponent(); // We set the faction to 6 so that the buff station sees players as friendly targets to buff - if (destroyableComponent != nullptr) destroyableComponent->SetFaction(6); + if (destroyableComponent != nullptr) destroyableComponent->SetFaction(1); auto skillComponent = self->GetComponent(); From 041dc8256f76319917c3a90495468f8f7df003c0 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 18:34:26 -0700 Subject: [PATCH 123/251] comment --- dScripts/AgSurvivalBuffStation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dScripts/AgSurvivalBuffStation.cpp b/dScripts/AgSurvivalBuffStation.cpp index 31db8797..86a2f653 100644 --- a/dScripts/AgSurvivalBuffStation.cpp +++ b/dScripts/AgSurvivalBuffStation.cpp @@ -8,7 +8,7 @@ void AgSurvivalBuffStation::OnRebuildComplete(Entity* self, Entity* target) { auto destroyableComponent = self->GetComponent(); - // We set the faction to 6 so that the buff station sees players as friendly targets to buff + // We set the faction to 1 so that the buff station sees players as friendly targets to buff if (destroyableComponent != nullptr) destroyableComponent->SetFaction(1); auto skillComponent = self->GetComponent(); From b903c81a0add07dc1dff95843601c879564191f2 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 20:31:23 -0700 Subject: [PATCH 124/251] Shortened reputation update --- dGame/dMission/Mission.cpp | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/dGame/dMission/Mission.cpp b/dGame/dMission/Mission.cpp index c0fe60c0..748bebd4 100644 --- a/dGame/dMission/Mission.cpp +++ b/dGame/dMission/Mission.cpp @@ -524,32 +524,16 @@ void Mission::YieldRewards() { auto charId = character->GetID(); auto propertyCloneId = character->GetPropertyCloneID(); - auto properties = Database::CreatePreppedStmt("SELECT reputation FROM properties WHERE owner_id = ? AND clone_id = ?"); + auto reputationUpdate = Database::CreatePreppedStmt("UPDATE properties SET reputation = reputation + ? where owner_id = ? AND clone_id = ?"); - properties->setInt(1, charId); - properties->setInt64(2, propertyCloneId); + reputationUpdate->setInt64(1, info->reward_reputation); + reputationUpdate->setInt(2, charId); + reputationUpdate->setInt64(3, propertyCloneId); - auto results = properties->executeQuery(); + reputationUpdate->executeUpdate(); - while (results->next()) { - const auto oldReputation = results->getInt(1); - - auto reputationUpdate = Database::CreatePreppedStmt("UPDATE properties SET reputation = ? where owner_id = ? AND clone_id = ?"); - - reputationUpdate->setInt64(1, oldReputation + info->reward_reputation); - reputationUpdate->setInt(2, charId); - reputationUpdate->setInt64(3, propertyCloneId); - - reputationUpdate->execute(); - - delete reputationUpdate; - reputationUpdate = nullptr; - } - delete results; - results = nullptr; - - delete properties; - properties = nullptr; + delete reputationUpdate; + reputationUpdate = nullptr; GameMessages::SendUpdateReputation(entity->GetObjectID(), info->reward_reputation, entity->GetSystemAddress()); } From c80a90e81e1385bec3e01f32021cb67b07538a0b Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 20:31:51 -0700 Subject: [PATCH 125/251] rejection statuses were backwards --- dGame/dGameMessages/PropertyDataMessage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dGame/dGameMessages/PropertyDataMessage.cpp b/dGame/dGameMessages/PropertyDataMessage.cpp index d763399d..0831ac26 100644 --- a/dGame/dGameMessages/PropertyDataMessage.cpp +++ b/dGame/dGameMessages/PropertyDataMessage.cpp @@ -65,8 +65,8 @@ void GameMessages::PropertyDataMessage::Serialize(RakNet::BitStream& stream) con stream.Write(0); if (rejectionReason != "") stream.Write(REJECTION_STATUS_REJECTED); - else if (moderatorRequested == true && rejectionReason == "") stream.Write(REJECTION_STATUS_PENDING); - else stream.Write(REJECTION_STATUS_APPROVED); + else if (moderatorRequested == true && rejectionReason == "") stream.Write(REJECTION_STATUS_APPROVED); + else stream.Write(REJECTION_STATUS_PENDING); // Does this go here??? const auto& rejectionReasonConverted = GeneralUtils::ASCIIToUTF16(rejectionReason); From d3f954bdacdc0b02251a64af31632165f1bc2ffa Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 20:32:59 -0700 Subject: [PATCH 126/251] changed serialized value to old I am unsure if this is what gets serialized here so I am reverting this back to a zero. --- dGame/dGameMessages/PropertyDataMessage.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dGame/dGameMessages/PropertyDataMessage.cpp b/dGame/dGameMessages/PropertyDataMessage.cpp index 0831ac26..85eb54cb 100644 --- a/dGame/dGameMessages/PropertyDataMessage.cpp +++ b/dGame/dGameMessages/PropertyDataMessage.cpp @@ -69,13 +69,13 @@ void GameMessages::PropertyDataMessage::Serialize(RakNet::BitStream& stream) con else stream.Write(REJECTION_STATUS_PENDING); // Does this go here??? - const auto& rejectionReasonConverted = GeneralUtils::ASCIIToUTF16(rejectionReason); - stream.Write(uint32_t(rejectionReasonConverted.size())); - for (uint32_t i = 0; i < rejectionReasonConverted.size(); ++i) { - stream.Write(uint16_t(rejectionReasonConverted[i])); - } + // const auto& rejectionReasonConverted = GeneralUtils::ASCIIToUTF16(rejectionReason); + // stream.Write(uint32_t(rejectionReasonConverted.size())); + // for (uint32_t i = 0; i < rejectionReasonConverted.size(); ++i) { + // stream.Write(uint16_t(rejectionReasonConverted[i])); + // } - // stream.Write(0); + stream.Write(0); stream.Write(0); From 061d2b394c5cc1381784a4010d45cf5132f3bb76 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 20:33:37 -0700 Subject: [PATCH 127/251] on the fly property moderating notifications --- .../PropertyManagementComponent.cpp | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/dGame/dComponents/PropertyManagementComponent.cpp b/dGame/dComponents/PropertyManagementComponent.cpp index a5e33667..431cb800 100644 --- a/dGame/dComponents/PropertyManagementComponent.cpp +++ b/dGame/dComponents/PropertyManagementComponent.cpp @@ -75,7 +75,7 @@ PropertyManagementComponent::PropertyManagementComponent(Entity* parent) : Compo this->moderatorRequested = propertyEntry->getInt(10) == 0 && rejectionReason == "" && privacyOption == PropertyPrivacyOption::Public; this->LastUpdatedTime = propertyEntry->getUInt64(11); this->claimedTime = propertyEntry->getUInt64(12); - this->rejectionReason = propertyEntry->getString(13); + this->rejectionReason = propertyEntry->getString(13).asStdString(); this->reputation = propertyEntry->getUInt(14); Load(); @@ -157,12 +157,18 @@ void PropertyManagementComponent::SetPrivacyOption(PropertyPrivacyOption value) value = PropertyPrivacyOption::Private; } + if (value == PropertyPrivacyOption::Public && privacyOption != PropertyPrivacyOption::Public) { + rejectionReason = ""; + moderatorRequested = true; + } privacyOption = value; - auto* propertyUpdate = Database::CreatePreppedStmt("UPDATE properties SET privacy_option = ? WHERE id = ?;"); + auto* propertyUpdate = Database::CreatePreppedStmt("UPDATE properties SET privacy_option = ?, rejection_reason = ?, mod_approved = ? WHERE id = ?;"); propertyUpdate->setInt(1, static_cast(value)); - propertyUpdate->setInt64(2, propertyId); + propertyUpdate->setString(2, ""); + propertyUpdate->setInt(3, 0); + propertyUpdate->setInt64(4, propertyId); propertyUpdate->executeUpdate(); } @@ -791,7 +797,7 @@ PropertyManagementComponent* PropertyManagementComponent::Instance() return instance; } -void PropertyManagementComponent::OnQueryPropertyData(Entity* originator, const SystemAddress& sysAddr, LWOOBJID author) const +void PropertyManagementComponent::OnQueryPropertyData(Entity* originator, const SystemAddress& sysAddr, LWOOBJID author) { if (author == LWOOBJID_EMPTY) { author = m_Parent->GetObjectID(); @@ -830,6 +836,28 @@ void PropertyManagementComponent::OnQueryPropertyData(Entity* originator, const description = propertyDescription; claimed = claimedTime; privacy = static_cast(this->privacyOption); + if (moderatorRequested) { + auto checkStatus = Database::CreatePreppedStmt("SELECT rejection_reason, mod_approved FROM properties WHERE id = ?;"); + + checkStatus->setInt64(1, propertyId); + + auto result = checkStatus->executeQuery(); + + result->next(); + + const auto reason = result->getString(1).asStdString();; + const auto modApproved = result->getInt(2); + if (reason != "") { + moderatorRequested = false; + rejectionReason = reason; + } else if (reason == "" && modApproved == 1) { + moderatorRequested = false; + rejectionReason = ""; + } else { + moderatorRequested = true; + rejectionReason = ""; + } + } } message.moderatorRequested = moderatorRequested; message.reputation = reputation; @@ -845,7 +873,7 @@ void PropertyManagementComponent::OnQueryPropertyData(Entity* originator, const message.Paths = GetPaths(); SendDownloadPropertyData(author, message, UNASSIGNED_SYSTEM_ADDRESS); - // send rejction here? + // send rejection here? } void PropertyManagementComponent::OnUse(Entity* originator) From 002025231e920229f4517044b7f79c62821f7825 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 20:33:50 -0700 Subject: [PATCH 128/251] Semantics --- .../dComponents/PropertyEntranceComponent.cpp | 40 +++++++++---------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index cfe39bed..c1e29b95 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -1,13 +1,15 @@ -#include -#include "PropertyEntranceComponent.h" +#include "PropertyEntranceComponent.h" + +#include + +#include "Character.h" +#include "Database.h" +#include "GameMessages.h" +#include "PropertyManagementComponent.h" #include "PropertySelectQueryProperty.h" #include "RocketLaunchpadControlComponent.h" -#include "Character.h" -#include "GameMessages.h" -#include "dLogger.h" -#include "Database.h" -#include "PropertyManagementComponent.h" #include "UserManager.h" +#include "dLogger.h" PropertyEntranceComponent::PropertyEntranceComponent(uint32_t componentID, Entity* parent) : Component(parent) { @@ -200,25 +202,22 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl propertyLookup->setInt(6, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? (uint32_t)PropertyPrivacyOption::Friends : (uint32_t)PropertyPrivacyOption::Public); propertyLookup->setInt(7, numResults); propertyLookup->setInt(8, startIndex); - - Game::logger->Log("PropertyEntranceComponent", "Property query is \n%s\n. Entity is %s.\n", query.c_str(), entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR ? "a moderator" : "not a moderator"); auto propertyEntry = propertyLookup->executeQuery(); - - while (propertyEntry->next()) - { - const auto propertyId = propertyEntry->getUInt64(1); - const auto owner = propertyEntry->getInt(2); + + while (propertyEntry->next()) { + const auto propertyId = propertyEntry->getUInt64(1); + const auto owner = propertyEntry->getInt(2); const auto cloneId = propertyEntry->getUInt64(4); const auto name = propertyEntry->getString(5).asStdString(); const auto description = propertyEntry->getString(6).asStdString(); - const auto privacyOption = propertyEntry->getInt(9); + const auto privacyOption = propertyEntry->getInt(9); const auto modApproved = propertyEntry->getBoolean(10); const auto dateLastUpdated = propertyEntry->getInt(11); const float reputation = propertyEntry->getInt(14); const auto performanceCost = (float)propertyEntry->getDouble(16); - PropertySelectQueryProperty entry {}; + PropertySelectQueryProperty entry{}; std::string ownerName = ""; bool isOwned = true; @@ -235,8 +234,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl Game::logger->Log("PropertyEntranceComponent", "Failed to find property owner name for %llu!\n", cloneId); continue; - } - else { + } else { isOwned = cloneId == character->GetPropertyCloneID(); ownerName = nameResult->getString(1).asStdString(); } @@ -244,7 +242,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl delete nameResult; nameResult = nullptr; - delete nameLookup; + delete nameLookup; nameLookup = nullptr; std::string propertyName = ""; @@ -269,7 +267,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl friendCheck->setInt64(4, entity->GetObjectID()); auto friendResult = friendCheck->executeQuery(); - + // If we got a result than the two players are friends. if (friendResult->next()) { isFriend = true; @@ -314,7 +312,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl entry = SetPropertyValues(entry, cloneId, ownerName, propertyName, propertyDescription, reputation, isBestFriend, isFriend, isModeratorApproved, isAlt, isOwned, privacyOption, dateLastUpdated, performanceCost); entries.push_back(entry); - } + } delete propertyEntry; propertyEntry = nullptr; From f22dab0f72ac94f6a1f0a86be34d0b4720566f62 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 21:12:22 -0700 Subject: [PATCH 129/251] unapproved properties render correctly --- .../dComponents/PropertyEntranceComponent.cpp | 19 +++++++++---------- dGame/dComponents/PropertyEntranceComponent.h | 2 +- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index c1e29b95..eaee9077 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -192,16 +192,15 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl const auto query = BuildQuery(entity, sortMethod); auto propertyLookup = Database::CreatePreppedStmt(query); - + const auto searchString = "%" + filterText + "%"; propertyLookup->setUInt(1, this->m_MapID); propertyLookup->setString(2, searchString.c_str()); propertyLookup->setString(3, searchString.c_str()); propertyLookup->setString(4, searchString.c_str()); - propertyLookup->setInt(5, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR || sortMethod == SORT_TYPE_FRIENDS ? 0 : 1); - propertyLookup->setInt(6, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? (uint32_t)PropertyPrivacyOption::Friends : (uint32_t)PropertyPrivacyOption::Public); - propertyLookup->setInt(7, numResults); - propertyLookup->setInt(8, startIndex); + propertyLookup->setInt(5, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? (uint32_t)PropertyPrivacyOption::Friends : (uint32_t)PropertyPrivacyOption::Public); + propertyLookup->setInt(6, numResults); + propertyLookup->setInt(7, startIndex); auto propertyEntry = propertyLookup->executeQuery(); @@ -291,7 +290,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl } bool isAlt = false; - // Query to determine whether this property is an alt of the entity. + // Query to determine whether this property is an alt character of the entity. auto isAltQuery = Database::CreatePreppedStmt("SELECT id FROM charinfo where account_id in (SELECT account_id from charinfo WHERE id = ?) AND id = ?;"); isAltQuery->setInt(1, character->GetID()); @@ -321,18 +320,18 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl propertyLookup = nullptr; propertyQueries[entity->GetObjectID()] = entries; - + + // Query here is to figure out whether or not to display the button to go to the next page or not. int32_t numberOfProperties = 0; - auto buttonQuery = BuildQuery(entity, sortMethod, "SELECT COUNT(*) FROM properties as p JOIN charinfo as ci ON ci.prop_clone_id = p.clone_id where p.zone_id = ? AND (p.description LIKE ? OR p.name LIKE ? OR ci.name LIKE ?) AND p.mod_approved >= ? AND p.privacy_option >= ? ", false); + auto buttonQuery = BuildQuery(entity, sortMethod, "SELECT COUNT(*) FROM properties as p JOIN charinfo as ci ON ci.prop_clone_id = p.clone_id where p.zone_id = ? AND (p.description LIKE ? OR p.name LIKE ? OR ci.name LIKE ?) AND p.privacy_option >= ? ", false); auto propertiesLeft = Database::CreatePreppedStmt(buttonQuery); propertiesLeft->setUInt(1, this->m_MapID); propertiesLeft->setString(2, searchString.c_str()); propertiesLeft->setString(3, searchString.c_str()); propertiesLeft->setString(4, searchString.c_str()); - propertiesLeft->setInt(5, entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR || sortMethod == SORT_TYPE_FRIENDS ? 0 : 1); - propertiesLeft->setInt(6, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? 1 : 2); + propertiesLeft->setInt(5, sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS ? 1 : 2); auto result = propertiesLeft->executeQuery(); result->next(); diff --git a/dGame/dComponents/PropertyEntranceComponent.h b/dGame/dComponents/PropertyEntranceComponent.h index 67b97ef2..0e948068 100644 --- a/dGame/dComponents/PropertyEntranceComponent.h +++ b/dGame/dComponents/PropertyEntranceComponent.h @@ -86,5 +86,5 @@ class PropertyEntranceComponent : public Component { SORT_TYPE_FEATURED = 5 }; - std::string baseQueryForProperties = "SELECT p.* FROM properties as p JOIN charinfo as ci ON ci.prop_clone_id = p.clone_id where p.zone_id = ? AND (p.description LIKE ? OR p.name LIKE ? OR ci.name LIKE ?) AND p.mod_approved >= ? AND p.privacy_option >= ? "; + std::string baseQueryForProperties = "SELECT p.* FROM properties as p JOIN charinfo as ci ON ci.prop_clone_id = p.clone_id where p.zone_id = ? AND (p.description LIKE ? OR p.name LIKE ? OR ci.name LIKE ?) AND p.privacy_option >= ? "; }; From bc7c54353062d0286f8a78c10c5866eab247b4a4 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 21:15:50 -0700 Subject: [PATCH 130/251] removed debug log --- dGame/dComponents/PropertyEntranceComponent.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index eaee9077..8ee20466 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -66,8 +66,6 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, cloneId = query[index].CloneId; } - Game::logger->Log("PropertyEntranceComponent", "index is %i\n", index); - auto* launcher = m_Parent->GetComponent(); if (launcher == nullptr) From 8a8b5b4f442c8849dced180557e910b72b9e833b Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 21:18:29 -0700 Subject: [PATCH 131/251] removed new line --- dGame/dComponents/PropertyEntranceComponent.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 8ee20466..06886a0a 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -78,8 +78,7 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, launcher->Launch(entity, LWOOBJID_EMPTY, launcher->GetTargetZone(), cloneId); } -PropertySelectQueryProperty PropertyEntranceComponent::SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId, std::string ownerName, std::string propertyName, std::string propertyDescription, - float reputation, bool isBFF, bool isFriend, bool isModeratorApproved, bool isAlt, bool isOwned, uint32_t privacyOption, uint32_t timeLastUpdated, float performanceCost) { +PropertySelectQueryProperty PropertyEntranceComponent::SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId, std::string ownerName, std::string propertyName, std::string propertyDescription, float reputation, bool isBFF, bool isFriend, bool isModeratorApproved, bool isAlt, bool isOwned, uint32_t privacyOption, uint32_t timeLastUpdated, float performanceCost) { property.CloneId = cloneId; property.OwnerName = ownerName; property.Name = propertyName; From 8462068a05c98ae8cd63c9c84f394fd884137fe4 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 21:33:25 -0700 Subject: [PATCH 132/251] clarified variable names, used encapsulation --- dGame/dComponents/PropertyEntranceComponent.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 06886a0a..f125f326 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -104,8 +104,9 @@ std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMe base = customQuery; } std::string orderBy = ""; - std::string friendsList = " AND p.owner_id IN ("; if (sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS) { + std::string friendsList = " AND p.owner_id IN ("; + auto friendsListQuery = Database::CreatePreppedStmt("SELECT * FROM (SELECT CASE WHEN player_id = ? THEN friend_id WHEN friend_id = ? THEN player_id END AS requested_player FROM dlu.friends ) AS fr WHERE requested_player IS NOT NULL ORDER BY requested_player DESC;"); friendsListQuery->setInt64(1, entity->GetObjectID()); @@ -165,15 +166,15 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl // If the player has a property this query will have a single result. if (playerPropertyLookupResults->next()) { const auto cloneId = playerPropertyLookupResults->getUInt64(4); - const auto name = playerPropertyLookupResults->getString(5).asStdString(); - const auto description = playerPropertyLookupResults->getString(6).asStdString(); + const auto propertyName = playerPropertyLookupResults->getString(5).asStdString(); + const auto propertyDescription = playerPropertyLookupResults->getString(6).asStdString(); const auto privacyOption = playerPropertyLookupResults->getInt(9); const auto modApproved = playerPropertyLookupResults->getBoolean(10); const auto dateLastUpdated = playerPropertyLookupResults->getInt64(11); const auto reputation = playerPropertyLookupResults->getUInt(14); const auto performanceCost = (float)playerPropertyLookupResults->getDouble(16); - playerEntry = SetPropertyValues(playerEntry, cloneId, character->GetName(), name, description, reputation, true, true, modApproved, true, true, privacyOption, dateLastUpdated, performanceCost); + playerEntry = SetPropertyValues(playerEntry, cloneId, character->GetName(), propertyName, propertyDescription, reputation, true, true, modApproved, true, true, privacyOption, dateLastUpdated, performanceCost); } else { playerEntry = SetPropertyValues(playerEntry, character->GetPropertyCloneID(), character->GetName(), "", "", 0, true, true); } From e66421d34f3868b7bb9ef9849cc80dcacd99a8c8 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 21:58:43 -0700 Subject: [PATCH 133/251] clarified variable name --- dGame/dComponents/PropertyEntranceComponent.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index f125f326..4dd2eed0 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -206,8 +206,8 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl const auto propertyId = propertyEntry->getUInt64(1); const auto owner = propertyEntry->getInt(2); const auto cloneId = propertyEntry->getUInt64(4); - const auto name = propertyEntry->getString(5).asStdString(); - const auto description = propertyEntry->getString(6).asStdString(); + const auto propertyNameFromDb = propertyEntry->getString(5).asStdString(); + const auto propertyDescriptionFromDb = propertyEntry->getString(6).asStdString(); const auto privacyOption = propertyEntry->getInt(9); const auto modApproved = propertyEntry->getBoolean(10); const auto dateLastUpdated = propertyEntry->getInt(11); @@ -242,10 +242,8 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl delete nameLookup; nameLookup = nullptr; - std::string propertyName = ""; - std::string propertyDescription = ""; - propertyName = name; - propertyDescription = description; + std::string propertyName = propertyNameFromDb; + std::string propertyDescription = propertyDescriptionFromDb; bool isBestFriend = false; bool isFriend = false; From 0561f600316c1d48dd57e93f94b3e0ae10c1d762 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 21:58:59 -0700 Subject: [PATCH 134/251] Added negative checks --- .../PropertyManagementComponent.cpp | 34 +++++++++++-------- .../dComponents/PropertyManagementComponent.h | 4 ++- dGame/dComponents/PropertyVendorComponent.cpp | 7 ++-- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/dGame/dComponents/PropertyManagementComponent.cpp b/dGame/dComponents/PropertyManagementComponent.cpp index 431cb800..550d15fe 100644 --- a/dGame/dComponents/PropertyManagementComponent.cpp +++ b/dGame/dComponents/PropertyManagementComponent.cpp @@ -192,31 +192,35 @@ void PropertyManagementComponent::UpdatePropertyDetails(std::string name, std::s OnQueryPropertyData(GetOwner(), UNASSIGNED_SYSTEM_ADDRESS); } -void PropertyManagementComponent::Claim(const LWOOBJID playerId) +bool PropertyManagementComponent::Claim(const LWOOBJID playerId) { if (owner != LWOOBJID_EMPTY) { - return; + return false; } - - SetOwnerId(playerId); - - auto* zone = dZoneManager::Instance()->GetZone(); - - const auto& worldId = zone->GetZoneID(); - const auto zoneId = worldId.GetMapID(); auto* entity = EntityManager::Instance()->GetEntity(playerId); auto* user = entity->GetParentUser(); auto character = entity->GetCharacter(); - if (!character) return; + if (!character) return false; - const auto cloneId = character->GetPropertyCloneID(); + auto* zone = dZoneManager::Instance()->GetZone(); + + const auto& worldId = zone->GetZoneID(); + const auto propertyZoneId = worldId.GetMapID(); + const auto propertyCloneId = worldId.GetCloneID(); + + const auto playerCloneId = character->GetPropertyCloneID(); + + // If we are not on our clone do not allow us to claim the property + if (propertyCloneId != playerCloneId) return false; + + SetOwnerId(playerId); propertyId = ObjectIDManager::GenerateRandomObjectID(); - + auto* insertion = Database::CreatePreppedStmt( "INSERT INTO properties" "(id, owner_id, template_id, clone_id, name, description, rent_amount, rent_due, privacy_option, last_updated, time_claimed, rejection_reason, reputation, zone_id, performance_cost)" @@ -225,9 +229,9 @@ void PropertyManagementComponent::Claim(const LWOOBJID playerId) insertion->setUInt64(1, propertyId); insertion->setUInt64(2, (uint32_t) playerId); insertion->setUInt(3, templateId); - insertion->setUInt64(4, cloneId); + insertion->setUInt64(4, playerCloneId); insertion->setString(5, zone->GetZoneName().c_str()); - insertion->setInt(6, zoneId); + insertion->setInt(6, propertyZoneId); // Try and execute the query, print an error if it fails. try @@ -239,12 +243,14 @@ void PropertyManagementComponent::Claim(const LWOOBJID playerId) Game::logger->Log("PropertyManagementComponent", "Failed to execute query: (%s)!\n", exception.what()); throw exception; + return false; } auto* zoneControlObject = dZoneManager::Instance()->GetZoneControlObject(); for (CppScripts::Script* script : CppScripts::GetEntityScripts(zoneControlObject)) { script->OnZonePropertyRented(zoneControlObject, entity); } + return true; } void PropertyManagementComponent::OnStartBuilding() diff --git a/dGame/dComponents/PropertyManagementComponent.h b/dGame/dComponents/PropertyManagementComponent.h index fd208b63..c37282e9 100644 --- a/dGame/dComponents/PropertyManagementComponent.h +++ b/dGame/dComponents/PropertyManagementComponent.h @@ -101,8 +101,10 @@ public: /** * Makes this property owned by the passed player ID, storing it in the database * @param playerId the ID of the entity that claimed the property + * + * @return If the claim is successful return true. */ - void Claim(LWOOBJID playerId); + bool Claim(LWOOBJID playerId); /** * Event triggered when the owner of the property starts building, will kick other entities out diff --git a/dGame/dComponents/PropertyVendorComponent.cpp b/dGame/dComponents/PropertyVendorComponent.cpp index e6b8fe97..72e8ad64 100644 --- a/dGame/dComponents/PropertyVendorComponent.cpp +++ b/dGame/dComponents/PropertyVendorComponent.cpp @@ -41,13 +41,16 @@ void PropertyVendorComponent::OnBuyFromVendor(Entity* originator, const bool con { if (PropertyManagementComponent::Instance() == nullptr) return; + if (PropertyManagementComponent::Instance()->Claim(originator->GetObjectID()) == false) { + Game::logger->Log("PropertyVendorComponent", "FAILED TO CLAIM PROPERTY. PLAYER ID IS %llu\n", originator->GetObjectID()); + return; + } + GameMessages::SendPropertyRentalResponse(m_Parent->GetObjectID(), 0, 0, 0, 0, originator->GetSystemAddress()); auto* controller = dZoneManager::Instance()->GetZoneControlObject(); controller->OnFireEventServerSide(m_Parent, "propertyRented"); - - PropertyManagementComponent::Instance()->Claim(originator->GetObjectID()); PropertyManagementComponent::Instance()->SetOwner(originator); From aed0ecc9fc3aea0677093ecae99ae857e1bc96f4 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 22:05:09 -0700 Subject: [PATCH 135/251] removed newline --- dGame/dComponents/PropertyEntranceComponent.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.h b/dGame/dComponents/PropertyEntranceComponent.h index 0e948068..a3be38a6 100644 --- a/dGame/dComponents/PropertyEntranceComponent.h +++ b/dGame/dComponents/PropertyEntranceComponent.h @@ -58,8 +58,7 @@ class PropertyEntranceComponent : public Component { */ [[nodiscard]] LWOMAPID GetMapID() const { return m_MapID; }; - PropertySelectQueryProperty SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId = LWOCLONEID_INVALID, std::string ownerName = "", std::string propertyName = "", std::string propertyDescription = "", - float reputation = 0, bool isBFF = false, bool isFriend = false, bool isModeratorApproved = false, bool isAlt = false, bool isOwned = false, uint32_t privacyOption = 0, uint32_t timeLastUpdated = 0, float performanceCost = 0.0f); + PropertySelectQueryProperty SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId = LWOCLONEID_INVALID, std::string ownerName = "", std::string propertyName = "", std::string propertyDescription = "", float reputation = 0, bool isBFF = false, bool isFriend = false, bool isModeratorApproved = false, bool isAlt = false, bool isOwned = false, uint32_t privacyOption = 0, uint32_t timeLastUpdated = 0, float performanceCost = 0.0f); std::string BuildQuery(Entity* entity, int32_t sortMethod, std::string customQuery = "", bool wantLimits = true); From 9169acad476d0f5f5e5427fbe247910419da28fa Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 22:14:51 -0700 Subject: [PATCH 136/251] changed to update --- dGame/dGameMessages/GameMessages.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index e8973283..1a1795f2 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -4167,7 +4167,7 @@ void GameMessages::HandleUpdatePropertyPerformanceCost(RakNet::BitStream* inStre updatePerformanceCostQuery->setInt(2, cloneId); updatePerformanceCostQuery->setInt(3, zoneId); - updatePerformanceCostQuery->execute(); + updatePerformanceCostQuery->executeUpdate(); delete updatePerformanceCostQuery; updatePerformanceCostQuery = nullptr; From cc9b6c05f60ebef1b545eec36c57239ecef934b2 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 22:35:41 -0700 Subject: [PATCH 137/251] removed include --- dGame/dGameMessages/PropertySelectQueryProperty.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/dGame/dGameMessages/PropertySelectQueryProperty.cpp b/dGame/dGameMessages/PropertySelectQueryProperty.cpp index 6a66554d..38e7cea2 100644 --- a/dGame/dGameMessages/PropertySelectQueryProperty.cpp +++ b/dGame/dGameMessages/PropertySelectQueryProperty.cpp @@ -1,5 +1,4 @@ #include "PropertySelectQueryProperty.h" -#include void PropertySelectQueryProperty::Serialize(RakNet::BitStream& stream) const { From 33b16a56e32beda7ffe55a3f4d9c401aa6bba241 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 30 Mar 2022 22:51:09 -0700 Subject: [PATCH 138/251] Added a save and fixed a crash If am item were to be added to properties_contents and an item with that Primary Key already existed, the world would crash. This addresses this. --- .../PropertyManagementComponent.cpp | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/dGame/dComponents/PropertyManagementComponent.cpp b/dGame/dComponents/PropertyManagementComponent.cpp index 550d15fe..f982326c 100644 --- a/dGame/dComponents/PropertyManagementComponent.cpp +++ b/dGame/dComponents/PropertyManagementComponent.cpp @@ -296,6 +296,8 @@ void PropertyManagementComponent::OnFinishBuilding() SetPrivacyOption(originalPrivacyOption); UpdateApprovedStatus(false); + + Save(); } void PropertyManagementComponent::UpdateModelPosition(const LWOOBJID id, const NiPoint3 position, NiQuaternion rotation) @@ -706,9 +708,12 @@ void PropertyManagementComponent::Save() auto* remove = Database::CreatePreppedStmt("DELETE FROM properties_contents WHERE id = ?;"); lookup->setUInt64(1, propertyId); - - auto* lookupResult = lookup->executeQuery(); - + sql::ResultSet* lookupResult = nullptr; + try { + lookupResult = lookup->executeQuery(); + } catch (sql::SQLException& ex) { + Game::logger->Log("PropertyManagementComponent", "lookup error %s\n", ex.what()); + } std::vector present; while (lookupResult->next()) @@ -751,8 +756,11 @@ void PropertyManagementComponent::Save() insertion->setDouble(9, rotation.y); insertion->setDouble(10, rotation.z); insertion->setDouble(11, rotation.w); - - insertion->execute(); + try { + insertion->execute(); + } catch (sql::SQLException& ex) { + Game::logger->Log("PropertyManagementComponent", "Error inserting into properties_contents. Error %s\n", ex.what()); + } } else { @@ -765,8 +773,11 @@ void PropertyManagementComponent::Save() update->setDouble(7, rotation.w); update->setInt64(8, id); - - update->executeUpdate(); + try { + update->executeUpdate(); + } catch (sql::SQLException& ex) { + Game::logger->Log("PropertyManagementComponent", "Error updating properties_contents. Error: %s\n", ex.what()); + } } } @@ -778,8 +789,11 @@ void PropertyManagementComponent::Save() } remove->setInt64(1, id); - - remove->execute(); + try { + remove->execute(); + } catch (sql::SQLException& ex) { + Game::logger->Log("PropertyManagementComponent", "Error removing from properties_contents. Error %s\n", ex.what()); + } } auto* removeUGC = Database::CreatePreppedStmt("DELETE FROM ugc WHERE id NOT IN (SELECT ugc_id FROM properties_contents);"); From cf708813703e696ba0c6a8affcba63984428696d Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 31 Mar 2022 03:20:13 -0700 Subject: [PATCH 139/251] simplified conversion --- dGame/dGameMessages/GameMessages.cpp | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 297df424..70c6bcae 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -5890,7 +5890,7 @@ void GameMessages::HandleReportBug(RakNet::BitStream* inStream, Entity* entity) std::string nOtherPlayerID; std::string selection; uint32_t messageLength; - int32_t reporterID; + int32_t reporterID = 0; //Reading: inStream->Read(messageLength); @@ -5920,18 +5920,9 @@ void GameMessages::HandleReportBug(RakNet::BitStream* inStream, Entity* entity) nOtherPlayerID.push_back(character); } // Convert other player id from LWOOBJID to the database id. - std::istringstream iss(nOtherPlayerID); - LWOOBJID nOtherPlayerLWOOBJID; - iss >> nOtherPlayerLWOOBJID; - if (nOtherPlayerLWOOBJID != LWOOBJID_EMPTY) { - auto otherPlayer = EntityManager::Instance()->GetEntity(nOtherPlayerLWOOBJID); - if (otherPlayer) { - auto character = otherPlayer->GetCharacter(); - if (character) { - nOtherPlayerID = std::to_string(character->GetID()); - } - } - } + uint32_t otherPlayer = LWOOBJID_EMPTY; + if (nOtherPlayerID != "") otherPlayer = std::atoi(nOtherPlayerID.c_str()); + uint32_t selectionLength; inStream->Read(selectionLength); for (unsigned int k = 0; k < selectionLength; k++) { @@ -5944,14 +5935,14 @@ void GameMessages::HandleReportBug(RakNet::BitStream* inStream, Entity* entity) sql::PreparedStatement* insertBug = Database::CreatePreppedStmt("INSERT INTO `bug_reports`(body, client_version, other_player_id, selection, reporter_id) VALUES (?, ?, ?, ?, ?)"); insertBug->setString(1, GeneralUtils::UTF16ToWTF8(body)); insertBug->setString(2, clientVersion); - insertBug->setString(3, nOtherPlayerID); + insertBug->setString(3, std::to_string(otherPlayer)); insertBug->setString(4, selection); insertBug->setInt(5, reporterID); insertBug->execute(); delete insertBug; } catch (sql::SQLException& e) { - Game::logger->Log("HandleReportBug", "Couldn't save bug report!\n"); + Game::logger->Log("HandleReportBug", "Couldn't save bug report! (%s)\n", e.what()); } } From 450bebc8a20beeed3040fcc34558a39a6f158de3 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 31 Mar 2022 14:11:43 -0700 Subject: [PATCH 140/251] i am a big dum --- dGame/dComponents/PropertyEntranceComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 4dd2eed0..728cdc9e 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -107,7 +107,7 @@ std::string PropertyEntranceComponent::BuildQuery(Entity* entity, int32_t sortMe if (sortMethod == SORT_TYPE_FEATURED || sortMethod == SORT_TYPE_FRIENDS) { std::string friendsList = " AND p.owner_id IN ("; - auto friendsListQuery = Database::CreatePreppedStmt("SELECT * FROM (SELECT CASE WHEN player_id = ? THEN friend_id WHEN friend_id = ? THEN player_id END AS requested_player FROM dlu.friends ) AS fr WHERE requested_player IS NOT NULL ORDER BY requested_player DESC;"); + auto friendsListQuery = Database::CreatePreppedStmt("SELECT * FROM (SELECT CASE WHEN player_id = ? THEN friend_id WHEN friend_id = ? THEN player_id END AS requested_player FROM friends ) AS fr WHERE requested_player IS NOT NULL ORDER BY requested_player DESC;"); friendsListQuery->setInt64(1, entity->GetObjectID()); friendsListQuery->setInt64(2, entity->GetObjectID()); From 8ae7bc0f926da9d05cd03fcdaf26a735a65a2537 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 31 Mar 2022 16:12:36 -0700 Subject: [PATCH 141/251] Where to send reputation to client --- dNet/WorldPackets.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/dNet/WorldPackets.cpp b/dNet/WorldPackets.cpp index 399ab9e5..53dbf062 100644 --- a/dNet/WorldPackets.cpp +++ b/dNet/WorldPackets.cpp @@ -131,7 +131,7 @@ void WorldPackets::SendCreateCharacter(const SystemAddress& sysAddr, const LWOOB PacketUtils::WriteHeader(bitStream, CLIENT, MSG_CLIENT_CREATE_CHARACTER); RakNet::BitStream data; - data.Write(6); //LDF key count + data.Write(7); //LDF key count LDFData* objid = new LDFData(u"objid", objectID); LDFData* lot = new LDFData(u"template", 1); @@ -139,13 +139,15 @@ void WorldPackets::SendCreateCharacter(const SystemAddress& sysAddr, const LWOOB LDFData* name = new LDFData(u"name", username); LDFData* gmlevel = new LDFData(u"gmlevel", gm); LDFData* chatmode = new LDFData(u"chatmode", gm); - + LDFData* reputation = new LDFData(u"reputation", 400); + objid->WriteToPacket(&data); lot->WriteToPacket(&data); name->WriteToPacket(&data); gmlevel->WriteToPacket(&data); chatmode->WriteToPacket(&data); xmlConfigData->WriteToPacket(&data); + reputation->WriteToPacket(&data); delete objid; delete lot; @@ -153,7 +155,8 @@ void WorldPackets::SendCreateCharacter(const SystemAddress& sysAddr, const LWOOB delete gmlevel; delete chatmode; delete name; - + delete reputation; + #ifdef _WIN32 bitStream.Write(data.GetNumberOfBytesUsed() + 1); bitStream.Write(0); From ece83db6ed50ddf9817a1b20a8a33cab82805230 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 31 Mar 2022 18:17:23 -0700 Subject: [PATCH 142/251] World packets change World packets now takes an entity so we can process reputation --- dNet/WorldPackets.cpp | 15 +++++++++++---- dNet/WorldPackets.h | 3 ++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/dNet/WorldPackets.cpp b/dNet/WorldPackets.cpp index 53dbf062..ae8f71a4 100644 --- a/dNet/WorldPackets.cpp +++ b/dNet/WorldPackets.cpp @@ -12,6 +12,7 @@ #include "LDFFormat.h" #include "dServer.h" #include "dZoneManager.h" +#include "CharacterComponent.h" #include "ZCompression.h" void WorldPackets::SendLoadStaticZone(const SystemAddress& sysAddr, float x, float y, float z, uint32_t checksum) { @@ -126,20 +127,26 @@ void WorldPackets::SendServerState ( const SystemAddress& sysAddr ) { SEND_PACKET } -void WorldPackets::SendCreateCharacter(const SystemAddress& sysAddr, const LWOOBJID& objectID, const std::string& xmlData, const std::u16string& username, int32_t gm) { +void WorldPackets::SendCreateCharacter(const SystemAddress& sysAddr, Entity* entity, const std::string& xmlData, const std::u16string& username, int32_t gm) { RakNet::BitStream bitStream; PacketUtils::WriteHeader(bitStream, CLIENT, MSG_CLIENT_CREATE_CHARACTER); RakNet::BitStream data; data.Write(7); //LDF key count - LDFData* objid = new LDFData(u"objid", objectID); + auto character = entity->GetComponent(); + if (!character) { + Game::logger->Log("WorldPackets", "Entity is not a character?? what??"); + return; + } + + LDFData* objid = new LDFData(u"objid", entity->GetObjectID()); LDFData* lot = new LDFData(u"template", 1); LDFData * xmlConfigData = new LDFData(u"xmlData", xmlData); LDFData* name = new LDFData(u"name", username); LDFData* gmlevel = new LDFData(u"gmlevel", gm); LDFData* chatmode = new LDFData(u"chatmode", gm); - LDFData* reputation = new LDFData(u"reputation", 400); + LDFData* reputation = new LDFData(u"reputation", character->GetReputation()); objid->WriteToPacket(&data); lot->WriteToPacket(&data); @@ -178,7 +185,7 @@ void WorldPackets::SendCreateCharacter(const SystemAddress& sysAddr, const LWOOB PacketUtils::SavePacket("chardata.bin", (const char *)bitStream.GetData(), static_cast(bitStream.GetNumberOfBytesUsed())); SEND_PACKET - Game::logger->Log("WorldPackets", "Sent CreateCharacter for ID: %llu\n", objectID); + Game::logger->Log("WorldPackets", "Sent CreateCharacter for ID: %llu\n", entity->GetObjectID()); } void WorldPackets::SendChatModerationResponse(const SystemAddress& sysAddr, bool requestAccepted, uint32_t requestID, const std::string& receiver, std::unordered_map unacceptedItems) { diff --git a/dNet/WorldPackets.h b/dNet/WorldPackets.h index ff51a7f6..3508d6f0 100644 --- a/dNet/WorldPackets.h +++ b/dNet/WorldPackets.h @@ -4,6 +4,7 @@ #include "dCommonVars.h" #include #include +#include "Entity.h" class User; struct SystemAddress; @@ -16,7 +17,7 @@ namespace WorldPackets { void SendCharacterDeleteResponse(const SystemAddress& sysAddr, bool response); void SendTransferToWorld(const SystemAddress& sysAddr, const std::string& serverIP, uint32_t serverPort, bool mythranShift); void SendServerState(const SystemAddress& sysAddr); - void SendCreateCharacter(const SystemAddress& sysAddr, const LWOOBJID& objectID, const std::string& xmlData, const std::u16string& username, int32_t gm); + void SendCreateCharacter(const SystemAddress& sysAddr, Entity* entity, const std::string& xmlData, const std::u16string& username, int32_t gm); void SendChatModerationResponse(const SystemAddress& sysAddr, bool requestAccepted, uint32_t requestID, const std::string& receiver, std::unordered_map unacceptedItems); void SendGMLevelChange(const SystemAddress& sysAddr, bool success, uint8_t highestLevel, uint8_t prevLevel, uint8_t newLevel); } From 0bf2d398eae9ae9074ce467239c16d913056c935 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 31 Mar 2022 18:17:43 -0700 Subject: [PATCH 143/251] moved initialization of entity --- dWorldServer/WorldServer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index c9b6b00b..c8f2641e 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -1013,15 +1013,15 @@ void HandlePacket(Packet* packet) { Character* c = user->GetLastUsedChar(); if (c != nullptr) { std::u16string username = GeneralUtils::ASCIIToUTF16(c->GetName()); - WorldPackets::SendCreateCharacter(packet->systemAddress, c->GetObjectID(), c->GetXMLData(), username, c->GetGMLevel()); - WorldPackets::SendServerState(packet->systemAddress); - Game::server->GetReplicaManager()->AddParticipant(packet->systemAddress); EntityInfo info {}; info.lot = 1; Entity* player = EntityManager::Instance()->CreateEntity(info, UserManager::Instance()->GetUser(packet->systemAddress)); + WorldPackets::SendCreateCharacter(packet->systemAddress, player, c->GetXMLData(), username, c->GetGMLevel()); + WorldPackets::SendServerState(packet->systemAddress); + const auto respawnPoint = player->GetCharacter()->GetRespawnPoint(dZoneManager::Instance()->GetZone()->GetWorldID()); EntityManager::Instance()->ConstructEntity(player, UNASSIGNED_SYSTEM_ADDRESS, true); From ba33c15b2d7824013d490953b4232f37f2a42922 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 31 Mar 2022 18:17:58 -0700 Subject: [PATCH 144/251] reputation rewards are now applied to character and not properties --- dGame/dMission/Mission.cpp | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/dGame/dMission/Mission.cpp b/dGame/dMission/Mission.cpp index 748bebd4..f7b57071 100644 --- a/dGame/dMission/Mission.cpp +++ b/dGame/dMission/Mission.cpp @@ -518,24 +518,11 @@ void Mission::YieldRewards() { if (info->reward_reputation > 0) { missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_EARN_REPUTATION, 0, 0L, "", info->reward_reputation); - auto character = entity->GetCharacter(); - if (!character) return; - - auto charId = character->GetID(); - auto propertyCloneId = character->GetPropertyCloneID(); - - auto reputationUpdate = Database::CreatePreppedStmt("UPDATE properties SET reputation = reputation + ? where owner_id = ? AND clone_id = ?"); - - reputationUpdate->setInt64(1, info->reward_reputation); - reputationUpdate->setInt(2, charId); - reputationUpdate->setInt64(3, propertyCloneId); - - reputationUpdate->executeUpdate(); - - delete reputationUpdate; - reputationUpdate = nullptr; - - GameMessages::SendUpdateReputation(entity->GetObjectID(), info->reward_reputation, entity->GetSystemAddress()); + auto character = entity->GetComponent(); + if (character) { + character->SetReputation(character->GetReputation() + info->reward_reputation); + GameMessages::SendUpdateReputation(entity->GetObjectID(), character->GetReputation(), entity->GetSystemAddress()); + } } if (info->reward_maxhealth > 0) { From 4bc5c8194f7570c60eda36d1c8850f2dc20e4c23 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 31 Mar 2022 18:18:13 -0700 Subject: [PATCH 145/251] Added reputation tracker in charxml --- dGame/dComponents/CharacterComponent.cpp | 8 +++++++- dGame/dComponents/CharacterComponent.h | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/dGame/dComponents/CharacterComponent.cpp b/dGame/dComponents/CharacterComponent.cpp index 3daa437e..4e9f4318 100644 --- a/dGame/dComponents/CharacterComponent.cpp +++ b/dGame/dComponents/CharacterComponent.cpp @@ -256,7 +256,11 @@ void CharacterComponent::LoadFromXML() { Game::logger->Log("CharacterComponent", "Failed to find char tag while loading XML!\n"); return; } - + if (character->QueryAttribute("rpt", &m_Reputation) == tinyxml2::XML_NO_ATTRIBUTE) { + SetReputation(0); + } + + Game::logger->Log("CharacterComponent", "error is %i", character->QueryAttribute("rpt", &m_Reputation)); character->QueryInt64Attribute("ls", &m_Uscore); // Load the statistics @@ -378,6 +382,8 @@ void CharacterComponent::UpdateXml(tinyxml2::XMLDocument* doc) { } character->SetAttribute("ls", m_Uscore); + // Custom attribute to keep track of reputation. + character->SetAttribute("rpt", GetReputation()); character->SetAttribute("stt", StatisticsToString().c_str()); // Set the zone statistics of the form ... diff --git a/dGame/dComponents/CharacterComponent.h b/dGame/dComponents/CharacterComponent.h index 62076fad..04245bf9 100644 --- a/dGame/dComponents/CharacterComponent.h +++ b/dGame/dComponents/CharacterComponent.h @@ -146,6 +146,18 @@ public: */ bool GetPvpEnabled() const; + /** + * Returns the characters lifetime reputation + * @return The lifetime reputation of this character. + */ + int64_t GetReputation() { return m_Reputation; }; + + /** + * Sets the lifetime reputation of the character to newValue + * @param newValue the value to set reputation to + */ + void SetReputation(int64_t newValue) { m_Reputation = newValue; }; + /** * Sets the current value of PvP combat being enabled * @param value whether to enable PvP combat @@ -291,6 +303,11 @@ private: */ int64_t m_Uscore; + /** + * The lifetime reputation earned by the entity + */ + int64_t m_Reputation; + /** * Whether the character is landing by rocket */ From 8379fba07990d4a54c9de38b06598cb822945e02 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 31 Mar 2022 18:46:56 -0700 Subject: [PATCH 146/251] added initializer --- dGame/dComponents/CharacterComponent.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/dGame/dComponents/CharacterComponent.cpp b/dGame/dComponents/CharacterComponent.cpp index 4e9f4318..b0561fc6 100644 --- a/dGame/dComponents/CharacterComponent.cpp +++ b/dGame/dComponents/CharacterComponent.cpp @@ -32,6 +32,7 @@ CharacterComponent::CharacterComponent(Entity* parent, Character* character) : C m_EditorEnabled = false; m_EditorLevel = m_GMLevel; + m_Reputation = 0; m_CurrentActivity = 0; m_CountryCode = 0; From acbd46afcb34abee3c7378079ad13dcc4ef3f8ad Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 31 Mar 2022 20:55:47 -0700 Subject: [PATCH 147/251] Removed debug log --- dGame/dComponents/CharacterComponent.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/dGame/dComponents/CharacterComponent.cpp b/dGame/dComponents/CharacterComponent.cpp index b0561fc6..590758b6 100644 --- a/dGame/dComponents/CharacterComponent.cpp +++ b/dGame/dComponents/CharacterComponent.cpp @@ -261,7 +261,6 @@ void CharacterComponent::LoadFromXML() { SetReputation(0); } - Game::logger->Log("CharacterComponent", "error is %i", character->QueryAttribute("rpt", &m_Reputation)); character->QueryInt64Attribute("ls", &m_Uscore); // Load the statistics From ec463dd4c84f38b5e2eaebf93bd4a13443105087 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Fri, 1 Apr 2022 04:14:15 -0700 Subject: [PATCH 148/251] Added a GM send after QB complete --- dGame/dComponents/RebuildComponent.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/dGame/dComponents/RebuildComponent.cpp b/dGame/dComponents/RebuildComponent.cpp index 7d4ae926..ef970d98 100644 --- a/dGame/dComponents/RebuildComponent.cpp +++ b/dGame/dComponents/RebuildComponent.cpp @@ -380,7 +380,7 @@ void RebuildComponent::StartRebuild(Entity* user) { EntityManager::Instance()->SerializeEntity(user); - GameMessages::SendRebuildNotifyState(m_Parent, m_State, eRebuildState::REBUILD_COMPLETED, user->GetObjectID()); + GameMessages::SendRebuildNotifyState(m_Parent, m_State, eRebuildState::REBUILD_BUILDING, user->GetObjectID()); GameMessages::SendEnableRebuild(m_Parent, true, false, false, eFailReason::REASON_NOT_GIVEN, 0.0f, user->GetObjectID()); m_State = eRebuildState::REBUILD_BUILDING; @@ -421,7 +421,10 @@ void RebuildComponent::CompleteRebuild(Entity* user) { EntityManager::Instance()->SerializeEntity(user); GameMessages::SendRebuildNotifyState(m_Parent, m_State, eRebuildState::REBUILD_COMPLETED, user->GetObjectID()); - GameMessages::SendEnableRebuild(m_Parent, false, true, false, eFailReason::REASON_NOT_GIVEN, m_ResetTime, user->GetObjectID()); + GameMessages::SendPlayFXEffect(m_Parent, 507, u"create", "BrickFadeUpVisCompleteEffect", LWOOBJID_EMPTY, 0.4f, 1.0f, true); + GameMessages::SendEnableRebuild(m_Parent, false, false, true, eFailReason::REASON_NOT_GIVEN, m_ResetTime, user->GetObjectID()); + GameMessages::SendTerminateInteraction(user->GetObjectID(), eTerminateType::FROM_INTERACTION, m_Parent->GetObjectID()); + m_State = eRebuildState::REBUILD_COMPLETED; m_Timer = 0.0f; @@ -429,9 +432,6 @@ void RebuildComponent::CompleteRebuild(Entity* user) { EntityManager::Instance()->SerializeEntity(m_Parent); - GameMessages::SendPlayFXEffect(m_Parent, 507, u"create", "BrickFadeUpVisCompleteEffect", LWOOBJID_EMPTY, 0.4f, 1.0f, true); - GameMessages::SendTerminateInteraction(user->GetObjectID(), eTerminateType::FROM_INTERACTION, m_Parent->GetObjectID()); - // Removes extra item requirements, isn't live accurate. // In live, all items were removed at the start of the quickbuild, then returned if it was cancelled. // TODO: fix? @@ -484,6 +484,7 @@ void RebuildComponent::CompleteRebuild(Entity* user) { character->SetPlayerFlag(flagNumber, true); } } + GameMessages::SendPlayAnimation(user, u"rebuild-celebrate", 1.09f); } void RebuildComponent::ResetRebuild(bool failed) { From 9d79fc3d2eb78fee124d6d574caf490123ebc7c8 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 5 Apr 2022 05:11:06 -0700 Subject: [PATCH 149/251] resolved MacOS compilation warnings --- dGame/TradingManager.cpp | 4 ++-- dGame/dComponents/BuffComponent.h | 2 +- dGame/dComponents/ControllablePhysicsComponent.h | 2 +- dGame/dComponents/MissionComponent.h | 4 ++-- dGame/dComponents/ModuleAssemblyComponent.h | 2 +- dGame/dComponents/MovementAIComponent.h | 2 +- dGame/dComponents/VendorComponent.h | 2 +- dScripts/AmDrawBridge.h | 2 +- dScripts/BaseConsoleTeleportServer.cpp | 2 +- dScripts/GfCampfire.h | 8 ++++---- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/dGame/TradingManager.cpp b/dGame/TradingManager.cpp index d0ec08d8..0963aa6f 100644 --- a/dGame/TradingManager.cpp +++ b/dGame/TradingManager.cpp @@ -60,7 +60,7 @@ void Trade::SetCoins(LWOOBJID participant, uint64_t coins) { m_CoinsA = coins; } - else if (participant = m_ParticipantB) + else if (participant == m_ParticipantB) { m_CoinsB = coins; } @@ -72,7 +72,7 @@ void Trade::SetItems(LWOOBJID participant, std::vector items) { m_ItemsA = items; } - else if (participant = m_ParticipantB) + else if (participant == m_ParticipantB) { m_ItemsB = items; } diff --git a/dGame/dComponents/BuffComponent.h b/dGame/dComponents/BuffComponent.h index 68cd5309..ba22c08b 100644 --- a/dGame/dComponents/BuffComponent.h +++ b/dGame/dComponents/BuffComponent.h @@ -51,7 +51,7 @@ public: void LoadFromXML(tinyxml2::XMLDocument* doc); - void UpdateXml(tinyxml2::XMLDocument* doc); + void UpdateXml(tinyxml2::XMLDocument* doc) override; void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); diff --git a/dGame/dComponents/ControllablePhysicsComponent.h b/dGame/dComponents/ControllablePhysicsComponent.h index 1c1a4f44..f0fe7461 100644 --- a/dGame/dComponents/ControllablePhysicsComponent.h +++ b/dGame/dComponents/ControllablePhysicsComponent.h @@ -23,7 +23,7 @@ public: ControllablePhysicsComponent(Entity* entity); ~ControllablePhysicsComponent() override; - void Update(float deltaTime); + void Update(float deltaTime) override; void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); void LoadFromXML(tinyxml2::XMLDocument* doc); void ResetFlags(); diff --git a/dGame/dComponents/MissionComponent.h b/dGame/dComponents/MissionComponent.h index 6e54a6b0..13a812d2 100644 --- a/dGame/dComponents/MissionComponent.h +++ b/dGame/dComponents/MissionComponent.h @@ -29,8 +29,8 @@ public: explicit MissionComponent(Entity* parent); ~MissionComponent() override; void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); - void LoadFromXml(tinyxml2::XMLDocument* doc); - void UpdateXml(tinyxml2::XMLDocument* doc); + void LoadFromXml(tinyxml2::XMLDocument* doc) override; + void UpdateXml(tinyxml2::XMLDocument* doc) override; /** * Returns all the missions for this entity, mapped by mission ID diff --git a/dGame/dComponents/ModuleAssemblyComponent.h b/dGame/dComponents/ModuleAssemblyComponent.h index 28dcfa70..7153f30b 100644 --- a/dGame/dComponents/ModuleAssemblyComponent.h +++ b/dGame/dComponents/ModuleAssemblyComponent.h @@ -17,7 +17,7 @@ public: ~ModuleAssemblyComponent() override; void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); - void Update(float deltaTime); + void Update(float deltaTime) override; /** * Sets the subkey of this entity diff --git a/dGame/dComponents/MovementAIComponent.h b/dGame/dComponents/MovementAIComponent.h index 477c39f4..032732cc 100644 --- a/dGame/dComponents/MovementAIComponent.h +++ b/dGame/dComponents/MovementAIComponent.h @@ -61,7 +61,7 @@ public: MovementAIComponent(Entity* parentEntity, MovementAIInfo info); ~MovementAIComponent() override; - void Update(float deltaTime); + void Update(float deltaTime) override; /** * Returns the basic settings that this entity uses to move around diff --git a/dGame/dComponents/VendorComponent.h b/dGame/dComponents/VendorComponent.h index 71297be9..fb9dbf6b 100644 --- a/dGame/dComponents/VendorComponent.h +++ b/dGame/dComponents/VendorComponent.h @@ -19,7 +19,7 @@ public: void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); - void OnUse(Entity* originator); + void OnUse(Entity* originator) override; /** * Gets the buy scaler diff --git a/dScripts/AmDrawBridge.h b/dScripts/AmDrawBridge.h index 1b00e2be..e7b801df 100644 --- a/dScripts/AmDrawBridge.h +++ b/dScripts/AmDrawBridge.h @@ -7,7 +7,7 @@ public: void OnStartup(Entity* self) override; void OnUse(Entity* self, Entity* user) override; void OnTimerDone(Entity* self, std::string timerName) override; - void OnNotifyObject(Entity *self, Entity *sender, const std::string& name, int32_t param1 = 0, int32_t param2 = 0); + void OnNotifyObject(Entity *self, Entity *sender, const std::string& name, int32_t param1 = 0, int32_t param2 = 0) override; void MoveBridgeDown(Entity* self, Entity* bridge, bool down); void NotifyDie(Entity* self, Entity* other); diff --git a/dScripts/BaseConsoleTeleportServer.cpp b/dScripts/BaseConsoleTeleportServer.cpp index b4e88af7..a9cd74e8 100644 --- a/dScripts/BaseConsoleTeleportServer.cpp +++ b/dScripts/BaseConsoleTeleportServer.cpp @@ -25,7 +25,7 @@ void BaseConsoleTeleportServer::BaseOnMessageBoxResponse(Entity* self, Entity* s if (rocketLaunchComponent == nullptr) { - rocketLaunchComponent; + return; } const auto& teleportZone = self->GetVar(u"transferZoneID"); diff --git a/dScripts/GfCampfire.h b/dScripts/GfCampfire.h index 668e7c1d..9e678419 100644 --- a/dScripts/GfCampfire.h +++ b/dScripts/GfCampfire.h @@ -4,11 +4,11 @@ class GfCampfire : public CppScripts::Script { public: - void OnStartup(Entity* self); + void OnStartup(Entity* self) override; void OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1, int32_t param2, - int32_t param3); - void OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status); - void OnTimerDone(Entity* self, std::string timerName); + int32_t param3) override; + void OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) override; + void OnTimerDone(Entity* self, std::string timerName) override; void OnSkillEventFired(Entity *self, Entity *caster, const std::string &message) override; private: int32_t m_skillCastId = 43; From bd0926e0a5e67cf0585f7008066d1271d4b21669 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 6 Apr 2022 22:21:08 -0700 Subject: [PATCH 150/251] special case for pets --- dGame/Entity.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 6515b9b4..bca7ffa2 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -231,7 +231,8 @@ void Entity::Initialize() m_Components.insert(std::make_pair(COMPONENT_TYPE_RACING_STATS, nullptr)); } - if (compRegistryTable->GetByIDAndType(m_TemplateID, COMPONENT_TYPE_ITEM) > 0) { + PetComponent* petComponent; + if (compRegistryTable->GetByIDAndType(m_TemplateID, COMPONENT_TYPE_ITEM) > 0 && !TryGetComponent(COMPONENT_TYPE_PET, petComponent)) { m_Components.insert(std::make_pair(COMPONENT_TYPE_ITEM, nullptr)); } From 4b0ab2380c679a8aabda506ad86e98ef6566787d Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 6 Apr 2022 22:21:17 -0700 Subject: [PATCH 151/251] Client does calcs --- dGame/dGameMessages/GameMessages.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index d2dcc54b..e6d7a164 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -3676,7 +3676,7 @@ void GameMessages::HandlePetTamingTryBuild(RakNet::BitStream* inStream, Entity* return; } - petComponent->TryBuild(bricks, clientFailed); + petComponent->TryBuild(bricks.size(), clientFailed); } void GameMessages::HandleNotifyTamingBuildSuccess(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) From 5eb801eb12eb84a9db3af9a10289285544c4c154 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 6 Apr 2022 22:21:29 -0700 Subject: [PATCH 152/251] uses number of bricks now --- dGame/dComponents/PetComponent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dComponents/PetComponent.h b/dGame/dComponents/PetComponent.h index 76afaff6..845cfe31 100644 --- a/dGame/dComponents/PetComponent.h +++ b/dGame/dComponents/PetComponent.h @@ -39,7 +39,7 @@ public: * @param bricks the bricks to try to complete the minigame with * @param clientFailed unused */ - void TryBuild(std::vector& bricks, bool clientFailed); + void TryBuild(uint32_t numBricks, bool clientFailed); /** * Handles a notification from the client regarding the completion of the pet minigame, adding the pet to their From e73793c1a3359bee1e3dad8b797cd2445f3b45d4 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 6 Apr 2022 22:21:54 -0700 Subject: [PATCH 153/251] removed unnccessary work --- dGame/dComponents/PetComponent.cpp | 98 ++++-------------------------- 1 file changed, 13 insertions(+), 85 deletions(-) diff --git a/dGame/dComponents/PetComponent.cpp b/dGame/dComponents/PetComponent.cpp index e605908f..6b10dccf 100644 --- a/dGame/dComponents/PetComponent.cpp +++ b/dGame/dComponents/PetComponent.cpp @@ -263,29 +263,12 @@ void PetComponent::OnUse(Entity* originator) auto position = originatorPosition; - NiPoint3 forward = NiQuaternion::LookAt(m_Parent->GetPosition(), originator->GetPosition()).GetForwardVector(); //m_Parent->GetRotation().GetForwardVector(); + NiPoint3 forward = NiQuaternion::LookAt(m_Parent->GetPosition(), originator->GetPosition()).GetForwardVector(); forward.y = 0; if (dpWorld::Instance().IsLoaded()) { - /* - if (interactionDistance > 2) - { - interactionDistance -= 1; - } - */ - NiPoint3 attempt = petPosition + forward * interactionDistance; - - /* - float deg = std::atan2(petPosition.z - originatorPosition.z, petPosition.x - originatorPosition.x); //* 180 / M_PI; - - auto position = NiPoint3( - petPosition.x + interactionDistance * std::cos(-deg), - petPosition.y, - petPosition.z + interactionDistance * std::sin(-deg) - ); - */ float y = dpWorld::Instance().GetHeightAtPoint(attempt); @@ -309,8 +292,6 @@ void PetComponent::OnUse(Entity* originator) auto rotation = NiQuaternion::LookAt(position, petPosition); - - //GameMessages::SendTeleport(originator->GetObjectID(), position, rotation, originator->GetSystemAddress(), true); GameMessages::SendNotifyPetTamingMinigame( originator->GetObjectID(), @@ -532,14 +513,12 @@ void PetComponent::Update(float deltaTime) m_Timer = 1; } -void PetComponent::TryBuild(std::vector& bricks, bool clientFailed) -{ +void PetComponent::TryBuild(uint32_t numBricks, bool clientFailed) { if (m_Tamer == LWOOBJID_EMPTY) return; auto* tamer = EntityManager::Instance()->GetEntity(m_Tamer); - if (tamer == nullptr) - { + if (tamer == nullptr) { m_Tamer = LWOOBJID_EMPTY; return; @@ -547,19 +526,11 @@ void PetComponent::TryBuild(std::vector& bricks, bool clientFailed) const auto& cached = buildCache.find(m_Parent->GetLOT()); - if (cached == buildCache.end()) - { - GameMessages::SendPetTamingTryBuildResult(m_Tamer, false, 0, tamer->GetSystemAddress()); - - return; - } + if (cached == buildCache.end()) return; auto* destroyableComponent = tamer->GetComponent(); - - if (destroyableComponent == nullptr) - { - return; - } + + if (destroyableComponent == nullptr) return; auto imagination = destroyableComponent->GetImagination(); @@ -569,59 +540,17 @@ void PetComponent::TryBuild(std::vector& bricks, bool clientFailed) EntityManager::Instance()->SerializeEntity(tamer); - const auto& trueBricks = BrickDatabase::Instance()->GetBricks(cached->second.buildFile); - - if (trueBricks.empty() || bricks.empty()) - { - GameMessages::SendPetTamingTryBuildResult(m_Tamer, false, 0, tamer->GetSystemAddress()); - - return; - } - - auto* brickIDTable = CDClientManager::Instance()->GetTable("BrickIDTable"); - - int32_t correct = 0; - - for (const auto& brick : bricks) - { - const auto brickEntries = brickIDTable->Query([brick](const CDBrickIDTable& entry) - { - return entry.NDObjectID == brick.designerID; - }); - - if (brickEntries.empty()) - { - continue; - } - - const auto designerID = brickEntries[0].LEGOBrickID; - - for (const auto& trueBrick : trueBricks) - { - if (designerID == trueBrick.designerID && brick.materialID == trueBrick.materialID) - { - correct++; - - break; - } - } - } - - const auto success = correct >= cached->second.numValidPieces; - - GameMessages::SendPetTamingTryBuildResult(m_Tamer, success, correct, tamer->GetSystemAddress()); - - if (!success) - { - if (imagination < cached->second.imaginationCost) - { + if (clientFailed) { + if (imagination < cached->second.imaginationCost) { ClientFailTamingMinigame(); } - } - else - { + } else { m_Timer = 0; } + + if (numBricks == 0) return; + + GameMessages::SendPetTamingTryBuildResult(m_Tamer, !clientFailed, numBricks, tamer->GetSystemAddress()); } void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) @@ -727,7 +656,6 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) if (missionComponent != nullptr) { - //missionComponent->ForceProgress(506, 768, 1, false); missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_PET_TAMING, m_Parent->GetLOT()); } From 7030d937b15b0bdac3107e171852139943154431 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 6 Apr 2022 22:24:50 -0700 Subject: [PATCH 154/251] dirty bit --- dGame/dComponents/PetComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dComponents/PetComponent.cpp b/dGame/dComponents/PetComponent.cpp index 6b10dccf..a5c1168d 100644 --- a/dGame/dComponents/PetComponent.cpp +++ b/dGame/dComponents/PetComponent.cpp @@ -81,7 +81,7 @@ void PetComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpd { const bool tamed = m_Owner != LWOOBJID_EMPTY; - outBitStream->Write1(); // Dirty? + outBitStream->Write1(); // Always serialize as dirty for now outBitStream->Write(static_cast(m_Status)); outBitStream->Write(static_cast(tamed ? m_Ability : PetAbilityType::Invalid)); // Something with the overhead icon? From 5a76cb3b441a56b3e9cd43bc448b13a3cef48f8d Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Fri, 8 Apr 2022 19:36:43 -0700 Subject: [PATCH 155/251] fixed erronous log --- dGame/dGameMessages/GameMessages.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index d2dcc54b..1fd6de64 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -3238,12 +3238,12 @@ void GameMessages::HandleClientTradeRequest(RakNet::BitStream* inStream, Entity* void GameMessages::HandleClientTradeCancel(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { - Game::logger->Log("GameMessages", "Trade canceled from (%llu)\n", entity->GetObjectID()); - auto* trade = TradingManager::Instance()->GetPlayerTrade(entity->GetObjectID()); if (trade == nullptr) return; + Game::logger->Log("GameMessages", "Trade canceled from (%llu)\n", entity->GetObjectID()); + TradingManager::Instance()->CancelTrade(trade->GetTradeId()); } From 96f1c0a70980d8871a957c17dcfb64c30b5c327f Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Fri, 8 Apr 2022 20:19:27 -0700 Subject: [PATCH 156/251] Fixed skills proxies --- dGame/dComponents/InventoryComponent.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index 56bf26d8..63080b2d 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -1229,19 +1229,19 @@ void InventoryComponent::AddItemSkills(const LOT lot) const auto index = m_Skills.find(slot); - if (index != m_Skills.end()) - { - const auto old = index->second; - - GameMessages::SendRemoveSkill(m_Parent, old); - } - const auto skill = FindSkill(lot); if (skill == 0) { return; } + + if (index != m_Skills.end()) + { + const auto old = index->second; + + GameMessages::SendRemoveSkill(m_Parent, old); + } GameMessages::SendAddSkill(m_Parent, skill, static_cast(slot)); From 0a494422b7647420b61b02f9f7cccd17534e85a1 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 9 Apr 2022 00:21:20 -0700 Subject: [PATCH 157/251] Added migration for plunger gun --- migrations/cdserver/3_plunger_gun_fix.sql | 1 + 1 file changed, 1 insertion(+) create mode 100644 migrations/cdserver/3_plunger_gun_fix.sql diff --git a/migrations/cdserver/3_plunger_gun_fix.sql b/migrations/cdserver/3_plunger_gun_fix.sql new file mode 100644 index 00000000..3d33592e --- /dev/null +++ b/migrations/cdserver/3_plunger_gun_fix.sql @@ -0,0 +1 @@ +UPDATE ItemComponent SET itemType = 5 where id = 7082; From 3900267fed72365f59f1c941f97ae14493bcc2d3 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 9 Apr 2022 00:31:18 -0700 Subject: [PATCH 158/251] added comment --- migrations/cdserver/3_plunger_gun_fix.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/migrations/cdserver/3_plunger_gun_fix.sql b/migrations/cdserver/3_plunger_gun_fix.sql index 3d33592e..35654e8b 100644 --- a/migrations/cdserver/3_plunger_gun_fix.sql +++ b/migrations/cdserver/3_plunger_gun_fix.sql @@ -1 +1,2 @@ +-- File added April 9th, 2022 UPDATE ItemComponent SET itemType = 5 where id = 7082; From 77c6350f03045254edec4a84b60dc186a35b4f70 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 9 Apr 2022 00:48:14 -0700 Subject: [PATCH 159/251] updated initial migration Made it so people wont accidentally wipe their database if 0_initial.sql is ever run again --- migrations/dlu/0_initial.sql | 48 ++++++++++++------------------------ 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/migrations/dlu/0_initial.sql b/migrations/dlu/0_initial.sql index 16cb3e7e..522e556f 100644 --- a/migrations/dlu/0_initial.sql +++ b/migrations/dlu/0_initial.sql @@ -1,5 +1,4 @@ -DROP TABLE IF EXISTS accounts; -CREATE TABLE accounts ( +CREATE TABLE IF NOT EXISTS accounts ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(35) NOT NULL UNIQUE, password TEXT NOT NULL, @@ -11,8 +10,7 @@ CREATE TABLE accounts ( mute_expire BIGINT UNSIGNED NOT NULL DEFAULT 0 ); -DROP TABLE IF EXISTS charinfo; -CREATE TABLE charinfo ( +CREATE TABLE IF NOT EXISTS charinfo ( id BIGINT NOT NULL PRIMARY KEY, account_id INT NOT NULL REFERENCES accounts(id), name VARCHAR(35) NOT NULL, @@ -23,21 +21,18 @@ CREATE TABLE charinfo ( permission_map BIGINT UNSIGNED NOT NULL DEFAULT 0 ); -DROP TABLE IF EXISTS charxml; -CREATE TABLE charxml ( +CREATE TABLE IF NOT EXISTS charxml ( id BIGINT NOT NULL PRIMARY KEY REFERENCES charinfo(id), xml_data LONGTEXT NOT NULL ); -DROP TABLE IF EXISTS command_log; -CREATE TABLE command_log ( +CREATE TABLE IF NOT EXISTS command_log ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, character_id BIGINT NOT NULL REFERENCES charinfo(id), command VARCHAR(256) NOT NULL ); -DROP TABLE IF EXISTS friends; -CREATE TABLE friends ( +CREATE TABLE IF NOT EXISTS friends ( player_id BIGINT NOT NULL REFERENCES charinfo(id), friend_id BIGINT NOT NULL REFERENCES charinfo(id), best_friend BOOLEAN NOT NULL DEFAULT FALSE, @@ -45,8 +40,7 @@ CREATE TABLE friends ( PRIMARY KEY (player_id, friend_id) ); -DROP TABLE IF EXISTS leaderboard; -CREATE TABLE leaderboard ( +CREATE TABLE IF NOT EXISTS leaderboard ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, game_id INT UNSIGNED NOT NULL DEFAULT 0, last_played TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP(), @@ -55,8 +49,7 @@ CREATE TABLE leaderboard ( score BIGINT UNSIGNED NOT NULL DEFAULT 0 ); -DROP TABLE IF EXISTS mail; -CREATE TABLE mail ( +CREATE TABLE IF NOT EXISTS mail ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, sender_id INT NOT NULL DEFAULT 0, sender_name VARCHAR(35) NOT NULL DEFAULT '', @@ -72,20 +65,17 @@ CREATE TABLE mail ( was_read BOOLEAN NOT NULL DEFAULT FALSE ); -DROP TABLE IF EXISTS object_id_tracker; -CREATE TABLE object_id_tracker ( +CREATE TABLE IF NOT EXISTS object_id_tracker ( last_object_id BIGINT UNSIGNED NOT NULL DEFAULT 0 PRIMARY KEY ); -DROP TABLE IF EXISTS pet_names; -CREATE TABLE pet_names ( +CREATE TABLE IF NOT EXISTS pet_names ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, pet_name TEXT NOT NULL, approved INT UNSIGNED NOT NULL ); -DROP TABLE IF EXISTS play_keys; -CREATE TABLE play_keys ( +CREATE TABLE IF NOT EXISTS play_keys ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, key_string CHAR(19) NOT NULL UNIQUE, key_uses INT NOT NULL DEFAULT 1, @@ -93,8 +83,7 @@ CREATE TABLE play_keys ( active BOOLEAN NOT NULL DEFAULT TRUE ); -DROP TABLE IF EXISTS properties; -CREATE TABLE properties ( +CREATE TABLE IF NOT EXISTS properties ( id BIGINT NOT NULL PRIMARY KEY, owner_id BIGINT NOT NULL REFERENCES charinfo(id), template_id INT UNSIGNED NOT NULL, @@ -112,8 +101,7 @@ CREATE TABLE properties ( zone_id INT NOT NULL ); -DROP TABLE IF EXISTS ugc; -CREATE TABLE ugc ( +CREATE TABLE IF NOT EXISTS ugc ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, account_id INT NOT NULL REFERENCES accounts(id), character_id BIGINT NOT NULL REFERENCES charinfo(id), @@ -123,8 +111,7 @@ CREATE TABLE ugc ( filename TEXT NOT NULL DEFAULT ('') ); -DROP TABLE IF EXISTS properties_contents; -CREATE TABLE properties_contents ( +CREATE TABLE IF NOT EXISTS properties_contents ( id BIGINT NOT NULL PRIMARY KEY, property_id BIGINT NOT NULL REFERENCES properties(id), ugc_id INT NULL REFERENCES ugc(id), @@ -138,8 +125,7 @@ CREATE TABLE properties_contents ( rw FLOAT NOT NULL ); -DROP TABLE IF EXISTS activity_log; -CREATE TABLE activity_log ( +CREATE TABLE IF NOT EXISTS activity_log ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, character_id BIGINT NOT NULL REFERENCES charinfo(id), activity INT NOT NULL, @@ -147,8 +133,7 @@ CREATE TABLE activity_log ( map_id INT NOT NULL ); -DROP TABLE IF EXISTS bug_reports; -CREATE TABLE bug_reports ( +CREATE TABLE IF NOT EXISTS bug_reports ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, body TEXT NOT NULL, client_version TEXT NOT NULL, @@ -157,8 +142,7 @@ CREATE TABLE bug_reports ( submitted TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP() ); -DROP TABLE IF EXISTS servers; -CREATE TABLE servers ( +CREATE TABLE IF NOT EXISTS servers ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name TEXT NOT NULL, ip TEXT NOT NULL, From fd13770e878ef5f337f3fe64f63b085760e49154 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 9 Apr 2022 14:17:31 -0700 Subject: [PATCH 160/251] Sped up server shutdown --- dMasterServer/MasterServer.cpp | 10 ++++++++++ dWorldServer/WorldServer.cpp | 4 ---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/dMasterServer/MasterServer.cpp b/dMasterServer/MasterServer.cpp index f307151f..0876eaa6 100644 --- a/dMasterServer/MasterServer.cpp +++ b/dMasterServer/MasterServer.cpp @@ -751,6 +751,14 @@ void ShutdownSequence() { Game::logger->Log("MasterServer", "Attempting to shutdown instances, max 60 seconds...\n"); while (true) { + + auto packet = Game::server->Receive(); + if (packet) { + HandlePacket(packet); + Game::server->DeallocatePacket(packet); + packet = nullptr; + } + auto done = true; for (auto* instance : Game::im->GetInstances()) { @@ -764,6 +772,7 @@ void ShutdownSequence() { } if (done) { + Game::logger->Log("MasterServer", "Finished shutting down naturally!\n"); break; } @@ -773,6 +782,7 @@ void ShutdownSequence() { ticks++; if (ticks == 600 * 6) { + Game::logger->Log("MasterServer", "Finished shutting down by timeout!\n"); break; } } diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index c8f2641e..23bf9356 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -522,10 +522,6 @@ int main(int argc, char** argv) { CBITSTREAM; PacketUtils::WriteHeader(bitStream, MASTER, MSG_MASTER_SHUTDOWN_RESPONSE); Game::server->SendToMaster(&bitStream); - } - - if (framesSinceShutdownSequence == 300) - { break; } } From 3e60b9db4ad3d8e398e73f5f8fdd9082964d9fc5 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 9 Apr 2022 15:35:01 -0700 Subject: [PATCH 161/251] Destroying database specifier --- dAuthServer/AuthServer.cpp | 4 ++-- dChatServer/ChatServer.cpp | 4 ++-- dDatabase/Database.cpp | 5 +++-- dDatabase/Database.h | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/dAuthServer/AuthServer.cpp b/dAuthServer/AuthServer.cpp index 67590fa0..c7f51487 100644 --- a/dAuthServer/AuthServer.cpp +++ b/dAuthServer/AuthServer.cpp @@ -57,7 +57,7 @@ int main(int argc, char** argv) { Database::Connect(mysql_host, mysql_database, mysql_username, mysql_password); } catch (sql::SQLException& ex) { Game::logger->Log("AuthServer", "Got an error while connecting to the database: %s\n", ex.what()); - Database::Destroy(); + Database::Destroy("AuthServer"); delete Game::server; delete Game::logger; return 0; @@ -143,7 +143,7 @@ int main(int argc, char** argv) { } //Delete our objects here: - Database::Destroy(); + Database::Destroy("AuthServer"); delete Game::server; delete Game::logger; diff --git a/dChatServer/ChatServer.cpp b/dChatServer/ChatServer.cpp index 81904d41..7835737f 100644 --- a/dChatServer/ChatServer.cpp +++ b/dChatServer/ChatServer.cpp @@ -61,7 +61,7 @@ int main(int argc, char** argv) { } catch (sql::SQLException& ex) { Game::logger->Log("ChatServer", "Got an error while connecting to the database: %s\n", ex.what()); - Database::Destroy(); + Database::Destroy("ChatServer"); delete Game::server; delete Game::logger; return 0; @@ -150,7 +150,7 @@ int main(int argc, char** argv) { } //Delete our objects here: - Database::Destroy(); + Database::Destroy("ChatServer"); delete Game::server; delete Game::logger; diff --git a/dDatabase/Database.cpp b/dDatabase/Database.cpp index cdadbbaa..7ba138cf 100644 --- a/dDatabase/Database.cpp +++ b/dDatabase/Database.cpp @@ -26,9 +26,10 @@ void Database::Connect(const string& host, const string& database, const string& con->setClientOption("MYSQL_OPT_RECONNECT", &myTrue); } //Connect -void Database::Destroy() { +void Database::Destroy(std::string source) { if (!con) return; - Game::logger->Log("Database", "Destroying MySQL connection!\n"); + if (source != "") Game::logger->Log("Database", "Destroying MySQL connection from %s!\n", source.c_str()); + else Game::logger->Log("Database", "Destroying MySQL connection!\n"); con->close(); delete con; } //Destroy diff --git a/dDatabase/Database.h b/dDatabase/Database.h index 8e4cf5dc..6e458065 100644 --- a/dDatabase/Database.h +++ b/dDatabase/Database.h @@ -22,7 +22,7 @@ private: public: static void Connect(const std::string& host, const std::string& database, const std::string& username, const std::string& password); - static void Destroy(); + static void Destroy(std::string source=""); static sql::Statement* CreateStmt(); static sql::PreparedStatement* CreatePreppedStmt(const std::string& query); }; From d085c0cf10f22787176b0e5e3311a4eb0db05346 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 9 Apr 2022 15:35:40 -0700 Subject: [PATCH 162/251] correct exit --- dMasterServer/MasterServer.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/dMasterServer/MasterServer.cpp b/dMasterServer/MasterServer.cpp index 0876eaa6..2fbee693 100644 --- a/dMasterServer/MasterServer.cpp +++ b/dMasterServer/MasterServer.cpp @@ -47,6 +47,7 @@ namespace Game { bool shutdownSequenceStarted = false; void ShutdownSequence(); +int FinalizeShutdown(); dLogger* SetupLogger(); void StartAuthServer(); void StartChatServer(); @@ -168,7 +169,7 @@ int main(int argc, char** argv) { std::cout << "Account created successfully!\n"; - Database::Destroy(); + Database::Destroy("MasterServer"); delete Game::logger; return EXIT_SUCCESS; @@ -318,14 +319,8 @@ int main(int argc, char** argv) { t += std::chrono::milliseconds(highFrameRate); std::this_thread::sleep_until(t); } - - //Delete our objects here: - Database::Destroy(); - delete Game::im; - delete Game::server; - delete Game::logger; - - return EXIT_SUCCESS; + FinalizeShutdown(); + exit(0); } dLogger* SetupLogger() { @@ -787,5 +782,15 @@ void ShutdownSequence() { } } - exit(0); + FinalizeShutdown(); } + +int FinalizeShutdown() { + //Delete our objects here: + Database::Destroy("MasterServer"); + delete Game::im; + delete Game::server; + delete Game::logger; + + exit(0); +} \ No newline at end of file From 1efbe2d2c0feebbd746fc3f0c84ecc9dd0087232 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 9 Apr 2022 15:57:18 -0700 Subject: [PATCH 163/251] added returns --- dAuthServer/AuthServer.cpp | 3 ++- dChatServer/ChatServer.cpp | 3 ++- dMasterServer/MasterServer.cpp | 8 +++++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/dAuthServer/AuthServer.cpp b/dAuthServer/AuthServer.cpp index c7f51487..fef3124b 100644 --- a/dAuthServer/AuthServer.cpp +++ b/dAuthServer/AuthServer.cpp @@ -147,7 +147,8 @@ int main(int argc, char** argv) { delete Game::server; delete Game::logger; - return 0; + exit(EXIT_SUCCESS); + return EXIT_SUCCESS; } dLogger * SetupLogger() { diff --git a/dChatServer/ChatServer.cpp b/dChatServer/ChatServer.cpp index 7835737f..9ba3ba1b 100644 --- a/dChatServer/ChatServer.cpp +++ b/dChatServer/ChatServer.cpp @@ -154,7 +154,8 @@ int main(int argc, char** argv) { delete Game::server; delete Game::logger; - return 0; + exit(EXIT_SUCCESS); + return EXIT_SUCCESS; } dLogger * SetupLogger() { diff --git a/dMasterServer/MasterServer.cpp b/dMasterServer/MasterServer.cpp index 2fbee693..959d5b99 100644 --- a/dMasterServer/MasterServer.cpp +++ b/dMasterServer/MasterServer.cpp @@ -320,7 +320,8 @@ int main(int argc, char** argv) { std::this_thread::sleep_until(t); } FinalizeShutdown(); - exit(0); + exit(EXIT_SUCCESS); + return EXIT_SUCCESS; } dLogger* SetupLogger() { @@ -740,7 +741,7 @@ void ShutdownSequence() { auto ticks = 0; if (!Game::im) { - exit(0); + exit(EXIT_SUCCESS); } Game::logger->Log("MasterServer", "Attempting to shutdown instances, max 60 seconds...\n"); @@ -792,5 +793,6 @@ int FinalizeShutdown() { delete Game::server; delete Game::logger; - exit(0); + exit(EXIT_SUCCESS); + return EXIT_SUCCESS; } \ No newline at end of file From aee329024882d6983e8fcc39a09bb7ff8a2675ab Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 9 Apr 2022 16:02:12 -0700 Subject: [PATCH 164/251] Update MasterServer.cpp --- dMasterServer/MasterServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dMasterServer/MasterServer.cpp b/dMasterServer/MasterServer.cpp index 959d5b99..8f41623e 100644 --- a/dMasterServer/MasterServer.cpp +++ b/dMasterServer/MasterServer.cpp @@ -768,7 +768,7 @@ void ShutdownSequence() { } if (done) { - Game::logger->Log("MasterServer", "Finished shutting down naturally!\n"); + Game::logger->Log("MasterServer", "Finished shutting down MasterServer!\n"); break; } From ae61b23896a39c30ee4178548ee85c2c723ac4a3 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 9 Apr 2022 16:02:27 -0700 Subject: [PATCH 165/251] Chat log no longer needed --- dWorldServer/WorldServer.cpp | 39 ++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index 23bf9356..7ff116a6 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -486,7 +486,7 @@ int main(int argc, char** argv) { const auto& player = Game::server->GetReplicaManager()->GetParticipantAtIndex(i); auto* entity = Player::GetPlayer(player); - + Game::logger->Log("WorldServer", "Saving data!\n"); if (entity != nullptr && entity->GetCharacter() != nullptr) { auto* skillComponent = entity->GetComponent(); @@ -495,35 +495,35 @@ int main(int argc, char** argv) { { skillComponent->Reset(); } - + std::string message = "Saving character " + entity->GetCharacter()->GetName() + "...\n"; + Game::logger->Log("WorldServer", message); entity->GetCharacter()->SaveXMLToDatabase(); + message = "Character data for " + entity->GetCharacter()->GetName() + " was saved!\n"; + Game::logger->Log("WorldServer", message); } } if (PropertyManagementComponent::Instance() != nullptr) { - ChatPackets::SendSystemMessage(UNASSIGNED_SYSTEM_ADDRESS, u"Property data saved...", true); + Game::logger->Log("WorldServer", "Saving ALL property data!\n"); PropertyManagementComponent::Instance()->Save(); + Game::logger->Log("WorldServer", "ALL property data saved!\n"); } - - ChatPackets::SendSystemMessage(UNASSIGNED_SYSTEM_ADDRESS, u"Character data saved...", true); + + Game::logger->Log("WorldServer", "ALL DATA HAS BEEN SAVED!\n"); } framesSinceShutdownSequence++; - if (framesSinceShutdownSequence == 100) - { - while (Game::server->GetReplicaManager()->GetParticipantCount() > 0) - { - const auto& player = Game::server->GetReplicaManager()->GetParticipantAtIndex(0); + while (Game::server->GetReplicaManager()->GetParticipantCount() > 0) { + const auto& player = Game::server->GetReplicaManager()->GetParticipantAtIndex(0); - Game::server->Disconnect(player, SERVER_DISCON_KICK); - } - - CBITSTREAM; - PacketUtils::WriteHeader(bitStream, MASTER, MSG_MASTER_SHUTDOWN_RESPONSE); - Game::server->SendToMaster(&bitStream); - break; + Game::server->Disconnect(player, SERVER_DISCON_KICK); } + + CBITSTREAM; + PacketUtils::WriteHeader(bitStream, MASTER, MSG_MASTER_SHUTDOWN_RESPONSE); + Game::server->SendToMaster(&bitStream); + break; } Metrics::AddMeasurement(MetricVariable::CPUTime, (1e6 * (1000.0 * (std::clock() - metricCPUTimeStart))) / CLOCKS_PER_SEC); @@ -537,14 +537,15 @@ int main(int argc, char** argv) { Game::logger->Log("WorldServer", "Shutdown complete, zone (%i), instance (%i)\n", Game::server->GetZoneID(), instanceID); Metrics::Clear(); - Database::Destroy(); + Database::Destroy("WorldServer"); delete Game::chatFilter; delete Game::server; delete Game::logger; worldShutdownSequenceComplete = true; - exit(0); + exit(EXIT_SUCCESS); + return EXIT_SUCCESS; } dLogger * SetupLogger(int zoneID, int instanceID) { From 6927bc614ef4c490dd3c18cd4d5cff9ba0ea6d83 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 9 Apr 2022 18:33:38 -0700 Subject: [PATCH 166/251] Spacing --- dMasterServer/MasterServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dMasterServer/MasterServer.cpp b/dMasterServer/MasterServer.cpp index 8f41623e..e1e4728f 100644 --- a/dMasterServer/MasterServer.cpp +++ b/dMasterServer/MasterServer.cpp @@ -660,7 +660,7 @@ void HandlePacket(Packet* packet) { RakNet::BitStream inStream(packet->data, packet->length, false); uint64_t header = inStream.Read(header); - auto* instance =Game::im->GetInstanceBySysAddr(packet->systemAddress); + auto* instance = Game::im->GetInstanceBySysAddr(packet->systemAddress); if (instance == nullptr) { return; From c08557f37d4705e5bba424985ba8acc11f69d46c Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 9 Apr 2022 18:35:41 -0700 Subject: [PATCH 167/251] separated world server to more functions --- dWorldServer/WorldServer.cpp | 161 ++++++++++++++++------------------- 1 file changed, 72 insertions(+), 89 deletions(-) diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index 7ff116a6..84791b52 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -77,6 +77,9 @@ bool chatConnected = false; bool worldShutdownSequenceStarted = false; bool worldShutdownSequenceComplete = false; void WorldShutdownSequence(); +void WorldShutdownProcess(uint32_t cloneId); +void FinalizeShutdown(); +void SendShutdownMessageToMaster(); dLogger* SetupLogger(int zoneID, int instanceID); void HandlePacketChat(Packet* packet); @@ -475,76 +478,15 @@ int main(int argc, char** argv) { } } - if (worldShutdownSequenceStarted && !worldShutdownSequenceComplete) - { - if (framesSinceShutdownSequence == 0) { - - ChatPackets::SendSystemMessage(UNASSIGNED_SYSTEM_ADDRESS, u"Server shutting down...", true); - - for (auto i = 0; i < Game::server->GetReplicaManager()->GetParticipantCount(); ++i) - { - const auto& player = Game::server->GetReplicaManager()->GetParticipantAtIndex(i); - - auto* entity = Player::GetPlayer(player); - Game::logger->Log("WorldServer", "Saving data!\n"); - if (entity != nullptr && entity->GetCharacter() != nullptr) - { - auto* skillComponent = entity->GetComponent(); - - if (skillComponent != nullptr) - { - skillComponent->Reset(); - } - std::string message = "Saving character " + entity->GetCharacter()->GetName() + "...\n"; - Game::logger->Log("WorldServer", message); - entity->GetCharacter()->SaveXMLToDatabase(); - message = "Character data for " + entity->GetCharacter()->GetName() + " was saved!\n"; - Game::logger->Log("WorldServer", message); - } - } - - if (PropertyManagementComponent::Instance() != nullptr) { - Game::logger->Log("WorldServer", "Saving ALL property data!\n"); - PropertyManagementComponent::Instance()->Save(); - Game::logger->Log("WorldServer", "ALL property data saved!\n"); - } - - Game::logger->Log("WorldServer", "ALL DATA HAS BEEN SAVED!\n"); - } - - framesSinceShutdownSequence++; - - while (Game::server->GetReplicaManager()->GetParticipantCount() > 0) { - const auto& player = Game::server->GetReplicaManager()->GetParticipantAtIndex(0); - - Game::server->Disconnect(player, SERVER_DISCON_KICK); - } - - CBITSTREAM; - PacketUtils::WriteHeader(bitStream, MASTER, MSG_MASTER_SHUTDOWN_RESPONSE); - Game::server->SendToMaster(&bitStream); + if (worldShutdownSequenceStarted && !worldShutdownSequenceComplete) { + WorldShutdownProcess(zoneID); break; } Metrics::AddMeasurement(MetricVariable::CPUTime, (1e6 * (1000.0 * (std::clock() - metricCPUTimeStart))) / CLOCKS_PER_SEC); Metrics::EndMeasurement(MetricVariable::Frame); } - - //Delete our objects here: - if (Game::physicsWorld) Game::physicsWorld = nullptr; - if (Game::zoneManager) delete Game::zoneManager; - - Game::logger->Log("WorldServer", "Shutdown complete, zone (%i), instance (%i)\n", Game::server->GetZoneID(), instanceID); - - Metrics::Clear(); - Database::Destroy("WorldServer"); - delete Game::chatFilter; - delete Game::server; - delete Game::logger; - - worldShutdownSequenceComplete = true; - - exit(EXIT_SUCCESS); + FinalizeShutdown(); return EXIT_SUCCESS; } @@ -1276,35 +1218,76 @@ void HandlePacket(Packet* packet) { } } -void WorldShutdownSequence() -{ - if (worldShutdownSequenceStarted || worldShutdownSequenceComplete) - { - return; - } +void WorldShutdownProcess(uint32_t zoneId) { + ChatPackets::SendSystemMessage(UNASSIGNED_SYSTEM_ADDRESS, u"Server shutting down...", true); + Game::logger->Log("WorldServer", "Saving map %i instance %i\n", zoneId, instanceID); + for (auto i = 0; i < Game::server->GetReplicaManager()->GetParticipantCount(); ++i) { + const auto& player = Game::server->GetReplicaManager()->GetParticipantAtIndex(i); - worldShutdownSequenceStarted = true; + auto* entity = Player::GetPlayer(player); + Game::logger->Log("WorldServer", "Saving data!\n"); + if (entity != nullptr && entity->GetCharacter() != nullptr) { + auto* skillComponent = entity->GetComponent(); - auto t = std::chrono::high_resolution_clock::now(); - auto ticks = 0; + if (skillComponent != nullptr) { + skillComponent->Reset(); + } + std::string message = "Saving character " + entity->GetCharacter()->GetName() + "...\n"; + Game::logger->Log("WorldServer", message); + entity->GetCharacter()->SaveXMLToDatabase(); + message = "Character data for " + entity->GetCharacter()->GetName() + " was saved!\n"; + Game::logger->Log("WorldServer", message); + } + } - Game::logger->Log("WorldServer", "Attempting to shutdown world, zone (%i), instance (%i), max 10 seconds...\n", Game::server->GetZoneID(), instanceID); + if (PropertyManagementComponent::Instance() != nullptr) { + Game::logger->Log("WorldServer", "Saving ALL property data!\n"); + PropertyManagementComponent::Instance()->Save(); + Game::logger->Log("WorldServer", "ALL property data saved!\n"); + } - while (true) - { - if (worldShutdownSequenceStarted) - { - break; - } + Game::logger->Log("WorldServer", "ALL DATA HAS BEEN SAVED!\n"); - t += std::chrono::milliseconds(highFrameRate); - std::this_thread::sleep_until(t); + while (Game::server->GetReplicaManager()->GetParticipantCount() > 0) { + const auto& player = Game::server->GetReplicaManager()->GetParticipantAtIndex(0); - ticks++; - - if (ticks == 600) - { - break; - } - } + Game::server->Disconnect(player, SERVER_DISCON_KICK); + } + SendShutdownMessageToMaster(); } + +void WorldShutdownSequence() { + if (worldShutdownSequenceStarted || worldShutdownSequenceComplete) { + return; + } + + worldShutdownSequenceStarted = true; + + Game::logger->Log("WorldServer", "Attempting to shutdown world, zone (%i), instance (%i), max 10 seconds...\n", Game::server->GetZoneID(), instanceID); + WorldShutdownProcess(Game::server->GetZoneID()); + FinalizeShutdown(); +} + +void FinalizeShutdown() { + //Delete our objects here: + if (Game::physicsWorld) Game::physicsWorld = nullptr; + if (Game::zoneManager) delete Game::zoneManager; + + Game::logger->Log("WorldServer", "Shutdown complete, zone (%i), instance (%i)\n", Game::server->GetZoneID(), instanceID); + + Metrics::Clear(); + Database::Destroy("WorldServer"); + delete Game::chatFilter; + delete Game::server; + delete Game::logger; + + worldShutdownSequenceComplete = true; + + exit(EXIT_SUCCESS); +} + +void SendShutdownMessageToMaster() { + CBITSTREAM; + PacketUtils::WriteHeader(bitStream, MASTER, MSG_MASTER_SHUTDOWN_RESPONSE); + Game::server->SendToMaster(&bitStream); +} \ No newline at end of file From 1e514a8b6194249ebed86582e07de5d9f6ade16d Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 9 Apr 2022 18:48:13 -0700 Subject: [PATCH 168/251] more specific logging --- dGame/dComponents/PropertyManagementComponent.h | 2 ++ dWorldServer/WorldServer.cpp | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/dGame/dComponents/PropertyManagementComponent.h b/dGame/dComponents/PropertyManagementComponent.h index c37282e9..c03c4949 100644 --- a/dGame/dComponents/PropertyManagementComponent.h +++ b/dGame/dComponents/PropertyManagementComponent.h @@ -161,6 +161,8 @@ public: */ const std::map& GetModels() const; + LWOCLONEID GetCloneId() { return clone_Id; }; + private: /** * This diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index 84791b52..408d520c 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -1241,12 +1241,12 @@ void WorldShutdownProcess(uint32_t zoneId) { } if (PropertyManagementComponent::Instance() != nullptr) { - Game::logger->Log("WorldServer", "Saving ALL property data!\n"); + Game::logger->Log("WorldServer", "Saving ALL property data for zone %i clone %i!\n", zoneId, PropertyManagementComponent::Instance()->GetCloneId()); PropertyManagementComponent::Instance()->Save(); - Game::logger->Log("WorldServer", "ALL property data saved!\n"); + Game::logger->Log("WorldServer", "ALL property data saved for zone %i clone %i!\n", zoneId, PropertyManagementComponent::Instance()->GetCloneId()); } - Game::logger->Log("WorldServer", "ALL DATA HAS BEEN SAVED!\n"); + Game::logger->Log("WorldServer", "ALL DATA HAS BEEN SAVED FOR ZONE %i INSTANCE %i!\n", zoneId, instanceID); while (Game::server->GetReplicaManager()->GetParticipantCount() > 0) { const auto& player = Game::server->GetReplicaManager()->GetParticipantAtIndex(0); From 30c7b65150ad049185af75d70e262ed9a38de9e0 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 10 Apr 2022 17:00:03 -0700 Subject: [PATCH 169/251] incorrecly named variable --- dWorldServer/WorldServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index 408d520c..d878462b 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -77,7 +77,7 @@ bool chatConnected = false; bool worldShutdownSequenceStarted = false; bool worldShutdownSequenceComplete = false; void WorldShutdownSequence(); -void WorldShutdownProcess(uint32_t cloneId); +void WorldShutdownProcess(uint32_t zoneId); void FinalizeShutdown(); void SendShutdownMessageToMaster(); From f01c2e1bd31488b8b10b184153e9faff404cdf87 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 10 Apr 2022 17:08:29 -0700 Subject: [PATCH 170/251] Updated logging --- dWorldServer/WorldServer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index d878462b..a4056de9 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -1219,7 +1219,6 @@ void HandlePacket(Packet* packet) { } void WorldShutdownProcess(uint32_t zoneId) { - ChatPackets::SendSystemMessage(UNASSIGNED_SYSTEM_ADDRESS, u"Server shutting down...", true); Game::logger->Log("WorldServer", "Saving map %i instance %i\n", zoneId, instanceID); for (auto i = 0; i < Game::server->GetReplicaManager()->GetParticipantCount(); ++i) { const auto& player = Game::server->GetReplicaManager()->GetParticipantAtIndex(i); @@ -1263,7 +1262,7 @@ void WorldShutdownSequence() { worldShutdownSequenceStarted = true; - Game::logger->Log("WorldServer", "Attempting to shutdown world, zone (%i), instance (%i), max 10 seconds...\n", Game::server->GetZoneID(), instanceID); + Game::logger->Log("WorldServer", "Zone (%i) instance (%i) shutting down outside of main loop!\n", Game::server->GetZoneID(), instanceID); WorldShutdownProcess(Game::server->GetZoneID()); FinalizeShutdown(); } From 6b44936c68f1755db3658bf30c904b53fb0a521a Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Tue, 12 Apr 2022 14:06:03 -0500 Subject: [PATCH 171/251] check if map exists for testmap --- dGame/dUtilities/SlashCommandHandler.cpp | 231 ++++++++++------------- 1 file changed, 99 insertions(+), 132 deletions(-) diff --git a/dGame/dUtilities/SlashCommandHandler.cpp b/dGame/dUtilities/SlashCommandHandler.cpp index 901bccbf..5811eae0 100644 --- a/dGame/dUtilities/SlashCommandHandler.cpp +++ b/dGame/dUtilities/SlashCommandHandler.cpp @@ -66,22 +66,22 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entity* entity, const SystemAddress& sysAddr) { std::string chatCommand; std::vector args; - + uint32_t breakIndex = 0; for (uint32_t i = 1; i < command.size(); ++i) { if (command[i] == L' ') { breakIndex = i; break; } - + chatCommand.push_back(static_cast(command[i])); breakIndex++; } - + uint32_t index = ++breakIndex; while (true) { std::string arg; - + while (index < command.size()) { if (command[index] == L' ') { args.push_back(arg); @@ -89,24 +89,24 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit index++; continue; } - + arg.push_back(static_cast(command[index])); index++; } - + if (arg != "") { args.push_back(arg); } - + break; } //Game::logger->Log("SlashCommandHandler", "Received chat command \"%s\"\n", GeneralUtils::UTF16ToWTF8(command).c_str()); - + User* user = UserManager::Instance()->GetUser(sysAddr); if ((chatCommand == "setgmlevel" || chatCommand == "makegm" || chatCommand == "gmlevel") && user->GetMaxGMLevel() > GAME_MASTER_LEVEL_CIVILIAN) { if (args.size() != 1) return; - + uint32_t level; if (!GeneralUtils::TryParse(args[0], level)) @@ -129,7 +129,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit if (level == entity->GetGMLevel()) return; bool success = user->GetMaxGMLevel() >= level; - + if (success) { if (entity->GetGMLevel() > GAME_MASTER_LEVEL_CIVILIAN && level == GAME_MASTER_LEVEL_CIVILIAN) { @@ -174,10 +174,10 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit character->SetPvpEnabled(!character->GetPvpEnabled()); EntityManager::Instance()->SerializeEntity(entity); - + std::stringstream message; message << character->GetName() << " changed their PVP flag to " << std::to_string(character->GetPvpEnabled()) << "!"; - + ChatPackets::SendSystemMessage(UNASSIGNED_SYSTEM_ADDRESS, GeneralUtils::ASCIIToUTF16(message.str()), true); return; @@ -206,14 +206,14 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit { std::stringstream message; message << "Your latest ping: " << std::to_string(Game::server->GetLatestPing(sysAddr)) << "ms"; - + ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(message.str())); } else { std::stringstream message; message << "Your average ping: " << std::to_string(Game::server->GetPing(sysAddr)) << "ms"; - + ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(message.str())); } return; @@ -293,7 +293,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit Game::logger->Log("SlashCommandHandler", "Sending \n%s\n", customText.c_str()); GameMessages::SendUIMessageServerToSingleClient(entity, entity->GetSystemAddress(), "ToggleStoryBox", &args); - + delete visiable; delete text; }); @@ -345,7 +345,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit if ((chatCommand == "join" && !args.empty())) { ChatPackets::SendSystemMessage(sysAddr, u"Requesting private map..."); const auto& password = args[0]; - + ZoneInstanceManager::Instance()->RequestPrivateZone(Game::server, false, password, [=](bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, std::string serverIP, uint16_t serverPort) { Game::logger->Log("UserManager", "Transferring %s to Zone %i (Instance %i | Clone %i | Mythran Shift: %s) with IP %s and Port %i\n", sysAddr.ToString(), zoneID, zoneInstance, zoneClone, mythranShift == true ? "true" : "false", serverIP.c_str(), serverPort); @@ -369,12 +369,12 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit if (chatCommand == "resurrect") { ScriptedActivityComponent* scriptedActivityComponent = dZoneManager::Instance()->GetZoneControlObject()->GetComponent(); - + if (scriptedActivityComponent) { // check if user is in activity world and if so, they can't resurrect ChatPackets::SendSystemMessage(sysAddr, u"You cannot resurrect in an activity world."); return; } - + GameMessages::SendResurrect(entity); } @@ -397,7 +397,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit stmt->setString(2, GeneralUtils::UTF16ToWTF8(command).c_str()); stmt->execute(); delete stmt; - + if (chatCommand == "setminifig" && args.size() == 2 && entity->GetGMLevel() >= GAME_MASTER_LEVEL_FORUM_MODERATOR) { // could break characters so only allow if GM > 0 int32_t minifigItemId; if (!GeneralUtils::TryParse(args[1], minifigItemId)) { @@ -435,13 +435,13 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit ChatPackets::SendSystemMessage(sysAddr, u"Invalid Minifig item to change, try one of the following: Eyebrows, Eyes, HairColor, HairStyle, Pants, LeftHand, Mouth, RightHand, Shirt, Hands"); return; } - + EntityManager::Instance()->ConstructEntity(entity); ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(lowerName) + u" set to " + (GeneralUtils::to_u16string(minifigItemId))); GameMessages::SendToggleGMInvis(entity->GetObjectID(), false, UNASSIGNED_SYSTEM_ADDRESS); // need to retoggle because it gets reenabled on creation of new character } - + if ((chatCommand == "playanimation" || chatCommand == "playanim") && args.size() == 1 && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { std::u16string anim = GeneralUtils::ASCIIToUTF16(args[0], args[0].size()); GameMessages::SendPlayAnimation(entity, anim); @@ -451,15 +451,15 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit for (const auto& pair : EntityManager::Instance()->GetSpawnPointEntities()) { ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(pair.first)); } - + ChatPackets::SendSystemMessage(sysAddr, u"Current: " + GeneralUtils::ASCIIToUTF16(entity->GetCharacter()->GetTargetScene())); return; } - + if (chatCommand == "unlock-emote" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { int32_t emoteID; - + if (!GeneralUtils::TryParse(args[0], emoteID)) { ChatPackets::SendSystemMessage(sysAddr, u"Invalid emote ID."); @@ -491,7 +491,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit if (chatCommand == "speedboost" && args.size() == 1 && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { float boost; - + if (!GeneralUtils::TryParse(args[0], boost)) { ChatPackets::SendSystemMessage(sysAddr, u"Invalid boost."); @@ -515,7 +515,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit entity->SetVar(u"freecam", state); GameMessages::SendSetPlayerControlScheme(entity, static_cast(state ? 9 : 1)); - + ChatPackets::SendSystemMessage(sysAddr, u"Toggled freecam."); return; } @@ -528,9 +528,9 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit ChatPackets::SendSystemMessage(sysAddr, u"Invalid control scheme."); return; } - + GameMessages::SendSetPlayerControlScheme(entity, static_cast(scheme)); - + ChatPackets::SendSystemMessage(sysAddr, u"Switched control scheme."); return; } @@ -552,7 +552,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit AMFArrayValue args; args.InsertValue("state", value); GameMessages::SendUIMessageServerToSingleClient(entity, sysAddr, "pushGameState", &args); - + ChatPackets::SendSystemMessage(sysAddr, u"Switched UI state."); delete value; @@ -566,7 +566,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit AMFArrayValue amfArgs; amfArgs.InsertValue("visible", value); GameMessages::SendUIMessageServerToSingleClient(entity, sysAddr, args[0], &amfArgs); - + ChatPackets::SendSystemMessage(sysAddr, u"Toggled UI state."); delete value; @@ -584,12 +584,12 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit ChatPackets::SendSystemMessage(sysAddr, u"Invalid size."); return; } - + InventoryComponent* inventory = static_cast(entity->GetComponent(COMPONENT_TYPE_INVENTORY)); if (inventory) { auto* items = inventory->GetInventory(ITEMS); - + items->SetSize(size); } @@ -610,7 +610,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit else { ChatPackets::SendSystemMessage(sysAddr, u"Unknown macro! Is the filename right?"); } - + return; } @@ -624,7 +624,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit ChatPackets::SendSystemMessage(sysAddr, u"Invalid mission id."); return; } - + auto comp = static_cast(entity->GetComponent(COMPONENT_TYPE_MISSION)); if (comp) comp->AcceptMission(missionID, true); return; @@ -640,7 +640,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit ChatPackets::SendSystemMessage(sysAddr, u"Invalid mission id."); return; } - + auto comp = static_cast(entity->GetComponent(COMPONENT_TYPE_MISSION)); if (comp) comp->CompleteMission(missionID, true); return; @@ -697,7 +697,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit ChatPackets::SendSystemMessage(sysAddr, u"Invalid mission id."); return; } - + auto* comp = static_cast(entity->GetComponent(COMPONENT_TYPE_MISSION)); if (comp == nullptr) { @@ -709,7 +709,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit if (mission == nullptr) { return; } - + mission->SetMissionState(MissionState::MISSION_STATE_ACTIVE); return; @@ -791,7 +791,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit ChatPackets::SendSystemMessage(sysAddr, u"Invalid item LOT."); return; } - + InventoryComponent * inventory = static_cast(entity->GetComponent(COMPONENT_TYPE_INVENTORY)); inventory->AddItem(itemLOT, 1); @@ -839,7 +839,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit if (receiverID == 0) { ChatPackets::SendSystemMessage(sysAddr, u"Failed to find that player"); - + return; } @@ -866,7 +866,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit ins->setInt(11, 1); ins->execute(); delete ins; - + ChatPackets::SendSystemMessage(sysAddr, u"Mail sent"); return; @@ -883,7 +883,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit GameMessages::SendSetName(entity->GetObjectID(), GeneralUtils::ASCIIToUTF16(name), UNASSIGNED_SYSTEM_ADDRESS); } - + if (chatCommand == "title" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { std::string name = entity->GetCharacter()->GetName() + " - "; @@ -901,19 +901,19 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit if (args.size() == 3) { float x, y, z; - + if (!GeneralUtils::TryParse(args[0], x)) { ChatPackets::SendSystemMessage(sysAddr, u"Invalid x."); return; } - + if (!GeneralUtils::TryParse(args[1], y)) { ChatPackets::SendSystemMessage(sysAddr, u"Invalid y."); return; } - + if (!GeneralUtils::TryParse(args[2], z)) { ChatPackets::SendSystemMessage(sysAddr, u"Invalid z."); @@ -923,7 +923,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit pos.SetX(x); pos.SetY(y); pos.SetZ(z); - + Game::logger->Log("SlashCommandHandler", "Teleporting objectID: %llu to %f, %f, %f\n", entity->GetObjectID(), pos.x, pos.y, pos.z); GameMessages::SendTeleport(entity->GetObjectID(), pos, NiQuaternion(), sysAddr); } else if (args.size() == 2) { @@ -945,7 +945,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit pos.SetY(0.0f); pos.SetZ(z); - + Game::logger->Log("SlashCommandHandler", "Teleporting objectID: %llu to X: %f, Z: %f\n", entity->GetObjectID(), pos.x, pos.z); GameMessages::SendTeleport(entity->GetObjectID(), pos, NiQuaternion(), sysAddr); } else { @@ -1018,7 +1018,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit if (player == nullptr) { auto* accountQuery = Database::CreatePreppedStmt("SELECT account_id, id FROM charinfo WHERE name=? LIMIT 1;"); - + accountQuery->setString(1, args[0]); auto result = accountQuery->executeQuery(); @@ -1028,7 +1028,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit while (result->next()) { accountId = result->getUInt(1); characterId = result->getUInt64(2); - + characterId = GeneralUtils::SetBit(characterId, OBJECT_BIT_CHARACTER); characterId = GeneralUtils::SetBit(characterId, OBJECT_BIT_PERSISTENT); } @@ -1086,7 +1086,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit userUpdate->executeUpdate(); delete userUpdate; - + char buffer[32] = "brought up for review.\0"; if (expire != 1) @@ -1095,12 +1095,12 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit // Format: Mo, 15.06.2009 20:20:00 std::strftime(buffer, 32, "%a, %d.%m.%Y %H:%M:%S", ptm); } - + const auto timeStr = GeneralUtils::ASCIIToUTF16(std::string(buffer)); ChatPackets::SendSystemMessage(sysAddr, u"Muted: " + GeneralUtils::ASCIIToUTF16(args[0]) + u" until " + timeStr); - //Notify chat about it + //Notify chat about it CBITSTREAM; PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_MUTE_UPDATE); @@ -1143,7 +1143,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit if (player == nullptr) { auto* accountQuery = Database::CreatePreppedStmt("SELECT account_id FROM charinfo WHERE name=? LIMIT 1;"); - + accountQuery->setString(1, args[0]); auto result = accountQuery->executeQuery(); @@ -1189,7 +1189,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit } //------------------------------------------------- - + if (chatCommand == "buffme" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { auto dest = static_cast(entity->GetComponent(COMPONENT_TYPE_DESTROYABLE)); if (dest) { @@ -1200,13 +1200,13 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit dest->SetImagination(999); dest->SetMaxImagination(999.0f); } - + EntityManager::Instance()->SerializeEntity(entity); } if (chatCommand == "startcelebration" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() == 1) { int32_t celebration; - + if (!GeneralUtils::TryParse(args[0], celebration)) { ChatPackets::SendSystemMessage(sysAddr, u"Invalid celebration."); @@ -1215,7 +1215,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit GameMessages::SendStartCelebrationEffect(entity, entity->GetSystemAddress(), celebration); } - + if (chatCommand == "buffmed" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { auto dest = static_cast(entity->GetComponent(COMPONENT_TYPE_DESTROYABLE)); if (dest) { @@ -1229,7 +1229,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit EntityManager::Instance()->SerializeEntity(entity); } - + if (chatCommand == "refillstats" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { auto dest = static_cast(entity->GetComponent(COMPONENT_TYPE_DESTROYABLE)); if (dest) { @@ -1240,7 +1240,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit EntityManager::Instance()->SerializeEntity(entity); } - + if (chatCommand == "lookup" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() == 1) { std::string query = "SELECT `id`, `name` FROM `Objects` WHERE `displayName` LIKE '%" + args[0] + "%' OR `name` LIKE '%" + args[0] + "%' OR `description` LIKE '%" + args[0] + "%'"; auto tables = CDClientDatabase::ExecuteQuery(query.c_str()); @@ -1250,13 +1250,13 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit tables.nextRow(); } } - + if (chatCommand == "spawn" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() >= 1) { ControllablePhysicsComponent* comp = static_cast(entity->GetComponent(COMPONENT_TYPE_CONTROLLABLE_PHYSICS)); if (!comp) return; uint32_t lot; - + if (!GeneralUtils::TryParse(args[0], lot)) { ChatPackets::SendSystemMessage(sysAddr, u"Invalid lot."); @@ -1292,7 +1292,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit CharacterComponent* character = entity->GetComponent(); if (character) character->SetUScore(character->GetUScore() + uscore); - // LOOT_SOURCE_MODERATION should work but it doesn't. Relog to see uscore changes + // LOOT_SOURCE_MODERATION should work but it doesn't. Relog to see uscore changes GameMessages::SendModifyLEGOScore(entity, entity->GetSystemAddress(), uscore, LOOT_SOURCE_MODERATION); } @@ -1300,7 +1300,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit const auto position = entity->GetPosition(); ChatPackets::SendSystemMessage(sysAddr, u"<" + (GeneralUtils::to_u16string(position.x)) + u", " + (GeneralUtils::to_u16string(position.y)) + u", " + (GeneralUtils::to_u16string(position.z)) + u">"); - + std::cout << position.x << ", " << position.y << ", " << position.z << std::endl; } @@ -1357,7 +1357,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit if (chatCommand == "gminvis" && entity->GetParentUser()->GetMaxGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { GameMessages::SendToggleGMInvis(entity->GetObjectID(), true, UNASSIGNED_SYSTEM_ADDRESS); - + return; } @@ -1377,7 +1377,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit { destroyableComponent->SetIsGMImmune(state); } - + return; } @@ -1404,7 +1404,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit { buffComponent->ApplyBuff(id, duration, entity->GetObjectID()); } - + return; } @@ -1439,10 +1439,10 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit } const auto objid = entity->GetObjectID(); - + if (force || CheckIfAccessibleZone(reqZone)) { // to prevent tomfoolery bool darwin = true; //Putting this on true, as I'm sick of having to wait 3-4 seconds on a transfer while trying to quickly moderate properties - + Character* character = entity->GetCharacter(); if (character) { std::string lowerName = character->GetName(); @@ -1487,7 +1487,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit WorldPackets::SendTransferToWorld(sysAddr, serverIP, serverPort, mythranShift); }); - + return; }); } else { @@ -1518,7 +1518,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit const auto& password = args[2]; ZoneInstanceManager::Instance()->CreatePrivateZone(Game::server, zone, clone, password); - + ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16("Sent request for private zone with password: " + password)); return; @@ -1593,7 +1593,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit } } } - + if (chatCommand == "triggerspawner" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() >= 1) { auto spawners = dZoneManager::Instance()->GetSpawnersByName(args[0]); @@ -1675,13 +1675,13 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit ChatPackets::SendSystemMessage( sysAddr, - GeneralUtils::ASCIIToUTF16(Metrics::MetricVariableToString(variable)) + - u": " + - GeneralUtils::to_u16string(Metrics::ToMiliseconds(metric->average)) + + GeneralUtils::ASCIIToUTF16(Metrics::MetricVariableToString(variable)) + + u": " + + GeneralUtils::to_u16string(Metrics::ToMiliseconds(metric->average)) + u"ms" ); } - + ChatPackets::SendSystemMessage( sysAddr, u"Peak RSS: " + GeneralUtils::to_u16string((float) ((double) Metrics::GetPeakRSS() / 1.024e6)) + @@ -1728,11 +1728,11 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit } std::u16string message = u"Ran loot drops looking for " - + GeneralUtils::to_u16string(targetLot) - + u", " - + GeneralUtils::to_u16string(loops) - + u" times. It ran " - + GeneralUtils::to_u16string(totalRuns) + + GeneralUtils::to_u16string(targetLot) + + u", " + + GeneralUtils::to_u16string(loops) + + u" times. It ran " + + GeneralUtils::to_u16string(totalRuns) + u" times. Averaging out at " + GeneralUtils::to_u16string((float) totalRuns / loops); @@ -1763,7 +1763,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit auto closestDistance = 0.0f; const auto candidates = EntityManager::Instance()->GetEntitiesByComponent(component); - + for (auto* candidate : candidates) { if (candidate->GetLOT() == 1 || candidate->GetLOT() == 8092) @@ -1775,16 +1775,16 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit { continue; } - + if (closest == nullptr) { closest = candidate; closestDistance = NiPoint3::Distance(candidate->GetPosition(), reference); - + continue; } - + const auto distance = NiPoint3::Distance(candidate->GetPosition(), reference); if (distance < closestDistance) @@ -1811,7 +1811,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit header << info.name << " [" << std::to_string(info.id) << "]" << " " << std::to_string(closestDistance) << " " << std::to_string(closest->IsSleeping()); ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(header.str())); - + for (const auto& pair : closest->GetComponents()) { auto id = pair.first; @@ -1824,7 +1824,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit } if (args.size() >= 2) - { + { if (args[1] == "-m" && args.size() >= 3) { auto* movingPlatformComponent = closest->GetComponent(); @@ -1868,7 +1868,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit const auto postion = closest->GetPosition(); ChatPackets::SendSystemMessage( - sysAddr, + sysAddr, GeneralUtils::ASCIIToUTF16("< " + std::to_string(postion.x) + ", " + std::to_string(postion.y) + ", " + std::to_string(postion.z) + " >") ); } @@ -1931,54 +1931,21 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit } bool SlashCommandHandler::CheckIfAccessibleZone(const unsigned int zoneID) { - switch (zoneID) { - case 98: - case 1000: - case 1001: - - case 1100: - case 1101: - case 1150: - case 1151: - case 1152: - - case 1200: - case 1201: - - case 1250: - case 1251: - case 1260: - - case 1300: - case 1350: - case 1351: - - case 1400: - case 1401: - case 1450: - case 1451: - - case 1600: - case 1601: - case 1602: - case 1603: - case 1604: - - case 1700: - case 1800: - case 1900: - case 2000: - - case 58004: - case 58005: - case 58006: + //We're gonna go ahead and presume we've got the db loaded already: + CDZoneTableTable * zoneTable = CDClientManager::Instance()->GetTable("ZoneTable"); + const CDZoneTable* zone = zoneTable->Query(zoneID); + if (zone != nullptr) { + std::string zonePath = "./res/maps/" + zone->zoneName; + std::transform(zonePath.begin(), zonePath.end(), zonePath.begin(), ::tolower); + std::ifstream f(zonePath.c_str()); + if (f.good()){ return true; - - default: + } else { return false; + } + } else { + return false; } - - return false; } void SlashCommandHandler::SendAnnouncement(const std::string& title, const std::string& message) { @@ -1998,7 +1965,7 @@ void SlashCommandHandler::SendAnnouncement(const std::string& title, const std:: titleValue = nullptr; messageValue = nullptr; - //Notify chat about it + //Notify chat about it CBITSTREAM; PacketUtils::WriteHeader(bitStream, CHAT_INTERNAL, MSG_CHAT_INTERNAL_ANNOUNCEMENT); From 40d396c7e26bac306bbfabd1a40c3cc8446ed66e Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Tue, 12 Apr 2022 18:05:22 -0500 Subject: [PATCH 172/251] simplify --- dGame/dUtilities/SlashCommandHandler.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/dGame/dUtilities/SlashCommandHandler.cpp b/dGame/dUtilities/SlashCommandHandler.cpp index 5811eae0..5907d7d8 100644 --- a/dGame/dUtilities/SlashCommandHandler.cpp +++ b/dGame/dUtilities/SlashCommandHandler.cpp @@ -1931,18 +1931,14 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit } bool SlashCommandHandler::CheckIfAccessibleZone(const unsigned int zoneID) { - //We're gonna go ahead and presume we've got the db loaded already: + //We're gonna go ahead and presume we've got the db loaded already: CDZoneTableTable * zoneTable = CDClientManager::Instance()->GetTable("ZoneTable"); const CDZoneTable* zone = zoneTable->Query(zoneID); if (zone != nullptr) { std::string zonePath = "./res/maps/" + zone->zoneName; std::transform(zonePath.begin(), zonePath.end(), zonePath.begin(), ::tolower); std::ifstream f(zonePath.c_str()); - if (f.good()){ - return true; - } else { - return false; - } + return f.good() } else { return false; } From 4a98c46fb938871f9ef34ab73b0f6cb1d682d801 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Tue, 12 Apr 2022 18:30:46 -0500 Subject: [PATCH 173/251] fix tabs/spaces --- dGame/dUtilities/SlashCommandHandler.cpp | 240 +++++++++++------------ 1 file changed, 120 insertions(+), 120 deletions(-) diff --git a/dGame/dUtilities/SlashCommandHandler.cpp b/dGame/dUtilities/SlashCommandHandler.cpp index 5907d7d8..42a4a565 100644 --- a/dGame/dUtilities/SlashCommandHandler.cpp +++ b/dGame/dUtilities/SlashCommandHandler.cpp @@ -64,48 +64,48 @@ #include "ScriptedActivityComponent.h" void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entity* entity, const SystemAddress& sysAddr) { - std::string chatCommand; - std::vector args; + std::string chatCommand; + std::vector args; - uint32_t breakIndex = 0; - for (uint32_t i = 1; i < command.size(); ++i) { - if (command[i] == L' ') { - breakIndex = i; - break; - } + uint32_t breakIndex = 0; + for (uint32_t i = 1; i < command.size(); ++i) { + if (command[i] == L' ') { + breakIndex = i; + break; + } - chatCommand.push_back(static_cast(command[i])); - breakIndex++; - } + chatCommand.push_back(static_cast(command[i])); + breakIndex++; + } - uint32_t index = ++breakIndex; - while (true) { - std::string arg; + uint32_t index = ++breakIndex; + while (true) { + std::string arg; - while (index < command.size()) { - if (command[index] == L' ') { - args.push_back(arg); - arg = ""; - index++; - continue; - } + while (index < command.size()) { + if (command[index] == L' ') { + args.push_back(arg); + arg = ""; + index++; + continue; + } - arg.push_back(static_cast(command[index])); - index++; - } + arg.push_back(static_cast(command[index])); + index++; + } - if (arg != "") { - args.push_back(arg); - } + if (arg != "") { + args.push_back(arg); + } - break; - } + break; + } - //Game::logger->Log("SlashCommandHandler", "Received chat command \"%s\"\n", GeneralUtils::UTF16ToWTF8(command).c_str()); + //Game::logger->Log("SlashCommandHandler", "Received chat command \"%s\"\n", GeneralUtils::UTF16ToWTF8(command).c_str()); - User* user = UserManager::Instance()->GetUser(sysAddr); - if ((chatCommand == "setgmlevel" || chatCommand == "makegm" || chatCommand == "gmlevel") && user->GetMaxGMLevel() > GAME_MASTER_LEVEL_CIVILIAN) { - if (args.size() != 1) return; + User* user = UserManager::Instance()->GetUser(sysAddr); + if ((chatCommand == "setgmlevel" || chatCommand == "makegm" || chatCommand == "gmlevel") && user->GetMaxGMLevel() > GAME_MASTER_LEVEL_CIVILIAN) { + if (args.size() != 1) return; uint32_t level; @@ -127,10 +127,10 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit level = user->GetMaxGMLevel(); } - if (level == entity->GetGMLevel()) return; - bool success = user->GetMaxGMLevel() >= level; + if (level == entity->GetGMLevel()) return; + bool success = user->GetMaxGMLevel() >= level; - if (success) { + if (success) { if (entity->GetGMLevel() > GAME_MASTER_LEVEL_CIVILIAN && level == GAME_MASTER_LEVEL_CIVILIAN) { GameMessages::SendToggleGMInvis(entity->GetObjectID(), false, UNASSIGNED_SYSTEM_ADDRESS); @@ -140,12 +140,12 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit GameMessages::SendToggleGMInvis(entity->GetObjectID(), true, UNASSIGNED_SYSTEM_ADDRESS); } - WorldPackets::SendGMLevelChange(sysAddr, success, user->GetMaxGMLevel(), entity->GetGMLevel(), level); - GameMessages::SendChatModeUpdate(entity->GetObjectID(), level); - entity->SetGMLevel(level); - Game::logger->Log("SlashCommandHandler", "User %s (%i) has changed their GM level to %i for charID %llu\n", user->GetUsername().c_str(), user->GetAccountID(), level, entity->GetObjectID()); - } - } + WorldPackets::SendGMLevelChange(sysAddr, success, user->GetMaxGMLevel(), entity->GetGMLevel(), level); + GameMessages::SendChatModeUpdate(entity->GetObjectID(), level); + entity->SetGMLevel(level); + Game::logger->Log("SlashCommandHandler", "User %s (%i) has changed their GM level to %i for charID %llu\n", user->GetUsername().c_str(), user->GetAccountID(), level, entity->GetObjectID()); + } + } #ifndef DEVELOPER_SERVER if ((entity->GetGMLevel() > user->GetMaxGMLevel()) || (entity->GetGMLevel() > GAME_MASTER_LEVEL_CIVILIAN && user->GetMaxGMLevel() == GAME_MASTER_LEVEL_JUNIOR_DEVELOPER)) @@ -362,7 +362,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit }); } - if (user->GetMaxGMLevel() == 0 || entity->GetGMLevel() >= 0) { + if (user->GetMaxGMLevel() == 0 || entity->GetGMLevel() >= 0) { if (chatCommand == "die") { entity->Smash(entity->GetObjectID()); } @@ -389,14 +389,14 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit } if (entity->GetGMLevel() == 0) return; - } + } // Log command to database - auto stmt = Database::CreatePreppedStmt("INSERT INTO command_log (character_id, command) VALUES (?, ?);"); - stmt->setInt(1, entity->GetCharacter()->GetID()); + auto stmt = Database::CreatePreppedStmt("INSERT INTO command_log (character_id, command) VALUES (?, ?);"); + stmt->setInt(1, entity->GetCharacter()->GetID()); stmt->setString(2, GeneralUtils::UTF16ToWTF8(command).c_str()); - stmt->execute(); - delete stmt; + stmt->execute(); + delete stmt; if (chatCommand == "setminifig" && args.size() == 2 && entity->GetGMLevel() >= GAME_MASTER_LEVEL_FORUM_MODERATOR) { // could break characters so only allow if GM > 0 int32_t minifigItemId; @@ -656,7 +656,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit return; } - entity->GetCharacter()->SetPlayerFlag(flagId, true); + entity->GetCharacter()->SetPlayerFlag(flagId, true); } if (chatCommand == "setflag" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() == 2) @@ -672,7 +672,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit ChatPackets::SendSystemMessage(sysAddr, u"Invalid flag type."); return; } - entity->GetCharacter()->SetPlayerFlag(flagId, onOffFlag == "on"); + entity->GetCharacter()->SetPlayerFlag(flagId, onOffFlag == "on"); } if (chatCommand == "clearflag" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() == 1) { @@ -684,7 +684,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit return; } - entity->GetCharacter()->SetPlayerFlag(flagId, false); + entity->GetCharacter()->SetPlayerFlag(flagId, false); } if (chatCommand == "resetmission" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { @@ -782,8 +782,8 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit ChatPackets::SendSystemMessage(sysAddr, msg); } - if (chatCommand == "gmadditem" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { - if (args.size() == 1) { + if (chatCommand == "gmadditem" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { + if (args.size() == 1) { uint32_t itemLOT; if (!GeneralUtils::TryParse(args[0], itemLOT)) @@ -795,7 +795,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit InventoryComponent * inventory = static_cast(entity->GetComponent(COMPONENT_TYPE_INVENTORY)); inventory->AddItem(itemLOT, 1); - } else if(args.size() == 2) { + } else if(args.size() == 2) { uint32_t itemLOT; if (!GeneralUtils::TryParse(args[0], itemLOT)) @@ -817,9 +817,9 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit inventory->AddItem(itemLOT, count); } else { - ChatPackets::SendSystemMessage(sysAddr, u"Correct usage: /gmadditem "); - } - } + ChatPackets::SendSystemMessage(sysAddr, u"Correct usage: /gmadditem "); + } + } if (chatCommand == "mailitem" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_MODERATOR && args.size() >= 2) { const auto& playerName = args[0]; @@ -896,9 +896,9 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit GameMessages::SendSetName(entity->GetObjectID(), GeneralUtils::ASCIIToUTF16(name), UNASSIGNED_SYSTEM_ADDRESS); } - if ((chatCommand == "teleport" || chatCommand == "tele") && entity->GetGMLevel() >= GAME_MASTER_LEVEL_JUNIOR_MODERATOR) { - NiPoint3 pos {}; - if (args.size() == 3) { + if ((chatCommand == "teleport" || chatCommand == "tele") && entity->GetGMLevel() >= GAME_MASTER_LEVEL_JUNIOR_MODERATOR) { + NiPoint3 pos {}; + if (args.size() == 3) { float x, y, z; @@ -920,13 +920,13 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit return; } - pos.SetX(x); - pos.SetY(y); - pos.SetZ(z); + pos.SetX(x); + pos.SetY(y); + pos.SetZ(z); - Game::logger->Log("SlashCommandHandler", "Teleporting objectID: %llu to %f, %f, %f\n", entity->GetObjectID(), pos.x, pos.y, pos.z); - GameMessages::SendTeleport(entity->GetObjectID(), pos, NiQuaternion(), sysAddr); - } else if (args.size() == 2) { + Game::logger->Log("SlashCommandHandler", "Teleporting objectID: %llu to %f, %f, %f\n", entity->GetObjectID(), pos.x, pos.y, pos.z); + GameMessages::SendTeleport(entity->GetObjectID(), pos, NiQuaternion(), sysAddr); + } else if (args.size() == 2) { float x, z; if (!GeneralUtils::TryParse(args[0], x)) @@ -946,11 +946,11 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit pos.SetZ(z); - Game::logger->Log("SlashCommandHandler", "Teleporting objectID: %llu to X: %f, Z: %f\n", entity->GetObjectID(), pos.x, pos.z); - GameMessages::SendTeleport(entity->GetObjectID(), pos, NiQuaternion(), sysAddr); - } else { - ChatPackets::SendSystemMessage(sysAddr, u"Correct usage: /teleport () - if no Y given, will teleport to the height of the terrain (or any physics object)."); - } + Game::logger->Log("SlashCommandHandler", "Teleporting objectID: %llu to X: %f, Z: %f\n", entity->GetObjectID(), pos.x, pos.z); + GameMessages::SendTeleport(entity->GetObjectID(), pos, NiQuaternion(), sysAddr); + } else { + ChatPackets::SendSystemMessage(sysAddr, u"Correct usage: /teleport () - if no Y given, will teleport to the height of the terrain (or any physics object)."); + } auto* possessorComponent = entity->GetComponent(); @@ -972,7 +972,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit } } } - } + } if (chatCommand == "tpall" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { @@ -1190,7 +1190,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit //------------------------------------------------- - if (chatCommand == "buffme" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { + if (chatCommand == "buffme" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { auto dest = static_cast(entity->GetComponent(COMPONENT_TYPE_DESTROYABLE)); if (dest) { dest->SetHealth(999); @@ -1201,8 +1201,8 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit dest->SetMaxImagination(999.0f); } - EntityManager::Instance()->SerializeEntity(entity); - } + EntityManager::Instance()->SerializeEntity(entity); + } if (chatCommand == "startcelebration" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() == 1) { int32_t celebration; @@ -1216,7 +1216,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit GameMessages::SendStartCelebrationEffect(entity, entity->GetSystemAddress(), celebration); } - if (chatCommand == "buffmed" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { + if (chatCommand == "buffmed" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { auto dest = static_cast(entity->GetComponent(COMPONENT_TYPE_DESTROYABLE)); if (dest) { dest->SetHealth(9); @@ -1227,10 +1227,10 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit dest->SetMaxImagination(9.0f); } - EntityManager::Instance()->SerializeEntity(entity); - } + EntityManager::Instance()->SerializeEntity(entity); + } - if (chatCommand == "refillstats" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { + if (chatCommand == "refillstats" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { auto dest = static_cast(entity->GetComponent(COMPONENT_TYPE_DESTROYABLE)); if (dest) { dest->SetHealth((int)dest->GetMaxHealth()); @@ -1238,22 +1238,22 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit dest->SetImagination((int)dest->GetMaxImagination()); } - EntityManager::Instance()->SerializeEntity(entity); - } + EntityManager::Instance()->SerializeEntity(entity); + } - if (chatCommand == "lookup" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() == 1) { - std::string query = "SELECT `id`, `name` FROM `Objects` WHERE `displayName` LIKE '%" + args[0] + "%' OR `name` LIKE '%" + args[0] + "%' OR `description` LIKE '%" + args[0] + "%'"; - auto tables = CDClientDatabase::ExecuteQuery(query.c_str()); - while (!tables.eof()) { - std::string message = std::to_string(tables.getIntField(0)) + " - " + tables.getStringField(1); - ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(message, message.size())); - tables.nextRow(); - } - } + if (chatCommand == "lookup" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() == 1) { + std::string query = "SELECT `id`, `name` FROM `Objects` WHERE `displayName` LIKE '%" + args[0] + "%' OR `name` LIKE '%" + args[0] + "%' OR `description` LIKE '%" + args[0] + "%'"; + auto tables = CDClientDatabase::ExecuteQuery(query.c_str()); + while (!tables.eof()) { + std::string message = std::to_string(tables.getIntField(0)) + " - " + tables.getStringField(1); + ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(message, message.size())); + tables.nextRow(); + } + } - if (chatCommand == "spawn" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() >= 1) { - ControllablePhysicsComponent* comp = static_cast(entity->GetComponent(COMPONENT_TYPE_CONTROLLABLE_PHYSICS)); - if (!comp) return; + if (chatCommand == "spawn" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() >= 1) { + ControllablePhysicsComponent* comp = static_cast(entity->GetComponent(COMPONENT_TYPE_CONTROLLABLE_PHYSICS)); + if (!comp) return; uint32_t lot; @@ -1263,23 +1263,23 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit return; } - EntityInfo info; - info.lot = lot; - info.pos = comp->GetPosition(); - info.rot = comp->GetRotation(); + EntityInfo info; + info.lot = lot; + info.pos = comp->GetPosition(); + info.rot = comp->GetRotation(); info.spawner = nullptr; info.spawnerID = entity->GetObjectID(); info.spawnerNodeID = 0; - Entity* newEntity = EntityManager::Instance()->CreateEntity(info, nullptr); + Entity* newEntity = EntityManager::Instance()->CreateEntity(info, nullptr); - if (newEntity == nullptr) { + if (newEntity == nullptr) { ChatPackets::SendSystemMessage(sysAddr, u"Failed to spawn entity."); return; - } + } - EntityManager::Instance()->ConstructEntity(newEntity); - } + EntityManager::Instance()->ConstructEntity(newEntity); + } if ((chatCommand == "giveuscore") && args.size() == 1 && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { int32_t uscore; @@ -1323,9 +1323,9 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit GameMessages::SendPlayFXEffect(entity, 7074, u"create", "7074", LWOOBJID_EMPTY, 1.0f, 1.0f, true); } - if (chatCommand == "playrebuildfx" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { - GameMessages::SendPlayFXEffect(entity, 230, u"rebuild", "230", LWOOBJID_EMPTY, 1.0f, 1.0f, true); - } + if (chatCommand == "playrebuildfx" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { + GameMessages::SendPlayFXEffect(entity, 230, u"rebuild", "230", LWOOBJID_EMPTY, 1.0f, 1.0f, true); + } if ((chatCommand == "freemoney" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) && args.size() == 1) { int32_t money; @@ -1408,8 +1408,8 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit return; } - if ((chatCommand == "testmap" && args.size() >= 1) && entity->GetGMLevel() >= GAME_MASTER_LEVEL_FORUM_MODERATOR) { - ChatPackets::SendSystemMessage(sysAddr, u"Requesting map change..."); + if ((chatCommand == "testmap" && args.size() >= 1) && entity->GetGMLevel() >= GAME_MASTER_LEVEL_FORUM_MODERATOR) { + ChatPackets::SendSystemMessage(sysAddr, u"Requesting map change..."); uint32_t reqZone; LWOCLONEID cloneId = 0; bool force = false; @@ -1440,7 +1440,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit const auto objid = entity->GetObjectID(); - if (force || CheckIfAccessibleZone(reqZone)) { // to prevent tomfoolery + if (force || CheckIfAccessibleZone(reqZone)) { // to prevent tomfoolery bool darwin = true; //Putting this on true, as I'm sick of having to wait 3-4 seconds on a transfer while trying to quickly moderate properties Character* character = entity->GetCharacter(); @@ -1460,12 +1460,12 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit ); } - ZoneInstanceManager::Instance()->RequestZoneTransfer(Game::server, reqZone, cloneId, false, [objid, darwin](bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, std::string serverIP, uint16_t serverPort) { + ZoneInstanceManager::Instance()->RequestZoneTransfer(Game::server, reqZone, cloneId, false, [objid, darwin](bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, std::string serverIP, uint16_t serverPort) { auto* entity = EntityManager::Instance()->GetEntity(objid); - if (entity == nullptr) { - return; - } + if (entity == nullptr) { + return; + } float transferTime = 3.32999992370605f; if (darwin) transferTime = 0.0f; @@ -1488,14 +1488,14 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit WorldPackets::SendTransferToWorld(sysAddr, serverIP, serverPort, mythranShift); }); - return; - }); - } else { - std::string msg = "ZoneID not found or allowed: "; - msg.append(args[0]); - ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(msg, msg.size())); - } - } + return; + }); + } else { + std::string msg = "ZoneID not found or allowed: "; + msg.append(args[0]); + ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(msg, msg.size())); + } + } if (chatCommand == "createprivate" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER && args.size() >= 3) { From 959c90985c498043c3ea361eabbc498803d73923 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Tue, 12 Apr 2022 18:32:52 -0500 Subject: [PATCH 174/251] missed a semicolon --- dGame/dUtilities/SlashCommandHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dUtilities/SlashCommandHandler.cpp b/dGame/dUtilities/SlashCommandHandler.cpp index 42a4a565..2e3e2be7 100644 --- a/dGame/dUtilities/SlashCommandHandler.cpp +++ b/dGame/dUtilities/SlashCommandHandler.cpp @@ -1938,7 +1938,7 @@ bool SlashCommandHandler::CheckIfAccessibleZone(const unsigned int zoneID) { std::string zonePath = "./res/maps/" + zone->zoneName; std::transform(zonePath.begin(), zonePath.end(), zonePath.begin(), ::tolower); std::ifstream f(zonePath.c_str()); - return f.good() + return f.good(); } else { return false; } From 59ec28a5a4bfabf054c0eeb7f288aff52ce793fe Mon Sep 17 00:00:00 2001 From: NinjaOfLU Date: Wed, 13 Apr 2022 01:58:00 +0100 Subject: [PATCH 175/251] Prevent integer underflow in item removal Previously, the only check that the user wasn't trashing more items than they had was clientsided, and this could be bypassed by contacting the server to remove items via a console or the like, and then trashing them before the server could respond, resulting in the count for the items being less than iStackCount. This check prevents that underflow. --- dGame/dGameMessages/GameMessages.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 1ede443b..35e1a13c 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -5441,7 +5441,7 @@ void GameMessages::HandleRemoveItemFromInventory(RakNet::BitStream* inStream, En } } - item->SetCount(item->GetCount() - iStackCount, true); + item->SetCount(item->GetCount() - std::min(item->GetCount(), iStackCount), true); EntityManager::Instance()->SerializeEntity(entity); auto* missionComponent = entity->GetComponent(); From a32c5a2f3c2cfac1234931fcd21a94d5325f9ebb Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 13 Apr 2022 01:49:55 -0700 Subject: [PATCH 176/251] Vault corrections --- dGame/Entity.cpp | 12 ++++++++++++ dGame/Entity.h | 6 +++++- dGame/UserManager.cpp | 2 +- dGame/dComponents/InventoryComponent.cpp | 1 + dGame/dMission/Mission.cpp | 4 +++- dWorldServer/WorldServer.cpp | 2 ++ 6 files changed, 24 insertions(+), 3 deletions(-) diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index bca7ffa2..57b7af14 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -2173,3 +2173,15 @@ void Entity::AddToGroup(const std::string& group) { m_Groups.push_back(group); } } + +void Entity::RetroactiveVaultSize() { + auto inventoryComponent = GetComponent(); + if (!inventoryComponent) return; + + auto itemsVault = inventoryComponent->GetInventory(eInventoryType::VAULT_ITEMS); + auto modelVault = inventoryComponent->GetInventory(eInventoryType::VAULT_MODELS); + + if (itemsVault->GetSize() == modelVault->GetSize()) return; + + modelVault->SetSize(itemsVault->GetSize()); +} diff --git a/dGame/Entity.h b/dGame/Entity.h index 31b2b303..cef7b97f 100644 --- a/dGame/Entity.h +++ b/dGame/Entity.h @@ -220,7 +220,11 @@ public: /* * Utility */ - + /** + * Retroactively corrects the model vault size due to incorrect initialization in a previous patch. + * + */ + 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; diff --git a/dGame/UserManager.cpp b/dGame/UserManager.cpp index adae72b0..1d14cb0a 100644 --- a/dGame/UserManager.cpp +++ b/dGame/UserManager.cpp @@ -291,7 +291,7 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet) xml << "ls=\"0\" lzx=\"-626.5847\" lzy=\"613.3515\" lzz=\"-28.6374\" lzrx=\"0.0\" lzry=\"0.7015\" lzrz=\"0.0\" lzrw=\"0.7126\" "; xml << "stt=\"0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;\">"; xml << ""; - xml << ""; + xml << ""; std::string xmlSave1 = xml.str(); ObjectIDManager::Instance()->RequestPersistentID([=](uint32_t idforshirt) { diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index 63080b2d..5d3dda2e 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -84,6 +84,7 @@ Inventory* InventoryComponent::GetInventory(const eInventoryType type) case eInventoryType::ITEMS: size = 20u; break; + case eInventoryType::VAULT_MODELS: case eInventoryType::VAULT_ITEMS: size = 40u; break; diff --git a/dGame/dMission/Mission.cpp b/dGame/dMission/Mission.cpp index f7b57071..14fc5a24 100644 --- a/dGame/dMission/Mission.cpp +++ b/dGame/dMission/Mission.cpp @@ -511,9 +511,11 @@ void Mission::YieldRewards() { } if (info->reward_bankinventory > 0) { - auto* inventory = inventoryComponent->GetInventory(VAULT_ITEMS); + auto* inventory = inventoryComponent->GetInventory(eInventoryType::VAULT_ITEMS); + auto modelInventory = inventoryComponent->GetInventory(eInventoryType::VAULT_MODELS); inventory->SetSize(inventory->GetSize() + info->reward_bankinventory); + modelInventory->SetSize(modelInventory->GetSize() + info->reward_bankinventory); } if (info->reward_reputation > 0) { diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index a4056de9..9d0c84cc 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -975,6 +975,8 @@ void HandlePacket(Packet* packet) { player->GetComponent()->SetLastRocketConfig(u""); c->SetRetroactiveFlags(); + + player->RetroactiveVaultSize(); player->GetCharacter()->SetTargetScene(""); From 1d1f47938769a6a40f0472c6643e68e8813b9227 Mon Sep 17 00:00:00 2001 From: NinjaOfLU Date: Thu, 14 Apr 2022 00:11:35 +0100 Subject: [PATCH 177/251] Ensure items correctly removed from missions Doubt it would have affected anyone, but technically if you had a mission to collect something interactable, and you deleted the items at the same time as interacting with something, this would have counted incorrectly. I'm being defensive because I was an idiot who couldn't read, but in my defence, it was late when I made the first edit, and I'm also a blundering idiot! --- dGame/dGameMessages/GameMessages.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 35e1a13c..c8c1e7aa 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -5448,7 +5448,7 @@ void GameMessages::HandleRemoveItemFromInventory(RakNet::BitStream* inStream, En if (missionComponent != nullptr) { - missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_ITEM_COLLECTION, item->GetLot(), LWOOBJID_EMPTY, "", -iStackCount); + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_ITEM_COLLECTION, item->GetLot(), LWOOBJID_EMPTY, "", -std::min(item->GetCount(), iStackCount); } } } From cdbb42badff3247cec8a2e4e016669d0d676f036 Mon Sep 17 00:00:00 2001 From: NinjaOfLU Date: Thu, 14 Apr 2022 00:15:45 +0100 Subject: [PATCH 178/251] Added a bracket... -_- Maybe I should write and test code on my computer rather than using Git as an IDE and commits as the save button... --- dGame/dGameMessages/GameMessages.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index c8c1e7aa..e1fb21ac 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -5448,7 +5448,7 @@ void GameMessages::HandleRemoveItemFromInventory(RakNet::BitStream* inStream, En if (missionComponent != nullptr) { - missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_ITEM_COLLECTION, item->GetLot(), LWOOBJID_EMPTY, "", -std::min(item->GetCount(), iStackCount); + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_ITEM_COLLECTION, item->GetLot(), LWOOBJID_EMPTY, "", -std::min(item->GetCount(), iStackCount)); } } } From 3d6d5e58a789ccf8df667a2683cad297d27a49e5 Mon Sep 17 00:00:00 2001 From: NinjaOfLU Date: Thu, 14 Apr 2022 10:09:40 +0100 Subject: [PATCH 179/251] Update GameMessages.cpp I promise I'm not farming changes. I woke up at like 4AM and realised that I'd screwed up in an obvious way. Note to self: You are ALLOWED to change variables. Wasn't caught in testing because, well, it turns out it's actually impossible to test the edge case this covers, due to the script for the brick console. --- dGame/dGameMessages/GameMessages.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index e1fb21ac..9e68941c 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -5433,6 +5433,8 @@ void GameMessages::HandleRemoveItemFromInventory(RakNet::BitStream* inStream, En return; } + iStackCount = std::min(item->GetCount(), iStackCount); + if (bConfirmed) { for (auto i = 0; i < iStackCount; ++i) { if (eInvType == eInventoryType::MODELS) @@ -5441,14 +5443,14 @@ void GameMessages::HandleRemoveItemFromInventory(RakNet::BitStream* inStream, En } } - item->SetCount(item->GetCount() - std::min(item->GetCount(), iStackCount), true); + item->SetCount(item->GetCount() - iStackCount, true); EntityManager::Instance()->SerializeEntity(entity); auto* missionComponent = entity->GetComponent(); if (missionComponent != nullptr) { - missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_ITEM_COLLECTION, item->GetLot(), LWOOBJID_EMPTY, "", -std::min(item->GetCount(), iStackCount)); + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_ITEM_COLLECTION, item->GetLot(), LWOOBJID_EMPTY, "", -iStackCount); } } } From b4acf329b492d44db939763cbece4a31ab93ceb5 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Sat, 16 Apr 2022 23:32:15 -0500 Subject: [PATCH 180/251] implement some missing scripts --- dScripts/CppScripts.cpp | 10 +++++ dScripts/RockHydrantBroken.cpp | 46 ++++++++++++++++++++++ dScripts/RockHydrantBroken.h | 10 +++++ dScripts/WhFans.cpp | 72 ++++++++++++++++++++++++++++++++++ dScripts/WhFans.h | 17 ++++++++ 5 files changed, 155 insertions(+) create mode 100644 dScripts/RockHydrantBroken.cpp create mode 100644 dScripts/RockHydrantBroken.h create mode 100644 dScripts/WhFans.cpp create mode 100644 dScripts/WhFans.h diff --git a/dScripts/CppScripts.cpp b/dScripts/CppScripts.cpp index b9fa50ef..95269dab 100644 --- a/dScripts/CppScripts.cpp +++ b/dScripts/CppScripts.cpp @@ -274,6 +274,10 @@ #include "AgSurvivalMech.h" #include "AgSurvivalSpiderling.h" +// Frostburgh Scripts +#include "RockHydrantBroken.h" +#include "WhFans.h" + //Big bad global bc this is a namespace and not a class: InvalidScript* invalidToReturn = new InvalidScript(); std::map m_Scripts; @@ -795,6 +799,12 @@ CppScripts::Script* CppScripts::GetScript(Entity* parent, const std::string& scr else if (scriptName == "scripts\\EquipmentScripts\\BuccaneerValiantShip.lua") script = new BuccaneerValiantShip(); + // FB + else if (scriptName = "scripts\\ai\\NS\\WH\\L_ROCKHYDRANT_BROKEN.lua") + script = new RockHydrantBroken(); + else if (scriptName = "L_NS_WH_FANS.lua") + script = new WhFans(); + //Ignore these scripts: else if (scriptName == "scripts\\02_server\\Enemy\\General\\L_SUSPEND_LUA_AI.lua") script = invalidToReturn; diff --git a/dScripts/RockHydrantBroken.cpp b/dScripts/RockHydrantBroken.cpp new file mode 100644 index 00000000..2c145b36 --- /dev/null +++ b/dScripts/RockHydrantBroken.cpp @@ -0,0 +1,46 @@ +#include "RockHydrantBroken.h" +#include "EntityManager.h" +#include "GameMessages.h" + +void RockHydrantBroken::OnStartup(Entity* self) +{ + self->AddTimer("playEffect", 1); + + const auto hydrant = "hydrant" + self->GetVar(u"hydrant"); + + const auto bouncers = EntityManager::Instance()->GetEntitiesInGroup(hydrant); + + Game::logger->Log("RockHydrantBroken", "Broken Hydrant spawned (%s)\n", hydrant.c_str()); + + for (auto* bouncer : bouncers) + { + self->SetVar(u"bouncer", bouncer->GetObjectID()); + + GameMessages::SendBouncerActiveStatus(bouncer->GetObjectID(), true, UNASSIGNED_SYSTEM_ADDRESS); + + GameMessages::SendNotifyObject(bouncer->GetObjectID(), self->GetObjectID(), u"enableCollision", UNASSIGNED_SYSTEM_ADDRESS); + } + + self->AddTimer("KillBroken", 25); +} + +void RockHydrantBroken::OnTimerDone(Entity* self, std::string timerName) +{ + if (timerName == "KillBroken") + { + auto* bouncer = EntityManager::Instance()->GetEntity(self->GetVar(u"bouncer")); + + if (bouncer != nullptr) + { + GameMessages::SendBouncerActiveStatus(bouncer->GetObjectID(), false, UNASSIGNED_SYSTEM_ADDRESS); + + GameMessages::SendNotifyObject(bouncer->GetObjectID(), self->GetObjectID(), u"disableCollision", UNASSIGNED_SYSTEM_ADDRESS); + } + + self->Kill(); + } + else if (timerName == "playEffect") + { + GameMessages::SendPlayFXEffect(self->GetObjectID(), 384, u"water", "water", LWOOBJID_EMPTY, 1, 1, true); + } +} diff --git a/dScripts/RockHydrantBroken.h b/dScripts/RockHydrantBroken.h new file mode 100644 index 00000000..3bea8341 --- /dev/null +++ b/dScripts/RockHydrantBroken.h @@ -0,0 +1,10 @@ +#pragma once +#include "CppScripts.h" + +class RockHydrantBroken : public CppScripts::Script +{ +public: + void OnStartup(Entity* self) override; + void OnTimerDone(Entity* self, std::string timerName) override; +}; + diff --git a/dScripts/WhFans.cpp b/dScripts/WhFans.cpp new file mode 100644 index 00000000..eee0cd30 --- /dev/null +++ b/dScripts/WhFans.cpp @@ -0,0 +1,72 @@ +#include "AgFans.h" + +#include "RenderComponent.h" + +void AgFans::OnStartup(Entity* self) { + self->SetVar(u"alive", true); + self->SetVar(u"on", false); + + ToggleFX(self, false); + + auto* renderComponent = static_cast(self->GetComponent(COMPONENT_TYPE_RENDER)); + + if (renderComponent == nullptr) { + return; + } + + renderComponent->PlayEffect(495, u"fanOn", "fanOn"); +} + +void AgFans::ToggleFX(Entity* self, bool hit) { + std::string fanGroup = self->GetGroups()[0]; + std::vector fanVolumes = EntityManager::Instance()->GetEntitiesInGroup(fanGroup); + + auto* renderComponent = static_cast(self->GetComponent(COMPONENT_TYPE_RENDER)); + + if (renderComponent == nullptr) { + return; + } + + if (fanVolumes.size() == 0 || !self->GetVar(u"alive")) return; + + if (self->GetVar(u"on")) { + GameMessages::SendPlayAnimation(self, u"fan-off"); + + renderComponent->StopEffect("fanOn"); + self->SetVar(u"on", false); + + for (Entity* volume : fanVolumes) { + PhantomPhysicsComponent* volumePhys = static_cast(volume->GetComponent(COMPONENT_TYPE_PHANTOM_PHYSICS)); + if (!volumePhys) continue; + volumePhys->SetPhysicsEffectActive(false); + EntityManager::Instance()->SerializeEntity(volume); + } + } + else if (!self->GetVar(u"on") && self->GetVar(u"alive")) { + GameMessages::SendPlayAnimation(self, u"fan-on"); + + self->SetVar(u"on", true); + + for (Entity* volume : fanVolumes) { + PhantomPhysicsComponent* volumePhys = static_cast(volume->GetComponent(COMPONENT_TYPE_PHANTOM_PHYSICS)); + if (!volumePhys) continue; + volumePhys->SetPhysicsEffectActive(true); + EntityManager::Instance()->SerializeEntity(volume); + } + } +} + +void AgFans::OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1, int32_t param2, + int32_t param3) { + if (args.length() == 0 || !self->GetVar(u"alive")) return; + + if ((args == "turnOn" && self->GetVar(u"on")) || (args == "turnOff" && !self->GetVar(u"on"))) return; + ToggleFX(self, false); +} + +void AgFans::OnDie(Entity* self, Entity* killer) { + if (self->GetVar(u"on")) { + ToggleFX(self, true); + } + self->SetVar(u"alive", false); +} \ No newline at end of file diff --git a/dScripts/WhFans.h b/dScripts/WhFans.h new file mode 100644 index 00000000..9b87430b --- /dev/null +++ b/dScripts/WhFans.h @@ -0,0 +1,17 @@ +#pragma once +#include "CppScripts.h" +#include "GameMessages.h" +#include "EntityManager.h" +#include "PhantomPhysicsComponent.h" + +class WhFans : public CppScripts::Script +{ +public: + void OnStartup(Entity* self); + void OnDie(Entity* self, Entity* killer); + void OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1, int32_t param2, + int32_t param3); +private: + void ToggleFX(Entity* self, bool hit); +}; + From 0e5a1c97219c224d90e53b54c5ea5ad65faf8fb5 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Sat, 16 Apr 2022 23:33:44 -0500 Subject: [PATCH 181/251] fix comparator --- dScripts/CppScripts.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dScripts/CppScripts.cpp b/dScripts/CppScripts.cpp index 95269dab..c81b01f4 100644 --- a/dScripts/CppScripts.cpp +++ b/dScripts/CppScripts.cpp @@ -1,4 +1,4 @@ -//I can feel my soul being torn apart with every script added to this monstrosity. +//I can feel my soul being torn apart with every script added to this monstrosity. // skate fast eat trash // do you think god stays in heaven because he too lives in fear of what he's created? @@ -800,9 +800,9 @@ CppScripts::Script* CppScripts::GetScript(Entity* parent, const std::string& scr script = new BuccaneerValiantShip(); // FB - else if (scriptName = "scripts\\ai\\NS\\WH\\L_ROCKHYDRANT_BROKEN.lua") + else if (scriptName == "scripts\\ai\\NS\\WH\\L_ROCKHYDRANT_BROKEN.lua") script = new RockHydrantBroken(); - else if (scriptName = "L_NS_WH_FANS.lua") + else if (scriptName == "L_NS_WH_FANS.lua") script = new WhFans(); //Ignore these scripts: From b3695c42b2d5697ae8c3c1d9aecc686d18bd39fd Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Sat, 16 Apr 2022 23:35:22 -0500 Subject: [PATCH 182/251] fix copy past error --- dScripts/WhFans.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dScripts/WhFans.cpp b/dScripts/WhFans.cpp index eee0cd30..da9af43f 100644 --- a/dScripts/WhFans.cpp +++ b/dScripts/WhFans.cpp @@ -1,8 +1,8 @@ -#include "AgFans.h" +#include "WhFans.h" #include "RenderComponent.h" -void AgFans::OnStartup(Entity* self) { +void WhFans::OnStartup(Entity* self) { self->SetVar(u"alive", true); self->SetVar(u"on", false); @@ -17,7 +17,7 @@ void AgFans::OnStartup(Entity* self) { renderComponent->PlayEffect(495, u"fanOn", "fanOn"); } -void AgFans::ToggleFX(Entity* self, bool hit) { +void WhFans::ToggleFX(Entity* self, bool hit) { std::string fanGroup = self->GetGroups()[0]; std::vector fanVolumes = EntityManager::Instance()->GetEntitiesInGroup(fanGroup); @@ -56,7 +56,7 @@ void AgFans::ToggleFX(Entity* self, bool hit) { } } -void AgFans::OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1, int32_t param2, +void WhFans::OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1, int32_t param2, int32_t param3) { if (args.length() == 0 || !self->GetVar(u"alive")) return; @@ -64,7 +64,7 @@ void AgFans::OnFireEventServerSide(Entity *self, Entity *sender, std::string arg ToggleFX(self, false); } -void AgFans::OnDie(Entity* self, Entity* killer) { +void WhFans::OnDie(Entity* self, Entity* killer) { if (self->GetVar(u"on")) { ToggleFX(self, true); } From 5b0f9174857dc16dd091924f80ae8db43b851a92 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Sun, 17 Apr 2022 00:05:04 -0500 Subject: [PATCH 183/251] update script path for fans --- dScripts/CppScripts.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dScripts/CppScripts.cpp b/dScripts/CppScripts.cpp index c81b01f4..8be1c0d4 100644 --- a/dScripts/CppScripts.cpp +++ b/dScripts/CppScripts.cpp @@ -802,7 +802,7 @@ CppScripts::Script* CppScripts::GetScript(Entity* parent, const std::string& scr // FB else if (scriptName == "scripts\\ai\\NS\\WH\\L_ROCKHYDRANT_BROKEN.lua") script = new RockHydrantBroken(); - else if (scriptName == "L_NS_WH_FANS.lua") + else if (scriptName == "scripts\\ai\\NS\\L_NS_WH_FANS.lua") script = new WhFans(); //Ignore these scripts: From 23677b4bd37fd88e86bb4a92f12e018b336c27ff Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Sun, 17 Apr 2022 12:38:12 -0500 Subject: [PATCH 184/251] Simplify some stuff Remove render component in startup --- dScripts/WhFans.cpp | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/dScripts/WhFans.cpp b/dScripts/WhFans.cpp index da9af43f..b11da6e5 100644 --- a/dScripts/WhFans.cpp +++ b/dScripts/WhFans.cpp @@ -7,22 +7,13 @@ void WhFans::OnStartup(Entity* self) { self->SetVar(u"on", false); ToggleFX(self, false); - - auto* renderComponent = static_cast(self->GetComponent(COMPONENT_TYPE_RENDER)); - - if (renderComponent == nullptr) { - return; - } - - renderComponent->PlayEffect(495, u"fanOn", "fanOn"); } void WhFans::ToggleFX(Entity* self, bool hit) { std::string fanGroup = self->GetGroups()[0]; std::vector fanVolumes = EntityManager::Instance()->GetEntitiesInGroup(fanGroup); - auto* renderComponent = static_cast(self->GetComponent(COMPONENT_TYPE_RENDER)); - + auto renderComponent = self->GetComponent(); if (renderComponent == nullptr) { return; } @@ -36,7 +27,7 @@ void WhFans::ToggleFX(Entity* self, bool hit) { self->SetVar(u"on", false); for (Entity* volume : fanVolumes) { - PhantomPhysicsComponent* volumePhys = static_cast(volume->GetComponent(COMPONENT_TYPE_PHANTOM_PHYSICS)); + auto phantomPhysicsComponent = volume->GetComponent(); if (!volumePhys) continue; volumePhys->SetPhysicsEffectActive(false); EntityManager::Instance()->SerializeEntity(volume); @@ -48,7 +39,7 @@ void WhFans::ToggleFX(Entity* self, bool hit) { self->SetVar(u"on", true); for (Entity* volume : fanVolumes) { - PhantomPhysicsComponent* volumePhys = static_cast(volume->GetComponent(COMPONENT_TYPE_PHANTOM_PHYSICS)); + auto phantomPhysicsComponent = volume->GetComponent(); if (!volumePhys) continue; volumePhys->SetPhysicsEffectActive(true); EntityManager::Instance()->SerializeEntity(volume); From 67615d568872c63900c6ed78ab244f5598e08f07 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Sun, 17 Apr 2022 12:46:41 -0500 Subject: [PATCH 185/251] fix volumen physics name --- dScripts/WhFans.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dScripts/WhFans.cpp b/dScripts/WhFans.cpp index b11da6e5..39bbab3b 100644 --- a/dScripts/WhFans.cpp +++ b/dScripts/WhFans.cpp @@ -27,7 +27,7 @@ void WhFans::ToggleFX(Entity* self, bool hit) { self->SetVar(u"on", false); for (Entity* volume : fanVolumes) { - auto phantomPhysicsComponent = volume->GetComponent(); + auto volumePhys = volume->GetComponent(); if (!volumePhys) continue; volumePhys->SetPhysicsEffectActive(false); EntityManager::Instance()->SerializeEntity(volume); @@ -39,7 +39,7 @@ void WhFans::ToggleFX(Entity* self, bool hit) { self->SetVar(u"on", true); for (Entity* volume : fanVolumes) { - auto phantomPhysicsComponent = volume->GetComponent(); + auto volumePhys = volume->GetComponent(); if (!volumePhys) continue; volumePhys->SetPhysicsEffectActive(true); EntityManager::Instance()->SerializeEntity(volume); From 1e85ae203563ebf6f5fc366aaa6a8d6b4afae8b5 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Sun, 17 Apr 2022 15:58:26 -0500 Subject: [PATCH 186/251] tabs and log --- dScripts/RockHydrantBroken.cpp | 51 +++++++++++++++++----------------- dScripts/WhFans.cpp | 2 ++ 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/dScripts/RockHydrantBroken.cpp b/dScripts/RockHydrantBroken.cpp index 2c145b36..b3d7f717 100644 --- a/dScripts/RockHydrantBroken.cpp +++ b/dScripts/RockHydrantBroken.cpp @@ -4,43 +4,44 @@ void RockHydrantBroken::OnStartup(Entity* self) { - self->AddTimer("playEffect", 1); + self->AddTimer("playEffect", 1); - const auto hydrant = "hydrant" + self->GetVar(u"hydrant"); + const auto hydrant = "hydrant" + self->GetVar(u"hydrant"); - const auto bouncers = EntityManager::Instance()->GetEntitiesInGroup(hydrant); + const auto bouncers = EntityManager::Instance()->GetEntitiesInGroup(hydrant); - Game::logger->Log("RockHydrantBroken", "Broken Hydrant spawned (%s)\n", hydrant.c_str()); + Game::logger->Log("RockHydrantBroken", "Broken Rock Hydrant spawned (%s)\n", hydrant.c_str()); - for (auto* bouncer : bouncers) - { - self->SetVar(u"bouncer", bouncer->GetObjectID()); + for (auto* bouncer : bouncers) + { + self->SetVar(u"bouncer", bouncer->GetObjectID()); + Game::logger->Log("RockHydrantBroken", "Activate Bouncer (%s)\n", bouncer.c_str()); - GameMessages::SendBouncerActiveStatus(bouncer->GetObjectID(), true, UNASSIGNED_SYSTEM_ADDRESS); + GameMessages::SendBouncerActiveStatus(bouncer->GetObjectID(), true, UNASSIGNED_SYSTEM_ADDRESS); - GameMessages::SendNotifyObject(bouncer->GetObjectID(), self->GetObjectID(), u"enableCollision", UNASSIGNED_SYSTEM_ADDRESS); - } + GameMessages::SendNotifyObject(bouncer->GetObjectID(), self->GetObjectID(), u"enableCollision", UNASSIGNED_SYSTEM_ADDRESS); + } - self->AddTimer("KillBroken", 25); + self->AddTimer("KillBroken", 10); } void RockHydrantBroken::OnTimerDone(Entity* self, std::string timerName) { - if (timerName == "KillBroken") - { - auto* bouncer = EntityManager::Instance()->GetEntity(self->GetVar(u"bouncer")); + if (timerName == "KillBroken") + { + auto* bouncer = EntityManager::Instance()->GetEntity(self->GetVar(u"bouncer")); - if (bouncer != nullptr) - { - GameMessages::SendBouncerActiveStatus(bouncer->GetObjectID(), false, UNASSIGNED_SYSTEM_ADDRESS); + if (bouncer != nullptr) + { + GameMessages::SendBouncerActiveStatus(bouncer->GetObjectID(), false, UNASSIGNED_SYSTEM_ADDRESS); - GameMessages::SendNotifyObject(bouncer->GetObjectID(), self->GetObjectID(), u"disableCollision", UNASSIGNED_SYSTEM_ADDRESS); - } + GameMessages::SendNotifyObject(bouncer->GetObjectID(), self->GetObjectID(), u"disableCollision", UNASSIGNED_SYSTEM_ADDRESS); + } - self->Kill(); - } - else if (timerName == "playEffect") - { - GameMessages::SendPlayFXEffect(self->GetObjectID(), 384, u"water", "water", LWOOBJID_EMPTY, 1, 1, true); - } + self->Kill(); + } + else if (timerName == "playEffect") + { + GameMessages::SendPlayFXEffect(self->GetObjectID(), 384, u"water", "water", LWOOBJID_EMPTY, 1, 1, true); + } } diff --git a/dScripts/WhFans.cpp b/dScripts/WhFans.cpp index 39bbab3b..dffedc14 100644 --- a/dScripts/WhFans.cpp +++ b/dScripts/WhFans.cpp @@ -11,6 +11,8 @@ void WhFans::OnStartup(Entity* self) { void WhFans::ToggleFX(Entity* self, bool hit) { std::string fanGroup = self->GetGroups()[0]; + + Game::logger->Log("WhFans", "Toggling FX for Fan Group(%s)\n", fanGroup.c_str()); std::vector fanVolumes = EntityManager::Instance()->GetEntitiesInGroup(fanGroup); auto renderComponent = self->GetComponent(); From a8fcb4c15375c2d3e86b7430cd72106e125b8311 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Sun, 17 Apr 2022 16:44:46 -0500 Subject: [PATCH 187/251] make the hydrant match the lua script --- dScripts/RockHydrantBroken.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dScripts/RockHydrantBroken.cpp b/dScripts/RockHydrantBroken.cpp index b3d7f717..8bae7f79 100644 --- a/dScripts/RockHydrantBroken.cpp +++ b/dScripts/RockHydrantBroken.cpp @@ -6,7 +6,7 @@ void RockHydrantBroken::OnStartup(Entity* self) { self->AddTimer("playEffect", 1); - const auto hydrant = "hydrant" + self->GetVar(u"hydrant"); + const auto hydrant = "hydrant0" + self->GetVar(u"hydrant"); const auto bouncers = EntityManager::Instance()->GetEntitiesInGroup(hydrant); From e696d26941e6240b718292aea351dc4c7153f807 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Sun, 17 Apr 2022 17:41:10 -0500 Subject: [PATCH 188/251] update the Effect ID --- dScripts/RockHydrantBroken.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dScripts/RockHydrantBroken.cpp b/dScripts/RockHydrantBroken.cpp index 8bae7f79..681335f2 100644 --- a/dScripts/RockHydrantBroken.cpp +++ b/dScripts/RockHydrantBroken.cpp @@ -42,6 +42,6 @@ void RockHydrantBroken::OnTimerDone(Entity* self, std::string timerName) } else if (timerName == "playEffect") { - GameMessages::SendPlayFXEffect(self->GetObjectID(), 384, u"water", "water", LWOOBJID_EMPTY, 1, 1, true); + GameMessages::SendPlayFXEffect(self->GetObjectID(), 4737, u"water", "water", LWOOBJID_EMPTY, 1, 1, true); } } From cc68b0768b4538b6723def491687c19f624ea985 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Sun, 17 Apr 2022 17:43:25 -0500 Subject: [PATCH 189/251] remove log --- dScripts/RockHydrantBroken.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dScripts/RockHydrantBroken.cpp b/dScripts/RockHydrantBroken.cpp index 681335f2..0347466c 100644 --- a/dScripts/RockHydrantBroken.cpp +++ b/dScripts/RockHydrantBroken.cpp @@ -15,7 +15,7 @@ void RockHydrantBroken::OnStartup(Entity* self) for (auto* bouncer : bouncers) { self->SetVar(u"bouncer", bouncer->GetObjectID()); - Game::logger->Log("RockHydrantBroken", "Activate Bouncer (%s)\n", bouncer.c_str()); + GameMessages::SendBouncerActiveStatus(bouncer->GetObjectID(), true, UNASSIGNED_SYSTEM_ADDRESS); From a343ed94933cb30b055d9928471e289005ece085 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Sun, 17 Apr 2022 19:43:17 -0500 Subject: [PATCH 190/251] rock hydrants work --- dScripts/RockHydrantBroken.cpp | 2 +- dScripts/RockHydrantSmashable.cpp | 33 +++++++++++++++---------------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/dScripts/RockHydrantBroken.cpp b/dScripts/RockHydrantBroken.cpp index 0347466c..7895b00b 100644 --- a/dScripts/RockHydrantBroken.cpp +++ b/dScripts/RockHydrantBroken.cpp @@ -6,7 +6,7 @@ void RockHydrantBroken::OnStartup(Entity* self) { self->AddTimer("playEffect", 1); - const auto hydrant = "hydrant0" + self->GetVar(u"hydrant"); + const auto hydrant = "hydrant" + self->GetVar(u"hydrant"); const auto bouncers = EntityManager::Instance()->GetEntitiesInGroup(hydrant); diff --git a/dScripts/RockHydrantSmashable.cpp b/dScripts/RockHydrantSmashable.cpp index a54f0b9d..04b39c84 100644 --- a/dScripts/RockHydrantSmashable.cpp +++ b/dScripts/RockHydrantSmashable.cpp @@ -1,24 +1,23 @@ #include "RockHydrantSmashable.h" #include "EntityManager.h" -#include "SimplePhysicsComponent.h" -#include "Entity.h" -#include "GameMessages.h" -#include "Game.h" -#include "dLogger.h" +#include "GeneralUtils.h" -void RockHydrantSmashable::OnDie(Entity* self, Entity* killer) { - SimplePhysicsComponent* physics = self->GetComponent(); - NiPoint3 pos = physics->GetPosition(); +void RockHydrantSmashable::OnDie(Entity* self, Entity* killer) +{ + const auto hydrantName = self->GetVar(u"hydrant"); - EntityInfo info; + LDFBaseData* data = new LDFData(u"hydrant", GeneralUtils::UTF16ToWTF8(hydrantName)); + + EntityInfo info {}; info.lot = 12293; - info.pos = pos; - info.spawner = nullptr; + info.pos = self->GetPosition(); + info.rot = self->GetRotation(); + info.settings = {data}; info.spawnerID = self->GetSpawnerID(); - info.spawnerNodeID = 0; - Entity* newEntity = EntityManager::Instance()->CreateEntity(info, nullptr); - if (newEntity) { - EntityManager::Instance()->ConstructEntity(newEntity); - } -} \ No newline at end of file + Game::logger->Log("RockHydrantBroken", "Rock Hydrant spawned (%s)\n", data->GetString().c_str()); + + auto* hydrant = EntityManager::Instance()->CreateEntity(info); + + EntityManager::Instance()->ConstructEntity(hydrant); +} From 235934714fca427bacaa92c0eae393b06c7f6045 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Sun, 17 Apr 2022 20:16:27 -0500 Subject: [PATCH 191/251] honor the logic in the lua script --- dScripts/WhFans.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dScripts/WhFans.cpp b/dScripts/WhFans.cpp index dffedc14..c6c798d9 100644 --- a/dScripts/WhFans.cpp +++ b/dScripts/WhFans.cpp @@ -10,7 +10,11 @@ void WhFans::OnStartup(Entity* self) { } void WhFans::ToggleFX(Entity* self, bool hit) { - std::string fanGroup = self->GetGroups()[0]; + try { + std::string fanGroup = self->GetGroups()[0]; + } catch(...) { + std::string fanGroup = "" + } Game::logger->Log("WhFans", "Toggling FX for Fan Group(%s)\n", fanGroup.c_str()); std::vector fanVolumes = EntityManager::Instance()->GetEntitiesInGroup(fanGroup); From 0778b4f81ce3e742e069c949040f7c9215584985 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Sun, 17 Apr 2022 20:17:36 -0500 Subject: [PATCH 192/251] missed semicolon --- dScripts/WhFans.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dScripts/WhFans.cpp b/dScripts/WhFans.cpp index c6c798d9..fe1aa01a 100644 --- a/dScripts/WhFans.cpp +++ b/dScripts/WhFans.cpp @@ -13,7 +13,7 @@ void WhFans::ToggleFX(Entity* self, bool hit) { try { std::string fanGroup = self->GetGroups()[0]; } catch(...) { - std::string fanGroup = "" + std::string fanGroup = ""; } Game::logger->Log("WhFans", "Toggling FX for Fan Group(%s)\n", fanGroup.c_str()); From 6cef7a437aef98758c2cc6c4c840291b1fcdbded Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Sun, 17 Apr 2022 20:24:19 -0500 Subject: [PATCH 193/251] scope --- dScripts/WhFans.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dScripts/WhFans.cpp b/dScripts/WhFans.cpp index fe1aa01a..ccf556be 100644 --- a/dScripts/WhFans.cpp +++ b/dScripts/WhFans.cpp @@ -10,10 +10,11 @@ void WhFans::OnStartup(Entity* self) { } void WhFans::ToggleFX(Entity* self, bool hit) { + std::string fanGroup = "" try { - std::string fanGroup = self->GetGroups()[0]; + fanGroup = self->GetGroups()[0]; } catch(...) { - std::string fanGroup = ""; + fanGroup = ""; } Game::logger->Log("WhFans", "Toggling FX for Fan Group(%s)\n", fanGroup.c_str()); From 263eaf03b07eb52a757a0c632e80e31fce95c59a Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Sun, 17 Apr 2022 20:24:49 -0500 Subject: [PATCH 194/251] ugh, another semicolon --- dScripts/WhFans.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dScripts/WhFans.cpp b/dScripts/WhFans.cpp index ccf556be..0139eb1d 100644 --- a/dScripts/WhFans.cpp +++ b/dScripts/WhFans.cpp @@ -10,7 +10,7 @@ void WhFans::OnStartup(Entity* self) { } void WhFans::ToggleFX(Entity* self, bool hit) { - std::string fanGroup = "" + std::string fanGroup = ""; try { fanGroup = self->GetGroups()[0]; } catch(...) { From 2122448284a1b8f55c582a3814903fb61860a4f1 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Sun, 17 Apr 2022 21:30:25 -0500 Subject: [PATCH 195/251] cleaning up some stuff --- dScripts/WhFans.cpp | 6 +----- dScripts/WhFans.h | 10 ++++++++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/dScripts/WhFans.cpp b/dScripts/WhFans.cpp index 0139eb1d..f2000d69 100644 --- a/dScripts/WhFans.cpp +++ b/dScripts/WhFans.cpp @@ -17,13 +17,9 @@ void WhFans::ToggleFX(Entity* self, bool hit) { fanGroup = ""; } - Game::logger->Log("WhFans", "Toggling FX for Fan Group(%s)\n", fanGroup.c_str()); std::vector fanVolumes = EntityManager::Instance()->GetEntitiesInGroup(fanGroup); - auto renderComponent = self->GetComponent(); - if (renderComponent == nullptr) { - return; - } + auto* renderComponent = static_cast(self->GetComponent(COMPONENT_TYPE_RENDER)); if (fanVolumes.size() == 0 || !self->GetVar(u"alive")) return; diff --git a/dScripts/WhFans.h b/dScripts/WhFans.h index 9b87430b..cac7236d 100644 --- a/dScripts/WhFans.h +++ b/dScripts/WhFans.h @@ -9,8 +9,14 @@ class WhFans : public CppScripts::Script public: void OnStartup(Entity* self); void OnDie(Entity* self, Entity* killer); - void OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1, int32_t param2, - int32_t param3); + void OnFireEventServerSide( + Entity *self, + Entity *sender, + std::string args, + int32_t param1, + int32_t param2, + int32_t param3 + ); private: void ToggleFX(Entity* self, bool hit); }; From 5691df9009556fc2ecbfff706c96afb3eb90dfd9 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 18 Apr 2022 01:04:29 -0700 Subject: [PATCH 196/251] Fixed Racing Mission * Try, Try Again achievement now progresses when the player gets last place in a race of 3 or more players, or when solo racing is enabled. * Race Series 1 mission from Velocity Lane now progresses correctly. --- dGame/dComponents/RacingControlComponent.cpp | 11 ++++++---- dGame/dMission/MissionTask.cpp | 21 ++++++++++++++++++-- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/dGame/dComponents/RacingControlComponent.cpp b/dGame/dComponents/RacingControlComponent.cpp index 27df339d..f3957fff 100644 --- a/dGame/dComponents/RacingControlComponent.cpp +++ b/dGame/dComponents/RacingControlComponent.cpp @@ -410,10 +410,13 @@ void RacingControlComponent::HandleMessageBoxResponse(Entity *player, // If solo racing is enabled OR if there are 3 players in the race, progress placement tasks. if(m_SoloRacing || m_LoadedPlayers > 2) { missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, data->finished, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_FINISH_WITH_PLACEMENT); // Finish in 1st place on a race - missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, data->finished, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_FIRST_PLACE_MULTIPLE_TRACKS); // Finish in 1st place on multiple tracks. - if(m_Finished != 1) return; - missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, dZoneManager::Instance()->GetZone()->GetWorldID(), (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_WIN_RACE_IN_WORLD); // Finished first place in specific world. - + if(data->finished == 1) { + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, dZoneManager::Instance()->GetZone()->GetWorldID(), (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_FIRST_PLACE_MULTIPLE_TRACKS); // Finish in 1st place on multiple tracks. + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, dZoneManager::Instance()->GetZone()->GetWorldID(), (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_WIN_RACE_IN_WORLD); // Finished first place in specific world. + } + if (data->finished == m_LoadedPlayers) { + missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, dZoneManager::Instance()->GetZone()->GetWorldID(), (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_LAST_PLACE_FINISH); // Finished first place in specific world. + } } } else if (id == "ACT_RACE_EXIT_THE_RACE?" || id == "Exit") { auto *vehicle = EntityManager::Instance()->GetEntity(data->vehicleID); diff --git a/dGame/dMission/MissionTask.cpp b/dGame/dMission/MissionTask.cpp index 1a340b23..30cd58a1 100644 --- a/dGame/dMission/MissionTask.cpp +++ b/dGame/dMission/MissionTask.cpp @@ -183,7 +183,13 @@ bool MissionTask::InParameters(const uint32_t value) const bool MissionTask::IsComplete() const { - return progress >= info->targetValue; + // Mission 668 has task uid 984 which is a bit mask. Its completion value is 3. + if (info->uid == 984) { + return progress >= 3; + } + else { + return progress >= info->targetValue; + } } @@ -423,12 +429,23 @@ void MissionTask::Progress(int32_t value, LWOOBJID associate, const std::string& if (parameters[0] != associate) break; - if (associate == 1 || associate == 15 || associate == 2 || associate == 3) + if (associate == 1 || associate == 2 || associate == 3) { if (value > info->targetValue) break; AddProgress(info->targetValue); } + // task 15 is a bit mask! + else if (associate == 15) { + if (!InAllTargets(value)) break; + + auto tempProgress = GetProgress(); + // If we won at Nimbus Station, set bit 0 + if (value == 1203) SetProgress(tempProgress |= 1 << 0); + // If we won at Gnarled Forest, set bit 1 + else if (value == 1303) SetProgress(tempProgress |= 1 << 1); + // If both bits are set, then the client sees the mission as complete. + } else if (associate == 10) { // If the player did not crash during the race, progress this task by count. From d05601ce642330910c6e23c43df9e81af823068f Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Mon, 18 Apr 2022 08:27:37 -0500 Subject: [PATCH 197/251] Fixes --- dScripts/WhFans.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/dScripts/WhFans.cpp b/dScripts/WhFans.cpp index f2000d69..24e6234c 100644 --- a/dScripts/WhFans.cpp +++ b/dScripts/WhFans.cpp @@ -10,16 +10,19 @@ void WhFans::OnStartup(Entity* self) { } void WhFans::ToggleFX(Entity* self, bool hit) { - std::string fanGroup = ""; - try { - fanGroup = self->GetGroups()[0]; - } catch(...) { + std::string fanGroup; + const auto& groups = self->GetGroups(); + if (!groups.empty()) { + fanGroup = groups[0]; + } else { fanGroup = ""; } std::vector fanVolumes = EntityManager::Instance()->GetEntitiesInGroup(fanGroup); - auto* renderComponent = static_cast(self->GetComponent(COMPONENT_TYPE_RENDER)); + auto* renderComponent = self->GetComponent(); + + if (renderComponent == nullptr) return; if (fanVolumes.size() == 0 || !self->GetVar(u"alive")) return; From 8fe5c009845fbc403bc963b84092dc3aef7e115f Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Mon, 18 Apr 2022 08:36:11 -0500 Subject: [PATCH 198/251] remove dereference (I think that's what it is called) --- dScripts/WhFans.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dScripts/WhFans.cpp b/dScripts/WhFans.cpp index 24e6234c..fc8fae0f 100644 --- a/dScripts/WhFans.cpp +++ b/dScripts/WhFans.cpp @@ -20,7 +20,7 @@ void WhFans::ToggleFX(Entity* self, bool hit) { std::vector fanVolumes = EntityManager::Instance()->GetEntitiesInGroup(fanGroup); - auto* renderComponent = self->GetComponent(); + auto* renderComponent = self->GetComponent(); if (renderComponent == nullptr) return; From f3dd71ccb1653d9d1d406ea22bfdd1a8aed7ea57 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Mon, 18 Apr 2022 21:02:04 -0500 Subject: [PATCH 199/251] cleanup logs, fix overrides, define LOTs in header --- dScripts/HydrantBroken.cpp | 8 +++----- dScripts/HydrantSmashable.cpp | 6 ++---- dScripts/HydrantSmashable.h | 6 ++++-- dScripts/RockHydrantBroken.cpp | 2 -- dScripts/RockHydrantSmashable.cpp | 8 +++----- dScripts/RockHydrantSmashable.h | 2 ++ dScripts/WhFans.cpp | 2 +- dScripts/WhFans.h | 6 +++--- 8 files changed, 18 insertions(+), 22 deletions(-) diff --git a/dScripts/HydrantBroken.cpp b/dScripts/HydrantBroken.cpp index 93424325..2b620a21 100644 --- a/dScripts/HydrantBroken.cpp +++ b/dScripts/HydrantBroken.cpp @@ -2,7 +2,7 @@ #include "EntityManager.h" #include "GameMessages.h" -void HydrantBroken::OnStartup(Entity* self) +void HydrantBroken::OnStartup(Entity* self) { self->AddTimer("playEffect", 1); @@ -10,8 +10,6 @@ void HydrantBroken::OnStartup(Entity* self) const auto bouncers = EntityManager::Instance()->GetEntitiesInGroup(hydrant); - Game::logger->Log("HydrantBroken", "Broken Hydrant spawned (%s)\n", hydrant.c_str()); - for (auto* bouncer : bouncers) { self->SetVar(u"bouncer", bouncer->GetObjectID()); @@ -20,11 +18,11 @@ void HydrantBroken::OnStartup(Entity* self) GameMessages::SendNotifyObject(bouncer->GetObjectID(), self->GetObjectID(), u"enableCollision", UNASSIGNED_SYSTEM_ADDRESS); } - + self->AddTimer("KillBroken", 25); } -void HydrantBroken::OnTimerDone(Entity* self, std::string timerName) +void HydrantBroken::OnTimerDone(Entity* self, std::string timerName) { if (timerName == "KillBroken") { diff --git a/dScripts/HydrantSmashable.cpp b/dScripts/HydrantSmashable.cpp index e39f7a35..5cdf84c9 100644 --- a/dScripts/HydrantSmashable.cpp +++ b/dScripts/HydrantSmashable.cpp @@ -2,20 +2,18 @@ #include "EntityManager.h" #include "GeneralUtils.h" -void HydrantSmashable::OnDie(Entity* self, Entity* killer) +void HydrantSmashable::OnDie(Entity* self, Entity* killer) { const auto hydrantName = self->GetVar(u"hydrant"); LDFBaseData* data = new LDFData(u"hydrant", GeneralUtils::UTF16ToWTF8(hydrantName)); EntityInfo info {}; - info.lot = 7328; + info.lot = HYDRANT_BROKEN; info.pos = self->GetPosition(); info.rot = self->GetRotation(); info.settings = {data}; info.spawnerID = self->GetSpawnerID(); - - Game::logger->Log("HydrantBroken", "Hydrant spawned (%s)\n", data->GetString().c_str()); auto* hydrant = EntityManager::Instance()->CreateEntity(info); diff --git a/dScripts/HydrantSmashable.h b/dScripts/HydrantSmashable.h index c7e23073..90b0f3a6 100644 --- a/dScripts/HydrantSmashable.h +++ b/dScripts/HydrantSmashable.h @@ -1,8 +1,10 @@ #pragma once #include "CppScripts.h" -class HydrantSmashable : public CppScripts::Script +class HydrantSmashable : public CppScripts::Script { public: - void OnDie(Entity* self, Entity* killer) override; + void OnDie(Entity* self, Entity* killer) override; +private: + LOT HYDRANT_BROKEN = 7328; }; \ No newline at end of file diff --git a/dScripts/RockHydrantBroken.cpp b/dScripts/RockHydrantBroken.cpp index 7895b00b..50e3c88d 100644 --- a/dScripts/RockHydrantBroken.cpp +++ b/dScripts/RockHydrantBroken.cpp @@ -10,8 +10,6 @@ void RockHydrantBroken::OnStartup(Entity* self) const auto bouncers = EntityManager::Instance()->GetEntitiesInGroup(hydrant); - Game::logger->Log("RockHydrantBroken", "Broken Rock Hydrant spawned (%s)\n", hydrant.c_str()); - for (auto* bouncer : bouncers) { self->SetVar(u"bouncer", bouncer->GetObjectID()); diff --git a/dScripts/RockHydrantSmashable.cpp b/dScripts/RockHydrantSmashable.cpp index 04b39c84..8d5b5861 100644 --- a/dScripts/RockHydrantSmashable.cpp +++ b/dScripts/RockHydrantSmashable.cpp @@ -9,15 +9,13 @@ void RockHydrantSmashable::OnDie(Entity* self, Entity* killer) LDFBaseData* data = new LDFData(u"hydrant", GeneralUtils::UTF16ToWTF8(hydrantName)); EntityInfo info {}; - info.lot = 12293; + info.lot = ROCK_HYDRANT_BROKEN; info.pos = self->GetPosition(); info.rot = self->GetRotation(); info.settings = {data}; info.spawnerID = self->GetSpawnerID(); - Game::logger->Log("RockHydrantBroken", "Rock Hydrant spawned (%s)\n", data->GetString().c_str()); + auto* hydrant = EntityManager::Instance()->CreateEntity(info); - auto* hydrant = EntityManager::Instance()->CreateEntity(info); - - EntityManager::Instance()->ConstructEntity(hydrant); + EntityManager::Instance()->ConstructEntity(hydrant); } diff --git a/dScripts/RockHydrantSmashable.h b/dScripts/RockHydrantSmashable.h index 12c21fb0..0578cb2e 100644 --- a/dScripts/RockHydrantSmashable.h +++ b/dScripts/RockHydrantSmashable.h @@ -5,5 +5,7 @@ class RockHydrantSmashable : public CppScripts::Script { public: void OnDie(Entity* self, Entity* killer); +private: + LOT ROCK_HYDRANT_BROKEN = 12293; }; diff --git a/dScripts/WhFans.cpp b/dScripts/WhFans.cpp index fc8fae0f..3a594a4c 100644 --- a/dScripts/WhFans.cpp +++ b/dScripts/WhFans.cpp @@ -66,4 +66,4 @@ void WhFans::OnDie(Entity* self, Entity* killer) { ToggleFX(self, true); } self->SetVar(u"alive", false); -} \ No newline at end of file +} diff --git a/dScripts/WhFans.h b/dScripts/WhFans.h index cac7236d..91aaa9d8 100644 --- a/dScripts/WhFans.h +++ b/dScripts/WhFans.h @@ -7,8 +7,8 @@ class WhFans : public CppScripts::Script { public: - void OnStartup(Entity* self); - void OnDie(Entity* self, Entity* killer); + void OnStartup(Entity* self) override; + void OnDie(Entity* self, Entity* killer) override; void OnFireEventServerSide( Entity *self, Entity *sender, @@ -16,7 +16,7 @@ public: int32_t param1, int32_t param2, int32_t param3 - ); + ) override; private: void ToggleFX(Entity* self, bool hit); }; From 8db7dfef755b61a63b6b9315a2677897a69a7692 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Mon, 18 Apr 2022 21:09:27 -0500 Subject: [PATCH 200/251] also apply overrides to AG fans --- dScripts/AgFans.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/dScripts/AgFans.h b/dScripts/AgFans.h index 0efe9c6d..09cc89d9 100644 --- a/dScripts/AgFans.h +++ b/dScripts/AgFans.h @@ -7,10 +7,16 @@ class AgFans : public CppScripts::Script { public: - void OnStartup(Entity* self); - void OnDie(Entity* self, Entity* killer); - void OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1, int32_t param2, - int32_t param3); + void OnStartup(Entity* self) override; + void OnDie(Entity* self, Entity* killer) override; + void OnFireEventServerSide( + Entity *self, + Entity *sender, + std::string args, + int32_t param1, + int32_t param2, + int32_t param3 + ) override; private: void ToggleFX(Entity* self, bool hit); }; From 6933b2c301985de163379abe3f1157bdda54f7a4 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Mon, 18 Apr 2022 23:33:09 -0500 Subject: [PATCH 201/251] case for putting you back into FB when leavign space blizzard --- dGame/dComponents/RacingControlComponent.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dGame/dComponents/RacingControlComponent.cpp b/dGame/dComponents/RacingControlComponent.cpp index 27df339d..8647cfb7 100644 --- a/dGame/dComponents/RacingControlComponent.cpp +++ b/dGame/dComponents/RacingControlComponent.cpp @@ -53,6 +53,11 @@ RacingControlComponent::RacingControlComponent(Entity *parent) m_MainWorld = 1200; break; + case 1261: + m_ActivityID = 60; + m_MainWorld = 1260; + break; + case 1303: m_ActivityID = 39; m_MainWorld = 1300; @@ -413,7 +418,7 @@ void RacingControlComponent::HandleMessageBoxResponse(Entity *player, missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, data->finished, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_FIRST_PLACE_MULTIPLE_TRACKS); // Finish in 1st place on multiple tracks. if(m_Finished != 1) return; missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, dZoneManager::Instance()->GetZone()->GetWorldID(), (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_WIN_RACE_IN_WORLD); // Finished first place in specific world. - + } } else if (id == "ACT_RACE_EXIT_THE_RACE?" || id == "Exit") { auto *vehicle = EntityManager::Instance()->GetEntity(data->vehicleID); From a3331d009db3d1c699dd565cc90bf2c40b387e90 Mon Sep 17 00:00:00 2001 From: Majo Date: Tue, 19 Apr 2022 12:33:57 +0200 Subject: [PATCH 202/251] Fix solo_racing for Frostburgh's Space Blizzard Racetrack --- dGame/dComponents/ScriptedActivityComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dComponents/ScriptedActivityComponent.cpp b/dGame/dComponents/ScriptedActivityComponent.cpp index 55add0b6..026fafce 100644 --- a/dGame/dComponents/ScriptedActivityComponent.cpp +++ b/dGame/dComponents/ScriptedActivityComponent.cpp @@ -28,7 +28,7 @@ ScriptedActivityComponent::ScriptedActivityComponent(Entity* parent, int activit const auto mapID = m_ActivityInfo.instanceMapID; - if ((mapID == 1203 || mapID == 1303 || mapID == 1403) && Game::config->GetValue("solo_racing") == "1") { + if ((mapID == 1203 || mapID == 1261 || mapID == 1303 || mapID == 1403) && Game::config->GetValue("solo_racing") == "1") { m_ActivityInfo.minTeamSize = 1; m_ActivityInfo.minTeams = 1; } From d4adb0e6e5b1dfe60ad6ab700bbd4641d495d151 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Tue, 19 Apr 2022 21:30:38 -0500 Subject: [PATCH 203/251] Fix migration 0 for cd server setting every component to 1901 instead of just component 39 Add migration to fix it for existing users and set the values back to what they were --- migrations/cdserver/0_nt_footrace.sql | 2 +- migrations/cdserver/4_nt_footrace_parrot.sql | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 migrations/cdserver/4_nt_footrace_parrot.sql diff --git a/migrations/cdserver/0_nt_footrace.sql b/migrations/cdserver/0_nt_footrace.sql index 2019f07d..fd37599e 100644 --- a/migrations/cdserver/0_nt_footrace.sql +++ b/migrations/cdserver/0_nt_footrace.sql @@ -1,6 +1,6 @@ BEGIN TRANSACTION; -UPDATE ComponentsRegistry SET component_id = 1901 WHERE id = 12916; +UPDATE ComponentsRegistry SET component_id = 1901 WHERE id = 12916 AND component_type = 39; INSERT INTO ActivityRewards (objectTemplate, ActivityRewardIndex, activityRating, LootMatrixIndex, CurrencyIndex, ChallengeRating, description) VALUES (1901, 166, -1, 598, 1, 4, 'NT Foot Race'); COMMIT; diff --git a/migrations/cdserver/4_nt_footrace_parrot.sql b/migrations/cdserver/4_nt_footrace_parrot.sql new file mode 100644 index 00000000..b1e7e012 --- /dev/null +++ b/migrations/cdserver/4_nt_footrace_parrot.sql @@ -0,0 +1,3 @@ +UPDATE ComponentsRegistry SET component_id = 12702 WHERE id = 12916 AND component_type = 2; +UPDATE ComponentsRegistry SET component_id = 6280 WHERE id = 12916 AND component_type = 3; +UPDATE ComponentsRegistry SET component_id = 1791 WHERE id = 12916 AND component_type = 7; \ No newline at end of file From d42cbb24739d20c69951a9279ffd3283b591befa Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Tue, 19 Apr 2022 21:36:09 -0500 Subject: [PATCH 204/251] make newline at end of file --- migrations/cdserver/4_nt_footrace_parrot.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrations/cdserver/4_nt_footrace_parrot.sql b/migrations/cdserver/4_nt_footrace_parrot.sql index b1e7e012..3d549815 100644 --- a/migrations/cdserver/4_nt_footrace_parrot.sql +++ b/migrations/cdserver/4_nt_footrace_parrot.sql @@ -1,3 +1,3 @@ UPDATE ComponentsRegistry SET component_id = 12702 WHERE id = 12916 AND component_type = 2; UPDATE ComponentsRegistry SET component_id = 6280 WHERE id = 12916 AND component_type = 3; -UPDATE ComponentsRegistry SET component_id = 1791 WHERE id = 12916 AND component_type = 7; \ No newline at end of file +UPDATE ComponentsRegistry SET component_id = 1791 WHERE id = 12916 AND component_type = 7; From 2e61839d93728d4193b5542558369f8cf05be61d Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Fri, 22 Apr 2022 00:10:15 -0700 Subject: [PATCH 205/251] isPlayer changes Changed isPlayer to check for whether the entity has a character instead of checking system address of entity. --- dGame/Entity.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 57b7af14..780ae45c 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -1739,7 +1739,7 @@ void Entity::CancelAllTimers() { } bool Entity::IsPlayer() const { - return m_TemplateID == 1 && GetSystemAddress() != UNASSIGNED_SYSTEM_ADDRESS; + return m_TemplateID == 1 && GetCharacter() != nullptr; } void Entity::TriggerEvent(std::string eventID, Entity* optionalTarget) { From 834b53b4ecbb51978b6afa63b7933a06886dfcb5 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 23 Apr 2022 04:13:23 -0700 Subject: [PATCH 206/251] Grammar error Level reward needed an underscore --- dCommon/dCommonVars.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dCommon/dCommonVars.h b/dCommon/dCommonVars.h index 680c0c1e..cbecdd37 100644 --- a/dCommon/dCommonVars.h +++ b/dCommon/dCommonVars.h @@ -493,7 +493,7 @@ enum eLootSourceType : int32_t { LOOT_SOURCE_CLAIMCODE, LOOT_SOURCE_CONSUMPTION, LOOT_SOURCE_CRAFTING, - LOOT_SOURCE_LEVELREWARD, + LOOT_SOURCE_LEVEL_REWARD, LOOT_SOURCE_RELOCATE }; From d0233a2cd064c78d2aa21dee0a7bacfb516204d0 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 23 Apr 2022 04:14:55 -0700 Subject: [PATCH 207/251] Updated AddItemToInventorySync AddItemToInventorySync now sends the correct loot source type --- dGame/dGameMessages/GameMessages.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 9e68941c..881b6ff5 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -411,7 +411,7 @@ void GameMessages::SendGMLevelBroadcast(const LWOOBJID& objectID, uint8_t level) SEND_PACKET_BROADCAST } -void GameMessages::SendAddItemToInventoryClientSync(Entity* entity, const SystemAddress& sysAddr, Item* item, const LWOOBJID& objectID, bool showFlyingLoot, int itemCount, LWOOBJID subKey) { +void GameMessages::SendAddItemToInventoryClientSync(Entity* entity, const SystemAddress& sysAddr, Item* item, const LWOOBJID& objectID, bool showFlyingLoot, int itemCount, LWOOBJID subKey, eLootSourceType lootSourceType) { CBITSTREAM CMSGHEADER @@ -421,8 +421,8 @@ void GameMessages::SendAddItemToInventoryClientSync(Entity* entity, const System bitStream.Write(item->GetInfo().isBOE); bitStream.Write(item->GetInfo().isBOP); - bitStream.Write0(); // Loot source - //if (invType != LOOTTYPE_NONE) bitStream.Write(invType); + bitStream.Write(lootSourceType != eLootSourceType::LOOT_SOURCE_NONE); // Loot source + if (lootSourceType != eLootSourceType::LOOT_SOURCE_NONE) bitStream.Write(lootSourceType); LWONameValue extraInfo; From 0eece14b6849cb1cbf71436bb4a86928c19cdd5f Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 23 Apr 2022 04:16:10 -0700 Subject: [PATCH 208/251] Vendor buyback inventory Fixed vendor buyback inventory so it properly scrolls when the player adds enough items to it. --- dGame/dComponents/InventoryComponent.cpp | 4 +++- dGame/dInventory/Inventory.cpp | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index 5d3dda2e..cca5dde0 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -88,7 +88,9 @@ Inventory* InventoryComponent::GetInventory(const eInventoryType type) case eInventoryType::VAULT_ITEMS: size = 40u; break; - + case eInventoryType::VENDOR_BUYBACK: + size = 27u; + break; default: break; } diff --git a/dGame/dInventory/Inventory.cpp b/dGame/dInventory/Inventory.cpp index b77be4b2..ae1715d7 100644 --- a/dGame/dInventory/Inventory.cpp +++ b/dGame/dInventory/Inventory.cpp @@ -90,17 +90,17 @@ int32_t Inventory::FindEmptySlot() { if (free <= 6) // Up from 1 { - if (type != ITEMS && type != VAULT_ITEMS) + if (type != ITEMS && type != VAULT_ITEMS && type != eInventoryType::VAULT_MODELS) { uint32_t newSize = size; - if (type == MODELS || type == VAULT_MODELS) + if (type == MODELS) { newSize = 240; } - else + else if (type == eInventoryType::VENDOR_BUYBACK) { - newSize += 20; + newSize += 9u; } if (newSize > GetSize()) From a4d934913c3ecf181ce3174ad8c41eaf211cb196 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 23 Apr 2022 05:13:06 -0700 Subject: [PATCH 209/251] added lootsource send in GM WIP commit --- dGame/Entity.cpp | 2 +- dGame/TradingManager.cpp | 4 ++-- dGame/dComponents/CharacterComponent.cpp | 2 +- dGame/dComponents/InventoryComponent.cpp | 17 ++++++++++------- dGame/dComponents/InventoryComponent.h | 3 ++- dGame/dComponents/PetComponent.cpp | 2 +- .../dComponents/PropertyManagementComponent.cpp | 4 ++-- dGame/dGameMessages/GameMessages.cpp | 16 ++++++++-------- dGame/dGameMessages/GameMessages.h | 2 +- dGame/dInventory/Item.cpp | 15 ++++++++------- dGame/dInventory/Item.h | 6 ++++-- dGame/dMission/Mission.cpp | 4 ++-- dGame/dUtilities/Loot.cpp | 2 +- dGame/dUtilities/Mail.cpp | 2 +- dGame/dUtilities/SlashCommandHandler.cpp | 6 +++--- dScripts/AmDropshipComputer.cpp | 2 +- dScripts/NPCAddRemoveItem.cpp | 2 +- dScripts/NjColeNPC.cpp | 2 +- dScripts/NjScrollChestServer.cpp | 2 +- dScripts/NpcCowboyServer.cpp | 2 +- dScripts/NpcPirateServer.cpp | 2 +- dScripts/NpcWispServer.cpp | 2 +- dScripts/NsConcertInstrument.cpp | 4 ++-- dScripts/NsTokenConsoleServer.cpp | 8 ++++---- dScripts/NtDukeServer.cpp | 2 +- dScripts/SGCannon.cpp | 2 +- dScripts/TokenConsoleServer.cpp | 12 +++++++----- dScripts/VeBricksampleServer.cpp | 2 +- dScripts/VeMissionConsole.cpp | 2 +- 29 files changed, 71 insertions(+), 62 deletions(-) diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 780ae45c..8a1d3c82 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -1637,7 +1637,7 @@ void Entity::PickupItem(const LWOOBJID& objectID) { } } else { - inv->AddItem(p.second.lot, p.second.count, INVALID, {}, LWOOBJID_EMPTY, true, false, LWOOBJID_EMPTY, INVALID, 1); + inv->AddItem(p.second.lot, p.second.count, INVALID, {}, LWOOBJID_EMPTY, true, false, LWOOBJID_EMPTY, INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_PICKUP); } } } diff --git a/dGame/TradingManager.cpp b/dGame/TradingManager.cpp index 0963aa6f..e178d130 100644 --- a/dGame/TradingManager.cpp +++ b/dGame/TradingManager.cpp @@ -170,12 +170,12 @@ void Trade::Complete() for (const auto& tradeItem : m_ItemsA) { - inventoryB->AddItem(tradeItem.itemLot, tradeItem.itemCount); + inventoryB->AddItem(tradeItem.itemLot, tradeItem.itemCount, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_TRADE); } for (const auto& tradeItem : m_ItemsB) { - inventoryA->AddItem(tradeItem.itemLot, tradeItem.itemCount); + inventoryA->AddItem(tradeItem.itemLot, tradeItem.itemCount, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_TRADE); } TradingManager::Instance()->CancelTrade(m_TradeId); diff --git a/dGame/dComponents/CharacterComponent.cpp b/dGame/dComponents/CharacterComponent.cpp index 590758b6..67b820c2 100644 --- a/dGame/dComponents/CharacterComponent.cpp +++ b/dGame/dComponents/CharacterComponent.cpp @@ -217,7 +217,7 @@ void CharacterComponent::HandleLevelUp() switch (reward->rewardType) { case 0: - inventoryComponent->AddItem(reward->value, reward->count); + inventoryComponent->AddItem(reward->value, reward->count, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_LEVEL_REWARD); break; case 4: { diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index cca5dde0..d7a059a0 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -150,7 +150,8 @@ void InventoryComponent::AddItem( const eInventoryType inventorySourceType, const int32_t sourceType, const bool bound, - int32_t preferredSlot) + int32_t preferredSlot, + eLootSourceType lootSourceType) { if (count == 0) { @@ -188,8 +189,7 @@ void InventoryComponent::AddItem( return; } - - auto* item = new Item(lot, inventory, slot, count, config, parent, showFlyingLoot, isModMoveAndEquip, subKey, bound); + auto* item = new Item(lot, inventory, slot, count, config, parent, showFlyingLoot, isModMoveAndEquip, subKey, bound, lootSourceType); if (missions != nullptr && !IsTransferInventory(inventoryType)) { @@ -255,6 +255,9 @@ void InventoryComponent::AddItem( if (slot == -1) { + // if (inventoryType == eInventoryType::VAULT_ITEMS || inventoryType == eInventoryType::VAULT_MODELS) { + + // } auto* player = dynamic_cast(GetParent()); if (player == nullptr) @@ -284,8 +287,8 @@ void InventoryComponent::AddItem( continue; } - - auto* item = new Item(lot, inventory, slot, size, {}, parent, showFlyingLoot, isModMoveAndEquip, subKey); + Game::logger->Log("InventoryComponent", "new item with source %i\n", lootSourceType); + auto* item = new Item(lot, inventory, slot, size, {}, parent, showFlyingLoot, isModMoveAndEquip, subKey, false, lootSourceType); isModMoveAndEquip = false; } @@ -369,7 +372,7 @@ void InventoryComponent::MoveItemToInventory(Item* item, const eInventoryType in left -= delta; - AddItem(lot, delta, inventory, {}, LWOOBJID_EMPTY, showFlyingLot, isModMoveAndEquip, LWOOBJID_EMPTY, origin->GetType(), 0, false, preferredSlot); + AddItem(lot, delta, inventory, {}, LWOOBJID_EMPTY, showFlyingLot, isModMoveAndEquip, LWOOBJID_EMPTY, origin->GetType(), 0, false, preferredSlot, eLootSourceType::LOOT_SOURCE_NONE); item->SetCount(item->GetCount() - delta, false, false); @@ -387,7 +390,7 @@ void InventoryComponent::MoveItemToInventory(Item* item, const eInventoryType in const auto delta = std::min(item->GetCount(), count); - AddItem(lot, delta, inventory, config, LWOOBJID_EMPTY, showFlyingLot, isModMoveAndEquip, LWOOBJID_EMPTY, origin->GetType(), 0, item->GetBound(), preferredSlot); + AddItem(lot, delta, inventory, config, LWOOBJID_EMPTY, showFlyingLot, isModMoveAndEquip, LWOOBJID_EMPTY, origin->GetType(), 0, item->GetBound(), preferredSlot, eLootSourceType::LOOT_SOURCE_NONE); item->SetCount(item->GetCount() - delta, false, false); } diff --git a/dGame/dComponents/InventoryComponent.h b/dGame/dComponents/InventoryComponent.h index 0a4cfdb3..d73ee51d 100644 --- a/dGame/dComponents/InventoryComponent.h +++ b/dGame/dComponents/InventoryComponent.h @@ -100,7 +100,8 @@ public: eInventoryType inventorySourceType = INVALID, int32_t sourceType = 0, bool bound = false, - int32_t preferredSlot = -1 + int32_t preferredSlot = -1, + eLootSourceType lootSourceType = eLootSourceType::LOOT_SOURCE_NONE ); /** diff --git a/dGame/dComponents/PetComponent.cpp b/dGame/dComponents/PetComponent.cpp index a5c1168d..4b61384d 100644 --- a/dGame/dComponents/PetComponent.cpp +++ b/dGame/dComponents/PetComponent.cpp @@ -615,7 +615,7 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) GameMessages::SendRegisterPetDBID(m_Tamer, petSubKey, tamer->GetSystemAddress()); - inventoryComponent->AddItem(m_Parent->GetLOT(), 1, MODELS, {}, LWOOBJID_EMPTY, true, false, petSubKey); + inventoryComponent->AddItem(m_Parent->GetLOT(), 1, MODELS, {}, LWOOBJID_EMPTY, true, false, petSubKey, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); auto* item = inventoryComponent->FindItemBySubKey(petSubKey, MODELS); if (item == nullptr) diff --git a/dGame/dComponents/PropertyManagementComponent.cpp b/dGame/dComponents/PropertyManagementComponent.cpp index f982326c..ad0ec7c3 100644 --- a/dGame/dComponents/PropertyManagementComponent.cpp +++ b/dGame/dComponents/PropertyManagementComponent.cpp @@ -491,7 +491,7 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet settings.push_back(propertyObjectID); settings.push_back(modelType); - inventoryComponent->AddItem(6662, 1, HIDDEN, settings, LWOOBJID_EMPTY, false, false, spawnerId, INVALID, 13, false, -1); + inventoryComponent->AddItem(6662, 1, HIDDEN, settings, LWOOBJID_EMPTY, false, false, spawnerId, INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_DELETION); auto* item = inventoryComponent->FindItemBySubKey(spawnerId); if (item == nullptr) { @@ -526,7 +526,7 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet return; } - inventoryComponent->AddItem(model->GetLOT(), 1, INVALID, {}, LWOOBJID_EMPTY, false); + inventoryComponent->AddItem(model->GetLOT(), 1, INVALID, {}, LWOOBJID_EMPTY, false, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_DELETION); auto* item = inventoryComponent->FindItemByLot(model->GetLOT()); diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 881b6ff5..d363f437 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -423,7 +423,7 @@ void GameMessages::SendAddItemToInventoryClientSync(Entity* entity, const System bitStream.Write(lootSourceType != eLootSourceType::LOOT_SOURCE_NONE); // Loot source if (lootSourceType != eLootSourceType::LOOT_SOURCE_NONE) bitStream.Write(lootSourceType); - + Game::logger->Log("GameMessages", "lootSource %i\n", lootSourceType); LWONameValue extraInfo; auto config = item->GetConfig(); @@ -451,8 +451,8 @@ void GameMessages::SendAddItemToInventoryClientSync(Entity* entity, const System auto* inventory = item->GetInventory(); const auto inventoryType = inventory->GetType(); - bitStream.Write(inventoryType != INVENTORY_DEFAULT); - if (inventoryType != INVENTORY_DEFAULT) bitStream.Write(inventoryType); + bitStream.Write(inventoryType != eInventoryType::ITEMS); + if (inventoryType != eInventoryType::ITEMS) bitStream.Write(inventoryType); bitStream.Write(itemCount != 1); if (itemCount != 1) bitStream.Write(itemCount); @@ -4700,7 +4700,7 @@ void GameMessages::HandleBuyFromVendor(RakNet::BitStream* inStream, Entity* enti inv->RemoveItem(tokenId, altCurrencyCost); - inv->AddItem(item, count); + inv->AddItem(item, count, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_VENDOR); } else { @@ -4726,7 +4726,7 @@ void GameMessages::HandleBuyFromVendor(RakNet::BitStream* inStream, Entity* enti } character->SetCoins(character->GetCoins() - (coinCost), LOOT_SOURCE_VENDOR); - inv->AddItem(item, count); + inv->AddItem(item, count, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_VENDOR); } GameMessages::SendVendorTransactionResult(entity, sysAddr); @@ -4769,7 +4769,7 @@ void GameMessages::HandleSellToVendor(RakNet::BitStream* inStream, Entity* entit if (Inventory::IsValidItem(itemComp.currencyLOT)) { const auto altCurrency = (itemComp.altCurrencyCost * sellScalar) * count; - inv->AddItem(itemComp.currencyLOT, std::floor(altCurrency)); // Return alt currencies like faction tokens. + inv->AddItem(itemComp.currencyLOT, std::floor(altCurrency), eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_VENDOR); // Return alt currencies like faction tokens. } //inv->RemoveItem(count, -1, iObjID); @@ -5590,11 +5590,11 @@ void GameMessages::HandleModularBuildFinish(RakNet::BitStream* inStream, Entity* if (count == 3) { - inv->AddItem(6416, 1, MODELS, config); + inv->AddItem(6416, 1, eInventoryType::MODELS, config, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_QUICKBUILD); } else if (count == 7) { - inv->AddItem(8092, 1, MODELS, config); + inv->AddItem(8092, 1, eInventoryType::MODELS, config, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_QUICKBUILD); } auto* missionComponent = character->GetComponent(); diff --git a/dGame/dGameMessages/GameMessages.h b/dGame/dGameMessages/GameMessages.h index ababed5f..f3997200 100644 --- a/dGame/dGameMessages/GameMessages.h +++ b/dGame/dGameMessages/GameMessages.h @@ -61,7 +61,7 @@ namespace GameMessages { void SendGMLevelBroadcast(const LWOOBJID& objectID, uint8_t level); void SendChatModeUpdate(const LWOOBJID& objectID, uint8_t level); - void SendAddItemToInventoryClientSync(Entity* entity, const SystemAddress& sysAddr, Item* item, const LWOOBJID& objectID, bool showFlyingLoot, int itemCount, LWOOBJID subKey = LWOOBJID_EMPTY); + void SendAddItemToInventoryClientSync(Entity* entity, const SystemAddress& sysAddr, Item* item, const LWOOBJID& objectID, bool showFlyingLoot, int itemCount, LWOOBJID subKey = LWOOBJID_EMPTY, eLootSourceType lootSourceType = eLootSourceType::LOOT_SOURCE_NONE); void SendNotifyClientFlagChange(const LWOOBJID& objectID, int iFlagID, bool bFlag, const SystemAddress& sysAddr); void SendChangeObjectWorldState(const LWOOBJID& objectID, int state, const SystemAddress& sysAddr); diff --git a/dGame/dInventory/Item.cpp b/dGame/dInventory/Item.cpp index 20f5321a..31601673 100644 --- a/dGame/dInventory/Item.cpp +++ b/dGame/dInventory/Item.cpp @@ -14,7 +14,7 @@ class Inventory; -Item::Item(const LWOOBJID id, const LOT lot, Inventory* inventory, const uint32_t slot, const uint32_t count, const bool bound, const std::vector& config, const LWOOBJID parent, LWOOBJID subKey) +Item::Item(const LWOOBJID id, const LOT lot, Inventory* inventory, const uint32_t slot, const uint32_t count, const bool bound, const std::vector& config, const LWOOBJID parent, LWOOBJID subKey, eLootSourceType lootSourceType) { if (!Inventory::IsValidItem(lot)) { @@ -46,7 +46,8 @@ Item::Item( bool showFlyingLoot, bool isModMoveAndEquip, LWOOBJID subKey, - bool bound) + bool bound, + eLootSourceType lootSourceType) { if (!Inventory::IsValidItem(lot)) { @@ -80,8 +81,8 @@ Item::Item( inventory->AddManagedItem(this); auto* entity = inventory->GetComponent()->GetParent(); - - GameMessages::SendAddItemToInventoryClientSync(entity, entity->GetSystemAddress(), this, id, showFlyingLoot, static_cast(this->count), subKey); + Game::logger->Log("test", "source %i\n", lootSourceType); + GameMessages::SendAddItemToInventoryClientSync(entity, entity->GetSystemAddress(), this, id, showFlyingLoot, static_cast(this->count), subKey, lootSourceType); if (isModMoveAndEquip) { @@ -176,7 +177,7 @@ void Item::SetCount(const uint32_t value, const bool silent, const bool disassem if (value > count) { - GameMessages::SendAddItemToInventoryClientSync(entity, entity->GetSystemAddress(), this, id, showFlyingLoot, delta); + GameMessages::SendAddItemToInventoryClientSync(entity, entity->GetSystemAddress(), this, id, showFlyingLoot, delta, 0LL); } else { @@ -374,7 +375,7 @@ void Item::Disassemble(const eInventoryType inventoryType) for (const auto mod : modArray) { - inventory->GetComponent()->AddItem(mod, 1, inventoryType); + inventory->GetComponent()->AddItem(mod, 1, inventoryType, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_DELETION); } } } @@ -472,7 +473,7 @@ void Item::DisassembleModel() continue; } - GetInventory()->GetComponent()->AddItem(brickID[0].NDObjectID, 1); + GetInventory()->GetComponent()->AddItem(brickID[0].NDObjectID, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_DELETION); } } diff --git a/dGame/dInventory/Item.h b/dGame/dInventory/Item.h index 83ebb633..dd81d7fe 100644 --- a/dGame/dInventory/Item.h +++ b/dGame/dInventory/Item.h @@ -36,7 +36,8 @@ public: bool bound, const std::vector& config, LWOOBJID parent, - LWOOBJID subKey + LWOOBJID subKey, + eLootSourceType lootSourceType = eLootSourceType::LOOT_SOURCE_NONE ); /** @@ -62,7 +63,8 @@ public: bool showFlyingLoot = true, bool isModMoveAndEquip = false, LWOOBJID subKey = LWOOBJID_EMPTY, - bool bound = false + bool bound = false, + eLootSourceType lootSourceType = eLootSourceType::LOOT_SOURCE_NONE ); ~Item(); diff --git a/dGame/dMission/Mission.cpp b/dGame/dMission/Mission.cpp index 14fc5a24..93a60ae9 100644 --- a/dGame/dMission/Mission.cpp +++ b/dGame/dMission/Mission.cpp @@ -463,7 +463,7 @@ void Mission::YieldRewards() { count = 0; } - inventoryComponent->AddItem(pair.first, count); + inventoryComponent->AddItem(pair.first, count, eInventoryType::INVALID, {}, 0LL, IsMission(), false, 0LL, eInventoryType::INVALID, 0, false, -1, IsMission() ? eLootSourceType::LOOT_SOURCE_MISSION : eLootSourceType::LOOT_SOURCE_ACHIEVEMENT); } if (info->reward_currency_repeatable > 0 || coinsToSend > 0) { @@ -496,7 +496,7 @@ void Mission::YieldRewards() { count = 0; } - inventoryComponent->AddItem(pair.first, count); + inventoryComponent->AddItem(pair.first, count, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, IsMission() ? eLootSourceType::LOOT_SOURCE_MISSION : eLootSourceType::LOOT_SOURCE_ACHIEVEMENT); } if (info->reward_currency > 0 || coinsToSend > 0) { diff --git a/dGame/dUtilities/Loot.cpp b/dGame/dUtilities/Loot.cpp index 635b2620..0cceaeb2 100644 --- a/dGame/dUtilities/Loot.cpp +++ b/dGame/dUtilities/Loot.cpp @@ -285,7 +285,7 @@ void LootGenerator::GiveLoot(Entity* player, std::unordered_map& r return; for (const auto& pair : result) { - inventoryComponent->AddItem(pair.first, pair.second); + inventoryComponent->AddItem(pair.first, pair.second, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); } } diff --git a/dGame/dUtilities/Mail.cpp b/dGame/dUtilities/Mail.cpp index 302ba1cd..d0718f4c 100644 --- a/dGame/dUtilities/Mail.cpp +++ b/dGame/dUtilities/Mail.cpp @@ -363,7 +363,7 @@ void Mail::HandleAttachmentCollect(RakNet::BitStream* packet, const SystemAddres auto inv = static_cast(player->GetComponent(COMPONENT_TYPE_INVENTORY)); if (!inv) return; - inv->AddItem(attachmentLOT, attachmentCount); + inv->AddItem(attachmentLOT, attachmentCount, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_MAIL); Mail::SendAttachmentRemoveConfirm(sysAddr, mailID); diff --git a/dGame/dUtilities/SlashCommandHandler.cpp b/dGame/dUtilities/SlashCommandHandler.cpp index 2e3e2be7..69ee60b0 100644 --- a/dGame/dUtilities/SlashCommandHandler.cpp +++ b/dGame/dUtilities/SlashCommandHandler.cpp @@ -794,7 +794,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit InventoryComponent * inventory = static_cast(entity->GetComponent(COMPONENT_TYPE_INVENTORY)); - inventory->AddItem(itemLOT, 1); + inventory->AddItem(itemLOT, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_MODERATION); } else if(args.size() == 2) { uint32_t itemLOT; @@ -814,7 +814,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit InventoryComponent* inventory = static_cast(entity->GetComponent(COMPONENT_TYPE_INVENTORY)); - inventory->AddItem(itemLOT, count); + inventory->AddItem(itemLOT, count, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_MODERATION); } else { ChatPackets::SendSystemMessage(sysAddr, u"Correct usage: /gmadditem "); @@ -1626,7 +1626,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit std::vector data {}; data.push_back(new LDFData(u"reforgedLOT", reforgedItem)); - inventoryComponent->AddItem(baseItem, 1, INVALID, data); + inventoryComponent->AddItem(baseItem, 1, eInventoryType::INVALID, data, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_MODERATION); } if (chatCommand == "crash" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_OPERATOR) diff --git a/dScripts/AmDropshipComputer.cpp b/dScripts/AmDropshipComputer.cpp index 4101f526..7f25574a 100644 --- a/dScripts/AmDropshipComputer.cpp +++ b/dScripts/AmDropshipComputer.cpp @@ -32,7 +32,7 @@ void AmDropshipComputer::OnUse(Entity* self, Entity* user) return; } - inventoryComponent->AddItem(12323, 1); + inventoryComponent->AddItem(12323, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); } void AmDropshipComputer::OnDie(Entity* self, Entity* killer) diff --git a/dScripts/NPCAddRemoveItem.cpp b/dScripts/NPCAddRemoveItem.cpp index 7d36c1e1..8cc2b6fd 100644 --- a/dScripts/NPCAddRemoveItem.cpp +++ b/dScripts/NPCAddRemoveItem.cpp @@ -11,7 +11,7 @@ void NPCAddRemoveItem::OnMissionDialogueOK(Entity *self, Entity *target, int mis for (const auto& itemSetting : missionSetting.second) { for (const auto& lot : itemSetting.items) { if (itemSetting.add && (missionState == MissionState::MISSION_STATE_AVAILABLE || missionState == MissionState::MISSION_STATE_COMPLETE_AVAILABLE)) { - inventory->AddItem(lot, 1); + inventory->AddItem(lot, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); } else if (itemSetting.remove && (missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE || missionState == MissionState::MISSION_STATE_COMPLETE_READY_TO_COMPLETE)) { inventory->RemoveItem(lot, 1); } diff --git a/dScripts/NjColeNPC.cpp b/dScripts/NjColeNPC.cpp index 54d38bda..e342e429 100644 --- a/dScripts/NjColeNPC.cpp +++ b/dScripts/NjColeNPC.cpp @@ -54,6 +54,6 @@ void NjColeNPC::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, return; } - inventoryComponent->AddItem(16644, 1); + inventoryComponent->AddItem(16644, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_VENDOR); } } diff --git a/dScripts/NjScrollChestServer.cpp b/dScripts/NjScrollChestServer.cpp index ba3fda7a..4677f827 100644 --- a/dScripts/NjScrollChestServer.cpp +++ b/dScripts/NjScrollChestServer.cpp @@ -12,6 +12,6 @@ void NjScrollChestServer::OnUse(Entity *self, Entity *user) { playerInventory->RemoveItem(keyLOT, 1); // Reward the player with the item set - playerInventory->AddItem(rewardItemLOT, 1); + playerInventory->AddItem(rewardItemLOT, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); } } diff --git a/dScripts/NpcCowboyServer.cpp b/dScripts/NpcCowboyServer.cpp index 7ec031b9..b92d921f 100644 --- a/dScripts/NpcCowboyServer.cpp +++ b/dScripts/NpcCowboyServer.cpp @@ -23,7 +23,7 @@ void NpcCowboyServer::OnMissionDialogueOK(Entity* self, Entity* target, int miss { if (inventoryComponent->GetLotCount(14378) == 0) { - inventoryComponent->AddItem(14378, 1); + inventoryComponent->AddItem(14378, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); } } else if (missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE || missionState == MissionState::MISSION_STATE_COMPLETE_READY_TO_COMPLETE) diff --git a/dScripts/NpcPirateServer.cpp b/dScripts/NpcPirateServer.cpp index 4a1db1f6..acf7e67f 100644 --- a/dScripts/NpcPirateServer.cpp +++ b/dScripts/NpcPirateServer.cpp @@ -9,7 +9,7 @@ void NpcPirateServer::OnMissionDialogueOK(Entity *self, Entity *target, int miss // Add or remove the lucky shovel based on whether the mission was completed or started if ((missionState == MissionState::MISSION_STATE_AVAILABLE || missionState == MissionState::MISSION_STATE_COMPLETE_AVAILABLE) && luckyShovel == nullptr) { - inventory->AddItem(14591, 1); + inventory->AddItem(14591, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); } else if (missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE || missionState == MissionState::MISSION_STATE_COMPLETE_READY_TO_COMPLETE) { inventory->RemoveItem(14591, 1); } diff --git a/dScripts/NpcWispServer.cpp b/dScripts/NpcWispServer.cpp index 2f94236d..3000b4c9 100644 --- a/dScripts/NpcWispServer.cpp +++ b/dScripts/NpcWispServer.cpp @@ -20,7 +20,7 @@ void NpcWispServer::OnMissionDialogueOK(Entity* self, Entity* target, int missio // For the daily we add the maelstrom vacuum if the player doesn't have it yet if (missionID == 1883 && (missionState == MissionState::MISSION_STATE_AVAILABLE || missionState == MissionState::MISSION_STATE_COMPLETE_AVAILABLE) && maelstromVacuum == nullptr) { - inventory->AddItem(maelstromVacuumLot, 1); + inventory->AddItem(maelstromVacuumLot, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); } else if (missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE || missionState == MissionState::MISSION_STATE_COMPLETE_READY_TO_COMPLETE) { inventory->RemoveItem(maelstromVacuumLot, 1); } diff --git a/dScripts/NsConcertInstrument.cpp b/dScripts/NsConcertInstrument.cpp index f0257c93..d1de993c 100644 --- a/dScripts/NsConcertInstrument.cpp +++ b/dScripts/NsConcertInstrument.cpp @@ -195,7 +195,7 @@ void NsConcertInstrument::EquipInstruments(Entity *self, Entity *player) { // Equip the left hand instrument const auto leftInstrumentLot = instrumentLotLeft.find(GetInstrumentLot(self))->second; if (leftInstrumentLot != LOT_NULL) { - inventory->AddItem(leftInstrumentLot, 1, TEMP_ITEMS, {}, LWOOBJID_EMPTY, false); + inventory->AddItem(leftInstrumentLot, 1, TEMP_ITEMS, {}, LWOOBJID_EMPTY, false, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); auto* leftInstrument = inventory->FindItemByLot(leftInstrumentLot, TEMP_ITEMS); leftInstrument->Equip(); } @@ -203,7 +203,7 @@ void NsConcertInstrument::EquipInstruments(Entity *self, Entity *player) { // Equip the right hand instrument const auto rightInstrumentLot = instrumentLotRight.find(GetInstrumentLot(self))->second; if (rightInstrumentLot != LOT_NULL) { - inventory->AddItem(rightInstrumentLot, 1, TEMP_ITEMS, {}, LWOOBJID_EMPTY, false); + inventory->AddItem(rightInstrumentLot, 1, TEMP_ITEMS, {}, LWOOBJID_EMPTY, false, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); auto* rightInstrument = inventory->FindItemByLot(rightInstrumentLot, TEMP_ITEMS); rightInstrument->Equip(); } diff --git a/dScripts/NsTokenConsoleServer.cpp b/dScripts/NsTokenConsoleServer.cpp index f6b022d0..0416a030 100644 --- a/dScripts/NsTokenConsoleServer.cpp +++ b/dScripts/NsTokenConsoleServer.cpp @@ -50,19 +50,19 @@ void NsTokenConsoleServer::OnUse(Entity* self, Entity* user) if (character->GetPlayerFlag(46)) { - inventoryComponent->AddItem(8321, 5); + inventoryComponent->AddItem(8321, 5, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_NONE); } else if (character->GetPlayerFlag(47)) { - inventoryComponent->AddItem(8318, 5); + inventoryComponent->AddItem(8318, 5, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_NONE); } else if (character->GetPlayerFlag(48)) { - inventoryComponent->AddItem(8320, 5); + inventoryComponent->AddItem(8320, 5, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_NONE); } else if (character->GetPlayerFlag(49)) { - inventoryComponent->AddItem(8319, 5); + inventoryComponent->AddItem(8319, 5, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_NONE); } missionComponent->ForceProgressTaskType(863, 1, 1, false); diff --git a/dScripts/NtDukeServer.cpp b/dScripts/NtDukeServer.cpp index 0f56d6cc..db278aa1 100644 --- a/dScripts/NtDukeServer.cpp +++ b/dScripts/NtDukeServer.cpp @@ -29,7 +29,7 @@ void NtDukeServer::OnMissionDialogueOK(Entity *self, Entity *target, int mission auto lotCount = inventoryComponent->GetLotCount(m_SwordLot); if ((state == MissionState::MISSION_STATE_AVAILABLE || state == MissionState::MISSION_STATE_ACTIVE) && lotCount < 1) { - inventoryComponent->AddItem(m_SwordLot, 1); + inventoryComponent->AddItem(m_SwordLot, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); } else if (state == MissionState::MISSION_STATE_READY_TO_COMPLETE) { inventoryComponent->RemoveItem(m_SwordLot, lotCount); } diff --git a/dScripts/SGCannon.cpp b/dScripts/SGCannon.cpp index 4b991253..efb7d7fc 100644 --- a/dScripts/SGCannon.cpp +++ b/dScripts/SGCannon.cpp @@ -574,7 +574,7 @@ void SGCannon::StopGame(Entity *self, bool cancel) { auto* inventory = player->GetComponent(); if (inventory != nullptr) { for (const auto rewardLot : self->GetVar>(RewardsVariable)) { - inventory->AddItem(rewardLot, 1, eInventoryType::MODELS); + inventory->AddItem(rewardLot, 1, eInventoryType::MODELS, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); } } diff --git a/dScripts/TokenConsoleServer.cpp b/dScripts/TokenConsoleServer.cpp index dcefe2f2..0ca18e76 100644 --- a/dScripts/TokenConsoleServer.cpp +++ b/dScripts/TokenConsoleServer.cpp @@ -21,15 +21,17 @@ void TokenConsoleServer::OnUse(Entity* self, Entity* user) { //figure out which faction the player belongs to: auto character = user->GetCharacter(); if (!character) return; - + // At this point the player has to be in a faction. + LOT tokenLOT = 0; if (character->GetPlayerFlag(ePlayerFlags::VENTURE_FACTION)) //venture - inv->AddItem(8321, tokensToGive); + tokenLOT = 8321; else if (character->GetPlayerFlag(ePlayerFlags::ASSEMBLY_FACTION)) //assembly - inv->AddItem(8318, tokensToGive); + tokenLOT = 8318; else if (character->GetPlayerFlag(ePlayerFlags::PARADOX_FACTION)) //paradox - inv->AddItem(8320, tokensToGive); + tokenLOT = 8320; else if (character->GetPlayerFlag(ePlayerFlags::SENTINEL_FACTION)) //sentinel - inv->AddItem(8319, tokensToGive); + tokenLOT = 8319; + inv->AddItem(tokenLOT, tokensToGive, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_NONE); } GameMessages::SendTerminateInteraction(user->GetObjectID(), eTerminateType::FROM_INTERACTION, self->GetObjectID()); diff --git a/dScripts/VeBricksampleServer.cpp b/dScripts/VeBricksampleServer.cpp index 42ccd460..f9d5f3d2 100644 --- a/dScripts/VeBricksampleServer.cpp +++ b/dScripts/VeBricksampleServer.cpp @@ -10,7 +10,7 @@ void VeBricksampleServer::OnUse(Entity *self, Entity *user) { auto* inventoryComponent = user->GetComponent(); if (loot && inventoryComponent != nullptr && inventoryComponent->GetLotCount(loot) == 0) { - inventoryComponent->AddItem(loot, 1); + inventoryComponent->AddItem(loot, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); for (auto* brickEntity : EntityManager::Instance()->GetEntitiesInGroup("Bricks")) { GameMessages::SendNotifyClientObject(brickEntity->GetObjectID(), u"Pickedup"); diff --git a/dScripts/VeMissionConsole.cpp b/dScripts/VeMissionConsole.cpp index 4a506dac..9e560244 100644 --- a/dScripts/VeMissionConsole.cpp +++ b/dScripts/VeMissionConsole.cpp @@ -8,7 +8,7 @@ void VeMissionConsole::OnUse(Entity *self, Entity *user) { auto* inventoryComponent = user->GetComponent(); if (inventoryComponent != nullptr) { - inventoryComponent->AddItem(12547, 1); // Add the panel required for pickup + inventoryComponent->AddItem(12547, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); // Add the panel required for pickup } // The flag to set is 101 From 8e10f090fd6309f5649184722fb6e864fbd0d066 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 23 Apr 2022 18:52:21 -0700 Subject: [PATCH 210/251] corrected number --- dGame/Entity.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 8a1d3c82..fbec1157 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -1637,7 +1637,7 @@ void Entity::PickupItem(const LWOOBJID& objectID) { } } else { - inv->AddItem(p.second.lot, p.second.count, INVALID, {}, LWOOBJID_EMPTY, true, false, LWOOBJID_EMPTY, INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_PICKUP); + inv->AddItem(p.second.lot, p.second.count, INVALID, {}, LWOOBJID_EMPTY, true, false, LWOOBJID_EMPTY, INVALID, 1, false, -1, eLootSourceType::LOOT_SOURCE_PICKUP); } } } From ceab229a63341ab763490f97724986bdf4c7e34d Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 23 Apr 2022 20:32:31 -0700 Subject: [PATCH 211/251] Specified enum the LOOT_SOURCE enum is now attached to all loot sources. --- dGame/Character.cpp | 2 +- dGame/TradingManager.cpp | 4 ++-- dGame/dComponents/CharacterComponent.cpp | 2 +- dGame/dComponents/DestroyableComponent.cpp | 2 +- dGame/dComponents/InventoryComponent.cpp | 2 +- dGame/dGameMessages/GameMessages.cpp | 28 +++++++++++----------- dGame/dMission/Mission.cpp | 6 ++--- dGame/dUtilities/Mail.cpp | 2 +- dGame/dUtilities/SlashCommandHandler.cpp | 6 ++--- 9 files changed, 27 insertions(+), 27 deletions(-) diff --git a/dGame/Character.cpp b/dGame/Character.cpp index d396382c..ce61ae70 100644 --- a/dGame/Character.cpp +++ b/dGame/Character.cpp @@ -534,7 +534,7 @@ void Character::OnZoneLoad() */ if (HasPermission(PermissionMap::Old)) { if (GetCoins() > 1000000) { - SetCoins(1000000, LOOT_SOURCE_NONE); + SetCoins(1000000, eLootSourceType::LOOT_SOURCE_NONE); } } diff --git a/dGame/TradingManager.cpp b/dGame/TradingManager.cpp index e178d130..c489c47b 100644 --- a/dGame/TradingManager.cpp +++ b/dGame/TradingManager.cpp @@ -151,8 +151,8 @@ void Trade::Complete() if (inventoryA == nullptr || inventoryB == nullptr || characterA == nullptr || characterB == nullptr || missionsA == nullptr || missionsB == nullptr) return; - characterA->SetCoins(characterA->GetCoins() - m_CoinsA + m_CoinsB, LOOT_SOURCE_TRADE); - characterB->SetCoins(characterB->GetCoins() - m_CoinsB + m_CoinsA, LOOT_SOURCE_TRADE); + characterA->SetCoins(characterA->GetCoins() - m_CoinsA + m_CoinsB, eLootSourceType::LOOT_SOURCE_TRADE); + characterB->SetCoins(characterB->GetCoins() - m_CoinsB + m_CoinsA, eLootSourceType::LOOT_SOURCE_TRADE); for (const auto& tradeItem : m_ItemsA) { diff --git a/dGame/dComponents/CharacterComponent.cpp b/dGame/dComponents/CharacterComponent.cpp index 67b820c2..8c4b0962 100644 --- a/dGame/dComponents/CharacterComponent.cpp +++ b/dGame/dComponents/CharacterComponent.cpp @@ -221,7 +221,7 @@ void CharacterComponent::HandleLevelUp() break; case 4: { - auto* items = inventoryComponent->GetInventory(ITEMS); + auto* items = inventoryComponent->GetInventory(eInventoryType::ITEMS); items->SetSize(items->GetSize() + reward->value); } break; diff --git a/dGame/dComponents/DestroyableComponent.cpp b/dGame/dComponents/DestroyableComponent.cpp index 31b3af19..8a99c069 100644 --- a/dGame/dComponents/DestroyableComponent.cpp +++ b/dGame/dComponents/DestroyableComponent.cpp @@ -821,7 +821,7 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType coinsTotal -= coinsToLoose; LootGenerator::Instance().DropLoot(m_Parent, m_Parent, -1, coinsToLoose, coinsToLoose); - character->SetCoins(coinsTotal, LOOT_SOURCE_PICKUP); + character->SetCoins(coinsTotal, eLootSourceType::LOOT_SOURCE_PICKUP); } } diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index d7a059a0..85d58065 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -207,7 +207,7 @@ void InventoryComponent::AddItem( auto stack = static_cast(info.stackSize); - if (inventoryType == BRICKS) + if (inventoryType == eInventoryType::BRICKS) { stack = 999; } diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index d363f437..b051ad45 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -566,8 +566,8 @@ void GameMessages::SendModifyLEGOScore(Entity* entity, const SystemAddress& sysA bitStream.Write((uint16_t)GAME_MSG_MODIFY_LEGO_SCORE); bitStream.Write(score); - bitStream.Write(sourceType != LOOT_SOURCE_NONE); - if (sourceType != LOOT_SOURCE_NONE) bitStream.Write(sourceType); + bitStream.Write(sourceType != eLootSourceType::LOOT_SOURCE_NONE); + if (sourceType != eLootSourceType::LOOT_SOURCE_NONE) bitStream.Write(sourceType); SEND_PACKET } @@ -4725,8 +4725,8 @@ void GameMessages::HandleBuyFromVendor(RakNet::BitStream* inStream, Entity* enti inv->RemoveItem(itemComp.currencyLOT, altCurrencyCost); } - character->SetCoins(character->GetCoins() - (coinCost), LOOT_SOURCE_VENDOR); inv->AddItem(item, count, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_VENDOR); + character->SetCoins(character->GetCoins() - (coinCost), eLootSourceType::LOOT_SOURCE_VENDOR); } GameMessages::SendVendorTransactionResult(entity, sysAddr); @@ -4773,8 +4773,8 @@ void GameMessages::HandleSellToVendor(RakNet::BitStream* inStream, Entity* entit } //inv->RemoveItem(count, -1, iObjID); - inv->MoveItemToInventory(item, VENDOR_BUYBACK, count, true, false, true); - character->SetCoins(std::floor(character->GetCoins() + ((itemComp.baseValue * sellScalar)*count)), LOOT_SOURCE_VENDOR); + inv->MoveItemToInventory(item, eInventoryType::VENDOR_BUYBACK, count, true, false, true); + character->SetCoins(std::floor(character->GetCoins() + ((itemComp.baseValue * sellScalar)*count)), eLootSourceType::LOOT_SOURCE_VENDOR); //EntityManager::Instance()->SerializeEntity(player); // so inventory updates GameMessages::SendVendorTransactionResult(entity, sysAddr); } @@ -4836,7 +4836,7 @@ void GameMessages::HandleBuybackFromVendor(RakNet::BitStream* inStream, Entity* //inv->RemoveItem(count, -1, iObjID); inv->MoveItemToInventory(item, Inventory::FindInventoryTypeForLot(item->GetLot()), count, true, false); - character->SetCoins(character->GetCoins() - cost, LOOT_SOURCE_VENDOR); + character->SetCoins(character->GetCoins() - cost, eLootSourceType::LOOT_SOURCE_VENDOR); //EntityManager::Instance()->SerializeEntity(player); // so inventory updates GameMessages::SendVendorTransactionResult(entity, sysAddr); } @@ -5269,7 +5269,7 @@ void GameMessages::HandlePickupCurrency(RakNet::BitStream* inStream, Entity* ent auto* ch = entity->GetCharacter(); if (entity->CanPickupCoins(currency)) { - ch->SetCoins(ch->GetCoins() + currency, LOOT_SOURCE_PICKUP); + ch->SetCoins(ch->GetCoins() + currency, eLootSourceType::LOOT_SOURCE_PICKUP); } } @@ -5484,8 +5484,8 @@ void GameMessages::HandleMoveItemInInventory(RakNet::BitStream* inStream, Entity } void GameMessages::HandleMoveItemBetweenInventoryTypes(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { - int inventoryTypeA; - int inventoryTypeB; + eInventoryType inventoryTypeA; + eInventoryType inventoryTypeB; LWOOBJID objectID; bool showFlyingLoot = true; bool stackCountIsDefault = false; @@ -5502,7 +5502,7 @@ void GameMessages::HandleMoveItemBetweenInventoryTypes(RakNet::BitStream* inStre inStream->Read(templateIDIsDefault); if (templateIDIsDefault) inStream->Read(templateID); - InventoryComponent* inv = static_cast(entity->GetComponent(COMPONENT_TYPE_INVENTORY)); + auto inv = entity->GetComponent(); if (!inv) return; auto* item = inv->FindItemById(objectID); @@ -5523,7 +5523,7 @@ void GameMessages::HandleMoveItemBetweenInventoryTypes(RakNet::BitStream* inStre } } - inv->MoveItemToInventory(item, static_cast(inventoryTypeB), stackCount, showFlyingLoot, false); + inv->MoveItemToInventory(item, inventoryTypeB, stackCount, showFlyingLoot); EntityManager::Instance()->SerializeEntity(entity); } @@ -5624,7 +5624,7 @@ void GameMessages::HandleModularBuildFinish(RakNet::BitStream* inStream, Entity* for (auto* item : items) { - inv->MoveItemToInventory(item, MODELS, item->GetCount(), false); + inv->MoveItemToInventory(item, eInventoryType::MODELS, item->GetCount(), false); } } @@ -5739,7 +5739,7 @@ void GameMessages::HandleDoneArrangingWithItem(RakNet::BitStream* inStream, Enti for (auto* item : items) { - inv->MoveItemToInventory(item, MODELS, item->GetCount(), false, false); + inv->MoveItemToInventory(item, eInventoryType::MODELS, item->GetCount(), false, false); } } @@ -5765,7 +5765,7 @@ void GameMessages::HandleModularBuildMoveAndEquip(RakNet::BitStream* inStream, E return; } - inv->MoveItemToInventory(item, MODELS, 1, false, true); + inv->MoveItemToInventory(item, eInventoryType::MODELS, 1, false, true); } void GameMessages::HandlePickupItem(RakNet::BitStream* inStream, Entity* entity) { diff --git a/dGame/dMission/Mission.cpp b/dGame/dMission/Mission.cpp index 93a60ae9..9732bb5b 100644 --- a/dGame/dMission/Mission.cpp +++ b/dGame/dMission/Mission.cpp @@ -430,7 +430,7 @@ void Mission::YieldRewards() { int32_t coinsToSend = 0; if (info->LegoScore > 0) { - eLootSourceType lootSource = info->isMission ? LOOT_SOURCE_MISSION : LOOT_SOURCE_ACHIEVEMENT; + eLootSourceType lootSource = info->isMission ? eLootSourceType::LOOT_SOURCE_MISSION : eLootSourceType::LOOT_SOURCE_ACHIEVEMENT; if(characterComponent->GetLevel() >= dZoneManager::Instance()->GetMaxLevel()) { // Since the character is at the level cap we reward them with coins instead of UScore. coinsToSend += info->LegoScore * dZoneManager::Instance()->GetLevelCapCurrencyConversion(); @@ -467,7 +467,7 @@ void Mission::YieldRewards() { } if (info->reward_currency_repeatable > 0 || coinsToSend > 0) { - eLootSourceType lootSource = info->isMission ? LOOT_SOURCE_MISSION : LOOT_SOURCE_ACHIEVEMENT; + eLootSourceType lootSource = info->isMission ? eLootSourceType::LOOT_SOURCE_MISSION : eLootSourceType::LOOT_SOURCE_ACHIEVEMENT; character->SetCoins(character->GetCoins() + info->reward_currency_repeatable + coinsToSend, lootSource); } @@ -500,7 +500,7 @@ void Mission::YieldRewards() { } if (info->reward_currency > 0 || coinsToSend > 0) { - eLootSourceType lootSource = info->isMission ? LOOT_SOURCE_MISSION : LOOT_SOURCE_ACHIEVEMENT; + eLootSourceType lootSource = info->isMission ? eLootSourceType::LOOT_SOURCE_MISSION : eLootSourceType::LOOT_SOURCE_ACHIEVEMENT; character->SetCoins(character->GetCoins() + info->reward_currency + coinsToSend, lootSource); } diff --git a/dGame/dUtilities/Mail.cpp b/dGame/dUtilities/Mail.cpp index d0718f4c..89cc0fff 100644 --- a/dGame/dUtilities/Mail.cpp +++ b/dGame/dUtilities/Mail.cpp @@ -262,7 +262,7 @@ void Mail::HandleSendMail(RakNet::BitStream* packet, const SystemAddress& sysAdd } Mail::SendSendResponse(sysAddr, Mail::MailSendResponse::Success); - entity->GetCharacter()->SetCoins(entity->GetCharacter()->GetCoins() - mailCost, LOOT_SOURCE_MAIL); + entity->GetCharacter()->SetCoins(entity->GetCharacter()->GetCoins() - mailCost, eLootSourceType::LOOT_SOURCE_MAIL); Game::logger->Log("Mail", "Seeing if we need to remove item with ID/count/LOT: %i %i %i\n", itemID, attachmentCount, itemLOT); diff --git a/dGame/dUtilities/SlashCommandHandler.cpp b/dGame/dUtilities/SlashCommandHandler.cpp index 69ee60b0..d94c8d47 100644 --- a/dGame/dUtilities/SlashCommandHandler.cpp +++ b/dGame/dUtilities/SlashCommandHandler.cpp @@ -1293,7 +1293,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit CharacterComponent* character = entity->GetComponent(); if (character) character->SetUScore(character->GetUScore() + uscore); // LOOT_SOURCE_MODERATION should work but it doesn't. Relog to see uscore changes - GameMessages::SendModifyLEGOScore(entity, entity->GetSystemAddress(), uscore, LOOT_SOURCE_MODERATION); + GameMessages::SendModifyLEGOScore(entity, entity->GetSystemAddress(), uscore, eLootSourceType::LOOT_SOURCE_MODERATION); } if (chatCommand == "pos" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { @@ -1337,7 +1337,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit } auto* ch = entity->GetCharacter(); - ch->SetCoins(ch->GetCoins() + money, LOOT_SOURCE_MODERATION); + ch->SetCoins(ch->GetCoins() + money, eLootSourceType::LOOT_SOURCE_MODERATION); } if ((chatCommand == "setcurrency") && args.size() == 1 && entity->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) { @@ -1350,7 +1350,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit } auto* ch = entity->GetCharacter(); - ch->SetCoins(money, LOOT_SOURCE_MODERATION); + ch->SetCoins(money, eLootSourceType::LOOT_SOURCE_MODERATION); } // Allow for this on even while not a GM, as it sometimes toggles incorrrectly. From 7a051afd97f49583a5fbfba7136a8077e41bb81f Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 23 Apr 2022 20:35:34 -0700 Subject: [PATCH 212/251] loot source for item drops Added support for Items to have a loot source attached to them when dropped or rolled. This fixes the issue where achievements would give the item before it appeared in the achievement window. --- dGame/Entity.cpp | 2 +- dGame/TradingManager.cpp | 4 ++-- dGame/dComponents/CharacterComponent.cpp | 2 +- dGame/dComponents/InventoryComponent.cpp | 15 ++++++--------- dGame/dComponents/InventoryComponent.h | 5 +++-- dGame/dComponents/PetComponent.cpp | 2 +- dGame/dComponents/PropertyManagementComponent.cpp | 4 ++-- dGame/dGameMessages/GameMessages.cpp | 12 ++++++------ dGame/dInventory/Item.cpp | 10 +++++----- dGame/dInventory/Item.h | 2 +- dGame/dMission/Mission.cpp | 4 ++-- dGame/dUtilities/Loot.cpp | 12 ++++++------ dGame/dUtilities/Loot.h | 4 ++-- dGame/dUtilities/Mail.cpp | 2 +- dGame/dUtilities/SlashCommandHandler.cpp | 6 +++--- dScripts/AmDropshipComputer.cpp | 2 +- dScripts/NPCAddRemoveItem.cpp | 2 +- dScripts/NjColeNPC.cpp | 2 +- dScripts/NjScrollChestServer.cpp | 2 +- dScripts/NpcCowboyServer.cpp | 2 +- dScripts/NpcPirateServer.cpp | 2 +- dScripts/NpcWispServer.cpp | 2 +- dScripts/NsConcertInstrument.cpp | 4 ++-- dScripts/NsTokenConsoleServer.cpp | 13 +++++++++---- dScripts/NtDukeServer.cpp | 2 +- dScripts/SGCannon.cpp | 2 +- dScripts/TokenConsoleServer.cpp | 2 +- dScripts/VeBricksampleServer.cpp | 2 +- dScripts/VeMissionConsole.cpp | 2 +- 29 files changed, 65 insertions(+), 62 deletions(-) diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index fbec1157..799e7803 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -1637,7 +1637,7 @@ void Entity::PickupItem(const LWOOBJID& objectID) { } } else { - inv->AddItem(p.second.lot, p.second.count, INVALID, {}, LWOOBJID_EMPTY, true, false, LWOOBJID_EMPTY, INVALID, 1, false, -1, eLootSourceType::LOOT_SOURCE_PICKUP); + inv->AddItem(p.second.lot, p.second.count, eLootSourceType::LOOT_SOURCE_PICKUP, eInventoryType::INVALID, {}, LWOOBJID_EMPTY, true, false, LWOOBJID_EMPTY, eInventoryType::INVALID, 1); } } } diff --git a/dGame/TradingManager.cpp b/dGame/TradingManager.cpp index c489c47b..04a0501d 100644 --- a/dGame/TradingManager.cpp +++ b/dGame/TradingManager.cpp @@ -170,12 +170,12 @@ void Trade::Complete() for (const auto& tradeItem : m_ItemsA) { - inventoryB->AddItem(tradeItem.itemLot, tradeItem.itemCount, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_TRADE); + inventoryB->AddItem(tradeItem.itemLot, tradeItem.itemCount, eLootSourceType::LOOT_SOURCE_TRADE); } for (const auto& tradeItem : m_ItemsB) { - inventoryA->AddItem(tradeItem.itemLot, tradeItem.itemCount, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_TRADE); + inventoryA->AddItem(tradeItem.itemLot, tradeItem.itemCount, eLootSourceType::LOOT_SOURCE_TRADE); } TradingManager::Instance()->CancelTrade(m_TradeId); diff --git a/dGame/dComponents/CharacterComponent.cpp b/dGame/dComponents/CharacterComponent.cpp index 8c4b0962..815a3d59 100644 --- a/dGame/dComponents/CharacterComponent.cpp +++ b/dGame/dComponents/CharacterComponent.cpp @@ -217,7 +217,7 @@ void CharacterComponent::HandleLevelUp() switch (reward->rewardType) { case 0: - inventoryComponent->AddItem(reward->value, reward->count, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_LEVEL_REWARD); + inventoryComponent->AddItem(reward->value, reward->count, eLootSourceType::LOOT_SOURCE_LEVEL_REWARD); break; case 4: { diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index 85d58065..e03f4e92 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -141,6 +141,7 @@ const EquipmentMap& InventoryComponent::GetEquippedItems() const void InventoryComponent::AddItem( const LOT lot, const uint32_t count, + eLootSourceType lootSourceType, eInventoryType inventoryType, const std::vector& config, const LWOOBJID parent, @@ -150,8 +151,7 @@ void InventoryComponent::AddItem( const eInventoryType inventorySourceType, const int32_t sourceType, const bool bound, - int32_t preferredSlot, - eLootSourceType lootSourceType) + int32_t preferredSlot) { if (count == 0) { @@ -181,7 +181,7 @@ void InventoryComponent::AddItem( if (!config.empty() || bound) { - const auto slot = inventory->FindEmptySlot(); + const auto slot = preferredSlot != -1 && inventory->IsSlotEmpty(preferredSlot) ? preferredSlot : inventory->FindEmptySlot(); if (slot == -1) { @@ -224,7 +224,7 @@ void InventoryComponent::AddItem( left -= delta; - existing->SetCount(existing->GetCount() + delta, false, true, showFlyingLoot); + existing->SetCount(existing->GetCount() + delta, false, true, showFlyingLoot, lootSourceType); if (isModMoveAndEquip) { @@ -255,9 +255,6 @@ void InventoryComponent::AddItem( if (slot == -1) { - // if (inventoryType == eInventoryType::VAULT_ITEMS || inventoryType == eInventoryType::VAULT_MODELS) { - - // } auto* player = dynamic_cast(GetParent()); if (player == nullptr) @@ -372,7 +369,7 @@ void InventoryComponent::MoveItemToInventory(Item* item, const eInventoryType in left -= delta; - AddItem(lot, delta, inventory, {}, LWOOBJID_EMPTY, showFlyingLot, isModMoveAndEquip, LWOOBJID_EMPTY, origin->GetType(), 0, false, preferredSlot, eLootSourceType::LOOT_SOURCE_NONE); + AddItem(lot, delta, eLootSourceType::LOOT_SOURCE_NONE, inventory, {}, LWOOBJID_EMPTY, showFlyingLot, isModMoveAndEquip, LWOOBJID_EMPTY, origin->GetType(), 0, false, preferredSlot); item->SetCount(item->GetCount() - delta, false, false); @@ -390,7 +387,7 @@ void InventoryComponent::MoveItemToInventory(Item* item, const eInventoryType in const auto delta = std::min(item->GetCount(), count); - AddItem(lot, delta, inventory, config, LWOOBJID_EMPTY, showFlyingLot, isModMoveAndEquip, LWOOBJID_EMPTY, origin->GetType(), 0, item->GetBound(), preferredSlot, eLootSourceType::LOOT_SOURCE_NONE); + AddItem(lot, delta, eLootSourceType::LOOT_SOURCE_NONE, inventory, config, LWOOBJID_EMPTY, showFlyingLot, isModMoveAndEquip, LWOOBJID_EMPTY, origin->GetType(), 0, item->GetBound(), preferredSlot); item->SetCount(item->GetCount() - delta, false, false); } diff --git a/dGame/dComponents/InventoryComponent.h b/dGame/dComponents/InventoryComponent.h index d73ee51d..bf18d132 100644 --- a/dGame/dComponents/InventoryComponent.h +++ b/dGame/dComponents/InventoryComponent.h @@ -87,10 +87,12 @@ public: * @param sourceType the source of the item, used to determine if the item is dropped or mailed if the inventory is full * @param bound whether this item is bound * @param preferredSlot the preferred slot to store this item + * @param lootSourceType The source of the loot. Defaults to none. */ void AddItem( LOT lot, uint32_t count, + eLootSourceType lootSourceType = eLootSourceType::LOOT_SOURCE_NONE, eInventoryType inventoryType = INVALID, const std::vector& config = {}, LWOOBJID parent = LWOOBJID_EMPTY, @@ -100,8 +102,7 @@ public: eInventoryType inventorySourceType = INVALID, int32_t sourceType = 0, bool bound = false, - int32_t preferredSlot = -1, - eLootSourceType lootSourceType = eLootSourceType::LOOT_SOURCE_NONE + int32_t preferredSlot = -1 ); /** diff --git a/dGame/dComponents/PetComponent.cpp b/dGame/dComponents/PetComponent.cpp index 4b61384d..97c7e95b 100644 --- a/dGame/dComponents/PetComponent.cpp +++ b/dGame/dComponents/PetComponent.cpp @@ -615,7 +615,7 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) GameMessages::SendRegisterPetDBID(m_Tamer, petSubKey, tamer->GetSystemAddress()); - inventoryComponent->AddItem(m_Parent->GetLOT(), 1, MODELS, {}, LWOOBJID_EMPTY, true, false, petSubKey, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); + inventoryComponent->AddItem(m_Parent->GetLOT(), 1, eLootSourceType::LOOT_SOURCE_ACTIVITY, eInventoryType::MODELS, {}, LWOOBJID_EMPTY, true, false, petSubKey); auto* item = inventoryComponent->FindItemBySubKey(petSubKey, MODELS); if (item == nullptr) diff --git a/dGame/dComponents/PropertyManagementComponent.cpp b/dGame/dComponents/PropertyManagementComponent.cpp index ad0ec7c3..0a428e04 100644 --- a/dGame/dComponents/PropertyManagementComponent.cpp +++ b/dGame/dComponents/PropertyManagementComponent.cpp @@ -491,7 +491,7 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet settings.push_back(propertyObjectID); settings.push_back(modelType); - inventoryComponent->AddItem(6662, 1, HIDDEN, settings, LWOOBJID_EMPTY, false, false, spawnerId, INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_DELETION); + inventoryComponent->AddItem(6662, 1, eLootSourceType::LOOT_SOURCE_DELETION, eInventoryType::HIDDEN, settings, LWOOBJID_EMPTY, false, false, spawnerId); auto* item = inventoryComponent->FindItemBySubKey(spawnerId); if (item == nullptr) { @@ -526,7 +526,7 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet return; } - inventoryComponent->AddItem(model->GetLOT(), 1, INVALID, {}, LWOOBJID_EMPTY, false, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_DELETION); + inventoryComponent->AddItem(model->GetLOT(), 1, eLootSourceType::LOOT_SOURCE_DELETION, INVALID, {}, LWOOBJID_EMPTY, false); auto* item = inventoryComponent->FindItemByLot(model->GetLOT()); diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index b051ad45..e0f38dbe 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -4700,7 +4700,7 @@ void GameMessages::HandleBuyFromVendor(RakNet::BitStream* inStream, Entity* enti inv->RemoveItem(tokenId, altCurrencyCost); - inv->AddItem(item, count, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_VENDOR); + inv->AddItem(item, count, eLootSourceType::LOOT_SOURCE_VENDOR); } else { @@ -4725,8 +4725,8 @@ void GameMessages::HandleBuyFromVendor(RakNet::BitStream* inStream, Entity* enti inv->RemoveItem(itemComp.currencyLOT, altCurrencyCost); } - inv->AddItem(item, count, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_VENDOR); character->SetCoins(character->GetCoins() - (coinCost), eLootSourceType::LOOT_SOURCE_VENDOR); + inv->AddItem(item, count, eLootSourceType::LOOT_SOURCE_VENDOR); } GameMessages::SendVendorTransactionResult(entity, sysAddr); @@ -4769,7 +4769,7 @@ void GameMessages::HandleSellToVendor(RakNet::BitStream* inStream, Entity* entit if (Inventory::IsValidItem(itemComp.currencyLOT)) { const auto altCurrency = (itemComp.altCurrencyCost * sellScalar) * count; - inv->AddItem(itemComp.currencyLOT, std::floor(altCurrency), eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_VENDOR); // Return alt currencies like faction tokens. + inv->AddItem(itemComp.currencyLOT, std::floor(altCurrency), eLootSourceType::LOOT_SOURCE_VENDOR); // Return alt currencies like faction tokens. } //inv->RemoveItem(count, -1, iObjID); @@ -5103,7 +5103,7 @@ void GameMessages::HandleModularBuildConvertModel(RakNet::BitStream* inStream, E item->Disassemble(TEMP_MODELS); - item->SetCount(item->GetCount() - 1, false, false); + item->SetCount(item->GetCount() - 1, false, false, true, eLootSourceType::LOOT_SOURCE_QUICKBUILD); } void GameMessages::HandleSetFlag(RakNet::BitStream* inStream, Entity* entity) { @@ -5590,11 +5590,11 @@ void GameMessages::HandleModularBuildFinish(RakNet::BitStream* inStream, Entity* if (count == 3) { - inv->AddItem(6416, 1, eInventoryType::MODELS, config, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_QUICKBUILD); + inv->AddItem(6416, 1, eLootSourceType::LOOT_SOURCE_QUICKBUILD, eInventoryType::MODELS, config); } else if (count == 7) { - inv->AddItem(8092, 1, eInventoryType::MODELS, config, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_QUICKBUILD); + inv->AddItem(8092, 1, eLootSourceType::LOOT_SOURCE_QUICKBUILD, eInventoryType::MODELS, config); } auto* missionComponent = character->GetComponent(); diff --git a/dGame/dInventory/Item.cpp b/dGame/dInventory/Item.cpp index 31601673..213430d2 100644 --- a/dGame/dInventory/Item.cpp +++ b/dGame/dInventory/Item.cpp @@ -149,7 +149,7 @@ PreconditionExpression* Item::GetPreconditionExpression() const return preconditions; } -void Item::SetCount(const uint32_t value, const bool silent, const bool disassemble, const bool showFlyingLoot) +void Item::SetCount(const uint32_t value, const bool silent, const bool disassemble, const bool showFlyingLoot, eLootSourceType lootSourceType) { if (value == count) { @@ -177,7 +177,7 @@ void Item::SetCount(const uint32_t value, const bool silent, const bool disassem if (value > count) { - GameMessages::SendAddItemToInventoryClientSync(entity, entity->GetSystemAddress(), this, id, showFlyingLoot, delta, 0LL); + GameMessages::SendAddItemToInventoryClientSync(entity, entity->GetSystemAddress(), this, id, showFlyingLoot, delta, LWOOBJID_EMPTY, lootSourceType); } else { @@ -341,7 +341,7 @@ bool Item::UseNonEquip() return false; } - LootGenerator::Instance().GiveLoot(inventory->GetComponent()->GetParent(), result); + LootGenerator::Instance().GiveLoot(inventory->GetComponent()->GetParent(), result, eLootSourceType::LOOT_SOURCE_CONSUMPTION); } inventory->GetComponent()->RemoveItem(lot, 1); @@ -375,7 +375,7 @@ void Item::Disassemble(const eInventoryType inventoryType) for (const auto mod : modArray) { - inventory->GetComponent()->AddItem(mod, 1, inventoryType, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_DELETION); + inventory->GetComponent()->AddItem(mod, 1, eLootSourceType::LOOT_SOURCE_DELETION, inventoryType); } } } @@ -473,7 +473,7 @@ void Item::DisassembleModel() continue; } - GetInventory()->GetComponent()->AddItem(brickID[0].NDObjectID, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_DELETION); + GetInventory()->GetComponent()->AddItem(brickID[0].NDObjectID, 1, eLootSourceType::LOOT_SOURCE_DELETION); } } diff --git a/dGame/dInventory/Item.h b/dGame/dInventory/Item.h index dd81d7fe..0be9449a 100644 --- a/dGame/dInventory/Item.h +++ b/dGame/dInventory/Item.h @@ -88,7 +88,7 @@ public: * @param disassemble if items were removed, this returns all the sub parts of the item individually if it had assembly part lots * @param showFlyingLoot shows flying loot to the client, if not silent */ - void SetCount(uint32_t value, bool silent = false, bool disassemble = true, bool showFlyingLoot = true); + void SetCount(uint32_t value, bool silent = false, bool disassemble = true, bool showFlyingLoot = true, eLootSourceType lootSourceType = eLootSourceType::LOOT_SOURCE_NONE); /** * Returns the number of items this item represents (e.g. for stacks) diff --git a/dGame/dMission/Mission.cpp b/dGame/dMission/Mission.cpp index 9732bb5b..c2553f24 100644 --- a/dGame/dMission/Mission.cpp +++ b/dGame/dMission/Mission.cpp @@ -463,7 +463,7 @@ void Mission::YieldRewards() { count = 0; } - inventoryComponent->AddItem(pair.first, count, eInventoryType::INVALID, {}, 0LL, IsMission(), false, 0LL, eInventoryType::INVALID, 0, false, -1, IsMission() ? eLootSourceType::LOOT_SOURCE_MISSION : eLootSourceType::LOOT_SOURCE_ACHIEVEMENT); + inventoryComponent->AddItem(pair.first, count, IsMission() ? eLootSourceType::LOOT_SOURCE_MISSION : eLootSourceType::LOOT_SOURCE_ACHIEVEMENT); } if (info->reward_currency_repeatable > 0 || coinsToSend > 0) { @@ -496,7 +496,7 @@ void Mission::YieldRewards() { count = 0; } - inventoryComponent->AddItem(pair.first, count, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, IsMission() ? eLootSourceType::LOOT_SOURCE_MISSION : eLootSourceType::LOOT_SOURCE_ACHIEVEMENT); + inventoryComponent->AddItem(pair.first, count, IsMission() ? eLootSourceType::LOOT_SOURCE_MISSION : eLootSourceType::LOOT_SOURCE_ACHIEVEMENT); } if (info->reward_currency > 0 || coinsToSend > 0) { diff --git a/dGame/dUtilities/Loot.cpp b/dGame/dUtilities/Loot.cpp index 0cceaeb2..8305e152 100644 --- a/dGame/dUtilities/Loot.cpp +++ b/dGame/dUtilities/Loot.cpp @@ -268,15 +268,15 @@ std::unordered_map LootGenerator::RollLootMatrix(uint32_t matrixIn return drops; } -void LootGenerator::GiveLoot(Entity* player, uint32_t matrixIndex) { +void LootGenerator::GiveLoot(Entity* player, uint32_t matrixIndex, eLootSourceType lootSourceType) { player = player->GetOwner(); // If the owner is overwritten, we collect that here std::unordered_map result = RollLootMatrix(player, matrixIndex); - GiveLoot(player, result); + GiveLoot(player, result, lootSourceType); } -void LootGenerator::GiveLoot(Entity* player, std::unordered_map& result) { +void LootGenerator::GiveLoot(Entity* player, std::unordered_map& result, eLootSourceType lootSourceType) { player = player->GetOwner(); // if the owner is overwritten, we collect that here auto* inventoryComponent = player->GetComponent(); @@ -285,7 +285,7 @@ void LootGenerator::GiveLoot(Entity* player, std::unordered_map& r return; for (const auto& pair : result) { - inventoryComponent->AddItem(pair.first, pair.second, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); + inventoryComponent->AddItem(pair.first, pair.second, lootSourceType); } } @@ -314,13 +314,13 @@ void LootGenerator::GiveActivityLoot(Entity* player, Entity* source, uint32_t ac maxCoins = currencyTable[0].maxvalue; } - GiveLoot(player, selectedReward->LootMatrixIndex); + GiveLoot(player, selectedReward->LootMatrixIndex, eLootSourceType::LOOT_SOURCE_ACTIVITY); uint32_t coins = (int)(minCoins + GeneralUtils::GenerateRandomNumber(0, 1) * (maxCoins - minCoins)); auto* character = player->GetCharacter(); - character->SetCoins(character->GetCoins() + coins, LOOT_SOURCE_ACTIVITY); + character->SetCoins(character->GetCoins() + coins, eLootSourceType::LOOT_SOURCE_ACTIVITY); } void LootGenerator::DropLoot(Entity* player, Entity* killedObject, uint32_t matrixIndex, uint32_t minCoins, uint32_t maxCoins) { diff --git a/dGame/dUtilities/Loot.h b/dGame/dUtilities/Loot.h index 23c6463d..b16c834a 100644 --- a/dGame/dUtilities/Loot.h +++ b/dGame/dUtilities/Loot.h @@ -47,8 +47,8 @@ class LootGenerator : public Singleton { std::unordered_map RollLootMatrix(Entity* player, uint32_t matrixIndex); std::unordered_map RollLootMatrix(uint32_t matrixIndex); - void GiveLoot(Entity* player, uint32_t matrixIndex); - void GiveLoot(Entity* player, std::unordered_map& result); + void GiveLoot(Entity* player, uint32_t matrixIndex, eLootSourceType lootSourceType = eLootSourceType::LOOT_SOURCE_NONE); + void GiveLoot(Entity* player, std::unordered_map& result, eLootSourceType lootSourceType = eLootSourceType::LOOT_SOURCE_NONE); 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& result, uint32_t minCoins, uint32_t maxCoins); diff --git a/dGame/dUtilities/Mail.cpp b/dGame/dUtilities/Mail.cpp index 89cc0fff..79e99c7d 100644 --- a/dGame/dUtilities/Mail.cpp +++ b/dGame/dUtilities/Mail.cpp @@ -363,7 +363,7 @@ void Mail::HandleAttachmentCollect(RakNet::BitStream* packet, const SystemAddres auto inv = static_cast(player->GetComponent(COMPONENT_TYPE_INVENTORY)); if (!inv) return; - inv->AddItem(attachmentLOT, attachmentCount, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_MAIL); + inv->AddItem(attachmentLOT, attachmentCount, eLootSourceType::LOOT_SOURCE_MAIL); Mail::SendAttachmentRemoveConfirm(sysAddr, mailID); diff --git a/dGame/dUtilities/SlashCommandHandler.cpp b/dGame/dUtilities/SlashCommandHandler.cpp index d94c8d47..ca858920 100644 --- a/dGame/dUtilities/SlashCommandHandler.cpp +++ b/dGame/dUtilities/SlashCommandHandler.cpp @@ -794,7 +794,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit InventoryComponent * inventory = static_cast(entity->GetComponent(COMPONENT_TYPE_INVENTORY)); - inventory->AddItem(itemLOT, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_MODERATION); + inventory->AddItem(itemLOT, 1, eLootSourceType::LOOT_SOURCE_MODERATION); } else if(args.size() == 2) { uint32_t itemLOT; @@ -814,7 +814,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit InventoryComponent* inventory = static_cast(entity->GetComponent(COMPONENT_TYPE_INVENTORY)); - inventory->AddItem(itemLOT, count, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_MODERATION); + inventory->AddItem(itemLOT, count, eLootSourceType::LOOT_SOURCE_MODERATION); } else { ChatPackets::SendSystemMessage(sysAddr, u"Correct usage: /gmadditem "); @@ -1626,7 +1626,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit std::vector data {}; data.push_back(new LDFData(u"reforgedLOT", reforgedItem)); - inventoryComponent->AddItem(baseItem, 1, eInventoryType::INVALID, data, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_MODERATION); + inventoryComponent->AddItem(baseItem, 1, eLootSourceType::LOOT_SOURCE_MODERATION); } if (chatCommand == "crash" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_OPERATOR) diff --git a/dScripts/AmDropshipComputer.cpp b/dScripts/AmDropshipComputer.cpp index 7f25574a..d90bfa97 100644 --- a/dScripts/AmDropshipComputer.cpp +++ b/dScripts/AmDropshipComputer.cpp @@ -32,7 +32,7 @@ void AmDropshipComputer::OnUse(Entity* self, Entity* user) return; } - inventoryComponent->AddItem(12323, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); + inventoryComponent->AddItem(12323, 1, eLootSourceType::LOOT_SOURCE_ACTIVITY); } void AmDropshipComputer::OnDie(Entity* self, Entity* killer) diff --git a/dScripts/NPCAddRemoveItem.cpp b/dScripts/NPCAddRemoveItem.cpp index 8cc2b6fd..484cc827 100644 --- a/dScripts/NPCAddRemoveItem.cpp +++ b/dScripts/NPCAddRemoveItem.cpp @@ -11,7 +11,7 @@ void NPCAddRemoveItem::OnMissionDialogueOK(Entity *self, Entity *target, int mis for (const auto& itemSetting : missionSetting.second) { for (const auto& lot : itemSetting.items) { if (itemSetting.add && (missionState == MissionState::MISSION_STATE_AVAILABLE || missionState == MissionState::MISSION_STATE_COMPLETE_AVAILABLE)) { - inventory->AddItem(lot, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); + inventory->AddItem(lot, 1, eLootSourceType::LOOT_SOURCE_ACTIVITY); } else if (itemSetting.remove && (missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE || missionState == MissionState::MISSION_STATE_COMPLETE_READY_TO_COMPLETE)) { inventory->RemoveItem(lot, 1); } diff --git a/dScripts/NjColeNPC.cpp b/dScripts/NjColeNPC.cpp index e342e429..d2388d7b 100644 --- a/dScripts/NjColeNPC.cpp +++ b/dScripts/NjColeNPC.cpp @@ -54,6 +54,6 @@ void NjColeNPC::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, return; } - inventoryComponent->AddItem(16644, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_VENDOR); + inventoryComponent->AddItem(16644, 1, eLootSourceType::LOOT_SOURCE_VENDOR); } } diff --git a/dScripts/NjScrollChestServer.cpp b/dScripts/NjScrollChestServer.cpp index 4677f827..8a2f7750 100644 --- a/dScripts/NjScrollChestServer.cpp +++ b/dScripts/NjScrollChestServer.cpp @@ -12,6 +12,6 @@ void NjScrollChestServer::OnUse(Entity *self, Entity *user) { playerInventory->RemoveItem(keyLOT, 1); // Reward the player with the item set - playerInventory->AddItem(rewardItemLOT, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); + playerInventory->AddItem(rewardItemLOT, 1, eLootSourceType::LOOT_SOURCE_ACTIVITY); } } diff --git a/dScripts/NpcCowboyServer.cpp b/dScripts/NpcCowboyServer.cpp index b92d921f..b638d24f 100644 --- a/dScripts/NpcCowboyServer.cpp +++ b/dScripts/NpcCowboyServer.cpp @@ -23,7 +23,7 @@ void NpcCowboyServer::OnMissionDialogueOK(Entity* self, Entity* target, int miss { if (inventoryComponent->GetLotCount(14378) == 0) { - inventoryComponent->AddItem(14378, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); + inventoryComponent->AddItem(14378, 1, eLootSourceType::LOOT_SOURCE_ACTIVITY); } } else if (missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE || missionState == MissionState::MISSION_STATE_COMPLETE_READY_TO_COMPLETE) diff --git a/dScripts/NpcPirateServer.cpp b/dScripts/NpcPirateServer.cpp index acf7e67f..b56380f3 100644 --- a/dScripts/NpcPirateServer.cpp +++ b/dScripts/NpcPirateServer.cpp @@ -9,7 +9,7 @@ void NpcPirateServer::OnMissionDialogueOK(Entity *self, Entity *target, int miss // Add or remove the lucky shovel based on whether the mission was completed or started if ((missionState == MissionState::MISSION_STATE_AVAILABLE || missionState == MissionState::MISSION_STATE_COMPLETE_AVAILABLE) && luckyShovel == nullptr) { - inventory->AddItem(14591, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); + inventory->AddItem(14591, 1, eLootSourceType::LOOT_SOURCE_ACTIVITY); } else if (missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE || missionState == MissionState::MISSION_STATE_COMPLETE_READY_TO_COMPLETE) { inventory->RemoveItem(14591, 1); } diff --git a/dScripts/NpcWispServer.cpp b/dScripts/NpcWispServer.cpp index 3000b4c9..a0f8392c 100644 --- a/dScripts/NpcWispServer.cpp +++ b/dScripts/NpcWispServer.cpp @@ -20,7 +20,7 @@ void NpcWispServer::OnMissionDialogueOK(Entity* self, Entity* target, int missio // For the daily we add the maelstrom vacuum if the player doesn't have it yet if (missionID == 1883 && (missionState == MissionState::MISSION_STATE_AVAILABLE || missionState == MissionState::MISSION_STATE_COMPLETE_AVAILABLE) && maelstromVacuum == nullptr) { - inventory->AddItem(maelstromVacuumLot, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); + inventory->AddItem(maelstromVacuumLot, 1, eLootSourceType::LOOT_SOURCE_ACTIVITY); } else if (missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE || missionState == MissionState::MISSION_STATE_COMPLETE_READY_TO_COMPLETE) { inventory->RemoveItem(maelstromVacuumLot, 1); } diff --git a/dScripts/NsConcertInstrument.cpp b/dScripts/NsConcertInstrument.cpp index d1de993c..92341ee9 100644 --- a/dScripts/NsConcertInstrument.cpp +++ b/dScripts/NsConcertInstrument.cpp @@ -195,7 +195,7 @@ void NsConcertInstrument::EquipInstruments(Entity *self, Entity *player) { // Equip the left hand instrument const auto leftInstrumentLot = instrumentLotLeft.find(GetInstrumentLot(self))->second; if (leftInstrumentLot != LOT_NULL) { - inventory->AddItem(leftInstrumentLot, 1, TEMP_ITEMS, {}, LWOOBJID_EMPTY, false, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); + inventory->AddItem(leftInstrumentLot, 1, eLootSourceType::LOOT_SOURCE_ACTIVITY); auto* leftInstrument = inventory->FindItemByLot(leftInstrumentLot, TEMP_ITEMS); leftInstrument->Equip(); } @@ -203,7 +203,7 @@ void NsConcertInstrument::EquipInstruments(Entity *self, Entity *player) { // Equip the right hand instrument const auto rightInstrumentLot = instrumentLotRight.find(GetInstrumentLot(self))->second; if (rightInstrumentLot != LOT_NULL) { - inventory->AddItem(rightInstrumentLot, 1, TEMP_ITEMS, {}, LWOOBJID_EMPTY, false, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); + inventory->AddItem(rightInstrumentLot, 1, eLootSourceType::LOOT_SOURCE_ACTIVITY); auto* rightInstrument = inventory->FindItemByLot(rightInstrumentLot, TEMP_ITEMS); rightInstrument->Equip(); } diff --git a/dScripts/NsTokenConsoleServer.cpp b/dScripts/NsTokenConsoleServer.cpp index 0416a030..0e9ac09e 100644 --- a/dScripts/NsTokenConsoleServer.cpp +++ b/dScripts/NsTokenConsoleServer.cpp @@ -47,24 +47,29 @@ void NsTokenConsoleServer::OnUse(Entity* self, Entity* user) { GameMessages::SendPlayNDAudioEmitter(self, UNASSIGNED_SYSTEM_ADDRESS, useSound); } + + // Player must be in faction to interact with this entity. + LOT tokenLOT = 0; if (character->GetPlayerFlag(46)) { - inventoryComponent->AddItem(8321, 5, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_NONE); + tokenLOT = 8321; } else if (character->GetPlayerFlag(47)) { - inventoryComponent->AddItem(8318, 5, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_NONE); + tokenLOT = 8318; } else if (character->GetPlayerFlag(48)) { - inventoryComponent->AddItem(8320, 5, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_NONE); + tokenLOT = 8320; } else if (character->GetPlayerFlag(49)) { - inventoryComponent->AddItem(8319, 5, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_NONE); + tokenLOT = 8319; } + inventoryComponent->AddItem(tokenLOT, 5, eLootSourceType::LOOT_SOURCE_NONE); + missionComponent->ForceProgressTaskType(863, 1, 1, false); GameMessages::SendTerminateInteraction(user->GetObjectID(), FROM_INTERACTION, self->GetObjectID()); diff --git a/dScripts/NtDukeServer.cpp b/dScripts/NtDukeServer.cpp index db278aa1..d82be277 100644 --- a/dScripts/NtDukeServer.cpp +++ b/dScripts/NtDukeServer.cpp @@ -29,7 +29,7 @@ void NtDukeServer::OnMissionDialogueOK(Entity *self, Entity *target, int mission auto lotCount = inventoryComponent->GetLotCount(m_SwordLot); if ((state == MissionState::MISSION_STATE_AVAILABLE || state == MissionState::MISSION_STATE_ACTIVE) && lotCount < 1) { - inventoryComponent->AddItem(m_SwordLot, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); + inventoryComponent->AddItem(m_SwordLot, 1, eLootSourceType::LOOT_SOURCE_ACTIVITY); } else if (state == MissionState::MISSION_STATE_READY_TO_COMPLETE) { inventoryComponent->RemoveItem(m_SwordLot, lotCount); } diff --git a/dScripts/SGCannon.cpp b/dScripts/SGCannon.cpp index efb7d7fc..a5c2c843 100644 --- a/dScripts/SGCannon.cpp +++ b/dScripts/SGCannon.cpp @@ -574,7 +574,7 @@ void SGCannon::StopGame(Entity *self, bool cancel) { auto* inventory = player->GetComponent(); if (inventory != nullptr) { for (const auto rewardLot : self->GetVar>(RewardsVariable)) { - inventory->AddItem(rewardLot, 1, eInventoryType::MODELS, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); + inventory->AddItem(rewardLot, 1, eLootSourceType::LOOT_SOURCE_ACTIVITY, eInventoryType::MODELS); } } diff --git a/dScripts/TokenConsoleServer.cpp b/dScripts/TokenConsoleServer.cpp index 0ca18e76..58565869 100644 --- a/dScripts/TokenConsoleServer.cpp +++ b/dScripts/TokenConsoleServer.cpp @@ -31,7 +31,7 @@ void TokenConsoleServer::OnUse(Entity* self, Entity* user) { tokenLOT = 8320; else if (character->GetPlayerFlag(ePlayerFlags::SENTINEL_FACTION)) //sentinel tokenLOT = 8319; - inv->AddItem(tokenLOT, tokensToGive, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_NONE); + inv->AddItem(tokenLOT, tokensToGive, eLootSourceType::LOOT_SOURCE_NONE); } GameMessages::SendTerminateInteraction(user->GetObjectID(), eTerminateType::FROM_INTERACTION, self->GetObjectID()); diff --git a/dScripts/VeBricksampleServer.cpp b/dScripts/VeBricksampleServer.cpp index f9d5f3d2..f42cd9a4 100644 --- a/dScripts/VeBricksampleServer.cpp +++ b/dScripts/VeBricksampleServer.cpp @@ -10,7 +10,7 @@ void VeBricksampleServer::OnUse(Entity *self, Entity *user) { auto* inventoryComponent = user->GetComponent(); if (loot && inventoryComponent != nullptr && inventoryComponent->GetLotCount(loot) == 0) { - inventoryComponent->AddItem(loot, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); + inventoryComponent->AddItem(loot, 1, eLootSourceType::LOOT_SOURCE_ACTIVITY); for (auto* brickEntity : EntityManager::Instance()->GetEntitiesInGroup("Bricks")) { GameMessages::SendNotifyClientObject(brickEntity->GetObjectID(), u"Pickedup"); diff --git a/dScripts/VeMissionConsole.cpp b/dScripts/VeMissionConsole.cpp index 9e560244..f815ebdc 100644 --- a/dScripts/VeMissionConsole.cpp +++ b/dScripts/VeMissionConsole.cpp @@ -8,7 +8,7 @@ void VeMissionConsole::OnUse(Entity *self, Entity *user) { auto* inventoryComponent = user->GetComponent(); if (inventoryComponent != nullptr) { - inventoryComponent->AddItem(12547, 1, eInventoryType::INVALID, {}, 0LL, true, false, 0LL, eInventoryType::INVALID, 0, false, -1, eLootSourceType::LOOT_SOURCE_ACTIVITY); // Add the panel required for pickup + inventoryComponent->AddItem(12547, 1, eLootSourceType::LOOT_SOURCE_ACTIVITY); // Add the panel required for pickup } // The flag to set is 101 From c6480192f8ef09ada262b0f9eac5038064aa6fe8 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 23 Apr 2022 20:35:39 -0700 Subject: [PATCH 213/251] Revert "isPlayer changes" This reverts commit 2e61839d93728d4193b5542558369f8cf05be61d. --- dGame/Entity.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 799e7803..75d8d8b6 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -1739,7 +1739,7 @@ void Entity::CancelAllTimers() { } bool Entity::IsPlayer() const { - return m_TemplateID == 1 && GetCharacter() != nullptr; + return m_TemplateID == 1 && GetSystemAddress() != UNASSIGNED_SYSTEM_ADDRESS; } void Entity::TriggerEvent(std::string eventID, Entity* optionalTarget) { From 18fc01cd499fc4a97805511146259fbbaeb0cb3f Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 23 Apr 2022 20:44:08 -0700 Subject: [PATCH 214/251] missed change for forge --- dGame/dUtilities/SlashCommandHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dUtilities/SlashCommandHandler.cpp b/dGame/dUtilities/SlashCommandHandler.cpp index ca858920..324da751 100644 --- a/dGame/dUtilities/SlashCommandHandler.cpp +++ b/dGame/dUtilities/SlashCommandHandler.cpp @@ -1626,7 +1626,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit std::vector data {}; data.push_back(new LDFData(u"reforgedLOT", reforgedItem)); - inventoryComponent->AddItem(baseItem, 1, eLootSourceType::LOOT_SOURCE_MODERATION); + inventoryComponent->AddItem(baseItem, 1, eLootSourceType::LOOT_SOURCE_MODERATION, eInventoryType::INVALID, data); } if (chatCommand == "crash" && entity->GetGMLevel() >= GAME_MASTER_LEVEL_OPERATOR) From dc770299d1c44ac5ceae051bd6c1848a0633c8de Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sat, 23 Apr 2022 22:22:21 -0700 Subject: [PATCH 215/251] removed debug logs --- dGame/dComponents/InventoryComponent.cpp | 1 - dGame/dGameMessages/GameMessages.cpp | 1 - dGame/dInventory/Item.cpp | 1 - 3 files changed, 3 deletions(-) diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index e03f4e92..d2292168 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -284,7 +284,6 @@ void InventoryComponent::AddItem( continue; } - Game::logger->Log("InventoryComponent", "new item with source %i\n", lootSourceType); auto* item = new Item(lot, inventory, slot, size, {}, parent, showFlyingLoot, isModMoveAndEquip, subKey, false, lootSourceType); isModMoveAndEquip = false; diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index e0f38dbe..a1fbdb47 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -423,7 +423,6 @@ void GameMessages::SendAddItemToInventoryClientSync(Entity* entity, const System bitStream.Write(lootSourceType != eLootSourceType::LOOT_SOURCE_NONE); // Loot source if (lootSourceType != eLootSourceType::LOOT_SOURCE_NONE) bitStream.Write(lootSourceType); - Game::logger->Log("GameMessages", "lootSource %i\n", lootSourceType); LWONameValue extraInfo; auto config = item->GetConfig(); diff --git a/dGame/dInventory/Item.cpp b/dGame/dInventory/Item.cpp index 213430d2..a8e8d408 100644 --- a/dGame/dInventory/Item.cpp +++ b/dGame/dInventory/Item.cpp @@ -81,7 +81,6 @@ Item::Item( inventory->AddManagedItem(this); auto* entity = inventory->GetComponent()->GetParent(); - Game::logger->Log("test", "source %i\n", lootSourceType); GameMessages::SendAddItemToInventoryClientSync(entity, entity->GetSystemAddress(), this, id, showFlyingLoot, static_cast(this->count), subKey, lootSourceType); if (isModMoveAndEquip) From e56732184fcad14f0b6fb0b9217465479d5c810b Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 24 Apr 2022 17:25:45 -0700 Subject: [PATCH 216/251] commit --- dGame/dComponents/DestroyableComponent.cpp | 26 +++++++++++----------- dGame/dMission/Mission.cpp | 4 ++-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/dGame/dComponents/DestroyableComponent.cpp b/dGame/dComponents/DestroyableComponent.cpp index 31b3af19..c0cad3ba 100644 --- a/dGame/dComponents/DestroyableComponent.cpp +++ b/dGame/dComponents/DestroyableComponent.cpp @@ -215,6 +215,8 @@ void DestroyableComponent::SetHealth(int32_t value) { void DestroyableComponent::SetMaxHealth(float value, bool playAnim) { m_DirtyHealth = true; + // Used for playAnim if opted in for. + int32_t difference = static_cast(std::abs(m_fMaxHealth - value)); m_fMaxHealth = value; if (m_iHealth > m_fMaxHealth) { @@ -225,22 +227,21 @@ void DestroyableComponent::SetMaxHealth(float value, bool playAnim) { // Now update the player bar if (!m_Parent->GetParentUser()) return; AMFStringValue* amount = new AMFStringValue(); - amount->SetStringValue(std::to_string(value)); + amount->SetStringValue(std::to_string(difference)); AMFStringValue* type = new AMFStringValue(); type->SetStringValue("health"); AMFArrayValue args; args.InsertValue("amount", amount); args.InsertValue("type", type); - + Game::logger->Log("DestComp", "Setting max health diff %i\n", difference); GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent->GetParentUser()->GetSystemAddress(), "MaxPlayerBarUpdate", &args); delete amount; delete type; } - else { - EntityManager::Instance()->SerializeEntity(m_Parent); - } + + EntityManager::Instance()->SerializeEntity(m_Parent); } void DestroyableComponent::SetArmor(int32_t value) { @@ -287,9 +288,8 @@ void DestroyableComponent::SetMaxArmor(float value, bool playAnim) { delete amount; delete type; } - else { - EntityManager::Instance()->SerializeEntity(m_Parent); - } + + EntityManager::Instance()->SerializeEntity(m_Parent); } void DestroyableComponent::SetImagination(int32_t value) { @@ -310,6 +310,8 @@ void DestroyableComponent::SetImagination(int32_t value) { void DestroyableComponent::SetMaxImagination(float value, bool playAnim) { m_DirtyHealth = true; + // Used for playAnim if opted in for. + int32_t difference = static_cast(std::abs(m_fMaxImagination - value)); m_fMaxImagination = value; if (m_iImagination > m_fMaxImagination) { @@ -320,22 +322,20 @@ void DestroyableComponent::SetMaxImagination(float value, bool playAnim) { // Now update the player bar if (!m_Parent->GetParentUser()) return; AMFStringValue* amount = new AMFStringValue(); - amount->SetStringValue(std::to_string(value)); + amount->SetStringValue(std::to_string(difference)); AMFStringValue* type = new AMFStringValue(); type->SetStringValue("imagination"); AMFArrayValue args; args.InsertValue("amount", amount); args.InsertValue("type", type); - + Game::logger->Log("DestComp", "Setting max imagiantion diff %i\n", difference); GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent->GetParentUser()->GetSystemAddress(), "MaxPlayerBarUpdate", &args); delete amount; delete type; } - else { - EntityManager::Instance()->SerializeEntity(m_Parent); - } + EntityManager::Instance()->SerializeEntity(m_Parent); } void DestroyableComponent::SetDamageToAbsorb(int32_t value) diff --git a/dGame/dMission/Mission.cpp b/dGame/dMission/Mission.cpp index 14fc5a24..a7d67c50 100644 --- a/dGame/dMission/Mission.cpp +++ b/dGame/dMission/Mission.cpp @@ -528,11 +528,11 @@ void Mission::YieldRewards() { } if (info->reward_maxhealth > 0) { - destroyableComponent->SetMaxHealth(destroyableComponent->GetMaxHealth() + static_cast(info->reward_maxhealth)); + destroyableComponent->SetMaxHealth(destroyableComponent->GetMaxHealth() + static_cast(info->reward_maxhealth), true); } if (info->reward_maximagination > 0) { - destroyableComponent->SetMaxImagination(destroyableComponent->GetMaxImagination() + static_cast(info->reward_maximagination)); + destroyableComponent->SetMaxImagination(destroyableComponent->GetMaxImagination() + static_cast(info->reward_maximagination), true); } EntityManager::Instance()->SerializeEntity(entity); From 2e29dce77c262fb3dae26ff421db6c357785f27c Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 24 Apr 2022 17:27:25 -0700 Subject: [PATCH 217/251] removed logs --- dGame/dComponents/DestroyableComponent.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/dGame/dComponents/DestroyableComponent.cpp b/dGame/dComponents/DestroyableComponent.cpp index c0cad3ba..0e348182 100644 --- a/dGame/dComponents/DestroyableComponent.cpp +++ b/dGame/dComponents/DestroyableComponent.cpp @@ -234,7 +234,6 @@ void DestroyableComponent::SetMaxHealth(float value, bool playAnim) { AMFArrayValue args; args.InsertValue("amount", amount); args.InsertValue("type", type); - Game::logger->Log("DestComp", "Setting max health diff %i\n", difference); GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent->GetParentUser()->GetSystemAddress(), "MaxPlayerBarUpdate", &args); delete amount; @@ -329,7 +328,6 @@ void DestroyableComponent::SetMaxImagination(float value, bool playAnim) { AMFArrayValue args; args.InsertValue("amount", amount); args.InsertValue("type", type); - Game::logger->Log("DestComp", "Setting max imagiantion diff %i\n", difference); GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent->GetParentUser()->GetSystemAddress(), "MaxPlayerBarUpdate", &args); delete amount; From 4fd1467cbf7d711c777c83ec8da41044e748a60f Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Sun, 24 Apr 2022 18:40:20 -0700 Subject: [PATCH 218/251] changed loot sources to none Changed loot sources for some scripts to none so they properly give loot to the player. --- dScripts/AmDropshipComputer.cpp | 2 +- dScripts/NPCAddRemoveItem.cpp | 2 +- dScripts/NjColeNPC.cpp | 2 +- dScripts/NjScrollChestServer.cpp | 2 +- dScripts/NpcCowboyServer.cpp | 2 +- dScripts/NpcPirateServer.cpp | 2 +- dScripts/NpcWispServer.cpp | 2 +- dScripts/NtDukeServer.cpp | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dScripts/AmDropshipComputer.cpp b/dScripts/AmDropshipComputer.cpp index d90bfa97..836b09b0 100644 --- a/dScripts/AmDropshipComputer.cpp +++ b/dScripts/AmDropshipComputer.cpp @@ -32,7 +32,7 @@ void AmDropshipComputer::OnUse(Entity* self, Entity* user) return; } - inventoryComponent->AddItem(12323, 1, eLootSourceType::LOOT_SOURCE_ACTIVITY); + inventoryComponent->AddItem(12323, 1, eLootSourceType::LOOT_SOURCE_NONE); } void AmDropshipComputer::OnDie(Entity* self, Entity* killer) diff --git a/dScripts/NPCAddRemoveItem.cpp b/dScripts/NPCAddRemoveItem.cpp index 484cc827..58c46ac0 100644 --- a/dScripts/NPCAddRemoveItem.cpp +++ b/dScripts/NPCAddRemoveItem.cpp @@ -11,7 +11,7 @@ void NPCAddRemoveItem::OnMissionDialogueOK(Entity *self, Entity *target, int mis for (const auto& itemSetting : missionSetting.second) { for (const auto& lot : itemSetting.items) { if (itemSetting.add && (missionState == MissionState::MISSION_STATE_AVAILABLE || missionState == MissionState::MISSION_STATE_COMPLETE_AVAILABLE)) { - inventory->AddItem(lot, 1, eLootSourceType::LOOT_SOURCE_ACTIVITY); + inventory->AddItem(lot, 1, eLootSourceType::LOOT_SOURCE_NONE); } else if (itemSetting.remove && (missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE || missionState == MissionState::MISSION_STATE_COMPLETE_READY_TO_COMPLETE)) { inventory->RemoveItem(lot, 1); } diff --git a/dScripts/NjColeNPC.cpp b/dScripts/NjColeNPC.cpp index d2388d7b..1b889445 100644 --- a/dScripts/NjColeNPC.cpp +++ b/dScripts/NjColeNPC.cpp @@ -54,6 +54,6 @@ void NjColeNPC::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, return; } - inventoryComponent->AddItem(16644, 1, eLootSourceType::LOOT_SOURCE_VENDOR); + inventoryComponent->AddItem(16644, 1, eLootSourceType::LOOT_SOURCE_NONE); } } diff --git a/dScripts/NjScrollChestServer.cpp b/dScripts/NjScrollChestServer.cpp index 8a2f7750..b72f93cf 100644 --- a/dScripts/NjScrollChestServer.cpp +++ b/dScripts/NjScrollChestServer.cpp @@ -12,6 +12,6 @@ void NjScrollChestServer::OnUse(Entity *self, Entity *user) { playerInventory->RemoveItem(keyLOT, 1); // Reward the player with the item set - playerInventory->AddItem(rewardItemLOT, 1, eLootSourceType::LOOT_SOURCE_ACTIVITY); + playerInventory->AddItem(rewardItemLOT, 1, eLootSourceType::LOOT_SOURCE_NONE); } } diff --git a/dScripts/NpcCowboyServer.cpp b/dScripts/NpcCowboyServer.cpp index b638d24f..9223dcd4 100644 --- a/dScripts/NpcCowboyServer.cpp +++ b/dScripts/NpcCowboyServer.cpp @@ -23,7 +23,7 @@ void NpcCowboyServer::OnMissionDialogueOK(Entity* self, Entity* target, int miss { if (inventoryComponent->GetLotCount(14378) == 0) { - inventoryComponent->AddItem(14378, 1, eLootSourceType::LOOT_SOURCE_ACTIVITY); + inventoryComponent->AddItem(14378, 1, eLootSourceType::LOOT_SOURCE_NONE); } } else if (missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE || missionState == MissionState::MISSION_STATE_COMPLETE_READY_TO_COMPLETE) diff --git a/dScripts/NpcPirateServer.cpp b/dScripts/NpcPirateServer.cpp index b56380f3..04c62b47 100644 --- a/dScripts/NpcPirateServer.cpp +++ b/dScripts/NpcPirateServer.cpp @@ -9,7 +9,7 @@ void NpcPirateServer::OnMissionDialogueOK(Entity *self, Entity *target, int miss // Add or remove the lucky shovel based on whether the mission was completed or started if ((missionState == MissionState::MISSION_STATE_AVAILABLE || missionState == MissionState::MISSION_STATE_COMPLETE_AVAILABLE) && luckyShovel == nullptr) { - inventory->AddItem(14591, 1, eLootSourceType::LOOT_SOURCE_ACTIVITY); + inventory->AddItem(14591, 1, eLootSourceType::LOOT_SOURCE_NONE); } else if (missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE || missionState == MissionState::MISSION_STATE_COMPLETE_READY_TO_COMPLETE) { inventory->RemoveItem(14591, 1); } diff --git a/dScripts/NpcWispServer.cpp b/dScripts/NpcWispServer.cpp index a0f8392c..03c8f071 100644 --- a/dScripts/NpcWispServer.cpp +++ b/dScripts/NpcWispServer.cpp @@ -20,7 +20,7 @@ void NpcWispServer::OnMissionDialogueOK(Entity* self, Entity* target, int missio // For the daily we add the maelstrom vacuum if the player doesn't have it yet if (missionID == 1883 && (missionState == MissionState::MISSION_STATE_AVAILABLE || missionState == MissionState::MISSION_STATE_COMPLETE_AVAILABLE) && maelstromVacuum == nullptr) { - inventory->AddItem(maelstromVacuumLot, 1, eLootSourceType::LOOT_SOURCE_ACTIVITY); + inventory->AddItem(maelstromVacuumLot, 1, eLootSourceType::LOOT_SOURCE_NONE); } else if (missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE || missionState == MissionState::MISSION_STATE_COMPLETE_READY_TO_COMPLETE) { inventory->RemoveItem(maelstromVacuumLot, 1); } diff --git a/dScripts/NtDukeServer.cpp b/dScripts/NtDukeServer.cpp index d82be277..fe196811 100644 --- a/dScripts/NtDukeServer.cpp +++ b/dScripts/NtDukeServer.cpp @@ -29,7 +29,7 @@ void NtDukeServer::OnMissionDialogueOK(Entity *self, Entity *target, int mission auto lotCount = inventoryComponent->GetLotCount(m_SwordLot); if ((state == MissionState::MISSION_STATE_AVAILABLE || state == MissionState::MISSION_STATE_ACTIVE) && lotCount < 1) { - inventoryComponent->AddItem(m_SwordLot, 1, eLootSourceType::LOOT_SOURCE_ACTIVITY); + inventoryComponent->AddItem(m_SwordLot, 1, eLootSourceType::LOOT_SOURCE_NONE); } else if (state == MissionState::MISSION_STATE_READY_TO_COMPLETE) { inventoryComponent->RemoveItem(m_SwordLot, lotCount); } From 4117ceb6c1721ae1dd277bbf42f2075bc712a1e0 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 25 Apr 2022 03:25:07 -0700 Subject: [PATCH 219/251] Skill Tasks changes Addressed an issue where the Spinjitzu Initiate achievement would not progress. This also allows mission tasks that specify that the player must get a kill on an enemy with a skill to progress. Tested mission 1935 and 1139 and both missions progressed and completed as intended. --- dGame/dBehaviors/BasicAttackBehavior.cpp | 6 +++--- dGame/dBehaviors/BehaviorContext.h | 2 ++ dGame/dComponents/DestroyableComponent.cpp | 24 ++++++---------------- dGame/dComponents/DestroyableComponent.h | 6 ++++-- dGame/dComponents/SkillComponent.cpp | 4 +++- dGame/dComponents/SkillComponent.h | 2 +- dGame/dGameMessages/GameMessageHandler.cpp | 2 +- dGame/dMission/MissionTask.cpp | 10 +++++---- 8 files changed, 26 insertions(+), 30 deletions(-) diff --git a/dGame/dBehaviors/BasicAttackBehavior.cpp b/dGame/dBehaviors/BasicAttackBehavior.cpp index 399efec1..a9a58245 100644 --- a/dGame/dBehaviors/BasicAttackBehavior.cpp +++ b/dGame/dBehaviors/BasicAttackBehavior.cpp @@ -14,7 +14,7 @@ void BasicAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bi auto* destroyableComponent = entity->GetComponent(); if (destroyableComponent != nullptr) { PlayFx(u"onhit", entity->GetObjectID()); - destroyableComponent->Damage(this->m_maxDamage, context->originator); + destroyableComponent->Damage(this->m_maxDamage, context->originator, context->skillID); } this->m_onSuccess->Handle(context, bitStream, branch); @@ -56,7 +56,7 @@ void BasicAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bi auto* destroyableComponent = entity->GetComponent(); if (destroyableComponent != nullptr) { PlayFx(u"onhit", entity->GetObjectID()); - destroyableComponent->Damage(damageDealt, context->originator); + destroyableComponent->Damage(damageDealt, context->originator, context->skillID); } } } @@ -113,7 +113,7 @@ void BasicAttackBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* auto* destroyableComponent = entity->GetComponent(); if (damage != 0 && destroyableComponent != nullptr) { PlayFx(u"onhit", entity->GetObjectID(), 1); - destroyableComponent->Damage(damage, context->originator, false); + destroyableComponent->Damage(damage, context->originator, context->skillID, false); context->ScheduleUpdate(branch.target); } } diff --git a/dGame/dBehaviors/BehaviorContext.h b/dGame/dBehaviors/BehaviorContext.h index 9f1d1621..f27889f1 100644 --- a/dGame/dBehaviors/BehaviorContext.h +++ b/dGame/dBehaviors/BehaviorContext.h @@ -58,6 +58,8 @@ struct BehaviorContext float skillTime = 0; + uint32_t skillID = 0; + uint32_t skillUId = 0; bool failed = false; diff --git a/dGame/dComponents/DestroyableComponent.cpp b/dGame/dComponents/DestroyableComponent.cpp index 2c906253..49b15b3f 100644 --- a/dGame/dComponents/DestroyableComponent.cpp +++ b/dGame/dComponents/DestroyableComponent.cpp @@ -593,7 +593,7 @@ void DestroyableComponent::Repair(const uint32_t armor) } -void DestroyableComponent::Damage(uint32_t damage, const LWOOBJID source, bool echo) +void DestroyableComponent::Damage(uint32_t damage, const LWOOBJID source, uint32_t skillID, bool echo) { if (GetHealth() <= 0) { @@ -677,11 +677,10 @@ void DestroyableComponent::Damage(uint32_t damage, const LWOOBJID source, bool e return; } - - Smash(source); + Smash(source, eKillType::VIOLENT, u"", skillID); } -void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType, const std::u16string& deathType) +void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType, const std::u16string& deathType, uint32_t skillID) { if (m_iHealth > 0) { @@ -727,31 +726,20 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType if (memberMissions == nullptr) continue; memberMissions->Progress(MissionTaskType::MISSION_TASK_TYPE_SMASH, m_Parent->GetLOT()); + memberMissions->Progress(MissionTaskType::MISSION_TASK_TYPE_SKILL, m_Parent->GetLOT(), skillID); } } else { missions->Progress(MissionTaskType::MISSION_TASK_TYPE_SMASH, m_Parent->GetLOT()); + missions->Progress(MissionTaskType::MISSION_TASK_TYPE_SKILL, m_Parent->GetLOT(), skillID); } } } const auto isPlayer = m_Parent->IsPlayer(); - GameMessages::SendDie( - m_Parent, - source, - source, - true, - killType, - deathType, - 0, - 0, - 0, - isPlayer, - false, - 1 - ); + GameMessages::SendDie(m_Parent, source, source, true, killType, deathType, 0, 0, 0, isPlayer, false, 1); //NANI?! if (!isPlayer) diff --git a/dGame/dComponents/DestroyableComponent.h b/dGame/dComponents/DestroyableComponent.h index d702897c..a1f57be4 100644 --- a/dGame/dComponents/DestroyableComponent.h +++ b/dGame/dComponents/DestroyableComponent.h @@ -377,17 +377,19 @@ public: * Attempt to damage this entity, handles everything from health and armor to absorption, immunity and callbacks. * @param damage the damage to attempt to apply * @param source the attacker that caused this damage + * @param skillID the skill that damaged this entity * @param echo whether or not to serialize the damage */ - void Damage(uint32_t damage, LWOOBJID source, bool echo = true); + void Damage(uint32_t damage, LWOOBJID source, uint32_t skillID = 0, bool echo = true); /** * Smashes this entity, notifying all clients * @param source the source that smashed this entity + * @param skillID the skill that killed this entity * @param killType the way this entity was killed, determines if a client animation is played * @param deathType the animation to play when killed */ - void Smash(LWOOBJID source, eKillType killType = eKillType::VIOLENT, const std::u16string& deathType = u""); + void Smash(LWOOBJID source, eKillType killType = eKillType::VIOLENT, const std::u16string& deathType = u"", uint32_t skillID = 0); /** * Pushes a layer of immunity to this entity, making it immune for longer diff --git a/dGame/dComponents/SkillComponent.cpp b/dGame/dComponents/SkillComponent.cpp index 0846f014..483e360f 100644 --- a/dGame/dComponents/SkillComponent.cpp +++ b/dGame/dComponents/SkillComponent.cpp @@ -25,12 +25,14 @@ ProjectileSyncEntry::ProjectileSyncEntry() { } -bool SkillComponent::CastPlayerSkill(const uint32_t behaviorId, const uint32_t skillUid, RakNet::BitStream* bitStream, const LWOOBJID target) +bool SkillComponent::CastPlayerSkill(const uint32_t behaviorId, const uint32_t skillUid, RakNet::BitStream* bitStream, const LWOOBJID target, uint32_t skillID) { auto* context = new BehaviorContext(this->m_Parent->GetObjectID()); context->caster = m_Parent->GetObjectID(); + context->skillID = skillID; + this->m_managedBehaviors.insert_or_assign(skillUid, context); auto* behavior = Behavior::CreateBehavior(behaviorId); diff --git a/dGame/dComponents/SkillComponent.h b/dGame/dComponents/SkillComponent.h index c0738efc..ad2449c3 100644 --- a/dGame/dComponents/SkillComponent.h +++ b/dGame/dComponents/SkillComponent.h @@ -92,7 +92,7 @@ public: * @param bitStream the bitSteam given by the client to determine the behavior path * @param target the explicit target of the skill */ - bool CastPlayerSkill(uint32_t behaviorId, uint32_t skillUid, RakNet::BitStream* bitStream, LWOOBJID target); + bool CastPlayerSkill(uint32_t behaviorId, uint32_t skillUid, RakNet::BitStream* bitStream, LWOOBJID target, uint32_t skillID = 0); /** * Continues a player skill. Should only be called when the server receives a sync message from the client. diff --git a/dGame/dGameMessages/GameMessageHandler.cpp b/dGame/dGameMessages/GameMessageHandler.cpp index 45760cc9..cdaae38c 100644 --- a/dGame/dGameMessages/GameMessageHandler.cpp +++ b/dGame/dGameMessages/GameMessageHandler.cpp @@ -285,7 +285,7 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System auto* skillComponent = entity->GetComponent(); - success = skillComponent->CastPlayerSkill(behaviorId, startSkill.uiSkillHandle, bs, startSkill.optionalTargetID); + success = skillComponent->CastPlayerSkill(behaviorId, startSkill.uiSkillHandle, bs, startSkill.optionalTargetID, startSkill.skillID); if (success && entity->GetCharacter()) { DestroyableComponent* destComp = entity->GetComponent(); diff --git a/dGame/dMission/MissionTask.cpp b/dGame/dMission/MissionTask.cpp index 30cd58a1..2dd59887 100644 --- a/dGame/dMission/MissionTask.cpp +++ b/dGame/dMission/MissionTask.cpp @@ -326,10 +326,12 @@ void MissionTask::Progress(int32_t value, LWOOBJID associate, const std::string& case MissionTaskType::MISSION_TASK_TYPE_SKILL: { - if (!InParameters(value)) break; - - AddProgress(count); - + // This is a complicated check because for some missions we need to check for the associate being in the parameters instead of the value being in the parameters. + if (associate == LWOOBJID_EMPTY && GetAllTargets().size() == 1 && GetAllTargets()[0] == -1) { + if (InParameters(value)) AddProgress(count); + } else { + if (InParameters(associate) && InAllTargets(value)) AddProgress(count); + } break; } From 7d233a04c0eb0c168ee1a9250aa0c0e049b58ea2 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 25 Apr 2022 16:56:40 -0700 Subject: [PATCH 220/251] Corrected action for OverTimeBehavior --- dGame/dBehaviors/OverTimeBehavior.cpp | 51 ++++++--------------------- dGame/dBehaviors/OverTimeBehavior.h | 3 +- 2 files changed, 12 insertions(+), 42 deletions(-) diff --git a/dGame/dBehaviors/OverTimeBehavior.cpp b/dGame/dBehaviors/OverTimeBehavior.cpp index dbee4c39..9e8618df 100644 --- a/dGame/dBehaviors/OverTimeBehavior.cpp +++ b/dGame/dBehaviors/OverTimeBehavior.cpp @@ -7,62 +7,26 @@ #include "SkillComponent.h" #include "DestroyableComponent.h" -/** - * The OverTime behavior is very inconsistent in how it appears in the skill tree vs. how it should behave. - * - * Items like "Doc in a Box" use an overtime behavior which you would expect have health & armor regen, but is only fallowed by a stun. - * - * Due to this inconsistency, we have to implement a special case for some items. - */ - void OverTimeBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) { const auto originator = context->originator; auto* entity = EntityManager::Instance()->GetEntity(originator); - if (entity == nullptr) - { - return; - } + if (entity == nullptr) return; for (size_t i = 0; i < m_NumIntervals; i++) { entity->AddCallbackTimer((i + 1) * m_Delay, [originator, branch, this]() { auto* entity = EntityManager::Instance()->GetEntity(originator); - if (entity == nullptr) - { - return; - } + if (entity == nullptr) return; auto* skillComponent = entity->GetComponent(); - if (skillComponent == nullptr) - { - return; - } + if (skillComponent == nullptr) return; - skillComponent->CalculateBehavior(0, m_Action->m_behaviorId, branch.target, true, true); - - auto* destroyableComponent = entity->GetComponent(); - - if (destroyableComponent == nullptr) - { - return; - } - - /** - * Special cases for inconsistent behavior. - */ - - switch (m_behaviorId) - { - case 26253: // "Doc in a Box", heal up to 6 health and regen up to 18 armor. - destroyableComponent->Heal(1); - destroyableComponent->Repair(3); - break; - } + skillComponent->CalculateBehavior(m_Action, m_ActionBehaviorId, branch.target, true, true); }); } } @@ -74,7 +38,12 @@ void OverTimeBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bi void OverTimeBehavior::Load() { - m_Action = GetAction("action"); + m_Action = GetInt("action"); + // Since m_Action is a skillID and not a behavior, get is correlated behaviorID. + + CDSkillBehaviorTable* skillTable = CDClientManager::Instance()->GetTable("SkillBehavior"); + m_ActionBehaviorId = skillTable->GetSkillByID(m_Action).behaviorID; + m_Delay = GetFloat("delay"); m_NumIntervals = GetInt("num_intervals"); } diff --git a/dGame/dBehaviors/OverTimeBehavior.h b/dGame/dBehaviors/OverTimeBehavior.h index 6be675aa..5c177926 100644 --- a/dGame/dBehaviors/OverTimeBehavior.h +++ b/dGame/dBehaviors/OverTimeBehavior.h @@ -4,7 +4,8 @@ class OverTimeBehavior final : public Behavior { public: - Behavior* m_Action; + uint32_t m_Action; + uint32_t m_ActionBehaviorId; float m_Delay; int32_t m_NumIntervals; From 27edf5da1d8e668e605bea3a29c2beb4d7cbd9d3 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 25 Apr 2022 18:16:30 -0700 Subject: [PATCH 221/251] Typo in NsConcertInstruments --- dScripts/NsConcertInstrument.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dScripts/NsConcertInstrument.cpp b/dScripts/NsConcertInstrument.cpp index 92341ee9..bfd35083 100644 --- a/dScripts/NsConcertInstrument.cpp +++ b/dScripts/NsConcertInstrument.cpp @@ -195,7 +195,7 @@ void NsConcertInstrument::EquipInstruments(Entity *self, Entity *player) { // Equip the left hand instrument const auto leftInstrumentLot = instrumentLotLeft.find(GetInstrumentLot(self))->second; if (leftInstrumentLot != LOT_NULL) { - inventory->AddItem(leftInstrumentLot, 1, eLootSourceType::LOOT_SOURCE_ACTIVITY); + inventory->AddItem(leftInstrumentLot, 1, eLootSourceType::LOOT_SOURCE_NONE, TEMP_ITEMS, {}, LWOOBJID_EMPTY, false); auto* leftInstrument = inventory->FindItemByLot(leftInstrumentLot, TEMP_ITEMS); leftInstrument->Equip(); } @@ -203,7 +203,7 @@ void NsConcertInstrument::EquipInstruments(Entity *self, Entity *player) { // Equip the right hand instrument const auto rightInstrumentLot = instrumentLotRight.find(GetInstrumentLot(self))->second; if (rightInstrumentLot != LOT_NULL) { - inventory->AddItem(rightInstrumentLot, 1, eLootSourceType::LOOT_SOURCE_ACTIVITY); + inventory->AddItem(rightInstrumentLot, 1, eLootSourceType::LOOT_SOURCE_NONE, TEMP_ITEMS, {}, LWOOBJID_EMPTY, false); auto* rightInstrument = inventory->FindItemByLot(rightInstrumentLot, TEMP_ITEMS); rightInstrument->Equip(); } From 5afeb265cdbefffa8fce46675a1073fbaf25f448 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 26 Apr 2022 03:41:16 -0700 Subject: [PATCH 222/251] Updated vendor component Fixed a few issues in VendorComponent. - Corrected serialization to only happen on construction. - Added functionality to refresh the vendor based on info from the vendor component table - some whitespaceing inconsistencies. - Sorted includes. Tested the vendor in Nimbus Station and when the player re-enters the world, the vendor inventory refreshes, as opposed to previously where the world would need to reset in order to refresh the inventory. --- dGame/dComponents/VendorComponent.cpp | 187 ++++++++++++++------------ dGame/dComponents/VendorComponent.h | 30 ++++- dGame/dGameMessages/GameMessages.cpp | 6 +- dGame/dGameMessages/GameMessages.h | 2 +- dNet/dMessageIdentifiers.h | 1 + 5 files changed, 133 insertions(+), 93 deletions(-) diff --git a/dGame/dComponents/VendorComponent.cpp b/dGame/dComponents/VendorComponent.cpp index b4346bb7..4dd88e71 100644 --- a/dGame/dComponents/VendorComponent.cpp +++ b/dGame/dComponents/VendorComponent.cpp @@ -1,116 +1,135 @@ #include "VendorComponent.h" -#include "Game.h" -#include "dServer.h" #include +#include "Game.h" +#include "dServer.h" + VendorComponent::VendorComponent(Entity* parent) : Component(parent) { - auto* compRegistryTable = CDClientManager::Instance()->GetTable("ComponentsRegistry"); - auto* vendorComponentTable = CDClientManager::Instance()->GetTable("VendorComponent"); - auto* lootMatrixTable = CDClientManager::Instance()->GetTable("LootMatrix"); - auto* lootTableTable = CDClientManager::Instance()->GetTable("LootTable"); - - int componentID = compRegistryTable->GetByIDAndType(m_Parent->GetLOT(), COMPONENT_TYPE_VENDOR); - std::vector vendorComps = vendorComponentTable->Query([=](CDVendorComponent entry) { return (entry.id == componentID); }); - if (vendorComps.empty()) { - return; - } - m_BuyScalar = vendorComps[0].buyScalar; - m_SellScalar = vendorComps[0].sellScalar; - int lootMatrixID = vendorComps[0].LootMatrixIndex; - std::vector lootMatrices = lootMatrixTable->Query([=](CDLootMatrix entry) { return (entry.LootMatrixIndex == lootMatrixID); }); - if (lootMatrices.empty()) { - return; - } - for (const auto& lootMatrix : lootMatrices) { - int lootTableID = lootMatrix.LootTableIndex; - std::vector vendorItems = lootTableTable->Query([=](CDLootTable entry) { return (entry.LootTableIndex == lootTableID); }); - if (lootMatrix.maxToDrop == 0 || lootMatrix.minToDrop == 0) { - for (CDLootTable item : vendorItems) { - m_Inventory.insert({item.itemid, item.sortPriority}); - } - } else { - auto randomCount = GeneralUtils::GenerateRandomNumber(lootMatrix.minToDrop, lootMatrix.maxToDrop); - - for (size_t i = 0; i < randomCount; i++) { - if (vendorItems.empty()) { - break; - } - - auto randomItemIndex = GeneralUtils::GenerateRandomNumber(0, vendorItems.size() - 1); - - const auto& randomItem = vendorItems[randomItemIndex]; - - vendorItems.erase(vendorItems.begin() + randomItemIndex); - - m_Inventory.insert({randomItem.itemid, randomItem.sortPriority}); - } - } - } - - //Because I want a vendor to sell these cameras - if (parent->GetLOT() == 13569) { - auto randomCamera = GeneralUtils::GenerateRandomNumber(0, 2); - - switch (randomCamera) { - case 0: - m_Inventory.insert({16253, 0}); //Grungagroid - break; - case 1: - m_Inventory.insert({16254, 0}); //Hipstabrick - break; - case 2: - m_Inventory.insert({16204, 0}); //Megabrixel snapshot - break; - default: - break; - } - } - - //Custom code for Max vanity NPC - if (parent->GetLOT() == 9749 && Game::server->GetZoneID() == 1201) { - m_Inventory.clear(); - m_Inventory.insert({11909, 0}); //Top hat w frog - m_Inventory.insert({7785, 0}); //Flash bulb - m_Inventory.insert({12764, 0}); //Big fountain soda - m_Inventory.insert({12241, 0}); //Hot cocoa (from fb) - } + SetupConstants(); + RefreshInventory(true); } VendorComponent::~VendorComponent() = default; void VendorComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { - outBitStream->Write1(); - outBitStream->Write1(); // this bit is REQUIRED for vendor + mission multiinteract - outBitStream->Write(HasCraftingStation()); + // Only serialize this entity on construction. + // [bool] hasVendorInfo + // [bool] hasStandardItems (always true?) + // [bool] hasMulticostItems (only true for umami with their cooking for now.) + if (!bIsInitialUpdate) return; + outBitStream->Write1(); + outBitStream->Write1(); + outBitStream->Write(HasCraftingStation()); } void VendorComponent::OnUse(Entity* originator) { - GameMessages::SendVendorOpenWindow(m_Parent, originator->GetSystemAddress()); - GameMessages::SendVendorStatusUpdate(m_Parent, originator->GetSystemAddress()); + GameMessages::SendVendorOpenWindow(m_Parent, originator->GetSystemAddress()); + GameMessages::SendVendorStatusUpdate(m_Parent, originator->GetSystemAddress()); } float VendorComponent::GetBuyScalar() const { - return m_BuyScalar; + return m_BuyScalar; } float VendorComponent::GetSellScalar() const { - return m_SellScalar; + return m_SellScalar; } void VendorComponent::SetBuyScalar(float value) { - m_BuyScalar = value; + m_BuyScalar = value; } void VendorComponent::SetSellScalar(float value) { - m_SellScalar = value; + m_SellScalar = value; } std::map& VendorComponent::GetInventory() { - return m_Inventory; + return m_Inventory; } bool VendorComponent::HasCraftingStation() { - // As far as we know, only Umami has a crafting station - return m_Parent->GetLOT() == 13800; + // As far as we know, only Umami has a crafting station + return m_Parent->GetLOT() == 13800; } + +void VendorComponent::RefreshInventory(bool isCreation) { + //Custom code for Max vanity NPC + if (m_Parent->GetLOT() == 9749 && Game::server->GetZoneID() == 1201) { + if (!isCreation) return; + m_Inventory.insert({11909, 0}); //Top hat w frog + m_Inventory.insert({7785, 0}); //Flash bulb + m_Inventory.insert({12764, 0}); //Big fountain soda + m_Inventory.insert({12241, 0}); //Hot cocoa (from fb) + return; + } + m_Inventory.clear(); + auto* lootMatrixTable = CDClientManager::Instance()->GetTable("LootMatrix"); + std::vector lootMatrices = lootMatrixTable->Query([=](CDLootMatrix entry) { return (entry.LootMatrixIndex == m_LootMatrixID); }); + + if (lootMatrices.empty()) return; + // Done with lootMatrix table + + auto* lootTableTable = CDClientManager::Instance()->GetTable("LootTable"); + + for (const auto& lootMatrix : lootMatrices) { + int lootTableID = lootMatrix.LootTableIndex; + std::vector vendorItems = lootTableTable->Query([=](CDLootTable entry) { return (entry.LootTableIndex == lootTableID); }); + if (lootMatrix.maxToDrop == 0 || lootMatrix.minToDrop == 0) { + for (CDLootTable item : vendorItems) { + m_Inventory.insert({item.itemid, item.sortPriority}); + } + } else { + auto randomCount = GeneralUtils::GenerateRandomNumber(lootMatrix.minToDrop, lootMatrix.maxToDrop); + + for (size_t i = 0; i < randomCount; i++) { + if (vendorItems.empty()) break; + + auto randomItemIndex = GeneralUtils::GenerateRandomNumber(0, vendorItems.size() - 1); + + const auto& randomItem = vendorItems[randomItemIndex]; + + vendorItems.erase(vendorItems.begin() + randomItemIndex); + + m_Inventory.insert({randomItem.itemid, randomItem.sortPriority}); + } + } + } + + //Because I want a vendor to sell these cameras + if (m_Parent->GetLOT() == 13569) { + auto randomCamera = GeneralUtils::GenerateRandomNumber(0, 2); + + switch (randomCamera) { + case 0: + m_Inventory.insert({16253, 0}); //Grungagroid + break; + case 1: + m_Inventory.insert({16254, 0}); //Hipstabrick + break; + case 2: + m_Inventory.insert({16204, 0}); //Megabrixel snapshot + break; + default: + break; + } + } + + // Callback timer to refresh this inventory. + m_Parent->AddCallbackTimer(m_RefreshTimeSeconds, [this]() { + RefreshInventory(); + }); +} + +void VendorComponent::SetupConstants() { + auto* compRegistryTable = CDClientManager::Instance()->GetTable("ComponentsRegistry"); + int componentID = compRegistryTable->GetByIDAndType(m_Parent->GetLOT(), COMPONENT_TYPE_VENDOR); + + auto* vendorComponentTable = CDClientManager::Instance()->GetTable("VendorComponent"); + std::vector vendorComps = vendorComponentTable->Query([=](CDVendorComponent entry) { return (entry.id == componentID); }); + if (vendorComps.empty()) return; + m_BuyScalar = vendorComps[0].buyScalar; + m_SellScalar = vendorComps[0].sellScalar; + m_RefreshTimeSeconds = vendorComps[0].refreshTimeSeconds; + m_LootMatrixID = vendorComps[0].LootMatrixIndex; +} \ No newline at end of file diff --git a/dGame/dComponents/VendorComponent.h b/dGame/dComponents/VendorComponent.h index fb9dbf6b..c037d875 100644 --- a/dGame/dComponents/VendorComponent.h +++ b/dGame/dComponents/VendorComponent.h @@ -1,11 +1,12 @@ +#pragma once #ifndef VENDORCOMPONENT_H #define VENDORCOMPONENT_H -#include "RakNetTypes.h" -#include "Entity.h" -#include "GameMessages.h" #include "CDClientManager.h" #include "Component.h" +#include "Entity.h" +#include "GameMessages.h" +#include "RakNetTypes.h" /** * A component for vendor NPCs. A vendor sells items to the player. @@ -56,17 +57,36 @@ public: */ std::map& GetInventory(); + /** + * Refresh the inventory of this vendor. + */ + void RefreshInventory(bool isCreation = false); + + /** + * Called on startup of vendor to setup the variables for the component. + */ + void SetupConstants(); private: /** - * The buy scaler. + * The buy scalar. */ float m_BuyScalar; /** - * The sell scaler. + * The sell scalar. */ float m_SellScalar; + /** + * The refresh time of this vendors' inventory. + */ + float m_RefreshTimeSeconds; + + /** + * Loot matrix id of this vendor. + */ + uint32_t m_LootMatrixID; + /** * The list of items the vendor sells. */ diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index a1fbdb47..e8e84931 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -1252,8 +1252,7 @@ void GameMessages::SendVendorOpenWindow(Entity* entity, const SystemAddress& sys SEND_PACKET } -// ah yes, impl code in a send function, beautiful! -void GameMessages::SendVendorStatusUpdate(Entity* entity, const SystemAddress& sysAddr) { +void GameMessages::SendVendorStatusUpdate(Entity* entity, const SystemAddress& sysAddr, bool bUpdateOnly) { CBITSTREAM CMSGHEADER @@ -1265,7 +1264,7 @@ void GameMessages::SendVendorStatusUpdate(Entity* entity, const SystemAddress& s bitStream.Write(entity->GetObjectID()); bitStream.Write(GAME_MSG::GAME_MSG_VENDOR_STATUS_UPDATE); - bitStream.Write(false); + bitStream.Write(bUpdateOnly); bitStream.Write(static_cast(vendorItems.size())); for (std::pair item : vendorItems) { @@ -1273,6 +1272,7 @@ void GameMessages::SendVendorStatusUpdate(Entity* entity, const SystemAddress& s bitStream.Write(static_cast(item.second)); } + if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST SEND_PACKET } diff --git a/dGame/dGameMessages/GameMessages.h b/dGame/dGameMessages/GameMessages.h index f3997200..602cb4b2 100644 --- a/dGame/dGameMessages/GameMessages.h +++ b/dGame/dGameMessages/GameMessages.h @@ -109,7 +109,7 @@ namespace GameMessages { void SendModularBuildEnd(Entity* entity); void SendVendorOpenWindow(Entity* entity, const SystemAddress& sysAddr); - void SendVendorStatusUpdate(Entity* entity, const SystemAddress& sysAddr); + void SendVendorStatusUpdate(Entity* entity, const SystemAddress& sysAddr, bool bUpdateOnly = false); void SendVendorTransactionResult(Entity* entity, const SystemAddress& sysAddr); void SendRemoveItemFromInventory(Entity* entity, const SystemAddress& sysAddr, LWOOBJID iObjID, LOT templateID, int inventoryType, uint32_t stackCount, uint32_t stackRemaining); diff --git a/dNet/dMessageIdentifiers.h b/dNet/dMessageIdentifiers.h index eae3f88a..8e20ab54 100644 --- a/dNet/dMessageIdentifiers.h +++ b/dNet/dMessageIdentifiers.h @@ -324,6 +324,7 @@ enum GAME_MSG : unsigned short { GAME_MSG_ACTIVITY_STOP = 408, GAME_MSG_SHOOTING_GALLERY_CLIENT_AIM_UPDATE = 409, GAME_MSG_SHOOTING_GALLERY_FIRE = 411, + GAME_MSG_REQUEST_VENDOR_STATUS_UPDATE = 416, GAME_MSG_VENDOR_STATUS_UPDATE = 417, GAME_MSG_NOTIFY_CLIENT_SHOOTING_GALLERY_SCORE = 425, GAME_MSG_CONSUME_CLIENT_ITEM = 427, From cacf4fcd977da998a4a608d0af2493c27727d76f Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 26 Apr 2022 15:23:29 -0700 Subject: [PATCH 223/251] corrected serialization --- dGame/dComponents/VendorComponent.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/dGame/dComponents/VendorComponent.cpp b/dGame/dComponents/VendorComponent.cpp index 4dd88e71..d2df1ef1 100644 --- a/dGame/dComponents/VendorComponent.cpp +++ b/dGame/dComponents/VendorComponent.cpp @@ -13,11 +13,6 @@ VendorComponent::VendorComponent(Entity* parent) : Component(parent) { VendorComponent::~VendorComponent() = default; void VendorComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { - // Only serialize this entity on construction. - // [bool] hasVendorInfo - // [bool] hasStandardItems (always true?) - // [bool] hasMulticostItems (only true for umami with their cooking for now.) - if (!bIsInitialUpdate) return; outBitStream->Write1(); outBitStream->Write1(); outBitStream->Write(HasCraftingStation()); From fa7c4d9c27df717e379d0ff07cb3bc472e476639 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 26 Apr 2022 15:26:30 -0700 Subject: [PATCH 224/251] added comments --- dGame/dComponents/VendorComponent.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dGame/dComponents/VendorComponent.cpp b/dGame/dComponents/VendorComponent.cpp index d2df1ef1..39558774 100644 --- a/dGame/dComponents/VendorComponent.cpp +++ b/dGame/dComponents/VendorComponent.cpp @@ -14,8 +14,8 @@ VendorComponent::~VendorComponent() = default; void VendorComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { outBitStream->Write1(); - outBitStream->Write1(); - outBitStream->Write(HasCraftingStation()); + outBitStream->Write1(); // Has standard items (Required for vendors with missions.) + outBitStream->Write(HasCraftingStation()); // Has multi use items } void VendorComponent::OnUse(Entity* originator) { From 843a5b39c08f9cdccfabb05d6ea514354cb9954f Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 27 Apr 2022 01:35:46 -0700 Subject: [PATCH 225/251] Vendor refresh change Changed vendor refresh to happen as soon as it is able to. --- dGame/dComponents/VendorComponent.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/dGame/dComponents/VendorComponent.cpp b/dGame/dComponents/VendorComponent.cpp index 39558774..6a8e7356 100644 --- a/dGame/dComponents/VendorComponent.cpp +++ b/dGame/dComponents/VendorComponent.cpp @@ -114,6 +114,7 @@ void VendorComponent::RefreshInventory(bool isCreation) { m_Parent->AddCallbackTimer(m_RefreshTimeSeconds, [this]() { RefreshInventory(); }); + GameMessages::SendVendorStatusUpdate(m_Parent, UNASSIGNED_SYSTEM_ADDRESS); } void VendorComponent::SetupConstants() { From b713b948418fd64909319667ab0a455b94bc6a7b Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 26 Apr 2022 21:44:35 -0700 Subject: [PATCH 226/251] Added Loot Buff Behavior Added functions and methods to support the pickup radius. Functionality includes: Corrected serialization for ControllablePhysicsComponent which correctly serializes the pickup radius to the client. A method to add the pickup radius to the list of active pickup radii the component has. A method to remove and re-calculate the largest active radii the component currently has. Tested equipping all variations of the LootBuff behavior (passive skills, items, item skills) and all functioned as intended. Tested equipping multiple items with a loot buff and then unequipping them in different orders. Tested adding pickup radii of different values and the server correctly adjusted the pickup radius to the largest one currently equipped. --- dGame/dBehaviors/AndBehavior.cpp | 6 +++ dGame/dBehaviors/AndBehavior.h | 2 + dGame/dBehaviors/Behavior.cpp | 5 ++- dGame/dBehaviors/BehaviorContext.cpp | 4 +- dGame/dBehaviors/LootBuffBehavior.cpp | 38 ++++++++++++++++++ dGame/dBehaviors/LootBuffBehavior.h | 32 +++++++++++++++ .../ControllablePhysicsComponent.cpp | 40 ++++++++++++++++++- .../ControllablePhysicsComponent.h | 33 +++++++++++++++ 8 files changed, 155 insertions(+), 5 deletions(-) create mode 100644 dGame/dBehaviors/LootBuffBehavior.cpp create mode 100644 dGame/dBehaviors/LootBuffBehavior.h diff --git a/dGame/dBehaviors/AndBehavior.cpp b/dGame/dBehaviors/AndBehavior.cpp index 231b39c9..5fc1e113 100644 --- a/dGame/dBehaviors/AndBehavior.cpp +++ b/dGame/dBehaviors/AndBehavior.cpp @@ -19,6 +19,12 @@ void AndBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStre } } +void AndBehavior::UnCast(BehaviorContext* context, const BehaviorBranchContext branch) { + for (auto behavior : this->m_behaviors) { + behavior->UnCast(context, branch); + } +} + void AndBehavior::Load() { const auto parameters = GetParameterNames(); diff --git a/dGame/dBehaviors/AndBehavior.h b/dGame/dBehaviors/AndBehavior.h index 2b7d95e6..9cbce569 100644 --- a/dGame/dBehaviors/AndBehavior.h +++ b/dGame/dBehaviors/AndBehavior.h @@ -20,5 +20,7 @@ public: void Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override; + void UnCast(BehaviorContext* context, BehaviorBranchContext branch) override; + void Load() override; }; diff --git a/dGame/dBehaviors/Behavior.cpp b/dGame/dBehaviors/Behavior.cpp index 74153c11..db5bbf2f 100644 --- a/dGame/dBehaviors/Behavior.cpp +++ b/dGame/dBehaviors/Behavior.cpp @@ -18,6 +18,7 @@ #include "AreaOfEffectBehavior.h" #include "DurationBehavior.h" #include "TacArcBehavior.h" +#include "LootBuffBehavior.h" #include "AttackDelayBehavior.h" #include "BasicAttackBehavior.h" #include "ChainBehavior.h" @@ -172,7 +173,9 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) behavior = new SpeedBehavior(behaviorId); break; case BehaviorTemplates::BEHAVIOR_DARK_INSPIRATION: break; - case BehaviorTemplates::BEHAVIOR_LOOT_BUFF: break; + case BehaviorTemplates::BEHAVIOR_LOOT_BUFF: + behavior = new LootBuffBehavior(behaviorId); + break; case BehaviorTemplates::BEHAVIOR_VENTURE_VISION: break; case BehaviorTemplates::BEHAVIOR_SPAWN_OBJECT: behavior = new SpawnBehavior(behaviorId); diff --git a/dGame/dBehaviors/BehaviorContext.cpp b/dGame/dBehaviors/BehaviorContext.cpp index fc67a82d..c7bf912f 100644 --- a/dGame/dBehaviors/BehaviorContext.cpp +++ b/dGame/dBehaviors/BehaviorContext.cpp @@ -64,8 +64,8 @@ void BehaviorContext::RegisterSyncBehavior(const uint32_t syncId, Behavior* beha void BehaviorContext::RegisterTimerBehavior(Behavior* behavior, const BehaviorBranchContext& branchContext, const LWOOBJID second) { - BehaviorTimerEntry entry -; + BehaviorTimerEntry entry; + entry.time = branchContext.duration; entry.behavior = behavior; entry.branchContext = branchContext; diff --git a/dGame/dBehaviors/LootBuffBehavior.cpp b/dGame/dBehaviors/LootBuffBehavior.cpp new file mode 100644 index 00000000..fe46f7bb --- /dev/null +++ b/dGame/dBehaviors/LootBuffBehavior.cpp @@ -0,0 +1,38 @@ +#include "LootBuffBehavior.h" + +void LootBuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) { + auto target = EntityManager::Instance()->GetEntity(context->caster); + if (!target) return; + + auto controllablePhysicsComponent = target->GetComponent(); + if (!controllablePhysicsComponent) return; + + controllablePhysicsComponent->AddPickupRadiusScale(m_Scale); + EntityManager::Instance()->SerializeEntity(target); + + if (branch.duration > 0) context->RegisterTimerBehavior(this, branch); + +} + +void LootBuffBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) { + Handle(context, bitStream, branch); +} + +void LootBuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) { + auto target = EntityManager::Instance()->GetEntity(context->caster); + if (!target) return; + + auto controllablePhysicsComponent = target->GetComponent(); + if (!controllablePhysicsComponent) return; + + controllablePhysicsComponent->RemovePickupRadiusScale(m_Scale); + EntityManager::Instance()->SerializeEntity(target); +} + +void LootBuffBehavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) { + UnCast(context, branch); +} + +void LootBuffBehavior::Load() { + this->m_Scale = GetFloat("scale"); +} \ No newline at end of file diff --git a/dGame/dBehaviors/LootBuffBehavior.h b/dGame/dBehaviors/LootBuffBehavior.h new file mode 100644 index 00000000..0f85b3b0 --- /dev/null +++ b/dGame/dBehaviors/LootBuffBehavior.h @@ -0,0 +1,32 @@ +#pragma once +#include "Behavior.h" +#include "BehaviorBranchContext.h" +#include "BehaviorContext.h" +#include "ControllablePhysicsComponent.h" + +/** + * @brief This is the behavior class to be used for all Loot Buff behavior nodes in the Behavior tree. + * + */ +class LootBuffBehavior final : public Behavior +{ +public: + + float m_Scale; + + /* + * Inherited + */ + + explicit LootBuffBehavior(const uint32_t behaviorId) : Behavior(behaviorId) {} + + void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override; + + void Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override; + + void UnCast(BehaviorContext* context, BehaviorBranchContext branch) override; + + void Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) override; + + void Load() override; +}; diff --git a/dGame/dComponents/ControllablePhysicsComponent.cpp b/dGame/dComponents/ControllablePhysicsComponent.cpp index 922ae55d..648b1471 100644 --- a/dGame/dComponents/ControllablePhysicsComponent.cpp +++ b/dGame/dComponents/ControllablePhysicsComponent.cpp @@ -29,6 +29,8 @@ ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity) : Com m_GravityScale = 1; m_DirtyCheats = false; m_IgnoreMultipliers = false; + m_PickupRadius = 0.0f; + m_DirtyPickupRadiusScale = true; if (entity->GetLOT() != 1) // Other physics entities we care about will be added by BaseCombatAI return; @@ -85,7 +87,13 @@ void ControllablePhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bo m_DirtyCheats = false; } - outBitStream->Write0(); + outBitStream->Write(m_DirtyPickupRadiusScale); + if (m_DirtyPickupRadiusScale) { + outBitStream->Write(m_PickupRadius); + outBitStream->Write0(); //No clue what this is so im leaving it false. + m_DirtyPickupRadiusScale = false; + } + outBitStream->Write0(); outBitStream->Write(m_DirtyPosition || bIsInitialUpdate); @@ -230,4 +238,32 @@ void ControllablePhysicsComponent::SetDirtyVelocity(bool val) { void ControllablePhysicsComponent::SetDirtyAngularVelocity(bool val) { m_DirtyAngularVelocity = val; -} \ No newline at end of file +} + +void ControllablePhysicsComponent::AddPickupRadiusScale(float value) { + m_ActivePickupRadiusScales.push_back(value); + if (value > m_PickupRadius) { + m_PickupRadius = value; + m_DirtyPickupRadiusScale = true; + } +} + +void ControllablePhysicsComponent::RemovePickupRadiusScale(float value) { + // Attempt to remove pickup radius from active radii + const auto pos = std::find(m_ActivePickupRadiusScales.begin(), m_ActivePickupRadiusScales.end(), value); + if (pos != m_ActivePickupRadiusScales.end()) { + m_ActivePickupRadiusScales.erase(pos); + } else { + Game::logger->Log("ControllablePhysicsComponent", "Warning: Could not find pickup radius %f in list of active radii. List has %i active radii.\n", value, m_ActivePickupRadiusScales.size()); + return; + } + + // Recalculate pickup radius since we removed one by now + m_PickupRadius = 0.0f; + m_DirtyPickupRadiusScale = true; + for (uint32_t i = 0; i < m_ActivePickupRadiusScales.size(); i++) { + auto candidateRadius = m_ActivePickupRadiusScales[i]; + if (m_PickupRadius < candidateRadius) m_PickupRadius = candidateRadius; + } + EntityManager::Instance()->SerializeEntity(m_Parent); +} diff --git a/dGame/dComponents/ControllablePhysicsComponent.h b/dGame/dComponents/ControllablePhysicsComponent.h index f0fe7461..c7acec62 100644 --- a/dGame/dComponents/ControllablePhysicsComponent.h +++ b/dGame/dComponents/ControllablePhysicsComponent.h @@ -227,6 +227,24 @@ public: dpEntity* GetdpEntity() const { return m_dpEntity; } + /** + * I store this in a vector because if I have 2 separate pickup radii being applied to the player, I dont know which one is correctly active. + * This method adds the pickup radius to the vector of active radii and if its larger than the current one, is applied as the new pickup radius. + */ + void AddPickupRadiusScale(float value) ; + + /** + * Removes the provided pickup radius scale from our list of buffs + * The recalculates what our pickup radius is. + */ + void RemovePickupRadiusScale(float value) ; + + /** + * The pickup radii of this component. + * @return All active radii scales for this component. + */ + std::vector GetActivePickupRadiusScales() { return m_ActivePickupRadiusScales; }; + private: /** * The entity that owns this component @@ -322,6 +340,21 @@ private: * Whether this entity is static, making it unable to move */ bool m_Static; + + /** + * Whether the pickup scale is dirty. + */ + bool m_DirtyPickupRadiusScale; + + /** + * The list of pickup radius scales for this entity + */ + std::vector m_ActivePickupRadiusScales; + + /** + * The active pickup radius for this entity + */ + float m_PickupRadius; }; #endif // CONTROLLABLEPHYSICSCOMPONENT_H From 2f598dad09d30b2ef8c3fe3ed18c7cdcd252232d Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 28 Apr 2022 00:13:57 -0700 Subject: [PATCH 227/251] Serialize ape when changing armor value --- dScripts/BaseEnemyApe.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dScripts/BaseEnemyApe.cpp b/dScripts/BaseEnemyApe.cpp index 3419b2c4..9aa391d1 100644 --- a/dScripts/BaseEnemyApe.cpp +++ b/dScripts/BaseEnemyApe.cpp @@ -49,7 +49,7 @@ void BaseEnemyApe::OnTimerDone(Entity *self, std::string timerName) { if (destroyableComponent != nullptr) { destroyableComponent->SetArmor(destroyableComponent->GetMaxArmor() / timesStunned); } - + EntityManager::Instance()->SerializeEntity(self); self->SetVar(u"timesStunned", timesStunned + 1); StunApe(self, false); From 59be7d86354e3aa058287aad0ce2c0efeb49b084 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 28 Apr 2022 14:36:55 -0700 Subject: [PATCH 228/251] Added back brick inventory resizing --- dGame/dInventory/Inventory.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dGame/dInventory/Inventory.cpp b/dGame/dInventory/Inventory.cpp index ae1715d7..6e8be6aa 100644 --- a/dGame/dInventory/Inventory.cpp +++ b/dGame/dInventory/Inventory.cpp @@ -102,6 +102,10 @@ int32_t Inventory::FindEmptySlot() { newSize += 9u; } + else + { + newSize += 10u; + } if (newSize > GetSize()) { From 2435870ec532ee6dcaa19ed75d6e9c828f78b988 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Thu, 28 Apr 2022 19:51:49 -0700 Subject: [PATCH 229/251] Added animation Added the GM animation and stun for the Nexus Tower Paradox Panels for mission 1281. Tested on local instance and animation played correctly when having the mission and did not play at all before or after completing the mission --- dScripts/NtParadoxPanelServer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dScripts/NtParadoxPanelServer.cpp b/dScripts/NtParadoxPanelServer.cpp index c1c9dd3f..556002fe 100644 --- a/dScripts/NtParadoxPanelServer.cpp +++ b/dScripts/NtParadoxPanelServer.cpp @@ -38,10 +38,11 @@ void NtParadoxPanelServer::OnUse(Entity* self, Entity* user) GameMessages::SendPlayAnimation(player, u"rebuild-celebrate"); GameMessages::SendNotifyClientObject(self->GetObjectID(), u"SparkStop", 0, 0, player->GetObjectID(), "", player->GetSystemAddress()); - + GameMessages::SendSetStunned(player->GetObjectID(), eStunState::POP, player->GetSystemAddress(), LWOOBJID_EMPTY, false, false, true, false, true, true, false, false, true); self->SetVar(u"bActive", false); }); - + GameMessages::SendPlayAnimation(user, u"nexus-powerpanel", 6.0f); + GameMessages::SendSetStunned(user->GetObjectID(), eStunState::PUSH, user->GetSystemAddress(), LWOOBJID_EMPTY, false, false, true, false, true, true, false, false, true); return; } From 763a1f4a613c2de8d438a4f64be4302b5005bcaf Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Sun, 1 May 2022 08:54:45 -0500 Subject: [PATCH 230/251] Split out Darkitect reveal into it's own file add reveal to Fong --- dScripts/CppScripts.cpp | 3 ++ dScripts/Darkitect.cpp | 35 ++++++++++++++++++ dScripts/Darkitect.h | 9 +++++ dScripts/FvFong.cpp | 12 ++++++ dScripts/FvFong.h | 8 ++++ dScripts/NtDarkitectRevealServer.cpp | 55 +++++----------------------- dScripts/NtDarkitectRevealServer.h | 3 +- 7 files changed, 77 insertions(+), 48 deletions(-) create mode 100644 dScripts/Darkitect.cpp create mode 100644 dScripts/Darkitect.h create mode 100644 dScripts/FvFong.cpp create mode 100644 dScripts/FvFong.h diff --git a/dScripts/CppScripts.cpp b/dScripts/CppScripts.cpp index 8be1c0d4..5036b111 100644 --- a/dScripts/CppScripts.cpp +++ b/dScripts/CppScripts.cpp @@ -147,6 +147,7 @@ #include "FvNinjaGuard.h" #include "FvPassThroughWall.h" #include "FvBounceOverWall.h" +#include "FvFong.h" // FB Scripts #include "AgJetEffectServer.h" @@ -568,6 +569,8 @@ CppScripts::Script* CppScripts::GetScript(Entity* parent, const std::string& scr script = new FvPassThroughWall(); else if (scriptName == "scripts\\ai\\FV\\L_ACT_BOUNCE_OVER_WALL.lua") script = new FvBounceOverWall(); + else if (scriptName == "scripts\\02_server\\Map\\FV\\L_NPC_FONG.lua") + script = new FvFong(); //Misc: if (scriptName == "scripts\\02_server\\Map\\General\\L_EXPLODING_ASSET.lua") diff --git a/dScripts/Darkitect.cpp b/dScripts/Darkitect.cpp new file mode 100644 index 00000000..c4e1e45d --- /dev/null +++ b/dScripts/Darkitect.cpp @@ -0,0 +1,35 @@ +#include "Darkitect.h" +#include "MissionComponent.h" +#include "DestroyableComponent.h" +#include "EntityManager.h" +#include "GameMessages.h" +#include "Character.h" + +void Darkitect::Reveal(Entity* self, Entity* player) +{ + const auto playerID = player->GetObjectID(); + + GameMessages::SendNotifyClientObject(self->GetObjectID(), u"reveal", 0, 0, playerID, "", player->GetSystemAddress()); + + self->AddCallbackTimer(20, [this, self, playerID]() { + auto* player = EntityManager::Instance()->GetEntity(playerID); + + if (!player) return; + + auto* destroyableComponent = player->GetComponent(); + auto* missionComponent = player->GetComponent(); + auto* character = player->GetCharacter(); + + if (destroyableComponent != nullptr && missionComponent != nullptr && character != nullptr) { + destroyableComponent->SetArmor(0); + destroyableComponent->SetHealth(1); + destroyableComponent->SetImagination(0); + + if (missionComponent->GetMissionState(1295) == MissionState::MISSION_STATE_ACTIVE) { + character->SetPlayerFlag(1911, true); + } + + EntityManager::Instance()->SerializeEntity(player); + } + }); +} diff --git a/dScripts/Darkitect.h b/dScripts/Darkitect.h new file mode 100644 index 00000000..f0d19648 --- /dev/null +++ b/dScripts/Darkitect.h @@ -0,0 +1,9 @@ +#pragma once + +class Entity; + +class Darkitect +{ +public: + void Reveal(Entity* self, Entity* player); +}; diff --git a/dScripts/FvFong.cpp b/dScripts/FvFong.cpp new file mode 100644 index 00000000..890bf0ff --- /dev/null +++ b/dScripts/FvFong.cpp @@ -0,0 +1,12 @@ +#include "FvFong.h" +#include "Darkitect.h" +#include "MissionComponent.h" + +void FvFong::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState) +{ + if (missionID == 734 && missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE) + { + Darkitect Baron; + Baron.Reveal(self, target); + } +} diff --git a/dScripts/FvFong.h b/dScripts/FvFong.h new file mode 100644 index 00000000..fc47b484 --- /dev/null +++ b/dScripts/FvFong.h @@ -0,0 +1,8 @@ +#pragma once +#include "CppScripts.h" + +class FvFong : public CppScripts::Script +{ + public: + void OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState) override; +}; diff --git a/dScripts/NtDarkitectRevealServer.cpp b/dScripts/NtDarkitectRevealServer.cpp index 2bfbb063..b8afa510 100644 --- a/dScripts/NtDarkitectRevealServer.cpp +++ b/dScripts/NtDarkitectRevealServer.cpp @@ -1,53 +1,16 @@ #include "NtDarkitectRevealServer.h" +#include "Darkitect.h" #include "MissionComponent.h" -#include "DestroyableComponent.h" -#include "EntityManager.h" -#include "GameMessages.h" -#include "Character.h" - -void NtDarkitectRevealServer::OnUse(Entity* self, Entity* user) +void NtDarkitectRevealServer::OnUse(Entity* self, Entity* user) { - Darkitect(self, user); + Darkitect Baron; + Baron.Reveal(self, user); - auto* missionComponent = user->GetComponent(); + auto* missionComponent = user->GetComponent(); - if (missionComponent != nullptr) - { - missionComponent->ForceProgressTaskType(1344, 1, 14293); - } -} - -void NtDarkitectRevealServer::Darkitect(Entity* self, Entity* player) -{ - const auto playerID = player->GetObjectID(); - - GameMessages::SendNotifyClientObject(self->GetObjectID(), u"reveal", 0, 0, playerID, "", player->GetSystemAddress()); - - self->AddCallbackTimer(20, [this, self, playerID]() { - auto* player = EntityManager::Instance()->GetEntity(playerID); - - if (player == nullptr) - { - return; - } - - auto* destroyableComponent = player->GetComponent(); - auto* missionComponent = player->GetComponent(); - auto* character = player->GetCharacter(); - - if (destroyableComponent != nullptr && missionComponent != nullptr && character != nullptr) - { - destroyableComponent->SetArmor(0); - destroyableComponent->SetHealth(1); - destroyableComponent->SetImagination(0); - - if (missionComponent->GetMissionState(1295) == MissionState::MISSION_STATE_ACTIVE) - { - character->SetPlayerFlag(1911, true); - } - - EntityManager::Instance()->SerializeEntity(player); - } - }); + if (missionComponent != nullptr) + { + missionComponent->ForceProgressTaskType(1344, 1, 14293); + } } diff --git a/dScripts/NtDarkitectRevealServer.h b/dScripts/NtDarkitectRevealServer.h index 60d89934..2b954671 100644 --- a/dScripts/NtDarkitectRevealServer.h +++ b/dScripts/NtDarkitectRevealServer.h @@ -4,6 +4,5 @@ class NtDarkitectRevealServer : public CppScripts::Script { public: - void OnUse(Entity* self, Entity* user) override; - void Darkitect(Entity* self, Entity* player); + void OnUse(Entity* self, Entity* user) override; }; From 6b409303afdf0730f3812a5c8fb62f4e73adeaa1 Mon Sep 17 00:00:00 2001 From: EmosewaMC <39972741+EmosewaMC@users.noreply.github.com> Date: Mon, 2 May 2022 22:32:00 -0700 Subject: [PATCH 231/251] Update RebuildComponent.h Quickbuilds jump fix Corrected an error where the builder was erronously changed to an empty lwoobjid when a quickbuild was completed, causing the builds to no longer jump on completion (if configured to do so.) Packet captures from live show that we do not want to get rid of the builder during resetting or during completion of the build so the file has been changed to not clear the builder in those cases. --- dGame/dComponents/RebuildComponent.cpp | 20 +++++++++++++------- dGame/dComponents/RebuildComponent.h | 8 ++++++-- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/dGame/dComponents/RebuildComponent.cpp b/dGame/dComponents/RebuildComponent.cpp index ef970d98..abee5e16 100644 --- a/dGame/dComponents/RebuildComponent.cpp +++ b/dGame/dComponents/RebuildComponent.cpp @@ -45,7 +45,14 @@ void RebuildComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitia outBitStream->Write(false); } - + // If build state is completed and we've already serialized once in the completed state, + // don't serializing this component anymore as this will cause the build to jump again. + // If state changes, serialization will begin again. + if (!m_StateDirty && m_State == REBUILD_COMPLETED) { + outBitStream->Write0(); + outBitStream->Write0(); + return; + } // BEGIN Scripted Activity outBitStream->Write1(); @@ -79,6 +86,7 @@ void RebuildComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitia outBitStream->Write(m_ActivatorPosition); outBitStream->Write(m_RepositionPlayer); } + m_StateDirty = false; } void RebuildComponent::Update(float deltaTime) { @@ -139,7 +147,6 @@ void RebuildComponent::Update(float deltaTime) { } if (m_Timer >= m_ResetTime) { - m_Builder = LWOOBJID_EMPTY; GameMessages::SendDieNoImplCode(m_Parent, LWOOBJID_EMPTY, LWOOBJID_EMPTY, eKillType::VIOLENT, u"", 0.0f, 0.0f, 0.0f, false, true); @@ -384,7 +391,7 @@ void RebuildComponent::StartRebuild(Entity* user) { GameMessages::SendEnableRebuild(m_Parent, true, false, false, eFailReason::REASON_NOT_GIVEN, 0.0f, user->GetObjectID()); m_State = eRebuildState::REBUILD_BUILDING; - + m_StateDirty = true; EntityManager::Instance()->SerializeEntity(m_Parent); auto* movingPlatform = m_Parent->GetComponent(); @@ -427,6 +434,7 @@ void RebuildComponent::CompleteRebuild(Entity* user) { m_State = eRebuildState::REBUILD_COMPLETED; + m_StateDirty = true; m_Timer = 0.0f; m_DrainedImagination = 0; @@ -455,8 +463,6 @@ void RebuildComponent::CompleteRebuild(Entity* user) { LootGenerator::Instance().DropActivityLoot(builder, m_Parent, m_ActivityId, 1); } - m_Builder = LWOOBJID_EMPTY; - // Notify scripts for (auto* script : CppScripts::GetEntityScripts(m_Parent)) { script->OnRebuildComplete(m_Parent, user); @@ -501,12 +507,11 @@ void RebuildComponent::ResetRebuild(bool failed) { GameMessages::SendRebuildNotifyState(m_Parent, m_State, eRebuildState::REBUILD_RESETTING, LWOOBJID_EMPTY); m_State = eRebuildState::REBUILD_RESETTING; + m_StateDirty = true; m_Timer = 0.0f; m_TimerIncomplete = 0.0f; m_ShowResetEffect = false; m_DrainedImagination = 0; - - m_Builder = LWOOBJID_EMPTY; EntityManager::Instance()->SerializeEntity(m_Parent); @@ -541,6 +546,7 @@ void RebuildComponent::CancelRebuild(Entity* entity, eFailReason failReason, boo // Now update the component itself m_State = eRebuildState::REBUILD_INCOMPLETE; + m_StateDirty = true; // Notify scripts and possible subscribers for (auto* script : CppScripts::GetEntityScripts(m_Parent)) diff --git a/dGame/dComponents/RebuildComponent.h b/dGame/dComponents/RebuildComponent.h index c177f42c..72c57bb0 100644 --- a/dGame/dComponents/RebuildComponent.h +++ b/dGame/dComponents/RebuildComponent.h @@ -216,7 +216,11 @@ public: */ void CancelRebuild(Entity* builder, eFailReason failReason, bool skipChecks = false); private: - + /** + * Whether or not the quickbuild state has been changed since we last serialized it. + */ + bool m_StateDirty = true; + /** * The state the rebuild is currently in */ @@ -235,7 +239,7 @@ private: /** * The position that the rebuild activator is spawned at */ - NiPoint3 m_ActivatorPosition {}; + NiPoint3 m_ActivatorPosition = NiPoint3::ZERO; /** * The entity that represents the rebuild activator From bd3e8aee51443838e4a87c31822d704ba49f4cd8 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Tue, 3 May 2022 15:05:29 -0500 Subject: [PATCH 232/251] Implement Rocket Launch Lup Component --- dGame/Entity.cpp | 15 +- .../dComponents/RocketLaunchLupComponent.cpp | 55 +++++++ dGame/dComponents/RocketLaunchLupComponent.h | 25 +++ dGame/dGameMessages/GameMessages.cpp | 12 +- dScripts/BaseConsoleTeleportServer.cpp | 15 -- dScripts/CppScripts.cpp | 3 - dScripts/SbLupTeleport.cpp | 154 ------------------ dScripts/SbLupTeleport.h | 23 --- 8 files changed, 94 insertions(+), 208 deletions(-) create mode 100644 dGame/dComponents/RocketLaunchLupComponent.cpp create mode 100644 dGame/dComponents/RocketLaunchLupComponent.h delete mode 100644 dScripts/SbLupTeleport.cpp delete mode 100644 dScripts/SbLupTeleport.h diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 75d8d8b6..132a0eb7 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -22,6 +22,7 @@ #include "Component.h" #include "ControllablePhysicsComponent.h" #include "RenderComponent.h" +#include "RocketLaunchLupComponent.h" #include "CharacterComponent.h" #include "DestroyableComponent.h" #include "BuffComponent.h" @@ -456,9 +457,10 @@ void Entity::Initialize() else comp = new InventoryComponent(this); m_Components.insert(std::make_pair(COMPONENT_TYPE_INVENTORY, comp)); } - - if (compRegistryTable->GetByIDAndType(m_TemplateID, COMPONENT_TYPE_ROCKET_LAUNCH_LUP) > 0) { - m_Components.insert(std::make_pair(COMPONENT_TYPE_ROCKET_LAUNCH_LUP, nullptr)); + // if this component exists, then we initialize it. it's value is always 0 + if (compRegistryTable->GetByIDAndType(m_TemplateID, COMPONENT_TYPE_ROCKET_LAUNCH_LUP, -1) != -1) { + auto comp = new RocketLaunchLupComponent(this); + m_Components.insert(std::make_pair(COMPONENT_TYPE_ROCKET_LAUNCH_LUP, comp)); } /** @@ -495,13 +497,6 @@ void Entity::Initialize() std::string customScriptServer; bool hasCustomServerScript = false; - // Custom script for the LUP teleporter - if (m_TemplateID == 14333) - { - hasCustomServerScript = true; - customScriptServer = "scripts\\02_server\\DLU\\L_SB_LUP_TELEPORT.lua"; - } - const auto customScriptServerName = GetVarAsString(u"custom_script_server"); const auto customScriptClientName = GetVarAsString(u"custom_script_client"); diff --git a/dGame/dComponents/RocketLaunchLupComponent.cpp b/dGame/dComponents/RocketLaunchLupComponent.cpp new file mode 100644 index 00000000..5e5db538 --- /dev/null +++ b/dGame/dComponents/RocketLaunchLupComponent.cpp @@ -0,0 +1,55 @@ +#include "RocketLaunchLupComponent.h" +#include "CDClientDatabase.h" +#include "RocketLaunchpadControlComponent.h" +#include "CharacterComponent.h" +#include "Item.h" + +RocketLaunchLupComponent::RocketLaunchLupComponent(Entity* parent) : Component(parent) { + m_Parent = parent; + + // get the lup worlds from the cdclient + std::string query = "SELECT * FROM LUPZoneIDs;"; + auto results = CDClientDatabase::ExecuteQuery(query); + while (!results.eof()) { + // fallback to 1600 incase there is an issue + m_LUPWorlds.push_back(results.getIntField(0, 1600)); + results.nextRow(); + } + results.finalize(); +} + +RocketLaunchLupComponent::~RocketLaunchLupComponent() { + if (!m_rocket) return; + // when we exit the ui we need to unequip the rocket + m_rocket->UnEquip(); +} + +void RocketLaunchLupComponent::OnUse(Entity* originator) { + // the LUP world menu is just the property menu, the client knows how to handle it + GameMessages::SendPropertyEntranceBegin(m_Parent->GetObjectID(), m_Parent->GetSystemAddress()); + + // get the rocket to "equip" it so we are holding it + // taken from the RocketLaunchControlComponent + auto* inventoryComponent = originator->GetComponent(); + auto* characterComponent = originator->GetComponent(); + + if (!inventoryComponent || !characterComponent) return; + + m_rocket = inventoryComponent->FindItemById(characterComponent->GetLastRocketItemID()); + if (!m_rocket) return; + + m_rocket->Equip(true); +} + +void RocketLaunchLupComponent::OnSelectWorld(Entity* originator, uint32_t index, const SystemAddress& sysAddr) { + if (m_rocket) m_rocket->UnEquip(); + + // Add one to index because the actual LUP worlds start at index 1. + index++; + + auto* rocketLaunchpadControlComponent = m_Parent->GetComponent(); + + if (!rocketLaunchpadControlComponent) return; + + rocketLaunchpadControlComponent->Launch(originator, LWOOBJID_EMPTY, m_LUPWorlds[index], 0); +} diff --git a/dGame/dComponents/RocketLaunchLupComponent.h b/dGame/dComponents/RocketLaunchLupComponent.h new file mode 100644 index 00000000..621a80cf --- /dev/null +++ b/dGame/dComponents/RocketLaunchLupComponent.h @@ -0,0 +1,25 @@ +#pragma once + +#include "Entity.h" +#include "GameMessages.h" +#include "Component.h" +#include "Item.h" + +/** + * Component that handles the LUP/WBL rocket launchpad that can be interacted with to travel to WBL worlds. + * + */ +class RocketLaunchLupComponent : public Component { +public: + static const uint32_t ComponentType = eReplicaComponentType::COMPONENT_TYPE_ROCKET_LAUNCH_LUP; + + RocketLaunchLupComponent(Entity* parent); + ~RocketLaunchLupComponent() override; + + void OnUse(Entity* originator) override; + + void OnSelectWorld(Entity* originator, uint32_t index, const SystemAddress& sysAddr); +private: + std::vector m_LUPWorlds {}; + Item* m_rocket = nullptr; +}; diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index e8e84931..7cb8ae8f 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -26,6 +26,7 @@ #include "TeamManager.h" #include "ChatPackets.h" #include "GameConfig.h" +#include "RocketLaunchLupComponent.h" #include #include @@ -2726,10 +2727,15 @@ void GameMessages::HandleEnterProperty(RakNet::BitStream* inStream, Entity* enti auto* player = Player::GetPlayer(sysAddr); auto* entranceComponent = entity->GetComponent(); + if (entranceComponent != nullptr) { + entranceComponent->OnEnterProperty(player, index, returnToZone, sysAddr); + return; + } - if (entranceComponent == nullptr) return; - - entranceComponent->OnEnterProperty(player, index, returnToZone, sysAddr); + auto rocketLaunchLupComponent = entity->GetComponent(); + if (rocketLaunchLupComponent) { + rocketLaunchLupComponent->OnSelectWorld(player, index, sysAddr); + } } void GameMessages::HandleSetConsumableItem(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) diff --git a/dScripts/BaseConsoleTeleportServer.cpp b/dScripts/BaseConsoleTeleportServer.cpp index a9cd74e8..ef2d00e0 100644 --- a/dScripts/BaseConsoleTeleportServer.cpp +++ b/dScripts/BaseConsoleTeleportServer.cpp @@ -19,21 +19,6 @@ void BaseConsoleTeleportServer::BaseOnMessageBoxResponse(Entity* self, Entity* s if (button == 1) { - if (self->GetLOT() == 14333) - { - auto* rocketLaunchComponent = self->GetComponent(); - - if (rocketLaunchComponent == nullptr) - { - return; - } - - const auto& teleportZone = self->GetVar(u"transferZoneID"); - - rocketLaunchComponent->Launch(player, LWOOBJID_EMPTY, std::stoi(GeneralUtils::UTF16ToWTF8(teleportZone))); - - return; - } GameMessages::SendSetStunned(player->GetObjectID(), PUSH, player->GetSystemAddress(), player->GetObjectID(), true, true, true, true, true, true, true diff --git a/dScripts/CppScripts.cpp b/dScripts/CppScripts.cpp index 5036b111..00a253dc 100644 --- a/dScripts/CppScripts.cpp +++ b/dScripts/CppScripts.cpp @@ -203,7 +203,6 @@ #include "NtSleepingGuard.h" // DLU Scripts -#include "SbLupTeleport.h" #include "DLUVanityNPC.h" // AM Scripts @@ -767,8 +766,6 @@ CppScripts::Script* CppScripts::GetScript(Entity* parent, const std::string& scr script = new NjNyaMissionitems(); //DLU: - else if (scriptName == "scripts\\02_server\\DLU\\L_SB_LUP_TELEPORT.lua") - script = new SbLupTeleport(); else if (scriptName == "scripts\\02_server\\DLU\\DLUVanityNPC.lua") script = new DLUVanityNPC(); diff --git a/dScripts/SbLupTeleport.cpp b/dScripts/SbLupTeleport.cpp deleted file mode 100644 index 2ea9c1fc..00000000 --- a/dScripts/SbLupTeleport.cpp +++ /dev/null @@ -1,154 +0,0 @@ -#include "SbLupTeleport.h" -#include "dZoneManager.h" -#include "EntityManager.h" -#include "GeneralUtils.h" -#include "GameMessages.h" - -void SbLupTeleport::OnStartup(Entity* self) -{ - self->SetVar(u"currentZone", (int32_t) dZoneManager::Instance()->GetZoneID().GetMapID()); - self->SetVar(u"choiceZone", m_ChoiceZoneID); - self->SetVar(u"teleportAnim", m_TeleportAnim); - self->SetVar(u"teleportString", m_TeleportString); - self->SetVar(u"spawnPoint", m_SpawnPoint); - - args = {}; - - AMFStringValue* callbackClient = new AMFStringValue(); - callbackClient->SetStringValue(std::to_string(self->GetObjectID())); - args.InsertValue("callbackClient", callbackClient); - - AMFStringValue* strIdentifier = new AMFStringValue(); - strIdentifier->SetStringValue("choiceDoor"); - args.InsertValue("strIdentifier", strIdentifier); - - AMFStringValue* title = new AMFStringValue(); - title->SetStringValue("%[LUP_Starbase3001_Launchpad]"); - args.InsertValue("title", title); - - AMFArrayValue* choiceOptions = new AMFArrayValue(); - - { - AMFArrayValue* nsArgs = new AMFArrayValue(); - - AMFStringValue* image = new AMFStringValue(); - image->SetStringValue("textures/ui/zone_thumnails/Deep_Freeze.dds"); - nsArgs->InsertValue("image", image); - - AMFStringValue* caption = new AMFStringValue(); - caption->SetStringValue("%[ZoneTable_1601_DisplayDescription]"); - nsArgs->InsertValue("caption", caption); - - AMFStringValue* identifier = new AMFStringValue(); - identifier->SetStringValue("zoneID_1601"); - nsArgs->InsertValue("identifier", identifier); - - AMFStringValue* tooltipText = new AMFStringValue(); - tooltipText->SetStringValue("%[ZoneTable_1601_summary]"); - nsArgs->InsertValue("tooltipText", tooltipText); - - choiceOptions->PushBackValue(nsArgs); - } - - { - AMFArrayValue* ntArgs = new AMFArrayValue(); - - AMFStringValue* image = new AMFStringValue(); - image->SetStringValue("textures/ui/zone_thumnails/Robot_City.dds"); - ntArgs->InsertValue("image", image); - - AMFStringValue* caption = new AMFStringValue(); - caption->SetStringValue("%[ZoneTable_1602_DisplayDescription]"); - ntArgs->InsertValue("caption", caption); - - AMFStringValue* identifier = new AMFStringValue(); - identifier->SetStringValue("zoneID_1602"); - ntArgs->InsertValue("identifier", identifier); - - AMFStringValue* tooltipText = new AMFStringValue(); - tooltipText->SetStringValue("%[ZoneTable_1602_summary]"); - ntArgs->InsertValue("tooltipText", tooltipText); - - choiceOptions->PushBackValue(ntArgs); - } - - { - AMFArrayValue* ntArgs = new AMFArrayValue(); - - AMFStringValue* image = new AMFStringValue(); - image->SetStringValue("textures/ui/zone_thumnails/Moon_Base.dds"); - ntArgs->InsertValue("image", image); - - AMFStringValue* caption = new AMFStringValue(); - caption->SetStringValue("%[ZoneTable_1603_DisplayDescription]"); - ntArgs->InsertValue("caption", caption); - - AMFStringValue* identifier = new AMFStringValue(); - identifier->SetStringValue("zoneID_1603"); - ntArgs->InsertValue("identifier", identifier); - - AMFStringValue* tooltipText = new AMFStringValue(); - tooltipText->SetStringValue("%[ZoneTable_1603_summary]"); - ntArgs->InsertValue("tooltipText", tooltipText); - - choiceOptions->PushBackValue(ntArgs); - } - - { - AMFArrayValue* ntArgs = new AMFArrayValue(); - - AMFStringValue* image = new AMFStringValue(); - image->SetStringValue("textures/ui/zone_thumnails/Porto_Bello.dds"); - ntArgs->InsertValue("image", image); - - AMFStringValue* caption = new AMFStringValue(); - caption->SetStringValue("%[ZoneTable_1604_DisplayDescription]"); - ntArgs->InsertValue("caption", caption); - - AMFStringValue* identifier = new AMFStringValue(); - identifier->SetStringValue("zoneID_1604"); - ntArgs->InsertValue("identifier", identifier); - - AMFStringValue* tooltipText = new AMFStringValue(); - tooltipText->SetStringValue("%[ZoneTable_1604_summary]"); - ntArgs->InsertValue("tooltipText", tooltipText); - - choiceOptions->PushBackValue(ntArgs); - } - - args.InsertValue("options", choiceOptions); -} - -void SbLupTeleport::OnUse(Entity* self, Entity* user) -{ - auto* player = user; - - //if (CheckChoice(self, player)) - { - GameMessages::SendUIMessageServerToSingleClient(player, player->GetSystemAddress(), "QueueChoiceBox", &args); - } - /*else - { - BaseOnUse(self, player); - }*/ -} - -void SbLupTeleport::OnMessageBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData) -{ - BaseOnMessageBoxResponse(self, sender, button, identifier, userData); -} - -void SbLupTeleport::OnChoiceBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& buttonIdentifier, const std::u16string& identifier) -{ - BaseChoiceBoxRespond(self, sender, button, buttonIdentifier, identifier); -} - -void SbLupTeleport::OnTimerDone(Entity* self, std::string timerName) -{ - BaseOnTimerDone(self, timerName); -} - -void SbLupTeleport::OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1, int32_t param2, int32_t param3) -{ - BaseOnFireEventServerSide(self, sender, args, param1, param2, param3); -} diff --git a/dScripts/SbLupTeleport.h b/dScripts/SbLupTeleport.h deleted file mode 100644 index f6c868d4..00000000 --- a/dScripts/SbLupTeleport.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once -#include "CppScripts.h" -#include "ChooseYourDestinationNsToNt.h" -#include "BaseConsoleTeleportServer.h" -#include "AMFFormat.h" - -class SbLupTeleport : public CppScripts::Script, ChooseYourDestinationNsToNt, BaseConsoleTeleportServer -{ -public: - void OnStartup(Entity* self) override; - void OnUse(Entity* self, Entity* user) override; - void OnMessageBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData) override; - void OnChoiceBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& buttonIdentifier, const std::u16string& identifier) override; - void OnTimerDone(Entity* self, std::string timerName) override; - void OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1, int32_t param2, int32_t param3) override; - -private: - int32_t m_ChoiceZoneID = 1600; - std::string m_SpawnPoint = "NS_LW"; - std::u16string m_TeleportAnim = u"lup-teleport"; - std::u16string m_TeleportString = u"UI_TRAVEL_TO_LUP_STATION"; - AMFArrayValue args = {}; -}; From aa212ae6d890be30a8aa796abed604ce557ad0e2 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Tue, 3 May 2022 22:38:49 -0500 Subject: [PATCH 233/251] Add precondition check --- dGame/dComponents/PetComponent.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dGame/dComponents/PetComponent.cpp b/dGame/dComponents/PetComponent.cpp index 97c7e95b..39d7eb60 100644 --- a/dGame/dComponents/PetComponent.cpp +++ b/dGame/dComponents/PetComponent.cpp @@ -75,6 +75,12 @@ PetComponent::PetComponent(Entity* parent, uint32_t componentId) : Component(par m_MovementAI = nullptr; m_TresureTime = 0; m_Preconditions = nullptr; + + std::string checkPreconditions = GeneralUtils::UTF16ToWTF8(parent->GetVar(u"CheckPrecondition")); + + if (!checkPreconditions.empty()) { + SetPreconditions(checkPreconditions); + } } void PetComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) From e81acb4c67765ba5c0cf48e4c3da85441cec17dc Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Wed, 4 May 2022 07:50:05 -0500 Subject: [PATCH 234/251] Client handles rocket being unequiped when closing the dialog and when launching --- dGame/dComponents/RocketLaunchLupComponent.cpp | 16 +++++----------- dGame/dComponents/RocketLaunchLupComponent.h | 2 -- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/dGame/dComponents/RocketLaunchLupComponent.cpp b/dGame/dComponents/RocketLaunchLupComponent.cpp index 5e5db538..7864e0e8 100644 --- a/dGame/dComponents/RocketLaunchLupComponent.cpp +++ b/dGame/dComponents/RocketLaunchLupComponent.cpp @@ -18,11 +18,7 @@ RocketLaunchLupComponent::RocketLaunchLupComponent(Entity* parent) : Component(p results.finalize(); } -RocketLaunchLupComponent::~RocketLaunchLupComponent() { - if (!m_rocket) return; - // when we exit the ui we need to unequip the rocket - m_rocket->UnEquip(); -} +RocketLaunchLupComponent::~RocketLaunchLupComponent() {} void RocketLaunchLupComponent::OnUse(Entity* originator) { // the LUP world menu is just the property menu, the client knows how to handle it @@ -34,16 +30,14 @@ void RocketLaunchLupComponent::OnUse(Entity* originator) { auto* characterComponent = originator->GetComponent(); if (!inventoryComponent || !characterComponent) return; + Item* rocket = nullptr; + rocket = inventoryComponent->FindItemById(characterComponent->GetLastRocketItemID()); + if (!rocket) return; - m_rocket = inventoryComponent->FindItemById(characterComponent->GetLastRocketItemID()); - if (!m_rocket) return; - - m_rocket->Equip(true); + rocket->Equip(true); } void RocketLaunchLupComponent::OnSelectWorld(Entity* originator, uint32_t index, const SystemAddress& sysAddr) { - if (m_rocket) m_rocket->UnEquip(); - // Add one to index because the actual LUP worlds start at index 1. index++; diff --git a/dGame/dComponents/RocketLaunchLupComponent.h b/dGame/dComponents/RocketLaunchLupComponent.h index 621a80cf..8b21735a 100644 --- a/dGame/dComponents/RocketLaunchLupComponent.h +++ b/dGame/dComponents/RocketLaunchLupComponent.h @@ -3,7 +3,6 @@ #include "Entity.h" #include "GameMessages.h" #include "Component.h" -#include "Item.h" /** * Component that handles the LUP/WBL rocket launchpad that can be interacted with to travel to WBL worlds. @@ -21,5 +20,4 @@ public: void OnSelectWorld(Entity* originator, uint32_t index, const SystemAddress& sysAddr); private: std::vector m_LUPWorlds {}; - Item* m_rocket = nullptr; }; From ad5c679d2d9b1120f52332e90684df954cd90b13 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Wed, 4 May 2022 18:24:28 -0500 Subject: [PATCH 235/251] Styling edits --- dGame/dComponents/RocketLaunchLupComponent.cpp | 4 ++-- dGame/dComponents/RocketLaunchLupComponent.h | 13 +++++++++++++ dGame/dGameMessages/GameMessages.cpp | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/dGame/dComponents/RocketLaunchLupComponent.cpp b/dGame/dComponents/RocketLaunchLupComponent.cpp index 7864e0e8..c822e4b4 100644 --- a/dGame/dComponents/RocketLaunchLupComponent.cpp +++ b/dGame/dComponents/RocketLaunchLupComponent.cpp @@ -30,8 +30,8 @@ void RocketLaunchLupComponent::OnUse(Entity* originator) { auto* characterComponent = originator->GetComponent(); if (!inventoryComponent || !characterComponent) return; - Item* rocket = nullptr; - rocket = inventoryComponent->FindItemById(characterComponent->GetLastRocketItemID()); + + Item* rocket = inventoryComponent->FindItemById(characterComponent->GetLastRocketItemID()); if (!rocket) return; rocket->Equip(true); diff --git a/dGame/dComponents/RocketLaunchLupComponent.h b/dGame/dComponents/RocketLaunchLupComponent.h index 8b21735a..37a4fb24 100644 --- a/dGame/dComponents/RocketLaunchLupComponent.h +++ b/dGame/dComponents/RocketLaunchLupComponent.h @@ -15,9 +15,22 @@ public: RocketLaunchLupComponent(Entity* parent); ~RocketLaunchLupComponent() override; + /** + * Handles an OnUse event from some entity, preparing it for launch to some other world + * Builds m_LUPWorlds + * @param originator the entity that triggered the event + */ void OnUse(Entity* originator) override; + /** + * Handles an OnUse event from some entity, preparing it for launch to some other world + * + * @param originator the entity that triggered the event + * @param index index of the world that was selected + * @param sysAddr the address to send gamemessage responses to + */ void OnSelectWorld(Entity* originator, uint32_t index, const SystemAddress& sysAddr); private: + // vector of the LUP World Zone IDs, built from CDServer's LUPZoneIDs table std::vector m_LUPWorlds {}; }; diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 7cb8ae8f..f35a0d5b 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -2733,7 +2733,7 @@ void GameMessages::HandleEnterProperty(RakNet::BitStream* inStream, Entity* enti } auto rocketLaunchLupComponent = entity->GetComponent(); - if (rocketLaunchLupComponent) { + if (rocketLaunchLupComponent != nullptr) { rocketLaunchLupComponent->OnSelectWorld(player, index, sysAddr); } } From b11b51664198bf2a1519670e161af8d464098c2f Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Wed, 4 May 2022 19:26:56 -0500 Subject: [PATCH 236/251] fix Java doc comments removed unused param --- dGame/dComponents/RocketLaunchLupComponent.cpp | 2 +- dGame/dComponents/RocketLaunchLupComponent.h | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/dGame/dComponents/RocketLaunchLupComponent.cpp b/dGame/dComponents/RocketLaunchLupComponent.cpp index c822e4b4..a2caa0bb 100644 --- a/dGame/dComponents/RocketLaunchLupComponent.cpp +++ b/dGame/dComponents/RocketLaunchLupComponent.cpp @@ -37,7 +37,7 @@ void RocketLaunchLupComponent::OnUse(Entity* originator) { rocket->Equip(true); } -void RocketLaunchLupComponent::OnSelectWorld(Entity* originator, uint32_t index, const SystemAddress& sysAddr) { +void RocketLaunchLupComponent::OnSelectWorld(Entity* originator, uint32_t index) { // Add one to index because the actual LUP worlds start at index 1. index++; diff --git a/dGame/dComponents/RocketLaunchLupComponent.h b/dGame/dComponents/RocketLaunchLupComponent.h index 37a4fb24..ce915d70 100644 --- a/dGame/dComponents/RocketLaunchLupComponent.h +++ b/dGame/dComponents/RocketLaunchLupComponent.h @@ -12,25 +12,28 @@ class RocketLaunchLupComponent : public Component { public: static const uint32_t ComponentType = eReplicaComponentType::COMPONENT_TYPE_ROCKET_LAUNCH_LUP; + /** + * Constructor for this component, builds the m_LUPWorlds vector + * @param parent parent that contains this component + */ RocketLaunchLupComponent(Entity* parent); ~RocketLaunchLupComponent() override; /** * Handles an OnUse event from some entity, preparing it for launch to some other world - * Builds m_LUPWorlds * @param originator the entity that triggered the event */ void OnUse(Entity* originator) override; /** * Handles an OnUse event from some entity, preparing it for launch to some other world - * * @param originator the entity that triggered the event * @param index index of the world that was selected - * @param sysAddr the address to send gamemessage responses to */ - void OnSelectWorld(Entity* originator, uint32_t index, const SystemAddress& sysAddr); + void OnSelectWorld(Entity* originator, uint32_t index); private: - // vector of the LUP World Zone IDs, built from CDServer's LUPZoneIDs table + /** + * vector of the LUP World Zone IDs, built from CDServer's LUPZoneIDs table + */ std::vector m_LUPWorlds {}; }; From 06a1949eaa786d5423adf95fb1c9310d95a753a9 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Wed, 4 May 2022 19:31:56 -0500 Subject: [PATCH 237/251] remove sysaddr from call in Game Messages --- dGame/dGameMessages/GameMessages.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index f35a0d5b..4ab67e09 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -2734,7 +2734,7 @@ void GameMessages::HandleEnterProperty(RakNet::BitStream* inStream, Entity* enti auto rocketLaunchLupComponent = entity->GetComponent(); if (rocketLaunchLupComponent != nullptr) { - rocketLaunchLupComponent->OnSelectWorld(player, index, sysAddr); + rocketLaunchLupComponent->OnSelectWorld(player, index); } } From ca042bd41539c6838185fbd72901c938d6641dc3 Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Fri, 6 May 2022 04:01:34 -0700 Subject: [PATCH 238/251] bump patch version - Quickbuilds jump on completion - Fong now plays darkitect cutscene on a mission completion - Nexus Tower panels now play the repair animation - Vendors can now refresh - Loot magnet abilities now work - Spinjitzu Initiate now works - Achievement items now get moved to the players inventory as they did in live, by popping up from the achievement box - pop up when you get a new life container now shows up as it did in live - Parrot in Nexus Tower is no longer an oar - Fixed an item underflow bug - Vaults for Items and Models now are the same size and start out at the correct size - The buy back inventory for vendors now allows you to scroll (only after backing out of the menu first for some reason) - Untamed pets no longer cause client hitches in Nimbus Station and Forbidden Valley - When shutting down, the server now shuts down in 1 second instead of 75 - Plunger gun is no longer a main hand item - Skills for proxy items no longer require a reload to be used - Resolved some MacOS compilation warnings - Quickbuilds now play a celebration on completion - Bug reports are more specific - Property viewer and plaques now work as they did in live and display all the correct information - Properties now also save more often instead of every 10 minutes - Avant Gardens Survival buff station now works - Exploding dummy for Nexus Tower combat training now works and allows progression - Racing missions for smashables now work - Apes now act as they did in live - Dragons on Crux Prime now spawn the quick build for insta smashes - Civilian players can no longer use /playanim - Proxy items no longer grant extra stats - Shooting gallery daily missions now work - Operators can now spawn race cars in non-racing worlds - Level rewards now show their achievement as they did in live We really need to do this monthly so the notes arent this long lol --- CMakeVariables.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeVariables.txt b/CMakeVariables.txt index 99742a07..b50b4446 100644 --- a/CMakeVariables.txt +++ b/CMakeVariables.txt @@ -1,6 +1,6 @@ PROJECT_VERSION_MAJOR=1 PROJECT_VERSION_MINOR=0 -PROJECT_VERSION_PATCH=1 +PROJECT_VERSION_PATCH=2 # LICENSE LICENSE=AGPL-3.0 # The network version. From ec207838d431ed10a1b71d9cbf43a1b59835aaa5 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Sun, 8 May 2022 19:57:36 -0500 Subject: [PATCH 239/251] Proper Rocket Holding Sanity checks on Prop and LUP launchpads to not open if no valid rocket Add serialization for sending item configs so that rockets show for other players --- dGame/dComponents/CharacterComponent.cpp | 51 +++++++++ dGame/dComponents/CharacterComponent.h | 21 ++++ dGame/dComponents/InventoryComponent.cpp | 29 ++++- .../dComponents/PropertyEntranceComponent.cpp | 22 ++-- .../dComponents/RocketLaunchLupComponent.cpp | 19 +--- .../RocketLaunchpadControlComponent.cpp | 103 ++++-------------- .../RocketLaunchpadControlComponent.h | 10 +- dGame/dGameMessages/GameMessages.cpp | 12 +- dGame/dInventory/EquippedItem.h | 8 +- dWorldServer/WorldServer.cpp | 13 ++- 10 files changed, 156 insertions(+), 132 deletions(-) diff --git a/dGame/dComponents/CharacterComponent.cpp b/dGame/dComponents/CharacterComponent.cpp index 815a3d59..f7941af8 100644 --- a/dGame/dComponents/CharacterComponent.cpp +++ b/dGame/dComponents/CharacterComponent.cpp @@ -13,6 +13,7 @@ #include "PossessorComponent.h" #include "VehiclePhysicsComponent.h" #include "GameMessages.h" +#include "Item.h" CharacterComponent::CharacterComponent(Entity* parent, Character* character) : Component(parent) { m_Character = character; @@ -448,6 +449,56 @@ void CharacterComponent::SetLastRocketConfig(std::u16string config) { m_LastRocketConfig = config; } +Item* CharacterComponent::GetRocket(Entity* player) { + Item* rocket = nullptr; + + auto* inventoryComponent = player->GetComponent(); + + if (!inventoryComponent) return rocket; + + // Select the rocket + if (!rocket){ + rocket = inventoryComponent->FindItemById(GetLastRocketItemID()); + } + + if (!rocket) { + rocket = inventoryComponent->FindItemByLot(6416); + } + + if (!rocket) { + Game::logger->Log("CharacterComponent", "Unable to find rocket to equip!\n"); + return rocket; + } + return rocket; +} + +Item* CharacterComponent::RocketEquip(Entity* player) { + Item* rocket = GetRocket(player); + if (!rocket) return rocket; + + // build and define the rocket config + for (LDFBaseData* data : rocket->GetConfig()) { + if (data->GetKey() == u"assemblyPartLOTs") { + std::string newRocketStr = data->GetValueAsString() + ";"; + GeneralUtils::ReplaceInString(newRocketStr, "+", ";"); + SetLastRocketConfig(GeneralUtils::ASCIIToUTF16(newRocketStr)); + } + } + + // Store the last used rocket item's ID + SetLastRocketItemID(rocket->GetId()); + // carry the rocket + rocket->Equip(true); + return rocket; +} + +void CharacterComponent::RocketUnEquip(Entity* player) { + Item* rocket = GetRocket(player); + if (!rocket) return; + // We don't want to carry it anymore + rocket->UnEquip(); +} + void CharacterComponent::TrackMissionCompletion(bool isAchievement) { UpdatePlayerStatistic(MissionsCompleted); diff --git a/dGame/dComponents/CharacterComponent.h b/dGame/dComponents/CharacterComponent.h index 04245bf9..99c8a098 100644 --- a/dGame/dComponents/CharacterComponent.h +++ b/dGame/dComponents/CharacterComponent.h @@ -5,6 +5,7 @@ #include "RakNetTypes.h" #include "Character.h" #include "Component.h" +#include "Item.h" #include #include "CDMissionsTable.h" #include "tinyxml2.h" @@ -74,6 +75,26 @@ public: */ void SetLastRocketConfig(std::u16string config); + /** + * Find a player's rocket + * @param player the entity that triggered the event + * @return rocket + */ + Item* GetRocket(Entity* player); + + /** + * Equip a player's rocket + * @param player the entity that triggered the event + * @return rocket + */ + Item* RocketEquip(Entity* player); + + /** + * Find a player's rocket and unequip it + * @param player the entity that triggered the event + */ + void RocketUnEquip(Entity* player); + /** * Gets the current level of the entity * @return the current level of the entity diff --git a/dGame/dComponents/InventoryComponent.cpp b/dGame/dComponents/InventoryComponent.cpp index d2292168..7235d2db 100644 --- a/dGame/dComponents/InventoryComponent.cpp +++ b/dGame/dComponents/InventoryComponent.cpp @@ -1,4 +1,4 @@ -#include "InventoryComponent.h" +#include "InventoryComponent.h" #include @@ -794,10 +794,29 @@ void InventoryComponent::Serialize(RakNet::BitStream* outBitStream, const bool b outBitStream->Write(item.slot != 0); if (item.slot != 0) outBitStream->Write(item.slot); - + outBitStream->Write0(); - - outBitStream->Write0(); //TODO: This is supposed to be true and write the assemblyPartLOTs when they're present. + + bool flag = !item.config.empty(); + outBitStream->Write(flag); + if (flag) { + RakNet::BitStream ldfStream; + ldfStream.Write(item.config.size()); // Key count + for (LDFBaseData* data : item.config) { + if (data->GetKey() == u"assemblyPartLOTs") { + std::string newRocketStr = data->GetValueAsString() + ";"; + GeneralUtils::ReplaceInString(newRocketStr, "+", ";"); + LDFData* ldf_data = new LDFData(u"assemblyPartLOTs", GeneralUtils::ASCIIToUTF16(newRocketStr)); + ldf_data->WriteToPacket(&ldfStream); + delete ldf_data; + } else { + data->WriteToPacket(&ldfStream); + } + } + outBitStream->Write(ldfStream.GetNumberOfBytesUsed() + 1); + outBitStream->Write(0); // Don't compress + outBitStream->Write(ldfStream); + } outBitStream->Write1(); } @@ -1043,7 +1062,7 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) GenerateProxies(item); - UpdateSlot(item->GetInfo().equipLocation, { item->GetId(), item->GetLot(), item->GetCount(), item->GetSlot() }); + UpdateSlot(item->GetInfo().equipLocation, { item->GetId(), item->GetLot(), item->GetCount(), item->GetSlot(), item->GetConfig() }); ApplyBuff(item); diff --git a/dGame/dComponents/PropertyEntranceComponent.cpp b/dGame/dComponents/PropertyEntranceComponent.cpp index 728cdc9e..6779d1c3 100644 --- a/dGame/dComponents/PropertyEntranceComponent.cpp +++ b/dGame/dComponents/PropertyEntranceComponent.cpp @@ -1,4 +1,4 @@ -#include "PropertyEntranceComponent.h" +#include "PropertyEntranceComponent.h" #include @@ -8,6 +8,7 @@ #include "PropertyManagementComponent.h" #include "PropertySelectQueryProperty.h" #include "RocketLaunchpadControlComponent.h" +#include "CharacterComponent.h" #include "UserManager.h" #include "dLogger.h" @@ -22,20 +23,25 @@ PropertyEntranceComponent::PropertyEntranceComponent(uint32_t componentID, Entit this->m_PropertyName = entry.propertyName; } -void PropertyEntranceComponent::OnUse(Entity* entity) -{ - GameMessages::SendPropertyEntranceBegin(m_Parent->GetObjectID(), entity->GetSystemAddress()); +void PropertyEntranceComponent::OnUse(Entity* entity) { + auto* characterComponent = entity->GetComponent(); + if (!characterComponent) return; - AMFArrayValue args; + auto* rocket = entity->GetComponent()->RocketEquip(entity); + if (!rocket) return; + + GameMessages::SendPropertyEntranceBegin(m_Parent->GetObjectID(), entity->GetSystemAddress()); + + AMFArrayValue args; auto* state = new AMFStringValue(); state->SetStringValue("property_menu"); args.InsertValue("state", state); - GameMessages::SendUIMessageServerToSingleClient(entity, entity->GetSystemAddress(), "pushGameState", &args); + GameMessages::SendUIMessageServerToSingleClient(entity, entity->GetSystemAddress(), "pushGameState", &args); - delete state; + delete state; } void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, bool returnToZone, const SystemAddress& sysAddr) @@ -75,7 +81,7 @@ void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, launcher->SetSelectedCloneId(entity->GetObjectID(), cloneId); - launcher->Launch(entity, LWOOBJID_EMPTY, launcher->GetTargetZone(), cloneId); + launcher->Launch(entity, launcher->GetTargetZone(), cloneId); } PropertySelectQueryProperty PropertyEntranceComponent::SetPropertyValues(PropertySelectQueryProperty property, LWOCLONEID cloneId, std::string ownerName, std::string propertyName, std::string propertyDescription, float reputation, bool isBFF, bool isFriend, bool isModeratorApproved, bool isAlt, bool isOwned, uint32_t privacyOption, uint32_t timeLastUpdated, float performanceCost) { diff --git a/dGame/dComponents/RocketLaunchLupComponent.cpp b/dGame/dComponents/RocketLaunchLupComponent.cpp index a2caa0bb..fa2a5b16 100644 --- a/dGame/dComponents/RocketLaunchLupComponent.cpp +++ b/dGame/dComponents/RocketLaunchLupComponent.cpp @@ -1,8 +1,8 @@ #include "RocketLaunchLupComponent.h" #include "CDClientDatabase.h" #include "RocketLaunchpadControlComponent.h" +#include "InventoryComponent.h" #include "CharacterComponent.h" -#include "Item.h" RocketLaunchLupComponent::RocketLaunchLupComponent(Entity* parent) : Component(parent) { m_Parent = parent; @@ -21,20 +21,11 @@ RocketLaunchLupComponent::RocketLaunchLupComponent(Entity* parent) : Component(p RocketLaunchLupComponent::~RocketLaunchLupComponent() {} void RocketLaunchLupComponent::OnUse(Entity* originator) { - // the LUP world menu is just the property menu, the client knows how to handle it - GameMessages::SendPropertyEntranceBegin(m_Parent->GetObjectID(), m_Parent->GetSystemAddress()); - - // get the rocket to "equip" it so we are holding it - // taken from the RocketLaunchControlComponent - auto* inventoryComponent = originator->GetComponent(); - auto* characterComponent = originator->GetComponent(); - - if (!inventoryComponent || !characterComponent) return; - - Item* rocket = inventoryComponent->FindItemById(characterComponent->GetLastRocketItemID()); + auto* rocket = originator->GetComponent()->RocketEquip(originator); if (!rocket) return; - rocket->Equip(true); + // the LUP world menu is just the property menu, the client knows how to handle it + GameMessages::SendPropertyEntranceBegin(m_Parent->GetObjectID(), m_Parent->GetSystemAddress()); } void RocketLaunchLupComponent::OnSelectWorld(Entity* originator, uint32_t index) { @@ -45,5 +36,5 @@ void RocketLaunchLupComponent::OnSelectWorld(Entity* originator, uint32_t index) if (!rocketLaunchpadControlComponent) return; - rocketLaunchpadControlComponent->Launch(originator, LWOOBJID_EMPTY, m_LUPWorlds[index], 0); + rocketLaunchpadControlComponent->Launch(originator, m_LUPWorlds[index], 0); } diff --git a/dGame/dComponents/RocketLaunchpadControlComponent.cpp b/dGame/dComponents/RocketLaunchpadControlComponent.cpp index 049a44b6..8585815f 100644 --- a/dGame/dComponents/RocketLaunchpadControlComponent.cpp +++ b/dGame/dComponents/RocketLaunchpadControlComponent.cpp @@ -13,6 +13,7 @@ #include "ChatPackets.h" #include "MissionComponent.h" #include "PropertyEntranceComponent.h" +#include "RocketLaunchLupComponent.h" #include "dServer.h" #include "dMessageIdentifiers.h" #include "PacketUtils.h" @@ -40,19 +41,7 @@ RocketLaunchpadControlComponent::~RocketLaunchpadControlComponent() { delete m_AltPrecondition; } -void RocketLaunchpadControlComponent::RocketEquip(Entity* entity, LWOOBJID rocketID) { - if (m_PlayersInRadius.find(entity->GetObjectID()) != m_PlayersInRadius.end()) { - Launch(entity, rocketID); - - //Go ahead and save the player - //This causes a double-save, but it should prevent players from not being saved - //before the next world server starts loading their data. - if (entity->GetCharacter()) - entity->GetCharacter()->SaveXMLToDatabase(); - } -} - -void RocketLaunchpadControlComponent::Launch(Entity* originator, LWOOBJID optionalRocketID, LWOMAPID mapId, LWOCLONEID cloneId) { +void RocketLaunchpadControlComponent::Launch(Entity* originator, LWOMAPID mapId, LWOCLONEID cloneId) { auto zone = mapId == LWOMAPID_INVALID ? m_TargetZone : mapId; if (zone == 0) @@ -60,53 +49,22 @@ void RocketLaunchpadControlComponent::Launch(Entity* originator, LWOOBJID option return; } - TellMasterToPrepZone(zone); - // This also gets triggered by a proximity monitor + item equip, I will set that up when havok is ready - auto* inventoryComponent = originator->GetComponent(); auto* characterComponent = originator->GetComponent(); - auto* character = originator->GetCharacter(); - if (inventoryComponent == nullptr || characterComponent == nullptr || character == nullptr) { + if (!characterComponent || !character) return; + + auto* rocket = characterComponent->GetRocket(originator); + if (!rocket) { + Game::logger->Log("RocketLaunchpadControlComponent", "Unable to find rocket!\n"); return; } - // Select the rocket - - Item* rocket = nullptr; - - if (optionalRocketID != LWOOBJID_EMPTY) - { - rocket = inventoryComponent->FindItemById(optionalRocketID); - } - - if (rocket == nullptr) - { - rocket = inventoryComponent->FindItemById(characterComponent->GetLastRocketItemID()); - } - - if (rocket == nullptr) - { - rocket = inventoryComponent->FindItemByLot(6416); - } - - if (rocket == nullptr) - { - Game::logger->Log("RocketLaunchpadControlComponent", "Unable to find rocket (%llu)!\n", optionalRocketID); - - return; - } - - if (rocket->GetConfig().empty()) // Sanity check - { - rocket->SetCount(0, false, false); - - return; - } + // we have the ability to launch, so now we prep the zone + TellMasterToPrepZone(zone); // Achievement unlocked: "All zones unlocked" - if (!m_AltLandingScene.empty() && m_AltPrecondition->Check(originator)) { character->SetTargetScene(m_AltLandingScene); } @@ -114,27 +72,6 @@ void RocketLaunchpadControlComponent::Launch(Entity* originator, LWOOBJID option character->SetTargetScene(m_TargetScene); } - if (characterComponent) { - for (LDFBaseData* data : rocket->GetConfig()) { - if (data->GetKey() == u"assemblyPartLOTs") { - std::string newRocketStr; - for (char character : data->GetValueAsString()) { - if (character == '+') { - newRocketStr.push_back(';'); - } - else { - newRocketStr.push_back(character); - } - } - newRocketStr.push_back(';'); - characterComponent->SetLastRocketConfig(GeneralUtils::ASCIIToUTF16(newRocketStr)); - } - } - } - - // Store the last used rocket item's ID - characterComponent->SetLastRocketItemID(rocket->GetId()); - characterComponent->UpdatePlayerStatistic(RocketsUsed); character->SaveXMLToDatabase(); @@ -143,23 +80,31 @@ void RocketLaunchpadControlComponent::Launch(Entity* originator, LWOOBJID option GameMessages::SendFireEventClientSide(m_Parent->GetObjectID(), originator->GetSystemAddress(), u"RocketEquipped", rocket->GetId(), cloneId, -1, originator->GetObjectID()); - rocket->Equip(true); - GameMessages::SendChangeObjectWorldState(rocket->GetId(), WORLDSTATE_ATTACHED, UNASSIGNED_SYSTEM_ADDRESS); EntityManager::Instance()->SerializeEntity(originator); } void RocketLaunchpadControlComponent::OnUse(Entity* originator) { + // If we are have the property or the LUP component, we don't want to immediately launch + // instead we let their OnUse handlers do their things + // which components of an Object have their OnUse called when using them + // so we don't need to call it here auto* propertyEntrance = m_Parent->GetComponent(); - - if (propertyEntrance != nullptr) - { - propertyEntrance->OnUse(originator); - + if (propertyEntrance) { return; } + auto* rocketLaunchLUP = m_Parent->GetComponent(); + if (rocketLaunchLUP) { + return; + } + + // No rocket no launch + auto* rocket = originator->GetComponent()->RocketEquip(originator); + if (!rocket) { + return; + } Launch(originator); } diff --git a/dGame/dComponents/RocketLaunchpadControlComponent.h b/dGame/dComponents/RocketLaunchpadControlComponent.h index c9ee0691..7fdf4b32 100644 --- a/dGame/dComponents/RocketLaunchpadControlComponent.h +++ b/dGame/dComponents/RocketLaunchpadControlComponent.h @@ -22,21 +22,13 @@ public: RocketLaunchpadControlComponent(Entity* parent, int rocketId); ~RocketLaunchpadControlComponent() override; - /** - * Launches the passed entity using the passed rocket and saves their data - * @param entity the entity to launch - * @param rocketID the ID of the rocket to use - */ - void RocketEquip(Entity* entity, LWOOBJID rocketID); - /** * Launches some entity to another world * @param originator the entity to launch - * @param optionalRocketID the ID of the rocket to launch * @param mapId the world to go to * @param cloneId the clone ID (for properties) */ - void Launch(Entity* originator, LWOOBJID optionalRocketID = LWOOBJID_EMPTY, LWOMAPID mapId = LWOMAPID_INVALID, LWOCLONEID cloneId = LWOCLONEID_INVALID); + void Launch(Entity* originator, LWOMAPID mapId = LWOMAPID_INVALID, LWOCLONEID cloneId = LWOCLONEID_INVALID); /** * Handles an OnUse event from some entity, preparing it for launch to some other world diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 4ab67e09..a813f6d3 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -5329,21 +5329,11 @@ void GameMessages::HandleEquipItem(RakNet::BitStream* inStream, Entity* entity) Item* item = inv->FindItemById(objectID); if (!item) return; - /*if (item->GetLot() == 6416) { // if it's a rocket - std::vector rocketPads = EntityManager::Instance()->GetEntitiesByComponent(COMPONENT_TYPE_ROCKET_LAUNCH); - for (Entity* rocketPad : rocketPads) { - RocketLaunchpadControlComponent* rocketComp = static_cast(rocketPad->GetComponent(COMPONENT_TYPE_ROCKET_LAUNCH)); - if (rocketComp) { - rocketComp->RocketEquip(entity, objectID); - } - } - } - else*/ { + item->Equip(); EntityManager::Instance()->SerializeEntity(entity); } -} void GameMessages::HandleUnequipItem(RakNet::BitStream* inStream, Entity* entity) { bool immediate; diff --git a/dGame/dInventory/EquippedItem.h b/dGame/dInventory/EquippedItem.h index 0d1d191f..cf5ba253 100644 --- a/dGame/dInventory/EquippedItem.h +++ b/dGame/dInventory/EquippedItem.h @@ -1,6 +1,7 @@ -#pragma once +#pragma once #include "dCommonVars.h" +#include "LDFFormat.h" /** * An item that's equipped, generally as a smaller return type than the regular Item class @@ -26,4 +27,9 @@ struct EquippedItem * The slot this item is stored in */ uint32_t slot = 0; + + /** + * The configuration of the item with any extra data + */ + std::vector config = {}; }; diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index 9d0c84cc..eb829f29 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -969,13 +969,16 @@ void HandlePacket(Packet* packet) { { GameMessages::SendPlayerReachedRespawnCheckpoint(player, respawnPoint, NiQuaternion::IDENTITY); } - - EntityManager::Instance()->ConstructAllEntities(packet->systemAddress); - player->GetComponent()->SetLastRocketConfig(u""); - + EntityManager::Instance()->ConstructAllEntities(packet->systemAddress); + + auto* characterComponent = player->GetComponent(); + if (characterComponent) { + player->GetComponent()->RocketUnEquip(player); + } + c->SetRetroactiveFlags(); - + player->RetroactiveVaultSize(); player->GetCharacter()->SetTargetScene(""); From 4c7034648b9bf7c7a68ed285cebd7ae1f10d88d4 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Sun, 8 May 2022 22:07:07 -0500 Subject: [PATCH 240/251] Exclude space blizzard from Zone ghosting --- dGame/EntityManager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dGame/EntityManager.cpp b/dGame/EntityManager.cpp index 8fb75fb2..aacb2bc8 100644 --- a/dGame/EntityManager.cpp +++ b/dGame/EntityManager.cpp @@ -24,12 +24,13 @@ EntityManager* EntityManager::m_Address = nullptr; std::vector EntityManager::m_GhostingExcludedZones = { // Small zones 1000, - + // Racing zones 1203, + 1261, 1303, 1403, - + // Property zones 1150, 1151, From d7eb8783a8275b347337c1db83f261a676c76fea Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Mon, 9 May 2022 08:43:31 -0500 Subject: [PATCH 241/251] replace the survey link with the repo link (not that anything can load in the in-game browser anyway) --- dWorldServer/WorldServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index 9d0c84cc..49e17e7f 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -1089,7 +1089,7 @@ void HandlePacket(Packet* packet) { noBBB: // Tell the client it's done loading: - GameMessages::SendInvalidZoneTransferList(player, packet->systemAddress, u"https://forms.zohopublic.eu/virtualoffice204/form/DLUInGameSurvey/formperma/kpU-IL5v2-Wt41QcB5UFnYjzlLp-j2LEisF8e11PisU", u"", false, false); + GameMessages::SendInvalidZoneTransferList(player, packet->systemAddress, u"https://github.com/DarkflameUniverse/DarkflameServer", u"", false, false); GameMessages::SendServerDoneLoadingAllObjects(player, packet->systemAddress); //Send the player it's mail count: From 875827d6885d58526ae8565f3dbf4dd43b8eaa66 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Mon, 9 May 2022 17:33:43 -0500 Subject: [PATCH 242/251] Set url from world config instead of hardcoding --- dWorldServer/WorldServer.cpp | 72 ++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index 49e17e7f..3fe92046 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -102,7 +102,7 @@ int main(int argc, char** argv) { // Triggers the shutdown sequence at application exit std::atexit(WorldShutdownSequence); - + signal(SIGINT, [](int){ WorldShutdownSequence(); }); signal(SIGTERM, [](int){ WorldShutdownSequence(); }); @@ -125,7 +125,7 @@ int main(int argc, char** argv) { //Create all the objects we need to run our service: Game::logger = SetupLogger(zoneID, instanceID); if (!Game::logger) return 0; - + Game::logger->SetLogToConsole(true); //We want this info to always be logged. Game::logger->Log("WorldServer", "Starting World server...\n"); Game::logger->Log("WorldServer", "Version: %i.%i\n", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR); @@ -151,7 +151,7 @@ int main(int argc, char** argv) { Game::logger->Log("WorldServer", "Error Code: %i\n", e.errorCode()); return -1; } - + CDClientManager::Instance()->Initialize(); //Connect to the MySQL Database @@ -197,7 +197,7 @@ int main(int argc, char** argv) { //Connect to the chat server: int chatPort = 1501; if (config.GetValue("chat_server_port") != "") chatPort = std::atoi(config.GetValue("chat_server_port").c_str()); - + auto chatSock = SocketDescriptor(uint16_t(ourPort + 2), 0); Game::chatServer = RakNetworkFactory::GetRakPeerInterface(); Game::chatServer->Startup(1, 30, &chatSock, 1); @@ -218,7 +218,7 @@ int main(int argc, char** argv) { int framesSinceLastUsersSave = 0; int framesSinceLastSQLPing = 0; int framesSinceLastUser = 0; - + const float maxPacketProcessingTime = 1.5f; //0.015f; const int maxPacketsToProcess = 1024; @@ -249,7 +249,7 @@ int main(int argc, char** argv) { "res/CDClient.fdb", "res/cdclient.fdb", }; - + for (const auto& file : aliases) { fileStream.open(file, std::ios::binary | std::ios::in); if (fileStream.is_open()) { @@ -259,7 +259,7 @@ int main(int argc, char** argv) { const int bufferSize = 1024; MD5* md5 = new MD5(); - + char fileStreamBuffer[1024] = {}; while (!fileStream.eof()) { @@ -274,7 +274,7 @@ int main(int argc, char** argv) { md5->update(nullTerminateBuffer, 1); // null terminate the data md5->finalize(); databaseChecksum = md5->hexdigest(); - + delete md5; Game::logger->Log("WorldServer", "FDB Checksum calculated as: %s\n", databaseChecksum.c_str()); @@ -360,7 +360,7 @@ int main(int argc, char** argv) { //Check for packets here: packet = Game::server->ReceiveFromMaster(); if (packet) { //We can get messages not handle-able by the dServer class, so handle them if we returned anything. - HandlePacket(packet); + HandlePacket(packet); Game::server->DeallocateMasterPacket(packet); } @@ -459,13 +459,13 @@ int main(int argc, char** argv) { t += std::chrono::milliseconds(currentFramerate); std::this_thread::sleep_until(t); - + Metrics::EndMeasurement(MetricVariable::Sleep); if (!ready && Game::server->GetIsConnectedToMaster()) { // Some delay is required here or else we crash the client? - + framesSinceMasterStatus++; if (framesSinceMasterStatus >= 200) @@ -505,7 +505,7 @@ dLogger * SetupLogger(int zoneID, int instanceID) { void HandlePacketChat(Packet* packet) { if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) { Game::logger->Log("WorldServer", "Lost our connection to chat, zone(%i), instance(%i)\n", Game::server->GetZoneID(), Game::server->GetInstanceID()); - + chatConnected = false; } @@ -579,7 +579,7 @@ void HandlePacketChat(Packet* packet) { inStream.Read(playerId); inStream.Read(playerId); inStream.Read(expire); - + auto* entity = EntityManager::Instance()->GetEntity(playerId); if (entity != nullptr) @@ -829,7 +829,7 @@ void HandlePacket(Packet* packet) { } if (packet->data[1] != WORLD) return; - + switch (packet->data[3]) { case MSG_WORLD_CLIENT_VALIDATION: { std::string username = PacketUtils::ReadString(0x08, packet, true); @@ -844,7 +844,7 @@ void HandlePacket(Packet* packet) { uint32_t gmLevel = 0; auto* stmt = Database::CreatePreppedStmt("SELECT gm_level FROM accounts WHERE name=? LIMIT 1;"); stmt->setString(1, username.c_str()); - + auto* res = stmt->executeQuery(); while (res->next()) { gmLevel = res->getInt(1); @@ -860,7 +860,7 @@ void HandlePacket(Packet* packet) { return; } } - + //Request the session info from Master: CBITSTREAM; PacketUtils::WriteHeader(bitStream, MASTER, MSG_MASTER_REQUEST_SESSION_KEY); @@ -872,7 +872,7 @@ void HandlePacket(Packet* packet) { info.sysAddr = SystemAddress(packet->systemAddress); info.hash = sessionKey; m_PendingUsers.insert(std::make_pair(username, info)); - + break; } @@ -885,7 +885,7 @@ void HandlePacket(Packet* packet) { } //This loops prevents users who aren't authenticated to double-request the char list, which - //would make the login screen freeze sometimes. + //would make the login screen freeze sometimes. if (m_PendingUsers.size() > 0) { for (auto it : m_PendingUsers) { if (it.second.sysAddr == packet->systemAddress) { @@ -900,18 +900,18 @@ void HandlePacket(Packet* packet) { case MSG_WORLD_CLIENT_GAME_MSG: { RakNet::BitStream bitStream(packet->data, packet->length, false); - + uint64_t header; LWOOBJID objectID; uint16_t messageID; - + bitStream.Read(header); bitStream.Read(objectID); bitStream.Read(messageID); - + RakNet::BitStream dataStream; bitStream.Read(dataStream, bitStream.GetNumberOfUnreadBits()); - + GameMessageHandler::HandleMessage(&dataStream, packet->systemAddress, objectID, GAME_MSG(messageID)); break; } @@ -924,7 +924,7 @@ void HandlePacket(Packet* packet) { case MSG_WORLD_CLIENT_LOGIN_REQUEST: { RakNet::BitStream inStream(packet->data, packet->length, false); uint64_t header = inStream.Read(header); - + LWOOBJID playerID = 0; inStream.Read(playerID); playerID = GeneralUtils::ClearBit(playerID, OBJECT_BIT_CHARACTER); @@ -939,7 +939,7 @@ void HandlePacket(Packet* packet) { UserManager::Instance()->RequestCharacterList(packet->systemAddress); break; } - + case MSG_WORLD_CLIENT_CHARACTER_RENAME_REQUEST: { UserManager::Instance()->RenameCharacter(packet->systemAddress, packet); break; @@ -950,10 +950,10 @@ void HandlePacket(Packet* packet) { User* user = UserManager::Instance()->GetUser(packet->systemAddress); if (user) { Character* c = user->GetLastUsedChar(); - if (c != nullptr) { + if (c != nullptr) { std::u16string username = GeneralUtils::ASCIIToUTF16(c->GetName()); Game::server->GetReplicaManager()->AddParticipant(packet->systemAddress); - + EntityInfo info {}; info.lot = 1; Entity* player = EntityManager::Instance()->CreateEntity(info, UserManager::Instance()->GetUser(packet->systemAddress)); @@ -962,20 +962,20 @@ void HandlePacket(Packet* packet) { WorldPackets::SendServerState(packet->systemAddress); const auto respawnPoint = player->GetCharacter()->GetRespawnPoint(dZoneManager::Instance()->GetZone()->GetWorldID()); - + EntityManager::Instance()->ConstructEntity(player, UNASSIGNED_SYSTEM_ADDRESS, true); - + if (respawnPoint != NiPoint3::ZERO) { GameMessages::SendPlayerReachedRespawnCheckpoint(player, respawnPoint, NiQuaternion::IDENTITY); } - + EntityManager::Instance()->ConstructAllEntities(packet->systemAddress); player->GetComponent()->SetLastRocketConfig(u""); - + c->SetRetroactiveFlags(); - + player->RetroactiveVaultSize(); player->GetCharacter()->SetTargetScene(""); @@ -1012,7 +1012,7 @@ void HandlePacket(Packet* packet) { int templateId = result.getIntField(0); result.finalize(); - + auto* propertyLookup = Database::CreatePreppedStmt("SELECT * FROM properties WHERE template_id = ? AND clone_id = ?;"); propertyLookup->setInt(1, templateId); @@ -1037,7 +1037,7 @@ void HandlePacket(Packet* packet) { stmtL->setUInt(1, res->getUInt(1)); auto lxres = stmtL->executeQuery(); - + while (lxres->next()) { auto lxfml = lxres->getBlob(1); @@ -1089,7 +1089,7 @@ void HandlePacket(Packet* packet) { noBBB: // Tell the client it's done loading: - GameMessages::SendInvalidZoneTransferList(player, packet->systemAddress, u"https://github.com/DarkflameUniverse/DarkflameServer", u"", false, false); + GameMessages::SendInvalidZoneTransferList(player, packet->systemAddress, GeneralUtils::ASCIIToUTF16(Game::config->GetValue("source")), u"", false, false); GameMessages::SendServerDoneLoadingAllObjects(player, packet->systemAddress); //Send the player it's mail count: @@ -1109,9 +1109,9 @@ void HandlePacket(Packet* packet) { { bitStream.Write(playerName[i]); } - + //bitStream.Write(playerName); - + auto zone = dZoneManager::Instance()->GetZone()->GetZoneID(); bitStream.Write(zone.GetMapID()); bitStream.Write(zone.GetInstanceID()); From aba349301f3fe3cb50af616ae4d02ef485c5d3c1 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Mon, 9 May 2022 23:21:20 -0500 Subject: [PATCH 243/251] Add AM Teapot server Resolves #224 --- dScripts/AmTeapotServer.cpp | 15 +++++++++++++++ dScripts/AmTeapotServer.h | 10 ++++++++++ dScripts/CppScripts.cpp | 3 +++ 3 files changed, 28 insertions(+) create mode 100644 dScripts/AmTeapotServer.cpp create mode 100644 dScripts/AmTeapotServer.h diff --git a/dScripts/AmTeapotServer.cpp b/dScripts/AmTeapotServer.cpp new file mode 100644 index 00000000..17b95eeb --- /dev/null +++ b/dScripts/AmTeapotServer.cpp @@ -0,0 +1,15 @@ +#include "AmTeapotServer.h" +#include "InventoryComponent.h" +#include "GameMessages.h" + + +void AmTeapotServer::OnUse(Entity* self, Entity* user) { + auto* inventoryComponent = user->GetComponent(); + if (!inventoryComponent) return; + + if (inventoryComponent->GetLotCount(BLUE_FLOWER_LEAVES) >= 10){ + inventoryComponent->RemoveItem(BLUE_FLOWER_LEAVES, 10); + inventoryComponent->AddItem(WU_S_IMAGINATION_TEA, 1); + } + GameMessages::SendTerminateInteraction(user->GetObjectID(), FROM_INTERACTION, self->GetObjectID()); +} diff --git a/dScripts/AmTeapotServer.h b/dScripts/AmTeapotServer.h new file mode 100644 index 00000000..19cb5639 --- /dev/null +++ b/dScripts/AmTeapotServer.h @@ -0,0 +1,10 @@ +#pragma once +#include "CppScripts.h" + +class AmTeapotServer : public CppScripts::Script { + public: + void OnUse(Entity* self, Entity* user) override; + private: + LOT BLUE_FLOWER_LEAVES = 12317; + LOT WU_S_IMAGINATION_TEA = 12109; +}; diff --git a/dScripts/CppScripts.cpp b/dScripts/CppScripts.cpp index 00a253dc..4381823a 100644 --- a/dScripts/CppScripts.cpp +++ b/dScripts/CppScripts.cpp @@ -226,6 +226,7 @@ #include "AmSkullkinTower.h" #include "AmDarklingDragon.h" #include "AmBlueX.h" +#include "AmTeapotServer.h" // NJ Scripts #include "NjGarmadonCelebration.h" @@ -704,6 +705,8 @@ CppScripts::Script* CppScripts::GetScript(Entity* parent, const std::string& scr script = new BaseEnemyApe(); else if (scriptName == "scripts\\02_server\\Map\\AM\\L_BLUE_X.lua") script = new AmBlueX(); + else if (scriptName == "scripts\\02_server\\Map\\AM\\L_TEAPOT_SERVER.lua") + script = new AmTeapotServer(); // Ninjago else if (scriptName == "scripts\\02_server\\Map\\njhub\\L_GARMADON_CELEBRATION_SERVER.lua") From 81af1f382ed34d0f095e8453a3e1fd18a50244e5 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Tue, 17 May 2022 10:18:50 -0500 Subject: [PATCH 244/251] get zones from settings --- .../dComponents/RocketLaunchLupComponent.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/dGame/dComponents/RocketLaunchLupComponent.cpp b/dGame/dComponents/RocketLaunchLupComponent.cpp index fa2a5b16..1c5f71c0 100644 --- a/dGame/dComponents/RocketLaunchLupComponent.cpp +++ b/dGame/dComponents/RocketLaunchLupComponent.cpp @@ -6,16 +6,13 @@ RocketLaunchLupComponent::RocketLaunchLupComponent(Entity* parent) : Component(parent) { m_Parent = parent; - - // get the lup worlds from the cdclient - std::string query = "SELECT * FROM LUPZoneIDs;"; - auto results = CDClientDatabase::ExecuteQuery(query); - while (!results.eof()) { - // fallback to 1600 incase there is an issue - m_LUPWorlds.push_back(results.getIntField(0, 1600)); - results.nextRow(); + std::string zoneString = GeneralUtils::UTF16ToWTF8(m_Parent->GetVar(u"MultiZoneIDs")); + std::stringstream ss(zoneString); + for (int i; ss >> i;) { + m_LUPWorlds.push_back(i); + if (ss.peek() == ';') + ss.ignore(); } - results.finalize(); } RocketLaunchLupComponent::~RocketLaunchLupComponent() {} @@ -29,11 +26,7 @@ void RocketLaunchLupComponent::OnUse(Entity* originator) { } void RocketLaunchLupComponent::OnSelectWorld(Entity* originator, uint32_t index) { - // Add one to index because the actual LUP worlds start at index 1. - index++; - auto* rocketLaunchpadControlComponent = m_Parent->GetComponent(); - if (!rocketLaunchpadControlComponent) return; rocketLaunchpadControlComponent->Launch(originator, m_LUPWorlds[index], 0); From ca55fccb27722eaf50e8572f300846f5c03e7b14 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Tue, 17 May 2022 10:20:36 -0500 Subject: [PATCH 245/251] remove cdclient include --- dGame/dComponents/RocketLaunchLupComponent.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/dGame/dComponents/RocketLaunchLupComponent.cpp b/dGame/dComponents/RocketLaunchLupComponent.cpp index 1c5f71c0..3c326540 100644 --- a/dGame/dComponents/RocketLaunchLupComponent.cpp +++ b/dGame/dComponents/RocketLaunchLupComponent.cpp @@ -1,5 +1,4 @@ #include "RocketLaunchLupComponent.h" -#include "CDClientDatabase.h" #include "RocketLaunchpadControlComponent.h" #include "InventoryComponent.h" #include "CharacterComponent.h" From 729e79eadbff2fd9bb73d0573573526face9c73a Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Tue, 17 May 2022 19:12:43 -0500 Subject: [PATCH 246/251] resolves #556 --- dScripts/ActMine.cpp | 53 +++++++++++++++++++++++++++++++++++++++++ dScripts/ActMine.h | 18 ++++++++++++++ dScripts/CppScripts.cpp | 3 +++ 3 files changed, 74 insertions(+) create mode 100644 dScripts/ActMine.cpp create mode 100644 dScripts/ActMine.h diff --git a/dScripts/ActMine.cpp b/dScripts/ActMine.cpp new file mode 100644 index 00000000..9cc116b1 --- /dev/null +++ b/dScripts/ActMine.cpp @@ -0,0 +1,53 @@ +#include "ActMine.h" +#include "SkillComponent.h" +#include "DestroyableComponent.h" +#include "RebuildComponent.h" + +void ActMine::OnStartup(Entity* self) { + self->SetVar(u"RebuildComplete", false); + self->SetProximityRadius(MINE_RADIUS, "mineRadius"); +} + +void ActMine::OnRebuildNotifyState(Entity* self, eRebuildState state) +{ + if (state == eRebuildState::REBUILD_COMPLETED) { + auto* rebuild = self->GetComponent(); + if (rebuild) { + auto* builder = rebuild->GetBuilder(); + self->SetVar(u"Builder", builder->GetObjectID()); + } + + self->SetVar(u"RebuildComplete", true); + self->SetVar(u"NumWarnings", 0); + self->AddToGroup("reset"); + } + +} + +void ActMine::OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) { + auto* detroyable = self->GetComponent(); + if (!detroyable) return; + if (status == "ENTER" && self->GetVar(u"RebuildComplete") == true && detroyable->IsEnemy(entering)) { + GameMessages::SendPlayFXEffect(self->GetObjectID(), 242, u"orange", "sirenlight_B"); + self->AddTimer("Tick", TICK_TIME); + } +} + +void ActMine::OnTimerDone(Entity* self, std::string timerName) { + if (timerName == "Tick") { + if (self->GetVar(u"NumWarnings") >= MAX_WARNINGS){ + auto* skill = self->GetComponent(); + if (!skill) return; + skill->CalculateBehavior(SKILL_ID, BEHAVIOR_ID, LWOOBJID_EMPTY); + self->AddTimer("BlowedUp", BLOWED_UP_TIME); + } else { + GameMessages::SendPlayFXEffect(self->GetObjectID(), 242, u"orange", "sirenlight_B"); + self->AddTimer("Tick", TICK_TIME); + self->SetVar(u"NumWarnings", self->GetVar(u"NumWarnings") + 1); + } + } + + if (timerName == "BlowedUp") { + self->Kill(self); + } +} \ No newline at end of file diff --git a/dScripts/ActMine.h b/dScripts/ActMine.h new file mode 100644 index 00000000..85efadcc --- /dev/null +++ b/dScripts/ActMine.h @@ -0,0 +1,18 @@ +#pragma once +#include "CppScripts.h" + +class ActMine : public CppScripts::Script { + public: + void OnStartup(Entity* self); + void OnRebuildNotifyState(Entity* self, eRebuildState state) override; + void OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status); + void OnTimerDone(Entity* self, std::string timerName); + private: + int MAX_WARNINGS = 3; + float MINE_RADIUS = 10.0; + float TICK_TIME = 0.25; + float BLOWED_UP_TIME = 0.1; + uint32_t SKILL_ID = 317; + uint32_t BEHAVIOR_ID = 3719; +}; + diff --git a/dScripts/CppScripts.cpp b/dScripts/CppScripts.cpp index 4381823a..9e402a21 100644 --- a/dScripts/CppScripts.cpp +++ b/dScripts/CppScripts.cpp @@ -164,6 +164,7 @@ #include "BaseFootRaceManager.h" #include "PropertyPlatform.h" #include "MailBoxServer.h" +#include "ActMine.h" // Racing Scripts #include "RaceImagineCrateServer.h" @@ -591,6 +592,8 @@ CppScripts::Script* CppScripts::GetScript(Entity* parent, const std::string& scr return new VeBricksampleServer(); else if (scriptName == "scripts\\02_server\\Map\\General\\L_MAIL_BOX_SERVER.lua") script = new MailBoxServer(); + else if (scriptName == "scripts\\ai\\ACT\\L_ACT_MINE.lua") + script = new ActMine(); //Racing: else if (scriptName == "scripts\\ai\\RACING\\OBJECTS\\RACE_IMAGINE_CRATE_SERVER.lua") From 03a5aa4da0935d82dbe1a848f5d3185e647cdd59 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Tue, 17 May 2022 21:27:08 -0500 Subject: [PATCH 247/251] climbable server side settings --- dGame/dComponents/SimplePhysicsComponent.cpp | 21 ++++++++++---- dGame/dComponents/SimplePhysicsComponent.h | 29 ++++++++++++++++++-- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/dGame/dComponents/SimplePhysicsComponent.cpp b/dGame/dComponents/SimplePhysicsComponent.cpp index 8a4cff4e..58bcee18 100644 --- a/dGame/dComponents/SimplePhysicsComponent.cpp +++ b/dGame/dComponents/SimplePhysicsComponent.cpp @@ -17,6 +17,17 @@ SimplePhysicsComponent::SimplePhysicsComponent(uint32_t componentID, Entity* par m_Position = m_Parent->GetDefaultPosition(); m_Rotation = m_Parent->GetDefaultRotation(); m_IsDirty = true; + + std::u16string climbable_type = m_Parent->GetVar(u"climbable"); + if (climbable_type == u"wall") { + SetClimbableType(CLIMBABLE_TYPE_WALL); + } else if (climbable_type == u"ladder") { + SetClimbableType(CLIMBABLE_TYPE_LADDER); + } else if (climbable_type == u"wallstick") { + SetClimbableType(CLIMBABLE_TYPE_WALL_STICK); + } else { + SetClimbableType(CLIMBABLE_TYPE_NOT); + } } SimplePhysicsComponent::~SimplePhysicsComponent() { @@ -24,10 +35,10 @@ SimplePhysicsComponent::~SimplePhysicsComponent() { void SimplePhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { if (bIsInitialUpdate) { - outBitStream->Write0(); // climbable - outBitStream->Write(0); // climbableType + outBitStream->Write(m_ClimbableType > 0); + outBitStream->Write(m_ClimbableType); } - + outBitStream->Write(m_DirtyVelocity || bIsInitialUpdate); if (m_DirtyVelocity || bIsInitialUpdate) { outBitStream->Write(m_Velocity); @@ -46,7 +57,7 @@ void SimplePhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIs { outBitStream->Write0(); } - + outBitStream->Write(m_IsDirty || bIsInitialUpdate); if (m_IsDirty || bIsInitialUpdate) { outBitStream->Write(m_Position.x); @@ -66,7 +77,7 @@ uint32_t SimplePhysicsComponent::GetPhysicsMotionState() const return m_PhysicsMotionState; } -void SimplePhysicsComponent::SetPhysicsMotionState(uint32_t value) +void SimplePhysicsComponent::SetPhysicsMotionState(uint32_t value) { m_PhysicsMotionState = value; } diff --git a/dGame/dComponents/SimplePhysicsComponent.h b/dGame/dComponents/SimplePhysicsComponent.h index 081b056b..bff84522 100644 --- a/dGame/dComponents/SimplePhysicsComponent.h +++ b/dGame/dComponents/SimplePhysicsComponent.h @@ -14,16 +14,24 @@ class Entity; +enum eClimbableType : int32_t { + CLIMBABLE_TYPE_NOT, + CLIMBABLE_TYPE_LADDER, + CLIMBABLE_TYPE_WALL, + CLIMBABLE_TYPE_WALL_STICK +}; + + /** * Component that serializes locations of entities to the client */ class SimplePhysicsComponent : public Component { public: static const uint32_t ComponentType = COMPONENT_TYPE_SIMPLE_PHYSICS; - + SimplePhysicsComponent(uint32_t componentID, Entity* parent); ~SimplePhysicsComponent() override; - + void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); /** @@ -86,6 +94,18 @@ public: */ void SetPhysicsMotionState(uint32_t value); + /** + * Returns the ClimbableType of this entity + * @return the ClimbableType of this entity + */ + const eClimbableType& GetClimabbleType() { return m_ClimbableType; } + + /** + * Sets the ClimbableType of this entity + * @param value the ClimbableType to set + */ + void SetClimbableType(const eClimbableType& value) { m_ClimbableType = value; } + private: /** @@ -122,6 +142,11 @@ private: * The current physics motion state */ uint32_t m_PhysicsMotionState = 0; + + /** + * Whether or not the entity is climbable + */ + eClimbableType m_ClimbableType = CLIMBABLE_TYPE_NOT; }; #endif // SIMPLEPHYSICSCOMPONENT_H From 9169d844e2ba6593204319f236a2a58ec74018fa Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Tue, 17 May 2022 21:38:36 -0500 Subject: [PATCH 248/251] explicit set to 0 --- dGame/dComponents/SimplePhysicsComponent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dGame/dComponents/SimplePhysicsComponent.h b/dGame/dComponents/SimplePhysicsComponent.h index bff84522..6ad4cac6 100644 --- a/dGame/dComponents/SimplePhysicsComponent.h +++ b/dGame/dComponents/SimplePhysicsComponent.h @@ -15,7 +15,7 @@ class Entity; enum eClimbableType : int32_t { - CLIMBABLE_TYPE_NOT, + CLIMBABLE_TYPE_NOT = 0, CLIMBABLE_TYPE_LADDER, CLIMBABLE_TYPE_WALL, CLIMBABLE_TYPE_WALL_STICK From 813aca9d20141783750d8e77f6482379c17722d3 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Wed, 18 May 2022 06:36:21 -0500 Subject: [PATCH 249/251] resolve comments --- dGame/dComponents/SimplePhysicsComponent.cpp | 10 +++++----- dGame/dComponents/SimplePhysicsComponent.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dGame/dComponents/SimplePhysicsComponent.cpp b/dGame/dComponents/SimplePhysicsComponent.cpp index 58bcee18..8a052313 100644 --- a/dGame/dComponents/SimplePhysicsComponent.cpp +++ b/dGame/dComponents/SimplePhysicsComponent.cpp @@ -18,15 +18,15 @@ SimplePhysicsComponent::SimplePhysicsComponent(uint32_t componentID, Entity* par m_Rotation = m_Parent->GetDefaultRotation(); m_IsDirty = true; - std::u16string climbable_type = m_Parent->GetVar(u"climbable"); + const auto& climbable_type = m_Parent->GetVar(u"climbable"); if (climbable_type == u"wall") { - SetClimbableType(CLIMBABLE_TYPE_WALL); + SetClimbableType(eClimbableType::CLIMBABLE_TYPE_WALL); } else if (climbable_type == u"ladder") { - SetClimbableType(CLIMBABLE_TYPE_LADDER); + SetClimbableType(eClimbableType::CLIMBABLE_TYPE_LADDER); } else if (climbable_type == u"wallstick") { - SetClimbableType(CLIMBABLE_TYPE_WALL_STICK); + SetClimbableType(eClimbableType::CLIMBABLE_TYPE_WALL_STICK); } else { - SetClimbableType(CLIMBABLE_TYPE_NOT); + SetClimbableType(eClimbableType::CLIMBABLE_TYPE_NOT); } } diff --git a/dGame/dComponents/SimplePhysicsComponent.h b/dGame/dComponents/SimplePhysicsComponent.h index 6ad4cac6..49e6be5b 100644 --- a/dGame/dComponents/SimplePhysicsComponent.h +++ b/dGame/dComponents/SimplePhysicsComponent.h @@ -14,7 +14,7 @@ class Entity; -enum eClimbableType : int32_t { +enum class eClimbableType : int32_t { CLIMBABLE_TYPE_NOT = 0, CLIMBABLE_TYPE_LADDER, CLIMBABLE_TYPE_WALL, @@ -146,7 +146,7 @@ private: /** * Whether or not the entity is climbable */ - eClimbableType m_ClimbableType = CLIMBABLE_TYPE_NOT; + eClimbableType m_ClimbableType = eClimbableType::CLIMBABLE_TYPE_NOT; }; #endif // SIMPLEPHYSICSCOMPONENT_H From 06df15717c05ce07ded563094b70c74ade1e3a59 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Thu, 19 May 2022 08:40:50 -0500 Subject: [PATCH 250/251] maybe fix it --- dGame/dComponents/SimplePhysicsComponent.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dGame/dComponents/SimplePhysicsComponent.cpp b/dGame/dComponents/SimplePhysicsComponent.cpp index 8a052313..c9a42971 100644 --- a/dGame/dComponents/SimplePhysicsComponent.cpp +++ b/dGame/dComponents/SimplePhysicsComponent.cpp @@ -35,8 +35,8 @@ SimplePhysicsComponent::~SimplePhysicsComponent() { void SimplePhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { if (bIsInitialUpdate) { - outBitStream->Write(m_ClimbableType > 0); - outBitStream->Write(m_ClimbableType); + outBitStream->Write(m_ClimbableType != eClimbableType::CLIMBABLE_TYPE_NOT); + outBitStream->Write(m_ClimbableType); } outBitStream->Write(m_DirtyVelocity || bIsInitialUpdate); From cdb2cf034449767b7a18dcaa6512b806d957a582 Mon Sep 17 00:00:00 2001 From: Jasper Reddin Date: Mon, 23 May 2022 21:59:31 -0500 Subject: [PATCH 251/251] Added Comprehensive Slash Command Documentation (#402) * Added documentation for all available commands * Adjust formatting, removing backtick characters * Replace HTML tables with Markdown tables * Formatting changes * Suggestions from @sersorrel in #402 and other minor edits * Add detailed usage for /inspect (thanks to @sersorrel for this information, in discussion of #402) --- docs/Commands.md | 140 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 docs/Commands.md diff --git a/docs/Commands.md b/docs/Commands.md new file mode 100644 index 00000000..4d169c76 --- /dev/null +++ b/docs/Commands.md @@ -0,0 +1,140 @@ +# In-game commands + +Here is a summary of the commands available in-game. All commands are prefixed by `/` and typed in the in-game chat window. Some commands requires admin privileges. Operands within `<>` are required, operands within `()` are not. For the full list of in-game commands, please checkout [the source file](../dGame/dUtilities/SlashCommandHandler.cpp). + +## General Commands + +|Command|Usage|Description|Admin Level Requirement| +|--- |--- |--- |--- | +|credits|`/credits`|Displays the names of the people behind Darkflame Universe.|| +|die|`/die`|Smashes the player.|| +|info|`/info`|Displays server info to the user, including where to find the server's source code.|| +|instanceinfo|`/instanceinfo`|Displays in the chat the current zone, clone, and instance id.|| +|ping|`/ping (-l)`|Displays in chat your average ping. If the `-l` flag is used, the latest ping is displayed.|| +|pvp|`/pvp`|Toggle your PVP flag.|| +|resurrect|`/resurrect`|Resurrects the player.|| +|requestmailcount|`/requestmailcount`|Sends notification with number of unread messages in the player's mailbox.|| +|skip-ags|`/skip-ags`|Skips the Avant Gardens Survival minigame mission, "Impress the Sentinel Faction".|| +|skip-sg|`/skip-sg`|Skips the Shooting Gallery minigame mission, "Monarch of the Sea".|| +|who|`/who`|Displays in chat all players on the instance.|| + +## Moderation Commands + +|Command|Usage|Description|Admin Level Requirement| +|--- |--- |--- |--- | +|gmlevel|`/gmlevel `|Within the authorized range of levels for the current account, changes the character's game master level to the specified value. This is required to use certain commands. Aliases: `/setgmlevel`, `/makegm`.|| +|kick|`/kick `|Kicks the player off the server.|2| +|mailitem|`/mailitem `|Mails an item to the given player. The mailed item has predetermined content. The sender name is set to "Darkflame Universe." The title of the message is "Lost item." The body of the message is "This is a replacement item for one you lost."|3| +|ban|`/ban `|Bans a user from the server.|4| +|approveproperty|`/approveproperty`|Approves the property the player is currently visiting.|5| +|mute|`/mute (days) (hours)`|Mute player for the given amount of time. If no time is given, the mute is indefinite.|6| +|gmimmune|`/gmimmunve `|Sets the character's GMImmune state, where value can be one of "1", to make yourself immune to damage, or "0" to undo.|8| +|gminvis|`/gminvis`|Toggles invisibility for the character, though it's currently a bit buggy. Requires nonzero GM Level for the character, but the account must have a GM level of 8.|8| +|setname|`/setname `|Sets a temporary name for your player. The name resets when you log out.|8| +|title|`/title `|Temporarily appends your player's name with " - <title>". This resets when you log out.|8| + +## Server Operation Commands + +|Command|Usage|Description|Admin Level Requirement| +|--- |--- |--- |--- | +|announce|`/announce`|Sends a announcement. `/setanntitle` and `/setannmsg` must be called first to configure the announcement.|8| +|config-set|`/config-set <key> <value>`|Set configuration item.|8| +|config-get|`/config-get <key>`|Get current value of a configuration item.|8| +|kill|`/kill <username>`|Smashes the character whom the given user is playing.|8| +|metrics|`/metrics`|Prints some information about the server's performance.|8| +|setannmsg|`/setannmsg <title>`|Sets the message of an announcement.|8| +|setanntitle|`/setanntitle <title>`|Sets the title of an announcement.|8| +|shutdownuniverse|`/shutdownuniverse`|Sends a shutdown message to the master server. This will send an announcement to all players that the universe will shut down in 10 minutes.|9| + +## Development Commands + +These commands are primarily for development and testing. The usage of many of these commands relies on knowledge of the codebase and client SQLite database. + +|Command|Usage|Description|Admin Level Requirement| +|--- |--- |--- |--- | +|fix-stats|`/fix-stats`|Resets skills, buffs, and destroyables.|| +|join|`/join <password>`|Joins a private zone with given password.|| +|leave-zone|`/leave-zone`|If you are in an instanced zone, transfers you to the closest main world. For example, if you are in an instance of Avant Gardens Survival or the Spider Queen Battle, you are sent to Avant Gardens. If you are in the Battle of Nimbus Station, you are sent to Nimbus Station.|| +|setminifig|`/setminifig <body part> <minifig item id>`|Alters your player's minifig. Body part can be one of "Eyebrows", "Eyes", "HairColor", "HairStyle", "Pants", "LeftHand", "Mouth", "RightHand", "Shirt", or "Hands". Changing minifig parts could break the character so this command is limited to GMs.|1| +|testmap|`/testmap <zone> (force) (clone-id)`|Transfers you to the given zone by id and clone id. Add "force" to skip checking if the zone is accessible (this can softlock your character, though, if you e.g. try to teleport to Frostburgh).|1| +|reportproxphys|`/reportproxphys`|Prints to console the position and radius of proximity sensors.|6| +|spawnphysicsverts|`/spawnphysicsverts`|Spawns a 1x1 brick at all vertices of phantom physics objects.|6| +|teleport|`/teleport <x> (y) <z>`|Teleports you. If no Y is given, you are teleported to the height of the terrain or physics object at (x, z). Alias: `/tele`.|6| +|activatespawner|`/activatespawner <spawner name>`|Activates spawner by name.|8| +|addmission|`/addmission <mission id>`|Accepts the mission, adding it to your journal.|8| +|boost|`/boost`|Adds a passive boost action if you are in a vehicle.|8| +|buff|`/buff <id> <duration>`|Applies the buff with the given id for the given number of seconds.|8| +|buffme|`/buffme`|Sets health, armor, and imagination to 999.|8| +|buffmed|`/buffmed`|Sets health, armor, and imagination to 9.|8| +|clearflag|`/clearflag <flag id>`|Removes the given health or inventory flag from your player. Equivalent of calling `/setflag off <flag id>`.|8| +|completemission|`/completemission <mission id>`|Completes the mission, removing it from your journal.|8| +|createprivate|`/createprivate <zone id> <clone id> <password>`|Creates a private zone with password.|8| +|debugui|`/debugui`|Toggle Debug UI.|8| +|dismount|`/dismount`|Dismounts you from the vehicle.|8| +|force-save|`/force-save`|While saving to database usually happens on regular intervals and when you disconnect from the server, this command saves your player's data to the database.|8| +|freecam|`/freecam`|Toggles freecam mode.|8| +|freemoney|`/freemoney <coins>`|Gives coins.|8| +|getnavmeshheight|`/getnavmeshheight`|Displays the navmesh height at your current position.|8| +|giveuscore|`/giveuscore <uscore>`|Gives uscore.|8| +|gmadditem|`/gmadditem <id> (count)`|Adds the given item to your inventory by id.|8| +|inspect|`/inspect <component> (-m <waypoint> \| -a <animation> \| -s \| -p \| -f (faction) \| -t)`|Finds the closest entity with the given component or LDF variable (ignoring players and racing cars), printing its ID, distance from the player, and whether it is sleeping, as well as the the IDs of all components the entity has. See [Detailed `/inspect` Usage](#detailed-inspect-usage) below.|8| +|list-spawns|`/list-spawns`|Lists all the character spawn points in the zone. Additionally, this command will display the current scene that plays when the character lands in the next zone, if there is one.|8| +|locrow|`/locrow`|Prints the your current position and rotation information to the console.|8| +|lookup|`/lookup <query>`|Searches through the Objects table in the client SQLite database for items whose display name, name, or description contains the query.|8| +|playanimation|`/playanimation <id>`|Plays animation with given ID. Alias: `/playanim`.|8| +|playeffect|`/playeffect <effect id> <effect type> <effect name>`|Plays an effect.|8| +|playlvlfx|`/playlvlfx`|Plays the level up animation on your character.|8| +|playrebuildfx|`/playrebuildfx`|Plays the quickbuild animation on your character.|8| +|pos|`/pos`|Displays your current position in chat and in the console.|8| +|refillstats|`/refillstats`|Refills health, armor, and imagination to their maximum level.|8| +|reforge|`/reforge <base item id> <reforged item id>`|Reforges an item.|8| +|resetmission|`/resetmission <mission id>`|Sets the state of the mission to accepted but not yet started.|8| +|rot|`/rot`|Displays your current rotation in chat and in the console.|8| +|runmacro|`/runmacro <macro>`|Runs any command macro found in `./res/macros/`|8| +|setcontrolscheme|`/setcontrolscheme <scheme number>`|Sets the character control scheme to the specified number.|8| +|setcurrency|`/setcurrency <coins>`|Sets your coins.|8| +|setflag|`/setflag (value) <flag id>`|Sets the given inventory or health flag to the given value, where value can be one of "on" or "off". If no value is given, by default this adds the flag to your character (equivalent of calling `/setflag on <flag id>`).|8| +|setinventorysize|`/setinventorysize <size>`|Sets your inventory size to the given size. Alias: `/setinvsize`|8| +|setuistate|`/setuistate <ui state>`|Changes UI state.|8| +|spawn|`/spawn <id>`|Spawns an object at your location by id.|8| +|speedboost|`/speedboost <amount>`|Sets the speed multiplier to the given amount. `/speedboost 1.5` will set the speed multiplier to 1.5x the normal speed.|8| +|startcelebration|`/startcelebration <id>`|Starts a celebration effect on your character.|8| +|stopeffect|`/stopeffect <effect id>`|Stops the given effect.|8| +|toggle|`/toggle <ui state>`|Toggles UI state.|8| +|tpall|`/tpall`|Teleports all characters to your current position.|8| +|triggerspawner|`/triggerspawner <spawner name>`|Triggers spawner by name.|8| +|unlock-emote|`/unlock-emote <emote id>`|Unlocks for your character the emote of the given id.|8| +|crash|`/crash`|Crashes the server.|9| +|rollloot|`/rollloot <loot matrix index> <item id> <amount>`|Rolls loot matrix.|9| + +## Detailed `/inspect` Usage + +`/inspect <component> (-m <waypoint> | -a <animation> | -s | -p | -f (faction) | -t)` + +Finds the closest entity with the given component or LDF variable (ignoring players and racing cars), printing its ID, distance from the player, and whether it is sleeping, as well as the the IDs of all components the entity has. + +### `/inspect` Options + +* `-m`: If the entity has a moving platform component, sends it to the given waypoint, or stops the platform if `waypoint` is `-1`. +* `-a`: Plays the given animation on the entity. +* `-s`: Prints the entity's settings and spawner ID. +* `-p`: Prints the entity's position +* `-f`: If the entity has a destroyable component, prints whether the entity is smashable and its friendly and enemy faction IDs; if `faction` is specified, adds that faction to the entity. +* `-t`: If the entity has a phantom physics component, prints the effect type, direction, directional multiplier, and whether the effect is active; in any case, if the entity has a trigger, prints the trigger ID. + +## Game Master Levels + +There are 9 Game master levels + +|Level|Variable Name|Description| +|--- |--- |--- | +|0|GAME_MASTER_LEVEL_CIVILIAN|Normal player| +|1|GAME_MASTER_LEVEL_FORUM_MODERATOR|Forum moderator. No permissions on live servers.| +|2|GAME_MASTER_LEVEL_JUNIOR_MODERATOR|Can kick/mute and pull chat logs| +|3|GAME_MASTER_LEVEL_MODERATOR|Can return lost items| +|4|GAME_MASTER_LEVEL_SENIOR_MODERATOR|Can ban| +|5|GAME_MASTER_LEVEL_LEAD_MODERATOR|Can approve properties| +|6|GAME_MASTER_LEVEL_JUNIOR_DEVELOPER|Junior developer & future content team. Civilan on live.| +|7|GAME_MASTER_LEVEL_INACTIVE_DEVELOPER|Inactive developer, limited permissions.| +|8|GAME_MASTER_LEVEL_DEVELOPER|Active developer, full permissions on live.| +|9|GAME_MASTER_LEVEL_OPERATOR|Can shutdown server for restarts & updates.|