From e2e2e6c1cdba102dd495c6e1e7350ca6c0c32a94 Mon Sep 17 00:00:00 2001 From: Jett <55758076+Jettford@users.noreply.github.com> Date: Thu, 16 Oct 2025 13:18:13 +0100 Subject: [PATCH] feat: banana tree defence program --- dScripts/ai/GF/GfBanana.cpp | 69 ++++++++++++++++++++++++------------- dScripts/ai/GF/GfBanana.h | 3 ++ 2 files changed, 48 insertions(+), 24 deletions(-) diff --git a/dScripts/ai/GF/GfBanana.cpp b/dScripts/ai/GF/GfBanana.cpp index 93741d24..0fd5b05f 100644 --- a/dScripts/ai/GF/GfBanana.cpp +++ b/dScripts/ai/GF/GfBanana.cpp @@ -5,6 +5,8 @@ #include "EntityInfo.h" #include "EntityManager.h" +#include "GeneralUtils.h" + void GfBanana::SpawnBanana(Entity* self) { auto position = self->GetPosition(); const auto rotation = self->GetRotation(); @@ -44,7 +46,36 @@ void GfBanana::OnHit(Entity* self, Entity* attacker) { const auto bananaId = self->GetVar(u"banana"); - if (bananaId == LWOOBJID_EMPTY) return; + if (bananaId == LWOOBJID_EMPTY) { + if (GeneralUtils::GenerateRandomNumber(1, 100) == 100 && self->GetVar(u"apeId") == LWOOBJID_EMPTY) { + // ape appears if you hurt the trees feeling while it has no banana + + // play fx effect + GameMessages::SendPlayEmbeddedEffectOnAllClientsNearObject(self, u"camshake-bridge", self->GetObjectID(), 100.0f); + + auto position = self->GetPosition(); + auto rotation = QuatUtils::LookAt(self->GetPosition(), position); + + EntityInfo info {}; + + info.pos = position; + info.rot = rotation; + info.lot = m_GorillaLOT; + info.spawner = nullptr; + info.spawnerID = self->GetObjectID(); + info.spawnerNodeID = 0; + + auto* entity = Game::entityManager->CreateEntity(info); + + Game::entityManager->ConstructEntity(entity, UNASSIGNED_SYSTEM_ADDRESS); + + self->SetVar(u"apeId", entity->GetObjectID()); + + self->AddTimer("apeTimer", 10); + } + + return; + } auto* bananaEntity = Game::entityManager->GetEntity(bananaId); @@ -56,39 +87,29 @@ void GfBanana::OnHit(Entity* self, Entity* attacker) { return; } - bananaEntity->SetPosition(bananaEntity->GetPosition() - NiPoint3Constant::UNIT_Y * 8); + auto bananaFloor = (bananaEntity->GetPosition() - NiPoint3Constant::UNIT_Y * 8); + bananaEntity->SetPosition(bananaFloor); auto* bananaDestroyable = bananaEntity->GetComponent(); - bananaDestroyable->SetHealth(0); - bananaDestroyable->Smash(attacker->GetObjectID()); - /* - auto position = self->GetPosition(); - const auto rotation = self->GetRotation(); - - position.y += 12; - position.x -= rotation.GetRightVector().x * 5; - position.z -= rotation.GetRightVector().z * 5; - - EntityInfo info {}; - - info.pos = position; - info.rot = rotation; - info.lot = 6718; - info.spawnerID = self->GetObjectID(); - - auto* entity = Game::entityManager->CreateEntity(info); - - Game::entityManager->ConstructEntity(entity, UNASSIGNED_SYSTEM_ADDRESS); - */ - Game::entityManager->SerializeEntity(self); } void GfBanana::OnTimerDone(Entity* self, std::string timerName) { if (timerName == "bananaTimer") { SpawnBanana(self); + } else if (timerName == "apeTimer") { + if (self->GetVar(u"apeId") == LWOOBJID_EMPTY) return; + + auto entity = Game::entityManager->GetEntity(self->GetVar(u"apeId")); + + if (entity) { + GameMessages::SendPlayEmbeddedEffectOnAllClientsNearObject(self, u"camshake-bridge", self->GetObjectID(), 100.0f); + entity->GetComponent()->Smash(self->GetObjectID(), eKillType::SILENT); // to destroy the anchor too + Game::entityManager->DestroyEntity(entity); + } + self->SetVar(u"apeId", LWOOBJID_EMPTY); } } diff --git a/dScripts/ai/GF/GfBanana.h b/dScripts/ai/GF/GfBanana.h index a33bddf6..996a8874 100644 --- a/dScripts/ai/GF/GfBanana.h +++ b/dScripts/ai/GF/GfBanana.h @@ -11,4 +11,7 @@ public: void OnHit(Entity* self, Entity* attacker) override; void OnTimerDone(Entity* self, std::string timerName) override; + +private: + LOT m_GorillaLOT = 13524; };