Public release of the DLU server code!

Have fun!
This commit is contained in:
Unknown
2021-12-05 18:54:36 +01:00
parent 5f7270e4ad
commit 0545adfac3
1146 changed files with 368646 additions and 1 deletions

View File

@@ -0,0 +1,31 @@
#include "ActNinjaTurret.h"
void ActNinjaTurret::OnRebuildNotifyState(Entity* self, eRebuildState state)
{
Game::logger->Log("ActNinjaTurret", "Rebuild state: %i\n", state);
if (state == eRebuildState::REBUILD_COMPLETED)
{
Game::logger->Log("ActNinjaTurret", "I am build\n");
self->SetVar(u"AmBuilt", true);
}
else if (state == eRebuildState::REBUILD_RESETTING)
{
Game::logger->Log("ActNinjaTurret", "I am not build\n");
self->SetVar(u"AmBuilt", false);
}
}
void
ActNinjaTurret::OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1, int32_t param2,
int32_t param3)
{
Game::logger->Log("ActNinjaTurret", "Got server side event %s\n", args.c_str());
if (args == "ISpawned" && self->GetVar<bool>(u"AmBuilt"))
{
sender->Smash();
}
}

11
dScripts/ActNinjaTurret.h Normal file
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,73 @@
#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,8 @@
#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,27 @@
#include "ActSharkPlayerDeathTrigger.h"
#include "Entity.h"
#include "GameMessages.h"
#include "Game.h"
#include "dLogger.h"
void ActSharkPlayerDeathTrigger::OnCollisionPhantom(Entity* self, Entity* target) {
}
void ActSharkPlayerDeathTrigger::OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1,
int32_t param2, int32_t param3) {
if (args == "achieve") {
MissionComponent* mis = static_cast<MissionComponent*>(sender->GetComponent(COMPONENT_TYPE_MISSION));
if (!mis) return;
mis->Progress(MissionTaskType::MISSION_TASK_TYPE_SCRIPT, 4734);
if (sender->GetIsDead() || !sender->GetPlayerReadyForUpdates()) return; //Don't kill already dead players or players not ready
Game::logger->Log("ActSharkPlayerDeathTrigger", "%i\n", self->GetLOT());
if (sender->GetCharacter()) {
sender->Smash(self->GetObjectID(), eKillType::VIOLENT, u"big-shark-death");
}
}
}

View File

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

View File

@@ -0,0 +1,62 @@
#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,219 @@
#include "ActivityManager.h"
#include "EntityManager.h"
#include "ScriptedActivityComponent.h"
#include "LeaderboardManager.h"
#include "GameMessages.h"
#include <algorithm>
bool ActivityManager::IsPlayerInActivity(Entity *self, LWOOBJID playerID) {
const auto* sac = self->GetComponent<ScriptedActivityComponent>();
return sac != nullptr && sac->IsPlayedBy(playerID);
}
void ActivityManager::UpdatePlayer(Entity *self, LWOOBJID playerID, const bool remove) {
auto* sac = self->GetComponent<ScriptedActivityComponent>();
if (sac == nullptr)
return;
if (remove) {
sac->PlayerRemove(playerID);
} else {
auto* player = EntityManager::Instance()->GetEntity(playerID);
if (player != nullptr) {
sac->PlayerJoin(player);
SetActivityScore(self, playerID, 0);
}
}
}
void ActivityManager::SetActivityScore(Entity *self, LWOOBJID playerID, uint32_t score) {
SetActivityValue(self, playerID, 0, score);
}
void ActivityManager::SetActivityValue(Entity *self, const LWOOBJID playerID, const uint32_t valueIndex,
const float_t value) {
auto* sac = self->GetComponent<ScriptedActivityComponent>();
if (sac == nullptr)
return;
sac->SetActivityValue(playerID, valueIndex, value);
}
float_t ActivityManager::GetActivityValue(Entity *self, const LWOOBJID playerID, const uint32_t valueIndex) {
auto* sac = self->GetComponent<ScriptedActivityComponent>();
if (sac == nullptr)
return -1.0f;
return sac->GetActivityValue(playerID, valueIndex);
}
void ActivityManager::StopActivity(Entity *self, const LWOOBJID playerID, const uint32_t score,
const uint32_t value1, const uint32_t value2, bool quit) {
int32_t gameID = 0;
auto* sac = self->GetComponent<ScriptedActivityComponent>();
if (sac == nullptr) {
gameID = self->GetLOT();
}
else {
gameID = sac->GetActivityID();
}
if (quit) {
UpdatePlayer(self, playerID, true);
} else {
auto* player = EntityManager::Instance()->GetEntity(playerID);
if (player == nullptr)
return;
SetActivityScore(self, playerID, score);
SetActivityValue(self, playerID, 1, value1);
SetActivityValue(self, playerID, 2, value2);
Loot::GiveActivityLoot(player, self, gameID, CalculateActivityRating(self, playerID));
// Save the new score to the leaderboard and show the leaderboard to the player
LeaderboardManager::SaveScore(playerID, gameID, score, value1);
const auto* leaderboard = LeaderboardManager::GetLeaderboard(gameID, InfoType::Standings,
false, player->GetObjectID());
GameMessages::SendActivitySummaryLeaderboardData(self->GetObjectID(), leaderboard, player->GetSystemAddress());
delete leaderboard;
// Makes the leaderboard show up for the player
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"ToggleLeaderBoard",
gameID,0, playerID, "",
player->GetSystemAddress());
if (sac != nullptr) {
sac->PlayerRemove(player->GetObjectID());
}
}
}
bool ActivityManager::TakeActivityCost(const Entity *self, const LWOOBJID playerID) {
auto* sac = self->GetComponent<ScriptedActivityComponent>();
if (sac == nullptr)
return false;
auto* player = EntityManager::Instance()->GetEntity(playerID);
if (player == nullptr)
return false;
return sac->TakeCost(player);
}
uint32_t ActivityManager::CalculateActivityRating(Entity *self, const LWOOBJID playerID) {
auto* sac = self->GetComponent<ScriptedActivityComponent>();
if (sac == nullptr)
return 0;
return sac->GetInstance(playerID)->GetParticipants().size();
}
uint32_t ActivityManager::GetActivityID(const Entity* self) {
auto* sac = self->GetComponent<ScriptedActivityComponent>();
return sac != nullptr ? sac->GetActivityID() : 0;
}
void ActivityManager::GetLeaderboardData(Entity *self, const LWOOBJID playerID, const uint32_t activityID, uint32_t numResults) {
LeaderboardManager::SendLeaderboard(activityID, Standings, false, self->GetObjectID(), playerID);
}
void ActivityManager::ActivityTimerStart(Entity *self, const std::string& timerName, const float_t updateInterval,
const float_t stopTime) {
auto* timer = new ActivityTimer { timerName, updateInterval, stopTime };
activeTimers.push_back(timer);
Game::logger->Log("ActivityManager", "Starting timer '%s', %f, %f\n", timerName.c_str(), updateInterval, stopTime);
self->AddTimer(GetPrefixedName(timer->name), timer->updateInterval);
}
void ActivityManager::ActivityTimerStopAllTimers(Entity* self) {
for (auto* timer : activeTimers) {
self->CancelTimer(GetPrefixedName(timer->name));
delete timer;
}
activeTimers.clear();
}
float_t ActivityManager::ActivityTimerGetCurrentTime(Entity *self, const std::string &timerName) const {
auto* timer = GetTimer(timerName);
return timer != nullptr ? timer->runTime : 0.0f;
}
int32_t ActivityManager::GetGameID(Entity *self) const
{
int32_t gameID = 0;
auto* sac = self->GetComponent<ScriptedActivityComponent>();
if (sac == nullptr) {
gameID = self->GetLOT();
}
else {
gameID = sac->GetActivityID();
}
return gameID;
}
float_t ActivityManager::ActivityTimerGetRemainingTime(Entity *self, const std::string &timerName) const {
auto* timer = GetTimer(timerName);
return timer != nullptr ? std::min(timer->stopTime - timer->runTime, 0.0f) : 0.0f;
}
void ActivityManager::ActivityTimerReset(Entity *self, const std::string &timerName) {
auto* timer = GetTimer(timerName);
if (timer != nullptr) {
timer->runTime = 0.0f;
}
}
ActivityTimer* ActivityManager::GetTimer(const std::string &name) const {
for (auto* timer : activeTimers) {
if (timer->name == name)
return timer;
}
return nullptr;
}
void ActivityManager::ActivityTimerStop(Entity *self, const std::string &timerName) {
auto* timer = GetTimer(timerName);
if (timer != nullptr) {
self->CancelTimer(GetPrefixedName(timer->name));
activeTimers.erase(std::remove(activeTimers.begin(), activeTimers.end(), timer),
activeTimers.end());
delete timer;
}
}
std::string ActivityManager::GetPrefixedName(const std::string &name) const {
return TimerPrefix + "_" + name;
}
void ActivityManager::OnTimerDone(Entity *self, std::string timerName) {
auto nameSplit = GeneralUtils::SplitString(timerName, '_');
if (nameSplit.size() > 1 && nameSplit.at(0) == TimerPrefix) {
const auto& activityTimerName = nameSplit.at(1);
auto* timer = GetTimer(activityTimerName);
if (timer != nullptr) {
timer->runTime += timer->updateInterval;
if (timer->stopTime != -1.0f && timer->runTime >= timer->stopTime) {
activeTimers.erase(std::remove(activeTimers.begin(), activeTimers.end(), timer),
activeTimers.end());
delete timer;
Game::logger->Log("ActivityManager", "Executing timer '%s'\n", activityTimerName.c_str());
OnActivityTimerDone(self, activityTimerName);
} else {
Game::logger->Log("ActivityManager", "Updating timer '%s'\n", activityTimerName.c_str());
OnActivityTimerUpdate(self, timer->name, timer->stopTime - timer->runTime, timer->runTime);
self->AddTimer(GetPrefixedName(timer->name), timer->updateInterval);
}
}
}
}

