feat: 젬 분류 사양과 장착 UI 반영
- 옵시디언 기준의 역할/발동 타입 분류를 스킬·젬 데이터와 장착 검증 로직에 반영 - 젬 보관 UI와 퀵슬롯 표시를 새 분류 및 실제 마나/쿨타임 계산 기준으로 갱신 - 테스트 스킬/젬 자산을 에디터 메뉴로 동기화하고 Unity 컴파일 및 플레이 검증 완료
This commit is contained in:
@@ -17,7 +17,9 @@ MonoBehaviour:
|
||||
\uBA74\uC5ED\uC744 \uBD80\uC5EC\uD558\uB294 \uD14C\uC2A4\uD2B8\uC6A9 \uBC29\uC5B4
|
||||
\uC82C"
|
||||
icon: {fileID: 0}
|
||||
category: 3
|
||||
category: 2
|
||||
allowedSkillRoles: 7
|
||||
allowedSkillActivationTypes: 3
|
||||
allowedSkillTypes: 63
|
||||
incompatibleCategories:
|
||||
incompatibleGems: []
|
||||
|
||||
@@ -17,6 +17,8 @@ MonoBehaviour:
|
||||
\uD14C\uC2A4\uD2B8\uC6A9 \uACF5\uACA9 \uC82C"
|
||||
icon: {fileID: 0}
|
||||
category: 1
|
||||
allowedSkillRoles: 1
|
||||
allowedSkillActivationTypes: 1
|
||||
allowedSkillTypes: 1
|
||||
incompatibleCategories:
|
||||
incompatibleGems: []
|
||||
|
||||
@@ -16,7 +16,9 @@ MonoBehaviour:
|
||||
description: "\uACE0\uC704\uB825 \uAE30\uC220\uC5D0 \uC704\uD611 \uC120\uC810 \uAE30\uB2A5\uC744
|
||||
\uC5B9\uB294 \uD14C\uC2A4\uD2B8\uC6A9 \uC82C"
|
||||
icon: {fileID: 0}
|
||||
category: 2
|
||||
category: 4
|
||||
allowedSkillRoles: 3
|
||||
allowedSkillActivationTypes: 1
|
||||
allowedSkillTypes: 1
|
||||
incompatibleCategories:
|
||||
incompatibleGems: []
|
||||
|
||||
@@ -16,7 +16,9 @@ MonoBehaviour:
|
||||
description: "\uACE0\uC704\uB825 \uAE30\uC220\uC5D0 \uBCF4\uD638\uB9C9 \uBCF4\uC870\uB97C
|
||||
\uC5B9\uB294 \uD14C\uC2A4\uD2B8\uC6A9 \uC82C"
|
||||
icon: {fileID: 0}
|
||||
category: 4
|
||||
category: 2
|
||||
allowedSkillRoles: 7
|
||||
allowedSkillActivationTypes: 1
|
||||
allowedSkillTypes: 1
|
||||
incompatibleCategories:
|
||||
incompatibleGems: []
|
||||
|
||||
@@ -16,7 +16,9 @@ MonoBehaviour:
|
||||
description: "\uC2A4\uD0AC \uC801\uC911 \uB300\uC0C1\uC5D0\uAC8C \uD14C\uC2A4\uD2B8
|
||||
\uB514\uBC84\uD504\uB97C \uBD80\uC5EC\uD558\uB294 \uC81C\uC5B4 \uC82C"
|
||||
icon: {fileID: 0}
|
||||
category: 5
|
||||
category: 4
|
||||
allowedSkillRoles: 7
|
||||
allowedSkillActivationTypes: 1
|
||||
allowedSkillTypes: 63
|
||||
incompatibleCategories:
|
||||
incompatibleGems: []
|
||||
|
||||
@@ -16,7 +16,9 @@ MonoBehaviour:
|
||||
description: "\uBD99\uC740 \uC2A4\uD0AC\uC744 \uD55C \uBC88 \uB354 \uBC18\uBCF5
|
||||
\uC2DC\uC804\uD558\uB294 \uD14C\uC2A4\uD2B8\uC6A9 \uC82C"
|
||||
icon: {fileID: 0}
|
||||
category: 6
|
||||
category: 4
|
||||
allowedSkillRoles: 1
|
||||
allowedSkillActivationTypes: 1
|
||||
allowedSkillTypes: 1
|
||||
incompatibleCategories:
|
||||
incompatibleGems: []
|
||||
|
||||
@@ -17,6 +17,8 @@ MonoBehaviour:
|
||||
\uD14C\uC2A4\uD2B8\uC6A9 \uACF5\uACA9 \uC82C"
|
||||
icon: {fileID: 0}
|
||||
category: 1
|
||||
allowedSkillRoles: 1
|
||||
allowedSkillActivationTypes: 1
|
||||
allowedSkillTypes: 1
|
||||
incompatibleCategories:
|
||||
incompatibleGems: []
|
||||
|
||||
@@ -17,6 +17,8 @@ MonoBehaviour:
|
||||
\uD14C\uC2A4\uD2B8\uC6A9 \uACF5\uACA9 \uC82C"
|
||||
icon: {fileID: 0}
|
||||
category: 1
|
||||
allowedSkillRoles: 1
|
||||
allowedSkillActivationTypes: 1
|
||||
allowedSkillTypes: 1
|
||||
incompatibleCategories:
|
||||
incompatibleGems: []
|
||||
|
||||
@@ -17,6 +17,8 @@ MonoBehaviour:
|
||||
\uAC15\uD654\uD558\uB294 \uD14C\uC2A4\uD2B8\uC6A9 \uC82C"
|
||||
icon: {fileID: 0}
|
||||
category: 1
|
||||
allowedSkillRoles: 1
|
||||
allowedSkillActivationTypes: 1
|
||||
allowedSkillTypes: 1
|
||||
incompatibleCategories:
|
||||
incompatibleGems: []
|
||||
|
||||
@@ -16,6 +16,8 @@ MonoBehaviour:
|
||||
description: "\uC8FC\uBCC0 \uC544\uAD70\uACFC \uC790\uC2E0\uC758 \uCCB4\uB825\uC744
|
||||
\uD568\uAED8 \uD68C\uBCF5\uD55C\uB2E4."
|
||||
icon: {fileID: 0}
|
||||
skillRole: 4
|
||||
activationType: 1
|
||||
baseTypes: 4
|
||||
skillClip: {fileID: -8689311932429934276, guid: 836c26605050496b9fd07dd456e6ea82, type: 3}
|
||||
endClip: {fileID: 0}
|
||||
|
||||
@@ -15,7 +15,9 @@ MonoBehaviour:
|
||||
skillName: "\uAD6C\uB974\uAE30"
|
||||
description:
|
||||
icon: {fileID: 21300000, guid: eafcc94eae3865944b93e64c4e281aa0, type: 3}
|
||||
baseTypes: 16
|
||||
skillRole: 2
|
||||
activationType: 1
|
||||
baseTypes: 2
|
||||
skillClip: {fileID: -14460799136228694, guid: d6d51384d6dd17a419c1d8e2a1c0c875, type: 3}
|
||||
endClip: {fileID: 0}
|
||||
animationSpeed: 1
|
||||
|
||||
@@ -17,7 +17,9 @@ MonoBehaviour:
|
||||
\uB192\uC774\uACE0 \uC9E7\uC740 \uC2DC\uAC04 \uB3D9\uC548 \uC704\uD611 \uC0DD\uC131\uB7C9\uC744
|
||||
\uC99D\uAC00\uC2DC\uD0A8\uB2E4."
|
||||
icon: {fileID: 0}
|
||||
baseTypes: 40
|
||||
skillRole: 2
|
||||
activationType: 1
|
||||
baseTypes: 2
|
||||
skillClip: {fileID: -4662563244894722208, guid: de4d0153716747cd9fc90c60f5efb1ae, type: 3}
|
||||
endClip: {fileID: 0}
|
||||
animationSpeed: 1
|
||||
|
||||
@@ -15,7 +15,9 @@ MonoBehaviour:
|
||||
skillName: "\uB3CC\uC9C4"
|
||||
description:
|
||||
icon: {fileID: 0}
|
||||
baseTypes: 16
|
||||
skillRole: 1
|
||||
activationType: 1
|
||||
baseTypes: 1
|
||||
skillClip: {fileID: 0}
|
||||
endClip: {fileID: 0}
|
||||
animationSpeed: 1
|
||||
|
||||
@@ -16,6 +16,8 @@ MonoBehaviour:
|
||||
description: "\uC9E7\uC740 \uC2DC\uAC04 \uB3D9\uC548 \uBC1B\uB294 \uD53C\uD574\uB97C
|
||||
\uC904\uC774\uACE0 \uC704\uD611 \uC0DD\uC131\uB7C9\uC744 \uB192\uC778\uB2E4."
|
||||
icon: {fileID: 0}
|
||||
skillRole: 2
|
||||
activationType: 2
|
||||
baseTypes: 2
|
||||
skillClip: {fileID: -592826573199220879, guid: 52e14756abda46499f4739d811043b3d, type: 3}
|
||||
endClip: {fileID: 0}
|
||||
|
||||
@@ -16,7 +16,9 @@ MonoBehaviour:
|
||||
description: "\uC8FC\uBCC0 \uC544\uAD70\uACFC \uC790\uC2E0\uC5D0\uAC8C \uD53C\uD574\uB97C
|
||||
\uD761\uC218\uD558\uB294 \uBCF4\uD638\uB9C9\uC744 \uBD80\uC5EC\uD55C\uB2E4."
|
||||
icon: {fileID: 0}
|
||||
baseTypes: 6
|
||||
skillRole: 4
|
||||
activationType: 1
|
||||
baseTypes: 4
|
||||
skillClip: {fileID: -1185230921767219677, guid: f2d90cfa60b04630af1dde00f4d29320, type: 3}
|
||||
endClip: {fileID: 0}
|
||||
animationSpeed: 1
|
||||
|
||||
@@ -16,7 +16,9 @@ MonoBehaviour:
|
||||
description: "\uC9E7\uC740 \uC2DC\uAC04 \uB3D9\uC548 \uBB34\uC801\uC774 \uB418\uBA70
|
||||
\uC704\uD611 \uC0DD\uC131\uB7C9\uC774 \uC57D\uAC04 \uC99D\uAC00\uD55C\uB2E4."
|
||||
icon: {fileID: 0}
|
||||
baseTypes: 6
|
||||
skillRole: 2
|
||||
activationType: 2
|
||||
baseTypes: 2
|
||||
skillClip: {fileID: -7313196749698736815, guid: 95764ba490b24918b73fc1553e34dc1e, type: 3}
|
||||
endClip: {fileID: 0}
|
||||
animationSpeed: 1
|
||||
|
||||
@@ -15,6 +15,8 @@ MonoBehaviour:
|
||||
skillName: "\uCE58\uC720"
|
||||
description: "\uC790\uC2E0\uC758 \uCCB4\uB825\uC744 \uBE60\uB974\uAC8C \uD68C\uBCF5\uD55C\uB2E4."
|
||||
icon: {fileID: 0}
|
||||
skillRole: 4
|
||||
activationType: 1
|
||||
baseTypes: 4
|
||||
skillClip: {fileID: -8689311932429934276, guid: 4450ee0d92144ade9f63dd601432d3bf, type: 3}
|
||||
endClip: {fileID: 0}
|
||||
|
||||
@@ -12,6 +12,7 @@ GameObject:
|
||||
- component: {fileID: 9156608660900377980}
|
||||
- component: {fileID: 3790117282943784127}
|
||||
- component: {fileID: 7777120333480524073}
|
||||
- component: {fileID: 110599025774604826}
|
||||
m_Layer: 5
|
||||
m_Name: UI_ActionBar
|
||||
m_TagString: Untagged
|
||||
@@ -115,6 +116,50 @@ MonoBehaviour:
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
--- !u!114 &110599025774604826
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 628750841697537993}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: ca98554fbe3918040881b21c34fbb373, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Colosseum.Game::Colosseum.UI.SkillGemInventoryUI
|
||||
toggleKey: 21
|
||||
toggleButtonLabel: "\uC82C"
|
||||
toggleButtonAnchoredPosition: {x: -48, y: 164}
|
||||
ownedGemEntries:
|
||||
- gem: {fileID: 11400000, guid: e020eee86f6c97f4393672759d73602e, type: 2}
|
||||
quantity: 1
|
||||
- gem: {fileID: 11400000, guid: 47a98aa9a30748a4da49455ac0fbd142, type: 2}
|
||||
quantity: 1
|
||||
- gem: {fileID: 11400000, guid: e86536592f45d2b49b9d25abbad1b184, type: 2}
|
||||
quantity: 1
|
||||
- gem: {fileID: 11400000, guid: de5e48980eba8794c93ea7168d592f8f, type: 2}
|
||||
quantity: 1
|
||||
- gem: {fileID: 11400000, guid: 2edf7687dc6caa0489ae2111499fcfab, type: 2}
|
||||
quantity: 1
|
||||
- gem: {fileID: 11400000, guid: 863dcd9e10827f94ab4574b529ffe683, type: 2}
|
||||
quantity: 1
|
||||
- gem: {fileID: 11400000, guid: 66ccf80cf9c50614dbe13ea7f24a6f19, type: 2}
|
||||
quantity: 1
|
||||
- gem: {fileID: 11400000, guid: cf3e3e1f9f1f42f499196fa819263dc1, type: 2}
|
||||
quantity: 1
|
||||
- gem: {fileID: 11400000, guid: 2c42bf0e90f5dd9488d534c337a44eed, type: 2}
|
||||
quantity: 1
|
||||
autoCollectOwnedGemsInEditor: 1
|
||||
gemSearchFolder: Assets/_Game/Data/SkillGems
|
||||
autoCollectedGemQuantity: 1
|
||||
panelBackgroundColor: {r: 0.08, g: 0.08, b: 0.11, a: 0.96}
|
||||
sectionBackgroundColor: {r: 0.14, g: 0.14, b: 0.18, a: 0.95}
|
||||
buttonNormalColor: {r: 0.19, g: 0.19, b: 0.24, a: 0.96}
|
||||
buttonSelectedColor: {r: 0.48, g: 0.32, b: 0.16, a: 0.96}
|
||||
buttonDisabledColor: {r: 0.12, g: 0.12, b: 0.15, a: 0.65}
|
||||
statusNormalColor: {r: 0.86, g: 0.85, b: 0.78, a: 1}
|
||||
statusErrorColor: {r: 1, g: 0.52, b: 0.45, a: 1}
|
||||
--- !u!1001 &3885202253629243258
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -615,7 +615,7 @@ namespace Colosseum.Editor
|
||||
CrushGemPath,
|
||||
"파쇄",
|
||||
"고위력 기술의 단일 피해를 강화하는 테스트용 젬",
|
||||
SkillGemCategory.Attack,
|
||||
SkillGemCategory.Damage,
|
||||
1.15f,
|
||||
1.1f,
|
||||
1f,
|
||||
@@ -625,13 +625,15 @@ namespace Colosseum.Editor
|
||||
1f,
|
||||
0,
|
||||
damageEffect,
|
||||
allowedSkillRoles: SkillRoleType.Attack,
|
||||
allowedSkillActivationTypes: SkillActivationType.Instant,
|
||||
allowedSkillTypes: SkillBaseType.Attack);
|
||||
|
||||
CreateOrUpdateGemAsset(
|
||||
ChallengerGemPath,
|
||||
"도전자",
|
||||
"고위력 기술에 위협 선점 기능을 얹는 테스트용 젬",
|
||||
SkillGemCategory.Threat,
|
||||
SkillGemCategory.Special,
|
||||
1f,
|
||||
1f,
|
||||
1f,
|
||||
@@ -641,13 +643,15 @@ namespace Colosseum.Editor
|
||||
1.5f,
|
||||
0,
|
||||
tauntEffect,
|
||||
allowedSkillRoles: SkillRoleType.Attack | SkillRoleType.Defense,
|
||||
allowedSkillActivationTypes: SkillActivationType.Instant,
|
||||
allowedSkillTypes: SkillBaseType.Attack);
|
||||
|
||||
CreateOrUpdateGemAsset(
|
||||
GuardianGemPath,
|
||||
"수호",
|
||||
"고위력 기술에 보호막 보조를 얹는 테스트용 젬",
|
||||
SkillGemCategory.Support,
|
||||
SkillGemCategory.Survival,
|
||||
1.05f,
|
||||
1.1f,
|
||||
1f,
|
||||
@@ -657,13 +661,15 @@ namespace Colosseum.Editor
|
||||
1f,
|
||||
0,
|
||||
shieldEffect,
|
||||
allowedSkillRoles: SkillRoleType.All,
|
||||
allowedSkillActivationTypes: SkillActivationType.Instant,
|
||||
allowedSkillTypes: SkillBaseType.Attack);
|
||||
|
||||
CreateOrUpdateGemAsset(
|
||||
RepeatGemPath,
|
||||
"연속",
|
||||
"붙은 스킬을 한 번 더 반복 시전하는 테스트용 젬",
|
||||
SkillGemCategory.Efficiency,
|
||||
SkillGemCategory.Special,
|
||||
1.2f,
|
||||
1.15f,
|
||||
1.1f,
|
||||
@@ -673,13 +679,15 @@ namespace Colosseum.Editor
|
||||
1f,
|
||||
1,
|
||||
null,
|
||||
allowedSkillRoles: SkillRoleType.Attack,
|
||||
allowedSkillActivationTypes: SkillActivationType.Instant,
|
||||
allowedSkillTypes: SkillBaseType.Attack);
|
||||
|
||||
CreateOrUpdateGemAsset(
|
||||
FortitudeGemPath,
|
||||
"강인함",
|
||||
"스킬 사용 시 자신에게 경직 면역을 부여하는 테스트용 방어 젬",
|
||||
SkillGemCategory.Defense,
|
||||
SkillGemCategory.Survival,
|
||||
1.05f,
|
||||
1.05f,
|
||||
1f,
|
||||
@@ -689,13 +697,15 @@ namespace Colosseum.Editor
|
||||
1f,
|
||||
0,
|
||||
null,
|
||||
new[] { hitReactionImmuneAbnormality });
|
||||
new[] { hitReactionImmuneAbnormality },
|
||||
allowedSkillRoles: SkillRoleType.All,
|
||||
allowedSkillActivationTypes: SkillActivationType.All);
|
||||
|
||||
CreateOrUpdateGemAsset(
|
||||
WitherGemPath,
|
||||
"약화",
|
||||
"스킬 적중 대상에게 테스트 디버프를 부여하는 제어 젬",
|
||||
SkillGemCategory.Control,
|
||||
SkillGemCategory.Special,
|
||||
1.05f,
|
||||
1.05f,
|
||||
1f,
|
||||
@@ -707,13 +717,15 @@ namespace Colosseum.Editor
|
||||
null,
|
||||
null,
|
||||
0,
|
||||
new[] { testDebuffAbnormality });
|
||||
new[] { testDebuffAbnormality },
|
||||
allowedSkillRoles: SkillRoleType.All,
|
||||
allowedSkillActivationTypes: SkillActivationType.Instant);
|
||||
|
||||
CreateOrUpdateGemAsset(
|
||||
EdgeGemPath,
|
||||
"예리함",
|
||||
"고정 추가 피해를 부여하는 테스트용 공격 젬",
|
||||
SkillGemCategory.Attack,
|
||||
SkillGemCategory.Damage,
|
||||
1f,
|
||||
1f,
|
||||
1f,
|
||||
@@ -723,13 +735,15 @@ namespace Colosseum.Editor
|
||||
1f,
|
||||
0,
|
||||
edgeDamageEffect,
|
||||
allowedSkillRoles: SkillRoleType.Attack,
|
||||
allowedSkillActivationTypes: SkillActivationType.Instant,
|
||||
allowedSkillTypes: SkillBaseType.Attack);
|
||||
|
||||
CreateOrUpdateGemAsset(
|
||||
ImpactGemPath,
|
||||
"충격",
|
||||
"중간 고정 추가 피해를 부여하는 테스트용 공격 젬",
|
||||
SkillGemCategory.Attack,
|
||||
SkillGemCategory.Damage,
|
||||
1f,
|
||||
1f,
|
||||
1f,
|
||||
@@ -739,13 +753,15 @@ namespace Colosseum.Editor
|
||||
1f,
|
||||
0,
|
||||
impactDamageEffect,
|
||||
allowedSkillRoles: SkillRoleType.Attack,
|
||||
allowedSkillActivationTypes: SkillActivationType.Instant,
|
||||
allowedSkillTypes: SkillBaseType.Attack);
|
||||
|
||||
CreateOrUpdateGemAsset(
|
||||
BreachGemPath,
|
||||
"관통",
|
||||
"높은 고정 추가 피해를 부여하는 테스트용 공격 젬",
|
||||
SkillGemCategory.Attack,
|
||||
SkillGemCategory.Damage,
|
||||
1f,
|
||||
1f,
|
||||
1f,
|
||||
@@ -755,6 +771,8 @@ namespace Colosseum.Editor
|
||||
1f,
|
||||
0,
|
||||
breachDamageEffect,
|
||||
allowedSkillRoles: SkillRoleType.Attack,
|
||||
allowedSkillActivationTypes: SkillActivationType.Instant,
|
||||
allowedSkillTypes: SkillBaseType.Attack);
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
@@ -793,19 +811,19 @@ namespace Colosseum.Editor
|
||||
SkillGemData impactGem = AssetDatabase.LoadAssetAtPath<SkillGemData>(ImpactGemPath);
|
||||
SkillGemData breachGem = AssetDatabase.LoadAssetAtPath<SkillGemData>(BreachGemPath);
|
||||
|
||||
SetSkillBaseTypes(slashSkill, SkillBaseType.Attack);
|
||||
SetSkillBaseTypes(tauntSkill, SkillBaseType.Control | SkillBaseType.Utility);
|
||||
SetSkillBaseTypes(guardSkill, SkillBaseType.Defense);
|
||||
SetSkillBaseTypes(dashSkill, SkillBaseType.Mobility);
|
||||
SetSkillBaseTypes(ironWallSkill, SkillBaseType.Defense | SkillBaseType.Support);
|
||||
SetSkillBaseTypes(pierceSkill, SkillBaseType.Attack);
|
||||
SetSkillBaseTypes(gemTestSkill, SkillBaseType.Attack);
|
||||
SetSkillBaseTypes(healSkill, SkillBaseType.Support);
|
||||
SetSkillBaseTypes(areaHealSkill, SkillBaseType.Support);
|
||||
SetSkillBaseTypes(shieldSkill, SkillBaseType.Defense | SkillBaseType.Support);
|
||||
SetSkillBaseTypes(projectileSkill, SkillBaseType.Attack);
|
||||
SetSkillBaseTypes(spinSkill, SkillBaseType.Attack);
|
||||
SetSkillBaseTypes(evadeSkill, SkillBaseType.Mobility);
|
||||
SetSkillClassification(slashSkill, SkillRoleType.Attack, SkillActivationType.Instant, SkillBaseType.Attack);
|
||||
SetSkillClassification(tauntSkill, SkillRoleType.Defense, SkillActivationType.Instant, SkillBaseType.Defense);
|
||||
SetSkillClassification(guardSkill, SkillRoleType.Defense, SkillActivationType.Buff, SkillBaseType.Defense);
|
||||
SetSkillClassification(dashSkill, SkillRoleType.Attack, SkillActivationType.Instant, SkillBaseType.Attack);
|
||||
SetSkillClassification(ironWallSkill, SkillRoleType.Defense, SkillActivationType.Buff, SkillBaseType.Defense);
|
||||
SetSkillClassification(pierceSkill, SkillRoleType.Attack, SkillActivationType.Instant, SkillBaseType.Attack);
|
||||
SetSkillClassification(gemTestSkill, SkillRoleType.Attack, SkillActivationType.Instant, SkillBaseType.Attack);
|
||||
SetSkillClassification(healSkill, SkillRoleType.Support, SkillActivationType.Instant, SkillBaseType.Support);
|
||||
SetSkillClassification(areaHealSkill, SkillRoleType.Support, SkillActivationType.Instant, SkillBaseType.Support);
|
||||
SetSkillClassification(shieldSkill, SkillRoleType.Support, SkillActivationType.Instant, SkillBaseType.Support);
|
||||
SetSkillClassification(projectileSkill, SkillRoleType.Attack, SkillActivationType.Instant, SkillBaseType.Attack);
|
||||
SetSkillClassification(spinSkill, SkillRoleType.Attack, SkillActivationType.Instant, SkillBaseType.Attack);
|
||||
SetSkillClassification(evadeSkill, SkillRoleType.Defense, SkillActivationType.Instant, SkillBaseType.Defense);
|
||||
|
||||
EnsureGemTestSkillSlotCount(gemTestSkill, 3);
|
||||
|
||||
@@ -1336,6 +1354,8 @@ namespace Colosseum.Editor
|
||||
AbnormalityData[] selfAbnormalities = null,
|
||||
int triggeredAbnormalityIndex = -1,
|
||||
AbnormalityData[] onHitAbnormalities = null,
|
||||
SkillRoleType allowedSkillRoles = SkillRoleType.All,
|
||||
SkillActivationType allowedSkillActivationTypes = SkillActivationType.All,
|
||||
SkillBaseType allowedSkillTypes = SkillBaseType.All,
|
||||
SkillGemCategory[] incompatibleCategories = null,
|
||||
SkillGemData[] incompatibleGems = null)
|
||||
@@ -1356,6 +1376,8 @@ namespace Colosseum.Editor
|
||||
serializedGem.FindProperty("gemName").stringValue = gemName;
|
||||
serializedGem.FindProperty("description").stringValue = description;
|
||||
serializedGem.FindProperty("category").enumValueIndex = (int)category;
|
||||
serializedGem.FindProperty("allowedSkillRoles").intValue = (int)allowedSkillRoles;
|
||||
serializedGem.FindProperty("allowedSkillActivationTypes").intValue = (int)allowedSkillActivationTypes;
|
||||
serializedGem.FindProperty("manaCostMultiplier").floatValue = manaCostMultiplier;
|
||||
serializedGem.FindProperty("cooldownMultiplier").floatValue = cooldownMultiplier;
|
||||
serializedGem.FindProperty("castSpeedMultiplier").floatValue = castSpeedMultiplier;
|
||||
@@ -1424,17 +1446,42 @@ namespace Colosseum.Editor
|
||||
EditorUtility.SetDirty(gem);
|
||||
}
|
||||
|
||||
private static void SetSkillBaseTypes(SkillData skill, SkillBaseType baseTypes)
|
||||
private static void SetSkillClassification(
|
||||
SkillData skill,
|
||||
SkillRoleType skillRole,
|
||||
SkillActivationType activationType,
|
||||
SkillBaseType baseTypes)
|
||||
{
|
||||
if (skill == null)
|
||||
return;
|
||||
|
||||
SerializedObject serializedSkill = new SerializedObject(skill);
|
||||
bool hasChanges = false;
|
||||
|
||||
SerializedProperty skillRoleProperty = serializedSkill.FindProperty("skillRole");
|
||||
if (skillRoleProperty != null && skillRoleProperty.intValue != (int)skillRole)
|
||||
{
|
||||
skillRoleProperty.intValue = (int)skillRole;
|
||||
hasChanges = true;
|
||||
}
|
||||
|
||||
SerializedProperty activationTypeProperty = serializedSkill.FindProperty("activationType");
|
||||
if (activationTypeProperty != null && activationTypeProperty.intValue != (int)activationType)
|
||||
{
|
||||
activationTypeProperty.intValue = (int)activationType;
|
||||
hasChanges = true;
|
||||
}
|
||||
|
||||
SerializedProperty baseTypesProperty = serializedSkill.FindProperty("baseTypes");
|
||||
if (baseTypesProperty == null || baseTypesProperty.intValue == (int)baseTypes)
|
||||
if (baseTypesProperty != null && baseTypesProperty.intValue != (int)baseTypes)
|
||||
{
|
||||
baseTypesProperty.intValue = (int)baseTypes;
|
||||
hasChanges = true;
|
||||
}
|
||||
|
||||
if (!hasChanges)
|
||||
return;
|
||||
|
||||
baseTypesProperty.intValue = (int)baseTypes;
|
||||
serializedSkill.ApplyModifiedPropertiesWithoutUndo();
|
||||
EditorUtility.SetDirty(skill);
|
||||
}
|
||||
@@ -1571,7 +1618,7 @@ namespace Colosseum.Editor
|
||||
if (hasGem)
|
||||
categoryBuilder.Append(", ");
|
||||
|
||||
categoryBuilder.Append(gem.Category);
|
||||
categoryBuilder.Append(SkillClassificationUtility.GetGemCategoryLabel(gem.Category));
|
||||
hasGem = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace Colosseum.Player
|
||||
private Vector3 velocity;
|
||||
private Vector2 moveInput; // 로컬 원시 입력 (IsOwner 전용)
|
||||
private InputSystem_Actions inputActions;
|
||||
private bool gameplayInputEnabled = true;
|
||||
private bool isJumping;
|
||||
private bool wasGrounded;
|
||||
private Vector3 forcedMovementVelocity;
|
||||
@@ -97,10 +98,10 @@ namespace Colosseum.Player
|
||||
private void InitializeInputActions()
|
||||
{
|
||||
inputActions = new InputSystem_Actions();
|
||||
inputActions.Player.Enable();
|
||||
inputActions.Player.Move.performed += OnMovePerformed;
|
||||
inputActions.Player.Move.canceled += OnMoveCanceled;
|
||||
inputActions.Player.Jump.performed += OnJumpPerformed;
|
||||
SetGameplayInputEnabled(true);
|
||||
}
|
||||
|
||||
private void CleanupInputActions()
|
||||
@@ -125,10 +126,7 @@ namespace Colosseum.Player
|
||||
{
|
||||
if (IsOwner && inputActions != null)
|
||||
{
|
||||
inputActions.Player.Enable();
|
||||
inputActions.Player.Move.performed += OnMovePerformed;
|
||||
inputActions.Player.Move.canceled += OnMoveCanceled;
|
||||
inputActions.Player.Jump.performed += OnJumpPerformed;
|
||||
SetGameplayInputEnabled(gameplayInputEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,9 +151,33 @@ namespace Colosseum.Player
|
||||
private void OnMovePerformed(InputAction.CallbackContext context) => moveInput = context.ReadValue<Vector2>();
|
||||
private void OnMoveCanceled(InputAction.CallbackContext context) => moveInput = Vector2.zero;
|
||||
|
||||
/// <summary>
|
||||
/// 로컬 플레이어의 전투 입력을 일시적으로 차단하거나 복구합니다.
|
||||
/// </summary>
|
||||
public void SetGameplayInputEnabled(bool enabled)
|
||||
{
|
||||
gameplayInputEnabled = enabled;
|
||||
|
||||
if (!IsOwner || inputActions == null)
|
||||
return;
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
inputActions.Player.Enable();
|
||||
return;
|
||||
}
|
||||
|
||||
moveInput = Vector2.zero;
|
||||
if (netMoveInput.Value != Vector2.zero)
|
||||
netMoveInput.Value = Vector2.zero;
|
||||
|
||||
inputActions.Player.Disable();
|
||||
}
|
||||
|
||||
private void OnJumpPerformed(InputAction.CallbackContext context)
|
||||
{
|
||||
if (!IsOwner) return;
|
||||
if (!gameplayInputEnabled) return;
|
||||
if (actionState != null && !actionState.CanJump) return;
|
||||
|
||||
JumpRequestRpc();
|
||||
|
||||
@@ -77,6 +77,7 @@ namespace Colosseum.Player
|
||||
[SerializeField] private PlayerActionState actionState;
|
||||
|
||||
private InputSystem_Actions inputActions;
|
||||
private bool gameplayInputEnabled = true;
|
||||
|
||||
public SkillData[] SkillSlots => skillSlots;
|
||||
public SkillLoadoutEntry[] SkillLoadoutEntries => skillLoadoutEntries;
|
||||
@@ -117,7 +118,7 @@ namespace Colosseum.Player
|
||||
inputActions.Player.Evade.performed += OnEvadePerformed;
|
||||
}
|
||||
|
||||
inputActions.Player.Enable();
|
||||
SetGameplayInputEnabled(true);
|
||||
}
|
||||
|
||||
public override void OnNetworkDespawn()
|
||||
@@ -148,10 +149,29 @@ namespace Colosseum.Player
|
||||
{
|
||||
if (IsOwner && inputActions != null)
|
||||
{
|
||||
inputActions.Player.Enable();
|
||||
SetGameplayInputEnabled(gameplayInputEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 로컬 플레이어의 스킬 입력을 일시적으로 차단하거나 복구합니다.
|
||||
/// </summary>
|
||||
public void SetGameplayInputEnabled(bool enabled)
|
||||
{
|
||||
gameplayInputEnabled = enabled;
|
||||
|
||||
if (!IsOwner || inputActions == null)
|
||||
return;
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
inputActions.Player.Enable();
|
||||
return;
|
||||
}
|
||||
|
||||
inputActions.Player.Disable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 기존 프리팹이나 씬 직렬화 데이터가 6칸으로 남아 있어도
|
||||
/// 긴급 회피 슬롯까지 포함한 7칸 구성을 항상 보장합니다.
|
||||
@@ -244,6 +264,9 @@ namespace Colosseum.Player
|
||||
/// </summary>
|
||||
private void OnSkillInput(int slotIndex)
|
||||
{
|
||||
if (!gameplayInputEnabled)
|
||||
return;
|
||||
|
||||
if (slotIndex < 0 || slotIndex >= skillSlots.Length)
|
||||
return;
|
||||
|
||||
|
||||
@@ -22,6 +22,32 @@ namespace Colosseum.Skills
|
||||
All = Attack | Defense | Support | Control | Mobility | Utility,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 스킬의 역할 분류입니다.
|
||||
/// 젬 장착 조건에는 비트 마스크 형태로도 사용합니다.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum SkillRoleType
|
||||
{
|
||||
None = 0,
|
||||
Attack = 1 << 0,
|
||||
Defense = 1 << 1,
|
||||
Support = 1 << 2,
|
||||
All = Attack | Defense | Support,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 스킬의 발동 타입 분류입니다.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum SkillActivationType
|
||||
{
|
||||
None = 0,
|
||||
Instant = 1 << 0,
|
||||
Buff = 1 << 1,
|
||||
All = Instant | Buff,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 스킬 데이터. 스킬의 기본 정보와 효과 목록을 관리합니다.
|
||||
/// </summary>
|
||||
@@ -34,8 +60,14 @@ namespace Colosseum.Skills
|
||||
[SerializeField] private string description;
|
||||
[SerializeField] private Sprite icon;
|
||||
|
||||
[Header("기반 스킬 분류")]
|
||||
[Tooltip("젬 장착 가능 조건에 사용하는 기반 스킬 분류")]
|
||||
[Header("스킬 분류")]
|
||||
[Tooltip("이 스킬의 주 역할입니다.")]
|
||||
[SerializeField] private SkillRoleType skillRole = SkillRoleType.Attack;
|
||||
[Tooltip("이 스킬의 발동 타입입니다.")]
|
||||
[SerializeField] private SkillActivationType activationType = SkillActivationType.Instant;
|
||||
|
||||
[Header("레거시 기반 스킬 분류")]
|
||||
[Tooltip("기존 테스트 데이터와의 호환을 위한 기반 분류입니다.")]
|
||||
[SerializeField] private SkillBaseType baseTypes = SkillBaseType.None;
|
||||
|
||||
[Header("애니메이션")]
|
||||
@@ -82,6 +114,8 @@ namespace Colosseum.Skills
|
||||
public string SkillName => skillName;
|
||||
public string Description => description;
|
||||
public Sprite Icon => icon;
|
||||
public SkillRoleType SkillRole => skillRole;
|
||||
public SkillActivationType ActivationType => activationType;
|
||||
public SkillBaseType BaseTypes => baseTypes;
|
||||
public AnimationClip SkillClip => skillClip;
|
||||
public AnimationClip EndClip => endClip;
|
||||
@@ -97,5 +131,104 @@ namespace Colosseum.Skills
|
||||
public bool BlockOtherSkillsWhileCasting => blockOtherSkillsWhileCasting;
|
||||
public IReadOnlyList<SkillEffect> CastStartEffects => castStartEffects;
|
||||
public IReadOnlyList<SkillEffect> Effects => effects;
|
||||
|
||||
/// <summary>
|
||||
/// 지정한 장착 조건과 현재 스킬 분류가 맞는지 확인합니다.
|
||||
/// </summary>
|
||||
public bool MatchesClassification(SkillRoleType allowedRoles, SkillActivationType allowedActivationTypes)
|
||||
{
|
||||
bool matchesRole = allowedRoles == SkillRoleType.None ||
|
||||
allowedRoles == SkillRoleType.All ||
|
||||
(allowedRoles & skillRole) != 0;
|
||||
|
||||
bool matchesActivationType = allowedActivationTypes == SkillActivationType.None ||
|
||||
allowedActivationTypes == SkillActivationType.All ||
|
||||
(allowedActivationTypes & activationType) != 0;
|
||||
|
||||
return matchesRole && matchesActivationType;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 스킬/젬 분류를 UI 친화적인 문자열로 변환하는 유틸리티입니다.
|
||||
/// </summary>
|
||||
public static class SkillClassificationUtility
|
||||
{
|
||||
public static string GetRoleLabel(SkillRoleType role)
|
||||
{
|
||||
return role switch
|
||||
{
|
||||
SkillRoleType.Attack => "공격",
|
||||
SkillRoleType.Defense => "방어",
|
||||
SkillRoleType.Support => "지원",
|
||||
SkillRoleType.All => "전체",
|
||||
_ => "미분류",
|
||||
};
|
||||
}
|
||||
|
||||
public static string GetActivationTypeLabel(SkillActivationType activationType)
|
||||
{
|
||||
return activationType switch
|
||||
{
|
||||
SkillActivationType.Instant => "즉발",
|
||||
SkillActivationType.Buff => "버프",
|
||||
SkillActivationType.All => "전체",
|
||||
_ => "미분류",
|
||||
};
|
||||
}
|
||||
|
||||
public static string GetSkillClassificationLabel(SkillData skill)
|
||||
{
|
||||
if (skill == null)
|
||||
return "미분류";
|
||||
|
||||
return $"{GetRoleLabel(skill.SkillRole)}/{GetActivationTypeLabel(skill.ActivationType)}";
|
||||
}
|
||||
|
||||
public static string GetGemCategoryLabel(SkillGemCategory category)
|
||||
{
|
||||
return category switch
|
||||
{
|
||||
SkillGemCategory.Damage => "데미지",
|
||||
SkillGemCategory.Survival => "생존",
|
||||
SkillGemCategory.Mana => "마나",
|
||||
SkillGemCategory.Special => "특수",
|
||||
SkillGemCategory.BuffPower => "효과 강화",
|
||||
SkillGemCategory.Duration => "지속시간",
|
||||
SkillGemCategory.Area => "범위",
|
||||
SkillGemCategory.Cost => "비용",
|
||||
_ => "공용",
|
||||
};
|
||||
}
|
||||
|
||||
public static string GetAllowedRoleSummary(SkillRoleType roles)
|
||||
{
|
||||
if (roles == SkillRoleType.None || roles == SkillRoleType.All)
|
||||
return "전체";
|
||||
|
||||
List<string> labels = new List<string>();
|
||||
if ((roles & SkillRoleType.Attack) != 0)
|
||||
labels.Add("공격");
|
||||
if ((roles & SkillRoleType.Defense) != 0)
|
||||
labels.Add("방어");
|
||||
if ((roles & SkillRoleType.Support) != 0)
|
||||
labels.Add("지원");
|
||||
|
||||
return labels.Count > 0 ? string.Join(" + ", labels) : "미분류";
|
||||
}
|
||||
|
||||
public static string GetAllowedActivationSummary(SkillActivationType activationTypes)
|
||||
{
|
||||
if (activationTypes == SkillActivationType.None || activationTypes == SkillActivationType.All)
|
||||
return "전체";
|
||||
|
||||
List<string> labels = new List<string>();
|
||||
if ((activationTypes & SkillActivationType.Instant) != 0)
|
||||
labels.Add("즉발");
|
||||
if ((activationTypes & SkillActivationType.Buff) != 0)
|
||||
labels.Add("버프");
|
||||
|
||||
return labels.Count > 0 ? string.Join(" + ", labels) : "미분류";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,12 +13,14 @@ namespace Colosseum.Skills
|
||||
public enum SkillGemCategory
|
||||
{
|
||||
Common,
|
||||
Attack,
|
||||
Threat,
|
||||
Defense,
|
||||
Support,
|
||||
Control,
|
||||
Efficiency,
|
||||
Damage,
|
||||
Survival,
|
||||
Mana,
|
||||
Special,
|
||||
BuffPower,
|
||||
Duration,
|
||||
Area,
|
||||
Cost,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -66,9 +68,13 @@ namespace Colosseum.Skills
|
||||
[SerializeField] private SkillGemCategory category = SkillGemCategory.Common;
|
||||
|
||||
[Header("장착 제약")]
|
||||
[Tooltip("장착 가능한 기반 스킬 분류입니다. None 또는 All이면 제한하지 않습니다.")]
|
||||
[Tooltip("장착 가능한 스킬 역할 조합입니다. None 또는 All이면 역할 제한을 두지 않습니다.")]
|
||||
[SerializeField] private SkillRoleType allowedSkillRoles = SkillRoleType.All;
|
||||
[Tooltip("장착 가능한 스킬 발동 타입 조합입니다. None 또는 All이면 타입 제한을 두지 않습니다.")]
|
||||
[SerializeField] private SkillActivationType allowedSkillActivationTypes = SkillActivationType.All;
|
||||
[Tooltip("기존 테스트 자산과의 호환을 위한 기반 스킬 분류입니다. 새 사양에서는 역할/발동 타입을 우선 사용합니다.")]
|
||||
[SerializeField] private SkillBaseType allowedSkillTypes = SkillBaseType.All;
|
||||
[Tooltip("함께 장착할 수 없는 젬 분류")]
|
||||
[Tooltip("함께 장착할 수 없는 젬 효과 분류")]
|
||||
[SerializeField] private SkillGemCategory[] incompatibleCategories = Array.Empty<SkillGemCategory>();
|
||||
[Tooltip("함께 장착할 수 없는 특정 젬")]
|
||||
[SerializeField] private List<SkillGemData> incompatibleGems = new();
|
||||
@@ -107,6 +113,8 @@ namespace Colosseum.Skills
|
||||
public string Description => description;
|
||||
public Sprite Icon => icon;
|
||||
public SkillGemCategory Category => category;
|
||||
public SkillRoleType AllowedSkillRoles => allowedSkillRoles;
|
||||
public SkillActivationType AllowedSkillActivationTypes => allowedSkillActivationTypes;
|
||||
public SkillBaseType AllowedSkillTypes => allowedSkillTypes;
|
||||
public float ManaCostMultiplier => manaCostMultiplier;
|
||||
public float CooldownMultiplier => cooldownMultiplier;
|
||||
@@ -131,6 +139,15 @@ namespace Colosseum.Skills
|
||||
if (skill == null)
|
||||
return false;
|
||||
|
||||
bool usesRoleRestriction = allowedSkillRoles != SkillRoleType.None && allowedSkillRoles != SkillRoleType.All;
|
||||
bool usesActivationRestriction = allowedSkillActivationTypes != SkillActivationType.None &&
|
||||
allowedSkillActivationTypes != SkillActivationType.All;
|
||||
|
||||
if (usesRoleRestriction || usesActivationRestriction)
|
||||
{
|
||||
return skill.MatchesClassification(allowedSkillRoles, allowedSkillActivationTypes);
|
||||
}
|
||||
|
||||
if (allowedSkillTypes == SkillBaseType.None || allowedSkillTypes == SkillBaseType.All)
|
||||
return true;
|
||||
|
||||
|
||||
@@ -425,7 +425,11 @@ namespace Colosseum.Skills
|
||||
|
||||
if (!gem.CanAttachToSkill(baseSkill))
|
||||
{
|
||||
reason = $"기반 스킬 분류 제약을 만족하지 않습니다. Skill={baseSkill.BaseTypes}, Allowed={gem.AllowedSkillTypes}";
|
||||
string skillClassification = SkillClassificationUtility.GetSkillClassificationLabel(baseSkill);
|
||||
string allowedClassification =
|
||||
$"{SkillClassificationUtility.GetAllowedRoleSummary(gem.AllowedSkillRoles)}/" +
|
||||
$"{SkillClassificationUtility.GetAllowedActivationSummary(gem.AllowedSkillActivationTypes)}";
|
||||
reason = $"장착 가능한 스킬 조합이 아닙니다. Skill={skillClassification}, Allowed={allowedClassification}";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -476,7 +480,9 @@ namespace Colosseum.Skills
|
||||
|
||||
if (gem.IsCategoryIncompatible(otherGem.Category) || otherGem.IsCategoryIncompatible(gem.Category))
|
||||
{
|
||||
reason = $"{gem.Category} / {otherGem.Category} 분류 조합은 허용되지 않습니다.";
|
||||
reason =
|
||||
$"{SkillClassificationUtility.GetGemCategoryLabel(gem.Category)} / " +
|
||||
$"{SkillClassificationUtility.GetGemCategoryLabel(otherGem.Category)} 효과 분류 조합은 허용되지 않습니다.";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
1348
Assets/_Game/Scripts/UI/SkillGemInventoryUI.cs
Normal file
1348
Assets/_Game/Scripts/UI/SkillGemInventoryUI.cs
Normal file
File diff suppressed because it is too large
Load Diff
2
Assets/_Game/Scripts/UI/SkillGemInventoryUI.cs.meta
Normal file
2
Assets/_Game/Scripts/UI/SkillGemInventoryUI.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ca98554fbe3918040881b21c34fbb373
|
||||
@@ -283,9 +283,11 @@ namespace Colosseum.UI
|
||||
SkillData skill = playerSkillInput.GetSkill(mappedSlotIndex);
|
||||
if (skill == null) continue;
|
||||
|
||||
SkillLoadoutEntry loadoutEntry = playerSkillInput.GetSkillLoadout(mappedSlotIndex);
|
||||
float remainingCooldown = playerSkillInput.GetRemainingCooldown(mappedSlotIndex);
|
||||
float totalCooldown = skill.Cooldown;
|
||||
bool hasEnoughMana = networkController == null || networkController.Mana >= skill.ManaCost;
|
||||
float totalCooldown = loadoutEntry != null ? loadoutEntry.GetResolvedCooldown() : skill.Cooldown;
|
||||
float requiredMana = loadoutEntry != null ? loadoutEntry.GetResolvedManaCost() : skill.ManaCost;
|
||||
bool hasEnoughMana = networkController == null || networkController.Mana >= requiredMana;
|
||||
|
||||
if (shouldLog && remainingCooldown > 0f)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user