#include "BasePropertyServer.h" #include "GameMessages.h" #include "EntityManager.h" #include "dZoneManager.h" #include "Character.h" #include "DestroyableComponent.h" #include "Entity.h" #include "RenderComponent.h" #include "PropertyManagementComponent.h" #include "MissionComponent.h" #include "eMissionTaskType.h" #include "eMissionState.h" void BasePropertyServer::SetGameVariables(Entity* self) { self->SetVar<std::string>(ClaimMarkerGroup, ""); self->SetVar<std::string>(GeneratorGroup, ""); self->SetVar<std::string>(GuardGroup, ""); self->SetVar<std::string>(PropertyPlaqueGroup, ""); self->SetVar<std::string>(PropertyVendorGroup, ""); self->SetVar<std::string>(SpotsGroup, ""); self->SetVar<std::string>(MSCloudsGroup, ""); self->SetVar<std::string>(EnemiesGroup, ""); self->SetVar<std::string>(FXManagerGroup, ""); self->SetVar<std::string>(ImagOrbGroup, ""); self->SetVar<std::string>(GeneratorFXGroup, ""); self->SetVar<std::vector<std::string>>(EnemiesSpawner, {}); self->SetVar<std::string>(ClaimMarkerSpawner, ""); self->SetVar<std::string>(GeneratorSpawner, ""); self->SetVar<std::string>(DamageFXSpawner, ""); self->SetVar<std::string>(FXSpotsSpawner, ""); self->SetVar<std::string>(PropertyMGSpawner, ""); self->SetVar<std::string>(ImageOrbSpawner, ""); self->SetVar<std::string>(GeneratorFXSpawner, ""); self->SetVar<std::string>(SmashablesSpawner, ""); self->SetVar<std::string>(FXManagerSpawner, ""); self->SetVar<std::string>(PropObjsSpawner, ""); self->SetVar<std::vector<std::string>>(AmbientFXSpawner, {}); self->SetVar<std::vector<std::string>>(BehaviorObjsSpawner, {}); self->SetVar<int32_t>(defeatedProperyFlag, 0); self->SetVar<int32_t>(placedModelFlag, 0); self->SetVar<uint32_t>(guardMissionFlag, 0); self->SetVar<uint32_t>(brickLinkMissionIDFlag, 0); self->SetVar<std::string>(passwordFlag, "s3kratK1ttN"); self->SetVar<LOT>(generatorIdFlag, 0); self->SetVar<LOT>(orbIDFlag, 0); self->SetVar<LOT>(behaviorQBID, 0); } void BasePropertyServer::CheckForOwner(Entity* self) { if (Game::entityManager->GetEntitiesInGroup(self->GetVar<std::string>(PropertyPlaqueGroup)).empty()) { self->AddTimer(RunPlayerLoadedAgainTimer, 0.5f); return; } self->SetI64(PropertyOwnerVariable, GetOwner()); } void BasePropertyServer::OnStartup(Entity* self) { SetGameVariables(self); } void BasePropertyServer::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2, int32_t param3) { if (args == CheckForPropertyOwnerEvent) { sender->SetNetworkVar<std::string>(PropertyOwnerIDVariable, std::to_string(self->GetVar<LWOOBJID>(PropertyOwnerVariable))); } } void BasePropertyServer::BasePlayerLoaded(Entity* self, Entity* player) { CheckForOwner(self); auto rented = false; auto propertyOwner = PropertyManagementComponent::Instance()->GetOwnerId(); self->OnFireEventServerSide(self, CheckForPropertyOwnerEvent); if (propertyOwner > 0) { rented = true; } if (propertyOwner < 0) { propertyOwner = LWOOBJID_EMPTY; } self->SetNetworkVar(PropertyOwnerIDVariable, propertyOwner); if (rented) { auto plaques = Game::entityManager->GetEntitiesInGroup("PropertyVendor"); for (auto* plaque : plaques) { Game::entityManager->DestructEntity(plaque); } const auto& mapID = Game::zoneManager->GetZone()->GetZoneID(); if (propertyOwner > 0) { auto* missionComponent = player->GetComponent<MissionComponent>(); if (missionComponent != nullptr) { missionComponent->Progress( eMissionTaskType::VISIT_PROPERTY, mapID.GetMapID(), PropertyManagementComponent::Instance()->GetId() ); } } GameMessages::SendStop2DAmbientSound(player, true, GUIDMaelstrom); GameMessages::SendPlay2DAmbientSound(player, GUIDPeaceful); self->AddTimer(TurnSkyOffTimer, 1.5f); // kill tornado FX and play peaceful noises if (!self->GetBoolean(FXObjectsGoneVariable)) { self->AddTimer(KillFXObjectTimer, 1.0f); } GameMessages::SendPlay2DAmbientSound(player, GUIDPeaceful); // activate property safe spawner network ActivateSpawner(self->GetVar<std::string>(PropObjsSpawner)); // tell client script who owns the property self->SetNetworkVar<std::string>(RenterVariable, std::to_string(propertyOwner)); if (player->GetObjectID() != propertyOwner) return; } else { const auto defeatedFlag = player->GetCharacter()->GetPlayerFlag(self->GetVar<int32_t>(defeatedProperyFlag)); self->SetNetworkVar(UnclaimedVariable, true); self->SetVar<LWOOBJID>(PlayerIDVariable, player->GetObjectID()); if (!defeatedFlag) { StartMaelstrom(self, player); SpawnSpots(self); GameMessages::SendPlay2DAmbientSound(player, GUIDMaelstrom); } else { GameMessages::SendStop2DAmbientSound(player, true, GUIDMaelstrom); GameMessages::SendPlay2DAmbientSound(player, GUIDPeaceful); self->AddTimer(TurnSkyOffTimer, 1.5f); self->AddTimer(KillFXObjectTimer, 1.0f); } } PropGuardCheck(self, player); } void BasePropertyServer::PropGuardCheck(Entity* self, Entity* player) { auto* missionComponent = player->GetComponent<MissionComponent>(); if (missionComponent != nullptr && missionComponent->GetMissionState(self->GetVar<uint32_t>(guardMissionFlag)) != eMissionState::COMPLETE) { ActivateSpawner(self->GetVar<std::string>(PropertyMGSpawner)); } } void BasePropertyServer::BaseZonePropertyRented(Entity* self, Entity* player) const { GameMessages::SendNotifyClientObject(self->GetObjectID(), u"PlayCinematic", 0, 0, LWOOBJID_EMPTY, "ShowProperty", UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer(BoundsVisOnTimer, 2); self->SetVar<LWOOBJID>(PropertyOwnerVariable, player->GetObjectID()); auto plaques = Game::entityManager->GetEntitiesInGroup("PropertyVendor"); for (auto* plaque : plaques) { Game::entityManager->DestructEntity(plaque); } auto brickLinkMissionID = self->GetVar<uint32_t>(brickLinkMissionIDFlag); if (brickLinkMissionID != 0) { auto missionComponent = player->GetComponent<MissionComponent>(); if (missionComponent) missionComponent->CompleteMission(brickLinkMissionID, true); } ActivateSpawner(self->GetVar<std::string>(PropObjsSpawner)); } void BasePropertyServer::BaseZonePropertyModelPlaced(Entity* self, Entity* player) const { auto* character = player->GetCharacter(); if (character == nullptr) return; auto flag = self->GetVar<int32_t>(placedModelFlag); if (flag) character->SetPlayerFlag(flag, true); } void BasePropertyServer::KillClouds(Entity* self) { DeactivateSpawner(self->GetVar<std::string>(DamageFXSpawner)); DestroySpawner(self->GetVar<std::string>(DamageFXSpawner)); } void BasePropertyServer::SpawnSpots(Entity* self) { ActivateSpawner(self->GetVar<std::string>(FXSpotsSpawner)); } void BasePropertyServer::KillSpots(Entity* self) { DeactivateSpawner(self->GetVar<std::string>(FXSpotsSpawner)); DestroySpawner(self->GetVar<std::string>(FXSpotsSpawner)); } void BasePropertyServer::StartMaelstrom(Entity* self, Entity* player) { for (const auto& enemySpawner : self->GetVar<std::vector<std::string>>(EnemiesSpawner)) { ActivateSpawner(enemySpawner); } for (const auto& behaviorObjectSpawner : self->GetVar<std::vector<std::string>>(BehaviorObjsSpawner)) { ActivateSpawner(behaviorObjectSpawner); } ActivateSpawner(self->GetVar<std::string>(DamageFXSpawner)); ActivateSpawner(self->GetVar<std::string>(GeneratorSpawner)); ActivateSpawner(self->GetVar<std::string>(GeneratorFXSpawner)); ActivateSpawner(self->GetVar<std::string>(FXManagerSpawner)); ActivateSpawner(self->GetVar<std::string>(ImageOrbSpawner)); ActivateSpawner(self->GetVar<std::string>(SmashablesSpawner)); DestroySpawner(self->GetVar<std::string>(ClaimMarkerSpawner)); for (const auto& ambientFXSpawner : self->GetVar<std::vector<std::string>>(AmbientFXSpawner)) { DestroySpawner(ambientFXSpawner); } StartTornadoFx(self); GameMessages::SendNotifyClientObject(self->GetObjectID(), u"maelstromSkyOn", 0, 0, LWOOBJID_EMPTY, "", player->GetSystemAddress()); self->AddTimer(StartGeneratorTimer, 0.0f); self->AddTimer(StartOrbTimer, 0.0f); } void BasePropertyServer::StartTornadoFx(Entity* self) const { const auto entities = Game::entityManager->GetEntitiesInGroup(self->GetVar<std::string>(FXManagerGroup)); if (entities.empty()) { self->AddTimer("pollTornadoFX", 0.1f); return; } for (auto* entity : entities) { auto* renderComponent = entity->GetComponent<RenderComponent>(); if (renderComponent != nullptr) { renderComponent->PlayEffect(-1, u"debrisOn", "TornadoDebris"); renderComponent->PlayEffect(-1, u"VortexOn", "TornadoVortex"); renderComponent->PlayEffect(-1, u"onSilhouette", "silhouette"); } } } void BasePropertyServer::BasePlayerExit(Entity* self, Entity* player) { if (self->GetBoolean(UnclaimedVariable)) { if (player->GetObjectID() == self->GetVar<LWOOBJID>(PlayerIDVariable)) { // Destroy all spawners } } } void BasePropertyServer::KillGuard(Entity* self) { const auto entities = Game::entityManager->GetEntitiesInGroup(self->GetVar<std::string>(GuardGroup)); if (entities.empty()) return; DeactivateSpawner(self->GetVar<std::string>(PropertyMGSpawner)); auto* guard = entities[0]; guard->Smash(self->GetObjectID()); } void BasePropertyServer::RequestDie(Entity* self, Entity* other) { auto* destroyable = other->GetComponent<DestroyableComponent>(); if (destroyable == nullptr) return; destroyable->Smash(other->GetObjectID(), eKillType::SILENT); } void BasePropertyServer::ActivateSpawner(const std::string& spawnerName) { for (auto* spawner : Game::zoneManager->GetSpawnersByName(spawnerName)) { spawner->Activate(); } } void BasePropertyServer::DeactivateSpawner(const std::string& spawnerName) { for (auto* spawner : Game::zoneManager->GetSpawnersByName(spawnerName)) { spawner->Deactivate(); } } void BasePropertyServer::TriggerSpawner(const std::string& spawnerName) { for (auto* spawner : Game::zoneManager->GetSpawnersInGroup(spawnerName)) { spawner->Spawn(); } } void BasePropertyServer::ResetSpawner(const std::string& spawnerName) { for (auto* spawner : Game::zoneManager->GetSpawnersByName(spawnerName)) { spawner->Reset(); } } void BasePropertyServer::DestroySpawner(const std::string& spawnerName) { for (auto* spawner : Game::zoneManager->GetSpawnersByName(spawnerName)) { if (!spawner) return; spawner->DestroyAllEntities(); spawner->Deactivate(); } } LWOOBJID BasePropertyServer::GetOwner() { auto* manager = PropertyManagementComponent::Instance(); return manager == nullptr ? LWOOBJID_EMPTY : manager->GetOwnerId(); } void BasePropertyServer::BaseTimerDone(Entity* self, const std::string& timerName) { if (timerName == StartGeneratorTimer) { HandleGeneratorTimer(self); } else if (timerName == StartOrbTimer) { HandleOrbsTimer(self); } else if (timerName == StartQuickbuildTimer) { HandleQuickBuildTimer(self); } else if (timerName == "GuardFlyAway") { const auto zoneId = Game::zoneManager->GetZone()->GetWorldID(); // No guard for the spider instance fight if (Game::zoneManager->GetZoneID().GetMapID() == 1150) return; const auto entities = Game::entityManager->GetEntitiesInGroup(self->GetVar<std::string>(GuardGroup)); if (entities.empty()) return; auto* guard = entities[0]; GameMessages::SendNotifyClientObject(Game::entityManager->GetZoneControlEntity()->GetObjectID(), u"GuardChat", 0, 0, guard->GetObjectID(), "", UNASSIGNED_SYSTEM_ADDRESS); self->AddTimer(KillGuardTimer, 5.0f); } else if (timerName == KillGuardTimer) { KillGuard(self); } else if (timerName == TornadoOffTimer) { auto fxManagers = Game::entityManager->GetEntitiesInGroup(self->GetVar<std::string>(FXManagerGroup)); for (auto* fxManager : fxManagers) { auto* renderComponent = fxManager->GetComponent<RenderComponent>(); if (renderComponent != nullptr) { renderComponent->StopEffect("TornadoDebris", false); renderComponent->StopEffect("TornadoVortex", false); renderComponent->StopEffect("silhouette", false); } } self->AddTimer(ShowClearEffectsTimer, 2); } else if (timerName == ShowClearEffectsTimer) { auto fxManagers = Game::entityManager->GetEntitiesInGroup(self->GetVar<std::string>(FXManagerGroup)); for (auto* fxManager : fxManagers) { auto* renderComponent = fxManager->GetComponent<RenderComponent>(); if (renderComponent != nullptr) renderComponent->PlayEffect(-1, u"beamOn", "beam"); } self->AddTimer(KillStrombiesTimer, 2.0f); self->AddTimer(TurnSkyOffTimer, 1.5f); self->AddTimer(KillFXObjectTimer, 8.0f); } else if (timerName == TurnSkyOffTimer) { auto* controller = Game::zoneManager->GetZoneControlObject(); GameMessages::SendNotifyClientObject(controller->GetObjectID(), u"SkyOff", 0, 0, LWOOBJID_EMPTY, "", UNASSIGNED_SYSTEM_ADDRESS); } else if (timerName == KillStrombiesTimer) { const auto enemies = Game::entityManager->GetEntitiesInGroup(self->GetVar<std::string>(EnemiesGroup)); for (auto* enemy : enemies) { RequestDie(self, enemy); } DestroySpawner(self->GetVar<std::string>(SmashablesSpawner)); KillSpots(self); auto* player = Game::entityManager->GetEntity(self->GetVar<LWOOBJID>(PlayerIDVariable)); if (player == nullptr) return; GameMessages::SendStop2DAmbientSound(player, true, GUIDMaelstrom); GameMessages::SendPlay2DAmbientSound(player, GUIDPeaceful); self->AddTimer(ShowVendorTimer, 5.0f); } else if (timerName == KillMarkerTimer) { DestroySpawner(self->GetVar<std::string>(ClaimMarkerSpawner)); for (const auto& behaviorObjectSpawner : self->GetVar<std::vector<std::string>>(BehaviorObjsSpawner)) { DestroySpawner(behaviorObjectSpawner); } for (auto* entity : Game::entityManager->GetEntitiesInGroup(self->GetVar<std::string>(ImagOrbGroup))) { entity->Smash(); } DestroySpawner(self->GetVar<std::string>(ImageOrbSpawner)); self->AddTimer(ShowVendorTimer, 1.0f); } else if (timerName == ShowVendorTimer) { GameMessages::SendNotifyClientObject(Game::entityManager->GetZoneControlEntity()->GetObjectID(), u"vendorOn", 0, 0, LWOOBJID_EMPTY, "", UNASSIGNED_SYSTEM_ADDRESS); for (const auto& ambientFXSpawner : self->GetVar<std::vector<std::string>>(AmbientFXSpawner)) { ActivateSpawner(ambientFXSpawner); } } else if (timerName == BoundsVisOnTimer) { GameMessages::SendNotifyClientObject(self->GetObjectID(), u"boundsAnim", 0, 0, LWOOBJID_EMPTY, "", UNASSIGNED_SYSTEM_ADDRESS); } else if (timerName == RunPlayerLoadedAgainTimer) { CheckForOwner(self); } else if (timerName == PollTornadoFXTimer) { StartTornadoFx(self); } else if (timerName == KillFXObjectTimer) { const auto fxManagers = Game::entityManager->GetEntitiesInGroup(self->GetVar<std::string>(FXManagerGroup)); if (fxManagers.empty()) { self->AddTimer(KillFXObjectTimer, 1.0f); return; } for (auto* fxManager : fxManagers) { auto* renderComponent = fxManager->GetComponent<RenderComponent>(); if (renderComponent != nullptr) { renderComponent->StopEffect("beam"); } } DestroySpawner(self->GetVar<std::string>(FXManagerSpawner)); self->SetVar<bool>(u"FXObjectGone", true); } } void BasePropertyServer::HandleOrbsTimer(Entity* self) { self->SetVar<bool>(CollidedVariable, false); auto orbs = Game::entityManager->GetEntitiesInGroup(self->GetVar<std::string>(ImagOrbGroup)); if (orbs.empty()) { self->AddTimer(StartOrbTimer, 0.5f); return; } for (auto* orb : orbs) { orb->AddCollisionPhantomCallback([self, this](Entity* other) { if (other != nullptr && other->IsPlayer() && !self->GetVar<bool>(CollidedVariable)) { self->SetVar<bool>(CollidedVariable, true); KillClouds(self); DeactivateSpawner(self->GetVar<std::string>(GeneratorSpawner)); for (const auto& enemySpawner : self->GetVar<std::vector<std::string>>(EnemiesSpawner)) { DeactivateSpawner(enemySpawner); } DestroySpawner(self->GetVar<std::string>(GeneratorFXSpawner)); GameMessages::SendNotifyClientObject(Game::entityManager->GetZoneControlEntity()->GetObjectID(), u"PlayCinematic", 0, 0, LWOOBJID_EMPTY, "DestroyMaelstrom", UNASSIGNED_SYSTEM_ADDRESS); // Notifies the client that the property has been claimed with a flag, completes missions too auto* player = Game::entityManager->GetEntity(self->GetVar<LWOOBJID>(PlayerIDVariable)); if (player != nullptr) { auto* character = player->GetCharacter(); if (character != nullptr) { character->SetPlayerFlag(self->GetVar<int32_t>(defeatedProperyFlag), true); } } self->AddTimer(TornadoOffTimer, 0.5f); self->AddTimer(KillMarkerTimer, 0.7f); } }); } } void BasePropertyServer::HandleGeneratorTimer(Entity* self) { auto generators = Game::entityManager->GetEntitiesInGroup(self->GetVar<std::string>(GeneratorGroup)); if (generators.empty()) { self->AddTimer(StartGeneratorTimer, 0.5f); return; } for (auto* generator : generators) { generator->AddDieCallback([self, this]() { ActivateSpawner(self->GetVar<std::string>(ClaimMarkerSpawner)); self->AddTimer(StartQuickbuildTimer, 0.0f); for (const auto& enemySpawner : self->GetVar<std::vector<std::string>>(EnemiesSpawner)) { DeactivateSpawner(enemySpawner); } DeactivateSpawner(self->GetVar<std::string>(GeneratorSpawner)); }); } } void BasePropertyServer::HandleQuickBuildTimer(Entity* self) { auto claimMarkers = Game::entityManager->GetEntitiesInGroup(self->GetVar<std::string>(ClaimMarkerGroup)); if (claimMarkers.empty()) { self->AddTimer(StartQuickbuildTimer, 0.5f); return; } for (auto* claimMarker : claimMarkers) { // TODO: Send password? } }