View File

@@ -0,0 +1,42 @@
#pragma once
#include "CppScripts.h"
struct ActivityTimer {
std::string name;
float_t updateInterval;
float_t stopTime;
float_t runTime = 0;
};
class ActivityManager : public CppScripts::Script {
public:
static bool IsPlayerInActivity(Entity *self, LWOOBJID playerID);
static void UpdatePlayer(Entity *self, LWOOBJID playerID, bool remove = false);
static void SetActivityScore(Entity *self, LWOOBJID playerID, uint32_t score);
static void SetActivityValue(Entity *self, LWOOBJID playerID, uint32_t valueIndex, float_t value);
static float_t GetActivityValue(Entity *self, LWOOBJID playerID, uint32_t valueIndex) ;
static bool TakeActivityCost(const Entity* self, LWOOBJID playerID);
static uint32_t GetActivityID(const Entity* self);
void StopActivity(Entity *self, LWOOBJID playerID, uint32_t score, uint32_t value1 = 0, uint32_t value2 = 0, bool quit = false);
virtual uint32_t CalculateActivityRating(Entity* self, LWOOBJID playerID);
static void GetLeaderboardData(Entity *self, LWOOBJID playerID, uint32_t activityID, uint32_t numResults = 0);
// void FreezePlayer(Entity *self, const LWOOBJID playerID, const bool state) const;
// Activity timer
void OnTimerDone(Entity *self, std::string timerName) override;
virtual void OnActivityTimerDone(Entity* self, const std::string& name) {};
virtual void OnActivityTimerUpdate(Entity* self, const std::string& name, float_t timeRemaining, float_t elapsedTime) {};
void ActivityTimerStart(Entity *self, const std::string& timerName, float_t updateInterval, float_t stopTime = -1.0f);
void ActivityTimerReset(Entity *self, const std::string& timerName);
void ActivityTimerStop(Entity* self, const std::string& timerName);
void ActivityTimerStopAllTimers(Entity* self);
float_t ActivityTimerGetRemainingTime(Entity *self, const std::string& timerName) const;
float_t ActivityTimerGetCurrentTime(Entity *self, const std::string& timerName) const;
int32_t GetGameID(Entity* self) const;
private:
std::string GetPrefixedName(const std::string& name) const;
[[nodiscard]] ActivityTimer* GetTimer(const std::string& name) const;
std::vector<ActivityTimer*> activeTimers {};
std::string TimerPrefix = "ActivityTimer";
};

21
dScripts/AgBugsprayer.cpp Normal file
View File

@@ -0,0 +1,21 @@
#include "AgBugsprayer.h"
#include "SkillComponent.h"
void AgBugsprayer::OnRebuildComplete(Entity* self, Entity* target)
{
self->AddTimer("castSkill", 1);
self->SetOwnerOverride(target->GetObjectID());
}
void AgBugsprayer::OnTimerDone(Entity* self, std::string timerName)
{
if (timerName == "castSkill")
{
auto* skillComponent = self->GetComponent<SkillComponent>();
if (skillComponent == nullptr) return;
skillComponent->CalculateBehavior(1435, 36581, LWOOBJID_EMPTY);
}
}

10
dScripts/AgBugsprayer.h Normal file
View File

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

71
dScripts/AgBusDoor.cpp Normal file
View File

@@ -0,0 +1,71 @@
#include "AgBusDoor.h"
#include "Entity.h"
#include "GameMessages.h"
#include "Game.h"
#include "dLogger.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);
}
}

15
dScripts/AgBusDoor.h Normal file
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,24 @@
#include "AgCagedBricksServer.h"
#include "InventoryComponent.h"
#include "GameMessages.h"
#include "Character.h"
#include "EntityManager.h"
void AgCagedBricksServer::OnUse(Entity* self, Entity* user) {
//Tell the client to spawn the baby spiderling:
auto spooders = EntityManager::Instance()->GetEntitiesInGroup("cagedSpider");
for (auto spodder : spooders) {
GameMessages::SendFireEventClientSide(spodder->GetObjectID(), user->GetSystemAddress(), u"toggle", LWOOBJID_EMPTY, 0, 0, user->GetObjectID());
}
//Set the flag & mission status:
user->GetCharacter()->SetPlayerFlag(74, true);
//Remove the maelstrom cube:
auto inv = static_cast<InventoryComponent*>(user->GetComponent(COMPONENT_TYPE_INVENTORY));
if (inv)
{
inv->RemoveItem(14553, 1);
}
}

View File

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

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

View File

@@ -0,0 +1,9 @@
#include "AgDarklingMech.h"
#include "DestroyableComponent.h"
void AgDarklingMech::OnStartup(Entity *self) {
auto* destroyableComponent = self->GetComponent<DestroyableComponent>();
if (destroyableComponent != nullptr) {
destroyableComponent->SetFaction(4);
}
}

View File

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

81
dScripts/AgFans.cpp Normal file
View File

@@ -0,0 +1,81 @@
#include "AgFans.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);
}

17
dScripts/AgFans.h Normal file
View File

@@ -0,0 +1,17 @@
#pragma once
#include "CppScripts.h"
#include "GameMessages.h"
#include "EntityManager.h"
#include "PhantomPhysicsComponent.h"
class AgFans : public CppScripts::Script
{
public:
void OnStartup(Entity* self);
void OnDie(Entity* self, Entity* killer);
void OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1, int32_t param2,
int32_t param3);
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,10 @@
#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,138 @@
#include "AgJetEffectServer.h"
#include "GameMessages.h"
#include "EntityManager.h"
#include "PhantomPhysicsComponent.h"
#include "SkillComponent.h"
void AgJetEffectServer::OnStartup(Entity* self)
{
}
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("PlayEffect", 2.5f);
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)\n", 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,19 @@
#pragma once
#include "CppScripts.h"
class AgJetEffectServer final : public CppScripts::Script
{
public:
void OnStartup(Entity* self) override;
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,54 @@
#include "AgLaserSensorServer.h"
#include "EntityManager.h"
void AgLaserSensorServer::OnStartup(Entity* self) {
PhantomPhysicsComponent* physComp = static_cast<PhantomPhysicsComponent*>(self->GetComponent(COMPONENT_TYPE_PHANTOM_PHYSICS));
physComp->SetPhysicsEffectActive(true);
physComp->SetEffectType(2); // repulse (prolly should make definitions of these are in Entity.cpp)
physComp->SetDirectionalMultiplier(static_cast<float>(m_RepelForce));
physComp->SetDirection(NiPoint3::UNIT_Y);
m_Skill = self->GetComponent<SkillComponent>();
}
void AgLaserSensorServer::OnCollisionPhantom(Entity* self, Entity* target) {
if (!m_Skill) return;
Entity* laser = nullptr;
for (auto script : EntityManager::Instance()->GetEntitiesByComponent(COMPONENT_TYPE_SCRIPT)) {
AgMonumentLaserServer* hasLaser = (AgMonumentLaserServer*)script;
if (hasLaser) {
const auto source = script->GetPosition();
const auto obj = self->GetObjectID();
if (obj == 76690936093053 && Vector3::DistanceSquared(source, NiPoint3(149.007f, 417.083f, 218.346f)) <= 1.0f) {
laser = script;
break;
}
else if (obj == 75866302318824 && Vector3::DistanceSquared(source, NiPoint3(48.6403f, 403.803f, 196.711f)) <= 1.0f) {
laser = script;
break;
}
else if (obj == 75866302318822 && Vector3::DistanceSquared(source, NiPoint3(19.2155f, 420.083f, 249.226f)) <= 1.0f) {
laser = script;
break;
}
else if (obj == 75866302318823 && Vector3::DistanceSquared(source, NiPoint3(-6.61596f, 404.633f, 274.323f)) <= 1.0f) {
laser = script;
break;
}
}
}
if (laser != nullptr) {
m_Skill->CalculateBehavior(m_SkillCastID, 15714, target->GetObjectID());
}
}

View File

@@ -0,0 +1,17 @@
#pragma once
#include "CppScripts.h"
#include "PhantomPhysicsComponent.h"
#include "SkillComponent.h"
#include "EntityManager.h"
#include "AgMonumentLaserServer.h"
class AgLaserSensorServer : public CppScripts::Script {
public:
void OnStartup(Entity* self);
void OnCollisionPhantom(Entity* self, Entity* target);
private:
SkillComponent* m_Skill;
int m_RepelForce = -25;
int m_SkillCastID = 163;
};

View File

@@ -0,0 +1,34 @@
#include "AgMonumentBirds.h"
#include "GameMessages.h"
#include "DestroyableComponent.h"
//--------------------------------------------------------------
//Makes the ag birds fly away when you get close and smashes them.
//Created mrb... 6 / 3 / 11
//Ported Max 20/07/2020
//--------------------------------------------------------------
void AgMonumentBirds::OnStartup(Entity* self) {
self->SetProximityRadius(flyRadius, "MonumentBirds");
}
void AgMonumentBirds::OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) {
if (self->GetVar<bool>(u"IsFlying")) return;
if (name == "MonumentBirds" && status == "ENTER") {
self->AddTimer("killBird", 1.0f);
GameMessages::SendPlayAnimation(self, sOnProximityAnim);
self->SetVar<bool>(u"IsFlying", true);
self->SetVar<LWOOBJID>(u"PlayerID", entering->GetObjectID());
}
}
void AgMonumentBirds::OnTimerDone(Entity* self, std::string timerName) {
if (timerName != "killBird") return;
auto* player = EntityManager::Instance()->GetEntity(self->GetVar<LWOOBJID>(u"PlayerID"));
if (player == nullptr) return;
self->ScheduleKillAfterUpdate(player);
}

