Name compat flags more consistently; add a couple; flip sliding blue tank behavior
This commit is contained in:
parent
3359c21387
commit
0119f45d54
11
js/game.js
11
js/game.js
@ -1461,13 +1461,6 @@ export class Level extends LevelInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
make_actor_decision(actor, forced_only = false) {
|
make_actor_decision(actor, forced_only = false) {
|
||||||
// Compat flag for blue tanks
|
|
||||||
if (this.compat.sliding_tanks_ignore_button &&
|
|
||||||
actor.slide_mode && actor.pending_reverse)
|
|
||||||
{
|
|
||||||
this._set_tile_prop(actor, 'pending_reverse', false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actor.pending_push) {
|
if (actor.pending_push) {
|
||||||
// Blocks that were pushed while sliding will move in the push direction as soon as
|
// Blocks that were pushed while sliding will move in the push direction as soon as
|
||||||
// they can make a decision, even if they're still sliding or are off-tic. Also used
|
// they can make a decision, even if they're still sliding or are off-tic. Also used
|
||||||
@ -2501,6 +2494,10 @@ export class Level extends LevelInterface {
|
|||||||
// Get the next direction a random force floor will use. They share global
|
// Get the next direction a random force floor will use. They share global
|
||||||
// state and cycle clockwise.
|
// state and cycle clockwise.
|
||||||
get_force_floor_direction() {
|
get_force_floor_direction() {
|
||||||
|
if (this.compat.rff_actually_random) {
|
||||||
|
return DIRECTION_ORDER[this.prng() % 4];
|
||||||
|
}
|
||||||
|
|
||||||
let d = this.force_floor_direction;
|
let d = this.force_floor_direction;
|
||||||
this.force_floor_direction = DIRECTIONS[d].right;
|
this.force_floor_direction = DIRECTIONS[d].right;
|
||||||
return d;
|
return d;
|
||||||
|
|||||||
117
js/main.js
117
js/main.js
@ -2944,73 +2944,102 @@ const COMPAT_RULESETS = [
|
|||||||
['ms', "Microsoft"],
|
['ms', "Microsoft"],
|
||||||
['custom', "Custom"],
|
['custom', "Custom"],
|
||||||
];
|
];
|
||||||
const COMPAT_FLAGS = [{
|
// FIXME some of the names of the flags themselves kinda suck
|
||||||
|
const COMPAT_FLAGS = [
|
||||||
|
// Level loading
|
||||||
|
{
|
||||||
key: 'no_auto_convert_ccl_popwalls',
|
key: 'no_auto_convert_ccl_popwalls',
|
||||||
label: "Don't fix populated recessed walls in CC1 levels",
|
label: "Recessed walls under actors in CCL levels are left alone",
|
||||||
rulesets: new Set(['steam-strict', 'lynx', 'ms']),
|
rulesets: new Set(['steam-strict', 'lynx', 'ms']),
|
||||||
}, {
|
}, {
|
||||||
key: 'no_auto_convert_ccl_blue_walls',
|
key: 'no_auto_convert_ccl_blue_walls',
|
||||||
label: "Don't fix populated blue walls in CC1 levels",
|
label: "Blue walls under blocks in CCL levels are left alone",
|
||||||
rulesets: new Set(['steam-strict', 'lynx']),
|
rulesets: new Set(['steam-strict', 'lynx']),
|
||||||
|
},
|
||||||
|
|
||||||
|
// Core
|
||||||
|
{
|
||||||
|
key: 'use_lynx_loop',
|
||||||
|
label: "Game uses the Lynx-style update loop",
|
||||||
|
rulesets: new Set(['steam', 'steam-strict', 'lynx', 'ms']),
|
||||||
}, {
|
}, {
|
||||||
|
key: 'emulate_60fps',
|
||||||
|
label: "Game runs at 60 FPS",
|
||||||
|
rulesets: new Set(['steam', 'steam-strict']),
|
||||||
|
},
|
||||||
|
|
||||||
|
// Tiles
|
||||||
|
{
|
||||||
|
// XXX this is goofy
|
||||||
|
key: 'tiles_react_instantly',
|
||||||
|
label: "Tiles react when approached",
|
||||||
|
rulesets: new Set(['ms']),
|
||||||
|
}, {
|
||||||
|
key: 'rff_actually_random',
|
||||||
|
label: "Random force floors are actually random",
|
||||||
|
rulesets: new Set(['ms']),
|
||||||
|
},
|
||||||
|
|
||||||
|
// Items
|
||||||
|
{
|
||||||
key: 'no_immediate_detonate_bombs',
|
key: 'no_immediate_detonate_bombs',
|
||||||
label: "Don't immediately detonate populated mines",
|
label: "Mines under non-player actors don't explode at level start",
|
||||||
rulesets: new Set(['lynx', 'ms']),
|
rulesets: new Set(['lynx', 'ms']),
|
||||||
}, {
|
}, {
|
||||||
key: 'detonate_bombs_under_players',
|
key: 'detonate_bombs_under_players',
|
||||||
label: "Detonate mines populated by players",
|
label: "Mines under players explode at level start",
|
||||||
rulesets: new Set(['steam', 'steam-strict']),
|
rulesets: new Set(['steam', 'steam-strict']),
|
||||||
}, {
|
}, {
|
||||||
key: 'tanks_teeth_push_ice_blocks',
|
key: 'monsters_ignore_keys',
|
||||||
label: "Blue tanks and teeth can push ice blocks",
|
label: "Monsters completely ignore keys",
|
||||||
rulesets: new Set(['ms']),
|
rulesets: new Set(['ms']),
|
||||||
}, {
|
},
|
||||||
key: 'sliding_tanks_ignore_button',
|
|
||||||
label: "Blue tanks ignore blue buttons while sliding",
|
// Blocks
|
||||||
// TODO ms?
|
{
|
||||||
rulesets: new Set(['lynx']),
|
key: 'no_early_push',
|
||||||
}, {
|
label: "Player pushes blocks at move time",
|
||||||
key: 'cloner_tanks_react_button',
|
rulesets: new Set(['lynx', 'ms']),
|
||||||
label: "Blue tanks on cloners respond to blue buttons",
|
|
||||||
rulesets: new Set(['steam-strict']),
|
|
||||||
}, {
|
}, {
|
||||||
key: 'use_legacy_hooking',
|
key: 'use_legacy_hooking',
|
||||||
label: "Player pulls blocks at decision time",
|
label: "Pulling blocks with the hook happens at decision time",
|
||||||
// TODO maybe steam as well?
|
rulesets: new Set(['steam', 'steam-strict']),
|
||||||
rulesets: new Set(['steam-strict']),
|
|
||||||
}, {
|
}, {
|
||||||
key: 'monsters_ignore_keys',
|
// FIXME this is kind of annoying, there are some collision rules too
|
||||||
label: "Monsters ignore keys",
|
key: 'tanks_teeth_push_ice_blocks',
|
||||||
rulesets: new Set(['ms']),
|
label: "Ice blocks emulate pgchip rules",
|
||||||
}, {
|
|
||||||
// XXX this is goofy
|
|
||||||
key: 'tiles_react_instantly',
|
|
||||||
label: "Tiles react instantly",
|
|
||||||
rulesets: new Set(['ms']),
|
rulesets: new Set(['ms']),
|
||||||
}, {
|
}, {
|
||||||
key: 'emulate_spring_mining',
|
key: 'emulate_spring_mining',
|
||||||
label: "Emulate spring mining",
|
label: "Spring mining is possible",
|
||||||
|
rulesets: new Set(['steam-strict']),
|
||||||
|
/* XXX not implemented
|
||||||
|
}, {
|
||||||
|
key: 'emulate_flicking',
|
||||||
|
label: "Flicking is possible",
|
||||||
|
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 always obey blue buttons",
|
||||||
rulesets: new Set(['steam-strict']),
|
rulesets: new Set(['steam-strict']),
|
||||||
}, {
|
}, {
|
||||||
// XXX not implemented
|
key: 'rff_blocks_monsters',
|
||||||
/*
|
label: "Random force floors block monsters",
|
||||||
key: 'emulate_flicking',
|
|
||||||
label: "Emulate flicking",
|
|
||||||
rulesets: new Set(['ms']),
|
rulesets: new Set(['ms']),
|
||||||
}, {
|
}, {
|
||||||
*/
|
key: 'fire_allows_monsters',
|
||||||
key: 'use_lynx_loop',
|
label: "Fire doesn't block monsters",
|
||||||
label: "Use Lynx-style update loop",
|
rulesets: new Set(['ms']),
|
||||||
rulesets: new Set(['steam', 'steam-strict', 'lynx', 'ms']),
|
},
|
||||||
}, {
|
];
|
||||||
key: 'no_early_push',
|
|
||||||
label: "Player doesn't push at decision time",
|
|
||||||
rulesets: new Set(['lynx', 'ms']),
|
|
||||||
}, {
|
|
||||||
key: 'emulate_60fps',
|
|
||||||
label: "Run at 60 FPS",
|
|
||||||
rulesets: new Set(['steam', 'steam-strict']),
|
|
||||||
}];
|
|
||||||
class CompatOverlay extends DialogOverlay {
|
class CompatOverlay extends DialogOverlay {
|
||||||
constructor(conductor) {
|
constructor(conductor) {
|
||||||
super(conductor);
|
super(conductor);
|
||||||
|
|||||||
@ -372,6 +372,7 @@ const TILE_TYPES = {
|
|||||||
{
|
{
|
||||||
// Blocks can be pushed off of blue walls in TW Lynx, which only works due to a tiny
|
// Blocks can be pushed off of blue walls in TW Lynx, which only works due to a tiny
|
||||||
// quirk of the engine that I don't want to replicate, so replace them with popwalls
|
// quirk of the engine that I don't want to replicate, so replace them with popwalls
|
||||||
|
// TODO this also works with invis walls apparently. maybe only for blocks?
|
||||||
me.type = TILE_TYPES['popwall'];
|
me.type = TILE_TYPES['popwall'];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -741,7 +742,15 @@ const TILE_TYPES = {
|
|||||||
// Hazards
|
// Hazards
|
||||||
fire: {
|
fire: {
|
||||||
layer: LAYERS.terrain,
|
layer: LAYERS.terrain,
|
||||||
blocks_collision: COLLISION.monster_solid & ~COLLISION.fireball,
|
// Fire blocks most monsters, except in MS where they walk right in and get roasted
|
||||||
|
blocks(me, level, other) {
|
||||||
|
if (other.type.collision_mask & (COLLISION.fireball | COLLISION.ghost))
|
||||||
|
return false;
|
||||||
|
if (other.type.collision_mask & COLLISION.monster_any) {
|
||||||
|
return ! level.compat.fire_allows_monsters;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
on_arrive(me, level, other) {
|
on_arrive(me, level, other) {
|
||||||
if (other.type.name === 'ghost') {
|
if (other.type.name === 'ghost') {
|
||||||
// Ghosts with fire boots erase fire, otherwise are unaffected
|
// Ghosts with fire boots erase fire, otherwise are unaffected
|
||||||
@ -986,6 +995,10 @@ const TILE_TYPES = {
|
|||||||
speed_factor: 2,
|
speed_factor: 2,
|
||||||
on_begin: on_begin_force_floor,
|
on_begin: on_begin_force_floor,
|
||||||
// TODO ms: this is random, and an acting wall to monsters (!)
|
// TODO ms: this is random, and an acting wall to monsters (!)
|
||||||
|
blocks(me, level, other) {
|
||||||
|
return (level.compat.rff_blocks_monsters &&
|
||||||
|
(other.type.collision_mask & COLLISION.monster_general));
|
||||||
|
},
|
||||||
on_arrive(me, level, other) {
|
on_arrive(me, level, other) {
|
||||||
level.set_actor_direction(other, level.get_force_floor_direction());
|
level.set_actor_direction(other, level.get_force_floor_direction());
|
||||||
},
|
},
|
||||||
@ -1871,11 +1884,16 @@ const TILE_TYPES = {
|
|||||||
// Flip direction of all blue tanks
|
// Flip direction of all blue tanks
|
||||||
for (let actor of level.actors) {
|
for (let actor of level.actors) {
|
||||||
// TODO generify somehow??
|
// TODO generify somehow??
|
||||||
if (actor.type.name === 'tank_blue') {
|
if (actor.type.name !== 'tank_blue')
|
||||||
if (level.compat.cloner_tanks_react_button || ! actor.cell.has('cloner')) {
|
continue;
|
||||||
level._set_tile_prop(actor, 'pending_reverse', ! actor.pending_reverse);
|
|
||||||
}
|
if (! level.compat.tanks_always_obey_button &&
|
||||||
|
(actor.slide_mode || actor.cell.has('cloner')))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
level._set_tile_prop(actor, 'pending_reverse', ! actor.pending_reverse);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
on_arrive(me, level, other) {
|
on_arrive(me, level, other) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user