Merge remote-tracking branch 'origin/master'

This commit is contained in:
Emilie Schott 2025-03-14 23:16:17 +01:00
commit 105caa0b0e
20 changed files with 299 additions and 35 deletions

BIN
Content/Legumix/Drops/BP_AmmoPack.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Content/Legumix/Drops/BP_HealthPack.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Content/Legumix/Drops/BP_ItemDrop.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Content/Legumix/Drops/C_AmmoPackDropRate.uasset (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

View File

@ -0,0 +1,10 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "Ammo/LMAmmoPack.h"
ALMAmmoPack::ALMAmmoPack()
{
PrimaryActorTick.bCanEverTick = false;
}

View File

@ -0,0 +1,61 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "Ammo/LMItemDropComponent.h"
#include "LMHealthPack.h"
#include "Ammo/LMAmmoPack.h"
#include "Kismet/GameplayStatics.h"
#include "Player/LMPlayer.h"
#include "Weapon/LMWeaponManager.h"
#include "Windows/WindowsApplication.h"
ULMItemDropComponent::ULMItemDropComponent()
{
PrimaryComponentTick.bCanEverTick = false;
}
void ULMItemDropComponent::TryDropItems()
{
float Result = FMath::RandRange(0.f, 100.f);
if (DropChanceHealthPack >= Result)
{
SpawnHealth();
}
if (ALMPlayer* Player = Cast<ALMPlayer>(UGameplayStatics::GetPlayerCharacter(GetWorld(), 0)))
{
Result = FMath::RandRange(0.f, 1.f);
const FLMAmmoData Ammo = Player->GetWeaponManager()->GetAmmoData(AmmoType);
const float Percentage = static_cast<float>(Ammo.AmmoCount) / static_cast<float>(Ammo.MaxAmmo);
const float DropChance = DropChanceAtRemainingAmmo->GetFloatValue(Percentage);
FString Random = FString::Printf(TEXT("Drop Chance of %f for ammo (%i / %i) %f with random at %f"), DropChance, Ammo.AmmoCount, Ammo.MaxAmmo, Percentage, Result);
GEngine->AddOnScreenDebugMessage(INDEX_NONE, 5.f, FColor::Green, Random);
if (DropChance >= Result)
{
SpawnAmmo();
}
}
}
void ULMItemDropComponent::SpawnAmmo()
{
FActorSpawnParameters SpawnParams;
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
ALMAmmoPack* Pack = GetWorld()->SpawnActor<ALMAmmoPack>(AmmoPack, GetOwner()->GetActorTransform(), SpawnParams);
}
void ULMItemDropComponent::SpawnHealth()
{
FActorSpawnParameters SpawnParams;
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
ALMHealthPack* Pack = GetWorld()->SpawnActor<ALMHealthPack>(HealthPack, GetOwner()->GetActorTransform(), SpawnParams);
}

View File

@ -0,0 +1,11 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "LMHealthPack.h"
ALMHealthPack::ALMHealthPack()
{
PrimaryActorTick.bCanEverTick = false;
}

View File

@ -0,0 +1,25 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "LMItemDrop.h"
ALMItemDrop::ALMItemDrop()
{
PrimaryActorTick.bCanEverTick = true;
StaticMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>("MeshComponent");
RootComponent = StaticMeshComponent;
}
void ALMItemDrop::BeginPlay()
{
Super::BeginPlay();
GetWorldTimerManager().SetTimer(DespawnHandle, this, &ALMItemDrop::Despawn, TimeBeforeDespawn);
}
void ALMItemDrop::Despawn()
{
GetWorldTimerManager().ClearTimer(DespawnHandle);
Destroy();
}

View File

@ -14,7 +14,7 @@ ALMSpawnPosition::ALMSpawnPosition()
} }
bool ALMSpawnPosition::CanSpawn() const bool ALMSpawnPosition::CanSpawn()
{ {
return !IsPlayerVisible() && !IsOnCooldow; return !IsPlayerVisible() && !IsOnCooldow;
} }
@ -59,7 +59,7 @@ bool ALMSpawnPosition::IsPlayerVisible() const
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 && !IsOnCooldow); // 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"));
@ -69,12 +69,14 @@ bool ALMSpawnPosition::IsPlayerVisible() const
void ALMSpawnPosition::StarCooldown() void ALMSpawnPosition::StarCooldown()
{ {
IsOnCooldow = true; IsOnCooldow = true;
UE_LOG(LogTemp, Warning, TEXT("Spawner Cooldown"));
GetWorld()->GetTimerManager().SetTimer(ProcessCooldown, this, &ALMSpawnPosition::EndCooldown, TimerCooldown, false); GetWorld()->GetTimerManager().SetTimer(ProcessCooldown, this, &ALMSpawnPosition::EndCooldown, TimerCooldown, false);
} }
void ALMSpawnPosition::EndCooldown() void ALMSpawnPosition::EndCooldown()
{ {
IsOnCooldow = false; IsOnCooldow = false;
UE_LOG(LogTemp, Warning, TEXT("Spawner End Cooldown"));
} }

