mirror of
https://github.com/DaanVandenBosch/phantasmal-world.git
synced 2025-04-04 22:58:29 +08:00
Set up basic LP algorithm to optimize hunts. Fixed errors in data.
This commit is contained in:
parent
734ed1016d
commit
72ecdac71d
2407
public/box_drops.ephinea.tsv
Normal file
2407
public/box_drops.ephinea.tsv
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
440
public/items.ephinea.tsv
Normal file
440
public/items.ephinea.tsv
Normal file
@ -0,0 +1,440 @@
|
|||||||
|
name
|
||||||
|
AddSlot
|
||||||
|
Agito (1975)
|
||||||
|
Agito (1977)
|
||||||
|
Agito (1980)
|
||||||
|
Agito (1983)
|
||||||
|
Agito (1991)
|
||||||
|
Agito (2001)
|
||||||
|
Alive Aqhu
|
||||||
|
Alliance Uniform
|
||||||
|
Amplifier of Anti
|
||||||
|
Amplifier of Barta
|
||||||
|
Amplifier of Blue
|
||||||
|
Amplifier of Deband
|
||||||
|
Amplifier of Foie
|
||||||
|
Amplifier of Gibarta
|
||||||
|
Amplifier of Gifoie
|
||||||
|
Amplifier of Gizonde
|
||||||
|
Amplifier of Rabarta
|
||||||
|
Amplifier of Rafoie
|
||||||
|
Amplifier of Razonde
|
||||||
|
Amplifier of Red
|
||||||
|
Amplifier of Resta
|
||||||
|
Amplifier of Shifta
|
||||||
|
Amplifier of Yellow
|
||||||
|
Amplifier of Zonde
|
||||||
|
Ancient Saber
|
||||||
|
Angel Harp
|
||||||
|
Angel/Luck
|
||||||
|
Angel/Mind
|
||||||
|
Angry Fist
|
||||||
|
Ano Bazooka
|
||||||
|
Ano Rifle
|
||||||
|
Anti Android Rifle
|
||||||
|
Anti-Light Ring
|
||||||
|
Arms
|
||||||
|
Assist Barrier
|
||||||
|
Asteron Belt
|
||||||
|
Asuka
|
||||||
|
Attribute Plate
|
||||||
|
Attribute Wall
|
||||||
|
Aura Field
|
||||||
|
Baton
|
||||||
|
Battle Verge
|
||||||
|
Beam
|
||||||
|
Belra's Right Arm
|
||||||
|
Berdys
|
||||||
|
Berdysh
|
||||||
|
Berill Photon
|
||||||
|
Black Hound Cuirass
|
||||||
|
Black Odoshi Domaru
|
||||||
|
Black Odoshi Red Nimaidou
|
||||||
|
Blade
|
||||||
|
Blade Dance
|
||||||
|
Blaster
|
||||||
|
Bloody Art
|
||||||
|
Blue Barrier
|
||||||
|
Blue Odoshi Violet Nimaidou
|
||||||
|
Bluefull Card
|
||||||
|
Book of Hitogata
|
||||||
|
Booma's Right Arm
|
||||||
|
Branch of Pakupaku
|
||||||
|
Bravace
|
||||||
|
Brave Hammer
|
||||||
|
Brave Knuckle
|
||||||
|
Breaker
|
||||||
|
Brightness Circle
|
||||||
|
Bringer's Right Arm
|
||||||
|
Brionac
|
||||||
|
Caduceus
|
||||||
|
Calibur
|
||||||
|
Cannon
|
||||||
|
Cannon Rouge
|
||||||
|
Celestial Armor
|
||||||
|
Centurion/Ability
|
||||||
|
Chain Sawd
|
||||||
|
Christmas Present
|
||||||
|
Cladding of Epsilon
|
||||||
|
Claymore
|
||||||
|
Clio
|
||||||
|
Club of Laconium
|
||||||
|
Club of Zumiuran
|
||||||
|
Combat Gear
|
||||||
|
Commander Uniform
|
||||||
|
Congeal Cloak
|
||||||
|
Crimson Coat
|
||||||
|
Cross Scar
|
||||||
|
Crush Bullet
|
||||||
|
Cure/Confuse
|
||||||
|
Cure/Freeze
|
||||||
|
Cure/Paralysis
|
||||||
|
Cure/Poison
|
||||||
|
Cure/Shock
|
||||||
|
Cure/Slow
|
||||||
|
Cursed Cloak
|
||||||
|
Custom Barrier ver.OO
|
||||||
|
Custom Frame ver.OO
|
||||||
|
Custom Ray ver.OO
|
||||||
|
Cutter
|
||||||
|
D-Parts ver1.01
|
||||||
|
D-Parts ver2.10
|
||||||
|
D-Photon Core
|
||||||
|
DB's Armor
|
||||||
|
DB's Saber
|
||||||
|
DB's Saber (3062)
|
||||||
|
DB's Saber (3064)
|
||||||
|
DB's Saber (3067)
|
||||||
|
DB's Saber (3069 Chris)
|
||||||
|
DB's Saber (3069 Torato)
|
||||||
|
DB's Saber (3070)
|
||||||
|
DB's Saber (3073)
|
||||||
|
DB's Saber (3075)
|
||||||
|
DB's Saber (3077)
|
||||||
|
DB's Shield
|
||||||
|
DF Field
|
||||||
|
DF Shield
|
||||||
|
Daylight Scar
|
||||||
|
De Rol Le Shell
|
||||||
|
Def Material
|
||||||
|
Delsaber's Left Arm
|
||||||
|
Delsaber's Right Arm
|
||||||
|
Demolition Comet
|
||||||
|
Demonic Fork
|
||||||
|
Devil/Battle
|
||||||
|
Devil/Technique
|
||||||
|
Diska
|
||||||
|
Diska of Braveman
|
||||||
|
Diska of Liberator
|
||||||
|
Divine Protection
|
||||||
|
Double Saber
|
||||||
|
Dragon Scale
|
||||||
|
Dragon Slayer
|
||||||
|
Dragon's Claw
|
||||||
|
Dragon/HP
|
||||||
|
Dress Plate
|
||||||
|
Durandal
|
||||||
|
Earth Wand: Brownie
|
||||||
|
Easter Egg
|
||||||
|
Edge
|
||||||
|
Electro Frame
|
||||||
|
Elysion
|
||||||
|
Evade Material
|
||||||
|
Evil Curst
|
||||||
|
Fatsia
|
||||||
|
Final Impact
|
||||||
|
Fire Scepter: Agni
|
||||||
|
Flamberge
|
||||||
|
Flame Garment
|
||||||
|
Flame Visit
|
||||||
|
Flapjack Flapper
|
||||||
|
Flight Cutter
|
||||||
|
Flight Fan
|
||||||
|
Flowen's Frame
|
||||||
|
Flowen's Shield
|
||||||
|
Flowen's Sword
|
||||||
|
Flowen's Sword (3060)
|
||||||
|
Flowen's Sword (3064)
|
||||||
|
Flowen's Sword (3067)
|
||||||
|
Flowen's Sword (3073)
|
||||||
|
Flowen's Sword (3077)
|
||||||
|
Flowen's Sword (3079)
|
||||||
|
Flowen's Sword (3082)
|
||||||
|
Flowen's Sword (3083)
|
||||||
|
Flowen's Sword (3084)
|
||||||
|
Frozen Shooter
|
||||||
|
Gae Bolg
|
||||||
|
Gal Gryphon's Wing
|
||||||
|
Galatine
|
||||||
|
Gatling
|
||||||
|
General/Arm
|
||||||
|
General/Legs
|
||||||
|
General/Mind
|
||||||
|
General/Power
|
||||||
|
Gi Gue's Body
|
||||||
|
Gigobooma's Right Arm
|
||||||
|
Girasole
|
||||||
|
Glaive
|
||||||
|
Glide Divine
|
||||||
|
Gobooma's Right Arm
|
||||||
|
God Hand
|
||||||
|
God/Ability
|
||||||
|
God/Arm
|
||||||
|
God/Battle
|
||||||
|
God/Body
|
||||||
|
God/HP
|
||||||
|
God/Legs
|
||||||
|
God/Luck
|
||||||
|
God/Mind
|
||||||
|
God/Power
|
||||||
|
God/TP
|
||||||
|
God/Technique
|
||||||
|
Grass Assassin's Arms
|
||||||
|
Gratia
|
||||||
|
Graviton Plate
|
||||||
|
Greenill Card
|
||||||
|
Guard Wave
|
||||||
|
Guardianna
|
||||||
|
Guilty Light
|
||||||
|
Gungnir
|
||||||
|
Guren
|
||||||
|
H&S25 Justice
|
||||||
|
HP Material
|
||||||
|
HP/Restorate
|
||||||
|
HP/Revival
|
||||||
|
Handgun: Guld
|
||||||
|
Handgun: Milla
|
||||||
|
Heart of Poumn
|
||||||
|
Heaven Punisher
|
||||||
|
Heaven Striker
|
||||||
|
Heaven Striker Coat
|
||||||
|
Heavenly/Ability
|
||||||
|
Heavenly/Arms
|
||||||
|
Heavenly/Battle
|
||||||
|
Heavenly/Body
|
||||||
|
Heavenly/HP
|
||||||
|
Heavenly/Legs
|
||||||
|
Heavenly/Luck
|
||||||
|
Heavenly/Mind
|
||||||
|
Heavenly/Power
|
||||||
|
Heavenly/Resist
|
||||||
|
Heavenly/TP
|
||||||
|
Hero/Ability
|
||||||
|
Hildebear's Head
|
||||||
|
Hildeblue's Head
|
||||||
|
Hitogata
|
||||||
|
Holy Ray
|
||||||
|
Ice Staff: Dagon
|
||||||
|
Ignition Cloak
|
||||||
|
Imperial Pick
|
||||||
|
Infantry Gear
|
||||||
|
Infantry Mantle
|
||||||
|
Inferno Bazooka
|
||||||
|
Invisible Guard
|
||||||
|
Jack-O'-Lantern
|
||||||
|
Justy-23ST
|
||||||
|
Kaladbolg
|
||||||
|
Kamui
|
||||||
|
Kasami Bracer
|
||||||
|
Kunai
|
||||||
|
Kusanagi
|
||||||
|
L&K14 Combat
|
||||||
|
L&K38 Combat
|
||||||
|
Laconium Axe
|
||||||
|
Lame d'Argent
|
||||||
|
Laser
|
||||||
|
Last Survivor
|
||||||
|
Launcher
|
||||||
|
Lavis Cannon
|
||||||
|
Liberta Kit
|
||||||
|
Lieutenant Gear
|
||||||
|
Lieutenant Mantle
|
||||||
|
Light Relief
|
||||||
|
Limiter
|
||||||
|
Luck Material
|
||||||
|
Luminous Field
|
||||||
|
M&A60 Vise
|
||||||
|
Mace of Adaman
|
||||||
|
Madam's Parasol
|
||||||
|
Madam's Umbrella
|
||||||
|
Mag
|
||||||
|
Magic Rock "Moola"
|
||||||
|
Magic Stone "Iritista"
|
||||||
|
Maguwa
|
||||||
|
Mahu
|
||||||
|
Maser Beam
|
||||||
|
Master/Ability
|
||||||
|
Meteor Cudgel
|
||||||
|
Meteor Smash
|
||||||
|
Mind Material
|
||||||
|
Monkey King Bar
|
||||||
|
Monogrinder
|
||||||
|
Morning Glory
|
||||||
|
Morning Prayer
|
||||||
|
Mother Garb
|
||||||
|
Mother Garb+
|
||||||
|
Musashi
|
||||||
|
NUG2000-Bazooka
|
||||||
|
Nei's Claw
|
||||||
|
Officer Uniform
|
||||||
|
Ophelie Seize
|
||||||
|
Oran Card
|
||||||
|
P-arm's Arms
|
||||||
|
PB/Create
|
||||||
|
Panzer Faust
|
||||||
|
Parasitic Gene "Flow"
|
||||||
|
Partisan of Lightning
|
||||||
|
Parts of Baranz
|
||||||
|
Parts of Egg Blaster
|
||||||
|
Perfect/Resist
|
||||||
|
Phoenix Claw
|
||||||
|
Phonon Maser
|
||||||
|
Photon Claw
|
||||||
|
Photon Crystal
|
||||||
|
Photon Launcher
|
||||||
|
Pillar
|
||||||
|
Pinkal Card
|
||||||
|
Plantain Leaf
|
||||||
|
Pole
|
||||||
|
Power Material
|
||||||
|
Prophets of Motav
|
||||||
|
Proto Regene Gear
|
||||||
|
Psycho Wand
|
||||||
|
Purplenum Card
|
||||||
|
Rabbit Wand
|
||||||
|
Rage de Feu
|
||||||
|
Rambling May
|
||||||
|
Rappy's Beak
|
||||||
|
Rappy's Wing
|
||||||
|
Recovery Barrier
|
||||||
|
Red Barrier
|
||||||
|
Red Coat
|
||||||
|
Red Dagger
|
||||||
|
Red Handgun
|
||||||
|
Red Mechgun
|
||||||
|
Red Odoshi Domaru
|
||||||
|
Red Partisan
|
||||||
|
Red Ring
|
||||||
|
Red Saber
|
||||||
|
Red Scorpio
|
||||||
|
Red Slicer
|
||||||
|
Red Sword
|
||||||
|
Redria Card
|
||||||
|
Regene Gear Adv.
|
||||||
|
Regenerate Gear
|
||||||
|
Regenerate Gear B.P.
|
||||||
|
Repeater
|
||||||
|
Resist/Fire
|
||||||
|
Resist/Flame
|
||||||
|
Resist/Freeze
|
||||||
|
Resist/Light
|
||||||
|
Resist/Thunder
|
||||||
|
Revival Cuirass
|
||||||
|
Revival Garment
|
||||||
|
Rianov 303SNR
|
||||||
|
Rianov 303SNR-1
|
||||||
|
Rianov 303SNR-2
|
||||||
|
Rianov 303SNR-3
|
||||||
|
Rianov 303SNR-4
|
||||||
|
Rianov 303SNR-5
|
||||||
|
Rico's Earring
|
||||||
|
Rico's Glasses
|
||||||
|
Rika's Claw
|
||||||
|
Ripper
|
||||||
|
Ruby Bullet
|
||||||
|
Rupika
|
||||||
|
S-Parts ver1.16
|
||||||
|
S-Parts ver2.01
|
||||||
|
S-beat's Arms
|
||||||
|
S-red's Arms
|
||||||
|
Sacred Cloth
|
||||||
|
Sacred Duster
|
||||||
|
Sacred Guard
|
||||||
|
Sange
|
||||||
|
Sawcer
|
||||||
|
Scape Doll
|
||||||
|
Scepter
|
||||||
|
Sealed J-Sword
|
||||||
|
Secret Gear
|
||||||
|
Secure Feet
|
||||||
|
Select Cloak
|
||||||
|
Sense Plate
|
||||||
|
Shouren
|
||||||
|
Silence Claw
|
||||||
|
Sinow Berill's Arms
|
||||||
|
Siren Glass Hammer
|
||||||
|
Skyly Card
|
||||||
|
Slicer of Assassin
|
||||||
|
Slicer of Fanatic
|
||||||
|
Smartlink
|
||||||
|
Smoking Plate
|
||||||
|
Snake Spire
|
||||||
|
Sol Atomizer
|
||||||
|
Solferino
|
||||||
|
Sorcerer's Right Arm
|
||||||
|
Soul Banish
|
||||||
|
Spirit Cuirass
|
||||||
|
Spirit Garment
|
||||||
|
Spread Needle
|
||||||
|
Staff
|
||||||
|
Stag Cutlery
|
||||||
|
Standstill Shield
|
||||||
|
Star Amplifier
|
||||||
|
Star Atomizer
|
||||||
|
Star Cuirass
|
||||||
|
Sting Tip
|
||||||
|
Stink Frame
|
||||||
|
Stink Shield
|
||||||
|
Storm Wand: Indra
|
||||||
|
Striker
|
||||||
|
Striker Plus
|
||||||
|
Suppressed Gun
|
||||||
|
Swordsman Lore
|
||||||
|
Syncesta
|
||||||
|
TP/Restorate
|
||||||
|
TP/Revival
|
||||||
|
Talis
|
||||||
|
Tanegashima
|
||||||
|
Technical Crozier
|
||||||
|
Tempest Cloak
|
||||||
|
The Sigh of a God
|
||||||
|
Thirteen
|
||||||
|
Trigrinder
|
||||||
|
Trimate
|
||||||
|
Tripolic Reflector
|
||||||
|
Tripolic Shield
|
||||||
|
Twin Blaze
|
||||||
|
Twin Brand
|
||||||
|
Twin Chakram
|
||||||
|
Twin Psychogun
|
||||||
|
Tyrell's Parasol
|
||||||
|
V101
|
||||||
|
V501
|
||||||
|
V502
|
||||||
|
V801
|
||||||
|
Valkyrie
|
||||||
|
Varista
|
||||||
|
Victor Axe
|
||||||
|
Viridia Card
|
||||||
|
Visk-235W
|
||||||
|
Vivienne
|
||||||
|
Vjaya
|
||||||
|
Vulcan
|
||||||
|
Wals-MK2
|
||||||
|
Wedding Dress
|
||||||
|
Whitill Card
|
||||||
|
Windmill
|
||||||
|
Yamato
|
||||||
|
Yamigarasu
|
||||||
|
Yasakani Magatama
|
||||||
|
Yasha
|
||||||
|
Yasminkov 2000H
|
||||||
|
Yasminkov 3000R
|
||||||
|
Yasminkov 7000V
|
||||||
|
Yasminkov 9000M
|
||||||
|
Yata Mirror
|
||||||
|
Yellow Barrier
|
||||||
|
Yellowboze Card
|
||||||
|
Yunchang
|
||||||
|
Zanba
|
||||||
|
Zero Divide
|
Can't render this file because it contains an unexpected character in line 261 and column 12.
|
@ -200,6 +200,7 @@ function parseNpcData(episode: number, npcs: DatNpc[]): QuestNpc[] {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: detect Mothmant, St. Rappy, Hallo Rappy, Egg Rappy, Death Gunner, Bulk and Recon.
|
||||||
function getNpcType(episode: number, { typeId, unknown, skin, areaId }: DatNpc): NpcType {
|
function getNpcType(episode: number, { typeId, unknown, skin, areaId }: DatNpc): NpcType {
|
||||||
const regular = (unknown[2][18] & 0x80) === 0;
|
const regular = (unknown[2][18] & 0x80) === 0;
|
||||||
|
|
||||||
@ -353,8 +354,6 @@ function getNpcType(episode: number, { typeId, unknown, skin, areaId }: DatNpc):
|
|||||||
case 0x0FE: return NpcType.Nurse2;
|
case 0x0FE: return NpcType.Nurse2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove log statement:
|
|
||||||
console.log(`Unknown type ID: ${typeId} (0x${typeId.toString(16)}).`);
|
|
||||||
return NpcType.Unknown;
|
return NpcType.Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ export class NpcType {
|
|||||||
id: number;
|
id: number;
|
||||||
code: string;
|
code: string;
|
||||||
/**
|
/**
|
||||||
* Unique name.
|
* Unique name. E.g. a Delsaber would have (Ep. II) appended to its name.
|
||||||
*/
|
*/
|
||||||
name: string;
|
name: string;
|
||||||
/**
|
/**
|
||||||
@ -10,44 +10,59 @@ export class NpcType {
|
|||||||
* Might conflict with other NPC names (e.g. Delsaber from ep. I and ep. II).
|
* Might conflict with other NPC names (e.g. Delsaber from ep. I and ep. II).
|
||||||
*/
|
*/
|
||||||
simpleName: string;
|
simpleName: string;
|
||||||
|
ultimateName: string;
|
||||||
episode?: number;
|
episode?: number;
|
||||||
enemy: boolean;
|
enemy: boolean;
|
||||||
|
|
||||||
constructor(id: number, code: string, name: string, simpleName: string, episode: number | undefined, enemy: boolean) {
|
constructor(
|
||||||
|
id: number,
|
||||||
|
code: string,
|
||||||
|
name: string,
|
||||||
|
simpleName: string,
|
||||||
|
ultimateName: string,
|
||||||
|
episode: number | undefined,
|
||||||
|
enemy: boolean
|
||||||
|
) {
|
||||||
if (!Number.isInteger(id) || id < 1)
|
if (!Number.isInteger(id) || id < 1)
|
||||||
throw new Error(`Expected id to be an integer greater than or equal to 1, got ${id}.`);
|
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 (!code) throw new Error('code is required.');
|
||||||
if (!name) throw new Error('name is required.');
|
if (!name) throw new Error('name is required.');
|
||||||
if (!simpleName) throw new Error('simpleName is required.');
|
if (!simpleName) throw new Error('simpleName is required.');
|
||||||
|
if (!ultimateName) throw new Error('ultimateName is required.');
|
||||||
if (episode != null && episode !== 1 && episode !== 2 && episode !== 4)
|
if (episode != null && episode !== 1 && episode !== 2 && episode !== 4)
|
||||||
throw new Error(`episode should be undefined, 1, 2 or 4, got ${episode}.`);
|
throw new Error(`episode should be undefined, 1, 2 or 4, got ${episode}.`);
|
||||||
if (typeof enemy !== 'boolean') throw new Error('enemy is required.');
|
if (typeof enemy !== 'boolean') throw new Error('enemy is required.');
|
||||||
|
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.code = code;
|
this.code = code;
|
||||||
this.name = name;
|
|
||||||
this.simpleName = simpleName;
|
this.simpleName = simpleName;
|
||||||
|
this.ultimateName = ultimateName;
|
||||||
|
this.name = name;
|
||||||
this.episode = episode;
|
this.episode = episode;
|
||||||
this.enemy = enemy;
|
this.enemy = enemy;
|
||||||
|
|
||||||
if (episode) {
|
if (episode) {
|
||||||
const map = NpcType.byEpAndSimpleName[episode];
|
const map = NpcType.byEpAndName[episode];
|
||||||
if (map) map.set(name, this);
|
|
||||||
|
if (map) {
|
||||||
|
map.set(simpleName, this);
|
||||||
|
map.set(ultimateName, this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byEpAndSimpleName = [
|
private static byEpAndName = [
|
||||||
undefined, new Map<string, NpcType>(), new Map<string, NpcType>(), undefined, new Map<string, NpcType>()
|
undefined, new Map<string, NpcType>(), new Map<string, NpcType>(), undefined, new Map<string, NpcType>()
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uniquely identifies an NPC.
|
* Uniquely identifies an NPC. Tries to match on simpleName and ultimateName.
|
||||||
*/
|
*/
|
||||||
static bySimpleNameAndEpisode(simpleName: string, episode: number): NpcType | undefined {
|
static byNameAndEpisode(name: string, episode: number): NpcType | undefined {
|
||||||
const ep = this.byEpAndSimpleName[episode];
|
const ep = this.byEpAndName[episode];
|
||||||
if (!ep) throw new Error(`No NpcTypes for episode ${episode}.`);
|
if (!ep) throw new Error(`No NpcTypes for episode ${episode}.`);
|
||||||
|
|
||||||
return ep.get(simpleName);
|
return ep.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -89,6 +104,7 @@ export class NpcType {
|
|||||||
static RagRappy: NpcType;
|
static RagRappy: NpcType;
|
||||||
static AlRappy: NpcType;
|
static AlRappy: NpcType;
|
||||||
static Monest: NpcType;
|
static Monest: NpcType;
|
||||||
|
static Mothmant: NpcType;
|
||||||
static SavageWolf: NpcType;
|
static SavageWolf: NpcType;
|
||||||
static BarbarousWolf: NpcType;
|
static BarbarousWolf: NpcType;
|
||||||
static Booma: NpcType;
|
static Booma: NpcType;
|
||||||
@ -108,6 +124,8 @@ export class NpcType {
|
|||||||
static PofuillySlime: NpcType;
|
static PofuillySlime: NpcType;
|
||||||
static PouillySlime: NpcType;
|
static PouillySlime: NpcType;
|
||||||
static PanArms: NpcType;
|
static PanArms: NpcType;
|
||||||
|
static Migium: NpcType;
|
||||||
|
static Hidoom: NpcType;
|
||||||
static DeRolLe: NpcType;
|
static DeRolLe: NpcType;
|
||||||
|
|
||||||
// Episode I Mines
|
// Episode I Mines
|
||||||
@ -127,12 +145,14 @@ export class NpcType {
|
|||||||
static Delsaber: NpcType;
|
static Delsaber: NpcType;
|
||||||
static ChaosSorcerer: NpcType;
|
static ChaosSorcerer: NpcType;
|
||||||
static DarkGunner: NpcType;
|
static DarkGunner: NpcType;
|
||||||
|
static DeathGunner: NpcType;
|
||||||
static ChaosBringer: NpcType;
|
static ChaosBringer: NpcType;
|
||||||
static DarkBelra: NpcType;
|
static DarkBelra: NpcType;
|
||||||
static Dimenian: NpcType;
|
static Dimenian: NpcType;
|
||||||
static LaDimenian: NpcType;
|
static LaDimenian: NpcType;
|
||||||
static SoDimenian: NpcType;
|
static SoDimenian: NpcType;
|
||||||
static Bulclaw: NpcType;
|
static Bulclaw: NpcType;
|
||||||
|
static Bulk: NpcType;
|
||||||
static Claw: NpcType;
|
static Claw: NpcType;
|
||||||
static DarkFalz: NpcType;
|
static DarkFalz: NpcType;
|
||||||
|
|
||||||
@ -142,7 +162,11 @@ export class NpcType {
|
|||||||
static Hildeblue2: NpcType;
|
static Hildeblue2: NpcType;
|
||||||
static RagRappy2: NpcType;
|
static RagRappy2: NpcType;
|
||||||
static LoveRappy: NpcType;
|
static LoveRappy: NpcType;
|
||||||
|
static StRappy: NpcType;
|
||||||
|
static HalloRappy: NpcType;
|
||||||
|
static EggRappy: NpcType;
|
||||||
static Monest2: NpcType;
|
static Monest2: NpcType;
|
||||||
|
static Mothmant2: NpcType;
|
||||||
static PoisonLily2: NpcType;
|
static PoisonLily2: NpcType;
|
||||||
static NarLily2: NpcType;
|
static NarLily2: NpcType;
|
||||||
static GrassAssassin2: NpcType;
|
static GrassAssassin2: NpcType;
|
||||||
@ -157,6 +181,8 @@ export class NpcType {
|
|||||||
static SavageWolf2: NpcType;
|
static SavageWolf2: NpcType;
|
||||||
static BarbarousWolf2: NpcType;
|
static BarbarousWolf2: NpcType;
|
||||||
static PanArms2: NpcType;
|
static PanArms2: NpcType;
|
||||||
|
static Migium2: NpcType;
|
||||||
|
static Hidoom2: NpcType;
|
||||||
static Dubchic2: NpcType;
|
static Dubchic2: NpcType;
|
||||||
static Gilchic2: NpcType;
|
static Gilchic2: NpcType;
|
||||||
static Garanz2: NpcType;
|
static Garanz2: NpcType;
|
||||||
@ -189,6 +215,7 @@ export class NpcType {
|
|||||||
static Dolmdarl: NpcType;
|
static Dolmdarl: NpcType;
|
||||||
static Morfos: NpcType;
|
static Morfos: NpcType;
|
||||||
static Recobox: NpcType;
|
static Recobox: NpcType;
|
||||||
|
static Recon: NpcType;
|
||||||
static Epsilon: NpcType;
|
static Epsilon: NpcType;
|
||||||
static SinowZoa: NpcType;
|
static SinowZoa: NpcType;
|
||||||
static SinowZele: NpcType;
|
static SinowZele: NpcType;
|
||||||
@ -228,29 +255,29 @@ export class NpcType {
|
|||||||
// Unknown NPCs
|
// Unknown NPCs
|
||||||
//
|
//
|
||||||
|
|
||||||
NpcType.Unknown = new NpcType(id++, 'Unknown', 'Unknown', 'Unknown', undefined, false);
|
NpcType.Unknown = new NpcType(id++, 'Unknown', 'Unknown', 'Unknown', 'Unknown', undefined, false);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Friendly NPCs
|
// Friendly NPCs
|
||||||
//
|
//
|
||||||
|
|
||||||
NpcType.FemaleFat = new NpcType(id++, 'FemaleFat', 'Female Fat', 'Female Fat', undefined, false);
|
NpcType.FemaleFat = new NpcType(id++, 'FemaleFat', 'Female Fat', 'Female Fat', 'Female Fat', undefined, false);
|
||||||
NpcType.FemaleMacho = new NpcType(id++, 'FemaleMacho', 'Female Macho', 'Female Macho', 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', 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', 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', 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', 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', 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', 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', undefined, false);
|
NpcType.RedSoldier = new NpcType(id++, 'RedSoldier', 'Red Soldier', 'Red Soldier', 'Red Soldier', undefined, false);
|
||||||
NpcType.Principal = new NpcType(id++, 'Principal', 'Principal', 'Principal', undefined, false);
|
NpcType.Principal = new NpcType(id++, 'Principal', 'Principal', 'Principal', 'Principal', undefined, false);
|
||||||
NpcType.Tekker = new NpcType(id++, 'Tekker', 'Tekker', 'Tekker', undefined, false);
|
NpcType.Tekker = new NpcType(id++, 'Tekker', 'Tekker', 'Tekker', 'Tekker', undefined, false);
|
||||||
NpcType.GuildLady = new NpcType(id++, 'GuildLady', 'Guild Lady', 'Guild Lady', undefined, false);
|
NpcType.GuildLady = new NpcType(id++, 'GuildLady', 'Guild Lady', 'Guild Lady', 'Guild Lady', undefined, false);
|
||||||
NpcType.Scientist = new NpcType(id++, 'Scientist', 'Scientist', 'Scientist', undefined, false);
|
NpcType.Scientist = new NpcType(id++, 'Scientist', 'Scientist', 'Scientist', 'Scientist', undefined, false);
|
||||||
NpcType.Nurse = new NpcType(id++, 'Nurse', 'Nurse', 'Nurse', undefined, false);
|
NpcType.Nurse = new NpcType(id++, 'Nurse', 'Nurse', 'Nurse', 'Nurse', undefined, false);
|
||||||
NpcType.Irene = new NpcType(id++, 'Irene', 'Irene', 'Irene', undefined, false);
|
NpcType.Irene = new NpcType(id++, 'Irene', 'Irene', 'Irene', 'Irene', undefined, false);
|
||||||
NpcType.ItemShop = new NpcType(id++, 'ItemShop', 'Item Shop', 'Item Shop', undefined, false);
|
NpcType.ItemShop = new NpcType(id++, 'ItemShop', 'Item Shop', 'Item Shop', 'Item Shop', undefined, false);
|
||||||
NpcType.Nurse2 = new NpcType(id++, 'Nurse2', 'Nurse', 'Nurse (Ep. II)', 2, false);
|
NpcType.Nurse2 = new NpcType(id++, 'Nurse2', 'Nurse (Ep. II)', 'Nurse', 'Nurse', 2, false);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Enemy NPCs
|
// Enemy NPCs
|
||||||
@ -258,139 +285,151 @@ export class NpcType {
|
|||||||
|
|
||||||
// Episode I Forest
|
// Episode I Forest
|
||||||
|
|
||||||
NpcType.Hildebear = new NpcType(id++, 'Hildebear', 'Hildebear', 'Hildebear', 1, true);
|
NpcType.Hildebear = new NpcType(id++, 'Hildebear', 'Hildebear', 'Hildebear', 'Hildelt', 1, true);
|
||||||
NpcType.Hildeblue = new NpcType(id++, 'Hildeblue', 'Hildeblue', 'Hildeblue', 1, true);
|
NpcType.Hildeblue = new NpcType(id++, 'Hildeblue', 'Hildeblue', 'Hildeblue', 'Hildetorr', 1, true);
|
||||||
NpcType.RagRappy = new NpcType(id++, 'RagRappy', 'Rag Rappy', 'Rag Rappy', 1, true);
|
NpcType.RagRappy = new NpcType(id++, 'RagRappy', 'Rag Rappy', 'Rag Rappy', 'El Rappy', 1, true);
|
||||||
NpcType.AlRappy = new NpcType(id++, 'AlRappy', 'Al Rappy', 'Al Rappy', 1, true);
|
NpcType.AlRappy = new NpcType(id++, 'AlRappy', 'Al Rappy', 'Al Rappy', 'Pal Rappy', 1, true);
|
||||||
NpcType.Monest = new NpcType(id++, 'Monest', 'Monest', 'Monest', 1, true);
|
NpcType.Monest = new NpcType(id++, 'Monest', 'Monest', 'Monest', 'Mothvist', 1, true);
|
||||||
NpcType.SavageWolf = new NpcType(id++, 'SavageWolf', 'Savage Wolf', 'Savage Wolf', 1, true);
|
NpcType.Mothmant = new NpcType(id++, 'Mothmant', 'Mothmant', 'Mothmant', 'Mothvert', 1, true);
|
||||||
NpcType.BarbarousWolf = new NpcType(id++, 'BarbarousWolf', 'Barbarous Wolf', 'Barbarous Wolf', 1, true);
|
NpcType.SavageWolf = new NpcType(id++, 'SavageWolf', 'Savage Wolf', 'Savage Wolf', 'Gulgus', 1, true);
|
||||||
NpcType.Booma = new NpcType(id++, 'Booma', 'Booma', 'Booma', 1, true);
|
NpcType.BarbarousWolf = new NpcType(id++, 'BarbarousWolf', 'Barbarous Wolf', 'Barbarous Wolf', 'Gulgus-Gue', 1, true);
|
||||||
NpcType.Gobooma = new NpcType(id++, 'Gobooma', 'Gobooma', 'Gobooma', 1, true);
|
NpcType.Booma = new NpcType(id++, 'Booma', 'Booma', 'Booma', 'Bartle', 1, true);
|
||||||
NpcType.Gigobooma = new NpcType(id++, 'Gigobooma', 'Gigobooma', 'Gigobooma', 1, true);
|
NpcType.Gobooma = new NpcType(id++, 'Gobooma', 'Gobooma', 'Gobooma', 'Barble', 1, true);
|
||||||
NpcType.Dragon = new NpcType(id++, 'Dragon', 'Dragon', 'Dragon', 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
|
// Episode I Caves
|
||||||
|
|
||||||
NpcType.GrassAssassin = new NpcType(id++, 'GrassAssassin', 'Grass Assassin', 'Grass Assassin', 1, true);
|
NpcType.GrassAssassin = new NpcType(id++, 'GrassAssassin', 'Grass Assassin', 'Grass Assassin', 'Crimson Assassin', 1, true);
|
||||||
NpcType.PoisonLily = new NpcType(id++, 'PoisonLily', 'Poison Lily', 'Poison Lily', 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', 1, true);
|
NpcType.NarLily = new NpcType(id++, 'NarLily', 'Nar Lily', 'Nar Lily', 'Mil Lily', 1, true);
|
||||||
NpcType.NanoDragon = new NpcType(id++, 'NanoDragon', 'Nano Dragon', 'Nano Dragon', 1, true);
|
NpcType.NanoDragon = new NpcType(id++, 'NanoDragon', 'Nano Dragon', 'Nano Dragon', 'Nano Dragon', 1, true);
|
||||||
NpcType.EvilShark = new NpcType(id++, 'EvilShark', 'Evil Shark', 'Evil Shark', 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', 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', 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', 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', 1, true);
|
NpcType.PouillySlime = new NpcType(id++, 'PouillySlime', 'Pouilly Slime', 'Pouilly Slime', 'Pouilly Slime', 1, true);
|
||||||
NpcType.PanArms = new NpcType(id++, 'PanArms', 'Pan Arms', 'Pan Arms', 1, true);
|
NpcType.PanArms = new NpcType(id++, 'PanArms', 'Pan Arms', 'Pan Arms', 'Pan Arms', 1, true);
|
||||||
NpcType.DeRolLe = new NpcType(id++, 'DeRolLe', 'De Rol Le', 'De Rol Le', 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
|
// Episode I Mines
|
||||||
|
|
||||||
NpcType.Dubchic = new NpcType(id++, 'Dubchic', 'Dubchic', 'Dubchic', 1, true);
|
NpcType.Dubchic = new NpcType(id++, 'Dubchic', 'Dubchic', 'Dubchic', 'Dubchich', 1, true);
|
||||||
NpcType.Gilchic = new NpcType(id++, 'Gilchic', 'Gilchic', 'Gilchic', 1, true);
|
NpcType.Gilchic = new NpcType(id++, 'Gilchic', 'Gilchic', 'Gilchic', 'Gilchich', 1, true);
|
||||||
NpcType.Garanz = new NpcType(id++, 'Garanz', 'Garanz', 'Garanz', 1, true);
|
NpcType.Garanz = new NpcType(id++, 'Garanz', 'Garanz', 'Garanz', 'Baranz', 1, true);
|
||||||
NpcType.SinowBeat = new NpcType(id++, 'SinowBeat', 'Sinow Beat', 'Sinow Beat', 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', 1, true);
|
NpcType.SinowGold = new NpcType(id++, 'SinowGold', 'Sinow Gold', 'Sinow Gold', 'Sinow Red', 1, true);
|
||||||
NpcType.Canadine = new NpcType(id++, 'Canadine', 'Canadine', 'Canadine', 1, true);
|
NpcType.Canadine = new NpcType(id++, 'Canadine', 'Canadine', 'Canadine', 'Canabin', 1, true);
|
||||||
NpcType.Canane = new NpcType(id++, 'Canane', 'Canane', 'Canane', 1, true);
|
NpcType.Canane = new NpcType(id++, 'Canane', 'Canane', 'Canane', 'Canune', 1, true);
|
||||||
NpcType.Dubswitch = new NpcType(id++, 'Dubswitch', 'Dubswitch', 'Dubswitch', 1, true);
|
NpcType.Dubswitch = new NpcType(id++, 'Dubswitch', 'Dubswitch', 'Dubswitch', 'Dubswitch', 1, true);
|
||||||
NpcType.VolOpt = new NpcType(id++, 'VolOpt', 'Vol Opt', 'Vol Opt', 1, true);
|
NpcType.VolOpt = new NpcType(id++, 'VolOpt', 'Vol Opt', 'Vol Opt', 'Vol Opt ver.2', 1, true);
|
||||||
|
|
||||||
// Episode I Ruins
|
// Episode I Ruins
|
||||||
|
|
||||||
NpcType.Delsaber = new NpcType(id++, 'Delsaber', 'Delsaber', 'Delsaber', 1, true);
|
NpcType.Delsaber = new NpcType(id++, 'Delsaber', 'Delsaber', 'Delsaber', 'Delsaber', 1, true);
|
||||||
NpcType.ChaosSorcerer = new NpcType(id++, 'ChaosSorcerer', 'Chaos Sorcerer', 'Chaos Sorcerer', 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', 1, true);
|
NpcType.DarkGunner = new NpcType(id++, 'DarkGunner', 'Dark Gunner', 'Dark Gunner', 'Dark Gunner', 1, true);
|
||||||
NpcType.ChaosBringer = new NpcType(id++, 'ChaosBringer', 'Chaos Bringer', 'Chaos Bringer', 1, true);
|
NpcType.DeathGunner = new NpcType(id++, 'DeathGunner', 'Death Gunner', 'Death Gunner', 'Death Gunner', 1, true);
|
||||||
NpcType.DarkBelra = new NpcType(id++, 'DarkBelra', 'Dark Belra', 'Dark Belra', 1, true);
|
NpcType.ChaosBringer = new NpcType(id++, 'ChaosBringer', 'Chaos Bringer', 'Chaos Bringer', 'Dark Bringer', 1, true);
|
||||||
NpcType.Dimenian = new NpcType(id++, 'Dimenian', 'Dimenian', 'Dimenian', 1, true);
|
NpcType.DarkBelra = new NpcType(id++, 'DarkBelra', 'Dark Belra', 'Dark Belra', 'Indi Belra', 1, true);
|
||||||
NpcType.LaDimenian = new NpcType(id++, 'LaDimenian', 'La Dimenian', 'La Dimenian', 1, true);
|
NpcType.Dimenian = new NpcType(id++, 'Dimenian', 'Dimenian', 'Dimenian', 'Arlan', 1, true);
|
||||||
NpcType.SoDimenian = new NpcType(id++, 'SoDimenian', 'So Dimenian', 'So Dimenian', 1, true);
|
NpcType.LaDimenian = new NpcType(id++, 'LaDimenian', 'La Dimenian', 'La Dimenian', 'Merlan', 1, true);
|
||||||
NpcType.Bulclaw = new NpcType(id++, 'Bulclaw', 'Bulclaw', 'Bulclaw', 1, true);
|
NpcType.SoDimenian = new NpcType(id++, 'SoDimenian', 'So Dimenian', 'So Dimenian', 'Del-D', 1, true);
|
||||||
NpcType.Claw = new NpcType(id++, 'Claw', 'Claw', 'Claw', 1, true);
|
NpcType.Bulclaw = new NpcType(id++, 'Bulclaw', 'Bulclaw', 'Bulclaw', 'Bulclaw', 1, true);
|
||||||
NpcType.DarkFalz = new NpcType(id++, 'DarkFalz', 'Dark Falz', 'Dark Falz', 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
|
// Episode II VR Temple
|
||||||
|
|
||||||
NpcType.Hildebear2 = new NpcType(id++, 'Hildebear2', 'Hildebear', 'Hildebear (Ep. II)', 2, true);
|
NpcType.Hildebear2 = new NpcType(id++, 'Hildebear2', 'Hildebear (Ep. II)', 'Hildebear', 'Hildelt', 2, true);
|
||||||
NpcType.Hildeblue2 = new NpcType(id++, 'Hildeblue2', 'Hildeblue', 'Hildeblue (Ep. II)', 2, true);
|
NpcType.Hildeblue2 = new NpcType(id++, 'Hildeblue2', 'Hildeblue (Ep. II)', 'Hildeblue', 'Hildetorr', 2, true);
|
||||||
NpcType.RagRappy2 = new NpcType(id++, 'RagRappy2', 'Rag Rappy', 'Rag Rappy (Ep. II)', 2, true);
|
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', 2, true);
|
NpcType.LoveRappy = new NpcType(id++, 'LoveRappy', 'Love Rappy', 'Love Rappy', 'Love Rappy', 2, true);
|
||||||
NpcType.Monest2 = new NpcType(id++, 'Monest2', 'Monest', 'Monest (Ep. II)', 2, true);
|
NpcType.StRappy = new NpcType(id++, 'StRappy', 'St. Rappy', 'St. Rappy', 'St. Rappy', 2, true);
|
||||||
NpcType.PoisonLily2 = new NpcType(id++, 'PoisonLily2', 'Poison Lily', 'Poison Lily (Ep. II)', 2, true);
|
NpcType.HalloRappy = new NpcType(id++, 'HalloRappy', 'Hallo Rappy', 'Hallo Rappy', 'Hallo Rappy', 2, true);
|
||||||
NpcType.NarLily2 = new NpcType(id++, 'NarLily2', 'Nar Lily', 'Nar Lily (Ep. II)', 2, true);
|
NpcType.EggRappy = new NpcType(id++, 'EggRappy', 'Egg Rappy', 'Egg Rappy', 'Egg Rappy', 2, true);
|
||||||
NpcType.GrassAssassin2 = new NpcType(id++, 'GrassAssassin2', 'Grass Assassin', 'Grass Assassin (Ep. II)', 2, true);
|
NpcType.Monest2 = new NpcType(id++, 'Monest2', 'Monest (Ep. II)', 'Monest', 'Mothvist', 2, true);
|
||||||
NpcType.Dimenian2 = new NpcType(id++, 'Dimenian2', 'Dimenian', 'Dimenian (Ep. II)', 2, true);
|
NpcType.Mothmant2 = new NpcType(id++, 'Mothmant2', 'Mothmant', 'Mothmant', 'Mothvert', 2, true);
|
||||||
NpcType.LaDimenian2 = new NpcType(id++, 'LaDimenian2', 'La Dimenian', 'La Dimenian (Ep. II)', 2, true);
|
NpcType.PoisonLily2 = new NpcType(id++, 'PoisonLily2', 'Poison Lily (Ep. II)', 'Poison Lily', 'Ob Lily', 2, true);
|
||||||
NpcType.SoDimenian2 = new NpcType(id++, 'SoDimenian2', 'So Dimenian', 'So Dimenian (Ep. II)', 2, true);
|
NpcType.NarLily2 = new NpcType(id++, 'NarLily2', 'Nar Lily (Ep. II)', 'Nar Lily', 'Mil Lily', 2, true);
|
||||||
NpcType.DarkBelra2 = new NpcType(id++, 'DarkBelra2', 'Dark Belra', 'Dark Belra (Ep. II)', 2, true);
|
NpcType.GrassAssassin2 = new NpcType(id++, 'GrassAssassin2', 'Grass Assassin (Ep. II)', 'Grass Assassin', 'Crimson Assassin', 2, true);
|
||||||
NpcType.BarbaRay = new NpcType(id++, 'BarbaRay', 'Barba Ray', 'Barba Ray', 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
|
// Episode II VR Spaceship
|
||||||
|
|
||||||
NpcType.SavageWolf2 = new NpcType(id++, 'SavageWolf2', 'Savage Wolf', 'Savage Wolf (Ep. II)', 2, true);
|
NpcType.SavageWolf2 = new NpcType(id++, 'SavageWolf2', 'Savage Wolf (Ep. II)', 'Savage Wolf', 'Gulgus', 2, true);
|
||||||
NpcType.BarbarousWolf2 = new NpcType(id++, 'BarbarousWolf2', 'Barbarous Wolf', 'Barbarous Wolf (Ep. II)', 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', 'Pan Arms (Ep. II)', 2, true);
|
NpcType.PanArms2 = new NpcType(id++, 'PanArms2', 'Pan Arms (Ep. II)', 'Pan Arms', 'Pan Arms', 2, true);
|
||||||
NpcType.Dubchic2 = new NpcType(id++, 'Dubchic2', 'Dubchic', 'Dubchic (Ep. II)', 2, true);
|
NpcType.Migium2 = new NpcType(id++, 'Migium2', 'Migium (Ep. II)', 'Migium', 'Migium', 2, true);
|
||||||
NpcType.Gilchic2 = new NpcType(id++, 'Gilchic2', 'Gilchic', 'Gilchic (Ep. II)', 2, true);
|
NpcType.Hidoom2 = new NpcType(id++, 'Hidoom2', 'Hidoom (Ep. II)', 'Hidoom', 'Hidoom', 2, true);
|
||||||
NpcType.Garanz2 = new NpcType(id++, 'Garanz2', 'Garanz', 'Garanz (Ep. II)', 2, true);
|
NpcType.Dubchic2 = new NpcType(id++, 'Dubchic2', 'Dubchic (Ep. II)', 'Dubchic', 'Dubchich', 2, true);
|
||||||
NpcType.Dubswitch2 = new NpcType(id++, 'Dubswitch2', 'Dubswitch', 'Dubswitch (Ep. II)', 2, true);
|
NpcType.Gilchic2 = new NpcType(id++, 'Gilchic2', 'Gilchic (Ep. II)', 'Gilchic', 'Gilchich', 2, true);
|
||||||
NpcType.Delsaber2 = new NpcType(id++, 'Delsaber2', 'Delsaber', 'Delsaber (Ep. II)', 2, true);
|
NpcType.Garanz2 = new NpcType(id++, 'Garanz2', 'Garanz (Ep. II)', 'Garanz', 'Baranz', 2, true);
|
||||||
NpcType.ChaosSorcerer2 = new NpcType(id++, 'ChaosSorcerer2', 'Chaos Sorcerer', 'Chaos Sorcerer (Ep. II)', 2, true);
|
NpcType.Dubswitch2 = new NpcType(id++, 'Dubswitch2', 'Dubswitch (Ep. II)', 'Dubswitch', 'Dubswitch', 2, true);
|
||||||
NpcType.GolDragon = new NpcType(id++, 'GolDragon', 'Gol Dragon', 'Gol Dragon', 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
|
// Episode II Central Control Area
|
||||||
|
|
||||||
NpcType.SinowBerill = new NpcType(id++, 'SinowBerill', 'Sinow Berill', 'Sinow Berill', 2, true);
|
NpcType.SinowBerill = new NpcType(id++, 'SinowBerill', 'Sinow Berill', 'Sinow Berill', 'Sinow Berill', 2, true);
|
||||||
NpcType.SinowSpigell = new NpcType(id++, 'SinowSpigell', 'Sinow Spigell', 'Sinow Spigell', 2, true);
|
NpcType.SinowSpigell = new NpcType(id++, 'SinowSpigell', 'Sinow Spigell', 'Sinow Spigell', 'Sinow Spigell', 2, true);
|
||||||
NpcType.Merillia = new NpcType(id++, 'Merillia', 'Merillia', 'Merillia', 2, true);
|
NpcType.Merillia = new NpcType(id++, 'Merillia', 'Merillia', 'Merillia', 'Merillia', 2, true);
|
||||||
NpcType.Meriltas = new NpcType(id++, 'Meriltas', 'Meriltas', 'Meriltas', 2, true);
|
NpcType.Meriltas = new NpcType(id++, 'Meriltas', 'Meriltas', 'Meriltas', 'Meriltas', 2, true);
|
||||||
NpcType.Mericarol = new NpcType(id++, 'Mericarol', 'Mericarol', 'Mericarol', 2, true);
|
NpcType.Mericarol = new NpcType(id++, 'Mericarol', 'Mericarol', 'Mericarol', 'Mericarol', 2, true);
|
||||||
NpcType.Mericus = new NpcType(id++, 'Mericus', 'Mericus', 'Mericus', 2, true);
|
NpcType.Mericus = new NpcType(id++, 'Mericus', 'Mericus', 'Mericus', 'Mericus', 2, true);
|
||||||
NpcType.Merikle = new NpcType(id++, 'Merikle', 'Merikle', 'Merikle', 2, true);
|
NpcType.Merikle = new NpcType(id++, 'Merikle', 'Merikle', 'Merikle', 'Merikle', 2, true);
|
||||||
NpcType.UlGibbon = new NpcType(id++, 'UlGibbon', 'Ul Gibbon', 'Ul Gibbon', 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', 2, true);
|
NpcType.ZolGibbon = new NpcType(id++, 'ZolGibbon', 'Zol Gibbon', 'Zol Gibbon', 'Zol Gibbon', 2, true);
|
||||||
NpcType.Gibbles = new NpcType(id++, 'Gibbles', 'Gibbles', 'Gibbles', 2, true);
|
NpcType.Gibbles = new NpcType(id++, 'Gibbles', 'Gibbles', 'Gibbles', 'Gibbles', 2, true);
|
||||||
NpcType.Gee = new NpcType(id++, 'Gee', 'Gee', 'Gee', 2, true);
|
NpcType.Gee = new NpcType(id++, 'Gee', 'Gee', 'Gee', 'Gee', 2, true);
|
||||||
NpcType.GiGue = new NpcType(id++, 'GiGue', 'Gi Gue', 'Gi Gue', 2, true);
|
NpcType.GiGue = new NpcType(id++, 'GiGue', 'Gi Gue', 'Gi Gue', 'Gi Gue', 2, true);
|
||||||
NpcType.GalGryphon = new NpcType(id++, 'GalGryphon', 'Gal Gryphon', 'Gal Gryphon', 2, true);
|
NpcType.GalGryphon = new NpcType(id++, 'GalGryphon', 'Gal Gryphon', 'Gal Gryphon', 'Gal Gryphon', 2, true);
|
||||||
|
|
||||||
// Episode II Seabed
|
// Episode II Seabed
|
||||||
|
|
||||||
NpcType.Deldepth = new NpcType(id++, 'Deldepth', 'Deldepth', 'Deldepth', 2, true);
|
NpcType.Deldepth = new NpcType(id++, 'Deldepth', 'Deldepth', 'Deldepth', 'Deldepth', 2, true);
|
||||||
NpcType.Delbiter = new NpcType(id++, 'Delbiter', 'Delbiter', 'Delbiter', 2, true);
|
NpcType.Delbiter = new NpcType(id++, 'Delbiter', 'Delbiter', 'Delbiter', 'Delbiter', 2, true);
|
||||||
NpcType.Dolmolm = new NpcType(id++, 'Dolmolm', 'Dolmolm', 'Dolmolm', 2, true);
|
NpcType.Dolmolm = new NpcType(id++, 'Dolmolm', 'Dolmolm', 'Dolmolm', 'Dolmolm', 2, true);
|
||||||
NpcType.Dolmdarl = new NpcType(id++, 'Dolmdarl', 'Dolmdarl', 'Dolmdarl', 2, true);
|
NpcType.Dolmdarl = new NpcType(id++, 'Dolmdarl', 'Dolmdarl', 'Dolmdarl', 'Dolmdarl', 2, true);
|
||||||
NpcType.Morfos = new NpcType(id++, 'Morfos', 'Morfos', 'Morfos', 2, true);
|
NpcType.Morfos = new NpcType(id++, 'Morfos', 'Morfos', 'Morfos', 'Morfos', 2, true);
|
||||||
NpcType.Recobox = new NpcType(id++, 'Recobox', 'Recobox', 'Recobox', 2, true);
|
NpcType.Recobox = new NpcType(id++, 'Recobox', 'Recobox', 'Recobox', 'Recobox', 2, true);
|
||||||
NpcType.Epsilon = new NpcType(id++, 'Epsilon', 'Epsilon', 'Epsilon', 2, true);
|
NpcType.Recon = new NpcType(id++, 'Recon', 'Recon', 'Recon', 'Recon', 2, true);
|
||||||
NpcType.SinowZoa = new NpcType(id++, 'SinowZoa', 'Sinow Zoa', 'Sinow Zoa', 2, true);
|
NpcType.Epsilon = new NpcType(id++, 'Epsilon', 'Epsilon', 'Epsilon', 'Epsilon', 2, true);
|
||||||
NpcType.SinowZele = new NpcType(id++, 'SinowZele', 'Sinow Zele', 'Sinow Zele', 2, true);
|
NpcType.SinowZoa = new NpcType(id++, 'SinowZoa', 'Sinow Zoa', 'Sinow Zoa', 'Sinow Zoa', 2, true);
|
||||||
NpcType.IllGill = new NpcType(id++, 'IllGill', 'Ill Gill', 'Ill Gill', 2, true);
|
NpcType.SinowZele = new NpcType(id++, 'SinowZele', 'Sinow Zele', 'Sinow Zele', 'Sinow Zele', 2, true);
|
||||||
NpcType.DelLily = new NpcType(id++, 'DelLily', 'Del Lily', 'Del Lily', 2, true);
|
NpcType.IllGill = new NpcType(id++, 'IllGill', 'Ill Gill', 'Ill Gill', 'Ill Gill', 2, true);
|
||||||
NpcType.OlgaFlow = new NpcType(id++, 'OlgaFlow', 'Olga Flow', 'Olga Flow', 2, true);
|
NpcType.DelLily = new NpcType(id++, 'DelLily', 'Del Lily', 'Del Lily', 'Del Lily', 2, true);
|
||||||
|
NpcType.OlgaFlow = new NpcType(id++, 'OlgaFlow', 'Olga Flow', 'Olga Flow', 'Olga Flow', 2, true);
|
||||||
|
|
||||||
// Episode IV
|
// Episode IV
|
||||||
|
|
||||||
NpcType.SandRappy = new NpcType(id++, 'SandRappy', 'Sand Rappy', 'Sand Rappy', 4, true);
|
NpcType.SandRappy = new NpcType(id++, 'SandRappy', 'Sand Rappy', 'Sand Rappy', 'Sand Rappy', 4, true);
|
||||||
NpcType.DelRappy = new NpcType(id++, 'DelRappy', 'Del Rappy', 'Del Rappy', 4, true);
|
NpcType.DelRappy = new NpcType(id++, 'DelRappy', 'Del Rappy', 'Del Rappy', 'Del Rappy', 4, true);
|
||||||
NpcType.Astark = new NpcType(id++, 'Astark', 'Astark', 'Astark', 4, true);
|
NpcType.Astark = new NpcType(id++, 'Astark', 'Astark', 'Astark', 'Astark', 4, true);
|
||||||
NpcType.SatelliteLizard = new NpcType(id++, 'SatelliteLizard', 'Satellite Lizard', 'Satellite Lizard', 4, true);
|
NpcType.SatelliteLizard = new NpcType(id++, 'SatelliteLizard', 'Satellite Lizard', 'Satellite Lizard', 'Satellite Lizard', 4, true);
|
||||||
NpcType.Yowie = new NpcType(id++, 'Yowie', 'Yowie', 'Yowie', 4, true);
|
NpcType.Yowie = new NpcType(id++, 'Yowie', 'Yowie', 'Yowie', 'Yowie', 4, true);
|
||||||
NpcType.MerissaA = new NpcType(id++, 'MerissaA', 'Merissa A', 'Merissa A', 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', 4, true);
|
NpcType.MerissaAA = new NpcType(id++, 'MerissaAA', 'Merissa AA', 'Merissa AA', 'Merissa AA', 4, true);
|
||||||
NpcType.Girtablulu = new NpcType(id++, 'Girtablulu', 'Girtablulu', 'Girtablulu', 4, true);
|
NpcType.Girtablulu = new NpcType(id++, 'Girtablulu', 'Girtablulu', 'Girtablulu', 'Girtablulu', 4, true);
|
||||||
NpcType.Zu = new NpcType(id++, 'Zu', 'Zu', 'Zu', 4, true);
|
NpcType.Zu = new NpcType(id++, 'Zu', 'Zu', 'Zu', 'Zu', 4, true);
|
||||||
NpcType.Pazuzu = new NpcType(id++, 'Pazuzu', 'Pazuzu', 'Pazuzu', 4, true);
|
NpcType.Pazuzu = new NpcType(id++, 'Pazuzu', 'Pazuzu', 'Pazuzu', 'Pazuzu', 4, true);
|
||||||
NpcType.Boota = new NpcType(id++, 'Boota', 'Boota', 'Boota', 4, true);
|
NpcType.Boota = new NpcType(id++, 'Boota', 'Boota', 'Boota', 'Boota', 4, true);
|
||||||
NpcType.ZeBoota = new NpcType(id++, 'ZeBoota', 'Ze Boota', 'Ze 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', 4, true);
|
NpcType.BaBoota = new NpcType(id++, 'BaBoota', 'Ba Boota', 'Ba Boota', 'Ba Boota', 4, true);
|
||||||
NpcType.Dorphon = new NpcType(id++, 'Dorphon', 'Dorphon', 'Dorphon', 4, true);
|
NpcType.Dorphon = new NpcType(id++, 'Dorphon', 'Dorphon', 'Dorphon', 'Dorphon', 4, true);
|
||||||
NpcType.DorphonEclair = new NpcType(id++, 'DorphonEclair', 'Dorphon Eclair', 'Dorphon Eclair', 4, true);
|
NpcType.DorphonEclair = new NpcType(id++, 'DorphonEclair', 'Dorphon Eclair', 'Dorphon Eclair', 'Dorphon Eclair', 4, true);
|
||||||
NpcType.Goran = new NpcType(id++, 'Goran', 'Goran', 'Goran', 4, true);
|
NpcType.Goran = new NpcType(id++, 'Goran', 'Goran', 'Goran', 'Goran', 4, true);
|
||||||
NpcType.PyroGoran = new NpcType(id++, 'PyroGoran', 'Pyro Goran', 'Pyro 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', 4, true);
|
NpcType.GoranDetonator = new NpcType(id++, 'GoranDetonator', 'Goran Detonator', 'Goran Detonator', 'Goran Detonator', 4, true);
|
||||||
NpcType.SaintMillion = new NpcType(id++, 'SaintMillion', 'Saint-Million', 'Saint-Million', 4, true);
|
NpcType.SaintMillion = new NpcType(id++, 'SaintMillion', 'Saint-Million', 'Saint-Million', 'Saint-Million', 4, true);
|
||||||
NpcType.Shambertin = new NpcType(id++, 'Shambertin', 'Shambertin', 'Shambertin', 4, true);
|
NpcType.Shambertin = new NpcType(id++, 'Shambertin', 'Shambertin', 'Shambertin', 'Shambertin', 4, true);
|
||||||
NpcType.Kondrieu = new NpcType(id++, 'Kondrieu', 'Kondrieu', 'Kondrieu', 4, true);
|
NpcType.Kondrieu = new NpcType(id++, 'Kondrieu', 'Kondrieu', 'Kondrieu', 'Kondrieu', 4, true);
|
||||||
}());
|
}());
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { Object3D } from 'three';
|
|
||||||
import { computed, observable } from 'mobx';
|
import { computed, observable } from 'mobx';
|
||||||
|
import { Object3D } from 'three';
|
||||||
|
import { ArrayBufferCursor } from '../bin-data/ArrayBufferCursor';
|
||||||
|
import { DatNpc, DatObject, DatUnknown } from '../bin-data/parsing/dat';
|
||||||
import { NpcType } from './NpcType';
|
import { NpcType } from './NpcType';
|
||||||
import { ObjectType } from './ObjectType';
|
import { ObjectType } from './ObjectType';
|
||||||
import { DatObject, DatNpc, DatUnknown } from '../bin-data/parsing/dat';
|
import { enumValues } from '../enums';
|
||||||
import { ArrayBufferCursor } from '../bin-data/ArrayBufferCursor';
|
|
||||||
|
|
||||||
export { NpcType } from './NpcType';
|
export { NpcType } from './NpcType';
|
||||||
export { ObjectType } from './ObjectType';
|
export { ObjectType } from './ObjectType';
|
||||||
@ -12,6 +13,8 @@ export enum Server {
|
|||||||
Ephinea = 'Ephinea'
|
Ephinea = 'Ephinea'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const Servers: Server[] = enumValues(Server);
|
||||||
|
|
||||||
export enum SectionId {
|
export enum SectionId {
|
||||||
Viridia = 'Viridia',
|
Viridia = 'Viridia',
|
||||||
Greenill = 'Greenill',
|
Greenill = 'Greenill',
|
||||||
@ -25,7 +28,16 @@ export enum SectionId {
|
|||||||
Whitill = 'Whitill',
|
Whitill = 'Whitill',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SectionIds = Object.keys(SectionId);
|
export const SectionIds: SectionId[] = enumValues(SectionId);
|
||||||
|
|
||||||
|
export enum Difficulty {
|
||||||
|
Normal = 'Normal',
|
||||||
|
Hard = 'Hard',
|
||||||
|
VHard = 'VHard',
|
||||||
|
Ultimate = 'Ultimate'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Difficulties: Difficulty[] = enumValues(Difficulty);
|
||||||
|
|
||||||
export class Vec3 {
|
export class Vec3 {
|
||||||
x: number;
|
x: number;
|
||||||
@ -292,6 +304,24 @@ export class Item {
|
|||||||
constructor(public name: string) { }
|
constructor(public name: string) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ItemDrop = {
|
||||||
|
item: Item,
|
||||||
|
anythingRate: number,
|
||||||
|
rareRate: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export class EnemyDrop implements ItemDrop {
|
||||||
|
rate: number;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public item: Item,
|
||||||
|
public anythingRate: number,
|
||||||
|
public rareRate: number
|
||||||
|
) {
|
||||||
|
this.rate = anythingRate * rareRate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class HuntMethod {
|
export class HuntMethod {
|
||||||
constructor(
|
constructor(
|
||||||
public quest: SimpleQuest
|
public quest: SimpleQuest
|
||||||
|
40
src/enums.ts
Normal file
40
src/enums.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
export function enumValues<E>(e: any): E[] {
|
||||||
|
const values = Object.values(e);
|
||||||
|
const numberValues = values.filter(v => typeof v === 'number');
|
||||||
|
|
||||||
|
if (numberValues.length) {
|
||||||
|
return numberValues as any as E[];
|
||||||
|
} else {
|
||||||
|
return values as any as E[];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function enumNames(e: any): string[] {
|
||||||
|
return Object.keys(e).filter(k => typeof (e as any)[k] === 'string');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map with a guaranteed value per enum key.
|
||||||
|
*/
|
||||||
|
export class EnumMap<K, V> {
|
||||||
|
private keys: K[];
|
||||||
|
private values = new Map<K, V>();
|
||||||
|
|
||||||
|
constructor(enum_: any, initialValue: V | ((key: K) => V)) {
|
||||||
|
this.keys = enumValues(enum_);
|
||||||
|
|
||||||
|
if (!(initialValue instanceof Function)) {
|
||||||
|
for (const key of this.keys) {
|
||||||
|
this.values.set(key, initialValue);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const key of this.keys) {
|
||||||
|
this.values.set(key, initialValue(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get(key: K): V {
|
||||||
|
return this.values.get(key)!;
|
||||||
|
}
|
||||||
|
}
|
@ -5,20 +5,52 @@ import fs from 'fs';
|
|||||||
const SECTION_IDS = [
|
const SECTION_IDS = [
|
||||||
'Viridia', 'Greenill', 'Skyly', 'Bluefull', 'Purplenum', 'Pinkal', 'Redria', 'Oran', 'Yellowboze', 'Whitill',
|
'Viridia', 'Greenill', 'Skyly', 'Bluefull', 'Purplenum', 'Pinkal', 'Redria', 'Oran', 'Yellowboze', 'Whitill',
|
||||||
];
|
];
|
||||||
|
const ENEMY_DROPS_HEADER = ['difficulty', 'episode', 'section_id', 'enemy', 'item', 'drop_rate', 'rare_rate'];
|
||||||
|
const BOX_DROPS_HEADER = ['difficulty', 'episode', 'section_id', 'box', 'item', 'drop_rate'];
|
||||||
|
const ITEMS_HEADER = ['name'];
|
||||||
|
|
||||||
async function update() {
|
async function update() {
|
||||||
const csv =
|
const normal = await download('normal');
|
||||||
|
const hard = await download('hard');
|
||||||
|
const vhard = await download('vhard', 'very-hard');
|
||||||
|
const ultimate = await download('ultimate');
|
||||||
|
|
||||||
|
const enemyCsv =
|
||||||
[
|
[
|
||||||
['mode', 'episode', 'section_id', 'monster', 'item', 'drop_rate', 'rare_rate'],
|
ENEMY_DROPS_HEADER,
|
||||||
...await download('normal'),
|
...normal.enemyDrops,
|
||||||
...await download('hard'),
|
...hard.enemyDrops,
|
||||||
...await download('vhard', 'very-hard'),
|
...vhard.enemyDrops,
|
||||||
...await download('ultimate')
|
...ultimate.enemyDrops
|
||||||
]
|
]
|
||||||
.map(r => r.join('\t'))
|
.map(r => r.join('\t'))
|
||||||
.join('\n')
|
.join('\n');
|
||||||
|
|
||||||
return fs.promises.writeFile('./public/drops.ephinea.tsv', csv);
|
await fs.promises.writeFile('./public/enemy_drops.ephinea.tsv', enemyCsv);
|
||||||
|
|
||||||
|
const boxCsv =
|
||||||
|
[
|
||||||
|
BOX_DROPS_HEADER,
|
||||||
|
...normal.boxDrops,
|
||||||
|
...hard.boxDrops,
|
||||||
|
...vhard.boxDrops,
|
||||||
|
...ultimate.boxDrops
|
||||||
|
]
|
||||||
|
.map(r => r.join('\t'))
|
||||||
|
.join('\n');
|
||||||
|
|
||||||
|
await fs.promises.writeFile('./public/box_drops.ephinea.tsv', boxCsv);
|
||||||
|
|
||||||
|
const items = new Set([...normal.items, ...hard.items, ...vhard.items, ...ultimate.items]);
|
||||||
|
|
||||||
|
const itemsCsv =
|
||||||
|
[
|
||||||
|
ITEMS_HEADER,
|
||||||
|
...[...items].sort()
|
||||||
|
]
|
||||||
|
.join('\n');
|
||||||
|
|
||||||
|
await fs.promises.writeFile('./public/items.ephinea.tsv', itemsCsv);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function download(mode: string, modeUrl: string = mode) {
|
async function download(mode: string, modeUrl: string = mode) {
|
||||||
@ -27,7 +59,11 @@ async function download(mode: string, modeUrl: string = mode) {
|
|||||||
const $ = cheerio.load(body);
|
const $ = cheerio.load(body);
|
||||||
|
|
||||||
let episode = 1;
|
let episode = 1;
|
||||||
const data: any[][] = [];
|
const data: {
|
||||||
|
enemyDrops: any[][], boxDrops: any[][], items: Set<string>
|
||||||
|
} = {
|
||||||
|
enemyDrops: [], boxDrops: [], items: new Set()
|
||||||
|
};
|
||||||
|
|
||||||
$('table').each((tableI, table) => {
|
$('table').each((tableI, table) => {
|
||||||
const isBox = tableI >= 3;
|
const isBox = tableI >= 3;
|
||||||
@ -43,7 +79,19 @@ async function download(mode: string, modeUrl: string = mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const monster = monsterText.split('/')[mode === 'ultimate' ? 1 : 0] || monsterText;
|
let monster = monsterText.split('/')[mode === 'ultimate' ? 1 : 0] || monsterText;
|
||||||
|
|
||||||
|
if (monster === 'Halo Rappy') {
|
||||||
|
monster = 'Hallo Rappy';
|
||||||
|
} else if (monster === 'Dal Ral Lie') {
|
||||||
|
monster = 'Dal Ra Lie';
|
||||||
|
} else if (monster === 'Vol Opt ver. 2') {
|
||||||
|
monster = 'Vol Opt ver.2';
|
||||||
|
} else if (monster === 'Za Boota') {
|
||||||
|
monster = 'Ze Boota';
|
||||||
|
} else if (monster === 'Saint Million') {
|
||||||
|
monster = 'Saint-Million';
|
||||||
|
}
|
||||||
|
|
||||||
$('td', tr).each((tdI, td) => {
|
$('td', tr).each((tdI, td) => {
|
||||||
if (tdI === 0) {
|
if (tdI === 0) {
|
||||||
@ -55,20 +103,21 @@ async function download(mode: string, modeUrl: string = mode) {
|
|||||||
if (isBox) {
|
if (isBox) {
|
||||||
$('font font', td).each((_, font) => {
|
$('font font', td).each((_, font) => {
|
||||||
const item = $('b', font).text();
|
const item = $('b', font).text();
|
||||||
const rareRateNum = parseFloat($('sup', font).text());
|
const rateNum = parseFloat($('sup', font).text());
|
||||||
const rareRateDenom = parseFloat($('sub', font).text());
|
const rateDenom = parseFloat($('sub', font).text());
|
||||||
|
|
||||||
data.push(
|
data.boxDrops.push(
|
||||||
[
|
[
|
||||||
mode,
|
mode,
|
||||||
episode,
|
episode,
|
||||||
sectionId,
|
sectionId,
|
||||||
`${monster} Box`,
|
monster,
|
||||||
item,
|
item,
|
||||||
1,
|
rateNum / rateDenom
|
||||||
rareRateNum / rareRateDenom
|
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
data.items.add(item);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
@ -85,7 +134,7 @@ async function download(mode: string, modeUrl: string = mode) {
|
|||||||
const [, rareRateNum, rareRateDenom] =
|
const [, rareRateNum, rareRateDenom] =
|
||||||
/Rare Rate: (\d+)\/(\d+(\.\d+)?)/g.exec(title)!.map(parseFloat);
|
/Rare Rate: (\d+)\/(\d+(\.\d+)?)/g.exec(title)!.map(parseFloat);
|
||||||
|
|
||||||
data.push(
|
data.enemyDrops.push(
|
||||||
[
|
[
|
||||||
mode,
|
mode,
|
||||||
episode,
|
episode,
|
||||||
@ -96,6 +145,8 @@ async function download(mode: string, modeUrl: string = mode) {
|
|||||||
rareRateNum / rareRateDenom,
|
rareRateNum / rareRateDenom,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
data.items.add(item);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`Error while processing item ${item} of ${monster} in episode ${episode} ${mode}.`, e);
|
console.error(`Error while processing item ${item} of ${monster} in episode ${episode} ${mode}.`, e);
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,23 @@
|
|||||||
import { observable } from "mobx";
|
import { observable } from "mobx";
|
||||||
import { HuntMethod, NpcType, Server, SimpleNpc, SimpleQuest } from "../domain";
|
import { HuntMethod, NpcType, Server, SimpleNpc, SimpleQuest } from "../domain";
|
||||||
import { Loadable } from "../Loadable";
|
import { Loadable } from "../Loadable";
|
||||||
import { PerServer } from "./PerServer";
|
import { ServerMap } from "./ServerMap";
|
||||||
|
|
||||||
class HuntMethodStore {
|
class HuntMethodStore {
|
||||||
@observable methods: PerServer<Loadable<Array<HuntMethod>>> = new PerServer(server =>
|
@observable methods: ServerMap<Loadable<Array<HuntMethod>>> = new ServerMap(server =>
|
||||||
new Loadable([], () => this.loadHuntMethods(server))
|
new Loadable([], () => this.loadHuntMethods(server))
|
||||||
);
|
);
|
||||||
|
|
||||||
private async loadHuntMethods(server: Server): Promise<HuntMethod[]> {
|
private async loadHuntMethods(server: Server): Promise<HuntMethod[]> {
|
||||||
const response = await fetch(process.env.PUBLIC_URL + `/quests.${Server[server]}.tsv`);
|
const response = await fetch(
|
||||||
|
`${process.env.PUBLIC_URL}/quests.${Server[server].toLowerCase()}.tsv`
|
||||||
|
);
|
||||||
const data = await response.text();
|
const data = await response.text();
|
||||||
const rows = data.split('\n').map(line => line.split('\t'));
|
const rows = data.split('\n').map(line => line.split('\t'));
|
||||||
|
|
||||||
const npcTypeByIndex = rows[0].slice(2, -2).map((episode, i) => {
|
const npcTypeByIndex = rows[0].slice(2, -2).map((episode, i) => {
|
||||||
const enemy = rows[1][i + 2];
|
const enemy = rows[1][i + 2];
|
||||||
return NpcType.bySimpleNameAndEpisode(enemy, parseInt(episode, 10))!;
|
return NpcType.byNameAndEpisode(enemy, parseInt(episode, 10))!;
|
||||||
});
|
});
|
||||||
|
|
||||||
return rows.slice(2).map(row => {
|
return rows.slice(2).map(row => {
|
||||||
@ -26,8 +28,10 @@ class HuntMethodStore {
|
|||||||
const type = npcTypeByIndex[cellI];
|
const type = npcTypeByIndex[cellI];
|
||||||
const enemies = [];
|
const enemies = [];
|
||||||
|
|
||||||
for (let i = 0; i < amount; i++) {
|
if (type) {
|
||||||
enemies.push(new SimpleNpc(type));
|
for (let i = 0; i < amount; i++) {
|
||||||
|
enemies.push(new SimpleNpc(type));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return enemies;
|
return enemies;
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { Solve } from 'javascript-lp-solver';
|
import { Solve } from 'javascript-lp-solver';
|
||||||
import { observable } from "mobx";
|
import { observable } from "mobx";
|
||||||
import { Item, SectionIds } from "../domain";
|
import { Difficulties, Item, NpcType, SectionIds } from "../domain";
|
||||||
import { huntMethodStore } from "./HuntMethodStore";
|
import { huntMethodStore } from "./HuntMethodStore";
|
||||||
|
import { itemDropStore } from './ItemDropStore';
|
||||||
|
|
||||||
export class WantedItem {
|
export class WantedItem {
|
||||||
@observable item: Item;
|
@observable item: Item;
|
||||||
@ -19,30 +20,55 @@ class HuntOptimizerStore {
|
|||||||
optimize = async () => {
|
optimize = async () => {
|
||||||
if (!this.wantedItems.length) return;
|
if (!this.wantedItems.length) return;
|
||||||
|
|
||||||
|
const methods = await huntMethodStore.methods.current.promise;
|
||||||
|
const dropTable = await itemDropStore.enemyDrops.current.promise;
|
||||||
|
|
||||||
const constraints: { [itemName: string]: { min: number } } = {};
|
const constraints: { [itemName: string]: { min: number } } = {};
|
||||||
|
|
||||||
for (const item of this.wantedItems) {
|
for (const wanted of this.wantedItems) {
|
||||||
constraints[item.item.name] = { min: item.amount };
|
constraints[wanted.item.name] = { min: wanted.amount };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const items = new Set(this.wantedItems.map(i => i.item));
|
||||||
const variables: { [methodName: string]: { [itemName: string]: number } } = {};
|
const variables: { [methodName: string]: { [itemName: string]: number } } = {};
|
||||||
|
|
||||||
for (const method of await huntMethodStore.methods.current.promise) {
|
for (const method of methods) {
|
||||||
for (const sectionId of SectionIds) {
|
const counts = new Map<NpcType, number>();
|
||||||
const variable = {};
|
|
||||||
|
|
||||||
// TODO
|
for (const enemy of method.quest.enemies) {
|
||||||
|
const count = counts.get(enemy.type);
|
||||||
|
counts.set(enemy.type, (count || 0) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
variables[`${sectionId} ${method.quest.name}`] = variable;
|
for (const diff of Difficulties) {
|
||||||
|
for (const sectionId of SectionIds) {
|
||||||
|
const variable: { [itemName: string]: number } = {
|
||||||
|
time: 0.5
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const [npcType, count] of counts.entries()) {
|
||||||
|
const drop = dropTable.getDrop(diff, sectionId, npcType);
|
||||||
|
|
||||||
|
if (drop && items.has(drop.item)) {
|
||||||
|
variable[drop.item.name] = count * drop.rate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.keys(variable).length) {
|
||||||
|
variables[`${diff} ${sectionId} ${method.quest.name}`] = variable;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = Solve({
|
const result = Solve({
|
||||||
optimize: '',
|
optimize: 'time',
|
||||||
opType: 'min',
|
opType: 'min',
|
||||||
constraints,
|
constraints,
|
||||||
variables
|
variables
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
102
src/stores/ItemDropStore.ts
Normal file
102
src/stores/ItemDropStore.ts
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
import { observable } from "mobx";
|
||||||
|
import { Difficulty, EnemyDrop, NpcType, SectionId, Server } from "../domain";
|
||||||
|
import { EnumMap } from "../enums";
|
||||||
|
import { Loadable } from "../Loadable";
|
||||||
|
import { itemStore } from "./ItemStore";
|
||||||
|
import { ServerMap } from "./ServerMap";
|
||||||
|
|
||||||
|
class EnemyDropTable {
|
||||||
|
private map: EnumMap<Difficulty, EnumMap<SectionId, Map<NpcType, EnemyDrop>>> =
|
||||||
|
new EnumMap(Difficulty, new EnumMap(SectionId, new Map()));
|
||||||
|
|
||||||
|
getDrop(difficulty: Difficulty, sectionId: SectionId, npcType: NpcType): EnemyDrop | undefined {
|
||||||
|
return this.map.get(difficulty).get(sectionId).get(npcType);
|
||||||
|
}
|
||||||
|
|
||||||
|
setDrop(difficulty: Difficulty, sectionId: SectionId, npcType: NpcType, drop: EnemyDrop) {
|
||||||
|
this.map.get(difficulty).get(sectionId).set(npcType, drop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ItemDropStore {
|
||||||
|
@observable enemyDrops: ServerMap<Loadable<EnemyDropTable>> = new ServerMap(server =>
|
||||||
|
new Loadable(new EnemyDropTable(), () => this.loadEnemyDrops(server))
|
||||||
|
);
|
||||||
|
|
||||||
|
private loadEnemyDrops = async (server: Server): Promise<EnemyDropTable> => {
|
||||||
|
const response = await fetch(
|
||||||
|
`${process.env.PUBLIC_URL}/enemy_drops.${Server[server].toLowerCase()}.tsv`
|
||||||
|
);
|
||||||
|
const data = await response.text();
|
||||||
|
const lines = data.split('\n');
|
||||||
|
const lineCount = lines.length;
|
||||||
|
|
||||||
|
const drops = new EnemyDropTable();
|
||||||
|
|
||||||
|
for (let i = 1; i < lineCount; i++) {
|
||||||
|
const line = lines[i];
|
||||||
|
const lineNo = i + 1;
|
||||||
|
const cells = line.split('\t');
|
||||||
|
const diffStr = cells[0].toLowerCase();
|
||||||
|
|
||||||
|
const diff =
|
||||||
|
diffStr === 'normal' ? Difficulty.Normal
|
||||||
|
: diffStr === 'hard' ? Difficulty.Hard
|
||||||
|
: diffStr === 'vhard' ? Difficulty.VHard
|
||||||
|
: diffStr === 'ultimate' ? Difficulty.Ultimate
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
if (!diff) {
|
||||||
|
console.error(`Couldn't parse difficulty for line ${lineNo}.`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const episode = parseInt(cells[1], 10);
|
||||||
|
|
||||||
|
if (episode !== 1 && episode !== 2 && episode !== 4) {
|
||||||
|
console.error(`Couldn't parse episode for line ${lineNo}.`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sectionId: SectionId | undefined = (SectionId as any)[cells[2]];
|
||||||
|
|
||||||
|
if (!sectionId) {
|
||||||
|
console.error(`Couldn't parse section_id for line ${lineNo}.`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const enemyName = cells[3];
|
||||||
|
|
||||||
|
const anythingRate = parseFloat(cells[5]);
|
||||||
|
|
||||||
|
if (!isFinite(anythingRate)) {
|
||||||
|
console.error(`Couldn't parse drop_rate for line ${lineNo}.`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rareRate = parseFloat(cells[5]);
|
||||||
|
|
||||||
|
if (!rareRate) {
|
||||||
|
console.error(`Couldn't parse rare_rate for line ${lineNo}.`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const npcType = NpcType.byNameAndEpisode(enemyName, episode);
|
||||||
|
|
||||||
|
if (!npcType) {
|
||||||
|
console.error(`Couldn't determine enemy type for line ${lineNo}.`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
drops.setDrop(diff, sectionId, npcType, new EnemyDrop(
|
||||||
|
itemStore.dedupItem(cells[4]),
|
||||||
|
anythingRate,
|
||||||
|
rareRate
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return drops;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const itemDropStore = new ItemDropStore();
|
@ -1,20 +1,31 @@
|
|||||||
import { sortedUniq } from "lodash";
|
|
||||||
import { observable } from "mobx";
|
import { observable } from "mobx";
|
||||||
import { Item, Server } from "../domain";
|
import { Item, Server } from "../domain";
|
||||||
import { Loadable } from "../Loadable";
|
import { Loadable } from "../Loadable";
|
||||||
import { PerServer } from "./PerServer";
|
import { ServerMap } from "./ServerMap";
|
||||||
|
|
||||||
class ItemStore {
|
class ItemStore {
|
||||||
@observable items: PerServer<Loadable<Array<Item>>> = new PerServer(server =>
|
private itemMap = new Map<string, Item>();
|
||||||
|
|
||||||
|
@observable items: ServerMap<Loadable<Array<Item>>> = new ServerMap(server =>
|
||||||
new Loadable([], () => this.loadItems(server))
|
new Loadable([], () => this.loadItems(server))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
dedupItem(name: string): Item {
|
||||||
|
let item = this.itemMap.get(name);
|
||||||
|
|
||||||
|
if (!item) {
|
||||||
|
this.itemMap.set(name, item = new Item(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
private async loadItems(server: Server): Promise<Item[]> {
|
private async loadItems(server: Server): Promise<Item[]> {
|
||||||
const response = await fetch(process.env.PUBLIC_URL + `/drops.${Server[server]}.tsv`);
|
const response = await fetch(
|
||||||
|
`${process.env.PUBLIC_URL}/items.${Server[server].toLowerCase()}.tsv`
|
||||||
|
);
|
||||||
const data = await response.text();
|
const data = await response.text();
|
||||||
return sortedUniq(
|
return data.split('\n').slice(1).map(name => new Item(name));
|
||||||
data.split('\n').slice(1).map(line => line.split('\t')[4]).sort()
|
|
||||||
).map(name => new Item(name));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
import { Server } from "../domain";
|
|
||||||
import { computed } from "mobx";
|
|
||||||
import { applicationStore } from "./ApplicationStore";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a value per server.
|
|
||||||
* E.g. drop tables differ per server, this can be represented by PerServer<DropTable>.
|
|
||||||
*/
|
|
||||||
export class PerServer<T> {
|
|
||||||
private values = new Map<Server, T>();
|
|
||||||
|
|
||||||
constructor(initialValue: T | ((server: Server) => T)) {
|
|
||||||
if (!(initialValue instanceof Function)) {
|
|
||||||
this.values.set(Server.Ephinea, initialValue);
|
|
||||||
} else {
|
|
||||||
this.values.set(Server.Ephinea, initialValue(Server.Ephinea));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get(server: Server): T {
|
|
||||||
return this.values.get(server)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns the value for the current server as set in {@link applicationStore}.
|
|
||||||
*/
|
|
||||||
@computed get current(): T {
|
|
||||||
return this.get(applicationStore.currentServer);
|
|
||||||
}
|
|
||||||
}
|
|
17
src/stores/ServerMap.ts
Normal file
17
src/stores/ServerMap.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { computed } from "mobx";
|
||||||
|
import { Server } from "../domain";
|
||||||
|
import { applicationStore } from "./ApplicationStore";
|
||||||
|
import { EnumMap } from "../enums";
|
||||||
|
|
||||||
|
export class ServerMap<V> extends EnumMap<Server, V> {
|
||||||
|
constructor(initialValue: V | ((server: Server) => V)) {
|
||||||
|
super(Server, initialValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns the value for the current server as set in {@link applicationStore}.
|
||||||
|
*/
|
||||||
|
@computed get current(): V {
|
||||||
|
return this.get(applicationStore.currentServer);
|
||||||
|
}
|
||||||
|
}
|
@ -31,14 +31,3 @@
|
|||||||
.ApplicationComponent-main>* {
|
.ApplicationComponent-main>* {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ApplicationComponent-error {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ApplicationComponent-error > div {
|
|
||||||
width: 300px;
|
|
||||||
margin-top: 30px;
|
|
||||||
}
|
|
@ -1,11 +1,15 @@
|
|||||||
import { Alert, Menu } from 'antd';
|
import { Menu } from 'antd';
|
||||||
import { ClickParam } from 'antd/lib/menu';
|
import { ClickParam } from 'antd/lib/menu';
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './ApplicationComponent.css';
|
import './ApplicationComponent.css';
|
||||||
|
import { withErrorBoundary } from './ErrorBoundary';
|
||||||
import { HuntOptimizerComponent } from './hunt-optimizer/HuntOptimizerComponent';
|
import { HuntOptimizerComponent } from './hunt-optimizer/HuntOptimizerComponent';
|
||||||
import { QuestEditorComponent } from './quest-editor/QuestEditorComponent';
|
import { QuestEditorComponent } from './quest-editor/QuestEditorComponent';
|
||||||
|
|
||||||
|
const QuestEditor = withErrorBoundary(QuestEditorComponent);
|
||||||
|
const HuntOptimizer = withErrorBoundary(HuntOptimizerComponent);
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class ApplicationComponent extends React.Component {
|
export class ApplicationComponent extends React.Component {
|
||||||
state = { tool: 'huntOptimizer' }
|
state = { tool: 'huntOptimizer' }
|
||||||
@ -15,10 +19,10 @@ export class ApplicationComponent extends React.Component {
|
|||||||
|
|
||||||
switch (this.state.tool) {
|
switch (this.state.tool) {
|
||||||
case 'questEditor':
|
case 'questEditor':
|
||||||
toolComponent = <QuestEditorComponent />;
|
toolComponent = <QuestEditor />;
|
||||||
break;
|
break;
|
||||||
case 'huntOptimizer':
|
case 'huntOptimizer':
|
||||||
toolComponent = <HuntOptimizerComponent />;
|
toolComponent = <HuntOptimizer />;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,9 +45,9 @@ export class ApplicationComponent extends React.Component {
|
|||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
</Menu>
|
</Menu>
|
||||||
</div>
|
</div>
|
||||||
<ErrorBoundary>
|
<div className="ApplicationComponent-main">
|
||||||
{toolComponent}
|
{toolComponent}
|
||||||
</ErrorBoundary>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -52,27 +56,3 @@ export class ApplicationComponent extends React.Component {
|
|||||||
this.setState({ tool: e.key });
|
this.setState({ tool: e.key });
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
class ErrorBoundary extends React.Component {
|
|
||||||
state = {
|
|
||||||
hasError: false
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div className="ApplicationComponent-main" >
|
|
||||||
{this.state.hasError ? (
|
|
||||||
<div className="ApplicationComponent-error">
|
|
||||||
<div>
|
|
||||||
<Alert type="error" message="Something went wrong." />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : this.props.children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static getDerivedStateFromError(_error: Error) {
|
|
||||||
return { hasError: true };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
10
src/ui/ErrorBoundary.css
Normal file
10
src/ui/ErrorBoundary.css
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
.ErrorBoundary-error {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ErrorBoundary-error > * {
|
||||||
|
margin-top: 10%;
|
||||||
|
}
|
31
src/ui/ErrorBoundary.tsx
Normal file
31
src/ui/ErrorBoundary.tsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { Alert } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
import './ErrorBoundary.css';
|
||||||
|
|
||||||
|
export class ErrorBoundary extends React.Component {
|
||||||
|
state = {
|
||||||
|
hasError: false
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (this.state.hasError) {
|
||||||
|
return (
|
||||||
|
<div className="ErrorBoundary-error">
|
||||||
|
<div>
|
||||||
|
<Alert type="error" message="Something went wrong." />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return this.props.children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static getDerivedStateFromError(_error: any) {
|
||||||
|
return { hasError: true };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function withErrorBoundary(Component: React.ComponentType) {
|
||||||
|
return () => <ErrorBoundary><Component /></ErrorBoundary>;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user