diff --git a/js/game.js b/js/game.js index b28ac55..b4e9a85 100644 --- a/js/game.js +++ b/js/game.js @@ -55,6 +55,11 @@ export class Tile { // TODO don't love that the arg order is different here vs tile type, but also don't love that // the name is the same? blocks(other, direction, level) { + // This can happen occasionally, like when testing teleports, where the actor's movement is + // being tested from a cell it's not actually in + if (this === other) + return false; + // Special case: item layer collision is ignored if the cell has an item mod if (this.type.layer === LAYERS.item && this.cell.get_item_mod()) return false; @@ -2037,8 +2042,7 @@ export class Level extends LevelInterface { let dest, direction; for ([dest, direction] of teleporter.type.teleport_dest_order(teleporter, this, actor)) { // Teleporters already containing an actor are blocked and unusable - // FIXME should check collision? otherwise this catches non-blocking vfx... - if (dest.cell.some(tile => tile && tile.type.is_actor && tile !== actor && ! tile.type.ttl)) + if (dest !== teleporter && dest.cell.get_actor()) continue; // XXX lynx treats this as a slide and does it in a pass in the main loop diff --git a/js/tiletypes.js b/js/tiletypes.js index ed5bd7c..a6c1f77 100644 --- a/js/tiletypes.js +++ b/js/tiletypes.js @@ -1914,14 +1914,20 @@ const TILE_TYPES = { // available teleporters are between the entry and chosen exit, they'll never be tried. // TODO that sucks actually; compat option? - // The iterator starts on the /next/ teleporter, so there's an implicit +1 here. The -1 - // avoids spitting us back out of the same teleporter, which will be last in the list + // The iterator starts on the /next/ teleporter, so the origin is last, and we can index + // from zero to the second-to-last element. let start_index = level.prng() % (all.length - 1); // Also pick the initial exit direction let exit_direction = DIRECTION_ORDER[level.prng() % 4]; - for (let index = start_index; index < all.length - 1; index++) { - let target = all[index]; + // Due to what appears to be a bug, CC2 picks a teleporter index from all available + // ones, but then only iterates over "unclogged" ones (those without actors on them) to + // find that particular teleporter. + let candidates = all.filter(tile => tile === me || ! tile.cell.get_actor()); + start_index %= candidates.length; + + for (let index = start_index; index < candidates.length - 1; index++) { + let target = candidates[index]; // Green teleporters allow exiting in any direction, similar to red yield [target, exit_direction];