Fix undo failure after being killed by a cloner; ensure the failure reason is assigned to the right player
This commit is contained in:
parent
560fd93c8b
commit
30c17c0c8b
16
js/game.js
16
js/game.js
@ -1560,15 +1560,15 @@ export class Level extends LevelInterface {
|
|||||||
// Helmet disables this, do nothing
|
// Helmet disables this, do nothing
|
||||||
}
|
}
|
||||||
else if (actor.type.is_real_player && tile.type.is_monster) {
|
else if (actor.type.is_real_player && tile.type.is_monster) {
|
||||||
this.fail(tile.type.name);
|
this.fail(tile.type.name, actor);
|
||||||
}
|
}
|
||||||
else if (actor.type.is_monster && tile.type.is_real_player) {
|
else if (actor.type.is_monster && tile.type.is_real_player) {
|
||||||
this.fail(actor.type.name);
|
this.fail(actor.type.name, tile);
|
||||||
}
|
}
|
||||||
else if (actor.type.is_block && tile.type.is_real_player && ! actor.is_pulled) {
|
else if (actor.type.is_block && tile.type.is_real_player && ! actor.is_pulled) {
|
||||||
// Note that blocks squish players if they move for ANY reason, even if pushed by
|
// Note that blocks squish players if they move for ANY reason, even if pushed by
|
||||||
// another player! The only exception is being pulled
|
// another player! The only exception is being pulled
|
||||||
this.fail('squished');
|
this.fail('squished', tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tile.type.on_approach) {
|
if (tile.type.on_approach) {
|
||||||
@ -2200,7 +2200,7 @@ export class Level extends LevelInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fail(reason) {
|
fail(reason, player = null) {
|
||||||
if (this.state !== 'playing')
|
if (this.state !== 'playing')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -2211,13 +2211,17 @@ export class Level extends LevelInterface {
|
|||||||
this.sfx.play_once('lose');
|
this.sfx.play_once('lose');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (player === null) {
|
||||||
|
player = this.player;
|
||||||
|
}
|
||||||
|
|
||||||
this._push_pending_undo(() => {
|
this._push_pending_undo(() => {
|
||||||
this.fail_reason = null;
|
this.fail_reason = null;
|
||||||
this.player.fail_reason = null;
|
player.fail_reason = null;
|
||||||
});
|
});
|
||||||
this.state = 'failure';
|
this.state = 'failure';
|
||||||
this.fail_reason = reason;
|
this.fail_reason = reason;
|
||||||
this.player.fail_reason = reason;
|
player.fail_reason = reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
win() {
|
win() {
|
||||||
|
|||||||
@ -641,7 +641,7 @@ const TILE_TYPES = {
|
|||||||
level.sfx.play_once('splash', me.cell);
|
level.sfx.play_once('splash', me.cell);
|
||||||
}
|
}
|
||||||
else if (other.type.is_real_player) {
|
else if (other.type.is_real_player) {
|
||||||
level.fail('burned');
|
level.fail('burned', other);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
level.transmute_tile(other, 'explosion');
|
level.transmute_tile(other, 'explosion');
|
||||||
@ -672,7 +672,7 @@ const TILE_TYPES = {
|
|||||||
level.transmute_tile(me, 'ice');
|
level.transmute_tile(me, 'ice');
|
||||||
}
|
}
|
||||||
else if (other.type.is_real_player) {
|
else if (other.type.is_real_player) {
|
||||||
level.fail('drowned');
|
level.fail('drowned', other);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
level.transmute_tile(other, 'splash');
|
level.transmute_tile(other, 'splash');
|
||||||
@ -863,7 +863,7 @@ const TILE_TYPES = {
|
|||||||
level.transmute_tile(me, 'floor');
|
level.transmute_tile(me, 'floor');
|
||||||
}
|
}
|
||||||
else if (other.type.is_real_player) {
|
else if (other.type.is_real_player) {
|
||||||
level.fail('slimed');
|
level.fail('slimed', other);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
level.transmute_tile(other, 'splash_slime');
|
level.transmute_tile(other, 'splash_slime');
|
||||||
@ -885,7 +885,7 @@ const TILE_TYPES = {
|
|||||||
on_arrive(me, level, other) {
|
on_arrive(me, level, other) {
|
||||||
level.remove_tile(me);
|
level.remove_tile(me);
|
||||||
if (other.type.is_real_player) {
|
if (other.type.is_real_player) {
|
||||||
level.fail('exploded');
|
level.fail('exploded', other);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
level.sfx.play_once('bomb', me.cell);
|
level.sfx.play_once('bomb', me.cell);
|
||||||
@ -1053,7 +1053,7 @@ const TILE_TYPES = {
|
|||||||
on_arrive(me, level, other) {
|
on_arrive(me, level, other) {
|
||||||
level.remove_tile(me);
|
level.remove_tile(me);
|
||||||
if (other.type.is_real_player) {
|
if (other.type.is_real_player) {
|
||||||
level.fail('exploded');
|
level.fail('exploded', other);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
level.sfx.play_once('bomb', me.cell);
|
level.sfx.play_once('bomb', me.cell);
|
||||||
@ -1110,6 +1110,14 @@ const TILE_TYPES = {
|
|||||||
// Wire activation allows the cloner to try every direction, searching clockwise
|
// Wire activation allows the cloner to try every direction, searching clockwise
|
||||||
for (let i = 0; i < (aggressive ? 4 : 1); i++) {
|
for (let i = 0; i < (aggressive ? 4 : 1); i++) {
|
||||||
if (level.attempt_out_of_turn_step(actor, direction)) {
|
if (level.attempt_out_of_turn_step(actor, direction)) {
|
||||||
|
// Surprising edge case: if the actor immediately killed the player, do NOT
|
||||||
|
// spawn a new template, since the move was actually aborted
|
||||||
|
// FIXME this is inconsistent. the move was aborted because of an emergency
|
||||||
|
// failure handling case in move_to, but that doesn't make the step count as a
|
||||||
|
// failure. would this be fixed by making the player block all other actors?
|
||||||
|
if (level.state === 'failure')
|
||||||
|
break;
|
||||||
|
|
||||||
// FIXME add this underneath, just above the cloner, so the new actor is on top
|
// FIXME add this underneath, just above the cloner, so the new actor is on top
|
||||||
let new_template = new actor.constructor(type, direction);
|
let new_template = new actor.constructor(type, direction);
|
||||||
// TODO maybe make a type method for this
|
// TODO maybe make a type method for this
|
||||||
@ -1437,7 +1445,7 @@ const TILE_TYPES = {
|
|||||||
// TODO would be neat if this understood "ignores anything with fire immunity" but that
|
// TODO would be neat if this understood "ignores anything with fire immunity" but that
|
||||||
// might be a bit too high-level for this game
|
// might be a bit too high-level for this game
|
||||||
if (actor.type.is_real_player) {
|
if (actor.type.is_real_player) {
|
||||||
level.fail('burned');
|
level.fail('burned', actor);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// TODO should this play a sound?
|
// TODO should this play a sound?
|
||||||
@ -2272,7 +2280,7 @@ const TILE_TYPES = {
|
|||||||
else if (tile.type.is_real_player) {
|
else if (tile.type.is_real_player) {
|
||||||
// TODO it would be nice if i didn't have to special-case this every
|
// TODO it would be nice if i didn't have to special-case this every
|
||||||
// time
|
// time
|
||||||
level.fail(me.type.name);
|
level.fail(me.type.name, tile);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Everything else is destroyed
|
// Everything else is destroyed
|
||||||
@ -2347,7 +2355,7 @@ const TILE_TYPES = {
|
|||||||
if (me.cell.has('cloner'))
|
if (me.cell.has('cloner'))
|
||||||
return;
|
return;
|
||||||
if (other.type.is_real_player) {
|
if (other.type.is_real_player) {
|
||||||
level.fail(me.type.name);
|
level.fail(me.type.name, other);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
level.transmute_tile(other, 'explosion');
|
level.transmute_tile(other, 'explosion');
|
||||||
@ -2359,7 +2367,7 @@ const TILE_TYPES = {
|
|||||||
// Blow up anything we run into
|
// Blow up anything we run into
|
||||||
if (obstacle && obstacle.type.is_actor) {
|
if (obstacle && obstacle.type.is_actor) {
|
||||||
if (obstacle.type.is_real_player) {
|
if (obstacle.type.is_real_player) {
|
||||||
level.fail(me.type.name);
|
level.fail(me.type.name, obstacle);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
level.transmute_tile(obstacle, 'explosion');
|
level.transmute_tile(obstacle, 'explosion');
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user