Add support for exporting hints to CCL; remove level hints
This commit is contained in:
parent
58cc6ff61e
commit
81b305b2f6
@ -100,7 +100,6 @@ export class StoredLevel extends LevelInterface {
|
|||||||
this.author = '';
|
this.author = '';
|
||||||
this.password = null;
|
this.password = null;
|
||||||
this.comment = '';
|
this.comment = '';
|
||||||
this.hint = ''; // XXX does this actually belong here, since hints contain the text? does anything set it?
|
|
||||||
// A number is a specified count; the default of null means that the chips are counted on
|
// A number is a specified count; the default of null means that the chips are counted on
|
||||||
// level init, as in CC2
|
// level init, as in CC2
|
||||||
this.chips_required = null;
|
this.chips_required = null;
|
||||||
|
|||||||
@ -1045,6 +1045,7 @@ export function parse_level(buf, number = 1) {
|
|||||||
let level = new format_base.StoredLevel(number);
|
let level = new format_base.StoredLevel(number);
|
||||||
level.format = 'c2m';
|
level.format = 'c2m';
|
||||||
level.uses_ll_extensions = false; // we'll update this if it changes
|
level.uses_ll_extensions = false; // we'll update this if it changes
|
||||||
|
let default_hint = '';
|
||||||
let extra_hints = [];
|
let extra_hints = [];
|
||||||
let hint_tiles = [];
|
let hint_tiles = [];
|
||||||
for (let [type, bytes] of read_c2m_sections(buf)) {
|
for (let [type, bytes] of read_c2m_sections(buf)) {
|
||||||
@ -1076,7 +1077,7 @@ export function parse_level(buf, number = 1) {
|
|||||||
}
|
}
|
||||||
else if (type === 'CLUE') {
|
else if (type === 'CLUE') {
|
||||||
// Level hint
|
// Level hint
|
||||||
level.hint = str;
|
default_hint = str;
|
||||||
}
|
}
|
||||||
else if (type === 'NOTE') {
|
else if (type === 'NOTE') {
|
||||||
// Author's comments... but might also include tags delimiting special blocks, most
|
// Author's comments... but might also include tags delimiting special blocks, most
|
||||||
@ -1319,7 +1320,7 @@ export function parse_level(buf, number = 1) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Fall back to regular hint
|
// Fall back to regular hint
|
||||||
tile.hint_text = null;
|
tile.hint_text = default_hint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -201,10 +201,6 @@ export function parse_level_metadata(bytes) {
|
|||||||
// Password, with trailing NUL, and XORed with 0x99 (???)
|
// Password, with trailing NUL, and XORed with 0x99 (???)
|
||||||
meta.password = decode_password(bytes, p, field_length - 1);
|
meta.password = decode_password(bytes, p, field_length - 1);
|
||||||
}
|
}
|
||||||
else if (field_type === 0x07) {
|
|
||||||
// Hint, including trailing NUL, of course
|
|
||||||
meta.hint = util.string_from_buffer_ascii(bytes, p, field_length - 1);
|
|
||||||
}
|
|
||||||
p += field_length;
|
p += field_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,6 +232,7 @@ function parse_level(bytes, number) {
|
|||||||
let unknown = view.getUint16(6, true);
|
let unknown = view.getUint16(6, true);
|
||||||
// Same structure twice, for the two layers
|
// Same structure twice, for the two layers
|
||||||
let p = 8;
|
let p = 8;
|
||||||
|
let hint_tiles = [];
|
||||||
for (let l = 0; l < 2; l++) {
|
for (let l = 0; l < 2; l++) {
|
||||||
let layer_length = view.getUint16(p, true);
|
let layer_length = view.getUint16(p, true);
|
||||||
p += 2;
|
p += 2;
|
||||||
@ -299,7 +296,11 @@ function parse_level(bytes, number) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
cell[tile.type.layer] = {...tile};
|
let new_tile = {...tile};
|
||||||
|
cell[tile.type.layer] = new_tile;
|
||||||
|
if (new_tile.type.name === 'hint') {
|
||||||
|
hint_tiles.push(new_tile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (c !== 1024)
|
if (c !== 1024)
|
||||||
@ -369,7 +370,10 @@ function parse_level(bytes, number) {
|
|||||||
}
|
}
|
||||||
else if (field_type === 0x07) {
|
else if (field_type === 0x07) {
|
||||||
// Hint, including trailing NUL, of course
|
// Hint, including trailing NUL, of course
|
||||||
level.hint = util.string_from_buffer_ascii(bytes, p, field_length - 1);
|
let hint = util.string_from_buffer_ascii(bytes, p, field_length - 1);
|
||||||
|
for (let tile of hint_tiles) {
|
||||||
|
tile.hint_text = hint;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (field_type === 0x08) {
|
else if (field_type === 0x08) {
|
||||||
// Password, but not encoded
|
// Password, but not encoded
|
||||||
@ -455,6 +459,7 @@ export function synthesize_level(stored_level) {
|
|||||||
let magic = 0x0002aaac;
|
let magic = 0x0002aaac;
|
||||||
let top_layer = [];
|
let top_layer = [];
|
||||||
let bottom_layer = [];
|
let bottom_layer = [];
|
||||||
|
let hint_text = null;
|
||||||
let error_found_wires = false;
|
let error_found_wires = false;
|
||||||
// TODO i could be a little kinder and support, say, items on terrain; do those work in mscc? tw lynx?
|
// TODO i could be a little kinder and support, say, items on terrain; do those work in mscc? tw lynx?
|
||||||
for (let [i, cell] of stored_level.linear_cells.entries()) {
|
for (let [i, cell] of stored_level.linear_cells.entries()) {
|
||||||
@ -515,6 +520,15 @@ export function synthesize_level(stored_level) {
|
|||||||
else {
|
else {
|
||||||
other_byte = rev_spec['all'];
|
other_byte = rev_spec['all'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (other.type.name === 'hint') {
|
||||||
|
if (hint_text === null) {
|
||||||
|
hint_text = other.hint_text;
|
||||||
|
}
|
||||||
|
else if (hint_text !== other.hint_text) {
|
||||||
|
errors.push(`All hints must contain the same text`);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
errors.push(`Can't encode tile: ${other.type.name}`);
|
errors.push(`Can't encode tile: ${other.type.name}`);
|
||||||
@ -565,9 +579,11 @@ export function synthesize_level(stored_level) {
|
|||||||
// TODO support this for real lol
|
// TODO support this for real lol
|
||||||
add_block(6, util.bytestring_to_buffer("XXXX\0"));
|
add_block(6, util.bytestring_to_buffer("XXXX\0"));
|
||||||
// Hint
|
// Hint
|
||||||
// TODO uh, yeah, this too
|
// TODO tile world seems to do latin-1 (just sort of, inherently); this will do modulo on
|
||||||
// TODO do something with not-ascii; does TW support utf8 or latin1 or anything?
|
// anything outside it (yyyyikes!), probably should sub with ? or something
|
||||||
add_block(7, util.bytestring_to_buffer("TODO hints aren't yet supported".substring(0, 127) + "\0"));
|
if (hint_text !== null) {
|
||||||
|
add_block(7, util.bytestring_to_buffer(hint_text.substring(0, 127) + "\0"));
|
||||||
|
}
|
||||||
// Monster positions
|
// Monster positions
|
||||||
// TODO this is dumb as hell but do it too
|
// TODO this is dumb as hell but do it too
|
||||||
add_block(10, new ArrayBuffer);
|
add_block(10, new ArrayBuffer);
|
||||||
|
|||||||
@ -1637,7 +1637,7 @@ class Player extends PrimaryView {
|
|||||||
this.hint_el.parentNode.classList.toggle('--visible', !! hint_tile);
|
this.hint_el.parentNode.classList.toggle('--visible', !! hint_tile);
|
||||||
if (hint_tile) {
|
if (hint_tile) {
|
||||||
// Parse out %X sequences and replace them with <kbd> elements
|
// Parse out %X sequences and replace them with <kbd> elements
|
||||||
let hint_text = hint_tile.hint_text ?? this.level.stored_level.hint;
|
let hint_text = hint_tile.hint_text;
|
||||||
for (let [i, chunk] of hint_text.split(/%(\w)/).entries()) {
|
for (let [i, chunk] of hint_text.split(/%(\w)/).entries()) {
|
||||||
if (i % 2 === 0) {
|
if (i % 2 === 0) {
|
||||||
this.hint_el.append(chunk);
|
this.hint_el.append(chunk);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user