Organize dScripts (#814)

* Organize dScripts

whitespace

Remove parent scope

Remove parent scope from initial setter

Remove debug

Remove helper programs

* Fix NtImagimeterVisibility script

Co-authored-by: aronwk-aaron <aronwk.aaron@gmail.com>
This commit is contained in:
David Markowitz
2022-11-03 10:57:54 -07:00
committed by GitHub
parent b974eed8f5
commit 8d37d9b681
567 changed files with 886 additions and 252 deletions

View File

@@ -0,0 +1,52 @@
#include "ActMine.h"
#include "SkillComponent.h"
#include "DestroyableComponent.h"
#include "RebuildComponent.h"
void ActMine::OnStartup(Entity* self) {
self->SetVar(u"RebuildComplete", false);
self->SetProximityRadius(MINE_RADIUS, "mineRadius");
}
void ActMine::OnRebuildNotifyState(Entity* self, eRebuildState state) {
if (state == eRebuildState::REBUILD_COMPLETED) {
auto* rebuild = self->GetComponent<RebuildComponent>();
if (rebuild) {
auto* builder = rebuild->GetBuilder();
self->SetVar(u"Builder", builder->GetObjectID());
}
self->SetVar(u"RebuildComplete", true);
self->SetVar(u"NumWarnings", 0);
self->AddToGroup("reset");
}
}
void ActMine::OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) {
auto* detroyable = self->GetComponent<DestroyableComponent>();
if (!detroyable) return;
if (status == "ENTER" && self->GetVar<bool>(u"RebuildComplete") == true && detroyable->IsEnemy(entering)) {
GameMessages::SendPlayFXEffect(self->GetObjectID(), 242, u"orange", "sirenlight_B");
self->AddTimer("Tick", TICK_TIME);
}
}
void ActMine::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "Tick") {
if (self->GetVar<int>(u"NumWarnings") >= MAX_WARNINGS) {
auto* skill = self->GetComponent<SkillComponent>();
if (!skill) return;
skill->CalculateBehavior(SKILL_ID, BEHAVIOR_ID, LWOOBJID_EMPTY);
self->AddTimer("BlowedUp", BLOWED_UP_TIME);
} else {
GameMessages::SendPlayFXEffect(self->GetObjectID(), 242, u"orange", "sirenlight_B");
self->AddTimer("Tick", TICK_TIME);
self->SetVar(u"NumWarnings", self->GetVar<int>(u"NumWarnings") + 1);
}
}
if (timerName == "BlowedUp") {
self->Kill(self);
}
}

18
dScripts/ai/ACT/ActMine.h Normal file
View File

@@ -0,0 +1,18 @@
#pragma once
#include "CppScripts.h"
class ActMine : public CppScripts::Script {
public:
void OnStartup(Entity* self) override;
void OnRebuildNotifyState(Entity* self, eRebuildState state) override;
void OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) override;
void OnTimerDone(Entity* self, std::string timerName) override;
private:
int MAX_WARNINGS = 3;
float MINE_RADIUS = 10.0;
float TICK_TIME = 0.25;
float BLOWED_UP_TIME = 0.1;
uint32_t SKILL_ID = 317;
uint32_t BEHAVIOR_ID = 3719;
};

View File

@@ -0,0 +1,7 @@
#include "ActPlayerDeathTrigger.h"
void ActPlayerDeathTrigger::OnCollisionPhantom(Entity* self, Entity* target) {
if (!target->IsPlayer() || target->GetIsDead() || !target->GetPlayerReadyForUpdates()) return; //Don't kill already dead players or players not ready
target->Smash(self->GetObjectID(), eKillType::SILENT);
}

View File

@@ -0,0 +1,9 @@
#pragma once
#include "CppScripts.h"
class ActPlayerDeathTrigger : public CppScripts::Script
{
public:
void OnCollisionPhantom(Entity* self, Entity* target);
};

View File

@@ -0,0 +1,52 @@
#include "ActVehicleDeathTrigger.h"
#include "PossessableComponent.h"
#include "GameMessages.h"
#include "RacingControlComponent.h"
#include "dZoneManager.h"
#include "EntityManager.h"
#include "PossessorComponent.h"
void ActVehicleDeathTrigger::OnCollisionPhantom(Entity* self, Entity* target) {
auto* possessableComponent = target->GetComponent<PossessableComponent>();
Entity* vehicle;
Entity* player;
if (possessableComponent != nullptr) {
auto* player = EntityManager::Instance()->GetEntity(possessableComponent->GetPossessor());
if (player == nullptr) {
return;
}
return;
} else if (target->IsPlayer()) {
auto* possessorComponent = target->GetComponent<PossessorComponent>();
if (possessorComponent == nullptr) {
return;
}
vehicle = EntityManager::Instance()->GetEntity(possessorComponent->GetPossessable());
if (vehicle == nullptr) {
return;
}
player = target;
} else {
return;
}
GameMessages::SendDie(vehicle, self->GetObjectID(), LWOOBJID_EMPTY, true, VIOLENT, u"", 0, 0, 0, true, false, 0);
auto* zoneController = dZoneManager::Instance()->GetZoneControlObject();
auto* racingControlComponent = zoneController->GetComponent<RacingControlComponent>();
if (racingControlComponent != nullptr) {
racingControlComponent->OnRequestDie(player);
}
}

View File

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

View File

@@ -0,0 +1,12 @@
set(DSCRIPTS_SOURCES_AI_ACT
"ActMine.cpp"
"ActPlayerDeathTrigger.cpp"
"ActVehicleDeathTrigger.cpp")
add_subdirectory(FootRace)
foreach(file ${DSCRIPTS_SOURCES_AI_ACT_FOOTRACE})
set(DSCRIPTS_SOURCES_AI_ACT ${DSCRIPTS_SOURCES_AI_ACT} "FootRace/${file}")
endforeach()
set(DSCRIPTS_SOURCES_AI_ACT ${DSCRIPTS_SOURCES_AI_ACT} PARENT_SCOPE)

View File

@@ -0,0 +1,48 @@
#include "BaseFootRaceManager.h"
#include "EntityManager.h"
#include "Character.h"
void BaseFootRaceManager::OnStartup(Entity* self) {
// TODO: Add to FootRaceStarter group
}
void BaseFootRaceManager::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1,
int32_t param2, int32_t param3) {
const auto splitArguments = GeneralUtils::SplitString(args, '_');
if (splitArguments.size() > 1) {
const auto eventName = splitArguments[0];
const auto player = EntityManager::Instance()->GetEntity(std::stoull(splitArguments[1]));
if (player != nullptr) {
if (eventName == "updatePlayer") {
UpdatePlayer(self, player->GetObjectID());
} else if (IsPlayerInActivity(self, player->GetObjectID())) {
if (eventName == "initialActivityScore") {
auto* character = player->GetCharacter();
if (character != nullptr) {
character->SetPlayerFlag(115, true);
}
SetActivityScore(self, player->GetObjectID(), 1);
} else if (eventName == "updatePlayerTrue") {
auto* character = player->GetCharacter();
if (character != nullptr) {
character->SetPlayerFlag(115, false);
}
UpdatePlayer(self, player->GetObjectID(), true);
} else if (eventName == "PlayerWon") {
auto* character = player->GetCharacter();
if (character != nullptr) {
character->SetPlayerFlag(115, false);
if (param2 != -1) // Certain footraces set a flag
character->SetPlayerFlag(param2, true);
}
StopActivity(self, player->GetObjectID(), 0, param1);
}
}
}
}
}

View File

@@ -0,0 +1,9 @@
#pragma once
#include "ActivityManager.h"
#include "CppScripts.h"
class BaseFootRaceManager : public ActivityManager {
void OnStartup(Entity* self) override;
void OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
int32_t param3) override;
};

View File

@@ -0,0 +1,3 @@
set(DSCRIPTS_SOURCES_AI_ACT_FOOTRACE
"BaseFootRaceManager.cpp"
PARENT_SCOPE)

View File

@@ -0,0 +1,20 @@
#include "ActSharkPlayerDeathTrigger.h"
#include "MissionComponent.h"
#include "MissionTaskType.h"
#include "Entity.h"
void ActSharkPlayerDeathTrigger::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1,
int32_t param2, int32_t param3) {
if (args == "achieve") {
auto missionComponent = sender->GetComponent<MissionComponent>();
if (!missionComponent) return;
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_SCRIPT, 8419);
if (sender->GetIsDead() || !sender->GetPlayerReadyForUpdates()) return; //Don't kill already dead players or players not ready
if (sender->GetCharacter()) {
sender->Smash(self->GetObjectID(), eKillType::VIOLENT, u"big-shark-death");
}
}
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include "CppScripts.h"
class ActSharkPlayerDeathTrigger : public CppScripts::Script
{
public:
void OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
int32_t param3) override;
};

View File

@@ -0,0 +1,65 @@
#include "AgBusDoor.h"
#include "Entity.h"
#include "GameMessages.h"
#include "ProximityMonitorComponent.h"
void AgBusDoor::OnStartup(Entity* self) {
m_Counter = 0;
m_OuterCounter = 0;
self->SetProximityRadius(75, "busDoor");
self->SetProximityRadius(85, "busDoorOuter");
}
void AgBusDoor::OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) {
if (name != "busDoor" && name != "busDoorOuter") return;
// Make sure only humans are taken into account
if (!entering->GetCharacter()) return;
auto* proximityMonitorComponent = self->GetComponent<ProximityMonitorComponent>();
if (proximityMonitorComponent == nullptr) return;
m_Counter = 0;
m_OuterCounter = 0;
for (const auto& pair : proximityMonitorComponent->GetProximityObjects("busDoor")) {
auto* entity = EntityManager::Instance()->GetEntity(pair.first);
if (entity != nullptr && entity->IsPlayer()) m_Counter++;
}
for (const auto& pair : proximityMonitorComponent->GetProximityObjects("busDoorOuter")) {
auto* entity = EntityManager::Instance()->GetEntity(pair.first);
if (entity != nullptr && entity->IsPlayer()) m_OuterCounter++;
}
if (status == "ENTER") {
// move up when a player is inside both radii
if (m_Counter > 0) {
MoveDoor(self, true);
}
} else if (status == "LEAVE") {
// move down when no players are inside either radii
if (m_Counter <= 0) {
MoveDoor(self, false);
}
}
}
void AgBusDoor::MoveDoor(Entity* self, bool bOpen) {
if (bOpen) {
GameMessages::SendPlatformResync(self, UNASSIGNED_SYSTEM_ADDRESS, true, 1, 0);
} else {
GameMessages::SendPlatformResync(self, UNASSIGNED_SYSTEM_ADDRESS, true, 0, 1);
self->AddTimer("dustTimer", 2.0f);
}
//This is currently commented out because it might be the reason that people's audio is cutting out.
GameMessages::SendPlayNDAudioEmitter(self, UNASSIGNED_SYSTEM_ADDRESS, "{9a24f1fa-3177-4745-a2df-fbd996d6e1e3}");
}
void AgBusDoor::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "dustTimer") {
GameMessages::SendPlayFXEffect(self->GetObjectID(), 642, u"create", "busDust", LWOOBJID_EMPTY, 1.0f, 1.0f, true);
}
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include "CppScripts.h"
class AgBusDoor : public CppScripts::Script
{
public:
void OnStartup(Entity* self);
void OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status);
void OnTimerDone(Entity* self, std::string timerName);
private:
void MoveDoor(Entity* self, bool bOpen);
int m_Counter;
int m_OuterCounter;
};

