| 
									
										
										
										
											2021-06-25 23:32:13 +02:00
										 |  |  | import typing | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  | from .ExtractedData import logic_options, starts, pool_options | 
					
						
							|  |  |  | from Options import Option, DefaultOnToggle, Toggle, Choice, Range | 
					
						
							| 
									
										
										
										
											2022-04-08 19:22:50 +02:00
										 |  |  | from .Charms import vanilla_costs | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-01 03:42:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | class Disabled(Toggle): | 
					
						
							|  |  |  |     def __init__(self, value: int): | 
					
						
							|  |  |  |         super(Disabled, self).__init__(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @classmethod | 
					
						
							|  |  |  |     def from_text(cls, text: str) -> Toggle: | 
					
						
							|  |  |  |         return cls(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @classmethod | 
					
						
							|  |  |  |     def from_any(cls, data: typing.Any): | 
					
						
							|  |  |  |         return cls(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-01 03:32:17 +02:00
										 |  |  | locations = {"option_" + start: i for i, start in enumerate(starts)} | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  | # This way the dynamic start names are picked up by the MetaClass Choice belongs to | 
					
						
							| 
									
										
										
										
											2022-04-03 18:10:13 -04:00
										 |  |  | StartLocation = type("StartLocation", (Choice,), {"__module__": __name__, "auto_display_name": False, **locations, | 
					
						
							|  |  |  |                                                   "__doc__": "Choose your start location. " | 
					
						
							|  |  |  |                                                              "This is currently only locked to King's Pass."}) | 
					
						
							| 
									
										
										
										
											2022-04-01 03:32:17 +02:00
										 |  |  | del (locations) | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-03 18:10:13 -04:00
										 |  |  | option_docstrings = { | 
					
						
							|  |  |  |     "RandomizeDreamers": "Allow for Dreamers to be randomized into the item pool and opens their locations for " | 
					
						
							|  |  |  |                          "randomization.", | 
					
						
							|  |  |  |     "RandomizeSkills": "Allow for Skills, such as Mantis Claw or Shade Soul, to be randomized into the item pool. " | 
					
						
							|  |  |  |                        "Also opens their locations for receiving randomized items.", | 
					
						
							|  |  |  |     "RandomizeCharms": "Allow for Charms to be randomized into the item pool and open their locations for " | 
					
						
							|  |  |  |                        "randomization. Includes Charms sold in shops.", | 
					
						
							|  |  |  |     "RandomizeKeys": "Allow for Keys to be randomized into the item pool. Includes those sold in shops.", | 
					
						
							|  |  |  |     "RandomizeMaskShards": "Allow for Mask Shard to be randomized into the item pool and open their locations for" | 
					
						
							|  |  |  |                            " randomization.", | 
					
						
							|  |  |  |     "RandomizeVesselFragments": "Allow for Vessel Fragments to be randomized into the item pool and open their " | 
					
						
							|  |  |  |                                 "locations for randomization.", | 
					
						
							|  |  |  |     "RandomizeCharmNotches": "Allow for Charm Notches to be randomized into the item pool. " | 
					
						
							|  |  |  |                              "Includes those sold by Salubra.", | 
					
						
							|  |  |  |     "RandomizePaleOre": "Randomize Pale Ores into the item pool and open their locations for randomization.", | 
					
						
							|  |  |  |     "RandomizeGeoChests": "Allow for Geo Chests to contain randomized items, " | 
					
						
							|  |  |  |                           "as well as their Geo reward being randomized into the item pool.", | 
					
						
							|  |  |  |     "RandomizeJunkPitChests": "Randomize the contents of junk pit chests into the item pool and open their locations " | 
					
						
							|  |  |  |                               "for randomization.", | 
					
						
							|  |  |  |     "RandomizeRancidEggs": "Randomize Rancid Eggs into the item pool and open their locations for randomization", | 
					
						
							|  |  |  |     "RandomizeRelics": "Randomize Relics (King's Idol, et al.) into the item pool and open their locations for" | 
					
						
							|  |  |  |                        " randomization.", | 
					
						
							|  |  |  |     "RandomizeWhisperingRoots": "Randomize the essence rewards from Whispering Roots into the item pool. Whispering " | 
					
						
							|  |  |  |                                 "Roots will now grant a randomized item when completed. This can be previewed by " | 
					
						
							|  |  |  |                                 "standing on the root.", | 
					
						
							|  |  |  |     "RandomizeBossEssence": "Randomize boss essence drops, such as those for defeating Warrior Dreams, into the item " | 
					
						
							|  |  |  |                             "pool and open their locations for randomization.", | 
					
						
							|  |  |  |     "RandomizeGrubs": "Randomize Grubs into the item pool and open their locations for randomization.", | 
					
						
							|  |  |  |     "RandomizeMaps": "Randomize Maps into the item pool. This causes Cornifer to give you a message allowing you to see" | 
					
						
							|  |  |  |                      " and buy an item that is randomized into that location as well.", | 
					
						
							|  |  |  |     "RandomizeStags": "Randomize Stag Stations unlocks into the item pool as well as placing randomized items " | 
					
						
							|  |  |  |                       "on the stag station bell/toll.", | 
					
						
							|  |  |  |     "RandomizeLifebloodCocoons": "Randomize Lifeblood Cocoon grants into the item pool and open their locations" | 
					
						
							|  |  |  |                                  " for randomization.", | 
					
						
							|  |  |  |     "RandomizeGrimmkinFlames": "Randomize Grimmkin Flames into the item pool and open their locations for " | 
					
						
							|  |  |  |                                "randomization.", | 
					
						
							|  |  |  |     "RandomizeJournalEntries": "Randomize the Hunter's Journal as well as the findable journal entries into the item " | 
					
						
							|  |  |  |                                "pool, and open their locations for randomization. Does not include journal entries " | 
					
						
							|  |  |  |                                "gained by killing enemies.", | 
					
						
							|  |  |  |     "RandomizeGeoRocks": "Randomize Geo Rock rewards into the item pool and open their locations for randomization.", | 
					
						
							|  |  |  |     "RandomizeBossGeo": "Randomize boss Geo drops into the item pool and open those locations for randomization.", | 
					
						
							|  |  |  |     "RandomizeSoulTotems": "Randomize Soul Refill items into the item pool and open the Soul Totem locations for" | 
					
						
							|  |  |  |                            " randomization.", | 
					
						
							|  |  |  |     "RandomizeLoreTablets": "Randomize Lore items into the itempool, one per Lore Tablet, and place randomized item " | 
					
						
							|  |  |  |                             "grants on the tablets themselves. You must still read the tablet to get the item.", | 
					
						
							|  |  |  |     "PreciseMovement": "Places skips into logic which require extremely precise player movement, possibly without " | 
					
						
							|  |  |  |                        "movement skills such as dash or hook.", | 
					
						
							|  |  |  |     "ProficientCombat": "Places skips into logic which require proficient combat, possibly with limited items.", | 
					
						
							|  |  |  |     "BackgroundObjectPogos": "Places skips into logic for locations which are reachable via pogoing off of " | 
					
						
							|  |  |  |                              "background objects.", | 
					
						
							|  |  |  |     "EnemyPogos": "Places skips into logic for locations which are reachable via pogos off of enemies.", | 
					
						
							|  |  |  |     "ObscureSkips": "Places skips into logic which are considered obscure enough that a beginner is not expected " | 
					
						
							|  |  |  |                     "to know them.", | 
					
						
							|  |  |  |     "ShadeSkips": "Places shade skips into logic which utilize the player's shade for pogoing or damage boosting.", | 
					
						
							|  |  |  |     "InfectionSkips": "Places skips into logic which are only possible after the crossroads become infected.", | 
					
						
							|  |  |  |     "FireballSkips": "Places skips into logic which require the use of spells to reset fall speed while in mid-air.", | 
					
						
							|  |  |  |     "SpikeTunnels": "Places skips into logic which require the navigation of narrow tunnels filled with spikes.", | 
					
						
							|  |  |  |     "AcidSkips": "Places skips into logic which require crossing a pool of acid without Isma's Tear, or water if swim " | 
					
						
							|  |  |  |                  "is disabled.", | 
					
						
							|  |  |  |     "DamageBoosts": "Places skips into logic which require you to take damage from an enemy or hazard to progress.", | 
					
						
							|  |  |  |     "DangerousSkips": "Places skips into logic which contain a high risk of taking damage.", | 
					
						
							|  |  |  |     "DarkRooms": "Places skips into logic which require navigating dark rooms without the use of the Lumafly Lantern.", | 
					
						
							|  |  |  |     "ComplexSkips": "Places skips into logic which require intense setup or are obscure even beyond advanced skip " | 
					
						
							|  |  |  |                     "standards.", | 
					
						
							|  |  |  |     "DifficultSkips": "Places skips into logic which are considered more difficult than typical.", | 
					
						
							|  |  |  |     "RemoveSpellUpgrades": "Removes the second level of all spells from the item pool." | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  | default_on = { | 
					
						
							|  |  |  |     "RandomizeDreamers", | 
					
						
							|  |  |  |     "RandomizeSkills", | 
					
						
							|  |  |  |     "RandomizeCharms", | 
					
						
							|  |  |  |     "RandomizeKeys", | 
					
						
							|  |  |  |     "RandomizeMaskShards", | 
					
						
							|  |  |  |     "RandomizeVesselFragments", | 
					
						
							|  |  |  |     "RandomizePaleOre", | 
					
						
							|  |  |  |     "RandomizeRelics" | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # not supported at this time | 
					
						
							|  |  |  | disabled = { | 
					
						
							|  |  |  |     "RandomizeFocus", | 
					
						
							|  |  |  |     "RandomizeSwim", | 
					
						
							|  |  |  |     "RandomizeMimics", | 
					
						
							|  |  |  |     "RandomizeNail", | 
					
						
							| 
									
										
										
										
											2021-06-25 23:32:13 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | hollow_knight_randomize_options: typing.Dict[str, type(Option)] = {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | for option_name, option_data in pool_options.items(): | 
					
						
							| 
									
										
										
										
											2022-04-02 20:49:27 +02:00
										 |  |  |     extra_data = {"__module__": __name__, "items": option_data[0], "locations": option_data[1]} | 
					
						
							| 
									
										
										
										
											2022-04-03 18:10:13 -04:00
										 |  |  |     if option_name in option_docstrings: | 
					
						
							|  |  |  |         extra_data["__doc__"] = option_docstrings[option_name] | 
					
						
							| 
									
										
										
										
											2022-04-01 03:42:56 +02:00
										 |  |  |     if option_name in disabled: | 
					
						
							|  |  |  |         extra_data["__doc__"] = "Disabled Option. Not implemented." | 
					
						
							|  |  |  |         option = type(option_name, (Disabled,), extra_data) | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |     if option_name in default_on: | 
					
						
							|  |  |  |         option = type(option_name, (DefaultOnToggle,), extra_data) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         option = type(option_name, (Toggle,), extra_data) | 
					
						
							| 
									
										
										
										
											2022-04-02 20:49:27 +02:00
										 |  |  |     globals()[option.__name__] = option | 
					
						
							|  |  |  |     hollow_knight_randomize_options[option.__name__] = option | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-03 18:10:13 -04:00
										 |  |  | hollow_knight_logic_options: typing.Dict[str, type(Option)] = {} | 
					
						
							|  |  |  | for option_name in logic_options.values(): | 
					
						
							|  |  |  |     if option_name in hollow_knight_randomize_options: | 
					
						
							|  |  |  |         continue | 
					
						
							| 
									
										
										
										
											2022-04-05 00:13:25 +02:00
										 |  |  |     extra_data = {"__module__": __name__} | 
					
						
							| 
									
										
										
										
											2022-04-03 18:10:13 -04:00
										 |  |  |     if option_name in option_docstrings: | 
					
						
							|  |  |  |         extra_data["__doc__"] = option_docstrings[option_name] | 
					
						
							|  |  |  |         option = type(option_name, (Toggle,), extra_data) | 
					
						
							|  |  |  |     if option_name in disabled: | 
					
						
							|  |  |  |         extra_data["__doc__"] = "Disabled Option. Not implemented." | 
					
						
							|  |  |  |         option = type(option_name, (Disabled,), extra_data) | 
					
						
							| 
									
										
										
										
											2022-04-05 00:13:25 +02:00
										 |  |  |     globals()[option.__name__] = option | 
					
						
							|  |  |  |     hollow_knight_logic_options[option.__name__] = option | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class MinimumGrubPrice(Range): | 
					
						
							| 
									
										
										
										
											2022-04-03 18:10:13 -04:00
										 |  |  |     """The minimum grub price in the range of prices that an item should cost from Grubfather.""" | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |     display_name = "Minimum Grub Price" | 
					
						
							|  |  |  |     range_start = 1 | 
					
						
							|  |  |  |     range_end = 46 | 
					
						
							|  |  |  |     default = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class MaximumGrubPrice(MinimumGrubPrice): | 
					
						
							| 
									
										
										
										
											2022-04-03 18:10:13 -04:00
										 |  |  |     """The maximum grub price in the range of prices that an item should cost from Grubfather.""" | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |     display_name = "Maximum Grub Price" | 
					
						
							|  |  |  |     default = 23 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class MinimumEssencePrice(Range): | 
					
						
							| 
									
										
										
										
											2022-04-03 18:10:13 -04:00
										 |  |  |     """The minimum essence price in the range of prices that an item should cost from Seer.""" | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |     display_name = "Minimum Essence Price" | 
					
						
							|  |  |  |     range_start = 1 | 
					
						
							|  |  |  |     range_end = 2800 | 
					
						
							|  |  |  |     default = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class MaximumEssencePrice(MinimumEssencePrice): | 
					
						
							| 
									
										
										
										
											2022-04-03 18:10:13 -04:00
										 |  |  |     """The maximum essence price in the range of prices that an item should cost from Seer.""" | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |     display_name = "Maximum Essence Price" | 
					
						
							|  |  |  |     default = 1400 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class MinimumEggPrice(Range): | 
					
						
							| 
									
										
										
										
											2022-04-03 18:10:13 -04:00
										 |  |  |     """The minimum rancid egg price in the range of prices that an item should cost from Ijii.
 | 
					
						
							|  |  |  |     Only takes effect if the EggSlotShops option is greater than 0."""
 | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |     display_name = "Minimum Egg Price" | 
					
						
							|  |  |  |     range_start = 1 | 
					
						
							|  |  |  |     range_end = 21 | 
					
						
							|  |  |  |     default = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class MaximumEggPrice(MinimumEggPrice): | 
					
						
							| 
									
										
										
										
											2022-04-03 18:10:13 -04:00
										 |  |  |     """The maximum rancid egg price in the range of prices that an item should cost from Ijii.
 | 
					
						
							|  |  |  |     Only takes effect if the EggSlotShops option is greater than 0."""
 | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |     display_name = "Maximum Egg Price" | 
					
						
							|  |  |  |     default = 10 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class MinimumCharmPrice(Range): | 
					
						
							| 
									
										
										
										
											2022-04-03 18:10:13 -04:00
										 |  |  |     """The minimum charm price in the range of prices that an item should cost for Salubra's shop item which also
 | 
					
						
							|  |  |  |     carry a charm cost."""
 | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |     display_name = "Minimum Charm Requirement" | 
					
						
							|  |  |  |     range_start = 1 | 
					
						
							|  |  |  |     range_end = 40 | 
					
						
							|  |  |  |     default = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class MaximumCharmPrice(MinimumCharmPrice): | 
					
						
							| 
									
										
										
										
											2022-04-03 18:10:13 -04:00
										 |  |  |     """The maximum charm price in the range of prices that an item should cost for Salubra's shop item which also
 | 
					
						
							|  |  |  |     carry a charm cost."""
 | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |     default = 20 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class RandomCharmCosts(Range): | 
					
						
							| 
									
										
										
										
											2022-04-03 18:10:13 -04:00
										 |  |  |     """Total Notch Cost of all Charms together. Set to -1 for vanilla costs. Vanilla sums to 90.
 | 
					
						
							|  |  |  |     This value is distributed among all charms in a random fashion."""
 | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-03 18:10:13 -04:00
										 |  |  |     display_name = "Randomize Charm Notch Costs" | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |     range_start = -1 | 
					
						
							|  |  |  |     range_end = 240 | 
					
						
							|  |  |  |     default = -1 | 
					
						
							| 
									
										
										
										
											2022-04-08 19:22:50 +02:00
										 |  |  |     vanilla_costs: typing.List[int] = vanilla_costs | 
					
						
							| 
									
										
										
										
											2022-04-01 03:23:52 +02:00
										 |  |  |     charm_count: int = len(vanilla_costs) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_costs(self, random_source) -> typing.List[int]: | 
					
						
							|  |  |  |         if -1 == self.value: | 
					
						
							|  |  |  |             return self.vanilla_costs | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             charms = [0]*self.charm_count | 
					
						
							|  |  |  |             for x in range(self.value): | 
					
						
							|  |  |  |                 index = random_source.randint(0, self.charm_count-1) | 
					
						
							|  |  |  |                 while charms[index] > 5: | 
					
						
							|  |  |  |                     index = random_source.randint(0, self.charm_count-1) | 
					
						
							|  |  |  |                 charms[index] += 1 | 
					
						
							|  |  |  |             return charms | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class EggShopSlots(Range): | 
					
						
							|  |  |  |     """For each slot, add a location to the Egg Shop and a Geo drop to the item pool.""" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     display_name = "Egg Shop Item Slots" | 
					
						
							|  |  |  |     range_end = 16 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hollow_knight_options: typing.Dict[str, type(Option)] = { | 
					
						
							|  |  |  |     **hollow_knight_randomize_options, | 
					
						
							|  |  |  |     **hollow_knight_logic_options, | 
					
						
							| 
									
										
										
										
											2022-04-03 18:10:13 -04:00
										 |  |  |     StartLocation.__name__: StartLocation, | 
					
						
							|  |  |  |     MinimumGrubPrice.__name__: MinimumGrubPrice, | 
					
						
							|  |  |  |     MaximumGrubPrice.__name__: MaximumGrubPrice, | 
					
						
							|  |  |  |     MinimumEssencePrice.__name__: MinimumEssencePrice, | 
					
						
							|  |  |  |     MaximumEssencePrice.__name__: MaximumEssencePrice, | 
					
						
							|  |  |  |     MinimumEggPrice.__name__: MinimumEggPrice, | 
					
						
							|  |  |  |     MaximumEggPrice.__name__: MaximumEggPrice, | 
					
						
							|  |  |  |     MinimumCharmPrice.__name__: MinimumCharmPrice, | 
					
						
							|  |  |  |     MaximumCharmPrice.__name__: MaximumCharmPrice, | 
					
						
							|  |  |  |     RandomCharmCosts.__name__: RandomCharmCosts, | 
					
						
							|  |  |  |     EggShopSlots.__name__: EggShopSlots, | 
					
						
							| 
									
										
										
										
											2021-06-25 23:32:13 +02:00
										 |  |  | } |