업그레이드 데이터 입력 로직 및 기능 추가
캐릭터 스탯을 PlayerStats 컴포넌트에서 모아서 관리하도록 변경 코드에서도 마찬가지
This commit is contained in:
@@ -70,6 +70,7 @@
|
||||
<Compile Include="Assets\Scripts\Editor\NetworkConnectionHelperEditor.cs" />
|
||||
<Compile Include="Assets\Scripts\Editor\FogOfWarVisibilitySetup.cs" />
|
||||
<Compile Include="Assets\FlatKit\Shaders\Editor\MaterialPropertyExtensions.cs" />
|
||||
<Compile Include="Assets\Scripts\Editor\UpgradePrefabSetup.cs" />
|
||||
<Compile Include="Assets\FlatKit\Shaders\Editor\TerrainEditor.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -79,9 +79,11 @@
|
||||
<Compile Include="Assets\Scripts\WorkerSpawner.cs" />
|
||||
<Compile Include="Assets\Scripts\Resource.cs" />
|
||||
<Compile Include="Assets\Data\Scripts\DataClasses\UpgradeData.cs" />
|
||||
<Compile Include="Assets\Scripts\UpgradeDatabase.cs" />
|
||||
<Compile Include="Assets\Scripts\AutoTargetSystem.cs" />
|
||||
<Compile Include="Assets\Scripts\CreepDataComponent.cs" />
|
||||
<Compile Include="Assets\Scripts\BuildingSlotButton.cs" />
|
||||
<Compile Include="Assets\Scripts\PlayerStats.cs" />
|
||||
<Compile Include="Assets\FlatKit\[Render Pipeline] URP\Water\Scripts\Buoyancy.cs" />
|
||||
<Compile Include="Assets\Scripts\ObstacleSpawner.cs" />
|
||||
<Compile Include="Assets\Scripts\BuildingFoundation.cs" />
|
||||
@@ -125,6 +127,7 @@
|
||||
<Compile Include="Assets\Scripts\EnemyAIState.cs" />
|
||||
<Compile Include="Assets\Scripts\ShortcutNetworkStarter.cs" />
|
||||
<Compile Include="Assets\Scripts\EquipmentData.cs" />
|
||||
<Compile Include="Assets\Scripts\PlayerUpgradeManager.cs" />
|
||||
<Compile Include="Assets\Scripts\NetworkConnectionHelper.cs" />
|
||||
<Compile Include="Assets\Scripts\NetworkConnectionHandler.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
8
Assets/Data/ScriptableObjects/Upgrade.meta
Normal file
8
Assets/Data/ScriptableObjects/Upgrade.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dc09279707549e041ae0219468b0a4a2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade1.asset
Normal file
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade1.asset
Normal file
@@ -0,0 +1,27 @@
|
||||
%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: 4f134815569ad014e9ccc81ddc443c4c, type: 3}
|
||||
m_Name: Upgrade1
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.Data.UpgradeData
|
||||
id: 1
|
||||
memo: "\uCCB4\uB825 \uC99D\uAC00 Lv.1"
|
||||
upgradeCategory: combat
|
||||
upgradeTarget: person
|
||||
mana: 200
|
||||
requireUpgradeId:
|
||||
effectStatList:
|
||||
- player_max_hp
|
||||
effectOpList:
|
||||
- add
|
||||
effectValueList:
|
||||
- 50
|
||||
sortOrder: 1
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9e46f00da341b24ab07b314c89b7fd9
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade10.asset
Normal file
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade10.asset
Normal file
@@ -0,0 +1,27 @@
|
||||
%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: 4f134815569ad014e9ccc81ddc443c4c, type: 3}
|
||||
m_Name: Upgrade10
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.Data.UpgradeData
|
||||
id: 10
|
||||
memo: "\uB178\uB3D9\uB825 \uC99D\uAC00 Lv.1"
|
||||
upgradeCategory: harvest
|
||||
upgradeTarget: person
|
||||
mana: 200
|
||||
requireUpgradeId:
|
||||
effectStatList:
|
||||
- player_manpower
|
||||
effectOpList:
|
||||
- add
|
||||
effectValueList:
|
||||
- 5
|
||||
sortOrder: 10
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c665e2cbdd230c04fb6d3e9fac091a65
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade11.asset
Normal file
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade11.asset
Normal file
@@ -0,0 +1,27 @@
|
||||
%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: 4f134815569ad014e9ccc81ddc443c4c, type: 3}
|
||||
m_Name: Upgrade11
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.Data.UpgradeData
|
||||
id: 11
|
||||
memo: "\uB178\uB3D9\uB825 \uC99D\uAC00 Lv.2"
|
||||
upgradeCategory: harvest
|
||||
upgradeTarget: person
|
||||
mana: 300
|
||||
requireUpgradeId: 0a000000
|
||||
effectStatList:
|
||||
- player_manpower
|
||||
effectOpList:
|
||||
- add
|
||||
effectValueList:
|
||||
- 10
|
||||
sortOrder: 11
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f5ad1c8a4ecf84a43b7c609c58592295
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade12.asset
Normal file
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade12.asset
Normal file
@@ -0,0 +1,27 @@
|
||||
%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: 4f134815569ad014e9ccc81ddc443c4c, type: 3}
|
||||
m_Name: Upgrade12
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.Data.UpgradeData
|
||||
id: 12
|
||||
memo: "\uB178\uB3D9\uB825 \uC99D\uAC00 Lv.3"
|
||||
upgradeCategory: harvest
|
||||
upgradeTarget: person
|
||||
mana: 400
|
||||
requireUpgradeId: 070000000a000000
|
||||
effectStatList:
|
||||
- player_manpower
|
||||
effectOpList:
|
||||
- add
|
||||
effectValueList:
|
||||
- 20
|
||||
sortOrder: 12
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 555ef1e6ff58ee442953d075e417c091
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade13.asset
Normal file
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade13.asset
Normal file
@@ -0,0 +1,27 @@
|
||||
%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: 4f134815569ad014e9ccc81ddc443c4c, type: 3}
|
||||
m_Name: Upgrade13
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.Data.UpgradeData
|
||||
id: 13
|
||||
memo: "\uC774\uB3D9\uC18D\uB3C4 \uC99D\uAC00 Lv.1"
|
||||
upgradeCategory: scout
|
||||
upgradeTarget: person
|
||||
mana: 200
|
||||
requireUpgradeId:
|
||||
effectStatList:
|
||||
- player_move_speed
|
||||
effectOpList:
|
||||
- mul
|
||||
effectValueList:
|
||||
- 1.1
|
||||
sortOrder: 13
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa2a6eecb804c3948a4fa7e75bacfca6
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade14.asset
Normal file
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade14.asset
Normal file
@@ -0,0 +1,27 @@
|
||||
%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: 4f134815569ad014e9ccc81ddc443c4c, type: 3}
|
||||
m_Name: Upgrade14
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.Data.UpgradeData
|
||||
id: 14
|
||||
memo: "\uC774\uB3D9\uC18D\uB3C4 \uC99D\uAC00 Lv.2"
|
||||
upgradeCategory: scout
|
||||
upgradeTarget: person
|
||||
mana: 300
|
||||
requireUpgradeId: 0d000000
|
||||
effectStatList:
|
||||
- player_move_speed
|
||||
effectOpList:
|
||||
- mul
|
||||
effectValueList:
|
||||
- 1.2
|
||||
sortOrder: 14
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3216444533dfdc14891741f0b1c5a30a
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade15.asset
Normal file
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade15.asset
Normal file
@@ -0,0 +1,27 @@
|
||||
%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: 4f134815569ad014e9ccc81ddc443c4c, type: 3}
|
||||
m_Name: Upgrade15
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.Data.UpgradeData
|
||||
id: 15
|
||||
memo: "\uC774\uB3D9\uC18D\uB3C4 \uC99D\uAC00 Lv.3"
|
||||
upgradeCategory: scout
|
||||
upgradeTarget: person
|
||||
mana: 400
|
||||
requireUpgradeId: 0e000000
|
||||
effectStatList:
|
||||
- player_move_speed
|
||||
effectOpList:
|
||||
- mul
|
||||
effectValueList:
|
||||
- 1.3
|
||||
sortOrder: 15
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 227e825691ca7c9498e4af4cbb592faa
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade2.asset
Normal file
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade2.asset
Normal file
@@ -0,0 +1,27 @@
|
||||
%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: 4f134815569ad014e9ccc81ddc443c4c, type: 3}
|
||||
m_Name: Upgrade2
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.Data.UpgradeData
|
||||
id: 2
|
||||
memo: "\uCCB4\uB825 \uC99D\uAC00 Lv.2"
|
||||
upgradeCategory: combat
|
||||
upgradeTarget: person
|
||||
mana: 300
|
||||
requireUpgradeId: 01000000
|
||||
effectStatList:
|
||||
- player_max_hp
|
||||
effectOpList:
|
||||
- add
|
||||
effectValueList:
|
||||
- 100
|
||||
sortOrder: 2
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d989011e0aeec9a4b9ed3d9e49488c8a
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade3.asset
Normal file
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade3.asset
Normal file
@@ -0,0 +1,27 @@
|
||||
%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: 4f134815569ad014e9ccc81ddc443c4c, type: 3}
|
||||
m_Name: Upgrade3
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.Data.UpgradeData
|
||||
id: 3
|
||||
memo: "\uCCB4\uB825 \uC99D\uAC00 Lv.3"
|
||||
upgradeCategory: combat
|
||||
upgradeTarget: person
|
||||
mana: 400
|
||||
requireUpgradeId: 0200000005000000
|
||||
effectStatList:
|
||||
- player_max_hp
|
||||
effectOpList:
|
||||
- add
|
||||
effectValueList:
|
||||
- 150
|
||||
sortOrder: 3
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 29b2206b90bc89c4183c6fb0a1bb699e
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade4.asset
Normal file
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade4.asset
Normal file
@@ -0,0 +1,27 @@
|
||||
%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: 4f134815569ad014e9ccc81ddc443c4c, type: 3}
|
||||
m_Name: Upgrade4
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.Data.UpgradeData
|
||||
id: 4
|
||||
memo: "\uACF5\uACA9\uB825 \uC99D\uAC00 Lv.1"
|
||||
upgradeCategory: combat
|
||||
upgradeTarget: person
|
||||
mana: 200
|
||||
requireUpgradeId:
|
||||
effectStatList:
|
||||
- player_atk_damage
|
||||
effectOpList:
|
||||
- add
|
||||
effectValueList:
|
||||
- 5
|
||||
sortOrder: 4
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4c370fa5d360b034b977fa923d14f60b
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade5.asset
Normal file
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade5.asset
Normal file
@@ -0,0 +1,27 @@
|
||||
%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: 4f134815569ad014e9ccc81ddc443c4c, type: 3}
|
||||
m_Name: Upgrade5
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.Data.UpgradeData
|
||||
id: 5
|
||||
memo: "\uACF5\uACA9\uB825 \uC99D\uAC00 Lv.2"
|
||||
upgradeCategory: combat
|
||||
upgradeTarget: person
|
||||
mana: 300
|
||||
requireUpgradeId: 04000000
|
||||
effectStatList:
|
||||
- player_atk_damage
|
||||
effectOpList:
|
||||
- add
|
||||
effectValueList:
|
||||
- 10
|
||||
sortOrder: 5
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 49e9bbb379a103741bca937c322db0cb
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade6.asset
Normal file
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade6.asset
Normal file
@@ -0,0 +1,27 @@
|
||||
%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: 4f134815569ad014e9ccc81ddc443c4c, type: 3}
|
||||
m_Name: Upgrade6
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.Data.UpgradeData
|
||||
id: 6
|
||||
memo: "\uACF5\uACA9\uB825 \uC99D\uAC00 Lv.3"
|
||||
upgradeCategory: combat
|
||||
upgradeTarget: person
|
||||
mana: 400
|
||||
requireUpgradeId: 0200000005000000
|
||||
effectStatList:
|
||||
- player_atk_damage
|
||||
effectOpList:
|
||||
- add
|
||||
effectValueList:
|
||||
- 15
|
||||
sortOrder: 6
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c6178f649bd6ad141888fb39c653bda9
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade7.asset
Normal file
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade7.asset
Normal file
@@ -0,0 +1,27 @@
|
||||
%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: 4f134815569ad014e9ccc81ddc443c4c, type: 3}
|
||||
m_Name: Upgrade7
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.Data.UpgradeData
|
||||
id: 7
|
||||
memo: "\uC790\uC6D0 \uCD5C\uB300 \uC6A9\uB7C9 \uC99D\uAC00 Lv.1"
|
||||
upgradeCategory: harvest
|
||||
upgradeTarget: person
|
||||
mana: 200
|
||||
requireUpgradeId:
|
||||
effectStatList:
|
||||
- player_capacity
|
||||
effectOpList:
|
||||
- add
|
||||
effectValueList:
|
||||
- 20
|
||||
sortOrder: 7
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 36cdb899e627bd54092fa9e4458ff6d2
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade8.asset
Normal file
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade8.asset
Normal file
@@ -0,0 +1,27 @@
|
||||
%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: 4f134815569ad014e9ccc81ddc443c4c, type: 3}
|
||||
m_Name: Upgrade8
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.Data.UpgradeData
|
||||
id: 8
|
||||
memo: "\uC790\uC6D0 \uCD5C\uB300 \uC6A9\uB7C9 \uC99D\uAC00 Lv.2"
|
||||
upgradeCategory: harvest
|
||||
upgradeTarget: person
|
||||
mana: 300
|
||||
requireUpgradeId: 07000000
|
||||
effectStatList:
|
||||
- player_capacity
|
||||
effectOpList:
|
||||
- add
|
||||
effectValueList:
|
||||
- 50
|
||||
sortOrder: 8
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9e8418449515bb142b06d88d7a0ac4e1
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade9.asset
Normal file
27
Assets/Data/ScriptableObjects/Upgrade/Upgrade9.asset
Normal file
@@ -0,0 +1,27 @@
|
||||
%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: 4f134815569ad014e9ccc81ddc443c4c, type: 3}
|
||||
m_Name: Upgrade9
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.Data.UpgradeData
|
||||
id: 9
|
||||
memo: "\uC790\uC6D0 \uCD5C\uB300 \uC6A9\uB7C9 \uC99D\uAC00 Lv.3"
|
||||
upgradeCategory: harvest
|
||||
upgradeTarget: person
|
||||
mana: 400
|
||||
requireUpgradeId: 070000000a000000
|
||||
effectStatList:
|
||||
- player_capacity
|
||||
effectOpList:
|
||||
- add
|
||||
effectValueList:
|
||||
- 100
|
||||
sortOrder: 9
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eca8a6e3f11a84f44aa061493293e791
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -23,6 +23,8 @@ GameObject:
|
||||
- component: {fileID: -4348726977448206869}
|
||||
- component: {fileID: 7148704114816793672}
|
||||
- component: {fileID: 6581787771557727003}
|
||||
- component: {fileID: 8704851935123448388}
|
||||
- component: {fileID: 2146720647481692606}
|
||||
m_Layer: 9
|
||||
m_Name: Player
|
||||
m_TagString: Untagged
|
||||
@@ -85,10 +87,8 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::NetworkPlayerController
|
||||
ShowTopMostFoldoutHeaderGroup: 1
|
||||
moveSpeed: 5
|
||||
rotationSpeed: 10
|
||||
initialTeam: 1
|
||||
maxHealth: 100
|
||||
damageEffectPrefab: {fileID: 0}
|
||||
deathEffectPrefab: {fileID: 0}
|
||||
resourcePickupPrefab: {fileID: 1627676033990080135, guid: 8c45964a69bf8fa4ba461ed217bc052f, type: 3}
|
||||
@@ -158,7 +158,6 @@ MonoBehaviour:
|
||||
interactableLayer:
|
||||
serializedVersion: 2
|
||||
m_Bits: 128
|
||||
workPower: 1
|
||||
rayOrigin: {fileID: 0}
|
||||
useForwardDirection: 1
|
||||
playAnimations: 1
|
||||
@@ -196,8 +195,6 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.AttackAction
|
||||
ShowTopMostFoldoutHeaderGroup: 1
|
||||
attackRange: 3
|
||||
attackDamage: 100
|
||||
attackCooldown: 1
|
||||
attackableLayer:
|
||||
serializedVersion: 2
|
||||
@@ -249,7 +246,6 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.PlayerResourceInventory
|
||||
ShowTopMostFoldoutHeaderGroup: 1
|
||||
maxResourceCapacity: 50
|
||||
--- !u!114 &2148255267416253297
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -263,7 +259,6 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.PlayerVisionProvider
|
||||
ShowTopMostFoldoutHeaderGroup: 1
|
||||
visionRange: 10
|
||||
--- !u!95 &1698609800605343773
|
||||
Animator:
|
||||
serializedVersion: 7
|
||||
@@ -393,6 +388,38 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.InteractableModalManager
|
||||
interactableModal: {fileID: 7317980967521758771}
|
||||
playerInteraction: {fileID: 8729870597719024730}
|
||||
--- !u!114 &8704851935123448388
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1314983689436087486}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: c2399ad44b71131439123eaec84abb08, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.PlayerUpgradeManager
|
||||
ShowTopMostFoldoutHeaderGroup: 1
|
||||
--- !u!114 &2146720647481692606
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1314983689436087486}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 6aa26fe48ebdaae438d465df7c6a3bef, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.PlayerStats
|
||||
baseMaxHp: 100
|
||||
baseDamage: 10
|
||||
baseCapacity: 100
|
||||
baseManpower: 10
|
||||
baseMoveSpeed: 5
|
||||
baseSight: 10
|
||||
baseAttackRange: 2
|
||||
--- !u!1 &1862223349553492570
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -920,6 +920,7 @@ Transform:
|
||||
- {fileID: 946527919}
|
||||
- {fileID: 1701756768}
|
||||
- {fileID: 1166878644}
|
||||
- {fileID: 1247940084}
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &672563220
|
||||
@@ -2024,6 +2025,51 @@ Transform:
|
||||
m_Children: []
|
||||
m_Father: {fileID: 640318137}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &1247940083
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1247940084}
|
||||
- component: {fileID: 1247940085}
|
||||
m_Layer: 0
|
||||
m_Name: UpgradeDatabase
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &1247940084
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1247940083}
|
||||
serializedVersion: 2
|
||||
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: 640318137}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &1247940085
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1247940083}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 12780dc9ee390c742b6cbd405e59a916, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Northbound.UpgradeDatabase
|
||||
_upgradeDataList: []
|
||||
--- !u!224 &1282800775 stripped
|
||||
RectTransform:
|
||||
m_CorrespondingSourceObject: {fileID: 8873176760615364646, guid: a470599cc0481164ab487ecf39b1ebd0, type: 3}
|
||||
|
||||
8
Assets/ScriptableObjects/Upgrade.meta
Normal file
8
Assets/ScriptableObjects/Upgrade.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba53e8dca24fd4346a54d32e8358a2bc
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -9,8 +9,6 @@ namespace Northbound
|
||||
public class AttackAction : NetworkBehaviour, IAction
|
||||
{
|
||||
[Header("Attack Settings")]
|
||||
public float attackRange = 2f;
|
||||
public int attackDamage = 10;
|
||||
public float attackCooldown = 0.5f;
|
||||
public LayerMask attackableLayer = ~0;
|
||||
|
||||
@@ -33,12 +31,14 @@ namespace Northbound
|
||||
private EquipmentSocket _equipmentSocket;
|
||||
private bool _isAttacking = false;
|
||||
private bool _isWeaponEquipped = false;
|
||||
private PlayerStats _playerStats;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_animator = GetComponent<Animator>();
|
||||
_teamMember = GetComponent<ITeamMember>();
|
||||
_equipmentSocket = GetComponent<EquipmentSocket>();
|
||||
_playerStats = GetComponent<PlayerStats>();
|
||||
}
|
||||
|
||||
public bool CanExecute(ulong playerId)
|
||||
@@ -80,7 +80,7 @@ namespace Northbound
|
||||
private void PerformAttack()
|
||||
{
|
||||
Vector3 attackOrigin = attackPoint != null ? attackPoint.position : transform.position;
|
||||
Collider[] hits = Physics.OverlapSphere(attackOrigin, attackRange, attackableLayer);
|
||||
Collider[] hits = Physics.OverlapSphere(attackOrigin, GetAttackRange(), attackableLayer);
|
||||
|
||||
foreach (Collider hit in hits)
|
||||
{
|
||||
@@ -115,7 +115,7 @@ namespace Northbound
|
||||
if (NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(targetNetworkId, out NetworkObject targetObj))
|
||||
{
|
||||
var damageable = targetObj.GetComponent<IDamageable>();
|
||||
damageable?.TakeDamage(attackDamage, attackerNetworkId);
|
||||
damageable?.TakeDamage(_playerStats?.GetDamage() ?? 10, attackerNetworkId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ namespace Northbound
|
||||
{
|
||||
Vector3 attackOrigin = attackPoint != null ? attackPoint.position : transform.position;
|
||||
Gizmos.color = Color.red;
|
||||
Gizmos.DrawWireSphere(attackOrigin, attackRange);
|
||||
Gizmos.DrawWireSphere(attackOrigin, GetAttackRange());
|
||||
}
|
||||
|
||||
public override void OnDestroy()
|
||||
@@ -263,5 +263,10 @@ namespace Northbound
|
||||
}
|
||||
|
||||
public bool IsAttacking => _isAttacking;
|
||||
|
||||
/// <summary>
|
||||
/// 공격 범위 반환 (PlayerStats 우선)
|
||||
/// </summary>
|
||||
public float GetAttackRange() => _playerStats?.GetAttackRange() ?? 2f;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -61,7 +62,8 @@ namespace Northbound.Editor
|
||||
{ "Monster", new MonsterPrefabSetup() },
|
||||
{ "Creep", new CreepPrefabSetup() },
|
||||
{ "Tower", new TowerPrefabSetup() },
|
||||
{ "Player", new PlayerPrefabSetup() }
|
||||
{ "Player", new PlayerPrefabSetup() },
|
||||
{ "Upgrade", new UpgradePrefabSetup() }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -82,15 +84,20 @@ namespace Northbound.Editor
|
||||
}
|
||||
|
||||
IPrefabSetup prefabSetup = prefabSetups[typeName];
|
||||
|
||||
// Upgrade는 템플릿이 필요 없음
|
||||
GameObject template = null;
|
||||
if (typeName != "Upgrade")
|
||||
{
|
||||
string templateName = prefabSetup.GetTemplateName();
|
||||
string templatePath = $"Assets/Data/Templates/{templateName}.prefab";
|
||||
|
||||
GameObject template = AssetDatabase.LoadAssetAtPath<GameObject>(templatePath);
|
||||
template = AssetDatabase.LoadAssetAtPath<GameObject>(templatePath);
|
||||
if (template == null)
|
||||
{
|
||||
Debug.LogError($"[CSVToSOImporter] Template not found: {templatePath}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
string[] csvLines = File.ReadAllLines(csvPath);
|
||||
if (csvLines.Length < 2)
|
||||
@@ -123,7 +130,6 @@ namespace Northbound.Editor
|
||||
Debug.Log($"[CSVToSOImporter] {typeName}: {successCount} prefabs created/updated");
|
||||
}
|
||||
|
||||
// If towers were imported, auto-configure BuildingManager
|
||||
if (typeName == "Tower")
|
||||
{
|
||||
Debug.Log($"<color=cyan>[CSVToSOImporter] Tower import complete!</color>");
|
||||
@@ -134,8 +140,19 @@ namespace Northbound.Editor
|
||||
|
||||
private static bool CreatePrefabFromRow(string typeName, string[] headers, string[] values, GameObject template, IPrefabSetup prefabSetup)
|
||||
{
|
||||
string soPath = $"Assets/Data/ScriptableObjects/{typeName}";
|
||||
string soPath;
|
||||
if (typeName == "Upgrade")
|
||||
{
|
||||
// Upgrade는 Resources 폴더에 저장 (런타임 자동 로드용)
|
||||
soPath = "Assets/Resources/Data/ScriptableObjects/Upgrade";
|
||||
Directory.CreateDirectory(Path.Combine(Application.dataPath, "Resources/Data/ScriptableObjects/Upgrade"));
|
||||
}
|
||||
else
|
||||
{
|
||||
soPath = $"Assets/Data/ScriptableObjects/{typeName}";
|
||||
Directory.CreateDirectory(Path.Combine(Application.dataPath, $"ScriptableObjects/{typeName}"));
|
||||
}
|
||||
|
||||
|
||||
int id = 0;
|
||||
for (int i = 0; i < headers.Length && i < values.Length; i++)
|
||||
@@ -188,6 +205,11 @@ namespace Northbound.Editor
|
||||
PlayerPrefabSetup.UpdatePlayerPrefab((PlayerData)data);
|
||||
prefabObj = null;
|
||||
}
|
||||
else if (typeName == "Upgrade")
|
||||
{
|
||||
// Upgrade는 프리팹이 필요 없음
|
||||
prefabObj = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
string prefabPath = $"Assets/Prefabs/{typeName}/{typeName}{id}.prefab";
|
||||
@@ -219,7 +241,6 @@ namespace Northbound.Editor
|
||||
EditorUtility.SetDirty(data);
|
||||
}
|
||||
|
||||
// Force save assets to disk
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
@@ -236,7 +257,6 @@ namespace Northbound.Editor
|
||||
return;
|
||||
}
|
||||
|
||||
// Load TowerData
|
||||
string[] towerDataGuids = AssetDatabase.FindAssets("t:TowerData", new[] { "Assets/Data/ScriptableObjects" });
|
||||
List<TowerData> allTowers = new List<TowerData>();
|
||||
|
||||
@@ -302,6 +322,26 @@ namespace Northbound.Editor
|
||||
return type.IsValueType ? System.Activator.CreateInstance(type) : null;
|
||||
}
|
||||
|
||||
// List<T> 타입 처리 (세미콜론 구분)
|
||||
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
|
||||
{
|
||||
System.Type elementType = type.GetGenericArguments()[0];
|
||||
var elements = value.Split(';').Select(s => s.Trim()).Where(s => !string.IsNullOrEmpty(s)).ToList();
|
||||
|
||||
IList list = (IList)System.Activator.CreateInstance(type);
|
||||
|
||||
foreach (string element in elements)
|
||||
{
|
||||
object elementValue = ParseValue(element, elementType);
|
||||
if (elementValue != null)
|
||||
{
|
||||
list.Add(elementValue);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
if (type == typeof(int))
|
||||
{
|
||||
int result;
|
||||
|
||||
@@ -45,52 +45,38 @@ namespace Northbound.Editor
|
||||
|
||||
private static void SetupPrefabComponents(GameObject prefab, PlayerData playerData)
|
||||
{
|
||||
var networkController = prefab.GetComponent<NetworkPlayerController>();
|
||||
if (networkController != null)
|
||||
// PlayerStats에 모든 스탯 설정
|
||||
var playerStats = prefab.GetComponent<PlayerStats>();
|
||||
if (playerStats != null)
|
||||
{
|
||||
SerializedObject so = new SerializedObject(networkController);
|
||||
so.FindProperty("moveSpeed").floatValue = playerData.moveSpeed;
|
||||
so.FindProperty("maxHealth").intValue = playerData.maxHp;
|
||||
SerializedObject so = new SerializedObject(playerStats);
|
||||
so.FindProperty("baseMaxHp").intValue = playerData.maxHp;
|
||||
so.FindProperty("baseDamage").intValue = playerData.atkDamage;
|
||||
so.FindProperty("baseCapacity").intValue = playerData.capacity;
|
||||
so.FindProperty("baseManpower").floatValue = playerData.manpower;
|
||||
so.FindProperty("baseMoveSpeed").floatValue = playerData.moveSpeed;
|
||||
so.FindProperty("baseSight").floatValue = playerData.sight;
|
||||
so.FindProperty("baseAttackRange").floatValue = playerData.atkRange;
|
||||
so.ApplyModifiedProperties();
|
||||
Debug.Log($"[PlayerPrefabSetup] Updated NetworkPlayerController: moveSpeed={playerData.moveSpeed}, maxHealth={playerData.maxHp}");
|
||||
Debug.Log($"[PlayerPrefabSetup] Updated PlayerStats: " +
|
||||
$"maxHp={playerData.maxHp}, damage={playerData.atkDamage}, " +
|
||||
$"capacity={playerData.capacity}, manpower={playerData.manpower}, " +
|
||||
$"moveSpeed={playerData.moveSpeed}, sight={playerData.sight}, " +
|
||||
$"attackRange={playerData.atkRange}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"[PlayerPrefabSetup] PlayerStats component not found on prefab!");
|
||||
}
|
||||
|
||||
// AttackAction의 attackCooldown은 별도 설정 (스탯이 아님)
|
||||
var attackAction = prefab.GetComponent<AttackAction>();
|
||||
if (attackAction != null)
|
||||
{
|
||||
SerializedObject so = new SerializedObject(attackAction);
|
||||
so.FindProperty("attackRange").intValue = playerData.atkRange;
|
||||
so.FindProperty("attackDamage").intValue = playerData.atkDamage;
|
||||
so.FindProperty("attackCooldown").floatValue = playerData.atkIntervalSec;
|
||||
so.ApplyModifiedProperties();
|
||||
Debug.Log($"[PlayerPrefabSetup] Updated AttackAction: attackRange={playerData.atkRange}, attackDamage={playerData.atkDamage}, attackCooldown={playerData.atkIntervalSec}");
|
||||
}
|
||||
|
||||
var visionProvider = prefab.GetComponent<PlayerVisionProvider>();
|
||||
if (visionProvider != null)
|
||||
{
|
||||
SerializedObject so = new SerializedObject(visionProvider);
|
||||
so.FindProperty("visionRange").floatValue = playerData.sight;
|
||||
so.ApplyModifiedProperties();
|
||||
Debug.Log($"[PlayerPrefabSetup] Updated PlayerVisionProvider: visionRange={playerData.sight}");
|
||||
}
|
||||
|
||||
var resourceInventory = prefab.GetComponent<PlayerResourceInventory>();
|
||||
if (resourceInventory != null)
|
||||
{
|
||||
SerializedObject so = new SerializedObject(resourceInventory);
|
||||
so.FindProperty("maxResourceCapacity").intValue = playerData.capacity;
|
||||
so.ApplyModifiedProperties();
|
||||
Debug.Log($"[PlayerPrefabSetup] Updated PlayerResourceInventory: maxResourceCapacity={playerData.capacity}");
|
||||
}
|
||||
|
||||
var playerInteraction = prefab.GetComponent<PlayerInteraction>();
|
||||
if (playerInteraction != null)
|
||||
{
|
||||
SerializedObject so = new SerializedObject(playerInteraction);
|
||||
so.FindProperty("workPower").floatValue = playerData.manpower;
|
||||
so.ApplyModifiedProperties();
|
||||
Debug.Log($"[PlayerPrefabSetup] Updated PlayerInteraction: workPower={playerData.manpower}");
|
||||
Debug.Log($"[PlayerPrefabSetup] Updated AttackAction: attackCooldown={playerData.atkIntervalSec}");
|
||||
}
|
||||
|
||||
EditorUtility.SetDirty(prefab);
|
||||
|
||||
23
Assets/Scripts/Editor/UpgradePrefabSetup.cs
Normal file
23
Assets/Scripts/Editor/UpgradePrefabSetup.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using Northbound.Data;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Northbound.Editor
|
||||
{
|
||||
/// <summary>
|
||||
/// Upgrade 타입은 프리팹이 필요 없으므로 빈 구현
|
||||
/// </summary>
|
||||
public class UpgradePrefabSetup : IPrefabSetup
|
||||
{
|
||||
public string GetTemplateName()
|
||||
{
|
||||
return ""; // 템플릿 필요 없음
|
||||
}
|
||||
|
||||
public void SetupPrefab(GameObject prefab, ScriptableObject data)
|
||||
{
|
||||
// Upgrade는 프리팹이 필요 없음
|
||||
Debug.LogWarning($"[UpgradePrefabSetup] Upgrade 타입은 프리팹이 필요하지 않습니다.");
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/Editor/UpgradePrefabSetup.cs.meta
Normal file
2
Assets/Scripts/Editor/UpgradePrefabSetup.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f33f085cffff92c489c74fc11a89fa49
|
||||
@@ -9,15 +9,11 @@ using Northbound;
|
||||
public class NetworkPlayerController : NetworkBehaviour, ITeamMember, IDamageable
|
||||
{
|
||||
[Header("Movement Settings")]
|
||||
public float moveSpeed = 5f;
|
||||
public float rotationSpeed = 10f;
|
||||
|
||||
[Header("Team Settings")]
|
||||
[SerializeField] private TeamType initialTeam = TeamType.Player;
|
||||
|
||||
[Header("Health Settings")]
|
||||
[SerializeField] private int maxHealth = 100;
|
||||
|
||||
[Header("Visual Effects")]
|
||||
[SerializeField] private GameObject damageEffectPrefab;
|
||||
[SerializeField] private GameObject deathEffectPrefab;
|
||||
@@ -50,8 +46,11 @@ public class NetworkPlayerController : NetworkBehaviour, ITeamMember, IDamageabl
|
||||
private PlayerInputActions _inputActions;
|
||||
private Animator _animator;
|
||||
private NetworkAnimator _networkAnimator;
|
||||
private PlayerStats _playerStats;
|
||||
|
||||
// 이 플레이어가 로컬 플레이어인지 확인
|
||||
|
||||
|
||||
public bool IsLocalPlayer => _ownerPlayerId.Value == NetworkManager.Singleton.LocalClientId;
|
||||
|
||||
public ulong OwnerPlayerId => _ownerPlayerId.Value;
|
||||
@@ -64,6 +63,7 @@ public class NetworkPlayerController : NetworkBehaviour, ITeamMember, IDamageabl
|
||||
_controller = GetComponent<CharacterController>();
|
||||
_animator = GetComponent<Animator>();
|
||||
_networkAnimator = GetComponent<NetworkAnimator>();
|
||||
_playerStats = GetComponent<PlayerStats>();
|
||||
}
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
@@ -80,7 +80,7 @@ public class NetworkPlayerController : NetworkBehaviour, ITeamMember, IDamageabl
|
||||
|
||||
if (_currentHealth.Value == 0)
|
||||
{
|
||||
_currentHealth.Value = maxHealth;
|
||||
_currentHealth.Value = GetMaxHealth();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ public class NetworkPlayerController : NetworkBehaviour, ITeamMember, IDamageabl
|
||||
|
||||
if (_controller != null)
|
||||
{
|
||||
_controller.Move(move * moveSpeed * Time.deltaTime);
|
||||
_controller.Move(move * (_playerStats?.GetMoveSpeed() ?? 5f) * Time.deltaTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -376,7 +376,7 @@ public class NetworkPlayerController : NetworkBehaviour, ITeamMember, IDamageabl
|
||||
if (!IsServer) return;
|
||||
|
||||
// 체력 회복
|
||||
_currentHealth.Value = maxHealth;
|
||||
_currentHealth.Value = GetMaxHealth();
|
||||
|
||||
// 스폰 포인트로 이동
|
||||
var spawnPoints = FindObjectsByType<PlayerSpawnPoint>(FindObjectsSortMode.None);
|
||||
@@ -423,11 +423,12 @@ public class NetworkPlayerController : NetworkBehaviour, ITeamMember, IDamageabl
|
||||
|
||||
public int GetCurrentHealth() => _currentHealth.Value;
|
||||
|
||||
public int GetMaxHealth() => maxHealth;
|
||||
public int GetMaxHealth() => _playerStats?.GetMaxHp() ?? 100;
|
||||
|
||||
public float GetHealthPercentage()
|
||||
{
|
||||
return maxHealth > 0 ? (float)_currentHealth.Value / maxHealth : 0f;
|
||||
int max = GetMaxHealth();
|
||||
return max > 0 ? (float)_currentHealth.Value / max : 0f;
|
||||
}
|
||||
|
||||
public bool IsDead() => _currentHealth.Value <= 0;
|
||||
@@ -436,7 +437,7 @@ public class NetworkPlayerController : NetworkBehaviour, ITeamMember, IDamageabl
|
||||
{
|
||||
if (!IsServer) return;
|
||||
|
||||
int healAmount = Mathf.Min(amount, maxHealth - _currentHealth.Value);
|
||||
int healAmount = Mathf.Min(amount, GetMaxHealth() - _currentHealth.Value);
|
||||
_currentHealth.Value += healAmount;
|
||||
}
|
||||
|
||||
@@ -459,13 +460,13 @@ public class NetworkPlayerController : NetworkBehaviour, ITeamMember, IDamageabl
|
||||
{
|
||||
string teamName = TeamManager.GetTeamName(_team.Value);
|
||||
UnityEditor.Handles.Label(transform.position + Vector3.up * 3f,
|
||||
$"Player: {gameObject.name}\nTeam: {teamName}\nHP: {_currentHealth.Value}/{maxHealth}");
|
||||
$"Player: {gameObject.name}\nTeam: {teamName}\nHP: {_currentHealth.Value}/{GetMaxHealth()}");
|
||||
}
|
||||
else
|
||||
{
|
||||
string teamName = TeamManager.GetTeamName(initialTeam);
|
||||
UnityEditor.Handles.Label(transform.position + Vector3.up * 3f,
|
||||
$"Player: {gameObject.name}\nTeam: {teamName}\nHP: {maxHealth}/{maxHealth}");
|
||||
$"Player: {gameObject.name}\nTeam: {teamName}");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Northbound
|
||||
[Header("Interaction Settings")]
|
||||
public float interactionRange = 3f;
|
||||
public LayerMask interactableLayer = ~0;
|
||||
public float workPower = 10f;
|
||||
|
||||
|
||||
[Header("Detection")]
|
||||
public Transform rayOrigin;
|
||||
@@ -47,9 +47,10 @@ namespace Northbound
|
||||
private Coroutine _interactionTimeoutCoroutine;
|
||||
|
||||
private NetworkPlayerController _networkPlayerController;
|
||||
private PlayerStats _playerStats;
|
||||
|
||||
public bool IsInteracting => _isInteracting;
|
||||
public float WorkPower => workPower;
|
||||
public float WorkPower => _playerStats?.GetManpower() ?? 10f;
|
||||
public IInteractable CurrentUnavailableInteractable => _unavailableInteractable;
|
||||
|
||||
// 로컬 플레이어인지 확인
|
||||
@@ -60,6 +61,8 @@ namespace Northbound
|
||||
{
|
||||
_networkPlayerController = GetComponent<NetworkPlayerController>();
|
||||
_networkAnimator = GetComponent<NetworkAnimator>();
|
||||
_playerStats = GetComponent<PlayerStats>();
|
||||
|
||||
}
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
|
||||
@@ -5,13 +5,13 @@ namespace Northbound
|
||||
{
|
||||
public class PlayerResourceInventory : NetworkBehaviour
|
||||
{
|
||||
public int maxResourceCapacity = 100;
|
||||
private int _displayAmount = 0;
|
||||
|
||||
public int CurrentResourceAmount => _displayAmount;
|
||||
public int MaxResourceCapacity => maxResourceCapacity;
|
||||
public int MaxResourceCapacity => _playerStats?.GetCapacity() ?? 100;
|
||||
|
||||
private NetworkPlayerController _networkPlayerController;
|
||||
private PlayerStats _playerStats;
|
||||
|
||||
private bool IsLocalPlayer => _networkPlayerController != null && _networkPlayerController.IsLocalPlayer;
|
||||
private ulong LocalPlayerId => _networkPlayerController != null ? _networkPlayerController.OwnerPlayerId : OwnerClientId;
|
||||
@@ -19,6 +19,7 @@ namespace Northbound
|
||||
private void Awake()
|
||||
{
|
||||
_networkPlayerController = GetComponent<NetworkPlayerController>();
|
||||
_playerStats = GetComponent<PlayerStats>();
|
||||
}
|
||||
|
||||
[Rpc(SendTo.Server)]
|
||||
@@ -33,7 +34,6 @@ namespace Northbound
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
// _ownerPlayerId 변경 이벤트 구독
|
||||
if (_networkPlayerController != null)
|
||||
{
|
||||
_networkPlayerController.OnOwnerChanged += OnOwnerPlayerIdChanged;
|
||||
@@ -51,7 +51,7 @@ namespace Northbound
|
||||
{
|
||||
if (!IsLocalPlayer) return;
|
||||
|
||||
SetMaxCapacityServerRpc(maxResourceCapacity, LocalPlayerId);
|
||||
SetMaxCapacityServerRpc(MaxResourceCapacity, LocalPlayerId);
|
||||
RequestResourceUpdateServerRpc(LocalPlayerId);
|
||||
}
|
||||
|
||||
|
||||
144
Assets/Scripts/PlayerStats.cs
Normal file
144
Assets/Scripts/PlayerStats.cs
Normal file
@@ -0,0 +1,144 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Northbound.Data;
|
||||
|
||||
namespace Northbound
|
||||
{
|
||||
/// <summary>
|
||||
/// 플레이어 스탯 계산 컴포넌트
|
||||
/// 기본 스탯 + 업그레이드 보너스를 계산하여 반환
|
||||
/// </summary>
|
||||
public class PlayerStats : MonoBehaviour
|
||||
{
|
||||
[Header("Base Stats")]
|
||||
[SerializeField] private int baseMaxHp = 100;
|
||||
[SerializeField] private int baseDamage = 10;
|
||||
[SerializeField] private int baseCapacity = 100;
|
||||
[SerializeField] private float baseManpower = 10f;
|
||||
[SerializeField] private float baseMoveSpeed = 5f;
|
||||
[SerializeField] private float baseSight = 10f;
|
||||
[SerializeField] private float baseAttackRange = 2f;
|
||||
|
||||
private PlayerUpgradeManager _upgradeManager;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_upgradeManager = GetComponent<PlayerUpgradeManager>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 특정 스탯에 대한 업그레이드 보너스 계산 (ADD만 지원)
|
||||
/// </summary>
|
||||
private float CalculateStatBonus(string statName)
|
||||
{
|
||||
float bonus = 0f;
|
||||
|
||||
if (_upgradeManager == null)
|
||||
return bonus;
|
||||
|
||||
var ownedUpgrades = _upgradeManager.GetOwnedUpgradeData();
|
||||
|
||||
foreach (var upgrade in ownedUpgrades)
|
||||
{
|
||||
if (upgrade == null) continue;
|
||||
|
||||
// effectStatList에서 해당 스탯 찾기
|
||||
for (int i = 0; i < upgrade.effectStatList.Count; i++)
|
||||
{
|
||||
if (i >= upgrade.effectOpList.Count || i >= upgrade.effectValueList.Count)
|
||||
continue;
|
||||
|
||||
if (upgrade.effectStatList[i] == statName)
|
||||
{
|
||||
string op = upgrade.effectOpList[i];
|
||||
float value = upgrade.effectValueList[i];
|
||||
|
||||
// ADD 연산만 지원
|
||||
if (op == "add")
|
||||
{
|
||||
bonus += value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bonus;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 최대 체력 반환
|
||||
/// </summary>
|
||||
public int GetMaxHp()
|
||||
{
|
||||
float bonus = CalculateStatBonus("player_max_hp");
|
||||
return baseMaxHp + (int)bonus;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 공격력 반환
|
||||
/// </summary>
|
||||
public int GetDamage()
|
||||
{
|
||||
float bonus = CalculateStatBonus("player_atk_damage");
|
||||
return baseDamage + (int)bonus;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 자원 용량 반환
|
||||
/// </summary>
|
||||
public int GetCapacity()
|
||||
{
|
||||
float bonus = CalculateStatBonus("player_capacity");
|
||||
return baseCapacity + (int)bonus;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 노동력(건설/채굴 작업량) 반환
|
||||
/// </summary>
|
||||
public float GetManpower()
|
||||
{
|
||||
float bonus = CalculateStatBonus("player_manpower");
|
||||
return baseManpower + bonus;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 이동 속도 반환
|
||||
/// </summary>
|
||||
public float GetMoveSpeed()
|
||||
{
|
||||
float bonus = CalculateStatBonus("player_move_speed");
|
||||
// move_speed는 mul 연산이지만, 우선 ADD만 지원하므로 add로 처리
|
||||
return baseMoveSpeed + bonus;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 시야 범위 반환
|
||||
/// </summary>
|
||||
public float GetSight()
|
||||
{
|
||||
float bonus = CalculateStatBonus("player_sight");
|
||||
return baseSight + bonus;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 공격 범위 반환
|
||||
/// </summary>
|
||||
public float GetAttackRange()
|
||||
{
|
||||
float bonus = CalculateStatBonus("player_atk_range");
|
||||
return baseAttackRange + bonus;
|
||||
}
|
||||
|
||||
#region Base Stat Setters (에디터/초기화용)
|
||||
|
||||
public void SetBaseMaxHp(int value) => baseMaxHp = value;
|
||||
public void SetBaseDamage(int value) => baseDamage = value;
|
||||
public void SetBaseCapacity(int value) => baseCapacity = value;
|
||||
public void SetBaseManpower(float value) => baseManpower = value;
|
||||
public void SetBaseMoveSpeed(float value) => baseMoveSpeed = value;
|
||||
public void SetBaseSight(float value) => baseSight = value;
|
||||
public void SetBaseAttackRange(float value) => baseAttackRange = value;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/PlayerStats.cs.meta
Normal file
2
Assets/Scripts/PlayerStats.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6aa26fe48ebdaae438d465df7c6a3bef
|
||||
269
Assets/Scripts/PlayerUpgradeManager.cs
Normal file
269
Assets/Scripts/PlayerUpgradeManager.cs
Normal file
@@ -0,0 +1,269 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
using Northbound.Data;
|
||||
|
||||
namespace Northbound
|
||||
{
|
||||
/// <summary>
|
||||
/// 플레이어별 업그레이드 보유 상태를 관리하는 컴포넌트
|
||||
/// </summary>
|
||||
public class PlayerUpgradeManager : NetworkBehaviour
|
||||
{
|
||||
// 보유한 업그레이드 ID 목록 (네트워크 동기화)
|
||||
private NetworkList<int> _ownedUpgradeIds;
|
||||
|
||||
// 이벤트
|
||||
public event Action<int> OnUpgradePurchased; // upgradeId
|
||||
|
||||
private NetworkPlayerController _networkPlayerController;
|
||||
|
||||
public new bool IsLocalPlayer => _networkPlayerController != null && _networkPlayerController.IsLocalPlayer;
|
||||
public ulong OwnerPlayerId => _networkPlayerController != null ? _networkPlayerController.OwnerPlayerId : OwnerClientId;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_ownedUpgradeIds = new NetworkList<int>();
|
||||
_networkPlayerController = GetComponent<NetworkPlayerController>();
|
||||
}
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
base.OnNetworkSpawn();
|
||||
|
||||
if (_networkPlayerController != null)
|
||||
{
|
||||
_networkPlayerController.OnOwnerChanged += OnOwnerChanged;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnNetworkDespawn()
|
||||
{
|
||||
base.OnNetworkDespawn();
|
||||
|
||||
if (_networkPlayerController != null)
|
||||
{
|
||||
_networkPlayerController.OnOwnerChanged -= OnOwnerChanged;
|
||||
}
|
||||
|
||||
_ownedUpgradeIds.Dispose();
|
||||
}
|
||||
|
||||
private void OnOwnerChanged(ulong newOwnerId)
|
||||
{
|
||||
// 소유자 변경 시 필요한 처리
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 보유한 업그레이드 ID 목록 (복사본 반환)
|
||||
/// </summary>
|
||||
public List<int> GetOwnedUpgradeIdList()
|
||||
{
|
||||
var list = new List<int>();
|
||||
foreach (int id in _ownedUpgradeIds)
|
||||
{
|
||||
list.Add(id);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 특정 업그레이드를 보유하고 있는지 확인
|
||||
/// </summary>
|
||||
public bool HasUpgrade(int upgradeId)
|
||||
{
|
||||
foreach (int id in _ownedUpgradeIds)
|
||||
{
|
||||
if (id == upgradeId)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 보유한 업그레이드 ID를 HashSet으로 반환
|
||||
/// </summary>
|
||||
public HashSet<int> GetOwnedUpgradeIdSet()
|
||||
{
|
||||
var set = new HashSet<int>();
|
||||
foreach (int id in _ownedUpgradeIds)
|
||||
{
|
||||
set.Add(id);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 업그레이드 구매 요청 (클라이언트에서 호출)
|
||||
/// </summary>
|
||||
public void RequestPurchaseUpgrade(int upgradeId)
|
||||
{
|
||||
PurchaseUpgradeServerRpc(upgradeId);
|
||||
}
|
||||
|
||||
[Rpc(SendTo.Server, InvokePermission = RpcInvokePermission.Everyone)]
|
||||
private void PurchaseUpgradeServerRpc(int upgradeId)
|
||||
{
|
||||
if (!CanPurchaseUpgrade(upgradeId, out string failReason))
|
||||
{
|
||||
Debug.LogWarning($"[PlayerUpgradeManager] 업그레이드 구매 실패: {failReason}");
|
||||
return;
|
||||
}
|
||||
|
||||
// 업그레이드 데이터 가져오기
|
||||
var upgrade = UpgradeDatabase.Instance?.GetUpgradeById(upgradeId);
|
||||
if (upgrade == null)
|
||||
{
|
||||
Debug.LogError($"[PlayerUpgradeManager] 업그레이드 ID {upgradeId}를 찾을 수 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 비용 차감
|
||||
var core = CoreResourceManager.Instance?.mainCore;
|
||||
if (core == null)
|
||||
{
|
||||
Debug.LogError("[PlayerUpgradeManager] 코어를 찾을 수 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!core.CanConsumeResource(upgrade.mana))
|
||||
{
|
||||
Debug.LogWarning($"[PlayerUpgradeManager] 자원이 부족합니다. 필요: {upgrade.mana}");
|
||||
return;
|
||||
}
|
||||
|
||||
core.ConsumeResourceServerRpc(upgrade.mana);
|
||||
|
||||
// 업그레이드 추가
|
||||
_ownedUpgradeIds.Add(upgradeId);
|
||||
|
||||
Debug.Log($"<color=green>[PlayerUpgradeManager] 업그레이드 '{upgrade.memo}' 구매 완료! (ID: {upgradeId})</color>");
|
||||
|
||||
// 이벤트 발생
|
||||
OnUpgradePurchased?.Invoke(upgradeId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 업그레이드 구매 가능 여부 확인
|
||||
/// </summary>
|
||||
private bool CanPurchaseUpgrade(int upgradeId, out string failReason)
|
||||
{
|
||||
failReason = string.Empty;
|
||||
|
||||
var upgradeDatabase = UpgradeDatabase.Instance;
|
||||
if (upgradeDatabase == null)
|
||||
{
|
||||
failReason = "UpgradeDatabase가 초기화되지 않았습니다.";
|
||||
return false;
|
||||
}
|
||||
|
||||
var upgrade = upgradeDatabase.GetUpgradeById(upgradeId);
|
||||
if (upgrade == null)
|
||||
{
|
||||
failReason = $"업그레이드 ID {upgradeId}를 찾을 수 없습니다.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// 이미 보유 중인지 확인
|
||||
if (HasUpgrade(upgradeId))
|
||||
{
|
||||
failReason = "이미 보유한 업그레이드입니다.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// 선행 조건 확인
|
||||
if (!upgradeDatabase.ArePrerequisitesMet(upgradeId, GetOwnedUpgradeIdSet()))
|
||||
{
|
||||
failReason = "선행 업그레이드 조건을 충족하지 않았습니다.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// 비용 확인
|
||||
var core = CoreResourceManager.Instance?.mainCore;
|
||||
if (core == null)
|
||||
{
|
||||
failReason = "코어를 찾을 수 없습니다.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!core.CanConsumeResource(upgrade.mana))
|
||||
{
|
||||
failReason = $"자원이 부족합니다. 필요: {upgrade.mana}, 보유: {core.TotalResources}";
|
||||
return false;
|
||||
}
|
||||
|
||||
// 개인 업그레이드인지 확인
|
||||
if (upgrade.upgradeTarget != "person")
|
||||
{
|
||||
failReason = "팀 업그레이드는 개인이 구매할 수 없습니다.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 업그레이드 구매 가능 여부 (외부용)
|
||||
/// </summary>
|
||||
public bool CanPurchase(int upgradeId)
|
||||
{
|
||||
return CanPurchaseUpgrade(upgradeId, out _);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 구매 가능한 업그레이드 목록 반환
|
||||
/// </summary>
|
||||
public List<UpgradeData> GetPurchasableUpgrades()
|
||||
{
|
||||
var result = new List<UpgradeData>();
|
||||
var upgradeDatabase = UpgradeDatabase.Instance;
|
||||
|
||||
if (upgradeDatabase == null) return result;
|
||||
|
||||
var personalUpgrades = upgradeDatabase.GetPersonalUpgrades();
|
||||
var ownedIds = GetOwnedUpgradeIdSet();
|
||||
|
||||
foreach (var upgrade in personalUpgrades)
|
||||
{
|
||||
if (upgrade == null) continue;
|
||||
|
||||
// 이미 보유하면 제외
|
||||
if (ownedIds.Contains(upgrade.id)) continue;
|
||||
|
||||
// 선행 조건 충족 시 구매 가능
|
||||
if (upgradeDatabase.ArePrerequisitesMet(upgrade.id, ownedIds))
|
||||
{
|
||||
result.Add(upgrade);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 보유한 업그레이드 데이터 목록 반환
|
||||
/// </summary>
|
||||
public List<UpgradeData> GetOwnedUpgradeData()
|
||||
{
|
||||
var result = new List<UpgradeData>();
|
||||
var upgradeDatabase = UpgradeDatabase.Instance;
|
||||
|
||||
if (upgradeDatabase == null) return result;
|
||||
|
||||
foreach (int id in _ownedUpgradeIds)
|
||||
{
|
||||
var upgrade = upgradeDatabase.GetUpgradeById(id);
|
||||
if (upgrade != null)
|
||||
{
|
||||
result.Add(upgrade);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/PlayerUpgradeManager.cs.meta
Normal file
2
Assets/Scripts/PlayerUpgradeManager.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c2399ad44b71131439123eaec84abb08
|
||||
@@ -8,11 +8,11 @@ namespace Northbound
|
||||
/// </summary>
|
||||
public class PlayerVisionProvider : NetworkBehaviour, IVisionProvider
|
||||
{
|
||||
[Header("Vision Settings")]
|
||||
public float visionRange = 10f;
|
||||
private PlayerStats _playerStats;
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
_playerStats = GetComponent<PlayerStats>();
|
||||
if (IsServer)
|
||||
{
|
||||
FogOfWarSystem.Instance?.RegisterVisionProvider(this);
|
||||
@@ -28,14 +28,14 @@ namespace Northbound
|
||||
}
|
||||
|
||||
public ulong GetOwnerId() => OwnerClientId;
|
||||
public float GetVisionRange() => visionRange;
|
||||
public float GetVisionRange() => _playerStats?.GetSight() ?? 10f;
|
||||
public Transform GetTransform() => transform;
|
||||
public bool IsActive() => IsSpawned;
|
||||
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
Gizmos.color = Color.yellow;
|
||||
Gizmos.DrawWireSphere(transform.position, visionRange);
|
||||
Gizmos.DrawWireSphere(transform.position, GetVisionRange());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -334,13 +334,21 @@ namespace Northbound
|
||||
return;
|
||||
|
||||
int playerAvailableSpace = resourceManager.GetAvailableSpace(playerId);
|
||||
// 플레이어의 작업량 가져오기
|
||||
float playerWorkPower = GetPlayerWorkPower(playerId);
|
||||
|
||||
int gatheredAmount = Mathf.Min(
|
||||
resourcesPerGathering,
|
||||
(int)playerWorkPower,
|
||||
_currentResources.Value,
|
||||
playerAvailableSpace
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (gatheredAmount <= 0)
|
||||
{
|
||||
return;
|
||||
@@ -411,8 +419,30 @@ namespace Northbound
|
||||
{
|
||||
return transform;
|
||||
}
|
||||
/// <summary>
|
||||
/// 플레이어의 작업량 가져오기 (PlayerInteraction.WorkPower)
|
||||
/// </summary>
|
||||
private float GetPlayerWorkPower(ulong playerId)
|
||||
{
|
||||
// PlayerInteraction 컴포넌트에서 workPower 가져오기
|
||||
if (NetworkManager.Singleton != null && NetworkManager.Singleton.ConnectedClients.TryGetValue(playerId, out var client))
|
||||
{
|
||||
if (client.PlayerObject != null)
|
||||
{
|
||||
var playerInteraction = client.PlayerObject.GetComponent<PlayerInteraction>();
|
||||
if (playerInteraction != null)
|
||||
{
|
||||
return playerInteraction.WorkPower;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 기본값: 10
|
||||
return 10f;
|
||||
}
|
||||
|
||||
private Worker FindWorkerForPlayer(ulong playerId)
|
||||
|
||||
{
|
||||
if (NetworkManager.Singleton == null || NetworkManager.Singleton.SpawnManager == null)
|
||||
{
|
||||
|
||||
177
Assets/Scripts/UpgradeDatabase.cs
Normal file
177
Assets/Scripts/UpgradeDatabase.cs
Normal file
@@ -0,0 +1,177 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Northbound.Data;
|
||||
|
||||
namespace Northbound
|
||||
{
|
||||
/// <summary>
|
||||
/// 업그레이드 데이터를 자동으로 로드하고 관리하는 싱글톤
|
||||
/// Resources 폴더에서 모든 UpgradeData를 자동으로 로드
|
||||
/// </summary>
|
||||
public class UpgradeDatabase : MonoBehaviour
|
||||
{
|
||||
private static UpgradeDatabase _instance;
|
||||
public static UpgradeDatabase Instance => _instance;
|
||||
|
||||
// Resources에서 자동 로드된 데이터
|
||||
private List<UpgradeData> _upgradeDataList = new List<UpgradeData>();
|
||||
|
||||
// 조회용 딕셔너리
|
||||
private Dictionary<int, UpgradeData> _upgradeById = new Dictionary<int, UpgradeData>();
|
||||
private Dictionary<string, List<UpgradeData>> _upgradesByCategory = new Dictionary<string, List<UpgradeData>>();
|
||||
|
||||
// Resources 경로
|
||||
private const string UPGRADE_RESOURCES_PATH = "Data/ScriptableObjects/Upgrade";
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (_instance != null && _instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
_instance = this;
|
||||
LoadUpgradeData();
|
||||
BuildLookupTables();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resources에서 모든 UpgradeData 자동 로드
|
||||
/// </summary>
|
||||
private void LoadUpgradeData()
|
||||
{
|
||||
_upgradeDataList.Clear();
|
||||
|
||||
var upgrades = Resources.LoadAll<UpgradeData>(UPGRADE_RESOURCES_PATH);
|
||||
_upgradeDataList.AddRange(upgrades);
|
||||
|
||||
Debug.Log($"[UpgradeDatabase] {_upgradeDataList.Count}개의 업그레이드 데이터를 로드했습니다.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 조회용 테이블 구축
|
||||
/// </summary>
|
||||
private void BuildLookupTables()
|
||||
{
|
||||
_upgradeById.Clear();
|
||||
_upgradesByCategory.Clear();
|
||||
|
||||
foreach (var upgrade in _upgradeDataList)
|
||||
{
|
||||
if (upgrade == null) continue;
|
||||
|
||||
// ID로 조회
|
||||
if (!_upgradeById.ContainsKey(upgrade.id))
|
||||
{
|
||||
_upgradeById[upgrade.id] = upgrade;
|
||||
}
|
||||
|
||||
// 카테고리로 조회
|
||||
string category = upgrade.upgradeCategory;
|
||||
if (!_upgradesByCategory.ContainsKey(category))
|
||||
{
|
||||
_upgradesByCategory[category] = new List<UpgradeData>();
|
||||
}
|
||||
_upgradesByCategory[category].Add(upgrade);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 데이터 다시 로드 (에디터에서 데이터 변경 시 호출)
|
||||
/// </summary>
|
||||
public void ReloadData()
|
||||
{
|
||||
LoadUpgradeData();
|
||||
BuildLookupTables();
|
||||
}
|
||||
|
||||
#region Getters
|
||||
|
||||
/// <summary>
|
||||
/// ID로 업그레이드 데이터 조회
|
||||
/// </summary>
|
||||
public UpgradeData GetUpgradeById(int id)
|
||||
{
|
||||
if (_upgradeById.TryGetValue(id, out var upgrade))
|
||||
{
|
||||
return upgrade;
|
||||
}
|
||||
Debug.LogWarning($"[UpgradeDatabase] ID {id}에 해당하는 업그레이드를 찾을 수 없습니다.");
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 카테고리로 업그레이드 목록 조회
|
||||
/// </summary>
|
||||
public List<UpgradeData> GetUpgradesByCategory(string category)
|
||||
{
|
||||
if (_upgradesByCategory.TryGetValue(category, out var upgrades))
|
||||
{
|
||||
return new List<UpgradeData>(upgrades);
|
||||
}
|
||||
return new List<UpgradeData>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 개인 업그레이드 목록 조회
|
||||
/// </summary>
|
||||
public List<UpgradeData> GetPersonalUpgrades()
|
||||
{
|
||||
var result = new List<UpgradeData>();
|
||||
foreach (var upgrade in _upgradeDataList)
|
||||
{
|
||||
if (upgrade != null && upgrade.upgradeTarget == "person")
|
||||
{
|
||||
result.Add(upgrade);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 팀 업그레이드 목록 조회
|
||||
/// </summary>
|
||||
public List<UpgradeData> GetTeamUpgrades()
|
||||
{
|
||||
var result = new List<UpgradeData>();
|
||||
foreach (var upgrade in _upgradeDataList)
|
||||
{
|
||||
if (upgrade != null && upgrade.upgradeTarget == "share")
|
||||
{
|
||||
result.Add(upgrade);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 모든 업그레이드 데이터 반환
|
||||
/// </summary>
|
||||
public List<UpgradeData> GetAllUpgrades()
|
||||
{
|
||||
return new List<UpgradeData>(_upgradeDataList);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 선행 업그레이드 조건 충족 여부 확인
|
||||
/// </summary>
|
||||
public bool ArePrerequisitesMet(int upgradeId, HashSet<int> ownedUpgradeIds)
|
||||
{
|
||||
var upgrade = GetUpgradeById(upgradeId);
|
||||
if (upgrade == null) return false;
|
||||
|
||||
foreach (int requiredId in upgrade.requireUpgradeId)
|
||||
{
|
||||
if (!ownedUpgradeIds.Contains(requiredId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/UpgradeDatabase.cs.meta
Normal file
2
Assets/Scripts/UpgradeDatabase.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 12780dc9ee390c742b6cbd405e59a916
|
||||
@@ -1,6 +1,6 @@
|
||||
id,memo,move_speed,max_hp,sight,atk_range,atk_damage,atk_interval_sec,cost,weight,model_path,animation_controller_path,wave_min,wave_max
|
||||
101,Grunt(기본),6.7,75,6,1,3,1.2,3,1,Assets/Models/Skeleton_Minion.fbx,Assets/Animations/MonsterAnimationController.controller,1,10
|
||||
101,Grunt(기본),6.7,75,6,1,3,1.2,3,1.0,Assets/Models/Skeleton_Minion.fbx,Assets/Animations/MonsterAnimationController.controller,1,10
|
||||
102,Tank(느림/단단),3.3,125,6,1,4,1.5,5,0.5,Assets/Models/Druid.fbx,Assets/Animations/MonsterAnimationController.controller,3,15
|
||||
103,Ranged(원거리/약함),5.3,65,6,5,2,1.4,3,0.2,Assets/Models/Skeleton_Warrior.fbx,Assets/Animations/MonsterAnimationController.controller,3,20
|
||||
104,Fast(빠름/약함),8.6,45,6,1,2,1,3,0.333,Assets/Models/Skeleton_Rogue.fbx,Assets/Animations/MonsterAnimationController.controller,3,20
|
||||
104,Fast(빠름/약함),8.6,45,6,1,2,1.0,3,0.333,Assets/Models/Skeleton_Rogue.fbx,Assets/Animations/MonsterAnimationController.controller,3,20
|
||||
105,Elite(소수 정예),6.6,100,6,1,7,1.3,6,0.1,Assets/Models/Barbarian_Large.fbx,Assets/Animations/MonsterAnimationController.controller,5,20
|
||||
|
||||
|
@@ -1,12 +1,12 @@
|
||||
id,memo,building_name,level,upgrade_to,tower_type,mana,manpower,size_x,size_y,size_z,max_hp,sight,atk_range,atk_damage,atk_interval_sec,model_path
|
||||
1,타워,Arrow Tower Lv.1,1,2,attack,100,10,4,10,4,50,10,5,3,2,Assets/Models/building_tower_B_blue.fbx
|
||||
2,타워,Arrow Tower Lv.2,2,3,attack,200,20,4,10,4,75,10,10,6,2,Assets/Models/building_tower_B_blue.fbx
|
||||
3,타워,Arrow Tower Lv.3,3,4,attack,300,30,4,10,4,100,15,10,9,2,Assets/Models/building_tower_B_blue.fbx
|
||||
4,타워,Arrow Tower Lv.4,4,5,attack,400,40,4,10,4,150,15,15,12,2,Assets/Models/building_tower_B_blue.fbx
|
||||
1,타워,Arrow Tower Lv.1,1,2.0,attack,100,10,4,10,4,50,10,5,3,2,Assets/Models/building_tower_B_blue.fbx
|
||||
2,타워,Arrow Tower Lv.2,2,3.0,attack,200,20,4,10,4,75,10,10,6,2,Assets/Models/building_tower_B_blue.fbx
|
||||
3,타워,Arrow Tower Lv.3,3,4.0,attack,300,30,4,10,4,100,15,10,9,2,Assets/Models/building_tower_B_blue.fbx
|
||||
4,타워,Arrow Tower Lv.4,4,5.0,attack,400,40,4,10,4,150,15,15,12,2,Assets/Models/building_tower_B_blue.fbx
|
||||
5,타워,Arrow Tower Lv.5,5,,attack,500,50,4,10,4,200,20,15,15,2,Assets/Models/building_tower_B_blue.fbx
|
||||
6,벽,Wall Lv.1,1,7,defense,10,10,8,4,3,30,1,0,0,0,Assets/Models/wall_straight.fbx
|
||||
7,벽,Wall Lv.2,2,8,defense,30,10,8,4,3,30,1,0,0,0,Assets/Models/wall_straight.fbx
|
||||
8,벽,Wall Lv.3,3,9,defense,50,20,8,4,3,30,1,0,0,0,Assets/Models/wall_straight.fbx
|
||||
9,벽,Wall Lv.4,4,10,defense,100,20,8,4,3,30,1,0,0,0,Assets/Models/wall_straight.fbx
|
||||
6,벽,Wall Lv.1,1,7.0,defense,10,10,8,4,3,30,1,0,0,0,Assets/Models/wall_straight.fbx
|
||||
7,벽,Wall Lv.2,2,8.0,defense,30,10,8,4,3,30,1,0,0,0,Assets/Models/wall_straight.fbx
|
||||
8,벽,Wall Lv.3,3,9.0,defense,50,20,8,4,3,30,1,0,0,0,Assets/Models/wall_straight.fbx
|
||||
9,벽,Wall Lv.4,4,10.0,defense,100,20,8,4,3,30,1,0,0,0,Assets/Models/wall_straight.fbx
|
||||
10,벽,Wall Lv.5,5,,defense,150,20,8,4,3,30,1,0,0,0,Assets/Models/wall_straight.fbx
|
||||
11,와드,Ward Lv.1,1,,sight,10,10,1,1,1,10,5,0,0,0,Assets/Models/torch.fbx
|
||||
|
||||
|
Reference in New Issue
Block a user