This commit is contained in:
Antoine Caru 2025-03-14 13:35:51 +01:00
commit 5d3c61d590
31 changed files with 232 additions and 59 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Content/Legumix/Levels/LVL_GYM_00.umap (Stored with Git LFS)

Binary file not shown.

BIN
Content/Legumix/Spawner/DT_WavePreset.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Content/Legumix/Spawner/LVL_TestSpawn.umap (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,3 @@
#include "Enemy/LMEnemyRatio.h"
#include "Enemy/LMEnemy.h"

View File

@ -0,0 +1 @@
#include "LMWaveStructure.h"

View File

@ -16,7 +16,7 @@ ALMSpawnPosition::ALMSpawnPosition()
bool ALMSpawnPosition::CanSpawn() const bool ALMSpawnPosition::CanSpawn() const
{ {
return !IsPlayerVisible(); return !IsPlayerVisible() && !IsOnCooldow;
} }
// Called when the game starts or when spawned // Called when the game starts or when spawned
@ -30,7 +30,7 @@ void ALMSpawnPosition::BeginPlay()
void ALMSpawnPosition::Tick(float DeltaTime) void ALMSpawnPosition::Tick(float DeltaTime)
{ {
Super::Tick(DeltaTime); Super::Tick(DeltaTime);
UE_LOG(LogTemp, Warning, TEXT("CanSpawn: %s"), CanSpawn() ? TEXT("true") : TEXT("false")); //UE_LOG(LogTemp, Warning, TEXT("CanSpawn: %s"), CanSpawn() ? TEXT("true") : TEXT("false"));
} }
bool ALMSpawnPosition::IsPlayerVisible() const bool ALMSpawnPosition::IsPlayerVisible() const
@ -54,15 +54,27 @@ bool ALMSpawnPosition::IsPlayerVisible() const
); );
// Debug trace // Debug trace
DrawDebugLine(GetWorld(), Start, End, bHit ? FColor::Red : FColor::Green, false, 2.0f); //DrawDebugLine(GetWorld(), Start, End, bHit ? FColor::Red : FColor::Green, false, 2.0f);
if (bHit) if (bHit)
{ {
UE_LOG(LogTemp, Warning, TEXT("LineTrace Hit: %s"), *HitResult.GetActor()->GetName()); //UE_LOG(LogTemp, Warning, TEXT("LineTrace Hit: %s"), *HitResult.GetActor()->GetName());
return HitResult.GetActor() == Player; // Retourne true uniquement si l'acteur touché est le joueur return HitResult.GetActor() == Player; // Retourne true uniquement si l'acteur touché est le joueur
} }
UE_LOG(LogTemp, Warning, TEXT("LineTrace: No Hit")); //UE_LOG(LogTemp, Warning, TEXT("LineTrace: No Hit"));
return false; // Aucun obstacle, le joueur est visible return false; // Aucun obstacle, le joueur est visible
} }
void ALMSpawnPosition::StarCooldown()
{
IsOnCooldow = true;
GetWorld()->GetTimerManager().SetTimer(ProcessCooldown, this, &ALMSpawnPosition::EndCooldown, TimerCooldown, false);
}
void ALMSpawnPosition::EndCooldown()
{
IsOnCooldow = false;
}

View File