View File

@ -37,7 +37,7 @@ void ALMWaveManager::SpawnEnemy(ALMSpawnPosition* spawnPosition)
if (!tempEnemy) if (!tempEnemy)
{ {
UE_LOG(LogTemp, Error, TEXT("Failed to spawn enemy!")); //UE_LOG(LogTemp, Error, TEXT("Failed to spawn enemy!"));
return; return;
} }
spawnPosition->StarCooldown(); spawnPosition->StarCooldown();
@ -50,7 +50,7 @@ void ALMWaveManager::SpawnEnemy(ALMSpawnPosition* spawnPosition)
//bind la method ennemydead à la death de l'ennemis //bind la method ennemydead à la death de l'ennemis
tempEnemy->OnEnemyDeath.AddDynamic(this, &ALMWaveManager::EnemyDead); tempEnemy->OnEnemyDeath.AddDynamic(this, &ALMWaveManager::EnemyDead);
UE_LOG(LogTemp, Error, TEXT("Succes to spawn and bind on death method")); //UE_LOG(LogTemp, Error, TEXT("Succes to spawn and bind on death method"));
EnemySpawned++; EnemySpawned++;
EnemiesPerType[RandomIndex]--; EnemiesPerType[RandomIndex]--;
@ -65,15 +65,9 @@ void ALMWaveManager::EnemyDead(ALMEnemy* enemyToRemoveFromLife)
bool ALMWaveManager::RemainsEnemyToSpawn() bool ALMWaveManager::RemainsEnemyToSpawn()
{ {
int TotalEnemies = 0; bool StillToSpawn = TotalOfEnemyToStillSpawn() !=0;
bool NoEnemyLeftToSpawn = EnemyAliveList.Num() < MaxEnemyInstantiate;
for (int EnemyCount : EnemiesPerType) return EnemyNumberInWave != EnemySpawned && NoEnemyLeftToSpawn && StillToSpawn;
{
TotalEnemies += EnemyCount;
}
bool stillToSpawn = TotalEnemies !=0;
bool no = EnemyAliveList.Num() < MaxEnemyInstantiate;
return EnemyNumberInWave != EnemySpawned && no && stillToSpawn;
} }
void ALMWaveManager::CheckForSpawnerOK() void ALMWaveManager::CheckForSpawnerOK()
@ -88,6 +82,17 @@ void ALMWaveManager::CheckForSpawnerOK()
} }
} }
int ALMWaveManager::TotalOfEnemyToStillSpawn()
{
int TotalEnemies = 0;
for (int EnemyCount : EnemiesPerType)
{
TotalEnemies += EnemyCount;
}
return TotalEnemies;
}
void ALMWaveManager::GetRandomDataWaveRow() void ALMWaveManager::GetRandomDataWaveRow()
{ {
TArray<FName> RowNames = WaveDatePreset->GetRowNames(); TArray<FName> RowNames = WaveDatePreset->GetRowNames();
@ -97,17 +102,18 @@ void ALMWaveManager::GetRandomDataWaveRow()
CurrentWaveName = WaveName.ToString(); CurrentWaveName = WaveName.ToString();
FLMWaveStructure* InfoWaveRow = WaveDatePreset->FindRow<FLMWaveStructure>(WaveName, ""); FLMWaveStructure* InfoWaveRow = WaveDatePreset->FindRow<FLMWaveStructure>(WaveName, "");
//InternalEnemyRatio = InfoWaveRow->WaveComposition;
EnemyNumberInWave = InfoWaveRow->EnemyCount; EnemyNumberInWave = InfoWaveRow->EnemyCount;
MaxEnemyInstantiate = InfoWaveRow->MaxEnemyCount; MaxEnemyInstantiate = InfoWaveRow->MaxEnemyCount;
AllEnemyType.Empty();
for (const FLMEnemyRatio& EnemyRatio : InfoWaveRow->WaveComposition) for (const FLMEnemyRatio& EnemyRatio : InfoWaveRow->WaveComposition)
{ {
// Ajoute chaque EnemyType à la liste // Ajoute chaque EnemyType à la liste
AllEnemyType.Add(EnemyRatio.EnemyType); AllEnemyType.Add(EnemyRatio.EnemyType);
} }
EnemiesPerType.Empty();
// Récupère les ratios (NbEnemy) et calcule leur somme // Récupère les ratios (NbEnemy) et calcule leur somme
int32 TotalRatio = 0; int32 TotalRatio = 0;
for (const FLMEnemyRatio& EnemyRatio : InfoWaveRow->WaveComposition) for (const FLMEnemyRatio& EnemyRatio : InfoWaveRow->WaveComposition)
@ -140,23 +146,29 @@ void ALMWaveManager::GetRandomDataWaveRow()
void ALMWaveManager::Tick(float DeltaTime) void ALMWaveManager::Tick(float DeltaTime)
{ {
Super::Tick(DeltaTime); Super::Tick(DeltaTime);
if(RemainsEnemyToSpawn()) if(!OnCooldown)
{ {
CheckForSpawnerOK(); if(RemainsEnemyToSpawn())
if(SpawnPositionsOK.Num() > 0)
{ {
//Choose spawnpoint to spawn CheckForSpawnerOK();
int32 RandomIndex = FMath::RandRange(0, SpawnPositionsOK.Num() - 1); if(SpawnPositionsOK.Num() > 0)
SpawnEnemy(SpawnPositionsOK[RandomIndex]); {
EnemySpawned++; //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
UE_LOG(LogTemp, Warning, TEXT("Start a new wave"));
OnCooldown = true;
GetWorld()->GetTimerManager().SetTimer(BreakTimer, this, &ALMWaveManager::StartWave, BreakTime, false);
} }
} }
else
{
//lauch break time
// Lance un timer de 3 secondes avant d'appeler StartWave()
GetWorld()->GetTimerManager().SetTimer(BreakTimer, this, &ALMWaveManager::StartWave, BreakTime, false);
}
} }
@ -164,4 +176,5 @@ void ALMWaveManager::StartWave()
{ {
GetRandomDataWaveRow(); GetRandomDataWaveRow();
EnemySpawned = 0; EnemySpawned = 0;
OnCooldown = false;
} }

View File

@ -143,6 +143,11 @@ int ULMWeaponManager::GetAmmoCount(const EAmmoType AmmoType)
return 0; return 0;
} }
FLMAmmoData& ULMWeaponManager::GetAmmoData(const EAmmoType AmmoType)
{
return AmmoData[AmmoType];
}
void ULMWeaponManager::Fire() void ULMWeaponManager::Fire()
{ {
ALMWeaponBase* Weapon = GetCurrentWeapon(); ALMWeaponBase* Weapon = GetCurrentWeapon();

View File

@ -0,0 +1,24 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "LMAmmoType.h"
#include "LMItemDrop.h"
#include "LMAmmoPack.generated.h"
UCLASS()
class LEGUMEMIX_API ALMAmmoPack : public ALMItemDrop
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Legumix, meta=(AllowPrivateAccess=true, ClampMin=0))
int AmmoCount = 6;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Legumix, meta=(AllowPrivateAccess=true))
EAmmoType AmmoType = EAmmoType::EAT_CornAmmo;
public:
ALMAmmoPack();
};

