diff --git a/Content/BattleField/BP_BattleUI.uasset b/Content/BattleField/BP_BattleUI.uasset index 200176a..346c66a 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 75f7d56..1a419bd 100644 Binary files a/Content/BattleField/BattleFieldMap.umap and b/Content/BattleField/BattleFieldMap.umap differ diff --git a/Content/Troopers/BP_DefaultProjectile.uasset b/Content/Troopers/BP_DefaultProjectile.uasset new file mode 100644 index 0000000..6c90094 Binary files /dev/null and b/Content/Troopers/BP_DefaultProjectile.uasset differ diff --git a/Content/Troopers/BP_Trooper.uasset b/Content/Troopers/BP_Trooper.uasset index 6e72344..d47ed93 100644 Binary files a/Content/Troopers/BP_Trooper.uasset and b/Content/Troopers/BP_Trooper.uasset differ diff --git a/Content/Troopers/MyMyProjectile.uasset b/Content/Troopers/MyMyProjectile.uasset index 7a95d3a..09044c9 100644 Binary files a/Content/Troopers/MyMyProjectile.uasset and b/Content/Troopers/MyMyProjectile.uasset differ diff --git a/Content/Troopers/TrooperSkeletonMelee.uasset b/Content/Troopers/TrooperSkeletonMelee.uasset index 5f291b7..1496a7a 100644 Binary files a/Content/Troopers/TrooperSkeletonMelee.uasset and b/Content/Troopers/TrooperSkeletonMelee.uasset differ diff --git a/Content/Troopers/TrooperWizard.uasset b/Content/Troopers/TrooperWizard.uasset index a3959ec..76c7053 100644 Binary files a/Content/Troopers/TrooperWizard.uasset and b/Content/Troopers/TrooperWizard.uasset differ diff --git a/Source/TurnBasedTutorial/MyGameMode.cpp b/Source/TurnBasedTutorial/MyGameMode.cpp index 955addf..1de3aef 100644 --- a/Source/TurnBasedTutorial/MyGameMode.cpp +++ b/Source/TurnBasedTutorial/MyGameMode.cpp @@ -6,6 +6,7 @@ #include "MyGameState.h" #include "MyPlayerController.h" #include "MyPlayerState.h" +#include "Trooper.h" AMyGameMode::AMyGameMode() : Super() { @@ -25,7 +26,7 @@ auto AMyGameMode::GetMyGameState() const { } -void AMyGameMode::InitializeBattleField() const { +void AMyGameMode::InitializeBattleField_Implementation() const { UE_LOG(LogTemp, Warning, TEXT("InitializeBattleField")); FVector Location(2000.0f, -1000.0f, 0.0f); FRotator Rotation(0.0f, 180.0f, 0.0f); @@ -121,6 +122,7 @@ void AMyGameMode::InitializeSpawnPointsIfNeeded(AController *Player) { void AMyGameMode::PostLogin(APlayerController *NewPlayer) { Super::PostLogin(NewPlayer); + NewPlayer->SetShowMouseCursor(true); UE_LOG(LogTemp, Warning, TEXT("PostLogin")); // PlayerControllers.Add(dynamic_cast(NewPlayer)); // const auto World = GetWorld(); @@ -137,6 +139,8 @@ void AMyGameMode::PostLogin(APlayerController *NewPlayer) { // GetWorld()->GetGameState())->StartGame(); // InitializeBattleField(); StartGame(); + // GetMyGameState()->PlayerInTurn()->SetEnemySelection(); + // GetMyGameState()->PlayerNotInTurn()->SetEnemySelection(); } else { // delay the game UE_LOG(LogTemp, Warning, TEXT("Game Delay")); diff --git a/Source/TurnBasedTutorial/MyGameMode.h b/Source/TurnBasedTutorial/MyGameMode.h index 6d3a651..7e68aa4 100644 --- a/Source/TurnBasedTutorial/MyGameMode.h +++ b/Source/TurnBasedTutorial/MyGameMode.h @@ -30,6 +30,7 @@ public: private: void InitializeSpawnPointsIfNeeded(AController *Player); + UFUNCTION(Server, Reliable) void InitializeBattleField() const; UPROPERTY() @@ -41,6 +42,7 @@ private: UFUNCTION(Server, Reliable) void StartGame(); + // UFUNCTION(BlueprintPure) // AMyPlayerController *PlayerInTurn() const; // diff --git a/Source/TurnBasedTutorial/MyGameState.cpp b/Source/TurnBasedTutorial/MyGameState.cpp index 35f4a6c..c66124d 100644 --- a/Source/TurnBasedTutorial/MyGameState.cpp +++ b/Source/TurnBasedTutorial/MyGameState.cpp @@ -14,7 +14,7 @@ void AMyGameState::BeginPlay() { Super::BeginPlay(); } -void AMyGameState::AddTrooper(ATrooper *Trooper) { +void AMyGameState::AddTrooper_Implementation(ATrooper *Trooper) { Troopers.Add(Trooper); } @@ -66,6 +66,10 @@ TArray AMyGameState::GetTroopers() const { return Troopers; } +bool AMyGameState::IsInTurn(uint8 PlayerIndex) const { + return PlayerIndex == CurrentPlayerTurn; +} + void AMyGameState::GetLifetimeReplicatedProps( TArray &OutLifetimeProps) const { Super::GetLifetimeReplicatedProps(OutLifetimeProps); diff --git a/Source/TurnBasedTutorial/MyGameState.h b/Source/TurnBasedTutorial/MyGameState.h index 4038845..fbbaf1e 100644 --- a/Source/TurnBasedTutorial/MyGameState.h +++ b/Source/TurnBasedTutorial/MyGameState.h @@ -17,7 +17,7 @@ class TURNBASEDTUTORIAL_API AMyGameState : public AGameState { public: virtual void BeginPlay() override; - UFUNCTION() + UFUNCTION(Server, Reliable) void AddTrooper(ATrooper *Trooper); UFUNCTION(Server, Reliable) @@ -35,6 +35,9 @@ public: UFUNCTION() TArray GetTroopers() const; + UFUNCTION() + bool IsInTurn(uint8 PlayerIndex) const; + private: UPROPERTY(Replicated) TArray Troopers; diff --git a/Source/TurnBasedTutorial/MyPlayerController.cpp b/Source/TurnBasedTutorial/MyPlayerController.cpp index 461caee..cf74f71 100644 --- a/Source/TurnBasedTutorial/MyPlayerController.cpp +++ b/Source/TurnBasedTutorial/MyPlayerController.cpp @@ -50,11 +50,13 @@ auto AMyPlayerController::GetMyGameMode() const { } -void AMyPlayerController::EndTurn() { +void AMyPlayerController::EndTurn_Implementation() { // if (GetMyPlayerState()->IsMyTurn()) { // GetMyGameState()->CycleTurns(); // } - GetMyPlayerState()->CycleTurns(); + // GetMyPlayerState()->CycleTurns(); + if (GetMyGameState()->IsInTurn(PlayerIndex)) + GetMyGameState()->CycleTurns(); } // void AMyPlayerController::EndTurn_Implementation() { @@ -132,6 +134,10 @@ void AMyPlayerController::SetPlayerIndex(uint8 NewPlayerIndex) { // GetMyPlayerState()->PlayerIndex = NewPlayerIndex; } +uint8 AMyPlayerController::GetPlayerIndex() const { + return PlayerIndex; +} + // float AMyPlayerController::SetCurrentActionAndReturnRadius(int action) { // return GetMyPlayerState()->SetCurrentActionAndReturnRadius(action); // diff --git a/Source/TurnBasedTutorial/MyPlayerController.h b/Source/TurnBasedTutorial/MyPlayerController.h index 5bacb6f..006d25d 100644 --- a/Source/TurnBasedTutorial/MyPlayerController.h +++ b/Source/TurnBasedTutorial/MyPlayerController.h @@ -2,7 +2,6 @@ #pragma once #include "CoreMinimal.h" -#include "Trooper.h" #include "GameFramework/PlayerController.h" #include "MyPlayerController.generated.h" @@ -19,7 +18,7 @@ public: AMyPlayerController(); - UFUNCTION(BlueprintCallable) + UFUNCTION(BlueprintCallable, Server, Reliable) void EndTurn(); // UFUNCTION(Client, Reliable) @@ -40,6 +39,9 @@ public: UFUNCTION() void SetPlayerIndex(uint8 NewPlayerIndex); + UFUNCTION() + uint8 GetPlayerIndex() const; + // UFUNCTION(BlueprintCallable) // float SetCurrentActionAndReturnRadius(int action); diff --git a/Source/TurnBasedTutorial/MyPlayerState.cpp b/Source/TurnBasedTutorial/MyPlayerState.cpp index e7fe995..5b8bfd7 100644 --- a/Source/TurnBasedTutorial/MyPlayerState.cpp +++ b/Source/TurnBasedTutorial/MyPlayerState.cpp @@ -4,7 +4,6 @@ #include "MyPlayerState.h" #include "MyGameState.h" -#include "Trooper.h" #include "Net/UnrealNetwork.h" AMyPlayerState::AMyPlayerState() @@ -34,6 +33,7 @@ void AMyPlayerState::SetEnemySelection_Implementation( void AMyPlayerState::MoveTrooper_Implementation(ATrooper *Trooper, FVector Location) { + Location.Z = 0.0f; if (Trooper->CheckMoveCorrectness(Location)) { Trooper->MoveTrooper(Location); // GetMyGameMode()->CycleTurns(); @@ -76,11 +76,11 @@ void AMyPlayerState::Attack_Implementation(ATrooper *Attacker, } } -void AMyPlayerState::CycleTurns() const { - if (bIsMyTurn) { - GetMyGameState()->CycleTurns(); - } -} +// void AMyPlayerState::CycleTurns_Implementation() const { +// if (bIsMyTurn) { +// GetMyGameState()->CycleTurns(); +// } +// } bool AMyPlayerState::IsMyTurn() const { return bIsMyTurn; @@ -175,7 +175,7 @@ void AMyPlayerState::SetCurrentAction_Implementation(int Action) { } -uint8 AMyPlayerState::GetPlayerIndex() { +uint8 AMyPlayerState::GetPlayerIndex() const { return PlayerIndex; } diff --git a/Source/TurnBasedTutorial/MyPlayerState.h b/Source/TurnBasedTutorial/MyPlayerState.h index 5387265..b650430 100644 --- a/Source/TurnBasedTutorial/MyPlayerState.h +++ b/Source/TurnBasedTutorial/MyPlayerState.h @@ -2,6 +2,7 @@ #pragma once +#include "Trooper.h" #include "CoreMinimal.h" #include "GameFramework/PlayerState.h" #include "MyPlayerState.generated.h" @@ -33,8 +34,8 @@ public: int ActionIndex, const TArray &Troopers); - UFUNCTION() - void CycleTurns() const; + // UFUNCTION(Client, Reliable) + // void CycleTurns() const; UFUNCTION(BlueprintCallable) bool IsMyTurn() const; @@ -46,7 +47,7 @@ public: void SetCurrentAction(int Action); UFUNCTION(BlueprintCallable) - uint8 GetPlayerIndex(); + uint8 GetPlayerIndex() const; UFUNCTION() void SetPlayerIndex(uint8 NewPlayerIndex); @@ -54,7 +55,9 @@ public: UFUNCTION(Client, Reliable) void SetEnemySelection(const TArray &Troopers) const; + private: + UPROPERTY(Replicated) uint8 PlayerIndex; diff --git a/Source/TurnBasedTutorial/MyProjectile.cpp b/Source/TurnBasedTutorial/MyProjectile.cpp index 2f05f04..d73cedb 100644 --- a/Source/TurnBasedTutorial/MyProjectile.cpp +++ b/Source/TurnBasedTutorial/MyProjectile.cpp @@ -3,15 +3,19 @@ #include "MyProjectile.h" +#include "Trooper.h" #include "Net/UnrealNetwork.h" -#include "VisualLogger/VisualLoggerCustomVersion.h" AMyProjectile::AMyProjectile() { + // if (!RootComponent) { + // RootComponent = CreateDefaultSubobject( + // TEXT("ProjectileSceneComponent")); + // } // if (!CollisionComponent) { // CollisionComponent = CreateDefaultSubobject( // TEXT("SphereComponent")); + // RootComponent = CollisionComponent; // } - // RootComponent = CollisionComponent; if (!ProjectileMeshComponent) { ProjectileMeshComponent = CreateDefaultSubobject( TEXT("ProjectileMeshComponent")); @@ -27,7 +31,9 @@ AMyProjectile::AMyProjectile() { ProjectileMovementComponent = CreateDefaultSubobject< UProjectileMovementComponent>(TEXT("ProjectileMovementComponent")); ProjectileMovementComponent->SetUpdatedComponent( + // CollisionComponent); ProjectileMeshComponent); + ProjectileMovementComponent->bRotationFollowsVelocity = true; ProjectileMovementComponent->InitialSpeed = 1000.0f; ProjectileMovementComponent->MaxSpeed = 1000.0f; ProjectileMovementComponent->ProjectileGravityScale = 0.0f; @@ -42,6 +48,7 @@ void AMyProjectile::Initialize(const UAbility *Ability, ProjectileMovementComponent->MaxSpeed = Ability->Speed; Damage = Ability->Damage; float Scale = Ability->LinearWidth / 100; + // CollisionComponent->SetSphereRadius(Ability->LinearWidth / 2); ProjectileMeshComponent->SetWorldScale3D({Scale, Scale, Scale}); PlayerIndex = playerIndex; SetLifeSpan(PathLength / Ability->Speed); @@ -52,6 +59,51 @@ void AMyProjectile::Shoot(FVector From, FVector To) const { (To - From).GetSafeNormal() * ProjectileMovementComponent->InitialSpeed; } +void AMyProjectile::NotifyActorBeginOverlap(AActor *OtherActor) { + Super::NotifyActorBeginOverlap(OtherActor); + ATrooper *OtherTrooper = Cast(OtherActor); + if (OtherTrooper) { + UE_LOG(LogTemp, Warning, + TEXT("Begin overlap: id: %d, index: %d, damage: %f, my index: %d" + ), + OtherTrooper->GetId(), OtherTrooper->GetPlayerIndex(), Damage, + PlayerIndex); + if (PlayerIndex != -1 && PlayerIndex != OtherTrooper-> + GetPlayerIndex()) { + OtherTrooper->TakeDamage(Damage); + } + } else { + UE_LOG(LogTemp, Warning, TEXT("Overlapped not a trooper")); + } +} + +void AMyProjectile::NotifyHit(UPrimitiveComponent *MyComp, + AActor *Other, + UPrimitiveComponent *OtherComp, + bool bSelfMoved, + FVector HitLocation, + FVector HitNormal, + FVector NormalImpulse, + const FHitResult &Hit) { + Super::NotifyHit(MyComp, Other, OtherComp, bSelfMoved, HitLocation, + HitNormal, + NormalImpulse, Hit); + ATrooper *OtherTrooper = Cast(Other); + if (OtherTrooper) { + UE_LOG(LogTemp, Warning, + TEXT("On Hit: id: %d, index: %d, damage: %f, my index: %d" + ), + OtherTrooper->GetId(), OtherTrooper->GetPlayerIndex(), Damage, + PlayerIndex); + if (PlayerIndex != -1 && PlayerIndex != OtherTrooper-> + GetPlayerIndex()) { + OtherTrooper->TakeDamage(Damage); + } + } else { + UE_LOG(LogTemp, Warning, TEXT("Overlapped not a trooper")); + } +} + void AMyProjectile::BeginPlay() { Super::BeginPlay(); @@ -61,4 +113,8 @@ void AMyProjectile::GetLifetimeReplicatedProps( TArray &OutLifetimeProps) const { Super::GetLifetimeReplicatedProps(OutLifetimeProps); DOREPLIFETIME(AMyProjectile, Damage); + DOREPLIFETIME(AMyProjectile, PlayerIndex); + // DOREPLIFETIME(AMyProjectile, CollisionComponent); + DOREPLIFETIME(AMyProjectile, ProjectileMeshComponent); + DOREPLIFETIME(AMyProjectile, ProjectileMovementComponent); } diff --git a/Source/TurnBasedTutorial/MyProjectile.h b/Source/TurnBasedTutorial/MyProjectile.h index 372a6ec..612001c 100644 --- a/Source/TurnBasedTutorial/MyProjectile.h +++ b/Source/TurnBasedTutorial/MyProjectile.h @@ -16,25 +16,38 @@ class TURNBASEDTUTORIAL_API AMyProjectile : public AActor { public: AMyProjectile(); - void Initialize(const UAbility *Ability, uint8 playerIndex, float PathLength); + void Initialize(const UAbility *Ability, + uint8 playerIndex, + float PathLength); void Shoot(FVector From, FVector To) const; protected: + virtual void NotifyActorBeginOverlap(AActor *OtherActor) override; + + virtual void NotifyHit(UPrimitiveComponent *MyComp, + AActor *Other, + UPrimitiveComponent *OtherComp, + bool bSelfMoved, + FVector HitLocation, + FVector HitNormal, + FVector NormalImpulse, + const FHitResult &Hit) override; + UPROPERTY(Replicated) float Damage; UPROPERTY(Replicated) - uint8 PlayerIndex = -1; - - // UPROPERTY(EditAnywhere) + int8 PlayerIndex = -1; + + // UPROPERTY(EditAnywhere, Replicated) // USphereComponent *CollisionComponent; - UPROPERTY(EditAnywhere) + UPROPERTY(EditAnywhere, Replicated) UStaticMeshComponent *ProjectileMeshComponent; - UPROPERTY(VisibleAnywhere) + UPROPERTY(VisibleAnywhere, Replicated) UProjectileMovementComponent *ProjectileMovementComponent; - + virtual void BeginPlay() override; }; diff --git a/Source/TurnBasedTutorial/Trooper.cpp b/Source/TurnBasedTutorial/Trooper.cpp index e5bfe1b..8e4d985 100644 --- a/Source/TurnBasedTutorial/Trooper.cpp +++ b/Source/TurnBasedTutorial/Trooper.cpp @@ -2,6 +2,8 @@ #include #include "HealthBar.h" +#include "MyPlayerController.h" +#include "MyPlayerState.h" #include "MyProjectile.h" #include "Components/WidgetComponent.h" #include "Net/UnrealNetwork.h" @@ -111,17 +113,20 @@ void ATrooper::Tick(float const DeltaTime) { } } -// void ATrooper::OnRepNotify_PlayerIndex() { -// UE_LOG(LogTemp, Warning, -// TEXT("On rep notify, index: %d, id: %d, on server: %d, player state: %d"), -// PlayerIndex, Id, GetNetMode() == NM_DedicatedServer, GetPlayerState() != nullptr); -// // if (GetNetMode() != NM_DedicatedServer && GetPlayerState()) { -// // if (Cast(GetPlayerState())->GetPlayerIndex() != -// // PlayerIndex) { -// // HighlightAsEnemy(); -// // } -// // } -// } +void ATrooper::OnRepNotify_PlayerIndex() const { + const AMyPlayerState *player = Cast( + GetPlayerState()); + if (!player) + return; + const uint8 ClientIndex = player->GetPlayerIndex(); + UE_LOG(LogTemp, Warning, + TEXT("On rep notify, index: %d, client index: %d, id: %d"), + PlayerIndex, + ClientIndex, Id); + if (ClientIndex == PlayerIndex) { + HighlightAsEnemy(); + } +} void ATrooper::MoveTrooper(FVector const NewPos) { TargetLocation = NewPos; @@ -240,6 +245,9 @@ UAbility *ATrooper::GetAbility(int AbilityIndex) const { } bool ATrooper::TakeDamage(float Damage) { + if (bIsTakingDamage) { + return false; + } HitPoints = FMath::Max(0, HitPoints - Damage); if (HitPoints == 0) { bIsDead = true; @@ -279,7 +287,8 @@ void ATrooper::FireProjectile_Implementation() { AMyProjectile *Projectile = GetWorld()->SpawnActor( GetProjectileClass(CurrentAbilityIndex), SpawnTransform, SpawnParameters); - Projectile->Initialize(GetAbility(CurrentAbilityIndex), CurrentAbilityIndex, + Projectile->SetActorLocation(SpawnLocation); + Projectile->Initialize(GetAbility(CurrentAbilityIndex), PlayerIndex, (CurrentAbilityDestination - SpawnLocation). Size()); Projectile->Shoot(SpawnLocation, CurrentAbilityDestination); diff --git a/Source/TurnBasedTutorial/Trooper.h b/Source/TurnBasedTutorial/Trooper.h index dde6005..6866ae4 100644 --- a/Source/TurnBasedTutorial/Trooper.h +++ b/Source/TurnBasedTutorial/Trooper.h @@ -160,10 +160,10 @@ protected: // const TCHAR *MeshPath = nullptr; - // UFUNCTION() - // void OnRepNotify_PlayerIndex(); + UFUNCTION() + void OnRepNotify_PlayerIndex() const; - UPROPERTY(Replicated/*Using = OnRepNotify_PlayerIndex*/) + UPROPERTY(ReplicatedUsing = OnRepNotify_PlayerIndex) uint8 PlayerIndex = -1; UPROPERTY(Replicated)