mirror of
				https://github.com/DarkflameUniverse/DarkflameServer.git
				synced 2025-10-26 18:11:59 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			244 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			244 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #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");
 | |
| 
 | |
| 	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 = QuatUtils::Forward(rot);
 | |
| 		pos.x += dir.x * offset;
 | |
| 		pos.z += dir.z * offset;
 | |
| 		info.pos = pos;
 | |
| 	} else if (loc == "Rear") {
 | |
| 		const auto dir = QuatUtils::Right(rot);
 | |
| 		pos.x += dir.x * offset;
 | |
| 		pos.z += dir.z * offset;
 | |
| 		info.pos = pos;
 | |
| 	} else if (loc == "Left") {
 | |
| 		const auto dir = QuatUtils::Forward(rot) * -1;
 | |
| 		pos.x += dir.x * offset;
 | |
| 		pos.z += dir.z * offset;
 | |
| 		info.pos = pos;
 | |
| 	}
 | |
| 
 | |
| 	info.rot = QuatUtils::LookAt(info.pos, self->GetPosition());
 | |
| 
 | |
| 	auto* entity = Game::entityManager->CreateEntity(info, nullptr, self);
 | |
| 
 | |
| 	Game::entityManager->ConstructEntity(entity);
 | |
| }
 | |
| 
 | |
| void AmSkullkinTower::OnChildLoaded(Entity& self, GameMessages::ChildLoaded& childLoaded) {
 | |
| 	auto legTable = self.GetVar<std::vector<LWOOBJID>>(u"legTable");
 | |
| 
 | |
| 	legTable.push_back(childLoaded.childID);
 | |
| 
 | |
| 	self.SetVar(u"legTable", legTable);
 | |
| 
 | |
| 	const auto selfID = self.GetObjectID();
 | |
| 	auto* const child = Game::entityManager->GetEntity(childLoaded.childID);
 | |
| 
 | |
| 	if (!child) return;
 | |
| 
 | |
| 	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;
 | |
| 			}
 | |
| 
 | |
| 			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 = Game::entityManager->CreateEntity(info);
 | |
| 
 | |
| 			Game::entityManager->ConstructEntity(entity);
 | |
| 		}
 | |
| 
 | |
| 		self->AddTimer("killTower", 0.7f);
 | |
| 	} else if (timerName == "killTower") {
 | |
| 		self->Smash(self->GetObjectID());
 | |
| 	}
 | |
| }
 | 
