From 63f09283ea8c973dc267f88cdc651c11f47a7a1f Mon Sep 17 00:00:00 2001 From: "Eevee (Evelyn Woods)" Date: Tue, 29 Dec 2020 07:21:18 -0700 Subject: [PATCH] Make actors explode when starting the level on a bomb --- js/game.js | 26 ++++++++++++++++++++++---- js/main.js | 4 ++++ js/tiletypes.js | 25 +++++++++++++++---------- 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/js/game.js b/js/game.js index eb3aa70..d139cdf 100644 --- a/js/game.js +++ b/js/game.js @@ -361,6 +361,7 @@ export class Level extends LevelInterface { this.aid = 0; // Time + this.done_on_begin = false; if (this.stored_level.time_limit === 0) { this.time_remaining = null; } @@ -615,10 +616,7 @@ export class Level extends LevelInterface { this.wired_outputs = Array.from(wired_outputs); this.wired_outputs.sort((a, b) => this.coords_to_scalar(a.cell.x, a.cell.y) - this.coords_to_scalar(b.cell.x, b.cell.y)); - // Finally, let all tiles do any custom init behavior... but backwards, to match actor - // order - // FIXME very much need an on_begin that's run at the start of the first tic for stuff like - // force floors and bombs + // Finally, let all tiles do custom init behavior... but backwards, to match actor order for (let i = this.linear_cells.length - 1; i >= 0; i--) { let cell = this.linear_cells[i]; for (let tile of cell) { @@ -691,6 +689,26 @@ export class Level extends LevelInterface { // FIXME a whole bunch of these comments are gonna be wrong or confusing now begin_tic(p1_input) { + // At the beginning of the very first tic, some tiles want to do initialization that's not + // appropriate to do before the game begins. (For example, bombs blow up anything that + // starts on them in CC2, but we don't want to do that before the game has run at all. We + // DEFINITELY don't want to blow the PLAYER up before the game starts!) + if (! this.done_on_begin) { + // Run backwards, to match actor order + for (let i = this.linear_cells.length - 1; i >= 0; i--) { + let cell = this.linear_cells[i]; + for (let tile of cell) { + if (tile.type.on_begin) { + tile.type.on_begin(tile, this); + } + } + } + // It's not possible to rewind to before this happened, so clear undo and permanently + // set a flag + this.pending_undo = this.create_undo_entry(); + this.done_on_begin = true; + } + if (this.undo_enabled) { // Store some current level state in the undo entry. (These will often not be modified, but // they only take a few bytes each so that's fine.) diff --git a/js/main.js b/js/main.js index f71f77d..4c24b49 100644 --- a/js/main.js +++ b/js/main.js @@ -2215,6 +2215,10 @@ const COMPAT_FLAGS = [{ key: 'cloner_tanks_react_button', label: "Blue tanks on cloners respond to blue buttons", rulesets: new Set(['steam-strict']), +}, { + key: 'no_immediate_detonate_bombs', + label: "Don't immediately detonate populated mines", + rulesets: new Set(['lynx', 'ms']), }, { // XXX this is goofy key: 'tiles_react_instantly', diff --git a/js/tiletypes.js b/js/tiletypes.js index 48c17cc..c164ea2 100644 --- a/js/tiletypes.js +++ b/js/tiletypes.js @@ -5,7 +5,7 @@ function activate_me(me, level) { me.type.activate(me, level); } -function on_ready_force_floor(me, level) { +function on_begin_force_floor(me, level) { // At the start of the level, if there's an actor on a force floor: // - use on_arrive to set the actor's direction // - set the slide_mode (normally done by the main game loop) @@ -748,7 +748,7 @@ const TILE_TYPES = { draw_layer: DRAW_LAYERS.terrain, slide_mode: 'force', speed_factor: 2, - on_ready: on_ready_force_floor, + on_begin: on_begin_force_floor, on_arrive(me, level, other) { level.set_actor_direction(other, 'north'); }, @@ -771,7 +771,7 @@ const TILE_TYPES = { draw_layer: DRAW_LAYERS.terrain, slide_mode: 'force', speed_factor: 2, - on_ready: on_ready_force_floor, + on_begin: on_begin_force_floor, on_arrive(me, level, other) { level.set_actor_direction(other, 'east'); }, @@ -792,7 +792,7 @@ const TILE_TYPES = { draw_layer: DRAW_LAYERS.terrain, slide_mode: 'force', speed_factor: 2, - on_ready: on_ready_force_floor, + on_begin: on_begin_force_floor, on_arrive(me, level, other) { level.set_actor_direction(other, 'south'); }, @@ -813,7 +813,7 @@ const TILE_TYPES = { draw_layer: DRAW_LAYERS.terrain, slide_mode: 'force', speed_factor: 2, - on_ready: on_ready_force_floor, + on_begin: on_begin_force_floor, on_arrive(me, level, other) { level.set_actor_direction(other, 'west'); }, @@ -834,7 +834,7 @@ const TILE_TYPES = { draw_layer: DRAW_LAYERS.terrain, slide_mode: 'force', speed_factor: 2, - on_ready: on_ready_force_floor, + on_begin: on_begin_force_floor, // TODO ms: this is random, and an acting wall to monsters (!) on_arrive(me, level, other) { level.set_actor_direction(other, level.get_force_floor_direction()); @@ -861,10 +861,15 @@ const TILE_TYPES = { }, bomb: { draw_layer: DRAW_LAYERS.item, - 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? or use on_tic, like flame jets? + on_begin(me, level) { + if (level.compat.no_immediate_detonate_bombs) + return; + + // In CC2, actors on a bomb (but not a green one) are immediately blown up + let actor = me.cell.get_actor(); + if (actor && ! actor.ignores(this.name)) { + this.on_arrive(me, level, actor); + } }, on_arrive(me, level, other) { level.remove_tile(me);