Merge branch 'wl/ui/WL-816m-dungeon-result'
This commit is contained in:
commit
9ae58d10ac
|
|
@ -0,0 +1,19 @@
|
|||
ⓒ HUD 던전1 "던전 1" "00:42" "남은 적 3 / 3"
|
||||
→ E:\NerdNavis\WL_wt\ui\Screenshots_WL\WL816m\c_hud_dungeon1.png (62853 B · 1080×1920)
|
||||
ⓐ 던전1 "던전 1 클리어!" 행=7 골드=96
|
||||
→ E:\NerdNavis\WL_wt\ui\Screenshots_WL\WL816m\a_dungeon1_clear.png (145037 B · 1080×1920)
|
||||
ⓑ 던전3 "던전 3 클리어!" 골드=192
|
||||
→ E:\NerdNavis\WL_wt\ui\Screenshots_WL\WL816m\b_dungeon3_clear.png (145609 B · 1080×1920)
|
||||
ⓓ HUD 스테이지 "스테이지 3" "00:08" "남은 적 5 / 12"
|
||||
→ E:\NerdNavis\WL_wt\ui\Screenshots_WL\WL816m\d1_hud_stage_new.png (66700 B · 1080×1920)
|
||||
ⓓ 스테이지 클리어(새 경로) "스테이지 3 클리어!" 행=6
|
||||
→ E:\NerdNavis\WL_wt\ui\Screenshots_WL\WL816m\d1_stage_clear_new.png (146352 B · 1080×1920)
|
||||
→ E:\NerdNavis\WL_wt\ui\Screenshots_WL\WL816m\d2_hud_stage_legacy.png (66700 B · 1080×1920)
|
||||
ⓓ 스테이지 클리어(구 4인자) "스테이지 3 클리어!" 행=6
|
||||
→ E:\NerdNavis\WL_wt\ui\Screenshots_WL\WL816m\d2_stage_clear_legacy.png (146352 B · 1080×1920)
|
||||
ⓔ 실패 "시간 초과! / 남은 적 4마리" 버튼=[다시 도전] [섬으로]
|
||||
→ E:\NerdNavis\WL_wt\ui\Screenshots_WL\WL816m\e_fail.png (84370 B · 1080×1920)
|
||||
|
||||
픽셀 대조 (MD5) — 새 경로 vs 816m 이전 경로
|
||||
HUD 동일 ae76d1c543ba / ae76d1c543ba
|
||||
결과창 동일 f77b6ffa7382 / f77b6ffa7382
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
# WL816m Probe 2026-09-15 00:47:59 (edit mode · Play 0 · 로그인 0)
|
||||
playMode=False
|
||||
|
||||
── ① 설정 실값 (SO · 하드코딩 0)
|
||||
[PASS] WLStageUiSettings 에셋 로드
|
||||
던전모드=True · 제목 "{0} 클리어!" · HUD "{0}" · 대체이름 "던전 {0}"
|
||||
골드행=True · 라벨 "획득 골드" · 값 "+{0}"
|
||||
스테이지 제목(불변) "스테이지 {0} 클리어!" · 스테이지 HUD(불변) "스테이지 {0}"
|
||||
[PASS] 던전 표 3행 이상
|
||||
던전 표[0] id=1 "던전 1" stageIndex=10 → 스테이지 표 id=11(지금 화면에 나오던 숫자) · goldMultiplier=1.00
|
||||
던전 표[1] id=2 "던전 2" stageIndex=11 → 스테이지 표 id=12(지금 화면에 나오던 숫자) · goldMultiplier=1.50
|
||||
던전 표[2] id=3 "던전 3" stageIndex=12 → 스테이지 표 id=13(지금 화면에 나오던 숫자) · goldMultiplier=2.00
|
||||
던전 표[3] id=4 "던전 4" stageIndex=13 → 스테이지 표 id=14(지금 화면에 나오던 숫자) · goldMultiplier=3.00
|
||||
보상 값 — clearBonus=60 perKill=12 bossBonus=120 배수적용=1 rewardEnabled=1
|
||||
|
||||
── ② 던전 판정 = WLDungeonSceneSetup.Current 하나뿐
|
||||
[PASS] Current=null → 던전 아님(#815 스테이지 모드)
|
||||
[PASS] 이름 null
|
||||
[PASS] Current=던전1 행 → 던전으로 판정
|
||||
이름 = "던전 1"
|
||||
[PASS] 이름 = 표의 displayName
|
||||
displayName 빈 경우 대체 이름 = "던전 1"
|
||||
[PASS] 대체 이름 = dungeonNameFallbackFormat + id
|
||||
|
||||
── ③ 획득 골드 = 섬 축 WLIslandBridge.ComputeGold 재사용(식 1곳)
|
||||
던전 1 (index 10 · 처치 3) → 96 / 섬 축 직접 = 96
|
||||
[PASS] 던전 1 = 96 (816g §5 실측과 같음)
|
||||
던전 3 (index 12 · 처치 3) → 192
|
||||
[PASS] 던전 3 = 192 (816i2 §3 실측과 같음)
|
||||
[PASS] UI 표시값 == 섬 축 지급 계산값(두 곳 일치)
|
||||
|
||||
── ④ 결과창 — 던전 1 / 던전 3 (StageEvents 실제 Dispatch 경로)
|
||||
제목 "던전 1 클리어!" · 행 7개 · 던전=True "던전 1" 골드=96
|
||||
본문 ⤵
|
||||
던전 1 클리어!
|
||||
클리어 시간 : 00:35
|
||||
처치 : 3 / 3
|
||||
엘리트 처치 : 0
|
||||
최대 연쇄 : 0
|
||||
피격 / 물약 : 0회 / 0개
|
||||
재도전 : 0회
|
||||
획득 골드 : +96
|
||||
무피격 클리어!
|
||||
[PASS] 제목 = "던전 1 클리어!" (지금까지는 "스테이지 11 클리어!")
|
||||
[PASS] 행 = "획득 골드 : +96"
|
||||
[PASS] 행 6 + 획득 골드 1 = 7
|
||||
제목 "던전 3 클리어!" · 골드=192
|
||||
[PASS] 제목 = "던전 3 클리어!"
|
||||
[PASS] 행 = "획득 골드 : +192"
|
||||
|
||||
── ⑤ HUD 단계 라벨 — 던전이면 「던전 N」
|
||||
던전 1 → 단계 "던전 1" · 남은 적 "남은 적 3 / 3"
|
||||
[PASS] HUD 라벨 = "던전 1" (지금까지는 "스테이지 11")
|
||||
던전 3 → 단계 "던전 3"
|
||||
[PASS] HUD 라벨 = "던전 3"
|
||||
[PASS] 같은 이름 재입력 시 쓰기 0회(GC 0)
|
||||
|
||||
── ⑥ #815 스테이지 모드 무변경 (Current = null)
|
||||
단계 "스테이지 3" · 시간 "00:08" · 남은 적 "남은 적 5 / 12"
|
||||
[PASS] HUD = "스테이지 3" 그대로
|
||||
제목 "스테이지 3 클리어!" · 행 6개 · 던전=False
|
||||
본문 ⤵
|
||||
스테이지 3 클리어!
|
||||
클리어 시간 : 00:35
|
||||
처치 : 12 / 12
|
||||
엘리트 처치 : 0
|
||||
최대 연쇄 : 0
|
||||
피격 / 물약 : 0회 / 0개
|
||||
재도전 : 0회
|
||||
무피격 클리어!
|
||||
[PASS] 제목 = "스테이지 3 클리어!" 그대로
|
||||
[PASS] 행 6개 그대로(획득 골드 없음)
|
||||
[PASS] 본문에 「획득 골드」 0건
|
||||
[PASS] 던전 문맥 없음
|
||||
구 경로 본문 ⤵
|
||||
스테이지 3 클리어!
|
||||
클리어 시간 : 00:35
|
||||
처치 : 12 / 12
|
||||
엘리트 처치 : 0
|
||||
최대 연쇄 : 0
|
||||
피격 / 물약 : 0회 / 0개
|
||||
재도전 : 0회
|
||||
무피격 클리어!
|
||||
[PASS] 구 4인자 경로(=816m 이전) == 새 경로 본문 문자열 동일
|
||||
|
||||
── ⑦ C8 롤백 — dungeonModeEnabled = 0 이면 던전도 지금까지 그대로
|
||||
롤백 제목 "스테이지 11 클리어!" · HUD "스테이지 11" · 행 6
|
||||
[PASS] 롤백 = "스테이지 11 클리어!"(PD 가 본 화면)
|
||||
[PASS] 롤백 HUD = "스테이지 11"
|
||||
[PASS] 롤백 행 6개
|
||||
|
||||
── ⑦ PlayerPrefs 무변경 (섬 축은 에디트 모드에 설치되지 않는다)
|
||||
키 "WL_Island_PendingGold" 전=0 후=0
|
||||
[PASS] 보류 보상 PlayerPrefs 무변경
|
||||
|
||||
RESULT PASS (pass=28 fail=0)
|
||||
|
|
@ -0,0 +1,504 @@
|
|||
// WL-816m 프로브 — 던전 결과창(던전 이름 + 획득 골드) 실측 (에디트 모드 · Play 0 · 로그인 0).
|
||||
// unity command run_script --file AgentScripts/WL816m_Probe.cs --entry WL816m_Probe.SaveAsset
|
||||
// unity command run_script --file AgentScripts/WL816m_Probe.cs --entry WL816m_Probe.RunAll
|
||||
// unity command run_script --file AgentScripts/WL816m_Probe.cs --entry WL816m_Probe.Capture
|
||||
// 산출물: <worktree>/AgentScripts/WL816m_PROBE.txt · Screenshots_WL/WL816m/*.png
|
||||
// 🔴 NewGameUI.prefab 은 LoadPrefabContents 로 열고 저장하지 않는다(UnloadPrefabContents).
|
||||
// 🔴 PlayerPrefs 는 건드리지 않는다 — 에디트 모드라 WLIslandBridge 는 설치되지 않는다(전후 값 실측 대조).
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using WL.UI;
|
||||
using WL.Island;
|
||||
|
||||
public static class WL816m_Probe
|
||||
{
|
||||
const string kPrefab = "Assets/Res_Addr/MainUI/NewGameUI.prefab";
|
||||
|
||||
static StringBuilder _o;
|
||||
static int _pass, _fail;
|
||||
|
||||
static string Root { get { return Directory.GetParent(Application.dataPath).FullName; } }
|
||||
static void H(string s) { _o.AppendLine(); _o.AppendLine("── " + s); }
|
||||
static void N(string s) { _o.AppendLine(" " + s); }
|
||||
static bool Chk(bool ok, string what)
|
||||
{
|
||||
if (ok) { _pass++; _o.AppendLine(" [PASS] " + what); }
|
||||
else { _fail++; _o.AppendLine(" [FAIL] " + what); }
|
||||
return ok;
|
||||
}
|
||||
|
||||
// ═════════════════════════════════════════════════════════════════════
|
||||
// ① SO 에 새 필드를 직렬화한다(에셋 YAML 에 값이 보이도록 · C45)
|
||||
// ═════════════════════════════════════════════════════════════════════
|
||||
public static string SaveAsset()
|
||||
{
|
||||
var g = WLStageUiSettings.Instance;
|
||||
if (g == null) return "WLStageUiSettings 에셋 없음";
|
||||
EditorUtility.SetDirty(g);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
return "저장 — 던전모드=" + g.dungeonModeEnabled + " 제목=\"" + g.dungeonClearTitleFormat +
|
||||
"\" 라벨=\"" + g.dungeonLabelFormat + "\" 골드행=" + g.dungeonGoldRowEnabled +
|
||||
" \"" + g.rowDungeonGoldLabel + "\" \"" + g.rowDungeonGoldFormat + "\"";
|
||||
}
|
||||
|
||||
// ═════════════════════════════════════════════════════════════════════
|
||||
// ② 실측
|
||||
// ═════════════════════════════════════════════════════════════════════
|
||||
public static string RunAll()
|
||||
{
|
||||
_o = new StringBuilder();
|
||||
_pass = _fail = 0;
|
||||
_o.AppendLine("# WL816m Probe " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " (edit mode · Play 0 · 로그인 0)");
|
||||
_o.AppendLine("playMode=" + Application.isPlaying);
|
||||
|
||||
var cfg = WLIslandSettings.Instance;
|
||||
string prefsKey = cfg != null ? cfg.pendingPrefsKey : "WL_Island_PendingGold";
|
||||
int prefsBefore = PlayerPrefs.GetInt(prefsKey, -1);
|
||||
var savedCurrent = WLDungeonSceneSetup.Current;
|
||||
|
||||
GameObject prefabRoot = null;
|
||||
try
|
||||
{
|
||||
Step0_Settings(cfg);
|
||||
prefabRoot = PrefabUtility.LoadPrefabContents(kPrefab);
|
||||
BuildRig(prefabRoot);
|
||||
Step1_Detect(cfg);
|
||||
Step2_Gold(cfg);
|
||||
Step3_Result(cfg, prefabRoot);
|
||||
Step4_Hud(cfg, prefabRoot);
|
||||
Step5_StageUnchanged(prefabRoot);
|
||||
Step6_Rollback(cfg, prefabRoot);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_fail++;
|
||||
_o.AppendLine(" [FAIL] 예외 " + e.GetType().Name + " : " + e.Message);
|
||||
_o.AppendLine(e.StackTrace);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try { StageUiBridge.Teardown(); RunHud.Teardown(); RunResultUI.Teardown(); } catch { }
|
||||
DestroyRig();
|
||||
WLDungeonSceneSetup.Current = savedCurrent;
|
||||
if (prefabRoot != null) PrefabUtility.UnloadPrefabContents(prefabRoot);
|
||||
}
|
||||
|
||||
int prefsAfter = PlayerPrefs.GetInt(prefsKey, -1);
|
||||
H("⑦ PlayerPrefs 무변경 (섬 축은 에디트 모드에 설치되지 않는다)");
|
||||
N("키 \"" + prefsKey + "\" 전=" + prefsBefore + " 후=" + prefsAfter);
|
||||
Chk(prefsBefore == prefsAfter, "보류 보상 PlayerPrefs 무변경");
|
||||
|
||||
_o.AppendLine();
|
||||
_o.AppendLine("RESULT " + (_fail == 0 ? "PASS" : "FAIL") + " (pass=" + _pass + " fail=" + _fail + ")");
|
||||
string path = Path.Combine(Path.Combine(Root, "AgentScripts"), "WL816m_PROBE.txt");
|
||||
File.WriteAllText(path, _o.ToString(), new UTF8Encoding(true));
|
||||
return _o.ToString();
|
||||
}
|
||||
|
||||
static void Step0_Settings(WLIslandSettings cfg)
|
||||
{
|
||||
H("① 설정 실값 (SO · 하드코딩 0)");
|
||||
var g = WLStageUiSettings.Instance;
|
||||
Chk(g != null, "WLStageUiSettings 에셋 로드");
|
||||
if (g == null) return;
|
||||
N("던전모드=" + g.dungeonModeEnabled + " · 제목 \"" + g.dungeonClearTitleFormat + "\" · HUD \"" +
|
||||
g.dungeonLabelFormat + "\" · 대체이름 \"" + g.dungeonNameFallbackFormat + "\"");
|
||||
N("골드행=" + g.dungeonGoldRowEnabled + " · 라벨 \"" + g.rowDungeonGoldLabel + "\" · 값 \"" + g.rowDungeonGoldFormat + "\"");
|
||||
N("스테이지 제목(불변) \"" + g.stageClearTitleFormat + "\" · 스테이지 HUD(불변) \"" + g.stageLabelFormat + "\"");
|
||||
Chk(cfg != null && cfg.dungeons != null && cfg.dungeons.Length >= 3, "던전 표 3행 이상");
|
||||
if (cfg == null || cfg.dungeons == null) return;
|
||||
for (int i = 0; i < cfg.dungeons.Length; i++)
|
||||
{
|
||||
var d = cfg.dungeons[i];
|
||||
int id = StageIdOf(d.stageIndex);
|
||||
N("던전 표[" + i + "] id=" + d.id + " \"" + d.displayName + "\" stageIndex=" + d.stageIndex +
|
||||
" → 스테이지 표 id=" + id + "(지금 화면에 나오던 숫자) · goldMultiplier=" +
|
||||
WLIslandBridge.MultiplierOf(d.stageIndex).ToString("F2"));
|
||||
}
|
||||
N("보상 값 — clearBonus=" + cfg.goldClearBonus + " perKill=" + cfg.goldPerKill + " bossBonus=" +
|
||||
cfg.goldBossBonus + " 배수적용=" + cfg.applyGoldMultiplier + " rewardEnabled=" + cfg.rewardEnabled);
|
||||
}
|
||||
|
||||
static int StageIdOf(int index)
|
||||
{
|
||||
var t = WL.Combat.Stage.WLStageTable.Instance;
|
||||
if (t == null) return -1;
|
||||
var def = t.Get(index);
|
||||
return def != null ? def.id : -1;
|
||||
}
|
||||
|
||||
static void Step1_Detect(WLIslandSettings cfg)
|
||||
{
|
||||
H("② 던전 판정 = WLDungeonSceneSetup.Current 하나뿐");
|
||||
WLDungeonSceneSetup.Current = null;
|
||||
Chk(StageUiBridge.CurrentDungeon == null, "Current=null → 던전 아님(#815 스테이지 모드)");
|
||||
Chk(StageUiBridge.DungeonNameOf(null) == null, "이름 null");
|
||||
|
||||
WLDungeonSceneSetup.Current = cfg.dungeons[0];
|
||||
var d1 = StageUiBridge.CurrentDungeon;
|
||||
Chk(d1 != null, "Current=던전1 행 → 던전으로 판정");
|
||||
N("이름 = \"" + StageUiBridge.DungeonNameOf(d1) + "\"");
|
||||
Chk(StageUiBridge.DungeonNameOf(d1) == cfg.dungeons[0].displayName, "이름 = 표의 displayName");
|
||||
|
||||
// displayName 이 비었을 때의 대체 이름
|
||||
string saved = cfg.dungeons[0].displayName;
|
||||
cfg.dungeons[0].displayName = "";
|
||||
string fb = StageUiBridge.DungeonNameOf(StageUiBridge.CurrentDungeon);
|
||||
cfg.dungeons[0].displayName = saved;
|
||||
N("displayName 빈 경우 대체 이름 = \"" + fb + "\"");
|
||||
Chk(fb == "던전 " + cfg.dungeons[0].id, "대체 이름 = dungeonNameFallbackFormat + id");
|
||||
}
|
||||
|
||||
static void Step2_Gold(WLIslandSettings cfg)
|
||||
{
|
||||
H("③ 획득 골드 = 섬 축 WLIslandBridge.ComputeGold 재사용(식 1곳)");
|
||||
var r1 = Cleared(cfg.dungeons[0].stageIndex, 3, false);
|
||||
int g1 = StageUiBridge.DungeonGoldOf(in r1);
|
||||
N("던전 1 (index " + cfg.dungeons[0].stageIndex + " · 처치 3) → " + g1 +
|
||||
" / 섬 축 직접 = " + WLIslandBridge.ComputeGold(cfg, in r1));
|
||||
Chk(g1 == 96, "던전 1 = 96 (816g §5 실측과 같음)");
|
||||
|
||||
var r3 = Cleared(cfg.dungeons[2].stageIndex, 3, false);
|
||||
int g3 = StageUiBridge.DungeonGoldOf(in r3);
|
||||
N("던전 3 (index " + cfg.dungeons[2].stageIndex + " · 처치 3) → " + g3);
|
||||
Chk(g3 == 192, "던전 3 = 192 (816i2 §3 실측과 같음)");
|
||||
Chk(g1 == WLIslandBridge.ComputeGold(cfg, in r1) && g3 == WLIslandBridge.ComputeGold(cfg, in r3),
|
||||
"UI 표시값 == 섬 축 지급 계산값(두 곳 일치)");
|
||||
}
|
||||
|
||||
static WL.Combat.Stage.StageClearResult Cleared(int index, int killed, bool isBoss)
|
||||
{
|
||||
return new WL.Combat.Stage.StageClearResult
|
||||
{
|
||||
index = index, stageId = StageIdOf(index), win = true,
|
||||
failReason = WL.Combat.Stage.StageFailReason.None,
|
||||
elapsedSec = 34.2f, timeLimit = 60f, killed = killed, total = killed, remaining = 0,
|
||||
retries = 0, isLastStage = false, isBoss = isBoss,
|
||||
time = Time.unscaledTime, frame = Time.frameCount,
|
||||
};
|
||||
}
|
||||
|
||||
// ── 목업 캔버스(815d 와 같은 방식) — TitleText·PhaseText 를 읽으려면 노드가 있어야 한다 ──
|
||||
static GameObject _rig;
|
||||
static Camera _cam;
|
||||
static RectTransform _crt;
|
||||
static ReviveDialog _revive;
|
||||
|
||||
static void BuildRig(GameObject prefabRoot)
|
||||
{
|
||||
_rig = new GameObject("WL816m_Rig");
|
||||
_rig.hideFlags = HideFlags.HideAndDontSave;
|
||||
var camGo = new GameObject("Cam");
|
||||
camGo.transform.SetParent(_rig.transform, false);
|
||||
_cam = camGo.AddComponent<Camera>();
|
||||
_cam.clearFlags = CameraClearFlags.SolidColor;
|
||||
_cam.backgroundColor = new Color(0.09f, 0.10f, 0.12f, 1f);
|
||||
_cam.orthographic = true; _cam.orthographicSize = 960f;
|
||||
_cam.nearClipPlane = 0.1f; _cam.farClipPlane = 5000f;
|
||||
camGo.transform.position = new Vector3(0f, 0f, -1000f);
|
||||
|
||||
var canvasGo = new GameObject("Canvas", typeof(RectTransform));
|
||||
canvasGo.transform.SetParent(_rig.transform, false);
|
||||
canvasGo.layer = 5;
|
||||
var canvas = canvasGo.AddComponent<Canvas>();
|
||||
canvas.renderMode = RenderMode.ScreenSpaceCamera;
|
||||
canvas.worldCamera = _cam;
|
||||
canvas.planeDistance = 500f;
|
||||
var scaler = canvasGo.AddComponent<UnityEngine.UI.CanvasScaler>();
|
||||
scaler.uiScaleMode = UnityEngine.UI.CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
||||
scaler.referenceResolution = new Vector2(1080f, 1920f);
|
||||
scaler.matchWidthOrHeight = 0.5f;
|
||||
canvasGo.AddComponent<UnityEngine.UI.GraphicRaycaster>();
|
||||
_crt = (RectTransform)canvasGo.transform;
|
||||
_crt.sizeDelta = new Vector2(1080f, 1920f);
|
||||
|
||||
var ingame = NewRect(_crt, "IngameUIs");
|
||||
var wlHud = NewRect(ingame, "WL_HUD");
|
||||
|
||||
var font = RunHud.BorrowFont(prefabRoot.transform);
|
||||
RunHud.SetFont(font); RunResultUI.SetFont(font);
|
||||
StageUiBridge.SetUiRootForProbe(prefabRoot.transform);
|
||||
RunHud.Subscribe(true); RunResultUI.Subscribe(true); StageUiBridge.Subscribe(true);
|
||||
RunHud.Bind(_crt); RunResultUI.Bind(_crt);
|
||||
|
||||
var dlgGo = new GameObject("WL_ReviveDialog", typeof(RectTransform));
|
||||
dlgGo.layer = 5;
|
||||
dlgGo.transform.SetParent(wlHud, false);
|
||||
_revive = dlgGo.AddComponent<ReviveDialog>();
|
||||
_revive.SetFont(font);
|
||||
_revive.Initialize();
|
||||
}
|
||||
|
||||
static void DestroyRig()
|
||||
{
|
||||
if (_rig != null) UnityEngine.Object.DestroyImmediate(_rig);
|
||||
_rig = null; _cam = null; _crt = null; _revive = null;
|
||||
}
|
||||
|
||||
static void Step3_Result(WLIslandSettings cfg, GameObject prefabRoot)
|
||||
{
|
||||
H("④ 결과창 — 던전 1 / 던전 3 (StageEvents 실제 Dispatch 경로)");
|
||||
// 던전 1
|
||||
WLDungeonSceneSetup.Current = cfg.dungeons[0];
|
||||
int idx1 = cfg.dungeons[0].stageIndex;
|
||||
WLStageUiProbeHooks.RaiseEntered(idx1, StageIdOf(idx1), 3, 60f, Vector3.zero, 13f, 1.5f, 0);
|
||||
StageUiBridge.ProbeSetInStage(true);
|
||||
WLStageUiProbeHooks.RaiseCleared(idx1, StageIdOf(idx1), 34.2f, 60f, 3, 3, 0, false, false);
|
||||
N("제목 \"" + RunResultUI.TitleText + "\" · 행 " + RunResultUI.VisibleRows + "개 · 던전=" +
|
||||
RunResultUI.IsDungeonResult + " \"" + RunResultUI.DungeonName + "\" 골드=" + RunResultUI.DungeonGold);
|
||||
N("본문 ⤵\n" + Indent(RunResultUI.BodyText));
|
||||
Chk(RunResultUI.TitleText == "던전 1 클리어!", "제목 = \"던전 1 클리어!\" (지금까지는 \"스테이지 11 클리어!\")");
|
||||
Chk(RunResultUI.BodyText.Contains("획득 골드 : +96"), "행 = \"획득 골드 : +96\"");
|
||||
Chk(RunResultUI.VisibleRows == 7, "행 6 + 획득 골드 1 = 7");
|
||||
|
||||
// 던전 3
|
||||
RunResultUI.Hide();
|
||||
WLDungeonSceneSetup.Current = cfg.dungeons[2];
|
||||
int idx3 = cfg.dungeons[2].stageIndex;
|
||||
WLStageUiProbeHooks.RaiseEntered(idx3, StageIdOf(idx3), 3, 60f, Vector3.zero, 13f, 1.5f, 0);
|
||||
StageUiBridge.ProbeSetInStage(true);
|
||||
WLStageUiProbeHooks.RaiseCleared(idx3, StageIdOf(idx3), 41.5f, 60f, 3, 3, 0, false, false);
|
||||
N("제목 \"" + RunResultUI.TitleText + "\" · 골드=" + RunResultUI.DungeonGold);
|
||||
Chk(RunResultUI.TitleText == "던전 3 클리어!", "제목 = \"던전 3 클리어!\"");
|
||||
Chk(RunResultUI.BodyText.Contains("획득 골드 : +192"), "행 = \"획득 골드 : +192\"");
|
||||
}
|
||||
|
||||
static string Indent(string s)
|
||||
{
|
||||
if (string.IsNullOrEmpty(s)) return " (빈 본문)";
|
||||
var lines = s.Replace("\r", "").Split('\n');
|
||||
var sb = new StringBuilder();
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
if (lines[i].Length > 0) sb.AppendLine(" " + lines[i]);
|
||||
return sb.ToString().TrimEnd();
|
||||
}
|
||||
|
||||
static void Step4_Hud(WLIslandSettings cfg, GameObject prefabRoot)
|
||||
{
|
||||
H("⑤ HUD 단계 라벨 — 던전이면 「던전 N」");
|
||||
WLDungeonSceneSetup.Current = cfg.dungeons[0];
|
||||
int idx1 = cfg.dungeons[0].stageIndex;
|
||||
WLStageUiProbeHooks.RaiseEntered(idx1, StageIdOf(idx1), 3, 60f, Vector3.zero, 13f, 1.5f, 0);
|
||||
N("던전 1 → 단계 \"" + RunHud.PhaseText + "\" · 남은 적 \"" + RunHud.EnemyText + "\"");
|
||||
Chk(RunHud.PhaseText == "던전 1", "HUD 라벨 = \"던전 1\" (지금까지는 \"스테이지 11\")");
|
||||
|
||||
WLDungeonSceneSetup.Current = cfg.dungeons[2];
|
||||
int idx3 = cfg.dungeons[2].stageIndex;
|
||||
WLStageUiProbeHooks.RaiseStarted(idx3, StageIdOf(idx3), 3, 60f, 0);
|
||||
N("던전 3 → 단계 \"" + RunHud.PhaseText + "\"");
|
||||
Chk(RunHud.PhaseText == "던전 3", "HUD 라벨 = \"던전 3\"");
|
||||
|
||||
int w0 = RunHud.StageLabelWrites;
|
||||
WLStageUiProbeHooks.RaiseStarted(idx3, StageIdOf(idx3), 3, 60f, 0);
|
||||
Chk(RunHud.StageLabelWrites == w0, "같은 이름 재입력 시 쓰기 0회(GC 0)");
|
||||
}
|
||||
|
||||
static void Step5_StageUnchanged(GameObject prefabRoot)
|
||||
{
|
||||
H("⑥ #815 스테이지 모드 무변경 (Current = null)");
|
||||
WLDungeonSceneSetup.Current = null;
|
||||
RunResultUI.Hide();
|
||||
WLStageUiProbeHooks.RaiseEntered(2, 3, 12, 60f, Vector3.zero, 14f, 1.5f, 0);
|
||||
WLStageUiProbeHooks.RaiseEnemyCount(2, 5, 12);
|
||||
WLStageUiProbeHooks.RaiseTime(2, 8f, 60f);
|
||||
N("단계 \"" + RunHud.PhaseText + "\" · 시간 \"" + RunHud.TimerText + "\" · 남은 적 \"" + RunHud.EnemyText + "\"");
|
||||
Chk(RunHud.PhaseText == "스테이지 3", "HUD = \"스테이지 3\" 그대로");
|
||||
|
||||
StageUiBridge.ProbeSetInStage(true);
|
||||
WLStageUiProbeHooks.RaiseCleared(2, 3, 34.2f, 60f, 12, 12, 0, false, false);
|
||||
N("제목 \"" + RunResultUI.TitleText + "\" · 행 " + RunResultUI.VisibleRows + "개 · 던전=" + RunResultUI.IsDungeonResult);
|
||||
N("본문 ⤵\n" + Indent(RunResultUI.BodyText));
|
||||
Chk(RunResultUI.TitleText == "스테이지 3 클리어!", "제목 = \"스테이지 3 클리어!\" 그대로");
|
||||
Chk(RunResultUI.VisibleRows == 6, "행 6개 그대로(획득 골드 없음)");
|
||||
Chk(!RunResultUI.BodyText.Contains("획득 골드"), "본문에 「획득 골드」 0건");
|
||||
Chk(!RunResultUI.IsDungeonResult && RunResultUI.DungeonGold == -1, "던전 문맥 없음");
|
||||
|
||||
// 구 경로(4인자 = 816m 이전 동작)와 같은 본문인가 — 진짜 before/after 대조
|
||||
string after = RunResultUI.BodyText;
|
||||
var r = Cleared(2, 12, false);
|
||||
RunResultUI.Hide();
|
||||
RunResultUI.SetStageMode(true);
|
||||
RunResultUI.ShowStage(in r, 0, 0, 0); // 816m 이전과 같은 진입점
|
||||
RunResultUI.BuildBody(WLRunUiSettings.Instance);
|
||||
N("구 경로 본문 ⤵\n" + Indent(RunResultUI.BodyText));
|
||||
Chk(RunResultUI.BodyText == after, "구 4인자 경로(=816m 이전) == 새 경로 본문 문자열 동일");
|
||||
}
|
||||
|
||||
static void Step6_Rollback(WLIslandSettings cfg, GameObject prefabRoot)
|
||||
{
|
||||
H("⑦ C8 롤백 — dungeonModeEnabled = 0 이면 던전도 지금까지 그대로");
|
||||
var g = WLStageUiSettings.Instance;
|
||||
bool saved = g.dungeonModeEnabled;
|
||||
try
|
||||
{
|
||||
g.dungeonModeEnabled = false;
|
||||
WLDungeonSceneSetup.Current = cfg.dungeons[0];
|
||||
int idx1 = cfg.dungeons[0].stageIndex;
|
||||
RunResultUI.Hide();
|
||||
WLStageUiProbeHooks.RaiseEntered(idx1, StageIdOf(idx1), 3, 60f, Vector3.zero, 13f, 1.5f, 0);
|
||||
StageUiBridge.ProbeSetInStage(true);
|
||||
WLStageUiProbeHooks.RaiseCleared(idx1, StageIdOf(idx1), 34.2f, 60f, 3, 3, 0, false, false);
|
||||
N("롤백 제목 \"" + RunResultUI.TitleText + "\" · HUD \"" + RunHud.PhaseText + "\" · 행 " + RunResultUI.VisibleRows);
|
||||
Chk(RunResultUI.TitleText == "스테이지 11 클리어!", "롤백 = \"스테이지 11 클리어!\"(PD 가 본 화면)");
|
||||
Chk(RunHud.PhaseText == "스테이지 11", "롤백 HUD = \"스테이지 11\"");
|
||||
Chk(RunResultUI.VisibleRows == 6, "롤백 행 6개");
|
||||
}
|
||||
finally { g.dungeonModeEnabled = saved; }
|
||||
}
|
||||
|
||||
// ═════════════════════════════════════════════════════════════════════
|
||||
// ③ 캡처 — 1080×1920 목업(실 노드 · 실 값 · RenderTexture · 815d 와 같은 방식)
|
||||
// ═════════════════════════════════════════════════════════════════════
|
||||
public static string Capture()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
string dir = Path.Combine(Path.Combine(Root, "Screenshots_WL"), "WL816m");
|
||||
Directory.CreateDirectory(dir);
|
||||
|
||||
var cfg = WLIslandSettings.Instance;
|
||||
var savedCurrent = WLDungeonSceneSetup.Current;
|
||||
GameObject prefabRoot = null;
|
||||
try
|
||||
{
|
||||
prefabRoot = PrefabUtility.LoadPrefabContents(kPrefab);
|
||||
BuildRig(prefabRoot);
|
||||
var cam = _cam;
|
||||
var revive = _revive;
|
||||
|
||||
var rt = new RenderTexture(1080, 1920, 24, RenderTextureFormat.ARGB32);
|
||||
cam.targetTexture = rt;
|
||||
|
||||
int idx1 = cfg.dungeons[0].stageIndex, idx3 = cfg.dungeons[2].stageIndex;
|
||||
|
||||
// ⓒ HUD — 던전 1
|
||||
WLDungeonSceneSetup.Current = cfg.dungeons[0];
|
||||
WLStageUiProbeHooks.RaiseEntered(idx1, StageIdOf(idx1), 3, 60f, Vector3.zero, 13f, 1.5f, 0);
|
||||
WLStageUiProbeHooks.RaiseEnemyCount(idx1, 3, 3);
|
||||
WLStageUiProbeHooks.RaiseTime(idx1, 42f, 60f);
|
||||
RunHud.ApplyLayout(); RunResultUI.Hide(); revive.HideNow();
|
||||
sb.AppendLine("ⓒ HUD 던전1 \"" + RunHud.PhaseText + "\" \"" + RunHud.TimerText + "\" \"" + RunHud.EnemyText + "\"");
|
||||
sb.AppendLine(Shot(cam, rt, Path.Combine(dir, "c_hud_dungeon1.png")));
|
||||
|
||||
// ⓐ 던전 1 클리어
|
||||
StageUiBridge.ProbeSetInStage(true);
|
||||
WLStageUiProbeHooks.RaiseCleared(idx1, StageIdOf(idx1), 34.2f, 60f, 3, 3, 0, false, false);
|
||||
RunResultUI.ApplyLayout();
|
||||
sb.AppendLine("ⓐ 던전1 \"" + RunResultUI.TitleText + "\" 행=" + RunResultUI.VisibleRows +
|
||||
" 골드=" + RunResultUI.DungeonGold);
|
||||
sb.AppendLine(Shot(cam, rt, Path.Combine(dir, "a_dungeon1_clear.png")));
|
||||
|
||||
// ⓑ 던전 3 클리어
|
||||
RunResultUI.Hide();
|
||||
WLDungeonSceneSetup.Current = cfg.dungeons[2];
|
||||
WLStageUiProbeHooks.RaiseEntered(idx3, StageIdOf(idx3), 3, 60f, Vector3.zero, 13f, 1.5f, 0);
|
||||
StageUiBridge.ProbeSetInStage(true);
|
||||
WLStageUiProbeHooks.RaiseCleared(idx3, StageIdOf(idx3), 41.5f, 60f, 3, 3, 0, false, false);
|
||||
RunResultUI.ApplyLayout();
|
||||
sb.AppendLine("ⓑ 던전3 \"" + RunResultUI.TitleText + "\" 골드=" + RunResultUI.DungeonGold);
|
||||
sb.AppendLine(Shot(cam, rt, Path.Combine(dir, "b_dungeon3_clear.png")));
|
||||
|
||||
// ⓓ 스테이지 모드 대조 — 새 경로(Current=null)
|
||||
RunResultUI.Hide();
|
||||
WLDungeonSceneSetup.Current = null;
|
||||
WLStageUiProbeHooks.RaiseEntered(2, 3, 12, 60f, Vector3.zero, 14f, 1.5f, 0);
|
||||
WLStageUiProbeHooks.RaiseEnemyCount(2, 5, 12);
|
||||
WLStageUiProbeHooks.RaiseTime(2, 8f, 60f);
|
||||
RunHud.ApplyLayout();
|
||||
sb.AppendLine("ⓓ HUD 스테이지 \"" + RunHud.PhaseText + "\" \"" + RunHud.TimerText + "\" \"" + RunHud.EnemyText + "\"");
|
||||
sb.AppendLine(Shot(cam, rt, Path.Combine(dir, "d1_hud_stage_new.png")));
|
||||
|
||||
StageUiBridge.ProbeSetInStage(true);
|
||||
WLStageUiProbeHooks.RaiseCleared(2, 3, 34.2f, 60f, 12, 12, 0, false, false);
|
||||
RunResultUI.ApplyLayout();
|
||||
sb.AppendLine("ⓓ 스테이지 클리어(새 경로) \"" + RunResultUI.TitleText + "\" 행=" + RunResultUI.VisibleRows);
|
||||
sb.AppendLine(Shot(cam, rt, Path.Combine(dir, "d1_stage_clear_new.png")));
|
||||
|
||||
// ⓓ 대조군 — 816m 이전과 같은 4인자 진입점
|
||||
RunResultUI.Hide();
|
||||
RunHud.WriteStageLabel(3);
|
||||
RunHud.ApplyLayout();
|
||||
sb.AppendLine(Shot(cam, rt, Path.Combine(dir, "d2_hud_stage_legacy.png")));
|
||||
var r = Cleared(2, 12, false);
|
||||
RunResultUI.SetStageMode(true);
|
||||
RunResultUI.ShowStage(in r, 0, 0, 0);
|
||||
RunResultUI.ApplyLayout();
|
||||
sb.AppendLine("ⓓ 스테이지 클리어(구 4인자) \"" + RunResultUI.TitleText + "\" 행=" + RunResultUI.VisibleRows);
|
||||
sb.AppendLine(Shot(cam, rt, Path.Combine(dir, "d2_stage_clear_legacy.png")));
|
||||
|
||||
// ⓔ 실패 팝업 (ReviveDialog.cs 0줄 변경)
|
||||
RunResultUI.Hide();
|
||||
StageUiBridge.ProbeSetInStage(true);
|
||||
WLStageUiProbeHooks.RaiseFailed(2, 3, WL.Combat.Stage.StageFailReason.TimeLimit, 4, 12, 60f, 0);
|
||||
revive.ApplyLayout();
|
||||
sb.AppendLine("ⓔ 실패 \"" + revive.LastMessage.Replace("\n", " / ") + "\" 버튼=[" +
|
||||
revive.PrimaryButtonText + "] [" + revive.SecondaryButtonText + "]");
|
||||
sb.AppendLine(Shot(cam, rt, Path.Combine(dir, "e_fail.png")));
|
||||
|
||||
cam.targetTexture = null;
|
||||
UnityEngine.Object.DestroyImmediate(rt);
|
||||
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("픽셀 대조 (MD5) — 새 경로 vs 816m 이전 경로");
|
||||
sb.AppendLine(" HUD " + SameFile(Path.Combine(dir, "d1_hud_stage_new.png"), Path.Combine(dir, "d2_hud_stage_legacy.png")));
|
||||
sb.AppendLine(" 결과창 " + SameFile(Path.Combine(dir, "d1_stage_clear_new.png"), Path.Combine(dir, "d2_stage_clear_legacy.png")));
|
||||
}
|
||||
catch (Exception e) { sb.AppendLine("예외 " + e.GetType().Name + " : " + e.Message + "\n" + e.StackTrace); }
|
||||
finally
|
||||
{
|
||||
try { StageUiBridge.Teardown(); RunHud.Teardown(); RunResultUI.Teardown(); } catch { }
|
||||
DestroyRig();
|
||||
WLDungeonSceneSetup.Current = savedCurrent;
|
||||
if (prefabRoot != null) PrefabUtility.UnloadPrefabContents(prefabRoot);
|
||||
}
|
||||
string path = Path.Combine(Path.Combine(Root, "AgentScripts"), "WL816m_CAPTURE.txt");
|
||||
File.WriteAllText(path, sb.ToString(), new UTF8Encoding(true));
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
static string SameFile(string a, string b)
|
||||
{
|
||||
if (!File.Exists(a) || !File.Exists(b)) return "파일 없음";
|
||||
string ha = Md5(a), hb = Md5(b);
|
||||
return (ha == hb ? "동일 " : "다름 ") + ha.Substring(0, 12) + " / " + hb.Substring(0, 12);
|
||||
}
|
||||
|
||||
static string Md5(string path)
|
||||
{
|
||||
using (var md5 = System.Security.Cryptography.MD5.Create())
|
||||
using (var fs = File.OpenRead(path))
|
||||
return BitConverter.ToString(md5.ComputeHash(fs)).Replace("-", "").ToLowerInvariant();
|
||||
}
|
||||
|
||||
static RectTransform NewRect(RectTransform parent, string name)
|
||||
{
|
||||
var go = new GameObject(name, typeof(RectTransform));
|
||||
go.layer = 5;
|
||||
var rt = (RectTransform)go.transform;
|
||||
rt.SetParent(parent, false);
|
||||
rt.anchorMin = Vector2.zero; rt.anchorMax = Vector2.one;
|
||||
rt.offsetMin = Vector2.zero; rt.offsetMax = Vector2.zero;
|
||||
rt.localScale = Vector3.one;
|
||||
return rt;
|
||||
}
|
||||
|
||||
static string Shot(Camera cam, RenderTexture rt, string path)
|
||||
{
|
||||
Canvas.ForceUpdateCanvases();
|
||||
cam.Render();
|
||||
var prev = RenderTexture.active;
|
||||
RenderTexture.active = rt;
|
||||
var tex = new Texture2D(rt.width, rt.height, TextureFormat.RGBA32, false);
|
||||
tex.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
|
||||
tex.Apply();
|
||||
RenderTexture.active = prev;
|
||||
var png = tex.EncodeToPNG();
|
||||
UnityEngine.Object.DestroyImmediate(tex);
|
||||
File.WriteAllBytes(path, png);
|
||||
return " → " + path + " (" + png.Length + " B · " + rt.width + "×" + rt.height + ")";
|
||||
}
|
||||
}
|
||||
|
|
@ -76,6 +76,7 @@ namespace WL.UI
|
|||
private static TextMeshProUGUI s_enemy; // "남은 적 M / T"
|
||||
private static TextMeshProUGUI s_notice; // 카운트다운("준비") 등 한 줄 알림
|
||||
private static int s_shownStageNo = int.MinValue;
|
||||
private static string s_shownDungeonLabel; // WL-816m — 던전 라벨 캐시(같은 문구면 쓰기 0 = GC 0)
|
||||
private static int s_shownEnemyRemain = int.MinValue, s_shownEnemyTotal = int.MinValue;
|
||||
private static bool s_shownEnemyHi;
|
||||
private static string s_shownNotice = null;
|
||||
|
|
@ -360,6 +361,7 @@ namespace WL.UI
|
|||
s_shownSec = int.MinValue; s_timerColorDirty = true;
|
||||
s_shownPhaseKind = -1; s_shownPhaseZone = -1;
|
||||
s_shownStageNo = int.MinValue;
|
||||
s_shownDungeonLabel = null; // WL-816m
|
||||
s_shownEnemyRemain = s_shownEnemyTotal = int.MinValue;
|
||||
s_shownNotice = null;
|
||||
if (!on) WriteNotice(null);
|
||||
|
|
@ -375,6 +377,7 @@ namespace WL.UI
|
|||
if (s_phase == null || g == null) return;
|
||||
if (stageNo == s_shownStageNo) return;
|
||||
s_shownStageNo = stageNo;
|
||||
s_shownDungeonLabel = null; // WL-816m — 던전 캐시 무효화(던전 → 스테이지 복귀)
|
||||
s_shownPhaseKind = 2; s_shownPhaseZone = stageNo; // 813q WritePhase 의 캐시와 충돌하지 않게
|
||||
s_phase.SetText(g.stageLabelFormat, stageNo); // TMP 무할당 오버로드({0} = float)
|
||||
var s = St;
|
||||
|
|
@ -382,6 +385,35 @@ namespace WL.UI
|
|||
StageLabelWrites++;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WL-816m — 던전 중 단계 라벨(「던전 1」). 이름은 <see cref="StageUiBridge"/> 가
|
||||
/// 던전 표(`WLDungeonDef.displayName`)에서 읽어 넘긴다 — 이 파일은 그리기만 한다.
|
||||
/// 같은 문구면 쓰지 않는다(GC 0).
|
||||
/// </summary>
|
||||
public static void WriteDungeonLabel(string dungeonName)
|
||||
{
|
||||
var g = WLStageUiSettings.Instance;
|
||||
if (s_phase == null || g == null || string.IsNullOrEmpty(dungeonName)) return;
|
||||
string text = FormatName(g.dungeonLabelFormat, dungeonName);
|
||||
if (string.Equals(text, s_shownDungeonLabel)) return;
|
||||
s_shownDungeonLabel = text;
|
||||
s_shownStageNo = int.MinValue; // 숫자 캐시 무효화(스테이지 복귀 시 다시 쓰게)
|
||||
s_shownPhaseKind = 3; s_shownPhaseZone = -1; // 813q WritePhase 의 캐시와 충돌하지 않게
|
||||
s_phase.SetText(text);
|
||||
var s = St;
|
||||
if (s != null) s_phase.color = s.phaseColor;
|
||||
StageLabelWrites++;
|
||||
}
|
||||
|
||||
/// <summary>"{0}" 한 자리를 문자열로 치환(입장 1회 경로 · 틱 부담 0).</summary>
|
||||
private static string FormatName(string format, string a0)
|
||||
{
|
||||
if (string.IsNullOrEmpty(format)) return a0;
|
||||
int i = format.IndexOf("{0}", System.StringComparison.Ordinal);
|
||||
if (i < 0) return format;
|
||||
return format.Substring(0, i) + a0 + format.Substring(i + 3);
|
||||
}
|
||||
|
||||
/// <summary>「남은 적 M / T」(값이 그대로면 쓰기 0 = GC 0).</summary>
|
||||
public static void WriteEnemies(int remaining, int total)
|
||||
{
|
||||
|
|
@ -677,6 +709,7 @@ namespace WL.UI
|
|||
s_shownSec = int.MinValue; s_shownWarn = false; s_timerColorDirty = false;
|
||||
s_shownPhaseKind = -1; s_shownPhaseZone = -1;
|
||||
s_shownStageNo = int.MinValue;
|
||||
s_shownDungeonLabel = null; // WL-816m
|
||||
s_shownEnemyRemain = s_shownEnemyTotal = int.MinValue; s_shownEnemyHi = false;
|
||||
s_shownNotice = null;
|
||||
if (s_notice != null && s_notice.gameObject.activeSelf) s_notice.gameObject.SetActive(false);
|
||||
|
|
|
|||
|
|
@ -113,6 +113,13 @@ namespace WL.UI
|
|||
private static TextMeshProUGUI s_badge; // 무피격 클리어 배지
|
||||
private static bool s_suppressNextRunEnded; // 실패 경로 — 병행 RunEnded 로 결과창이 겹쳐 뜨는 것을 막는다
|
||||
|
||||
// ── WL-816m 던전 모드 (#816) ─────────────────────────────────────────
|
||||
// 🔴 이 파일은 던전인지 **스스로 판정하지 않는다** — 유일한 이음매 `StageUiBridge` 가
|
||||
// `WLDungeonSceneSetup.Current` 를 보고 이름·골드를 넘겨준다(UI ↔ 게임 로직 분리).
|
||||
// s_dungeonName == null 이면 #815 스테이지 모드 그대로다(한 글자도 안 바뀐다).
|
||||
private static string s_dungeonName;
|
||||
private static int s_dungeonGold = -1; // -1 = 모름(보상 축이 꺼져 있거나 던전이 아님)
|
||||
|
||||
/// <summary>815d 가 대입한다 — [다음 스테이지] / [처음부터].</summary>
|
||||
public static System.Action StagePrimary;
|
||||
/// <summary>815d 가 대입한다 — [로비로].</summary>
|
||||
|
|
@ -528,10 +535,23 @@ namespace WL.UI
|
|||
public static string SetStageMode(bool on)
|
||||
{
|
||||
s_stageMode = on;
|
||||
if (!on) { s_hasStage = false; if (s_badge != null && s_badge.gameObject.activeSelf) s_badge.gameObject.SetActive(false); }
|
||||
if (!on)
|
||||
{
|
||||
s_hasStage = false;
|
||||
s_dungeonName = null; s_dungeonGold = -1; // WL-816m — 던전 문맥도 함께 비운다
|
||||
if (s_badge != null && s_badge.gameObject.activeSelf) s_badge.gameObject.SetActive(false);
|
||||
}
|
||||
return "결과창 스테이지 모드=" + on;
|
||||
}
|
||||
|
||||
// ── WL-816m 던전 문맥 (실측 덤프용) ──────────────────────────────────
|
||||
/// <summary>이번 결과가 던전인가(= StageUiBridge 가 이름을 넘겼는가).</summary>
|
||||
public static bool IsDungeonResult { get { return !string.IsNullOrEmpty(s_dungeonName); } }
|
||||
/// <summary>이번 결과의 던전 이름(던전이 아니면 빈 문자열).</summary>
|
||||
public static string DungeonName { get { return s_dungeonName ?? ""; } }
|
||||
/// <summary>이번 결과의 획득 골드(모르면 -1).</summary>
|
||||
public static int DungeonGold { get { return s_dungeonGold; } }
|
||||
|
||||
/// <summary>다음 `RunEnded` 1건을 무시한다(스테이지 실패 경로 · 결과창 중복 표시 0).</summary>
|
||||
public static string SuppressNextRunEnded()
|
||||
{
|
||||
|
|
@ -545,6 +565,16 @@ namespace WL.UI
|
|||
/// hits/potions/maxChain 은 <see cref="StageUiBridge"/> 가 스테이지 구간 동안 실측한 값이다.
|
||||
/// </summary>
|
||||
public static string ShowStage(in WL.Combat.Stage.StageClearResult r, int hits, int potions, int maxChain)
|
||||
{
|
||||
return ShowStage(in r, hits, potions, maxChain, null, -1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// WL-816m — 던전 문맥을 함께 받는 경로. <paramref name="dungeonName"/> 이 비어 있으면
|
||||
/// 위 4인자 경로와 **완전히 같다**(#815 스테이지 모드 무변경).
|
||||
/// </summary>
|
||||
public static string ShowStage(in WL.Combat.Stage.StageClearResult r, int hits, int potions, int maxChain,
|
||||
string dungeonName, int dungeonGold)
|
||||
{
|
||||
var s = St;
|
||||
var g = WLStageUiSettings.Instance;
|
||||
|
|
@ -552,6 +582,9 @@ namespace WL.UI
|
|||
if (g == null || !WLStageUiSettings.Enabled || !g.stageResultEnabled) return "815d off — 스테이지 결과 생략";
|
||||
if (!WLRunUiSettings.Enabled || !s.resultEnabled) return "813q off — 결과 화면 생략";
|
||||
|
||||
s_dungeonName = g.dungeonModeEnabled && !string.IsNullOrEmpty(dungeonName) ? dungeonName : null;
|
||||
s_dungeonGold = s_dungeonName != null ? dungeonGold : -1;
|
||||
|
||||
s_stage = r; s_hasStage = true;
|
||||
s_stageHits = hits; s_stagePotions = potions; s_stageMaxChain = maxChain;
|
||||
s_stageMode = true;
|
||||
|
|
@ -564,13 +597,29 @@ namespace WL.UI
|
|||
return TryShow(Time.unscaledTime);
|
||||
}
|
||||
|
||||
/// <summary>스테이지 결과 제목(마지막 스테이지면 다른 문구).</summary>
|
||||
/// <summary>스테이지 결과 제목(마지막 스테이지면 다른 문구). WL-816m — 던전이면 「던전 N 클리어!」.</summary>
|
||||
private static string StageTitle(WLStageUiSettings g)
|
||||
{
|
||||
// 🔴 WL-816m — 던전은 스테이지 표 id(던전 1 = 11)가 아니라 던전 이름을 쓴다.
|
||||
// isLastStage(전 스테이지 클리어) 문구도 던전에는 해당하지 않는다(던전은 표의 한 줄이다).
|
||||
if (s_dungeonName != null && g.dungeonModeEnabled)
|
||||
return FormatName(g.dungeonClearTitleFormat, s_dungeonName);
|
||||
|
||||
string f = s_stage.isLastStage ? g.stageAllClearTitleFormat : g.stageClearTitleFormat;
|
||||
return FormatOne(f, s_stage.stageId > 0 ? s_stage.stageId : s_stage.index + 1);
|
||||
}
|
||||
|
||||
/// <summary>"{0}" 한 자리를 **문자열**로 치환(string.Format 없이 · 클리어 1회 경로라 틱 부담 0).</summary>
|
||||
private static string FormatName(string format, string a0)
|
||||
{
|
||||
if (string.IsNullOrEmpty(format)) return a0 ?? "";
|
||||
int i = format.IndexOf("{0}", System.StringComparison.Ordinal);
|
||||
if (i < 0) return format;
|
||||
s_sb.Length = 0;
|
||||
s_sb.Append(format, 0, i).Append(a0).Append(format, i + 3, format.Length - i - 3);
|
||||
return s_sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>"{0}" 한 자리 치환(정수 전용 · string.Format 없이 · GC 최소).</summary>
|
||||
private static string FormatOne(string format, long a0)
|
||||
{
|
||||
|
|
@ -583,7 +632,11 @@ namespace WL.UI
|
|||
/// <summary>스테이지 본문(기준서 §F-1). 813q 의 행 노드를 그대로 재사용한다.</summary>
|
||||
private static string BuildStageBody(WLRunUiSettings s, WLStageUiSettings g)
|
||||
{
|
||||
EnsureStageRows(s, g);
|
||||
// 🔴 WL-816m — 던전이면 「획득 골드」 행이 한 줄 늘어난다.
|
||||
// stageResultRows 에 Gold 를 이미 넣어 뒀다면 그 자리에 쓰고 줄을 더하지 않는다(중복 0).
|
||||
bool goldRow = s_dungeonName != null && g.dungeonModeEnabled && g.dungeonGoldRowEnabled &&
|
||||
!g.HasRow(WLStageResultRow.Gold);
|
||||
EnsureStageRows(s, g, goldRow ? 1 : 0);
|
||||
|
||||
var body = new StringBuilder(256);
|
||||
string title = StageTitle(g);
|
||||
|
|
@ -599,15 +652,14 @@ namespace WL.UI
|
|||
string label = StageLabelOf(g, kind);
|
||||
s_sb.Length = 0;
|
||||
StageValueOf(g, kind, s_sb);
|
||||
string value = s_sb.ToString();
|
||||
|
||||
if (slot < s_row.Length)
|
||||
{
|
||||
if (s_rowLabel[slot] != null) s_rowLabel[slot].SetText(label);
|
||||
if (s_rowValue[slot] != null) s_rowValue[slot].SetText(value);
|
||||
if (s_row[slot] != null && !s_row[slot].gameObject.activeSelf) s_row[slot].gameObject.SetActive(true);
|
||||
}
|
||||
body.Append(label).Append(" : ").Append(value).Append('\n');
|
||||
WriteStageRow(slot, label, s_sb.ToString(), body);
|
||||
slot++;
|
||||
}
|
||||
if (goldRow)
|
||||
{
|
||||
s_sb.Length = 0;
|
||||
StageValueOf(g, WLStageResultRow.Gold, s_sb);
|
||||
WriteStageRow(slot, StageLabelOf(g, WLStageResultRow.Gold), s_sb.ToString(), body);
|
||||
slot++;
|
||||
}
|
||||
for (int i = slot; i < s_row.Length; i++)
|
||||
|
|
@ -632,9 +684,21 @@ namespace WL.UI
|
|||
return "스테이지 행 " + slot + "개 · 배지=" + badge;
|
||||
}
|
||||
|
||||
private static void EnsureStageRows(WLRunUiSettings s, WLStageUiSettings g)
|
||||
/// <summary>행 하나를 노드에 쓰고 본문 문자열에도 남긴다(노드가 없어도 본문은 끝까지 만든다).</summary>
|
||||
private static void WriteStageRow(int slot, string label, string value, StringBuilder body)
|
||||
{
|
||||
int want = g.stageResultRows != null ? g.stageResultRows.Length : 0;
|
||||
if (slot < s_row.Length)
|
||||
{
|
||||
if (s_rowLabel[slot] != null) s_rowLabel[slot].SetText(label);
|
||||
if (s_rowValue[slot] != null) s_rowValue[slot].SetText(value);
|
||||
if (s_row[slot] != null && !s_row[slot].gameObject.activeSelf) s_row[slot].gameObject.SetActive(true);
|
||||
}
|
||||
body.Append(label).Append(" : ").Append(value).Append('\n');
|
||||
}
|
||||
|
||||
private static void EnsureStageRows(WLRunUiSettings s, WLStageUiSettings g, int extra)
|
||||
{
|
||||
int want = (g.stageResultRows != null ? g.stageResultRows.Length : 0) + extra;
|
||||
if (s_rowRoot == null || s_row.Length >= want) return;
|
||||
int old = s_row.Length;
|
||||
System.Array.Resize(ref s_row, want);
|
||||
|
|
@ -661,7 +725,8 @@ namespace WL.UI
|
|||
case WLStageResultRow.Retries: return g.rowRetriesLabel;
|
||||
case WLStageResultRow.BossClear: return g.rowBossLabel;
|
||||
case WLStageResultRow.Level: return g.rowLevelLabel;
|
||||
case WLStageResultRow.Gold: return g.rowGoldLabel;
|
||||
// 🔴 WL-816m — 던전이면 「획득 골드」, 스테이지 모드면 지금까지와 같은 「골드」.
|
||||
case WLStageResultRow.Gold: return s_dungeonName != null && g.dungeonModeEnabled ? g.rowDungeonGoldLabel : g.rowGoldLabel;
|
||||
default: return g.rowLootLabel;
|
||||
}
|
||||
}
|
||||
|
|
@ -692,8 +757,15 @@ namespace WL.UI
|
|||
case WLStageResultRow.BossClear:
|
||||
sb.Append(s_stage.win ? g.rowBossClearedText : g.rowUnknownText);
|
||||
break;
|
||||
case WLStageResultRow.Gold:
|
||||
// 🔴 WL-816m — 던전이면 섬 축이 실제로 지급할 값(StageUiBridge 가 WLIslandBridge.ComputeGold 로 받아 넘긴다).
|
||||
// 던전이 아니거나 보상 축이 꺼져 있으면 지금까지처럼 「미확인」.
|
||||
if (s_dungeonName != null && g.dungeonModeEnabled && s_dungeonGold >= 0)
|
||||
AppendFormat2(sb, g.rowDungeonGoldFormat, s_dungeonGold, 0);
|
||||
else sb.Append(g.rowUnknownText);
|
||||
break;
|
||||
default:
|
||||
// 🔴 레벨 · 골드 · 등급별 획득 = 815b 페이로드에 없다(실측) → 「미확인」 표기
|
||||
// 🔴 레벨 · 등급별 획득 = 815b 페이로드에 없다(실측) → 「미확인」 표기
|
||||
sb.Append(g.rowUnknownText);
|
||||
break;
|
||||
}
|
||||
|
|
@ -1196,6 +1268,7 @@ namespace WL.UI
|
|||
s_title = null; s_rowRoot = null; s_nextButton = null; s_closeButton = null;
|
||||
s_nextLabel = null; s_closeLabel = null; s_nextBg = null; s_closeBg = null;
|
||||
s_badge = null; s_stageMode = false; // WL-815d
|
||||
s_dungeonName = null; s_dungeonGold = -1; // WL-816m
|
||||
s_row = new RectTransform[0]; s_rowLabel = new TextMeshProUGUI[0]; s_rowValue = new TextMeshProUGUI[0];
|
||||
s_uiRoot = null;
|
||||
ResetState();
|
||||
|
|
@ -1221,6 +1294,7 @@ namespace WL.UI
|
|||
" " + s_stage.elapsedSec.ToString("F1") + "s " + s_stage.killed + "/" + s_stage.total +
|
||||
" 재도전=" + s_stage.retries + " 마지막=" + s_stage.isLastStage + " 보스=" + s_stage.isBoss +
|
||||
" · 피격=" + s_stageHits + " 물약=" + s_stagePotions + " 최대연쇄=" + s_stageMaxChain);
|
||||
sb.AppendLine(" [816m] 던전=" + IsDungeonResult + " \"" + DungeonName + "\" 골드=" + s_dungeonGold);
|
||||
sb.AppendLine(" [813q2] 부활우선=" + ReviveBusy + "(" + ReviveBusyReason + ") · DeathFlow=" + DeathFlow.State +
|
||||
" 런=" + RunDirector.Phase + "(running=" + RunDirector.IsRunning + ") · died=" + DiedSeen + " request=" + ReviveRequestSeen +
|
||||
" revived=" + RevivedSeen + " 팝업생략부활=" + SkipPopupReviveCount +
|
||||
|
|
|
|||
|
|
@ -71,6 +71,51 @@ namespace WL.UI
|
|||
|
||||
private static WLStageUiSettings St { get { return WLStageUiSettings.Instance; } }
|
||||
|
||||
// ═════════════════════════════════════════════════════════════════════
|
||||
// WL-816m — 던전 문맥 (#816)
|
||||
// PD 원문(2026-09-15) 「클리어 던전은 무조건 11로 나오고 획득한 재화 정보를 알 수 없어」.
|
||||
// 🔴 판정 기준은 **`WLDungeonSceneSetup.Current` 하나**다 — null 이면 #815 스테이지 모드
|
||||
// 그대로이고 아래 값은 한 번도 읽히지 않는다.
|
||||
// 🔴 골드는 여기서 계산하지 않는다 — 섬 축의 `WLIslandBridge.ComputeGold` 를 그대로 다시 부른다
|
||||
// (계산식 1곳 · 지급은 섬 축이 한다 · `Assets/WL/Island/**` 는 읽기만 · 0줄 변경).
|
||||
// ═════════════════════════════════════════════════════════════════════
|
||||
|
||||
/// <summary>지금 도는 것이 던전이면 그 표 행, 아니면 null(던전 모드가 꺼져 있어도 null).</summary>
|
||||
public static WL.Island.WLDungeonDef CurrentDungeon
|
||||
{
|
||||
get
|
||||
{
|
||||
var g = St;
|
||||
if (g == null || !WLStageUiSettings.Enabled || !g.dungeonModeEnabled) return null;
|
||||
return WL.Island.WLDungeonSceneSetup.Current;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>던전 이름(표의 displayName · 비었으면 id 로 만든다). 던전이 아니면 null.</summary>
|
||||
public static string DungeonNameOf(WL.Island.WLDungeonDef d)
|
||||
{
|
||||
var g = St;
|
||||
if (d == null || g == null) return null;
|
||||
if (!string.IsNullOrEmpty(d.displayName)) return d.displayName;
|
||||
return FormatOne(g.dungeonNameFallbackFormat, d.id);
|
||||
}
|
||||
|
||||
/// <summary>이번 클리어로 섬에서 받을 코인(보상 축이 꺼져 있으면 -1 = 「모름」).</summary>
|
||||
public static int DungeonGoldOf(in WL.Combat.Stage.StageClearResult r)
|
||||
{
|
||||
var cfg = WL.Island.WLIslandSettings.Instance;
|
||||
if (cfg == null || cfg.enabled_ == 0 || cfg.rewardEnabled == 0) return -1;
|
||||
return WL.Island.WLIslandBridge.ComputeGold(cfg, in r);
|
||||
}
|
||||
|
||||
/// <summary>상단 단계 라벨을 쓴다 — 던전이면 「던전 N」, 아니면 지금까지대로 「스테이지 N」.</summary>
|
||||
private static void WritePhaseLabel(int stageNo)
|
||||
{
|
||||
string name = DungeonNameOf(CurrentDungeon);
|
||||
if (name != null) RunHud.WriteDungeonLabel(name);
|
||||
else RunHud.WriteStageLabel(stageNo);
|
||||
}
|
||||
|
||||
// ── 부팅 ──────────────────────────────────────────────────────────────
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
|
||||
private static void Boot()
|
||||
|
|
@ -161,7 +206,7 @@ namespace WL.UI
|
|||
{
|
||||
RunHud.SetStageMode(true);
|
||||
RunHud.SetVisible(true);
|
||||
RunHud.WriteStageLabel(s_stageNo);
|
||||
WritePhaseLabel(s_stageNo); // WL-816m — 던전이면 「던전 N」
|
||||
RunHud.WriteEnemies(e.totalEnemies, e.totalEnemies);
|
||||
RunHud.WriteStageTime(e.timeLimit);
|
||||
}
|
||||
|
|
@ -191,7 +236,7 @@ namespace WL.UI
|
|||
s_hits = 0; s_maxChain = 0;
|
||||
if (!g.stageHudEnabled) return;
|
||||
RunHud.WriteNotice(null); // 카운트다운 줄을 접는다
|
||||
RunHud.WriteStageLabel(e.stageId > 0 ? e.stageId : e.index + 1);
|
||||
WritePhaseLabel(e.stageId > 0 ? e.stageId : e.index + 1); // WL-816m — 던전이면 「던전 N」
|
||||
RunHud.WriteStageTime(e.timeLimit);
|
||||
}
|
||||
|
||||
|
|
@ -218,8 +263,13 @@ namespace WL.UI
|
|||
if (g == null || !WLStageUiSettings.Enabled) return;
|
||||
if (g.stageHudEnabled) RunHud.WriteNotice(null);
|
||||
if (!g.stageResultEnabled) return;
|
||||
LastLog = RunResultUI.ShowStage(in r, s_hits, PotionsUsed, s_maxChain);
|
||||
Log(g, "클리어 스테이지 " + (r.stageId > 0 ? r.stageId : r.index + 1) + " — " + LastLog);
|
||||
// WL-816m — 던전이면 제목을 「던전 N 클리어!」로 바꾸고 획득 골드 행을 한 줄 더한다.
|
||||
var d = CurrentDungeon;
|
||||
string dName = DungeonNameOf(d);
|
||||
int dGold = dName != null ? DungeonGoldOf(in r) : -1;
|
||||
LastLog = RunResultUI.ShowStage(in r, s_hits, PotionsUsed, s_maxChain, dName, dGold);
|
||||
Log(g, "클리어 " + (dName ?? ("스테이지 " + (r.stageId > 0 ? r.stageId : r.index + 1))) +
|
||||
(dName != null ? " · 획득 골드 " + dGold : "") + " — " + LastLog);
|
||||
}
|
||||
|
||||
private static void OnFailed(in WL.Combat.Stage.StageFailedEvent e)
|
||||
|
|
@ -533,6 +583,10 @@ namespace WL.UI
|
|||
" · 입장 " + EnteredSeen + " 카운트 " + CountdownSeen + " 시작 " + StartedSeen +
|
||||
" 적수 " + EnemySeen + " 시간 " + TimeSeen + " 클리어 " + ClearedSeen +
|
||||
" 실패 " + FailedSeen + " 이탈 " + ExitedSeen);
|
||||
var dd = CurrentDungeon;
|
||||
sb.AppendLine(" [816m] 던전=" + (dd != null) + " \"" + (DungeonNameOf(dd) ?? "-") + "\" (Current=" +
|
||||
(WL.Island.WLDungeonSceneSetup.Current != null ? WL.Island.WLDungeonSceneSetup.Current.displayName : "null") +
|
||||
" · 던전모드=" + (g != null && g.dungeonModeEnabled) + ")");
|
||||
sb.AppendLine(" 실측 — 피격 " + s_hits + "회 · 물약 " + PotionsUsed + "개(시작 스냅 " + s_potionsAtStart +
|
||||
" / 현재 " + PotionUse.UsedCount + ") · 최대 연쇄 " + s_maxChain +
|
||||
"(진행중 " + KillChain.ChainKills + ")");
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ MonoBehaviour:
|
|||
timerWarnColor: {r: 1, g: 0.29, b: 0.278, a: 1}
|
||||
countdownEnabled: 1
|
||||
countdownText: "\uC900\uBE44"
|
||||
countdownNumberFormat: "{0}"
|
||||
countdownNumberFormat: '{0}'
|
||||
countdownFontPx: 72
|
||||
countdownColor: {r: 1, g: 0.86, b: 0.42, a: 1}
|
||||
countdownTopGapPx: 24
|
||||
|
|
@ -58,13 +58,7 @@ MonoBehaviour:
|
|||
stageResultEnabled: 1
|
||||
stageClearTitleFormat: "\uC2A4\uD14C\uC774\uC9C0 {0} \uD074\uB9AC\uC5B4!"
|
||||
stageAllClearTitleFormat: "\uC804 \uC2A4\uD14C\uC774\uC9C0 \uD074\uB9AC\uC5B4!"
|
||||
stageResultRows:
|
||||
- 0
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
- 5
|
||||
stageResultRows: 000000000100000002000000030000000400000005000000
|
||||
rowClearTimeLabel: "\uD074\uB9AC\uC5B4 \uC2DC\uAC04"
|
||||
rowKillsLabel: "\uCC98\uCE58"
|
||||
rowEliteLabel: "\uC5D8\uB9AC\uD2B8 \uCC98\uCE58"
|
||||
|
|
@ -75,7 +69,7 @@ MonoBehaviour:
|
|||
rowLevelLabel: "\uB808\uBCA8"
|
||||
rowGoldLabel: "\uACE8\uB4DC"
|
||||
rowLootLabel: "\uD68D\uB4DD"
|
||||
rowKillsFormat: "{0} / {1}"
|
||||
rowKillsFormat: '{0} / {1}'
|
||||
rowHitsPotionsFormat: "{0}\uD68C / {1}\uAC1C"
|
||||
rowRetriesFormat: "{0}\uD68C"
|
||||
rowBossClearedText: "\uCC98\uCE58"
|
||||
|
|
@ -87,13 +81,20 @@ MonoBehaviour:
|
|||
nextStageText: "\uB2E4\uC74C \uC2A4\uD14C\uC774\uC9C0"
|
||||
restartFromFirstText: "\uCC98\uC74C\uBD80\uD130"
|
||||
showRestartOnLastStage: 1
|
||||
toLobbyText: "섬으로"
|
||||
toLobbyText: "\uC12C\uC73C\uB85C"
|
||||
dungeonModeEnabled: 1
|
||||
dungeonClearTitleFormat: "{0} \uD074\uB9AC\uC5B4!"
|
||||
dungeonLabelFormat: '{0}'
|
||||
dungeonNameFallbackFormat: "\uB358\uC804 {0}"
|
||||
dungeonGoldRowEnabled: 1
|
||||
rowDungeonGoldLabel: "\uD68D\uB4DD \uACE8\uB4DC"
|
||||
rowDungeonGoldFormat: +{0}
|
||||
stageFailEnabled: 1
|
||||
failDeathMessage: "\uC4F0\uB7EC\uC84C\uC2B5\uB2C8\uB2E4.\n\uB2E4\uC2DC \uB3C4\uC804\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?"
|
||||
failTimeoutMessage: "\uC2DC\uAC04 \uCD08\uACFC!\n\uB0A8\uC740 \uC801 {0}\uB9C8\uB9AC"
|
||||
failAbortedMessage: "\uC2A4\uD14C\uC774\uC9C0\uAC00 \uC911\uB2E8\uB418\uC5C8\uC2B5\uB2C8\uB2E4."
|
||||
failRetryText: "\uB2E4\uC2DC \uB3C4\uC804"
|
||||
failLobbyText: "섬으로"
|
||||
failLobbyText: "\uC12C\uC73C\uB85C"
|
||||
suppressResultOnFail: 1
|
||||
lobbyMode: 0
|
||||
titleSceneName: Title
|
||||
|
|
|
|||
|
|
@ -284,6 +284,33 @@ namespace WL.UI
|
|||
[Tooltip("오른쪽 버튼 문구 — 누르면 「로비로」(lobbyMode).")]
|
||||
public string toLobbyText = "로비로";
|
||||
|
||||
// ── 던전 모드 (WL-816m · #816) ───────────────────────────────────────
|
||||
// PD 원문(2026-09-15) 「클리어 던전은 무조건 11로 나오고 획득한 재화 정보를 알 수 없어」.
|
||||
// 던전에서는 스테이지 표 id(던전 1 = 11)가 아니라 **던전 이름**을 쓰고 획득 골드를 한 줄 더한다.
|
||||
// 🔴 판정 기준은 `WL.Island.WLDungeonSceneSetup.Current` 하나뿐이다 —
|
||||
// 그것이 null 인 #815 스테이지 모드는 이 절의 어떤 값도 읽지 않는다(한 글자도 안 바뀐다).
|
||||
[Header("던전 모드 (WL-816m · 던전에서만 · 스테이지 모드는 불변)")]
|
||||
[Tooltip("끄면 던전에서도 지금처럼 「스테이지 N 클리어!」 로 나온다(C8 롤백 1줄).")]
|
||||
public bool dungeonModeEnabled = true;
|
||||
|
||||
[Tooltip("던전 클리어 제목 — {0} = 던전 이름(WLIslandSettings 던전 표의 displayName · 예 「던전 1」).")]
|
||||
public string dungeonClearTitleFormat = "{0} 클리어!";
|
||||
|
||||
[Tooltip("던전 중 상단 단계 라벨 — {0} = 던전 이름(스테이지 모드의 stageLabelFormat 을 대신한다).")]
|
||||
public string dungeonLabelFormat = "{0}";
|
||||
|
||||
[Tooltip("던전 표의 displayName 이 비었을 때 쓰는 이름 — {0} = 그 행의 id.")]
|
||||
public string dungeonNameFallbackFormat = "던전 {0}";
|
||||
|
||||
[Tooltip("던전 클리어 화면에 획득 골드 행을 더한다(stageResultRows 에 Gold 가 이미 있으면 그 자리에 쓴다).")]
|
||||
public bool dungeonGoldRowEnabled = true;
|
||||
|
||||
[Tooltip("획득 골드 행 라벨.")]
|
||||
public string rowDungeonGoldLabel = "획득 골드";
|
||||
|
||||
[Tooltip("획득 골드 행 값 문구 — {0} = 코인 수.")]
|
||||
public string rowDungeonGoldFormat = "+{0}";
|
||||
|
||||
// ── 실패 팝업 (기준서 §E) ────────────────────────────────────────────
|
||||
[Header("실패 팝업 (기준서 §E · 813z ReviveDialog 2버튼)")]
|
||||
[Tooltip("끄면 스테이지 실패에 813z 부활 팝업이 **원래대로**(1버튼 「부활」) 뜬다.")]
|
||||
|
|
|
|||
Loading…
Reference in New Issue