diff --git a/.gitignore b/.gitignore index b464b06f..febbc2a1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # Editors +.idea .vscode # dependencies diff --git a/.prettierrc.json b/.prettierrc.json index af726a55..56ca4ffe 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -2,5 +2,5 @@ "printWidth": 100, "tabWidth": 4, "singleQuote": false, - "trailingComma": "es5" + "trailingComma": "all" } \ No newline at end of file diff --git a/FEATURES.md b/FEATURES.md index 7916a33c..4739048b 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -31,6 +31,7 @@ Features that are in ***bold italics*** are planned and not yet implemented. ## Area Selection - Dropdown menu to switch area +- Add new area ## Simple Quest Properties diff --git a/src/data_formats/index.ts b/src/data_formats/Endianness.ts similarity index 100% rename from src/data_formats/index.ts rename to src/data_formats/Endianness.ts diff --git a/src/data_formats/compression/prs/compress.ts b/src/data_formats/compression/prs/compress.ts index 40744302..a7641e7c 100644 --- a/src/data_formats/compression/prs/compress.ts +++ b/src/data_formats/compression/prs/compress.ts @@ -1,4 +1,4 @@ -import { Endianness } from "../.."; +import { Endianness } from "../../Endianness"; import { Cursor } from "../../cursor/Cursor"; import { ResizableBufferCursor } from "../../cursor/ResizableBufferCursor"; import { WritableCursor } from "../../cursor/WritableCursor"; diff --git a/src/data_formats/compression/prs/index.test.ts b/src/data_formats/compression/prs/index.test.ts index 8d857e88..61679123 100644 --- a/src/data_formats/compression/prs/index.test.ts +++ b/src/data_formats/compression/prs/index.test.ts @@ -1,5 +1,5 @@ import { readFileSync } from "fs"; -import { Endianness } from "../.."; +import { Endianness } from "../../Endianness"; import { ArrayBufferCursor } from "../../cursor/ArrayBufferCursor"; import { BufferCursor } from "../../cursor/BufferCursor"; import { prs_compress } from "./compress"; diff --git a/src/data_formats/cursor/AbstractCursor.ts b/src/data_formats/cursor/AbstractCursor.ts index 6dd0895b..3f6bc98b 100644 --- a/src/data_formats/cursor/AbstractCursor.ts +++ b/src/data_formats/cursor/AbstractCursor.ts @@ -1,4 +1,4 @@ -import { Endianness } from ".."; +import { Endianness } from "../Endianness"; import { Vec2, Vec3 } from "../vector"; import { Cursor } from "./Cursor"; diff --git a/src/data_formats/cursor/ArrayBufferCursor.ts b/src/data_formats/cursor/ArrayBufferCursor.ts index ae67e84b..507c3741 100644 --- a/src/data_formats/cursor/ArrayBufferCursor.ts +++ b/src/data_formats/cursor/ArrayBufferCursor.ts @@ -1,4 +1,4 @@ -import { Endianness } from ".."; +import { Endianness } from "../Endianness"; import { AbstractWritableCursor } from "./AbstractWritableCursor"; import { WritableCursor } from "./WritableCursor"; diff --git a/src/data_formats/cursor/BufferCursor.ts b/src/data_formats/cursor/BufferCursor.ts index a6f65016..96e14cb1 100644 --- a/src/data_formats/cursor/BufferCursor.ts +++ b/src/data_formats/cursor/BufferCursor.ts @@ -1,4 +1,4 @@ -import { Endianness } from ".."; +import { Endianness } from "../Endianness"; import { AbstractCursor } from "./AbstractCursor"; import { Cursor } from "./Cursor"; diff --git a/src/data_formats/cursor/Cursor.test.ts b/src/data_formats/cursor/Cursor.test.ts index a6674284..0d951cf9 100644 --- a/src/data_formats/cursor/Cursor.test.ts +++ b/src/data_formats/cursor/Cursor.test.ts @@ -1,4 +1,4 @@ -import { Endianness } from ".."; +import { Endianness } from "../Endianness"; import { enum_values } from "../../enums"; import { ResizableBuffer } from "../ResizableBuffer"; import { ArrayBufferCursor } from "./ArrayBufferCursor"; diff --git a/src/data_formats/cursor/Cursor.ts b/src/data_formats/cursor/Cursor.ts index 9094cd60..59291e43 100644 --- a/src/data_formats/cursor/Cursor.ts +++ b/src/data_formats/cursor/Cursor.ts @@ -1,4 +1,4 @@ -import { Endianness } from ".."; +import { Endianness } from "../Endianness"; import { Vec3, Vec2 } from "../vector"; /** diff --git a/src/data_formats/cursor/ResizableBufferCursor.test.ts b/src/data_formats/cursor/ResizableBufferCursor.test.ts index d56e6c28..1b4b2f0f 100644 --- a/src/data_formats/cursor/ResizableBufferCursor.test.ts +++ b/src/data_formats/cursor/ResizableBufferCursor.test.ts @@ -1,4 +1,4 @@ -import { Endianness } from ".."; +import { Endianness } from "../Endianness"; import { ResizableBuffer } from "../ResizableBuffer"; import { ResizableBufferCursor } from "./ResizableBufferCursor"; diff --git a/src/data_formats/cursor/ResizableBufferCursor.ts b/src/data_formats/cursor/ResizableBufferCursor.ts index 6252b4fd..fdc565de 100644 --- a/src/data_formats/cursor/ResizableBufferCursor.ts +++ b/src/data_formats/cursor/ResizableBufferCursor.ts @@ -1,4 +1,4 @@ -import { Endianness } from ".."; +import { Endianness } from "../Endianness"; import { ResizableBuffer } from "../ResizableBuffer"; import { AbstractWritableCursor } from "./AbstractWritableCursor"; import { WritableCursor } from "./WritableCursor"; diff --git a/src/data_formats/cursor/WritableCursor.test.ts b/src/data_formats/cursor/WritableCursor.test.ts index 87ead1a4..cf94ae02 100644 --- a/src/data_formats/cursor/WritableCursor.test.ts +++ b/src/data_formats/cursor/WritableCursor.test.ts @@ -1,4 +1,4 @@ -import { Endianness } from ".."; +import { Endianness } from "../Endianness"; import { enum_values } from "../../enums"; import { ResizableBuffer } from "../ResizableBuffer"; import { ArrayBufferCursor } from "./ArrayBufferCursor"; diff --git a/src/data_formats/encryption/prc.ts b/src/data_formats/encryption/prc.ts index e0cc3a9f..ac99b7cd 100644 --- a/src/data_formats/encryption/prc.ts +++ b/src/data_formats/encryption/prc.ts @@ -1,4 +1,4 @@ -import { Endianness } from ".."; +import { Endianness } from "../Endianness"; import { ArrayBufferCursor } from "../cursor/ArrayBufferCursor"; import { Cursor } from "../cursor/Cursor"; diff --git a/src/data_formats/parsing/area_collision_geometry.test.ts b/src/data_formats/parsing/area_collision_geometry.test.ts index f2a5ad5b..a022d922 100644 --- a/src/data_formats/parsing/area_collision_geometry.test.ts +++ b/src/data_formats/parsing/area_collision_geometry.test.ts @@ -1,7 +1,7 @@ import { readFileSync } from "fs"; import { parse_area_collision_geometry } from "./area_collision_geometry"; import { BufferCursor } from "../cursor/BufferCursor"; -import { Endianness } from ".."; +import { Endianness } from "../Endianness"; test("parse_area_collision_geometry", () => { const buf = readFileSync("test/resources/map_forest01c.rel"); diff --git a/src/data_formats/parsing/itempmt.test.ts b/src/data_formats/parsing/itempmt.test.ts index 855b270b..4b354e4f 100644 --- a/src/data_formats/parsing/itempmt.test.ts +++ b/src/data_formats/parsing/itempmt.test.ts @@ -1,7 +1,7 @@ import { parse_item_pmt } from "./itempmt"; import { readFileSync } from "fs"; import { BufferCursor } from "../cursor/BufferCursor"; -import { Endianness } from ".."; +import { Endianness } from "../Endianness"; test("parse_item_pmt", () => { const buf = readFileSync("test/resources/ItemPMT.bin"); diff --git a/src/data_formats/parsing/quest/Episode.ts b/src/data_formats/parsing/quest/Episode.ts new file mode 100644 index 00000000..06fb5a5b --- /dev/null +++ b/src/data_formats/parsing/quest/Episode.ts @@ -0,0 +1,13 @@ +export enum Episode { + I = 1, + II = 2, + IV = 4, +} + +export const EPISODES = [Episode.I, Episode.II, Episode.IV]; + +export function check_episode(episode: Episode): void { + if (Episode[episode] == undefined) { + throw new Error(`Invalid episode ${episode}.`); + } +} diff --git a/src/data_formats/parsing/quest/areas.ts b/src/data_formats/parsing/quest/areas.ts new file mode 100644 index 00000000..dd525dff --- /dev/null +++ b/src/data_formats/parsing/quest/areas.ts @@ -0,0 +1,100 @@ +import { Episode } from "./Episode"; + +export type Area = { + readonly id: number; + readonly name: string; + readonly order: number; + readonly area_variants: AreaVariant[]; +}; + +export type AreaVariant = { + readonly id: number; + readonly area: Area; +}; + +export function get_areas_for_episode(episode: Episode): Area[] { + return AREAS[episode]; +} + +export function get_area_variant( + episode: Episode, + area_id: number, + variant_id: number, +): AreaVariant { + const area = AREAS[episode].find(area => area.id === area_id); + if (!area) throw new Error(`No area with id ${area_id}.`); + + const variant = area.area_variants[variant_id]; + if (!variant) throw new Error(`No area variant with id ${variant_id}.`); + + return variant; +} + +const AREAS: { [episode: number]: Area[] } = []; + +function create_area(id: number, name: string, order: number, variants: number): Area { + const area: Area = { id, name, order, area_variants: [] }; + + for (let id = 0; id < variants; id++) { + area.area_variants.push({ id, area }); + } + + return area; +} + +// The IDs match the PSO IDs for areas. +let order = 0; +AREAS[Episode.I] = [ + create_area(0, "Pioneer II", order++, 1), + create_area(1, "Forest 1", order++, 1), + create_area(2, "Forest 2", order++, 1), + create_area(11, "Under the Dome", order++, 1), + create_area(3, "Cave 1", order++, 6), + create_area(4, "Cave 2", order++, 5), + create_area(5, "Cave 3", order++, 6), + create_area(12, "Underground Channel", order++, 1), + create_area(6, "Mine 1", order++, 6), + create_area(7, "Mine 2", order++, 6), + create_area(13, "Monitor Room", order++, 1), + create_area(8, "Ruins 1", order++, 5), + create_area(9, "Ruins 2", order++, 5), + create_area(10, "Ruins 3", order++, 5), + create_area(14, "Dark Falz", order++, 1), + create_area(15, "BA Ruins", order++, 3), + create_area(16, "BA Spaceship", order++, 3), + create_area(17, "Lobby", order++, 15), +]; +order = 0; +AREAS[Episode.II] = [ + create_area(0, "Lab", order++, 1), + create_area(1, "VR Temple Alpha", order++, 3), + create_area(2, "VR Temple Beta", order++, 3), + create_area(14, "VR Temple Final", order++, 1), + create_area(3, "VR Spaceship Alpha", order++, 3), + create_area(4, "VR Spaceship Beta", order++, 3), + create_area(15, "VR Spaceship Final", order++, 1), + create_area(5, "Central Control Area", order++, 1), + create_area(6, "Jungle Area East", order++, 1), + create_area(7, "Jungle Area North", order++, 1), + create_area(8, "Mountain Area", order++, 3), + create_area(9, "Seaside Area", order++, 1), + create_area(12, "Cliffs of Gal Da Val", order++, 1), + create_area(10, "Seabed Upper Levels", order++, 3), + create_area(11, "Seabed Lower Levels", order++, 3), + create_area(13, "Test Subject Disposal Area", order++, 1), + create_area(16, "Seaside Area at Night", order++, 1), + create_area(17, "Control Tower", order++, 5), +]; +order = 0; +AREAS[Episode.IV] = [ + create_area(0, "Pioneer II (Ep. IV)", order++, 1), + create_area(1, "Crater Route 1", order++, 1), + create_area(2, "Crater Route 2", order++, 1), + create_area(3, "Crater Route 3", order++, 1), + create_area(4, "Crater Route 4", order++, 1), + create_area(5, "Crater Interior", order++, 1), + create_area(6, "Subterranean Desert 1", order++, 3), + create_area(7, "Subterranean Desert 2", order++, 3), + create_area(8, "Subterranean Desert 3", order++, 3), + create_area(9, "Meteor Impact Site", order++, 1), +]; diff --git a/src/data_formats/parsing/quest/bin.test.ts b/src/data_formats/parsing/quest/bin.test.ts index d6d974dd..5c3f1693 100644 --- a/src/data_formats/parsing/quest/bin.test.ts +++ b/src/data_formats/parsing/quest/bin.test.ts @@ -1,5 +1,5 @@ import { readFileSync } from "fs"; -import { Endianness } from "../.."; +import { Endianness } from "../../Endianness"; import { prs_decompress } from "../../compression/prs/decompress"; import { ArrayBufferCursor } from "../../cursor/ArrayBufferCursor"; import { BufferCursor } from "../../cursor/BufferCursor"; diff --git a/src/data_formats/parsing/quest/bin.ts b/src/data_formats/parsing/quest/bin.ts index d25115b8..7a3472fb 100644 --- a/src/data_formats/parsing/quest/bin.ts +++ b/src/data_formats/parsing/quest/bin.ts @@ -1,5 +1,5 @@ import Logger from "js-logger"; -import { Endianness } from "../.."; +import { Endianness } from "../../Endianness"; import { ControlFlowGraph } from "../../../scripting/data_flow_analysis/ControlFlowGraph"; import { register_value } from "../../../scripting/data_flow_analysis/register_value"; import { stack_value } from "../../../scripting/data_flow_analysis/stack_value"; @@ -567,18 +567,19 @@ function parse_instructions_segment( // Recurse on label drop-through. if (next_label != undefined) { - // Find the first non-nop. - let last_opcode: Opcode | undefined; + // Find the first ret or jmp. + let drop_through = true; for (let i = instructions.length - 1; i >= 0; i--) { - last_opcode = instructions[i].opcode; + const opcode = instructions[i].opcode; - if (last_opcode !== Opcode.NOP) { + if (opcode === Opcode.RET || opcode === Opcode.JMP) { + drop_through = false; break; } } - if (last_opcode !== Opcode.RET && last_opcode !== Opcode.JMP) { + if (drop_through) { parse_segment( offset_to_segment, label_holder, diff --git a/src/data_formats/parsing/quest/dat.test.ts b/src/data_formats/parsing/quest/dat.test.ts index dd47917d..9c03f3aa 100644 --- a/src/data_formats/parsing/quest/dat.test.ts +++ b/src/data_formats/parsing/quest/dat.test.ts @@ -1,4 +1,4 @@ -import { Endianness } from "../.."; +import { Endianness } from "../../Endianness"; import { prs_decompress } from "../../compression/prs/decompress"; import { BufferCursor } from "../../cursor/BufferCursor"; import { ResizableBufferCursor } from "../../cursor/ResizableBufferCursor"; diff --git a/src/data_formats/parsing/quest/dat.ts b/src/data_formats/parsing/quest/dat.ts index 4ec4403d..2844dab6 100644 --- a/src/data_formats/parsing/quest/dat.ts +++ b/src/data_formats/parsing/quest/dat.ts @@ -1,6 +1,6 @@ import Logger from "js-logger"; import { groupBy } from "lodash"; -import { Endianness } from "../.."; +import { Endianness } from "../../Endianness"; import { Cursor } from "../../cursor/Cursor"; import { ResizableBufferCursor } from "../../cursor/ResizableBufferCursor"; import { ResizableBuffer } from "../../ResizableBuffer"; diff --git a/src/data_formats/parsing/quest/entities.ts b/src/data_formats/parsing/quest/entities.ts new file mode 100644 index 00000000..76cea963 --- /dev/null +++ b/src/data_formats/parsing/quest/entities.ts @@ -0,0 +1,51 @@ +import { Vec3 } from "../../vector"; +import { npc_data, NpcType, NpcTypeData } from "./npc_types"; +import { object_data, ObjectType, ObjectTypeData } from "./object_types"; + +export type QuestEntity = QuestNpc | QuestObject; + +export type QuestNpc = { + readonly type: NpcType; + readonly area_id: number; + readonly section_id: number; + /** + * Section-relative position + */ + readonly position: Vec3; + readonly rotation: Vec3; + readonly scale: Vec3; + /** + * Data of which the purpose hasn't been discovered yet. + */ + readonly unknown: number[][]; + readonly pso_type_id: number; + readonly pso_skin: number; +}; + +export type QuestObject = { + readonly type: ObjectType; + readonly area_id: number; + readonly section_id: number; + /** + * Section-relative position + */ + readonly position: Vec3; + readonly rotation: Vec3; + readonly scale: Vec3; + /** + * Data of which the purpose hasn't been discovered yet. + */ + readonly unknown: number[][]; +}; + +export type EntityTypeData = NpcTypeData | ObjectTypeData; + +export type EntityType = NpcType | ObjectType; + +export function entity_type_to_string(type: EntityType): string { + return (NpcType as any)[type] || (ObjectType as any)[type]; +} + +export function entity_data(type: EntityType): EntityTypeData { + return npc_data(type as NpcType) || object_data(type as ObjectType); +} diff --git a/src/data_formats/parsing/quest/index.test.ts b/src/data_formats/parsing/quest/index.test.ts index 5c42717a..c6ce0b85 100644 --- a/src/data_formats/parsing/quest/index.test.ts +++ b/src/data_formats/parsing/quest/index.test.ts @@ -1,10 +1,10 @@ import { readFileSync } from "fs"; -import { Endianness } from "../.."; +import { Endianness } from "../../Endianness"; import { walk_qst_files } from "../../../../test/src/utils"; -import { ObjectType, Quest } from "../../../domain"; import { ArrayBufferCursor } from "../../cursor/ArrayBufferCursor"; import { BufferCursor } from "../../cursor/BufferCursor"; -import { parse_quest, write_quest_qst } from "../quest"; +import { parse_quest, Quest, write_quest_qst } from "./index"; +import { ObjectType } from "./object_types"; test("parse Towards the Future", () => { const buffer = readFileSync("test/resources/quest118_e.qst"); @@ -14,7 +14,7 @@ test("parse Towards the Future", () => { expect(quest.name).toBe("Towards the Future"); expect(quest.short_description).toBe("Challenge the\nnew simulator."); expect(quest.long_description).toBe( - "Client: Principal\nQuest: Wishes to have\nhunters challenge the\nnew simulator\nReward: ??? Meseta" + "Client: Principal\nQuest: Wishes to have\nhunters challenge the\nnew simulator\nReward: ??? Meseta", ); expect(quest.episode).toBe(1); expect(quest.objects.length).toBe(277); @@ -36,25 +36,25 @@ test("parse Towards the Future", () => { }); /** - * Roundtrip tests. + * Round-trip tests. * Parse a QST file, write the resulting Quest object to QST again, then parse that again. * Then check whether the two Quest objects are equal. */ if (process.env["RUN_ALL_TESTS"] === "true") { - walk_qst_files(roundtrip_test); + walk_qst_files(round_trip_test); } else { const file_name_1 = "quest118_e.qst"; const path_1 = `test/resources/${file_name_1}`; const buffer_1 = readFileSync(path_1); - roundtrip_test(path_1, file_name_1, buffer_1); + round_trip_test(path_1, file_name_1, buffer_1); const file_name_2 = "quest27_e.qst"; const path_2 = `test/resources/${file_name_2}`; const buffer_2 = readFileSync(path_2); - roundtrip_test(path_2, file_name_2, buffer_2); + round_trip_test(path_2, file_name_2, buffer_2); } -function roundtrip_test(path: string, file_name: string, contents: Buffer): void { +function round_trip_test(path: string, file_name: string, contents: Buffer): void { test(`parse_quest and write_quest_qst ${path}`, () => { const orig_quest = parse_quest(new BufferCursor(contents, Endianness.Little))!; const test_bin = write_quest_qst(orig_quest, file_name); @@ -72,7 +72,7 @@ function roundtrip_test(path: string, file_name: string, contents: Buffer): void expect(test_obj.area_id).toBe(orig_obj.area_id); expect(test_obj.section_id).toBe(orig_obj.section_id); expect(test_obj.position).toEqual(orig_obj.position); - expect(test_obj.type.id).toBe(orig_obj.type.id); + expect(test_obj.type).toBe(orig_obj.type); } expect(test_quest.npcs.length).toBe(orig_quest.npcs.length); @@ -83,7 +83,7 @@ function roundtrip_test(path: string, file_name: string, contents: Buffer): void expect(test_npc.area_id).toBe(orig_npc.area_id); expect(test_npc.section_id).toBe(orig_npc.section_id); expect(test_npc.position).toEqual(orig_npc.position); - expect(test_npc.type.id).toBe(orig_npc.type.id); + expect(test_npc.type).toBe(orig_npc.type); } expect(test_quest.area_variants.length).toBe(orig_quest.area_variants.length); @@ -91,8 +91,8 @@ function roundtrip_test(path: string, file_name: string, contents: Buffer): void for (let i = 0; i < orig_quest.area_variants.length; i++) { const orig_area_variant = orig_quest.area_variants[i]; const test_area_variant = test_quest.area_variants[i]; - expect(test_area_variant.area.id).toBe(orig_area_variant.area.id); expect(test_area_variant.id).toBe(orig_area_variant.id); + expect(test_area_variant.area.id).toBe(orig_area_variant.area.id); } expect(test_quest.object_code.length).toBe(orig_quest.object_code.length); diff --git a/src/data_formats/parsing/quest/index.ts b/src/data_formats/parsing/quest/index.ts index e9e5cb94..68bb0ace 100644 --- a/src/data_formats/parsing/quest/index.ts +++ b/src/data_formats/parsing/quest/index.ts @@ -1,29 +1,47 @@ import Logger from "js-logger"; -import { Endianness } from "../.."; import { - AreaVariant, - Episode, - NpcType, - ObjectType, - Quest, - QuestNpc, - QuestObject, -} from "../../../domain"; -import { Instruction, InstructionSegment, SegmentType } from "../../../scripting/instructions"; + Instruction, + InstructionSegment, + Segment, + SegmentType, +} from "../../../scripting/instructions"; import { Opcode } from "../../../scripting/opcodes"; -import { area_store } from "../../../stores/AreaStore"; import { prs_compress } from "../../compression/prs/compress"; import { prs_decompress } from "../../compression/prs/decompress"; import { ArrayBufferCursor } from "../../cursor/ArrayBufferCursor"; import { Cursor } from "../../cursor/Cursor"; import { ResizableBufferCursor } from "../../cursor/ResizableBufferCursor"; +import { Endianness } from "../../Endianness"; import { Vec3 } from "../../vector"; +import { AreaVariant, get_area_variant } from "./areas"; import { BinFile, parse_bin, write_bin } from "./bin"; -import { DatFile, DatNpc, DatObject, parse_dat, write_dat } from "./dat"; +import { DatFile, DatNpc, DatObject, DatUnknown, parse_dat, write_dat } from "./dat"; +import { QuestNpc, QuestObject } from "./entities"; +import { Episode } from "./Episode"; +import { object_data, pso_id_to_object_type } from "./object_types"; import { parse_qst, QstContainedFile, write_qst } from "./qst"; +import { NpcType } from "./npc_types"; const logger = Logger.get("data_formats/parsing/quest"); +export type Quest = { + readonly id: number; + readonly language: number; + readonly name: string; + readonly short_description: string; + readonly long_description: string; + readonly episode: Episode; + readonly objects: QuestObject[]; + readonly npcs: QuestNpc[]; + /** + * (Partial) raw DAT data that can't be parsed yet by Phantasmal. + */ + readonly dat_unknowns: DatUnknown[]; + readonly object_code: Segment[]; + readonly shop_items: number[]; + readonly area_variants: AreaVariant[]; +}; + /** * High level parsing function that delegates to lower level parsing functions. * @@ -60,14 +78,14 @@ export function parse_quest(cursor: Cursor, lenient: boolean = false): Quest | u } const dat_decompressed = prs_decompress( - new ArrayBufferCursor(dat_file.data, Endianness.Little) + new ArrayBufferCursor(dat_file.data, Endianness.Little), ); const dat = parse_dat(dat_decompressed); const bin_decompressed = prs_decompress( - new ArrayBufferCursor(bin_file.data, Endianness.Little) + new ArrayBufferCursor(bin_file.data, Endianness.Little), ); const bin = parse_bin(bin_decompressed, [0], lenient); - let episode = 1; + let episode = Episode.I; let area_variants: AreaVariant[] = []; if (bin.object_code.length) { @@ -82,7 +100,12 @@ export function parse_quest(cursor: Cursor, lenient: boolean = false): Quest | u if (label_0_segment) { episode = get_episode(label_0_segment.instructions); - area_variants = get_area_variants(dat, episode, label_0_segment.instructions, lenient); + area_variants = extract_area_variants( + dat, + episode, + label_0_segment.instructions, + lenient, + ); } else { logger.warn(`No instruction for label 0 found.`); } @@ -90,20 +113,20 @@ export function parse_quest(cursor: Cursor, lenient: boolean = false): Quest | u logger.warn("File contains no instruction labels."); } - return new Quest( - bin.quest_id, - bin.language, - bin.quest_name, - bin.short_description, - bin.long_description, + return { + id: bin.quest_id, + language: bin.language, + name: bin.quest_name, + short_description: bin.short_description, + long_description: bin.long_description, episode, + objects: parse_obj_data(dat.objs), + npcs: parse_npc_data(episode, dat.npcs), + dat_unknowns: dat.unknowns, + object_code: bin.object_code, + shop_items: bin.shop_items, area_variants, - parse_obj_data(dat.objs), - parse_npc_data(episode, dat.npcs), - dat.unknowns, - bin.object_code, - bin.shop_items - ); + }; } export function write_quest_qst(quest: Quest, file_name: string): ArrayBuffer { @@ -120,8 +143,8 @@ export function write_quest_qst(quest: Quest, file_name: string): ArrayBuffer { quest.short_description, quest.long_description, quest.object_code, - quest.shop_items - ) + quest.shop_items, + ), ); const ext_start = file_name.lastIndexOf("."); const base_file_name = @@ -133,7 +156,7 @@ export function write_quest_qst(quest: Quest, file_name: string): ArrayBuffer { name: base_file_name + ".dat", id: quest.id, data: prs_compress( - new ResizableBufferCursor(dat, Endianness.Little) + new ResizableBufferCursor(dat, Endianness.Little), ).array_buffer(), }, { @@ -150,7 +173,7 @@ export function write_quest_qst(quest: Quest, file_name: string): ArrayBuffer { */ function get_episode(func_0_instructions: Instruction[]): Episode { const set_episode = func_0_instructions.find( - instruction => instruction.opcode === Opcode.SET_EPISODE + instruction => instruction.opcode === Opcode.SET_EPISODE, ); if (set_episode) { @@ -165,15 +188,15 @@ function get_episode(func_0_instructions: Instruction[]): Episode { } } else { logger.debug("Function 0 has no set_episode instruction."); - return 1; + return Episode.I; } } -function get_area_variants( +function extract_area_variants( dat: DatFile, - episode: number, + episode: Episode, func_0_instructions: Instruction[], - lenient: boolean + lenient: boolean, ): AreaVariant[] { // Add area variants that have npcs or objects even if there are no BB_Map_Designate instructions for them. const area_variants = new Map(); @@ -187,7 +210,7 @@ function get_area_variants( } const bb_maps = func_0_instructions.filter( - instruction => instruction.opcode === Opcode.BB_MAP_DESIGNATE + instruction => instruction.opcode === Opcode.BB_MAP_DESIGNATE, ); for (const bb_map of bb_maps) { @@ -196,11 +219,11 @@ function get_area_variants( area_variants.set(area_id, variant_id); } - const area_variants_array = new Array(); + const area_variants_array: AreaVariant[] = []; for (const [area_id, variant_id] of area_variants.entries()) { try { - area_variants_array.push(area_store.get_variant(episode, area_id, variant_id)); + area_variants_array.push(get_area_variant(episode, area_id, variant_id)); } catch (e) { if (lenient) { logger.error(`Unknown area variant.`, e); @@ -216,31 +239,31 @@ function get_area_variants( function parse_obj_data(objs: DatObject[]): QuestObject[] { return objs.map(obj_data => { - return new QuestObject( - ObjectType.from_pso_id(obj_data.type_id), - obj_data.area_id, - obj_data.section_id, - obj_data.position.clone(), - obj_data.rotation.clone(), - obj_data.scale.clone(), - obj_data.unknown - ); + return { + type: pso_id_to_object_type(obj_data.type_id), + area_id: obj_data.area_id, + section_id: obj_data.section_id, + position: obj_data.position, + rotation: obj_data.rotation, + scale: obj_data.scale, + unknown: obj_data.unknown, + }; }); } function parse_npc_data(episode: number, npcs: DatNpc[]): QuestNpc[] { return npcs.map(npc_data => { - return new QuestNpc( - get_npc_type(episode, npc_data), - npc_data.type_id, - npc_data.skin, - npc_data.area_id, - npc_data.section_id, - npc_data.position.clone(), - npc_data.rotation.clone(), - npc_data.scale.clone(), - npc_data.unknown - ); + return { + type: get_npc_type(episode, npc_data), + area_id: npc_data.area_id, + section_id: npc_data.section_id, + position: npc_data.position, + rotation: npc_data.rotation, + scale: npc_data.scale, + unknown: npc_data.unknown, + pso_type_id: npc_data.type_id, + pso_skin: npc_data.skin, + }; }); } @@ -522,11 +545,11 @@ function get_npc_type(episode: number, { type_id, scale, skin, area_id }: DatNpc function objects_to_dat_data(objects: QuestObject[]): DatObject[] { return objects.map(object => ({ - type_id: object.type.pso_id!, + type_id: object_data(object.type).pso_id!, section_id: object.section_id, - position: object.section_position.clone(), - rotation: object.rotation.clone(), - scale: object.scale.clone(), + position: object.position, + rotation: object.rotation, + scale: object.scale, area_id: object.area_id, unknown: object.unknown, })); @@ -551,8 +574,8 @@ function npcs_to_dat_data(npcs: QuestNpc[]): DatNpc[] { return { type_id: type_data.type_id, section_id: npc.section_id, - position: npc.section_position.clone(), - rotation: npc.rotation.clone(), + position: npc.position, + rotation: npc.rotation, scale, skin: type_data.skin, area_id: npc.area_id, @@ -562,11 +585,11 @@ function npcs_to_dat_data(npcs: QuestNpc[]): DatNpc[] { } function npc_type_to_dat_data( - type: NpcType + type: NpcType, ): { type_id: number; skin: number; regular: boolean } | undefined { switch (type) { default: - throw new Error(`Unexpected type ${type.code}.`); + throw new Error(`Unexpected type ${NpcType[type]}.`); case NpcType.Unknown: return undefined; diff --git a/src/data_formats/parsing/quest/npc_types.ts b/src/data_formats/parsing/quest/npc_types.ts new file mode 100644 index 00000000..7ef3f736 --- /dev/null +++ b/src/data_formats/parsing/quest/npc_types.ts @@ -0,0 +1,669 @@ +import { Episode, check_episode } from "./Episode"; + +export enum NpcType { + // + // Unknown NPCs + // + + Unknown, + + // + // Friendly NPCs + // + + FemaleFat, + FemaleMacho, + FemaleTall, + MaleDwarf, + MaleFat, + MaleMacho, + MaleOld, + BlueSoldier, + RedSoldier, + Principal, + Tekker, + GuildLady, + Scientist, + Nurse, + Irene, + ItemShop, + Nurse2, + + // + // Enemy NPCs + // + + // Episode I Forest + + Hildebear, + Hildeblue, + RagRappy, + AlRappy, + Monest, + Mothmant, + SavageWolf, + BarbarousWolf, + Booma, + Gobooma, + Gigobooma, + Dragon, + + // Episode I Caves + + GrassAssassin, + PoisonLily, + NarLily, + NanoDragon, + EvilShark, + PalShark, + GuilShark, + PofuillySlime, + PouillySlime, + PanArms, + Migium, + Hidoom, + DeRolLe, + + // Episode I Mines + + Dubchic, + Gilchic, + Garanz, + SinowBeat, + SinowGold, + Canadine, + Canane, + Dubswitch, + VolOpt, + + // Episode I Ruins + + Delsaber, + ChaosSorcerer, + DarkGunner, + DeathGunner, + ChaosBringer, + DarkBelra, + Dimenian, + LaDimenian, + SoDimenian, + Bulclaw, + Bulk, + Claw, + DarkFalz, + + // Episode II VR Temple + + Hildebear2, + Hildeblue2, + RagRappy2, + LoveRappy, + StRappy, + HalloRappy, + EggRappy, + Monest2, + Mothmant2, + PoisonLily2, + NarLily2, + GrassAssassin2, + Dimenian2, + LaDimenian2, + SoDimenian2, + DarkBelra2, + BarbaRay, + + // Episode II VR Spaceship + + SavageWolf2, + BarbarousWolf2, + PanArms2, + Migium2, + Hidoom2, + Dubchic2, + Gilchic2, + Garanz2, + Dubswitch2, + Delsaber2, + ChaosSorcerer2, + GolDragon, + + // Episode II Central Control Area + + SinowBerill, + SinowSpigell, + Merillia, + Meriltas, + Mericarol, + Mericus, + Merikle, + UlGibbon, + ZolGibbon, + Gibbles, + Gee, + GiGue, + IllGill, + DelLily, + Epsilon, + GalGryphon, + + // Episode II Seabed + + Deldepth, + Delbiter, + Dolmolm, + Dolmdarl, + Morfos, + Recobox, + Recon, + SinowZoa, + SinowZele, + OlgaFlow, + + // Episode IV + + SandRappy, + DelRappy, + Astark, + SatelliteLizard, + Yowie, + MerissaA, + MerissaAA, + Girtablulu, + Zu, + Pazuzu, + Boota, + ZeBoota, + BaBoota, + Dorphon, + DorphonEclair, + Goran, + PyroGoran, + GoranDetonator, + SaintMilion, + Shambertin, + // Kondrieu should be last to make sure ObjectType does not overlap NpcType. See code below. + Kondrieu, +} + +export type NpcTypeData = { + /** + * Unique name. E.g. a Delsaber would have (Ep. II) appended to its name. + */ + readonly name: string; + /** + * Name used in the game. + * Might conflict with other NPC names (e.g. Delsaber from ep. I and ep. II). + */ + readonly simple_name: string; + readonly ultimate_name: string; + readonly episode?: Episode; + readonly enemy: boolean; + readonly rare_type?: NpcType; +}; + +export const ENEMY_NPC_TYPES: NpcType[] = []; + +export function npc_data(type: NpcType): NpcTypeData { + return NPC_TYPE_DATA[type]; +} + +/** + * Uniquely identifies an NPC. Tries to match on simple_name and ultimate_name. + */ +export function name_and_episode_to_npc_type(name: string, episode: Episode): NpcType | undefined { + check_episode(episode); + return EP_AND_NAME_TO_NPC_TYPE[episode]!.get(name); +} + +const EP_AND_NAME_TO_NPC_TYPE = [ + undefined, + new Map(), + new Map(), + undefined, + new Map(), +]; + +const NPC_TYPE_DATA: NpcTypeData[] = []; + +function define_npc_type_data( + npc_type: NpcType, + name: string, + simple_name: string, + ultimate_name: string, + episode: Episode | undefined, + enemy: boolean, + rare_type?: NpcType, +): void { + if (episode) { + const map = EP_AND_NAME_TO_NPC_TYPE[episode]; + + if (map) { + map.set(simple_name, npc_type); + map.set(ultimate_name, npc_type); + } + } + + NPC_TYPE_DATA[npc_type] = { + name, + simple_name, + ultimate_name, + episode, + enemy, + rare_type, + }; + + if (enemy) { + ENEMY_NPC_TYPES.push(npc_type); + } +} + +// +// Unknown NPCs +// + +define_npc_type_data(NpcType.Unknown, "Unknown", "Unknown", "Unknown", undefined, false); + +// +// Friendly NPCs +// + +define_npc_type_data(NpcType.FemaleFat, "Female Fat", "Female Fat", "Female Fat", undefined, false); +define_npc_type_data( + NpcType.FemaleMacho, + "Female Macho", + "Female Macho", + "Female Macho", + undefined, + false, +); +define_npc_type_data( + NpcType.FemaleTall, + "Female Tall", + "Female Tall", + "Female Tall", + undefined, + false, +); +define_npc_type_data(NpcType.MaleDwarf, "Male Dwarf", "Male Dwarf", "Male Dwarf", undefined, false); +define_npc_type_data(NpcType.MaleFat, "Male Fat", "Male Fat", "Male Fat", undefined, false); +define_npc_type_data(NpcType.MaleMacho, "Male Macho", "Male Macho", "Male Macho", undefined, false); +define_npc_type_data(NpcType.MaleOld, "Male Old", "Male Old", "Male Old", undefined, false); +define_npc_type_data( + NpcType.BlueSoldier, + "Blue Soldier", + "Blue Soldier", + "Blue Soldier", + undefined, + false, +); +define_npc_type_data( + NpcType.RedSoldier, + "Red Soldier", + "Red Soldier", + "Red Soldier", + undefined, + false, +); +define_npc_type_data(NpcType.Principal, "Principal", "Principal", "Principal", undefined, false); +define_npc_type_data(NpcType.Tekker, "Tekker", "Tekker", "Tekker", undefined, false); +define_npc_type_data(NpcType.GuildLady, "Guild Lady", "Guild Lady", "Guild Lady", undefined, false); +define_npc_type_data(NpcType.Scientist, "Scientist", "Scientist", "Scientist", undefined, false); +define_npc_type_data(NpcType.Nurse, "Nurse", "Nurse", "Nurse", undefined, false); +define_npc_type_data(NpcType.Irene, "Irene", "Irene", "Irene", undefined, false); +define_npc_type_data(NpcType.ItemShop, "Item Shop", "Item Shop", "Item Shop", undefined, false); +define_npc_type_data(NpcType.Nurse2, "Nurse (Ep. II);", "Nurse", "Nurse", 2, false); + +// +// Enemy NPCs +// + +// Episode I Forest + +define_npc_type_data( + NpcType.Hildebear, + "Hildebear", + "Hildebear", + "Hildelt", + 1, + true, + NpcType.Hildeblue, +); +define_npc_type_data(NpcType.Hildeblue, "Hildeblue", "Hildeblue", "Hildetorr", 1, true); +define_npc_type_data( + NpcType.RagRappy, + "Rag Rappy", + "Rag Rappy", + "El Rappy", + 1, + true, + NpcType.AlRappy, +); +define_npc_type_data(NpcType.AlRappy, "Al Rappy", "Al Rappy", "Pal Rappy", 1, true); +define_npc_type_data(NpcType.Monest, "Monest", "Monest", "Mothvist", 1, true); +define_npc_type_data(NpcType.Mothmant, "Mothmant", "Mothmant", "Mothvert", 1, true); +define_npc_type_data(NpcType.SavageWolf, "Savage Wolf", "Savage Wolf", "Gulgus", 1, true); +define_npc_type_data( + NpcType.BarbarousWolf, + "Barbarous Wolf", + "Barbarous Wolf", + "Gulgus-Gue", + 1, + true, +); +define_npc_type_data(NpcType.Booma, "Booma", "Booma", "Bartle", 1, true); +define_npc_type_data(NpcType.Gobooma, "Gobooma", "Gobooma", "Barble", 1, true); +define_npc_type_data(NpcType.Gigobooma, "Gigobooma", "Gigobooma", "Tollaw", 1, true); +define_npc_type_data(NpcType.Dragon, "Dragon", "Dragon", "Sil Dragon", 1, true); + +// Episode I Caves + +define_npc_type_data( + NpcType.GrassAssassin, + "Grass Assassin", + "Grass Assassin", + "Crimson Assassin", + 1, + true, +); +define_npc_type_data( + NpcType.PoisonLily, + "Poison Lily", + "Poison Lily", + "Ob Lily", + 1, + true, + NpcType.NarLily, +); +define_npc_type_data(NpcType.NarLily, "Nar Lily", "Nar Lily", "Mil Lily", 1, true); +define_npc_type_data(NpcType.NanoDragon, "Nano Dragon", "Nano Dragon", "Nano Dragon", 1, true); +define_npc_type_data(NpcType.EvilShark, "Evil Shark", "Evil Shark", "Vulmer", 1, true); +define_npc_type_data(NpcType.PalShark, "Pal Shark", "Pal Shark", "Govulmer", 1, true); +define_npc_type_data(NpcType.GuilShark, "Guil Shark", "Guil Shark", "Melqueek", 1, true); +define_npc_type_data( + NpcType.PofuillySlime, + "Pofuilly Slime", + "Pofuilly Slime", + "Pofuilly Slime", + 1, + true, + NpcType.PouillySlime, +); +define_npc_type_data( + NpcType.PouillySlime, + "Pouilly Slime", + "Pouilly Slime", + "Pouilly Slime", + 1, + true, +); +define_npc_type_data(NpcType.PanArms, "Pan Arms", "Pan Arms", "Pan Arms", 1, true); +define_npc_type_data(NpcType.Migium, "Migium", "Migium", "Migium", 1, true); +define_npc_type_data(NpcType.Hidoom, "Hidoom", "Hidoom", "Hidoom", 1, true); +define_npc_type_data(NpcType.DeRolLe, "De Rol Le", "De Rol Le", "Dal Ra Lie", 1, true); + +// Episode I Mines + +define_npc_type_data(NpcType.Dubchic, "Dubchic", "Dubchic", "Dubchich", 1, true); +define_npc_type_data(NpcType.Gilchic, "Gilchic", "Gilchic", "Gilchich", 1, true); +define_npc_type_data(NpcType.Garanz, "Garanz", "Garanz", "Baranz", 1, true); +define_npc_type_data(NpcType.SinowBeat, "Sinow Beat", "Sinow Beat", "Sinow Blue", 1, true); +define_npc_type_data(NpcType.SinowGold, "Sinow Gold", "Sinow Gold", "Sinow Red", 1, true); +define_npc_type_data(NpcType.Canadine, "Canadine", "Canadine", "Canabin", 1, true); +define_npc_type_data(NpcType.Canane, "Canane", "Canane", "Canune", 1, true); +define_npc_type_data(NpcType.Dubswitch, "Dubswitch", "Dubswitch", "Dubswitch", 1, true); +define_npc_type_data(NpcType.VolOpt, "Vol Opt", "Vol Opt", "Vol Opt ver.2", 1, true); + +// Episode I Ruins + +define_npc_type_data(NpcType.Delsaber, "Delsaber", "Delsaber", "Delsaber", 1, true); +define_npc_type_data( + NpcType.ChaosSorcerer, + "Chaos Sorcerer", + "Chaos Sorcerer", + "Gran Sorcerer", + 1, + true, +); +define_npc_type_data(NpcType.DarkGunner, "Dark Gunner", "Dark Gunner", "Dark Gunner", 1, true); +define_npc_type_data(NpcType.DeathGunner, "Death Gunner", "Death Gunner", "Death Gunner", 1, true); +define_npc_type_data( + NpcType.ChaosBringer, + "Chaos Bringer", + "Chaos Bringer", + "Dark Bringer", + 1, + true, +); +define_npc_type_data(NpcType.DarkBelra, "Dark Belra", "Dark Belra", "Indi Belra", 1, true); +define_npc_type_data(NpcType.Dimenian, "Dimenian", "Dimenian", "Arlan", 1, true); +define_npc_type_data(NpcType.LaDimenian, "La Dimenian", "La Dimenian", "Merlan", 1, true); +define_npc_type_data(NpcType.SoDimenian, "So Dimenian", "So Dimenian", "Del-D", 1, true); +define_npc_type_data(NpcType.Bulclaw, "Bulclaw", "Bulclaw", "Bulclaw", 1, true); +define_npc_type_data(NpcType.Bulk, "Bulk", "Bulk", "Bulk", 1, true); +define_npc_type_data(NpcType.Claw, "Claw", "Claw", "Claw", 1, true); +define_npc_type_data(NpcType.DarkFalz, "Dark Falz", "Dark Falz", "Dark Falz", 1, true); + +// Episode II VR Temple + +define_npc_type_data( + NpcType.Hildebear2, + "Hildebear (Ep. II);", + "Hildebear", + "Hildelt", + 2, + true, + NpcType.Hildeblue2, +); +define_npc_type_data(NpcType.Hildeblue2, "Hildeblue (Ep. II);", "Hildeblue", "Hildetorr", 2, true); +define_npc_type_data( + NpcType.RagRappy2, + "Rag Rappy (Ep. II);", + "Rag Rappy", + "El Rappy", + 2, + true, + NpcType.LoveRappy, +); +define_npc_type_data(NpcType.LoveRappy, "Love Rappy", "Love Rappy", "Love Rappy", 2, true); +define_npc_type_data(NpcType.StRappy, "St. Rappy", "St. Rappy", "St. Rappy", 2, true); +define_npc_type_data(NpcType.HalloRappy, "Hallo Rappy", "Hallo Rappy", "Hallo Rappy", 2, true); +define_npc_type_data(NpcType.EggRappy, "Egg Rappy", "Egg Rappy", "Egg Rappy", 2, true); +define_npc_type_data(NpcType.Monest2, "Monest (Ep. II);", "Monest", "Mothvist", 2, true); +define_npc_type_data(NpcType.Mothmant2, "Mothmant", "Mothmant", "Mothvert", 2, true); +define_npc_type_data( + NpcType.PoisonLily2, + "Poison Lily (Ep. II);", + "Poison Lily", + "Ob Lily", + 2, + true, + NpcType.NarLily2, +); +define_npc_type_data(NpcType.NarLily2, "Nar Lily (Ep. II);", "Nar Lily", "Mil Lily", 2, true); +define_npc_type_data( + NpcType.GrassAssassin2, + "Grass Assassin (Ep. II);", + "Grass Assassin", + "Crimson Assassin", + 2, + true, +); +define_npc_type_data(NpcType.Dimenian2, "Dimenian (Ep. II);", "Dimenian", "Arlan", 2, true); +define_npc_type_data( + NpcType.LaDimenian2, + "La Dimenian (Ep. II);", + "La Dimenian", + "Merlan", + 2, + true, +); +define_npc_type_data(NpcType.SoDimenian2, "So Dimenian (Ep. II);", "So Dimenian", "Del-D", 2, true); +define_npc_type_data( + NpcType.DarkBelra2, + "Dark Belra (Ep. II);", + "Dark Belra", + "Indi Belra", + 2, + true, +); +define_npc_type_data(NpcType.BarbaRay, "Barba Ray", "Barba Ray", "Barba Ray", 2, true); + +// Episode II VR Spaceship + +define_npc_type_data( + NpcType.SavageWolf2, + "Savage Wolf (Ep. II);", + "Savage Wolf", + "Gulgus", + 2, + true, +); +define_npc_type_data( + NpcType.BarbarousWolf2, + "Barbarous Wolf (Ep. II);", + "Barbarous Wolf", + "Gulgus-Gue", + 2, + true, +); +define_npc_type_data(NpcType.PanArms2, "Pan Arms (Ep. II);", "Pan Arms", "Pan Arms", 2, true); +define_npc_type_data(NpcType.Migium2, "Migium (Ep. II);", "Migium", "Migium", 2, true); +define_npc_type_data(NpcType.Hidoom2, "Hidoom (Ep. II);", "Hidoom", "Hidoom", 2, true); +define_npc_type_data(NpcType.Dubchic2, "Dubchic (Ep. II);", "Dubchic", "Dubchich", 2, true); +define_npc_type_data(NpcType.Gilchic2, "Gilchic (Ep. II);", "Gilchic", "Gilchich", 2, true); +define_npc_type_data(NpcType.Garanz2, "Garanz (Ep. II);", "Garanz", "Baranz", 2, true); +define_npc_type_data(NpcType.Dubswitch2, "Dubswitch (Ep. II);", "Dubswitch", "Dubswitch", 2, true); +define_npc_type_data(NpcType.Delsaber2, "Delsaber (Ep. II);", "Delsaber", "Delsaber", 2, true); +define_npc_type_data( + NpcType.ChaosSorcerer2, + "Chaos Sorcerer (Ep. II);", + "Chaos Sorcerer", + "Gran Sorcerer", + 2, + true, +); +define_npc_type_data(NpcType.GolDragon, "Gol Dragon", "Gol Dragon", "Gol Dragon", 2, true); + +// Episode II Central Control Area + +define_npc_type_data(NpcType.SinowBerill, "Sinow Berill", "Sinow Berill", "Sinow Berill", 2, true); +define_npc_type_data( + NpcType.SinowSpigell, + "Sinow Spigell", + "Sinow Spigell", + "Sinow Spigell", + 2, + true, +); +define_npc_type_data(NpcType.Merillia, "Merillia", "Merillia", "Merillia", 2, true); +define_npc_type_data(NpcType.Meriltas, "Meriltas", "Meriltas", "Meriltas", 2, true); +define_npc_type_data(NpcType.Mericarol, "Mericarol", "Mericarol", "Mericarol", 2, true); +define_npc_type_data(NpcType.Mericus, "Mericus", "Mericus", "Mericus", 2, true); +define_npc_type_data(NpcType.Merikle, "Merikle", "Merikle", "Merikle", 2, true); +define_npc_type_data(NpcType.UlGibbon, "Ul Gibbon", "Ul Gibbon", "Ul Gibbon", 2, true); +define_npc_type_data(NpcType.ZolGibbon, "Zol Gibbon", "Zol Gibbon", "Zol Gibbon", 2, true); +define_npc_type_data(NpcType.Gibbles, "Gibbles", "Gibbles", "Gibbles", 2, true); +define_npc_type_data(NpcType.Gee, "Gee", "Gee", "Gee", 2, true); +define_npc_type_data(NpcType.GiGue, "Gi Gue", "Gi Gue", "Gi Gue", 2, true); +define_npc_type_data(NpcType.IllGill, "Ill Gill", "Ill Gill", "Ill Gill", 2, true); +define_npc_type_data(NpcType.DelLily, "Del Lily", "Del Lily", "Del Lily", 2, true); +define_npc_type_data(NpcType.Epsilon, "Epsilon", "Epsilon", "Epsilon", 2, true); +define_npc_type_data(NpcType.GalGryphon, "Gal Gryphon", "Gal Gryphon", "Gal Gryphon", 2, true); + +// Episode II Seabed + +define_npc_type_data(NpcType.Deldepth, "Deldepth", "Deldepth", "Deldepth", 2, true); +define_npc_type_data(NpcType.Delbiter, "Delbiter", "Delbiter", "Delbiter", 2, true); +define_npc_type_data(NpcType.Dolmolm, "Dolmolm", "Dolmolm", "Dolmolm", 2, true); +define_npc_type_data(NpcType.Dolmdarl, "Dolmdarl", "Dolmdarl", "Dolmdarl", 2, true); +define_npc_type_data(NpcType.Morfos, "Morfos", "Morfos", "Morfos", 2, true); +define_npc_type_data(NpcType.Recobox, "Recobox", "Recobox", "Recobox", 2, true); +define_npc_type_data(NpcType.Recon, "Recon", "Recon", "Recon", 2, true); +define_npc_type_data(NpcType.SinowZoa, "Sinow Zoa", "Sinow Zoa", "Sinow Zoa", 2, true); +define_npc_type_data(NpcType.SinowZele, "Sinow Zele", "Sinow Zele", "Sinow Zele", 2, true); +define_npc_type_data(NpcType.OlgaFlow, "Olga Flow", "Olga Flow", "Olga Flow", 2, true); + +// Episode IV + +define_npc_type_data( + NpcType.SandRappy, + "Sand Rappy", + "Sand Rappy", + "Sand Rappy", + 4, + true, + NpcType.DelRappy, +); +define_npc_type_data(NpcType.DelRappy, "Del Rappy", "Del Rappy", "Del Rappy", 4, true); +define_npc_type_data(NpcType.Astark, "Astark", "Astark", "Astark", 4, true); +define_npc_type_data( + NpcType.SatelliteLizard, + "Satellite Lizard", + "Satellite Lizard", + "Satellite Lizard", + 4, + true, +); +define_npc_type_data(NpcType.Yowie, "Yowie", "Yowie", "Yowie", 4, true); +define_npc_type_data( + NpcType.MerissaA, + "Merissa A", + "Merissa A", + "Merissa A", + 4, + true, + NpcType.MerissaAA, +); +define_npc_type_data(NpcType.MerissaAA, "Merissa AA", "Merissa AA", "Merissa AA", 4, true); +define_npc_type_data(NpcType.Girtablulu, "Girtablulu", "Girtablulu", "Girtablulu", 4, true); +define_npc_type_data(NpcType.Zu, "Zu", "Zu", "Zu", 4, true, NpcType.Pazuzu); +define_npc_type_data(NpcType.Pazuzu, "Pazuzu", "Pazuzu", "Pazuzu", 4, true); +define_npc_type_data(NpcType.Boota, "Boota", "Boota", "Boota", 4, true); +define_npc_type_data(NpcType.ZeBoota, "Ze Boota", "Ze Boota", "Ze Boota", 4, true); +define_npc_type_data(NpcType.BaBoota, "Ba Boota", "Ba Boota", "Ba Boota", 4, true); +define_npc_type_data( + NpcType.Dorphon, + "Dorphon", + "Dorphon", + "Dorphon", + 4, + true, + NpcType.DorphonEclair, +); +define_npc_type_data( + NpcType.DorphonEclair, + "Dorphon Eclair", + "Dorphon Eclair", + "Dorphon Eclair", + 4, + true, +); +define_npc_type_data(NpcType.Goran, "Goran", "Goran", "Goran", 4, true); +define_npc_type_data(NpcType.PyroGoran, "Pyro Goran", "Pyro Goran", "Pyro Goran", 4, true); +define_npc_type_data( + NpcType.GoranDetonator, + "Goran Detonator", + "Goran Detonator", + "Goran Detonator", + 4, + true, +); +define_npc_type_data( + NpcType.SaintMilion, + "Saint-Milion", + "Saint-Milion", + "Saint-Milion", + 4, + true, + NpcType.Kondrieu, +); +define_npc_type_data( + NpcType.Shambertin, + "Shambertin", + "Shambertin", + "Shambertin", + 4, + true, + NpcType.Kondrieu, +); +define_npc_type_data(NpcType.Kondrieu, "Kondrieu", "Kondrieu", "Kondrieu", 4, true); diff --git a/src/data_formats/parsing/quest/object_types.ts b/src/data_formats/parsing/quest/object_types.ts new file mode 100644 index 00000000..1901949e --- /dev/null +++ b/src/data_formats/parsing/quest/object_types.ts @@ -0,0 +1,1217 @@ +export enum ObjectType { + // Make sure ObjectType does not overlap NpcType. + Unknown = 1000, + PlayerSet, + Particle, + Teleporter, + Warp, + LightCollision, + Item, + EnvSound, + FogCollision, + EventCollision, + CharaCollision, + ElementalTrap, + StatusTrap, + HealTrap, + LargeElementalTrap, + ObjRoomID, + Sensor, + UnknownItem16, + Lensflare, + ScriptCollision, + HealRing, + MapCollision, + ScriptCollisionA, + ItemLight, + RadarCollision, + FogCollisionSW, + BossTeleporter, + ImageBoard, + QuestWarp, + Epilogue, + UnknownItem29, + UnknownItem30, + UnknownItem31, + BoxDetectObject, + SymbolChatObject, + TouchPlateObject, + TargetableObject, + EffectObject, + CountDownObject, + UnknownItem38, + UnknownItem39, + UnknownItem40, + UnknownItem41, + MenuActivation, + TelepipeLocation, + BGMCollision, + MainRagolTeleporter, + LobbyTeleporter, + PrincipalWarp, + ShopDoor, + HuntersGuildDoor, + TeleporterDoor, + MedicalCenterDoor, + Elevator, + EasterEgg, + ValentinesHeart, + ChristmasTree, + ChristmasWreath, + HalloweenPumpkin, + TwentyFirstCentury, + Sonic, + WelcomeBoard, + Firework, + LobbyScreenDoor, + MainRagolTeleporterBattleInNextArea, + LabTeleporterDoor, + Pioneer2InvisibleTouchplate, + ForestDoor, + ForestSwitch, + LaserFence, + LaserSquareFence, + ForestLaserFenceSwitch, + LightRays, + BlueButterfly, + Probe, + RandomTypeBox1, + ForestWeatherStation, + Battery, + ForestConsole, + BlackSlidingDoor, + RicoMessagePod, + EnergyBarrier, + ForestRisingBridge, + SwitchNoneDoor, + EnemyBoxGrey, + FixedTypeBox, + EnemyBoxBrown, + EmptyTypeBox, + LaserFenseEx, + LaserSquareFenceEx, + FloorPanel1, + Caves4ButtonDoor, + CavesNormalDoor, + CavesSmashingPillar, + CavesSign1, + CavesSign2, + CavesSign3, + HexagalTank, + BrownPlatform, + WarningLightObject, + Rainbow, + FloatingJelifish, + FloatingDragonfly, + CavesSwitchDoor, + RobotRechargeStation, + CavesCakeShop, + Caves1SmallRedRock, + Caves1MediumRedRock, + Caves1LargeRedRock, + Caves2SmallRock1, + Caves2MediumRock1, + Caves2LargeRock1, + Caves2SmallRock2, + Caves2MediumRock2, + Caves2LargeRock2, + Caves3SmallRock, + Caves3MediumRock, + Caves3LargeRock, + FloorPanel2, + DestructableRockCaves1, + DestructableRockCaves2, + DestructableRockCaves3, + MinesDoor, + FloorPanel3, + MinesSwitchDoor, + LargeCryoTube, + ComputerLikeCalus, + GreenScreenOpeningAndClosing, + FloatingRobot, + FloatingBlueLight, + SelfDestructingObject1, + SelfDestructingObject2, + SelfDestructingObject3, + SparkMachine, + MinesLargeFlashingCrate, + RuinsSeal, + RuinsTeleporter, + RuinsWarpSiteToSite, + RuinsSwitch, + FloorPanel4, + Ruins1Door, + Ruins3Door, + Ruins2Door, + Ruins11ButtonDoor, + Ruins21ButtonDoor, + Ruins31ButtonDoor, + Ruins4ButtonDoor, + Ruins2ButtonDoor, + RuinsSensor, + RuinsFenceSwitch, + RuinsLaserFence4x2, + RuinsLaserFence6x2, + RuinsLaserFence4x4, + RuinsLaserFence6x4, + RuinsPoisonBlob, + RuinsPilarTrap, + PopupTrapNoTech, + RuinsCrystal, + Monument, + RuinsRock1, + RuinsRock2, + RuinsRock3, + RuinsRock4, + RuinsRock5, + RuinsRock6, + RuinsRock7, + Poison, + FixedBoxTypeRuins, + RandomBoxTypeRuins, + EnemyTypeBoxYellow, + EnemyTypeBoxBlue, + EmptyTypeBoxBlue, + DestructableRock, + PopupTrapsTechs, + FlyingWhiteBird, + Tower, + FloatingRocks, + FloatingSoul, + Butterfly, + LobbyGameMenu, + LobbyWarpObject, + Lobby1EventObjectDefaultTree, + UnknownItem387, + UnknownItem388, + UnknownItem389, + LobbyEventObjectStaticPumpkin, + LobbyEventObject3ChristmasWindows, + LobbyEventObjectRedAndWhiteCurtain, + UnknownItem393, + UnknownItem394, + LobbyFishTank, + LobbyEventObjectButterflies, + UnknownItem400, + GreyWallLow, + SpaceshipDoor, + GreyWallHigh, + TempleNormalDoor, + BreakableWallWallButUnbreakable, + BrokenCilinderAndRubble, + ThreeBrokenWallPiecesOnFloor, + HighBrickCilinder, + LyingCilinder, + BrickConeWithFlatTop, + BreakableTempleWall, + TempleMapDetect, + SmallBrownBrickRisingBridge, + LongRisingBridgeWithPinkHighEdges, + FourSwitchTempleDoor, + FourButtonSpaceshipDoor, + ItemBoxCca, + TeleporterEp2, + CCADoor, + SpecialBoxCCA, + BigCCADoor, + BigCCADoorSwitch, + LittleRock, + Little3StoneWall, + Medium3StoneWall, + SpiderPlant, + CCAAreaTeleporter, + UnknownItem523, + WhiteBird, + OrangeBird, + Saw, + LaserDetect, + UnknownItem529, + UnknownItem530, + Seagull, + Fish, + SeabedDoorWithBlueEdges, + SeabedDoorAlwaysOpenNonTriggerable, + LittleCryotube, + WideGlassWallBreakable, + BlueFloatingRobot, + RedFloatingRobot, + Dolphin, + CaptureTrap, + VRLink, + UnknownItem576, + WarpInBarbaRayRoom, + UnknownItem672, + GeeNest, + LabComputerConsole, + LabComputerConsoleGreenScreen, + ChairYelllowPillow, + OrangeWallWithHoleInMiddle, + GreyWallWithHoleInMiddle, + LongTable, + GBAStation, + TalkLinkToSupport, + InstaWarp, + LabInvisibleObject, + LabGlassWindowDoor, + UnknownItem700, + LabCelingWarp, + Ep4LightSource, + Cacti, + BigBrownRock, + BreakableBrownRock, + UnknownItem832, + UnknownItem833, + PoisonPlant, + UnknownItem897, + UnknownItem898, + OozingDesertPlant, + UnknownItem901, + BigBlackRocks, + UnknownItem903, + UnknownItem904, + UnknownItem905, + UnknownItem906, + FallingRock, + DesertPlantHasCollision, + DesertFixedTypeBoxBreakableCrystals, + UnknownItem910, + BeeHive, + UnknownItem912, + Heat, + TopOfSaintMillionEgg, + UnknownItem961, +} + +export type ObjectTypeData = { + readonly name: string; + readonly pso_id?: number; +}; + +export function object_data(type: ObjectType): ObjectTypeData { + return OBJECT_TYPE_DATA[type]; +} + +export function pso_id_to_object_type(psoId: number): ObjectType { + switch (psoId) { + default: + return ObjectType.Unknown; + + case 0: + return ObjectType.PlayerSet; + case 1: + return ObjectType.Particle; + case 2: + return ObjectType.Teleporter; + case 3: + return ObjectType.Warp; + case 4: + return ObjectType.LightCollision; + case 5: + return ObjectType.Item; + case 6: + return ObjectType.EnvSound; + case 7: + return ObjectType.FogCollision; + case 8: + return ObjectType.EventCollision; + case 9: + return ObjectType.CharaCollision; + case 10: + return ObjectType.ElementalTrap; + case 11: + return ObjectType.StatusTrap; + case 12: + return ObjectType.HealTrap; + case 13: + return ObjectType.LargeElementalTrap; + case 14: + return ObjectType.ObjRoomID; + case 15: + return ObjectType.Sensor; + case 16: + return ObjectType.UnknownItem16; + case 17: + return ObjectType.Lensflare; + case 18: + return ObjectType.ScriptCollision; + case 19: + return ObjectType.HealRing; + case 20: + return ObjectType.MapCollision; + case 21: + return ObjectType.ScriptCollisionA; + case 22: + return ObjectType.ItemLight; + case 23: + return ObjectType.RadarCollision; + case 24: + return ObjectType.FogCollisionSW; + case 25: + return ObjectType.BossTeleporter; + case 26: + return ObjectType.ImageBoard; + case 27: + return ObjectType.QuestWarp; + case 28: + return ObjectType.Epilogue; + case 29: + return ObjectType.UnknownItem29; + case 30: + return ObjectType.UnknownItem30; + case 31: + return ObjectType.UnknownItem31; + case 32: + return ObjectType.BoxDetectObject; + case 33: + return ObjectType.SymbolChatObject; + case 34: + return ObjectType.TouchPlateObject; + case 35: + return ObjectType.TargetableObject; + case 36: + return ObjectType.EffectObject; + case 37: + return ObjectType.CountDownObject; + case 38: + return ObjectType.UnknownItem38; + case 39: + return ObjectType.UnknownItem39; + case 40: + return ObjectType.UnknownItem40; + case 41: + return ObjectType.UnknownItem41; + case 64: + return ObjectType.MenuActivation; + case 65: + return ObjectType.TelepipeLocation; + case 66: + return ObjectType.BGMCollision; + case 67: + return ObjectType.MainRagolTeleporter; + case 68: + return ObjectType.LobbyTeleporter; + case 69: + return ObjectType.PrincipalWarp; + case 70: + return ObjectType.ShopDoor; + case 71: + return ObjectType.HuntersGuildDoor; + case 72: + return ObjectType.TeleporterDoor; + case 73: + return ObjectType.MedicalCenterDoor; + case 74: + return ObjectType.Elevator; + case 75: + return ObjectType.EasterEgg; + case 76: + return ObjectType.ValentinesHeart; + case 77: + return ObjectType.ChristmasTree; + case 78: + return ObjectType.ChristmasWreath; + case 79: + return ObjectType.HalloweenPumpkin; + case 80: + return ObjectType.TwentyFirstCentury; + case 81: + return ObjectType.Sonic; + case 82: + return ObjectType.WelcomeBoard; + case 83: + return ObjectType.Firework; + case 84: + return ObjectType.LobbyScreenDoor; + case 85: + return ObjectType.MainRagolTeleporterBattleInNextArea; + case 86: + return ObjectType.LabTeleporterDoor; + case 87: + return ObjectType.Pioneer2InvisibleTouchplate; + case 128: + return ObjectType.ForestDoor; + case 129: + return ObjectType.ForestSwitch; + case 130: + return ObjectType.LaserFence; + case 131: + return ObjectType.LaserSquareFence; + case 132: + return ObjectType.ForestLaserFenceSwitch; + case 133: + return ObjectType.LightRays; + case 134: + return ObjectType.BlueButterfly; + case 135: + return ObjectType.Probe; + case 136: + return ObjectType.RandomTypeBox1; + case 137: + return ObjectType.ForestWeatherStation; + case 138: + return ObjectType.Battery; + case 139: + return ObjectType.ForestConsole; + case 140: + return ObjectType.BlackSlidingDoor; + case 141: + return ObjectType.RicoMessagePod; + case 142: + return ObjectType.EnergyBarrier; + case 143: + return ObjectType.ForestRisingBridge; + case 144: + return ObjectType.SwitchNoneDoor; + case 145: + return ObjectType.EnemyBoxGrey; + case 146: + return ObjectType.FixedTypeBox; + case 147: + return ObjectType.EnemyBoxBrown; + case 149: + return ObjectType.EmptyTypeBox; + case 150: + return ObjectType.LaserFenseEx; + case 151: + return ObjectType.LaserSquareFenceEx; + case 192: + return ObjectType.FloorPanel1; + case 193: + return ObjectType.Caves4ButtonDoor; + case 194: + return ObjectType.CavesNormalDoor; + case 195: + return ObjectType.CavesSmashingPillar; + case 196: + return ObjectType.CavesSign1; + case 197: + return ObjectType.CavesSign2; + case 198: + return ObjectType.CavesSign3; + case 199: + return ObjectType.HexagalTank; + case 200: + return ObjectType.BrownPlatform; + case 201: + return ObjectType.WarningLightObject; + case 203: + return ObjectType.Rainbow; + case 204: + return ObjectType.FloatingJelifish; + case 205: + return ObjectType.FloatingDragonfly; + case 206: + return ObjectType.CavesSwitchDoor; + case 207: + return ObjectType.RobotRechargeStation; + case 208: + return ObjectType.CavesCakeShop; + case 209: + return ObjectType.Caves1SmallRedRock; + case 210: + return ObjectType.Caves1MediumRedRock; + case 211: + return ObjectType.Caves1LargeRedRock; + case 212: + return ObjectType.Caves2SmallRock1; + case 213: + return ObjectType.Caves2MediumRock1; + case 214: + return ObjectType.Caves2LargeRock1; + case 215: + return ObjectType.Caves2SmallRock2; + case 216: + return ObjectType.Caves2MediumRock2; + case 217: + return ObjectType.Caves2LargeRock2; + case 218: + return ObjectType.Caves3SmallRock; + case 219: + return ObjectType.Caves3MediumRock; + case 220: + return ObjectType.Caves3LargeRock; + case 222: + return ObjectType.FloorPanel2; + case 223: + return ObjectType.DestructableRockCaves1; + case 224: + return ObjectType.DestructableRockCaves2; + case 225: + return ObjectType.DestructableRockCaves3; + case 256: + return ObjectType.MinesDoor; + case 257: + return ObjectType.FloorPanel3; + case 258: + return ObjectType.MinesSwitchDoor; + case 259: + return ObjectType.LargeCryoTube; + case 260: + return ObjectType.ComputerLikeCalus; + case 261: + return ObjectType.GreenScreenOpeningAndClosing; + case 262: + return ObjectType.FloatingRobot; + case 263: + return ObjectType.FloatingBlueLight; + case 264: + return ObjectType.SelfDestructingObject1; + case 265: + return ObjectType.SelfDestructingObject2; + case 266: + return ObjectType.SelfDestructingObject3; + case 267: + return ObjectType.SparkMachine; + case 268: + return ObjectType.MinesLargeFlashingCrate; + case 304: + return ObjectType.RuinsSeal; + case 320: + return ObjectType.RuinsTeleporter; + case 321: + return ObjectType.RuinsWarpSiteToSite; + case 322: + return ObjectType.RuinsSwitch; + case 323: + return ObjectType.FloorPanel4; + case 324: + return ObjectType.Ruins1Door; + case 325: + return ObjectType.Ruins3Door; + case 326: + return ObjectType.Ruins2Door; + case 327: + return ObjectType.Ruins11ButtonDoor; + case 328: + return ObjectType.Ruins21ButtonDoor; + case 329: + return ObjectType.Ruins31ButtonDoor; + case 330: + return ObjectType.Ruins4ButtonDoor; + case 331: + return ObjectType.Ruins2ButtonDoor; + case 332: + return ObjectType.RuinsSensor; + case 333: + return ObjectType.RuinsFenceSwitch; + case 334: + return ObjectType.RuinsLaserFence4x2; + case 335: + return ObjectType.RuinsLaserFence6x2; + case 336: + return ObjectType.RuinsLaserFence4x4; + case 337: + return ObjectType.RuinsLaserFence6x4; + case 338: + return ObjectType.RuinsPoisonBlob; + case 339: + return ObjectType.RuinsPilarTrap; + case 340: + return ObjectType.PopupTrapNoTech; + case 341: + return ObjectType.RuinsCrystal; + case 342: + return ObjectType.Monument; + case 345: + return ObjectType.RuinsRock1; + case 346: + return ObjectType.RuinsRock2; + case 347: + return ObjectType.RuinsRock3; + case 348: + return ObjectType.RuinsRock4; + case 349: + return ObjectType.RuinsRock5; + case 350: + return ObjectType.RuinsRock6; + case 351: + return ObjectType.RuinsRock7; + case 352: + return ObjectType.Poison; + case 353: + return ObjectType.FixedBoxTypeRuins; + case 354: + return ObjectType.RandomBoxTypeRuins; + case 355: + return ObjectType.EnemyTypeBoxYellow; + case 356: + return ObjectType.EnemyTypeBoxBlue; + case 357: + return ObjectType.EmptyTypeBoxBlue; + case 358: + return ObjectType.DestructableRock; + case 359: + return ObjectType.PopupTrapsTechs; + case 368: + return ObjectType.FlyingWhiteBird; + case 369: + return ObjectType.Tower; + case 370: + return ObjectType.FloatingRocks; + case 371: + return ObjectType.FloatingSoul; + case 372: + return ObjectType.Butterfly; + case 384: + return ObjectType.LobbyGameMenu; + case 385: + return ObjectType.LobbyWarpObject; + case 386: + return ObjectType.Lobby1EventObjectDefaultTree; + case 387: + return ObjectType.UnknownItem387; + case 388: + return ObjectType.UnknownItem388; + case 389: + return ObjectType.UnknownItem389; + case 390: + return ObjectType.LobbyEventObjectStaticPumpkin; + case 391: + return ObjectType.LobbyEventObject3ChristmasWindows; + case 392: + return ObjectType.LobbyEventObjectRedAndWhiteCurtain; + case 393: + return ObjectType.UnknownItem393; + case 394: + return ObjectType.UnknownItem394; + case 395: + return ObjectType.LobbyFishTank; + case 396: + return ObjectType.LobbyEventObjectButterflies; + case 400: + return ObjectType.UnknownItem400; + case 401: + return ObjectType.GreyWallLow; + case 402: + return ObjectType.SpaceshipDoor; + case 403: + return ObjectType.GreyWallHigh; + case 416: + return ObjectType.TempleNormalDoor; + case 417: + return ObjectType.BreakableWallWallButUnbreakable; + case 418: + return ObjectType.BrokenCilinderAndRubble; + case 419: + return ObjectType.ThreeBrokenWallPiecesOnFloor; + case 420: + return ObjectType.HighBrickCilinder; + case 421: + return ObjectType.LyingCilinder; + case 422: + return ObjectType.BrickConeWithFlatTop; + case 423: + return ObjectType.BreakableTempleWall; + case 424: + return ObjectType.TempleMapDetect; + case 425: + return ObjectType.SmallBrownBrickRisingBridge; + case 426: + return ObjectType.LongRisingBridgeWithPinkHighEdges; + case 427: + return ObjectType.FourSwitchTempleDoor; + case 448: + return ObjectType.FourButtonSpaceshipDoor; + case 512: + return ObjectType.ItemBoxCca; + case 513: + return ObjectType.TeleporterEp2; + case 514: + return ObjectType.CCADoor; + case 515: + return ObjectType.SpecialBoxCCA; + case 516: + return ObjectType.BigCCADoor; + case 517: + return ObjectType.BigCCADoorSwitch; + case 518: + return ObjectType.LittleRock; + case 519: + return ObjectType.Little3StoneWall; + case 520: + return ObjectType.Medium3StoneWall; + case 521: + return ObjectType.SpiderPlant; + case 522: + return ObjectType.CCAAreaTeleporter; + case 523: + return ObjectType.UnknownItem523; + case 524: + return ObjectType.WhiteBird; + case 525: + return ObjectType.OrangeBird; + case 527: + return ObjectType.Saw; + case 528: + return ObjectType.LaserDetect; + case 529: + return ObjectType.UnknownItem529; + case 530: + return ObjectType.UnknownItem530; + case 531: + return ObjectType.Seagull; + case 544: + return ObjectType.Fish; + case 545: + return ObjectType.SeabedDoorWithBlueEdges; + case 546: + return ObjectType.SeabedDoorAlwaysOpenNonTriggerable; + case 547: + return ObjectType.LittleCryotube; + case 548: + return ObjectType.WideGlassWallBreakable; + case 549: + return ObjectType.BlueFloatingRobot; + case 550: + return ObjectType.RedFloatingRobot; + case 551: + return ObjectType.Dolphin; + case 552: + return ObjectType.CaptureTrap; + case 553: + return ObjectType.VRLink; + case 576: + return ObjectType.UnknownItem576; + case 640: + return ObjectType.WarpInBarbaRayRoom; + case 672: + return ObjectType.UnknownItem672; + case 688: + return ObjectType.GeeNest; + case 689: + return ObjectType.LabComputerConsole; + case 690: + return ObjectType.LabComputerConsoleGreenScreen; + case 691: + return ObjectType.ChairYelllowPillow; + case 692: + return ObjectType.OrangeWallWithHoleInMiddle; + case 693: + return ObjectType.GreyWallWithHoleInMiddle; + case 694: + return ObjectType.LongTable; + case 695: + return ObjectType.GBAStation; + case 696: + return ObjectType.TalkLinkToSupport; + case 697: + return ObjectType.InstaWarp; + case 698: + return ObjectType.LabInvisibleObject; + case 699: + return ObjectType.LabGlassWindowDoor; + case 700: + return ObjectType.UnknownItem700; + case 701: + return ObjectType.LabCelingWarp; + case 768: + return ObjectType.Ep4LightSource; + case 769: + return ObjectType.Cacti; + case 770: + return ObjectType.BigBrownRock; + case 771: + return ObjectType.BreakableBrownRock; + case 832: + return ObjectType.UnknownItem832; + case 833: + return ObjectType.UnknownItem833; + case 896: + return ObjectType.PoisonPlant; + case 897: + return ObjectType.UnknownItem897; + case 898: + return ObjectType.UnknownItem898; + case 899: + return ObjectType.OozingDesertPlant; + case 901: + return ObjectType.UnknownItem901; + case 902: + return ObjectType.BigBlackRocks; + case 903: + return ObjectType.UnknownItem903; + case 904: + return ObjectType.UnknownItem904; + case 905: + return ObjectType.UnknownItem905; + case 906: + return ObjectType.UnknownItem906; + case 907: + return ObjectType.FallingRock; + case 908: + return ObjectType.DesertPlantHasCollision; + case 909: + return ObjectType.DesertFixedTypeBoxBreakableCrystals; + case 910: + return ObjectType.UnknownItem910; + case 911: + return ObjectType.BeeHive; + case 912: + return ObjectType.UnknownItem912; + case 913: + return ObjectType.Heat; + case 960: + return ObjectType.TopOfSaintMillionEgg; + case 961: + return ObjectType.UnknownItem961; + } +} + +const OBJECT_TYPE_DATA: ObjectTypeData[] = []; + +function define_object_type_data( + object_type: ObjectType, + pso_id: number | undefined, + name: string, +): void { + OBJECT_TYPE_DATA[object_type] = { + name, + pso_id, + }; +} + +define_object_type_data(ObjectType.Unknown, undefined, "Unknown"); + +define_object_type_data(ObjectType.PlayerSet, 0, "Player Set"); +define_object_type_data(ObjectType.Particle, 1, "Particle"); +define_object_type_data(ObjectType.Teleporter, 2, "Teleporter"); +define_object_type_data(ObjectType.Warp, 3, "Warp"); +define_object_type_data(ObjectType.LightCollision, 4, "Light Collision"); +define_object_type_data(ObjectType.Item, 5, "Item"); +define_object_type_data(ObjectType.EnvSound, 6, "Env Sound"); +define_object_type_data(ObjectType.FogCollision, 7, "Fog Collision"); +define_object_type_data(ObjectType.EventCollision, 8, "Event Collision"); +define_object_type_data(ObjectType.CharaCollision, 9, "Chara Collision"); +define_object_type_data(ObjectType.ElementalTrap, 10, "Elemental Trap"); +define_object_type_data(ObjectType.StatusTrap, 11, "Status Trap"); +define_object_type_data(ObjectType.HealTrap, 12, "Heal Trap"); +define_object_type_data(ObjectType.LargeElementalTrap, 13, "Large Elemental Trap"); +define_object_type_data(ObjectType.ObjRoomID, 14, "Obj Room ID"); +define_object_type_data(ObjectType.Sensor, 15, "Sensor"); +define_object_type_data(ObjectType.UnknownItem16, 16, "Unknown Item (16)"); +define_object_type_data(ObjectType.Lensflare, 17, "Lensflare"); +define_object_type_data(ObjectType.ScriptCollision, 18, "Script Collision"); +define_object_type_data(ObjectType.HealRing, 19, "Heal Ring"); +define_object_type_data(ObjectType.MapCollision, 20, "Map Collision"); +define_object_type_data(ObjectType.ScriptCollisionA, 21, "Script Collision A"); +define_object_type_data(ObjectType.ItemLight, 22, "Item Light"); +define_object_type_data(ObjectType.RadarCollision, 23, "Radar Collision"); +define_object_type_data(ObjectType.FogCollisionSW, 24, "Fog Collision SW"); +define_object_type_data(ObjectType.BossTeleporter, 25, "Boss Teleporter"); +define_object_type_data(ObjectType.ImageBoard, 26, "Image Board"); +define_object_type_data(ObjectType.QuestWarp, 27, "Quest Warp"); +define_object_type_data(ObjectType.Epilogue, 28, "Epilogue"); +define_object_type_data(ObjectType.UnknownItem29, 29, "Unknown Item (29)"); +define_object_type_data(ObjectType.UnknownItem30, 30, "Unknown Item (30)"); +define_object_type_data(ObjectType.UnknownItem31, 31, "Unknown Item (31)"); +define_object_type_data(ObjectType.BoxDetectObject, 32, "Box Detect Object"); +define_object_type_data(ObjectType.SymbolChatObject, 33, "Symbol Chat Object"); +define_object_type_data(ObjectType.TouchPlateObject, 34, "Touch plate Object"); +define_object_type_data(ObjectType.TargetableObject, 35, "Targetable Object"); +define_object_type_data(ObjectType.EffectObject, 36, "Effect object"); +define_object_type_data(ObjectType.CountDownObject, 37, "Count Down Object"); +define_object_type_data(ObjectType.UnknownItem38, 38, "Unknown Item (38)"); +define_object_type_data(ObjectType.UnknownItem39, 39, "Unknown Item (39)"); +define_object_type_data(ObjectType.UnknownItem40, 40, "Unknown Item (40)"); +define_object_type_data(ObjectType.UnknownItem41, 41, "Unknown Item (41)"); +define_object_type_data(ObjectType.MenuActivation, 64, "Menu activation"); +define_object_type_data(ObjectType.TelepipeLocation, 65, "Telepipe Location"); +define_object_type_data(ObjectType.BGMCollision, 66, "BGM Collision"); +define_object_type_data(ObjectType.MainRagolTeleporter, 67, "Main Ragol Teleporter"); +define_object_type_data(ObjectType.LobbyTeleporter, 68, "Lobby Teleporter"); +define_object_type_data(ObjectType.PrincipalWarp, 69, "Principal warp"); +define_object_type_data(ObjectType.ShopDoor, 70, "Shop Door"); +define_object_type_data(ObjectType.HuntersGuildDoor, 71, "Hunter's Guild Door"); +define_object_type_data(ObjectType.TeleporterDoor, 72, "Teleporter Door"); +define_object_type_data(ObjectType.MedicalCenterDoor, 73, "Medical Center Door"); +define_object_type_data(ObjectType.Elevator, 74, "Elevator"); +define_object_type_data(ObjectType.EasterEgg, 75, "Easter Egg"); +define_object_type_data(ObjectType.ValentinesHeart, 76, "Valentines Heart"); +define_object_type_data(ObjectType.ChristmasTree, 77, "Christmas Tree"); +define_object_type_data(ObjectType.ChristmasWreath, 78, "Christmas Wreath"); +define_object_type_data(ObjectType.HalloweenPumpkin, 79, "Halloween Pumpkin"); +define_object_type_data(ObjectType.TwentyFirstCentury, 80, "21st Century"); +define_object_type_data(ObjectType.Sonic, 81, "Sonic"); +define_object_type_data(ObjectType.WelcomeBoard, 82, "Welcome Board"); +define_object_type_data(ObjectType.Firework, 83, "Firework"); +define_object_type_data(ObjectType.LobbyScreenDoor, 84, "Lobby Screen Door"); +define_object_type_data( + ObjectType.MainRagolTeleporterBattleInNextArea, + 85, + "Main Ragol Teleporter (Battle in next area?)", +); +define_object_type_data(ObjectType.LabTeleporterDoor, 86, "Lab Teleporter Door"); +define_object_type_data( + ObjectType.Pioneer2InvisibleTouchplate, + 87, + "Pioneer 2 Invisible Touchplate", +); +define_object_type_data(ObjectType.ForestDoor, 128, "Forest Door"); +define_object_type_data(ObjectType.ForestSwitch, 129, "Forest Switch"); +define_object_type_data(ObjectType.LaserFence, 130, "Laser Fence"); +define_object_type_data(ObjectType.LaserSquareFence, 131, "Laser Square Fence"); +define_object_type_data(ObjectType.ForestLaserFenceSwitch, 132, "Forest Laser Fence Switch"); +define_object_type_data(ObjectType.LightRays, 133, "Light rays"); +define_object_type_data(ObjectType.BlueButterfly, 134, "Blue Butterfly"); +define_object_type_data(ObjectType.Probe, 135, "Probe"); +define_object_type_data(ObjectType.RandomTypeBox1, 136, "Random Type Box 1"); +define_object_type_data(ObjectType.ForestWeatherStation, 137, "Forest Weather Station"); +define_object_type_data(ObjectType.Battery, 138, "Battery"); +define_object_type_data(ObjectType.ForestConsole, 139, "Forest Console"); +define_object_type_data(ObjectType.BlackSlidingDoor, 140, "Black Sliding Door"); +define_object_type_data(ObjectType.RicoMessagePod, 141, "Rico Message Pod"); +define_object_type_data(ObjectType.EnergyBarrier, 142, "Energy Barrier"); +define_object_type_data(ObjectType.ForestRisingBridge, 143, "Forest Rising Bridge"); +define_object_type_data(ObjectType.SwitchNoneDoor, 144, "Switch (none door)"); +define_object_type_data(ObjectType.EnemyBoxGrey, 145, "Enemy Box (Grey)"); +define_object_type_data(ObjectType.FixedTypeBox, 146, "Fixed Type Box"); +define_object_type_data(ObjectType.EnemyBoxBrown, 147, "Enemy Box (Brown)"); +define_object_type_data(ObjectType.EmptyTypeBox, 149, "Empty Type Box"); +define_object_type_data(ObjectType.LaserFenseEx, 150, "Laser Fense Ex"); +define_object_type_data(ObjectType.LaserSquareFenceEx, 151, "Laser Square Fence Ex"); +define_object_type_data(ObjectType.FloorPanel1, 192, "Floor Panel 1"); +define_object_type_data(ObjectType.Caves4ButtonDoor, 193, "Caves 4 Button door"); +define_object_type_data(ObjectType.CavesNormalDoor, 194, "Caves Normal door"); +define_object_type_data(ObjectType.CavesSmashingPillar, 195, "Caves Smashing Pillar"); +define_object_type_data(ObjectType.CavesSign1, 196, "Caves Sign 1"); +define_object_type_data(ObjectType.CavesSign2, 197, "Caves Sign 2"); +define_object_type_data(ObjectType.CavesSign3, 198, "Caves Sign 3"); +define_object_type_data(ObjectType.HexagalTank, 199, "Hexagal Tank"); +define_object_type_data(ObjectType.BrownPlatform, 200, "Brown Platform"); +define_object_type_data(ObjectType.WarningLightObject, 201, "Warning Light Object"); +define_object_type_data(ObjectType.Rainbow, 203, "Rainbow"); +define_object_type_data(ObjectType.FloatingJelifish, 204, "Floating Jelifish"); +define_object_type_data(ObjectType.FloatingDragonfly, 205, "Floating Dragonfly"); +define_object_type_data(ObjectType.CavesSwitchDoor, 206, "Caves Switch Door"); +define_object_type_data(ObjectType.RobotRechargeStation, 207, "Robot Recharge Station"); +define_object_type_data(ObjectType.CavesCakeShop, 208, "Caves Cake Shop"); +define_object_type_data(ObjectType.Caves1SmallRedRock, 209, "Caves 1 Small Red Rock"); +define_object_type_data(ObjectType.Caves1MediumRedRock, 210, "Caves 1 Medium Red Rock"); +define_object_type_data(ObjectType.Caves1LargeRedRock, 211, "Caves 1 Large Red Rock"); +define_object_type_data(ObjectType.Caves2SmallRock1, 212, "Caves 2 Small Rock 1"); +define_object_type_data(ObjectType.Caves2MediumRock1, 213, "Caves 2 Medium Rock 1"); +define_object_type_data(ObjectType.Caves2LargeRock1, 214, "Caves 2 Large Rock 1"); +define_object_type_data(ObjectType.Caves2SmallRock2, 215, "Caves 2 Small Rock 2"); +define_object_type_data(ObjectType.Caves2MediumRock2, 216, "Caves 2 Medium Rock 2"); +define_object_type_data(ObjectType.Caves2LargeRock2, 217, "Caves 2 Large Rock 2"); +define_object_type_data(ObjectType.Caves3SmallRock, 218, "Caves 3 Small Rock"); +define_object_type_data(ObjectType.Caves3MediumRock, 219, "Caves 3 Medium Rock"); +define_object_type_data(ObjectType.Caves3LargeRock, 220, "Caves 3 Large Rock"); +define_object_type_data(ObjectType.FloorPanel2, 222, "Floor Panel 2"); +define_object_type_data(ObjectType.DestructableRockCaves1, 223, "Destructable Rock (Caves 1)"); +define_object_type_data(ObjectType.DestructableRockCaves2, 224, "Destructable Rock (Caves 2)"); +define_object_type_data(ObjectType.DestructableRockCaves3, 225, "Destructable Rock (Caves 3)"); +define_object_type_data(ObjectType.MinesDoor, 256, "Mines Door"); +define_object_type_data(ObjectType.FloorPanel3, 257, "Floor Panel 3"); +define_object_type_data(ObjectType.MinesSwitchDoor, 258, "Mines Switch Door"); +define_object_type_data(ObjectType.LargeCryoTube, 259, "Large Cryo-Tube"); +define_object_type_data(ObjectType.ComputerLikeCalus, 260, "Computer (like calus)"); +define_object_type_data( + ObjectType.GreenScreenOpeningAndClosing, + 261, + "Green Screen opening and closing", +); +define_object_type_data(ObjectType.FloatingRobot, 262, "Floating Robot"); +define_object_type_data(ObjectType.FloatingBlueLight, 263, "Floating Blue Light"); +define_object_type_data(ObjectType.SelfDestructingObject1, 264, "Self Destructing Object 1"); +define_object_type_data(ObjectType.SelfDestructingObject2, 265, "Self Destructing Object 2"); +define_object_type_data(ObjectType.SelfDestructingObject3, 266, "Self Destructing Object 3"); +define_object_type_data(ObjectType.SparkMachine, 267, "Spark Machine"); +define_object_type_data(ObjectType.MinesLargeFlashingCrate, 268, "Mines Large Flashing Crate"); +define_object_type_data(ObjectType.RuinsSeal, 304, "Ruins Seal"); +define_object_type_data(ObjectType.RuinsTeleporter, 320, "Ruins Teleporter"); +define_object_type_data(ObjectType.RuinsWarpSiteToSite, 321, "Ruins Warp (Site to site)"); +define_object_type_data(ObjectType.RuinsSwitch, 322, "Ruins Switch"); +define_object_type_data(ObjectType.FloorPanel4, 323, "Floor Panel 4"); +define_object_type_data(ObjectType.Ruins1Door, 324, "Ruins 1 Door"); +define_object_type_data(ObjectType.Ruins3Door, 325, "Ruins 3 Door"); +define_object_type_data(ObjectType.Ruins2Door, 326, "Ruins 2 Door"); +define_object_type_data(ObjectType.Ruins11ButtonDoor, 327, "Ruins 1-1 Button Door"); +define_object_type_data(ObjectType.Ruins21ButtonDoor, 328, "Ruins 2-1 Button Door"); +define_object_type_data(ObjectType.Ruins31ButtonDoor, 329, "Ruins 3-1 Button Door"); +define_object_type_data(ObjectType.Ruins4ButtonDoor, 330, "Ruins 4-Button Door"); +define_object_type_data(ObjectType.Ruins2ButtonDoor, 331, "Ruins 2-Button Door"); +define_object_type_data(ObjectType.RuinsSensor, 332, "Ruins Sensor"); +define_object_type_data(ObjectType.RuinsFenceSwitch, 333, "Ruins Fence Switch"); +define_object_type_data(ObjectType.RuinsLaserFence4x2, 334, "Ruins Laser Fence 4x2"); +define_object_type_data(ObjectType.RuinsLaserFence6x2, 335, "Ruins Laser Fence 6x2"); +define_object_type_data(ObjectType.RuinsLaserFence4x4, 336, "Ruins Laser Fence 4x4"); +define_object_type_data(ObjectType.RuinsLaserFence6x4, 337, "Ruins Laser Fence 6x4"); +define_object_type_data(ObjectType.RuinsPoisonBlob, 338, "Ruins poison Blob"); +define_object_type_data(ObjectType.RuinsPilarTrap, 339, "Ruins Pilar Trap"); +define_object_type_data(ObjectType.PopupTrapNoTech, 340, "Popup Trap (No Tech)"); +define_object_type_data(ObjectType.RuinsCrystal, 341, "Ruins Crystal"); +define_object_type_data(ObjectType.Monument, 342, "Monument"); +define_object_type_data(ObjectType.RuinsRock1, 345, "Ruins Rock 1"); +define_object_type_data(ObjectType.RuinsRock2, 346, "Ruins Rock 2"); +define_object_type_data(ObjectType.RuinsRock3, 347, "Ruins Rock 3"); +define_object_type_data(ObjectType.RuinsRock4, 348, "Ruins Rock 4"); +define_object_type_data(ObjectType.RuinsRock5, 349, "Ruins Rock 5"); +define_object_type_data(ObjectType.RuinsRock6, 350, "Ruins Rock 6"); +define_object_type_data(ObjectType.RuinsRock7, 351, "Ruins Rock 7"); +define_object_type_data(ObjectType.Poison, 352, "Poison"); +define_object_type_data(ObjectType.FixedBoxTypeRuins, 353, "Fixed Box Type (Ruins)"); +define_object_type_data(ObjectType.RandomBoxTypeRuins, 354, "Random Box Type (Ruins)"); +define_object_type_data(ObjectType.EnemyTypeBoxYellow, 355, "Enemy Type Box (Yellow)"); +define_object_type_data(ObjectType.EnemyTypeBoxBlue, 356, "Enemy Type Box (Blue)"); +define_object_type_data(ObjectType.EmptyTypeBoxBlue, 357, "Empty Type Box (Blue)"); +define_object_type_data(ObjectType.DestructableRock, 358, "Destructable Rock"); +define_object_type_data(ObjectType.PopupTrapsTechs, 359, "Popup Traps (techs)"); +define_object_type_data(ObjectType.FlyingWhiteBird, 368, "Flying White Bird"); +define_object_type_data(ObjectType.Tower, 369, "Tower"); +define_object_type_data(ObjectType.FloatingRocks, 370, "Floating Rocks"); +define_object_type_data(ObjectType.FloatingSoul, 371, "Floating Soul"); +define_object_type_data(ObjectType.Butterfly, 372, "Butterfly"); +define_object_type_data(ObjectType.LobbyGameMenu, 384, "Lobby Game menu"); +define_object_type_data(ObjectType.LobbyWarpObject, 385, "Lobby Warp Object"); +define_object_type_data( + ObjectType.Lobby1EventObjectDefaultTree, + 386, + "Lobby 1 Event Object (Default Tree)", +); +define_object_type_data(ObjectType.UnknownItem387, 387, "Unknown Item (387)"); +define_object_type_data(ObjectType.UnknownItem388, 388, "Unknown Item (388)"); +define_object_type_data(ObjectType.UnknownItem389, 389, "Unknown Item (389)"); +define_object_type_data( + ObjectType.LobbyEventObjectStaticPumpkin, + 390, + "Lobby Event Object (Static Pumpkin)", +); +define_object_type_data( + ObjectType.LobbyEventObject3ChristmasWindows, + 391, + "Lobby Event Object (3 Christmas Windows)", +); +define_object_type_data( + ObjectType.LobbyEventObjectRedAndWhiteCurtain, + 392, + "Lobby Event Object (Red and White Curtain)", +); +define_object_type_data(ObjectType.UnknownItem393, 393, "Unknown Item (393)"); +define_object_type_data(ObjectType.UnknownItem394, 394, "Unknown Item (394)"); +define_object_type_data(ObjectType.LobbyFishTank, 395, "Lobby Fish Tank"); +define_object_type_data( + ObjectType.LobbyEventObjectButterflies, + 396, + "Lobby Event Object (Butterflies)", +); +define_object_type_data(ObjectType.UnknownItem400, 400, "Unknown Item (400)"); +define_object_type_data(ObjectType.GreyWallLow, 401, "grey wall low"); +define_object_type_data(ObjectType.SpaceshipDoor, 402, "Spaceship Door"); +define_object_type_data(ObjectType.GreyWallHigh, 403, "grey wall high"); +define_object_type_data(ObjectType.TempleNormalDoor, 416, "Temple Normal Door"); +define_object_type_data( + ObjectType.BreakableWallWallButUnbreakable, + 417, + '"breakable wall wall, but unbreakable"', +); +define_object_type_data(ObjectType.BrokenCilinderAndRubble, 418, "Broken cilinder and rubble"); +define_object_type_data( + ObjectType.ThreeBrokenWallPiecesOnFloor, + 419, + "3 broken wall pieces on floor", +); +define_object_type_data(ObjectType.HighBrickCilinder, 420, "high brick cilinder"); +define_object_type_data(ObjectType.LyingCilinder, 421, "lying cilinder"); +define_object_type_data(ObjectType.BrickConeWithFlatTop, 422, "brick cone with flat top"); +define_object_type_data(ObjectType.BreakableTempleWall, 423, "breakable temple wall"); +define_object_type_data(ObjectType.TempleMapDetect, 424, "Temple Map Detect"); +define_object_type_data( + ObjectType.SmallBrownBrickRisingBridge, + 425, + "small brown brick rising bridge", +); +define_object_type_data( + ObjectType.LongRisingBridgeWithPinkHighEdges, + 426, + "long rising bridge (with pink high edges)", +); +define_object_type_data(ObjectType.FourSwitchTempleDoor, 427, "4 switch temple door"); +define_object_type_data(ObjectType.FourButtonSpaceshipDoor, 448, "4 button spaceship door"); +define_object_type_data(ObjectType.ItemBoxCca, 512, "item box cca"); +define_object_type_data(ObjectType.TeleporterEp2, 513, "Teleporter (Ep 2)"); +define_object_type_data(ObjectType.CCADoor, 514, "CCA Door"); +define_object_type_data(ObjectType.SpecialBoxCCA, 515, "Special Box CCA"); +define_object_type_data(ObjectType.BigCCADoor, 516, "Big CCA Door"); +define_object_type_data(ObjectType.BigCCADoorSwitch, 517, "Big CCA Door Switch"); +define_object_type_data(ObjectType.LittleRock, 518, "Little Rock"); +define_object_type_data(ObjectType.Little3StoneWall, 519, "Little 3 Stone Wall"); +define_object_type_data(ObjectType.Medium3StoneWall, 520, "Medium 3 stone wall"); +define_object_type_data(ObjectType.SpiderPlant, 521, "Spider Plant"); +define_object_type_data(ObjectType.CCAAreaTeleporter, 522, "CCA Area Teleporter"); +define_object_type_data(ObjectType.UnknownItem523, 523, "Unknown Item (523)"); +define_object_type_data(ObjectType.WhiteBird, 524, "White Bird"); +define_object_type_data(ObjectType.OrangeBird, 525, "Orange Bird"); +define_object_type_data(ObjectType.Saw, 527, "Saw"); +define_object_type_data(ObjectType.LaserDetect, 528, "Laser Detect"); +define_object_type_data(ObjectType.UnknownItem529, 529, "Unknown Item (529)"); +define_object_type_data(ObjectType.UnknownItem530, 530, "Unknown Item (530)"); +define_object_type_data(ObjectType.Seagull, 531, "Seagull"); +define_object_type_data(ObjectType.Fish, 544, "Fish"); +define_object_type_data(ObjectType.SeabedDoorWithBlueEdges, 545, "Seabed Door (with blue edges)"); +define_object_type_data( + ObjectType.SeabedDoorAlwaysOpenNonTriggerable, + 546, + "Seabed door (always open, non-triggerable)", +); +define_object_type_data(ObjectType.LittleCryotube, 547, "Little Cryotube"); +define_object_type_data(ObjectType.WideGlassWallBreakable, 548, "Wide Glass Wall (breakable)"); +define_object_type_data(ObjectType.BlueFloatingRobot, 549, "Blue floating robot"); +define_object_type_data(ObjectType.RedFloatingRobot, 550, "Red floating robot"); +define_object_type_data(ObjectType.Dolphin, 551, "Dolphin"); +define_object_type_data(ObjectType.CaptureTrap, 552, "Capture Trap"); +define_object_type_data(ObjectType.VRLink, 553, "VR link"); +define_object_type_data(ObjectType.UnknownItem576, 576, "Unknown Item (576)"); +define_object_type_data(ObjectType.WarpInBarbaRayRoom, 640, "Warp in Barba Ray Room"); +define_object_type_data(ObjectType.UnknownItem672, 672, "Unknown Item (672)"); +define_object_type_data(ObjectType.GeeNest, 688, "Gee Nest"); +define_object_type_data(ObjectType.LabComputerConsole, 689, "Lab Computer Console"); +define_object_type_data( + ObjectType.LabComputerConsoleGreenScreen, + 690, + "Lab Computer Console (Green Screen)", +); +define_object_type_data(ObjectType.ChairYelllowPillow, 691, "Chair, Yelllow Pillow"); +define_object_type_data( + ObjectType.OrangeWallWithHoleInMiddle, + 692, + "orange wall with hole in middle", +); +define_object_type_data(ObjectType.GreyWallWithHoleInMiddle, 693, "grey wall with hole in middle"); +define_object_type_data(ObjectType.LongTable, 694, "long table"); +define_object_type_data(ObjectType.GBAStation, 695, "GBA Station"); +define_object_type_data(ObjectType.TalkLinkToSupport, 696, "Talk (link to support)"); +define_object_type_data(ObjectType.InstaWarp, 697, "insta-warp"); +define_object_type_data(ObjectType.LabInvisibleObject, 698, "Lab Invisible Object"); +define_object_type_data(ObjectType.LabGlassWindowDoor, 699, "Lab Glass window Door"); +define_object_type_data(ObjectType.UnknownItem700, 700, "Unknown Item (700)"); +define_object_type_data(ObjectType.LabCelingWarp, 701, "Lab Celing Warp"); +define_object_type_data(ObjectType.Ep4LightSource, 768, "Ep4 Light Source"); +define_object_type_data(ObjectType.Cacti, 769, "cacti"); +define_object_type_data(ObjectType.BigBrownRock, 770, "Big Brown Rock"); +define_object_type_data(ObjectType.BreakableBrownRock, 771, "Breakable Brown Rock"); +define_object_type_data(ObjectType.UnknownItem832, 832, "Unknown Item (832)"); +define_object_type_data(ObjectType.UnknownItem833, 833, "Unknown Item (833)"); +define_object_type_data(ObjectType.PoisonPlant, 896, "Poison Plant"); +define_object_type_data(ObjectType.UnknownItem897, 897, "Unknown Item (897)"); +define_object_type_data(ObjectType.UnknownItem898, 898, "Unknown Item (898)"); +define_object_type_data(ObjectType.OozingDesertPlant, 899, "Oozing Desert Plant"); +define_object_type_data(ObjectType.UnknownItem901, 901, "Unknown Item (901)"); +define_object_type_data(ObjectType.BigBlackRocks, 902, "big black rocks"); +define_object_type_data(ObjectType.UnknownItem903, 903, "Unknown Item (903)"); +define_object_type_data(ObjectType.UnknownItem904, 904, "Unknown Item (904)"); +define_object_type_data(ObjectType.UnknownItem905, 905, "Unknown Item (905)"); +define_object_type_data(ObjectType.UnknownItem906, 906, "Unknown Item (906)"); +define_object_type_data(ObjectType.FallingRock, 907, "Falling Rock"); +define_object_type_data(ObjectType.DesertPlantHasCollision, 908, "Desert Plant (has collision)"); +define_object_type_data( + ObjectType.DesertFixedTypeBoxBreakableCrystals, + 909, + "Desert Fixed Type Box (Breakable Crystals)", +); +define_object_type_data(ObjectType.UnknownItem910, 910, "Unknown Item (910)"); +define_object_type_data(ObjectType.BeeHive, 911, "Bee Hive"); +define_object_type_data(ObjectType.UnknownItem912, 912, "Unknown Item (912)"); +define_object_type_data(ObjectType.Heat, 913, "Heat"); +define_object_type_data(ObjectType.TopOfSaintMillionEgg, 960, "Top of saint million egg"); +define_object_type_data(ObjectType.UnknownItem961, 961, "Unknown Item (961)"); diff --git a/src/data_formats/parsing/quest/qst.test.ts b/src/data_formats/parsing/quest/qst.test.ts index f5161f3b..cf126533 100644 --- a/src/data_formats/parsing/quest/qst.test.ts +++ b/src/data_formats/parsing/quest/qst.test.ts @@ -1,6 +1,6 @@ import { walk_qst_files } from "../../../../test/src/utils"; import { parse_qst, write_qst } from "./qst"; -import { Endianness } from "../.."; +import { Endianness } from "../../Endianness"; import { BufferCursor } from "../../cursor/BufferCursor"; import { ArrayBufferCursor } from "../../cursor/ArrayBufferCursor"; diff --git a/src/data_formats/parsing/quest/qst.ts b/src/data_formats/parsing/quest/qst.ts index 28243f65..be56c747 100644 --- a/src/data_formats/parsing/quest/qst.ts +++ b/src/data_formats/parsing/quest/qst.ts @@ -1,5 +1,5 @@ import Logger from "js-logger"; -import { Endianness } from "../.."; +import { Endianness } from "../../Endianness"; import { ArrayBufferCursor } from "../../cursor/ArrayBufferCursor"; import { Cursor } from "../../cursor/Cursor"; import { ResizableBufferCursor } from "../../cursor/ResizableBufferCursor"; diff --git a/src/data_formats/parsing/rlc.ts b/src/data_formats/parsing/rlc.ts index 65d397cd..ca15ac85 100644 --- a/src/data_formats/parsing/rlc.ts +++ b/src/data_formats/parsing/rlc.ts @@ -1,5 +1,5 @@ import Logger from "js-logger"; -import { Endianness } from ".."; +import { Endianness } from "../Endianness"; import { Cursor } from "../cursor/Cursor"; import { parse_prc } from "./prc"; diff --git a/src/domain/NpcType.ts b/src/domain/NpcType.ts deleted file mode 100644 index 2af262a6..00000000 --- a/src/domain/NpcType.ts +++ /dev/null @@ -1,1291 +0,0 @@ -import { Episode, check_episode, EntityType } from "."; - -export class NpcType implements EntityType { - readonly id: number; - /** - * Matches the constant name. E.g. the code of NpcType.Zu is "Zu". - * Uniquely identifies an NPC. - */ - readonly code: string; - /** - * Unique name. E.g. a Delsaber would have (Ep. II) appended to its name. - */ - readonly name: string; - /** - * Name used in the game. - * Might conflict with other NPC names (e.g. Delsaber from ep. I and ep. II). - */ - readonly simple_name: string; - readonly ultimate_name: string; - readonly episode?: number; - readonly enemy: boolean; - rare_type?: NpcType; - - constructor( - id: number, - code: string, - name: string, - simple_name: string, - ultimate_name: string, - episode: number | undefined, - enemy: boolean - ) { - if (!Number.isInteger(id) || id < 0) - throw new Error(`Expected id to be an integer greater than or equal to 0, got ${id}.`); - if (!code) throw new Error("code is required."); - if (!name) throw new Error("name is required."); - if (!simple_name) throw new Error("simple_name is required."); - if (!ultimate_name) throw new Error("ultimate_name is required."); - if (episode != null && episode !== 1 && episode !== 2 && episode !== 4) - throw new Error(`episode should be undefined, 1, 2 or 4, got ${episode}.`); - if (typeof enemy !== "boolean") throw new Error("enemy is required."); - - this.id = id; - this.code = code; - this.simple_name = simple_name; - this.ultimate_name = ultimate_name; - this.name = name; - this.episode = episode; - this.enemy = enemy; - - NpcType.by_code_map.set(code, this); - - if (episode) { - const map = NpcType.by_ep_and_name[episode]; - - if (map) { - map.set(simple_name, this); - map.set(ultimate_name, this); - } - } - } - - private static by_code_map = new Map(); - - private static by_ep_and_name = [ - undefined, - new Map(), - new Map(), - undefined, - new Map(), - ]; - - static by_code(code: string): NpcType | undefined { - return this.by_code_map.get(code); - } - - /** - * Uniquely identifies an NPC. Tries to match on simple_name and ultimate_name. - */ - static by_name_and_episode(name: string, episode: Episode): NpcType | undefined { - check_episode(episode); - return this.by_ep_and_name[episode]!.get(name); - } - - // - // Unknown NPCs - // - - static Unknown: NpcType; - - // - // Friendly NPCs - // - - static FemaleFat: NpcType; - static FemaleMacho: NpcType; - static FemaleTall: NpcType; - static MaleDwarf: NpcType; - static MaleFat: NpcType; - static MaleMacho: NpcType; - static MaleOld: NpcType; - static BlueSoldier: NpcType; - static RedSoldier: NpcType; - static Principal: NpcType; - static Tekker: NpcType; - static GuildLady: NpcType; - static Scientist: NpcType; - static Nurse: NpcType; - static Irene: NpcType; - static ItemShop: NpcType; - static Nurse2: NpcType; - - // - // Enemy NPCs - // - - // Episode I Forest - - static Hildebear: NpcType; - static Hildeblue: NpcType; - static RagRappy: NpcType; - static AlRappy: NpcType; - static Monest: NpcType; - static Mothmant: NpcType; - static SavageWolf: NpcType; - static BarbarousWolf: NpcType; - static Booma: NpcType; - static Gobooma: NpcType; - static Gigobooma: NpcType; - static Dragon: NpcType; - - // Episode I Caves - - static GrassAssassin: NpcType; - static PoisonLily: NpcType; - static NarLily: NpcType; - static NanoDragon: NpcType; - static EvilShark: NpcType; - static PalShark: NpcType; - static GuilShark: NpcType; - static PofuillySlime: NpcType; - static PouillySlime: NpcType; - static PanArms: NpcType; - static Migium: NpcType; - static Hidoom: NpcType; - static DeRolLe: NpcType; - - // Episode I Mines - - static Dubchic: NpcType; - static Gilchic: NpcType; - static Garanz: NpcType; - static SinowBeat: NpcType; - static SinowGold: NpcType; - static Canadine: NpcType; - static Canane: NpcType; - static Dubswitch: NpcType; - static VolOpt: NpcType; - - // Episode I Ruins - - static Delsaber: NpcType; - static ChaosSorcerer: NpcType; - static DarkGunner: NpcType; - static DeathGunner: NpcType; - static ChaosBringer: NpcType; - static DarkBelra: NpcType; - static Dimenian: NpcType; - static LaDimenian: NpcType; - static SoDimenian: NpcType; - static Bulclaw: NpcType; - static Bulk: NpcType; - static Claw: NpcType; - static DarkFalz: NpcType; - - // Episode II VR Temple - - static Hildebear2: NpcType; - static Hildeblue2: NpcType; - static RagRappy2: NpcType; - static LoveRappy: NpcType; - static StRappy: NpcType; - static HalloRappy: NpcType; - static EggRappy: NpcType; - static Monest2: NpcType; - static Mothmant2: NpcType; - static PoisonLily2: NpcType; - static NarLily2: NpcType; - static GrassAssassin2: NpcType; - static Dimenian2: NpcType; - static LaDimenian2: NpcType; - static SoDimenian2: NpcType; - static DarkBelra2: NpcType; - static BarbaRay: NpcType; - - // Episode II VR Spaceship - - static SavageWolf2: NpcType; - static BarbarousWolf2: NpcType; - static PanArms2: NpcType; - static Migium2: NpcType; - static Hidoom2: NpcType; - static Dubchic2: NpcType; - static Gilchic2: NpcType; - static Garanz2: NpcType; - static Dubswitch2: NpcType; - static Delsaber2: NpcType; - static ChaosSorcerer2: NpcType; - static GolDragon: NpcType; - - // Episode II Central Control Area - - static SinowBerill: NpcType; - static SinowSpigell: NpcType; - static Merillia: NpcType; - static Meriltas: NpcType; - static Mericarol: NpcType; - static Mericus: NpcType; - static Merikle: NpcType; - static UlGibbon: NpcType; - static ZolGibbon: NpcType; - static Gibbles: NpcType; - static Gee: NpcType; - static GiGue: NpcType; - static IllGill: NpcType; - static DelLily: NpcType; - static Epsilon: NpcType; - static GalGryphon: NpcType; - - // Episode II Seabed - - static Deldepth: NpcType; - static Delbiter: NpcType; - static Dolmolm: NpcType; - static Dolmdarl: NpcType; - static Morfos: NpcType; - static Recobox: NpcType; - static Recon: NpcType; - static SinowZoa: NpcType; - static SinowZele: NpcType; - static OlgaFlow: NpcType; - - // Episode IV - - static SandRappy: NpcType; - static DelRappy: NpcType; - static Astark: NpcType; - static SatelliteLizard: NpcType; - static Yowie: NpcType; - static MerissaA: NpcType; - static MerissaAA: NpcType; - static Girtablulu: NpcType; - static Zu: NpcType; - static Pazuzu: NpcType; - static Boota: NpcType; - static ZeBoota: NpcType; - static BaBoota: NpcType; - static Dorphon: NpcType; - static DorphonEclair: NpcType; - static Goran: NpcType; - static PyroGoran: NpcType; - static GoranDetonator: NpcType; - static SaintMilion: NpcType; - static Shambertin: NpcType; - static Kondrieu: NpcType; -} - -(function() { - let id = 0; - - // - // Unknown NPCs - // - - NpcType.Unknown = new NpcType( - id++, - "Unknown", - "Unknown", - "Unknown", - "Unknown", - undefined, - false - ); - - // - // Friendly NPCs - // - - NpcType.FemaleFat = new NpcType( - id++, - "FemaleFat", - "Female Fat", - "Female Fat", - "Female Fat", - undefined, - false - ); - NpcType.FemaleMacho = new NpcType( - id++, - "FemaleMacho", - "Female Macho", - "Female Macho", - "Female Macho", - undefined, - false - ); - NpcType.FemaleTall = new NpcType( - id++, - "FemaleTall", - "Female Tall", - "Female Tall", - "Female Tall", - undefined, - false - ); - NpcType.MaleDwarf = new NpcType( - id++, - "MaleDwarf", - "Male Dwarf", - "Male Dwarf", - "Male Dwarf", - undefined, - false - ); - NpcType.MaleFat = new NpcType( - id++, - "MaleFat", - "Male Fat", - "Male Fat", - "Male Fat", - undefined, - false - ); - NpcType.MaleMacho = new NpcType( - id++, - "MaleMacho", - "Male Macho", - "Male Macho", - "Male Macho", - undefined, - false - ); - NpcType.MaleOld = new NpcType( - id++, - "MaleOld", - "Male Old", - "Male Old", - "Male Old", - undefined, - false - ); - NpcType.BlueSoldier = new NpcType( - id++, - "BlueSoldier", - "Blue Soldier", - "Blue Soldier", - "Blue Soldier", - undefined, - false - ); - NpcType.RedSoldier = new NpcType( - id++, - "RedSoldier", - "Red Soldier", - "Red Soldier", - "Red Soldier", - undefined, - false - ); - NpcType.Principal = new NpcType( - id++, - "Principal", - "Principal", - "Principal", - "Principal", - undefined, - false - ); - NpcType.Tekker = new NpcType(id++, "Tekker", "Tekker", "Tekker", "Tekker", undefined, false); - NpcType.GuildLady = new NpcType( - id++, - "GuildLady", - "Guild Lady", - "Guild Lady", - "Guild Lady", - undefined, - false - ); - NpcType.Scientist = new NpcType( - id++, - "Scientist", - "Scientist", - "Scientist", - "Scientist", - undefined, - false - ); - NpcType.Nurse = new NpcType(id++, "Nurse", "Nurse", "Nurse", "Nurse", undefined, false); - NpcType.Irene = new NpcType(id++, "Irene", "Irene", "Irene", "Irene", undefined, false); - NpcType.ItemShop = new NpcType( - id++, - "ItemShop", - "Item Shop", - "Item Shop", - "Item Shop", - undefined, - false - ); - NpcType.Nurse2 = new NpcType(id++, "Nurse2", "Nurse (Ep. II)", "Nurse", "Nurse", 2, false); - - // - // Enemy NPCs - // - - // Episode I Forest - - NpcType.Hildebear = new NpcType( - id++, - "Hildebear", - "Hildebear", - "Hildebear", - "Hildelt", - 1, - true - ); - NpcType.Hildeblue = new NpcType( - id++, - "Hildeblue", - "Hildeblue", - "Hildeblue", - "Hildetorr", - 1, - true - ); - NpcType.Hildebear.rare_type = NpcType.Hildeblue; - NpcType.RagRappy = new NpcType(id++, "RagRappy", "Rag Rappy", "Rag Rappy", "El Rappy", 1, true); - NpcType.AlRappy = new NpcType(id++, "AlRappy", "Al Rappy", "Al Rappy", "Pal Rappy", 1, true); - NpcType.RagRappy.rare_type = NpcType.AlRappy; - NpcType.Monest = new NpcType(id++, "Monest", "Monest", "Monest", "Mothvist", 1, true); - NpcType.Mothmant = new NpcType(id++, "Mothmant", "Mothmant", "Mothmant", "Mothvert", 1, true); - NpcType.SavageWolf = new NpcType( - id++, - "SavageWolf", - "Savage Wolf", - "Savage Wolf", - "Gulgus", - 1, - true - ); - NpcType.BarbarousWolf = new NpcType( - id++, - "BarbarousWolf", - "Barbarous Wolf", - "Barbarous Wolf", - "Gulgus-Gue", - 1, - true - ); - NpcType.Booma = new NpcType(id++, "Booma", "Booma", "Booma", "Bartle", 1, true); - NpcType.Gobooma = new NpcType(id++, "Gobooma", "Gobooma", "Gobooma", "Barble", 1, true); - NpcType.Gigobooma = new NpcType(id++, "Gigobooma", "Gigobooma", "Gigobooma", "Tollaw", 1, true); - NpcType.Dragon = new NpcType(id++, "Dragon", "Dragon", "Dragon", "Sil Dragon", 1, true); - - // Episode I Caves - - NpcType.GrassAssassin = new NpcType( - id++, - "GrassAssassin", - "Grass Assassin", - "Grass Assassin", - "Crimson Assassin", - 1, - true - ); - NpcType.PoisonLily = new NpcType( - id++, - "PoisonLily", - "Poison Lily", - "Poison Lily", - "Ob Lily", - 1, - true - ); - NpcType.NarLily = new NpcType(id++, "NarLily", "Nar Lily", "Nar Lily", "Mil Lily", 1, true); - NpcType.PoisonLily.rare_type = NpcType.NarLily; - NpcType.NanoDragon = new NpcType( - id++, - "NanoDragon", - "Nano Dragon", - "Nano Dragon", - "Nano Dragon", - 1, - true - ); - NpcType.EvilShark = new NpcType( - id++, - "EvilShark", - "Evil Shark", - "Evil Shark", - "Vulmer", - 1, - true - ); - NpcType.PalShark = new NpcType(id++, "PalShark", "Pal Shark", "Pal Shark", "Govulmer", 1, true); - NpcType.GuilShark = new NpcType( - id++, - "GuilShark", - "Guil Shark", - "Guil Shark", - "Melqueek", - 1, - true - ); - NpcType.PofuillySlime = new NpcType( - id++, - "PofuillySlime", - "Pofuilly Slime", - "Pofuilly Slime", - "Pofuilly Slime", - 1, - true - ); - NpcType.PouillySlime = new NpcType( - id++, - "PouillySlime", - "Pouilly Slime", - "Pouilly Slime", - "Pouilly Slime", - 1, - true - ); - NpcType.PofuillySlime.rare_type = NpcType.PouillySlime; - NpcType.PanArms = new NpcType(id++, "PanArms", "Pan Arms", "Pan Arms", "Pan Arms", 1, true); - NpcType.Migium = new NpcType(id++, "Migium", "Migium", "Migium", "Migium", 1, true); - NpcType.Hidoom = new NpcType(id++, "Hidoom", "Hidoom", "Hidoom", "Hidoom", 1, true); - NpcType.DeRolLe = new NpcType(id++, "DeRolLe", "De Rol Le", "De Rol Le", "Dal Ra Lie", 1, true); - - // Episode I Mines - - NpcType.Dubchic = new NpcType(id++, "Dubchic", "Dubchic", "Dubchic", "Dubchich", 1, true); - NpcType.Gilchic = new NpcType(id++, "Gilchic", "Gilchic", "Gilchic", "Gilchich", 1, true); - NpcType.Garanz = new NpcType(id++, "Garanz", "Garanz", "Garanz", "Baranz", 1, true); - NpcType.SinowBeat = new NpcType( - id++, - "SinowBeat", - "Sinow Beat", - "Sinow Beat", - "Sinow Blue", - 1, - true - ); - NpcType.SinowGold = new NpcType( - id++, - "SinowGold", - "Sinow Gold", - "Sinow Gold", - "Sinow Red", - 1, - true - ); - NpcType.Canadine = new NpcType(id++, "Canadine", "Canadine", "Canadine", "Canabin", 1, true); - NpcType.Canane = new NpcType(id++, "Canane", "Canane", "Canane", "Canune", 1, true); - NpcType.Dubswitch = new NpcType( - id++, - "Dubswitch", - "Dubswitch", - "Dubswitch", - "Dubswitch", - 1, - true - ); - NpcType.VolOpt = new NpcType(id++, "VolOpt", "Vol Opt", "Vol Opt", "Vol Opt ver.2", 1, true); - - // Episode I Ruins - - NpcType.Delsaber = new NpcType(id++, "Delsaber", "Delsaber", "Delsaber", "Delsaber", 1, true); - NpcType.ChaosSorcerer = new NpcType( - id++, - "ChaosSorcerer", - "Chaos Sorcerer", - "Chaos Sorcerer", - "Gran Sorcerer", - 1, - true - ); - NpcType.DarkGunner = new NpcType( - id++, - "DarkGunner", - "Dark Gunner", - "Dark Gunner", - "Dark Gunner", - 1, - true - ); - NpcType.DeathGunner = new NpcType( - id++, - "DeathGunner", - "Death Gunner", - "Death Gunner", - "Death Gunner", - 1, - true - ); - NpcType.ChaosBringer = new NpcType( - id++, - "ChaosBringer", - "Chaos Bringer", - "Chaos Bringer", - "Dark Bringer", - 1, - true - ); - NpcType.DarkBelra = new NpcType( - id++, - "DarkBelra", - "Dark Belra", - "Dark Belra", - "Indi Belra", - 1, - true - ); - NpcType.Dimenian = new NpcType(id++, "Dimenian", "Dimenian", "Dimenian", "Arlan", 1, true); - NpcType.LaDimenian = new NpcType( - id++, - "LaDimenian", - "La Dimenian", - "La Dimenian", - "Merlan", - 1, - true - ); - NpcType.SoDimenian = new NpcType( - id++, - "SoDimenian", - "So Dimenian", - "So Dimenian", - "Del-D", - 1, - true - ); - NpcType.Bulclaw = new NpcType(id++, "Bulclaw", "Bulclaw", "Bulclaw", "Bulclaw", 1, true); - NpcType.Bulk = new NpcType(id++, "Bulk", "Bulk", "Bulk", "Bulk", 1, true); - NpcType.Claw = new NpcType(id++, "Claw", "Claw", "Claw", "Claw", 1, true); - NpcType.DarkFalz = new NpcType( - id++, - "DarkFalz", - "Dark Falz", - "Dark Falz", - "Dark Falz", - 1, - true - ); - - // Episode II VR Temple - - NpcType.Hildebear2 = new NpcType( - id++, - "Hildebear2", - "Hildebear (Ep. II)", - "Hildebear", - "Hildelt", - 2, - true - ); - NpcType.Hildeblue2 = new NpcType( - id++, - "Hildeblue2", - "Hildeblue (Ep. II)", - "Hildeblue", - "Hildetorr", - 2, - true - ); - NpcType.Hildebear2.rare_type = NpcType.Hildeblue2; - NpcType.RagRappy2 = new NpcType( - id++, - "RagRappy2", - "Rag Rappy (Ep. II)", - "Rag Rappy", - "El Rappy", - 2, - true - ); - NpcType.LoveRappy = new NpcType( - id++, - "LoveRappy", - "Love Rappy", - "Love Rappy", - "Love Rappy", - 2, - true - ); - NpcType.RagRappy2.rare_type = NpcType.LoveRappy; - NpcType.StRappy = new NpcType(id++, "StRappy", "St. Rappy", "St. Rappy", "St. Rappy", 2, true); - NpcType.HalloRappy = new NpcType( - id++, - "HalloRappy", - "Hallo Rappy", - "Hallo Rappy", - "Hallo Rappy", - 2, - true - ); - NpcType.EggRappy = new NpcType( - id++, - "EggRappy", - "Egg Rappy", - "Egg Rappy", - "Egg Rappy", - 2, - true - ); - NpcType.Monest2 = new NpcType( - id++, - "Monest2", - "Monest (Ep. II)", - "Monest", - "Mothvist", - 2, - true - ); - NpcType.Mothmant2 = new NpcType(id++, "Mothmant2", "Mothmant", "Mothmant", "Mothvert", 2, true); - NpcType.PoisonLily2 = new NpcType( - id++, - "PoisonLily2", - "Poison Lily (Ep. II)", - "Poison Lily", - "Ob Lily", - 2, - true - ); - NpcType.NarLily2 = new NpcType( - id++, - "NarLily2", - "Nar Lily (Ep. II)", - "Nar Lily", - "Mil Lily", - 2, - true - ); - NpcType.PoisonLily2.rare_type = NpcType.NarLily2; - NpcType.GrassAssassin2 = new NpcType( - id++, - "GrassAssassin2", - "Grass Assassin (Ep. II)", - "Grass Assassin", - "Crimson Assassin", - 2, - true - ); - NpcType.Dimenian2 = new NpcType( - id++, - "Dimenian2", - "Dimenian (Ep. II)", - "Dimenian", - "Arlan", - 2, - true - ); - NpcType.LaDimenian2 = new NpcType( - id++, - "LaDimenian2", - "La Dimenian (Ep. II)", - "La Dimenian", - "Merlan", - 2, - true - ); - NpcType.SoDimenian2 = new NpcType( - id++, - "SoDimenian2", - "So Dimenian (Ep. II)", - "So Dimenian", - "Del-D", - 2, - true - ); - NpcType.DarkBelra2 = new NpcType( - id++, - "DarkBelra2", - "Dark Belra (Ep. II)", - "Dark Belra", - "Indi Belra", - 2, - true - ); - NpcType.BarbaRay = new NpcType( - id++, - "BarbaRay", - "Barba Ray", - "Barba Ray", - "Barba Ray", - 2, - true - ); - - // Episode II VR Spaceship - - NpcType.SavageWolf2 = new NpcType( - id++, - "SavageWolf2", - "Savage Wolf (Ep. II)", - "Savage Wolf", - "Gulgus", - 2, - true - ); - NpcType.BarbarousWolf2 = new NpcType( - id++, - "BarbarousWolf2", - "Barbarous Wolf (Ep. II)", - "Barbarous Wolf", - "Gulgus-Gue", - 2, - true - ); - NpcType.PanArms2 = new NpcType( - id++, - "PanArms2", - "Pan Arms (Ep. II)", - "Pan Arms", - "Pan Arms", - 2, - true - ); - NpcType.Migium2 = new NpcType(id++, "Migium2", "Migium (Ep. II)", "Migium", "Migium", 2, true); - NpcType.Hidoom2 = new NpcType(id++, "Hidoom2", "Hidoom (Ep. II)", "Hidoom", "Hidoom", 2, true); - NpcType.Dubchic2 = new NpcType( - id++, - "Dubchic2", - "Dubchic (Ep. II)", - "Dubchic", - "Dubchich", - 2, - true - ); - NpcType.Gilchic2 = new NpcType( - id++, - "Gilchic2", - "Gilchic (Ep. II)", - "Gilchic", - "Gilchich", - 2, - true - ); - NpcType.Garanz2 = new NpcType(id++, "Garanz2", "Garanz (Ep. II)", "Garanz", "Baranz", 2, true); - NpcType.Dubswitch2 = new NpcType( - id++, - "Dubswitch2", - "Dubswitch (Ep. II)", - "Dubswitch", - "Dubswitch", - 2, - true - ); - NpcType.Delsaber2 = new NpcType( - id++, - "Delsaber2", - "Delsaber (Ep. II)", - "Delsaber", - "Delsaber", - 2, - true - ); - NpcType.ChaosSorcerer2 = new NpcType( - id++, - "ChaosSorcerer2", - "Chaos Sorcerer (Ep. II)", - "Chaos Sorcerer", - "Gran Sorcerer", - 2, - true - ); - NpcType.GolDragon = new NpcType( - id++, - "GolDragon", - "Gol Dragon", - "Gol Dragon", - "Gol Dragon", - 2, - true - ); - - // Episode II Central Control Area - - NpcType.SinowBerill = new NpcType( - id++, - "SinowBerill", - "Sinow Berill", - "Sinow Berill", - "Sinow Berill", - 2, - true - ); - NpcType.SinowSpigell = new NpcType( - id++, - "SinowSpigell", - "Sinow Spigell", - "Sinow Spigell", - "Sinow Spigell", - 2, - true - ); - NpcType.Merillia = new NpcType(id++, "Merillia", "Merillia", "Merillia", "Merillia", 2, true); - NpcType.Meriltas = new NpcType(id++, "Meriltas", "Meriltas", "Meriltas", "Meriltas", 2, true); - NpcType.Mericarol = new NpcType( - id++, - "Mericarol", - "Mericarol", - "Mericarol", - "Mericarol", - 2, - true - ); - NpcType.Mericus = new NpcType(id++, "Mericus", "Mericus", "Mericus", "Mericus", 2, true); - NpcType.Merikle = new NpcType(id++, "Merikle", "Merikle", "Merikle", "Merikle", 2, true); - NpcType.UlGibbon = new NpcType( - id++, - "UlGibbon", - "Ul Gibbon", - "Ul Gibbon", - "Ul Gibbon", - 2, - true - ); - NpcType.ZolGibbon = new NpcType( - id++, - "ZolGibbon", - "Zol Gibbon", - "Zol Gibbon", - "Zol Gibbon", - 2, - true - ); - NpcType.Gibbles = new NpcType(id++, "Gibbles", "Gibbles", "Gibbles", "Gibbles", 2, true); - NpcType.Gee = new NpcType(id++, "Gee", "Gee", "Gee", "Gee", 2, true); - NpcType.GiGue = new NpcType(id++, "GiGue", "Gi Gue", "Gi Gue", "Gi Gue", 2, true); - NpcType.IllGill = new NpcType(id++, "IllGill", "Ill Gill", "Ill Gill", "Ill Gill", 2, true); - NpcType.DelLily = new NpcType(id++, "DelLily", "Del Lily", "Del Lily", "Del Lily", 2, true); - NpcType.Epsilon = new NpcType(id++, "Epsilon", "Epsilon", "Epsilon", "Epsilon", 2, true); - NpcType.GalGryphon = new NpcType( - id++, - "GalGryphon", - "Gal Gryphon", - "Gal Gryphon", - "Gal Gryphon", - 2, - true - ); - - // Episode II Seabed - - NpcType.Deldepth = new NpcType(id++, "Deldepth", "Deldepth", "Deldepth", "Deldepth", 2, true); - NpcType.Delbiter = new NpcType(id++, "Delbiter", "Delbiter", "Delbiter", "Delbiter", 2, true); - NpcType.Dolmolm = new NpcType(id++, "Dolmolm", "Dolmolm", "Dolmolm", "Dolmolm", 2, true); - NpcType.Dolmdarl = new NpcType(id++, "Dolmdarl", "Dolmdarl", "Dolmdarl", "Dolmdarl", 2, true); - NpcType.Morfos = new NpcType(id++, "Morfos", "Morfos", "Morfos", "Morfos", 2, true); - NpcType.Recobox = new NpcType(id++, "Recobox", "Recobox", "Recobox", "Recobox", 2, true); - NpcType.Recon = new NpcType(id++, "Recon", "Recon", "Recon", "Recon", 2, true); - NpcType.SinowZoa = new NpcType( - id++, - "SinowZoa", - "Sinow Zoa", - "Sinow Zoa", - "Sinow Zoa", - 2, - true - ); - NpcType.SinowZele = new NpcType( - id++, - "SinowZele", - "Sinow Zele", - "Sinow Zele", - "Sinow Zele", - 2, - true - ); - NpcType.OlgaFlow = new NpcType( - id++, - "OlgaFlow", - "Olga Flow", - "Olga Flow", - "Olga Flow", - 2, - true - ); - - // Episode IV - - NpcType.SandRappy = new NpcType( - id++, - "SandRappy", - "Sand Rappy", - "Sand Rappy", - "Sand Rappy", - 4, - true - ); - NpcType.DelRappy = new NpcType( - id++, - "DelRappy", - "Del Rappy", - "Del Rappy", - "Del Rappy", - 4, - true - ); - NpcType.SandRappy.rare_type = NpcType.DelRappy; - NpcType.Astark = new NpcType(id++, "Astark", "Astark", "Astark", "Astark", 4, true); - NpcType.SatelliteLizard = new NpcType( - id++, - "SatelliteLizard", - "Satellite Lizard", - "Satellite Lizard", - "Satellite Lizard", - 4, - true - ); - NpcType.Yowie = new NpcType(id++, "Yowie", "Yowie", "Yowie", "Yowie", 4, true); - NpcType.MerissaA = new NpcType( - id++, - "MerissaA", - "Merissa A", - "Merissa A", - "Merissa A", - 4, - true - ); - NpcType.MerissaAA = new NpcType( - id++, - "MerissaAA", - "Merissa AA", - "Merissa AA", - "Merissa AA", - 4, - true - ); - NpcType.MerissaA.rare_type = NpcType.MerissaAA; - NpcType.Girtablulu = new NpcType( - id++, - "Girtablulu", - "Girtablulu", - "Girtablulu", - "Girtablulu", - 4, - true - ); - NpcType.Zu = new NpcType(id++, "Zu", "Zu", "Zu", "Zu", 4, true); - NpcType.Pazuzu = new NpcType(id++, "Pazuzu", "Pazuzu", "Pazuzu", "Pazuzu", 4, true); - NpcType.Zu.rare_type = NpcType.Pazuzu; - NpcType.Boota = new NpcType(id++, "Boota", "Boota", "Boota", "Boota", 4, true); - NpcType.ZeBoota = new NpcType(id++, "ZeBoota", "Ze Boota", "Ze Boota", "Ze Boota", 4, true); - NpcType.BaBoota = new NpcType(id++, "BaBoota", "Ba Boota", "Ba Boota", "Ba Boota", 4, true); - NpcType.Dorphon = new NpcType(id++, "Dorphon", "Dorphon", "Dorphon", "Dorphon", 4, true); - NpcType.DorphonEclair = new NpcType( - id++, - "DorphonEclair", - "Dorphon Eclair", - "Dorphon Eclair", - "Dorphon Eclair", - 4, - true - ); - NpcType.Dorphon.rare_type = NpcType.DorphonEclair; - NpcType.Goran = new NpcType(id++, "Goran", "Goran", "Goran", "Goran", 4, true); - NpcType.PyroGoran = new NpcType( - id++, - "PyroGoran", - "Pyro Goran", - "Pyro Goran", - "Pyro Goran", - 4, - true - ); - NpcType.GoranDetonator = new NpcType( - id++, - "GoranDetonator", - "Goran Detonator", - "Goran Detonator", - "Goran Detonator", - 4, - true - ); - NpcType.SaintMilion = new NpcType( - id++, - "SaintMilion", - "Saint-Milion", - "Saint-Milion", - "Saint-Milion", - 4, - true - ); - NpcType.Shambertin = new NpcType( - id++, - "Shambertin", - "Shambertin", - "Shambertin", - "Shambertin", - 4, - true - ); - NpcType.Kondrieu = new NpcType(id++, "Kondrieu", "Kondrieu", "Kondrieu", "Kondrieu", 4, true); - NpcType.SaintMilion.rare_type = NpcType.Kondrieu; - NpcType.Shambertin.rare_type = NpcType.Kondrieu; -})(); - -export const NpcTypes: NpcType[] = [ - // - // Unknown NPCs - // - - NpcType.Unknown, - - // - // Friendly NPCs - // - - NpcType.FemaleFat, - NpcType.FemaleMacho, - NpcType.FemaleTall, - NpcType.MaleDwarf, - NpcType.MaleFat, - NpcType.MaleMacho, - NpcType.MaleOld, - NpcType.BlueSoldier, - NpcType.RedSoldier, - NpcType.Principal, - NpcType.Tekker, - NpcType.GuildLady, - NpcType.Scientist, - NpcType.Nurse, - NpcType.Irene, - NpcType.ItemShop, - NpcType.Nurse2, - - // - // Enemy NPCs - // - - // Episode I Forest - - NpcType.Hildebear, - NpcType.Hildeblue, - NpcType.RagRappy, - NpcType.AlRappy, - NpcType.Monest, - NpcType.Mothmant, - NpcType.SavageWolf, - NpcType.BarbarousWolf, - NpcType.Booma, - NpcType.Gobooma, - NpcType.Gigobooma, - NpcType.Dragon, - - // Episode I Caves - - NpcType.GrassAssassin, - NpcType.PoisonLily, - NpcType.NarLily, - NpcType.NanoDragon, - NpcType.EvilShark, - NpcType.PalShark, - NpcType.GuilShark, - NpcType.PofuillySlime, - NpcType.PouillySlime, - NpcType.PanArms, - NpcType.Migium, - NpcType.Hidoom, - NpcType.DeRolLe, - - // Episode I Mines - - NpcType.Dubchic, - NpcType.Gilchic, - NpcType.Garanz, - NpcType.SinowBeat, - NpcType.SinowGold, - NpcType.Canadine, - NpcType.Canane, - NpcType.Dubswitch, - NpcType.VolOpt, - - // Episode I Ruins - - NpcType.Delsaber, - NpcType.ChaosSorcerer, - NpcType.DarkGunner, - NpcType.DeathGunner, - NpcType.ChaosBringer, - NpcType.DarkBelra, - NpcType.Dimenian, - NpcType.LaDimenian, - NpcType.SoDimenian, - NpcType.Bulclaw, - NpcType.Bulk, - NpcType.Claw, - NpcType.DarkFalz, - - // Episode II VR Temple - - NpcType.Hildebear2, - NpcType.Hildeblue2, - NpcType.RagRappy2, - NpcType.LoveRappy, - NpcType.StRappy, - NpcType.HalloRappy, - NpcType.EggRappy, - NpcType.Monest2, - NpcType.Mothmant2, - NpcType.PoisonLily2, - NpcType.NarLily2, - NpcType.GrassAssassin2, - NpcType.Dimenian2, - NpcType.LaDimenian2, - NpcType.SoDimenian2, - NpcType.DarkBelra2, - NpcType.BarbaRay, - - // Episode II VR Spaceship - - NpcType.SavageWolf2, - NpcType.BarbarousWolf2, - NpcType.PanArms2, - NpcType.Migium2, - NpcType.Hidoom2, - NpcType.Dubchic2, - NpcType.Gilchic2, - NpcType.Garanz2, - NpcType.Dubswitch2, - NpcType.Delsaber2, - NpcType.ChaosSorcerer2, - NpcType.GolDragon, - - // Episode II Central Control Area - - NpcType.SinowBerill, - NpcType.SinowSpigell, - NpcType.Merillia, - NpcType.Meriltas, - NpcType.Mericarol, - NpcType.Mericus, - NpcType.Merikle, - NpcType.UlGibbon, - NpcType.ZolGibbon, - NpcType.Gibbles, - NpcType.Gee, - NpcType.GiGue, - NpcType.IllGill, - NpcType.DelLily, - NpcType.Epsilon, - NpcType.GalGryphon, - - // Episode II Seabed - - NpcType.Deldepth, - NpcType.Delbiter, - NpcType.Dolmolm, - NpcType.Dolmdarl, - NpcType.Morfos, - NpcType.Recobox, - NpcType.Recon, - NpcType.SinowZoa, - NpcType.SinowZele, - NpcType.OlgaFlow, - - // Episode IV - - NpcType.SandRappy, - NpcType.DelRappy, - NpcType.Astark, - NpcType.SatelliteLizard, - NpcType.Yowie, - NpcType.MerissaA, - NpcType.MerissaAA, - NpcType.Girtablulu, - NpcType.Zu, - NpcType.Pazuzu, - NpcType.Boota, - NpcType.ZeBoota, - NpcType.BaBoota, - NpcType.Dorphon, - NpcType.DorphonEclair, - NpcType.Goran, - NpcType.PyroGoran, - NpcType.GoranDetonator, - NpcType.SaintMilion, - NpcType.Shambertin, - NpcType.Kondrieu, -]; - -export const EnemyNpcTypes = NpcTypes.filter(type => type.enemy); diff --git a/src/domain/ObjectType.ts b/src/domain/ObjectType.ts deleted file mode 100644 index 9ad4c113..00000000 --- a/src/domain/ObjectType.ts +++ /dev/null @@ -1,1657 +0,0 @@ -import { EntityType } from "."; - -export class ObjectType implements EntityType { - readonly id: number; - readonly code: string; - readonly pso_id?: number; - readonly name: string; - - constructor(id: number, code: string, pso_id: number | undefined, name: string) { - if (!Number.isInteger(id) || id < 1) - throw new Error(`Expected id to be an integer greater than or equal to 1, got ${id}.`); - if (!code) throw new Error("code is required."); - if (pso_id != null && (!Number.isInteger(pso_id) || pso_id < 0)) - throw new Error( - `Expected pso_id to be null or an integer greater than or equal to 0, got ${pso_id}.` - ); - if (!name) throw new Error("name is required."); - - this.id = id; - this.code = code; - this.pso_id = pso_id; - this.name = name; - } - - static Unknown: ObjectType; - static PlayerSet: ObjectType; - static Particle: ObjectType; - static Teleporter: ObjectType; - static Warp: ObjectType; - static LightCollision: ObjectType; - static Item: ObjectType; - static EnvSound: ObjectType; - static FogCollision: ObjectType; - static EventCollision: ObjectType; - static CharaCollision: ObjectType; - static ElementalTrap: ObjectType; - static StatusTrap: ObjectType; - static HealTrap: ObjectType; - static LargeElementalTrap: ObjectType; - static ObjRoomID: ObjectType; - static Sensor: ObjectType; - static UnknownItem16: ObjectType; - static Lensflare: ObjectType; - static ScriptCollision: ObjectType; - static HealRing: ObjectType; - static MapCollision: ObjectType; - static ScriptCollisionA: ObjectType; - static ItemLight: ObjectType; - static RadarCollision: ObjectType; - static FogCollisionSW: ObjectType; - static BossTeleporter: ObjectType; - static ImageBoard: ObjectType; - static QuestWarp: ObjectType; - static Epilogue: ObjectType; - static UnknownItem29: ObjectType; - static UnknownItem30: ObjectType; - static UnknownItem31: ObjectType; - static BoxDetectObject: ObjectType; - static SymbolChatObject: ObjectType; - static TouchPlateObject: ObjectType; - static TargetableObject: ObjectType; - static EffectObject: ObjectType; - static CountDownObject: ObjectType; - static UnknownItem38: ObjectType; - static UnknownItem39: ObjectType; - static UnknownItem40: ObjectType; - static UnknownItem41: ObjectType; - static MenuActivation: ObjectType; - static TelepipeLocation: ObjectType; - static BGMCollision: ObjectType; - static MainRagolTeleporter: ObjectType; - static LobbyTeleporter: ObjectType; - static PrincipalWarp: ObjectType; - static ShopDoor: ObjectType; - static HuntersGuildDoor: ObjectType; - static TeleporterDoor: ObjectType; - static MedicalCenterDoor: ObjectType; - static Elevator: ObjectType; - static EasterEgg: ObjectType; - static ValentinesHeart: ObjectType; - static ChristmasTree: ObjectType; - static ChristmasWreath: ObjectType; - static HalloweenPumpkin: ObjectType; - static TwentyFirstCentury: ObjectType; - static Sonic: ObjectType; - static WelcomeBoard: ObjectType; - static Firework: ObjectType; - static LobbyScreenDoor: ObjectType; - static MainRagolTeleporterBattleInNextArea: ObjectType; - static LabTeleporterDoor: ObjectType; - static Pioneer2InvisibleTouchplate: ObjectType; - static ForestDoor: ObjectType; - static ForestSwitch: ObjectType; - static LaserFence: ObjectType; - static LaserSquareFence: ObjectType; - static ForestLaserFenceSwitch: ObjectType; - static LightRays: ObjectType; - static BlueButterfly: ObjectType; - static Probe: ObjectType; - static RandomTypeBox1: ObjectType; - static ForestWeatherStation: ObjectType; - static Battery: ObjectType; - static ForestConsole: ObjectType; - static BlackSlidingDoor: ObjectType; - static RicoMessagePod: ObjectType; - static EnergyBarrier: ObjectType; - static ForestRisingBridge: ObjectType; - static SwitchNoneDoor: ObjectType; - static EnemyBoxGrey: ObjectType; - static FixedTypeBox: ObjectType; - static EnemyBoxBrown: ObjectType; - static EmptyTypeBox: ObjectType; - static LaserFenseEx: ObjectType; - static LaserSquareFenceEx: ObjectType; - static FloorPanel1: ObjectType; - static Caves4ButtonDoor: ObjectType; - static CavesNormalDoor: ObjectType; - static CavesSmashingPillar: ObjectType; - static CavesSign1: ObjectType; - static CavesSign2: ObjectType; - static CavesSign3: ObjectType; - static HexagalTank: ObjectType; - static BrownPlatform: ObjectType; - static WarningLightObject: ObjectType; - static Rainbow: ObjectType; - static FloatingJelifish: ObjectType; - static FloatingDragonfly: ObjectType; - static CavesSwitchDoor: ObjectType; - static RobotRechargeStation: ObjectType; - static CavesCakeShop: ObjectType; - static Caves1SmallRedRock: ObjectType; - static Caves1MediumRedRock: ObjectType; - static Caves1LargeRedRock: ObjectType; - static Caves2SmallRock1: ObjectType; - static Caves2MediumRock1: ObjectType; - static Caves2LargeRock1: ObjectType; - static Caves2SmallRock2: ObjectType; - static Caves2MediumRock2: ObjectType; - static Caves2LargeRock2: ObjectType; - static Caves3SmallRock: ObjectType; - static Caves3MediumRock: ObjectType; - static Caves3LargeRock: ObjectType; - static FloorPanel2: ObjectType; - static DestructableRockCaves1: ObjectType; - static DestructableRockCaves2: ObjectType; - static DestructableRockCaves3: ObjectType; - static MinesDoor: ObjectType; - static FloorPanel3: ObjectType; - static MinesSwitchDoor: ObjectType; - static LargeCryoTube: ObjectType; - static ComputerLikeCalus: ObjectType; - static GreenScreenOpeningAndClosing: ObjectType; - static FloatingRobot: ObjectType; - static FloatingBlueLight: ObjectType; - static SelfDestructingObject1: ObjectType; - static SelfDestructingObject2: ObjectType; - static SelfDestructingObject3: ObjectType; - static SparkMachine: ObjectType; - static MinesLargeFlashingCrate: ObjectType; - static RuinsSeal: ObjectType; - static RuinsTeleporter: ObjectType; - static RuinsWarpSiteToSite: ObjectType; - static RuinsSwitch: ObjectType; - static FloorPanel4: ObjectType; - static Ruins1Door: ObjectType; - static Ruins3Door: ObjectType; - static Ruins2Door: ObjectType; - static Ruins11ButtonDoor: ObjectType; - static Ruins21ButtonDoor: ObjectType; - static Ruins31ButtonDoor: ObjectType; - static Ruins4ButtonDoor: ObjectType; - static Ruins2ButtonDoor: ObjectType; - static RuinsSensor: ObjectType; - static RuinsFenceSwitch: ObjectType; - static RuinsLaserFence4x2: ObjectType; - static RuinsLaserFence6x2: ObjectType; - static RuinsLaserFence4x4: ObjectType; - static RuinsLaserFence6x4: ObjectType; - static RuinsPoisonBlob: ObjectType; - static RuinsPilarTrap: ObjectType; - static PopupTrapNoTech: ObjectType; - static RuinsCrystal: ObjectType; - static Monument: ObjectType; - static RuinsRock1: ObjectType; - static RuinsRock2: ObjectType; - static RuinsRock3: ObjectType; - static RuinsRock4: ObjectType; - static RuinsRock5: ObjectType; - static RuinsRock6: ObjectType; - static RuinsRock7: ObjectType; - static Poison: ObjectType; - static FixedBoxTypeRuins: ObjectType; - static RandomBoxTypeRuins: ObjectType; - static EnemyTypeBoxYellow: ObjectType; - static EnemyTypeBoxBlue: ObjectType; - static EmptyTypeBoxBlue: ObjectType; - static DestructableRock: ObjectType; - static PopupTrapsTechs: ObjectType; - static FlyingWhiteBird: ObjectType; - static Tower: ObjectType; - static FloatingRocks: ObjectType; - static FloatingSoul: ObjectType; - static Butterfly: ObjectType; - static LobbyGameMenu: ObjectType; - static LobbyWarpObject: ObjectType; - static Lobby1EventObjectDefaultTree: ObjectType; - static UnknownItem387: ObjectType; - static UnknownItem388: ObjectType; - static UnknownItem389: ObjectType; - static LobbyEventObjectStaticPumpkin: ObjectType; - static LobbyEventObject3ChristmasWindows: ObjectType; - static LobbyEventObjectRedAndWhiteCurtain: ObjectType; - static UnknownItem393: ObjectType; - static UnknownItem394: ObjectType; - static LobbyFishTank: ObjectType; - static LobbyEventObjectButterflies: ObjectType; - static UnknownItem400: ObjectType; - static GreyWallLow: ObjectType; - static SpaceshipDoor: ObjectType; - static GreyWallHigh: ObjectType; - static TempleNormalDoor: ObjectType; - static BreakableWallWallButUnbreakable: ObjectType; - static BrokenCilinderAndRubble: ObjectType; - static ThreeBrokenWallPiecesOnFloor: ObjectType; - static HighBrickCilinder: ObjectType; - static LyingCilinder: ObjectType; - static BrickConeWithFlatTop: ObjectType; - static BreakableTempleWall: ObjectType; - static TempleMapDetect: ObjectType; - static SmallBrownBrickRisingBridge: ObjectType; - static LongRisingBridgeWithPinkHighEdges: ObjectType; - static FourSwitchTempleDoor: ObjectType; - static FourButtonSpaceshipDoor: ObjectType; - static ItemBoxCca: ObjectType; - static TeleporterEp2: ObjectType; - static CCADoor: ObjectType; - static SpecialBoxCCA: ObjectType; - static BigCCADoor: ObjectType; - static BigCCADoorSwitch: ObjectType; - static LittleRock: ObjectType; - static Little3StoneWall: ObjectType; - static Medium3StoneWall: ObjectType; - static SpiderPlant: ObjectType; - static CCAAreaTeleporter: ObjectType; - static UnknownItem523: ObjectType; - static WhiteBird: ObjectType; - static OrangeBird: ObjectType; - static Saw: ObjectType; - static LaserDetect: ObjectType; - static UnknownItem529: ObjectType; - static UnknownItem530: ObjectType; - static Seagull: ObjectType; - static Fish: ObjectType; - static SeabedDoorWithBlueEdges: ObjectType; - static SeabedDoorAlwaysOpenNonTriggerable: ObjectType; - static LittleCryotube: ObjectType; - static WideGlassWallBreakable: ObjectType; - static BlueFloatingRobot: ObjectType; - static RedFloatingRobot: ObjectType; - static Dolphin: ObjectType; - static CaptureTrap: ObjectType; - static VRLink: ObjectType; - static UnknownItem576: ObjectType; - static WarpInBarbaRayRoom: ObjectType; - static UnknownItem672: ObjectType; - static GeeNest: ObjectType; - static LabComputerConsole: ObjectType; - static LabComputerConsoleGreenScreen: ObjectType; - static ChairYelllowPillow: ObjectType; - static OrangeWallWithHoleInMiddle: ObjectType; - static GreyWallWithHoleInMiddle: ObjectType; - static LongTable: ObjectType; - static GBAStation: ObjectType; - static TalkLinkToSupport: ObjectType; - static InstaWarp: ObjectType; - static LabInvisibleObject: ObjectType; - static LabGlassWindowDoor: ObjectType; - static UnknownItem700: ObjectType; - static LabCelingWarp: ObjectType; - static Ep4LightSource: ObjectType; - static Cacti: ObjectType; - static BigBrownRock: ObjectType; - static BreakableBrownRock: ObjectType; - static UnknownItem832: ObjectType; - static UnknownItem833: ObjectType; - static PoisonPlant: ObjectType; - static UnknownItem897: ObjectType; - static UnknownItem898: ObjectType; - static OozingDesertPlant: ObjectType; - static UnknownItem901: ObjectType; - static BigBlackRocks: ObjectType; - static UnknownItem903: ObjectType; - static UnknownItem904: ObjectType; - static UnknownItem905: ObjectType; - static UnknownItem906: ObjectType; - static FallingRock: ObjectType; - static DesertPlantHasCollision: ObjectType; - static DesertFixedTypeBoxBreakableCrystals: ObjectType; - static UnknownItem910: ObjectType; - static BeeHive: ObjectType; - static UnknownItem912: ObjectType; - static Heat: ObjectType; - static TopOfSaintMillionEgg: ObjectType; - static UnknownItem961: ObjectType; - - static from_pso_id(psoId: number): ObjectType { - switch (psoId) { - default: - return ObjectType.Unknown; - - case 0: - return ObjectType.PlayerSet; - case 1: - return ObjectType.Particle; - case 2: - return ObjectType.Teleporter; - case 3: - return ObjectType.Warp; - case 4: - return ObjectType.LightCollision; - case 5: - return ObjectType.Item; - case 6: - return ObjectType.EnvSound; - case 7: - return ObjectType.FogCollision; - case 8: - return ObjectType.EventCollision; - case 9: - return ObjectType.CharaCollision; - case 10: - return ObjectType.ElementalTrap; - case 11: - return ObjectType.StatusTrap; - case 12: - return ObjectType.HealTrap; - case 13: - return ObjectType.LargeElementalTrap; - case 14: - return ObjectType.ObjRoomID; - case 15: - return ObjectType.Sensor; - case 16: - return ObjectType.UnknownItem16; - case 17: - return ObjectType.Lensflare; - case 18: - return ObjectType.ScriptCollision; - case 19: - return ObjectType.HealRing; - case 20: - return ObjectType.MapCollision; - case 21: - return ObjectType.ScriptCollisionA; - case 22: - return ObjectType.ItemLight; - case 23: - return ObjectType.RadarCollision; - case 24: - return ObjectType.FogCollisionSW; - case 25: - return ObjectType.BossTeleporter; - case 26: - return ObjectType.ImageBoard; - case 27: - return ObjectType.QuestWarp; - case 28: - return ObjectType.Epilogue; - case 29: - return ObjectType.UnknownItem29; - case 30: - return ObjectType.UnknownItem30; - case 31: - return ObjectType.UnknownItem31; - case 32: - return ObjectType.BoxDetectObject; - case 33: - return ObjectType.SymbolChatObject; - case 34: - return ObjectType.TouchPlateObject; - case 35: - return ObjectType.TargetableObject; - case 36: - return ObjectType.EffectObject; - case 37: - return ObjectType.CountDownObject; - case 38: - return ObjectType.UnknownItem38; - case 39: - return ObjectType.UnknownItem39; - case 40: - return ObjectType.UnknownItem40; - case 41: - return ObjectType.UnknownItem41; - case 64: - return ObjectType.MenuActivation; - case 65: - return ObjectType.TelepipeLocation; - case 66: - return ObjectType.BGMCollision; - case 67: - return ObjectType.MainRagolTeleporter; - case 68: - return ObjectType.LobbyTeleporter; - case 69: - return ObjectType.PrincipalWarp; - case 70: - return ObjectType.ShopDoor; - case 71: - return ObjectType.HuntersGuildDoor; - case 72: - return ObjectType.TeleporterDoor; - case 73: - return ObjectType.MedicalCenterDoor; - case 74: - return ObjectType.Elevator; - case 75: - return ObjectType.EasterEgg; - case 76: - return ObjectType.ValentinesHeart; - case 77: - return ObjectType.ChristmasTree; - case 78: - return ObjectType.ChristmasWreath; - case 79: - return ObjectType.HalloweenPumpkin; - case 80: - return ObjectType.TwentyFirstCentury; - case 81: - return ObjectType.Sonic; - case 82: - return ObjectType.WelcomeBoard; - case 83: - return ObjectType.Firework; - case 84: - return ObjectType.LobbyScreenDoor; - case 85: - return ObjectType.MainRagolTeleporterBattleInNextArea; - case 86: - return ObjectType.LabTeleporterDoor; - case 87: - return ObjectType.Pioneer2InvisibleTouchplate; - case 128: - return ObjectType.ForestDoor; - case 129: - return ObjectType.ForestSwitch; - case 130: - return ObjectType.LaserFence; - case 131: - return ObjectType.LaserSquareFence; - case 132: - return ObjectType.ForestLaserFenceSwitch; - case 133: - return ObjectType.LightRays; - case 134: - return ObjectType.BlueButterfly; - case 135: - return ObjectType.Probe; - case 136: - return ObjectType.RandomTypeBox1; - case 137: - return ObjectType.ForestWeatherStation; - case 138: - return ObjectType.Battery; - case 139: - return ObjectType.ForestConsole; - case 140: - return ObjectType.BlackSlidingDoor; - case 141: - return ObjectType.RicoMessagePod; - case 142: - return ObjectType.EnergyBarrier; - case 143: - return ObjectType.ForestRisingBridge; - case 144: - return ObjectType.SwitchNoneDoor; - case 145: - return ObjectType.EnemyBoxGrey; - case 146: - return ObjectType.FixedTypeBox; - case 147: - return ObjectType.EnemyBoxBrown; - case 149: - return ObjectType.EmptyTypeBox; - case 150: - return ObjectType.LaserFenseEx; - case 151: - return ObjectType.LaserSquareFenceEx; - case 192: - return ObjectType.FloorPanel1; - case 193: - return ObjectType.Caves4ButtonDoor; - case 194: - return ObjectType.CavesNormalDoor; - case 195: - return ObjectType.CavesSmashingPillar; - case 196: - return ObjectType.CavesSign1; - case 197: - return ObjectType.CavesSign2; - case 198: - return ObjectType.CavesSign3; - case 199: - return ObjectType.HexagalTank; - case 200: - return ObjectType.BrownPlatform; - case 201: - return ObjectType.WarningLightObject; - case 203: - return ObjectType.Rainbow; - case 204: - return ObjectType.FloatingJelifish; - case 205: - return ObjectType.FloatingDragonfly; - case 206: - return ObjectType.CavesSwitchDoor; - case 207: - return ObjectType.RobotRechargeStation; - case 208: - return ObjectType.CavesCakeShop; - case 209: - return ObjectType.Caves1SmallRedRock; - case 210: - return ObjectType.Caves1MediumRedRock; - case 211: - return ObjectType.Caves1LargeRedRock; - case 212: - return ObjectType.Caves2SmallRock1; - case 213: - return ObjectType.Caves2MediumRock1; - case 214: - return ObjectType.Caves2LargeRock1; - case 215: - return ObjectType.Caves2SmallRock2; - case 216: - return ObjectType.Caves2MediumRock2; - case 217: - return ObjectType.Caves2LargeRock2; - case 218: - return ObjectType.Caves3SmallRock; - case 219: - return ObjectType.Caves3MediumRock; - case 220: - return ObjectType.Caves3LargeRock; - case 222: - return ObjectType.FloorPanel2; - case 223: - return ObjectType.DestructableRockCaves1; - case 224: - return ObjectType.DestructableRockCaves2; - case 225: - return ObjectType.DestructableRockCaves3; - case 256: - return ObjectType.MinesDoor; - case 257: - return ObjectType.FloorPanel3; - case 258: - return ObjectType.MinesSwitchDoor; - case 259: - return ObjectType.LargeCryoTube; - case 260: - return ObjectType.ComputerLikeCalus; - case 261: - return ObjectType.GreenScreenOpeningAndClosing; - case 262: - return ObjectType.FloatingRobot; - case 263: - return ObjectType.FloatingBlueLight; - case 264: - return ObjectType.SelfDestructingObject1; - case 265: - return ObjectType.SelfDestructingObject2; - case 266: - return ObjectType.SelfDestructingObject3; - case 267: - return ObjectType.SparkMachine; - case 268: - return ObjectType.MinesLargeFlashingCrate; - case 304: - return ObjectType.RuinsSeal; - case 320: - return ObjectType.RuinsTeleporter; - case 321: - return ObjectType.RuinsWarpSiteToSite; - case 322: - return ObjectType.RuinsSwitch; - case 323: - return ObjectType.FloorPanel4; - case 324: - return ObjectType.Ruins1Door; - case 325: - return ObjectType.Ruins3Door; - case 326: - return ObjectType.Ruins2Door; - case 327: - return ObjectType.Ruins11ButtonDoor; - case 328: - return ObjectType.Ruins21ButtonDoor; - case 329: - return ObjectType.Ruins31ButtonDoor; - case 330: - return ObjectType.Ruins4ButtonDoor; - case 331: - return ObjectType.Ruins2ButtonDoor; - case 332: - return ObjectType.RuinsSensor; - case 333: - return ObjectType.RuinsFenceSwitch; - case 334: - return ObjectType.RuinsLaserFence4x2; - case 335: - return ObjectType.RuinsLaserFence6x2; - case 336: - return ObjectType.RuinsLaserFence4x4; - case 337: - return ObjectType.RuinsLaserFence6x4; - case 338: - return ObjectType.RuinsPoisonBlob; - case 339: - return ObjectType.RuinsPilarTrap; - case 340: - return ObjectType.PopupTrapNoTech; - case 341: - return ObjectType.RuinsCrystal; - case 342: - return ObjectType.Monument; - case 345: - return ObjectType.RuinsRock1; - case 346: - return ObjectType.RuinsRock2; - case 347: - return ObjectType.RuinsRock3; - case 348: - return ObjectType.RuinsRock4; - case 349: - return ObjectType.RuinsRock5; - case 350: - return ObjectType.RuinsRock6; - case 351: - return ObjectType.RuinsRock7; - case 352: - return ObjectType.Poison; - case 353: - return ObjectType.FixedBoxTypeRuins; - case 354: - return ObjectType.RandomBoxTypeRuins; - case 355: - return ObjectType.EnemyTypeBoxYellow; - case 356: - return ObjectType.EnemyTypeBoxBlue; - case 357: - return ObjectType.EmptyTypeBoxBlue; - case 358: - return ObjectType.DestructableRock; - case 359: - return ObjectType.PopupTrapsTechs; - case 368: - return ObjectType.FlyingWhiteBird; - case 369: - return ObjectType.Tower; - case 370: - return ObjectType.FloatingRocks; - case 371: - return ObjectType.FloatingSoul; - case 372: - return ObjectType.Butterfly; - case 384: - return ObjectType.LobbyGameMenu; - case 385: - return ObjectType.LobbyWarpObject; - case 386: - return ObjectType.Lobby1EventObjectDefaultTree; - case 387: - return ObjectType.UnknownItem387; - case 388: - return ObjectType.UnknownItem388; - case 389: - return ObjectType.UnknownItem389; - case 390: - return ObjectType.LobbyEventObjectStaticPumpkin; - case 391: - return ObjectType.LobbyEventObject3ChristmasWindows; - case 392: - return ObjectType.LobbyEventObjectRedAndWhiteCurtain; - case 393: - return ObjectType.UnknownItem393; - case 394: - return ObjectType.UnknownItem394; - case 395: - return ObjectType.LobbyFishTank; - case 396: - return ObjectType.LobbyEventObjectButterflies; - case 400: - return ObjectType.UnknownItem400; - case 401: - return ObjectType.GreyWallLow; - case 402: - return ObjectType.SpaceshipDoor; - case 403: - return ObjectType.GreyWallHigh; - case 416: - return ObjectType.TempleNormalDoor; - case 417: - return ObjectType.BreakableWallWallButUnbreakable; - case 418: - return ObjectType.BrokenCilinderAndRubble; - case 419: - return ObjectType.ThreeBrokenWallPiecesOnFloor; - case 420: - return ObjectType.HighBrickCilinder; - case 421: - return ObjectType.LyingCilinder; - case 422: - return ObjectType.BrickConeWithFlatTop; - case 423: - return ObjectType.BreakableTempleWall; - case 424: - return ObjectType.TempleMapDetect; - case 425: - return ObjectType.SmallBrownBrickRisingBridge; - case 426: - return ObjectType.LongRisingBridgeWithPinkHighEdges; - case 427: - return ObjectType.FourSwitchTempleDoor; - case 448: - return ObjectType.FourButtonSpaceshipDoor; - case 512: - return ObjectType.ItemBoxCca; - case 513: - return ObjectType.TeleporterEp2; - case 514: - return ObjectType.CCADoor; - case 515: - return ObjectType.SpecialBoxCCA; - case 516: - return ObjectType.BigCCADoor; - case 517: - return ObjectType.BigCCADoorSwitch; - case 518: - return ObjectType.LittleRock; - case 519: - return ObjectType.Little3StoneWall; - case 520: - return ObjectType.Medium3StoneWall; - case 521: - return ObjectType.SpiderPlant; - case 522: - return ObjectType.CCAAreaTeleporter; - case 523: - return ObjectType.UnknownItem523; - case 524: - return ObjectType.WhiteBird; - case 525: - return ObjectType.OrangeBird; - case 527: - return ObjectType.Saw; - case 528: - return ObjectType.LaserDetect; - case 529: - return ObjectType.UnknownItem529; - case 530: - return ObjectType.UnknownItem530; - case 531: - return ObjectType.Seagull; - case 544: - return ObjectType.Fish; - case 545: - return ObjectType.SeabedDoorWithBlueEdges; - case 546: - return ObjectType.SeabedDoorAlwaysOpenNonTriggerable; - case 547: - return ObjectType.LittleCryotube; - case 548: - return ObjectType.WideGlassWallBreakable; - case 549: - return ObjectType.BlueFloatingRobot; - case 550: - return ObjectType.RedFloatingRobot; - case 551: - return ObjectType.Dolphin; - case 552: - return ObjectType.CaptureTrap; - case 553: - return ObjectType.VRLink; - case 576: - return ObjectType.UnknownItem576; - case 640: - return ObjectType.WarpInBarbaRayRoom; - case 672: - return ObjectType.UnknownItem672; - case 688: - return ObjectType.GeeNest; - case 689: - return ObjectType.LabComputerConsole; - case 690: - return ObjectType.LabComputerConsoleGreenScreen; - case 691: - return ObjectType.ChairYelllowPillow; - case 692: - return ObjectType.OrangeWallWithHoleInMiddle; - case 693: - return ObjectType.GreyWallWithHoleInMiddle; - case 694: - return ObjectType.LongTable; - case 695: - return ObjectType.GBAStation; - case 696: - return ObjectType.TalkLinkToSupport; - case 697: - return ObjectType.InstaWarp; - case 698: - return ObjectType.LabInvisibleObject; - case 699: - return ObjectType.LabGlassWindowDoor; - case 700: - return ObjectType.UnknownItem700; - case 701: - return ObjectType.LabCelingWarp; - case 768: - return ObjectType.Ep4LightSource; - case 769: - return ObjectType.Cacti; - case 770: - return ObjectType.BigBrownRock; - case 771: - return ObjectType.BreakableBrownRock; - case 832: - return ObjectType.UnknownItem832; - case 833: - return ObjectType.UnknownItem833; - case 896: - return ObjectType.PoisonPlant; - case 897: - return ObjectType.UnknownItem897; - case 898: - return ObjectType.UnknownItem898; - case 899: - return ObjectType.OozingDesertPlant; - case 901: - return ObjectType.UnknownItem901; - case 902: - return ObjectType.BigBlackRocks; - case 903: - return ObjectType.UnknownItem903; - case 904: - return ObjectType.UnknownItem904; - case 905: - return ObjectType.UnknownItem905; - case 906: - return ObjectType.UnknownItem906; - case 907: - return ObjectType.FallingRock; - case 908: - return ObjectType.DesertPlantHasCollision; - case 909: - return ObjectType.DesertFixedTypeBoxBreakableCrystals; - case 910: - return ObjectType.UnknownItem910; - case 911: - return ObjectType.BeeHive; - case 912: - return ObjectType.UnknownItem912; - case 913: - return ObjectType.Heat; - case 960: - return ObjectType.TopOfSaintMillionEgg; - case 961: - return ObjectType.UnknownItem961; - } - } -} - -(function() { - let id = 1; - - ObjectType.Unknown = new ObjectType(id++, "Unknown", undefined, "Unknown"); - - ObjectType.PlayerSet = new ObjectType(id++, "PlayerSet", 0, "Player Set"); - ObjectType.Particle = new ObjectType(id++, "Particle", 1, "Particle"); - ObjectType.Teleporter = new ObjectType(id++, "Teleporter", 2, "Teleporter"); - ObjectType.Warp = new ObjectType(id++, "Warp", 3, "Warp"); - ObjectType.LightCollision = new ObjectType(id++, "LightCollision", 4, "Light Collision"); - ObjectType.Item = new ObjectType(id++, "Item", 5, "Item"); - ObjectType.EnvSound = new ObjectType(id++, "EnvSound", 6, "Env Sound"); - ObjectType.FogCollision = new ObjectType(id++, "FogCollision", 7, "Fog Collision"); - ObjectType.EventCollision = new ObjectType(id++, "EventCollision", 8, "Event Collision"); - ObjectType.CharaCollision = new ObjectType(id++, "CharaCollision", 9, "Chara Collision"); - ObjectType.ElementalTrap = new ObjectType(id++, "ElementalTrap", 10, "Elemental Trap"); - ObjectType.StatusTrap = new ObjectType(id++, "StatusTrap", 11, "Status Trap"); - ObjectType.HealTrap = new ObjectType(id++, "HealTrap", 12, "Heal Trap"); - ObjectType.LargeElementalTrap = new ObjectType( - id++, - "LargeElementalTrap", - 13, - "Large Elemental Trap" - ); - ObjectType.ObjRoomID = new ObjectType(id++, "ObjRoomID", 14, "Obj Room ID"); - ObjectType.Sensor = new ObjectType(id++, "Sensor", 15, "Sensor"); - ObjectType.UnknownItem16 = new ObjectType(id++, "UnknownItem16", 16, "Unknown Item (16)"); - ObjectType.Lensflare = new ObjectType(id++, "Lensflare", 17, "Lensflare"); - ObjectType.ScriptCollision = new ObjectType(id++, "ScriptCollision", 18, "Script Collision"); - ObjectType.HealRing = new ObjectType(id++, "HealRing", 19, "Heal Ring"); - ObjectType.MapCollision = new ObjectType(id++, "MapCollision", 20, "Map Collision"); - ObjectType.ScriptCollisionA = new ObjectType( - id++, - "ScriptCollisionA", - 21, - "Script Collision A" - ); - ObjectType.ItemLight = new ObjectType(id++, "ItemLight", 22, "Item Light"); - ObjectType.RadarCollision = new ObjectType(id++, "RadarCollision", 23, "Radar Collision"); - ObjectType.FogCollisionSW = new ObjectType(id++, "FogCollisionSW", 24, "Fog Collision SW"); - ObjectType.BossTeleporter = new ObjectType(id++, "BossTeleporter", 25, "Boss Teleporter"); - ObjectType.ImageBoard = new ObjectType(id++, "ImageBoard", 26, "Image Board"); - ObjectType.QuestWarp = new ObjectType(id++, "QuestWarp", 27, "Quest Warp"); - ObjectType.Epilogue = new ObjectType(id++, "Epilogue", 28, "Epilogue"); - ObjectType.UnknownItem29 = new ObjectType(id++, "UnknownItem29", 29, "Unknown Item (29)"); - ObjectType.UnknownItem30 = new ObjectType(id++, "UnknownItem30", 30, "Unknown Item (30)"); - ObjectType.UnknownItem31 = new ObjectType(id++, "UnknownItem31", 31, "Unknown Item (31)"); - ObjectType.BoxDetectObject = new ObjectType(id++, "BoxDetectObject", 32, "Box Detect Object"); - ObjectType.SymbolChatObject = new ObjectType( - id++, - "SymbolChatObject", - 33, - "Symbol Chat Object" - ); - ObjectType.TouchPlateObject = new ObjectType( - id++, - "TouchPlateObject", - 34, - "Touch plate Object" - ); - ObjectType.TargetableObject = new ObjectType(id++, "TargetableObject", 35, "Targetable Object"); - ObjectType.EffectObject = new ObjectType(id++, "EffectObject", 36, "Effect object"); - ObjectType.CountDownObject = new ObjectType(id++, "CountDownObject", 37, "Count Down Object"); - ObjectType.UnknownItem38 = new ObjectType(id++, "UnknownItem38", 38, "Unknown Item (38)"); - ObjectType.UnknownItem39 = new ObjectType(id++, "UnknownItem39", 39, "Unknown Item (39)"); - ObjectType.UnknownItem40 = new ObjectType(id++, "UnknownItem40", 40, "Unknown Item (40)"); - ObjectType.UnknownItem41 = new ObjectType(id++, "UnknownItem41", 41, "Unknown Item (41)"); - ObjectType.MenuActivation = new ObjectType(id++, "MenuActivation", 64, "Menu activation"); - ObjectType.TelepipeLocation = new ObjectType(id++, "TelepipeLocation", 65, "Telepipe Location"); - ObjectType.BGMCollision = new ObjectType(id++, "BGMCollision", 66, "BGM Collision"); - ObjectType.MainRagolTeleporter = new ObjectType( - id++, - "MainRagolTeleporter", - 67, - "Main Ragol Teleporter" - ); - ObjectType.LobbyTeleporter = new ObjectType(id++, "LobbyTeleporter", 68, "Lobby Teleporter"); - ObjectType.PrincipalWarp = new ObjectType(id++, "PrincipalWarp", 69, "Principal warp"); - ObjectType.ShopDoor = new ObjectType(id++, "ShopDoor", 70, "Shop Door"); - ObjectType.HuntersGuildDoor = new ObjectType( - id++, - "HuntersGuildDoor", - 71, - "Hunter's Guild Door" - ); - ObjectType.TeleporterDoor = new ObjectType(id++, "TeleporterDoor", 72, "Teleporter Door"); - ObjectType.MedicalCenterDoor = new ObjectType( - id++, - "MedicalCenterDoor", - 73, - "Medical Center Door" - ); - ObjectType.Elevator = new ObjectType(id++, "Elevator", 74, "Elevator"); - ObjectType.EasterEgg = new ObjectType(id++, "EasterEgg", 75, "Easter Egg"); - ObjectType.ValentinesHeart = new ObjectType(id++, "ValentinesHeart", 76, "Valentines Heart"); - ObjectType.ChristmasTree = new ObjectType(id++, "ChristmasTree", 77, "Christmas Tree"); - ObjectType.ChristmasWreath = new ObjectType(id++, "ChristmasWreath", 78, "Christmas Wreath"); - ObjectType.HalloweenPumpkin = new ObjectType(id++, "HalloweenPumpkin", 79, "Halloween Pumpkin"); - ObjectType.TwentyFirstCentury = new ObjectType(id++, "TwentyFirstCentury", 80, "21st Century"); - ObjectType.Sonic = new ObjectType(id++, "Sonic", 81, "Sonic"); - ObjectType.WelcomeBoard = new ObjectType(id++, "WelcomeBoard", 82, "Welcome Board"); - ObjectType.Firework = new ObjectType(id++, "Firework", 83, "Firework"); - ObjectType.LobbyScreenDoor = new ObjectType(id++, "LobbyScreenDoor", 84, "Lobby Screen Door"); - ObjectType.MainRagolTeleporterBattleInNextArea = new ObjectType( - id++, - "MainRagolTeleporterBattleInNextArea", - 85, - "Main Ragol Teleporter (Battle in next area?)" - ); - ObjectType.LabTeleporterDoor = new ObjectType( - id++, - "LabTeleporterDoor", - 86, - "Lab Teleporter Door" - ); - ObjectType.Pioneer2InvisibleTouchplate = new ObjectType( - id++, - "Pioneer2InvisibleTouchplate", - 87, - "Pioneer 2 Invisible Touchplate" - ); - ObjectType.ForestDoor = new ObjectType(id++, "ForestDoor", 128, "Forest Door"); - ObjectType.ForestSwitch = new ObjectType(id++, "ForestSwitch", 129, "Forest Switch"); - ObjectType.LaserFence = new ObjectType(id++, "LaserFence", 130, "Laser Fence"); - ObjectType.LaserSquareFence = new ObjectType( - id++, - "LaserSquareFence", - 131, - "Laser Square Fence" - ); - ObjectType.ForestLaserFenceSwitch = new ObjectType( - id++, - "ForestLaserFenceSwitch", - 132, - "Forest Laser Fence Switch" - ); - ObjectType.LightRays = new ObjectType(id++, "LightRays", 133, "Light rays"); - ObjectType.BlueButterfly = new ObjectType(id++, "BlueButterfly", 134, "Blue Butterfly"); - ObjectType.Probe = new ObjectType(id++, "Probe", 135, "Probe"); - ObjectType.RandomTypeBox1 = new ObjectType(id++, "RandomTypeBox1", 136, "Random Type Box 1"); - ObjectType.ForestWeatherStation = new ObjectType( - id++, - "ForestWeatherStation", - 137, - "Forest Weather Station" - ); - ObjectType.Battery = new ObjectType(id++, "Battery", 138, "Battery"); - ObjectType.ForestConsole = new ObjectType(id++, "ForestConsole", 139, "Forest Console"); - ObjectType.BlackSlidingDoor = new ObjectType( - id++, - "BlackSlidingDoor", - 140, - "Black Sliding Door" - ); - ObjectType.RicoMessagePod = new ObjectType(id++, "RicoMessagePod", 141, "Rico Message Pod"); - ObjectType.EnergyBarrier = new ObjectType(id++, "EnergyBarrier", 142, "Energy Barrier"); - ObjectType.ForestRisingBridge = new ObjectType( - id++, - "ForestRisingBridge", - 143, - "Forest Rising Bridge" - ); - ObjectType.SwitchNoneDoor = new ObjectType(id++, "SwitchNoneDoor", 144, "Switch (none door)"); - ObjectType.EnemyBoxGrey = new ObjectType(id++, "EnemyBoxGrey", 145, "Enemy Box (Grey)"); - ObjectType.FixedTypeBox = new ObjectType(id++, "FixedTypeBox", 146, "Fixed Type Box"); - ObjectType.EnemyBoxBrown = new ObjectType(id++, "EnemyBoxBrown", 147, "Enemy Box (Brown)"); - ObjectType.EmptyTypeBox = new ObjectType(id++, "EmptyTypeBox", 149, "Empty Type Box"); - ObjectType.LaserFenseEx = new ObjectType(id++, "LaserFenseEx", 150, "Laser Fense Ex"); - ObjectType.LaserSquareFenceEx = new ObjectType( - id++, - "LaserSquareFenceEx", - 151, - "Laser Square Fence Ex" - ); - ObjectType.FloorPanel1 = new ObjectType(id++, "FloorPanel1", 192, "Floor Panel 1"); - ObjectType.Caves4ButtonDoor = new ObjectType( - id++, - "Caves4ButtonDoor", - 193, - "Caves 4 Button door" - ); - ObjectType.CavesNormalDoor = new ObjectType(id++, "CavesNormalDoor", 194, "Caves Normal door"); - ObjectType.CavesSmashingPillar = new ObjectType( - id++, - "CavesSmashingPillar", - 195, - "Caves Smashing Pillar" - ); - ObjectType.CavesSign1 = new ObjectType(id++, "CavesSign1", 196, "Caves Sign 1"); - ObjectType.CavesSign2 = new ObjectType(id++, "CavesSign2", 197, "Caves Sign 2"); - ObjectType.CavesSign3 = new ObjectType(id++, "CavesSign3", 198, "Caves Sign 3"); - ObjectType.HexagalTank = new ObjectType(id++, "HexagalTank", 199, "Hexagal Tank"); - ObjectType.BrownPlatform = new ObjectType(id++, "BrownPlatform", 200, "Brown Platform"); - ObjectType.WarningLightObject = new ObjectType( - id++, - "WarningLightObject", - 201, - "Warning Light Object" - ); - ObjectType.Rainbow = new ObjectType(id++, "Rainbow", 203, "Rainbow"); - ObjectType.FloatingJelifish = new ObjectType( - id++, - "FloatingJelifish", - 204, - "Floating Jelifish" - ); - ObjectType.FloatingDragonfly = new ObjectType( - id++, - "FloatingDragonfly", - 205, - "Floating Dragonfly" - ); - ObjectType.CavesSwitchDoor = new ObjectType(id++, "CavesSwitchDoor", 206, "Caves Switch Door"); - ObjectType.RobotRechargeStation = new ObjectType( - id++, - "RobotRechargeStation", - 207, - "Robot Recharge Station" - ); - ObjectType.CavesCakeShop = new ObjectType(id++, "CavesCakeShop", 208, "Caves Cake Shop"); - ObjectType.Caves1SmallRedRock = new ObjectType( - id++, - "Caves1SmallRedRock", - 209, - "Caves 1 Small Red Rock" - ); - ObjectType.Caves1MediumRedRock = new ObjectType( - id++, - "Caves1MediumRedRock", - 210, - "Caves 1 Medium Red Rock" - ); - ObjectType.Caves1LargeRedRock = new ObjectType( - id++, - "Caves1LargeRedRock", - 211, - "Caves 1 Large Red Rock" - ); - ObjectType.Caves2SmallRock1 = new ObjectType( - id++, - "Caves2SmallRock1", - 212, - "Caves 2 Small Rock 1" - ); - ObjectType.Caves2MediumRock1 = new ObjectType( - id++, - "Caves2MediumRock1", - 213, - "Caves 2 Medium Rock 1" - ); - ObjectType.Caves2LargeRock1 = new ObjectType( - id++, - "Caves2LargeRock1", - 214, - "Caves 2 Large Rock 1" - ); - ObjectType.Caves2SmallRock2 = new ObjectType( - id++, - "Caves2SmallRock2", - 215, - "Caves 2 Small Rock 2" - ); - ObjectType.Caves2MediumRock2 = new ObjectType( - id++, - "Caves2MediumRock2", - 216, - "Caves 2 Medium Rock 2" - ); - ObjectType.Caves2LargeRock2 = new ObjectType( - id++, - "Caves2LargeRock2", - 217, - "Caves 2 Large Rock 2" - ); - ObjectType.Caves3SmallRock = new ObjectType(id++, "Caves3SmallRock", 218, "Caves 3 Small Rock"); - ObjectType.Caves3MediumRock = new ObjectType( - id++, - "Caves3MediumRock", - 219, - "Caves 3 Medium Rock" - ); - ObjectType.Caves3LargeRock = new ObjectType(id++, "Caves3LargeRock", 220, "Caves 3 Large Rock"); - ObjectType.FloorPanel2 = new ObjectType(id++, "FloorPanel2", 222, "Floor Panel 2"); - ObjectType.DestructableRockCaves1 = new ObjectType( - id++, - "DestructableRockCaves1", - 223, - "Destructable Rock (Caves 1)" - ); - ObjectType.DestructableRockCaves2 = new ObjectType( - id++, - "DestructableRockCaves2", - 224, - "Destructable Rock (Caves 2)" - ); - ObjectType.DestructableRockCaves3 = new ObjectType( - id++, - "DestructableRockCaves3", - 225, - "Destructable Rock (Caves 3)" - ); - ObjectType.MinesDoor = new ObjectType(id++, "MinesDoor", 256, "Mines Door"); - ObjectType.FloorPanel3 = new ObjectType(id++, "FloorPanel3", 257, "Floor Panel 3"); - ObjectType.MinesSwitchDoor = new ObjectType(id++, "MinesSwitchDoor", 258, "Mines Switch Door"); - ObjectType.LargeCryoTube = new ObjectType(id++, "LargeCryoTube", 259, "Large Cryo-Tube"); - ObjectType.ComputerLikeCalus = new ObjectType( - id++, - "ComputerLikeCalus", - 260, - "Computer (like calus)" - ); - ObjectType.GreenScreenOpeningAndClosing = new ObjectType( - id++, - "GreenScreenOpeningAndClosing", - 261, - "Green Screen opening and closing" - ); - ObjectType.FloatingRobot = new ObjectType(id++, "FloatingRobot", 262, "Floating Robot"); - ObjectType.FloatingBlueLight = new ObjectType( - id++, - "FloatingBlueLight", - 263, - "Floating Blue Light" - ); - ObjectType.SelfDestructingObject1 = new ObjectType( - id++, - "SelfDestructingObject1", - 264, - "Self Destructing Object 1" - ); - ObjectType.SelfDestructingObject2 = new ObjectType( - id++, - "SelfDestructingObject2", - 265, - "Self Destructing Object 2" - ); - ObjectType.SelfDestructingObject3 = new ObjectType( - id++, - "SelfDestructingObject3", - 266, - "Self Destructing Object 3" - ); - ObjectType.SparkMachine = new ObjectType(id++, "SparkMachine", 267, "Spark Machine"); - ObjectType.MinesLargeFlashingCrate = new ObjectType( - id++, - "MinesLargeFlashingCrate", - 268, - "Mines Large Flashing Crate" - ); - ObjectType.RuinsSeal = new ObjectType(id++, "RuinsSeal", 304, "Ruins Seal"); - ObjectType.RuinsTeleporter = new ObjectType(id++, "RuinsTeleporter", 320, "Ruins Teleporter"); - ObjectType.RuinsWarpSiteToSite = new ObjectType( - id++, - "RuinsWarpSiteToSite", - 321, - "Ruins Warp (Site to site)" - ); - ObjectType.RuinsSwitch = new ObjectType(id++, "RuinsSwitch", 322, "Ruins Switch"); - ObjectType.FloorPanel4 = new ObjectType(id++, "FloorPanel4", 323, "Floor Panel 4"); - ObjectType.Ruins1Door = new ObjectType(id++, "Ruins1Door", 324, "Ruins 1 Door"); - ObjectType.Ruins3Door = new ObjectType(id++, "Ruins3Door", 325, "Ruins 3 Door"); - ObjectType.Ruins2Door = new ObjectType(id++, "Ruins2Door", 326, "Ruins 2 Door"); - ObjectType.Ruins11ButtonDoor = new ObjectType( - id++, - "Ruins11ButtonDoor", - 327, - "Ruins 1-1 Button Door" - ); - ObjectType.Ruins21ButtonDoor = new ObjectType( - id++, - "Ruins21ButtonDoor", - 328, - "Ruins 2-1 Button Door" - ); - ObjectType.Ruins31ButtonDoor = new ObjectType( - id++, - "Ruins31ButtonDoor", - 329, - "Ruins 3-1 Button Door" - ); - ObjectType.Ruins4ButtonDoor = new ObjectType( - id++, - "Ruins4ButtonDoor", - 330, - "Ruins 4-Button Door" - ); - ObjectType.Ruins2ButtonDoor = new ObjectType( - id++, - "Ruins2ButtonDoor", - 331, - "Ruins 2-Button Door" - ); - ObjectType.RuinsSensor = new ObjectType(id++, "RuinsSensor", 332, "Ruins Sensor"); - ObjectType.RuinsFenceSwitch = new ObjectType( - id++, - "RuinsFenceSwitch", - 333, - "Ruins Fence Switch" - ); - ObjectType.RuinsLaserFence4x2 = new ObjectType( - id++, - "RuinsLaserFence4x2", - 334, - "Ruins Laser Fence 4x2" - ); - ObjectType.RuinsLaserFence6x2 = new ObjectType( - id++, - "RuinsLaserFence6x2", - 335, - "Ruins Laser Fence 6x2" - ); - ObjectType.RuinsLaserFence4x4 = new ObjectType( - id++, - "RuinsLaserFence4x4", - 336, - "Ruins Laser Fence 4x4" - ); - ObjectType.RuinsLaserFence6x4 = new ObjectType( - id++, - "RuinsLaserFence6x4", - 337, - "Ruins Laser Fence 6x4" - ); - ObjectType.RuinsPoisonBlob = new ObjectType(id++, "RuinsPoisonBlob", 338, "Ruins poison Blob"); - ObjectType.RuinsPilarTrap = new ObjectType(id++, "RuinsPilarTrap", 339, "Ruins Pilar Trap"); - ObjectType.PopupTrapNoTech = new ObjectType( - id++, - "PopupTrapNoTech", - 340, - "Popup Trap (No Tech)" - ); - ObjectType.RuinsCrystal = new ObjectType(id++, "RuinsCrystal", 341, "Ruins Crystal"); - ObjectType.Monument = new ObjectType(id++, "Monument", 342, "Monument"); - ObjectType.RuinsRock1 = new ObjectType(id++, "RuinsRock1", 345, "Ruins Rock 1"); - ObjectType.RuinsRock2 = new ObjectType(id++, "RuinsRock2", 346, "Ruins Rock 2"); - ObjectType.RuinsRock3 = new ObjectType(id++, "RuinsRock3", 347, "Ruins Rock 3"); - ObjectType.RuinsRock4 = new ObjectType(id++, "RuinsRock4", 348, "Ruins Rock 4"); - ObjectType.RuinsRock5 = new ObjectType(id++, "RuinsRock5", 349, "Ruins Rock 5"); - ObjectType.RuinsRock6 = new ObjectType(id++, "RuinsRock6", 350, "Ruins Rock 6"); - ObjectType.RuinsRock7 = new ObjectType(id++, "RuinsRock7", 351, "Ruins Rock 7"); - ObjectType.Poison = new ObjectType(id++, "Poison", 352, "Poison"); - ObjectType.FixedBoxTypeRuins = new ObjectType( - id++, - "FixedBoxTypeRuins", - 353, - "Fixed Box Type (Ruins)" - ); - ObjectType.RandomBoxTypeRuins = new ObjectType( - id++, - "RandomBoxTypeRuins", - 354, - "Random Box Type (Ruins)" - ); - ObjectType.EnemyTypeBoxYellow = new ObjectType( - id++, - "EnemyTypeBoxYellow", - 355, - "Enemy Type Box (Yellow)" - ); - ObjectType.EnemyTypeBoxBlue = new ObjectType( - id++, - "EnemyTypeBoxBlue", - 356, - "Enemy Type Box (Blue)" - ); - ObjectType.EmptyTypeBoxBlue = new ObjectType( - id++, - "EmptyTypeBoxBlue", - 357, - "Empty Type Box (Blue)" - ); - ObjectType.DestructableRock = new ObjectType( - id++, - "DestructableRock", - 358, - "Destructable Rock" - ); - ObjectType.PopupTrapsTechs = new ObjectType( - id++, - "PopupTrapsTechs", - 359, - "Popup Traps (techs)" - ); - ObjectType.FlyingWhiteBird = new ObjectType(id++, "FlyingWhiteBird", 368, "Flying White Bird"); - ObjectType.Tower = new ObjectType(id++, "Tower", 369, "Tower"); - ObjectType.FloatingRocks = new ObjectType(id++, "FloatingRocks", 370, "Floating Rocks"); - ObjectType.FloatingSoul = new ObjectType(id++, "FloatingSoul", 371, "Floating Soul"); - ObjectType.Butterfly = new ObjectType(id++, "Butterfly", 372, "Butterfly"); - ObjectType.LobbyGameMenu = new ObjectType(id++, "LobbyGameMenu", 384, "Lobby Game menu"); - ObjectType.LobbyWarpObject = new ObjectType(id++, "LobbyWarpObject", 385, "Lobby Warp Object"); - ObjectType.Lobby1EventObjectDefaultTree = new ObjectType( - id++, - "Lobby1EventObjectDefaultTree", - 386, - "Lobby 1 Event Object (Default Tree)" - ); - ObjectType.UnknownItem387 = new ObjectType(id++, "UnknownItem387", 387, "Unknown Item (387)"); - ObjectType.UnknownItem388 = new ObjectType(id++, "UnknownItem388", 388, "Unknown Item (388)"); - ObjectType.UnknownItem389 = new ObjectType(id++, "UnknownItem389", 389, "Unknown Item (389)"); - ObjectType.LobbyEventObjectStaticPumpkin = new ObjectType( - id++, - "LobbyEventObjectStaticPumpkin", - 390, - "Lobby Event Object (Static Pumpkin)" - ); - ObjectType.LobbyEventObject3ChristmasWindows = new ObjectType( - id++, - "LobbyEventObject3ChristmasWindows", - 391, - "Lobby Event Object (3 Christmas Windows)" - ); - ObjectType.LobbyEventObjectRedAndWhiteCurtain = new ObjectType( - id++, - "LobbyEventObjectRedAndWhiteCurtain", - 392, - "Lobby Event Object (Red and White Curtain)" - ); - ObjectType.UnknownItem393 = new ObjectType(id++, "UnknownItem393", 393, "Unknown Item (393)"); - ObjectType.UnknownItem394 = new ObjectType(id++, "UnknownItem394", 394, "Unknown Item (394)"); - ObjectType.LobbyFishTank = new ObjectType(id++, "LobbyFishTank", 395, "Lobby Fish Tank"); - ObjectType.LobbyEventObjectButterflies = new ObjectType( - id++, - "LobbyEventObjectButterflies", - 396, - "Lobby Event Object (Butterflies)" - ); - ObjectType.UnknownItem400 = new ObjectType(id++, "UnknownItem400", 400, "Unknown Item (400)"); - ObjectType.GreyWallLow = new ObjectType(id++, "GreyWallLow", 401, "grey wall low"); - ObjectType.SpaceshipDoor = new ObjectType(id++, "SpaceshipDoor", 402, "Spaceship Door"); - ObjectType.GreyWallHigh = new ObjectType(id++, "GreyWallHigh", 403, "grey wall high"); - ObjectType.TempleNormalDoor = new ObjectType( - id++, - "TempleNormalDoor", - 416, - "Temple Normal Door" - ); - ObjectType.BreakableWallWallButUnbreakable = new ObjectType( - id++, - "BreakableWallWallButUnbreakable", - 417, - '"breakable wall wall, but unbreakable"' - ); - ObjectType.BrokenCilinderAndRubble = new ObjectType( - id++, - "BrokenCilinderAndRubble", - 418, - "Broken cilinder and rubble" - ); - ObjectType.ThreeBrokenWallPiecesOnFloor = new ObjectType( - id++, - "ThreeBrokenWallPiecesOnFloor", - 419, - "3 broken wall pieces on floor" - ); - ObjectType.HighBrickCilinder = new ObjectType( - id++, - "HighBrickCilinder", - 420, - "high brick cilinder" - ); - ObjectType.LyingCilinder = new ObjectType(id++, "LyingCilinder", 421, "lying cilinder"); - ObjectType.BrickConeWithFlatTop = new ObjectType( - id++, - "BrickConeWithFlatTop", - 422, - "brick cone with flat top" - ); - ObjectType.BreakableTempleWall = new ObjectType( - id++, - "BreakableTempleWall", - 423, - "breakable temple wall" - ); - ObjectType.TempleMapDetect = new ObjectType(id++, "TempleMapDetect", 424, "Temple Map Detect"); - ObjectType.SmallBrownBrickRisingBridge = new ObjectType( - id++, - "SmallBrownBrickRisingBridge", - 425, - "small brown brick rising bridge" - ); - ObjectType.LongRisingBridgeWithPinkHighEdges = new ObjectType( - id++, - "LongRisingBridgeWithPinkHighEdges", - 426, - "long rising bridge (with pink high edges)" - ); - ObjectType.FourSwitchTempleDoor = new ObjectType( - id++, - "FourSwitchTempleDoor", - 427, - "4 switch temple door" - ); - ObjectType.FourButtonSpaceshipDoor = new ObjectType( - id++, - "FourButtonSpaceshipDoor", - 448, - "4 button spaceship door" - ); - ObjectType.ItemBoxCca = new ObjectType(id++, "ItemBoxCca", 512, "item box cca"); - ObjectType.TeleporterEp2 = new ObjectType(id++, "TeleporterEp2", 513, "Teleporter (Ep 2)"); - ObjectType.CCADoor = new ObjectType(id++, "CCADoor", 514, "CCA Door"); - ObjectType.SpecialBoxCCA = new ObjectType(id++, "SpecialBoxCCA", 515, "Special Box CCA"); - ObjectType.BigCCADoor = new ObjectType(id++, "BigCCADoor", 516, "Big CCA Door"); - ObjectType.BigCCADoorSwitch = new ObjectType( - id++, - "BigCCADoorSwitch", - 517, - "Big CCA Door Switch" - ); - ObjectType.LittleRock = new ObjectType(id++, "LittleRock", 518, "Little Rock"); - ObjectType.Little3StoneWall = new ObjectType( - id++, - "Little3StoneWall", - 519, - "Little 3 Stone Wall" - ); - ObjectType.Medium3StoneWall = new ObjectType( - id++, - "Medium3StoneWall", - 520, - "Medium 3 stone wall" - ); - ObjectType.SpiderPlant = new ObjectType(id++, "SpiderPlant", 521, "Spider Plant"); - ObjectType.CCAAreaTeleporter = new ObjectType( - id++, - "CCAAreaTeleporter", - 522, - "CCA Area Teleporter" - ); - ObjectType.UnknownItem523 = new ObjectType(id++, "UnknownItem523", 523, "Unknown Item (523)"); - ObjectType.WhiteBird = new ObjectType(id++, "WhiteBird", 524, "White Bird"); - ObjectType.OrangeBird = new ObjectType(id++, "OrangeBird", 525, "Orange Bird"); - ObjectType.Saw = new ObjectType(id++, "Saw", 527, "Saw"); - ObjectType.LaserDetect = new ObjectType(id++, "LaserDetect", 528, "Laser Detect"); - ObjectType.UnknownItem529 = new ObjectType(id++, "UnknownItem529", 529, "Unknown Item (529)"); - ObjectType.UnknownItem530 = new ObjectType(id++, "UnknownItem530", 530, "Unknown Item (530)"); - ObjectType.Seagull = new ObjectType(id++, "Seagull", 531, "Seagull"); - ObjectType.Fish = new ObjectType(id++, "Fish", 544, "Fish"); - ObjectType.SeabedDoorWithBlueEdges = new ObjectType( - id++, - "SeabedDoorWithBlueEdges", - 545, - "Seabed Door (with blue edges)" - ); - ObjectType.SeabedDoorAlwaysOpenNonTriggerable = new ObjectType( - id++, - "SeabedDoorAlwaysOpenNonTriggerable", - 546, - "Seabed door (always open, non-triggerable)" - ); - ObjectType.LittleCryotube = new ObjectType(id++, "LittleCryotube", 547, "Little Cryotube"); - ObjectType.WideGlassWallBreakable = new ObjectType( - id++, - "WideGlassWallBreakable", - 548, - "Wide Glass Wall (breakable)" - ); - ObjectType.BlueFloatingRobot = new ObjectType( - id++, - "BlueFloatingRobot", - 549, - "Blue floating robot" - ); - ObjectType.RedFloatingRobot = new ObjectType( - id++, - "RedFloatingRobot", - 550, - "Red floating robot" - ); - ObjectType.Dolphin = new ObjectType(id++, "Dolphin", 551, "Dolphin"); - ObjectType.CaptureTrap = new ObjectType(id++, "CaptureTrap", 552, "Capture Trap"); - ObjectType.VRLink = new ObjectType(id++, "VRLink", 553, "VR link"); - ObjectType.UnknownItem576 = new ObjectType(id++, "UnknownItem576", 576, "Unknown Item (576)"); - ObjectType.WarpInBarbaRayRoom = new ObjectType( - id++, - "WarpInBarbaRayRoom", - 640, - "Warp in Barba Ray Room" - ); - ObjectType.UnknownItem672 = new ObjectType(id++, "UnknownItem672", 672, "Unknown Item (672)"); - ObjectType.GeeNest = new ObjectType(id++, "GeeNest", 688, "Gee Nest"); - ObjectType.LabComputerConsole = new ObjectType( - id++, - "LabComputerConsole", - 689, - "Lab Computer Console" - ); - ObjectType.LabComputerConsoleGreenScreen = new ObjectType( - id++, - "LabComputerConsoleGreenScreen", - 690, - "Lab Computer Console (Green Screen)" - ); - ObjectType.ChairYelllowPillow = new ObjectType( - id++, - "ChairYelllowPillow", - 691, - "Chair, Yelllow Pillow" - ); - ObjectType.OrangeWallWithHoleInMiddle = new ObjectType( - id++, - "OrangeWallWithHoleInMiddle", - 692, - "orange wall with hole in middle" - ); - ObjectType.GreyWallWithHoleInMiddle = new ObjectType( - id++, - "GreyWallWithHoleInMiddle", - 693, - "grey wall with hole in middle" - ); - ObjectType.LongTable = new ObjectType(id++, "LongTable", 694, "long table"); - ObjectType.GBAStation = new ObjectType(id++, "GBAStation", 695, "GBA Station"); - ObjectType.TalkLinkToSupport = new ObjectType( - id++, - "TalkLinkToSupport", - 696, - "Talk (link to support)" - ); - ObjectType.InstaWarp = new ObjectType(id++, "InstaWarp", 697, "insta-warp"); - ObjectType.LabInvisibleObject = new ObjectType( - id++, - "LabInvisibleObject", - 698, - "Lab Invisible Object" - ); - ObjectType.LabGlassWindowDoor = new ObjectType( - id++, - "LabGlassWindowDoor", - 699, - "Lab Glass window Door" - ); - ObjectType.UnknownItem700 = new ObjectType(id++, "UnknownItem700", 700, "Unknown Item (700)"); - ObjectType.LabCelingWarp = new ObjectType(id++, "LabCelingWarp", 701, "Lab Celing Warp"); - ObjectType.Ep4LightSource = new ObjectType(id++, "Ep4LightSource", 768, "Ep4 Light Source"); - ObjectType.Cacti = new ObjectType(id++, "Cacti", 769, "cacti"); - ObjectType.BigBrownRock = new ObjectType(id++, "BigBrownRock", 770, "Big Brown Rock"); - ObjectType.BreakableBrownRock = new ObjectType( - id++, - "BreakableBrownRock", - 771, - "Breakable Brown Rock" - ); - ObjectType.UnknownItem832 = new ObjectType(id++, "UnknownItem832", 832, "Unknown Item (832)"); - ObjectType.UnknownItem833 = new ObjectType(id++, "UnknownItem833", 833, "Unknown Item (833)"); - ObjectType.PoisonPlant = new ObjectType(id++, "PoisonPlant", 896, "Poison Plant"); - ObjectType.UnknownItem897 = new ObjectType(id++, "UnknownItem897", 897, "Unknown Item (897)"); - ObjectType.UnknownItem898 = new ObjectType(id++, "UnknownItem898", 898, "Unknown Item (898)"); - ObjectType.OozingDesertPlant = new ObjectType( - id++, - "OozingDesertPlant", - 899, - "Oozing Desert Plant" - ); - ObjectType.UnknownItem901 = new ObjectType(id++, "UnknownItem901", 901, "Unknown Item (901)"); - ObjectType.BigBlackRocks = new ObjectType(id++, "BigBlackRocks", 902, "big black rocks"); - ObjectType.UnknownItem903 = new ObjectType(id++, "UnknownItem903", 903, "Unknown Item (903)"); - ObjectType.UnknownItem904 = new ObjectType(id++, "UnknownItem904", 904, "Unknown Item (904)"); - ObjectType.UnknownItem905 = new ObjectType(id++, "UnknownItem905", 905, "Unknown Item (905)"); - ObjectType.UnknownItem906 = new ObjectType(id++, "UnknownItem906", 906, "Unknown Item (906)"); - ObjectType.FallingRock = new ObjectType(id++, "FallingRock", 907, "Falling Rock"); - ObjectType.DesertPlantHasCollision = new ObjectType( - id++, - "DesertPlantHasCollision", - 908, - "Desert Plant (has collision)" - ); - ObjectType.DesertFixedTypeBoxBreakableCrystals = new ObjectType( - id++, - "DesertFixedTypeBoxBreakableCrystals", - 909, - "Desert Fixed Type Box (Breakable Crystals)" - ); - ObjectType.UnknownItem910 = new ObjectType(id++, "UnknownItem910", 910, "Unknown Item (910)"); - ObjectType.BeeHive = new ObjectType(id++, "BeeHive", 911, "Bee Hive"); - ObjectType.UnknownItem912 = new ObjectType(id++, "UnknownItem912", 912, "Unknown Item (912)"); - ObjectType.Heat = new ObjectType(id++, "Heat", 913, "Heat"); - ObjectType.TopOfSaintMillionEgg = new ObjectType( - id++, - "TopOfSaintMillionEgg", - 960, - "Top of saint million egg" - ); - ObjectType.UnknownItem961 = new ObjectType(id++, "UnknownItem961", 961, "Unknown Item (961)"); -})(); diff --git a/src/domain/index.ts b/src/domain/index.ts index 570e51e2..672321b5 100644 --- a/src/domain/index.ts +++ b/src/domain/index.ts @@ -1,15 +1,15 @@ -import { action, computed, observable } from "mobx"; +import { action, computed, IObservableArray, observable } from "mobx"; import { DatUnknown } from "../data_formats/parsing/quest/dat"; +import { EntityType } from "../data_formats/parsing/quest/entities"; +import { check_episode, Episode } from "../data_formats/parsing/quest/Episode"; import { Vec3 } from "../data_formats/vector"; import { enum_values } from "../enums"; import { Segment } from "../scripting/instructions"; import { ItemType } from "./items"; -import { NpcType } from "./NpcType"; -import { ObjectType } from "./ObjectType"; +import { ObjectType } from "../data_formats/parsing/quest/object_types"; +import { NpcType } from "../data_formats/parsing/quest/npc_types"; export * from "./items"; -export * from "./NpcType"; -export * from "./ObjectType"; export const RARE_ENEMY_PROB = 1 / 512; export const KONDRIEU_PROB = 1 / 10; @@ -20,20 +20,6 @@ export enum Server { export const Servers: Server[] = enum_values(Server); -export enum Episode { - I = 1, - II = 2, - IV = 4, -} - -export const Episodes: Episode[] = enum_values(Episode); - -export function check_episode(episode: Episode): void { - if (Episode[episode] == undefined) { - throw new Error(`Invalid episode ${episode}.`); - } -} - export enum SectionId { Viridia, Greenill, @@ -69,7 +55,7 @@ export class Section { if (!Number.isInteger(id) || id < -1) throw new Error(`Expected id to be an integer greater than or equal to -1, got ${id}.`); if (!position) throw new Error("position is required."); - if (typeof y_axis_rotation !== "number") throw new Error("y_axis_rotation is required."); + if (!Number.isFinite(y_axis_rotation)) throw new Error("y_axis_rotation is required."); this.id = id; this.position = position; @@ -79,7 +65,7 @@ export class Section { } } -export class Quest { +export class ObservableQuest { @observable private _id!: number; get id(): number { @@ -145,9 +131,12 @@ export class Quest { readonly episode: Episode; - @observable readonly area_variants: AreaVariant[]; - @observable readonly objects: QuestObject[]; - @observable readonly npcs: QuestNpc[]; + /** + * One variant per area. + */ + @observable readonly area_variants: ObservableAreaVariant[]; + @observable readonly objects: ObservableQuestObject[]; + @observable readonly npcs: ObservableQuestNpc[]; /** * (Partial) raw DAT data that can't be parsed yet by Phantasmal. */ @@ -162,17 +151,17 @@ export class Quest { short_description: string, long_description: string, episode: Episode, - area_variants: AreaVariant[], - objects: QuestObject[], - npcs: QuestNpc[], + area_variants: ObservableAreaVariant[], + objects: ObservableQuestObject[], + npcs: ObservableQuestNpc[], dat_unknowns: DatUnknown[], object_code: Segment[], - shop_items: number[] + shop_items: number[], ) { check_episode(episode); if (!area_variants) throw new Error("area_variants is required."); - if (!objects || !(objects instanceof Array)) throw new Error("objs is required."); - if (!npcs || !(npcs instanceof Array)) throw new Error("npcs is required."); + if (!Array.isArray(objects)) throw new Error("objs is required."); + if (!Array.isArray(npcs)) throw new Error("npcs is required."); if (!dat_unknowns) throw new Error("dat_unknowns is required."); if (!object_code) throw new Error("object_code is required."); if (!shop_items) throw new Error("shop_items is required."); @@ -192,21 +181,15 @@ export class Quest { } } -export interface EntityType { - readonly id: number; - readonly code: string; - readonly name: string; -} - /** - * Abstract class from which QuestNpc and QuestObject derive. + * Abstract class from which ObservableQuestNpc and ObservableQuestObject derive. */ -export abstract class QuestEntity { +export abstract class ObservableQuestEntity { readonly type: Type; @observable area_id: number; - private _section_id: number; + private readonly _section_id: number; @computed get section_id(): number { return this.section ? this.section.id : this._section_id; @@ -260,15 +243,15 @@ export abstract class QuestEntity { } } - constructor( + protected constructor( type: Type, area_id: number, section_id: number, position: Vec3, rotation: Vec3, - scale: Vec3 + scale: Vec3, ) { - if (!type) throw new Error("type is required."); + if (type == undefined) throw new Error("type is required."); if (!Number.isInteger(area_id) || area_id < 0) throw new Error(`Expected area_id to be a non-negative integer, got ${area_id}.`); if (!Number.isInteger(section_id) || section_id < 0) @@ -292,7 +275,7 @@ export abstract class QuestEntity { } } -export class QuestObject extends QuestEntity { +export class ObservableQuestObject extends ObservableQuestEntity { @observable type: ObjectType; /** * Data of which the purpose hasn't been discovered yet. @@ -306,7 +289,7 @@ export class QuestObject extends QuestEntity { position: Vec3, rotation: Vec3, scale: Vec3, - unknown: number[][] + unknown: number[][], ) { super(type, area_id, section_id, position, rotation, scale); @@ -315,7 +298,7 @@ export class QuestObject extends QuestEntity { } } -export class QuestNpc extends QuestEntity { +export class ObservableQuestNpc extends ObservableQuestEntity { @observable type: NpcType; pso_type_id: number; pso_skin: number; @@ -333,7 +316,7 @@ export class QuestNpc extends QuestEntity { position: Vec3, rotation: Vec3, scale: Vec3, - unknown: number[][] + unknown: number[][], ) { super(type, area_id, section_id, position, rotation, scale); @@ -344,13 +327,16 @@ export class QuestNpc extends QuestEntity { } } -export class Area { - id: number; - name: string; - order: number; - area_variants: AreaVariant[]; +export class ObservableArea { + /** + * Matches the PSO ID. + */ + readonly id: number; + readonly name: string; + readonly order: number; + readonly area_variants: ObservableAreaVariant[]; - constructor(id: number, name: string, order: number, area_variants: AreaVariant[]) { + constructor(id: number, name: string, order: number, area_variants: ObservableAreaVariant[]) { if (!Number.isInteger(id) || id < 0) throw new Error(`Expected id to be a non-negative integer, got ${id}.`); if (!name) throw new Error("name is required."); @@ -363,12 +349,17 @@ export class Area { } } -export class AreaVariant { - @observable.shallow sections: Section[] = []; +export class ObservableAreaVariant { + readonly id: number; + readonly area: ObservableArea; + @observable.shallow readonly sections: IObservableArray
= observable.array(); - constructor(public id: number, public area: Area) { + constructor(id: number, area: ObservableArea) { if (!Number.isInteger(id) || id < 0) throw new Error(`Expected id to be a non-negative integer, got ${id}.`); + + this.id = id; + this.area = area; } } @@ -387,7 +378,7 @@ export class EnemyDrop implements ItemDrop { readonly npc_type: NpcType, readonly item_type: ItemType, readonly anything_rate: number, - readonly rare_rate: number + readonly rare_rate: number, ) { this.rate = anything_rate * rare_rate; } @@ -429,10 +420,10 @@ export class HuntMethod { export class SimpleQuest { constructor( - public readonly id: number, - public readonly name: string, - public readonly episode: Episode, - public readonly enemy_counts: Map + readonly id: number, + readonly name: string, + readonly episode: Episode, + readonly enemy_counts: Map, ) { if (!id) throw new Error("id is required."); if (!name) throw new Error("name is required."); @@ -442,13 +433,13 @@ export class SimpleQuest { export class PlayerModel { constructor( - public readonly name: string, - public readonly head_style_count: number, - public readonly hair_styles_count: number, - public readonly hair_styles_with_accessory: Set + readonly name: string, + readonly head_style_count: number, + readonly hair_styles_count: number, + readonly hair_styles_with_accessory: Set, ) {} } export class PlayerAnimation { - constructor(public readonly id: number, public readonly name: string) {} + constructor(readonly id: number, readonly name: string) {} } diff --git a/src/loading/areas.ts b/src/loading/areas.ts index dbe45796..64d78b26 100644 --- a/src/loading/areas.ts +++ b/src/loading/areas.ts @@ -1,5 +1,5 @@ import { Object3D } from "three"; -import { Endianness } from "../data_formats"; +import { Endianness } from "../data_formats/Endianness"; import { ArrayBufferCursor } from "../data_formats/cursor/ArrayBufferCursor"; import { parse_area_collision_geometry } from "../data_formats/parsing/area_collision_geometry"; import { parse_area_geometry } from "../data_formats/parsing/area_geometry"; @@ -20,46 +20,46 @@ const collision_geometry_cache = new LoadingCache>(); export async function load_area_sections( episode: number, area_id: number, - area_variant: number + area_variant: number, ): Promise { return render_geometry_cache.get_or_set(`${episode}-${area_id}-${area_variant}`, () => - load_area_sections_and_render_geometry(episode, area_id, area_variant) + load_area_sections_and_render_geometry(episode, area_id, area_variant), ).sections; } export async function load_area_render_geometry( episode: number, area_id: number, - area_variant: number + area_variant: number, ): Promise { return render_geometry_cache.get_or_set(`${episode}-${area_id}-${area_variant}`, () => - load_area_sections_and_render_geometry(episode, area_id, area_variant) + load_area_sections_and_render_geometry(episode, area_id, area_variant), ).geometry; } export async function load_area_collision_geometry( episode: number, area_id: number, - area_variant: number + area_variant: number, ): Promise { return collision_geometry_cache.get_or_set(`${episode}-${area_id}-${area_variant}`, () => get_area_asset(episode, area_id, area_variant, "collision").then(buffer => area_collision_geometry_to_object_3d( - parse_area_collision_geometry(new ArrayBufferCursor(buffer, Endianness.Little)) - ) - ) + parse_area_collision_geometry(new ArrayBufferCursor(buffer, Endianness.Little)), + ), + ), ); } function load_area_sections_and_render_geometry( episode: number, area_id: number, - area_variant: number + area_variant: number, ): { geometry: Promise; sections: Promise } { const promise = get_area_asset(episode, area_id, area_variant, "render").then(buffer => area_geometry_to_sections_and_object_3d( - parse_area_geometry(new ArrayBufferCursor(buffer, Endianness.Little)) - ) + parse_area_geometry(new ArrayBufferCursor(buffer, Endianness.Little)), + ), ); return { @@ -127,7 +127,7 @@ async function get_area_asset( episode: number, area_id: number, area_variant: number, - type: "render" | "collision" + type: "render" | "collision", ): Promise { const base_url = area_version_to_base_url(episode, area_id, area_variant); const suffix = type === "render" ? "n.rel" : "c.rel"; @@ -153,7 +153,7 @@ function area_version_to_base_url(episode: number, area_id: number, area_variant return `/maps/map_${base_name}${variant}`; } else { throw new Error( - `Unknown variant ${area_variant} of area ${area_id} in episode ${episode}.` + `Unknown variant ${area_variant} of area ${area_id} in episode ${episode}.`, ); } } else { diff --git a/src/loading/entities.ts b/src/loading/entities.ts index 91918eda..e2a3fdc9 100644 --- a/src/loading/entities.ts +++ b/src/loading/entities.ts @@ -1,14 +1,15 @@ import { Texture, CylinderBufferGeometry, BufferGeometry } from "three"; -import { ObjectType, NpcType } from "../domain"; import Logger from "js-logger"; import { LoadingCache } from "./LoadingCache"; -import { Endianness } from "../data_formats"; +import { Endianness } from "../data_formats/Endianness"; import { ArrayBufferCursor } from "../data_formats/cursor/ArrayBufferCursor"; import { ninja_object_to_buffer_geometry } from "../rendering/conversion/ninja_geometry"; import { parse_nj, parse_xj } from "../data_formats/parsing/ninja"; import { parse_xvm } from "../data_formats/parsing/ninja/texture"; import { xvm_to_textures } from "../rendering/conversion/ninja_textures"; import { load_array_buffer } from "./load_array_buffer"; +import { object_data, ObjectType } from "../data_formats/parsing/quest/object_types"; +import { NpcType } from "../data_formats/parsing/quest/npc_types"; const logger = Logger.get("loading/entities"); @@ -16,13 +17,13 @@ const DEFAULT_ENTITY = new CylinderBufferGeometry(3, 3, 20); DEFAULT_ENTITY.translate(0, 10, 0); const DEFAULT_ENTITY_PROMISE: Promise = new Promise(resolve => - resolve(DEFAULT_ENTITY) + resolve(DEFAULT_ENTITY), ); const DEFAULT_ENTITY_TEX: Texture[] = []; const DEFAULT_ENTITY_TEX_PROMISE: Promise = new Promise(resolve => - resolve(DEFAULT_ENTITY_TEX) + resolve(DEFAULT_ENTITY_TEX), ); const npc_cache = new LoadingCache>(); @@ -69,11 +70,11 @@ export async function load_npc_geometry(npc_type: NpcType): Promise { const xvm = parse_xvm(cursor); return xvm_to_textures(xvm); } catch (e) { - logger.warn(`Couldn't load texture file for ${npc_type.code}.`, e); + logger.warn(`Couldn't load texture file for ${NpcType[npc_type]}.`, e); return DEFAULT_ENTITY_TEX; } }); @@ -103,11 +104,11 @@ export async function load_object_geometry(object_type: ObjectType): Promise { const url = npc_type_to_url(npc_type, type); const data = await load_array_buffer(url); @@ -138,7 +139,7 @@ export async function load_npc_data( export async function load_object_data( object_type: ObjectType, - type: AssetType + type: AssetType, ): Promise<{ url: string; data: ArrayBuffer }> { const url = object_type_to_url(object_type, type); const data = await load_array_buffer(url); @@ -154,7 +155,7 @@ function npc_type_to_url(npc_type: NpcType, type: AssetType): string { switch (npc_type) { // The dubswitch model is in XJ format. case NpcType.Dubswitch: - return `/npcs/${npc_type.code}.${type === AssetType.Geometry ? "xj" : "xvm"}`; + return `/npcs/${NpcType[npc_type]}.${type === AssetType.Geometry ? "xj" : "xvm"}`; // Episode II VR Temple @@ -203,7 +204,7 @@ function npc_type_to_url(npc_type: NpcType, type: AssetType): string { return npc_type_to_url(NpcType.ChaosSorcerer, type); default: - return `/npcs/${npc_type.code}.${type === AssetType.Geometry ? "nj" : "xvm"}`; + return `/npcs/${NpcType[npc_type]}.${type === AssetType.Geometry ? "nj" : "xvm"}`; } } @@ -226,12 +227,12 @@ function object_type_to_url(object_type: ObjectType, type: AssetType): string { case ObjectType.FallingRock: case ObjectType.DesertFixedTypeBoxBreakableCrystals: case ObjectType.BeeHive: - return `/objects/${object_type.pso_id}.nj`; + return `/objects/${object_data(object_type).pso_id}.nj`; default: - return `/objects/${object_type.pso_id}.xj`; + return `/objects/${object_data(object_type).pso_id}.xj`; } } else { - return `/objects/${object_type.pso_id}.xvm`; + return `/objects/${object_data(object_type).pso_id}.xvm`; } } diff --git a/src/rendering/QuestEntityControls.ts b/src/rendering/QuestEntityControls.ts index 2ccf8e8f..2c0d4b44 100644 --- a/src/rendering/QuestEntityControls.ts +++ b/src/rendering/QuestEntityControls.ts @@ -1,16 +1,16 @@ import { autorun } from "mobx"; import { Intersection, Mesh, MeshLambertMaterial, Plane, Raycaster, Vector2, Vector3 } from "three"; import { Vec3 } from "../data_formats/vector"; -import { QuestEntity, QuestNpc, Section } from "../domain"; import { quest_editor_store } from "../stores/QuestEditorStore"; import { AreaUserData } from "./conversion/areas"; import { ColorType, EntityUserData, NPC_COLORS, OBJECT_COLORS } from "./conversion/entities"; import { QuestRenderer } from "./QuestRenderer"; +import { ObservableQuestEntity, ObservableQuestNpc, Section } from "../domain"; const DOWN_VECTOR = new Vector3(0, -1, 0); type Highlighted = { - entity: QuestEntity; + entity: ObservableQuestEntity; mesh: Mesh; }; @@ -22,7 +22,7 @@ type Pick = { }; type PickResult = Pick & { - entity: QuestEntity; + entity: ObservableQuestEntity; mesh: Mesh; }; @@ -203,7 +203,7 @@ export class QuestEntityControls { private translate_vertically( selection: Highlighted, pick: Pick, - pointer_position: Vector2 + pointer_position: Vector2, ): void { // We intersect with a plane that's oriented toward the camera and that's coplanar with the point where the entity was grabbed. this.raycaster.setFromCamera(pointer_position, this.renderer.camera); @@ -212,7 +212,7 @@ export class QuestEntityControls { const negative_world_dir = this.renderer.camera.getWorldDirection(new Vector3()).negate(); const plane = new Plane().setFromNormalAndCoplanarPoint( new Vector3(negative_world_dir.x, 0, negative_world_dir.z).normalize(), - selection.mesh.position.sub(pick.grab_offset) + selection.mesh.position.sub(pick.grab_offset), ); const intersection_point = new Vector3(); @@ -225,7 +225,7 @@ export class QuestEntityControls { selection.entity.position = new Vec3( selection.entity.position.x, y, - selection.entity.position.z + selection.entity.position.z, ); } } @@ -233,7 +233,7 @@ export class QuestEntityControls { private translate_horizontally( selection: Highlighted, pick: Pick, - pointer_position: Vector2 + pointer_position: Vector2, ): void { // Cast ray adjusted for dragging entities. const { intersection, section } = this.pick_terrain(pointer_position, pick); @@ -243,9 +243,9 @@ export class QuestEntityControls { new Vec3( intersection.point.x, intersection.point.y + pick.drag_y, - intersection.point.z + intersection.point.z, ), - section + section, ); } else { // If the cursor is not over any terrain, we translate the entity accross the horizontal plane in which the entity's origin lies. @@ -254,7 +254,7 @@ export class QuestEntityControls { // ray.origin.add(data.dragAdjust); const plane = new Plane( new Vector3(0, 1, 0), - -selection.entity.position.y + pick.grab_offset.y + -selection.entity.position.y + pick.grab_offset.y, ); const intersection_point = new Vector3(); @@ -262,7 +262,7 @@ export class QuestEntityControls { selection.entity.position = new Vec3( intersection_point.x + pick.grab_offset.x, selection.entity.position.y, - intersection_point.z + pick.grab_offset.z + intersection_point.z + pick.grab_offset.z, ); } } @@ -274,7 +274,7 @@ export class QuestEntityControls { quest_editor_store.push_entity_move_action( entity, this.pick.initial_position, - entity.position + entity.position, ); } @@ -288,7 +288,7 @@ export class QuestEntityControls { // Find the nearest object and NPC under the pointer. this.raycaster.setFromCamera(pointer_position, this.renderer.camera); const [intersection] = this.raycaster.intersectObjects( - this.renderer.entity_models.children + this.renderer.entity_models.children, ); if (!intersection) { @@ -307,7 +307,7 @@ export class QuestEntityControls { this.raycaster.set(intersection.object.position, DOWN_VECTOR); const [collision_geom_intersection] = this.raycaster.intersectObjects( this.renderer.collision_geometry.children, - true + true, ); if (collision_geom_intersection) { @@ -330,7 +330,7 @@ export class QuestEntityControls { */ private pick_terrain( pointer_pos: Vector2, - data: Pick + data: Pick, ): { intersection?: Intersection; section?: Section; @@ -339,7 +339,7 @@ export class QuestEntityControls { this.raycaster.ray.origin.add(data.drag_adjust); const intersections = this.raycaster.intersectObjects( this.renderer.collision_geometry.children, - true + true, ); // Don't allow entities to be placed on very steep terrain. @@ -359,7 +359,7 @@ export class QuestEntityControls { } function set_color({ entity, mesh }: Highlighted, type: ColorType): void { - const color = entity instanceof QuestNpc ? NPC_COLORS[type] : OBJECT_COLORS[type]; + const color = entity instanceof ObservableQuestNpc ? NPC_COLORS[type] : OBJECT_COLORS[type]; if (mesh) { if (Array.isArray(mesh.material)) { diff --git a/src/rendering/QuestModelManager.ts b/src/rendering/QuestModelManager.ts index cf7917dc..c519de02 100644 --- a/src/rendering/QuestModelManager.ts +++ b/src/rendering/QuestModelManager.ts @@ -1,7 +1,6 @@ import Logger from "js-logger"; import { autorun, IReactionDisposer } from "mobx"; import { Mesh, Object3D, Vector3, Raycaster, Intersection } from "three"; -import { Area, Quest, QuestEntity } from "../domain"; import { load_area_collision_geometry, load_area_render_geometry } from "../loading/areas"; import { load_npc_geometry, @@ -12,6 +11,7 @@ import { import { create_npc_mesh, create_object_mesh } from "./conversion/entities"; import { QuestRenderer } from "./QuestRenderer"; import { AreaUserData } from "./conversion/areas"; +import { ObservableArea, ObservableQuest, ObservableQuestEntity } from "../domain"; const logger = Logger.get("rendering/QuestModelManager"); @@ -20,13 +20,13 @@ const CAMERA_LOOKAT = new Vector3(0, 0, 0); const DUMMY_OBJECT = new Object3D(); export class QuestModelManager { - private quest?: Quest; - private area?: Area; + private quest?: ObservableQuest; + private area?: ObservableArea; private entity_reaction_disposers: IReactionDisposer[] = []; constructor(private renderer: QuestRenderer) {} - async load_models(quest?: Quest, area?: Area): Promise { + async load_models(quest?: ObservableQuest, area?: ObservableArea): Promise { if (this.quest === quest && this.area === area) { return; } @@ -47,13 +47,13 @@ export class QuestModelManager { const collision_geometry = await load_area_collision_geometry( episode, area_id, - variant_id + variant_id, ); const render_geometry = await load_area_render_geometry( episode, area_id, - variant_id + variant_id, ); this.add_sections_to_collision_geometry(collision_geometry, render_geometry); @@ -106,7 +106,7 @@ export class QuestModelManager { private add_sections_to_collision_geometry( collision_geom: Object3D, - render_geom: Object3D + render_geom: Object3D, ): void { const raycaster = new Raycaster(); const origin = new Vector3(); @@ -145,7 +145,7 @@ export class QuestModelManager { } } - private update_entity_geometry(entity: QuestEntity, model: Mesh): void { + private update_entity_geometry(entity: ObservableQuestEntity, model: Mesh): void { this.renderer.add_entity_model(model); this.entity_reaction_disposers.push( @@ -155,7 +155,7 @@ export class QuestModelManager { const rot = entity.rotation; model.rotation.set(rot.x, rot.y, rot.z); this.renderer.schedule_render(); - }) + }), ); } diff --git a/src/rendering/QuestRenderer.ts b/src/rendering/QuestRenderer.ts index 4ae8ac6c..1f4b981f 100644 --- a/src/rendering/QuestRenderer.ts +++ b/src/rendering/QuestRenderer.ts @@ -1,11 +1,11 @@ import { autorun } from "mobx"; import { Mesh, Object3D, PerspectiveCamera, Group } from "three"; -import { QuestEntity } from "../domain"; import { quest_editor_store } from "../stores/QuestEditorStore"; import { QuestEntityControls } from "./QuestEntityControls"; import { QuestModelManager } from "./QuestModelManager"; import { Renderer } from "./Renderer"; import { EntityUserData } from "./conversion/entities"; +import { ObservableQuestEntity } from "../domain"; let renderer: QuestRenderer | undefined; @@ -58,7 +58,7 @@ export class QuestRenderer extends Renderer { return this._entity_models; } - private entity_to_mesh = new Map(); + private entity_to_mesh = new Map(); private entity_controls: QuestEntityControls; constructor() { @@ -69,7 +69,7 @@ export class QuestRenderer extends Renderer { autorun(() => { model_manager.load_models( quest_editor_store.current_quest, - quest_editor_store.current_area + quest_editor_store.current_area, ); }); @@ -103,7 +103,7 @@ export class QuestRenderer extends Renderer { } } - get_entity_mesh(entity: QuestEntity): Mesh | undefined { + get_entity_mesh(entity: ObservableQuestEntity): Mesh | undefined { return this.entity_to_mesh.get(entity); } } diff --git a/src/rendering/conversion/entities.ts b/src/rendering/conversion/entities.ts index 7ce35d1a..a575d97a 100644 --- a/src/rendering/conversion/entities.ts +++ b/src/rendering/conversion/entities.ts @@ -1,6 +1,8 @@ import { BufferGeometry, DoubleSide, Mesh, MeshLambertMaterial, Texture } from "three"; -import { QuestEntity, QuestNpc, QuestObject } from "../../domain"; import { create_mesh } from "./create_mesh"; +import { ObservableQuestEntity, ObservableQuestNpc, ObservableQuestObject } from "../../domain"; +import { ObjectType } from "../../data_formats/parsing/quest/object_types"; +import { NpcType } from "../../data_formats/parsing/quest/npc_types"; export enum ColorType { Normal, @@ -19,31 +21,37 @@ NPC_COLORS[ColorType.Hovered] = 0xff3f5f; NPC_COLORS[ColorType.Selected] = 0xff0054; export type EntityUserData = { - entity: QuestEntity; + entity: ObservableQuestEntity; }; export function create_object_mesh( - object: QuestObject, + object: ObservableQuestObject, geometry: BufferGeometry, - textures: Texture[] + textures: Texture[], ): Mesh { - return create(object, geometry, textures, OBJECT_COLORS[ColorType.Normal], object.type.name); + return create( + object, + geometry, + textures, + OBJECT_COLORS[ColorType.Normal], + ObjectType[object.type], + ); } export function create_npc_mesh( - npc: QuestNpc, + npc: ObservableQuestNpc, geometry: BufferGeometry, - textures: Texture[] + textures: Texture[], ): Mesh { - return create(npc, geometry, textures, NPC_COLORS[ColorType.Normal], npc.type.code); + return create(npc, geometry, textures, NPC_COLORS[ColorType.Normal], NpcType[npc.type]); } function create( - entity: QuestEntity, + entity: ObservableQuestEntity, geometry: BufferGeometry, textures: Texture[], color: number, - name: string + name: string, ): Mesh { const default_material = new MeshLambertMaterial({ color, @@ -59,10 +67,10 @@ function create( map: tex, side: DoubleSide, alphaTest: 0.5, - }) + }), ) : default_material, - default_material + default_material, ); mesh.name = name; diff --git a/src/scripting/disassembly.test.ts b/src/scripting/disassembly.test.ts index 0c4c0897..4e0b7d81 100644 --- a/src/scripting/disassembly.test.ts +++ b/src/scripting/disassembly.test.ts @@ -1,5 +1,5 @@ import { readFileSync } from "fs"; -import { Endianness } from "../data_formats"; +import { Endianness } from "../data_formats/Endianness"; import { prs_decompress } from "../data_formats/compression/prs/decompress"; import { ArrayBufferCursor } from "../data_formats/cursor/ArrayBufferCursor"; import { BufferCursor } from "../data_formats/cursor/BufferCursor"; diff --git a/src/stores/AreaStore.ts b/src/stores/AreaStore.ts index 872e265f..d0619ce4 100644 --- a/src/stores/AreaStore.ts +++ b/src/stores/AreaStore.ts @@ -1,90 +1,48 @@ -import { Area, AreaVariant, Section, Episode } from "../domain"; +import { ObservableArea, ObservableAreaVariant, Section } from "../domain"; import { load_area_sections } from "../loading/areas"; - -function area(id: number, name: string, order: number, variants: number): Area { - const area = new Area(id, name, order, []); - const varis = Array(variants) - .fill(null) - .map((_, i) => new AreaVariant(i, area)); - area.area_variants.splice(0, 0, ...varis); - return area; -} +import { Episode, EPISODES } from "../data_formats/parsing/quest/Episode"; +import { get_areas_for_episode } from "../data_formats/parsing/quest/areas"; class AreaStore { - private areas: Area[][] = []; + private readonly areas: ObservableArea[][] = []; constructor() { - // The IDs match the PSO IDs for areas. - let order = 0; - this.areas[Episode.I] = [ - area(0, "Pioneer II", order++, 1), - area(1, "Forest 1", order++, 1), - area(2, "Forest 2", order++, 1), - area(11, "Under the Dome", order++, 1), - area(3, "Cave 1", order++, 6), - area(4, "Cave 2", order++, 5), - area(5, "Cave 3", order++, 6), - area(12, "Underground Channel", order++, 1), - area(6, "Mine 1", order++, 6), - area(7, "Mine 2", order++, 6), - area(13, "Monitor Room", order++, 1), - area(8, "Ruins 1", order++, 5), - area(9, "Ruins 2", order++, 5), - area(10, "Ruins 3", order++, 5), - area(14, "Dark Falz", order++, 1), - area(15, "BA Ruins", order++, 3), - area(16, "BA Spaceship", order++, 3), - area(17, "Lobby", order++, 15), - ]; - order = 0; - this.areas[Episode.II] = [ - area(0, "Lab", order++, 1), - area(1, "VR Temple Alpha", order++, 3), - area(2, "VR Temple Beta", order++, 3), - area(14, "VR Temple Final", order++, 1), - area(3, "VR Spaceship Alpha", order++, 3), - area(4, "VR Spaceship Beta", order++, 3), - area(15, "VR Spaceship Final", order++, 1), - area(5, "Central Control Area", order++, 1), - area(6, "Jungle Area East", order++, 1), - area(7, "Jungle Area North", order++, 1), - area(8, "Mountain Area", order++, 3), - area(9, "Seaside Area", order++, 1), - area(12, "Cliffs of Gal Da Val", order++, 1), - area(10, "Seabed Upper Levels", order++, 3), - area(11, "Seabed Lower Levels", order++, 3), - area(13, "Test Subject Disposal Area", order++, 1), - area(16, "Seaside Area at Night", order++, 1), - area(17, "Control Tower", order++, 5), - ]; - order = 0; - this.areas[Episode.IV] = [ - area(0, "Pioneer II (Ep. IV)", order++, 1), - area(1, "Crater Route 1", order++, 1), - area(2, "Crater Route 2", order++, 1), - area(3, "Crater Route 3", order++, 1), - area(4, "Crater Route 4", order++, 1), - area(5, "Crater Interior", order++, 1), - area(6, "Subterranean Desert 1", order++, 3), - area(7, "Subterranean Desert 2", order++, 3), - area(8, "Subterranean Desert 3", order++, 3), - area(9, "Meteor Impact Site", order++, 1), - ]; + for (const episode of EPISODES) { + this.areas[episode] = get_areas_for_episode(episode).map(area => { + const observable_area = new ObservableArea(area.id, area.name, area.order, []); + + for (const variant of area.area_variants) { + observable_area.area_variants.push( + new ObservableAreaVariant(variant.id, observable_area), + ); + } + + return observable_area; + }); + } } - get_area = (episode: Episode, area_id: number): Area => { + get_areas_for_episode = (episode: Episode): ObservableArea[] => { + return this.areas[episode]; + }; + + get_area = (episode: Episode, area_id: number): ObservableArea => { const area = this.areas[episode].find(a => a.id === area_id); if (!area) throw new Error(`Area id ${area_id} for episode ${episode} is invalid.`); return area; }; - get_variant = (episode: Episode, area_id: number, variant_id: number): AreaVariant => { + get_variant = ( + episode: Episode, + area_id: number, + variant_id: number, + ): ObservableAreaVariant => { const area = this.get_area(episode, area_id); const area_variant = area.area_variants[variant_id]; if (!area_variant) throw new Error( - `Area variant id ${variant_id} for area ${area_id} of episode ${episode} is invalid.` + `Area variant id ${variant_id} for area ${area_id} of episode ${episode} is invalid.`, ); return area_variant; @@ -93,7 +51,7 @@ class AreaStore { get_area_sections = ( episode: Episode, area_id: number, - variant_id: number + variant_id: number, ): Promise => { return load_area_sections(episode, area_id, variant_id); }; diff --git a/src/stores/HuntMethodStore.ts b/src/stores/HuntMethodStore.ts index b49a242f..0540d145 100644 --- a/src/stores/HuntMethodStore.ts +++ b/src/stores/HuntMethodStore.ts @@ -1,23 +1,24 @@ import Logger from "js-logger"; import { autorun, IReactionDisposer, observable } from "mobx"; -import { HuntMethod, NpcType, Server, SimpleQuest } from "../domain"; +import { HuntMethod, Server, SimpleQuest } from "../domain"; import { QuestDto } from "../dto"; import { Loadable } from "../Loadable"; import { hunt_method_persister } from "../persistence/HuntMethodPersister"; import { ServerMap } from "./ServerMap"; +import { NpcType } from "../data_formats/parsing/quest/npc_types"; const logger = Logger.get("stores/HuntMethodStore"); class HuntMethodStore { @observable methods: ServerMap> = new ServerMap( - server => new Loadable([], () => this.load_hunt_methods(server)) + server => new Loadable([], () => this.load_hunt_methods(server)), ); private storage_disposer?: IReactionDisposer; private async load_hunt_methods(server: Server): Promise { const response = await fetch( - `${process.env.PUBLIC_URL}/quests.${Server[server].toLowerCase()}.json` + `${process.env.PUBLIC_URL}/quests.${Server[server].toLowerCase()}.json`, ); const quests = (await response.json()) as QuestDto[]; const methods = new Array(); @@ -27,7 +28,7 @@ class HuntMethodStore { const enemy_counts = new Map(); for (const [code, count] of Object.entries(quest.enemyCounts)) { - const npc_type = NpcType.by_code(code); + const npc_type = (NpcType as any)[code]; if (!npc_type) { logger.error(`No NpcType found for code ${code}.`); @@ -59,8 +60,8 @@ class HuntMethodStore { `q${quest.id}`, quest.name, new SimpleQuest(quest.id, quest.name, quest.episode, enemy_counts), - /^\d-\d.*/.test(quest.name) ? 0.75 : total_count > 400 ? 0.75 : 0.5 - ) + /^\d-\d.*/.test(quest.name) ? 0.75 : total_count > 400 ? 0.75 : 0.5, + ), ); } diff --git a/src/stores/HuntOptimizerStore.ts b/src/stores/HuntOptimizerStore.ts index dfa6dbc6..1e6cf9c4 100644 --- a/src/stores/HuntOptimizerStore.ts +++ b/src/stores/HuntOptimizerStore.ts @@ -3,11 +3,9 @@ import { autorun, computed, IObservableArray, observable } from "mobx"; import { Difficulties, Difficulty, - Episode, HuntMethod, ItemType, KONDRIEU_PROB, - NpcType, RARE_ENEMY_PROB, SectionId, SectionIds, @@ -17,6 +15,8 @@ import { application_store } from "./ApplicationStore"; import { hunt_method_store } from "./HuntMethodStore"; import { item_drop_stores } from "./ItemDropStore"; import { item_type_stores } from "./ItemTypeStore"; +import { Episode } from "../data_formats/parsing/quest/Episode"; +import { npc_data, NpcType } from "../data_formats/parsing/quest/npc_types"; export class WantedItem { @observable readonly item_type: ItemType; @@ -55,7 +55,7 @@ export class OptimalMethod { method_episode: Episode, method_time: number, runs: number, - item_counts: Map + item_counts: Map, ) { this.difficulty = difficulty; this.section_ids = section_ids; @@ -79,7 +79,7 @@ class HuntOptimizerStore { @computed get huntable_item_types(): ItemType[] { const item_drop_store = item_drop_stores.current.value; return item_type_stores.current.value.item_types.filter( - i => item_drop_store.enemy_drops.get_drops_for_item_type(i.id).length + i => item_drop_store.enemy_drops.get_drops_for_item_type(i.id).length, ); } @@ -100,7 +100,7 @@ class HuntOptimizerStore { // Initialize this set before awaiting data, so user changes don't affect this optimization // run from this point on. const wanted_items = new Set( - this.wanted_items.filter(w => w.amount > 0).map(w => w.item_type) + this.wanted_items.filter(w => w.amount > 0).map(w => w.item_type), ); const methods = await hunt_method_store.methods.current.promise; @@ -136,11 +136,12 @@ class HuntOptimizerStore { // Counts include rare enemies, so they are fractional. const counts = new Map(); - for (const [enemy, count] of method.enemy_counts.entries()) { - const old_count = counts.get(enemy) || 0; + for (const [enemy_type, count] of method.enemy_counts.entries()) { + const old_count = counts.get(enemy_type) || 0; + const enemy = npc_data(enemy_type); if (enemy.rare_type == null) { - counts.set(enemy, old_count + count); + counts.set(enemy_type, old_count + count); } else { let rate, rare_rate; @@ -152,10 +153,10 @@ class HuntOptimizerStore { rare_rate = RARE_ENEMY_PROB; } - counts.set(enemy, old_count + count * rate); + counts.set(enemy_type, old_count + count * rate); counts.set( enemy.rare_type, - (counts.get(enemy.rare_type) || 0) + count * rare_rate + (counts.get(enemy.rare_type) || 0) + count * rare_rate, ); } } @@ -216,7 +217,7 @@ class HuntOptimizerStore { difficulty, section_id, method, - split_pan_arms + split_pan_arms, ); variables[name] = variable; variable_details.set(name, { @@ -312,8 +313,8 @@ class HuntOptimizerStore { method.episode, method.time, runs, - items - ) + items, + ), ); } } @@ -325,7 +326,7 @@ class HuntOptimizerStore { difficulty: Difficulty, section_id: SectionId, method: HuntMethod, - split_pan_arms: boolean + split_pan_arms: boolean, ): string { let name = `${difficulty}\t${section_id}\t${method.id}`; if (split_pan_arms) name += "\tspa"; @@ -334,13 +335,13 @@ class HuntOptimizerStore { private initialize_persistence = async () => { this.wanted_items.replace( - await hunt_optimizer_persister.load_wanted_items(application_store.current_server) + await hunt_optimizer_persister.load_wanted_items(application_store.current_server), ); autorun(() => { hunt_optimizer_persister.persist_wanted_items( application_store.current_server, - this.wanted_items + this.wanted_items, ); }); }; diff --git a/src/stores/ItemDropStore.ts b/src/stores/ItemDropStore.ts index 6f1b6e79..ee5487b6 100644 --- a/src/stores/ItemDropStore.ts +++ b/src/stores/ItemDropStore.ts @@ -1,54 +1,47 @@ import { observable } from "mobx"; -import { - Difficulties, - Difficulty, - EnemyDrop, - NpcType, - SectionId, - SectionIds, - Server, -} from "../domain"; -import { NpcTypes } from "../domain/NpcType"; +import { Difficulties, Difficulty, EnemyDrop, SectionId, SectionIds, Server } from "../domain"; import { EnemyDropDto } from "../dto"; import { Loadable } from "../Loadable"; import { item_type_stores } from "./ItemTypeStore"; import { ServerMap } from "./ServerMap"; import Logger from "js-logger"; +import { NpcType } from "../data_formats/parsing/quest/npc_types"; const logger = Logger.get("stores/ItemDropStore"); export class EnemyDropTable { // Mapping of difficulties to section IDs to NpcTypes to EnemyDrops. - private table: EnemyDrop[] = new Array( - Difficulties.length * SectionIds.length * NpcTypes.length - ); + private table: EnemyDrop[][][] = []; // Mapping of ItemType ids to EnemyDrops. private item_type_to_drops: EnemyDrop[][] = []; + constructor() { + for (let i = 0; i < Difficulties.length; i++) { + const diff_array: EnemyDrop[][] = []; + this.table.push(diff_array); + + for (let j = 0; j < SectionIds.length; j++) { + diff_array.push([]); + } + } + } + get_drop( difficulty: Difficulty, section_id: SectionId, - npc_type: NpcType + npc_type: NpcType, ): EnemyDrop | undefined { - return this.table[ - difficulty * SectionIds.length * NpcTypes.length + - section_id * NpcTypes.length + - npc_type.id - ]; + return this.table[difficulty][section_id][npc_type]; } set_drop( difficulty: Difficulty, section_id: SectionId, npc_type: NpcType, - drop: EnemyDrop + drop: EnemyDrop, ): void { - this.table[ - difficulty * SectionIds.length * NpcTypes.length + - section_id * NpcTypes.length + - npc_type.id - ] = drop; + this.table[difficulty][section_id][npc_type] = drop; let drops = this.item_type_to_drops[drop.item_type.id]; @@ -77,18 +70,18 @@ export const item_drop_stores: ServerMap> = new ServerMa async function load(store: ItemDropStore, server: Server): Promise { const item_type_store = await item_type_stores.current.promise; const response = await fetch( - `${process.env.PUBLIC_URL}/enemyDrops.${Server[server].toLowerCase()}.json` + `${process.env.PUBLIC_URL}/enemyDrops.${Server[server].toLowerCase()}.json`, ); const data: EnemyDropDto[] = await response.json(); const drops = new EnemyDropTable(); for (const drop_dto of data) { - const npc_type = NpcType.by_code(drop_dto.enemy); + const npc_type = (NpcType as any)[drop_dto.enemy]; if (!npc_type) { logger.warn( - `Couldn't determine NpcType of episode ${drop_dto.episode} ${drop_dto.enemy}.` + `Couldn't determine NpcType of episode ${drop_dto.episode} ${drop_dto.enemy}.`, ); continue; } @@ -118,8 +111,8 @@ async function load(store: ItemDropStore, server: Server): Promise {}, () => {}); @observable current_quest_filename?: string; - @observable current_quest?: Quest; - @observable current_area?: Area; + @observable current_quest?: ObservableQuest; + @observable current_area?: ObservableArea; - @observable selected_entity?: QuestEntity; + @observable selected_entity?: ObservableQuestEntity; @observable save_dialog_filename?: string; @observable save_dialog_open: boolean = false; constructor() { application_store.on_global_keyup("quest_editor", "Ctrl-Z", () => { - // Let Monaco handle its own keybindings. + // Let Monaco handle its own key bindings. if (undo_manager.current !== this.script_undo) { undo_manager.undo(); } }); application_store.on_global_keyup("quest_editor", "Ctrl-Shift-Z", () => { - // Let Monaco handle its own keybindings. + // Let Monaco handle its own key bindings. if (undo_manager.current !== this.script_undo) { undo_manager.redo(); } @@ -50,7 +59,7 @@ class QuestEditorStore { }; @action - set_selected_entity = (entity?: QuestEntity) => { + set_selected_entity = (entity?: ObservableQuestEntity) => { if (entity) { this.set_current_area_id(entity.area_id); } @@ -65,10 +74,7 @@ class QuestEditorStore { if (area_id == null) { this.current_area = undefined; } else if (this.current_quest) { - const area_variant = this.current_quest.area_variants.find( - variant => variant.area.id === area_id - ); - this.current_area = area_variant && area_variant.area; + this.current_area = area_store.get_area(this.current_quest.episode, area_id); } }; @@ -82,7 +88,50 @@ class QuestEditorStore { try { const buffer = yield read_file(file); const quest = parse_quest(new ArrayBufferCursor(buffer, Endianness.Little)); - this.set_quest(quest, filename); + this.set_quest( + quest && + new ObservableQuest( + quest.id, + quest.language, + quest.name, + quest.short_description, + quest.long_description, + quest.episode, + quest.area_variants.map(variant => + area_store.get_variant(quest.episode, variant.area.id, variant.id), + ), + quest.objects.map( + obj => + new ObservableQuestObject( + obj.type, + obj.area_id, + obj.section_id, + obj.position, + obj.rotation, + obj.scale, + obj.unknown, + ), + ), + quest.npcs.map( + npc => + new ObservableQuestNpc( + npc.type, + npc.pso_type_id, + npc.pso_skin, + npc.area_id, + npc.section_id, + npc.position, + npc.rotation, + npc.scale, + npc.unknown, + ), + ), + quest.dat_unknowns, + quest.object_code, + quest.shop_items, + ), + filename, + ); } catch (e) { logger.error("Couldn't read file.", e); } @@ -110,8 +159,44 @@ class QuestEditorStore { }; save_current_quest_to_file = (file_name: string) => { - if (this.current_quest) { - const buffer = write_quest_qst(this.current_quest, file_name); + const quest = this.current_quest; + + if (quest) { + const buffer = write_quest_qst( + { + id: quest.id, + language: quest.language, + name: quest.name, + short_description: quest.short_description, + long_description: quest.long_description, + episode: quest.episode, + objects: quest.objects.map(obj => ({ + type: obj.type, + area_id: obj.area_id, + section_id: obj.section_id, + position: obj.section_position, + rotation: obj.rotation, + scale: obj.scale, + unknown: obj.unknown, + })), + npcs: quest.npcs.map(npc => ({ + type: npc.type, + area_id: npc.area_id, + section_id: npc.section_id, + position: npc.section_position, + rotation: npc.rotation, + scale: npc.scale, + unknown: npc.unknown, + pso_type_id: npc.pso_type_id, + pso_skin: npc.pso_skin, + })), + dat_unknowns: quest.dat_unknowns, + object_code: quest.object_code, + shop_items: quest.shop_items, + area_variants: quest.area_variants, + }, + file_name, + ); if (!file_name.endsWith(".qst")) { file_name += ".qst"; @@ -130,9 +215,13 @@ class QuestEditorStore { }; @action - push_entity_move_action = (entity: QuestEntity, initial_position: Vec3, new_position: Vec3) => { + push_entity_move_action = ( + entity: ObservableQuestEntity, + initial_position: Vec3, + new_position: Vec3, + ) => { this.undo.push_action( - `Move ${entity.type.name}`, + `Move ${entity_data(entity.type).name}`, () => { entity.position = initial_position; quest_editor_store.set_selected_entity(entity); @@ -140,15 +229,15 @@ class QuestEditorStore { () => { entity.position = new_position; quest_editor_store.set_selected_entity(entity); - } + }, ); }; @action private set_quest = flow(function* set_quest( this: QuestEditorStore, - quest?: Quest, - filename?: string + quest?: ObservableQuest, + filename?: string, ) { this.current_quest_filename = filename; @@ -158,8 +247,8 @@ class QuestEditorStore { this.selected_entity = undefined; this.current_quest = quest; - if (quest && quest.area_variants.length) { - this.current_area = quest.area_variants[0].area; + if (quest) { + this.current_area = area_store.get_area(quest.episode, 0); } else { this.current_area = undefined; } @@ -170,13 +259,13 @@ class QuestEditorStore { const sections = yield area_store.get_area_sections( quest.episode, variant.area.id, - variant.id + variant.id, ); - variant.sections = sections; + variant.sections.replace(sections); for (const object of quest.objects.filter(o => o.area_id === variant.area.id)) { try { - this.set_section_on_visible_quest_entity(object, sections); + this.set_section_on_quest_entity(object, sections); } catch (e) { logger.error(e); } @@ -184,7 +273,7 @@ class QuestEditorStore { for (const npc of quest.npcs.filter(npc => npc.area_id === variant.area.id)) { try { - this.set_section_on_visible_quest_entity(npc, sections); + this.set_section_on_quest_entity(npc, sections); } catch (e) { logger.error(e); } @@ -196,7 +285,7 @@ class QuestEditorStore { } }); - private set_section_on_visible_quest_entity = (entity: QuestEntity, sections: Section[]) => { + private set_section_on_quest_entity = (entity: ObservableQuestEntity, sections: Section[]) => { let { x, y, z } = entity.position; const section = sections.find(s => s.id === entity.section_id); diff --git a/src/stores/TextureViewerStore.ts b/src/stores/TextureViewerStore.ts index 1de228a5..7de07501 100644 --- a/src/stores/TextureViewerStore.ts +++ b/src/stores/TextureViewerStore.ts @@ -2,7 +2,7 @@ import { observable } from "mobx"; import { Xvm, parse_xvm } from "../data_formats/parsing/ninja/texture"; import { ArrayBufferCursor } from "../data_formats/cursor/ArrayBufferCursor"; import { read_file } from "../read_file"; -import { Endianness } from "../data_formats"; +import { Endianness } from "../data_formats/Endianness"; import Logger from "js-logger"; const logger = Logger.get("stores/TextureViewerStore"); diff --git a/src/stores/quest_creation.ts b/src/stores/quest_creation.ts index 29f02b67..8a86b4bc 100644 --- a/src/stores/quest_creation.ts +++ b/src/stores/quest_creation.ts @@ -1,13 +1,17 @@ import { Vec3 } from "../data_formats/vector"; -import { Episode, NpcType, ObjectType, Quest, QuestNpc, QuestObject } from "../domain"; +import { ObservableQuest, ObservableQuestNpc, ObservableQuestObject } from "../domain"; import { area_store } from "./AreaStore"; import { SegmentType, Instruction } from "../scripting/instructions"; import { Opcode } from "../scripting/opcodes"; +import { Episode } from "../data_formats/parsing/quest/Episode"; +import { ObjectType } from "../data_formats/parsing/quest/object_types"; +import { NpcType } from "../data_formats/parsing/quest/npc_types"; -export function create_new_quest(episode: Episode): Quest { +export function create_new_quest(episode: Episode): ObservableQuest { if (episode === Episode.II) throw new Error("Episode II not yet supported."); + if (episode === Episode.IV) throw new Error("Episode IV not yet supported."); - return new Quest( + return new ObservableQuest( 0, 0, "Untitled", @@ -72,13 +76,13 @@ export function create_new_quest(episode: Episode): Quest { ], }, ], - [] + [], ); } -function create_default_objects(): QuestObject[] { +function create_default_objects(): ObservableQuestObject[] { return [ - new QuestObject( + new ObservableQuestObject( ObjectType.MenuActivation, 0, 10, @@ -89,9 +93,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 0, 0, 0, 0, 0, 64, 0, 0], [0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 75, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.MenuActivation, 0, 10, @@ -102,9 +106,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 1, 0, 0, 0, 1, 64, 0, 0], [0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 76, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.MenuActivation, 0, 10, @@ -115,9 +119,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 2, 0, 0, 0, 2, 64, 0, 0], [0, 0], [2, 0, 0, 0, 0, 0, 1, 0, 10, 0, 0, 0, 192, 76, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.MenuActivation, 0, 10, @@ -128,9 +132,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 3, 0, 0, 0, 3, 64, 0, 0], [0, 0], [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 77, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.PlayerSet, 0, 10, @@ -141,9 +145,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 4, 0, 0, 0, 4, 64, 0, 0], [0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.PlayerSet, 0, 10, @@ -154,9 +158,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 5, 0, 0, 0, 5, 64, 0, 0], [0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 78, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.PlayerSet, 0, 10, @@ -167,9 +171,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 6, 0, 0, 0, 6, 64, 0, 0], [0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 79, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.PlayerSet, 0, 10, @@ -180,9 +184,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 7, 0, 0, 0, 7, 64, 0, 0], [0, 0], [0, 0, 1, 0, 10, 0, 0, 0, 0, 0, 0, 0, 224, 79, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.MainRagolTeleporter, 0, 10, @@ -193,9 +197,9 @@ function create_default_objects(): QuestObject[] { [0, 0, 87, 7, 0, 0, 88, 71, 0, 0], [0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 128, 250, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.PrincipalWarp, 0, 10, @@ -206,9 +210,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 9, 0, 0, 0, 9, 64, 0, 0], [0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 176, 81, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.MenuActivation, 0, 10, @@ -219,9 +223,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 10, 0, 0, 0, 10, 64, 0, 0], [1, 0], [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 82, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.MenuActivation, 0, 10, @@ -232,9 +236,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 11, 0, 0, 0, 11, 64, 0, 0], [0, 0], [5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 83, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.PrincipalWarp, 0, 10, @@ -245,9 +249,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 12, 0, 0, 0, 12, 64, 0, 0], [0, 0], [0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 84, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.TelepipeLocation, 0, 10, @@ -258,9 +262,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 13, 0, 0, 0, 13, 64, 0, 0], [0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 85, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.TelepipeLocation, 0, 10, @@ -271,9 +275,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 14, 0, 0, 0, 14, 64, 0, 0], [0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 86, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.TelepipeLocation, 0, 10, @@ -284,9 +288,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 15, 0, 0, 0, 15, 64, 0, 0], [0, 0], [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 86, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.TelepipeLocation, 0, 10, @@ -297,9 +301,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 16, 0, 0, 0, 16, 64, 0, 0], [0, 0], [2, 0, 0, 0, 0, 0, 1, 0, 10, 0, 0, 0, 144, 87, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.MedicalCenterDoor, 0, 10, @@ -310,9 +314,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 17, 0, 0, 0, 17, 64, 0, 0], [0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 88, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.ShopDoor, 0, 10, @@ -323,9 +327,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 18, 0, 0, 0, 18, 64, 0, 0], [0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 89, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.MenuActivation, 0, 10, @@ -336,9 +340,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 19, 0, 0, 0, 19, 64, 0, 0], [0, 0], [6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 90, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.HuntersGuildDoor, 0, 10, @@ -349,9 +353,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 20, 0, 0, 0, 20, 64, 0, 0], [0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 90, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.TeleporterDoor, 0, 10, @@ -362,9 +366,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 21, 0, 0, 0, 21, 64, 0, 0], [0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 91, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.PlayerSet, 0, 10, @@ -375,9 +379,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 22, 0, 0, 0, 22, 64, 0, 0], [0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 92, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.PlayerSet, 0, 10, @@ -388,9 +392,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 23, 0, 0, 0, 23, 64, 0, 0], [0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 93, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.PlayerSet, 0, 10, @@ -401,9 +405,9 @@ function create_default_objects(): QuestObject[] { [2, 0, 24, 0, 0, 0, 24, 64, 0, 0], [0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 94, 251, 140], - ] + ], ), - new QuestObject( + new ObservableQuestObject( ObjectType.PlayerSet, 0, 10, @@ -414,14 +418,14 @@ function create_default_objects(): QuestObject[] { [2, 0, 25, 0, 0, 0, 25, 64, 0, 0], [0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 94, 251, 140], - ] + ], ), ]; } -function create_default_npcs(): QuestNpc[] { +function create_default_npcs(): ObservableQuestNpc[] { return [ - new QuestNpc( + new ObservableQuestNpc( NpcType.GuildLady, 29, 0, @@ -435,9 +439,9 @@ function create_default_npcs(): QuestNpc[] { [0, 0, 0, 0, 0, 0], [18, 192, 124, 68, 0, 128, 84, 68], [128, 238, 223, 176], - ] + ], ), - new QuestNpc( + new ObservableQuestNpc( NpcType.FemaleFat, 4, 1, @@ -451,9 +455,9 @@ function create_default_npcs(): QuestNpc[] { [0, 0, 0, 0, 0, 0], [18, 0, 126, 68, 6, 0, 200, 66], [128, 238, 232, 48], - ] + ], ), - new QuestNpc( + new ObservableQuestNpc( NpcType.MaleDwarf, 10, 1, @@ -467,9 +471,9 @@ function create_default_npcs(): QuestNpc[] { [0, 0, 0, 0, 0, 0], [18, 192, 125, 68, 6, 0, 180, 66], [128, 238, 236, 176], - ] + ], ), - new QuestNpc( + new ObservableQuestNpc( NpcType.RedSoldier, 26, 0, @@ -483,9 +487,9 @@ function create_default_npcs(): QuestNpc[] { [0, 0, 0, 0, 0, 0], [18, 0, 127, 68, 6, 0, 2, 67], [128, 238, 241, 48], - ] + ], ), - new QuestNpc( + new ObservableQuestNpc( NpcType.BlueSoldier, 25, 0, @@ -499,9 +503,9 @@ function create_default_npcs(): QuestNpc[] { [0, 0, 0, 0, 0, 0], [18, 192, 126, 68, 11, 0, 240, 66], [128, 238, 245, 176], - ] + ], ), - new QuestNpc( + new ObservableQuestNpc( NpcType.FemaleMacho, 5, 1, @@ -515,9 +519,9 @@ function create_default_npcs(): QuestNpc[] { [0, 0, 0, 0, 0, 0], [18, 128, 125, 68, 9, 0, 160, 66], [128, 238, 250, 48], - ] + ], ), - new QuestNpc( + new ObservableQuestNpc( NpcType.Scientist, 30, 1, @@ -531,9 +535,9 @@ function create_default_npcs(): QuestNpc[] { [0, 0, 0, 0, 0, 0], [18, 64, 125, 68, 8, 0, 140, 66], [128, 238, 254, 176], - ] + ], ), - new QuestNpc( + new ObservableQuestNpc( NpcType.MaleOld, 13, 1, @@ -547,9 +551,9 @@ function create_default_npcs(): QuestNpc[] { [0, 0, 0, 0, 0, 0], [18, 0, 125, 68, 15, 0, 112, 66], [128, 239, 3, 48], - ] + ], ), - new QuestNpc( + new ObservableQuestNpc( NpcType.GuildLady, 29, 0, @@ -563,9 +567,9 @@ function create_default_npcs(): QuestNpc[] { [0, 0, 0, 0, 0, 0], [18, 128, 124, 68, 0, 0, 82, 68], [128, 239, 100, 192], - ] + ], ), - new QuestNpc( + new ObservableQuestNpc( NpcType.Tekker, 28, 0, @@ -579,9 +583,9 @@ function create_default_npcs(): QuestNpc[] { [0, 0, 0, 0, 0, 0], [0, 64, 124, 68, 0, 128, 79, 68], [128, 239, 16, 176], - ] + ], ), - new QuestNpc( + new ObservableQuestNpc( NpcType.MaleMacho, 12, 0, @@ -595,9 +599,9 @@ function create_default_npcs(): QuestNpc[] { [0, 0, 0, 0, 0, 0], [0, 128, 123, 68, 0, 0, 72, 68], [128, 239, 21, 48], - ] + ], ), - new QuestNpc( + new ObservableQuestNpc( NpcType.FemaleMacho, 5, 0, @@ -611,9 +615,9 @@ function create_default_npcs(): QuestNpc[] { [0, 0, 0, 0, 0, 0], [0, 0, 124, 68, 0, 0, 77, 68], [128, 239, 25, 176], - ] + ], ), - new QuestNpc( + new ObservableQuestNpc( NpcType.MaleFat, 11, 0, @@ -627,9 +631,9 @@ function create_default_npcs(): QuestNpc[] { [0, 0, 0, 0, 0, 0], [18, 192, 123, 68, 0, 128, 74, 68], [128, 239, 30, 48], - ] + ], ), - new QuestNpc( + new ObservableQuestNpc( NpcType.FemaleTall, 7, 1, @@ -643,9 +647,9 @@ function create_default_npcs(): QuestNpc[] { [0, 0, 0, 0, 0, 0], [18, 64, 127, 68, 4, 0, 12, 67], [128, 239, 34, 176], - ] + ], ), - new QuestNpc( + new ObservableQuestNpc( NpcType.Nurse, 31, 0, @@ -659,9 +663,9 @@ function create_default_npcs(): QuestNpc[] { [0, 0, 0, 0, 0, 0], [0, 64, 126, 68, 0, 0, 87, 68], [128, 239, 39, 48], - ] + ], ), - new QuestNpc( + new ObservableQuestNpc( NpcType.Nurse, 31, 1, @@ -675,7 +679,7 @@ function create_default_npcs(): QuestNpc[] { [0, 0, 0, 0, 0, 0], [18, 128, 126, 68, 7, 0, 220, 66], [128, 239, 43, 176], - ] + ], ), ]; } diff --git a/src/ui/hunt_optimizer/MethodsComponent.tsx b/src/ui/hunt_optimizer/MethodsComponent.tsx index 66298e7e..2b659aa1 100644 --- a/src/ui/hunt_optimizer/MethodsComponent.tsx +++ b/src/ui/hunt_optimizer/MethodsComponent.tsx @@ -1,13 +1,14 @@ import { TimePicker } from "antd"; import { observer } from "mobx-react"; import moment, { Moment } from "moment"; -import React, { ReactNode, Component } from "react"; +import React, { Component, ReactNode } from "react"; import { AutoSizer, Index, SortDirection } from "react-virtualized"; -import { Episode, HuntMethod } from "../../domain"; -import { EnemyNpcTypes, NpcType } from "../../domain/NpcType"; import { hunt_method_store } from "../../stores/HuntMethodStore"; import { BigTable, Column, ColumnSort } from "../BigTable"; import styles from "./MethodsComponent.css"; +import { HuntMethod } from "../../domain"; +import { Episode } from "../../data_formats/parsing/quest/Episode"; +import { ENEMY_NPC_TYPES, npc_data, NpcType } from "../../data_formats/parsing/quest/npc_types"; @observer export class MethodsComponent extends Component { @@ -39,13 +40,13 @@ export class MethodsComponent extends Component { ]; // One column per enemy type. - for (const enemy of EnemyNpcTypes) { + for (const enemy_type of ENEMY_NPC_TYPES) { columns.push({ - key: enemy.code, - name: enemy.name, + key: NpcType[enemy_type], + name: npc_data(enemy_type).name, width: 75, cell_renderer: method => { - const count = method.enemy_counts.get(enemy); + const count = method.enemy_counts.get(enemy_type); return count == null ? "" : count.toString(); }, class_name: "number", @@ -97,7 +98,7 @@ export class MethodsComponent extends Component { } else if (column.key === "time") { cmp = a.time - b.time; } else if (column.key) { - const type = NpcType.by_code(column.key); + const type = (NpcType as any)[column.key]; if (type) { cmp = (a.enemy_counts.get(type) || 0) - (b.enemy_counts.get(type) || 0); diff --git a/src/ui/hunt_optimizer/OptimizationResultComponent.tsx b/src/ui/hunt_optimizer/OptimizationResultComponent.tsx index 83f0f822..0a077002 100644 --- a/src/ui/hunt_optimizer/OptimizationResultComponent.tsx +++ b/src/ui/hunt_optimizer/OptimizationResultComponent.tsx @@ -2,12 +2,13 @@ import { computed } from "mobx"; import { observer } from "mobx-react"; import React, { Component, ReactNode } from "react"; import { AutoSizer, Index } from "react-virtualized"; -import { Difficulty, Episode, SectionId } from "../../domain"; +import { Difficulty, SectionId } from "../../domain"; import { hunt_optimizer_store, OptimalMethod } from "../../stores/HuntOptimizerStore"; import { BigTable, Column } from "../BigTable"; import { SectionIdIcon } from "../SectionIdIcon"; import { hours_to_string } from "../time"; import styles from "./OptimizationResultComponent.css"; +import { Episode } from "../../data_formats/parsing/quest/Episode"; @observer export class OptimizationResultComponent extends Component { diff --git a/src/ui/quest_editor/EntityInfoComponent.tsx b/src/ui/quest_editor/EntityInfoComponent.tsx index 3542b4df..88c5d6d1 100644 --- a/src/ui/quest_editor/EntityInfoComponent.tsx +++ b/src/ui/quest_editor/EntityInfoComponent.tsx @@ -3,10 +3,11 @@ import { autorun, IReactionDisposer } from "mobx"; import { observer } from "mobx-react"; import React, { Component, PureComponent, ReactNode } from "react"; import { Vec3 } from "../../data_formats/vector"; -import { QuestEntity, QuestNpc } from "../../domain"; import { quest_editor_store } from "../../stores/QuestEditorStore"; import { DisabledTextComponent } from "../DisabledTextComponent"; import styles from "./EntityInfoComponent.css"; +import { ObservableQuestEntity, ObservableQuestNpc } from "../../domain"; +import { entity_data, entity_type_to_string } from "../../data_formats/parsing/quest/entities"; @observer export class EntityInfoComponent extends Component { @@ -21,8 +22,8 @@ export class EntityInfoComponent extends Component { - - + + @@ -56,7 +57,7 @@ export class EntityInfoComponent extends Component { } type CoordProps = { - entity: QuestEntity; + entity: ObservableQuestEntity; position_type: "position" | "section_position"; coord: "x" | "y" | "z"; }; @@ -117,9 +118,11 @@ class CoordInput extends Component a[0].id - b[0].id); + // Sort by canonical order. + const sorted_npc_counts = [...npc_counts].sort((a, b) => a[0] - b[0]); const npc_count_rows = sorted_npc_counts.map(([npc_type, count]) => { const extra = npc_type === NpcType.Canadine ? extra_canadines : 0; return ( - - + + ); diff --git a/src/ui/quest_editor/Toolbar.tsx b/src/ui/quest_editor/Toolbar.tsx index db5182a8..7a20dabb 100644 --- a/src/ui/quest_editor/Toolbar.tsx +++ b/src/ui/quest_editor/Toolbar.tsx @@ -1,20 +1,19 @@ import { Button, Dropdown, Form, Icon, Input, Menu, Modal, Select, Upload } from "antd"; import { ClickParam } from "antd/lib/menu"; import { UploadChangeParam, UploadFile } from "antd/lib/upload/interface"; +import { computed } from "mobx"; import { observer } from "mobx-react"; import React, { ChangeEvent, Component, ReactNode } from "react"; -import { Episode } from "../../domain"; +import { area_store } from "../../stores/AreaStore"; import { quest_editor_store } from "../../stores/QuestEditorStore"; import { undo_manager } from "../../undo"; import styles from "./Toolbar.css"; +import { Episode } from "../../data_formats/parsing/quest/Episode"; @observer export class Toolbar extends Component { render(): ReactNode { const quest = quest_editor_store.current_quest; - const areas = quest ? Array.from(quest.area_variants).map(a => a.area) : []; - const area = quest_editor_store.current_area; - const area_id = area && area.id; return (
@@ -67,18 +66,7 @@ export class Toolbar extends Component { > Redo - +
); @@ -103,6 +91,51 @@ export class Toolbar extends Component { } } +@observer +class AreaComponent extends Component { + @computed private get entities_per_area(): Map { + const quest = quest_editor_store.current_quest; + const map = new Map(); + + if (quest) { + for (const npc of quest.npcs) { + map.set(npc.area_id, (map.get(npc.area_id) || 0) + 1); + } + + for (const obj of quest.objects) { + map.set(obj.area_id, (map.get(obj.area_id) || 0) + 1); + } + } + + return map; + } + + render(): ReactNode { + const quest = quest_editor_store.current_quest; + const areas = quest ? area_store.get_areas_for_episode(quest.episode) : []; + const area = quest_editor_store.current_area; + + return ( + + ); + } +} + @observer class SaveQuestComponent extends Component { render(): ReactNode { @@ -137,7 +170,7 @@ class SaveQuestComponent extends Component { private ok(): void { quest_editor_store.save_current_quest_to_file( - quest_editor_store.save_dialog_filename || "untitled" + quest_editor_store.save_dialog_filename || "untitled", ); }
{entity instanceof QuestNpc ? "NPC" : "Object"}:{entity.type.name}{entity instanceof ObservableQuestNpc ? "NPC" : "Object"}:{entity_data(entity.type).name}
Section:
{npc_type.name}:
{npc_data(npc_type).name}: {count + extra}