b451f83174
Captures the pre-Godot-port state of the codebase. This is the rollback anchor for the Godot port (M0 of theriapolis-rpg-implementation-plan-godot-port.md). All Phase 0 through Phase 6.5 work is included; Phase 7 is in flight. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
99 lines
3.5 KiB
C#
99 lines
3.5 KiB
C#
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework.Graphics;
|
|
using Microsoft.Xna.Framework.Input;
|
|
using Myra.Graphics2D;
|
|
using Myra.Graphics2D.Brushes;
|
|
using Myra.Graphics2D.UI;
|
|
using Theriapolis.Core;
|
|
using Theriapolis.Game.Platform;
|
|
|
|
namespace Theriapolis.Game.Screens;
|
|
|
|
/// <summary>
|
|
/// Phase 5 M6: shown when the player's death-save loop fails (3 cumulative
|
|
/// failures). Permadeath per the §9 resolved decision — the only option is
|
|
/// "Return to Title". The autosave_combat slot persists, so the player can
|
|
/// load it from the title screen and retry.
|
|
/// </summary>
|
|
public sealed class DefeatedScreen : IScreen
|
|
{
|
|
private readonly string _causeOfDeath;
|
|
private Game1 _game = null!;
|
|
private Desktop _desktop = null!;
|
|
private bool _enterWas = true;
|
|
private bool _escWas = true;
|
|
|
|
public DefeatedScreen(string causeOfDeath = "")
|
|
{
|
|
_causeOfDeath = causeOfDeath ?? "";
|
|
}
|
|
|
|
public void Initialize(Game1 game)
|
|
{
|
|
_game = game;
|
|
var root = new VerticalStackPanel
|
|
{
|
|
Spacing = 14,
|
|
HorizontalAlignment = HorizontalAlignment.Center,
|
|
VerticalAlignment = VerticalAlignment.Center,
|
|
Padding = new Thickness(50, 40, 50, 40),
|
|
Background = new SolidBrush(new Color(20, 0, 0, 230)),
|
|
};
|
|
root.Widgets.Add(new Label { Text = "YOU HAVE DIED", HorizontalAlignment = HorizontalAlignment.Center });
|
|
root.Widgets.Add(new Label { Text = " " });
|
|
if (!string.IsNullOrEmpty(_causeOfDeath))
|
|
{
|
|
root.Widgets.Add(new Label { Text = _causeOfDeath, HorizontalAlignment = HorizontalAlignment.Center });
|
|
root.Widgets.Add(new Label { Text = " " });
|
|
}
|
|
root.Widgets.Add(new Label
|
|
{
|
|
Text = $"Your last autosave is at slot \"{C.SAVE_SLOT_AUTOSAVE_COMBAT}\".",
|
|
HorizontalAlignment = HorizontalAlignment.Center,
|
|
});
|
|
root.Widgets.Add(new Label
|
|
{
|
|
Text = "Load from the title to retry the encounter.",
|
|
HorizontalAlignment = HorizontalAlignment.Center,
|
|
});
|
|
root.Widgets.Add(new Label { Text = " " });
|
|
|
|
var ret = new TextButton { Text = "Return to Title (ENTER)", Width = 280, HorizontalAlignment = HorizontalAlignment.Center };
|
|
ret.Click += (_, _) => ReturnToTitle();
|
|
root.Widgets.Add(ret);
|
|
|
|
_desktop = new Desktop { Root = root };
|
|
}
|
|
|
|
private void ReturnToTitle()
|
|
{
|
|
// Pop everything above the TitleScreen. Stack at this point is:
|
|
// Title → CharacterCreation (popped) → WorldGenProgress (popped) →
|
|
// PlayScreen → CombatHUD (popped earlier) → DefeatedScreen.
|
|
// So we need to pop DefeatedScreen + PlayScreen = 2 pops.
|
|
// ScreenManager.Pop is queue-based now, so multiple calls all apply.
|
|
_game.Screens.Pop();
|
|
_game.Screens.Pop();
|
|
}
|
|
|
|
public void Update(GameTime gt)
|
|
{
|
|
var ks = Keyboard.GetState();
|
|
bool enter = ks.IsKeyDown(Keys.Enter);
|
|
bool esc = ks.IsKeyDown(Keys.Escape);
|
|
bool enterPressed = enter && !_enterWas;
|
|
bool escPressed = esc && !_escWas;
|
|
_enterWas = enter; _escWas = esc;
|
|
if (enterPressed || escPressed) ReturnToTitle();
|
|
}
|
|
|
|
public void Draw(GameTime gt, SpriteBatch sb)
|
|
{
|
|
// Don't clear — leave the play-screen's last frame underneath.
|
|
_desktop.Render();
|
|
}
|
|
|
|
public void Deactivate() { }
|
|
public void Reactivate() { }
|
|
}
|