Crusader_Decomp/docs/usecode/windsurf-regret-vs-remorse.md
2026-03-26 00:37:17 +01:00

10 KiB

WINDSURF: Regret vs No Remorse

This note compares the exported WINDSURF USECODE handlers between the Regret corpus at USECODE/REGRET/REGRET_USECODE_extracted/ and the No Remorse corpus at USECODE/EUSECODE_extracted/.

Scope

  • Regret source class: WINDSURF entry 179, class id 0x0337
  • No Remorse source class: WINDSURF entry 180, class id 0x0337
  • Active slots in both corpora:
    • 0x06 gotHit
    • 0x0A equip
    • 0x0B unequip
    • 0x10 leaveFastArea

Slot metadata confirms the same active event set in both builds:

High-Level Read

Current best read: WINDSURF is a wind-force / push-volume helper that applies directional displacement to overlapping targets. It is not primarily an item-use script or a one-off effect trigger.

The strongest common behavior is in gotHit, which:

  • resolves a target/reference pair from a helper call
  • filters out unwanted targets by type, shape, overlap state, and actor flags
  • converts a 16-step direction value into x and y offsets
  • scales those offsets by a speed value, with a difficulty-based override when speed is 15
  • repeatedly applies movement toward the offset destination while the target remains within the effect

Regret evidence: USECODE/REGRET/REGRET_USECODE_extracted/pseudocode/WINDSURF/slot_06_gotHit.txt

No Remorse evidence with preserved local names: USECODE/EUSECODE_extracted/pseudocode/WINDSURF/slot_06_gotHit.txt

Shared Behavior

The two corpora agree on the overall lifecycle.

equip

Both versions:

  • set local bookkeeping/info state
  • register the object with a helper using selector 0x020C
  • skip the scan if a parameter is 0x00FF
  • otherwise iterate nearby candidates and spawn WINDSURF::gotHit for non-overlapping matches

Regret: USECODE/REGRET/REGRET_USECODE_extracted/pseudocode/WINDSURF/slot_0A_equip.txt

No Remorse: USECODE/EUSECODE_extracted/pseudocode/WINDSURF/slot_0A_equip.txt

unequip

Both versions iterate the same candidate loop and re-spawn gotHit for the same overlap-based filter.

Regret: USECODE/REGRET/REGRET_USECODE_extracted/pseudocode/WINDSURF/slot_0B_unequip.txt

No Remorse: USECODE/EUSECODE_extracted/pseudocode/WINDSURF/slot_0B_unequip.txt

leaveFastArea

Both versions only perform lightweight bookkeeping and unregister/update the 0x020C helper state.

Regret: USECODE/REGRET/REGRET_USECODE_extracted/pseudocode/WINDSURF/slot_10_leaveFastArea.txt

No Remorse: USECODE/EUSECODE_extracted/pseudocode/WINDSURF/slot_10_leaveFastArea.txt

gotHit

Both versions perform the same gameplay-side stages:

  1. Resolve target and velocity/reference context from a helper call.
  2. Reject cases on wrong map array/map number, wrong type/shape, missing overlap, and incompatible actor/NPC state.
  3. Default speed to 3 when zero and expand 15 into a difficulty-scaled speed.
  4. Map a 16-way direction into signed xoff and yoff steps.
  5. Multiply those steps by speed.
  6. Feed the result into a pair of movement/update helper calls.
  7. Fall back to a separate spawned helper when the source object is on another map array.

The No Remorse decompile makes this especially clear because it preserved locals such as item, xoff, yoff, speed, and dir: USECODE/EUSECODE_extracted/pseudocode/WINDSURF/slot_06_gotHit.txt

Important Differences

The differences currently look like implementation/layout differences rather than a different gameplay role.

1. Body sizes are materially smaller in Regret

  • Regret gotHit: 753 bytes vs No Remorse 1121 bytes
  • Regret equip: 114 bytes vs No Remorse 193 bytes
  • Regret unequip: 78 bytes vs No Remorse 145 bytes
  • Regret leaveFastArea: 27 bytes vs No Remorse 59 bytes

Evidence:

At the current pseudocode fidelity, this does not yet prove a gameplay change. It more likely indicates one or more of:

  • more compact compiled helper usage in Regret
  • different trailer/debug-symbol coverage between variants
  • helper-class renumbering and wrapper differences that the exporter is not yet lowering into named operations

2. Helper class IDs differ across the two corpora

The high-level actions align, but the helper targets differ:

  • Regret tends to call/spawn class_0A1D_* and class_0A17_slot_20
  • No Remorse tends to call/spawn class_0A0C_* and class_0A18_slot_20

Examples:

Current best read: these are corresponding support classes in different builds, not evidence that WINDSURF changed role.

3. No Remorse preserves clearer local names

The No Remorse gotHit pseudocode retained variable names such as item, xoff, yoff, speed, and dir, which makes the movement semantics explicit. The Regret decompile currently renders the same logic through anonymous locals like local_02, local_04, local_06, local_08, and local_0A.

This is a tooling/output-quality difference, not currently a behavior difference.

Cross-Reference: Wind Vents

The No Remorse vent handlers WVENTNS and WVENTEW both carry a local variable named windsurf, which strongly supports the interpretation that WINDSURF is the reusable wind-effect object used by vent-style map machinery.

This supports the gameplay-facing name wind surface / wind push field much more strongly than anything like a weapon, NPC AI, or one-shot trap script.

Current Conclusion

Current best read remains:

WINDSURF is a directional wind-force helper shared by both Regret and No Remorse. It registers an area-effect object, scans nearby candidates, and pushes overlapping targets along a configured direction and speed, with some actor/type filtering and an alternate map-array handling path.`

There is no strong evidence yet that the gameplay role changed between Regret and No Remorse. The main differences are:

  • helper/wrapper class numbering
  • larger compiled bodies in No Remorse
  • better preserved symbolic locals in the No Remorse export

Open Questions

  • Whether Regret's smaller bodies reflect true logic removal or just tighter helper factoring.
  • What helper families 0A1D and 0A17 in Regret correspond to exactly relative to No Remorse 0A0C and 0A18.
  • Whether shape 0x01D9 is the same excluded target class in both variants and why WINDSURF explicitly skips it.
  • Whether the map-array fallback helper is a teleport/materialization path, a cross-map handoff, or a delayed movement dispatch.