Modern open-source C# .NET 10 Asheron's Call client. Faithful port of retail client behaviour to Silk.NET with a plugin API.
Find a file
Erik 82aa2ba1d9 fix(core): SetupMesh prefers Placement.Resting over Default (Phase 5d)
The Nullified Statue of a Drudge renders correctly in scale + color +
texture after Phases 5a/b/c, but the user reported the figure on top
looks like the wrong drudge model — specifically the pose is wrong.
acdream shows a hunched aggressive crouch with arms forward, retail
shows an upright statue stance with arms at sides. Same drudge mesh,
different pose.

Diagnosis from a targeted statue dump:
  [STATUE] objScale=3.500
  [STATUE] base Setup 0x020007DD has 17 parts (full drudge body rig)
  [STATUE] animPart index=1 newModel=0x01001B91   ← NO-OP, same as default
  [STATUE]   placementFrames count=1

The animPart change is a no-op (replaces part 1 with the id it already
has). The Setup is the standard drudge body. So the difference HAS to
come from the per-part placement frame. With only 1 placement frame,
there's exactly one pose to use — and our SetupMesh.Flatten only checks
Placement.Default.

Fix found by reading ACViewer's Physics/PartArray.cs::CreateMesh:

  public static PartArray CreateMesh(PhysicsObj owner, uint setupDID) {
      var mesh = new PartArray();
      ...
      if (!mesh.SetMeshID(setupDID)) return null;
      mesh.SetPlacementFrame(0x65);     // ← always Resting after create
      return mesh;
  }

0x65 = 101 = Placement.Resting. ACViewer puts EVERY mesh into the
Resting pose immediately after creation, regardless of object type.
For drudges/characters/creatures:
  - Default = aggressive battle crouch (what we render)
  - Resting = upright idle pose (what retail's statue actually shows)

The statue's single placement frame is keyed by Resting, so our
"only check Default" code returned no frame and the parts ended up at
Setup-root with identity orientation — which happened to look like a
clawing-forward pose because each part's local mesh starts in roughly
that shape.

Fix: SetupMesh.Flatten now tries Resting first and falls back to
Default. Static scenery setups (which only define Default) are
unaffected; creatures and characters now render in their proper idle
pose. One-line conceptual change with effects on every multi-part
live entity in the world.

The reference-priority rule in CLAUDE.md saved me here: I'd already
chased this through ACE.Server and DatReaderWriter looking for a parent-
hierarchy walking algorithm before checking ACViewer's Physics/PartArray.
The pose fix lives in ACViewer's renderer, exactly where I'd expect
"the canonical client-side visual pipeline" per the rule's wording.

Tests: 77 core + 83 net = 160, all green. Existing scenery
SetupMesh tests still pass because their setups only define Default.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 18:21:13 +02:00
docs/plans docs(plan): Phase 3c terrain blending plan 2026-04-10 23:43:04 +02:00
src fix(core): SetupMesh prefers Placement.Resting over Default (Phase 5d) 2026-04-11 18:21:13 +02:00
tests feat(net): CreateObject body parser — GUID + Position + SetupId extracted (Phase 4.7d) 2026-04-11 15:18:54 +02:00
.gitignore chore: phase 0 — skeleton + dat asset inventory 2026-04-10 09:02:56 +02:00
AcDream.slnx feat(net): AcDream.Core.Net scaffold + ISAAC keystream (Phase 4.1) 2026-04-11 14:14:28 +02:00
CLAUDE.md feat(net+app): SubPalette overlays applied to palette-indexed textures (Phase 5b) 2026-04-11 16:30:08 +02:00
README.md chore: phase 0 — skeleton + dat asset inventory 2026-04-10 09:02:56 +02:00

acdream

Experimental modern open-source Asheron's Call client in C# / .NET 10.

Status: pre-alpha, not playable. Phase 0 only — dat file asset inventory.

Stack: .NET 10, Chorizite.DatReaderWriter for dat parsing. Silk.NET + Avalonia planned for rendering/UI (not yet wired up).

Requires: A retail Asheron's Call install (Turbine/Microsoft property — supply your own). Set ACDREAM_DAT_DIR environment variable to the directory containing client_portal.dat, client_cell_1.dat, client_highres.dat, and client_local_English.dat, or pass it as the first CLI argument.

Layout

  • src/AcDream.Cli/ — console app that dumps asset counts from a dat directory
  • references/ — local read-only reference material (ACE, ACViewer, WorldBuilder, DatReaderWriter, holtburger, retail AC install). Gitignored.

Run

dotnet run --project src/AcDream.Cli -- "C:\path\to\Asheron's Call"

Or set ACDREAM_DAT_DIR and run without args.