From dade03ed647b7b48302c70431d07c1026527f071 Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Wed, 30 Jul 2025 02:18:10 -0600 Subject: [PATCH 01/23] create lambda condition prototype --- worlds/crosscode/logic.py | 5 +- worlds/crosscode/types/condition.py | 81 ++++++++++++++++------------- 2 files changed, 48 insertions(+), 38 deletions(-) diff --git a/worlds/crosscode/logic.py b/worlds/crosscode/logic.py index 05811468b6f1..cf3a1292a926 100644 --- a/worlds/crosscode/logic.py +++ b/worlds/crosscode/logic.py @@ -15,7 +15,6 @@ def condition_satisfied( """ Factory function. Return value is a rule that checks whether all the conditions are satisfied. """ - def conditions_satisfied_internal(state: CollectionState) -> bool: - return all(c.satisfied(state, player, location, cond_args) for c in conditions) + callbacks = [c.satisfied(player, location, cond_args) for c in conditions] - return conditions_satisfied_internal + return lambda state: all(map(lambda x: x(state), callbacks)) diff --git a/worlds/crosscode/types/condition.py b/worlds/crosscode/types/condition.py index 6145c1beec28..5fdac94c7dee 100644 --- a/worlds/crosscode/types/condition.py +++ b/worlds/crosscode/types/condition.py @@ -1,6 +1,6 @@ import typing import abc -from dataclasses import field, dataclass +from dataclasses import dataclass from BaseClasses import CollectionState from ..options import ShopReceiveMode @@ -22,7 +22,7 @@ class LogicDict(typing.TypedDict): class Condition(abc.ABC): @abc.abstractmethod - def satisfied(self, state: CollectionState, player: int, location: int | None, args: LogicDict) -> bool: + def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: pass @dataclass @@ -30,7 +30,7 @@ class ItemCondition(Condition): item_name: str amount: int = 1 - def satisfied(self, state: CollectionState, player: int, location: int | None, args: LogicDict) -> bool: + def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: target = self.amount if self.item_name in args["keyrings"]: target = 1 @@ -38,32 +38,36 @@ def satisfied(self, state: CollectionState, player: int, location: int | None, a replacements = args["item_progressive_replacements"] if self.item_name in replacements: - for prog_item_name, quantity in replacements[self.item_name]: - if state.has(prog_item_name, player, quantity): - return True + def callback(state: CollectionState) -> bool: + for prog_item_name, quantity in replacements[self.item_name]: + if state.has(prog_item_name, player, quantity): + return True + return state.has(self.item_name, player, target) + + return callback - return state.has(self.item_name, player, target) + return lambda state: state.has(self.item_name, player, target) @dataclass class QuestCondition(Condition): quest_name: str - def satisfied(self, state: CollectionState, player: int, location: int | None, args: LogicDict) -> bool: - return state.has(f"{self.quest_name} (Event)", player) + def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: + return lambda state: state.has(f"{self.quest_name} (Event)", player) @dataclass class LocationCondition(Condition): location_name: str - def satisfied(self, state: CollectionState, player: int, location: int | None, args: LogicDict) -> bool: - return state.has(f"{self.location_name} (Event)", player) + def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: + return lambda state: state.has(f"{self.location_name} (Event)", player) @dataclass class RegionCondition(Condition): target_mode: typing.Optional[str] region_name: str - def satisfied(self, state: CollectionState, player: int, location: int | None, args: LogicDict) -> bool: + def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: # target_mode == None means that it matches in all modes. # so if target_mode == None, check if we can reach that region. # else, if the target mode matches, also check if we can reach that region. @@ -71,14 +75,14 @@ def satisfied(self, state: CollectionState, player: int, location: int | None, a mode: str = args["mode"] if self.target_mode is None or mode == self.target_mode: - return state.can_reach_region(self.region_name, player) + return lambda state: state.can_reach_region(self.region_name, player) - return True + return lambda _: True @dataclass class AnyElementCondition(Condition): - def satisfied(self, state: CollectionState, player: int, location: int | None, args: LogicDict) -> bool: - return any([ + def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: + return lambda state: any([ state.has("Heat", player), state.has("Cold", player), state.has("Shock", player), @@ -89,8 +93,9 @@ def satisfied(self, state: CollectionState, player: int, location: int | None, a class OrCondition(Condition): subconditions: list[Condition] - def satisfied(self, state: CollectionState, player: int, location: int | None, args: LogicDict) -> bool: - return any(map(lambda x: x.satisfied(state, player, location, args), self.subconditions)) + def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: + callbacks = [x.satisfied(player, location, args) for x in self.subconditions] + return lambda state: any(map(lambda x: x(state), callbacks)) @dataclass class AndCondition(Condition): @@ -103,18 +108,24 @@ def satisfied(self, state: CollectionState, player: int, location: int | None, a class VariableCondition(Condition): name: str - def satisfied(self, state: CollectionState, player: int, location: int | None, args: LogicDict) -> bool: + def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: variables = args["variables"] variable_definitions = args["variable_definitions"] if self.name not in variables: - return True + return lambda _: True - for value in variables[self.name]: - if not all(map(lambda c: c.satisfied(state, player, location, args), variable_definitions[self.name][value])): - return False + callbacks = sum( + [ + [ + x.satisfied(player, location, args) + for x in variable_definitions[self.name][value] + ] for value in variables[self.name] + ], + start=[] + ) - return True + return lambda state: all(map(lambda x: x(state), callbacks)) @dataclass class VariableEntryCondition(Condition): @@ -137,7 +148,7 @@ class ChestKeyCondition(Condition): "Gold": "Radiant Key", } - def satisfied(self, state: CollectionState, player: int, location: int | None, args: LogicDict) -> bool: + def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: chest_levels = args["chest_clearance_levels"] if location is None: @@ -146,25 +157,25 @@ def satisfied(self, state: CollectionState, player: int, location: int | None, a level: str = chest_levels.get(location, self.default_level) if level == "Default": - return True + return lambda _: True - return state.has(ChestKeyCondition.clearance_items[level], player) + return lambda state: state.has(ChestKeyCondition.clearance_items[level], player) @dataclass class ShopSlotCondition(Condition): shop_name: str item_id: int - def satisfied(self, state: CollectionState, player: int, location: int | None, args: LogicDict) -> bool: + def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: if args["shop_receive_mode"] is None: - return True + return lambda _: True if args["shop_receive_mode"] == ShopReceiveMode.option_per_item_type: - return state.has(args["shop_unlock_by_id"][self.item_id].name, player) + return lambda state: state.has(args["shop_unlock_by_id"][self.item_id].name, player) if args["shop_receive_mode"] == ShopReceiveMode.option_per_shop: - return state.has(args["shop_unlock_by_shop"][self.shop_name].name, player) + return lambda state: state.has(args["shop_unlock_by_shop"][self.shop_name].name, player) if args["shop_receive_mode"] == ShopReceiveMode.option_per_slot: - return state.has(args["shop_unlock_by_shop_and_id"][self.shop_name, self.item_id].name, player) - return True + return lambda state: state.has(args["shop_unlock_by_shop_and_id"][self.shop_name, self.item_id].name, player) + return lambda _: True @dataclass class BotanicsCompletionCondition(Condition): @@ -180,8 +191,8 @@ def satisfied(self, state: CollectionState, player: int, location: int | None, a return collected >= self.amount class NeverCondition(Condition): - def satisfied(self, state: CollectionState, player: int, location: int | None, args: LogicDict) -> bool: - return False + def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: + return lambda _: False __all__ = [ "Condition", From 653a0086302df2aa255ef698abfaad94a23f8c62 Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Thu, 14 May 2026 02:29:16 -0600 Subject: [PATCH 02/23] add support for new conditions --- worlds/crosscode/types/condition.py | 30 +++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/worlds/crosscode/types/condition.py b/worlds/crosscode/types/condition.py index 5fdac94c7dee..31b11afb9a9c 100644 --- a/worlds/crosscode/types/condition.py +++ b/worlds/crosscode/types/condition.py @@ -101,8 +101,9 @@ def satisfied(self, player: int, location: int | None, args: LogicDict) -> typin class AndCondition(Condition): subconditions: list[Condition] - def satisfied(self, state: CollectionState, player: int, location: int | None, args: LogicDict) -> bool: - return all(map(lambda x: x.satisfied(state, player, location, args), self.subconditions)) + def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: + callbacks = [x.satisfied(player, location, args) for x in self.subconditions] + return lambda state: all(map(lambda x: x(state), callbacks)) @dataclass class VariableCondition(Condition): @@ -133,10 +134,9 @@ class VariableEntryCondition(Condition): value: str desired: bool - def satisfied(self, state: CollectionState, player: int, location: int | None, args: LogicDict) -> bool: - variables = args["variables"] - - return (self.value in variables[self.name]) == self.desired + def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: + valid = (self.value in args["variables"][self.name]) == self.desired + return lambda _: valid @dataclass class ChestKeyCondition(Condition): @@ -181,14 +181,16 @@ def satisfied(self, player: int, location: int | None, args: LogicDict) -> typin class BotanicsCompletionCondition(Condition): amount: int - def satisfied(self, state: CollectionState, player: int, location: int | None, args: LogicDict) -> bool: - collected = sum([ - amount - for region, amount in args["region_botanics_amounts"].items() - if state.can_reach_region(region, player) - ]) - - return collected >= self.amount + def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: + def satisfied_internal(state: CollectionState): + collected = sum([ + amount + for region, amount in args["region_botanics_amounts"].items() + if state.can_reach_region(region, player) + ]) + + return collected >= self.amount + return satisfied_internal class NeverCondition(Condition): def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: From 84cf980ef5e8a26f66f1f3ae959b42798c3989b8 Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Thu, 14 May 2026 03:00:31 -0600 Subject: [PATCH 03/23] pre-cache some f-strings for speed --- worlds/crosscode/types/condition.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/worlds/crosscode/types/condition.py b/worlds/crosscode/types/condition.py index 31b11afb9a9c..5348f1f6bfc6 100644 --- a/worlds/crosscode/types/condition.py +++ b/worlds/crosscode/types/condition.py @@ -1,6 +1,6 @@ import typing import abc -from dataclasses import dataclass +from dataclasses import dataclass, field from BaseClasses import CollectionState from ..options import ShopReceiveMode @@ -51,16 +51,24 @@ def callback(state: CollectionState) -> bool: @dataclass class QuestCondition(Condition): quest_name: str + event_name: str = field(init=False) + + def __post_init__(self): + self.event_name = f"{self.quest_name} (Event)" def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: - return lambda state: state.has(f"{self.quest_name} (Event)", player) + return lambda state: state.has(self.event_name, player) @dataclass class LocationCondition(Condition): location_name: str + event_name: str = field(init=False) + + def __post_init__(self): + self.event_name = f"{self.location_name} (Event)" def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: - return lambda state: state.has(f"{self.location_name} (Event)", player) + return lambda state: state.has(self.event_name, player) @dataclass class RegionCondition(Condition): From 709ca1646acc92108e47ca1ad6cff2d0eb290d87 Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Thu, 18 Jun 2026 21:20:05 -0600 Subject: [PATCH 04/23] add enemy types --- worlds/crosscode/types/enemies.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 worlds/crosscode/types/enemies.py diff --git a/worlds/crosscode/types/enemies.py b/worlds/crosscode/types/enemies.py new file mode 100644 index 000000000000..9aa0f1e7d918 --- /dev/null +++ b/worlds/crosscode/types/enemies.py @@ -0,0 +1,28 @@ +from dataclasses import dataclass, field + +from .items import ItemData +from .locations import LocationData + +@dataclass +class Booster: + level: int + """Level that the enemy gets boosted to in vanilla""" + booster: ItemData + """Booster that effects the boost""" + +@dataclass +class Enemy: + name: str + """The human-readable name of the enemy""" + area: str + """The internal area where the enemy is found""" + internal_name: str + """The enemy's name in the game files""" + level: int + """The enemy's base level in vanilla""" + first_encounter_event: LocationData + """The event that unlocks whether you can fight one instance of the enemy (for killsanity)""" + grind_access_event: LocationData | None = field(default=None) + """The event that unlocks whether you can grind the enemy -- if null, enemy cannot be grinded""" + booster: Booster | None = field(default=None) + """If the enemy can be boosted, the details about that""" From 8b7a1b9e0a3e950e16bf95ea476d9e7950c19d2e Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Thu, 18 Jun 2026 21:28:20 -0600 Subject: [PATCH 05/23] read enemy data (but do not do anything with it yet) --- worlds/crosscode/codegen/lists.py | 56 ++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/worlds/crosscode/codegen/lists.py b/worlds/crosscode/codegen/lists.py index 1b5f254a35c8..2fe67a3da392 100644 --- a/worlds/crosscode/codegen/lists.py +++ b/worlds/crosscode/codegen/lists.py @@ -8,12 +8,13 @@ from BaseClasses import ItemClassification -from .parse import JsonParser +from .parse import JsonParser, JsonParserError from .context import Context from .util import BASE_ID, DYNAMIC_ITEM_AREA_OFFSET, RESERVED_ITEM_IDS from .markers import Marker, MarkerGenerator from ..types.items import ItemData, ProgressiveItemChainSingle, SingleItemData, ItemPoolEntry, ProgressiveItemChain +from ..types.enemies import Enemy from ..types.locations import AccessInfo, LocationData from ..types.condition import Condition, NeverCondition, RegionCondition, OrCondition, AndCondition, ShopSlotCondition from ..types.shops import ShopData @@ -69,6 +70,8 @@ class ListInfo: region_botanics_amounts: dict[str, dict[str, int]] # { mode => { region => number of plants } } botanics_internal_names_to_ids: dict[str, int] + enemies: dict[str, Enemy] + progressive_chains: dict[str, ProgressiveItemChain] progressive_items: dict[str, ItemData] @@ -115,6 +118,8 @@ def __init__(self, ctx: Context): self.region_botanics_amounts = defaultdict(lambda: defaultdict(lambda: 0)) self.botanics_internal_names_to_ids = {} + self.enemies = {} + self.json_parser = JsonParser(self.ctx) self.json_parser.single_items_dict = self.single_items_dict self.json_parser.items_dict = self.items_dict @@ -165,6 +170,8 @@ def build(self): self.__add_botanics(file["botanics"]) + self.__add_enemies(file["enemies"]) + self.__add_vars(self.ctx.rando_data["vars"]) def __get_cached_location_id(self, name: str) -> typing.Optional[int]: @@ -544,6 +551,53 @@ def __add_botanics(self, raw: dict[str, dict[str, typing.Any]]): for name, plant in raw.items(): self.__add_plant(name, plant) + def __add_enemy(self, raw: dict[str, typing.Any]): + try: + name = raw["name"] + area = raw["area"] + internal_name = raw["id"] + level = raw["level"] + except KeyError: + raise JsonParserError(raw, raw, "", f"Enemy specification lacks an essential parameter: {raw}") + + try: + first_encounter_access = grind_access = self.json_parser.parse_location_access_info(raw) + except JsonParserError: + if "firstEncounter" in raw: + first_encounter_access = self.json_parser.parse_location_access_info(raw["firstEncounter"]) + else: + raise JsonParserError(raw, raw, "first encounter", f"Enemy must at least have a first encounter") + + if "grindAccess" in raw: + grind_access = self.json_parser.parse_location_access_info(raw["grindAccess"]) + else: + grind_access = None + + first_encounter_event = LocationData( + name="First Encounter: {name} (Event)", + code=None, + access=first_encounter_access, + area=area, + metadata=raw.get("metadata", None), + ) + + self.events_data[first_encounter_event.name] = first_encounter_event + + if grind_access is not None: + grind_access_event = LocationData( + name="Grind Access: {name} (Event)", + code=None, + access=grind_access, + area=area, + metadata=raw.get("metadata", None), + ) + + self.events_data[grind_access_event.name] = grind_access_event + + def __add_enemies(self, raw: list[dict[str, typing.Any]]): + for enemy in raw: + self.__add_enemy(enemy) + def __add_reward(self, reward: list[dict[str, typing.Any]]) -> ItemData: """ Ensure an item reward is in the list of items. From 3cc3980122e5d0ceaf6b43b76f17aef2670e741c Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Thu, 18 Jun 2026 21:37:05 -0600 Subject: [PATCH 06/23] do not emit non-`init` fields --- worlds/crosscode/codegen/ast.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/worlds/crosscode/codegen/ast.py b/worlds/crosscode/codegen/ast.py index 4250f264fe70..ebee1269dd00 100644 --- a/worlds/crosscode/codegen/ast.py +++ b/worlds/crosscode/codegen/ast.py @@ -19,7 +19,11 @@ def create_expression_condition(condition: Condition) -> ast.Call: result = ast.Call( func=ast.Name(condition.__class__.__name__), args=[], - keywords=[ast.keyword(arg=key, value=ast.Constant(value)) for key, value in condition.__dict__.items()], + keywords=[ + ast.keyword(arg=key, value=ast.Constant(value)) + for key, value in condition.__dict__.items() + if condition.__dataclass_fields__[key].init + ], ) ast.fix_missing_locations(result) From e9b7a0c6e9642089847d2e6b23a7a628e78fef17 Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Thu, 18 Jun 2026 22:23:15 -0600 Subject: [PATCH 07/23] add special handling of and/or conditions --- worlds/crosscode/codegen/ast.py | 36 +++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/worlds/crosscode/codegen/ast.py b/worlds/crosscode/codegen/ast.py index ebee1269dd00..377ea815aed5 100644 --- a/worlds/crosscode/codegen/ast.py +++ b/worlds/crosscode/codegen/ast.py @@ -5,30 +5,50 @@ import typing import ast -from ..types.condition import Condition +from ..types.condition import AndCondition, Condition, OrCondition, QuestCondition from ..types.locations import AccessInfo, LocationData from ..types.regions import Goal, RegionConnection from ..types.items import ItemData, ItemPoolEntry, ProgressiveChainEntry, SingleItemData from ..types.shops import ShopData -def create_expression_condition(condition: Condition) -> ast.Call: - """ - Create an expression representing a singular condition. - """ +def create_expression_dataclass(cls) -> ast.Call: result = ast.Call( - func=ast.Name(condition.__class__.__name__), + func=ast.Name(cls.__class__.__name__), args=[], keywords=[ ast.keyword(arg=key, value=ast.Constant(value)) - for key, value in condition.__dict__.items() - if condition.__dataclass_fields__[key].init + for key, value in cls.__dict__.items() + if cls.__dataclass_fields__[key].init ], ) ast.fix_missing_locations(result) return result +def create_expression_condition(condition: Condition) -> ast.Call: + """ + Create an expression representing a singular condition. + """ + if isinstance(condition, OrCondition) or isinstance(condition, AndCondition): + # we handle these conditions in a special way, since their lists cannot be encoded by ast.Constant + result = ast.Call( + func=ast.Name(condition.__class__.__name__), + args=[], + keywords=[ + ast.keyword( + arg="subconditions", + value=create_expression_condition_list(condition.subconditions) + ) + ], + ) + else: + # this block should handle most cases, unless you make a condition that has a complex type + result = create_expression_dataclass(condition) + ast.fix_missing_locations(result) + + return result + def create_expression_condition_list(conditions: typing.Optional[list[Condition]]) -> ast.expr: """ Create an expression representing a list of conditions. From d10adcca0b76cf09051e09aa5fcd4b29677901c5 Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Tue, 30 Jun 2026 22:31:18 -0600 Subject: [PATCH 08/23] condense dataclass encoding operation --- worlds/crosscode/codegen/ast.py | 1 + 1 file changed, 1 insertion(+) diff --git a/worlds/crosscode/codegen/ast.py b/worlds/crosscode/codegen/ast.py index 377ea815aed5..6e5d0db68f18 100644 --- a/worlds/crosscode/codegen/ast.py +++ b/worlds/crosscode/codegen/ast.py @@ -20,6 +20,7 @@ def create_expression_dataclass(cls) -> ast.Call: ast.keyword(arg=key, value=ast.Constant(value)) for key, value in cls.__dict__.items() if cls.__dataclass_fields__[key].init + # and cls.__dataclass_fields__[key].default != value ], ) ast.fix_missing_locations(result) From 9e6f7bcf3bd31374e808888b51521f14221b9f9a Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Tue, 30 Jun 2026 22:37:00 -0600 Subject: [PATCH 09/23] add codegen for enemies (and do codegen) --- worlds/crosscode/codegen/gen.py | 15 ++ worlds/crosscode/codegen/lists.py | 34 +++-- worlds/crosscode/enemies.py | 74 ++++++++++ worlds/crosscode/locations.py | 128 ++++++++++++++++++ .../crosscode/templates/enemies.template.py | 6 + worlds/crosscode/types/enemies.py | 4 +- worlds/crosscode/types/metadata.py | 2 + 7 files changed, 251 insertions(+), 12 deletions(-) create mode 100644 worlds/crosscode/enemies.py create mode 100644 worlds/crosscode/templates/enemies.template.py diff --git a/worlds/crosscode/codegen/gen.py b/worlds/crosscode/codegen/gen.py index 8ea8fe9e54c9..0d6c92715ee7 100644 --- a/worlds/crosscode/codegen/gen.py +++ b/worlds/crosscode/codegen/gen.py @@ -215,6 +215,20 @@ def generate_python_file_shops(self): with open(os.path.join(self.world_dir, "shops.py"), "w", encoding="utf8") as f: f.write(locations_complete) + def generate_python_file_enemies(self): + """ + Generates enemies.py, which provides a list of enemies. + """ + template = self.environment.get_template("enemies.template.py") + + locations_complete = template.render( + enemies=self.lists.enemies.items(), + **self.common_args + ) + + with open(os.path.join(self.world_dir, "enemies.py"), "w", encoding="utf8") as f: + f.write(locations_complete) + def generate_python_files(self) -> None: """ @@ -228,6 +242,7 @@ def generate_python_files(self) -> None: self.generate_python_file_regions() self.generate_python_file_vars() self.generate_python_file_shops() + self.generate_python_file_enemies() def generate_mod_files(self): """ diff --git a/worlds/crosscode/codegen/lists.py b/worlds/crosscode/codegen/lists.py index 2fe67a3da392..5eb4f4acc32b 100644 --- a/worlds/crosscode/codegen/lists.py +++ b/worlds/crosscode/codegen/lists.py @@ -568,34 +568,48 @@ def __add_enemy(self, raw: dict[str, typing.Any]): else: raise JsonParserError(raw, raw, "first encounter", f"Enemy must at least have a first encounter") - if "grindAccess" in raw: - grind_access = self.json_parser.parse_location_access_info(raw["grindAccess"]) + if "grind" in raw: + grind_access = self.json_parser.parse_location_access_info(raw["grind"]) else: grind_access = None + metadata = raw.get("metadata", {}) first_encounter_event = LocationData( - name="First Encounter: {name} (Event)", + name=f"First Encounter: {name} (Event)", code=None, access=first_encounter_access, area=area, - metadata=raw.get("metadata", None), + metadata=metadata | { "kill": True }, ) self.events_data[first_encounter_event.name] = first_encounter_event if grind_access is not None: - grind_access_event = LocationData( - name="Grind Access: {name} (Event)", + grind_event = LocationData( + name=f"Grind: {name} (Event)", code=None, access=grind_access, area=area, - metadata=raw.get("metadata", None), + metadata=metadata | { "combat": True }, ) - self.events_data[grind_access_event.name] = grind_access_event + self.events_data[grind_event.name] = grind_event + else: + grind_event = None + + enemy = Enemy( + name=name, + area=area, + internal_name=internal_name, + level=level, + first_encounter_event_name=first_encounter_event.name, + grind_event_name=grind_event.name if grind_event is not None else None + ) + + self.enemies[name] = enemy - def __add_enemies(self, raw: list[dict[str, typing.Any]]): - for enemy in raw: + def __add_enemies(self, raw: dict[str, dict[str, typing.Any]]): + for enemy in raw.values(): self.__add_enemy(enemy) def __add_reward(self, reward: list[dict[str, typing.Any]]) -> ItemData: diff --git a/worlds/crosscode/enemies.py b/worlds/crosscode/enemies.py new file mode 100644 index 000000000000..850474273005 --- /dev/null +++ b/worlds/crosscode/enemies.py @@ -0,0 +1,74 @@ +# WARNING: THIS FILE HAS BEEN GENERATED! +# Modifications to this file will not be kept. +# If you need to change something here, check out codegen.py and the templates directory. + + +from .types.condition import * +from .types.enemies import Enemy + +enemies: dict[str, Enemy] = { + 'Hedgehag': Enemy(name='Hedgehag', area='autumn-area', internal_name='hedgehog', level=4, first_encounter_event_name='First Encounter: Hedgehag (Event)', grind_event_name='Grind: Hedgehag (Event)', booster=None), + "Rockin' Hillkat": Enemy(name="Rockin' Hillkat", area='autumn-area', internal_name='meerkat', level=5, first_encounter_event_name="First Encounter: Rockin' Hillkat (Event)", grind_event_name="Grind: Rockin' Hillkat (Event)", booster=None), + 'Mad Bovine': Enemy(name='Mad Bovine', area='autumn-area', internal_name='buffalo', level=6, first_encounter_event_name='First Encounter: Mad Bovine (Event)', grind_event_name='Grind: Mad Bovine (Event)', booster=None), + 'Old Hedgehag': Enemy(name='Old Hedgehag', area='autumn-area', internal_name='hedgehog-alt', level=9, first_encounter_event_name='First Encounter: Old Hedgehag (Event)', grind_event_name='Grind: Old Hedgehag (Event)', booster=None), + "Flamin' Hillkat": Enemy(name="Flamin' Hillkat", area='autumn-area', internal_name='meerkat-alt', level=10, first_encounter_event_name="First Encounter: Flamin' Hillkat (Event)", grind_event_name="Grind: Flamin' Hillkat (Event)", booster=None), + 'Red Eyed Bovine': Enemy(name='Red Eyed Bovine', area='autumn-area', internal_name='buffalo-alt', level=12, first_encounter_event_name='First Encounter: Red Eyed Bovine (Event)', grind_event_name='Grind: Red Eyed Bovine (Event)', booster=None), + 'Young Frobbit': Enemy(name='Young Frobbit', area='bergen-trails', internal_name='gray-frobbit', level=13, first_encounter_event_name='First Encounter: Young Frobbit (Event)', grind_event_name='Grind: Young Frobbit (Event)', booster=None), + 'White Frobbit': Enemy(name='White Frobbit', area='bergen-trails', internal_name='frobbit', level=15, first_encounter_event_name='First Encounter: White Frobbit (Event)', grind_event_name='Grind: White Frobbit (Event)', booster=None), + 'Seafly': Enemy(name='Seafly', area='bergen-trails', internal_name='seahorse', level=16, first_encounter_event_name='First Encounter: Seafly (Event)', grind_event_name='Grind: Seafly (Event)', booster=None), + 'Pengpeng': Enemy(name='Pengpeng', area='bergen-trails', internal_name='penguin', level=17, first_encounter_event_name='First Encounter: Pengpeng (Event)', grind_event_name='Grind: Pengpeng (Event)', booster=None), + 'Horny Goat': Enemy(name='Horny Goat', area='bergen-trails', internal_name='goat', level=17, first_encounter_event_name='First Encounter: Horny Goat (Event)', grind_event_name='Grind: Horny Goat (Event)', booster=None), + 'Karotto': Enemy(name='Karotto', area='bergen-trails', internal_name='snowman', level=18, first_encounter_event_name='First Encounter: Karotto (Event)', grind_event_name='Grind: Karotto (Event)', booster=None), + 'Fleazer': Enemy(name='Fleazer', area='cold-dng', internal_name='mine-coldbug', level=18, first_encounter_event_name='First Encounter: Fleazer (Event)', grind_event_name='Grind: Fleazer (Event)', booster=None), + 'Carritrich': Enemy(name='Carritrich', area='cold-dng', internal_name='mine-runbot', level=18, first_encounter_event_name='First Encounter: Carritrich (Event)', grind_event_name='Grind: Carritrich (Event)', booster=None), + 'Kamikatze': Enemy(name='Kamikatze', area='cold-dng', internal_name='mine-kamikatze', level=18, first_encounter_event_name='First Encounter: Kamikatze (Event)', grind_event_name='Grind: Kamikatze (Event)', booster=None), + 'Digmo': Enemy(name='Digmo', area='cold-dng', internal_name='mine-diggingbot', level=19, first_encounter_event_name='First Encounter: Digmo (Event)', grind_event_name='Grind: Digmo (Event)', booster=None), + 'Pinceron': Enemy(name='Pinceron', area='heat-area', internal_name='heat.scorpion', level=23, first_encounter_event_name='First Encounter: Pinceron (Event)', grind_event_name='Grind: Pinceron (Event)', booster=None), + 'Sharkster': Enemy(name='Sharkster', area='heat-area', internal_name='heat.sandshark', level=24, first_encounter_event_name='First Encounter: Sharkster (Event)', grind_event_name='Grind: Sharkster (Event)', booster=None), + 'Vulturbine': Enemy(name='Vulturbine', area='heat-area', internal_name='heat.volturbine', level=24, first_encounter_event_name='First Encounter: Vulturbine (Event)', grind_event_name='Grind: Vulturbine (Event)', booster=None), + 'Drillertoise': Enemy(name='Drillertoise', area='heat-area', internal_name='heat.drillertoise', level=25, first_encounter_event_name='First Encounter: Drillertoise (Event)', grind_event_name='Grind: Drillertoise (Event)', booster=None), + 'Tim': Enemy(name='Tim', area='heat-area', internal_name='heat.sandworm', level=25, first_encounter_event_name='First Encounter: Tim (Event)', grind_event_name='Grind: Tim (Event)', booster=None), + 'Boss Pincer': Enemy(name='Boss Pincer', area='heat-area', internal_name='heat.scorpion-alt', level=26, first_encounter_event_name='First Encounter: Boss Pincer (Event)', grind_event_name='Grind: Boss Pincer (Event)', booster=None), + 'Trijelly': Enemy(name='Trijelly', area='heat-dng', internal_name='heat.jellyfish', level=27, first_encounter_event_name='First Encounter: Trijelly (Event)', grind_event_name='Grind: Trijelly (Event)', booster=None), + 'Pada Moth': Enemy(name='Pada Moth', area='heat-dng', internal_name='heat.moth', level=27, first_encounter_event_name='First Encounter: Pada Moth (Event)', grind_event_name='Grind: Pada Moth (Event)', booster=None), + 'Darth Moth': Enemy(name='Darth Moth', area='heat-dng', internal_name='heat.darth-moth', level=28, first_encounter_event_name='First Encounter: Darth Moth (Event)', grind_event_name='Grind: Darth Moth (Event)', booster=None), + 'Magmanizer': Enemy(name='Magmanizer', area='heat-dng', internal_name='heat.heat-golem', level=28, first_encounter_event_name='First Encounter: Magmanizer (Event)', grind_event_name='Grind: Magmanizer (Event)', booster=None), + 'Radical Hedgehag': Enemy(name='Radical Hedgehag', area='autumn-fall', internal_name='autumn-fall.hedgehog-fall', level=32, first_encounter_event_name='First Encounter: Radical Hedgehag (Event)', grind_event_name='Grind: Radical Hedgehag (Event)', booster=None), + "Chillin' Hillkat": Enemy(name="Chillin' Hillkat", area='autumn-fall', internal_name='autumn-fall.meerkat-fall', level=34, first_encounter_event_name="First Encounter: Chillin' Hillkat (Event)", grind_event_name="Grind: Chillin' Hillkat (Event)", booster=None), + 'Fallfly': Enemy(name='Fallfly', area='autumn-fall', internal_name='autumn-fall.seahorse-fall', level=35, first_encounter_event_name='First Encounter: Fallfly (Event)', grind_event_name='Grind: Fallfly (Event)', booster=None), + 'Ivory Bovine': Enemy(name='Ivory Bovine', area='autumn-fall', internal_name='autumn-fall.buffalo-fall', level=36, first_encounter_event_name='First Encounter: Ivory Bovine (Event)', grind_event_name='Grind: Ivory Bovine (Event)', booster=None), + 'Neutral Virus': Enemy(name='Neutral Virus', area='arid', internal_name='arid.virus-neutral', level=38, first_encounter_event_name='First Encounter: Neutral Virus (Event)', grind_event_name='Grind: Neutral Virus (Event)', booster=None), + 'Heat Virus': Enemy(name='Heat Virus', area='arid', internal_name='arid.virus-heat', level=38, first_encounter_event_name='First Encounter: Heat Virus (Event)', grind_event_name='Grind: Heat Virus (Event)', booster=None), + 'Cold Virus': Enemy(name='Cold Virus', area='arid', internal_name='arid.virus-cold', level=38, first_encounter_event_name='First Encounter: Cold Virus (Event)', grind_event_name='Grind: Cold Virus (Event)', booster=None), + 'Argeby': Enemy(name='Argeby', area='jungle', internal_name='jungle.plant', level=37, first_encounter_event_name='First Encounter: Argeby (Event)', grind_event_name='Grind: Argeby (Event)', booster=None), + 'Gelleric': Enemy(name='Gelleric', area='jungle', internal_name='jungle.blob', level=38, first_encounter_event_name='First Encounter: Gelleric (Event)', grind_event_name='Grind: Gelleric (Event)', booster=None), + 'Papagun': Enemy(name='Papagun', area='jungle', internal_name='jungle.parrot', level=38, first_encounter_event_name='First Encounter: Papagun (Event)', grind_event_name='Grind: Papagun (Event)', booster=None), + 'Angler': Enemy(name='Angler', area='jungle', internal_name='jungle.fish', level=39, first_encounter_event_name='First Encounter: Angler (Event)', grind_event_name='Grind: Angler (Event)', booster=None), + 'Shokat': Enemy(name='Shokat', area='jungle', internal_name='jungle.shockcat', level=40, first_encounter_event_name='First Encounter: Shokat (Event)', grind_event_name='Grind: Shokat (Event)', booster=None), + 'Behesloth': Enemy(name='Behesloth', area='jungle', internal_name='jungle.sloth', level=42, first_encounter_event_name='First Encounter: Behesloth (Event)', grind_event_name='Grind: Behesloth (Event)', booster=None), + 'Jelleric': Enemy(name='Jelleric', area='wave-dng', internal_name='jungle.blob-wave', level=42, first_encounter_event_name='First Encounter: Jelleric (Event)', grind_event_name='Grind: Jelleric (Event)', booster=None), + 'Ocubepus': Enemy(name='Ocubepus', area='wave-dng', internal_name='jungle.octopus', level=42, first_encounter_event_name='First Encounter: Ocubepus (Event)', grind_event_name='Grind: Ocubepus (Event)', booster=None), + 'Blue Ray': Enemy(name='Blue Ray', area='wave-dng', internal_name='jungle.blueray', level=44, first_encounter_event_name='First Encounter: Blue Ray (Event)', grind_event_name='Grind: Blue Ray (Event)', booster=None), + 'Rob0ck': Enemy(name='Rob0ck', area='shock-dng', internal_name='jungle.chicken', level=42, first_encounter_event_name='First Encounter: Rob0ck (Event)', grind_event_name='Grind: Rob0ck (Event)', booster=None), + 'Powerplant': Enemy(name='Powerplant', area='shock-dng', internal_name='jungle.powerplant', level=43, first_encounter_event_name='First Encounter: Powerplant (Event)', grind_event_name='Grind: Powerplant (Event)', booster=None), + 'Ectovolt': Enemy(name='Ectovolt', area='shock-dng', internal_name='jungle.ghost', level=44, first_encounter_event_name='First Encounter: Ectovolt (Event)', grind_event_name='Grind: Ectovolt (Event)', booster=None), + 'Sun Beetle': Enemy(name='Sun Beetle', area='forest', internal_name='forest.bug-samurai-heat', level=51, first_encounter_event_name='First Encounter: Sun Beetle (Event)', grind_event_name='Grind: Sun Beetle (Event)', booster=None), + 'Moon Beetle': Enemy(name='Moon Beetle', area='forest', internal_name='forest.bug-samurai-shock', level=51, first_encounter_event_name='First Encounter: Moon Beetle (Event)', grind_event_name='Grind: Moon Beetle (Event)', booster=None), + 'Pandza': Enemy(name='Pandza', area='forest', internal_name='forest.panda', level=51, first_encounter_event_name='First Encounter: Pandza (Event)', grind_event_name='Grind: Pandza (Event)', booster=None), + 'Aranetarda': Enemy(name='Aranetarda', area='forest', internal_name='forest.spider', level=52, first_encounter_event_name='First Encounter: Aranetarda (Event)', grind_event_name='Grind: Aranetarda (Event)', booster=None), + 'Echinoignis': Enemy(name='Echinoignis', area='beach', internal_name='beach.sea-star-heat', level=66, first_encounter_event_name='First Encounter: Echinoignis (Event)', grind_event_name='Grind: Echinoignis (Event)', booster=None), + 'Echinonix': Enemy(name='Echinonix', area='beach', internal_name='beach.sea-star-cold', level=66, first_encounter_event_name='First Encounter: Echinonix (Event)', grind_event_name='Grind: Echinonix (Event)', booster=None), + 'Echinofulgur': Enemy(name='Echinofulgur', area='beach', internal_name='beach.sea-star-shock', level=66, first_encounter_event_name='First Encounter: Echinofulgur (Event)', grind_event_name='Grind: Echinofulgur (Event)', booster=None), + 'Echinofluctus': Enemy(name='Echinofluctus', area='beach', internal_name='beach.sea-star-wave', level=66, first_encounter_event_name='First Encounter: Echinofluctus (Event)', grind_event_name='Grind: Echinofluctus (Event)', booster=None), + 'Salteric': Enemy(name='Salteric', area='beach', internal_name='beach.special.blob-salt', level=67, first_encounter_event_name='First Encounter: Salteric (Event)', grind_event_name='Grind: Salteric (Event)', booster=None), + 'Balooneer': Enemy(name='Balooneer', area='beach', internal_name='beach.fish', level=68, first_encounter_event_name='First Encounter: Balooneer (Event)', grind_event_name='Grind: Balooneer (Event)', booster=None), + "K'im": Enemy(name="K'im", area='beach', internal_name='beach.worm', level=70, first_encounter_event_name="First Encounter: K'im (Event)", grind_event_name="Grind: K'im (Event)", booster=None), + 'Trigenbu': Enemy(name='Trigenbu', area='beach', internal_name='beach.turtle-man', level=71, first_encounter_event_name='First Encounter: Trigenbu (Event)', grind_event_name='Grind: Trigenbu (Event)', booster=None), + 'Heat Crystalid': Enemy(name='Heat Crystalid', area='final-dng', internal_name='final.crystal-heat', level=71, first_encounter_event_name='First Encounter: Heat Crystalid (Event)', grind_event_name='Grind: Heat Crystalid (Event)', booster=None), + 'Cold Crystalid': Enemy(name='Cold Crystalid', area='final-dng', internal_name='final.crystal-cold', level=71, first_encounter_event_name='First Encounter: Cold Crystalid (Event)', grind_event_name='Grind: Cold Crystalid (Event)', booster=None), + 'Shock Crystalid': Enemy(name='Shock Crystalid', area='final-dng', internal_name='final.crystal-shock', level=71, first_encounter_event_name='First Encounter: Shock Crystalid (Event)', grind_event_name='Grind: Shock Crystalid (Event)', booster=None), + 'Wave Crystalid': Enemy(name='Wave Crystalid', area='final-dng', internal_name='final.crystal-wave', level=71, first_encounter_event_name='First Encounter: Wave Crystalid (Event)', grind_event_name='Grind: Wave Crystalid (Event)', booster=None), + 'Hummagnum': Enemy(name='Hummagnum', area='final-dng', internal_name='final.colibri', level=72, first_encounter_event_name='First Encounter: Hummagnum (Event)', grind_event_name='Grind: Hummagnum (Event)', booster=None), + 'Mizree': Enemy(name='Mizree', area='final-dng', internal_name='guest.firespirit', level=73, first_encounter_event_name='First Encounter: Mizree (Event)', grind_event_name='Grind: Mizree (Event)', booster=None), + 'Beearbot': Enemy(name='Beearbot', area='final-dng', internal_name='guest.honeybear', level=73, first_encounter_event_name='First Encounter: Beearbot (Event)', grind_event_name='Grind: Beearbot (Event)', booster=None), +} \ No newline at end of file diff --git a/worlds/crosscode/locations.py b/worlds/crosscode/locations.py index b5022cf7aaa9..fe5f2933da6f 100644 --- a/worlds/crosscode/locations.py +++ b/worlds/crosscode/locations.py @@ -1136,6 +1136,134 @@ LocationData(code=None, name='Trouble on the Highway (Event)', metadata={'quest': True, 'dlc': True}, access=AccessInfo(region={'linear': '23', 'open': 'open20'}, cond=[ItemCondition(item_name='Azure Archipelago Pass', amount=1)])), LocationData(code=None, name='Tremors of the Past (Event)', metadata={'quest': True, 'dlc': True}, access=AccessInfo(region={'linear': '23', 'open': 'open20'}, cond=[ItemCondition(item_name='Tremor Engine', amount=4), ItemCondition(item_name='Humming Razor', amount=1), ItemCondition(item_name='Shock', amount=1), RegionCondition(target_mode='open', region_name='open10.Right'), RegionCondition(target_mode='open', region_name='open16'), ItemCondition(item_name='Azure Archipelago Pass', amount=1)])), LocationData(code=None, name='Wetter Work (Event)', metadata={'quest': True, 'dlc': True}, access=AccessInfo(region={'linear': '23', 'open': 'open2'}, cond=[QuestCondition(quest_name='Wet Work'), ItemCondition(item_name='Wave', amount=1), ItemCondition(item_name='Azure Archipelago Pass', amount=1)])), + LocationData(code=None, name='First Encounter: Hedgehag (Event)', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name='Grind: Hedgehag (Event)', area='autumn-area', metadata={'combat': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name="First Encounter: Rockin' Hillkat (Event)", area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name="Grind: Rockin' Hillkat (Event)", area='autumn-area', metadata={'combat': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name='First Encounter: Mad Bovine (Event)', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name='Grind: Mad Bovine (Event)', area='autumn-area', metadata={'combat': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name='First Encounter: Old Hedgehag (Event)', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name='Grind: Old Hedgehag (Event)', area='autumn-area', metadata={'combat': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name="First Encounter: Flamin' Hillkat (Event)", area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name="Grind: Flamin' Hillkat (Event)", area='autumn-area', metadata={'combat': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name='First Encounter: Red Eyed Bovine (Event)', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name='Grind: Red Eyed Bovine (Event)', area='autumn-area', metadata={'combat': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name='First Encounter: Young Frobbit (Event)', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name='Grind: Young Frobbit (Event)', area='bergen-trails', metadata={'combat': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name='First Encounter: White Frobbit (Event)', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name='Grind: White Frobbit (Event)', area='bergen-trails', metadata={'combat': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name='First Encounter: Seafly (Event)', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name='Grind: Seafly (Event)', area='bergen-trails', metadata={'combat': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name='First Encounter: Pengpeng (Event)', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name='Grind: Pengpeng (Event)', area='bergen-trails', metadata={'combat': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name='First Encounter: Horny Goat (Event)', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name='Grind: Horny Goat (Event)', area='bergen-trails', metadata={'combat': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name='First Encounter: Karotto (Event)', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name='Grind: Karotto (Event)', area='bergen-trails', metadata={'combat': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name='First Encounter: Fleazer (Event)', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={})), + LocationData(code=None, name='Grind: Fleazer (Event)', area='cold-dng', metadata={'combat': True}, access=AccessInfo(region={})), + LocationData(code=None, name='First Encounter: Carritrich (Event)', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={})), + LocationData(code=None, name='Grind: Carritrich (Event)', area='cold-dng', metadata={'combat': True}, access=AccessInfo(region={})), + LocationData(code=None, name='First Encounter: Kamikatze (Event)', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={})), + LocationData(code=None, name='Grind: Kamikatze (Event)', area='cold-dng', metadata={'combat': True}, access=AccessInfo(region={})), + LocationData(code=None, name='First Encounter: Digmo (Event)', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={})), + LocationData(code=None, name='Grind: Digmo (Event)', area='cold-dng', metadata={'combat': True}, access=AccessInfo(region={})), + LocationData(code=None, name='First Encounter: Pinceron (Event)', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'open5'})), + LocationData(code=None, name='Grind: Pinceron (Event)', area='heat-area', metadata={'combat': True}, access=AccessInfo(region={'open': 'open5'})), + LocationData(code=None, name='First Encounter: Sharkster (Event)', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'open5'})), + LocationData(code=None, name='Grind: Sharkster (Event)', area='heat-area', metadata={'combat': True}, access=AccessInfo(region={'open': 'open5'})), + LocationData(code=None, name='First Encounter: Vulturbine (Event)', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'open5'})), + LocationData(code=None, name='Grind: Vulturbine (Event)', area='heat-area', metadata={'combat': True}, access=AccessInfo(region={'open': 'open5'})), + LocationData(code=None, name='First Encounter: Drillertoise (Event)', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'open5'})), + LocationData(code=None, name='Grind: Drillertoise (Event)', area='heat-area', metadata={'combat': True}, access=AccessInfo(region={'open': 'open5'})), + LocationData(code=None, name='First Encounter: Tim (Event)', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'open5'})), + LocationData(code=None, name='Grind: Tim (Event)', area='heat-area', metadata={'combat': True}, access=AccessInfo(region={'open': 'open5'})), + LocationData(code=None, name='First Encounter: Boss Pincer (Event)', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'open5'})), + LocationData(code=None, name='Grind: Boss Pincer (Event)', area='heat-area', metadata={'combat': True}, access=AccessInfo(region={'open': 'open5'})), + LocationData(code=None, name='First Encounter: Trijelly (Event)', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={})), + LocationData(code=None, name='Grind: Trijelly (Event)', area='heat-dng', metadata={'combat': True}, access=AccessInfo(region={})), + LocationData(code=None, name='First Encounter: Pada Moth (Event)', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={})), + LocationData(code=None, name='Grind: Pada Moth (Event)', area='heat-dng', metadata={'combat': True}, access=AccessInfo(region={})), + LocationData(code=None, name='First Encounter: Darth Moth (Event)', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={})), + LocationData(code=None, name='Grind: Darth Moth (Event)', area='heat-dng', metadata={'combat': True}, access=AccessInfo(region={})), + LocationData(code=None, name='First Encounter: Magmanizer (Event)', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={})), + LocationData(code=None, name='Grind: Magmanizer (Event)', area='heat-dng', metadata={'combat': True}, access=AccessInfo(region={})), + LocationData(code=None, name='First Encounter: Radical Hedgehag (Event)', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'open': 'open8'})), + LocationData(code=None, name='Grind: Radical Hedgehag (Event)', area='autumn-fall', metadata={'combat': True}, access=AccessInfo(region={'open': 'open8'})), + LocationData(code=None, name="First Encounter: Chillin' Hillkat (Event)", area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'open': 'open8'})), + LocationData(code=None, name="Grind: Chillin' Hillkat (Event)", area='autumn-fall', metadata={'combat': True}, access=AccessInfo(region={'open': 'open8'})), + LocationData(code=None, name='First Encounter: Fallfly (Event)', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'open': 'open8'})), + LocationData(code=None, name='Grind: Fallfly (Event)', area='autumn-fall', metadata={'combat': True}, access=AccessInfo(region={'open': 'open8'})), + LocationData(code=None, name='First Encounter: Ivory Bovine (Event)', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'open': 'open8'})), + LocationData(code=None, name='Grind: Ivory Bovine (Event)', area='autumn-fall', metadata={'combat': True}, access=AccessInfo(region={'open': 'open8'})), + LocationData(code=None, name='First Encounter: Neutral Virus (Event)', area='arid', metadata={'kill': True}, access=AccessInfo(region={'open': 'open16'})), + LocationData(code=None, name='Grind: Neutral Virus (Event)', area='arid', metadata={'combat': True}, access=AccessInfo(region={'open': 'open16'})), + LocationData(code=None, name='First Encounter: Heat Virus (Event)', area='arid', metadata={'kill': True}, access=AccessInfo(region={'open': 'open16'})), + LocationData(code=None, name='Grind: Heat Virus (Event)', area='arid', metadata={'combat': True}, access=AccessInfo(region={'open': 'open16'})), + LocationData(code=None, name='First Encounter: Cold Virus (Event)', area='arid', metadata={'kill': True}, access=AccessInfo(region={'open': 'open16'})), + LocationData(code=None, name='Grind: Cold Virus (Event)', area='arid', metadata={'combat': True}, access=AccessInfo(region={'open': 'open16'})), + LocationData(code=None, name='First Encounter: Argeby (Event)', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'open10'})), + LocationData(code=None, name='Grind: Argeby (Event)', area='jungle', metadata={'combat': True}, access=AccessInfo(region={'open': 'open10'})), + LocationData(code=None, name='First Encounter: Gelleric (Event)', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'open10'})), + LocationData(code=None, name='Grind: Gelleric (Event)', area='jungle', metadata={'combat': True}, access=AccessInfo(region={'open': 'open10'})), + LocationData(code=None, name='First Encounter: Papagun (Event)', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'open10'})), + LocationData(code=None, name='Grind: Papagun (Event)', area='jungle', metadata={'combat': True}, access=AccessInfo(region={'open': 'open10'})), + LocationData(code=None, name='First Encounter: Angler (Event)', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'open10.Grove'})), + LocationData(code=None, name='Grind: Angler (Event)', area='jungle', metadata={'combat': True}, access=AccessInfo(region={'open': 'open10.Grove'})), + LocationData(code=None, name='First Encounter: Shokat (Event)', area='jungle', metadata={'kill': True}, access=AccessInfo(region={})), + LocationData(code=None, name='Grind: Shokat (Event)', area='jungle', metadata={'combat': True}, access=AccessInfo(region={})), + LocationData(code=None, name='First Encounter: Behesloth (Event)', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'open10.Infested'})), + LocationData(code=None, name='Grind: Behesloth (Event)', area='jungle', metadata={'combat': True}, access=AccessInfo(region={'open': 'open10.Infested'})), + LocationData(code=None, name='First Encounter: Jelleric (Event)', area='wave-dng', metadata={'kill': True}, access=AccessInfo(region={})), + LocationData(code=None, name='Grind: Jelleric (Event)', area='wave-dng', metadata={'combat': True}, access=AccessInfo(region={})), + LocationData(code=None, name='First Encounter: Ocubepus (Event)', area='wave-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open14.1'})), + LocationData(code=None, name='Grind: Ocubepus (Event)', area='wave-dng', metadata={'combat': True}, access=AccessInfo(region={'open': 'open14.1'})), + LocationData(code=None, name='First Encounter: Blue Ray (Event)', area='wave-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open14.1'})), + LocationData(code=None, name='Grind: Blue Ray (Event)', area='wave-dng', metadata={'combat': True}, access=AccessInfo(region={'open': 'open14.1'})), + LocationData(code=None, name='First Encounter: Rob0ck (Event)', area='shock-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open10.Right'})), + LocationData(code=None, name='Grind: Rob0ck (Event)', area='shock-dng', metadata={'combat': True}, access=AccessInfo(region={'open': 'open10.Right'})), + LocationData(code=None, name='First Encounter: Powerplant (Event)', area='shock-dng', metadata={'kill': True}, access=AccessInfo(region={})), + LocationData(code=None, name='Grind: Powerplant (Event)', area='shock-dng', metadata={'combat': True}, access=AccessInfo(region={})), + LocationData(code=None, name='First Encounter: Ectovolt (Event)', area='shock-dng', metadata={'kill': True}, access=AccessInfo(region={})), + LocationData(code=None, name='Grind: Ectovolt (Event)', area='shock-dng', metadata={'combat': True}, access=AccessInfo(region={})), + LocationData(code=None, name='First Encounter: Sun Beetle (Event)', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'open16'})), + LocationData(code=None, name='Grind: Sun Beetle (Event)', area='forest', metadata={'combat': True}, access=AccessInfo(region={'open': 'open16'})), + LocationData(code=None, name='First Encounter: Moon Beetle (Event)', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'open16'})), + LocationData(code=None, name='Grind: Moon Beetle (Event)', area='forest', metadata={'combat': True}, access=AccessInfo(region={'open': 'open16'})), + LocationData(code=None, name='First Encounter: Pandza (Event)', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'open16'})), + LocationData(code=None, name='Grind: Pandza (Event)', area='forest', metadata={'combat': True}, access=AccessInfo(region={'open': 'open16'})), + LocationData(code=None, name='First Encounter: Aranetarda (Event)', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'open16'})), + LocationData(code=None, name='Grind: Aranetarda (Event)', area='forest', metadata={'combat': True}, access=AccessInfo(region={'open': 'open16'})), + LocationData(code=None, name='First Encounter: Echinoignis (Event)', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), + LocationData(code=None, name='Grind: Echinoignis (Event)', area='beach', metadata={'dlc': True, 'combat': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), + LocationData(code=None, name='First Encounter: Echinonix (Event)', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), + LocationData(code=None, name='Grind: Echinonix (Event)', area='beach', metadata={'dlc': True, 'combat': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), + LocationData(code=None, name='First Encounter: Echinofulgur (Event)', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), + LocationData(code=None, name='Grind: Echinofulgur (Event)', area='beach', metadata={'dlc': True, 'combat': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), + LocationData(code=None, name='First Encounter: Echinofluctus (Event)', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), + LocationData(code=None, name='Grind: Echinofluctus (Event)', area='beach', metadata={'dlc': True, 'combat': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), + LocationData(code=None, name='First Encounter: Salteric (Event)', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), + LocationData(code=None, name='Grind: Salteric (Event)', area='beach', metadata={'dlc': True, 'combat': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), + LocationData(code=None, name='First Encounter: Balooneer (Event)', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), + LocationData(code=None, name='Grind: Balooneer (Event)', area='beach', metadata={'dlc': True, 'combat': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), + LocationData(code=None, name="First Encounter: K'im (Event)", area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), + LocationData(code=None, name="Grind: K'im (Event)", area='beach', metadata={'dlc': True, 'combat': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), + LocationData(code=None, name='First Encounter: Trigenbu (Event)', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), + LocationData(code=None, name='Grind: Trigenbu (Event)', area='beach', metadata={'dlc': True, 'combat': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), + LocationData(code=None, name='First Encounter: Heat Crystalid (Event)', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_DungeonEntry'})), + LocationData(code=None, name='Grind: Heat Crystalid (Event)', area='final-dng', metadata={'dlc': True, 'combat': True}, access=AccessInfo(region={'open': 'openDLC_DungeonEntry'})), + LocationData(code=None, name='First Encounter: Cold Crystalid (Event)', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_DungeonEntry'})), + LocationData(code=None, name='Grind: Cold Crystalid (Event)', area='final-dng', metadata={'dlc': True, 'combat': True}, access=AccessInfo(region={'open': 'openDLC_DungeonEntry'})), + LocationData(code=None, name='First Encounter: Shock Crystalid (Event)', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_DungeonEntry'})), + LocationData(code=None, name='Grind: Shock Crystalid (Event)', area='final-dng', metadata={'dlc': True, 'combat': True}, access=AccessInfo(region={'open': 'openDLC_DungeonEntry'})), + LocationData(code=None, name='First Encounter: Wave Crystalid (Event)', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_DungeonEntry'})), + LocationData(code=None, name='Grind: Wave Crystalid (Event)', area='final-dng', metadata={'dlc': True, 'combat': True}, access=AccessInfo(region={'open': 'openDLC_DungeonEntry'})), + LocationData(code=None, name='First Encounter: Hummagnum (Event)', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_DungeonEntry'})), + LocationData(code=None, name='Grind: Hummagnum (Event)', area='final-dng', metadata={'dlc': True, 'combat': True}, access=AccessInfo(region={'open': 'openDLC_DungeonEntry'})), + LocationData(code=None, name='First Encounter: Mizree (Event)', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_DungeonEntry'})), + LocationData(code=None, name='Grind: Mizree (Event)', area='final-dng', metadata={'dlc': True, 'combat': True}, access=AccessInfo(region={'open': 'openDLC_DungeonEntry'})), + LocationData(code=None, name='First Encounter: Beearbot (Event)', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_DungeonEntry'})), + LocationData(code=None, name='Grind: Beearbot (Event)', area='final-dng', metadata={'dlc': True, 'combat': True}, access=AccessInfo(region={'open': 'openDLC_DungeonEntry'})), ] events_dict = { location.name: location for location in events_data } diff --git a/worlds/crosscode/templates/enemies.template.py b/worlds/crosscode/templates/enemies.template.py new file mode 100644 index 000000000000..2930b395e46c --- /dev/null +++ b/worlds/crosscode/templates/enemies.template.py @@ -0,0 +1,6 @@ +{{generated_comment | indent("# ", True)}} + +from .types.condition import * +from .types.enemies import Enemy + +enemies: dict[str, Enemy] = {{ enemies | emit_dict("constant", "dataclass") }} diff --git a/worlds/crosscode/types/enemies.py b/worlds/crosscode/types/enemies.py index 9aa0f1e7d918..5b42ff7f35b7 100644 --- a/worlds/crosscode/types/enemies.py +++ b/worlds/crosscode/types/enemies.py @@ -20,9 +20,9 @@ class Enemy: """The enemy's name in the game files""" level: int """The enemy's base level in vanilla""" - first_encounter_event: LocationData + first_encounter_event_name: str """The event that unlocks whether you can fight one instance of the enemy (for killsanity)""" - grind_access_event: LocationData | None = field(default=None) + grind_event_name: str | None = field(default=None) """The event that unlocks whether you can grind the enemy -- if null, enemy cannot be grinded""" booster: Booster | None = field(default=None) """If the enemy can be boosted, the details about that""" diff --git a/worlds/crosscode/types/metadata.py b/worlds/crosscode/types/metadata.py index 387d77ffdcfd..67c8a0fde833 100644 --- a/worlds/crosscode/types/metadata.py +++ b/worlds/crosscode/types/metadata.py @@ -8,3 +8,5 @@ class IncludeOptions(TypedDict, total=False): chest: bool quest: bool botanics: bool + combat: bool + kill: bool From 90e7bd637aac0f981776b92c4688b6929b2b1a78 Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Fri, 3 Jul 2026 21:32:17 -0600 Subject: [PATCH 10/23] fix enemy event generation --- worlds/crosscode/codegen/lists.py | 4 +- worlds/crosscode/enemies.py | 37 +++++++++++++ worlds/crosscode/locations.py | 91 ++++++++++++++++++++++--------- worlds/crosscode/regions.py | 2 + 4 files changed, 105 insertions(+), 29 deletions(-) diff --git a/worlds/crosscode/codegen/lists.py b/worlds/crosscode/codegen/lists.py index 5eb4f4acc32b..11612f48d610 100644 --- a/worlds/crosscode/codegen/lists.py +++ b/worlds/crosscode/codegen/lists.py @@ -560,9 +560,9 @@ def __add_enemy(self, raw: dict[str, typing.Any]): except KeyError: raise JsonParserError(raw, raw, "", f"Enemy specification lacks an essential parameter: {raw}") - try: + if "region" in raw: first_encounter_access = grind_access = self.json_parser.parse_location_access_info(raw) - except JsonParserError: + else: if "firstEncounter" in raw: first_encounter_access = self.json_parser.parse_location_access_info(raw["firstEncounter"]) else: diff --git a/worlds/crosscode/enemies.py b/worlds/crosscode/enemies.py index 850474273005..1c21ec44021d 100644 --- a/worlds/crosscode/enemies.py +++ b/worlds/crosscode/enemies.py @@ -56,6 +56,32 @@ 'Moon Beetle': Enemy(name='Moon Beetle', area='forest', internal_name='forest.bug-samurai-shock', level=51, first_encounter_event_name='First Encounter: Moon Beetle (Event)', grind_event_name='Grind: Moon Beetle (Event)', booster=None), 'Pandza': Enemy(name='Pandza', area='forest', internal_name='forest.panda', level=51, first_encounter_event_name='First Encounter: Pandza (Event)', grind_event_name='Grind: Pandza (Event)', booster=None), 'Aranetarda': Enemy(name='Aranetarda', area='forest', internal_name='forest.spider', level=52, first_encounter_event_name='First Encounter: Aranetarda (Event)', grind_event_name='Grind: Aranetarda (Event)', booster=None), + 'Hillkat Bandleader': Enemy(name='Hillkat Bandleader', area='autumn-area', internal_name='meerkat-special-command-1', level=13, first_encounter_event_name='First Encounter: Hillkat Bandleader (Event)', grind_event_name=None, booster=None), + 'Blue Hedgehag': Enemy(name='Blue Hedgehag', area='autumn-area', internal_name='minibosses.blue-hedge', level=15, first_encounter_event_name='First Encounter: Blue Hedgehag (Event)', grind_event_name=None, booster=None), + 'Infected Digmo': Enemy(name='Infected Digmo', area='cold-dng', internal_name='mine-diggingbot-cold', level=19, first_encounter_event_name='First Encounter: Infected Digmo (Event)', grind_event_name=None, booster=None), + 'Peng King Dakara': Enemy(name='Peng King Dakara', area='bergen-trails', internal_name='minibosses.penguin-rapper', level=21, first_encounter_event_name='First Encounter: Peng King Dakara (Event)', grind_event_name=None, booster=None), + 'X01 Driller H.F.S.': Enemy(name='X01 Driller H.F.S.', area='cold-dng', internal_name='boss-driller', level=21, first_encounter_event_name='First Encounter: X01 Driller H.F.S. (Event)', grind_event_name=None, booster=None), + "Ti'im": Enemy(name="Ti'im", area='heat-area', internal_name='heat.sandworm-boss', level=26, first_encounter_event_name="First Encounter: Ti'im (Event)", grind_event_name=None, booster=None), + 'Cursed Sharkster': Enemy(name='Cursed Sharkster', area='heat-area', internal_name='minibosses.cursed-sandshark', level=30, first_encounter_event_name='First Encounter: Cursed Sharkster (Event)', grind_event_name=None, booster=None), + "Pinzo'jrahrrrn": Enemy(name="Pinzo'jrahrrrn", area='heat-dng', internal_name='heat.antlion', level=28, first_encounter_event_name="First Encounter: Pinzo'jrahrrrn (Event)", grind_event_name=None, booster=None), + 'Master Magmoth': Enemy(name='Master Magmoth', area='heat-dng', internal_name='heat.megamoth', level=30, first_encounter_event_name='First Encounter: Master Magmoth (Event)', grind_event_name=None, booster=None), + 'Guard Billston': Enemy(name='Guard Billston', area='heat-area', internal_name='heat.special.guard-hostile-mustache', level=33, first_encounter_event_name='First Encounter: Guard Billston (Event)', grind_event_name=None, booster=None), + 'Hologram Frobbit': Enemy(name='Hologram Frobbit', area='autumn-fall', internal_name='daft-frobbit', level=36, first_encounter_event_name='First Encounter: Hologram Frobbit (Event)', grind_event_name=None, booster=None), + 'Smelter Digmo': Enemy(name='Smelter Digmo', area='cold-dng', internal_name='cold.mine-diggingbot-quest', level=36, first_encounter_event_name='First Encounter: Smelter Digmo (Event)', grind_event_name=None, booster=None), + 'Blazehoof': Enemy(name='Blazehoof', area='autumn-fall', internal_name='autumn-fall.buffalo-fire-quest', level=37, first_encounter_event_name='First Encounter: Blazehoof (Event)', grind_event_name=None, booster=None), + 'Plasma Phantom': Enemy(name='Plasma Phantom', area='shock-dng', internal_name='jungle.shockboss', level=44, first_encounter_event_name='First Encounter: Plasma Phantom (Event)', grind_event_name=None, booster=None), + 'Sir Blobus Starnikus': Enemy(name='Sir Blobus Starnikus', area='wave-dng', internal_name='jungle.waveboss', level=44, first_encounter_event_name='First Encounter: Sir Blobus Starnikus (Event)', grind_event_name=None, booster=None), + 'Tiefsee Angler': Enemy(name='Tiefsee Angler', area='jungle', internal_name='minibosses.deep-fish', level=46, first_encounter_event_name='First Encounter: Tiefsee Angler (Event)', grind_event_name=None, booster=None), + 'Son of the East': Enemy(name='Son of the East', area='tree-dng', internal_name='jungle.ape-boss', level=46, first_encounter_event_name='First Encounter: Son of the East (Event)', grind_event_name=None, booster=None), + 'Ancient Guardian': Enemy(name='Ancient Guardian', area='tree-dng', internal_name='jungle.whale-boss', level=46, first_encounter_event_name='First Encounter: Ancient Guardian (Event)', grind_event_name=None, booster=None), + 'Karotto Fruitseeker': Enemy(name='Karotto Fruitseeker', area='jungle', internal_name='jungle.special.snowman-jungle-boss', level=47, first_encounter_event_name='First Encounter: Karotto Fruitseeker (Event)', grind_event_name=None, booster=None), + 'Buff Bloomy': Enemy(name='Buff Bloomy', area='jungle', internal_name='jungle.special.powerplant-quest-1', level=47, first_encounter_event_name='First Encounter: Buff Bloomy (Event)', grind_event_name=None, booster=None), + 'Twilight Master': Enemy(name='Twilight Master', area='forest', internal_name='forest.samurai-boss', level=51, first_encounter_event_name='First Encounter: Twilight Master (Event)', grind_event_name=None, booster=None), + 'King Kaktorro': Enemy(name='King Kaktorro', area='heat-area', internal_name='heat.special.sandman-1', level=57, first_encounter_event_name='First Encounter: King Kaktorro (Event)', grind_event_name=None, booster=None), + "DON'T USE THIS": Enemy(name="DON'T USE THIS", area='heat-area', internal_name='guest.glitch-boss', level=58, first_encounter_event_name="First Encounter: DON'T USE THIS (Event)", grind_event_name=None, booster=None), + 'Designer': Enemy(name='Designer', area='arid', internal_name='boss.designer-2', level=60, first_encounter_event_name='First Encounter: Designer (Event)', grind_event_name=None, booster=None), + 'The Creator': Enemy(name='The Creator', area='arid-dng-2', internal_name='boss.elephant', level=60, first_encounter_event_name='First Encounter: The Creator (Event)', grind_event_name=None, booster=None), + 'Pandza Mk. II': Enemy(name='Pandza Mk. II', area='forest', internal_name='minibosses.panda-boss', level=62, first_encounter_event_name='First Encounter: Pandza Mk. II (Event)', grind_event_name=None, booster=None), 'Echinoignis': Enemy(name='Echinoignis', area='beach', internal_name='beach.sea-star-heat', level=66, first_encounter_event_name='First Encounter: Echinoignis (Event)', grind_event_name='Grind: Echinoignis (Event)', booster=None), 'Echinonix': Enemy(name='Echinonix', area='beach', internal_name='beach.sea-star-cold', level=66, first_encounter_event_name='First Encounter: Echinonix (Event)', grind_event_name='Grind: Echinonix (Event)', booster=None), 'Echinofulgur': Enemy(name='Echinofulgur', area='beach', internal_name='beach.sea-star-shock', level=66, first_encounter_event_name='First Encounter: Echinofulgur (Event)', grind_event_name='Grind: Echinofulgur (Event)', booster=None), @@ -71,4 +97,15 @@ 'Hummagnum': Enemy(name='Hummagnum', area='final-dng', internal_name='final.colibri', level=72, first_encounter_event_name='First Encounter: Hummagnum (Event)', grind_event_name='Grind: Hummagnum (Event)', booster=None), 'Mizree': Enemy(name='Mizree', area='final-dng', internal_name='guest.firespirit', level=73, first_encounter_event_name='First Encounter: Mizree (Event)', grind_event_name='Grind: Mizree (Event)', booster=None), 'Beearbot': Enemy(name='Beearbot', area='final-dng', internal_name='guest.honeybear', level=73, first_encounter_event_name='First Encounter: Beearbot (Event)', grind_event_name='Grind: Beearbot (Event)', booster=None), + 'Illegal Coordinator': Enemy(name='Illegal Coordinator', area='autumn-area', internal_name='autumn-rh.turret_boss-quest_naval', level=63, first_encounter_event_name='First Encounter: Illegal Coordinator (Event)', grind_event_name=None, booster=None), + 'Tremmy': Enemy(name='Tremmy', area='rhombus-sqr', internal_name='autumn-fall.runbot-tremor', level=67, first_encounter_event_name='First Encounter: Tremmy (Event)', grind_event_name=None, booster=None), + 'Distillizer': Enemy(name='Distillizer', area='heat-village', internal_name='heat.special.heat-golem-booze', level=67, first_encounter_event_name='First Encounter: Distillizer (Event)', grind_event_name=None, booster=None), + 'Toxovolt': Enemy(name='Toxovolt', area='jungle', internal_name='jungle.special.ghost-toxic', level=68, first_encounter_event_name='First Encounter: Toxovolt (Event)', grind_event_name=None, booster=None), + 'Papaboss the Younger': Enemy(name='Papaboss the Younger', area='jungle-city', internal_name='jungle.special.parrot-gangster-boss-1', level=69, first_encounter_event_name='First Encounter: Papaboss the Younger (Event)', grind_event_name=None, booster=None), + 'Hillcart': Enemy(name='Hillcart', area='rhombus-sqr', internal_name='rhombus.meerkat-delorean', level=72, first_encounter_event_name='First Encounter: Hillcart (Event)', grind_event_name=None, booster=None), + 'The Goatfather': Enemy(name='The Goatfather', area='rhombus-sqr', internal_name='cold.goat-father-2', level=72, first_encounter_event_name='First Encounter: The Goatfather (Event)', grind_event_name=None, booster=None), + 'Guardian Statue': Enemy(name='Guardian Statue', area='final-dng', internal_name='final.guardian', level=74, first_encounter_event_name='First Encounter: Guardian Statue (Event)', grind_event_name=None, booster=None), + 'Gynthar': Enemy(name='Gynthar', area='final-dng', internal_name='final.gynthar', level=75, first_encounter_event_name='First Encounter: Gynthar (Event)', grind_event_name=None, booster=None), + "Di'orbis": Enemy(name="Di'orbis", area='final-dng', internal_name='final.god-neutral', level=77, first_encounter_event_name="First Encounter: Di'orbis (Event)", grind_event_name=None, booster=None), + 'Son of the Beach': Enemy(name='Son of the Beach', area='beach', internal_name='beach.ape-beach', level=79, first_encounter_event_name='First Encounter: Son of the Beach (Event)', grind_event_name=None, booster=None), } \ No newline at end of file diff --git a/worlds/crosscode/locations.py b/worlds/crosscode/locations.py index fe5f2933da6f..48ebdb365b2e 100644 --- a/worlds/crosscode/locations.py +++ b/worlds/crosscode/locations.py @@ -181,9 +181,9 @@ LocationData(code=3235824172, name='Ridge: Baton Pond', area='forest', access=AccessInfo(region={'linear': '31', 'open': 'open16'}, cond=[ChestKeyCondition(default_level='Bronze')])), LocationData(code=3235824173, name='Maroon: Mystery Cave Lower', area='heat-area', access=AccessInfo(region={'linear': '11', 'open': 'open5'}, cond=[ChestKeyCondition(default_level='Gold')])), LocationData(code=3235824174, name='Maroon: Mystery Cave Upper', area='heat-area', access=AccessInfo(region={'linear': '11', 'open': 'open5'}, cond=[ChestKeyCondition(default_level='Silver')])), - LocationData(code=3235824175, name='Maroon: Cursed Temple Upper', area='heat-area', access=AccessInfo(region={'linear': '11', 'open': 'open5'}, cond=[ItemCondition(item_name='Heat', amount=1), ItemCondition(item_name='Cold', amount=1), ItemCondition(item_name='Cursed Coin', amount=1), ChestKeyCondition(default_level='Silver')])), - LocationData(code=3235824176, name='Maroon: Cursed Temple Lower', area='heat-area', access=AccessInfo(region={'linear': '11', 'open': 'open5'}, cond=[ItemCondition(item_name='Heat', amount=1), ItemCondition(item_name='Cold', amount=1), ItemCondition(item_name='Cursed Coin', amount=1), ChestKeyCondition(default_level='Silver')])), - LocationData(code=3235824177, name='Maroon: Cursed Temple Treasure Room', area='heat-area', access=AccessInfo(region={'linear': '11', 'open': 'open5'}, cond=[ItemCondition(item_name='Heat', amount=1), ItemCondition(item_name='Cold', amount=1), ItemCondition(item_name='Cursed Coin', amount=1), ChestKeyCondition(default_level='Bronze')])), + LocationData(code=3235824175, name='Maroon: Cursed Temple Upper', area='heat-area', access=AccessInfo(region={'linear': '11', 'open': 'openCursedTemple'}, cond=[ChestKeyCondition(default_level='Silver')])), + LocationData(code=3235824176, name='Maroon: Cursed Temple Lower', area='heat-area', access=AccessInfo(region={'linear': '11', 'open': 'openCursedTemple'}, cond=[ChestKeyCondition(default_level='Silver')])), + LocationData(code=3235824177, name='Maroon: Cursed Temple Treasure Room', area='heat-area', access=AccessInfo(region={'linear': '11', 'open': 'openCursedTemple'}, cond=[ChestKeyCondition(default_level='Bronze')])), LocationData(code=3235824178, name='Maroon: Maroon Cave 1', area='heat-area', access=AccessInfo(region={'linear': '12', 'open': 'open6'}, cond=[ItemCondition(item_name='Heat', amount=1), ChestKeyCondition(default_level='Default')])), LocationData(code=3235824179, name='Maroon: River Cliff Right', area='heat-area', access=AccessInfo(region={'linear': '11', 'open': 'open5'}, cond=[ChestKeyCondition(default_level='Default')])), LocationData(code=3235824180, name='Maroon: River Cliff Left', area='heat-area', access=AccessInfo(region={'linear': '11', 'open': 'open5'}, cond=[ChestKeyCondition(default_level='Default')])), @@ -1160,14 +1160,14 @@ LocationData(code=None, name='Grind: Horny Goat (Event)', area='bergen-trails', metadata={'combat': True}, access=AccessInfo(region={'open': 'open3'})), LocationData(code=None, name='First Encounter: Karotto (Event)', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'open3'})), LocationData(code=None, name='Grind: Karotto (Event)', area='bergen-trails', metadata={'combat': True}, access=AccessInfo(region={'open': 'open3'})), - LocationData(code=None, name='First Encounter: Fleazer (Event)', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={})), - LocationData(code=None, name='Grind: Fleazer (Event)', area='cold-dng', metadata={'combat': True}, access=AccessInfo(region={})), - LocationData(code=None, name='First Encounter: Carritrich (Event)', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={})), - LocationData(code=None, name='Grind: Carritrich (Event)', area='cold-dng', metadata={'combat': True}, access=AccessInfo(region={})), - LocationData(code=None, name='First Encounter: Kamikatze (Event)', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={})), - LocationData(code=None, name='Grind: Kamikatze (Event)', area='cold-dng', metadata={'combat': True}, access=AccessInfo(region={})), - LocationData(code=None, name='First Encounter: Digmo (Event)', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={})), - LocationData(code=None, name='Grind: Digmo (Event)', area='cold-dng', metadata={'combat': True}, access=AccessInfo(region={})), + LocationData(code=None, name='First Encounter: Fleazer (Event)', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open4.2'})), + LocationData(code=None, name='Grind: Fleazer (Event)', area='cold-dng', metadata={'combat': True}, access=AccessInfo(region={'open': 'open4.4'})), + LocationData(code=None, name='First Encounter: Carritrich (Event)', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open4.2'})), + LocationData(code=None, name='Grind: Carritrich (Event)', area='cold-dng', metadata={'combat': True}, access=AccessInfo(region={'open': 'open4.4'})), + LocationData(code=None, name='First Encounter: Kamikatze (Event)', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open4.2'})), + LocationData(code=None, name='Grind: Kamikatze (Event)', area='cold-dng', metadata={'combat': True}, access=AccessInfo(region={'open': 'open4.4'})), + LocationData(code=None, name='First Encounter: Digmo (Event)', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open4.4'})), + LocationData(code=None, name='Grind: Digmo (Event)', area='cold-dng', metadata={'combat': True}, access=AccessInfo(region={'open': 'open4.6'})), LocationData(code=None, name='First Encounter: Pinceron (Event)', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'open5'})), LocationData(code=None, name='Grind: Pinceron (Event)', area='heat-area', metadata={'combat': True}, access=AccessInfo(region={'open': 'open5'})), LocationData(code=None, name='First Encounter: Sharkster (Event)', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'open5'})), @@ -1180,14 +1180,14 @@ LocationData(code=None, name='Grind: Tim (Event)', area='heat-area', metadata={'combat': True}, access=AccessInfo(region={'open': 'open5'})), LocationData(code=None, name='First Encounter: Boss Pincer (Event)', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'open5'})), LocationData(code=None, name='Grind: Boss Pincer (Event)', area='heat-area', metadata={'combat': True}, access=AccessInfo(region={'open': 'open5'})), - LocationData(code=None, name='First Encounter: Trijelly (Event)', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={})), - LocationData(code=None, name='Grind: Trijelly (Event)', area='heat-dng', metadata={'combat': True}, access=AccessInfo(region={})), - LocationData(code=None, name='First Encounter: Pada Moth (Event)', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={})), - LocationData(code=None, name='Grind: Pada Moth (Event)', area='heat-dng', metadata={'combat': True}, access=AccessInfo(region={})), - LocationData(code=None, name='First Encounter: Darth Moth (Event)', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={})), - LocationData(code=None, name='Grind: Darth Moth (Event)', area='heat-dng', metadata={'combat': True}, access=AccessInfo(region={})), - LocationData(code=None, name='First Encounter: Magmanizer (Event)', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={})), - LocationData(code=None, name='Grind: Magmanizer (Event)', area='heat-dng', metadata={'combat': True}, access=AccessInfo(region={})), + LocationData(code=None, name='First Encounter: Trijelly (Event)', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open7.2'})), + LocationData(code=None, name='Grind: Trijelly (Event)', area='heat-dng', metadata={'combat': True}, access=AccessInfo(region={'open': 'open7.6'})), + LocationData(code=None, name='First Encounter: Pada Moth (Event)', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open7.2'})), + LocationData(code=None, name='Grind: Pada Moth (Event)', area='heat-dng', metadata={'combat': True}, access=AccessInfo(region={'open': 'open7.6'})), + LocationData(code=None, name='First Encounter: Darth Moth (Event)', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open7.6'})), + LocationData(code=None, name='Grind: Darth Moth (Event)', area='heat-dng', metadata={'combat': True}, access=AccessInfo(region={'open': 'open7.7'})), + LocationData(code=None, name='First Encounter: Magmanizer (Event)', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open7.5'})), + LocationData(code=None, name='Grind: Magmanizer (Event)', area='heat-dng', metadata={'combat': True}, access=AccessInfo(region={'open': 'open7.6'})), LocationData(code=None, name='First Encounter: Radical Hedgehag (Event)', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'open': 'open8'})), LocationData(code=None, name='Grind: Radical Hedgehag (Event)', area='autumn-fall', metadata={'combat': True}, access=AccessInfo(region={'open': 'open8'})), LocationData(code=None, name="First Encounter: Chillin' Hillkat (Event)", area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'open': 'open8'})), @@ -1210,22 +1210,22 @@ LocationData(code=None, name='Grind: Papagun (Event)', area='jungle', metadata={'combat': True}, access=AccessInfo(region={'open': 'open10'})), LocationData(code=None, name='First Encounter: Angler (Event)', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'open10.Grove'})), LocationData(code=None, name='Grind: Angler (Event)', area='jungle', metadata={'combat': True}, access=AccessInfo(region={'open': 'open10.Grove'})), - LocationData(code=None, name='First Encounter: Shokat (Event)', area='jungle', metadata={'kill': True}, access=AccessInfo(region={})), - LocationData(code=None, name='Grind: Shokat (Event)', area='jungle', metadata={'combat': True}, access=AccessInfo(region={})), + LocationData(code=None, name='First Encounter: Shokat (Event)', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'open10'})), + LocationData(code=None, name='Grind: Shokat (Event)', area='jungle', metadata={'combat': True}, access=AccessInfo(region={'open': 'open10.Mid'})), LocationData(code=None, name='First Encounter: Behesloth (Event)', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'open10.Infested'})), LocationData(code=None, name='Grind: Behesloth (Event)', area='jungle', metadata={'combat': True}, access=AccessInfo(region={'open': 'open10.Infested'})), - LocationData(code=None, name='First Encounter: Jelleric (Event)', area='wave-dng', metadata={'kill': True}, access=AccessInfo(region={})), - LocationData(code=None, name='Grind: Jelleric (Event)', area='wave-dng', metadata={'combat': True}, access=AccessInfo(region={})), + LocationData(code=None, name='First Encounter: Jelleric (Event)', area='wave-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open10.Left'})), + LocationData(code=None, name='Grind: Jelleric (Event)', area='wave-dng', metadata={'combat': True}, access=AccessInfo(region={'open': 'open14.1'})), LocationData(code=None, name='First Encounter: Ocubepus (Event)', area='wave-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open14.1'})), LocationData(code=None, name='Grind: Ocubepus (Event)', area='wave-dng', metadata={'combat': True}, access=AccessInfo(region={'open': 'open14.1'})), LocationData(code=None, name='First Encounter: Blue Ray (Event)', area='wave-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open14.1'})), LocationData(code=None, name='Grind: Blue Ray (Event)', area='wave-dng', metadata={'combat': True}, access=AccessInfo(region={'open': 'open14.1'})), LocationData(code=None, name='First Encounter: Rob0ck (Event)', area='shock-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open10.Right'})), LocationData(code=None, name='Grind: Rob0ck (Event)', area='shock-dng', metadata={'combat': True}, access=AccessInfo(region={'open': 'open10.Right'})), - LocationData(code=None, name='First Encounter: Powerplant (Event)', area='shock-dng', metadata={'kill': True}, access=AccessInfo(region={})), - LocationData(code=None, name='Grind: Powerplant (Event)', area='shock-dng', metadata={'combat': True}, access=AccessInfo(region={})), - LocationData(code=None, name='First Encounter: Ectovolt (Event)', area='shock-dng', metadata={'kill': True}, access=AccessInfo(region={})), - LocationData(code=None, name='Grind: Ectovolt (Event)', area='shock-dng', metadata={'combat': True}, access=AccessInfo(region={})), + LocationData(code=None, name='First Encounter: Powerplant (Event)', area='shock-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open10.Right'})), + LocationData(code=None, name='Grind: Powerplant (Event)', area='shock-dng', metadata={'combat': True}, access=AccessInfo(region={'open': 'open13.1'})), + LocationData(code=None, name='First Encounter: Ectovolt (Event)', area='shock-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open10.Right'})), + LocationData(code=None, name='Grind: Ectovolt (Event)', area='shock-dng', metadata={'combat': True}, access=AccessInfo(region={'open': 'open13.1'})), LocationData(code=None, name='First Encounter: Sun Beetle (Event)', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'open16'})), LocationData(code=None, name='Grind: Sun Beetle (Event)', area='forest', metadata={'combat': True}, access=AccessInfo(region={'open': 'open16'})), LocationData(code=None, name='First Encounter: Moon Beetle (Event)', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'open16'})), @@ -1234,6 +1234,32 @@ LocationData(code=None, name='Grind: Pandza (Event)', area='forest', metadata={'combat': True}, access=AccessInfo(region={'open': 'open16'})), LocationData(code=None, name='First Encounter: Aranetarda (Event)', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'open16'})), LocationData(code=None, name='Grind: Aranetarda (Event)', area='forest', metadata={'combat': True}, access=AccessInfo(region={'open': 'open16'})), + LocationData(code=None, name='First Encounter: Hillkat Bandleader (Event)', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'open3'}, cond=[QuestCondition(quest_name='Digging for Data')])), + LocationData(code=None, name='First Encounter: Blue Hedgehag (Event)', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'open3'})), + LocationData(code=None, name='First Encounter: Infected Digmo (Event)', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open4.5'})), + LocationData(code=None, name='First Encounter: Peng King Dakara (Event)', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'open3'}, cond=[ItemCondition(item_name='Heat', amount=1)])), + LocationData(code=None, name='First Encounter: X01 Driller H.F.S. (Event)', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open4.8'})), + LocationData(code=None, name="First Encounter: Ti'im (Event)", area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'open6'})), + LocationData(code=None, name='First Encounter: Cursed Sharkster (Event)', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'openCursedTemple'})), + LocationData(code=None, name="First Encounter: Pinzo'jrahrrrn (Event)", area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open7.1'})), + LocationData(code=None, name='First Encounter: Master Magmoth (Event)', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open7.8'})), + LocationData(code=None, name='First Encounter: Guard Billston (Event)', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'open5'}, cond=[QuestCondition(quest_name='Shady Theft'), ItemCondition(item_name='Red Flame Shade', amount=1), ItemCondition(item_name='Heat', amount=1), ItemCondition(item_name='Cold', amount=1)])), + LocationData(code=None, name='First Encounter: Hologram Frobbit (Event)', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'linear': '20', 'open': 'open9'}, cond=[ItemCondition(item_name='Heat', amount=1), ItemCondition(item_name='Cold', amount=1)])), + LocationData(code=None, name='First Encounter: Smelter Digmo (Event)', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'linear': '20', 'open': 'open9'}, cond=[ItemCondition(item_name='Red Flame Shade', amount=1), ItemCondition(item_name='Heat', amount=1), ItemCondition(item_name='Cold', amount=1), RegionCondition(target_mode='open', region_name='open4.5'), QuestCondition(quest_name='Bull Grab')])), + LocationData(code=None, name='First Encounter: Blazehoof (Event)', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'linear': '20', 'open': 'open9'}, cond=[QuestCondition(quest_name='Intensive Tree Care'), ItemCondition(item_name='Heat', amount=1), ItemCondition(item_name='Cold', amount=1)])), + LocationData(code=None, name='First Encounter: Plasma Phantom (Event)', area='shock-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open13.1'})), + LocationData(code=None, name='First Encounter: Sir Blobus Starnikus (Event)', area='wave-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open14.5'})), + LocationData(code=None, name='First Encounter: Tiefsee Angler (Event)', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'open10.Grove'}, cond=[ItemCondition(item_name='Wave', amount=1), ItemCondition(item_name='Shock', amount=1)])), + LocationData(code=None, name='First Encounter: Son of the East (Event)', area='tree-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open15.1'})), + LocationData(code=None, name='First Encounter: Ancient Guardian (Event)', area='tree-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open15.3'})), + LocationData(code=None, name='First Encounter: Karotto Fruitseeker (Event)', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'linear': '23', 'open': 'open10'}, cond=[ItemCondition(item_name='Purple Bolt Shade', amount=1), ItemCondition(item_name='Azure Drop Shade', amount=1), ItemCondition(item_name='Shock', amount=1), ItemCondition(item_name='Wave', amount=1), QuestCondition(quest_name='Tropical Chill')])), + LocationData(code=None, name='First Encounter: Buff Bloomy (Event)', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'linear': '23', 'open': 'open10'}, cond=[ItemCondition(item_name='Purple Bolt Shade', amount=1), ItemCondition(item_name='Azure Drop Shade', amount=1), ItemCondition(item_name='Wave', amount=1), QuestCondition(quest_name='Lakeside Escort')])), + LocationData(code=None, name='First Encounter: Twilight Master (Event)', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'open17'})), + LocationData(code=None, name='First Encounter: King Kaktorro (Event)', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'linear': '11', 'open': 'open5'}, cond=[QuestCondition(quest_name='Hot Trail'), ItemCondition(item_name='Wave', amount=1), ItemCondition(item_name='Meteor Shade', amount=1)])), + LocationData(code=None, name="First Encounter: DON'T USE THIS (Event)", area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'linear': '31', 'open': 'open16'}, cond=[ItemCondition(item_name='Heat', amount=1), ItemCondition(item_name='Cold', amount=1), ItemCondition(item_name='Wave', amount=1), ItemCondition(item_name='Shock', amount=1)])), + LocationData(code=None, name='First Encounter: Designer (Event)', area='arid', metadata={'kill': True}, access=AccessInfo(region={'open': 'open18'})), + LocationData(code=None, name='First Encounter: The Creator (Event)', area='arid-dng-2', metadata={'kill': True}, access=AccessInfo(region={'open': 'open18'})), + LocationData(code=None, name='First Encounter: Pandza Mk. II (Event)', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'open20'})), LocationData(code=None, name='First Encounter: Echinoignis (Event)', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), LocationData(code=None, name='Grind: Echinoignis (Event)', area='beach', metadata={'dlc': True, 'combat': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), LocationData(code=None, name='First Encounter: Echinonix (Event)', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), @@ -1264,6 +1290,17 @@ LocationData(code=None, name='Grind: Mizree (Event)', area='final-dng', metadata={'dlc': True, 'combat': True}, access=AccessInfo(region={'open': 'openDLC_DungeonEntry'})), LocationData(code=None, name='First Encounter: Beearbot (Event)', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_DungeonEntry'})), LocationData(code=None, name='Grind: Beearbot (Event)', area='final-dng', metadata={'dlc': True, 'combat': True}, access=AccessInfo(region={'open': 'openDLC_DungeonEntry'})), + LocationData(code=None, name='First Encounter: Illegal Coordinator (Event)', area='autumn-area', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': '23', 'open': 'open2'}, cond=[QuestCondition(quest_name='Wet Work'), ItemCondition(item_name='Wave', amount=1), ItemCondition(item_name='Azure Archipelago Pass', amount=1)])), + LocationData(code=None, name='First Encounter: Tremmy (Event)', area='rhombus-sqr', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': '23', 'open': 'open20'}, cond=[ItemCondition(item_name='Tremor Engine', amount=4), ItemCondition(item_name='Humming Razor', amount=1), ItemCondition(item_name='Shock', amount=1), RegionCondition(target_mode='open', region_name='open10.Right'), RegionCondition(target_mode='open', region_name='open16'), ItemCondition(item_name='Azure Archipelago Pass', amount=1)])), + LocationData(code=None, name='First Encounter: Distillizer (Event)', area='heat-village', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': '11', 'open': 'open5'}, cond=[QuestCondition(quest_name='Steamy Booze'), QuestCondition(quest_name='Steamy Challenge'), ItemCondition(item_name='Cold', amount=1), RegionCondition(target_mode='open', region_name='openDLC_Beach'), OrCondition(subconditions=[VariableEntryCondition(name='allowBoosterGrinding', value='off', desired=True), AndCondition(subconditions=[VariableEntryCondition(name='allowBoosterGrinding', value='on', desired=True), ItemCondition(item_name='Everlasting Amber', amount=1), OrCondition(subconditions=[QuestCondition(quest_name='New Metal'), RegionCondition(target_mode='open', region_name='open16'), RegionCondition(target_mode='open', region_name='open10.Infested'), AndCondition(subconditions=[RegionCondition(target_mode='open', region_name='open10.Right'), RegionCondition(target_mode='open', region_name='open10.Left')])])])]), ItemCondition(item_name='Azure Archipelago Pass', amount=1)])), + LocationData(code=None, name='First Encounter: Toxovolt (Event)', area='jungle', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'open10'}, cond=[QuestCondition(quest_name='Rooting for Power'), RegionCondition(target_mode='open', region_name='openDLC_Beach'), ItemCondition(item_name='Cold', amount=1), ItemCondition(item_name='Wave', amount=1), ItemCondition(item_name='Azure Archipelago Pass', amount=1)])), + LocationData(code=None, name='First Encounter: Papaboss the Younger (Event)', area='jungle-city', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openXX'})), + LocationData(code=None, name='First Encounter: Hillcart (Event)', area='rhombus-sqr', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openXX'})), + LocationData(code=None, name='First Encounter: The Goatfather (Event)', area='rhombus-sqr', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': '3', 'open': 'open3'}, cond=[QuestCondition(quest_name='In Cawhoofs'), RegionCondition(target_mode='open', region_name='open20'), ItemCondition(item_name='Azure Archipelago Pass', amount=1)])), + LocationData(code=None, name='First Encounter: Guardian Statue (Event)', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_DungeonEntry'})), + LocationData(code=None, name='First Encounter: Gynthar (Event)', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_DungeonB2_L'})), + LocationData(code=None, name="First Encounter: Di'orbis (Event)", area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_DungeonBoss'})), + LocationData(code=None, name='First Encounter: Son of the Beach (Event)', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': '23', 'open': 'openDLC_Beach'}, cond=[RegionCondition(target_mode='open', region_name='open15.1'), ItemCondition(item_name='Azure Archipelago Pass', amount=1)])), ] events_dict = { location.name: location for location in events_data } diff --git a/worlds/crosscode/regions.py b/worlds/crosscode/regions.py index d910284088b0..1e0ac791e6eb 100644 --- a/worlds/crosscode/regions.py +++ b/worlds/crosscode/regions.py @@ -145,6 +145,7 @@ 'open7.8', 'open8', 'open9', + 'openCursedTemple', 'openDLC1', 'openDLC_Beach', 'openDLC_DungeonB2_L', @@ -175,6 +176,7 @@ RegionConnection(region_from='open4.1', region_to='open4.8', cond=[ItemCondition(item_name='Mine Master Key', amount=1)]), RegionConnection(region_from='open3', region_to='open5', cond=[ItemCondition(item_name='Blue Ice Shade', amount=1)]), RegionConnection(region_from='open2', region_to='open5', cond=[ItemCondition(item_name='Blue Ice Shade', amount=1), VariableCondition(name='rhombusHubUnlock')]), + RegionConnection(region_from='open5', region_to='openCursedTemple', cond=[ItemCondition(item_name='Heat', amount=1), ItemCondition(item_name='Cold', amount=1), ItemCondition(item_name='Cursed Coin', amount=1)]), RegionConnection(region_from='open5', region_to='open6', cond=[ItemCondition(item_name='Maroon Cave Pass', amount=1)]), RegionConnection(region_from='open5', region_to='open7.1', cond=[ItemCondition(item_name='Yellow Sand Shade', amount=1), ItemCondition(item_name='Heat', amount=1)]), RegionConnection(region_from='open7.1', region_to='open7.2', cond=[ItemCondition(item_name="Faj'ro Key", amount=1)]), From 503191a1476f76a43c461adf1df356ba4474e5f3 Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Fri, 3 Jul 2026 21:43:47 -0600 Subject: [PATCH 11/23] add killsanity to codegen --- worlds/crosscode/codegen/lists.py | 19 +++++- worlds/crosscode/locations.py | 101 ++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 1 deletion(-) diff --git a/worlds/crosscode/codegen/lists.py b/worlds/crosscode/codegen/lists.py index 11612f48d610..5fb16f83e266 100644 --- a/worlds/crosscode/codegen/lists.py +++ b/worlds/crosscode/codegen/lists.py @@ -16,7 +16,7 @@ from ..types.items import ItemData, ProgressiveItemChainSingle, SingleItemData, ItemPoolEntry, ProgressiveItemChain from ..types.enemies import Enemy from ..types.locations import AccessInfo, LocationData -from ..types.condition import Condition, NeverCondition, RegionCondition, OrCondition, AndCondition, ShopSlotCondition +from ..types.condition import Condition, ItemCondition, NeverCondition, RegionCondition, OrCondition, AndCondition, ShopSlotCondition from ..types.shops import ShopData class LocationCategory(StrEnum): @@ -608,6 +608,23 @@ def __add_enemy(self, raw: dict[str, typing.Any]): self.enemies[name] = enemy + kill_loc_name = f"Killsanity: {name}" + kill_loc_id = self.__get_or_allocate_location_id(name) + kill_location = LocationData( + name=kill_loc_name, + code=kill_loc_id, + access=AccessInfo( + region={ name: "Menu" for name in first_encounter_access.region }, + cond=[ + ItemCondition(first_encounter_event.name) + ], + ), + area=raw["area"], + metadata=metadata | { "kill": True }, + ) + + self.locations_data[kill_loc_name] = kill_location + def __add_enemies(self, raw: dict[str, dict[str, typing.Any]]): for enemy in raw.values(): self.__add_enemy(enemy) diff --git a/worlds/crosscode/locations.py b/worlds/crosscode/locations.py index 48ebdb365b2e..8ad18ac001e5 100644 --- a/worlds/crosscode/locations.py +++ b/worlds/crosscode/locations.py @@ -1018,6 +1018,107 @@ LocationData(code=3235825005, name='Botanics: Beta Keen Sprout', area='beach', metadata={'botanics': True, 'dlc': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), LocationData(code=3235825006, name='Botanics: Alpha Fossil Stone', area='beach', metadata={'botanics': True, 'dlc': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), LocationData(code=3235825007, name='Botanics: Beta Fossil Stone', area='beach', metadata={'botanics': True, 'dlc': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), + LocationData(code=3235825012, name='Killsanity: Hedgehag', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Hedgehag (Event)', amount=1)])), + LocationData(code=3235825013, name="Killsanity: Rockin' Hillkat", area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: Rockin' Hillkat (Event)", amount=1)])), + LocationData(code=3235825014, name='Killsanity: Mad Bovine', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Mad Bovine (Event)', amount=1)])), + LocationData(code=3235825015, name='Killsanity: Old Hedgehag', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Old Hedgehag (Event)', amount=1)])), + LocationData(code=3235825016, name="Killsanity: Flamin' Hillkat", area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: Flamin' Hillkat (Event)", amount=1)])), + LocationData(code=3235825017, name='Killsanity: Red Eyed Bovine', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Red Eyed Bovine (Event)', amount=1)])), + LocationData(code=3235825018, name='Killsanity: Young Frobbit', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Young Frobbit (Event)', amount=1)])), + LocationData(code=3235825019, name='Killsanity: White Frobbit', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: White Frobbit (Event)', amount=1)])), + LocationData(code=3235825020, name='Killsanity: Seafly', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Seafly (Event)', amount=1)])), + LocationData(code=3235825021, name='Killsanity: Pengpeng', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Pengpeng (Event)', amount=1)])), + LocationData(code=3235825022, name='Killsanity: Horny Goat', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Horny Goat (Event)', amount=1)])), + LocationData(code=3235825023, name='Killsanity: Karotto', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Karotto (Event)', amount=1)])), + LocationData(code=3235825024, name='Killsanity: Fleazer', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Fleazer (Event)', amount=1)])), + LocationData(code=3235825025, name='Killsanity: Carritrich', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Carritrich (Event)', amount=1)])), + LocationData(code=3235825026, name='Killsanity: Kamikatze', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Kamikatze (Event)', amount=1)])), + LocationData(code=3235825027, name='Killsanity: Digmo', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Digmo (Event)', amount=1)])), + LocationData(code=3235825028, name='Killsanity: Pinceron', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Pinceron (Event)', amount=1)])), + LocationData(code=3235825029, name='Killsanity: Sharkster', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Sharkster (Event)', amount=1)])), + LocationData(code=3235825030, name='Killsanity: Vulturbine', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Vulturbine (Event)', amount=1)])), + LocationData(code=3235825031, name='Killsanity: Drillertoise', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Drillertoise (Event)', amount=1)])), + LocationData(code=3235825032, name='Killsanity: Tim', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Tim (Event)', amount=1)])), + LocationData(code=3235825033, name='Killsanity: Boss Pincer', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Boss Pincer (Event)', amount=1)])), + LocationData(code=3235825034, name='Killsanity: Trijelly', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Trijelly (Event)', amount=1)])), + LocationData(code=3235825035, name='Killsanity: Pada Moth', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Pada Moth (Event)', amount=1)])), + LocationData(code=3235825036, name='Killsanity: Darth Moth', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Darth Moth (Event)', amount=1)])), + LocationData(code=3235825037, name='Killsanity: Magmanizer', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Magmanizer (Event)', amount=1)])), + LocationData(code=3235825038, name='Killsanity: Radical Hedgehag', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Radical Hedgehag (Event)', amount=1)])), + LocationData(code=3235825039, name="Killsanity: Chillin' Hillkat", area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: Chillin' Hillkat (Event)", amount=1)])), + LocationData(code=3235825040, name='Killsanity: Fallfly', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Fallfly (Event)', amount=1)])), + LocationData(code=3235825041, name='Killsanity: Ivory Bovine', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Ivory Bovine (Event)', amount=1)])), + LocationData(code=3235825042, name='Killsanity: Neutral Virus', area='arid', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Neutral Virus (Event)', amount=1)])), + LocationData(code=3235825043, name='Killsanity: Heat Virus', area='arid', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Heat Virus (Event)', amount=1)])), + LocationData(code=3235825044, name='Killsanity: Cold Virus', area='arid', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Cold Virus (Event)', amount=1)])), + LocationData(code=3235825045, name='Killsanity: Argeby', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Argeby (Event)', amount=1)])), + LocationData(code=3235825046, name='Killsanity: Gelleric', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Gelleric (Event)', amount=1)])), + LocationData(code=3235825047, name='Killsanity: Papagun', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Papagun (Event)', amount=1)])), + LocationData(code=3235825048, name='Killsanity: Angler', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Angler (Event)', amount=1)])), + LocationData(code=3235825049, name='Killsanity: Shokat', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Shokat (Event)', amount=1)])), + LocationData(code=3235825050, name='Killsanity: Behesloth', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Behesloth (Event)', amount=1)])), + LocationData(code=3235825051, name='Killsanity: Jelleric', area='wave-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Jelleric (Event)', amount=1)])), + LocationData(code=3235825052, name='Killsanity: Ocubepus', area='wave-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Ocubepus (Event)', amount=1)])), + LocationData(code=3235825053, name='Killsanity: Blue Ray', area='wave-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Blue Ray (Event)', amount=1)])), + LocationData(code=3235825054, name='Killsanity: Rob0ck', area='shock-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Rob0ck (Event)', amount=1)])), + LocationData(code=3235825055, name='Killsanity: Powerplant', area='shock-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Powerplant (Event)', amount=1)])), + LocationData(code=3235825056, name='Killsanity: Ectovolt', area='shock-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Ectovolt (Event)', amount=1)])), + LocationData(code=3235825057, name='Killsanity: Sun Beetle', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Sun Beetle (Event)', amount=1)])), + LocationData(code=3235825058, name='Killsanity: Moon Beetle', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Moon Beetle (Event)', amount=1)])), + LocationData(code=3235825059, name='Killsanity: Pandza', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Pandza (Event)', amount=1)])), + LocationData(code=3235825060, name='Killsanity: Aranetarda', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Aranetarda (Event)', amount=1)])), + LocationData(code=3235825061, name='Killsanity: Hillkat Bandleader', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Hillkat Bandleader (Event)', amount=1)])), + LocationData(code=3235825062, name='Killsanity: Blue Hedgehag', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Blue Hedgehag (Event)', amount=1)])), + LocationData(code=3235825063, name='Killsanity: Infected Digmo', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Infected Digmo (Event)', amount=1)])), + LocationData(code=3235825064, name='Killsanity: Peng King Dakara', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Peng King Dakara (Event)', amount=1)])), + LocationData(code=3235825065, name='Killsanity: X01 Driller H.F.S.', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: X01 Driller H.F.S. (Event)', amount=1)])), + LocationData(code=3235825066, name="Killsanity: Ti'im", area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: Ti'im (Event)", amount=1)])), + LocationData(code=3235825067, name='Killsanity: Cursed Sharkster', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Cursed Sharkster (Event)', amount=1)])), + LocationData(code=3235825068, name="Killsanity: Pinzo'jrahrrrn", area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: Pinzo'jrahrrrn (Event)", amount=1)])), + LocationData(code=3235825069, name='Killsanity: Master Magmoth', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Master Magmoth (Event)', amount=1)])), + LocationData(code=3235825070, name='Killsanity: Guard Billston', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Guard Billston (Event)', amount=1)])), + LocationData(code=3235825071, name='Killsanity: Hologram Frobbit', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Hologram Frobbit (Event)', amount=1)])), + LocationData(code=3235825072, name='Killsanity: Smelter Digmo', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Smelter Digmo (Event)', amount=1)])), + LocationData(code=3235825073, name='Killsanity: Blazehoof', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Blazehoof (Event)', amount=1)])), + LocationData(code=3235825074, name='Killsanity: Plasma Phantom', area='shock-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Plasma Phantom (Event)', amount=1)])), + LocationData(code=3235825075, name='Killsanity: Sir Blobus Starnikus', area='wave-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Sir Blobus Starnikus (Event)', amount=1)])), + LocationData(code=3235825076, name='Killsanity: Tiefsee Angler', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Tiefsee Angler (Event)', amount=1)])), + LocationData(code=3235825077, name='Killsanity: Son of the East', area='tree-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Son of the East (Event)', amount=1)])), + LocationData(code=3235825078, name='Killsanity: Ancient Guardian', area='tree-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Ancient Guardian (Event)', amount=1)])), + LocationData(code=3235825079, name='Killsanity: Karotto Fruitseeker', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Karotto Fruitseeker (Event)', amount=1)])), + LocationData(code=3235825080, name='Killsanity: Buff Bloomy', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Buff Bloomy (Event)', amount=1)])), + LocationData(code=3235825081, name='Killsanity: Twilight Master', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Twilight Master (Event)', amount=1)])), + LocationData(code=3235825082, name='Killsanity: King Kaktorro', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: King Kaktorro (Event)', amount=1)])), + LocationData(code=3235825083, name="Killsanity: DON'T USE THIS", area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: DON'T USE THIS (Event)", amount=1)])), + LocationData(code=3235825084, name='Killsanity: Designer', area='arid', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Designer (Event)', amount=1)])), + LocationData(code=3235825085, name='Killsanity: The Creator', area='arid-dng-2', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: The Creator (Event)', amount=1)])), + LocationData(code=3235825086, name='Killsanity: Pandza Mk. II', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Pandza Mk. II (Event)', amount=1)])), + LocationData(code=3235825087, name='Killsanity: Echinoignis', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Echinoignis (Event)', amount=1)])), + LocationData(code=3235825088, name='Killsanity: Echinonix', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Echinonix (Event)', amount=1)])), + LocationData(code=3235825089, name='Killsanity: Echinofulgur', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Echinofulgur (Event)', amount=1)])), + LocationData(code=3235825090, name='Killsanity: Echinofluctus', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Echinofluctus (Event)', amount=1)])), + LocationData(code=3235825091, name='Killsanity: Salteric', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Salteric (Event)', amount=1)])), + LocationData(code=3235825092, name='Killsanity: Balooneer', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Balooneer (Event)', amount=1)])), + LocationData(code=3235825093, name="Killsanity: K'im", area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: K'im (Event)", amount=1)])), + LocationData(code=3235825094, name='Killsanity: Trigenbu', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Trigenbu (Event)', amount=1)])), + LocationData(code=3235825095, name='Killsanity: Heat Crystalid', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Heat Crystalid (Event)', amount=1)])), + LocationData(code=3235825096, name='Killsanity: Cold Crystalid', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Cold Crystalid (Event)', amount=1)])), + LocationData(code=3235825097, name='Killsanity: Shock Crystalid', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Shock Crystalid (Event)', amount=1)])), + LocationData(code=3235825098, name='Killsanity: Wave Crystalid', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Wave Crystalid (Event)', amount=1)])), + LocationData(code=3235825099, name='Killsanity: Hummagnum', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Hummagnum (Event)', amount=1)])), + LocationData(code=3235825100, name='Killsanity: Mizree', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Mizree (Event)', amount=1)])), + LocationData(code=3235825101, name='Killsanity: Beearbot', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Beearbot (Event)', amount=1)])), + LocationData(code=3235825102, name='Killsanity: Illegal Coordinator', area='autumn-area', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Illegal Coordinator (Event)', amount=1)])), + LocationData(code=3235825103, name='Killsanity: Tremmy', area='rhombus-sqr', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Tremmy (Event)', amount=1)])), + LocationData(code=3235825104, name='Killsanity: Distillizer', area='heat-village', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Distillizer (Event)', amount=1)])), + LocationData(code=3235825105, name='Killsanity: Toxovolt', area='jungle', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Toxovolt (Event)', amount=1)])), + LocationData(code=3235825106, name='Killsanity: Papaboss the Younger', area='jungle-city', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Papaboss the Younger (Event)', amount=1)])), + LocationData(code=3235825107, name='Killsanity: Hillcart', area='rhombus-sqr', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Hillcart (Event)', amount=1)])), + LocationData(code=3235825108, name='Killsanity: The Goatfather', area='rhombus-sqr', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: The Goatfather (Event)', amount=1)])), + LocationData(code=3235825109, name='Killsanity: Guardian Statue', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Guardian Statue (Event)', amount=1)])), + LocationData(code=3235825110, name='Killsanity: Gynthar', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Gynthar (Event)', amount=1)])), + LocationData(code=3235825111, name="Killsanity: Di'orbis", area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: Di'orbis (Event)", amount=1)])), + LocationData(code=3235825112, name='Killsanity: Son of the Beach', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Son of the Beach (Event)', amount=1)])), ] locations_dict = { location.name: location for location in locations_data } From b2ac929f5d9e7ea7cb89f0698c2c4539e916ab38 Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Fri, 3 Jul 2026 22:28:43 -0600 Subject: [PATCH 12/23] add killsanity support to generation --- worlds/crosscode/codegen/lists.py | 2 +- worlds/crosscode/locations.py | 2 +- worlds/crosscode/options.py | 13 +++++++++++++ worlds/crosscode/types/pools.py | 2 +- worlds/crosscode/world.py | 2 ++ 5 files changed, 18 insertions(+), 3 deletions(-) diff --git a/worlds/crosscode/codegen/lists.py b/worlds/crosscode/codegen/lists.py index 5fb16f83e266..b442b783ec57 100644 --- a/worlds/crosscode/codegen/lists.py +++ b/worlds/crosscode/codegen/lists.py @@ -609,7 +609,7 @@ def __add_enemy(self, raw: dict[str, typing.Any]): self.enemies[name] = enemy kill_loc_name = f"Killsanity: {name}" - kill_loc_id = self.__get_or_allocate_location_id(name) + kill_loc_id = self.__get_or_allocate_location_id(kill_loc_name) kill_location = LocationData( name=kill_loc_name, code=kill_loc_id, diff --git a/worlds/crosscode/locations.py b/worlds/crosscode/locations.py index 8ad18ac001e5..914513c64ebe 100644 --- a/worlds/crosscode/locations.py +++ b/worlds/crosscode/locations.py @@ -1344,7 +1344,7 @@ LocationData(code=None, name='First Encounter: Cursed Sharkster (Event)', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'openCursedTemple'})), LocationData(code=None, name="First Encounter: Pinzo'jrahrrrn (Event)", area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open7.1'})), LocationData(code=None, name='First Encounter: Master Magmoth (Event)', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'open7.8'})), - LocationData(code=None, name='First Encounter: Guard Billston (Event)', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'open5'}, cond=[QuestCondition(quest_name='Shady Theft'), ItemCondition(item_name='Red Flame Shade', amount=1), ItemCondition(item_name='Heat', amount=1), ItemCondition(item_name='Cold', amount=1)])), + LocationData(code=None, name='First Encounter: Guard Billston (Event)', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'open5'}, cond=[QuestCondition(quest_name='Shady Thief'), ItemCondition(item_name='Red Flame Shade', amount=1), ItemCondition(item_name='Heat', amount=1), ItemCondition(item_name='Cold', amount=1)])), LocationData(code=None, name='First Encounter: Hologram Frobbit (Event)', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'linear': '20', 'open': 'open9'}, cond=[ItemCondition(item_name='Heat', amount=1), ItemCondition(item_name='Cold', amount=1)])), LocationData(code=None, name='First Encounter: Smelter Digmo (Event)', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'linear': '20', 'open': 'open9'}, cond=[ItemCondition(item_name='Red Flame Shade', amount=1), ItemCondition(item_name='Heat', amount=1), ItemCondition(item_name='Cold', amount=1), RegionCondition(target_mode='open', region_name='open4.5'), QuestCondition(quest_name='Bull Grab')])), LocationData(code=None, name='First Encounter: Blazehoof (Event)', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'linear': '20', 'open': 'open9'}, cond=[QuestCondition(quest_name='Intensive Tree Care'), ItemCondition(item_name='Heat', amount=1), ItemCondition(item_name='Cold', amount=1)])), diff --git a/worlds/crosscode/options.py b/worlds/crosscode/options.py index 175997c104b3..879feabe7f6c 100644 --- a/worlds/crosscode/options.py +++ b/worlds/crosscode/options.py @@ -208,6 +208,11 @@ class ShopDialogHints(DefaultOnToggle): """ display_name = "Shop Dialog Hints" +class Killsanity(Toggle): + """ + If enabled, killing every enemy is a check. + """ + class Botanity(Toggle): """ If enabled, acquiring all the information about each plant by collecting drops is a location. @@ -571,6 +576,8 @@ class CrossCodeOptions(PerGameCommonOptions): shop_send_mode: ShopSendMode shop_receive_mode: ShopReceiveMode + killsanity: Killsanity + botanity: Botanity start_with_green_leaf_shade: StartWithGreenLeafShade @@ -628,6 +635,12 @@ class CrossCodeOptions(PerGameCommonOptions): ShopReceiveMode ] ), + OptionGroup( + name="Killsanity", + options=[ + Killsanity, + ] + ), OptionGroup( name="Botanics", options=[ diff --git a/worlds/crosscode/types/pools.py b/worlds/crosscode/types/pools.py index 4ab9a394a5de..b406cefb373e 100644 --- a/worlds/crosscode/types/pools.py +++ b/worlds/crosscode/types/pools.py @@ -147,7 +147,7 @@ def __should_include(self, metadata: IncludeOptions | None) -> bool: result = True - for var in ("dlc", "trade", "shop", "arena", "chest", "quest", "botanics"): + for var in ("dlc", "trade", "shop", "arena", "chest", "quest", "botanics", "combat", "kill"): val = metadata.get(var) if val is None: diff --git a/worlds/crosscode/world.py b/worlds/crosscode/world.py index 8b099984c515..52a00bf5a0cb 100644 --- a/worlds/crosscode/world.py +++ b/worlds/crosscode/world.py @@ -171,6 +171,8 @@ def get_include_options(self) -> IncludeOptions: "chest": True, "quest": bool(self.options.quest_rando.value), "botanics": bool(self.options.botanity.value), + "combat": False, + "kill": bool(self.options.killsanity.value), } def create_location(self, location: str, event_from_location: bool = False) -> CrossCodeLocation: From e42d09ddec256c54499c55ef09467088cf3c4f72 Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Fri, 3 Jul 2026 22:43:34 -0600 Subject: [PATCH 13/23] add killsanity to pool locations --- worlds/crosscode/codegen/lists.py | 1 + worlds/crosscode/locations.py | 101 ++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) diff --git a/worlds/crosscode/codegen/lists.py b/worlds/crosscode/codegen/lists.py index b442b783ec57..6b0c5923c72d 100644 --- a/worlds/crosscode/codegen/lists.py +++ b/worlds/crosscode/codegen/lists.py @@ -624,6 +624,7 @@ def __add_enemy(self, raw: dict[str, typing.Any]): ) self.locations_data[kill_loc_name] = kill_location + self.pool_locations.append(kill_location) def __add_enemies(self, raw: dict[str, dict[str, typing.Any]]): for enemy in raw.values(): diff --git a/worlds/crosscode/locations.py b/worlds/crosscode/locations.py index 914513c64ebe..c08e0453927d 100644 --- a/worlds/crosscode/locations.py +++ b/worlds/crosscode/locations.py @@ -2501,6 +2501,107 @@ locations_dict['Botanics: Beta Keen Sprout'], locations_dict['Botanics: Alpha Fossil Stone'], locations_dict['Botanics: Beta Fossil Stone'], + locations_dict['Killsanity: Hedgehag'], + locations_dict["Killsanity: Rockin' Hillkat"], + locations_dict['Killsanity: Mad Bovine'], + locations_dict['Killsanity: Old Hedgehag'], + locations_dict["Killsanity: Flamin' Hillkat"], + locations_dict['Killsanity: Red Eyed Bovine'], + locations_dict['Killsanity: Young Frobbit'], + locations_dict['Killsanity: White Frobbit'], + locations_dict['Killsanity: Seafly'], + locations_dict['Killsanity: Pengpeng'], + locations_dict['Killsanity: Horny Goat'], + locations_dict['Killsanity: Karotto'], + locations_dict['Killsanity: Fleazer'], + locations_dict['Killsanity: Carritrich'], + locations_dict['Killsanity: Kamikatze'], + locations_dict['Killsanity: Digmo'], + locations_dict['Killsanity: Pinceron'], + locations_dict['Killsanity: Sharkster'], + locations_dict['Killsanity: Vulturbine'], + locations_dict['Killsanity: Drillertoise'], + locations_dict['Killsanity: Tim'], + locations_dict['Killsanity: Boss Pincer'], + locations_dict['Killsanity: Trijelly'], + locations_dict['Killsanity: Pada Moth'], + locations_dict['Killsanity: Darth Moth'], + locations_dict['Killsanity: Magmanizer'], + locations_dict['Killsanity: Radical Hedgehag'], + locations_dict["Killsanity: Chillin' Hillkat"], + locations_dict['Killsanity: Fallfly'], + locations_dict['Killsanity: Ivory Bovine'], + locations_dict['Killsanity: Neutral Virus'], + locations_dict['Killsanity: Heat Virus'], + locations_dict['Killsanity: Cold Virus'], + locations_dict['Killsanity: Argeby'], + locations_dict['Killsanity: Gelleric'], + locations_dict['Killsanity: Papagun'], + locations_dict['Killsanity: Angler'], + locations_dict['Killsanity: Shokat'], + locations_dict['Killsanity: Behesloth'], + locations_dict['Killsanity: Jelleric'], + locations_dict['Killsanity: Ocubepus'], + locations_dict['Killsanity: Blue Ray'], + locations_dict['Killsanity: Rob0ck'], + locations_dict['Killsanity: Powerplant'], + locations_dict['Killsanity: Ectovolt'], + locations_dict['Killsanity: Sun Beetle'], + locations_dict['Killsanity: Moon Beetle'], + locations_dict['Killsanity: Pandza'], + locations_dict['Killsanity: Aranetarda'], + locations_dict['Killsanity: Hillkat Bandleader'], + locations_dict['Killsanity: Blue Hedgehag'], + locations_dict['Killsanity: Infected Digmo'], + locations_dict['Killsanity: Peng King Dakara'], + locations_dict['Killsanity: X01 Driller H.F.S.'], + locations_dict["Killsanity: Ti'im"], + locations_dict['Killsanity: Cursed Sharkster'], + locations_dict["Killsanity: Pinzo'jrahrrrn"], + locations_dict['Killsanity: Master Magmoth'], + locations_dict['Killsanity: Guard Billston'], + locations_dict['Killsanity: Hologram Frobbit'], + locations_dict['Killsanity: Smelter Digmo'], + locations_dict['Killsanity: Blazehoof'], + locations_dict['Killsanity: Plasma Phantom'], + locations_dict['Killsanity: Sir Blobus Starnikus'], + locations_dict['Killsanity: Tiefsee Angler'], + locations_dict['Killsanity: Son of the East'], + locations_dict['Killsanity: Ancient Guardian'], + locations_dict['Killsanity: Karotto Fruitseeker'], + locations_dict['Killsanity: Buff Bloomy'], + locations_dict['Killsanity: Twilight Master'], + locations_dict['Killsanity: King Kaktorro'], + locations_dict["Killsanity: DON'T USE THIS"], + locations_dict['Killsanity: Designer'], + locations_dict['Killsanity: The Creator'], + locations_dict['Killsanity: Pandza Mk. II'], + locations_dict['Killsanity: Echinoignis'], + locations_dict['Killsanity: Echinonix'], + locations_dict['Killsanity: Echinofulgur'], + locations_dict['Killsanity: Echinofluctus'], + locations_dict['Killsanity: Salteric'], + locations_dict['Killsanity: Balooneer'], + locations_dict["Killsanity: K'im"], + locations_dict['Killsanity: Trigenbu'], + locations_dict['Killsanity: Heat Crystalid'], + locations_dict['Killsanity: Cold Crystalid'], + locations_dict['Killsanity: Shock Crystalid'], + locations_dict['Killsanity: Wave Crystalid'], + locations_dict['Killsanity: Hummagnum'], + locations_dict['Killsanity: Mizree'], + locations_dict['Killsanity: Beearbot'], + locations_dict['Killsanity: Illegal Coordinator'], + locations_dict['Killsanity: Tremmy'], + locations_dict['Killsanity: Distillizer'], + locations_dict['Killsanity: Toxovolt'], + locations_dict['Killsanity: Papaboss the Younger'], + locations_dict['Killsanity: Hillcart'], + locations_dict['Killsanity: The Goatfather'], + locations_dict['Killsanity: Guardian Statue'], + locations_dict['Killsanity: Gynthar'], + locations_dict["Killsanity: Di'orbis"], + locations_dict['Killsanity: Son of the Beach'], ] location_groups = { From d4fd0533ff1d813694952a40856a30cea47d61d5 Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Fri, 3 Jul 2026 22:43:51 -0600 Subject: [PATCH 14/23] fix some dlc boss details --- worlds/crosscode/locations.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/worlds/crosscode/locations.py b/worlds/crosscode/locations.py index c08e0453927d..45d9b93a6b5a 100644 --- a/worlds/crosscode/locations.py +++ b/worlds/crosscode/locations.py @@ -1112,8 +1112,8 @@ LocationData(code=3235825103, name='Killsanity: Tremmy', area='rhombus-sqr', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Tremmy (Event)', amount=1)])), LocationData(code=3235825104, name='Killsanity: Distillizer', area='heat-village', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Distillizer (Event)', amount=1)])), LocationData(code=3235825105, name='Killsanity: Toxovolt', area='jungle', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Toxovolt (Event)', amount=1)])), - LocationData(code=3235825106, name='Killsanity: Papaboss the Younger', area='jungle-city', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Papaboss the Younger (Event)', amount=1)])), - LocationData(code=3235825107, name='Killsanity: Hillcart', area='rhombus-sqr', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Hillcart (Event)', amount=1)])), + LocationData(code=3235825106, name='Killsanity: Papaboss the Younger', area='jungle-city', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Papaboss the Younger (Event)', amount=1)])), + LocationData(code=3235825107, name='Killsanity: Hillcart', area='rhombus-sqr', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Hillcart (Event)', amount=1)])), LocationData(code=3235825108, name='Killsanity: The Goatfather', area='rhombus-sqr', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: The Goatfather (Event)', amount=1)])), LocationData(code=3235825109, name='Killsanity: Guardian Statue', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Guardian Statue (Event)', amount=1)])), LocationData(code=3235825110, name='Killsanity: Gynthar', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Gynthar (Event)', amount=1)])), @@ -1395,8 +1395,8 @@ LocationData(code=None, name='First Encounter: Tremmy (Event)', area='rhombus-sqr', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': '23', 'open': 'open20'}, cond=[ItemCondition(item_name='Tremor Engine', amount=4), ItemCondition(item_name='Humming Razor', amount=1), ItemCondition(item_name='Shock', amount=1), RegionCondition(target_mode='open', region_name='open10.Right'), RegionCondition(target_mode='open', region_name='open16'), ItemCondition(item_name='Azure Archipelago Pass', amount=1)])), LocationData(code=None, name='First Encounter: Distillizer (Event)', area='heat-village', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': '11', 'open': 'open5'}, cond=[QuestCondition(quest_name='Steamy Booze'), QuestCondition(quest_name='Steamy Challenge'), ItemCondition(item_name='Cold', amount=1), RegionCondition(target_mode='open', region_name='openDLC_Beach'), OrCondition(subconditions=[VariableEntryCondition(name='allowBoosterGrinding', value='off', desired=True), AndCondition(subconditions=[VariableEntryCondition(name='allowBoosterGrinding', value='on', desired=True), ItemCondition(item_name='Everlasting Amber', amount=1), OrCondition(subconditions=[QuestCondition(quest_name='New Metal'), RegionCondition(target_mode='open', region_name='open16'), RegionCondition(target_mode='open', region_name='open10.Infested'), AndCondition(subconditions=[RegionCondition(target_mode='open', region_name='open10.Right'), RegionCondition(target_mode='open', region_name='open10.Left')])])])]), ItemCondition(item_name='Azure Archipelago Pass', amount=1)])), LocationData(code=None, name='First Encounter: Toxovolt (Event)', area='jungle', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'open10'}, cond=[QuestCondition(quest_name='Rooting for Power'), RegionCondition(target_mode='open', region_name='openDLC_Beach'), ItemCondition(item_name='Cold', amount=1), ItemCondition(item_name='Wave', amount=1), ItemCondition(item_name='Azure Archipelago Pass', amount=1)])), - LocationData(code=None, name='First Encounter: Papaboss the Younger (Event)', area='jungle-city', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openXX'})), - LocationData(code=None, name='First Encounter: Hillcart (Event)', area='rhombus-sqr', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openXX'})), + LocationData(code=None, name='First Encounter: Papaboss the Younger (Event)', area='jungle-city', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': '3', 'open': 'open3'}, cond=[QuestCondition(quest_name='In Cawhoofs'), RegionCondition(target_mode='open', region_name='open20'), ItemCondition(item_name='Azure Archipelago Pass', amount=1)])), + LocationData(code=None, name='First Encounter: Hillcart (Event)', area='rhombus-sqr', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': '23', 'open': 'open20'}, cond=[ItemCondition(item_name='Azure Archipelago Pass', amount=1)])), LocationData(code=None, name='First Encounter: The Goatfather (Event)', area='rhombus-sqr', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': '3', 'open': 'open3'}, cond=[QuestCondition(quest_name='In Cawhoofs'), RegionCondition(target_mode='open', region_name='open20'), ItemCondition(item_name='Azure Archipelago Pass', amount=1)])), LocationData(code=None, name='First Encounter: Guardian Statue (Event)', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_DungeonEntry'})), LocationData(code=None, name='First Encounter: Gynthar (Event)', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'openDLC_DungeonB2_L'})), From c65a385cd5b517e69eccb51c20333f07c7155217 Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Sat, 4 Jul 2026 01:46:18 -0600 Subject: [PATCH 15/23] add enemies to randoData --- worlds/crosscode/codegen/gen.py | 4 ++++ worlds/crosscode/types/json_data.py | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/worlds/crosscode/codegen/gen.py b/worlds/crosscode/codegen/gen.py index 0d6c92715ee7..7aad1f96e55e 100644 --- a/worlds/crosscode/codegen/gen.py +++ b/worlds/crosscode/codegen/gen.py @@ -271,6 +271,10 @@ def generate_mod_files(self): "byShopAndId": defaultdict(dict) }, }, + "enemies": { + enemy.internal_name: { "kill": self.lists.locations_data[f"Killsanity: {enemy.name}"].code } + for enemy in self.lists.enemies.values() + }, "botanics": self.lists.botanics_internal_names_to_ids, "descriptions": self.lists.descriptions, "markers": self.lists.markers diff --git a/worlds/crosscode/types/json_data.py b/worlds/crosscode/types/json_data.py index 77b92b4d82c9..e7ad0b3bdb44 100644 --- a/worlds/crosscode/types/json_data.py +++ b/worlds/crosscode/types/json_data.py @@ -38,9 +38,13 @@ class ExportShopInfo(TypedDict): locations: ExportShopLocationsInfo unlocks: ExportShopUnlocksInfo +class ExportEnemyInfo(TypedDict): + kill: int + class ExportInfo(TypedDict): items: dict[str, ExportRoomInfo] quests: dict[str, typing.Any] shops: ExportShopInfo descriptions: dict[int, dict[str, str]] markers: dict[int, list[dict[str, typing.Any]]] + enemies: dict[str, ExportEnemyInfo] From a05debce063f613e0468e335e665ee87a32479ab Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Sun, 5 Jul 2026 17:40:34 -0600 Subject: [PATCH 16/23] add killsanity item groups --- worlds/crosscode/codegen/lists.py | 9 + worlds/crosscode/locations.py | 343 ++++++++++++++++++++++++++++++ 2 files changed, 352 insertions(+) diff --git a/worlds/crosscode/codegen/lists.py b/worlds/crosscode/codegen/lists.py index 6b0c5923c72d..2c04e56c72a4 100644 --- a/worlds/crosscode/codegen/lists.py +++ b/worlds/crosscode/codegen/lists.py @@ -555,6 +555,7 @@ def __add_enemy(self, raw: dict[str, typing.Any]): try: name = raw["name"] area = raw["area"] + area_name = self.ctx.area_names[area] internal_name = raw["id"] level = raw["level"] except KeyError: @@ -623,8 +624,16 @@ def __add_enemy(self, raw: dict[str, typing.Any]): metadata=metadata | { "kill": True }, ) + if area != None: + try: + self.location_groups[area_name].append(kill_location) + self.location_groups[f"{area_name} Kills"].append(kill_location) + except KeyError: + print(f"Cannot add location '{name}' in area '{area}'") + self.locations_data[kill_loc_name] = kill_location self.pool_locations.append(kill_location) + self.location_groups["Kills"].append(kill_location) def __add_enemies(self, raw: dict[str, dict[str, typing.Any]]): for enemy in raw.values(): diff --git a/worlds/crosscode/locations.py b/worlds/crosscode/locations.py index 45d9b93a6b5a..661f451b0c5b 100644 --- a/worlds/crosscode/locations.py +++ b/worlds/crosscode/locations.py @@ -2633,6 +2633,10 @@ locations_dict['Shop Slot: Fruit Drink (Vermillion Items)'], locations_dict['Shop Slot: Rice Cracker (Vermillion Items)'], locations_dict['Shop Slot: Veggie Sticks (Vermillion Items)'], + locations_dict['Killsanity: Neutral Virus'], + locations_dict['Killsanity: Heat Virus'], + locations_dict['Killsanity: Cold Virus'], + locations_dict['Killsanity: Designer'], }, "Vermillion Wasteland Chests": { locations_dict['Wasteland: Spiral Cliff Center'], @@ -2696,6 +2700,15 @@ locations_dict['Botanics: Alpha Water Blades'], locations_dict['Botanics: Beta Water Blades'], locations_dict['Botanics: Omega Water Blades'], + locations_dict['Killsanity: Hedgehag'], + locations_dict["Killsanity: Rockin' Hillkat"], + locations_dict['Killsanity: Mad Bovine'], + locations_dict['Killsanity: Old Hedgehag'], + locations_dict["Killsanity: Flamin' Hillkat"], + locations_dict['Killsanity: Red Eyed Bovine'], + locations_dict['Killsanity: Hillkat Bandleader'], + locations_dict['Killsanity: Blue Hedgehag'], + locations_dict['Killsanity: Illegal Coordinator'], }, "Autumn's Rise Chests": { locations_dict['Rise: Drippy Den'], @@ -2761,6 +2774,12 @@ locations_dict['Botanics: Alpha Water Cutlass'], locations_dict['Botanics: Beta Water Cutlass'], locations_dict['Botanics: Omega Water Cutlass'], + locations_dict['Killsanity: Radical Hedgehag'], + locations_dict["Killsanity: Chillin' Hillkat"], + locations_dict['Killsanity: Fallfly'], + locations_dict['Killsanity: Ivory Bovine'], + locations_dict['Killsanity: Hologram Frobbit'], + locations_dict['Killsanity: Blazehoof'], }, "Autumn's Fall Chests": { locations_dict['Fall: Ruby Tunnel'], @@ -2940,6 +2959,13 @@ locations_dict['Botanics: Beta Lance Shrub'], locations_dict['Botanics: Omega Lance Shrub'], locations_dict['Botanics: Diamond Ice'], + locations_dict['Killsanity: Young Frobbit'], + locations_dict['Killsanity: White Frobbit'], + locations_dict['Killsanity: Seafly'], + locations_dict['Killsanity: Pengpeng'], + locations_dict['Killsanity: Horny Goat'], + locations_dict['Killsanity: Karotto'], + locations_dict['Killsanity: Peng King Dakara'], }, "Bergen Trail Chests": { locations_dict['Trail: Abandoned Cave'], @@ -3006,6 +3032,13 @@ locations_dict['Botanics: Delta Egg Pot'], locations_dict['Botanics: Omega Egg Pot A'], locations_dict['Botanics: Omega Egg Pot B'], + locations_dict['Killsanity: Fleazer'], + locations_dict['Killsanity: Carritrich'], + locations_dict['Killsanity: Kamikatze'], + locations_dict['Killsanity: Digmo'], + locations_dict['Killsanity: Infected Digmo'], + locations_dict['Killsanity: X01 Driller H.F.S.'], + locations_dict['Killsanity: Smelter Digmo'], }, "Temple Mine Chests": { locations_dict['Mine U1: Elevator'], @@ -3115,6 +3148,12 @@ locations_dict['Botanics: Alpha Crystal'], locations_dict['Botanics: Beta Crystal'], locations_dict['Botanics: Omega Crystal'], + locations_dict['Killsanity: Sun Beetle'], + locations_dict['Killsanity: Moon Beetle'], + locations_dict['Killsanity: Pandza'], + locations_dict['Killsanity: Aranetarda'], + locations_dict['Killsanity: Twilight Master'], + locations_dict['Killsanity: Pandza Mk. II'], }, "Sapphire Ridge Chests": { locations_dict['Ridge: The Barracks'], @@ -3219,6 +3258,17 @@ locations_dict['Botanics: Alpha Bone Pile'], locations_dict['Botanics: Beta Bone Pile'], locations_dict['Botanics: Omega Bone Pile'], + locations_dict['Killsanity: Pinceron'], + locations_dict['Killsanity: Sharkster'], + locations_dict['Killsanity: Vulturbine'], + locations_dict['Killsanity: Drillertoise'], + locations_dict['Killsanity: Tim'], + locations_dict['Killsanity: Boss Pincer'], + locations_dict["Killsanity: Ti'im"], + locations_dict['Killsanity: Cursed Sharkster'], + locations_dict['Killsanity: Guard Billston'], + locations_dict['Killsanity: King Kaktorro'], + locations_dict["Killsanity: DON'T USE THIS"], }, "Maroon Valley Chests": { locations_dict['Maroon: Mystery Cave Lower'], @@ -3282,6 +3332,12 @@ locations_dict["Faj'ro Circuit Override"], locations_dict["Faj'ro SP Upgrade"], locations_dict['Cold Pedestal'], + locations_dict['Killsanity: Trijelly'], + locations_dict['Killsanity: Pada Moth'], + locations_dict['Killsanity: Darth Moth'], + locations_dict['Killsanity: Magmanizer'], + locations_dict["Killsanity: Pinzo'jrahrrrn"], + locations_dict['Killsanity: Master Magmoth'], }, "Faj'ro Temple Chests": { locations_dict["Faj'ro 1F: Right Chamber 1"], @@ -3357,6 +3413,7 @@ locations_dict["Shop Slot: Steel Mail (Ba'kii Weapons)"], locations_dict["Shop Slot: Steel Boots (Ba'kii Weapons)"], locations_dict['Botanics: Sprout of Space'], + locations_dict['Killsanity: Distillizer'], }, "Ba'kii Kum Chests": { locations_dict["Ba'kii: Solar Farm Upper"], @@ -3456,6 +3513,16 @@ locations_dict['Botanics: Alpha Virus Shroom'], locations_dict['Botanics: Beta Virus Shroom'], locations_dict['Botanics: Omega Virus Shroom'], + locations_dict['Killsanity: Argeby'], + locations_dict['Killsanity: Gelleric'], + locations_dict['Killsanity: Papagun'], + locations_dict['Killsanity: Angler'], + locations_dict['Killsanity: Shokat'], + locations_dict['Killsanity: Behesloth'], + locations_dict['Killsanity: Tiefsee Angler'], + locations_dict['Killsanity: Karotto Fruitseeker'], + locations_dict['Killsanity: Buff Bloomy'], + locations_dict['Killsanity: Toxovolt'], }, "Gaia's Garden Chests": { locations_dict['Garden: Dripping Cave'], @@ -3604,6 +3671,7 @@ locations_dict['Shop Slot: Titan Boots (Basin Weapons)'], locations_dict['Shop Slot: One Up (Calzone Shop)'], locations_dict['Botanics: Sprout of Spirit'], + locations_dict['Killsanity: Papaboss the Younger'], }, "Basin Keep Chests": { locations_dict['Basin: Centrum'], @@ -3685,6 +3753,9 @@ locations_dict['Shop Slot: Cross Mail (Rhombus Weapons + DLC)'], locations_dict['Shop Slot: Cross Boots (Rhombus Weapons + DLC)'], locations_dict['Botanics: Sprout of Ages'], + locations_dict['Killsanity: Tremmy'], + locations_dict['Killsanity: Hillcart'], + locations_dict['Killsanity: The Goatfather'], }, "Rhombus Square Chests": { locations_dict['Rhombus: Arena Plaza East'], @@ -3822,6 +3893,10 @@ locations_dict["Zir'vitar Shade Statue"], locations_dict["Zir'vitar Circuit Override"], locations_dict['Wave Pedestal'], + locations_dict['Killsanity: Rob0ck'], + locations_dict['Killsanity: Powerplant'], + locations_dict['Killsanity: Ectovolt'], + locations_dict['Killsanity: Plasma Phantom'], }, "Zir'vitar Temple Chests": { locations_dict["Zir'vitar 1F: Moving Transmit Left"], @@ -3843,6 +3918,8 @@ locations_dict["Krys'kajo Shade Statue"], locations_dict["Krys'kajo Circuit Override"], locations_dict["Krys'kajo SP Upgrade"], + locations_dict['Killsanity: Son of the East'], + locations_dict['Killsanity: Ancient Guardian'], }, "Grand Krys'kajo Chests": { locations_dict['Kajo 3F: East Branch Lower'], @@ -3871,6 +3948,10 @@ locations_dict["So'najiz Shade Statue"], locations_dict["So'najiz Circuit Override"], locations_dict['Shock Pedestal'], + locations_dict['Killsanity: Jelleric'], + locations_dict['Killsanity: Ocubepus'], + locations_dict['Killsanity: Blue Ray'], + locations_dict['Killsanity: Sir Blobus Starnikus'], }, "So'najiz Temple Chests": { locations_dict["So'najiz U1: Principle of Conveyance"], @@ -3954,6 +4035,15 @@ locations_dict['Botanics: Beta Keen Sprout'], locations_dict['Botanics: Alpha Fossil Stone'], locations_dict['Botanics: Beta Fossil Stone'], + locations_dict['Killsanity: Echinoignis'], + locations_dict['Killsanity: Echinonix'], + locations_dict['Killsanity: Echinofulgur'], + locations_dict['Killsanity: Echinofluctus'], + locations_dict['Killsanity: Salteric'], + locations_dict['Killsanity: Balooneer'], + locations_dict["Killsanity: K'im"], + locations_dict['Killsanity: Trigenbu'], + locations_dict['Killsanity: Son of the Beach'], }, "Azure Archipelago Chests": { locations_dict['Azure A.: Sandy Bar Lower'], @@ -4001,6 +4091,16 @@ locations_dict['Botanics: Gamma Cone Sprout'], locations_dict['Botanics: Delta Cone Sprout'], locations_dict['Botanics: Alpha Shard'], + locations_dict['Killsanity: Heat Crystalid'], + locations_dict['Killsanity: Cold Crystalid'], + locations_dict['Killsanity: Shock Crystalid'], + locations_dict['Killsanity: Wave Crystalid'], + locations_dict['Killsanity: Hummagnum'], + locations_dict['Killsanity: Mizree'], + locations_dict['Killsanity: Beearbot'], + locations_dict['Killsanity: Guardian Statue'], + locations_dict['Killsanity: Gynthar'], + locations_dict["Killsanity: Di'orbis"], }, "Ku'lero Temple Chests": { locations_dict["Ku'lero: Comet Trail Right"], @@ -4786,5 +4886,248 @@ locations_dict['Botanics: Alpha Fossil Stone'], locations_dict['Botanics: Beta Fossil Stone'], }, + "Autumn's Rise Kills": { + locations_dict['Killsanity: Hedgehag'], + locations_dict["Killsanity: Rockin' Hillkat"], + locations_dict['Killsanity: Mad Bovine'], + locations_dict['Killsanity: Old Hedgehag'], + locations_dict["Killsanity: Flamin' Hillkat"], + locations_dict['Killsanity: Red Eyed Bovine'], + locations_dict['Killsanity: Hillkat Bandleader'], + locations_dict['Killsanity: Blue Hedgehag'], + locations_dict['Killsanity: Illegal Coordinator'], + }, + "Kills": { + locations_dict['Killsanity: Hedgehag'], + locations_dict["Killsanity: Rockin' Hillkat"], + locations_dict['Killsanity: Mad Bovine'], + locations_dict['Killsanity: Old Hedgehag'], + locations_dict["Killsanity: Flamin' Hillkat"], + locations_dict['Killsanity: Red Eyed Bovine'], + locations_dict['Killsanity: Young Frobbit'], + locations_dict['Killsanity: White Frobbit'], + locations_dict['Killsanity: Seafly'], + locations_dict['Killsanity: Pengpeng'], + locations_dict['Killsanity: Horny Goat'], + locations_dict['Killsanity: Karotto'], + locations_dict['Killsanity: Fleazer'], + locations_dict['Killsanity: Carritrich'], + locations_dict['Killsanity: Kamikatze'], + locations_dict['Killsanity: Digmo'], + locations_dict['Killsanity: Pinceron'], + locations_dict['Killsanity: Sharkster'], + locations_dict['Killsanity: Vulturbine'], + locations_dict['Killsanity: Drillertoise'], + locations_dict['Killsanity: Tim'], + locations_dict['Killsanity: Boss Pincer'], + locations_dict['Killsanity: Trijelly'], + locations_dict['Killsanity: Pada Moth'], + locations_dict['Killsanity: Darth Moth'], + locations_dict['Killsanity: Magmanizer'], + locations_dict['Killsanity: Radical Hedgehag'], + locations_dict["Killsanity: Chillin' Hillkat"], + locations_dict['Killsanity: Fallfly'], + locations_dict['Killsanity: Ivory Bovine'], + locations_dict['Killsanity: Neutral Virus'], + locations_dict['Killsanity: Heat Virus'], + locations_dict['Killsanity: Cold Virus'], + locations_dict['Killsanity: Argeby'], + locations_dict['Killsanity: Gelleric'], + locations_dict['Killsanity: Papagun'], + locations_dict['Killsanity: Angler'], + locations_dict['Killsanity: Shokat'], + locations_dict['Killsanity: Behesloth'], + locations_dict['Killsanity: Jelleric'], + locations_dict['Killsanity: Ocubepus'], + locations_dict['Killsanity: Blue Ray'], + locations_dict['Killsanity: Rob0ck'], + locations_dict['Killsanity: Powerplant'], + locations_dict['Killsanity: Ectovolt'], + locations_dict['Killsanity: Sun Beetle'], + locations_dict['Killsanity: Moon Beetle'], + locations_dict['Killsanity: Pandza'], + locations_dict['Killsanity: Aranetarda'], + locations_dict['Killsanity: Hillkat Bandleader'], + locations_dict['Killsanity: Blue Hedgehag'], + locations_dict['Killsanity: Infected Digmo'], + locations_dict['Killsanity: Peng King Dakara'], + locations_dict['Killsanity: X01 Driller H.F.S.'], + locations_dict["Killsanity: Ti'im"], + locations_dict['Killsanity: Cursed Sharkster'], + locations_dict["Killsanity: Pinzo'jrahrrrn"], + locations_dict['Killsanity: Master Magmoth'], + locations_dict['Killsanity: Guard Billston'], + locations_dict['Killsanity: Hologram Frobbit'], + locations_dict['Killsanity: Smelter Digmo'], + locations_dict['Killsanity: Blazehoof'], + locations_dict['Killsanity: Plasma Phantom'], + locations_dict['Killsanity: Sir Blobus Starnikus'], + locations_dict['Killsanity: Tiefsee Angler'], + locations_dict['Killsanity: Son of the East'], + locations_dict['Killsanity: Ancient Guardian'], + locations_dict['Killsanity: Karotto Fruitseeker'], + locations_dict['Killsanity: Buff Bloomy'], + locations_dict['Killsanity: Twilight Master'], + locations_dict['Killsanity: King Kaktorro'], + locations_dict["Killsanity: DON'T USE THIS"], + locations_dict['Killsanity: Designer'], + locations_dict['Killsanity: The Creator'], + locations_dict['Killsanity: Pandza Mk. II'], + locations_dict['Killsanity: Echinoignis'], + locations_dict['Killsanity: Echinonix'], + locations_dict['Killsanity: Echinofulgur'], + locations_dict['Killsanity: Echinofluctus'], + locations_dict['Killsanity: Salteric'], + locations_dict['Killsanity: Balooneer'], + locations_dict["Killsanity: K'im"], + locations_dict['Killsanity: Trigenbu'], + locations_dict['Killsanity: Heat Crystalid'], + locations_dict['Killsanity: Cold Crystalid'], + locations_dict['Killsanity: Shock Crystalid'], + locations_dict['Killsanity: Wave Crystalid'], + locations_dict['Killsanity: Hummagnum'], + locations_dict['Killsanity: Mizree'], + locations_dict['Killsanity: Beearbot'], + locations_dict['Killsanity: Illegal Coordinator'], + locations_dict['Killsanity: Tremmy'], + locations_dict['Killsanity: Distillizer'], + locations_dict['Killsanity: Toxovolt'], + locations_dict['Killsanity: Papaboss the Younger'], + locations_dict['Killsanity: Hillcart'], + locations_dict['Killsanity: The Goatfather'], + locations_dict['Killsanity: Guardian Statue'], + locations_dict['Killsanity: Gynthar'], + locations_dict["Killsanity: Di'orbis"], + locations_dict['Killsanity: Son of the Beach'], + }, + "Bergen Trail Kills": { + locations_dict['Killsanity: Young Frobbit'], + locations_dict['Killsanity: White Frobbit'], + locations_dict['Killsanity: Seafly'], + locations_dict['Killsanity: Pengpeng'], + locations_dict['Killsanity: Horny Goat'], + locations_dict['Killsanity: Karotto'], + locations_dict['Killsanity: Peng King Dakara'], + }, + "Temple Mine Kills": { + locations_dict['Killsanity: Fleazer'], + locations_dict['Killsanity: Carritrich'], + locations_dict['Killsanity: Kamikatze'], + locations_dict['Killsanity: Digmo'], + locations_dict['Killsanity: Infected Digmo'], + locations_dict['Killsanity: X01 Driller H.F.S.'], + locations_dict['Killsanity: Smelter Digmo'], + }, + "Maroon Valley Kills": { + locations_dict['Killsanity: Pinceron'], + locations_dict['Killsanity: Sharkster'], + locations_dict['Killsanity: Vulturbine'], + locations_dict['Killsanity: Drillertoise'], + locations_dict['Killsanity: Tim'], + locations_dict['Killsanity: Boss Pincer'], + locations_dict["Killsanity: Ti'im"], + locations_dict['Killsanity: Cursed Sharkster'], + locations_dict['Killsanity: Guard Billston'], + locations_dict['Killsanity: King Kaktorro'], + locations_dict["Killsanity: DON'T USE THIS"], + }, + "Faj'ro Temple Kills": { + locations_dict['Killsanity: Trijelly'], + locations_dict['Killsanity: Pada Moth'], + locations_dict['Killsanity: Darth Moth'], + locations_dict['Killsanity: Magmanizer'], + locations_dict["Killsanity: Pinzo'jrahrrrn"], + locations_dict['Killsanity: Master Magmoth'], + }, + "Autumn's Fall Kills": { + locations_dict['Killsanity: Radical Hedgehag'], + locations_dict["Killsanity: Chillin' Hillkat"], + locations_dict['Killsanity: Fallfly'], + locations_dict['Killsanity: Ivory Bovine'], + locations_dict['Killsanity: Hologram Frobbit'], + locations_dict['Killsanity: Blazehoof'], + }, + "Vermillion Wasteland Kills": { + locations_dict['Killsanity: Neutral Virus'], + locations_dict['Killsanity: Heat Virus'], + locations_dict['Killsanity: Cold Virus'], + locations_dict['Killsanity: Designer'], + }, + "Gaia's Garden Kills": { + locations_dict['Killsanity: Argeby'], + locations_dict['Killsanity: Gelleric'], + locations_dict['Killsanity: Papagun'], + locations_dict['Killsanity: Angler'], + locations_dict['Killsanity: Shokat'], + locations_dict['Killsanity: Behesloth'], + locations_dict['Killsanity: Tiefsee Angler'], + locations_dict['Killsanity: Karotto Fruitseeker'], + locations_dict['Killsanity: Buff Bloomy'], + locations_dict['Killsanity: Toxovolt'], + }, + "So'najiz Temple Kills": { + locations_dict['Killsanity: Jelleric'], + locations_dict['Killsanity: Ocubepus'], + locations_dict['Killsanity: Blue Ray'], + locations_dict['Killsanity: Sir Blobus Starnikus'], + }, + "Zir'vitar Temple Kills": { + locations_dict['Killsanity: Rob0ck'], + locations_dict['Killsanity: Powerplant'], + locations_dict['Killsanity: Ectovolt'], + locations_dict['Killsanity: Plasma Phantom'], + }, + "Sapphire Ridge Kills": { + locations_dict['Killsanity: Sun Beetle'], + locations_dict['Killsanity: Moon Beetle'], + locations_dict['Killsanity: Pandza'], + locations_dict['Killsanity: Aranetarda'], + locations_dict['Killsanity: Twilight Master'], + locations_dict['Killsanity: Pandza Mk. II'], + }, + "Grand Krys'kajo Kills": { + locations_dict['Killsanity: Son of the East'], + locations_dict['Killsanity: Ancient Guardian'], + }, + "Vermillion Tower": { + locations_dict['Killsanity: The Creator'], + }, + "Vermillion Tower Kills": { + locations_dict['Killsanity: The Creator'], + }, + "Azure Archipelago Kills": { + locations_dict['Killsanity: Echinoignis'], + locations_dict['Killsanity: Echinonix'], + locations_dict['Killsanity: Echinofulgur'], + locations_dict['Killsanity: Echinofluctus'], + locations_dict['Killsanity: Salteric'], + locations_dict['Killsanity: Balooneer'], + locations_dict["Killsanity: K'im"], + locations_dict['Killsanity: Trigenbu'], + locations_dict['Killsanity: Son of the Beach'], + }, + "Ku'lero Temple Kills": { + locations_dict['Killsanity: Heat Crystalid'], + locations_dict['Killsanity: Cold Crystalid'], + locations_dict['Killsanity: Shock Crystalid'], + locations_dict['Killsanity: Wave Crystalid'], + locations_dict['Killsanity: Hummagnum'], + locations_dict['Killsanity: Mizree'], + locations_dict['Killsanity: Beearbot'], + locations_dict['Killsanity: Guardian Statue'], + locations_dict['Killsanity: Gynthar'], + locations_dict["Killsanity: Di'orbis"], + }, + "Rhombus Square Kills": { + locations_dict['Killsanity: Tremmy'], + locations_dict['Killsanity: Hillcart'], + locations_dict['Killsanity: The Goatfather'], + }, + "Ba'kii Kum Kills": { + locations_dict['Killsanity: Distillizer'], + }, + "Basin Keep Kills": { + locations_dict['Killsanity: Papaboss the Younger'], + }, } \ No newline at end of file From 8d6d486cda08b90e0cf8244cdec4213edc0cdef4 Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Fri, 24 Jul 2026 23:26:03 -0600 Subject: [PATCH 17/23] finish implementing level condition --- worlds/crosscode/types/condition.py | 23 +++++++++++++++++++++++ worlds/crosscode/util.py | 17 +++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/worlds/crosscode/types/condition.py b/worlds/crosscode/types/condition.py index 7d872ae84bfb..960303d22e9d 100644 --- a/worlds/crosscode/types/condition.py +++ b/worlds/crosscode/types/condition.py @@ -3,9 +3,11 @@ from dataclasses import dataclass, field from BaseClasses import CollectionState +from worlds.crosscode.util import maximum_gap from ..options import ShopReceiveMode from .items import ItemPoolEntry +from .enemies import Enemy class LogicDict(typing.TypedDict): mode: str @@ -20,6 +22,8 @@ class LogicDict(typing.TypedDict): shop_unlock_by_shop_and_id: dict[tuple[str, int], ItemPoolEntry] region_botanics_amounts: dict[str, int] botanics_completion_amount: int + enemies: dict[str, Enemy] + maximum_grind_gap: int class Condition(abc.ABC): @abc.abstractmethod @@ -201,6 +205,25 @@ def satisfied_internal(state: CollectionState): return collected / args["botanics_completion_amount"] >= self.amount return satisfied_internal +@dataclass +class LevelCondition(Condition): + level: int + + def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: + def satisfied_internal(state: CollectionState): + levels = [0 for _ in range(self.level)] + for enemy in args["enemies"].values(): + if ( + enemy.grind_event_name is not None and + enemy.level < self.level and + state.has(enemy.grind_event_name, player) + ): + levels[enemy.level] += 1 + + return maximum_gap(levels) <= args["maximum_grind_gap"] + + return satisfied_internal + class NeverCondition(Condition): def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: return lambda _: False diff --git a/worlds/crosscode/util.py b/worlds/crosscode/util.py index b4aa4d6dcb49..ed1d0f2cd727 100644 --- a/worlds/crosscode/util.py +++ b/worlds/crosscode/util.py @@ -2,6 +2,7 @@ Everyone's favorite part of every python library: miscellaneous utility functions anc classes. """ +import functools import typing K = typing.TypeVar("K") @@ -36,3 +37,19 @@ def __missing__(self, key: K): raise KeyError( key ) ret = self[key] = self.default_factory(key) return ret + +def maximum_gap(counter: list[int]) -> int: + """ + Calculates the maximum number of consecutive elements in a list that are zero. + """ + + # in the tuple, the first element represents the current largest known gap + # and the second element represents the gap that is currently being calculated + def gapfun(t: tuple[int, int], d: int) -> tuple[int, int]: + return (max(t[0], t[1] + 1), t[1] + 1) if not d else (t[0], 0) + + return functools.reduce( + gapfun, + counter, + initial=(0, 0) + )[0] From 5b5a7514270f1fca3e11e27c949ec9aaa41cd1b3 Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Sat, 1 Aug 2026 22:10:47 -0600 Subject: [PATCH 18/23] add more combat-related options --- worlds/crosscode/options.py | 45 ++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/worlds/crosscode/options.py b/worlds/crosscode/options.py index 879feabe7f6c..7b4a452b421e 100644 --- a/worlds/crosscode/options.py +++ b/worlds/crosscode/options.py @@ -4,7 +4,7 @@ from dataclasses import dataclass -from Options import Choice, DefaultOnToggle, NamedRange, OptionGroup, PerGameCommonOptions, Toggle, Range +from Options import Choice, DefaultOnToggle, NamedRange, OptionGroup, OptionSet, PerGameCommonOptions, Toggle, Range # class LogicMode(Choice): # """ @@ -213,6 +213,40 @@ class Killsanity(Toggle): If enabled, killing every enemy is a check. """ +class CombatLogic(OptionSet): + """ + Determines what must be done to consider a combat check in logic. If in doubt, leave this default. + + If player_level is included, then you must have enough enemies in logic to grind to the level in question. + If equipment_level is included, then you must have received equipment of high enough level to take on the check. + """ + + display_name = "Combat Logic" + + default = { + "player_level", + "equipment_level", + } + + valid_keys = { + "player_level", + "equipment_level", + } + +class MaximumGrindGap(Range): + """ + The maximum amount the player can be underleveled to consider checks that require combat in logic. For instance, + if this value is set at 10, then you may be required to fight enemies 10 levels over your current level. + + When player level logic is on, this determines the maximum gap between enemy levels you are willing to grind. + When equipment level logic is on, this determines how close your highest received equipment must be. + """ + + range_start = 5 + range_end = 20 + + display_name = "Maximum Grind Gap" + class Botanity(Toggle): """ If enabled, acquiring all the information about each plant by collecting drops is a location. @@ -577,6 +611,8 @@ class CrossCodeOptions(PerGameCommonOptions): shop_receive_mode: ShopReceiveMode killsanity: Killsanity + allow_booster_grinding: AllowBoosterGrinding + maximum_grind_gap: MaximumGrindGap botanity: Botanity @@ -589,7 +625,6 @@ class CrossCodeOptions(PerGameCommonOptions): progressive_area_unlocks: ProgressiveAreaUnlocks progressive_equipment: ProgressiveEquipment keyrings: Keyrings - allow_booster_grinding: AllowBoosterGrinding chest_reveal: ChestReveal shade_shuffle: ShadeShuffle @@ -636,9 +671,13 @@ class CrossCodeOptions(PerGameCommonOptions): ] ), OptionGroup( - name="Killsanity", + name="Combat", options=[ + AllowBoosterGrinding, Killsanity, + CombatLogic, + AllowBoosterGrinding, + MaximumGrindGap, ] ), OptionGroup( From 18f0019cf5f20b350c2409c581c2e5411a47fd00 Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Sat, 22 Aug 2026 22:12:21 -0600 Subject: [PATCH 19/23] start hooking options and functionality together --- worlds/crosscode/options.py | 15 +++++++++++++-- worlds/crosscode/types/condition.py | 26 ++++++++++++++++++++------ worlds/crosscode/types/world.py | 4 ++++ worlds/crosscode/world.py | 3 +++ worlds/crosscode/world_data.py | 2 ++ 5 files changed, 42 insertions(+), 8 deletions(-) diff --git a/worlds/crosscode/options.py b/worlds/crosscode/options.py index 7b4a452b421e..5182855e63fb 100644 --- a/worlds/crosscode/options.py +++ b/worlds/crosscode/options.py @@ -3,6 +3,7 @@ """ from dataclasses import dataclass +from enum import IntFlag from Options import Choice, DefaultOnToggle, NamedRange, OptionGroup, OptionSet, PerGameCommonOptions, Toggle, Range @@ -221,6 +222,10 @@ class CombatLogic(OptionSet): If equipment_level is included, then you must have received equipment of high enough level to take on the check. """ + class Flag(IntFlag): + PLAYER = 0x1 + EQUIP = 0x2 + display_name = "Combat Logic" default = { @@ -233,6 +238,12 @@ class CombatLogic(OptionSet): "equipment_level", } + def flag(self) -> Flag: + return ( + (CombatLogic.Flag.PLAYER if "player_level" in self.value else CombatLogic.Flag(0)) | + (CombatLogic.Flag.EQUIP if "equipment_level" in self.value else CombatLogic.Flag(0)) + ) + class MaximumGrindGap(Range): """ The maximum amount the player can be underleveled to consider checks that require combat in logic. For instance, @@ -612,6 +623,7 @@ class CrossCodeOptions(PerGameCommonOptions): killsanity: Killsanity allow_booster_grinding: AllowBoosterGrinding + combat_logic: CombatLogic maximum_grind_gap: MaximumGrindGap botanity: Botanity @@ -673,11 +685,10 @@ class CrossCodeOptions(PerGameCommonOptions): OptionGroup( name="Combat", options=[ - AllowBoosterGrinding, Killsanity, CombatLogic, - AllowBoosterGrinding, MaximumGrindGap, + AllowBoosterGrinding, ] ), OptionGroup( diff --git a/worlds/crosscode/types/condition.py b/worlds/crosscode/types/condition.py index 960303d22e9d..64d447cd8b1e 100644 --- a/worlds/crosscode/types/condition.py +++ b/worlds/crosscode/types/condition.py @@ -1,13 +1,16 @@ +from __future__ import annotations import typing import abc from dataclasses import dataclass, field from BaseClasses import CollectionState from worlds.crosscode.util import maximum_gap -from ..options import ShopReceiveMode +from ..options import CombatLogic, ShopReceiveMode from .items import ItemPoolEntry -from .enemies import Enemy + +if typing.TYPE_CHECKING: + from .enemies import Enemy class LogicDict(typing.TypedDict): mode: str @@ -23,6 +26,7 @@ class LogicDict(typing.TypedDict): region_botanics_amounts: dict[str, int] botanics_completion_amount: int enemies: dict[str, Enemy] + combat_logic_flag: CombatLogic.Flag maximum_grind_gap: int class Condition(abc.ABC): @@ -206,11 +210,11 @@ def satisfied_internal(state: CollectionState): return satisfied_internal @dataclass -class LevelCondition(Condition): +class CombatCondition(Condition): level: int def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: - def satisfied_internal(state: CollectionState): + def player_level_satisfied(state: CollectionState): levels = [0 for _ in range(self.level)] for enemy in args["enemies"].values(): if ( @@ -219,10 +223,20 @@ def satisfied_internal(state: CollectionState): state.has(enemy.grind_event_name, player) ): levels[enemy.level] += 1 - return maximum_gap(levels) <= args["maximum_grind_gap"] - return satisfied_internal + def equip_level_satisfied(state: CollectionState): + max(item for item in state.prog_items[player]) + return True + + if args["combat_logic_flag"] == CombatLogic.Flag.PLAYER | CombatLogic.Flag.EQUIP: + return lambda state: equip_level_satisfied(state) and player_level_satisfied(state) + elif args["combat_logic_flag"] == CombatLogic.Flag.PLAYER: + return player_level_satisfied + elif args["combat_logic_flag"] == CombatLogic.Flag.EQUIP: + return equip_level_satisfied + else: + return lambda: True class NeverCondition(Condition): def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: diff --git a/worlds/crosscode/types/world.py b/worlds/crosscode/types/world.py index 7cd7099d1e9f..1dcd06e0250f 100644 --- a/worlds/crosscode/types/world.py +++ b/worlds/crosscode/types/world.py @@ -5,6 +5,7 @@ from .regions import RegionsData from .shops import ShopData from .condition import Condition +from .enemies import Enemy @dataclass class WorldData: @@ -37,6 +38,9 @@ class WorldData: shop_unlock_by_shop: dict[str, ItemPoolEntry] shop_unlock_by_shop_and_id: dict[tuple[str, int], ItemPoolEntry] + # enemies.py + enemies: dict[str, Enemy] + # item_pools.py item_pools_template: dict[str, list[ItemPoolEntry]] item_groups: dict[str, list[ItemData]] diff --git a/worlds/crosscode/world.py b/worlds/crosscode/world.py index 52a00bf5a0cb..d2b932c1b212 100644 --- a/worlds/crosscode/world.py +++ b/worlds/crosscode/world.py @@ -436,6 +436,9 @@ def generate_early(self): "shop_unlock_by_shop_and_id": self.world_data.shop_unlock_by_shop_and_id, "region_botanics_amounts": self.world_data.region_botanics_amounts[self.logic_mode], "botanics_completion_amount": self.options.botanics_completion_amount.value, + "enemies": self.world_data.enemies, + "combat_logic_flag": self.options.combat_logic.flag(), + "maximum_grind_gap": self.options.maximum_grind_gap.value, } # Universal Tracker support diff --git a/worlds/crosscode/world_data.py b/worlds/crosscode/world_data.py index 957814de4e66..403d0b9934f3 100644 --- a/worlds/crosscode/world_data.py +++ b/worlds/crosscode/world_data.py @@ -9,6 +9,7 @@ from .shops import shop_dict, per_shop_locations, global_shop_locations, shop_unlock_by_id, shop_unlock_by_shop, \ shop_unlock_by_shop_and_id from .locations import locations_dict, events_dict, locked_locations, pool_locations, location_groups +from .enemies import enemies from .item_pools import item_pools_template, item_groups from .prog_items import progressive_chains, progressive_items from .vars import variable_definitions @@ -33,6 +34,7 @@ shop_unlock_by_id=shop_unlock_by_id, shop_unlock_by_shop=shop_unlock_by_shop, shop_unlock_by_shop_and_id=shop_unlock_by_shop_and_id, + enemies=enemies, item_pools_template=item_pools_template, item_groups=item_groups, progressive_chains=progressive_chains, From de411e81f6a9b5bc7cb260442ea60cc385677736 Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Sat, 22 Aug 2026 22:51:01 -0600 Subject: [PATCH 20/23] remove logicdict; replace with world reference --- worlds/crosscode/logic.py | 10 ++-- worlds/crosscode/types/condition.py | 82 +++++++++++++---------------- worlds/crosscode/world.py | 44 ++++++---------- 3 files changed, 60 insertions(+), 76 deletions(-) diff --git a/worlds/crosscode/logic.py b/worlds/crosscode/logic.py index cf3a1292a926..de7ce9e252c6 100644 --- a/worlds/crosscode/logic.py +++ b/worlds/crosscode/logic.py @@ -2,19 +2,23 @@ This module contains various logic functions """ +from __future__ import annotations import typing from BaseClasses import CollectionState -from .types.condition import Condition, LogicDict +from .types.condition import Condition + +if typing.TYPE_CHECKING: + from .world import CrossCodeWorld def condition_satisfied( player: int, conditions: list[Condition], location: int | None, - cond_args: LogicDict + world: CrossCodeWorld ) -> typing.Callable[[CollectionState], bool]: """ Factory function. Return value is a rule that checks whether all the conditions are satisfied. """ - callbacks = [c.satisfied(player, location, cond_args) for c in conditions] + callbacks = [c.satisfied(player, location, world) for c in conditions] return lambda state: all(map(lambda x: x(state), callbacks)) diff --git a/worlds/crosscode/types/condition.py b/worlds/crosscode/types/condition.py index 7d872ae84bfb..cd7cbc338f1d 100644 --- a/worlds/crosscode/types/condition.py +++ b/worlds/crosscode/types/condition.py @@ -1,3 +1,4 @@ +from __future__ import annotations import typing import abc from dataclasses import dataclass, field @@ -7,23 +8,12 @@ from .items import ItemPoolEntry -class LogicDict(typing.TypedDict): - mode: str - variables: dict[str, list[str]] - variable_definitions: dict[str, dict[str, list["Condition"]]] - keyrings: set[str] - item_progressive_replacements: dict[str, list[tuple[str, int]]] - chest_clearance_levels: dict[int, str] - shop_receive_mode: int | None - shop_unlock_by_id: dict[int, ItemPoolEntry] - shop_unlock_by_shop: dict[str, ItemPoolEntry] - shop_unlock_by_shop_and_id: dict[tuple[str, int], ItemPoolEntry] - region_botanics_amounts: dict[str, int] - botanics_completion_amount: int +if typing.TYPE_CHECKING: + from ..world import CrossCodeWorld class Condition(abc.ABC): @abc.abstractmethod - def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: + def satisfied(self, player: int, location: int | None, world: CrossCodeWorld) -> typing.Callable[[CollectionState], bool]: pass @dataclass @@ -31,12 +21,12 @@ class ItemCondition(Condition): item_name: str amount: int = 1 - def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: + def satisfied(self, player: int, location: int | None, world: CrossCodeWorld) -> typing.Callable[[CollectionState], bool]: target = self.amount - if self.item_name in args["keyrings"]: + if self.item_name in world.keyrings: target = 1 - replacements = args["item_progressive_replacements"] + replacements = world.pools.item_progressive_replacements if self.item_name in replacements: def callback(state: CollectionState) -> bool: @@ -57,7 +47,7 @@ class QuestCondition(Condition): def __post_init__(self): self.event_name = f"{self.quest_name} (Event)" - def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: + def satisfied(self, player: int, location: int | None, world: CrossCodeWorld) -> typing.Callable[[CollectionState], bool]: return lambda state: state.has(self.event_name, player) @dataclass @@ -68,7 +58,7 @@ class LocationCondition(Condition): def __post_init__(self): self.event_name = f"{self.location_name} (Event)" - def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: + def satisfied(self, player: int, location: int | None, world: CrossCodeWorld) -> typing.Callable[[CollectionState], bool]: return lambda state: state.has(self.event_name, player) @dataclass @@ -76,13 +66,13 @@ class RegionCondition(Condition): target_mode: typing.Optional[str] region_name: str - def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: + def satisfied(self, player: int, location: int | None, world: CrossCodeWorld) -> typing.Callable[[CollectionState], bool]: # target_mode == None means that it matches in all modes. # so if target_mode == None, check if we can reach that region. # else, if the target mode matches, also check if we can reach that region. # otherwise, if the target mode does not match, return true (assume that it's being ANDed with other conditions) - mode: str = args["mode"] + mode: str = world.logic_mode if self.target_mode is None or mode == self.target_mode: return lambda state: state.can_reach_region(self.region_name, player) @@ -90,7 +80,7 @@ def satisfied(self, player: int, location: int | None, args: LogicDict) -> typin @dataclass class AnyElementCondition(Condition): - def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: + def satisfied(self, player: int, location: int | None, world: CrossCodeWorld) -> typing.Callable[[CollectionState], bool]: return lambda state: any([ state.has("Heat", player), state.has("Cold", player), @@ -102,25 +92,25 @@ def satisfied(self, player: int, location: int | None, args: LogicDict) -> typin class OrCondition(Condition): subconditions: list[Condition] - def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: - callbacks = [x.satisfied(player, location, args) for x in self.subconditions] + def satisfied(self, player: int, location: int | None, world: CrossCodeWorld) -> typing.Callable[[CollectionState], bool]: + callbacks = [x.satisfied(player, location, world) for x in self.subconditions] return lambda state: any(map(lambda x: x(state), callbacks)) @dataclass class AndCondition(Condition): subconditions: list[Condition] - def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: - callbacks = [x.satisfied(player, location, args) for x in self.subconditions] + def satisfied(self, player: int, location: int | None, world: CrossCodeWorld) -> typing.Callable[[CollectionState], bool]: + callbacks = [x.satisfied(player, location, world) for x in self.subconditions] return lambda state: all(map(lambda x: x(state), callbacks)) @dataclass class VariableCondition(Condition): name: str - def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: - variables = args["variables"] - variable_definitions = args["variable_definitions"] + def satisfied(self, player: int, location: int | None, world: CrossCodeWorld) -> typing.Callable[[CollectionState], bool]: + variables = world.variables + variable_definitions = world.world_data.variable_definitions if self.name not in variables: return lambda _: True @@ -128,7 +118,7 @@ def satisfied(self, player: int, location: int | None, args: LogicDict) -> typin callbacks = sum( [ [ - x.satisfied(player, location, args) + x.satisfied(player, location, world) for x in variable_definitions[self.name][value] ] for value in variables[self.name] ], @@ -143,8 +133,8 @@ class VariableEntryCondition(Condition): value: str desired: bool - def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: - valid = (self.value in args["variables"][self.name]) == self.desired + def satisfied(self, player: int, location: int | None, world: CrossCodeWorld) -> typing.Callable[[CollectionState], bool]: + valid = (self.value in world.variables[self.name]) == self.desired return lambda _: valid @dataclass @@ -157,8 +147,8 @@ class ChestKeyCondition(Condition): "Gold": "Radiant Key", } - def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: - chest_levels = args["chest_clearance_levels"] + def satisfied(self, player: int, location: int | None, world: CrossCodeWorld) -> typing.Callable[[CollectionState], bool]: + chest_levels = world.chest_clearance_levels if location is None: raise RuntimeError("An event cannot have a chest key condition") @@ -175,34 +165,34 @@ class ShopSlotCondition(Condition): shop_name: str item_id: int - def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: - if args["shop_receive_mode"] is None: + def satisfied(self, player: int, location: int | None, world: CrossCodeWorld) -> typing.Callable[[CollectionState], bool]: + if world.shop_receive_mode is None: return lambda _: True - if args["shop_receive_mode"] == ShopReceiveMode.option_per_item_type: - return lambda state: state.has(args["shop_unlock_by_id"][self.item_id].item.name, player) - if args["shop_receive_mode"] == ShopReceiveMode.option_per_shop: - return lambda state: state.has(args["shop_unlock_by_shop"][self.shop_name].item.name, player) - if args["shop_receive_mode"] == ShopReceiveMode.option_per_slot: - return lambda state: state.has(args["shop_unlock_by_shop_and_id"][self.shop_name, self.item_id].item.name, player) + if world.shop_receive_mode == ShopReceiveMode.option_per_item_type: + return lambda state: state.has(world.world_data.shop_unlock_by_id[self.item_id].item.name, player) + if world.shop_receive_mode == ShopReceiveMode.option_per_shop: + return lambda state: state.has(world.world_data.shop_unlock_by_shop[self.shop_name].item.name, player) + if world.shop_receive_mode == ShopReceiveMode.option_per_slot: + return lambda state: state.has(world.world_data.shop_unlock_by_shop_and_id[self.shop_name, self.item_id].item.name, player) return lambda _: True @dataclass class BotanicsCompletionCondition(Condition): amount: float - def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: + def satisfied(self, player: int, location: int | None, world: CrossCodeWorld) -> typing.Callable[[CollectionState], bool]: def satisfied_internal(state: CollectionState): collected = sum([ amount - for region, amount in args["region_botanics_amounts"].items() + for region, amount in world.world_data.region_botanics_amounts[world.logic_mode].items() if state.can_reach_region(region, player) ]) - return collected / args["botanics_completion_amount"] >= self.amount + return collected / world.options.botanics_completion_amount >= self.amount return satisfied_internal class NeverCondition(Condition): - def satisfied(self, player: int, location: int | None, args: LogicDict) -> typing.Callable[[CollectionState], bool]: + def satisfied(self, player: int, location: int | None, world: CrossCodeWorld) -> typing.Callable[[CollectionState], bool]: return lambda _: False __all__ = [ diff --git a/worlds/crosscode/world.py b/worlds/crosscode/world.py index 8b099984c515..0484be060276 100644 --- a/worlds/crosscode/world.py +++ b/worlds/crosscode/world.py @@ -1,5 +1,4 @@ """ - This module contains the world class for CrossCode. """ @@ -21,7 +20,7 @@ from .types.items import ItemData, CrossCodeItem from .types.locations import CrossCodeLocation, LocationData -from .types.condition import LogicDict, Condition, LocationCondition +from .types.condition import Condition, LocationCondition from .types.world import WorldData from .types.regions import RegionsData from .types.metadata import IncludeOptions @@ -97,6 +96,10 @@ class CrossCodeWorld(World): rhombus_hub_unlock: bool + keyrings: set[str] + shop_receive_mode: int | None + chest_clearance_levels: dict[int, str] + pre_fill_specific_dungeons_names: dict[str, set[str]] pre_fill_any_dungeon_names: set[str] @@ -106,8 +109,6 @@ class CrossCodeWorld(World): dungeon_location_list: dict[str, set[CrossCodeLocation]] dungeon_areas: typing.ClassVar[set[str]] = {"cold-dng", "heat-dng", "shock-dng", "wave-dng", "tree-dng", "final-dng"} - logic_dict: LogicDict - location_events: dict[str, Location] variables: dict[str, list[str]] @@ -421,27 +422,16 @@ def generate_early(self): self.pre_fill_any_dungeon_names ) - self.logic_dict: LogicDict = { - "mode": self.logic_mode, - "variables": self.variables, - "variable_definitions": self.world_data.variable_definitions, - "keyrings": self.world_data.keyring_items if self.options.keyrings.value else set(), - "item_progressive_replacements": self.pools.item_progressive_replacements, - "chest_clearance_levels": {}, - "shop_receive_mode": self.options.shop_receive_mode.value if self.options.shop_rando.value else None, - "shop_unlock_by_id": self.world_data.shop_unlock_by_id, - "shop_unlock_by_shop": self.world_data.shop_unlock_by_shop, - "shop_unlock_by_shop_and_id": self.world_data.shop_unlock_by_shop_and_id, - "region_botanics_amounts": self.world_data.region_botanics_amounts[self.logic_mode], - "botanics_completion_amount": self.options.botanics_completion_amount.value, - } + self.keyrings = self.world_data.keyring_items if self.options.keyrings.value else set() + self.shop_receive_mode = self.options.shop_receive_mode.value if self.options.shop_rando.value else None + self.chest_clearance_levels = {} # Universal Tracker support # Anything that is generated in a non-standard fashion on my end has to be brought back into scope here from slot data. if hasattr(self.multiworld, "re_gen_passthrough"): slot_data: SlotData = self.multiworld.re_gen_passthrough["CrossCode"] # Reinterpret the JSON chest clearance levels dict (a string -> string mapping) as an int -> int mapping instead. - self.logic_dict["chest_clearance_levels"] = {int(combo_id): clearance for combo_id, clearance in slot_data["options"]["chestClearanceLevels"].items()} + self.chest_clearance_levels = {int(combo_id): clearance for combo_id, clearance in slot_data["options"]["chestClearanceLevels"].items()} @classmethod def create_group(cls, multiworld: "MultiWorld", new_player_id: int, players: set[int]) -> World: @@ -478,7 +468,7 @@ def add_location(self, data: LocationData, region: Region): cum_weights=self._chest_lock_weights )[0] - self.logic_dict["chest_clearance_levels"][data.code] = clearance + self.chest_clearance_levels[data.code] = clearance def create_shops(self): # don't filter the shop pool - the regions must always exist to prevent generation errors @@ -490,7 +480,7 @@ def create_shops(self): self.region_dict[from_region].connect( region, f"{from_region} => {shop_name}", - condition_satisfied(self.player, shop.access.cond, None, self.logic_dict) if shop.access.cond else None + condition_satisfied(self.player, shop.access.cond, None, self) if shop.access.cond else None ) if self.options.shop_send_mode == ShopSendMode.option_per_slot: @@ -514,7 +504,7 @@ def create_regions(self): self.region_dict[conn.region_from].connect( self.region_dict[conn.region_to], f"{conn.region_from} => {conn.region_to}", - condition_satisfied(self.player, conn.cond, None, self.logic_dict) if conn.cond is not None else None + condition_satisfied(self.player, conn.cond, None, self) if conn.cond is not None else None ) self.create_event_conditions(conn.cond) @@ -562,7 +552,7 @@ def create_regions(self): self.player, goal.condition if goal.condition is not None else [], None, - self.logic_dict + self ) ) self.multiworld.completion_condition[self.player] = lambda state: state.has("Victory", self.player) @@ -653,7 +643,7 @@ def set_rules(self): if not isinstance(loc, CrossCodeLocation): continue if loc.data.access.cond is not None: - add_rule(loc, condition_satisfied(self.player, loc.data.access.cond, loc.data.code, self.logic_dict)) + add_rule(loc, condition_satisfied(self.player, loc.data.access.cond, loc.data.code, self)) def get_pre_fill_items(self) -> list[Item]: pre_fill_items = self.pre_fill_any_dungeon.copy() @@ -758,7 +748,7 @@ def priority(item: CrossCodeItem) -> int: def extend_hint_information(self, hint_data: dict[int, dict[int, str]]): ours = hint_data.setdefault(self.player, {}) - for loc, clearance in self.logic_dict["chest_clearance_levels"].items(): + for loc, clearance in self.chest_clearance_levels.items(): ours[loc] = clearance def fill_slot_data(self) -> SlotData: @@ -793,7 +783,7 @@ def fill_slot_data(self) -> SlotData: "meteorPassage": bool(self.options.vw_meteor_passage.value), "closedGaia": self.options.closed_gaia.value, "vtSkip": bool(self.options.vt_skip.value), - "keyrings": [self.world_data.single_items_dict[name].item_id for name in self.logic_dict["keyrings"]], + "keyrings": [self.world_data.single_items_dict[name].item_id for name in self.keyrings], "chestReveal": bool(self.options.chest_reveal.value), "allowBoosterGrinding": bool(self.options.allow_booster_grinding), "questRando": bool(self.options.quest_rando.value), @@ -804,7 +794,7 @@ def fill_slot_data(self) -> SlotData: "shopSendMode": shop_send_mode_string, "shopReceiveMode": shop_receive_mode_string, "shopDialogHints": bool(self.options.shop_dialog_hints.value), - "chestClearanceLevels": self.logic_dict["chest_clearance_levels"], + "chestClearanceLevels": self.chest_clearance_levels, "botanicsCompletionAmount": self.options.botanics_completion_amount.value, } } From 8cb70793164acdb5ec1ece414a5d2bcb5a5d40da Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Sun, 23 Aug 2026 00:41:38 -0600 Subject: [PATCH 21/23] rename killsanity -> monster fibula --- worlds/crosscode/codegen/gen.py | 2 +- worlds/crosscode/codegen/lists.py | 32 +- worlds/crosscode/locations.py | 1048 ++++++++++++++--------------- worlds/crosscode/options.py | 8 +- 4 files changed, 545 insertions(+), 545 deletions(-) diff --git a/worlds/crosscode/codegen/gen.py b/worlds/crosscode/codegen/gen.py index 7aad1f96e55e..c30b67ffa858 100644 --- a/worlds/crosscode/codegen/gen.py +++ b/worlds/crosscode/codegen/gen.py @@ -272,7 +272,7 @@ def generate_mod_files(self): }, }, "enemies": { - enemy.internal_name: { "kill": self.lists.locations_data[f"Killsanity: {enemy.name}"].code } + enemy.internal_name: { "kill": self.lists.locations_data[f"Monster Fibula: {enemy.name}"].code } for enemy in self.lists.enemies.values() }, "botanics": self.lists.botanics_internal_names_to_ids, diff --git a/worlds/crosscode/codegen/lists.py b/worlds/crosscode/codegen/lists.py index 2c04e56c72a4..2bdc1ddeca79 100644 --- a/worlds/crosscode/codegen/lists.py +++ b/worlds/crosscode/codegen/lists.py @@ -598,18 +598,7 @@ def __add_enemy(self, raw: dict[str, typing.Any]): else: grind_event = None - enemy = Enemy( - name=name, - area=area, - internal_name=internal_name, - level=level, - first_encounter_event_name=first_encounter_event.name, - grind_event_name=grind_event.name if grind_event is not None else None - ) - - self.enemies[name] = enemy - - kill_loc_name = f"Killsanity: {name}" + kill_loc_name = f"Monster Fibula: {name}" kill_loc_id = self.__get_or_allocate_location_id(kill_loc_name) kill_location = LocationData( name=kill_loc_name, @@ -624,16 +613,27 @@ def __add_enemy(self, raw: dict[str, typing.Any]): metadata=metadata | { "kill": True }, ) + enemy = Enemy( + name=name, + area=area, + internal_name=internal_name, + level=level, + first_encounter_event_name=first_encounter_event.name, + grind_event_name=grind_event.name if grind_event is not None else None + ) + + self.locations_data[kill_loc_name] = kill_location + self.pool_locations.append(kill_location) + self.location_groups["Monster Defeats"].append(kill_location) + if area != None: try: self.location_groups[area_name].append(kill_location) - self.location_groups[f"{area_name} Kills"].append(kill_location) + self.location_groups[f"{area_name} Monster Defeats"].append(kill_location) except KeyError: print(f"Cannot add location '{name}' in area '{area}'") - self.locations_data[kill_loc_name] = kill_location - self.pool_locations.append(kill_location) - self.location_groups["Kills"].append(kill_location) + self.enemies[name] = enemy def __add_enemies(self, raw: dict[str, dict[str, typing.Any]]): for enemy in raw.values(): diff --git a/worlds/crosscode/locations.py b/worlds/crosscode/locations.py index 661f451b0c5b..501bb5f17b64 100644 --- a/worlds/crosscode/locations.py +++ b/worlds/crosscode/locations.py @@ -1018,107 +1018,107 @@ LocationData(code=3235825005, name='Botanics: Beta Keen Sprout', area='beach', metadata={'botanics': True, 'dlc': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), LocationData(code=3235825006, name='Botanics: Alpha Fossil Stone', area='beach', metadata={'botanics': True, 'dlc': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), LocationData(code=3235825007, name='Botanics: Beta Fossil Stone', area='beach', metadata={'botanics': True, 'dlc': True}, access=AccessInfo(region={'open': 'openDLC_Beach'})), - LocationData(code=3235825012, name='Killsanity: Hedgehag', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Hedgehag (Event)', amount=1)])), - LocationData(code=3235825013, name="Killsanity: Rockin' Hillkat", area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: Rockin' Hillkat (Event)", amount=1)])), - LocationData(code=3235825014, name='Killsanity: Mad Bovine', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Mad Bovine (Event)', amount=1)])), - LocationData(code=3235825015, name='Killsanity: Old Hedgehag', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Old Hedgehag (Event)', amount=1)])), - LocationData(code=3235825016, name="Killsanity: Flamin' Hillkat", area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: Flamin' Hillkat (Event)", amount=1)])), - LocationData(code=3235825017, name='Killsanity: Red Eyed Bovine', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Red Eyed Bovine (Event)', amount=1)])), - LocationData(code=3235825018, name='Killsanity: Young Frobbit', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Young Frobbit (Event)', amount=1)])), - LocationData(code=3235825019, name='Killsanity: White Frobbit', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: White Frobbit (Event)', amount=1)])), - LocationData(code=3235825020, name='Killsanity: Seafly', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Seafly (Event)', amount=1)])), - LocationData(code=3235825021, name='Killsanity: Pengpeng', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Pengpeng (Event)', amount=1)])), - LocationData(code=3235825022, name='Killsanity: Horny Goat', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Horny Goat (Event)', amount=1)])), - LocationData(code=3235825023, name='Killsanity: Karotto', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Karotto (Event)', amount=1)])), - LocationData(code=3235825024, name='Killsanity: Fleazer', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Fleazer (Event)', amount=1)])), - LocationData(code=3235825025, name='Killsanity: Carritrich', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Carritrich (Event)', amount=1)])), - LocationData(code=3235825026, name='Killsanity: Kamikatze', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Kamikatze (Event)', amount=1)])), - LocationData(code=3235825027, name='Killsanity: Digmo', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Digmo (Event)', amount=1)])), - LocationData(code=3235825028, name='Killsanity: Pinceron', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Pinceron (Event)', amount=1)])), - LocationData(code=3235825029, name='Killsanity: Sharkster', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Sharkster (Event)', amount=1)])), - LocationData(code=3235825030, name='Killsanity: Vulturbine', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Vulturbine (Event)', amount=1)])), - LocationData(code=3235825031, name='Killsanity: Drillertoise', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Drillertoise (Event)', amount=1)])), - LocationData(code=3235825032, name='Killsanity: Tim', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Tim (Event)', amount=1)])), - LocationData(code=3235825033, name='Killsanity: Boss Pincer', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Boss Pincer (Event)', amount=1)])), - LocationData(code=3235825034, name='Killsanity: Trijelly', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Trijelly (Event)', amount=1)])), - LocationData(code=3235825035, name='Killsanity: Pada Moth', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Pada Moth (Event)', amount=1)])), - LocationData(code=3235825036, name='Killsanity: Darth Moth', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Darth Moth (Event)', amount=1)])), - LocationData(code=3235825037, name='Killsanity: Magmanizer', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Magmanizer (Event)', amount=1)])), - LocationData(code=3235825038, name='Killsanity: Radical Hedgehag', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Radical Hedgehag (Event)', amount=1)])), - LocationData(code=3235825039, name="Killsanity: Chillin' Hillkat", area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: Chillin' Hillkat (Event)", amount=1)])), - LocationData(code=3235825040, name='Killsanity: Fallfly', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Fallfly (Event)', amount=1)])), - LocationData(code=3235825041, name='Killsanity: Ivory Bovine', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Ivory Bovine (Event)', amount=1)])), - LocationData(code=3235825042, name='Killsanity: Neutral Virus', area='arid', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Neutral Virus (Event)', amount=1)])), - LocationData(code=3235825043, name='Killsanity: Heat Virus', area='arid', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Heat Virus (Event)', amount=1)])), - LocationData(code=3235825044, name='Killsanity: Cold Virus', area='arid', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Cold Virus (Event)', amount=1)])), - LocationData(code=3235825045, name='Killsanity: Argeby', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Argeby (Event)', amount=1)])), - LocationData(code=3235825046, name='Killsanity: Gelleric', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Gelleric (Event)', amount=1)])), - LocationData(code=3235825047, name='Killsanity: Papagun', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Papagun (Event)', amount=1)])), - LocationData(code=3235825048, name='Killsanity: Angler', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Angler (Event)', amount=1)])), - LocationData(code=3235825049, name='Killsanity: Shokat', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Shokat (Event)', amount=1)])), - LocationData(code=3235825050, name='Killsanity: Behesloth', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Behesloth (Event)', amount=1)])), - LocationData(code=3235825051, name='Killsanity: Jelleric', area='wave-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Jelleric (Event)', amount=1)])), - LocationData(code=3235825052, name='Killsanity: Ocubepus', area='wave-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Ocubepus (Event)', amount=1)])), - LocationData(code=3235825053, name='Killsanity: Blue Ray', area='wave-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Blue Ray (Event)', amount=1)])), - LocationData(code=3235825054, name='Killsanity: Rob0ck', area='shock-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Rob0ck (Event)', amount=1)])), - LocationData(code=3235825055, name='Killsanity: Powerplant', area='shock-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Powerplant (Event)', amount=1)])), - LocationData(code=3235825056, name='Killsanity: Ectovolt', area='shock-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Ectovolt (Event)', amount=1)])), - LocationData(code=3235825057, name='Killsanity: Sun Beetle', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Sun Beetle (Event)', amount=1)])), - LocationData(code=3235825058, name='Killsanity: Moon Beetle', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Moon Beetle (Event)', amount=1)])), - LocationData(code=3235825059, name='Killsanity: Pandza', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Pandza (Event)', amount=1)])), - LocationData(code=3235825060, name='Killsanity: Aranetarda', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Aranetarda (Event)', amount=1)])), - LocationData(code=3235825061, name='Killsanity: Hillkat Bandleader', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Hillkat Bandleader (Event)', amount=1)])), - LocationData(code=3235825062, name='Killsanity: Blue Hedgehag', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Blue Hedgehag (Event)', amount=1)])), - LocationData(code=3235825063, name='Killsanity: Infected Digmo', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Infected Digmo (Event)', amount=1)])), - LocationData(code=3235825064, name='Killsanity: Peng King Dakara', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Peng King Dakara (Event)', amount=1)])), - LocationData(code=3235825065, name='Killsanity: X01 Driller H.F.S.', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: X01 Driller H.F.S. (Event)', amount=1)])), - LocationData(code=3235825066, name="Killsanity: Ti'im", area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: Ti'im (Event)", amount=1)])), - LocationData(code=3235825067, name='Killsanity: Cursed Sharkster', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Cursed Sharkster (Event)', amount=1)])), - LocationData(code=3235825068, name="Killsanity: Pinzo'jrahrrrn", area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: Pinzo'jrahrrrn (Event)", amount=1)])), - LocationData(code=3235825069, name='Killsanity: Master Magmoth', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Master Magmoth (Event)', amount=1)])), - LocationData(code=3235825070, name='Killsanity: Guard Billston', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Guard Billston (Event)', amount=1)])), - LocationData(code=3235825071, name='Killsanity: Hologram Frobbit', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Hologram Frobbit (Event)', amount=1)])), - LocationData(code=3235825072, name='Killsanity: Smelter Digmo', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Smelter Digmo (Event)', amount=1)])), - LocationData(code=3235825073, name='Killsanity: Blazehoof', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Blazehoof (Event)', amount=1)])), - LocationData(code=3235825074, name='Killsanity: Plasma Phantom', area='shock-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Plasma Phantom (Event)', amount=1)])), - LocationData(code=3235825075, name='Killsanity: Sir Blobus Starnikus', area='wave-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Sir Blobus Starnikus (Event)', amount=1)])), - LocationData(code=3235825076, name='Killsanity: Tiefsee Angler', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Tiefsee Angler (Event)', amount=1)])), - LocationData(code=3235825077, name='Killsanity: Son of the East', area='tree-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Son of the East (Event)', amount=1)])), - LocationData(code=3235825078, name='Killsanity: Ancient Guardian', area='tree-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Ancient Guardian (Event)', amount=1)])), - LocationData(code=3235825079, name='Killsanity: Karotto Fruitseeker', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Karotto Fruitseeker (Event)', amount=1)])), - LocationData(code=3235825080, name='Killsanity: Buff Bloomy', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Buff Bloomy (Event)', amount=1)])), - LocationData(code=3235825081, name='Killsanity: Twilight Master', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Twilight Master (Event)', amount=1)])), - LocationData(code=3235825082, name='Killsanity: King Kaktorro', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: King Kaktorro (Event)', amount=1)])), - LocationData(code=3235825083, name="Killsanity: DON'T USE THIS", area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: DON'T USE THIS (Event)", amount=1)])), - LocationData(code=3235825084, name='Killsanity: Designer', area='arid', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Designer (Event)', amount=1)])), - LocationData(code=3235825085, name='Killsanity: The Creator', area='arid-dng-2', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: The Creator (Event)', amount=1)])), - LocationData(code=3235825086, name='Killsanity: Pandza Mk. II', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Pandza Mk. II (Event)', amount=1)])), - LocationData(code=3235825087, name='Killsanity: Echinoignis', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Echinoignis (Event)', amount=1)])), - LocationData(code=3235825088, name='Killsanity: Echinonix', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Echinonix (Event)', amount=1)])), - LocationData(code=3235825089, name='Killsanity: Echinofulgur', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Echinofulgur (Event)', amount=1)])), - LocationData(code=3235825090, name='Killsanity: Echinofluctus', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Echinofluctus (Event)', amount=1)])), - LocationData(code=3235825091, name='Killsanity: Salteric', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Salteric (Event)', amount=1)])), - LocationData(code=3235825092, name='Killsanity: Balooneer', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Balooneer (Event)', amount=1)])), - LocationData(code=3235825093, name="Killsanity: K'im", area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: K'im (Event)", amount=1)])), - LocationData(code=3235825094, name='Killsanity: Trigenbu', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Trigenbu (Event)', amount=1)])), - LocationData(code=3235825095, name='Killsanity: Heat Crystalid', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Heat Crystalid (Event)', amount=1)])), - LocationData(code=3235825096, name='Killsanity: Cold Crystalid', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Cold Crystalid (Event)', amount=1)])), - LocationData(code=3235825097, name='Killsanity: Shock Crystalid', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Shock Crystalid (Event)', amount=1)])), - LocationData(code=3235825098, name='Killsanity: Wave Crystalid', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Wave Crystalid (Event)', amount=1)])), - LocationData(code=3235825099, name='Killsanity: Hummagnum', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Hummagnum (Event)', amount=1)])), - LocationData(code=3235825100, name='Killsanity: Mizree', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Mizree (Event)', amount=1)])), - LocationData(code=3235825101, name='Killsanity: Beearbot', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Beearbot (Event)', amount=1)])), - LocationData(code=3235825102, name='Killsanity: Illegal Coordinator', area='autumn-area', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Illegal Coordinator (Event)', amount=1)])), - LocationData(code=3235825103, name='Killsanity: Tremmy', area='rhombus-sqr', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Tremmy (Event)', amount=1)])), - LocationData(code=3235825104, name='Killsanity: Distillizer', area='heat-village', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Distillizer (Event)', amount=1)])), - LocationData(code=3235825105, name='Killsanity: Toxovolt', area='jungle', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Toxovolt (Event)', amount=1)])), - LocationData(code=3235825106, name='Killsanity: Papaboss the Younger', area='jungle-city', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Papaboss the Younger (Event)', amount=1)])), - LocationData(code=3235825107, name='Killsanity: Hillcart', area='rhombus-sqr', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Hillcart (Event)', amount=1)])), - LocationData(code=3235825108, name='Killsanity: The Goatfather', area='rhombus-sqr', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: The Goatfather (Event)', amount=1)])), - LocationData(code=3235825109, name='Killsanity: Guardian Statue', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Guardian Statue (Event)', amount=1)])), - LocationData(code=3235825110, name='Killsanity: Gynthar', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Gynthar (Event)', amount=1)])), - LocationData(code=3235825111, name="Killsanity: Di'orbis", area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: Di'orbis (Event)", amount=1)])), - LocationData(code=3235825112, name='Killsanity: Son of the Beach', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Son of the Beach (Event)', amount=1)])), + LocationData(code=3235825113, name='Monster Fibula: Hedgehag', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Hedgehag (Event)', amount=1)])), + LocationData(code=3235825114, name="Monster Fibula: Rockin' Hillkat", area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: Rockin' Hillkat (Event)", amount=1)])), + LocationData(code=3235825115, name='Monster Fibula: Mad Bovine', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Mad Bovine (Event)', amount=1)])), + LocationData(code=3235825116, name='Monster Fibula: Old Hedgehag', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Old Hedgehag (Event)', amount=1)])), + LocationData(code=3235825117, name="Monster Fibula: Flamin' Hillkat", area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: Flamin' Hillkat (Event)", amount=1)])), + LocationData(code=3235825118, name='Monster Fibula: Red Eyed Bovine', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Red Eyed Bovine (Event)', amount=1)])), + LocationData(code=3235825119, name='Monster Fibula: Young Frobbit', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Young Frobbit (Event)', amount=1)])), + LocationData(code=3235825120, name='Monster Fibula: White Frobbit', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: White Frobbit (Event)', amount=1)])), + LocationData(code=3235825121, name='Monster Fibula: Seafly', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Seafly (Event)', amount=1)])), + LocationData(code=3235825122, name='Monster Fibula: Pengpeng', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Pengpeng (Event)', amount=1)])), + LocationData(code=3235825123, name='Monster Fibula: Horny Goat', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Horny Goat (Event)', amount=1)])), + LocationData(code=3235825124, name='Monster Fibula: Karotto', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Karotto (Event)', amount=1)])), + LocationData(code=3235825125, name='Monster Fibula: Fleazer', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Fleazer (Event)', amount=1)])), + LocationData(code=3235825126, name='Monster Fibula: Carritrich', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Carritrich (Event)', amount=1)])), + LocationData(code=3235825127, name='Monster Fibula: Kamikatze', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Kamikatze (Event)', amount=1)])), + LocationData(code=3235825128, name='Monster Fibula: Digmo', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Digmo (Event)', amount=1)])), + LocationData(code=3235825129, name='Monster Fibula: Pinceron', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Pinceron (Event)', amount=1)])), + LocationData(code=3235825130, name='Monster Fibula: Sharkster', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Sharkster (Event)', amount=1)])), + LocationData(code=3235825131, name='Monster Fibula: Vulturbine', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Vulturbine (Event)', amount=1)])), + LocationData(code=3235825132, name='Monster Fibula: Drillertoise', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Drillertoise (Event)', amount=1)])), + LocationData(code=3235825133, name='Monster Fibula: Tim', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Tim (Event)', amount=1)])), + LocationData(code=3235825134, name='Monster Fibula: Boss Pincer', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Boss Pincer (Event)', amount=1)])), + LocationData(code=3235825135, name='Monster Fibula: Trijelly', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Trijelly (Event)', amount=1)])), + LocationData(code=3235825136, name='Monster Fibula: Pada Moth', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Pada Moth (Event)', amount=1)])), + LocationData(code=3235825137, name='Monster Fibula: Darth Moth', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Darth Moth (Event)', amount=1)])), + LocationData(code=3235825138, name='Monster Fibula: Magmanizer', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Magmanizer (Event)', amount=1)])), + LocationData(code=3235825139, name='Monster Fibula: Radical Hedgehag', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Radical Hedgehag (Event)', amount=1)])), + LocationData(code=3235825140, name="Monster Fibula: Chillin' Hillkat", area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: Chillin' Hillkat (Event)", amount=1)])), + LocationData(code=3235825141, name='Monster Fibula: Fallfly', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Fallfly (Event)', amount=1)])), + LocationData(code=3235825142, name='Monster Fibula: Ivory Bovine', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Ivory Bovine (Event)', amount=1)])), + LocationData(code=3235825143, name='Monster Fibula: Neutral Virus', area='arid', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Neutral Virus (Event)', amount=1)])), + LocationData(code=3235825144, name='Monster Fibula: Heat Virus', area='arid', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Heat Virus (Event)', amount=1)])), + LocationData(code=3235825145, name='Monster Fibula: Cold Virus', area='arid', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Cold Virus (Event)', amount=1)])), + LocationData(code=3235825146, name='Monster Fibula: Argeby', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Argeby (Event)', amount=1)])), + LocationData(code=3235825147, name='Monster Fibula: Gelleric', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Gelleric (Event)', amount=1)])), + LocationData(code=3235825148, name='Monster Fibula: Papagun', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Papagun (Event)', amount=1)])), + LocationData(code=3235825149, name='Monster Fibula: Angler', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Angler (Event)', amount=1)])), + LocationData(code=3235825150, name='Monster Fibula: Shokat', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Shokat (Event)', amount=1)])), + LocationData(code=3235825151, name='Monster Fibula: Behesloth', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Behesloth (Event)', amount=1)])), + LocationData(code=3235825152, name='Monster Fibula: Jelleric', area='wave-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Jelleric (Event)', amount=1)])), + LocationData(code=3235825153, name='Monster Fibula: Ocubepus', area='wave-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Ocubepus (Event)', amount=1)])), + LocationData(code=3235825154, name='Monster Fibula: Blue Ray', area='wave-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Blue Ray (Event)', amount=1)])), + LocationData(code=3235825155, name='Monster Fibula: Rob0ck', area='shock-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Rob0ck (Event)', amount=1)])), + LocationData(code=3235825156, name='Monster Fibula: Powerplant', area='shock-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Powerplant (Event)', amount=1)])), + LocationData(code=3235825157, name='Monster Fibula: Ectovolt', area='shock-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Ectovolt (Event)', amount=1)])), + LocationData(code=3235825158, name='Monster Fibula: Sun Beetle', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Sun Beetle (Event)', amount=1)])), + LocationData(code=3235825159, name='Monster Fibula: Moon Beetle', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Moon Beetle (Event)', amount=1)])), + LocationData(code=3235825160, name='Monster Fibula: Pandza', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Pandza (Event)', amount=1)])), + LocationData(code=3235825161, name='Monster Fibula: Aranetarda', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Aranetarda (Event)', amount=1)])), + LocationData(code=3235825162, name='Monster Fibula: Hillkat Bandleader', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Hillkat Bandleader (Event)', amount=1)])), + LocationData(code=3235825163, name='Monster Fibula: Blue Hedgehag', area='autumn-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Blue Hedgehag (Event)', amount=1)])), + LocationData(code=3235825164, name='Monster Fibula: Infected Digmo', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Infected Digmo (Event)', amount=1)])), + LocationData(code=3235825165, name='Monster Fibula: Peng King Dakara', area='bergen-trails', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Peng King Dakara (Event)', amount=1)])), + LocationData(code=3235825166, name='Monster Fibula: X01 Driller H.F.S.', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: X01 Driller H.F.S. (Event)', amount=1)])), + LocationData(code=3235825167, name="Monster Fibula: Ti'im", area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: Ti'im (Event)", amount=1)])), + LocationData(code=3235825168, name='Monster Fibula: Cursed Sharkster', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Cursed Sharkster (Event)', amount=1)])), + LocationData(code=3235825169, name="Monster Fibula: Pinzo'jrahrrrn", area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: Pinzo'jrahrrrn (Event)", amount=1)])), + LocationData(code=3235825170, name='Monster Fibula: Master Magmoth', area='heat-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Master Magmoth (Event)', amount=1)])), + LocationData(code=3235825171, name='Monster Fibula: Guard Billston', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Guard Billston (Event)', amount=1)])), + LocationData(code=3235825172, name='Monster Fibula: Hologram Frobbit', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Hologram Frobbit (Event)', amount=1)])), + LocationData(code=3235825173, name='Monster Fibula: Smelter Digmo', area='cold-dng', metadata={'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Smelter Digmo (Event)', amount=1)])), + LocationData(code=3235825174, name='Monster Fibula: Blazehoof', area='autumn-fall', metadata={'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Blazehoof (Event)', amount=1)])), + LocationData(code=3235825175, name='Monster Fibula: Plasma Phantom', area='shock-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Plasma Phantom (Event)', amount=1)])), + LocationData(code=3235825176, name='Monster Fibula: Sir Blobus Starnikus', area='wave-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Sir Blobus Starnikus (Event)', amount=1)])), + LocationData(code=3235825177, name='Monster Fibula: Tiefsee Angler', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Tiefsee Angler (Event)', amount=1)])), + LocationData(code=3235825178, name='Monster Fibula: Son of the East', area='tree-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Son of the East (Event)', amount=1)])), + LocationData(code=3235825179, name='Monster Fibula: Ancient Guardian', area='tree-dng', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Ancient Guardian (Event)', amount=1)])), + LocationData(code=3235825180, name='Monster Fibula: Karotto Fruitseeker', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Karotto Fruitseeker (Event)', amount=1)])), + LocationData(code=3235825181, name='Monster Fibula: Buff Bloomy', area='jungle', metadata={'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Buff Bloomy (Event)', amount=1)])), + LocationData(code=3235825182, name='Monster Fibula: Twilight Master', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Twilight Master (Event)', amount=1)])), + LocationData(code=3235825183, name='Monster Fibula: King Kaktorro', area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: King Kaktorro (Event)', amount=1)])), + LocationData(code=3235825184, name="Monster Fibula: DON'T USE THIS", area='heat-area', metadata={'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: DON'T USE THIS (Event)", amount=1)])), + LocationData(code=3235825185, name='Monster Fibula: Designer', area='arid', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Designer (Event)', amount=1)])), + LocationData(code=3235825186, name='Monster Fibula: The Creator', area='arid-dng-2', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: The Creator (Event)', amount=1)])), + LocationData(code=3235825187, name='Monster Fibula: Pandza Mk. II', area='forest', metadata={'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Pandza Mk. II (Event)', amount=1)])), + LocationData(code=3235825188, name='Monster Fibula: Echinoignis', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Echinoignis (Event)', amount=1)])), + LocationData(code=3235825189, name='Monster Fibula: Echinonix', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Echinonix (Event)', amount=1)])), + LocationData(code=3235825190, name='Monster Fibula: Echinofulgur', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Echinofulgur (Event)', amount=1)])), + LocationData(code=3235825191, name='Monster Fibula: Echinofluctus', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Echinofluctus (Event)', amount=1)])), + LocationData(code=3235825192, name='Monster Fibula: Salteric', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Salteric (Event)', amount=1)])), + LocationData(code=3235825193, name='Monster Fibula: Balooneer', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Balooneer (Event)', amount=1)])), + LocationData(code=3235825194, name="Monster Fibula: K'im", area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: K'im (Event)", amount=1)])), + LocationData(code=3235825195, name='Monster Fibula: Trigenbu', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Trigenbu (Event)', amount=1)])), + LocationData(code=3235825196, name='Monster Fibula: Heat Crystalid', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Heat Crystalid (Event)', amount=1)])), + LocationData(code=3235825197, name='Monster Fibula: Cold Crystalid', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Cold Crystalid (Event)', amount=1)])), + LocationData(code=3235825198, name='Monster Fibula: Shock Crystalid', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Shock Crystalid (Event)', amount=1)])), + LocationData(code=3235825199, name='Monster Fibula: Wave Crystalid', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Wave Crystalid (Event)', amount=1)])), + LocationData(code=3235825200, name='Monster Fibula: Hummagnum', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Hummagnum (Event)', amount=1)])), + LocationData(code=3235825201, name='Monster Fibula: Mizree', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Mizree (Event)', amount=1)])), + LocationData(code=3235825202, name='Monster Fibula: Beearbot', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Beearbot (Event)', amount=1)])), + LocationData(code=3235825203, name='Monster Fibula: Illegal Coordinator', area='autumn-area', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Illegal Coordinator (Event)', amount=1)])), + LocationData(code=3235825204, name='Monster Fibula: Tremmy', area='rhombus-sqr', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Tremmy (Event)', amount=1)])), + LocationData(code=3235825205, name='Monster Fibula: Distillizer', area='heat-village', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Distillizer (Event)', amount=1)])), + LocationData(code=3235825206, name='Monster Fibula: Toxovolt', area='jungle', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Toxovolt (Event)', amount=1)])), + LocationData(code=3235825207, name='Monster Fibula: Papaboss the Younger', area='jungle-city', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Papaboss the Younger (Event)', amount=1)])), + LocationData(code=3235825208, name='Monster Fibula: Hillcart', area='rhombus-sqr', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Hillcart (Event)', amount=1)])), + LocationData(code=3235825209, name='Monster Fibula: The Goatfather', area='rhombus-sqr', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: The Goatfather (Event)', amount=1)])), + LocationData(code=3235825210, name='Monster Fibula: Guardian Statue', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Guardian Statue (Event)', amount=1)])), + LocationData(code=3235825211, name='Monster Fibula: Gynthar', area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Gynthar (Event)', amount=1)])), + LocationData(code=3235825212, name="Monster Fibula: Di'orbis", area='final-dng', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'open': 'Menu'}, cond=[ItemCondition(item_name="First Encounter: Di'orbis (Event)", amount=1)])), + LocationData(code=3235825213, name='Monster Fibula: Son of the Beach', area='beach', metadata={'dlc': True, 'kill': True}, access=AccessInfo(region={'linear': 'Menu', 'open': 'Menu'}, cond=[ItemCondition(item_name='First Encounter: Son of the Beach (Event)', amount=1)])), ] locations_dict = { location.name: location for location in locations_data } @@ -2501,107 +2501,107 @@ locations_dict['Botanics: Beta Keen Sprout'], locations_dict['Botanics: Alpha Fossil Stone'], locations_dict['Botanics: Beta Fossil Stone'], - locations_dict['Killsanity: Hedgehag'], - locations_dict["Killsanity: Rockin' Hillkat"], - locations_dict['Killsanity: Mad Bovine'], - locations_dict['Killsanity: Old Hedgehag'], - locations_dict["Killsanity: Flamin' Hillkat"], - locations_dict['Killsanity: Red Eyed Bovine'], - locations_dict['Killsanity: Young Frobbit'], - locations_dict['Killsanity: White Frobbit'], - locations_dict['Killsanity: Seafly'], - locations_dict['Killsanity: Pengpeng'], - locations_dict['Killsanity: Horny Goat'], - locations_dict['Killsanity: Karotto'], - locations_dict['Killsanity: Fleazer'], - locations_dict['Killsanity: Carritrich'], - locations_dict['Killsanity: Kamikatze'], - locations_dict['Killsanity: Digmo'], - locations_dict['Killsanity: Pinceron'], - locations_dict['Killsanity: Sharkster'], - locations_dict['Killsanity: Vulturbine'], - locations_dict['Killsanity: Drillertoise'], - locations_dict['Killsanity: Tim'], - locations_dict['Killsanity: Boss Pincer'], - locations_dict['Killsanity: Trijelly'], - locations_dict['Killsanity: Pada Moth'], - locations_dict['Killsanity: Darth Moth'], - locations_dict['Killsanity: Magmanizer'], - locations_dict['Killsanity: Radical Hedgehag'], - locations_dict["Killsanity: Chillin' Hillkat"], - locations_dict['Killsanity: Fallfly'], - locations_dict['Killsanity: Ivory Bovine'], - locations_dict['Killsanity: Neutral Virus'], - locations_dict['Killsanity: Heat Virus'], - locations_dict['Killsanity: Cold Virus'], - locations_dict['Killsanity: Argeby'], - locations_dict['Killsanity: Gelleric'], - locations_dict['Killsanity: Papagun'], - locations_dict['Killsanity: Angler'], - locations_dict['Killsanity: Shokat'], - locations_dict['Killsanity: Behesloth'], - locations_dict['Killsanity: Jelleric'], - locations_dict['Killsanity: Ocubepus'], - locations_dict['Killsanity: Blue Ray'], - locations_dict['Killsanity: Rob0ck'], - locations_dict['Killsanity: Powerplant'], - locations_dict['Killsanity: Ectovolt'], - locations_dict['Killsanity: Sun Beetle'], - locations_dict['Killsanity: Moon Beetle'], - locations_dict['Killsanity: Pandza'], - locations_dict['Killsanity: Aranetarda'], - locations_dict['Killsanity: Hillkat Bandleader'], - locations_dict['Killsanity: Blue Hedgehag'], - locations_dict['Killsanity: Infected Digmo'], - locations_dict['Killsanity: Peng King Dakara'], - locations_dict['Killsanity: X01 Driller H.F.S.'], - locations_dict["Killsanity: Ti'im"], - locations_dict['Killsanity: Cursed Sharkster'], - locations_dict["Killsanity: Pinzo'jrahrrrn"], - locations_dict['Killsanity: Master Magmoth'], - locations_dict['Killsanity: Guard Billston'], - locations_dict['Killsanity: Hologram Frobbit'], - locations_dict['Killsanity: Smelter Digmo'], - locations_dict['Killsanity: Blazehoof'], - locations_dict['Killsanity: Plasma Phantom'], - locations_dict['Killsanity: Sir Blobus Starnikus'], - locations_dict['Killsanity: Tiefsee Angler'], - locations_dict['Killsanity: Son of the East'], - locations_dict['Killsanity: Ancient Guardian'], - locations_dict['Killsanity: Karotto Fruitseeker'], - locations_dict['Killsanity: Buff Bloomy'], - locations_dict['Killsanity: Twilight Master'], - locations_dict['Killsanity: King Kaktorro'], - locations_dict["Killsanity: DON'T USE THIS"], - locations_dict['Killsanity: Designer'], - locations_dict['Killsanity: The Creator'], - locations_dict['Killsanity: Pandza Mk. II'], - locations_dict['Killsanity: Echinoignis'], - locations_dict['Killsanity: Echinonix'], - locations_dict['Killsanity: Echinofulgur'], - locations_dict['Killsanity: Echinofluctus'], - locations_dict['Killsanity: Salteric'], - locations_dict['Killsanity: Balooneer'], - locations_dict["Killsanity: K'im"], - locations_dict['Killsanity: Trigenbu'], - locations_dict['Killsanity: Heat Crystalid'], - locations_dict['Killsanity: Cold Crystalid'], - locations_dict['Killsanity: Shock Crystalid'], - locations_dict['Killsanity: Wave Crystalid'], - locations_dict['Killsanity: Hummagnum'], - locations_dict['Killsanity: Mizree'], - locations_dict['Killsanity: Beearbot'], - locations_dict['Killsanity: Illegal Coordinator'], - locations_dict['Killsanity: Tremmy'], - locations_dict['Killsanity: Distillizer'], - locations_dict['Killsanity: Toxovolt'], - locations_dict['Killsanity: Papaboss the Younger'], - locations_dict['Killsanity: Hillcart'], - locations_dict['Killsanity: The Goatfather'], - locations_dict['Killsanity: Guardian Statue'], - locations_dict['Killsanity: Gynthar'], - locations_dict["Killsanity: Di'orbis"], - locations_dict['Killsanity: Son of the Beach'], + locations_dict['Monster Fibula: Hedgehag'], + locations_dict["Monster Fibula: Rockin' Hillkat"], + locations_dict['Monster Fibula: Mad Bovine'], + locations_dict['Monster Fibula: Old Hedgehag'], + locations_dict["Monster Fibula: Flamin' Hillkat"], + locations_dict['Monster Fibula: Red Eyed Bovine'], + locations_dict['Monster Fibula: Young Frobbit'], + locations_dict['Monster Fibula: White Frobbit'], + locations_dict['Monster Fibula: Seafly'], + locations_dict['Monster Fibula: Pengpeng'], + locations_dict['Monster Fibula: Horny Goat'], + locations_dict['Monster Fibula: Karotto'], + locations_dict['Monster Fibula: Fleazer'], + locations_dict['Monster Fibula: Carritrich'], + locations_dict['Monster Fibula: Kamikatze'], + locations_dict['Monster Fibula: Digmo'], + locations_dict['Monster Fibula: Pinceron'], + locations_dict['Monster Fibula: Sharkster'], + locations_dict['Monster Fibula: Vulturbine'], + locations_dict['Monster Fibula: Drillertoise'], + locations_dict['Monster Fibula: Tim'], + locations_dict['Monster Fibula: Boss Pincer'], + locations_dict['Monster Fibula: Trijelly'], + locations_dict['Monster Fibula: Pada Moth'], + locations_dict['Monster Fibula: Darth Moth'], + locations_dict['Monster Fibula: Magmanizer'], + locations_dict['Monster Fibula: Radical Hedgehag'], + locations_dict["Monster Fibula: Chillin' Hillkat"], + locations_dict['Monster Fibula: Fallfly'], + locations_dict['Monster Fibula: Ivory Bovine'], + locations_dict['Monster Fibula: Neutral Virus'], + locations_dict['Monster Fibula: Heat Virus'], + locations_dict['Monster Fibula: Cold Virus'], + locations_dict['Monster Fibula: Argeby'], + locations_dict['Monster Fibula: Gelleric'], + locations_dict['Monster Fibula: Papagun'], + locations_dict['Monster Fibula: Angler'], + locations_dict['Monster Fibula: Shokat'], + locations_dict['Monster Fibula: Behesloth'], + locations_dict['Monster Fibula: Jelleric'], + locations_dict['Monster Fibula: Ocubepus'], + locations_dict['Monster Fibula: Blue Ray'], + locations_dict['Monster Fibula: Rob0ck'], + locations_dict['Monster Fibula: Powerplant'], + locations_dict['Monster Fibula: Ectovolt'], + locations_dict['Monster Fibula: Sun Beetle'], + locations_dict['Monster Fibula: Moon Beetle'], + locations_dict['Monster Fibula: Pandza'], + locations_dict['Monster Fibula: Aranetarda'], + locations_dict['Monster Fibula: Hillkat Bandleader'], + locations_dict['Monster Fibula: Blue Hedgehag'], + locations_dict['Monster Fibula: Infected Digmo'], + locations_dict['Monster Fibula: Peng King Dakara'], + locations_dict['Monster Fibula: X01 Driller H.F.S.'], + locations_dict["Monster Fibula: Ti'im"], + locations_dict['Monster Fibula: Cursed Sharkster'], + locations_dict["Monster Fibula: Pinzo'jrahrrrn"], + locations_dict['Monster Fibula: Master Magmoth'], + locations_dict['Monster Fibula: Guard Billston'], + locations_dict['Monster Fibula: Hologram Frobbit'], + locations_dict['Monster Fibula: Smelter Digmo'], + locations_dict['Monster Fibula: Blazehoof'], + locations_dict['Monster Fibula: Plasma Phantom'], + locations_dict['Monster Fibula: Sir Blobus Starnikus'], + locations_dict['Monster Fibula: Tiefsee Angler'], + locations_dict['Monster Fibula: Son of the East'], + locations_dict['Monster Fibula: Ancient Guardian'], + locations_dict['Monster Fibula: Karotto Fruitseeker'], + locations_dict['Monster Fibula: Buff Bloomy'], + locations_dict['Monster Fibula: Twilight Master'], + locations_dict['Monster Fibula: King Kaktorro'], + locations_dict["Monster Fibula: DON'T USE THIS"], + locations_dict['Monster Fibula: Designer'], + locations_dict['Monster Fibula: The Creator'], + locations_dict['Monster Fibula: Pandza Mk. II'], + locations_dict['Monster Fibula: Echinoignis'], + locations_dict['Monster Fibula: Echinonix'], + locations_dict['Monster Fibula: Echinofulgur'], + locations_dict['Monster Fibula: Echinofluctus'], + locations_dict['Monster Fibula: Salteric'], + locations_dict['Monster Fibula: Balooneer'], + locations_dict["Monster Fibula: K'im"], + locations_dict['Monster Fibula: Trigenbu'], + locations_dict['Monster Fibula: Heat Crystalid'], + locations_dict['Monster Fibula: Cold Crystalid'], + locations_dict['Monster Fibula: Shock Crystalid'], + locations_dict['Monster Fibula: Wave Crystalid'], + locations_dict['Monster Fibula: Hummagnum'], + locations_dict['Monster Fibula: Mizree'], + locations_dict['Monster Fibula: Beearbot'], + locations_dict['Monster Fibula: Illegal Coordinator'], + locations_dict['Monster Fibula: Tremmy'], + locations_dict['Monster Fibula: Distillizer'], + locations_dict['Monster Fibula: Toxovolt'], + locations_dict['Monster Fibula: Papaboss the Younger'], + locations_dict['Monster Fibula: Hillcart'], + locations_dict['Monster Fibula: The Goatfather'], + locations_dict['Monster Fibula: Guardian Statue'], + locations_dict['Monster Fibula: Gynthar'], + locations_dict["Monster Fibula: Di'orbis"], + locations_dict['Monster Fibula: Son of the Beach'], ] location_groups = { @@ -2633,10 +2633,10 @@ locations_dict['Shop Slot: Fruit Drink (Vermillion Items)'], locations_dict['Shop Slot: Rice Cracker (Vermillion Items)'], locations_dict['Shop Slot: Veggie Sticks (Vermillion Items)'], - locations_dict['Killsanity: Neutral Virus'], - locations_dict['Killsanity: Heat Virus'], - locations_dict['Killsanity: Cold Virus'], - locations_dict['Killsanity: Designer'], + locations_dict['Monster Fibula: Neutral Virus'], + locations_dict['Monster Fibula: Heat Virus'], + locations_dict['Monster Fibula: Cold Virus'], + locations_dict['Monster Fibula: Designer'], }, "Vermillion Wasteland Chests": { locations_dict['Wasteland: Spiral Cliff Center'], @@ -2700,15 +2700,15 @@ locations_dict['Botanics: Alpha Water Blades'], locations_dict['Botanics: Beta Water Blades'], locations_dict['Botanics: Omega Water Blades'], - locations_dict['Killsanity: Hedgehag'], - locations_dict["Killsanity: Rockin' Hillkat"], - locations_dict['Killsanity: Mad Bovine'], - locations_dict['Killsanity: Old Hedgehag'], - locations_dict["Killsanity: Flamin' Hillkat"], - locations_dict['Killsanity: Red Eyed Bovine'], - locations_dict['Killsanity: Hillkat Bandleader'], - locations_dict['Killsanity: Blue Hedgehag'], - locations_dict['Killsanity: Illegal Coordinator'], + locations_dict['Monster Fibula: Hedgehag'], + locations_dict["Monster Fibula: Rockin' Hillkat"], + locations_dict['Monster Fibula: Mad Bovine'], + locations_dict['Monster Fibula: Old Hedgehag'], + locations_dict["Monster Fibula: Flamin' Hillkat"], + locations_dict['Monster Fibula: Red Eyed Bovine'], + locations_dict['Monster Fibula: Hillkat Bandleader'], + locations_dict['Monster Fibula: Blue Hedgehag'], + locations_dict['Monster Fibula: Illegal Coordinator'], }, "Autumn's Rise Chests": { locations_dict['Rise: Drippy Den'], @@ -2774,12 +2774,12 @@ locations_dict['Botanics: Alpha Water Cutlass'], locations_dict['Botanics: Beta Water Cutlass'], locations_dict['Botanics: Omega Water Cutlass'], - locations_dict['Killsanity: Radical Hedgehag'], - locations_dict["Killsanity: Chillin' Hillkat"], - locations_dict['Killsanity: Fallfly'], - locations_dict['Killsanity: Ivory Bovine'], - locations_dict['Killsanity: Hologram Frobbit'], - locations_dict['Killsanity: Blazehoof'], + locations_dict['Monster Fibula: Radical Hedgehag'], + locations_dict["Monster Fibula: Chillin' Hillkat"], + locations_dict['Monster Fibula: Fallfly'], + locations_dict['Monster Fibula: Ivory Bovine'], + locations_dict['Monster Fibula: Hologram Frobbit'], + locations_dict['Monster Fibula: Blazehoof'], }, "Autumn's Fall Chests": { locations_dict['Fall: Ruby Tunnel'], @@ -2959,13 +2959,13 @@ locations_dict['Botanics: Beta Lance Shrub'], locations_dict['Botanics: Omega Lance Shrub'], locations_dict['Botanics: Diamond Ice'], - locations_dict['Killsanity: Young Frobbit'], - locations_dict['Killsanity: White Frobbit'], - locations_dict['Killsanity: Seafly'], - locations_dict['Killsanity: Pengpeng'], - locations_dict['Killsanity: Horny Goat'], - locations_dict['Killsanity: Karotto'], - locations_dict['Killsanity: Peng King Dakara'], + locations_dict['Monster Fibula: Young Frobbit'], + locations_dict['Monster Fibula: White Frobbit'], + locations_dict['Monster Fibula: Seafly'], + locations_dict['Monster Fibula: Pengpeng'], + locations_dict['Monster Fibula: Horny Goat'], + locations_dict['Monster Fibula: Karotto'], + locations_dict['Monster Fibula: Peng King Dakara'], }, "Bergen Trail Chests": { locations_dict['Trail: Abandoned Cave'], @@ -3032,13 +3032,13 @@ locations_dict['Botanics: Delta Egg Pot'], locations_dict['Botanics: Omega Egg Pot A'], locations_dict['Botanics: Omega Egg Pot B'], - locations_dict['Killsanity: Fleazer'], - locations_dict['Killsanity: Carritrich'], - locations_dict['Killsanity: Kamikatze'], - locations_dict['Killsanity: Digmo'], - locations_dict['Killsanity: Infected Digmo'], - locations_dict['Killsanity: X01 Driller H.F.S.'], - locations_dict['Killsanity: Smelter Digmo'], + locations_dict['Monster Fibula: Fleazer'], + locations_dict['Monster Fibula: Carritrich'], + locations_dict['Monster Fibula: Kamikatze'], + locations_dict['Monster Fibula: Digmo'], + locations_dict['Monster Fibula: Infected Digmo'], + locations_dict['Monster Fibula: X01 Driller H.F.S.'], + locations_dict['Monster Fibula: Smelter Digmo'], }, "Temple Mine Chests": { locations_dict['Mine U1: Elevator'], @@ -3148,12 +3148,12 @@ locations_dict['Botanics: Alpha Crystal'], locations_dict['Botanics: Beta Crystal'], locations_dict['Botanics: Omega Crystal'], - locations_dict['Killsanity: Sun Beetle'], - locations_dict['Killsanity: Moon Beetle'], - locations_dict['Killsanity: Pandza'], - locations_dict['Killsanity: Aranetarda'], - locations_dict['Killsanity: Twilight Master'], - locations_dict['Killsanity: Pandza Mk. II'], + locations_dict['Monster Fibula: Sun Beetle'], + locations_dict['Monster Fibula: Moon Beetle'], + locations_dict['Monster Fibula: Pandza'], + locations_dict['Monster Fibula: Aranetarda'], + locations_dict['Monster Fibula: Twilight Master'], + locations_dict['Monster Fibula: Pandza Mk. II'], }, "Sapphire Ridge Chests": { locations_dict['Ridge: The Barracks'], @@ -3258,17 +3258,17 @@ locations_dict['Botanics: Alpha Bone Pile'], locations_dict['Botanics: Beta Bone Pile'], locations_dict['Botanics: Omega Bone Pile'], - locations_dict['Killsanity: Pinceron'], - locations_dict['Killsanity: Sharkster'], - locations_dict['Killsanity: Vulturbine'], - locations_dict['Killsanity: Drillertoise'], - locations_dict['Killsanity: Tim'], - locations_dict['Killsanity: Boss Pincer'], - locations_dict["Killsanity: Ti'im"], - locations_dict['Killsanity: Cursed Sharkster'], - locations_dict['Killsanity: Guard Billston'], - locations_dict['Killsanity: King Kaktorro'], - locations_dict["Killsanity: DON'T USE THIS"], + locations_dict['Monster Fibula: Pinceron'], + locations_dict['Monster Fibula: Sharkster'], + locations_dict['Monster Fibula: Vulturbine'], + locations_dict['Monster Fibula: Drillertoise'], + locations_dict['Monster Fibula: Tim'], + locations_dict['Monster Fibula: Boss Pincer'], + locations_dict["Monster Fibula: Ti'im"], + locations_dict['Monster Fibula: Cursed Sharkster'], + locations_dict['Monster Fibula: Guard Billston'], + locations_dict['Monster Fibula: King Kaktorro'], + locations_dict["Monster Fibula: DON'T USE THIS"], }, "Maroon Valley Chests": { locations_dict['Maroon: Mystery Cave Lower'], @@ -3332,12 +3332,12 @@ locations_dict["Faj'ro Circuit Override"], locations_dict["Faj'ro SP Upgrade"], locations_dict['Cold Pedestal'], - locations_dict['Killsanity: Trijelly'], - locations_dict['Killsanity: Pada Moth'], - locations_dict['Killsanity: Darth Moth'], - locations_dict['Killsanity: Magmanizer'], - locations_dict["Killsanity: Pinzo'jrahrrrn"], - locations_dict['Killsanity: Master Magmoth'], + locations_dict['Monster Fibula: Trijelly'], + locations_dict['Monster Fibula: Pada Moth'], + locations_dict['Monster Fibula: Darth Moth'], + locations_dict['Monster Fibula: Magmanizer'], + locations_dict["Monster Fibula: Pinzo'jrahrrrn"], + locations_dict['Monster Fibula: Master Magmoth'], }, "Faj'ro Temple Chests": { locations_dict["Faj'ro 1F: Right Chamber 1"], @@ -3413,7 +3413,7 @@ locations_dict["Shop Slot: Steel Mail (Ba'kii Weapons)"], locations_dict["Shop Slot: Steel Boots (Ba'kii Weapons)"], locations_dict['Botanics: Sprout of Space'], - locations_dict['Killsanity: Distillizer'], + locations_dict['Monster Fibula: Distillizer'], }, "Ba'kii Kum Chests": { locations_dict["Ba'kii: Solar Farm Upper"], @@ -3513,16 +3513,16 @@ locations_dict['Botanics: Alpha Virus Shroom'], locations_dict['Botanics: Beta Virus Shroom'], locations_dict['Botanics: Omega Virus Shroom'], - locations_dict['Killsanity: Argeby'], - locations_dict['Killsanity: Gelleric'], - locations_dict['Killsanity: Papagun'], - locations_dict['Killsanity: Angler'], - locations_dict['Killsanity: Shokat'], - locations_dict['Killsanity: Behesloth'], - locations_dict['Killsanity: Tiefsee Angler'], - locations_dict['Killsanity: Karotto Fruitseeker'], - locations_dict['Killsanity: Buff Bloomy'], - locations_dict['Killsanity: Toxovolt'], + locations_dict['Monster Fibula: Argeby'], + locations_dict['Monster Fibula: Gelleric'], + locations_dict['Monster Fibula: Papagun'], + locations_dict['Monster Fibula: Angler'], + locations_dict['Monster Fibula: Shokat'], + locations_dict['Monster Fibula: Behesloth'], + locations_dict['Monster Fibula: Tiefsee Angler'], + locations_dict['Monster Fibula: Karotto Fruitseeker'], + locations_dict['Monster Fibula: Buff Bloomy'], + locations_dict['Monster Fibula: Toxovolt'], }, "Gaia's Garden Chests": { locations_dict['Garden: Dripping Cave'], @@ -3671,7 +3671,7 @@ locations_dict['Shop Slot: Titan Boots (Basin Weapons)'], locations_dict['Shop Slot: One Up (Calzone Shop)'], locations_dict['Botanics: Sprout of Spirit'], - locations_dict['Killsanity: Papaboss the Younger'], + locations_dict['Monster Fibula: Papaboss the Younger'], }, "Basin Keep Chests": { locations_dict['Basin: Centrum'], @@ -3753,9 +3753,9 @@ locations_dict['Shop Slot: Cross Mail (Rhombus Weapons + DLC)'], locations_dict['Shop Slot: Cross Boots (Rhombus Weapons + DLC)'], locations_dict['Botanics: Sprout of Ages'], - locations_dict['Killsanity: Tremmy'], - locations_dict['Killsanity: Hillcart'], - locations_dict['Killsanity: The Goatfather'], + locations_dict['Monster Fibula: Tremmy'], + locations_dict['Monster Fibula: Hillcart'], + locations_dict['Monster Fibula: The Goatfather'], }, "Rhombus Square Chests": { locations_dict['Rhombus: Arena Plaza East'], @@ -3893,10 +3893,10 @@ locations_dict["Zir'vitar Shade Statue"], locations_dict["Zir'vitar Circuit Override"], locations_dict['Wave Pedestal'], - locations_dict['Killsanity: Rob0ck'], - locations_dict['Killsanity: Powerplant'], - locations_dict['Killsanity: Ectovolt'], - locations_dict['Killsanity: Plasma Phantom'], + locations_dict['Monster Fibula: Rob0ck'], + locations_dict['Monster Fibula: Powerplant'], + locations_dict['Monster Fibula: Ectovolt'], + locations_dict['Monster Fibula: Plasma Phantom'], }, "Zir'vitar Temple Chests": { locations_dict["Zir'vitar 1F: Moving Transmit Left"], @@ -3918,8 +3918,8 @@ locations_dict["Krys'kajo Shade Statue"], locations_dict["Krys'kajo Circuit Override"], locations_dict["Krys'kajo SP Upgrade"], - locations_dict['Killsanity: Son of the East'], - locations_dict['Killsanity: Ancient Guardian'], + locations_dict['Monster Fibula: Son of the East'], + locations_dict['Monster Fibula: Ancient Guardian'], }, "Grand Krys'kajo Chests": { locations_dict['Kajo 3F: East Branch Lower'], @@ -3948,10 +3948,10 @@ locations_dict["So'najiz Shade Statue"], locations_dict["So'najiz Circuit Override"], locations_dict['Shock Pedestal'], - locations_dict['Killsanity: Jelleric'], - locations_dict['Killsanity: Ocubepus'], - locations_dict['Killsanity: Blue Ray'], - locations_dict['Killsanity: Sir Blobus Starnikus'], + locations_dict['Monster Fibula: Jelleric'], + locations_dict['Monster Fibula: Ocubepus'], + locations_dict['Monster Fibula: Blue Ray'], + locations_dict['Monster Fibula: Sir Blobus Starnikus'], }, "So'najiz Temple Chests": { locations_dict["So'najiz U1: Principle of Conveyance"], @@ -4035,15 +4035,15 @@ locations_dict['Botanics: Beta Keen Sprout'], locations_dict['Botanics: Alpha Fossil Stone'], locations_dict['Botanics: Beta Fossil Stone'], - locations_dict['Killsanity: Echinoignis'], - locations_dict['Killsanity: Echinonix'], - locations_dict['Killsanity: Echinofulgur'], - locations_dict['Killsanity: Echinofluctus'], - locations_dict['Killsanity: Salteric'], - locations_dict['Killsanity: Balooneer'], - locations_dict["Killsanity: K'im"], - locations_dict['Killsanity: Trigenbu'], - locations_dict['Killsanity: Son of the Beach'], + locations_dict['Monster Fibula: Echinoignis'], + locations_dict['Monster Fibula: Echinonix'], + locations_dict['Monster Fibula: Echinofulgur'], + locations_dict['Monster Fibula: Echinofluctus'], + locations_dict['Monster Fibula: Salteric'], + locations_dict['Monster Fibula: Balooneer'], + locations_dict["Monster Fibula: K'im"], + locations_dict['Monster Fibula: Trigenbu'], + locations_dict['Monster Fibula: Son of the Beach'], }, "Azure Archipelago Chests": { locations_dict['Azure A.: Sandy Bar Lower'], @@ -4091,16 +4091,16 @@ locations_dict['Botanics: Gamma Cone Sprout'], locations_dict['Botanics: Delta Cone Sprout'], locations_dict['Botanics: Alpha Shard'], - locations_dict['Killsanity: Heat Crystalid'], - locations_dict['Killsanity: Cold Crystalid'], - locations_dict['Killsanity: Shock Crystalid'], - locations_dict['Killsanity: Wave Crystalid'], - locations_dict['Killsanity: Hummagnum'], - locations_dict['Killsanity: Mizree'], - locations_dict['Killsanity: Beearbot'], - locations_dict['Killsanity: Guardian Statue'], - locations_dict['Killsanity: Gynthar'], - locations_dict["Killsanity: Di'orbis"], + locations_dict['Monster Fibula: Heat Crystalid'], + locations_dict['Monster Fibula: Cold Crystalid'], + locations_dict['Monster Fibula: Shock Crystalid'], + locations_dict['Monster Fibula: Wave Crystalid'], + locations_dict['Monster Fibula: Hummagnum'], + locations_dict['Monster Fibula: Mizree'], + locations_dict['Monster Fibula: Beearbot'], + locations_dict['Monster Fibula: Guardian Statue'], + locations_dict['Monster Fibula: Gynthar'], + locations_dict["Monster Fibula: Di'orbis"], }, "Ku'lero Temple Chests": { locations_dict["Ku'lero: Comet Trail Right"], @@ -4886,248 +4886,248 @@ locations_dict['Botanics: Alpha Fossil Stone'], locations_dict['Botanics: Beta Fossil Stone'], }, - "Autumn's Rise Kills": { - locations_dict['Killsanity: Hedgehag'], - locations_dict["Killsanity: Rockin' Hillkat"], - locations_dict['Killsanity: Mad Bovine'], - locations_dict['Killsanity: Old Hedgehag'], - locations_dict["Killsanity: Flamin' Hillkat"], - locations_dict['Killsanity: Red Eyed Bovine'], - locations_dict['Killsanity: Hillkat Bandleader'], - locations_dict['Killsanity: Blue Hedgehag'], - locations_dict['Killsanity: Illegal Coordinator'], + "Monster Defeats": { + locations_dict['Monster Fibula: Hedgehag'], + locations_dict["Monster Fibula: Rockin' Hillkat"], + locations_dict['Monster Fibula: Mad Bovine'], + locations_dict['Monster Fibula: Old Hedgehag'], + locations_dict["Monster Fibula: Flamin' Hillkat"], + locations_dict['Monster Fibula: Red Eyed Bovine'], + locations_dict['Monster Fibula: Young Frobbit'], + locations_dict['Monster Fibula: White Frobbit'], + locations_dict['Monster Fibula: Seafly'], + locations_dict['Monster Fibula: Pengpeng'], + locations_dict['Monster Fibula: Horny Goat'], + locations_dict['Monster Fibula: Karotto'], + locations_dict['Monster Fibula: Fleazer'], + locations_dict['Monster Fibula: Carritrich'], + locations_dict['Monster Fibula: Kamikatze'], + locations_dict['Monster Fibula: Digmo'], + locations_dict['Monster Fibula: Pinceron'], + locations_dict['Monster Fibula: Sharkster'], + locations_dict['Monster Fibula: Vulturbine'], + locations_dict['Monster Fibula: Drillertoise'], + locations_dict['Monster Fibula: Tim'], + locations_dict['Monster Fibula: Boss Pincer'], + locations_dict['Monster Fibula: Trijelly'], + locations_dict['Monster Fibula: Pada Moth'], + locations_dict['Monster Fibula: Darth Moth'], + locations_dict['Monster Fibula: Magmanizer'], + locations_dict['Monster Fibula: Radical Hedgehag'], + locations_dict["Monster Fibula: Chillin' Hillkat"], + locations_dict['Monster Fibula: Fallfly'], + locations_dict['Monster Fibula: Ivory Bovine'], + locations_dict['Monster Fibula: Neutral Virus'], + locations_dict['Monster Fibula: Heat Virus'], + locations_dict['Monster Fibula: Cold Virus'], + locations_dict['Monster Fibula: Argeby'], + locations_dict['Monster Fibula: Gelleric'], + locations_dict['Monster Fibula: Papagun'], + locations_dict['Monster Fibula: Angler'], + locations_dict['Monster Fibula: Shokat'], + locations_dict['Monster Fibula: Behesloth'], + locations_dict['Monster Fibula: Jelleric'], + locations_dict['Monster Fibula: Ocubepus'], + locations_dict['Monster Fibula: Blue Ray'], + locations_dict['Monster Fibula: Rob0ck'], + locations_dict['Monster Fibula: Powerplant'], + locations_dict['Monster Fibula: Ectovolt'], + locations_dict['Monster Fibula: Sun Beetle'], + locations_dict['Monster Fibula: Moon Beetle'], + locations_dict['Monster Fibula: Pandza'], + locations_dict['Monster Fibula: Aranetarda'], + locations_dict['Monster Fibula: Hillkat Bandleader'], + locations_dict['Monster Fibula: Blue Hedgehag'], + locations_dict['Monster Fibula: Infected Digmo'], + locations_dict['Monster Fibula: Peng King Dakara'], + locations_dict['Monster Fibula: X01 Driller H.F.S.'], + locations_dict["Monster Fibula: Ti'im"], + locations_dict['Monster Fibula: Cursed Sharkster'], + locations_dict["Monster Fibula: Pinzo'jrahrrrn"], + locations_dict['Monster Fibula: Master Magmoth'], + locations_dict['Monster Fibula: Guard Billston'], + locations_dict['Monster Fibula: Hologram Frobbit'], + locations_dict['Monster Fibula: Smelter Digmo'], + locations_dict['Monster Fibula: Blazehoof'], + locations_dict['Monster Fibula: Plasma Phantom'], + locations_dict['Monster Fibula: Sir Blobus Starnikus'], + locations_dict['Monster Fibula: Tiefsee Angler'], + locations_dict['Monster Fibula: Son of the East'], + locations_dict['Monster Fibula: Ancient Guardian'], + locations_dict['Monster Fibula: Karotto Fruitseeker'], + locations_dict['Monster Fibula: Buff Bloomy'], + locations_dict['Monster Fibula: Twilight Master'], + locations_dict['Monster Fibula: King Kaktorro'], + locations_dict["Monster Fibula: DON'T USE THIS"], + locations_dict['Monster Fibula: Designer'], + locations_dict['Monster Fibula: The Creator'], + locations_dict['Monster Fibula: Pandza Mk. II'], + locations_dict['Monster Fibula: Echinoignis'], + locations_dict['Monster Fibula: Echinonix'], + locations_dict['Monster Fibula: Echinofulgur'], + locations_dict['Monster Fibula: Echinofluctus'], + locations_dict['Monster Fibula: Salteric'], + locations_dict['Monster Fibula: Balooneer'], + locations_dict["Monster Fibula: K'im"], + locations_dict['Monster Fibula: Trigenbu'], + locations_dict['Monster Fibula: Heat Crystalid'], + locations_dict['Monster Fibula: Cold Crystalid'], + locations_dict['Monster Fibula: Shock Crystalid'], + locations_dict['Monster Fibula: Wave Crystalid'], + locations_dict['Monster Fibula: Hummagnum'], + locations_dict['Monster Fibula: Mizree'], + locations_dict['Monster Fibula: Beearbot'], + locations_dict['Monster Fibula: Illegal Coordinator'], + locations_dict['Monster Fibula: Tremmy'], + locations_dict['Monster Fibula: Distillizer'], + locations_dict['Monster Fibula: Toxovolt'], + locations_dict['Monster Fibula: Papaboss the Younger'], + locations_dict['Monster Fibula: Hillcart'], + locations_dict['Monster Fibula: The Goatfather'], + locations_dict['Monster Fibula: Guardian Statue'], + locations_dict['Monster Fibula: Gynthar'], + locations_dict["Monster Fibula: Di'orbis"], + locations_dict['Monster Fibula: Son of the Beach'], }, - "Kills": { - locations_dict['Killsanity: Hedgehag'], - locations_dict["Killsanity: Rockin' Hillkat"], - locations_dict['Killsanity: Mad Bovine'], - locations_dict['Killsanity: Old Hedgehag'], - locations_dict["Killsanity: Flamin' Hillkat"], - locations_dict['Killsanity: Red Eyed Bovine'], - locations_dict['Killsanity: Young Frobbit'], - locations_dict['Killsanity: White Frobbit'], - locations_dict['Killsanity: Seafly'], - locations_dict['Killsanity: Pengpeng'], - locations_dict['Killsanity: Horny Goat'], - locations_dict['Killsanity: Karotto'], - locations_dict['Killsanity: Fleazer'], - locations_dict['Killsanity: Carritrich'], - locations_dict['Killsanity: Kamikatze'], - locations_dict['Killsanity: Digmo'], - locations_dict['Killsanity: Pinceron'], - locations_dict['Killsanity: Sharkster'], - locations_dict['Killsanity: Vulturbine'], - locations_dict['Killsanity: Drillertoise'], - locations_dict['Killsanity: Tim'], - locations_dict['Killsanity: Boss Pincer'], - locations_dict['Killsanity: Trijelly'], - locations_dict['Killsanity: Pada Moth'], - locations_dict['Killsanity: Darth Moth'], - locations_dict['Killsanity: Magmanizer'], - locations_dict['Killsanity: Radical Hedgehag'], - locations_dict["Killsanity: Chillin' Hillkat"], - locations_dict['Killsanity: Fallfly'], - locations_dict['Killsanity: Ivory Bovine'], - locations_dict['Killsanity: Neutral Virus'], - locations_dict['Killsanity: Heat Virus'], - locations_dict['Killsanity: Cold Virus'], - locations_dict['Killsanity: Argeby'], - locations_dict['Killsanity: Gelleric'], - locations_dict['Killsanity: Papagun'], - locations_dict['Killsanity: Angler'], - locations_dict['Killsanity: Shokat'], - locations_dict['Killsanity: Behesloth'], - locations_dict['Killsanity: Jelleric'], - locations_dict['Killsanity: Ocubepus'], - locations_dict['Killsanity: Blue Ray'], - locations_dict['Killsanity: Rob0ck'], - locations_dict['Killsanity: Powerplant'], - locations_dict['Killsanity: Ectovolt'], - locations_dict['Killsanity: Sun Beetle'], - locations_dict['Killsanity: Moon Beetle'], - locations_dict['Killsanity: Pandza'], - locations_dict['Killsanity: Aranetarda'], - locations_dict['Killsanity: Hillkat Bandleader'], - locations_dict['Killsanity: Blue Hedgehag'], - locations_dict['Killsanity: Infected Digmo'], - locations_dict['Killsanity: Peng King Dakara'], - locations_dict['Killsanity: X01 Driller H.F.S.'], - locations_dict["Killsanity: Ti'im"], - locations_dict['Killsanity: Cursed Sharkster'], - locations_dict["Killsanity: Pinzo'jrahrrrn"], - locations_dict['Killsanity: Master Magmoth'], - locations_dict['Killsanity: Guard Billston'], - locations_dict['Killsanity: Hologram Frobbit'], - locations_dict['Killsanity: Smelter Digmo'], - locations_dict['Killsanity: Blazehoof'], - locations_dict['Killsanity: Plasma Phantom'], - locations_dict['Killsanity: Sir Blobus Starnikus'], - locations_dict['Killsanity: Tiefsee Angler'], - locations_dict['Killsanity: Son of the East'], - locations_dict['Killsanity: Ancient Guardian'], - locations_dict['Killsanity: Karotto Fruitseeker'], - locations_dict['Killsanity: Buff Bloomy'], - locations_dict['Killsanity: Twilight Master'], - locations_dict['Killsanity: King Kaktorro'], - locations_dict["Killsanity: DON'T USE THIS"], - locations_dict['Killsanity: Designer'], - locations_dict['Killsanity: The Creator'], - locations_dict['Killsanity: Pandza Mk. II'], - locations_dict['Killsanity: Echinoignis'], - locations_dict['Killsanity: Echinonix'], - locations_dict['Killsanity: Echinofulgur'], - locations_dict['Killsanity: Echinofluctus'], - locations_dict['Killsanity: Salteric'], - locations_dict['Killsanity: Balooneer'], - locations_dict["Killsanity: K'im"], - locations_dict['Killsanity: Trigenbu'], - locations_dict['Killsanity: Heat Crystalid'], - locations_dict['Killsanity: Cold Crystalid'], - locations_dict['Killsanity: Shock Crystalid'], - locations_dict['Killsanity: Wave Crystalid'], - locations_dict['Killsanity: Hummagnum'], - locations_dict['Killsanity: Mizree'], - locations_dict['Killsanity: Beearbot'], - locations_dict['Killsanity: Illegal Coordinator'], - locations_dict['Killsanity: Tremmy'], - locations_dict['Killsanity: Distillizer'], - locations_dict['Killsanity: Toxovolt'], - locations_dict['Killsanity: Papaboss the Younger'], - locations_dict['Killsanity: Hillcart'], - locations_dict['Killsanity: The Goatfather'], - locations_dict['Killsanity: Guardian Statue'], - locations_dict['Killsanity: Gynthar'], - locations_dict["Killsanity: Di'orbis"], - locations_dict['Killsanity: Son of the Beach'], + "Autumn's Rise Monster Defeats": { + locations_dict['Monster Fibula: Hedgehag'], + locations_dict["Monster Fibula: Rockin' Hillkat"], + locations_dict['Monster Fibula: Mad Bovine'], + locations_dict['Monster Fibula: Old Hedgehag'], + locations_dict["Monster Fibula: Flamin' Hillkat"], + locations_dict['Monster Fibula: Red Eyed Bovine'], + locations_dict['Monster Fibula: Hillkat Bandleader'], + locations_dict['Monster Fibula: Blue Hedgehag'], + locations_dict['Monster Fibula: Illegal Coordinator'], }, - "Bergen Trail Kills": { - locations_dict['Killsanity: Young Frobbit'], - locations_dict['Killsanity: White Frobbit'], - locations_dict['Killsanity: Seafly'], - locations_dict['Killsanity: Pengpeng'], - locations_dict['Killsanity: Horny Goat'], - locations_dict['Killsanity: Karotto'], - locations_dict['Killsanity: Peng King Dakara'], + "Bergen Trail Monster Defeats": { + locations_dict['Monster Fibula: Young Frobbit'], + locations_dict['Monster Fibula: White Frobbit'], + locations_dict['Monster Fibula: Seafly'], + locations_dict['Monster Fibula: Pengpeng'], + locations_dict['Monster Fibula: Horny Goat'], + locations_dict['Monster Fibula: Karotto'], + locations_dict['Monster Fibula: Peng King Dakara'], }, - "Temple Mine Kills": { - locations_dict['Killsanity: Fleazer'], - locations_dict['Killsanity: Carritrich'], - locations_dict['Killsanity: Kamikatze'], - locations_dict['Killsanity: Digmo'], - locations_dict['Killsanity: Infected Digmo'], - locations_dict['Killsanity: X01 Driller H.F.S.'], - locations_dict['Killsanity: Smelter Digmo'], + "Temple Mine Monster Defeats": { + locations_dict['Monster Fibula: Fleazer'], + locations_dict['Monster Fibula: Carritrich'], + locations_dict['Monster Fibula: Kamikatze'], + locations_dict['Monster Fibula: Digmo'], + locations_dict['Monster Fibula: Infected Digmo'], + locations_dict['Monster Fibula: X01 Driller H.F.S.'], + locations_dict['Monster Fibula: Smelter Digmo'], }, - "Maroon Valley Kills": { - locations_dict['Killsanity: Pinceron'], - locations_dict['Killsanity: Sharkster'], - locations_dict['Killsanity: Vulturbine'], - locations_dict['Killsanity: Drillertoise'], - locations_dict['Killsanity: Tim'], - locations_dict['Killsanity: Boss Pincer'], - locations_dict["Killsanity: Ti'im"], - locations_dict['Killsanity: Cursed Sharkster'], - locations_dict['Killsanity: Guard Billston'], - locations_dict['Killsanity: King Kaktorro'], - locations_dict["Killsanity: DON'T USE THIS"], + "Maroon Valley Monster Defeats": { + locations_dict['Monster Fibula: Pinceron'], + locations_dict['Monster Fibula: Sharkster'], + locations_dict['Monster Fibula: Vulturbine'], + locations_dict['Monster Fibula: Drillertoise'], + locations_dict['Monster Fibula: Tim'], + locations_dict['Monster Fibula: Boss Pincer'], + locations_dict["Monster Fibula: Ti'im"], + locations_dict['Monster Fibula: Cursed Sharkster'], + locations_dict['Monster Fibula: Guard Billston'], + locations_dict['Monster Fibula: King Kaktorro'], + locations_dict["Monster Fibula: DON'T USE THIS"], }, - "Faj'ro Temple Kills": { - locations_dict['Killsanity: Trijelly'], - locations_dict['Killsanity: Pada Moth'], - locations_dict['Killsanity: Darth Moth'], - locations_dict['Killsanity: Magmanizer'], - locations_dict["Killsanity: Pinzo'jrahrrrn"], - locations_dict['Killsanity: Master Magmoth'], + "Faj'ro Temple Monster Defeats": { + locations_dict['Monster Fibula: Trijelly'], + locations_dict['Monster Fibula: Pada Moth'], + locations_dict['Monster Fibula: Darth Moth'], + locations_dict['Monster Fibula: Magmanizer'], + locations_dict["Monster Fibula: Pinzo'jrahrrrn"], + locations_dict['Monster Fibula: Master Magmoth'], }, - "Autumn's Fall Kills": { - locations_dict['Killsanity: Radical Hedgehag'], - locations_dict["Killsanity: Chillin' Hillkat"], - locations_dict['Killsanity: Fallfly'], - locations_dict['Killsanity: Ivory Bovine'], - locations_dict['Killsanity: Hologram Frobbit'], - locations_dict['Killsanity: Blazehoof'], + "Autumn's Fall Monster Defeats": { + locations_dict['Monster Fibula: Radical Hedgehag'], + locations_dict["Monster Fibula: Chillin' Hillkat"], + locations_dict['Monster Fibula: Fallfly'], + locations_dict['Monster Fibula: Ivory Bovine'], + locations_dict['Monster Fibula: Hologram Frobbit'], + locations_dict['Monster Fibula: Blazehoof'], }, - "Vermillion Wasteland Kills": { - locations_dict['Killsanity: Neutral Virus'], - locations_dict['Killsanity: Heat Virus'], - locations_dict['Killsanity: Cold Virus'], - locations_dict['Killsanity: Designer'], + "Vermillion Wasteland Monster Defeats": { + locations_dict['Monster Fibula: Neutral Virus'], + locations_dict['Monster Fibula: Heat Virus'], + locations_dict['Monster Fibula: Cold Virus'], + locations_dict['Monster Fibula: Designer'], }, - "Gaia's Garden Kills": { - locations_dict['Killsanity: Argeby'], - locations_dict['Killsanity: Gelleric'], - locations_dict['Killsanity: Papagun'], - locations_dict['Killsanity: Angler'], - locations_dict['Killsanity: Shokat'], - locations_dict['Killsanity: Behesloth'], - locations_dict['Killsanity: Tiefsee Angler'], - locations_dict['Killsanity: Karotto Fruitseeker'], - locations_dict['Killsanity: Buff Bloomy'], - locations_dict['Killsanity: Toxovolt'], + "Gaia's Garden Monster Defeats": { + locations_dict['Monster Fibula: Argeby'], + locations_dict['Monster Fibula: Gelleric'], + locations_dict['Monster Fibula: Papagun'], + locations_dict['Monster Fibula: Angler'], + locations_dict['Monster Fibula: Shokat'], + locations_dict['Monster Fibula: Behesloth'], + locations_dict['Monster Fibula: Tiefsee Angler'], + locations_dict['Monster Fibula: Karotto Fruitseeker'], + locations_dict['Monster Fibula: Buff Bloomy'], + locations_dict['Monster Fibula: Toxovolt'], }, - "So'najiz Temple Kills": { - locations_dict['Killsanity: Jelleric'], - locations_dict['Killsanity: Ocubepus'], - locations_dict['Killsanity: Blue Ray'], - locations_dict['Killsanity: Sir Blobus Starnikus'], + "So'najiz Temple Monster Defeats": { + locations_dict['Monster Fibula: Jelleric'], + locations_dict['Monster Fibula: Ocubepus'], + locations_dict['Monster Fibula: Blue Ray'], + locations_dict['Monster Fibula: Sir Blobus Starnikus'], }, - "Zir'vitar Temple Kills": { - locations_dict['Killsanity: Rob0ck'], - locations_dict['Killsanity: Powerplant'], - locations_dict['Killsanity: Ectovolt'], - locations_dict['Killsanity: Plasma Phantom'], + "Zir'vitar Temple Monster Defeats": { + locations_dict['Monster Fibula: Rob0ck'], + locations_dict['Monster Fibula: Powerplant'], + locations_dict['Monster Fibula: Ectovolt'], + locations_dict['Monster Fibula: Plasma Phantom'], }, - "Sapphire Ridge Kills": { - locations_dict['Killsanity: Sun Beetle'], - locations_dict['Killsanity: Moon Beetle'], - locations_dict['Killsanity: Pandza'], - locations_dict['Killsanity: Aranetarda'], - locations_dict['Killsanity: Twilight Master'], - locations_dict['Killsanity: Pandza Mk. II'], + "Sapphire Ridge Monster Defeats": { + locations_dict['Monster Fibula: Sun Beetle'], + locations_dict['Monster Fibula: Moon Beetle'], + locations_dict['Monster Fibula: Pandza'], + locations_dict['Monster Fibula: Aranetarda'], + locations_dict['Monster Fibula: Twilight Master'], + locations_dict['Monster Fibula: Pandza Mk. II'], }, - "Grand Krys'kajo Kills": { - locations_dict['Killsanity: Son of the East'], - locations_dict['Killsanity: Ancient Guardian'], + "Grand Krys'kajo Monster Defeats": { + locations_dict['Monster Fibula: Son of the East'], + locations_dict['Monster Fibula: Ancient Guardian'], }, "Vermillion Tower": { - locations_dict['Killsanity: The Creator'], + locations_dict['Monster Fibula: The Creator'], }, - "Vermillion Tower Kills": { - locations_dict['Killsanity: The Creator'], + "Vermillion Tower Monster Defeats": { + locations_dict['Monster Fibula: The Creator'], }, - "Azure Archipelago Kills": { - locations_dict['Killsanity: Echinoignis'], - locations_dict['Killsanity: Echinonix'], - locations_dict['Killsanity: Echinofulgur'], - locations_dict['Killsanity: Echinofluctus'], - locations_dict['Killsanity: Salteric'], - locations_dict['Killsanity: Balooneer'], - locations_dict["Killsanity: K'im"], - locations_dict['Killsanity: Trigenbu'], - locations_dict['Killsanity: Son of the Beach'], + "Azure Archipelago Monster Defeats": { + locations_dict['Monster Fibula: Echinoignis'], + locations_dict['Monster Fibula: Echinonix'], + locations_dict['Monster Fibula: Echinofulgur'], + locations_dict['Monster Fibula: Echinofluctus'], + locations_dict['Monster Fibula: Salteric'], + locations_dict['Monster Fibula: Balooneer'], + locations_dict["Monster Fibula: K'im"], + locations_dict['Monster Fibula: Trigenbu'], + locations_dict['Monster Fibula: Son of the Beach'], }, - "Ku'lero Temple Kills": { - locations_dict['Killsanity: Heat Crystalid'], - locations_dict['Killsanity: Cold Crystalid'], - locations_dict['Killsanity: Shock Crystalid'], - locations_dict['Killsanity: Wave Crystalid'], - locations_dict['Killsanity: Hummagnum'], - locations_dict['Killsanity: Mizree'], - locations_dict['Killsanity: Beearbot'], - locations_dict['Killsanity: Guardian Statue'], - locations_dict['Killsanity: Gynthar'], - locations_dict["Killsanity: Di'orbis"], + "Ku'lero Temple Monster Defeats": { + locations_dict['Monster Fibula: Heat Crystalid'], + locations_dict['Monster Fibula: Cold Crystalid'], + locations_dict['Monster Fibula: Shock Crystalid'], + locations_dict['Monster Fibula: Wave Crystalid'], + locations_dict['Monster Fibula: Hummagnum'], + locations_dict['Monster Fibula: Mizree'], + locations_dict['Monster Fibula: Beearbot'], + locations_dict['Monster Fibula: Guardian Statue'], + locations_dict['Monster Fibula: Gynthar'], + locations_dict["Monster Fibula: Di'orbis"], }, - "Rhombus Square Kills": { - locations_dict['Killsanity: Tremmy'], - locations_dict['Killsanity: Hillcart'], - locations_dict['Killsanity: The Goatfather'], + "Rhombus Square Monster Defeats": { + locations_dict['Monster Fibula: Tremmy'], + locations_dict['Monster Fibula: Hillcart'], + locations_dict['Monster Fibula: The Goatfather'], }, - "Ba'kii Kum Kills": { - locations_dict['Killsanity: Distillizer'], + "Ba'kii Kum Monster Defeats": { + locations_dict['Monster Fibula: Distillizer'], }, - "Basin Keep Kills": { - locations_dict['Killsanity: Papaboss the Younger'], + "Basin Keep Monster Defeats": { + locations_dict['Monster Fibula: Papaboss the Younger'], }, } \ No newline at end of file diff --git a/worlds/crosscode/options.py b/worlds/crosscode/options.py index 5182855e63fb..4011cdfbcaa4 100644 --- a/worlds/crosscode/options.py +++ b/worlds/crosscode/options.py @@ -209,9 +209,9 @@ class ShopDialogHints(DefaultOnToggle): """ display_name = "Shop Dialog Hints" -class Killsanity(Toggle): +class MonsterFibulaRandomization(Toggle): """ - If enabled, killing every enemy is a check. + If enabled, defeating every enemy is a check. """ class CombatLogic(OptionSet): @@ -621,7 +621,7 @@ class CrossCodeOptions(PerGameCommonOptions): shop_send_mode: ShopSendMode shop_receive_mode: ShopReceiveMode - killsanity: Killsanity + monster_fibula_randomization: MonsterFibulaRandomization allow_booster_grinding: AllowBoosterGrinding combat_logic: CombatLogic maximum_grind_gap: MaximumGrindGap @@ -685,7 +685,7 @@ class CrossCodeOptions(PerGameCommonOptions): OptionGroup( name="Combat", options=[ - Killsanity, + MonsterFibulaRandomization, CombatLogic, MaximumGrindGap, AllowBoosterGrinding, From ac2cd569442f9bc3d85e532e8b67644b1df9f988 Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Mon, 24 Aug 2026 00:53:42 -0600 Subject: [PATCH 22/23] add equipment data to items in codegen --- worlds/crosscode/codegen/ast.py | 6 + worlds/crosscode/codegen/parse.py | 8 +- worlds/crosscode/items.py | 506 +++++++++---------- worlds/crosscode/templates/items.template.py | 2 +- worlds/crosscode/types/items.py | 6 + 5 files changed, 273 insertions(+), 255 deletions(-) diff --git a/worlds/crosscode/codegen/ast.py b/worlds/crosscode/codegen/ast.py index c63b0356283e..78dcc7ab6e77 100644 --- a/worlds/crosscode/codegen/ast.py +++ b/worlds/crosscode/codegen/ast.py @@ -176,6 +176,12 @@ def create_expression_single_item(data: SingleItemData): value=ast.Constant(True) )) + if data.equip_data is not None: + ast_item.keywords.append(ast.keyword( + arg="equip_data", + value=create_expression_dataclass(data.equip_data) + )) + ast.fix_missing_locations(ast_item) return ast_item diff --git a/worlds/crosscode/codegen/parse.py b/worlds/crosscode/codegen/parse.py index 9843d496da11..56d9a5b4d13b 100644 --- a/worlds/crosscode/codegen/parse.py +++ b/worlds/crosscode/codegen/parse.py @@ -10,7 +10,7 @@ from .context import Context from .util import BASE_ID, RESERVED_ITEM_IDS, get_item_classification -from ..types.items import ItemData, ProgressiveChainEntry, ProgressiveItemChain, ProgressiveItemChainSingle, ProgressiveItemChainMulti, ProgressiveItemSubchain, SingleItemData +from ..types.items import ItemData, ProgressiveChainEntry, ProgressiveItemChain, ProgressiveItemChainSingle, ProgressiveItemChainMulti, ProgressiveItemSubchain, SingleItemData, EquipmentData from ..types.locations import AccessInfo, Condition from ..types.regions import Goal, RegionConnection, RegionsData from ..types.condition import * @@ -228,6 +228,12 @@ def parse_item_data(self, name: str, raw: dict[str, typing.Any]) -> tuple[Single amount=1 ) + if db_entry.get("type", None) == "EQUIP" and raw.get("providesLevels", True): + single_item.equip_data = EquipmentData( + equip_type=db_entry["equipType"], + level=self.ctx.item_data[single_item.item_id]["level"], + ) + return single_item, item def parse_item_reward(self, raw: list[typing.Any]) -> ItemData: diff --git a/worlds/crosscode/items.py b/worlds/crosscode/items.py index 89bd3dc33d2f..fa9fe8358df1 100644 --- a/worlds/crosscode/items.py +++ b/worlds/crosscode/items.py @@ -7,7 +7,7 @@ from BaseClasses import ItemClassification from worlds.crosscode.types.items import get_info_from_full_name from .util import KeyDefaultDict -from .types.items import ItemData, SingleItemData +from .types.items import EquipmentData, ItemData, SingleItemData num_items = 676 @@ -384,51 +384,51 @@ 'Sweet Berry Tea': SingleItemData(item_id=3, name='Sweet Berry Tea', classification=ItemClassification.filler), 'Masterball': SingleItemData(item_id=6, name='Masterball', classification=ItemClassification.filler, unique=True), 'Blue Shell': SingleItemData(item_id=7, name='Blue Shell', classification=ItemClassification.filler, unique=True), - 'Hardwood Stave': SingleItemData(item_id=8, name='Hardwood Stave', classification=ItemClassification.progression_skip_balancing, unique=True), - "Miner's Helmet": SingleItemData(item_id=9, name="Miner's Helmet", classification=ItemClassification.progression_skip_balancing, unique=True), - 'Lunatic Paws': SingleItemData(item_id=10, name='Lunatic Paws', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Timeworn Belt': SingleItemData(item_id=11, name='Timeworn Belt', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Humming Razor': SingleItemData(item_id=13, name='Humming Razor', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Scarecrown': SingleItemData(item_id=15, name='Scarecrown', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Hardwood Stave': SingleItemData(item_id=8, name='Hardwood Stave', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=20)), + "Miner's Helmet": SingleItemData(item_id=9, name="Miner's Helmet", classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=25)), + 'Lunatic Paws': SingleItemData(item_id=10, name='Lunatic Paws', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=60)), + 'Timeworn Belt': SingleItemData(item_id=11, name='Timeworn Belt', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=49)), + 'Humming Razor': SingleItemData(item_id=13, name='Humming Razor', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=36)), + 'Scarecrown': SingleItemData(item_id=15, name='Scarecrown', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=44)), 'Holiday Boots': SingleItemData(item_id=16, name='Holiday Boots', classification=ItemClassification.filler, unique=True), 'Dungeon Heart': SingleItemData(item_id=18, name='Dungeon Heart', classification=ItemClassification.filler, unique=True), - 'Rookiehat': SingleItemData(item_id=23, name='Rookiehat', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Rookieblade': SingleItemData(item_id=24, name='Rookieblade', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Rookieboots': SingleItemData(item_id=25, name='Rookieboots', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Rookiebelt': SingleItemData(item_id=26, name='Rookiebelt', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Rookiehat': SingleItemData(item_id=23, name='Rookiehat', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=1)), + 'Rookieblade': SingleItemData(item_id=24, name='Rookieblade', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=1)), + 'Rookieboots': SingleItemData(item_id=25, name='Rookieboots', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=1)), + 'Rookiebelt': SingleItemData(item_id=26, name='Rookiebelt', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=1)), 'Hi-Sandwich': SingleItemData(item_id=27, name='Hi-Sandwich', classification=ItemClassification.filler), 'Chef Sandwich': SingleItemData(item_id=28, name='Chef Sandwich', classification=ItemClassification.filler), - 'Bronze Edge': SingleItemData(item_id=29, name='Bronze Edge', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Bronze Mail': SingleItemData(item_id=30, name='Bronze Mail', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Bronze Goggles': SingleItemData(item_id=31, name='Bronze Goggles', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Bronze Boots': SingleItemData(item_id=32, name='Bronze Boots', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Grasswalkers': SingleItemData(item_id=33, name='Grasswalkers', classification=ItemClassification.progression_skip_balancing, unique=True), - "Explorer's Cap": SingleItemData(item_id=34, name="Explorer's Cap", classification=ItemClassification.progression_skip_balancing, unique=True), - "Edge o' All": SingleItemData(item_id=35, name="Edge o' All", classification=ItemClassification.progression_skip_balancing, unique=True), - 'Second Hide': SingleItemData(item_id=36, name='Second Hide', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Civilian Trigger': SingleItemData(item_id=37, name='Civilian Trigger', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Winterclaw': SingleItemData(item_id=38, name='Winterclaw', classification=ItemClassification.progression_skip_balancing, unique=True), - "Winner's Pride": SingleItemData(item_id=39, name="Winner's Pride", classification=ItemClassification.progression_skip_balancing, unique=True), + 'Bronze Edge': SingleItemData(item_id=29, name='Bronze Edge', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=9)), + 'Bronze Mail': SingleItemData(item_id=30, name='Bronze Mail', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=9)), + 'Bronze Goggles': SingleItemData(item_id=31, name='Bronze Goggles', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=9)), + 'Bronze Boots': SingleItemData(item_id=32, name='Bronze Boots', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=9)), + 'Grasswalkers': SingleItemData(item_id=33, name='Grasswalkers', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=5)), + "Explorer's Cap": SingleItemData(item_id=34, name="Explorer's Cap", classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=5)), + "Edge o' All": SingleItemData(item_id=35, name="Edge o' All", classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=5)), + 'Second Hide': SingleItemData(item_id=36, name='Second Hide', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=5)), + 'Civilian Trigger': SingleItemData(item_id=37, name='Civilian Trigger', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=11)), + 'Winterclaw': SingleItemData(item_id=38, name='Winterclaw', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=26)), + "Winner's Pride": SingleItemData(item_id=39, name="Winner's Pride", classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=1)), 'Mega-Sandwich': SingleItemData(item_id=40, name='Mega-Sandwich', classification=ItemClassification.filler), - 'Bovine Armor': SingleItemData(item_id=41, name='Bovine Armor', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Swiftspike': SingleItemData(item_id=42, name='Swiftspike', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Weird Skates': SingleItemData(item_id=43, name='Weird Skates', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Rusty Anchors': SingleItemData(item_id=44, name='Rusty Anchors', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Fleety Sandals': SingleItemData(item_id=45, name='Fleety Sandals', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Feline Paws': SingleItemData(item_id=46, name='Feline Paws', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Leaf Cape': SingleItemData(item_id=47, name='Leaf Cape', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Assault Vest': SingleItemData(item_id=48, name='Assault Vest', classification=ItemClassification.progression_skip_balancing, unique=True), - "Recruit's Scope": SingleItemData(item_id=49, name="Recruit's Scope", classification=ItemClassification.progression_skip_balancing, unique=True), - 'Shady Monocle': SingleItemData(item_id=50, name='Shady Monocle', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Bovine Armor': SingleItemData(item_id=41, name='Bovine Armor', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=11)), + 'Swiftspike': SingleItemData(item_id=42, name='Swiftspike', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=15)), + 'Weird Skates': SingleItemData(item_id=43, name='Weird Skates', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=26)), + 'Rusty Anchors': SingleItemData(item_id=44, name='Rusty Anchors', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=11)), + 'Fleety Sandals': SingleItemData(item_id=45, name='Fleety Sandals', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=11)), + 'Feline Paws': SingleItemData(item_id=46, name='Feline Paws', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=17)), + 'Leaf Cape': SingleItemData(item_id=47, name='Leaf Cape', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=15)), + 'Assault Vest': SingleItemData(item_id=48, name='Assault Vest', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=13)), + "Recruit's Scope": SingleItemData(item_id=49, name="Recruit's Scope", classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=11)), + 'Shady Monocle': SingleItemData(item_id=50, name='Shady Monocle', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=15)), 'Key Piece': SingleItemData(item_id=51, name='Key Piece', classification=ItemClassification.progression, unique=True), - "Winner's Proof": SingleItemData(item_id=53, name="Winner's Proof", classification=ItemClassification.progression_skip_balancing, unique=True), - 'Dented Crown': SingleItemData(item_id=54, name='Dented Crown', classification=ItemClassification.progression_skip_balancing, unique=True), - "Student's Bandana": SingleItemData(item_id=55, name="Student's Bandana", classification=ItemClassification.progression_skip_balancing, unique=True), - "Mugger's Blade": SingleItemData(item_id=56, name="Mugger's Blade", classification=ItemClassification.progression_skip_balancing, unique=True), - 'Daikon': SingleItemData(item_id=57, name='Daikon', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Hydra Fang': SingleItemData(item_id=58, name='Hydra Fang', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Scrappy Plate': SingleItemData(item_id=59, name='Scrappy Plate', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Bull Stompers': SingleItemData(item_id=60, name='Bull Stompers', classification=ItemClassification.progression_skip_balancing, unique=True), + "Winner's Proof": SingleItemData(item_id=53, name="Winner's Proof", classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=1)), + 'Dented Crown': SingleItemData(item_id=54, name='Dented Crown', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=35)), + "Student's Bandana": SingleItemData(item_id=55, name="Student's Bandana", classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=13)), + "Mugger's Blade": SingleItemData(item_id=56, name="Mugger's Blade", classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=11)), + 'Daikon': SingleItemData(item_id=57, name='Daikon', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=13)), + 'Hydra Fang': SingleItemData(item_id=58, name='Hydra Fang', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=61)), + 'Scrappy Plate': SingleItemData(item_id=59, name='Scrappy Plate', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=11)), + 'Bull Stompers': SingleItemData(item_id=60, name='Bull Stompers', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=15)), 'Perfect Karrot': SingleItemData(item_id=61, name='Perfect Karrot', classification=ItemClassification.filler, unique=True), 'Precursor Shard': SingleItemData(item_id=62, name='Precursor Shard', classification=ItemClassification.progression, unique=True), 'Cross Sandwich': SingleItemData(item_id=63, name='Cross Sandwich', classification=ItemClassification.filler), @@ -451,14 +451,14 @@ 'Headphone Scraps': SingleItemData(item_id=80, name='Headphone Scraps', classification=ItemClassification.filler, unique=True), 'Metal Needles': SingleItemData(item_id=81, name='Metal Needles', classification=ItemClassification.filler, unique=True), 'Bovine Skin': SingleItemData(item_id=82, name='Bovine Skin', classification=ItemClassification.filler, unique=True), - 'Edgy Headphones': SingleItemData(item_id=83, name='Edgy Headphones', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Climbing Pick': SingleItemData(item_id=84, name='Climbing Pick', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Boom Walkers': SingleItemData(item_id=85, name='Boom Walkers', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Edgy Headphones': SingleItemData(item_id=83, name='Edgy Headphones', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=17)), + 'Climbing Pick': SingleItemData(item_id=84, name='Climbing Pick', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=19)), + 'Boom Walkers': SingleItemData(item_id=85, name='Boom Walkers', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=40)), 'Golden Ring': SingleItemData(item_id=86, name='Golden Ring', classification=ItemClassification.filler, unique=True), 'Chili Dog': SingleItemData(item_id=87, name='Chili Dog', classification=ItemClassification.filler), 'Raw Meat': SingleItemData(item_id=88, name='Raw Meat', classification=ItemClassification.filler, unique=True), - 'Core Drill': SingleItemData(item_id=89, name='Core Drill', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Giga Spiral Drill': SingleItemData(item_id=90, name='Giga Spiral Drill', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Core Drill': SingleItemData(item_id=89, name='Core Drill', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=10)), + 'Giga Spiral Drill': SingleItemData(item_id=90, name='Giga Spiral Drill', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=30)), 'Autumn Leaves': SingleItemData(item_id=91, name='Autumn Leaves', classification=ItemClassification.filler, unique=True), 'Season Apples': SingleItemData(item_id=92, name='Season Apples', classification=ItemClassification.filler, unique=True), 'Gold Beetle': SingleItemData(item_id=93, name='Gold Beetle', classification=ItemClassification.filler, unique=True), @@ -470,7 +470,7 @@ 'Junk Metal': SingleItemData(item_id=99, name='Junk Metal', classification=ItemClassification.filler, unique=True), 'Spiral Gem': SingleItemData(item_id=100, name='Spiral Gem', classification=ItemClassification.filler, unique=True), 'Sparkly Boots': SingleItemData(item_id=101, name='Sparkly Boots', classification=ItemClassification.filler, unique=True), - "Gunner's Trigger": SingleItemData(item_id=102, name="Gunner's Trigger", classification=ItemClassification.progression_skip_balancing, unique=True), + "Gunner's Trigger": SingleItemData(item_id=102, name="Gunner's Trigger", classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=29)), 'Feather Leaf': SingleItemData(item_id=103, name='Feather Leaf', classification=ItemClassification.filler, unique=True), 'Rusty Bits': SingleItemData(item_id=104, name='Rusty Bits', classification=ItemClassification.filler, unique=True), 'Frozen Tear': SingleItemData(item_id=105, name='Frozen Tear', classification=ItemClassification.filler, unique=True), @@ -479,21 +479,21 @@ 'Winter Thorn': SingleItemData(item_id=108, name='Winter Thorn', classification=ItemClassification.filler, unique=True), 'Bergen Ice': SingleItemData(item_id=109, name='Bergen Ice', classification=ItemClassification.filler, unique=True), 'Bergen Ice Cream': SingleItemData(item_id=110, name='Bergen Ice Cream', classification=ItemClassification.filler), - 'Battered Fist': SingleItemData(item_id=111, name='Battered Fist', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Copper Gull': SingleItemData(item_id=112, name='Copper Gull', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Iron Edge': SingleItemData(item_id=113, name='Iron Edge', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Rocksplitter': SingleItemData(item_id=114, name='Rocksplitter', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Silver Hawk': SingleItemData(item_id=115, name='Silver Hawk', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Cooling Veil': SingleItemData(item_id=116, name='Cooling Veil', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Longears': SingleItemData(item_id=117, name='Longears', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Iron Goggles': SingleItemData(item_id=118, name='Iron Goggles', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Furry Cap': SingleItemData(item_id=119, name='Furry Cap', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Icewalkers': SingleItemData(item_id=120, name='Icewalkers', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Iron Boots': SingleItemData(item_id=121, name='Iron Boots', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Iron Mail': SingleItemData(item_id=122, name='Iron Mail', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Hardrock Plate': SingleItemData(item_id=123, name='Hardrock Plate', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Spiky Jacket': SingleItemData(item_id=124, name='Spiky Jacket', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Bubblebelt': SingleItemData(item_id=125, name='Bubblebelt', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Battered Fist': SingleItemData(item_id=111, name='Battered Fist', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=17)), + 'Copper Gull': SingleItemData(item_id=112, name='Copper Gull', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=21)), + 'Iron Edge': SingleItemData(item_id=113, name='Iron Edge', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=18)), + 'Rocksplitter': SingleItemData(item_id=114, name='Rocksplitter', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=21)), + 'Silver Hawk': SingleItemData(item_id=115, name='Silver Hawk', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=47)), + 'Cooling Veil': SingleItemData(item_id=116, name='Cooling Veil', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=11)), + 'Longears': SingleItemData(item_id=117, name='Longears', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=21)), + 'Iron Goggles': SingleItemData(item_id=118, name='Iron Goggles', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=18)), + 'Furry Cap': SingleItemData(item_id=119, name='Furry Cap', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=19)), + 'Icewalkers': SingleItemData(item_id=120, name='Icewalkers', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=19)), + 'Iron Boots': SingleItemData(item_id=121, name='Iron Boots', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=18)), + 'Iron Mail': SingleItemData(item_id=122, name='Iron Mail', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=18)), + 'Hardrock Plate': SingleItemData(item_id=123, name='Hardrock Plate', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=19)), + 'Spiky Jacket': SingleItemData(item_id=124, name='Spiky Jacket', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=17)), + 'Bubblebelt': SingleItemData(item_id=125, name='Bubblebelt', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=21)), 'Fluffy Fur': SingleItemData(item_id=126, name='Fluffy Fur', classification=ItemClassification.filler, unique=True), 'Rock Beak': SingleItemData(item_id=127, name='Rock Beak', classification=ItemClassification.filler, unique=True), 'Solid Bubble': SingleItemData(item_id=128, name='Solid Bubble', classification=ItemClassification.filler, unique=True), @@ -501,16 +501,16 @@ 'Spice Set': SingleItemData(item_id=130, name='Spice Set', classification=ItemClassification.filler, unique=True), 'The End': SingleItemData(item_id=131, name='The End', classification=ItemClassification.progression, unique=True), 'Echo Roll': SingleItemData(item_id=132, name='Echo Roll', classification=ItemClassification.filler), - 'Broken Gauntlet': SingleItemData(item_id=133, name='Broken Gauntlet', classification=ItemClassification.progression, unique=True), + 'Broken Gauntlet': SingleItemData(item_id=133, name='Broken Gauntlet', classification=ItemClassification.progression, unique=True, equip_data=EquipmentData(equip_type='ARM', level=1)), 'Disc of Insight': SingleItemData(item_id=135, name='Disc of Insight', classification=ItemClassification.progression, unique=True), 'Disc of Treasure': SingleItemData(item_id=136, name='Disc of Treasure', classification=ItemClassification.progression, unique=True), - 'Broken Shield': SingleItemData(item_id=137, name='Broken Shield', classification=ItemClassification.progression, unique=True), + 'Broken Shield': SingleItemData(item_id=137, name='Broken Shield', classification=ItemClassification.progression, unique=True, equip_data=EquipmentData(equip_type='ARM', level=1)), 'Autumn Ingredients': SingleItemData(item_id=138, name='Autumn Ingredients', classification=ItemClassification.progression, unique=True), 'Frosted Carrot': SingleItemData(item_id=139, name='Frosted Carrot', classification=ItemClassification.filler, unique=True), 'Perforated Tophat': SingleItemData(item_id=140, name='Perforated Tophat', classification=ItemClassification.filler, unique=True), 'Diabolic Horns': SingleItemData(item_id=141, name='Diabolic Horns', classification=ItemClassification.filler, unique=True), 'Captured Bunny': SingleItemData(item_id=142, name='Captured Bunny', classification=ItemClassification.progression, unique=True), - 'Disciple Gloves': SingleItemData(item_id=143, name='Disciple Gloves', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Disciple Gloves': SingleItemData(item_id=143, name='Disciple Gloves', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=20)), 'Capture Device': SingleItemData(item_id=144, name='Capture Device', classification=ItemClassification.progression, unique=True), 'Green Leaf Shade': SingleItemData(item_id=145, name='Green Leaf Shade', classification=ItemClassification.progression, unique=True), "Faj'ro Key": SingleItemData(item_id=146, name="Faj'ro Key", classification=ItemClassification.progression, unique=True), @@ -528,9 +528,9 @@ 'Stone of Valor': SingleItemData(item_id=158, name='Stone of Valor', classification=ItemClassification.progression, unique=True), 'Bug Shell': SingleItemData(item_id=159, name='Bug Shell', classification=ItemClassification.filler, unique=True), 'Blue Orb': SingleItemData(item_id=160, name='Blue Orb', classification=ItemClassification.filler, unique=True), - 'Proper Tophat': SingleItemData(item_id=161, name='Proper Tophat', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Proper Tophat': SingleItemData(item_id=161, name='Proper Tophat', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=20)), 'Metal Gears': SingleItemData(item_id=163, name='Metal Gears', classification=ItemClassification.filler, unique=True), - 'Ancient Sandals': SingleItemData(item_id=164, name='Ancient Sandals', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Ancient Sandals': SingleItemData(item_id=164, name='Ancient Sandals', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=25)), 'Sweet Lemonjuice': SingleItemData(item_id=165, name='Sweet Lemonjuice', classification=ItemClassification.filler), 'Hotsauce': SingleItemData(item_id=166, name='Hotsauce', classification=ItemClassification.filler), 'Vanilla Ice Cream': SingleItemData(item_id=167, name='Vanilla Ice Cream', classification=ItemClassification.filler), @@ -570,37 +570,37 @@ 'Jelly Extract': SingleItemData(item_id=201, name='Jelly Extract', classification=ItemClassification.filler, unique=True), 'Magma Residue': SingleItemData(item_id=202, name='Magma Residue', classification=ItemClassification.filler, unique=True), 'Laser Eyes': SingleItemData(item_id=203, name='Laser Eyes', classification=ItemClassification.filler, unique=True), - 'Steel Goggles': SingleItemData(item_id=204, name='Steel Goggles', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Steel Edge': SingleItemData(item_id=205, name='Steel Edge', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Steel Mail': SingleItemData(item_id=206, name='Steel Mail', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Steel Boots': SingleItemData(item_id=207, name='Steel Boots', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Fin Cap': SingleItemData(item_id=208, name='Fin Cap', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Rapier Carrot': SingleItemData(item_id=209, name='Rapier Carrot', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Dessert Vest': SingleItemData(item_id=210, name='Dessert Vest', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Desert Sandals': SingleItemData(item_id=211, name='Desert Sandals', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Nomadic Turban': SingleItemData(item_id=212, name='Nomadic Turban', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Chilling Veil': SingleItemData(item_id=213, name='Chilling Veil', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Shiny Glasses': SingleItemData(item_id=214, name='Shiny Glasses', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Magic Robe': SingleItemData(item_id=215, name='Magic Robe', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Assassin Garb': SingleItemData(item_id=216, name='Assassin Garb', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Crystal Plate': SingleItemData(item_id=217, name='Crystal Plate', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Curly Slippers': SingleItemData(item_id=218, name='Curly Slippers', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Lavish Anchors': SingleItemData(item_id=219, name='Lavish Anchors', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Carpet Runners': SingleItemData(item_id=220, name='Carpet Runners', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Hidden Blade': SingleItemData(item_id=221, name='Hidden Blade', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Maverick Edge': SingleItemData(item_id=222, name='Maverick Edge', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Western Starfist': SingleItemData(item_id=223, name='Western Starfist', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Steel Goggles': SingleItemData(item_id=204, name='Steel Goggles', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=27)), + 'Steel Edge': SingleItemData(item_id=205, name='Steel Edge', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=27)), + 'Steel Mail': SingleItemData(item_id=206, name='Steel Mail', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=27)), + 'Steel Boots': SingleItemData(item_id=207, name='Steel Boots', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=27)), + 'Fin Cap': SingleItemData(item_id=208, name='Fin Cap', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=24)), + 'Rapier Carrot': SingleItemData(item_id=209, name='Rapier Carrot', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=24)), + 'Dessert Vest': SingleItemData(item_id=210, name='Dessert Vest', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=24)), + 'Desert Sandals': SingleItemData(item_id=211, name='Desert Sandals', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=24)), + 'Nomadic Turban': SingleItemData(item_id=212, name='Nomadic Turban', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=28)), + 'Chilling Veil': SingleItemData(item_id=213, name='Chilling Veil', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=30)), + 'Shiny Glasses': SingleItemData(item_id=214, name='Shiny Glasses', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=31)), + 'Magic Robe': SingleItemData(item_id=215, name='Magic Robe', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=30)), + 'Assassin Garb': SingleItemData(item_id=216, name='Assassin Garb', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=29)), + 'Crystal Plate': SingleItemData(item_id=217, name='Crystal Plate', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=31)), + 'Curly Slippers': SingleItemData(item_id=218, name='Curly Slippers', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=28)), + 'Lavish Anchors': SingleItemData(item_id=219, name='Lavish Anchors', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=29)), + 'Carpet Runners': SingleItemData(item_id=220, name='Carpet Runners', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=30)), + 'Hidden Blade': SingleItemData(item_id=221, name='Hidden Blade', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=28)), + 'Maverick Edge': SingleItemData(item_id=222, name='Maverick Edge', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=30)), + 'Western Starfist': SingleItemData(item_id=223, name='Western Starfist', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=31)), 'Bergen Probe': SingleItemData(item_id=224, name='Bergen Probe', classification=ItemClassification.progression, unique=True), 'Blue Ice Shade': SingleItemData(item_id=225, name='Blue Ice Shade', classification=ItemClassification.progression, unique=True), 'Steak, rare': SingleItemData(item_id=226, name='Steak, rare', classification=ItemClassification.filler), 'Stone of Space': SingleItemData(item_id=227, name='Stone of Space', classification=ItemClassification.progression, unique=True), - "Thief's Band": SingleItemData(item_id=228, name="Thief's Band", classification=ItemClassification.progression_skip_balancing, unique=True), - 'Mighty Strand': SingleItemData(item_id=229, name='Mighty Strand', classification=ItemClassification.progression_skip_balancing, unique=True), + "Thief's Band": SingleItemData(item_id=228, name="Thief's Band", classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=25)), + 'Mighty Strand': SingleItemData(item_id=229, name='Mighty Strand', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=25)), 'Red Flame Shade': SingleItemData(item_id=230, name='Red Flame Shade', classification=ItemClassification.progression, unique=True), 'Purple Bolt Shade': SingleItemData(item_id=231, name='Purple Bolt Shade', classification=ItemClassification.progression, unique=True), - 'Meister Gloves': SingleItemData(item_id=233, name='Meister Gloves', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Meister Gloves': SingleItemData(item_id=233, name='Meister Gloves', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=67)), 'Aspiration Proof': SingleItemData(item_id=234, name='Aspiration Proof', classification=ItemClassification.progression, unique=True), - 'Wooly Socks': SingleItemData(item_id=235, name='Wooly Socks', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Wooly Socks': SingleItemData(item_id=235, name='Wooly Socks', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=20)), 'Maroon Cave Pass': SingleItemData(item_id=236, name='Maroon Cave Pass', classification=ItemClassification.progression, unique=True), 'Shiny Orb': SingleItemData(item_id=237, name='Shiny Orb', classification=ItemClassification.progression, unique=True), 'Laser Pickaxe': SingleItemData(item_id=238, name='Laser Pickaxe', classification=ItemClassification.progression, unique=True), @@ -628,14 +628,14 @@ 'Galaxy Berry': SingleItemData(item_id=261, name='Galaxy Berry', classification=ItemClassification.progression, unique=True), 'Royal Hive': SingleItemData(item_id=262, name='Royal Hive', classification=ItemClassification.filler, unique=True), 'Progression Proof': SingleItemData(item_id=263, name='Progression Proof', classification=ItemClassification.progression, unique=True), - 'Silver Goggles': SingleItemData(item_id=264, name='Silver Goggles', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Titan Goggles': SingleItemData(item_id=265, name='Titan Goggles', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Silver Edge': SingleItemData(item_id=266, name='Silver Edge', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Titan Edge': SingleItemData(item_id=267, name='Titan Edge', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Silver Mail': SingleItemData(item_id=268, name='Silver Mail', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Titan Mail': SingleItemData(item_id=269, name='Titan Mail', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Silver Boots': SingleItemData(item_id=270, name='Silver Boots', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Titan Boots': SingleItemData(item_id=271, name='Titan Boots', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Silver Goggles': SingleItemData(item_id=264, name='Silver Goggles', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=34)), + 'Titan Goggles': SingleItemData(item_id=265, name='Titan Goggles', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=42)), + 'Silver Edge': SingleItemData(item_id=266, name='Silver Edge', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=34)), + 'Titan Edge': SingleItemData(item_id=267, name='Titan Edge', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=42)), + 'Silver Mail': SingleItemData(item_id=268, name='Silver Mail', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=34)), + 'Titan Mail': SingleItemData(item_id=269, name='Titan Mail', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=42)), + 'Silver Boots': SingleItemData(item_id=270, name='Silver Boots', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=34)), + 'Titan Boots': SingleItemData(item_id=271, name='Titan Boots', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=42)), "Zir'vitar Key": SingleItemData(item_id=272, name="Zir'vitar Key", classification=ItemClassification.progression, unique=True), 'GIT': SingleItemData(item_id=273, name='GIT', classification=ItemClassification.progression, unique=True), 'Static Furball': SingleItemData(item_id=274, name='Static Furball', classification=ItemClassification.filler, unique=True), @@ -651,33 +651,33 @@ 'Glow Pear': SingleItemData(item_id=284, name='Glow Pear', classification=ItemClassification.filler, unique=True), 'Disc of Flora': SingleItemData(item_id=285, name='Disc of Flora', classification=ItemClassification.progression, unique=True), 'Azure Drop Shade': SingleItemData(item_id=286, name='Azure Drop Shade', classification=ItemClassification.progression, unique=True), - 'Strawhat': SingleItemData(item_id=287, name='Strawhat', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Strawhat': SingleItemData(item_id=287, name='Strawhat', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=25)), 'Gaia Temple Pass': SingleItemData(item_id=288, name='Gaia Temple Pass', classification=ItemClassification.progression, unique=True), 'Prime Pistachios': SingleItemData(item_id=289, name='Prime Pistachios', classification=ItemClassification.filler), 'Salted Peanuts': SingleItemData(item_id=290, name='Salted Peanuts', classification=ItemClassification.filler), "Cup o' Coffee": SingleItemData(item_id=291, name="Cup o' Coffee", classification=ItemClassification.filler), 'Energy Espresso': SingleItemData(item_id=292, name='Energy Espresso', classification=ItemClassification.filler), - 'Nifty Grey Shades': SingleItemData(item_id=293, name='Nifty Grey Shades', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Red Bandana': SingleItemData(item_id=294, name='Red Bandana', classification=ItemClassification.progression_skip_balancing, unique=True), - "Electrician's Cap": SingleItemData(item_id=295, name="Electrician's Cap", classification=ItemClassification.progression_skip_balancing, unique=True), - 'Faedora': SingleItemData(item_id=296, name='Faedora', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Mystic Mohawk': SingleItemData(item_id=297, name='Mystic Mohawk', classification=ItemClassification.progression_skip_balancing, unique=True), - "Hunter's Bolt": SingleItemData(item_id=298, name="Hunter's Bolt", classification=ItemClassification.progression_skip_balancing, unique=True), - "Lawkeeper's Fist": SingleItemData(item_id=299, name="Lawkeeper's Fist", classification=ItemClassification.progression_skip_balancing, unique=True), - 'Aehre': SingleItemData(item_id=300, name='Aehre', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Twitching Slicer': SingleItemData(item_id=301, name='Twitching Slicer', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Sunset Claw': SingleItemData(item_id=302, name='Sunset Claw', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Sneaky Shiv': SingleItemData(item_id=303, name='Sneaky Shiv', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Ramming Shell': SingleItemData(item_id=304, name='Ramming Shell', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Survival Plate': SingleItemData(item_id=305, name='Survival Plate', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Rootweave': SingleItemData(item_id=306, name='Rootweave', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Petal Cloak': SingleItemData(item_id=307, name='Petal Cloak', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Loose Trenchcoat': SingleItemData(item_id=308, name='Loose Trenchcoat', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Stable Footguard': SingleItemData(item_id=309, name='Stable Footguard', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Hydraulic Anchors': SingleItemData(item_id=310, name='Hydraulic Anchors', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Shinkickers': SingleItemData(item_id=311, name='Shinkickers', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Urban Sneakers': SingleItemData(item_id=312, name='Urban Sneakers', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Pathfinders': SingleItemData(item_id=313, name='Pathfinders', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Nifty Grey Shades': SingleItemData(item_id=293, name='Nifty Grey Shades', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=38)), + 'Red Bandana': SingleItemData(item_id=294, name='Red Bandana', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=37)), + "Electrician's Cap": SingleItemData(item_id=295, name="Electrician's Cap", classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=45)), + 'Faedora': SingleItemData(item_id=296, name='Faedora', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=46)), + 'Mystic Mohawk': SingleItemData(item_id=297, name='Mystic Mohawk', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=47)), + "Hunter's Bolt": SingleItemData(item_id=298, name="Hunter's Bolt", classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=37)), + "Lawkeeper's Fist": SingleItemData(item_id=299, name="Lawkeeper's Fist", classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=46)), + 'Aehre': SingleItemData(item_id=300, name='Aehre', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=45)), + 'Twitching Slicer': SingleItemData(item_id=301, name='Twitching Slicer', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=44)), + 'Sunset Claw': SingleItemData(item_id=302, name='Sunset Claw', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=38)), + 'Sneaky Shiv': SingleItemData(item_id=303, name='Sneaky Shiv', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=47)), + 'Ramming Shell': SingleItemData(item_id=304, name='Ramming Shell', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=38)), + 'Survival Plate': SingleItemData(item_id=305, name='Survival Plate', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=46)), + 'Rootweave': SingleItemData(item_id=306, name='Rootweave', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=47)), + 'Petal Cloak': SingleItemData(item_id=307, name='Petal Cloak', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=37)), + 'Loose Trenchcoat': SingleItemData(item_id=308, name='Loose Trenchcoat', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=45)), + 'Stable Footguard': SingleItemData(item_id=309, name='Stable Footguard', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=38)), + 'Hydraulic Anchors': SingleItemData(item_id=310, name='Hydraulic Anchors', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=47)), + 'Shinkickers': SingleItemData(item_id=311, name='Shinkickers', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=37)), + 'Urban Sneakers': SingleItemData(item_id=312, name='Urban Sneakers', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=46)), + 'Pathfinders': SingleItemData(item_id=313, name='Pathfinders', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=45)), 'Sea Disc': SingleItemData(item_id=314, name='Sea Disc', classification=ItemClassification.filler, unique=True), 'Maultasche': SingleItemData(item_id=315, name='Maultasche', classification=ItemClassification.filler), 'Werewolf Stick': SingleItemData(item_id=316, name='Werewolf Stick', classification=ItemClassification.filler), @@ -686,26 +686,26 @@ "So'najiz Key": SingleItemData(item_id=319, name="So'najiz Key", classification=ItemClassification.progression, unique=True), "Jack's Flame": SingleItemData(item_id=320, name="Jack's Flame", classification=ItemClassification.progression, unique=True), 'Aged Travelguide': SingleItemData(item_id=321, name='Aged Travelguide', classification=ItemClassification.progression, unique=True), - 'Galaxy Spiral Drill': SingleItemData(item_id=322, name='Galaxy Spiral Drill', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Galaxy Spiral Drill': SingleItemData(item_id=322, name='Galaxy Spiral Drill', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=51)), 'Infinity Spiral Drill': SingleItemData(item_id=323, name='Infinity Spiral Drill', classification=ItemClassification.progression_skip_balancing, unique=True), 'Stone of Truth': SingleItemData(item_id=324, name='Stone of Truth', classification=ItemClassification.progression, unique=True), 'Creation Gem': SingleItemData(item_id=325, name='Creation Gem', classification=ItemClassification.filler, unique=True), "King's Ring": SingleItemData(item_id=326, name="King's Ring", classification=ItemClassification.filler, unique=True), - 'Golden Revolver': SingleItemData(item_id=327, name='Golden Revolver', classification=ItemClassification.progression_skip_balancing, unique=True), - "Bandit's Scarf": SingleItemData(item_id=328, name="Bandit's Scarf", classification=ItemClassification.progression_skip_balancing, unique=True), + 'Golden Revolver': SingleItemData(item_id=327, name='Golden Revolver', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=50)), + "Bandit's Scarf": SingleItemData(item_id=328, name="Bandit's Scarf", classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=48)), "Burglar's Rope": SingleItemData(item_id=329, name="Burglar's Rope", classification=ItemClassification.progression_skip_balancing, unique=True), 'Excalibro': SingleItemData(item_id=330, name='Excalibro', classification=ItemClassification.progression_skip_balancing, unique=True), 'Snack Mix': SingleItemData(item_id=331, name='Snack Mix', classification=ItemClassification.filler), - 'Rough Branch': SingleItemData(item_id=332, name='Rough Branch', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Bigger Stick': SingleItemData(item_id=333, name='Bigger Stick', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Rough Branch': SingleItemData(item_id=332, name='Rough Branch', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=41)), + 'Bigger Stick': SingleItemData(item_id=333, name='Bigger Stick', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=51)), 'Goddess Plume': SingleItemData(item_id=334, name='Goddess Plume', classification=ItemClassification.filler, unique=True), 'Cold Platter': SingleItemData(item_id=335, name='Cold Platter', classification=ItemClassification.filler), 'Full Course': SingleItemData(item_id=336, name='Full Course', classification=ItemClassification.filler), - 'Bronze Chest Plate': SingleItemData(item_id=337, name='Bronze Chest Plate', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Silver Chest Plate': SingleItemData(item_id=338, name='Silver Chest Plate', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Golden Chest Plate': SingleItemData(item_id=339, name='Golden Chest Plate', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Bronze Chest Plate': SingleItemData(item_id=337, name='Bronze Chest Plate', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=22)), + 'Silver Chest Plate': SingleItemData(item_id=338, name='Silver Chest Plate', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=33)), + 'Golden Chest Plate': SingleItemData(item_id=339, name='Golden Chest Plate', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=54)), 'Hungry Salmon': SingleItemData(item_id=340, name='Hungry Salmon', classification=ItemClassification.filler, unique=True), - 'Plate of Chests': SingleItemData(item_id=341, name='Plate of Chests', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Plate of Chests': SingleItemData(item_id=341, name='Plate of Chests', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=67)), "Billston's Com": SingleItemData(item_id=342, name="Billston's Com", classification=ItemClassification.progression, unique=True), 'Smokaway': SingleItemData(item_id=343, name='Smokaway', classification=ItemClassification.progression, unique=True), 'Tracker Chip': SingleItemData(item_id=344, name='Tracker Chip', classification=ItemClassification.progression, unique=True), @@ -715,7 +715,7 @@ 'Polished Mic': SingleItemData(item_id=348, name='Polished Mic', classification=ItemClassification.filler, unique=True), "Krys'kajo Key": SingleItemData(item_id=349, name="Krys'kajo Key", classification=ItemClassification.progression, unique=True), 'Kajo Master Key': SingleItemData(item_id=350, name='Kajo Master Key', classification=ItemClassification.progression, unique=True), - 'Warkeeper': SingleItemData(item_id=351, name='Warkeeper', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Warkeeper': SingleItemData(item_id=351, name='Warkeeper', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=60)), 'Ambiguous Rod': SingleItemData(item_id=352, name='Ambiguous Rod', classification=ItemClassification.filler, unique=True), 'Kebab Roll': SingleItemData(item_id=353, name='Kebab Roll', classification=ItemClassification.filler), 'Wrap Roll': SingleItemData(item_id=354, name='Wrap Roll', classification=ItemClassification.filler), @@ -723,13 +723,13 @@ 'Shrimp Risotto': SingleItemData(item_id=356, name='Shrimp Risotto', classification=ItemClassification.filler), 'Green Risotto': SingleItemData(item_id=357, name='Green Risotto', classification=ItemClassification.filler), 'Final Dinner': SingleItemData(item_id=358, name='Final Dinner', classification=ItemClassification.filler), - 'Tattered Satchel': SingleItemData(item_id=359, name='Tattered Satchel', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Prism Pouch': SingleItemData(item_id=360, name='Prism Pouch', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Infinite Bag': SingleItemData(item_id=361, name='Infinite Bag', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Tattered Satchel': SingleItemData(item_id=359, name='Tattered Satchel', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=28)), + 'Prism Pouch': SingleItemData(item_id=360, name='Prism Pouch', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=39)), + 'Infinite Bag': SingleItemData(item_id=361, name='Infinite Bag', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=52)), "Ti'im Residue": SingleItemData(item_id=362, name="Ti'im Residue", classification=ItemClassification.progression, unique=True), - 'Adept Gloves': SingleItemData(item_id=363, name='Adept Gloves', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Adept Gloves': SingleItemData(item_id=363, name='Adept Gloves', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=40)), 'Storage Unit #1': SingleItemData(item_id=364, name='Storage Unit #1', classification=ItemClassification.progression, unique=True), - 'Scouting Visor': SingleItemData(item_id=365, name='Scouting Visor', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Scouting Visor': SingleItemData(item_id=365, name='Scouting Visor', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=56)), 'Just Water': SingleItemData(item_id=366, name='Just Water', classification=ItemClassification.filler), 'Bear Beer': SingleItemData(item_id=367, name='Bear Beer', classification=ItemClassification.filler), 'Crab Mead': SingleItemData(item_id=368, name='Crab Mead', classification=ItemClassification.filler), @@ -757,55 +757,55 @@ 'Spark Tin': SingleItemData(item_id=390, name='Spark Tin', classification=ItemClassification.filler, unique=True), 'Cobalt Crystal': SingleItemData(item_id=391, name='Cobalt Crystal', classification=ItemClassification.filler, unique=True), 'Dream Globe': SingleItemData(item_id=392, name='Dream Globe', classification=ItemClassification.progression, unique=True), - 'Cobalt Goggles': SingleItemData(item_id=393, name='Cobalt Goggles', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Cobalt Edge': SingleItemData(item_id=394, name='Cobalt Edge', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Cobalt Mail': SingleItemData(item_id=395, name='Cobalt Mail', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Cobalt Boots': SingleItemData(item_id=396, name='Cobalt Boots', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Laser Goggles': SingleItemData(item_id=397, name='Laser Goggles', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Laser Edge': SingleItemData(item_id=398, name='Laser Edge', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Laser Mail': SingleItemData(item_id=399, name='Laser Mail', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Laser Boots': SingleItemData(item_id=400, name='Laser Boots', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Cobalt Goggles': SingleItemData(item_id=393, name='Cobalt Goggles', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=50)), + 'Cobalt Edge': SingleItemData(item_id=394, name='Cobalt Edge', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=50)), + 'Cobalt Mail': SingleItemData(item_id=395, name='Cobalt Mail', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=50)), + 'Cobalt Boots': SingleItemData(item_id=396, name='Cobalt Boots', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=50)), + 'Laser Goggles': SingleItemData(item_id=397, name='Laser Goggles', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=59)), + 'Laser Edge': SingleItemData(item_id=398, name='Laser Edge', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=59)), + 'Laser Mail': SingleItemData(item_id=399, name='Laser Mail', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=59)), + 'Laser Boots': SingleItemData(item_id=400, name='Laser Boots', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=59)), 'Infected Cell': SingleItemData(item_id=401, name='Infected Cell', classification=ItemClassification.filler, unique=True), 'Elemental DNA': SingleItemData(item_id=402, name='Elemental DNA', classification=ItemClassification.filler, unique=True), 'Cursed Coin': SingleItemData(item_id=403, name='Cursed Coin', classification=ItemClassification.progression, unique=True), - 'Broken Sword': SingleItemData(item_id=404, name='Broken Sword', classification=ItemClassification.progression, unique=True), + 'Broken Sword': SingleItemData(item_id=404, name='Broken Sword', classification=ItemClassification.progression, unique=True, equip_data=EquipmentData(equip_type='ARM', level=1)), 'Ronin Shell': SingleItemData(item_id=405, name='Ronin Shell', classification=ItemClassification.filler, unique=True), 'Samurai Shell': SingleItemData(item_id=406, name='Samurai Shell', classification=ItemClassification.filler, unique=True), 'Sharp Splitter': SingleItemData(item_id=407, name='Sharp Splitter', classification=ItemClassification.filler, unique=True), 'Hoverpad': SingleItemData(item_id=408, name='Hoverpad', classification=ItemClassification.filler, unique=True), 'Sticky Web': SingleItemData(item_id=409, name='Sticky Web', classification=ItemClassification.filler, unique=True), 'Star Shade': SingleItemData(item_id=410, name='Star Shade', classification=ItemClassification.progression, unique=True), - 'Hardhead Hat': SingleItemData(item_id=411, name='Hardhead Hat', classification=ItemClassification.progression_skip_balancing, unique=True), - "Survivor's Blade": SingleItemData(item_id=412, name="Survivor's Blade", classification=ItemClassification.progression_skip_balancing, unique=True), - 'Marksmen Trigger': SingleItemData(item_id=413, name='Marksmen Trigger', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Panzer Fist': SingleItemData(item_id=414, name='Panzer Fist', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Shadowy Cloak': SingleItemData(item_id=415, name='Shadowy Cloak', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Plated Plate': SingleItemData(item_id=416, name='Plated Plate', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Bamboots': SingleItemData(item_id=417, name='Bamboots', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Brave Anchors': SingleItemData(item_id=418, name='Brave Anchors', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Shuddering Cleaver': SingleItemData(item_id=419, name='Shuddering Cleaver', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Tengu Mask': SingleItemData(item_id=420, name='Tengu Mask', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Sonic Spike': SingleItemData(item_id=421, name='Sonic Spike', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Lead Boots': SingleItemData(item_id=422, name='Lead Boots', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Hardhead Hat': SingleItemData(item_id=411, name='Hardhead Hat', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=55)), + "Survivor's Blade": SingleItemData(item_id=412, name="Survivor's Blade", classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=54)), + 'Marksmen Trigger': SingleItemData(item_id=413, name='Marksmen Trigger', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=55)), + 'Panzer Fist': SingleItemData(item_id=414, name='Panzer Fist', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=56)), + 'Shadowy Cloak': SingleItemData(item_id=415, name='Shadowy Cloak', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=55)), + 'Plated Plate': SingleItemData(item_id=416, name='Plated Plate', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=56)), + 'Bamboots': SingleItemData(item_id=417, name='Bamboots', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=55)), + 'Brave Anchors': SingleItemData(item_id=418, name='Brave Anchors', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=56)), + 'Shuddering Cleaver': SingleItemData(item_id=419, name='Shuddering Cleaver', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=58)), + 'Tengu Mask': SingleItemData(item_id=420, name='Tengu Mask', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=53)), + 'Sonic Spike': SingleItemData(item_id=421, name='Sonic Spike', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=57)), + 'Lead Boots': SingleItemData(item_id=422, name='Lead Boots', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=58)), 'Omni Lock': SingleItemData(item_id=423, name='Omni Lock', classification=ItemClassification.filler, unique=True), - 'Shining Bracer': SingleItemData(item_id=424, name='Shining Bracer', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Bluefiber Robe': SingleItemData(item_id=425, name='Bluefiber Robe', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Shining Bracer': SingleItemData(item_id=424, name='Shining Bracer', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=59)), + 'Bluefiber Robe': SingleItemData(item_id=425, name='Bluefiber Robe', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=51)), 'Toggle Test': SingleItemData(item_id=426, name='Toggle Test', classification=ItemClassification.filler, unique=True), 'Stone Key': SingleItemData(item_id=427, name='Stone Key', classification=ItemClassification.progression, unique=True), 'Circuit Override': SingleItemData(item_id=428, name='Circuit Override', classification=ItemClassification.progression, unique=True), 'F.A.I.R. Device': SingleItemData(item_id=429, name='F.A.I.R. Device', classification=ItemClassification.progression, unique=True), 'Smelter Parts': SingleItemData(item_id=430, name='Smelter Parts', classification=ItemClassification.progression, unique=True), 'Marinated Meat': SingleItemData(item_id=431, name='Marinated Meat', classification=ItemClassification.filler, unique=True), - 'Bright Bracer': SingleItemData(item_id=432, name='Bright Bracer', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Prickly Bracer': SingleItemData(item_id=433, name='Prickly Bracer', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Bright Bracer': SingleItemData(item_id=432, name='Bright Bracer', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=35)), + 'Prickly Bracer': SingleItemData(item_id=433, name='Prickly Bracer', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=25)), 'Meteor Shade': SingleItemData(item_id=434, name='Meteor Shade', classification=ItemClassification.progression, unique=True), 'Golden Bug': SingleItemData(item_id=435, name='Golden Bug', classification=ItemClassification.progression, unique=True), - 'Sparkling Bracer': SingleItemData(item_id=436, name='Sparkling Bracer', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Brostick of Force': SingleItemData(item_id=438, name='Brostick of Force', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Sparkling Bracer': SingleItemData(item_id=436, name='Sparkling Bracer', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=48)), + 'Brostick of Force': SingleItemData(item_id=438, name='Brostick of Force', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=64)), 'Old Dojo Key': SingleItemData(item_id=439, name='Old Dojo Key', classification=ItemClassification.progression, unique=True), 'Twilight Shard': SingleItemData(item_id=440, name='Twilight Shard', classification=ItemClassification.filler, unique=True), - 'Old Geta': SingleItemData(item_id=441, name='Old Geta', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Broken Deck': SingleItemData(item_id=443, name='Broken Deck', classification=ItemClassification.progression, unique=True), + 'Old Geta': SingleItemData(item_id=441, name='Old Geta', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=62)), + 'Broken Deck': SingleItemData(item_id=443, name='Broken Deck', classification=ItemClassification.progression, unique=True, equip_data=EquipmentData(equip_type='ARM', level=1)), 'Stone of Spirit': SingleItemData(item_id=444, name='Stone of Spirit', classification=ItemClassification.progression, unique=True), 'Infinity Gem': SingleItemData(item_id=445, name='Infinity Gem', classification=ItemClassification.filler, unique=True), 'Stone of Ages': SingleItemData(item_id=446, name='Stone of Ages', classification=ItemClassification.progression, unique=True), @@ -829,23 +829,23 @@ 'Emerald': SingleItemData(item_id=464, name='Emerald', classification=ItemClassification.filler, unique=True), 'Lapis Lazuli': SingleItemData(item_id=465, name='Lapis Lazuli', classification=ItemClassification.filler, unique=True), 'Mine Detector': SingleItemData(item_id=466, name='Mine Detector', classification=ItemClassification.progression, unique=True), - 'Dried Grass Hat': SingleItemData(item_id=467, name='Dried Grass Hat', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Strawberry Hat': SingleItemData(item_id=468, name='Strawberry Hat', classification=ItemClassification.progression_skip_balancing, unique=True), - 'The Last Strawhat': SingleItemData(item_id=469, name='The Last Strawhat', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Climate Cowl': SingleItemData(item_id=470, name='Climate Cowl', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Serene Bubble': SingleItemData(item_id=471, name='Serene Bubble', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Furious Hothead': SingleItemData(item_id=472, name='Furious Hothead', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Trackwalker Visor': SingleItemData(item_id=473, name='Trackwalker Visor', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Skirmisher': SingleItemData(item_id=474, name='Skirmisher', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Unbreaking Fist': SingleItemData(item_id=475, name='Unbreaking Fist', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Golden Falcon': SingleItemData(item_id=476, name='Golden Falcon', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Zealous Lamellar': SingleItemData(item_id=477, name='Zealous Lamellar', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Pioneer Vest': SingleItemData(item_id=478, name='Pioneer Vest', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Reactive Plate': SingleItemData(item_id=479, name='Reactive Plate', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Vermillion Mantle': SingleItemData(item_id=480, name='Vermillion Mantle', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Deadly Dancers': SingleItemData(item_id=481, name='Deadly Dancers', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Praetorian Anchors': SingleItemData(item_id=482, name='Praetorian Anchors', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Mistwalkers': SingleItemData(item_id=483, name='Mistwalkers', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Dried Grass Hat': SingleItemData(item_id=467, name='Dried Grass Hat', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=35)), + 'Strawberry Hat': SingleItemData(item_id=468, name='Strawberry Hat', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=45)), + 'The Last Strawhat': SingleItemData(item_id=469, name='The Last Strawhat', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=60)), + 'Climate Cowl': SingleItemData(item_id=470, name='Climate Cowl', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=49)), + 'Serene Bubble': SingleItemData(item_id=471, name='Serene Bubble', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=62)), + 'Furious Hothead': SingleItemData(item_id=472, name='Furious Hothead', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=63)), + 'Trackwalker Visor': SingleItemData(item_id=473, name='Trackwalker Visor', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=64)), + 'Skirmisher': SingleItemData(item_id=474, name='Skirmisher', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=62)), + 'Unbreaking Fist': SingleItemData(item_id=475, name='Unbreaking Fist', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=63)), + 'Golden Falcon': SingleItemData(item_id=476, name='Golden Falcon', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=64)), + 'Zealous Lamellar': SingleItemData(item_id=477, name='Zealous Lamellar', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=62)), + 'Pioneer Vest': SingleItemData(item_id=478, name='Pioneer Vest', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=63)), + 'Reactive Plate': SingleItemData(item_id=479, name='Reactive Plate', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=64)), + 'Vermillion Mantle': SingleItemData(item_id=480, name='Vermillion Mantle', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=41)), + 'Deadly Dancers': SingleItemData(item_id=481, name='Deadly Dancers', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=62)), + 'Praetorian Anchors': SingleItemData(item_id=482, name='Praetorian Anchors', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=63)), + 'Mistwalkers': SingleItemData(item_id=483, name='Mistwalkers', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=64)), 'Geta Wood': SingleItemData(item_id=484, name='Geta Wood', classification=ItemClassification.filler, unique=True), 'Geta Straps': SingleItemData(item_id=485, name='Geta Straps', classification=ItemClassification.filler, unique=True), 'Geta Glue': SingleItemData(item_id=486, name='Geta Glue', classification=ItemClassification.filler, unique=True), @@ -861,43 +861,43 @@ 'Old Blueprint': SingleItemData(item_id=497, name='Old Blueprint', classification=ItemClassification.progression, unique=True), 'Kunoichi': SingleItemData(item_id=498, name='Kunoichi', classification=ItemClassification.filler, unique=True), 'Antique Token': SingleItemData(item_id=499, name='Antique Token', classification=ItemClassification.filler, unique=True), - 'Radiant Bracer': SingleItemData(item_id=500, name='Radiant Bracer', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Radiant Bracer': SingleItemData(item_id=500, name='Radiant Bracer', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=68)), 'Chest Detector': SingleItemData(item_id=501, name='Chest Detector', classification=ItemClassification.filler, unique=True), 'Moistured Line': SingleItemData(item_id=502, name='Moistured Line', classification=ItemClassification.filler, unique=True), 'Trash': SingleItemData(item_id=503, name='Trash', classification=ItemClassification.filler, unique=True), - 'Thrashing Ripper': SingleItemData(item_id=504, name='Thrashing Ripper', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Thrashing Ripper': SingleItemData(item_id=504, name='Thrashing Ripper', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=68)), 'Rusty Hook': SingleItemData(item_id=505, name='Rusty Hook', classification=ItemClassification.filler, unique=True), - 'Gorgon Veil': SingleItemData(item_id=506, name='Gorgon Veil', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Centaur Vest': SingleItemData(item_id=507, name='Centaur Vest', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Unicorn Greaves': SingleItemData(item_id=508, name='Unicorn Greaves', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Gorgon Veil': SingleItemData(item_id=506, name='Gorgon Veil', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=61)), + 'Centaur Vest': SingleItemData(item_id=507, name='Centaur Vest', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=61)), + 'Unicorn Greaves': SingleItemData(item_id=508, name='Unicorn Greaves', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=61)), 'Chestlink': SingleItemData(item_id=509, name='Chestlink', classification=ItemClassification.filler, unique=True), - 'Lifefiber Uniform': SingleItemData(item_id=510, name='Lifefiber Uniform', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Infinity+1 Bag': SingleItemData(item_id=511, name='Infinity+1 Bag', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Mantis Whip': SingleItemData(item_id=512, name='Mantis Whip', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Nanopoint Needle': SingleItemData(item_id=513, name='Nanopoint Needle', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Roundhousers': SingleItemData(item_id=514, name='Roundhousers', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Broken Chakrams': SingleItemData(item_id=515, name='Broken Chakrams', classification=ItemClassification.progression, unique=True), + 'Lifefiber Uniform': SingleItemData(item_id=510, name='Lifefiber Uniform', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=68)), + 'Infinity+1 Bag': SingleItemData(item_id=511, name='Infinity+1 Bag', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=66)), + 'Mantis Whip': SingleItemData(item_id=512, name='Mantis Whip', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=63)), + 'Nanopoint Needle': SingleItemData(item_id=513, name='Nanopoint Needle', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=71)), + 'Roundhousers': SingleItemData(item_id=514, name='Roundhousers', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=65)), + 'Broken Chakrams': SingleItemData(item_id=515, name='Broken Chakrams', classification=ItemClassification.progression, unique=True, equip_data=EquipmentData(equip_type='ARM', level=1)), 'Mooncake': SingleItemData(item_id=516, name='Mooncake', classification=ItemClassification.filler), 'Turret Tokens': SingleItemData(item_id=517, name='Turret Tokens', classification=ItemClassification.filler, unique=True), - 'Trench Boots': SingleItemData(item_id=518, name='Trench Boots', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Trench Boots': SingleItemData(item_id=518, name='Trench Boots', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=52)), 'Element Aura': SingleItemData(item_id=519, name='Element Aura', classification=ItemClassification.filler, unique=True), 'Menacing Aura': SingleItemData(item_id=520, name='Menacing Aura', classification=ItemClassification.filler, unique=True), 'Chunky': SingleItemData(item_id=521, name='Chunky', classification=ItemClassification.filler, unique=True), - 'Paedalos': SingleItemData(item_id=522, name='Paedalos', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Killing Dress': SingleItemData(item_id=523, name='Killing Dress', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Pendulum Striker': SingleItemData(item_id=524, name='Pendulum Striker', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Knocking One': SingleItemData(item_id=525, name='Knocking One', classification=ItemClassification.progression_skip_balancing, unique=True), - "Dragon's Bandana": SingleItemData(item_id=526, name="Dragon's Bandana", classification=ItemClassification.progression_skip_balancing, unique=True), + 'Paedalos': SingleItemData(item_id=522, name='Paedalos', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=65)), + 'Killing Dress': SingleItemData(item_id=523, name='Killing Dress', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=65)), + 'Pendulum Striker': SingleItemData(item_id=524, name='Pendulum Striker', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=65)), + 'Knocking One': SingleItemData(item_id=525, name='Knocking One', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=65)), + "Dragon's Bandana": SingleItemData(item_id=526, name="Dragon's Bandana", classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=65)), 'Orange Twister': SingleItemData(item_id=527, name='Orange Twister', classification=ItemClassification.filler, unique=True), 'Baby Peng': SingleItemData(item_id=528, name='Baby Peng', classification=ItemClassification.filler, unique=True), 'FDNI Fox': SingleItemData(item_id=529, name='FDNI Fox', classification=ItemClassification.filler, unique=True), - 'Eternal Salami': SingleItemData(item_id=530, name='Eternal Salami', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Assault Harness': SingleItemData(item_id=531, name='Assault Harness', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Tranquil Earmuffs': SingleItemData(item_id=532, name='Tranquil Earmuffs', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Combat Skates': SingleItemData(item_id=533, name='Combat Skates', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Eternal Salami': SingleItemData(item_id=530, name='Eternal Salami', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=65)), + 'Assault Harness': SingleItemData(item_id=531, name='Assault Harness', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=65)), + 'Tranquil Earmuffs': SingleItemData(item_id=532, name='Tranquil Earmuffs', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=65)), + 'Combat Skates': SingleItemData(item_id=533, name='Combat Skates', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=65)), 'Good Boy': SingleItemData(item_id=534, name='Good Boy', classification=ItemClassification.filler, unique=True), 'Coarse Powerring': SingleItemData(item_id=535, name='Coarse Powerring', classification=ItemClassification.progression, unique=True), - 'Artillery Boots': SingleItemData(item_id=536, name='Artillery Boots', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Artillery Boots': SingleItemData(item_id=536, name='Artillery Boots', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=66)), 'S-Rex': SingleItemData(item_id=537, name='S-Rex', classification=ItemClassification.filler, unique=True), "Lil' Reap": SingleItemData(item_id=538, name="Lil' Reap", classification=ItemClassification.filler, unique=True), 'Red Liz': SingleItemData(item_id=539, name='Red Liz', classification=ItemClassification.filler, unique=True), @@ -928,49 +928,49 @@ 'Rose Cone': SingleItemData(item_id=564, name='Rose Cone', classification=ItemClassification.filler, unique=True), 'Salty Grass': SingleItemData(item_id=565, name='Salty Grass', classification=ItemClassification.filler, unique=True), 'Coral Piece': SingleItemData(item_id=566, name='Coral Piece', classification=ItemClassification.filler, unique=True), - 'Cross Edge': SingleItemData(item_id=567, name='Cross Edge', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Cross Goggles': SingleItemData(item_id=568, name='Cross Goggles', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Cross Mail': SingleItemData(item_id=569, name='Cross Mail', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Cross Boots': SingleItemData(item_id=570, name='Cross Boots', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Serene Bubble+': SingleItemData(item_id=571, name='Serene Bubble+', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Furious Hothead+': SingleItemData(item_id=572, name='Furious Hothead+', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Trackwalker Visor+': SingleItemData(item_id=573, name='Trackwalker Visor+', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Medusa Veil': SingleItemData(item_id=574, name='Medusa Veil', classification=ItemClassification.progression_skip_balancing, unique=True), - "Dragon's Bandana+": SingleItemData(item_id=575, name="Dragon's Bandana+", classification=ItemClassification.progression_skip_balancing, unique=True), - 'Tranquil Earmuffs+': SingleItemData(item_id=576, name='Tranquil Earmuffs+', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Skirmisher+': SingleItemData(item_id=577, name='Skirmisher+', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Unbreaking Fist+': SingleItemData(item_id=578, name='Unbreaking Fist+', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Mantis Whip+': SingleItemData(item_id=579, name='Mantis Whip+', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Golden Falcon+': SingleItemData(item_id=580, name='Golden Falcon+', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Brostick of Force+': SingleItemData(item_id=581, name='Brostick of Force+', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Cerberus Fang': SingleItemData(item_id=582, name='Cerberus Fang', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Zealous Lamellar+': SingleItemData(item_id=583, name='Zealous Lamellar+', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Pioneer Vest+': SingleItemData(item_id=584, name='Pioneer Vest+', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Reactive Plate+': SingleItemData(item_id=585, name='Reactive Plate+', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Chiron Vest': SingleItemData(item_id=586, name='Chiron Vest', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Killing Dress+': SingleItemData(item_id=587, name='Killing Dress+', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Assault Harness+': SingleItemData(item_id=588, name='Assault Harness+', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Pendulum Striker+': SingleItemData(item_id=589, name='Pendulum Striker+', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Knocking One+': SingleItemData(item_id=590, name='Knocking One+', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Deadly Dancers+': SingleItemData(item_id=592, name='Deadly Dancers+', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Praetorian Anchors+': SingleItemData(item_id=593, name='Praetorian Anchors+', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Mistwalkers+': SingleItemData(item_id=594, name='Mistwalkers+', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Pegasus Greaves': SingleItemData(item_id=595, name='Pegasus Greaves', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Combat Skates+': SingleItemData(item_id=596, name='Combat Skates+', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Paedalos+': SingleItemData(item_id=597, name='Paedalos+', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Very Last Strawhat': SingleItemData(item_id=598, name='Very Last Strawhat', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Sunshine Bracer': SingleItemData(item_id=599, name='Sunshine Bracer', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Highmeister Gloves': SingleItemData(item_id=601, name='Highmeister Gloves', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Body Armoire': SingleItemData(item_id=602, name='Body Armoire', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Artillery Boots+': SingleItemData(item_id=603, name='Artillery Boots+', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Lifefiber Dress': SingleItemData(item_id=604, name='Lifefiber Dress', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Eternal Salami+': SingleItemData(item_id=605, name='Eternal Salami+', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Cross Edge': SingleItemData(item_id=567, name='Cross Edge', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=71)), + 'Cross Goggles': SingleItemData(item_id=568, name='Cross Goggles', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=71)), + 'Cross Mail': SingleItemData(item_id=569, name='Cross Mail', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=71)), + 'Cross Boots': SingleItemData(item_id=570, name='Cross Boots', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=71)), + 'Serene Bubble+': SingleItemData(item_id=571, name='Serene Bubble+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=71)), + 'Furious Hothead+': SingleItemData(item_id=572, name='Furious Hothead+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=71)), + 'Trackwalker Visor+': SingleItemData(item_id=573, name='Trackwalker Visor+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=71)), + 'Medusa Veil': SingleItemData(item_id=574, name='Medusa Veil', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=71)), + "Dragon's Bandana+": SingleItemData(item_id=575, name="Dragon's Bandana+", classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=71)), + 'Tranquil Earmuffs+': SingleItemData(item_id=576, name='Tranquil Earmuffs+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=71)), + 'Skirmisher+': SingleItemData(item_id=577, name='Skirmisher+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=71)), + 'Unbreaking Fist+': SingleItemData(item_id=578, name='Unbreaking Fist+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=71)), + 'Mantis Whip+': SingleItemData(item_id=579, name='Mantis Whip+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=71)), + 'Golden Falcon+': SingleItemData(item_id=580, name='Golden Falcon+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=71)), + 'Brostick of Force+': SingleItemData(item_id=581, name='Brostick of Force+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=71)), + 'Cerberus Fang': SingleItemData(item_id=582, name='Cerberus Fang', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=71)), + 'Zealous Lamellar+': SingleItemData(item_id=583, name='Zealous Lamellar+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=71)), + 'Pioneer Vest+': SingleItemData(item_id=584, name='Pioneer Vest+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=71)), + 'Reactive Plate+': SingleItemData(item_id=585, name='Reactive Plate+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=71)), + 'Chiron Vest': SingleItemData(item_id=586, name='Chiron Vest', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=71)), + 'Killing Dress+': SingleItemData(item_id=587, name='Killing Dress+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=71)), + 'Assault Harness+': SingleItemData(item_id=588, name='Assault Harness+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=71)), + 'Pendulum Striker+': SingleItemData(item_id=589, name='Pendulum Striker+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=71)), + 'Knocking One+': SingleItemData(item_id=590, name='Knocking One+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=71)), + 'Deadly Dancers+': SingleItemData(item_id=592, name='Deadly Dancers+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=71)), + 'Praetorian Anchors+': SingleItemData(item_id=593, name='Praetorian Anchors+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=71)), + 'Mistwalkers+': SingleItemData(item_id=594, name='Mistwalkers+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=71)), + 'Pegasus Greaves': SingleItemData(item_id=595, name='Pegasus Greaves', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=71)), + 'Combat Skates+': SingleItemData(item_id=596, name='Combat Skates+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=71)), + 'Paedalos+': SingleItemData(item_id=597, name='Paedalos+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=71)), + 'Very Last Strawhat': SingleItemData(item_id=598, name='Very Last Strawhat', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=71)), + 'Sunshine Bracer': SingleItemData(item_id=599, name='Sunshine Bracer', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=71)), + 'Highmeister Gloves': SingleItemData(item_id=601, name='Highmeister Gloves', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=71)), + 'Body Armoire': SingleItemData(item_id=602, name='Body Armoire', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=71)), + 'Artillery Boots+': SingleItemData(item_id=603, name='Artillery Boots+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=71)), + 'Lifefiber Dress': SingleItemData(item_id=604, name='Lifefiber Dress', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=71)), + 'Eternal Salami+': SingleItemData(item_id=605, name='Eternal Salami+', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=71)), 'Light Gem': SingleItemData(item_id=606, name='Light Gem', classification=ItemClassification.filler, unique=True), - 'Shuriken Shooter': SingleItemData(item_id=607, name='Shuriken Shooter', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Shuriken Shooter': SingleItemData(item_id=607, name='Shuriken Shooter', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=71)), 'Barrel Beak': SingleItemData(item_id=608, name='Barrel Beak', classification=ItemClassification.filler, unique=True), 'Rumble Hive': SingleItemData(item_id=609, name='Rumble Hive', classification=ItemClassification.filler, unique=True), 'Burned Ash': SingleItemData(item_id=610, name='Burned Ash', classification=ItemClassification.filler, unique=True), - 'Speedy Boom Boots': SingleItemData(item_id=611, name='Speedy Boom Boots', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Speedy Boom Boots': SingleItemData(item_id=611, name='Speedy Boom Boots', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=71)), 'Unruly Emeralds': SingleItemData(item_id=612, name='Unruly Emeralds', classification=ItemClassification.filler, unique=True), 'Booster Booster': SingleItemData(item_id=618, name='Booster Booster', classification=ItemClassification.progression, unique=True), 'Yellow Sponge': SingleItemData(item_id=619, name='Yellow Sponge', classification=ItemClassification.filler, unique=True), @@ -992,7 +992,7 @@ 'Rift Spore': SingleItemData(item_id=635, name='Rift Spore', classification=ItemClassification.filler, unique=True), 'Pumpkin Spice Cof.': SingleItemData(item_id=637, name='Pumpkin Spice Cof.', classification=ItemClassification.filler), 'Tremor Core': SingleItemData(item_id=638, name='Tremor Core', classification=ItemClassification.progression, unique=True), - 'Tremor Mirage': SingleItemData(item_id=639, name='Tremor Mirage', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Tremor Mirage': SingleItemData(item_id=639, name='Tremor Mirage', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=71)), "Champion's Towel": SingleItemData(item_id=640, name="Champion's Towel", classification=ItemClassification.filler, unique=True), 'Dragon Sphere': SingleItemData(item_id=641, name='Dragon Sphere', classification=ItemClassification.filler, unique=True), 'Tranquility Sphere': SingleItemData(item_id=642, name='Tranquility Sphere', classification=ItemClassification.filler, unique=True), @@ -1010,24 +1010,24 @@ 'Symbol of Wave': SingleItemData(item_id=654, name='Symbol of Wave', classification=ItemClassification.progression, unique=True), 'Tremor Lab Key': SingleItemData(item_id=655, name='Tremor Lab Key', classification=ItemClassification.progression, unique=True), 'Ultra Secret Note': SingleItemData(item_id=656, name='Ultra Secret Note', classification=ItemClassification.filler, unique=True), - 'Sunglass Visor': SingleItemData(item_id=657, name='Sunglass Visor', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Lunatic Paws UwU': SingleItemData(item_id=658, name='Lunatic Paws UwU', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Meteor Trigger': SingleItemData(item_id=659, name='Meteor Trigger', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Asteroid Belt': SingleItemData(item_id=660, name='Asteroid Belt', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Sunglass Visor': SingleItemData(item_id=657, name='Sunglass Visor', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=71)), + 'Lunatic Paws UwU': SingleItemData(item_id=658, name='Lunatic Paws UwU', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=71)), + 'Meteor Trigger': SingleItemData(item_id=659, name='Meteor Trigger', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=71)), + 'Asteroid Belt': SingleItemData(item_id=660, name='Asteroid Belt', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=71)), 'Asteroid Chunk': SingleItemData(item_id=662, name='Asteroid Chunk', classification=ItemClassification.filler, unique=True), 'Meteor Chunk': SingleItemData(item_id=663, name='Meteor Chunk', classification=ItemClassification.filler, unique=True), - 'Infinity+2 Bag': SingleItemData(item_id=664, name='Infinity+2 Bag', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Infinity+2 Bag': SingleItemData(item_id=664, name='Infinity+2 Bag', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=71)), "Lis'mita Cap": SingleItemData(item_id=665, name="Lis'mita Cap", classification=ItemClassification.progression_skip_balancing, unique=True), - 'Enlightened Halo': SingleItemData(item_id=666, name='Enlightened Halo', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Moonwalkers': SingleItemData(item_id=667, name='Moonwalkers', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Enlightened Halo': SingleItemData(item_id=666, name='Enlightened Halo', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=71)), + 'Moonwalkers': SingleItemData(item_id=667, name='Moonwalkers', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='FEET', level=71)), 'Moon Chunk': SingleItemData(item_id=668, name='Moon Chunk', classification=ItemClassification.filler, unique=True), 'The Last Straw': SingleItemData(item_id=669, name='The Last Straw', classification=ItemClassification.filler, unique=True), 'Goat Cheese': SingleItemData(item_id=670, name='Goat Cheese', classification=ItemClassification.filler), 'Goat Milk': SingleItemData(item_id=671, name='Goat Milk', classification=ItemClassification.filler), 'Manlea': SingleItemData(item_id=672, name='Manlea', classification=ItemClassification.filler, unique=True), - 'Bearserker Claw': SingleItemData(item_id=673, name='Bearserker Claw', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Headset TYPE>:3': SingleItemData(item_id=674, name='Headset TYPE>:3', classification=ItemClassification.progression_skip_balancing, unique=True), - 'Nightfeather Coat': SingleItemData(item_id=675, name='Nightfeather Coat', classification=ItemClassification.progression_skip_balancing, unique=True), + 'Bearserker Claw': SingleItemData(item_id=673, name='Bearserker Claw', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='ARM', level=71)), + 'Headset TYPE>:3': SingleItemData(item_id=674, name='Headset TYPE>:3', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='HEAD', level=71)), + 'Nightfeather Coat': SingleItemData(item_id=675, name='Nightfeather Coat', classification=ItemClassification.progression_skip_balancing, unique=True, equip_data=EquipmentData(equip_type='TORSO', level=71)), } """Dict associating item name with single item data. SingleItemData represents properties inherent to the item itself, regardless of diff --git a/worlds/crosscode/templates/items.template.py b/worlds/crosscode/templates/items.template.py index ef1c876ccf3d..228b52522843 100644 --- a/worlds/crosscode/templates/items.template.py +++ b/worlds/crosscode/templates/items.template.py @@ -4,7 +4,7 @@ from BaseClasses import ItemClassification from worlds.crosscode.types.items import get_info_from_full_name from .util import KeyDefaultDict -from .types.items import ItemData, SingleItemData +from .types.items import EquipmentData, ItemData, SingleItemData num_items = {{num_items}} diff --git a/worlds/crosscode/types/items.py b/worlds/crosscode/types/items.py index 07b12034e28b..be62ed82f1d8 100644 --- a/worlds/crosscode/types/items.py +++ b/worlds/crosscode/types/items.py @@ -6,12 +6,18 @@ import typing from BaseClasses import Item, ItemClassification +@dataclass +class EquipmentData: + equip_type: str + level: int + @dataclass class SingleItemData: name: str item_id: int classification: ItemClassification unique: bool = False + equip_data: EquipmentData | None = None def get_combo_id(item: SingleItemData, amount: int) -> int: return BASE_ID + RESERVED_ITEM_IDS + NUM_ITEMS * (amount - 1) + item.item_id From a82561f437741d2d27a3874999c265aeaac11313 Mon Sep 17 00:00:00 2001 From: Richard Snider Date: Mon, 24 Aug 2026 00:54:19 -0600 Subject: [PATCH 23/23] create a very rough draft of the equipment level check function --- worlds/crosscode/types/condition.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/worlds/crosscode/types/condition.py b/worlds/crosscode/types/condition.py index 83b10d71fcb1..4965798dd72b 100644 --- a/worlds/crosscode/types/condition.py +++ b/worlds/crosscode/types/condition.py @@ -217,9 +217,26 @@ def player_level_satisfied(state: CollectionState): levels[enemy.level] += 1 return maximum_gap(levels) <= world.options.maximum_grind_gap - def equip_level_satisfied(state: CollectionState): - max(item for item in state.prog_items[player]) - return True + if world.options.progressive_equipment.value: + def equip_level_satisfied(state: CollectionState): + return True + else: + def equip_level_satisfied(state: CollectionState): + maxima = { "HEAD": 0, "FEET": 0, "TORSO": 0 } + max_arm = [0, 0] + for item_name in state.prog_items[player]: + item = world.world_data.items_by_full_name[item_name] + equip_data = item.item.equip_data + if equip_data is None: + continue + if equip_data.equip_type == "ARM": + max_arm.append(equip_data.level) + max_arm.sort() + max_arm.pop() + continue + maxima[equip_data.equip_type] = max(maxima[equip_data.equip_type], equip_data.level) + average_level = sum(maxima.values()) + sum(max_arm) / 6 + return average_level + world.options.maximum_grind_gap >= self.level if world.combat_logic_flag == CombatLogic.Flag.PLAYER | CombatLogic.Flag.EQUIP: return lambda state: equip_level_satisfied(state) and player_level_satisfied(state)