Project_WL/Assets/WL/IslandMob/WLIslandMobSettings.cs

107 lines
7.6 KiB
C#

// ─────────────────────────────────────────────────────────────────────────────
// WLIslandMobSettings.cs — 섬 몬스터 존 + 섬 전투 아바타 설정(SO · Resources/WL/WLIslandMobSettings.asset) (#822)
//
// PD 지시(2026-10-09): 섬에서도 몬스터 등장 · 확장 땅 1칸 = 섬 1개 · 섬마다 1곳에서만 · 한도(10) 뒤 긴 쿨타임(3시간) ·
// 남은 시간 텍스트. PD 역제안: 「기본 = 전투 캐릭터 · 농작물 있을 때만 농부」.
// 🔴 SO 는 클래스와 같은 이름의 .cs 에만(816g 교훈).
// ─────────────────────────────────────────────────────────────────────────────
using UnityEngine;
namespace WL.IslandMob
{
public sealed class WLIslandMobSettings : ScriptableObject
{
[Header("스위치")]
[Tooltip("0 이면 전부 무동작(섬은 지금처럼 농부만 · 몬스터 없음)")]
public int enabled_ = 1;
public int verboseLog = 1;
[Header("섬 아바타 — 기본 전투 PC · 농부는 보이지 않는 그림자")]
[Tooltip("1 이면 섬에서 힘민지 전투 PC 를 켜고 조이스틱으로 움직인다(FI 농부는 PC 를 따라다니는 투명 그림자 = 발판·상인·밭 트리거 유지)")]
public int combatAvatarEnabled = 1;
[Tooltip("농부 모드 조건 ① FI 가 농사 중(IsWorking) · 조작 잠김(낚시·나무 흔들기) ② 밭(Farm) 콜라이더까지 이 거리(m) 안 — 0 이면 ②는 안 씀")]
public float farmerModeRadius = 2f;
[Tooltip("농부 모드 조건이 사라진 뒤 전투로 돌아가기까지 대기(초) — 밭 가장자리에서 깜빡임 방지")]
public float farmerExitDelay = 0.4f;
[Tooltip("조이스틱 입력 데드존(0~1)")]
public float moveDeadzone = 0.15f;
[Tooltip("PC 를 FI 자리로 되돌릴 때 NavMesh 탐색 반경(m) — 섬 확장 재베이크 뒤 이탈 복구에도 쓴다")]
public float pcNavSnapRadius = 3f;
[Tooltip("PC 가 NavMesh 밖인지 확인하는 주기(초)")]
public float pcNavCheckSeconds = 1f;
[Tooltip("전투 PC 가 생길 때까지 기다리는 상한(초 · Addressables 비동기)")]
public float pcWaitSeconds = 10f;
[Tooltip("1 이면 섬에서 PC 가 죽으면 부활 팝업 없이 제자리에서 자동 부활(던전의 실패·복귀 흐름이 섬을 재로드하는 사고 방지)")]
public int autoReviveOnIsland = 1;
[Header("타격감 확인용 무적 몬스터 (2026-10-15 PD 「섬에 타격감을 체크할 수 있도록 무적 몬스터 1기를 다시 추가」)")]
[Tooltip("1 = 섬에 무적 몬스터 1마리를 세운다(#828 테스트 모드와 같은 동작 · 체력 되채움). 몬스터 존(zonesEnabled)이 꺼져 있으면 시작 땅에 이 1마리 전용 자리만 만들고(라벨 없음), " +
"켜져 있으면 존 몹 중 1마리만 남긴다. 0 = 없음(PlayerPrefs WL_TrailTest 로 켤 수는 있다).")]
public int hitTestDummy = 1;
[Tooltip("무적 몬스터로 쓸 몹 ID(MonsterList n_MonsterID) — 다른 종류가 먼저 나오면 회수하고 이 종류를 기다린다. 0 = 처음 나온 몹. " +
"101 = 근접 선공 몹(#907 부터 박쥐 · 플레이어에게 다가온다 — 원거리형 102·104 는 거리를 벌려 타격감 보기 어렵다).")]
public int hitTestDummyMobId = 101;
[Tooltip("존이 꺼져 있을 때 무적 몬스터 자리 — 시작 땅(격자 0,0) 중심에서의 오프셋(m · NavMesh 로 맞춘다).")]
public Vector3 hitTestDummyOffset = new Vector3(2f, 0f, -1.5f);
[Header("몬스터 존 — 땅 1칸(FI Island) 당 1곳")]
[Tooltip("#850 PD 「당분간 섬에 일반 몬스터를 등장시키지 마」 — 0 이면 몬스터 존(스포너·라벨)을 만들지 않는다. 전투 PC·자동 부활 등 섬 아바타 기능은 그대로(enabled_ 와 별개)")]
public int zonesEnabled = 1;
[Tooltip("MonsterAppear 표의 SpawnerID(몹 종류·리젠 간격 f_SpawnerDelay 는 표가 정한다). 🔴 e_SpawnerType = Random 이어야 한 마리 죽을 때마다 리젠된다 · 1 = 힘민지 Lv1 잡몹(101~104 · 딜레이 4 s). 813001 은 PhaseAllKill 이라 부적합")]
public int spawnerId = 1;
[Tooltip("존에 동시에 살아 있는 몬스터 상한 — 표의 n_MaxMonsterCount 가 더 커도 초과분은 즉시 회수(Off)하고 누적에 세지 않는다")]
public int aliveMax = 3;
[Tooltip("등장하는 몬스터의 최대 HP 를 이 값으로 덮는다(PD 2026-10-09 「플레이어 공격 3~4방」 · 기본 공격력 5 기준 18). 0 = MonsterAppear 표 값(스포너 1 은 300)")]
public double mobMaxHp = 18;
[Tooltip("타일 중심에서 존 자리까지의 오프셋(m · 타일 한 변 8 m)")]
public Vector3 zoneOffset = new Vector3(2.5f, 0f, 2.5f);
[Tooltip("존 반경(m) = 몹 생성 범위(MobGenRange)")]
public float zoneRadius = 3f;
[Tooltip("존 자리를 NavMesh 위로 맞출 탐색 반경(m)")]
public float zoneNavSnap = 4f;
[Tooltip("1 이면 다리 타일에는 존을 두지 않는다")]
public int skipBridgeTiles = 1;
[Tooltip("밭·플로우 설치물과 이 거리(m) 안이면 다른 모서리 오프셋을 시도한다 · 0 = 안 피함")]
public float avoidFarmRadius = 3f;
[Tooltip("새 타일 검색 주기(초)")]
public float rescanSeconds = 3f;
[Header("한도 · 쿨타임")]
[Tooltip("존당 누적 등장 한도(마리) — 이 수가 생성되면 더 안 나오고 쿨타임 시작")]
public int spawnLimit = 10;
[Tooltip("쿨타임(초) · 10800 = 3시간 · 실시간(앱을 꺼도 흐른다)")]
public double cooldownSeconds = 10800;
[Tooltip("한도를 넘긴 뒤 리젠으로 새로 나온 몹은 즉시 회수한다(원본 리젠 예약은 끊을 수 없어 사후 회수)")]
public int recallOverLimit = 1;
[Tooltip("PlayerPrefs 키 접두 — 존 누적 수·재등장 시각 저장")]
public string prefsPrefix = "WL_MobZone_";
[Tooltip("1 이면 섬 세이브 초기화(실행마다) 때 존 기록도 지운다")]
public int resetWithIslandSave = 1;
[Header("존 라벨(3D 글자)")]
public float labelHeight = 1.8f;
[Tooltip("{0} = 누적 등장 · {1} = 한도")]
public string labelActiveFormat = "몬스터 {0}/{1}";
[Tooltip("{0} = 남은 시간 TimeSpan · {1} = 남아 있는 몬스터")]
public string labelCooldownFormat = "재등장 {0:hh\\:mm\\:ss}";
public string labelRemainSuffix = " · 남은 몬스터 {0}";
public float labelFontSize = 3.2f;
public Color labelActiveColor = new Color(1f, 0.85f, 0.4f, 1f);
public Color labelCooldownColor = new Color(0.8f, 0.9f, 1f, 1f);
[Tooltip("라벨 갱신 주기(초)")]
public float labelRefreshSeconds = 1f;
static WLIslandMobSettings s_cache;
public static WLIslandMobSettings Instance
{
get
{
if (s_cache == null) s_cache = Resources.Load<WLIslandMobSettings>("WL/WLIslandMobSettings");
return s_cache;
}
}
public static bool Enabled { get { var c = Instance; return c != null && c.enabled_ != 0; } }
}
}