@ -1,6 +1,9 @@
// Fill out your copyright notice in the Description page of Project Settings. // Fill out your copyright notice in the Description page of Project Settings.
#include "LMWaveManager.h" #include "LMWaveManager.h"
#include "IPropertyTable.h"
#include "Components/CapsuleComponent.h"
#include "Enemy/LMEnemy.h" #include "Enemy/LMEnemy.h"
// Sets default values // Sets default values
@ -18,16 +21,40 @@ void ALMWaveManager::BeginPlay()
StartWave(); StartWave();
} }
void ALMWaveManager::SpawnEnemy(ALMSpawnPosition* spawnPosition, TSubclassOf<ALMEnemy> enemyToSpawn) void ALMWaveManager::SpawnEnemy(ALMSpawnPosition* spawnPosition)
{ {
//Spawn sur une position int RandomIndex = FMath::RandRange(0, AllEnemyType.Num()-1);
ALMEnemy* tempEnemy = GetWorld()->SpawnActor<ALMEnemy>(enemyToSpawn, spawnPosition->GetActorLocation(), FRotator::ZeroRotator); 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 //ajoute l'ennemis à la liste des ennemis vivants
EnemyAliveList.Add(tempEnemy); EnemyAliveList.Add(tempEnemy);
//bind la method ennemydead à la death de l'ennemis //bind la method ennemydead à la death de l'ennemis
tempEnemy->OnEnemyDeath.AddUniqueDynamic(this, &ALMWaveManager::EnemyDead); 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) void ALMWaveManager::EnemyDead(ALMEnemy* enemyToRemoveFromLife)
@ -39,8 +66,15 @@ void ALMWaveManager::EnemyDead(ALMEnemy* enemyToRemoveFromLife)
bool ALMWaveManager::RemainsEnemyToSpawn() bool ALMWaveManager::RemainsEnemyToSpawn()
{ {
int TotalEnemies = 0;
for (int EnemyCount : EnemiesPerType)
{
TotalEnemies += EnemyCount;
}
bool stillToSpawn = TotalEnemies !=0;
bool no = EnemyAliveList.Num() < MaxEnemyInstantiate; bool no = EnemyAliveList.Num() < MaxEnemyInstantiate;
return EnemyNumberInWave != EnemySpawned && no; return EnemyNumberInWave != EnemySpawned && no && stillToSpawn;
} }
void ALMWaveManager::CheckForSpawnerOK() void ALMWaveManager::CheckForSpawnerOK()
@ -55,6 +89,54 @@ void ALMWaveManager::CheckForSpawnerOK()
} }
} }
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, "");
//InternalEnemyRatio = InfoWaveRow->WaveComposition;
EnemyNumberInWave = InfoWaveRow->EnemyCount;
MaxEnemyInstantiate = InfoWaveRow->MaxEnemyCount;
for (const FLMEnemyRatio& EnemyRatio : InfoWaveRow->WaveComposition)
{
// Ajoute chaque EnemyType à la liste
AllEnemyType.Add(EnemyRatio.EnemyType);
}
// 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 // Called every frame
void ALMWaveManager::Tick(float DeltaTime) void ALMWaveManager::Tick(float DeltaTime)
{ {
@ -66,7 +148,7 @@ void ALMWaveManager::Tick(float DeltaTime)
{ {
//Choose spawnpoint to spawn //Choose spawnpoint to spawn
int32 RandomIndex = FMath::RandRange(0, SpawnPositionsOK.Num() - 1); int32 RandomIndex = FMath::RandRange(0, SpawnPositionsOK.Num() - 1);
SpawnEnemy(SpawnPositionsOK[RandomIndex],TypeOfEnemy); SpawnEnemy(SpawnPositionsOK[RandomIndex]);
EnemySpawned++; EnemySpawned++;
} }
} }
@ -81,5 +163,6 @@ void ALMWaveManager::Tick(float DeltaTime)
void ALMWaveManager::StartWave() void ALMWaveManager::StartWave()
{ {
GetRandomDataWaveRow();
EnemySpawned = 0;
} }

View File

@ -131,6 +131,11 @@ void ALMPlayer::SetWeaponManager(ULMWeaponManager* Manager)
void ALMPlayer::PlayAnimation(UAnimMontage* Animation) void ALMPlayer::PlayAnimation(UAnimMontage* Animation)
{ {
UAnimInstance* AnimInstance = GetArms()->GetAnimInstance();
if (AnimInstance && Animation)
{
AnimInstance->Montage_Play(Animation);
}
} }
void ALMPlayer::FireBullets(const FLMBulletInfo Settings) void ALMPlayer::FireBullets(const FLMBulletInfo Settings)

