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

153 lines
No EOL
10 KiB
Markdown

# 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:
- Regret: [USECODE/REGRET/REGRET_USECODE_extracted/class_event_index.tsv](USECODE/REGRET/REGRET_USECODE_extracted/class_event_index.tsv#L5715), [USECODE/REGRET/REGRET_USECODE_extracted/class_event_index.tsv](USECODE/REGRET/REGRET_USECODE_extracted/class_event_index.tsv#L5719), [USECODE/REGRET/REGRET_USECODE_extracted/class_event_index.tsv](USECODE/REGRET/REGRET_USECODE_extracted/class_event_index.tsv#L5720), [USECODE/REGRET/REGRET_USECODE_extracted/class_event_index.tsv](USECODE/REGRET/REGRET_USECODE_extracted/class_event_index.tsv#L5725)
- No Remorse: [USECODE/EUSECODE_extracted/class_event_index.tsv](USECODE/EUSECODE_extracted/class_event_index.tsv#L5743), [USECODE/EUSECODE_extracted/class_event_index.tsv](USECODE/EUSECODE_extracted/class_event_index.tsv#L5747), [USECODE/EUSECODE_extracted/class_event_index.tsv](USECODE/EUSECODE_extracted/class_event_index.tsv#L5748), [USECODE/EUSECODE_extracted/class_event_index.tsv](USECODE/EUSECODE_extracted/class_event_index.tsv#L5753)
## 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](USECODE/REGRET/REGRET_USECODE_extracted/pseudocode/WINDSURF/slot_06_gotHit.txt#L1)
No Remorse evidence with preserved local names: [USECODE/EUSECODE_extracted/pseudocode/WINDSURF/slot_06_gotHit.txt](USECODE/EUSECODE_extracted/pseudocode/WINDSURF/slot_06_gotHit.txt#L1)
## 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](USECODE/REGRET/REGRET_USECODE_extracted/pseudocode/WINDSURF/slot_0A_equip.txt#L1)
No Remorse: [USECODE/EUSECODE_extracted/pseudocode/WINDSURF/slot_0A_equip.txt](USECODE/EUSECODE_extracted/pseudocode/WINDSURF/slot_0A_equip.txt#L1)
### `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](USECODE/REGRET/REGRET_USECODE_extracted/pseudocode/WINDSURF/slot_0B_unequip.txt#L1)
No Remorse: [USECODE/EUSECODE_extracted/pseudocode/WINDSURF/slot_0B_unequip.txt](USECODE/EUSECODE_extracted/pseudocode/WINDSURF/slot_0B_unequip.txt#L1)
### `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](USECODE/REGRET/REGRET_USECODE_extracted/pseudocode/WINDSURF/slot_10_leaveFastArea.txt#L1)
No Remorse: [USECODE/EUSECODE_extracted/pseudocode/WINDSURF/slot_10_leaveFastArea.txt](USECODE/EUSECODE_extracted/pseudocode/WINDSURF/slot_10_leaveFastArea.txt#L1)
### `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](USECODE/EUSECODE_extracted/pseudocode/WINDSURF/slot_06_gotHit.txt#L1)
## 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:
- Regret metadata: [USECODE/REGRET/REGRET_USECODE_extracted/class_event_index.tsv](USECODE/REGRET/REGRET_USECODE_extracted/class_event_index.tsv#L5715), [USECODE/REGRET/REGRET_USECODE_extracted/class_event_index.tsv](USECODE/REGRET/REGRET_USECODE_extracted/class_event_index.tsv#L5719), [USECODE/REGRET/REGRET_USECODE_extracted/class_event_index.tsv](USECODE/REGRET/REGRET_USECODE_extracted/class_event_index.tsv#L5720), [USECODE/REGRET/REGRET_USECODE_extracted/class_event_index.tsv](USECODE/REGRET/REGRET_USECODE_extracted/class_event_index.tsv#L5725)
- No Remorse metadata: [USECODE/EUSECODE_extracted/class_event_index.tsv](USECODE/EUSECODE_extracted/class_event_index.tsv#L5743), [USECODE/EUSECODE_extracted/class_event_index.tsv](USECODE/EUSECODE_extracted/class_event_index.tsv#L5747), [USECODE/EUSECODE_extracted/class_event_index.tsv](USECODE/EUSECODE_extracted/class_event_index.tsv#L5748), [USECODE/EUSECODE_extracted/class_event_index.tsv](USECODE/EUSECODE_extracted/class_event_index.tsv#L5753)
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:
- Regret `equip` uses `class_0A1D_slot_3C`: [USECODE/REGRET/REGRET_USECODE_extracted/pseudocode/WINDSURF/slot_0A_equip.txt](USECODE/REGRET/REGRET_USECODE_extracted/pseudocode/WINDSURF/slot_0A_equip.txt#L4)
- No Remorse `equip` uses `class_0A0C_slot_33`: [USECODE/EUSECODE_extracted/pseudocode/WINDSURF/slot_0A_equip.txt](USECODE/EUSECODE_extracted/pseudocode/WINDSURF/slot_0A_equip.txt#L9)
- Regret `gotHit` spawns `class_0A1D_slot_3B` and `class_0A17_slot_20`: [USECODE/REGRET/REGRET_USECODE_extracted/pseudocode/WINDSURF/slot_06_gotHit.txt](USECODE/REGRET/REGRET_USECODE_extracted/pseudocode/WINDSURF/slot_06_gotHit.txt#L104), [USECODE/REGRET/REGRET_USECODE_extracted/pseudocode/WINDSURF/slot_06_gotHit.txt](USECODE/REGRET/REGRET_USECODE_extracted/pseudocode/WINDSURF/slot_06_gotHit.txt#L123)
- No Remorse `gotHit` spawns `class_0A0C_slot_32` and `class_0A18_slot_20`: [USECODE/EUSECODE_extracted/pseudocode/WINDSURF/slot_06_gotHit.txt](USECODE/EUSECODE_extracted/pseudocode/WINDSURF/slot_06_gotHit.txt#L118), [USECODE/EUSECODE_extracted/pseudocode/WINDSURF/slot_06_gotHit.txt](USECODE/EUSECODE_extracted/pseudocode/WINDSURF/slot_06_gotHit.txt#L145)
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.
- [USECODE/EUSECODE_extracted/pseudocode/WVENTNS/slot_06_gotHit.txt](USECODE/EUSECODE_extracted/pseudocode/WVENTNS/slot_06_gotHit.txt#L1)
- [USECODE/EUSECODE_extracted/pseudocode/WVENTEW/slot_06_gotHit.txt](USECODE/EUSECODE_extracted/pseudocode/WVENTEW/slot_06_gotHit.txt#L1)
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.