goldbox.effects¶
The active-effect arrays at SAVEDGAME0 $4900, and the spell table that
gives a new one its duration.
Ported out of automap/live.py on #13 (Edit traits and active effects, in
two separate panels), because the panels that read and write this belong to
editor/, and editor/ may not import automap – tests/test_wish.py::
test_editor_imports_nothing_live is what enforces it. automap/live.py
imports these same names back, so automap/combat.py, tools/combatshot.py,
tools/livestrip.py and tests/test_coldread.py still resolve them as
live.EFFECT_ID_OFFSET and so on.
No Qt and no emulator here, the same rule the rest of goldbox/ follows –
load_effect_table is the one function that touches a disk, and it is bytes
in, bytes out, exactly like goldbox/items.py’s load_item_names.
These are not the ten trait slots at record `0x0AD`. The two meet only at
LIBRARY $4028 and the $9AD5 dispatch and share one code namespace
(goldbox/traits.py); the active effects here are 64 slots for the whole
save, own a character, a monster or the party, and expire. A trait never
does. docs/133-active-effects.md is the plan for the two panels this module
feeds.
Functions
|
Every effect slot whose id is non-zero, read across all four arrays. |
|
Zero one slot across all four arrays. |
|
Read ECL65's spell-effect table off a game disk, keyed by the record's own position -- spell id 1-56, then item-only effect argument 57-67. |
|
Write one slot across all four arrays. |
Classes
One slot of the effect table. |
|
One record of ECL65's spell-effect table. |
- class goldbox.effects.Effect[source]¶
Bases:
objectOne slot of the effect table.
Expiry clears only the id, so a slot with id 0 is free whatever the other three arrays still hold.
active_effectsfilters on exactly that, and anything that skips it shows effects that ended hours ago.- __init__(slot, id, owner, duration, magnitude)¶
- property label: str¶
effect 12– always the number, never a looked-up name.goldbox/traits.pydoes hold an id-to-name table (traits.describe), so the old claim that no such table existed anywhere in the project was wrong.labelstill prints the bare number, deliberately: it is what a debug log shows for an effect no condition badge covers, and the point there is to say an id is unbadged, not to name it. A caller that wants the name callstraits.describe(effect.id, game)itself.
- class goldbox.effects.EffectTableEntry[source]¶
Bases:
objectOne record of ECL65’s spell-effect table.
durationis bits 0-5 a count and bits 6-7 a time unit not decoded, the same shapeEffect.durationcarries – and it is frequently 0: a spell whose whole duration scales with the caster sets onlyper_level. ENLARGE is exactly this:duration0,per_level$0A, and a level-1 cast measured live wrote effect duration$0A– one level’s worth,docs/50-experiments.mdconfirms the live write and this table gives the per-level rate it came from.- __init__(duration, per_level, castable_outside_combat, message_index)¶
- goldbox.effects.active_effects(save0_bytes)[source]¶
Every effect slot whose id is non-zero, read across all four arrays.
Takes the payload, so it is already title-independent: the offsets are inside the save image and follow it wherever the title loads it.
- Parameters:
save0_bytes (bytes)
- Return type:
- goldbox.effects.clear_effect(payload, slot)[source]¶
Zero one slot across all four arrays.
Tidier than the game’s own clear:
CAMP $131Fexpires an effect by clearing$4900,Xalone and leaving owner, duration and magnitude as residue (docs/125-bug-notes.mdN7 –PORSAVE13carries six slots with a leftover magnitude of 1 from effects that had already lapsed). A slot this function clears is fully free, not merely free by the one fieldactive_effectshappens to filter on.
- goldbox.effects.load_effect_table(disk)[source]¶
Read ECL65’s spell-effect table off a game disk, keyed by the record’s own position – spell id 1-56, then item-only effect argument 57-67.
Pattern:
goldbox/items.py::load_item_names.ECL65’s own PRG header claims load address$1000, not$9900– like every other game overlay (docs/50-experiments.md, “every game overlay loads at $0800, not the $1000 its header claims”), the header is not where the loader actually puts it, andload_payloadnever reads the header for anything but its length. Record 1’s duration byte reading$06– CONFIRMED live as BLESS’s – is what says these are the right 469 bytes.- Parameters:
disk (goldbox.d64.D64 | str)
- Return type:
- goldbox.effects.write_effect(payload, slot, id, owner, duration, magnitude)[source]¶
Write one slot across all four arrays.
Each of the five arguments is a raw byte; nothing here validates that the combination means anything the game would recognise –
owneris not checked againstPARTY_WIDE/FIRST_MONSTERandmagnitudeis not checked against whichever ids indocs/50-experiments.mdturn out to carry restore data – M2 of#13 (Edit traits and active effects, in two separate panels). Callers behind a write path decide what is safe to offer; this only puts the bytes where the four arrays expect them.