Project_WL/Assets/WL/Scripts/Combat/CombatSettings.cs

209 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
namespace WL.Combat
{
/// <summary>검 궤적 이펙트를 그리는 방식 (PD #718)</summary>
public enum SlashMode
{
/// <summary>NamuFX 프리팹을 스윙 호에 맞춰 1회 배치한다</summary>
PrefabArc = 0,
/// <summary>검이 지나간 자리를 매 프레임 리본 메시로 그린다(궤적 일치도 최고)</summary>
BladeTrail = 1
}
/// <summary>
/// 플레이어·몬스터 전투 수치의 단일 출처(SOT). 코드 상수 금지(C45) — 모든 값은 이 에셋에서 읽는다.
/// 에셋 경로: Assets/WL/Settings/CombatSettings.asset
///
/// 현재 값은 전부 PD 지시 기준의 임시값이며, 추후 테이블(데이터 시트)로 대체할 예정이다.
/// </summary>
[CreateAssetMenu(fileName = "CombatSettings", menuName = "WL/Combat Settings")]
public class CombatSettings : ScriptableObject
{
[Header("■ 플레이어 공격 (PD 지시 · 임시 3~5)")]
[Tooltip("1회 공격 최소 피해량 · 임시 3")]
public int playerAttackMin = 3;
[Tooltip("1회 공격 최대 피해량(이 값 포함) · 임시 5")]
public int playerAttackMax = 5;
[Header("■ 플레이어 체력 (PD 지시 ⑥ · 아직 사망하지 않는다)")]
[Tooltip("표시·계산용 최대 체력 · 임시 100")]
public float playerMaxHp = 100f;
[Tooltip("체력 하한. 이 값 아래로 내려가지 않아 사망하지 않는다 · 임시 1")]
public float playerMinHp = 1f;
[Tooltip("피격 모션 길이를 Animator 에서 못 읽을 때 쓰는 대체 시간(초)")]
public float playerHitFallbackDuration = 1.07f;
[Tooltip("피격 모션 크로스페이드 시간(초)")]
public float playerHitBlendTime = 0.06f;
[Header("■ 플레이어 콤보 공격 (PD #704 추가지시 1·2 · 임시)")]
[Tooltip("콤보 단계 수. 3 이면 Attack1 -> Attack2 -> Attack3 (3히트) · PD 지시 3")]
public int comboStepCount = 3;
[Tooltip("현재 공격 클립의 이 정규화 시각(0~1)을 넘으면 다음 콤보 단계로 넘어간다 · 임시 0.78")]
[Range(0.1f, 1f)] public float comboAdvanceNormalizedTime = 0.78f;
[Tooltip("콤보 단계 사이 크로스페이드 시간(초) · 임시 0.10")]
public float comboBlendTime = 0.10f;
[Tooltip("공격 클립 길이 대비 피해가 들어가는 정규화 시각(0~1). 각 단계마다 1회씩 판정 · 임시 0.35")]
[Range(0f, 1f)] public float comboHitNormalizedTime = 0.35f;
[Header("■ 검 궤적 VFX — 방식 선택 (PD #718)")]
[Tooltip("BladeTrail = 검이 지나간 자리를 매 프레임 리본으로 그린다(궤적 일치도 최고) · PrefabArc = NamuFX 프리팹을 호에 맞춰 1회 배치")]
public SlashMode slashMode = SlashMode.BladeTrail;
[Tooltip("공격 클립에서 스윙이 시작되는 정규화 시각(0~1) · 임시 0.10")]
[Range(0f, 1f)] public float slashSwingStartNormalized = 0.10f;
[Tooltip("공격 클립에서 스윙이 끝나는 정규화 시각(0~1) · 임시 0.60")]
[Range(0f, 1f)] public float slashSwingEndNormalized = 0.60f;
[Header("■ 검날 트레일 (slashMode = BladeTrail · 임시)")]
[Tooltip("트레일 1겹 — NamuFX Slash_B 의 가산 머티리얼(M_slashB_Add)")]
public Material trailMaterial;
[Tooltip("트레일 2겹 — NamuFX Slash_B 의 알파 머티리얼(M_slashB_Alp). 원본과 같은 2겹 구성 · PD #718")]
public Material trailMaterialAlpha;
[Tooltip("리본 폭 비율. 1 = 손잡이~칼끝 전체 · 원본 SlashMesh_00 실측 안쪽/바깥 반지름 = 0.47/1.0 이므로 0.53 이 원본과 같은 두께")]
[Range(0.05f, 1f)] public float trailWidthScale = 0.53f;
[Tooltip("꼬리(오래된 쪽) 폭 비율. 1 = 균일, 작을수록 꼬리가 얇아진다(원본 크레센트의 테이퍼) · 임시 0.25")]
[Range(0f, 1f)] public float trailTailWidthRatio = 0.25f;
[Tooltip("스윙이 끝난 검끝 위치에 원본의 fx·dust 만 터뜨려 '튀는' 느낌을 유지한다 · PD #718 ④")]
public bool trailSpawnBurst = true;
[Tooltip("스윙이 끝난 뒤 트레일이 사라지는 시간(초) · 임시 0.18")]
public float trailFadeSeconds = 0.18f;
[Tooltip("페이드 중 알파를 그대로 유지하는 구간 비율(0~1). 원본 Custom2 그라디언트 실측 = 0.51 까지 알파 1 유지 후 0 까지 감소")]
[Range(0f, 0.95f)] public float trailFadeHoldRatio = 0.51f;
[Tooltip("트레일이 기억하는 최대 프레임 수 · 임시 48")]
public int trailMaxSamples = 48;
[Header("■ 트레일 색·UV (NamuFX 원본 실측값 · PD #718 마무리)")]
[Tooltip("가산 겹(M_slashB_Add) 색(HDR). 원본은 파티클 Custom Data 2 로 색을 넣는다 — 실측 피크 = (0.086, 1.553, 2.024)")]
[ColorUsage(true, true)] public Color trailColorAdd = new Color(0.086f, 1.553f, 2.024f, 1f);
[Tooltip("알파 겹(M_slashB_Alp) 색(HDR). 원본 Custom Data 2 그라디언트 시작값 실측 = (0, 0.762, 1.582)")]
[ColorUsage(true, true)] public Color trailColorAlpha = new Color(0f, 0.762f, 1.582f, 1f);
[Tooltip("가산 겹 텍스처(T_SlashSheet01)는 3x3 시트다. 한 칸만 쓰도록 u 범위를 지정한다 — 프레임 2(가장 밝은 크레센트) = 0.667~1.0")]
[Range(0f, 1f)] public float trailUvUMin = 0.6667f;
[Range(0f, 1f)] public float trailUvUMax = 1f;
[Tooltip("가산 겹 v 범위(0 = 손잡이 쪽, 1 = 칼끝 쪽). 프레임 2 = 0.667~1.0 · 코어(밝은 띠)는 v 위쪽에 있다")]
[Range(0f, 1f)] public float trailUvVMin = 0.6667f;
[Range(0f, 1f)] public float trailUvVMax = 1f;
[Tooltip("알파 겹의 마스크(SlashMaskTest)는 시트가 아니라 한 장이다 — 켜면 알파 겹만 UV 0~1 전체를 쓴다")]
public bool trailAlphaUvFull = true;
[Tooltip("알파 겹의 디졸브 진행량(원본 Custom Data 1 실측 = 수명 동안 0 → 0.98). 페이드 구간에서 이 값까지 올린다")]
[Range(0f, 1f)] public float trailDissolveMax = 0.98f;
[Header("■ 검 궤적 VFX (PD #712 ② · 임시)")]
[Tooltip("타격마다 1회 재생할 슬래시 프리팹. 비우면 재생하지 않는다 (NamuFX Slash_B_recolor_1 등)")]
public GameObject slashVfxPrefab;
[Tooltip("미리 만들어 돌려 쓰는 개수. 콤보 3타가 겹쳐도 모자라지 않게 · 임시 3")]
public int slashVfxPoolSize = 3;
[Tooltip("검날 프레임(전방 = 검날 방향) 기준 추가 위치 오프셋(m) · 임시 (0, 0, 0)")]
public Vector3 slashLocalOffset = Vector3.zero;
[Tooltip("검날 길이의 몇 지점에서 호가 시작할지(0=손잡이, 1=칼끝) · PD #716 ④ · 임시 0.15")]
[Range(0f, 1.5f)] public float slashBladeFraction = 0.15f;
[Tooltip("호가 칼끝까지 덮도록 검날 길이에 맞춰 크기를 자동 보정한다 · PD #716 ④")]
public bool slashFitToBlade = true;
[Tooltip("콤보 단계별 회전 오프셋(도). 배열 길이가 모자라면 마지막 값을 쓴다 · 임시 1타 가로 / 2타 반대 가로 / 3타 세로")]
public Vector3[] slashRotationOffsets = new Vector3[]
{
new Vector3(0f, 0f, 0f),
new Vector3(0f, 0f, 180f),
new Vector3(0f, 0f, 90f)
};
[Tooltip("슬래시 크기 배수 · 임시 1.0")]
public float slashScale = 1f;
[Tooltip("재생 후 이 시간(초)이 지나면 회수한다. 파티클 길이보다 넉넉하게 · 임시 2.0")]
public float slashAutoReturnSeconds = 2f;
[Tooltip("소켓으로 쓸 트랜스폼 이름 후보(위에서부터 탐색). 못 찾으면 Humanoid 오른손 본을 쓴다")]
public string[] slashSocketNames = new string[] { "Kazuko_claymore", "Weapon_Target_Hand_R", "Sword" };
// slashParentToSocket 은 PD #718 로 폐기 — 검 본에 붙이면 이펙트가 검을 따라 끌려다녀
// "궤적과 다른 방향으로 보인다"는 증상의 원인이 됐다(PM 실측). 이제 항상 무부모 월드 스폰이다.
[Header("■ 플레이어 사망 (PD #704 범위확정 4 · 현재 비활성)")]
[Tooltip("체크하면 체력이 0 이 될 때 사망 모션을 재생한다. 기본 false = 하한 1 유지(기존 규칙)")]
public bool playerCanDie = false;
[Tooltip("사망 클립 길이를 Animator 에서 못 읽을 때 쓰는 대체 시간(초) · 임시 1.0")]
public float playerDeathFallbackDuration = 1.0f;
[Tooltip("사망 모션 크로스페이드 시간(초) · 임시 0.10")]
public float playerDeathBlendTime = 0.10f;
[Header("■ 몬스터 스탯 (PD 지시 · 임시 · 추후 테이블)")]
[Tooltip("몬스터 최대 체력 · 임시 10")]
public float enemyHp = 10f;
[Tooltip("이 반경(m) 안에 플레이어가 들어오면 추적한다 · 임시 6")]
public float enemySight = 6f;
[Tooltip("이 반경(m) 안이면 공격한다 · 임시 1.5")]
public float enemyAttackRange = 1.5f;
[Tooltip("추적을 포기하는 거리(m). 시야보다 크게 잡아 경계에서 깜빡이지 않게 한다 · 임시 8")]
public float enemyLoseSight = 8f;
[Tooltip("공격 간격(초) · 임시 1.5")]
public float enemyCooldown = 1.5f;
[Tooltip("1회 공격이 플레이어에게 주는 피해량 · 임시 1")]
public int enemyDamage = 1;
[Tooltip("추적 이동 속도(m/s) · 임시 1.6")]
public float enemyMoveSpeed = 1.6f;
[Tooltip("플레이어를 향해 도는 속도(도/초) · 임시 360")]
public float enemyTurnSpeed = 360f;
[Tooltip("공격 모션 시작 후 피해가 들어가는 시간(초) · 임시 0.3")]
public float enemyAttackHitDelay = 0.3f;
[Tooltip("공격 모션 길이를 Animator 에서 못 읽을 때 쓰는 대체 시간(초)")]
public float enemyAttackFallbackDuration = 0.7f;
[Tooltip("피격 반응 모션 길이(초). 0 이면 재생하지 않는다 · 임시 0.35")]
public float enemyDamageReactionSeconds = 0.35f;
[Tooltip("중력 가속도(m/s²)")]
public float enemyGravity = -19.62f;
[Header("■ 몬스터 사망 연출 (PD 지시 ⑤ · 임시)")]
[Tooltip("Die 클립 길이를 Animator 에서 못 읽을 때 쓰는 대체 시간(초)")]
public float deathDieFallbackDuration = 1.2f;
[Tooltip("Die 클립 종료 후 깜빡이기 시작할 때까지 대기(초) · 임시 0.15")]
public float deathDieHoldSeconds = 0.15f;
[Tooltip("깜빡이는 총 시간(초) · 임시 0.9")]
public float deathBlinkSeconds = 0.9f;
[Tooltip("깜빡이는 횟수(꺼짐 기준) · 임시 6")]
public int deathBlinkCount = 6;
[Tooltip("알파 페이드아웃 시간(초) · 임시 1.0")]
public float deathFadeSeconds = 1.0f;
[Header("■ 데미지 숫자 연출 (PD #702-① · 힘민지 HUDDMGUI 규약 이식)")]
[Tooltip("숫자가 화면에 떠 있는 시간(초) · 힘민지 destroyTime 0.9 동일")]
public float dmgPopupLifetime = 0.9f;
[Tooltip("초당 위로 올라가는 캔버스 단위 거리 · 임시 90")]
public float dmgPopupRiseSpeed = 90f;
[Tooltip("알파 감쇠 속도 계수(Lerp) · 힘민지 alphaSpeed 0.5 대비 가독성 위해 상향 · 임시 2.2")]
public float dmgPopupFadeSpeed = 2.2f;
[Tooltip("겹침 방지용 위치 흔들기 반경(캔버스 단위) · 힘민지 ±25 동일")]
public float dmgPopupJitter = 25f;
[Tooltip("대상 위로 띄우는 화면 높이 보정(캔버스 단위) · 임시 20")]
public float dmgPopupScreenOffsetY = 20f;
[Tooltip("적이 맞았을 때 숫자 색")]
public Color dmgPopupColorToEnemy = new Color(1f, 0.95f, 0.35f, 1f);
[Tooltip("플레이어가 맞았을 때 숫자 색")]
public Color dmgPopupColorToPlayer = new Color(1f, 0.35f, 0.35f, 1f);
[Tooltip("숫자 글자 크기(캔버스 단위) · 임시 46")]
public float dmgPopupFontSize = 72f;
[Tooltip("굵게 표시한다 (PD #703)")]
public bool dmgPopupBold = true;
[Tooltip("검은 아웃라인 두께 0~1 · 임시 0.22 (PD #703)")]
[Range(0f, 1f)] public float dmgPopupOutlineWidth = 0.22f;
[Tooltip("아웃라인 색 · 기본 검정")]
public Color dmgPopupOutlineColor = Color.black;
[Tooltip("글자 두께 보정 1~1. 아웃라인에 획이 먹히지 않게 살짝 굵힌다 · 임시 0.1")]
[Range(-1f, 1f)] public float dmgPopupFaceDilate = 0.1f;
[Tooltip("풀 초기 개수. 모자라면 런타임에 증설한다 · 임시 12")]
public int dmgPopupPoolSize = 12;
[Header("■ 피격 하이라이트 (PD #702-① · MaterialPropertyBlock)")]
[Tooltip("피격 시 몬스터 전신에 입히는 색 · 임시 주황빨강")]
public Color hitFlashColor = new Color(1f, 0.30f, 0.22f, 1f);
[Tooltip("피격 색이 원래 색으로 돌아오는 시간(초) · 임시 0.15")]
public float hitFlashSeconds = 0.15f;
[Tooltip("피격 색 세기 0~1. 1 이면 전부 flashColor 로 덮는다 · 임시 0.85")]
[Range(0f, 1f)] public float hitFlashStrength = 0.85f;
/// <summary>플레이어 1회 공격 피해량. min~max 정수 균등 난수(max 포함).</summary>
public int RollPlayerDamage()
{
int lo = Mathf.Min(playerAttackMin, playerAttackMax);
int hi = Mathf.Max(playerAttackMin, playerAttackMax);
return Random.Range(lo, hi + 1);
}
}
}