Announcement

Collapse
No announcement yet.

UI WidgetBP to access GameMode/State Variable made in C++

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    UI WidgetBP to access GameMode/State Variable made in C++

    Hey!

    Working on a small wave based game where the player has to survive for as long as they can.

    Basic idea is that the player spawns into the game and in 5 seconds the first enemy spawns, once that enemy is i killed after another 5 seconds more enemies spawn etc etc.

    Right now ive got two variables in my C++ Header class (which are private - in bold):

    Code:
      
    #pragma once
    
    #include "CoreMinimal.h"
    #include "GameFramework/GameModeBase.h"
    #include "TPSGameMode.generated.h"
    
    enum class EWaveState : uint8;
    
    DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnActorKilled, AActor*, VictimActor, AActor*, KillerActor, AController*, KillerController);
    
    UCLASS()
    class TP_PROJECT_API ATPSGameMode : public AGameModeBase
    {
        GENERATED_BODY()
    
    protected:
    
        FTimerHandle TH_BotSpawn;
    
        FTimerHandle TH_NextWaveStart;
    
        // Number of bots to spawn in current wave
        int32 BotsToSpawn;
    
    protected:
    
        // Allow BP to spawn a single bot
        UFUNCTION(BlueprintImplementableEvent, Category = "GameMode")
        void SpawnNewBot();
    
        void SpawnBotTimerElapsed();
    
        // Start spawning bots for wave
        void StartWave();
    
        // Stop spawning bots and end wave
        void EndWave();
    
        // set timer for next wave
        void PrepareNextWave();
    
        void CheckWaveState();
    
        void CheckPlayerState();
    
        void GameOver();
    
        void SetWaveState(EWaveState NewState);
    
    private:
    
    UPROPERTY(EditAnywhere, Category = "GameMode")
        float TimeBetweenWaves;
    
    UPROPERTY(EditAnywhere, Category = "GameMode")
        int32 WaveCount;
    
    public:
    
        ATPSGameMode();
    
        virtual void StartPlay() override;
    
        virtual void Tick(float DeltaSeconds);
    
        UPROPERTY(BlueprintAssignable, Category = "GameMode")
        FOnActorKilled OnActorKilled;
    };
    Im trying access them in my Widget BP that will have a count down timer and the current wave number.

    Below is my CPP file for my GameMode:

    Code:
    #include "TPSGameMode.h"
    #include "TimerManager.h"
    #include "Engine/World.h"
    #include "TPSHealthComponent.h"
    #include "TPSPlayerState.h"
    #include "TPSGameState.h"
    
    
    ATPSGameMode::ATPSGameMode()
    {
        TimeBetweenWaves = 5.0f;
        GameStateClass = ATPSGameState::StaticClass();
        PlayerStateClass = ATPSGameMode::StaticClass();
    
        PrimaryActorTick.bCanEverTick = true;
        PrimaryActorTick.TickInterval = 1.0f;
    }
    
    void ATPSGameMode::StartWave()
    {
        WaveCount++;
    
        BotsToSpawn = 1 * WaveCount;
    
        GetWorldTimerManager().SetTimer(TH_BotSpawn, this, &ATPSGameMode::SpawnBotTimerElapsed, 1.0f, true, 0.0f);
    
        SetWaveState(EWaveState::WaveInProgress);
    }
    
    void ATPSGameMode::EndWave()
    {
        GetWorldTimerManager().ClearTimer(TH_BotSpawn);
        SetWaveState(EWaveState::WaitingToComplete);
    }
    
    void ATPSGameMode::PrepareNextWave()
    {
        GetWorldTimerManager().SetTimer(TH_NextWaveStart, this, &ATPSGameMode::StartWave, TimeBetweenWaves, false);
        SetWaveState(EWaveState::WaitingToStart);
    
    }
    
    void ATPSGameMode::CheckWaveState()
    {
        bool bIsPrepForWave = GetWorldTimerManager().IsTimerActive(TH_NextWaveStart);
    
        if (BotsToSpawn > 0 || bIsPrepForWave)
        {
            return;
        }
    
        bool bIsAnyBotAlive = false;
    
        for (FConstPawnIterator ItPawns = GetWorld()->GetPawnIterator(); ItPawns; ++ItPawns)
        {
            APawn* TestPawn = ItPawns->Get();
            if (TestPawn == nullptr || TestPawn->IsPlayerControlled())
            {
                continue;
            }
    
            UTPSHealthComponent* HealthComponent = Cast<UTPSHealthComponent>(TestPawn->GetComponentByClass(UTPSHealthComponent::StaticClass()));
            if (HealthComponent && HealthComponent->GetHealth() > 0.0f)
            {
                bIsAnyBotAlive = true;
                break;
            }
        }
    
        if (!bIsAnyBotAlive)
        {
            SetWaveState(EWaveState::WaveComplete);
            PrepareNextWave();
        }
    }
    
    void ATPSGameMode::CheckPlayerState()
    {
        for (FConstPlayerControllerIterator ItPlayer = GetWorld()->GetPlayerControllerIterator(); ItPlayer; ++ItPlayer)
        {
            APlayerController* PC = ItPlayer->Get();
            if (PC && PC->GetPawn())
            {
                APawn* MyPawn = PC->GetPawn();
                UTPSHealthComponent* HealthComponent = Cast<UTPSHealthComponent>(MyPawn->GetComponentByClass(UTPSHealthComponent::StaticClass()));
                if (ensure(HealthComponent) && HealthComponent->GetHealth() > 0.0f)
                {
                    // Player is alive
                    return;
                }
            }
        }
    
        // Player is dead
        GameOver();
    }
    
    void ATPSGameMode::GameOver()
    {
        EndWave();
        SetWaveState(EWaveState::GameOver);
    }
    
    void ATPSGameMode::SetWaveState(EWaveState NewState)
    {
        ATPSGameState* GS = GetGameState<ATPSGameState>();
        if (ensure(GS))
        {
            GS->SetWaveState(NewState);
        }
    }
    
    void ATPSGameMode::StartPlay()
    {
        Super::StartPlay();
        PrepareNextWave();
    }
    
    void ATPSGameMode::Tick(float DeltaSeconds)
    {
        Super::Tick(DeltaSeconds);
    
        CheckWaveState();
        CheckPlayerState();
    }
    
    void ATPSGameMode::SpawnBotTimerElapsed()
    {
        SpawnNewBot();
    
        BotsToSpawn--;
    
        if (BotsToSpawn <=0)
        {
            EndWave();
        }
    }
    I also have a game state class that has an Enum and tracks the state of each wave:

    Code:
    // GameState.CPP
    
    void ATPSGameState::OnWaveState(EWaveState OldState)
    {
        WaveStateChanged(WaveState, OldState);
    }
    
    void ATPSGameState::SetWaveState(EWaveState NewState)
    {
        EWaveState OldState = WaveState;
        WaveState = NewState;
        OnWaveState(OldState);
    }
    and

    Code:
    GameState.H
    
    UENUM(BlueprintType)
    enum class EWaveState : uint8 {
        WaitingToStart,
    
        WaveInProgress,
    
        // No longer spawning new bots
        WaitingToComplete,
    
        WaveComplete,
    
        GameOver,
    };
    
    UCLASS()
    class TP_PROJECT_API ATPSGameState : public AGameStateBase
    {
        GENERATED_BODY()
    
    protected:
    
        UFUNCTION()
        void OnWaveState(EWaveState OldState);
    
        UFUNCTION(BlueprintImplementableEvent, Category = "GameState")
        void WaveStateChanged(EWaveState NewState, EWaveState OldState);
    
        UPROPERTY(BlueprintReadOnly, Category = "GameState")
        EWaveState WaveState;
    
    public:
    
        void SetWaveState(EWaveState NewState);
    };
    Im stuck on how to access the WaveCount and the TimeBetweenWaves in my UI BP
    Last edited by KingSpud; 04-23-2019, 11:46 AM.
    Looking for Level Design work https://tsayed.artstation.com/
Working...
X