mirror of
				https://github.com/DarkflameUniverse/DarkflameServer.git
				synced 2025-10-31 12:41:55 +00:00 
			
		
		
		
	 bd9b790e1d
			
		
	
	bd9b790e1d
	
	
	
		
			
			* remove goto * Update MovementAIComponent.cpp * convert to PathWaypoint Easier for usage with paths * add path parsing * ref removal, simplification of work * it works * Update MovementAIComponent.cpp * disable pathing for combat we just need it for npcs for now, combat ai can be done later * fixed stuttery enemies wow * start at ramped up speed * add pausing and resuming * Update MovementAIComponent.cpp * Update MovementAIComponent.h * Update CMakeLists.txt
		
			
				
	
	
		
			1095 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1095 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "SGCannon.h"
 | |
| #include "EntityManager.h"
 | |
| #include "GameMessages.h"
 | |
| #include "dZoneManager.h"
 | |
| #include "Character.h"
 | |
| #include "ShootingGalleryComponent.h"
 | |
| #include "PossessorComponent.h"
 | |
| #include "CharacterComponent.h"
 | |
| #include "SimplePhysicsComponent.h"
 | |
| #include "MovementAIComponent.h"
 | |
| #include "ObjectIDManager.h"
 | |
| #include "MissionComponent.h"
 | |
| #include "Loot.h"
 | |
| #include "InventoryComponent.h"
 | |
| #include "eMissionTaskType.h"
 | |
| #include "eReplicaComponentType.h"
 | |
| #include "RenderComponent.h"
 | |
| #include "eGameActivity.h"
 | |
| 
 | |
