호-밍 공격 및 선택 시스템 구현

This commit is contained in:
2023-10-25 02:40:51 +09:00
parent 3d59b3d336
commit 053c56f37c
25 changed files with 347 additions and 134 deletions

Binary file not shown.

Binary file not shown.

BIN
Content/Blueprints/DefaultClass.uasset (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
Content/Character/Lb/BP_Lb.uasset (Stored with Git LFS)

Binary file not shown.

BIN
Content/Character/Lb/BaseArrow.uasset (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
Content/Effect/AliumQ/Knife1.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Content/Effect/CC.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Content/Effect/dust.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Content/Effect/tnt.uasset (Stored with Git LFS) Normal file

Binary file not shown.

BIN
Content/Maps/DevMap.umap (Stored with Git LFS)

Binary file not shown.

View File

@@ -1,5 +1,5 @@
// 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 "DamageType/ApDamage.h" #include "APDamage.h"

View File

@@ -4,13 +4,13 @@
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "GameFramework/DamageType.h" #include "GameFramework/DamageType.h"
#include "ApDamage.generated.h" #include "APDamage.generated.h"
/** /**
* *
*/ */
UCLASS() UCLASS()
class PROMETHER_API UApDamage : public UDamageType class PROMETHER_API UAPDamage : public UDamageType
{ {
GENERATED_BODY() GENERATED_BODY()

View File

@@ -0,0 +1,45 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "HomingAttack.h"
#include "../PlayerGeneric/DefaultPlayerCharacter.h"
#include "../PlayerGeneric/DefaultPlayerState.h"
#include "Kismet/KismetMathLibrary.h"
// Sets default values
AHomingAttack::AHomingAttack()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
ProjectileMovement = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("ProjectileMovement"));
ProjectileMovement->InitialSpeed = 200;
ProjectileMovement->MaxSpeed = 200;
ProjectileMovement->ProjectileGravityScale = 0;
ProjectileMovement->bIsHomingProjectile = true;
ProjectileMovement->HomingAccelerationMagnitude = 200;
ProjectileMovement->Velocity = { 0, 0, 0 };
ProjectileMovement->bRotationFollowsVelocity = true;
}
// Called when the game starts or when spawned
void AHomingAttack::BeginPlay()
{
Super::BeginPlay();
ADefaultPlayerState* State = Cast<APawn>(GetOwner())->GetPlayerState<ADefaultPlayerState>();
if (!State) return;
if (!State->GetCurrentAttackTarget())
{
UE_LOG(LogTemp, Error, TEXT("No Target"));
return;
}
ProjectileMovement->HomingTargetComponent = State->GetCurrentAttackTarget()->GetRootComponent();
}
// Called every frame
void AHomingAttack::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}

View File

@@ -0,0 +1,30 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "HomingAttack.generated.h"
UCLASS()
class PROMETHER_API AHomingAttack : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AHomingAttack();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
UProjectileMovementComponent* ProjectileMovement;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
};

View File

@@ -0,0 +1,33 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "DefaultAIController.h"
#include "PlayerGeneric/DefaultPlayerState.h"
#include "PlayerGeneric/DefaultPlayerCharacter.h"
ADefaultAIController::ADefaultAIController()
{
bWantsPlayerState = true;
}
void ADefaultAIController::OnPossess(APawn* aPawn)
{
//debug
FString MyName = aPawn->GetName();
ADefaultPlayerState* MyPlayerState = GetPlayerState<ADefaultPlayerState>();
if (!MyPlayerState) return;
ADefaultPlayerCharacter* ControlledPawn = Cast<ADefaultPlayerCharacter>(aPawn);
if (!ControlledPawn) return;
ControlledPawn->SetPlayerState(MyPlayerState);
TArray<float> DefaultStatsValue;
TArray<float> CooldownDurationValue;
ControlledPawn->DefaultStats.GenerateValueArray(DefaultStatsValue);
ControlledPawn->CooldownDuration.GenerateValueArray(CooldownDurationValue);
MyPlayerState->InitPlayerStats(DefaultStatsValue, CooldownDurationValue);
}

View File

@@ -0,0 +1,21 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "AIController.h"
#include "DefaultAIController.generated.h"
/**
*
*/
UCLASS()
class PROMETHER_API ADefaultAIController : public AAIController
{
GENERATED_BODY()
public:
ADefaultAIController();
void OnPossess(APawn* aPawn) override;
};

