diff --git a/dScripts/AmDarklingDragon.cpp b/dScripts/AmDarklingDragon.cpp new file mode 100644 index 00000000..be87f466 --- /dev/null +++ b/dScripts/AmDarklingDragon.cpp @@ -0,0 +1,164 @@ +#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 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..ea4c2a19 --- /dev/null +++ b/dScripts/AmDarklingDragon.h @@ -0,0 +1,48 @@ +#pragma once +#include "CppScripts.h" + +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; +}; 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 3b9ce5f9..1e2d0313 100644 --- a/dScripts/CppScripts.cpp +++ b/dScripts/CppScripts.cpp @@ -223,7 +223,7 @@ #include "AmSkullkinDrill.h" #include "AmSkullkinDrillStand.h" #include "AmSkullkinTower.h" -#include "AmNamedDarklingDragon.h" +#include "AmDarklingDragon.h" #include "AmBlueX.h" // NJ Scripts @@ -687,11 +687,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")