Initial commit: Theriapolis baseline at port/godot branch point
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>
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
using Theriapolis.Core.Data;
|
||||
using Theriapolis.Core.Entities;
|
||||
using Theriapolis.Core.Items;
|
||||
using Theriapolis.Core.Rules.Reputation;
|
||||
using Theriapolis.Core.Time;
|
||||
using Theriapolis.Core.World;
|
||||
using Theriapolis.Core.World.Settlements;
|
||||
|
||||
namespace Theriapolis.Core.Rules.Quests;
|
||||
|
||||
/// <summary>
|
||||
/// Phase 6 M4 — read/write window the QuestEngine uses to evaluate
|
||||
/// conditions and apply effects. Deliberately holds references rather
|
||||
/// than copies so engine ticks see live state.
|
||||
/// </summary>
|
||||
public sealed class QuestContext
|
||||
{
|
||||
public ContentResolver Content { get; }
|
||||
public ActorManager Actors { get; }
|
||||
public PlayerReputation Reputation { get; }
|
||||
public Dictionary<string, int> Flags { get; }
|
||||
public AnchorRegistry Anchors { get; }
|
||||
public WorldClock Clock { get; }
|
||||
public WorldState World { get; }
|
||||
public Rules.Character.Character? PlayerCharacter { get; set; }
|
||||
|
||||
/// <summary>Most recent dialogue node id reached, surfaced by InteractionScreen for the dialogue_choice condition.</summary>
|
||||
public string LastDialogueNodeReached { get; set; } = "";
|
||||
|
||||
public QuestContext(ContentResolver content, ActorManager actors,
|
||||
PlayerReputation rep, Dictionary<string, int> flags,
|
||||
AnchorRegistry anchors, WorldClock clock, WorldState world)
|
||||
{
|
||||
Content = content;
|
||||
Actors = actors;
|
||||
Reputation = rep;
|
||||
Flags = flags;
|
||||
Anchors = anchors;
|
||||
Clock = clock;
|
||||
World = world;
|
||||
}
|
||||
|
||||
public bool HasItem(string itemId)
|
||||
{
|
||||
if (PlayerCharacter is null) return false;
|
||||
foreach (var inst in PlayerCharacter.Inventory.Items)
|
||||
if (string.Equals(inst.Def.Id, itemId, System.StringComparison.OrdinalIgnoreCase))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Position of the live player actor in tactical-tile (= world-pixel)
|
||||
/// space, or null if the actor isn't yet spawned.
|
||||
/// </summary>
|
||||
public (int x, int y)? PlayerTacticalPos()
|
||||
{
|
||||
if (Actors.Player is null) return null;
|
||||
return ((int)Actors.Player.Position.X, (int)Actors.Player.Position.Y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// World-tile Chebyshev distance from the player to the settlement
|
||||
/// with the given id, or null if the player or settlement isn't
|
||||
/// resolvable.
|
||||
/// </summary>
|
||||
public int? PlayerDistanceToSettlement(int settlementId)
|
||||
{
|
||||
if (Actors.Player is null) return null;
|
||||
Settlement? s = null;
|
||||
foreach (var sx in World.Settlements)
|
||||
if (sx.Id == settlementId) { s = sx; break; }
|
||||
if (s is null) return null;
|
||||
int playerWX = (int)Actors.Player.Position.X / C.WORLD_TILE_PIXELS;
|
||||
int playerWY = (int)Actors.Player.Position.Y / C.WORLD_TILE_PIXELS;
|
||||
int dx = System.Math.Abs(playerWX - s.TileX);
|
||||
int dy = System.Math.Abs(playerWY - s.TileY);
|
||||
return System.Math.Max(dx, dy);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user