Releases: codingncaffeine/SiegeFX
v0.9.0 — Phase 10: actors
What's New
Phase 10 — actor pipeline
- Template store with
specializes-chain inheritance; resolves3W_goblin_gruntback through3W_base_goblin → actor_evil → actor, merging[aspect]/[common]/[chore_dictionary]blocks along the way. - Region actor loader reads per-region actor instances from
objects/regular/actor.gasand hands them off as(scid, template, position)tuples. - ActorSpawner stands up per-region shared
SkritRuntime+WorldMessageBusand drives each actor through its archetype's startup state. - WorldMessageBus routes
PostWorldMessagebroadcasts (toScid==0) and targeted sends to registered skrit instances on drain. - Viewer
--play-region: loads terrain + 181 actors infh_r1, runs the skrit VM at 20 Hz, renders per-actor skinned meshes with identity-bone fallback for archetypes whose PRS clips aren't parsed yet.
Composition fix
RegionLayout/WorldLayoutmatrix composition had the operands reversed relative to row-vector convention — regions were collapsing to a near-identity cluster at the anchor ("the world clumps at origin" since Phase 6b). New order matches OpenSiegeSiegeNodeMesh::connectexactly. Post-fixWorld.dsmapplaces 81/81 regions spanning(-1954, -304, -947)→(400, 28, 924)across 53,453 snodes.
Tooling
siegefx templates show <tank> <name>/templates list --prefix=… --tag=…siegefx region actors <map-tank> <region-path>siegefx region spawn <map-tank> <logic-tank> <objects-tank> <region-path> [--broadcast=EVENT]test-all.batgains options 10–13 for the Phase 10 slices.
v0.8.0 — Skrit scripting runtime
What's New
Shipped DS1 scripts now drive real behavior inside SiegeFX. The Skrit VM is complete (lex / parse / bind / compile / interpret) and the viewer can hand an actor's animation decisions off to a shipped .skrit file.
Skrit VM (Phase 8)
- Lexer — 364 shipped skrits (Logic + Objects), 0 lex failures on all of them.
- Parser — recursive descent with 14 precedence levels; shipped-quirk tolerance (inline state triggers, declarative transitions with
ifguards and= { body }edge-fire blocks, bare-name functions, unbalanced-paren tolerance,**exponent, commented-out parameter names, multi-declaratorint a$, b$ = 0). - Binder — two-pass symbol table covering properties, fields, functions, states, and the host-API extern catalogue. Surfaces 154 real bugs in GPG's shipped scripts as informational diagnostics without aborting the pipeline.
- Compiler + VM — stack-based bytecode with tagged-union values, ~35 opcodes, short-circuit via
Dup+JumpIf, synthetic@__init__chunk for property initialisers, case-insensitive keyword dispatch. - Runtime — per-actor
SkritInstancewith deferredSetState, one-shot chore scheduler at 20 Hz (DS1's authoritative scripted-systems rate), event/trigger resolution across state-local and top-level scopes. - Host bridge —
ActorHostBridgecapturesowner.blender.*activity through tag-string dispatch so undefined identifiers can't silently answerMath.RandomInt.ANIMEVENT_*bitmask constants synthesised on demand.
Tools
siegefx skrit tokens | parse | bind | compile | run | tick | fuzz <file.skrit>— full pipeline on the CLI, including a tick driver that runs shipped scripts against the runtime.
Viewer (Phase 9a)
SiegeFX.Runtime --skrit-anim <rigged.asp> <file.skrit> <clip0.prs> [clip1.prs ...] [--texture <raw>]— hand the viewer a rigged mesh, a shipped skrit, and a set of PRS clips; the skrit'sOnStartChore$handler decides which clip plays viaowner.blender.AddAnimToBlendGroup.
Verified against shipped content
basic_walk.skrit: dispatchesOpenBlendGroup/AddAnimToBlendGroup(0,1)/CloseBlendGroup/SetBlendGroupWeight(0,1)through the host bridge.simple_loop.skrit:Startup$ -> Looper$state transition via deferredSetState,OnEnterState$fires the next state's blender calls.
Notes
Requires original Dungeon Siege 1 game data. Ships no copyrighted assets. Prerelease per the until-v1.0 rule.
v0.7.0 — Skeletal animation milestone
What's New in v0.7.0
First tagged release. SiegeFX is a clean-room Dungeon Siege 1 reimplementation in C#/.NET 8. This milestone closes Phases 0-7 of a 9-phase plan — everything through a visibly-animated rigged character.
Rendering
- Skeletal animation — rigged ASP + PRS clip viewer, per-corner 4-bone GPU skinning, looped playback. Walks the goblin.
- Continuous world streaming — regions stitched via intra-region door graphs and
editor/stitch_helper.gascross-region pairs.World.dsmap: 81/81 regions placed, 0 unresolved. - Textured terrain —
.snosubsets with per-surface albedo from.dsmaptanks. - Textured meshes —
.aspstatic meshes,.rawalbedo with pre-baked mip chain respected.
Asset Pipeline
- Tank reader —
.dsres/.dsmap, zlib round-trip clean. 9187 files fuzzed across Logic/Objects/Terrain tanks, 0 failures. - RAW textures — BGRA→RGBA decode, full on-disc mipmap chain, hand-rolled PNG encoder.
- GAS parser — DS1 hierarchical config format; tolerates authoring typos. Fuzz-clean across every shipped
.gas. - PRS animation — bone name map, KLST key lists, normalized-time sampling.
- ASP rigged — BMSH/BONH/RPOS/WCRN; cached inverse-bind matrices.
Viewer Modes
Launch via dotnet run --project src/SiegeFX.Runtime -- <args>:
<mesh.asp|mesh.sno> [texture.raw|tank.dsres]— single asset--region <map-tank> <terrain-tank> <region-path>--world <map-tank> <terrain-tank> [root-region]--anim <rigged.asp> <clip.prs> [texture.raw]
Controls: RMB + WASD to fly, Shift to sprint, Esc to quit.
CLI (siegefx)
tank info|list|extractasp info,raw info|decode,gas info|dump|fuzzregion info|layout|layout-diag|fuzz,world layoutprs info|sample|fuzz,anim fuzz
What's Next
- Phase 8 — Skrit VM (actor behavior scripts)
- Phase 9+ — Gameplay (combat, AI, inventory, pathfinding)
Requirements
Original Dungeon Siege game data (e.g., a GOG install) for Logic.dsres, Objects.dsres, Terrain.dsres, World.dsmap. No copyrighted assets ship with this release.
Build
dotnet build -c Release — .NET 8 SDK, Windows (Silk.NET OpenGL 3.3 core).
Prerelease. All versions up to v1.0 are marked as such.