View File

@ -0,0 +1,42 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "LMAmmoType.h"
#include "Components/ActorComponent.h"
#include "LMItemDropComponent.generated.h"
class ALMAmmoPack;
class ALMHealthPack;
UCLASS(Blueprintable, ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class LEGUMEMIX_API ULMItemDropComponent : public UActorComponent
{
GENERATED_BODY()
private:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Legumix, meta=(AllowPrivateAccess=true))
TObjectPtr<UCurveFloat> DropChanceAtRemainingAmmo;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Legumix, meta=(AllowPrivateAccess=true, ClampMin=0, ClampMax=100, UIMin=0, UIMax=100))
float DropChanceHealthPack = 10.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Legumix, meta=(AllowPrivateAccess=true))
EAmmoType AmmoType = EAmmoType::EAT_CornAmmo;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Legumix, meta=(AllowPrivateAccess=true))
TSubclassOf<ALMAmmoPack> AmmoPack;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Legumix, meta=(AllowPrivateAccess=true))
TSubclassOf<ALMHealthPack> HealthPack;
public:
ULMItemDropComponent();
UFUNCTION(BlueprintCallable)
void TryDropItems();
UFUNCTION(BlueprintCallable)
void SpawnAmmo();
UFUNCTION(BlueprintCallable)
void SpawnHealth();
};