View File

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

View File

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

83
dScripts/ai/AG/AgFans.cpp Normal file
View File

@@ -0,0 +1,83 @@
#include "AgFans.h"
#include "EntityManager.h"
#include "GameMessages.h"
#include "PhantomPhysicsComponent.h"
#include "RenderComponent.h"
void AgFans::OnStartup(Entity* self) {
self->SetVar<bool>(u"alive", true);
self->SetVar<bool>(u"on", false);
ToggleFX(self, false);
auto* renderComponent = static_cast<RenderComponent*>(self->GetComponent(COMPONENT_TYPE_RENDER));
if (renderComponent == nullptr) {
return;
}
renderComponent->PlayEffect(495, u"fanOn", "fanOn");
}
void AgFans::ToggleFX(Entity* self, bool hit) {
std::string fanGroup = self->GetGroups()[0];
std::vector<Entity*> fanVolumes = EntityManager::Instance()->GetEntitiesInGroup(fanGroup);
auto* renderComponent = static_cast<RenderComponent*>(self->GetComponent(COMPONENT_TYPE_RENDER));
if (renderComponent == nullptr) {
return;
}
if (fanVolumes.size() == 0 || !self->GetVar<bool>(u"alive")) return;
if (self->GetVar<bool>(u"on")) {
GameMessages::SendPlayAnimation(self, u"fan-off");
renderComponent->StopEffect("fanOn");
self->SetVar<bool>(u"on", false);
for (Entity* volume : fanVolumes) {
PhantomPhysicsComponent* volumePhys = static_cast<PhantomPhysicsComponent*>(volume->GetComponent(COMPONENT_TYPE_PHANTOM_PHYSICS));
if (!volumePhys) continue;
volumePhys->SetPhysicsEffectActive(false);
EntityManager::Instance()->SerializeEntity(volume);
if (!hit) {
Entity* fxObj = EntityManager::Instance()->GetEntitiesInGroup(fanGroup + "fx")[0];
GameMessages::SendPlayAnimation(fxObj, u"trigger");
}
}
} else if (!self->GetVar<bool>(u"on") && self->GetVar<bool>(u"alive")) {
GameMessages::SendPlayAnimation(self, u"fan-on");
renderComponent->PlayEffect(495, u"fanOn", "fanOn");
self->SetVar<bool>(u"on", true);
for (Entity* volume : fanVolumes) {
PhantomPhysicsComponent* volumePhys = static_cast<PhantomPhysicsComponent*>(volume->GetComponent(COMPONENT_TYPE_PHANTOM_PHYSICS));
if (!volumePhys) continue;
volumePhys->SetPhysicsEffectActive(true);
EntityManager::Instance()->SerializeEntity(volume);
if (!hit) {
Entity* fxObj = EntityManager::Instance()->GetEntitiesInGroup(fanGroup + "fx")[0];
GameMessages::SendPlayAnimation(fxObj, u"idle");
}
}
}
}
void AgFans::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
int32_t param3) {
if (args.length() == 0 || !self->GetVar<bool>(u"alive")) return;
if ((args == "turnOn" && self->GetVar<bool>(u"on")) || (args == "turnOff" && !self->GetVar<bool>(u"on"))) return;
ToggleFX(self, false);
}
void AgFans::OnDie(Entity* self, Entity* killer) {
if (self->GetVar<bool>(u"on")) {
ToggleFX(self, true);
}
self->SetVar<bool>(u"alive", false);
}

20
dScripts/ai/AG/AgFans.h Normal file
View File

@@ -0,0 +1,20 @@
#pragma once
#include "CppScripts.h"
class AgFans : public CppScripts::Script
{
public:
void OnStartup(Entity* self) override;
void OnDie(Entity* self, Entity* killer) override;
void OnFireEventServerSide(
Entity* self,
Entity* sender,
std::string args,
int32_t param1,
int32_t param2,
int32_t param3
) override;
private:
void ToggleFX(Entity* self, bool hit);
};

View File

@@ -0,0 +1,42 @@
#include "AgImagSmashable.h"
#include "EntityManager.h"
#include "GeneralUtils.h"
#include "GameMessages.h"
#include "DestroyableComponent.h"
void AgImagSmashable::OnDie(Entity* self, Entity* killer) {
bool maxImagGreaterThanZero = false;
if (killer) {
DestroyableComponent* dest = static_cast<DestroyableComponent*>(killer->GetComponent(COMPONENT_TYPE_DESTROYABLE));
if (dest) {
maxImagGreaterThanZero = dest->GetMaxImagination() > 0;
}
if (maxImagGreaterThanZero) {
int amount = GeneralUtils::GenerateRandomNumber<int>(0, 3);
for (int i = 0; i < amount; ++i) {
GameMessages::SendDropClientLoot(killer, self->GetObjectID(), 935, 0, self->GetPosition());
}
}
}
CrateAnimal(self);
}
void AgImagSmashable::CrateAnimal(Entity* self) {
int funnychance = GeneralUtils::GenerateRandomNumber<int>(0, 26);
if (funnychance == 1) {
EntityInfo info;
info.lot = 8114;
info.pos = self->GetPosition();
info.spawner = nullptr;
info.spawnerID = self->GetSpawnerID();
info.spawnerNodeID = 0;
Entity* newEntity = EntityManager::Instance()->CreateEntity(info, nullptr);
if (newEntity) {
EntityManager::Instance()->ConstructEntity(newEntity);
}
}
}

View File

@@ -0,0 +1,9 @@
#pragma once
#include "CppScripts.h"
class AgImagSmashable : public CppScripts::Script {
public:
void OnDie(Entity* self, Entity* killer);
private:
void CrateAnimal(Entity* self);
};

View File

@@ -0,0 +1,116 @@
#include "AgJetEffectServer.h"
#include "GameMessages.h"
#include "EntityManager.h"
#include "SkillComponent.h"
void AgJetEffectServer::OnUse(Entity* self, Entity* user) {
if (inUse) {
return;
}
GameMessages::SendNotifyClientObject(
self->GetObjectID(),
u"isInUse",
0,
0,
LWOOBJID_EMPTY,
"",
UNASSIGNED_SYSTEM_ADDRESS
);
inUse = true;
auto entities = EntityManager::Instance()->GetEntitiesInGroup("Jet_FX");
if (entities.empty()) {
return;
}
auto* effect = entities[0];
GameMessages::SendPlayFXEffect(effect, 641, u"create", "radarDish", LWOOBJID_EMPTY, 1, 1, true);
self->AddTimer("radarDish", 2);
self->AddTimer("CineDone", 9);
}
void AgJetEffectServer::OnRebuildComplete(Entity* self, Entity* target) {
auto entities = EntityManager::Instance()->GetEntitiesInGroup("Jet_FX");
if (entities.empty()) {
return;
}
auto* effect = entities[0];
auto groups = self->GetGroups();
if (groups.empty()) {
return;
}
builder = target->GetObjectID();
const auto group = groups[0];
GameMessages::SendPlayAnimation(effect, u"jetFX");
self->AddTimer("PlayEffect", 2.5f);
if (group == "Base_Radar") {
self->AddTimer("CineDone", 5);
}
}
void AgJetEffectServer::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "radarDish") {
GameMessages::SendStopFXEffect(self, true, "radarDish");
return;
}
if (timerName == "PlayEffect") {
auto entities = EntityManager::Instance()->GetEntitiesInGroup("mortarMain");
if (entities.empty()) {
return;
}
const auto size = entities.size();
if (size == 0) {
return;
}
const auto selected = GeneralUtils::GenerateRandomNumber<int>(0, size - 1);
auto* mortar = entities[selected];
Game::logger->Log("AgJetEffectServer", "Mortar (%i) (&d)", mortar->GetLOT(), mortar->HasComponent(COMPONENT_TYPE_SKILL));
mortar->SetOwnerOverride(builder);
SkillComponent* skillComponent;
if (!mortar->TryGetComponent(COMPONENT_TYPE_SKILL, skillComponent)) {
return;
}
skillComponent->CalculateBehavior(318, 3727, LWOOBJID_EMPTY, true);
return;
}
if (timerName == "CineDone") {
GameMessages::SendNotifyClientObject(
self->GetObjectID(),
u"toggleInUse",
-1,
0,
LWOOBJID_EMPTY,
"",
UNASSIGNED_SYSTEM_ADDRESS
);
inUse = false;
}
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include "CppScripts.h"
class AgJetEffectServer final : public CppScripts::Script
{
public:
void OnUse(Entity* self, Entity* user) override;
void OnRebuildComplete(Entity* self, Entity* target) override;
void OnTimerDone(Entity* self, std::string timerName) override;
private:
LWOOBJID builder;
bool inUse;
};

View File

@@ -0,0 +1,16 @@
#include "AgPicnicBlanket.h"
#include "GameMessages.h"
void AgPicnicBlanket::OnUse(Entity* self, Entity* user) {
GameMessages::SendTerminateInteraction(user->GetObjectID(), FROM_INTERACTION, self->GetObjectID());
if (self->GetVar<bool>(u"active"))
return;
self->SetVar<bool>(u"active", true);
auto lootTable = std::unordered_map<LOT, int32_t>{ {935, 3} };
LootGenerator::Instance().DropLoot(user, self, lootTable, 0, 0);
self->AddCallbackTimer(5.0f, [self]() {
self->SetVar<bool>(u"active", false);
});
}

View File

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

View File

@@ -0,0 +1,60 @@
#include "AgQbElevator.h"
#include "EntityManager.h"
#include "GameMessages.h"
void AgQbElevator::OnStartup(Entity* self) {
}
//when the QB is finished being built by a player
void AgQbElevator::OnRebuildComplete(Entity* self, Entity* target) {
self->SetProximityRadius(proxRadius, "elevatorProx");
self->SetI64(u"qbPlayer", target->GetObjectID());
float delayTime = killTime - endTime;
if (delayTime < 1) delayTime = 1;
GameMessages::SendPlatformResync(self, UNASSIGNED_SYSTEM_ADDRESS, true, 0,
0, 0, MovementPlatformState::Stationary);
//add a timer that will kill the QB if no players get on in the killTime
self->AddTimer("startKillTimer", killTime);
}
void AgQbElevator::OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) {
//make sure we haven't already started pathing.
if (self->GetBoolean(u"qbPlayerRdy")) return;
if (status == "ENTER") {
Entity* builder = EntityManager::Instance()->GetEntity(self->GetI64(u"qbPlayer"));
if (builder && builder == entering) {
//the builder has entered so cancel the start timer and just start moving
self->SetBoolean(u"qbPlayerRdy", true);
self->CancelTimer("StartElevator");
GameMessages::SendPlatformResync(self, UNASSIGNED_SYSTEM_ADDRESS, true, 0,
1, 1, MovementPlatformState::Moving);
} else if (!self->GetBoolean(u"StartTimer")) {
self->SetBoolean(u"StartTimer", true);
self->AddTimer("StartElevator", startTime);
}
}
}
void AgQbElevator::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "StartElevator") {
GameMessages::SendPlatformResync(self, UNASSIGNED_SYSTEM_ADDRESS, true, 0,
1, 1, MovementPlatformState::Moving);
} else if (timerName == "startKillTimer") {
killTimerStartup(self);
} else if (timerName == "KillTimer") {
self->Smash(self->GetObjectID(), VIOLENT);
}
}
void AgQbElevator::killTimerStartup(Entity* self) const {
self->CancelAllTimers();
self->AddTimer("KillTimer", endTime);
self->SetNetworkVar<float>(u"startEffect", endTime); // Blinking effect
}

View File

@@ -0,0 +1,19 @@
#pragma once
#include "CppScripts.h"
class AgQbElevator : public CppScripts::Script {
public:
void OnStartup(Entity* self) override;
void OnRebuildComplete(Entity* self, Entity* target) override;
void OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) override;
void OnTimerDone(Entity* self, std::string timerName) override;
private:
void killTimerStartup(Entity* self) const;
// constants
float endTime = 4.0f;
float startTime = 8.0f;
float killTime = 10.0f;
float proxRadius = 5.0f;
};

View File

@@ -0,0 +1,15 @@
#include "AgQbWall.h"
void AgQbWall::OnRebuildComplete(Entity* self, Entity* player) {
self->SetVar(u"player", player->GetObjectID());
auto targetWallSpawners = GeneralUtils::UTF16ToWTF8(self->GetVar<std::u16string>(u"spawner"));
if (targetWallSpawners != "") {
auto groupObjs = EntityManager::Instance()->GetEntitiesInGroup(targetWallSpawners);
for (auto* obj : groupObjs) {
if (obj) {
obj->SetVar(u"player", player->GetObjectID());
obj->OnFireEventServerSide(self, "spawnMobs");
}
}
}
}

View File

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

View File

@@ -0,0 +1,11 @@
#include "AgSalutingNpcs.h"
#include "GameMessages.h"
void AgSalutingNpcs::OnEmoteReceived(Entity* self, const int32_t emote, Entity* target) {
if (emote != 356) {
return;
}
GameMessages::SendPlayAnimation(self, u"salutePlayer");
}

View File

@@ -0,0 +1,8 @@
#pragma once
#include "CppScripts.h"
class AgSalutingNpcs final : public CppScripts::Script
{
public:
void OnEmoteReceived(Entity* self, int32_t emote, Entity* target) override;
};

View File

@@ -0,0 +1,8 @@
#include "AgShipPlayerDeathTrigger.h"
#include "Entity.h"
void AgShipPlayerDeathTrigger::OnCollisionPhantom(Entity* self, Entity* target) {
if (target->GetLOT() == 1 && !target->GetIsDead()) {
target->Smash(self->GetObjectID(), eKillType::VIOLENT, u"electro-shock-death");
}
}

View File

@@ -0,0 +1,9 @@
#pragma once
#include "CppScripts.h"
class AgShipPlayerDeathTrigger : public CppScripts::Script
{
public:
void OnCollisionPhantom(Entity* self, Entity* target);
};

View File

@@ -0,0 +1,20 @@
#include "AgShipPlayerShockServer.h"
#include "GameMessages.h"
void AgShipPlayerShockServer::OnUse(Entity* self, Entity* user) {
GameMessages::SendTerminateInteraction(user->GetObjectID(), eTerminateType::FROM_INTERACTION, self->GetObjectID());
if (active) {
return;
}
active = true;
GameMessages::SendPlayAnimation(user, shockAnim);
GameMessages::SendKnockback(user->GetObjectID(), self->GetObjectID(), self->GetObjectID(), 0, NiPoint3(-20, 10, -20));
GameMessages::SendPlayFXEffect(self, 1430, u"create", "console_sparks", LWOOBJID_EMPTY, 1.0, 1.0, true);
self->AddTimer("FXTime", fxTime);
}
void AgShipPlayerShockServer::OnTimerDone(Entity* self, std::string timerName) {
GameMessages::SendStopFXEffect(self, true, "console_sparks");
active = false;
}

View File

@@ -0,0 +1,14 @@
#pragma once
#include "CppScripts.h"
class AgShipPlayerShockServer : public CppScripts::Script
{
public:
void OnUse(Entity* self, Entity* user);
void OnTimerDone(Entity* self, std::string timerName);
private:
std::u16string shockAnim = u"knockback-recovery";
float fxTime = 2.0;
bool active = false;
};

View File

@@ -0,0 +1,103 @@
#include "AgSpaceStuff.h"
#include "GeneralUtils.h"
#include "GameMessages.h"
#include "EntityManager.h"
void AgSpaceStuff::OnStartup(Entity* self) {
self->AddTimer("FloaterScale", 5.0f);
EntityInfo info{};
info.pos = { -418, 585, -30 };
info.lot = 33;
info.spawnerID = self->GetObjectID();
auto* ref = EntityManager::Instance()->CreateEntity(info);
EntityManager::Instance()->ConstructEntity(ref);
self->SetVar(u"ShakeObject", ref->GetObjectID());
self->AddTimer("ShipShakeIdle", 2.0f);
self->SetVar(u"RandomTime", 10);
}
void AgSpaceStuff::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "FloaterScale") {
int scaleType = GeneralUtils::GenerateRandomNumber<int>(1, 5);
GameMessages::SendPlayAnimation(self, u"scale_0" + GeneralUtils::to_u16string(scaleType));
self->AddTimer("FloaterPath", 0.4);
} else if (timerName == "FloaterPath") {
int pathType = GeneralUtils::GenerateRandomNumber<int>(1, 4);
int randTime = GeneralUtils::GenerateRandomNumber<int>(20, 25);
GameMessages::SendPlayAnimation(self, u"path_0" + (GeneralUtils::to_u16string(pathType)));
self->AddTimer("FloaterScale", randTime);
} else if (timerName == "ShipShakeExplode") {
DoShake(self, true);
} else if (timerName == "ShipShakeIdle") {
DoShake(self, false);
}
}
void AgSpaceStuff::DoShake(Entity* self, bool explodeIdle) {
if (!explodeIdle) {
auto* ref = EntityManager::Instance()->GetEntity(self->GetVar<LWOOBJID>(u"ShakeObject"));
const auto randomTime = self->GetVar<int>(u"RandomTime");
auto time = GeneralUtils::GenerateRandomNumber<int>(0, randomTime + 1);
if (time < randomTime / 2) {
time += randomTime / 2;
}
self->AddTimer("ShipShakeIdle", static_cast<float>(time));
if (ref)
GameMessages::SendPlayEmbeddedEffectOnAllClientsNearObject(ref, FXName, ref->GetObjectID(), 500.0f);
auto* debrisObject = GetEntityInGroup(DebrisFX);
if (debrisObject)
GameMessages::SendPlayFXEffect(debrisObject, -1, u"DebrisFall", "Debris", LWOOBJID_EMPTY, 1.0f, 1.0f, true);
const auto randomFx = GeneralUtils::GenerateRandomNumber<int>(0, 3);
auto* shipFxObject = GetEntityInGroup(ShipFX);
if (shipFxObject) {
std::string effectType = "shipboom" + std::to_string(randomFx);
GameMessages::SendPlayFXEffect(shipFxObject, 559, GeneralUtils::ASCIIToUTF16(effectType), "FX", LWOOBJID_EMPTY, 1.0f, 1.0f, true);
}
self->AddTimer("ShipShakeExplode", 5.0f);
auto* shipFxObject2 = GetEntityInGroup(ShipFX2);
if (shipFxObject2)
GameMessages::SendPlayAnimation(shipFxObject2, u"explosion");
} else {
auto* shipFxObject = GetEntityInGroup(ShipFX);
auto* shipFxObject2 = GetEntityInGroup(ShipFX2);
if (shipFxObject)
GameMessages::SendPlayAnimation(shipFxObject, u"idle");
if (shipFxObject2)
GameMessages::SendPlayAnimation(shipFxObject2, u"idle");
}
}
Entity* AgSpaceStuff::GetEntityInGroup(const std::string& group) {
auto entities = EntityManager::Instance()->GetEntitiesInGroup(group);
Entity* en = nullptr;
for (auto entity : entities) {
if (entity) {
en = entity;
break;
}
}
return en;
}

View File

@@ -0,0 +1,18 @@
#pragma once
#include "CppScripts.h"
class AgSpaceStuff : public CppScripts::Script {
public:
void OnStartup(Entity* self);
void OnTimerDone(Entity* self, std::string timerName);
void DoShake(Entity* self, bool explodeIdle);
std::string DebrisFX = "DebrisFX";
std::string ShipFX = "ShipFX";
std::string ShipFX2 = "ShipFX2";
std::u16string FXName = u"camshake-bridge";
private:
Entity* GetEntityInGroup(const std::string& group);
};

View File

@@ -0,0 +1,16 @@
#include "AgStagePlatforms.h"
#include "MovingPlatformComponent.h"
void AgStagePlatforms::OnStartup(Entity* self) {
auto* component = self->GetComponent<MovingPlatformComponent>();
if (component) {
component->SetNoAutoStart(true);
component->StopPathing();
}
}
void AgStagePlatforms::OnWaypointReached(Entity* self, uint32_t waypointIndex) {
auto* component = self->GetComponent<MovingPlatformComponent>();
if (waypointIndex == 0 && component)
component->StopPathing();
}

View File

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

View File

@@ -0,0 +1,16 @@
#include "AgStromlingProperty.h"
#include "MovementAIComponent.h"
void AgStromlingProperty::OnStartup(Entity* self) {
auto movementInfo = MovementAIInfo{
"Wander",
71,
3,
100,
1,
4
};
auto* movementAIComponent = new MovementAIComponent(self, movementInfo);
self->AddComponent(COMPONENT_TYPE_MOVEMENT_AI, movementAIComponent);
}

View File

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

View File

@@ -0,0 +1,17 @@
#include "AgTurret.h"
#include "GameMessages.h"
void AgTurret::OnStartup(Entity* self) {
// TODO: do this legit way
self->AddTimer("killTurret", 20.0f);
}
void AgTurret::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "killTurret") {
self->ScheduleKillAfterUpdate();
}
}
void AgTurret::OnRebuildStart(Entity* self, Entity* user) {
GameMessages::SendLockNodeRotation(self, "base");
}

