#include "AmSkullkinDrill.h" #include "GameMessages.h" #include "MovingPlatformComponent.h" #include "DestroyableComponent.h" #include "ProximityMonitorComponent.h" #include "dLogger.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(); 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(u"bIsInUse")) { return; } auto* proximityMonitorComponent = self->GetComponent(); 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(); 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(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(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(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(u"userID")); if (player == nullptr) { return; } const auto& cine = self->GetVar(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(); if (destroyableComponent == nullptr || !attacker->IsPlayer()) { return; } if (self->GetVar(u"bActive")) { return; } const auto activaterID = self->GetVar(u"activaterID"); auto* activator = EntityManager::Instance()->GetEntity(activaterID); // TODO: Missions if (activator != nullptr) { auto* missionComponent = activator->GetComponent(); 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(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(); 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(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") { } }