diff --git a/Config/Tags/Enemy.ini b/Config/Tags/Enemy.ini index cefe9a4c..f0c0dc1a 100644 --- a/Config/Tags/Enemy.ini +++ b/Config/Tags/Enemy.ini @@ -6,8 +6,8 @@ GameplayTagList=(Tag="Enemy.Name.BrownWolf",DevComment="") GameplayTagList=(Tag="Enemy.Name.DarkWolf",DevComment="") GameplayTagList=(Tag="Enemy.Name.EarthGolem",DevComment="") GameplayTagList=(Tag="Enemy.Name.FireElemental",DevComment="") -GameplayTagList=(Tag="Enemy.Name.ForestCreature",DevComment="") GameplayTagList=(Tag="Enemy.Name.FireGolem",DevComment="") +GameplayTagList=(Tag="Enemy.Name.ForestCreature",DevComment="") GameplayTagList=(Tag="Enemy.Name.GreenPlant",DevComment="") GameplayTagList=(Tag="Enemy.Name.GreenSpider",DevComment="") GameplayTagList=(Tag="Enemy.Name.GreyWolf",DevComment="") @@ -19,6 +19,7 @@ GameplayTagList=(Tag="Enemy.Name.MiniPinkPlant",DevComment="") GameplayTagList=(Tag="Enemy.Name.PinkPlant",DevComment="") GameplayTagList=(Tag="Enemy.Name.PoisonElemental",DevComment="") GameplayTagList=(Tag="Enemy.Name.RedSpider",DevComment="") +GameplayTagList=(Tag="Enemy.Name.SpiderQueen",DevComment="") GameplayTagList=(Tag="Enemy.Name.StoneElement",DevComment="") GameplayTagList=(Tag="Enemy.Name.WaterElemental",DevComment="") GameplayTagList=(Tag="Enemy.Species",DevComment="") @@ -26,8 +27,8 @@ GameplayTagList=(Tag="Enemy.Species.CarnivorousPlant",DevComment="") GameplayTagList=(Tag="Enemy.Species.Golem",DevComment="") GameplayTagList=(Tag="Enemy.Species.Spider",DevComment="") GameplayTagList=(Tag="Enemy.Species.Spirit",DevComment="") -GameplayTagList=(Tag="Enemy.Type.Boss",DevComment="") GameplayTagList=(Tag="Enemy.Species.Wolf",DevComment="") +GameplayTagList=(Tag="Enemy.Type.Boss",DevComment="") GameplayTagList=(Tag="Enemy.Type.Nomal",DevComment="") GameplayTagList=(Tag="ForestCreature",DevComment="") diff --git a/Config/Tags/Skill.ini b/Config/Tags/Skill.ini index bead7469..a3447eb5 100644 --- a/Config/Tags/Skill.ini +++ b/Config/Tags/Skill.ini @@ -16,6 +16,7 @@ GameplayTagList=(Tag="Event.Character.Action.Normal.FireGolem",DevComment="") GameplayTagList=(Tag="Event.Character.Action.Normal.ForestCreature",DevComment="") GameplayTagList=(Tag="Event.Character.Action.Normal.IceGolem",DevComment="") GameplayTagList=(Tag="Event.Character.Action.Normal.Spider",DevComment="") +GameplayTagList=(Tag="Event.Character.Action.Normal.SpiderQueen",DevComment="") GameplayTagList=(Tag="Event.Character.Action.Normal.Stone",DevComment="") GameplayTagList=(Tag="Event.Character.Action.NormalMeleeAttack",DevComment="") GameplayTagList=(Tag="Event.Character.Action.PoisonSlash",DevComment="") @@ -39,6 +40,7 @@ GameplayTagList=(Tag="Skill.Instant.ForestCreatureMeleeAttack",DevComment="") GameplayTagList=(Tag="Skill.Instant.IceGolemIdentity",DevComment="") GameplayTagList=(Tag="Skill.Instant.MysticShot",DevComment="") GameplayTagList=(Tag="Skill.Instant.PoisonSlash",DevComment="") +GameplayTagList=(Tag="Skill.Instant.SpiderQueenIdentity",DevComment="") GameplayTagList=(Tag="Skill.Instant.StoneElementalMeleeAttack",DevComment="") GameplayTagList=(Tag="Skill.Normal.Cooldown",DevComment="") GameplayTagList=(Tag="Skill.Normal.EarthGolem",DevComment="") @@ -48,6 +50,7 @@ GameplayTagList=(Tag="Skill.Normal.ForestCreature",DevComment="") GameplayTagList=(Tag="Skill.Normal.IceGolem",DevComment="") GameplayTagList=(Tag="Skill.Normal.MeleeAttack",DevComment="") GameplayTagList=(Tag="Skill.Normal.Spider",DevComment="") +GameplayTagList=(Tag="Skill.Normal.SpiderQueen",DevComment="") GameplayTagList=(Tag="Skill.Normal.Stone",DevComment="") GameplayTagList=(Tag="Skill.Passive",DevComment="") GameplayTagList=(Tag="Skill.Passive.DamageUp",DevComment="") diff --git a/Content/AI/SpiderMinion/BP_SpiderEgg.uasset b/Content/AI/SpiderMinion/BP_SpiderEgg.uasset index d60b6839..5dd4e076 100644 Binary files a/Content/AI/SpiderMinion/BP_SpiderEgg.uasset and b/Content/AI/SpiderMinion/BP_SpiderEgg.uasset differ diff --git a/Content/AI/SpiderMinion/Curve_Spider_Table.uasset b/Content/AI/SpiderMinion/Curve_SpiderMinion_Table.uasset similarity index 88% rename from Content/AI/SpiderMinion/Curve_Spider_Table.uasset rename to Content/AI/SpiderMinion/Curve_SpiderMinion_Table.uasset index 296c1443..2a16b346 100644 Binary files a/Content/AI/SpiderMinion/Curve_Spider_Table.uasset and b/Content/AI/SpiderMinion/Curve_SpiderMinion_Table.uasset differ diff --git a/Content/AI/SpiderMinion/Montage/AM_Dead_SpiderMinion.uasset b/Content/AI/SpiderMinion/Montage/AM_Dead_SpiderMinion.uasset index a4906596..17f8ba70 100644 Binary files a/Content/AI/SpiderMinion/Montage/AM_Dead_SpiderMinion.uasset and b/Content/AI/SpiderMinion/Montage/AM_Dead_SpiderMinion.uasset differ diff --git a/Content/AI/SpiderMinion/SKill/Normal/Curve_Normal_SpiderMinion.uasset b/Content/AI/SpiderMinion/SKill/Normal/Curve_Normal_SpiderMinion.uasset index a25c9516..1eedff22 100644 Binary files a/Content/AI/SpiderMinion/SKill/Normal/Curve_Normal_SpiderMinion.uasset and b/Content/AI/SpiderMinion/SKill/Normal/Curve_Normal_SpiderMinion.uasset differ diff --git a/Content/AI/SpiderMinion/SKill/Passive/BPGA_Passive_SpiderMinion.uasset b/Content/AI/SpiderMinion/SKill/Passive/BPGA_Passive_SpiderMinion.uasset new file mode 100644 index 00000000..92d39bcd Binary files /dev/null and b/Content/AI/SpiderMinion/SKill/Passive/BPGA_Passive_SpiderMinion.uasset differ diff --git a/Content/AI/SpiderMinion/SKill/Passive/BPGE_DamageUp_SpiderMinion.uasset b/Content/AI/SpiderMinion/SKill/Passive/BPGE_DamageUp_SpiderMinion.uasset new file mode 100644 index 00000000..6f33e4b0 Binary files /dev/null and b/Content/AI/SpiderMinion/SKill/Passive/BPGE_DamageUp_SpiderMinion.uasset differ diff --git a/Content/AI/SpiderMinion/SKill/Passive/Curve_Passive_Damage.uasset b/Content/AI/SpiderMinion/SKill/Passive/Curve_Passive_Damage.uasset new file mode 100644 index 00000000..454ff371 Binary files /dev/null and b/Content/AI/SpiderMinion/SKill/Passive/Curve_Passive_Damage.uasset differ diff --git a/Content/AI/SpiderMinion/SKill/Passive/DT_Passive_SpiderMinion.uasset b/Content/AI/SpiderMinion/SKill/Passive/DT_Passive_SpiderMinion.uasset new file mode 100644 index 00000000..4a3e4921 Binary files /dev/null and b/Content/AI/SpiderMinion/SKill/Passive/DT_Passive_SpiderMinion.uasset differ diff --git a/Content/AI/SpiderQueen/ABP_SpiderQueen.uasset b/Content/AI/SpiderQueen/ABP_SpiderQueen.uasset new file mode 100644 index 00000000..1e9e4d04 Binary files /dev/null and b/Content/AI/SpiderQueen/ABP_SpiderQueen.uasset differ diff --git a/Content/AI/SpiderQueen/BPGA_ActionAppear_SpiderQueen.uasset b/Content/AI/SpiderQueen/BPGA_ActionAppear_SpiderQueen.uasset new file mode 100644 index 00000000..0d8a49e2 Binary files /dev/null and b/Content/AI/SpiderQueen/BPGA_ActionAppear_SpiderQueen.uasset differ diff --git a/Content/AI/SpiderQueen/BPGA_ActionDeath_SpiderQueen.uasset b/Content/AI/SpiderQueen/BPGA_ActionDeath_SpiderQueen.uasset new file mode 100644 index 00000000..ddda02d4 Binary files /dev/null and b/Content/AI/SpiderQueen/BPGA_ActionDeath_SpiderQueen.uasset differ diff --git a/Content/AI/SpiderQueen/BP_MJAIController_SpiderQueen.uasset b/Content/AI/SpiderQueen/BP_MJAIController_SpiderQueen.uasset new file mode 100644 index 00000000..1990166c Binary files /dev/null and b/Content/AI/SpiderQueen/BP_MJAIController_SpiderQueen.uasset differ diff --git a/Content/AI/SpiderQueen/BP_SpiderQueen.uasset b/Content/AI/SpiderQueen/BP_SpiderQueen.uasset new file mode 100644 index 00000000..d8e286b6 Binary files /dev/null and b/Content/AI/SpiderQueen/BP_SpiderQueen.uasset differ diff --git a/Content/AI/SpiderQueen/BS_SpiderQueen.uasset b/Content/AI/SpiderQueen/BS_SpiderQueen.uasset new file mode 100644 index 00000000..5aff63c8 Binary files /dev/null and b/Content/AI/SpiderQueen/BS_SpiderQueen.uasset differ diff --git a/Content/AI/SpiderQueen/BT/BB_SpiderQueen.uasset b/Content/AI/SpiderQueen/BT/BB_SpiderQueen.uasset new file mode 100644 index 00000000..0801327f Binary files /dev/null and b/Content/AI/SpiderQueen/BT/BB_SpiderQueen.uasset differ diff --git a/Content/AI/SpiderQueen/BT/BT_SpiderQueen.uasset b/Content/AI/SpiderQueen/BT/BT_SpiderQueen.uasset new file mode 100644 index 00000000..6d357c40 Binary files /dev/null and b/Content/AI/SpiderQueen/BT/BT_SpiderQueen.uasset differ diff --git a/Content/AI/SpiderQueen/Curve_SpiderQueen_Table.uasset b/Content/AI/SpiderQueen/Curve_SpiderQueen_Table.uasset new file mode 100644 index 00000000..db4943d9 Binary files /dev/null and b/Content/AI/SpiderQueen/Curve_SpiderQueen_Table.uasset differ diff --git a/Content/AI/SpiderQueen/DT_SpiderQueenStatAbility.uasset b/Content/AI/SpiderQueen/DT_SpiderQueenStatAbility.uasset new file mode 100644 index 00000000..08804f29 Binary files /dev/null and b/Content/AI/SpiderQueen/DT_SpiderQueenStatAbility.uasset differ diff --git a/Content/AI/SpiderQueen/Montage/AM_Agr_SpiderQueen.uasset b/Content/AI/SpiderQueen/Montage/AM_Agr_SpiderQueen.uasset new file mode 100644 index 00000000..812874c4 Binary files /dev/null and b/Content/AI/SpiderQueen/Montage/AM_Agr_SpiderQueen.uasset differ diff --git a/Content/AI/SpiderQueen/Montage/AM_Death_SpiderQueen.uasset b/Content/AI/SpiderQueen/Montage/AM_Death_SpiderQueen.uasset new file mode 100644 index 00000000..dab0ea2b Binary files /dev/null and b/Content/AI/SpiderQueen/Montage/AM_Death_SpiderQueen.uasset differ diff --git a/Content/AI/SpiderQueen/Montage/AM_NormalAttack_SpiderQueen.uasset b/Content/AI/SpiderQueen/Montage/AM_NormalAttack_SpiderQueen.uasset new file mode 100644 index 00000000..152a2701 Binary files /dev/null and b/Content/AI/SpiderQueen/Montage/AM_NormalAttack_SpiderQueen.uasset differ diff --git a/Content/AI/SpiderQueen/Montage/AM_Spawn_SpiderQueen.uasset b/Content/AI/SpiderQueen/Montage/AM_Spawn_SpiderQueen.uasset new file mode 100644 index 00000000..6446c31e Binary files /dev/null and b/Content/AI/SpiderQueen/Montage/AM_Spawn_SpiderQueen.uasset differ diff --git a/Content/AI/SpiderQueen/Skill/Identity/BPGA_Identity_SpiderQueen.uasset b/Content/AI/SpiderQueen/Skill/Identity/BPGA_Identity_SpiderQueen.uasset new file mode 100644 index 00000000..eb9634ad Binary files /dev/null and b/Content/AI/SpiderQueen/Skill/Identity/BPGA_Identity_SpiderQueen.uasset differ diff --git a/Content/AI/SpiderQueen/Skill/Identity/Curve_Identity_SpiderQueen.uasset b/Content/AI/SpiderQueen/Skill/Identity/Curve_Identity_SpiderQueen.uasset new file mode 100644 index 00000000..73eeb870 Binary files /dev/null and b/Content/AI/SpiderQueen/Skill/Identity/Curve_Identity_SpiderQueen.uasset differ diff --git a/Content/AI/SpiderQueen/Skill/Identity/DT_Identity_SpiderQueen.uasset b/Content/AI/SpiderQueen/Skill/Identity/DT_Identity_SpiderQueen.uasset new file mode 100644 index 00000000..7c08a34f Binary files /dev/null and b/Content/AI/SpiderQueen/Skill/Identity/DT_Identity_SpiderQueen.uasset differ diff --git a/Content/AI/SpiderQueen/Skill/Normal/BPGA_ActionNormalSpiderQueen.uasset b/Content/AI/SpiderQueen/Skill/Normal/BPGA_ActionNormalSpiderQueen.uasset new file mode 100644 index 00000000..961c31ba Binary files /dev/null and b/Content/AI/SpiderQueen/Skill/Normal/BPGA_ActionNormalSpiderQueen.uasset differ diff --git a/Content/AI/SpiderQueen/Skill/Normal/BPGA_Normal_SpiderQueen.uasset b/Content/AI/SpiderQueen/Skill/Normal/BPGA_Normal_SpiderQueen.uasset new file mode 100644 index 00000000..4dc8e03a Binary files /dev/null and b/Content/AI/SpiderQueen/Skill/Normal/BPGA_Normal_SpiderQueen.uasset differ diff --git a/Content/AI/SpiderQueen/Skill/Normal/Curve_Normal_SpiderQueen.uasset b/Content/AI/SpiderQueen/Skill/Normal/Curve_Normal_SpiderQueen.uasset new file mode 100644 index 00000000..4bdba756 Binary files /dev/null and b/Content/AI/SpiderQueen/Skill/Normal/Curve_Normal_SpiderQueen.uasset differ diff --git a/Content/AI/SpiderQueen/Skill/Normal/DT_Normal_SpiderQueenAbility.uasset b/Content/AI/SpiderQueen/Skill/Normal/DT_Normal_SpiderQueenAbility.uasset new file mode 100644 index 00000000..ce03f074 Binary files /dev/null and b/Content/AI/SpiderQueen/Skill/Normal/DT_Normal_SpiderQueenAbility.uasset differ diff --git a/Content/Characters/Player/BP_MJNewPlayerCharacter.uasset b/Content/Characters/Player/BP_MJNewPlayerCharacter.uasset index db52e50b..36634a65 100644 Binary files a/Content/Characters/Player/BP_MJNewPlayerCharacter.uasset and b/Content/Characters/Player/BP_MJNewPlayerCharacter.uasset differ diff --git a/Content/DataTable/Enemy/DT_EnemyDataTable.uasset b/Content/DataTable/Enemy/DT_EnemyDataTable.uasset index 98e2cc69..bb54e719 100644 Binary files a/Content/DataTable/Enemy/DT_EnemyDataTable.uasset and b/Content/DataTable/Enemy/DT_EnemyDataTable.uasset differ diff --git a/Content/DataTable/Skill/DT_EnemySkillDataTable.uasset b/Content/DataTable/Skill/DT_EnemySkillDataTable.uasset index bafdee95..08a70934 100644 Binary files a/Content/DataTable/Skill/DT_EnemySkillDataTable.uasset and b/Content/DataTable/Skill/DT_EnemySkillDataTable.uasset differ diff --git a/Content/Maps/JH_Test.umap b/Content/Maps/JH_Test.umap index e3ddc207..8cf4421c 100644 Binary files a/Content/Maps/JH_Test.umap and b/Content/Maps/JH_Test.umap differ diff --git a/Content/PlayerSkill/Normal/BPGE_NormalCooldown.uasset b/Content/PlayerSkill/Normal/BPGE_NormalCooldown.uasset index ca0ddef5..41444f0c 100644 Binary files a/Content/PlayerSkill/Normal/BPGE_NormalCooldown.uasset and b/Content/PlayerSkill/Normal/BPGE_NormalCooldown.uasset differ diff --git a/Content/PlayerSkill/Passive/DamageUp/BPGA_DamageUp.uasset b/Content/PlayerSkill/Passive/DamageUp/BPGA_DamageUp.uasset index 9feaaf39..3a115709 100644 Binary files a/Content/PlayerSkill/Passive/DamageUp/BPGA_DamageUp.uasset and b/Content/PlayerSkill/Passive/DamageUp/BPGA_DamageUp.uasset differ diff --git a/Content/TG/GameData/AISpawn_Static_Data.uasset b/Content/TG/GameData/AISpawn_Static_Data.uasset index 6856f5b2..befde3ee 100644 Binary files a/Content/TG/GameData/AISpawn_Static_Data.uasset and b/Content/TG/GameData/AISpawn_Static_Data.uasset differ diff --git a/Source/ProjectMJ/AnimInstance/Notify/MJAnim_SpawnMonster.cpp b/Source/ProjectMJ/AnimInstance/Notify/MJAnim_SpawnMonster.cpp new file mode 100644 index 00000000..a4e6a386 --- /dev/null +++ b/Source/ProjectMJ/AnimInstance/Notify/MJAnim_SpawnMonster.cpp @@ -0,0 +1,92 @@ +// ThenOneDayStudio + + +#include "AnimInstance/Notify/MJAnim_SpawnMonster.h" + +#include "ProjectMJ.h" +#include "MJ/Character/MJBossMonsterCharacter.h" +#include "TG/MJGameInstance.h" +#include "Character/Component/MJEnemySkillComponent.h" +#include "Components/CapsuleComponent.h" +#include "Kismet/GameplayStatics.h" + + +void UMJAnim_SpawnMonster::Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation) +{ + if (!SpawnMonster) + { + return; + } + + if (SpawnCount <= 0) + { + return; + } + + AMJBossMonsterCharacter* Owner = Cast(MeshComp->GetOwner()); + if (!Owner) + { + return; + } + if (!SpawnLocation.IsEmpty()) + { + SpawnLocation.Empty(); + } + + int32 LimitSearch = SpawnCount * 10; + + float InnerRadius = Owner->GetCapsuleComponent()->GetScaledCapsuleRadius(); + float ExcludeHalfAngle = FMath::DegreesToRadians(60.f); + + for (int32 i = 0; i < SpawnCount; i++) + { + bool SpawnCheck = false; + FVector NewDistance; + + /*for (int Attempt = 0; Attempt < LimitSearch; Attempt++) + {*/ + while (SpawnLocation.Num() GetActorLocation().X + OffsetX, Owner->GetActorLocation().Y + OffsetY, 0.f); + + FVector DirToCandidate = (NewDistance - Owner->GetActorLocation()).GetSafeNormal(); + float Dot = FVector::DotProduct(Owner->GetActorForwardVector(), DirToCandidate); + if (FMath::Acos(Dot) < ExcludeHalfAngle) + { + continue; + } + + bool bTooClose = false; + for (const FVector& OldLocation : SpawnLocation) + { + if (FVector::Dist(OldLocation, NewDistance) < MinDistance) + { + bTooClose = true; + break; + } + } + if (!bTooClose) + { + + SpawnCheck = true; + break; + } + //} + } + if (SpawnCheck) + { + SpawnLocation.Add(NewDistance); + GetWorld()->SpawnActor(SpawnMonster, NewDistance, FRotator::ZeroRotator); + } + } + + DrawDebugCircle(GetWorld(), Owner->GetActorLocation(), InnerRadius, 16, FColor::White, false, 0.2f, 0, 0, FVector::RightVector, FVector::ForwardVector, false); + DrawDebugCircle(GetWorld(), Owner->GetActorLocation(), OuterRadius, 16, FColor::Black,false, 0.2f, 0, 0, FVector::RightVector, FVector::ForwardVector, false); + +} diff --git a/Source/ProjectMJ/AnimInstance/Notify/MJAnim_SpawnMonster.h b/Source/ProjectMJ/AnimInstance/Notify/MJAnim_SpawnMonster.h new file mode 100644 index 00000000..6c021591 --- /dev/null +++ b/Source/ProjectMJ/AnimInstance/Notify/MJAnim_SpawnMonster.h @@ -0,0 +1,38 @@ +// ThenOneDayStudio + +#pragma once + +#include "CoreMinimal.h" +#include "Animation/AnimNotifies/AnimNotify.h" +#include "MJAnim_SpawnMonster.generated.h" + +/** + * + */ +UCLASS() +class PROJECTMJ_API UMJAnim_SpawnMonster : public UAnimNotify +{ + GENERATED_BODY() + + +public: + UPROPERTY(EditAnywhere,BlueprintReadOnly,Category="Pawn") + TSubclassOf SpawnMonster; + + UPROPERTY(EditAnywhere,Category="Pawn") + int32 SpawnCount; + UPROPERTY(EditAnywhere,Category="Pawn") + float OuterRadius; + + UPROPERTY(EditAnywhere,Category="Pawn") + bool ForwordSpawn; + + UFUNCTION() + virtual void Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation) override; + +private: + + TArray SpawnLocation; + + float MinDistance = 30.f; +}; diff --git a/Source/ProjectMJ/Character/Component/MJSkillComponentBase.cpp b/Source/ProjectMJ/Character/Component/MJSkillComponentBase.cpp index 69c39de4..096b36c7 100644 --- a/Source/ProjectMJ/Character/Component/MJSkillComponentBase.cpp +++ b/Source/ProjectMJ/Character/Component/MJSkillComponentBase.cpp @@ -12,7 +12,7 @@ #include "DataTable/MJSkillDataRow.h" #include "DataTable/MJSkillLevelAbilityRow.h" -// Sets default values for this component's properties +// Sets default values for this component's propertiesk UMJSkillComponentBase::UMJSkillComponentBase() { PrimaryComponentTick.bCanEverTick = false; @@ -326,7 +326,7 @@ void UMJSkillComponentBase::RemoveAbility(const FGameplayTag& SkillTag) if (GivenPassiveAbilityHandles.Contains(SkillTag)) { - ASC->ClearAbility(GivenSkillAbilityHandles[SkillTag]); + ASC->ClearAbility(GivenPassiveAbilityHandles[SkillTag]); GivenPassiveAbilityHandles.Remove(SkillTag); } diff --git a/Source/ProjectMJ/Character/Component/MJSkillComponentBase.h b/Source/ProjectMJ/Character/Component/MJSkillComponentBase.h index b9f84018..48c5342b 100644 --- a/Source/ProjectMJ/Character/Component/MJSkillComponentBase.h +++ b/Source/ProjectMJ/Character/Component/MJSkillComponentBase.h @@ -15,8 +15,8 @@ * - *더 구체적으로 분류한다면, AI가 스킬을 여러개 사용 + 장착을 안 하는 개념으로 더 추상화 가능* * Author: 신동민 * Created Date: 2025.07.08 - * Last Modified By: - * Last Modified Date: + * Last Modified By: LEE JUHyeon + * Last Modified Date:2025.08.22 */ DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnLearnSkillEvent,FGameplayTag,SkillTag,int32,Level); diff --git a/Source/ProjectMJ/Character/MJForestCreatureCharacter.h b/Source/ProjectMJ/Character/MJForestCreatureCharacter.h index 35d134aa..c117d56c 100644 --- a/Source/ProjectMJ/Character/MJForestCreatureCharacter.h +++ b/Source/ProjectMJ/Character/MJForestCreatureCharacter.h @@ -3,15 +3,18 @@ #pragma once #include "CoreMinimal.h" -#include "MJ/Character/MJMonsterCharacter.h" +#include "MJ/Character/MJBossMonsterCharacter.h" #include "MJForestCreatureCharacter.generated.h" /** - * + * Class Description: ForestMonster + * Author: Lee JuHyeon + * Created Date: 2025.07.20. + */ class UMJCharacterAttributeSet; UCLASS() -class PROJECTMJ_API AMJForestCreatureCharacter : public AMJMonsterCharacter +class PROJECTMJ_API AMJForestCreatureCharacter : public AMJBossMonsterCharacter { GENERATED_BODY() @@ -21,7 +24,7 @@ class PROJECTMJ_API AMJForestCreatureCharacter : public AMJMonsterCharacter virtual void BeginPlay() override; virtual void PossessedBy(AController* NewController) override; - FORCEINLINE UMJCharacterAttributeSet* GetAttributeSet() { return CharacterAttributeSet; } + private: diff --git a/Source/ProjectMJ/Character/MJPlayerCharacter.cpp b/Source/ProjectMJ/Character/MJPlayerCharacter.cpp index 64c6352b..b3662cc4 100644 --- a/Source/ProjectMJ/Character/MJPlayerCharacter.cpp +++ b/Source/ProjectMJ/Character/MJPlayerCharacter.cpp @@ -55,7 +55,8 @@ AMJPlayerCharacter::AMJPlayerCharacter() PlayerCombatComponent = CreateDefaultSubobject(TEXT("PlayerCombatComponent")); //Add FadeComponent - //FadeComponent = CreateDefaultSubobject(TEXT("FadeComponent")); + FadeComponent = CreateDefaultSubobject(TEXT("FadeComponent")); + // Minjin: AI Perception-캐릭터를 StimuliSource로 등록(AI가 감지) PerceptionStimuliSourceComponent = CreateDefaultSubobject(TEXT("AIPerceptionStimuliSourceComponent")); if (nullptr!= PerceptionStimuliSourceComponent) diff --git a/Source/ProjectMJ/Character/MJPlayerCharacter.h b/Source/ProjectMJ/Character/MJPlayerCharacter.h index e7f993cd..74235f70 100644 --- a/Source/ProjectMJ/Character/MJPlayerCharacter.h +++ b/Source/ProjectMJ/Character/MJPlayerCharacter.h @@ -93,8 +93,8 @@ class PROJECTMJ_API AMJPlayerCharacter : public AMJCharacterBase, public IMJInve TObjectPtrPlayerCombatComponent; //FadeActor System Part - /*UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category="Fade", meta = (AllowPrivateAccess = true)) - TObjectPtrFadeComponent;*/ + UPROPERTY(EditDefaultsOnly,BlueprintReadWrite,Category="Fade", meta = (AllowPrivateAccess = true)) + TObjectPtrFadeComponent; #pragma endregion public: diff --git a/Source/ProjectMJ/Component/MJFadeObjectComponent.cpp b/Source/ProjectMJ/Component/MJFadeObjectComponent.cpp index 00f49840..b74fb13c 100644 --- a/Source/ProjectMJ/Component/MJFadeObjectComponent.cpp +++ b/Source/ProjectMJ/Component/MJFadeObjectComponent.cpp @@ -1,4 +1,4 @@ -// 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 "Component/MJFadeObjectComponent.h" @@ -78,142 +78,194 @@ void UMJFadeObjectComponent::BeginPlay() SetActivate(bIsActivate); } - + UGameplayStatics::GetAllActorsOfClass(this, PlayerClass, CharacterArray); + + CachedTraceObjectTypes.Empty(); + CachedTraceObjectTypes.Reserve(ObjectTypes.Num()); + + for (const auto& OT : ObjectTypes) + { + CachedTraceObjectTypes.Add(UEngineTypes::ConvertToObjectType(OT.GetValue())); + } + + CachedTraceParams = FCollisionQueryParams(TEXT("FadeObjectsTrace"), bIsTraceComplex, GetOwner()); + CachedTraceParams.bReturnPhysicalMaterial = false; + CachedTraceParams.bTraceComplex = bIsTraceComplex; + CachedTraceParams.AddIgnoredActors(ActorIgnore); } void UMJFadeObjectComponent::AddObjectHideTimer() { - UGameplayStatics::GetAllActorsOfClass(this, PlayerClass, CharacterArray); + const FVector TraceStart = GEngine->GetFirstLocalPlayerController(GetOwner()->GetWorld())->PlayerCameraManager->GetCameraLocation(); + + TArrayHitArray; + HitArray.Reserve(64); for (AActor* CurrentActor : CharacterArray) { - const FVector TraceStart=GEngine->GetFirstLocalPlayerController(GetOwner()->GetWorld())->PlayerCameraManager->GetCameraLocation(); - const FVector TraceEnd = CurrentActor->GetActorLocation(); - FVector TraceLength = TraceStart - TraceEnd; - const FQuat AcQuat = CurrentActor->GetActorQuat(); - if (TraceLength.Size() < WorkDistance) + if (!IsValid(CurrentActor)) { - FCollisionQueryParams TraceParams(TEXT("FadeObjectsTrace"), bIsTraceComplex, GetOwner()); + return; + } + const FVector TargetLocation = CurrentActor->GetActorLocation(); + const float DistSq = FVector::DistSquared(TraceStart, TargetLocation); + if (DistSq > FMath::Square(WorkDistance)) + { + continue; + } + HitArray.Reset(); - TraceParams.AddIgnoredActors(ActorIgnore); - TraceParams.bReturnPhysicalMaterial = false; - TraceParams.bTraceComplex = bIsTraceComplex; + GetOwner()->GetWorld()->SweepMultiByObjectType(HitArray, TraceStart, TargetLocation, FQuat::Identity, CachedTraceObjectTypes, + FCollisionShape::MakeCapsule(CapsuleRadius, CapsuleHalfHeight), CachedTraceParams); - TArrayHitArray; - TArray> traceObjectTypes; - for (int i = 0; i < ObjectTypes.Num(); i++) + for (const FHitResult& HR : HitArray) + { + UPrimitiveComponent* HitComp = HR.GetComponent(); + if (!HR.bBlockingHit || !IsValid(HitComp)) { - traceObjectTypes.Add(UEngineTypes::ConvertToObjectType(ObjectTypes[i].GetValue())); + continue; } - GetOwner()->GetWorld()->SweepMultiByObjectType(HitArray, TraceStart, TraceEnd, AcQuat, traceObjectTypes, - FCollisionShape::MakeCapsule(CapsuleRadius, CapsuleHalfHeight), TraceParams); - for (int IHit = 0; IHit < HitArray.Num(); IHit++) + if (!FadeObjectsHit.Contains(HitComp)) { - if (HitArray[IHit].bBlockingHit && IsValid(HitArray[IHit].GetComponent()) - && !FadeObjectsHit.Contains(HitArray[IHit].GetComponent())) - { - FadeObjectsHit.AddUnique(HitArray[IHit].GetComponent()); - } + FadeObjectsHit.Add(HitComp); } - } - } - for (int IObject = 0; IObject < FadeObjectsHit.Num(); IObject++) - { - if (!FadeObjectTemp.Contains(FadeObjectsHit[IObject])) + } + for (int32 i = FadeObjectTemp.Num() - 1; i >= 0; --i) + { + UPrimitiveComponent* Comp = FadeObjectTemp[i]; + if (!IsValid(Comp)) { + FadeObjectTemp.RemoveAt(i); + continue; + } - FadeObjectTemp.AddUnique(FadeObjectsHit[IObject]); - - TArray IBaseMaterials; - TArray IMID; - - IBaseMaterials.Empty(); - IMID.Empty(); - - for (int Nm = 0; Nm < FadeObjectsHit[IObject]->GetNumMaterials(); Nm++) + if (!FadeObjectsHit.Contains(Comp)) { - IMID.Add(UMaterialInstanceDynamic::Create(FadeMaterial, FadeObjectsHit[IObject])); - IBaseMaterials.Add(FadeObjectsHit[IObject]->GetMaterial(Nm)); + int32 FoundIndex = INDEX_NONE; + for (int32 j = 0; j < FadeObject.Num(); ++j) + { + if (FadeObject[j].PrimitiveComp == Comp) + { + FoundIndex = j; + break; + } + } - FadeObjectsHit[IObject]->SetMaterial(Nm, IMID.Last()); + if (FoundIndex != INDEX_NONE) + { + FFadeSystemStuc& Item = FadeObject[FoundIndex]; - } - FFadeSystemStuc NewObject; - NewObject.NewElement(FadeObjectsHit[IObject], IBaseMaterials, IMID, ImmediatelyFade, true); - NewObject.CameraCollsion = FadeObjectsHit[IObject]->GetCollisionResponseToChannel(ECC_Camera); + + for (int32 m = 0; m < Item.BaseMatInterface.Num(); ++m) + { + Comp->SetMaterial(m, Item.BaseMatInterface[m]); + } + Item.SetToHide(false); - FadeObject.Add(NewObject); + } - FadeObjectsHit[IObject]->SetCollisionResponseToChannel(ECC_Camera, ECR_Ignore); } + } + } - for (int Fot = 0; Fot < FadeObjectTemp.Num(); ++Fot) + + for (UPrimitiveComponent* PrimComp : FadeObjectsHit) { - if (!FadeObjectsHit.Contains(FadeObjectTemp[Fot])) + if (!IsValid(PrimComp)) { - FadeObject[Fot].SetToHide(false); + continue; } + + if (ComponentMIDMap.Contains(PrimComp)) + { + if (!FadeObjectTemp.Contains(PrimComp)) + { + FadeObjectTemp.Add(PrimComp); + } + continue; + } + + TArray IBaseMaterials; + TArray IMID; + const int32 NumMats = PrimComp->GetNumMaterials(); + IBaseMaterials.Reserve(NumMats); + IMID.Reserve(NumMats); + + for (int32 idx = 0; idx < NumMats; ++idx) + { + UMaterialInterface* CurMat = PrimComp->GetMaterial(idx); + IBaseMaterials.Add(CurMat); + + UMaterialInstanceDynamic* NewMID = UMaterialInstanceDynamic::Create(FadeMaterial, PrimComp); + IMID.Add(NewMID); + + PrimComp->SetMaterial(idx, NewMID); + } + + FFadeSystemStuc NewObject; + NewObject.NewElement(PrimComp, IBaseMaterials, IMID, ImmediatelyFade, true); + NewObject.CameraCollsion = PrimComp->GetCollisionResponseToChannel(ECC_Camera); + + FadeObject.Add(NewObject); + + + TArray> WeakMIDs; + for (UMaterialInstanceDynamic* m : IMID) WeakMIDs.Add(m); + ComponentMIDMap.Add(PrimComp, WeakMIDs); + + + PrimComp->SetCollisionResponseToChannel(ECC_Camera, ECR_Ignore); + } + FadeObjectsHit.Empty(); } void UMJFadeObjectComponent::FadeWorkTimer() { - if (FadeObject.Num() > 0) + if (FadeObject.Num() == 0) return; + + UWorld* World = GetWorld(); + if (!World) return; + + for (int32 i = FadeObject.Num() - 1; i >= 0; --i) { - for (int IObject = 0; IObject < FadeObject.Num(); ++IObject) + FFadeSystemStuc& Item = FadeObject[i]; + + const bool bToHide = Item.bToHide; + const float TargetF = bToHide ? FarObjectFade : 1.0f; + const float CurrentF = Item.FadeCount; + + const float NewFade = FMath::FInterpConstantTo(CurrentF, TargetF, World->GetDeltaSeconds(), FadeRate); + + + for (UMaterialInstanceDynamic* MID : Item.FadeMID) { - float AdaptiveFade; - int FniD = IObject; - - if (FniD == FadeObject.Num()) - { - AdaptiveFade = NearObjectFade; - } - else + if (IsValid(MID)) { - AdaptiveFade = FarObjectFade; + MID->SetScalarParameterValue(TEXT("Fade"), NewFade); } + } - for (int i = 0; i < FadeObject[IObject].FadeMID.Num(); i++) - { - float TargetF; - const float CurrentF = FadeObject[IObject].FadeCount; - if (FadeObject[IObject].bToHide) - { - TargetF = AdaptiveFade; - } - else - { - TargetF = 1.0f; - } - const float NewFade = FMath::FInterpConstantTo(CurrentF, TargetF, GetOwner()->GetWorld()->GetDeltaSeconds(), FadeRate); - FadeObject[IObject].FadeMID[i]->SetScalarParameterValue("Fade", NewFade); - CurrentFade = NewFade; + Item.SetHideAndFade(bToHide, NewFade); + Item.FadeCount = NewFade; - FadeObject[IObject].SetHideAndFade(FadeObject[IObject].bToHide, NewFade); - } - if (CurrentFade == 1.0f) - { - for (int IBaseMat = 0; IBaseMat < FadeObject[FniD].BaseMatInterface.Num(); ++IBaseMat) - { - FadeObject[FniD].PrimitiveComp->SetMaterial(IBaseMat, FadeObject[FniD].BaseMatInterface[IBaseMat]); - } - FadeObject[FniD].PrimitiveComp->SetCollisionResponseToChannel(ECC_Camera, FadeObject[FniD].CameraCollsion); - FadeObject.RemoveAt(FniD); - FadeObjectTemp.RemoveAt(FniD); - } + if (FMath::IsNearlyEqual(NewFade, 1.0f, 1e-3f)) + { + ComponentMIDMap.Remove(Item.PrimitiveComp); + FadeObject.RemoveAt(i, 1, false); + FadeObjectTemp.Remove(Item.PrimitiveComp); } - } + } void UMJFadeObjectComponent::SetEnable(bool _bIsEnable) diff --git a/Source/ProjectMJ/Component/MJFadeObjectComponent.h b/Source/ProjectMJ/Component/MJFadeObjectComponent.h index 2cac682d..b66fa710 100644 --- a/Source/ProjectMJ/Component/MJFadeObjectComponent.h +++ b/Source/ProjectMJ/Component/MJFadeObjectComponent.h @@ -1,4 +1,4 @@ -// Fill out your copyright notice in the Description page of Project Settings. +// Fill out your copyright notice in the Description page of Project Settings. #pragma once @@ -145,5 +145,10 @@ class PROJECTMJ_API UMJFadeObjectComponent : public UActorComponent UPROPERTY(EditAnywhere, Category = "Fade Objects") float ImmediatelyFade; + TMap, TArray>> ComponentMIDMap; + + TArray> CachedTraceObjectTypes; + + FCollisionQueryParams CachedTraceParams; }; diff --git a/Source/ProjectMJ/MJ/AI/BTService_MJCheckAttackRange.cpp b/Source/ProjectMJ/MJ/AI/BTService_MJCheckAttackRange.cpp index 297545c1..c6590c75 100644 --- a/Source/ProjectMJ/MJ/AI/BTService_MJCheckAttackRange.cpp +++ b/Source/ProjectMJ/MJ/AI/BTService_MJCheckAttackRange.cpp @@ -127,8 +127,8 @@ void UBTService_MJCheckAttackRange::TickNode(UBehaviorTreeComponent& OwnerComp, const float MinimumAttackRange = Character->GetCapsuleComponent()->GetScaledCapsuleRadius() * ((Offset!=0)?Offset:1); const float MaximumAttackRange = MinimumAttackRange + AttackRange; - //DrawDebugCircle(GetWorld(), ControlledPawn->GetActorLocation(), MaximumAttackRange, 16, FColor::Emerald, false, 0.2f, 0, 0, FVector::RightVector,FVector::ForwardVector, false); - //DrawDebugCircle(GetWorld(), ControlledPawn->GetActorLocation(), MinimumAttackRange, 16, FColor::Magenta, false, 0.2f, 0, 0, FVector::RightVector,FVector::ForwardVector, false); + DrawDebugCircle(GetWorld(), ControlledPawn->GetActorLocation(), MaximumAttackRange, 16, FColor::Emerald, false, 0.2f, 0, 0, FVector::RightVector,FVector::ForwardVector, false); + DrawDebugCircle(GetWorld(), ControlledPawn->GetActorLocation(), MinimumAttackRange, 16, FColor::Magenta, false, 0.2f, 0, 0, FVector::RightVector,FVector::ForwardVector, false); bool IsInAttackRange = DistanceToTarget <= MaximumAttackRange && DistanceToTarget >= MinimumAttackRange; diff --git a/Source/ProjectMJ/MJ/AI/BTService_MJCheckHealth.cpp b/Source/ProjectMJ/MJ/AI/BTService_MJCheckHealth.cpp index 8d31df9f..fc37d503 100644 --- a/Source/ProjectMJ/MJ/AI/BTService_MJCheckHealth.cpp +++ b/Source/ProjectMJ/MJ/AI/BTService_MJCheckHealth.cpp @@ -21,7 +21,7 @@ void UBTService_MJCheckHealth::TickNode(UBehaviorTreeComponent& OwnerComp, uint8 { Super::TickNode(OwnerComp, NodeMemory, DeltaSeconds); - ControlledPawn =Cast(OwnerComp.GetAIOwner()->GetPawn()); + ControlledPawn =Cast(OwnerComp.GetAIOwner()->GetPawn()); if (!ControlledPawn) { return; @@ -35,7 +35,7 @@ void UBTService_MJCheckHealth::TickNode(UBehaviorTreeComponent& OwnerComp, uint8 } CachedASC->GetGameplayAttributeValueChangeDelegate(ControlledPawn->GetAttributeSet()->GetHealthAttribute()).AddUObject(this, &UBTService_MJCheckHealth::EnemyOnChangedHealth); - + MaxHealth = ControlledPawn->GetAttributeSet()->GetMaxHealth(); } void UBTService_MJCheckHealth::EnemyOnChangedHealth(const FOnAttributeChangeData& Data) @@ -45,7 +45,7 @@ void UBTService_MJCheckHealth::EnemyOnChangedHealth(const FOnAttributeChangeData return; } float CurrentHP = Data.NewValue; - bool IsSet = (CurrentHP <= 200.f) ? true : false; + bool IsSet = (CurrentHP/MaxHealth <= 0.6f) ? true : false; Blackboard->SetValueAsBool("IsAttack",IsSet); } \ No newline at end of file diff --git a/Source/ProjectMJ/MJ/AI/BTService_MJCheckHealth.h b/Source/ProjectMJ/MJ/AI/BTService_MJCheckHealth.h index c4a1718e..2a652c2c 100644 --- a/Source/ProjectMJ/MJ/AI/BTService_MJCheckHealth.h +++ b/Source/ProjectMJ/MJ/AI/BTService_MJCheckHealth.h @@ -14,7 +14,7 @@ * Last Modified By: (Last Modifier) * Last Modified Date: (Last Modified Date) */ -class AMJForestCreatureCharacter; +class AMJBossMonsterCharacter; class UAbilitySystemComponent; class UBlackboardComponent; @@ -32,9 +32,10 @@ class PROJECTMJ_API UBTService_MJCheckHealth : public UBTService private: - AMJForestCreatureCharacter* ControlledPawn = nullptr; + AMJBossMonsterCharacter* ControlledPawn = nullptr; UAbilitySystemComponent* CachedASC; UBlackboardComponent* Blackboard; + float MaxHealth; public: void EnemyOnChangedHealth(const FOnAttributeChangeData& Data); diff --git a/Source/ProjectMJ/MJ/Character/MJBossMonsterCharacter.cpp b/Source/ProjectMJ/MJ/Character/MJBossMonsterCharacter.cpp new file mode 100644 index 00000000..0ef9b66b --- /dev/null +++ b/Source/ProjectMJ/MJ/Character/MJBossMonsterCharacter.cpp @@ -0,0 +1,40 @@ +// ThenOneDayStudio + + +#include "MJ/Character/MJBossMonsterCharacter.h" + +#include "AbilitySystemComponent.h" +#include "AbilitySystem/Attributes/MJCharacterAttributeSet.h" +#include "MJ/AI/MJMonsterAIControllerBase.h" +#include "BehaviorTree/BlackboardComponent.h" + +void AMJBossMonsterCharacter::BeginPlay() +{ + Super::BeginPlay(); + bHasTriggerPatten = false; + GetAbilitySystemComponent()->GetGameplayAttributeValueChangeDelegate(GetAttributeSet()->GetHealthAttribute()).AddUObject(this, &AMJBossMonsterCharacter::OnHealthChanged); +} + +void AMJBossMonsterCharacter::OnHealthChanged(const FOnAttributeChangeData& Data) +{ + float CurrentHp = Data.NewValue; + bool bIsAttack = (CurrentHp / GetAttributeSet()->GetMaxHealth() <= 0.6); + + if (!bHasTriggerPatten && bIsAttack) + { + bHasTriggerPatten = true; + + AMJMonsterAIControllerBase* AIController = Cast(GetController()); + if (!AIController) + { + return; + } + UBlackboardComponent* BB = AIController->GetBlackboardComponent(); + if (!BB) + { + return; + } + + BB->SetValueAsBool("IsAttack", bIsAttack); + } +} diff --git a/Source/ProjectMJ/MJ/Character/MJBossMonsterCharacter.h b/Source/ProjectMJ/MJ/Character/MJBossMonsterCharacter.h new file mode 100644 index 00000000..b7b75c81 --- /dev/null +++ b/Source/ProjectMJ/MJ/Character/MJBossMonsterCharacter.h @@ -0,0 +1,31 @@ +// ThenOneDayStudio + +#pragma once + +#include "CoreMinimal.h" +#include "MJ/Character/MJMonsterCharacter.h" +#include "MJBossMonsterCharacter.generated.h" + +/** + * Class Description: Boss Character + * Author: Lee JuHyeon + * Created Date: 2025.08.19. + * Last Modified By: (Last Modifier) + * Last Modified Date: (Last Modified Date) + */ +UCLASS() +class PROJECTMJ_API AMJBossMonsterCharacter : public AMJMonsterCharacter +{ + GENERATED_BODY() + +protected: + virtual void BeginPlay() override; + +public: + + void OnHealthChanged(const FOnAttributeChangeData& Data); + FORCEINLINE UMJCharacterAttributeSet* GetAttributeSet() { return CharacterAttributeSet; } + +private: + bool bHasTriggerPatten; +}; diff --git a/Source/ProjectMJ/MJ/Character/MJSpiderMinionCharacter.h b/Source/ProjectMJ/MJ/Character/MJSpiderMinionCharacter.h index 1c77a45e..144cdb93 100644 --- a/Source/ProjectMJ/MJ/Character/MJSpiderMinionCharacter.h +++ b/Source/ProjectMJ/MJ/Character/MJSpiderMinionCharacter.h @@ -7,7 +7,10 @@ #include "MJSpiderMinionCharacter.generated.h" /** - * + * Class Description: SpiderMinion + * Author: Lee JuHyeon + * Created Date: 2025.08.11. + */ UCLASS() class PROJECTMJ_API AMJSpiderMinionCharacter : public AMJMonsterCharacter diff --git a/Source/ProjectMJ/TG/UI/MJBossHpBarWidget.cpp b/Source/ProjectMJ/TG/UI/MJBossHpBarWidget.cpp index 310848df..9ddb8462 100644 --- a/Source/ProjectMJ/TG/UI/MJBossHpBarWidget.cpp +++ b/Source/ProjectMJ/TG/UI/MJBossHpBarWidget.cpp @@ -7,6 +7,7 @@ #include "AbilitySystem/Attributes/MJCharacterAttributeSet.h" #include "Components/ProgressBar.h" #include "Kismet/GameplayStatics.h" +#include "MJ/Character/MJBossMonsterCharacter.h" #include "TG/AI/MJAIBossCharacterTG.h" void UMJBossHpBarWidget::NativeConstruct() @@ -16,11 +17,11 @@ void UMJBossHpBarWidget::NativeConstruct() void UMJBossHpBarWidget::BindToAttributes() { - AActor* BossRef = UGameplayStatics::GetActorOfClass(GetWorld(),AMJAIBossCharacterTG::StaticClass()); + AActor* BossRef = UGameplayStatics::GetActorOfClass(GetWorld(),AMJBossMonsterCharacter::StaticClass()); if (BossRef) { - AMJAIBossCharacterTG* MJBossRef = Cast(BossRef); + AMJBossMonsterCharacter* MJBossRef = Cast(BossRef); if (MJBossRef) { diff --git a/Source/ProjectMJ/TG/UI/MJBossHpBarWidget.h b/Source/ProjectMJ/TG/UI/MJBossHpBarWidget.h index 6d27caf1..50252d60 100644 --- a/Source/ProjectMJ/TG/UI/MJBossHpBarWidget.h +++ b/Source/ProjectMJ/TG/UI/MJBossHpBarWidget.h @@ -13,6 +13,8 @@ class UProgressBar; * Created Date: 2025-07-19 * Last Modified By: Cha Tae Gwan * Last Modified Date: 2025-07-19 + * Last Modified By: Lee Ju Hyeon + * Last Modified Date: 2025-08-30 */ UCLASS() class PROJECTMJ_API UMJBossHpBarWidget : public UUserWidget