mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 02:43:44 +00:00
feat: add missing force field, jetpack NPC and Skullkin volume scripts
Ported from the live server scripts that ship with the client: - scripts\ai\LS\ForceFieldEffect.lua (LEGO Club and Starbase 3001 force fields): plays effect 3671 "cast" on whatever touches the phantom. - scripts\ai\NP\L_NPC_NP_JETPACK_GUY.lua (jetpack ambient NPCs): plays the object's "launch" effect when used. - scripts\02_server\Map\AM\L_SKELETON_SPAWNER_VOLUME.lua (Crux Prime Skullkin area): with 10 or more players in the volume the Skullkin engineer, miner and patroller networks maintain 2/6/6 instead of 1/4/4, with a 60 second cooldown between changes and a catch-up check when it ends. Only players are counted, and the count never goes below zero. WBL_Enemy_Grabbler.lua only sets wander variables for the old Lua movement AI, so it joins the other alpha wander scripts in the excluded list instead of logging as missing. Refs #746 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
75
dScripts/02_server/Map/AM/AmSkeletonSpawnerVolume.cpp
Normal file
75
dScripts/02_server/Map/AM/AmSkeletonSpawnerVolume.cpp
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
#include "AmSkeletonSpawnerVolume.h"
|
||||||
|
|
||||||
|
#include "Entity.h"
|
||||||
|
#include "dZoneManager.h"
|
||||||
|
#include "Spawner.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const std::u16string TotalPlayers = u"TotalPlayers";
|
||||||
|
const std::u16string SpawnStateMax = u"SpawnStateMax";
|
||||||
|
const std::u16string JustChanged = u"JustChanged";
|
||||||
|
|
||||||
|
void SetNumAndReset(const std::string& spawnerName, const int32_t num) {
|
||||||
|
for (auto* const spawner : Game::zoneManager->GetSpawnersByName(spawnerName)) {
|
||||||
|
spawner->SetNumToMaintain(num);
|
||||||
|
spawner->Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmSkeletonSpawnerVolume::OnStartup(Entity* self) {
|
||||||
|
self->SetVar<int32_t>(TotalPlayers, 0);
|
||||||
|
self->SetVar<bool>(SpawnStateMax, false);
|
||||||
|
self->SetVar<bool>(JustChanged, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmSkeletonSpawnerVolume::OnCollisionPhantom(Entity* self, Entity* target) {
|
||||||
|
if (!target || !target->IsPlayer()) return;
|
||||||
|
|
||||||
|
const auto totalPlayers = self->GetVar<int32_t>(TotalPlayers) + 1;
|
||||||
|
self->SetVar<int32_t>(TotalPlayers, totalPlayers);
|
||||||
|
|
||||||
|
if (totalPlayers >= ChangeNum && !self->GetVar<bool>(JustChanged) && !self->GetVar<bool>(SpawnStateMax)) {
|
||||||
|
SetSpawnCounts(self, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmSkeletonSpawnerVolume::OnOffCollisionPhantom(Entity* self, Entity* target) {
|
||||||
|
if (!target || !target->IsPlayer()) return;
|
||||||
|
|
||||||
|
const auto totalPlayers = std::max(self->GetVar<int32_t>(TotalPlayers) - 1, 0);
|
||||||
|
self->SetVar<int32_t>(TotalPlayers, totalPlayers);
|
||||||
|
|
||||||
|
if (totalPlayers < ChangeNum && !self->GetVar<bool>(JustChanged) && self->GetVar<bool>(SpawnStateMax)) {
|
||||||
|
SetSpawnCounts(self, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmSkeletonSpawnerVolume::OnTimerDone(Entity* self, std::string timerName) {
|
||||||
|
if (timerName != "StateChange") return;
|
||||||
|
|
||||||
|
self->SetVar<bool>(JustChanged, false);
|
||||||
|
|
||||||
|
// Catch up on any change that was held back while the counts were cooling down.
|
||||||
|
const auto totalPlayers = self->GetVar<int32_t>(TotalPlayers);
|
||||||
|
const auto isMax = self->GetVar<bool>(SpawnStateMax);
|
||||||
|
if (!isMax && totalPlayers >= ChangeNum) {
|
||||||
|
SetSpawnCounts(self, true);
|
||||||
|
} else if (isMax && totalPlayers < ChangeNum) {
|
||||||
|
SetSpawnCounts(self, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmSkeletonSpawnerVolume::SetSpawnCounts(Entity* self, const bool max) {
|
||||||
|
self->SetVar<bool>(SpawnStateMax, max);
|
||||||
|
self->SetVar<bool>(JustChanged, true);
|
||||||
|
self->AddTimer("StateChange", ChangeCooldown);
|
||||||
|
|
||||||
|
// There are 6 engineer and 6 miner spawner networks.
|
||||||
|
for (int32_t i = 1; i <= 6; i++) {
|
||||||
|
SetNumAndReset("Skullkin_Engineer_" + std::to_string(i), max ? 2 : 1);
|
||||||
|
SetNumAndReset("Skullkin_Miner_" + std::to_string(i), max ? 6 : 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetNumAndReset("Skullkin_Patrollers", max ? 6 : 4);
|
||||||
|
}
|
||||||
21
dScripts/02_server/Map/AM/AmSkeletonSpawnerVolume.h
Normal file
21
dScripts/02_server/Map/AM/AmSkeletonSpawnerVolume.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "CppScripts.h"
|
||||||
|
|
||||||
|
// A volume over the Skullkin area of Crux Prime that spawns more Skullkin while many players are in it.
|
||||||
|
class AmSkeletonSpawnerVolume : public CppScripts::Script {
|
||||||
|
public:
|
||||||
|
void OnStartup(Entity* self) override;
|
||||||
|
void OnCollisionPhantom(Entity* self, Entity* target) override;
|
||||||
|
void OnOffCollisionPhantom(Entity* self, Entity* target) override;
|
||||||
|
void OnTimerDone(Entity* self, std::string timerName) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Sets the spawner networks to the higher or lower counts.
|
||||||
|
static void SetSpawnCounts(Entity* self, bool max);
|
||||||
|
|
||||||
|
// Players needed in the volume for the higher counts.
|
||||||
|
static constexpr int32_t ChangeNum = 10;
|
||||||
|
|
||||||
|
// Seconds after a change before the counts may change again.
|
||||||
|
static constexpr float ChangeCooldown = 60.0f;
|
||||||
|
};
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
set(DSCRIPTS_SOURCES_02_SERVER_MAP_AM
|
set(DSCRIPTS_SOURCES_02_SERVER_MAP_AM
|
||||||
"AmConsoleTeleportServer.cpp"
|
"AmConsoleTeleportServer.cpp"
|
||||||
|
"AmSkeletonSpawnerVolume.cpp"
|
||||||
"RandomSpawnerFin.cpp"
|
"RandomSpawnerFin.cpp"
|
||||||
"RandomSpawnerPit.cpp"
|
"RandomSpawnerPit.cpp"
|
||||||
"RandomSpawnerStr.cpp"
|
"RandomSpawnerStr.cpp"
|
||||||
|
|||||||
@@ -136,6 +136,8 @@
|
|||||||
#include "FvHorsemenTrigger.h"
|
#include "FvHorsemenTrigger.h"
|
||||||
#include "FvFlyingCreviceDragon.h"
|
#include "FvFlyingCreviceDragon.h"
|
||||||
#include "FvDragonInstanceServer.h"
|
#include "FvDragonInstanceServer.h"
|
||||||
|
#include "ForceFieldEffect.h"
|
||||||
|
#include "NpcNpJetpackGuy.h"
|
||||||
#include "FvMaelstromDragon.h"
|
#include "FvMaelstromDragon.h"
|
||||||
#include "DragonRonin.h"
|
#include "DragonRonin.h"
|
||||||
#include "FvDragonSmashingGolemQb.h"
|
#include "FvDragonSmashingGolemQb.h"
|
||||||
@@ -251,6 +253,7 @@
|
|||||||
#include "AmDarklingDragon.h"
|
#include "AmDarklingDragon.h"
|
||||||
#include "AmBlueX.h"
|
#include "AmBlueX.h"
|
||||||
#include "AmTeapotServer.h"
|
#include "AmTeapotServer.h"
|
||||||
|
#include "AmSkeletonSpawnerVolume.h"
|
||||||
#include "WanderingVendor.h"
|
#include "WanderingVendor.h"
|
||||||
|
|
||||||
// NJ Scripts
|
// NJ Scripts
|
||||||
@@ -608,6 +611,7 @@ namespace {
|
|||||||
{"scripts\\02_server\\Enemy\\AM\\L_AM_DARKLING_APE.lua", []() {return new BaseEnemyApe();}},
|
{"scripts\\02_server\\Enemy\\AM\\L_AM_DARKLING_APE.lua", []() {return new BaseEnemyApe();}},
|
||||||
{"scripts\\02_server\\Map\\AM\\L_BLUE_X.lua", []() {return new AmBlueX();}},
|
{"scripts\\02_server\\Map\\AM\\L_BLUE_X.lua", []() {return new AmBlueX();}},
|
||||||
{"scripts\\02_server\\Map\\AM\\L_TEAPOT_SERVER.lua", []() {return new AmTeapotServer();}},
|
{"scripts\\02_server\\Map\\AM\\L_TEAPOT_SERVER.lua", []() {return new AmTeapotServer();}},
|
||||||
|
{"scripts\\02_server\\Map\\AM\\L_SKELETON_SPAWNER_VOLUME.lua", []() {return new AmSkeletonSpawnerVolume();}},
|
||||||
|
|
||||||
//Ninjago
|
//Ninjago
|
||||||
{"scripts\\02_server\\Map\\njhub\\L_GARMADON_CELEBRATION_SERVER.lua", []() {return new NjGarmadonCelebration();}},
|
{"scripts\\02_server\\Map\\njhub\\L_GARMADON_CELEBRATION_SERVER.lua", []() {return new NjGarmadonCelebration();}},
|
||||||
@@ -723,6 +727,8 @@ namespace {
|
|||||||
{"scripts\\equipmenttriggers\\ImaginationBackPack.lua", []() {return new ImaginationBackPack();}},
|
{"scripts\\equipmenttriggers\\ImaginationBackPack.lua", []() {return new ImaginationBackPack();}},
|
||||||
{"scripts\\ai\\MINIGAME\\SG_GF\\SERVER\\SG_CANNON_INSTANCE_ACTOR.lua", [](){return new RegisterWithZoneControl();}},
|
{"scripts\\ai\\MINIGAME\\SG_GF\\SERVER\\SG_CANNON_INSTANCE_ACTOR.lua", [](){return new RegisterWithZoneControl();}},
|
||||||
{"scripts\\ai\\MINIGAME\\SG_GF\\SERVER\\SG_CANNON_INSTANCE_EFFECT.lua", [](){return new RegisterWithZoneControl();}},
|
{"scripts\\ai\\MINIGAME\\SG_GF\\SERVER\\SG_CANNON_INSTANCE_EFFECT.lua", [](){return new RegisterWithZoneControl();}},
|
||||||
|
{"scripts\\ai\\LS\\ForceFieldEffect.lua", []() {return new ForceFieldEffect();}},
|
||||||
|
{"scripts\\ai\\NP\\L_NPC_NP_JETPACK_GUY.lua", []() {return new NpcNpJetpackGuy();}},
|
||||||
};
|
};
|
||||||
|
|
||||||
std::set<std::string> g_ExcludedScripts = {
|
std::set<std::string> g_ExcludedScripts = {
|
||||||
@@ -749,6 +755,7 @@ namespace {
|
|||||||
"scripts\\ai\\GENERAL\\L_NPC_GENERIC_MOVEMENT.lua", // Really old alpha script
|
"scripts\\ai\\GENERAL\\L_NPC_GENERIC_MOVEMENT.lua", // Really old alpha script
|
||||||
"scripts\\zone\\LUPs\\DeepFreeze Intro\\WBL_Enemy_Beaver.lua", // Really old alpha script
|
"scripts\\zone\\LUPs\\DeepFreeze Intro\\WBL_Enemy_Beaver.lua", // Really old alpha script
|
||||||
"scripts\\ai\\GENERAL\\L_NPC_GENERIC_WANDER_SMALL.lua", // Really old alpha script
|
"scripts\\ai\\GENERAL\\L_NPC_GENERIC_WANDER_SMALL.lua", // Really old alpha script
|
||||||
|
"scripts\\zone\\LUPs\\Moonbase Intro\\WBL_Enemy_Grabbler.lua", // Really old alpha script, only sets wander variables
|
||||||
"scripts\\ai\\NP\\L_NPC_NP_OLD_MAN_SHERLAND.lua", // This NPC doesn't even exist in modern crux, the only place this is used...
|
"scripts\\ai\\NP\\L_NPC_NP_OLD_MAN_SHERLAND.lua", // This NPC doesn't even exist in modern crux, the only place this is used...
|
||||||
"scripts\\02_server\\Map\\General\\L_SIMPLE_MOVER_SWITCH.lua", // This platform does not exist even when moved manually on a client
|
"scripts\\02_server\\Map\\General\\L_SIMPLE_MOVER_SWITCH.lua", // This platform does not exist even when moved manually on a client
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
set(DSCRIPTS_SOURCES_AI_GENERAL
|
set(DSCRIPTS_SOURCES_AI_GENERAL
|
||||||
|
"ForceFieldEffect.cpp"
|
||||||
"InstanceExitTransferPlayerToLastNonInstance.cpp"
|
"InstanceExitTransferPlayerToLastNonInstance.cpp"
|
||||||
"LegoDieRoll.cpp")
|
"LegoDieRoll.cpp")
|
||||||
|
|
||||||
|
|||||||
10
dScripts/ai/GENERAL/ForceFieldEffect.cpp
Normal file
10
dScripts/ai/GENERAL/ForceFieldEffect.cpp
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#include "ForceFieldEffect.h"
|
||||||
|
|
||||||
|
#include "Entity.h"
|
||||||
|
#include "GameMessages.h"
|
||||||
|
|
||||||
|
void ForceFieldEffect::OnCollisionPhantom(Entity* self, Entity* target) {
|
||||||
|
if (!target) return;
|
||||||
|
|
||||||
|
GameMessages::SendPlayFXEffect(target, 3671, u"cast", "", LWOOBJID_EMPTY);
|
||||||
|
}
|
||||||
8
dScripts/ai/GENERAL/ForceFieldEffect.h
Normal file
8
dScripts/ai/GENERAL/ForceFieldEffect.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "CppScripts.h"
|
||||||
|
|
||||||
|
// Plays a sparkle effect on anything that touches this phantom physics object.
|
||||||
|
class ForceFieldEffect : public CppScripts::Script {
|
||||||
|
public:
|
||||||
|
void OnCollisionPhantom(Entity* self, Entity* target) override;
|
||||||
|
};
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
set(DSCRIPTS_SOURCES_AI_NP
|
set(DSCRIPTS_SOURCES_AI_NP
|
||||||
|
"NpcNpJetpackGuy.cpp"
|
||||||
"NpcNpSpacemanBob.cpp")
|
"NpcNpSpacemanBob.cpp")
|
||||||
|
|
||||||
add_library(dScriptsAiNP OBJECT ${DSCRIPTS_SOURCES_AI_NP})
|
add_library(dScriptsAiNP OBJECT ${DSCRIPTS_SOURCES_AI_NP})
|
||||||
|
|||||||
9
dScripts/ai/NP/NpcNpJetpackGuy.cpp
Normal file
9
dScripts/ai/NP/NpcNpJetpackGuy.cpp
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#include "NpcNpJetpackGuy.h"
|
||||||
|
|
||||||
|
#include "Entity.h"
|
||||||
|
#include "GameMessages.h"
|
||||||
|
|
||||||
|
void NpcNpJetpackGuy::OnUse(Entity* self, Entity* user) {
|
||||||
|
// No effect ID, the client plays the object's own effect of this type.
|
||||||
|
GameMessages::SendPlayFXEffect(self, -1, u"launch", "", LWOOBJID_EMPTY);
|
||||||
|
}
|
||||||
8
dScripts/ai/NP/NpcNpJetpackGuy.h
Normal file
8
dScripts/ai/NP/NpcNpJetpackGuy.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "CppScripts.h"
|
||||||
|
|
||||||
|
// Plays the launch effect when a player talks to the jetpack NPC.
|
||||||
|
class NpcNpJetpackGuy : public CppScripts::Script {
|
||||||
|
public:
|
||||||
|
void OnUse(Entity* self, Entity* user) override;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user