1
1
import typing
2
+ import re
2
3
from .ExtractedData import logic_options , starts , pool_options
3
4
from .Rules import cost_terms
4
5
11
12
else :
12
13
Random = typing .Any
13
14
14
-
15
15
locations = {"option_" + start : i for i , start in enumerate (starts )}
16
16
# This way the dynamic start names are picked up by the MetaClass Choice belongs to
17
- StartLocation = type ("StartLocation" , (Choice ,), {"__module__" : __name__ , "auto_display_name" : False , ** locations ,
18
- "__doc__" : "Choose your start location. "
19
- "This is currently only locked to King's Pass." })
17
+ StartLocation = type ("StartLocation" , (Choice ,), {
18
+ "__module__" : __name__ ,
19
+ "auto_display_name" : False ,
20
+ "display_name" : "Start Location" ,
21
+ "__doc__" : "Choose your start location. "
22
+ "This is currently only locked to King's Pass." ,
23
+ ** locations ,
24
+ })
20
25
del (locations )
21
26
22
27
option_docstrings = {
49
54
"RandomizeBossEssence" : "Randomize boss essence drops, such as those for defeating Warrior Dreams, into the item "
50
55
"pool and open their locations\n for randomization." ,
51
56
"RandomizeGrubs" : "Randomize Grubs into the item pool and open their locations for randomization." ,
52
- "RandomizeMimics" : "Randomize Mimic Grubs into the item pool and open their locations for randomization."
53
- "Mimic Grubs are always placed\n in your own game." ,
57
+ "RandomizeMimics" : "Randomize Mimic Grubs into the item pool and open their locations for randomization." ,
54
58
"RandomizeMaps" : "Randomize Maps into the item pool. This causes Cornifer to give you a message allowing you to see"
55
59
" and buy an item\n that is randomized into that location as well." ,
56
60
"RandomizeStags" : "Randomize Stag Stations unlocks into the item pool as well as placing randomized items "
99
103
"RandomizeKeys" ,
100
104
"RandomizeMaskShards" ,
101
105
"RandomizeVesselFragments" ,
106
+ "RandomizeCharmNotches" ,
102
107
"RandomizePaleOre" ,
103
- "RandomizeRelics"
108
+ "RandomizeRancidEggs"
109
+ "RandomizeRelics" ,
110
+ "RandomizeStags" ,
111
+ "RandomizeLifebloodCocoons"
104
112
}
105
113
106
114
shop_to_option = {
117
125
118
126
hollow_knight_randomize_options : typing .Dict [str , type (Option )] = {}
119
127
128
+ splitter_pattern = re .compile (r'(?<!^)(?=[A-Z])' )
120
129
for option_name , option_data in pool_options .items ():
121
130
extra_data = {"__module__" : __name__ , "items" : option_data [0 ], "locations" : option_data [1 ]}
122
131
if option_name in option_docstrings :
125
134
option = type (option_name , (DefaultOnToggle ,), extra_data )
126
135
else :
127
136
option = type (option_name , (Toggle ,), extra_data )
137
+ option .display_name = splitter_pattern .sub (" " , option_name )
128
138
globals ()[option .__name__ ] = option
129
139
hollow_knight_randomize_options [option .__name__ ] = option
130
140
133
143
if option_name in hollow_knight_randomize_options :
134
144
continue
135
145
extra_data = {"__module__" : __name__ }
146
+ # some options, such as elevator pass, appear in logic_options despite explicitly being
147
+ # handled below as classes.
136
148
if option_name in option_docstrings :
137
149
extra_data ["__doc__" ] = option_docstrings [option_name ]
138
150
option = type (option_name , (Toggle ,), extra_data )
139
- globals ()[option .__name__ ] = option
140
- hollow_knight_logic_options [option .__name__ ] = option
151
+ option .display_name = splitter_pattern .sub (" " , option_name )
152
+ globals ()[option .__name__ ] = option
153
+ hollow_knight_logic_options [option .__name__ ] = option
141
154
142
155
143
156
class RandomizeElevatorPass (Toggle ):
@@ -269,11 +282,11 @@ def get_costs(self, random_source: Random) -> typing.List[int]:
269
282
random_source .shuffle (charms )
270
283
return charms
271
284
else :
272
- charms = [0 ]* self .charm_count
285
+ charms = [0 ] * self .charm_count
273
286
for x in range (self .value ):
274
- index = random_source .randint (0 , self .charm_count - 1 )
287
+ index = random_source .randint (0 , self .charm_count - 1 )
275
288
while charms [index ] > 5 :
276
- index = random_source .randint (0 , self .charm_count - 1 )
289
+ index = random_source .randint (0 , self .charm_count - 1 )
277
290
charms [index ] += 1
278
291
return charms
279
292
@@ -404,6 +417,7 @@ class WhitePalace(Choice):
404
417
405
418
class ExtraPlatforms (DefaultOnToggle ):
406
419
"""Places additional platforms to make traveling throughout Hallownest more convenient."""
420
+ display_name = "Extra Platforms"
407
421
408
422
409
423
class AddUnshuffledLocations (Toggle ):
@@ -413,6 +427,7 @@ class AddUnshuffledLocations(Toggle):
413
427
Note: This will increase the number of location checks required to purchase
414
428
hints to the total maximum.
415
429
"""
430
+ display_name = "Add Unshuffled Locations"
416
431
417
432
418
433
class DeathLinkShade (Choice ):
@@ -430,6 +445,7 @@ class DeathLinkShade(Choice):
430
445
option_shadeless = 1
431
446
option_shade = 2
432
447
default = 2
448
+ display_name = "Deathlink Shade Handling"
433
449
434
450
435
451
class DeathLinkBreaksFragileCharms (Toggle ):
@@ -439,6 +455,7 @@ class DeathLinkBreaksFragileCharms(Toggle):
439
455
** Self-death fragile charm behavior is not changed; if a self-death normally breaks fragile charms in vanilla, it
440
456
will continue to do so.
441
457
"""
458
+ display_name = "Deathlink Breaks Fragile Charms"
442
459
443
460
444
461
class StartingGeo (Range ):
@@ -462,18 +479,20 @@ class CostSanity(Choice):
462
479
alias_yes = 1
463
480
option_shopsonly = 2
464
481
option_notshops = 3
465
- display_name = "Cost Sanity "
482
+ display_name = "Costsanity "
466
483
467
484
468
485
class CostSanityHybridChance (Range ):
469
486
"""The chance that a CostSanity cost will include two components instead of one, e.g. Grubs + Essence"""
470
487
range_end = 100
471
488
default = 10
489
+ display_name = "Costsanity Hybrid Chance"
472
490
473
491
474
492
cost_sanity_weights : typing .Dict [str , type (Option )] = {}
475
493
for term , cost in cost_terms .items ():
476
494
option_name = f"CostSanity{ cost .option } Weight"
495
+ display_name = f"Costsanity { cost .option } Weight"
477
496
extra_data = {
478
497
"__module__" : __name__ , "range_end" : 1000 ,
479
498
"__doc__" : (
@@ -486,10 +505,10 @@ class CostSanityHybridChance(Range):
486
505
extra_data ["__doc__" ] += " Geo costs will never be chosen for Grubfather, Seer, or Egg Shop."
487
506
488
507
option = type (option_name , (Range ,), extra_data )
508
+ option .display_name = display_name
489
509
globals ()[option .__name__ ] = option
490
510
cost_sanity_weights [option .__name__ ] = option
491
511
492
-
493
512
hollow_knight_options : typing .Dict [str , type (Option )] = {
494
513
** hollow_knight_randomize_options ,
495
514
RandomizeElevatorPass .__name__ : RandomizeElevatorPass ,
0 commit comments