From 021db0ecd1555a7173d2b88a9cd82244e3d1fc89 Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Tue, 31 Dec 2024 22:46:00 -0800 Subject: [PATCH] add child loading (#1706) Tested that the NT combat challenge, am skullkin towers and qa wall in avant gardens all function as before. --- dGame/Entity.cpp | 10 +++++++++ dGame/Entity.h | 2 ++ dGame/dGameMessages/GameMessages.h | 7 ++++++ dScripts/02_server/Map/AM/AmSkullkinTower.cpp | 17 +++++++------- dScripts/02_server/Map/AM/AmSkullkinTower.h | 2 +- dScripts/02_server/Map/General/QbSpawner.cpp | 15 +++++++------ dScripts/02_server/Map/General/QbSpawner.h | 2 +- .../Map/NT/NtCombatChallengeServer.cpp | 22 ++++++------------- .../Map/NT/NtCombatChallengeServer.h | 2 +- dScripts/CppScripts.h | 8 +++++++ 10 files changed, 54 insertions(+), 33 deletions(-) diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index bd1a2793..5a0dab77 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -775,6 +775,12 @@ void Entity::Initialize() { // Hacky way to trigger these when the object has had a chance to get constructed AddCallbackTimer(0, [this]() { this->GetScript()->OnStartup(this); + if (this->m_ParentEntity) { + GameMessages::ChildLoaded childLoaded; + childLoaded.childID = this->m_ObjectID; + childLoaded.templateID = this->GetLOT(); + this->m_ParentEntity->OnChildLoaded(childLoaded); + } }); if (!m_Character && Game::entityManager->GetGhostingEnabled()) { @@ -1501,6 +1507,10 @@ void Entity::OnShootingGalleryFire(GameMessages::ShootingGalleryFire& fire) { GetScript()->OnShootingGalleryFire(*this, fire); } +void Entity::OnChildLoaded(GameMessages::ChildLoaded& childLoaded) { + GetScript()->OnChildLoaded(*this, childLoaded); +} + void Entity::RequestActivityExit(Entity* sender, LWOOBJID player, bool canceled) { GetScript()->OnRequestActivityExit(sender, player, canceled); } diff --git a/dGame/Entity.h b/dGame/Entity.h index 1e07aff0..7bb53c2d 100644 --- a/dGame/Entity.h +++ b/dGame/Entity.h @@ -16,6 +16,7 @@ namespace GameMessages { struct ActivityNotify; struct ShootingGalleryFire; + struct ChildLoaded; }; namespace Loot { @@ -217,6 +218,7 @@ public: void OnZonePropertyModelRotated(Entity* player); void OnActivityNotify(GameMessages::ActivityNotify& notify); void OnShootingGalleryFire(GameMessages::ShootingGalleryFire& notify); + void OnChildLoaded(GameMessages::ChildLoaded& childLoaded); void OnMessageBoxResponse(Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData); void OnChoiceBoxResponse(Entity* sender, int32_t button, const std::u16string& buttonIdentifier, const std::u16string& identifier); diff --git a/dGame/dGameMessages/GameMessages.h b/dGame/dGameMessages/GameMessages.h index 0b1bcf52..b5ef62d9 100644 --- a/dGame/dGameMessages/GameMessages.h +++ b/dGame/dGameMessages/GameMessages.h @@ -758,6 +758,13 @@ namespace GameMessages { NiPoint3 target{}; NiQuaternion rotation{}; }; + + struct ChildLoaded : public GameMsg { + ChildLoaded() : GameMsg(MessageType::Game::CHILD_LOADED) {} + + LOT templateID{}; + LWOOBJID childID{}; + }; }; #endif // GAMEMESSAGES_H diff --git a/dScripts/02_server/Map/AM/AmSkullkinTower.cpp b/dScripts/02_server/Map/AM/AmSkullkinTower.cpp index 1eaad3c9..a6a4b8c8 100644 --- a/dScripts/02_server/Map/AM/AmSkullkinTower.cpp +++ b/dScripts/02_server/Map/AM/AmSkullkinTower.cpp @@ -64,21 +64,22 @@ void AmSkullkinTower::SpawnLegs(Entity* self, const std::string& loc) { info.rot = NiQuaternion::LookAt(info.pos, self->GetPosition()); - auto* entity = Game::entityManager->CreateEntity(info); + auto* entity = Game::entityManager->CreateEntity(info, nullptr, self); Game::entityManager->ConstructEntity(entity); - - OnChildLoaded(self, entity); } -void AmSkullkinTower::OnChildLoaded(Entity* self, Entity* child) { - auto legTable = self->GetVar>(u"legTable"); +void AmSkullkinTower::OnChildLoaded(Entity& self, GameMessages::ChildLoaded& childLoaded) { + auto legTable = self.GetVar>(u"legTable"); - legTable.push_back(child->GetObjectID()); + legTable.push_back(childLoaded.childID); - self->SetVar(u"legTable", legTable); + self.SetVar(u"legTable", legTable); - const auto selfID = self->GetObjectID(); + const auto selfID = self.GetObjectID(); + auto* const child = Game::entityManager->GetEntity(childLoaded.childID); + + if (!child) return; child->AddDieCallback([this, selfID, child]() { auto* self = Game::entityManager->GetEntity(selfID); diff --git a/dScripts/02_server/Map/AM/AmSkullkinTower.h b/dScripts/02_server/Map/AM/AmSkullkinTower.h index 495641de..53638f32 100644 --- a/dScripts/02_server/Map/AM/AmSkullkinTower.h +++ b/dScripts/02_server/Map/AM/AmSkullkinTower.h @@ -8,7 +8,7 @@ public: void SpawnLegs(Entity* self, const std::string& loc); - void OnChildLoaded(Entity* self, Entity* child); + void OnChildLoaded(Entity& self, GameMessages::ChildLoaded& childLoaded) override; void NotifyDie(Entity* self, Entity* other, Entity* killer); diff --git a/dScripts/02_server/Map/General/QbSpawner.cpp b/dScripts/02_server/Map/General/QbSpawner.cpp index 6776c8ea..6fc93d05 100644 --- a/dScripts/02_server/Map/General/QbSpawner.cpp +++ b/dScripts/02_server/Map/General/QbSpawner.cpp @@ -77,8 +77,6 @@ void QbSpawner::OnTimerDone(Entity* self, std::string timerName) { auto* child = Game::entityManager->CreateEntity(info, nullptr, self); Game::entityManager->ConstructEntity(child); - - OnChildLoaded(self, child); } else { auto* mob = Game::entityManager->GetEntity(mobTable[i]); AggroTargetObject(self, mob); @@ -88,16 +86,19 @@ void QbSpawner::OnTimerDone(Entity* self, std::string timerName) { } } -void QbSpawner::OnChildLoaded(Entity* self, Entity* child) { - auto mobTable = self->GetVar>(u"mobTable"); +void QbSpawner::OnChildLoaded(Entity& self, GameMessages::ChildLoaded& childLoaded) { + auto* const child = Game::entityManager->GetEntity(childLoaded.childID); + if (!child) return; + + auto mobTable = self.GetVar>(u"mobTable"); auto tableLoc = child->GetVar(u"mobTableLoc"); mobTable[tableLoc] = child->GetObjectID(); - self->SetVar>(u"mobTable", mobTable); + self.SetVar>(u"mobTable", mobTable); - AggroTargetObject(self, child); + AggroTargetObject(&self, child); - const auto selfID = self->GetObjectID(); + const auto selfID = self.GetObjectID(); child->AddDieCallback([this, selfID, child]() { auto* self = Game::entityManager->GetEntity(selfID); diff --git a/dScripts/02_server/Map/General/QbSpawner.h b/dScripts/02_server/Map/General/QbSpawner.h index 105d0835..14990122 100644 --- a/dScripts/02_server/Map/General/QbSpawner.h +++ b/dScripts/02_server/Map/General/QbSpawner.h @@ -6,7 +6,7 @@ public: void OnStartup(Entity* self) override; void OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2, int32_t param3) override; void OnTimerDone(Entity* self, std::string timerName) override; - void OnChildLoaded(Entity* self, Entity* child); + void OnChildLoaded(Entity& self, GameMessages::ChildLoaded& childLoaded) override; void OnChildRemoved(Entity* self, Entity* child); void AggroTargetObject(Entity* self, Entity* enemy); private: diff --git a/dScripts/02_server/Map/NT/NtCombatChallengeServer.cpp b/dScripts/02_server/Map/NT/NtCombatChallengeServer.cpp index 011a67ea..94ad718f 100644 --- a/dScripts/02_server/Map/NT/NtCombatChallengeServer.cpp +++ b/dScripts/02_server/Map/NT/NtCombatChallengeServer.cpp @@ -91,7 +91,7 @@ void NtCombatChallengeServer::SpawnTargetDummy(Entity* self) { info.rot = self->GetRotation(); info.settings = { new LDFData(u"custom_script_server", "scripts\\02_server\\Map\\NT\\L_NT_COMBAT_CHALLENGE_DUMMY.lua") }; - auto* dummy = Game::entityManager->CreateEntity(info); + auto* dummy = Game::entityManager->CreateEntity(info, nullptr, self); dummy->SetVar(u"challengeObjectID", self->GetObjectID()); @@ -104,26 +104,18 @@ void NtCombatChallengeServer::SetAttackImmunity(LWOOBJID objID, bool bTurnOn) { } -void NtCombatChallengeServer::OnChildLoaded(Entity* self, Entity* child) { - auto targetNumber = self->GetVar(u"TargetNumber"); - if (targetNumber == 0) targetNumber = 1; - self->SetVar(u"TargetNumber", targetNumber + 1); +void NtCombatChallengeServer::OnChildLoaded(Entity& self, GameMessages::ChildLoaded& childLoaded) { + auto* const child = Game::entityManager->GetEntity(childLoaded.childID); - const auto playerID = self->GetVar(u"playerID"); - - auto* player = Game::entityManager->GetEntity(playerID); - - if (player == nullptr) { - return; + if (child) { + child->SetRotation(NiQuaternion::FromEulerAngles(child->GetRotation().GetEulerAngles() += NiPoint3(0, PI, 0))); // rotate 180 degrees } - child->SetRotation(NiQuaternion::LookAt(child->GetPosition(), player->GetPosition())); - - self->SetVar(u"currentTargetID", child->GetObjectID()); + self.SetVar(u"currentTargetID", child->GetObjectID()); Game::entityManager->SerializeEntity(child); - child->GetGroups().push_back("targets_" + std::to_string(self->GetObjectID())); + child->GetGroups().push_back("targets_" + std::to_string(self.GetObjectID())); } void NtCombatChallengeServer::ResetGame(Entity* self) { diff --git a/dScripts/02_server/Map/NT/NtCombatChallengeServer.h b/dScripts/02_server/Map/NT/NtCombatChallengeServer.h index 72bb981f..3b59b937 100644 --- a/dScripts/02_server/Map/NT/NtCombatChallengeServer.h +++ b/dScripts/02_server/Map/NT/NtCombatChallengeServer.h @@ -12,7 +12,7 @@ public: void OnMessageBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData) override; void SpawnTargetDummy(Entity* self); void SetAttackImmunity(LWOOBJID objID, bool bTurnOn); - void OnChildLoaded(Entity* self, Entity* child); + void OnChildLoaded(Entity& self, GameMessages::ChildLoaded& childLoaded) override; void ResetGame(Entity* self); void OnActivityTimerUpdate(Entity* self, float timeRemaining); void OnTimerDone(Entity* self, std::string timerName) override; diff --git a/dScripts/CppScripts.h b/dScripts/CppScripts.h index 573dab89..18e0ec10 100644 --- a/dScripts/CppScripts.h +++ b/dScripts/CppScripts.h @@ -373,6 +373,14 @@ namespace CppScripts { * @param fire The firing data */ virtual void OnShootingGalleryFire(Entity& self, GameMessages::ShootingGalleryFire& fire) {}; + + /** + * @brief Handles when a child is loaded + * + * @param self + * @param fire The child info + */ + virtual void OnChildLoaded(Entity& self, GameMessages::ChildLoaded& childLoaded) {}; }; Script* const GetScript(Entity* parent, const std::string& scriptName);