View File

@@ -0,0 +1,8 @@
#pragma once
#include "CppScripts.h"
class AgTurret : public CppScripts::Script {
void OnStartup(Entity* self);
void OnTimerDone(Entity* self, std::string timerName);
void OnRebuildStart(Entity* self, Entity* user);
};

View File

@@ -0,0 +1,18 @@
set(DSCRIPTS_SOURCES_AI_AG
"AgShipPlayerDeathTrigger.cpp"
"AgSpaceStuff.cpp"
"AgShipPlayerShockServer.cpp"
"AgImagSmashable.cpp"
"ActSharkPlayerDeathTrigger.cpp"
"AgBusDoor.cpp"
"AgTurret.cpp"
"AgFans.cpp"
"AgSalutingNpcs.cpp"
"AgJetEffectServer.cpp"
"AgQbElevator.cpp"
"AgStromlingProperty.cpp"
"AgDarkSpiderling.cpp"
"AgPicnicBlanket.cpp"
"AgStagePlatforms.cpp"
"AgQbWall.cpp"
PARENT_SCOPE)

View File

@@ -0,0 +1,81 @@
set(DSCRIPTS_SOURCES_AI)
add_subdirectory(ACT)
foreach(file ${DSCRIPTS_SOURCES_AI_ACT})
set(DSCRIPTS_SOURCES_AI ${DSCRIPTS_SOURCES_AI} "ACT/${file}")
endforeach()
add_subdirectory(AG)
foreach(file ${DSCRIPTS_SOURCES_AI_AG})
set(DSCRIPTS_SOURCES_AI ${DSCRIPTS_SOURCES_AI} "AG/${file}")
endforeach()
add_subdirectory(FV)
foreach(file ${DSCRIPTS_SOURCES_AI_FV})
set(DSCRIPTS_SOURCES_AI ${DSCRIPTS_SOURCES_AI} "FV/${file}")
endforeach()
add_subdirectory(GENERAL)
foreach(file ${DSCRIPTS_SOURCES_AI_GENERAL})
set(DSCRIPTS_SOURCES_AI ${DSCRIPTS_SOURCES_AI} "GENERAL/${file}")
endforeach()
add_subdirectory(GF)
foreach(file ${DSCRIPTS_SOURCES_AI_GF})
set(DSCRIPTS_SOURCES_AI ${DSCRIPTS_SOURCES_AI} "GF/${file}")
endforeach()
add_subdirectory(MINIGAME)
foreach(file ${DSCRIPTS_SOURCES_AI_MINIGAME})
set(DSCRIPTS_SOURCES_AI ${DSCRIPTS_SOURCES_AI} "MINIGAME/${file}")
endforeach()
add_subdirectory(NP)
foreach(file ${DSCRIPTS_SOURCES_AI_NP})
set(DSCRIPTS_SOURCES_AI ${DSCRIPTS_SOURCES_AI} "NP/${file}")
endforeach()
add_subdirectory(NS)
foreach(file ${DSCRIPTS_SOURCES_AI_NS})
set(DSCRIPTS_SOURCES_AI ${DSCRIPTS_SOURCES_AI} "NS/${file}")
endforeach()
add_subdirectory(PETS)
foreach(file ${DSCRIPTS_SOURCES_AI_PETS})
set(DSCRIPTS_SOURCES_AI ${DSCRIPTS_SOURCES_AI} "PETS/${file}")
endforeach()
add_subdirectory(PROPERTY)
foreach(file ${DSCRIPTS_SOURCES_AI_PROPERTY})
set(DSCRIPTS_SOURCES_AI ${DSCRIPTS_SOURCES_AI} "PROPERTY/${file}")
endforeach()
add_subdirectory(RACING)
foreach(file ${DSCRIPTS_SOURCES_AI_RACING})
set(DSCRIPTS_SOURCES_AI ${DSCRIPTS_SOURCES_AI} "RACING/${file}")
endforeach()
add_subdirectory(SPEC)
foreach(file ${DSCRIPTS_SOURCES_AI_SPEC})
set(DSCRIPTS_SOURCES_AI ${DSCRIPTS_SOURCES_AI} "SPEC/${file}")
endforeach()
add_subdirectory(WILD)
foreach(file ${DSCRIPTS_SOURCES_AI_WILD})
set(DSCRIPTS_SOURCES_AI ${DSCRIPTS_SOURCES_AI} "WILD/${file}")
endforeach()
set(DSCRIPTS_SOURCES_AI ${DSCRIPTS_SOURCES_AI} PARENT_SCOPE)

View File

@@ -0,0 +1,17 @@
#include "ActNinjaTurret.h"
void ActNinjaTurret::OnRebuildNotifyState(Entity* self, eRebuildState state) {
if (state == eRebuildState::REBUILD_COMPLETED) {
self->SetVar(u"AmBuilt", true);
} else if (state == eRebuildState::REBUILD_RESETTING) {
self->SetVar(u"AmBuilt", false);
}
}
void
ActNinjaTurret::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
int32_t param3) {
if (args == "ISpawned" && self->GetVar<bool>(u"AmBuilt")) {
sender->Smash();
}
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include "CppScripts.h"
class ActNinjaTurret : public CppScripts::Script
{
public:
void OnRebuildNotifyState(Entity* self, eRebuildState state) override;
void OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
int32_t param3) override;
};

View File

@@ -0,0 +1,61 @@
#include "ActParadoxPipeFix.h"
#include "EntityManager.h"
#include "RebuildComponent.h"
#include "GameMessages.h"
#include "MissionComponent.h"
void ActParadoxPipeFix::OnRebuildComplete(Entity* self, Entity* target) {
const auto myGroup = "AllPipes";
const auto groupObjs = EntityManager::Instance()->GetEntitiesInGroup(myGroup);
auto indexCount = 0;
self->SetVar(u"PlayerID", target->GetObjectID());
for (auto* object : groupObjs) {
if (object == self) {
continue;
}
auto* rebuildComponent = object->GetComponent<RebuildComponent>();
if (rebuildComponent->GetState() == REBUILD_COMPLETED) {
indexCount++;
}
}
if (indexCount >= 2) {
const auto refinery = EntityManager::Instance()->GetEntitiesInGroup("Paradox");
if (!refinery.empty()) {
GameMessages::SendPlayFXEffect(refinery[0]->GetObjectID(), 3999, u"create", "pipeFX");
}
for (auto* object : groupObjs) {
auto* player = EntityManager::Instance()->GetEntity(object->GetVar<LWOOBJID>(u"PlayerID"));
if (player != nullptr) {
auto* missionComponent = player->GetComponent<MissionComponent>();
if (missionComponent != nullptr) {
missionComponent->ForceProgressTaskType(769, 1, 1, false);
}
GameMessages::SendPlayCinematic(player->GetObjectID(), u"ParadoxPipeFinish", player->GetSystemAddress(), true, true, false, false, 0, false, 2.0f);
}
object->SetVar(u"PlayerID", LWOOBJID_EMPTY);
}
}
}
void ActParadoxPipeFix::OnRebuildNotifyState(Entity* self, eRebuildState state) {
if (state == REBUILD_RESETTING) {
const auto refinery = EntityManager::Instance()->GetEntitiesInGroup("Paradox");
if (!refinery.empty()) {
GameMessages::SendStopFXEffect(refinery[0], true, "pipeFX");
}
}
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include "CppScripts.h"
class ActParadoxPipeFix : public CppScripts::Script
{
public:
void OnRebuildComplete(Entity* self, Entity* target) override;
void OnRebuildNotifyState(Entity* self, eRebuildState state) override;
};

View File

@@ -0,0 +1,18 @@
set(DSCRIPTS_SOURCES_AI_FV
"ActNinjaTurret.cpp"
"FvFlyingCreviceDragon.cpp"
"FvDragonSmashingGolemQb.cpp"
"FvFreeGfNinjas.cpp"
"FvPandaSpawnerServer.cpp"
"FvPandaServer.cpp"
"FvBrickPuzzleServer.cpp"
"FvConsoleLeftQuickbuild.cpp"
"FvConsoleRightQuickbuild.cpp"
"FvFacilityBrick.cpp"
"FvFacilityPipes.cpp"
"ActParadoxPipeFix.cpp"
"FvNinjaGuard.cpp"
"FvPassThroughWall.cpp"
"FvBounceOverWall.cpp"
"FvMaelstromGeyser.cpp"
PARENT_SCOPE)

View File

@@ -0,0 +1,10 @@
#include "FvBounceOverWall.h"
#include "MissionComponent.h"
void FvBounceOverWall::OnCollisionPhantom(Entity* self, Entity* target) {
auto missionComponent = target->GetComponent<MissionComponent>();
if (missionComponent == nullptr) return;
// We force progress here to the Gate Crasher mission due to an overlap in LOTs with the 'Shark Bite' missions.
missionComponent->ForceProgress(GateCrasherMissionId, GateCrasherMissionUid, 1);
}

View File

@@ -0,0 +1,22 @@
#pragma once
#include "CppScripts.h"
class FvBounceOverWall : public CppScripts::Script
{
/**
* @brief When a collision has been made with self this method is called.
*
* @param self The Entity that called this function.
* @param target The target Entity of self.
*/
void OnCollisionPhantom(Entity* self, Entity* target) override;
private:
/**
* MissionId for the Gate Crasher mission.
*/
int32_t GateCrasherMissionId = 849;
/**
* MissionUid for the Gate Crasher mission.
*/
int32_t GateCrasherMissionUid = 1241;
};

View File

@@ -0,0 +1,68 @@
#include "FvBrickPuzzleServer.h"
#include "GeneralUtils.h"
#include "dZoneManager.h"
#include "Spawner.h"
#include "RebuildComponent.h"
void FvBrickPuzzleServer::OnStartup(Entity* self) {
const auto myGroup = GeneralUtils::UTF16ToWTF8(self->GetVar<std::u16string>(u"spawner_name"));
int32_t pipeNum = 0;
if (!GeneralUtils::TryParse<int32_t>(myGroup.substr(10, 1), pipeNum)) {
return;
}
if (pipeNum != 1) {
self->AddTimer("reset", 30);
}
}
void FvBrickPuzzleServer::OnDie(Entity* self, Entity* killer) {
const auto myGroup = GeneralUtils::UTF16ToWTF8(self->GetVar<std::u16string>(u"spawner_name"));
int32_t pipeNum = 0;
if (!GeneralUtils::TryParse<int32_t>(myGroup.substr(10, 1), pipeNum)) {
return;
}
const auto pipeGroup = myGroup.substr(0, 10);
const auto nextPipeNum = pipeNum + 1;
const auto samePipeSpawners = dZoneManager::Instance()->GetSpawnersByName(myGroup);
if (!samePipeSpawners.empty()) {
samePipeSpawners[0]->SoftReset();
samePipeSpawners[0]->Deactivate();
}
if (killer != nullptr && killer->IsPlayer()) {
const auto nextPipe = pipeGroup + std::to_string(nextPipeNum);
const auto nextPipeSpawners = dZoneManager::Instance()->GetSpawnersByName(nextPipe);
if (!nextPipeSpawners.empty()) {
nextPipeSpawners[0]->Activate();
}
} else {
const auto nextPipe = pipeGroup + "1";
const auto firstPipeSpawners = dZoneManager::Instance()->GetSpawnersByName(nextPipe);
if (!firstPipeSpawners.empty()) {
firstPipeSpawners[0]->Activate();
}
}
}
void FvBrickPuzzleServer::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "reset") {
auto* rebuildComponent = self->GetComponent<RebuildComponent>();
if (rebuildComponent != nullptr && rebuildComponent->GetState() == REBUILD_OPEN) {
self->Smash(self->GetObjectID(), SILENT);
}
}
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include "CppScripts.h"
class FvBrickPuzzleServer : public CppScripts::Script
{
public:
void OnStartup(Entity* self) override;
void OnDie(Entity* self, Entity* killer) override;
void OnTimerDone(Entity* self, std::string timerName) override;
};

