mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-08-04 09:44:10 +00:00
Organize dScripts (#814)
* Organize dScripts whitespace Remove parent scope Remove parent scope from initial setter Remove debug Remove helper programs * Fix NtImagimeterVisibility script Co-authored-by: aronwk-aaron <aronwk.aaron@gmail.com>
This commit is contained in:
24
dScripts/ai/NS/CMakeLists.txt
Normal file
24
dScripts/ai/NS/CMakeLists.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
set(DSCRIPTS_SOURCES_AI_NS
|
||||
"ClRing.cpp"
|
||||
"NsConcertChoiceBuild.cpp"
|
||||
"NsConcertInstrument.cpp"
|
||||
"NsConcertQuickBuild.cpp"
|
||||
"NsGetFactionMissionServer.cpp"
|
||||
"NsJohnnyMissionServer.cpp"
|
||||
"NsModularBuild.cpp"
|
||||
"NsQbImaginationStatue.cpp"
|
||||
"WhFans.cpp")
|
||||
|
||||
add_subdirectory(NS_PP_01)
|
||||
|
||||
foreach(file ${DSCRIPTS_SOURCES_AI_NS_NS_PP_01})
|
||||
set(DSCRIPTS_SOURCES_AI_NS ${DSCRIPTS_SOURCES_AI_NS} "NS_PP_01/${file}")
|
||||
endforeach()
|
||||
|
||||
add_subdirectory(WH)
|
||||
|
||||
foreach(file ${DSCRIPTS_SOURCES_AI_NS_WH})
|
||||
set(DSCRIPTS_SOURCES_AI_NS ${DSCRIPTS_SOURCES_AI_NS} "WH/${file}")
|
||||
endforeach()
|
||||
|
||||
set(DSCRIPTS_SOURCES_AI_NS ${DSCRIPTS_SOURCES_AI_NS} PARENT_SCOPE)
|
5
dScripts/ai/NS/ClRing.cpp
Normal file
5
dScripts/ai/NS/ClRing.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
#include "ClRing.h"
|
||||
|
||||
void ClRing::OnCollisionPhantom(Entity* self, Entity* target) {
|
||||
self->Smash(target->GetObjectID());
|
||||
}
|
8
dScripts/ai/NS/ClRing.h
Normal file
8
dScripts/ai/NS/ClRing.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class ClRing : public CppScripts::Script
|
||||
{
|
||||
public:
|
||||
void OnCollisionPhantom(Entity* self, Entity* target) override;
|
||||
};
|
3
dScripts/ai/NS/NS_PP_01/CMakeLists.txt
Normal file
3
dScripts/ai/NS/NS_PP_01/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
set(DSCRIPTS_SOURCES_AI_NS_NS_PP_01
|
||||
"PropertyDeathPlane.cpp"
|
||||
PARENT_SCOPE)
|
16
dScripts/ai/NS/NS_PP_01/PropertyDeathPlane.cpp
Normal file
16
dScripts/ai/NS/NS_PP_01/PropertyDeathPlane.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include "PropertyDeathPlane.h"
|
||||
#include "Entity.h"
|
||||
#include "GameMessages.h"
|
||||
#include "EntityManager.h"
|
||||
|
||||
void PropertyDeathPlane::OnCollisionPhantom(Entity* self, Entity* target) {
|
||||
const auto teleportGroup = EntityManager::Instance()->GetEntitiesInGroup("Teleport");
|
||||
|
||||
if (teleportGroup.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* teleport = teleportGroup[0];
|
||||
|
||||
GameMessages::SendTeleport(target->GetObjectID(), teleport->GetPosition(), teleport->GetRotation(), target->GetSystemAddress());
|
||||
}
|
9
dScripts/ai/NS/NS_PP_01/PropertyDeathPlane.h
Normal file
9
dScripts/ai/NS/NS_PP_01/PropertyDeathPlane.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class PropertyDeathPlane : public CppScripts::Script
|
||||
{
|
||||
public:
|
||||
void OnCollisionPhantom(Entity* self, Entity* target) override;
|
||||
};
|
||||
|
4
dScripts/ai/NS/NsConcertChoiceBuild.cpp
Normal file
4
dScripts/ai/NS/NsConcertChoiceBuild.cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#include "NsConcertChoiceBuild.h"
|
||||
|
||||
void NsConcertChoiceBuild::OnStartup(Entity* self) {
|
||||
}
|
7
dScripts/ai/NS/NsConcertChoiceBuild.h
Normal file
7
dScripts/ai/NS/NsConcertChoiceBuild.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class NsConcertChoiceBuild : public CppScripts::Script {
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
};
|
362
dScripts/ai/NS/NsConcertInstrument.cpp
Normal file
362
dScripts/ai/NS/NsConcertInstrument.cpp
Normal file
@@ -0,0 +1,362 @@
|
||||
#include "NsConcertInstrument.h"
|
||||
#include "GameMessages.h"
|
||||
#include "Item.h"
|
||||
#include "DestroyableComponent.h"
|
||||
#include "EntityManager.h"
|
||||
#include "RebuildComponent.h"
|
||||
#include "SoundTriggerComponent.h"
|
||||
#include "MissionComponent.h"
|
||||
|
||||
// Constants are at the bottom
|
||||
|
||||
void NsConcertInstrument::OnStartup(Entity* self) {
|
||||
self->SetVar<bool>(u"beingPlayed", false);
|
||||
self->SetVar<LWOOBJID>(u"activePlayer", LWOOBJID_EMPTY);
|
||||
self->SetVar<LWOOBJID>(u"oldItemLeft", LWOOBJID_EMPTY);
|
||||
self->SetVar<LWOOBJID>(u"oldItemRight", LWOOBJID_EMPTY);
|
||||
}
|
||||
|
||||
void NsConcertInstrument::OnRebuildNotifyState(Entity* self, eRebuildState state) {
|
||||
if (state == REBUILD_RESETTING || state == REBUILD_OPEN) {
|
||||
self->SetVar<LWOOBJID>(u"activePlayer", LWOOBJID_EMPTY);
|
||||
}
|
||||
}
|
||||
|
||||
void NsConcertInstrument::OnRebuildComplete(Entity* self, Entity* target) {
|
||||
if (!target->GetIsDead()) {
|
||||
self->SetVar<LWOOBJID>(u"activePlayer", target->GetObjectID());
|
||||
|
||||
self->AddCallbackTimer(0.2f, [self, target]() {
|
||||
RepositionPlayer(self, target);
|
||||
if (hideInstrumentOnPlay.at(GetInstrumentLot(self)))
|
||||
self->SetNetworkVar<bool>(u"Hide", true);
|
||||
});
|
||||
|
||||
self->AddCallbackTimer(0.1f, [self, target]() {
|
||||
StartPlayingInstrument(self, target);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void NsConcertInstrument::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1,
|
||||
int32_t param2, int32_t param3) {
|
||||
if (args == "stopPlaying") {
|
||||
const auto activePlayerID = self->GetVar<LWOOBJID>(u"activePlayer");
|
||||
if (activePlayerID == LWOOBJID_EMPTY)
|
||||
return;
|
||||
|
||||
const auto activePlayer = EntityManager::Instance()->GetEntity(activePlayerID);
|
||||
if (activePlayer == nullptr)
|
||||
return;
|
||||
|
||||
StopPlayingInstrument(self, activePlayer);
|
||||
}
|
||||
}
|
||||
|
||||
void NsConcertInstrument::OnTimerDone(Entity* self, std::string name) {
|
||||
const auto activePlayerID = self->GetVar<LWOOBJID>(u"activePlayer");
|
||||
if (activePlayerID == LWOOBJID_EMPTY)
|
||||
return;
|
||||
|
||||
// If for some reason the player becomes null (for example an unexpected leave), we need to clean up
|
||||
const auto activePlayer = EntityManager::Instance()->GetEntity(activePlayerID);
|
||||
if (activePlayer == nullptr && name != "cleanupAfterStop") {
|
||||
StopPlayingInstrument(self, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (activePlayer != nullptr && name == "checkPlayer" && self->GetVar<bool>(u"beingPlayed")) {
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"checkMovement", 0, 0,
|
||||
activePlayer->GetObjectID(), "", UNASSIGNED_SYSTEM_ADDRESS);
|
||||
auto* stats = activePlayer->GetComponent<DestroyableComponent>();
|
||||
if (stats) {
|
||||
if (stats->GetImagination() > 0) {
|
||||
self->AddTimer("checkPlayer", updateFrequency);
|
||||
} else {
|
||||
StopPlayingInstrument(self, activePlayer);
|
||||
}
|
||||
}
|
||||
} else if (activePlayer != nullptr && name == "deductImagination" && self->GetVar<bool>(u"beingPlayed")) {
|
||||
auto* stats = activePlayer->GetComponent<DestroyableComponent>();
|
||||
if (stats)
|
||||
stats->SetImagination(stats->GetImagination() - instrumentImaginationCost);
|
||||
|
||||
self->AddTimer("deductImagination", instrumentCostFrequency);
|
||||
} else if (name == "cleanupAfterStop") {
|
||||
if (activePlayer != nullptr) {
|
||||
UnEquipInstruments(self, activePlayer);
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"stopPlaying", 0, 0,
|
||||
activePlayer->GetObjectID(), "", UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
|
||||
auto* rebuildComponent = self->GetComponent<RebuildComponent>();
|
||||
if (rebuildComponent != nullptr)
|
||||
rebuildComponent->ResetRebuild(false);
|
||||
|
||||
self->Smash(self->GetObjectID(), VIOLENT);
|
||||
self->SetVar<LWOOBJID>(u"activePlayer", LWOOBJID_EMPTY);
|
||||
} else if (activePlayer != nullptr && name == "achievement") {
|
||||
auto* missionComponent = activePlayer->GetComponent<MissionComponent>();
|
||||
if (missionComponent != nullptr) {
|
||||
missionComponent->ForceProgress(302, 462, self->GetLOT());
|
||||
}
|
||||
self->AddTimer("achievement2", 10.0f);
|
||||
} else if (activePlayer != nullptr && name == "achievement2") {
|
||||
auto* missionComponent = activePlayer->GetComponent<MissionComponent>();
|
||||
if (missionComponent != nullptr) {
|
||||
missionComponent->ForceProgress(602, achievementTaskID.at(GetInstrumentLot(self)), self->GetLOT());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NsConcertInstrument::StartPlayingInstrument(Entity* self, Entity* player) {
|
||||
const auto instrumentLot = GetInstrumentLot(self);
|
||||
self->SetVar<bool>(u"beingPlayed", true);
|
||||
|
||||
// Stuff to notify the player
|
||||
EquipInstruments(self, player);
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"startPlaying", 0, 0,
|
||||
player->GetObjectID(), "", UNASSIGNED_SYSTEM_ADDRESS);
|
||||
GameMessages::SendPlayCinematic(player->GetObjectID(), cinematics.at(instrumentLot), UNASSIGNED_SYSTEM_ADDRESS);
|
||||
self->AddCallbackTimer(1.0f, [player, instrumentLot]() {
|
||||
GameMessages::SendPlayAnimation(player, animations.at(instrumentLot), 2.0f);
|
||||
});
|
||||
|
||||
for (auto* soundBox : EntityManager::Instance()->GetEntitiesInGroup("Audio-Concert")) {
|
||||
auto* soundTrigger = soundBox->GetComponent<SoundTriggerComponent>();
|
||||
if (soundTrigger != nullptr) {
|
||||
soundTrigger->ActivateMusicCue(music.at(instrumentLot));
|
||||
}
|
||||
}
|
||||
|
||||
// Add timers for deducting imagination and checking if the instruments can still be played
|
||||
self->AddTimer("checkPlayer", updateFrequency);
|
||||
self->AddTimer("deductImagination", instrumentCostFrequency);
|
||||
self->AddTimer("achievement", 20.0f);
|
||||
}
|
||||
|
||||
void NsConcertInstrument::StopPlayingInstrument(Entity* self, Entity* player) {
|
||||
// No use in stopping twice
|
||||
if (!self->GetVar<bool>(u"beingPlayed"))
|
||||
return;
|
||||
|
||||
const auto instrumentLot = GetInstrumentLot(self);
|
||||
|
||||
// Player might be null if they left
|
||||
if (player != nullptr) {
|
||||
auto* missions = player->GetComponent<MissionComponent>();
|
||||
if (missions != nullptr && missions->GetMissionState(176) == MissionState::MISSION_STATE_ACTIVE) {
|
||||
missions->Progress(MissionTaskType::MISSION_TASK_TYPE_SCRIPT, self->GetLOT());
|
||||
}
|
||||
|
||||
GameMessages::SendEndCinematic(player->GetObjectID(), cinematics.at(instrumentLot), UNASSIGNED_SYSTEM_ADDRESS, 1.0f);
|
||||
GameMessages::SendPlayAnimation(player, smashAnimations.at(instrumentLot), 2.0f);
|
||||
GameMessages::SendNotifyClientObject(self->GetObjectID(), u"stopCheckingMovement", 0, 0,
|
||||
player->GetObjectID(), "", UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
|
||||
self->SetVar<bool>(u"beingPlayed", false);
|
||||
|
||||
for (auto* soundBox : EntityManager::Instance()->GetEntitiesInGroup("Audio-Concert")) {
|
||||
auto* soundTrigger = soundBox->GetComponent<SoundTriggerComponent>();
|
||||
if (soundTrigger != nullptr) {
|
||||
soundTrigger->DeactivateMusicCue(music.at(instrumentLot));
|
||||
}
|
||||
}
|
||||
|
||||
self->CancelAllTimers();
|
||||
self->AddTimer("cleanupAfterStop", instrumentSmashAnimationTime.at(instrumentLot));
|
||||
}
|
||||
|
||||
void NsConcertInstrument::EquipInstruments(Entity* self, Entity* player) {
|
||||
auto* inventory = player->GetComponent<InventoryComponent>();
|
||||
if (inventory != nullptr) {
|
||||
auto equippedItems = inventory->GetEquippedItems();
|
||||
|
||||
// Un equip the current left item
|
||||
const auto equippedLeftItem = equippedItems.find("special_l");
|
||||
if (equippedLeftItem != equippedItems.end()) {
|
||||
auto* leftItem = inventory->FindItemById(equippedLeftItem->second.id);
|
||||
if (leftItem != nullptr) {
|
||||
leftItem->UnEquip();
|
||||
self->SetVar<LWOOBJID>(u"oldItemLeft", leftItem->GetId());
|
||||
}
|
||||
}
|
||||
|
||||
// Un equip the current right item
|
||||
const auto equippedRightItem = equippedItems.find("special_r");
|
||||
if (equippedRightItem != equippedItems.end()) {
|
||||
auto* rightItem = inventory->FindItemById(equippedRightItem->second.id);
|
||||
if (rightItem != nullptr) {
|
||||
rightItem->UnEquip();
|
||||
self->SetVar<LWOOBJID>(u"oldItemRight", rightItem->GetId());
|
||||
}
|
||||
}
|
||||
|
||||
// Equip the left hand instrument
|
||||
const auto leftInstrumentLot = instrumentLotLeft.find(GetInstrumentLot(self))->second;
|
||||
if (leftInstrumentLot != LOT_NULL) {
|
||||
inventory->AddItem(leftInstrumentLot, 1, eLootSourceType::LOOT_SOURCE_NONE, TEMP_ITEMS, {}, LWOOBJID_EMPTY, false);
|
||||
auto* leftInstrument = inventory->FindItemByLot(leftInstrumentLot, TEMP_ITEMS);
|
||||
leftInstrument->Equip();
|
||||
}
|
||||
|
||||
// Equip the right hand instrument
|
||||
const auto rightInstrumentLot = instrumentLotRight.find(GetInstrumentLot(self))->second;
|
||||
if (rightInstrumentLot != LOT_NULL) {
|
||||
inventory->AddItem(rightInstrumentLot, 1, eLootSourceType::LOOT_SOURCE_NONE, TEMP_ITEMS, {}, LWOOBJID_EMPTY, false);
|
||||
auto* rightInstrument = inventory->FindItemByLot(rightInstrumentLot, TEMP_ITEMS);
|
||||
rightInstrument->Equip();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NsConcertInstrument::UnEquipInstruments(Entity* self, Entity* player) {
|
||||
auto* inventory = player->GetComponent<InventoryComponent>();
|
||||
if (inventory != nullptr) {
|
||||
auto equippedItems = inventory->GetEquippedItems();
|
||||
|
||||
// Un equip the current left instrument
|
||||
const auto equippedInstrumentLeft = equippedItems.find("special_l");
|
||||
if (equippedInstrumentLeft != equippedItems.end()) {
|
||||
auto* leftItem = inventory->FindItemById(equippedInstrumentLeft->second.id);
|
||||
if (leftItem != nullptr) {
|
||||
leftItem->UnEquip();
|
||||
inventory->RemoveItem(leftItem->GetLot(), 1, TEMP_ITEMS);
|
||||
}
|
||||
}
|
||||
|
||||
// Un equip the current right instrument
|
||||
const auto equippedInstrumentRight = equippedItems.find("special_r");
|
||||
if (equippedInstrumentRight != equippedItems.end()) {
|
||||
auto* rightItem = inventory->FindItemById(equippedInstrumentRight->second.id);
|
||||
if (rightItem != nullptr) {
|
||||
rightItem->UnEquip();
|
||||
inventory->RemoveItem(rightItem->GetLot(), 1, TEMP_ITEMS);
|
||||
}
|
||||
}
|
||||
|
||||
// Equip the old left hand item
|
||||
const auto leftItemID = self->GetVar<LWOOBJID>(u"oldItemLeft");
|
||||
if (leftItemID != LWOOBJID_EMPTY) {
|
||||
auto* item = inventory->FindItemById(leftItemID);
|
||||
if (item != nullptr)
|
||||
item->Equip();
|
||||
self->SetVar<LWOOBJID>(u"oldItemLeft", LWOOBJID_EMPTY);
|
||||
}
|
||||
|
||||
// Equip the old right hand item
|
||||
const auto rightItemID = self->GetVar<LWOOBJID>(u"oldItemRight");
|
||||
if (rightItemID != LWOOBJID_EMPTY) {
|
||||
auto* item = inventory->FindItemById(rightItemID);
|
||||
if (item != nullptr)
|
||||
item->Equip();
|
||||
self->SetVar<LWOOBJID>(u"oldItemRight", LWOOBJID_EMPTY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NsConcertInstrument::RepositionPlayer(Entity* self, Entity* player) {
|
||||
auto position = self->GetPosition();
|
||||
auto rotation = self->GetRotation();
|
||||
position.SetY(0.0f);
|
||||
|
||||
switch (GetInstrumentLot(self)) {
|
||||
case Bass:
|
||||
case Guitar:
|
||||
position.SetX(position.GetX() + 5.0f);
|
||||
break;
|
||||
case Keyboard:
|
||||
position.SetX(position.GetX() - 0.45f);
|
||||
position.SetZ(position.GetZ() + 0.75f);
|
||||
rotation = NiQuaternion::CreateFromAxisAngle(position, -0.8f); // Slight rotation to make the animation sensible
|
||||
break;
|
||||
case Drum:
|
||||
position.SetZ(position.GetZ() - 0.5f);
|
||||
break;
|
||||
}
|
||||
|
||||
GameMessages::SendTeleport(player->GetObjectID(), position, rotation, player->GetSystemAddress());
|
||||
}
|
||||
|
||||
InstrumentLot NsConcertInstrument::GetInstrumentLot(Entity* self) {
|
||||
return static_cast<const InstrumentLot>(self->GetLOT());
|
||||
}
|
||||
|
||||
// Static stuff needed for script execution
|
||||
|
||||
const std::map<InstrumentLot, std::u16string> NsConcertInstrument::animations{
|
||||
{ Guitar, u"guitar"},
|
||||
{ Bass, u"bass"},
|
||||
{ Keyboard, u"keyboard"},
|
||||
{ Drum, u"drums"}
|
||||
};
|
||||
|
||||
const std::map<InstrumentLot, std::u16string> NsConcertInstrument::smashAnimations{
|
||||
{Guitar, u"guitar-smash"},
|
||||
{Bass, u"bass-smash"},
|
||||
{Keyboard, u"keyboard-smash"},
|
||||
{Drum, u"keyboard-smash"}
|
||||
};
|
||||
|
||||
const std::map<InstrumentLot, float> NsConcertInstrument::instrumentSmashAnimationTime{
|
||||
{Guitar, 2.167f},
|
||||
{Bass, 1.167f},
|
||||
{Keyboard, 1.0f},
|
||||
{Drum, 1.0f}
|
||||
};
|
||||
|
||||
const std::map<InstrumentLot, std::string> NsConcertInstrument::music{
|
||||
{Guitar, "Concert_Guitar"},
|
||||
{Bass, "Concert_Bass"},
|
||||
{Keyboard, "Concert_Keys"},
|
||||
{Drum, "Concert_Drums"},
|
||||
};
|
||||
|
||||
const std::map<InstrumentLot, std::u16string> NsConcertInstrument::cinematics{
|
||||
{Guitar, u"Concert_Cam_G"},
|
||||
{Bass, u"Concert_Cam_B"},
|
||||
{Keyboard, u"Concert_Cam_K"},
|
||||
{Drum, u"Concert_Cam_D"},
|
||||
};
|
||||
|
||||
const std::map<InstrumentLot, LOT> NsConcertInstrument::instrumentLotLeft{
|
||||
{Guitar, 4991},
|
||||
{Bass, 4992},
|
||||
{Keyboard, LOT_NULL},
|
||||
{Drum, 4995},
|
||||
};
|
||||
|
||||
const std::map<InstrumentLot, LOT> NsConcertInstrument::instrumentLotRight{
|
||||
{Guitar, LOT_NULL},
|
||||
{Bass, LOT_NULL},
|
||||
{Keyboard, LOT_NULL},
|
||||
{Drum, 4996},
|
||||
};
|
||||
|
||||
const std::map<InstrumentLot, bool> NsConcertInstrument::hideInstrumentOnPlay{
|
||||
{Guitar, true},
|
||||
{Bass, true},
|
||||
{Keyboard, false},
|
||||
{Drum, false},
|
||||
};
|
||||
|
||||
const std::map<InstrumentLot, float> NsConcertInstrument::instrumentEquipTime{
|
||||
{Guitar, 1.033},
|
||||
{Bass, 0.75},
|
||||
{Keyboard, -1},
|
||||
{Drum, 0},
|
||||
};
|
||||
|
||||
const std::map<InstrumentLot, uint32_t> NsConcertInstrument::achievementTaskID{
|
||||
{Guitar, 911},
|
||||
{Bass, 912},
|
||||
{Keyboard, 913},
|
||||
{Drum, 914},
|
||||
};
|
||||
|
||||
const uint32_t NsConcertInstrument::instrumentImaginationCost = 2;
|
||||
|
||||
const float NsConcertInstrument::instrumentCostFrequency = 4.0f;
|
||||
|
||||
const float NsConcertInstrument::updateFrequency = 1.0f;
|
91
dScripts/ai/NS/NsConcertInstrument.h
Normal file
91
dScripts/ai/NS/NsConcertInstrument.h
Normal file
@@ -0,0 +1,91 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
enum InstrumentLot {
|
||||
Guitar = 4039,
|
||||
Bass = 4040,
|
||||
Keyboard = 4041,
|
||||
Drum = 4042
|
||||
};
|
||||
|
||||
class NsConcertInstrument : public CppScripts::Script {
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
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;
|
||||
void OnRebuildComplete(Entity* self, Entity* target) override;
|
||||
void OnTimerDone(Entity* self, std::string name) override;
|
||||
private:
|
||||
static void StartPlayingInstrument(Entity* self, Entity* player);
|
||||
static void StopPlayingInstrument(Entity* self, Entity* player);
|
||||
static void EquipInstruments(Entity* self, Entity* player);
|
||||
static void UnEquipInstruments(Entity* self, Entity* player);
|
||||
static void RepositionPlayer(Entity* self, Entity* player);
|
||||
static InstrumentLot GetInstrumentLot(Entity* self);
|
||||
|
||||
/**
|
||||
* Animations played when using an instrument
|
||||
*/
|
||||
static const std::map<InstrumentLot, std::u16string> animations;
|
||||
|
||||
/**
|
||||
* Animation played when an instrument is smashed
|
||||
*/
|
||||
static const std::map<InstrumentLot, std::u16string> smashAnimations;
|
||||
|
||||
/**
|
||||
* Music to play while playing an instrument
|
||||
*/
|
||||
static const std::map<InstrumentLot, std::string> music;
|
||||
|
||||
/**
|
||||
* Cinematics to play while playing an instrument
|
||||
*/
|
||||
static const std::map<InstrumentLot, std::u16string> cinematics;
|
||||
|
||||
/**
|
||||
* Lot to equip in your left hand when playing an instrument
|
||||
*/
|
||||
static const std::map<InstrumentLot, LOT> instrumentLotLeft;
|
||||
|
||||
/**
|
||||
* Lot to play in your right hand when playing an instrument
|
||||
*/
|
||||
static const std::map<InstrumentLot, LOT> instrumentLotRight;
|
||||
|
||||
/**
|
||||
* Whether to hide the instrument or not when someone is playing it
|
||||
*/
|
||||
static const std::map<InstrumentLot, bool> hideInstrumentOnPlay;
|
||||
|
||||
/**
|
||||
* How long to wait before unequipping the instrument if the instrument was smashed
|
||||
*/
|
||||
static const std::map<InstrumentLot, float> instrumentEquipTime;
|
||||
|
||||
/**
|
||||
* How long the smash animation takes for each of the instruments
|
||||
*/
|
||||
static const std::map<InstrumentLot, float> instrumentSmashAnimationTime;
|
||||
|
||||
/**
|
||||
* Task ID of tasks of the Solo Artist 2 achievement
|
||||
*/
|
||||
static const std::map<InstrumentLot, uint32_t> achievementTaskID;
|
||||
|
||||
/**
|
||||
* How much imagination playing an instrument costs per interval
|
||||
*/
|
||||
static const uint32_t instrumentImaginationCost;
|
||||
|
||||
/**
|
||||
* The interval to deduct imagination at when playing an instrument
|
||||
*/
|
||||
static const float instrumentCostFrequency;
|
||||
|
||||
/**
|
||||
* The interval to check if the player still has enough imagination
|
||||
*/
|
||||
static const float updateFrequency;
|
||||
};
|
224
dScripts/ai/NS/NsConcertQuickBuild.cpp
Normal file
224
dScripts/ai/NS/NsConcertQuickBuild.cpp
Normal file
@@ -0,0 +1,224 @@
|
||||
#include "NsConcertQuickBuild.h"
|
||||
#include "EntityManager.h"
|
||||
#include "NsConcertChoiceBuildManager.h"
|
||||
#include "DestroyableComponent.h"
|
||||
#include "GameMessages.h"
|
||||
#include "MovingPlatformComponent.h"
|
||||
#include "MissionComponent.h"
|
||||
|
||||
const float NsConcertQuickBuild::resetTime = 40.0f;
|
||||
const float NsConcertQuickBuild::resetBlinkTime = 6.0f;
|
||||
const float NsConcertQuickBuild::resetStageTime = 66.5f;
|
||||
const float NsConcertQuickBuild::resetActivatorTime = 30.0f;
|
||||
const std::map<LOT, QuickBuildSet> NsConcertQuickBuild::quickBuildSets{
|
||||
{5846, QuickBuildSet {"laser", {"discoball", "discofloor", "stagelights", "spotlight"}}},
|
||||
{5847, QuickBuildSet {"spotlight", {"spotlight", "stagelights"}}},
|
||||
{5848, QuickBuildSet {"rocket", {"flamethrower"}}},
|
||||
{5845, QuickBuildSet {"speaker", {"speaker", "speakerHill", "stagelights", "spotlight"}}}
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> NsConcertQuickBuild::quickBuildFX{
|
||||
{"discoball", "effectsDiscoball"},
|
||||
{"speaker", "effectsShell"},
|
||||
{"speakerHill", "effectsHill"},
|
||||
{"spotlight", "effectsHill"},
|
||||
{"discofloor", "effectsShell"},
|
||||
{"flamethrower", "effectsShell"},
|
||||
{"stagelights", "effectsShell"}
|
||||
};
|
||||
|
||||
std::vector<LWOOBJID> NsConcertQuickBuild::finishedQuickBuilds = {};
|
||||
|
||||
void NsConcertQuickBuild::OnStartup(Entity* self) {
|
||||
const auto groups = self->GetGroups();
|
||||
if (groups.empty())
|
||||
return;
|
||||
|
||||
// Groups are of the form Concert_Laser_QB_1, Concert_Laser_QB_2, etc.
|
||||
auto group = groups.at(0);
|
||||
const auto splitGroup = GeneralUtils::SplitString(group, '_');
|
||||
if (splitGroup.size() < 4)
|
||||
return;
|
||||
|
||||
// Get the manager of the crate of this quick build
|
||||
const auto groupNumber = std::stoi(splitGroup.at(3));
|
||||
const auto managerObjects = EntityManager::Instance()->GetEntitiesInGroup("CB_" + std::to_string(groupNumber));
|
||||
if (managerObjects.empty())
|
||||
return;
|
||||
|
||||
auto* managerObject = managerObjects.at(0);
|
||||
self->SetVar<LWOOBJID>(u"managerObject", managerObject->GetObjectID());
|
||||
self->SetVar<int32_t>(u"groupNumber", groupNumber);
|
||||
|
||||
// Makes the quick build blink after a certain amount of time
|
||||
self->AddCallbackTimer(GetBlinkTime(resetActivatorTime), [self]() {
|
||||
self->SetNetworkVar<float>(u"startEffect", NsConcertQuickBuild::GetBlinkTime(resetActivatorTime));
|
||||
});
|
||||
|
||||
// Destroys the quick build after a while if it wasn't built
|
||||
self->AddCallbackTimer(resetActivatorTime, [self]() {
|
||||
self->SetNetworkVar<float>(u"startEffect", -1.0f);
|
||||
self->Smash(self->GetObjectID(), SILENT);
|
||||
});
|
||||
}
|
||||
|
||||
float NsConcertQuickBuild::GetBlinkTime(float time) {
|
||||
return time <= NsConcertQuickBuild::resetBlinkTime ? 1.0f : time - NsConcertQuickBuild::resetBlinkTime;
|
||||
}
|
||||
|
||||
void NsConcertQuickBuild::OnDie(Entity* self, Entity* killer) {
|
||||
auto* managerObject = EntityManager::Instance()->GetEntity(self->GetVar<LWOOBJID>(u"managerObject"));
|
||||
if (managerObject) {
|
||||
managerObject->CancelAllTimers();
|
||||
managerObject->AddCallbackTimer(1.0f, [managerObject]() {
|
||||
NsConcertChoiceBuildManager::SpawnCrate(managerObject);
|
||||
});
|
||||
}
|
||||
|
||||
auto position = std::find(finishedQuickBuilds.begin(), finishedQuickBuilds.end(), self->GetObjectID());
|
||||
if (position != finishedQuickBuilds.end())
|
||||
finishedQuickBuilds.erase(position);
|
||||
}
|
||||
|
||||
void NsConcertQuickBuild::OnRebuildComplete(Entity* self, Entity* target) {
|
||||
const auto groupNumber = self->GetVar<int32_t>(u"groupNumber");
|
||||
finishedQuickBuilds.push_back(self->GetObjectID());
|
||||
self->SetNetworkVar<float>(u"startEffect", -1.0f);
|
||||
|
||||
ProgressStageCraft(self, target);
|
||||
|
||||
// Find all the quick build objects of the same lot
|
||||
auto finishedQuickBuildObjects = std::vector<Entity*>();
|
||||
for (auto quickBuildID : finishedQuickBuilds) {
|
||||
const auto quickBuildObject = EntityManager::Instance()->GetEntity(quickBuildID);
|
||||
if (quickBuildObject && quickBuildObject->GetLOT() == self->GetLOT()) {
|
||||
quickBuildObject->SetVar<LWOOBJID>(u"Player_" + (GeneralUtils::to_u16string(groupNumber)), target->GetObjectID());
|
||||
finishedQuickBuildObjects.push_back(quickBuildObject);
|
||||
}
|
||||
}
|
||||
|
||||
// If all 4 sets were built, do cool stuff
|
||||
if (finishedQuickBuildObjects.size() >= 4) {
|
||||
|
||||
// Move all the platforms so the user can collect the imagination brick
|
||||
const auto movingPlatforms = EntityManager::Instance()->GetEntitiesInGroup("ConcertPlatforms");
|
||||
for (auto* movingPlatform : movingPlatforms) {
|
||||
auto* component = movingPlatform->GetComponent<MovingPlatformComponent>();
|
||||
if (component) {
|
||||
component->WarpToWaypoint(component->GetLastWaypointIndex());
|
||||
|
||||
movingPlatform->AddCallbackTimer(resetStageTime, [movingPlatform, component]() {
|
||||
component->WarpToWaypoint(0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ProgressLicensedTechnician(self);
|
||||
|
||||
// Reset all timers for the quickbuilds and make them indestructible
|
||||
for (auto quickBuild : finishedQuickBuildObjects) {
|
||||
quickBuild->SetNetworkVar<float>(u"startEffect", -1.0f);
|
||||
quickBuild->CancelAllTimers();
|
||||
|
||||
// Indicate that the stage will reset
|
||||
quickBuild->AddCallbackTimer(GetBlinkTime(resetStageTime), [quickBuild]() {
|
||||
quickBuild->SetNetworkVar<float>(u"startEffect", GetBlinkTime(resetTime));
|
||||
});
|
||||
|
||||
// Reset the stage
|
||||
quickBuild->AddCallbackTimer(resetStageTime, [quickBuild]() {
|
||||
CancelEffects(quickBuild);
|
||||
quickBuild->SetNetworkVar<float>(u"startEffect", -1);
|
||||
quickBuild->Smash();
|
||||
});
|
||||
|
||||
auto* destroyableComponent = quickBuild->GetComponent<DestroyableComponent>();
|
||||
if (destroyableComponent)
|
||||
destroyableComponent->SetFaction(-1);
|
||||
}
|
||||
|
||||
UpdateEffects(self);
|
||||
return;
|
||||
}
|
||||
|
||||
// If not all 4 sets were built, reset the timers that were set on spawn
|
||||
self->CancelAllTimers();
|
||||
|
||||
// Makes the quick build blink after a certain amount of time
|
||||
self->AddCallbackTimer(GetBlinkTime(resetTime), [self]() {
|
||||
self->SetNetworkVar<float>(u"startEffect", NsConcertQuickBuild::GetBlinkTime(resetActivatorTime));
|
||||
});
|
||||
|
||||
// Destroys the quick build after a while if it wasn't built
|
||||
self->AddCallbackTimer(resetTime, [self]() {
|
||||
self->SetNetworkVar<float>(u"startEffect", -1.0f);
|
||||
self->Smash(self->GetObjectID());
|
||||
});
|
||||
}
|
||||
|
||||
void NsConcertQuickBuild::ProgressStageCraft(Entity* self, Entity* player) {
|
||||
auto* missionComponent = player->GetComponent<MissionComponent>();
|
||||
if (missionComponent) {
|
||||
|
||||
// Has to be forced as to not accidentally trigger the licensed technician achievement
|
||||
switch (self->GetLOT()) {
|
||||
case 5845:
|
||||
missionComponent->ForceProgress(283, 432, 5845);
|
||||
break;
|
||||
case 5846:
|
||||
missionComponent->ForceProgress(283, 433, 5846);
|
||||
break;
|
||||
case 5847:
|
||||
missionComponent->ForceProgress(283, 434, 5847);
|
||||
break;
|
||||
case 5848:
|
||||
missionComponent->ForceProgress(283, 435, 5848);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NsConcertQuickBuild::ProgressLicensedTechnician(Entity* self) {
|
||||
for (auto i = 1; i < 5; i++) {
|
||||
const auto playerID = self->GetVar<LWOOBJID>(u"Player_" + (GeneralUtils::to_u16string(i)));
|
||||
if (playerID != LWOOBJID_EMPTY) {
|
||||
const auto player = EntityManager::Instance()->GetEntity(playerID);
|
||||
if (player) {
|
||||
auto playerMissionComponent = player->GetComponent<MissionComponent>();
|
||||
if (playerMissionComponent)
|
||||
playerMissionComponent->ForceProgress(598, 903, self->GetLOT());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NsConcertQuickBuild::UpdateEffects(Entity* self) {
|
||||
CancelEffects(self);
|
||||
|
||||
auto setIterator = quickBuildSets.find(self->GetLOT());
|
||||
if (setIterator == quickBuildSets.end())
|
||||
return;
|
||||
|
||||
for (const auto& effectName : setIterator->second.effects) {
|
||||
const auto effectObjects = EntityManager::Instance()->GetEntitiesInGroup(quickBuildFX.at(effectName));
|
||||
for (auto* effectObject : effectObjects) {
|
||||
GameMessages::SendPlayFXEffect(effectObject, 0, GeneralUtils::ASCIIToUTF16(effectName),
|
||||
effectName + "Effect", LWOOBJID_EMPTY, 1, 1, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NsConcertQuickBuild::CancelEffects(Entity* self) {
|
||||
auto setIterator = quickBuildSets.find(self->GetLOT());
|
||||
if (setIterator == quickBuildSets.end())
|
||||
return;
|
||||
|
||||
for (const auto& effectName : setIterator->second.effects) {
|
||||
const auto effectObjects = EntityManager::Instance()->GetEntitiesInGroup(quickBuildFX.at(effectName));
|
||||
for (auto* effectObject : effectObjects) {
|
||||
GameMessages::SendStopFXEffect(effectObject, true, effectName + "Effect");
|
||||
}
|
||||
}
|
||||
}
|
27
dScripts/ai/NS/NsConcertQuickBuild.h
Normal file
27
dScripts/ai/NS/NsConcertQuickBuild.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
struct QuickBuildSet {
|
||||
std::string name;
|
||||
std::vector<std::string> effects;
|
||||
};
|
||||
|
||||
class NsConcertQuickBuild : public CppScripts::Script {
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
void OnRebuildComplete(Entity* self, Entity* target) override;
|
||||
void OnDie(Entity* self, Entity* killer) override;
|
||||
private:
|
||||
static std::vector<LWOOBJID> finishedQuickBuilds;
|
||||
static const float resetBlinkTime;
|
||||
static const float resetStageTime;
|
||||
static const float resetActivatorTime;
|
||||
static const float resetTime;
|
||||
static const std::map<std::string, std::string> quickBuildFX;
|
||||
static const std::map<LOT, QuickBuildSet> quickBuildSets;
|
||||
static float GetBlinkTime(float time);
|
||||
static void ProgressStageCraft(Entity* self, Entity* player);
|
||||
static void ProgressLicensedTechnician(Entity* self);
|
||||
static void UpdateEffects(Entity* self);
|
||||
static void CancelEffects(Entity* self);
|
||||
};
|
54
dScripts/ai/NS/NsGetFactionMissionServer.cpp
Normal file
54
dScripts/ai/NS/NsGetFactionMissionServer.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include "NsGetFactionMissionServer.h"
|
||||
#include "GameMessages.h"
|
||||
#include "MissionComponent.h"
|
||||
#include "Character.h"
|
||||
|
||||
void NsGetFactionMissionServer::OnRespondToMission(Entity* self, int missionID, Entity* player, int reward) {
|
||||
if (missionID != 474) return;
|
||||
|
||||
if (reward != LOT_NULL) {
|
||||
std::vector<int> factionMissions;
|
||||
int celebrationID = -1;
|
||||
int flagID = -1;
|
||||
|
||||
if (reward == 6980) {
|
||||
// Venture League
|
||||
factionMissions = { 555, 556 };
|
||||
celebrationID = 14;
|
||||
flagID = 46;
|
||||
} else if (reward == 6979) {
|
||||
// Assembly
|
||||
factionMissions = { 544, 545 };
|
||||
celebrationID = 15;
|
||||
flagID = 47;
|
||||
} else if (reward == 6981) {
|
||||
// Paradox
|
||||
factionMissions = { 577, 578 };
|
||||
celebrationID = 16;
|
||||
flagID = 48;
|
||||
} else if (reward == 6978) {
|
||||
// Sentinel
|
||||
factionMissions = { 566, 567 };
|
||||
celebrationID = 17;
|
||||
flagID = 49;
|
||||
}
|
||||
|
||||
factionMissions.push_back(778);
|
||||
|
||||
if (celebrationID != -1) {
|
||||
GameMessages::SendStartCelebrationEffect(player, player->GetSystemAddress(), celebrationID);
|
||||
}
|
||||
|
||||
if (flagID != -1) {
|
||||
player->GetCharacter()->SetPlayerFlag(ePlayerFlags::JOINED_A_FACTION, true);
|
||||
player->GetCharacter()->SetPlayerFlag(flagID, true);
|
||||
}
|
||||
|
||||
MissionComponent* mis = static_cast<MissionComponent*>(player->GetComponent(COMPONENT_TYPE_MISSION));
|
||||
|
||||
for (int mission : factionMissions) {
|
||||
mis->AcceptMission(mission);
|
||||
mis->CompleteMission(mission);
|
||||
}
|
||||
}
|
||||
}
|
8
dScripts/ai/NS/NsGetFactionMissionServer.h
Normal file
8
dScripts/ai/NS/NsGetFactionMissionServer.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class NsGetFactionMissionServer : public CppScripts::Script
|
||||
{
|
||||
public:
|
||||
void OnRespondToMission(Entity* self, int missionID, Entity* player, int reward) override;
|
||||
};
|
14
dScripts/ai/NS/NsJohnnyMissionServer.cpp
Normal file
14
dScripts/ai/NS/NsJohnnyMissionServer.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include "NsJohnnyMissionServer.h"
|
||||
#include "MissionComponent.h"
|
||||
|
||||
void NsJohnnyMissionServer::OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState) {
|
||||
if (missionID == 773 && missionState <= MissionState::MISSION_STATE_ACTIVE) {
|
||||
auto* missionComponent = target->GetComponent<MissionComponent>();
|
||||
if (missionComponent != nullptr) {
|
||||
missionComponent->AcceptMission(774);
|
||||
missionComponent->AcceptMission(775);
|
||||
missionComponent->AcceptMission(776);
|
||||
missionComponent->AcceptMission(777);
|
||||
}
|
||||
}
|
||||
}
|
6
dScripts/ai/NS/NsJohnnyMissionServer.h
Normal file
6
dScripts/ai/NS/NsJohnnyMissionServer.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class NsJohnnyMissionServer : public CppScripts::Script {
|
||||
void OnMissionDialogueOK(Entity* self, Entity* target, int missionID, MissionState missionState) override;
|
||||
};
|
16
dScripts/ai/NS/NsModularBuild.cpp
Normal file
16
dScripts/ai/NS/NsModularBuild.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include "NsModularBuild.h"
|
||||
#include "MissionComponent.h"
|
||||
|
||||
void NsModularBuild::OnModularBuildExit(Entity* self, Entity* player, bool bCompleted, std::vector<LOT> modules) {
|
||||
if (bCompleted) {
|
||||
MissionComponent* mission = static_cast<MissionComponent*>(player->GetComponent(COMPONENT_TYPE_MISSION));
|
||||
|
||||
if (mission->GetMissionState(m_MissionNum) == MissionState::MISSION_STATE_ACTIVE) {
|
||||
for (LOT mod : modules) {
|
||||
if (mod == 9516 || mod == 9517 || mod == 9518) {
|
||||
mission->ForceProgress(m_MissionNum, 1178, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
10
dScripts/ai/NS/NsModularBuild.h
Normal file
10
dScripts/ai/NS/NsModularBuild.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class NsModularBuild : public CppScripts::Script
|
||||
{
|
||||
public:
|
||||
void OnModularBuildExit(Entity* self, Entity* player, bool bCompleted, std::vector<LOT> modules);
|
||||
private:
|
||||
int m_MissionNum = 809;
|
||||
};
|
40
dScripts/ai/NS/NsQbImaginationStatue.cpp
Normal file
40
dScripts/ai/NS/NsQbImaginationStatue.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "NsQbImaginationStatue.h"
|
||||
#include "EntityManager.h"
|
||||
#include "GameMessages.h"
|
||||
|
||||
void NsQbImaginationStatue::OnStartup(Entity* self) {
|
||||
|
||||
}
|
||||
|
||||
void NsQbImaginationStatue::OnRebuildComplete(Entity* self, Entity* target) {
|
||||
if (target == nullptr) return;
|
||||
|
||||
self->SetVar(u"Player", target->GetObjectID());
|
||||
|
||||
SpawnLoot(self);
|
||||
|
||||
self->AddTimer("SpawnDelay", 1.5f);
|
||||
|
||||
self->AddTimer("StopSpawner", 10.0f);
|
||||
}
|
||||
|
||||
void NsQbImaginationStatue::OnTimerDone(Entity* self, std::string timerName) {
|
||||
if (timerName == "SpawnDelay") {
|
||||
SpawnLoot(self);
|
||||
|
||||
self->AddTimer("SpawnDelay", 1.5f);
|
||||
} else if (timerName == "StopSpawner") {
|
||||
self->CancelAllTimers();
|
||||
}
|
||||
}
|
||||
|
||||
void NsQbImaginationStatue::SpawnLoot(Entity* self) {
|
||||
const auto playerId = self->GetVar<LWOOBJID>(u"Player");
|
||||
|
||||
auto* player = EntityManager::Instance()->GetEntity(playerId);
|
||||
|
||||
if (player == nullptr) return;
|
||||
|
||||
GameMessages::SendDropClientLoot(player, self->GetObjectID(), 935, 0);
|
||||
GameMessages::SendDropClientLoot(player, self->GetObjectID(), 935, 0);
|
||||
}
|
11
dScripts/ai/NS/NsQbImaginationStatue.h
Normal file
11
dScripts/ai/NS/NsQbImaginationStatue.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class NsQbImaginationStatue : public CppScripts::Script
|
||||
{
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
void OnRebuildComplete(Entity* self, Entity* target) override;
|
||||
void OnTimerDone(Entity* self, std::string timerName) override;
|
||||
void SpawnLoot(Entity* self);
|
||||
};
|
4
dScripts/ai/NS/WH/CMakeLists.txt
Normal file
4
dScripts/ai/NS/WH/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
set(DSCRIPTS_SOURCES_AI_NS_WH
|
||||
"RockHydrantSmashable.cpp"
|
||||
"RockHydrantBroken.cpp"
|
||||
PARENT_SCOPE)
|
38
dScripts/ai/NS/WH/RockHydrantBroken.cpp
Normal file
38
dScripts/ai/NS/WH/RockHydrantBroken.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "RockHydrantBroken.h"
|
||||
#include "EntityManager.h"
|
||||
#include "GameMessages.h"
|
||||
|
||||
void RockHydrantBroken::OnStartup(Entity* self) {
|
||||
self->AddTimer("playEffect", 1);
|
||||
|
||||
const auto hydrant = "hydrant" + self->GetVar<std::string>(u"hydrant");
|
||||
|
||||
const auto bouncers = EntityManager::Instance()->GetEntitiesInGroup(hydrant);
|
||||
|
||||
for (auto* bouncer : bouncers) {
|
||||
self->SetVar<LWOOBJID>(u"bouncer", bouncer->GetObjectID());
|
||||
|
||||
|
||||
GameMessages::SendBouncerActiveStatus(bouncer->GetObjectID(), true, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
GameMessages::SendNotifyObject(bouncer->GetObjectID(), self->GetObjectID(), u"enableCollision", UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
|
||||
self->AddTimer("KillBroken", 10);
|
||||
}
|
||||
|
||||
void RockHydrantBroken::OnTimerDone(Entity* self, std::string timerName) {
|
||||
if (timerName == "KillBroken") {
|
||||
auto* bouncer = EntityManager::Instance()->GetEntity(self->GetVar<LWOOBJID>(u"bouncer"));
|
||||
|
||||
if (bouncer != nullptr) {
|
||||
GameMessages::SendBouncerActiveStatus(bouncer->GetObjectID(), false, UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
GameMessages::SendNotifyObject(bouncer->GetObjectID(), self->GetObjectID(), u"disableCollision", UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
|
||||
self->Kill();
|
||||
} else if (timerName == "playEffect") {
|
||||
GameMessages::SendPlayFXEffect(self->GetObjectID(), 4737, u"water", "water", LWOOBJID_EMPTY, 1, 1, true);
|
||||
}
|
||||
}
|
10
dScripts/ai/NS/WH/RockHydrantBroken.h
Normal file
10
dScripts/ai/NS/WH/RockHydrantBroken.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class RockHydrantBroken : public CppScripts::Script
|
||||
{
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
void OnTimerDone(Entity* self, std::string timerName) override;
|
||||
};
|
||||
|
20
dScripts/ai/NS/WH/RockHydrantSmashable.cpp
Normal file
20
dScripts/ai/NS/WH/RockHydrantSmashable.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "RockHydrantSmashable.h"
|
||||
#include "EntityManager.h"
|
||||
#include "GeneralUtils.h"
|
||||
|
||||
void RockHydrantSmashable::OnDie(Entity* self, Entity* killer) {
|
||||
const auto hydrantName = self->GetVar<std::u16string>(u"hydrant");
|
||||
|
||||
LDFBaseData* data = new LDFData<std::string>(u"hydrant", GeneralUtils::UTF16ToWTF8(hydrantName));
|
||||
|
||||
EntityInfo info{};
|
||||
info.lot = ROCK_HYDRANT_BROKEN;
|
||||
info.pos = self->GetPosition();
|
||||
info.rot = self->GetRotation();
|
||||
info.settings = { data };
|
||||
info.spawnerID = self->GetSpawnerID();
|
||||
|
||||
auto* hydrant = EntityManager::Instance()->CreateEntity(info);
|
||||
|
||||
EntityManager::Instance()->ConstructEntity(hydrant);
|
||||
}
|
11
dScripts/ai/NS/WH/RockHydrantSmashable.h
Normal file
11
dScripts/ai/NS/WH/RockHydrantSmashable.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class RockHydrantSmashable : public CppScripts::Script
|
||||
{
|
||||
public:
|
||||
void OnDie(Entity* self, Entity* killer);
|
||||
private:
|
||||
LOT ROCK_HYDRANT_BROKEN = 12293;
|
||||
};
|
||||
|
71
dScripts/ai/NS/WhFans.cpp
Normal file
71
dScripts/ai/NS/WhFans.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#include "WhFans.h"
|
||||
|
||||
#include "RenderComponent.h"
|
||||
#include "GameMessages.h"
|
||||
#include "EntityManager.h"
|
||||
#include "PhantomPhysicsComponent.h"
|
||||
|
||||
void WhFans::OnStartup(Entity* self) {
|
||||
self->SetVar<bool>(u"alive", true);
|
||||
self->SetVar<bool>(u"on", false);
|
||||
|
||||
ToggleFX(self, false);
|
||||
}
|
||||
|
||||
void WhFans::ToggleFX(Entity* self, bool hit) {
|
||||
std::string fanGroup;
|
||||
const auto& groups = self->GetGroups();
|
||||
if (!groups.empty()) {
|
||||
fanGroup = groups[0];
|
||||
} else {
|
||||
fanGroup = "";
|
||||
}
|
||||
|
||||
std::vector<Entity*> fanVolumes = EntityManager::Instance()->GetEntitiesInGroup(fanGroup);
|
||||
|
||||
auto* renderComponent = self->GetComponent<RenderComponent>();
|
||||
|
||||
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) {
|
||||
auto volumePhys = volume->GetComponent<PhantomPhysicsComponent>();
|
||||
if (!volumePhys) continue;
|
||||
volumePhys->SetPhysicsEffectActive(false);
|
||||
EntityManager::Instance()->SerializeEntity(volume);
|
||||
}
|
||||
} else if (!self->GetVar<bool>(u"on") && self->GetVar<bool>(u"alive")) {
|
||||
GameMessages::SendPlayAnimation(self, u"fan-on");
|
||||
|
||||
self->SetVar<bool>(u"on", true);
|
||||
|
||||
for (Entity* volume : fanVolumes) {
|
||||
auto volumePhys = volume->GetComponent<PhantomPhysicsComponent>();
|
||||
if (!volumePhys) continue;
|
||||
volumePhys->SetPhysicsEffectActive(true);
|
||||
EntityManager::Instance()->SerializeEntity(volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WhFans::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 WhFans::OnDie(Entity* self, Entity* killer) {
|
||||
if (self->GetVar<bool>(u"on")) {
|
||||
ToggleFX(self, true);
|
||||
}
|
||||
self->SetVar<bool>(u"alive", false);
|
||||
}
|
19
dScripts/ai/NS/WhFans.h
Normal file
19
dScripts/ai/NS/WhFans.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
class WhFans : public CppScripts::Script
|
||||
{
|
||||
public:
|
||||
void OnStartup(Entity* self) override;
|
||||
void OnDie(Entity* self, Entity* killer) override;
|
||||
void OnFireEventServerSide(
|
||||
Entity* self,
|
||||
Entity* sender,
|
||||
std::string args,
|
||||
int32_t param1,
|
||||
int32_t param2,
|
||||
int32_t param3
|
||||
) override;
|
||||
private:
|
||||
void ToggleFX(Entity* self, bool hit);
|
||||
};
|
||||
|
Reference in New Issue
Block a user