View File

@@ -0,0 +1,13 @@
#pragma once
#include "CppScripts.h"
class AgMonumentBirds : 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:
std::u16string sOnProximityAnim = u"fly1";
float flyRadius = 5.0f;
};

View File

@@ -0,0 +1,20 @@
#include "AgMonumentLaserServer.h"
void AgMonumentLaserServer::OnStartup(Entity* self) {
/*
self->SetProximityRadius(m_Radius, "MonumentLaser");
std::cout << "Monument Laser " << self->GetObjectID() << " is at " << self->GetPosition().GetX()
<< ","<< self->GetPosition().GetY() << "," << self->GetPosition().GetZ() << std::endl;
*/
}
void AgMonumentLaserServer::OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) {
/*
if (status == "ENTER") {
std::cout << "Monument laser ID: " << self->GetObjectID() << std::endl;
}
*/
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include "CppScripts.h"
class AgMonumentLaserServer : public CppScripts::Script {
public:
void OnStartup(Entity* self);
void OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status);
private:
float m_Radius = 25.0f;
};

View File

@@ -0,0 +1,9 @@
#include "AgMonumentRaceCancel.h"
#include "EntityManager.h"
void AgMonumentRaceCancel::OnCollisionPhantom(Entity *self, Entity *target) {
auto managers = EntityManager::Instance()->GetEntitiesInGroup("race_manager");
if (!managers.empty()) {
managers[0]->OnFireEventServerSide(target, "course_cancel");
}
}

View File

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

View File

@@ -0,0 +1,18 @@
#include "AgMonumentRaceGoal.h"
#include "EntityManager.h"
void AgMonumentRaceGoal::OnStartup(Entity* self)
{
self->SetProximityRadius(15, "RaceGoal");
}
void AgMonumentRaceGoal::OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status)
{
if (name == "RaceGoal" && entering->IsPlayer() && status == "ENTER")
{
auto* manager = EntityManager::Instance()->GetEntitiesInGroup("race_manager")[0];
manager->OnFireEventServerSide(entering, "course_finish");
}
}

View File

@@ -0,0 +1,9 @@
#pragma once
#include "CppScripts.h"
class AgMonumentRaceGoal : public CppScripts::Script
{
public:
void OnStartup(Entity* self) override;
void OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) override;
};

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}};
Loot::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;
};

48
dScripts/AgPropGuard.cpp Normal file
View File

@@ -0,0 +1,48 @@
#include "AgPropGuard.h"
#include "Entity.h"
#include "Character.h"
#include "GameMessages.h"
#include "EntityManager.h"
#include "InventoryComponent.h"
#include "Item.h"
void AgPropGuard::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState)
{
auto* character = target->GetCharacter();
auto* missionComponent = target->GetComponent<MissionComponent>();
auto* inventoryComponent = target->GetComponent<InventoryComponent>();
const auto state = missionComponent->GetMissionState(320);
if (missionID == 768 && missionState == MissionState::MISSION_STATE_AVAILABLE)
{
if (!character->GetPlayerFlag(71))
{
// TODO: Cinematic "MissionCam"
}
}
else if (missionID == 768 && missionState >= MissionState::MISSION_STATE_READY_TO_COMPLETE)
{
//remove the inventory items
for (int item : gearSets)
{
auto* id = inventoryComponent->FindItemByLot(item);
if (id)
{
inventoryComponent->UnEquipItem(id);
inventoryComponent->RemoveItem(id->GetLot(), id->GetCount());
}
}
}
else if (
(missionID == 320 && state == MissionState::MISSION_STATE_AVAILABLE) /*||
(state == MissionState::MISSION_STATE_COMPLETE && missionID == 891 && missionState == MissionState::MISSION_STATE_READY_TO_COMPLETE)*/
)
{
//GameMessages::SendNotifyClientObject(EntityManager::Instance()->GetZoneControlEntity()->GetObjectID(), u"GuardChat", target->GetObjectID(), 0, target->GetObjectID(), "", target->GetSystemAddress());
target->GetCharacter()->SetPlayerFlag(113, true);
EntityManager::Instance()->GetZoneControlEntity()->AddTimer("GuardFlyAway", 1.0f);
}
}

11
dScripts/AgPropGuard.h Normal file
View File

@@ -0,0 +1,11 @@
#pragma once
#include "CppScripts.h"
class AgPropGuard final : public CppScripts::Script
{
public:
void OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState) override;
private:
std::vector<int> gearSets = { 14359,14321,14353,14315 };
};

56
dScripts/AgPropguards.cpp Normal file
View File

@@ -0,0 +1,56 @@
#include "AgPropguards.h"
#include "Character.h"
#include "GameMessages.h"
#include "EntityManager.h"
#include "dZoneManager.h"
void AgPropguards::OnMissionDialogueOK(Entity *self, Entity *target, int missionID, MissionState missionState) {
auto* character = target->GetCharacter();
if (character == nullptr)
return;
const auto flag = GetFlagForMission(missionID);
if (flag == 0)
return;
if ((missionState == MissionState::MISSION_STATE_AVAILABLE || missionState == MissionState::MISSION_STATE_ACTIVE)
&& !character->GetPlayerFlag(flag)) {
// If the player just started the mission, play a cinematic highlighting the target
GameMessages::SendPlayCinematic(target->GetObjectID(), u"MissionCam", target->GetSystemAddress());
} else if (missionState == MissionState::MISSION_STATE_COMPLETE_READY_TO_COMPLETE) {
// Makes the guard disappear once the mission has been completed
const auto zoneControlID = EntityManager::Instance()->GetZoneControlEntity()->GetObjectID();
GameMessages::SendNotifyClientObject(zoneControlID, u"GuardChat", 0, 0, self->GetObjectID(),
"", UNASSIGNED_SYSTEM_ADDRESS);
self->AddCallbackTimer(5.0f, [self]() {
auto spawnerName = self->GetVar<std::string>(u"spawner_name");
if (spawnerName.empty())
spawnerName = "Guard";
auto spawners = dZoneManager::Instance()->GetSpawnersByName(spawnerName);
for (auto* spawner : spawners) {
spawner->Deactivate();
}
self->Smash();
});
}
}
uint32_t AgPropguards::GetFlagForMission(uint32_t missionID) {
switch (missionID) {
case 872:
return 97;
case 873:
return 98;
case 874:
return 99;
case 1293:
return 118;
case 1322:
return 122;
default:
return 0;
}
}

8
dScripts/AgPropguards.h Normal file
View File

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

62
dScripts/AgQbElevator.cpp Normal file
View File

@@ -0,0 +1,62 @@
#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
}

19
dScripts/AgQbElevator.h Normal file
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,14 @@
#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,12 @@
#include "AgShipPlayerDeathTrigger.h"
#include "Entity.h"
#include "GameMessages.h"
#include "Game.h"
#include "dLogger.h"
void AgShipPlayerDeathTrigger::OnCollisionPhantom(Entity* self, Entity* target) {
if (target->GetLOT() == 1 && !target->GetIsDead()) {
Game::logger->Log("CppScripts::AgShipPlayerDeathTrigger", "Attempting to kill %llu\n", target->GetObjectID());
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,22 @@
#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;
};

109
dScripts/AgSpaceStuff.cpp Normal file
View File

@@ -0,0 +1,109 @@
#include "AgSpaceStuff.h"
#include "GeneralUtils.h"
#include "GameMessages.h"
#include "dZoneManager.h"
#include "EntityManager.h"
#include "Game.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", 1.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;
}

18
dScripts/AgSpaceStuff.h Normal file
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,15 @@
#include "AgSurvivalMech.h"
#include "DestroyableComponent.h"
void AgSurvivalMech::OnStartup(Entity *self) {
BaseWavesGenericEnemy::OnStartup(self);
auto* destroyable = self->GetComponent<DestroyableComponent>();
if (destroyable != nullptr) {
destroyable->SetFaction(4);
}
}
uint32_t AgSurvivalMech::GetPoints() {
return 200;
}

View File

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

View File

@@ -0,0 +1,16 @@
#include "AgSurvivalSpiderling.h"
#include "BaseCombatAIComponent.h"
#include "GameMessages.h"
void AgSurvivalSpiderling::OnStartup(Entity *self) {
BaseWavesGenericEnemy::OnStartup(self);
auto* combatAI = self->GetComponent<BaseCombatAIComponent>();
if (combatAI != nullptr) {
combatAI->SetStunImmune(true);
}
}
uint32_t AgSurvivalSpiderling::GetPoints() {
return 300;
}

View File

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

View File

@@ -0,0 +1,5 @@
#include "AgSurvivalStromling.h"
uint32_t AgSurvivalStromling::GetPoints() {
return 100;
}

View File

@@ -0,0 +1,6 @@
#pragma once
#include "BaseWavesGenericEnemy.h"
class AgSurvivalStromling : public BaseWavesGenericEnemy {
uint32_t GetPoints() override;
};

19
dScripts/AgTurret.cpp Normal file
View File

@@ -0,0 +1,19 @@
#include "AgTurret.h"
#include "EntityManager.h"
#include "RebuildComponent.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");
}

8
dScripts/AgTurret.h Normal file
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,14 @@
#include "AllCrateChicken.h"
#include "dCommonVars.h"
#include "EntityManager.h"
#include "Entity.h"
void AllCrateChicken::OnStartup(Entity* self) {
self->AddTimer("KillRooster", 4.2f);
}
void AllCrateChicken::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "KillRooster") {
self->ScheduleKillAfterUpdate();
}
}

