mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-11-23 05:57:20 +00:00
284 lines
7.1 KiB
C++
284 lines
7.1 KiB
C++
|
#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());
|
||
|
}
|
||
|
}
|