Added a new auto-fix for actors atop bombs in CCL levels
This fixes CCLP5 level 25 (and I think one or two others) by introducing a new item, the dormant bomb, which turns into a regular bomb when something moves off of it. Other accumulated tileset touchups that snuck in: - Recolored the canopy to hopefully look more like a tent - Lightened slime by one shade - Made the custom green floor colors clash less, and lightened the yellow floor grout - Removed the shadow from the pause stopwatch, and lightened the other two, to better distinguish their different behavior - Added little rivets to steel walls - Made the symbols on the sokoban blocks easier to see - Lightened the blue and red keys to match the shade of the other two, and also hopefully make them easier to see atop water and thieves - Shrank the railroad crossing sign slightly - Added laces to the hiking boots - Added shading to the bowling ball - Removed the shadows from the actor versions of the bowling ball and dynamite - Darkened the dynamite item to better distinguish it from active dynamite - Lightened the blue teleporter exit so it doesn't look too much like an inactive red teleporter - Improved the gradient on the beetle - Made the hint tile look recessed like CC2, to better convey that it blocks some actors - Added art for some possible tiles: rainbow teleporter, toll gate, nega heart, phantom ring, feather
This commit is contained in:
parent
e33c35bbe0
commit
f6ee09b6c7
@ -150,6 +150,10 @@ export const COMPAT_FLAG_CATEGORIES = [{
|
|||||||
key: 'no_auto_convert_ccl_blue_walls',
|
key: 'no_auto_convert_ccl_blue_walls',
|
||||||
label: "Blue walls under blocks are not auto-converted in CCL levels",
|
label: "Blue walls under blocks are not auto-converted in CCL levels",
|
||||||
rulesets: new Set(['steam-strict', 'lynx', 'ms']),
|
rulesets: new Set(['steam-strict', 'lynx', 'ms']),
|
||||||
|
}, {
|
||||||
|
key: 'no_auto_convert_ccl_bombs',
|
||||||
|
label: "Mines under actors are not auto-converted in CCL levels",
|
||||||
|
rulesets: new Set(['steam-strict', 'lynx', 'ms']),
|
||||||
}],
|
}],
|
||||||
}, {
|
}, {
|
||||||
title: "Actor behavior",
|
title: "Actor behavior",
|
||||||
@ -300,6 +304,7 @@ export const COMPAT_FLAG_CATEGORIES = [{
|
|||||||
label: "Bowling balls on cloners are destroyed when fired at point blank",
|
label: "Bowling balls on cloners are destroyed when fired at point blank",
|
||||||
rulesets: new Set(['steam-strict']),
|
rulesets: new Set(['steam-strict']),
|
||||||
}, {
|
}, {
|
||||||
|
// XXX is this necessary, with the addition of the dormant bomb?
|
||||||
key: 'bombs_immediately_detonate_under_players',
|
key: 'bombs_immediately_detonate_under_players',
|
||||||
label: "Mines under players detonate when the level starts",
|
label: "Mines under players detonate when the level starts",
|
||||||
rulesets: new Set(['steam-strict']),
|
rulesets: new Set(['steam-strict']),
|
||||||
|
|||||||
@ -142,6 +142,7 @@ export const CC2_TILESET_LAYOUT = {
|
|||||||
bomb: [5, 4],
|
bomb: [5, 4],
|
||||||
fuse: [7, 4],
|
fuse: [7, 4],
|
||||||
},
|
},
|
||||||
|
dormant_bomb: [5, 4], // compat tile, so needs a fallback
|
||||||
green_bomb: {
|
green_bomb: {
|
||||||
__special__: 'bomb-fuse',
|
__special__: 'bomb-fuse',
|
||||||
bomb: [6, 4],
|
bomb: [6, 4],
|
||||||
@ -309,7 +310,7 @@ export const CC2_TILESET_LAYOUT = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
popwall: [8, 10],
|
popwall: [8, 10],
|
||||||
popwall2: [8, 10],
|
popwall2: [8, 10], // compat tile, so needs a fallback
|
||||||
gravel: [9, 10],
|
gravel: [9, 10],
|
||||||
ball: {
|
ball: {
|
||||||
__special__: 'animated',
|
__special__: 'animated',
|
||||||
@ -897,6 +898,7 @@ export const TILE_WORLD_TILESET_LAYOUT = {
|
|||||||
button_blue: [2, 8],
|
button_blue: [2, 8],
|
||||||
teleport_blue: [2, 9],
|
teleport_blue: [2, 9],
|
||||||
bomb: [2, 10],
|
bomb: [2, 10],
|
||||||
|
dormant_bomb: [2, 10], // compat tile, so needs a fallback
|
||||||
trap: {
|
trap: {
|
||||||
__special__: 'visual-state',
|
__special__: 'visual-state',
|
||||||
closed: [2, 11],
|
closed: [2, 11],
|
||||||
@ -905,7 +907,7 @@ export const TILE_WORLD_TILESET_LAYOUT = {
|
|||||||
wall_appearing: [2, 12],
|
wall_appearing: [2, 12],
|
||||||
gravel: [2, 13],
|
gravel: [2, 13],
|
||||||
popwall: [2, 14],
|
popwall: [2, 14],
|
||||||
popwall2: [2, 14],
|
popwall2: [2, 14], // compat tile, so needs a fallback
|
||||||
hint: [2, 15],
|
hint: [2, 15],
|
||||||
|
|
||||||
cloner: [3, 1],
|
cloner: [3, 1],
|
||||||
@ -1335,9 +1337,13 @@ export const LL_TILESET_LAYOUT = {
|
|||||||
foil: [2, 17],
|
foil: [2, 17],
|
||||||
xray_eye: [3, 17],
|
xray_eye: [3, 17],
|
||||||
helmet: [4, 17],
|
helmet: [4, 17],
|
||||||
|
phantom_ring: [5, 17],
|
||||||
|
feather: [6, 17],
|
||||||
|
dormant_bomb: [7, 17],
|
||||||
skeleton_key: [0, 18],
|
skeleton_key: [0, 18],
|
||||||
ankh: [1, 18],
|
ankh: [1, 18],
|
||||||
floor_ankh: [2, 18],
|
floor_ankh: [2, 18],
|
||||||
|
toll_gate: [5, 18],
|
||||||
no_sign: [6, 18],
|
no_sign: [6, 18],
|
||||||
gift_bow: [7, 18],
|
gift_bow: [7, 18],
|
||||||
score_10: [0, 19],
|
score_10: [0, 19],
|
||||||
@ -3070,6 +3076,10 @@ export function parse_tile_world_large_tileset(canvas) {
|
|||||||
}
|
}
|
||||||
ctx.putImageData(image_data, 0, 0);
|
ctx.putImageData(image_data, 0, 0);
|
||||||
|
|
||||||
|
// These are compat tiles, which need to have a fallback
|
||||||
|
layout['popwall2'] = layout['popwall'];
|
||||||
|
layout['dormant_bomb'] = layout['bomb'];
|
||||||
|
|
||||||
return new Tileset(canvas, layout, tw, th);
|
return new Tileset(canvas, layout, tw, th);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -352,8 +352,8 @@ const TILE_TYPES = {
|
|||||||
level.stored_level.format === 'ccl' &&
|
level.stored_level.format === 'ccl' &&
|
||||||
me.cell.get_actor())
|
me.cell.get_actor())
|
||||||
{
|
{
|
||||||
// Fix blocks and other actors on top of popwalls by turning them into double
|
// CCL: Actors who start on popwalls are not intended to activate them when they
|
||||||
// popwalls, which preserves CC2 popwall behavior
|
// leave, so preserve CC2 behavior by changing them to double popwalls
|
||||||
me.type = TILE_TYPES['popwall2'];
|
me.type = TILE_TYPES['popwall2'];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -430,8 +430,8 @@ const TILE_TYPES = {
|
|||||||
level.stored_level.format === 'ccl' &&
|
level.stored_level.format === 'ccl' &&
|
||||||
me.cell.get_actor())
|
me.cell.get_actor())
|
||||||
{
|
{
|
||||||
// Blocks can be pushed off of blue walls in TW Lynx, which only works due to a tiny
|
// CCL: Blocks can be pushed off of blue walls in TW Lynx, but we can replicate the
|
||||||
// quirk of the engine that I don't want to replicate, so replace them with popwalls
|
// behavior with CC2 rules by replacing them with popwalls
|
||||||
// TODO this also works with invis walls apparently. maybe only for blocks?
|
// TODO this also works with invis walls apparently. maybe only for blocks?
|
||||||
me.type = TILE_TYPES['popwall'];
|
me.type = TILE_TYPES['popwall'];
|
||||||
}
|
}
|
||||||
@ -1062,6 +1062,17 @@ const TILE_TYPES = {
|
|||||||
},
|
},
|
||||||
bomb: {
|
bomb: {
|
||||||
layer: LAYERS.item,
|
layer: LAYERS.item,
|
||||||
|
on_ready(me, level) {
|
||||||
|
if (! level.compat.no_auto_convert_ccl_bombs &&
|
||||||
|
level.stored_level.format === 'ccl' &&
|
||||||
|
me.cell.get_actor())
|
||||||
|
{
|
||||||
|
// CCL: A number of custom levels start an actor on top of a bomb (I guess to
|
||||||
|
// conserve space), relying on the CC1 behavior that bombs only detonate when
|
||||||
|
// stepped onto. Replace those with the custom "dormant bomb" tile.
|
||||||
|
me.type = TILE_TYPES['dormant_bomb'];
|
||||||
|
}
|
||||||
|
},
|
||||||
on_arrive(me, level, other) {
|
on_arrive(me, level, other) {
|
||||||
if (level.compat.bombs_detonate_on_arrive) {
|
if (level.compat.bombs_detonate_on_arrive) {
|
||||||
me.type._detonate(me, level, other);
|
me.type._detonate(me, level, other);
|
||||||
@ -1083,6 +1094,18 @@ const TILE_TYPES = {
|
|||||||
level.kill_actor(other, me, 'explosion', 'bomb', 'exploded');
|
level.kill_actor(other, me, 'explosion', 'bomb', 'exploded');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// Bomb variant originally added as a CC1 autofix, but which doubles as an experimental item --
|
||||||
|
// it's dormant until you drop it and move off of it, at which point it becomes a normal bomb
|
||||||
|
dormant_bomb: {
|
||||||
|
...COMMON_TOOL,
|
||||||
|
on_depart(me, level, other) {
|
||||||
|
// Unlike dynamite, anyone can activate this (important to make it work as CCL compat)
|
||||||
|
if (me.cell.get_item_mod())
|
||||||
|
return;
|
||||||
|
|
||||||
|
level.transmute_tile(me, 'bomb');
|
||||||
|
},
|
||||||
|
},
|
||||||
hole: {
|
hole: {
|
||||||
layer: LAYERS.terrain,
|
layer: LAYERS.terrain,
|
||||||
on_ready(me, level) {
|
on_ready(me, level) {
|
||||||
@ -2800,24 +2823,28 @@ const TILE_TYPES = {
|
|||||||
dynamite: {
|
dynamite: {
|
||||||
...COMMON_TOOL,
|
...COMMON_TOOL,
|
||||||
on_depart(me, level, other) {
|
on_depart(me, level, other) {
|
||||||
if (other.type.is_real_player && ! me.cell.get_item_mod()) {
|
if (! other.type.is_real_player)
|
||||||
// FIXME wiki just says about 4.3 seconds; more likely this is exactly 255 frames
|
return;
|
||||||
level._set_tile_prop(me, 'timer', 85);
|
if (me.cell.get_item_mod())
|
||||||
level.transmute_tile(me, 'dynamite_lit');
|
return;
|
||||||
// Actors are expected to have this, so populate it
|
|
||||||
level._set_tile_prop(me, 'movement_cooldown', 0);
|
// XXX wiki just says about 4.3 seconds; more likely this is exactly 255 frames (and
|
||||||
level.add_actor(me);
|
// there haven't been any compat problems so far...)
|
||||||
// Dynamite inherits a copy of the player's inventory, which largely doesn't matter
|
level._set_tile_prop(me, 'timer', 85);
|
||||||
// except for suction boots, helmet, or lightning bolt; keys can't matter because
|
level.transmute_tile(me, 'dynamite_lit');
|
||||||
// dynamite is blocked by doors
|
// Actors are expected to have this, so populate it
|
||||||
if (other.toolbelt) {
|
level._set_tile_prop(me, 'movement_cooldown', 0);
|
||||||
level._set_tile_prop(me, 'toolbelt', [...other.toolbelt]);
|
level.add_actor(me);
|
||||||
}
|
// Dynamite inherits a copy of the player's inventory, which largely doesn't matter
|
||||||
// Dynamite that lands on a force floor is moved by it, and dynamite that lands on a
|
// except for suction boots, helmet, or lightning bolt; keys can't matter because
|
||||||
// button holds it down
|
// dynamite is blocked by doors
|
||||||
// TODO is there anything this should NOT activate?
|
if (other.toolbelt) {
|
||||||
level.step_on_cell(me, me.cell);
|
level._set_tile_prop(me, 'toolbelt', [...other.toolbelt]);
|
||||||
}
|
}
|
||||||
|
// Dynamite that lands on a force floor is moved by it, and dynamite that lands on a
|
||||||
|
// button holds it down
|
||||||
|
// TODO is there anything this should NOT activate?
|
||||||
|
level.step_on_cell(me, me.cell);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
dynamite_lit: {
|
dynamite_lit: {
|
||||||
|
|||||||
BIN
tileset-lexy.png
BIN
tileset-lexy.png
Binary file not shown.
|
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 94 KiB |
Binary file not shown.
Loading…
Reference in New Issue
Block a user