added some ui and logic, but right now have troubles with replication

pull/6/head
m4xxx1m 2 years ago
parent 7816cf735f
commit 24279b7255

Binary file not shown.

@ -0,0 +1,22 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "Ability.h"
// Sets default values for this component's properties
UAbility::UAbility() {
PrimaryComponentTick.bCanEverTick = false;
}
// Called when the game starts
void UAbility::BeginPlay() {
Super::BeginPlay();
}
// void UAbility::TickComponent(float DeltaTime,
// ELevelTick TickType,
// FActorComponentTickFunction *ThisTickFunction) {
// Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
//
// }

@ -0,0 +1,41 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "Ability.generated.h"
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class TURNBASEDTUTORIAL_API UAbility : public UActorComponent {
GENERATED_BODY()
public:
// Sets default values for this component's properties
UAbility();
// Called when the game starts
virtual void BeginPlay() override;
UPROPERTY(EditAnywhere)
float ActionCost = 100.0f;
UPROPERTY(EditAnywhere)
float Damage = 50.0f;
UPROPERTY(EditAnywhere)
float ActionRadius = 1000.0f;
UPROPERTY(EditAnywhere)
float SplashRadius = 100.0f;
UPROPERTY(EditAnywhere)
float LinearWidth = 50.0f;
// Called every frame
// virtual void TickComponent(float DeltaTime,
// ELevelTick TickType,
// FActorComponentTickFunction *
// ThisTickFunction) override;
};

@ -0,0 +1,18 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "HealthBar.h"
#include "Components/ProgressBar.h"
void UHealthBar::SetOwnerTrooper(ATrooper *Trooper) {
OwnerTrooper = Trooper;
}
void UHealthBar::NativeTick(const FGeometry &MyGeometry, float InDeltaTime) {
Super::NativeTick(MyGeometry, InDeltaTime);
if (!OwnerTrooper.IsValid())
return;
HealthBar->SetPercent(OwnerTrooper->GetHitPoints() / OwnerTrooper->GetMaxHitPoints());
}

@ -0,0 +1,26 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Trooper.h"
#include "Blueprint/UserWidget.h"
#include "HealthBar.generated.h"
/**
*
*/
UCLASS(Abstract)
class TURNBASEDTUTORIAL_API UHealthBar : public UUserWidget {
GENERATED_BODY()
public:
void SetOwnerTrooper(ATrooper *Trooper);
protected:
TWeakObjectPtr<ATrooper> OwnerTrooper;
UPROPERTY(meta=(BindWidget))
class UProgressBar *HealthBar;
virtual void NativeTick(const FGeometry &MyGeometry, float InDeltaTime) override;
};

