From 4144aaa60aa443580bd5eeb7bc351788ca85697b Mon Sep 17 00:00:00 2001 From: "PCYPC\\pcy35" Date: Mon, 4 Sep 2023 18:16:52 +0900 Subject: [PATCH] =?UTF-8?q?[=EB=B0=95=EC=B9=98=EC=98=81]=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EB=B3=80=EA=B2=BD=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Config/DefaultEngine.ini | 13 +- .../Animnotifies/ToggleCombat_AN.uasset | Bin 25194 -> 34990 bytes .../Blueprints/BP_CombatCharacter.uasset | Bin 38372 -> 37980 bytes .../AI/BehaviorTreeNodes/T_PerformAction.cpp | 2 +- .../AI/BehaviorTreeNodes/T_PerformAttack.cpp | 2 +- Source/D1/AI/BossEnemy.cpp | 1 - Source/D1/AI/BossEnemy.h | 6 +- Source/D1/AI/MasterAI.cpp | 13 +- Source/D1/AI/MasterAI.h | 7 +- Source/D1/Actor/BaseWeapon.cpp | 6 +- ...haracter.cpp => CombatPlayerCharacter.cpp} | 317 +++++------------- ...batCharacter.h => CombatPlayerCharacter.h} | 18 +- Source/D1/Components/CollisionComponent.cpp | 11 + Source/D1/Components/CollisionComponent.h | 1 + Source/D1/D1GameMode.cpp | 2 +- Source/D1/Interface/CombatInterface.cpp | 4 +- Source/D1/Interface/CombatInterface.h | 6 +- Source/D1/UI/CombatHUD.cpp | 7 - Source/D1/UI/UI_HealthBar.cpp | 2 +- Source/D1/UI/UI_HealthBar.h | 2 - Source/D1/UI/UI_StatBar.cpp | 22 +- Source/D1/UI/UI_StatBar.h | 2 + 22 files changed, 141 insertions(+), 303 deletions(-) rename Source/D1/{CombatCharacter.cpp => CombatPlayerCharacter.cpp} (69%) rename Source/D1/{CombatCharacter.h => CombatPlayerCharacter.h} (92%) diff --git a/Config/DefaultEngine.ini b/Config/DefaultEngine.ini index 694bbe3a..a767fe5a 100644 --- a/Config/DefaultEngine.ini +++ b/Config/DefaultEngine.ini @@ -107,6 +107,8 @@ ManualIPAddress= +Profiles=(Name="Vehicle",CollisionEnabled=QueryAndPhysics,bCanModify=False,ObjectTypeName="Vehicle",CustomResponses=,HelpMessage="Vehicle object that blocks Vehicle, WorldStatic, and WorldDynamic. All other channels will be set to default.") +Profiles=(Name="UI",CollisionEnabled=QueryOnly,bCanModify=False,ObjectTypeName="WorldDynamic",CustomResponses=((Channel="WorldStatic",Response=ECR_Overlap),(Channel="Pawn",Response=ECR_Overlap),(Channel="Visibility"),(Channel="WorldDynamic",Response=ECR_Overlap),(Channel="Camera",Response=ECR_Overlap),(Channel="PhysicsBody",Response=ECR_Overlap),(Channel="Vehicle",Response=ECR_Overlap),(Channel="Destructible",Response=ECR_Overlap)),HelpMessage="WorldStatic object that overlaps all actors by default. All new custom channels will use its own default response. ") +DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,DefaultResponse=ECR_Block,bTraceType=False,bStaticObject=False,Name="Interactable") ++EditProfiles=(Name="Pawn",CustomResponses=((Channel="Camera",Response=ECR_Ignore))) ++EditProfiles=(Name="CharacterMesh",CustomResponses=((Channel="Camera",Response=ECR_Ignore))) -ProfileRedirects=(OldName="BlockingVolume",NewName="InvisibleWall") -ProfileRedirects=(OldName="InterpActor",NewName="IgnoreOnlyPawn") -ProfileRedirects=(OldName="StaticMeshComponent",NewName="BlockAllDynamic") @@ -126,18 +128,21 @@ ManualIPAddress= +CollisionChannelRedirects=(OldName="VehicleMovement",NewName="Vehicle") +CollisionChannelRedirects=(OldName="PawnMovement",NewName="Pawn") - [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.CombatCharacter.ToogleLockOnAction",NewName="/Script/D1.CombatCharacter.ToggleLockOnAction") ++PropertyRedirects=(OldName="/Script/D1.CombatCharacter.ToogleLockOnAction",NewName="/Script/D1.CombatPlayerCharacter.ToggleLockOnAction") +ClassRedirects=(OldName="/Script/D1.UI_LockOnComponent",NewName="/Script/D1.LockOnWidgetComponent") +PropertyRedirects=(OldName="/Script/D1.MasterAI.TargetingWidget",NewName="/Script/D1.MasterAI.TargetingWidgetComponent") +PropertyRedirects=(OldName="/Script/D1.HumanoidEnemy.HealthBar",NewName="/Script/D1.HumanoidEnemy.HealthBarComponent") +PropertyRedirects=(OldName="/Script/D1.T_FindNextPatrolPoint.TargetLocation",NewName="/Script/D1.T_FindNextPatrolPoint.BlackboardKey_TargetLocation") +PropertyRedirects=(OldName="/Script/D1.T_FindNextPatrolPoint.PatrolIndex",NewName="/Script/D1.T_FindNextPatrolPoint.BlackboardKey_PatrolIndex") -+PropertyRedirects=(OldName="/Script/D1.CombatCharacter.ToggleCombatAction",NewName="/Script/D1.CombatCharacter.ToggleCombatInputAction") ++PropertyRedirects=(OldName="/Script/D1.CombatCharacter.ToggleCombatAction",NewName="/Script/D1.CombatPlayerCharacter.ToggleCombatInputAction") +FunctionRedirects=(OldName="/Script/D1.BaseWeapon.ToggleCombat",NewName="/Script/D1.BaseWeapon.ToggleWeaponCombat") +PropertyRedirects=(OldName="/Script/D1.S_UpdateBehavior.AttackingRange",NewName="/Script/D1.S_UpdateBehavior.TotalAttackingDistance") -+PropertyRedirects=(OldName="/Script/D1.S_UpdateBehavior.TotalAttackingDistanceRange",NewName="/Script/D1.S_UpdateBehavior.TotalAttackingDistance") \ No newline at end of file ++PropertyRedirects=(OldName="/Script/D1.S_UpdateBehavior.TotalAttackingDistanceRange",NewName="/Script/D1.S_UpdateBehavior.TotalAttackingDistance") ++ClassRedirects=(OldName="/Script/D1.CombatCharacter",NewName="/Script/D1.CombatPlayerCharacter") ++FunctionRedirects=(OldName="/Script/D1.ICombatInterface.PerformCombatAction",NewName="/Script/D1.ICombatInterface.PerformAction") ++FunctionRedirects=(OldName="/Script/D1.ICombatInterface.PerformCombatAttack",NewName="/Script/D1.ICombatInterface.PerformAttack") + diff --git a/Content/CombatSystem/Blueprints/Animnotifies/ToggleCombat_AN.uasset b/Content/CombatSystem/Blueprints/Animnotifies/ToggleCombat_AN.uasset index 9cab9deaffa85c3a9a8fc157d958d8516722d70a..87cc86bd822def4df0e0c67b45a7f6086a0b9c8a 100644 GIT binary patch literal 34990 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 Z6-4^s6B8*B5^=xj7SMJTS4vs@e*m@=yX*h} diff --git a/Source/D1/AI/BehaviorTreeNodes/T_PerformAction.cpp b/Source/D1/AI/BehaviorTreeNodes/T_PerformAction.cpp index 841b65f1..3cfeb6e3 100644 --- a/Source/D1/AI/BehaviorTreeNodes/T_PerformAction.cpp +++ b/Source/D1/AI/BehaviorTreeNodes/T_PerformAction.cpp @@ -19,7 +19,7 @@ EBTNodeResult::Type UT_PerformAction::ExecuteTask(UBehaviorTreeComponent& OwnerC if(!CombatInterface) return EBTNodeResult::Failed; - float actionDuration = CombatInterface->PerformCombatAction(ActionTag, StateTag, MontageIndex, RandomIndex); + float actionDuration = CombatInterface->PerformAction(ActionTag, StateTag, MontageIndex, RandomIndex); actionDuration += ActionDurationModifier; FTimerHandle ActionTimer; GetWorld()->GetTimerManager().SetTimer(ActionTimer, FTimerDelegate::CreateLambda([&]() diff --git a/Source/D1/AI/BehaviorTreeNodes/T_PerformAttack.cpp b/Source/D1/AI/BehaviorTreeNodes/T_PerformAttack.cpp index 7e3d9375..2c92d300 100644 --- a/Source/D1/AI/BehaviorTreeNodes/T_PerformAttack.cpp +++ b/Source/D1/AI/BehaviorTreeNodes/T_PerformAttack.cpp @@ -19,7 +19,7 @@ EBTNodeResult::Type UT_PerformAttack::ExecuteTask(UBehaviorTreeComponent& OwnerC if(!CombatInterface) return EBTNodeResult::Failed; - float actionDuration = CombatInterface->PerformCombatAttack(AttackTypeTag, AttackIndex, RandomIndex); + float actionDuration = CombatInterface->PerformAttack(AttackTypeTag, AttackIndex, RandomIndex); actionDuration += ActionDurationModifier; FTimerHandle ActionTimer; GetWorld()->GetTimerManager().SetTimer(ActionTimer, FTimerDelegate::CreateLambda([&]() diff --git a/Source/D1/AI/BossEnemy.cpp b/Source/D1/AI/BossEnemy.cpp index 9ccb13b5..8eab5019 100644 --- a/Source/D1/AI/BossEnemy.cpp +++ b/Source/D1/AI/BossEnemy.cpp @@ -9,7 +9,6 @@ #include "Components/CombatComponent.h" #include "DamageType/AttackDamageType.h" #include "Kismet/GameplayStatics.h" -#include "UI/UI_BossHealth.h" #include "UI/UI_HealthBar.h" ABossEnemy::ABossEnemy() diff --git a/Source/D1/AI/BossEnemy.h b/Source/D1/AI/BossEnemy.h index 5fb0c951..372e6c19 100644 --- a/Source/D1/AI/BossEnemy.h +++ b/Source/D1/AI/BossEnemy.h @@ -48,9 +48,5 @@ private: UPROPERTY(EditAnywhere, Blueprintable, Category="Initialization", meta=(AllowPrivateAccess="true")) FName WeaponHandSocketName; UPROPERTY(VisibleAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess="true")) - TObjectPtr BossHealthWidget; - UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess="true")) - TSubclassOf BossHealthClass; - - + TObjectPtr BossHealthWidget; }; diff --git a/Source/D1/AI/MasterAI.cpp b/Source/D1/AI/MasterAI.cpp index cc3b750b..3e1e7c4b 100644 --- a/Source/D1/AI/MasterAI.cpp +++ b/Source/D1/AI/MasterAI.cpp @@ -195,14 +195,7 @@ void AMasterAI::DeactivateCollision_Implementation(ECollisionPart CollisionPart) MainWeaponCollisionComponent->DeactivateCollision(); } -void AMasterAI::ToggleCombat_Implementation() -{ - if (!IsValid(CombatComponent)) - return; - CombatComponent->SetCombatEnabled(!CombatComponent->GetCombatEnabled()); -} - -float AMasterAI::PerformCombatAction(FGameplayTag ActionTag, FGameplayTag StateTag, int32 MontageIndex, bool bRandomIndex) +float AMasterAI::PerformAction(FGameplayTag ActionTag, FGameplayTag StateTag, int32 MontageIndex, bool bRandomIndex) { TArray montages = GetActionMontage(ActionTag); int32 montageIdx = MontageIndex; @@ -232,7 +225,7 @@ float AMasterAI::PerformCombatAction(FGameplayTag ActionTag, FGameplayTag StateT return actionDuration; } -float AMasterAI::PerformCombatAttack(FGameplayTag AttackType, int32 AttackIndex, bool bRandomIndex) +float AMasterAI::PerformAttack(FGameplayTag AttackType, int32 AttackIndex, bool bRandomIndex) { TArray montages = GetActionMontage(AttackType); int32 attackIdx = AttackIndex; @@ -353,7 +346,7 @@ void AMasterAI::AttackEvent() return; if (CombatComponent->GetCombatEnabled()) - PerformCombatAttack(GetDesiredAttackType(), CombatComponent->GetAttackCount(), false); + PerformAttack(GetDesiredAttackType(), CombatComponent->GetAttackCount(), false); } void AMasterAI::ApplyHitReactionPhysicsVelocity(float InitialSpeed) diff --git a/Source/D1/AI/MasterAI.h b/Source/D1/AI/MasterAI.h index edd12168..a4f1ab26 100644 --- a/Source/D1/AI/MasterAI.h +++ b/Source/D1/AI/MasterAI.h @@ -63,13 +63,10 @@ public: UFUNCTION(BlueprintCallable, BlueprintNativeEvent) void DeactivateCollision(ECollisionPart CollisionPart); virtual void DeactivateCollision_Implementation(ECollisionPart CollisionPart) override; - UFUNCTION(BlueprintCallable, BlueprintNativeEvent) - void ToggleCombat(); - virtual void ToggleCombat_Implementation() override; virtual EMovementSpeedMode GetCombatMovementSpeedMode() override { return GetMovementSpeedMode(); } - virtual float PerformCombatAction(FGameplayTag ActionTag, FGameplayTag StateTag, int32 MontageIndex, bool bRandomIndex); - virtual float PerformCombatAttack(FGameplayTag AttackType, int32 AttackIndex, bool bRandomIndex); + virtual float PerformAction(FGameplayTag ActionTag, FGameplayTag StateTag, int32 MontageIndex, bool bRandomIndex); + virtual float PerformAttack(FGameplayTag AttackType, int32 AttackIndex, bool bRandomIndex); // Inherited via ITargetingInterface virtual bool CanBeTargeted() override; diff --git a/Source/D1/Actor/BaseWeapon.cpp b/Source/D1/Actor/BaseWeapon.cpp index 47a5695f..0d6cd9b8 100644 --- a/Source/D1/Actor/BaseWeapon.cpp +++ b/Source/D1/Actor/BaseWeapon.cpp @@ -51,6 +51,8 @@ void ABaseWeapon::OnEquipped() if (!owner) return; CombatComponent = owner->GetComponentByClass(); + CombatComponent->OnCombatToggled.AddUObject(this, &ABaseWeapon::ToggleWeaponCombat); + OwnerStateManager = owner->GetComponentByClass(); if (CombatComponent->GetCombatEnabled()) @@ -117,10 +119,6 @@ void ABaseWeapon::DeactivateCollision(ECollisionPart CollsionPart) void ABaseWeapon::ToggleWeaponCombat(bool EnableCombat) { - if(!CombatComponent) - return; - - CombatComponent->SetCombatEnabled(EnableCombat); if(EnableCombat) AttachActor(HandSocketName); else diff --git a/Source/D1/CombatCharacter.cpp b/Source/D1/CombatPlayerCharacter.cpp similarity index 69% rename from Source/D1/CombatCharacter.cpp rename to Source/D1/CombatPlayerCharacter.cpp index 41b01894..11c89028 100644 --- a/Source/D1/CombatCharacter.cpp +++ b/Source/D1/CombatPlayerCharacter.cpp @@ -1,6 +1,6 @@ // Copyright Epic Games, Inc. All Rights Reserved. -#include "CombatCharacter.h" +#include "CombatPlayerCharacter.h" #include "Camera/CameraComponent.h" #include "Components/CapsuleComponent.h" #include "Components/InputComponent.h" @@ -16,7 +16,6 @@ #include "Definitions/CombatGameplayTags.h" #include "Engine/DamageEvents.h" #include "NiagaraFunctionLibrary.h" -#include "NiagaraComponent.h" #include "DamageType/AttackDamageType.h" #include "Kismet/KismetSystemLibrary.h" #include "Kismet/KismetMathLibrary.h" @@ -25,7 +24,7 @@ ////////////////////////////////////////////////////////////////////////// // ACombatCharacter -ACombatCharacter::ACombatCharacter() +ACombatPlayerCharacter::ACombatPlayerCharacter() { // Set size for collision capsule GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f); @@ -70,19 +69,24 @@ ACombatCharacter::ACombatCharacter() // Setting CombatComponent CombatComponent = CreateDefaultSubobject(TEXT("CombatComponent")); - CombatComponent->OnCombatToggled.AddUObject(this, &ACombatCharacter::CharacterCombatToggled); + CombatComponent->OnCombatToggled.AddUObject(this, &ACombatPlayerCharacter::CharacterCombatToggled); // Setting StateManagerComponent StateManagerComponent = CreateDefaultSubobject(TEXT("StateManagerComponent")); - StateManagerComponent->OnStateBegin.AddUObject(this, &ACombatCharacter::CharacterStateBegin); - StateManagerComponent->OnStateEnd.AddUObject(this, &ACombatCharacter::CharacterStateEnd); - StateManagerComponent->OnActionBegin.AddUObject(this, &ACombatCharacter::CharacterActionBegin); - StateManagerComponent->OnActionEnd.AddUObject(this, &ACombatCharacter::CharacterActionEnd); + StateManagerComponent->OnStateBegin.AddUObject(this, &ACombatPlayerCharacter::CharacterStateBegin); + StateManagerComponent->OnStateEnd.AddUObject(this, &ACombatPlayerCharacter::CharacterStateEnd); // Setting StatsComponent StatsComponent = CreateDefaultSubobject(TEXT("StatsComponent")); - StatsComponent->OnCurrentStatValueUpdated.AddUObject(this, &ACombatCharacter::CharacterCurrentStatValueUpdated); - + StatsComponent->OnCurrentStatValueUpdated.AddUObject(this, &ACombatPlayerCharacter::CharacterCurrentStatValueUpdated); + StatsComponent->SetBaseStatValue(EStats::Health, 100.f); + StatsComponent->SetMaxStatValue(EStats::Health, 100.f); + StatsComponent->SetBaseStatValue(EStats::Stamina, 100.f); + StatsComponent->SetMaxStatValue(EStats::Stamina, 100.f); + StatsComponent->SetBaseStatValue(EStats::Armor, 0.f); + StatsComponent->SetMaxStatValue(EStats::Armor, 100.f); + StatsComponent->InitializeStats(); + //Setting TargetComponent TargetingComponent = CreateDefaultSubobject(TEXT("TargetingComponent")); @@ -100,7 +104,7 @@ ACombatCharacter::ACombatCharacter() } -void ACombatCharacter::BeginPlay() +void ACombatPlayerCharacter::BeginPlay() { // Call the base class Super::BeginPlay(); @@ -121,11 +125,9 @@ void ACombatCharacter::BeginPlay() ABaseEquippable* SpawnItem = Cast(GetWorld()->SpawnActor(Weapon, &GetActorTransform(), spawnParam)); if (SpawnItem) SpawnItem->OnEquipped(); - - StatsComponent->InitializeStats(); } -float ACombatCharacter::TakeDamage(float Damage, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) +float ACombatPlayerCharacter::TakeDamage(float Damage, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) { float fDamage = Super::TakeDamage(Damage, DamageEvent, EventInstigator, DamageCauser); @@ -153,7 +155,7 @@ float ACombatCharacter::TakeDamage(float Damage, FDamageEvent const& DamageEvent return fDamage; } -void ACombatCharacter::ContinueAttack_Implementation() +void ACombatPlayerCharacter::ContinueAttack_Implementation() { if (CombatComponent->GetIsAttackSaved()) { @@ -164,19 +166,19 @@ void ACombatCharacter::ContinueAttack_Implementation() } } -void ACombatCharacter::ResetAttack_Implementation() +void ACombatPlayerCharacter::ResetAttack_Implementation() { CombatComponent->ResetAttack(); } -void ACombatCharacter::ResetCombat_Implementation() +void ACombatPlayerCharacter::ResetCombat_Implementation() { CombatComponent->ResetAttack(); StateManagerComponent->ResetState(); StateManagerComponent->SetCurrentAction(FGameplayTag::EmptyTag); } -FRotator ACombatCharacter::GetDesiredRotation_Implementation() +FRotator ACombatPlayerCharacter::GetDesiredRotation_Implementation() { FVector InputVector = GetCharacterMovement()->GetLastInputVector(); if (InputVector.Equals(FVector(0, 0, 0), 0.001f)) @@ -185,7 +187,7 @@ FRotator ACombatCharacter::GetDesiredRotation_Implementation() return UKismetMathLibrary::MakeRotFromX(GetLastMovementInputVector()); } -bool ACombatCharacter::CanReceiveDamage_Implementation() +bool ACombatPlayerCharacter::CanReceiveDamage_Implementation() { bool result; result = (StateManagerComponent->GetCurrentState() != FCombatGameplayTags::Get().Character_State_Dead); @@ -195,78 +197,70 @@ bool ACombatCharacter::CanReceiveDamage_Implementation() ////////////////////////////////////////////////////////////////////////// // Input -void ACombatCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) +void ACombatPlayerCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) { // Set up action bindings if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked(PlayerInputComponent)) { //Jumping - EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Triggered, this, &ACombatCharacter::Jumping); + EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Triggered, this, &ACombatPlayerCharacter::Jumping); EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping); //Moving - EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &ACombatCharacter::Move); + EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &ACombatPlayerCharacter::Move); //Looking - EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &ACombatCharacter::Look); + EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &ACombatPlayerCharacter::Look); //Interact - EnhancedInputComponent->BindAction(InteractAction, ETriggerEvent::Started, this, &ACombatCharacter::Interact); + EnhancedInputComponent->BindAction(InteractAction, ETriggerEvent::Started, this, &ACombatPlayerCharacter::Interact); //ToggleCombat - EnhancedInputComponent->BindAction(ToggleCombatInputAction, ETriggerEvent::Started, this, &ACombatCharacter::ToggleCombatAction); + EnhancedInputComponent->BindAction(ToggleCombatInputAction, ETriggerEvent::Started, this, &ACombatPlayerCharacter::ToggleCombatAction); //LightAttack - EnhancedInputComponent->BindAction(LightAttackAction, ETriggerEvent::Triggered, this, &ACombatCharacter::LightChargeAttack); - EnhancedInputComponent->BindAction(LightAttackAction, ETriggerEvent::Completed, this, &ACombatCharacter::LightAttack); + EnhancedInputComponent->BindAction(LightAttackAction, ETriggerEvent::Triggered, this, &ACombatPlayerCharacter::LightChargeAttack); + EnhancedInputComponent->BindAction(LightAttackAction, ETriggerEvent::Completed, this, &ACombatPlayerCharacter::LightAttack); //HeavyAttack - EnhancedInputComponent->BindAction(HeavyAttackAction, ETriggerEvent::Started, this, &ACombatCharacter::HeavyAttack); + EnhancedInputComponent->BindAction(HeavyAttackAction, ETriggerEvent::Started, this, &ACombatPlayerCharacter::HeavyAttack); //Dodge - EnhancedInputComponent->BindAction(DodgeAction, ETriggerEvent::Started, this, &ACombatCharacter::Dodge); + EnhancedInputComponent->BindAction(DodgeAction, ETriggerEvent::Started, this, &ACombatPlayerCharacter::Dodge); //ToggleWalk - EnhancedInputComponent->BindAction(ToggleWalkAction, ETriggerEvent::Started, this, &ACombatCharacter::ToggleWalk); + EnhancedInputComponent->BindAction(ToggleWalkAction, ETriggerEvent::Started, this, &ACombatPlayerCharacter::ToggleWalk); //Sprint - EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Started, this, &ACombatCharacter::StartSprint); - EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Completed, this, &ACombatCharacter::StopSprint); + EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Started, this, &ACombatPlayerCharacter::StartSprint); + EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Completed, this, &ACombatPlayerCharacter::StopSprint); //ToggleLockOn - EnhancedInputComponent->BindAction(ToggleLockOnAction, ETriggerEvent::Started, this, &ACombatCharacter::ToggleLockOn); + EnhancedInputComponent->BindAction(ToggleLockOnAction, ETriggerEvent::Started, this, &ACombatPlayerCharacter::ToggleLockOn); } } -void ACombatCharacter::SetCanMove_Implementation(bool inputCanMove) +void ACombatPlayerCharacter::SetCanMove_Implementation(bool inputCanMove) { bCanMove = inputCanMove; } -void ACombatCharacter::ActivateCollision_Implementation(ECollisionPart CollisionPart) +void ACombatPlayerCharacter::ActivateCollision_Implementation(ECollisionPart CollisionPart) { ABaseWeapon* weapon = CombatComponent->GetMainWeapon(); if(IsValid(weapon)) weapon->ActivateCollision(CollisionPart); } -void ACombatCharacter::DeactivateCollision_Implementation(ECollisionPart CollisionPart) +void ACombatPlayerCharacter::DeactivateCollision_Implementation(ECollisionPart CollisionPart) { ABaseWeapon* weapon = CombatComponent->GetMainWeapon(); if(IsValid(weapon)) weapon->DeactivateCollision(CollisionPart); } -void ACombatCharacter::ToggleCombat_Implementation() +float ACombatPlayerCharacter::PerformAction(FGameplayTag ActionTag, FGameplayTag StateTag, int32 MontageIndex, bool bRandomIndex) { - ABaseWeapon* weapon = CombatComponent->GetMainWeapon(); - if (IsValid(weapon)) - weapon->ToggleWeaponCombat(!CombatComponent->GetCombatEnabled()); -} - -float ACombatCharacter::PerformCombatAction(FGameplayTag ActionTag, FGameplayTag StateTag, int32 MontageIndex, bool bRandomIndex) -{ - //TODO : 나중에 이 함수로 바꿔서 쓰기 혹시 몰라 구현만 해놓음 ABaseWeapon* CurrentWeapon = CombatComponent->GetMainWeapon(); if (!CurrentWeapon) return false; @@ -299,9 +293,8 @@ float ACombatCharacter::PerformCombatAction(FGameplayTag ActionTag, FGameplayTag return actionDuration; } -float ACombatCharacter::PerformCombatAttack(FGameplayTag AttackType, int32 AttackIndex, bool bRandomIndex) +float ACombatPlayerCharacter::PerformAttack(FGameplayTag AttackType, int32 AttackIndex, bool bRandomIndex) { - //TODO : 나중에 이 함수로 바꿔서 쓰기 혹시 몰라 구현만 해놓음 if(!CombatComponent->GetCombatEnabled()) return 0.f; @@ -343,7 +336,7 @@ float ACombatCharacter::PerformCombatAttack(FGameplayTag AttackType, int32 Attac return attackDuration; } -void ACombatCharacter::SetMovementSpeedMode(EMovementSpeedMode NewSpeedMode) +void ACombatPlayerCharacter::SetMovementSpeedMode(EMovementSpeedMode NewSpeedMode) { if (NewSpeedMode == MovementSpeedMode) return; @@ -367,7 +360,7 @@ void ACombatCharacter::SetMovementSpeedMode(EMovementSpeedMode NewSpeedMode) } } -void ACombatCharacter::Move(const FInputActionValue& Value) +void ACombatPlayerCharacter::Move(const FInputActionValue& Value) { if(!bCanMove) //Value changes SetCanMove Func Call to Animnotify return; @@ -393,7 +386,7 @@ void ACombatCharacter::Move(const FInputActionValue& Value) } } -void ACombatCharacter::Look(const FInputActionValue& Value) +void ACombatPlayerCharacter::Look(const FInputActionValue& Value) { // input is a Vector2D FVector2D LookAxisVector = Value.Get(); @@ -411,7 +404,7 @@ void ACombatCharacter::Look(const FInputActionValue& Value) } } -void ACombatCharacter::Jumping(const FInputActionValue& Value) +void ACombatPlayerCharacter::Jumping(const FInputActionValue& Value) { if (!CanJumping()) return; @@ -422,7 +415,7 @@ void ACombatCharacter::Jumping(const FInputActionValue& Value) Super::Jump(); } -void ACombatCharacter::Interact(const FInputActionValue& Value) +void ACombatPlayerCharacter::Interact(const FInputActionValue& Value) { bool bInput = Value.Get(); @@ -440,14 +433,14 @@ void ACombatCharacter::Interact(const FInputActionValue& Value) } } -void ACombatCharacter::ToggleCombatAction(const FInputActionValue& Value) +void ACombatPlayerCharacter::ToggleCombatAction(const FInputActionValue& Value) { bool bInput = Value.Get(); ToggleCombatEvent(); } -void ACombatCharacter::LightAttack(const FInputActionValue& Value) +void ACombatPlayerCharacter::LightAttack(const FInputActionValue& Value) { if (!ResetChargeAttack()) return; @@ -460,7 +453,7 @@ void ACombatCharacter::LightAttack(const FInputActionValue& Value) } //누르고 있는 시간을 받기 위해서 FInputActionValue가 아니라 FInputActionInstance로 인자값을 받음 -void ACombatCharacter::LightChargeAttack(const FInputActionInstance& Instance) +void ACombatPlayerCharacter::LightChargeAttack(const FInputActionInstance& Instance) { AttackHeldTime = Instance.GetElapsedTime(); bAttackCharged = (AttackHeldTime >= ChargeAttackTime); @@ -468,7 +461,7 @@ void ACombatCharacter::LightChargeAttack(const FInputActionInstance& Instance) ChargeAttackEvent(); } -void ACombatCharacter::HeavyAttack(const FInputActionValue& Value) +void ACombatPlayerCharacter::HeavyAttack(const FInputActionValue& Value) { if (bAttackCharged) return; @@ -479,11 +472,11 @@ void ACombatCharacter::HeavyAttack(const FInputActionValue& Value) AttackEvent(); } -void ACombatCharacter::Dodge(const FInputActionValue& Value) +void ACombatPlayerCharacter::Dodge(const FInputActionValue& Value) { if (CanPerformDodge()) { - PerformDodge(); + PerformAction(FCombatGameplayTags::Get().Character_Action_Dodge, FCombatGameplayTags::Get().Character_State_Dodging, 0); ABaseWeapon* pBaseWeapon = CombatComponent->GetMainWeapon(); if (IsValid(pBaseWeapon)) { @@ -493,7 +486,7 @@ void ACombatCharacter::Dodge(const FInputActionValue& Value) } -void ACombatCharacter::ToggleWalk(const FInputActionValue& Value) +void ACombatPlayerCharacter::ToggleWalk(const FInputActionValue& Value) { if (GetCombatMovementSpeedMode() != EMovementSpeedMode::Walking) SetMovementSpeedMode(EMovementSpeedMode::Walking); @@ -502,30 +495,28 @@ void ACombatCharacter::ToggleWalk(const FInputActionValue& Value) } -void ACombatCharacter::StartSprint(const FInputActionValue& Value) +void ACombatPlayerCharacter::StartSprint(const FInputActionValue& Value) { if (CanPerformSprint()) { SetMovementSpeedMode(EMovementSpeedMode::Sprinting); UWorld* World = GEngine->GetWorldFromContextObjectChecked(this); if (World) - World->GetTimerManager().SetTimer(StaminaTimerHandle, this, &ACombatCharacter::SprintStaminaCost, 0.1f, true); + World->GetTimerManager().SetTimer(StaminaTimerHandle, this, &ACombatPlayerCharacter::SprintStaminaCost, 0.1f, true); } } -void ACombatCharacter::StopSprint(const FInputActionValue& Value) +void ACombatPlayerCharacter::StopSprint(const FInputActionValue& Value) { DisableSprint(); } -void ACombatCharacter::ToggleLockOn(const FInputActionValue& Value) +void ACombatPlayerCharacter::ToggleLockOn(const FInputActionValue& Value) { - if(!CombatComponent->GetCombatEnabled() && !TargetingComponent->GetIsTargeting()) - return; TargetingComponent->ToggleLockOn(); } -void ACombatCharacter::CharacterStateBegin(FGameplayTag CharState) +void ACombatPlayerCharacter::CharacterStateBegin(FGameplayTag CharState) { if (FGameplayTag::EmptyTag == CharState) {/*None*/} @@ -543,7 +534,7 @@ void ACombatCharacter::CharacterStateBegin(FGameplayTag CharState) {/*None*/} } -void ACombatCharacter::CharacterStateEnd(FGameplayTag CharState) +void ACombatPlayerCharacter::CharacterStateEnd(FGameplayTag CharState) { if (FGameplayTag::EmptyTag == CharState) {/*None*/} @@ -559,55 +550,7 @@ void ACombatCharacter::CharacterStateEnd(FGameplayTag CharState) {/*None*/} } -void ACombatCharacter::CharacterActionBegin(FGameplayTag CharAction) -{ - if(FGameplayTag::EmptyTag == CharAction) - {/*None*/ } - else if(FCombatGameplayTags::Get().Character_Action_GeneralAction == CharAction) - {/*None*/ } - else if(FCombatGameplayTags::Get().Character_Action_Dodge == CharAction) - {/*None*/ } - else if(FCombatGameplayTags::Get().Character_Action_EnterCombat == CharAction) - {/*None*/ } - else if(FCombatGameplayTags::Get().Character_Action_ExitCombat == CharAction) - {/*None*/ } - else if(FCombatGameplayTags::Get().Character_Action_Attack_LightAttack == CharAction) - {/*None*/ } - else if(FCombatGameplayTags::Get().Character_Action_Attack_HeavyAttack == CharAction) - {/*None*/ } - else if(FCombatGameplayTags::Get().Character_Action_Attack_ChargedAttack == CharAction) - {/*None*/ } - else if(FCombatGameplayTags::Get().Character_Action_Attack_FallingAttack == CharAction) - {/*None*/ } - else if(FCombatGameplayTags::Get().Character_Action_Attack_SprintAttack == CharAction) - {/*None*/ } -} - -void ACombatCharacter::CharacterActionEnd(FGameplayTag CharAction) -{ - if(FGameplayTag::EmptyTag == CharAction) - {/*None*/ } - else if(FCombatGameplayTags::Get().Character_Action_GeneralAction == CharAction) - {/*None*/ } - else if(FCombatGameplayTags::Get().Character_Action_Dodge == CharAction) - {/*None*/ } - else if(FCombatGameplayTags::Get().Character_Action_EnterCombat == CharAction) - {/*None*/ } - else if(FCombatGameplayTags::Get().Character_Action_ExitCombat == CharAction) - {/*None*/ } - else if(FCombatGameplayTags::Get().Character_Action_Attack_LightAttack == CharAction) - {/*None*/ } - else if(FCombatGameplayTags::Get().Character_Action_Attack_HeavyAttack == CharAction) - {/*None*/ } - else if(FCombatGameplayTags::Get().Character_Action_Attack_ChargedAttack == CharAction) - {/*None*/ } - else if(FCombatGameplayTags::Get().Character_Action_Attack_FallingAttack == CharAction) - {/*None*/ } - else if(FCombatGameplayTags::Get().Character_Action_Attack_SprintAttack == CharAction) - {/*None*/ } -} - -void ACombatCharacter::CharacterCurrentStatValueUpdated(EStats statType, float value) +void ACombatPlayerCharacter::CharacterCurrentStatValueUpdated(EStats statType, float value) { if (!(statType == EStats::Health) || value > 0.f) return; @@ -615,13 +558,13 @@ void ACombatCharacter::CharacterCurrentStatValueUpdated(EStats statType, float v StateManagerComponent->SetCurrentState(FCombatGameplayTags::Get().Character_State_Dead); } -void ACombatCharacter::CharacterCombatToggled(bool IsCombatEnabled) +void ACombatPlayerCharacter::CharacterCombatToggled(bool IsCombatEnabled) { if(IsValid(TargetingComponent)) TargetingComponent->UpdateRotationMode(); } -void ACombatCharacter::ToggleCombatEvent() +void ACombatPlayerCharacter::ToggleCombatEvent() { ABaseWeapon* baseWeapon = CombatComponent->GetMainWeapon(); if (!baseWeapon) @@ -631,12 +574,12 @@ void ACombatCharacter::ToggleCombatEvent() return; if (!CombatComponent->GetCombatEnabled()) - PerformAction(FCombatGameplayTags::Get().Character_State_GeneralActionState, FCombatGameplayTags::Get().Character_Action_EnterCombat, 0); + PerformAction(FCombatGameplayTags::Get().Character_Action_EnterCombat, FCombatGameplayTags::Get().Character_State_GeneralActionState, 0); else - PerformAction(FCombatGameplayTags::Get().Character_State_GeneralActionState, FCombatGameplayTags::Get().Character_Action_ExitCombat, 0); + PerformAction(FCombatGameplayTags::Get().Character_Action_ExitCombat, FCombatGameplayTags::Get().Character_State_GeneralActionState, 0); } -void ACombatCharacter::AttackEvent() +void ACombatPlayerCharacter::AttackEvent() { if (!CanPerformAttack()) return; @@ -651,7 +594,7 @@ void ACombatCharacter::AttackEvent() ToggleCombatEvent(); } -void ACombatCharacter::ChargeAttackEvent() +void ACombatPlayerCharacter::ChargeAttackEvent() { if (CanPerformAttack()) { @@ -664,7 +607,7 @@ void ACombatCharacter::ChargeAttackEvent() } } -bool ACombatCharacter::ResetChargeAttack() +bool ACombatPlayerCharacter::ResetChargeAttack() { AttackHeldTime = 0.f; if (bAttackCharged) @@ -676,7 +619,7 @@ bool ACombatCharacter::ResetChargeAttack() return true; } -void ACombatCharacter::ApplyHitReactionPhysicsVelocity(float InitialSpeed) +void ACombatPlayerCharacter::ApplyHitReactionPhysicsVelocity(float InitialSpeed) { if (!GetMesh()) return; @@ -684,7 +627,7 @@ void ACombatCharacter::ApplyHitReactionPhysicsVelocity(float InitialSpeed) GetMesh()->SetPhysicsLinearVelocity(GetActorForwardVector() * -InitialSpeed, false, PelvisBoneName); } -void ACombatCharacter::EnableRagdoll() +void ACombatPlayerCharacter::EnableRagdoll() { GetCharacterMovement()->SetMovementMode(EMovementMode::MOVE_None, 0); //movement 더 이상 없게 바꿈 GetCapsuleComponent()->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Ignore); //충돌무시 @@ -697,7 +640,7 @@ void ACombatCharacter::EnableRagdoll() GetMesh()->SetAllBodiesBelowPhysicsBlendWeight(PelvisBoneName, 1.f); } -void ACombatCharacter::DisableSprint() +void ACombatPlayerCharacter::DisableSprint() { UWorld* World = GEngine->GetWorldFromContextObjectChecked(this); if (World) @@ -707,7 +650,7 @@ void ACombatCharacter::DisableSprint() SetMovementSpeedMode(EMovementSpeedMode::Jogging); } -void ACombatCharacter::SprintStaminaCost() +void ACombatPlayerCharacter::SprintStaminaCost() { if (!CanPerformSprint()) { @@ -723,7 +666,7 @@ void ACombatCharacter::SprintStaminaCost() } } -void ACombatCharacter::ApplyHitReaction(EDamageType InDamageType) +void ACombatPlayerCharacter::ApplyHitReaction(EDamageType InDamageType) { switch (InDamageType) { @@ -741,7 +684,7 @@ void ACombatCharacter::ApplyHitReaction(EDamageType InDamageType) } } -void ACombatCharacter::ApplyImpactEffect(EDamageType InDamageType) +void ACombatPlayerCharacter::ApplyImpactEffect(EDamageType InDamageType) { //Play Sound UGameplayStatics::PlaySoundAtLocation(this, HitSound, LastHitInfo.Location); @@ -750,103 +693,7 @@ void ACombatCharacter::ApplyImpactEffect(EDamageType InDamageType) UNiagaraFunctionLibrary::SpawnSystemAtLocation(GetWorld(), HitEmitter, LastHitInfo.Location); } -void ACombatCharacter::PerformAttack(FGameplayTag attackType, int32 attackIndex) -{ - if(!CombatComponent->GetCombatEnabled()) - return; - - ABaseWeapon* CurrentWeapon = CombatComponent->GetMainWeapon(); - if (!CurrentWeapon) - return; - - TArray montages = CurrentWeapon->GetActionMontage(attackType); - int32 attackIdx = attackIndex; - - if (montages.Num() <= attackIdx) - attackIdx = 0; - if (!montages.IsValidIndex(attackIdx)) - return; - - UAnimMontage* attackMontage = montages[attackIdx]; - if (!IsValid(attackMontage)) - { - FString debugStr = FString::Printf(TEXT("Index %d Is NOT VALID!!"), attackIdx); - GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Red, debugStr); - return; - } - else - { - StateManagerComponent->SetCurrentState(FCombatGameplayTags::Get().Character_State_Attacking); - StateManagerComponent->SetCurrentAction(attackType); - - PlayAnimMontage(attackMontage); - - int idx = attackIdx + 1; - if (idx >= montages.Num()) - idx = 0; - - CombatComponent->SetAttackCount(idx); - } -} - -//인자값은 나중에 필요하면 추가 PerformDodge(int32 dodgeIndex) -void ACombatCharacter::PerformDodge() -{ - ABaseWeapon* CurrentWeapon = CombatComponent->GetMainWeapon(); - if (!CurrentWeapon) - return; - int32 montageIndex = 0; - TArray montages = CurrentWeapon->GetActionMontage(FCombatGameplayTags::Get().Character_Action_Dodge); - if (montages.Num() <= montageIndex) - montageIndex = 0; - if (!montages.IsValidIndex(montageIndex)) - return; - - UAnimMontage* dodgeMontage = montages[montageIndex]; - if (IsValid(dodgeMontage)) - { - StateManagerComponent->SetCurrentState(FCombatGameplayTags::Get().Character_State_Dodging); - StateManagerComponent->SetCurrentAction(FCombatGameplayTags::Get().Character_Action_Dodge); - PlayAnimMontage(dodgeMontage); - } - else - { - FString str = FString::Printf(TEXT("Dodge Index %n is NOT VALID!!"), montageIndex); - GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Red, str); - } -} - -bool ACombatCharacter::PerformAction(FGameplayTag characterState, FGameplayTag characterAction, int32 montageIndex) -{ - ABaseWeapon* CurrentWeapon = CombatComponent->GetMainWeapon(); - if (!CurrentWeapon) - return false; - - TArray montages = CurrentWeapon->GetActionMontage(characterAction); - int32 montageIdx = montageIndex; - - if (montages.Num() <= montageIdx) - montageIdx = 0; - if (!montages.IsValidIndex(montageIdx)) - return false; - - UAnimMontage* actionMontage = montages[montageIdx]; - if (IsValid(actionMontage)) - { - StateManagerComponent->SetCurrentState(characterState); - StateManagerComponent->SetCurrentAction(characterAction); - PlayAnimMontage(actionMontage); - return true; - } - else - { - FString str = FString::Printf(TEXT("Dodge Index %n is NOT VALID!!"), montageIdx); - GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Red, str); - return false; - } -} - -void ACombatCharacter::PerformDeath() +void ACombatPlayerCharacter::PerformDeath() { EnableRagdoll(); ApplyHitReactionPhysicsVelocity(2000.f); //충돌을 좀 더 그럴싸하게 하기 위해서 뒷방향으로 충격 @@ -863,7 +710,7 @@ void ACombatCharacter::PerformDeath() }), 4.f, false); // 4초 후에 object 삭제 } -bool ACombatCharacter::PerformHitStun() +bool ACombatPlayerCharacter::PerformHitStun() { UAnimMontage* hitMontage = nullptr; if(bHitFront) @@ -879,7 +726,7 @@ bool ACombatCharacter::PerformHitStun() return true; } -bool ACombatCharacter::PerformKnockdown() +bool ACombatPlayerCharacter::PerformKnockdown() { UAnimMontage* hitMontage = nullptr; if(bHitFront) @@ -895,7 +742,7 @@ bool ACombatCharacter::PerformKnockdown() return true; } -bool ACombatCharacter::CanPerformToggleCombat() +bool ACombatPlayerCharacter::CanPerformToggleCombat() { bool ReturnValue = true; @@ -911,7 +758,7 @@ bool ACombatCharacter::CanPerformToggleCombat() return ReturnValue; } -bool ACombatCharacter::CanPerformAttack() +bool ACombatPlayerCharacter::CanPerformAttack() { bool ReturnValue = true; @@ -928,7 +775,7 @@ bool ACombatCharacter::CanPerformAttack() return ReturnValue; } -bool ACombatCharacter::CanPerformDodge() +bool ACombatPlayerCharacter::CanPerformDodge() { bool ReturnValue = true; @@ -944,7 +791,7 @@ bool ACombatCharacter::CanPerformDodge() return ReturnValue; } -bool ACombatCharacter::CanJumping() +bool ACombatPlayerCharacter::CanJumping() { bool ReturnValue = true; @@ -959,7 +806,7 @@ bool ACombatCharacter::CanJumping() return ReturnValue; } -bool ACombatCharacter::CanReceiveHitReaction() +bool ACombatPlayerCharacter::CanReceiveHitReaction() { bool ReturnValue = true; @@ -970,12 +817,12 @@ bool ACombatCharacter::CanReceiveHitReaction() return ReturnValue; } -bool ACombatCharacter::CanPerformSprint() +bool ACombatPlayerCharacter::CanPerformSprint() { return (FMath::IsNearlyEqual(GetVelocity().Length(), 0.f)) == false; } -FGameplayTag ACombatCharacter::GetDesiredAttackType() +FGameplayTag ACombatPlayerCharacter::GetDesiredAttackType() { if (GetCharacterMovement()->IsFalling()) return FCombatGameplayTags::Get().Character_Action_Attack_FallingAttack; diff --git a/Source/D1/CombatCharacter.h b/Source/D1/CombatPlayerCharacter.h similarity index 92% rename from Source/D1/CombatCharacter.h rename to Source/D1/CombatPlayerCharacter.h index e3b52877..a4057266 100644 --- a/Source/D1/CombatCharacter.h +++ b/Source/D1/CombatPlayerCharacter.h @@ -12,11 +12,11 @@ #include "Components/StatsComponent.h" #include "Components/TargetingComponent.h" #include "Definitions/GameEnums.h" -#include "CombatCharacter.generated.h" +#include "CombatPlayerCharacter.generated.h" UCLASS(config=Game) -class ACombatCharacter : public ACharacter, public ICombatInterface, public IGameplayTagAssetInterface +class ACombatPlayerCharacter : public ACharacter, public ICombatInterface, public IGameplayTagAssetInterface { GENERATED_BODY() @@ -73,7 +73,7 @@ class ACombatCharacter : public ACharacter, public ICombatInterface, public IGam UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Input, meta = (AllowPrivateAccess = "true")) float ChargeAttackTime; public: - ACombatCharacter(); + ACombatPlayerCharacter(); public: /** Returns CameraBoom subobject **/ @@ -113,13 +113,10 @@ public: UFUNCTION(BlueprintCallable, BlueprintNativeEvent) void DeactivateCollision(ECollisionPart CollisionPart); virtual void DeactivateCollision_Implementation(ECollisionPart CollisionPart) override; - UFUNCTION(BlueprintCallable, BlueprintNativeEvent) - void ToggleCombat(); - virtual void ToggleCombat_Implementation() override; virtual EMovementSpeedMode GetCombatMovementSpeedMode() override { return GetMovementSpeedMode(); } - virtual float PerformCombatAction(FGameplayTag ActionTag, FGameplayTag StateTag, int32 MontageIndex, bool bRandomIndex); - virtual float PerformCombatAttack(FGameplayTag AttackType, int32 AttackIndex, bool bRandomIndex); + virtual float PerformAction(FGameplayTag ActionTag, FGameplayTag StateTag, int32 MontageIndex, bool bRandomIndex = false); + virtual float PerformAttack(FGameplayTag AttackType, int32 AttackIndex, bool bRandomIndex = false); // Inherited via IGameplayTagAssetInterface virtual void GetOwnedGameplayTags(FGameplayTagContainer& TagContainer) const override { TagContainer = OwnedGameplayTags; } @@ -146,8 +143,6 @@ protected: private://Delegate void CharacterStateBegin(FGameplayTag CharState); void CharacterStateEnd(FGameplayTag CharState); - void CharacterActionBegin(FGameplayTag CharAction); - void CharacterActionEnd(FGameplayTag CharAction); void CharacterCurrentStatValueUpdated(EStats statType, float value); void CharacterCombatToggled(bool IsCombatEnabled); @@ -164,9 +159,6 @@ private: void ApplyImpactEffect(EDamageType InDamageType); private: - void PerformAttack(FGameplayTag attackType, int32 attackIndex); - void PerformDodge(); - bool PerformAction(FGameplayTag characterState, FGameplayTag characterAction, int32 montageIndex); void PerformDeath(); bool PerformHitStun(); bool PerformKnockdown(); diff --git a/Source/D1/Components/CollisionComponent.cpp b/Source/D1/Components/CollisionComponent.cpp index 27d4c191..c10a727e 100644 --- a/Source/D1/Components/CollisionComponent.cpp +++ b/Source/D1/Components/CollisionComponent.cpp @@ -3,6 +3,8 @@ #include "Components/CollisionComponent.h" +#include "GameplayTagAssetInterface.h" + // Sets default values for this component's properties UCollisionComponent::UCollisionComponent() @@ -61,3 +63,12 @@ void UCollisionComponent::ActivateCollision() bCollisionEnabled = true; } +bool UCollisionComponent::CanHitActor(AActor* InActor) +{ + IGameplayTagAssetInterface* tagInterface = Cast(InActor); + if(tagInterface) + { + + } +} + diff --git a/Source/D1/Components/CollisionComponent.h b/Source/D1/Components/CollisionComponent.h index 3c83ded4..f309bac9 100644 --- a/Source/D1/Components/CollisionComponent.h +++ b/Source/D1/Components/CollisionComponent.h @@ -54,6 +54,7 @@ public: UFUNCTION(BlueprintCallable) FORCEINLINE void DeactivateCollision() { bCollisionEnabled = false; } bool IsCollisionEnabled() { return bCollisionEnabled; } + bool CanHitActor(AActor* InActor); private: UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Initialization", meta=(AllowPrivateAccess="true")) float TraceRadius; diff --git a/Source/D1/D1GameMode.cpp b/Source/D1/D1GameMode.cpp index beefad7f..b42b569a 100644 --- a/Source/D1/D1GameMode.cpp +++ b/Source/D1/D1GameMode.cpp @@ -1,7 +1,7 @@ // Copyright Epic Games, Inc. All Rights Reserved. #include "D1GameMode.h" -#include "CombatCharacter.h" +#include "CombatPlayerCharacter.h" #include "UObject/ConstructorHelpers.h" AD1GameMode::AD1GameMode() diff --git a/Source/D1/Interface/CombatInterface.cpp b/Source/D1/Interface/CombatInterface.cpp index 31e7e481..b7f151d2 100644 --- a/Source/D1/Interface/CombatInterface.cpp +++ b/Source/D1/Interface/CombatInterface.cpp @@ -4,13 +4,13 @@ #include "Interface/CombatInterface.h" // Add default functionality here for any ICombatInterface functions that are not pure virtual. -float ICombatInterface::PerformCombatAction(FGameplayTag ActionTag, FGameplayTag StateTag, int32 MontageIndex, +float ICombatInterface::PerformAction(FGameplayTag ActionTag, FGameplayTag StateTag, int32 MontageIndex, bool bRandomIndex) { return 0.f; } -float ICombatInterface::PerformCombatAttack(FGameplayTag AttackType, int32 AttackIndex, bool bRandomIndex) +float ICombatInterface::PerformAttack(FGameplayTag AttackType, int32 AttackIndex, bool bRandomIndex) { return 0.f; } diff --git a/Source/D1/Interface/CombatInterface.h b/Source/D1/Interface/CombatInterface.h index dc757f32..0402268a 100644 --- a/Source/D1/Interface/CombatInterface.h +++ b/Source/D1/Interface/CombatInterface.h @@ -40,15 +40,13 @@ public: void ActivateCollision(ECollisionPart CollisionPart); UFUNCTION(BlueprintCallable, BlueprintNativeEvent) void DeactivateCollision(ECollisionPart CollisionPart); - UFUNCTION(BlueprintCallable, BlueprintNativeEvent) - void ToggleCombat(); UFUNCTION() virtual EMovementSpeedMode GetCombatMovementSpeedMode() = 0; UFUNCTION(Category="CombatActions") - virtual float PerformCombatAction(FGameplayTag ActionTag, FGameplayTag StateTag, int32 MontageIndex, bool bRandomIndex); + virtual float PerformAction(FGameplayTag ActionTag, FGameplayTag StateTag, int32 MontageIndex, bool bRandomIndex = false); UFUNCTION(Category="CombatActions") - virtual float PerformCombatAttack(FGameplayTag AttackType, int32 AttackIndex, bool bRandomIndex); + virtual float PerformAttack(FGameplayTag AttackType, int32 AttackIndex, bool bRandomIndex = false); }; diff --git a/Source/D1/UI/CombatHUD.cpp b/Source/D1/UI/CombatHUD.cpp index c0bd59b7..185ca6eb 100644 --- a/Source/D1/UI/CombatHUD.cpp +++ b/Source/D1/UI/CombatHUD.cpp @@ -3,7 +3,6 @@ #include "UI/CombatHUD.h" -#include "UI_BossHealth.h" #include "UI/UI_MainHUD.h" void ACombatHUD::BeginPlay() @@ -19,11 +18,5 @@ void ACombatHUD::BeginPlay() UUI_MainHUD* outputUI = CreateWidget(Contorller, MainUI); outputUI->AddToViewport(); } - - UUI_BossHealth* BossHealthRef = CreateWidget(Contorller, UUI_BossHealth::StaticClass()); - if (BossHealthRef) //ExposeOnSpawn 대용으로 사용 - { - BossHealthRef->AddToViewport(); - } } } diff --git a/Source/D1/UI/UI_HealthBar.cpp b/Source/D1/UI/UI_HealthBar.cpp index eec2c076..f5f46ba0 100644 --- a/Source/D1/UI/UI_HealthBar.cpp +++ b/Source/D1/UI/UI_HealthBar.cpp @@ -9,7 +9,7 @@ void UUI_HealthBar::NativeConstruct() { Super::NativeConstruct(); - if(bUsePlayerStatsComponent) + if(!IsValid(StatsComponent)) { if(const APlayerController* playerController = GetOwningPlayer()) StatsComponent = playerController->GetComponentByClass(); diff --git a/Source/D1/UI/UI_HealthBar.h b/Source/D1/UI/UI_HealthBar.h index 57c786d3..f3932029 100644 --- a/Source/D1/UI/UI_HealthBar.h +++ b/Source/D1/UI/UI_HealthBar.h @@ -26,8 +26,6 @@ private: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Initialization" , meta=(AllowPrivateAccess="true")) EStats StatType; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Initialization" , meta=(AllowPrivateAccess="true")) - bool bUsePlayerStatsComponent; public: UFUNCTION(BlueprintCallable) diff --git a/Source/D1/UI/UI_StatBar.cpp b/Source/D1/UI/UI_StatBar.cpp index eebb332a..6912a1e2 100644 --- a/Source/D1/UI/UI_StatBar.cpp +++ b/Source/D1/UI/UI_StatBar.cpp @@ -6,13 +6,7 @@ void UUI_StatBar::NativeConstruct() { - APawn* pplayer = GetOwningPlayerPawn(); - if (pplayer) - { - StatsComponent = pplayer->GetComponentByClass(); - if (IsValid(StatsComponent)) - StatsComponent->OnCurrentStatValueUpdated.AddUObject(this, &UUI_StatBar::StatBarStatValueUpdated); - } + InitializeStatBar(nullptr); } void UUI_StatBar::StatBarStatValueUpdated(EStats stat, float value) @@ -26,3 +20,17 @@ void UUI_StatBar::StatBarStatValueUpdated(EStats stat, float value) float fPercent = value / StatsComponent->GetMaxStatValue(StatType); StatBar->SetPercent(fPercent); } + +void UUI_StatBar::InitializeStatBar(UStatsComponent* InputStatsComponent) +{ + if(IsValid(InputStatsComponent)) + StatsComponent = InputStatsComponent; + else if(!IsValid(StatsComponent)) + { + APawn* pplayer = GetOwningPlayerPawn(); + if (pplayer) + StatsComponent = pplayer->GetComponentByClass(); + } + StatsComponent->OnCurrentStatValueUpdated.AddUObject(this, &UUI_StatBar::StatBarStatValueUpdated); + StatBarStatValueUpdated(StatType, StatsComponent->GetCurrentStatValue(StatType)); +} diff --git a/Source/D1/UI/UI_StatBar.h b/Source/D1/UI/UI_StatBar.h index 3dcbf40e..c37bcc3c 100644 --- a/Source/D1/UI/UI_StatBar.h +++ b/Source/D1/UI/UI_StatBar.h @@ -19,6 +19,8 @@ protected: virtual void NativeConstruct() override; public: //Delegate void StatBarStatValueUpdated(EStats stat, float value); +public: + void InitializeStatBar(UStatsComponent* InputStatsComponent); public: UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget)) TObjectPtr StatBar;