Implement green bombs/chips, ice blocks, and custom walls/floors
This commit is contained in:
parent
88ec9f89e7
commit
8097339886
@ -169,12 +169,12 @@ const TILE_ENCODING = {
|
|||||||
// 0x68: Bowling ball : '#next'
|
// 0x68: Bowling ball : '#next'
|
||||||
// 0x69: Rover : '#direction', '#next'
|
// 0x69: Rover : '#direction', '#next'
|
||||||
// 0x6a: Time penalty : '#next'
|
// 0x6a: Time penalty : '#next'
|
||||||
// 0x6b: Custom floor (green) : Modifier allows other styles, see below
|
0x6b: ['#mod8?', ['floor_custom_green', 'floor_custom_pink', 'floor_custom_yellow', 'floor_custom_blue']],
|
||||||
// 0x6c: (Unused) :
|
// 0x6c: (Unused) :
|
||||||
0x6d: ['#thinwall/canopy', '#next'],
|
0x6d: ['#thinwall/canopy', '#next'],
|
||||||
// 0x6e: (Unused) :
|
// 0x6e: (Unused) :
|
||||||
// 0x6f: Railroad sign : '#next'
|
// 0x6f: Railroad sign : '#next'
|
||||||
// 0x70: Custom wall (green) : Modifier allows other styles, see below
|
0x70: ['#mod8?', ['wall_custom_green', 'wall_custom_pink', 'wall_custom_yellow', 'wall_custom_blue']],
|
||||||
0x71: ['#mod8', 'floor_letter'],
|
0x71: ['#mod8', 'floor_letter'],
|
||||||
// 0x72: Purple toggle wall :
|
// 0x72: Purple toggle wall :
|
||||||
// 0x73: Purple toggle floor :
|
// 0x73: Purple toggle floor :
|
||||||
@ -193,8 +193,8 @@ const TILE_ENCODING = {
|
|||||||
0x80: ['score_2x', '#next'],
|
0x80: ['score_2x', '#next'],
|
||||||
// 0x81: Directional block : '#direction', Directional Arrows Bitmask, '#next'
|
// 0x81: Directional block : '#direction', Directional Arrows Bitmask, '#next'
|
||||||
// 0x82: Floor mimic : '#direction', '#next'
|
// 0x82: Floor mimic : '#direction', '#next'
|
||||||
// 0x83: Green bomb : '#next'
|
0x83: ['green_bomb', '#next'],
|
||||||
// 0x84: Green chip : '#next'
|
0x84: ['green_chip', '#next'],
|
||||||
// 0x85: (Unused) : '#next'
|
// 0x85: (Unused) : '#next'
|
||||||
// 0x86: (Unused) : '#next'
|
// 0x86: (Unused) : '#next'
|
||||||
// 0x87: Black button :
|
// 0x87: Black button :
|
||||||
@ -411,9 +411,14 @@ export function parse_level(buf) {
|
|||||||
p++;
|
p++;
|
||||||
let mod_marker;
|
let mod_marker;
|
||||||
[mod_marker, name, ...args] = read_spec();
|
[mod_marker, name, ...args] = read_spec();
|
||||||
if (mod_marker !== '#mod8')
|
if (mod_marker !== '#mod8' && mod_marker !== '#mod8?')
|
||||||
throw new Error(`Expected a tile requiring a modifier`);
|
throw new Error(`Expected a tile requiring a modifier`);
|
||||||
}
|
}
|
||||||
|
else if (name === '#mod8?') {
|
||||||
|
// This is optional, so if we didn't get one, the modifier is 0
|
||||||
|
modifier = 0;
|
||||||
|
[name, ...args] = args;
|
||||||
|
}
|
||||||
|
|
||||||
// Make a tile template, possibly dealing with some special cases
|
// Make a tile template, possibly dealing with some special cases
|
||||||
if (name === '#thinwall/canopy') {
|
if (name === '#thinwall/canopy') {
|
||||||
@ -444,6 +449,11 @@ export function parse_level(buf) {
|
|||||||
// it, so that's fine
|
// it, so that's fine
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
else if (name instanceof Array) {
|
||||||
|
// Custom floors and walls are one of several options,
|
||||||
|
// given by an optional modifier
|
||||||
|
name = name[modifier];
|
||||||
|
}
|
||||||
|
|
||||||
let tile = {name, modifier};
|
let tile = {name, modifier};
|
||||||
cell.push(tile);
|
cell.push(tile);
|
||||||
|
|||||||
@ -53,14 +53,15 @@ export const CC2_TILESET_LAYOUT = {
|
|||||||
[8, 2],
|
[8, 2],
|
||||||
[9, 2],
|
[9, 2],
|
||||||
],
|
],
|
||||||
// ice block, xray
|
ice_block: [10, 2],
|
||||||
score_10: [14, 2],
|
// TODO ice block xray
|
||||||
score_100: [13, 2],
|
|
||||||
score_1000: [12, 2],
|
score_1000: [12, 2],
|
||||||
|
score_100: [13, 2],
|
||||||
|
score_10: [14, 2],
|
||||||
score_2x: [15, 2],
|
score_2x: [15, 2],
|
||||||
|
|
||||||
// LCD digit font
|
// LCD digit font
|
||||||
green_chip: [10, 3],
|
green_chip: [9, 3],
|
||||||
chip_extra: [10, 3],
|
chip_extra: [10, 3],
|
||||||
chip: [11, 3],
|
chip: [11, 3],
|
||||||
// bribe
|
// bribe
|
||||||
@ -71,8 +72,14 @@ export const CC2_TILESET_LAYOUT = {
|
|||||||
bomb: [5, 4],
|
bomb: [5, 4],
|
||||||
green_bomb: [6, 4],
|
green_bomb: [6, 4],
|
||||||
// ??? tiny fireworks
|
// ??? tiny fireworks
|
||||||
// custom floors
|
floor_custom_green: [8, 4],
|
||||||
// custom walls
|
floor_custom_pink: [9, 4],
|
||||||
|
floor_custom_yellow: [10, 4],
|
||||||
|
floor_custom_blue: [11, 4],
|
||||||
|
wall_custom_green: [12, 4],
|
||||||
|
wall_custom_pink: [13, 4],
|
||||||
|
wall_custom_yellow: [14, 4],
|
||||||
|
wall_custom_blue: [15, 4],
|
||||||
|
|
||||||
// explosion
|
// explosion
|
||||||
// splash
|
// splash
|
||||||
|
|||||||
101
js/tiletypes.js
101
js/tiletypes.js
@ -18,10 +18,38 @@ const TILE_TYPES = {
|
|||||||
me.ascii_code = template.modifier;
|
me.ascii_code = template.modifier;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
floor_custom_green: {
|
||||||
|
draw_layer: LAYER_TERRAIN,
|
||||||
|
},
|
||||||
|
floor_custom_pink: {
|
||||||
|
draw_layer: LAYER_TERRAIN,
|
||||||
|
},
|
||||||
|
floor_custom_yellow: {
|
||||||
|
draw_layer: LAYER_TERRAIN,
|
||||||
|
},
|
||||||
|
floor_custom_blue: {
|
||||||
|
draw_layer: LAYER_TERRAIN,
|
||||||
|
},
|
||||||
wall: {
|
wall: {
|
||||||
draw_layer: LAYER_TERRAIN,
|
draw_layer: LAYER_TERRAIN,
|
||||||
blocks: true,
|
blocks: true,
|
||||||
},
|
},
|
||||||
|
wall_custom_green: {
|
||||||
|
draw_layer: LAYER_TERRAIN,
|
||||||
|
blocks: true,
|
||||||
|
},
|
||||||
|
wall_custom_pink: {
|
||||||
|
draw_layer: LAYER_TERRAIN,
|
||||||
|
blocks: true,
|
||||||
|
},
|
||||||
|
wall_custom_yellow: {
|
||||||
|
draw_layer: LAYER_TERRAIN,
|
||||||
|
blocks: true,
|
||||||
|
},
|
||||||
|
wall_custom_blue: {
|
||||||
|
draw_layer: LAYER_TERRAIN,
|
||||||
|
blocks: true,
|
||||||
|
},
|
||||||
wall_invisible: {
|
wall_invisible: {
|
||||||
draw_layer: LAYER_TERRAIN,
|
draw_layer: LAYER_TERRAIN,
|
||||||
// TODO cc2 seems to make these flicker briefly
|
// TODO cc2 seems to make these flicker briefly
|
||||||
@ -195,7 +223,11 @@ const TILE_TYPES = {
|
|||||||
fire: {
|
fire: {
|
||||||
draw_layer: LAYER_TERRAIN,
|
draw_layer: LAYER_TERRAIN,
|
||||||
on_arrive(me, level, other) {
|
on_arrive(me, level, other) {
|
||||||
if (other.type.is_player) {
|
if (other.type.name === 'ice_block') {
|
||||||
|
level.remove_tile(other);
|
||||||
|
level.transmute_tile(me, 'water');
|
||||||
|
}
|
||||||
|
else if (other.type.is_player) {
|
||||||
level.fail("Oops! You can't walk on fire without fire boots!");
|
level.fail("Oops! You can't walk on fire without fire boots!");
|
||||||
level.transmute_tile(other, 'player_burned');
|
level.transmute_tile(other, 'player_burned');
|
||||||
}
|
}
|
||||||
@ -208,10 +240,14 @@ const TILE_TYPES = {
|
|||||||
draw_layer: LAYER_TERRAIN,
|
draw_layer: LAYER_TERRAIN,
|
||||||
on_arrive(me, level, other) {
|
on_arrive(me, level, other) {
|
||||||
// TODO cc1 allows items under water, i think; water was on the upper layer
|
// TODO cc1 allows items under water, i think; water was on the upper layer
|
||||||
if (other.type.name == 'dirt_block' || other.type.name == 'clone_block') {
|
if (other.type.name === 'dirt_block' || other.type.name === 'clone_block') {
|
||||||
level.remove_tile(other);
|
level.remove_tile(other);
|
||||||
level.transmute_tile(me, 'dirt');
|
level.transmute_tile(me, 'dirt');
|
||||||
}
|
}
|
||||||
|
else if (other.type.name === 'ice_block') {
|
||||||
|
level.remove_tile(other);
|
||||||
|
level.transmute_tile(me, 'ice');
|
||||||
|
}
|
||||||
else if (other.type.is_player) {
|
else if (other.type.is_player) {
|
||||||
level.fail("swimming with the fishes");
|
level.fail("swimming with the fishes");
|
||||||
level.transmute_tile(other, 'player_drowned');
|
level.transmute_tile(other, 'player_drowned');
|
||||||
@ -363,7 +399,6 @@ const TILE_TYPES = {
|
|||||||
dirt_block: {
|
dirt_block: {
|
||||||
draw_layer: LAYER_ACTOR,
|
draw_layer: LAYER_ACTOR,
|
||||||
blocks: true,
|
blocks: true,
|
||||||
is_object: true,
|
|
||||||
is_actor: true,
|
is_actor: true,
|
||||||
is_block: true,
|
is_block: true,
|
||||||
ignores: new Set(['fire']),
|
ignores: new Set(['fire']),
|
||||||
@ -373,12 +408,21 @@ const TILE_TYPES = {
|
|||||||
draw_layer: LAYER_ACTOR,
|
draw_layer: LAYER_ACTOR,
|
||||||
// TODO is this in any way distinct from dirt block
|
// TODO is this in any way distinct from dirt block
|
||||||
blocks: true,
|
blocks: true,
|
||||||
is_object: true,
|
|
||||||
is_actor: true,
|
is_actor: true,
|
||||||
is_block: true,
|
is_block: true,
|
||||||
ignores: new Set(['fire']),
|
ignores: new Set(['fire']),
|
||||||
movement_speed: 4,
|
movement_speed: 4,
|
||||||
},
|
},
|
||||||
|
ice_block: {
|
||||||
|
draw_layer: LAYER_ACTOR,
|
||||||
|
blocks: true,
|
||||||
|
is_actor: true,
|
||||||
|
is_block: true,
|
||||||
|
movement_speed: 4,
|
||||||
|
pushes: {
|
||||||
|
ice_block: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
green_floor: {
|
green_floor: {
|
||||||
draw_layer: LAYER_TERRAIN,
|
draw_layer: LAYER_TERRAIN,
|
||||||
},
|
},
|
||||||
@ -386,6 +430,30 @@ const TILE_TYPES = {
|
|||||||
draw_layer: LAYER_TERRAIN,
|
draw_layer: LAYER_TERRAIN,
|
||||||
blocks: true,
|
blocks: true,
|
||||||
},
|
},
|
||||||
|
green_chip: {
|
||||||
|
draw_layer: LAYER_ITEM,
|
||||||
|
is_chip: true,
|
||||||
|
is_required_chip: true,
|
||||||
|
blocks_monsters: true,
|
||||||
|
blocks_blocks: true,
|
||||||
|
on_arrive(me, level, other) {
|
||||||
|
if (other.type.is_player) {
|
||||||
|
level.collect_chip();
|
||||||
|
level.remove_tile(me);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
green_bomb: {
|
||||||
|
draw_layer: LAYER_ITEM,
|
||||||
|
on_arrive(me, level, other) {
|
||||||
|
// TODO explode
|
||||||
|
level.remove_tile(me);
|
||||||
|
level.remove_tile(other);
|
||||||
|
if (other.type.is_player) {
|
||||||
|
level.fail("watch where you step");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
cloner: {
|
cloner: {
|
||||||
draw_layer: LAYER_TERRAIN,
|
draw_layer: LAYER_TERRAIN,
|
||||||
blocks: true,
|
blocks: true,
|
||||||
@ -513,7 +581,6 @@ const TILE_TYPES = {
|
|||||||
bug: {
|
bug: {
|
||||||
draw_layer: LAYER_ACTOR,
|
draw_layer: LAYER_ACTOR,
|
||||||
is_actor: true,
|
is_actor: true,
|
||||||
is_object: true,
|
|
||||||
is_monster: true,
|
is_monster: true,
|
||||||
blocks_monsters: true,
|
blocks_monsters: true,
|
||||||
blocks_blocks: true,
|
blocks_blocks: true,
|
||||||
@ -523,7 +590,6 @@ const TILE_TYPES = {
|
|||||||
paramecium: {
|
paramecium: {
|
||||||
draw_layer: LAYER_ACTOR,
|
draw_layer: LAYER_ACTOR,
|
||||||
is_actor: true,
|
is_actor: true,
|
||||||
is_object: true,
|
|
||||||
is_monster: true,
|
is_monster: true,
|
||||||
blocks_monsters: true,
|
blocks_monsters: true,
|
||||||
blocks_blocks: true,
|
blocks_blocks: true,
|
||||||
@ -533,7 +599,6 @@ const TILE_TYPES = {
|
|||||||
ball: {
|
ball: {
|
||||||
draw_layer: LAYER_ACTOR,
|
draw_layer: LAYER_ACTOR,
|
||||||
is_actor: true,
|
is_actor: true,
|
||||||
is_object: true,
|
|
||||||
is_monster: true,
|
is_monster: true,
|
||||||
blocks_monsters: true,
|
blocks_monsters: true,
|
||||||
blocks_blocks: true,
|
blocks_blocks: true,
|
||||||
@ -543,7 +608,6 @@ const TILE_TYPES = {
|
|||||||
walker: {
|
walker: {
|
||||||
draw_layer: LAYER_ACTOR,
|
draw_layer: LAYER_ACTOR,
|
||||||
is_actor: true,
|
is_actor: true,
|
||||||
is_object: true,
|
|
||||||
is_monster: true,
|
is_monster: true,
|
||||||
blocks_monsters: true,
|
blocks_monsters: true,
|
||||||
blocks_blocks: true,
|
blocks_blocks: true,
|
||||||
@ -553,7 +617,6 @@ const TILE_TYPES = {
|
|||||||
tank_blue: {
|
tank_blue: {
|
||||||
draw_layer: LAYER_ACTOR,
|
draw_layer: LAYER_ACTOR,
|
||||||
is_actor: true,
|
is_actor: true,
|
||||||
is_object: true,
|
|
||||||
is_monster: true,
|
is_monster: true,
|
||||||
blocks_monsters: true,
|
blocks_monsters: true,
|
||||||
blocks_blocks: true,
|
blocks_blocks: true,
|
||||||
@ -563,7 +626,6 @@ const TILE_TYPES = {
|
|||||||
blob: {
|
blob: {
|
||||||
draw_layer: LAYER_ACTOR,
|
draw_layer: LAYER_ACTOR,
|
||||||
is_actor: true,
|
is_actor: true,
|
||||||
is_object: true,
|
|
||||||
is_monster: true,
|
is_monster: true,
|
||||||
blocks_monsters: true,
|
blocks_monsters: true,
|
||||||
blocks_blocks: true,
|
blocks_blocks: true,
|
||||||
@ -573,7 +635,6 @@ const TILE_TYPES = {
|
|||||||
teeth: {
|
teeth: {
|
||||||
draw_layer: LAYER_ACTOR,
|
draw_layer: LAYER_ACTOR,
|
||||||
is_actor: true,
|
is_actor: true,
|
||||||
is_object: true,
|
|
||||||
is_monster: true,
|
is_monster: true,
|
||||||
blocks_monsters: true,
|
blocks_monsters: true,
|
||||||
blocks_blocks: true,
|
blocks_blocks: true,
|
||||||
@ -584,7 +645,6 @@ const TILE_TYPES = {
|
|||||||
fireball: {
|
fireball: {
|
||||||
draw_layer: LAYER_ACTOR,
|
draw_layer: LAYER_ACTOR,
|
||||||
is_actor: true,
|
is_actor: true,
|
||||||
is_object: true,
|
|
||||||
is_monster: true,
|
is_monster: true,
|
||||||
blocks_monsters: true,
|
blocks_monsters: true,
|
||||||
blocks_blocks: true,
|
blocks_blocks: true,
|
||||||
@ -595,7 +655,6 @@ const TILE_TYPES = {
|
|||||||
glider: {
|
glider: {
|
||||||
draw_layer: LAYER_ACTOR,
|
draw_layer: LAYER_ACTOR,
|
||||||
is_actor: true,
|
is_actor: true,
|
||||||
is_object: true,
|
|
||||||
is_monster: true,
|
is_monster: true,
|
||||||
blocks_monsters: true,
|
blocks_monsters: true,
|
||||||
blocks_blocks: true,
|
blocks_blocks: true,
|
||||||
@ -607,39 +666,33 @@ const TILE_TYPES = {
|
|||||||
// Keys
|
// Keys
|
||||||
key_red: {
|
key_red: {
|
||||||
draw_layer: LAYER_ITEM,
|
draw_layer: LAYER_ITEM,
|
||||||
is_object: true,
|
|
||||||
is_item: true,
|
is_item: true,
|
||||||
is_key: true,
|
is_key: true,
|
||||||
},
|
},
|
||||||
key_blue: {
|
key_blue: {
|
||||||
draw_layer: LAYER_ITEM,
|
draw_layer: LAYER_ITEM,
|
||||||
is_object: true,
|
|
||||||
is_item: true,
|
is_item: true,
|
||||||
is_key: true,
|
is_key: true,
|
||||||
},
|
},
|
||||||
key_yellow: {
|
key_yellow: {
|
||||||
draw_layer: LAYER_ITEM,
|
draw_layer: LAYER_ITEM,
|
||||||
is_object: true,
|
|
||||||
is_item: true,
|
is_item: true,
|
||||||
is_key: true,
|
is_key: true,
|
||||||
},
|
},
|
||||||
key_green: {
|
key_green: {
|
||||||
draw_layer: LAYER_ITEM,
|
draw_layer: LAYER_ITEM,
|
||||||
is_object: true,
|
|
||||||
is_item: true,
|
is_item: true,
|
||||||
is_key: true,
|
is_key: true,
|
||||||
},
|
},
|
||||||
// Tools
|
// Tools
|
||||||
cleats: {
|
cleats: {
|
||||||
draw_layer: LAYER_ITEM,
|
draw_layer: LAYER_ITEM,
|
||||||
is_object: true,
|
|
||||||
is_item: true,
|
is_item: true,
|
||||||
is_tool: true,
|
is_tool: true,
|
||||||
item_ignores: new Set(['ice', 'ice_nw', 'ice_ne', 'ice_sw', 'ice_se']),
|
item_ignores: new Set(['ice', 'ice_nw', 'ice_ne', 'ice_sw', 'ice_se']),
|
||||||
},
|
},
|
||||||
suction_boots: {
|
suction_boots: {
|
||||||
draw_layer: LAYER_ITEM,
|
draw_layer: LAYER_ITEM,
|
||||||
is_object: true,
|
|
||||||
is_item: true,
|
is_item: true,
|
||||||
is_tool: true,
|
is_tool: true,
|
||||||
item_ignores: new Set([
|
item_ignores: new Set([
|
||||||
@ -652,14 +705,12 @@ const TILE_TYPES = {
|
|||||||
},
|
},
|
||||||
fire_boots: {
|
fire_boots: {
|
||||||
draw_layer: LAYER_ITEM,
|
draw_layer: LAYER_ITEM,
|
||||||
is_object: true,
|
|
||||||
is_item: true,
|
is_item: true,
|
||||||
is_tool: true,
|
is_tool: true,
|
||||||
item_ignores: new Set(['fire']),
|
item_ignores: new Set(['fire']),
|
||||||
},
|
},
|
||||||
flippers: {
|
flippers: {
|
||||||
draw_layer: LAYER_ITEM,
|
draw_layer: LAYER_ITEM,
|
||||||
is_object: true,
|
|
||||||
is_item: true,
|
is_item: true,
|
||||||
is_tool: true,
|
is_tool: true,
|
||||||
item_ignores: new Set(['water']),
|
item_ignores: new Set(['water']),
|
||||||
@ -671,11 +722,11 @@ const TILE_TYPES = {
|
|||||||
is_actor: true,
|
is_actor: true,
|
||||||
is_player: true,
|
is_player: true,
|
||||||
has_inventory: true,
|
has_inventory: true,
|
||||||
is_object: true,
|
|
||||||
movement_speed: 4,
|
movement_speed: 4,
|
||||||
pushes: {
|
pushes: {
|
||||||
dirt_block: true,
|
dirt_block: true,
|
||||||
clone_block: true,
|
clone_block: true,
|
||||||
|
ice_block: true,
|
||||||
},
|
},
|
||||||
// FIXME this prevents thief from taking green key
|
// FIXME this prevents thief from taking green key
|
||||||
infinite_items: {
|
infinite_items: {
|
||||||
@ -690,7 +741,6 @@ const TILE_TYPES = {
|
|||||||
},
|
},
|
||||||
chip: {
|
chip: {
|
||||||
draw_layer: LAYER_ITEM,
|
draw_layer: LAYER_ITEM,
|
||||||
is_object: true,
|
|
||||||
is_chip: true,
|
is_chip: true,
|
||||||
is_required_chip: true,
|
is_required_chip: true,
|
||||||
blocks_monsters: true,
|
blocks_monsters: true,
|
||||||
@ -705,7 +755,6 @@ const TILE_TYPES = {
|
|||||||
chip_extra: {
|
chip_extra: {
|
||||||
draw_layer: LAYER_ITEM,
|
draw_layer: LAYER_ITEM,
|
||||||
is_chip: true,
|
is_chip: true,
|
||||||
is_object: true,
|
|
||||||
blocks_monsters: true,
|
blocks_monsters: true,
|
||||||
blocks_blocks: true,
|
blocks_blocks: true,
|
||||||
on_arrive(me, level, other) {
|
on_arrive(me, level, other) {
|
||||||
@ -717,19 +766,15 @@ const TILE_TYPES = {
|
|||||||
},
|
},
|
||||||
score_10: {
|
score_10: {
|
||||||
draw_layer: LAYER_ITEM,
|
draw_layer: LAYER_ITEM,
|
||||||
is_object: true,
|
|
||||||
},
|
},
|
||||||
score_100: {
|
score_100: {
|
||||||
draw_layer: LAYER_ITEM,
|
draw_layer: LAYER_ITEM,
|
||||||
is_object: true,
|
|
||||||
},
|
},
|
||||||
score_1000: {
|
score_1000: {
|
||||||
draw_layer: LAYER_ITEM,
|
draw_layer: LAYER_ITEM,
|
||||||
is_object: true,
|
|
||||||
},
|
},
|
||||||
score_2x: {
|
score_2x: {
|
||||||
draw_layer: LAYER_ITEM,
|
draw_layer: LAYER_ITEM,
|
||||||
is_object: true,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
hint: {
|
hint: {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user