convert game playing..

This commit is contained in:
2026-09-23 12:53:52 +09:00
parent 37c7942b71
commit 5d11288a6f
136 changed files with 15856 additions and 299 deletions
@@ -5,6 +5,17 @@ namespace BumpCombat.Constants
[CreateAssetMenu(menuName = "BumpCombat/Constants/Combat")]
public sealed class CombatConstants : ScriptableObject
{
[Header("정면 몸통박치기 접촉 피해")]
[SerializeField, Tooltip("OFF: 정면 몸통박치기 자체 피해 없음. ON: 이전 enemy.ContactDamage를 PlayerHealth.TryTakeDamage로 전달해 일반 무적·가드·피격 넉백을 적용하며 EnemyAttack는 영향 없음.")]
private bool enableFrontalBumpSelfDamage;
public bool EnableFrontalBumpSelfDamage
{
get => enableFrontalBumpSelfDamage;
set => enableFrontalBumpSelfDamage = value;
}
[Header("몸통박치기 방향 판정")]
[Tooltip("적 정면으로 분류하는 방향 내적 기준"), Range(-1f, 1f)] public float FrontThreshold = 0.707f;
[Tooltip("적 후방으로 분류하는 방향 내적 기준"), Range(-1f, 1f)] public float BackThreshold = -0.5f;
@@ -25,6 +25,9 @@ namespace BumpCombat.Constants
[Tooltip("흔들림 지속시간 (초)"), Min(0f)] public float CameraShakeDuration = 0.12f;
[Tooltip("일반 흔들림 크기 (픽셀)"), Min(0f)] public float CameraShakePixels = 3f;
[Tooltip("강한 흔들림 크기 (픽셀)"), Min(0f)] public float HeavyCameraShakePixels = 5f;
public float RearHitCameraPunchDuration = 0.07f;
public float RearHitCameraPunchPixels = 1f;
public float RearHitCameraPunchRearmDelay = 0.45f;
[Tooltip("강한 피격으로 표시하는 넉백 거리 (유닛)"), Min(0f)] public float HeavyKnockbackThreshold = 1f;
[Header("무적 적 몸통박치기 표시")]
@@ -0,0 +1,117 @@
using BumpCombat.Defense;
using UnityEngine;
namespace BumpCombat.Constants
{
[CreateAssetMenu(menuName = "BumpCombat/Constants/Defense Prototype")]
public sealed class DefenseConstants : ScriptableObject
{
[Header("Prototype economy")]
[Tooltip("Initial construction currency for the test mode.")]
[Min(0)] public int InitialConstructionCurrency = 100;
[Min(0)] public int DirectTowerCost = 30;
[Min(0)] public int SummonTowerCost = 40;
[Min(0)] public int PortalRewardCurrency = 20;
[Min(0.1f)] public float BuildInteractionRadius = 1.5f;
[Header("Prototype arena")]
public Vector2 ArenaCenter = Vector2.zero;
public Vector2 ArenaPlayableHalfExtents = new(11f, 6f);
[Header("Prototype bases and routes")]
[Min(1)] public int BaseMaximumHealth = 12;
[Min(1)] public int PortalEnemyCount = 8;
[Min(0)] public int ArrivalBaseDamage = 1;
[Min(0.1f)] public float PortalSpawnInterval = 1.25f;
[Min(0.1f)] public float RouteSpeedMultiplier = 0.75f;
[Min(0f)] public float PostAttackProgressSeconds = 0.65f;
public Vector2[] PortalPositions =
{
new(-9f, 3.25f),
new(-9f, -3.25f),
};
public Vector2[] BasePositions =
{
new(9f, 0f),
new(9f, 0f),
};
public Vector2[] BuildPadPositions =
{
new(-3.25f, 3.25f),
new(3.25f, -3.25f),
};
[Tooltip("Two ordered waypoints per lane, indexed by lane * 2 + waypoint.")]
public Vector2[] WaypointPositions =
{
new(-3f, 3.25f), new(3f, 3.25f),
new(-3f, -3.25f), new(3f, -3.25f),
};
[Tooltip("The tower source kind ignored by each portal's enemies.")]
public DefenseTowerKind[] PortalImmuneTowerKinds =
{
DefenseTowerKind.Direct,
DefenseTowerKind.Summon,
};
[Header("Prototype tower sight and damage")]
[Min(0.1f)] public float PlayerSightRadius = 6f;
[Range(0f, 1f)] public float OutsideSightDamageEfficiency = 0.7f;
[Min(0.1f)] public float TowerRange = 5.5f;
[Min(0.1f)] public float DirectTowerDamage = 10f;
[Min(0.05f)] public float DirectTowerAttackInterval = 0.75f;
[Min(0.1f)] public float SummonDamage = 6f;
[Min(0.05f)] public float SummonAttackInterval = 0.9f;
[Min(1)] public int SummonUnitCount = 2;
[Min(0.1f)] public float SummonAreaRadius = 2.25f;
[Min(0.1f)] public float SummonUnitMoveSpeed = 2.5f;
[Min(0.1f)] public float SummonAttackRange = 1.2f;
[Header("Prototype player recovery")]
[Min(0f)] public float PlayerReviveDelaySeconds = 5f;
[Min(0f)] public float PlayerReviveInvulnerabilitySeconds = 1f;
[Min(0.1f)] public float RewardPickupRadius = 1.35f;
public Vector2 GetPortalPosition(int lane)
{
return GetPosition(PortalPositions, lane, new Vector2(-9f, lane == 0 ? 3.25f : -3.25f));
}
public Vector2 GetBasePosition(int lane)
{
return GetPosition(BasePositions, lane, new Vector2(9f, 0f));
}
public Vector2 GetBuildPadPosition(int index)
{
return GetPosition(BuildPadPositions, index, Vector2.zero);
}
public Vector2 GetWaypointPosition(int lane, int waypointIndex)
{
int index = lane * 2 + waypointIndex;
Vector2 fallback = new(
waypointIndex == 0 ? -3f : 3f,
lane == 0 ? 3.25f : -3.25f);
return GetPosition(WaypointPositions, index, fallback);
}
public DefenseTowerKind GetPortalImmuneTowerKind(int lane)
{
if (PortalImmuneTowerKinds != null
&& lane >= 0
&& lane < PortalImmuneTowerKinds.Length)
{
return PortalImmuneTowerKinds[lane];
}
return (DefenseTowerKind)Mathf.Clamp(lane, 0, 1);
}
private static Vector2 GetPosition(Vector2[] positions, int index, Vector2 fallback)
{
return positions != null && index >= 0 && index < positions.Length
? positions[index]
: fallback;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8a83cd68928e48f89b011bc92f0ca8e3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -21,6 +21,17 @@ namespace BumpCombat.Constants
[Tooltip("군중형 접근 기준점의 가장 안쪽 반경 (유닛)"), Min(0f)] public float CrowdApproachBaseRadius = 0.75f;
[Tooltip("군중형 접근 기준점 동심원 간 간격 (유닛)"), Min(0f)] public float CrowdApproachRingSpacing = 0.15f;
[Min(0f)] public float SummonedEnemyNoAnimationLockDuration = 0.15f;
[Tooltip("시야 장애물 차폐를 무시하고 무조건 감지하는 초근접 반경 (유닛)"), Min(0f)] public float ProximityAlertRange = 2.0f;
[Tooltip("적의 기본 시야 사거리 (유닛)"), Min(0f)] public float DefaultSightRange = 8.0f;
[Tooltip("일반 적이 시야를 잃은 뒤 마지막 위치를 기억하는 시간 (초)"), Min(0f)] public float LostSightMemoryDuration = 1.5f;
[Tooltip("비탐지 일반 적의 로밍 반경 최솟값 (유닛)"), Min(0f)] public float RoamRadiusMin = 2.5f;
[Tooltip("비탐지 일반 적의 로밍 반경 최댓값 (유닛)"), Min(0f)] public float RoamRadiusMax = 4.0f;
[Tooltip("로밍 지점 도착 후 최소 대기시간 (초)"), Min(0f)] public float RoamPauseMin = 0.4f;
[Tooltip("로밍 지점 도착 후 최대 대기시간 (초)"), Min(0f)] public float RoamPauseMax = 1.0f;
[Tooltip("EncounterGroup 내부 적의 최소 초기 간격 (유닛)"), Min(0f)] public float EncounterGroupMinSpacing = 1.5f;
[Tooltip("EncounterGroup 내부 적의 최대 초기 간격 (유닛)"), Min(0f)] public float EncounterGroupMaxSpacing = 2.5f;
[Tooltip("장애물 회피(Wall Slide) 원형 캐스트 반경"), Min(0.05f)] public float WallSlideCastRadius = 0.35f;
[Tooltip("장애물 회피(Wall Slide) 원형 캐스트 거리"), Min(0.05f)] public float WallSlideCastDistance = 0.4f;
[Header("적과 플레이어 사이 거리")]
[Tooltip("일반 적이 주는 플레이어 넉백 거리 (유닛)"), Min(0f)] public float NormalPlayerKnockbackDistance = 0.75f;
@@ -15,6 +15,8 @@ namespace BumpCombat.Constants
private static ArtifactConstants fallbackArtifacts;
private static RunConstants fallbackRun;
private static CombatFeedbackSettings fallbackCombatFeedback;
private static DefenseConstants fallbackDefense;
private static PassiveRelicConstants fallbackPassiveRelics;
[Header("설정 분류")]
[SerializeField, Tooltip("플레이어 기본 능력치, 피격, 가드 설정")]
@@ -33,6 +35,10 @@ namespace BumpCombat.Constants
private RunConstants run;
[SerializeField, Tooltip("타격, 피격, 가드 효과의 표시 설정")]
private CombatFeedbackSettings combatFeedback;
[SerializeField, Tooltip("역병형 방어전 테스트 모드 설정")]
private DefenseConstants defense;
[SerializeField, Tooltip("방어전 패시브 유물 효과 설정")]
private PassiveRelicConstants passiveRelics;
public static GameplayConstants Current
{
@@ -60,6 +66,8 @@ namespace BumpCombat.Constants
public RunConstants Run => Resolve(run, ref fallbackRun);
public CombatFeedbackSettings CombatFeedback =>
Resolve(combatFeedback, ref fallbackCombatFeedback);
public DefenseConstants Defense => Resolve(defense, ref fallbackDefense);
public PassiveRelicConstants PassiveRelics => Resolve(passiveRelics, ref fallbackPassiveRelics);
#if UNITY_EDITOR
public static void SetCurrentForTests(GameplayConstants value)
@@ -78,6 +86,8 @@ namespace BumpCombat.Constants
fallbackArtifacts = null;
fallbackRun = null;
fallbackCombatFeedback = null;
fallbackDefense = null;
fallbackPassiveRelics = null;
}
#endif
@@ -0,0 +1,21 @@
using UnityEngine;
namespace BumpCombat.Constants
{
[CreateAssetMenu(menuName = "BumpCombat/Constants/Passive Relics")]
public sealed class PassiveRelicConstants : ScriptableObject
{
[Header("Twin Horn Talisman")]
[Range(0f, 1f)] public float TwinHornDoubleDamageChance = 0.15f;
[Header("Resonance Core")]
[Range(0f, 1f)] public float ResonanceEchoChance = 0.08f;
[Min(0f)] public float ResonanceEchoCooldownSeconds = 3f;
[Range(0f, 1f)] public float ResonanceEchoDamageMultiplier = 0.5f;
[Header("Rupture Seed")]
[Range(0f, 1f)] public float RuptureSeedChance = 0.25f;
[Range(0f, 1f)] public float RuptureExplosionMaxHealthFraction = 0.1f;
[Min(0f)] public float RuptureExplosionPlayerBodyDiameters = 3f;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f0f9bca102564c4395943d6b39c6d9f0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -6,7 +6,7 @@ namespace BumpCombat.Constants
public sealed class PlayerConstants : ScriptableObject
{
[Header("기본 능력치")]
[Tooltip("플레이어 기본 이동 속도 (유닛/초)"), Min(0f)] public float BaseMoveSpeed = 3f;
[Tooltip("플레이어 기본 이동 속도 (유닛/초)"), Min(0f)] public float BaseMoveSpeed = 3.75f;
[Tooltip("플레이어 기본 최대 체력"), Min(1f)] public float BaseMaxHealth = 100f;
[Header("피격")]
@@ -5,6 +5,13 @@ using UnityEngine;
namespace BumpCombat.Constants
{
public enum RoomScaleComparisonMode
{
Disabled = 0,
Original = 1,
Expanded = 2,
}
[Serializable]
public struct SpawnDensityPhase
{
@@ -123,9 +130,25 @@ namespace BumpCombat.Constants
public Vector2 ArenaPlayableHalfExtents = new(15f, 8.4375f);
public Vector2 ArenaPlayerPadding = new(0.5f, 0.625f);
public Vector2 ArenaCameraViewHalfExtents = new(10f, 5.625f);
[Tooltip("스테이지 방에서 사용할 플레이어 추적 시야의 반쪽 크기")]
public Vector2 StageCameraViewHalfExtents = new(7.5f, 4.21875f);
[Tooltip("대표 Stage 1 비교 방에서 Original 선택 시 사용할 좁은 추적 시야의 반쪽 크기")]
public Vector2 StageComparisonOriginalCameraViewHalfExtents = new(5f, 2.8125f);
[Tooltip("대표 Stage 1 비교 방에서 Expanded 선택 시 사용할 추적 시야의 반쪽 크기")]
public Vector2 StageComparisonCameraViewHalfExtents = new(7.5f, 4.21875f);
public Vector2 ArenaCameraDeadZone = new(0.5f, 0.3f);
[Min(0f)] public float ArenaCameraSmoothTime = 0.15f;
[Header("대표 Stage 1 방 크기 비교")]
[Tooltip("Disabled는 기존 카탈로그 선택을 유지하고, Original/Expanded는 입구 직결 첫 전투 방을 S1-A로 고정합니다.")]
public RoomScaleComparisonMode Stage1FirstCombatRoomScaleComparison = RoomScaleComparisonMode.Disabled;
[Header("제한 시야 교전")]
[Min(0.1f)] public float StagePlayerVisibilityRadius = 6f;
[Range(0f, 1f)] public float StageExploredFogOpacity = 0.65f;
[Range(0f, 1f)] public float StageUnseenFogOpacity = 1f;
[Range(0.1f, 1f)] public float StageEncounterSightRangeMultiplier = 0.5f;
public float[] EliteTimes(bool development, bool production)
{
float[] times = production