From 9b76c6b9ce39d6b3e2152309d1c99f76488204c7 Mon Sep 17 00:00:00 2001 From: Timothy Stiles Date: Fri, 5 Feb 2021 14:41:11 +1100 Subject: [PATCH] implement the Terraformer The Terraformer is like a clone machine for everything that isn't an actor. It copies the terrain (and item) behind it to in front of it when powered. --- js/main-editor.js | 13 +++++- js/tileset.js | 6 +++ js/tiletypes.js | 117 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+), 1 deletion(-) diff --git a/js/main-editor.js b/js/main-editor.js index 2e7548f..abe472f 100644 --- a/js/main-editor.js +++ b/js/main-editor.js @@ -1598,6 +1598,8 @@ const EDITOR_PALETTE = [{ 'gate_yellow', 'gate_green', 'sand', + 'terraformer_n', + 'global_cycler', ], }]; @@ -2171,7 +2173,15 @@ const EDITOR_TILE_DESCRIPTIONS = { sand: { name: "Sand", desc: "Anything walking on it moves at half speed. Stops all blocks.", - } + }, + terraformer_n: { + name: "Terraformer", + desc: "When activated, copies the terrain and item behind it to the tile in front of it.", + }, + global_cycler: { + name: "Global Cycler", + desc: "When activated, every terrain/item on the surrounding four tiles in the entire level becomes the terrain/item one clockwise.", + }, }; const SPECIAL_PALETTE_ENTRIES = { @@ -2418,6 +2428,7 @@ for (let cycle of [ ['force_floor_n', 'force_floor_e', 'force_floor_s', 'force_floor_w'], ['ice_nw', 'ice_ne', 'ice_se', 'ice_sw'], ['swivel_nw', 'swivel_ne', 'swivel_se', 'swivel_sw'], + ['terraformer_n', 'terraformer_e', 'terraformer_s', 'terraformer_w'], ]) { for (let [i, name] of cycle.entries()) { let left = cycle[(i - 1 + cycle.length) % cycle.length]; diff --git a/js/tileset.js b/js/tileset.js index 87c28c6..71c819b 100644 --- a/js/tileset.js +++ b/js/tileset.js @@ -1031,6 +1031,12 @@ export const LL_TILESET_LAYOUT = Object.assign({}, CC2_TILESET_LAYOUT, { skeleton_key: [4, 40], sand: [10, 41], + terraformer_n: [0, 43], + terraformer_e: [1, 43], + terraformer_s: [2, 43], + terraformer_w: [3, 43], + global_cycler: [4, 43], + }); export const TILESET_LAYOUTS = { diff --git a/js/tiletypes.js b/js/tiletypes.js index 72ae140..8ac7625 100644 --- a/js/tiletypes.js +++ b/js/tiletypes.js @@ -89,6 +89,67 @@ function _define_gate(key) { }; } +function activate_terraformer(me, level, dx, dy) { + let did_something = false; + let old_cell = level.cell( + (me.cell.x - dx + level.width) % level.width, + (me.cell.y - dy + level.height) % level.height); + let new_cell = level.cell( + (me.cell.x + dx + level.width) % level.width, + (me.cell.y + dy + level.height) % level.height); + let old_terrain = old_cell.get_terrain(); + let new_terrain = new_cell.get_terrain(); + if (old_terrain.type.name != new_terrain.type.name) + { + level.transmute_tile(new_cell.get_terrain(), old_terrain.type.name); + did_something = true; + } + let old_item = old_cell.get_item(); + if (old_item != null) + { + let new_item = new_cell.get_item(); + if (new_item != null) + { + if (old_item.type.name != new_item.type.name) + { + level.transmute_tile(new_item, old_item.type.name) + did_something = true; + } + } + else + { + let type = TILE_TYPES[old_item.type.name]; + let tile = new old_item.constructor(type); + level.add_tile(tile, new_cell); + did_something = true; + } + } + let old_item_mod = old_cell.get_item_mod(); + if (old_item_mod != null) + { + let new_item_mod = new_cell.get_item_mod(); + if (new_item_mod != null) + { + if (old_item_mod.type.name != new_item_mod.type.name) + { + level.transmute_tile(new_item_mod, old_item_mod.type.name) + did_something = true; + } + } + else + { + let type = TILE_TYPES[old_item_mod.type.name]; + let tile = new old_item_mod.constructor(type); + level.add_tile(tile, new_cell); + did_something = true; + } + } + if (did_something) + { + level.spawn_animation(new_cell, 'transmogrify_flash'); + } +} + function player_visual_state(me) { if (! me) { return 'normal'; @@ -1511,6 +1572,62 @@ const TILE_TYPES = { } }, }, + terraformer_n: { + layer: LAYERS.terrain, + blocks_collision: COLLISION.real_player | COLLISION.block_cc1 | COLLISION.monster_solid, + activate(me, level) { + activate_terraformer(me, level, 0, -1); + }, + // Also terraforms on rising pulse or gray button + on_power(me, level) { + me.type.activate(me, level); + }, + on_gray_button(me, level) { + me.type.activate(me, level); + }, + }, + terraformer_e: { + layer: LAYERS.terrain, + blocks_collision: COLLISION.real_player | COLLISION.block_cc1 | COLLISION.monster_solid, + activate(me, level) { + activate_terraformer(me, level, 1, 0); + }, + // Also terraforms on rising pulse or gray button + on_power(me, level) { + me.type.activate(me, level); + }, + on_gray_button(me, level) { + me.type.activate(me, level); + }, + }, + terraformer_s: { + layer: LAYERS.terrain, + blocks_collision: COLLISION.real_player | COLLISION.block_cc1 | COLLISION.monster_solid, + activate(me, level) { + activate_terraformer(me, level, 0, 1); + }, + // Also terraforms on rising pulse or gray button + on_power(me, level) { + me.type.activate(me, level); + }, + on_gray_button(me, level) { + me.type.activate(me, level); + }, + }, + terraformer_w: { + layer: LAYERS.terrain, + blocks_collision: COLLISION.real_player | COLLISION.block_cc1 | COLLISION.monster_solid, + activate(me, level) { + activate_terraformer(me, level, -1, 0); + }, + // Also terraforms on rising pulse or gray button + on_power(me, level) { + me.type.activate(me, level); + }, + on_gray_button(me, level) { + me.type.activate(me, level); + }, + }, // Buttons button_blue: { layer: LAYERS.terrain,