View File

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

55
dScripts/AmBlueX.cpp Normal file
View File

@@ -0,0 +1,55 @@
#include "AmBlueX.h"
#include "SkillComponent.h"
#include "EntityManager.h"
#include "Character.h"
void AmBlueX::OnUse(Entity *self, Entity *user) {
auto* skillComponent = user->GetComponent<SkillComponent>();
if (skillComponent != nullptr) {
skillComponent->CalculateBehavior(m_SwordSkill, m_SwordBehavior, self->GetObjectID());
}
}
void AmBlueX::OnSkillEventFired(Entity *self, Entity *caster, const std::string &message) {
if (message == "FireDukesStrike") {
self->SetNetworkVar<bool>(m_XUsedVariable, true);
self->SetNetworkVar<bool>(m_StartEffectVariable, true);
auto* character = caster->GetCharacter();
if (character != nullptr) {
character->SetPlayerFlag(self->GetVar<int32_t>(m_FlagVariable), true);
}
EntityInfo info {};
info.lot = m_FXObject;
info.pos = self->GetPosition();
info.rot = self->GetRotation();
info.spawnerID = self->GetObjectID();
auto* fxObject = EntityManager::Instance()->CreateEntity(info, nullptr, self);
EntityManager::Instance()->ConstructEntity(fxObject);
auto fxObjectID = fxObject->GetObjectID();
auto playerID = caster->GetObjectID();
// Add a callback for the bomb to explode
self->AddCallbackTimer(m_BombTime, [this, self, fxObjectID, playerID]() {
auto* fxObject = EntityManager::Instance()->GetEntity(fxObjectID);
auto* player = EntityManager::Instance()->GetEntity(playerID);
auto* skillComponent = self->GetComponent<SkillComponent>();
if (skillComponent == nullptr)
return;
// Cast the skill that destroys the object
if (player != nullptr) {
skillComponent->CalculateBehavior(m_AOESkill, m_AOEBehavior, LWOOBJID_EMPTY, false, false, playerID);
} else {
skillComponent->CalculateBehavior(m_AOESkill, m_AOEBehavior, LWOOBJID_EMPTY);
}
fxObject->Smash();
self->Smash();
});
}
}

20
dScripts/AmBlueX.h Normal file
View File

@@ -0,0 +1,20 @@
#pragma once
#include "CppScripts.h"
class AmBlueX : public CppScripts::Script {
void OnUse(Entity *self, Entity *user) override;
void OnSkillEventFired(Entity *self, Entity *caster, const std::string &message) override;
private:
const float_t m_BombTime = 3.3f;
const uint32_t m_MissionID = 1448;
const uint32_t m_SwordSkill = 1259;
const uint32_t m_SwordBehavior = 29305;
const uint32_t m_AOESkill = 1258;
const uint32_t m_AOEBehavior = 29301;
const LOT m_FXObject = 13808;
// Variables
const std::u16string m_XUsedVariable = u"XUsed";
const std::u16string m_FlagVariable = u"flag";
const std::u16string m_StartEffectVariable = u"startEffect";
};

33
dScripts/AmBridge.cpp Normal file
View File

@@ -0,0 +1,33 @@
#include "AmBridge.h"
#include "EntityManager.h"
void AmBridge::OnStartup(Entity* self)
{
}
void AmBridge::OnRebuildComplete(Entity* self, Entity* target)
{
const auto consoles = EntityManager::Instance()->GetEntitiesInGroup("Console" + GeneralUtils::UTF16ToWTF8(self->GetVar<std::u16string>(u"bridge")));
if (consoles.empty())
{
return;
}
auto* console = consoles[0];
console->NotifyObject(self, "BridgeBuilt");
self->AddTimer("SmashBridge", 50);
}
void AmBridge::OnTimerDone(Entity* self, std::string timerName)
{
if (timerName != "SmashBridge")
{
return;
}
self->Smash(self->GetObjectID(), VIOLENT);
}

10
dScripts/AmBridge.h Normal file
View File

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

View File

@@ -0,0 +1,35 @@
#include "AmConsoleTeleportServer.h"
void AmConsoleTeleportServer::OnStartup(Entity* self)
{
self->SetVar(u"teleportAnim", m_TeleportAnim);
self->SetVar(u"teleportString", m_TeleportString);
self->SetVar(u"teleportEffectID", m_TeleportEffectID);
self->SetVar(u"teleportEffectTypes", m_TeleportEffectTypes);
}
void AmConsoleTeleportServer::OnUse(Entity* self, Entity* user)
{
BaseOnUse(self, user);
}
void AmConsoleTeleportServer::OnMessageBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData)
{
BaseOnMessageBoxResponse(self, sender, button, identifier, userData);
}
void AmConsoleTeleportServer::OnChoiceBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& buttonIdentifier, const std::u16string& identifier)
{
}
void AmConsoleTeleportServer::OnTimerDone(Entity* self, std::string timerName)
{
BaseOnTimerDone(self, timerName);
}
void AmConsoleTeleportServer::OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1, int32_t param2, int32_t param3)
{
BaseOnFireEventServerSide(self, sender, args, param1, param2, param3);
}

View File

@@ -0,0 +1,24 @@
#pragma once
#include "CppScripts.h"
#include "ChooseYourDestinationNsToNt.h"
#include "BaseConsoleTeleportServer.h"
#include "AMFFormat.h"
class AmConsoleTeleportServer : public CppScripts::Script, BaseConsoleTeleportServer
{
public:
void OnStartup(Entity* self) override;
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;
void OnChoiceBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& buttonIdentifier, const std::u16string& identifier) override;
void OnTimerDone(Entity* self, std::string timerName) override;
void OnFireEventServerSide(Entity *self, Entity *sender, std::string args, int32_t param1, int32_t param2, int32_t param3) override;
private:
int32_t m_ChoiceZoneID = 1900;
std::string m_SpawnPoint = "NS_LW";
std::u16string m_TeleportAnim = u"nexus-teleport";
std::u16string m_TeleportString = u"UI_TRAVEL_TO_NEXUS_TOWER";
int32_t m_TeleportEffectID = 6478;
std::vector<std::u16string> m_TeleportEffectTypes = {u"teleportRings", u"teleportBeam"};
};

View File

@@ -0,0 +1,11 @@
#include "AmDarklingMech.h"
#include "DestroyableComponent.h"
void AmDarklingMech::OnStartup(Entity* self)
{
auto* destroyableComponent = self->GetComponent<DestroyableComponent>();
destroyableComponent->SetFaction(4);
qbTurretLOT = 13171;
}

12
dScripts/AmDarklingMech.h Normal file
View File

@@ -0,0 +1,12 @@
#pragma once
#include "CppScripts.h"
#include "ChooseYourDestinationNsToNt.h"
#include "BaseConsoleTeleportServer.h"
#include "AMFFormat.h"
#include "BaseEnemyMech.h"
class AmDarklingMech : public BaseEnemyMech
{
public:
void OnStartup(Entity* self) override;
};

144
dScripts/AmDrawBridge.cpp Normal file
View File

@@ -0,0 +1,144 @@
#include "AmDrawBridge.h"
#include "EntityManager.h"
#include "GameMessages.h"
#include "SimplePhysicsComponent.h"
void AmDrawBridge::OnStartup(Entity* self)
{
self->SetNetworkVar(u"InUse", false);
self->SetVar(u"BridgeDown", false);
}
void AmDrawBridge::OnUse(Entity* self, Entity* user)
{
auto* bridge = GetBridge(self);
if (bridge == nullptr)
{
return;
}
if (!self->GetNetworkVar<bool>(u"InUse"))
{
self->SetNetworkVar(u"startEffect", 5);
self->AddTimer("ChangeBridge", 5);
self->SetNetworkVar(u"InUse", true);
}
auto* player = user;
GameMessages::SendTerminateInteraction(player->GetObjectID(), FROM_INTERACTION, self->GetObjectID());
}
void AmDrawBridge::OnTimerDone(Entity* self, std::string timerName)
{
if (timerName == "ChangeBridge")
{
auto* bridge = GetBridge(self);
if (bridge == nullptr)
{
return;
}
if (!self->GetVar<bool>(u"BridgeDown"))
{
self->SetVar(u"BridgeDown", true);
MoveBridgeDown(self, bridge, true);
}
else
{
self->SetVar(u"BridgeDown", false);
MoveBridgeDown(self, bridge, false);
}
self->SetNetworkVar(u"BridgeLeaving", true);
self->SetVar(u"BridgeDown", false);
}
else if (timerName == "SmashEffectBridge")
{
self->SetNetworkVar(u"SmashBridge", 5);
}
else if (timerName == "rotateBridgeDown")
{
auto* bridge = GetBridge(self);
if (bridge == nullptr)
{
return;
}
self->SetNetworkVar(u"BridgeLeaving", false);
auto* simplePhysicsComponent = bridge->GetComponent<SimplePhysicsComponent>();
if (simplePhysicsComponent == nullptr)
{
return;
}
simplePhysicsComponent->SetAngularVelocity(NiPoint3::ZERO);
EntityManager::Instance()->SerializeEntity(bridge);
}
}
void AmDrawBridge::OnNotifyObject(Entity *self, Entity *sender, const std::string& name, int32_t param1, int32_t param2)
{
if (name == "BridgeBuilt")
{
self->SetVar(u"BridgeID", sender->GetObjectID());
self->AddTimer("SmashEffectBridge", 45);
self->SetNetworkVar(u"BridgeDead", true);
sender->AddDieCallback([this, self, sender] () {
NotifyDie(self, sender);
});
}
}
void AmDrawBridge::MoveBridgeDown(Entity* self, Entity* bridge, bool down)
{
auto* simplePhysicsComponent = bridge->GetComponent<SimplePhysicsComponent>();
if (simplePhysicsComponent == nullptr)
{
return;
}
auto forwardVect = simplePhysicsComponent->GetRotation().GetForwardVector();
auto degrees = down ? 90.0f : -90.0f;
const auto travelTime = 2.0f;
forwardVect = forwardVect * (float) ((degrees / travelTime) * (3.14f / 180.0f));
simplePhysicsComponent->SetAngularVelocity(forwardVect);
EntityManager::Instance()->SerializeEntity(bridge);
self->AddTimer("rotateBridgeDown", travelTime);
}
void AmDrawBridge::NotifyDie(Entity* self, Entity* other)
{
self->SetNetworkVar(u"InUse", false);
self->SetVar(u"BridgeDown", false);
self->CancelAllTimers();
}
Entity* AmDrawBridge::GetBridge(Entity* self)
{
const auto bridgeID = self->GetVar<LWOOBJID>(u"BridgeID");
return EntityManager::Instance()->GetEntity(bridgeID);
}