View File

@ -29,10 +29,10 @@ void ALMRevolver::PrimaryFire()
} }
return; return;
} }
PlayEvent(FireEvent); PlayEvent(FireEvent);
PlayAnimation(PrimaryFireAnimation); PlayAnimation(PrimaryFireAnimation);
Player->PlayAnimation(PrimaryFireArmsAnimation);
const FVector Origin = Player->GetWeaponFiringOrigin(); const FVector Origin = Player->GetWeaponFiringOrigin();
const FVector Direction = Player->GetAimVector(); const FVector Direction = Player->GetAimVector();

View File

@ -77,7 +77,7 @@ void ALMWeaponBase::PlayEvent(UFMODEvent* Event) const
void ALMWeaponBase::PlayAnimation(UAnimMontage* Animation) void ALMWeaponBase::PlayAnimation(UAnimMontage* Animation)
{ {
UAnimInstance* AnimInstance = WeaponMesh->GetAnimInstance(); UAnimInstance* AnimInstance = WeaponMesh->GetAnimInstance();
if (Animation && AnimInstance) if (Animation && AnimInstance)
{ {
AnimInstance->Montage_Play(Animation); AnimInstance->Montage_Play(Animation);

View File

@ -0,0 +1,17 @@
#pragma once
#include "LMEnemyRatio.generated.h"
class ALMEnemy;
USTRUCT(BlueprintType)
struct FLMEnemyRatio : public FTableRowBase
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Legumix")
TSubclassOf<ALMEnemy> EnemyType;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Legumix", meta = (ClampMin = 0))
int NbEnemy;
};

View File

@ -17,15 +17,22 @@ public:
// Méthode pour vérifier si le spawn est possible // Méthode pour vérifier si le spawn est possible
bool CanSpawn() const; bool CanSpawn() const;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"), Category = "Legumix")
float TimerCooldown = 1.5;
void StarCooldown();
protected: protected:
// Called when the game starts or when spawned // Called when the game starts or when spawned
virtual void BeginPlay() override; virtual void BeginPlay() override;
virtual void EndCooldown();
public: public:
// Called every frame // Called every frame
virtual void Tick(float DeltaTime) override; virtual void Tick(float DeltaTime) override;
private: private:
bool IsPlayerVisible() const; bool IsPlayerVisible() const;
FTimerHandle ProcessCooldown;
bool IsOnCooldow;
}; };

View File

@ -5,6 +5,7 @@
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "GameFramework/Actor.h" #include "GameFramework/Actor.h"
#include "LMSpawnPosition.h" #include "LMSpawnPosition.h"
#include "LMWaveStructure.h"
#include "LMWaveManager.generated.h" #include "LMWaveManager.generated.h"
class ALMEnemy; class ALMEnemy;
@ -17,34 +18,45 @@ class LEGUMEMIX_API ALMWaveManager : public AActor
public: public:
// Sets default values for this actor's properties // Sets default values for this actor's properties
ALMWaveManager(); ALMWaveManager();
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"), Category = "Legumix")
TArray<ALMEnemy*> EnemyAliveList; // Liste des ennemis
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"), Category = "Legumix")
FString CurrentWaveName; // Name of the current wave
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"), Category = "Legumix") UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"), Category = "Legumix")
TArray<ALMSpawnPosition*> SpawnPositionsList; // Liste des ennemis TArray<ALMSpawnPosition*> SpawnPositionsList; // Liste des ennemis
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"), Category = "Legumix")
TArray<ALMEnemy*> EnemyAliveList; // Liste des ennemis
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"), Category = "Legumix") UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"), Category = "Legumix")
int EnemyNumberInWave; // Nombre d'ennemis dans la wave int EnemyNumberInWave; // Nombre d'ennemis dans la wave
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"), Category = "Legumix") UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"), Category = "Legumix")
int MaxEnemyInstantiate; // Nombre d'ennemis max spawnés int MaxEnemyInstantiate; // Nombre d'ennemis max spawnés
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"), Category = "Legumix")
TSubclassOf<ALMEnemy> TypeOfEnemy; // Type d'ennemis to spawn
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"), Category = "Legumix") UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"), Category = "Legumix")
float BreakTime; // Nombre d'ennemis dans la wave float BreakTime; // Nombre d'ennemis dans la wave
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"), Category = "Legumix")
UDataTable* WaveDatePreset;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Legumix")
TArray<TSubclassOf<ALMEnemy>> AllEnemyType;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Legumix")
TArray<int> EnemiesPerType;
protected: protected:
// Called when the game starts or when spawned // Called when the game starts or when spawned
virtual void BeginPlay() override; virtual void BeginPlay() override;
virtual void StartWave(); virtual void StartWave();
virtual void SpawnEnemy(ALMSpawnPosition* spawnPosition, TSubclassOf<ALMEnemy> enemyToSpawn); virtual void SpawnEnemy(ALMSpawnPosition* spawnPosition);
UFUNCTION() UFUNCTION()
virtual void EnemyDead(ALMEnemy* enemyToRemoveFromLife); virtual void EnemyDead(ALMEnemy* enemyToRemoveFromLife);
virtual bool RemainsEnemyToSpawn(); virtual bool RemainsEnemyToSpawn();
virtual void CheckForSpawnerOK(); virtual void CheckForSpawnerOK();
virtual void GetRandomDataWaveRow();
public: public:
// Called every frame // Called every frame
@ -52,7 +64,7 @@ public:
private: private:
TArray<ALMSpawnPosition*> SpawnPositionsOK; TArray<ALMSpawnPosition*> SpawnPositionsOK;
int EnemySpawned; int EnemySpawned = 0;
FTimerHandle BreakTimer; FTimerHandle BreakTimer;
}; };

