diff --git a/WebHostLib/static/assets/tutorial/ror2/setup_en.md b/WebHostLib/static/assets/tutorial/ror2/setup_en.md index 4763a43c..df3c6378 100644 --- a/WebHostLib/static/assets/tutorial/ror2/setup_en.md +++ b/WebHostLib/static/assets/tutorial/ror2/setup_en.md @@ -46,6 +46,28 @@ Risk of Rain 2: start_with_revive: true item_pickup_step: 1 enable_lunar: true + item_weights: + default: 50 + new: 0 + uncommon: 0 + legendary: 0 + lunartic: 0 + chaos: 0 + no_scraps: 0 + even: 0 + scraps_only: 0 + item_pool_presets: true + # custom item weights + green_scrap: 16 + red_scrap: 4 + yellow_scrap: 1 + white_scrap: 32 + common_item: 64 + uncommon_item: 32 + legendary_item: 8 + boss_item: 4 + lunar_item: 16 + equipment: 32 ``` | Name | Description | Allowed values | @@ -55,6 +77,10 @@ Risk of Rain 2: | start_with_revive | Starts the player off with a `Dio's Best Friend`. Functionally equivalent to putting a `Dio's Best Friend` in your `starting_inventory`. | true/false | | item_pickup_step | The number of item pickups which you are allowed to claim before they become an Archipelago location check. | 0 - 5 | | enable_lunar | Allows for lunar items to be shuffled into the item pool on behalf of the Risk of Rain player. | true/false | +| item_weights | Each option here is a preset item weight that can be used to customize your generate item pool with certain settings. | default, new, uncommon, legendary, lunartic, chaos, no_scraps, even, scraps_only | +| item_pool_presets | A simple toggle to determine whether the item_weight presets are used or the custom item pool as defined below | true/false | +| custom item weights | Each defined item here is a single item in the pool that will have a weight against the other items when the item pool gets generated. These values can be modified to adjust how frequently certain items appear | 0-100| + Using the example YAML above: the Risk of Rain 2 player will have 15 total items which they can pick up for other players. (total_locations = 15) @@ -67,3 +93,5 @@ They will have 4 of the items which other players can grant them replaced with ` The player will also start with a `Dio's Best Friend`. (start_with_revive = true) The player will have lunar items shuffled into the item pool on their behalf. (enable_lunar = true) + +The player will have the default preset generated item pool with the custom item weights being ignored. (item_weights: default and item_pool_presets: true) diff --git a/worlds/ror2/Items.py b/worlds/ror2/Items.py index 35992e1f..3345fd6d 100644 --- a/worlds/ror2/Items.py +++ b/worlds/ror2/Items.py @@ -1,6 +1,6 @@ from BaseClasses import Item import typing - +from random import randint class RiskOfRainItem(Item): game: str = "Risk of Rain 2" @@ -26,7 +26,7 @@ item_table = { "Beat Level Five": None, } -junk_weights = { +default_weights = { "Item Scrap, Green": 16, "Item Scrap, Red": 4, "Item Scrap, Yellow": 1, @@ -36,7 +36,109 @@ junk_weights = { "Legendary Item": 8, "Boss Item": 4, "Lunar Item": 16, - "Equipment": 32, + "Equipment": 32 +} + +new_weights = { + "Item Scrap, Green": 15, + "Item Scrap, Red": 5, + "Item Scrap, Yellow": 1, + "Item Scrap, White": 30, + "Common Item": 75, + "Uncommon Item": 40, + "Legendary Item": 10, + "Boss Item": 5, + "Lunar Item": 15, + "Equipment": 25 +} + +uncommon_weights = { + "Item Scrap, Green": 15, + "Item Scrap, Red": 5, + "Item Scrap, Yellow": 1, + "Item Scrap, White": 30, + "Common Item": 45, + "Uncommon Item": 100, + "Legendary Item": 10, + "Boss Item": 5, + "Lunar Item": 15, + "Equipment": 25 +} + +legendary_weights = { + "Item Scrap, Green": 15, + "Item Scrap, Red": 5, + "Item Scrap, Yellow": 1, + "Item Scrap, White": 30, + "Common Item": 50, + "Uncommon Item": 25, + "Legendary Item": 100, + "Boss Item": 5, + "Lunar Item": 15, + "Equipment": 25 +} + +lunartic_weights = { + "Item Scrap, Green": 0, + "Item Scrap, Red": 0, + "Item Scrap, Yellow": 0, + "Item Scrap, White": 0, + "Common Item": 0, + "Uncommon Item": 0, + "Legendary Item": 0, + "Boss Item": 0, + "Lunar Item": 100, + "Equipment": 0 +} + +no_scraps_weights = { + "Item Scrap, Green": 0, + "Item Scrap, Red": 0, + "Item Scrap, Yellow": 0, + "Item Scrap, White": 0, + "Common Item": 80, + "Uncommon Item": 30, + "Legendary Item": 15, + "Boss Item": 5, + "Lunar Item": 10, + "Equipment": 25 +} + +even_weights = { + "Item Scrap, Green": 1, + "Item Scrap, Red": 1, + "Item Scrap, Yellow": 1, + "Item Scrap, White": 1, + "Common Item": 1, + "Uncommon Item": 1, + "Legendary Item": 1, + "Boss Item": 1, + "Lunar Item": 1, + "Equipment": 1 +} + +scraps_only_weights = { + "Item Scrap, Green": 80, + "Item Scrap, Red": 40, + "Item Scrap, Yellow": 10, + "Item Scrap, White": 100, + "Common Item": 0, + "Uncommon Item": 0, + "Legendary Item": 0, + "Boss Item": 0, + "Lunar Item": 0, + "Equipment": 0 +} + +item_pool_weights: typing.Dict[int, typing.Dict[str, int]] = { + 0: default_weights, + 1: new_weights, + 2: uncommon_weights, + 3: legendary_weights, + 4: lunartic_weights, + 6: no_scraps_weights, + 7: even_weights, + 8: scraps_only_weights } lookup_id_to_name: typing.Dict[int, str] = {id: name for name, id in item_table.items() if id} diff --git a/worlds/ror2/Options.py b/worlds/ror2/Options.py index a58104e4..1a011706 100644 --- a/worlds/ror2/Options.py +++ b/worlds/ror2/Options.py @@ -1,5 +1,5 @@ import typing -from Options import Option, Toggle, Range +from Options import Option, DefaultOnToggle, Range, Choice class TotalLocations(Range): @@ -7,7 +7,7 @@ class TotalLocations(Range): displayname = "Total Locations" range_start = 10 range_end = 50 - default = 15 + default = 20 class TotalRevivals(Range): @@ -25,23 +25,145 @@ class ItemPickupStep(Range): displayname = "Item Pickup Step" range_start = 0 range_end = 5 - default = 1 + default = 2 -class AllowLunarItems(Toggle): + +class AllowLunarItems(DefaultOnToggle): """Allows Lunar items in the item pool.""" displayname = "Enable Lunar Item Shuffling" - default = True -class StartWithRevive(Toggle): + +class StartWithRevive(DefaultOnToggle): """Start the game with a `Dio's Best Friend` item.""" displayname = "Start with a Revive" - default = True +class GreenScrap(Range): + """Weight of Green Scraps in the item pool.""" + displayname = "Green Scraps" + range_start = 0 + range_end = 100 + default = 16 + + +class RedScrap(Range): + """Weight of Red Scraps in the item pool.""" + displayname = "Red Scraps" + range_start = 0 + range_end = 100 + default = 4 + + +class YellowScrap(Range): + """Weight of yellow scraps in the item pool.""" + displayname = "Yellow Scraps" + range_start = 0 + range_end = 100 + default = 1 + + +class WhiteScrap(Range): + """Weight of white scraps in the item pool.""" + displayname = "White Scraps" + range_start = 0 + range_end = 100 + default = 32 + + +class CommonItem(Range): + """Weight of common items in the item pool.""" + displayname = "Common Items" + range_start = 0 + range_end = 100 + default = 64 + + +class UncommonItem(Range): + """Weight of uncommon items in the item pool.""" + displayname = "Uncommon Items" + range_start = 0 + range_end = 100 + default = 32 + + +class LegendaryItem(Range): + """Weight of legendary items in the item pool.""" + displayname = "Legendary Items" + range_start = 0 + range_end = 100 + default = 8 + + +class BossItem(Range): + """Weight of boss items in the item pool.""" + displayname = "Boss Items" + range_start = 0 + range_end = 100 + default = 4 + + +class LunarItem(Range): + """Weight of lunar items in the item pool.""" + displayname = "Lunar Items" + range_start = 0 + range_end = 100 + default = 16 + + +class Equipment(Range): + """Weight of equipment items in the item pool.""" + displayname = "Equipment" + range_start = 0 + range_end = 100 + default = 32 + + +class ItemPoolPresetToggle(DefaultOnToggle): + """Will use the item weight presets when set to true, otherwise will use the custom set item pool weights.""" + displayname = "Item Weight Presets" + +class ItemWeights(Choice): + """Preset choices for determining the weights of the item pool. + New is a test for a potential adjustment to the default weights. + Uncommon puts a large number of uncommon items in the pool. + Legendary puts a large number of legendary items in the pool. + lunartic makes everything a lunar item. + chaos generates the pool completely at random with rarer items having a slight cap to prevent this option being too easy. + no_scraps removes all scrap items from the item pool. + even generates the item pool with every item having an even weight. + scraps_only removes all non scrap items from the item pool.""" + displayname = "Item Weights" + option_default = 0 + option_new = 1 + option_uncommon = 2 + option_legendary = 3 + option_lunartic = 4 + option_chaos = 5 + option_no_scraps = 6 + option_even = 7 + option_scraps_only = 8 + +#define a dictionary for the weights of the generated item pool. +ror2_weights: typing.Dict[str, type(Option)] = { + "green_scrap": GreenScrap, + "red_scrap": RedScrap, + "yellow_scrap": YellowScrap, + "white_scrap": WhiteScrap, + "common_item": CommonItem, + "uncommon_item": UncommonItem, + "legendary_item": LegendaryItem, + "boss_item": BossItem, + "lunar_item": LunarItem, + "equipment": Equipment +} + ror2_options: typing.Dict[str, type(Option)] = { "total_locations": TotalLocations, "total_revivals": TotalRevivals, "start_with_revive": StartWithRevive, "item_pickup_step": ItemPickupStep, - "enable_lunar": AllowLunarItems -} + "enable_lunar": AllowLunarItems, + "item_weights": ItemWeights, + "item_pool_presets": ItemPoolPresetToggle, + **ror2_weights +} \ No newline at end of file diff --git a/worlds/ror2/Rules.py b/worlds/ror2/Rules.py index c1992be5..3653f047 100644 --- a/worlds/ror2/Rules.py +++ b/worlds/ror2/Rules.py @@ -6,7 +6,8 @@ from ..generic.Rules import set_rule class RiskOfRainLogic(LogicMixin): def _ror_has_items(self, player: int, amount: int) -> bool: count: int = self.item_count("Common Item", player) + self.item_count("Uncommon Item", player) + \ - self.item_count("Legendary Item", player) + self.item_count("Boss Item", player) + self.item_count("Legendary Item", player) + self.item_count("Boss Item", player) + \ + self.item_count("Lunar Item", player) + self.item_count("Equipment", player) return count >= amount diff --git a/worlds/ror2/__init__.py b/worlds/ror2/__init__.py index d05851db..a0f45346 100644 --- a/worlds/ror2/__init__.py +++ b/worlds/ror2/__init__.py @@ -1,5 +1,5 @@ import string -from .Items import RiskOfRainItem, item_table, junk_weights +from .Items import RiskOfRainItem, item_table, item_pool_weights from .Locations import location_table, RiskOfRainLocation, base_location_table from .Rules import set_rules @@ -31,9 +31,41 @@ class RiskOfRainWorld(World): if self.world.start_with_revive[self.player].value: self.world.push_precollected(self.world.create_item("Dio's Best Friend", self.player)) + # if presets are enabled generate junk_pool from the selected preset + if self.world.item_pool_presets[self.player].value: + pool_option = self.world.item_weights[self.player].value + # generate chaos weights if the preset is chosen + if pool_option == 5: + junk_pool = { + "Item Scrap, Green": self.world.random.randint(0, 100), + "Item Scrap, Red": self.world.random.randint(0, 100), + "Item Scrap, Yellow": self.world.random.randint(0, 100), + "Item Scrap, White": self.world.random.randint(0, 100), + "Common Item": self.world.random.randint(0, 100), + "Uncommon Item": self.world.random.randint(0, 70), + "Legendary Item": self.world.random.randint(0, 45), + "Boss Item": self.world.random.randint(0, 30), + "Lunar Item": self.world.random.randint(0, 60), + "Equipment": self.world.random.randint(0, 50) + } + else: + junk_pool = item_pool_weights[pool_option] + else:# generate junk pool from user created presets + junk_pool = { + "Item Scrap, Green": self.world.green_scrap[self.player].value, + "Item Scrap, Red": self.world.red_scrap[self.player].value, + "Item Scrap, Yellow": self.world.yellow_scrap[self.player].value, + "Item Scrap, White": self.world.white_scrap[self.player].value, + "Common Item": self.world.common_item[self.player].value, + "Uncommon Item": self.world.uncommon_item[self.player].value, + "Legendary Item": self.world.legendary_item[self.player].value, + "Boss Item": self.world.boss_item[self.player].value, + "Lunar Item": self.world.lunar_item[self.player].value, + "Equipment": self.world.equipment[self.player].value + } + # Generate item pool itempool = [] - junk_pool = junk_weights.copy() # Add revive items for the player itempool += ["Dio's Best Friend"] * self.world.total_revivals[self.player] @@ -41,10 +73,11 @@ class RiskOfRainWorld(World): if not self.world.enable_lunar[self.player]: junk_pool.pop("Lunar Item") + # Fill remaining items with randomly generated junk itempool += self.world.random.choices(list(junk_pool.keys()), weights=list(junk_pool.values()), k=self.world.total_locations[self.player] - - self.world.total_revivals[self.player]) + self.world.total_revivals[self.player] - self.world.start_with_revive[self.player].value) # Convert itempool into real items itempool = [item for item in map(lambda name: self.create_item(name), itempool)]