diff --git a/js/format-c2g.js b/js/format-c2g.js index 8148f29..50dce51 100644 --- a/js/format-c2g.js +++ b/js/format-c2g.js @@ -799,6 +799,66 @@ const TILE_ENCODING = { extra_args: [arg_direction], is_extension: true, }, + 0xe2: { + name: 'skeleton_key', + has_next: true, + is_extension: true, + }, + 0xe2: { + name: 'gate_red', + has_next: true, + is_extension: true, + }, + 0xe3: { + name: 'gate_blue', + has_next: true, + is_extension: true, + }, + 0xe4: { + name: 'gate_yellow', + has_next: true, + is_extension: true, + }, + 0xe5: { + name: 'gate_green', + has_next: true, + is_extension: true, + }, + 0xe6: { + name: 'sand', + has_next: true, + is_extension: true, + }, + 0xe7: { + name: 'terraformer_n', + has_next: true, + is_extension: true, + }, + 0xe8: { + name: 'terraformer_e', + has_next: true, + is_extension: true, + }, + 0xe9: { + name: 'terraformer_s', + has_next: true, + is_extension: true, + }, + 0xea: { + name: 'terraformer_w', + has_next: true, + is_extension: true, + }, + 0xeb: { + name: 'global_cycler', + has_next: true, + is_extension: true, + }, + 0xec: { + name: 'halo', + has_next: true, + is_extension: true, + }, }; const REVERSE_TILE_ENCODING = {}; for (let [tile_byte, spec] of Object.entries(TILE_ENCODING)) { diff --git a/js/game.js b/js/game.js index 4235bd7..a260817 100644 --- a/js/game.js +++ b/js/game.js @@ -1600,15 +1600,15 @@ export class Level extends LevelInterface { // Helmet disables this, do nothing } else if (actor.type.is_real_player && tile.type.is_monster) { - this.fail(tile.type.name, actor); + this.fail(tile.type.name, tile, actor); } else if (actor.type.is_monster && tile.type.is_real_player) { - this.fail(actor.type.name, tile); + this.fail(actor.type.name, actor, tile); } else if (actor.type.is_block && tile.type.is_real_player && ! actor.is_pulled) { // Note that blocks squish players if they move for ANY reason, even if pushed by // another player! The only exception is being pulled - this.fail('squished', tile); + this.fail('squished', actor, tile); } if (tile.type.on_approach) { @@ -1641,7 +1641,7 @@ export class Level extends LevelInterface { this.player.movement_cooldown === this.player.movement_speed && ! actor.has_item('helmet') && ! this.player.has_item('helmet')) { - this.fail(actor.type.name); + this.fail(actor.type.name, actor, this.player); } if (this.compat.tiles_react_instantly) { @@ -2264,7 +2264,7 @@ export class Level extends LevelInterface { } } - fail(reason, player = null) { + fail(reason, killer = null, player = null) { if (this.state !== 'playing') return; @@ -2278,6 +2278,26 @@ export class Level extends LevelInterface { if (player === null) { player = this.player; } + + if (this.take_tool_from_actor(player, 'halo')) { + //play sound? + if (reason === 'time') + { + this.pause_timer(); + } + else if (killer !== null) + { + if (killer.type.is_actor || killer.type.is_item) + { + this.remove_tile(killer); + } + else //presumably terrain + { + this.transmute_tile(killer, 'floor'); + } + } + return; + } this._push_pending_undo(() => { this.fail_reason = null; diff --git a/js/main-editor.js b/js/main-editor.js index 74d909d..068ab6a 100644 --- a/js/main-editor.js +++ b/js/main-editor.js @@ -1600,6 +1600,7 @@ const EDITOR_PALETTE = [{ 'sand', 'terraformer_n', 'global_cycler', + 'halo', ], }]; @@ -2182,6 +2183,10 @@ const EDITOR_TILE_DESCRIPTIONS = { name: "Global Cycler", desc: "When activated, every terrain/item on the surrounding four tiles in the entire level becomes the terrain/item one clockwise. Adjacent tiles with a 'no sign' on them are ignored. Two of the same tile in a row mean that tile will not be transformed and will stay as-is. Tiles next to Global Cyclers are not transformed.", }, + halo: { + name: "Halo", + desc: "Protects the player from death once, destroying the would-be killer in the process.", + }, }; const SPECIAL_PALETTE_ENTRIES = { diff --git a/js/tileset.js b/js/tileset.js index 71c819b..6bffb4e 100644 --- a/js/tileset.js +++ b/js/tileset.js @@ -1036,6 +1036,7 @@ export const LL_TILESET_LAYOUT = Object.assign({}, CC2_TILESET_LAYOUT, { terraformer_s: [2, 43], terraformer_w: [3, 43], global_cycler: [4, 43], + halo: [5, 43], }); diff --git a/js/tiletypes.js b/js/tiletypes.js index 764ea07..dd287e4 100644 --- a/js/tiletypes.js +++ b/js/tiletypes.js @@ -702,7 +702,7 @@ const TILE_TYPES = { level.sfx.play_once('splash', me.cell); } else if (other.type.is_real_player) { - level.fail('burned', other); + level.fail('burned', me, other); } else { level.transmute_tile(other, 'explosion'); @@ -733,7 +733,7 @@ const TILE_TYPES = { level.transmute_tile(me, 'ice'); } else if (other.type.is_real_player) { - level.fail('drowned', other); + level.fail('drowned', me, other); } else { level.transmute_tile(other, 'splash'); @@ -923,7 +923,7 @@ const TILE_TYPES = { level.transmute_tile(me, 'floor'); } else if (other.type.is_real_player) { - level.fail('slimed', other); + level.fail('slimed', me, other); } else { level.transmute_tile(other, 'splash_slime'); @@ -947,7 +947,7 @@ const TILE_TYPES = { on_arrive(me, level, other) { level.remove_tile(me); if (other.type.is_real_player) { - level.fail('exploded', other); + level.fail('exploded', me, other); } else { level.sfx.play_once('bomb', me.cell); @@ -1148,7 +1148,7 @@ const TILE_TYPES = { on_arrive(me, level, other) { level.remove_tile(me); if (other.type.is_real_player) { - level.fail('exploded', other); + level.fail('exploded', me, other); } else { level.sfx.play_once('bomb', me.cell); @@ -1563,7 +1563,7 @@ const TILE_TYPES = { // 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', actor); + level.fail('burned', me, actor); } else { level.sfx.play_once('bomb', me.cell); @@ -2573,7 +2573,7 @@ const TILE_TYPES = { else if (tile.type.is_real_player) { // TODO it would be nice if i didn't have to special-case this every // time - level.fail(me.type.name, tile); + level.fail(me.type.name, me, tile); } else { // Everything else is destroyed @@ -2650,7 +2650,7 @@ const TILE_TYPES = { if (me.cell.has('cloner')) return; if (other.type.is_real_player) { - level.fail(me.type.name, other); + level.fail(me.type.name, me, other); } else { level.transmute_tile(other, 'explosion'); @@ -2662,7 +2662,7 @@ const TILE_TYPES = { // Blow up anything we run into if (obstacle && obstacle.type.is_actor) { if (obstacle.type.is_real_player) { - level.fail(me.type.name, obstacle); + level.fail(me.type.name, me, obstacle); } else { level.transmute_tile(obstacle, 'explosion'); @@ -2734,6 +2734,12 @@ const TILE_TYPES = { is_tool: true, blocks_collision: COLLISION.block_cc1 | (COLLISION.monster_solid & ~COLLISION.rover), }, + halo: { + layer: LAYERS.item, + is_item: true, + is_tool: true, + blocks_collision: COLLISION.block_cc1 | (COLLISION.monster_solid & ~COLLISION.rover), + }, // Progression player: { diff --git a/tileset-lexy.png b/tileset-lexy.png index 7580b4f..c1d72c5 100644 Binary files a/tileset-lexy.png and b/tileset-lexy.png differ