This note records the current evidence-backed read of exported `ALARMHAT` pseudocode and what the class most likely means in gameplay.
The goal is not to force a final rename. The goal is to state what the script definitely does, what it probably does, and where the remaining uncertainty sits.
- raw linear disassembly in `K:/ghidra/crusader-disasm/crusader_disasm.txt`
- nearby alarm-family comparators:
-`ALARMBOX`
-`ALRMTRIG`
-`ALARM_NS`
-`ALARM_EW`
## Short version
`ALARMHAT` is not a general many-event alarm controller. In the extracted corpus it has one live body: slot `0x0A` (`equip`).
That body behaves like an alarm-family state controller attached to an item. It does two different things depending on the current frame of the item:
1. in frame `0`, it searches nearby shape `0x04D0` objects and equips qualifying ones with mode `0x17`
2. in non-zero frames, it first requires the item to be on-screen, then performs a nearby actor/family scan, and if that passes it searches nearby shape `0x04D0` objects and equips qualifying ones with mode `0x15`
The likely gameplay read is: `ALARMHAT` is a local alarm-state driver that flips nearby helper objects or actors into one of two equipment/activation states, with the second state gated by player-visible activity near the item.
## Structural facts
From `class_event_index.tsv`:
- class: `ALARMHAT`
- class id: `0x0561`
- only decoded non-zero slot: `0x0A equip`
- body window: `0x00D4..0x025F`
- body length: `395` bytes
From the debug trailer/local names in the exported body:
- locals currently render as `referent`, `var`, `item`, and `npc`
Those local names are useful hints, but the behavior matters more than the variable spelling.
## Direct script behavior
The body begins with the standard alarm-family setup:
```text
set_info(0x0211, *(arg_06));
process_exclude();
```
That matches `ALARMBOX::equip`, which also begins with `set_info(0x0211, *(arg_06)); process_exclude();`.
After that, the script splits on `Item.getFrame(arg_06)`.
### Branch 1: frame == 0
The raw disassembly shows a loop-selector sequence equivalent to:
- search nearby items
- constrain by `item->shape == 0x04D0`
- use the current item as the search origin
For each matching object:
- call `Item.getFrame(item)`
- only continue on frame `0`
- call `Item::I_equip(pid, 0x17, item)`
-`suspend`
So the first branch is not sounding an alarm by itself. It is driving nearby shape `0x04D0` objects into a specific equip/activation mode.
### Branch 2: frame != 0
This branch only runs if `Item::I_isOnScreen(arg_06)` passes.
It then performs another nearby search, this time using `item->family` with family value `6`. Inside that scan it uses:
-`Actor::I_isNPC(...)`
-`Item::I_getZ(...)`
- a vertical-band test of `origin_z - 10 < candidate_z < origin_z + 10`
The exact truth sense of the `Actor::I_isNPC` step is still slightly uncertain because we are reading it through the current pseudo-IR condition simplifier, but the script is clearly trying to qualify nearby actor-like entities in the same local vertical band before proceeding.
If that actor/family gate succeeds, the script runs a second nearby shape search for `item->shape == 0x04D0`, again requiring frame `0` on the found object, then calls:
```text
Item::I_equip(pid, 0x15, item)
```
followed by `suspend`.
So the non-zero-frame branch is the more selective mode: it only arms the nearby `0x04D0` helper objects once a local visibility/actor-proximity condition is satisfied.
## What shape `0x04D0` likely is
The old disassembly corpus labels usecode class `0x04D0` as `MONSTER`.
That does not prove every shape-id use of `0x04D0` is literally a monster actor object, but it is a strong clue that `ALARMHAT` is not interacting with an arbitrary visual prop. It is probably targeting a helper/actor class in the monster or hostile-response lane.
This is the strongest reason not to read `ALARMHAT` as just a decorative siren hat sprite. The script is actively scanning for nearby `0x04D0` objects and equipping them.
This follow-up also narrows one tempting overread: `quality` low byte is not the primary `spawn now vs wait` control in `MONSTER::enterFastArea`. The current Regret `ALARMHAT` body does still compare nearby `0x04D0``Item.getQLo(...)` values against difficulty lanes `0/1/2`, so low quality remains relevant as a secondary filter, just not as the automatic-enter-area gate.
The wider exported corpus now supports keeping that claim local but real. Additional `0x04D0`-adjacent bodies in `ITEM.slot_2D`, `FUSPAC.slot_01`, and `MISS8.slot_20` also scan nearby `0x04D0` objects and branch on frame and/or `Item.getQLo(...)`. Current safest synthesis is therefore:
-`frame` plus `mapNum bit 0x08` controls the automatic `MONSTER.enterFastArea` lane
-`quality` low byte is still a real local signal key used by several authored trigger/alarm/helper families
- but that low byte is not yet proven to be a single universal direct-link field across every `0x04D0` interaction
`ALARMHAT` fits the broader alarm family, but it is not identical to the other alarm classes.
### `ALARM_NS` and `ALARM_EW`
These are tiny `enterFastArea` stubs. They mainly stamp info, exclude themselves from processing, and gate on a simple intrinsic.
Those look like directional/environment trigger markers.
### `ALRMTRIG`
This class is a compact trigger/spawner. Its `equip` body branches on map/state and spawns `class_0A18_slot_20(...)` with different mode values.
That looks more like an alarm-event relay.
### `ALARMBOX`
This is the closest comparator.
`ALARMBOX::equip`:
- uses the same `set_info(0x0211)` + `process_exclude()` prologue
- branches by local state and frame
- spawns different helper slots for low/high alarm states
- can also spawn `class_0A18_slot_20(...)`
So `ALARMBOX` reads like a more explicit alarm control box, while `ALARMHAT` reads like a local accessory/controller that pushes nearby helper objects into one of two equip states.
## Gameplay interpretation
The safest gameplay-facing read is:
`ALARMHAT` is an alarm-state accessory or controller item that toggles nearby hostile/helper objects between two alarm-response modes.
The second mode only activates when the item is visible on screen and when a nearby actor-like entity qualifies within a narrow Z band, which strongly suggests local encounter awareness rather than a map-global trigger.
In practical gameplay terms, the object likely does something like one of these:
- wake up or arm nearby hostile responders
- switch nearby helper entities between idle and alert states
- mark a local alarm point as actively triggered once the player or another actor is nearby
The name `ALARMHAT` therefore probably reflects object art or designer shorthand rather than a full behavior description. The script behavior is closer to `alarm accessory that equips nearby monster/helper actors into a response mode` than to `play a siren sound` or `flash a light`.
## Confidence and uncertainty
High confidence:
-`ALARMHAT` has one live exported body, slot `0x0A equip`
- it uses the same `0x0211` alarm-family setup as `ALARMBOX`
- it branches on its own frame
- it performs nearby searches on shape `0x04D0`
- it calls `Item::I_equip(...)` on qualifying found objects with two different mode values: `0x17` and `0x15`
- the second mode is gated by on-screen and nearby actor/family checks
Moderate confidence:
- shape `0x04D0` is a monster/helper/hostile-response class rather than an inert prop
- the non-zero-frame branch is the alert or escalation state
Lower confidence / still open:
- the exact semantic meaning of equip modes `0x17` versus `0x15`
- the precise truth sense of the `Actor::I_isNPC`-named intrinsic inside the family-`6` scan
- whether `ALARMHAT` is physically a wearable-looking prop, a mounted alarm device, or a small controller object whose art happened to be named `HAT`
## Current best rename-level takeaway
Do not rename it yet.
But the current best mental model is:
`ALARMHAT = local alarm-state driver that equips nearby MONSTER/helper objects into one of two response modes depending on frame/state and nearby actor visibility.`