Merge pull request #70 from alwaysintreble/main
Risk of Rain 2 dynamic item pool
This commit is contained in:
commit
b4c3c5deea
|
@ -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)
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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)]
|
||||
|
|
Loading…
Reference in New Issue