Global Cyclers can cycle actors now too

This commit is contained in:
Timothy Stiles 2021-02-07 23:19:33 +11:00
parent f79a8cc259
commit 5cc5370817
4 changed files with 87 additions and 16 deletions

View File

@ -1566,7 +1566,7 @@ export class Level extends LevelInterface {
let original_cell = actor.cell;
// Physically remove the actor first, so that it won't get in the way of e.g. a splash
// spawned from stepping off of a lilypad
this.remove_tile(actor);
this.remove_tile(actor, true);
// Announce we're leaving, for the handful of tiles that care about it
for (let tile of original_cell) {
@ -1796,7 +1796,7 @@ export class Level extends LevelInterface {
}
// Now physically move the actor, but their movement waits until next decision phase
this.remove_tile(actor);
this.remove_tile(actor, true);
this.add_tile(actor, dest.cell);
}
@ -1874,7 +1874,7 @@ export class Level extends LevelInterface {
// already in this cell's actor layer. But we also know for sure that there's no
// item in this cell, so we'll cheat a little: remove the dropping actor, set the
// item moving, then put the dropping actor back before anyone notices.
this.remove_tile(dropping_actor);
this.remove_tile(dropping_actor, true);
this.add_tile(tile, cell);
if (! this.attempt_out_of_turn_step(tile, dropping_actor.direction)) {
// It was unable to move, so there's nothing we can do but destroy it
@ -2279,7 +2279,7 @@ export class Level extends LevelInterface {
player = this.player;
}
if (this.take_tool_from_actor(player, 'halo')) {
if (player != null && reason !== 'nonexistence' && this.take_tool_from_actor(player, 'halo')) {
this.sfx.play_once('revive');
if (reason === 'time')
{
@ -2301,11 +2301,11 @@ export class Level extends LevelInterface {
this._push_pending_undo(() => {
this.fail_reason = null;
player.fail_reason = null;
if (player != null) { player.fail_reason = null; }
});
this.state = 'failure';
this.fail_reason = reason;
player.fail_reason = reason;
if (player != null) { player.fail_reason = reason; }
}
win() {
@ -2346,7 +2346,12 @@ export class Level extends LevelInterface {
// have things stacked in a weird order though
// TODO would be nice to make these not be closures but order matters much more here
remove_tile(tile) {
remove_tile(tile, temporary = false) {
if (!temporary && tile == this.player)
{
this.fail('nonexistence');
return;
}
let cell = tile.cell;
cell._remove(tile);
this._push_pending_undo(() => cell._add(tile));

View File

@ -2184,7 +2184,7 @@ const EDITOR_TILE_DESCRIPTIONS = {
},
global_cycler: {
name: "Global Cycler",
desc: "When activated, every terrain/item on the surrounding four tiles in the entire level becomes the terrain/item one clockwise. Adjacent tiles with a 'no sign' on them are ignored. Two of the same tile in a row mean that tile will not be transformed and will stay as-is. Tiles next to Global Cyclers are not transformed.",
desc: "When activated, every terrain/item/actor on the surrounding four tiles in the entire level becomes the terrain/item/actor one clockwise. Adjacent tiles with a 'no sign' on them are ignored. Two of the same tile in a row mean that tile will not be transformed and will stay as-is. Actors facing different directions will cause a relative direction change. Tiles next to Global Cyclers are not transformed.",
},
halo: {
name: "Halo",

View File

@ -85,6 +85,12 @@ const OBITUARIES = {
"you're feeling quite alarmed",
//"
],
nonexistence: [
"I guess you don't exist",
"critical existence failure",
"no place to be",
"on a trip to nowhere",
],
generic: [
"you had a bad time",
],

View File

@ -1718,6 +1718,7 @@ const TILE_TYPES = {
layer: LAYERS.terrain,
blocks_collision: COLLISION.real_player | COLLISION.block_cc1 | COLLISION.monster_solid,
activate(me, level) {
//learn about surrounding tiles
//some logic: we ignore tiles with a 'no sign' on them. for items, we ignore itemless tiles. if the same terrain/item is twice in a row, it stays the same. tiles next to global cycles aren't touched.
let cells = [level.cell(
@ -1732,8 +1733,10 @@ const TILE_TYPES = {
level.cell(
me.cell.x - 1,
me.cell.y + 0)].filter(x => x != null && x.get_item_mod()?.type.name != 'no_sign');
let terrains = cells.map(x => x.get_terrain().type.name).filter(x => x != 'global_cycler');
let items = cells.map(x => x.get_item()?.type.name ?? null).filter(x => x != null);
let actors = cells.map(x => x.get_actor()).filter(x => x != null);
//globally cycle terrain
if (new Set(terrains).size > 1)
@ -1784,17 +1787,20 @@ const TILE_TYPES = {
for (var j = 0; j < level.height; ++j)
{
let target_safe = [level.cell(
(i + 0 + level.width) % level.width,
(j - 1 + level.height) % level.height),
i + 0,
j + 0),
level.cell(
(i + 1 + level.width) % level.width,
(j + 0 + level.height) % level.height),
i + 0,
j - 1),
level.cell(
(i + 0 + level.width) % level.width,
(j + 1 + level.height) % level.height),
i + 1,
j + 0),
level.cell(
(i- 1 + level.width) % level.width,
(j + 0 + level.height) % level.height)].filter(x => x.get_terrain().type.name == 'global_cycler');
i + 0,
j + 1),
level.cell(
i - 1,
j + 0)].filter(x => x != null && x.get_terrain().type.name == 'global_cycler');
if (target_safe.length > 0)
{
continue;
@ -1816,6 +1822,60 @@ const TILE_TYPES = {
}
}
}
//globally cycle... actors???
//intended logic: if the same monster exists twice in a row we rotate it it by the relative direction (left, right, flip or do nothing). if it's two different monsters, we do that AND transmute.
//this code is slightly different from the previous two blocks!
if (actors.length > 1)
{
for (let a = level.actors.length - 1; a >= 0; a--)
{
let thing = level.actors[a];
let i = thing.cell.x;
let j = thing.cell.y;
let target_safe = [level.cell(
i + 0,
j + 0),
level.cell(
i + 0,
j - 1),
level.cell(
i + 1,
j + 0),
level.cell(
i + 0,
j + 1),
level.cell(
i - 1,
j + 0)].filter(x => x != null && x.get_terrain().type.name == 'global_cycler');
if (target_safe.length > 0)
{
continue;
}
let things = actors;
for (var k = 0; k < things.length; ++k)
{
if (thing.type.name == things[k].type.name)
{
let turn = ['right', 'left', 'opposite'].filter(t => {
return DIRECTIONS[things[k].direction][t] === things[(k + 1) % things.length].direction;
})[0]
if (turn !== undefined)
{
thing.direction = DIRECTIONS[thing.direction][turn];
}
if (thing.type.name != things[(k - 1 + things.length) % things.length].type.name)
{
level.transmute_tile(thing, things[(k + 1) % things.length].type.name);
}
break;
}
}
}
}
},
// Also activates on rising pulse or gray button
on_power(me, level) {