16
dScripts/AmDrawBridge.h Normal file
View File

@@ -0,0 +1,16 @@
#pragma once
#include "CppScripts.h"
class AmDrawBridge : public CppScripts::Script
{
public:
void OnStartup(Entity* self) override;
void OnUse(Entity* self, Entity* user) override;
void OnTimerDone(Entity* self, std::string timerName) override;
void OnNotifyObject(Entity *self, Entity *sender, const std::string& name, int32_t param1 = 0, int32_t param2 = 0);
void MoveBridgeDown(Entity* self, Entity* bridge, bool down);
void NotifyDie(Entity* self, Entity* other);
Entity* GetBridge(Entity* self);
};

View File

@@ -0,0 +1,98 @@
#include "AmDropshipComputer.h"
#include "MissionComponent.h"
#include "RebuildComponent.h"
#include "InventoryComponent.h"
#include "GameMessages.h"
#include "dZoneManager.h"
void AmDropshipComputer::OnStartup(Entity* self)
{
self->AddTimer("reset", 45.0f);
}
void AmDropshipComputer::OnUse(Entity* self, Entity* user)
{
auto* rebuildComponent = self->GetComponent<RebuildComponent>();
if (rebuildComponent == nullptr || rebuildComponent->GetState() != REBUILD_COMPLETED)
{
return;
}
auto* missionComponent = user->GetComponent<MissionComponent>();
auto* inventoryComponent = user->GetComponent<InventoryComponent>();
if (missionComponent == nullptr || inventoryComponent == nullptr)
{
return;
}
if (inventoryComponent->GetLotCount(12323) != 0)
{
return;
}
inventoryComponent->AddItem(12323, 1);
}
void AmDropshipComputer::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 AmDropshipComputer::OnTimerDone(Entity* self, std::string timerName)
{
auto* rebuildComponent = self->GetComponent<RebuildComponent>();
if (rebuildComponent == nullptr)
{
return;
}
if (timerName == "reset" && rebuildComponent->GetState() == REBUILD_OPEN)
{
self->Smash(self->GetObjectID(), SILENT);
}
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,17 @@
#include "AmScrollReaderServer.h"
#include "MissionComponent.h"
void AmScrollReaderServer::OnMessageBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData)
{
if (identifier == u"story_end")
{
auto* missionComponent = sender->GetComponent<MissionComponent>();
if (missionComponent == nullptr)
{
return;
}
missionComponent->ForceProgressTaskType(969, 1, 1, false);
}
}

View File

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

View File

@@ -0,0 +1,173 @@
#include "AmShieldGenerator.h"
#include "EntityManager.h"
#include "DestroyableComponent.h"
#include "GameMessages.h"
#include "MovementAIComponent.h"
#include "BaseCombatAIComponent.h"
#include "SkillComponent.h"
void AmShieldGenerator::OnStartup(Entity* self)
{
self->SetProximityRadius(20, "shield");
self->SetProximityRadius(21, "buffer");
StartShield(self);
}
void AmShieldGenerator::OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status)
{
auto* destroyableComponent = entering->GetComponent<DestroyableComponent>();
if (status == "ENTER" && name == "shield")
{
if (destroyableComponent->HasFaction(4))
{
EnemyEnteredShield(self, entering);
}
}
if (name != "buffer" || !entering->IsPlayer())
{
return;
}
auto entitiesInProximity = self->GetVar<std::vector<LWOOBJID>>(u"Players");
if (status == "ENTER")
{
const auto& iter = std::find(entitiesInProximity.begin(), entitiesInProximity.end(), entering->GetObjectID());
if (iter == entitiesInProximity.end())
{
entitiesInProximity.push_back(entering->GetObjectID());
}
}
else if (status == "LEAVE")
{
const auto& iter = std::find(entitiesInProximity.begin(), entitiesInProximity.end(), entering->GetObjectID());
if (iter != entitiesInProximity.end())
{
entitiesInProximity.erase(iter);
}
}
self->SetVar<std::vector<LWOOBJID>>(u"Players", entitiesInProximity);
}
void AmShieldGenerator::OnDie(Entity* self, Entity* killer)
{
self->CancelAllTimers();
auto* child = EntityManager::Instance()->GetEntity(self->GetVar<LWOOBJID>(u"Child"));
if (child != nullptr)
{
child->Kill();
}
}
void AmShieldGenerator::OnTimerDone(Entity* self, std::string timerName)
{
if (timerName == "BuffPlayers")
{
BuffPlayers(self);
self->AddTimer("BuffPlayers", 3.0f);
}
else if (timerName == "PlayFX")
{
GameMessages::SendPlayFXEffect(self->GetObjectID(), 5351, u"generatorOn", "generatorOn");
self->AddTimer("PlayFX", 1.5f);
}
else if (timerName == "RefreshEnemies")
{
auto enemiesInProximity = self->GetVar<std::vector<LWOOBJID>>(u"Enemies");
for (const auto enemyID : enemiesInProximity)
{
auto* enemy = EntityManager::Instance()->GetEntity(enemyID);
if (enemy != nullptr)
{
EnemyEnteredShield(self, enemy);
}
}
self->AddTimer("RefreshEnemies", 1.5f);
}
}
void AmShieldGenerator::StartShield(Entity* self)
{
self->AddTimer("PlayFX", 1.5f);
self->AddTimer("BuffPlayers", 3.0f);
self->AddTimer("RefreshEnemies", 1.5f);
const auto myPos = self->GetPosition();
const auto myRot = self->GetRotation();
EntityInfo info {};
info.lot = 13111;
info.pos = myPos;
info.rot = myRot;
info.spawnerID = self->GetObjectID();
auto* child = EntityManager::Instance()->CreateEntity(info);
self->SetVar(u"Child", child->GetObjectID());
BuffPlayers(self);
}
void AmShieldGenerator::BuffPlayers(Entity* self)
{
auto* skillComponent = self->GetComponent<SkillComponent>();
if (skillComponent == nullptr)
{
return;
}
auto entitiesInProximity = self->GetVar<std::vector<LWOOBJID>>(u"Players");
for (const auto playerID : entitiesInProximity)
{
auto* player = EntityManager::Instance()->GetEntity(playerID);
if (player == nullptr)
{
return;
}
skillComponent->CalculateBehavior(1200, 27024, playerID, true);
}
}
void AmShieldGenerator::EnemyEnteredShield(Entity* self, Entity* intruder)
{
auto* baseCombatAIComponent = intruder->GetComponent<BaseCombatAIComponent>();
auto* movementAIComponent = intruder->GetComponent<MovementAIComponent>();
if (baseCombatAIComponent == nullptr || movementAIComponent == nullptr)
{
return;
}
auto dir = intruder->GetRotation().GetForwardVector() * -1;
dir.y += 15;
dir.x *= 50;
dir.z *= 50;
// TODO: Figure out how todo knockback, I'll stun them for now
if (NiPoint3::DistanceSquared(self->GetPosition(), movementAIComponent->GetCurrentPosition()) < 20 * 20)
{
baseCombatAIComponent->Stun(2.0f);
movementAIComponent->SetDestination(baseCombatAIComponent->GetStartPosition());
}
baseCombatAIComponent->ClearThreat();
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include "CppScripts.h"
class AmShieldGenerator : public CppScripts::Script
{
public:
void OnStartup(Entity* self) override;
void OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) override;
void OnDie(Entity* self, Entity* killer) override;
void OnTimerDone(Entity* self, std::string timerName) override;
void StartShield(Entity* self);
void BuffPlayers(Entity* self);
void EnemyEnteredShield(Entity* self, Entity* intruder);
};

View File