View File

@ -0,0 +1,17 @@
#pragma once
#include "Enemy/LMEnemyRatio.h"
#include "LMWaveStructure.generated.h"
USTRUCT(BlueprintType)
struct FLMWaveStructure : public FTableRowBase
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Legumix")
TArray<FLMEnemyRatio> WaveComposition;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Legumix", meta = (ClampMin = 0))
int EnemyCount;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Legumix", meta = (ClampMin = 0))
int MaxEnemyCount;
};

View File

@ -85,11 +85,15 @@ protected: /* Weapon Data */
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Legumix|Sounds") UPROPERTY(EditAnywhere, BlueprintReadWrite,Category="Legumix|Sounds")
TObjectPtr<UFMODEvent> EquipSound; TObjectPtr<UFMODEvent> EquipSound;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Legumix|Animations", meta=(AllowPrivateAccess=true)) UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Legumix|Animations|Fire", meta=(AllowPrivateAccess=true))
TObjectPtr<UAnimMontage> PrimaryFireAnimation; TObjectPtr<UAnimMontage> PrimaryFireAnimation;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Legumix|Animations|Fire", meta=(AllowPrivateAccess=true))
TObjectPtr<UAnimMontage> PrimaryFireArmsAnimation;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Legumix|Animations", meta=(AllowPrivateAccess=true)) UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Legumix|Animations|Reload", meta=(AllowPrivateAccess=true))
TObjectPtr<UAnimMontage> ReloadAnimation; TObjectPtr<UAnimMontage> ReloadAnimation;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Legumix|Animations|Reload", meta=(AllowPrivateAccess=true))
TObjectPtr<UAnimMontage> ReloadArmsAnimation;
/** The number of seconds before being able to fire again. */ /** The number of seconds before being able to fire again. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Legumix|Weapon", meta=(AllowPrivateAccess=true)) UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Legumix|Weapon", meta=(AllowPrivateAccess=true))