From 4e90ebc7d93bfef7cee0e082fb43ba0b59be0127 Mon Sep 17 00:00:00 2001 From: espeon65536 <81029175+espeon65536@users.noreply.github.com> Date: Thu, 19 May 2022 12:15:23 -0400 Subject: [PATCH] MC: add 1.18.2 advancements (#537) * MC: add 1.18.2 advancements and update options to match * client version 8 * MC: multiworkd -> multiworld * MC: account for overworld villager in Star Trader logic Also standardized Surge Protector and VVFrightening logic * MC: fix _mc_overworld_villager some day I won't second-guess myself when writing logic --- worlds/minecraft/Locations.py | 7 ++++++- worlds/minecraft/Options.py | 14 ++++---------- worlds/minecraft/Rules.py | 29 +++++++++++++++++++++++------ worlds/minecraft/__init__.py | 6 +++--- 4 files changed, 36 insertions(+), 20 deletions(-) diff --git a/worlds/minecraft/Locations.py b/worlds/minecraft/Locations.py index 7dbf85de..a5c0421f 100644 --- a/worlds/minecraft/Locations.py +++ b/worlds/minecraft/Locations.py @@ -119,6 +119,10 @@ advancement_table = { "Light as a Rabbit": AdvData(42100, 'Overworld'), "Glow and Behold!": AdvData(42101, 'Overworld'), "Whatever Floats Your Goat!": AdvData(42102, 'Overworld'), + "Caves & Cliffs": AdvData(42103, 'Overworld'), + "Feels like home": AdvData(42104, 'The Nether'), + "Sound of Music": AdvData(42105, 'Overworld'), + "Star Trader": AdvData(42106, 'Village'), "Blaze Spawner": AdvData(None, 'Nether Fortress'), "Ender Dragon": AdvData(None, 'The End'), @@ -139,7 +143,8 @@ exclusion_table = { "Cover Me in Debris", "A Complete Catalogue", "Surge Protector", - "Light as a Rabbit", # will be normal in 1.18 + "Sound of Music", + "Star Trader", }, "unreasonable": { "How Did We Get Here?", diff --git a/worlds/minecraft/Options.py b/worlds/minecraft/Options.py index 19a166d5..f35866f7 100644 --- a/worlds/minecraft/Options.py +++ b/worlds/minecraft/Options.py @@ -1,12 +1,12 @@ import typing -from Options import Choice, Option, Toggle, Range, OptionList, DeathLink +from Options import Choice, Option, Toggle, DefaultOnToggle, Range, OptionList, DeathLink class AdvancementGoal(Range): """Number of advancements required to spawn bosses.""" display_name = "Advancement Goal" range_start = 0 - range_end = 92 + range_end = 95 default = 40 @@ -36,16 +36,14 @@ class BossGoal(Choice): default = 1 -class ShuffleStructures(Toggle): +class ShuffleStructures(DefaultOnToggle): """Enables shuffling of villages, outposts, fortresses, bastions, and end cities.""" display_name = "Shuffle Structures" - default = 1 -class StructureCompasses(Toggle): +class StructureCompasses(DefaultOnToggle): """Adds structure compasses to the item pool, which point to the nearest indicated structure.""" display_name = "Structure Compasses" - default = 1 class BeeTraps(Range): @@ -68,25 +66,21 @@ class CombatDifficulty(Choice): class HardAdvancements(Toggle): """Enables certain RNG-reliant or tedious advancements.""" display_name = "Include Hard Advancements" - default = 0 class UnreasonableAdvancements(Toggle): """Enables the extremely difficult advancements "How Did We Get Here?" and "Adventuring Time.\"""" display_name = "Include Unreasonable Advancements" - default = 0 class PostgameAdvancements(Toggle): """Enables advancements that require spawning and defeating the required bosses.""" display_name = "Include Postgame Advancements" - default = 0 class SendDefeatedMobs(Toggle): """Send killed mobs to other Minecraft worlds which have this option enabled.""" display_name = "Send Defeated Mobs" - default = 0 class StartingItems(OptionList): diff --git a/worlds/minecraft/Rules.py b/worlds/minecraft/Rules.py index b66de59d..f2872e2d 100644 --- a/worlds/minecraft/Rules.py +++ b/worlds/minecraft/Rules.py @@ -41,8 +41,17 @@ class MinecraftLogic(LogicMixin): def _mc_can_piglin_trade(self, player: int): return self._mc_has_gold_ingots(player) and ( - self.can_reach('The Nether', 'Region', player) or self.can_reach('Bastion Remnant', 'Region', - player)) + self.can_reach('The Nether', 'Region', player) or + self.can_reach('Bastion Remnant', 'Region', player)) + + def _mc_overworld_villager(self, player: int): + village_region = self.world.get_region('Village', player).entrances[0].parent_region.name + if village_region == 'The Nether': # 2 options: cure zombie villager or build portal in village + return (self.can_reach('Zombie Doctor', 'Location', player) or + (self._mc_has_diamond_pickaxe(player) and self.can_reach('Village', 'Region', player))) + elif village_region == 'The End': + return self.can_reach('Zombie Doctor', 'Location', player) + return self.can_reach('Village', 'Region', player) def _mc_enter_stronghold(self, player: int): return self.has('Blaze Rods', player) and self.has('Brewing', player) and self.has('3 Ender Pearls', player) @@ -132,8 +141,8 @@ def set_advancement_rules(world: MultiWorld, player: int): set_rule(world.get_location("Who is Cutting Onions?", player), lambda state: state._mc_can_piglin_trade(player)) set_rule(world.get_location("Oh Shiny", player), lambda state: state._mc_can_piglin_trade(player)) set_rule(world.get_location("Suit Up", player), lambda state: state.has("Progressive Armor", player) and state._mc_has_iron_ingots(player)) - set_rule(world.get_location("Very Very Frightening", player), lambda state: state.has("Channeling Book", player) and state._mc_can_use_anvil(player) and state._mc_can_enchant(player) and \ - ((world.get_region('Village', player).entrances[0].parent_region.name != 'The End' and state.can_reach('Village', 'Region', player)) or state.can_reach('Zombie Doctor', 'Location', player))) # need villager into the overworld for lightning strike + set_rule(world.get_location("Very Very Frightening", player), lambda state: state.has("Channeling Book", player) and + state._mc_can_use_anvil(player) and state._mc_can_enchant(player) and state._mc_overworld_villager(player)) set_rule(world.get_location("Hot Stuff", player), lambda state: state.has("Bucket", player) and state._mc_has_iron_ingots(player)) set_rule(world.get_location("Free the End", player), lambda state: state._mc_can_respawn_ender_dragon(player) and state._mc_can_kill_ender_dragon(player)) set_rule(world.get_location("A Furious Cocktail", player), lambda state: state._mc_can_brew_potions(player) and @@ -252,11 +261,19 @@ def set_advancement_rules(world: MultiWorld, player: int): set_rule(world.get_location("Is It a Bird?", player), lambda state: state._mc_has_spyglass(player) and state._mc_can_adventure(player)) set_rule(world.get_location("Is It a Balloon?", player), lambda state: state._mc_has_spyglass(player)) set_rule(world.get_location("Is It a Plane?", player), lambda state: state._mc_has_spyglass(player) and state._mc_can_respawn_ender_dragon(player)) - set_rule(world.get_location("Surge Protector", player), lambda state: state.has("Channeling Book", player) and state._mc_can_use_anvil(player) and state._mc_can_enchant(player) and \ - ((world.get_region('Village', player).entrances[0].parent_region.name != 'The End' and state.can_reach('Village', 'Region', player)) or state.can_reach('Zombie Doctor', 'Location', player))) + set_rule(world.get_location("Surge Protector", player), lambda state: state.has("Channeling Book", player) and + state._mc_can_use_anvil(player) and state._mc_can_enchant(player) and state._mc_overworld_villager(player)) set_rule(world.get_location("Light as a Rabbit", player), lambda state: state._mc_can_adventure(player) and state._mc_has_iron_ingots(player) and state.has('Bucket', player)) set_rule(world.get_location("Glow and Behold!", player), lambda state: state._mc_can_adventure(player)) set_rule(world.get_location("Whatever Floats Your Goat!", player), lambda state: state._mc_can_adventure(player)) + set_rule(world.get_location("Caves & Cliffs", player), lambda state: state._mc_has_iron_ingots(player) and state.has('Bucket', player) and state.has('Progressive Tools', player, 2)) + set_rule(world.get_location("Feels like home", player), lambda state: state._mc_has_iron_ingots(player) and state.has('Bucket', player) and state.has('Fishing Rod', player) and + (state._mc_fortress_loot(player) or state._mc_complete_raid(player)) and state.has("Saddle", player)) + set_rule(world.get_location("Sound of Music", player), lambda state: state.can_reach("Diamonds!", "Location", player) and state._mc_basic_combat(player)) + set_rule(world.get_location("Star Trader", player), lambda state: state._mc_has_iron_ingots(player) and state.has('Bucket', player) and + (state.can_reach("The Nether", 'Region', player) or state.can_reach("Nether Fortress", 'Region', player) or state._mc_can_piglin_trade(player)) and # soul sand for water elevator + state._mc_overworld_villager(player)) + # Sets rules on completion condition and postgame advancements def set_completion_rules(world: MultiWorld, player: int): diff --git a/worlds/minecraft/__init__.py b/worlds/minecraft/__init__.py index 4c75e5a0..b0f0ae74 100644 --- a/worlds/minecraft/__init__.py +++ b/worlds/minecraft/__init__.py @@ -13,7 +13,7 @@ from BaseClasses import Region, Entrance, Item, Tutorial from .Options import minecraft_options from ..AutoWorld import World, WebWorld -client_version = 7 +client_version = 8 class MinecraftWebWorld(WebWorld): theme = "jungle" @@ -22,7 +22,7 @@ class MinecraftWebWorld(WebWorld): setup = Tutorial( "Multiworld Setup Tutorial", "A guide to setting up the Archipelago Minecraft software on your computer. This guide covers" - "single-player, multiworkd, and related software.", + "single-player, multiworld, and related software.", "English", "minecraft_en.md", "minecraft/en", @@ -65,7 +65,7 @@ class MinecraftWorld(World): item_name_to_id = {name: data.code for name, data in item_table.items()} location_name_to_id = {name: data.id for name, data in advancement_table.items()} - data_version = 4 + data_version = 5 def _get_mc_data(self): exits = [connection[0] for connection in default_connections]