Split teleporting into its own pass, like Lynx
This commit is contained in:
parent
93954135d2
commit
0f5b8098f6
128
js/game.js
128
js/game.js
@ -587,6 +587,19 @@ export class Level {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mini extra pass: deal with teleporting separately. Otherwise, actors may have been in
|
||||||
|
// the way of the teleporter but finished moving away during the above loop; this is
|
||||||
|
// particularly bad when it happens with a block you're pushing.
|
||||||
|
for (let i = this.actors.length - 1; i >= 0; i--) {
|
||||||
|
let actor = this.actors[i];
|
||||||
|
if (! actor.cell)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (actor.just_stepped_on_teleporter) {
|
||||||
|
this.attempt_teleport(actor);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
finish_tic(p1_actions) {
|
finish_tic(p1_actions) {
|
||||||
@ -1087,7 +1100,6 @@ export class Level {
|
|||||||
|
|
||||||
// Step on every tile in a cell we just arrived in
|
// Step on every tile in a cell we just arrived in
|
||||||
step_on_cell(actor, cell) {
|
step_on_cell(actor, cell) {
|
||||||
let teleporter;
|
|
||||||
// Step on topmost things first -- notably, it's safe to step on water with flippers on top
|
// Step on topmost things first -- notably, it's safe to step on water with flippers on top
|
||||||
for (let tile of Array.from(cell).reverse()) {
|
for (let tile of Array.from(cell).reverse()) {
|
||||||
if (tile === actor)
|
if (tile === actor)
|
||||||
@ -1108,76 +1120,80 @@ export class Level {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tile.type.teleport_dest_order) {
|
else if (tile.type.teleport_dest_order) {
|
||||||
teleporter = tile;
|
// This is used by an extra pass just after our caller, so it doesn't need to undo
|
||||||
|
actor.just_stepped_on_teleporter = tile;
|
||||||
}
|
}
|
||||||
else if (tile.type.on_arrive) {
|
else if (tile.type.on_arrive) {
|
||||||
tile.type.on_arrive(tile, this, actor);
|
tile.type.on_arrive(tile, this, actor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
attempt_teleport(actor) {
|
||||||
|
let teleporter = actor.just_stepped_on_teleporter;
|
||||||
|
actor.just_stepped_on_teleporter = null;
|
||||||
|
|
||||||
// Handle teleporting, now that the dust has cleared
|
// Handle teleporting, now that the dust has cleared
|
||||||
// FIXME something funny happening here, your input isn't ignored while walking out of it?
|
// FIXME something funny happening here, your input isn't ignored while walking out of it?
|
||||||
if (teleporter) {
|
let original_direction = actor.direction;
|
||||||
let original_direction = actor.direction;
|
let success = false;
|
||||||
let success = false;
|
for (let dest of teleporter.type.teleport_dest_order(teleporter, this, actor)) {
|
||||||
for (let dest of teleporter.type.teleport_dest_order(teleporter, this, actor)) {
|
// Teleporters already containing an actor are blocked and unusable
|
||||||
// Teleporters already containing an actor are blocked and unusable
|
if (dest.cell.some(tile => tile.type.is_actor && tile !== actor))
|
||||||
if (dest.cell.some(tile => tile.type.is_actor && tile !== actor))
|
continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
// Physically move the actor to the new teleporter
|
// Physically move the actor to the new teleporter
|
||||||
// XXX lynx treats this as a slide and does it in a pass in the main loop
|
// XXX lynx treats this as a slide and does it in a pass in the main loop
|
||||||
// XXX not especially undo-efficient
|
// XXX not especially undo-efficient
|
||||||
this.remove_tile(actor);
|
this.remove_tile(actor);
|
||||||
this.add_tile(actor, dest.cell);
|
this.add_tile(actor, dest.cell);
|
||||||
|
|
||||||
// Red and green teleporters attempt to spit you out in every direction before
|
// Red and green teleporters attempt to spit you out in every direction before
|
||||||
// giving up on a destination (but not if you return to the original).
|
// giving up on a destination (but not if you return to the original).
|
||||||
// Note that we use actor.direction here (rather than original_direction) because
|
// Note that we use actor.direction here (rather than original_direction) because
|
||||||
// green teleporters modify it in teleport_dest_order, to randomize the exit
|
// green teleporters modify it in teleport_dest_order, to randomize the exit
|
||||||
// direction
|
// direction
|
||||||
let direction = actor.direction;
|
let direction = actor.direction;
|
||||||
let num_directions = 1;
|
let num_directions = 1;
|
||||||
if (teleporter.type.teleport_try_all_directions && dest !== teleporter) {
|
if (teleporter.type.teleport_try_all_directions && dest !== teleporter) {
|
||||||
num_directions = 4;
|
num_directions = 4;
|
||||||
}
|
}
|
||||||
// FIXME bleugh hardcode
|
// FIXME bleugh hardcode
|
||||||
if (dest === teleporter && teleporter.type.name === 'teleport_yellow') {
|
if (dest === teleporter && teleporter.type.name === 'teleport_yellow') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < num_directions; i++) {
|
||||||
|
if (this.attempt_out_of_turn_step(actor, direction)) {
|
||||||
|
success = true;
|
||||||
|
// Sound plays from the origin cell simply because that's where the sfx player
|
||||||
|
// thinks the player is currently; position isn't updated til next turn
|
||||||
|
this.sfx.play_once('teleport', teleporter.cell);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for (let i = 0; i < num_directions; i++) {
|
else {
|
||||||
if (this.attempt_out_of_turn_step(actor, direction)) {
|
direction = DIRECTIONS[direction].right;
|
||||||
success = true;
|
|
||||||
// Sound plays from the origin cell simply because that's where the sfx player
|
|
||||||
// thinks the player is currently; position isn't updated til next turn
|
|
||||||
this.sfx.play_once('teleport', teleporter.cell);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
direction = DIRECTIONS[direction].right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (num_directions === 4) {
|
|
||||||
// Restore our original facing before continuing
|
|
||||||
// (For red teleports, we try every possible destination in our original
|
|
||||||
// movement direction, so this is correct. For green teleports, we only try one
|
|
||||||
// destination and then fall back to walking through the source in our original
|
|
||||||
// movement direction, so this is still correct.)
|
|
||||||
this.set_actor_direction(actor, original_direction);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! success && actor.type.has_inventory && teleporter.type.name === 'teleport_yellow') {
|
if (success) {
|
||||||
// Super duper special yellow teleporter behavior: you pick it the fuck up
|
break;
|
||||||
// FIXME not if there's only one in the level?
|
}
|
||||||
this.attempt_take(actor, teleporter);
|
else if (num_directions === 4) {
|
||||||
if (actor === this.player) {
|
// Restore our original facing before continuing
|
||||||
this.sfx.play_once('get-tool', teleporter.cell);
|
// (For red teleports, we try every possible destination in our original
|
||||||
}
|
// movement direction, so this is correct. For green teleports, we only try one
|
||||||
|
// destination and then fall back to walking through the source in our original
|
||||||
|
// movement direction, so this is still correct.)
|
||||||
|
this.set_actor_direction(actor, original_direction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! success && actor.type.has_inventory && teleporter.type.name === 'teleport_yellow') {
|
||||||
|
// Super duper special yellow teleporter behavior: you pick it the fuck up
|
||||||
|
// FIXME not if there's only one in the level?
|
||||||
|
this.attempt_take(actor, teleporter);
|
||||||
|
if (actor === this.player) {
|
||||||
|
this.sfx.play_once('get-tool', teleporter.cell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user