Emulate an obscure CC2 bug when selecting a green teleport destination

This commit is contained in:
Eevee (Evelyn Woods) 2021-05-08 17:13:48 -06:00
parent 8efa3a572a
commit eebe8b9581
2 changed files with 16 additions and 6 deletions

View File

@ -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 // 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? // the name is the same?
blocks(other, direction, level) { 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 // 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()) if (this.type.layer === LAYERS.item && this.cell.get_item_mod())
return false; return false;
@ -2037,8 +2042,7 @@ export class Level extends LevelInterface {
let dest, direction; let dest, direction;
for ([dest, direction] of teleporter.type.teleport_dest_order(teleporter, this, actor)) { for ([dest, direction] 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
// FIXME should check collision? otherwise this catches non-blocking vfx... if (dest !== teleporter && dest.cell.get_actor())
if (dest.cell.some(tile => tile && tile.type.is_actor && tile !== actor && ! tile.type.ttl))
continue; continue;
// 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

View File

@ -1914,14 +1914,20 @@ const TILE_TYPES = {
// available teleporters are between the entry and chosen exit, they'll never be tried. // available teleporters are between the entry and chosen exit, they'll never be tried.
// TODO that sucks actually; compat option? // TODO that sucks actually; compat option?
// The iterator starts on the /next/ teleporter, so there's an implicit +1 here. The -1 // The iterator starts on the /next/ teleporter, so the origin is last, and we can index
// avoids spitting us back out of the same teleporter, which will be last in the list // from zero to the second-to-last element.
let start_index = level.prng() % (all.length - 1); let start_index = level.prng() % (all.length - 1);
// Also pick the initial exit direction // Also pick the initial exit direction
let exit_direction = DIRECTION_ORDER[level.prng() % 4]; let exit_direction = DIRECTION_ORDER[level.prng() % 4];
for (let index = start_index; index < all.length - 1; index++) { // Due to what appears to be a bug, CC2 picks a teleporter index from all available
let target = all[index]; // 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 // Green teleporters allow exiting in any direction, similar to red
yield [target, exit_direction]; yield [target, exit_direction];