Merge pull request #70 from alwaysintreble/main

Risk of Rain 2 dynamic item pool
This commit is contained in:
Hussein Farran 2021-09-08 15:44:47 -04:00 committed by GitHub
commit b4c3c5deea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 302 additions and 16 deletions

View File

@ -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)

View File

@ -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}

View File

@ -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
}

View File

@ -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

View File

@ -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)]