diff --git a/js/game.js b/js/game.js index fa0d5c2..fdcb799 100644 --- a/js/game.js +++ b/js/game.js @@ -52,6 +52,8 @@ export class Tile { // Extremely awkward special case: items don't block monsters if the cell also contains an // item modifier (i.e. "no" sign) or a real player // TODO would love to get this outta here + // FIXME i think this can be removed if monster/player interaction stops being a literal + // collision and starts being a result of even attempting to move if (this.type.is_item && this.cell.some(tile => tile.type.item_modifier || tile.type.is_real_player)) return false; @@ -59,6 +61,11 @@ export class Tile { if (this.type.blocks_collision & other.type.collision_mask) return true; + // FIXME bowling ball isn't affected by helmet? also not sure bowling ball is stopped by + // helmet? + if (this.has_item('helmet') || (this.type.is_actor && other.has_item('helmet'))) + return true; + // FIXME get this out of here if (this.type.thin_walls && this.type.thin_walls.has(DIRECTIONS[direction].opposite) && @@ -902,14 +909,6 @@ export class Level { } make_actor_decision(actor) { - // Teeth can only move the first 4 of every 8 tics, and mimics only the first 4 of every - // 16, though "first" can be adjusted - if (actor.slide_mode === null && actor.type.movement_parity && - (this.tic_counter + this.step_parity) % (actor.type.movement_parity * 4) >= 4) - { - return; - } - // Compat flag for blue tanks if (this.compat.sliding_tanks_ignore_button && actor.slide_mode && actor.pending_reverse) diff --git a/js/tiletypes.js b/js/tiletypes.js index aadbefa..b4dd3f0 100644 --- a/js/tiletypes.js +++ b/js/tiletypes.js @@ -92,6 +92,11 @@ function player_visual_state(me) { // Logic for chasing after the player (or running away); shared by both teeth and mimics function pursue_player(me, level) { + // Teeth can only move the first 4 of every 8 tics, and mimics only the first 4 of every 16, + // though "first" can be adjusted + if ((level.tic_counter + level.step_parity) % (me.type.movement_parity * 4) >= 4) + return null; + let player = level.player; // CC2 behavior (not Lynx (TODO compat?)): pursue the player's apparent position, not just the // cell they're in @@ -1857,7 +1862,7 @@ const TILE_TYPES = { movement_parity: 2, decide_movement(me, level) { let preference = pursue_player(me, level); - if (level.player.type.name === 'player') { + if (preference && level.player.type.name === 'player') { // Run away from Lexy for (let [i, direction] of preference.entries()) { preference[i] = DIRECTIONS[direction].opposite; @@ -1932,6 +1937,7 @@ const TILE_TYPES = { blocks_collision: COLLISION.all_but_player, can_reveal_walls: true, movement_speed: 4, + movement_parity: 4, on_ready(me, level) { me.current_emulatee = 0; me.attempted_moves = 0; @@ -1946,8 +1952,17 @@ const TILE_TYPES = { me.attempted_moves += 1; let emulatee = me.type._emulatees[me.current_emulatee]; let preference = TILE_TYPES[emulatee].decide_movement(me, level); + // Rig up the preference so a failure counts as two moves + if (preference) { + let last = preference.pop(); + preference.push(function() { + // FIXME still not right, this'll happen if the last preference works + me.attempted_moves += 1; + return typeof last === 'function' ? last() : last; + }); + } // TODO need to rig this so a failure counts as two moves - // TODO obeys step while emulating teeth (gah, i guess move that in here too) + // FIXME obeys step while emulating teeth (gah, i guess move that in here too) return preference; }, visual_state(me) {