diff --git a/Assets/Resources/BalanceConfig.asset b/Assets/Resources/BalanceConfig.asset
index 0331bd1f..bf286e57 100644
--- a/Assets/Resources/BalanceConfig.asset
+++ b/Assets/Resources/BalanceConfig.asset
@@ -69,13 +69,16 @@ MonoBehaviour:
minDragDistance: 0.35
finalHitTolerance: 0.15
moveSpeed: 9
- boardSize: {x: 12, y: 16}
+ boardSize: {x: 20, y: 32}
+ cameraViewHeight: 18
+ cameraMinViewHeight: 10
+ cameraMaxViewHeight: 36
playerSpawnPoints:
- - {x: -4, y: -5.5}
- - {x: -2, y: -5.5}
- - {x: 0, y: -5.5}
- - {x: 2, y: -5.5}
- - {x: 4, y: -5.5}
+ - {x: -4, y: -13}
+ - {x: -2, y: -13}
+ - {x: 0, y: -13}
+ - {x: 2, y: -13}
+ - {x: 4, y: -13}
heroes:
- name: "\uC720\uBE44"
type: 0
@@ -101,184 +104,236 @@ MonoBehaviour:
- title: "\uD669\uAC74\uC801\uC758 \uB09C"
subtitle: "184\uB144"
aiAccuracy: 0.5
+ aiAggroRange: 11
enemies:
- name: "\uD669\uAC74\uC801 \uBCF4\uBCD1"
type: 0
- position: {x: -3.5, y: 2.5}
+ position: {x: -3, y: -6}
hpMult: 1
atkMult: 1
isBoss: 0
- name: "\uD669\uAC74\uC801 \uBCF4\uBCD1"
type: 0
- position: {x: 3.5, y: 2.5}
+ position: {x: 3, y: -6}
hpMult: 1
atkMult: 1
isBoss: 0
- name: "\uD669\uAC74\uC801 \uCC3D\uBCD1"
type: 3
- position: {x: 0, y: 2}
+ position: {x: 0, y: -4.5}
hpMult: 1
atkMult: 1
isBoss: 0
- name: "\uD669\uAC74\uC801 \uAD81\uBCD1"
type: 2
- position: {x: -2, y: 5}
+ position: {x: -4, y: 1}
hpMult: 1
atkMult: 1
isBoss: 0
- name: "\uD669\uAC74\uC801 \uAD81\uBCD1"
type: 2
- position: {x: 2, y: 5}
+ position: {x: 4, y: 1}
+ hpMult: 1
+ atkMult: 1
+ isBoss: 0
+ - name: "\uD669\uAC74\uC801 \uBCF4\uBCD1"
+ type: 0
+ position: {x: 0, y: 2.5}
+ hpMult: 1
+ atkMult: 1
+ isBoss: 0
+ - name: "\uD669\uAC74\uC801 \uCC3D\uBCD1"
+ type: 3
+ position: {x: -2.5, y: 8}
hpMult: 1
atkMult: 1
isBoss: 0
- name: "\uC7A5\uAC01"
type: 0
- position: {x: 0, y: 6.5}
+ position: {x: 0, y: 10}
hpMult: 1.3
atkMult: 1.2
isBoss: 1
- title: "\uD638\uB85C\uAD00 \uC804\uD22C"
subtitle: "190\uB144"
aiAccuracy: 0.6
+ aiAggroRange: 11
enemies:
- name: "\uB3D9\uD0C1\uAD70 \uCC3D\uBCD1"
type: 3
- position: {x: -2, y: 2.2}
+ position: {x: -2.5, y: -5}
hpMult: 1
atkMult: 1
isBoss: 0
- name: "\uB3D9\uD0C1\uAD70 \uCC3D\uBCD1"
type: 3
- position: {x: 2, y: 2.2}
+ position: {x: 2.5, y: -5}
hpMult: 1
atkMult: 1
isBoss: 0
- name: "\uB3D9\uD0C1\uAD70 \uAE30\uBCD1"
type: 1
- position: {x: -4, y: 3.5}
+ position: {x: -6, y: -1}
hpMult: 1
atkMult: 1
isBoss: 0
- name: "\uB3D9\uD0C1\uAD70 \uAE30\uBCD1"
type: 1
- position: {x: 4, y: 3.5}
+ position: {x: 6, y: -1}
+ hpMult: 1
+ atkMult: 1
+ isBoss: 0
+ - name: "\uB3D9\uD0C1\uAD70 \uBCF4\uBCD1"
+ type: 0
+ position: {x: 0, y: 1}
hpMult: 1
atkMult: 1
isBoss: 0
- name: "\uB3D9\uD0C1\uAD70 \uAD81\uBCD1"
type: 2
- position: {x: -2.5, y: 5.5}
+ position: {x: -3, y: 3}
hpMult: 1
atkMult: 1
isBoss: 0
- name: "\uB3D9\uD0C1\uAD70 \uAD81\uBCD1"
type: 2
- position: {x: 2.5, y: 5.5}
+ position: {x: 3, y: 3}
+ hpMult: 1
+ atkMult: 1
+ isBoss: 0
+ - name: "\uB3D9\uD0C1\uAD70 \uAE30\uBCD1"
+ type: 1
+ position: {x: 0, y: 7}
hpMult: 1
atkMult: 1
isBoss: 0
- name: "\uC5EC\uD3EC"
type: 1
- position: {x: 0, y: 4.5}
+ position: {x: 0, y: 11}
hpMult: 1.6
atkMult: 1.5
isBoss: 1
- title: "\uC801\uBCBD\uB300\uC804"
subtitle: "208\uB144"
aiAccuracy: 0.65
+ aiAggroRange: 12
enemies:
- name: "\uC870\uC870\uAD70 \uBCF4\uBCD1"
type: 0
- position: {x: -4, y: 2.5}
+ position: {x: -5, y: -6}
hpMult: 1
atkMult: 1
isBoss: 0
- name: "\uC870\uC870\uAD70 \uBCF4\uBCD1"
type: 0
- position: {x: 0, y: 2}
+ position: {x: 0, y: -5}
hpMult: 1
atkMult: 1
isBoss: 0
- name: "\uC870\uC870\uAD70 \uBCF4\uBCD1"
type: 0
- position: {x: 4, y: 2.5}
- hpMult: 1
- atkMult: 1
- isBoss: 0
- - name: "\uC870\uC870\uAD70 \uAD81\uBCD1"
- type: 2
- position: {x: -2.5, y: 5}
- hpMult: 1
- atkMult: 1
- isBoss: 0
- - name: "\uC870\uC870\uAD70 \uAD81\uBCD1"
- type: 2
- position: {x: 2.5, y: 5}
+ position: {x: 5, y: -6}
hpMult: 1
atkMult: 1
isBoss: 0
- name: "\uC870\uC870\uAD70 \uAE30\uBCD1"
type: 1
- position: {x: 0, y: 4.2}
+ position: {x: -3, y: 0}
+ hpMult: 1
+ atkMult: 1
+ isBoss: 0
+ - name: "\uC870\uC870\uAD70 \uAE30\uBCD1"
+ type: 1
+ position: {x: 3, y: 0}
+ hpMult: 1
+ atkMult: 1
+ isBoss: 0
+ - name: "\uC870\uC870\uAD70 \uAD81\uBCD1"
+ type: 2
+ position: {x: -4, y: 5}
+ hpMult: 1
+ atkMult: 1
+ isBoss: 0
+ - name: "\uC870\uC870\uAD70 \uAD81\uBCD1"
+ type: 2
+ position: {x: 4, y: 5}
+ hpMult: 1
+ atkMult: 1
+ isBoss: 0
+ - name: "\uC870\uC870\uAD70 \uCC3D\uBCD1"
+ type: 3
+ position: {x: 0, y: 7}
hpMult: 1
atkMult: 1
isBoss: 0
- name: "\uC870\uC870"
type: 0
- position: {x: 0, y: 6.8}
+ position: {x: 0, y: 12}
hpMult: 1.5
atkMult: 1.3
isBoss: 1
- title: "\uC624\uC7A5\uC6D0 \uC804\uD22C"
subtitle: "234\uB144"
aiAccuracy: 0.7
+ aiAggroRange: 12
enemies:
- name: "\uC704\uAD70 \uCC3D\uBCD1"
type: 3
- position: {x: -2.5, y: 2.2}
+ position: {x: -3, y: -6}
hpMult: 1
atkMult: 1
isBoss: 0
- name: "\uC704\uAD70 \uCC3D\uBCD1"
type: 3
- position: {x: 2.5, y: 2.2}
+ position: {x: 3, y: -6}
hpMult: 1
atkMult: 1
isBoss: 0
- name: "\uC704\uAD70 \uBCF4\uBCD1"
type: 0
- position: {x: -4.5, y: 3.5}
+ position: {x: -7, y: -2}
hpMult: 1
atkMult: 1
isBoss: 0
- name: "\uC704\uAD70 \uBCF4\uBCD1"
type: 0
- position: {x: 4.5, y: 3.5}
+ position: {x: 7, y: -2}
hpMult: 1
atkMult: 1
isBoss: 0
- name: "\uC704\uAD70 \uAE30\uBCD1"
type: 1
- position: {x: -1.5, y: 4.5}
+ position: {x: -2, y: 2}
hpMult: 1
atkMult: 1
isBoss: 0
- name: "\uC704\uAD70 \uAE30\uBCD1"
type: 1
- position: {x: 1.5, y: 4.5}
+ position: {x: 2, y: 2}
hpMult: 1
atkMult: 1
isBoss: 0
- name: "\uC704\uAD70 \uAD81\uBCD1"
type: 2
- position: {x: 0, y: 6}
+ position: {x: -4, y: 7}
+ hpMult: 1
+ atkMult: 1
+ isBoss: 0
+ - name: "\uC704\uAD70 \uAD81\uBCD1"
+ type: 2
+ position: {x: 4, y: 7}
+ hpMult: 1
+ atkMult: 1
+ isBoss: 0
+ - name: "\uC704\uAD70 \uCC3D\uBCD1"
+ type: 3
+ position: {x: 0, y: 9}
hpMult: 1
atkMult: 1
isBoss: 0
- name: "\uC0AC\uB9C8\uC758"
type: 0
- position: {x: 0, y: 7.2}
+ position: {x: 0, y: 13}
hpMult: 1.6
atkMult: 1.3
isBoss: 1
diff --git a/Assets/Scenes/Battle.unity b/Assets/Scenes/Battle.unity
index 85d8cb73..e3c37d31 100644
--- a/Assets/Scenes/Battle.unity
+++ b/Assets/Scenes/Battle.unity
@@ -24,9 +24,9 @@ RenderSettings:
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
m_AmbientIntensity: 1
- m_AmbientMode: 0
+ m_AmbientMode: 3
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
- m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
+ m_SkyboxMaterial: {fileID: 0}
m_HaloStrength: 0.5
m_FlareStrength: 1
m_FlareFadeSpeed: 3
@@ -50,7 +50,7 @@ LightmapSettings:
m_IndirectOutputScale: 1
m_AlbedoBoost: 1
m_EnvironmentLightingMode: 0
- m_EnableBakedLightmaps: 1
+ m_EnableBakedLightmaps: 0
m_EnableRealtimeLightmaps: 0
m_LightmapEditorSettings:
serializedVersion: 12
@@ -119,7 +119,7 @@ NavMeshSettings:
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
---- !u!1 &930732900
+--- !u!1 &1288297926
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
@@ -127,9 +127,56 @@ GameObject:
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- - component: {fileID: 930732903}
- - component: {fileID: 930732902}
- - component: {fileID: 930732901}
+ - component: {fileID: 1288297928}
+ - component: {fileID: 1288297927}
+ m_Layer: 0
+ m_Name: GameBootstrap
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!114 &1288297927
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1288297926}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: d0d49dc40532d984485290e1cfc0f91f, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: TKS.Runtime::TKS.GameBootstrap
+ Config: {fileID: 11400000, guid: 6b41999f2857842408b1a9edeaf47cb8, type: 2}
+ AutoStart: 1
+ StartStageIndex: 0
+--- !u!4 &1288297928
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1288297926}
+ 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: 0}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &1938987432
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1938987435}
+ - component: {fileID: 1938987434}
+ - component: {fileID: 1938987433}
m_Layer: 0
m_Name: Main Camera
m_TagString: MainCamera
@@ -137,21 +184,21 @@ GameObject:
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
---- !u!81 &930732901
+--- !u!81 &1938987433
AudioListener:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 930732900}
+ m_GameObject: {fileID: 1938987432}
m_Enabled: 1
---- !u!20 &930732902
+--- !u!20 &1938987434
Camera:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 930732900}
+ m_GameObject: {fileID: 1938987432}
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 2
@@ -196,13 +243,13 @@ Camera:
m_OcclusionCulling: 1
m_StereoConvergence: 10
m_StereoSeparation: 0.022
---- !u!4 &930732903
+--- !u!4 &1938987435
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 930732900}
+ m_GameObject: {fileID: 1938987432}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: -10}
@@ -211,56 +258,9 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &1640921812
-GameObject:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- serializedVersion: 6
- m_Component:
- - component: {fileID: 1640921814}
- - component: {fileID: 1640921813}
- m_Layer: 0
- m_Name: GameBootstrap
- m_TagString: Untagged
- m_Icon: {fileID: 0}
- m_NavMeshLayer: 0
- m_StaticEditorFlags: 0
- m_IsActive: 1
---- !u!114 &1640921813
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1640921812}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: d0d49dc40532d984485290e1cfc0f91f, type: 3}
- m_Name:
- m_EditorClassIdentifier: TKS.Runtime::TKS.GameBootstrap
- Config: {fileID: 11400000, guid: 6b41999f2857842408b1a9edeaf47cb8, type: 2}
- AutoStart: 1
- StartStageIndex: 0
---- !u!4 &1640921814
-Transform:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1640921812}
- 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: 0}
- m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1660057539 &9223372036854775807
SceneRoots:
m_ObjectHideFlags: 0
m_Roots:
- - {fileID: 930732903}
- - {fileID: 1640921814}
+ - {fileID: 1938987435}
+ - {fileID: 1288297928}
diff --git a/Assets/Scripts/Editor/BalanceDefaults.cs b/Assets/Scripts/Editor/BalanceDefaults.cs
index 7a69dff5..c895e87e 100644
--- a/Assets/Scripts/Editor/BalanceDefaults.cs
+++ b/Assets/Scripts/Editor/BalanceDefaults.cs
@@ -5,7 +5,7 @@ namespace TKS.EditorTools
{
///
/// BalanceConfig 자산의 최초 1회 시드 값(프로토타입 초안). 이후 수치 조정은 자산(Inspector)에서 한다 — 코드가 SOT 가 아니다.
- /// 전장 = 가로 12 × 세로 16 (x −6~6 · y −8~8). 아군은 아래쪽(y −5.5), 적은 위쪽 절반.
+ /// 전장 = 가로 20 × 세로 32 (x −10~10 · y −16~16) · 화면에는 세로 18 만 보여 스크롤한다. 아군은 아래(y −13) · 적은 전위/중군/후군으로 흩어 배치.
///
public static class BalanceDefaults
{
@@ -44,10 +44,13 @@ namespace TKS.EditorTools
c.finalHitTolerance = 0.15f;
c.moveSpeed = 9f;
- c.boardSize = new Vector2(12f, 16f);
+ c.boardSize = new Vector2(20f, 32f);
+ c.cameraViewHeight = 18f;
+ c.cameraMinViewHeight = 10f;
+ c.cameraMaxViewHeight = 36f;
c.playerSpawnPoints = new[]
{
- new Vector2(-4f, -5.5f), new Vector2(-2f, -5.5f), new Vector2(0f, -5.5f), new Vector2(2f, -5.5f), new Vector2(4f, -5.5f),
+ new Vector2(-4f, -13f), new Vector2(-2f, -13f), new Vector2(0f, -13f), new Vector2(2f, -13f), new Vector2(4f, -13f),
};
c.heroes = new[]
@@ -61,38 +64,49 @@ namespace TKS.EditorTools
c.stages = new[]
{
- Stage("황건적의 난", "184년", 0.5f,
- E("황건적 보병", UnitType.Infantry, -3.5f, 2.5f),
- E("황건적 보병", UnitType.Infantry, 3.5f, 2.5f),
- E("황건적 창병", UnitType.Spear, 0f, 2.0f),
- E("황건적 궁병", UnitType.Archer, -2f, 5f),
- E("황건적 궁병", UnitType.Archer, 2f, 5f),
- Boss("장각", UnitType.Infantry, 0f, 6.5f, 1.3f, 1.2f)),
- Stage("호로관 전투", "190년", 0.6f,
- E("동탁군 창병", UnitType.Spear, -2f, 2.2f),
- E("동탁군 창병", UnitType.Spear, 2f, 2.2f),
- E("동탁군 기병", UnitType.Cavalry, -4f, 3.5f),
- E("동탁군 기병", UnitType.Cavalry, 4f, 3.5f),
- E("동탁군 궁병", UnitType.Archer, -2.5f, 5.5f),
- E("동탁군 궁병", UnitType.Archer, 2.5f, 5.5f),
- Boss("여포", UnitType.Cavalry, 0f, 4.5f, 1.6f, 1.5f)),
- Stage("적벽대전", "208년", 0.65f,
- E("조조군 보병", UnitType.Infantry, -4f, 2.5f),
- E("조조군 보병", UnitType.Infantry, 0f, 2.0f),
- E("조조군 보병", UnitType.Infantry, 4f, 2.5f),
- E("조조군 궁병", UnitType.Archer, -2.5f, 5f),
- E("조조군 궁병", UnitType.Archer, 2.5f, 5f),
- E("조조군 기병", UnitType.Cavalry, 0f, 4.2f),
- Boss("조조", UnitType.Infantry, 0f, 6.8f, 1.5f, 1.3f)),
- Stage("오장원 전투", "234년", 0.7f,
- E("위군 창병", UnitType.Spear, -2.5f, 2.2f),
- E("위군 창병", UnitType.Spear, 2.5f, 2.2f),
- E("위군 보병", UnitType.Infantry, -4.5f, 3.5f),
- E("위군 보병", UnitType.Infantry, 4.5f, 3.5f),
- E("위군 기병", UnitType.Cavalry, -1.5f, 4.5f),
- E("위군 기병", UnitType.Cavalry, 1.5f, 4.5f),
- E("위군 궁병", UnitType.Archer, 0f, 6f),
- Boss("사마의", UnitType.Infantry, 0f, 7.2f, 1.6f, 1.3f)),
+ Stage("황건적의 난", "184년", 0.5f, 11f,
+ // 전위
+ E("황건적 보병", UnitType.Infantry, -3f, -6f),
+ E("황건적 보병", UnitType.Infantry, 3f, -6f),
+ E("황건적 창병", UnitType.Spear, 0f, -4.5f),
+ // 중군
+ E("황건적 궁병", UnitType.Archer, -4f, 1f),
+ E("황건적 궁병", UnitType.Archer, 4f, 1f),
+ E("황건적 보병", UnitType.Infantry, 0f, 2.5f),
+ // 후군
+ E("황건적 창병", UnitType.Spear, -2.5f, 8f),
+ Boss("장각", UnitType.Infantry, 0f, 10f, 1.3f, 1.2f)),
+ Stage("호로관 전투", "190년", 0.6f, 11f,
+ E("동탁군 창병", UnitType.Spear, -2.5f, -5f),
+ E("동탁군 창병", UnitType.Spear, 2.5f, -5f),
+ E("동탁군 기병", UnitType.Cavalry, -6f, -1f),
+ E("동탁군 기병", UnitType.Cavalry, 6f, -1f),
+ E("동탁군 보병", UnitType.Infantry, 0f, 1f),
+ E("동탁군 궁병", UnitType.Archer, -3f, 3f),
+ E("동탁군 궁병", UnitType.Archer, 3f, 3f),
+ E("동탁군 기병", UnitType.Cavalry, 0f, 7f),
+ Boss("여포", UnitType.Cavalry, 0f, 11f, 1.6f, 1.5f)),
+ Stage("적벽대전", "208년", 0.65f, 12f,
+ E("조조군 보병", UnitType.Infantry, -5f, -6f),
+ E("조조군 보병", UnitType.Infantry, 0f, -5f),
+ E("조조군 보병", UnitType.Infantry, 5f, -6f),
+ E("조조군 기병", UnitType.Cavalry, -3f, 0f),
+ E("조조군 기병", UnitType.Cavalry, 3f, 0f),
+ E("조조군 궁병", UnitType.Archer, -4f, 5f),
+ E("조조군 궁병", UnitType.Archer, 4f, 5f),
+ E("조조군 창병", UnitType.Spear, 0f, 7f),
+ Boss("조조", UnitType.Infantry, 0f, 12f, 1.5f, 1.3f)),
+ Stage("오장원 전투", "234년", 0.7f, 12f,
+ E("위군 창병", UnitType.Spear, -3f, -6f),
+ E("위군 창병", UnitType.Spear, 3f, -6f),
+ E("위군 보병", UnitType.Infantry, -7f, -2f),
+ E("위군 보병", UnitType.Infantry, 7f, -2f),
+ E("위군 기병", UnitType.Cavalry, -2f, 2f),
+ E("위군 기병", UnitType.Cavalry, 2f, 2f),
+ E("위군 궁병", UnitType.Archer, -4f, 7f),
+ E("위군 궁병", UnitType.Archer, 4f, 7f),
+ E("위군 창병", UnitType.Spear, 0f, 9f),
+ Boss("사마의", UnitType.Infantry, 0f, 13f, 1.6f, 1.3f)),
};
}
@@ -116,9 +130,9 @@ namespace TKS.EditorTools
return new BalanceConfig.EnemySpawn { name = name, type = t, position = new Vector2(x, y), hpMult = hpMult, atkMult = atkMult, isBoss = true };
}
- static BalanceConfig.StageDef Stage(string title, string subtitle, float accuracy, params BalanceConfig.EnemySpawn[] enemies)
+ static BalanceConfig.StageDef Stage(string title, string subtitle, float accuracy, float aggro, params BalanceConfig.EnemySpawn[] enemies)
{
- return new BalanceConfig.StageDef { title = title, subtitle = subtitle, aiAccuracy = accuracy, enemies = new List(enemies) };
+ return new BalanceConfig.StageDef { title = title, subtitle = subtitle, aiAccuracy = accuracy, aiAggroRange = aggro, enemies = new List(enemies) };
}
}
}
diff --git a/Assets/Scripts/Editor/ProjectSetup.cs b/Assets/Scripts/Editor/ProjectSetup.cs
index 2e404a20..798f7e18 100644
--- a/Assets/Scripts/Editor/ProjectSetup.cs
+++ b/Assets/Scripts/Editor/ProjectSetup.cs
@@ -33,6 +33,17 @@ namespace TKS.EditorTools
Debug.Log("[TKS] BalanceConfig 기본값 재시드");
}
+ /// CLI 용: 기본값 재시드 + 씬·설정 재생성(기존 자산 수치를 덮어쓴다).
+ public static void BuildFresh()
+ {
+ var cfg = EnsureConfig(true);
+ BuildScene(cfg);
+ ApplySettings();
+ AssetDatabase.SaveAssets();
+ AssetDatabase.Refresh();
+ Debug.Log("[TKS] BuildFresh 완료 · 기본값 재시드 · " + ScenePath);
+ }
+
public static BalanceConfig EnsureConfig(bool overwrite)
{
if (!AssetDatabase.IsValidFolder("Assets/Resources")) AssetDatabase.CreateFolder("Assets", "Resources");
@@ -81,6 +92,7 @@ namespace TKS.EditorTools
PlayerSettings.companyName = "NerdNavis";
PlayerSettings.productName = "ThreeKingdomsSlingshot";
PlayerSettings.defaultInterfaceOrientation = UIOrientation.Portrait;
+ PlayerSettings.runInBackground = true;
EditorSettings.defaultBehaviorMode = EditorBehaviorMode.Mode2D;
}
diff --git a/Assets/Scripts/Runtime/AutoPlayDriver.cs b/Assets/Scripts/Runtime/AutoPlayDriver.cs
index 454084fa..b42ee8fa 100644
--- a/Assets/Scripts/Runtime/AutoPlayDriver.cs
+++ b/Assets/Scripts/Runtime/AutoPlayDriver.cs
@@ -8,6 +8,7 @@ namespace TKS
///
/// 자동 플레이 실측: 아군도 AI 로 조작해 몇 턴을 돌리며 스크린샷·로그를 남긴다.
/// 에디터에서 ProjectSetup.AutoPlayCapture 가 SessionState 로 출력 폴더를 넘기면 생성된다.
+ /// 비활성 에디터 창은 프레임이 느리므로 timeScale 을 올려 실시간 기준으로 빨리 끝낸다.
///
public class AutoPlayDriver : MonoBehaviour
{
@@ -36,6 +37,8 @@ namespace TKS
IEnumerator Start()
{
Directory.CreateDirectory(OutputDir);
+ Time.timeScale = 4f;
+ Time.maximumDeltaTime = 1f;
float t0 = Time.realtimeSinceStartup;
while ((BattleManager.Instance == null || BattleManager.Instance.Phase != BattlePhase.PlayerTurn)
&& Time.realtimeSinceStartup - t0 < 20f)
@@ -50,22 +53,42 @@ namespace TKS
Finish(1);
yield break;
}
+ var camCtrl = cam.GetComponent();
- Log("stage=" + bm.Stage.title + " players=" + bm.AliveCount(Faction.Player) + " enemies=" + bm.AliveCount(Faction.Enemy));
+ Log("stage=" + bm.Stage.title + " players=" + bm.AliveCount(Faction.Player) + " enemies=" + bm.AliveCount(Faction.Enemy) + " board=" + bm.Config.boardSize);
yield return Fx.Wait(0.6f);
yield return Shot(cam, "start");
+ // 전장 전체 조감(최대 줌아웃) → 원래 줌
+ if (camCtrl != null)
+ {
+ float prev = camCtrl.ViewHeight;
+ camCtrl.SetViewHeight(camCtrl.MaxViewHeight);
+ camCtrl.SnapTo(Vector2.zero);
+ yield return null;
+ yield return Shot(cam, "overview_zoom_out");
+ camCtrl.SetViewHeight(prev);
+ camCtrl.PanBy(new Vector2(0f, 6f)); // 스크롤 확인
+ yield return null;
+ yield return Shot(cam, "scrolled_up");
+ camCtrl.FocusOn(bm.AliveUnits(Faction.Player)[0].Position + new Vector2(0f, 3f));
+ yield return Fx.Wait(0.5f);
+ }
+
var first = FirstActable(bm);
if (first != null)
{
- var tgt = EnemyAI.Decide(first, bm.AliveUnits(Faction.Enemy), 1f, bm.Rng, bm.Board);
- Vector2 pointer = first.Position - (tgt - first.Position) * 0.5f;
- bm.Sling.ShowPreview(first, tgt, pointer);
- first.View.SetSelected(true);
- yield return null;
- yield return Shot(cam, "aim_" + first.DisplayName);
- first.View.SetSelected(false);
- bm.Sling.HidePreview();
+ var tgt = EnemyAI.Decide(first, bm.AliveUnits(Faction.Enemy), 1f, float.PositiveInfinity, bm.Rng, bm.Board);
+ if (tgt.HasValue)
+ {
+ Vector2 pointer = first.Position - (tgt.Value - first.Position) * 0.5f;
+ bm.Sling.ShowPreview(first, tgt.Value, pointer);
+ first.View.SetSelected(true);
+ yield return null;
+ yield return Shot(cam, "aim_" + first.DisplayName);
+ first.View.SetSelected(false);
+ bm.Sling.HidePreview();
+ }
}
bool firstActionShot = false;
@@ -80,8 +103,9 @@ namespace TKS
bm.OnEmptyTap();
break;
}
- var target = EnemyAI.Decide(u, bm.AliveUnits(Faction.Enemy), 1f, bm.Rng, bm.Board);
- if (!bm.RequestPlayerAction(u, target)) break;
+ var target = EnemyAI.Decide(u, bm.AliveUnits(Faction.Enemy), 1f, float.PositiveInfinity, bm.Rng, bm.Board);
+ if (!target.HasValue) break;
+ if (!bm.RequestPlayerAction(u, target.Value)) break;
while (bm.Phase == BattlePhase.Resolving) yield return null;
Log("turn " + turn + " | " + bm.LastMessage);
if (!firstActionShot)
@@ -93,11 +117,11 @@ namespace TKS
}
while (bm.Phase == BattlePhase.EnemyTurn || bm.Phase == BattlePhase.Resolving) yield return null;
Log("turn " + turn + " end | phase=" + bm.Phase + " players=" + bm.AliveCount(Faction.Player) + " enemies=" + bm.AliveCount(Faction.Enemy) + " | " + bm.LastMessage);
+ yield return Fx.Wait(0.4f);
yield return Shot(cam, "turn" + turn + "_end");
if (bm.Phase == BattlePhase.StageClear || bm.Phase == BattlePhase.Defeat) break;
}
- File.WriteAllLines(Path.Combine(OutputDir, "autoplay_log.txt"), log.ToArray());
Finish(0);
}
@@ -122,10 +146,6 @@ namespace TKS
{
log.Add(s);
Debug.Log("[AutoPlay] " + s);
- }
-
- void Finish(int code)
- {
try
{
File.WriteAllLines(Path.Combine(OutputDir, "autoplay_log.txt"), log.ToArray());
@@ -133,6 +153,12 @@ namespace TKS
catch
{
}
+ }
+
+ void Finish(int code)
+ {
+ Log("finish code=" + code);
+ Time.timeScale = 1f;
#if UNITY_EDITOR
UnityEditor.EditorApplication.Exit(code);
#else
diff --git a/Assets/Scripts/Runtime/BalanceConfig.cs b/Assets/Scripts/Runtime/BalanceConfig.cs
index ab01b4d6..01632e65 100644
--- a/Assets/Scripts/Runtime/BalanceConfig.cs
+++ b/Assets/Scripts/Runtime/BalanceConfig.cs
@@ -51,6 +51,8 @@ namespace TKS
public string title;
public string subtitle;
[Range(0f, 1f)] public float aiAccuracy = 0.6f;
+ [Tooltip("이 거리 안에 아군이 들어와야 적이 움직인다(넓은 전장에서 부대별 교전)")]
+ public float aiAggroRange = 11f;
public List enemies = new List();
}
@@ -82,8 +84,12 @@ namespace TKS
public float finalHitTolerance = 0.15f;
public float moveSpeed = 9f;
- [Header("전장")]
- public Vector2 boardSize = new Vector2(12f, 16f);
+ [Header("전장·카메라 (화면보다 넓은 전장을 스크롤)")]
+ public Vector2 boardSize = new Vector2(20f, 32f);
+ [Tooltip("화면 세로에 보이는 월드 높이")]
+ public float cameraViewHeight = 18f;
+ public float cameraMinViewHeight = 10f;
+ public float cameraMaxViewHeight = 36f;
public Vector2[] playerSpawnPoints = new Vector2[0];
[Header("아군 영웅 (최대 5)")]
diff --git a/Assets/Scripts/Runtime/BattleHUD.cs b/Assets/Scripts/Runtime/BattleHUD.cs
index 9b88d53b..f556fc52 100644
--- a/Assets/Scripts/Runtime/BattleHUD.cs
+++ b/Assets/Scripts/Runtime/BattleHUD.cs
@@ -1,13 +1,16 @@
+using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace TKS
{
- /// 화면 HUD(uGUI · 코드 생성): 스테이지·턴·유닛 수·안내·선택 유닛 정보·스킬 아이콘(추후)·결과 오버레이.
+ /// 화면 HUD(uGUI · 코드 생성): 스테이지·턴·유닛 수·안내·선택 유닛 정보·미니맵·스킬 아이콘(추후)·결과 오버레이.
public class BattleHUD : MonoBehaviour
{
BattleManager battle;
+ Camera uiCam;
+ CameraController camCtrl;
Text stageText;
Text turnText;
Text countText;
@@ -19,9 +22,15 @@ namespace TKS
Text resultSub;
Unit selected;
- public void Build(BattleManager b, Camera cam)
+ Image minimapBg;
+ Image minimapView;
+ readonly Dictionary minimapDots = new Dictionary();
+
+ public void Build(BattleManager b, Camera cam, CameraController cc)
{
battle = b;
+ uiCam = cam;
+ camCtrl = cc;
var canvas = gameObject.AddComponent