- UI SFX v3: procedurally synthesized one-shots (Tools/synth_ui_sfx.py) wired to buttons, rewards, errors and red dots via UiSfx, gated by the SFX setting. - Five formal enemies (Hornlet, Dashlet, Shellhorn, HornCaptain, GreatHorn): Hunyuan 50k -> 2000-tri XPbr, DGXA TokenRig, Idle/Walk/Attack, nested per type in PrototypeArena; PrototypeBattle.Enemy gains presentation-only Moving/Strikes. - Formal partners for all ten pets in the arena and portraits, including new VineSprite, ThunderLeopard and TideWhale. - Pipeline fixes: reject local TokenRig fallback, drop loose mesh islands, configurable Unity run_script timeout, companion static stage. - Also includes concurrent work from another tool in this working tree (FlameLion, enemy combat FX, challenge mode, home explorer, server updates). - Resources registered in Doc/ResDesc_*.md; verified on isolated :18081. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
59 lines
2.7 KiB
C#
59 lines
2.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Threading.Tasks;
|
|
using HotUpdate.UI;
|
|
using TMPro;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEngine.EventSystems;
|
|
using UnityEngine.UI;
|
|
|
|
/// <summary>Confirms the camp painting has a walking placeholder and speech only after a tap.</summary>
|
|
public static class VerifyHomeExplorer
|
|
{
|
|
static async Task Until(Func<bool> condition, int seconds = 20)
|
|
{
|
|
var end = DateTime.UtcNow.AddSeconds(seconds);
|
|
while (!condition())
|
|
{
|
|
if (DateTime.UtcNow >= end) throw new Exception("Home explorer timed out");
|
|
await Task.Delay(100);
|
|
}
|
|
}
|
|
|
|
public static async Task<string> Play()
|
|
{
|
|
if (!EditorApplication.isPlaying) throw new Exception("Enter Play Mode first");
|
|
HomeExplorerPresenter presenter = null;
|
|
await Until(() => (presenter = UnityEngine.Object.FindObjectOfType<HomeExplorerPresenter>()) != null && presenter.Ready);
|
|
if (presenter.Talking) throw new Exception("Speech was visible before a tap: " + presenter.Line);
|
|
var greeting = presenter.transform.parent.Find("Layout_Sides/Panel_Greeting");
|
|
if (greeting != null && greeting.gameObject.activeSelf) throw new Exception("Static greeting is still visible");
|
|
float x = presenter.transform.parent.Find("Btn_Explorer").position.x;
|
|
await Task.Delay(900);
|
|
float moved = presenter.transform.parent.Find("Btn_Explorer").position.x;
|
|
if (Mathf.Abs(moved - x) < 1f) throw new Exception("Explorer did not move: " + x + " -> " + moved);
|
|
await Capture("walk");
|
|
var button = GameObject.Find("Btn_Explorer").GetComponent<Button>();
|
|
button.onClick.Invoke();
|
|
await Task.Delay(200);
|
|
if (!presenter.Talking) throw new Exception("Tap did not open speech");
|
|
string line = presenter.Line;
|
|
if (string.IsNullOrEmpty(line)) throw new Exception("Speech was empty");
|
|
await Capture("talk");
|
|
button.onClick.Invoke();
|
|
await Task.Delay(100);
|
|
if (presenter.Line == line) throw new Exception("Second tap repeated the same line");
|
|
return "PASS explorer walks and speaks only after a tap: " + line;
|
|
}
|
|
|
|
static async Task Capture(string name)
|
|
{
|
|
await Task.Delay(150);
|
|
var type = AppDomain.CurrentDomain.GetAssemblies().Select(a => a.GetType("Unity.Pipeline.Editor.Commands.Capture.CaptureCommands")).First(t => t != null);
|
|
type.GetMethod("CaptureGameView", BindingFlags.Public | BindingFlags.Static).Invoke(null, new object[] { 1080, 1920, null, "Screenshots/home_explorer_" + name + ".png", false, 0, "screen" });
|
|
}
|
|
}
|