Compare commits

...

7 Commits

Author SHA1 Message Date
David Markowitz
ef44da055c use float
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-21 21:18:16 -07:00
David Markowitz
9c9f3d3207 remove unused handlers
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-21 21:18:01 -07:00
David Markowitz
539ff2bac2 default initialize
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-21 21:15:12 -07:00
David Markowitz
90b4913c55 Update CountdownDestroyAI.cpp 2026-06-21 21:08:35 -07:00
David Markowitz
30479a0ef0 feat: implement ronin script 2026-06-21 20:57:09 -07:00
David Markowitz
5fa158298b Update FvDragonInstanceServer.h 2026-06-20 22:24:56 -07:00
David Markowitz
bfd0f1ff35 feat: dragon instance script 2026-06-20 22:11:35 -07:00
15 changed files with 142 additions and 3 deletions

View File

@@ -521,6 +521,10 @@ void BaseCombatAIComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsI
void BaseCombatAIComponent::SetAiState(AiState newState) {
if (newState == this->m_State) return;
GameMessages::NotifyCombatAIStateChange stateMsg;
stateMsg.prevState = this->m_State;
stateMsg.newState = newState;
m_Parent->HandleMsg(stateMsg);
this->m_State = newState;
m_DirtyStateOrTarget = true;
Game::entityManager->SerializeEntity(m_Parent);

View File

@@ -16,7 +16,7 @@ ScriptComponent::ScriptComponent(Entity* parent, const int32_t componentID, cons
m_ScriptName = scriptName;
SetScript(scriptName);
RegisterMsg(&ScriptComponent::OnGetObjectReportInfo);
Component::RegisterMsg(&ScriptComponent::OnGetObjectReportInfo);
}
void ScriptComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) {

View File

@@ -8,6 +8,9 @@
#include "CppScripts.h"
#include "Component.h"
#include "GameMessages.h"
#include <functional>
#include <map>
#include <string>
#include "eReplicaComponentType.h"
@@ -45,6 +48,17 @@ public:
bool OnGetObjectReportInfo(GameMessages::GetObjectReportInfo& reportInfo);
// Registers a message from a script to be listened for on the parent object
template<typename ScriptClass, typename DerivedMsgType>
void RegisterMsg(ScriptClass* scriptThis, bool (ScriptClass::*scriptHandler)(Entity&, DerivedMsgType&)) {
const auto boundMsg = std::bind(scriptHandler, scriptThis, std::placeholders::_1, std::placeholders::_2);
const auto castWrapper = [this, boundMsg](GameMessages::GameMsg& msg) {
return boundMsg(*m_Parent, static_cast<DerivedMsgType&>(msg));
};
DerivedMsgType msg;
m_Parent->RegisterMsg(msg.msgId, castWrapper);
}
private:
/**

View File

@@ -45,6 +45,7 @@ enum class BehaviorSlot : int32_t;
enum class eVendorTransactionResult : uint32_t;
enum class eReponseMoveItemBetweenInventoryTypeCode : int32_t;
enum class eMissionState : int;
enum class AiState : uint32_t;
enum class eCameraTargetCyclingMode : int32_t {
ALLOW_CYCLE_TEAMMATES,
@@ -971,5 +972,12 @@ namespace GameMessages {
LWOOBJID objectID{};
LOT lot{};
};
struct NotifyCombatAIStateChange : public GameMsg {
NotifyCombatAIStateChange() : GameMsg(MessageType::Game::NOTIFY_COMBAT_AI_STATE_CHANGE) {}
AiState newState{};
AiState prevState{};
};
};
#endif // GAMEMESSAGES_H

View File

@@ -1,4 +1,5 @@
set(DSCRIPTS_SOURCES_02_SERVER_ENEMY_FV
"DragonRonin.cpp"
"FvMaelstromCavalry.cpp"
"FvMaelstromDragon.cpp"
PARENT_SCOPE)

View File

@@ -0,0 +1,6 @@
#include "DragonRonin.h"
void DragonRonin::OnStartup(Entity* self) {
self->SetVar<float>(u"suicideTimer", 40.0f);
CountdownDestroyAI::OnStartup(self);
}

View File

@@ -0,0 +1,7 @@
#pragma once
#include "CountdownDestroyAI.h"
class DragonRonin : public CountdownDestroyAI {
public:
void OnStartup(Entity* self) override;
};

View File

@@ -1,6 +1,7 @@
set(DSCRIPTS_SOURCES_02_SERVER_ENEMY_GENERAL
"BaseEnemyMech.cpp"
"BaseEnemyApe.cpp"
"CountdownDestroyAI.cpp"
"GfApeSmashingQB.cpp"
"TreasureChestDragonServer.cpp"
"EnemyNjBuff.cpp"

View File

@@ -0,0 +1,50 @@
#include "CountdownDestroyAI.h"
#include "BaseCombatAIComponent.h"
#include "ScriptComponent.h"
void CountdownDestroyAI::OnStartup(Entity* self) {
CountdownStartup(*self);
auto* scriptComp = self->GetComponent<ScriptComponent>();
if (scriptComp) scriptComp->RegisterMsg(this, &CountdownDestroyAI::OnNotifyCombatAIStateChange);
}
void CountdownDestroyAI::CountdownStartup(Entity& self) {
auto suicideTimer = self.GetVar<float>(u"suicideTimer");
if (suicideTimer == 0.0f) suicideTimer = 60;
self.AddTimer("Dead", suicideTimer);
}
void CountdownDestroyAI::OnHit(Entity* self, Entity* attacker) {
if (!self->GetVar<bool>(u"ShouldBeDead")) return;
self->CancelTimer("IsBeingAttacked");
self->AddTimer("Dead", 5.0f);
}
void CountdownDestroyAI::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "Dead") {
self->SetVar<bool>(u"ShouldBeDead", true);
if (self->GetVar<bool>(u"Busy")) {
self->AddTimer("IsBeingAttacked", 5.0f);
} else {
self->Smash();
}
} else if (timerName == "IsBeingAttacked") {
self->Smash();
}
}
bool CountdownDestroyAI::OnNotifyCombatAIStateChange(Entity& self, GameMessages::NotifyCombatAIStateChange& notifyMsg) {
const auto curState = notifyMsg.newState;
if (curState == AiState::dead) return true;
if (curState == AiState::aggro || curState == AiState::tether) {
self.SetVar(u"Busy", true);
} else {
self.SetVar(u"Busy", false);
if (self.GetVar<bool>(u"ShouldBeDead")) {
self.Smash();
}
}
return true;
}

View File

@@ -0,0 +1,13 @@
#pragma once
#include "CppScripts.h"
#include "GameMessages.h"
class CountdownDestroyAI : public CppScripts::Script {
public:
void OnStartup(Entity* self) override;
void CountdownStartup(Entity& self);
void OnHit(Entity* self, Entity* attacker) override;
void OnTimerDone(Entity* self, std::string timerName) override;
bool OnNotifyCombatAIStateChange(Entity& self, GameMessages::NotifyCombatAIStateChange& msg);
};

View File

@@ -135,8 +135,11 @@
#include "FvMaelstromCavalry.h"
#include "FvHorsemenTrigger.h"
#include "FvFlyingCreviceDragon.h"
#include "FvDragonInstanceServer.h"
#include "FvMaelstromDragon.h"
#include "DragonRonin.h"
#include "FvDragonSmashingGolemQb.h"
#include "CountdownDestroyAI.h"
#include "TreasureChestDragonServer.h"
#include "InstanceExitTransferPlayerToLastNonInstance.h"
#include "FvFreeGfNinjas.h"
@@ -490,7 +493,10 @@ namespace {
{"scripts\\ai\\FV\\L_ACT_NINJA_TURRET_1.lua", []() {return new ActNinjaTurret();}},
{"scripts\\02_server\\Map\\FV\\L_FV_HORSEMEN_TRIGGER.lua", []() {return new FvHorsemenTrigger();}},
{"scripts\\ai\\FV\\L_FV_FLYING_CREVICE_DRAGON.lua", []() {return new FvFlyingCreviceDragon();}},
{"scripts\\ai\\FV\\Dragon_Instance\\L_FV_DRAGON_INSTANCE_SERVER.lua", []() {return new FvDragonInstanceServer();}},
{"scripts\\02_server\\Enemy\\FV\\L_FV_DRAGON_RONIN.lua", []() {return new DragonRonin();}},
{"scripts\\02_server\\Enemy\\FV\\L_FV_MAELSTROM_DRAGON.lua", []() {return new FvMaelstromDragon();}},
{"scripts\\02_server\\Enemy\\General\\L_COUNTDOWN_DESTROY_AI.lua", []() {return new CountdownDestroyAI();}},
{"scripts\\ai\\FV\\L_FV_DRAGON_SMASHING_GOLEM_QB.lua", []() {return new FvDragonSmashingGolemQb();}},
{"scripts\\02_server\\Enemy\\General\\L_TREASURE_CHEST_DRAGON_SERVER.lua", []() {return new TreasureChestDragonServer();}},
{"scripts\\ai\\GENERAL\\L_INSTANCE_EXIT_TRANSFER_PLAYER_TO_LAST_NON_INSTANCE.lua", []() {return new InstanceExitTransferPlayerToLastNonInstance();}},

View File

@@ -18,7 +18,13 @@ set(DSCRIPTS_SOURCES_AI_FV
"FvMaelstromGeyser.cpp"
"TriggerGas.cpp")
add_subdirectory(Dragon_Instance)
foreach(file ${DSCRIPTS_SOURCES_AI_FV_DRAGON_INSTANCE})
set(DSCRIPTS_SOURCES_AI_FV ${DSCRIPTS_SOURCES_AI_FV} "Dragon_Instance/${file}")
endforeach()
add_library(dScriptsAiFV OBJECT ${DSCRIPTS_SOURCES_AI_FV})
target_include_directories(dScriptsAiFV PUBLIC ".")
target_include_directories(dScriptsAiFV PUBLIC "." "Dragon_Instance")
target_precompile_headers(dScriptsAiFV REUSE_FROM dScriptsBase)

View File

@@ -0,0 +1,3 @@
set(DSCRIPTS_SOURCES_AI_FV_DRAGON_INSTANCE
"FvDragonInstanceServer.cpp"
PARENT_SCOPE)

View File

@@ -0,0 +1,13 @@
#include "FvDragonInstanceServer.h"
#include "Entity.h"
#include "DestroyableComponent.h"
void FvDragonInstanceServer::OnPlayerLoaded(Entity* self, Entity* player) {
auto* const destComp = player->GetComponent<DestroyableComponent>();
if (destComp) {
destComp->SetHealth(destComp->GetMaxHealth());
destComp->SetArmor(destComp->GetMaxArmor());
destComp->SetImagination(destComp->GetMaxImagination());
}
}

View File

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