@@ -0,0 +1,243 @@
#include "AmShieldGeneratorQuickbuild.h"
#include "EntityManager.h"
#include "DestroyableComponent.h"
#include "GameMessages.h"
#include "MovementAIComponent.h"
#include "BaseCombatAIComponent.h"
#include "SkillComponent.h"
#include "RebuildComponent.h"
#include "MissionComponent.h"
void AmShieldGeneratorQuickbuild::OnStartup(Entity* self)
{
self->SetProximityRadius(20, "shield");
self->SetProximityRadius(21, "buffer");
}
void AmShieldGeneratorQuickbuild::OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status)
{
auto* destroyableComponent = entering->GetComponent<DestroyableComponent>();
if (name == "shield")
{
if (!destroyableComponent->HasFaction(4) || entering->IsPlayer())
{
return;
}
auto enemiesInProximity = self->GetVar<std::vector<LWOOBJID>>(u"Enemies");
if (status == "ENTER")
{
EnemyEnteredShield(self, entering);
const auto& iter = std::find(enemiesInProximity.begin(), enemiesInProximity.end(), entering->GetObjectID());
if (iter == enemiesInProximity.end())
{
enemiesInProximity.push_back(entering->GetObjectID());
}
}
else if (status == "LEAVE")
{
const auto& iter = std::find(enemiesInProximity.begin(), enemiesInProximity.end(), entering->GetObjectID());
if (iter != enemiesInProximity.end())
{
enemiesInProximity.erase(iter);
}
}
self->SetVar<std::vector<LWOOBJID>>(u"Enemies", enemiesInProximity);
}
if (name != "buffer" || !entering->IsPlayer())
{
return;
}
auto entitiesInProximity = self->GetVar<std::vector<LWOOBJID>>(u"Players");
if (status == "ENTER")
{
const auto& iter = std::find(entitiesInProximity.begin(), entitiesInProximity.end(), entering->GetObjectID());
if (iter == entitiesInProximity.end())
{
entitiesInProximity.push_back(entering->GetObjectID());
}
}
else if (status == "LEAVE")
{
const auto& iter = std::find(entitiesInProximity.begin(), entitiesInProximity.end(), entering->GetObjectID());
if (iter != entitiesInProximity.end())
{
entitiesInProximity.erase(iter);
}
}
self->SetVar<std::vector<LWOOBJID>>(u"Players", entitiesInProximity);
}
void AmShieldGeneratorQuickbuild::OnDie(Entity* self, Entity* killer)
{
self->CancelAllTimers();
auto* child = EntityManager::Instance()->GetEntity(self->GetVar<LWOOBJID>(u"Child"));
if (child != nullptr)
{
child->Kill();
}
}
void AmShieldGeneratorQuickbuild::OnTimerDone(Entity* self, std::string timerName)
{
if (timerName == "BuffPlayers")
{
BuffPlayers(self);
self->AddTimer("BuffPlayers", 3.0f);
}
else if (timerName == "PlayFX")
{
GameMessages::SendPlayFXEffect(self->GetObjectID(), 5351, u"generatorOn", "generatorOn");
self->AddTimer("PlayFX", 1.5f);
}
else if (timerName == "RefreshEnemies")
{
auto enemiesInProximity = self->GetVar<std::vector<LWOOBJID>>(u"Enemies");
for (const auto enemyID : enemiesInProximity)
{
auto* enemy = EntityManager::Instance()->GetEntity(enemyID);
if (enemy != nullptr)
{
EnemyEnteredShield(self, enemy);
}
}
self->AddTimer("RefreshEnemies", 1.5f);
}
}
void AmShieldGeneratorQuickbuild::OnRebuildComplete(Entity* self, Entity* target)
{
StartShield(self);
auto enemiesInProximity = self->GetVar<std::vector<LWOOBJID>>(u"Enemies");
for (const auto enemyID : enemiesInProximity)
{
auto* enemy = EntityManager::Instance()->GetEntity(enemyID);
if (enemy != nullptr)
{
enemy->Smash();
}
}
auto entitiesInProximity = self->GetVar<std::vector<LWOOBJID>>(u"Players");
for (const auto playerID : entitiesInProximity)
{
auto* player = EntityManager::Instance()->GetEntity(playerID);
if (player == nullptr)
{
continue;
}
auto* missionComponent = player->GetComponent<MissionComponent>();
if (missionComponent == nullptr)
{
return;
}
missionComponent->ForceProgressTaskType(987, 1, 1, false);
}
}
void AmShieldGeneratorQuickbuild::StartShield(Entity* self)
{
self->AddTimer("PlayFX", 1.5f);
self->AddTimer("BuffPlayers", 3.0f);
self->AddTimer("RefreshEnemies", 1.5f);
const auto myPos = self->GetPosition();
const auto myRot = self->GetRotation();
EntityInfo info {};
info.lot = 13111;
info.pos = myPos;
info.rot = myRot;
info.spawnerID = self->GetObjectID();
auto* child = EntityManager::Instance()->CreateEntity(info);
self->SetVar(u"Child", child->GetObjectID());
BuffPlayers(self);
}
void AmShieldGeneratorQuickbuild::BuffPlayers(Entity* self)
{
auto* skillComponent = self->GetComponent<SkillComponent>();
if (skillComponent == nullptr)
{
return;
}
auto entitiesInProximity = self->GetVar<std::vector<LWOOBJID>>(u"Players");
for (const auto playerID : entitiesInProximity)
{
auto* player = EntityManager::Instance()->GetEntity(playerID);
if (player == nullptr)
{
return;
}
skillComponent->CalculateBehavior(1200, 27024, playerID, true);
}
}
void AmShieldGeneratorQuickbuild::EnemyEnteredShield(Entity* self, Entity* intruder)
{
auto* rebuildComponent = self->GetComponent<RebuildComponent>();
if (rebuildComponent == nullptr || rebuildComponent->GetState() != REBUILD_COMPLETED)
{
return;
}
auto* baseCombatAIComponent = intruder->GetComponent<BaseCombatAIComponent>();
auto* movementAIComponent = intruder->GetComponent<MovementAIComponent>();
if (baseCombatAIComponent == nullptr || movementAIComponent == nullptr)
{
return;
}
auto dir = intruder->GetRotation().GetForwardVector() * -1;
dir.y += 15;
dir.x *= 50;
dir.z *= 50;
// TODO: Figure out how todo knockback, I'll stun them for now
if (NiPoint3::DistanceSquared(self->GetPosition(), movementAIComponent->GetCurrentPosition()) < 20 * 20)
{
baseCombatAIComponent->Stun(2.0f);
movementAIComponent->SetDestination(baseCombatAIComponent->GetStartPosition());
}
baseCombatAIComponent->ClearThreat();
}

View File

@@ -0,0 +1,16 @@
#pragma once
#include "CppScripts.h"
class AmShieldGeneratorQuickbuild : public CppScripts::Script
{
public:
void OnStartup(Entity* self) override;
void OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) override;
void OnDie(Entity* self, Entity* killer) override;
void OnTimerDone(Entity* self, std::string timerName) override;
void OnRebuildComplete(Entity* self, Entity* target) override;
void StartShield(Entity* self);
void BuffPlayers(Entity* self);
void EnemyEnteredShield(Entity* self, Entity* intruder);
};

View File

@@ -0,0 +1,27 @@
#include "AmSkeletonEngineer.h"
#include "DestroyableComponent.h"
#include "SkillComponent.h"
void AmSkeletonEngineer::OnHit(Entity* self, Entity* attacker)
{
auto* destroyableComponent = self->GetComponent<DestroyableComponent>();
auto* skillComponent = self->GetComponent<SkillComponent>();
if (destroyableComponent == nullptr || skillComponent == nullptr)
{
return;
}
if (destroyableComponent->GetHealth() < 12 && !self->GetVar<bool>(u"injured"))
{
self->SetVar(u"injured", true);
skillComponent->CalculateBehavior(953, 19864, self->GetObjectID(), true);
const auto attackerID = attacker->GetObjectID();
self->AddCallbackTimer(4.5f, [this, self, attackerID] () {
self->Smash(attackerID);
});
}
}

View File

@@ -0,0 +1,9 @@
#pragma once
#include "CppScripts.h"
#include "EnemyNjBuff.h"
class AmSkeletonEngineer : public EnemyNjBuff
{
public:
void OnHit(Entity* self, Entity* attacker) override;
};

View File

