From ec99e302ede9b379388d92246432b84a89368e81 Mon Sep 17 00:00:00 2001 From: dal4segno Date: Wed, 11 Mar 2026 01:35:02 +0900 Subject: [PATCH] =?UTF-8?q?[Abnormality]=20=EC=9D=B4=EC=83=81=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=EC=8B=9C=EC=8A=A4=ED=85=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 이상 상태 데이터 (버프/디버프) ScriptableObject 정의 - 런타임임 활성 이상 상태 관리 (ActiveAbnormality) - 캐릭터터별 AbnormalityManager 컴포넌트로 이상 상태 적용/제거 - 스킬 효과(AbnormalityEffect)로 스킬에 이상 상태 연동 - UI 슬롯 및 목록 표시 구현 (버프/디버프 구분) - 테스트 코드 및 씬 설정 추가 Co-Authored-By: Claude Opus 4.6 --- .claude/settings.local.json | 8 +- Assets/Abnormalities.meta | 8 + .../Abnormalities/Abnormality_Test_Buff.asset | 24 + .../Abnormality_Test_Buff.asset.meta | 8 + .../Abnormality_Test_Debuff.asset | 24 + .../Abnormality_Test_Debuff.asset.meta | 8 + .../Animations/Melee_Slash.fbx.meta | 14 + .../UI/SPR_FantasyWarrior_Frame_Box_16.png | Bin 0 -> 60486 bytes .../SPR_FantasyWarrior_Frame_Box_16.png.meta | 108 +++ .../UI/UI_AbnormalitySlot.prefab | 696 ++++++++++++++++++ .../UI/UI_AbnormalitySlot.prefab.meta | 7 + Assets/Prefabs/Player/Player.prefab | 28 +- Assets/Scenes/Test.unity | 207 ++++++ Assets/Scripts/Abnormalities.meta | 8 + .../Scripts/Abnormalities/AbnormalityData.cs | 101 +++ .../Abnormalities/AbnormalityData.cs.meta | 2 + .../Abnormalities/AbnormalityManager.cs | 494 +++++++++++++ .../Abnormalities/AbnormalityManager.cs.meta | 2 + .../Abnormalities/ActiveAbnormality.cs | 134 ++++ .../Abnormalities/ActiveAbnormality.cs.meta | 2 + .../Skills/Effects/AbnormalityEffect.cs | 46 ++ .../Skills/Effects/AbnormalityEffect.cs.meta | 2 + Assets/Scripts/Skills/Effects/BuffEffect.cs | 32 - .../Scripts/Skills/Effects/BuffEffect.cs.meta | 2 - Assets/Scripts/StatusEffects.meta | 8 + Assets/Scripts/UI/AbnormalityListUI.cs | 279 +++++++ Assets/Scripts/UI/AbnormalityListUI.cs.meta | 2 + Assets/Scripts/UI/AbnormalitySlotUI.cs | 182 +++++ Assets/Scripts/UI/AbnormalitySlotUI.cs.meta | 2 + Assets/Scripts/UI/AbnormalitySystemTest.cs | 116 +++ .../Scripts/UI/AbnormalitySystemTest.cs.meta | 2 + Assets/Skills/Effects/Melee_Slash_1.asset | 26 + .../Skills/Effects/Melee_Slash_1.asset.meta | 8 + Assets/Skills/Effects/Melee_Slash_2.asset | 26 + .../Skills/Effects/Melee_Slash_2.asset.meta | 8 + 35 files changed, 2586 insertions(+), 38 deletions(-) create mode 100644 Assets/Abnormalities.meta create mode 100644 Assets/Abnormalities/Abnormality_Test_Buff.asset create mode 100644 Assets/Abnormalities/Abnormality_Test_Buff.asset.meta create mode 100644 Assets/Abnormalities/Abnormality_Test_Debuff.asset create mode 100644 Assets/Abnormalities/Abnormality_Test_Debuff.asset.meta create mode 100644 Assets/External_Used/UI/SPR_FantasyWarrior_Frame_Box_16.png create mode 100644 Assets/External_Used/UI/SPR_FantasyWarrior_Frame_Box_16.png.meta create mode 100644 Assets/External_Used/UI/UI_AbnormalitySlot.prefab create mode 100644 Assets/External_Used/UI/UI_AbnormalitySlot.prefab.meta create mode 100644 Assets/Scripts/Abnormalities.meta create mode 100644 Assets/Scripts/Abnormalities/AbnormalityData.cs create mode 100644 Assets/Scripts/Abnormalities/AbnormalityData.cs.meta create mode 100644 Assets/Scripts/Abnormalities/AbnormalityManager.cs create mode 100644 Assets/Scripts/Abnormalities/AbnormalityManager.cs.meta create mode 100644 Assets/Scripts/Abnormalities/ActiveAbnormality.cs create mode 100644 Assets/Scripts/Abnormalities/ActiveAbnormality.cs.meta create mode 100644 Assets/Scripts/Skills/Effects/AbnormalityEffect.cs create mode 100644 Assets/Scripts/Skills/Effects/AbnormalityEffect.cs.meta delete mode 100644 Assets/Scripts/Skills/Effects/BuffEffect.cs delete mode 100644 Assets/Scripts/Skills/Effects/BuffEffect.cs.meta create mode 100644 Assets/Scripts/StatusEffects.meta create mode 100644 Assets/Scripts/UI/AbnormalityListUI.cs create mode 100644 Assets/Scripts/UI/AbnormalityListUI.cs.meta create mode 100644 Assets/Scripts/UI/AbnormalitySlotUI.cs create mode 100644 Assets/Scripts/UI/AbnormalitySlotUI.cs.meta create mode 100644 Assets/Scripts/UI/AbnormalitySystemTest.cs create mode 100644 Assets/Scripts/UI/AbnormalitySystemTest.cs.meta create mode 100644 Assets/Skills/Effects/Melee_Slash_1.asset create mode 100644 Assets/Skills/Effects/Melee_Slash_1.asset.meta create mode 100644 Assets/Skills/Effects/Melee_Slash_2.asset create mode 100644 Assets/Skills/Effects/Melee_Slash_2.asset.meta diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 4cf7fc51..f985ddfe 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -5,7 +5,13 @@ "Bash(git fsck:*)", "Bash(git commit:*)", "Bash(git read-tree:*)", - "Bash(git push:*)" + "Bash(git push:*)", + "Bash(cd \"D:/Colosseum/Assets/Scripts/StatusEffects\" && sed -i 's/ActiveStatusEffect/ActiveStatusEffect/g' StatusEffectManager.cs)", + "Bash(cd \"D:/Colosseum/Assets/Scripts/UI\" && sed -i 's/ActiveStatusEffect/ActiveStatusEffect/g' StatusEffectUI.cs StatusEffectListUI.cs)", + "Bash(cd \"D:/Colosseum/Assets/Scripts\" && mv StatusEffects Abnormalities)", + "Bash(cd \"D:/Colosseum/Assets/Scripts/Abnormalities\" && mv StatusEffectData.cs AbnormalityData.cs && mv ActiveStatusEffect.cs ActiveAbnormality.cs && mv StatusEffectManager.cs AbnormalityManager.cs)", + "Bash(cd \"D:/Colosseum/Assets/Scripts/UI\" && mv StatusEffectUI.cs AbnormalitySlotUI.cs && mv StatusEffectListUI.cs AbnormalityListUI.cs)", + "Bash(git -C \"D:/Colosseum\" mv \"Assets/Scripts/Skills/Effects/BuffEffect.cs\" \"Assets/Scripts/Skills/Effects/AbnormalityEffect.cs\")" ] } } diff --git a/Assets/Abnormalities.meta b/Assets/Abnormalities.meta new file mode 100644 index 00000000..ef1f3c36 --- /dev/null +++ b/Assets/Abnormalities.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 72b7a9faa543d444882609fe047a2073 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Abnormalities/Abnormality_Test_Buff.asset b/Assets/Abnormalities/Abnormality_Test_Buff.asset new file mode 100644 index 00000000..c3e4f6be --- /dev/null +++ b/Assets/Abnormalities/Abnormality_Test_Buff.asset @@ -0,0 +1,24 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b08cc671f858a3b409170a5356e960a0, type: 3} + m_Name: Abnormality_Test_Buff + m_EditorClassIdentifier: Colosseum.Game::Colosseum.Abnormalities.AbnormalityData + abnormalityName: Abnormality + icon: {fileID: 21300000, guid: 173f7bf0258285c4f8bf01825ac02a11, type: 3} + duration: 99 + level: 1 + isDebuff: 0 + statModifiers: [] + periodicInterval: 0 + periodicValue: 0 + controlType: 0 + slowMultiplier: 0.5 diff --git a/Assets/Abnormalities/Abnormality_Test_Buff.asset.meta b/Assets/Abnormalities/Abnormality_Test_Buff.asset.meta new file mode 100644 index 00000000..8aee3144 --- /dev/null +++ b/Assets/Abnormalities/Abnormality_Test_Buff.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: da5a38e4e2c383940a34d9d8080fbbe0 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Abnormalities/Abnormality_Test_Debuff.asset b/Assets/Abnormalities/Abnormality_Test_Debuff.asset new file mode 100644 index 00000000..b055031d --- /dev/null +++ b/Assets/Abnormalities/Abnormality_Test_Debuff.asset @@ -0,0 +1,24 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b08cc671f858a3b409170a5356e960a0, type: 3} + m_Name: Abnormality_Test_Debuff + m_EditorClassIdentifier: Colosseum.Game::Colosseum.Abnormalities.AbnormalityData + abnormalityName: Abnormality + icon: {fileID: 21300000, guid: 173f7bf0258285c4f8bf01825ac02a11, type: 3} + duration: 99 + level: 1 + isDebuff: 1 + statModifiers: [] + periodicInterval: 0 + periodicValue: 0 + controlType: 0 + slowMultiplier: 0.5 diff --git a/Assets/Abnormalities/Abnormality_Test_Debuff.asset.meta b/Assets/Abnormalities/Abnormality_Test_Debuff.asset.meta new file mode 100644 index 00000000..54c22c3b --- /dev/null +++ b/Assets/Abnormalities/Abnormality_Test_Debuff.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c4abb0f89779f294ab99562e085e8f3b +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External_Used/Animations/Melee_Slash.fbx.meta b/Assets/External_Used/Animations/Melee_Slash.fbx.meta index 0452702c..faf74fc2 100644 --- a/Assets/External_Used/Animations/Melee_Slash.fbx.meta +++ b/Assets/External_Used/Animations/Melee_Slash.fbx.meta @@ -55,6 +55,20 @@ ModelImporter: bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000 curves: [] events: + - time: 0.4590326 + functionName: OnEffect + data: + objectReferenceParameter: {instanceID: 0} + floatParameter: 0 + intParameter: 1 + messageOptions: 0 + - time: 0.46052074 + functionName: OnEffect + data: + objectReferenceParameter: {instanceID: 0} + floatParameter: 0 + intParameter: 2 + messageOptions: 0 - time: 0.4627699 functionName: OnEffect data: diff --git a/Assets/External_Used/UI/SPR_FantasyWarrior_Frame_Box_16.png b/Assets/External_Used/UI/SPR_FantasyWarrior_Frame_Box_16.png new file mode 100644 index 0000000000000000000000000000000000000000..c207d8f1cdf98edd3bbb20353e128b1612388c6f GIT binary patch literal 60486 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 literal 0 HcmV?d00001 diff --git a/Assets/External_Used/UI/SPR_FantasyWarrior_Frame_Box_16.png.meta b/Assets/External_Used/UI/SPR_FantasyWarrior_Frame_Box_16.png.meta new file mode 100644 index 00000000..04425dc9 --- /dev/null +++ b/Assets/External_Used/UI/SPR_FantasyWarrior_Frame_Box_16.png.meta @@ -0,0 +1,108 @@ +fileFormatVersion: 2 +guid: 976db4f04c3bd4e469e9b8eb2c20e1ca +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 0 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 80, y: 80, z: 80, w: 80} + spriteGenerateFallbackPhysicsShape: 0 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External_Used/UI/UI_AbnormalitySlot.prefab b/Assets/External_Used/UI/UI_AbnormalitySlot.prefab new file mode 100644 index 00000000..0661d592 --- /dev/null +++ b/Assets/External_Used/UI/UI_AbnormalitySlot.prefab @@ -0,0 +1,696 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &3383354828365798028 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8742265258977334277} + - component: {fileID: 3698892055439276710} + - component: {fileID: 9068576939756357679} + - component: {fileID: 8350059981962847808} + - component: {fileID: 800351318774919540} + - component: {fileID: 5402880947663824673} + m_Layer: 5 + m_Name: UI_AbnormalitySlot + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &8742265258977334277 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3383354828365798028} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 2211778034640404479} + - {fileID: 2830353451877067372} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 50, y: 50} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &3698892055439276710 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3383354828365798028} + m_CullTransparentMesh: 1 +--- !u!114 &9068576939756357679 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3383354828365798028} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 1, b: 0.14357352, a: 0} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 0 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!114 &8350059981962847808 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3383354828365798028} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 3 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 9068576939756357679} + m_OnClick: + m_PersistentCalls: + m_Calls: [] +--- !u!95 &800351318774919540 +Animator: + serializedVersion: 7 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3383354828365798028} + m_Enabled: 1 + m_Avatar: {fileID: 0} + m_Controller: {fileID: 9100000, guid: f6c1759d41da8c942acb67824989a5b8, type: 2} + m_CullingMode: 0 + m_UpdateMode: 0 + m_ApplyRootMotion: 0 + m_LinearVelocityBlending: 0 + m_StabilizeFeet: 0 + m_AnimatePhysics: 0 + m_WarningMessage: + m_HasTransformHierarchy: 1 + m_AllowConstantClipSamplingOptimization: 1 + m_KeepAnimatorStateOnDisable: 0 + m_WriteDefaultValuesOnDisable: 0 +--- !u!114 &5402880947663824673 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3383354828365798028} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 287a45a81e69cbf48845f88759cf7eb4, type: 3} + m_Name: + m_EditorClassIdentifier: + iconImage: {fileID: 8225599256848301212} + durationFill: {fileID: 3807928883176071825} + durationText: {fileID: 2584127467159023136} + effectNameText: {fileID: 0} + backgroundImage: {fileID: 6218527427496975808} + buffColor: {r: 0.2, g: 0.6, b: 0.2, a: 0.8} + debuffColor: {r: 0.6, g: 0.2, b: 0.2, a: 0.8} +--- !u!1 &3546204093425322779 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2830353451877067372} + - component: {fileID: 8318959168881738735} + - component: {fileID: 5659953853696642109} + - component: {fileID: 3039300877730597146} + m_Layer: 5 + m_Name: SPR_Frame + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2830353451877067372 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3546204093425322779} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 8742265258977334277} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &8318959168881738735 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3546204093425322779} + m_CullTransparentMesh: 1 +--- !u!114 &5659953853696642109 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3546204093425322779} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 1, b: 0, a: 1} + m_RaycastTarget: 0 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 0 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: 976db4f04c3bd4e469e9b8eb2c20e1ca, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 4 +--- !u!225 &3039300877730597146 +CanvasGroup: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3546204093425322779} + m_Enabled: 1 + m_Alpha: 1 + m_Interactable: 0 + m_BlocksRaycasts: 0 + m_IgnoreParentGroups: 0 +--- !u!1 &4902539774281912895 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2062133184972599418} + - component: {fileID: 5719122352651651396} + m_Layer: 5 + m_Name: Item + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2062133184972599418 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4902539774281912895} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1336485923641369346} + m_Father: {fileID: 2211778034640404479} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!225 &5719122352651651396 +CanvasGroup: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4902539774281912895} + m_Enabled: 1 + m_Alpha: 1 + m_Interactable: 0 + m_BlocksRaycasts: 0 + m_IgnoreParentGroups: 0 +--- !u!1 &5010645131502399754 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 441187093428371753} + - component: {fileID: 7014205823490043849} + m_Layer: 5 + m_Name: Normal + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &441187093428371753 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5010645131502399754} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1901598294175631088} + m_Father: {fileID: 2211778034640404479} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7014205823490043849 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5010645131502399754} + m_CullTransparentMesh: 1 +--- !u!1 &7471771060503184807 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1901598294175631088} + - component: {fileID: 2489496512246523176} + - component: {fileID: 6218527427496975808} + m_Layer: 5 + m_Name: SPR_Background + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1901598294175631088 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7471771060503184807} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 441187093428371753} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &2489496512246523176 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7471771060503184807} + m_CullTransparentMesh: 1 +--- !u!114 &6218527427496975808 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7471771060503184807} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0, g: 0.12990497, b: 0.23584908, a: 0.9019608} + m_RaycastTarget: 0 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: 626f1122650d7b344a394cf52ebb14ec, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 2.6 +--- !u!1 &8154639474077861285 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2211778034640404479} + m_Layer: 5 + m_Name: MASK + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2211778034640404479 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8154639474077861285} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 441187093428371753} + - {fileID: 2062133184972599418} + m_Father: {fileID: 8742265258977334277} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1001 &3573928083118294605 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 2062133184972599418} + m_Modifications: + - target: {fileID: 378688860670387420, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_Type + value: 3 + objectReference: {fileID: 0} + - target: {fileID: 378688860670387420, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_Color.a + value: 0.39215687 + objectReference: {fileID: 0} + - target: {fileID: 378688860670387420, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_Color.b + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 378688860670387420, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_Color.g + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 378688860670387420, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_Color.r + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 378688860670387420, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_FillAmount + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 378688860670387420, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_FillMethod + value: 4 + objectReference: {fileID: 0} + - target: {fileID: 378688860670387420, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_FillOrigin + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 378688860670387420, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_FillClockwise + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1316615260321933421, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_text + value: 99 + objectReference: {fileID: 0} + - target: {fileID: 1316615260321933421, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_fontSize + value: 16 + objectReference: {fileID: 0} + - target: {fileID: 1316615260321933421, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_margin.x + value: -4.874298 + objectReference: {fileID: 0} + - target: {fileID: 1316615260321933421, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_margin.z + value: -4.115387 + objectReference: {fileID: 0} + - target: {fileID: 1316615260321933421, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_fontSizeBase + value: 16 + objectReference: {fileID: 0} + - target: {fileID: 1316615260321933421, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_VerticalAlignment + value: 256 + objectReference: {fileID: 0} + - target: {fileID: 1316615260321933421, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_HorizontalAlignment + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 1316615260321933421, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: 'm_ActiveFontFeatures.Array.data[0]' + value: 1801810542 + objectReference: {fileID: 0} + - target: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_RootOrder + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_AnchorMax.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_AnchorMax.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_SizeDelta.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_AnchoredPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2889380205718597033, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_IsActive + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 3471770531181138231, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_SizeDelta.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3471770531181138231, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_SizeDelta.y + value: 30 + objectReference: {fileID: 0} + - target: {fileID: 3471770531181138231, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 3471770531181138231, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_AnchoredPosition.y + value: 15 + objectReference: {fileID: 0} + - target: {fileID: 4290268768443257266, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_CullTransparentMesh + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 6658490951639871620, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_Name + value: CooldownItem + objectReference: {fileID: 0} + - target: {fileID: 8431704748052656868, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + propertyPath: m_IsActive + value: 1 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} +--- !u!224 &1336485923641369346 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 2527929489434551631, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + m_PrefabInstance: {fileID: 3573928083118294605} + m_PrefabAsset: {fileID: 0} +--- !u!114 &2584127467159023136 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 1316615260321933421, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + m_PrefabInstance: {fileID: 3573928083118294605} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!114 &3807928883176071825 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 378688860670387420, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + m_PrefabInstance: {fileID: 3573928083118294605} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!114 &8225599256848301212 stripped +MonoBehaviour: + m_CorrespondingSourceObject: {fileID: 4881363607392615121, guid: 76cc919941c27814fa50c37e4df08f89, type: 3} + m_PrefabInstance: {fileID: 3573928083118294605} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: diff --git a/Assets/External_Used/UI/UI_AbnormalitySlot.prefab.meta b/Assets/External_Used/UI/UI_AbnormalitySlot.prefab.meta new file mode 100644 index 00000000..53e7502d --- /dev/null +++ b/Assets/External_Used/UI/UI_AbnormalitySlot.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 60d898ecea82b6c429850e04d2e95b7c +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/Player/Player.prefab b/Assets/Prefabs/Player/Player.prefab index 06d18887..98d30cc3 100644 --- a/Assets/Prefabs/Player/Player.prefab +++ b/Assets/Prefabs/Player/Player.prefab @@ -20,6 +20,7 @@ GameObject: - component: {fileID: 6048740021537676210} - component: {fileID: 6912018896034183004} - component: {fileID: 6585367215453362640} + - component: {fileID: 7524694206394173403} m_Layer: 0 m_Name: Player m_TagString: Untagged @@ -134,6 +135,7 @@ MonoBehaviour: gravity: -9.81 jumpForce: 5 skillController: {fileID: 0} + animator: {fileID: 0} --- !u!114 &194806265065691022 MonoBehaviour: m_ObjectHideFlags: 0 @@ -193,8 +195,7 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: Colosseum.Game::Colosseum.Player.PlayerNetworkController ShowTopMostFoldoutHeaderGroup: 1 - maxHealth: 100 - maxMana: 50 + characterStats: {fileID: 0} --- !u!114 &8606252901290138286 MonoBehaviour: m_ObjectHideFlags: 0 @@ -248,7 +249,10 @@ Animator: m_LinearVelocityBlending: 0 m_StabilizeFeet: 0 m_AnimatePhysics: 0 - m_WarningMessage: + m_WarningMessage: "\nBinding warning: Some generic clip(s) animate transforms that + are already bound by a Humanoid avatar. These transforms can only be changed + by Humanoid clips.\n\tTransform 'Toes_R'\n\tTransform 'Toes_R'\n\tFrom animation + clip 'A_Idle_Base_Sword'\n\tFrom animation clip 'A_Attack_LightCombo01A_Sword'" m_HasTransformHierarchy: 1 m_AllowConstantClipSamplingOptimization: 1 m_KeepAnimatorStateOnDisable: 0 @@ -287,6 +291,8 @@ MonoBehaviour: baseController: {fileID: 9100000, guid: db718381bb2992e469c76c64015e065b, type: 2} baseSkillClip: {fileID: -7717634560727564301, guid: 079bd00af1b92964d8973dcbf2dcd21f, type: 3} debugMode: 1 + showAreaDebug: 1 + debugDrawDuration: 1 --- !u!114 &6585367215453362640 MonoBehaviour: m_ObjectHideFlags: 0 @@ -308,6 +314,22 @@ MonoBehaviour: - {fileID: 0} - {fileID: 0} skillController: {fileID: 6912018896034183004} + networkController: {fileID: 0} +--- !u!114 &7524694206394173403 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6473031571298860035} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1301e893694bcc741a7c4c9be05334ad, type: 3} + m_Name: + m_EditorClassIdentifier: Colosseum.Game::Colosseum.StatusEffects.StatusEffectManager + ShowTopMostFoldoutHeaderGroup: 1 + characterStats: {fileID: 0} + networkController: {fileID: 0} --- !u!1001 &7705728874586931617 PrefabInstance: m_ObjectHideFlags: 0 diff --git a/Assets/Scenes/Test.unity b/Assets/Scenes/Test.unity index a038e085..6abc5bb5 100644 --- a/Assets/Scenes/Test.unity +++ b/Assets/Scenes/Test.unity @@ -250,6 +250,7 @@ RectTransform: m_Children: - {fileID: 1162990049} - {fileID: 7078605117837265129} + - {fileID: 1269404371} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} @@ -1121,6 +1122,68 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} m_Name: m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshProUGUI +--- !u!1 &972424299 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 972424300} + - component: {fileID: 972424301} + m_Layer: 5 + m_Name: Bad Abnormalities + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &972424300 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 972424299} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1269404371} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 400, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &972424301 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 972424299} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.HorizontalLayoutGroup + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 0 + m_ChildControlHeight: 0 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 --- !u!1 &998115954 GameObject: m_ObjectHideFlags: 0 @@ -1328,6 +1391,88 @@ MonoBehaviour: useColorTransition: 0 smoothTransition: 1 lerpSpeed: 15 +--- !u!1 &1269404370 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1269404371} + - component: {fileID: 1269404372} + - component: {fileID: 1269404373} + m_Layer: 5 + m_Name: Abnormalities + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1269404371 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1269404370} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1873670928} + - {fileID: 972424300} + m_Father: {fileID: 260528176} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0} + m_AnchorMax: {x: 0.5, y: 0} + m_AnchoredPosition: {x: -520, y: 120} + m_SizeDelta: {x: 400, y: 200} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1269404372 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1269404370} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.VerticalLayoutGroup + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 0 + m_ChildControlHeight: 0 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!114 &1269404373 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1269404370} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 15447f4a4d271354fb52bbdf1a526c6e, type: 3} + m_Name: + m_EditorClassIdentifier: + buffContainer: {fileID: 1873670928} + debuffContainer: {fileID: 972424300} + slotPrefab: {fileID: 5402880947663824673, guid: 287a45a81e69cbf48845f88759cf7eb4, type: 3} + maxSlots: 10 + autoFindPlayer: 1 --- !u!1 &1432187382 GameObject: m_ObjectHideFlags: 0 @@ -1576,6 +1721,68 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1873670927 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1873670928} + - component: {fileID: 1873670929} + m_Layer: 5 + m_Name: Good Abnormalities + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1873670928 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1873670927} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1269404371} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 400, y: 100} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1873670929 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1873670927} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.HorizontalLayoutGroup + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 0 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 0 + m_ChildControlHeight: 0 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 --- !u!1 &2122318093 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/Abnormalities.meta b/Assets/Scripts/Abnormalities.meta new file mode 100644 index 00000000..b055a845 --- /dev/null +++ b/Assets/Scripts/Abnormalities.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bc6434195fb88a443939a5a0b2747f0a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Abnormalities/AbnormalityData.cs b/Assets/Scripts/Abnormalities/AbnormalityData.cs new file mode 100644 index 00000000..54504f42 --- /dev/null +++ b/Assets/Scripts/Abnormalities/AbnormalityData.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using Colosseum.Stats; + +namespace Colosseum.Abnormalities +{ + /// + /// 제어 효과 타입 + /// + public enum ControlType + { + None, // 제어 효과 없음 + Stun, // 기절 (이동, 스킬 사용 불가) + Silence, // 침묵 (스킬 사용 불가) + Slow // 둔화 (이동 속도 감소) + } + + /// + /// 스탯 수정자 엔트리 + /// + [Serializable] + public class AbnormalityStatModifier + { + [Tooltip("수정할 스탯 타입")] + public StatType statType; + + [Tooltip("수정값")] + public float value; + + [Tooltip("수정 타입 (Flat: 고정값, PercentAdd: 퍼센트 합산, PercentMult: 퍼센트 곱셈)")] + public StatModType modType; + + public AbnormalityStatModifier() { } + + public AbnormalityStatModifier(StatType statType, float value, StatModType modType) + { + this.statType = statType; + this.value = value; + this.modType = modType; + } + } + + /// + /// 이상 상태 정의 ScriptableObject + /// 버프/디버프의 데이터를 정의합니다. + /// + [CreateAssetMenu(fileName = "AbnormalityData", menuName = "Colosseum/Abnormalities/Abnormality")] + public class AbnormalityData : ScriptableObject + { + [Header("기본 정보")] + [Tooltip("이상 상태 이름")] + public string abnormalityName = "Abnormality"; + + [Tooltip("아이콘")] + public Sprite icon; + + [Tooltip("지속 시간 (초, 0 이하면 영구)")] + public float duration = 5f; + + [Tooltip("효과 레벨 (중복 처리용, 높으면 우선)")] + public int level = 1; + + [Tooltip("디버프 여부")] + public bool isDebuff = false; + + [Header("스탯 수정자")] + [Tooltip("스탯에 적용할 수정자 목록")] + public List statModifiers = new List(); + + [Header("주기적 효과 (DoT/HoT)")] + [Tooltip("주기적 효과 간격 (초, 0이면 비활성)")] + public float periodicInterval = 0f; + + [Tooltip("주기적 효과값 (양수=힐, 음수=데미지)")] + public float periodicValue = 0f; + + [Header("제어 효과 (CC)")] + [Tooltip("제어 효과 타입")] + public ControlType controlType = ControlType.None; + + [Tooltip("둔화 배율 (Slow일 때, 0.5 = 50% 감소)")] + [Range(0f, 1f)] + public float slowMultiplier = 0.5f; + + /// + /// 영구 효과인지 확인 + /// + public bool IsPermanent => duration <= 0f; + + /// + /// 주기적 효과가 있는지 확인 + /// + public bool HasPeriodicEffect => periodicInterval > 0f && periodicValue != 0f; + + /// + /// 제어 효과가 있는지 확인 + /// + public bool HasControlEffect => controlType != ControlType.None; + } +} diff --git a/Assets/Scripts/Abnormalities/AbnormalityData.cs.meta b/Assets/Scripts/Abnormalities/AbnormalityData.cs.meta new file mode 100644 index 00000000..14de43d7 --- /dev/null +++ b/Assets/Scripts/Abnormalities/AbnormalityData.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: b08cc671f858a3b409170a5356e960a0 \ No newline at end of file diff --git a/Assets/Scripts/Abnormalities/AbnormalityManager.cs b/Assets/Scripts/Abnormalities/AbnormalityManager.cs new file mode 100644 index 00000000..0a9503de --- /dev/null +++ b/Assets/Scripts/Abnormalities/AbnormalityManager.cs @@ -0,0 +1,494 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using Unity.Netcode; +using Colosseum.Stats; +using Colosseum.Player; + +namespace Colosseum.Abnormalities +{ + /// + /// 캐릭터에 부착되어 이상 상태를 관리하는 컴포넌트 + /// 버프/디버프의 적용, 제거, 주기적 효과를 처리합니다. + /// + public class AbnormalityManager : NetworkBehaviour + { + [Header("References")] + [Tooltip("CharacterStats 컴포넌트 (없으면 자동 검색)")] + [SerializeField] private CharacterStats characterStats; + + [Tooltip("PlayerNetworkController 컴포넌트 (HP/MP 관리용)")] + [SerializeField] private PlayerNetworkController networkController; + + // 활성화된 이상 상태 목록 + private readonly List activeAbnormalities = new List(); + + // 제어 효과 상태 + private int stunCount; + private int silenceCount; + private float slowMultiplier = 1f; + + // 네트워크 동기화용 데이터 + private NetworkList syncedAbnormalities; + + /// + /// 기절 상태 여부 + /// + public bool IsStunned => stunCount > 0; + + /// + /// 침묵 상태 여부 + /// + public bool IsSilenced => silenceCount > 0; + + /// + /// 이동 속도 배율 (1.0 = 기본, 0.5 = 50% 감소) + /// + public float MoveSpeedMultiplier => slowMultiplier; + + /// + /// 행동 가능 여부 (기절이 아닐 때) + /// + public bool CanAct => !IsStunned; + + /// + /// 스킬 사용 가능 여부 + /// + public bool CanUseSkills => !IsStunned && !IsSilenced; + + /// + /// 활성화된 이상 상태 목록 (읽기 전용) + /// + public IReadOnlyList ActiveAbnormalities => activeAbnormalities; + + // 이벤트 + public event Action OnAbnormalityAdded; + public event Action OnAbnormalityRemoved; + public event Action OnAbnormalitiesChanged; + + /// + /// 네트워크 동기화용 이상 상태 데이터 구조체 + /// + private struct AbnormalitySyncData : INetworkSerializable, IEquatable + { + public int AbnormalityId; + public float RemainingDuration; + public ulong SourceClientId; + + public void NetworkSerialize(BufferSerializer serializer) where T : IReaderWriter + { + serializer.SerializeValue(ref AbnormalityId); + serializer.SerializeValue(ref RemainingDuration); + serializer.SerializeValue(ref SourceClientId); + } + + public bool Equals(AbnormalitySyncData other) + { + return AbnormalityId == other.AbnormalityId; + } + } + + private void Awake() + { + if (characterStats == null) + characterStats = GetComponent(); + + if (networkController == null) + networkController = GetComponent(); + + syncedAbnormalities = new NetworkList(); + } + + public override void OnNetworkSpawn() + { + syncedAbnormalities.OnListChanged += OnSyncedAbnormalitiesChanged; + } + + public override void OnNetworkDespawn() + { + syncedAbnormalities.OnListChanged -= OnSyncedAbnormalitiesChanged; + } + + private void Update() + { + if (!IsServer) return; + + UpdateAbnormalities(Time.deltaTime); + } + + /// + /// 이상 상태 적용 + /// + /// 적용할 이상 상태 데이터 + /// 효과 시전자 + public void ApplyAbnormality(AbnormalityData data, GameObject source) + { + if (data == null) + { + Debug.LogWarning("[Abnormality] ApplyAbnormality called with null data"); + return; + } + + if (IsServer) + { + ApplyAbnormalityInternal(data, source); + } + else + { + var sourceNetId = source != null && source.TryGetComponent(out var netObj) ? netObj.NetworkObjectId : 0UL; + ApplyAbnormalityServerRpc(data.GetInstanceID(), sourceNetId); + } + } + + [Rpc(SendTo.Server)] + private void ApplyAbnormalityServerRpc(int dataId, ulong sourceNetworkId) + { + var data = FindAbnormalityDataById(dataId); + if (data == null) + { + Debug.LogWarning($"[Abnormality] Could not find data with ID: {dataId}"); + return; + } + + GameObject source = null; + if (sourceNetworkId != 0UL && NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(sourceNetworkId, out var netObj)) + { + source = netObj.gameObject; + } + + ApplyAbnormalityInternal(data, source); + } + + private void ApplyAbnormalityInternal(AbnormalityData data, GameObject source) + { + var existing = FindExistingAbnormality(data); + + if (existing != null) + { + if (existing.Data == data) + { + existing.RefreshDuration(); + UpdateSyncedAbnormalityDuration(existing); + Debug.Log($"[Abnormality] Refreshed {data.abnormalityName} on {gameObject.name}"); + return; + } + + if (data.level > existing.Data.level) + { + RemoveAbnormalityInternal(existing); + } + else + { + Debug.Log($"[Abnormality] Ignored {data.abnormalityName} (level {data.level}) - existing level {existing.Data.level} is higher or equal"); + return; + } + } + + var newAbnormality = new ActiveAbnormality(data, source); + activeAbnormalities.Add(newAbnormality); + + ApplyStatModifiers(newAbnormality); + ApplyControlEffect(data); + SyncAbnormalityAdd(newAbnormality, source); + + OnAbnormalityAdded?.Invoke(newAbnormality); + OnAbnormalitiesChanged?.Invoke(); + + Debug.Log($"[Abnormality] Applied {data.abnormalityName} (level {data.level}) to {gameObject.name} for {data.duration}s"); + } + + /// + /// 이상 상태 제거 + /// + /// 제거할 이상 상태 데이터 + public void RemoveAbnormality(AbnormalityData data) + { + if (data == null) return; + + if (IsServer) + { + var abnormality = FindExistingAbnormality(data); + if (abnormality != null) + { + RemoveAbnormalityInternal(abnormality); + } + } + else + { + RemoveAbnormalityServerRpc(data.GetInstanceID()); + } + } + + [Rpc(SendTo.Server)] + private void RemoveAbnormalityServerRpc(int dataId) + { + var abnormality = activeAbnormalities.Find(a => a.Data.GetInstanceID() == dataId); + if (abnormality != null) + { + RemoveAbnormalityInternal(abnormality); + } + } + + private void RemoveAbnormalityInternal(ActiveAbnormality abnormality) + { + RemoveStatModifiers(abnormality); + RemoveControlEffect(abnormality.Data); + SyncAbnormalityRemove(abnormality); + activeAbnormalities.Remove(abnormality); + + OnAbnormalityRemoved?.Invoke(abnormality); + OnAbnormalitiesChanged?.Invoke(); + + Debug.Log($"[Abnormality] Removed {abnormality.Data.abnormalityName} from {gameObject.name}"); + } + + /// + /// 모든 이상 상태 제거 + /// + public void RemoveAllAbnormalities() + { + if (!IsServer) + { + RemoveAllAbnormalitiesServerRpc(); + return; + } + + while (activeAbnormalities.Count > 0) + { + RemoveAbnormalityInternal(activeAbnormalities[0]); + } + } + + [Rpc(SendTo.Server)] + private void RemoveAllAbnormalitiesServerRpc() + { + RemoveAllAbnormalities(); + } + + /// + /// 특정 출처의 모든 이상 상태 제거 + /// + public void RemoveAbnormalitiesFromSource(GameObject source) + { + if (!IsServer) + { + var sourceNetId = source != null && source.TryGetComponent(out var netObj) ? netObj.NetworkObjectId : 0UL; + RemoveAbnormalitiesFromSourceServerRpc(sourceNetId); + return; + } + + for (int i = activeAbnormalities.Count - 1; i >= 0; i--) + { + if (activeAbnormalities[i].Source == source) + { + RemoveAbnormalityInternal(activeAbnormalities[i]); + } + } + } + + [Rpc(SendTo.Server)] + private void RemoveAbnormalitiesFromSourceServerRpc(ulong sourceNetworkId) + { + for (int i = activeAbnormalities.Count - 1; i >= 0; i--) + { + var abnormality = activeAbnormalities[i]; + var sourceNetId = abnormality.Source != null && abnormality.Source.TryGetComponent(out var netObj) ? netObj.NetworkObjectId : 0UL; + if (sourceNetId == sourceNetworkId) + { + RemoveAbnormalityInternal(abnormality); + } + } + } + + private void UpdateAbnormalities(float deltaTime) + { + for (int i = activeAbnormalities.Count - 1; i >= 0; i--) + { + var abnormality = activeAbnormalities[i]; + + if (abnormality.CanTriggerPeriodic()) + { + TriggerPeriodicEffect(abnormality); + } + + if (abnormality.Tick(deltaTime)) + { + RemoveAbnormalityInternal(abnormality); + } + } + } + + private void TriggerPeriodicEffect(ActiveAbnormality abnormality) + { + if (networkController == null) return; + + float value = abnormality.Data.periodicValue; + + if (value > 0) + { + networkController.RestoreHealthRpc(value); + Debug.Log($"[Abnormality] Periodic heal: +{value} HP from {abnormality.Data.abnormalityName}"); + } + else if (value < 0) + { + networkController.TakeDamageRpc(-value); + Debug.Log($"[Abnormality] Periodic damage: {-value} HP from {abnormality.Data.abnormalityName}"); + } + } + + private ActiveAbnormality FindExistingAbnormality(AbnormalityData data) + { + return activeAbnormalities.Find(a => a.Data.abnormalityName == data.abnormalityName); + } + + private void ApplyStatModifiers(ActiveAbnormality abnormality) + { + if (characterStats == null) return; + + foreach (var entry in abnormality.Data.statModifiers) + { + var stat = characterStats.GetStat(entry.statType); + if (stat != null) + { + var modifier = new StatModifier(entry.value, entry.modType, abnormality); + abnormality.AppliedModifiers.Add(modifier); + stat.AddModifier(modifier); + } + } + } + + private void RemoveStatModifiers(ActiveAbnormality abnormality) + { + if (characterStats == null) return; + + foreach (StatType statType in Enum.GetValues(typeof(StatType))) + { + var stat = characterStats.GetStat(statType); + stat?.RemoveAllModifiersFromSource(abnormality); + } + + abnormality.AppliedModifiers.Clear(); + } + + private void ApplyControlEffect(AbnormalityData data) + { + switch (data.controlType) + { + case ControlType.Stun: + stunCount++; + break; + + case ControlType.Silence: + silenceCount++; + break; + + case ControlType.Slow: + slowMultiplier = Mathf.Min(slowMultiplier, data.slowMultiplier); + break; + } + } + + private void RemoveControlEffect(AbnormalityData data) + { + switch (data.controlType) + { + case ControlType.Stun: + stunCount = Mathf.Max(0, stunCount - 1); + break; + + case ControlType.Silence: + silenceCount = Mathf.Max(0, silenceCount - 1); + break; + + case ControlType.Slow: + RecalculateSlowMultiplier(); + break; + } + } + + private void RecalculateSlowMultiplier() + { + slowMultiplier = 1f; + + foreach (var abnormality in activeAbnormalities) + { + if (abnormality.Data.controlType == ControlType.Slow) + { + slowMultiplier = Mathf.Min(slowMultiplier, abnormality.Data.slowMultiplier); + } + } + } + + private void SyncAbnormalityAdd(ActiveAbnormality abnormality, GameObject source) + { + var sourceClientId = source != null && source.TryGetComponent(out var netObj) ? netObj.OwnerClientId : 0UL; + + var syncData = new AbnormalitySyncData + { + AbnormalityId = abnormality.Data.GetInstanceID(), + RemainingDuration = abnormality.RemainingDuration, + SourceClientId = sourceClientId + }; + + syncedAbnormalities.Add(syncData); + } + + private void UpdateSyncedAbnormalityDuration(ActiveAbnormality abnormality) + { + for (int i = 0; i < syncedAbnormalities.Count; i++) + { + if (syncedAbnormalities[i].AbnormalityId == abnormality.Data.GetInstanceID()) + { + var syncData = syncedAbnormalities[i]; + syncData.RemainingDuration = abnormality.RemainingDuration; + syncedAbnormalities[i] = syncData; + break; + } + } + } + + private void SyncAbnormalityRemove(ActiveAbnormality abnormality) + { + for (int i = 0; i < syncedAbnormalities.Count; i++) + { + if (syncedAbnormalities[i].AbnormalityId == abnormality.Data.GetInstanceID()) + { + syncedAbnormalities.RemoveAt(i); + break; + } + } + } + + private void OnSyncedAbnormalitiesChanged(NetworkListEvent changeEvent) + { + OnAbnormalitiesChanged?.Invoke(); + } + + private AbnormalityData FindAbnormalityDataById(int instanceId) + { + var allData = Resources.FindObjectsOfTypeAll(); + foreach (var data in allData) + { + if (data.GetInstanceID() == instanceId) + return data; + } + return null; + } + + /// + /// 특정 이름의 이상 상태가 활성화되어 있는지 확인 + /// + public bool HasAbnormality(string name) + { + return activeAbnormalities.Exists(a => a.Data.abnormalityName == name); + } + + /// + /// 특정 데이터의 이상 상태가 활성화되어 있는지 확인 + /// + public bool HasAbnormality(AbnormalityData data) + { + return activeAbnormalities.Exists(a => a.Data.abnormalityName == data.abnormalityName); + } + } +} diff --git a/Assets/Scripts/Abnormalities/AbnormalityManager.cs.meta b/Assets/Scripts/Abnormalities/AbnormalityManager.cs.meta new file mode 100644 index 00000000..d66c5774 --- /dev/null +++ b/Assets/Scripts/Abnormalities/AbnormalityManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 7a766b6ab825c1445a3385079bb32cc5 \ No newline at end of file diff --git a/Assets/Scripts/Abnormalities/ActiveAbnormality.cs b/Assets/Scripts/Abnormalities/ActiveAbnormality.cs new file mode 100644 index 00000000..744b2594 --- /dev/null +++ b/Assets/Scripts/Abnormalities/ActiveAbnormality.cs @@ -0,0 +1,134 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using Colosseum.Stats; + +namespace Colosseum.Abnormalities +{ + /// + /// 런타임 활성 이상 상태 인스턴스 + /// AbnormalityData의 인스턴스로, 실제 적용 중인 이상 상태를 관리합니다. + /// + public class ActiveAbnormality + { + /// + /// 이상 상태 데이터 + /// + public AbnormalityData Data { get; } + + /// + /// 효과를 건 대상 (버프/디버프 시전자) + /// + public GameObject Source { get; } + + /// + /// 남은 지속 시간 + /// + public float RemainingDuration { get; set; } + + /// + /// 적용된 스탯 수정자 목록 + /// + public List AppliedModifiers { get; } + + /// + /// 주기적 효과 타이머 + /// + public float PeriodicTimer { get; set; } + + /// + /// 고유 식별자 (네트워크 동기화용) + /// + public Guid Id { get; } + + /// + /// 활성 이상 상태 생성 + /// + /// 이상 상태 데이터 + /// 효과 시전자 + public ActiveAbnormality(AbnormalityData data, GameObject source) + { + Data = data; + Source = source; + RemainingDuration = data.duration; + PeriodicTimer = 0f; + Id = Guid.NewGuid(); + AppliedModifiers = new List(); + } + + /// + /// 지속 시간 갱신 + /// + public void RefreshDuration() + { + RemainingDuration = Data.duration; + PeriodicTimer = 0f; + } + + /// + /// 시간 경과 처리 + /// + /// 경과 시간 + /// 효과가 만료되었으면 true + public bool Tick(float deltaTime) + { + // 영구 효과는 시간 감소 없음 + if (Data.IsPermanent) + return false; + + RemainingDuration -= deltaTime; + + // 주기적 효과 타이머 업데이트 + if (Data.HasPeriodicEffect) + { + PeriodicTimer += deltaTime; + } + + return RemainingDuration <= 0f; + } + + /// + /// 주기적 효과 발동 가능 여부 확인 + /// + /// 발동 가능하면 true + public bool CanTriggerPeriodic() + { + if (!Data.HasPeriodicEffect) + return false; + + if (PeriodicTimer >= Data.periodicInterval) + { + PeriodicTimer -= Data.periodicInterval; + return true; + } + + return false; + } + + /// + /// 진행률 (0~1) + /// + public float Progress + { + get + { + if (Data.IsPermanent) + return 1f; + return Mathf.Clamp01(1f - (RemainingDuration / Data.duration)); + } + } + + /// + /// 남은 시간 비율 (1~0, UI 표시용) + /// + public float RemainingRatio + { + get + { + if (Data.IsPermanent) + return 1f; + return Mathf.Clamp01(RemainingDuration / Data.duration); + } + } + } +} diff --git a/Assets/Scripts/Abnormalities/ActiveAbnormality.cs.meta b/Assets/Scripts/Abnormalities/ActiveAbnormality.cs.meta new file mode 100644 index 00000000..bdc8a0fc --- /dev/null +++ b/Assets/Scripts/Abnormalities/ActiveAbnormality.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: b90fb3ef8cb13be4383eb397857cfa2b \ No newline at end of file diff --git a/Assets/Scripts/Skills/Effects/AbnormalityEffect.cs b/Assets/Scripts/Skills/Effects/AbnormalityEffect.cs new file mode 100644 index 00000000..ad0082c1 --- /dev/null +++ b/Assets/Scripts/Skills/Effects/AbnormalityEffect.cs @@ -0,0 +1,46 @@ +using UnityEngine; +using Colosseum.Abnormalities; + +namespace Colosseum.Skills.Effects +{ + /// + /// 이상 상태 효과 + /// AbnormalityManager를 통해 대상에게 이상 상태를 적용합니다. + /// + [CreateAssetMenu(fileName = "AbnormalityEffect", menuName = "Colosseum/Skills/Effects/Abnormality")] + public class AbnormalityEffect : SkillEffect + { + [Header("Abnormality")] + [Tooltip("적용할 이상 상태 데이터")] + [SerializeField] private AbnormalityData abnormalityData; + + protected override void ApplyEffect(GameObject caster, GameObject target) + { + if (target == null) return; + + if (abnormalityData == null) + { + Debug.LogWarning($"[AbnormalityEffect] AbnormalityData is not assigned"); + return; + } + + var abnormalityManager = target.GetComponent(); + if (abnormalityManager == null) + { + Debug.LogWarning($"[AbnormalityEffect] Target {target.name} has no AbnormalityManager"); + return; + } + + abnormalityManager.ApplyAbnormality(abnormalityData, caster); + Debug.Log($"[AbnormalityEffect] Applied {abnormalityData.abnormalityName} to {target.name} from {caster?.name ?? "unknown"}"); + } + + /// + /// 이상 상태 데이터 설정 (런타임용) + /// + public void SetAbnormalityData(AbnormalityData data) + { + abnormalityData = data; + } + } +} diff --git a/Assets/Scripts/Skills/Effects/AbnormalityEffect.cs.meta b/Assets/Scripts/Skills/Effects/AbnormalityEffect.cs.meta new file mode 100644 index 00000000..ad528061 --- /dev/null +++ b/Assets/Scripts/Skills/Effects/AbnormalityEffect.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: bf750718c64c4bd48af905d2927351de \ No newline at end of file diff --git a/Assets/Scripts/Skills/Effects/BuffEffect.cs b/Assets/Scripts/Skills/Effects/BuffEffect.cs deleted file mode 100644 index 4e3c265b..00000000 --- a/Assets/Scripts/Skills/Effects/BuffEffect.cs +++ /dev/null @@ -1,32 +0,0 @@ -using UnityEngine; - -namespace Colosseum.Skills.Effects -{ - /// - /// 버프/디버프 효과 - /// - [CreateAssetMenu(fileName = "BuffEffect", menuName = "Colosseum/Skills/Effects/Buff")] - public class BuffEffect : SkillEffect - { - [Header("Buff Settings")] - [SerializeField] private string buffName = "Buff"; - [Min(0f)] [SerializeField] private float duration = 5f; - - [Header("Stat Modifiers")] - [Range(0f, 10f)] [SerializeField] private float moveSpeedMultiplier = 1f; - [Range(0f, 10f)] [SerializeField] private float attackPowerMultiplier = 1f; - [Range(0f, 10f)] [SerializeField] private float defenseMultiplier = 1f; - - protected override void ApplyEffect(GameObject caster, GameObject target) - { - if (target == null) return; - - // TODO: 실제 버프 시스템 연동 - // var buffSystem = target.GetComponent(); - // buffSystem?.ApplyBuff(new BuffData(buffName, duration, moveSpeedMultiplier, attackPowerMultiplier, defenseMultiplier)); - - Debug.Log($"[Buff] {buffName} on {target.name} for {duration}s " + - $"(Speed: {moveSpeedMultiplier}x, ATK: {attackPowerMultiplier}x, DEF: {defenseMultiplier}x)"); - } - } -} diff --git a/Assets/Scripts/Skills/Effects/BuffEffect.cs.meta b/Assets/Scripts/Skills/Effects/BuffEffect.cs.meta deleted file mode 100644 index 49a2451d..00000000 --- a/Assets/Scripts/Skills/Effects/BuffEffect.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: 32bab3b586da0d7469f63e03f18ee29f \ No newline at end of file diff --git a/Assets/Scripts/StatusEffects.meta b/Assets/Scripts/StatusEffects.meta new file mode 100644 index 00000000..75200698 --- /dev/null +++ b/Assets/Scripts/StatusEffects.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 148d81d9974baed45b212857d96aed37 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/UI/AbnormalityListUI.cs b/Assets/Scripts/UI/AbnormalityListUI.cs new file mode 100644 index 00000000..ca3a3a12 --- /dev/null +++ b/Assets/Scripts/UI/AbnormalityListUI.cs @@ -0,0 +1,279 @@ +using System.Collections.Generic; +using UnityEngine; +using Colosseum.Abnormalities; + +namespace Colosseum.UI +{ + /// + /// 이상 상태 목록 UI 관리자 + /// 버프/디버프 목록을 표시하고 관리합니다. + /// + public class AbnormalityListUI : MonoBehaviour + { + [Header("Containers")] + [Tooltip("버프 컨테이너")] + [SerializeField] private Transform buffContainer; + + [Tooltip("디버프 컨테이너")] + [SerializeField] private Transform debuffContainer; + + [Header("Prefab")] + [Tooltip("이상 상태 슬롯 프리팹")] + [SerializeField] private AbnormalitySlotUI slotPrefab; + + [Header("Settings")] + [Tooltip("최대 표시 개수")] + [SerializeField] private int maxSlots = 10; + + [Tooltip("자동으로 플레이어 추적")] + [SerializeField] private bool autoFindPlayer = true; + + // 추적 중인 AbnormalityManager + private AbnormalityManager targetManager; + + // 생성된 슬롯 풀 + private readonly List slotPool = new List(); + + // 현재 활성화된 슬롯 목록 + private readonly List activeSlots = new List(); + + // 이전 프레임의 효과 수 (변경 감지용) + private int lastAbnormalityCount = -1; + + private void Start() + { + if (autoFindPlayer) + { + // 로컬 플레이어 찾기 + FindLocalPlayer(); + } + + // 슬롯 풀 초기화 + InitializeSlotPool(); + } + + private void OnDestroy() + { + // 이벤트 구독 해제 + if (targetManager != null) + { + targetManager.OnAbnormalityAdded -= OnAbnormalityAdded; + targetManager.OnAbnormalityRemoved -= OnAbnormalityRemoved; + targetManager.OnAbnormalitiesChanged -= OnAbnormalitiesChanged; + } + } + + private void Update() + { + // 주기적으로 UI 갱신 (성능 최적화를 위해 매 프레임이 아닌 일정 간격으로) + if (Time.frameCount % 10 == 0) // 10프레임마다 한 번 + { + RefreshUI(); + } + } + + /// + /// 로컬 플레이어 찾기 + /// + private void FindLocalPlayer() + { + var playerObjects = FindObjectsByType(FindObjectsSortMode.None); + + foreach (var manager in playerObjects) + { + // 네트워크 오브젝트인 경우 로컬 플레이어 확인 + if (manager.TryGetComponent(out var netObj) && netObj.IsOwner) + { + SetTarget(manager); + return; + } + } + + // 네트워크 오브젝트가 없거나 로컬 플레이어를 찾지 못한 경우 + // 첫 번째 플레이어 사용 (싱글플레이어용) + if (playerObjects.Length > 0) + { + SetTarget(playerObjects[0]); + } + } + + /// + /// 추적 대상 설정 + /// + /// 추적할 AbnormalityManager + public void SetTarget(AbnormalityManager manager) + { + // 기존 구독 해제 + if (targetManager != null) + { + targetManager.OnAbnormalityAdded -= OnAbnormalityAdded; + targetManager.OnAbnormalityRemoved -= OnAbnormalityRemoved; + targetManager.OnAbnormalitiesChanged -= OnAbnormalitiesChanged; + } + + targetManager = manager; + + // 새로운 대상 구독 + if (targetManager != null) + { + targetManager.OnAbnormalityAdded += OnAbnormalityAdded; + targetManager.OnAbnormalityRemoved += OnAbnormalityRemoved; + targetManager.OnAbnormalitiesChanged += OnAbnormalitiesChanged; + } + + // 즉시 UI 갱신 + ForceRefreshUI(); + } + + /// + /// 슬롯 풀 초기화 + /// + private void InitializeSlotPool() + { + if (slotPrefab == null) + { + Debug.LogWarning("[AbnormalityListUI] Slot prefab is not assigned"); + return; + } + + // 필요한 만큼 슬롯 미리 생성 + for (int i = 0; i < maxSlots; i++) + { + var slot = CreateSlot(); + slot.gameObject.SetActive(false); + slotPool.Add(slot); + } + } + + /// + /// 새 슬롯 생성 + /// + private AbnormalitySlotUI CreateSlot() + { + var go = Instantiate(slotPrefab.gameObject, transform); + return go.GetComponent(); + } + + /// + /// 슬롯 가져오기 (풀에서 또는 새로 생성) + /// + private AbnormalitySlotUI GetSlot() + { + // 풀에서 비활성화된 슬롯 찾기 + foreach (var slot in slotPool) + { + if (!slot.gameObject.activeSelf) + { + return slot; + } + } + + // 풀에 없으면 새로 생성 + if (slotPool.Count < maxSlots) + { + var newSlot = CreateSlot(); + slotPool.Add(newSlot); + return newSlot; + } + + return null; + } + + /// + /// 슬롯 반환 (비활성화) + /// + private void ReturnSlot(AbnormalitySlotUI slot) + { + slot.gameObject.SetActive(false); + activeSlots.Remove(slot); + } + + /// + /// 이상 상태 추가 시 호출 + /// + private void OnAbnormalityAdded(ActiveAbnormality abnormality) + { + ForceRefreshUI(); + } + + /// + /// 이상 상태 제거 시 호출 + /// + private void OnAbnormalityRemoved(ActiveAbnormality abnormality) + { + ForceRefreshUI(); + } + + /// + /// 이상 상태 변경 시 호출 + /// + private void OnAbnormalitiesChanged() + { + ForceRefreshUI(); + } + + /// + /// UI 강제 갱신 + /// + public void ForceRefreshUI() + { + if (targetManager == null) return; + + // 모든 슬롯 반환 + foreach (var slot in activeSlots.ToArray()) + { + ReturnSlot(slot); + } + + activeSlots.Clear(); + + // 활성화된 이상 상태 표시 + var abnormalities = targetManager.ActiveAbnormalities; + foreach (var abnormality in abnormalities) + { + var slot = GetSlot(); + if (slot == null) continue; + + // 버프/디버프에 따라 적절한 컨테이너에 배치 + Transform container = abnormality.Data.isDebuff ? debuffContainer : buffContainer; + if (container == null) container = transform; + + slot.transform.SetParent(container, false); + slot.Initialize(abnormality); + slot.gameObject.SetActive(true); + activeSlots.Add(slot); + } + + lastAbnormalityCount = abnormalities.Count; + } + + /// + /// UI 주기적 갱신 (변경 감지 시에만) + /// + private void RefreshUI() + { + if (targetManager == null) return; + + int currentCount = targetManager.ActiveAbnormalities.Count; + + // 이상 상태 수가 변경되었으면 갱신 + if (currentCount != lastAbnormalityCount) + { + ForceRefreshUI(); + } + } + + /// + /// 모든 슬롯 숨기기 + /// + public void HideAll() + { + foreach (var slot in activeSlots.ToArray()) + { + ReturnSlot(slot); + } + + activeSlots.Clear(); + } + } +} diff --git a/Assets/Scripts/UI/AbnormalityListUI.cs.meta b/Assets/Scripts/UI/AbnormalityListUI.cs.meta new file mode 100644 index 00000000..5b6f2b2d --- /dev/null +++ b/Assets/Scripts/UI/AbnormalityListUI.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 15447f4a4d271354fb52bbdf1a526c6e \ No newline at end of file diff --git a/Assets/Scripts/UI/AbnormalitySlotUI.cs b/Assets/Scripts/UI/AbnormalitySlotUI.cs new file mode 100644 index 00000000..34225359 --- /dev/null +++ b/Assets/Scripts/UI/AbnormalitySlotUI.cs @@ -0,0 +1,182 @@ +using UnityEngine; +using UnityEngine.UI; +using TMPro; +using Colosseum.Abnormalities; + +namespace Colosseum.UI +{ + /// + /// 개별 이상 상태 UI 슬롯 + /// 버프/디버프 아이콘, 지속 시간 등을 표시합니다. + /// + public class AbnormalitySlotUI : MonoBehaviour + { + [Header("UI References")] + [Tooltip("이상 상태 아이콘")] + [SerializeField] private Image iconImage; + + [Tooltip("지속 시간 채우기 이미지 (시계 방향)")] + [SerializeField] private Image durationFill; + + [Tooltip("남은 시간 텍스트")] + [SerializeField] private TMP_Text durationText; + + [Tooltip("효과 이름 텍스트")] + [SerializeField] private TMP_Text effectNameText; + + [Tooltip("배경 이미지 (버프/디버프 구분용)")] + [SerializeField] private Image backgroundImage; + + [Header("Colors")] + [Tooltip("버프 배경 색상")] + [SerializeField] private Color buffColor = new Color(0.2f, 0.6f, 0.2f, 0.8f); + + [Tooltip("디버프 배경 색상")] + [SerializeField] private Color debuffColor = new Color(0.6f, 0.2f, 0.2f, 0.8f); + + private ActiveAbnormality trackedAbnormality; + + /// + /// 추적 중인 활성 이상 상태 + /// + public ActiveAbnormality TrackedAbnormality => trackedAbnormality; + + /// + /// UI 초기화 + /// + /// 표시할 활성 이상 상태 + public void Initialize(ActiveAbnormality abnormality) + { + trackedAbnormality = abnormality; + + if (abnormality?.Data == null) + { + Debug.LogWarning("[AbnormalitySlotUI] Initialize called with null abnormality or data"); + return; + } + + // 아이콘 설정 + if (iconImage != null) + { + iconImage.sprite = abnormality.Data.icon; + iconImage.enabled = abnormality.Data.icon != null; + } + + // 이름 설정 + if (effectNameText != null) + { + effectNameText.text = abnormality.Data.abnormalityName; + } + + // 배경 색상 설정 (버프/디버프 구분) + if (backgroundImage != null) + { + backgroundImage.color = abnormality.Data.isDebuff ? debuffColor : buffColor; + } + + // 초기 상태 업데이트 + UpdateDisplay(abnormality.RemainingDuration, abnormality.Data.duration); + } + + /// + /// 화면 표시 업데이트 + /// + /// 남은 시간 + /// 전체 시간 + public void UpdateDisplay(float remainingDuration, float totalDuration) + { + // 지속 시간 채우기 업데이트 + if (durationFill != null) + { + if (totalDuration > 0f) + { + float fillAmount = Mathf.Clamp01(remainingDuration / totalDuration); + durationFill.fillAmount = fillAmount; + durationFill.enabled = true; + } + else + { + // 영구 효과 + durationFill.fillAmount = 1f; + } + } + + // 남은 시간 텍스트 업데이트 + if (durationText != null) + { + if (totalDuration > 0f) + { + if (remainingDuration >= 60f) + { + durationText.text = $"{remainingDuration / 60f:F0}m"; + } + else if (remainingDuration >= 1f) + { + durationText.text = $"{remainingDuration:F0}s"; + } + else + { + durationText.text = $"{remainingDuration:F1}s"; + } + } + else + { + // 영구 효과 + durationText.text = "∞"; + } + } + } + + /// + /// 프레임마다 호출하여 추적 중인 효과 업데이트 + /// + private void Update() + { + if (trackedAbnormality == null) + { + gameObject.SetActive(false); + return; + } + + UpdateDisplay(trackedAbnormality.RemainingDuration, trackedAbnormality.Data.duration); + } + + /// + /// 툴팁 표시용 정보 반환 + /// + public string GetTooltipText() + { + if (trackedAbnormality?.Data == null) return string.Empty; + + var data = trackedAbnormality.Data; + string tooltip = $"{data.abnormalityName}\n"; + + if (!data.IsPermanent) + { + tooltip += $"지속 시간: {trackedAbnormality.RemainingDuration:F1}초\n"; + } + else + { + tooltip += "영구 효과\n"; + } + + if (data.HasPeriodicEffect) + { + tooltip += $"주기적 효과: {data.periodicValue:+0}/ {data.periodicInterval}초\n"; + } + + if (data.HasControlEffect) + { + tooltip += $"제어 효과: {data.controlType}\n"; + } + + foreach (var mod in data.statModifiers) + { + string sign = mod.value >= 0 ? "+" : ""; + tooltip += $"{mod.statType}: {sign}{mod.value}\n"; + } + + return tooltip; + } + } +} diff --git a/Assets/Scripts/UI/AbnormalitySlotUI.cs.meta b/Assets/Scripts/UI/AbnormalitySlotUI.cs.meta new file mode 100644 index 00000000..b9910edd --- /dev/null +++ b/Assets/Scripts/UI/AbnormalitySlotUI.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 287a45a81e69cbf48845f88759cf7eb4 \ No newline at end of file diff --git a/Assets/Scripts/UI/AbnormalitySystemTest.cs b/Assets/Scripts/UI/AbnormalitySystemTest.cs new file mode 100644 index 00000000..3c0a4655 --- /dev/null +++ b/Assets/Scripts/UI/AbnormalitySystemTest.cs @@ -0,0 +1,116 @@ +using UnityEngine; +using Colosseum.Abnormalities; + +namespace Colosseum.UI +{ + /// + /// 이상 상태 시스템 테스트 스크립트 + /// Q 키: 버프 적용, E 키: 디버프 적용 + /// 로그를 통해 OnEffect 이벤트 호출 및 이상 상태 적용 과정을 추적합니다. + /// + public class AbnormalitySystemTest : MonoBehaviour + { + private AbnormalityManager abnormalityManager; + private AbnormalityData testBuff; + private AbnormalityData testDebuff; + + private float testTimer; + + void Start() + { + // 플레이어에서 AbnormalityManager 찾기 + abnormalityManager = GetComponent(); + if (abnormalityManager == null) + { + Debug.LogError("[AbnormalitySystemTest] AbnormalityManager not found on player!"); + return; + } + + // 테스트용 이상 상태 데이터 생성 (에셋 생성) + testBuff = ScriptableObject.CreateInstance(); + testBuff.abnormalityName = "Test Buff"; + testBuff.duration = 5f; + testBuff.isDebuff = false; + + testDebuff = ScriptableObject.CreateInstance(); + testDebuff.abnormalityName = "Test Debuff"; + testDebuff.duration = 5f; + testDebuff.isDebuff = true; + + // 이벤트 구독 + abnormalityManager.OnAbnormalityAdded += OnAbnormalityAdded; + abnormalityManager.OnAbnormalityRemoved += OnAbnormalityRemoved; + + Debug.Log("=== Abnormality System Test Started ==="); + Debug.Log("Press Q to apply buff, Press E to apply debuff"); + Debug.Log($"Initial Active Abnormalities Count: {abnormalityManager.ActiveAbnormalities.Count}"); + } + + void Update() + { + testTimer += Time.deltaTime; + + // Q 키로 버프 적용 (3초마다 1회만) + if (Input.GetKeyDown(KeyCode.Q) && testTimer >= 3f) + { + testTimer = 0f; + ApplyTestBuff(); + } + + // E 키로 디버프 적용 (3초마다 1회만) + if (Input.GetKeyDown(KeyCode.E) && testTimer >= 3f) + { + testTimer = 0f; + ApplyTestDebuff(); + } + } + + private void ApplyTestBuff() + { + if (testBuff == null || abnormalityManager == null) + { + Debug.LogWarning("[AbnormalitySystemTest] Cannot apply buff - data or manager is null"); + return; + } + + Debug.Log($"[AbnormalitySystemTest] >>> Applying BUFF: {testBuff.abnormalityName} to {gameObject.name}"); + abnormalityManager.ApplyAbnormality(testBuff, gameObject); + } + + private void ApplyTestDebuff() + { + if (testDebuff == null || abnormalityManager == null) + { + Debug.LogWarning("[AbnormalitySystemTest] Cannot apply debuff - data or manager is null"); + return; + } + + Debug.Log($"[AbnormalitySystemTest] >>> Applying DEBUFF: {testDebuff.abnormalityName} to {gameObject.name}"); + abnormalityManager.ApplyAbnormality(testDebuff, gameObject); + } + + private void OnAbnormalityAdded(ActiveAbnormality abnormality) + { + Debug.Log($"[AbnormalitySystemTest] <<< ABNORMALITY ADDED: {abnormality.Data.abnormalityName} | isDebuff: {abnormality.Data.isDebuff} | Duration: {abnormality.Data.duration}s | Remaining: {abnormality.RemainingDuration:F1}s"); + } + + private void OnAbnormalityRemoved(ActiveAbnormality abnormality) + { + Debug.Log($"[AbnormalitySystemTest] <<< ABNORMALITY REMOVED: {abnormality.Data.abnormalityName}"); + } + + void OnDestroy() + { + // 이벤트 구독 해제 + if (abnormalityManager != null) + { + abnormalityManager.OnAbnormalityAdded -= OnAbnormalityAdded; + abnormalityManager.OnAbnormalityRemoved -= OnAbnormalityRemoved; + } + + // 정리 + if (testBuff != null) Destroy(testBuff); + if (testDebuff != null) Destroy(testDebuff); + } + } +} diff --git a/Assets/Scripts/UI/AbnormalitySystemTest.cs.meta b/Assets/Scripts/UI/AbnormalitySystemTest.cs.meta new file mode 100644 index 00000000..d99bf342 --- /dev/null +++ b/Assets/Scripts/UI/AbnormalitySystemTest.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: a1b2c3d4e5f6a7b8c9a0d1e5e3 diff --git a/Assets/Skills/Effects/Melee_Slash_1.asset b/Assets/Skills/Effects/Melee_Slash_1.asset new file mode 100644 index 00000000..d1844233 --- /dev/null +++ b/Assets/Skills/Effects/Melee_Slash_1.asset @@ -0,0 +1,26 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: bf750718c64c4bd48af905d2927351de, type: 3} + m_Name: Melee_Slash_1 + m_EditorClassIdentifier: Colosseum.Game::Colosseum.Skills.Effects.AbnormalityEffect + targetType: 0 + targetTeam: 0 + areaCenter: 0 + areaShape: 0 + targetLayers: + serializedVersion: 2 + m_Bits: 0 + areaRadius: 3 + fanOriginDistance: 0 + fanRadius: 3 + fanHalfAngle: 45 + abnormalityData: {fileID: 11400000, guid: da5a38e4e2c383940a34d9d8080fbbe0, type: 2} diff --git a/Assets/Skills/Effects/Melee_Slash_1.asset.meta b/Assets/Skills/Effects/Melee_Slash_1.asset.meta new file mode 100644 index 00000000..596f0947 --- /dev/null +++ b/Assets/Skills/Effects/Melee_Slash_1.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 75bac55a016a0da46899806f58b76ce3 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Skills/Effects/Melee_Slash_2.asset b/Assets/Skills/Effects/Melee_Slash_2.asset new file mode 100644 index 00000000..a3cc7c03 --- /dev/null +++ b/Assets/Skills/Effects/Melee_Slash_2.asset @@ -0,0 +1,26 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: bf750718c64c4bd48af905d2927351de, type: 3} + m_Name: Melee_Slash_2 + m_EditorClassIdentifier: Colosseum.Game::Colosseum.Skills.Effects.AbnormalityEffect + targetType: 0 + targetTeam: 0 + areaCenter: 0 + areaShape: 0 + targetLayers: + serializedVersion: 2 + m_Bits: 0 + areaRadius: 3 + fanOriginDistance: 0 + fanRadius: 3 + fanHalfAngle: 45 + abnormalityData: {fileID: 11400000, guid: c4abb0f89779f294ab99562e085e8f3b, type: 2} diff --git a/Assets/Skills/Effects/Melee_Slash_2.asset.meta b/Assets/Skills/Effects/Melee_Slash_2.asset.meta new file mode 100644 index 00000000..69e616ee --- /dev/null +++ b/Assets/Skills/Effects/Melee_Slash_2.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0e496b26a1dbf40488ce54cb4fe9c27b +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: