Fix rendering of the moment of death

Finally!  With the help of several mildly unpleasant hacks, the game now
draws as if a monster killing the player were walking onto her.
This commit is contained in:
Eevee (Evelyn Woods) 2024-05-05 15:32:56 -06:00
parent 4527eb972e
commit 3f6278f281

View File

@ -59,6 +59,11 @@ export class Tile {
if (this.type.layer === LAYERS.item && this.cell.get_item_mod()) if (this.type.layer === LAYERS.item && this.cell.get_item_mod())
return false; return false;
// Extremely niche interaction: monsters can enter cells with items by killing a player
// who's revived by an ankh
if (this.type.is_item && other.temp_ignore_item_collision)
return false;
if (level.compat.monsters_ignore_keys && this.type.is_key) if (level.compat.monsters_ignore_keys && this.type.is_key)
// MS: Monsters are never blocked by keys // MS: Monsters are never blocked by keys
return false; return false;
@ -180,6 +185,9 @@ Object.assign(Tile.prototype, {
is_pending_slide: false, is_pending_slide: false,
can_override_slide: false, can_override_slide: false,
pending_push: null, pending_push: null,
destination_cell: null,
is_making_failure_move: false,
temp_ignore_item_collision: false,
}); });
@ -849,6 +857,10 @@ export class Level extends LevelInterface {
if (actor.destination_cell) { if (actor.destination_cell) {
this._set_tile_prop(actor, 'destination_cell', null); this._set_tile_prop(actor, 'destination_cell', null);
} }
// This is only used for killing an ankh'd player on an item
if (actor.temp_ignore_item_collision) {
this._set_tile_prop(actor, 'temp_ignore_item_collision', false);
}
if (! actor.cell) if (! actor.cell)
continue; continue;
@ -966,7 +978,7 @@ export class Level extends LevelInterface {
} }
// Track when the player is blocked for visual effect // Track when the player is blocked for visual effect
if (actor === this.player && ! success) { if (actor === this.player && ! success && ! actor.is_making_failure_move) {
this._set_tile_prop(actor, 'is_blocked', true); this._set_tile_prop(actor, 'is_blocked', true);
if (actor.last_blocked_direction !== actor.direction) { if (actor.last_blocked_direction !== actor.direction) {
// This is only used for checking when to play the mmf sound, doesn't need undoing; // This is only used for checking when to play the mmf sound, doesn't need undoing;
@ -1082,8 +1094,17 @@ export class Level extends LevelInterface {
} }
_do_actor_cooldown(actor, cooldown = 3) { _do_actor_cooldown(actor, cooldown = 3) {
if (actor.movement_cooldown <= 0) if (actor.movement_cooldown <= 0) {
if (actor.is_making_failure_move) {
// For actors that are causing the game to end with an attempted move, and which
// aren't actually moving, give them a cooldown /as if/ they were moving into the
// deadly cell (which should have already been fudged with .destination_cell)
let speed = actor.type.movement_speed * 3;
this._set_tile_prop(actor, 'movement_cooldown', speed - cooldown);
this._set_tile_prop(actor, 'movement_speed', speed);
}
return; return;
}
if (actor.last_extra_cooldown_tic === this.tic_counter) if (actor.last_extra_cooldown_tic === this.tic_counter)
return; return;
@ -1636,7 +1657,25 @@ export class Level extends LevelInterface {
// happen at decision time thanks to no_early_push // happen at decision time thanks to no_early_push
(! this.compat.player_safe_at_decision_time || push_mode === 'push')) (! this.compat.player_safe_at_decision_time || push_mode === 'push'))
{ {
this._check_for_player_death(actor, tile); if (this._check_for_player_death(actor, tile)) {
// Actors can't move into each other's cells, so monsters aren't allowed to
// actually step on the player (or vice versa) -- however, to make it LOOK like
// that's what's happening in the final frame, use the 'destination_cell'
// (originally meant for teleporters) property to pretend this movement happens.
// But first -- this implies that if a player is standing on an item, and a
// monster kills the player, AND the player has an inscribed ankh, then the
// monster should be able to continue on into the cell despite the item! So
// let's make that happen too.
if (tile.type.is_real_player && tile.cell !== cell) {
this._set_tile_prop(actor, 'temp_ignore_item_collision', true);
return true;
}
else {
this._set_tile_prop(actor, 'previous_cell', actor.cell);
this._set_tile_prop(actor, 'destination_cell', cell);
this._set_tile_prop(actor, 'is_making_failure_move', true);
}
}
} }
if (this.compat.allow_pushing_blocks_off_faux_walls && if (this.compat.allow_pushing_blocks_off_faux_walls &&