@ -17,6 +17,7 @@ void AMyGameMode::BeginPlay() {
Super::BeginPlay(); Super::BeginPlay();
} }
void AMyGameMode::InitializeBattleField() const { void AMyGameMode::InitializeBattleField() const {
UE_LOG(LogTemp, Warning, TEXT("InitializeBattleField")); UE_LOG(LogTemp, Warning, TEXT("InitializeBattleField"));
FVector Location(2000.0f, -1000.0f, 0.0f); FVector Location(2000.0f, -1000.0f, 0.0f);
@ -49,6 +50,7 @@ void AMyGameMode::InitializeBattleField() const {
0, Location, TrooperCount++); 0, Location, TrooperCount++);
Spawned->FinishSpawning(SpawnLocationAndRotation); Spawned->FinishSpawning(SpawnLocationAndRotation);
Spawned->SetActorLocation(Location); Spawned->SetActorLocation(Location);
Troopers.Add(dynamic_cast<ATrooper *>(Spawned));
Location += {0.f, 500.f, 0.0f}; Location += {0.f, 500.f, 0.0f};
} }
Location = {-2000.0f, -1000.0f, 0.0f}; Location = {-2000.0f, -1000.0f, 0.0f};
@ -64,10 +66,12 @@ void AMyGameMode::InitializeBattleField() const {
1, Location, TrooperCount++); 1, Location, TrooperCount++);
Spawned->FinishSpawning(SpawnLocationAndRotation); Spawned->FinishSpawning(SpawnLocationAndRotation);
Spawned->SetActorLocation(Location); Spawned->SetActorLocation(Location);
Troopers.Add(dynamic_cast<ATrooper *>(Spawned));
Location += {0.f, 500.f, 0.0f}; Location += {0.f, 500.f, 0.0f};
} }
} }
AActor *AMyGameMode::ChoosePlayerStart_Implementation(AController *Player) { AActor *AMyGameMode::ChoosePlayerStart_Implementation(AController *Player) {
UE_LOG(LogTemp, Warning, TEXT("GameMode ChoosePlayerStart %d"), UE_LOG(LogTemp, Warning, TEXT("GameMode ChoosePlayerStart %d"),
GetNumPlayers()); GetNumPlayers());
@ -111,6 +115,7 @@ void AMyGameMode::InitializeSpawnPointsIfNeeded(AController *Player) {
void AMyGameMode::PostLogin(APlayerController *NewPlayer) { void AMyGameMode::PostLogin(APlayerController *NewPlayer) {
Super::PostLogin(NewPlayer); Super::PostLogin(NewPlayer);
UE_LOG(LogTemp, Warning, TEXT("PostLogin")); UE_LOG(LogTemp, Warning, TEXT("PostLogin"));
// PlayerControllers.Add(dynamic_cast<AMyPlayerController *>(NewPlayer));
// const auto World = GetWorld(); // const auto World = GetWorld();
const auto CurrentNumberOfPlayers = GetNumPlayers(); const auto CurrentNumberOfPlayers = GetNumPlayers();
@ -121,6 +126,9 @@ void AMyGameMode::PostLogin(APlayerController *NewPlayer) {
if (CurrentNumberOfPlayers == 2) { if (CurrentNumberOfPlayers == 2) {
UE_LOG(LogTemp, Warning, TEXT("Game Start")); UE_LOG(LogTemp, Warning, TEXT("Game Start"));
// start the game // start the game
// dynamic_cast<AMyGameState *>(
// GetWorld()->GetGameState())->StartGame();
// InitializeBattleField();
StartGame(); StartGame();
} else { } else {
// delay the game // delay the game
@ -131,6 +139,10 @@ void AMyGameMode::PostLogin(APlayerController *NewPlayer) {
void AMyGameMode::StartGame() { void AMyGameMode::StartGame() {
InitializeBattleField(); InitializeBattleField();
// PlayerNotInTurn()->SetEnemySelection(Troopers);
// PlayerInTurn()->SetEnemySelection(Troopers);
// PlayerControllers[0]->SetEnemySelection(Troopers);
// PlayerControllers[1]->SetEnemySelection(Troopers);
PlayerInTurn()->StartTurn(); PlayerInTurn()->StartTurn();
} }
@ -140,22 +152,31 @@ AMyPlayerController *AMyGameMode::PlayerInTurn() const {
} }
AMyPlayerController *AMyGameMode::PlayerNotInTurn() const { AMyPlayerController *AMyGameMode::PlayerNotInTurn() const {
uint8 PlayerControllerIndexNotInTurn; // uint8 PlayerControllerIndexNotInTurn;
if (CurrentPlayerTurn == 0) { // if (CurrentPlayerTurn == 0) {
PlayerControllerIndexNotInTurn = 1; // PlayerControllerIndexNotInTurn = 1;
} else { // } else {
PlayerControllerIndexNotInTurn = 0; // PlayerControllerIndexNotInTurn = 0;
} // }
return GetMyPlayerController(PlayerControllerIndexNotInTurn); // return GetMyPlayerController(PlayerControllerIndexNotInTurn);
return GetMyPlayerController(!CurrentPlayerTurn);
} }
void AMyGameMode::CycleTurns() { void AMyGameMode::CycleTurns() {
PlayerInTurn()->EndTurn(); if (!this)
if (CurrentPlayerTurn == 0) { return;
CurrentPlayerTurn = 1; // PlayerInTurn()->EndTurn();
} else { for (const auto Trooper : Troopers) {
CurrentPlayerTurn = 0; if (Trooper != nullptr) {
} Trooper->ResetActionPoints();
}
}
CurrentPlayerTurn = !CurrentPlayerTurn;
// if (CurrentPlayerTurn == 0) {
// CurrentPlayerTurn = 1;
// } else {
// CurrentPlayerTurn = 0;
// }
PlayerInTurn()->StartTurn(); PlayerInTurn()->StartTurn();
} }

@ -23,6 +23,7 @@ public:
virtual void BeginPlay() override; virtual void BeginPlay() override;
UFUNCTION(BlueprintCallable) UFUNCTION(BlueprintCallable)
void CycleTurns(); void CycleTurns();
@ -34,7 +35,8 @@ private:
UPROPERTY() UPROPERTY()
TMap<uint8, AMyPlayerStart *> SpawnPoints{}; TMap<uint8, AMyPlayerStart *> SpawnPoints{};
AMyPlayerController *GetMyPlayerController(uint8 const PlayerIndex) const; UPROPERTY()
mutable TArray<ATrooper *> Troopers;
UFUNCTION(BlueprintCallable) UFUNCTION(BlueprintCallable)
void StartGame(); void StartGame();
@ -47,4 +49,7 @@ private:
UPROPERTY() UPROPERTY()
uint8 CurrentPlayerTurn{0}; uint8 CurrentPlayerTurn{0};
UFUNCTION()
AMyPlayerController *GetMyPlayerController(uint8 const PlayerIndex) const;
}; };

@ -1,8 +1,87 @@
// Fill out your copyright notice in the Description page of Project Settings. // Fill out your copyright notice in the Description page of Project Settings.
#include "MyGameState.h" #include "MyGameState.h"
// #include "MyPlayerController.h"
// #include "Trooper.h"
// #include "Kismet/GameplayStatics.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<const TCHAR *> bpPaths{
// TEXT(
// "Blueprint'/Game/Troopers/TrooperSkeletonMelee.TrooperSkeletonMelee_C'"
// ),
// TEXT("Blueprint'/Game/Troopers/TrooperWizard.TrooperWizard_C'")
// };
// TArray<UClass *> LoadedBpAssets;
// for (int i = 0; i < bpPaths.Num(); ++i) {
// TSoftClassPtr<ATrooper> ActorBpClass = TSoftClassPtr<ATrooper>(
// FSoftObjectPath(bpPaths[i])
// );
// LoadedBpAssets.Push(ActorBpClass.LoadSynchronous());
// }
//
// for (int i = 0; i < 5; ++i) {
// FTransform SpawnLocationAndRotation(Rotation);
// SpawnLocationAndRotation.SetLocation(Location);
// AActor *Spawned = GetWorld()->SpawnActorDeferred<ATrooper>(
// LoadedBpAssets[i % 2], SpawnLocationAndRotation);
// // AActor *Spawned = GetWorld()->SpawnActorDeferred<ATrooper>(
// // ATrooper::StaticClass(), SpawnLocationAndRotation);
// dynamic_cast<ATrooper *>(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<ATrooper>(
// LoadedBpAssets[i % 2], SpawnLocationAndRotation);
// // AActor *Spawned = GetWorld()->SpawnActorDeferred<ATrooper>(
// // ATrooper::StaticClass(), SpawnLocationAndRotation);
// dynamic_cast<ATrooper *>(Spawned)->Initialize(
// 1, Location, TrooperCount++);
// Spawned->FinishSpawning(SpawnLocationAndRotation);
// Spawned->SetActorLocation(Location);
// Location += {0.f, 500.f, 0.0f};
// }
// }
// AMyPlayerController *AMyGameState::GetMyPlayerController(
// uint8 const PlayerIndex) const {
// return dynamic_cast<AMyPlayerController *>(
// UGameplayStatics::GetPlayerController(GetWorld(), PlayerIndex));
// }
//
// void AMyGameState::StartGame() {
// // InitializeBattleField();
// PlayerInTurn()->StartTurn();
// }
//
// void AMyGameState::CycleTurns() {
// PlayerInTurn()->EndTurn();
// if (CurrentPlayerTurn == 0) {
// CurrentPlayerTurn = 1;
// } else {
// CurrentPlayerTurn = 0;
// }
// PlayerInTurn()->StartTurn();
// }
//
// AMyPlayerController *AMyGameState::PlayerInTurn() const {
// return GetMyPlayerController(CurrentPlayerTurn);
// }
//
// AMyPlayerController *AMyGameState::PlayerNotInTurn() const {
// return GetMyPlayerController(CurrentPlayerTurn == 0 ? 1 : 0);
// }

@ -10,11 +10,28 @@
* *
*/ */
UCLASS() UCLASS()
class TURNBASEDTUTORIAL_API AMyGameState : public AGameState class TURNBASEDTUTORIAL_API AMyGameState : public AGameState {
{
GENERATED_BODY() 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};
}; };

@ -8,6 +8,7 @@
AMyPlayerController::AMyPlayerController() AMyPlayerController::AMyPlayerController()
: Super(), bIsMyTurn(false), SelectedTrooper(nullptr) { : Super(), bIsMyTurn(false), SelectedTrooper(nullptr) {
UE_LOG(LogTemp, Warning, TEXT("Player controller created")); UE_LOG(LogTemp, Warning, TEXT("Player controller created"));
SetShowMouseCursor(true);
} }
void AMyPlayerController::SetupInputComponent() { void AMyPlayerController::SetupInputComponent() {
@ -32,22 +33,36 @@ void AMyPlayerController::StartTurn_Implementation() {
UE_LOG(LogTemp, Warning, TEXT("Your turn, %d"), PlayerIndex); UE_LOG(LogTemp, Warning, TEXT("Your turn, %d"), PlayerIndex);
} }
auto AMyPlayerController::GetMyGameMode() const {
return dynamic_cast<AMyGameMode *>(
UGameplayStatics::GetGameMode(GetWorld()));
}
void AMyPlayerController::EndTurn_Implementation() { void AMyPlayerController::EndTurn_Implementation() {
if (bIsMyTurn) {
UE_LOG(LogTemp, Warning, TEXT("End Turn from player %d"), PlayerIndex);
SetMyTurn(false); SetMyTurn(false);
if (SelectedTrooper) {
SelectedTrooper->SetSelection(false);
SelectedTrooper = nullptr;
}
UE_LOG(LogTemp, Warning, TEXT("Not your turn, %d"), PlayerIndex); UE_LOG(LogTemp, Warning, TEXT("Not your turn, %d"), PlayerIndex);
AMyGameMode *gameMode = GetMyGameMode();
gameMode->CycleTurns();
} }
auto AMyPlayerController::GetMyGameMode() const {
return dynamic_cast<AMyGameMode *>(
UGameplayStatics::GetGameMode(GetWorld()));
} }
// AMyGameState *AMyPlayerController::GetMyGameState() const {
// return dynamic_cast<AMyGameState *>(
// GetWorld()->GetGameState());
// }
void AMyPlayerController::MoveTrooper_Implementation( void AMyPlayerController::MoveTrooper_Implementation(
ATrooper *Trooper, ATrooper *Trooper,
FVector Location) { FVector Location) {
if (Trooper->CheckMoveCorrectness(Location)) { if (Trooper->CheckMoveCorrectness(Location)) {
Trooper->MoveTrooper(Location); Trooper->MoveTrooper(Location);
GetMyGameMode()->CycleTurns(); // GetMyGameMode()->CycleTurns();
} else { } else {
GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Red, GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Red,
FString::Printf( FString::Printf(
@ -55,33 +70,89 @@ void AMyPlayerController::MoveTrooper_Implementation(
} }
} }
void AMyPlayerController::AttackTrooper_Implementation( // void AMyPlayerController::AttackTrooper_Implementation(
ATrooper *Attacker, // ATrooper *Attacker,
ATrooper *Victim) { // ATrooper *Victim) {
if (Attacker->CheckAttackCorrectness(Victim->GetLocation())) { // if (Attacker->CheckAttackCorrectness(Victim->GetLocation())) {
Attacker->Attack(); // Attacker->Attack();
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, // // GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red,
FString::Printf( // // FString::Printf(
TEXT("ATTACK!! %d attacked %d"), // // TEXT("ATTACK!! %d attacked %d"),
Attacker->GetId(), // // Attacker->GetId(),
Victim->GetId())); // // Victim->GetId()));
GetMyGameMode()->CycleTurns(); // // GetMyGameMode()->CycleTurns();
// } else {
// GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red,
// FString::Printf(
// TEXT(
// "Attack failed! Out of attack radius!")));
// }
// }
void AMyPlayerController::Attack_Implementation(ATrooper *Attacker,
FVector Location,
int ActionIndex) {
if (Attacker && CurrentAction >= 1 && CurrentAction <= 2 &&
Attacker->CheckAttackCorrectness(Location, CurrentAction)) {
Attacker->Attack(CurrentAction);
} else { } else {
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, UE_LOG(LogTemp, Warning,
FString::Printf( TEXT("Out of radius or not enough Action Points"));
TEXT(
"Attack failed! Out of attack radius!")));
} }
} }
void AMyPlayerController::SetPlayerIndex(uint8 NewPlayerIndex) { void AMyPlayerController::SetPlayerIndex(uint8 NewPlayerIndex) {
PlayerIndex = NewPlayerIndex; 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;
}
void AMyPlayerController::SetEnemySelection_Implementation(
const TArray<ATrooper *> &Troopers) const {
for (const auto Trooper : Troopers) {
if (Trooper != nullptr && Trooper->GetPlayerIndex() != PlayerIndex) {
Trooper->HighlightAsEnemy();
}
}
}
// void AMyPlayerController::SetEnemySelection_Implementation() {
// if (!GetMyGameMode()) {
// UE_LOG(LogTemp, Warning, TEXT("Failed to get Game mode, Index: %d"), PlayerIndex);
// return;
// }
// const auto &Troopers = GetMyGameMode()->GetTroopers();
// for (const auto Trooper : Troopers) {
// if (Trooper != nullptr && Trooper->GetPlayerIndex() != PlayerIndex) {
// Trooper->HighlightAsEnemy();
// }
// }
// }
// void AMyPlayerController::SetEnemySelection(TArray<ATrooper *> &Troopers) const {
// for (const auto Trooper : Troopers) {
// if (Trooper->GetPlayerIndex() != PlayerIndex) {
// Trooper->HighlightAsEnemy();
// }
// }
// }
void AMyPlayerController::GetLifetimeReplicatedProps( void AMyPlayerController::GetLifetimeReplicatedProps(
TArray<FLifetimeProperty> &OutLifetimeProps) const { TArray<FLifetimeProperty> &OutLifetimeProps) const {
DOREPLIFETIME(AMyPlayerController, PlayerIndex); DOREPLIFETIME(AMyPlayerController, PlayerIndex);
DOREPLIFETIME(AMyPlayerController, CurrentAction);
DOREPLIFETIME(AMyPlayerController, bIsMyTurn);
DOREPLIFETIME(AMyPlayerController, SelectedTrooper);
} }
void AMyPlayerController::OnLeftMouseClick() { void AMyPlayerController::OnLeftMouseClick() {
@ -89,6 +160,7 @@ void AMyPlayerController::OnLeftMouseClick() {
return; return;
} }
UE_LOG(LogTemp, Warning, TEXT("Mouse clicked")); UE_LOG(LogTemp, Warning, TEXT("Mouse clicked"));
UE_LOG(LogTemp, Warning, TEXT("Current action: %d"), CurrentAction);
FHitResult HitResult; FHitResult HitResult;
bool const IsHitResult = GetHitResultUnderCursorForObjects( bool const IsHitResult = GetHitResultUnderCursorForObjects(
TArray<TEnumAsByte<EObjectTypeQuery>>{ObjectTypeQuery1}, false, TArray<TEnumAsByte<EObjectTypeQuery>>{ObjectTypeQuery1}, false,
@ -103,43 +175,97 @@ void AMyPlayerController::OnLeftMouseClick() {
ATrooper *NewlySelectedTrooper = dynamic_cast<ATrooper *>( ATrooper *NewlySelectedTrooper = dynamic_cast<ATrooper *>(
HitResult.GetActor()); HitResult.GetActor());
// skip re-selection
if (SelectedTrooper == NewlySelectedTrooper) {
UE_LOG(LogTemp, Warning, TEXT("Skip reselection"));
return;
}
if (NewlySelectedTrooper == nullptr || !NewlySelectedTrooper-> if (NewlySelectedTrooper == nullptr || !NewlySelectedTrooper->
IsValidLowLevel()) { IsValidLowLevel() || NewlySelectedTrooper->GetPlayerIndex() !=
PlayerIndex) {
// we selected something that is not a trooper (or trooper in shitty state...) // we selected something that is not a trooper (or trooper in shitty state...)
// probably we should move to it if we can... // probably we should move to it if we can...
UE_LOG(LogTemp, Warning, TEXT("Not a trooper")); // UE_LOG(LogTemp, Warning, TEXT("Not a trooper"));
// if initial trooper is valid... // if initial trooper is valid...
if (SelectedTrooper != nullptr && SelectedTrooper->IsValidLowLevel()) { if (SelectedTrooper != nullptr && SelectedTrooper->IsValidLowLevel()) {
switch (CurrentAction) {
case 0:
UE_LOG(LogTemp, Warning, TEXT("Do move")); UE_LOG(LogTemp, Warning, TEXT("Do move"));
// move this mf // move this mf
MoveTrooper(SelectedTrooper, NewlySelectedLocation); MoveTrooper(SelectedTrooper, NewlySelectedLocation);
// and reset the selection.... // 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; SelectedTrooper = nullptr;
break;
} }
return;
} }
UE_LOG(LogTemp, Warning, TEXT("New Selected Player Index %d"), } else if (NewlySelectedTrooper != nullptr && NewlySelectedTrooper->
NewlySelectedTrooper->GetPlayerIndex()); IsValidLowLevel() && NewlySelectedTrooper->GetPlayerIndex() ==
// skip re-selection PlayerIndex) {
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")); UE_LOG(LogTemp, Warning, TEXT("Do reselect"));
// our move, selection // our move, selection
if (SelectedTrooper) {
SelectedTrooper->SetSelection(false);
}
SelectedTrooper = NewlySelectedTrooper; SelectedTrooper = NewlySelectedTrooper;
} else { SelectedTrooper->SetSelection(true);
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;
} }
//
// 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->SetSelection(false);
// 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
// if (SelectedTrooper) {
// SelectedTrooper->SetSelection(false);
// }
// SelectedTrooper = NewlySelectedTrooper;
// SelectedTrooper->SetSelection(true);
// } 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->SetSelection(false);
// SelectedTrooper = nullptr;
// }
} }

@ -2,6 +2,7 @@
#pragma once #pragma once
#include "CoreMinimal.h" #include "CoreMinimal.h"
// #include "MyGameState.h"
#include "Trooper.h" #include "Trooper.h"
#include "GameFramework/PlayerController.h" #include "GameFramework/PlayerController.h"
#include "MyPlayerController.generated.h" #include "MyPlayerController.generated.h"
@ -22,25 +23,38 @@ public:
UFUNCTION(Client, Reliable) UFUNCTION(Client, Reliable)
void StartTurn(); void StartTurn();
UFUNCTION(Client, Reliable) UFUNCTION(Client, Reliable, BlueprintCallable)
void EndTurn(); void EndTurn();
UFUNCTION(Server, Reliable) UFUNCTION(Server, Reliable)
void MoveTrooper(ATrooper *Trooper, FVector Location); void MoveTrooper(ATrooper *Trooper, FVector Location);
// UFUNCTION(Server, Reliable)
// void AttackTrooper(ATrooper *Attacker, ATrooper *Victim);
UFUNCTION(Server, Reliable) UFUNCTION(Server, Reliable)
void AttackTrooper(ATrooper *Attacker, ATrooper *Victim); void Attack(ATrooper *Attacker, FVector Location, int ActionIndex);
UFUNCTION() UFUNCTION()
void SetPlayerIndex(uint8 NewPlayerIndex); void SetPlayerIndex(uint8 NewPlayerIndex);
UFUNCTION(BlueprintCallable)
float SetCurrentActionAndReturnRadius(int action);
UFUNCTION(Client, Reliable)
void SetEnemySelection(const TArray<ATrooper *> &Troopers) const;
private: private:
UPROPERTY(Replicated)
bool bIsMyTurn; bool bIsMyTurn;
UPROPERTY(Replicated)
int CurrentAction = 0;
UPROPERTY(Replicated) UPROPERTY(Replicated)
uint8 PlayerIndex; uint8 PlayerIndex;
UPROPERTY() UPROPERTY(Replicated)
ATrooper *SelectedTrooper; ATrooper *SelectedTrooper;
void OnLeftMouseClick(); void OnLeftMouseClick();
@ -48,4 +62,6 @@ private:
void SetMyTurn(bool bMyTurn); void SetMyTurn(bool bMyTurn);
auto GetMyGameMode() const; auto GetMyGameMode() const;
// AMyGameState *GetMyGameState() const;
}; };

@ -1,13 +1,42 @@
#include "Trooper.h" #include "Trooper.h"
#include <Kismet/GameplayStatics.h> #include <Kismet/GameplayStatics.h>
#include "HealthBar.h"
#include "Components/WidgetComponent.h"
#include "Net/UnrealNetwork.h" #include "Net/UnrealNetwork.h"
// Sets default values // Sets default values
ATrooper::ATrooper() { ATrooper::ATrooper()
: HitPoints(StartHitPoints), ActionPoints(StartActionPoints) {
bReplicates = true; bReplicates = true;
PrimaryActorTick.bCanEverTick = true; PrimaryActorTick.bCanEverTick = true;
Tags.Add(FName("Trooper")); Tags.Add(FName("Trooper"));
AttackAbility = CreateDefaultSubobject<UAbility>("AttackAbility");
SpecialAbility = CreateDefaultSubobject<UAbility>("SpecialAbility");
HealthWidgetComponent = CreateDefaultSubobject<UWidgetComponent>(
"HealthBar");
HealthWidgetComponent->AttachToComponent(RootComponent,
FAttachmentTransformRules::KeepRelativeTransform);
SelectionStaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(
"SelectionMesh");
static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshToUse(TEXT(
"StaticMesh'/Game/StarterContent/Shapes/Shape_Cylinder.Shape_Cylinder'"));
SelectionStaticMesh->AttachToComponent(RootComponent,
FAttachmentTransformRules::KeepRelativeTransform);
SelectionStaticMesh->SetRelativeScale3D({1.8, 1.8, 0.01});
SelectionStaticMesh->SetVisibility(false);
if (MeshToUse.Object) {
SelectionStaticMesh->SetStaticMesh(MeshToUse.Object);
SelectionStaticMesh->SetStaticMesh(MeshToUse.Object);
}
// SelectionStaticMesh->SetRelativeTransform(FTransform({1000,1000,100}, {0, 0, 0}), false,
// nullptr, ETeleportType::TeleportPhysics);
// SelectionStaticMesh->
// MyStaticMesh = CreateDefaultSubobject<UStaticMeshComponent>("Mesh"); // MyStaticMesh = CreateDefaultSubobject<UStaticMeshComponent>("Mesh");
// RootComponent = MyStaticMesh; // RootComponent = MyStaticMesh;
// MeshPath = TEXT("StaticMesh'/Game/StarterContent/Props/SM_Chair.SM_Chair'"); // MeshPath = TEXT("StaticMesh'/Game/StarterContent/Props/SM_Chair.SM_Chair'");
@ -31,6 +60,8 @@ ATrooper::ATrooper() {
// Called when the game starts or when spawned // Called when the game starts or when spawned
void ATrooper::BeginPlay() { void ATrooper::BeginPlay() {
Super::BeginPlay(); Super::BeginPlay();
Cast<UHealthBar>(HealthWidgetComponent->GetUserWidgetObject())->
SetOwnerTrooper(this);
} }
void ATrooper::Initialize(uint8 const NewPlayerIndex, void ATrooper::Initialize(uint8 const NewPlayerIndex,
@ -55,7 +86,8 @@ void ATrooper::Tick(float const DeltaTime) {
FVector PositionVector = (TargetLocation - CurrentLocation); FVector PositionVector = (TargetLocation - CurrentLocation);
PositionVector.Normalize(); PositionVector.Normalize();
PositionVector *= (Speed * DeltaTime); PositionVector *= (Speed * DeltaTime);
if (PositionVector.Size() >= (TargetLocation - CurrentLocation).Size()) { if (PositionVector.Size() >= (TargetLocation - CurrentLocation).
Size()) {
CurrentLocation = TargetLocation; CurrentLocation = TargetLocation;
bIsMoving = false; bIsMoving = false;
} else { } else {
@ -68,6 +100,7 @@ void ATrooper::Tick(float const DeltaTime) {
void ATrooper::MoveTrooper(FVector const NewPos) { void ATrooper::MoveTrooper(FVector const NewPos) {
TargetLocation = NewPos; TargetLocation = NewPos;
bIsMoving = true; bIsMoving = true;
ActionPoints -= (NewPos - CurrentLocation).Size() * MoveCost;
} }
uint8 ATrooper::GetId() const { uint8 ATrooper::GetId() const {
@ -83,6 +116,9 @@ void ATrooper::GetLifetimeReplicatedProps(
DOREPLIFETIME(ATrooper, bIsMoving); DOREPLIFETIME(ATrooper, bIsMoving);
DOREPLIFETIME(ATrooper, Id); DOREPLIFETIME(ATrooper, Id);
DOREPLIFETIME(ATrooper, bIsAttacking); DOREPLIFETIME(ATrooper, bIsAttacking);
DOREPLIFETIME(ATrooper, HitPoints);
DOREPLIFETIME(ATrooper, ActionPoints);
DOREPLIFETIME(ATrooper, HealthWidgetComponent);
DOREPLIFETIME(ATrooper, AttackPlayedTime); DOREPLIFETIME(ATrooper, AttackPlayedTime);
} }
@ -108,8 +144,52 @@ FVector ATrooper::GetLocation() const {
return CurrentLocation; return CurrentLocation;
} }
void ATrooper::Attack() {
bIsAttacking = true; float ATrooper::GetActionRadius(int action) const {
switch (action) {
case 1:
return AttackAbility->ActionRadius;
case 2:
return SpecialAbility->ActionRadius;
default:
return ActionPoints;
}
}
float ATrooper::GetHitPoints() const {
return HitPoints;
}
float ATrooper::GetMaxHitPoints() const {
return StartHitPoints;
}
void ATrooper::SetSelection(bool Selection) const {
if (SelectionStaticMesh) {
if (SelectionStaticMesh->GetMaterial(0) != GreenMaterial) {
SelectionStaticMesh->SetMaterial(0, GreenMaterial);
}
SelectionStaticMesh->SetVisibility(Selection);
}
}
void ATrooper::HighlightAsEnemy() const {
SelectionStaticMesh->SetVisibility(true);
}
void ATrooper::ResetActionPoints() {
ActionPoints = StartActionPoints;
}
UAbility *ATrooper::GetAbility(int AbilityIndex) const {
switch (AbilityIndex) {
case 1:
return AttackAbility;
case 2:
return SpecialAbility;
default:
return nullptr;
}
} }
float ATrooper::GetAnimationValue() { float ATrooper::GetAnimationValue() {
@ -122,10 +202,20 @@ float ATrooper::GetAnimationValue() {
return 0.0f; return 0.0f;
} }
void ATrooper::Attack(int abilityIndex) {
bIsAttacking = true;
ActionPoints -= GetAbility(abilityIndex)->ActionCost;
}
bool ATrooper::CheckMoveCorrectness(const FVector newPos) const { bool ATrooper::CheckMoveCorrectness(const FVector newPos) const {
return (newPos - CurrentLocation).Size() <= MoveRadius; return (newPos - CurrentLocation).Size() * MoveCost <= ActionPoints;
// return (newPos - CurrentLocation).Size() <= MoveRadius;
} }
bool ATrooper::CheckAttackCorrectness(const FVector attackLocation) const { bool ATrooper::CheckAttackCorrectness(const FVector attackLocation,
return (attackLocation - CurrentLocation).Size() <= AttackRadius; int abilityIndex) const {
return (attackLocation - CurrentLocation).Size() <=
GetAbility(abilityIndex)->ActionRadius && ActionPoints >=
GetAbility(abilityIndex)->ActionCost;
// return (attackLocation - CurrentLocation).Size() <= AttackRadius;
} }

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "Ability.h"
#include "GameFramework/Character.h" #include "GameFramework/Character.h"
#include "Trooper.generated.h" #include "Trooper.generated.h"
@ -29,7 +30,7 @@ public:
bool CheckMoveCorrectness(const FVector newPos) const; bool CheckMoveCorrectness(const FVector newPos) const;
UFUNCTION() UFUNCTION()
bool CheckAttackCorrectness(const FVector attackLocation) const; bool CheckAttackCorrectness(const FVector attackLocation, int abilityIndex) const;
UFUNCTION() UFUNCTION()
FVector GetLocation() const; FVector GetLocation() const;
@ -38,12 +39,63 @@ public:
float GetAnimationValue(); float GetAnimationValue();
UFUNCTION() UFUNCTION()
void Attack(); void Attack(int abilityIndex);
UFUNCTION()
float GetActionRadius(int action) const;
UFUNCTION()
float GetHitPoints() const;
UFUNCTION()
float GetMaxHitPoints() const;
UFUNCTION()
void SetSelection(bool Selected) const;
UFUNCTION()
void HighlightAsEnemy() const;
UFUNCTION()
void ResetActionPoints();
UFUNCTION()
UAbility *GetAbility(int AbilityIndex) const;
protected: protected:
UPROPERTY(EditAnywhere)
UMaterialInterface *GreenMaterial = nullptr;
UPROPERTY(EditAnywhere)
UMaterialInterface *RedMaterial = nullptr;
UPROPERTY(EditAnywhere)
UAbility *AttackAbility;
UPROPERTY(EditAnywhere)
UAbility *SpecialAbility;
const float MoveRadius = 1500.f; const float MoveRadius = 1500.f;
const float AttackRadius = 1000.f; float AttackRadius = 1000.f;
UPROPERTY(EditAnywhere)
float Speed = 300.0f;
UPROPERTY(EditAnywhere)
float StartHitPoints = 100.0f;
UPROPERTY(EditAnywhere)
float MoveCost = 0.0667f;
UPROPERTY(EditAnywhere)
float StartActionPoints = 100.0f;
UPROPERTY(Replicated)
float HitPoints;
UPROPERTY(Replicated)
float ActionPoints;
UPROPERTY(Replicated) UPROPERTY(Replicated)
bool bIsAttacking = false; bool bIsAttacking = false;
@ -57,10 +109,13 @@ protected:
virtual void Tick(float const DeltaTime) override; virtual void Tick(float const DeltaTime) override;
UPROPERTY(VisibleAnywhere, Replicated)
class UWidgetComponent *HealthWidgetComponent;
// void SetStaticMesh() const; // void SetStaticMesh() const;
// UPROPERTY(VisibleAnywhere, BlueprintReadOnly) UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
// UStaticMeshComponent *MyStaticMesh; UStaticMeshComponent *SelectionStaticMesh;
// UPROPERTY(EditAnywhere, BlueprintReadWrite) // UPROPERTY(EditAnywhere, BlueprintReadWrite)
// USkeletalMeshComponent *MySkeletalMesh; // USkeletalMeshComponent *MySkeletalMesh;
@ -73,9 +128,6 @@ protected:
UPROPERTY(Replicated) UPROPERTY(Replicated)
uint8 Id; uint8 Id;
UPROPERTY()
float Speed = 300.0f;
UPROPERTY(Replicated) UPROPERTY(Replicated)
FVector CurrentLocation; FVector CurrentLocation;

@ -1,6 +1,6 @@
{ {
"FileVersion": 3, "FileVersion": 3,
"EngineAssociation": "4.27", "EngineAssociation": "{B4FE6467-4579-3D84-B22A-558A3D607596}",
"Category": "", "Category": "",
"Description": "", "Description": "",
"Modules": [ "Modules": [
@ -9,7 +9,8 @@
"Type": "Runtime", "Type": "Runtime",
"LoadingPhase": "Default", "LoadingPhase": "Default",
"AdditionalDependencies": [ "AdditionalDependencies": [
"Engine" "Engine",
"UMG"
] ]
} }
] ]

Loading…
Cancel
Save