Implement Boulder

Similar to a dirt block, but rolls when pushed. Boulders transfer momentum to each other. Has ice block/frame block collision. Turns into gravel in water. Spreads slime.
This commit is contained in:
Timothy Stiles 2021-02-14 18:38:56 +11:00
parent 7bcb1ac018
commit 20dad5c76a
5 changed files with 68 additions and 3 deletions

View File

@ -812,6 +812,11 @@ const TILE_ENCODING = {
name: 'spikes', name: 'spikes',
is_extension: true, is_extension: true,
}, },
0xd6: {
name: 'boulder',
has_next: true,
extra_args: [arg_direction],
},
0xe0: { 0xe0: {
name: 'gift_bow', name: 'gift_bow',
has_next: true, has_next: true,

View File

@ -1578,6 +1578,10 @@ export class Level extends LevelInterface {
if (actor.cell === goal_cell) if (actor.cell === goal_cell)
return; return;
if (actor.type.on_starting_move) {
actor.type.on_starting_move(actor, this);
}
let original_cell = actor.cell; let original_cell = actor.cell;
// Physically remove the actor first, so that it won't get in the way of e.g. a splash // 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 // spawned from stepping off of a lilypad

View File

@ -1609,7 +1609,8 @@ const EDITOR_PALETTE = [{
'cracked_floor', 'cracked_floor',
'cracked_ice', 'cracked_ice',
'score_5x', 'score_5x',
'spikes' 'spikes',
'boulder',
], ],
}]; }];
@ -2232,6 +2233,10 @@ const EDITOR_TILE_DESCRIPTIONS = {
name: "Spikes", name: "Spikes",
desc: "Stops players (and doppelgangers) unless they have hiking boots. Everything else can pass.", desc: "Stops players (and doppelgangers) unless they have hiking boots. Everything else can pass.",
}, },
boulder: {
name: "Boulder",
desc: "Similar to a dirt block, but rolls when pushed. Boulders transfer momentum to each other. Has ice block/frame block collision. Turns into gravel in water. Spreads slime.",
},
}; };
const SPECIAL_PALETTE_ENTRIES = { const SPECIAL_PALETTE_ENTRIES = {

View File

@ -1064,6 +1064,7 @@ export const LL_TILESET_LAYOUT = Object.assign({}, CC2_TILESET_LAYOUT, {
cracked_ice: [7, 40], cracked_ice: [7, 40],
score_5x: [10, 40], score_5x: [10, 40],
spikes: [5, 40], spikes: [5, 40],
boulder: [8, 40],
}); });
export const TILESET_LAYOUTS = { export const TILESET_LAYOUTS = {

View File

@ -259,7 +259,7 @@ const TILE_TYPES = {
floor: { floor: {
layer: LAYERS.terrain, layer: LAYERS.terrain,
on_approach(me, level, other) { on_approach(me, level, other) {
if (other.type.name === 'blob') { if (other.type.name === 'blob' || other.type.name === 'boulder') {
// Blobs spread slime onto floor // Blobs spread slime onto floor
if (other.previous_cell && other.previous_cell.has('slime')) { if (other.previous_cell && other.previous_cell.has('slime')) {
level.transmute_tile(me, 'slime'); level.transmute_tile(me, 'slime');
@ -830,6 +830,10 @@ const TILE_TYPES = {
level.transmute_tile(other, 'splash'); level.transmute_tile(other, 'splash');
level.transmute_tile(me, 'ice'); level.transmute_tile(me, 'ice');
} }
else if (other.type.name === 'boulder') {
level.transmute_tile(other, 'splash');
level.transmute_tile(me, 'gravel');
}
else if (other.type.is_real_player) { else if (other.type.is_real_player) {
level.fail('drowned', me, other); level.fail('drowned', me, other);
} }
@ -1021,7 +1025,7 @@ const TILE_TYPES = {
slime: { slime: {
layer: LAYERS.terrain, layer: LAYERS.terrain,
on_arrive(me, level, other) { on_arrive(me, level, other) {
if (other.type.name === 'ghost' || other.type.name === 'blob') { if (other.type.name === 'ghost' || other.type.name === 'blob' || other.type.name === 'boulder') {
// No effect // No effect
return; return;
} }
@ -1185,6 +1189,7 @@ const TILE_TYPES = {
pushes: { pushes: {
ice_block: true, ice_block: true,
frame_block: true, frame_block: true,
boulder: true,
}, },
on_bumped(me, level, other) { on_bumped(me, level, other) {
// Fireballs melt ice blocks on regular floor FIXME and water! // Fireballs melt ice blocks on regular floor FIXME and water!
@ -1215,6 +1220,7 @@ const TILE_TYPES = {
dirt_block: true, dirt_block: true,
ice_block: true, ice_block: true,
frame_block: true, frame_block: true,
boulder: true,
}, },
on_clone(me, original) { on_clone(me, original) {
me.arrows = new Set(original.arrows); me.arrows = new Set(original.arrows);
@ -1228,6 +1234,43 @@ const TILE_TYPES = {
level._set_tile_prop(me, 'arrows', new_arrows); level._set_tile_prop(me, 'arrows', new_arrows);
}, },
}, },
boulder: {
layer: LAYERS.actor,
collision_mask: COLLISION.block_cc2,
blocks_collision: COLLISION.all,
is_actor: true,
is_block: true,
can_reveal_walls: true,
pushes: {
ice_block: true,
frame_block: true,
//boulders don't push each other; instead on_bumped will chain through them
},
ignores: new Set(['fire', 'flame_jet_on', 'electrified_floor']),
can_reverse_on_railroad: true,
movement_speed: 4,
decide_movement(me, level) {
if (me.rolling) {
level._set_tile_prop(me, 'rolling', false);
return [me.direction, null];
}
else {
return null;
}
},
on_bumped(me, level, other) {
if (other.type.name === 'boulder') {
level._set_tile_prop(me, 'rolling', true);
level._set_tile_prop(me, 'direction', other.direction);
level._set_tile_prop(other, 'rolling', false);
}
},
on_starting_move(me, level) {
if (!me.rolling) {
level._set_tile_prop(me, 'rolling', true);
}
},
},
glass_block: { glass_block: {
layer: LAYERS.actor, layer: LAYERS.actor,
collision_mask: COLLISION.block_cc2, collision_mask: COLLISION.block_cc2,
@ -1244,6 +1287,7 @@ const TILE_TYPES = {
dirt_block: true, dirt_block: true,
ice_block: true, ice_block: true,
frame_block: true, frame_block: true,
boulder: true,
}, },
on_clone(me, original) { on_clone(me, original) {
me.arrows = new Set(original.arrows); me.arrows = new Set(original.arrows);
@ -2490,6 +2534,7 @@ const TILE_TYPES = {
ice_block: true, ice_block: true,
frame_block: true, frame_block: true,
circuit_block: true, circuit_block: true,
boulder: true,
}, },
movement_speed: 4, movement_speed: 4,
decide_movement(me, level) { decide_movement(me, level) {
@ -2641,6 +2686,7 @@ const TILE_TYPES = {
ice_block: true, ice_block: true,
frame_block: true, frame_block: true,
circuit_block: true, circuit_block: true,
boulder: true,
}, },
on_ready(me, level) { on_ready(me, level) {
me.current_emulatee = 0; me.current_emulatee = 0;
@ -3004,6 +3050,7 @@ const TILE_TYPES = {
ice_block: true, ice_block: true,
frame_block: true, frame_block: true,
circuit_block: true, circuit_block: true,
boulder: true,
}, },
infinite_items: { infinite_items: {
key_green: true, key_green: true,
@ -3026,6 +3073,7 @@ const TILE_TYPES = {
ice_block: true, ice_block: true,
frame_block: true, frame_block: true,
circuit_block: true, circuit_block: true,
boulder: true,
}, },
infinite_items: { infinite_items: {
key_yellow: true, key_yellow: true,
@ -3047,6 +3095,7 @@ const TILE_TYPES = {
ice_block: true, ice_block: true,
frame_block: true, frame_block: true,
circuit_block: true, circuit_block: true,
boulder: true,
}, },
infinite_items: { infinite_items: {
key_green: true, key_green: true,
@ -3072,6 +3121,7 @@ const TILE_TYPES = {
ice_block: true, ice_block: true,
frame_block: true, frame_block: true,
circuit_block: true, circuit_block: true,
boulder: true,
}, },
infinite_items: { infinite_items: {
key_yellow: true, key_yellow: true,