View File

@ -0,0 +1,20 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "LMItemDrop.h"
#include "LMHealthPack.generated.h"
UCLASS()
class LEGUMEMIX_API ALMHealthPack : public ALMItemDrop
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Legumix, meta=(AllowPrivateAccess=true, ClampMin=0))
float HealthGain = 10.f;
public:
ALMHealthPack();
};

View File

@ -0,0 +1,33 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "LMItemDrop.generated.h"
class ULMDropData;
UCLASS()
class LEGUMEMIX_API ALMItemDrop : public AActor
{
GENERATED_BODY()
protected:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Legumix)
float TimeBeforeDespawn = 30.f;
private:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Legumix, meta = (AllowPrivateAccess = true))
TObjectPtr<UStaticMeshComponent> StaticMeshComponent;
FTimerHandle DespawnHandle;
public:
ALMItemDrop();
virtual void BeginPlay() override;
protected:
UFUNCTION(BlueprintCallable)
void Despawn();
};

View File

@ -16,7 +16,7 @@ public:
ALMSpawnPosition(); ALMSpawnPosition();
// Méthode pour vérifier si le spawn est possible // Méthode pour vérifier si le spawn est possible
bool CanSpawn() const; virtual bool CanSpawn();
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"), Category = "Legumix") UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (AllowPrivateAccess = "true"), Category = "Legumix")
float TimerCooldown = 1.5; float TimerCooldown = 1.5;
void StarCooldown(); void StarCooldown();

View File

@ -43,6 +43,9 @@ public:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Legumix") UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Legumix")
TArray<TSubclassOf<ALMEnemy>> AllEnemyType; TArray<TSubclassOf<ALMEnemy>> AllEnemyType;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Legumix")
int EnemySpawned = 0;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Legumix") UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Legumix")
TArray<int> EnemiesPerType; TArray<int> EnemiesPerType;
@ -55,6 +58,7 @@ protected:
virtual void EnemyDead(ALMEnemy* enemyToRemoveFromLife); virtual void EnemyDead(ALMEnemy* enemyToRemoveFromLife);
virtual bool RemainsEnemyToSpawn(); virtual bool RemainsEnemyToSpawn();
virtual void CheckForSpawnerOK(); virtual void CheckForSpawnerOK();
virtual int TotalOfEnemyToStillSpawn();
virtual void GetRandomDataWaveRow(); virtual void GetRandomDataWaveRow();
@ -64,7 +68,7 @@ public:
private: private:
TArray<ALMSpawnPosition*> SpawnPositionsOK; TArray<ALMSpawnPosition*> SpawnPositionsOK;
int EnemySpawned = 0;
FTimerHandle BreakTimer; FTimerHandle BreakTimer;
bool OnCooldown;
}; };

View File

@ -38,6 +38,8 @@ public:
bool AddAmmoType(EAmmoType AmmoType, int AmmoCount); bool AddAmmoType(EAmmoType AmmoType, int AmmoCount);
UFUNCTION(BlueprintCallable, Category=Legumix) UFUNCTION(BlueprintCallable, Category=Legumix)
int GetAmmoCount(EAmmoType AmmoType); int GetAmmoCount(EAmmoType AmmoType);
UFUNCTION(BlueprintCallable, Category=Legumix)
FLMAmmoData& GetAmmoData(EAmmoType AmmoType);
UFUNCTION(BlueprintCallable, Category=Legumix) UFUNCTION(BlueprintCallable, Category=Legumix)
void Fire(); void Fire();