View File

@@ -3,8 +3,10 @@
#include "DefaultPlayerCharacter.h" #include "DefaultPlayerCharacter.h"
#include "DefaultPlayerState.h" #include "DefaultPlayerState.h"
#include "../DefaultAIController.h"
#include "Engine/DamageEvents.h" #include "Engine/DamageEvents.h"
#include "Kismet/GameplayStatics.h" #include "Kismet/GameplayStatics.h"
#include "Components/CapsuleComponent.h"
ADefaultPlayerCharacter::ADefaultPlayerCharacter() ADefaultPlayerCharacter::ADefaultPlayerCharacter()
{ {
@@ -13,6 +15,9 @@ ADefaultPlayerCharacter::ADefaultPlayerCharacter()
SetCanBeDamaged(true); SetCanBeDamaged(true);
bUseControllerRotationYaw = false; bUseControllerRotationYaw = false;
AIControllerClass = ADefaultAIController::StaticClass();
AutoPossessAI = EAutoPossessAI::PlacedInWorldOrSpawned;
CameraSpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm")); CameraSpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
CameraSpringArm->SetRelativeLocationAndRotation(FVector(0.0f, 0.0f, 0.0f), FRotator(-45.0f, 0.0f, 0.0f)); CameraSpringArm->SetRelativeLocationAndRotation(FVector(0.0f, 0.0f, 0.0f), FRotator(-45.0f, 0.0f, 0.0f));
CameraSpringArm->SetAbsolute(false, true, true); CameraSpringArm->SetAbsolute(false, true, true);
@@ -49,14 +54,13 @@ void ADefaultPlayerCharacter::Tick(float DeltaTime)
*/ */
} }
void ADefaultPlayerCharacter::Attack_Implementation() void ADefaultPlayerCharacter::Attack_Implementation()
{ {
NetMulticast_Attack(); Client_Attack();
BP_Attack();
} }
void ADefaultPlayerCharacter::NetMulticast_Attack_Implementation() void ADefaultPlayerCharacter::Client_Attack_Implementation()
{ {
BP_Attack(); BP_Attack();
} }
@@ -65,67 +69,61 @@ float ADefaultPlayerCharacter::TakeDamage_Implementation(float DamageAmount, str
{ {
float ReturnValue = Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser); float ReturnValue = Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);
if (HasAuthority()) ADefaultPlayerState* State = GetPlayerState<ADefaultPlayerState>();
{ if (!State) return ReturnValue;
UE_LOG(LogTemp, Warning, TEXT("TakeDamage Called On Server"));
} if (!Cast<APawn>(DamageCauser)) return ReturnValue;
else
{ ADefaultPlayerState* AttackerState = Cast<APawn>(DamageCauser)->GetPlayerState<ADefaultPlayerState>();
UE_LOG(LogTemp, Warning, TEXT("TakeDamage Called On Client")); if (!AttackerState) return ReturnValue;
}
if (HasAuthority())
{
if (ADefaultPlayerState* MyState = this->GetInstigatorController()->GetPlayerState<ADefaultPlayerState>())
{
if (ADefaultPlayerState* EventInstigatorState = EventInstigator->GetPlayerState<ADefaultPlayerState>())
{
float ADDamageMultiplier = 0; float ADDamageMultiplier = 0;
float APDamageMultiplier = 0; float APDamageMultiplier = 0;
if (MyState->Stats[(uint8)EStats::Armor] >= 0) if (State->Stats[(uint8)EStats::Armor] >= 0)
ADDamageMultiplier = 100 / (100 + MyState->Stats[(uint8)EStats::Armor]); ADDamageMultiplier = 100 / (100 + State->Stats[(uint8)EStats::Armor]);
else else
ADDamageMultiplier = 2 - 100 / (100 - MyState->Stats[(uint8)EStats::Armor]); ADDamageMultiplier = 2 - 100 / (100 - State->Stats[(uint8)EStats::Armor]);
if (MyState->Stats[(uint8)EStats::MagicResistance] >= 0) if (State->Stats[(uint8)EStats::MagicResistance] >= 0)
APDamageMultiplier = 100 / (100 + MyState->Stats[(uint8)EStats::MagicResistance]); APDamageMultiplier = 100 / (100 + State->Stats[(uint8)EStats::MagicResistance]);
else else
APDamageMultiplier = 2 - 100 / (100 - MyState->Stats[(uint8)EStats::MagicResistance]); APDamageMultiplier = 2 - 100 / (100 - State->Stats[(uint8)EStats::MagicResistance]);
UE_LOG(LogTemp, Warning, TEXT("%s : ADDamageMultiplier : %f CalculatedDamage : %f"), *DamageCauser->GetName(), ADDamageMultiplier, DamageAmount * ADDamageMultiplier); UE_LOG(LogTemp, Warning, TEXT("%s : ADDamageMultiplier : %f CalculatedDamage : %f"), *DamageCauser->GetName(), ADDamageMultiplier, DamageAmount * ADDamageMultiplier);
UE_LOG(LogTemp, Warning, TEXT("%s : APDamageMultiplier : %f CalculatedDamage : %f"), *DamageCauser->GetName(), APDamageMultiplier, DamageAmount * APDamageMultiplier); UE_LOG(LogTemp, Warning, TEXT("%s : APDamageMultiplier : %f CalculatedDamage : %f"), *DamageCauser->GetName(), APDamageMultiplier, DamageAmount * APDamageMultiplier);
float UpdatedHealth = 0;
if (Cast<UBaseAttack>(DamageEvent.DamageTypeClass->GetDefaultObject())) if (Cast<UBaseAttack>(DamageEvent.DamageTypeClass->GetDefaultObject()))
{ {
UE_LOG(LogTemp, Warning, TEXT("DamageType : BaseAttack")); UE_LOG(LogTemp, Warning, TEXT("DamageType : BaseAttack"));
float UpdatedHealth = MyState->Stats[(uint8)EStats::Health] - EventInstigatorState->Stats[(uint8)EStats::AttackDamage] * ADDamageMultiplier; UpdatedHealth = State->Stats[(uint8)EStats::Health] - AttackerState->Stats[(uint8)EStats::AttackDamage] * ADDamageMultiplier;
if (UpdatedHealth < 0) }
else if (Cast<UAPDamage>(DamageEvent.DamageTypeClass->GetDefaultObject()))
{ {
MyState->Stats[(uint8)EStats::Health] = 0; UE_LOG(LogTemp, Warning, TEXT("DamageType : APDamage"));
UpdatedHealth = State->Stats[(uint8)EStats::Health] - AttackerState->Stats[(uint8)EStats::AbilityPower] * APDamageMultiplier;
}
if (UpdatedHealth < 0 || UpdatedHealth < 0.1 )
{
State->Stats[(uint8)EStats::Health] = 0;
Server_PerformDead();
Client_PerformDead();
} }
else else
{ {
MyState->Stats[(uint8)EStats::Health] = UpdatedHealth; State->Stats[(uint8)EStats::Health] = UpdatedHealth;
} }
UE_LOG(LogTemp, Warning, TEXT("Current Health : %f"), MyState->Stats[(uint8)EStats::Health]); UE_LOG(LogTemp, Warning, TEXT("Current Health : %f"), State->Stats[(uint8)EStats::Health]);
}
}
}
return ReturnValue; return ReturnValue;
} }
else
{
return -1.0f;
}
}
void ADefaultPlayerCharacter::Skill1_Implementation() void ADefaultPlayerCharacter::Skill1_Implementation()
{ {
@@ -206,3 +204,23 @@ void ADefaultPlayerCharacter::NetMulticast_Skill7_Implementation()
{ {
BP_Skill7(); BP_Skill7();
} }
void ADefaultPlayerCharacter::PerformDead()
{
ADefaultPlayerState* State = GetPlayerState<ADefaultPlayerState>();
if (!State) return;
State->SetState(ECharacterState::Dead);
GetCapsuleComponent()->SetGenerateOverlapEvents(false);
GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}
void ADefaultPlayerCharacter::Server_PerformDead_Implementation()
{
PerformDead();
}
void ADefaultPlayerCharacter::Client_PerformDead_Implementation()
{
PerformDead();
}

View File

@@ -26,8 +26,9 @@ public:
//Override me //Override me
UFUNCTION(BlueprintImplementableEvent) UFUNCTION(BlueprintImplementableEvent)
void BP_Attack(); void BP_Attack();
UFUNCTION(NetMulticast, Reliable) UFUNCTION(Client, Reliable)
void NetMulticast_Attack(); void Client_Attack();
UFUNCTION(BlueprintNativeEvent) UFUNCTION(BlueprintNativeEvent)
float TakeDamage( float Damage, float TakeDamage( float Damage,
struct FDamageEvent const& DamageEvent, struct FDamageEvent const& DamageEvent,
@@ -35,7 +36,13 @@ public:
AActor* DamageCauser ) override; AActor* DamageCauser ) override;
void PerformDead();
UFUNCTION(Client, Reliable)
void Client_PerformDead();
UFUNCTION(Server, Reliable)
void Server_PerformDead();
UFUNCTION(BlueprintCallable, Server, Reliable) UFUNCTION(BlueprintCallable, Server, Reliable)

View File

@@ -105,7 +105,7 @@ void ADefaultPlayerController::Server_SpawnPlayerCamera_Implementation()
void ADefaultPlayerController::SetACharacterOutlineColor(ACharacter* Target, bool Visible) void ADefaultPlayerController::SetACharacterOutlineColor(ACharacter* Target, bool Visible)
{ {
if (HasAuthority()) return; if (!Target) return;
ADefaultPlayerState* State = Target->GetPlayerState<ADefaultPlayerState>(); ADefaultPlayerState* State = Target->GetPlayerState<ADefaultPlayerState>();
if (!State) if (!State)
@@ -405,47 +405,50 @@ void ADefaultPlayerController::Bomb()
void ADefaultPlayerController::ObjectSelect() void ADefaultPlayerController::ObjectSelect()
{ {
ADefaultPlayerState* State = GetPlayerState<ADefaultPlayerState>();
if (!State) return;
FHitResult HitResult; FHitResult HitResult;
TArray<TEnumAsByte<EObjectTypeQuery>> ObjectTypes; TArray<TEnumAsByte<EObjectTypeQuery>> ObjectTypes;
ObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECollisionChannel::ECC_WorldStatic));
ObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECollisionChannel::ECC_Pawn)); ObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECollisionChannel::ECC_Pawn));
GetHitResultUnderCursorForObjects(ObjectTypes, true, HitResult); GetHitResultUnderCursorForObjects(ObjectTypes, true, HitResult);
ACharacter* HitObject = Cast<ACharacter>(HitResult.GetActor()); ACharacter* HitObject = Cast<ACharacter>(HitResult.GetActor());
if (!HitObject) return;
UE_LOG(LogTemp, Warning, TEXT("%s"), *HitObject->GetName()); if (!HitObject)
{
SetACharacterOutlineColor(Cast<ACharacter>(State->GetPreviousAttackTarget()), false);
State->SetPreviousAttackTarget(nullptr);
State->SetCurrentAttackTarget(nullptr);
return;
}
if (State->GetPreviousAttackTarget() != HitResult.GetActor())
{
SetACharacterOutlineColor(Cast<ACharacter>(State->GetPreviousAttackTarget()), false);
State->SetPreviousAttackTarget(HitResult.GetActor());
State->SetCurrentAttackTarget(HitResult.GetActor());
SetACharacterOutlineColor(HitObject, true); SetACharacterOutlineColor(HitObject, true);
} }
UE_LOG(LogTemp, Warning, TEXT("%s"), *State->GetCurrentAttackTarget()->GetName());
FString Name = HitResult.GetActor()->GetName();
APlayerState* TargetState = Cast<APawn>(HitResult.GetActor())->GetPlayerState();
}
void ADefaultPlayerController::Move() void ADefaultPlayerController::Move()
{ {
EndAttack(); EndAttack();
FHitResult HitResult; ObjectSelect();
TArray<TEnumAsByte<EObjectTypeQuery>> ObjectTypes;
ObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECollisionChannel::ECC_WorldStatic));
ObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECollisionChannel::ECC_Pawn));
GetHitResultUnderCursorForObjects(ObjectTypes, true, HitResult); if (GetPlayerState<ADefaultPlayerState>()->GetCurrentAttackTarget() != GetPawn<AActor>() &&
ACharacter* HitCharacter = Cast<ACharacter>(HitResult.GetActor()); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> HitCharactor<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><<<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> ij<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>϶<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؾ<EFBFBD><EFBFBD><EFBFBD> Cast<ADefaultPlayerCharacter>(GetPlayerState<ADefaultPlayerState>()->GetCurrentAttackTarget())) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ƴϰ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD>̵<EFBFBD> <20>Ʊ<EFBFBD><C6B1>̵<EFBFBD>)<29><> <EFBFBD><EFBFBD>
HitTarget = HitResult.GetActor();
UE_LOG(LogTemp, Warning, TEXT("%s"), *HitResult.GetActor()->GetName());
if (HitResult.GetActor() != GetPawn<AActor>()) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> HitObject<63><74> null<6C><6C> <20>ƴ<EFBFBD> <20><><EFBFBD><EFBFBD> Attack()<29><> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD>, HitObject<63><74> <20><> ij<><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؾ<EFBFBD><D8BE><EFBFBD>
{ {
if (!GetPlayerState<ADefaultPlayerState>()->Stats[(uint8)EStats::Attackable] == 0) if (!GetPlayerState<ADefaultPlayerState>()->Stats[(uint8)EStats::Attackable] == 0) return;
return;
if (!HitCharacter)
{
FVector Destination = GetMouseHitLocation();
GetPlayerState<ADefaultPlayerState>()->SetState(ECharacterState::Moving);
SimpleMoveToLocation(this, Destination);
this->MoveToLocation(Destination);
return;
}
BeginAttack(); //HitObject<63><74> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> BeginAttack <20><><EFBFBD><EFBFBD> BeginAttack(); //HitObject<63><74> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> BeginAttack <20><><EFBFBD><EFBFBD>
} }
else else
@@ -500,7 +503,10 @@ void ADefaultPlayerController::Multicast_StopMove_Implementation()
FVector ADefaultPlayerController::GetMouseHitLocation() FVector ADefaultPlayerController::GetMouseHitLocation()
{ {
FHitResult HitResult; FHitResult HitResult;
GetHitResultUnderCursor(ECollisionChannel::ECC_Visibility, true, HitResult); TArray<TEnumAsByte<EObjectTypeQuery>> ObjectTypes;
ObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECollisionChannel::ECC_WorldStatic));
GetHitResultUnderCursorForObjects(ObjectTypes, true, HitResult);
HitResult.Location.Z = 0; HitResult.Location.Z = 0;
//UE_LOG(LogTemp, Warning, TEXT("Client%d MoveTo : (%f, %f)"), GPlayInEditorID, HitResult.Location.X, HitResult.Location.Y); //UE_LOG(LogTemp, Warning, TEXT("Client%d MoveTo : (%f, %f)"), GPlayInEditorID, HitResult.Location.X, HitResult.Location.Y);
@@ -629,8 +635,6 @@ void ADefaultPlayerController::OnMoveCompleted(FAIRequestID RequestID, const FPa
GetPlayerState<ADefaultPlayerState>()->SetState(ECharacterState::Idle); GetPlayerState<ADefaultPlayerState>()->SetState(ECharacterState::Idle);
} }
FTimerHandle TimerHandle;
void ADefaultPlayerController::BeginAttack() void ADefaultPlayerController::BeginAttack()
{ {
GetWorldTimerManager().SetTimer(TimerHandle, this, &ADefaultPlayerController::RepeatedAttack, 0.1f, true); GetWorldTimerManager().SetTimer(TimerHandle, this, &ADefaultPlayerController::RepeatedAttack, 0.1f, true);
@@ -638,31 +642,30 @@ void ADefaultPlayerController::BeginAttack()
void ADefaultPlayerController::EndAttack() void ADefaultPlayerController::EndAttack()
{ {
GetWorldTimerManager().ClearTimer(TimerHandle); GetWorldTimerManager().ClearTimer(TimerHandle);
} }
void ADefaultPlayerController::RepeatedAttack() void ADefaultPlayerController::RepeatedAttack()
{ {
if (!GetPlayerState<ADefaultPlayerState>()->Stats[(uint8)EStats::Attackable] == 0)
return;
Attack(); Attack();
} }
void ADefaultPlayerController::Attack() void ADefaultPlayerController::Attack()
{ {
if (!GetPlayerState<ADefaultPlayerState>()->Stats[(uint8)EStats::Attackable] == 0)
return;
float MinDistance = GetPlayerState<ADefaultPlayerState>()->Stats[(uint8)EStats:: AttackRange]; float MinDistance = GetPlayerState<ADefaultPlayerState>()->Stats[(uint8)EStats:: AttackRange];
FVector Destination = HitTarget->GetActorLocation(); // HitObject<63><74> <20><>ġ<EFBFBD><C4A1> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
if (!GetPlayerState<ADefaultPlayerState>()->GetCurrentAttackTarget()) return;
FVector Destination = GetPlayerState<ADefaultPlayerState>()->GetCurrentAttackTarget()->GetActorLocation(); // HitObject<63><74> <20><>ġ<EFBFBD><C4A1> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
if (FVector::Dist(Destination, GetPawn()->GetActorLocation()) <= MinDistance) if (FVector::Dist(Destination, GetPawn()->GetActorLocation()) <= MinDistance)
{ {
if ((GetPlayerState<ADefaultPlayerState>()->CooldownDuration[(uint8)CooldownType::Attack] != 0)) if ((GetPlayerState<ADefaultPlayerState>()->CooldownDuration[(uint8)CooldownType::Attack] != 0))
return; return;
FVector Location = GetPawn()->GetActorLocation(); FVector Location = GetPawn()->GetActorLocation();
Location.X = 0; Location.X = 0;
@@ -672,7 +675,6 @@ void ADefaultPlayerController::Attack()
Multicast_SetRotation(Destination); Multicast_SetRotation(Destination);
Server_SetRotation(Destination); Server_SetRotation(Destination);
UE_LOG(LogTemp, Warning, TEXT("Attack")); UE_LOG(LogTemp, Warning, TEXT("Attack"));
GetPlayerState<ADefaultPlayerState>()->SetState(ECharacterState::Attack); GetPlayerState<ADefaultPlayerState>()->SetState(ECharacterState::Attack);
GetPlayerState<ADefaultPlayerState>()->SetAttackType(CooldownType::Attack); GetPlayerState<ADefaultPlayerState>()->SetAttackType(CooldownType::Attack);
@@ -681,12 +683,8 @@ void ADefaultPlayerController::Attack()
{ {
GetPlayerState<ADefaultPlayerState>()->SetState(ECharacterState::Moving); GetPlayerState<ADefaultPlayerState>()->SetState(ECharacterState::Moving);
SimpleMoveToLocation(this, Destination); SimpleMoveToLocation(this, Destination);
this->MoveToLocation(Destination); this->MoveToLocation(Destination);
} }
SetTarget();
} }
void ADefaultPlayerController::MoveToLocation_Implementation(FVector Location) void ADefaultPlayerController::MoveToLocation_Implementation(FVector Location)

View File

@@ -77,9 +77,7 @@ public:
UPROPERTY(BlueprintReadWrite) UPROPERTY(BlueprintReadWrite)
float MouseClickInterval; float MouseClickInterval;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "My Actor") FTimerHandle TimerHandle;
AActor* HitTarget;
private: private:
UPROPERTY(EditAnywhere, Category = "Input") UPROPERTY(EditAnywhere, Category = "Input")

View File

@@ -22,8 +22,10 @@ void ADefaultPlayerState::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>&
DOREPLIFETIME(ADefaultPlayerState, State); DOREPLIFETIME(ADefaultPlayerState, State);
DOREPLIFETIME(ADefaultPlayerState, AttackType); DOREPLIFETIME(ADefaultPlayerState, AttackType);
//DOREPLIFETIME(ADefaultPlayerState, StatusEffectObject);
DOREPLIFETIME(ADefaultPlayerState, PlayerCamera); DOREPLIFETIME(ADefaultPlayerState, PlayerCamera);
DOREPLIFETIME(ADefaultPlayerState, CurrentAttackTarget);
DOREPLIFETIME(ADefaultPlayerState, PreviousAttackTarget);
} }
void ADefaultPlayerState::InitPlayerStats_Implementation(const TArray<float>& StatsValue, const TArray<float>& CooldownDurationValue) void ADefaultPlayerState::InitPlayerStats_Implementation(const TArray<float>& StatsValue, const TArray<float>& CooldownDurationValue)
@@ -33,7 +35,6 @@ void ADefaultPlayerState::InitPlayerStats_Implementation(const TArray<float>& St
CooldownDuration.Append(CooldownDurationValue); CooldownDuration.Append(CooldownDurationValue);
MaxCooldownDuration.Append(CooldownDurationValue); MaxCooldownDuration.Append(CooldownDurationValue);
for (float Value : StatsValue) for (float Value : StatsValue)
{ {
UE_LOG(LogTemp, Warning, TEXT("Values: %f"), Value); UE_LOG(LogTemp, Warning, TEXT("Values: %f"), Value);
@@ -64,3 +65,35 @@ int32 ADefaultPlayerState::GetCharacterLevel() const
{ {
return int32(); return int32();
} }
void ADefaultPlayerState::SetCurrentAttackTarget(AActor* Target)
{
Server_SetCurrentAttackTarget(Target);
Client_SetCurrentAttackTarget(Target);
}
void ADefaultPlayerState::Server_SetCurrentAttackTarget_Implementation(AActor* Target)
{
CurrentAttackTarget = Target;
}
void ADefaultPlayerState::Client_SetCurrentAttackTarget_Implementation(AActor* Target)
{
CurrentAttackTarget = Target;
}
void ADefaultPlayerState::SetPreviousAttackTarget(AActor* Target)
{
Server_SetPreviousAttackTarget(Target);
Client_SetPreviousAttackTarget(Target);
}
void ADefaultPlayerState::Server_SetPreviousAttackTarget_Implementation(AActor* Target)
{
PreviousAttackTarget = Target;
}
void ADefaultPlayerState::Client_SetPreviousAttackTarget_Implementation(AActor* Target)
{
PreviousAttackTarget = Target;
}

View File

@@ -63,6 +63,23 @@ public:
UFUNCTION(BlueprintCallable) UFUNCTION(BlueprintCallable)
int32 GetCharacterLevel() const; int32 GetCharacterLevel() const;
UFUNCTION(BlueprintCallable)
AActor* GetCurrentAttackTarget() const { return CurrentAttackTarget; };
UFUNCTION(BlueprintCallable)
AActor* GetPreviousAttackTarget() const { return PreviousAttackTarget; };
void SetCurrentAttackTarget(AActor* Target);
UFUNCTION(Server, Reliable)
void Server_SetCurrentAttackTarget(AActor* Target);
UFUNCTION(Client, Reliable)
void Client_SetCurrentAttackTarget(AActor* Target);
void SetPreviousAttackTarget(AActor* Target);
UFUNCTION(Server, Reliable)
void Server_SetPreviousAttackTarget(AActor* Target);
UFUNCTION(Client, Reliable)
void Client_SetPreviousAttackTarget(AActor* Target);
UPROPERTY(Replicated, Transient, EditAnywhere, BlueprintReadWrite) UPROPERTY(Replicated, Transient, EditAnywhere, BlueprintReadWrite)
TArray<float> Stats; TArray<float> Stats;
UPROPERTY(Replicated, Transient, EditAnywhere, BlueprintReadWrite) UPROPERTY(Replicated, Transient, EditAnywhere, BlueprintReadWrite)
@@ -73,6 +90,7 @@ public:
UPROPERTY(Replicated, Transient, BlueprintReadWrite) UPROPERTY(Replicated, Transient, BlueprintReadWrite)
TArray<float> MaxCooldownDuration; TArray<float> MaxCooldownDuration;
private: private:
UPROPERTY(Replicated, Transient) UPROPERTY(Replicated, Transient)
UClass* CharacterBPRef; UClass* CharacterBPRef;
@@ -84,9 +102,11 @@ private:
UPROPERTY(Replicated, Transient) UPROPERTY(Replicated, Transient)
CooldownType AttackType; CooldownType AttackType;
//UPROPERTY(Replicated, Transient)
//TMap<FUniqueObjectID, UStatusEffect> StatusEffectObject;
UPROPERTY(Replicated, Transient) UPROPERTY(Replicated, Transient)
AActor* PlayerCamera; AActor* PlayerCamera;
UPROPERTY(Replicated, Transient)
AActor* CurrentAttackTarget;
UPROPERTY(Replicated, Transient)
AActor* PreviousAttackTarget;
}; };

View File

@@ -2,6 +2,7 @@
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "DamageType/BaseAttack.h" #include "DamageType/BaseAttack.h"
#include "DamageType/APDamage.h"
UENUM(BlueprintType) UENUM(BlueprintType)
enum class CharacterType : uint8 enum class CharacterType : uint8