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.
This commit is contained in:
EmosewaMC 2022-01-19 02:10:04 -08:00
parent 84a376b425
commit 67d5061416
5 changed files with 182 additions and 24 deletions

View File

@ -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<int32_t>(u"weakspot", 0);
auto* baseCombatAIComponent = self->GetComponent<BaseCombatAIComponent>();
if (baseCombatAIComponent != nullptr) {
baseCombatAIComponent->SetStunImmune(true);
}
}
void AmDarklingDragon::OnDie(Entity* self, Entity* killer) {
if (self->GetVar<bool>(u"bDied")) {
return;
}
self->SetVar<bool>(u"bDied", true);
auto position = self->GetPosition();
auto rotation = self->GetRotation();
auto golemId = self->GetVar<LWOOBJID>(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<int32_t>(u"weakspot");
if (weakpoint == 1)
{
self->Smash(attacker->GetObjectID());
}
}
auto* destroyableComponent = self->GetComponent<DestroyableComponent>();
if (destroyableComponent != nullptr) {
Game::logger->Log("AmDarklingDragon", "Armor is %i\n", destroyableComponent->GetArmor());
if (destroyableComponent->GetArmor() > 0) return;
auto weakpoint = self->GetVar<int32_t>(u"weakpoint");
if (weakpoint == 0) {
Game::logger->Log("AmDarklingDragon", "Activating weakpoint\n");
self->AddTimer("ReviveTimer", 12);
auto* baseCombatAIComponent = self->GetComponent<BaseCombatAIComponent>();
auto* skillComponent = self->GetComponent<SkillComponent>();
if (baseCombatAIComponent != nullptr) {
baseCombatAIComponent->SetDisabled(true);
baseCombatAIComponent->SetStunned(true);
}
if (skillComponent != nullptr) {
skillComponent->Interrupt();
}
self->SetVar<int32_t>(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<int32_t>(u"DragonSmashingGolem");
EntityInfo info {};
info.lot = golem != 0 ? golem : 8340;
info.pos = objectPosition;
info.rot = rotation;
info.spawnerID = self->GetObjectID();
info.settings = {
new LDFData<std::string>(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<int32_t>(u"respawn", 100000),
new LDFData<float>(u"rebuild_reset_time", 15),
new LDFData<bool>(u"no_timed_spawn", true),
new LDFData<LWOOBJID>(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<int32_t>(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<BaseCombatAIComponent>();
auto* skillComponent = self->GetComponent<SkillComponent>();
if (baseCombatAIComponent != nullptr)
{
baseCombatAIComponent->SetDisabled(false);
baseCombatAIComponent->SetStunned(false);
}
if (skillComponent != nullptr)
{
skillComponent->Interrupt();
}
self->SetVar<int32_t>(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<LWOOBJID>(u"Golem", sender->GetObjectID());
GameMessages::SendPlayAnimation(self, u"quickbuildhold", 1.9f);
}

View File

@ -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;
};

View File

@ -1,12 +0,0 @@
#include "AmNamedDarklingDragon.h"
#include "BaseCombatAIComponent.h"
void AmNamedDarklingDragon::OnStartup(Entity* self)
{
auto* baseCombatAIComponent = self->GetComponent<BaseCombatAIComponent>();
if (baseCombatAIComponent != nullptr)
{
baseCombatAIComponent->SetStunImmune(true);
}
}

View File

@ -1,8 +0,0 @@
#pragma once
#include "CppScripts.h"
class AmNamedDarklingDragon : public CppScripts::Script
{
public:
void OnStartup(Entity* self) override;
};

View File

@ -219,7 +219,7 @@
#include "AmSkullkinDrill.h" #include "AmSkullkinDrill.h"
#include "AmSkullkinDrillStand.h" #include "AmSkullkinDrillStand.h"
#include "AmSkullkinTower.h" #include "AmSkullkinTower.h"
#include "AmNamedDarklingDragon.h" #include "AmDarklingDragon.h"
#include "AmBlueX.h" #include "AmBlueX.h"
// NJ Scripts // NJ Scripts
@ -675,11 +675,10 @@ CppScripts::Script* CppScripts::GetScript(Entity* parent, const std::string& scr
script = new AmSkullkinDrillStand(); script = new AmSkullkinDrillStand();
else if (scriptName == "scripts\\02_server\\Map\\AM\\L_SKULLKIN_TOWER.lua") else if (scriptName == "scripts\\02_server\\Map\\AM\\L_SKULLKIN_TOWER.lua")
script = new AmSkullkinTower(); 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") 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") 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") else if (scriptName == "scripts\\02_server\\Enemy\\AM\\L_AM_DARKLING_APE.lua")
script = new BaseEnemyApe(); script = new BaseEnemyApe();
else if (scriptName == "scripts\\02_server\\Map\\AM\\L_BLUE_X.lua") else if (scriptName == "scripts\\02_server\\Map\\AM\\L_BLUE_X.lua")