Static data formats now conform to the rest of the project's code style.

This commit is contained in:
Daan Vanden Bosch 2020-01-01 16:05:23 +01:00
parent 050e0ffd57
commit 02708a0436
18 changed files with 43689 additions and 43642 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,6 @@
import cheerio from "cheerio";
import * as cheerio from "cheerio";
import { writeFileSync } from "fs";
import "isomorphic-fetch";
import Logger from "js-logger";
import fetch from "node-fetch";
import { ASSETS_DIR } from ".";
import { Difficulty, SectionId, SectionIds } from "../src/core/model";
import {
@ -10,8 +9,9 @@ import {
} from "../src/core/data_formats/parsing/quest/npc_types";
import { ItemTypeDto } from "../src/core/dto/ItemTypeDto";
import { BoxDropDto, EnemyDropDto } from "../src/hunt_optimizer/dto/drops";
import { LogManager } from "../src/core/Logger";
const logger = Logger.get("assets_generation/update_drops_ephinea");
const logger = LogManager.get("assets_generation/update_drops_ephinea");
export async function update_drops_from_website(item_types: ItemTypeDto[]): Promise<void> {
logger.info("Updating item drops.");
@ -27,7 +27,7 @@ export async function update_drops_from_website(item_types: ItemTypeDto[]): Prom
4,
);
writeFileSync(`${ASSETS_DIR}/enemyDrops.ephinea.json`, enemy_json);
writeFileSync(`${ASSETS_DIR}/enemy_drops.ephinea.json`, enemy_json);
const box_json = JSON.stringify(
[...normal.box_drops, ...hard.box_drops, ...vhard.box_drops, ...ultimate.box_drops],
@ -35,7 +35,7 @@ export async function update_drops_from_website(item_types: ItemTypeDto[]): Prom
4,
);
writeFileSync(`${ASSETS_DIR}/boxDrops.ephinea.json`, box_json);
writeFileSync(`${ASSETS_DIR}/box_drops.ephinea.json`, box_json);
logger.info("Done updating item drops.");
}
@ -136,9 +136,10 @@ async function download(
throw new Error(`Couldn't retrieve NpcType.`);
}
const title = $("font abbr", td)
.attr("title")
.replace("\r", "");
const title = ($("font abbr", td).attr("title") ?? "").replace(
"\r",
"",
);
const [
,
drop_rate_num,
@ -153,11 +154,11 @@ async function download(
data.enemy_drops.push({
difficulty: Difficulty[difficulty],
episode,
sectionId: SectionId[section_id],
section_id: SectionId[section_id],
enemy: NpcType[npc_type],
itemTypeId: item_type.id,
dropRate: drop_rate_num / drop_rate_denom,
rareRate: rare_rate_num / rare_rate_denom,
item_type_id: item_type.id,
drop_rate: drop_rate_num / drop_rate_denom,
rare_rate: rare_rate_num / rare_rate_denom,
});
data.items.add(item);

View File

@ -69,7 +69,6 @@ async function update(): Promise<void> {
* - Knight of Coral
* - Knight of Coral Advent
* - CAL's Clock Challenge
* - The Value of Money (quest3_e.dat, can't be parsed, luckily doesn't have enemies)
* Note: The MA4R quests use a random area variation per area from the ABC MA quests. E.g. MA4-1R will use a random caves 2 variation from MA4-1A, MA4-1B or MA4-1C. Same for mines 2 and ruins 2.
*/
function update_quests(): void {
@ -133,7 +132,7 @@ function process_quest(path: string, quests: QuestDto[]): void {
id: q.id,
name: q.name,
episode: q.episode,
enemyCounts: enemy_counts,
enemy_counts: enemy_counts,
});
} else {
logger.error(`Couldn't process ${path}.`);
@ -176,11 +175,11 @@ function update_items(item_names: string[]): ItemTypeDto[] {
class: "weapon",
id,
name: item_names[weapon.id],
minAtp: weapon.min_atp,
maxAtp: weapon.max_atp,
min_atp: weapon.min_atp,
max_atp: weapon.max_atp,
ata: weapon.ata,
maxGrind: weapon.max_grind,
requiredAtp: weapon.req_atp,
max_grind: weapon.max_grind,
required_atp: weapon.req_atp,
});
}
});
@ -193,16 +192,16 @@ function update_items(item_names: string[]): ItemTypeDto[] {
ids.add(id);
const stats = get_stat_boosts(item_pmt, armor.stat_boost);
stats.minEvp += armor.evp;
stats.minDfp += armor.dfp;
stats.min_evp += armor.evp;
stats.min_dfp += armor.dfp;
item_types.push({
class: "armor",
id,
name: item_names[armor.id],
...stats,
maxEvp: stats.minEvp + armor.evp_range,
maxDfp: stats.minDfp + armor.dfp_range,
max_evp: stats.min_evp + armor.evp_range,
max_dfp: stats.min_dfp + armor.dfp_range,
});
}
});
@ -214,16 +213,16 @@ function update_items(item_names: string[]): ItemTypeDto[] {
ids.add(id);
const stats = get_stat_boosts(item_pmt, shield.stat_boost);
stats.minEvp += shield.evp;
stats.minDfp += shield.dfp;
stats.min_evp += shield.evp;
stats.min_dfp += shield.dfp;
item_types.push({
class: "shield",
id,
name: item_names[shield.id],
...stats,
maxEvp: stats.minEvp + shield.evp_range,
maxDfp: stats.minDfp + shield.dfp_range,
max_evp: stats.min_evp + shield.evp_range,
max_dfp: stats.min_dfp + shield.dfp_range,
});
}
});
@ -256,7 +255,7 @@ function update_items(item_names: string[]): ItemTypeDto[] {
});
});
writeFileSync(`${ASSETS_DIR}/itemTypes.ephinea.json`, JSON.stringify(item_types, null, 4));
writeFileSync(`${ASSETS_DIR}/item_types.ephinea.json`, JSON.stringify(item_types, null, 4));
logger.info("Done updating item type data.");
return item_types;
@ -275,7 +274,7 @@ function update_drops(item_pt: ItemPt): void {
}
}
writeFileSync(`${ASSETS_DIR}/enemyDrops.ephinea.json`, JSON.stringify(enemy_drops, null, 4));
writeFileSync(`${ASSETS_DIR}/enemy_drops.ephinea.json`, JSON.stringify(enemy_drops, null, 4));
const box_drops = new Array<BoxDropDto>();
@ -287,7 +286,7 @@ function update_drops(item_pt: ItemPt): void {
}
}
writeFileSync(`${ASSETS_DIR}/boxDrops.ephinea.json`, JSON.stringify(box_drops, null, 4));
writeFileSync(`${ASSETS_DIR}/box_drops.ephinea.json`, JSON.stringify(box_drops, null, 4));
logger.info("Done updating drop data.");
}
@ -331,7 +330,7 @@ function load_item_pt(): ItemPt {
switch (npc) {
case NpcType.Dragon:
case NpcType.DeRolLe:
case NpcType.VolOptPart2:
case NpcType.VolOptPart1:
case NpcType.DarkFalz:
case NpcType.BarbaRay:
case NpcType.GolDragon:
@ -539,11 +538,11 @@ function load_enemy_drops(
drops.push({
difficulty: Difficulty[difficulty],
episode,
sectionId: SectionId[section_id],
section_id: SectionId[section_id],
enemy: NpcType[enemy],
itemTypeId: item_type_id,
dropRate: dar,
rareRate: rare_rate,
item_type_id: item_type_id,
drop_rate: dar,
rare_rate: rare_rate,
});
}
}
@ -583,10 +582,10 @@ function load_box_drops(
drops.push({
difficulty: Difficulty[difficulty],
episode,
sectionId: SectionId[section_id],
areaId: area_id,
itemTypeId: item_type_id,
dropRate: drop_rate,
section_id: SectionId[section_id],
area_id: area_id,
item_type_id: item_type_id,
drop_rate: drop_rate,
});
}
}
@ -605,8 +604,8 @@ function get_stat_boosts(
): {
atp: number;
ata: number;
minEvp: number;
minDfp: number;
min_evp: number;
min_dfp: number;
mst: number;
hp: number;
lck: number;
@ -683,7 +682,7 @@ function get_stat_boosts(
break;
}
return { atp, ata, minEvp: min_evp, minDfp: min_dfp, mst, hp, lck };
return { atp, ata, min_evp, min_dfp, mst, hp, lck };
}
function get_enemy_type(episode: Episode, index: number): NpcType | undefined {
@ -739,7 +738,7 @@ function get_enemy_type(episode: Episode, index: number): NpcType | undefined {
NpcType.Dragon,
NpcType.DeRolLe,
NpcType.VolOptPart2,
NpcType.VolOptPart1,
NpcType.DarkFalz,
undefined,

View File

@ -1,14 +1,14 @@
import { readFileSync, writeFileSync } from "fs";
import Logger from "js-logger";
import { ASSETS_DIR, RESOURCE_DIR, SRC_DIR } from ".";
import { BufferCursor } from "../src/core/data_formats/cursor/BufferCursor";
import { parse_rlc } from "../src/core/data_formats/parsing/rlc";
import YAML from "yaml";
import * as yaml from "yaml";
import { Endianness } from "../src/core/data_formats/Endianness";
import { LogLevel, LogManager } from "../src/core/Logger";
const logger = Logger.get("assets_generation/update_generic_data");
const logger = LogManager.get("assets_generation/update_generic_data");
Logger.useDefaults({ defaultLevel: Logger.TRACE });
LogManager.default_level = LogLevel.Trace;
const OPCODES_YML_FILE = `${RESOURCE_DIR}/scripting/opcodes.yml`;
const OPCODES_SRC_FILE = `${SRC_DIR}/quest_editor/scripting/opcodes.ts`;
@ -69,7 +69,7 @@ function update_opcodes(): void {
// Add generated code.
const yml = readFileSync(OPCODES_YML_FILE, { encoding: "UTF-8" });
const input = YAML.parse(yml);
const input = yaml.parse(yml);
const generated_lines: string[] = [];
let i = 0;

View File

@ -26,6 +26,7 @@
"@fortawesome/fontawesome-free": "^5.12.0",
"@types/cheerio": "^0.22.15",
"@types/jest": "^24.0.24",
"@types/node-fetch": "^2.5.4",
"@types/yaml": "^1.2.0",
"@typescript-eslint/eslint-plugin": "^2.12.0",
"@typescript-eslint/parser": "^2.12.0",
@ -44,6 +45,7 @@
"jest-canvas-mock": "^2.2.0",
"mini-css-extract-plugin": "^0.9.0",
"monaco-editor-webpack-plugin": "^1.8.1",
"node-fetch": "^2.6.0",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"prettier": "^1.19.1",
"terser-webpack-plugin": "^2.3.1",

View File

@ -279,8 +279,14 @@ function parse_events(cursor: Cursor, area_id: number, events: DatEvent[]): void
const unknown = cursor.u16(); // "wavesetting"?
const event_actions_offset = cursor.u32();
actions_cursor.seek_start(event_actions_offset);
const actions = parse_event_actions(actions_cursor);
let actions: DatEventAction[] = [];
if (event_actions_offset < actions_cursor.size) {
actions_cursor.seek_start(event_actions_offset);
actions = parse_event_actions(actions_cursor);
} else {
logger.warn(`Invalid event actions offset ${event_actions_offset} for event ${id}.`);
}
events.push({
id,

View File

@ -9,6 +9,22 @@ import { LogManager } from "../../../Logger";
const logger = LogManager.get("core/data_formats/parsing/quest/qst");
export enum Version {
PC,
/**
* Dreamcast/GameCube
*/
DC_GC,
/**
* BlueBurst
*/
BB,
/**
* Dreamcast Download
*/
DC_DOWNLOAD,
}
export type QstContainedFile = {
id?: number;
name: string;
@ -17,7 +33,7 @@ export type QstContainedFile = {
};
export type ParseQstResult = {
version: string;
version: Version;
files: QstContainedFile[];
};
@ -27,7 +43,7 @@ export type ParseQstResult = {
*/
export function parse_qst(cursor: Cursor): ParseQstResult | undefined {
// A .qst file contains two 88-byte headers that describe the embedded .dat and .bin files.
let version = "PC";
let version = Version.PC;
// Detect version.
const version_a = cursor.u8();
@ -35,16 +51,16 @@ export function parse_qst(cursor: Cursor): ParseQstResult | undefined {
const version_b = cursor.u8();
if (version_a === 0x44) {
version = "Dreamcast/GameCube";
version = Version.DC_GC;
} else if (version_a === 0x58) {
if (version_b === 0x44) {
version = "Blue Burst";
version = Version.BB;
}
} else if (version_a === 0xa6) {
version = "Dreamcast download";
version = Version.DC_DOWNLOAD;
}
if (version === "Blue Burst") {
if (version === Version.BB) {
// Read headers and contained files.
cursor.seek_start(0);
@ -66,7 +82,7 @@ export function parse_qst(cursor: Cursor): ParseQstResult | undefined {
files,
};
} else {
logger.error(`Can't parse ${version} QST files.`);
logger.error(`Can't parse ${Version[version]} QST files.`);
return undefined;
}
}
@ -79,7 +95,7 @@ export type QstContainedFileParam = {
};
export type WriteQstParams = {
version?: string;
version?: Version;
files: QstContainedFileParam[];
};

View File

@ -9,11 +9,11 @@ export type WeaponItemTypeDto = {
class: "weapon";
id: number;
name: string;
minAtp: number;
maxAtp: number;
min_atp: number;
max_atp: number;
ata: number;
maxGrind: number;
requiredAtp: number;
max_grind: number;
required_atp: number;
};
export type ArmorItemTypeDto = {
@ -22,10 +22,10 @@ export type ArmorItemTypeDto = {
name: string;
atp: number;
ata: number;
minEvp: number;
maxEvp: number;
minDfp: number;
maxDfp: number;
min_evp: number;
max_evp: number;
min_dfp: number;
max_dfp: number;
mst: number;
hp: number;
lck: number;
@ -37,10 +37,10 @@ export type ShieldItemTypeDto = {
name: string;
atp: number;
ata: number;
minEvp: number;
maxEvp: number;
minDfp: number;
maxDfp: number;
min_evp: number;
max_evp: number;
min_dfp: number;
max_dfp: number;
mst: number;
hp: number;
lck: number;

View File

@ -36,7 +36,7 @@ export class ItemTypeStore extends Store {
function create_loader(http_client: HttpClient): (server: Server) => Promise<ItemTypeStore> {
return async server => {
const data: ItemTypeDto[] = await http_client
.get(`/itemTypes.${Server[server].toLowerCase()}.json`)
.get(`/item_types.${Server[server].toLowerCase()}.json`)
.json();
const item_types: ItemType[] = [];
const id_to_item_type: ItemType[] = [];
@ -49,11 +49,11 @@ function create_loader(http_client: HttpClient): (server: Server) => Promise<Ite
item_type = new WeaponItemType(
item_type_dto.id,
item_type_dto.name,
item_type_dto.minAtp,
item_type_dto.maxAtp,
item_type_dto.min_atp,
item_type_dto.max_atp,
item_type_dto.ata,
item_type_dto.maxGrind,
item_type_dto.requiredAtp,
item_type_dto.max_grind,
item_type_dto.required_atp,
);
break;
case "armor":
@ -62,10 +62,10 @@ function create_loader(http_client: HttpClient): (server: Server) => Promise<Ite
item_type_dto.name,
item_type_dto.atp,
item_type_dto.ata,
item_type_dto.minEvp,
item_type_dto.maxEvp,
item_type_dto.minDfp,
item_type_dto.maxDfp,
item_type_dto.min_evp,
item_type_dto.max_evp,
item_type_dto.min_dfp,
item_type_dto.max_dfp,
item_type_dto.mst,
item_type_dto.hp,
item_type_dto.lck,
@ -77,10 +77,10 @@ function create_loader(http_client: HttpClient): (server: Server) => Promise<Ite
item_type_dto.name,
item_type_dto.atp,
item_type_dto.ata,
item_type_dto.minEvp,
item_type_dto.maxEvp,
item_type_dto.minDfp,
item_type_dto.maxDfp,
item_type_dto.min_evp,
item_type_dto.max_evp,
item_type_dto.min_dfp,
item_type_dto.max_dfp,
item_type_dto.mst,
item_type_dto.hp,
item_type_dto.lck,

View File

@ -2,5 +2,5 @@ export type QuestDto = {
id: number;
name: string;
episode: 1 | 2 | 4;
enemyCounts: { [npcTypeCode: string]: number };
enemy_counts: { [npc_type_code: string]: number };
};

View File

@ -1,18 +1,18 @@
export type EnemyDropDto = {
difficulty: string;
episode: number;
sectionId: string;
section_id: string;
enemy: string;
itemTypeId: number;
dropRate: number;
rareRate: number;
item_type_id: number;
drop_rate: number;
rare_rate: number;
};
export type BoxDropDto = {
difficulty: string;
episode: number;
sectionId: string;
areaId: number;
itemTypeId: number;
dropRate: number;
section_id: string;
area_id: number;
item_type_id: number;
drop_rate: number;
};

View File

@ -61,7 +61,7 @@ function create_loader(
let total_enemy_count = 0;
const enemy_counts = new Map<NpcType, number>();
for (const [code, count] of Object.entries(quest.enemyCounts)) {
for (const [code, count] of Object.entries(quest.enemy_counts)) {
const npc_type = (NpcType as any)[code];
if (!npc_type) {

View File

@ -85,7 +85,7 @@ function create_loader(
return async server => {
const item_type_store = await item_type_stores.get(server);
const data: EnemyDropDto[] = await http_client
.get(`/enemyDrops.${Server[server].toLowerCase()}.json`)
.get(`/enemy_drops.${Server[server].toLowerCase()}.json`)
.json();
const enemy_drops = new EnemyDropTable();
@ -100,17 +100,17 @@ function create_loader(
}
const difficulty = (Difficulty as any)[drop_dto.difficulty];
const item_type = item_type_store.get_by_id(drop_dto.itemTypeId);
const item_type = item_type_store.get_by_id(drop_dto.item_type_id);
if (!item_type) {
logger.warn(`Couldn't find item kind ${drop_dto.itemTypeId}.`);
logger.warn(`Couldn't find item kind ${drop_dto.item_type_id}.`);
continue;
}
const section_id = (SectionId as any)[drop_dto.sectionId];
const section_id = (SectionId as any)[drop_dto.section_id];
if (section_id == null) {
logger.warn(`Couldn't find section ID ${drop_dto.sectionId}.`);
logger.warn(`Couldn't find section ID ${drop_dto.section_id}.`);
continue;
}
@ -123,8 +123,8 @@ function create_loader(
section_id,
npc_type,
item_type,
drop_dto.dropRate,
drop_dto.rareRate,
drop_dto.drop_rate,
drop_dto.rare_rate,
),
);
}

View File

@ -409,6 +409,13 @@
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
"@types/node-fetch@^2.5.4":
version "2.5.4"
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.4.tgz#5245b6d8841fc3a6208b82291119bc11c4e0ce44"
integrity sha512-Oz6id++2qAOFuOlE1j0ouk1dzl3mmI1+qINPNBhi9nt/gVOz0G+13Ao6qjhdF0Ys+eOkhu6JnFmt38bR3H0POQ==
dependencies:
"@types/node" "*"
"@types/node@*":
version "12.12.21"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.21.tgz#aa44a6363291c7037111c47e4661ad210aded23f"
@ -5079,6 +5086,11 @@ no-case@^2.2.0:
dependencies:
lower-case "^1.1.1"
node-fetch@^2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
node-forge@0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579"