197 lines
5.6 KiB
C++
197 lines
5.6 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
#include "LMWaveManager.h"
|
|
|
|
#include "EngineUtils.h"
|
|
#include "Components/CapsuleComponent.h"
|
|
#include "Enemy/LMEnemy.h"
|
|
|
|
// Sets default values
|
|
ALMWaveManager::ALMWaveManager()
|
|
{
|
|
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
|
|
PrimaryActorTick.bCanEverTick = true;
|
|
|
|
}
|
|
|
|
// Called when the game starts or when spawned
|
|
void ALMWaveManager::BeginPlay()
|
|
{
|
|
Super::BeginPlay();
|
|
|
|
SpawnPositionsList.Empty(); // Nettoie la liste avant de remplir
|
|
|
|
for (TActorIterator<ALMSpawnPosition> It(GetWorld()); It; ++It)
|
|
{
|
|
ALMSpawnPosition* SpawnPos = *It;
|
|
if (SpawnPos)
|
|
{
|
|
SpawnPositionsList.Add(SpawnPos);
|
|
}
|
|
}
|
|
|
|
StartWave();
|
|
}
|
|
|
|
void ALMWaveManager::SpawnEnemy(ALMSpawnPosition* spawnPosition)
|
|
{
|
|
int RandomIndex = FMath::RandRange(0, AllEnemyType.Num()-1);
|
|
while(EnemiesPerType[RandomIndex] <= 0 )
|
|
{
|
|
RandomIndex = FMath::RandRange(0, AllEnemyType.Num()-1);
|
|
}
|
|
|
|
//Choisis un ennemis à spawn random
|
|
TSubclassOf<ALMEnemy> enemyToSpawn = AllEnemyType[RandomIndex];
|
|
//Spawn sur une position
|
|
FActorSpawnParameters SpawnParameters;
|
|
SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
|
|
ALMEnemy* tempEnemy = GetWorld()->SpawnActor<ALMEnemy>(enemyToSpawn, spawnPosition->GetActorLocation(), FRotator::ZeroRotator);
|
|
|
|
if (!tempEnemy)
|
|
{
|
|
//UE_LOG(LogTemp, Error, TEXT("Failed to spawn enemy!"));
|
|
return;
|
|
}
|
|
spawnPosition->StarCooldown();
|
|
float tailleCapsule = tempEnemy->GetCapsuleComponent()->GetScaledCapsuleHalfHeight();
|
|
FVector newPosition = tempEnemy->GetActorLocation();
|
|
tempEnemy->SetActorLocation(FVector(newPosition.X,newPosition.Y,newPosition.Z + tailleCapsule));
|
|
|
|
//ajoute l'ennemis à la liste des ennemis vivants
|
|
EnemyAliveList.Add(tempEnemy);
|
|
|
|
//bind la method ennemydead à la death de l'ennemis
|
|
tempEnemy->OnEnemyDeath.AddDynamic(this, &ALMWaveManager::EnemyDead);
|
|
//UE_LOG(LogTemp, Error, TEXT("Succes to spawn and bind on death method"));
|
|
|
|
EnemySpawned++;
|
|
EnemiesPerType[RandomIndex]--;
|
|
}
|
|
|
|
void ALMWaveManager::EnemyDead(ALMEnemy* enemyToRemoveFromLife)
|
|
{
|
|
//remove l'ennemis de la liste des ennemis vivants
|
|
enemyToRemoveFromLife->OnEnemyDeath.RemoveDynamic(this,&ALMWaveManager::EnemyDead);
|
|
EnemyAliveList.Remove(enemyToRemoveFromLife);
|
|
}
|
|
|
|
bool ALMWaveManager::RemainsEnemyToSpawn()
|
|
{
|
|
bool StillToSpawn = TotalOfEnemyToStillSpawn() !=0;
|
|
bool NoEnemyLeftToSpawn = EnemyAliveList.Num() < MaxEnemyInstantiate;
|
|
return EnemyNumberInWave != EnemySpawned && NoEnemyLeftToSpawn && StillToSpawn;
|
|
}
|
|
|
|
void ALMWaveManager::CheckForSpawnerOK()
|
|
{
|
|
SpawnPositionsOK.Empty();
|
|
for (ALMSpawnPosition* spawnPosition : SpawnPositionsList)
|
|
{
|
|
if(spawnPosition->CanSpawn())
|
|
{
|
|
SpawnPositionsOK.Add(spawnPosition);
|
|
}
|
|
}
|
|
}
|
|
|
|
int ALMWaveManager::TotalOfEnemyToStillSpawn()
|
|
{
|
|
int TotalEnemies = 0;
|
|
|
|
for (int EnemyCount : EnemiesPerType)
|
|
{
|
|
TotalEnemies += EnemyCount;
|
|
}
|
|
return TotalEnemies;
|
|
}
|
|
|
|
void ALMWaveManager::GetRandomDataWaveRow()
|
|
{
|
|
TArray<FName> RowNames = WaveDatePreset->GetRowNames();
|
|
int RandomIndex = FMath::RandRange(0, RowNames.Num() - 1);;
|
|
|
|
FName WaveName = RowNames[RandomIndex];
|
|
|
|
CurrentWaveName = WaveName.ToString();
|
|
FLMWaveStructure* InfoWaveRow = WaveDatePreset->FindRow<FLMWaveStructure>(WaveName, "");
|
|
|
|
//Set le nombre d'ennemis dans la wave en fonction de la Row, de la courbe et du nombre de vague passée
|
|
EnemyNumberInWave = FMath::CeilToInt((InfoWaveRow->EnemyCount)* CurveForScalingEnemyInWave->GetFloatValue(WaveNumber));
|
|
|
|
//Set le nombre d'ennemis max spawnés en fonction de la Row, de la courbe, et du nombre de vague passée
|
|
MaxEnemyInstantiate = FMath::CeilToInt((InfoWaveRow->MaxEnemyCount) * CurveForScalingMaxEnemyInstantiate->GetFloatValue(WaveNumber));
|
|
|
|
AllEnemyType.Empty();
|
|
for (const FLMEnemyRatio& EnemyRatio : InfoWaveRow->WaveComposition)
|
|
{
|
|
// Ajoute chaque EnemyType à la liste
|
|
AllEnemyType.Add(EnemyRatio.EnemyType);
|
|
}
|
|
|
|
EnemiesPerType.Empty();
|
|
// Récupère les ratios (NbEnemy) et calcule leur somme
|
|
int32 TotalRatio = 0;
|
|
for (const FLMEnemyRatio& EnemyRatio : InfoWaveRow->WaveComposition)
|
|
{
|
|
TotalRatio += EnemyRatio.NbEnemy;
|
|
}
|
|
|
|
// Sécurité : Si le total est 0, évite la division par zéro
|
|
if (TotalRatio == 0) return;
|
|
|
|
// Répartit les ennemis proportionnellement
|
|
int32 RemainingEnemies = EnemyNumberInWave;
|
|
for (const FLMEnemyRatio& EnemyRatio : InfoWaveRow->WaveComposition)
|
|
{
|
|
// Calcul proportionnel arrondi
|
|
int32 Count = FMath::RoundToInt((float(EnemyRatio.NbEnemy) / TotalRatio) * EnemyNumberInWave);
|
|
|
|
EnemiesPerType.Add(Count);
|
|
RemainingEnemies -= Count;
|
|
}
|
|
|
|
// Ajuste les arrondis pour respecter exactement EnemyNumberInWave
|
|
for (int32 i = 0; i < RemainingEnemies; ++i)
|
|
{
|
|
EnemiesPerType[i % EnemiesPerType.Num()]++;
|
|
}
|
|
}
|
|
|
|
// Called every frame
|
|
void ALMWaveManager::Tick(float DeltaTime)
|
|
{
|
|
Super::Tick(DeltaTime);
|
|
if(!OnCooldown)
|
|
{
|
|
if(RemainsEnemyToSpawn())
|
|
{
|
|
CheckForSpawnerOK();
|
|
if(SpawnPositionsOK.Num() > 0)
|
|
{
|
|
//Choose spawnpoint to spawn
|
|
int32 RandomIndex = FMath::RandRange(0, SpawnPositionsOK.Num() - 1);
|
|
SpawnEnemy(SpawnPositionsOK[RandomIndex]);
|
|
}
|
|
return;
|
|
}
|
|
if(TotalOfEnemyToStillSpawn() == 0 && EnemyAliveList.Num() == 0)
|
|
{
|
|
//lauch break time
|
|
// Lance un breaktime avant de relancer une wave
|
|
OnCooldown = true;
|
|
GetWorld()->GetTimerManager().SetTimer(BreakTimer, this, &ALMWaveManager::StartWave, BreakTime, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void ALMWaveManager::StartWave()
|
|
{
|
|
UE_LOG(LogTemp, Warning, TEXT("Start a new wave"));
|
|
GetRandomDataWaveRow();
|
|
EnemySpawned = 0;
|
|
OnCooldown = false;
|
|
WaveNumber++;
|
|
}
|