From cdd8c11f8b1db0e863fd869fa7592989617c8085 Mon Sep 17 00:00:00 2001 From: eyakm1 Date: Mon, 27 Mar 2023 08:11:27 +0300 Subject: [PATCH] Full replication of movement and attacks implemented --- Config/DefaultEngine.ini | 4 +- Content/BattleField/BattleFieldMap.umap | Bin 634586 -> 634601 bytes Source/TurnBasedTutorial/MyGameMode.cpp | 56 ++++---- Source/TurnBasedTutorial/MyGameMode.h | 1 + .../TurnBasedTutorial/MyPlayerController.cpp | 121 +++++++++++------- Source/TurnBasedTutorial/MyPlayerController.h | 15 ++- Source/TurnBasedTutorial/Trooper.cpp | 79 ++++++------ Source/TurnBasedTutorial/Trooper.h | 50 ++++---- Source/TurnBasedTutorial/TurnBasedTutorial.h | 2 +- 9 files changed, 183 insertions(+), 145 deletions(-) diff --git a/Config/DefaultEngine.ini b/Config/DefaultEngine.ini index 0d2ee23..ae6b8ed 100644 --- a/Config/DefaultEngine.ini +++ b/Config/DefaultEngine.ini @@ -28,4 +28,6 @@ AppliedDefaultGraphicsPerformance=Maximum [CoreRedirects] -+PropertyRedirects=(OldName="/Script/TurnBasedTutorial.Trooper.OnPlayersSide",NewName="/Script/TurnBasedTutorial.Trooper.bOnPlayersSide") \ No newline at end of file ++PropertyRedirects=(OldName="/Script/TurnBasedTutorial.Trooper.OnPlayersSide",NewName="/Script/TurnBasedTutorial.Trooper.bOnPlayersSide") ++FunctionRedirects=(OldName="/Script/TurnBasedTutorial.MyPlayerController.MoveHero",NewName="/Script/TurnBasedTutorial.MyPlayerController.MoveTropper") ++FunctionRedirects=(OldName="/Script/TurnBasedTutorial.MyPlayerController.MoveTropper",NewName="/Script/TurnBasedTutorial.MyPlayerController.MoveTrooper") \ No newline at end of file diff --git a/Content/BattleField/BattleFieldMap.umap b/Content/BattleField/BattleFieldMap.umap index 2c00f7a6471996c67fac462d41735ef19c8cb70c..49216a997b1ec940529e5558f5acd49bc2176691 100644 GIT binary patch delta 1098 zcmZ8fYe-XJ81}rbTsm#h!B&e{^tm0kcD6b7eAI$|B$f8Vpd#3hZl;yFE=G}3*mM!@cek5_jzw0?~4KJ#{p|g zu3%{n&sufYpSLU=mcFUdU`ON6SpTO+=hCa~vD3p9eOb6h*eJYHZwZGRVLyZR z9&E;4vK5WH^;l`8kXMZ7_PVfMo{sBm228Y>ptTq~E5;lJHVOlAYL*B-vxzXdggeX< z1y`KLnB$@(!rJi?g+p;#V6$L(rU{zj((OzNPvbO&h^W{J{3v0Q+S#N!JZ7iRxrH~? z97zrWLtDAzcTmXR##i$@Ecn)8f=6-5F`ojKa)(yq;(P+Z?OYmR4nrCLk9|%8U1dCa z-$@}7;8e?BDie4U_?w`>mmNHJhKmR?&JE1ODmfiXT@=dq@ZftFfqDD>P@h|Y`~wq; zwz&zUSFy$HxZbM66c2?!kkdL@#9@ySBOVdzYIx#H=E?|h+MGqOBuj*A<0T5ZBix~l zZ}SpC!Ie8_vPNlR7vYtr3G7I;gE4B?!d~=02NjwoCrNA|d7FI9^+ z-GWm`Q!(8)Rkar%o-HKc_25mMQ?m$Lf;Z4#Q;l0fCMJ)4pH_>W{r;7<3^FJz#C}Bh$H>Y#OD$8YiCTy{6M${(6pTnC3F$)Kl7fmU8j}5xSl`k3rXM`#oacF;=ewQv=alO6l&Z_h zDYLdaW+vt%GQ6>=$12wxnQ8)W12kGA;72tNf7VL`lm#r{ zqmB*@4~N!E1j+(5Q?11E1O>DOq=5ti!vPvD@MzNtFke8oro~3>9_T*JRuHQpIsx9F zVN#BcKw2R?R*p`IUv&x?3P`#{0`*1AAIpQR zV^qv%7zB7nrPTm|*%FrBVHCJH+*Z017ptSN$Vk9`ffc_S1>l{lG|fb}eR;#AeI@}y zYUshVctRz?@FW7cwTy~CX(36Dtw}t%>sfGux}sc+b|wp0kj%rq^%8;K4a^~KU!5X= zrin>aDH;qn%b|IL6d6eyMoJ+UJBN+|H%nxi35*7)IOi*~05`8PN3?}N+_iO-wuXg= z<$&a)jwdb5;j<{Q+^T>@WYU0@aL2H_LcQ9s;vzPi0Qy#DXtoi!v_^flba;K2RdNV{ zk#XWbZPD0L8CEyxX`J+M6hIM7A)(krv6&)-LfSX!360?Y E0jaW+E&u=k diff --git a/Source/TurnBasedTutorial/MyGameMode.cpp b/Source/TurnBasedTutorial/MyGameMode.cpp index 2103d43..1a9aff9 100644 --- a/Source/TurnBasedTutorial/MyGameMode.cpp +++ b/Source/TurnBasedTutorial/MyGameMode.cpp @@ -16,35 +16,37 @@ AMyGameMode::AMyGameMode() : Super() void AMyGameMode::BeginPlay() { Super::BeginPlay(); - // ATrooper::InitNumberOfTroopersForId(); - // UE_LOG(LogTemp, Warning, TEXT("GameMode BeginPlay")); - // if (GetWorld()->GetMapName().Contains("BattleFieldMap")) - // { - // UE_LOG(LogTemp, Warning, TEXT("Player Logined")); - // InitializeBattleField(); - // GetMyPlayerController()->StartTurn(); - // } } void AMyGameMode::InitializeBattleField() const { - // FVector Location(2000.0f, -1000.0f, 0.0f); - // FRotator Rotation(0.0f, 180.0f, 0.0f); - // FActorSpawnParameters const SpawnInfo; - // for (int i = 0; i < 5; ++i) - // { - // AActor* Spawned = GetWorld()->SpawnActor(Location, Rotation, SpawnInfo); - // dynamic_cast(Spawned)->InitTrooper(Location, true); - // 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) - // { - // AActor* Spawned = GetWorld()->SpawnActor(Location, Rotation, SpawnInfo); - // dynamic_cast(Spawned)->InitTrooper(Location, false); - // Location += {0.f, 500.f, 0.0f}; - // } + UE_LOG(LogTemp, Warning, TEXT("InitializeBattleField")); + FVector Location(2000.0f, -1000.0f, 0.0f); + FRotator Rotation(0.0f, 180.0f, 0.0f); + FActorSpawnParameters const SpawnInfo; + + uint8 TrooperCount = 0; + + for (int i = 0; i < 5; ++i) + { + FTransform SpawnLocationAndRotation(Rotation); + SpawnLocationAndRotation.SetLocation(Location); + AActor* Spawned = GetWorld()->SpawnActorDeferred(ATrooper::StaticClass(), SpawnLocationAndRotation); + dynamic_cast(Spawned)->Initialize(0, Location, TrooperCount++); + Spawned->FinishSpawning(SpawnLocationAndRotation); + 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::StaticClass(), SpawnLocationAndRotation); + dynamic_cast(Spawned)->Initialize(1, Location, TrooperCount++); + Spawned->FinishSpawning(SpawnLocationAndRotation); + Location += {0.f, 500.f, 0.0f}; + } } @@ -90,6 +92,9 @@ void AMyGameMode::PostLogin(APlayerController* NewPlayer) UE_LOG(LogTemp, Warning, TEXT("PostLogin")); const auto World = GetWorld(); const auto CurrentNumberOfPlayers = GetNumPlayers(); + + // 0-indexation + dynamic_cast(NewPlayer)->SetPlayerIndex(CurrentNumberOfPlayers - 1); UE_LOG(LogTemp, Warning, TEXT("%d"), CurrentNumberOfPlayers); if (CurrentNumberOfPlayers == 2) { @@ -107,6 +112,7 @@ void AMyGameMode::PostLogin(APlayerController* NewPlayer) void AMyGameMode::StartGame() { + InitializeBattleField(); PlayerInTurn()->StartTurn(); } diff --git a/Source/TurnBasedTutorial/MyGameMode.h b/Source/TurnBasedTutorial/MyGameMode.h index 2304cbd..265066c 100644 --- a/Source/TurnBasedTutorial/MyGameMode.h +++ b/Source/TurnBasedTutorial/MyGameMode.h @@ -32,6 +32,7 @@ private: void InitializeBattleField() const; + UPROPERTY() TMap SpawnPoints{}; AMyPlayerController* GetMyPlayerController(uint8 const PlayerIndex) const; diff --git a/Source/TurnBasedTutorial/MyPlayerController.cpp b/Source/TurnBasedTutorial/MyPlayerController.cpp index 8056434..99de807 100644 --- a/Source/TurnBasedTutorial/MyPlayerController.cpp +++ b/Source/TurnBasedTutorial/MyPlayerController.cpp @@ -3,6 +3,8 @@ #include "MyPlayerController.h" #include "Kismet/GameplayStatics.h" #include "MyGameMode.h" +#include "AIController.h" +#include "Net/UnrealNetwork.h" AMyPlayerController::AMyPlayerController() : Super(), bIsMyTurn(false), SelectedTrooper(nullptr) { @@ -40,68 +42,93 @@ void AMyPlayerController::EndTurn_Implementation() UE_LOG(LogTemp, Warning, TEXT("Not your turn")); } -void AMyPlayerController::SetTrooperIsMoving(bool isMoving) +auto AMyPlayerController::GetMyGameMode() const { - bIsThereTrooperMoving = isMoving; + return dynamic_cast(UGameplayStatics::GetGameMode(GetWorld())); } -auto AMyPlayerController::GetMyGameMode() const +void AMyPlayerController::MoveTrooper_Implementation(ATrooper* Trooper, FVector Location) { - return dynamic_cast(UGameplayStatics::GetGameMode(GetWorld())); + Trooper->MoveTrooper(Location); + GetMyGameMode()->CycleTurns(); } -void AMyPlayerController::MoveHero_Implementation() + +void AMyPlayerController::AttackTrooper_Implementation(ATrooper* Attacker, ATrooper* Victim) { + GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, + FString::Printf( + TEXT("ATTACK!! %d attacked %d"), Attacker->GetId(), Victim->GetId())); GetMyGameMode()->CycleTurns(); } +void AMyPlayerController::SetPlayerIndex(uint8 NewPlayerIndex) +{ + PlayerIndex = NewPlayerIndex; +} + +void AMyPlayerController::GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const +{ + DOREPLIFETIME(AMyPlayerController, PlayerIndex); +} + void AMyPlayerController::OnLeftMouseClick() { - // if (bIsThereTrooperMoving) - // { - // return; - // } - // UE_LOG(LogTemp, Warning, TEXT("Mouse clicked")); - // FHitResult HitResult; - // bool const IsHitResult = GetHitResultUnderCursorByChannel(TraceTypeQuery1, false, HitResult); - // if (IsHitResult) - // { - // AActor* Actor = HitResult.Actor.Get(); - // if (Actor->ActorHasTag(FName("Trooper"))) - // { - // ATrooper* Trooper = dynamic_cast(Actor); - // if (Trooper != nullptr && Trooper != SelectedTrooper) - // { - // if (Trooper->IsOnPlayersSide()) - // { - // UE_LOG(LogTemp, Warning, TEXT("Hitted trooper id: %d, on our side"), - // Trooper->GetId()); - // SelectedTrooper = Trooper; - // } - // else - // { - // UE_LOG(LogTemp, Warning, TEXT("Hitted trooper id: %d, enemy"), - // Trooper->GetId()); - // UE_LOG(LogTemp, Warning, TEXT("Trooper #%d hit enemy trooper #%d"), - // SelectedTrooper->GetId(), Trooper->GetId()); - // } - // } - // } - // else if (Actor->ActorHasTag(FName("Floor"))) - // { - // UE_LOG(LogTemp, Warning, TEXT("Hitted floor: %f, %f, %f"), HitResult.Location.X, - // HitResult.Location.Y, HitResult.Location.Z); - // if (SelectedTrooper != nullptr) - // { - // SelectedTrooper->MoveTrooper(HitResult.Location); - // bIsThereTrooperMoving = true; - // } - // } - // } if (!bIsMyTurn) { return; } - MoveHero(); + UE_LOG(LogTemp, Warning, TEXT("Mouse clicked")); + FHitResult HitResult; + bool const IsHitResult = GetHitResultUnderCursorByChannel(TraceTypeQuery1, false, HitResult); + if (!IsHitResult) + return; + UE_LOG(LogTemp, Warning, TEXT("Got hit result")); + auto const NewlySelectedLocation = HitResult.Location; + ATrooper* NewlySelectedTrooper = dynamic_cast(HitResult.GetActor()); + + if (NewlySelectedTrooper == nullptr || !NewlySelectedTrooper->IsValidLowLevel()) + { + // 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()) + { + UE_LOG(LogTemp, Warning, TEXT("Do move")); + // move this mf + MoveTrooper(SelectedTrooper, NewlySelectedLocation); + // and reset the selection.... + SelectedTrooper = nullptr; + } + return; + } + UE_LOG(LogTemp, Warning, TEXT("New Selected Player Index %d"), NewlySelectedTrooper->GetPlayerIndex()); + // skip re-selection + if (SelectedTrooper == NewlySelectedTrooper) + { + UE_LOG(LogTemp, Warning, TEXT("Skip reselection")); + return; + } + // we selected valid trooper... + if (NewlySelectedTrooper->GetPlayerIndex() == PlayerIndex) + { + UE_LOG(LogTemp, Warning, TEXT("Do reselect")); + // our move, selection + SelectedTrooper = NewlySelectedTrooper; + } + else + { + UE_LOG(LogTemp, Warning, TEXT("Attack or skip...")); + // maybe selected trooper had gone crazy... + if (SelectedTrooper == nullptr || !SelectedTrooper->IsValidLowLevel()) + return; + UE_LOG(LogTemp, Warning, TEXT("Do attack")); + // ATTACK!!! ATTACK!!!!!! + AttackTrooper(SelectedTrooper, NewlySelectedTrooper); + SelectedTrooper = nullptr; + } } diff --git a/Source/TurnBasedTutorial/MyPlayerController.h b/Source/TurnBasedTutorial/MyPlayerController.h index 2060f43..146c175 100644 --- a/Source/TurnBasedTutorial/MyPlayerController.h +++ b/Source/TurnBasedTutorial/MyPlayerController.h @@ -29,16 +29,21 @@ public: void EndTurn(); UFUNCTION(Server, Reliable) - void MoveHero(); + void MoveTrooper(ATrooper *Trooper, FVector Location); + UFUNCTION(Server, Reliable) + void AttackTrooper(ATrooper *Attacker, ATrooper *Victim); + virtual void SetupInputComponent() override; - void SetTrooperIsMoving(bool isMoving); - + UFUNCTION() + void SetPlayerIndex(uint8 NewPlayerIndex); + private: bool bIsMyTurn; - - bool bIsThereTrooperMoving = false; + + UPROPERTY(Replicated) + uint8 PlayerIndex; ATrooper* SelectedTrooper; diff --git a/Source/TurnBasedTutorial/Trooper.cpp b/Source/TurnBasedTutorial/Trooper.cpp index eac1cf6..3a594fc 100644 --- a/Source/TurnBasedTutorial/Trooper.cpp +++ b/Source/TurnBasedTutorial/Trooper.cpp @@ -1,22 +1,23 @@ #include "Trooper.h" #include #include "MyPlayerController.h" +#include "Net/UnrealNetwork.h" // Sets default values ATrooper::ATrooper() { + bReplicates = true; + PrimaryActorTick.bCanEverTick = true; Tags.Add(FName("Trooper")); - Id = NumberOfTroopersForId++; - Position.Set(0, 0, 0); - Mesh = CreateDefaultSubobject("Mesh"); - RootComponent = Mesh; + MyStaticMesh = CreateDefaultSubobject("Mesh"); + RootComponent = MyStaticMesh; static ConstructorHelpers::FObjectFinder MeshToUse(TEXT( "StaticMesh'/Game/StarterContent/Props/SM_Chair.SM_Chair'" )); if (MeshToUse.Object) { - Mesh->SetStaticMesh(MeshToUse.Object); + MyStaticMesh->SetStaticMesh(MeshToUse.Object); } } @@ -26,59 +27,55 @@ void ATrooper::BeginPlay() Super::BeginPlay(); } +void ATrooper::Initialize(uint8 const NewPlayerIndex, FVector const SpawnLocation, uint8 const NewId) +{ + PlayerIndex = NewPlayerIndex; + bIsMoving = false; + CurrentLocation = SpawnLocation; + Id = NewId; +} + void ATrooper::Tick(float const DeltaTime) { - if (bIsMoving) + if (!bIsMoving) + return; + FVector PositionVector = (TargetLocation - CurrentLocation); + PositionVector.Normalize(); + PositionVector *= (Speed * DeltaTime); + if (PositionVector.Size() >= (TargetLocation - CurrentLocation).Size()) { - FVector vector = (MoveToVector - Position); - vector.Normalize(); - vector *= (Speed * DeltaTime); - if (vector.Size() >= (MoveToVector - Position).Size()) - { - Position = MoveToVector; - bIsMoving = false; - dynamic_cast( - UGameplayStatics::GetPlayerController(GetWorld(), 0) - )->SetTrooperIsMoving(false); - } - else - { - Position += vector; - } - SetActorLocation(Position); + CurrentLocation = TargetLocation; + bIsMoving = false; } + else + { + CurrentLocation += PositionVector; + } + SetActorLocation(CurrentLocation); } void ATrooper::MoveTrooper(FVector const NewPos) { - MoveToVector = NewPos; + TargetLocation = NewPos; bIsMoving = true; } -uint8 ATrooper::NumberOfTroopersForId = 0; - -void ATrooper::InitNumberOfTroopersForId() -{ - NumberOfTroopersForId = 0; -} - -FVector ATrooper::GetPosition() const +uint8 ATrooper::GetId() const { - return Position; + return Id; } -bool ATrooper::IsOnPlayersSide() const -{ - return bOnPlayersSide; -} -uint8 ATrooper::GetId() const +void ATrooper::GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const { - return Id; + DOREPLIFETIME(ATrooper, PlayerIndex); + DOREPLIFETIME(ATrooper, CurrentLocation); + DOREPLIFETIME(ATrooper, TargetLocation); + DOREPLIFETIME(ATrooper, bIsMoving); + DOREPLIFETIME(ATrooper, Id); } -void ATrooper::InitTrooper(FVector const NewPosition, bool const bIsOnPlayersSide) +uint8 ATrooper::GetPlayerIndex() const { - Position = NewPosition; - bOnPlayersSide = bIsOnPlayersSide; + return PlayerIndex; } diff --git a/Source/TurnBasedTutorial/Trooper.h b/Source/TurnBasedTutorial/Trooper.h index fc1ee7c..46cf1ae 100644 --- a/Source/TurnBasedTutorial/Trooper.h +++ b/Source/TurnBasedTutorial/Trooper.h @@ -3,10 +3,11 @@ #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "Components/StaticMeshComponent.h" +#include "GameFramework/Character.h" #include "Trooper.generated.h" UCLASS() -class TURNBASEDTUTORIAL_API ATrooper : public AActor +class TURNBASEDTUTORIAL_API ATrooper : public ACharacter { GENERATED_BODY() @@ -14,42 +15,41 @@ public: // Sets default values for this actor's properties ATrooper(); -protected: - static uint8 NumberOfTroopersForId; + void Initialize(uint8 const NewPlayerIndex, FVector const SpawnLocation, uint8 const NewId); + + UFUNCTION() + uint8 GetPlayerIndex() const; + + UFUNCTION() + void MoveTrooper(FVector const NewPos); + + UFUNCTION() + uint8 GetId() const; +protected: virtual void BeginPlay() override; virtual void Tick(float const DeltaTime) override; - UPROPERTY() - FVector Position; + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + UStaticMeshComponent* MyStaticMesh; - UPROPERTY() - bool bOnPlayersSide; +private: + UPROPERTY(Replicated) + uint8 PlayerIndex; - UPROPERTY() + UPROPERTY(Replicated) uint8 Id; - UPROPERTY(VisibleAnywhere, BlueprintReadOnly) - UStaticMeshComponent* Mesh; - UPROPERTY() float Speed = 300.0f; - bool bIsMoving = false; - - FVector MoveToVector; - -public: - void MoveTrooper(FVector const NewPos); + UPROPERTY(Replicated) + FVector CurrentLocation; - static void InitNumberOfTroopersForId(); + UPROPERTY(Replicated) + FVector TargetLocation; - FVector GetPosition() const; - - bool IsOnPlayersSide() const; - - uint8 GetId() const; - - void InitTrooper(FVector const NewPosition, bool const bIsOnPlayersSide); + UPROPERTY(Replicated) + bool bIsMoving = false; }; diff --git a/Source/TurnBasedTutorial/TurnBasedTutorial.h b/Source/TurnBasedTutorial/TurnBasedTutorial.h index 677c8e2..4dd4c4f 100644 --- a/Source/TurnBasedTutorial/TurnBasedTutorial.h +++ b/Source/TurnBasedTutorial/TurnBasedTutorial.h @@ -2,5 +2,5 @@ #pragma once -#include "CoreMinimal.h" +#include "Core.h"