Hunt methods are now loaded for ephinea.

This commit is contained in:
Daan Vanden Bosch 2019-06-01 16:02:06 +02:00
parent 0dc55b5eb7
commit 0c9218be16
17 changed files with 520 additions and 234 deletions

129
public/quests.ephinea.tsv Normal file
View 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
1 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
2 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
3 Valentine's Event 0,50 8 3 11 9 11 3 23 5
4 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
5 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
6 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
7 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
8 Principal's Gift 0,50 6 68 2 22 3 20 1
9 White Day 0,50 26 5 24 24 24 7 4
10 Endless Nightmare #1 0,50 8 19 4 29 4 60 32 23
11 Endless Nightmare #2 0,50 20 32 6 152 44 28 5
12 Endless Nightmare #3 0,50 37 108 10 48 14 84 2 8
13 Endless Nightmare #4 0,50 44 3 21 13 28 49 59 49 6 90
14 Mop-up Operation #1 0,50 2 10 5 14 23 36
15 Mop-up Operation #2 0,50 10 9 18 72 21 24
16 Mop-up Operation #3 0,50 9 59 6 17 7 55 2 2
17 Mop-up Operation #4 0,50 13 5 6 12 35 27 33 50
18 Today's Rate 0,50 52 7 1 1 53 5 6 9 47 6 27 7 25 3
19 Fragment of Memory 0,50 81 68 77 16 38 226 86 237 1
20 Gallon's Treachery 0,50 22 7 16 13 14 5 1 3 2 3 3 3 10 12
21 Lost HAVOC VULCAN 0,50 68 28 81 49 54 156 94 89 36 152 1
22 Lost HEAT SWORD 0,33 12 10 7 26 7 34 38 53 1
23 Lost ICE SPINNER 1,00 37 56 26 129 65 125 7 5 1
24 Lost SOUL BLADE 0,50 17 85 26 70 37 112 4 4 1
25 Rappy's Holiday 0,50 75 10 15 20 20 11 13
26 Labyrinthine Trial 0,50 14 15 2 10 38 16 12 6
27 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
28 Dream Messenger 0,50 8 8 1 49
29 Festivity On The Beach 0,50 15
30 Pioneer Halloween 0,50 2 57 25 1 51 8 30 1
31 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
32 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
33 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
34 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
35 Phantasmal World #1 0,50 25 7 83 41 6 45 20 122 12
36 Phantasmal World #2 0,50 24 9 54 42 114 26 9 80
37 Phantasmal World #3 0,50 31 27 103 57 47 27 33 22
38 Phantasmal World #4 1,00 11 6 6 20 22 19 20 9 72 57
39 The East Tower 0,50 2 2 16 5 1 3 6 9 6 8 8 3 14 1 4 7
40 The West Tower 0,50 6 1 1 5 7 14 10 10 36 1 7 6 8 9
41 Reach for the Dream 0,50 4 2 6 19 3 1 7
42 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
43 LOGiN presents 勇場のマッチレース 0,50 88 19 46 70 84 14 20 59 51 22 4 94 52 22
44 Maximum Attack 4th Stage -A- (Ep. IV) 0,33 57 13 68 56 58 20 18 13 16 3 30 26 6
45 Maximum Attack 4th Stage -B- (Ep. IV) 0,33 60 11 58 50 20 3 48 24 15 17 3 40 32 19
46 Maximum Attack 4th Stage -C- (Ep. IV) 0,33 73 16 69 74 37 6 33 20 22 16 13 37 26 18
47 New Mop-up Operation #1 0,50 37 22 32 20 8 20 5 5 2
48 New Mop-up Operation #2 0,50 20 11 41 23 5 31 36 14 5
49 New Mop-up Operation #3 0,50 38 73 41 4 4 108 55 16
50 New Mop-up Operation #4 0,50 29 25 38 24 1 46 40 3
51 New Mop-up Operation #5 0,50 11 38 40 25 4 19 37 30 7
52 War of Limits 1 0,50 42 42 51 25 12 47 12 10 5
53 War of Limits 2 0,50 37 11 92 37 5 39 74 25 3
54 War of Limits 3 0,50 47 37 66 6 85 87 26 4
55 War of Limits 4 0,50 26 30 26 28 3 1 37 36 16
56 War of Limits 5 0,50 44 48 41 11 4 15 49 19 7
57 MAXIMUM ATTACK 3 Ver2 0,50 83 54 122 115 99 4 46 45 39 47 10 101 103 32
58 1-1:Planet Ragol 0,50 2 4 36 4 40 7 6
59 1-2:Torrential Woods 0,50 5 17 3 19 7 35 31 16
60 1-3:Subterranean Den 0,50 5 12 3 33 10 45 32 15 1
61 2-1:Infernal Cavern 0,75 18 37 17 114 18 3
62 2-2:Deep Within 0,75 20 59 15 165 31 7 16
63 2-3:The Mutation 0,75 7 41 12 89 42 24 10 2 13
64 2-4:Waterway Shadow 0,75 16 36 4 17 165 87 28 4 4 1
65 3-1:The Facility 0,75 3 115 12 2 47 2 1
66 3-2:Machines Attack 0,75 22 60 9 14 2 59 2 7
67 3-3:Central Control 0,75 11 93 4 16 6 90 3 3 1
68 4-1:The Lost Ruins 0,75 14 42 3 8 4 41 1 4 10 13 18 61 7 3 5 89
69 4-2:Buried Relics 0,75 31 20 2 28 55 6 5 50
70 4-3:Hero & Daughter 0,75 26 4 30 7 5 75 50 22 8 122
71 4-4:The Tomb Stirs 0,75 17 16 10 25 82 35 34 7 55
72 4-5:Dark Inheritance 0,75 26 11 36 9 12 111 78 44 6 143 1
73 5-1:Test/VR Temple 1 0,75 5 13 3 29 2 16 17 33
74 5-2:Test/VR Temple 2 0,75 11 23 6 52 17 21 25 15 7
75 5-3:Test/VR Temple 3 0,75 9 4 4 35 12 17 17 12 9
76 5-4:Test/VR Temple 4 0,75 5 29 5 56 5 24 14 47 23 8
77 5-5:Test/VR Temple 5 0,75 11 26 6 63 16 21 34 27 9 1
78 6-1:Test/Spaceship 1 0,75 32 24 5 54 7 12
79 6-2:Test/Spaceship 2 0,75 50 24 9 8 84 5 3 17 5
80 6-3:Test/Spaceship 3 0,75 36 27 15 16 50 1 5 26 5
81 6-4:Test/Spaceship 4 0,75 39 36 8 10 87 6 3 25 11
82 6-5:Test/Spaceship 5 0,75 41 32 10 10 92 5 3 27 11 1
83 7-1:From the Past 0,75 3 55 17 4 20 3 20
84 7-2:Seeking Clues 0,75 3 37 19 1 25 43 6 8
85 7-3:Silent Beach 0,75 4 29 8 30 45 1 94 5
86 7-4:Central Control 0,75 11 6 22 6 4 17 18 3 34 4
87 7-5:Isle of Mutants 0,75 11 6 59 42 1 43 56 1 132 1 1
88 8-1:Below the Waves 0,75 9 3 35 17 25 23 3
89 8-2:Desire's End 0,75 2 4 34 43 25 28 24 5
90 8-3:Purple Lamplight 0,75 7 7 23 38 19 41 39 4 1
91 9-1:Missing Research 0,75 26 10 40 12 67 48 27 1
92 9-2:Data Retrieval 0,75 41 18 28 18 48 21 24 5
93 9-3:Reality & Truth 0,75 24 9 31 4 13 21 22 50 1
94 9-4:Pursuit 0,75 30 17 34 5 17 45 55 29 5
95 9-5:The Chosen (1/2) 0,75 36 5 46 9 25 10 12 5 3 2 62 20 9
96 9-6:The Chosen (2/2) 0,75 12 21 19 34 1 2 25 34 4
97 9-7:Sacred Ground 0,75 28 39 11 29 1 5 54 38 11
98 9-8:The Final Cycle 0,75 45 41 63 47 1 6 57 61 8 1
99 Point of Disaster 0,25 50 31 50 31 4 1 20 24 8 6 9 10 4 3 1
100 Battle Training 0,50 2 2 12 2 14 3
101 Claiming a Stake 0,50 5 1 1 19 2
102 Magnitude of Metal 0,50 4 1 16
103 Journalistic Pursuit 0,50 1 11 3 12 1 18 9 6
104 The Fake in Yellow 0,50 47
105 Native Research 0,50 2 13 4 10 4 29 13 8
106 Forest of Sorrow 0,13 16 15 4 14 7 26 15 3
107 Gran Squall 0,50 4 15 7 18 4 24 13 7
108 Addicting Food 0,50 19 62 2 19 195 38 15 13 7
109 The Lost Bride 0,50 2 20 2 33 6 5 7
110 Waterfall Tears 0,50 6 18 12 37 6 1
111 Black Paper 0,50 12 20 2 14 94 31 10 8 3
112 Secret Delivery 0,50 9 18 5 59 9 5 5
113 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
114 Letter from Lionel 0,50 5 17 2 19 4 34 15 5 4 36 2 74 19 9 11 1
115 The Grave's Butler 0,50 9 22 4 35 7 2 1
116 Knowing One's Heart 0,50 22 5 2 29 1
117 The Retired Hunter 0,50 1 8 2 7 6 6 4 3 3 3 4 17 7 18 1 42
118 Dr. Osto's Research 0,50 13 27 3 2 15 3
119 Unsealed Door 0,50 1 13 97 6 2 62 3 3
120 Soul of Steel 0,50 22 1 2 1 5 11 4 7 14 12 14 4 40
121 Doc's Secret Plan 0,50 9 11 7 47 7 1 6 29
122 Seek my Master 0,50 21 3 20 2 9 43 24 4 2 86
123 From the Depths 0,50 11 3 17 6 4 41 23 11 7 71
124 Central Dome Fire Swirl 0,50 4 19 19 14 9 19 34
125 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
126 Pioneer Spirit 0,50 40 1 14 25 29 31 3 21 8 2 4 4 40 29 5
127 Warrior's Pride 0,50 61 46 51 53 29 35 10 23 13
128 The Restless Lion 0,50 8 16 13 14 3 13 10 1
129 To the End of the Wilderness 0,50 56 14 14 41 13 77 55 47 2

View 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));
}
);

View File

@ -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);
});

View File

@ -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);

View File

@ -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;
});

View 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
)
);
});
}

View File

@ -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);
}());

View File

@ -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.');
}
}

View File

@ -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) {

View File

@ -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

View 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();

View File

@ -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();

View File

@ -1,8 +1,4 @@
.HuntOptimizerComponent {
.ho-HuntOptimizerComponent {
display: flex;
align-items: stretch;
}
.HuntOptimizerComponent-wanted-items {
margin: 10px;
}

View File

@ -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));
}
}
}
}

View File

@ -0,0 +1,7 @@
.ho-WantedItemsComponent {
margin: 10px;
}
.ho-WantedItemsComponent-table {
margin-top: 10px;
}

View 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;
}
}
}

View File

@ -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'
}> {