diff --git a/.idea/.idea.TurnBased/.idea/.gitignore b/.idea/.idea.TurnBased/.idea/.gitignore new file mode 100644 index 0000000..bdaabaf --- /dev/null +++ b/.idea/.idea.TurnBased/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/modules.xml +/contentModel.xml +/projectSettingsUpdater.xml +/.idea.TurnBased.iml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.idea.TurnBased/.idea/.name b/.idea/.idea.TurnBased/.idea/.name new file mode 100644 index 0000000..496e6cf --- /dev/null +++ b/.idea/.idea.TurnBased/.idea/.name @@ -0,0 +1 @@ +TurnBased \ No newline at end of file diff --git a/.idea/.idea.TurnBased/.idea/encodings.xml b/.idea/.idea.TurnBased/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/.idea/.idea.TurnBased/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.TurnBased/.idea/indexLayout.xml b/.idea/.idea.TurnBased/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.TurnBased/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.TurnBased/.idea/vcs.xml b/.idea/.idea.TurnBased/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/.idea.TurnBased/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Config/DefaultEditor.ini b/Config/DefaultEditor.ini index e69de29..8b13789 100644 --- a/Config/DefaultEditor.ini +++ b/Config/DefaultEditor.ini @@ -0,0 +1 @@ + diff --git a/Config/DefaultEngine.ini b/Config/DefaultEngine.ini index 9fe9839..33eb9b3 100644 --- a/Config/DefaultEngine.ini +++ b/Config/DefaultEngine.ini @@ -31,6 +31,14 @@ AppliedDefaultGraphicsPerformance=Maximum +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") ++PropertyRedirects=(OldName="/Script/TurnBasedTutorial.ManageSquadTrooper.IndexInSquad",NewName="/Script/TurnBasedTutorial.ManageSquadTrooper.Index") ++PropertyRedirects=(OldName="/Script/TurnBasedTutorial.ManageSquadTrooper.IndexInSquadOrSample",NewName="/Script/TurnBasedTutorial.ManageSquadTrooper.Index") ++FunctionRedirects=(OldName="/Script/TurnBasedTutorial.Trooper.GetActionCost",NewName="/Script/TurnBasedTutorial.Trooper.GetActionRadius") ++FunctionRedirects=(OldName="/Script/TurnBasedTutorial.Trooper.GetActionCost",NewName="/Script/TurnBasedTutorial.Trooper.GetActionRadius") ++PropertyRedirects=(OldName="/Script/TurnBasedTutorial.Trooper.RedMaterialInterface",NewName="/Script/TurnBasedTutorial.Trooper.RedMaterial") ++FunctionRedirects=(OldName="/Script/TurnBasedTutorial.Trooper.HighlightEnemy",NewName="/Script/TurnBasedTutorial.Trooper.HighlightAsEnemy") ++PropertyRedirects=(OldName="/Script/TurnBasedTutorial.Trooper.bIsDying",NewName="/Script/TurnBasedTutorial.Trooper.bIsDead") ++PropertyRedirects=(OldName="/Script/TurnBasedTutorial.Trooper.bIsDying",NewName="/Script/TurnBasedTutorial.Trooper.bIsDead") [OnlineSubsystem] DefaultPlatformService=Null diff --git a/Config/DefaultInput.ini b/Config/DefaultInput.ini index 07e992c..3d5b79e 100644 --- a/Config/DefaultInput.ini +++ b/Config/DefaultInput.ini @@ -78,6 +78,8 @@ DefaultViewportMouseLockMode=LockOnCapture FOVScale=0.011110 DoubleClickTime=0.200000 +ActionMappings=(ActionName="MyAction",bShift=False,bCtrl=False,bAlt=False,bCmd=False,Key=LeftMouseButton) ++AxisMappings=(AxisName="MoveForward",Scale=1.000000,Key=W) ++AxisMappings=(AxisName="MoveForward",Scale=-1.000000,Key=S) DefaultPlayerInputClass=/Script/Engine.PlayerInput DefaultInputComponentClass=/Script/Engine.InputComponent DefaultTouchInterface=/Engine/MobileResources/HUD/DefaultVirtualJoysticks.DefaultVirtualJoysticks diff --git a/Content/BP_MyPlayerController.uasset b/Content/BP_MyPlayerController.uasset index 42ec990..3006c01 100644 Binary files a/Content/BP_MyPlayerController.uasset and b/Content/BP_MyPlayerController.uasset differ diff --git a/Content/BattleField/BattleFieldMap.umap b/Content/BattleField/BattleFieldMap.umap index 1a419bd..250219a 100644 Binary files a/Content/BattleField/BattleFieldMap.umap and b/Content/BattleField/BattleFieldMap.umap differ diff --git a/Content/MainMenu/BP_MainMenuGameMode.uasset b/Content/MainMenu/BP_MainMenuGameMode.uasset new file mode 100644 index 0000000..0f7a079 Binary files /dev/null and b/Content/MainMenu/BP_MainMenuGameMode.uasset differ diff --git a/Content/MainMenu/BP_MainMenuPlayerController.uasset b/Content/MainMenu/BP_MainMenuPlayerController.uasset new file mode 100644 index 0000000..4a59f6f Binary files /dev/null and b/Content/MainMenu/BP_MainMenuPlayerController.uasset differ diff --git a/Content/MainMenu/BP_ManageSquad_TrooperItem.uasset b/Content/MainMenu/BP_ManageSquad_TrooperItem.uasset deleted file mode 100644 index dd8d609..0000000 Binary files a/Content/MainMenu/BP_ManageSquad_TrooperItem.uasset and /dev/null differ diff --git a/Content/MainMenu/MainMenu.uasset b/Content/MainMenu/MainMenu.uasset index e515d16..8a95a1f 100644 Binary files a/Content/MainMenu/MainMenu.uasset and b/Content/MainMenu/MainMenu.uasset differ diff --git a/Content/MainMenu/MainMenuLevel.umap b/Content/MainMenu/MainMenuLevel.umap index 4c50f68..ec2d162 100644 Binary files a/Content/MainMenu/MainMenuLevel.umap and b/Content/MainMenu/MainMenuLevel.umap differ diff --git a/Content/MainMenu/ManageSquadWidget.uasset b/Content/MainMenu/ManageSquadWidget.uasset deleted file mode 100644 index 073d01e..0000000 Binary files a/Content/MainMenu/ManageSquadWidget.uasset and /dev/null differ diff --git a/Content/MainMenu/ManageSquad_TrooperEntry.uasset b/Content/MainMenu/ManageSquad_TrooperEntry.uasset deleted file mode 100644 index 1cf4bef..0000000 Binary files a/Content/MainMenu/ManageSquad_TrooperEntry.uasset and /dev/null differ diff --git a/Content/Troopers/BP_DefaultProjectile.uasset b/Content/Troopers/BP_DefaultProjectile.uasset deleted file mode 100644 index 6c90094..0000000 Binary files a/Content/Troopers/BP_DefaultProjectile.uasset and /dev/null differ diff --git a/Content/Troopers/BP_Trooper.uasset b/Content/Troopers/BP_Trooper.uasset index d47ed93..7b9e42d 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 deleted file mode 100644 index 09044c9..0000000 Binary files a/Content/Troopers/MyMyProjectile.uasset and /dev/null differ diff --git a/Content/Troopers/TrooperSkeletonMelee.uasset b/Content/Troopers/TrooperSkeletonMelee.uasset index 1496a7a..c8753e4 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 76c7053..7fb6aec 100644 Binary files a/Content/Troopers/TrooperWizard.uasset and b/Content/Troopers/TrooperWizard.uasset differ diff --git a/Content/Troopers/WBP_HealthBar.uasset b/Content/Troopers/WBP_HealthBar.uasset index 053eef5..2c2d067 100644 Binary files a/Content/Troopers/WBP_HealthBar.uasset and b/Content/Troopers/WBP_HealthBar.uasset differ diff --git a/Content/Troopers/projectiles/BP_DefaultProjectile.uasset b/Content/Troopers/projectiles/BP_DefaultProjectile.uasset new file mode 100644 index 0000000..18875aa Binary files /dev/null and b/Content/Troopers/projectiles/BP_DefaultProjectile.uasset differ diff --git a/Content/Troopers/projectiles/BP_Fireball.uasset b/Content/Troopers/projectiles/BP_Fireball.uasset new file mode 100644 index 0000000..3a5feb6 Binary files /dev/null and b/Content/Troopers/projectiles/BP_Fireball.uasset differ diff --git a/Content/Troopers/projectiles/BP_MyExplosion.uasset b/Content/Troopers/projectiles/BP_MyExplosion.uasset new file mode 100644 index 0000000..06ea15c Binary files /dev/null and b/Content/Troopers/projectiles/BP_MyExplosion.uasset differ diff --git a/Content/Troopers/projectiles/Materials/Fire_Material.uasset b/Content/Troopers/projectiles/Materials/Fire_Material.uasset new file mode 100644 index 0000000..86dede3 Binary files /dev/null and b/Content/Troopers/projectiles/Materials/Fire_Material.uasset differ diff --git a/Content/Troopers/projectiles/MyMyExplosion.uasset b/Content/Troopers/projectiles/MyMyExplosion.uasset new file mode 100644 index 0000000..52cfe7a Binary files /dev/null and b/Content/Troopers/projectiles/MyMyExplosion.uasset differ diff --git a/Source/TurnBasedTutorial/MainMenuPlayerController.cpp b/Source/TurnBasedTutorial/MainMenuPlayerController.cpp new file mode 100644 index 0000000..02ca458 --- /dev/null +++ b/Source/TurnBasedTutorial/MainMenuPlayerController.cpp @@ -0,0 +1,13 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "MainMenuPlayerController.h" +#include "Blueprint/UserWidget.h" + +void AMainMenuPlayerController::BeginPlay() { + Super::BeginPlay(); + SetShowMouseCursor(true); + UUserWidget *CreatedWidget = CreateWidget( + GetWorld(), WidgetClass); + CreatedWidget->AddToViewport(); +} diff --git a/Source/TurnBasedTutorial/MainMenuPlayerController.h b/Source/TurnBasedTutorial/MainMenuPlayerController.h new file mode 100644 index 0000000..8ad88e6 --- /dev/null +++ b/Source/TurnBasedTutorial/MainMenuPlayerController.h @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/PlayerController.h" +#include "MainMenuPlayerController.generated.h" + +/** + * + */ +UCLASS() +class TURNBASEDTUTORIAL_API + AMainMenuPlayerController : public APlayerController { + GENERATED_BODY() + + virtual void BeginPlay() override; + +protected: + UPROPERTY(EditAnywhere) + TSubclassOf WidgetClass; +}; diff --git a/Source/TurnBasedTutorial/MyExplosion.cpp b/Source/TurnBasedTutorial/MyExplosion.cpp new file mode 100644 index 0000000..4d3caf1 --- /dev/null +++ b/Source/TurnBasedTutorial/MyExplosion.cpp @@ -0,0 +1,68 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "MyExplosion.h" + +#include "Trooper.h" +#include "Components/SphereComponent.h" +#include "Net/UnrealNetwork.h" +#include "Particles/ParticleSystemComponent.h" + +AMyExplosion::AMyExplosion() { + // if (!CollisionComponent) { + // CollisionComponent = CreateDefaultSubobject( + // TEXT("SphereComponent")); + // RootComponent = CollisionComponent; + // } + if (!ParticleSystemComponent) { + ParticleSystemComponent = CreateDefaultSubobject< + UParticleSystemComponent>( + TEXT("ParticleSystemComponent")); + RootComponent = ParticleSystemComponent; + } + InitialLifeSpan = 1.0f; +} + +void AMyExplosion::Initialize(float damage, + float splashRadius, + uint8 playerIndex) { + Damage = damage; + PlayerIndex = playerIndex; + float Scale = splashRadius / 50; + // CollisionComponent->SetWorldScale3D({Scale, Scale, Scale}); + if (ParticleSystemComponent && ParticleSystemComponent->IsValidLowLevel()) { + ParticleSystemComponent->SetWorldScale3D({Scale, Scale, Scale}); + } +} + +void AMyExplosion::BeginPlay() { + Super::BeginPlay(); +} + +void AMyExplosion::NotifyActorBeginOverlap(AActor *OtherActor) { + Super::NotifyActorBeginOverlap(OtherActor); + ATrooper *OtherTrooper = Cast(OtherActor); + if (OtherTrooper) { + UE_LOG(LogTemp, Warning, + TEXT( + "Begin explosion 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 AMyExplosion::GetLifetimeReplicatedProps( + TArray &OutLifetimeProps) const { + Super::GetLifetimeReplicatedProps(OutLifetimeProps); + DOREPLIFETIME(AMyExplosion, Damage); + DOREPLIFETIME(AMyExplosion, PlayerIndex); + // DOREPLIFETIME(AMyExplosion, CollisionComponent); + DOREPLIFETIME(AMyExplosion, ParticleSystemComponent); +} diff --git a/Source/TurnBasedTutorial/MyExplosion.h b/Source/TurnBasedTutorial/MyExplosion.h new file mode 100644 index 0000000..535cf0f --- /dev/null +++ b/Source/TurnBasedTutorial/MyExplosion.h @@ -0,0 +1,37 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "Components/SphereComponent.h" +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "MyExplosion.generated.h" + +UCLASS() +class TURNBASEDTUTORIAL_API AMyExplosion : public AActor { + GENERATED_BODY() + +public: + AMyExplosion(); + + void Initialize(float damage, + float splashRadius, + uint8 playerIndex); + +protected: + virtual void BeginPlay() override; + + virtual void NotifyActorBeginOverlap(AActor *OtherActor) override; + + UPROPERTY(Replicated) + float Damage; + + UPROPERTY(Replicated) + int8 PlayerIndex = -1; + + // UPROPERTY(EditAnywhere, Replicated) + // USphereComponent *CollisionComponent; + + UPROPERTY(EditAnywhere, Replicated) + UParticleSystemComponent *ParticleSystemComponent; +}; diff --git a/Source/TurnBasedTutorial/MyGameInstanceSubsystem.cpp b/Source/TurnBasedTutorial/MyGameInstanceSubsystem.cpp index e0b684f..4f8f813 100644 --- a/Source/TurnBasedTutorial/MyGameInstanceSubsystem.cpp +++ b/Source/TurnBasedTutorial/MyGameInstanceSubsystem.cpp @@ -238,7 +238,7 @@ void UMyGameInstanceSubsystem::FindSessions(int32 MaxSearchResults, bool bIsLANQ LastSessionSearch->QuerySettings.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals); const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController(); - if (!SessionInterface->FindSessions(*LocalPlayer->GetPreferredUniqueNetId(), LastSessionSearch.ToSharedRef()) + if (!SessionInterface->FindSessions(*LocalPlayer->GetPreferredUniqueNetId(), LastSessionSearch.ToSharedRef())) { SessionInterface->ClearOnFindSessionsCompleteDelegate_Handle(FindSessionsCompleteDelegateHandle); diff --git a/Source/TurnBasedTutorial/MyGameState.cpp b/Source/TurnBasedTutorial/MyGameState.cpp index c66124d..e219a74 100644 --- a/Source/TurnBasedTutorial/MyGameState.cpp +++ b/Source/TurnBasedTutorial/MyGameState.cpp @@ -12,24 +12,23 @@ auto AMyGameState::GetMyPlayerState(uint8 PlayerIndex) const { void AMyGameState::BeginPlay() { Super::BeginPlay(); + LivingTroopers.SetNum(2); } void AMyGameState::AddTrooper_Implementation(ATrooper *Trooper) { + if (Trooper->GetPlayerIndex() >= 0 && Trooper->GetPlayerIndex() <= LivingTroopers.Num()) { + LivingTroopers[Trooper->GetPlayerIndex()]++; + } Troopers.Add(Trooper); } -void AMyGameState::StartGame_Implementation() const { - PlayerNotInTurn()->SetEnemySelection(Troopers); - PlayerInTurn()->SetEnemySelection(Troopers); +void AMyGameState::StartGame_Implementation() { + PlayerNotInTurn()->SetEnemySelection(); + PlayerInTurn()->SetEnemySelection(); + bGameStarted = true; PlayerInTurn()->StartTurn(); } -// void AMyGameState::StartGame() const { -// PlayerNotInTurn()->SetEnemySelection(Troopers); -// PlayerInTurn()->SetEnemySelection(Troopers); -// PlayerInTurn()->StartTurn(); -// } - void AMyGameState::CycleTurns_Implementation() { PlayerInTurn()->EndTurn(); for (const auto Trooper : Troopers) { @@ -70,9 +69,25 @@ bool AMyGameState::IsInTurn(uint8 PlayerIndex) const { return PlayerIndex == CurrentPlayerTurn; } +bool AMyGameState::IsGameStarted() const { + return bGameStarted; +} + +void AMyGameState::DecreaseLivingTroopers(int PlayerIndex) { + if (bGameIsOver) + return; + LivingTroopers[PlayerIndex]--; + if (LivingTroopers[PlayerIndex] <= 0) { + UE_LOG(LogTemp, Warning, TEXT("Player %d lose!"), PlayerIndex); + bGameIsOver = true; + } +} + + void AMyGameState::GetLifetimeReplicatedProps( TArray &OutLifetimeProps) const { Super::GetLifetimeReplicatedProps(OutLifetimeProps); DOREPLIFETIME(AMyGameState, Troopers); DOREPLIFETIME(AMyGameState, CurrentPlayerTurn); + DOREPLIFETIME(AMyGameState, bGameStarted); } diff --git a/Source/TurnBasedTutorial/MyGameState.h b/Source/TurnBasedTutorial/MyGameState.h index fbbaf1e..1b4bf8a 100644 --- a/Source/TurnBasedTutorial/MyGameState.h +++ b/Source/TurnBasedTutorial/MyGameState.h @@ -21,7 +21,7 @@ public: void AddTrooper(ATrooper *Trooper); UFUNCTION(Server, Reliable) - void StartGame() const; + void StartGame(); UFUNCTION(BlueprintCallable, Server, Reliable) void CycleTurns(); @@ -38,10 +38,25 @@ public: UFUNCTION() bool IsInTurn(uint8 PlayerIndex) const; + UFUNCTION() + bool IsGameStarted() const; + + UFUNCTION() + void DecreaseLivingTroopers(int PlayerIndex); + private: + UPROPERTY(Replicated) + bool bGameIsOver = false; + UPROPERTY(Replicated) TArray Troopers; + UPROPERTY(Replicated) + TArray LivingTroopers; + + UPROPERTY(Replicated) + bool bGameStarted = false; + UPROPERTY(Replicated) uint8 CurrentPlayerTurn{0}; diff --git a/Source/TurnBasedTutorial/MyPawn.cpp b/Source/TurnBasedTutorial/MyPawn.cpp index 0895d91..22cccff 100644 --- a/Source/TurnBasedTutorial/MyPawn.cpp +++ b/Source/TurnBasedTutorial/MyPawn.cpp @@ -15,6 +15,20 @@ void AMyPawn::BeginPlay() { Super::BeginPlay(); } +void AMyPawn::MoveForward(float Val) { + if (Val != 0.f) + { + if (Controller) + { + FRotator ControlSpaceRot = Controller->GetControlRotation(); + ControlSpaceRot.Pitch = 0; + + // transform to world space and add it + AddMovementInput( FRotationMatrix(ControlSpaceRot).GetScaledAxis( EAxis::X ), Val ); + } + } +} + // Called every frame void AMyPawn::Tick(float DeltaTime) { Super::Tick(DeltaTime); diff --git a/Source/TurnBasedTutorial/MyPawn.h b/Source/TurnBasedTutorial/MyPawn.h index 04a4157..ad9b445 100644 --- a/Source/TurnBasedTutorial/MyPawn.h +++ b/Source/TurnBasedTutorial/MyPawn.h @@ -19,6 +19,8 @@ protected: // Called when the game starts or when spawned virtual void BeginPlay() override; + virtual void MoveForward(float Val) override; + public: // Called every frame virtual void Tick(float DeltaTime) override; diff --git a/Source/TurnBasedTutorial/MyPlayerController.cpp b/Source/TurnBasedTutorial/MyPlayerController.cpp index cf74f71..3f7332b 100644 --- a/Source/TurnBasedTutorial/MyPlayerController.cpp +++ b/Source/TurnBasedTutorial/MyPlayerController.cpp @@ -5,6 +5,7 @@ #include "MyGameMode.h" #include "MyGameState.h" #include "MyPlayerState.h" +#include "Blueprint/UserWidget.h" #include "Net/UnrealNetwork.h" AMyPlayerController::AMyPlayerController() @@ -13,6 +14,13 @@ AMyPlayerController::AMyPlayerController() SetShowMouseCursor(true); } +void AMyPlayerController::BeginPlay() { + Super::BeginPlay(); + UUserWidget *CreatedWidget = CreateWidget( + GetWorld(), WidgetClass); + CreatedWidget->AddToViewport(); +} + void AMyPlayerController::SetupInputComponent() { Super::SetupInputComponent(); InputComponent->BindAction("MyAction", IE_Pressed, this, @@ -129,7 +137,7 @@ void AMyPlayerController::EndTurn_Implementation() { void AMyPlayerController::SetPlayerIndex(uint8 NewPlayerIndex) { PlayerIndex = NewPlayerIndex; - + GetMyPlayerState()->SetPlayerIndex(NewPlayerIndex); // GetMyPlayerState()->PlayerIndex = NewPlayerIndex; } diff --git a/Source/TurnBasedTutorial/MyPlayerController.h b/Source/TurnBasedTutorial/MyPlayerController.h index 006d25d..9b962e7 100644 --- a/Source/TurnBasedTutorial/MyPlayerController.h +++ b/Source/TurnBasedTutorial/MyPlayerController.h @@ -12,6 +12,8 @@ class TURNBASEDTUTORIAL_API AMyPlayerController : public APlayerController { GENERATED_BODY() public: + virtual void BeginPlay() override; + // FOnMyTurnChangedDelegate OnMyTurnChanged; virtual void SetupInputComponent() override; @@ -49,6 +51,9 @@ public: // void SetEnemySelection(const TArray &Troopers) const; private: + UPROPERTY(EditAnywhere) + TSubclassOf WidgetClass; + // UPROPERTY(Replicated) // bool bIsMyTurn; // diff --git a/Source/TurnBasedTutorial/MyPlayerState.cpp b/Source/TurnBasedTutorial/MyPlayerState.cpp index 5b8bfd7..179fbff 100644 --- a/Source/TurnBasedTutorial/MyPlayerState.cpp +++ b/Source/TurnBasedTutorial/MyPlayerState.cpp @@ -4,10 +4,12 @@ #include "MyPlayerState.h" #include "MyGameState.h" +#include "Kismet/GameplayStatics.h" #include "Net/UnrealNetwork.h" AMyPlayerState::AMyPlayerState() : Super(), bIsMyTurn(false), SelectedTrooper(nullptr) { + // PrimaryActorTick.bCanEverTick = true; } void AMyPlayerState::BeginPlay() { @@ -18,15 +20,35 @@ auto AMyPlayerState::GetMyGameState() const { return Cast(GetWorld()->GetGameState()); } +// void AMyPlayerState::Tick(float DeltaSeconds) { +// Super::Tick(DeltaSeconds); +// if (GetMyGameState() && GetMyGameState()->IsGameStarted()) { +// // for (const auto Actor : Troopers) { +// // const auto Trooper = Cast(Actor); +// // if (Trooper != nullptr && Trooper->GetPlayerIndex() != +// // PlayerIndex) { +// // Trooper->HighlightAsEnemy(PlayerIndex); +// // } +// // } +// bIsSelectionInitialized = true; +// SetActorTickEnabled(false); +// } +// } + void AMyPlayerState::SetPlayerIndex(uint8 NewPlayerIndex) { PlayerIndex = NewPlayerIndex; } void AMyPlayerState::SetEnemySelection_Implementation( - const TArray &Troopers) const { - for (const auto Trooper : Troopers) { - if (Trooper != nullptr && Trooper->GetPlayerIndex() != PlayerIndex) { - Trooper->HighlightAsEnemy(); + /*const TArray &Troopers*/) const { + TArray Troopers; + UGameplayStatics::GetAllActorsOfClass(GetWorld(), + ATrooper::StaticClass(), + Troopers); + for (const auto Actor : Troopers) { + const auto Trooper = Cast(Actor); + if (Trooper != nullptr) { + Trooper->HighlightAsEnemy(PlayerIndex); } } } @@ -60,7 +82,8 @@ void AMyPlayerState::MoveTrooper_Implementation(ATrooper *Trooper, void AMyPlayerState::Attack_Implementation(ATrooper *Attacker, FVector Location, int ActionIndex, - const TArray &Troopers) { + const TArray & + Troopers) { if (Attacker->CheckAttackCorrectness(Location, ActionIndex)) { Attacker->Attack(ActionIndex, Location); // for (const auto Trooper : Troopers) { @@ -96,7 +119,6 @@ void AMyPlayerState::SetMyTurn(bool bMyTurn) { } } - void AMyPlayerState::StartTurn_Implementation() { SetMyTurn(true); UE_LOG(LogTemp, Warning, TEXT("Your turn, %d"), PlayerIndex); @@ -104,7 +126,8 @@ void AMyPlayerState::StartTurn_Implementation() { void AMyPlayerState::EndTurn_Implementation() { if (bIsMyTurn) { - UE_LOG(LogTemp, Warning, TEXT("End Turn from player %d"), PlayerIndex); + UE_LOG(LogTemp, Warning, TEXT("End Turn from player %d"), + PlayerIndex); SetMyTurn(false); if (SelectedTrooper) { SelectedTrooper->SetSelection(false, CurrentAction); @@ -117,7 +140,6 @@ void AMyPlayerState::EndTurn_Implementation() { } } - void AMyPlayerState::OnPlayerAction(const FHitResult &HitResult) { auto const NewlySelectedLocation = HitResult.Location; ATrooper *NewlySelectedTrooper = Cast( @@ -132,7 +154,8 @@ void AMyPlayerState::OnPlayerAction(const FHitResult &HitResult) { if (NewlySelectedTrooper == nullptr || !NewlySelectedTrooper-> IsValidLowLevel() || NewlySelectedTrooper->GetPlayerIndex() != PlayerIndex) { - if (SelectedTrooper != nullptr && SelectedTrooper->IsValidLowLevel()) { + if (SelectedTrooper != nullptr && SelectedTrooper-> + IsValidLowLevel()) { switch (CurrentAction) { case 0: UE_LOG(LogTemp, Warning, TEXT("Do move")); @@ -153,7 +176,8 @@ void AMyPlayerState::OnPlayerAction(const FHitResult &HitResult) { } } } else if (NewlySelectedTrooper != nullptr && NewlySelectedTrooper-> - IsValidLowLevel() && NewlySelectedTrooper->GetPlayerIndex() == + IsValidLowLevel() && NewlySelectedTrooper->GetPlayerIndex() + == PlayerIndex) { UE_LOG(LogTemp, Warning, TEXT("Do reselect")); // our move, selection @@ -170,11 +194,11 @@ void AMyPlayerState::SetCurrentAction_Implementation(int Action) { if (SelectedTrooper) { SelectedTrooper->UpdateSelectionRadius(Action); } - UE_LOG(LogTemp, Warning, TEXT("SetCurrentAction: %d on Player Controller " + UE_LOG(LogTemp, Warning, + TEXT("SetCurrentAction: %d on Player Controller " "with index %d"), CurrentAction, PlayerIndex); } - uint8 AMyPlayerState::GetPlayerIndex() const { return PlayerIndex; } @@ -186,4 +210,5 @@ void AMyPlayerState::GetLifetimeReplicatedProps( DOREPLIFETIME(AMyPlayerState, CurrentAction); DOREPLIFETIME(AMyPlayerState, bIsMyTurn); DOREPLIFETIME(AMyPlayerState, SelectedTrooper); + DOREPLIFETIME(AMyPlayerState, bIsSelectionInitialized); } diff --git a/Source/TurnBasedTutorial/MyPlayerState.h b/Source/TurnBasedTutorial/MyPlayerState.h index b650430..a3beef1 100644 --- a/Source/TurnBasedTutorial/MyPlayerState.h +++ b/Source/TurnBasedTutorial/MyPlayerState.h @@ -19,6 +19,8 @@ public: virtual void BeginPlay() override; + // virtual void Tick(float DeltaSeconds) override; + UFUNCTION(Client, Reliable) void StartTurn(); @@ -53,10 +55,11 @@ public: void SetPlayerIndex(uint8 NewPlayerIndex); UFUNCTION(Client, Reliable) - void SetEnemySelection(const TArray &Troopers) const; - + void SetEnemySelection(/*const TArray &Troopers*/) const; private: + UPROPERTY(Replicated) + bool bIsSelectionInitialized = false; UPROPERTY(Replicated) uint8 PlayerIndex; diff --git a/Source/TurnBasedTutorial/MyProjectile.cpp b/Source/TurnBasedTutorial/MyProjectile.cpp index d73cedb..301ea77 100644 --- a/Source/TurnBasedTutorial/MyProjectile.cpp +++ b/Source/TurnBasedTutorial/MyProjectile.cpp @@ -47,6 +47,7 @@ void AMyProjectile::Initialize(const UAbility *Ability, ProjectileMovementComponent->InitialSpeed = ProjectileMovementComponent->MaxSpeed = Ability->Speed; Damage = Ability->Damage; + SplashRadius = Ability->SplashRadius; float Scale = Ability->LinearWidth / 100; // CollisionComponent->SetSphereRadius(Ability->LinearWidth / 2); ProjectileMeshComponent->SetWorldScale3D({Scale, Scale, Scale}); @@ -77,38 +78,55 @@ void AMyProjectile::NotifyActorBeginOverlap(AActor *OtherActor) { } } -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::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(); } +void AMyProjectile::EndPlay(const EEndPlayReason::Type EndPlayReason) { + Super::EndPlay(EndPlayReason); + Explode(); +} + +void AMyProjectile::Explode_Implementation() const { + const FTransform SpawnTransform = GetTransform(); + FActorSpawnParameters SpawnParameters; + SpawnParameters.Instigator = GetInstigator(); + SpawnParameters.SpawnCollisionHandlingOverride = + ESpawnActorCollisionHandlingMethod::AlwaysSpawn; + AMyExplosion *Explosion = GetWorld()->SpawnActor( + ExplosionSubclass, SpawnTransform, SpawnParameters); + Explosion->Initialize(Damage, SplashRadius, PlayerIndex); + Explosion->SetActorLocation(GetActorLocation()); +} + void AMyProjectile::GetLifetimeReplicatedProps( TArray &OutLifetimeProps) const { Super::GetLifetimeReplicatedProps(OutLifetimeProps); @@ -117,4 +135,5 @@ void AMyProjectile::GetLifetimeReplicatedProps( // DOREPLIFETIME(AMyProjectile, CollisionComponent); DOREPLIFETIME(AMyProjectile, ProjectileMeshComponent); DOREPLIFETIME(AMyProjectile, ProjectileMovementComponent); + DOREPLIFETIME(AMyProjectile, SplashRadius); } diff --git a/Source/TurnBasedTutorial/MyProjectile.h b/Source/TurnBasedTutorial/MyProjectile.h index 612001c..bfcc820 100644 --- a/Source/TurnBasedTutorial/MyProjectile.h +++ b/Source/TurnBasedTutorial/MyProjectile.h @@ -4,6 +4,7 @@ #include "CoreMinimal.h" #include "Ability.h" +#include "MyExplosion.h" #include "Components/SphereComponent.h" #include "GameFramework/Actor.h" #include "GameFramework/ProjectileMovementComponent.h" @@ -24,15 +25,18 @@ public: protected: virtual void NotifyActorBeginOverlap(AActor *OtherActor) override; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TSubclassOf ExplosionSubclass; - virtual void NotifyHit(UPrimitiveComponent *MyComp, - AActor *Other, - UPrimitiveComponent *OtherComp, - bool bSelfMoved, - FVector HitLocation, - FVector HitNormal, - FVector NormalImpulse, - const FHitResult &Hit) 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; @@ -40,6 +44,9 @@ protected: UPROPERTY(Replicated) int8 PlayerIndex = -1; + UPROPERTY(Replicated) + float SplashRadius; + // UPROPERTY(EditAnywhere, Replicated) // USphereComponent *CollisionComponent; @@ -50,4 +57,9 @@ protected: UProjectileMovementComponent *ProjectileMovementComponent; virtual void BeginPlay() override; + + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + + UFUNCTION(Server, Reliable) + void Explode() const; }; diff --git a/Source/TurnBasedTutorial/Trooper.cpp b/Source/TurnBasedTutorial/Trooper.cpp index 8e4d985..b560e27 100644 --- a/Source/TurnBasedTutorial/Trooper.cpp +++ b/Source/TurnBasedTutorial/Trooper.cpp @@ -2,6 +2,7 @@ #include #include "HealthBar.h" +#include "MyGameState.h" #include "MyPlayerController.h" #include "MyPlayerState.h" #include "MyProjectile.h" @@ -113,22 +114,22 @@ void ATrooper::Tick(float const DeltaTime) { } } -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::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) { +void ATrooper::MoveTrooper_Implementation(FVector const NewPos) { TargetLocation = NewPos; bIsMoving = true; ActionPoints -= (NewPos - CurrentLocation).Size() * MoveCost; @@ -158,7 +159,7 @@ void ATrooper::GetLifetimeReplicatedProps( DOREPLIFETIME(ATrooper, CurrentAbilityDestination); } -uint8 ATrooper::GetPlayerIndex() const { +int8 ATrooper::GetPlayerIndex() const { return PlayerIndex; } @@ -225,8 +226,10 @@ void ATrooper::UpdateSelectionRadius(uint8 ActionType) const { {radiusScale, radiusScale, 0.01f}); } -void ATrooper::HighlightAsEnemy_Implementation() const { - SelectionStaticMesh->SetVisibility(true); +void ATrooper::HighlightAsEnemy_Implementation(int8 Index) const { + if (PlayerIndex != Index) { + SelectionStaticMesh->SetVisibility(true); + } } void ATrooper::ResetActionPoints() { @@ -244,17 +247,18 @@ UAbility *ATrooper::GetAbility(int AbilityIndex) const { } } -bool ATrooper::TakeDamage(float Damage) { - if (bIsTakingDamage) { - return false; +void ATrooper::TakeDamage_Implementation(float Damage) { + if (bIsTakingDamage || bIsDead) { + return; } HitPoints = FMath::Max(0, HitPoints - Damage); if (HitPoints == 0) { bIsDead = true; - return true; + SetLifeSpan(DyingAnimationDuration); + GetWorld()->GetGameState()->DecreaseLivingTroopers(PlayerIndex); + } else { + bIsTakingDamage = true; } - bIsTakingDamage = true; - return false; } TSubclassOf ATrooper::GetProjectileClass( @@ -310,7 +314,7 @@ int ATrooper::GetAnimationValue() { return 0; } -void ATrooper::Attack(int AbilityIndex, FVector ToLocation) { +void ATrooper::Attack_Implementation(int AbilityIndex, FVector ToLocation) { bIsAttacking = true; bIsWaitingForFire = true; ActionPoints -= GetAbility(AbilityIndex)->ActionCost; diff --git a/Source/TurnBasedTutorial/Trooper.h b/Source/TurnBasedTutorial/Trooper.h index 6866ae4..0ca380f 100644 --- a/Source/TurnBasedTutorial/Trooper.h +++ b/Source/TurnBasedTutorial/Trooper.h @@ -18,9 +18,9 @@ public: uint8 const NewId); UFUNCTION() - uint8 GetPlayerIndex() const; + int8 GetPlayerIndex() const; - UFUNCTION() + UFUNCTION(Server, Reliable) void MoveTrooper(FVector const NewPos); UFUNCTION() @@ -38,7 +38,7 @@ public: UFUNCTION(BlueprintCallable) int GetAnimationValue(); - UFUNCTION() + UFUNCTION(Server, Reliable) void Attack(int AbilityIndex, FVector ToLocation); UFUNCTION() @@ -57,16 +57,16 @@ public: void UpdateSelectionRadius(uint8 ActionType) const; UFUNCTION(Client, Reliable) - void HighlightAsEnemy() const; - + void HighlightAsEnemy(int8 Index) const; + UFUNCTION() void ResetActionPoints(); UFUNCTION() UAbility *GetAbility(int AbilityIndex) const; - UFUNCTION() - bool TakeDamage(float Damage); + UFUNCTION(Server, Reliable) + void TakeDamage(float Damage); protected: constexpr static float PIXELS_IN_RADIUS = 50; @@ -139,6 +139,8 @@ protected: float TakingDamagePlayedTime; const float TakingDamageDuration = 1.46667f; + + const float DyingAnimationDuration = 2.83333f; UPROPERTY(Replicated) bool bIsDead = false; @@ -160,11 +162,11 @@ protected: // const TCHAR *MeshPath = nullptr; - UFUNCTION() - void OnRepNotify_PlayerIndex() const; + // UFUNCTION() + // void OnRepNotify_PlayerIndex() const; - UPROPERTY(ReplicatedUsing = OnRepNotify_PlayerIndex) - uint8 PlayerIndex = -1; + UPROPERTY(Replicated/*Using = OnRepNotify_PlayerIndex*/) + int8 PlayerIndex = -1; UPROPERTY(Replicated) uint8 Id; diff --git a/TurnBased.sln.DotSettings.user b/TurnBased.sln.DotSettings.user new file mode 100644 index 0000000..f591ba1 --- /dev/null +++ b/TurnBased.sln.DotSettings.user @@ -0,0 +1,2 @@ + + INFO \ No newline at end of file diff --git a/WindowsNoEditor/Manifest_NonUFSFiles_Win64.txt b/WindowsNoEditor/Manifest_NonUFSFiles_Win64.txt new file mode 100644 index 0000000..f1f2447 --- /dev/null +++ b/WindowsNoEditor/Manifest_NonUFSFiles_Win64.txt @@ -0,0 +1,25 @@ +TurnBased/Binaries/Win64/TurnBasedTutorial.exe 2023-03-16T03:05:02.259Z +TurnBased/Binaries/Win64/OpenImageDenoise.dll 2023-03-16T01:52:15.842Z +TurnBased/Binaries/Win64/tbb12.dll 2023-03-16T01:52:15.844Z +Engine/Extras/Redist/en-us/UE4PrereqSetup_x64.exe 2023-03-16T01:46:38.646Z +Engine/Binaries/ThirdParty/Oculus/OVRPlugin/OVRPlugin/Win64/OVRPlugin.dll 2023-03-16T01:41:33.496Z +Engine/Binaries/ThirdParty/DbgHelp/dbghelp.dll 2023-03-16T01:41:25.090Z +Engine/Binaries/ThirdParty/PhysX3/Win64/VS2015/PxFoundationPROFILE_x64.dll 2023-03-16T01:41:46.155Z +Engine/Binaries/ThirdParty/PhysX3/Win64/VS2015/PxPvdSDKPROFILE_x64.dll 2023-03-16T01:41:46.339Z +Engine/Binaries/ThirdParty/PhysX3/Win64/VS2015/PhysX3PROFILE_x64.dll 2023-03-16T01:41:45.025Z +Engine/Binaries/ThirdParty/PhysX3/Win64/VS2015/PhysX3CookingPROFILE_x64.dll 2023-03-16T01:41:45.005Z +Engine/Binaries/ThirdParty/PhysX3/Win64/VS2015/PhysX3CommonPROFILE_x64.dll 2023-03-16T01:41:44.869Z +Engine/Binaries/ThirdParty/PhysX3/Win64/VS2015/APEX_ClothingPROFILE_x64.dll 2023-03-16T01:41:41.229Z +Engine/Binaries/ThirdParty/PhysX3/Win64/VS2015/APEX_LegacyPROFILE_x64.dll 2023-03-16T01:41:42.482Z +Engine/Binaries/ThirdParty/PhysX3/Win64/VS2015/ApexFrameworkPROFILE_x64.dll 2023-03-16T01:41:43.065Z +Engine/Binaries/ThirdParty/PhysX3/Win64/VS2015/NvClothPROFILE_x64.dll 2023-03-16T01:41:43.666Z +Engine/Binaries/ThirdParty/Ogg/Win64/VS2015/libogg_64.dll 2023-03-16T01:41:33.497Z +Engine/Binaries/ThirdParty/Vorbis/Win64/VS2015/libvorbis_64.dll 2023-03-16T01:41:53.464Z +Engine/Binaries/ThirdParty/Vorbis/Win64/VS2015/libvorbisfile_64.dll 2023-03-16T01:41:53.464Z +Engine/Binaries/ThirdParty/NVIDIA/NVaftermath/Win64/GFSDK_Aftermath_Lib.x64.dll 2023-03-16T01:41:32.651Z +Engine/Binaries/ThirdParty/OpenXR/win64/openxr_loader.dll 2023-03-16T01:41:33.921Z +Engine/Binaries/ThirdParty/OpenVR/OpenVRv1_5_17/Win64/openvr_api.dll 2023-03-16T01:41:33.917Z +Engine/Binaries/ThirdParty/NVIDIA/GeForceNOW/Win64/GfnRuntimeSdk.dll 2023-03-16T01:41:32.648Z +Engine/Binaries/ThirdParty/Windows/WinPixEventRuntime/x64/WinPixEventRuntime.dll 2023-03-16T01:41:53.487Z +Engine/Binaries/ThirdParty/Windows/XAudio2_9/x64/xaudio2_9redist.dll 2023-03-16T01:41:54.149Z +TurnBasedTutorial.exe 2023-03-16T03:07:14.267Z diff --git a/WindowsNoEditor/TurnBased/Content/Paks/TurnBased-WindowsNoEditor.pak b/WindowsNoEditor/TurnBased/Content/Paks/TurnBased-WindowsNoEditor.pak new file mode 100644 index 0000000..549883f Binary files /dev/null and b/WindowsNoEditor/TurnBased/Content/Paks/TurnBased-WindowsNoEditor.pak differ