SinglePlayer Infinity Mode

pull/6/head
m4xxx1m 2 years ago
parent 3e2f409f43
commit 3151f79474

@ -8,7 +8,7 @@
AEnemyAIController::AEnemyAIController()
: Super() {
PrimaryActorTick.bCanEverTick = true;
SetActorTickInterval(0.3f);
SetActorTickInterval(2.0f);
}
void AEnemyAIController::Tick(float DeltaSeconds) {
@ -44,6 +44,67 @@ bool AEnemyAIController::IsAITurn() const {
return bIsAITurn;
}
void AEnemyAIController::SpawnIfNeeded() {
RemoveDeadTroopers();
while (PossessedTroopers.Num() < MAX_TROOPERS_COUNT) {
const FVector Location = GetFreeLocation();
const FVector Rotation = {0.0f, 0.0f, 0.0f};
FTransform SpawnLocationAndRotation(Rotation);
SpawnLocationAndRotation.SetLocation(Location);
const TArray<TSubclassOf<ATrooper>> &LoadedTroopersAssets = GetWorld()->
GetGameState<ASinglePlayerGS>()->GetTroopersAssets();
AActor *Spawned = GetWorld()->SpawnActorDeferred<ATrooper>(
LoadedTroopersAssets[FMath::RandRange(
0, LoadedTroopersAssets.Num() - 1)],
SpawnLocationAndRotation);
Cast<ATrooper>(Spawned)->Initialize(
1, Location, TroopersCount++);
Spawned->FinishSpawning(SpawnLocationAndRotation);
Spawned->SetActorLocation(Location);
ATrooper *Trooper = Cast<ATrooper>(Spawned);
GetWorld()->GetGameState<ASinglePlayerGS>()->AddTrooper(Trooper);
PossessedTroopers.Add(Trooper);
Trooper->SetAIPossession(this);
Trooper->HighlightAsEnemy(PLAYER_INDEX);
}
}
// void AEnemyAIController::SetTrooperAssetsAndSpawn(
// TArray<UClass *> TrooperAssets,
// int TrooperCount) {
// LoadedTrooperAssets = MoveTemp(TrooperAssets);
// TroopersCount = TrooperCount;
// SpawnIfNeeded();
// }
void AEnemyAIController::RemoveDeadTroopers() {
for (int index = 0; index < PossessedTroopers.Num(); ++index) {
if (!PossessedTroopers[index] || !PossessedTroopers[index]->
IsValidLowLevel() ||
PossessedTroopers[index]->IsDead()) {
PossessedTroopers.RemoveAtSwap(index);
index--;
}
}
}
FVector AEnemyAIController::GetFreeLocation() const {
for (const auto Location : SpawnPoints) {
bool bIsClose = false;
for (const auto Trooper : PossessedTroopers) {
if ((Location - Trooper->GetLocation()).Size() < 100.0f) {
bIsClose = true;
break;
}
}
if (bIsClose) {
continue;
}
return Location;
}
return {-2000.0f, FMath::RandRange(-2000.0f, 2000.0f), 0.0f};
}
void AEnemyAIController::MakeMove() {
while (TroopersCursor < PossessedTroopers.Num()) {
while (TroopersCursor < PossessedTroopers.Num() && (
@ -111,6 +172,17 @@ bool AEnemyAIController::MoveTo(int TrooperIndex) {
return true;
}
void AEnemyAIController::InitializeSpawnPoints() {
SpawnPoints.Add(FVector{
-2000.0f,
-(MAX_TROOPERS_COUNT - 1) * TROOPERS_DISTANCE.Y / 2,
0.0f
});
for (int index = 1; index < MAX_TROOPERS_COUNT; ++index) {
SpawnPoints.Add(SpawnPoints[SpawnPoints.Num() - 1] + TROOPERS_DISTANCE);
}
}
int AEnemyAIController::GetClosestTrooper() const {
float minDistance = 1000000.0f;
int minIndex = 0;
@ -142,6 +214,8 @@ void AEnemyAIController::InitializeTroopers(
}
}
}
InitializeSpawnPoints();
SpawnIfNeeded();
}
void AEnemyAIController::BeginPlay() {

@ -13,8 +13,6 @@ class TURNBASEDTUTORIAL_API AEnemyAIController : public AActor {
GENERATED_BODY()
public:
static constexpr int AI_INDEX = 1;
AEnemyAIController();
UFUNCTION()
@ -39,7 +37,30 @@ public:
UFUNCTION()
bool IsAITurn() const;
UFUNCTION()
void SpawnIfNeeded();
// UFUNCTION()
// void SetTrooperAssetsAndSpawn(TArray<UClass *> TrooperAssets, int TrooperCount);
private:
static constexpr int AI_INDEX = 1;
static constexpr int PLAYER_INDEX = 0;
static constexpr int MAX_TROOPERS_COUNT = 3;
UPROPERTY()
int TroopersCount = 5;
// UPROPERTY()
// TArray<UClass *> LoadedTrooperAssets;
UFUNCTION()
void RemoveDeadTroopers();
FVector GetFreeLocation() const;
UFUNCTION()
void MakeMove();
@ -53,6 +74,8 @@ private:
bool TryAttack(int TrooperIndex);
bool MoveTo(int TrooperIndex);
void InitializeSpawnPoints();
UPROPERTY()
bool bIsAITurn = false;
@ -65,4 +88,8 @@ private:
UPROPERTY()
TArray<ATrooper *> PlayerTroopers;
TArray<FVector> SpawnPoints;
const FVector TROOPERS_DISTANCE = {0.0f, 1000.0f, 0.0f};
};

@ -6,6 +6,7 @@
#include "MyGameState.h"
#include "MyPlayerController.h"
#include "MyPlayerState.h"
#include "SinglePlayerGS.h"
#include "Trooper.h"
AMyGameMode::AMyGameMode()
@ -26,7 +27,7 @@ auto AMyGameMode::GetMyGameState() const {
}
void AMyGameMode::InitializeBattleField_Implementation() const {
void AMyGameMode::InitializeBattleField_Implementation() {
UE_LOG(LogTemp, Warning, TEXT("InitializeBattleField"));
FVector Location(2000.0f, -1000.0f, 0.0f);
FRotator Rotation(0.0f, 180.0f, 0.0f);
@ -39,7 +40,7 @@ void AMyGameMode::InitializeBattleField_Implementation() const {
),
TEXT("Blueprint'/Game/Troopers/TrooperWizard.TrooperWizard_C'")
};
TArray<UClass *> LoadedBpAssets;
// TArray<UClass *> LoadedBpAssets;
for (int i = 0; i < bpPaths.Num(); ++i) {
TSoftClassPtr<ATrooper> ActorBpClass = TSoftClassPtr<ATrooper>(
FSoftObjectPath(bpPaths[i])
@ -61,25 +62,31 @@ void AMyGameMode::InitializeBattleField_Implementation() const {
GetMyGameState()->AddTrooper(Cast<ATrooper>(Spawned));
Location += {0.f, 500.f, 0.0f};
}
Location = {-2000.0f, -1000.0f, 0.0f};
Rotation = {0.0f, 0.0f, 0.0f};
for (int i = 0; i < 5; ++i) {
FTransform SpawnLocationAndRotation(Rotation);
SpawnLocationAndRotation.SetLocation(Location);
AActor *Spawned = GetWorld()->SpawnActorDeferred<ATrooper>(
LoadedBpAssets[i % 2], SpawnLocationAndRotation);
// AActor *Spawned = GetWorld()->SpawnActorDeferred<ATrooper>(
// ATrooper::StaticClass(), SpawnLocationAndRotation);
Cast<ATrooper>(Spawned)->Initialize(
1, Location, TrooperCount++);
Spawned->FinishSpawning(SpawnLocationAndRotation);
Spawned->SetActorLocation(Location);
GetMyGameState()->AddTrooper(Cast<ATrooper>(Spawned));
Location += {0.f, 500.f, 0.0f};
if (bIsMultiplayer) {
Location = {-2000.0f, -1000.0f, 0.0f};
Rotation = {0.0f, 0.0f, 0.0f};
for (int i = 0; i < 5; ++i) {
FTransform SpawnLocationAndRotation(Rotation);
SpawnLocationAndRotation.SetLocation(Location);
AActor *Spawned = GetWorld()->SpawnActorDeferred<ATrooper>(
LoadedBpAssets[i % 2], SpawnLocationAndRotation);
// AActor *Spawned = GetWorld()->SpawnActorDeferred<ATrooper>(
// ATrooper::StaticClass(), SpawnLocationAndRotation);
Cast<ATrooper>(Spawned)->Initialize(
1, Location, TrooperCount++);
Spawned->FinishSpawning(SpawnLocationAndRotation);
Spawned->SetActorLocation(Location);
GetMyGameState()->AddTrooper(Cast<ATrooper>(Spawned));
Location += {0.f, 500.f, 0.0f};
}
} else {
// Cast<ASinglePlayerGS>(GetMyGameState())->GetEnemyAIController()->
// SetTrooperAssetsAndSpawn(
// LoadedBpAssets,
// TrooperCount);
}
}
AActor *AMyGameMode::ChoosePlayerStart_Implementation(AController *Player) {
UE_LOG(LogTemp, Warning, TEXT("GameMode ChoosePlayerStart %d"),
GetNumPlayers());
@ -151,7 +158,7 @@ void AMyGameMode::StartGame_Implementation() {
InitializeBattleField();
// PlayerNotInTurn()->SetEnemySelection(Troopers);
// PlayerInTurn()->SetEnemySelection(Troopers);
// PlayerInTurn()->StartTurn();
GetMyGameState()->StartGame();
}
@ -206,4 +213,3 @@ void AMyGameMode::StartGame_Implementation() {
// return Cast<AMyPlayerController>(
// UGameplayStatics::GetPlayerController(GetWorld(), PlayerIndex));
// }

@ -28,10 +28,16 @@ public:
// void CycleTurns();
protected:
UPROPERTY()
TArray<UClass *> LoadedBpAssets;
UPROPERTY()
bool bIsMultiplayer = true;
void InitializeSpawnPointsIfNeeded(AController *Player);
UFUNCTION(Server, Reliable)
void InitializeBattleField() const;
void InitializeBattleField();
UPROPERTY()
TMap<uint8, AMyPlayerStart *> SpawnPoints{};

@ -84,6 +84,9 @@ void AMyGameState::DecreaseLivingTroopers(int PlayerIndex) {
if (bGameIsOver)
return;
LivingTroopersCount[PlayerIndex]--;
if (!bIsMultiplayer && PlayerIndex == 1) {
return;
}
if (LivingTroopersCount[PlayerIndex] <= 0) {
UE_LOG(LogTemp, Warning, TEXT("Player %d lose!"), PlayerIndex);
bGameIsOver = true;

@ -48,7 +48,7 @@ public:
protected:
UPROPERTY()
bool IsMultiplayer = true;
bool bIsMultiplayer = true;
UPROPERTY(Replicated)
bool bGameIsOver = false;

@ -5,6 +5,7 @@
ASinglePlayerGM::ASinglePlayerGM() : Super() {
GameStateClass = ASinglePlayerGS::StaticClass();
bIsMultiplayer = false;
}
void ASinglePlayerGM::BeginPlay() {

@ -5,7 +5,7 @@
ASinglePlayerGS::ASinglePlayerGS()
: Super() {
IsMultiplayer = false;
bIsMultiplayer = false;
PrimaryActorTick.bCanEverTick = true;
SetActorTickInterval(0.5f);
}
@ -43,12 +43,22 @@ void ASinglePlayerGS::Tick(float DeltaSeconds) {
Super::Tick(DeltaSeconds);
if (EnemyAiManager->bIsEnded) {
EnemyAiManager->bIsEnded = false;
EnemyAiManager->SpawnIfNeeded();
CycleTurns();
} else if (CurrentPlayerTurn == 1 && !EnemyAiManager->IsAITurn()) {
CycleTurns();
}
}
AEnemyAIController * ASinglePlayerGS::GetEnemyAIController() const {
return EnemyAiManager;
}
const TArray<TSubclassOf<ATrooper>> & ASinglePlayerGS::
GetTroopersAssets() const {
return TrooperBpAssets;
}
void ASinglePlayerGS::GetLifetimeReplicatedProps(
TArray<FLifetimeProperty> &OutLifetimeProps) const {
Super::GetLifetimeReplicatedProps(OutLifetimeProps);

@ -23,7 +23,14 @@ public:
virtual void Tick(float DeltaSeconds) override;
AEnemyAIController *GetEnemyAIController() const;
const TArray<TSubclassOf<ATrooper>> &GetTroopersAssets() const;
protected:
UPROPERTY(Replicated)
AEnemyAIController *EnemyAiManager = nullptr;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TArray<TSubclassOf<ATrooper>> TrooperBpAssets;
};

Loading…
Cancel
Save