Add rank, friends, fishing, and camp treasure with T2 studio models and skill presentation.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
udx
2026-10-21 23:01:31 +08:00
co-authored by Cursor
parent 89e0fa246f
commit 079313fb06
677 changed files with 395371 additions and 9692 deletions
+14 -4
View File
@@ -55,7 +55,7 @@ public static class VerifyFormalHeroes
var hero = arena.transform.Find("Heroes/Hero" + id);
var visual = hero.Find("Visual");
Check(visual != null && PrefabUtility.IsAnyPrefabInstanceRoot(visual.gameObject), "Hero" + id + " lacks nested formal prefab");
Check(hero.Cast<Transform>().All(c => c.name == "Visual" || c.name == "T2Crest"), "Hero" + id + " still has primitive parts");
Check(hero.Cast<Transform>().All(c => c.name == "Visual" || c.name == "VisualT2" || c.name == "T2Crest"), "Hero" + id + " still has primitive parts");
Check(visual.GetComponentsInChildren<Transform>(true).All(t => t.gameObject.layer == 30), "Hero" + id + " visual not on battle layer 30");
var animator = visual.GetComponentInChildren<Animator>(true);
Check(animator != null && animator.runtimeAnimatorController != null && !animator.applyRootMotion, "Hero" + id + " animator missing");
@@ -112,7 +112,12 @@ public static class VerifyFormalHeroes
var arena = Get<GameObject>("_arena");
var fielded = Flow.Battle.Heroes.Select(h => h.Pet).Where(p => Formal.Contains(p)).Distinct().ToArray();
Check(fielded.Length > 0, "No formal partner fielded in 1-" + stage);
var animators = fielded.ToDictionary(p => p, p => arena.transform.Find("Heroes/Hero" + p + "/Visual").GetComponentInChildren<Animator>());
// Tier-2 partners show VisualT2 (same rig + evolution accessory); read whichever visual is currently shown.
Animator Shown(int p) { var hero = arena.transform.Find("Heroes/Hero" + p); var t2 = hero.Find("VisualT2"); return (t2 != null && t2.gameObject.activeSelf ? t2 : hero.Find("Visual")).GetComponentInChildren<Animator>(); }
await Task.Delay(300);
var evolved = Flow.Battle.Heroes.Where(h => h.Tier == 2 && arena.transform.Find("Heroes/Hero" + h.Pet + "/VisualT2") != null).Select(h => h.Pet).Distinct().ToArray();
foreach (var p in evolved) Check(arena.transform.Find("Heroes/Hero" + p + "/VisualT2").gameObject.activeSelf && !arena.transform.Find("Heroes/Hero" + p + "/Visual").gameObject.activeSelf, "Hero" + p + " tier 2 does not show VisualT2");
var animators = fielded.ToDictionary(p => p, Shown);
var attacked = new HashSet<int>(); var end = DateTime.UtcNow.AddSeconds(stage > 1 ? 45 : 20);
string shot = seededUser != null ? "seeded_" : "";
await Capture(shot + "idle"); bool attackShot = false;
@@ -125,7 +130,7 @@ public static class VerifyFormalHeroes
Check(attacked.Count == fielded.Length, "Attack never played for " + string.Join(",", fielded.Except(attacked)));
Click("Speed");
await Until(() => animators.Values.All(a => !a.isActiveAndEnabled || Mathf.Approximately(a.speed, 2)), 5);
return "PASS formal partners " + string.Join(",", fielded) + " fielded in 1-" + stage + ", played Attack and follow 2x speed; screenshots formal_heroes_" + shot + "idle/attack.png";
return "PASS formal partners " + string.Join(",", fielded) + " (T2 visuals " + string.Join(",", evolved) + ") fielded in 1-" + stage + ", played Attack and follow 2x speed; screenshots formal_heroes_" + shot + "idle/attack.png";
}
public static async Task<string> OpenSeedAccount()
@@ -169,7 +174,12 @@ public static class VerifyFormalHeroes
var fielded = Flow.Battle.Heroes.Select(h => h.Pet).OrderBy(p => p).ToArray();
Check(fielded.SequenceEqual(new[] { 3, 4 }), "1-1 fielded " + string.Join(",", fielded));
Check(Flow.Battle.Heroes.Single(h => h.Pet == 4).Slot == 0 && Flow.Battle.Heroes.Single(h => h.Pet == 3).Slot == 1, "Turtle is not in front of the bird");
var animators = fielded.ToDictionary(p => p, p => arena.transform.Find("Heroes/Hero" + p + "/Visual").GetComponentInChildren<Animator>());
// Tier-2 partners show VisualT2 (same rig + evolution accessory); read whichever visual is currently shown.
Animator Shown(int p) { var hero = arena.transform.Find("Heroes/Hero" + p); var t2 = hero.Find("VisualT2"); return (t2 != null && t2.gameObject.activeSelf ? t2 : hero.Find("Visual")).GetComponentInChildren<Animator>(); }
await Task.Delay(300);
var evolved = Flow.Battle.Heroes.Where(h => h.Tier == 2 && arena.transform.Find("Heroes/Hero" + h.Pet + "/VisualT2") != null).Select(h => h.Pet).Distinct().ToArray();
foreach (var p in evolved) Check(arena.transform.Find("Heroes/Hero" + p + "/VisualT2").gameObject.activeSelf && !arena.transform.Find("Heroes/Hero" + p + "/Visual").gameObject.activeSelf, "Hero" + p + " tier 2 does not show VisualT2");
var animators = fielded.ToDictionary(p => p, Shown);
foreach (var kv in animators) Check(kv.Value != null && arena.transform.Find("Heroes/Hero" + kv.Key).gameObject.activeInHierarchy, "Hero" + kv.Key + " inactive");
var attacked = new HashSet<int>(); var end = DateTime.UtcNow.AddSeconds(25);
await Capture("bird_turtle_idle"); bool attackShot = false;