Arrange the compat flags into categories & show compat icon in main UI
This commit is contained in:
parent
0efbefb999
commit
5a17b9022d
@ -135,7 +135,7 @@
|
|||||||
<h1><a href="https://github.com/eevee/lexys-labyrinth">Lexy's Labyrinth</a></h1>
|
<h1><a href="https://github.com/eevee/lexys-labyrinth">Lexy's Labyrinth</a></h1>
|
||||||
<p>— an <a href="https://github.com/eevee/lexys-labyrinth">open source</a> game by <a href="https://eev.ee/">eevee</a></p>
|
<p>— an <a href="https://github.com/eevee/lexys-labyrinth">open source</a> game by <a href="https://eev.ee/">eevee</a></p>
|
||||||
<nav>
|
<nav>
|
||||||
<button id="main-compat" type="button">mode: <output>lexy</output></button>
|
<button id="main-compat" type="button"><img src="icons/compat-lexy.png" alt=""> <output>lexy</output></button>
|
||||||
<button id="main-options" type="button">options</button>
|
<button id="main-options" type="button">options</button>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
340
js/defs.js
340
js/defs.js
@ -135,185 +135,193 @@ export const COMPAT_RULESET_LABELS = {
|
|||||||
};
|
};
|
||||||
export const COMPAT_RULESET_ORDER = ['lexy', 'steam', 'steam-strict', 'lynx', 'ms', 'custom'];
|
export const COMPAT_RULESET_ORDER = ['lexy', 'steam', 'steam-strict', 'lynx', 'ms', 'custom'];
|
||||||
// FIXME some of the names of the flags themselves kinda suck
|
// FIXME some of the names of the flags themselves kinda suck
|
||||||
export const COMPAT_FLAGS = [
|
// TODO some ms compat things that wouldn't be too hard to add:
|
||||||
// Level loading
|
// - walkers choose a random /unblocked/ direction, not just a random direction
|
||||||
// TODO? /strictly/ speaking, these should be turned on for lynx+ms/lynx respectively, but then i'd
|
// - (boosting) player cooldown is /zero/ after ending a slide
|
||||||
// have to also alter the behavior of the corresponding terrain, which seems kind of silly
|
// - cleats allow walking through ice corner walls while standing on them
|
||||||
{
|
// - blocks can be pushed through thin walls + ice corners
|
||||||
key: 'no_auto_convert_ccl_popwalls',
|
export const COMPAT_FLAG_CATEGORIES = [{
|
||||||
label: "Recessed walls under actors in CCL levels are left alone",
|
title: "Level loading",
|
||||||
rulesets: new Set(['steam-strict', 'lynx', 'ms']),
|
flags: [{
|
||||||
|
key: 'no_auto_convert_ccl_popwalls',
|
||||||
|
label: "Recessed walls under actors are not auto-converted in CCL levels",
|
||||||
|
rulesets: new Set(['steam-strict', 'lynx', 'ms']),
|
||||||
|
}, {
|
||||||
|
key: 'no_auto_convert_ccl_blue_walls',
|
||||||
|
label: "Blue walls under blocks are not auto-converted in CCL levels",
|
||||||
|
rulesets: new Set(['steam-strict', 'lynx', 'ms']),
|
||||||
|
}],
|
||||||
}, {
|
}, {
|
||||||
key: 'no_auto_convert_ccl_blue_walls',
|
title: "Actor behavior",
|
||||||
label: "Blue walls under blocks in CCL levels are left alone",
|
flags: [{
|
||||||
rulesets: new Set(['steam-strict', 'lynx', 'ms']),
|
key: 'emulate_60fps',
|
||||||
},
|
label: "Actors update at 60 FPS",
|
||||||
|
rulesets: new Set(['steam', 'steam-strict']),
|
||||||
// Core
|
}, {
|
||||||
{
|
key: 'no_separate_idle_phase',
|
||||||
key: 'allow_double_cooldowns',
|
label: "Actors teleport immediately after moving",
|
||||||
label: "Actors may cooldown twice in one tic",
|
rulesets: new Set(['steam', 'steam-strict']),
|
||||||
rulesets: new Set(['steam', 'steam-strict', 'lynx']),
|
}, {
|
||||||
|
key: 'allow_double_cooldowns',
|
||||||
|
label: "Actors may move forwards twice in one tic",
|
||||||
|
rulesets: new Set(['steam', 'steam-strict', 'lynx']),
|
||||||
|
}, {
|
||||||
|
key: 'player_moves_last',
|
||||||
|
label: "Players always update last",
|
||||||
|
rulesets: new Set(['lynx']),
|
||||||
|
}, {
|
||||||
|
key: 'reuse_actor_slots',
|
||||||
|
label: "New actors reuse slots in the actor list",
|
||||||
|
rulesets: new Set(['lynx']),
|
||||||
|
}, {
|
||||||
|
key: 'player_protected_by_items',
|
||||||
|
label: "Players can't be trampled while standing on items",
|
||||||
|
rulesets: new Set(['lynx']),
|
||||||
|
}, {
|
||||||
|
key: 'force_lynx_animation_lengths',
|
||||||
|
label: "Animations play at their slower Lynx duration",
|
||||||
|
rulesets: new Set(['lynx']),
|
||||||
|
}, {
|
||||||
|
// Note that this requires no_early_push as well
|
||||||
|
key: 'player_safe_at_decision_time',
|
||||||
|
label: "Players can't be trampled at decision time",
|
||||||
|
rulesets: new Set(['lynx', 'ms']),
|
||||||
|
}, {
|
||||||
|
key: 'bonking_isnt_instant',
|
||||||
|
label: "Bonking while sliding doesn't apply instantly",
|
||||||
|
rulesets: new Set(['lynx', 'ms']),
|
||||||
|
}, {
|
||||||
|
key: 'actors_move_instantly',
|
||||||
|
label: "Movement is instant",
|
||||||
|
rulesets: new Set(['ms']),
|
||||||
|
}],
|
||||||
}, {
|
}, {
|
||||||
key: 'no_separate_idle_phase',
|
title: "Monsters",
|
||||||
label: "Actors teleport immediately after moving",
|
flags: [{
|
||||||
rulesets: new Set(['steam', 'steam-strict']),
|
// TODO ms needs "player doesn't block monsters", but tbh that's kind of how it should work
|
||||||
|
// anyway, especially in combination with the ankh
|
||||||
|
// TODO? in lynx they ignore the button while in motion too
|
||||||
|
// TODO what about in a trap, in every game??
|
||||||
|
// TODO what does ms do when a tank is on ice or a ff? wiki's description is wacky
|
||||||
|
// TODO yellow tanks seem to have memory too??
|
||||||
|
key: 'tanks_always_obey_button',
|
||||||
|
label: "Blue tanks obey blue buttons even on clone machines",
|
||||||
|
rulesets: new Set(['steam-strict']),
|
||||||
|
}, {
|
||||||
|
key: 'tanks_ignore_button_while_moving',
|
||||||
|
label: "Blue tanks ignore blue buttons while moving",
|
||||||
|
rulesets: new Set(['lynx']),
|
||||||
|
}, {
|
||||||
|
key: 'blobs_use_tw_prng',
|
||||||
|
label: "Blobs use the Lynx RNG",
|
||||||
|
rulesets: new Set(['lynx']),
|
||||||
|
}, {
|
||||||
|
key: 'teeth_target_internal_position',
|
||||||
|
label: "Teeth pursue the cell the player is moving into",
|
||||||
|
rulesets: new Set(['lynx']),
|
||||||
|
}, {
|
||||||
|
key: 'rff_blocks_monsters',
|
||||||
|
label: "Monsters cannot step on random force floors",
|
||||||
|
rulesets: new Set(['ms']),
|
||||||
|
}, {
|
||||||
|
key: 'fire_allows_most_monsters',
|
||||||
|
label: "Monsters can walk into fire, except for bugs and walkers",
|
||||||
|
rulesets: new Set(['ms']),
|
||||||
|
}],
|
||||||
}, {
|
}, {
|
||||||
key: 'player_moves_last',
|
title: "Blocks",
|
||||||
label: "Players always move last",
|
flags: [{
|
||||||
rulesets: new Set(['lynx', 'ms']),
|
key: 'use_legacy_hooking',
|
||||||
}, {
|
label: "Pulling blocks with the hook happens earlier, and may prevent moving",
|
||||||
key: 'player_protected_by_items',
|
rulesets: new Set(['steam', 'steam-strict']),
|
||||||
label: "Players can't be trampled when standing on items",
|
}, {
|
||||||
rulesets: new Set(['lynx']),
|
key: 'no_directly_pushing_sliding_blocks',
|
||||||
}, {
|
label: "Pushing sliding blocks queues a move, rather than moving them right away",
|
||||||
// Note that this requires no_early_push as well
|
rulesets: new Set(['steam', 'steam-strict']),
|
||||||
key: 'player_safe_at_decision_time',
|
}, {
|
||||||
label: "Players can't be trampled at decision time",
|
key: 'emulate_spring_mining',
|
||||||
rulesets: new Set(['lynx']),
|
label: "Pushing a block off a recessed wall may cause you to move into the resulting wall",
|
||||||
}, {
|
rulesets: new Set(['steam-strict']),
|
||||||
key: 'emulate_60fps',
|
}, {
|
||||||
label: "Game runs at 60 FPS",
|
key: 'no_early_push',
|
||||||
rulesets: new Set(['steam', 'steam-strict']),
|
label: "Pushing blocks happens at move time (block slapping is disabled)",
|
||||||
}, {
|
// XXX wait but the DEFAULT behavior allows block slapping, which lynx has, so why is lynx listed here?
|
||||||
key: 'reuse_actor_slots',
|
rulesets: new Set(['lynx', 'ms']),
|
||||||
label: "Game reuses slots in the actor list",
|
}, {
|
||||||
rulesets: new Set(['lynx']),
|
key: 'use_pgchip_ice_blocks',
|
||||||
}, {
|
label: "Ice blocks use pgchip rules",
|
||||||
key: 'force_lynx_animation_lengths',
|
rulesets: new Set(['ms']),
|
||||||
label: "Animations use Lynx duration",
|
}, {
|
||||||
rulesets: new Set(['lynx']),
|
key: 'allow_pushing_blocks_off_faux_walls',
|
||||||
}, {
|
label: "Blocks may be pushed off of blue (fake), invisible, and revealing walls",
|
||||||
key: 'actors_move_instantly',
|
rulesets: new Set(['lynx']),
|
||||||
label: "Movement happens instantly",
|
}, {
|
||||||
rulesets: new Set(['ms']),
|
key: 'block_splashes_dont_block',
|
||||||
},
|
label: "Block splashes don't block the player",
|
||||||
|
rulesets: new Set(['ms']),
|
||||||
// Tiles
|
|
||||||
{
|
|
||||||
key: 'rff_actually_random',
|
|
||||||
label: "Random force floors are actually random",
|
|
||||||
rulesets: new Set(['ms']),
|
|
||||||
}, {
|
|
||||||
key: 'no_backwards_override',
|
|
||||||
label: "Players can't override backwards on a force floor",
|
|
||||||
rulesets: new Set(['lynx']),
|
|
||||||
}, {
|
|
||||||
key: 'traps_like_lynx',
|
|
||||||
label: "Traps eject faster, and even when already open",
|
|
||||||
rulesets: new Set(['lynx']),
|
|
||||||
}, {
|
|
||||||
key: 'popwalls_pop_on_arrive',
|
|
||||||
label: "Recessed walls activate when stepped on",
|
|
||||||
rulesets: new Set(['lynx', 'ms']),
|
|
||||||
}, {
|
|
||||||
key: 'blue_floors_vanish_on_arrive',
|
|
||||||
label: "Fake blue walls vanish when stepped on",
|
|
||||||
rulesets: new Set(['lynx']),
|
|
||||||
}, {
|
|
||||||
key: 'green_teleports_can_fail',
|
|
||||||
label: "Green teleporters sometimes fail",
|
|
||||||
rulesets: new Set(['steam-strict']),
|
|
||||||
},
|
|
||||||
|
|
||||||
// Items
|
|
||||||
{
|
|
||||||
key: 'bombs_detonate_on_arrive',
|
|
||||||
label: "Mines detonate only when stepped on",
|
|
||||||
rulesets: new Set(['lynx', 'ms']),
|
|
||||||
}, {
|
|
||||||
key: 'bombs_immediately_detonate_under_players',
|
|
||||||
label: "Mines under players detonate at level start",
|
|
||||||
rulesets: new Set(['steam-strict']),
|
|
||||||
}, {
|
|
||||||
key: 'cloned_bowling_balls_can_be_lost',
|
|
||||||
label: "Bowling balls on cloners are destroyed when fired at point blank",
|
|
||||||
rulesets: new Set(['steam-strict']),
|
|
||||||
}, {
|
|
||||||
key: 'monsters_ignore_keys',
|
|
||||||
label: "Monsters completely ignore keys",
|
|
||||||
rulesets: new Set(['ms']),
|
|
||||||
},
|
|
||||||
|
|
||||||
// Blocks
|
|
||||||
{
|
|
||||||
key: 'no_early_push',
|
|
||||||
label: "Pushing blocks happens at move time (block slapping is disabled)",
|
|
||||||
// XXX wait but the DEFAULT behavior allows block slapping, which lynx has, so why is lynx listed here?
|
|
||||||
rulesets: new Set(['lynx', 'ms']),
|
|
||||||
}, {
|
|
||||||
key: 'use_legacy_hooking',
|
|
||||||
label: "Pulling blocks with the hook happens at decision time",
|
|
||||||
rulesets: new Set(['steam', 'steam-strict']),
|
|
||||||
}, {
|
|
||||||
key: 'no_directly_pushing_sliding_blocks',
|
|
||||||
label: "Don't directly push sliding blocks",
|
|
||||||
rulesets: new Set(['steam', 'steam-strict']),
|
|
||||||
}, {
|
|
||||||
key: 'use_pgchip_ice_blocks',
|
|
||||||
label: "Ice blocks emulate pgchip rules",
|
|
||||||
rulesets: new Set(['ms']),
|
|
||||||
}, {
|
|
||||||
key: 'allow_pushing_blocks_off_faux_walls',
|
|
||||||
label: "Blocks may be pushed off of blue (fake), invisible, and revealing walls",
|
|
||||||
rulesets: new Set(['lynx']),
|
|
||||||
}, {
|
|
||||||
key: 'emulate_spring_mining',
|
|
||||||
label: "Spring mining is possible",
|
|
||||||
rulesets: new Set(['steam-strict']),
|
|
||||||
}, {
|
|
||||||
key: 'block_splashes_dont_block',
|
|
||||||
label: "Block splashes don't block the player",
|
|
||||||
rulesets: new Set(['ms']),
|
|
||||||
/* XXX not implemented
|
/* XXX not implemented
|
||||||
}, {
|
}, {
|
||||||
key: 'emulate_flicking',
|
key: 'emulate_flicking',
|
||||||
label: "Flicking is possible",
|
label: "Flicking is possible",
|
||||||
rulesets: new Set(['ms']),
|
rulesets: new Set(['ms']),
|
||||||
*/
|
*/
|
||||||
},
|
}],
|
||||||
|
}, {
|
||||||
|
title: "Terrain",
|
||||||
|
flags: [{
|
||||||
|
key: 'green_teleports_can_fail',
|
||||||
|
label: "Green teleporters sometimes fail",
|
||||||
|
rulesets: new Set(['steam-strict']),
|
||||||
|
}, {
|
||||||
|
key: 'no_backwards_override',
|
||||||
|
label: "Players can't override backwards on a force floor",
|
||||||
|
rulesets: new Set(['lynx']),
|
||||||
|
}, {
|
||||||
|
key: 'traps_like_lynx',
|
||||||
|
label: "Traps eject faster, and eject when already open",
|
||||||
|
rulesets: new Set(['lynx']),
|
||||||
|
}, {
|
||||||
|
key: 'blue_floors_vanish_on_arrive',
|
||||||
|
label: "Fake blue walls vanish when stepped on",
|
||||||
|
rulesets: new Set(['lynx']),
|
||||||
|
}, {
|
||||||
|
key: 'popwalls_pop_on_arrive',
|
||||||
|
label: "Recessed walls activate when stepped on",
|
||||||
|
rulesets: new Set(['lynx', 'ms']),
|
||||||
|
}, {
|
||||||
|
key: 'rff_actually_random',
|
||||||
|
label: "Random force floors are actually random",
|
||||||
|
rulesets: new Set(['ms']),
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
title: "Items",
|
||||||
|
flags: [{
|
||||||
|
key: 'cloned_bowling_balls_can_be_lost',
|
||||||
|
label: "Bowling balls on cloners are destroyed when fired at point blank",
|
||||||
|
rulesets: new Set(['steam-strict']),
|
||||||
|
}, {
|
||||||
|
key: 'bombs_immediately_detonate_under_players',
|
||||||
|
label: "Mines under players detonate when the level starts",
|
||||||
|
rulesets: new Set(['steam-strict']),
|
||||||
|
}, {
|
||||||
|
key: 'bombs_detonate_on_arrive',
|
||||||
|
label: "Mines detonate only when stepped on",
|
||||||
|
rulesets: new Set(['lynx', 'ms']),
|
||||||
|
}, {
|
||||||
|
key: 'monsters_ignore_keys',
|
||||||
|
label: "Monsters completely ignore keys",
|
||||||
|
rulesets: new Set(['ms']),
|
||||||
|
}],
|
||||||
|
}];
|
||||||
|
|
||||||
// Monsters
|
|
||||||
{
|
|
||||||
// TODO? in lynx they ignore the button while in motion too
|
|
||||||
// TODO what about in a trap, in every game??
|
|
||||||
// TODO what does ms do when a tank is on ice or a ff? wiki's description is wacky
|
|
||||||
// TODO yellow tanks seem to have memory too??
|
|
||||||
key: 'tanks_always_obey_button',
|
|
||||||
label: "Blue tanks on cloners obey blue buttons",
|
|
||||||
rulesets: new Set(['steam-strict']),
|
|
||||||
}, {
|
|
||||||
key: 'tanks_ignore_button_while_moving',
|
|
||||||
label: "Blue tanks ignore blue buttons while moving",
|
|
||||||
rulesets: new Set(['lynx']),
|
|
||||||
}, {
|
|
||||||
key: 'blobs_use_tw_prng',
|
|
||||||
label: "Blobs use the Tile World RNG",
|
|
||||||
rulesets: new Set(['lynx']),
|
|
||||||
}, {
|
|
||||||
key: 'teeth_target_internal_position',
|
|
||||||
label: "Teeth target the player's internal position",
|
|
||||||
rulesets: new Set(['lynx']),
|
|
||||||
}, {
|
|
||||||
key: 'rff_blocks_monsters',
|
|
||||||
label: "Random force floors block monsters",
|
|
||||||
rulesets: new Set(['ms']),
|
|
||||||
}, {
|
|
||||||
key: 'bonking_isnt_instant',
|
|
||||||
label: "Bonking while sliding doesn't apply instantly",
|
|
||||||
rulesets: new Set(['lynx', 'ms']),
|
|
||||||
}, {
|
|
||||||
key: 'fire_allows_most_monsters',
|
|
||||||
label: "Fire doesn't block monsters, except bugs and walkers",
|
|
||||||
rulesets: new Set(['ms']),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export function compat_flags_for_ruleset(ruleset) {
|
export function compat_flags_for_ruleset(ruleset) {
|
||||||
let compat = {};
|
let compat = {};
|
||||||
for (let compatdef of COMPAT_FLAGS) {
|
for (let category of COMPAT_FLAG_CATEGORIES) {
|
||||||
if (compatdef.rulesets.has(ruleset)) {
|
for (let compatdef of category.flags) {
|
||||||
compat[compatdef.key] = true;
|
if (compatdef.rulesets.has(ruleset)) {
|
||||||
|
compat[compatdef.key] = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return compat;
|
return compat;
|
||||||
|
|||||||
50
js/main.js
50
js/main.js
@ -2,7 +2,7 @@
|
|||||||
// - steam: if a player character starts on a force floor they won't be able to make any voluntary movements until they are no longer on a force floor
|
// - steam: if a player character starts on a force floor they won't be able to make any voluntary movements until they are no longer on a force floor
|
||||||
import * as fflate from './vendor/fflate.js';
|
import * as fflate from './vendor/fflate.js';
|
||||||
|
|
||||||
import { COMPAT_FLAGS, COMPAT_RULESET_LABELS, COMPAT_RULESET_ORDER, INPUT_BITS, TICS_PER_SECOND, compat_flags_for_ruleset } from './defs.js';
|
import { COMPAT_FLAG_CATEGORIES, COMPAT_RULESET_LABELS, COMPAT_RULESET_ORDER, INPUT_BITS, TICS_PER_SECOND, compat_flags_for_ruleset } from './defs.js';
|
||||||
import * as c2g from './format-c2g.js';
|
import * as c2g from './format-c2g.js';
|
||||||
import * as dat from './format-dat.js';
|
import * as dat from './format-dat.js';
|
||||||
import * as format_base from './format-base.js';
|
import * as format_base from './format-base.js';
|
||||||
@ -3301,8 +3301,8 @@ class CompatOverlay extends DialogOverlay {
|
|||||||
"These are more technical settings, and as such are documented in full on ",
|
"These are more technical settings, and as such are documented in full on ",
|
||||||
mk('a', {href: 'https://github.com/eevee/lexys-labyrinth/wiki/Compatibility'}, "the project wiki"),
|
mk('a', {href: 'https://github.com/eevee/lexys-labyrinth/wiki/Compatibility'}, "the project wiki"),
|
||||||
"."),
|
"."),
|
||||||
mk('p', "The short version is: Lexy mode is fine 99% of the time. If a level doesn't seem to work, try the mode for the game it's designed for. Microsoft mode is best-effort and nothing is guaranteed."),
|
mk('p', "Lexy mode should be fine 99% of the time. If a level doesn't seem to work, try the mode for the game it's designed for."),
|
||||||
mk('p', "Changes won't take effect until you restart the level or change levels."),
|
mk('p', "Changes take effect when a level starts."),
|
||||||
);
|
);
|
||||||
|
|
||||||
let button_set = mk('div.radio-faux-button-set');
|
let button_set = mk('div.radio-faux-button-set');
|
||||||
@ -3321,7 +3321,7 @@ class CompatOverlay extends DialogOverlay {
|
|||||||
if (ruleset === 'custom')
|
if (ruleset === 'custom')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (let compat of COMPAT_FLAGS) {
|
for (let compat of this.all_compat_flags) {
|
||||||
this.set(compat.key, compat.rulesets.has(ruleset));
|
this.set(compat.key, compat.rulesets.has(ruleset));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -3329,30 +3329,36 @@ class CompatOverlay extends DialogOverlay {
|
|||||||
|
|
||||||
// TODO include the section dividers, somehow
|
// TODO include the section dividers, somehow
|
||||||
let list = mk('ul.compat-flags');
|
let list = mk('ul.compat-flags');
|
||||||
for (let compat of COMPAT_FLAGS) {
|
this.all_compat_flags = [];
|
||||||
let label = mk('label',
|
for (let category of COMPAT_FLAG_CATEGORIES) {
|
||||||
mk('input', {type: 'checkbox', name: compat.key}),
|
this.all_compat_flags.push(...category.flags);
|
||||||
mk('span.-desc', compat.label),
|
list.append(mk('h2', category.title));
|
||||||
);
|
|
||||||
for (let ruleset of COMPAT_RULESET_ORDER) {
|
|
||||||
if (ruleset === 'lexy' || ruleset === 'custom')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (compat.rulesets.has(ruleset)) {
|
for (let compat of category.flags) {
|
||||||
label.append(mk('img.compat-icon', {src: `icons/compat-${ruleset}.png`}));
|
let label = mk('label',
|
||||||
}
|
mk('input', {type: 'checkbox', name: compat.key}),
|
||||||
else {
|
mk('span.-desc', compat.label),
|
||||||
label.append(mk('span.compat-icon-gap'));
|
);
|
||||||
|
for (let ruleset of COMPAT_RULESET_ORDER) {
|
||||||
|
if (ruleset === 'lexy' || ruleset === 'custom')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (compat.rulesets.has(ruleset)) {
|
||||||
|
label.append(mk('img.compat-icon', {src: `icons/compat-${ruleset}.png`}));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
label.append(mk('span.compat-icon-gap'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
list.append(mk('li', label));
|
||||||
}
|
}
|
||||||
list.append(mk('li', label));
|
|
||||||
}
|
}
|
||||||
list.addEventListener('change', ev => {
|
list.addEventListener('change', ev => {
|
||||||
// If the current set of flags exactly matches one of the presets, highlight that button
|
// If the current set of flags exactly matches one of the presets, highlight that button
|
||||||
let selected_ruleset = 'custom';
|
let selected_ruleset = 'custom';
|
||||||
for (let ruleset of COMPAT_RULESET_ORDER) {
|
for (let ruleset of COMPAT_RULESET_ORDER) {
|
||||||
let ok = true;
|
let ok = true;
|
||||||
for (let compat of COMPAT_FLAGS) {
|
for (let compat of this.all_compat_flags) {
|
||||||
if (this.root.elements[compat.key].checked !== compat.rulesets.has(ruleset)) {
|
if (this.root.elements[compat.key].checked !== compat.rulesets.has(ruleset)) {
|
||||||
ok = false;
|
ok = false;
|
||||||
break;
|
break;
|
||||||
@ -3372,7 +3378,7 @@ class CompatOverlay extends DialogOverlay {
|
|||||||
|
|
||||||
// Populate everything to match the current settings
|
// Populate everything to match the current settings
|
||||||
this.root.elements['__ruleset__'].value = this.conductor._compat_ruleset ?? 'custom';
|
this.root.elements['__ruleset__'].value = this.conductor._compat_ruleset ?? 'custom';
|
||||||
for (let compat of COMPAT_FLAGS) {
|
for (let compat of this.all_compat_flags) {
|
||||||
this.set(compat.key, !! this.conductor.compat[compat.key]);
|
this.set(compat.key, !! this.conductor.compat[compat.key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3397,7 +3403,7 @@ class CompatOverlay extends DialogOverlay {
|
|||||||
|
|
||||||
save(permanent) {
|
save(permanent) {
|
||||||
let flags = {};
|
let flags = {};
|
||||||
for (let compat of COMPAT_FLAGS) {
|
for (let compat of this.all_compat_flags) {
|
||||||
if (this.root.elements[compat.key].checked) {
|
if (this.root.elements[compat.key].checked) {
|
||||||
flags[compat.key] = true;
|
flags[compat.key] = true;
|
||||||
}
|
}
|
||||||
@ -3915,7 +3921,6 @@ class Conductor {
|
|||||||
document.querySelector('#main-compat').addEventListener('click', () => {
|
document.querySelector('#main-compat').addEventListener('click', () => {
|
||||||
new CompatOverlay(this).open();
|
new CompatOverlay(this).open();
|
||||||
});
|
});
|
||||||
document.querySelector('#main-compat output').textContent = COMPAT_RULESET_LABELS[this._compat_ruleset ?? 'custom'];
|
|
||||||
|
|
||||||
// Bind to the navigation headers, which list the current level pack
|
// Bind to the navigation headers, which list the current level pack
|
||||||
// and level
|
// and level
|
||||||
@ -4266,6 +4271,7 @@ class Conductor {
|
|||||||
this._compat_ruleset = ruleset;
|
this._compat_ruleset = ruleset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.querySelector('#main-compat img').src = `icons/compat-${ruleset}.png`;
|
||||||
document.querySelector('#main-compat output').textContent = COMPAT_RULESET_LABELS[ruleset];
|
document.querySelector('#main-compat output').textContent = COMPAT_RULESET_LABELS[ruleset];
|
||||||
|
|
||||||
this.compat = flags;
|
this.compat = flags;
|
||||||
|
|||||||
18
style.css
18
style.css
@ -327,6 +327,16 @@ button.--pressed,
|
|||||||
.dialog a:visited {
|
.dialog a:visited {
|
||||||
color: hsl(255, 50%, 50%);
|
color: hsl(255, 50%, 50%);
|
||||||
}
|
}
|
||||||
|
.dialog code {
|
||||||
|
color: hsl(var(--main-hue), 50%, 30%);
|
||||||
|
}
|
||||||
|
.dialog h2 {
|
||||||
|
color: hsl(var(--main-hue), 75%, 25%);
|
||||||
|
border-bottom: 1px dotted hsl(var(--main-hue), 50%, 40%);
|
||||||
|
}
|
||||||
|
.dialog h2:nth-child(n+1) {
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
dl.formgrid {
|
dl.formgrid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid: auto-flow min-content / 1fr 4fr;
|
grid: auto-flow min-content / 1fr 4fr;
|
||||||
@ -525,6 +535,9 @@ ul.compat-flags > li > label {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.25em;
|
gap: 0.25em;
|
||||||
}
|
}
|
||||||
|
ul.compat-flags > li > label > input[type=check] {
|
||||||
|
margin: 0.25em;
|
||||||
|
}
|
||||||
ul.compat-flags > li > label > span.-desc {
|
ul.compat-flags > li > label > span.-desc {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
@ -727,6 +740,11 @@ pre.stack-trace {
|
|||||||
image-rendering: crisp-edges;
|
image-rendering: crisp-edges;
|
||||||
image-rendering: pixelated;
|
image-rendering: pixelated;
|
||||||
}
|
}
|
||||||
|
#main-compat > img {
|
||||||
|
height: 16px;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-right: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
@media (orientation: portrait) and (max-width: 800px), (orientation: landscape) and (max-height: 600px) {
|
@media (orientation: portrait) and (max-width: 800px), (orientation: landscape) and (max-height: 600px) {
|
||||||
body > header {
|
body > header {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user