@@ -0,0 +1,388 @@
#include "AmSkullkinDrill.h"
#include "GameMessages.h"
#include "MovingPlatformComponent.h"
#include "DestroyableComponent.h"
#include "ProximityMonitorComponent.h"
#include "MissionComponent.h"
void AmSkullkinDrill::OnStartup(Entity* self)
{
self->SetNetworkVar(u"bIsInUse", false);
self->SetVar(u"bActive", true);
GameMessages::SendPlayFXEffect(self->GetObjectID(), -1, u"spin", "active");
auto* movingPlatformComponent = self->GetComponent<MovingPlatformComponent>();
if (movingPlatformComponent == nullptr)
{
return;
}
movingPlatformComponent->SetSerialized(true);
movingPlatformComponent->GotoWaypoint(0);
auto* standObj = GetStandObj(self);
if (standObj != nullptr)
{
standObj->SetVar(u"bActive", true);
}
self->SetProximityRadius(5, "spin_distance");
}
Entity* AmSkullkinDrill::GetStandObj(Entity* self)
{
const auto& myGroup = self->GetGroups();
if (myGroup.empty())
{
return nullptr;
}
std::string groupName = "Drill_Stand_";
groupName.push_back(myGroup[0][myGroup[0].size() - 1]);
const auto standObjs = EntityManager::Instance()->GetEntitiesInGroup(groupName);
if (standObjs.empty())
{
return nullptr;
}
return standObjs[0];
}
void AmSkullkinDrill::OnSkillEventFired(Entity* self, Entity* caster, const std::string& message)
{
if (message != "NinjagoSpinEvent" || self->GetNetworkVar<bool>(u"bIsInUse"))
{
return;
}
auto* proximityMonitorComponent = self->GetComponent<ProximityMonitorComponent>();
if (proximityMonitorComponent == nullptr || !proximityMonitorComponent->IsInProximity("spin_distance", caster->GetObjectID()))
{
return;
}
self->SetVar(u"activaterID", caster->GetObjectID());
self->SetNetworkVar(u"bIsInUse", true);
TriggerDrill(self);
}
void AmSkullkinDrill::TriggerDrill(Entity* self)
{
GameMessages::SendPlayAnimation(self, u"slowdown");
self->AddTimer("killDrill", 10.0f);
auto* standObj = GetStandObj(self);
if (standObj != nullptr)
{
Game::logger->Log("AmSkullkinDrill", "Disabling knockback\n");
standObj->SetVar(u"bActive", false);
}
auto* movingPlatformComponent = self->GetComponent<MovingPlatformComponent>();
if (movingPlatformComponent == nullptr)
{
return;
}
movingPlatformComponent->GotoWaypoint(1);
}
void AmSkullkinDrill::OnWaypointReached(Entity* self, uint32_t waypointIndex)
{
if (waypointIndex == 1)
{
auto myPos = self->GetPosition();
auto myRot = self->GetRotation();
myPos.y -= 21;
EntityInfo info = {};
info.lot = 12346;
info.pos = myPos;
info.rot = myRot;
info.scale = 3; // Needs the scale, otherwise attacks fail
info.spawnerID = self->GetObjectID();
auto* child = EntityManager::Instance()->CreateEntity(info);
EntityManager::Instance()->ConstructEntity(child);
self->SetVar(u"ChildSmash", child->GetObjectID());
child->AddDieCallback([this, self] () {
const auto& userID = self->GetVar<LWOOBJID>(u"activaterID");
auto* player = EntityManager::Instance()->GetEntity(userID);
if (player == nullptr)
{
return;
}
OnHitOrHealResult(self, player, 1);
});
}
OnArrived(self, waypointIndex);
}
void AmSkullkinDrill::OnUse(Entity* self, Entity* user)
{
if (self->GetNetworkVar<bool>(u"bIsInUse"))
{
return;
}
self->SetNetworkVar(u"bIsInUse", true);
GameMessages::SendPlayFXEffect(user->GetObjectID(), 5499, u"on-anim", "tornado");
GameMessages::SendPlayFXEffect(user->GetObjectID(), 5502, u"on-anim", "staff");
const auto userID = user->GetObjectID();
self->SetVar(u"userID", userID);
self->SetVar(u"activaterID", userID);
PlayAnim(self, user, "spinjitzu-staff-windup");
PlayCinematic(self);
FreezePlayer(self, user, true);
}
void AmSkullkinDrill::FreezePlayer(Entity* self, Entity* player, bool bFreeze)
{
eStunState eChangeType = POP;
if (bFreeze)
{
if (player->GetIsDead())
{
return;
}
eChangeType = PUSH;
}
else
{
if (player->GetIsDead())
{
//
}
}
GameMessages::SendSetStunned(player->GetObjectID(), eChangeType, player->GetSystemAddress(), self->GetObjectID(),
true, false, true, false, true, false, true
);
}
void AmSkullkinDrill::OnArrived(Entity* self, uint32_t waypointIndex)
{
auto* standObj = GetStandObj(self);
if (waypointIndex == 1)
{
GameMessages::SendPlayAnimation(self, u"no-spin");
GameMessages::SendStopFXEffect(self, true, "active");
GameMessages::SendPlayFXEffect(self->GetObjectID(), -1, u"indicator", "indicator");
self->SetVar(u"bActive", false);
const auto playerID = self->GetVar<LWOOBJID>(u"userID");
auto* player = EntityManager::Instance()->GetEntity(playerID);
if (player != nullptr)
{
PlayAnim(self, player, "spinjitzu-staff-end");
}
if (standObj != nullptr)
{
Game::logger->Log("AmSkullkinDrill", "Disabling knockback\n");
standObj->SetVar(u"bActive", false);
}
return;
}
else
{
GameMessages::SendPlayAnimation(self, u"idle");
GameMessages::SendPlayFXEffect(self->GetObjectID(), -1, u"spin", "active");
GameMessages::SendStopFXEffect(self, true, "indicator");
}
}
void AmSkullkinDrill::PlayCinematic(Entity* self)
{
auto* player = EntityManager::Instance()->GetEntity(self->GetVar<LWOOBJID>(u"userID"));
if (player == nullptr)
{
return;
}
const auto& cine = self->GetVar<std::u16string>(u"cinematic");
if (cine.empty())
{
return;
}
GameMessages::SendPlayCinematic(player->GetObjectID(), cine, player->GetSystemAddress());
}
void AmSkullkinDrill::PlayAnim(Entity* self, Entity* player, const std::string& animName)
{
const auto animTime = animName == "spinjitzu-staff-end" ? 0.5f : 1.0f;
GameMessages::SendPlayAnimation(player, GeneralUtils::ASCIIToUTF16(animName));
self->AddTimer("AnimDone_" + animName, animTime);
}
void AmSkullkinDrill::OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage)
{
auto* destroyableComponent = self->GetComponent<DestroyableComponent>();
if (destroyableComponent == nullptr || !attacker->IsPlayer())
{
return;
}
if (self->GetVar<bool>(u"bActive"))
{
return;
}
const auto activaterID = self->GetVar<LWOOBJID>(u"activaterID");
auto* activator = EntityManager::Instance()->GetEntity(activaterID);
// TODO: Missions
if (activator != nullptr)
{
auto* missionComponent = activator->GetComponent<MissionComponent>();
if (missionComponent != nullptr)
{
for (const auto missionID : m_MissionsToUpdate)
{
missionComponent->ForceProgressValue(missionID, 1, self->GetLOT());
}
}
}
self->Smash(attacker->GetObjectID(), SILENT);
self->CancelAllTimers();
auto* standObj = GetStandObj(self);
if (standObj != nullptr)
{
GameMessages::SendPlayFXEffect(standObj->GetObjectID(), 4946, u"explode", "explode");
}
}
void AmSkullkinDrill::OnTimerDone(Entity* self, std::string timerName)
{
Game::logger->Log("AmSkullkinDrill", "Timer: %s\n", timerName.c_str());
if (timerName == "killDrill")
{
const auto childID = self->GetVar<LWOOBJID>(u"ChildSmash");
auto* child = EntityManager::Instance()->GetEntity(childID);
if (child != nullptr)
{
child->Smash(self->GetObjectID(), SILENT);
}
self->SetNetworkVar(u"bIsInUse", false);
self->SetVar(u"bActive", true);
self->SetVar(u"activaterID", LWOOBJID_EMPTY);
auto* standObj = GetStandObj(self);
if (standObj != nullptr)
{
Game::logger->Log("AmSkullkinDrill", "Enabling knockback\n");
standObj->SetVar(u"bActive", true);
}
auto* movingPlatformComponent = self->GetComponent<MovingPlatformComponent>();
if (movingPlatformComponent == nullptr)
{
return;
}
movingPlatformComponent->GotoWaypoint(0);
return;
}
const auto& data = GeneralUtils::SplitString(timerName, '_');
if (data.empty())
{
return;
}
if (data[0] == "AnimDone")
{
const auto& animName = data[1];
Game::logger->Log("AmSkullkinDrill", "Anim done: %s\n", animName.c_str());
const auto playerID = self->GetVar<LWOOBJID>(u"userID");
auto* player = EntityManager::Instance()->GetEntity(playerID);
if (player == nullptr)
{
return;
}
if (animName == "spinjitzu-staff-windup")
{
Game::logger->Log("AmSkullkinDrill", "Triggering drill\n");
TriggerDrill(self);
GameMessages::SendPlayAnimation(player, u"spinjitzu-staff-loop");
}
else if (animName == "spinjitzu-staff-end")
{
FreezePlayer(self, player, false);
self->SetVar(u"userID", LWOOBJID_EMPTY);
GameMessages::SendStopFXEffect(player, true, "tornado");
GameMessages::SendStopFXEffect(player, true, "staff");
}
}
else if (data[0] == "TryUnFreezeAgain")
{
}
}

View File

@@ -0,0 +1,33 @@
#pragma once
#include "CppScripts.h"
class AmSkullkinDrill : public CppScripts::Script
{
public:
void OnStartup(Entity* self) override;
Entity* GetStandObj(Entity* self);
void OnSkillEventFired(Entity* self, Entity* caster, const std::string& message) override;
void TriggerDrill(Entity* self);
void OnWaypointReached(Entity* self, uint32_t waypointIndex) override;
void OnUse(Entity* self, Entity* user) override;
void FreezePlayer(Entity* self, Entity* player, bool bFreeze);
void OnArrived(Entity* self, uint32_t waypointIndex);
void PlayCinematic(Entity* self);
void PlayAnim(Entity* self, Entity* player, const std::string& animName);
void OnHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) override;
void OnTimerDone(Entity* self, std::string timerName) override;
private:
std::vector<int32_t> m_MissionsToUpdate = {972, 1305, 1308};
};

View File

@@ -0,0 +1,40 @@
#include "AmSkullkinDrillStand.h"
#include "GameMessages.h"
#include "dpEntity.h"
void AmSkullkinDrillStand::OnStartup(Entity* self)
{
self->SetVar(u"bActive", true);
self->SetProximityRadius(new dpEntity(self->GetObjectID(), {6, 14, 6}), "knockback");
}
void AmSkullkinDrillStand::OnNotifyObject(Entity *self, Entity *sender, const std::string& name, int32_t param1, int32_t param2)
{
}
void AmSkullkinDrillStand::OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status)
{
if (!self->GetVar<bool>(u"bActive"))
{
return;
}
if (!entering->IsPlayer() || status != "ENTER" || name != "knockback")
{
return;
}
auto myPos = self->GetPosition();
auto objPos = entering->GetPosition();
NiPoint3 newVec = {(objPos.x - myPos.x) * 4.5f, 15, (objPos.z - myPos.z) * 4.5f};
GameMessages::SendKnockback(entering->GetObjectID(), self->GetObjectID(), self->GetObjectID(), 0, newVec);
GameMessages::SendPlayFXEffect(entering->GetObjectID(), 1378, u"create", "pushBack");
GameMessages::SendPlayAnimation(entering, u"knockback-recovery");
}

View File

