champions-of-luneraria/Assets/Luneraria/Tests/UI/PlayMode/S1RulesViewsTests.cs
Martin Stickelbroeck 8e4b52f4ab S1 Strategie-Regeln nach Legion TD 2, Dota 2 und League of Legends
Hinter MatchOptions.Extended (Standard im Spiel, Schalter im Startbildschirm):
Söldner-Einkommen (Angriffschampion +Preis/12 Einkommen dauerhaft), Kasernen
(gefallener innerer Turm: Gegnerwellen +25 % und ein Monster mehr), Erschöpfung
und Rückkauf (60 % Leben, Rückkauf 60 + 20 x Stufe), Mondsegen (Grottensieg
+4 % je Stapel, Mondseele bei 4). Bots wählen mit erweiterten Regeln auch
Sylvara und kaufen Helden zurück. Netz überträgt Regeln und neue Zustände.
HUD: Einkommen, Kasernen-Symbol, Rückkauf, Segen im Teamkopf.
Kern 531/531 (s1 31), EditMode 31/31, PlayMode 16/16, Verify 718/0,
Selbsttest 30/30, Golden 0 Abweichungen, Fingerabdruck unverändert.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 12:18:47 +02:00

120 lines
5.6 KiB
C#
Raw Permalink 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 System;
using System.Collections;
using System.Linq;
using Luneraria.Core;
using Luneraria.View;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
namespace Luneraria.UI.Tests
{
/// <summary>
/// S1: the extended rules in the real scene. S1Hud checks the champion income in the gold display and the champion tooltip, the barracks mark of a
/// lane, exhaustion and the buyback button of the hero window, and the Mondsegen in the team
/// header. Fixtures set public match state only (a fallen tower, a fallen hero, blessing
/// stacks), as the G3 verify does. S1Bilder (explicit) captures the evidence at 1920×1080;
/// LUNE_EVIDENCE names the folder below docs/port/screenshots (default s1/spiel).
/// </summary>
public sealed class S1RulesViewsTests
{
static void Send(HudSession s, Command command)
{
CommandResult result = s.Match.Submit(HudSession.Human, command);
Assert.IsTrue(result.Ok, command.Type + ": " + result.Message);
s.Game.RebuildPreview();
s.Sync();
}
static IEnumerator WaitReady(HudSession s)
{
float waited = 0f;
while (s.Hud.ReadyBlocked() && waited < 5f)
{
waited += Time.unscaledDeltaTime;
yield return null;
}
}
/// <summary>One round with a booked champion and a hero that falls; returns in the next planning.</summary>
static IEnumerator Prepare(HudSession s)
{
Assert.IsTrue(s.Match.Extended, "the driver started an extended match");
yield return s.Starter();
s.Leave();
Send(s, Command.HeroBuy("held_sylvara"));
Send(s, Command.ChampionBook("ch_belagerung", "mid"));
s.Game.Key(KeyCode.Space);
yield return HudSession.Frames(2);
Assert.AreEqual(LuneMatchRunner.Stage.Combat, s.Runner.Current, "combat starts");
LuneUnit hero = s.Match.Combat.Units.First(u => u.Kind == "hero" && u.OwnerSlot == HudSession.Human);
hero.Hp = 0.0;
yield return s.FinishCombat();
yield return WaitReady(s);
// Public fixtures: Rot's inner mid tower fell earlier, Blau won the grotto twice.
s.Match.BuildingHp["rot_mid_inner"] = 0.0;
s.Match.BuildingHp["rot_mid_outer"] = 0.0;
s.Match.Boss.Blessing[0] = 2;
s.Sync();
}
[UnityTest, Timeout(600000)]
public IEnumerator S1Hud()
{
var s = new HudSession();
yield return s.Open(1920, 1080, seed: 4, startRound: 6, extraGold: 1500, extended: true);
yield return Prepare(s);
Assert.AreEqual(15, s.Me.IncomeBonus, "the Keilbrecher adds 15 income");
string texts = s.Texts();
StringAssert.Contains("davon 15 Söldner", texts, "the gold display shows the champion income");
StringAssert.Contains("SEGEN 2/4", texts, "the team header shows the Mondsegen");
Assert.IsTrue(HudSession.Visible(s.Hud.Lanes["mid"].Barracks), "mid shows the barracks mark");
Assert.IsFalse(HudSession.Visible(s.Hud.Lanes["top"].Barracks), "top shows none");
Assert.IsTrue(s.Me.Hero.Exhausted, "the fallen hero is exhausted");
s.Hud.OpenHero();
yield return HudSession.Frames(2);
s.Sync();
Assert.IsNotNull(s.Hud.HeroDetail.BuybackButton, "the hero window offers the buyback");
int gold = s.Me.Draft.Gold;
int cost = s.Match.BuybackCost(s.Me.Draft.Hero);
s.Click(s.Hud.HeroDetail.BuybackButton);
yield return HudSession.Frames(2);
s.Sync();
Assert.AreEqual(gold - cost, s.Me.Draft.Gold, "the buyback costs " + cost);
Assert.IsFalse(s.Me.Draft.Hero.Exhausted, "the hero is bought back");
Assert.IsNull(s.Hud.HeroDetail.BuybackButton, "no buyback button afterwards");
s.Hud.CloseModal();
s.Close();
}
[UnityTest, Timeout(600000), Explicit("Bildwerkzeug: nur gezielt per -testFilter")]
public IEnumerator S1Bilder()
{
string evidence = Environment.GetEnvironmentVariable("LUNE_EVIDENCE");
string folder = "docs/port/screenshots/" + (string.IsNullOrEmpty(evidence) ? "s1/spiel" : evidence) + "/";
var s = new HudSession();
yield return s.Open(1920, 1080, seed: 4, startRound: 6, extraGold: 1500, extended: true);
yield return Prepare(s);
yield return new WaitForSecondsRealtime(.5f);
yield return s.Shot(folder + "01-planung-einkommen-kaserne-mondsegen.png");
s.Hover(s.Hud.Lanes["mid"]);
yield return new WaitForSecondsRealtime(.3f);
yield return s.Shot(folder + "02-kaserne-tooltip.png");
s.Leave();
s.Hud.OpenHero();
yield return new WaitForSecondsRealtime(.6f);
yield return s.Shot(folder + "03-rueckkauf.png");
s.Hud.CloseModal();
s.Game.Key(KeyCode.Space);
yield return HudSession.Frames(2);
yield return s.Fight(12.0);
s.Driver.Paused = true;
LuneUnit monster = s.Match.Combat.Units.Where(u => u.Kind == "monster" && u.Team == 0 && u.Lane == "mid" && u.Alive).OrderByDescending(u => u.Progress).FirstOrDefault();
if (monster != null)
s.Rig.LookAt(monster.Position, 20f, true);
yield return new WaitForSecondsRealtime(.5f);
yield return s.Shot(folder + "04-verstaerkte-welle-mid.png");
s.Close();
}
}
}