[박치영] LockOn SYstem 추가
parent
d4283aef0d
commit
00b2ef6ab4
|
@ -130,4 +130,6 @@ ManualIPAddress=
|
|||
[CoreRedirects]
|
||||
+FunctionRedirects=(OldName="/Script/D1.CollisionComponent.EnableCollision",NewName="/Script/D1.CollisionComponent.ActivateCollision")
|
||||
+FunctionRedirects=(OldName="/Script/D1.CollisionComponent.DisableCollision",NewName="/Script/D1.CollisionComponent.DeactivateCollision")
|
||||
+PropertyRedirects=(OldName="/Script/D1.BaseDualWeapon.RightFoot",NewName="/Script/D1.BaseDualWeapon.RightFootCollisionComponent")
|
||||
+PropertyRedirects=(OldName="/Script/D1.BaseDualWeapon.RightFoot",NewName="/Script/D1.BaseDualWeapon.RightFootCollisionComponent")
|
||||
+PropertyRedirects=(OldName="/Script/D1.CombatCharacter.ToogleLockOnAction",NewName="/Script/D1.CombatCharacter.ToggleLockOnAction")
|
||||
+ClassRedirects=(OldName="/Script/D1.UI_LockOnComponent",NewName="/Script/D1.LockOnWidgetComponent")
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -2,6 +2,8 @@
|
|||
|
||||
|
||||
#include "Animation/CombatAnimInstance.h"
|
||||
|
||||
#include "Components/CombatComponent.h"
|
||||
#include "GameFramework/Character.h"
|
||||
#include "GameFramework/CharacterMovementComponent.h"
|
||||
#include "Kismet/KismetMathLibrary.h"
|
||||
|
@ -12,7 +14,14 @@ void UCombatAnimInstance::NativeInitializeAnimation()
|
|||
|
||||
Character = Cast<ACharacter>(TryGetPawnOwner());
|
||||
if (Character)
|
||||
{
|
||||
CharacterMovementComponent = Character->GetCharacterMovement();
|
||||
|
||||
UCombatComponent* CombatComponent = Character->GetComponentByClass<UCombatComponent>();
|
||||
ensure(CombatComponent);
|
||||
if(IsValid(CombatComponent))
|
||||
CombatComponent->OnCombatToggled.AddUObject(this, &UCombatAnimInstance::UpdateCombatEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
void UCombatAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
|
||||
|
@ -28,6 +37,8 @@ void UCombatAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
|
|||
FVector2D vel = { Velocity.X, Velocity.Y };
|
||||
GroundSpeed = vel.Length();
|
||||
|
||||
Direction = CalculateDirection(CharacterMovementComponent->Velocity, Character->GetActorRotation());
|
||||
|
||||
ShouldMove = (GroundSpeed > 3.f) && (CharacterMovementComponent->GetCurrentAcceleration().Length() != 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,9 @@ public:
|
|||
|
||||
public:
|
||||
virtual void UpdateCombatType(ECombatType combatType) override;
|
||||
virtual void UpdateCombatEnabled(bool combatEnabled) override;
|
||||
|
||||
public: //Delegate
|
||||
void UpdateCombatEnabled(bool combatEnabled);
|
||||
|
||||
private:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="References", meta=(AllowPrivateAccess="true"))
|
||||
|
@ -35,6 +37,8 @@ private:
|
|||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="EssentialMovementData", meta = (AllowPrivateAccess = "true"))
|
||||
float GroundSpeed;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="EssentialMovementData", meta = (AllowPrivateAccess = "true"))
|
||||
float Direction;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="EssentialMovementData", meta = (AllowPrivateAccess = "true"))
|
||||
bool ShouldMove;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="EssentialMovementData", meta = (AllowPrivateAccess = "true"))
|
||||
bool IsFalling;
|
||||
|
|
|
@ -67,6 +67,7 @@ ACombatCharacter::ACombatCharacter()
|
|||
|
||||
// Setting CombatComponent
|
||||
CombatComponent = CreateDefaultSubobject<UCombatComponent>(TEXT("CombatComponent"));
|
||||
CombatComponent->OnCombatToggled.AddUObject(this, &ACombatCharacter::CharacterCombatToggled);
|
||||
|
||||
// Setting StateManagerComponent
|
||||
StateManagerComponent = CreateDefaultSubobject<UStateManagerComponent>(TEXT("StateManagerComponent"));
|
||||
|
@ -79,6 +80,9 @@ ACombatCharacter::ACombatCharacter()
|
|||
StatsComponent = CreateDefaultSubobject<UStatsComponent>(TEXT("StatsComponent"));
|
||||
StatsComponent->OnCurrentStatValueUpdated.AddUObject(this, &ACombatCharacter::CharacterCurrentStatValueUpdated);
|
||||
|
||||
//Setting TargetComponent
|
||||
TargetingComponent = CreateDefaultSubobject<UTargetingComponent>(TEXT("TargetingComponent"));
|
||||
|
||||
//Setting MovementSpeed
|
||||
MovementSpeedMode = EMovementSpeedMode::Jogging;
|
||||
WalkingSpeed = 200.f;
|
||||
|
@ -104,7 +108,7 @@ void ACombatCharacter::BeginPlay()
|
|||
}
|
||||
}
|
||||
|
||||
//Player에 무기를 처음부터 들고있게함. 아마도 임시코드
|
||||
//Player have Weapon until first time : probably temp coding
|
||||
FActorSpawnParameters spawnParam;
|
||||
spawnParam.Owner = this;
|
||||
spawnParam.Instigator = this;
|
||||
|
@ -190,7 +194,6 @@ void ACombatCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerIn
|
|||
// Set up action bindings
|
||||
if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
|
||||
{
|
||||
|
||||
//Jumping
|
||||
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Triggered, this, &ACombatCharacter::Jumping);
|
||||
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping);
|
||||
|
@ -223,7 +226,9 @@ void ACombatCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerIn
|
|||
//Sprint
|
||||
EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Started, this, &ACombatCharacter::StartSprint);
|
||||
EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Completed, this, &ACombatCharacter::StopSprint);
|
||||
|
||||
|
||||
//ToggleLockOn
|
||||
EnhancedInputComponent->BindAction(ToggleLockOnAction, ETriggerEvent::Started, this, &ACombatCharacter::ToggleLockOn);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,6 +237,30 @@ void ACombatCharacter::SetCanMove_Implementation(bool inputCanMove)
|
|||
bCanMove = inputCanMove;
|
||||
}
|
||||
|
||||
void ACombatCharacter::SetMovementSpeedMode(EMovementSpeedMode NewSpeedMode)
|
||||
{
|
||||
if (NewSpeedMode == MovementSpeedMode)
|
||||
return;
|
||||
|
||||
MovementSpeedMode = NewSpeedMode;
|
||||
TargetingComponent->UpdateRotationMode();
|
||||
|
||||
switch (MovementSpeedMode)
|
||||
{
|
||||
case EMovementSpeedMode::Walking:
|
||||
GetCharacterMovement()->MaxWalkSpeed = WalkingSpeed;
|
||||
break;
|
||||
case EMovementSpeedMode::Jogging:
|
||||
GetCharacterMovement()->MaxWalkSpeed = JoggingSpeed;
|
||||
break;
|
||||
case EMovementSpeedMode::Sprinting:
|
||||
GetCharacterMovement()->MaxWalkSpeed = SprintSpeed;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ACombatCharacter::Move(const FInputActionValue& Value)
|
||||
{
|
||||
if(!bCanMove) //Value changes SetCanMove Func Call to Animnotify
|
||||
|
@ -266,8 +295,13 @@ void ACombatCharacter::Look(const FInputActionValue& Value)
|
|||
if (Controller != nullptr)
|
||||
{
|
||||
// add yaw and pitch input to controller
|
||||
AddControllerYawInput(LookAxisVector.X);
|
||||
AddControllerPitchInput(LookAxisVector.Y);
|
||||
if(!TargetingComponent->GetIsTargeting()) // Not Targeting
|
||||
{
|
||||
AddControllerYawInput(LookAxisVector.X);
|
||||
AddControllerPitchInput(LookAxisVector.Y);
|
||||
}
|
||||
else // Targeting
|
||||
AddControllerPitchInput(LookAxisVector.Y * 0.2f);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -366,7 +400,7 @@ void ACombatCharacter::Dodge(const FInputActionValue& Value)
|
|||
|
||||
void ACombatCharacter::ToggleWalk(const FInputActionValue& Value)
|
||||
{
|
||||
if (GetMovementSpeedMode() != EMovementSpeedMode::Walking)
|
||||
if (GetCombatMovementSpeedMode() != EMovementSpeedMode::Walking)
|
||||
SetMovementSpeedMode(EMovementSpeedMode::Walking);
|
||||
else
|
||||
SetMovementSpeedMode(EMovementSpeedMode::Jogging);
|
||||
|
@ -389,6 +423,13 @@ void ACombatCharacter::StopSprint(const FInputActionValue& Value)
|
|||
DisableSprint();
|
||||
}
|
||||
|
||||
void ACombatCharacter::ToggleLockOn(const FInputActionValue& Value)
|
||||
{
|
||||
if(!CombatComponent->GetCombatEnabled() && !TargetingComponent->GetIsTargeting())
|
||||
return;
|
||||
TargetingComponent->ToggleLockOn();
|
||||
}
|
||||
|
||||
void ACombatCharacter::CharacterStateBegin(FGameplayTag CharState)
|
||||
{
|
||||
if (FGameplayTag::EmptyTag == CharState)
|
||||
|
@ -479,6 +520,12 @@ void ACombatCharacter::CharacterCurrentStatValueUpdated(EStats statType, float v
|
|||
StateManagerComponent->SetCurrentState(FCombatGameplayTags::Get().Character_State_Dead);
|
||||
}
|
||||
|
||||
void ACombatCharacter::CharacterCombatToggled(bool IsCombatEnabled)
|
||||
{
|
||||
if(IsValid(TargetingComponent))
|
||||
TargetingComponent->UpdateRotationMode();
|
||||
}
|
||||
|
||||
void ACombatCharacter::ToggleCombatEvent()
|
||||
{
|
||||
ABaseWeapon* baseWeapon = CombatComponent->GetMainWeapon();
|
||||
|
@ -530,28 +577,6 @@ void ACombatCharacter::EnableRagdoll()
|
|||
GetMesh()->SetAllBodiesBelowPhysicsBlendWeight(PelvisBoneName, 1.f);
|
||||
}
|
||||
|
||||
void ACombatCharacter::SetMovementSpeedMode(EMovementSpeedMode NewSpeedMode)
|
||||
{
|
||||
if (NewSpeedMode == MovementSpeedMode)
|
||||
return;
|
||||
|
||||
MovementSpeedMode = NewSpeedMode;
|
||||
switch (MovementSpeedMode)
|
||||
{
|
||||
case EMovementSpeedMode::Walking:
|
||||
GetCharacterMovement()->MaxWalkSpeed = WalkingSpeed;
|
||||
break;
|
||||
case EMovementSpeedMode::Jogging:
|
||||
GetCharacterMovement()->MaxWalkSpeed = JoggingSpeed;
|
||||
break;
|
||||
case EMovementSpeedMode::Sprinting:
|
||||
GetCharacterMovement()->MaxWalkSpeed = SprintSpeed;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool ACombatCharacter::ResetChargeAttack()
|
||||
{
|
||||
AttackHeldTime = 0.f;
|
||||
|
@ -570,7 +595,7 @@ void ACombatCharacter::DisableSprint()
|
|||
if (World)
|
||||
World->GetTimerManager().ClearTimer(StaminaTimerHandle);
|
||||
|
||||
if (GetMovementSpeedMode() == EMovementSpeedMode::Sprinting)
|
||||
if (GetCombatMovementSpeedMode() == EMovementSpeedMode::Sprinting)
|
||||
SetMovementSpeedMode(EMovementSpeedMode::Jogging);
|
||||
}
|
||||
|
||||
|
@ -785,7 +810,7 @@ FGameplayTag ACombatCharacter::GetDesiredAttackType()
|
|||
if (GetCharacterMovement()->IsFalling())
|
||||
return FCombatGameplayTags::Get().Character_Action_Attack_FallingAttack;
|
||||
|
||||
if (GetMovementSpeedMode() == EMovementSpeedMode::Sprinting)
|
||||
if (GetCombatMovementSpeedMode() == EMovementSpeedMode::Sprinting)
|
||||
return FCombatGameplayTags::Get().Character_Action_Attack_SprintAttack;
|
||||
|
||||
if (IsHeavyAttack)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "Interface/CombatInterface.h"
|
||||
#include "Components/StateManagerComponent.h"
|
||||
#include "Components/StatsComponent.h"
|
||||
#include "Components/TargetingComponent.h"
|
||||
#include "Definitions/GameEnums.h"
|
||||
#include "CombatCharacter.generated.h"
|
||||
|
||||
|
@ -65,6 +66,9 @@ class ACombatCharacter : public ACharacter, public ICombatInterface
|
|||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
|
||||
class UInputAction* SprintAction;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
|
||||
class UInputAction* ToggleLockOnAction;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Input, meta = (AllowPrivateAccess = "true"))
|
||||
float ChargeAttackTime;
|
||||
public:
|
||||
|
@ -103,6 +107,12 @@ public:
|
|||
void SetCanMove(bool inputCanMove);
|
||||
virtual void SetCanMove_Implementation(bool inputCanMove) override;
|
||||
|
||||
virtual EMovementSpeedMode GetCombatMovementSpeedMode() override { return GetMovementSpeedMode(); }
|
||||
|
||||
public:
|
||||
void SetMovementSpeedMode(EMovementSpeedMode NewSpeedMode);
|
||||
FORCEINLINE EMovementSpeedMode GetMovementSpeedMode() const { return MovementSpeedMode; }
|
||||
|
||||
protected:
|
||||
//Input Funcs
|
||||
void Move(const FInputActionValue& Value);
|
||||
|
@ -117,7 +127,8 @@ protected:
|
|||
void ToggleWalk(const FInputActionValue& Value);
|
||||
void StartSprint(const FInputActionValue& Value);
|
||||
void StopSprint(const FInputActionValue& Value);
|
||||
|
||||
void ToggleLockOn(const FInputActionValue& Value);
|
||||
|
||||
private://Delegate
|
||||
void CharacterStateBegin(FGameplayTag CharState);
|
||||
void CharacterStateEnd(FGameplayTag CharState);
|
||||
|
@ -125,13 +136,12 @@ private://Delegate
|
|||
void CharacterActionEnd(FGameplayTag CharAction);
|
||||
void CharacterCurrentStatValueUpdated(EStats statType, float value);
|
||||
|
||||
void CharacterCombatToggled(bool IsCombatEnabled);
|
||||
private:
|
||||
void ToggleCombatEvent();
|
||||
void AttackEvent();
|
||||
void ApplyHitReactionPhysicsVelocity(float InitialSpeed);
|
||||
void EnableRagdoll();
|
||||
void SetMovementSpeedMode(EMovementSpeedMode NewSpeedMode);
|
||||
FORCEINLINE EMovementSpeedMode GetMovementSpeedMode() const { return MovementSpeedMode; }
|
||||
bool ResetChargeAttack();
|
||||
void DisableSprint();
|
||||
void SprintStaminaCost();
|
||||
|
@ -161,6 +171,9 @@ public:
|
|||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components", meta=(AllowPrivateAccess="true"))
|
||||
TObjectPtr<UStatsComponent> StatsComponent;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components", meta=(AllowPrivateAccess="true"))
|
||||
TObjectPtr<UTargetingComponent> TargetingComponent;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Weapon", meta = (AllowPrivateAccess = "true"))
|
||||
TSubclassOf<class ABaseEquippable> Weapon;
|
||||
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
#include "Components/CombatComponent.h"
|
||||
#include "Actor/BaseWeapon.h"
|
||||
#include "Definitions/GameEnums.h"
|
||||
#include "GameFramework/Character.h"
|
||||
#include "Interface/IAnimInstance.h"
|
||||
|
||||
// Sets default values for this component's properties
|
||||
UCombatComponent::UCombatComponent()
|
||||
|
@ -21,13 +19,15 @@ void UCombatComponent::SetCombatEnabled(bool bInputCombat)
|
|||
{
|
||||
bCombatEnabled = bInputCombat;
|
||||
|
||||
ACharacter* character = Cast<ACharacter>(GetOwner());
|
||||
if (character)
|
||||
{
|
||||
IIAnimInstance* Animinstance = Cast<IIAnimInstance>(character->GetMesh()->GetAnimInstance());
|
||||
if (Animinstance)
|
||||
Animinstance->UpdateCombatEnabled(bInputCombat);
|
||||
}
|
||||
OnCombatToggled.Broadcast(bInputCombat);
|
||||
|
||||
// ACharacter* character = Cast<ACharacter>(GetOwner());
|
||||
// if (character)
|
||||
// {
|
||||
// IIAnimInstance* Animinstance = Cast<IIAnimInstance>(character->GetMesh()->GetAnimInstance());
|
||||
// if (Animinstance)
|
||||
// Animinstance->UpdateCombatEnabled(bInputCombat);
|
||||
// }
|
||||
}
|
||||
|
||||
void UCombatComponent::ResetAttack()
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "Components/ActorComponent.h"
|
||||
#include "CombatComponent.generated.h"
|
||||
|
||||
DECLARE_MULTICAST_DELEGATE_OneParam(FOnCombatToggled, bool);
|
||||
|
||||
class ABaseWeapon;
|
||||
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
|
||||
|
@ -46,5 +47,8 @@ private:
|
|||
bool bIsAttackSaved;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess="true"))
|
||||
int32 AttackCount;
|
||||
int32 AttackCount;
|
||||
|
||||
public: //Delegate
|
||||
FOnCombatToggled OnCombatToggled;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#include "Components/TargetingComponent.h"
|
||||
|
||||
#include "CombatComponent.h"
|
||||
#include "GameFramework/Character.h"
|
||||
#include "Camera/CameraComponent.h"
|
||||
#include "GameFramework/CharacterMovementComponent.h"
|
||||
#include "Interface/CombatInterface.h"
|
||||
#include "Interface/TargetingInterface.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "Kismet/KismetMathLibrary.h"
|
||||
|
||||
// Sets default values for this component's properties
|
||||
UTargetingComponent::UTargetingComponent()
|
||||
{
|
||||
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
|
||||
// off to improve performance if you don't need them.
|
||||
PrimaryComponentTick.bCanEverTick = true;
|
||||
|
||||
TargetObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECollisionChannel::ECC_Pawn));
|
||||
TargetingDistance = 900.f;
|
||||
TargetingRadius = 100.f;
|
||||
TargetRotationInterpSpeed = 9.f;
|
||||
DefaultRotationMode = ERotationMode::OrientToMovement;
|
||||
}
|
||||
|
||||
|
||||
// Called when the game starts
|
||||
void UTargetingComponent::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
ACharacter* character = Cast<ACharacter>(GetOwner());
|
||||
if(IsValid(character))
|
||||
{
|
||||
OwnerCharacter = character;
|
||||
OwnerController = OwnerCharacter->GetController();
|
||||
FollowCamera = OwnerCharacter->GetComponentByClass<UCameraComponent>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Called every frame
|
||||
void UTargetingComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
||||
{
|
||||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||||
|
||||
if(bIsTargeting)
|
||||
UpdateTargetingControlRotation();
|
||||
}
|
||||
|
||||
void UTargetingComponent::ToggleLockOn()
|
||||
{
|
||||
if(!bIsTargeting)
|
||||
EnableLockOn();
|
||||
else
|
||||
DisableLockOn();
|
||||
}
|
||||
|
||||
void UTargetingComponent::EnableLockOn()
|
||||
{
|
||||
AActor* FoundTarget;
|
||||
if(FindTarget(&FoundTarget) && CanTargetActor(FoundTarget))
|
||||
{
|
||||
SetTargetActor(FoundTarget);
|
||||
SetIsTargeting(true);
|
||||
UpdateRotationMode();
|
||||
}
|
||||
}
|
||||
|
||||
void UTargetingComponent::DisableLockOn()
|
||||
{
|
||||
SetIsTargeting(false);
|
||||
SetTargetActor(nullptr);
|
||||
UpdateRotationMode();
|
||||
}
|
||||
|
||||
void UTargetingComponent::SetIsTargeting(bool bEnableTargeting)
|
||||
{
|
||||
bIsTargeting = bEnableTargeting;
|
||||
if(IsValid(TargetActor))
|
||||
Cast<ITargetingInterface>(TargetActor)->OnTargeted(bEnableTargeting);
|
||||
}
|
||||
|
||||
void UTargetingComponent::SetRotationMode(ERotationMode NewRotationMode)
|
||||
{
|
||||
if(!IsValid(OwnerCharacter))
|
||||
return;
|
||||
UCharacterMovementComponent* CharacterMovement = OwnerCharacter->GetCharacterMovement();
|
||||
if(!IsValid(CharacterMovement))
|
||||
return;
|
||||
|
||||
CurrentRotationMode = NewRotationMode;
|
||||
switch (CurrentRotationMode)
|
||||
{
|
||||
case ERotationMode::OrientToCamera:
|
||||
OwnerCharacter->bUseControllerRotationYaw = false;
|
||||
CharacterMovement->bUseControllerDesiredRotation = true;
|
||||
CharacterMovement->bOrientRotationToMovement = false;
|
||||
break;
|
||||
case ERotationMode::OrientToMovement:
|
||||
OwnerCharacter->bUseControllerRotationYaw = false;
|
||||
CharacterMovement->bUseControllerDesiredRotation = false;
|
||||
CharacterMovement->bOrientRotationToMovement = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool UTargetingComponent::FindTarget(AActor** OutFoundTarget)
|
||||
{
|
||||
FVector StartLocation, EndLocation;
|
||||
StartLocation = GetOwner()->GetActorLocation();
|
||||
EndLocation = GetOwner()->GetActorLocation() + (FollowCamera->GetForwardVector() * TargetingDistance);
|
||||
|
||||
TArray<AActor*> ActorsToIgnore;
|
||||
ActorsToIgnore.Add(GetOwner());
|
||||
FHitResult OutHit;
|
||||
bool CollisionResult = UKismetSystemLibrary::SphereTraceSingleForObjects(GetWorld(), StartLocation, EndLocation, TargetingRadius, TargetObjectTypes, false, ActorsToIgnore, EDrawDebugTrace::None, OutHit, true);
|
||||
if(CollisionResult && IsValid(OutHit.GetActor()))
|
||||
{
|
||||
ITargetingInterface* targetingActor = Cast<ITargetingInterface>(OutHit.GetActor());
|
||||
if(targetingActor)
|
||||
{
|
||||
*OutFoundTarget = OutHit.GetActor();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UTargetingComponent::CanTargetActor(AActor* InTargetActor)
|
||||
{
|
||||
if(!IsValid(InTargetActor))
|
||||
return false;
|
||||
if(!IsValid(GetOwner()))
|
||||
return false;
|
||||
|
||||
ITargetingInterface* TargetActorInterface = Cast<ITargetingInterface>(InTargetActor);
|
||||
if(!TargetActorInterface)
|
||||
return false;
|
||||
|
||||
return ((GetOwner()->GetDistanceTo(TargetActor) < TargetingDistance) && TargetActorInterface->CanBeTargeted());
|
||||
}
|
||||
|
||||
void UTargetingComponent::UpdateTargetingControlRotation()
|
||||
{
|
||||
if(!IsValid(OwnerController))
|
||||
return;
|
||||
if(!IsValid(TargetActor))
|
||||
return;
|
||||
if(CanTargetActor(TargetActor))
|
||||
{
|
||||
FVector TargetLocation;
|
||||
TargetLocation = TargetActor->GetActorLocation() - FVector(0.f, 0.f, 100.f);
|
||||
FRotator TargetRotation = UKismetMathLibrary::FindLookAtRotation(GetOwner()->GetActorLocation(), TargetLocation);
|
||||
|
||||
FRotator CameraRotation = FMath::RInterpTo(OwnerController->K2_GetActorRotation(), TargetRotation, UGameplayStatics::GetWorldDeltaSeconds(GetOwner()), TargetRotationInterpSpeed);
|
||||
OwnerController->SetControlRotation(UKismetMathLibrary::MakeRotator(OwnerController->K2_GetActorRotation().Roll, CameraRotation.Pitch, CameraRotation.Yaw));
|
||||
}
|
||||
else
|
||||
DisableLockOn();
|
||||
|
||||
}
|
||||
|
||||
void UTargetingComponent::UpdateRotationMode()
|
||||
{
|
||||
if(!IsValid(OwnerCombatComponent))
|
||||
OwnerCombatComponent = OwnerCharacter->GetComponentByClass<UCombatComponent>();
|
||||
|
||||
bool result = OwnerCombatComponent->GetCombatEnabled();
|
||||
result &= (Cast<ICombatInterface>(OwnerCharacter)->GetCombatMovementSpeedMode() != EMovementSpeedMode::Sprinting);
|
||||
result &= GetIsTargeting();
|
||||
if(result)
|
||||
SetRotationMode(ERotationMode::OrientToCamera);
|
||||
else
|
||||
SetRotationMode(DefaultRotationMode);
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/ActorComponent.h"
|
||||
#include "TargetingComponent.generated.h"
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class ERotationMode : uint8
|
||||
{
|
||||
OrientToCamera UMETA(DisplayName = "OrientToCamera"),
|
||||
OrientToMovement UMETA(DisplayName = "OrientToMovement"),
|
||||
};
|
||||
|
||||
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
|
||||
class D1_API UTargetingComponent : public UActorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// Sets default values for this component's properties
|
||||
UTargetingComponent();
|
||||
|
||||
protected:
|
||||
// Called when the game starts
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
public:
|
||||
// Called every frame
|
||||
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
|
||||
|
||||
public:
|
||||
void ToggleLockOn();
|
||||
void EnableLockOn();
|
||||
void DisableLockOn();
|
||||
|
||||
void SetIsTargeting(bool bEnableTargeting);
|
||||
FORCEINLINE bool GetIsTargeting() { return bIsTargeting; }
|
||||
FORCEINLINE void SetTargetActor(AActor* NewTargetActor) { TargetActor = NewTargetActor; }
|
||||
FORCEINLINE AActor* GetTargetActor() { return TargetActor; }
|
||||
void SetRotationMode(ERotationMode NewRotationMode);
|
||||
FORCEINLINE ERotationMode GetRotationMode() { return CurrentRotationMode; }
|
||||
|
||||
bool FindTarget(AActor** OutFoundTarget);
|
||||
bool CanTargetActor(AActor* InTargetActor);
|
||||
void UpdateTargetingControlRotation();
|
||||
void UpdateRotationMode();
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Initialization")
|
||||
TArray<TEnumAsByte<EObjectTypeQuery>> TargetObjectTypes;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Initialization")
|
||||
float TargetingDistance;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Initialization")
|
||||
float TargetingRadius;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Initialization")
|
||||
float TargetRotationInterpSpeed;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Initialization")
|
||||
ERotationMode DefaultRotationMode;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components")
|
||||
TObjectPtr<class UCameraComponent> FollowCamera;
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components")
|
||||
TObjectPtr<class UCombatComponent> OwnerCombatComponent;
|
||||
|
||||
private:
|
||||
TObjectPtr<ACharacter> OwnerCharacter;
|
||||
TObjectPtr<AController> OwnerController;
|
||||
TObjectPtr<AActor> TargetActor;
|
||||
bool bIsTargeting;
|
||||
ERotationMode CurrentRotationMode;
|
||||
};
|
|
@ -3,6 +3,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Definitions/GameEnums.h"
|
||||
#include "UObject/Interface.h"
|
||||
#include "CombatInterface.generated.h"
|
||||
|
||||
|
@ -34,4 +35,6 @@ public:
|
|||
bool CanReceiveDamage();
|
||||
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
|
||||
void SetCanMove(bool inputCanMove);
|
||||
|
||||
virtual EMovementSpeedMode GetCombatMovementSpeedMode() = 0;
|
||||
};
|
||||
|
|
|
@ -24,5 +24,4 @@ class D1_API IIAnimInstance
|
|||
// Add interface functions to this class. This is the class that will be inherited to implement this interface.
|
||||
public:
|
||||
virtual void UpdateCombatType(ECombatType combatType) = 0;
|
||||
virtual void UpdateCombatEnabled(bool combatEnabled) = 0;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "Interface/TargetingInterface.h"
|
||||
|
||||
// Add default functionality here for any ITargetingInterface functions that are not pure virtual.
|
|
@ -0,0 +1,27 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Interface.h"
|
||||
#include "TargetingInterface.generated.h"
|
||||
|
||||
// This class does not need to be modified.
|
||||
UINTERFACE(MinimalAPI)
|
||||
class UTargetingInterface : public UInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class D1_API ITargetingInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
// Add interface functions to this class. This is the class that will be inherited to implement this interface.
|
||||
public:
|
||||
virtual bool CanBeTargeted() = 0;
|
||||
virtual void OnTargeted(bool bIsTargeted) = 0;
|
||||
};
|
|
@ -4,8 +4,20 @@
|
|||
#include "TestDummyCharacter.h"
|
||||
#include "Engine/DamageEvents.h"
|
||||
#include "Actor/BaseEquippable.h"
|
||||
#include "Components/WidgetComponent.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
|
||||
ATestDummyCharacter::ATestDummyCharacter()
|
||||
{
|
||||
//Setting Widget class is Editor to Blueprint
|
||||
LockOnWidgetComponent = CreateDefaultSubobject<UWidgetComponent>(TEXT("LockOnWidget"));
|
||||
LockOnWidgetComponent->SetWidgetSpace(EWidgetSpace::Screen);
|
||||
LockOnWidgetComponent->SetDrawSize({20.f, 20.f});
|
||||
LockOnWidgetComponent->SetupAttachment(RootComponent);
|
||||
LockOnWidgetComponent->SetRelativeLocation(FVector(0.f, 0.f, 40.f));
|
||||
LockOnWidgetComponent->SetVisibility(false);
|
||||
}
|
||||
|
||||
void ATestDummyCharacter::BeginPlay()
|
||||
{
|
||||
ACharacter::BeginPlay();
|
||||
|
@ -22,6 +34,19 @@ void ATestDummyCharacter::BeginPlay()
|
|||
}
|
||||
}
|
||||
|
||||
bool ATestDummyCharacter::CanBeTargeted()
|
||||
{
|
||||
FGameplayTagContainer inputContainer;
|
||||
inputContainer.AddTag(FCombatGameplayTags::Get().Character_State_Dead);
|
||||
|
||||
return !StateManagerComponent->IsCurrentStateEqualToAny(inputContainer);
|
||||
}
|
||||
|
||||
void ATestDummyCharacter::OnTargeted(bool bIsTargeted)
|
||||
{
|
||||
LockOnWidgetComponent->SetVisibility(bIsTargeted);
|
||||
}
|
||||
|
||||
//float ATestDummyCharacter::TakeDamage(float Damage, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
|
||||
//{
|
||||
// float fDamage = ACharacter::TakeDamage(Damage, DamageEvent, EventInstigator, DamageCauser);
|
||||
|
|
|
@ -4,20 +4,30 @@
|
|||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CombatCharacter.h"
|
||||
#include "Interface/TargetingInterface.h"
|
||||
#include "TestDummyCharacter.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class D1_API ATestDummyCharacter : public ACombatCharacter
|
||||
class D1_API ATestDummyCharacter : public ACombatCharacter, public ITargetingInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
public:
|
||||
ATestDummyCharacter();
|
||||
public:
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
protected:
|
||||
// Inherited via ITargetingInterface
|
||||
virtual bool CanBeTargeted() override;
|
||||
virtual void OnTargeted(bool bIsTargeted) override;
|
||||
public:
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
|
||||
TArray<TSubclassOf<class ABaseEquippable>> StartingEquipment;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="UI")
|
||||
TObjectPtr<class UWidgetComponent> LockOnWidgetComponent;
|
||||
|
||||
};
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "UI/UI_LockOn.h"
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Blueprint/UserWidget.h"
|
||||
#include "UI_LockOn.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class D1_API UUI_LockOn : public UUserWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(BindWidget))
|
||||
TObjectPtr<class UImage> LockOnPoint;
|
||||
};
|
Loading…
Reference in New Issue