@@ -0,0 +1,12 @@
#pragma once
#include "CppScripts.h"
class AmSkullkinDrillStand : 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 OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) override;
};

View File

@@ -0,0 +1,283 @@
#include "AmSkullkinTower.h"
#include "EntityManager.h"
#include "DestroyableComponent.h"
#include "MovingPlatformComponent.h"
#include "dCommonVars.h"
#include "GameMessages.h"
#include "MissionComponent.h"
void AmSkullkinTower::OnStartup(Entity* self)
{
self->SetProximityRadius(20, "Tower");
// onPhysicsComponentReady
auto* movingPlatformComponent = self->GetComponent<MovingPlatformComponent>();
if (movingPlatformComponent != nullptr)
{
movingPlatformComponent->StopPathing();
}
SpawnLegs(self, "Left");
SpawnLegs(self, "Right");
SpawnLegs(self, "Rear");
}
void AmSkullkinTower::SpawnLegs(Entity* self, const std::string& loc)
{
auto pos = self->GetPosition();
auto rot = self->GetRotation();
pos.y += self->GetVarAs<float>(u"vert_offset");
auto newRot = rot;
auto offset = self->GetVarAs<float>(u"hort_offset");
auto legLOT = self->GetVar<LOT>(u"legLOT");
if (legLOT == 0)
{
return;
}
std::vector<LDFBaseData*> config = { new LDFData<std::string>(u"Leg", loc) };
EntityInfo info {};
info.lot = legLOT;
info.spawnerID = self->GetObjectID();
info.settings = config;
info.rot = newRot;
if (loc == "Right")
{
const auto dir = rot.GetForwardVector();
pos.x += dir.x * offset;
pos.z += dir.z * offset;
info.pos = pos;
}
else if (loc == "Rear")
{
const auto dir = rot.GetRightVector();
pos.x += dir.x * offset;
pos.z += dir.z * offset;
info.pos = pos;
}
else if (loc == "Left")
{
const auto dir = rot.GetForwardVector() * -1;
pos.x += dir.x * offset;
pos.z += dir.z * offset;
info.pos = pos;
}
info.rot = NiQuaternion::LookAt(info.pos, self->GetPosition());
auto* entity = EntityManager::Instance()->CreateEntity(info);
EntityManager::Instance()->ConstructEntity(entity);
OnChildLoaded(self, entity);
}
void AmSkullkinTower::OnChildLoaded(Entity* self, Entity* child)
{
auto legTable = self->GetVar<std::vector<LWOOBJID>>(u"legTable");
legTable.push_back(child->GetObjectID());
self->SetVar(u"legTable", legTable);
const auto selfID = self->GetObjectID();
child->AddDieCallback([this, selfID, child] () {
auto* self = EntityManager::Instance()->GetEntity(selfID);
auto* destroyableComponent = child->GetComponent<DestroyableComponent>();
if (destroyableComponent == nullptr || self == nullptr)
{
return;
}
NotifyDie(self, child, destroyableComponent->GetKiller());
});
}
void AmSkullkinTower::NotifyDie(Entity* self, Entity* other, Entity* killer)
{
auto players = self->GetVar<std::vector<LWOOBJID>>(u"Players");
const auto& iter = std::find(players.begin(), players.end(), killer->GetObjectID());
if (iter == players.end())
{
players.push_back(killer->GetObjectID());
}
self->SetVar(u"Players", players);
OnChildRemoved(self, other);
}
void AmSkullkinTower::OnChildRemoved(Entity* self, Entity* child)
{
auto legTable = self->GetVar<std::vector<LWOOBJID>>(u"legTable");
const auto& iter = std::find(legTable.begin(), legTable.end(), child->GetObjectID());
if (iter != legTable.end())
{
legTable.erase(iter);
}
self->SetVar(u"legTable", legTable);
if (legTable.size() == 2)
{
GameMessages::SendPlayAnimation(self, u"wobble-1");
}
else if (legTable.size() == 1)
{
GameMessages::SendPlayAnimation(self, u"wobble-2");
}
else if (legTable.empty())
{
const auto animTime = 2.5f;
GameMessages::SendPlayAnimation(self, u"fall");
self->AddTimer("spawnGuys", animTime - 0.2f);
self->CancelTimer("RespawnLeg");
self->CancelTimer("RespawnLeg");
self->CancelTimer("RespawnLeg");
std::vector<int32_t> missionIDs;
auto missionsString = self->GetVar<std::u16string>(u"missions");
if (!missionsString.empty())
{
// Split the missions string by '_'
const auto missions = GeneralUtils::SplitString(
GeneralUtils::UTF16ToWTF8(missionsString),
'_'
);
for (const auto& mission : missions)
{
int32_t missionID = 0;
if (!GeneralUtils::TryParse(mission, missionID))
{
continue;
}
missionIDs.push_back(missionID);
}
}
const auto& players = self->GetVar<std::vector<LWOOBJID>>(u"Players");
for (const auto& playerID : players)
{
auto* player = EntityManager::Instance()->GetEntity(playerID);
if (player == nullptr)
{
continue;
}
auto* missionComponent = player->GetComponent<MissionComponent>();
if (missionComponent == nullptr)
{
continue;
}
for (const auto missionID : missionIDs)
{
missionComponent->ForceProgressValue(missionID, 1, self->GetLOT());
}
//missionComponent->ForceProgressValue(1305, 1, self->GetLOT());
}
}
auto deadLegs = self->GetVar<std::vector<std::string>>(u"DeadLegs");
const auto& leg = child->GetVar<std::string>(u"Leg");
const auto& legIter = std::find(deadLegs.begin(), deadLegs.end(), leg);
if (legIter == deadLegs.end())
{
deadLegs.push_back(leg);
}
self->SetVar(u"DeadLegs", deadLegs);
self->AddTimer("RespawnLeg", 20);
}
void AmSkullkinTower::OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status)
{
if (status != "LEAVE")
{
return;
}
auto players = self->GetVar<std::vector<LWOOBJID>>(u"Players");
const auto& iter = std::find(players.begin(), players.end(), entering->GetObjectID());
if (iter != players.end())
{
players.erase(iter);
}
self->SetVar(u"Players", players);
}
void AmSkullkinTower::OnTimerDone(Entity* self, std::string timerName)
{
if (timerName == "RespawnLeg")
{
auto deadLegs = self->GetVar<std::vector<std::string>>(u"DeadLegs");
if (deadLegs.empty())
{
return;
}
SpawnLegs(self, deadLegs[0]);
deadLegs.erase(deadLegs.begin());
self->SetVar<std::vector<std::string>>(u"DeadLegs", deadLegs);
}
else if (timerName == "spawnGuys")
{
EntityInfo info {};
info.lot = self->GetVar<LOT>(u"enemyToSpawn");
auto pos = self->GetPosition();
pos.y += 7;
info.pos = pos;
info.rot = self->GetRotation();
info.spawnerID = self->GetObjectID();
for (size_t i = 0; i < 2; i++)
{
info.pos.x += i * 2; // Just to set the apart a bit
auto* entity = EntityManager::Instance()->CreateEntity(info);
EntityManager::Instance()->ConstructEntity(entity);
}
self->AddTimer("killTower", 0.7f);
}
else if (timerName == "killTower")
{
self->Smash(self->GetObjectID());
}
}

View File

@@ -0,0 +1,20 @@
#pragma once
#include "CppScripts.h"
class AmSkullkinTower : public CppScripts::Script
{
public:
void OnStartup(Entity* self) override;
void SpawnLegs(Entity* self, const std::string& loc);
void OnChildLoaded(Entity* self, Entity* child);
void NotifyDie(Entity* self, Entity* other, Entity* killer);
void OnChildRemoved(Entity* self, Entity* child);
void OnProximityUpdate(Entity* self, Entity* entering, std::string name, std::string status) override;
void OnTimerDone(Entity* self, std::string timerName) override;
};

View File

@@ -0,0 +1,27 @@
#include "AmTemplateSkillVolume.h"
#include "MissionComponent.h"
void AmTemplateSkillVolume::OnSkillEventFired(Entity* self, Entity* caster, const std::string& message)
{
if (message != "NinjagoSpinAttackEvent")
{
return;
}
auto* missionComponent = caster->GetComponent<MissionComponent>();
const auto missionIDsVariable = GeneralUtils::UTF16ToWTF8(self->GetVar<std::u16string>(u"missions"));
const auto missionIDs = GeneralUtils::SplitString(missionIDsVariable, '_');
for (const auto& missionIDStr : missionIDs)
{
int32_t missionID = 0;
if (!GeneralUtils::TryParse(missionIDStr, missionID))
{
continue;
}
missionComponent->ForceProgressTaskType(missionID, 1, 1, false);
}
}

View File

@@ -0,0 +1,8 @@
#pragma once
#include "CppScripts.h"
class AmTemplateSkillVolume : public CppScripts::Script
{
public:
void OnSkillEventFired(Entity* self, Entity* caster, const std::string& message) override;
};

13
dScripts/AnvilOfArmor.cpp Normal file
View File

@@ -0,0 +1,13 @@
#include "AnvilOfArmor.h"
void AnvilOfArmor::OnStartup(Entity *self) {
self->SetVar<uint32_t>(u"numCycles", 8);
self->SetVar<float_t>(u"secPerCycle", 25.0f);
self->SetVar<float_t>(u"delayToFirstCycle", 1.5f);
self->SetVar<float_t>(u"deathDelay", 25.0f);
self->SetVar<uint32_t>(u"numberOfPowerups", 4);
self->SetVar<LOT>(u"lootLOT", 6431);
// Initiate the actual script
OnTemplateStartup(self);
}

6
dScripts/AnvilOfArmor.h Normal file
View File

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

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