Renamed event-related types. Updated feature list.

This commit is contained in:
Daan Vanden Bosch 2019-10-10 19:47:38 +02:00
parent 2d534d2567
commit c287fdeb2f
9 changed files with 87 additions and 84 deletions

View File

@ -73,9 +73,16 @@ Features that are in ***bold italics*** are planned and not yet implemented.
## Events ## Events
- ***Create events*** - ***Event chain list***
- ***Delete events*** - ***Add chain of events***
- ***Edit events*** - ***Add event to chain***
- ***Delete event***
- ***Delete coupled NPCs if requested***
- ***Edit event section***
### Event Actions
- ***Add/Delete***
## Script Object Code ## Script Object Code
@ -122,10 +129,6 @@ Features that are in ***bold italics*** are planned and not yet implemented.
- ***When saving, ask user whether to really save when asm contains errors*** - ***When saving, ask user whether to really save when asm contains errors***
- ***Theme selection*** - ***Theme selection***
## Enemy Waves
- ***Figure out how they work***
## Non-BlueBurst Support ## Non-BlueBurst Support
- ***Support different sets of instructions (older versions had no stack)*** - ***Support different sets of instructions (older versions had no stack)***

View File

@ -15,7 +15,7 @@ const NPC_SIZE = 72;
export type DatFile = { export type DatFile = {
readonly objs: readonly DatObject[]; readonly objs: readonly DatObject[];
readonly npcs: readonly DatNpc[]; readonly npcs: readonly DatNpc[];
readonly waves: readonly DatWave[]; readonly waves: readonly DatEvent[];
readonly unknowns: readonly DatUnknown[]; readonly unknowns: readonly DatUnknown[];
}; };
@ -41,47 +41,47 @@ export type DatNpc = DatEntity & {
readonly roaming: number; readonly roaming: number;
}; };
export type DatWave = { export type DatEvent = {
readonly id: number; readonly id: number;
readonly section_id: number; readonly section_id: number;
readonly wave: number; readonly wave: number;
readonly delay: number; readonly delay: number;
readonly actions: readonly DatWaveAction[]; readonly actions: readonly DatEventAction[];
readonly area_id: number; readonly area_id: number;
readonly unknown: number; readonly unknown: number;
}; };
export enum DatWaveActionType { export enum DatEventActionType {
SpawnNpcs = 0x8, SpawnNpcs = 0x8,
Unlock = 0xa, Unlock = 0xa,
Lock = 0xb, Lock = 0xb,
SpawnWave = 0xc, SpawnWave = 0xc,
} }
export type DatWaveAction = export type DatEventAction =
| DatWaveActionSpawnNpcs | DatEventActionSpawnNpcs
| DatWaveActionUnlock | DatEventActionUnlock
| DatWaveActionLock | DatEventActionLock
| DatWaveActionSpawnWave; | DatEventActionSpawnWave;
export type DatWaveActionSpawnNpcs = { export type DatEventActionSpawnNpcs = {
readonly type: DatWaveActionType.SpawnNpcs; readonly type: DatEventActionType.SpawnNpcs;
readonly section_id: number; readonly section_id: number;
readonly appear_flag: number; readonly appear_flag: number;
}; };
export type DatWaveActionUnlock = { export type DatEventActionUnlock = {
readonly type: DatWaveActionType.Unlock; readonly type: DatEventActionType.Unlock;
readonly door_id: number; readonly door_id: number;
}; };
export type DatWaveActionLock = { export type DatEventActionLock = {
readonly type: DatWaveActionType.Lock; readonly type: DatEventActionType.Lock;
readonly door_id: number; readonly door_id: number;
}; };
export type DatWaveActionSpawnWave = { export type DatEventActionSpawnWave = {
readonly type: DatWaveActionType.SpawnWave; readonly type: DatEventActionType.SpawnWave;
readonly wave_id: number; readonly wave_id: number;
}; };
@ -96,7 +96,7 @@ export type DatUnknown = {
export function parse_dat(cursor: Cursor): DatFile { export function parse_dat(cursor: Cursor): DatFile {
const objs: DatObject[] = []; const objs: DatObject[] = [];
const npcs: DatNpc[] = []; const npcs: DatNpc[] = [];
const waves: DatWave[] = []; const waves: DatEvent[] = [];
const unknowns: DatUnknown[] = []; const unknowns: DatUnknown[] = [];
while (cursor.bytes_left) { while (cursor.bytes_left) {
@ -249,7 +249,7 @@ function parse_npcs(cursor: Cursor, area_id: number, npcs: DatNpc[]): void {
} }
} }
function parse_waves(cursor: Cursor, area_id: number, waves: DatWave[]): void { function parse_waves(cursor: Cursor, area_id: number, waves: DatEvent[]): void {
const actions_offset = cursor.u32(); const actions_offset = cursor.u32();
cursor.seek(4); // Always 0x10 cursor.seek(4); // Always 0x10
const wave_count = cursor.u32(); const wave_count = cursor.u32();
@ -312,8 +312,8 @@ function parse_waves(cursor: Cursor, area_id: number, waves: DatWave[]): void {
cursor.seek_start(actions_offset + actions_cursor.position); cursor.seek_start(actions_offset + actions_cursor.position);
} }
function parse_wave_actions(cursor: Cursor): DatWaveAction[] { function parse_wave_actions(cursor: Cursor): DatEventAction[] {
const actions: DatWaveAction[] = []; const actions: DatEventAction[] = [];
outer: while (cursor.bytes_left) { outer: while (cursor.bytes_left) {
const type = cursor.u8(); const type = cursor.u8();
@ -322,31 +322,31 @@ function parse_wave_actions(cursor: Cursor): DatWaveAction[] {
case 1: case 1:
break outer; break outer;
case DatWaveActionType.SpawnNpcs: case DatEventActionType.SpawnNpcs:
actions.push({ actions.push({
type: DatWaveActionType.SpawnNpcs, type: DatEventActionType.SpawnNpcs,
section_id: cursor.u16(), section_id: cursor.u16(),
appear_flag: cursor.u16(), appear_flag: cursor.u16(),
}); });
break; break;
case DatWaveActionType.Unlock: case DatEventActionType.Unlock:
actions.push({ actions.push({
type: DatWaveActionType.Unlock, type: DatEventActionType.Unlock,
door_id: cursor.u16(), door_id: cursor.u16(),
}); });
break; break;
case DatWaveActionType.Lock: case DatEventActionType.Lock:
actions.push({ actions.push({
type: DatWaveActionType.Lock, type: DatEventActionType.Lock,
door_id: cursor.u16(), door_id: cursor.u16(),
}); });
break; break;
case DatWaveActionType.SpawnWave: case DatEventActionType.SpawnWave:
actions.push({ actions.push({
type: DatWaveActionType.SpawnWave, type: DatEventActionType.SpawnWave,
wave_id: cursor.u32(), wave_id: cursor.u32(),
}); });
break; break;
@ -458,7 +458,7 @@ function write_npcs(cursor: WritableCursor, npcs: readonly DatNpc[]): void {
} }
} }
function write_waves(cursor: WritableCursor, waves: readonly DatWave[]): void { function write_waves(cursor: WritableCursor, waves: readonly DatEvent[]): void {
const grouped_waves = groupBy(waves, wave => wave.area_id); const grouped_waves = groupBy(waves, wave => wave.area_id);
const wave_area_ids = Object.keys(grouped_waves) const wave_area_ids = Object.keys(grouped_waves)
.map(key => parseInt(key, 10)) .map(key => parseInt(key, 10))
@ -506,20 +506,20 @@ function write_waves(cursor: WritableCursor, waves: readonly DatWave[]): void {
cursor.write_u8(action.type); cursor.write_u8(action.type);
switch (action.type) { switch (action.type) {
case DatWaveActionType.SpawnNpcs: case DatEventActionType.SpawnNpcs:
cursor.write_u16(action.section_id); cursor.write_u16(action.section_id);
cursor.write_u16(action.appear_flag); cursor.write_u16(action.appear_flag);
break; break;
case DatWaveActionType.Unlock: case DatEventActionType.Unlock:
cursor.write_u16(action.door_id); cursor.write_u16(action.door_id);
break; break;
case DatWaveActionType.Lock: case DatEventActionType.Lock:
cursor.write_u16(action.door_id); cursor.write_u16(action.door_id);
break; break;
case DatWaveActionType.SpawnWave: case DatEventActionType.SpawnWave:
cursor.write_u32(action.wave_id); cursor.write_u32(action.wave_id);
break; break;

View File

@ -1,7 +1,7 @@
import { Vec3 } from "../../vector"; import { Vec3 } from "../../vector";
import { npc_data, NpcType, NpcTypeData } from "./npc_types"; import { npc_data, NpcType, NpcTypeData } from "./npc_types";
import { object_data, ObjectType, ObjectTypeData } from "./object_types"; import { object_data, ObjectType, ObjectTypeData } from "./object_types";
import { DatWave } from "./dat"; import { DatEvent } from "./dat";
export type QuestNpc = { export type QuestNpc = {
readonly type: NpcType; readonly type: NpcType;
@ -47,7 +47,7 @@ export type QuestObject = {
readonly unknown: readonly number[][]; readonly unknown: readonly number[][];
}; };
export type QuestWave = DatWave; export type QuestEvent = DatEvent;
export type EntityTypeData = NpcTypeData | ObjectTypeData; export type EntityTypeData = NpcTypeData | ObjectTypeData;

View File

@ -14,7 +14,7 @@ import { ResizableBufferCursor } from "../../cursor/ResizableBufferCursor";
import { Endianness } from "../../Endianness"; import { Endianness } from "../../Endianness";
import { parse_bin, write_bin } from "./bin"; import { parse_bin, write_bin } from "./bin";
import { DatFile, DatNpc, DatObject, DatUnknown, parse_dat, write_dat } from "./dat"; import { DatFile, DatNpc, DatObject, DatUnknown, parse_dat, write_dat } from "./dat";
import { QuestNpc, QuestObject, QuestWave } from "./entities"; import { QuestNpc, QuestObject, QuestEvent } from "./entities";
import { Episode } from "./Episode"; import { Episode } from "./Episode";
import { object_data, ObjectType, pso_id_to_object_type } from "./object_types"; import { object_data, ObjectType, pso_id_to_object_type } from "./object_types";
import { parse_qst, QstContainedFile, write_qst } from "./qst"; import { parse_qst, QstContainedFile, write_qst } from "./qst";
@ -32,7 +32,7 @@ export type Quest = {
readonly episode: Episode; readonly episode: Episode;
readonly objects: readonly QuestObject[]; readonly objects: readonly QuestObject[];
readonly npcs: readonly QuestNpc[]; readonly npcs: readonly QuestNpc[];
readonly waves: readonly QuestWave[]; readonly waves: readonly QuestEvent[];
/** /**
* (Partial) raw DAT data that can't be parsed yet by Phantasmal. * (Partial) raw DAT data that can't be parsed yet by Phantasmal.
*/ */

View File

@ -1,6 +1,6 @@
export abstract class QuestWaveActionModel {} export abstract class QuestEventActionModel {}
export class QuestWaveActionSpawnNpcsModel extends QuestWaveActionModel { export class QuestEventActionSpawnNpcsModel extends QuestEventActionModel {
readonly section_id: number; readonly section_id: number;
readonly appear_flag: number; readonly appear_flag: number;
@ -12,7 +12,7 @@ export class QuestWaveActionSpawnNpcsModel extends QuestWaveActionModel {
} }
} }
export class QuestWaveActionUnlockModel extends QuestWaveActionModel { export class QuestEventActionUnlockModel extends QuestEventActionModel {
readonly door_id: number; readonly door_id: number;
constructor(door_id: number) { constructor(door_id: number) {
@ -22,7 +22,7 @@ export class QuestWaveActionUnlockModel extends QuestWaveActionModel {
} }
} }
export class QuestWaveActionLockModel extends QuestWaveActionModel { export class QuestEventActionLockModel extends QuestEventActionModel {
readonly door_id: number; readonly door_id: number;
constructor(door_id: number) { constructor(door_id: number) {
@ -32,7 +32,7 @@ export class QuestWaveActionLockModel extends QuestWaveActionModel {
} }
} }
export class QuestWaveActionSpawnWaveModel extends QuestWaveActionModel { export class QuestEventActionSpawnWaveModel extends QuestEventActionModel {
readonly wave_id: number; readonly wave_id: number;
constructor(wave_id: number) { constructor(wave_id: number) {

View File

@ -1,11 +1,11 @@
import { QuestWaveActionModel } from "./QuestWaveActionModel"; import { QuestEventActionModel } from "./QuestEventActionModel";
export class QuestWaveModel { export class QuestEventModel {
readonly id: number; readonly id: number;
readonly section_id: number; readonly section_id: number;
readonly wave: number; readonly wave: number;
readonly delay: number; readonly delay: number;
readonly actions: readonly QuestWaveActionModel[]; readonly actions: readonly QuestEventActionModel[];
readonly area_id: number; readonly area_id: number;
readonly unknown: number; readonly unknown: number;
@ -14,7 +14,7 @@ export class QuestWaveModel {
section_id: number, section_id: number,
wave: number, wave: number,
delay: number, delay: number,
actions: readonly QuestWaveActionModel[], actions: readonly QuestEventActionModel[],
area_id: number, area_id: number,
unknown: number, unknown: number,
) { ) {

View File

@ -13,7 +13,7 @@ import { ListProperty } from "../../core/observable/property/list/ListProperty";
import { WritableListProperty } from "../../core/observable/property/list/WritableListProperty"; import { WritableListProperty } from "../../core/observable/property/list/WritableListProperty";
import { QuestEntityModel } from "./QuestEntityModel"; import { QuestEntityModel } from "./QuestEntityModel";
import { entity_type_to_string } from "../../core/data_formats/parsing/quest/entities"; import { entity_type_to_string } from "../../core/data_formats/parsing/quest/entities";
import { QuestWaveModel } from "./QuestWaveModel"; import { QuestEventModel } from "./QuestEventModel";
const logger = Logger.get("quest_editor/model/QuestModel"); const logger = Logger.get("quest_editor/model/QuestModel");
@ -27,7 +27,7 @@ export class QuestModel {
private readonly _area_variants: WritableListProperty<AreaVariantModel> = list_property(); private readonly _area_variants: WritableListProperty<AreaVariantModel> = list_property();
private readonly _objects: WritableListProperty<QuestObjectModel>; private readonly _objects: WritableListProperty<QuestObjectModel>;
private readonly _npcs: WritableListProperty<QuestNpcModel>; private readonly _npcs: WritableListProperty<QuestNpcModel>;
private readonly _waves: WritableListProperty<QuestWaveModel>; private readonly _waves: WritableListProperty<QuestEventModel>;
readonly id: Property<number> = this._id; readonly id: Property<number> = this._id;
@ -60,7 +60,7 @@ export class QuestModel {
readonly npcs: ListProperty<QuestNpcModel>; readonly npcs: ListProperty<QuestNpcModel>;
readonly waves: ListProperty<QuestWaveModel>; readonly waves: ListProperty<QuestEventModel>;
/** /**
* (Partial) raw DAT data that can't be parsed yet by Phantasmal. * (Partial) raw DAT data that can't be parsed yet by Phantasmal.
@ -81,7 +81,7 @@ export class QuestModel {
map_designations: Map<number, number>, map_designations: Map<number, number>,
objects: readonly QuestObjectModel[], objects: readonly QuestObjectModel[],
npcs: readonly QuestNpcModel[], npcs: readonly QuestNpcModel[],
waves: readonly QuestWaveModel[], waves: readonly QuestEventModel[],
dat_unknowns: readonly DatUnknown[], dat_unknowns: readonly DatUnknown[],
object_code: readonly Segment[], object_code: readonly Segment[],
shop_items: readonly number[], shop_items: readonly number[],

View File

@ -29,14 +29,14 @@ import { Euler, Vector3 } from "three";
import { vec3_to_threejs } from "../../core/rendering/conversion"; import { vec3_to_threejs } from "../../core/rendering/conversion";
import { RotateEntityAction } from "../actions/RotateEntityAction"; import { RotateEntityAction } from "../actions/RotateEntityAction";
import { ExecutionResult, VirtualMachine } from "../scripting/vm"; import { ExecutionResult, VirtualMachine } from "../scripting/vm";
import { QuestWaveModel } from "../model/QuestWaveModel"; import { QuestEventModel } from "../model/QuestEventModel";
import { DatWaveActionType } from "../../core/data_formats/parsing/quest/dat"; import { DatEventActionType } from "../../core/data_formats/parsing/quest/dat";
import { import {
QuestWaveActionLockModel, QuestEventActionLockModel,
QuestWaveActionSpawnNpcsModel, QuestEventActionSpawnNpcsModel,
QuestWaveActionSpawnWaveModel, QuestEventActionSpawnWaveModel,
QuestWaveActionUnlockModel, QuestEventActionUnlockModel,
} from "../model/QuestWaveActionModel"; } from "../model/QuestEventActionModel";
import Logger = require("js-logger"); import Logger = require("js-logger");
const logger = Logger.get("quest_editor/gui/QuestEditorStore"); const logger = Logger.get("quest_editor/gui/QuestEditorStore");
@ -170,26 +170,26 @@ export class QuestEditorStore implements Disposable {
), ),
quest.waves.map( quest.waves.map(
wave => wave =>
new QuestWaveModel( new QuestEventModel(
wave.id, wave.id,
wave.section_id, wave.section_id,
wave.wave, wave.wave,
wave.delay, wave.delay,
wave.actions.map(action => { wave.actions.map(action => {
switch (action.type) { switch (action.type) {
case DatWaveActionType.SpawnNpcs: case DatEventActionType.SpawnNpcs:
return new QuestWaveActionSpawnNpcsModel( return new QuestEventActionSpawnNpcsModel(
action.section_id, action.section_id,
action.appear_flag, action.appear_flag,
); );
case DatWaveActionType.Unlock: case DatEventActionType.Unlock:
return new QuestWaveActionUnlockModel( return new QuestEventActionUnlockModel(
action.door_id, action.door_id,
); );
case DatWaveActionType.Lock: case DatEventActionType.Lock:
return new QuestWaveActionLockModel(action.door_id); return new QuestEventActionLockModel(action.door_id);
case DatWaveActionType.SpawnWave: case DatEventActionType.SpawnWave:
return new QuestWaveActionSpawnWaveModel( return new QuestEventActionSpawnWaveModel(
action.wave_id, action.wave_id,
); );
} }
@ -261,25 +261,25 @@ export class QuestEditorStore implements Disposable {
wave: wave.wave, wave: wave.wave,
delay: wave.delay, delay: wave.delay,
actions: wave.actions.map(action => { actions: wave.actions.map(action => {
if (action instanceof QuestWaveActionSpawnNpcsModel) { if (action instanceof QuestEventActionSpawnNpcsModel) {
return { return {
type: DatWaveActionType.SpawnNpcs, type: DatEventActionType.SpawnNpcs,
section_id: action.section_id, section_id: action.section_id,
appear_flag: action.appear_flag, appear_flag: action.appear_flag,
}; };
} else if (action instanceof QuestWaveActionUnlockModel) { } else if (action instanceof QuestEventActionUnlockModel) {
return { return {
type: DatWaveActionType.Unlock, type: DatEventActionType.Unlock,
door_id: action.door_id, door_id: action.door_id,
}; };
} else if (action instanceof QuestWaveActionLockModel) { } else if (action instanceof QuestEventActionLockModel) {
return { return {
type: DatWaveActionType.Lock, type: DatEventActionType.Lock,
door_id: action.door_id, door_id: action.door_id,
}; };
} else if (action instanceof QuestWaveActionSpawnWaveModel) { } else if (action instanceof QuestEventActionSpawnWaveModel) {
return { return {
type: DatWaveActionType.SpawnWave, type: DatEventActionType.SpawnWave,
wave_id: action.wave_id, wave_id: action.wave_id,
}; };
} else { } else {

View File

@ -17,7 +17,7 @@ import {
import { QuestObjectModel } from "../model/QuestObjectModel"; import { QuestObjectModel } from "../model/QuestObjectModel";
import { QuestNpcModel } from "../model/QuestNpcModel"; import { QuestNpcModel } from "../model/QuestNpcModel";
import { Euler, Vector3 } from "three"; import { Euler, Vector3 } from "three";
import { QuestWaveModel } from "../model/QuestWaveModel"; import { QuestEventModel } from "../model/QuestEventModel";
export function create_new_quest(episode: Episode): QuestModel { export function create_new_quest(episode: Episode): QuestModel {
if (episode === Episode.II) throw new Error("Episode II not yet supported."); if (episode === Episode.II) throw new Error("Episode II not yet supported.");
@ -807,6 +807,6 @@ function create_default_npcs(): QuestNpcModel[] {
]; ];
} }
function create_default_waves(): QuestWaveModel[] { function create_default_waves(): QuestEventModel[] {
return []; return [];
} }