diff --git a/Content/BP_MyGameMode.uasset b/Content/BP_MyGameMode.uasset index d432830..f1ac113 100644 Binary files a/Content/BP_MyGameMode.uasset and b/Content/BP_MyGameMode.uasset differ diff --git a/Content/BP_MyGameState.uasset b/Content/BP_MyGameState.uasset new file mode 100644 index 0000000..459f885 Binary files /dev/null and b/Content/BP_MyGameState.uasset differ diff --git a/Content/BP_MyPlayerState.uasset b/Content/BP_MyPlayerState.uasset new file mode 100644 index 0000000..6e5c02f Binary files /dev/null and b/Content/BP_MyPlayerState.uasset differ diff --git a/Content/BattleField/BP_BattleUI.uasset b/Content/BattleField/BP_BattleUI.uasset index c601229..1925d52 100644 Binary files a/Content/BattleField/BP_BattleUI.uasset and b/Content/BattleField/BP_BattleUI.uasset differ diff --git a/Content/BattleField/BattleFieldMap.umap b/Content/BattleField/BattleFieldMap.umap index b06ca50..6c84f51 100644 Binary files a/Content/BattleField/BattleFieldMap.umap and b/Content/BattleField/BattleFieldMap.umap differ diff --git a/Source/TurnBasedTutorial/ManageSquadPlayerController.cpp b/Source/TurnBasedTutorial/ManageSquadPlayerController.cpp index 5c324df..72d4c77 100644 --- a/Source/TurnBasedTutorial/ManageSquadPlayerController.cpp +++ b/Source/TurnBasedTutorial/ManageSquadPlayerController.cpp @@ -25,8 +25,8 @@ void AManageSquadPlayerController::OnLeftMouseClick() { UE_LOG(LogTemp, Warning, TEXT("Got hit result")); // auto const NewlySelectedLocation = HitResult.Location; - AManageSquadTrooper *NewlySelectedTrooper = dynamic_cast - ( + AManageSquadTrooper *NewlySelectedTrooper = Cast + ( HitResult.GetActor()); if (NewlySelectedTrooper == nullptr || !NewlySelectedTrooper-> @@ -46,11 +46,11 @@ void AManageSquadPlayerController::OnLeftMouseClick() { if (SelectedTrooper) { UE_LOG(LogTemp, Warning, TEXT("Trooper replacement")); SelectedTrooper->ChangeSkeletalMesh(NewlySelectedTrooper); - dynamic_cast( + Cast( GetWorld()->GetGameState())->ChangeSquad( SelectedTrooper->GetIndex(), NewlySelectedTrooper->GetIndex() - ); + ); } break; case ETrooperType::TROOPER_IN_SQUAD: diff --git a/Source/TurnBasedTutorial/MyGameMode.cpp b/Source/TurnBasedTutorial/MyGameMode.cpp index dfb44fd..dd2aed5 100644 --- a/Source/TurnBasedTutorial/MyGameMode.cpp +++ b/Source/TurnBasedTutorial/MyGameMode.cpp @@ -4,12 +4,15 @@ #include "Kismet/GameplayStatics.h" #include "MyPawn.h" #include "MyGameState.h" +#include "MyPlayerController.h" +#include "MyPlayerState.h" AMyGameMode::AMyGameMode() : Super() { UE_LOG(LogTemp, Warning, TEXT("GameMode Constructor")); GameStateClass = AMyGameState::StaticClass(); PlayerControllerClass = AMyPlayerController::StaticClass(); + PlayerStateClass = AMyPlayerState::StaticClass(); DefaultPawnClass = AMyPawn::StaticClass(); } @@ -17,6 +20,10 @@ void AMyGameMode::BeginPlay() { Super::BeginPlay(); } +auto AMyGameMode::GetMyGameState() const { + return GetGameState(); +} + void AMyGameMode::InitializeBattleField() const { UE_LOG(LogTemp, Warning, TEXT("InitializeBattleField")); @@ -46,11 +53,11 @@ void AMyGameMode::InitializeBattleField() const { LoadedBpAssets[i % 2], SpawnLocationAndRotation); // AActor *Spawned = GetWorld()->SpawnActorDeferred( // ATrooper::StaticClass(), SpawnLocationAndRotation); - dynamic_cast(Spawned)->Initialize( + Cast(Spawned)->Initialize( 0, Location, TrooperCount++); Spawned->FinishSpawning(SpawnLocationAndRotation); Spawned->SetActorLocation(Location); - Troopers.Add(dynamic_cast(Spawned)); + GetMyGameState()->AddTrooper(Cast(Spawned)); Location += {0.f, 500.f, 0.0f}; } Location = {-2000.0f, -1000.0f, 0.0f}; @@ -62,11 +69,11 @@ void AMyGameMode::InitializeBattleField() const { LoadedBpAssets[i % 2], SpawnLocationAndRotation); // AActor *Spawned = GetWorld()->SpawnActorDeferred( // ATrooper::StaticClass(), SpawnLocationAndRotation); - dynamic_cast(Spawned)->Initialize( + Cast(Spawned)->Initialize( 1, Location, TrooperCount++); Spawned->FinishSpawning(SpawnLocationAndRotation); Spawned->SetActorLocation(Location); - Troopers.Add(dynamic_cast(Spawned)); + GetMyGameState()->AddTrooper(Cast(Spawned)); Location += {0.f, 500.f, 0.0f}; } } @@ -120,7 +127,7 @@ void AMyGameMode::PostLogin(APlayerController *NewPlayer) { const auto CurrentNumberOfPlayers = GetNumPlayers(); // 0-indexation - dynamic_cast(NewPlayer)->SetPlayerIndex( + Cast(NewPlayer)->SetPlayerIndex( CurrentNumberOfPlayers - 1); UE_LOG(LogTemp, Warning, TEXT("%d"), CurrentNumberOfPlayers); if (CurrentNumberOfPlayers == 2) { @@ -141,48 +148,49 @@ void AMyGameMode::StartGame() { InitializeBattleField(); // PlayerNotInTurn()->SetEnemySelection(Troopers); // PlayerInTurn()->SetEnemySelection(Troopers); - // PlayerControllers[0]->SetEnemySelection(Troopers); - // PlayerControllers[1]->SetEnemySelection(Troopers); - PlayerInTurn()->StartTurn(); -} - - -AMyPlayerController *AMyGameMode::PlayerInTurn() const { - return GetMyPlayerController(CurrentPlayerTurn); -} - -AMyPlayerController *AMyGameMode::PlayerNotInTurn() const { - // uint8 PlayerControllerIndexNotInTurn; - // if (CurrentPlayerTurn == 0) { - // PlayerControllerIndexNotInTurn = 1; - // } else { - // PlayerControllerIndexNotInTurn = 0; - // } - // return GetMyPlayerController(PlayerControllerIndexNotInTurn); - return GetMyPlayerController(!CurrentPlayerTurn); + + // PlayerInTurn()->StartTurn(); + GetMyGameState()->StartGame(); } -void AMyGameMode::CycleTurns() { - if (!this) - return; - // PlayerInTurn()->EndTurn(); - for (const auto Trooper : Troopers) { - if (Trooper != nullptr) { - Trooper->ResetActionPoints(); - } - } - CurrentPlayerTurn = !CurrentPlayerTurn; - // if (CurrentPlayerTurn == 0) { - // CurrentPlayerTurn = 1; - // } else { - // CurrentPlayerTurn = 0; - // } - PlayerInTurn()->StartTurn(); -} +// AMyPlayerController *AMyGameMode::PlayerInTurn() const { +// return GetMyPlayerController(CurrentPlayerTurn); +// } + +// AMyPlayerController *AMyGameMode::PlayerNotInTurn() const { +// // uint8 PlayerControllerIndexNotInTurn; +// // if (CurrentPlayerTurn == 0) { +// // PlayerControllerIndexNotInTurn = 1; +// // } else { +// // PlayerControllerIndexNotInTurn = 0; +// // } +// // return GetMyPlayerController(PlayerControllerIndexNotInTurn); +// return GetMyPlayerController(!CurrentPlayerTurn); +// } + +// void AMyGameMode::CycleTurns() { +// if (!this) +// return; +// // PlayerInTurn()->EndTurn(); +// for (const auto Trooper : Troopers) { +// if (Trooper != nullptr) { +// Trooper->ResetActionPoints(); +// } +// } +// CurrentPlayerTurn = !CurrentPlayerTurn; +// // if (CurrentPlayerTurn == 0) { +// // CurrentPlayerTurn = 1; +// // } else { +// // CurrentPlayerTurn = 0; +// // } +// PlayerInTurn()->StartTurn(); +// } + + +// AMyPlayerController *AMyGameMode::GetMyPlayerController( +// uint8 const PlayerIndex) const { +// return Cast( +// UGameplayStatics::GetPlayerController(GetWorld(), PlayerIndex)); +// } -AMyPlayerController *AMyGameMode::GetMyPlayerController( - uint8 const PlayerIndex) const { - return dynamic_cast( - UGameplayStatics::GetPlayerController(GetWorld(), PlayerIndex)); -} diff --git a/Source/TurnBasedTutorial/MyGameMode.h b/Source/TurnBasedTutorial/MyGameMode.h index e7f19ab..3d7e2d3 100644 --- a/Source/TurnBasedTutorial/MyGameMode.h +++ b/Source/TurnBasedTutorial/MyGameMode.h @@ -4,7 +4,7 @@ #include "CoreMinimal.h" #include "EngineUtils.h" -#include "MyPlayerController.h" +// #include "MyPlayerController.h" #include "MyPlayerStart.h" #include "GameFramework/GameMode.h" #include "MyGameMode.generated.h" @@ -23,9 +23,9 @@ public: virtual void BeginPlay() override; - - UFUNCTION(BlueprintCallable) - void CycleTurns(); + // + // UFUNCTION(BlueprintCallable) + // void CycleTurns(); private: void InitializeSpawnPointsIfNeeded(AController *Player); @@ -34,22 +34,24 @@ private: UPROPERTY() TMap SpawnPoints{}; - - UPROPERTY() - mutable TArray Troopers; + + // UPROPERTY() + // mutable TArray Troopers; UFUNCTION(BlueprintCallable) void StartGame(); - UFUNCTION(BlueprintPure) - AMyPlayerController *PlayerInTurn() const; + // UFUNCTION(BlueprintPure) + // AMyPlayerController *PlayerInTurn() const; + // + // UFUNCTION(BlueprintPure) + // AMyPlayerController *PlayerNotInTurn() const; - UFUNCTION(BlueprintPure) - AMyPlayerController *PlayerNotInTurn() const; + // UPROPERTY() + // uint8 CurrentPlayerTurn{0}; - UPROPERTY() - uint8 CurrentPlayerTurn{0}; + // UFUNCTION() + // AMyPlayerController *GetMyPlayerController(uint8 const PlayerIndex) const; - UFUNCTION() - AMyPlayerController *GetMyPlayerController(uint8 const PlayerIndex) const; + auto GetMyGameState() const; }; diff --git a/Source/TurnBasedTutorial/MyGameState.cpp b/Source/TurnBasedTutorial/MyGameState.cpp index b1538d3..1b84b68 100644 --- a/Source/TurnBasedTutorial/MyGameState.cpp +++ b/Source/TurnBasedTutorial/MyGameState.cpp @@ -2,86 +2,65 @@ #include "MyGameState.h" -// #include "MyPlayerController.h" -// #include "Trooper.h" -// #include "Kismet/GameplayStatics.h" +#include "MyPlayerState.h" +#include "Trooper.h" +#include "Net/UnrealNetwork.h" -// void AMyGameState::InitializeBattleField() const { -// UE_LOG(LogTemp, Warning, TEXT("InitializeBattleField")); -// FVector Location(2000.0f, -1000.0f, 0.0f); -// FRotator Rotation(0.0f, 180.0f, 0.0f); -// -// uint8 TrooperCount = 0; -// -// TArray bpPaths{ -// TEXT( -// "Blueprint'/Game/Troopers/TrooperSkeletonMelee.TrooperSkeletonMelee_C'" -// ), -// TEXT("Blueprint'/Game/Troopers/TrooperWizard.TrooperWizard_C'") -// }; -// TArray LoadedBpAssets; -// for (int i = 0; i < bpPaths.Num(); ++i) { -// TSoftClassPtr ActorBpClass = TSoftClassPtr( -// FSoftObjectPath(bpPaths[i]) -// ); -// LoadedBpAssets.Push(ActorBpClass.LoadSynchronous()); -// } -// -// for (int i = 0; i < 5; ++i) { -// FTransform SpawnLocationAndRotation(Rotation); -// SpawnLocationAndRotation.SetLocation(Location); -// AActor *Spawned = GetWorld()->SpawnActorDeferred( -// LoadedBpAssets[i % 2], SpawnLocationAndRotation); -// // AActor *Spawned = GetWorld()->SpawnActorDeferred( -// // ATrooper::StaticClass(), SpawnLocationAndRotation); -// dynamic_cast(Spawned)->Initialize( -// 0, Location, TrooperCount++); -// Spawned->FinishSpawning(SpawnLocationAndRotation); -// Spawned->SetActorLocation(Location); -// 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( -// LoadedBpAssets[i % 2], SpawnLocationAndRotation); -// // AActor *Spawned = GetWorld()->SpawnActorDeferred( -// // ATrooper::StaticClass(), SpawnLocationAndRotation); -// dynamic_cast(Spawned)->Initialize( -// 1, Location, TrooperCount++); -// Spawned->FinishSpawning(SpawnLocationAndRotation); -// Spawned->SetActorLocation(Location); -// Location += {0.f, 500.f, 0.0f}; -// } -// } +auto AMyGameState::GetMyPlayerState(uint8 PlayerIndex) const { + return Cast(PlayerArray[PlayerIndex]); +} -// AMyPlayerController *AMyGameState::GetMyPlayerController( -// uint8 const PlayerIndex) const { -// return dynamic_cast( -// UGameplayStatics::GetPlayerController(GetWorld(), PlayerIndex)); -// } -// -// void AMyGameState::StartGame() { -// // InitializeBattleField(); -// PlayerInTurn()->StartTurn(); -// } -// -// void AMyGameState::CycleTurns() { -// PlayerInTurn()->EndTurn(); -// if (CurrentPlayerTurn == 0) { -// CurrentPlayerTurn = 1; -// } else { -// CurrentPlayerTurn = 0; +void AMyGameState::BeginPlay() { + Super::BeginPlay(); +} + +void AMyGameState::AddTrooper(ATrooper *Trooper) { + Troopers.Add(Trooper); +} + +void AMyGameState::StartGame() const { + // PlayerNotInTurn()->SetEnemySelection(Troopers); + // PlayerInTurn()->SetEnemySelection(Troopers); + PlayerInTurn()->StartTurn(); +} + +void AMyGameState::CycleTurns_Implementation(uint8 CurrentPlayerIndex) { + if (CurrentPlayerTurn == CurrentPlayerIndex) { + PlayerInTurn()->EndTurn(); + for (const auto Trooper : Troopers) { + if (Trooper != nullptr) { + Trooper->ResetActionPoints(); + } + } + CurrentPlayerTurn = !CurrentPlayerTurn; + PlayerInTurn()->StartTurn(); + } +} + +// void AMyGameState::CycleTurns(uint8 CurrentPlayerIndex) { +// if (CurrentPlayerTurn == CurrentPlayerIndex) { +// PlayerInTurn()->EndTurn(); +// for (const auto Trooper : Troopers) { +// if (Trooper != nullptr) { +// Trooper->ResetActionPoints(); +// } +// } +// CurrentPlayerTurn = !CurrentPlayerTurn; +// PlayerInTurn()->StartTurn(); // } -// PlayerInTurn()->StartTurn(); -// } -// -// AMyPlayerController *AMyGameState::PlayerInTurn() const { -// return GetMyPlayerController(CurrentPlayerTurn); -// } -// -// AMyPlayerController *AMyGameState::PlayerNotInTurn() const { -// return GetMyPlayerController(CurrentPlayerTurn == 0 ? 1 : 0); // } + +AMyPlayerState *AMyGameState::PlayerInTurn() const { + return GetMyPlayerState(CurrentPlayerTurn); +} + +AMyPlayerState *AMyGameState::PlayerNotInTurn() const { + return GetMyPlayerState(!CurrentPlayerTurn); +} + +void AMyGameState::GetLifetimeReplicatedProps( + TArray &OutLifetimeProps) const { + Super::GetLifetimeReplicatedProps(OutLifetimeProps); + DOREPLIFETIME(AMyGameState, Troopers); + DOREPLIFETIME(AMyGameState, CurrentPlayerTurn); +} diff --git a/Source/TurnBasedTutorial/MyGameState.h b/Source/TurnBasedTutorial/MyGameState.h index d9220da..dafd47a 100644 --- a/Source/TurnBasedTutorial/MyGameState.h +++ b/Source/TurnBasedTutorial/MyGameState.h @@ -3,6 +3,7 @@ #pragma once #include "CoreMinimal.h" +#include "MyPlayerState.h" #include "GameFramework/GameState.h" #include "MyGameState.generated.h" @@ -12,26 +13,32 @@ UCLASS() class TURNBASEDTUTORIAL_API AMyGameState : public AGameState { GENERATED_BODY() -// public: -// UFUNCTION(BlueprintCallable) -// void CycleTurns(); -// -// UFUNCTION(BlueprintCallable) -// void StartGame(); -// -// private: -// // void InitializeBattleField() const; -// -// UFUNCTION() -// AMyPlayerController *GetMyPlayerController(uint8 const PlayerIndex) const; -// -// -// UFUNCTION(BlueprintPure) -// AMyPlayerController *PlayerInTurn() const; -// -// UFUNCTION(BlueprintPure) -// AMyPlayerController *PlayerNotInTurn() const; -// -// UPROPERTY() -// uint8 CurrentPlayerTurn{0}; + +public: + virtual void BeginPlay() override; + + UFUNCTION() + void AddTrooper(ATrooper *Trooper); + + UFUNCTION() + void StartGame() const; + + UFUNCTION(BlueprintCallable, Server, Reliable) + void CycleTurns(uint8 CurrentPlayerIndex); + + UFUNCTION(BlueprintPure) + AMyPlayerState *PlayerInTurn() const; + + UFUNCTION(BlueprintPure) + AMyPlayerState *PlayerNotInTurn() const; + + auto GetMyPlayerState(uint8 PlayerIndex) const; + +private: + UPROPERTY(Replicated) + TArray Troopers; + + UPROPERTY(Replicated) + uint8 CurrentPlayerTurn{0}; + }; diff --git a/Source/TurnBasedTutorial/MyPlayerController.cpp b/Source/TurnBasedTutorial/MyPlayerController.cpp index c1ef308..e89f66b 100644 --- a/Source/TurnBasedTutorial/MyPlayerController.cpp +++ b/Source/TurnBasedTutorial/MyPlayerController.cpp @@ -3,10 +3,12 @@ #include "MyPlayerController.h" #include "Kismet/GameplayStatics.h" #include "MyGameMode.h" +#include "MyGameState.h" +#include "MyPlayerState.h" #include "Net/UnrealNetwork.h" AMyPlayerController::AMyPlayerController() - : Super(), bIsMyTurn(false), SelectedTrooper(nullptr) { + : Super()/*, bIsMyTurn(false), SelectedTrooper(nullptr)*/ { UE_LOG(LogTemp, Warning, TEXT("Player controller created")); SetShowMouseCursor(true); } @@ -17,58 +19,72 @@ void AMyPlayerController::SetupInputComponent() { &AMyPlayerController::OnLeftMouseClick); } -void AMyPlayerController::SetMyTurn(bool bMyTurn) { - bIsMyTurn = bMyTurn; - if (bIsMyTurn) { - GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Green, - FString::Printf( - TEXT("CURRENT TURN: %d"), - PlayerIndex)); - } - // OnMyTurnChanged.ExecuteIfBound(bIsMyTurn); +// void AMyPlayerController::SetMyTurn(bool bMyTurn) { +// bIsMyTurn = bMyTurn; +// if (bIsMyTurn) { +// GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Green, +// FString::Printf( +// TEXT("CURRENT TURN: %d"), +// PlayerIndex)); +// } +// OnMyTurnChanged.ExecuteIfBound(bIsMyTurn); +// } + +// void AMyPlayerController::StartTurn_Implementation() { +// SetMyTurn(true); +// UE_LOG(LogTemp, Warning, TEXT("Your turn, %d"), PlayerIndex); +// } + +auto AMyPlayerController::GetMyGameState() const { + return Cast(UGameplayStatics::GetGameState(GetWorld())); } -void AMyPlayerController::StartTurn_Implementation() { - SetMyTurn(true); - UE_LOG(LogTemp, Warning, TEXT("Your turn, %d"), PlayerIndex); +auto AMyPlayerController::GetMyPlayerState() const { + return GetPlayerState(); } + auto AMyPlayerController::GetMyGameMode() const { - return dynamic_cast( + return Cast( UGameplayStatics::GetGameMode(GetWorld())); } -void AMyPlayerController::EndTurn_Implementation() { - if (bIsMyTurn) { - UE_LOG(LogTemp, Warning, TEXT("End Turn from player %d"), PlayerIndex); - SetMyTurn(false); - if (SelectedTrooper) { - SelectedTrooper->SetSelection(false); - SelectedTrooper = nullptr; - } - UE_LOG(LogTemp, Warning, TEXT("Not your turn, %d"), PlayerIndex); - AMyGameMode *gameMode = GetMyGameMode(); - gameMode->CycleTurns(); - } -} + +// void AMyPlayerController::EndTurn_Implementation() { +// GetMyPlayerState()->EndTurn(); +// } + + +// if (bIsMyTurn) { +// UE_LOG(LogTemp, Warning, TEXT("End Turn from player %d"), PlayerIndex); +// SetMyTurn(false); +// if (SelectedTrooper) { +// SelectedTrooper->SetSelection(false); +// SelectedTrooper = nullptr; +// } +// UE_LOG(LogTemp, Warning, TEXT("Not your turn, %d"), PlayerIndex); +// AMyGameMode *gameMode = GetMyGameMode(); +// gameMode->CycleTurns(); +// } +// } // AMyGameState *AMyPlayerController::GetMyGameState() const { // return dynamic_cast( // GetWorld()->GetGameState()); // } -void AMyPlayerController::MoveTrooper_Implementation( - ATrooper *Trooper, - FVector Location) { - if (Trooper->CheckMoveCorrectness(Location)) { - Trooper->MoveTrooper(Location); - // GetMyGameMode()->CycleTurns(); - } else { - GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Red, - FString::Printf( - TEXT("Out of move radius!"))); - } -} +// void AMyPlayerController::MoveTrooper_Implementation( +// ATrooper *Trooper, +// FVector Location) { +// if (Trooper->CheckMoveCorrectness(Location)) { +// Trooper->MoveTrooper(Location); +// // GetMyGameMode()->CycleTurns(); +// } else { +// GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Red, +// FString::Printf( +// TEXT("Out of move radius!"))); +// } +// } // void AMyPlayerController::AttackTrooper_Implementation( // ATrooper *Attacker, @@ -90,32 +106,38 @@ void AMyPlayerController::MoveTrooper_Implementation( // } -void AMyPlayerController::Attack_Implementation(ATrooper *Attacker, - FVector Location, - int ActionIndex) { - if (Attacker && CurrentAction >= 1 && CurrentAction <= 2 && - Attacker->CheckAttackCorrectness(Location, CurrentAction)) { - Attacker->Attack(CurrentAction); - } else { - UE_LOG(LogTemp, Warning, - TEXT("Out of radius or not enough Action Points")); - } -} +// void AMyPlayerController::Attack_Implementation(ATrooper *Attacker, +// FVector Location, +// int ActionIndex) { +// if (Attacker && CurrentAction >= 1 && CurrentAction <= 2 && +// Attacker->CheckAttackCorrectness(Location, CurrentAction)) { +// Attacker->Attack(CurrentAction); +// } else { +// UE_LOG(LogTemp, Warning, +// TEXT("Out of radius or not enough Action Points")); +// } +// } void AMyPlayerController::SetPlayerIndex(uint8 NewPlayerIndex) { PlayerIndex = NewPlayerIndex; + + GetMyPlayerState()->SetPlayerIndex(NewPlayerIndex); + // GetMyPlayerState()->PlayerIndex = NewPlayerIndex; } float AMyPlayerController::SetCurrentActionAndReturnRadius(int action) { - CurrentAction = action; - UE_LOG(LogTemp, Warning, TEXT("SetCurrentAction: %d on Player Controller " - "with index %d"), CurrentAction, PlayerIndex); - if (SelectedTrooper) { - return SelectedTrooper->GetActionRadius(CurrentAction); - } - return 0.0f; + return GetMyPlayerState()->SetCurrentActionAndReturnRadius(action); + + // CurrentAction = action; + // UE_LOG(LogTemp, Warning, TEXT("SetCurrentAction: %d on Player Controller " + // "with index %d"), CurrentAction, PlayerIndex); + // if (SelectedTrooper) { + // return SelectedTrooper->GetActionRadius(CurrentAction); + // } + // return 0.0f; } + void AMyPlayerController::SetEnemySelection_Implementation( const TArray &Troopers) const { for (const auto Trooper : Troopers) { @@ -149,18 +171,19 @@ void AMyPlayerController::SetEnemySelection_Implementation( void AMyPlayerController::GetLifetimeReplicatedProps( TArray &OutLifetimeProps) const { + Super::GetLifetimeReplicatedProps(OutLifetimeProps); DOREPLIFETIME(AMyPlayerController, PlayerIndex); - DOREPLIFETIME(AMyPlayerController, CurrentAction); - DOREPLIFETIME(AMyPlayerController, bIsMyTurn); - DOREPLIFETIME(AMyPlayerController, SelectedTrooper); + // DOREPLIFETIME(AMyPlayerController, CurrentAction); + // DOREPLIFETIME(AMyPlayerController, bIsMyTurn); + // DOREPLIFETIME(AMyPlayerController, SelectedTrooper); } void AMyPlayerController::OnLeftMouseClick() { - if (!bIsMyTurn) { + if (!GetMyPlayerState()->IsMyTurn()) { return; } UE_LOG(LogTemp, Warning, TEXT("Mouse clicked")); - UE_LOG(LogTemp, Warning, TEXT("Current action: %d"), CurrentAction); + // UE_LOG(LogTemp, Warning, TEXT("Current action: %d"), CurrentAction); FHitResult HitResult; bool const IsHitResult = GetHitResultUnderCursorForObjects( TArray>{ObjectTypeQuery1}, false, @@ -171,56 +194,57 @@ void AMyPlayerController::OnLeftMouseClick() { if (!IsHitResult) return; UE_LOG(LogTemp, Warning, TEXT("Got hit result")); - auto const NewlySelectedLocation = HitResult.Location; - ATrooper *NewlySelectedTrooper = dynamic_cast( - HitResult.GetActor()); - - // skip re-selection - if (SelectedTrooper == NewlySelectedTrooper) { - UE_LOG(LogTemp, Warning, TEXT("Skip reselection")); - return; - } - - if (NewlySelectedTrooper == nullptr || !NewlySelectedTrooper-> - IsValidLowLevel() || NewlySelectedTrooper->GetPlayerIndex() != - PlayerIndex) { - // we selected something that is not a trooper (or trooper in shitty state...) - // probably we should move to it if we can... - - // UE_LOG(LogTemp, Warning, TEXT("Not a trooper")); - - // if initial trooper is valid... - if (SelectedTrooper != nullptr && SelectedTrooper->IsValidLowLevel()) { - switch (CurrentAction) { - case 0: - UE_LOG(LogTemp, Warning, TEXT("Do move")); - // move this mf - MoveTrooper(SelectedTrooper, NewlySelectedLocation); - // and reset the selection.... - SelectedTrooper->SetSelection(false); - SelectedTrooper = nullptr; - break; - default: - // ATTACK! ATTACK! - UE_LOG(LogTemp, Warning, TEXT("Do attack")); - Attack(SelectedTrooper, NewlySelectedLocation, - CurrentAction); - SelectedTrooper->SetSelection(false); - SelectedTrooper = nullptr; - break; - } - } - } else if (NewlySelectedTrooper != nullptr && NewlySelectedTrooper-> - IsValidLowLevel() && NewlySelectedTrooper->GetPlayerIndex() == - PlayerIndex) { - UE_LOG(LogTemp, Warning, TEXT("Do reselect")); - // our move, selection - if (SelectedTrooper) { - SelectedTrooper->SetSelection(false); - } - SelectedTrooper = NewlySelectedTrooper; - SelectedTrooper->SetSelection(true); - } + GetMyPlayerState()->OnPlayerAction(HitResult); + // auto const NewlySelectedLocation = HitResult.Location; + // ATrooper *NewlySelectedTrooper = Cast( + // HitResult.GetActor()); + // + // // skip re-selection + // if (SelectedTrooper == NewlySelectedTrooper) { + // UE_LOG(LogTemp, Warning, TEXT("Skip reselection")); + // return; + // } + // + // if (NewlySelectedTrooper == nullptr || !NewlySelectedTrooper-> + // IsValidLowLevel() || NewlySelectedTrooper->GetPlayerIndex() != + // PlayerIndex) { + // // we selected something that is not a trooper (or trooper in shitty state...) + // // probably we should move to it if we can... + // + // // UE_LOG(LogTemp, Warning, TEXT("Not a trooper")); + // + // // if initial trooper is valid... + // if (SelectedTrooper != nullptr && SelectedTrooper->IsValidLowLevel()) { + // switch (CurrentAction) { + // case 0: + // UE_LOG(LogTemp, Warning, TEXT("Do move")); + // // move this mf + // MoveTrooper(SelectedTrooper, NewlySelectedLocation); + // // and reset the selection.... + // SelectedTrooper->SetSelection(false); + // SelectedTrooper = nullptr; + // break; + // default: + // // ATTACK! ATTACK! + // UE_LOG(LogTemp, Warning, TEXT("Do attack")); + // Attack(SelectedTrooper, NewlySelectedLocation, + // CurrentAction); + // SelectedTrooper->SetSelection(false); + // SelectedTrooper = nullptr; + // break; + // } + // } + // } else if (NewlySelectedTrooper != nullptr && NewlySelectedTrooper-> + // IsValidLowLevel() && NewlySelectedTrooper->GetPlayerIndex() == + // PlayerIndex) { + // UE_LOG(LogTemp, Warning, TEXT("Do reselect")); + // // our move, selection + // if (SelectedTrooper) { + // SelectedTrooper->SetSelection(false); + // } + // SelectedTrooper = NewlySelectedTrooper; + // SelectedTrooper->SetSelection(true); + // } // // if (NewlySelectedTrooper == nullptr || !NewlySelectedTrooper-> diff --git a/Source/TurnBasedTutorial/MyPlayerController.h b/Source/TurnBasedTutorial/MyPlayerController.h index 6b56c55..f04607c 100644 --- a/Source/TurnBasedTutorial/MyPlayerController.h +++ b/Source/TurnBasedTutorial/MyPlayerController.h @@ -2,7 +2,6 @@ #pragma once #include "CoreMinimal.h" -// #include "MyGameState.h" #include "Trooper.h" #include "GameFramework/PlayerController.h" #include "MyPlayerController.generated.h" @@ -15,25 +14,25 @@ class TURNBASEDTUTORIAL_API AMyPlayerController : public APlayerController { public: // FOnMyTurnChangedDelegate OnMyTurnChanged; - + virtual void SetupInputComponent() override; AMyPlayerController(); - UFUNCTION(Client, Reliable) - void StartTurn(); - - UFUNCTION(Client, Reliable, BlueprintCallable) - void EndTurn(); - - UFUNCTION(Server, Reliable) - void MoveTrooper(ATrooper *Trooper, FVector Location); + // UFUNCTION(Client, Reliable) + // void StartTurn(); + // UFUNCTION(Client, Reliable, BlueprintCallable) + // void EndTurn(); + // // UFUNCTION(Server, Reliable) - // void AttackTrooper(ATrooper *Attacker, ATrooper *Victim); - - UFUNCTION(Server, Reliable) - void Attack(ATrooper *Attacker, FVector Location, int ActionIndex); + // void MoveTrooper(ATrooper *Trooper, FVector Location); + // + // // // UFUNCTION(Server, Reliable) + // // // void AttackTrooper(ATrooper *Attacker, ATrooper *Victim); + // + // UFUNCTION(Server, Reliable) + // void Attack(ATrooper *Attacker, FVector Location, int ActionIndex); UFUNCTION() void SetPlayerIndex(uint8 NewPlayerIndex); @@ -45,23 +44,26 @@ public: void SetEnemySelection(const TArray &Troopers) const; private: - UPROPERTY(Replicated) - bool bIsMyTurn; - - UPROPERTY(Replicated) - int CurrentAction = 0; - + // UPROPERTY(Replicated) + // bool bIsMyTurn; + // + // UPROPERTY(Replicated) + // int CurrentAction = 0; + // UPROPERTY(Replicated) uint8 PlayerIndex; + // + // UPROPERTY(Replicated) + // ATrooper *SelectedTrooper; - UPROPERTY(Replicated) - ATrooper *SelectedTrooper; - + UFUNCTION() void OnLeftMouseClick(); - void SetMyTurn(bool bMyTurn); + // void SetMyTurn(bool bMyTurn); auto GetMyGameMode() const; - // AMyGameState *GetMyGameState() const; + auto GetMyGameState() const; + + auto GetMyPlayerState() const; }; diff --git a/Source/TurnBasedTutorial/MyPlayerStart.cpp b/Source/TurnBasedTutorial/MyPlayerStart.cpp index e963a5a..fd44adc 100644 --- a/Source/TurnBasedTutorial/MyPlayerStart.cpp +++ b/Source/TurnBasedTutorial/MyPlayerStart.cpp @@ -3,7 +3,6 @@ #include "MyPlayerStart.h" -uint8 AMyPlayerStart::GetPlayerIndex() const -{ - return PlayerIndex; +uint8 AMyPlayerStart::GetPlayerIndex() const { + return PlayerIndex; } diff --git a/Source/TurnBasedTutorial/MyPlayerStart.h b/Source/TurnBasedTutorial/MyPlayerStart.h index 297594a..c28a149 100644 --- a/Source/TurnBasedTutorial/MyPlayerStart.h +++ b/Source/TurnBasedTutorial/MyPlayerStart.h @@ -10,15 +10,14 @@ * */ UCLASS() -class TURNBASEDTUTORIAL_API AMyPlayerStart : public APlayerStart -{ - GENERATED_BODY() -public: +class TURNBASEDTUTORIAL_API AMyPlayerStart : public APlayerStart { + GENERATED_BODY() +public: uint8 GetPlayerIndex() const; protected: private: UPROPERTY(EditAnywhere, Category="Spawn Info") - uint8 PlayerIndex=0; + uint8 PlayerIndex = 0; }; diff --git a/Source/TurnBasedTutorial/MyPlayerState.cpp b/Source/TurnBasedTutorial/MyPlayerState.cpp new file mode 100644 index 0000000..cb29a24 --- /dev/null +++ b/Source/TurnBasedTutorial/MyPlayerState.cpp @@ -0,0 +1,149 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "MyPlayerState.h" + +#include "MyGameState.h" +#include "Trooper.h" +#include "Net/UnrealNetwork.h" + +AMyPlayerState::AMyPlayerState() + : Super(), bIsMyTurn(false), SelectedTrooper(nullptr) { +} + +void AMyPlayerState::BeginPlay() { + Super::BeginPlay(); +} + +void AMyPlayerState::SetPlayerIndex(uint8 NewPlayerIndex) { + PlayerIndex = NewPlayerIndex; +} + +bool AMyPlayerState::IsMyTurn() const { + return bIsMyTurn; +} + +void AMyPlayerState::SetMyTurn(bool bMyTurn) { + bIsMyTurn = bMyTurn; + if (bIsMyTurn) { + GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Green, + FString::Printf( + TEXT("CURRENT TURN: %d"), + PlayerIndex)); + } +} + +void AMyPlayerState::StartTurn_Implementation() { + SetMyTurn(true); + UE_LOG(LogTemp, Warning, TEXT("Your turn, %d"), PlayerIndex); +} + +void AMyPlayerState::EndTurn_Implementation() { + if (bIsMyTurn) { + UE_LOG(LogTemp, Warning, TEXT("End Turn from player %d"), PlayerIndex); + SetMyTurn(false); + if (SelectedTrooper) { + SelectedTrooper->SetSelection(false); + SelectedTrooper = nullptr; + } + UE_LOG(LogTemp, Warning, TEXT("Not your turn, %d"), PlayerIndex); + // AMyGameMode *gameMode = GetMyGameMode(); + // gameMode->CycleTurns(); + // Cast(GetWorld()->GetGameState())->CycleTurns(); + } +} + +void AMyPlayerState::MoveTrooper_Implementation( + ATrooper *Trooper, + FVector Location) { + if (Trooper->CheckMoveCorrectness(Location)) { + Trooper->MoveTrooper(Location); + // GetMyGameMode()->CycleTurns(); + } else { + GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Red, + FString::Printf( + TEXT("Out of move radius!"))); + } +} + +void AMyPlayerState::Attack_Implementation(ATrooper *Attacker, + FVector Location, + int ActionIndex) { + if (Attacker && CurrentAction >= 1 && CurrentAction <= 2 && + Attacker->CheckAttackCorrectness(Location, CurrentAction)) { + Attacker->Attack(CurrentAction); + } else { + UE_LOG(LogTemp, Warning, + TEXT("Out of radius or not enough Action Points")); + } +} + +void AMyPlayerState::OnPlayerAction(const FHitResult &HitResult) { + auto const NewlySelectedLocation = HitResult.Location; + ATrooper *NewlySelectedTrooper = Cast( + HitResult.GetActor()); + + // skip re-selection + if (SelectedTrooper == NewlySelectedTrooper) { + UE_LOG(LogTemp, Warning, TEXT("Skip reselection")); + return; + } + + if (NewlySelectedTrooper == nullptr || !NewlySelectedTrooper-> + IsValidLowLevel() || NewlySelectedTrooper->GetPlayerIndex() != + PlayerIndex) { + if (SelectedTrooper != nullptr && SelectedTrooper->IsValidLowLevel()) { + switch (CurrentAction) { + case 0: + UE_LOG(LogTemp, Warning, TEXT("Do move")); + // move this mf + MoveTrooper(SelectedTrooper, NewlySelectedLocation); + // and reset the selection.... + SelectedTrooper->SetSelection(false); + SelectedTrooper = nullptr; + break; + default: + // ATTACK! ATTACK! + UE_LOG(LogTemp, Warning, TEXT("Do attack")); + Attack(SelectedTrooper, NewlySelectedLocation, + CurrentAction); + SelectedTrooper->SetSelection(false); + SelectedTrooper = nullptr; + break; + } + } + } else if (NewlySelectedTrooper != nullptr && NewlySelectedTrooper-> + IsValidLowLevel() && NewlySelectedTrooper->GetPlayerIndex() == + PlayerIndex) { + UE_LOG(LogTemp, Warning, TEXT("Do reselect")); + // our move, selection + if (SelectedTrooper) { + SelectedTrooper->SetSelection(false); + } + SelectedTrooper = NewlySelectedTrooper; + SelectedTrooper->SetSelection(true); + } +} + +float AMyPlayerState::SetCurrentActionAndReturnRadius(int Action) { + CurrentAction = Action; + UE_LOG(LogTemp, Warning, TEXT("SetCurrentAction: %d on Player Controller " + "with index %d"), CurrentAction, PlayerIndex); + if (SelectedTrooper) { + return SelectedTrooper->GetActionRadius(CurrentAction); + } + return 0.0f; +} + +uint8 AMyPlayerState::GetPlayerIndex() { + return PlayerIndex; +} + +void AMyPlayerState::GetLifetimeReplicatedProps( + TArray &OutLifetimeProps) const { + Super::GetLifetimeReplicatedProps(OutLifetimeProps); + DOREPLIFETIME(AMyPlayerState, PlayerIndex); + DOREPLIFETIME(AMyPlayerState, CurrentAction); + DOREPLIFETIME(AMyPlayerState, bIsMyTurn); + DOREPLIFETIME(AMyPlayerState, SelectedTrooper); +} diff --git a/Source/TurnBasedTutorial/MyPlayerState.h b/Source/TurnBasedTutorial/MyPlayerState.h new file mode 100644 index 0000000..cd08241 --- /dev/null +++ b/Source/TurnBasedTutorial/MyPlayerState.h @@ -0,0 +1,63 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/PlayerState.h" +#include "MyPlayerState.generated.h" + +/** + * + */ +UCLASS() +class TURNBASEDTUTORIAL_API AMyPlayerState : public APlayerState { + GENERATED_BODY() +public: + AMyPlayerState(); + + virtual void BeginPlay() override; + + UFUNCTION(Client, Reliable) + void StartTurn(); + + UFUNCTION(Client, Reliable, BlueprintCallable) + void EndTurn(); + + UFUNCTION(Server, Reliable) + void MoveTrooper(ATrooper *Trooper, FVector Location); + + UFUNCTION(Server, Reliable) + void Attack(ATrooper *Attacker, FVector Location, int ActionIndex); + + UFUNCTION() + bool IsMyTurn() const; + + UFUNCTION() + void OnPlayerAction(const FHitResult &HitResult); + + UFUNCTION(BlueprintCallable) + float SetCurrentActionAndReturnRadius(int Action); + + UFUNCTION(BlueprintCallable) + uint8 GetPlayerIndex(); + + UFUNCTION() + void SetPlayerIndex(uint8 NewPlayerIndex); + +private: + UPROPERTY(Replicated) + uint8 PlayerIndex; + + UFUNCTION() + void SetMyTurn(bool bMyTurn); + + UPROPERTY(Replicated) + bool bIsMyTurn; + + UPROPERTY(Replicated) + int CurrentAction = 0; + + + UPROPERTY(Replicated) + ATrooper *SelectedTrooper; +}; diff --git a/Source/TurnBasedTutorial/Trooper.h b/Source/TurnBasedTutorial/Trooper.h index 8446480..5adb591 100644 --- a/Source/TurnBasedTutorial/Trooper.h +++ b/Source/TurnBasedTutorial/Trooper.h @@ -75,10 +75,6 @@ protected: UPROPERTY(EditAnywhere) UAbility *SpecialAbility; - const float MoveRadius = 1500.f; - - float AttackRadius = 1000.f; - UPROPERTY(EditAnywhere) float Speed = 300.0f;