From ec4113996084ad080be81ddc22e4104c5202e921 Mon Sep 17 00:00:00 2001 From: "Eevee (Evelyn Woods)" Date: Mon, 14 Sep 2020 16:03:35 -0600 Subject: [PATCH] Stub out enough to get CC2 Lesson 4 loading - Gender signs: implemented - Transmogrifier: basically implemented - Yellow tank: basically implemented - Directional blocks: load but don't draw or behave correctly - Floor mimic: moves at hyperspeed - Secret eye: no effect --- js/format-c2m.js | 37 ++++++++++---- js/tileset.js | 11 ++-- js/tiletypes.js | 130 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 164 insertions(+), 14 deletions(-) diff --git a/js/format-c2m.js b/js/format-c2m.js index d38ec81..51b9e93 100644 --- a/js/format-c2m.js +++ b/js/format-c2m.js @@ -133,7 +133,7 @@ const TILE_ENCODING = { //0x41: Open trap (unused in main levels) : 0x42: 'trap', 0x43: 'cloner', - //0x44: Clone machine : Modifier required, see below + 0x44: ['#mod8', 'cloner'], 0x45: 'hint', 0x46: 'force_floor_all', // 0x47: 'button_gray', @@ -143,7 +143,7 @@ const TILE_ENCODING = { 0x4b: ['swivel_se', 'swivel_floor'], 0x4c: ['stopwatch_bonus', '#next'], 0x4d: ['stopwatch_toggle', '#next'], - // 0x4e: Transmogrifier : + 0x4e: ['transmogrifier'], // 0x4f: Railroad track (Modifier required, see section below) : 0x50: ['steel'], 0x51: ['dynamite', '#next'], @@ -152,16 +152,16 @@ const TILE_ENCODING = { // 0x57: Timid teeth : '#direction', '#next' // 0x58: Explosion animation (unused in main levels) : '#direction', '#next' 0x59: ['hiking_boots', '#next'], - // 0x5a: Male-only sign : - // 0x5b: Female-only sign : + 0x5a: ['no_player2_sign'], + 0x5b: ['no_player1_sign'], // 0x5c: Inverter gate (N) : Modifier allows other gates, see below // 0x5e: Logic switch (ON) : 0x5f: 'flame_jet_off', 0x60: 'flame_jet_on', 0x61: 'button_orange', // 0x62: Lightning bolt : '#next' - // 0x63: Yellow tank : '#direction', '#next' - // 0x64: Yellow tank button : + 0x63: ['tank_yellow', '#direction', '#next'], + 0x64: 'button_yellow', // 0x65: Mirror Chip : '#direction', '#next' // 0x66: Mirror Melinda : '#direction', '#next' // 0x68: Bowling ball : '#next' @@ -184,8 +184,8 @@ const TILE_ENCODING = { 0x7e: ['popdown_floor'], 0x7f: ['forbidden', '#next'], 0x80: ['score_2x', '#next'], - // 0x81: Directional block : '#direction', Directional Arrows Bitmask, '#next' - // 0x82: Floor mimic : '#direction', '#next' + 0x81: ['directional_block', '#direction', '#directional_block_mask', '#next'], + 0x82: ['floor_mimic', '#direction', '#next'], 0x83: ['green_bomb', '#next'], 0x84: ['green_chip', '#next'], // 0x87: Black button : @@ -195,7 +195,7 @@ const TILE_ENCODING = { // 0x8b: Ghost : '#direction', '#next' // 0x8c: Steel foil : '#next' 0x8d: 'turtle', - // 0x8e: Secret eye : '#next' + 0x8e: ['xray_eye', '#next'], // 0x8f: Thief bribe : '#next' // 0x90: Speed boots : '#next' // 0x92: Hook : '#next' @@ -476,6 +476,25 @@ export function parse_level(buf) { else if (arg === '#next') { has_next = true; } + else if (arg === '#directional_block_mask') { + // Direction mask used specifically for the directional block + let mask = bytes[p]; + p++; + let arrows = new Set; + if (mask & 0x01) { + arrows.add('north'); + } + if (mask & 0x02) { + arrows.add('east'); + } + if (mask & 0x04) { + arrows.add('south'); + } + if (mask & 0x08) { + arrows.add('west'); + } + tile.directional_block_arrows = arrows; + } else { // Anything else is an implicit next tile, e.g. // turtles imply water underneath diff --git a/js/tileset.js b/js/tileset.js index 89fd60b..e805407 100644 --- a/js/tileset.js +++ b/js/tileset.js @@ -90,7 +90,8 @@ export const CC2_TILESET_LAYOUT = { popdown_floor: [12, 5], popdown_floor_visible: [13, 5], forbidden: [14, 5], - // directional block frame, i think? + // TODO arrows overlay at [3, 10] + directional_block: [15, 5], flippers: [0, 6], fire_boots: [1, 6], @@ -215,7 +216,7 @@ export const CC2_TILESET_LAYOUT = { blob: [0, 15], // TODO blob animations also span multiple tiles // TODO [0, 16] some kinda red/blue outline - mimic: [14, 16], + floor_mimic: [0, 2], // TODO [14, 16] with xray // TODO [15, 16] some kinda yellow/black outline // timid teeth @@ -228,7 +229,7 @@ export const CC2_TILESET_LAYOUT = { }, // TODO saucer, has layers and moves and stuff - eyeball: [11, 18], + xray_eye: [11, 18], ghost: { north: [12, 18], east: [13, 18], @@ -242,7 +243,7 @@ export const CC2_TILESET_LAYOUT = { force_floor_w: [[2, 20], [3, 20]], teleport_green: [[4, 19], [5, 19], [6, 19], [7, 19]], teleport_yellow: [[8, 19], [9, 19], [10, 19], [11, 19]], - // TODO round, thing, not sure what + transmogrifier: [[12, 19], [13, 19], [14, 19], [15, 19]], teleport_red: [[4, 20], [5, 20], [6, 20], [7, 20]], slime: [[8, 20], [9, 20], [10, 20], [11, 20], [12, 20], [13, 20], [14, 20], [15, 20]], @@ -300,6 +301,8 @@ export const CC2_TILESET_LAYOUT = { // train tracks, which are layered... dirt: [4, 31], + no_player2_sign: [5, 31], + no_player1_sign: [6, 31], // misc other stuff }; diff --git a/js/tiletypes.js b/js/tiletypes.js index 5e2fe65..06fba6e 100644 --- a/js/tiletypes.js +++ b/js/tiletypes.js @@ -7,6 +7,7 @@ const LAYER_ACTOR = 2; const LAYER_OVERLAY = 3; // TODO cc2 order is: swivel, thinwalls, canopy (and yes you can have them all in the same tile) +// TODO get rid of mentions of 'modifier' here, put them in the c2m loader const TILE_TYPES = { // Floors and walls floor: { @@ -111,6 +112,7 @@ const TILE_TYPES = { }, popdown_floor: { draw_layer: LAYER_TERRAIN, + blocks_blocks: true, // FIXME should be on_approach on_arrive(me, level, other) { // FIXME could probably do this with state? or, eh @@ -119,11 +121,25 @@ const TILE_TYPES = { }, popdown_floor_visible: { draw_layer: LAYER_TERRAIN, + blocks_blocks: true, on_depart(me, level, other) { // FIXME possibly changes back too fast, not even visible for a tic for me (much like stepping on a button oops) level.transmute_tile(me, 'popdown_floor'); }, }, + // TODO these also block the corresponding mirror actors + no_player1_sign: { + draw_layer: LAYER_TERRAIN, + blocks(me, level, other) { + return (other.type.name === 'player'); + }, + }, + no_player2_sign: { + draw_layer: LAYER_TERRAIN, + blocks(me, level, other) { + return (other.type.name === 'player2'); + }, + }, steel: { draw_layer: LAYER_TERRAIN, blocks_all: true, @@ -482,6 +498,28 @@ const TILE_TYPES = { movement_speed: 4, pushes: { ice_block: true, + directional_block: true, + }, + }, + directional_block: { + // TODO directional, obviously + // TODO floor in water + // TODO destroyed in fire, flame jet, slime + // TODO rotate on train tracks + draw_layer: LAYER_ACTOR, + blocks_all: true, + is_actor: true, + is_block: true, + load(me, template) { + me.arrows = template.directional_block_arrows; + }, + ignores: new Set(['fire']), + movement_speed: 4, + pushes: { + dirt_block: true, + clone_block: true, + ice_block: true, + directional_block: true, }, }, green_floor: { @@ -519,7 +557,12 @@ const TILE_TYPES = { }, cloner: { draw_layer: LAYER_TERRAIN, + // TODO not the case for an empty one in cc2, apparently blocks_all: true, + load(me, template) { + // FIXME not actually right, this is a bitmask + me.clone_direction = template.modifier; + }, activate(me, level) { let cell = me.cell; // Copy, so we don't end up repeatedly cloning the same object @@ -554,6 +597,44 @@ const TILE_TYPES = { } }, }, + transmogrifier: { + draw_layer: LAYER_TERRAIN, + _mogrifications: { + player: 'player2', + player2: 'player', + // TODO mirror players too + + dirt_block: 'ice_block', + clone_block: 'ice_block', + ice_block: 'dirt_block', + + ball: 'walker', + walker: 'ball', + + fireball: 'bug', + bug: 'glider', + glider: 'paramecium', + paramecium: 'fireball', + + tank_blue: 'tank_yellow', + tank_yellow: 'tank_blue', + + // TODO teeth, timid teeth + }, + _blob_mogrifications: ['ball', 'walker', 'fireball', 'glider', 'paramecium', 'bug', 'tank_blue', 'teeth', /* TODO 'timid_teeth' */ ], + // TODO can be wired, in which case only works when powered; other minor concerns, see wiki + on_arrive(me, level, other) { + let name = other.type.name; + if (me.type._mogrifications[name]) { + level.transmute_tile(other, me.type._mogrifications[name]); + } + else if (name === 'blob') { + // TODO how is this randomness determined? important for replays! + let options = me.type._blob_mogrifications; + level.transmute_tile(other, options[Math.floor(Math.random() * options.length)]); + } + }, + }, teleport_blue: { draw_layer: LAYER_TERRAIN, connects_to: 'teleport_blue', @@ -592,7 +673,7 @@ const TILE_TYPES = { button_blue: { draw_layer: LAYER_TERRAIN, on_arrive(me, level, other) { - // Flip direction of all tanks + // Flip direction of all blue tanks for (let actor of level.actors) { // TODO generify somehow?? if (actor.type.name === 'tank_blue') { @@ -601,6 +682,19 @@ const TILE_TYPES = { } }, }, + button_yellow: { + draw_layer: LAYER_TERRAIN, + on_arrive(me, level, other) { + // Move all yellow tanks one tile in the direction of the pressing actor + for (let actor of level.actors) { + // TODO generify somehow?? + if (actor.type.name === 'tank_yellow') { + level.set_actor_direction(actor, other.direction); + level.attempt_step(actor, other.direction); + } + } + }, + }, button_green: { draw_layer: LAYER_TERRAIN, on_arrive(me, level, other) { @@ -753,6 +847,20 @@ const TILE_TYPES = { movement_mode: 'forward', movement_speed: 4, }, + tank_yellow: { + draw_layer: LAYER_ACTOR, + is_actor: true, + is_monster: true, + blocks_monsters: true, + blocks_blocks: true, + pushes: { + dirt_block: true, + clone_block: true, + ice_block: true, + directional_block: true, + }, + movement_speed: 4, + }, blob: { draw_layer: LAYER_ACTOR, is_actor: true, @@ -792,6 +900,17 @@ const TILE_TYPES = { movement_speed: 4, ignores: new Set(['water']), }, + floor_mimic: { + draw_layer: LAYER_ACTOR, + is_actor: true, + is_monster: true, + blocks_monsters: true, + blocks_blocks: true, + // TODO not like teeth; always pursues + // TODO takes 3 turns off! + movement_mode: 'pursue', + movement_speed: 4, + }, // Keys // Note that red and blue keys do NOT block monsters, but yellow and green DO @@ -876,6 +995,13 @@ const TILE_TYPES = { blocks_blocks: true, // FIXME does a thing when dropped, but that isn't implemented at all yet }, + xray_eye: { + draw_layer: LAYER_ITEM, + is_item: true, + is_tool: true, + blocks_monsters: true, + blocks_blocks: true, + }, // Progression player: { @@ -888,6 +1014,7 @@ const TILE_TYPES = { dirt_block: true, clone_block: true, ice_block: true, + directional_block: true, }, infinite_items: { key_green: true, @@ -904,6 +1031,7 @@ const TILE_TYPES = { dirt_block: true, clone_block: true, ice_block: true, + directional_block: true, }, infinite_items: { key_yellow: true,