From 92ee40de6533f6fbe23865d6985e8e0ff5024052 Mon Sep 17 00:00:00 2001 From: Daan Vanden Bosch Date: Thu, 6 Jun 2019 15:42:02 +0200 Subject: [PATCH] Hunt optimizer now takes rare enemies into account. --- public/enemy_drops.ephinea.tsv | 40 +++++++++---------- public/quests.ephinea.tsv | 2 +- src/bin-data/parsing/quest.ts | 4 +- src/domain/NpcType.ts | 32 ++++++++++----- src/domain/index.ts | 3 ++ src/static/updateDropsEphinea.ts | 2 +- src/stores/HuntOptimizerStore.ts | 32 ++++++++++++--- .../hunt-optimizer/WantedItemsComponent.tsx | 4 +- 8 files changed, 78 insertions(+), 41 deletions(-) diff --git a/public/enemy_drops.ephinea.tsv b/public/enemy_drops.ephinea.tsv index 96d8927e..d56adb1e 100644 --- a/public/enemy_drops.ephinea.tsv +++ b/public/enemy_drops.ephinea.tsv @@ -3093,16 +3093,16 @@ vhard 4 Redria Girtablulu Heaven Striker Coat 0.8 0.015625 vhard 4 Oran Girtablulu Stink Shield 0.8 0.0078125 vhard 4 Yellowboze Girtablulu Heaven Striker Coat 0.8 0.015625 vhard 4 Whitill Girtablulu Heaven Striker Coat 0.8 0.015625 -vhard 4 Viridia Saint-Million Revival Cuirass 1 0.0625 -vhard 4 Greenill Saint-Million Revival Cuirass 1 0.0625 -vhard 4 Skyly Saint-Million Spirit Cuirass 1 0.0625 -vhard 4 Bluefull Saint-Million Revival Cuirass 1 0.0625 -vhard 4 Purplenum Saint-Million Spirit Cuirass 1 0.0625 -vhard 4 Pinkal Saint-Million Spirit Cuirass 1 0.0625 -vhard 4 Redria Saint-Million Spirit Cuirass 1 0.0625 -vhard 4 Oran Saint-Million Revival Cuirass 1 0.0625 -vhard 4 Yellowboze Saint-Million Revival Cuirass 1 0.0625 -vhard 4 Whitill Saint-Million Spirit Cuirass 1 0.0625 +vhard 4 Viridia Saint-Milion Revival Cuirass 1 0.0625 +vhard 4 Greenill Saint-Milion Revival Cuirass 1 0.0625 +vhard 4 Skyly Saint-Milion Spirit Cuirass 1 0.0625 +vhard 4 Bluefull Saint-Milion Revival Cuirass 1 0.0625 +vhard 4 Purplenum Saint-Milion Spirit Cuirass 1 0.0625 +vhard 4 Pinkal Saint-Milion Spirit Cuirass 1 0.0625 +vhard 4 Redria Saint-Milion Spirit Cuirass 1 0.0625 +vhard 4 Oran Saint-Milion Revival Cuirass 1 0.0625 +vhard 4 Yellowboze Saint-Milion Revival Cuirass 1 0.0625 +vhard 4 Whitill Saint-Milion Spirit Cuirass 1 0.0625 vhard 4 Viridia Shambertin Dragon Scale 1 0.015625 vhard 4 Greenill Shambertin Dragon Scale 1 0.015625 vhard 4 Skyly Shambertin Dragon Scale 1 0.015625 @@ -4273,16 +4273,16 @@ ultimate 4 Redria Girtablulu Gratia 0.8 0.006347594261774787 ultimate 4 Oran Girtablulu Syncesta 0.8 0.0010986354947155632 ultimate 4 Yellowboze Girtablulu Kamui 0.8 0.006347594261774787 ultimate 4 Whitill Girtablulu Rage de Feu 0.8 0.006347594261774787 -ultimate 4 Viridia Saint-Million Heavenly/Ability 1 0.025393600812595226 -ultimate 4 Greenill Saint-Million Galatine 1 0.015625 -ultimate 4 Skyly Saint-Million Laconium Axe 1 0.025393600812595226 -ultimate 4 Bluefull Saint-Million Siren Glass Hammer 1 0.03125 -ultimate 4 Purplenum Saint-Million Heavenly/Ability 1 0.025393600812595226 -ultimate 4 Pinkal Saint-Million Rupika 1 0.03125 -ultimate 4 Redria Saint-Million Heavenly/Ability 1 0.025393600812595226 -ultimate 4 Oran Saint-Million Rupika 1 0.03125 -ultimate 4 Yellowboze Saint-Million Galatine 1 0.015625 -ultimate 4 Whitill Saint-Million Crimson Coat 1 0.025393600812595226 +ultimate 4 Viridia Saint-Milion Heavenly/Ability 1 0.025393600812595226 +ultimate 4 Greenill Saint-Milion Galatine 1 0.015625 +ultimate 4 Skyly Saint-Milion Laconium Axe 1 0.025393600812595226 +ultimate 4 Bluefull Saint-Milion Siren Glass Hammer 1 0.03125 +ultimate 4 Purplenum Saint-Milion Heavenly/Ability 1 0.025393600812595226 +ultimate 4 Pinkal Saint-Milion Rupika 1 0.03125 +ultimate 4 Redria Saint-Milion Heavenly/Ability 1 0.025393600812595226 +ultimate 4 Oran Saint-Milion Rupika 1 0.03125 +ultimate 4 Yellowboze Saint-Milion Galatine 1 0.015625 +ultimate 4 Whitill Saint-Milion Crimson Coat 1 0.025393600812595226 ultimate 4 Viridia Shambertin Dragon Scale 1 0.021482277121374866 ultimate 4 Greenill Shambertin Dragon Scale 1 0.021482277121374866 ultimate 4 Skyly Shambertin Dragon Scale 1 0.021482277121374866 diff --git a/public/quests.ephinea.tsv b/public/quests.ephinea.tsv index fe8a9ada..a7bf8f47 100644 --- a/public/quests.ephinea.tsv +++ b/public/quests.ephinea.tsv @@ -1,5 +1,5 @@ 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 +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-Milion 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 diff --git a/src/bin-data/parsing/quest.ts b/src/bin-data/parsing/quest.ts index 8ed995c8..e9d3d959 100644 --- a/src/bin-data/parsing/quest.ts +++ b/src/bin-data/parsing/quest.ts @@ -272,7 +272,7 @@ function getNpcType(episode: number, { typeId, unknown, skin, areaId }: DatNpc): case `${0x114}, 1, 4`: return NpcType.Pazuzu; case `${0x116}, 0, 4`: return NpcType.Dorphon; case `${0x116}, 1, 4`: return NpcType.DorphonEclair; - case `${0x119}, 0, 4`: return regular ? NpcType.SaintMillion : NpcType.Kondrieu; + case `${0x119}, 0, 4`: return regular ? NpcType.SaintMilion : NpcType.Kondrieu; case `${0x119}, 1, 4`: return regular ? NpcType.Shambertin : NpcType.Kondrieu; } @@ -531,7 +531,7 @@ function npcTypeToDatData( case NpcType.Goran: return { typeId: 0x117, skin: 0, regular: true }; case NpcType.PyroGoran: return { typeId: 0x117, skin: 1, regular: true }; case NpcType.GoranDetonator: return { typeId: 0x117, skin: 2, regular: true }; - case NpcType.SaintMillion: return { typeId: 0x119, skin: 0, regular: true }; + case NpcType.SaintMilion: return { typeId: 0x119, skin: 0, regular: true }; case NpcType.Shambertin: return { typeId: 0x119, skin: 1, regular: true }; case NpcType.Kondrieu: return { typeId: 0x119, skin: 0, regular: false }; } diff --git a/src/domain/NpcType.ts b/src/domain/NpcType.ts index 9fc4d2bd..8c5755c2 100644 --- a/src/domain/NpcType.ts +++ b/src/domain/NpcType.ts @@ -1,18 +1,19 @@ export class NpcType { - id: number; - code: string; + readonly id: number; + readonly code: string; /** * Unique name. E.g. a Delsaber would have (Ep. II) appended to its name. */ - name: string; + readonly name: string; /** * Name used in the game. * Might conflict with other NPC names (e.g. Delsaber from ep. I and ep. II). */ - simpleName: string; - ultimateName: string; - episode?: number; - enemy: boolean; + readonly simpleName: string; + readonly ultimateName: string; + readonly episode?: number; + readonly enemy: boolean; + rareType?: NpcType; constructor( id: number, @@ -243,7 +244,7 @@ export class NpcType { static Goran: NpcType; static PyroGoran: NpcType; static GoranDetonator: NpcType; - static SaintMillion: NpcType; + static SaintMilion: NpcType; static Shambertin: NpcType; static Kondrieu: NpcType; } @@ -287,8 +288,10 @@ export class NpcType { NpcType.Hildebear = new NpcType(id++, 'Hildebear', 'Hildebear', 'Hildebear', 'Hildelt', 1, true); NpcType.Hildeblue = new NpcType(id++, 'Hildeblue', 'Hildeblue', 'Hildeblue', 'Hildetorr', 1, true); + NpcType.Hildebear.rareType = NpcType.Hildeblue; NpcType.RagRappy = new NpcType(id++, 'RagRappy', 'Rag Rappy', 'Rag Rappy', 'El Rappy', 1, true); NpcType.AlRappy = new NpcType(id++, 'AlRappy', 'Al Rappy', 'Al Rappy', 'Pal Rappy', 1, true); + NpcType.RagRappy.rareType = NpcType.AlRappy; NpcType.Monest = new NpcType(id++, 'Monest', 'Monest', 'Monest', 'Mothvist', 1, true); NpcType.Mothmant = new NpcType(id++, 'Mothmant', 'Mothmant', 'Mothmant', 'Mothvert', 1, true); NpcType.SavageWolf = new NpcType(id++, 'SavageWolf', 'Savage Wolf', 'Savage Wolf', 'Gulgus', 1, true); @@ -303,12 +306,14 @@ export class NpcType { NpcType.GrassAssassin = new NpcType(id++, 'GrassAssassin', 'Grass Assassin', 'Grass Assassin', 'Crimson Assassin', 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', 'Mil Lily', 1, true); + NpcType.PoisonLily.rareType = NpcType.NarLily; NpcType.NanoDragon = new NpcType(id++, 'NanoDragon', 'Nano Dragon', 'Nano Dragon', 'Nano Dragon', 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', 'Govulmer', 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', 'Pofuilly Slime', 1, true); NpcType.PouillySlime = new NpcType(id++, 'PouillySlime', 'Pouilly Slime', 'Pouilly Slime', 'Pouilly Slime', 1, true); + NpcType.PofuillySlime.rareType = NpcType.PouillySlime; NpcType.PanArms = new NpcType(id++, 'PanArms', 'Pan Arms', 'Pan Arms', 'Pan Arms', 1, true); NpcType.Migium = new NpcType(id++, 'Migium', 'Migium', 'Migium', 'Migium', 1, true); NpcType.Hidoom = new NpcType(id++, 'Hidoom', 'Hidoom', 'Hidoom', 'Hidoom', 1, true); @@ -346,8 +351,10 @@ export class NpcType { NpcType.Hildebear2 = new NpcType(id++, 'Hildebear2', 'Hildebear (Ep. II)', 'Hildebear', 'Hildelt', 2, true); NpcType.Hildeblue2 = new NpcType(id++, 'Hildeblue2', 'Hildeblue (Ep. II)', 'Hildeblue', 'Hildetorr', 2, true); + NpcType.Hildebear2.rareType = NpcType.Hildeblue2; 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', 'Love Rappy', 2, true); + NpcType.RagRappy2.rareType = NpcType.LoveRappy; NpcType.StRappy = new NpcType(id++, 'StRappy', 'St. Rappy', 'St. Rappy', 'St. Rappy', 2, true); NpcType.HalloRappy = new NpcType(id++, 'HalloRappy', 'Hallo Rappy', 'Hallo Rappy', 'Hallo Rappy', 2, true); NpcType.EggRappy = new NpcType(id++, 'EggRappy', 'Egg Rappy', 'Egg Rappy', 'Egg Rappy', 2, true); @@ -355,6 +362,7 @@ export class NpcType { NpcType.Mothmant2 = new NpcType(id++, 'Mothmant2', 'Mothmant', 'Mothmant', 'Mothvert', 2, true); NpcType.PoisonLily2 = new NpcType(id++, 'PoisonLily2', 'Poison Lily (Ep. II)', 'Poison Lily', 'Ob Lily', 2, true); NpcType.NarLily2 = new NpcType(id++, 'NarLily2', 'Nar Lily (Ep. II)', 'Nar Lily', 'Mil Lily', 2, true); + NpcType.PoisonLily2.rareType = NpcType.NarLily2; NpcType.GrassAssassin2 = new NpcType(id++, 'GrassAssassin2', 'Grass Assassin (Ep. II)', 'Grass Assassin', 'Crimson Assassin', 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); @@ -413,23 +421,29 @@ export class NpcType { NpcType.SandRappy = new NpcType(id++, 'SandRappy', 'Sand Rappy', 'Sand Rappy', 'Sand Rappy', 4, true); NpcType.DelRappy = new NpcType(id++, 'DelRappy', 'Del Rappy', 'Del Rappy', 'Del Rappy', 4, true); + NpcType.SandRappy.rareType = NpcType.DelRappy; NpcType.Astark = new NpcType(id++, 'Astark', 'Astark', 'Astark', 'Astark', 4, true); NpcType.SatelliteLizard = new NpcType(id++, 'SatelliteLizard', 'Satellite Lizard', 'Satellite Lizard', 'Satellite Lizard', 4, true); NpcType.Yowie = new NpcType(id++, 'Yowie', 'Yowie', 'Yowie', 'Yowie', 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', 'Merissa AA', 4, true); + NpcType.MerissaA.rareType = NpcType.MerissaAA; NpcType.Girtablulu = new NpcType(id++, 'Girtablulu', 'Girtablulu', 'Girtablulu', 'Girtablulu', 4, true); NpcType.Zu = new NpcType(id++, 'Zu', 'Zu', 'Zu', 'Zu', 4, true); NpcType.Pazuzu = new NpcType(id++, 'Pazuzu', 'Pazuzu', 'Pazuzu', 'Pazuzu', 4, true); + NpcType.Zu.rareType = NpcType.Pazuzu; NpcType.Boota = new NpcType(id++, 'Boota', 'Boota', 'Boota', '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', 'Ba Boota', 4, true); NpcType.Dorphon = new NpcType(id++, 'Dorphon', 'Dorphon', 'Dorphon', 'Dorphon', 4, true); NpcType.DorphonEclair = new NpcType(id++, 'DorphonEclair', 'Dorphon Eclair', 'Dorphon Eclair', 'Dorphon Eclair', 4, true); + NpcType.Dorphon.rareType = NpcType.DorphonEclair; NpcType.Goran = new NpcType(id++, 'Goran', 'Goran', 'Goran', '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', 'Goran Detonator', 4, true); - NpcType.SaintMillion = new NpcType(id++, 'SaintMillion', 'Saint-Million', 'Saint-Million', 'Saint-Million', 4, true); + NpcType.SaintMilion = new NpcType(id++, 'SaintMilion', 'Saint-Milion', 'Saint-Milion', 'Saint-Milion', 4, true); NpcType.Shambertin = new NpcType(id++, 'Shambertin', 'Shambertin', 'Shambertin', 'Shambertin', 4, true); NpcType.Kondrieu = new NpcType(id++, 'Kondrieu', 'Kondrieu', 'Kondrieu', 'Kondrieu', 4, true); + NpcType.SaintMilion.rareType = NpcType.Kondrieu; + NpcType.Shambertin.rareType = NpcType.Kondrieu; }()); diff --git a/src/domain/index.ts b/src/domain/index.ts index 8ba6a48f..9e4cc26e 100644 --- a/src/domain/index.ts +++ b/src/domain/index.ts @@ -9,6 +9,9 @@ import { enumValues } from '../enums'; export { NpcType } from './NpcType'; export { ObjectType } from './ObjectType'; +export const RARE_ENEMY_PROB = 1 / 512; +export const KONDRIEU_PROB = 1 / 512; + export enum Server { Ephinea = 'Ephinea' } diff --git a/src/static/updateDropsEphinea.ts b/src/static/updateDropsEphinea.ts index af420ae8..effd534b 100644 --- a/src/static/updateDropsEphinea.ts +++ b/src/static/updateDropsEphinea.ts @@ -90,7 +90,7 @@ async function download(mode: string, modeUrl: string = mode) { } else if (monster === 'Za Boota') { monster = 'Ze Boota'; } else if (monster === 'Saint Million') { - monster = 'Saint-Million'; + monster = 'Saint-Milion'; } $('td', tr).each((tdI, td) => { diff --git a/src/stores/HuntOptimizerStore.ts b/src/stores/HuntOptimizerStore.ts index 30e2e103..bdf3c8da 100644 --- a/src/stores/HuntOptimizerStore.ts +++ b/src/stores/HuntOptimizerStore.ts @@ -1,6 +1,6 @@ import solver from 'javascript-lp-solver'; import { IObservableArray, observable, runInAction } from "mobx"; -import { Difficulties, Difficulty, Item, NpcType, SectionId, SectionIds } from "../domain"; +import { Difficulties, Difficulty, Item, NpcType, SectionId, SectionIds, KONDRIEU_PROB, RARE_ENEMY_PROB } from "../domain"; import { huntMethodStore } from "./HuntMethodStore"; import { itemDropStore } from './ItemDropStore'; @@ -29,11 +29,12 @@ export class OptimizationResult { } } +// TODO: Deal with hidoom and migium. +// TODO: Row of totals. // TODO: group similar methods (e.g. same difficulty, same quest and similar ID). -// This way people can choose their preferred section ID. -// TODO: boxes. -// TODO: rare enemy variants. +// This way people can choose their preferred section ID. // TODO: order of items in results table should match order in wanted table. +// TODO: boxes. class HuntOptimizerStore { @observable readonly wantedItems: Array = []; @observable readonly result: IObservableArray = observable.array(); @@ -63,14 +64,33 @@ class HuntOptimizerStore { } const variables: { [methodName: string]: Variable } = {}; - const wantedItems = new Set(this.wantedItems.map(i => i.item)); + const wantedItems = new Set(this.wantedItems.filter(w => w.amount > 0).map(w => w.item)); for (const method of methods) { + // Counts include rare enemies, so they are fractional. const counts = new Map(); for (const enemy of method.quest.enemies) { const count = counts.get(enemy.type); - counts.set(enemy.type, (count || 0) + 1); + + if (enemy.type.rareType == null) { + counts.set(enemy.type, (count || 0) + 1); + } else { + let rate, rareRate; + + if (enemy.type.rareType === NpcType.Kondrieu) { + rate = 1 - KONDRIEU_PROB; + rareRate = KONDRIEU_PROB; + } else { + rate = 1 - RARE_ENEMY_PROB; + rareRate = RARE_ENEMY_PROB; + } + + counts.set(enemy.type, (count || 0) + rate); + + const rareCount = counts.get(enemy.type.rareType); + counts.set(enemy.type.rareType, (rareCount || 0) + rareRate); + } } for (const diff of Difficulties) { diff --git a/src/ui/hunt-optimizer/WantedItemsComponent.tsx b/src/ui/hunt-optimizer/WantedItemsComponent.tsx index 6bf7b7d6..9eeec229 100644 --- a/src/ui/hunt-optimizer/WantedItemsComponent.tsx +++ b/src/ui/hunt-optimizer/WantedItemsComponent.tsx @@ -106,7 +106,7 @@ class WantedAmountCell extends React.Component<{ wantedItem: WantedItem }> { return ( { } private wantedAmountChanged = (value?: number) => { - if (value && value >= 1) { + if (value != null && value >= 0) { this.props.wantedItem.amount = value; } }