View File

@@ -0,0 +1,47 @@
#include "FvConsoleLeftQuickbuild.h"
#include "EntityManager.h"
#include "GameMessages.h"
void FvConsoleLeftQuickbuild::OnStartup(Entity* self) {
self->SetVar(u"IAmBuilt", false);
self->SetVar(u"AmActive", false);
}
void FvConsoleLeftQuickbuild::OnRebuildNotifyState(Entity* self, eRebuildState state) {
if (state == REBUILD_COMPLETED) {
self->SetVar(u"IAmBuilt", true);
const auto objects = EntityManager::Instance()->GetEntitiesInGroup("Facility");
if (!objects.empty()) {
objects[0]->NotifyObject(self, "ConsoleLeftUp");
}
} else if (state == REBUILD_RESETTING) {
self->SetVar(u"IAmBuilt", false);
self->SetVar(u"AmActive", false);
const auto objects = EntityManager::Instance()->GetEntitiesInGroup("Facility");
if (!objects.empty()) {
objects[0]->NotifyObject(self, "ConsoleLeftDown");
}
}
}
void FvConsoleLeftQuickbuild::OnUse(Entity* self, Entity* user) {
if (self->GetVar<bool>(u"AmActive")) {
return;
}
if (self->GetVar<bool>(u"IAmBuilt")) {
self->SetVar(u"AmActive", true);
const auto objects = EntityManager::Instance()->GetEntitiesInGroup("Facility");
if (!objects.empty()) {
objects[0]->NotifyObject(self, "ConsoleLeftActive");
}
}
GameMessages::SendTerminateInteraction(user->GetObjectID(), FROM_INTERACTION, self->GetObjectID());
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include "CppScripts.h"
class FvConsoleLeftQuickbuild : public CppScripts::Script
{
public:
void OnStartup(Entity* self) override;
void OnRebuildNotifyState(Entity* self, eRebuildState state) override;
void OnUse(Entity* self, Entity* user) override;
};

View File

@@ -0,0 +1,47 @@
#include "FvConsoleRightQuickbuild.h"
#include "EntityManager.h"
#include "GameMessages.h"
void FvConsoleRightQuickbuild::OnStartup(Entity* self) {
self->SetVar(u"IAmBuilt", false);
self->SetVar(u"AmActive", false);
}
void FvConsoleRightQuickbuild::OnRebuildNotifyState(Entity* self, eRebuildState state) {
if (state == REBUILD_COMPLETED) {
self->SetVar(u"IAmBuilt", true);
const auto objects = EntityManager::Instance()->GetEntitiesInGroup("Facility");
if (!objects.empty()) {
objects[0]->NotifyObject(self, "ConsoleRightUp");
}
} else if (state == REBUILD_RESETTING) {
self->SetVar(u"IAmBuilt", false);
self->SetVar(u"AmActive", false);
const auto objects = EntityManager::Instance()->GetEntitiesInGroup("Facility");
if (!objects.empty()) {
objects[0]->NotifyObject(self, "ConsoleRightDown");
}
}
}
void FvConsoleRightQuickbuild::OnUse(Entity* self, Entity* user) {
if (self->GetVar<bool>(u"AmActive")) {
return;
}
if (self->GetVar<bool>(u"IAmBuilt")) {
self->SetVar(u"AmActive", true);
const auto objects = EntityManager::Instance()->GetEntitiesInGroup("Facility");
if (!objects.empty()) {
objects[0]->NotifyObject(self, "ConsoleRightActive");
}
}
GameMessages::SendTerminateInteraction(user->GetObjectID(), FROM_INTERACTION, self->GetObjectID());
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include "CppScripts.h"
class FvConsoleRightQuickbuild : public CppScripts::Script
{
public:
void OnStartup(Entity* self) override;
void OnRebuildNotifyState(Entity* self, eRebuildState state) override;
void OnUse(Entity* self, Entity* user) override;
};

View File

@@ -0,0 +1,30 @@
#include "FvDragonSmashingGolemQb.h"
#include "GameMessages.h"
#include "EntityManager.h"
void FvDragonSmashingGolemQb::OnStartup(Entity* self) {
self->AddTimer("GolemBreakTimer", 10.5f);
}
void FvDragonSmashingGolemQb::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "GolemBreakTimer") {
self->Smash();
}
}
void FvDragonSmashingGolemQb::OnRebuildNotifyState(Entity* self, eRebuildState state) {
if (state == eRebuildState::REBUILD_COMPLETED) {
GameMessages::SendPlayAnimation(self, u"dragonsmash");
const auto dragonId = self->GetVar<LWOOBJID>(u"Dragon");
auto* dragon = EntityManager::Instance()->GetEntity(dragonId);
if (dragon != nullptr) {
dragon->OnFireEventServerSide(self, "rebuildDone");
}
self->CancelTimer("GolemBreakTimer");
self->AddTimer("GolemBreakTimer", 10.5f);
}
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include "CppScripts.h"
class FvDragonSmashingGolemQb : public CppScripts::Script
{
public:
void OnStartup(Entity* self) override;
void OnTimerDone(Entity* self, std::string timerName) override;
void OnRebuildNotifyState(Entity* self, eRebuildState state) override;
};

View File

@@ -0,0 +1,97 @@
#include "FvFacilityBrick.h"
#include "GameMessages.h"
#include "dZoneManager.h"
#include "EntityManager.h"
void FvFacilityBrick::OnStartup(Entity* self) {
self->SetVar(u"ConsoleLEFTActive", false);
self->SetVar(u"ConsoleRIGHTtActive", false);
}
void FvFacilityBrick::OnNotifyObject(Entity* self, Entity* sender, const std::string& name, int32_t param1, int32_t param2) {
auto* brickSpawner = dZoneManager::Instance()->GetSpawnersByName("ImaginationBrick")[0];
auto* bugSpawner = dZoneManager::Instance()->GetSpawnersByName("MaelstromBug")[0];
auto* canisterSpawner = dZoneManager::Instance()->GetSpawnersByName("BrickCanister")[0];
if (name == "ConsoleLeftUp") {
GameMessages::SendStopFXEffect(self, true, "LeftPipeOff");
GameMessages::SendPlayFXEffect(self->GetObjectID(), 2775, u"create", "LeftPipeEnergy");
} else if (name == "ConsoleLeftDown") {
self->SetVar(u"ConsoleLEFTActive", false);
GameMessages::SendStopFXEffect(self, true, "LeftPipeEnergy");
GameMessages::SendStopFXEffect(self, true, "LeftPipeOn");
GameMessages::SendPlayFXEffect(self->GetObjectID(), 2774, u"create", "LeftPipeOff");
} else if (name == "ConsoleLeftActive") {
self->SetVar(u"ConsoleLEFTActive", true);
GameMessages::SendStopFXEffect(self, true, "LeftPipeEnergy");
GameMessages::SendPlayFXEffect(self->GetObjectID(), 2776, u"create", "LeftPipeOn");
}
else if (name == "ConsoleRightUp") {
GameMessages::SendStopFXEffect(self, true, "RightPipeOff");
GameMessages::SendPlayFXEffect(self->GetObjectID(), 2778, u"create", "RightPipeEnergy");
} else if (name == "ConsoleRightDown") {
self->SetVar(u"ConsoleRIGHTActive", false);
GameMessages::SendStopFXEffect(self, true, "RightPipeEnergy");
GameMessages::SendStopFXEffect(self, true, "RightPipeOn");
GameMessages::SendPlayFXEffect(self->GetObjectID(), 2777, u"create", "RightPipeOff");
} else if (name == "ConsoleRightActive") {
self->SetVar(u"ConsoleRIGHTActive", true);
GameMessages::SendStopFXEffect(self, true, "RightPipeOff");
GameMessages::SendPlayFXEffect(self->GetObjectID(), 2779, u"create", "RightPipeEnergy");
}
if (self->GetVar<bool>(u"ConsoleLEFTActive") && self->GetVar<bool>(u"ConsoleRIGHTActive")) {
auto* object = EntityManager::Instance()->GetEntitiesInGroup("Brick")[0];
if (object != nullptr) {
GameMessages::SendPlayFXEffect(object->GetObjectID(), 122, u"create", "bluebrick");
GameMessages::SendPlayFXEffect(object->GetObjectID(), 1034, u"cast", "imaginationexplosion");
}
object = EntityManager::Instance()->GetEntitiesInGroup("Canister")[0];
if (object != nullptr) {
object->Smash(self->GetObjectID(), SILENT);
}
canisterSpawner->Reset();
canisterSpawner->Deactivate();
} else if (self->GetVar<bool>(u"ConsoleLEFTActive") || self->GetVar<bool>(u"ConsoleRIGHTActive")) {
brickSpawner->Activate();
auto* object = EntityManager::Instance()->GetEntitiesInGroup("Brick")[0];
if (object != nullptr) {
GameMessages::SendStopFXEffect(object, true, "bluebrick");
}
bugSpawner->Reset();
bugSpawner->Deactivate();
canisterSpawner->Reset();
canisterSpawner->Activate();
} else {
brickSpawner->Reset();
brickSpawner->Deactivate();
bugSpawner->Reset();
bugSpawner->Activate();
}
}
void FvFacilityBrick::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
int32_t param3) {
if (args != "PlayFX") {
return;
}
GameMessages::SendPlayFXEffect(self->GetObjectID(), 2774, u"create", "LeftPipeOff");
GameMessages::SendPlayFXEffect(self->GetObjectID(), 2777, u"create", "RightPipeOff");
GameMessages::SendPlayFXEffect(self->GetObjectID(), 2750, u"create", "imagination_canister");
GameMessages::SendPlayFXEffect(self->GetObjectID(), 2751, u"create", "canister_light_filler");
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include "CppScripts.h"
class FvFacilityBrick : public CppScripts::Script
{
public:
void OnStartup(Entity* self) override;
void OnNotifyObject(Entity* self, Entity* sender, const std::string& name, int32_t param1 = 0, int32_t param2 = 0) override;
void OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
int32_t param3) override;
};

