mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-03-30 00:03:28 -07:00
Mess with state with collect and remove to save like 2 seconds (never again)
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
from typing import Dict, List, Any, Tuple, TypedDict, ClassVar, Union
|
||||
from logging import warning
|
||||
from BaseClasses import Region, Location, Item, Tutorial, ItemClassification, MultiWorld
|
||||
from .items import item_name_to_id, item_table, item_name_groups, fool_tiers, filler_items, slot_data_item_names
|
||||
from BaseClasses import Region, Location, Item, Tutorial, ItemClassification, MultiWorld, CollectionState
|
||||
from .items import (item_name_to_id, item_table, item_name_groups, fool_tiers, filler_items, slot_data_item_names,
|
||||
combat_items)
|
||||
from .locations import location_table, location_name_groups, location_name_to_id, hexagon_locations
|
||||
from .rules import set_location_rules, set_region_rules, randomize_ability_unlocks, gold_hexagon
|
||||
from .er_rules import set_er_location_rules
|
||||
@@ -347,6 +348,21 @@ class TunicWorld(World):
|
||||
def get_filler_item_name(self) -> str:
|
||||
return self.random.choice(filler_items)
|
||||
|
||||
# cache whether you can get through combat logic areas
|
||||
def collect(self, state: CollectionState, item: Item) -> bool:
|
||||
change = super().collect(state, item)
|
||||
if change:
|
||||
if item.name in combat_items:
|
||||
state.prog_items[self.player]["need_to_reset_combat_state"] = 1
|
||||
return change
|
||||
|
||||
def remove(self, state: CollectionState, item: Item) -> bool:
|
||||
change = super().remove(state, item)
|
||||
if change:
|
||||
if item.name in combat_items:
|
||||
state.prog_items[self.player]["need_to_reset_combat_state"] = 1
|
||||
return change
|
||||
|
||||
def extend_hint_information(self, hint_data: Dict[int, Dict[int, str]]) -> None:
|
||||
if self.options.entrance_rando:
|
||||
hint_data.update({self.player: {}})
|
||||
|
||||
@@ -45,7 +45,61 @@ area_data: Dict[str, AreaStats] = {
|
||||
}
|
||||
|
||||
|
||||
def has_combat_reqs(area_name: str, state: CollectionState, player: int, alt_data: Optional[AreaStats] = None) -> bool:
|
||||
# these are used for caching which areas can currently be reached in state
|
||||
boss_areas: List[str] = [name for name, data in area_data.items() if data.is_boss and name != "Gauntlet"]
|
||||
non_boss_areas: List[str] = [name for name, data in area_data.items() if not data.is_boss]
|
||||
|
||||
|
||||
def has_combat_reqs(area_name: str, state: CollectionState, player: int) -> bool:
|
||||
# we're caching whether you've met the combat reqs before if the state didn't change first
|
||||
player_state = state.prog_items[player]
|
||||
# if the combat state is stale, mark each area's combat state as stale
|
||||
if player_state["need_to_reset_combat_state"]:
|
||||
player_state["need_to_reset_combat_state"] = 0
|
||||
for name in boss_areas:
|
||||
player_state["combat_state_calced_for_" + name] = 0
|
||||
for name in non_boss_areas:
|
||||
player_state["combat_state_calced_for_" + name] = 0
|
||||
player_state["combat_state_calced_for_Gauntlet"] = 0
|
||||
|
||||
met_combat_reqs = check_combat_reqs(area_name, state, player)
|
||||
if player_state["combat_state_calced_for_" + area_name]:
|
||||
return met_combat_reqs
|
||||
|
||||
# loop through the lists and set the easier/harder area states accordingly
|
||||
if area_name in boss_areas:
|
||||
area_list = boss_areas
|
||||
elif area_name in non_boss_areas:
|
||||
area_list = non_boss_areas
|
||||
else:
|
||||
area_list = [area_name]
|
||||
|
||||
if area_name in area_list:
|
||||
if met_combat_reqs:
|
||||
# set the state as true for each area until you get to the area we're looking at
|
||||
for name in area_list:
|
||||
player_state["combat_state_calced_for_" + name] = 1
|
||||
player_state["combat_reqs_met_for_" + name] = 1
|
||||
if name == area_name:
|
||||
break
|
||||
else:
|
||||
# set the state as false for the area we're looking at and each area after that
|
||||
reached_name = False
|
||||
for name in area_list:
|
||||
if name == area_name:
|
||||
reached_name = True
|
||||
if reached_name:
|
||||
player_state["combat_state_calced_for_" + name] = 1
|
||||
player_state["combat_reqs_met_for_" + name] = 0
|
||||
|
||||
return check_combat_reqs(area_name, state, player)
|
||||
|
||||
|
||||
def check_combat_reqs(area_name: str, state: CollectionState, player: int, alt_data: Optional[AreaStats] = None) -> bool:
|
||||
# if our cache says we've already calced this, we don't need to go through these calculations again
|
||||
if state.prog_items[player]["combat_state_calced_for_" + area_name]:
|
||||
return bool(state.prog_items[player]["combat_reqs_met_for_" + area_name])
|
||||
|
||||
data = alt_data or area_data[area_name]
|
||||
extra_att_needed = 0
|
||||
extra_def_needed = 0
|
||||
@@ -108,7 +162,7 @@ def has_combat_reqs(area_name: str, state: CollectionState, player: int, alt_dat
|
||||
more_modified_stats = AreaStats(data.att_level - 16, data.def_level, data.potion_level,
|
||||
data.hp_level, data.sp_level, data.mp_level + 4, data.potion_count,
|
||||
equip_list)
|
||||
if has_combat_reqs("none", state, player, more_modified_stats):
|
||||
if check_combat_reqs("none", state, player, more_modified_stats):
|
||||
return True
|
||||
|
||||
# and we need to check if you would have the required stats if you didn't have magic
|
||||
@@ -116,7 +170,7 @@ def has_combat_reqs(area_name: str, state: CollectionState, player: int, alt_dat
|
||||
more_modified_stats = AreaStats(data.att_level + 2, data.def_level + 2, data.potion_level,
|
||||
data.hp_level, data.sp_level, data.mp_level - 16, data.potion_count,
|
||||
equip_list)
|
||||
if has_combat_reqs("none", state, player, more_modified_stats):
|
||||
if check_combat_reqs("none", state, player, more_modified_stats):
|
||||
return True
|
||||
|
||||
elif stick_bool and "Stick" in data.equipment and "Magic" in data.equipment:
|
||||
@@ -125,7 +179,7 @@ def has_combat_reqs(area_name: str, state: CollectionState, player: int, alt_dat
|
||||
more_modified_stats = AreaStats(data.att_level - 16, data.def_level, data.potion_level,
|
||||
data.hp_level, data.sp_level, data.mp_level + 4, data.potion_count,
|
||||
equip_list)
|
||||
if has_combat_reqs("none", state, player, more_modified_stats):
|
||||
if check_combat_reqs("none", state, player, more_modified_stats):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
@@ -163,12 +217,11 @@ def has_required_stats(data: AreaStats, state: CollectionState, player: int) ->
|
||||
free_def = player_def - def_offerings
|
||||
free_sp = player_sp - sp_offerings
|
||||
paid_stats = data.def_level + data.sp_level - free_def - free_sp
|
||||
def_to_buy = 0
|
||||
sp_to_buy = 0
|
||||
|
||||
if paid_stats <= 0:
|
||||
# if you don't have to pay for any stats, you don't need money for these upgrades
|
||||
pass
|
||||
def_to_buy = 0
|
||||
elif paid_stats <= def_offerings:
|
||||
# get the amount needed to buy these def offerings
|
||||
def_to_buy = paid_stats
|
||||
|
||||
@@ -208,6 +208,10 @@ slot_data_item_names = [
|
||||
"Gold Questagon",
|
||||
]
|
||||
|
||||
combat_items: List[str] = [name for name, data in item_table.items()
|
||||
if data.combat_ic and IC.progression in data.combat_ic]
|
||||
combat_items.extend(["Stick", "Sword", "Sword Upgrade", "Magic Wand", "Hero's Laurels"])
|
||||
|
||||
item_name_to_id: Dict[str, int] = {name: item_base_id + data.item_id_offset for name, data in item_table.items()}
|
||||
|
||||
filler_items: List[str] = [name for name, data in item_table.items() if data.classification == IC.filler]
|
||||
|
||||
Reference in New Issue
Block a user