diff --git a/js/format-c2g.js b/js/format-c2g.js index 1701498..29e6a78 100644 --- a/js/format-c2g.js +++ b/js/format-c2g.js @@ -895,7 +895,7 @@ const TILE_ENCODING = { is_extension: true, }, 0xed: { - name: 'halo', + name: 'ankh', has_next: true, is_extension: true, }, diff --git a/js/game.js b/js/game.js index 49e2d7c..0d69e59 100644 --- a/js/game.js +++ b/js/game.js @@ -518,6 +518,7 @@ export class Level extends LevelInterface { let n = 0; let connectables = []; this.remaining_players = 0; + this.ankh_tile = null; // If there's exactly one yellow teleporter when the level loads, it cannot be picked up let yellow_teleporter_count = 0; this.allow_taking_yellow_teleporters = false; @@ -2507,8 +2508,17 @@ export class Level extends LevelInterface { } } - kill_actor(actor, animation_name = null) { + kill_actor(actor, killer, animation_name = null, sfx = null, fail_reason = null) { // FIXME use this everywhere, fail when it's a player, move on_death here + if (actor.type.is_real_player) { + // FIXME move death here + this.fail(fail_reason, null, actor); + return; + } + + if (sfx) { + this.sfx.play_once(sfx, actor.cell); + } if (animation_name) { this.transmute_tile(actor, animation_name); } @@ -2521,6 +2531,34 @@ export class Level extends LevelInterface { if (this.state !== 'playing') return; + if (player === null) { + player = this.player; + } + + // FIXME move to kill_actor + if (player != null && this.ankh_tile && reason !== 'time') { + let cell = this.ankh_tile.cell; + let actor = cell.get_actor(); + if (! actor) { + // FIXME water should still splash, etc + this.sfx.play_once('revive'); + + this._set_tile_prop(player, 'movement_cooldown', null); + this._set_tile_prop(player, 'movement_speed', null); + this.make_slide(player, null); + this.move_to(player, cell); + + this.transmute_tile(this.ankh_tile, 'floor'); + this.spawn_animation(cell, 'resurrection'); + let old_tile = this.ankh_tile; + this.ankh_tile = null; + this._push_pending_undo(() => { + this.ankh_tile = old_tile; + }); + return; + } + } + if (reason === 'time') { this.sfx.play_once('timeup'); } @@ -2528,33 +2566,6 @@ export class Level extends LevelInterface { this.sfx.play_once('lose'); } - if (player === null) { - player = this.player; - } - - if (player != null && this.take_tool_from_actor(player, 'halo')) { - this.sfx.play_once('revive'); - if (reason === 'time') - { - this.pause_timer(); - } - else if (killer !== null) - { - if (killer.type.is_actor || killer.type.is_item) - { - if (killer.type.on_death) { - killer.type.on_death(killer, this); - } - this.remove_tile(killer); - } - else //presumably terrain - { - this.transmute_tile(killer, 'floor'); - } - } - return; - } - this._push_pending_undo(() => { this.fail_reason = null; if (player != null) { player.fail_reason = null; } diff --git a/js/main-editor.js b/js/main-editor.js index 344d678..a776cd8 100644 --- a/js/main-editor.js +++ b/js/main-editor.js @@ -1607,7 +1607,7 @@ const EDITOR_PALETTE = [{ 'turntable_ccw', 'teleport_blue_exit', 'electrified_floor', - 'halo', + 'ankh', 'score_5x', 'boulder', 'glass_block', diff --git a/js/tileset.js b/js/tileset.js index bcfcdd9..712345e 100644 --- a/js/tileset.js +++ b/js/tileset.js @@ -1293,7 +1293,8 @@ export const LL_TILESET_LAYOUT = { xray_eye: [3, 17], helmet: [4, 17], skeleton_key: [0, 18], - halo: [1, 18], + ankh: [1, 18], + floor_ankh: [2, 18], no_sign: [6, 18], gift_bow: [7, 18], score_10: [0, 19], @@ -1418,7 +1419,7 @@ export const LL_TILESET_LAYOUT = { __special__: 'animated', duration: 12, cc2_duration: 16, - all: [[8, 21], [9, 21], [10, 21], [11, 21]], + all: [[8, 22], [9, 22], [10, 22], [11, 22]], } }, turntable_ccw: { @@ -1428,7 +1429,7 @@ export const LL_TILESET_LAYOUT = { __special__: 'animated', duration: 12, cc2_duration: 16, - all: [[8, 22], [9, 22], [10, 22], [11, 22]], + all: [[8, 21], [9, 21], [10, 21], [11, 21]], } }, flame_jet_off: [12, 21], @@ -1978,6 +1979,7 @@ export const LL_TILESET_LAYOUT = { transmogrify_flash: [[24, 26], [25, 26], [26, 26], [27, 26], [28, 26], [29, 26], [30, 26], [31, 26]], teleport_flash: [[24, 27], [25, 27], [26, 27], [27, 27]], puff: [[24, 28], [25, 28], [26, 28], [27, 28]], + resurrection: [[23, 28], [22, 28], [21, 28], [20, 28]], }; export const TILESET_LAYOUTS = { diff --git a/js/tiletypes.js b/js/tiletypes.js index 569b151..f2f8f81 100644 --- a/js/tiletypes.js +++ b/js/tiletypes.js @@ -706,7 +706,7 @@ const TILE_TYPES = { on_arrive(me, level, other) { if (other.type.name === 'glass_block') { // FIXME need a glass shatter vfx - level.kill_actor(other, 'explosion'); + level.kill_actor(other, me, 'explosion'); } }, }, @@ -770,12 +770,8 @@ const TILE_TYPES = { level.transmute_tile(me, 'water'); level.sfx.play_once('splash', me.cell); } - else if (other.type.is_real_player) { - level.fail('burned', me, other); - } else { - level.transmute_tile(other, 'explosion'); - level.sfx.play_once('bomb', me.cell); + level.kill_actor(other, me, 'explosion', 'bomb', 'burned'); } }, }, @@ -2922,8 +2918,31 @@ const TILE_TYPES = { skeleton_key: { ...COMMON_TOOL, }, - halo: { + ankh: { ...COMMON_TOOL, + on_depart(me, level, other) { + let terrain = me.cell.get_terrain(); + if (other.type.is_real_player && terrain && terrain.type.name === 'floor' && + terrain.wire_directions === 0 && terrain.wire_tunnel_directions === 0) + { + if (level.ankh_tile) { + level.transmute_tile(level.ankh_tile, 'floor'); + level.spawn_animation(level.ankh_tile, 'puff'); + } + let old_tile = level.ankh_tile; + level.ankh_tile = terrain; + level._push_pending_undo(() => { + level.ankh_tile = old_tile; + }); + level.transmute_tile(terrain, 'floor_ankh'); + // TODO some kinda vfx + sfx + level.remove_tile(me); + } + }, + }, + floor_ankh: { + layer: LAYERS.terrain, + blocks_collision: COLLISION.all_but_real_player, }, // Progression @@ -3246,6 +3265,12 @@ const TILE_TYPES = { collision_mask: 0, ttl: 4 * 3 + 1, }, + resurrection: { + layer: LAYERS.vfx, + is_actor: true, + collision_mask: 0, + ttl: 4 * 3 + 1, + }, // Invalid tiles that appear in some CCL levels because community level // designers love to make nonsense