DarkflameServer/dScripts/02_server/Map/AM/AmSkullkinDrill.cpp
David Markowitz 891648288a Organize Entity header
Probably the third or fourth pass of this darn header...  Just keep making it better every time
Rename some functions to make more sense to a reader
Use different method for Observing/subscribing to component events
Get rid of abomination of overloading GetParentUser
2023-06-16 01:56:02 -07:00

327 lines
7.9 KiB
C++

#include "AmSkullkinDrill.h"
#include "GameMessages.h"
#include "MovingPlatformComponent.h"
#include "DestroyableComponent.h"
#include "ProximityMonitorComponent.h"
#include "MissionComponent.h"
#include "EntityInfo.h"
#include "RenderComponent.h"
#include "eStateChangeType.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) {
RenderComponent::PlayAnimation(self, u"slowdown");
self->AddTimer("killDrill", 10.0f);
auto* standObj = GetStandObj(self);
if (standObj != nullptr) {
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) {
auto StateChangeType = eStateChangeType::POP;
if (bFreeze) {
if (player->IsDead()) {
return;
}
StateChangeType = eStateChangeType::PUSH;
} else {
if (player->IsDead()) {
//
}
}
GameMessages::SendSetStunned(player->GetObjectID(), StateChangeType, 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) {
RenderComponent::PlayAnimation(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) {
standObj->SetVar(u"bActive", false);
}
return;
} else {
RenderComponent::PlayAnimation(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;
RenderComponent::PlayAnimation(player, 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(), eKillType::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) {
if (timerName == "killDrill") {
const auto childID = self->GetVar<LWOOBJID>(u"ChildSmash");
auto* child = EntityManager::Instance()->GetEntity(childID);
if (child != nullptr) {
child->Smash(self->GetObjectID(), eKillType::SILENT);
}
self->SetNetworkVar(u"bIsInUse", false);
self->SetVar(u"bActive", true);
self->SetVar(u"activaterID", LWOOBJID_EMPTY);
auto* standObj = GetStandObj(self);
if (standObj != nullptr) {
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];
const auto playerID = self->GetVar<LWOOBJID>(u"userID");
auto* player = EntityManager::Instance()->GetEntity(playerID);
if (player == nullptr) {
return;
}
if (animName == "spinjitzu-staff-windup") {
TriggerDrill(self);
RenderComponent::PlayAnimation(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") {
}
}