Implement "hide logic", and actually save options (fixes #52)

This commit is contained in:
Eevee (Evelyn Woods) 2021-03-08 21:04:23 -07:00
parent 028fc016b0
commit dd10236b22
6 changed files with 49 additions and 15 deletions

View File

@ -113,6 +113,7 @@ export class StoredLevel extends LevelInterface {
// 1 - 4 patterns (default; PRNG + rotating through 0-3)
// 2 - extra random (like deterministic, but initial seed is "actually" random)
this.blob_behavior = 1;
this.hide_logic = false;
// Lazy-loading that allows for checking existence (see methods below)
// TODO this needs a better interface, these get accessed too much atm

View File

@ -1130,11 +1130,11 @@ export function parse_level(buf, number = 1) {
if (view.byteLength <= 22)
continue;
//options.hide_logic = view.getUint8(22, true);
level.hide_logic = !! view.getUint8(22, true);
if (view.byteLength <= 23)
continue;
level.use_cc1_boots = view.getUint8(23, true);
level.use_cc1_boots = !! view.getUint8(23, true);
if (view.byteLength <= 24)
continue;
@ -1482,17 +1482,32 @@ export function synthesize_level(stored_level) {
}
// Options block
let options = new Uint8Array(3);
let options = new Uint8Array(25); // max possible size
let options_length = 0;
new DataView(options.buffer).setUint16(0, stored_level.time_limit, true);
if (stored_level.viewport_size === 10) {
options[2] = 0;
}
else if (stored_level.viewport_size === 9) {
options[2] = 1;
options_length = 3;
}
if (stored_level.hide_logic) {
options[22] = 1;
options_length = 23;
}
if (stored_level.use_cc1_boots) {
options[23] = 1;
options_length = 24;
}
if (stored_level.blob_behavior !== 0) {
options[24] = stored_level.blob_behavior;
options_length = 25;
}
// TODO split
// TODO for size purposes, omit the block entirely if all options are defaults?
c2m.add_section('OPTN', options);
if (options_length > 0) {
c2m.add_section('OPTN', options.slice(0, options_length));
}
// Store camera regions
// TODO LL feature, should be distinguished somehow

View File

@ -141,17 +141,24 @@ class EditorLevelMetaOverlay extends DialogOverlay {
mk('br'),
mk('label',
mk('input', {name: 'blob_behavior', type: 'radio', value: '1'}),
" 4 patterns (default; PRNG + rotating offset)"),
" 4 patterns (CC2 default; PRNG + rotating offset)"),
mk('br'),
mk('label',
mk('input', {name: 'blob_behavior', type: 'radio', value: '2'}),
" Extra random (initial seed is truly random)"),
" Extra random (LL default; initial seed is truly random)"),
),
mk('dt', "Options"),
mk('dd', mk('label',
mk('input', {name: 'hide_logic', type: 'checkbox'}),
" Hide wires and logic gates (warning: CC2 also hides pink/black buttons!)")),
mk('dd', mk('label',
mk('input', {name: 'use_cc1_boots', type: 'checkbox'}),
" Use CC1-style inventory (can only pick up the four classic boots; can't drop or cycle)")),
);
this.root.elements['viewport'].value = stored_level.viewport_size;
// FIXME this isn't actually saved lol but also it's 24 bytes into the damn options. also
// it should default to 2, the good one
this.root.elements['blob_behavior'].value = stored_level.blob_behavior;
this.root.elements['hide_logic'].checked = stored_level.hide_logic;
this.root.elements['use_cc1_boots'].checked = stored_level.use_cc1_boots;
// TODO:
// - chips?
// - password???
@ -183,6 +190,8 @@ class EditorLevelMetaOverlay extends DialogOverlay {
}
stored_level.blob_behavior = parseInt(els.blob_behavior.value, 10);
stored_level.hide_logic = els.hide_logic.checked;
stored_level.use_cc1_boots = els.use_cc1_boots.checked;
stored_level.viewport_size = parseInt(els.viewport.value, 10);
this.conductor.player.update_viewport_size();
@ -3212,6 +3221,7 @@ export class Editor extends PrimaryView {
stored_level.size_x = size_x;
stored_level.size_y = size_y;
stored_level.viewport_size = 10;
stored_level.blob_behavior = 2; // extra random
for (let i = 0; i < size_x * size_y; i++) {
stored_level.linear_cells.push(this.make_blank_cell(...stored_level.scalar_to_coords(i)));
}

View File

@ -1334,6 +1334,8 @@ class Player extends PrimaryView {
// (This happens here because we could technically still do 20tps if we wanted, and the
// renderer doesn't actually have any way to know that)
this.renderer.update_rate = this.level.update_rate;
// Likewise, we don't want this automatically read from the level, but we do respect it here
this.renderer.hide_logic = this.level.stored_level.hide_logic;
this.update_ui();
// Force a redraw, which won't happen on its own since the game isn't running

View File

@ -5,7 +5,7 @@ import TILE_TYPES from './tiletypes.js';
class CanvasRendererDrawPacket extends DrawPacket {
constructor(renderer, ctx, perception, clock, update_progress, update_rate) {
super(perception, clock, update_progress, update_rate);
super(perception, renderer.hide_logic, clock, update_progress, update_rate);
this.renderer = renderer;
this.ctx = ctx;
// Canvas position of the cell being drawn
@ -62,6 +62,7 @@ export class CanvasRenderer {
this.show_actor_order = false;
this.use_rewind_effect = false;
this.perception = 'normal'; // normal, xray, editor, palette
this.hide_logic = false;
this.update_rate = 3;
this.use_cc2_anim_speed = false;
this.active_player = null;

View File

@ -1994,8 +1994,9 @@ export const TILESET_LAYOUTS = {
// Bundle of arguments for drawing a tile, containing some standard state about the game
export class DrawPacket {
constructor(perception = 'normal', clock = 0, update_progress = 0, update_rate = 3) {
constructor(perception = 'normal', hide_logic = false, clock = 0, update_progress = 0, update_rate = 3) {
this.perception = perception;
this.hide_logic = hide_logic && perception === 'normal';
this.use_cc2_anim_speed = false;
this.clock = clock;
this.update_progress = update_progress;
@ -2177,7 +2178,7 @@ export class Tileset {
let wire_radius = this.layout['#wire-width'] / 2;
// TODO circuit block with a lightning bolt is always powered
// TODO circuit block in motion doesn't inherit cell's power
if (tile && tile.wire_directions) {
if (tile && tile.wire_directions && ! packet.hide_logic) {
// Draw the base tile
packet.blit(drawspec.base[0], drawspec.base[1]);
@ -2210,9 +2211,8 @@ export class Tileset {
}
}
// Wired tiles may also have tunnels, drawn on top of everything else
if (tile && tile.wire_tunnel_directions) {
if (tile && tile.wire_tunnel_directions && ! packet.hide_logic) {
let tunnel_coords = this.layout['#wire-tunnel'];
let tunnel_width = 6/32;
let tunnel_length = 12/32;
@ -2602,7 +2602,12 @@ export class Tileset {
}
}
else if (drawspec.__special__ === 'logic-gate') {
this._draw_logic_gate(drawspec, name, tile, packet);
if (packet.hide_logic) {
this.draw_type('floor', tile, packet);
}
else {
this._draw_logic_gate(drawspec, name, tile, packet);
}
}
else if (drawspec.__special__ === 'railroad') {
this._draw_railroad(drawspec, name, tile, packet);