From 0bb3f78a338b59428b61daf788e1dd1967ec58be Mon Sep 17 00:00:00 2001 From: "Eevee (Evelyn Woods)" Date: Sat, 26 Dec 2020 02:03:39 -0700 Subject: [PATCH] Give flame jets their own mini-pass --- js/game.js | 38 ++++++++++++++++++++++++++++---------- js/tiletypes.js | 41 +++++++++++++++++++---------------------- 2 files changed, 47 insertions(+), 32 deletions(-) diff --git a/js/game.js b/js/game.js index 010f2f6..da5c440 100644 --- a/js/game.js +++ b/js/game.js @@ -400,8 +400,10 @@ export class Level extends LevelInterface { let n = 0; let connectables = []; this.remaining_players = 0; - // FIXME handle traps correctly: - // - if an actor is in the cell, set the trap to open and unstick everything in it + // Speedup for flame jets, which aren't actors but do a thing every tic + // TODO this won't notice if a new tile with an on_tic is created, but that's impossible + // atm... or, at least, it's hacked to still work with flame_jet_off + this.static_on_tic_tiles = []; for (let y = 0; y < this.height; y++) { let row = []; for (let x = 0; x < this.width; x++) { @@ -428,6 +430,9 @@ export class Level extends LevelInterface { if (tile.type.is_actor) { this.actors.push(tile); } + else if (tile.type.on_tic) { + this.static_on_tic_tiles.push(tile); + } cell._add(tile); if (tile.type.connects_to) { @@ -742,9 +747,9 @@ export class Level extends LevelInterface { // are only two wiring updates before everything gets its first chance to move, so we skip // the very first one here. if (this.tic_counter !== 0) { - this.update_wiring(); + this._do_wire_phase(); } - this.update_wiring(); + this._do_wire_phase(); // Advance everyone's cooldowns // Note that we iterate in reverse order, DESPITE keeping dead actors around with null @@ -775,14 +780,17 @@ export class Level extends LevelInterface { } } - this.update_wiring(); + this._do_wire_phase(); + // TODO should this also happen three times? + this._do_static_phase(); } // Lynx-style loop: everyone decides, then everyone moves/cools. _begin_tic_lynx() { this._do_decision_phase(); this._do_combined_action_phase(3); - this.update_wiring(); + this._do_wire_phase(); + this._do_static_phase(); this._do_cleanup_phase(); } @@ -792,15 +800,18 @@ export class Level extends LevelInterface { _begin_tic_lynx60() { this._do_decision_phase(true); this._do_combined_action_phase(1, true); - this.update_wiring(); + this._do_wire_phase(); + this._do_static_phase(); this._do_decision_phase(true); this._do_combined_action_phase(1, true); - this.update_wiring(); + this._do_wire_phase(); + this._do_static_phase(); this._do_decision_phase(); this._do_combined_action_phase(1); - this.update_wiring(); + this._do_wire_phase(); + this._do_static_phase(); this._do_cleanup_phase(); } @@ -1648,7 +1659,7 @@ export class Level extends LevelInterface { } } - update_wiring() { + _do_wire_phase() { if (this.circuits.length === 0) return; @@ -1778,6 +1789,13 @@ export class Level extends LevelInterface { }); } + // Some non-actor tiles still want to act every tic. Note that this should happen AFTER wiring. + _do_static_phase() { + for (let tile of this.static_on_tic_tiles) { + tile.type.on_tic(tile, this); + } + } + // ------------------------------------------------------------------------- // Board inspection diff --git a/js/tiletypes.js b/js/tiletypes.js index 3d50de7..06a6b45 100644 --- a/js/tiletypes.js +++ b/js/tiletypes.js @@ -804,7 +804,7 @@ const TILE_TYPES = { on_ready(me, level) { // FIXME in cc2 only, actors on a bomb immediately explode, but that's tricky for the // player since we can't kill them before the game even starts. cc2 just murders them - // instantly. maybe we could do that then + // instantly. maybe we could do that then? or use on_tic, like flame jets? }, on_arrive(me, level, other) { level.remove_tile(me); @@ -1326,11 +1326,8 @@ const TILE_TYPES = { draw_layer: DRAW_LAYERS.terrain, activate(me, level) { level.transmute_tile(me, 'flame_jet_on'); - // If there's anything on us already, nuke it - let actor = me.cell.get_actor(); - if (actor && ! actor.movement_cooldown) { - me.type._kill(me, level, actor); - } + // Do NOT immediately nuke anything on us, or it'd be impossible to push a block off an + // adjacent orange button; this is probably why flame jets kill on tics }, on_gray_button(me, level) { me.type.activate(me, level); @@ -1338,6 +1335,9 @@ const TILE_TYPES = { on_power(me, level) { me.type.activate(me, level); }, + // This is a silly hack to get us flagged as a static tile, so when we're turned on, that + // tile's on_tic will still run + on_tic() {}, }, flame_jet_on: { draw_layer: DRAW_LAYERS.terrain, @@ -1350,23 +1350,20 @@ const TILE_TYPES = { on_power(me, level) { me.type.activate(me, level); }, - // Kill anything that shows up - // FIXME every tic, also kills every actor in the cell (mostly matters if something steps on - // with fire boots and then drops them, which is unlike fire) - _kill(me, level, other) { - // Note that (dirt?) blocks, fireballs, and anything with fire boots are immune - // TODO would be neat if this understood "ignores anything with fire immunity" but that - // might be a bit too high-level for this game - if (other.type.is_real_player) { - level.fail('burned'); + on_tic(me, level) { + let actor = me.cell.get_actor(); + if (actor && actor.movement_cooldown <= 0 && ! actor.ignores(me.type.name)) { + // Note that (dirt?) blocks, fireballs, and anything with fire boots are immune + // TODO would be neat if this understood "ignores anything with fire immunity" but that + // might be a bit too high-level for this game + if (actor.type.is_real_player) { + level.fail('burned'); + } + else { + // TODO should this play a sound? + level.transmute_tile(actor, 'explosion'); + } } - else { - // TODO should this play a sound? - level.transmute_tile(other, 'explosion'); - } - }, - on_arrive(me, level, other) { - this._kill(me, level, other); }, }, // Buttons