From f1aba45f7965c977e3fa27e3ae3cf06feafc44fc Mon Sep 17 00:00:00 2001 From: Scipio Wright Date: Mon, 8 Jul 2024 20:40:07 -0400 Subject: [PATCH] Make has_combat_reqs --- worlds/tunic/combat_logic.py | 68 ++++++++++++++++-------------------- worlds/tunic/er_rules.py | 10 +++--- 2 files changed, 36 insertions(+), 42 deletions(-) diff --git a/worlds/tunic/combat_logic.py b/worlds/tunic/combat_logic.py index 6830406534..d73816ca6b 100644 --- a/worlds/tunic/combat_logic.py +++ b/worlds/tunic/combat_logic.py @@ -26,33 +26,49 @@ class AreaStats(NamedTuple): sp_level: int mp_level: int potion_count: int + equipment: List[str] = [] area_data: Dict[str, AreaStats] = { # The upgrade page is right by the Well entrance. Upper Overworld by the chest in the top right might need something "Overworld": AreaStats(1, 1, 1, 1, 1, 1, 0), - "East Forest": AreaStats(1, 1, 1, 1, 1, 1, 0), + "East Forest": AreaStats(1, 1, 1, 1, 1, 1, 0, ["Stick"]), # learn how to upgrade - "Beneath the Well": AreaStats(2, 1, 3, 3, 1, 1, 3), - "Dark Tomb": AreaStats(2, 2, 3, 3, 1, 1, 3), - "West Garden": AreaStats(2, 3, 3, 3, 1, 1, 4), - "Garden Knight": AreaStats(3, 3, 3, 3, 2, 1, 4), + "Beneath the Well": AreaStats(2, 1, 3, 3, 1, 1, 3, ["Sword", "Shield"]), + "Dark Tomb": AreaStats(2, 2, 3, 3, 1, 1, 3, ["Sword", "Shield"]), + "West Garden": AreaStats(2, 3, 3, 3, 1, 1, 4, ["Sword", "Shield"]), + "Garden Knight": AreaStats(3, 3, 3, 3, 2, 1, 4, ["Sword", "Shield"]), # get the wand here - "Beneath the Vault": AreaStats(3, 3, 3, 3, 2, 1, 4), - "Eastern Vault Fortress": AreaStats(3, 3, 3, 4, 3, 2, 4), - "Frog's Domain": AreaStats(3, 4, 3, 5, 3, 3, 4), + "Beneath the Vault": AreaStats(3, 3, 3, 3, 2, 1, 4, ["Sword", "Shield", "Magic Wand"]), + "Eastern Vault Fortress": AreaStats(3, 3, 3, 4, 3, 2, 4, ["Sword", "Shield", "Magic Wand"]), + "Frog's Domain": AreaStats(3, 4, 3, 5, 3, 3, 4, ["Sword", "Shield", "Magic Wand"]), # the second half of Atoll is the part you need the stats for, so putting it after frogs - "Ruined Atoll": AreaStats(4, 4, 3, 5, 3, 3, 5), - "Library": AreaStats(4, 4, 3, 5, 3, 3, 5), - "Quarry": AreaStats(5, 4, 3, 5, 3, 3, 5), - "Rooted Ziggurat": AreaStats(5, 5, 3, 5, 3, 3, 6), - "Swamp": AreaStats(1, 1, 1, 1, 1, 1, 6), - "Cathedral": AreaStats(1, 1, 1, 1, 1, 1, 6), + "Ruined Atoll": AreaStats(4, 4, 3, 5, 3, 3, 5, ["Sword", "Shield", "Magic Wand"]), + "The Librarian": AreaStats(4, 4, 3, 5, 3, 3, 5, ["Sword", "Shield", "Magic Wand"]), + "Quarry": AreaStats(5, 4, 3, 5, 3, 3, 5, ["Sword", "Shield", "Magic Wand"]), + "Rooted Ziggurat": AreaStats(5, 5, 3, 5, 3, 3, 6, ["Sword", "Shield", "Magic Wand"]), + "Swamp": AreaStats(1, 1, 1, 1, 1, 1, 6, ["Sword", "Shield", "Magic Wand"]), + "Cathedral": AreaStats(1, 1, 1, 1, 1, 1, 6, ["Sword", "Shield", "Magic Wand"]), + "The Heir": AreaStats(5, 5, 3, 5, 3, 3, 6, ["Sword", "Shield", "Magic Wand"]), } -def has_required_stats(area_name: str, state: CollectionState, player: int) -> bool: +def has_combat_reqs(area_name: str, state: CollectionState, player: int) -> bool: data = area_data[area_name] + for item in data.equipment: + if item == "Stick" and not has_melee(state, player): + return False + elif item == "Sword" and not has_sword(state, player): + return False + else: + if not state.has(item, player): + return False + if not has_required_stats(data, state, player): + return False + return True + + +def has_required_stats(data: AreaStats, state: CollectionState, player: int) -> bool: # for now, just check if you have the vanilla stat requirements, can get more advanced later if data.att_level > 1 and get_att_level(state, player) < data.att_level: return False @@ -71,28 +87,6 @@ def has_required_stats(area_name: str, state: CollectionState, player: int) -> b return True -def has_required_items(required_items: List[List[str]], stick_req: bool, state: CollectionState, player: int) -> bool: - # stick required for power unless excepted - if stick_req and not has_melee(state, player): - return False - if not required_items: - return True - - for reqs in required_items: - # stick and sword have special handling because of the progressive sword option - if sword in reqs: - # state.has_all returns true for an empty list - if has_sword(state, player) and state.has_all([item for item in reqs if item != sword], player): - return True - elif stick in reqs: - if has_melee(state, player) and state.has_all([item for item in reqs if item != stick], player): - return True - else: - if state.has_all(reqs, player): - return True - return False - - def get_effective_hp(state: CollectionState, player: int) -> int: # starting hp is 80, you get 20 per upgrade player_hp = 60 + get_hp_level(state, player) * 20 diff --git a/worlds/tunic/er_rules.py b/worlds/tunic/er_rules.py index d7d4cd5f35..3eec7393c9 100644 --- a/worlds/tunic/er_rules.py +++ b/worlds/tunic/er_rules.py @@ -5,7 +5,7 @@ from .rules import (has_ability, has_sword, has_melee, has_ice_grapple_logic, ha laurels_zip) from .er_data import Portal from .ladder_storage_data import ow_ladder_groups, region_ladders, easy_ls, medium_ls, hard_ls -from .combat_logic import has_combat_logic +from .combat_logic import has_required_stats from BaseClasses import Region, CollectionState if TYPE_CHECKING: @@ -930,7 +930,7 @@ def set_er_region_rules(world: "TunicWorld", regions: Dict[str, Region], portal_ or (state.has("Ladder to Ruined Atoll", player) and state.can_reach_region("Overworld Beach", player))))) and (not options.combat_logic - or has_combat_logic(["Birds with Guns", "Lost Echoes"], state, player))) + or has_required_stats("Swamp", state, player))) or has_ice_grapple_logic(False, IceGrappling.option_medium, state, world)) if options.ladder_storage >= LadderStorage.option_hard and options.shuffle_ladders: @@ -1167,16 +1167,16 @@ def set_er_region_rules(world: "TunicWorld", regions: Dict[str, Region], portal_ if world.options.combat_logic >= CombatLogic.option_bosses_only: set_rule(wg_to_after_gk, lambda state: state.has(laurels, player) - or has_combat_logic(["Garden Knight"], state, player)) + or has_required_stats("Garden Knight", state, player)) if not world.options.hexagon_quest: add_rule(heir_fight, - lambda state: has_combat_logic(["The Heir"], state, player)) + lambda state: has_required_stats("The Heir", state, player)) if world.options.combat_logic == CombatLogic.option_on: # need to fight through the rudelings and turret, or just laurels from near the windmill set_rule(ow_to_well_entry, lambda state: state.has(laurels, player) - or has_combat_logic(["Shield Rudelings", "Autobolts"], state, player)) + or has_combat_requirements(["Shield Rudelings", "Autobolts"], state, player)) set_rule(ow_tunnel_beach, lambda state: has_combat_logic(["Shield Rudelings"], state, player)) # need some strength to deal with the frogs at the northwest fuse