From 763a1f4a613c2de8d438a4f64be4302b5005bcaf Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Sun, 1 May 2022 08:54:45 -0500 Subject: [PATCH 01/14] 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 02/14] 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 03/14] 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 04/14] 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 05/14] 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 06/14] 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 07/14] 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 08/14] 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 09/14] 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 10/14] 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 11/14] 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 12/14] 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 13/14] 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 14/14] 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")