Make sliding be the tiles' responsibility
This seems to simplify things and also explain the CC2 semantics: force floors activate while being stood on (which happens, I guess, during idle), so it applies to objects that start the level on force floors. This was probably done to make force floor flipping work, too. On the other hand, ice still only activates when being stepped on.
This commit is contained in:
parent
7ba261c7d9
commit
a1f357f317
58
js/game.js
58
js/game.js
@ -1238,25 +1238,6 @@ export class Level extends LevelInterface {
|
||||
}
|
||||
this.pending_green_toggle = false;
|
||||
}
|
||||
|
||||
// On the very first tic, check for any actors standing on force floors, and set their slide
|
||||
// directions. Done here because they do NOT move yet, even if unblocked!
|
||||
// TODO this feels oddly artificial. is this supposed to happen during idle, maybe?
|
||||
// FIXME check compat flag for lynx
|
||||
if (this.tic_counter === 0 && this.frame_offset === 0) {
|
||||
for (let i = this.actors.length - 1; i >= 0; i--) {
|
||||
let actor = this.actors[i];
|
||||
|
||||
let terrain = actor.cell.get_terrain();
|
||||
if (terrain && terrain.type.slide_mode === 'force') {
|
||||
let forced_move = this.get_forced_move(actor, terrain);
|
||||
if (forced_move) {
|
||||
this._set_tile_prop(actor, 'is_pending_slide', true)
|
||||
this.set_actor_direction(actor, forced_move);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_do_cleanup_phase() {
|
||||
@ -1338,22 +1319,6 @@ export class Level extends LevelInterface {
|
||||
return [dir1, dir2];
|
||||
}
|
||||
|
||||
get_forced_move(actor, terrain = null) {
|
||||
if (! terrain) {
|
||||
terrain = actor.cell.get_terrain();
|
||||
}
|
||||
if (! terrain.type.slide_mode)
|
||||
return null;
|
||||
if (! terrain.type.get_slide_direction)
|
||||
return null;
|
||||
if (! (actor.is_pending_slide || terrain.type.slide_automatically))
|
||||
return null;
|
||||
if (actor.ignores(terrain.type.name))
|
||||
return null;
|
||||
|
||||
return terrain.type.get_slide_direction(terrain, this, actor);
|
||||
}
|
||||
|
||||
make_player_decision(actor, input, forced_only = false) {
|
||||
// Only reset the player's is_pushing between movement, so it lasts for the whole push
|
||||
this._set_tile_prop(actor, 'is_pushing', false);
|
||||
@ -2048,23 +2013,23 @@ export class Level extends LevelInterface {
|
||||
// Kind of weird putting slide_ignores here, except that all sliding happens on
|
||||
// on_arrive, and tiles that make you slide in on_arrive don't do anything else, so
|
||||
// for now it works
|
||||
// XXX that is jank as hell what are you talking about
|
||||
tile.type.on_arrive(tile, this, actor);
|
||||
}
|
||||
|
||||
if (tile.type.on_stand && !actor.slide_ignores(tile.type.name)) {
|
||||
// XXX according to notcc, cc2 also has actors "stand" on tiles immediately upon
|
||||
// arrival, even though they'll do it anyway on their idle phase
|
||||
tile.type.on_stand(tile, this, actor);
|
||||
}
|
||||
|
||||
if (tile.type.slide_automatically) {
|
||||
// This keeps a player on force floor consistently using their sliding pose, even if
|
||||
// drawn between moves. It also simplifies checks elsewhere, so that's nice
|
||||
// FIXME if i'm right about how this works then this may not be necessary?
|
||||
this._set_tile_prop(actor, 'is_pending_slide', true);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME ingratiate this with the rest of this stuff i think
|
||||
// FIXME figure out what the hell that comment means
|
||||
let forced_move = this.get_forced_move(actor);
|
||||
if (forced_move) {
|
||||
this._set_tile_prop(actor, 'is_pending_slide', true)
|
||||
this.set_actor_direction(actor, forced_move);
|
||||
}
|
||||
}
|
||||
|
||||
attempt_teleport(actor) {
|
||||
@ -3031,4 +2996,11 @@ export class Level extends LevelInterface {
|
||||
set_actor_direction(actor, direction) {
|
||||
this._set_tile_prop(actor, 'direction', direction);
|
||||
}
|
||||
|
||||
schedule_actor_slide(actor, direction = null) {
|
||||
if (direction) {
|
||||
this.set_actor_direction(actor, direction);
|
||||
}
|
||||
this._set_tile_prop(actor, 'is_pending_slide', true);
|
||||
}
|
||||
}
|
||||
|
||||
112
js/tiletypes.js
112
js/tiletypes.js
@ -58,14 +58,17 @@ function _define_force_floor(direction, opposite_type) {
|
||||
speed_factor: 2,
|
||||
slide_automatically: true,
|
||||
allow_player_override: true,
|
||||
get_slide_direction(me, level, other) {
|
||||
on_stand(me, level, other) {
|
||||
level.schedule_actor_slide(other, direction);
|
||||
// FIXME i think it's really that in lynx these push on arrival; try that and see if
|
||||
// it's better
|
||||
/*
|
||||
if (level.compat.force_floors_inert_on_first_tic && level.tic_counter === 0) {
|
||||
// Lynx: Force floors don't push on the first tic
|
||||
return null;
|
||||
}
|
||||
return direction;
|
||||
*/
|
||||
},
|
||||
force_floor_direction: direction,
|
||||
activate(me, level) {
|
||||
level.transmute_tile(me, opposite_type);
|
||||
},
|
||||
@ -744,9 +747,6 @@ const TILE_TYPES = {
|
||||
contains_wire: true,
|
||||
wire_propagation_mode: 'all',
|
||||
slide_mode: 'turntable',
|
||||
get_slide_direction(me, level, other) {
|
||||
return other.direction;
|
||||
},
|
||||
on_arrive(me, level, other) {
|
||||
level._set_tile_prop(other, 'is_pending_slide', true);
|
||||
level.set_actor_direction(other, DIRECTIONS[other.direction].right);
|
||||
@ -754,6 +754,9 @@ const TILE_TYPES = {
|
||||
other.type.on_rotate(other, level, 'right');
|
||||
}
|
||||
},
|
||||
on_stand(me, level, other) {
|
||||
level.schedule_actor_slide(other);
|
||||
},
|
||||
activate(me, level) {
|
||||
level.transmute_tile(me, 'turntable_ccw');
|
||||
},
|
||||
@ -765,9 +768,6 @@ const TILE_TYPES = {
|
||||
contains_wire: true,
|
||||
wire_propagation_mode: 'all',
|
||||
slide_mode: 'turntable',
|
||||
get_slide_direction(me, level, other) {
|
||||
return other.direction;
|
||||
},
|
||||
on_arrive(me, level, other) {
|
||||
level._set_tile_prop(other, 'is_pending_slide', true);
|
||||
level.set_actor_direction(other, DIRECTIONS[other.direction].left);
|
||||
@ -775,6 +775,9 @@ const TILE_TYPES = {
|
||||
other.type.on_rotate(other, level, 'left');
|
||||
}
|
||||
},
|
||||
on_stand(me, level, other) {
|
||||
level.schedule_actor_slide(other);
|
||||
},
|
||||
activate(me, level) {
|
||||
level.transmute_tile(me, 'turntable_cw');
|
||||
},
|
||||
@ -886,12 +889,9 @@ const TILE_TYPES = {
|
||||
cracked_ice: {
|
||||
layer: LAYERS.terrain,
|
||||
slide_mode: 'ice',
|
||||
get_slide_direction(me, level, other) {
|
||||
return other.direction;
|
||||
},
|
||||
speed_factor: 2,
|
||||
on_arrive(me, level, other) {
|
||||
level._set_tile_prop(other, 'is_pending_slide', true);
|
||||
level.schedule_actor_slide(other);
|
||||
},
|
||||
on_depart(me, level, other) {
|
||||
level.transmute_tile(me, 'water');
|
||||
@ -902,84 +902,73 @@ const TILE_TYPES = {
|
||||
ice: {
|
||||
layer: LAYERS.terrain,
|
||||
slide_mode: 'ice',
|
||||
get_slide_direction(me, level, other) {
|
||||
return other.direction;
|
||||
},
|
||||
speed_factor: 2,
|
||||
on_arrive(me, level, other) {
|
||||
level._set_tile_prop(other, 'is_pending_slide', true);
|
||||
level.schedule_actor_slide(other);
|
||||
},
|
||||
},
|
||||
ice_sw: {
|
||||
layer: LAYERS.terrain,
|
||||
thin_walls: new Set(['south', 'west']),
|
||||
slide_mode: 'ice',
|
||||
get_slide_direction(me, level, other) {
|
||||
return {
|
||||
speed_factor: 2,
|
||||
blocks_leaving: blocks_leaving_thin_walls,
|
||||
on_arrive(me, level, other) {
|
||||
let direction = {
|
||||
north: 'north',
|
||||
south: 'east',
|
||||
east: 'east',
|
||||
west: 'north',
|
||||
}[other.direction];
|
||||
},
|
||||
speed_factor: 2,
|
||||
blocks_leaving: blocks_leaving_thin_walls,
|
||||
on_arrive(me, level, other) {
|
||||
level._set_tile_prop(other, 'is_pending_slide', true);
|
||||
level.schedule_actor_slide(other, direction);
|
||||
},
|
||||
},
|
||||
ice_nw: {
|
||||
layer: LAYERS.terrain,
|
||||
thin_walls: new Set(['north', 'west']),
|
||||
slide_mode: 'ice',
|
||||
get_slide_direction(me, level, other) {
|
||||
return {
|
||||
speed_factor: 2,
|
||||
blocks_leaving: blocks_leaving_thin_walls,
|
||||
on_arrive(me, level, other) {
|
||||
let direction = {
|
||||
north: 'east',
|
||||
south: 'south',
|
||||
east: 'east',
|
||||
west: 'south',
|
||||
}[other.direction];
|
||||
},
|
||||
speed_factor: 2,
|
||||
blocks_leaving: blocks_leaving_thin_walls,
|
||||
on_arrive(me, level, other) {
|
||||
level._set_tile_prop(other, 'is_pending_slide', true);
|
||||
level.schedule_actor_slide(other, direction);
|
||||
},
|
||||
},
|
||||
ice_ne: {
|
||||
layer: LAYERS.terrain,
|
||||
thin_walls: new Set(['north', 'east']),
|
||||
slide_mode: 'ice',
|
||||
get_slide_direction(me, level, other) {
|
||||
return {
|
||||
speed_factor: 2,
|
||||
blocks_leaving: blocks_leaving_thin_walls,
|
||||
on_arrive(me, level, other) {
|
||||
let direction = {
|
||||
north: 'west',
|
||||
south: 'south',
|
||||
east: 'south',
|
||||
west: 'west',
|
||||
}[other.direction];
|
||||
},
|
||||
speed_factor: 2,
|
||||
blocks_leaving: blocks_leaving_thin_walls,
|
||||
on_arrive(me, level, other) {
|
||||
level._set_tile_prop(other, 'is_pending_slide', true);
|
||||
level.schedule_actor_slide(other, direction);
|
||||
},
|
||||
},
|
||||
ice_se: {
|
||||
layer: LAYERS.terrain,
|
||||
thin_walls: new Set(['south', 'east']),
|
||||
slide_mode: 'ice',
|
||||
get_slide_direction(me, level, other) {
|
||||
return {
|
||||
speed_factor: 2,
|
||||
blocks_leaving: blocks_leaving_thin_walls,
|
||||
on_arrive(me, level, other) {
|
||||
let direction = {
|
||||
north: 'north',
|
||||
south: 'west',
|
||||
east: 'north',
|
||||
west: 'west',
|
||||
}[other.direction];
|
||||
},
|
||||
speed_factor: 2,
|
||||
blocks_leaving: blocks_leaving_thin_walls,
|
||||
on_arrive(me, level, other) {
|
||||
level._set_tile_prop(other, 'is_pending_slide', true);
|
||||
level.schedule_actor_slide(other, direction);
|
||||
},
|
||||
},
|
||||
force_floor_n: _define_force_floor('north', 'force_floor_s'),
|
||||
@ -992,16 +981,25 @@ const TILE_TYPES = {
|
||||
slide_automatically: true,
|
||||
speed_factor: 2,
|
||||
allow_player_override: true,
|
||||
get_slide_direction(me, level, _other) {
|
||||
blocks(me, level, other) {
|
||||
return (level.compat.rff_blocks_monsters &&
|
||||
(other.type.collision_mask & COLLISION.monster_typical));
|
||||
},
|
||||
on_stand(me, level, other) {
|
||||
// XXX this check is necessary because of step_on_cell and then the idle phase causing
|
||||
// us to be called twice. who is correct?? is the step_on_cell call supposed to be
|
||||
// there?
|
||||
if (! other.is_pending_slide) {
|
||||
level.schedule_actor_slide(other, level.get_force_floor_direction());
|
||||
}
|
||||
// FIXME i think it's really that in lynx these push on arrival; try that and see if
|
||||
// it's better
|
||||
/*
|
||||
if (level.compat.force_floors_inert_on_first_tic && level.tic_counter === 0) {
|
||||
// Lynx: Force floors don't push on the first tic
|
||||
return null;
|
||||
}
|
||||
return level.get_force_floor_direction();
|
||||
},
|
||||
blocks(me, level, other) {
|
||||
return (level.compat.rff_blocks_monsters &&
|
||||
(other.type.collision_mask & COLLISION.monster_typical));
|
||||
*/
|
||||
},
|
||||
},
|
||||
slime: {
|
||||
@ -1726,9 +1724,6 @@ const TILE_TYPES = {
|
||||
teleport_blue: {
|
||||
layer: LAYERS.terrain,
|
||||
slide_mode: 'teleport',
|
||||
get_slide_direction(me, level, other) {
|
||||
return other.direction;
|
||||
},
|
||||
contains_wire: true,
|
||||
wire_propagation_mode: 'all',
|
||||
*teleport_dest_order(me, level, other) {
|
||||
@ -1816,9 +1811,6 @@ const TILE_TYPES = {
|
||||
teleport_red: {
|
||||
layer: LAYERS.terrain,
|
||||
slide_mode: 'teleport',
|
||||
get_slide_direction(me, level, other) {
|
||||
return other.direction;
|
||||
},
|
||||
contains_wire: true,
|
||||
wire_propagation_mode: 'none',
|
||||
allow_player_override: true,
|
||||
@ -1873,9 +1865,6 @@ const TILE_TYPES = {
|
||||
teleport_green: {
|
||||
layer: LAYERS.terrain,
|
||||
slide_mode: 'teleport',
|
||||
get_slide_direction(me, level, other) {
|
||||
return other.direction;
|
||||
},
|
||||
*teleport_dest_order(me, level, other) {
|
||||
// The CC2 green teleporter scheme is:
|
||||
// 1. Use the PRNG to pick another green teleporter
|
||||
@ -1947,9 +1936,6 @@ const TILE_TYPES = {
|
||||
layer: LAYERS.terrain,
|
||||
item_priority: PICKUP_PRIORITIES.always,
|
||||
slide_mode: 'teleport',
|
||||
get_slide_direction(me, level, other) {
|
||||
return other.direction;
|
||||
},
|
||||
allow_player_override: true,
|
||||
*teleport_dest_order(me, level, other) {
|
||||
let exit_direction = other.direction;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user