Bullet Heaven — sim architecture
Bullet Heaven — sim architecture
Section titled “Bullet Heaven — sim architecture”This is the current ownership map for the deterministic /sim layer. The sim is a
~3,000-line conductor plus focused RefCounted modules, not one monolith. The module split
originally extracted eleven modules from a 4,784-line sim/sim.gd; the conductor has regrown
since then, so use the current file locations below rather than the historical plan as a map.
Module ownership
Section titled “Module ownership”Gameplay logic lives in:
sim/boss_rotation.gd— boss-index lookups andany_boss_alive/is_boss_type/hp_scale. The old rotation dispatch was removed fromsim.gd.sim/boss_warden.gd,sim/boss2.gd,sim/funzo.gd,sim/graviton.gd, andsim/eye.gd— one director per boss.sim/drone_director.gd— drones and the decoy.sim/enemy_behaviors.gd— movement steppers.sim/enemy_attacks.gd— ranged attack loops.sim/elemental_system.gd— damage, collision, reactions, zones, and webs.damage_enemy,resolve_collisions, andapply_elementlive here without a leading underscore._sweep_deadremains onSim.sim/upgrade_system.gd— upgrade rolling, application, evolutions, and display data. Its level-up resolvers areapply_upgrade,reroll_choicesandskip_upgrade(issue #77): render-side, called by main (andReplayDriver) between ticks, never by the tick. They take an explicitpilot, draw only fromupgrade_rng, and keepPlayerState.rerolls_used/levelup_skipsout of the checksums.
Every module is class_name X extends RefCounted, held as a field on Sim (for example
sim.elemental_system), and takes sim: Sim as its explicit first parameter, matching the
older SpawnDirector and StoryDirector pattern.
Director names versus state names
Section titled “Director names versus state names”Boss2, FunZo, Graviton, and Eye directors are named
boss2_director, funzo_director, graviton_director, and eye_director. Sim already has
boss2, funzo, graviton, and eye fields containing each boss’s attack-pattern state
(Boss2State, etc.). For example, sim.funzo.hp is state, while
sim.funzo_director.spawn(sim, ...) invokes the director.
Most tunable constants remain on Sim because modules share them, including
SHOOTER_PROJ_RADIUS, FIRE_RATE_CAP, and RULESET_SURVIVAL. Move a constant only when it is
confirmed exclusive to one module. When extending a system, grep the owning module first;
sim.gd may only contain the conductor call site.