View File

@@ -0,0 +1,10 @@
#include "FvFacilityPipes.h"
#include "GameMessages.h"
void FvFacilityPipes::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2, int32_t param3) {
if (args == "startFX") {
GameMessages::SendPlayFXEffect(self->GetObjectID(), m_LeftPipeEffectID, m_EffectType, m_LeftPipeEffectName);
GameMessages::SendPlayFXEffect(self->GetObjectID(), m_RightPipeEffectID, m_EffectType, m_RightPipeEffectName);
GameMessages::SendPlayFXEffect(self->GetObjectID(), m_ImaginationCanisterEffectID, m_EffectType, m_ImaginationCanisterEffectName);
}
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include "CppScripts.h"
class FvFacilityPipes : public CppScripts::Script {
public:
void OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2, int32_t param3) override;
private:
const std::u16string m_EffectType = u"create";
const std::string m_LeftPipeEffectName = "LeftPipeOff";
const int32_t m_LeftPipeEffectID = 2774;
const std::string m_RightPipeEffectName = "RightPipeOff";
const int32_t m_RightPipeEffectID = 2777;
const std::string m_ImaginationCanisterEffectName = "imagination_canister";
const int32_t m_ImaginationCanisterEffectID = 2750;
};

View File

@@ -0,0 +1,107 @@
#include "FvFlyingCreviceDragon.h"
#include "GameMessages.h"
#include "EntityManager.h"
#include "SkillComponent.h"
#include "GeneralUtils.h"
void FvFlyingCreviceDragon::OnStartup(Entity* self) {
self->AddTimer("waypoint", 5);
}
void FvFlyingCreviceDragon::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "waypoint") {
auto point = self->GetVar<int32_t>(u"waypoint");
if (point >= 20) {
point = 0;
}
self->SetVar<int32_t>(u"waypoint", point + 1);
self->AddTimer("waypoint", 5);
OnArrived(self);
return;
}
std::string groupName = "";
if (timerName == "platform1attack") {
groupName = "dragonFireballs1";
} else if (timerName == "platform3attack") {
groupName = "dragonFireballs3";
}
const auto& group = EntityManager::Instance()->GetEntitiesInGroup(groupName);
if (group.empty()) {
return;
}
auto* skillComponent = group[0]->GetComponent<SkillComponent>();
if (skillComponent != nullptr) {
skillComponent->CalculateBehavior(762, 12506, LWOOBJID_EMPTY, true);
}
auto minionCount = 1;
for (size_t i = 1; i < group.size(); i++) {
if (minionCount == 4) {
return;
}
if (/*GeneralUtils::GenerateRandomNumber<int32_t>(1, 5) > 3*/ true) {
skillComponent = group[i]->GetComponent<SkillComponent>();
if (skillComponent != nullptr) {
skillComponent->CalculateBehavior(762, 12506, LWOOBJID_EMPTY);
++minionCount;
}
}
}
}
void FvFlyingCreviceDragon::OnArrived(Entity* self) {
auto point = self->GetVar<int32_t>(u"waypoint");
if (point == 4) {
GameMessages::SendPlayAnimation(self, u"attack1", 2);
self->AddTimer("platform1attack", 1.75f);
} else if (point == 12) {
GameMessages::SendPlayAnimation(self, u"attack2", 2);
const auto& group2 = EntityManager::Instance()->GetEntitiesInGroup("dragonFireballs2");
if (group2.empty()) {
return;
}
auto* skillComponent = group2[0]->GetComponent<SkillComponent>();
if (skillComponent != nullptr) {
skillComponent->CalculateBehavior(762, 12506, LWOOBJID_EMPTY);
}
auto minionCount = 1;
for (size_t i = 1; i < group2.size(); i++) {
if (minionCount == 4) {
return;
}
if (GeneralUtils::GenerateRandomNumber<int32_t>(1, 5) > 3) {
skillComponent = group2[i]->GetComponent<SkillComponent>();
if (skillComponent != nullptr) {
skillComponent->CalculateBehavior(762, 12506, LWOOBJID_EMPTY, true);
++minionCount;
}
}
}
} else if (point == 16) {
GameMessages::SendPlayAnimation(self, u"attack3", 2);
self->AddTimer("platform3attack", 0.5f);
}
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include "CppScripts.h"
class FvFlyingCreviceDragon : public CppScripts::Script
{
public:
void OnStartup(Entity* self) override;
void OnTimerDone(Entity* self, std::string timerName) override;
void OnArrived(Entity* self);
};

View File

@@ -0,0 +1,42 @@
#include "FvFreeGfNinjas.h"
#include "Character.h"
#include "MissionComponent.h"
void FvFreeGfNinjas::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState) {
if (missionID == 705 && missionState == MissionState::MISSION_STATE_AVAILABLE) {
auto* missionComponent = target->GetComponent<MissionComponent>();
if (missionComponent == nullptr)
return;
missionComponent->AcceptMission(701);
missionComponent->AcceptMission(702);
missionComponent->AcceptMission(703);
missionComponent->AcceptMission(704);
auto* character = target->GetCharacter();
if (character != nullptr)
character->SetPlayerFlag(68, true);
} else if (missionID == 786) {
auto* character = target->GetCharacter();
if (character != nullptr)
character->SetPlayerFlag(81, true);
}
}
void FvFreeGfNinjas::OnUse(Entity* self, Entity* user) {
// To allow player who already have the mission to progress.
auto* missionComponent = user->GetComponent<MissionComponent>();
if (missionComponent == nullptr)
return;
if (missionComponent->GetMissionState(705) == MissionState::MISSION_STATE_ACTIVE) {
auto* character = user->GetCharacter();
if (character != nullptr)
character->SetPlayerFlag(68, true);
missionComponent->AcceptMission(701, true);
missionComponent->AcceptMission(702, true);
missionComponent->AcceptMission(703, true);
missionComponent->AcceptMission(704, true);
}
}

View File

@@ -0,0 +1,8 @@
#pragma once
#include "CppScripts.h"
class FvFreeGfNinjas : public CppScripts::Script {
public:
void OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState) override;
void OnUse(Entity* self, Entity* user) override;
};

View File

@@ -0,0 +1,18 @@
#include "FvMaelstromGeyser.h"
#include "SkillComponent.h"
void FvMaelstromGeyser::OnStartup(Entity* self) {
self->AddTimer(m_StartSkillTimerName, m_StartSkillTimerTime);
self->AddTimer(m_KillSelfTimerName, m_KillSelfTimerTime);
}
void FvMaelstromGeyser::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == m_StartSkillTimerName) {
auto* skillComponent = self->GetComponent<SkillComponent>();
skillComponent->CalculateBehavior(m_SkillID, m_BehaviorID, LWOOBJID_EMPTY, true);
}
if (timerName == m_KillSelfTimerName) {
self->Smash(LWOOBJID_EMPTY, eKillType::SILENT);
}
}

View File

@@ -0,0 +1,18 @@
#pragma once
#include "CppScripts.h"
class FvMaelstromGeyser final : public CppScripts::Script
{
public:
void OnStartup(Entity* self) override;
void OnTimerDone(Entity* self, std::string timerName) override;
private:
const std::string m_StartSkillTimerName = "startSkill";
const float m_StartSkillTimerTime = 2.0;
const std::string m_KillSelfTimerName = "killSelf";
const float m_KillSelfTimerTime = 5.5;
const uint32_t m_SkillID = 831;
const uint32_t m_BehaviorID = 15500;
};

View File

@@ -0,0 +1,42 @@
#include "FvNinjaGuard.h"
#include "GameMessages.h"
#include "MissionComponent.h"
void FvNinjaGuard::OnStartup(Entity* self) {
if (self->GetLOT() == 7412) {
m_LeftGuard = self->GetObjectID();
} else if (self->GetLOT() == 11128) {
m_RightGuard = self->GetObjectID();
}
}
void FvNinjaGuard::OnEmoteReceived(Entity* self, const int32_t emote, Entity* target) {
if (emote != 392) {
GameMessages::SendPlayAnimation(self, u"no");
return;
}
GameMessages::SendPlayAnimation(self, u"scared");
auto* missionComponent = target->GetComponent<MissionComponent>();
if (missionComponent != nullptr && missionComponent->HasMission(737)) {
missionComponent->ForceProgressTaskType(737, 5, 1, false);
}
if (self->GetLOT() == 7412) {
auto* rightGuard = EntityManager::Instance()->GetEntity(m_RightGuard);
if (rightGuard != nullptr) {
GameMessages::SendPlayAnimation(rightGuard, u"laugh_rt");
}
} else if (self->GetLOT() == 11128) {
auto* leftGuard = EntityManager::Instance()->GetEntity(m_LeftGuard);
if (leftGuard != nullptr) {
GameMessages::SendPlayAnimation(leftGuard, u"laugh_lt");
}
}
}

View File

@@ -0,0 +1,13 @@
#pragma once
#include "CppScripts.h"
class FvNinjaGuard final : public CppScripts::Script
{
public:
void OnStartup(Entity* self) override;
void OnEmoteReceived(Entity* self, int32_t emote, Entity* target) override;
private:
LWOOBJID m_LeftGuard;
LWOOBJID m_RightGuard;
};

View File

@@ -0,0 +1,35 @@
#include "FvPandaServer.h"
#include "PetComponent.h"
#include "Character.h"
void FvPandaServer::OnStartup(Entity* self) {
const auto* petComponent = self->GetComponent<PetComponent>();
if (petComponent != nullptr && petComponent->GetOwner() == nullptr) {
self->SetNetworkVar<std::string>(u"pandatamer", std::to_string(self->GetVar<LWOOBJID>(u"tamer")));
self->AddTimer("killSelf", 45);
}
}
void FvPandaServer::OnNotifyPetTamingMinigame(Entity* self, Entity* tamer, eNotifyType type) {
if (type == NOTIFY_TYPE_BEGIN) {
self->CancelAllTimers();
} else if (type == NOTIFY_TYPE_QUIT || type == NOTIFY_TYPE_FAILED) {
self->Smash();
} else if (type == NOTIFY_TYPE_SUCCESS) {
// TODO: Remove from groups
auto* character = tamer->GetCharacter();
if (character != nullptr) {
character->SetPlayerFlag(82, true);
}
}
}
void FvPandaServer::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "killSelf") {
const auto* petComponent = self->GetComponent<PetComponent>();
if (petComponent != nullptr && petComponent->GetOwner() == nullptr) {
self->Smash(self->GetObjectID(), SILENT);
}
}
}

View File

