Move sliding back to arrive time, but force floor bonking to movement time

This commit is contained in:
Eevee (Evelyn Woods) 2020-12-26 03:15:00 -07:00
parent 0bb3f78a33
commit 0500518537
2 changed files with 76 additions and 59 deletions

View File

@ -878,21 +878,24 @@ export class Level extends LevelInterface {
// Actor is allowed to move, so do so // Actor is allowed to move, so do so
let success = this.attempt_step(actor, direction); let success = this.attempt_step(actor, direction);
// FIXME not convinced that ice bonking should actually go here. in cc2 it appears to // CC2 handles bonking for all kinds of sliding here -- bonking on ice causes an immediate
// happen every frame, fwiw, but i'm not sure if that includes frames with forced moves // turnaround, and bonking on an RFF rolls a new direction and tries again
// (though i guess that's impossible) // TODO this assumes the slide comes from the terrain, which is always the case atm
if (! success) { if (! success) {
let terrain = actor.cell.get_terrain(); let terrain = actor.cell.get_terrain();
if (terrain.type.slide_mode === 'ice' && (! actor.ignores(terrain.type.name) || if (terrain && (
(actor.slide_mode && ! actor.ignores(terrain.type.name)) ||
// TODO weird cc2 quirk/bug: ghosts bonk on ice even though they don't slide on it // TODO weird cc2 quirk/bug: ghosts bonk on ice even though they don't slide on it
// FIXME and if they have cleats, they get stuck instead (?!) // FIXME and if they have cleats, they get stuck instead (?!)
(actor.type.name === 'ghost' && actor.cell.get_terrain().type.slide_mode === 'ice'))) (actor.type.name === 'ghost' && terrain.type.slide_mode === 'ice')))
{ {
// Bonk on ice: turn the actor around, consult the tile in case it's an ice // Turn the actor around (so ice corners bonk correctly), pretend they stepped on
// corner, and try again // the tile again (so RFFs roll again), and try moving again
actor.direction = DIRECTIONS[direction].opposite; this.set_actor_direction(actor, DIRECTIONS[direction].opposite);
direction = terrain.type.get_slide_direction(terrain, this, actor); if (terrain.type.on_arrive) {
success = this.attempt_step(actor, direction); terrain.type.on_arrive(terrain, this, actor);
}
success = this.attempt_step(actor, actor.direction);
} }
} }
@ -1083,10 +1086,6 @@ export class Level extends LevelInterface {
// succeed, even if overriding in the same direction we're already moving, that does count // succeed, even if overriding in the same direction we're already moving, that does count
// as an override. // as an override.
let terrain = actor.cell.get_terrain(); let terrain = actor.cell.get_terrain();
let forced_decision;
if (actor.slide_mode) {
forced_decision = terrain.type.get_slide_direction(terrain, this, actor);
}
let may_move = ! forced_only && (! actor.slide_mode || (actor.slide_mode === 'force' && actor.last_move_was_force)); let may_move = ! forced_only && (! actor.slide_mode || (actor.slide_mode === 'force' && actor.last_move_was_force));
let [dir1, dir2] = this._extract_player_directions(input); let [dir1, dir2] = this._extract_player_directions(input);
@ -1116,7 +1115,7 @@ export class Level extends LevelInterface {
if (actor.slide_mode && ! (may_move && dir1)) { if (actor.slide_mode && ! (may_move && dir1)) {
// This is a forced move and we're not overriding it, so we're done // This is a forced move and we're not overriding it, so we're done
actor.decision = forced_decision; actor.decision = actor.direction;
if (actor.slide_mode === 'force') { if (actor.slide_mode === 'force') {
this._set_tile_prop(actor, 'last_move_was_force', true); this._set_tile_prop(actor, 'last_move_was_force', true);
@ -1140,17 +1139,16 @@ export class Level extends LevelInterface {
// one, UNLESS it's blocked AND the other isn't. // one, UNLESS it's blocked AND the other isn't.
// Note that if this is an override, then the forced direction is still used to // Note that if this is an override, then the forced direction is still used to
// interpret our input! // interpret our input!
let facing = forced_decision ?? actor.direction; if (dir1 === actor.direction || dir2 === actor.direction) {
if (dir1 === facing || dir2 === facing) { let other_direction = dir1 === actor.direction ? dir2 : dir1;
let other_direction = dir1 === facing ? dir2 : dir1; let curr_open = try_direction(actor.direction, 'push');
let curr_open = try_direction(facing, 'push');
let other_open = try_direction(other_direction, 'push'); let other_open = try_direction(other_direction, 'push');
if (! curr_open && other_open) { if (! curr_open && other_open) {
actor.decision = other_direction; actor.decision = other_direction;
open = true; open = true;
} }
else { else {
actor.decision = facing; actor.decision = actor.direction;
open = curr_open; open = curr_open;
} }
} }
@ -1184,7 +1182,7 @@ export class Level extends LevelInterface {
// force floor takes priority (and we've already bumped the wall(s)) // force floor takes priority (and we've already bumped the wall(s))
if (actor.slide_mode && ! open) { if (actor.slide_mode && ! open) {
this._set_tile_prop(actor, 'last_move_was_force', true); this._set_tile_prop(actor, 'last_move_was_force', true);
actor.decision = forced_decision; actor.decision = actor.direction;
} }
else { else {
// Otherwise this is 100% a conscious move so we lose our override power next tic // Otherwise this is 100% a conscious move so we lose our override power next tic
@ -1217,7 +1215,7 @@ export class Level extends LevelInterface {
(actor.type.name === 'ghost' && terrain.type.slide_mode === 'ice')) (actor.type.name === 'ghost' && terrain.type.slide_mode === 'ice'))
{ {
// Actors can't make voluntary moves while sliding; they just, ah, slide. // Actors can't make voluntary moves while sliding; they just, ah, slide.
actor.decision = terrain.type.get_slide_direction(terrain, this, actor); actor.decision = actor.direction;
return; return;
} }
if (forced_only) if (forced_only)

View File

@ -7,6 +7,7 @@ function activate_me(me, level) {
function on_ready_force_floor(me, level) { function on_ready_force_floor(me, level) {
// At the start of the level, if there's an actor on a force floor: // At the start of the level, if there's an actor on a force floor:
// - use on_arrive to set the actor's direction
// - set the slide_mode (normally done by the main game loop) // - set the slide_mode (normally done by the main game loop)
// - item bestowal: if they're being pushed into a wall and standing on an item, pick up the // - item bestowal: if they're being pushed into a wall and standing on an item, pick up the
// item, even if they couldn't normally pick items up // item, even if they couldn't normally pick items up
@ -15,6 +16,7 @@ function on_ready_force_floor(me, level) {
if (! actor) if (! actor)
return; return;
me.type.on_arrive(me, level, actor);
if (me.type.slide_mode) { if (me.type.slide_mode) {
actor.slide_mode = me.type.slide_mode; actor.slide_mode = me.type.slide_mode;
} }
@ -663,21 +665,19 @@ const TILE_TYPES = {
ice: { ice: {
draw_layer: DRAW_LAYERS.terrain, draw_layer: DRAW_LAYERS.terrain,
slide_mode: 'ice', slide_mode: 'ice',
get_slide_direction(me, level, other) {
return other.direction;
},
}, },
ice_sw: { ice_sw: {
draw_layer: DRAW_LAYERS.terrain, draw_layer: DRAW_LAYERS.terrain,
thin_walls: new Set(['south', 'west']), thin_walls: new Set(['south', 'west']),
slide_mode: 'ice', slide_mode: 'ice',
blocks_leaving: blocks_leaving_thin_walls, blocks_leaving: blocks_leaving_thin_walls,
get_slide_direction(me, level, other) { on_arrive(me, level, other) {
if (other.direction === 'south') if (other.direction === 'south') {
return 'east'; level.set_actor_direction(other, 'east');
if (other.direction === 'west') }
return 'north'; else if (other.direction === 'west') {
return other.direction; level.set_actor_direction(other, 'north');
}
}, },
}, },
ice_nw: { ice_nw: {
@ -685,12 +685,13 @@ const TILE_TYPES = {
thin_walls: new Set(['north', 'west']), thin_walls: new Set(['north', 'west']),
slide_mode: 'ice', slide_mode: 'ice',
blocks_leaving: blocks_leaving_thin_walls, blocks_leaving: blocks_leaving_thin_walls,
get_slide_direction(me, level, other) { on_arrive(me, level, other) {
if (other.direction === 'north') if (other.direction === 'north') {
return 'east'; level.set_actor_direction(other, 'east');
if (other.direction === 'west') }
return 'south'; else if (other.direction === 'west') {
return other.direction; level.set_actor_direction(other, 'south');
}
}, },
}, },
ice_ne: { ice_ne: {
@ -698,12 +699,13 @@ const TILE_TYPES = {
thin_walls: new Set(['north', 'east']), thin_walls: new Set(['north', 'east']),
slide_mode: 'ice', slide_mode: 'ice',
blocks_leaving: blocks_leaving_thin_walls, blocks_leaving: blocks_leaving_thin_walls,
get_slide_direction(me, level, other) { on_arrive(me, level, other) {
if (other.direction === 'north') if (other.direction === 'north') {
return 'west'; level.set_actor_direction(other, 'west');
if (other.direction === 'east') }
return 'south'; else if (other.direction === 'east') {
return other.direction; level.set_actor_direction(other, 'south');
}
}, },
}, },
ice_se: { ice_se: {
@ -711,23 +713,28 @@ const TILE_TYPES = {
thin_walls: new Set(['south', 'east']), thin_walls: new Set(['south', 'east']),
slide_mode: 'ice', slide_mode: 'ice',
blocks_leaving: blocks_leaving_thin_walls, blocks_leaving: blocks_leaving_thin_walls,
get_slide_direction(me, level, other) { on_arrive(me, level, other) {
if (other.direction === 'south') if (other.direction === 'south') {
return 'west'; level.set_actor_direction(other, 'west');
if (other.direction === 'east') }
return 'north'; else if (other.direction === 'east') {
return other.direction; level.set_actor_direction(other, 'north');
}
}, },
}, },
force_floor_n: { force_floor_n: {
draw_layer: DRAW_LAYERS.terrain, draw_layer: DRAW_LAYERS.terrain,
slide_mode: 'force', slide_mode: 'force',
on_ready: on_ready_force_floor, on_ready: on_ready_force_floor,
get_slide_direction(me, level, other) { on_arrive(me, level, other) {
return 'north'; level.set_actor_direction(other, 'north');
}, },
activate(me, level) { activate(me, level) {
level.transmute_tile(me, 'force_floor_s'); level.transmute_tile(me, 'force_floor_s');
let actor = me.cell.get_actor();
if (actor && actor.movement_cooldown <= 0) {
this.on_arrive(me, level, actor);
}
}, },
on_gray_button: activate_me, on_gray_button: activate_me,
on_power: activate_me, on_power: activate_me,
@ -736,11 +743,15 @@ const TILE_TYPES = {
draw_layer: DRAW_LAYERS.terrain, draw_layer: DRAW_LAYERS.terrain,
slide_mode: 'force', slide_mode: 'force',
on_ready: on_ready_force_floor, on_ready: on_ready_force_floor,
get_slide_direction(me, level, other) { on_arrive(me, level, other) {
return 'east'; level.set_actor_direction(other, 'east');
}, },
activate(me, level) { activate(me, level) {
level.transmute_tile(me, 'force_floor_w'); level.transmute_tile(me, 'force_floor_w');
let actor = me.cell.get_actor();
if (actor && actor.movement_cooldown <= 0) {
this.on_arrive(me, level, actor);
}
}, },
on_gray_button: activate_me, on_gray_button: activate_me,
on_power: activate_me, on_power: activate_me,
@ -749,11 +760,15 @@ const TILE_TYPES = {
draw_layer: DRAW_LAYERS.terrain, draw_layer: DRAW_LAYERS.terrain,
slide_mode: 'force', slide_mode: 'force',
on_ready: on_ready_force_floor, on_ready: on_ready_force_floor,
get_slide_direction(me, level, other) { on_arrive(me, level, other) {
return 'south'; level.set_actor_direction(other, 'south');
}, },
activate(me, level) { activate(me, level) {
level.transmute_tile(me, 'force_floor_n'); level.transmute_tile(me, 'force_floor_n');
let actor = me.cell.get_actor();
if (actor && actor.movement_cooldown <= 0) {
this.on_arrive(me, level, actor);
}
}, },
on_gray_button: activate_me, on_gray_button: activate_me,
on_power: activate_me, on_power: activate_me,
@ -762,11 +777,15 @@ const TILE_TYPES = {
draw_layer: DRAW_LAYERS.terrain, draw_layer: DRAW_LAYERS.terrain,
slide_mode: 'force', slide_mode: 'force',
on_ready: on_ready_force_floor, on_ready: on_ready_force_floor,
get_slide_direction(me, level, other) { on_arrive(me, level, other) {
return 'west'; level.set_actor_direction(other, 'west');
}, },
activate(me, level) { activate(me, level) {
level.transmute_tile(me, 'force_floor_e'); level.transmute_tile(me, 'force_floor_e');
let actor = me.cell.get_actor();
if (actor && actor.movement_cooldown <= 0) {
this.on_arrive(me, level, actor);
}
}, },
on_gray_button: activate_me, on_gray_button: activate_me,
on_power: activate_me, on_power: activate_me,
@ -776,8 +795,8 @@ const TILE_TYPES = {
slide_mode: 'force', slide_mode: 'force',
on_ready: on_ready_force_floor, on_ready: on_ready_force_floor,
// TODO ms: this is random, and an acting wall to monsters (!) // TODO ms: this is random, and an acting wall to monsters (!)
get_slide_direction(me, level, other) { on_arrive(me, level, other) {
return level.get_force_floor_direction(); level.set_actor_direction(other, level.get_force_floor_direction());
}, },
}, },
slime: { slime: {