Bonus pickups (rewrite)¶
This page tracks parity for world bonus pickups (the floating pickups you walk over), comparing the Python + raylib rewrite to the classic exe.
Authoritative reference: bonus_render (0x004295f0) and bonus_spawn_at
(0x0041f5b0) in analysis/ghidra/raw/crimsonland.exe_decompiled.c.
What the exe does¶
Rendering (bonus_render)¶
For each active bonus_pool entry:
- Draw a 32×32 bubble backdrop using
bonuses.pngframe0(grid 4×4). - Draw the bonus icon on top:
- For most bonuses:
bonuses.pngframe =bonus_meta.icon_id(grid 4×4). - For Points (bonus id
1): ifamount == 1000, useicon_id + 1(the 1000‑points icon). - For Weapon (bonus id
3): draw a 2×1 sub-rect fromui_wicons.pngbased onweapon_table[weapon_id].hud_icon_id, scaled to 60×30 at full size. - Animate:
- Fade in for the first 0.5s and fade out for the last 0.5s.
- Subtle pulse using
sin(...)^4 * 0.25 + 0.75. - Icons (non-weapon) also rotate slightly (
sin(...) * 0.2radians).
Effects¶
- On spawn (
bonus_spawn_at): spawn a burst of transient effects (effect_id=0, 16 entries). - On pickup (
bonus_apply): playsfx_ui_bonusand spawn another burst (effect_id=0, 12 entries, different lifetime/scale defaults). Some bonuses also spawn a ring/halo (effect_id=1) (e.g. Reflex Boost / Freeze).
What was missing in the rewrite¶
- World pickups were drawn as a plain icon (no bubble backdrop).
- No fade/pulse/rotation animation.
- Weapon bonus pickups didn’t render
ui_wicons(no wide weapon icon). - No “bonus spawn / bonus pickup” visual burst, and no
sfx_ui_bonuson pickup.
What is implemented now¶
src/crimson/game_world.py: world bonus pickups render with the bubble backdrop + animated icon (including weaponui_wiconsrendering).src/crimson/effects.py:EffectPool.spawn_burstandEffectPool.spawn_ringports used by bonus spawn/pickup effects.src/crimson/creatures/runtime.py: bonus spawn burst is emitted when a bonus drops on creature death.src/crimson/game_world.py: bonus pickup playssfx_ui_bonusand spawns the pickup burst (+ ring for Reflex/Freeze).
Remaining gaps / TODO¶
- Bonus label text near players (and Telekinetic “aim to pick up” behavior) from
the tail of
bonus_render. - Full
bonus_applyFX parity for high-impact bonuses (notably the Nuke explosion burst path).