@@ -0,0 +1,8 @@
#pragma once
#include "CppScripts.h"
class FvPandaServer : public CppScripts::Script {
void OnStartup(Entity* self) override;
void OnNotifyPetTamingMinigame(Entity* self, Entity* tamer, eNotifyType type) override;
void OnTimerDone(Entity* self, std::string timerName) override;
};

View File

@@ -0,0 +1,48 @@
#include "FvPandaSpawnerServer.h"
#include "Character.h"
#include "EntityManager.h"
#include "GameMessages.h"
#include "ScriptedActivityComponent.h"
void FvPandaSpawnerServer::OnCollisionPhantom(Entity* self, Entity* target) {
auto* character = target->GetCharacter();
if (character != nullptr && character->GetPlayerFlag(81)) {
auto raceObjects = EntityManager::Instance()->GetEntitiesInGroup("PandaRaceObject");
if (raceObjects.empty())
return;
// Check if the player is currently in a footrace
auto* scriptedActivityComponent = raceObjects.at(0)->GetComponent<ScriptedActivityComponent>();
if (scriptedActivityComponent == nullptr || !scriptedActivityComponent->IsPlayedBy(target))
return;
// If the player already spawned a panda
auto playerPandas = EntityManager::Instance()->GetEntitiesInGroup("panda" + std::to_string(target->GetObjectID()));
if (!playerPandas.empty()) {
GameMessages::SendFireEventClientSide(self->GetObjectID(), target->GetSystemAddress(), u"playerPanda",
target->GetObjectID(), 0, 0, target->GetObjectID());
return;
}
// If there's already too many spawned pandas
auto pandas = EntityManager::Instance()->GetEntitiesInGroup("pandas");
if (pandas.size() > 4) {
GameMessages::SendFireEventClientSide(self->GetObjectID(), target->GetSystemAddress(), u"tooManyPandas",
target->GetObjectID(), 0, 0, target->GetObjectID());
return;
}
EntityInfo info{};
info.spawnerID = target->GetObjectID();
info.pos = self->GetPosition();
info.lot = 5643;
info.settings = {
new LDFData<LWOOBJID>(u"tamer", target->GetObjectID()),
new LDFData<std::u16string>(u"groupID", u"panda" + (GeneralUtils::to_u16string(target->GetObjectID())) + u";pandas")
};
auto* panda = EntityManager::Instance()->CreateEntity(info);
EntityManager::Instance()->ConstructEntity(panda);
}
}

View File

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

View File

@@ -0,0 +1,18 @@
#include "FvPassThroughWall.h"
#include "InventoryComponent.h"
#include "MissionComponent.h"
void FvPassThroughWall::OnCollisionPhantom(Entity* self, Entity* target) {
auto missionComponent = target->GetComponent<MissionComponent>();
if (missionComponent == nullptr) return;
//Because at the moment we do not have an ItemComponent component, we check to make sure a Maelstrom-Infused hood is equipped. There are only three in the game right now.
auto inventoryComponent = target->GetComponent<InventoryComponent>();
// If no inventory component is found then abort.
if (inventoryComponent == nullptr) return;
// If no Maelstrom hoods are equipped then abort.
if (!inventoryComponent->IsEquipped(WhiteMaelstromHood) && !inventoryComponent->IsEquipped(BlackMaelstromHood) && !inventoryComponent->IsEquipped(RedMaelstromHood)) return;
// Progress mission Friend of the Ninja since all prerequisites are met.
missionComponent->ForceProgress(friendOfTheNinjaMissionId, friendOfTheNinjaMissionUid, 1);
}

View File

@@ -0,0 +1,34 @@
#pragma once
#include "CppScripts.h"
class FvPassThroughWall : public CppScripts::Script
{
/**
* @brief This method is called when there is a collision with self from target.
*
* @param self The Entity that called this method.
* @param target The Entity that self is targetting.
*/
void OnCollisionPhantom(Entity* self, Entity* target) override;
private:
/**
* Mission ID for Friend of the Ninjas.
*/
int32_t friendOfTheNinjaMissionId = 848;
/**
* Mission UID for Friend of the Ninjas.
*/
int32_t friendOfTheNinjaMissionUid = 1221;
/**
* Item LOT for Maelstrom-Infused White Ninja Hood
*/
int32_t WhiteMaelstromHood = 2641;
/**
* Item LOT for Maelstrom-Infused Black Ninja Hood
*/
int32_t BlackMaelstromHood = 2642;
/**
* Item LOT for Red Ninja Hood - Maelstrom Infused
*/
int32_t RedMaelstromHood = 1889;
};

View File

@@ -0,0 +1,4 @@
set(DSCRIPTS_SOURCES_AI_GENERAL
"InstanceExitTransferPlayerToLastNonInstance.cpp"
"LegoDieRoll.cpp"
PARENT_SCOPE)

View File

@@ -0,0 +1,56 @@
#include "InstanceExitTransferPlayerToLastNonInstance.h"
#include "GameMessages.h"
#include "Player.h"
#include "Character.h"
#include "dServer.h"
void InstanceExitTransferPlayerToLastNonInstance::OnUse(Entity* self, Entity* user) {
auto transferText = self->GetVar<std::u16string>(u"transferText");
if (transferText.empty())
transferText = u"DRAGON_EXIT_QUESTION";
GameMessages::SendDisplayMessageBox(
user->GetObjectID(),
true,
self->GetObjectID(),
u"Instance_Exit",
1,
transferText,
u"",
user->GetSystemAddress()
);
}
void InstanceExitTransferPlayerToLastNonInstance::OnMessageBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData) {
auto* player = dynamic_cast<Player*>(sender);
if (player == nullptr)
return;
auto* character = sender->GetCharacter();
if (character != nullptr) {
if (identifier == u"Instance_Exit" && button == 1) {
auto lastInstance = character->GetLastNonInstanceZoneID();
// Sanity check
if (lastInstance == 0) {
switch (Game::server->GetZoneID()) {
case 2001:
lastInstance = 2000;
break;
case 1402:
lastInstance = 1400;
break;
default:
lastInstance = 1100;
break;
}
}
player->SendToZone(lastInstance);
}
}
GameMessages::SendTerminateInteraction(sender->GetObjectID(), eTerminateType::FROM_INTERACTION, self->GetObjectID());
}

View File

@@ -0,0 +1,9 @@
#pragma once
#include "CppScripts.h"
class InstanceExitTransferPlayerToLastNonInstance : public CppScripts::Script
{
public:
void OnUse(Entity* self, Entity* user) override;
void OnMessageBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData) override;
};

View File

@@ -0,0 +1,52 @@
#include "LegoDieRoll.h"
#include "Entity.h"
#include "GameMessages.h"
#include "MissionComponent.h"
void LegoDieRoll::OnStartup(Entity* self) {
self->AddTimer("DoneRolling", 10.0f);
self->AddTimer("ThrowDice", LegoDieRoll::animTime);
}
void LegoDieRoll::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "DoneRolling") {
self->Smash(self->GetObjectID(), SILENT);
} else if (timerName == "ThrowDice") {
int dieRoll = GeneralUtils::GenerateRandomNumber<int>(1, 6);
switch (dieRoll) {
case 1:
GameMessages::SendPlayAnimation(self, u"roll-die-1");
break;
case 2:
GameMessages::SendPlayAnimation(self, u"roll-die-2");
break;
case 3:
GameMessages::SendPlayAnimation(self, u"roll-die-3");
break;
case 4:
GameMessages::SendPlayAnimation(self, u"roll-die-4");
break;
case 5:
GameMessages::SendPlayAnimation(self, u"roll-die-5");
break;
case 6:
{
GameMessages::SendPlayAnimation(self, u"roll-die-6");
// tracking the It's Truly Random Achievement
auto* owner = self->GetOwner();
auto* missionComponent = owner->GetComponent<MissionComponent>();
if (missionComponent != nullptr) {
const auto rollMissionState = missionComponent->GetMissionState(756);
if (rollMissionState == MissionState::MISSION_STATE_ACTIVE) {
missionComponent->ForceProgress(756, 1103, 1);
}
}
break;
}
default:
break;
}
}
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include "CppScripts.h"
class LegoDieRoll : public CppScripts::Script {
public:
void OnStartup(Entity* self);
void OnTimerDone(Entity* self, std::string timerName);
private:
constexpr static const float animTime = 2.0f;
};

View File

@@ -0,0 +1,14 @@
set(DSCRIPTS_SOURCES_AI_GF
"GfCampfire.cpp"
"GfOrgan.cpp"
"GfBanana.cpp"
"GfBananaCluster.cpp"
"GfJailkeepMission.cpp"
"TriggerAmbush.cpp"
"GfJailWalls.cpp"
"PetDigBuild.cpp"
"GfArchway.cpp"
"GfMaelstromGeyser.cpp"
"PirateRep.cpp"
"GfParrotCrash.cpp"
PARENT_SCOPE)

View File

@@ -0,0 +1,8 @@
#include "GfArchway.h"
#include "Entity.h"
#include "SkillComponent.h"
void GfArchway::OnRebuildComplete(Entity* self, Entity* target) {
auto* skillComponent = target->GetComponent<SkillComponent>();
if (skillComponent) skillComponent->CalculateBehavior(SHIELDING_SKILL, SHIELDING_BEHAVIOR, target->GetObjectID(), true);
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include "CppScripts.h"
class GfArchway : public CppScripts::Script {
public:
void OnRebuildComplete(Entity* self, Entity* target) override;
private:
const uint32_t SHIELDING_SKILL = 863;
const uint32_t SHIELDING_BEHAVIOR = 3788;
};

View File

@@ -0,0 +1,93 @@
#include "GfBanana.h"
#include "Entity.h"
#include "DestroyableComponent.h"
#include "EntityManager.h"
void GfBanana::SpawnBanana(Entity* self) {
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 = 6909;
info.spawnerID = self->GetObjectID();
auto* entity = EntityManager::Instance()->CreateEntity(info);
EntityManager::Instance()->ConstructEntity(entity);
self->SetVar(u"banana", entity->GetObjectID());
entity->AddDieCallback([self]() {
self->SetVar(u"banana", LWOOBJID_EMPTY);
self->AddTimer("bananaTimer", 30);
});
}
void GfBanana::OnStartup(Entity* self) {
SpawnBanana(self);
}
void GfBanana::OnHit(Entity* self, Entity* attacker) {
auto* destroyable = self->GetComponent<DestroyableComponent>();
destroyable->SetHealth(9999);
const auto bananaId = self->GetVar<LWOOBJID>(u"banana");
if (bananaId == LWOOBJID_EMPTY) return;
auto* bananaEntity = EntityManager::Instance()->GetEntity(bananaId);
if (bananaEntity == nullptr) {
self->SetVar(u"banana", LWOOBJID_EMPTY);
self->AddTimer("bananaTimer", 30);
return;
}
bananaEntity->SetPosition(bananaEntity->GetPosition() - NiPoint3::UNIT_Y * 8);
auto* bananaDestroyable = bananaEntity->GetComponent<DestroyableComponent>();
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 = EntityManager::Instance()->CreateEntity(info);
EntityManager::Instance()->ConstructEntity(entity, UNASSIGNED_SYSTEM_ADDRESS);
*/
EntityManager::Instance()->SerializeEntity(self);
}
void GfBanana::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "bananaTimer") {
SpawnBanana(self);
}
}

