mirror of
https://github.com/DaanVandenBosch/phantasmal-world.git
synced 2025-04-04 22:58:29 +08:00
Hunt methods are now loaded for ephinea.
This commit is contained in:
parent
0dc55b5eb7
commit
0c9218be16
129
public/quests.ephinea.tsv
Normal file
129
public/quests.ephinea.tsv
Normal file
@ -0,0 +1,129 @@
|
||||
episode: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
|
||||
quest hours Hildebear Hildeblue Rag Rappy Al Rappy Monest Savage Wolf Barbarous Wolf Booma Gobooma Gigobooma Dragon Grass Assassin Poison Lily Nar Lily Nano Dragon Evil Shark Pal Shark Guil Shark Pofuilly Slime Pouilly Slime Pan Arms De Rol Le Dubchic Gilchic Garanz Sinow Beat Sinow Gold Canadine Canane Dubswitch Vol Opt Delsaber Chaos Sorcerer Dark Gunner Chaos Bringer Dark Belra Dimenian La Dimenian So Dimenian Bulclaw Claw Dark Falz Hildebear Hildeblue Rag Rappy Love Rappy Monest Poison Lily Nar Lily Grass Assassin Dimenian La Dimenian So Dimenian Dark Belra Barba Ray Savage Wolf Barbarous Wolf Pan Arms Dubchic Gilchic Garanz Dubswitch Delsaber Chaos Sorcerer Gol Dragon Sinow Berill Sinow Spigell Merillia Meriltas Mericarol Merikle Mericus Ul Gibbon Zol Gibbon Gibbles Gee Gi Gue Gal Gryphon Deldepth Delbiter Dolmolm Dolmdarl Morfos Recobox Epsilon Sinow Zoa Sinow Zele Ill Gill Del Lily Olga Flow Sand Rappy Del Rappy Astark Satellite Lizard Yowie Merissa A Merissa AA Girtablulu Zu Pazuzu Boota Ze Boota Ba Boota Dorphon Dorphon Eclair Goran Pyro Goran Goran Detonator Saint-Million Shambertin Kondrieu Normal Box Gold Box
|
||||
Valentine's Event 0,50 8 3 11 9 11 3 23 5
|
||||
AOL CUP -Maximum Attack- 0,50 11 1 25 18 59 24 37 81 13 54 12 23 6 6 96 22 34 3 79 2
|
||||
Maximum Attack 4th Stage -A- (Ep. I) 0,33 25 63 14 43 21 28 16 20 46 12 17 21 67 3 4 7 31 3 23 37 33 30 8 51
|
||||
Maximum Attack 4th Stage -B- (Ep. I) 0,33 28 62 22 20 40 32 14 21 21 13 19 16 59 3 4 10 24 5 27 13 18 25 11 52
|
||||
Maximum Attack 4th Stage -C- (Ep. I) 0,33 28 62 22 20 40 32 14 24 19 16 17 19 48 4 3 7 18 12 9 11 11 20 5 17 1
|
||||
Principal's Gift 0,50 6 68 2 22 3 20 1
|
||||
White Day 0,50 26 5 24 24 24 7 4
|
||||
Endless Nightmare #1 0,50 8 19 4 29 4 60 32 23
|
||||
Endless Nightmare #2 0,50 20 32 6 152 44 28 5
|
||||
Endless Nightmare #3 0,50 37 108 10 48 14 84 2 8
|
||||
Endless Nightmare #4 0,50 44 3 21 13 28 49 59 49 6 90
|
||||
Mop-up Operation #1 0,50 2 10 5 14 23 36
|
||||
Mop-up Operation #2 0,50 10 9 18 72 21 24
|
||||
Mop-up Operation #3 0,50 9 59 6 17 7 55 2 2
|
||||
Mop-up Operation #4 0,50 13 5 6 12 35 27 33 50
|
||||
Today's Rate 0,50 52 7 1 1 53 5 6 9 47 6 27 7 25 3
|
||||
Fragment of Memory 0,50 81 68 77 16 38 226 86 237 1
|
||||
Gallon's Treachery 0,50 22 7 16 13 14 5 1 3 2 3 3 3 10 12
|
||||
Lost HAVOC VULCAN 0,50 68 28 81 49 54 156 94 89 36 152 1
|
||||
Lost HEAT SWORD 0,33 12 10 7 26 7 34 38 53 1
|
||||
Lost ICE SPINNER 1,00 37 56 26 129 65 125 7 5 1
|
||||
Lost SOUL BLADE 0,50 17 85 26 70 37 112 4 4 1
|
||||
Rappy's Holiday 0,50 75 10 15 20 20 11 13
|
||||
Labyrinthine Trial 0,50 14 15 2 10 38 16 12 6
|
||||
Towards the Future 0,50 4 1 2 1 12 6 7 1 13 5 13 5 7 5 4 1 1 26 3 12 2 24 1 1 1 2 4 4 17 4 14 1
|
||||
Dream Messenger 0,50 8 8 1 49
|
||||
Festivity On The Beach 0,50 15
|
||||
Pioneer Halloween 0,50 2 57 25 1 51 8 30 1
|
||||
Maximum Attack 2 0,50 18 35 6 20 21 27 14 56 5 10 52 17 36 19 2 76 97 7 1 1 106 78 8 122 9
|
||||
Maximum Attack 4th Stage -A- (Ep. II) 0,33 20 8 32 21 1 29 41 6 62 12 7 55 51 20 56 12 7
|
||||
Maximum Attack 4th Stage -B- (Ep. II) 0,33 25 12 52 42 6 1 1 16 27 67 25 2 51 53 38 42 12 18
|
||||
Maximum Attack 4th Stage -C- (Ep. II) 0,33 22 14 24 20 4 6 6 14 26 14 45 15 10 19 44 38 16 58 4 18 18 21 28
|
||||
Phantasmal World #1 0,50 25 7 83 41 6 45 20 122 12
|
||||
Phantasmal World #2 0,50 24 9 54 42 114 26 9 80
|
||||
Phantasmal World #3 0,50 31 27 103 57 47 27 33 22
|
||||
Phantasmal World #4 1,00 11 6 6 20 22 19 20 9 72 57
|
||||
The East Tower 0,50 2 2 16 5 1 3 6 9 6 8 8 3 14 1 4 7
|
||||
The West Tower 0,50 6 1 1 5 7 14 10 10 36 1 7 6 8 9
|
||||
Reach for the Dream 0,50 4 2 6 19 3 1 7
|
||||
Respective Tomorrow 0,50 5 10 2 19 3 18 9 1 1 1 1 28 1 1 6 1 1 3 19 2 6 1 1 6 3 4 88 5 1 1 2 4 4 62 1 9 1 3 3 1
|
||||
LOGiN presents 勇場のマッチレース 0,50 88 19 46 70 84 14 20 59 51 22 4 94 52 22
|
||||
Maximum Attack 4th Stage -A- (Ep. IV) 0,33 57 13 68 56 58 20 18 13 16 3 30 26 6
|
||||
Maximum Attack 4th Stage -B- (Ep. IV) 0,33 60 11 58 50 20 3 48 24 15 17 3 40 32 19
|
||||
Maximum Attack 4th Stage -C- (Ep. IV) 0,33 73 16 69 74 37 6 33 20 22 16 13 37 26 18
|
||||
New Mop-up Operation #1 0,50 37 22 32 20 8 20 5 5 2
|
||||
New Mop-up Operation #2 0,50 20 11 41 23 5 31 36 14 5
|
||||
New Mop-up Operation #3 0,50 38 73 41 4 4 108 55 16
|
||||
New Mop-up Operation #4 0,50 29 25 38 24 1 46 40 3
|
||||
New Mop-up Operation #5 0,50 11 38 40 25 4 19 37 30 7
|
||||
War of Limits 1 0,50 42 42 51 25 12 47 12 10 5
|
||||
War of Limits 2 0,50 37 11 92 37 5 39 74 25 3
|
||||
War of Limits 3 0,50 47 37 66 6 85 87 26 4
|
||||
War of Limits 4 0,50 26 30 26 28 3 1 37 36 16
|
||||
War of Limits 5 0,50 44 48 41 11 4 15 49 19 7
|
||||
MAXIMUM ATTACK 3 Ver2 0,50 83 54 122 115 99 4 46 45 39 47 10 101 103 32
|
||||
1-1:Planet Ragol 0,50 2 4 36 4 40 7 6
|
||||
1-2:Torrential Woods 0,50 5 17 3 19 7 35 31 16
|
||||
1-3:Subterranean Den 0,50 5 12 3 33 10 45 32 15 1
|
||||
2-1:Infernal Cavern 0,75 18 37 17 114 18 3
|
||||
2-2:Deep Within 0,75 20 59 15 165 31 7 16
|
||||
2-3:The Mutation 0,75 7 41 12 89 42 24 10 2 13
|
||||
2-4:Waterway Shadow 0,75 16 36 4 17 165 87 28 4 4 1
|
||||
3-1:The Facility 0,75 3 115 12 2 47 2 1
|
||||
3-2:Machines Attack 0,75 22 60 9 14 2 59 2 7
|
||||
3-3:Central Control 0,75 11 93 4 16 6 90 3 3 1
|
||||
4-1:The Lost Ruins 0,75 14 42 3 8 4 41 1 4 10 13 18 61 7 3 5 89
|
||||
4-2:Buried Relics 0,75 31 20 2 28 55 6 5 50
|
||||
4-3:Hero & Daughter 0,75 26 4 30 7 5 75 50 22 8 122
|
||||
4-4:The Tomb Stirs 0,75 17 16 10 25 82 35 34 7 55
|
||||
4-5:Dark Inheritance 0,75 26 11 36 9 12 111 78 44 6 143 1
|
||||
5-1:Test/VR Temple 1 0,75 5 13 3 29 2 16 17 33
|
||||
5-2:Test/VR Temple 2 0,75 11 23 6 52 17 21 25 15 7
|
||||
5-3:Test/VR Temple 3 0,75 9 4 4 35 12 17 17 12 9
|
||||
5-4:Test/VR Temple 4 0,75 5 29 5 56 5 24 14 47 23 8
|
||||
5-5:Test/VR Temple 5 0,75 11 26 6 63 16 21 34 27 9 1
|
||||
6-1:Test/Spaceship 1 0,75 32 24 5 54 7 12
|
||||
6-2:Test/Spaceship 2 0,75 50 24 9 8 84 5 3 17 5
|
||||
6-3:Test/Spaceship 3 0,75 36 27 15 16 50 1 5 26 5
|
||||
6-4:Test/Spaceship 4 0,75 39 36 8 10 87 6 3 25 11
|
||||
6-5:Test/Spaceship 5 0,75 41 32 10 10 92 5 3 27 11 1
|
||||
7-1:From the Past 0,75 3 55 17 4 20 3 20
|
||||
7-2:Seeking Clues 0,75 3 37 19 1 25 43 6 8
|
||||
7-3:Silent Beach 0,75 4 29 8 30 45 1 94 5
|
||||
7-4:Central Control 0,75 11 6 22 6 4 17 18 3 34 4
|
||||
7-5:Isle of Mutants 0,75 11 6 59 42 1 43 56 1 132 1 1
|
||||
8-1:Below the Waves 0,75 9 3 35 17 25 23 3
|
||||
8-2:Desire's End 0,75 2 4 34 43 25 28 24 5
|
||||
8-3:Purple Lamplight 0,75 7 7 23 38 19 41 39 4 1
|
||||
9-1:Missing Research 0,75 26 10 40 12 67 48 27 1
|
||||
9-2:Data Retrieval 0,75 41 18 28 18 48 21 24 5
|
||||
9-3:Reality & Truth 0,75 24 9 31 4 13 21 22 50 1
|
||||
9-4:Pursuit 0,75 30 17 34 5 17 45 55 29 5
|
||||
9-5:The Chosen (1/2) 0,75 36 5 46 9 25 10 12 5 3 2 62 20 9
|
||||
9-6:The Chosen (2/2) 0,75 12 21 19 34 1 2 25 34 4
|
||||
9-7:Sacred Ground 0,75 28 39 11 29 1 5 54 38 11
|
||||
9-8:The Final Cycle 0,75 45 41 63 47 1 6 57 61 8 1
|
||||
Point of Disaster 0,25 50 31 50 31 4 1 20 24 8 6 9 10 4 3 1
|
||||
Battle Training 0,50 2 2 12 2 14 3
|
||||
Claiming a Stake 0,50 5 1 1 19 2
|
||||
Magnitude of Metal 0,50 4 1 16
|
||||
Journalistic Pursuit 0,50 1 11 3 12 1 18 9 6
|
||||
The Fake in Yellow 0,50 47
|
||||
Native Research 0,50 2 13 4 10 4 29 13 8
|
||||
Forest of Sorrow 0,13 16 15 4 14 7 26 15 3
|
||||
Gran Squall 0,50 4 15 7 18 4 24 13 7
|
||||
Addicting Food 0,50 19 62 2 19 195 38 15 13 7
|
||||
The Lost Bride 0,50 2 20 2 33 6 5 7
|
||||
Waterfall Tears 0,50 6 18 12 37 6 1
|
||||
Black Paper 0,50 12 20 2 14 94 31 10 8 3
|
||||
Secret Delivery 0,50 9 18 5 59 9 5 5
|
||||
Soul of a Blacksmith 0,50 5 11 5 28 11 31 29 27 1 14 17 6 12 125 44 25 9 2 6
|
||||
Letter from Lionel 0,50 5 17 2 19 4 34 15 5 4 36 2 74 19 9 11 1
|
||||
The Grave's Butler 0,50 9 22 4 35 7 2 1
|
||||
Knowing One's Heart 0,50 22 5 2 29 1
|
||||
The Retired Hunter 0,50 1 8 2 7 6 6 4 3 3 3 4 17 7 18 1 42
|
||||
Dr. Osto's Research 0,50 13 27 3 2 15 3
|
||||
Unsealed Door 0,50 1 13 97 6 2 62 3 3
|
||||
Soul of Steel 0,50 22 1 2 1 5 11 4 7 14 12 14 4 40
|
||||
Doc's Secret Plan 0,50 9 11 7 47 7 1 6 29
|
||||
Seek my Master 0,50 21 3 20 2 9 43 24 4 2 86
|
||||
From the Depths 0,50 11 3 17 6 4 41 23 11 7 71
|
||||
Central Dome Fire Swirl 0,50 4 19 19 14 9 19 34
|
||||
Seat of the Heart 0,50 3 7 2 9 3 12 11 12 2 25 1 16 16 3 2 1 1 2 5 5 12 4 8 4 6 10 5 2 13 1 7 2
|
||||
Pioneer Spirit 0,50 40 1 14 25 29 31 3 21 8 2 4 4 40 29 5
|
||||
Warrior's Pride 0,50 61 46 51 53 29 35 10 23 13
|
||||
The Restless Lion 0,50 8 16 13 14 3 13 10 1
|
||||
To the End of the Wilderness 0,50 56 14 14 41 13 77 55 47 2
|
|
9
src/actions/huntMethods.ts
Normal file
9
src/actions/huntMethods.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { memoize } from 'lodash';
|
||||
import { huntMethodStore } from '../stores/HuntMethodStore';
|
||||
import { getHuntMethods } from '../data/loading/huntMethods';
|
||||
|
||||
export const loadHuntMethods = memoize(
|
||||
async (server: string) => {
|
||||
huntMethodStore.methods.replace(await getHuntMethods(server));
|
||||
}
|
||||
);
|
@ -1,15 +1,9 @@
|
||||
import { memoize } from "lodash";
|
||||
import { getItems } from "../data/loading/items";
|
||||
import { itemStore } from "../stores/ItemStore";
|
||||
import { action } from "mobx";
|
||||
import { memoize } from "lodash";
|
||||
import { Item } from "../domain";
|
||||
|
||||
export const loadItems = memoize(
|
||||
async (server: string) => {
|
||||
setItems(await getItems(server));
|
||||
itemStore.items.replace(await getItems(server));
|
||||
}
|
||||
);
|
||||
|
||||
const setItems = action('setItems', (items: Item[]) => {
|
||||
itemStore.items.replace(items);
|
||||
});
|
@ -4,7 +4,7 @@ import { getAreaSections } from '../../data/loading/areas';
|
||||
import { getNpcGeometry, getObjectGeometry } from '../../data/loading/entities';
|
||||
import { parseNj, parseXj } from '../../data/parsing/ninja';
|
||||
import { parseQuest } from '../../data/parsing/quest';
|
||||
import { Section, Vec3, VisibleQuestEntity } from '../../domain';
|
||||
import { Section, Vec3, QuestEntity } from '../../domain';
|
||||
import { createNpcMesh, createObjectMesh } from '../../rendering/entities';
|
||||
import { createModelMesh } from '../../rendering/models';
|
||||
import { setModel, setQuest } from './questEditor';
|
||||
@ -65,7 +65,7 @@ async function loadend(file: File, reader: FileReader) {
|
||||
}
|
||||
|
||||
const setSectionOnVisibleQuestEntity = action('setSectionOnVisibleQuestEntity',
|
||||
(entity: VisibleQuestEntity, sections: Section[]) => {
|
||||
(entity: QuestEntity, sections: Section[]) => {
|
||||
let { x, y, z } = entity.position;
|
||||
|
||||
const section = sections.find(s => s.id === entity.sectionId);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { writeQuestQst } from '../../data/parsing/quest';
|
||||
import { VisibleQuestEntity, Quest } from '../../domain';
|
||||
import { QuestEntity, Quest } from '../../domain';
|
||||
import { questEditorStore } from '../../stores/QuestEditorStore';
|
||||
import { action } from 'mobx';
|
||||
import { Object3D } from 'three';
|
||||
@ -31,7 +31,7 @@ function resetModelAndQuestState() {
|
||||
questEditorStore.currentModel = undefined;
|
||||
}
|
||||
|
||||
export const setSelectedEntity = action('setSelectedEntity', (entity?: VisibleQuestEntity) => {
|
||||
export const setSelectedEntity = action('setSelectedEntity', (entity?: QuestEntity) => {
|
||||
questEditorStore.selectedEntity = entity;
|
||||
});
|
||||
|
||||
|
35
src/data/loading/huntMethods.ts
Normal file
35
src/data/loading/huntMethods.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { HuntMethod, NpcType, SimpleNpc, SimpleQuest } from "../../domain";
|
||||
|
||||
export async function getHuntMethods(server: string): Promise<HuntMethod[]> {
|
||||
const response = await fetch(process.env.PUBLIC_URL + `/quests.${server}.tsv`);
|
||||
const data = await response.text();
|
||||
const rows = data.split('\n').map(line => line.split('\t'));
|
||||
|
||||
const npcTypeByIndex = rows[0].slice(2, -2).map((episode, i) => {
|
||||
const enemy = rows[1][i + 2];
|
||||
return NpcType.bySimpleNameAndEpisode(enemy, parseInt(episode, 10))!;
|
||||
});
|
||||
|
||||
return rows.slice(2).map(row => {
|
||||
const questName = row[0];
|
||||
|
||||
const npcs = row.slice(2, -2).flatMap((cell, cellI) => {
|
||||
const amount = parseInt(cell, 10);
|
||||
const type = npcTypeByIndex[cellI];
|
||||
const enemies = [];
|
||||
|
||||
for (let i = 0; i < amount; i++) {
|
||||
enemies.push(new SimpleNpc(type));
|
||||
}
|
||||
|
||||
return enemies;
|
||||
});
|
||||
|
||||
return new HuntMethod(
|
||||
new SimpleQuest(
|
||||
questName,
|
||||
npcs
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
@ -1,20 +1,53 @@
|
||||
export class NpcType {
|
||||
id: number;
|
||||
code: string;
|
||||
/**
|
||||
* Unique name.
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Name used in the game.
|
||||
* Might conflict with other NPC names (e.g. Delsaber from ep. I and ep. II).
|
||||
*/
|
||||
simpleName: string;
|
||||
episode?: number;
|
||||
enemy: boolean;
|
||||
|
||||
constructor(id: number, code: string, name: string, enemy: boolean) {
|
||||
constructor(id: number, code: string, name: string, simpleName: string, episode: number | undefined, enemy: boolean) {
|
||||
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 (!name) throw new Error('name is required.');
|
||||
if (!simpleName) throw new Error('simpleName 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.name = name;
|
||||
this.simpleName = simpleName;
|
||||
this.episode = episode;
|
||||
this.enemy = enemy;
|
||||
|
||||
if (episode) {
|
||||
const map = NpcType.byEpAndSimpleName[episode];
|
||||
if (map) map.set(name, this);
|
||||
}
|
||||
}
|
||||
|
||||
private static byEpAndSimpleName = [
|
||||
undefined, new Map<string, NpcType>(), new Map<string, NpcType>(), undefined, new Map<string, NpcType>()
|
||||
];
|
||||
|
||||
/**
|
||||
* Uniquely identifies an NPC.
|
||||
*/
|
||||
static bySimpleNameAndEpisode(simpleName: string, episode: number): NpcType | undefined {
|
||||
const ep = this.byEpAndSimpleName[episode];
|
||||
if (!ep) throw new Error(`No NpcTypes for episode ${episode}.`);
|
||||
|
||||
return ep.get(simpleName);
|
||||
}
|
||||
|
||||
//
|
||||
@ -195,29 +228,29 @@ export class NpcType {
|
||||
// Unknown NPCs
|
||||
//
|
||||
|
||||
NpcType.Unknown = new NpcType(id++, 'Unknown', 'Unknown', false);
|
||||
NpcType.Unknown = new NpcType(id++, 'Unknown', 'Unknown', 'Unknown', undefined, false);
|
||||
|
||||
//
|
||||
// Friendly NPCs
|
||||
//
|
||||
|
||||
NpcType.FemaleFat = new NpcType(id++, 'FemaleFat', 'Female Fat', false);
|
||||
NpcType.FemaleMacho = new NpcType(id++, 'FemaleMacho', 'Female Macho', false);
|
||||
NpcType.FemaleTall = new NpcType(id++, 'FemaleTall', 'Female Tall', false);
|
||||
NpcType.MaleDwarf = new NpcType(id++, 'MaleDwarf', 'Male Dwarf', false);
|
||||
NpcType.MaleFat = new NpcType(id++, 'MaleFat', 'Male Fat', false);
|
||||
NpcType.MaleMacho = new NpcType(id++, 'MaleMacho', 'Male Macho', false);
|
||||
NpcType.MaleOld = new NpcType(id++, 'MaleOld', 'Male Old', false);
|
||||
NpcType.BlueSoldier = new NpcType(id++, 'BlueSoldier', 'Blue Soldier', false);
|
||||
NpcType.RedSoldier = new NpcType(id++, 'RedSoldier', 'Red Soldier', false);
|
||||
NpcType.Principal = new NpcType(id++, 'Principal', 'Principal', false);
|
||||
NpcType.Tekker = new NpcType(id++, 'Tekker', 'Tekker', false);
|
||||
NpcType.GuildLady = new NpcType(id++, 'GuildLady', 'Guild Lady', false);
|
||||
NpcType.Scientist = new NpcType(id++, 'Scientist', 'Scientist', false);
|
||||
NpcType.Nurse = new NpcType(id++, 'Nurse', 'Nurse', false);
|
||||
NpcType.Irene = new NpcType(id++, 'Irene', 'Irene', false);
|
||||
NpcType.ItemShop = new NpcType(id++, 'ItemShop', 'Item Shop', false);
|
||||
NpcType.Nurse2 = new NpcType(id++, 'Nurse2', 'Nurse (Episode II)', false);
|
||||
NpcType.FemaleFat = new NpcType(id++, 'FemaleFat', 'Female Fat', 'Female Fat', undefined, false);
|
||||
NpcType.FemaleMacho = new NpcType(id++, 'FemaleMacho', 'Female Macho', 'Female Macho', undefined, false);
|
||||
NpcType.FemaleTall = new NpcType(id++, 'FemaleTall', 'Female Tall', 'Female Tall', undefined, false);
|
||||
NpcType.MaleDwarf = new NpcType(id++, 'MaleDwarf', 'Male Dwarf', 'Male Dwarf', undefined, false);
|
||||
NpcType.MaleFat = new NpcType(id++, 'MaleFat', 'Male Fat', 'Male Fat', undefined, false);
|
||||
NpcType.MaleMacho = new NpcType(id++, 'MaleMacho', 'Male Macho', 'Male Macho', undefined, false);
|
||||
NpcType.MaleOld = new NpcType(id++, 'MaleOld', 'Male Old', 'Male Old', undefined, false);
|
||||
NpcType.BlueSoldier = new NpcType(id++, 'BlueSoldier', 'Blue Soldier', 'Blue Soldier', undefined, false);
|
||||
NpcType.RedSoldier = new NpcType(id++, 'RedSoldier', 'Red Soldier', 'Red Soldier', undefined, false);
|
||||
NpcType.Principal = new NpcType(id++, 'Principal', 'Principal', 'Principal', undefined, false);
|
||||
NpcType.Tekker = new NpcType(id++, 'Tekker', 'Tekker', 'Tekker', undefined, false);
|
||||
NpcType.GuildLady = new NpcType(id++, 'GuildLady', 'Guild Lady', 'Guild Lady', undefined, false);
|
||||
NpcType.Scientist = new NpcType(id++, 'Scientist', 'Scientist', 'Scientist', undefined, false);
|
||||
NpcType.Nurse = new NpcType(id++, 'Nurse', 'Nurse', 'Nurse', undefined, false);
|
||||
NpcType.Irene = new NpcType(id++, 'Irene', 'Irene', 'Irene', undefined, false);
|
||||
NpcType.ItemShop = new NpcType(id++, 'ItemShop', 'Item Shop', 'Item Shop', undefined, false);
|
||||
NpcType.Nurse2 = new NpcType(id++, 'Nurse2', 'Nurse', 'Nurse (Ep. II)', 2, false);
|
||||
|
||||
//
|
||||
// Enemy NPCs
|
||||
@ -225,139 +258,139 @@ export class NpcType {
|
||||
|
||||
// Episode I Forest
|
||||
|
||||
NpcType.Hildebear = new NpcType(id++, 'Hildebear', 'Hildebear', true);
|
||||
NpcType.Hildeblue = new NpcType(id++, 'Hildeblue', 'Hildeblue', true);
|
||||
NpcType.RagRappy = new NpcType(id++, 'RagRappy', 'Rag Rappy', true);
|
||||
NpcType.AlRappy = new NpcType(id++, 'AlRappy', 'Al Rappy', true);
|
||||
NpcType.Monest = new NpcType(id++, 'Monest', 'Monest', true);
|
||||
NpcType.SavageWolf = new NpcType(id++, 'SavageWolf', 'Savage Wolf', true);
|
||||
NpcType.BarbarousWolf = new NpcType(id++, 'BarbarousWolf', 'Barbarous Wolf', true);
|
||||
NpcType.Booma = new NpcType(id++, 'Booma', 'Booma', true);
|
||||
NpcType.Gobooma = new NpcType(id++, 'Gobooma', 'Gobooma', true);
|
||||
NpcType.Gigobooma = new NpcType(id++, 'Gigobooma', 'Gigobooma', true);
|
||||
NpcType.Dragon = new NpcType(id++, 'Dragon', 'Dragon', true);
|
||||
NpcType.Hildebear = new NpcType(id++, 'Hildebear', 'Hildebear', 'Hildebear', 1, true);
|
||||
NpcType.Hildeblue = new NpcType(id++, 'Hildeblue', 'Hildeblue', 'Hildeblue', 1, true);
|
||||
NpcType.RagRappy = new NpcType(id++, 'RagRappy', 'Rag Rappy', 'Rag Rappy', 1, true);
|
||||
NpcType.AlRappy = new NpcType(id++, 'AlRappy', 'Al Rappy', 'Al Rappy', 1, true);
|
||||
NpcType.Monest = new NpcType(id++, 'Monest', 'Monest', 'Monest', 1, true);
|
||||
NpcType.SavageWolf = new NpcType(id++, 'SavageWolf', 'Savage Wolf', 'Savage Wolf', 1, true);
|
||||
NpcType.BarbarousWolf = new NpcType(id++, 'BarbarousWolf', 'Barbarous Wolf', 'Barbarous Wolf', 1, true);
|
||||
NpcType.Booma = new NpcType(id++, 'Booma', 'Booma', 'Booma', 1, true);
|
||||
NpcType.Gobooma = new NpcType(id++, 'Gobooma', 'Gobooma', 'Gobooma', 1, true);
|
||||
NpcType.Gigobooma = new NpcType(id++, 'Gigobooma', 'Gigobooma', 'Gigobooma', 1, true);
|
||||
NpcType.Dragon = new NpcType(id++, 'Dragon', 'Dragon', 'Dragon', 1, true);
|
||||
|
||||
// Episode I Caves
|
||||
|
||||
NpcType.GrassAssassin = new NpcType(id++, 'GrassAssassin', 'Grass Assassin', true);
|
||||
NpcType.PoisonLily = new NpcType(id++, 'PoisonLily', 'Poison Lily', true);
|
||||
NpcType.NarLily = new NpcType(id++, 'NarLily', 'Nar Lily', true);
|
||||
NpcType.NanoDragon = new NpcType(id++, 'NanoDragon', 'Nano Dragon', true);
|
||||
NpcType.EvilShark = new NpcType(id++, 'EvilShark', 'Evil Shark', true);
|
||||
NpcType.PalShark = new NpcType(id++, 'PalShark', 'Pal Shark', true);
|
||||
NpcType.GuilShark = new NpcType(id++, 'GuilShark', 'Guil Shark', true);
|
||||
NpcType.PofuillySlime = new NpcType(id++, 'PofuillySlime', 'Pofuilly Slime', true);
|
||||
NpcType.PouillySlime = new NpcType(id++, 'PouillySlime', 'Pouilly Slime', true);
|
||||
NpcType.PanArms = new NpcType(id++, 'PanArms', 'Pan Arms', true);
|
||||
NpcType.DeRolLe = new NpcType(id++, 'DeRolLe', 'De Rol Le', true);
|
||||
NpcType.GrassAssassin = new NpcType(id++, 'GrassAssassin', 'Grass Assassin', 'Grass Assassin', 1, true);
|
||||
NpcType.PoisonLily = new NpcType(id++, 'PoisonLily', 'Poison Lily', 'Poison Lily', 1, true);
|
||||
NpcType.NarLily = new NpcType(id++, 'NarLily', 'Nar Lily', 'Nar Lily', 1, true);
|
||||
NpcType.NanoDragon = new NpcType(id++, 'NanoDragon', 'Nano Dragon', 'Nano Dragon', 1, true);
|
||||
NpcType.EvilShark = new NpcType(id++, 'EvilShark', 'Evil Shark', 'Evil Shark', 1, true);
|
||||
NpcType.PalShark = new NpcType(id++, 'PalShark', 'Pal Shark', 'Pal Shark', 1, true);
|
||||
NpcType.GuilShark = new NpcType(id++, 'GuilShark', 'Guil Shark', 'Guil Shark', 1, true);
|
||||
NpcType.PofuillySlime = new NpcType(id++, 'PofuillySlime', 'Pofuilly Slime', 'Pofuilly Slime', 1, true);
|
||||
NpcType.PouillySlime = new NpcType(id++, 'PouillySlime', 'Pouilly Slime', 'Pouilly Slime', 1, true);
|
||||
NpcType.PanArms = new NpcType(id++, 'PanArms', 'Pan Arms', 'Pan Arms', 1, true);
|
||||
NpcType.DeRolLe = new NpcType(id++, 'DeRolLe', 'De Rol Le', 'De Rol Le', 1, true);
|
||||
|
||||
// Episode I Mines
|
||||
|
||||
NpcType.Dubchic = new NpcType(id++, 'Dubchic', 'Dubchic', true);
|
||||
NpcType.Gilchic = new NpcType(id++, 'Gilchic', 'Gilchic', true);
|
||||
NpcType.Garanz = new NpcType(id++, 'Garanz', 'Garanz', true);
|
||||
NpcType.SinowBeat = new NpcType(id++, 'SinowBeat', 'Sinow Beat', true);
|
||||
NpcType.SinowGold = new NpcType(id++, 'SinowGold', 'Sinow Gold', true);
|
||||
NpcType.Canadine = new NpcType(id++, 'Canadine', 'Canadine', true);
|
||||
NpcType.Canane = new NpcType(id++, 'Canane', 'Canane', true);
|
||||
NpcType.Dubswitch = new NpcType(id++, 'Dubswitch', 'Dubswitch', true);
|
||||
NpcType.VolOpt = new NpcType(id++, 'VolOpt', 'Vol Opt', true);
|
||||
NpcType.Dubchic = new NpcType(id++, 'Dubchic', 'Dubchic', 'Dubchic', 1, true);
|
||||
NpcType.Gilchic = new NpcType(id++, 'Gilchic', 'Gilchic', 'Gilchic', 1, true);
|
||||
NpcType.Garanz = new NpcType(id++, 'Garanz', 'Garanz', 'Garanz', 1, true);
|
||||
NpcType.SinowBeat = new NpcType(id++, 'SinowBeat', 'Sinow Beat', 'Sinow Beat', 1, true);
|
||||
NpcType.SinowGold = new NpcType(id++, 'SinowGold', 'Sinow Gold', 'Sinow Gold', 1, true);
|
||||
NpcType.Canadine = new NpcType(id++, 'Canadine', 'Canadine', 'Canadine', 1, true);
|
||||
NpcType.Canane = new NpcType(id++, 'Canane', 'Canane', 'Canane', 1, true);
|
||||
NpcType.Dubswitch = new NpcType(id++, 'Dubswitch', 'Dubswitch', 'Dubswitch', 1, true);
|
||||
NpcType.VolOpt = new NpcType(id++, 'VolOpt', 'Vol Opt', 'Vol Opt', 1, true);
|
||||
|
||||
// Episode I Ruins
|
||||
|
||||
NpcType.Delsaber = new NpcType(id++, 'Delsaber', 'Delsaber', true);
|
||||
NpcType.ChaosSorcerer = new NpcType(id++, 'ChaosSorcerer', 'Chaos Sorcerer', true);
|
||||
NpcType.DarkGunner = new NpcType(id++, 'DarkGunner', 'Dark Gunner', true);
|
||||
NpcType.ChaosBringer = new NpcType(id++, 'ChaosBringer', 'Chaos Bringer', true);
|
||||
NpcType.DarkBelra = new NpcType(id++, 'DarkBelra', 'Dark Belra', true);
|
||||
NpcType.Dimenian = new NpcType(id++, 'Dimenian', 'Dimenian', true);
|
||||
NpcType.LaDimenian = new NpcType(id++, 'LaDimenian', 'La Dimenian', true);
|
||||
NpcType.SoDimenian = new NpcType(id++, 'SoDimenian', 'So Dimenian', true);
|
||||
NpcType.Bulclaw = new NpcType(id++, 'Bulclaw', 'Bulclaw', true);
|
||||
NpcType.Claw = new NpcType(id++, 'Claw', 'Claw', true);
|
||||
NpcType.DarkFalz = new NpcType(id++, 'DarkFalz', 'Dark Falz', true);
|
||||
NpcType.Delsaber = new NpcType(id++, 'Delsaber', 'Delsaber', 'Delsaber', 1, true);
|
||||
NpcType.ChaosSorcerer = new NpcType(id++, 'ChaosSorcerer', 'Chaos Sorcerer', 'Chaos Sorcerer', 1, true);
|
||||
NpcType.DarkGunner = new NpcType(id++, 'DarkGunner', 'Dark Gunner', 'Dark Gunner', 1, true);
|
||||
NpcType.ChaosBringer = new NpcType(id++, 'ChaosBringer', 'Chaos Bringer', 'Chaos Bringer', 1, true);
|
||||
NpcType.DarkBelra = new NpcType(id++, 'DarkBelra', 'Dark Belra', 'Dark Belra', 1, true);
|
||||
NpcType.Dimenian = new NpcType(id++, 'Dimenian', 'Dimenian', 'Dimenian', 1, true);
|
||||
NpcType.LaDimenian = new NpcType(id++, 'LaDimenian', 'La Dimenian', 'La Dimenian', 1, true);
|
||||
NpcType.SoDimenian = new NpcType(id++, 'SoDimenian', 'So Dimenian', 'So Dimenian', 1, true);
|
||||
NpcType.Bulclaw = new NpcType(id++, 'Bulclaw', 'Bulclaw', 'Bulclaw', 1, true);
|
||||
NpcType.Claw = new NpcType(id++, 'Claw', 'Claw', 'Claw', 1, true);
|
||||
NpcType.DarkFalz = new NpcType(id++, 'DarkFalz', 'Dark Falz', 'Dark Falz', 1, true);
|
||||
|
||||
// Episode II VR Temple
|
||||
|
||||
NpcType.Hildebear2 = new NpcType(id++, 'Hildebear2', 'Hildebear (Ep. II)', true);
|
||||
NpcType.Hildeblue2 = new NpcType(id++, 'Hildeblue2', 'Hildeblue (Ep. II)', true);
|
||||
NpcType.RagRappy2 = new NpcType(id++, 'RagRappy2', 'Rag Rappy (Ep. II)', true);
|
||||
NpcType.LoveRappy = new NpcType(id++, 'LoveRappy', 'Love Rappy', true);
|
||||
NpcType.Monest2 = new NpcType(id++, 'Monest2', 'Monest (Ep. II)', true);
|
||||
NpcType.PoisonLily2 = new NpcType(id++, 'PoisonLily2', 'Poison Lily (Ep. II)', true);
|
||||
NpcType.NarLily2 = new NpcType(id++, 'NarLily2', 'Nar Lily (Ep. II)', true);
|
||||
NpcType.GrassAssassin2 = new NpcType(id++, 'GrassAssassin2', 'Grass Assassin (Ep. II)', true);
|
||||
NpcType.Dimenian2 = new NpcType(id++, 'Dimenian2', 'Dimenian (Ep. II)', true);
|
||||
NpcType.LaDimenian2 = new NpcType(id++, 'LaDimenian2', 'La Dimenian (Ep. II)', true);
|
||||
NpcType.SoDimenian2 = new NpcType(id++, 'SoDimenian2', 'So Dimenian (Ep. II)', true);
|
||||
NpcType.DarkBelra2 = new NpcType(id++, 'DarkBelra2', 'Dark Belra (Ep. II)', true);
|
||||
NpcType.BarbaRay = new NpcType(id++, 'BarbaRay', 'Barba Ray', true);
|
||||
NpcType.Hildebear2 = new NpcType(id++, 'Hildebear2', 'Hildebear', 'Hildebear (Ep. II)', 2, true);
|
||||
NpcType.Hildeblue2 = new NpcType(id++, 'Hildeblue2', 'Hildeblue', 'Hildeblue (Ep. II)', 2, true);
|
||||
NpcType.RagRappy2 = new NpcType(id++, 'RagRappy2', 'Rag Rappy', 'Rag Rappy (Ep. II)', 2, true);
|
||||
NpcType.LoveRappy = new NpcType(id++, 'LoveRappy', 'Love Rappy', 'Love Rappy', 2, true);
|
||||
NpcType.Monest2 = new NpcType(id++, 'Monest2', 'Monest', 'Monest (Ep. II)', 2, true);
|
||||
NpcType.PoisonLily2 = new NpcType(id++, 'PoisonLily2', 'Poison Lily', 'Poison Lily (Ep. II)', 2, true);
|
||||
NpcType.NarLily2 = new NpcType(id++, 'NarLily2', 'Nar Lily', 'Nar Lily (Ep. II)', 2, true);
|
||||
NpcType.GrassAssassin2 = new NpcType(id++, 'GrassAssassin2', 'Grass Assassin', 'Grass Assassin (Ep. II)', 2, true);
|
||||
NpcType.Dimenian2 = new NpcType(id++, 'Dimenian2', 'Dimenian', 'Dimenian (Ep. II)', 2, true);
|
||||
NpcType.LaDimenian2 = new NpcType(id++, 'LaDimenian2', 'La Dimenian', 'La Dimenian (Ep. II)', 2, true);
|
||||
NpcType.SoDimenian2 = new NpcType(id++, 'SoDimenian2', 'So Dimenian', 'So Dimenian (Ep. II)', 2, true);
|
||||
NpcType.DarkBelra2 = new NpcType(id++, 'DarkBelra2', 'Dark Belra', 'Dark Belra (Ep. II)', 2, true);
|
||||
NpcType.BarbaRay = new NpcType(id++, 'BarbaRay', 'Barba Ray', 'Barba Ray', 2, true);
|
||||
|
||||
// Episode II VR Spaceship
|
||||
|
||||
NpcType.SavageWolf2 = new NpcType(id++, 'SavageWolf2', 'Savage Wolf (Ep. II)', true);
|
||||
NpcType.BarbarousWolf2 = new NpcType(id++, 'BarbarousWolf2', 'Barbarous Wolf (Ep. II)', true);
|
||||
NpcType.PanArms2 = new NpcType(id++, 'PanArms2', 'Pan Arms (Ep. II)', true);
|
||||
NpcType.Dubchic2 = new NpcType(id++, 'Dubchic2', 'Dubchic (Ep. II)', true);
|
||||
NpcType.Gilchic2 = new NpcType(id++, 'Gilchic2', 'Gilchic (Ep. II)', true);
|
||||
NpcType.Garanz2 = new NpcType(id++, 'Garanz2', 'Garanz (Ep. II)', true);
|
||||
NpcType.Dubswitch2 = new NpcType(id++, 'Dubswitch2', 'Dubswitch (Ep. II)', true);
|
||||
NpcType.Delsaber2 = new NpcType(id++, 'Delsaber2', 'Delsaber (Ep. II)', true);
|
||||
NpcType.ChaosSorcerer2 = new NpcType(id++, 'ChaosSorcerer2', 'Chaos Sorcerer (Ep. II)', true);
|
||||
NpcType.GolDragon = new NpcType(id++, 'GolDragon', 'Gol Dragon', true);
|
||||
NpcType.SavageWolf2 = new NpcType(id++, 'SavageWolf2', 'Savage Wolf', 'Savage Wolf (Ep. II)', 2, true);
|
||||
NpcType.BarbarousWolf2 = new NpcType(id++, 'BarbarousWolf2', 'Barbarous Wolf', 'Barbarous Wolf (Ep. II)', 2, true);
|
||||
NpcType.PanArms2 = new NpcType(id++, 'PanArms2', 'Pan Arms', 'Pan Arms (Ep. II)', 2, true);
|
||||
NpcType.Dubchic2 = new NpcType(id++, 'Dubchic2', 'Dubchic', 'Dubchic (Ep. II)', 2, true);
|
||||
NpcType.Gilchic2 = new NpcType(id++, 'Gilchic2', 'Gilchic', 'Gilchic (Ep. II)', 2, true);
|
||||
NpcType.Garanz2 = new NpcType(id++, 'Garanz2', 'Garanz', 'Garanz (Ep. II)', 2, true);
|
||||
NpcType.Dubswitch2 = new NpcType(id++, 'Dubswitch2', 'Dubswitch', 'Dubswitch (Ep. II)', 2, true);
|
||||
NpcType.Delsaber2 = new NpcType(id++, 'Delsaber2', 'Delsaber', 'Delsaber (Ep. II)', 2, true);
|
||||
NpcType.ChaosSorcerer2 = new NpcType(id++, 'ChaosSorcerer2', 'Chaos Sorcerer', 'Chaos Sorcerer (Ep. II)', 2, true);
|
||||
NpcType.GolDragon = new NpcType(id++, 'GolDragon', 'Gol Dragon', 'Gol Dragon', 2, true);
|
||||
|
||||
// Episode II Central Control Area
|
||||
|
||||
NpcType.SinowBerill = new NpcType(id++, 'SinowBerill', 'Sinow Berill', true);
|
||||
NpcType.SinowSpigell = new NpcType(id++, 'SinowSpigell', 'Sinow Spigell', true);
|
||||
NpcType.Merillia = new NpcType(id++, 'Merillia', 'Merillia', true);
|
||||
NpcType.Meriltas = new NpcType(id++, 'Meriltas', 'Meriltas', true);
|
||||
NpcType.Mericarol = new NpcType(id++, 'Mericarol', 'Mericarol', true);
|
||||
NpcType.Mericus = new NpcType(id++, 'Mericus', 'Mericus', true);
|
||||
NpcType.Merikle = new NpcType(id++, 'Merikle', 'Merikle', true);
|
||||
NpcType.UlGibbon = new NpcType(id++, 'UlGibbon', 'Ul Gibbon', true);
|
||||
NpcType.ZolGibbon = new NpcType(id++, 'ZolGibbon', 'Zol Gibbon', true);
|
||||
NpcType.Gibbles = new NpcType(id++, 'Gibbles', 'Gibbles', true);
|
||||
NpcType.Gee = new NpcType(id++, 'Gee', 'Gee', true);
|
||||
NpcType.GiGue = new NpcType(id++, 'GiGue', 'Gi Gue', true);
|
||||
NpcType.GalGryphon = new NpcType(id++, 'GalGryphon', 'Gal Gryphon', true);
|
||||
NpcType.SinowBerill = new NpcType(id++, 'SinowBerill', 'Sinow Berill', 'Sinow Berill', 2, true);
|
||||
NpcType.SinowSpigell = new NpcType(id++, 'SinowSpigell', 'Sinow Spigell', 'Sinow Spigell', 2, true);
|
||||
NpcType.Merillia = new NpcType(id++, 'Merillia', 'Merillia', 'Merillia', 2, true);
|
||||
NpcType.Meriltas = new NpcType(id++, 'Meriltas', 'Meriltas', 'Meriltas', 2, true);
|
||||
NpcType.Mericarol = new NpcType(id++, 'Mericarol', 'Mericarol', 'Mericarol', 2, true);
|
||||
NpcType.Mericus = new NpcType(id++, 'Mericus', 'Mericus', 'Mericus', 2, true);
|
||||
NpcType.Merikle = new NpcType(id++, 'Merikle', 'Merikle', 'Merikle', 2, true);
|
||||
NpcType.UlGibbon = new NpcType(id++, 'UlGibbon', 'Ul Gibbon', 'Ul Gibbon', 2, true);
|
||||
NpcType.ZolGibbon = new NpcType(id++, 'ZolGibbon', 'Zol Gibbon', 'Zol Gibbon', 2, true);
|
||||
NpcType.Gibbles = new NpcType(id++, 'Gibbles', 'Gibbles', 'Gibbles', 2, true);
|
||||
NpcType.Gee = new NpcType(id++, 'Gee', 'Gee', 'Gee', 2, true);
|
||||
NpcType.GiGue = new NpcType(id++, 'GiGue', 'Gi Gue', 'Gi Gue', 2, true);
|
||||
NpcType.GalGryphon = new NpcType(id++, 'GalGryphon', 'Gal Gryphon', 'Gal Gryphon', 2, true);
|
||||
|
||||
// Episode II Seabed
|
||||
|
||||
NpcType.Deldepth = new NpcType(id++, 'Deldepth', 'Deldepth', true);
|
||||
NpcType.Delbiter = new NpcType(id++, 'Delbiter', 'Delbiter', true);
|
||||
NpcType.Dolmolm = new NpcType(id++, 'Dolmolm', 'Dolmolm', true);
|
||||
NpcType.Dolmdarl = new NpcType(id++, 'Dolmdarl', 'Dolmdarl', true);
|
||||
NpcType.Morfos = new NpcType(id++, 'Morfos', 'Morfos', true);
|
||||
NpcType.Recobox = new NpcType(id++, 'Recobox', 'Recobox', true);
|
||||
NpcType.Epsilon = new NpcType(id++, 'Epsilon', 'Epsilon', true);
|
||||
NpcType.SinowZoa = new NpcType(id++, 'SinowZoa', 'Sinow Zoa', true);
|
||||
NpcType.SinowZele = new NpcType(id++, 'SinowZele', 'Sinow Zele', true);
|
||||
NpcType.IllGill = new NpcType(id++, 'IllGill', 'Ill Gill', true);
|
||||
NpcType.DelLily = new NpcType(id++, 'DelLily', 'Del Lily', true);
|
||||
NpcType.OlgaFlow = new NpcType(id++, 'OlgaFlow', 'Olga Flow', true);
|
||||
NpcType.Deldepth = new NpcType(id++, 'Deldepth', 'Deldepth', 'Deldepth', 2, true);
|
||||
NpcType.Delbiter = new NpcType(id++, 'Delbiter', 'Delbiter', 'Delbiter', 2, true);
|
||||
NpcType.Dolmolm = new NpcType(id++, 'Dolmolm', 'Dolmolm', 'Dolmolm', 2, true);
|
||||
NpcType.Dolmdarl = new NpcType(id++, 'Dolmdarl', 'Dolmdarl', 'Dolmdarl', 2, true);
|
||||
NpcType.Morfos = new NpcType(id++, 'Morfos', 'Morfos', 'Morfos', 2, true);
|
||||
NpcType.Recobox = new NpcType(id++, 'Recobox', 'Recobox', 'Recobox', 2, true);
|
||||
NpcType.Epsilon = new NpcType(id++, 'Epsilon', 'Epsilon', 'Epsilon', 2, true);
|
||||
NpcType.SinowZoa = new NpcType(id++, 'SinowZoa', 'Sinow Zoa', 'Sinow Zoa', 2, true);
|
||||
NpcType.SinowZele = new NpcType(id++, 'SinowZele', 'Sinow Zele', 'Sinow Zele', 2, true);
|
||||
NpcType.IllGill = new NpcType(id++, 'IllGill', 'Ill Gill', 'Ill Gill', 2, true);
|
||||
NpcType.DelLily = new NpcType(id++, 'DelLily', 'Del Lily', 'Del Lily', 2, true);
|
||||
NpcType.OlgaFlow = new NpcType(id++, 'OlgaFlow', 'Olga Flow', 'Olga Flow', 2, true);
|
||||
|
||||
// Episode IV
|
||||
|
||||
NpcType.SandRappy = new NpcType(id++, 'SandRappy', 'Sand Rappy', true);
|
||||
NpcType.DelRappy = new NpcType(id++, 'DelRappy', 'Del Rappy', true);
|
||||
NpcType.Astark = new NpcType(id++, 'Astark', 'Astark', true);
|
||||
NpcType.SatelliteLizard = new NpcType(id++, 'SatelliteLizard', 'Satellite Lizard', true);
|
||||
NpcType.Yowie = new NpcType(id++, 'Yowie', 'Yowie', true);
|
||||
NpcType.MerissaA = new NpcType(id++, 'MerissaA', 'Merissa A', true);
|
||||
NpcType.MerissaAA = new NpcType(id++, 'MerissaAA', 'Merissa AA', true);
|
||||
NpcType.Girtablulu = new NpcType(id++, 'Girtablulu', 'Girtablulu', true);
|
||||
NpcType.Zu = new NpcType(id++, 'Zu', 'Zu', true);
|
||||
NpcType.Pazuzu = new NpcType(id++, 'Pazuzu', 'Pazuzu', true);
|
||||
NpcType.Boota = new NpcType(id++, 'Boota', 'Boota', true);
|
||||
NpcType.ZeBoota = new NpcType(id++, 'ZeBoota', 'Ze Boota', true);
|
||||
NpcType.BaBoota = new NpcType(id++, 'BaBoota', 'Ba Boota', true);
|
||||
NpcType.Dorphon = new NpcType(id++, 'Dorphon', 'Dorphon', true);
|
||||
NpcType.DorphonEclair = new NpcType(id++, 'DorphonEclair', 'Dorphon Eclair', true);
|
||||
NpcType.Goran = new NpcType(id++, 'Goran', 'Goran', true);
|
||||
NpcType.PyroGoran = new NpcType(id++, 'PyroGoran', 'Pyro Goran', true);
|
||||
NpcType.GoranDetonator = new NpcType(id++, 'GoranDetonator', 'Goran Detonator', true);
|
||||
NpcType.SaintMillion = new NpcType(id++, 'SaintMillion', 'Saint-Million', true);
|
||||
NpcType.Shambertin = new NpcType(id++, 'Shambertin', 'Shambertin', true);
|
||||
NpcType.Kondrieu = new NpcType(id++, 'Kondrieu', 'Kondrieu', true);
|
||||
} ());
|
||||
NpcType.SandRappy = new NpcType(id++, 'SandRappy', 'Sand Rappy', 'Sand Rappy', 4, true);
|
||||
NpcType.DelRappy = new NpcType(id++, 'DelRappy', 'Del Rappy', 'Del Rappy', 4, true);
|
||||
NpcType.Astark = new NpcType(id++, 'Astark', 'Astark', 'Astark', 4, true);
|
||||
NpcType.SatelliteLizard = new NpcType(id++, 'SatelliteLizard', 'Satellite Lizard', 'Satellite Lizard', 4, true);
|
||||
NpcType.Yowie = new NpcType(id++, 'Yowie', 'Yowie', 'Yowie', 4, true);
|
||||
NpcType.MerissaA = new NpcType(id++, 'MerissaA', 'Merissa A', 'Merissa A', 4, true);
|
||||
NpcType.MerissaAA = new NpcType(id++, 'MerissaAA', 'Merissa AA', 'Merissa AA', 4, true);
|
||||
NpcType.Girtablulu = new NpcType(id++, 'Girtablulu', 'Girtablulu', 'Girtablulu', 4, true);
|
||||
NpcType.Zu = new NpcType(id++, 'Zu', 'Zu', 'Zu', 4, true);
|
||||
NpcType.Pazuzu = new NpcType(id++, 'Pazuzu', 'Pazuzu', 'Pazuzu', 4, true);
|
||||
NpcType.Boota = new NpcType(id++, 'Boota', 'Boota', 'Boota', 4, true);
|
||||
NpcType.ZeBoota = new NpcType(id++, 'ZeBoota', 'Ze Boota', 'Ze Boota', 4, true);
|
||||
NpcType.BaBoota = new NpcType(id++, 'BaBoota', 'Ba Boota', 'Ba Boota', 4, true);
|
||||
NpcType.Dorphon = new NpcType(id++, 'Dorphon', 'Dorphon', 'Dorphon', 4, true);
|
||||
NpcType.DorphonEclair = new NpcType(id++, 'DorphonEclair', 'Dorphon Eclair', 'Dorphon Eclair', 4, true);
|
||||
NpcType.Goran = new NpcType(id++, 'Goran', 'Goran', 'Goran', 4, true);
|
||||
NpcType.PyroGoran = new NpcType(id++, 'PyroGoran', 'Pyro Goran', 'Pyro Goran', 4, true);
|
||||
NpcType.GoranDetonator = new NpcType(id++, 'GoranDetonator', 'Goran Detonator', 'Goran Detonator', 4, true);
|
||||
NpcType.SaintMillion = new NpcType(id++, 'SaintMillion', 'Saint-Million', 'Saint-Million', 4, true);
|
||||
NpcType.Shambertin = new NpcType(id++, 'Shambertin', 'Shambertin', 'Shambertin', 4, true);
|
||||
NpcType.Kondrieu = new NpcType(id++, 'Kondrieu', 'Kondrieu', 'Kondrieu', 4, true);
|
||||
}());
|
||||
|
@ -111,7 +111,10 @@ export class Quest {
|
||||
}
|
||||
}
|
||||
|
||||
export class VisibleQuestEntity {
|
||||
/**
|
||||
* Abstract class from which QuestNpc and QuestObject derive.
|
||||
*/
|
||||
export class QuestEntity {
|
||||
@observable areaId: number;
|
||||
|
||||
private _sectionId: number;
|
||||
@ -174,7 +177,7 @@ export class VisibleQuestEntity {
|
||||
position: Vec3,
|
||||
rotation: Vec3
|
||||
) {
|
||||
if (Object.getPrototypeOf(this) === Object.getPrototypeOf(VisibleQuestEntity))
|
||||
if (Object.getPrototypeOf(this) === Object.getPrototypeOf(QuestEntity))
|
||||
throw new Error('Abstract class should not be instantiated directly.');
|
||||
if (!Number.isInteger(areaId) || areaId < 0)
|
||||
throw new Error(`Expected areaId to be a non-negative integer, got ${areaId}.`);
|
||||
@ -190,7 +193,7 @@ export class VisibleQuestEntity {
|
||||
}
|
||||
}
|
||||
|
||||
export class QuestObject extends VisibleQuestEntity {
|
||||
export class QuestObject extends QuestEntity {
|
||||
@observable type: ObjectType;
|
||||
/**
|
||||
* The raw data from a DAT file.
|
||||
@ -214,7 +217,7 @@ export class QuestObject extends VisibleQuestEntity {
|
||||
}
|
||||
}
|
||||
|
||||
export class QuestNpc extends VisibleQuestEntity {
|
||||
export class QuestNpc extends QuestEntity {
|
||||
@observable type: NpcType;
|
||||
/**
|
||||
* The raw data from a DAT file.
|
||||
@ -269,3 +272,31 @@ export class AreaVariant {
|
||||
export class Item {
|
||||
constructor(public name: string) { }
|
||||
}
|
||||
|
||||
export class HuntMethod {
|
||||
constructor(
|
||||
public quest: SimpleQuest
|
||||
) { }
|
||||
}
|
||||
|
||||
export class SimpleQuest {
|
||||
enemies: SimpleNpc[];
|
||||
|
||||
constructor(
|
||||
public name: string,
|
||||
public npcs: SimpleNpc[]
|
||||
) {
|
||||
if (!name) throw new Error('name is required.');
|
||||
if (!npcs) throw new Error('npcs is required.');
|
||||
|
||||
this.enemies = npcs.filter(npc => npc.type.enemy);
|
||||
}
|
||||
}
|
||||
|
||||
export class SimpleNpc {
|
||||
constructor(
|
||||
public type: NpcType
|
||||
) {
|
||||
if (!type) throw new Error('type is required.');
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ import {
|
||||
MeshLambertMaterial
|
||||
} from 'three';
|
||||
import OrbitControlsCreator from 'three-orbit-controls';
|
||||
import { Vec3, Area, Quest, VisibleQuestEntity, QuestObject, QuestNpc, Section } from '../domain';
|
||||
import { Vec3, Area, Quest, QuestEntity, QuestObject, QuestNpc, Section } from '../domain';
|
||||
import { getAreaCollisionGeometry, getAreaRenderGeometry } from '../data/loading/areas';
|
||||
import {
|
||||
OBJECT_COLOR,
|
||||
@ -32,7 +32,7 @@ const OrbitControls = OrbitControlsCreator(THREE);
|
||||
|
||||
interface PickEntityResult {
|
||||
object: Mesh;
|
||||
entity: VisibleQuestEntity;
|
||||
entity: QuestEntity;
|
||||
grabOffset: Vector3;
|
||||
dragAdjust: Vector3;
|
||||
dragY: number;
|
||||
@ -464,7 +464,7 @@ export class Renderer {
|
||||
return {};
|
||||
}
|
||||
|
||||
private getColor(entity: VisibleQuestEntity, type: 'normal' | 'hover' | 'selected') {
|
||||
private getColor(entity: QuestEntity, type: 'normal' | 'hover' | 'selected') {
|
||||
const isNpc = entity instanceof QuestNpc;
|
||||
|
||||
switch (type) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { autorun } from 'mobx';
|
||||
import { BufferGeometry, DoubleSide, Mesh, MeshLambertMaterial } from 'three';
|
||||
import { QuestNpc, QuestObject, VisibleQuestEntity } from '../domain';
|
||||
import { QuestNpc, QuestObject, QuestEntity } from '../domain';
|
||||
|
||||
export const OBJECT_COLOR = 0xFFFF00;
|
||||
export const OBJECT_HOVER_COLOR = 0xFFDF3F;
|
||||
@ -18,7 +18,7 @@ export function createNpcMesh(npc: QuestNpc, geometry: BufferGeometry): Mesh {
|
||||
}
|
||||
|
||||
function createMesh(
|
||||
entity: VisibleQuestEntity,
|
||||
entity: QuestEntity,
|
||||
geometry: BufferGeometry,
|
||||
color: number,
|
||||
type: string
|
||||
|
8
src/stores/HuntMethodStore.ts
Normal file
8
src/stores/HuntMethodStore.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { observable, IObservableArray } from "mobx";
|
||||
import { HuntMethod } from "../domain";
|
||||
|
||||
class HuntMethodStore {
|
||||
@observable methods: IObservableArray<HuntMethod> = observable.array();
|
||||
}
|
||||
|
||||
export const huntMethodStore = new HuntMethodStore();
|
@ -1,12 +1,12 @@
|
||||
import { observable } from 'mobx';
|
||||
import { Object3D } from 'three';
|
||||
import { Area, Quest, VisibleQuestEntity } from '../domain';
|
||||
import { Area, Quest, QuestEntity } from '../domain';
|
||||
|
||||
class QuestEditorStore {
|
||||
@observable currentModel?: Object3D;
|
||||
@observable currentQuest?: Quest;
|
||||
@observable currentArea?: Area;
|
||||
@observable selectedEntity?: VisibleQuestEntity;
|
||||
@observable selectedEntity?: QuestEntity;
|
||||
}
|
||||
|
||||
export const questEditorStore = new QuestEditorStore();
|
||||
|
@ -1,8 +1,4 @@
|
||||
.HuntOptimizerComponent {
|
||||
.ho-HuntOptimizerComponent {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.HuntOptimizerComponent-wanted-items {
|
||||
margin: 10px;
|
||||
}
|
@ -1,84 +1,20 @@
|
||||
import { Select, Table, Button } from "antd";
|
||||
import { observable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import React from "react";
|
||||
import { loadItems } from "../../actions/items";
|
||||
import { Item } from "../../domain";
|
||||
import { itemStore } from "../../stores/ItemStore";
|
||||
import './HuntOptimizerComponent.css';
|
||||
import { WantedItemsComponent } from "./WantedItemsComponent";
|
||||
import { loadItems } from "../../actions/items";
|
||||
import { loadHuntMethods } from "../../actions/huntMethods";
|
||||
|
||||
export function HuntOptimizerComponent() {
|
||||
return (
|
||||
<section className="HuntOptimizerComponent">
|
||||
<WantedItemsComponent />
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
class WantedItem {
|
||||
@observable item: Item;
|
||||
@observable amount: number;
|
||||
|
||||
constructor(item: Item, amount: number) {
|
||||
this.item = item;
|
||||
this.amount = amount;
|
||||
}
|
||||
}
|
||||
|
||||
@observer
|
||||
class WantedItemsComponent extends React.Component {
|
||||
@observable private wantedItems: Array<WantedItem> = [];
|
||||
|
||||
export class HuntOptimizerComponent extends React.Component {
|
||||
componentDidMount() {
|
||||
loadItems('ephinea');
|
||||
loadHuntMethods('ephinea');
|
||||
}
|
||||
|
||||
render() {
|
||||
// Make sure render is called on updates.
|
||||
this.wantedItems.slice(0, 0);
|
||||
|
||||
return (
|
||||
<section className="HuntOptimizerComponent-wanted-items">
|
||||
<h2>Wanted Items</h2>
|
||||
<Select
|
||||
value={undefined}
|
||||
showSearch
|
||||
placeholder="Add an item"
|
||||
optionFilterProp="children"
|
||||
style={{ width: 200 }}
|
||||
filterOption
|
||||
onChange={this.addWanted}
|
||||
>
|
||||
{itemStore.items.map(item => (
|
||||
<Select.Option key={item.name}>
|
||||
{item.name}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
<Table
|
||||
size="small"
|
||||
dataSource={this.wantedItems}
|
||||
rowKey={wanted => wanted.item.name}
|
||||
pagination={false}
|
||||
>
|
||||
<Table.Column title="Amount" dataIndex="amount" />
|
||||
<Table.Column title="Item" dataIndex="item.name" />
|
||||
<Table.Column
|
||||
render={() => (
|
||||
<Button type="link" icon="delete" />
|
||||
)}
|
||||
/>
|
||||
</Table>
|
||||
<section className="ho-HuntOptimizerComponent">
|
||||
<WantedItemsComponent />
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
private addWanted = (itemName: string) => {
|
||||
let added = this.wantedItems.find(w => w.item.name === itemName);
|
||||
|
||||
if (!added) {
|
||||
const item = itemStore.items.find(i => i.name === itemName)!;
|
||||
this.wantedItems.push(new WantedItem(item, 1));
|
||||
}
|
||||
}
|
||||
}
|
7
src/ui/hunt-optimizer/WantedItemsComponent.css
Normal file
7
src/ui/hunt-optimizer/WantedItemsComponent.css
Normal file
@ -0,0 +1,7 @@
|
||||
.ho-WantedItemsComponent {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.ho-WantedItemsComponent-table {
|
||||
margin-top: 10px;
|
||||
}
|
108
src/ui/hunt-optimizer/WantedItemsComponent.tsx
Normal file
108
src/ui/hunt-optimizer/WantedItemsComponent.tsx
Normal file
@ -0,0 +1,108 @@
|
||||
import { Button, InputNumber, Select, Table } from "antd";
|
||||
import { observable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import React from "react";
|
||||
import { Item } from "../../domain";
|
||||
import { itemStore } from "../../stores/ItemStore";
|
||||
import './WantedItemsComponent.css';
|
||||
|
||||
@observer
|
||||
export class WantedItemsComponent extends React.Component {
|
||||
@observable
|
||||
private wantedItems: Array<WantedItem> = [];
|
||||
|
||||
render() {
|
||||
// Make sure render is called on updates.
|
||||
this.wantedItems.slice(0, 0);
|
||||
|
||||
return (
|
||||
<section className="ho-WantedItemsComponent">
|
||||
<h2>Wanted Items</h2>
|
||||
<Select
|
||||
value={undefined}
|
||||
showSearch
|
||||
placeholder="Add an item"
|
||||
optionFilterProp="children"
|
||||
style={{ width: 200 }}
|
||||
filterOption
|
||||
onChange={this.addWanted}
|
||||
>
|
||||
{itemStore.items.map(item => (
|
||||
<Select.Option key={item.name}>
|
||||
{item.name}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
<Table
|
||||
className="ho-WantedItemsComponent-table"
|
||||
size="small"
|
||||
dataSource={this.wantedItems}
|
||||
rowKey={wanted => wanted.item.name}
|
||||
pagination={false}
|
||||
>
|
||||
<Table.Column<WantedItem>
|
||||
title="Amount"
|
||||
dataIndex="amount"
|
||||
render={(_, wanted) => (
|
||||
<WantedAmountCell wantedItem={wanted} />
|
||||
)}
|
||||
/>
|
||||
<Table.Column title="Item" dataIndex="item.name" />
|
||||
<Table.Column<WantedItem>
|
||||
render={(_, wanted) => (
|
||||
<Button type="link" icon="delete" onClick={this.removeWanted(wanted)} />
|
||||
)}
|
||||
/>
|
||||
</Table>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
private addWanted = (itemName: string) => {
|
||||
let added = this.wantedItems.find(w => w.item.name === itemName);
|
||||
|
||||
if (!added) {
|
||||
const item = itemStore.items.find(i => i.name === itemName)!;
|
||||
this.wantedItems.push(new WantedItem(item, 1));
|
||||
}
|
||||
};
|
||||
|
||||
private removeWanted = (wanted: WantedItem) => () => {
|
||||
const i = this.wantedItems.findIndex(w => w === wanted);
|
||||
|
||||
if (i !== -1) {
|
||||
this.wantedItems.splice(i, 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class WantedItem {
|
||||
@observable item: Item;
|
||||
@observable amount: number;
|
||||
|
||||
constructor(item: Item, amount: number) {
|
||||
this.item = item;
|
||||
this.amount = amount;
|
||||
}
|
||||
}
|
||||
|
||||
@observer
|
||||
class WantedAmountCell extends React.Component<{ wantedItem: WantedItem }> {
|
||||
render() {
|
||||
const wanted = this.props.wantedItem;
|
||||
|
||||
return (
|
||||
<InputNumber
|
||||
min={1}
|
||||
value={wanted.amount}
|
||||
onChange={this.wantedAmountChanged}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
private wantedAmountChanged = (value?: number) => {
|
||||
if (value && value >= 1) {
|
||||
this.props.wantedItem.amount = value;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
import { InputNumber } from 'antd';
|
||||
import { observer } from 'mobx-react';
|
||||
import React from 'react';
|
||||
import { QuestNpc, QuestObject, VisibleQuestEntity } from '../../domain';
|
||||
import { QuestNpc, QuestObject, QuestEntity } from '../../domain';
|
||||
import './EntityInfoComponent.css';
|
||||
|
||||
interface Props {
|
||||
entity?: VisibleQuestEntity;
|
||||
entity?: QuestEntity;
|
||||
}
|
||||
|
||||
@observer
|
||||
@ -79,7 +79,7 @@ export class EntityInfoComponent extends React.Component<Props> {
|
||||
|
||||
@observer
|
||||
class CoordRow extends React.Component<{
|
||||
entity: VisibleQuestEntity,
|
||||
entity: QuestEntity,
|
||||
positionType: 'position' | 'sectionPosition',
|
||||
coord: 'x' | 'y' | 'z'
|
||||
}> {
|
||||
|
Loading…
Reference in New Issue
Block a user