DarkflameServer/dScripts/02_server/Map/AM/AmSkullkinTower.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

243 lines
6.1 KiB
C++
Raw Permalink Normal View History

#include "AmSkullkinTower.h"
#include "EntityManager.h"
#include "DestroyableComponent.h"
#include "MovingPlatformComponent.h"
#include "EntityInfo.h"
#include "GameMessages.h"
#include "MissionComponent.h"
#include "RenderComponent.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");
2022-07-28 13:39:57 +00:00
auto newRot = rot;
auto offset = self->GetVarAs<float>(u"hort_offset");
2022-07-28 13:39:57 +00:00
auto legLOT = self->GetVar<LOT>(u"legLOT");
2022-07-28 13:39:57 +00:00
if (legLOT == 0) {
return;
}
2022-07-28 13:39:57 +00:00
std::vector<LDFBaseData*> config = { new LDFData<std::string>(u"Leg", loc) };
2022-07-28 13:39:57 +00:00
EntityInfo info{};
info.lot = legLOT;
info.spawnerID = self->GetObjectID();
info.settings = config;
info.rot = newRot;
2022-07-28 13:39:57 +00:00
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;
}
2022-07-28 13:39:57 +00:00
info.rot = NiQuaternion::LookAt(info.pos, self->GetPosition());
2022-07-28 13:39:57 +00:00
auto* entity = Game::entityManager->CreateEntity(info);
2022-07-28 13:39:57 +00:00
Game::entityManager->ConstructEntity(entity);
2022-07-28 13:39:57 +00:00
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 = Game::entityManager->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) {
RenderComponent::PlayAnimation(self, u"wobble-1");
} else if (legTable.size() == 1) {
RenderComponent::PlayAnimation(self, u"wobble-2");
} else if (legTable.empty()) {
const auto animTime = 2.5f;
RenderComponent::PlayAnimation(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) {
const auto missionID = GeneralUtils::TryParse<int32_t>(mission);
if (!missionID) continue;
missionIDs.push_back(missionID.value());
}
}
const auto& players = self->GetVar<std::vector<LWOOBJID>>(u"Players");
for (const auto& playerID : players) {
auto* player = Game::entityManager->GetEntity(playerID);
if (player == nullptr) {
continue;
2022-07-28 13:39:57 +00:00
}
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());
2022-07-28 13:39:57 +00:00
}
}
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);
2022-07-28 13:39:57 +00:00
}
self->SetVar(u"DeadLegs", deadLegs);
2022-07-28 13:39:57 +00:00
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");
2022-07-28 13:39:57 +00:00
if (deadLegs.empty()) {
return;
}
2022-07-28 13:39:57 +00:00
SpawnLegs(self, deadLegs[0]);
2022-07-28 13:39:57 +00:00
deadLegs.erase(deadLegs.begin());
2022-07-28 13:39:57 +00:00
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();
2022-07-28 13:39:57 +00:00
for (size_t i = 0; i < 2; i++) {
info.pos.x += i * 2; // Just to set the apart a bit
2022-07-28 13:39:57 +00:00
auto* entity = Game::entityManager->CreateEntity(info);
2022-07-28 13:39:57 +00:00
Game::entityManager->ConstructEntity(entity);
}
2022-07-28 13:39:57 +00:00
self->AddTimer("killTower", 0.7f);
} else if (timerName == "killTower") {
self->Smash(self->GetObjectID());
}
}