14
dScripts/ai/GF/GfBanana.h Normal file
View File

@@ -0,0 +1,14 @@
#pragma once
#include "CppScripts.h"
class GfBanana final : public CppScripts::Script
{
public:
void SpawnBanana(Entity* self);
void OnStartup(Entity* self) override;
void OnHit(Entity* self, Entity* attacker) override;
void OnTimerDone(Entity* self, std::string timerName) override;
};

View File

@@ -0,0 +1,12 @@
#include "GfBananaCluster.h"
#include "Entity.h"
void GfBananaCluster::OnStartup(Entity* self) {
self->AddTimer("startup", 100);
}
void GfBananaCluster::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "startup") {
self->ScheduleKillAfterUpdate(nullptr);
}
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include "CppScripts.h"
class GfBananaCluster final : public CppScripts::Script
{
public:
void OnStartup(Entity* self) override;
void OnTimerDone(Entity* self, std::string timerName) override;
};

View File

@@ -0,0 +1,100 @@
#include "GfCampfire.h"
#include "RenderComponent.h"
#include "SkillComponent.h"
#include "MissionComponent.h"
#include "RenderComponent.h"
#include "EntityManager.h"
void GfCampfire::OnStartup(Entity* self) {
self->SetI32(u"counter", static_cast<int32_t>(0));
self->SetProximityRadius(2.0f, "placeholder");
self->SetBoolean(u"isBurning", true);
auto* render = static_cast<RenderComponent*>(self->GetComponent(COMPONENT_TYPE_RENDER));
if (render == nullptr)
return;
render->PlayEffect(295, u"running", "Burn");
}
void GfCampfire::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
int32_t param3) {
if (args == "physicsReady") {
auto* render = static_cast<RenderComponent*>(self->GetComponent(COMPONENT_TYPE_RENDER));
render->PlayEffect(295, u"running", "Burn");
}
}
void GfCampfire::OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) {
auto* skill = self->GetComponent<SkillComponent>();
if (self->GetBoolean(u"isBurning")) {
if (status == "ENTER") {
if (entering->GetCharacter()) {
int32_t counter = self->GetI32(u"counter");
counter = counter + 1;
self->SetI32(u"counter", counter);
if (counter == 1) {
skill->CalculateBehavior(m_skillCastId, 115, entering->GetObjectID());
self->AddTimer("TimeBetweenCast", FIRE_COOLDOWN);
//self->SetVar<LWOOBJID>("target", entering->GetObjectID());
auto* missionComponet = entering->GetComponent<MissionComponent>();
if (missionComponet != nullptr) {
missionComponet->ForceProgress(440, 658, 1);
}
}
}
} else {
int32_t counter = self->GetI32(u"counter");
if (counter > 0) {
counter = counter - 1;
self->SetI32(u"counter", counter);
if (counter == 0) {
self->CancelAllTimers();
}
}
}
}
}
void GfCampfire::OnSkillEventFired(Entity* self, Entity* caster, const std::string& message) {
if (message == "waterspray" && self->GetVar<bool>(u"isBurning")) {
auto* renderComponent = self->GetComponent<RenderComponent>();
if (renderComponent != nullptr) {
renderComponent->StopEffect("Burn");
renderComponent->PlayEffect(295, u"idle", "Off");
self->SetVar<bool>(u"isBurning", false);
self->AddTimer("FireRestart", 37);
}
}
}
void GfCampfire::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "TimeBetweenCast") {
/*
self->AddTimer("TimeBetweenCast", FIRE_COOLDOWN);
const auto targetId = self->GetVar<LWOOBJID>("target");
auto* entering = EntityManager::Instance()->GetEntity(targetId);
if (entering == nullptr)
{
}
*/
} else if (timerName == "FireRestart" && !self->GetVar<bool>(u"isBurning")) {
auto* renderComponent = self->GetComponent<RenderComponent>();
if (renderComponent != nullptr) {
renderComponent->StopEffect("Off");
renderComponent->PlayEffect(295, u"running", "Burn");
self->SetVar<bool>(u"isBurning", true);
}
}
}

View File

@@ -0,0 +1,16 @@
#pragma once
#include "CppScripts.h"
class GfCampfire : public CppScripts::Script
{
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 OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) override;
void OnTimerDone(Entity* self, std::string timerName) override;
void OnSkillEventFired(Entity* self, Entity* caster, const std::string& message) override;
private:
int32_t m_skillCastId = 43;
int32_t FIRE_COOLDOWN = 2;
};

View File

@@ -0,0 +1,29 @@
#include "GfJailWalls.h"
#include "dZoneManager.h"
#include "GeneralUtils.h"
void GfJailWalls::OnRebuildComplete(Entity* self, Entity* target) {
const auto wall = GeneralUtils::UTF16ToWTF8(self->GetVar<std::u16string>(u"Wall"));
for (auto* spawner : dZoneManager::Instance()->GetSpawnersByName("Jail0" + wall)) {
spawner->Deactivate();
}
for (auto* spawner : dZoneManager::Instance()->GetSpawnersByName("JailCaptain0" + wall)) {
spawner->Deactivate();
}
}
void GfJailWalls::OnRebuildNotifyState(Entity* self, eRebuildState state) {
if (state != eRebuildState::REBUILD_RESETTING) return;
const auto wall = GeneralUtils::UTF16ToWTF8(self->GetVar<std::u16string>(u"Wall"));
for (auto* spawner : dZoneManager::Instance()->GetSpawnersByName("Jail0" + wall)) {
spawner->Activate();
}
for (auto* spawner : dZoneManager::Instance()->GetSpawnersByName("JailCaptain0" + wall)) {
spawner->Activate();
}
}

View File

@@ -0,0 +1,9 @@
#pragma once
#include "CppScripts.h"
class GfJailWalls final : public CppScripts::Script
{
public:
void OnRebuildComplete(Entity* self, Entity* target) override;
void OnRebuildNotifyState(Entity* self, eRebuildState state) override;
};

View File

@@ -0,0 +1,38 @@
#include "GfJailkeepMission.h"
#include "MissionComponent.h"
#include "Character.h"
void GfJailkeepMission::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState) {
auto* missionComponent = target->GetComponent<MissionComponent>();
if (missionComponent == nullptr)
return;
if (missionID == 385 && missionState == MissionState::MISSION_STATE_AVAILABLE) {
missionComponent->AcceptMission(386, true);
missionComponent->AcceptMission(387, true);
missionComponent->AcceptMission(388, true);
missionComponent->AcceptMission(390, true);
} else if (missionID == 385 && missionState == MissionState::MISSION_STATE_COMPLETE_READY_TO_COMPLETE) {
auto* character = target->GetCharacter();
if (character != nullptr && character->GetPlayerFlag(68)) {
missionComponent->AcceptMission(701);
missionComponent->AcceptMission(702);
missionComponent->AcceptMission(703);
missionComponent->AcceptMission(704);
}
}
}
void GfJailkeepMission::OnUse(Entity* self, Entity* user) {
auto* missionComponent = user->GetComponent<MissionComponent>();
if (missionComponent == nullptr)
return;
if (missionComponent->GetMissionState(385) == MissionState::MISSION_STATE_ACTIVE) {
missionComponent->AcceptMission(386, true);
missionComponent->AcceptMission(387, true);
missionComponent->AcceptMission(388, true);
missionComponent->AcceptMission(390, true);
}
}

View File

@@ -0,0 +1,9 @@
#pragma once
#include "CppScripts.h"
class GfJailkeepMission final : public CppScripts::Script
{
public:
void OnUse(Entity* self, Entity* user) override;
void OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState) override;
};

View File

@@ -0,0 +1,18 @@
#include "GfMaelstromGeyser.h"
#include "SkillComponent.h"
void GfMaelstromGeyser::OnStartup(Entity* self) {
self->AddTimer(m_StartSkillTimerName, m_StartSkillTimerTime);
self->AddTimer(m_KillSelfTimerName, m_KillSelfTimerTime);
}
void GfMaelstromGeyser::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == m_StartSkillTimerName) {
auto* skillComponent = self->GetComponent<SkillComponent>();
skillComponent->CalculateBehavior(m_SkillID, m_BehaviorID, LWOOBJID_EMPTY, true);
}
if (timerName == m_KillSelfTimerName) {
self->Smash(LWOOBJID_EMPTY, eKillType::SILENT);
}
}

View File

@@ -0,0 +1,17 @@
#pragma once
#include "CppScripts.h"
class GfMaelstromGeyser final : public CppScripts::Script
{
public:
void OnStartup(Entity* self) override;
void OnTimerDone(Entity* self, std::string timerName) override;
private:
const std::string m_StartSkillTimerName = "startSkill";
const float m_StartSkillTimerTime = 2.0;
const std::string m_KillSelfTimerName = "killSelf";
const float m_KillSelfTimerTime = 7.5;
const uint32_t m_SkillID = 607;
const uint32_t m_BehaviorID = 10500;
};

View File

@@ -0,0 +1,21 @@
#include "GfOrgan.h"
#include "GameMessages.h"
void GfOrgan::OnUse(Entity* self, Entity* user) {
if (self->GetBoolean(u"bIsInUse")) {
m_canUse = false;
return;
}
GameMessages::SendPlayNDAudioEmitter(self, UNASSIGNED_SYSTEM_ADDRESS, "{15d5f8bd-139a-4c31-8904-970c480cd70f}");
self->SetBoolean(u"bIsInUse", true);
self->AddTimer("reset", 5.0f);
GameMessages::SendPlayAnimation(user, u"jig");
}
void GfOrgan::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "reset") {
self->SetBoolean(u"bIsInUse", false);
}
}

11
dScripts/ai/GF/GfOrgan.h Normal file
View File

@@ -0,0 +1,11 @@
#pragma once
#include "CppScripts.h"
class GfOrgan : public CppScripts::Script
{
public:
void OnUse(Entity* self, Entity* user);
void OnTimerDone(Entity* self, std::string timerName);
private:
bool m_canUse;
};

View File

@@ -0,0 +1,13 @@
#include "GfParrotCrash.h"
#include "SkillComponent.h"
#include "Entity.h"
#include "dLogger.h"
void GfParrotCrash::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2, int32_t param3) {
auto* skillComponent = self->GetComponent<SkillComponent>();
if (args == "Slow") {
skillComponent->CalculateBehavior(m_SlowSkillID, m_SlowBehaviorID, sender->GetObjectID());
} else if (args == "Unslow") {
skillComponent->CalculateBehavior(m_UnslowSkillID, m_UnslowBehaviorID, sender->GetObjectID());
}
}

Some files were not shown because too many files have changed in this diff Show More