| void SGCannon::OnStartup(Entity* self) {
 | |
| 	LOG("OnStartup");
 | |
| 
 | |
| 	m_Waves = GetWaves();
 | |
| 	constants = GetConstants();
 | |
| 
 | |
| 	ResetVars(self);
 | |
| 
 | |
| 	self->SetVar<bool>(GameStartedVariable, false);
 | |
| 	self->SetVar<Vector3>(InitialVelocityVariable, {});
 | |
| 	self->SetVar<uint32_t>(ImpactSkillVariale, constants.impactSkillID);
 | |
| 
 | |
| 	auto* shootingGalleryComponent = self->GetComponent<ShootingGalleryComponent>();
 | |
| 	if (shootingGalleryComponent != nullptr) {
 | |
| 		shootingGalleryComponent->SetStaticParams({
 | |
| 			Vector3 { -327.8609924316406, 256.8999938964844, 1.6482199430465698 },
 | |
| 			Vector3 { -181.4320068359375, 212.39999389648438, 2.5182199478149414 }
 | |
| 			});
 | |
| 
 | |
| 		shootingGalleryComponent->SetDynamicParams({
 | |
| 			Vector3 { 0.0, 4.3, 9.0 },
 | |
| 			Vector3 { },
 | |
| 			129.0,
 | |
| 			800.0,
 | |
| 			30.0,
 | |
| 			0.0,
 | |
| 			-1.0,
 | |
| 			58.6
 | |
| 			});
 | |
| 	}
 | |
| 
 | |
| 	self->SetVar<uint32_t>(TimeLimitVariable, 30);
 | |
| 	self->SetVar<std::vector<LOT>>(ValidActorsVariable, { 3109, 3110, 3111, 3112, 3125, 3126 });
 | |
| 	self->SetVar<std::vector<LOT>>(ValidEffectsVariable, { 3122 });
 | |
| 	self->SetVar<std::vector<uint32_t>>(StreakBonusVariable, { 1, 2, 5, 10 });
 | |
| 	self->SetVar<bool>(SuperChargeActiveVariable, false);
 | |
| 	self->SetVar<uint32_t>(MatrixVariable, 1);
 | |
| 	self->SetVar<bool>(InitVariable, true);
 | |
| 
 | |
| 	auto* simplePhysicsComponent = self->GetComponent<SimplePhysicsComponent>();
 | |
| 
 | |
| 	if (simplePhysicsComponent != nullptr) {
 | |
| 		simplePhysicsComponent->SetPhysicsMotionState(5);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void SGCannon::OnPlayerLoaded(Entity* self, Entity* player) {
 | |
| 	LOG("Player loaded");
 | |
| 	self->SetVar<LWOOBJID>(PlayerIDVariable, player->GetObjectID());
 | |
| }
 | |
| 
 | |
| void SGCannon::OnFireEventServerSide(Entity* self, Entity* sender, std::string args, int32_t param1, int32_t param2,
 | |
| 	int32_t param3) {
 | |
| 	Script::OnFireEventServerSide(self, sender, args, param1, param2, param3);
 | |
| }
 | |
| 
 | |
| void SGCannon::OnActivityStateChangeRequest(Entity* self, LWOOBJID senderID, int32_t value1, int32_t value2,
 | |
| 	const std::u16string& stringValue) {
 | |
| 	LOG("Got activity state change request: %s", GeneralUtils::UTF16ToWTF8(stringValue).c_str());
 | |
| 	if (stringValue == u"clientready") {
 | |
| 		auto* player = Game::entityManager->GetEntity(self->GetVar<LWOOBJID>(PlayerIDVariable));
 | |
| 		if (player != nullptr) {
 | |
| 			LOG("Player is ready");
 | |
| 			/*GameMessages::SendSetStunned(player->GetObjectID(), eStateChangeType::PUSH, player->GetSystemAddress(), LWOOBJID_EMPTY,
 | |
| 										 true, true, true, true, true, true, true);*/
 | |
| 
 | |
| 			LOG("Sending ActivityEnter");
 | |
| 
 | |
| 			GameMessages::SendActivityEnter(self->GetObjectID(), player->GetSystemAddress());
 | |
| 
 | |
| 			auto* shootingGalleryComponent = self->GetComponent<ShootingGalleryComponent>();
 | |
| 
 | |
| 			if (shootingGalleryComponent != nullptr) {
 | |
| 				shootingGalleryComponent->SetCurrentPlayerID(player->GetObjectID());
 | |
| 
 | |
| 				LOG("Setting player ID");
 | |
| 
 | |
| 				Game::entityManager->SerializeEntity(self);
 | |
| 			} else {
 | |
| 				LOG("Shooting gallery component is null");
 | |
| 			}
 | |
| 
 | |
| 			auto* characterComponent = player->GetComponent<CharacterComponent>();
 | |
| 
 | |
| 			if (characterComponent != nullptr) {
 | |
| 				characterComponent->SetIsRacing(true);
 | |
| 				characterComponent->SetCurrentActivity(eGameActivity::SHOOTING_GALLERY);
 | |
| 				auto possessor = player->GetComponent<PossessorComponent>();
 | |
| 				if (possessor) {
 | |
| 					possessor->SetPossessable(self->GetObjectID());
 | |
| 					possessor->SetPossessableType(ePossessionType::NO_POSSESSION);
 | |
| 				}
 | |
| 
 | |
| 				Game::entityManager->SerializeEntity(player);
 | |
| 			}
 | |
| 
 | |
| 			self->SetNetworkVar<bool>(HideScoreBoardVariable, true);
 | |
| 			self->SetNetworkVar<bool>(ReSetSuperChargeVariable, true);
 | |
| 			self->SetNetworkVar<bool>(ShowLoadingUI, true);
 | |
| 
 | |
| 			/*
 | |
| 			GameMessages::SendTeleport(
 | |
| 				player->GetObjectID(),
 | |
| 				{-292.6415710449219, 230.20237731933594, -3.9090466499328613},
 | |
| 				{0.7067984342575073, -6.527870573336259e-05, 0.707414984703064, 0.00021762956748716533},
 | |
| 				player->GetSystemAddress(), true
 | |
| 			);
 | |
| 			*/
 | |
| 
 | |
| 			//GameMessages::SendRequestActivityEnter(self->GetObjectID(), player->GetSystemAddress(), false, player->GetObjectID());
 | |
| 		} else {
 | |
| 			LOG("Player not found");
 | |
| 		}
 | |
| 	} else if (value1 == 1200) {
 | |
| 		StartGame(self);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void SGCannon::OnMessageBoxResponse(Entity* self, Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData) {
 | |
| 	auto* player = Game::entityManager->GetEntity(self->GetVar<LWOOBJID>(PlayerIDVariable));
 | |
| 	if (!player) return;
 | |
| 
 | |
| 	if (identifier == u"Scoreboardinfo") {
 | |
| 		GameMessages::SendDisplayMessageBox(player->GetObjectID(), true,
 | |
| 			Game::zoneManager->GetZoneControlObject()->GetObjectID(),
 | |
| 			u"Shooting_Gallery_Retry", 2, u"Retry?",
 | |
| 			u"", player->GetSystemAddress());
 | |
| 	} else {
 | |
| 		if ((button == 1 && (identifier == u"Shooting_Gallery_Retry" || identifier == u"RePlay")) || identifier == u"SG1" || button == 0) {
 | |
| 			if (IsPlayerInActivity(self, player->GetObjectID())) return;
 | |
| 			self->SetNetworkVar<bool>(ClearVariable, true);
 | |
| 			StartGame(self);
 | |
| 		} else if (button == 0 && ((identifier == u"Shooting_Gallery_Retry" || identifier == u"RePlay"))) {
 | |
| 			RemovePlayer(player->GetObjectID());
 | |
| 			UpdatePlayer(self, player->GetObjectID(), true);
 | |
| 		} else if (button == 1 && identifier == u"Shooting_Gallery_Exit") {
 | |
| 			UpdatePlayer(self, player->GetObjectID(), true);
 | |
| 			RemovePlayer(player->GetObjectID());
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void SGCannon::SuperChargeTimerFunc(Entity* self) {
 | |
| 	if (self->GetVar<bool>(WaveStatusVariable) || self->GetVar<uint32_t>(CurrentSuperChargedTimeVariable) < 1) {
 | |
| 		self->SetNetworkVar<uint32_t>(ChargeCountingVariable, 99);
 | |
| 		self->SetNetworkVar<uint32_t>(SuperChargeBarVariable, 0);
 | |
| 		ToggleSuperCharge(self, false);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void SGCannon::SpawnWaveTimerFunc(Entity* self) {
 | |
| 	if (self->GetVar<bool>(GameStartedVariable)) {
 | |
| 		self->SetVar<bool>(WaveStatusVariable, true);
 | |
| 		const auto wave = static_cast<int32_t>(self->GetVar<uint32_t>(ThisWaveVariable));
 | |
| 
 | |
| 		if (wave != 0 && self->GetVar<bool>(SuperChargePausedVariable)) {
 | |
| 			StartChargedCannon(self, self->GetVar<uint32_t>(CurrentSuperChargedTimeVariable));
 | |
| 			self->SetVar<uint32_t>(CurrentSuperChargedTimeVariable, 0);
 | |
| 		}
 | |
| 
 | |
| 		TimerToggle(self, true);
 | |
| 
 | |
| 		for (const auto& enemyToSpawn : m_Waves.at(self->GetVar<uint32_t>(ThisWaveVariable))) {
 | |
| 			SpawnObject(self, enemyToSpawn, true);
 | |
| 		}
 | |
| 
 | |
| 		LOG("Current wave spawn: %i/%i", wave, m_Waves.size());
 | |
| 
 | |
| 		// All waves completed
 | |
| 		const auto timeLimit = static_cast<float_t>(self->GetVar<uint32_t>(TimeLimitVariable));
 | |
| 		if (wave >= m_Waves.size()) {
 | |
| 			ActivityTimerStart(self, GameOverTimer, timeLimit, timeLimit);
 | |
| 		} else {
 | |
| 			ActivityTimerStart(self, EndWaveTimer, timeLimit, timeLimit);
 | |
| 		}
 | |
| 
 | |
| 		const auto* player = Game::entityManager->GetEntity(self->GetVar<LWOOBJID>(PlayerIDVariable));
 | |
| 		if (player != nullptr) {
 | |
| 			GameMessages::SendPlayFXEffect(player->GetObjectID(), -1, u"SG-start", "");
 | |
| 
 | |
| 			GameMessages::SendStartActivityTime(self->GetObjectID(), timeLimit, player->GetSystemAddress());
 | |
| 			LOG("Sending ActivityPause false");
 | |
| 
 | |
| 			GameMessages::SendActivityPause(self->GetObjectID(), false, player->GetSystemAddress());
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void SGCannon::EndWaveTimerFunc(Entity* self) {
 | |
| 	self->SetVar<bool>(WaveStatusVariable, false);
 | |
| 	TimerToggle(self);
 | |
| 	RecordPlayerScore(self);
 | |
| 
 | |
| 	if (self->GetVar<uint32_t>(ThisWaveVariable) >= 2) {
 | |
| 		GameMessages::SendActivityPause(self->GetObjectID(), true);
 | |
| 		ActivityTimerStart(self, GameOverTimer, 0.1, 0.1);
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	self->SetVar<uint32_t>(ThisWaveVariable, self->GetVar<uint32_t>(ThisWaveVariable) + 1);
 | |
| 	PlaySceneAnimation(self, u"wave" + GeneralUtils::to_u16string(self->GetVar<uint32_t>(ThisWaveVariable)), true, true, 1.7f);
 | |
| 	self->SetNetworkVar<uint32_t>(WaveNumVariable, self->GetVar<uint32_t>(ThisWaveVariable) + 1);
 | |
| 	self->SetNetworkVar<uint32_t>(WaveStrVariable, self->GetVar<uint32_t>(TimeLimitVariable));
 | |
| 
 | |
| 	LOG("Current wave: %i/%i", self->GetVar<uint32_t>(ThisWaveVariable), m_Waves.size());
 | |
| 
 | |
| 	if (self->GetVar<uint32_t>(ThisWaveVariable) >= m_Waves.size()) {
 | |
| 		ActivityTimerStart(self, GameOverTimer, 0.1, 0.1);
 | |
| 	} else {
 | |
| 		ActivityTimerStart(self, SpawnWaveTimer, constants.inBetweenWavePause, constants.inBetweenWavePause);
 | |
| 	}
 | |
| 
 | |
| 	LOG("Sending ActivityPause true");
 | |
| 
 | |
| 	GameMessages::SendActivityPause(self->GetObjectID(), true);
 | |
| 	if (self->GetVar<bool>(SuperChargeActiveVariable) && !self->GetVar<bool>(SuperChargePausedVariable)) {
 | |
| 		PauseChargeCannon(self);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void SGCannon::GameOverTimerFunc(Entity* self) {
 | |
| 	auto* player = Game::entityManager->GetEntity(self->GetVar<LWOOBJID>(PlayerIDVariable));
 | |
| 	if (player != nullptr) {
 | |
| 		LOG_DEBUG("Sending ActivityPause true");
 | |
| 
 | |
| 		GameMessages::SendActivityPause(self->GetObjectID(), true, player->GetSystemAddress());
 | |
| 
 | |
| 		/*const auto leftoverCannonballs = Game::entityManager->GetEntitiesInGroup("cannonball");
 | |
| 		if (leftoverCannonballs.empty()) {
 | |
| 			RecordPlayerScore(self);
 | |
| 
 | |
| 		} else {
 | |
| 			ActivityTimerStart(self, EndGameBufferTimer, 1, leftoverCannonballs.size());
 | |
| 		}*/
 | |
| 
 | |
| 		ActivityTimerStart(self, EndGameBufferTimer, 1, 1);
 | |
| 
 | |
| 		TimerToggle(self);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void SGCannon::DoSpawnTimerFunc(Entity* self, const std::string& name) {
 | |
| 	if (self->GetVar<bool>(GameStartedVariable)) {
 | |
| 		LOG_DEBUG("time name %s %s", name.c_str(), name.substr(7).c_str());
 | |
| 		const auto spawnNumber = static_cast<uint32_t>(std::stoi(name.substr(7)));
 | |
| 		const auto& activeSpawns = self->GetVar<std::vector<SGEnemy>>(ActiveSpawnsVariable);
 | |
| 		LOG_DEBUG("size %i, %i", activeSpawns.size(), spawnNumber);
 | |
| 		if (activeSpawns.size() <= spawnNumber) {
 | |
| 			LOG_DEBUG("Trying to spawn %i when spawns size is only %i", spawnNumber, activeSpawns.size());
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		const auto& toSpawn = activeSpawns.at(spawnNumber);
 | |
| 		LOG_DEBUG("toSpawn %i", toSpawn.spawnPaths.size());
 | |
| 		const auto pathIndex = GeneralUtils::GenerateRandomNumber<float_t>(0, toSpawn.spawnPaths.size() - 1);
 | |
| 		LOG_DEBUG("index %f", pathIndex);
 | |
| 		LOG_DEBUG("%s", toSpawn.spawnPaths.at(pathIndex).c_str());
 | |
| 		const auto* path = Game::zoneManager->GetZone()->GetPath(toSpawn.spawnPaths.at(pathIndex));
 | |
| 		if (!path) {
 | |
| 			LOG_DEBUG("Path %s at index %i is null", toSpawn.spawnPaths.at(pathIndex).c_str(), pathIndex);
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		LOG_DEBUG("%s", path->pathName.c_str());
 | |
| 
 | |
| 		auto info = EntityInfo{};
 | |
| 		info.lot = toSpawn.lot;
 | |
| 		info.spawnerID = self->GetObjectID();
 | |
| 		info.pos = path->pathWaypoints.at(0).position;
 | |
| 
 | |
| 		info.settings = {
 | |
| 			new LDFData<SGEnemy>(u"SpawnData", toSpawn),
 | |
| 			new LDFData<std::string>(u"custom_script_server", "scripts/ai/ACT/SG_TARGET.lua"),
 | |
| 			new LDFData<std::string>(u"custom_script_client", "scripts/client/ai/SG_TARGET_CLIENT.lua"),
 | |
| 			new LDFData<std::string>(u"attached_path", path->pathName),
 | |
| 			new LDFData<uint32_t>(u"attached_path_start", 0),
 | |
| 			new LDFData<std::u16string>(u"groupID", u"SGEnemy")
 | |
| 		};
 | |
| 
 | |
| 		LOG_DEBUG("Spawning enemy %i on path %s", toSpawn.lot, path->pathName.c_str());
 | |
| 
 | |
| 		auto* enemy = Game::entityManager->CreateEntity(info, nullptr, self);
 | |
| 		Game::entityManager->ConstructEntity(enemy);
 | |
| 
 | |
| 		auto* movementAI = enemy->AddComponent<MovementAIComponent>(MovementAIInfo{});
 | |
| 
 | |
| 		movementAI->SetMaxSpeed(toSpawn.initialSpeed);
 | |
| 		movementAI->SetCurrentSpeed(toSpawn.initialSpeed);
 | |
| 		movementAI->SetHaltDistance(0.0f);
 | |
| 
 | |
| 		std::vector<PathWaypoint> pathWaypoints = path->pathWaypoints;
 | |
| 
 | |
| 		if (GeneralUtils::GenerateRandomNumber<float_t>(0, 1) < 0.5f) {
 | |
| 			std::reverse(pathWaypoints.begin(), pathWaypoints.end());
 | |
| 		}
 | |
| 
 | |
| 		movementAI->SetPath(pathWaypoints);
 | |
| 
 | |
| 		enemy->AddDieCallback([this, self, enemy, name]() {
 | |
| 			RegisterHit(self, enemy, name);
 | |
| 			});
 | |
| 
 | |
| 		// Save the enemy and tell it to start pathing
 | |
| 		if (enemy != nullptr) {
 | |
| 			const_cast<std::vector<LWOOBJID>&>(self->GetVar<std::vector<LWOOBJID>>(SpawnedObjects)).push_back(enemy->GetObjectID());
 | |
| 			GameMessages::SendPlatformResync(enemy, UNASSIGNED_SYSTEM_ADDRESS);
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void SGCannon::EndGameBufferTimerFunc(Entity* self) {
 | |
| 	RecordPlayerScore(self);
 | |
| 	StopGame(self, false);
 | |
| }
 | |
| 
 | |
| void SGCannon::OnActivityTimerDone(Entity* self, const std::string& name) {
 | |
| 	if (name == SuperChargeTimer && !self->GetVar<bool>(SuperChargePausedVariable)) {
 | |
| 		SuperChargeTimerFunc(self);
 | |
| 	} else if (name == SpawnWaveTimer) {
 | |
| 		SpawnWaveTimerFunc(self);
 | |
| 	} else if (name == EndWaveTimer) {
 | |
| 		EndWaveTimerFunc(self);
 | |
| 	} else if (name == GameOverTimer) {
 | |
| 		GameOverTimerFunc(self);
 | |
| 	} else if (name.rfind(DoSpawnTimer, 0) == 0) {
 | |
| 		DoSpawnTimerFunc(self, name);
 | |
| 	} else if (name == EndGameBufferTimer) {
 | |
| 		EndGameBufferTimerFunc(self);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void
 | |
| SGCannon::OnActivityTimerUpdate(Entity* self, const std::string& name, float_t timeRemaining, float_t elapsedTime) {
 | |
| 	ActivityManager::OnActivityTimerUpdate(self, name, timeRemaining, elapsedTime);
 | |
| }
 | |
| 
 | |
| void SGCannon::StartGame(Entity* self) {
 | |
| 	if (self->GetVar<bool>(GameStartedVariable)) return;
 | |
| 	self->SetNetworkVar<uint32_t>(TimeLimitVariable, self->GetVar<uint32_t>(TimeLimitVariable));
 | |
| 	self->SetNetworkVar<bool>(AudioStartIntroVariable, true);
 | |
| 	self->SetVar<LOT>(CurrentRewardVariable, LOT_NULL);
 | |
| 
 | |
| 	auto rewardObjects = Game::entityManager->GetEntitiesInGroup(constants.rewardModelGroup);
 | |
| 	for (auto* reward : rewardObjects) {
 | |
| 		reward->OnFireEventServerSide(self, ModelToBuildEvent);
 | |
| 	}
 | |
| 
 | |
| 	auto* player = Game::entityManager->GetEntity(self->GetVar<LWOOBJID>(PlayerIDVariable));
 | |
| 	if (player != nullptr) {
 | |
| 		GetLeaderboardData(self, player->GetObjectID(), GetActivityID(self), 1);
 | |
| 		LOG("Sending ActivityStart");
 | |
| 		GameMessages::SendActivityStart(self->GetObjectID(), player->GetSystemAddress());
 | |
| 
 | |
| 		GameMessages::SendPlayFXEffect(self->GetObjectID(), -1, u"start", "");
 | |
| 
 | |
| 		self->SetNetworkVar<bool>(ClearVariable, true);
 | |
| 		DoGameStartup(self);
 | |
| 
 | |
| 		if (!self->GetVar<bool>(FirstTimeDoneVariable)) {
 | |
| 			TakeActivityCost(self, player->GetObjectID());
 | |
| 		}
 | |
| 
 | |
| 		self->SetVar<bool>(FirstTimeDoneVariable, true);
 | |
| 	}
 | |
| 
 | |
| 	SpawnNewModel(self);
 | |
| }
 | |
| 
 | |
| void SGCannon::DoGameStartup(Entity* self) {
 | |
| 	ResetVars(self);
 | |
| 	self->SetVar<bool>(GameStartedVariable, true);
 | |
| 	self->SetNetworkVar<bool>(ClearVariable, true);
 | |
| 	self->SetVar<uint32_t>(ThisWaveVariable, 0);
 | |
| 
 | |
| 	if (constants.firstWaveStartTime < 1) {
 | |
| 		constants.firstWaveStartTime = 1;
 | |
| 	}
 | |
| 
 | |
| 	ActivityTimerStart(self, SpawnWaveTimer, constants.firstWaveStartTime,
 | |
| 		constants.firstWaveStartTime);
 | |
| }
 | |
| 
 | |
| void SGCannon::SpawnNewModel(Entity* self) {
 | |
| 
 | |
| 	// Add a new reward to the existing rewards
 | |
| 	const auto currentReward = self->GetVar<LOT>(CurrentRewardVariable);
 | |
| 	if (currentReward != -1) {
 | |
| 		auto rewards = self->GetVar<std::vector<LOT>>(RewardsVariable);
 | |
| 		rewards.push_back(currentReward);
 | |
| 		self->SetNetworkVar<int32_t>(RewardAddedVariable, currentReward);
 | |
| 	}
 | |
| 
 | |
| 	auto* player = Game::entityManager->GetEntity(self->GetVar<LWOOBJID>(PlayerIDVariable));
 | |
| 	if (player != nullptr) {
 | |
| 		for (auto* rewardModel : Game::entityManager->GetEntitiesInGroup(constants.rewardModelGroup)) {
 | |
| 			uint32_t lootMatrix;
 | |
| 			switch (self->GetVar<uint32_t>(MatrixVariable)) {
 | |
| 			case 1:
 | |
| 				lootMatrix = constants.scoreLootMatrix1;
 | |
| 				break;
 | |
| 			case 2:
 | |
| 				lootMatrix = constants.scoreLootMatrix2;
 | |
| 				break;
 | |
| 			case 3:
 | |
| 				lootMatrix = constants.scoreLootMatrix3;
 | |
| 				break;
 | |
| 			case 4:
 | |
| 				lootMatrix = constants.scoreLootMatrix4;
 | |
| 				break;
 | |
| 			case 5:
 | |
| 				lootMatrix = constants.scoreLootMatrix5;
 | |
| 				break;
 | |
| 			default:
 | |
| 				lootMatrix = 0;
 | |
| 			}
 | |
| 
 | |
| 			if (lootMatrix != 0) {
 | |
| 				std::unordered_map<LOT, int32_t> toDrop = {};
 | |
| 				toDrop = Loot::RollLootMatrix(player, lootMatrix);
 | |
| 
 | |
| 				for (auto drop : toDrop) {
 | |
| 					rewardModel->OnFireEventServerSide(self, ModelToBuildEvent, drop.first);
 | |
| 					self->SetVar<LOT>(CurrentRewardVariable, drop.first);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void SGCannon::RemovePlayer(LWOOBJID playerID) {
 | |
| 	auto* player = Game::entityManager->GetEntity(playerID);
 | |
| 	if (!player) return;
 | |
| 
 | |
| 	auto* character = player->GetCharacter();
 | |
| 	auto* characterComponent = player->GetComponent<CharacterComponent>();
 | |
| 	if (characterComponent && character) {
 | |
| 		characterComponent->SendToZone(character->GetLastNonInstanceZoneID());
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void SGCannon::OnRequestActivityExit(Entity* self, LWOOBJID player, bool canceled) {
 | |
| 	if (canceled) {
 | |
| 		StopGame(self, canceled);
 | |
| 		RemovePlayer(player);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| void SGCannon::StartChargedCannon(Entity* self, uint32_t optionalTime) {
 | |
| 	optionalTime = optionalTime == 0 ? constants.chargedTime : optionalTime;
 | |
| 	self->SetVar<bool>(SuperChargePausedVariable, false);
 | |
| 	ToggleSuperCharge(self, true);
 | |
| 	ActivityTimerStart(self, SuperChargeTimer, 1, optionalTime);
 | |
| 
 | |
| 	if (!self->GetVar<bool>(WaveStatusVariable)) {
 | |
| 		PauseChargeCannon(self);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void SGCannon::TimerToggle(Entity* self, bool start) {
 | |
| 	if (start) {
 | |
| 		self->SetNetworkVar<uint32_t>(CountVariable, self->GetVar<uint32_t>(TimeLimitVariable));
 | |
| 		self->SetVar<bool>(GameStartedVariable, true);
 | |
| 	} else {
 | |
| 		self->SetNetworkVar<bool>(StopVariable, true);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void SGCannon::SpawnObject(Entity* self, const SGEnemy& toSpawn, bool spawnNow) {
 | |
| 	auto activeSpawns = self->GetVar<std::vector<SGEnemy>>(ActiveSpawnsVariable);
 | |
| 	activeSpawns.push_back(toSpawn);
 | |
| 	self->SetVar<std::vector<SGEnemy>>(ActiveSpawnsVariable, activeSpawns);
 | |
| 
 | |
| 	self->SetVar(SpawnNumberVariable, activeSpawns.size() - 1);
 | |
| 	const auto timerName = DoSpawnTimer + std::to_string(activeSpawns.size() - 1);
 | |
| 
 | |
| 	if (spawnNow) {
 | |
| 		if (toSpawn.minSpawnTime > 0 && toSpawn.maxSpawnTime > 0) {
 | |
| 			const auto spawnTime = GeneralUtils::GenerateRandomNumber<float_t>(toSpawn.minSpawnTime, toSpawn.maxSpawnTime);
 | |
| 
 | |
| 			ActivityTimerStart(self, timerName, spawnTime, spawnTime);
 | |
| 		} else {
 | |
| 			ActivityTimerStart(self, timerName, 1, 1);
 | |
| 		}
 | |
| 	} else if (toSpawn.respawns) {
 | |
| 		const auto spawnTime = GeneralUtils::GenerateRandomNumber<float_t>(toSpawn.minRespawnTime, toSpawn.maxRespawnTime);
 | |
| 
 | |
| 		ActivityTimerStart(self, timerName, spawnTime, spawnTime);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void SGCannon::RecordPlayerScore(Entity* self) {
 | |
| 	const auto totalScore = self->GetVar<int32_t>(TotalScoreVariable);
 | |
| 	const auto currentWave = self->GetVar<uint32_t>(ThisWaveVariable);
 | |
| 
 | |
| 	if (currentWave > 0) {
 | |
| 		auto totalWaveScore = 0;
 | |
| 		auto playerScores = self->GetVar<std::vector<int32_t>>(PlayerScoresVariable);
 | |
| 
 | |
| 		for (const auto& waveScore : playerScores) {
 | |
| 			totalWaveScore += waveScore;
 | |
| 		}
 | |
| 
 | |
| 		if (currentWave >= playerScores.size()) {
 | |
| 			playerScores.push_back(totalWaveScore);
 | |
| 		} else {
 | |
| 			playerScores[currentWave] = totalWaveScore;
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void SGCannon::PlaySceneAnimation(Entity* self, const std::u16string& animationName, bool onCannon, bool onPlayer, float_t priority) {
 | |
| 	for (auto* cannon : Game::entityManager->GetEntitiesInGroup("cannongroup")) {
 | |
| 		RenderComponent::PlayAnimation(cannon, animationName, priority);
 | |
| 	}
 | |
| 
 | |
| 	if (onCannon) {
 | |
| 		RenderComponent::PlayAnimation(self, animationName, priority);
 | |
| 	}
 | |
| 
 | |
| 	if (onPlayer) {
 | |
| 		auto* player = Game::entityManager->GetEntity(self->GetVar<LWOOBJID>(PlayerIDVariable));
 | |
| 		if (player != nullptr) {
 | |
| 			RenderComponent::PlayAnimation(player, animationName, priority);
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void SGCannon::PauseChargeCannon(Entity* self) {
 | |
| 	const auto time = std::max(static_cast<uint32_t>(std::ceil(ActivityTimerGetCurrentTime(self, SuperChargeTimer))), static_cast<uint32_t>(1));
 | |
| 
 | |
| 	self->SetVar<bool>(SuperChargePausedVariable, true);
 | |
| 	self->SetVar<uint32_t>(CurrentSuperChargedTimeVariable, time);
 | |
| 	self->SetNetworkVar<uint32_t>(ChargeCountingVariable, time);
 | |
| 
 | |
| 	ActivityTimerStop(self, SuperChargeTimer);
 | |
| }
 | |
| 
 | |
| void SGCannon::StopGame(Entity* self, bool cancel) {
 | |
| 	self->SetNetworkVar<bool>(ReSetSuperChargeVariable, true);
 | |
| 	self->SetNetworkVar<bool>(HideSuperChargeVariable, true);
 | |
| 
 | |
| 	auto* player = Game::entityManager->GetEntity(self->GetVar<LWOOBJID>(PlayerIDVariable));
 | |
| 	if (player == nullptr)
 | |
| 		return;
 | |
| 
 | |
| 	ToggleSuperCharge(self, false);
 | |
| 
 | |
| 	// The player won, store all the score and send rewards
 | |
| 	if (!cancel) {
 | |
| 		int32_t percentage = 0.0f;
 | |
| 		auto misses = self->GetVar<uint32_t>(MissesVariable);
 | |
| 		auto fired = self->GetVar<uint32_t>(ShotsFiredVariable);
 | |
| 
 | |
| 		if (fired > 0) {
 | |
| 			percentage = misses / fired;
 | |
| 		}
 | |
| 
 | |
| 		auto* missionComponent = player->GetComponent<MissionComponent>();
 | |
| 
 | |
| 		if (missionComponent != nullptr) {
 | |
| 			missionComponent->Progress(eMissionTaskType::PERFORM_ACTIVITY, self->GetVar<int32_t>(TotalScoreVariable), self->GetObjectID(), "performact_score");
 | |
| 			missionComponent->Progress(eMissionTaskType::PERFORM_ACTIVITY, self->GetVar<uint32_t>(MaxStreakVariable), self->GetObjectID(), "performact_streak");
 | |
| 			missionComponent->Progress(eMissionTaskType::ACTIVITY, m_CannonLot, 0, "", self->GetVar<int32_t>(TotalScoreVariable));
 | |
| 		}
 | |
| 
 | |
| 		Loot::GiveActivityLoot(player, self, GetGameID(self), self->GetVar<int32_t>(TotalScoreVariable));
 | |
| 
 | |
| 		SaveScore(self, player->GetObjectID(),
 | |
| 			static_cast<float>(self->GetVar<int32_t>(TotalScoreVariable)), static_cast<float>(self->GetVar<uint32_t>(MaxStreakVariable)), percentage);
 | |
| 
 | |
| 		StopActivity(self, player->GetObjectID(), self->GetVar<int32_t>(TotalScoreVariable), self->GetVar<uint32_t>(MaxStreakVariable), percentage);
 | |
| 		self->SetNetworkVar<bool>(AudioFinalWaveDoneVariable, true);
 | |
| 
 | |
| 		// Give the player the model rewards they earned
 | |
| 		auto* inventory = player->GetComponent<InventoryComponent>();
 | |
| 		if (inventory != nullptr) {
 | |
| 			for (const auto rewardLot : self->GetVar<std::vector<LOT>>(RewardsVariable)) {
 | |
| 				inventory->AddItem(rewardLot, 1, eLootSourceType::ACTIVITY, eInventoryType::MODELS);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		self->SetNetworkVar<std::u16string>(u"UI_Rewards",
 | |
| 			GeneralUtils::to_u16string(self->GetVar<int32_t>(TotalScoreVariable)) + u"_0_0_0_0_0_0"
 | |
| 		);
 | |
| 	}
 | |
| 
 | |
| 	GameMessages::SendActivityStop(self->GetObjectID(), false, cancel, player->GetSystemAddress());
 | |
| 	self->SetVar<bool>(GameStartedVariable, false);
 | |
| 	ActivityTimerStopAllTimers(self);
 | |
| 
 | |
| 	// Destroy all spawners
 | |
| 	for (auto* entity : Game::entityManager->GetEntitiesInGroup("SGEnemy")) {
 | |
| 		entity->Kill();
 | |
| 	}
 | |
| 
 | |
| 	ResetVars(self);
 | |
| }
 | |
| 
 | |
| void SGCannon::RegisterHit(Entity* self, Entity* target, const std::string& timerName) {
 | |
| 	const auto& spawnInfo = target->GetVar<SGEnemy>(u"SpawnData");
 | |
| 
 | |
| 	if (spawnInfo.respawns) {
 | |
| 		const auto respawnTime = GeneralUtils::GenerateRandomNumber<float_t>(spawnInfo.minRespawnTime, spawnInfo.maxRespawnTime);
 | |
| 
 | |
| 		ActivityTimerStart(self, timerName, respawnTime, respawnTime);
 | |
| 	}
 | |
| 
 | |
| 	int32_t score = spawnInfo.score;
 | |
| 
 | |
| 	if (score > 0) {
 | |
| 		score += score * GetCurrentBonus(self);
 | |
| 
 | |
| 		if (!self->GetVar<bool>(SuperChargeActiveVariable)) {
 | |
| 			self->SetVar<uint32_t>(u"m_curStreak", self->GetVar<uint32_t>(u"m_curStreak") + 1);
 | |
| 		}
 | |
| 	} else {
 | |
| 		if (!self->GetVar<bool>(SuperChargeActiveVariable)) {
 | |
| 			self->SetVar<uint32_t>(u"m_curStreak", 0);
 | |
| 		}
 | |
| 
 | |
| 		self->SetNetworkVar<bool>(u"hitFriend", true);
 | |
| 	}
 | |
| 
 | |
| 	auto lastSuperTotal = self->GetVar<uint32_t>(u"LastSuperTotal");
 | |
| 
 | |
| 	auto scScore = self->GetVar<int32_t>(TotalScoreVariable) - lastSuperTotal;
 | |
| 
 | |
| 	LOG("LastSuperTotal: %i, scScore: %i, constants.chargedPoints: %i",
 | |
| 		lastSuperTotal, scScore, constants.chargedPoints
 | |
| 	);
 | |
| 
 | |
| 	if (!self->GetVar<bool>(SuperChargeActiveVariable) && scScore >= constants.chargedPoints && score >= 0) {
 | |
| 		StartChargedCannon(self);
 | |
| 		self->SetNetworkVar<float>(u"SuperChargeBar", 100.0f);
 | |
| 		self->SetVar<uint32_t>(u"LastSuperTotal", self->GetVar<int32_t>(TotalScoreVariable));
 | |
| 	}
 | |
| 
 | |
| 	UpdateStreak(self);
 | |
| 
 | |
| 	GameMessages::SendNotifyClientShootingGalleryScore(self->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS,
 | |
| 		0.0f,
 | |
| 		score,
 | |
| 		target->GetObjectID(),
 | |
| 		target->GetPosition()
 | |
| 	);
 | |
| 
 | |
| 	auto newScore = self->GetVar<int32_t>(TotalScoreVariable) + score;
 | |
| 
 | |
| 	if (newScore < 0) {
 | |
| 		newScore = 0;
 | |
| 	}
 | |
| 
 | |
| 	self->SetVar<int32_t>(TotalScoreVariable, newScore);
 | |
| 
 | |
| 	self->SetNetworkVar<uint32_t>(u"updateScore", newScore);
 | |
| 
 | |
| 	self->SetNetworkVar<std::u16string>(u"beatHighScore", GeneralUtils::to_u16string(newScore));
 | |
| 
 | |
| 	auto* player = Game::entityManager->GetEntity(self->GetVar<LWOOBJID>(PlayerIDVariable));
 | |
| 	if (player == nullptr) return;
 | |
| 
 | |
| 	auto missionComponent = player->GetComponent<MissionComponent>();
 | |
| 	if (missionComponent == nullptr) return;
 | |
| 
 | |
| 	missionComponent->Progress(eMissionTaskType::SMASH, spawnInfo.lot, self->GetObjectID());
 | |
| }
 | |
| 
 | |
| void SGCannon::UpdateStreak(Entity* self) {
 | |
| 	const auto streakBonus = GetCurrentBonus(self);
 | |
| 
 | |
| 	const auto curStreak = self->GetVar<uint32_t>(u"m_curStreak");
 | |
| 
 | |
| 	const auto marks = curStreak % 3;
 | |
| 
 | |
| 	self->SetNetworkVar<uint32_t>(u"cStreak", curStreak);
 | |
| 
 | |
| 	if (curStreak >= 0 && curStreak < 13) {
 | |
| 		if (marks == 1) {
 | |
| 			self->SetNetworkVar<bool>(u"Mark1", true);
 | |
| 		} else if (marks == 2) {
 | |
| 			self->SetNetworkVar<bool>(u"Mark2", true);
 | |
| 		} else if (marks == 0 && curStreak > 0) {
 | |
| 			self->SetVar<float_t>(u"StreakBonus", streakBonus);
 | |
| 			self->SetNetworkVar<bool>(u"ShowStreak", streakBonus + 1);
 | |
| 			self->SetNetworkVar<bool>(u"Mark3", true);
 | |
| 		} else {
 | |
| 			self->SetVar<float_t>(u"StreakBonus", streakBonus);
 | |
| 			self->SetNetworkVar<bool>(u"UnMarkAll", true);
 | |
| 		}
 | |
| 	}
 | |
| 	auto maxStreak = self->GetVar<uint32_t>(MaxStreakVariable);
 | |
| 	if (maxStreak < curStreak) self->SetVar<uint32_t>(MaxStreakVariable, curStreak);
 | |
| }
 | |
| 
 | |
| float_t SGCannon::GetCurrentBonus(Entity* self) {
 | |
| 	auto streak = self->GetVar<uint32_t>(u"m_curStreak");
 | |
| 
 | |
| 	if (streak > 12) {
 | |
| 		streak = 12;
 | |
| 	}
 | |
| 
 | |
| 	return streak / 3;
 | |
| }
 | |
| 
 | |
| void SGCannon::ToggleSuperCharge(Entity* self, bool enable) {
 | |
| 	if (enable && self->GetVar<bool>(SuperChargeActiveVariable))
 | |
| 		return;
 | |
| 
 | |
| 	auto* player = Game::entityManager->GetEntity(self->GetVar<LWOOBJID>(PlayerIDVariable));
 | |
| 
 | |
| 	if (player == nullptr) {
 | |
| 		LOG("Player not found in toggle super charge");
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	auto* inventoryComponent = player->GetComponent<InventoryComponent>();
 | |
| 
 | |
| 	auto equippedItems = inventoryComponent->GetEquippedItems();
 | |
| 
 | |
| 	LOG("Player has %d equipped items", equippedItems.size());
 | |
| 
 | |
| 	auto skillID = constants.cannonSkill;
 | |
| 	auto cooldown = constants.cannonRefireRate;
 | |
| 
 | |
| 	auto* selfInventoryComponent = self->GetComponent<InventoryComponent>();
 | |
| 
 | |
| 	if (inventoryComponent == nullptr) {
 | |
| 		LOG("Inventory component not found");
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	if (enable) {
 | |
| 		LOG("Player is activating super charge");
 | |
| 		selfInventoryComponent->UpdateSlot("greeble_r", { ObjectIDManager::GenerateRandomObjectID(), 6505, 1, 0 });
 | |
| 		selfInventoryComponent->UpdateSlot("greeble_l", { ObjectIDManager::GenerateRandomObjectID(), 6506, 1, 0 });
 | |
| 
 | |
| 		// TODO: Equip items
 | |
| 		skillID = constants.cannonSuperChargeSkill;
 | |
| 		cooldown = 400;
 | |
| 	} else {
 | |
| 		selfInventoryComponent->UpdateSlot("greeble_r", { ObjectIDManager::GenerateRandomObjectID(), 0, 0, 0 });
 | |
| 		selfInventoryComponent->UpdateSlot("greeble_l", { ObjectIDManager::GenerateRandomObjectID(), 0, 0, 0 });
 | |
| 
 | |
| 		self->SetNetworkVar<float>(u"SuperChargeBar", 0);
 | |
| 
 | |
| 		LOG("Player disables super charge");
 | |
| 
 | |
| 		// TODO: Unequip items
 | |
| 		for (const auto& equipped : equippedItems) {
 | |
| 			if (equipped.first == "special_r" || equipped.first == "special_l") {
 | |
| 				LOG("Trying to unequip a weapon, %i", equipped.second.lot);
 | |
| 
 | |
| 				auto* item = inventoryComponent->FindItemById(equipped.second.id);
 | |
| 
 | |
| 				if (item != nullptr) {
 | |
| 					inventoryComponent->UnEquipItem(item);
 | |
| 				} else {
 | |
| 					LOG("Item not found, %i", equipped.second.lot);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		cooldown = 800;
 | |
| 		self->SetVar<uint32_t>(NumberOfChargesVariable, 0);
 | |
| 	}
 | |
| 
 | |
| 	const auto& constants = GetConstants();
 | |
| 
 | |
| 	auto* shootingGalleryComponent = self->GetComponent<ShootingGalleryComponent>();
 | |
| 
 | |
| 	if (shootingGalleryComponent == nullptr) {
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	DynamicShootingGalleryParams properties = shootingGalleryComponent->GetDynamicParams();
 | |
| 
 | |
| 	properties.cannonFOV = 58.6f;
 | |
| 	properties.cannonVelocity = 129.0;
 | |
| 	properties.cannonRefireRate = cooldown;
 | |
| 	properties.cannonMinDistance = 30;
 | |
| 	properties.cannonTimeout = -1;
 | |
| 
 | |
| 	shootingGalleryComponent->SetDynamicParams(properties);
 | |
| 
 | |
| 	Game::entityManager->SerializeEntity(self);
 | |
| 	Game::entityManager->SerializeEntity(player);
 | |
| 
 | |
| 	self->SetNetworkVar<uint64_t>(CannonBallSkillIDVariable, skillID);
 | |
| 	self->SetVar<bool>(SuperChargeActiveVariable, enable);
 | |
| }
 | |
| 
 | |
| std::vector<std::vector<SGEnemy>> SGCannon::GetWaves() {
 | |
| 	return {
 | |
| 		// Wave 1
 | |
| 		{
 | |
| 			// Ship 1
 | |
| 			{
 | |
| 				std::vector<std::string> { "Wave_1_Ship_1", "Wave_1_Ship_3" },
 | |
| 				6015, 0.0, 2.0, true, 0.0, 2.0,
 | |
| 				2.0, 1500, false, 0.0, 1.0,
 | |
| 				1.0, false, true
 | |
| 			},
 | |
| 
 | |
| 		// Ship 2
 | |
| 		{
 | |
| 			std::vector<std::string> { "Wave_1_Ship_2", "Wave_1_Ship_4" },
 | |
| 			6300, 0.0, 2.0, true, 0.0, 2.0,
 | |
| 			2.0, 500, false, 0.0, 1.0,
 | |
| 			1.0, false, true
 | |
| 		},
 | |
| 
 | |
| 		// Sub 1
 | |
| 		{
 | |
| 			std::vector<std::string> { "Wave_1_Sub_1", "Wave_1_Sub_2" },
 | |
| 			6016, 0.0, 2.0, true, 0.0, 2.0,
 | |
| 			10.0, 1000, false, 0.0, 1.0,
 | |
| 			1.0, true, true
 | |
| 		},
 | |
| 
 | |
| 		// Sub 2
 | |
| 		{
 | |
| 			std::vector<std::string> { "Wave_2_Sub_1", "Wave_2_Sub_2" },
 | |
| 			6016, 0.0, 2.0, true, 0.0, 2.0,
 | |
| 			2.0, 1000, false, 0.0, 1.0,
 | |
| 			1.0, true, true
 | |
| 		},
 | |
| 
 | |
| 		// Friendly
 | |
| 		{
 | |
| 			std::vector<std::string> { "Wave_3_FShip_1", "Wave_3_FShip_2" },
 | |
| 			2168,0.0,5.0,true, 2.0, 5.0,
 | |
| 			1.0, -1000, false, 0.0, 1.0,
 | |
| 			1.0, false,true
 | |
| 		}
 | |
| 	},
 | |
| 
 | |
| 		// Wave 2
 | |
| 		{
 | |
| 			// Ship 1
 | |
| 			{
 | |
| 				std::vector<std::string> { "Wave_1_Ship_1", "Wave_1_Ship_3" },
 | |
| 				6015, 0.0, 2.0, true, 0.0, 2.0,
 | |
| 				2.0, 1500, false, 0.0, 1.0,
 | |
| 				1.0, false, true
 | |
| 			},
 | |
| 
 | |
| 		// Ship 2
 | |
| 		{
 | |
| 			std::vector<std::string> { "Wave_1_Ship_2", "Wave_1_Ship_4" },
 | |
| 			6300, 0.0, 2.0, true, 0.0, 2.0,
 | |
| 			2.0, 500, false, 0.0, 1.0,
 | |
| 			1.0, false, true
 | |
| 		},
 | |
| 
 | |
| 		// Ship 3
 | |
| 		{
 | |
| 			std::vector<std::string> { "Wave_2_Ship_1" },
 | |
| 			6300, 0.0, 2.0, true, 0.0, 2.0,
 | |
| 			2.0, 500, false, 0.0, 1.0,
 | |
| 			1.0, false, true
 | |
| 		},
 | |
| 
 | |
| 		// Ship 4
 | |
| 		{
 | |
| 			std::vector<std::string> { "Wave_2_Ship_2" },
 | |
| 			6015, 0.0, 2.0, true, 0.0, 2.0,
 | |
| 			2.0, 500, false, 0.0, 1.0,
 | |
| 			1.0, false, true
 | |
| 		},
 | |
| 
 | |
| 		// Sub 1
 | |
| 		{
 | |
| 			std::vector<std::string> { "Wave_1_Sub_1", "Wave_1_Sub_2" },
 | |
| 			6016, 0.0, 2.0, true, 0.0, 2.0,
 | |
| 			2.0, 1000, false, 0.0, 1.0,
 | |
| 			1.0, true, true
 | |
| 		},
 | |
| 
 | |
| 		// Sub 2
 | |
| 		{
 | |
| 			std::vector<std::string> { "Wave_2_Sub_1", "Wave_2_Sub_2" },
 | |
| 			6016, 0.0, 2.0, true, 0.0, 2.0,
 | |
| 			2.0, 1000, false, 0.0, 1.0,
 | |
| 			1.0, true, true
 | |
| 		},
 | |
| 
 | |
| 		// Duck
 | |
| 		{
 | |
| 			std::vector<std::string> { "Wave_1_Duck_1", "Wave_1_Duck_2" },
 | |
| 			5946, 5.0, 10.0, true, 5.0, 10.0,
 | |
| 			4.0, 5000, false, 0.0, 1.0,
 | |
| 			1.0, false, true
 | |
| 		},
 | |
| 
 | |
| 		// Friendly
 | |
| 		{
 | |
| 			std::vector<std::string> { "Wave_3_FShip_1", "Wave_3_FShip_2" },
 | |
| 			2168,0.0,5.0,true, 2.0, 5.0,
 | |
| 			1.0, -1000, false, 0.0, 1.0,
 | |
| 			1.0, false,true
 | |
| 		}
 | |
| 	},
 | |
| 
 | |
| 		// Wave 3
 | |
| 		{
 | |
| 			// Ship 1
 | |
| 			{
 | |
| 				std::vector<std::string> { "Wave_1_Ship_1", "Wave_1_Ship_3" },
 | |
| 				6015, 0.0, 2.0, true, 0.0, 2.0,
 | |
| 				2.0, 1500, false, 0.0, 1.0,
 | |
| 				1.0, false, true
 | |
| 			},
 | |
| 
 | |
| 		// Ship 2
 | |
| 		{
 | |
| 			std::vector<std::string> { "Wave_1_Ship_2", "Wave_1_Ship_4" },
 | |
| 			6300, 0.0, 2.0, true, 0.0, 2.0,
 | |
| 			2.0, 500, false, 0.0, 1.0,
 | |
| 			1.0, false, true
 | |
| 		},
 | |
| 
 | |
| 		// Ship 3
 | |
| 		{
 | |
| 			std::vector<std::string> { "Wave_2_Ship_1", "Wave_2_Ship_2" },
 | |
| 			6015, 0.0, 2.0, true, 0.0, 2.0,
 | |
| 			2.0, 500, false, 0.0, 1.0,
 | |
| 			1.0, false, true
 | |
| 		},
 | |
| 
 | |
| 		// Ship 4
 | |
| 		{
 | |
| 			std::vector<std::string> { "Wave_3_Ship_1", "Wave_3_Ship_2" },
 | |
| 			6300, 0.0, 2.0, true, 0.0, 2.0,
 | |
| 			2.0, 1500, false, 0.0, 1.0,
 | |
| 			1.0, false, true
 | |
| 		},
 | |
| 
 | |
| 		// Sub 1
 | |
| 		{
 | |
| 			std::vector<std::string> { "Wave_1_Sub_1", "Wave_1_Sub_2" },
 | |
| 			6016, 0.0, 2.0, true, 0.0, 2.0,
 | |
| 			2.0, 1000, false, 0.0, 1.0,
 | |
| 			1.0, true, true
 | |
| 		},
 | |
| 
 | |
| 		// Sub 2
 | |
| 		{
 | |
| 			std::vector<std::string> { "Wave_2_Sub_1", "Wave_2_Sub_2" },
 | |
| 			6016, 0.0, 2.0, true, 0.0, 2.0,
 | |
| 			2.0, 1000, false, 0.0, 1.0,
 | |
| 			1.0, true, true
 | |
| 		},
 | |
| 
 | |
| 		// Sub 3
 | |
| 		{
 | |
| 			std::vector<std::string> { "Wave_3_Sub_1", "Wave_3_Sub_2" },
 | |
| 			6016, 0.0, 2.0, true, 0.0, 2.0,
 | |
| 			2.0, 1000, false, 0.0, 1.0,
 | |
| 			1.0, true, true
 | |
| 		},
 | |
| 
 | |
| 		// Duck
 | |
| 		{
 | |
| 			std::vector<std::string> { "Wave_1_Duck_1", "Wave_1_Duck_2" },
 | |
| 			5946, 5.0, 10.0, true, 5.0, 10.0,
 | |
| 			4.0, 5000, false, 0.0, 1.0,
 | |
| 			1.0, false, true
 | |
| 		},
 | |
| 
 | |
| 		// Ness
 | |
| 		{
 | |
| 			std::vector<std::string> { "Wave_1_Ness_1", "Wave_1_Ness_2", "Wave_2_Ness_1" },
 | |
| 			2565, 10.0, 15.0, true, 10.0, 15.0,
 | |
| 			2.0, 10000, false, 0.0, 1.0,
 | |
| 			1.0, true, true
 | |
| 		},
 | |
| 
 | |
| 		// Friendly 1
 | |
| 		{
 | |
| 			std::vector<std::string> { "Wave_3_FShip_1", "Wave_3_FShip_2" },
 | |
| 			2168,0.0,5.0,true, 2.0, 5.0,
 | |
| 			1.0, -1000, false, 0.0, 1.0,
 | |
| 			1.0, false,true
 | |
| 		},
 | |
| 
 | |
| 		// Friendly 2
 | |
| 		{
 | |
| 			std::vector<std::string> { "Wave_3_FShip_1", "Wave_3_FShip_2" },
 | |
| 			2168,0.0,5.0,true, 2.0, 5.0,
 | |
| 			1.0, -1000, false, 0.0, 1.0,
 | |
| 			1.0, false,true
 | |
| 		}
 | |
| 	}
 | |
| 	};
 | |
| }
 | |
| 
 | |
| void SGCannon::ResetVars(Entity* self) {
 | |
| 	self->SetVar<uint32_t>(SpawnNumberVariable, 0);
 | |
| 	self->SetVar<uint32_t>(CurrentSpawnNumberVariable, 0);
 | |
| 	self->SetVar<uint32_t>(ThisWaveVariable, 0);
 | |
| 	self->SetVar<uint32_t>(GameScoreVariable, 0);
 | |
| 	self->SetVar<uint32_t>(GameTimeVariable, 0);
 | |
| 	self->SetVar<bool>(GameStartedVariable, false);
 | |
| 	self->SetVar<uint32_t>(ShotsFiredVariable, 0);
 | |
| 	self->SetVar<uint32_t>(MaxStreakVariable, 0);
 | |
| 	self->SetVar<uint32_t>(MissesVariable, 0);
 | |
| 	self->SetVar<uint32_t>(CurrentStreakVariable, 0);
 | |
| 	self->SetVar<uint32_t>(CurrentSuperChargedTimeVariable, 0);
 | |
| 	self->SetVar<std::vector<uint32_t>>(StreakBonusVariable, {});
 | |
| 	self->SetVar<uint32_t>(LastSuperTotalVariable, 0);
 | |
| 	self->SetVar<LOT>(CurrentRewardVariable, LOT_NULL);
 | |
| 	self->SetVar<std::vector<LOT>>(RewardsVariable, {});
 | |
| 	self->SetVar<int32_t>(TotalScoreVariable, 0);
 | |
| 
 | |
| 	self->SetVar<uint32_t>(u"m_curStreak", 0);
 | |
| 	self->SetNetworkVar<float>(u"SuperChargeBar", 0);
 | |
| 	self->SetVar<uint32_t>(u"LastSuperTotal", 0);
 | |
| 	self->SetNetworkVar<float>(u"SuperChargeBar", 0.0f);
 | |
| 	self->SetNetworkVar<bool>(u"ShowStreak", 0);
 | |
| 	self->SetNetworkVar<bool>(u"UnMarkAll", true);
 | |
| 
 | |
| 	const_cast<std::vector<SGEnemy>&>(self->GetVar<std::vector<SGEnemy>>(ActiveSpawnsVariable)).clear();
 | |
| 	self->SetVar<std::vector<SGEnemy>>(ActiveSpawnsVariable, {});
 | |
| 
 | |
| 	const_cast<std::vector<LWOOBJID>&>(self->GetVar<std::vector<LWOOBJID>>(SpawnedObjects)).clear();
 | |
| 	self->SetVar<std::vector<LWOOBJID>>(SpawnedObjects, {});
 | |
| 
 | |
| 	if (self->GetVar<bool>(InitVariable)) {
 | |
| 		ToggleSuperCharge(self, false);
 | |
| 	}
 | |
| 
 | |
| 	self->SetVar<uint32_t>(ImpactSkillVariale, constants.impactSkillID);
 | |
| 	self->SetVar<std::vector<int32_t>>(PlayerScoresVariable, {});
 | |
| 	ActivityTimerStopAllTimers(self);
 | |
| }
 | |
| 
 | |
| SGConstants SGCannon::GetConstants() {
 | |
| 	return {
 | |
| 		Vector3 { -908.542480, 229.773178, -908.542480 },
 | |
| 		Quaternion { 0.91913521289825, 0, 0.39394217729568, 0 },
 | |
| 		1864,
 | |
| 		34,
 | |
| 		1822,
 | |
| 		Vector3 { 6.652, -2, 1.5 },
 | |
| 		157,
 | |
| 		129.0,
 | |
| 		30.0,
 | |
| 		800.0,
 | |
| 		Vector3 { 0, 4.3, 9 },
 | |
| 		6297,
 | |
| 		1822,
 | |
| 		249,
 | |
| 		228,
 | |
| 		-1,
 | |
| 		58.6,
 | |
| 		true,
 | |
| 		2,
 | |
| 		10,
 | |
| 		25000,
 | |
| 		"QBRewardGroup",
 | |
| 		1864,
 | |
| 		50000,
 | |
| 		157,
 | |
| 		100000,
 | |
| 		187,
 | |
| 		200000,
 | |
| 		188,
 | |
| 		400000,
 | |
| 		189,
 | |
| 		800000,
 | |
| 		190,
 | |
| 		4.0,
 | |
| 		7.0
 | |
| 	};
 | |
| }
 |