From 82850d7f66a1f7a6032d94135ed7d471c775ceb3 Mon Sep 17 00:00:00 2001 From: alwaysintreble Date: Fri, 15 Jul 2022 16:19:36 -0500 Subject: [PATCH 1/6] Ror2: reduce locations to 250 and mark legendary items as useful (#776) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * reduce total locations to 250 * minor styling cleanup. mark legendary items as useful * 😡 Co-authored-by: black-sliver <59490463+black-sliver@users.noreply.github.com> Co-authored-by: black-sliver <59490463+black-sliver@users.noreply.github.com> --- worlds/ror2/Options.py | 6 ++++-- worlds/ror2/__init__.py | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/worlds/ror2/Options.py b/worlds/ror2/Options.py index d747f3801c..4abca9a33a 100644 --- a/worlds/ror2/Options.py +++ b/worlds/ror2/Options.py @@ -6,7 +6,7 @@ class TotalLocations(Range): """Number of location checks which are added to the Risk of Rain playthrough.""" display_name = "Total Locations" range_start = 10 - range_end = 500 + range_end = 250 default = 20 @@ -122,6 +122,7 @@ class ItemPoolPresetToggle(DefaultOnToggle): """Will use the item weight presets when set to true, otherwise will use the custom set item pool weights.""" display_name = "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.
@@ -143,7 +144,8 @@ class ItemWeights(Choice): option_even = 7 option_scraps_only = 8 -#define a dictionary for the weights of the generated item pool. + +# define a dictionary for the weights of the generated item pool. ror2_weights: typing.Dict[str, type(Option)] = { "green_scrap": GreenScrap, "red_scrap": RedScrap, diff --git a/worlds/ror2/__init__.py b/worlds/ror2/__init__.py index 06df244b97..6e240ee1c1 100644 --- a/worlds/ror2/__init__.py +++ b/worlds/ror2/__init__.py @@ -116,9 +116,9 @@ class RiskOfRainWorld(World): def create_item(self, name: str) -> Item: item_id = item_table[name] item = RiskOfRainItem(name, ItemClassification.filler, item_id, self.player) - if name == 'Dio\'s Best Friend': + if name == "Dio's Best Friend": item.classification = ItemClassification.progression - elif name == 'Equipment': + elif name in {"Equipment", "Legendary Item"}: item.classification = ItemClassification.useful return item From 090c5bcf00a41e632857081118abf60ef0728d5b Mon Sep 17 00:00:00 2001 From: Vale <58179315+Vale-X@users.noreply.github.com> Date: Fri, 15 Jul 2022 22:21:36 +0100 Subject: [PATCH 2/6] RoR2: FinalStageDeath (#766) Added a YAML option for 'FinalStageDeath', a toggle for 'death on the final boss stage counts as a win'. Defaults to on. Co-authored-by: Vale <58179315+DelosIX@users.noreply.github.com> --- worlds/ror2/Options.py | 5 +++++ worlds/ror2/__init__.py | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/worlds/ror2/Options.py b/worlds/ror2/Options.py index 4abca9a33a..0ab43443e0 100644 --- a/worlds/ror2/Options.py +++ b/worlds/ror2/Options.py @@ -36,6 +36,10 @@ class AllowLunarItems(DefaultOnToggle): class StartWithRevive(DefaultOnToggle): """Start the game with a `Dio's Best Friend` item.""" display_name = "Start with a Revive" + +class FinalStageDeath(DefaultOnToggle): + """Death on the final boss stage counts as a win.""" + display_name = "Final Stage Death is Win" class GreenScrap(Range): @@ -163,6 +167,7 @@ ror2_options: typing.Dict[str, type(Option)] = { "total_locations": TotalLocations, "total_revivals": TotalRevivals, "start_with_revive": StartWithRevive, + "final_stage_death": FinalStageDeath, "item_pickup_step": ItemPickupStep, "enable_lunar": AllowLunarItems, "item_weights": ItemWeights, diff --git a/worlds/ror2/__init__.py b/worlds/ror2/__init__.py index 6e240ee1c1..1a7060786f 100644 --- a/worlds/ror2/__init__.py +++ b/worlds/ror2/__init__.py @@ -110,7 +110,8 @@ class RiskOfRainWorld(World): "seed": "".join(self.world.slot_seeds[self.player].choice(string.digits) for i in range(16)), "totalLocations": self.world.total_locations[self.player].value, "totalRevivals": self.world.total_revivals[self.player].value, - "startWithDio": self.world.start_with_revive[self.player].value + "startWithDio": self.world.start_with_revive[self.player].value, + "FinalStageDeath": self.world.final_stage_death[self.player].value } def create_item(self, name: str) -> Item: From a4211d5f11d122ef235924f29fd8a5f494e47b14 Mon Sep 17 00:00:00 2001 From: Rome Reginelli Date: Fri, 15 Jul 2022 14:24:40 -0700 Subject: [PATCH 3/6] Improve Risk of Rain 2 docs (#770) * Improve Risk of Rain 2 docs * RoR2: clarify custom item weight settings * Update worlds/ror2/docs/en_Risk of Rain 2.md Co-authored-by: Hussein Farran --- worlds/ror2/Options.py | 36 +++++++++---------- worlds/ror2/docs/en_Risk of Rain 2.md | 51 +++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 20 deletions(-) diff --git a/worlds/ror2/Options.py b/worlds/ror2/Options.py index 0ab43443e0..727d01ffaa 100644 --- a/worlds/ror2/Options.py +++ b/worlds/ror2/Options.py @@ -43,7 +43,7 @@ class FinalStageDeath(DefaultOnToggle): class GreenScrap(Range): - """Weight of Green Scraps in the item pool.""" + """Weight of Green Scraps in the item pool. (Ignored unless Item Weight Presets is 'No')""" display_name = "Green Scraps" range_start = 0 range_end = 100 @@ -51,7 +51,7 @@ class GreenScrap(Range): class RedScrap(Range): - """Weight of Red Scraps in the item pool.""" + """Weight of Red Scraps in the item pool. (Ignored unless Item Weight Presets is 'No')""" display_name = "Red Scraps" range_start = 0 range_end = 100 @@ -59,7 +59,7 @@ class RedScrap(Range): class YellowScrap(Range): - """Weight of yellow scraps in the item pool.""" + """Weight of yellow scraps in the item pool. (Ignored unless Item Weight Presets is 'No')""" display_name = "Yellow Scraps" range_start = 0 range_end = 100 @@ -67,7 +67,7 @@ class YellowScrap(Range): class WhiteScrap(Range): - """Weight of white scraps in the item pool.""" + """Weight of white scraps in the item pool. (Ignored unless Item Weight Presets is 'No')""" display_name = "White Scraps" range_start = 0 range_end = 100 @@ -75,7 +75,7 @@ class WhiteScrap(Range): class CommonItem(Range): - """Weight of common items in the item pool.""" + """Weight of common items in the item pool. (Ignored unless Item Weight Presets is 'No')""" display_name = "Common Items" range_start = 0 range_end = 100 @@ -83,7 +83,7 @@ class CommonItem(Range): class UncommonItem(Range): - """Weight of uncommon items in the item pool.""" + """Weight of uncommon items in the item pool. (Ignored unless Item Weight Presets is 'No')""" display_name = "Uncommon Items" range_start = 0 range_end = 100 @@ -91,7 +91,7 @@ class UncommonItem(Range): class LegendaryItem(Range): - """Weight of legendary items in the item pool.""" + """Weight of legendary items in the item pool. (Ignored unless Item Weight Presets is 'No')""" display_name = "Legendary Items" range_start = 0 range_end = 100 @@ -99,7 +99,7 @@ class LegendaryItem(Range): class BossItem(Range): - """Weight of boss items in the item pool.""" + """Weight of boss items in the item pool. (Ignored unless Item Weight Presets is 'No')""" display_name = "Boss Items" range_start = 0 range_end = 100 @@ -107,7 +107,7 @@ class BossItem(Range): class LunarItem(Range): - """Weight of lunar items in the item pool.""" + """Weight of lunar items in the item pool. (Ignored unless Item Weight Presets is 'No')""" display_name = "Lunar Items" range_start = 0 range_end = 100 @@ -115,7 +115,7 @@ class LunarItem(Range): class Equipment(Range): - """Weight of equipment items in the item pool.""" + """Weight of equipment items in the item pool. (Ignored unless Item Weight Presets is 'No')""" display_name = "Equipment" range_start = 0 range_end = 100 @@ -128,14 +128,14 @@ class ItemPoolPresetToggle(DefaultOnToggle): 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.
+ """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 will be only scrap items in the item pool.""" display_name = "Item Weights" option_default = 0 diff --git a/worlds/ror2/docs/en_Risk of Rain 2.md b/worlds/ror2/docs/en_Risk of Rain 2.md index 92232116cc..a58269a35b 100644 --- a/worlds/ror2/docs/en_Risk of Rain 2.md +++ b/worlds/ror2/docs/en_Risk of Rain 2.md @@ -12,6 +12,32 @@ functionality in which certain chests (made clear via a location check progress multiworld. The items that _would have been_ in those chests will be returned to the Risk of Rain player via grants by other players in other worlds. +## What is the goal of Risk of Rain 2 in Archipelago? + +Just like in the original game, any way to "beat the game or obliterate" counts as a win. By default, if you die while +on a final boss stage, that also counts as a win. (You can turn this off in your player settings.) **You do not need to +complete all the location checks** to win; any item you don't collect is automatically sent out to the multiworld when +you meet your goal. + +If you die before you accomplish your goal, you can start a new run. You will start the run with any items that you +received from other players. Any items that you picked up the "normal" way will be lost. + +Note, you can play Simulacrum mode as part of an Archipelago, but you can't achieve any of the victory conditions in +Simulacrum. So you could, for example, collect most of your items through a Simulacrum run, then finish a normal mode +run while keeping the items you received via the multiworld. + +## Can you play multiplayer? + +Yes! You can have a single multiplayer instance as one world in the multiworld. All the players involved need to have +the Archipelago mod, but only the host needs to configure the Archipelago settings. When someone finds an item for your +world, all the connected players will receive a copy of the item, and the location check bar will increase whenever any +player finds an item in Risk of Rain. + +You cannot have players with different player slots in the same co-op game instance. Only the host's Archipelago +settings apply, so each Risk of Rain 2 player slot in the multiworld needs to be a separate game instance. You could, +for example, have two players trade off hosting and making progress on each other's player slot, but a single co-op +instance can't make progress towards multiple player slots in the multiworld. + ## What Risk of Rain items can appear in other players' worlds? The Risk of Rain items are: @@ -31,13 +57,34 @@ in-game item of that tier will appear in the Risk of Rain player's inventory. If the player already has an equipment item equipped then the _item that was equipped_ will be dropped on the ground and _ the new equipment_ will take it's place. (If you want the old one back, pick it up.) +### How many items are there? + +Since a Risk of Rain 2 run can go on indefinitely, you have to configure how many collectible items (also known as +"checks") the game has for purposes of Archipelago when you set up a multiworld. You can configure anywhere from **10 +to 250** items. The number of items will be randomized between all players, so you may want to adjust the number and +item pickup step based on how many items the other players in the multiworld have. (Around 100 seems to be a good +ballpark if you want to have a similar number of items to most other games.) + +After you have completed the specified number of checks, you won't send anything else to the multiworld. You can +receive up to the specified number of randomized items from the multiworld as the players find them. In either case, +you can continue to collect items as normal in Risk of Rain 2 if you've already found all your location checks. + ## What does another world's item look like in Risk of Rain? When the Risk of Rain player fills up their location check bar then the next spawned item will become an item grant for -another player's world. The item in Risk of Rain will disappear in a poof of smoke and the grant will automatically go -out to the multiworld. +another player's world (or possibly get sent back to yourself). The item in Risk of Rain will disappear in a poof of +smoke and the grant will automatically go out to the multiworld. ## What is the item pickup step? The item pickup step is a YAML setting which allows you to set how many items you need to spawn before the _next_ item that is spawned disappears (in a poof of smoke) and goes out to the multiworld. + +## Is Archipelago compatible with other Risk of Rain 2 mods? + +Mostly, yes. Not every mod will work; in particular, anything that causes items to go directly into your inventory +rather than spawning onto the map will interfere with the way the Archipelago mod works. However, many common mods work +just fine with Archipelago. + +For competitive play, of course, you should only use mods that are agreed-upon by the competitors so that you don't +have an unfair advantage. From 3c6bd555b4d0e535e29ca02043fb7c5d4e581fdc Mon Sep 17 00:00:00 2001 From: black-sliver <59490463+black-sliver@users.noreply.github.com> Date: Fri, 15 Jul 2022 23:52:35 +0200 Subject: [PATCH 4/6] doc: add style guide (#746) * doc: add style guide * doc: style guide for python and markdown * doc: consistent use of periods and explicit double quotes in style guide Co-authored-by: Hussein Farran * doc: better define string style in style guide * doc: add format string literals to style guide * doc: add HTML, CSS and JS to style guide Co-authored-by: Hussein Farran --- docs/style.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++ docs/world api.md | 8 ++++---- 2 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 docs/style.md diff --git a/docs/style.md b/docs/style.md new file mode 100644 index 0000000000..a9f55caa7c --- /dev/null +++ b/docs/style.md @@ -0,0 +1,49 @@ +# Style Guide + +## Generic + +* This guide can be ignored for data files that are not to be viewed in an editor. +* 120 character per line for all source files. +* Avoid white space errors like trailing spaces. + + +## Python Code + +* We mostly follow [PEP8](https://peps.python.org/pep-0008/). Read below to see the differences. +* 120 characters per line. PyCharm does this automatically, other editors can be configured for it. +* Strings in core code will be `"strings"`. In other words: double quote your strings. +* Strings in worlds should use double quotes as well, but imported code may differ. +* Prefer [format string literals](https://peps.python.org/pep-0498/) over string concatenation, + use single quotes inside them: `f"Like {dct['key']}"` +* Use type annotation where possible. + + +## Markdown + +* We almost follow [Google's styleguide](https://google.github.io/styleguide/docguide/style.html). + Read below for differences. +* For existing documents, try to follow its style or ask to completely reformat it. +* 120 characters per line. +* One space between bullet/number and text. +* No lazy numbering. + + +## HTML + +* Indent with 2 spaces for new code. +* kebab-case for ids and classes. + + +## CSS + +* Indent with 2 spaces for new code. +* `{` on the same line as the selector. +* No space between selector and `{`. + + +## JS + +* Indent with 2 spaces. +* Indent `case` inside `switch ` with 2 spaces. +* Use single quotes. +* Semicolons are required after every statement. diff --git a/docs/world api.md b/docs/world api.md index a1138c9e16..4fa81f4aab 100644 --- a/docs/world api.md +++ b/docs/world api.md @@ -236,7 +236,7 @@ class MyGameLocation(Location): game: str = "My Game" # override constructor to automatically mark event locations as such - def __init__(self, player: int, name = '', code = None, parent = None): + def __init__(self, player: int, name = "", code = None, parent = None): super(MyGameLocation, self).__init__(player, name, code, parent) self.event = code is None ``` @@ -487,14 +487,14 @@ def create_items(self) -> None: for item in map(self.create_item, mygame_items): if item in exclude: exclude.remove(item) # this is destructive. create unique list above - self.world.itempool.append(self.create_item('nothing')) + self.world.itempool.append(self.create_item("nothing")) else: self.world.itempool.append(item) # itempool and number of locations should match up. # If this is not the case we want to fill the itempool with junk. junk = 0 # calculate this based on player settings - self.world.itempool += [self.create_item('nothing') for _ in range(junk)] + self.world.itempool += [self.create_item("nothing") for _ in range(junk)] ``` #### create_regions @@ -628,7 +628,7 @@ class MyGameLogic(LogicMixin): def _mygame_has_key(self, world: MultiWorld, player: int): # Arguments above are free to choose # it may make sense to use World as argument instead of MultiWorld - return self.has('key', player) # or whatever + return self.has("key", player) # or whatever ``` ```python # __init__.py From a42f7f99fead3676a79169f462ed53f01cf878c9 Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Sat, 16 Jul 2022 01:22:14 +0200 Subject: [PATCH 5/6] Factorio: specify rcon version --- worlds/factorio/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worlds/factorio/requirements.txt b/worlds/factorio/requirements.txt index ce5a83049a..00d9d20af1 100644 --- a/worlds/factorio/requirements.txt +++ b/worlds/factorio/requirements.txt @@ -1 +1 @@ -factorio-rcon-py>=1.2.1 +factorio-rcon-py==1.2.1 From 622af177059265346819f6abfbabb9a3a7342a5d Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Sat, 16 Jul 2022 11:44:56 +0200 Subject: [PATCH 6/6] MultiServer: make !hint prefer non-local --- MultiServer.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MultiServer.py b/MultiServer.py index dd695fc1bb..e8e1cc8d4c 100644 --- a/MultiServer.py +++ b/MultiServer.py @@ -1308,6 +1308,8 @@ class ClientMessageProcessor(CommonCommandProcessor): can_pay = 1000 self.ctx.random.shuffle(not_found_hints) + # By popular vote, make hints prefer non-local placements + not_found_hints.sort(key=lambda hint: int(hint.receiving_player != hint.finding_player)) hints = found_hints while can_pay > 0: