diff --git a/KH2Client.py b/KH2Client.py index 1134932dc26c..69e4adf8bf7c 100644 --- a/KH2Client.py +++ b/KH2Client.py @@ -1,894 +1,8 @@ -import os -import asyncio import ModuleUpdate -import json import Utils -from pymem import pymem -from worlds.kh2.Items import exclusionItem_table, CheckDupingItems -from worlds.kh2 import all_locations, item_dictionary_table, exclusion_table - -from worlds.kh2.WorldLocations import * - -from worlds import network_data_package - -if __name__ == "__main__": - Utils.init_logging("KH2Client", exception_logger="Client") - -from NetUtils import ClientStatus -from CommonClient import gui_enabled, logger, get_base_parser, ClientCommandProcessor, \ - CommonContext, server_loop - +from worlds.kh2.Client import launch ModuleUpdate.update() -kh2_loc_name_to_id = network_data_package["games"]["Kingdom Hearts 2"]["location_name_to_id"] - - -# class KH2CommandProcessor(ClientCommandProcessor): - - -class KH2Context(CommonContext): - # command_processor: int = KH2CommandProcessor - game = "Kingdom Hearts 2" - items_handling = 0b101 # Indicates you get items sent from other worlds. - - def __init__(self, server_address, password): - super(KH2Context, self).__init__(server_address, password) - self.kh2LocalItems = None - self.ability = None - self.growthlevel = None - self.KH2_sync_task = None - self.syncing = False - self.kh2connected = False - self.serverconneced = False - self.item_name_to_data = {name: data for name, data, in item_dictionary_table.items()} - self.location_name_to_data = {name: data for name, data, in all_locations.items()} - self.lookup_id_to_item: typing.Dict[int, str] = {data.code: item_name for item_name, data in - item_dictionary_table.items() if data.code} - self.lookup_id_to_Location: typing.Dict[int, str] = {data.code: item_name for item_name, data in - all_locations.items() if data.code} - self.location_name_to_worlddata = {name: data for name, data, in all_world_locations.items()} - - self.location_table = {} - self.collectible_table = {} - self.collectible_override_flags_address = 0 - self.collectible_offsets = {} - self.sending = [] - # list used to keep track of locations+items player has. Used for disoneccting - self.kh2seedsave = None - self.slotDataProgressionNames = {} - self.kh2seedname = None - self.kh2slotdata = None - self.itemamount = {} - # sora equipped, valor equipped, master equipped, final equipped - self.keybladeAnchorList = (0x24F0, 0x32F4, 0x339C, 0x33D4) - if "localappdata" in os.environ: - self.game_communication_path = os.path.expandvars(r"%localappdata%\KH2AP") - self.amountOfPieces = 0 - # hooked object - self.kh2 = None - self.ItemIsSafe = False - self.game_connected = False - self.finalxemnas = False - self.worldid = { - # 1: {}, # world of darkness (story cutscenes) - 2: TT_Checks, - # 3: {}, # destiny island doesn't have checks to ima put tt checks here - 4: HB_Checks, - 5: BC_Checks, - 6: Oc_Checks, - 7: AG_Checks, - 8: LoD_Checks, - 9: HundredAcreChecks, - 10: PL_Checks, - 11: DC_Checks, # atlantica isn't a supported world. if you go in atlantica it will check dc - 12: DC_Checks, - 13: TR_Checks, - 14: HT_Checks, - 15: HB_Checks, # world map, but you only go to the world map while on the way to goa so checking hb - 16: PR_Checks, - 17: SP_Checks, - 18: TWTNW_Checks, - # 255: {}, # starting screen - } - # 0x2A09C00+0x40 is the sve anchor. +1 is the last saved room - self.sveroom = 0x2A09C00 + 0x41 - # 0 not in battle 1 in yellow battle 2 red battle #short - self.inBattle = 0x2A0EAC4 + 0x40 - self.onDeath = 0xAB9078 - # PC Address anchors - self.Now = 0x0714DB8 - self.Save = 0x09A70B0 - self.Sys3 = 0x2A59DF0 - self.Bt10 = 0x2A74880 - self.BtlEnd = 0x2A0D3E0 - self.Slot1 = 0x2A20C98 - - self.chest_set = set(exclusion_table["Chests"]) - - self.keyblade_set = set(CheckDupingItems["Weapons"]["Keyblades"]) - self.staff_set = set(CheckDupingItems["Weapons"]["Staffs"]) - self.shield_set = set(CheckDupingItems["Weapons"]["Shields"]) - - self.all_weapons = self.keyblade_set.union(self.staff_set).union(self.shield_set) - - self.equipment_categories = CheckDupingItems["Equipment"] - self.armor_set = set(self.equipment_categories["Armor"]) - self.accessories_set = set(self.equipment_categories["Accessories"]) - self.all_equipment = self.armor_set.union(self.accessories_set) - - self.Equipment_Anchor_Dict = { - "Armor": [0x2504, 0x2506, 0x2508, 0x250A], - "Accessories": [0x2514, 0x2516, 0x2518, 0x251A]} - - self.AbilityQuantityDict = {} - self.ability_categories = CheckDupingItems["Abilities"] - - self.sora_ability_set = set(self.ability_categories["Sora"]) - self.donald_ability_set = set(self.ability_categories["Donald"]) - self.goofy_ability_set = set(self.ability_categories["Goofy"]) - - self.all_abilities = self.sora_ability_set.union(self.donald_ability_set).union(self.goofy_ability_set) - - self.boost_set = set(CheckDupingItems["Boosts"]) - self.stat_increase_set = set(CheckDupingItems["Stat Increases"]) - self.AbilityQuantityDict = {item: self.item_name_to_data[item].quantity for item in self.all_abilities} - # Growth:[level 1,level 4,slot] - self.growth_values_dict = {"High Jump": [0x05E, 0x061, 0x25DA], - "Quick Run": [0x62, 0x65, 0x25DC], - "Dodge Roll": [0x234, 0x237, 0x25DE], - "Aerial Dodge": [0x066, 0x069, 0x25E0], - "Glide": [0x6A, 0x6D, 0x25E2]} - self.boost_to_anchor_dict = { - "Power Boost": 0x24F9, - "Magic Boost": 0x24FA, - "Defense Boost": 0x24FB, - "AP Boost": 0x24F8} - - self.AbilityCodeList = [self.item_name_to_data[item].code for item in exclusionItem_table["Ability"]] - self.master_growth = {"High Jump", "Quick Run", "Dodge Roll", "Aerial Dodge", "Glide"} - - self.bitmask_item_code = [ - 0x130000, 0x130001, 0x130002, 0x130003, 0x130004, 0x130005, 0x130006, 0x130007 - , 0x130008, 0x130009, 0x13000A, 0x13000B, 0x13000C - , 0x13001F, 0x130020, 0x130021, 0x130022, 0x130023 - , 0x13002A, 0x13002B, 0x13002C, 0x13002D] - - async def server_auth(self, password_requested: bool = False): - if password_requested and not self.password: - await super(KH2Context, self).server_auth(password_requested) - await self.get_username() - await self.send_connect() - - async def connection_closed(self): - self.kh2connected = False - self.serverconneced = False - if self.kh2seedname is not None and self.auth is not None: - with open(os.path.join(self.game_communication_path, f"kh2save{self.kh2seedname}{self.auth}.json"), - 'w') as f: - f.write(json.dumps(self.kh2seedsave, indent=4)) - await super(KH2Context, self).connection_closed() - - async def disconnect(self, allow_autoreconnect: bool = False): - self.kh2connected = False - self.serverconneced = False - if self.kh2seedname not in {None} and self.auth not in {None}: - with open(os.path.join(self.game_communication_path, f"kh2save{self.kh2seedname}{self.auth}.json"), - 'w') as f: - f.write(json.dumps(self.kh2seedsave, indent=4)) - await super(KH2Context, self).disconnect() - - @property - def endpoints(self): - if self.server: - return [self.server] - else: - return [] - - async def shutdown(self): - if self.kh2seedname not in {None} and self.auth not in {None}: - with open(os.path.join(self.game_communication_path, f"kh2save{self.kh2seedname}{self.auth}.json"), - 'w') as f: - f.write(json.dumps(self.kh2seedsave, indent=4)) - await super(KH2Context, self).shutdown() - - def on_package(self, cmd: str, args: dict): - if cmd in {"RoomInfo"}: - self.kh2seedname = args['seed_name'] - if not os.path.exists(self.game_communication_path): - os.makedirs(self.game_communication_path) - if not os.path.exists(self.game_communication_path + f"\kh2save{self.kh2seedname}{self.auth}.json"): - self.kh2seedsave = {"itemIndex": -1, - # back of soras invo is 0x25E2. Growth should be moved there - # Character: [back of invo, front of invo] - "SoraInvo": [0x25D8, 0x2546], - "DonaldInvo": [0x26F4, 0x2658], - "GoofyInvo": [0x280A, 0x276C], - "AmountInvo": { - "ServerItems": { - "Ability": {}, - "Amount": {}, - "Growth": {"High Jump": 0, "Quick Run": 0, "Dodge Roll": 0, - "Aerial Dodge": 0, - "Glide": 0}, - "Bitmask": [], - "Weapon": {"Sora": [], "Donald": [], "Goofy": []}, - "Equipment": [], - "Magic": {}, - "StatIncrease": {}, - "Boost": {}, - }, - "LocalItems": { - "Ability": {}, - "Amount": {}, - "Growth": {"High Jump": 0, "Quick Run": 0, "Dodge Roll": 0, - "Aerial Dodge": 0, "Glide": 0}, - "Bitmask": [], - "Weapon": {"Sora": [], "Donald": [], "Goofy": []}, - "Equipment": [], - "Magic": {}, - "StatIncrease": {}, - "Boost": {}, - }}, - # 1,3,255 are in this list in case the player gets locations in those "worlds" and I need to still have them checked - "LocationsChecked": [], - "Levels": { - "SoraLevel": 0, - "ValorLevel": 0, - "WisdomLevel": 0, - "LimitLevel": 0, - "MasterLevel": 0, - "FinalLevel": 0, - }, - "SoldEquipment": [], - "SoldBoosts": {"Power Boost": 0, - "Magic Boost": 0, - "Defense Boost": 0, - "AP Boost": 0} - } - with open(os.path.join(self.game_communication_path, f"kh2save{self.kh2seedname}{self.auth}.json"), - 'wt') as f: - pass - self.locations_checked = set() - elif os.path.exists(self.game_communication_path + f"\kh2save{self.kh2seedname}{self.auth}.json"): - with open(self.game_communication_path + f"\kh2save{self.kh2seedname}{self.auth}.json", 'r') as f: - self.kh2seedsave = json.load(f) - self.locations_checked = set(self.kh2seedsave["LocationsChecked"]) - self.serverconneced = True - - if cmd in {"Connected"}: - self.kh2slotdata = args['slot_data'] - self.kh2LocalItems = {int(location): item for location, item in self.kh2slotdata["LocalItems"].items()} - try: - self.kh2 = pymem.Pymem(process_name="KINGDOM HEARTS II FINAL MIX") - logger.info("You are now auto-tracking") - self.kh2connected = True - except Exception as e: - logger.info("Line 247") - if self.kh2connected: - logger.info("Connection Lost") - self.kh2connected = False - logger.info(e) - - if cmd in {"ReceivedItems"}: - start_index = args["index"] - if start_index == 0: - # resetting everything that were sent from the server - self.kh2seedsave["SoraInvo"][0] = 0x25D8 - self.kh2seedsave["DonaldInvo"][0] = 0x26F4 - self.kh2seedsave["GoofyInvo"][0] = 0x280A - self.kh2seedsave["itemIndex"] = - 1 - self.kh2seedsave["AmountInvo"]["ServerItems"] = { - "Ability": {}, - "Amount": {}, - "Growth": {"High Jump": 0, "Quick Run": 0, "Dodge Roll": 0, - "Aerial Dodge": 0, - "Glide": 0}, - "Bitmask": [], - "Weapon": {"Sora": [], "Donald": [], "Goofy": []}, - "Equipment": [], - "Magic": {}, - "StatIncrease": {}, - "Boost": {}, - } - if start_index > self.kh2seedsave["itemIndex"]: - self.kh2seedsave["itemIndex"] = start_index - for item in args['items']: - asyncio.create_task(self.give_item(item.item)) - - if cmd in {"RoomUpdate"}: - if "checked_locations" in args: - new_locations = set(args["checked_locations"]) - # TODO: make this take locations from other players on the same slot so proper coop happens - # items_to_give = [self.kh2slotdata["LocalItems"][str(location_id)] for location_id in new_locations if - # location_id in self.kh2LocalItems.keys()] - self.checked_locations |= new_locations - - async def checkWorldLocations(self): - try: - currentworldint = int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + 0x0714DB8, 1), "big") - if currentworldint in self.worldid: - curworldid = self.worldid[currentworldint] - for location, data in curworldid.items(): - locationId = kh2_loc_name_to_id[location] - if locationId not in self.locations_checked \ - and (int.from_bytes( - self.kh2.read_bytes(self.kh2.base_address + self.Save + data.addrObtained, 1), - "big") & 0x1 << data.bitIndex) > 0: - self.sending = self.sending + [(int(locationId))] - except Exception as e: - logger.info("Line 285") - if self.kh2connected: - logger.info("Connection Lost.") - self.kh2connected = False - logger.info(e) - - async def checkLevels(self): - try: - for location, data in SoraLevels.items(): - currentLevel = int.from_bytes( - self.kh2.read_bytes(self.kh2.base_address + self.Save + 0x24FF, 1), "big") - locationId = kh2_loc_name_to_id[location] - if locationId not in self.locations_checked \ - and currentLevel >= data.bitIndex: - if self.kh2seedsave["Levels"]["SoraLevel"] < currentLevel: - self.kh2seedsave["Levels"]["SoraLevel"] = currentLevel - self.sending = self.sending + [(int(locationId))] - formDict = { - 0: ["ValorLevel", ValorLevels], 1: ["WisdomLevel", WisdomLevels], 2: ["LimitLevel", LimitLevels], - 3: ["MasterLevel", MasterLevels], 4: ["FinalLevel", FinalLevels]} - for i in range(5): - for location, data in formDict[i][1].items(): - formlevel = int.from_bytes( - self.kh2.read_bytes(self.kh2.base_address + self.Save + data.addrObtained, 1), "big") - locationId = kh2_loc_name_to_id[location] - if locationId not in self.locations_checked \ - and formlevel >= data.bitIndex: - if formlevel > self.kh2seedsave["Levels"][formDict[i][0]]: - self.kh2seedsave["Levels"][formDict[i][0]] = formlevel - self.sending = self.sending + [(int(locationId))] - except Exception as e: - logger.info("Line 312") - if self.kh2connected: - logger.info("Connection Lost.") - self.kh2connected = False - logger.info(e) - - async def checkSlots(self): - try: - for location, data in weaponSlots.items(): - locationId = kh2_loc_name_to_id[location] - if locationId not in self.locations_checked: - if int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + self.Save + data.addrObtained, 1), - "big") > 0: - self.sending = self.sending + [(int(locationId))] - - for location, data in formSlots.items(): - locationId = kh2_loc_name_to_id[location] - if locationId not in self.locations_checked: - if int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + self.Save + data.addrObtained, 1), - "big") & 0x1 << data.bitIndex > 0: - # self.locations_checked - self.sending = self.sending + [(int(locationId))] - - except Exception as e: - if self.kh2connected: - logger.info("Line 333") - logger.info("Connection Lost.") - self.kh2connected = False - logger.info(e) - - async def verifyChests(self): - try: - for location in self.locations_checked: - locationName = self.lookup_id_to_Location[location] - if locationName in self.chest_set: - if locationName in self.location_name_to_worlddata.keys(): - locationData = self.location_name_to_worlddata[locationName] - if int.from_bytes( - self.kh2.read_bytes(self.kh2.base_address + self.Save + locationData.addrObtained, 1), - "big") & 0x1 << locationData.bitIndex == 0: - roomData = int.from_bytes( - self.kh2.read_bytes(self.kh2.base_address + self.Save + locationData.addrObtained, - 1), "big") - self.kh2.write_bytes(self.kh2.base_address + self.Save + locationData.addrObtained, - (roomData | 0x01 << locationData.bitIndex).to_bytes(1, 'big'), 1) - - except Exception as e: - if self.kh2connected: - logger.info("Line 350") - logger.info("Connection Lost.") - self.kh2connected = False - logger.info(e) - - async def verifyLevel(self): - for leveltype, anchor in {"SoraLevel": 0x24FF, - "ValorLevel": 0x32F6, - "WisdomLevel": 0x332E, - "LimitLevel": 0x3366, - "MasterLevel": 0x339E, - "FinalLevel": 0x33D6}.items(): - if int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + self.Save + anchor, 1), "big") < \ - self.kh2seedsave["Levels"][leveltype]: - self.kh2.write_bytes(self.kh2.base_address + self.Save + anchor, - (self.kh2seedsave["Levels"][leveltype]).to_bytes(1, 'big'), 1) - - async def give_item(self, item, ItemType="ServerItems"): - try: - itemname = self.lookup_id_to_item[item] - itemcode = self.item_name_to_data[itemname] - if itemcode.ability: - abilityInvoType = 0 - TwilightZone = 2 - if ItemType == "LocalItems": - abilityInvoType = 1 - TwilightZone = -2 - if itemname in {"High Jump", "Quick Run", "Dodge Roll", "Aerial Dodge", "Glide"}: - self.kh2seedsave["AmountInvo"][ItemType]["Growth"][itemname] += 1 - return - - if itemname not in self.kh2seedsave["AmountInvo"][ItemType]["Ability"]: - self.kh2seedsave["AmountInvo"][ItemType]["Ability"][itemname] = [] - # appending the slot that the ability should be in - - if len(self.kh2seedsave["AmountInvo"][ItemType]["Ability"][itemname]) < \ - self.AbilityQuantityDict[itemname]: - if itemname in self.sora_ability_set: - self.kh2seedsave["AmountInvo"][ItemType]["Ability"][itemname].append( - self.kh2seedsave["SoraInvo"][abilityInvoType]) - self.kh2seedsave["SoraInvo"][abilityInvoType] -= TwilightZone - elif itemname in self.donald_ability_set: - self.kh2seedsave["AmountInvo"][ItemType]["Ability"][itemname].append( - self.kh2seedsave["DonaldInvo"][abilityInvoType]) - self.kh2seedsave["DonaldInvo"][abilityInvoType] -= TwilightZone - else: - self.kh2seedsave["AmountInvo"][ItemType]["Ability"][itemname].append( - self.kh2seedsave["GoofyInvo"][abilityInvoType]) - self.kh2seedsave["GoofyInvo"][abilityInvoType] -= TwilightZone - - elif itemcode.code in self.bitmask_item_code: - - if itemname not in self.kh2seedsave["AmountInvo"][ItemType]["Bitmask"]: - self.kh2seedsave["AmountInvo"][ItemType]["Bitmask"].append(itemname) - - elif itemcode.memaddr in {0x3594, 0x3595, 0x3596, 0x3597, 0x35CF, 0x35D0}: - - if itemname in self.kh2seedsave["AmountInvo"][ItemType]["Magic"]: - self.kh2seedsave["AmountInvo"][ItemType]["Magic"][itemname] += 1 - else: - self.kh2seedsave["AmountInvo"][ItemType]["Magic"][itemname] = 1 - elif itemname in self.all_equipment: - - self.kh2seedsave["AmountInvo"][ItemType]["Equipment"].append(itemname) - - elif itemname in self.all_weapons: - if itemname in self.keyblade_set: - self.kh2seedsave["AmountInvo"][ItemType]["Weapon"]["Sora"].append(itemname) - elif itemname in self.staff_set: - self.kh2seedsave["AmountInvo"][ItemType]["Weapon"]["Donald"].append(itemname) - else: - self.kh2seedsave["AmountInvo"][ItemType]["Weapon"]["Goofy"].append(itemname) - - elif itemname in self.boost_set: - if itemname in self.kh2seedsave["AmountInvo"][ItemType]["Boost"]: - self.kh2seedsave["AmountInvo"][ItemType]["Boost"][itemname] += 1 - else: - self.kh2seedsave["AmountInvo"][ItemType]["Boost"][itemname] = 1 - - elif itemname in self.stat_increase_set: - - if itemname in self.kh2seedsave["AmountInvo"][ItemType]["StatIncrease"]: - self.kh2seedsave["AmountInvo"][ItemType]["StatIncrease"][itemname] += 1 - else: - self.kh2seedsave["AmountInvo"][ItemType]["StatIncrease"][itemname] = 1 - - else: - if itemname in self.kh2seedsave["AmountInvo"][ItemType]["Amount"]: - self.kh2seedsave["AmountInvo"][ItemType]["Amount"][itemname] += 1 - else: - self.kh2seedsave["AmountInvo"][ItemType]["Amount"][itemname] = 1 - - except Exception as e: - if self.kh2connected: - logger.info("Line 398") - logger.info("Connection Lost.") - self.kh2connected = False - logger.info(e) - - def run_gui(self): - """Import kivy UI system and start running it as self.ui_task.""" - from kvui import GameManager - - class KH2Manager(GameManager): - logging_pairs = [ - ("Client", "Archipelago") - ] - base_title = "Archipelago KH2 Client" - - self.ui = KH2Manager(self) - self.ui_task = asyncio.create_task(self.ui.async_run(), name="UI") - - async def IsInShop(self, sellable, master_boost): - # journal = 0x741230 shop = 0x741320 - # if journal=-1 and shop = 5 then in shop - # if journam !=-1 and shop = 10 then journal - journal = self.kh2.read_short(self.kh2.base_address + 0x741230) - shop = self.kh2.read_short(self.kh2.base_address + 0x741320) - if (journal == -1 and shop == 5) or (journal != -1 and shop == 10): - # print("your in the shop") - sellable_dict = {} - for itemName in sellable: - itemdata = self.item_name_to_data[itemName] - amount = int.from_bytes( - self.kh2.read_bytes(self.kh2.base_address + self.Save + itemdata.memaddr, 1), "big") - sellable_dict[itemName] = amount - while (journal == -1 and shop == 5) or (journal != -1 and shop == 10): - journal = self.kh2.read_short(self.kh2.base_address + 0x741230) - shop = self.kh2.read_short(self.kh2.base_address + 0x741320) - await asyncio.sleep(0.5) - for item, amount in sellable_dict.items(): - itemdata = self.item_name_to_data[item] - afterShop = int.from_bytes( - self.kh2.read_bytes(self.kh2.base_address + self.Save + itemdata.memaddr, 1), "big") - if afterShop < amount: - if item in master_boost: - self.kh2seedsave["SoldBoosts"][item] += (amount - afterShop) - else: - self.kh2seedsave["SoldEquipment"].append(item) - - async def verifyItems(self): - try: - local_amount = set(self.kh2seedsave["AmountInvo"]["LocalItems"]["Amount"].keys()) - server_amount = set(self.kh2seedsave["AmountInvo"]["ServerItems"]["Amount"].keys()) - master_amount = local_amount | server_amount - - local_ability = set(self.kh2seedsave["AmountInvo"]["LocalItems"]["Ability"].keys()) - server_ability = set(self.kh2seedsave["AmountInvo"]["ServerItems"]["Ability"].keys()) - master_ability = local_ability | server_ability - - local_bitmask = set(self.kh2seedsave["AmountInvo"]["LocalItems"]["Bitmask"]) - server_bitmask = set(self.kh2seedsave["AmountInvo"]["ServerItems"]["Bitmask"]) - master_bitmask = local_bitmask | server_bitmask - - local_keyblade = set(self.kh2seedsave["AmountInvo"]["LocalItems"]["Weapon"]["Sora"]) - local_staff = set(self.kh2seedsave["AmountInvo"]["LocalItems"]["Weapon"]["Donald"]) - local_shield = set(self.kh2seedsave["AmountInvo"]["LocalItems"]["Weapon"]["Goofy"]) - - server_keyblade = set(self.kh2seedsave["AmountInvo"]["ServerItems"]["Weapon"]["Sora"]) - server_staff = set(self.kh2seedsave["AmountInvo"]["ServerItems"]["Weapon"]["Donald"]) - server_shield = set(self.kh2seedsave["AmountInvo"]["ServerItems"]["Weapon"]["Goofy"]) - - master_keyblade = local_keyblade | server_keyblade - master_staff = local_staff | server_staff - master_shield = local_shield | server_shield - - local_equipment = set(self.kh2seedsave["AmountInvo"]["LocalItems"]["Equipment"]) - server_equipment = set(self.kh2seedsave["AmountInvo"]["ServerItems"]["Equipment"]) - master_equipment = local_equipment | server_equipment - - local_magic = set(self.kh2seedsave["AmountInvo"]["LocalItems"]["Magic"].keys()) - server_magic = set(self.kh2seedsave["AmountInvo"]["ServerItems"]["Magic"].keys()) - master_magic = local_magic | server_magic - - local_stat = set(self.kh2seedsave["AmountInvo"]["LocalItems"]["StatIncrease"].keys()) - server_stat = set(self.kh2seedsave["AmountInvo"]["ServerItems"]["StatIncrease"].keys()) - master_stat = local_stat | server_stat - - local_boost = set(self.kh2seedsave["AmountInvo"]["LocalItems"]["Boost"].keys()) - server_boost = set(self.kh2seedsave["AmountInvo"]["ServerItems"]["Boost"].keys()) - master_boost = local_boost | server_boost - - master_sell = master_equipment | master_staff | master_shield | master_boost - await asyncio.create_task(self.IsInShop(master_sell, master_boost)) - for itemName in master_amount: - itemData = self.item_name_to_data[itemName] - amountOfItems = 0 - if itemName in local_amount: - amountOfItems += self.kh2seedsave["AmountInvo"]["LocalItems"]["Amount"][itemName] - if itemName in server_amount: - amountOfItems += self.kh2seedsave["AmountInvo"]["ServerItems"]["Amount"][itemName] - - if itemName == "Torn Page": - # Torn Pages are handled differently because they can be consumed. - # Will check the progression in 100 acre and - the amount of visits - # amountofitems-amount of visits done - for location, data in tornPageLocks.items(): - if int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + self.Save + data.addrObtained, 1), - "big") & 0x1 << data.bitIndex > 0: - amountOfItems -= 1 - if int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + self.Save + itemData.memaddr, 1), - "big") != amountOfItems and amountOfItems >= 0: - self.kh2.write_bytes(self.kh2.base_address + self.Save + itemData.memaddr, - amountOfItems.to_bytes(1, 'big'), 1) - - for itemName in master_keyblade: - itemData = self.item_name_to_data[itemName] - # if the inventory slot for that keyblade is less than the amount they should have - if int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + self.Save + itemData.memaddr, 1), - "big") != 1 and int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + 0x1CFF, 1), - "big") != 13: - # Checking form anchors for the keyblade - if self.kh2.read_short(self.kh2.base_address + self.Save + 0x24F0) == itemData.kh2id \ - or self.kh2.read_short(self.kh2.base_address + self.Save + 0x32F4) == itemData.kh2id \ - or self.kh2.read_short(self.kh2.base_address + self.Save + 0x339C) == itemData.kh2id \ - or self.kh2.read_short(self.kh2.base_address + self.Save + 0x33D4) == itemData.kh2id: - self.kh2.write_bytes(self.kh2.base_address + self.Save + itemData.memaddr, - (0).to_bytes(1, 'big'), 1) - else: - self.kh2.write_bytes(self.kh2.base_address + self.Save + itemData.memaddr, - (1).to_bytes(1, 'big'), 1) - for itemName in master_staff: - itemData = self.item_name_to_data[itemName] - if int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + self.Save + itemData.memaddr, 1), - "big") != 1 \ - and self.kh2.read_short(self.kh2.base_address + self.Save + 0x2604) != itemData.kh2id \ - and itemName not in self.kh2seedsave["SoldEquipment"]: - self.kh2.write_bytes(self.kh2.base_address + self.Save + itemData.memaddr, - (1).to_bytes(1, 'big'), 1) - - for itemName in master_shield: - itemData = self.item_name_to_data[itemName] - if int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + self.Save + itemData.memaddr, 1), - "big") != 1 \ - and self.kh2.read_short(self.kh2.base_address + self.Save + 0x2718) != itemData.kh2id \ - and itemName not in self.kh2seedsave["SoldEquipment"]: - self.kh2.write_bytes(self.kh2.base_address + self.Save + itemData.memaddr, - (1).to_bytes(1, 'big'), 1) - - for itemName in master_ability: - itemData = self.item_name_to_data[itemName] - ability_slot = [] - if itemName in local_ability: - ability_slot += self.kh2seedsave["AmountInvo"]["LocalItems"]["Ability"][itemName] - if itemName in server_ability: - ability_slot += self.kh2seedsave["AmountInvo"]["ServerItems"]["Ability"][itemName] - for slot in ability_slot: - current = self.kh2.read_short(self.kh2.base_address + self.Save + slot) - ability = current & 0x0FFF - if ability | 0x8000 != (0x8000 + itemData.memaddr): - if current - 0x8000 > 0: - self.kh2.write_short(self.kh2.base_address + self.Save + slot, (0x8000 + itemData.memaddr)) - else: - self.kh2.write_short(self.kh2.base_address + self.Save + slot, itemData.memaddr) - # removes the duped ability if client gave faster than the game. - for charInvo in {"SoraInvo", "DonaldInvo", "GoofyInvo"}: - if self.kh2.read_short(self.kh2.base_address + self.Save + self.kh2seedsave[charInvo][1]) != 0 and \ - self.kh2seedsave[charInvo][1] + 2 < self.kh2seedsave[charInvo][0]: - self.kh2.write_short(self.kh2.base_address + self.Save + self.kh2seedsave[charInvo][1], 0) - # remove the dummy level 1 growths if they are in these invo slots. - for inventorySlot in {0x25CE, 0x25D0, 0x25D2, 0x25D4, 0x25D6, 0x25D8}: - current = self.kh2.read_short(self.kh2.base_address + self.Save + inventorySlot) - ability = current & 0x0FFF - if 0x05E <= ability <= 0x06D: - self.kh2.write_short(self.kh2.base_address + self.Save + inventorySlot, 0) - - for itemName in self.master_growth: - growthLevel = self.kh2seedsave["AmountInvo"]["ServerItems"]["Growth"][itemName] \ - + self.kh2seedsave["AmountInvo"]["LocalItems"]["Growth"][itemName] - if growthLevel > 0: - slot = self.growth_values_dict[itemName][2] - min_growth = self.growth_values_dict[itemName][0] - max_growth = self.growth_values_dict[itemName][1] - if growthLevel > 4: - growthLevel = 4 - current_growth_level = self.kh2.read_short(self.kh2.base_address + self.Save + slot) - ability = current_growth_level & 0x0FFF - # if the player should be getting a growth ability - if ability | 0x8000 != 0x8000 + min_growth - 1 + growthLevel: - # if it should be level one of that growth - if 0x8000 + min_growth - 1 + growthLevel <= 0x8000 + min_growth or ability < min_growth: - self.kh2.write_short(self.kh2.base_address + self.Save + slot, min_growth) - # if it is already in the inventory - elif ability | 0x8000 < (0x8000 + max_growth): - self.kh2.write_short(self.kh2.base_address + self.Save + slot, current_growth_level + 1) - - for itemName in master_bitmask: - itemData = self.item_name_to_data[itemName] - itemMemory = int.from_bytes( - self.kh2.read_bytes(self.kh2.base_address + self.Save + itemData.memaddr, 1), "big") - if (int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + self.Save + itemData.memaddr, 1), - "big") & 0x1 << itemData.bitmask) == 0: - # when getting a form anti points should be reset to 0 but bit-shift doesn't trigger the game. - if itemName in {"Valor Form", "Wisdom Form", "Limit Form", "Master Form", "Final Form"}: - self.kh2.write_bytes(self.kh2.base_address + self.Save + 0x3410, - (0).to_bytes(1, 'big'), 1) - self.kh2.write_bytes(self.kh2.base_address + self.Save + itemData.memaddr, - (itemMemory | 0x01 << itemData.bitmask).to_bytes(1, 'big'), 1) - - for itemName in master_equipment: - itemData = self.item_name_to_data[itemName] - isThere = False - if itemName in self.accessories_set: - Equipment_Anchor_List = self.Equipment_Anchor_Dict["Accessories"] - else: - Equipment_Anchor_List = self.Equipment_Anchor_Dict["Armor"] - # Checking form anchors for the equipment - for slot in Equipment_Anchor_List: - if self.kh2.read_short(self.kh2.base_address + self.Save + slot) == itemData.kh2id: - isThere = True - if int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + self.Save + itemData.memaddr, 1), - "big") != 0: - self.kh2.write_bytes(self.kh2.base_address + self.Save + itemData.memaddr, - (0).to_bytes(1, 'big'), 1) - break - if not isThere and itemName not in self.kh2seedsave["SoldEquipment"]: - if int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + self.Save + itemData.memaddr, 1), - "big") != 1: - self.kh2.write_bytes(self.kh2.base_address + self.Save + itemData.memaddr, - (1).to_bytes(1, 'big'), 1) - - for itemName in master_magic: - itemData = self.item_name_to_data[itemName] - amountOfItems = 0 - if itemName in local_magic: - amountOfItems += self.kh2seedsave["AmountInvo"]["LocalItems"]["Magic"][itemName] - if itemName in server_magic: - amountOfItems += self.kh2seedsave["AmountInvo"]["ServerItems"]["Magic"][itemName] - if int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + self.Save + itemData.memaddr, 1), - "big") != amountOfItems \ - and int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + 0x741320, 1), "big") in {10, 8}: - self.kh2.write_bytes(self.kh2.base_address + self.Save + itemData.memaddr, - amountOfItems.to_bytes(1, 'big'), 1) - - for itemName in master_stat: - itemData = self.item_name_to_data[itemName] - amountOfItems = 0 - if itemName in local_stat: - amountOfItems += self.kh2seedsave["AmountInvo"]["LocalItems"]["StatIncrease"][itemName] - if itemName in server_stat: - amountOfItems += self.kh2seedsave["AmountInvo"]["ServerItems"]["StatIncrease"][itemName] - - # 0x130293 is Crit_1's location id for touching the computer - if int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + self.Save + itemData.memaddr, 1), - "big") != amountOfItems \ - and int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + self.Slot1 + 0x1B2, 1), - "big") >= 5 and int.from_bytes( - self.kh2.read_bytes(self.kh2.base_address + self.Save + 0x23DF, 1), - "big") > 0: - self.kh2.write_bytes(self.kh2.base_address + self.Save + itemData.memaddr, - amountOfItems.to_bytes(1, 'big'), 1) - - for itemName in master_boost: - itemData = self.item_name_to_data[itemName] - amountOfItems = 0 - if itemName in local_boost: - amountOfItems += self.kh2seedsave["AmountInvo"]["LocalItems"]["Boost"][itemName] - if itemName in server_boost: - amountOfItems += self.kh2seedsave["AmountInvo"]["ServerItems"]["Boost"][itemName] - amountOfBoostsInInvo = int.from_bytes( - self.kh2.read_bytes(self.kh2.base_address + self.Save + itemData.memaddr, 1), - "big") - amountOfUsedBoosts = int.from_bytes( - self.kh2.read_bytes(self.kh2.base_address + self.Save + self.boost_to_anchor_dict[itemName], 1), - "big") - # Ap Boots start at +50 for some reason - if itemName == "AP Boost": - amountOfUsedBoosts -= 50 - totalBoosts = (amountOfBoostsInInvo + amountOfUsedBoosts) - if totalBoosts <= amountOfItems - self.kh2seedsave["SoldBoosts"][ - itemName] and amountOfBoostsInInvo < 255: - self.kh2.write_bytes(self.kh2.base_address + self.Save + itemData.memaddr, - (amountOfBoostsInInvo + 1).to_bytes(1, 'big'), 1) - - except Exception as e: - logger.info("Line 573") - if self.kh2connected: - logger.info("Connection Lost.") - self.kh2connected = False - logger.info(e) - - -def finishedGame(ctx: KH2Context, message): - if ctx.kh2slotdata['FinalXemnas'] == 1: - if 0x1301ED in message[0]["locations"]: - ctx.finalxemnas = True - # three proofs - if ctx.kh2slotdata['Goal'] == 0: - if int.from_bytes(ctx.kh2.read_bytes(ctx.kh2.base_address + ctx.Save + 0x36B2, 1), "big") > 0 \ - and int.from_bytes(ctx.kh2.read_bytes(ctx.kh2.base_address + ctx.Save + 0x36B3, 1), "big") > 0 \ - and int.from_bytes(ctx.kh2.read_bytes(ctx.kh2.base_address + ctx.Save + 0x36B4, 1), "big") > 0: - if ctx.kh2slotdata['FinalXemnas'] == 1: - if ctx.finalxemnas: - return True - else: - return False - else: - return True - else: - return False - elif ctx.kh2slotdata['Goal'] == 1: - if int.from_bytes(ctx.kh2.read_bytes(ctx.kh2.base_address + ctx.Save + 0x3641, 1), "big") >= \ - ctx.kh2slotdata['LuckyEmblemsRequired']: - ctx.kh2.write_bytes(ctx.kh2.base_address + ctx.Save + 0x36B2, (1).to_bytes(1, 'big'), 1) - ctx.kh2.write_bytes(ctx.kh2.base_address + ctx.Save + 0x36B3, (1).to_bytes(1, 'big'), 1) - ctx.kh2.write_bytes(ctx.kh2.base_address + ctx.Save + 0x36B4, (1).to_bytes(1, 'big'), 1) - if ctx.kh2slotdata['FinalXemnas'] == 1: - if ctx.finalxemnas: - return True - else: - return False - else: - return True - else: - return False - elif ctx.kh2slotdata['Goal'] == 2: - for boss in ctx.kh2slotdata["hitlist"]: - if boss in message[0]["locations"]: - ctx.amountOfPieces += 1 - if ctx.amountOfPieces >= ctx.kh2slotdata["BountyRequired"]: - ctx.kh2.write_bytes(ctx.kh2.base_address + ctx.Save + 0x36B2, (1).to_bytes(1, 'big'), 1) - ctx.kh2.write_bytes(ctx.kh2.base_address + ctx.Save + 0x36B3, (1).to_bytes(1, 'big'), 1) - ctx.kh2.write_bytes(ctx.kh2.base_address + ctx.Save + 0x36B4, (1).to_bytes(1, 'big'), 1) - if ctx.kh2slotdata['FinalXemnas'] == 1: - if ctx.finalxemnas: - return True - else: - return False - else: - return True - else: - return False - - -async def kh2_watcher(ctx: KH2Context): - while not ctx.exit_event.is_set(): - try: - if ctx.kh2connected and ctx.serverconneced: - ctx.sending = [] - await asyncio.create_task(ctx.checkWorldLocations()) - await asyncio.create_task(ctx.checkLevels()) - await asyncio.create_task(ctx.checkSlots()) - await asyncio.create_task(ctx.verifyChests()) - await asyncio.create_task(ctx.verifyItems()) - await asyncio.create_task(ctx.verifyLevel()) - message = [{"cmd": 'LocationChecks', "locations": ctx.sending}] - if finishedGame(ctx, message): - await ctx.send_msgs([{"cmd": "StatusUpdate", "status": ClientStatus.CLIENT_GOAL}]) - ctx.finished_game = True - location_ids = [] - location_ids = [location for location in message[0]["locations"] if location not in location_ids] - for location in location_ids: - if location not in ctx.locations_checked: - ctx.locations_checked.add(location) - ctx.kh2seedsave["LocationsChecked"].append(location) - if location in ctx.kh2LocalItems: - item = ctx.kh2slotdata["LocalItems"][str(location)] - await asyncio.create_task(ctx.give_item(item, "LocalItems")) - await ctx.send_msgs(message) - elif not ctx.kh2connected and ctx.serverconneced: - logger.info("Game is not open. Disconnecting from Server.") - await ctx.disconnect() - except Exception as e: - logger.info("Line 661") - if ctx.kh2connected: - logger.info("Connection Lost.") - ctx.kh2connected = False - logger.info(e) - await asyncio.sleep(0.5) - - if __name__ == '__main__': - async def main(args): - ctx = KH2Context(args.connect, args.password) - ctx.server_task = asyncio.create_task(server_loop(ctx), name="server loop") - if gui_enabled: - ctx.run_gui() - ctx.run_cli() - progression_watcher = asyncio.create_task( - kh2_watcher(ctx), name="KH2ProgressionWatcher") - - await ctx.exit_event.wait() - ctx.server_address = None - - await progression_watcher - - await ctx.shutdown() - - - import colorama - - parser = get_base_parser(description="KH2 Client, for text interfacing.") - - args, rest = parser.parse_known_args() - colorama.init() - asyncio.run(main(args)) - colorama.deinit() + Utils.init_logging("KH2Client", exception_logger="Client") + launch() diff --git a/setup.py b/setup.py index 0d2da0bb1818..c864a8cc9d39 100644 --- a/setup.py +++ b/setup.py @@ -71,7 +71,6 @@ "Clique", "DLCQuest", "Final Fantasy", - "Kingdom Hearts 2", "Lufia II Ancient Cave", "Meritous", "Ocarina of Time", diff --git a/worlds/LauncherComponents.py b/worlds/LauncherComponents.py index 31739bb24606..03c89b75ff11 100644 --- a/worlds/LauncherComponents.py +++ b/worlds/LauncherComponents.py @@ -112,8 +112,6 @@ def launch_textclient(): # Zillion Component('Zillion Client', 'ZillionClient', file_identifier=SuffixIdentifier('.apzl')), - # Kingdom Hearts 2 - Component('KH2 Client', "KH2Client"), #MegaMan Battle Network 3 Component('MMBN3 Client', 'MMBN3Client', file_identifier=SuffixIdentifier('.apbn3')) diff --git a/worlds/kh2/Client.py b/worlds/kh2/Client.py new file mode 100644 index 000000000000..be85dc6907be --- /dev/null +++ b/worlds/kh2/Client.py @@ -0,0 +1,881 @@ +import ModuleUpdate + +ModuleUpdate.update() + +import os +import asyncio +import json +from pymem import pymem +from . import item_dictionary_table, exclusion_item_table, CheckDupingItems, all_locations, exclusion_table, SupportAbility_Table, ActionAbility_Table, all_weapon_slot +from .Names import ItemName +from .WorldLocations import * + +from NetUtils import ClientStatus +from CommonClient import gui_enabled, logger, get_base_parser, CommonContext, server_loop + + +class KH2Context(CommonContext): + # command_processor: int = KH2CommandProcessor + game = "Kingdom Hearts 2" + items_handling = 0b111 # Indicates you get items sent from other worlds. + + def __init__(self, server_address, password): + super(KH2Context, self).__init__(server_address, password) + self.goofy_ability_to_slot = dict() + self.donald_ability_to_slot = dict() + self.all_weapon_location_id = None + self.sora_ability_to_slot = dict() + self.kh2_seed_save = None + self.kh2_local_items = None + self.growthlevel = None + self.kh2connected = False + self.serverconneced = False + self.item_name_to_data = {name: data for name, data, in item_dictionary_table.items()} + self.location_name_to_data = {name: data for name, data, in all_locations.items()} + self.kh2_loc_name_to_id = None + self.kh2_item_name_to_id = None + self.lookup_id_to_item = None + self.lookup_id_to_location = None + self.sora_ability_dict = {k: v.quantity for dic in [SupportAbility_Table, ActionAbility_Table] for k, v in + dic.items()} + self.location_name_to_worlddata = {name: data for name, data, in all_world_locations.items()} + + self.sending = [] + # list used to keep track of locations+items player has. Used for disoneccting + self.kh2_seed_save_cache = { + "itemIndex": -1, + # back of soras invo is 0x25E2. Growth should be moved there + # Character: [back of invo, front of invo] + "SoraInvo": [0x25D8, 0x2546], + "DonaldInvo": [0x26F4, 0x2658], + "GoofyInvo": [0x2808, 0x276C], + "AmountInvo": { + "Ability": {}, + "Amount": { + "Bounty": 0, + }, + "Growth": { + "High Jump": 0, "Quick Run": 0, "Dodge Roll": 0, + "Aerial Dodge": 0, "Glide": 0 + }, + "Bitmask": [], + "Weapon": {"Sora": [], "Donald": [], "Goofy": []}, + "Equipment": [], + "Magic": { + "Fire Element": 0, + "Blizzard Element": 0, + "Thunder Element": 0, + "Cure Element": 0, + "Magnet Element": 0, + "Reflect Element": 0 + }, + "StatIncrease": { + ItemName.MaxHPUp: 0, + ItemName.MaxMPUp: 0, + ItemName.DriveGaugeUp: 0, + ItemName.ArmorSlotUp: 0, + ItemName.AccessorySlotUp: 0, + ItemName.ItemSlotUp: 0, + }, + }, + } + self.front_of_inventory = { + "Sora": 0x2546, + "Donald": 0x2658, + "Goofy": 0x276C, + } + self.kh2seedname = None + self.kh2slotdata = None + self.itemamount = {} + if "localappdata" in os.environ: + self.game_communication_path = os.path.expandvars(r"%localappdata%\KH2AP") + self.hitlist_bounties = 0 + # hooked object + self.kh2 = None + self.final_xemnas = False + self.worldid_to_locations = { + # 1: {}, # world of darkness (story cutscenes) + 2: TT_Checks, + # 3: {}, # destiny island doesn't have checks + 4: HB_Checks, + 5: BC_Checks, + 6: Oc_Checks, + 7: AG_Checks, + 8: LoD_Checks, + 9: HundredAcreChecks, + 10: PL_Checks, + 11: Atlantica_Checks, + 12: DC_Checks, + 13: TR_Checks, + 14: HT_Checks, + 15: HB_Checks, # world map, but you only go to the world map while on the way to goa so checking hb + 16: PR_Checks, + 17: SP_Checks, + 18: TWTNW_Checks, + # 255: {}, # starting screen + } + # 0x2A09C00+0x40 is the sve anchor. +1 is the last saved room + # self.sveroom = 0x2A09C00 + 0x41 + # 0 not in battle 1 in yellow battle 2 red battle #short + # self.inBattle = 0x2A0EAC4 + 0x40 + # self.onDeath = 0xAB9078 + # PC Address anchors + self.Now = 0x0714DB8 + self.Save = 0x09A70B0 + # self.Sys3 = 0x2A59DF0 + # self.Bt10 = 0x2A74880 + # self.BtlEnd = 0x2A0D3E0 + self.Slot1 = 0x2A20C98 + + self.chest_set = set(exclusion_table["Chests"]) + self.keyblade_set = set(CheckDupingItems["Weapons"]["Keyblades"]) + self.staff_set = set(CheckDupingItems["Weapons"]["Staffs"]) + self.shield_set = set(CheckDupingItems["Weapons"]["Shields"]) + + self.all_weapons = self.keyblade_set.union(self.staff_set).union(self.shield_set) + + self.equipment_categories = CheckDupingItems["Equipment"] + self.armor_set = set(self.equipment_categories["Armor"]) + self.accessories_set = set(self.equipment_categories["Accessories"]) + self.all_equipment = self.armor_set.union(self.accessories_set) + + self.Equipment_Anchor_Dict = { + "Armor": [0x2504, 0x2506, 0x2508, 0x250A], + "Accessories": [0x2514, 0x2516, 0x2518, 0x251A] + } + + self.AbilityQuantityDict = {} + self.ability_categories = CheckDupingItems["Abilities"] + + self.sora_ability_set = set(self.ability_categories["Sora"]) + self.donald_ability_set = set(self.ability_categories["Donald"]) + self.goofy_ability_set = set(self.ability_categories["Goofy"]) + + self.all_abilities = self.sora_ability_set.union(self.donald_ability_set).union(self.goofy_ability_set) + + self.stat_increase_set = set(CheckDupingItems["Stat Increases"]) + self.AbilityQuantityDict = {item: self.item_name_to_data[item].quantity for item in self.all_abilities} + + # Growth:[level 1,level 4,slot] + self.growth_values_dict = { + "High Jump": [0x05E, 0x061, 0x25DA], + "Quick Run": [0x62, 0x65, 0x25DC], + "Dodge Roll": [0x234, 0x237, 0x25DE], + "Aerial Dodge": [0x66, 0x069, 0x25E0], + "Glide": [0x6A, 0x6D, 0x25E2] + } + + self.ability_code_list = None + self.master_growth = {"High Jump", "Quick Run", "Dodge Roll", "Aerial Dodge", "Glide"} + + async def server_auth(self, password_requested: bool = False): + if password_requested and not self.password: + await super(KH2Context, self).server_auth(password_requested) + await self.get_username() + await self.send_connect() + + async def connection_closed(self): + self.kh2connected = False + self.serverconneced = False + if self.kh2seedname is not None and self.auth is not None: + with open(os.path.join(self.game_communication_path, f"kh2save2{self.kh2seedname}{self.auth}.json"), + 'w') as f: + f.write(json.dumps(self.kh2_seed_save, indent=4)) + await super(KH2Context, self).connection_closed() + + async def disconnect(self, allow_autoreconnect: bool = False): + self.kh2connected = False + self.serverconneced = False + if self.kh2seedname not in {None} and self.auth not in {None}: + with open(os.path.join(self.game_communication_path, f"kh2save2{self.kh2seedname}{self.auth}.json"), + 'w') as f: + f.write(json.dumps(self.kh2_seed_save, indent=4)) + await super(KH2Context, self).disconnect() + + @property + def endpoints(self): + if self.server: + return [self.server] + else: + return [] + + async def shutdown(self): + if self.kh2seedname not in {None} and self.auth not in {None}: + with open(os.path.join(self.game_communication_path, f"kh2save2{self.kh2seedname}{self.auth}.json"), + 'w') as f: + f.write(json.dumps(self.kh2_seed_save, indent=4)) + await super(KH2Context, self).shutdown() + + def kh2_read_short(self, address): + return self.kh2.read_short(self.kh2.base_address + address) + + def kh2_write_short(self, address, value): + return self.kh2.write_short(self.kh2.base_address + address, value) + + def kh2_write_byte(self, address, value): + return self.kh2.write_bytes(self.kh2.base_address + address, value.to_bytes(1, 'big'), 1) + + def kh2_read_byte(self, address): + return int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + address, 1), "big") + + def on_package(self, cmd: str, args: dict): + if cmd in {"RoomInfo"}: + self.kh2seedname = args['seed_name'] + if not os.path.exists(self.game_communication_path): + os.makedirs(self.game_communication_path) + if not os.path.exists(self.game_communication_path + f"\kh2save2{self.kh2seedname}{self.auth}.json"): + self.kh2_seed_save = { + "Levels": { + "SoraLevel": 0, + "ValorLevel": 0, + "WisdomLevel": 0, + "LimitLevel": 0, + "MasterLevel": 0, + "FinalLevel": 0, + "SummonLevel": 0, + }, + "SoldEquipment": [], + } + with open(os.path.join(self.game_communication_path, f"kh2save2{self.kh2seedname}{self.auth}.json"), + 'wt') as f: + pass + # self.locations_checked = set() + elif os.path.exists(self.game_communication_path + f"\kh2save2{self.kh2seedname}{self.auth}.json"): + with open(self.game_communication_path + f"\kh2save2{self.kh2seedname}{self.auth}.json", 'r') as f: + self.kh2_seed_save = json.load(f) + if self.kh2_seed_save is None: + self.kh2_seed_save = { + "Levels": { + "SoraLevel": 0, + "ValorLevel": 0, + "WisdomLevel": 0, + "LimitLevel": 0, + "MasterLevel": 0, + "FinalLevel": 0, + "SummonLevel": 0, + }, + "SoldEquipment": [], + } + # self.locations_checked = set(self.kh2_seed_save_cache["LocationsChecked"]) + # self.serverconneced = True + + if cmd in {"Connected"}: + asyncio.create_task(self.send_msgs([{"cmd": "GetDataPackage", "games": ["Kingdom Hearts 2"]}])) + self.kh2slotdata = args['slot_data'] + # self.kh2_local_items = {int(location): item for location, item in self.kh2slotdata["LocalItems"].items()} + self.locations_checked = set(args["checked_locations"]) + + if cmd in {"ReceivedItems"}: + # 0x2546 + # 0x2658 + # 0x276A + start_index = args["index"] + if start_index == 0: + self.kh2_seed_save_cache = { + "itemIndex": -1, + # back of soras invo is 0x25E2. Growth should be moved there + # Character: [back of invo, front of invo] + "SoraInvo": [0x25D8, 0x2546], + "DonaldInvo": [0x26F4, 0x2658], + "GoofyInvo": [0x2808, 0x276C], + "AmountInvo": { + "Ability": {}, + "Amount": { + "Bounty": 0, + }, + "Growth": { + "High Jump": 0, "Quick Run": 0, "Dodge Roll": 0, + "Aerial Dodge": 0, "Glide": 0 + }, + "Bitmask": [], + "Weapon": {"Sora": [], "Donald": [], "Goofy": []}, + "Equipment": [], + "Magic": { + "Fire Element": 0, + "Blizzard Element": 0, + "Thunder Element": 0, + "Cure Element": 0, + "Magnet Element": 0, + "Reflect Element": 0 + }, + "StatIncrease": { + ItemName.MaxHPUp: 0, + ItemName.MaxMPUp: 0, + ItemName.DriveGaugeUp: 0, + ItemName.ArmorSlotUp: 0, + ItemName.AccessorySlotUp: 0, + ItemName.ItemSlotUp: 0, + }, + }, + } + if start_index > self.kh2_seed_save_cache["itemIndex"] and self.serverconneced: + self.kh2_seed_save_cache["itemIndex"] = start_index + for item in args['items']: + asyncio.create_task(self.give_item(item.item, item.location)) + + if cmd in {"RoomUpdate"}: + if "checked_locations" in args: + new_locations = set(args["checked_locations"]) + self.locations_checked |= new_locations + + if cmd in {"DataPackage"}: + self.kh2_loc_name_to_id = args["data"]["games"]["Kingdom Hearts 2"]["location_name_to_id"] + self.lookup_id_to_location = {v: k for k, v in self.kh2_loc_name_to_id.items()} + self.kh2_item_name_to_id = args["data"]["games"]["Kingdom Hearts 2"]["item_name_to_id"] + self.lookup_id_to_item = {v: k for k, v in self.kh2_item_name_to_id.items()} + self.ability_code_list = [self.kh2_item_name_to_id[item] for item in exclusion_item_table["Ability"]] + + if "keyblade_abilities" in self.kh2slotdata.keys(): + sora_ability_dict = self.kh2slotdata["KeybladeAbilities"] + # sora ability to slot + # itemid:[slots that are available for that item] + for k, v in sora_ability_dict.items(): + if v >= 1: + if k not in self.sora_ability_to_slot.keys(): + self.sora_ability_to_slot[k] = [] + for _ in range(sora_ability_dict[k]): + self.sora_ability_to_slot[k].append(self.kh2_seed_save_cache["SoraInvo"][0]) + self.kh2_seed_save_cache["SoraInvo"][0] -= 2 + donald_ability_dict = self.kh2slotdata["StaffAbilities"] + for k, v in donald_ability_dict.items(): + if v >= 1: + if k not in self.donald_ability_to_slot.keys(): + self.donald_ability_to_slot[k] = [] + for _ in range(donald_ability_dict[k]): + self.donald_ability_to_slot[k].append(self.kh2_seed_save_cache["DonaldInvo"][0]) + self.kh2_seed_save_cache["DonaldInvo"][0] -= 2 + goofy_ability_dict = self.kh2slotdata["ShieldAbilities"] + for k, v in goofy_ability_dict.items(): + if v >= 1: + if k not in self.goofy_ability_to_slot.keys(): + self.goofy_ability_to_slot[k] = [] + for _ in range(goofy_ability_dict[k]): + self.goofy_ability_to_slot[k].append(self.kh2_seed_save_cache["GoofyInvo"][0]) + self.kh2_seed_save_cache["GoofyInvo"][0] -= 2 + + all_weapon_location_id = [] + for weapon_location in all_weapon_slot: + all_weapon_location_id.append(self.kh2_loc_name_to_id[weapon_location]) + self.all_weapon_location_id = set(all_weapon_location_id) + try: + self.kh2 = pymem.Pymem(process_name="KINGDOM HEARTS II FINAL MIX") + logger.info("You are now auto-tracking") + self.kh2connected = True + + except Exception as e: + if self.kh2connected: + self.kh2connected = False + logger.info("Game is not open.") + self.serverconneced = True + asyncio.create_task(self.send_msgs([{'cmd': 'Sync'}])) + + async def checkWorldLocations(self): + try: + currentworldint = self.kh2_read_byte(self.Now) + await self.send_msgs([{ + "cmd": "Set", "key": "Slot: " + str(self.slot) + " :CurrentWorld", + "default": 0, "want_reply": True, "operations": [{ + "operation": "replace", + "value": currentworldint + }] + }]) + if currentworldint in self.worldid_to_locations: + curworldid = self.worldid_to_locations[currentworldint] + for location, data in curworldid.items(): + if location in self.kh2_loc_name_to_id.keys(): + locationId = self.kh2_loc_name_to_id[location] + if locationId not in self.locations_checked \ + and self.kh2_read_byte(self.Save + data.addrObtained) & 0x1 << data.bitIndex > 0: + self.sending = self.sending + [(int(locationId))] + except Exception as e: + if self.kh2connected: + self.kh2connected = False + logger.info(e) + logger.info("line 425") + + async def checkLevels(self): + try: + for location, data in SoraLevels.items(): + currentLevel = self.kh2_read_byte(self.Save + 0x24FF) + locationId = self.kh2_loc_name_to_id[location] + if locationId not in self.locations_checked \ + and currentLevel >= data.bitIndex: + if self.kh2_seed_save["Levels"]["SoraLevel"] < currentLevel: + self.kh2_seed_save["Levels"]["SoraLevel"] = currentLevel + self.sending = self.sending + [(int(locationId))] + formDict = { + 0: ["ValorLevel", ValorLevels], 1: ["WisdomLevel", WisdomLevels], 2: ["LimitLevel", LimitLevels], + 3: ["MasterLevel", MasterLevels], 4: ["FinalLevel", FinalLevels], 5: ["SummonLevel", SummonLevels] + } + # TODO: remove formDict[i][0] in self.kh2_seed_save_cache["Levels"].keys() after 4.3 + for i in range(6): + for location, data in formDict[i][1].items(): + formlevel = self.kh2_read_byte(self.Save + data.addrObtained) + if location in self.kh2_loc_name_to_id.keys(): + # if current form level is above other form level + locationId = self.kh2_loc_name_to_id[location] + if locationId not in self.locations_checked \ + and formlevel >= data.bitIndex: + if formlevel > self.kh2_seed_save["Levels"][formDict[i][0]]: + self.kh2_seed_save["Levels"][formDict[i][0]] = formlevel + self.sending = self.sending + [(int(locationId))] + except Exception as e: + if self.kh2connected: + self.kh2connected = False + logger.info(e) + logger.info("line 456") + + async def checkSlots(self): + try: + for location, data in weaponSlots.items(): + locationId = self.kh2_loc_name_to_id[location] + if locationId not in self.locations_checked: + if self.kh2_read_byte(self.Save + data.addrObtained) > 0: + self.sending = self.sending + [(int(locationId))] + + for location, data in formSlots.items(): + locationId = self.kh2_loc_name_to_id[location] + if locationId not in self.locations_checked and self.kh2_read_byte(self.Save + 0x06B2) == 0: + if self.kh2_read_byte(self.Save + data.addrObtained) & 0x1 << data.bitIndex > 0: + self.sending = self.sending + [(int(locationId))] + except Exception as e: + if self.kh2connected: + self.kh2connected = False + logger.info(e) + logger.info("line 475") + + async def verifyChests(self): + try: + for location in self.locations_checked: + locationName = self.lookup_id_to_location[location] + if locationName in self.chest_set: + if locationName in self.location_name_to_worlddata.keys(): + locationData = self.location_name_to_worlddata[locationName] + if self.kh2_read_byte(self.Save + locationData.addrObtained) & 0x1 << locationData.bitIndex == 0: + roomData = self.kh2_read_byte(self.Save + locationData.addrObtained) + self.kh2_write_byte(self.Save + locationData.addrObtained, roomData | 0x01 << locationData.bitIndex) + + except Exception as e: + if self.kh2connected: + self.kh2connected = False + logger.info(e) + logger.info("line 491") + + async def verifyLevel(self): + for leveltype, anchor in { + "SoraLevel": 0x24FF, + "ValorLevel": 0x32F6, + "WisdomLevel": 0x332E, + "LimitLevel": 0x3366, + "MasterLevel": 0x339E, + "FinalLevel": 0x33D6 + }.items(): + if self.kh2_read_byte(self.Save + anchor) < self.kh2_seed_save["Levels"][leveltype]: + self.kh2_write_byte(self.Save + anchor, self.kh2_seed_save["Levels"][leveltype]) + + async def give_item(self, item, location): + try: + # todo: ripout all the itemtype stuff and just have one dictionary. the only thing that needs to be tracked from the server/local is abilites + itemname = self.lookup_id_to_item[item] + itemdata = self.item_name_to_data[itemname] + # itemcode = self.kh2_item_name_to_id[itemname] + if itemdata.ability: + if location in self.all_weapon_location_id: + return + if itemname in {"High Jump", "Quick Run", "Dodge Roll", "Aerial Dodge", "Glide"}: + self.kh2_seed_save_cache["AmountInvo"]["Growth"][itemname] += 1 + return + + if itemname not in self.kh2_seed_save_cache["AmountInvo"]["Ability"]: + self.kh2_seed_save_cache["AmountInvo"]["Ability"][itemname] = [] + # appending the slot that the ability should be in + # for non beta. remove after 4.3 + if "PoptrackerVersion" in self.kh2slotdata: + if self.kh2slotdata["PoptrackerVersionCheck"] < 4.3: + if (itemname in self.sora_ability_set + and len(self.kh2_seed_save_cache["AmountInvo"]["Ability"][itemname]) < self.item_name_to_data[itemname].quantity) \ + and self.kh2_seed_save_cache["SoraInvo"][1] > 0x254C: + ability_slot = self.kh2_seed_save_cache["SoraInvo"][1] + self.kh2_seed_save_cache["AmountInvo"]["Ability"][itemname].append(ability_slot) + self.kh2_seed_save_cache["SoraInvo"][1] -= 2 + elif itemname in self.donald_ability_set: + ability_slot = self.kh2_seed_save_cache["DonaldInvo"][1] + self.kh2_seed_save_cache["AmountInvo"]["Ability"][itemname].append(ability_slot) + self.kh2_seed_save_cache["DonaldInvo"][1] -= 2 + else: + ability_slot = self.kh2_seed_save_cache["GoofyInvo"][1] + self.kh2_seed_save_cache["AmountInvo"]["Ability"][itemname].append(ability_slot) + self.kh2_seed_save_cache["GoofyInvo"][1] -= 2 + + elif len(self.kh2_seed_save_cache["AmountInvo"]["Ability"][itemname]) < \ + self.AbilityQuantityDict[itemname]: + if itemname in self.sora_ability_set: + ability_slot = self.kh2_seed_save_cache["SoraInvo"][0] + self.kh2_seed_save_cache["AmountInvo"]["Ability"][itemname].append(ability_slot) + self.kh2_seed_save_cache["SoraInvo"][0] -= 2 + elif itemname in self.donald_ability_set: + ability_slot = self.kh2_seed_save_cache["DonaldInvo"][0] + self.kh2_seed_save_cache["AmountInvo"]["Ability"][itemname].append(ability_slot) + self.kh2_seed_save_cache["DonaldInvo"][0] -= 2 + elif itemname in self.goofy_ability_set: + ability_slot = self.kh2_seed_save_cache["GoofyInvo"][0] + self.kh2_seed_save_cache["AmountInvo"]["Ability"][itemname].append(ability_slot) + self.kh2_seed_save_cache["GoofyInvo"][0] -= 2 + + elif itemdata.memaddr in {0x36C4, 0x36C5, 0x36C6, 0x36C0, 0x36CA}: + # if memaddr is in a bitmask location in memory + if itemname not in self.kh2_seed_save_cache["AmountInvo"]["Bitmask"]: + self.kh2_seed_save_cache["AmountInvo"]["Bitmask"].append(itemname) + + elif itemdata.memaddr in {0x3594, 0x3595, 0x3596, 0x3597, 0x35CF, 0x35D0}: + # if memaddr is in magic addresses + self.kh2_seed_save_cache["AmountInvo"]["Magic"][itemname] += 1 + + elif itemname in self.all_equipment: + self.kh2_seed_save_cache["AmountInvo"]["Equipment"].append(itemname) + + elif itemname in self.all_weapons: + if itemname in self.keyblade_set: + self.kh2_seed_save_cache["AmountInvo"]["Weapon"]["Sora"].append(itemname) + elif itemname in self.staff_set: + self.kh2_seed_save_cache["AmountInvo"]["Weapon"]["Donald"].append(itemname) + else: + self.kh2_seed_save_cache["AmountInvo"]["Weapon"]["Goofy"].append(itemname) + + elif itemname in self.stat_increase_set: + self.kh2_seed_save_cache["AmountInvo"]["StatIncrease"][itemname] += 1 + else: + if itemname in self.kh2_seed_save_cache["AmountInvo"]["Amount"]: + self.kh2_seed_save_cache["AmountInvo"]["Amount"][itemname] += 1 + else: + self.kh2_seed_save_cache["AmountInvo"]["Amount"][itemname] = 1 + + except Exception as e: + if self.kh2connected: + self.kh2connected = False + logger.info(e) + logger.info("line 582") + + def run_gui(self): + """Import kivy UI system and start running it as self.ui_task.""" + from kvui import GameManager + + class KH2Manager(GameManager): + logging_pairs = [ + ("Client", "Archipelago") + ] + base_title = "Archipelago KH2 Client" + + self.ui = KH2Manager(self) + self.ui_task = asyncio.create_task(self.ui.async_run(), name="UI") + + async def IsInShop(self, sellable): + # journal = 0x741230 shop = 0x741320 + # if journal=-1 and shop = 5 then in shop + # if journal !=-1 and shop = 10 then journal + + journal = self.kh2_read_short(0x741230) + shop = self.kh2_read_short(0x741320) + if (journal == -1 and shop == 5) or (journal != -1 and shop == 10): + # print("your in the shop") + sellable_dict = {} + for itemName in sellable: + itemdata = self.item_name_to_data[itemName] + amount = self.kh2_read_byte(self.Save + itemdata.memaddr) + sellable_dict[itemName] = amount + while (journal == -1 and shop == 5) or (journal != -1 and shop == 10): + journal = self.kh2_read_short(0x741230) + shop = self.kh2_read_short(0x741320) + await asyncio.sleep(0.5) + for item, amount in sellable_dict.items(): + itemdata = self.item_name_to_data[item] + afterShop = self.kh2_read_byte(self.Save + itemdata.memaddr) + if afterShop < amount: + self.kh2_seed_save["SoldEquipment"].append(item) + + async def verifyItems(self): + try: + master_amount = set(self.kh2_seed_save_cache["AmountInvo"]["Amount"].keys()) + + master_ability = set(self.kh2_seed_save_cache["AmountInvo"]["Ability"].keys()) + + master_bitmask = set(self.kh2_seed_save_cache["AmountInvo"]["Bitmask"]) + + master_keyblade = set(self.kh2_seed_save_cache["AmountInvo"]["Weapon"]["Sora"]) + master_staff = set(self.kh2_seed_save_cache["AmountInvo"]["Weapon"]["Donald"]) + master_shield = set(self.kh2_seed_save_cache["AmountInvo"]["Weapon"]["Goofy"]) + + master_equipment = set(self.kh2_seed_save_cache["AmountInvo"]["Equipment"]) + + master_magic = set(self.kh2_seed_save_cache["AmountInvo"]["Magic"].keys()) + + master_stat = set(self.kh2_seed_save_cache["AmountInvo"]["StatIncrease"].keys()) + + master_sell = master_equipment | master_staff | master_shield + + await asyncio.create_task(self.IsInShop(master_sell)) + + for item_name in master_amount: + item_data = self.item_name_to_data[item_name] + amount_of_items = 0 + amount_of_items += self.kh2_seed_save_cache["AmountInvo"]["Amount"][item_name] + + if item_name == "Torn Page": + # Torn Pages are handled differently because they can be consumed. + # Will check the progression in 100 acre and - the amount of visits + # amountofitems-amount of visits done + for location, data in tornPageLocks.items(): + if self.kh2_read_byte(self.Save + data.addrObtained) & 0x1 << data.bitIndex > 0: + amount_of_items -= 1 + if self.kh2_read_byte(self.Save + item_data.memaddr) != amount_of_items and amount_of_items >= 0: + self.kh2_write_byte(self.Save + item_data.memaddr, amount_of_items) + + for item_name in master_keyblade: + item_data = self.item_name_to_data[item_name] + # if the inventory slot for that keyblade is less than the amount they should have, + # and they are not in stt + if self.kh2_read_byte(self.Save + item_data.memaddr) != 1 and self.kh2_read_byte(self.Save + 0x1CFF) != 13: + # Checking form anchors for the keyblade to remove extra keyblades + if self.kh2_read_short(self.Save + 0x24F0) == item_data.kh2id \ + or self.kh2_read_short(self.Save + 0x32F4) == item_data.kh2id \ + or self.kh2_read_short(self.Save + 0x339C) == item_data.kh2id \ + or self.kh2_read_short(self.Save + 0x33D4) == item_data.kh2id: + self.kh2_write_byte(self.Save + item_data.memaddr, 0) + else: + self.kh2_write_byte(self.Save + item_data.memaddr, 1) + + for item_name in master_staff: + item_data = self.item_name_to_data[item_name] + if self.kh2_read_byte(self.Save + item_data.memaddr) != 1 \ + and self.kh2_read_short(self.Save + 0x2604) != item_data.kh2id \ + and item_name not in self.kh2_seed_save["SoldEquipment"]: + self.kh2_write_byte(self.Save + item_data.memaddr, 1) + + for item_name in master_shield: + item_data = self.item_name_to_data[item_name] + if self.kh2_read_byte(self.Save + item_data.memaddr) != 1 \ + and self.kh2_read_short(self.Save + 0x2718) != item_data.kh2id \ + and item_name not in self.kh2_seed_save["SoldEquipment"]: + self.kh2_write_byte(self.Save + item_data.memaddr, 1) + + for item_name in master_ability: + item_data = self.item_name_to_data[item_name] + ability_slot = [] + ability_slot += self.kh2_seed_save_cache["AmountInvo"]["Ability"][item_name] + for slot in ability_slot: + current = self.kh2_read_short(self.Save + slot) + ability = current & 0x0FFF + if ability | 0x8000 != (0x8000 + item_data.memaddr): + if current - 0x8000 > 0: + self.kh2_write_short(self.Save + slot, 0x8000 + item_data.memaddr) + else: + self.kh2_write_short(self.Save + slot, item_data.memaddr) + # removes the duped ability if client gave faster than the game. + + for charInvo in {"Sora", "Donald", "Goofy"}: + if self.kh2_read_short(self.Save + self.front_of_inventory[charInvo]) != 0: + print(f"removed {self.Save + self.front_of_inventory[charInvo]} from {charInvo}") + self.kh2_write_short(self.Save + self.front_of_inventory[charInvo], 0) + + # remove the dummy level 1 growths if they are in these invo slots. + for inventorySlot in {0x25CE, 0x25D0, 0x25D2, 0x25D4, 0x25D6, 0x25D8}: + current = self.kh2_read_short(self.Save + inventorySlot) + ability = current & 0x0FFF + if 0x05E <= ability <= 0x06D: + self.kh2_write_short(self.Save + inventorySlot, 0) + + for item_name in self.master_growth: + growthLevel = self.kh2_seed_save_cache["AmountInvo"]["Growth"][item_name] + if growthLevel > 0: + slot = self.growth_values_dict[item_name][2] + min_growth = self.growth_values_dict[item_name][0] + max_growth = self.growth_values_dict[item_name][1] + if growthLevel > 4: + growthLevel = 4 + current_growth_level = self.kh2_read_short(self.Save + slot) + ability = current_growth_level & 0x0FFF + + # if the player should be getting a growth ability + if ability | 0x8000 != 0x8000 + min_growth - 1 + growthLevel: + # if it should be level one of that growth + if 0x8000 + min_growth - 1 + growthLevel <= 0x8000 + min_growth or ability < min_growth: + self.kh2_write_short(self.Save + slot, min_growth) + # if it is already in the inventory + elif ability | 0x8000 < (0x8000 + max_growth): + self.kh2_write_short(self.Save + slot, current_growth_level + 1) + + for item_name in master_bitmask: + item_data = self.item_name_to_data[item_name] + itemMemory = self.kh2_read_byte(self.Save + item_data.memaddr) + if self.kh2_read_byte(self.Save + item_data.memaddr) & 0x1 << item_data.bitmask == 0: + # when getting a form anti points should be reset to 0 but bit-shift doesn't trigger the game. + if item_name in {"Valor Form", "Wisdom Form", "Limit Form", "Master Form", "Final Form"}: + self.kh2_write_byte(self.Save + 0x3410, 0) + self.kh2_write_byte(self.Save + item_data.memaddr, itemMemory | 0x01 << item_data.bitmask) + + for item_name in master_equipment: + item_data = self.item_name_to_data[item_name] + is_there = False + if item_name in self.accessories_set: + Equipment_Anchor_List = self.Equipment_Anchor_Dict["Accessories"] + else: + Equipment_Anchor_List = self.Equipment_Anchor_Dict["Armor"] + # Checking form anchors for the equipment + for slot in Equipment_Anchor_List: + if self.kh2_read_short(self.Save + slot) == item_data.kh2id: + is_there = True + if self.kh2_read_byte(self.Save + item_data.memaddr) != 0: + self.kh2_write_byte(self.Save + item_data.memaddr, 0) + break + if not is_there and item_name not in self.kh2_seed_save["SoldEquipment"]: + if self.kh2_read_byte(self.Save + item_data.memaddr) != 1: + self.kh2_write_byte(self.Save + item_data.memaddr, 1) + + for item_name in master_magic: + item_data = self.item_name_to_data[item_name] + amount_of_items = 0 + amount_of_items += self.kh2_seed_save_cache["AmountInvo"]["Magic"][item_name] + if self.kh2_read_byte(self.Save + item_data.memaddr) != amount_of_items and self.kh2_read_byte(0x741320) in {10, 8}: + self.kh2_write_byte(self.Save + item_data.memaddr, amount_of_items) + + for item_name in master_stat: + item_data = self.item_name_to_data[item_name] + amount_of_items = 0 + amount_of_items += self.kh2_seed_save_cache["AmountInvo"]["StatIncrease"][item_name] + + # if slot1 has 5 drive gauge and goa lost illusion is checked and they are not in a cutscene + if self.kh2_read_byte(self.Save + item_data.memaddr) != amount_of_items \ + and self.kh2_read_byte(self.Slot1 + 0x1B2) >= 5 and \ + self.kh2_read_byte(self.Save + 0x23DF) & 0x1 << 3 > 0 and self.kh2_read_byte(0x741320) in {10, 8}: + self.kh2_write_byte(self.Save + item_data.memaddr, amount_of_items) + if "PoptrackerVersionCheck" in self.kh2slotdata: + if self.kh2slotdata["PoptrackerVersionCheck"] > 4.2 and self.kh2_read_byte(self.Save + 0x3607) != 1: # telling the goa they are on version 4.3 + self.kh2_write_byte(self.Save + 0x3607, 1) + + except Exception as e: + if self.kh2connected: + self.kh2connected = False + logger.info(e) + logger.info("line 840") + + +def finishedGame(ctx: KH2Context, message): + if ctx.kh2slotdata['FinalXemnas'] == 1: + if not ctx.final_xemnas and ctx.kh2_loc_name_to_id[LocationName.FinalXemnas] in ctx.locations_checked: + ctx.final_xemnas = True + # three proofs + if ctx.kh2slotdata['Goal'] == 0: + if ctx.kh2_read_byte(ctx.Save + 0x36B2) > 0 \ + and ctx.kh2_read_byte(ctx.Save + 0x36B3) > 0 \ + and ctx.kh2_read_byte(ctx.Save + 0x36B4) > 0: + if ctx.kh2slotdata['FinalXemnas'] == 1: + if ctx.final_xemnas: + return True + return False + return True + return False + elif ctx.kh2slotdata['Goal'] == 1: + if ctx.kh2_read_byte(ctx.Save + 0x3641) >= ctx.kh2slotdata['LuckyEmblemsRequired']: + if ctx.kh2_read_byte(ctx.Save + 0x36B3) < 1: + ctx.kh2_write_byte(ctx.Save + 0x36B2, 1) + ctx.kh2_write_byte(ctx.Save + 0x36B3, 1) + ctx.kh2_write_byte(ctx.Save + 0x36B4, 1) + logger.info("The Final Door is now Open") + if ctx.kh2slotdata['FinalXemnas'] == 1: + if ctx.final_xemnas: + return True + return False + return True + return False + elif ctx.kh2slotdata['Goal'] == 2: + # for backwards compat + if "hitlist" in ctx.kh2slotdata: + for boss in ctx.kh2slotdata["hitlist"]: + if boss in message[0]["locations"]: + ctx.hitlist_bounties += 1 + if ctx.hitlist_bounties >= ctx.kh2slotdata["BountyRequired"] or ctx.kh2_seed_save_cache["AmountInvo"]["Amount"]["Bounty"] >= ctx.kh2slotdata["BountyRequired"]: + if ctx.kh2_read_byte(ctx.Save + 0x36B3) < 1: + ctx.kh2_write_byte(ctx.Save + 0x36B2, 1) + ctx.kh2_write_byte(ctx.Save + 0x36B3, 1) + ctx.kh2_write_byte(ctx.Save + 0x36B4, 1) + logger.info("The Final Door is now Open") + if ctx.kh2slotdata['FinalXemnas'] == 1: + if ctx.final_xemnas: + return True + return False + return True + return False + elif ctx.kh2slotdata["Goal"] == 3: + if ctx.kh2_seed_save_cache["AmountInvo"]["Amount"]["Bounty"] >= ctx.kh2slotdata["BountyRequired"] and \ + ctx.kh2_read_byte(ctx.Save + 0x3641) >= ctx.kh2slotdata['LuckyEmblemsRequired']: + if ctx.kh2_read_byte(ctx.Save + 0x36B3) < 1: + ctx.kh2_write_byte(ctx.Save + 0x36B2, 1) + ctx.kh2_write_byte(ctx.Save + 0x36B3, 1) + ctx.kh2_write_byte(ctx.Save + 0x36B4, 1) + logger.info("The Final Door is now Open") + if ctx.kh2slotdata['FinalXemnas'] == 1: + if ctx.final_xemnas: + return True + return False + return True + return False + + +async def kh2_watcher(ctx: KH2Context): + while not ctx.exit_event.is_set(): + try: + if ctx.kh2connected and ctx.serverconneced: + ctx.sending = [] + await asyncio.create_task(ctx.checkWorldLocations()) + await asyncio.create_task(ctx.checkLevels()) + await asyncio.create_task(ctx.checkSlots()) + await asyncio.create_task(ctx.verifyChests()) + await asyncio.create_task(ctx.verifyItems()) + await asyncio.create_task(ctx.verifyLevel()) + message = [{"cmd": 'LocationChecks', "locations": ctx.sending}] + if finishedGame(ctx, message): + await ctx.send_msgs([{"cmd": "StatusUpdate", "status": ClientStatus.CLIENT_GOAL}]) + ctx.finished_game = True + await ctx.send_msgs(message) + elif not ctx.kh2connected and ctx.serverconneced: + logger.info("Game Connection lost. waiting 15 seconds until trying to reconnect.") + ctx.kh2 = None + while not ctx.kh2connected and ctx.serverconneced: + await asyncio.sleep(15) + ctx.kh2 = pymem.Pymem(process_name="KINGDOM HEARTS II FINAL MIX") + if ctx.kh2 is not None: + logger.info("You are now auto-tracking") + ctx.kh2connected = True + except Exception as e: + if ctx.kh2connected: + ctx.kh2connected = False + logger.info(e) + logger.info("line 940") + await asyncio.sleep(0.5) + + +def launch(): + async def main(args): + ctx = KH2Context(args.connect, args.password) + ctx.server_task = asyncio.create_task(server_loop(ctx), name="server loop") + if gui_enabled: + ctx.run_gui() + ctx.run_cli() + progression_watcher = asyncio.create_task( + kh2_watcher(ctx), name="KH2ProgressionWatcher") + + await ctx.exit_event.wait() + ctx.server_address = None + + await progression_watcher + + await ctx.shutdown() + + import colorama + + parser = get_base_parser(description="KH2 Client, for text interfacing.") + + args, rest = parser.parse_known_args() + colorama.init() + asyncio.run(main(args)) + colorama.deinit() diff --git a/worlds/kh2/Items.py b/worlds/kh2/Items.py index aa0e326c3da7..3e656b418bfc 100644 --- a/worlds/kh2/Items.py +++ b/worlds/kh2/Items.py @@ -9,7 +9,6 @@ class KH2Item(Item): class ItemData(typing.NamedTuple): - code: typing.Optional[int] quantity: int = 0 kh2id: int = 0 # Save+ mem addr @@ -20,336 +19,421 @@ class ItemData(typing.NamedTuple): ability: bool = False +# 0x130000 Reports_Table = { - ItemName.SecretAnsemsReport1: ItemData(0x130000, 1, 226, 0x36C4, 6), - ItemName.SecretAnsemsReport2: ItemData(0x130001, 1, 227, 0x36C4, 7), - ItemName.SecretAnsemsReport3: ItemData(0x130002, 1, 228, 0x36C5, 0), - ItemName.SecretAnsemsReport4: ItemData(0x130003, 1, 229, 0x36C5, 1), - ItemName.SecretAnsemsReport5: ItemData(0x130004, 1, 230, 0x36C5, 2), - ItemName.SecretAnsemsReport6: ItemData(0x130005, 1, 231, 0x36C5, 3), - ItemName.SecretAnsemsReport7: ItemData(0x130006, 1, 232, 0x36C5, 4), - ItemName.SecretAnsemsReport8: ItemData(0x130007, 1, 233, 0x36C5, 5), - ItemName.SecretAnsemsReport9: ItemData(0x130008, 1, 234, 0x36C5, 6), - ItemName.SecretAnsemsReport10: ItemData(0x130009, 1, 235, 0x36C5, 7), - ItemName.SecretAnsemsReport11: ItemData(0x13000A, 1, 236, 0x36C6, 0), - ItemName.SecretAnsemsReport12: ItemData(0x13000B, 1, 237, 0x36C6, 1), - ItemName.SecretAnsemsReport13: ItemData(0x13000C, 1, 238, 0x36C6, 2), + ItemName.SecretAnsemsReport1: ItemData(1, 226, 0x36C4, 6), + ItemName.SecretAnsemsReport2: ItemData(1, 227, 0x36C4, 7), + ItemName.SecretAnsemsReport3: ItemData(1, 228, 0x36C5, 0), + ItemName.SecretAnsemsReport4: ItemData(1, 229, 0x36C5, 1), + ItemName.SecretAnsemsReport5: ItemData(1, 230, 0x36C5, 2), + ItemName.SecretAnsemsReport6: ItemData(1, 231, 0x36C5, 3), + ItemName.SecretAnsemsReport7: ItemData(1, 232, 0x36C5, 4), + ItemName.SecretAnsemsReport8: ItemData(1, 233, 0x36C5, 5), + ItemName.SecretAnsemsReport9: ItemData(1, 234, 0x36C5, 6), + ItemName.SecretAnsemsReport10: ItemData(1, 235, 0x36C5, 7), + ItemName.SecretAnsemsReport11: ItemData(1, 236, 0x36C6, 0), + ItemName.SecretAnsemsReport12: ItemData(1, 237, 0x36C6, 1), + ItemName.SecretAnsemsReport13: ItemData(1, 238, 0x36C6, 2), } Progression_Table = { - ItemName.ProofofConnection: ItemData(0x13000D, 1, 593, 0x36B2), - ItemName.ProofofNonexistence: ItemData(0x13000E, 1, 594, 0x36B3), - ItemName.ProofofPeace: ItemData(0x13000F, 1, 595, 0x36B4), - ItemName.PromiseCharm: ItemData(0x130010, 1, 524, 0x3694), - ItemName.NamineSketches: ItemData(0x130011, 1, 368, 0x3642), - ItemName.CastleKey: ItemData(0x130012, 2, 460, 0x365D), # dummy 13 - ItemName.BattlefieldsofWar: ItemData(0x130013, 2, 54, 0x35AE), - ItemName.SwordoftheAncestor: ItemData(0x130014, 2, 55, 0x35AF), - ItemName.BeastsClaw: ItemData(0x130015, 2, 59, 0x35B3), - ItemName.BoneFist: ItemData(0x130016, 2, 60, 0x35B4), - ItemName.ProudFang: ItemData(0x130017, 2, 61, 0x35B5), - ItemName.SkillandCrossbones: ItemData(0x130018, 2, 62, 0x35B6), - ItemName.Scimitar: ItemData(0x130019, 2, 72, 0x35C0), - ItemName.MembershipCard: ItemData(0x13001A, 2, 369, 0x3643), - ItemName.IceCream: ItemData(0x13001B, 3, 375, 0x3649), + ItemName.ProofofConnection: ItemData(1, 593, 0x36B2), + ItemName.ProofofNonexistence: ItemData(1, 594, 0x36B3), + ItemName.ProofofPeace: ItemData(1, 595, 0x36B4), + ItemName.PromiseCharm: ItemData(1, 524, 0x3694), + ItemName.NamineSketches: ItemData(1, 368, 0x3642), + ItemName.CastleKey: ItemData(2, 460, 0x365D), # dummy 13 + ItemName.BattlefieldsofWar: ItemData(2, 54, 0x35AE), + ItemName.SwordoftheAncestor: ItemData(2, 55, 0x35AF), + ItemName.BeastsClaw: ItemData(2, 59, 0x35B3), + ItemName.BoneFist: ItemData(2, 60, 0x35B4), + ItemName.ProudFang: ItemData(2, 61, 0x35B5), + ItemName.SkillandCrossbones: ItemData(2, 62, 0x35B6), + ItemName.Scimitar: ItemData(2, 72, 0x35C0), + ItemName.MembershipCard: ItemData(2, 369, 0x3643), + ItemName.IceCream: ItemData(3, 375, 0x3649), # Changed to 3 instead of one poster, picture and ice cream respectively - ItemName.WaytotheDawn: ItemData(0x13001C, 1, 73, 0x35C1), + ItemName.WaytotheDawn: ItemData(2, 73, 0x35C1), # currently first visit locking doesn't work for twtnw.When goa is updated should be 2 - ItemName.IdentityDisk: ItemData(0x13001D, 2, 74, 0x35C2), - ItemName.TornPages: ItemData(0x13001E, 5, 32, 0x3598), + ItemName.IdentityDisk: ItemData(2, 74, 0x35C2), + ItemName.TornPages: ItemData(5, 32, 0x3598), } Forms_Table = { - ItemName.ValorForm: ItemData(0x13001F, 1, 26, 0x36C0, 1), - ItemName.WisdomForm: ItemData(0x130020, 1, 27, 0x36C0, 2), - ItemName.LimitForm: ItemData(0x130021, 1, 563, 0x36CA, 3), - ItemName.MasterForm: ItemData(0x130022, 1, 31, 0x36C0, 6), - ItemName.FinalForm: ItemData(0x130023, 1, 29, 0x36C0, 4), + ItemName.ValorForm: ItemData(1, 26, 0x36C0, 1), + ItemName.WisdomForm: ItemData(1, 27, 0x36C0, 2), + ItemName.LimitForm: ItemData(1, 563, 0x36CA, 3), + ItemName.MasterForm: ItemData(1, 31, 0x36C0, 6), + ItemName.FinalForm: ItemData(1, 29, 0x36C0, 4), + ItemName.AntiForm: ItemData(1, 30, 0x36C0, 5) } Magic_Table = { - ItemName.FireElement: ItemData(0x130024, 3, 21, 0x3594), - ItemName.BlizzardElement: ItemData(0x130025, 3, 22, 0x3595), - ItemName.ThunderElement: ItemData(0x130026, 3, 23, 0x3596), - ItemName.CureElement: ItemData(0x130027, 3, 24, 0x3597), - ItemName.MagnetElement: ItemData(0x130028, 3, 87, 0x35CF), - ItemName.ReflectElement: ItemData(0x130029, 3, 88, 0x35D0), - ItemName.Genie: ItemData(0x13002A, 1, 159, 0x36C4, 4), - ItemName.PeterPan: ItemData(0x13002B, 1, 160, 0x36C4, 5), - ItemName.Stitch: ItemData(0x13002C, 1, 25, 0x36C0, 0), - ItemName.ChickenLittle: ItemData(0x13002D, 1, 383, 0x36C0, 3), + ItemName.FireElement: ItemData(3, 21, 0x3594), + ItemName.BlizzardElement: ItemData(3, 22, 0x3595), + ItemName.ThunderElement: ItemData(3, 23, 0x3596), + ItemName.CureElement: ItemData(3, 24, 0x3597), + ItemName.MagnetElement: ItemData(3, 87, 0x35CF), + ItemName.ReflectElement: ItemData(3, 88, 0x35D0), +} +Summon_Table = { + ItemName.Genie: ItemData(1, 159, 0x36C4, 4), + ItemName.PeterPan: ItemData(1, 160, 0x36C4, 5), + ItemName.Stitch: ItemData(1, 25, 0x36C0, 0), + ItemName.ChickenLittle: ItemData(1, 383, 0x36C0, 3), } - Movement_Table = { - ItemName.HighJump: ItemData(0x13002E, 4, 94, 0x05E, 0, True), - ItemName.QuickRun: ItemData(0x13002F, 4, 98, 0x062, 0, True), - ItemName.DodgeRoll: ItemData(0x130030, 4, 564, 0x234, 0, True), - ItemName.AerialDodge: ItemData(0x130031, 4, 102, 0x066, 0, True), - ItemName.Glide: ItemData(0x130032, 4, 106, 0x06A, 0, True), + ItemName.HighJump: ItemData(4, 94, 0x05E, ability=True), + ItemName.QuickRun: ItemData(4, 98, 0x062, ability=True), + ItemName.DodgeRoll: ItemData(4, 564, 0x234, ability=True), + ItemName.AerialDodge: ItemData(4, 102, 0x066, ability=True), + ItemName.Glide: ItemData(4, 106, 0x06A, ability=True), } Keyblade_Table = { - ItemName.Oathkeeper: ItemData(0x130033, 1, 42, 0x35A2), - ItemName.Oblivion: ItemData(0x130034, 1, 43, 0x35A3), - ItemName.StarSeeker: ItemData(0x130035, 1, 480, 0x367B), - ItemName.HiddenDragon: ItemData(0x130036, 1, 481, 0x367C), - ItemName.HerosCrest: ItemData(0x130037, 1, 484, 0x367F), - ItemName.Monochrome: ItemData(0x130038, 1, 485, 0x3680), - ItemName.FollowtheWind: ItemData(0x130039, 1, 486, 0x3681), - ItemName.CircleofLife: ItemData(0x13003A, 1, 487, 0x3682), - ItemName.PhotonDebugger: ItemData(0x13003B, 1, 488, 0x3683), - ItemName.GullWing: ItemData(0x13003C, 1, 489, 0x3684), - ItemName.RumblingRose: ItemData(0x13003D, 1, 490, 0x3685), - ItemName.GuardianSoul: ItemData(0x13003E, 1, 491, 0x3686), - ItemName.WishingLamp: ItemData(0x13003F, 1, 492, 0x3687), - ItemName.DecisivePumpkin: ItemData(0x130040, 1, 493, 0x3688), - ItemName.SleepingLion: ItemData(0x130041, 1, 494, 0x3689), - ItemName.SweetMemories: ItemData(0x130042, 1, 495, 0x368A), - ItemName.MysteriousAbyss: ItemData(0x130043, 1, 496, 0x368B), - ItemName.TwoBecomeOne: ItemData(0x130044, 1, 543, 0x3698), - ItemName.FatalCrest: ItemData(0x130045, 1, 497, 0x368C), - ItemName.BondofFlame: ItemData(0x130046, 1, 498, 0x368D), - ItemName.Fenrir: ItemData(0x130047, 1, 499, 0x368E), - ItemName.UltimaWeapon: ItemData(0x130048, 1, 500, 0x368F), - ItemName.WinnersProof: ItemData(0x130049, 1, 544, 0x3699), - ItemName.Pureblood: ItemData(0x13004A, 1, 71, 0x35BF), + ItemName.Oathkeeper: ItemData(1, 42, 0x35A2), + ItemName.Oblivion: ItemData(1, 43, 0x35A3), + ItemName.StarSeeker: ItemData(1, 480, 0x367B), + ItemName.HiddenDragon: ItemData(1, 481, 0x367C), + ItemName.HerosCrest: ItemData(1, 484, 0x367F), + ItemName.Monochrome: ItemData(1, 485, 0x3680), + ItemName.FollowtheWind: ItemData(1, 486, 0x3681), + ItemName.CircleofLife: ItemData(1, 487, 0x3682), + ItemName.PhotonDebugger: ItemData(1, 488, 0x3683), + ItemName.GullWing: ItemData(1, 489, 0x3684), + ItemName.RumblingRose: ItemData(1, 490, 0x3685), + ItemName.GuardianSoul: ItemData(1, 491, 0x3686), + ItemName.WishingLamp: ItemData(1, 492, 0x3687), + ItemName.DecisivePumpkin: ItemData(1, 493, 0x3688), + ItemName.SleepingLion: ItemData(1, 494, 0x3689), + ItemName.SweetMemories: ItemData(1, 495, 0x368A), + ItemName.MysteriousAbyss: ItemData(1, 496, 0x368B), + ItemName.TwoBecomeOne: ItemData(1, 543, 0x3698), + ItemName.FatalCrest: ItemData(1, 497, 0x368C), + ItemName.BondofFlame: ItemData(1, 498, 0x368D), + ItemName.Fenrir: ItemData(1, 499, 0x368E), + ItemName.UltimaWeapon: ItemData(1, 500, 0x368F), + ItemName.WinnersProof: ItemData(1, 544, 0x3699), + ItemName.Pureblood: ItemData(1, 71, 0x35BF), } Staffs_Table = { - ItemName.Centurion2: ItemData(0x13004B, 1, 546, 0x369B), - ItemName.MeteorStaff: ItemData(0x13004C, 1, 150, 0x35F1), - ItemName.NobodyLance: ItemData(0x13004D, 1, 155, 0x35F6), - ItemName.PreciousMushroom: ItemData(0x13004E, 1, 549, 0x369E), - ItemName.PreciousMushroom2: ItemData(0x13004F, 1, 550, 0x369F), - ItemName.PremiumMushroom: ItemData(0x130050, 1, 551, 0x36A0), - ItemName.RisingDragon: ItemData(0x130051, 1, 154, 0x35F5), - ItemName.SaveTheQueen2: ItemData(0x130052, 1, 503, 0x3692), - ItemName.ShamansRelic: ItemData(0x130053, 1, 156, 0x35F7), + ItemName.Centurion2: ItemData(1, 546, 0x369B), + ItemName.MeteorStaff: ItemData(1, 150, 0x35F1), + ItemName.NobodyLance: ItemData(1, 155, 0x35F6), + ItemName.PreciousMushroom: ItemData(1, 549, 0x369E), + ItemName.PreciousMushroom2: ItemData(1, 550, 0x369F), + ItemName.PremiumMushroom: ItemData(1, 551, 0x36A0), + ItemName.RisingDragon: ItemData(1, 154, 0x35F5), + ItemName.SaveTheQueen2: ItemData(1, 503, 0x3692), + ItemName.ShamansRelic: ItemData(1, 156, 0x35F7), } Shields_Table = { - ItemName.AkashicRecord: ItemData(0x130054, 1, 146, 0x35ED), - ItemName.FrozenPride2: ItemData(0x130055, 1, 553, 0x36A2), - ItemName.GenjiShield: ItemData(0x130056, 1, 145, 0x35EC), - ItemName.MajesticMushroom: ItemData(0x130057, 1, 556, 0x36A5), - ItemName.MajesticMushroom2: ItemData(0x130058, 1, 557, 0x36A6), - ItemName.NobodyGuard: ItemData(0x130059, 1, 147, 0x35EE), - ItemName.OgreShield: ItemData(0x13005A, 1, 141, 0x35E8), - ItemName.SaveTheKing2: ItemData(0x13005B, 1, 504, 0x3693), - ItemName.UltimateMushroom: ItemData(0x13005C, 1, 558, 0x36A7), + ItemName.AkashicRecord: ItemData(1, 146, 0x35ED), + ItemName.FrozenPride2: ItemData(1, 553, 0x36A2), + ItemName.GenjiShield: ItemData(1, 145, 0x35EC), + ItemName.MajesticMushroom: ItemData(1, 556, 0x36A5), + ItemName.MajesticMushroom2: ItemData(1, 557, 0x36A6), + ItemName.NobodyGuard: ItemData(1, 147, 0x35EE), + ItemName.OgreShield: ItemData(1, 141, 0x35E8), + ItemName.SaveTheKing2: ItemData(1, 504, 0x3693), + ItemName.UltimateMushroom: ItemData(1, 558, 0x36A7), } Accessory_Table = { - ItemName.AbilityRing: ItemData(0x13005D, 1, 8, 0x3587), - ItemName.EngineersRing: ItemData(0x13005E, 1, 9, 0x3588), - ItemName.TechniciansRing: ItemData(0x13005F, 1, 10, 0x3589), - ItemName.SkillRing: ItemData(0x130060, 1, 38, 0x359F), - ItemName.SkillfulRing: ItemData(0x130061, 1, 39, 0x35A0), - ItemName.ExpertsRing: ItemData(0x130062, 1, 11, 0x358A), - ItemName.MastersRing: ItemData(0x130063, 1, 34, 0x359B), - ItemName.CosmicRing: ItemData(0x130064, 1, 52, 0x35AD), - ItemName.ExecutivesRing: ItemData(0x130065, 1, 599, 0x36B5), - ItemName.SardonyxRing: ItemData(0x130066, 1, 12, 0x358B), - ItemName.TourmalineRing: ItemData(0x130067, 1, 13, 0x358C), - ItemName.AquamarineRing: ItemData(0x130068, 1, 14, 0x358D), - ItemName.GarnetRing: ItemData(0x130069, 1, 15, 0x358E), - ItemName.DiamondRing: ItemData(0x13006A, 1, 16, 0x358F), - ItemName.SilverRing: ItemData(0x13006B, 1, 17, 0x3590), - ItemName.GoldRing: ItemData(0x13006C, 1, 18, 0x3591), - ItemName.PlatinumRing: ItemData(0x13006D, 1, 19, 0x3592), - ItemName.MythrilRing: ItemData(0x13006E, 1, 20, 0x3593), - ItemName.OrichalcumRing: ItemData(0x13006F, 1, 28, 0x359A), - ItemName.SoldierEarring: ItemData(0x130070, 1, 40, 0x35A6), - ItemName.FencerEarring: ItemData(0x130071, 1, 46, 0x35A7), - ItemName.MageEarring: ItemData(0x130072, 1, 47, 0x35A8), - ItemName.SlayerEarring: ItemData(0x130073, 1, 48, 0x35AC), - ItemName.Medal: ItemData(0x130074, 1, 53, 0x35B0), - ItemName.MoonAmulet: ItemData(0x130075, 1, 35, 0x359C), - ItemName.StarCharm: ItemData(0x130076, 1, 36, 0x359E), - ItemName.CosmicArts: ItemData(0x130077, 1, 56, 0x35B1), - ItemName.ShadowArchive: ItemData(0x130078, 1, 57, 0x35B2), - ItemName.ShadowArchive2: ItemData(0x130079, 1, 58, 0x35B7), - ItemName.FullBloom: ItemData(0x13007A, 1, 64, 0x35B9), - ItemName.FullBloom2: ItemData(0x13007B, 1, 66, 0x35BB), - ItemName.DrawRing: ItemData(0x13007C, 1, 65, 0x35BA), - ItemName.LuckyRing: ItemData(0x13007D, 1, 63, 0x35B8), + ItemName.AbilityRing: ItemData(1, 8, 0x3587), + ItemName.EngineersRing: ItemData(1, 9, 0x3588), + ItemName.TechniciansRing: ItemData(1, 10, 0x3589), + ItemName.SkillRing: ItemData(1, 38, 0x359F), + ItemName.SkillfulRing: ItemData(1, 39, 0x35A0), + ItemName.ExpertsRing: ItemData(1, 11, 0x358A), + ItemName.MastersRing: ItemData(1, 34, 0x359B), + ItemName.CosmicRing: ItemData(1, 52, 0x35AD), + ItemName.ExecutivesRing: ItemData(1, 599, 0x36B5), + ItemName.SardonyxRing: ItemData(1, 12, 0x358B), + ItemName.TourmalineRing: ItemData(1, 13, 0x358C), + ItemName.AquamarineRing: ItemData(1, 14, 0x358D), + ItemName.GarnetRing: ItemData(1, 15, 0x358E), + ItemName.DiamondRing: ItemData(1, 16, 0x358F), + ItemName.SilverRing: ItemData(1, 17, 0x3590), + ItemName.GoldRing: ItemData(1, 18, 0x3591), + ItemName.PlatinumRing: ItemData(1, 19, 0x3592), + ItemName.MythrilRing: ItemData(1, 20, 0x3593), + ItemName.OrichalcumRing: ItemData(1, 28, 0x359A), + ItemName.SoldierEarring: ItemData(1, 40, 0x35A6), + ItemName.FencerEarring: ItemData(1, 46, 0x35A7), + ItemName.MageEarring: ItemData(1, 47, 0x35A8), + ItemName.SlayerEarring: ItemData(1, 48, 0x35AC), + ItemName.Medal: ItemData(1, 53, 0x35B0), + ItemName.MoonAmulet: ItemData(1, 35, 0x359C), + ItemName.StarCharm: ItemData(1, 36, 0x359E), + ItemName.CosmicArts: ItemData(1, 56, 0x35B1), + ItemName.ShadowArchive: ItemData(1, 57, 0x35B2), + ItemName.ShadowArchive2: ItemData(1, 58, 0x35B7), + ItemName.FullBloom: ItemData(1, 64, 0x35B9), + ItemName.FullBloom2: ItemData(1, 66, 0x35BB), + ItemName.DrawRing: ItemData(1, 65, 0x35BA), + ItemName.LuckyRing: ItemData(1, 63, 0x35B8), } Armor_Table = { - ItemName.ElvenBandana: ItemData(0x13007E, 1, 67, 0x35BC), - ItemName.DivineBandana: ItemData(0x13007F, 1, 68, 0x35BD), - ItemName.ProtectBelt: ItemData(0x130080, 1, 78, 0x35C7), - ItemName.GaiaBelt: ItemData(0x130081, 1, 79, 0x35CA), - ItemName.PowerBand: ItemData(0x130082, 1, 69, 0x35BE), - ItemName.BusterBand: ItemData(0x130083, 1, 70, 0x35C6), - ItemName.CosmicBelt: ItemData(0x130084, 1, 111, 0x35D1), - ItemName.FireBangle: ItemData(0x130085, 1, 173, 0x35D7), - ItemName.FiraBangle: ItemData(0x130086, 1, 174, 0x35D8), - ItemName.FiragaBangle: ItemData(0x130087, 1, 197, 0x35D9), - ItemName.FiragunBangle: ItemData(0x130088, 1, 284, 0x35DA), - ItemName.BlizzardArmlet: ItemData(0x130089, 1, 286, 0x35DC), - ItemName.BlizzaraArmlet: ItemData(0x13008A, 1, 287, 0x35DD), - ItemName.BlizzagaArmlet: ItemData(0x13008B, 1, 288, 0x35DE), - ItemName.BlizzagunArmlet: ItemData(0x13008C, 1, 289, 0x35DF), - ItemName.ThunderTrinket: ItemData(0x13008D, 1, 291, 0x35E2), - ItemName.ThundaraTrinket: ItemData(0x13008E, 1, 292, 0x35E3), - ItemName.ThundagaTrinket: ItemData(0x13008F, 1, 293, 0x35E4), - ItemName.ThundagunTrinket: ItemData(0x130090, 1, 294, 0x35E5), - ItemName.ShockCharm: ItemData(0x130091, 1, 132, 0x35D2), - ItemName.ShockCharm2: ItemData(0x130092, 1, 133, 0x35D3), - ItemName.ShadowAnklet: ItemData(0x130093, 1, 296, 0x35F9), - ItemName.DarkAnklet: ItemData(0x130094, 1, 297, 0x35FB), - ItemName.MidnightAnklet: ItemData(0x130095, 1, 298, 0x35FC), - ItemName.ChaosAnklet: ItemData(0x130096, 1, 299, 0x35FD), - ItemName.ChampionBelt: ItemData(0x130097, 1, 305, 0x3603), - ItemName.AbasChain: ItemData(0x130098, 1, 301, 0x35FF), - ItemName.AegisChain: ItemData(0x130099, 1, 302, 0x3600), - ItemName.Acrisius: ItemData(0x13009A, 1, 303, 0x3601), - ItemName.Acrisius2: ItemData(0x13009B, 1, 307, 0x3605), - ItemName.CosmicChain: ItemData(0x13009C, 1, 308, 0x3606), - ItemName.PetiteRibbon: ItemData(0x13009D, 1, 306, 0x3604), - ItemName.Ribbon: ItemData(0x13009E, 1, 304, 0x3602), - ItemName.GrandRibbon: ItemData(0x13009F, 1, 157, 0x35D4), + ItemName.ElvenBandana: ItemData(1, 67, 0x35BC), + ItemName.DivineBandana: ItemData(1, 68, 0x35BD), + ItemName.ProtectBelt: ItemData(1, 78, 0x35C7), + ItemName.GaiaBelt: ItemData(1, 79, 0x35CA), + ItemName.PowerBand: ItemData(1, 69, 0x35BE), + ItemName.BusterBand: ItemData(1, 70, 0x35C6), + ItemName.CosmicBelt: ItemData(1, 111, 0x35D1), + ItemName.FireBangle: ItemData(1, 173, 0x35D7), + ItemName.FiraBangle: ItemData(1, 174, 0x35D8), + ItemName.FiragaBangle: ItemData(1, 197, 0x35D9), + ItemName.FiragunBangle: ItemData(1, 284, 0x35DA), + ItemName.BlizzardArmlet: ItemData(1, 286, 0x35DC), + ItemName.BlizzaraArmlet: ItemData(1, 287, 0x35DD), + ItemName.BlizzagaArmlet: ItemData(1, 288, 0x35DE), + ItemName.BlizzagunArmlet: ItemData(1, 289, 0x35DF), + ItemName.ThunderTrinket: ItemData(1, 291, 0x35E2), + ItemName.ThundaraTrinket: ItemData(1, 292, 0x35E3), + ItemName.ThundagaTrinket: ItemData(1, 293, 0x35E4), + ItemName.ThundagunTrinket: ItemData(1, 294, 0x35E5), + ItemName.ShockCharm: ItemData(1, 132, 0x35D2), + ItemName.ShockCharm2: ItemData(1, 133, 0x35D3), + ItemName.ShadowAnklet: ItemData(1, 296, 0x35F9), + ItemName.DarkAnklet: ItemData(1, 297, 0x35FB), + ItemName.MidnightAnklet: ItemData(1, 298, 0x35FC), + ItemName.ChaosAnklet: ItemData(1, 299, 0x35FD), + ItemName.ChampionBelt: ItemData(1, 305, 0x3603), + ItemName.AbasChain: ItemData(1, 301, 0x35FF), + ItemName.AegisChain: ItemData(1, 302, 0x3600), + ItemName.Acrisius: ItemData(1, 303, 0x3601), + ItemName.Acrisius2: ItemData(1, 307, 0x3605), + ItemName.CosmicChain: ItemData(1, 308, 0x3606), + ItemName.PetiteRibbon: ItemData(1, 306, 0x3604), + ItemName.Ribbon: ItemData(1, 304, 0x3602), + ItemName.GrandRibbon: ItemData(1, 157, 0x35D4), } Usefull_Table = { - ItemName.MickyMunnyPouch: ItemData(0x1300A0, 3, 535, 0x3695), # 5000 munny per - ItemName.OletteMunnyPouch: ItemData(0x1300A1, 6, 362, 0x363C), # 2500 munny per - ItemName.HadesCupTrophy: ItemData(0x1300A2, 1, 537, 0x3696), - ItemName.UnknownDisk: ItemData(0x1300A3, 1, 462, 0x365F), - ItemName.OlympusStone: ItemData(0x1300A4, 1, 370, 0x3644), - ItemName.MaxHPUp: ItemData(0x1300A5, 20, 470, 0x3671), - ItemName.MaxMPUp: ItemData(0x1300A6, 4, 471, 0x3672), - ItemName.DriveGaugeUp: ItemData(0x1300A7, 6, 472, 0x3673), - ItemName.ArmorSlotUp: ItemData(0x1300A8, 3, 473, 0x3674), - ItemName.AccessorySlotUp: ItemData(0x1300A9, 3, 474, 0x3675), - ItemName.ItemSlotUp: ItemData(0x1300AA, 5, 463, 0x3660), + ItemName.MickeyMunnyPouch: ItemData(1, 535, 0x3695), # 5000 munny per + ItemName.OletteMunnyPouch: ItemData(2, 362, 0x363C), # 2500 munny per + ItemName.HadesCupTrophy: ItemData(1, 537, 0x3696), + ItemName.UnknownDisk: ItemData(1, 462, 0x365F), + ItemName.OlympusStone: ItemData(1, 370, 0x3644), + ItemName.MaxHPUp: ItemData(20, 112, 0x3671), # 470 is DUMMY 23, 112 is Encampment Area Map + ItemName.MaxMPUp: ItemData(4, 113, 0x3672), # 471 is DUMMY 24, 113 is Village Area Map + ItemName.DriveGaugeUp: ItemData(6, 114, 0x3673), # 472 is DUMMY 25, 114 is Cornerstone Hill Map + ItemName.ArmorSlotUp: ItemData(3, 116, 0x3674), # 473 is DUMMY 26, 116 is Lilliput Map + ItemName.AccessorySlotUp: ItemData(3, 117, 0x3675), # 474 is DUMMY 27, 117 is Building Site Map + ItemName.ItemSlotUp: ItemData(5, 118, 0x3660), # 463 is DUMMY 16, 118 is Mickey’s House Map } SupportAbility_Table = { - ItemName.Scan: ItemData(0x1300AB, 2, 138, 0x08A, 0, True), - ItemName.AerialRecovery: ItemData(0x1300AC, 1, 158, 0x09E, 0, True), - ItemName.ComboMaster: ItemData(0x1300AD, 1, 539, 0x21B, 0, True), - ItemName.ComboPlus: ItemData(0x1300AE, 3, 162, 0x0A2, 0, True), - ItemName.AirComboPlus: ItemData(0x1300AF, 3, 163, 0x0A3, 0, True), - ItemName.ComboBoost: ItemData(0x1300B0, 2, 390, 0x186, 0, True), - ItemName.AirComboBoost: ItemData(0x1300B1, 2, 391, 0x187, 0, True), - ItemName.ReactionBoost: ItemData(0x1300B2, 3, 392, 0x188, 0, True), - ItemName.FinishingPlus: ItemData(0x1300B3, 3, 393, 0x189, 0, True), - ItemName.NegativeCombo: ItemData(0x1300B4, 2, 394, 0x18A, 0, True), - ItemName.BerserkCharge: ItemData(0x1300B5, 2, 395, 0x18B, 0, True), - ItemName.DamageDrive: ItemData(0x1300B6, 2, 396, 0x18C, 0, True), - ItemName.DriveBoost: ItemData(0x1300B7, 2, 397, 0x18D, 0, True), - ItemName.FormBoost: ItemData(0x1300B8, 3, 398, 0x18E, 0, True), - ItemName.SummonBoost: ItemData(0x1300B9, 1, 399, 0x18F, 0, True), - ItemName.ExperienceBoost: ItemData(0x1300BA, 2, 401, 0x191, 0, True), - ItemName.Draw: ItemData(0x1300BB, 4, 405, 0x195, 0, True), - ItemName.Jackpot: ItemData(0x1300BC, 2, 406, 0x196, 0, True), - ItemName.LuckyLucky: ItemData(0x1300BD, 3, 407, 0x197, 0, True), - ItemName.DriveConverter: ItemData(0x1300BE, 2, 540, 0x21C, 0, True), - ItemName.FireBoost: ItemData(0x1300BF, 2, 408, 0x198, 0, True), - ItemName.BlizzardBoost: ItemData(0x1300C0, 2, 409, 0x199, 0, True), - ItemName.ThunderBoost: ItemData(0x1300C1, 2, 410, 0x19A, 0, True), - ItemName.ItemBoost: ItemData(0x1300C2, 2, 411, 0x19B, 0, True), - ItemName.MPRage: ItemData(0x1300C3, 2, 412, 0x19C, 0, True), - ItemName.MPHaste: ItemData(0x1300C4, 2, 413, 0x19D, 0, True), - ItemName.MPHastera: ItemData(0x1300C5, 2, 421, 0x1A5, 0, True), - ItemName.MPHastega: ItemData(0x1300C6, 1, 422, 0x1A6, 0, True), - ItemName.Defender: ItemData(0x1300C7, 2, 414, 0x19E, 0, True), - ItemName.DamageControl: ItemData(0x1300C8, 2, 542, 0x21E, 0, True), - ItemName.NoExperience: ItemData(0x1300C9, 1, 404, 0x194, 0, True), - ItemName.LightDarkness: ItemData(0x1300CA, 1, 541, 0x21D, 0, True), - ItemName.MagicLock: ItemData(0x1300CB, 1, 403, 0x193, 0, True), - ItemName.LeafBracer: ItemData(0x1300CC, 1, 402, 0x192, 0, True), - ItemName.CombinationBoost: ItemData(0x1300CD, 1, 400, 0x190, 0, True), - ItemName.OnceMore: ItemData(0x1300CE, 1, 416, 0x1A0, 0, True), - ItemName.SecondChance: ItemData(0x1300CF, 1, 415, 0x19F, 0, True), + ItemName.Scan: ItemData(2, 138, 0x08A, ability=True), + ItemName.AerialRecovery: ItemData(1, 158, 0x09E, ability=True), + ItemName.ComboMaster: ItemData(1, 539, 0x21B, ability=True), + ItemName.ComboPlus: ItemData(3, 162, 0x0A2, ability=True), + ItemName.AirComboPlus: ItemData(3, 163, 0x0A3, ability=True), + ItemName.ComboBoost: ItemData(2, 390, 0x186, ability=True), + ItemName.AirComboBoost: ItemData(2, 391, 0x187, ability=True), + ItemName.ReactionBoost: ItemData(3, 392, 0x188, ability=True), + ItemName.FinishingPlus: ItemData(3, 393, 0x189, ability=True), + ItemName.NegativeCombo: ItemData(2, 394, 0x18A, ability=True), + ItemName.BerserkCharge: ItemData(2, 395, 0x18B, ability=True), + ItemName.DamageDrive: ItemData(2, 396, 0x18C, ability=True), + ItemName.DriveBoost: ItemData(2, 397, 0x18D, ability=True), + ItemName.FormBoost: ItemData(3, 398, 0x18E, ability=True), + ItemName.SummonBoost: ItemData(1, 399, 0x18F, ability=True), + ItemName.ExperienceBoost: ItemData(2, 401, 0x191, ability=True), + ItemName.Draw: ItemData(4, 405, 0x195, ability=True), + ItemName.Jackpot: ItemData(2, 406, 0x196, ability=True), + ItemName.LuckyLucky: ItemData(3, 407, 0x197, ability=True), + ItemName.DriveConverter: ItemData(2, 540, 0x21C, ability=True), + ItemName.FireBoost: ItemData(2, 408, 0x198, ability=True), + ItemName.BlizzardBoost: ItemData(2, 409, 0x199, ability=True), + ItemName.ThunderBoost: ItemData(2, 410, 0x19A, ability=True), + ItemName.ItemBoost: ItemData(2, 411, 0x19B, ability=True), + ItemName.MPRage: ItemData(2, 412, 0x19C, ability=True), + ItemName.MPHaste: ItemData(2, 413, 0x19D, ability=True), + ItemName.MPHastera: ItemData(2, 421, 0x1A5, ability=True), + ItemName.MPHastega: ItemData(1, 422, 0x1A6, ability=True), + ItemName.Defender: ItemData(2, 414, 0x19E, ability=True), + ItemName.DamageControl: ItemData(2, 542, 0x21E, ability=True), + ItemName.NoExperience: ItemData(0, 404, 0x194, ability=True), # quantity changed to 0 because the player starts with one always. + ItemName.LightDarkness: ItemData(1, 541, 0x21D, ability=True), + ItemName.MagicLock: ItemData(1, 403, 0x193, ability=True), + ItemName.LeafBracer: ItemData(1, 402, 0x192, ability=True), + ItemName.CombinationBoost: ItemData(1, 400, 0x190, ability=True), + ItemName.OnceMore: ItemData(1, 416, 0x1A0, ability=True), + ItemName.SecondChance: ItemData(1, 415, 0x19F, ability=True), } ActionAbility_Table = { - ItemName.Guard: ItemData(0x1300D0, 1, 82, 0x052, 0, True), - ItemName.UpperSlash: ItemData(0x1300D1, 1, 137, 0x089, 0, True), - ItemName.HorizontalSlash: ItemData(0x1300D2, 1, 271, 0x10F, 0, True), - ItemName.FinishingLeap: ItemData(0x1300D3, 1, 267, 0x10B, 0, True), - ItemName.RetaliatingSlash: ItemData(0x1300D4, 1, 273, 0x111, 0, True), - ItemName.Slapshot: ItemData(0x1300D5, 1, 262, 0x106, 0, True), - ItemName.DodgeSlash: ItemData(0x1300D6, 1, 263, 0x107, 0, True), - ItemName.FlashStep: ItemData(0x1300D7, 1, 559, 0x22F, 0, True), - ItemName.SlideDash: ItemData(0x1300D8, 1, 264, 0x108, 0, True), - ItemName.VicinityBreak: ItemData(0x1300D9, 1, 562, 0x232, 0, True), - ItemName.GuardBreak: ItemData(0x1300DA, 1, 265, 0x109, 0, True), - ItemName.Explosion: ItemData(0x1300DB, 1, 266, 0x10A, 0, True), - ItemName.AerialSweep: ItemData(0x1300DC, 1, 269, 0x10D, 0, True), - ItemName.AerialDive: ItemData(0x1300DD, 1, 560, 0x230, 0, True), - ItemName.AerialSpiral: ItemData(0x1300DE, 1, 270, 0x10E, 0, True), - ItemName.AerialFinish: ItemData(0x1300DF, 1, 272, 0x110, 0, True), - ItemName.MagnetBurst: ItemData(0x1300E0, 1, 561, 0x231, 0, True), - ItemName.Counterguard: ItemData(0x1300E1, 1, 268, 0x10C, 0, True), - ItemName.AutoValor: ItemData(0x1300E2, 1, 385, 0x181, 0, True), - ItemName.AutoWisdom: ItemData(0x1300E3, 1, 386, 0x182, 0, True), - ItemName.AutoLimit: ItemData(0x1300E4, 1, 568, 0x238, 0, True), - ItemName.AutoMaster: ItemData(0x1300E5, 1, 387, 0x183, 0, True), - ItemName.AutoFinal: ItemData(0x1300E6, 1, 388, 0x184, 0, True), - ItemName.AutoSummon: ItemData(0x1300E7, 1, 389, 0x185, 0, True), - ItemName.TrinityLimit: ItemData(0x1300E8, 1, 198, 0x0C6, 0, True), + ItemName.Guard: ItemData(1, 82, 0x052, ability=True), + ItemName.UpperSlash: ItemData(1, 137, 0x089, ability=True), + ItemName.HorizontalSlash: ItemData(1, 271, 0x10F, ability=True), + ItemName.FinishingLeap: ItemData(1, 267, 0x10B, ability=True), + ItemName.RetaliatingSlash: ItemData(1, 273, 0x111, ability=True), + ItemName.Slapshot: ItemData(1, 262, 0x106, ability=True), + ItemName.DodgeSlash: ItemData(1, 263, 0x107, ability=True), + ItemName.FlashStep: ItemData(1, 559, 0x22F, ability=True), + ItemName.SlideDash: ItemData(1, 264, 0x108, ability=True), + ItemName.VicinityBreak: ItemData(1, 562, 0x232, ability=True), + ItemName.GuardBreak: ItemData(1, 265, 0x109, ability=True), + ItemName.Explosion: ItemData(1, 266, 0x10A, ability=True), + ItemName.AerialSweep: ItemData(1, 269, 0x10D, ability=True), + ItemName.AerialDive: ItemData(1, 560, 0x230, ability=True), + ItemName.AerialSpiral: ItemData(1, 270, 0x10E, ability=True), + ItemName.AerialFinish: ItemData(1, 272, 0x110, ability=True), + ItemName.MagnetBurst: ItemData(1, 561, 0x231, ability=True), + ItemName.Counterguard: ItemData(1, 268, 0x10C, ability=True), + ItemName.AutoValor: ItemData(1, 385, 0x181, ability=True), + ItemName.AutoWisdom: ItemData(1, 386, 0x182, ability=True), + ItemName.AutoLimit: ItemData(1, 568, 0x238, ability=True), + ItemName.AutoMaster: ItemData(1, 387, 0x183, ability=True), + ItemName.AutoFinal: ItemData(1, 388, 0x184, ability=True), + ItemName.AutoSummon: ItemData(1, 389, 0x185, ability=True), + ItemName.TrinityLimit: ItemData(1, 198, 0x0C6, ability=True), } -Items_Table = { - ItemName.PowerBoost: ItemData(0x1300E9, 1, 276, 0x3666), - ItemName.MagicBoost: ItemData(0x1300EA, 1, 277, 0x3667), - ItemName.DefenseBoost: ItemData(0x1300EB, 1, 278, 0x3668), - ItemName.APBoost: ItemData(0x1300EC, 1, 279, 0x3669), +Boosts_Table = { + ItemName.PowerBoost: ItemData(1, 253, 0x359D), # 276, 0x3666, market place map + ItemName.MagicBoost: ItemData(1, 586, 0x35E0), # 277, 0x3667, dark rememberance map + ItemName.DefenseBoost: ItemData(1, 590, 0x35F8), # 278, 0x3668, depths of remembrance map + ItemName.APBoost: ItemData(1, 532, 0x35FE), # 279, 0x3669, mansion map } # These items cannot be in other games so these are done locally in kh2 DonaldAbility_Table = { - ItemName.DonaldFire: ItemData(0x1300ED, 1, 165, 0xA5, 0, True), - ItemName.DonaldBlizzard: ItemData(0x1300EE, 1, 166, 0xA6, 0, True), - ItemName.DonaldThunder: ItemData(0x1300EF, 1, 167, 0xA7, 0, True), - ItemName.DonaldCure: ItemData(0x1300F0, 1, 168, 0xA8, 0, True), - ItemName.Fantasia: ItemData(0x1300F1, 1, 199, 0xC7, 0, True), - ItemName.FlareForce: ItemData(0x1300F2, 1, 200, 0xC8, 0, True), - ItemName.DonaldMPRage: ItemData(0x1300F3, 3, 412, 0x19C, 0, True), - ItemName.DonaldJackpot: ItemData(0x1300F4, 1, 406, 0x196, 0, True), - ItemName.DonaldLuckyLucky: ItemData(0x1300F5, 3, 407, 0x197, 0, True), - ItemName.DonaldFireBoost: ItemData(0x1300F6, 2, 408, 0x198, 0, True), - ItemName.DonaldBlizzardBoost: ItemData(0x1300F7, 2, 409, 0x199, 0, True), - ItemName.DonaldThunderBoost: ItemData(0x1300F8, 2, 410, 0x19A, 0, True), - ItemName.DonaldMPHaste: ItemData(0x1300F9, 1, 413, 0x19D, 0, True), - ItemName.DonaldMPHastera: ItemData(0x1300FA, 2, 421, 0x1A5, 0, True), - ItemName.DonaldMPHastega: ItemData(0x1300FB, 2, 422, 0x1A6, 0, True), - ItemName.DonaldAutoLimit: ItemData(0x1300FC, 1, 417, 0x1A1, 0, True), - ItemName.DonaldHyperHealing: ItemData(0x1300FD, 2, 419, 0x1A3, 0, True), - ItemName.DonaldAutoHealing: ItemData(0x1300FE, 1, 420, 0x1A4, 0, True), - ItemName.DonaldItemBoost: ItemData(0x1300FF, 1, 411, 0x19B, 0, True), - ItemName.DonaldDamageControl: ItemData(0x130100, 2, 542, 0x21E, 0, True), - ItemName.DonaldDraw: ItemData(0x130101, 1, 405, 0x195, 0, True), + ItemName.DonaldFire: ItemData(1, 165, 0xA5, ability=True), + ItemName.DonaldBlizzard: ItemData(1, 166, 0xA6, ability=True), + ItemName.DonaldThunder: ItemData(1, 167, 0xA7, ability=True), + ItemName.DonaldCure: ItemData(1, 168, 0xA8, ability=True), + ItemName.Fantasia: ItemData(1, 199, 0xC7, ability=True), + ItemName.FlareForce: ItemData(1, 200, 0xC8, ability=True), + ItemName.DonaldMPRage: ItemData(1, 412, 0x19C, ability=True), # originally 3 but swapped to 1 because crit checks + ItemName.DonaldJackpot: ItemData(1, 406, 0x196, ability=True), + ItemName.DonaldLuckyLucky: ItemData(3, 407, 0x197, ability=True), + ItemName.DonaldFireBoost: ItemData(2, 408, 0x198, ability=True), + ItemName.DonaldBlizzardBoost: ItemData(2, 409, 0x199, ability=True), + ItemName.DonaldThunderBoost: ItemData(2, 410, 0x19A, ability=True), + ItemName.DonaldMPHaste: ItemData(1, 413, 0x19D, ability=True), + ItemName.DonaldMPHastera: ItemData(2, 421, 0x1A5, ability=True), + ItemName.DonaldMPHastega: ItemData(2, 422, 0x1A6, ability=True), + ItemName.DonaldAutoLimit: ItemData(1, 417, 0x1A1, ability=True), + ItemName.DonaldHyperHealing: ItemData(2, 419, 0x1A3, ability=True), + ItemName.DonaldAutoHealing: ItemData(1, 420, 0x1A4, ability=True), + ItemName.DonaldItemBoost: ItemData(1, 411, 0x19B, ability=True), + ItemName.DonaldDamageControl: ItemData(2, 542, 0x21E, ability=True), + ItemName.DonaldDraw: ItemData(1, 405, 0x195, ability=True), } + GoofyAbility_Table = { - ItemName.GoofyTornado: ItemData(0x130102, 1, 423, 0x1A7, 0, True), - ItemName.GoofyTurbo: ItemData(0x130103, 1, 425, 0x1A9, 0, True), - ItemName.GoofyBash: ItemData(0x130104, 1, 429, 0x1AD, 0, True), - ItemName.TornadoFusion: ItemData(0x130105, 1, 201, 0xC9, 0, True), - ItemName.Teamwork: ItemData(0x130106, 1, 202, 0xCA, 0, True), - ItemName.GoofyDraw: ItemData(0x130107, 1, 405, 0x195, 0, True), - ItemName.GoofyJackpot: ItemData(0x130108, 1, 406, 0x196, 0, True), - ItemName.GoofyLuckyLucky: ItemData(0x130109, 1, 407, 0x197, 0, True), - ItemName.GoofyItemBoost: ItemData(0x13010A, 2, 411, 0x19B, 0, True), - ItemName.GoofyMPRage: ItemData(0x13010B, 2, 412, 0x19C, 0, True), - ItemName.GoofyDefender: ItemData(0x13010C, 2, 414, 0x19E, 0, True), - ItemName.GoofyDamageControl: ItemData(0x13010D, 3, 542, 0x21E, 0, True), - ItemName.GoofyAutoLimit: ItemData(0x13010E, 1, 417, 0x1A1, 0, True), - ItemName.GoofySecondChance: ItemData(0x13010F, 1, 415, 0x19F, 0, True), - ItemName.GoofyOnceMore: ItemData(0x130110, 1, 416, 0x1A0, 0, True), - ItemName.GoofyAutoChange: ItemData(0x130111, 1, 418, 0x1A2, 0, True), - ItemName.GoofyHyperHealing: ItemData(0x130112, 2, 419, 0x1A3, 0, True), - ItemName.GoofyAutoHealing: ItemData(0x130113, 1, 420, 0x1A4, 0, True), - ItemName.GoofyMPHaste: ItemData(0x130114, 1, 413, 0x19D, 0, True), - ItemName.GoofyMPHastera: ItemData(0x130115, 1, 421, 0x1A5, 0, True), - ItemName.GoofyMPHastega: ItemData(0x130116, 1, 422, 0x1A6, 0, True), - ItemName.GoofyProtect: ItemData(0x130117, 2, 596, 0x254, 0, True), - ItemName.GoofyProtera: ItemData(0x130118, 2, 597, 0x255, 0, True), - ItemName.GoofyProtega: ItemData(0x130119, 2, 598, 0x256, 0, True), + ItemName.GoofyTornado: ItemData(1, 423, 0x1A7, ability=True), + ItemName.GoofyTurbo: ItemData(1, 425, 0x1A9, ability=True), + ItemName.GoofyBash: ItemData(1, 429, 0x1AD, ability=True), + ItemName.TornadoFusion: ItemData(1, 201, 0xC9, ability=True), + ItemName.Teamwork: ItemData(1, 202, 0xCA, ability=True), + ItemName.GoofyDraw: ItemData(1, 405, 0x195, ability=True), + ItemName.GoofyJackpot: ItemData(1, 406, 0x196, ability=True), + ItemName.GoofyLuckyLucky: ItemData(1, 407, 0x197, ability=True), + ItemName.GoofyItemBoost: ItemData(2, 411, 0x19B, ability=True), + ItemName.GoofyMPRage: ItemData(2, 412, 0x19C, ability=True), + ItemName.GoofyDefender: ItemData(2, 414, 0x19E, ability=True), + ItemName.GoofyDamageControl: ItemData(1, 542, 0x21E, ability=True), # originally 3 but swapped to 1 because crit checks + ItemName.GoofyAutoLimit: ItemData(1, 417, 0x1A1, ability=True), + ItemName.GoofySecondChance: ItemData(1, 415, 0x19F, ability=True), + ItemName.GoofyOnceMore: ItemData(1, 416, 0x1A0, ability=True), + ItemName.GoofyAutoChange: ItemData(1, 418, 0x1A2, ability=True), + ItemName.GoofyHyperHealing: ItemData(2, 419, 0x1A3, ability=True), + ItemName.GoofyAutoHealing: ItemData(1, 420, 0x1A4, ability=True), + ItemName.GoofyMPHaste: ItemData(1, 413, 0x19D, ability=True), + ItemName.GoofyMPHastera: ItemData(1, 421, 0x1A5, ability=True), + ItemName.GoofyMPHastega: ItemData(1, 422, 0x1A6, ability=True), + ItemName.GoofyProtect: ItemData(2, 596, 0x254, ability=True), + ItemName.GoofyProtera: ItemData(2, 597, 0x255, ability=True), + ItemName.GoofyProtega: ItemData(2, 598, 0x256, ability=True), } -Misc_Table = { - ItemName.LuckyEmblem: ItemData(0x13011A, 0, 367, 0x3641), # letter item - ItemName.Victory: ItemData(0x13011B, 0, 263, 0x111), - ItemName.Bounty: ItemData(0x13011C, 0, 461, 0, 0), # Dummy 14 - # ItemName.UniversalKey:ItemData(0x130129,0,365,0x363F,0)#Tournament Poster +Wincon_Table = { + ItemName.LuckyEmblem: ItemData(kh2id=367, memaddr=0x3641), # letter item + ItemName.Victory: ItemData(kh2id=263, memaddr=0x111), + ItemName.Bounty: ItemData(kh2id=461, memaddr=0x365E), # Dummy 14 + # ItemName.UniversalKey:ItemData(,365,0x363F,0)#Tournament Poster +} +Consumable_Table = { + ItemName.Potion: ItemData(1, 127, 0x36B8), # 1, 0x3580, piglets house map + ItemName.HiPotion: ItemData(1, 126, 0x36B9), # 2, 0x03581, rabbits house map + ItemName.Ether: ItemData(1, 128, 0x36BA), # 3, 0x3582, kangas house map + ItemName.Elixir: ItemData(1, 129, 0x36BB), # 4, 0x3583, spooky cave map + ItemName.Megalixir: ItemData(1, 124, 0x36BC), # 7, 0x3586, starry hill map + ItemName.Tent: ItemData(1, 512, 0x36BD), # 131,0x35E1, savannah map + ItemName.DriveRecovery: ItemData(1, 252, 0x36BE), # 274,0x3664, pride rock map + ItemName.HighDriveRecovery: ItemData(1, 511, 0x36BF), # 275,0x3665, oasis map +} + +Events_Table = { + ItemName.HostileProgramEvent, + ItemName.McpEvent, + ItemName.ASLarxeneEvent, + ItemName.DataLarxeneEvent, + ItemName.BarbosaEvent, + ItemName.GrimReaper1Event, + ItemName.GrimReaper2Event, + ItemName.DataLuxordEvent, + ItemName.DataAxelEvent, + ItemName.CerberusEvent, + ItemName.OlympusPeteEvent, + ItemName.HydraEvent, + ItemName.OcPainAndPanicCupEvent, + ItemName.OcCerberusCupEvent, + ItemName.HadesEvent, + ItemName.ASZexionEvent, + ItemName.DataZexionEvent, + ItemName.Oc2TitanCupEvent, + ItemName.Oc2GofCupEvent, + ItemName.Oc2CupsEvent, + ItemName.HadesCupEvents, + ItemName.PrisonKeeperEvent, + ItemName.OogieBoogieEvent, + ItemName.ExperimentEvent, + ItemName.ASVexenEvent, + ItemName.DataVexenEvent, + ItemName.ShanYuEvent, + ItemName.AnsemRikuEvent, + ItemName.StormRiderEvent, + ItemName.DataXigbarEvent, + ItemName.RoxasEvent, + ItemName.XigbarEvent, + ItemName.LuxordEvent, + ItemName.SaixEvent, + ItemName.XemnasEvent, + ItemName.ArmoredXemnasEvent, + ItemName.ArmoredXemnas2Event, + ItemName.FinalXemnasEvent, + ItemName.DataXemnasEvent, + ItemName.ThresholderEvent, + ItemName.BeastEvent, + ItemName.DarkThornEvent, + ItemName.XaldinEvent, + ItemName.DataXaldinEvent, + ItemName.TwinLordsEvent, + ItemName.GenieJafarEvent, + ItemName.ASLexaeusEvent, + ItemName.DataLexaeusEvent, + ItemName.ScarEvent, + ItemName.GroundShakerEvent, + ItemName.DataSaixEvent, + ItemName.HBDemyxEvent, + ItemName.ThousandHeartlessEvent, + ItemName.Mushroom13Event, + ItemName.SephiEvent, + ItemName.DataDemyxEvent, + ItemName.CorFirstFightEvent, + ItemName.CorSecondFightEvent, + ItemName.TransportEvent, + ItemName.OldPeteEvent, + ItemName.FuturePeteEvent, + ItemName.ASMarluxiaEvent, + ItemName.DataMarluxiaEvent, + ItemName.TerraEvent, + ItemName.TwilightThornEvent, + ItemName.Axel1Event, + ItemName.Axel2Event, + ItemName.DataRoxasEvent, } # Items that are prone to duping. # anchors for checking form keyblade @@ -358,185 +442,37 @@ class ItemData(typing.NamedTuple): # Equipped abilities have an offset of 0x8000 so check for if whatever || whatever+0x8000 CheckDupingItems = { "Items": { - ItemName.ProofofConnection, - ItemName.ProofofNonexistence, - ItemName.ProofofPeace, - ItemName.PromiseCharm, - ItemName.NamineSketches, - ItemName.CastleKey, - ItemName.BattlefieldsofWar, - ItemName.SwordoftheAncestor, - ItemName.BeastsClaw, - ItemName.BoneFist, - ItemName.ProudFang, - ItemName.SkillandCrossbones, - ItemName.Scimitar, - ItemName.MembershipCard, - ItemName.IceCream, - ItemName.WaytotheDawn, - ItemName.IdentityDisk, - ItemName.TornPages, - ItemName.LuckyEmblem, - ItemName.MickyMunnyPouch, - ItemName.OletteMunnyPouch, - ItemName.HadesCupTrophy, - ItemName.UnknownDisk, - ItemName.OlympusStone, + item_name for keys in [Progression_Table.keys(), Wincon_Table.keys(), Consumable_Table, [ItemName.MickeyMunnyPouch, + ItemName.OletteMunnyPouch, + ItemName.HadesCupTrophy, + ItemName.UnknownDisk, + ItemName.OlympusStone, ], Boosts_Table.keys()] + for item_name in keys + }, "Magic": { - ItemName.FireElement, - ItemName.BlizzardElement, - ItemName.ThunderElement, - ItemName.CureElement, - ItemName.MagnetElement, - ItemName.ReflectElement, + magic for magic in Magic_Table.keys() }, "Bitmask": { - ItemName.ValorForm, - ItemName.WisdomForm, - ItemName.LimitForm, - ItemName.MasterForm, - ItemName.FinalForm, - ItemName.Genie, - ItemName.PeterPan, - ItemName.Stitch, - ItemName.ChickenLittle, - ItemName.SecretAnsemsReport1, - ItemName.SecretAnsemsReport2, - ItemName.SecretAnsemsReport3, - ItemName.SecretAnsemsReport4, - ItemName.SecretAnsemsReport5, - ItemName.SecretAnsemsReport6, - ItemName.SecretAnsemsReport7, - ItemName.SecretAnsemsReport8, - ItemName.SecretAnsemsReport9, - ItemName.SecretAnsemsReport10, - ItemName.SecretAnsemsReport11, - ItemName.SecretAnsemsReport12, - ItemName.SecretAnsemsReport13, - + item_name for keys in [Forms_Table.keys(), Summon_Table.keys(), Reports_Table.keys()] for item_name in keys }, "Weapons": { "Keyblades": { - ItemName.Oathkeeper, - ItemName.Oblivion, - ItemName.StarSeeker, - ItemName.HiddenDragon, - ItemName.HerosCrest, - ItemName.Monochrome, - ItemName.FollowtheWind, - ItemName.CircleofLife, - ItemName.PhotonDebugger, - ItemName.GullWing, - ItemName.RumblingRose, - ItemName.GuardianSoul, - ItemName.WishingLamp, - ItemName.DecisivePumpkin, - ItemName.SleepingLion, - ItemName.SweetMemories, - ItemName.MysteriousAbyss, - ItemName.TwoBecomeOne, - ItemName.FatalCrest, - ItemName.BondofFlame, - ItemName.Fenrir, - ItemName.UltimaWeapon, - ItemName.WinnersProof, - ItemName.Pureblood, + keyblade for keyblade in Keyblade_Table.keys() }, "Staffs": { - ItemName.Centurion2, - ItemName.MeteorStaff, - ItemName.NobodyLance, - ItemName.PreciousMushroom, - ItemName.PreciousMushroom2, - ItemName.PremiumMushroom, - ItemName.RisingDragon, - ItemName.SaveTheQueen2, - ItemName.ShamansRelic, + staff for staff in Staffs_Table.keys() }, "Shields": { - ItemName.AkashicRecord, - ItemName.FrozenPride2, - ItemName.GenjiShield, - ItemName.MajesticMushroom, - ItemName.MajesticMushroom2, - ItemName.NobodyGuard, - ItemName.OgreShield, - ItemName.SaveTheKing2, - ItemName.UltimateMushroom, + shield for shield in Shields_Table.keys() } }, "Equipment": { "Accessories": { - ItemName.AbilityRing, - ItemName.EngineersRing, - ItemName.TechniciansRing, - ItemName.SkillRing, - ItemName.SkillfulRing, - ItemName.ExpertsRing, - ItemName.MastersRing, - ItemName.CosmicRing, - ItemName.ExecutivesRing, - ItemName.SardonyxRing, - ItemName.TourmalineRing, - ItemName.AquamarineRing, - ItemName.GarnetRing, - ItemName.DiamondRing, - ItemName.SilverRing, - ItemName.GoldRing, - ItemName.PlatinumRing, - ItemName.MythrilRing, - ItemName.OrichalcumRing, - ItemName.SoldierEarring, - ItemName.FencerEarring, - ItemName.MageEarring, - ItemName.SlayerEarring, - ItemName.Medal, - ItemName.MoonAmulet, - ItemName.StarCharm, - ItemName.CosmicArts, - ItemName.ShadowArchive, - ItemName.ShadowArchive2, - ItemName.FullBloom, - ItemName.FullBloom2, - ItemName.DrawRing, - ItemName.LuckyRing, + accessory for accessory in Accessory_Table.keys() }, "Armor": { - ItemName.ElvenBandana, - ItemName.DivineBandana, - ItemName.ProtectBelt, - ItemName.GaiaBelt, - ItemName.PowerBand, - ItemName.BusterBand, - ItemName.CosmicBelt, - ItemName.FireBangle, - ItemName.FiraBangle, - ItemName.FiragaBangle, - ItemName.FiragunBangle, - ItemName.BlizzardArmlet, - ItemName.BlizzaraArmlet, - ItemName.BlizzagaArmlet, - ItemName.BlizzagunArmlet, - ItemName.ThunderTrinket, - ItemName.ThundaraTrinket, - ItemName.ThundagaTrinket, - ItemName.ThundagunTrinket, - ItemName.ShockCharm, - ItemName.ShockCharm2, - ItemName.ShadowAnklet, - ItemName.DarkAnklet, - ItemName.MidnightAnklet, - ItemName.ChaosAnklet, - ItemName.ChampionBelt, - ItemName.AbasChain, - ItemName.AegisChain, - ItemName.Acrisius, - ItemName.Acrisius2, - ItemName.CosmicChain, - ItemName.PetiteRibbon, - ItemName.Ribbon, - ItemName.GrandRibbon, + armor for armor in Armor_Table.keys() } }, "Stat Increases": { @@ -549,297 +485,103 @@ class ItemData(typing.NamedTuple): }, "Abilities": { "Sora": { - ItemName.Scan, + item_name for keys in [SupportAbility_Table.keys(), ActionAbility_Table.keys(), Movement_Table.keys()] for item_name in keys + }, + "Donald": { + donald_ability for donald_ability in DonaldAbility_Table.keys() + }, + "Goofy": { + goofy_ability for goofy_ability in GoofyAbility_Table.keys() + } + }, +} +progression_set = { + # abilities + item_name for keys in [ + Wincon_Table.keys(), + Progression_Table.keys(), + Forms_Table.keys(), + Magic_Table.keys(), + Summon_Table.keys(), + Movement_Table.keys(), + Keyblade_Table.keys(), + Staffs_Table.keys(), + Shields_Table.keys(), + [ ItemName.AerialRecovery, ItemName.ComboMaster, ItemName.ComboPlus, ItemName.AirComboPlus, - ItemName.ComboBoost, - ItemName.AirComboBoost, - ItemName.ReactionBoost, ItemName.FinishingPlus, ItemName.NegativeCombo, ItemName.BerserkCharge, - ItemName.DamageDrive, - ItemName.DriveBoost, ItemName.FormBoost, - ItemName.SummonBoost, - ItemName.ExperienceBoost, - ItemName.Draw, - ItemName.Jackpot, - ItemName.LuckyLucky, - ItemName.DriveConverter, - ItemName.FireBoost, - ItemName.BlizzardBoost, - ItemName.ThunderBoost, - ItemName.ItemBoost, - ItemName.MPRage, - ItemName.MPHaste, - ItemName.MPHastera, - ItemName.MPHastega, - ItemName.Defender, - ItemName.DamageControl, - ItemName.NoExperience, ItemName.LightDarkness, - ItemName.MagicLock, - ItemName.LeafBracer, - ItemName.CombinationBoost, ItemName.OnceMore, ItemName.SecondChance, ItemName.Guard, - ItemName.UpperSlash, ItemName.HorizontalSlash, ItemName.FinishingLeap, - ItemName.RetaliatingSlash, ItemName.Slapshot, - ItemName.DodgeSlash, ItemName.FlashStep, ItemName.SlideDash, - ItemName.VicinityBreak, ItemName.GuardBreak, ItemName.Explosion, ItemName.AerialSweep, ItemName.AerialDive, ItemName.AerialSpiral, ItemName.AerialFinish, - ItemName.MagnetBurst, - ItemName.Counterguard, ItemName.AutoValor, ItemName.AutoWisdom, ItemName.AutoLimit, ItemName.AutoMaster, ItemName.AutoFinal, - ItemName.AutoSummon, ItemName.TrinityLimit, - ItemName.HighJump, - ItemName.QuickRun, - ItemName.DodgeRoll, - ItemName.AerialDodge, - ItemName.Glide, - }, - "Donald": { - ItemName.DonaldFire, - ItemName.DonaldBlizzard, - ItemName.DonaldThunder, - ItemName.DonaldCure, - ItemName.Fantasia, + ItemName.DriveConverter, + # Party Limits ItemName.FlareForce, - ItemName.DonaldMPRage, - ItemName.DonaldJackpot, - ItemName.DonaldLuckyLucky, - ItemName.DonaldFireBoost, - ItemName.DonaldBlizzardBoost, - ItemName.DonaldThunderBoost, - ItemName.DonaldMPHaste, - ItemName.DonaldMPHastera, - ItemName.DonaldMPHastega, - ItemName.DonaldAutoLimit, - ItemName.DonaldHyperHealing, - ItemName.DonaldAutoHealing, - ItemName.DonaldItemBoost, - ItemName.DonaldDamageControl, - ItemName.DonaldDraw, - }, - "Goofy": { - ItemName.GoofyTornado, - ItemName.GoofyTurbo, - ItemName.GoofyBash, - ItemName.TornadoFusion, + ItemName.Fantasia, ItemName.Teamwork, - ItemName.GoofyDraw, - ItemName.GoofyJackpot, - ItemName.GoofyLuckyLucky, - ItemName.GoofyItemBoost, - ItemName.GoofyMPRage, - ItemName.GoofyDefender, - ItemName.GoofyDamageControl, - ItemName.GoofyAutoLimit, - ItemName.GoofySecondChance, - ItemName.GoofyOnceMore, - ItemName.GoofyAutoChange, - ItemName.GoofyHyperHealing, - ItemName.GoofyAutoHealing, - ItemName.GoofyMPHaste, - ItemName.GoofyMPHastera, - ItemName.GoofyMPHastega, - ItemName.GoofyProtect, - ItemName.GoofyProtera, - ItemName.GoofyProtega, - } - }, - "Boosts": { - ItemName.PowerBoost, - ItemName.MagicBoost, - ItemName.DefenseBoost, - ItemName.APBoost, - } + ItemName.TornadoFusion, + ItemName.HadesCupTrophy], + Events_Table] + for item_name in keys } +party_filler_set = { + ItemName.GoofyAutoHealing, + ItemName.GoofyMPHaste, + ItemName.GoofyMPHastera, + ItemName.GoofyMPHastega, + ItemName.GoofyProtect, + ItemName.GoofyProtera, + ItemName.GoofyProtega, + ItemName.GoofyMPRage, + ItemName.GoofyDefender, + ItemName.GoofyDamageControl, -Progression_Dicts = { - # Items that are classified as progression - "Progression": { - # Wincons - ItemName.Victory, - ItemName.LuckyEmblem, - ItemName.Bounty, - ItemName.ProofofConnection, - ItemName.ProofofNonexistence, - ItemName.ProofofPeace, - ItemName.PromiseCharm, - # visit locking - ItemName.NamineSketches, - # dummy 13 - ItemName.CastleKey, - ItemName.BattlefieldsofWar, - ItemName.SwordoftheAncestor, - ItemName.BeastsClaw, - ItemName.BoneFist, - ItemName.ProudFang, - ItemName.SkillandCrossbones, - ItemName.Scimitar, - ItemName.MembershipCard, - ItemName.IceCream, - ItemName.WaytotheDawn, - ItemName.IdentityDisk, - ItemName.TornPages, - # forms - ItemName.ValorForm, - ItemName.WisdomForm, - ItemName.LimitForm, - ItemName.MasterForm, - ItemName.FinalForm, - # magic - ItemName.FireElement, - ItemName.BlizzardElement, - ItemName.ThunderElement, - ItemName.CureElement, - ItemName.MagnetElement, - ItemName.ReflectElement, - ItemName.Genie, - ItemName.PeterPan, - ItemName.Stitch, - ItemName.ChickenLittle, - # movement - ItemName.HighJump, - ItemName.QuickRun, - ItemName.DodgeRoll, - ItemName.AerialDodge, - ItemName.Glide, - # abilities - ItemName.Scan, - ItemName.AerialRecovery, - ItemName.ComboMaster, - ItemName.ComboPlus, - ItemName.AirComboPlus, - ItemName.ComboBoost, - ItemName.AirComboBoost, - ItemName.ReactionBoost, - ItemName.FinishingPlus, - ItemName.NegativeCombo, - ItemName.BerserkCharge, - ItemName.DamageDrive, - ItemName.DriveBoost, - ItemName.FormBoost, - ItemName.SummonBoost, - ItemName.ExperienceBoost, - ItemName.Draw, - ItemName.Jackpot, - ItemName.LuckyLucky, - ItemName.DriveConverter, - ItemName.FireBoost, - ItemName.BlizzardBoost, - ItemName.ThunderBoost, - ItemName.ItemBoost, - ItemName.MPRage, - ItemName.MPHaste, - ItemName.MPHastera, - ItemName.MPHastega, - ItemName.Defender, - ItemName.DamageControl, - ItemName.NoExperience, - ItemName.LightDarkness, - ItemName.MagicLock, - ItemName.LeafBracer, - ItemName.CombinationBoost, - ItemName.OnceMore, - ItemName.SecondChance, - ItemName.Guard, - ItemName.UpperSlash, - ItemName.HorizontalSlash, - ItemName.FinishingLeap, - ItemName.RetaliatingSlash, - ItemName.Slapshot, - ItemName.DodgeSlash, - ItemName.FlashStep, - ItemName.SlideDash, - ItemName.VicinityBreak, - ItemName.GuardBreak, - ItemName.Explosion, - ItemName.AerialSweep, - ItemName.AerialDive, - ItemName.AerialSpiral, - ItemName.AerialFinish, - ItemName.MagnetBurst, - ItemName.Counterguard, - ItemName.AutoValor, - ItemName.AutoWisdom, - ItemName.AutoLimit, - ItemName.AutoMaster, - ItemName.AutoFinal, - ItemName.AutoSummon, - ItemName.TrinityLimit, - # keyblades - ItemName.Oathkeeper, - ItemName.Oblivion, - ItemName.StarSeeker, - ItemName.HiddenDragon, - ItemName.HerosCrest, - ItemName.Monochrome, - ItemName.FollowtheWind, - ItemName.CircleofLife, - ItemName.PhotonDebugger, - ItemName.GullWing, - ItemName.RumblingRose, - ItemName.GuardianSoul, - ItemName.WishingLamp, - ItemName.DecisivePumpkin, - ItemName.SleepingLion, - ItemName.SweetMemories, - ItemName.MysteriousAbyss, - ItemName.TwoBecomeOne, - ItemName.FatalCrest, - ItemName.BondofFlame, - ItemName.Fenrir, - ItemName.UltimaWeapon, - ItemName.WinnersProof, - ItemName.Pureblood, - # Staffs - ItemName.Centurion2, - ItemName.MeteorStaff, - ItemName.NobodyLance, - ItemName.PreciousMushroom, - ItemName.PreciousMushroom2, - ItemName.PremiumMushroom, - ItemName.RisingDragon, - ItemName.SaveTheQueen2, - ItemName.ShamansRelic, - # Shields - ItemName.AkashicRecord, - ItemName.FrozenPride2, - ItemName.GenjiShield, - ItemName.MajesticMushroom, - ItemName.MajesticMushroom2, - ItemName.NobodyGuard, - ItemName.OgreShield, - ItemName.SaveTheKing2, - ItemName.UltimateMushroom, - # Party Limits - ItemName.FlareForce, - ItemName.Fantasia, - ItemName.Teamwork, - ItemName.TornadoFusion - }, - "2VisitLocking": { + ItemName.DonaldFireBoost, + ItemName.DonaldBlizzardBoost, + ItemName.DonaldThunderBoost, + ItemName.DonaldMPHaste, + ItemName.DonaldMPHastera, + ItemName.DonaldMPHastega, + ItemName.DonaldAutoHealing, + ItemName.DonaldDamageControl, + ItemName.DonaldDraw, + ItemName.DonaldMPRage, +} +useful_set = {item_name for keys in [ + SupportAbility_Table.keys(), + ActionAbility_Table.keys(), + DonaldAbility_Table.keys(), + GoofyAbility_Table.keys(), + Armor_Table.keys(), + Usefull_Table.keys(), + Accessory_Table.keys()] + for item_name in keys if item_name not in progression_set and item_name not in party_filler_set} + +visit_locking_dict = { + "2VisitLocking": [ ItemName.CastleKey, ItemName.BattlefieldsofWar, ItemName.SwordoftheAncestor, @@ -854,7 +596,7 @@ class ItemData(typing.NamedTuple): ItemName.IdentityDisk, ItemName.IceCream, ItemName.NamineSketches - }, + ], "AllVisitLocking": { ItemName.CastleKey: 2, ItemName.BattlefieldsofWar: 2, @@ -865,84 +607,13 @@ class ItemData(typing.NamedTuple): ItemName.SkillandCrossbones: 2, ItemName.Scimitar: 2, ItemName.MembershipCard: 2, - ItemName.WaytotheDawn: 1, + ItemName.WaytotheDawn: 2, ItemName.IdentityDisk: 2, ItemName.IceCream: 3, ItemName.NamineSketches: 1, } } - -exclusionItem_table = { - "Ability": { - ItemName.Scan, - ItemName.AerialRecovery, - ItemName.ComboMaster, - ItemName.ComboPlus, - ItemName.AirComboPlus, - ItemName.ComboBoost, - ItemName.AirComboBoost, - ItemName.ReactionBoost, - ItemName.FinishingPlus, - ItemName.NegativeCombo, - ItemName.BerserkCharge, - ItemName.DamageDrive, - ItemName.DriveBoost, - ItemName.FormBoost, - ItemName.SummonBoost, - ItemName.ExperienceBoost, - ItemName.Draw, - ItemName.Jackpot, - ItemName.LuckyLucky, - ItemName.DriveConverter, - ItemName.FireBoost, - ItemName.BlizzardBoost, - ItemName.ThunderBoost, - ItemName.ItemBoost, - ItemName.MPRage, - ItemName.MPHaste, - ItemName.MPHastera, - ItemName.MPHastega, - ItemName.Defender, - ItemName.DamageControl, - ItemName.NoExperience, - ItemName.LightDarkness, - ItemName.MagicLock, - ItemName.LeafBracer, - ItemName.CombinationBoost, - ItemName.DamageDrive, - ItemName.OnceMore, - ItemName.SecondChance, - ItemName.Guard, - ItemName.UpperSlash, - ItemName.HorizontalSlash, - ItemName.FinishingLeap, - ItemName.RetaliatingSlash, - ItemName.Slapshot, - ItemName.DodgeSlash, - ItemName.FlashStep, - ItemName.SlideDash, - ItemName.VicinityBreak, - ItemName.GuardBreak, - ItemName.Explosion, - ItemName.AerialSweep, - ItemName.AerialDive, - ItemName.AerialSpiral, - ItemName.AerialFinish, - ItemName.MagnetBurst, - ItemName.Counterguard, - ItemName.AutoValor, - ItemName.AutoWisdom, - ItemName.AutoLimit, - ItemName.AutoMaster, - ItemName.AutoFinal, - ItemName.AutoSummon, - ItemName.TrinityLimit, - ItemName.HighJump, - ItemName.QuickRun, - ItemName.DodgeRoll, - ItemName.AerialDodge, - ItemName.Glide, - }, +exclusion_item_table = { "StatUps": { ItemName.MaxHPUp, ItemName.MaxMPUp, @@ -951,59 +622,64 @@ class ItemData(typing.NamedTuple): ItemName.AccessorySlotUp, ItemName.ItemSlotUp, }, + "Ability": { + item_name for keys in [SupportAbility_Table.keys(), ActionAbility_Table.keys(), Movement_Table.keys()] for item_name in keys + } } -item_dictionary_table = {**Reports_Table, - **Progression_Table, - **Forms_Table, - **Magic_Table, - **Armor_Table, - **Movement_Table, - **Staffs_Table, - **Shields_Table, - **Keyblade_Table, - **Accessory_Table, - **Usefull_Table, - **SupportAbility_Table, - **ActionAbility_Table, - **Items_Table, - **Misc_Table, - **Items_Table, - **DonaldAbility_Table, - **GoofyAbility_Table, - } - -lookup_id_to_name: typing.Dict[int, str] = {data.code: item_name for item_name, data in item_dictionary_table.items() if - data.code} - -item_groups: typing.Dict[str, list] = {"Drive Form": [item_name for item_name in Forms_Table.keys()], - "Growth": [item_name for item_name in Movement_Table.keys()], - "Donald Limit": [ItemName.FlareForce, ItemName.Fantasia], - "Goofy Limit": [ItemName.Teamwork, ItemName.TornadoFusion], - "Magic": [ItemName.FireElement, ItemName.BlizzardElement, - ItemName.ThunderElement, - ItemName.CureElement, ItemName.MagnetElement, - ItemName.ReflectElement], - "Summon": [ItemName.ChickenLittle, ItemName.Genie, ItemName.Stitch, - ItemName.PeterPan], - "Gap Closer": [ItemName.SlideDash, ItemName.FlashStep], - "Ground Finisher": [ItemName.GuardBreak, ItemName.Explosion, - ItemName.FinishingLeap], - "Visit Lock": [item_name for item_name in - Progression_Dicts["2VisitLocking"]], - "Keyblade": [item_name for item_name in Keyblade_Table.keys()], - "Fire": [ItemName.FireElement], - "Blizzard": [ItemName.BlizzardElement], - "Thunder": [ItemName.ThunderElement], - "Cure": [ItemName.CureElement], - "Magnet": [ItemName.MagnetElement], - "Reflect": [ItemName.ReflectElement], - "Proof": [ItemName.ProofofNonexistence, ItemName.ProofofPeace, - ItemName.ProofofConnection], - "Filler": [ - ItemName.PowerBoost, ItemName.MagicBoost, - ItemName.DefenseBoost, ItemName.APBoost] - } - -# lookup_kh2id_to_name: typing.Dict[int, str] = {data.kh2id: item_name for item_name, data in -# item_dictionary_table.items() if data.kh2id} +default_itempool_option = { + item_name: ItemData.quantity for dic in [Magic_Table, Progression_Table, Summon_Table, Movement_Table, Forms_Table] for item_name, ItemData in dic.items() +} +item_dictionary_table = { + **Reports_Table, + **Progression_Table, + **Forms_Table, + **Magic_Table, + **Summon_Table, + **Armor_Table, + **Movement_Table, + **Staffs_Table, + **Shields_Table, + **Keyblade_Table, + **Accessory_Table, + **Usefull_Table, + **SupportAbility_Table, + **ActionAbility_Table, + **Boosts_Table, + **Wincon_Table, + **Boosts_Table, + **DonaldAbility_Table, + **GoofyAbility_Table, + **Consumable_Table +} +filler_items = [ItemName.PowerBoost, ItemName.MagicBoost, ItemName.DefenseBoost, ItemName.APBoost, + ItemName.Potion, ItemName.HiPotion, ItemName.Ether, ItemName.Elixir, ItemName.Megalixir, + ItemName.Tent, ItemName.DriveRecovery, ItemName.HighDriveRecovery, + ] +item_groups: typing.Dict[str, list] = { + "Drive Form": [item_name for item_name in Forms_Table.keys()], + "Growth": [item_name for item_name in Movement_Table.keys()], + "Donald Limit": [ItemName.FlareForce, ItemName.Fantasia], + "Goofy Limit": [ItemName.Teamwork, ItemName.TornadoFusion], + "Magic": [ItemName.FireElement, ItemName.BlizzardElement, + ItemName.ThunderElement, + ItemName.CureElement, ItemName.MagnetElement, + ItemName.ReflectElement], + "Summon": [ItemName.ChickenLittle, ItemName.Genie, ItemName.Stitch, + ItemName.PeterPan], + "Gap Closer": [ItemName.SlideDash, ItemName.FlashStep], + "Ground Finisher": [ItemName.GuardBreak, ItemName.Explosion, + ItemName.FinishingLeap], + "Visit Lock": [item_name for item_name in + visit_locking_dict["2VisitLocking"]], + "Keyblade": [item_name for item_name in Keyblade_Table.keys()], + "Fire": [ItemName.FireElement], + "Blizzard": [ItemName.BlizzardElement], + "Thunder": [ItemName.ThunderElement], + "Cure": [ItemName.CureElement], + "Magnet": [ItemName.MagnetElement], + "Reflect": [ItemName.ReflectElement], + "Proof": [ItemName.ProofofNonexistence, ItemName.ProofofPeace, + ItemName.ProofofConnection], + "hitlist": [ItemName.Bounty], +} diff --git a/worlds/kh2/Locations.py b/worlds/kh2/Locations.py index 9046dfc67be5..9d7d948443cd 100644 --- a/worlds/kh2/Locations.py +++ b/worlds/kh2/Locations.py @@ -1,7 +1,7 @@ import typing from BaseClasses import Location -from .Names import LocationName, RegionName, ItemName +from .Names import LocationName, ItemName class KH2Location(Location): @@ -9,7 +9,6 @@ class KH2Location(Location): class LocationData(typing.NamedTuple): - code: typing.Optional[int] locid: int yml: str charName: str = "Sora" @@ -18,950 +17,1072 @@ class LocationData(typing.NamedTuple): # data's addrcheck sys3 addr obtained roomid bit index is eventid LoD_Checks = { - LocationName.BambooGroveDarkShard: LocationData(0x130000, 245, "Chest"), - LocationName.BambooGroveEther: LocationData(0x130001, 497, "Chest"), - LocationName.BambooGroveMythrilShard: LocationData(0x130002, 498, "Chest"), - LocationName.EncampmentAreaMap: LocationData(0x130003, 350, "Chest"), - LocationName.Mission3: LocationData(0x130004, 417, "Chest"), - LocationName.CheckpointHiPotion: LocationData(0x130005, 21, "Chest"), - LocationName.CheckpointMythrilShard: LocationData(0x130006, 121, "Chest"), - LocationName.MountainTrailLightningShard: LocationData(0x130007, 22, "Chest"), - LocationName.MountainTrailRecoveryRecipe: LocationData(0x130008, 23, "Chest"), - LocationName.MountainTrailEther: LocationData(0x130009, 122, "Chest"), - LocationName.MountainTrailMythrilShard: LocationData(0x13000A, 123, "Chest"), - LocationName.VillageCaveAreaMap: LocationData(0x13000B, 495, "Chest"), - LocationName.VillageCaveDarkShard: LocationData(0x13000C, 125, "Chest"), - LocationName.VillageCaveAPBoost: LocationData(0x13000D, 124, "Chest"), - LocationName.VillageCaveBonus: LocationData(0x13000E, 43, "Get Bonus"), - LocationName.RidgeFrostShard: LocationData(0x13000F, 24, "Chest"), - LocationName.RidgeAPBoost: LocationData(0x130010, 126, "Chest"), - LocationName.ShanYu: LocationData(0x130011, 9, "Double Get Bonus"), - LocationName.ShanYuGetBonus: LocationData(0x130012, 9, "Second Get Bonus"), - LocationName.HiddenDragon: LocationData(0x130013, 257, "Chest"), - -} -LoD2_Checks = { - LocationName.ThroneRoomTornPages: LocationData(0x130014, 25, "Chest"), - LocationName.ThroneRoomPalaceMap: LocationData(0x130015, 127, "Chest"), - LocationName.ThroneRoomAPBoost: LocationData(0x130016, 26, "Chest"), - LocationName.ThroneRoomQueenRecipe: LocationData(0x130017, 27, "Chest"), - LocationName.ThroneRoomAPBoost2: LocationData(0x130018, 128, "Chest"), - LocationName.ThroneRoomOgreShield: LocationData(0x130019, 129, "Chest"), - LocationName.ThroneRoomMythrilCrystal: LocationData(0x13001A, 130, "Chest"), - LocationName.ThroneRoomOrichalcum: LocationData(0x13001B, 131, "Chest"), - LocationName.StormRider: LocationData(0x13001C, 10, "Get Bonus"), - LocationName.XigbarDataDefenseBoost: LocationData(0x13001D, 555, "Chest"), + LocationName.BambooGroveDarkShard: LocationData(245, "Chest"), + LocationName.BambooGroveEther: LocationData(497, "Chest"), + LocationName.BambooGroveMythrilShard: LocationData(498, "Chest"), + LocationName.EncampmentAreaMap: LocationData(350, "Chest"), + LocationName.Mission3: LocationData(417, "Chest"), + LocationName.CheckpointHiPotion: LocationData(21, "Chest"), + LocationName.CheckpointMythrilShard: LocationData(121, "Chest"), + LocationName.MountainTrailLightningShard: LocationData(22, "Chest"), + LocationName.MountainTrailRecoveryRecipe: LocationData(23, "Chest"), + LocationName.MountainTrailEther: LocationData(122, "Chest"), + LocationName.MountainTrailMythrilShard: LocationData(123, "Chest"), + LocationName.VillageCaveAreaMap: LocationData(495, "Chest"), + LocationName.VillageCaveDarkShard: LocationData(125, "Chest"), + LocationName.VillageCaveAPBoost: LocationData(124, "Chest"), + LocationName.VillageCaveBonus: LocationData(43, "Get Bonus"), + LocationName.RidgeFrostShard: LocationData(24, "Chest"), + LocationName.RidgeAPBoost: LocationData(126, "Chest"), + LocationName.ShanYu: LocationData(9, "Double Get Bonus"), + LocationName.ShanYuGetBonus: LocationData(9, "Second Get Bonus"), + LocationName.HiddenDragon: LocationData(257, "Chest"), + LocationName.ThroneRoomTornPages: LocationData(25, "Chest"), + LocationName.ThroneRoomPalaceMap: LocationData(127, "Chest"), + LocationName.ThroneRoomAPBoost: LocationData(26, "Chest"), + LocationName.ThroneRoomQueenRecipe: LocationData(27, "Chest"), + LocationName.ThroneRoomAPBoost2: LocationData(128, "Chest"), + LocationName.ThroneRoomOgreShield: LocationData(129, "Chest"), + LocationName.ThroneRoomMythrilCrystal: LocationData(130, "Chest"), + LocationName.ThroneRoomOrichalcum: LocationData(131, "Chest"), + LocationName.StormRider: LocationData(10, "Get Bonus"), + LocationName.XigbarDataDefenseBoost: LocationData(555, "Chest"), } AG_Checks = { - LocationName.AgrabahMap: LocationData(0x13001E, 353, "Chest"), - LocationName.AgrabahDarkShard: LocationData(0x13001F, 28, "Chest"), - LocationName.AgrabahMythrilShard: LocationData(0x130020, 29, "Chest"), - LocationName.AgrabahHiPotion: LocationData(0x130021, 30, "Chest"), - LocationName.AgrabahAPBoost: LocationData(0x130022, 132, "Chest"), - LocationName.AgrabahMythrilStone: LocationData(0x130023, 133, "Chest"), - LocationName.AgrabahMythrilShard2: LocationData(0x130024, 249, "Chest"), - LocationName.AgrabahSerenityShard: LocationData(0x130025, 501, "Chest"), - LocationName.BazaarMythrilGem: LocationData(0x130026, 31, "Chest"), - LocationName.BazaarPowerShard: LocationData(0x130027, 32, "Chest"), - LocationName.BazaarHiPotion: LocationData(0x130028, 33, "Chest"), - LocationName.BazaarAPBoost: LocationData(0x130029, 134, "Chest"), - LocationName.BazaarMythrilShard: LocationData(0x13002A, 135, "Chest"), - LocationName.PalaceWallsSkillRing: LocationData(0x13002B, 136, "Chest"), - LocationName.PalaceWallsMythrilStone: LocationData(0x13002C, 520, "Chest"), - LocationName.CaveEntrancePowerStone: LocationData(0x13002D, 250, "Chest"), - LocationName.CaveEntranceMythrilShard: LocationData(0x13002E, 251, "Chest"), - LocationName.ValleyofStoneMythrilStone: LocationData(0x13002F, 35, "Chest"), - LocationName.ValleyofStoneAPBoost: LocationData(0x130030, 36, "Chest"), - LocationName.ValleyofStoneMythrilShard: LocationData(0x130031, 137, "Chest"), - LocationName.ValleyofStoneHiPotion: LocationData(0x130032, 138, "Chest"), - LocationName.AbuEscort: LocationData(0x130033, 42, "Get Bonus"), - LocationName.ChasmofChallengesCaveofWondersMap: LocationData(0x130034, 487, "Chest"), - LocationName.ChasmofChallengesAPBoost: LocationData(0x130035, 37, "Chest"), - LocationName.TreasureRoom: LocationData(0x130036, 46, "Get Bonus"), - LocationName.TreasureRoomAPBoost: LocationData(0x130037, 502, "Chest"), - LocationName.TreasureRoomSerenityGem: LocationData(0x130038, 503, "Chest"), - LocationName.ElementalLords: LocationData(0x130039, 37, "Get Bonus"), - LocationName.LampCharm: LocationData(0x13003A, 300, "Chest"), - -} -AG2_Checks = { - LocationName.RuinedChamberTornPages: LocationData(0x13003B, 34, "Chest"), - LocationName.RuinedChamberRuinsMap: LocationData(0x13003C, 486, "Chest"), - LocationName.GenieJafar: LocationData(0x13003D, 15, "Get Bonus"), - LocationName.WishingLamp: LocationData(0x13003E, 303, "Chest"), - LocationName.LexaeusBonus: LocationData(0x13003F, 65, "Get Bonus"), - LocationName.LexaeusASStrengthBeyondStrength: LocationData(0x130040, 545, "Chest"), - LocationName.LexaeusDataLostIllusion: LocationData(0x130041, 550, "Chest"), + LocationName.AgrabahMap: LocationData(353, "Chest"), + LocationName.AgrabahDarkShard: LocationData(28, "Chest"), + LocationName.AgrabahMythrilShard: LocationData(29, "Chest"), + LocationName.AgrabahHiPotion: LocationData(30, "Chest"), + LocationName.AgrabahAPBoost: LocationData(132, "Chest"), + LocationName.AgrabahMythrilStone: LocationData(133, "Chest"), + LocationName.AgrabahMythrilShard2: LocationData(249, "Chest"), + LocationName.AgrabahSerenityShard: LocationData(501, "Chest"), + LocationName.BazaarMythrilGem: LocationData(31, "Chest"), + LocationName.BazaarPowerShard: LocationData(32, "Chest"), + LocationName.BazaarHiPotion: LocationData(33, "Chest"), + LocationName.BazaarAPBoost: LocationData(134, "Chest"), + LocationName.BazaarMythrilShard: LocationData(135, "Chest"), + LocationName.PalaceWallsSkillRing: LocationData(136, "Chest"), + LocationName.PalaceWallsMythrilStone: LocationData(520, "Chest"), + LocationName.CaveEntrancePowerStone: LocationData(250, "Chest"), + LocationName.CaveEntranceMythrilShard: LocationData(251, "Chest"), + LocationName.ValleyofStoneMythrilStone: LocationData(35, "Chest"), + LocationName.ValleyofStoneAPBoost: LocationData(36, "Chest"), + LocationName.ValleyofStoneMythrilShard: LocationData(137, "Chest"), + LocationName.ValleyofStoneHiPotion: LocationData(138, "Chest"), + LocationName.AbuEscort: LocationData(42, "Get Bonus"), + LocationName.ChasmofChallengesCaveofWondersMap: LocationData(487, "Chest"), + LocationName.ChasmofChallengesAPBoost: LocationData(37, "Chest"), + LocationName.TreasureRoom: LocationData(46, "Get Bonus"), + LocationName.TreasureRoomAPBoost: LocationData(502, "Chest"), + LocationName.TreasureRoomSerenityGem: LocationData(503, "Chest"), + LocationName.ElementalLords: LocationData(37, "Get Bonus"), + LocationName.LampCharm: LocationData(300, "Chest"), + LocationName.RuinedChamberTornPages: LocationData(34, "Chest"), + LocationName.RuinedChamberRuinsMap: LocationData(486, "Chest"), + LocationName.GenieJafar: LocationData(15, "Get Bonus"), + LocationName.WishingLamp: LocationData(303, "Chest"), + LocationName.LexaeusBonus: LocationData(65, "Get Bonus"), + LocationName.LexaeusASStrengthBeyondStrength: LocationData(545, "Chest"), + LocationName.LexaeusDataLostIllusion: LocationData(550, "Chest"), } DC_Checks = { - LocationName.DCCourtyardMythrilShard: LocationData(0x130042, 16, "Chest"), - LocationName.DCCourtyardStarRecipe: LocationData(0x130043, 17, "Chest"), - LocationName.DCCourtyardAPBoost: LocationData(0x130044, 18, "Chest"), - LocationName.DCCourtyardMythrilStone: LocationData(0x130045, 92, "Chest"), - LocationName.DCCourtyardBlazingStone: LocationData(0x130046, 93, "Chest"), - LocationName.DCCourtyardBlazingShard: LocationData(0x130047, 247, "Chest"), - LocationName.DCCourtyardMythrilShard2: LocationData(0x130048, 248, "Chest"), - LocationName.LibraryTornPages: LocationData(0x130049, 91, "Chest"), - LocationName.DisneyCastleMap: LocationData(0x13004A, 332, "Chest"), - LocationName.MinnieEscort: LocationData(0x13004B, 38, "Double Get Bonus"), - LocationName.MinnieEscortGetBonus: LocationData(0x13004C, 38, "Second Get Bonus"), + LocationName.DCCourtyardMythrilShard: LocationData(16, "Chest"), + LocationName.DCCourtyardStarRecipe: LocationData(17, "Chest"), + LocationName.DCCourtyardAPBoost: LocationData(18, "Chest"), + LocationName.DCCourtyardMythrilStone: LocationData(92, "Chest"), + LocationName.DCCourtyardBlazingStone: LocationData(93, "Chest"), + LocationName.DCCourtyardBlazingShard: LocationData(247, "Chest"), + LocationName.DCCourtyardMythrilShard2: LocationData(248, "Chest"), + LocationName.LibraryTornPages: LocationData(91, "Chest"), + LocationName.DisneyCastleMap: LocationData(332, "Chest"), + LocationName.MinnieEscort: LocationData(38, "Double Get Bonus"), + LocationName.MinnieEscortGetBonus: LocationData(38, "Second Get Bonus"), + LocationName.CornerstoneHillMap: LocationData(79, "Chest"), + LocationName.CornerstoneHillFrostShard: LocationData(12, "Chest"), + LocationName.PierMythrilShard: LocationData(81, "Chest"), + LocationName.PierHiPotion: LocationData(82, "Chest"), + LocationName.WaterwayMythrilStone: LocationData(83, "Chest"), + LocationName.WaterwayAPBoost: LocationData(84, "Chest"), + LocationName.WaterwayFrostStone: LocationData(85, "Chest"), + LocationName.WindowofTimeMap: LocationData(368, "Chest"), + LocationName.BoatPete: LocationData(16, "Get Bonus"), + LocationName.FuturePete: LocationData(17, "Double Get Bonus"), + LocationName.FuturePeteGetBonus: LocationData(17, "Second Get Bonus"), + LocationName.Monochrome: LocationData(261, "Chest"), + LocationName.WisdomForm: LocationData(262, "Chest"), + LocationName.MarluxiaGetBonus: LocationData(67, "Get Bonus"), + LocationName.MarluxiaASEternalBlossom: LocationData(548, "Chest"), + LocationName.MarluxiaDataLostIllusion: LocationData(553, "Chest"), + LocationName.LingeringWillBonus: LocationData(70, "Get Bonus"), + LocationName.LingeringWillProofofConnection: LocationData(587, "Chest"), + LocationName.LingeringWillManifestIllusion: LocationData(591, "Chest"), } -TR_Checks = { - LocationName.CornerstoneHillMap: LocationData(0x13004D, 79, "Chest"), - LocationName.CornerstoneHillFrostShard: LocationData(0x13004E, 12, "Chest"), - LocationName.PierMythrilShard: LocationData(0x13004F, 81, "Chest"), - LocationName.PierHiPotion: LocationData(0x130050, 82, "Chest"), - LocationName.WaterwayMythrilStone: LocationData(0x130051, 83, "Chest"), - LocationName.WaterwayAPBoost: LocationData(0x130052, 84, "Chest"), - LocationName.WaterwayFrostStone: LocationData(0x130053, 85, "Chest"), - LocationName.WindowofTimeMap: LocationData(0x130054, 368, "Chest"), - LocationName.BoatPete: LocationData(0x130055, 16, "Get Bonus"), - LocationName.FuturePete: LocationData(0x130056, 17, "Double Get Bonus"), - LocationName.FuturePeteGetBonus: LocationData(0x130057, 17, "Second Get Bonus"), - LocationName.Monochrome: LocationData(0x130058, 261, "Chest"), - LocationName.WisdomForm: LocationData(0x130059, 262, "Chest"), - LocationName.MarluxiaGetBonus: LocationData(0x13005A, 67, "Get Bonus"), - LocationName.MarluxiaASEternalBlossom: LocationData(0x13005B, 548, "Chest"), - LocationName.MarluxiaDataLostIllusion: LocationData(0x13005C, 553, "Chest"), - LocationName.LingeringWillBonus: LocationData(0x13005D, 70, "Get Bonus"), - LocationName.LingeringWillProofofConnection: LocationData(0x13005E, 587, "Chest"), - LocationName.LingeringWillManifestIllusion: LocationData(0x13005F, 591, "Chest"), -} -# the mismatch might be here -HundredAcre1_Checks = { - LocationName.PoohsHouse100AcreWoodMap: LocationData(0x130060, 313, "Chest"), - LocationName.PoohsHouseAPBoost: LocationData(0x130061, 97, "Chest"), - LocationName.PoohsHouseMythrilStone: LocationData(0x130062, 98, "Chest"), -} -HundredAcre2_Checks = { - LocationName.PigletsHouseDefenseBoost: LocationData(0x130063, 105, "Chest"), - LocationName.PigletsHouseAPBoost: LocationData(0x130064, 103, "Chest"), - LocationName.PigletsHouseMythrilGem: LocationData(0x130065, 104, "Chest"), -} -HundredAcre3_Checks = { - LocationName.RabbitsHouseDrawRing: LocationData(0x130066, 314, "Chest"), - LocationName.RabbitsHouseMythrilCrystal: LocationData(0x130067, 100, "Chest"), - LocationName.RabbitsHouseAPBoost: LocationData(0x130068, 101, "Chest"), -} -HundredAcre4_Checks = { - LocationName.KangasHouseMagicBoost: LocationData(0x130069, 108, "Chest"), - LocationName.KangasHouseAPBoost: LocationData(0x13006A, 106, "Chest"), - LocationName.KangasHouseOrichalcum: LocationData(0x13006B, 107, "Chest"), -} -HundredAcre5_Checks = { - LocationName.SpookyCaveMythrilGem: LocationData(0x13006C, 110, "Chest"), - LocationName.SpookyCaveAPBoost: LocationData(0x13006D, 111, "Chest"), - LocationName.SpookyCaveOrichalcum: LocationData(0x13006E, 112, "Chest"), - LocationName.SpookyCaveGuardRecipe: LocationData(0x13006F, 113, "Chest"), - LocationName.SpookyCaveMythrilCrystal: LocationData(0x130070, 115, "Chest"), - LocationName.SpookyCaveAPBoost2: LocationData(0x130071, 116, "Chest"), - LocationName.SweetMemories: LocationData(0x130072, 284, "Chest"), - LocationName.SpookyCaveMap: LocationData(0x130073, 485, "Chest"), -} -HundredAcre6_Checks = { - LocationName.StarryHillCosmicRing: LocationData(0x130074, 312, "Chest"), - LocationName.StarryHillStyleRecipe: LocationData(0x130075, 94, "Chest"), - LocationName.StarryHillCureElement: LocationData(0x130076, 285, "Chest"), - LocationName.StarryHillOrichalcumPlus: LocationData(0x130077, 539, "Chest"), +HundredAcre_Checks = { + LocationName.PoohsHouse100AcreWoodMap: LocationData(313, "Chest"), + LocationName.PoohsHouseAPBoost: LocationData(97, "Chest"), + LocationName.PoohsHouseMythrilStone: LocationData(98, "Chest"), + LocationName.PigletsHouseDefenseBoost: LocationData(105, "Chest"), + LocationName.PigletsHouseAPBoost: LocationData(103, "Chest"), + LocationName.PigletsHouseMythrilGem: LocationData(104, "Chest"), + LocationName.RabbitsHouseDrawRing: LocationData(314, "Chest"), + LocationName.RabbitsHouseMythrilCrystal: LocationData(100, "Chest"), + LocationName.RabbitsHouseAPBoost: LocationData(101, "Chest"), + LocationName.KangasHouseMagicBoost: LocationData(108, "Chest"), + LocationName.KangasHouseAPBoost: LocationData(106, "Chest"), + LocationName.KangasHouseOrichalcum: LocationData(107, "Chest"), + LocationName.SpookyCaveMythrilGem: LocationData(110, "Chest"), + LocationName.SpookyCaveAPBoost: LocationData(111, "Chest"), + LocationName.SpookyCaveOrichalcum: LocationData(112, "Chest"), + LocationName.SpookyCaveGuardRecipe: LocationData(113, "Chest"), + LocationName.SpookyCaveMythrilCrystal: LocationData(115, "Chest"), + LocationName.SpookyCaveAPBoost2: LocationData(116, "Chest"), + LocationName.SweetMemories: LocationData(284, "Chest"), + LocationName.SpookyCaveMap: LocationData(485, "Chest"), + LocationName.StarryHillCosmicRing: LocationData(312, "Chest"), + LocationName.StarryHillStyleRecipe: LocationData(94, "Chest"), + LocationName.StarryHillCureElement: LocationData(285, "Chest"), + LocationName.StarryHillOrichalcumPlus: LocationData(539, "Chest"), } Oc_Checks = { - LocationName.PassageMythrilShard: LocationData(0x130078, 7, "Chest"), - LocationName.PassageMythrilStone: LocationData(0x130079, 8, "Chest"), - LocationName.PassageEther: LocationData(0x13007A, 144, "Chest"), - LocationName.PassageAPBoost: LocationData(0x13007B, 145, "Chest"), - LocationName.PassageHiPotion: LocationData(0x13007C, 146, "Chest"), - LocationName.InnerChamberUnderworldMap: LocationData(0x13007D, 2, "Chest"), - LocationName.InnerChamberMythrilShard: LocationData(0x13007E, 243, "Chest"), - LocationName.Cerberus: LocationData(0x13007F, 5, "Get Bonus"), - LocationName.ColiseumMap: LocationData(0x130080, 338, "Chest"), - LocationName.Urns: LocationData(0x130081, 57, "Get Bonus"), - LocationName.UnderworldEntrancePowerBoost: LocationData(0x130082, 242, "Chest"), - LocationName.CavernsEntranceLucidShard: LocationData(0x130083, 3, "Chest"), - LocationName.CavernsEntranceAPBoost: LocationData(0x130084, 11, "Chest"), - LocationName.CavernsEntranceMythrilShard: LocationData(0x130085, 504, "Chest"), - LocationName.TheLostRoadBrightShard: LocationData(0x130086, 9, "Chest"), - LocationName.TheLostRoadEther: LocationData(0x130087, 10, "Chest"), - LocationName.TheLostRoadMythrilShard: LocationData(0x130088, 148, "Chest"), - LocationName.TheLostRoadMythrilStone: LocationData(0x130089, 149, "Chest"), - LocationName.AtriumLucidStone: LocationData(0x13008A, 150, "Chest"), - LocationName.AtriumAPBoost: LocationData(0x13008B, 151, "Chest"), - LocationName.DemyxOC: LocationData(0x13008C, 58, "Get Bonus"), - LocationName.SecretAnsemReport5: LocationData(0x13008D, 529, "Chest"), - LocationName.OlympusStone: LocationData(0x13008E, 293, "Chest"), - LocationName.TheLockCavernsMap: LocationData(0x13008F, 244, "Chest"), - LocationName.TheLockMythrilShard: LocationData(0x130090, 5, "Chest"), - LocationName.TheLockAPBoost: LocationData(0x130091, 142, "Chest"), - LocationName.PeteOC: LocationData(0x130092, 6, "Get Bonus"), - LocationName.Hydra: LocationData(0x130093, 7, "Double Get Bonus"), - LocationName.HydraGetBonus: LocationData(0x130094, 7, "Second Get Bonus"), - LocationName.HerosCrest: LocationData(0x130095, 260, "Chest"), - -} -Oc2_Checks = { - LocationName.AuronsStatue: LocationData(0x130096, 295, "Chest"), - LocationName.Hades: LocationData(0x130097, 8, "Double Get Bonus"), - LocationName.HadesGetBonus: LocationData(0x130098, 8, "Second Get Bonus"), - LocationName.GuardianSoul: LocationData(0x130099, 272, "Chest"), - LocationName.ZexionBonus: LocationData(0x13009A, 66, "Get Bonus"), - LocationName.ZexionASBookofShadows: LocationData(0x13009B, 546, "Chest"), - LocationName.ZexionDataLostIllusion: LocationData(0x13009C, 551, "Chest"), -} -Oc2Cups = { - LocationName.ProtectBeltPainandPanicCup: LocationData(0x13009D, 513, "Chest"), - LocationName.SerenityGemPainandPanicCup: LocationData(0x13009E, 540, "Chest"), - LocationName.RisingDragonCerberusCup: LocationData(0x13009F, 515, "Chest"), - LocationName.SerenityCrystalCerberusCup: LocationData(0x1300A0, 542, "Chest"), - LocationName.GenjiShieldTitanCup: LocationData(0x1300A1, 514, "Chest"), - LocationName.SkillfulRingTitanCup: LocationData(0x1300A2, 541, "Chest"), - LocationName.FatalCrestGoddessofFateCup: LocationData(0x1300A3, 516, "Chest"), - LocationName.OrichalcumPlusGoddessofFateCup: LocationData(0x1300A4, 517, "Chest"), - LocationName.HadesCupTrophyParadoxCups: LocationData(0x1300A5, 518, "Chest"), + LocationName.PassageMythrilShard: LocationData(7, "Chest"), + LocationName.PassageMythrilStone: LocationData(8, "Chest"), + LocationName.PassageEther: LocationData(144, "Chest"), + LocationName.PassageAPBoost: LocationData(145, "Chest"), + LocationName.PassageHiPotion: LocationData(146, "Chest"), + LocationName.InnerChamberUnderworldMap: LocationData(2, "Chest"), + LocationName.InnerChamberMythrilShard: LocationData(243, "Chest"), + LocationName.Cerberus: LocationData(5, "Get Bonus"), + LocationName.ColiseumMap: LocationData(338, "Chest"), + LocationName.Urns: LocationData(57, "Get Bonus"), + LocationName.UnderworldEntrancePowerBoost: LocationData(242, "Chest"), + LocationName.CavernsEntranceLucidShard: LocationData(3, "Chest"), + LocationName.CavernsEntranceAPBoost: LocationData(11, "Chest"), + LocationName.CavernsEntranceMythrilShard: LocationData(504, "Chest"), + LocationName.TheLostRoadBrightShard: LocationData(9, "Chest"), + LocationName.TheLostRoadEther: LocationData(10, "Chest"), + LocationName.TheLostRoadMythrilShard: LocationData(148, "Chest"), + LocationName.TheLostRoadMythrilStone: LocationData(149, "Chest"), + LocationName.AtriumLucidStone: LocationData(150, "Chest"), + LocationName.AtriumAPBoost: LocationData(151, "Chest"), + LocationName.DemyxOC: LocationData(58, "Get Bonus"), + LocationName.SecretAnsemReport5: LocationData(529, "Chest"), + LocationName.OlympusStone: LocationData(293, "Chest"), + LocationName.TheLockCavernsMap: LocationData(244, "Chest"), + LocationName.TheLockMythrilShard: LocationData(5, "Chest"), + LocationName.TheLockAPBoost: LocationData(142, "Chest"), + LocationName.PeteOC: LocationData(6, "Get Bonus"), + LocationName.Hydra: LocationData(7, "Double Get Bonus"), + LocationName.HydraGetBonus: LocationData(7, "Second Get Bonus"), + LocationName.HerosCrest: LocationData(260, "Chest"), + LocationName.AuronsStatue: LocationData(295, "Chest"), + LocationName.Hades: LocationData(8, "Double Get Bonus"), + LocationName.HadesGetBonus: LocationData(8, "Second Get Bonus"), + LocationName.GuardianSoul: LocationData(272, "Chest"), + LocationName.ZexionBonus: LocationData(66, "Get Bonus"), + LocationName.ZexionASBookofShadows: LocationData(546, "Chest"), + LocationName.ZexionDataLostIllusion: LocationData(551, "Chest"), + LocationName.ProtectBeltPainandPanicCup: LocationData(513, "Chest"), + LocationName.SerenityGemPainandPanicCup: LocationData(540, "Chest"), + LocationName.RisingDragonCerberusCup: LocationData(515, "Chest"), + LocationName.SerenityCrystalCerberusCup: LocationData(542, "Chest"), + LocationName.GenjiShieldTitanCup: LocationData(514, "Chest"), + LocationName.SkillfulRingTitanCup: LocationData(541, "Chest"), + LocationName.FatalCrestGoddessofFateCup: LocationData(516, "Chest"), + LocationName.OrichalcumPlusGoddessofFateCup: LocationData(517, "Chest"), + LocationName.HadesCupTrophyParadoxCups: LocationData(518, "Chest"), } BC_Checks = { - LocationName.BCCourtyardAPBoost: LocationData(0x1300A6, 39, "Chest"), - LocationName.BCCourtyardHiPotion: LocationData(0x1300A7, 40, "Chest"), - LocationName.BCCourtyardMythrilShard: LocationData(0x1300A8, 505, "Chest"), - LocationName.BellesRoomCastleMap: LocationData(0x1300A9, 46, "Chest"), - LocationName.BellesRoomMegaRecipe: LocationData(0x1300AA, 240, "Chest"), - LocationName.TheEastWingMythrilShard: LocationData(0x1300AB, 63, "Chest"), - LocationName.TheEastWingTent: LocationData(0x1300AC, 155, "Chest"), - LocationName.TheWestHallHiPotion: LocationData(0x1300AD, 41, "Chest"), - LocationName.TheWestHallPowerShard: LocationData(0x1300AE, 207, "Chest"), - LocationName.TheWestHallAPBoostPostDungeon: LocationData(0x1300AF, 158, "Chest"), - LocationName.TheWestHallBrightStone: LocationData(0x1300B0, 159, "Chest"), - LocationName.TheWestHallMythrilShard: LocationData(0x1300B1, 206, "Chest"), - LocationName.Thresholder: LocationData(0x1300B2, 2, "Get Bonus"), - LocationName.DungeonBasementMap: LocationData(0x1300B3, 239, "Chest"), - LocationName.DungeonAPBoost: LocationData(0x1300B4, 43, "Chest"), - LocationName.SecretPassageMythrilShard: LocationData(0x1300B5, 44, "Chest"), - LocationName.SecretPassageHiPotion: LocationData(0x1300B6, 168, "Chest"), - LocationName.SecretPassageLucidShard: LocationData(0x1300B7, 45, "Chest"), - LocationName.TheWestHallMythrilShard2: LocationData(0x1300B8, 208, "Chest"), - LocationName.TheWestWingMythrilShard: LocationData(0x1300B9, 42, "Chest"), - LocationName.TheWestWingTent: LocationData(0x1300BA, 164, "Chest"), - LocationName.Beast: LocationData(0x1300BB, 12, "Get Bonus"), - LocationName.TheBeastsRoomBlazingShard: LocationData(0x1300BC, 241, "Chest"), - LocationName.DarkThorn: LocationData(0x1300BD, 3, "Double Get Bonus"), - LocationName.DarkThornGetBonus: LocationData(0x1300BE, 3, "Second Get Bonus"), - LocationName.DarkThornCureElement: LocationData(0x1300BF, 299, "Chest"), - -} -BC2_Checks = { - LocationName.RumblingRose: LocationData(0x1300C0, 270, "Chest"), - LocationName.CastleWallsMap: LocationData(0x1300C1, 325, "Chest"), - LocationName.Xaldin: LocationData(0x1300C2, 4, "Double Get Bonus"), - LocationName.XaldinGetBonus: LocationData(0x1300C3, 4, "Second Get Bonus"), - LocationName.SecretAnsemReport4: LocationData(0x1300C4, 528, "Chest"), - LocationName.XaldinDataDefenseBoost: LocationData(0x1300C5, 559, "Chest"), + LocationName.BCCourtyardAPBoost: LocationData(39, "Chest"), + LocationName.BCCourtyardHiPotion: LocationData(40, "Chest"), + LocationName.BCCourtyardMythrilShard: LocationData(505, "Chest"), + LocationName.BellesRoomCastleMap: LocationData(46, "Chest"), + LocationName.BellesRoomMegaRecipe: LocationData(240, "Chest"), + LocationName.TheEastWingMythrilShard: LocationData(63, "Chest"), + LocationName.TheEastWingTent: LocationData(155, "Chest"), + LocationName.TheWestHallHiPotion: LocationData(41, "Chest"), + LocationName.TheWestHallPowerShard: LocationData(207, "Chest"), + LocationName.TheWestHallAPBoostPostDungeon: LocationData(158, "Chest"), + LocationName.TheWestHallBrightStone: LocationData(159, "Chest"), + LocationName.TheWestHallMythrilShard: LocationData(206, "Chest"), + LocationName.Thresholder: LocationData(2, "Get Bonus"), + LocationName.DungeonBasementMap: LocationData(239, "Chest"), + LocationName.DungeonAPBoost: LocationData(43, "Chest"), + LocationName.SecretPassageMythrilShard: LocationData(44, "Chest"), + LocationName.SecretPassageHiPotion: LocationData(168, "Chest"), + LocationName.SecretPassageLucidShard: LocationData(45, "Chest"), + LocationName.TheWestHallMythrilShard2: LocationData(208, "Chest"), + LocationName.TheWestWingMythrilShard: LocationData(42, "Chest"), + LocationName.TheWestWingTent: LocationData(164, "Chest"), + LocationName.Beast: LocationData(12, "Get Bonus"), + LocationName.TheBeastsRoomBlazingShard: LocationData(241, "Chest"), + LocationName.DarkThorn: LocationData(3, "Double Get Bonus"), + LocationName.DarkThornGetBonus: LocationData(3, "Second Get Bonus"), + LocationName.DarkThornCureElement: LocationData(299, "Chest"), + LocationName.RumblingRose: LocationData(270, "Chest"), + LocationName.CastleWallsMap: LocationData(325, "Chest"), + LocationName.Xaldin: LocationData(4, "Double Get Bonus"), + LocationName.XaldinGetBonus: LocationData(4, "Second Get Bonus"), + LocationName.SecretAnsemReport4: LocationData(528, "Chest"), + LocationName.XaldinDataDefenseBoost: LocationData(559, "Chest"), } SP_Checks = { - LocationName.PitCellAreaMap: LocationData(0x1300C6, 316, "Chest"), - LocationName.PitCellMythrilCrystal: LocationData(0x1300C7, 64, "Chest"), - LocationName.CanyonDarkCrystal: LocationData(0x1300C8, 65, "Chest"), - LocationName.CanyonMythrilStone: LocationData(0x1300C9, 171, "Chest"), - LocationName.CanyonMythrilGem: LocationData(0x1300CA, 253, "Chest"), - LocationName.CanyonFrostCrystal: LocationData(0x1300CB, 521, "Chest"), - LocationName.Screens: LocationData(0x1300CC, 45, "Get Bonus"), - LocationName.HallwayPowerCrystal: LocationData(0x1300CD, 49, "Chest"), - LocationName.HallwayAPBoost: LocationData(0x1300CE, 50, "Chest"), - LocationName.CommunicationsRoomIOTowerMap: LocationData(0x1300CF, 255, "Chest"), - LocationName.CommunicationsRoomGaiaBelt: LocationData(0x1300D0, 499, "Chest"), - LocationName.HostileProgram: LocationData(0x1300D1, 31, "Double Get Bonus"), - LocationName.HostileProgramGetBonus: LocationData(0x1300D2, 31, "Second Get Bonus"), - LocationName.PhotonDebugger: LocationData(0x1300D3, 267, "Chest"), - -} -SP2_Checks = { - LocationName.SolarSailer: LocationData(0x1300D4, 61, "Get Bonus"), - LocationName.CentralComputerCoreAPBoost: LocationData(0x1300D5, 177, "Chest"), - LocationName.CentralComputerCoreOrichalcumPlus: LocationData(0x1300D6, 178, "Chest"), - LocationName.CentralComputerCoreCosmicArts: LocationData(0x1300D7, 51, "Chest"), - LocationName.CentralComputerCoreMap: LocationData(0x1300D8, 488, "Chest"), - LocationName.MCP: LocationData(0x1300D9, 32, "Double Get Bonus"), - LocationName.MCPGetBonus: LocationData(0x1300DA, 32, "Second Get Bonus"), - LocationName.LarxeneBonus: LocationData(0x1300DB, 68, "Get Bonus"), - LocationName.LarxeneASCloakedThunder: LocationData(0x1300DC, 547, "Chest"), - LocationName.LarxeneDataLostIllusion: LocationData(0x1300DD, 552, "Chest"), + LocationName.PitCellAreaMap: LocationData(316, "Chest"), + LocationName.PitCellMythrilCrystal: LocationData(64, "Chest"), + LocationName.CanyonDarkCrystal: LocationData(65, "Chest"), + LocationName.CanyonMythrilStone: LocationData(171, "Chest"), + LocationName.CanyonMythrilGem: LocationData(253, "Chest"), + LocationName.CanyonFrostCrystal: LocationData(521, "Chest"), + LocationName.Screens: LocationData(45, "Get Bonus"), + LocationName.HallwayPowerCrystal: LocationData(49, "Chest"), + LocationName.HallwayAPBoost: LocationData(50, "Chest"), + LocationName.CommunicationsRoomIOTowerMap: LocationData(255, "Chest"), + LocationName.CommunicationsRoomGaiaBelt: LocationData(499, "Chest"), + LocationName.HostileProgram: LocationData(31, "Double Get Bonus"), + LocationName.HostileProgramGetBonus: LocationData(31, "Second Get Bonus"), + LocationName.PhotonDebugger: LocationData(267, "Chest"), + LocationName.SolarSailer: LocationData(61, "Get Bonus"), + LocationName.CentralComputerCoreAPBoost: LocationData(177, "Chest"), + LocationName.CentralComputerCoreOrichalcumPlus: LocationData(178, "Chest"), + LocationName.CentralComputerCoreCosmicArts: LocationData(51, "Chest"), + LocationName.CentralComputerCoreMap: LocationData(488, "Chest"), + LocationName.MCP: LocationData(32, "Double Get Bonus"), + LocationName.MCPGetBonus: LocationData(32, "Second Get Bonus"), + LocationName.LarxeneBonus: LocationData(68, "Get Bonus"), + LocationName.LarxeneASCloakedThunder: LocationData(547, "Chest"), + LocationName.LarxeneDataLostIllusion: LocationData(552, "Chest"), } HT_Checks = { - LocationName.GraveyardMythrilShard: LocationData(0x1300DE, 53, "Chest"), - LocationName.GraveyardSerenityGem: LocationData(0x1300DF, 212, "Chest"), - LocationName.FinklesteinsLabHalloweenTownMap: LocationData(0x1300E0, 211, "Chest"), - LocationName.TownSquareMythrilStone: LocationData(0x1300E1, 209, "Chest"), - LocationName.TownSquareEnergyShard: LocationData(0x1300E2, 210, "Chest"), - LocationName.HinterlandsLightningShard: LocationData(0x1300E3, 54, "Chest"), - LocationName.HinterlandsMythrilStone: LocationData(0x1300E4, 213, "Chest"), - LocationName.HinterlandsAPBoost: LocationData(0x1300E5, 214, "Chest"), - LocationName.CandyCaneLaneMegaPotion: LocationData(0x1300E6, 55, "Chest"), - LocationName.CandyCaneLaneMythrilGem: LocationData(0x1300E7, 56, "Chest"), - LocationName.CandyCaneLaneLightningStone: LocationData(0x1300E8, 216, "Chest"), - LocationName.CandyCaneLaneMythrilStone: LocationData(0x1300E9, 217, "Chest"), - LocationName.SantasHouseChristmasTownMap: LocationData(0x1300EA, 57, "Chest"), - LocationName.SantasHouseAPBoost: LocationData(0x1300EB, 58, "Chest"), - LocationName.PrisonKeeper: LocationData(0x1300EC, 18, "Get Bonus"), - LocationName.OogieBoogie: LocationData(0x1300ED, 19, "Get Bonus"), - LocationName.OogieBoogieMagnetElement: LocationData(0x1300EE, 301, "Chest"), -} -HT2_Checks = { - LocationName.Lock: LocationData(0x1300EF, 40, "Get Bonus"), - LocationName.Present: LocationData(0x1300F0, 297, "Chest"), - LocationName.DecoyPresents: LocationData(0x1300F1, 298, "Chest"), - LocationName.Experiment: LocationData(0x1300F2, 20, "Get Bonus"), - LocationName.DecisivePumpkin: LocationData(0x1300F3, 275, "Chest"), - LocationName.VexenBonus: LocationData(0x1300F4, 64, "Get Bonus"), - LocationName.VexenASRoadtoDiscovery: LocationData(0x1300F5, 544, "Chest"), - LocationName.VexenDataLostIllusion: LocationData(0x1300F6, 549, "Chest"), + LocationName.GraveyardMythrilShard: LocationData(53, "Chest"), + LocationName.GraveyardSerenityGem: LocationData(212, "Chest"), + LocationName.FinklesteinsLabHalloweenTownMap: LocationData(211, "Chest"), + LocationName.TownSquareMythrilStone: LocationData(209, "Chest"), + LocationName.TownSquareEnergyShard: LocationData(210, "Chest"), + LocationName.HinterlandsLightningShard: LocationData(54, "Chest"), + LocationName.HinterlandsMythrilStone: LocationData(213, "Chest"), + LocationName.HinterlandsAPBoost: LocationData(214, "Chest"), + LocationName.CandyCaneLaneMegaPotion: LocationData(55, "Chest"), + LocationName.CandyCaneLaneMythrilGem: LocationData(56, "Chest"), + LocationName.CandyCaneLaneLightningStone: LocationData(216, "Chest"), + LocationName.CandyCaneLaneMythrilStone: LocationData(217, "Chest"), + LocationName.SantasHouseChristmasTownMap: LocationData(57, "Chest"), + LocationName.SantasHouseAPBoost: LocationData(58, "Chest"), + LocationName.PrisonKeeper: LocationData(18, "Get Bonus"), + LocationName.OogieBoogie: LocationData(19, "Get Bonus"), + LocationName.OogieBoogieMagnetElement: LocationData(301, "Chest"), + LocationName.Lock: LocationData(40, "Get Bonus"), + LocationName.Present: LocationData(297, "Chest"), + LocationName.DecoyPresents: LocationData(298, "Chest"), + LocationName.Experiment: LocationData(20, "Get Bonus"), + LocationName.DecisivePumpkin: LocationData(275, "Chest"), + LocationName.VexenBonus: LocationData(64, "Get Bonus"), + LocationName.VexenASRoadtoDiscovery: LocationData(544, "Chest"), + LocationName.VexenDataLostIllusion: LocationData(549, "Chest"), } PR_Checks = { - LocationName.RampartNavalMap: LocationData(0x1300F7, 70, "Chest"), - LocationName.RampartMythrilStone: LocationData(0x1300F8, 219, "Chest"), - LocationName.RampartDarkShard: LocationData(0x1300F9, 220, "Chest"), - LocationName.TownDarkStone: LocationData(0x1300FA, 71, "Chest"), - LocationName.TownAPBoost: LocationData(0x1300FB, 72, "Chest"), - LocationName.TownMythrilShard: LocationData(0x1300FC, 73, "Chest"), - LocationName.TownMythrilGem: LocationData(0x1300FD, 221, "Chest"), - LocationName.CaveMouthBrightShard: LocationData(0x1300FE, 74, "Chest"), - LocationName.CaveMouthMythrilShard: LocationData(0x1300FF, 223, "Chest"), - LocationName.IsladeMuertaMap: LocationData(0x130100, 329, "Chest"), - LocationName.BoatFight: LocationData(0x130101, 62, "Get Bonus"), - LocationName.InterceptorBarrels: LocationData(0x130102, 39, "Get Bonus"), - LocationName.PowderStoreAPBoost1: LocationData(0x130103, 369, "Chest"), - LocationName.PowderStoreAPBoost2: LocationData(0x130104, 370, "Chest"), - LocationName.MoonlightNookMythrilShard: LocationData(0x130105, 75, "Chest"), - LocationName.MoonlightNookSerenityGem: LocationData(0x130106, 224, "Chest"), - LocationName.MoonlightNookPowerStone: LocationData(0x130107, 371, "Chest"), - LocationName.Barbossa: LocationData(0x130108, 21, "Double Get Bonus"), - LocationName.BarbossaGetBonus: LocationData(0x130109, 21, "Second Get Bonus"), - LocationName.FollowtheWind: LocationData(0x13010A, 263, "Chest"), - -} -PR2_Checks = { - LocationName.GrimReaper1: LocationData(0x13010B, 59, "Get Bonus"), - LocationName.InterceptorsHoldFeatherCharm: LocationData(0x13010C, 252, "Chest"), - LocationName.SeadriftKeepAPBoost: LocationData(0x13010D, 76, "Chest"), - LocationName.SeadriftKeepOrichalcum: LocationData(0x13010E, 225, "Chest"), - LocationName.SeadriftKeepMeteorStaff: LocationData(0x13010F, 372, "Chest"), - LocationName.SeadriftRowSerenityGem: LocationData(0x130110, 77, "Chest"), - LocationName.SeadriftRowKingRecipe: LocationData(0x130111, 78, "Chest"), - LocationName.SeadriftRowMythrilCrystal: LocationData(0x130112, 373, "Chest"), - LocationName.SeadriftRowCursedMedallion: LocationData(0x130113, 296, "Chest"), - LocationName.SeadriftRowShipGraveyardMap: LocationData(0x130114, 331, "Chest"), - LocationName.GrimReaper2: LocationData(0x130115, 22, "Get Bonus"), - LocationName.SecretAnsemReport6: LocationData(0x130116, 530, "Chest"), - LocationName.LuxordDataAPBoost: LocationData(0x130117, 557, "Chest"), + LocationName.RampartNavalMap: LocationData(70, "Chest"), + LocationName.RampartMythrilStone: LocationData(219, "Chest"), + LocationName.RampartDarkShard: LocationData(220, "Chest"), + LocationName.TownDarkStone: LocationData(71, "Chest"), + LocationName.TownAPBoost: LocationData(72, "Chest"), + LocationName.TownMythrilShard: LocationData(73, "Chest"), + LocationName.TownMythrilGem: LocationData(221, "Chest"), + LocationName.CaveMouthBrightShard: LocationData(74, "Chest"), + LocationName.CaveMouthMythrilShard: LocationData(223, "Chest"), + LocationName.IsladeMuertaMap: LocationData(329, "Chest"), + LocationName.BoatFight: LocationData(62, "Get Bonus"), + LocationName.InterceptorBarrels: LocationData(39, "Get Bonus"), + LocationName.PowderStoreAPBoost1: LocationData(369, "Chest"), + LocationName.PowderStoreAPBoost2: LocationData(370, "Chest"), + LocationName.MoonlightNookMythrilShard: LocationData(75, "Chest"), + LocationName.MoonlightNookSerenityGem: LocationData(224, "Chest"), + LocationName.MoonlightNookPowerStone: LocationData(371, "Chest"), + LocationName.Barbossa: LocationData(21, "Double Get Bonus"), + LocationName.BarbossaGetBonus: LocationData(21, "Second Get Bonus"), + LocationName.FollowtheWind: LocationData(263, "Chest"), + LocationName.GrimReaper1: LocationData(59, "Get Bonus"), + LocationName.InterceptorsHoldFeatherCharm: LocationData(252, "Chest"), + LocationName.SeadriftKeepAPBoost: LocationData(76, "Chest"), + LocationName.SeadriftKeepOrichalcum: LocationData(225, "Chest"), + LocationName.SeadriftKeepMeteorStaff: LocationData(372, "Chest"), + LocationName.SeadriftRowSerenityGem: LocationData(77, "Chest"), + LocationName.SeadriftRowKingRecipe: LocationData(78, "Chest"), + LocationName.SeadriftRowMythrilCrystal: LocationData(373, "Chest"), + LocationName.SeadriftRowCursedMedallion: LocationData(296, "Chest"), + LocationName.SeadriftRowShipGraveyardMap: LocationData(331, "Chest"), + LocationName.GrimReaper2: LocationData(22, "Get Bonus"), + LocationName.SecretAnsemReport6: LocationData(530, "Chest"), + LocationName.LuxordDataAPBoost: LocationData(557, "Chest"), } HB_Checks = { - LocationName.MarketplaceMap: LocationData(0x130118, 362, "Chest"), - LocationName.BoroughDriveRecovery: LocationData(0x130119, 194, "Chest"), - LocationName.BoroughAPBoost: LocationData(0x13011A, 195, "Chest"), - LocationName.BoroughHiPotion: LocationData(0x13011B, 196, "Chest"), - LocationName.BoroughMythrilShard: LocationData(0x13011C, 305, "Chest"), - LocationName.BoroughDarkShard: LocationData(0x13011D, 506, "Chest"), - LocationName.MerlinsHouseMembershipCard: LocationData(0x13011E, 256, "Chest"), - LocationName.MerlinsHouseBlizzardElement: LocationData(0x13011F, 292, "Chest"), - LocationName.Bailey: LocationData(0x130120, 47, "Get Bonus"), - LocationName.BaileySecretAnsemReport7: LocationData(0x130121, 531, "Chest"), - LocationName.BaseballCharm: LocationData(0x130122, 258, "Chest"), -} -HB2_Checks = { - LocationName.PosternCastlePerimeterMap: LocationData(0x130123, 310, "Chest"), - LocationName.PosternMythrilGem: LocationData(0x130124, 189, "Chest"), - LocationName.PosternAPBoost: LocationData(0x130125, 190, "Chest"), - LocationName.CorridorsMythrilStone: LocationData(0x130126, 200, "Chest"), - LocationName.CorridorsMythrilCrystal: LocationData(0x130127, 201, "Chest"), - LocationName.CorridorsDarkCrystal: LocationData(0x130128, 202, "Chest"), - LocationName.CorridorsAPBoost: LocationData(0x130129, 307, "Chest"), - LocationName.AnsemsStudyMasterForm: LocationData(0x13012A, 276, "Chest"), - LocationName.AnsemsStudySleepingLion: LocationData(0x13012B, 266, "Chest"), - LocationName.AnsemsStudySkillRecipe: LocationData(0x13012C, 184, "Chest"), - LocationName.AnsemsStudyUkuleleCharm: LocationData(0x13012D, 183, "Chest"), - LocationName.RestorationSiteMoonRecipe: LocationData(0x13012E, 309, "Chest"), - LocationName.RestorationSiteAPBoost: LocationData(0x13012F, 507, "Chest"), - LocationName.DemyxHB: LocationData(0x130130, 28, "Double Get Bonus"), - LocationName.DemyxHBGetBonus: LocationData(0x130131, 28, "Second Get Bonus"), - LocationName.FFFightsCureElement: LocationData(0x130132, 361, "Chest"), - LocationName.CrystalFissureTornPages: LocationData(0x130133, 179, "Chest"), - LocationName.CrystalFissureTheGreatMawMap: LocationData(0x130134, 489, "Chest"), - LocationName.CrystalFissureEnergyCrystal: LocationData(0x130135, 180, "Chest"), - LocationName.CrystalFissureAPBoost: LocationData(0x130136, 181, "Chest"), - LocationName.ThousandHeartless: LocationData(0x130137, 60, "Get Bonus"), - LocationName.ThousandHeartlessSecretAnsemReport1: LocationData(0x130138, 525, "Chest"), - LocationName.ThousandHeartlessIceCream: LocationData(0x130139, 269, "Chest"), - LocationName.ThousandHeartlessPicture: LocationData(0x13013A, 511, "Chest"), - LocationName.PosternGullWing: LocationData(0x13013B, 491, "Chest"), - LocationName.HeartlessManufactoryCosmicChain: LocationData(0x13013C, 311, "Chest"), - LocationName.SephirothBonus: LocationData(0x13013D, 35, "Get Bonus"), - LocationName.SephirothFenrir: LocationData(0x13013E, 282, "Chest"), - LocationName.WinnersProof: LocationData(0x13013F, 588, "Chest"), - LocationName.ProofofPeace: LocationData(0x130140, 589, "Chest"), - LocationName.DemyxDataAPBoost: LocationData(0x130141, 560, "Chest"), - LocationName.CoRDepthsAPBoost: LocationData(0x130142, 562, "Chest"), - LocationName.CoRDepthsPowerCrystal: LocationData(0x130143, 563, "Chest"), - LocationName.CoRDepthsFrostCrystal: LocationData(0x130144, 564, "Chest"), - LocationName.CoRDepthsManifestIllusion: LocationData(0x130145, 565, "Chest"), - LocationName.CoRDepthsAPBoost2: LocationData(0x130146, 566, "Chest"), - LocationName.CoRMineshaftLowerLevelDepthsofRemembranceMap: LocationData(0x130147, 580, "Chest"), - LocationName.CoRMineshaftLowerLevelAPBoost: LocationData(0x130148, 578, "Chest"), - -} -CoR_Checks = { - LocationName.CoRDepthsUpperLevelRemembranceGem: LocationData(0x130149, 567, "Chest"), - LocationName.CoRMiningAreaSerenityGem: LocationData(0x13014A, 568, "Chest"), - LocationName.CoRMiningAreaAPBoost: LocationData(0x13014B, 569, "Chest"), - LocationName.CoRMiningAreaSerenityCrystal: LocationData(0x13014C, 570, "Chest"), - LocationName.CoRMiningAreaManifestIllusion: LocationData(0x13014D, 571, "Chest"), - LocationName.CoRMiningAreaSerenityGem2: LocationData(0x13014E, 572, "Chest"), - LocationName.CoRMiningAreaDarkRemembranceMap: LocationData(0x13014F, 573, "Chest"), - LocationName.CoRMineshaftMidLevelPowerBoost: LocationData(0x130150, 581, "Chest"), - LocationName.CoREngineChamberSerenityCrystal: LocationData(0x130151, 574, "Chest"), - LocationName.CoREngineChamberRemembranceCrystal: LocationData(0x130152, 575, "Chest"), - LocationName.CoREngineChamberAPBoost: LocationData(0x130153, 576, "Chest"), - LocationName.CoREngineChamberManifestIllusion: LocationData(0x130154, 577, "Chest"), - LocationName.CoRMineshaftUpperLevelMagicBoost: LocationData(0x130155, 582, "Chest"), - LocationName.CoRMineshaftUpperLevelAPBoost: LocationData(0x130156, 579, "Chest"), - LocationName.TransporttoRemembrance: LocationData(0x130157, 72, "Get Bonus"), + LocationName.MarketplaceMap: LocationData(362, "Chest"), + LocationName.BoroughDriveRecovery: LocationData(194, "Chest"), + LocationName.BoroughAPBoost: LocationData(195, "Chest"), + LocationName.BoroughHiPotion: LocationData(196, "Chest"), + LocationName.BoroughMythrilShard: LocationData(305, "Chest"), + LocationName.BoroughDarkShard: LocationData(506, "Chest"), + LocationName.MerlinsHouseMembershipCard: LocationData(256, "Chest"), + LocationName.MerlinsHouseBlizzardElement: LocationData(292, "Chest"), + LocationName.Bailey: LocationData(47, "Get Bonus"), + LocationName.BaileySecretAnsemReport7: LocationData(531, "Chest"), + LocationName.BaseballCharm: LocationData(258, "Chest"), + LocationName.PosternCastlePerimeterMap: LocationData(310, "Chest"), + LocationName.PosternMythrilGem: LocationData(189, "Chest"), + LocationName.PosternAPBoost: LocationData(190, "Chest"), + LocationName.CorridorsMythrilStone: LocationData(200, "Chest"), + LocationName.CorridorsMythrilCrystal: LocationData(201, "Chest"), + LocationName.CorridorsDarkCrystal: LocationData(202, "Chest"), + LocationName.CorridorsAPBoost: LocationData(307, "Chest"), + LocationName.AnsemsStudyMasterForm: LocationData(276, "Chest"), + LocationName.AnsemsStudySleepingLion: LocationData(266, "Chest"), + LocationName.AnsemsStudySkillRecipe: LocationData(184, "Chest"), + LocationName.AnsemsStudyUkuleleCharm: LocationData(183, "Chest"), + LocationName.RestorationSiteMoonRecipe: LocationData(309, "Chest"), + LocationName.RestorationSiteAPBoost: LocationData(507, "Chest"), + LocationName.DemyxHB: LocationData(28, "Double Get Bonus"), + LocationName.DemyxHBGetBonus: LocationData(28, "Second Get Bonus"), + LocationName.FFFightsCureElement: LocationData(361, "Chest"), + LocationName.CrystalFissureTornPages: LocationData(179, "Chest"), + LocationName.CrystalFissureTheGreatMawMap: LocationData(489, "Chest"), + LocationName.CrystalFissureEnergyCrystal: LocationData(180, "Chest"), + LocationName.CrystalFissureAPBoost: LocationData(181, "Chest"), + LocationName.ThousandHeartless: LocationData(60, "Get Bonus"), + LocationName.ThousandHeartlessSecretAnsemReport1: LocationData(525, "Chest"), + LocationName.ThousandHeartlessIceCream: LocationData(269, "Chest"), + LocationName.ThousandHeartlessPicture: LocationData(511, "Chest"), + LocationName.PosternGullWing: LocationData(491, "Chest"), + LocationName.HeartlessManufactoryCosmicChain: LocationData(311, "Chest"), + LocationName.SephirothBonus: LocationData(35, "Get Bonus"), + LocationName.SephirothFenrir: LocationData(282, "Chest"), + LocationName.WinnersProof: LocationData(588, "Chest"), + LocationName.ProofofPeace: LocationData(589, "Chest"), + LocationName.DemyxDataAPBoost: LocationData(560, "Chest"), + LocationName.CoRDepthsAPBoost: LocationData(562, "Chest"), + LocationName.CoRDepthsPowerCrystal: LocationData(563, "Chest"), + LocationName.CoRDepthsFrostCrystal: LocationData(564, "Chest"), + LocationName.CoRDepthsManifestIllusion: LocationData(565, "Chest"), + LocationName.CoRDepthsAPBoost2: LocationData(566, "Chest"), + LocationName.CoRMineshaftLowerLevelDepthsofRemembranceMap: LocationData(580, "Chest"), + LocationName.CoRMineshaftLowerLevelAPBoost: LocationData(578, "Chest"), + LocationName.CoRDepthsUpperLevelRemembranceGem: LocationData(567, "Chest"), + LocationName.CoRMiningAreaSerenityGem: LocationData(568, "Chest"), + LocationName.CoRMiningAreaAPBoost: LocationData(569, "Chest"), + LocationName.CoRMiningAreaSerenityCrystal: LocationData(570, "Chest"), + LocationName.CoRMiningAreaManifestIllusion: LocationData(571, "Chest"), + LocationName.CoRMiningAreaSerenityGem2: LocationData(572, "Chest"), + LocationName.CoRMiningAreaDarkRemembranceMap: LocationData(573, "Chest"), + LocationName.CoRMineshaftMidLevelPowerBoost: LocationData(581, "Chest"), + LocationName.CoREngineChamberSerenityCrystal: LocationData(574, "Chest"), + LocationName.CoREngineChamberRemembranceCrystal: LocationData(575, "Chest"), + LocationName.CoREngineChamberAPBoost: LocationData(576, "Chest"), + LocationName.CoREngineChamberManifestIllusion: LocationData(577, "Chest"), + LocationName.CoRMineshaftUpperLevelMagicBoost: LocationData(582, "Chest"), + LocationName.CoRMineshaftUpperLevelAPBoost: LocationData(579, "Chest"), + LocationName.TransporttoRemembrance: LocationData(72, "Get Bonus"), } PL_Checks = { - LocationName.GorgeSavannahMap: LocationData(0x130158, 492, "Chest"), - LocationName.GorgeDarkGem: LocationData(0x130159, 404, "Chest"), - LocationName.GorgeMythrilStone: LocationData(0x13015A, 405, "Chest"), - LocationName.ElephantGraveyardFrostGem: LocationData(0x13015B, 401, "Chest"), - LocationName.ElephantGraveyardMythrilStone: LocationData(0x13015C, 402, "Chest"), - LocationName.ElephantGraveyardBrightStone: LocationData(0x13015D, 403, "Chest"), - LocationName.ElephantGraveyardAPBoost: LocationData(0x13015E, 508, "Chest"), - LocationName.ElephantGraveyardMythrilShard: LocationData(0x13015F, 509, "Chest"), - LocationName.PrideRockMap: LocationData(0x130160, 418, "Chest"), - LocationName.PrideRockMythrilStone: LocationData(0x130161, 392, "Chest"), - LocationName.PrideRockSerenityCrystal: LocationData(0x130162, 393, "Chest"), - LocationName.WildebeestValleyEnergyStone: LocationData(0x130163, 396, "Chest"), - LocationName.WildebeestValleyAPBoost: LocationData(0x130164, 397, "Chest"), - LocationName.WildebeestValleyMythrilGem: LocationData(0x130165, 398, "Chest"), - LocationName.WildebeestValleyMythrilStone: LocationData(0x130166, 399, "Chest"), - LocationName.WildebeestValleyLucidGem: LocationData(0x130167, 400, "Chest"), - LocationName.WastelandsMythrilShard: LocationData(0x130168, 406, "Chest"), - LocationName.WastelandsSerenityGem: LocationData(0x130169, 407, "Chest"), - LocationName.WastelandsMythrilStone: LocationData(0x13016A, 408, "Chest"), - LocationName.JungleSerenityGem: LocationData(0x13016B, 409, "Chest"), - LocationName.JungleMythrilStone: LocationData(0x13016C, 410, "Chest"), - LocationName.JungleSerenityCrystal: LocationData(0x13016D, 411, "Chest"), - LocationName.OasisMap: LocationData(0x13016E, 412, "Chest"), - LocationName.OasisTornPages: LocationData(0x13016F, 493, "Chest"), - LocationName.OasisAPBoost: LocationData(0x130170, 413, "Chest"), - LocationName.CircleofLife: LocationData(0x130171, 264, "Chest"), - LocationName.Hyenas1: LocationData(0x130172, 49, "Get Bonus"), - LocationName.Scar: LocationData(0x130173, 29, "Get Bonus"), - LocationName.ScarFireElement: LocationData(0x130174, 302, "Chest"), - -} -PL2_Checks = { - LocationName.Hyenas2: LocationData(0x130175, 50, "Get Bonus"), - LocationName.Groundshaker: LocationData(0x130176, 30, "Double Get Bonus"), - LocationName.GroundshakerGetBonus: LocationData(0x130177, 30, "Second Get Bonus"), - LocationName.SaixDataDefenseBoost: LocationData(0x130178, 556, "Chest"), + LocationName.GorgeSavannahMap: LocationData(492, "Chest"), + LocationName.GorgeDarkGem: LocationData(404, "Chest"), + LocationName.GorgeMythrilStone: LocationData(405, "Chest"), + LocationName.ElephantGraveyardFrostGem: LocationData(401, "Chest"), + LocationName.ElephantGraveyardMythrilStone: LocationData(402, "Chest"), + LocationName.ElephantGraveyardBrightStone: LocationData(403, "Chest"), + LocationName.ElephantGraveyardAPBoost: LocationData(508, "Chest"), + LocationName.ElephantGraveyardMythrilShard: LocationData(509, "Chest"), + LocationName.PrideRockMap: LocationData(418, "Chest"), + LocationName.PrideRockMythrilStone: LocationData(392, "Chest"), + LocationName.PrideRockSerenityCrystal: LocationData(393, "Chest"), + LocationName.WildebeestValleyEnergyStone: LocationData(396, "Chest"), + LocationName.WildebeestValleyAPBoost: LocationData(397, "Chest"), + LocationName.WildebeestValleyMythrilGem: LocationData(398, "Chest"), + LocationName.WildebeestValleyMythrilStone: LocationData(399, "Chest"), + LocationName.WildebeestValleyLucidGem: LocationData(400, "Chest"), + LocationName.WastelandsMythrilShard: LocationData(406, "Chest"), + LocationName.WastelandsSerenityGem: LocationData(407, "Chest"), + LocationName.WastelandsMythrilStone: LocationData(408, "Chest"), + LocationName.JungleSerenityGem: LocationData(409, "Chest"), + LocationName.JungleMythrilStone: LocationData(410, "Chest"), + LocationName.JungleSerenityCrystal: LocationData(411, "Chest"), + LocationName.OasisMap: LocationData(412, "Chest"), + LocationName.OasisTornPages: LocationData(493, "Chest"), + LocationName.OasisAPBoost: LocationData(413, "Chest"), + LocationName.CircleofLife: LocationData(264, "Chest"), + LocationName.Hyenas1: LocationData(49, "Get Bonus"), + LocationName.Scar: LocationData(29, "Get Bonus"), + LocationName.ScarFireElement: LocationData(302, "Chest"), + LocationName.Hyenas2: LocationData(50, "Get Bonus"), + LocationName.Groundshaker: LocationData(30, "Double Get Bonus"), + LocationName.GroundshakerGetBonus: LocationData(30, "Second Get Bonus"), + LocationName.SaixDataDefenseBoost: LocationData(556, "Chest"), } STT_Checks = { - LocationName.TwilightTownMap: LocationData(0x130179, 319, "Chest"), - LocationName.MunnyPouchOlette: LocationData(0x13017A, 288, "Chest"), - LocationName.StationDusks: LocationData(0x13017B, 54, "Get Bonus", "Roxas", 14), - LocationName.StationofSerenityPotion: LocationData(0x13017C, 315, "Chest"), - LocationName.StationofCallingPotion: LocationData(0x13017D, 472, "Chest"), - LocationName.TwilightThorn: LocationData(0x13017E, 33, "Get Bonus", "Roxas", 14), - LocationName.Axel1: LocationData(0x13017F, 73, "Get Bonus", "Roxas", 14), - LocationName.JunkChampionBelt: LocationData(0x130180, 389, "Chest"), - LocationName.JunkMedal: LocationData(0x130181, 390, "Chest"), - LocationName.TheStruggleTrophy: LocationData(0x130182, 519, "Chest"), - LocationName.CentralStationPotion1: LocationData(0x130183, 428, "Chest"), - LocationName.STTCentralStationHiPotion: LocationData(0x130184, 429, "Chest"), - LocationName.CentralStationPotion2: LocationData(0x130185, 430, "Chest"), - LocationName.SunsetTerraceAbilityRing: LocationData(0x130186, 434, "Chest"), - LocationName.SunsetTerraceHiPotion: LocationData(0x130187, 435, "Chest"), - LocationName.SunsetTerracePotion1: LocationData(0x130188, 436, "Chest"), - LocationName.SunsetTerracePotion2: LocationData(0x130189, 437, "Chest"), - LocationName.MansionFoyerHiPotion: LocationData(0x13018A, 449, "Chest"), - LocationName.MansionFoyerPotion1: LocationData(0x13018B, 450, "Chest"), - LocationName.MansionFoyerPotion2: LocationData(0x13018C, 451, "Chest"), - LocationName.MansionDiningRoomElvenBandanna: LocationData(0x13018D, 455, "Chest"), - LocationName.MansionDiningRoomPotion: LocationData(0x13018E, 456, "Chest"), - LocationName.NaminesSketches: LocationData(0x13018F, 289, "Chest"), - LocationName.MansionMap: LocationData(0x130190, 483, "Chest"), - LocationName.MansionLibraryHiPotion: LocationData(0x130191, 459, "Chest"), - LocationName.Axel2: LocationData(0x130192, 34, "Get Bonus", "Roxas", 14), - LocationName.MansionBasementCorridorHiPotion: LocationData(0x130193, 463, "Chest"), - LocationName.RoxasDataMagicBoost: LocationData(0x130194, 558, "Chest"), + LocationName.TwilightTownMap: LocationData(319, "Chest"), + LocationName.MunnyPouchOlette: LocationData(288, "Chest"), + LocationName.StationDusks: LocationData(54, "Get Bonus", "Roxas", 14), + LocationName.StationofSerenityPotion: LocationData(315, "Chest"), + LocationName.StationofCallingPotion: LocationData(472, "Chest"), + LocationName.TwilightThorn: LocationData(33, "Get Bonus", "Roxas", 14), + LocationName.Axel1: LocationData(73, "Get Bonus", "Roxas", 14), + LocationName.JunkChampionBelt: LocationData(389, "Chest"), + LocationName.JunkMedal: LocationData(390, "Chest"), + LocationName.TheStruggleTrophy: LocationData(519, "Chest"), + LocationName.CentralStationPotion1: LocationData(428, "Chest"), + LocationName.STTCentralStationHiPotion: LocationData(429, "Chest"), + LocationName.CentralStationPotion2: LocationData(430, "Chest"), + LocationName.SunsetTerraceAbilityRing: LocationData(434, "Chest"), + LocationName.SunsetTerraceHiPotion: LocationData(435, "Chest"), + LocationName.SunsetTerracePotion1: LocationData(436, "Chest"), + LocationName.SunsetTerracePotion2: LocationData(437, "Chest"), + LocationName.MansionFoyerHiPotion: LocationData(449, "Chest"), + LocationName.MansionFoyerPotion1: LocationData(450, "Chest"), + LocationName.MansionFoyerPotion2: LocationData(451, "Chest"), + LocationName.MansionDiningRoomElvenBandanna: LocationData(455, "Chest"), + LocationName.MansionDiningRoomPotion: LocationData(456, "Chest"), + LocationName.NaminesSketches: LocationData(289, "Chest"), + LocationName.MansionMap: LocationData(483, "Chest"), + LocationName.MansionLibraryHiPotion: LocationData(459, "Chest"), + LocationName.Axel2: LocationData(34, "Get Bonus", "Roxas", 14), + LocationName.MansionBasementCorridorHiPotion: LocationData(463, "Chest"), + LocationName.RoxasDataMagicBoost: LocationData(558, "Chest"), } TT_Checks = { - LocationName.OldMansionPotion: LocationData(0x130195, 447, "Chest"), - LocationName.OldMansionMythrilShard: LocationData(0x130196, 448, "Chest"), - LocationName.TheWoodsPotion: LocationData(0x130197, 442, "Chest"), - LocationName.TheWoodsMythrilShard: LocationData(0x130198, 443, "Chest"), - LocationName.TheWoodsHiPotion: LocationData(0x130199, 444, "Chest"), - LocationName.TramCommonHiPotion: LocationData(0x13019A, 420, "Chest"), - LocationName.TramCommonAPBoost: LocationData(0x13019B, 421, "Chest"), - LocationName.TramCommonTent: LocationData(0x13019C, 422, "Chest"), - LocationName.TramCommonMythrilShard1: LocationData(0x13019D, 423, "Chest"), - LocationName.TramCommonPotion1: LocationData(0x13019E, 424, "Chest"), - LocationName.TramCommonMythrilShard2: LocationData(0x13019F, 425, "Chest"), - LocationName.TramCommonPotion2: LocationData(0x1301A0, 484, "Chest"), - LocationName.StationPlazaSecretAnsemReport2: LocationData(0x1301A1, 526, "Chest"), - LocationName.MunnyPouchMickey: LocationData(0x1301A2, 290, "Chest"), - LocationName.CrystalOrb: LocationData(0x1301A3, 291, "Chest"), - LocationName.CentralStationTent: LocationData(0x1301A4, 431, "Chest"), - LocationName.TTCentralStationHiPotion: LocationData(0x1301A5, 432, "Chest"), - LocationName.CentralStationMythrilShard: LocationData(0x1301A6, 433, "Chest"), - LocationName.TheTowerPotion: LocationData(0x1301A7, 465, "Chest"), - LocationName.TheTowerHiPotion: LocationData(0x1301A8, 466, "Chest"), - LocationName.TheTowerEther: LocationData(0x1301A9, 522, "Chest"), - LocationName.TowerEntrywayEther: LocationData(0x1301AA, 467, "Chest"), - LocationName.TowerEntrywayMythrilShard: LocationData(0x1301AB, 468, "Chest"), - LocationName.SorcerersLoftTowerMap: LocationData(0x1301AC, 469, "Chest"), - LocationName.TowerWardrobeMythrilStone: LocationData(0x1301AD, 470, "Chest"), - LocationName.StarSeeker: LocationData(0x1301AE, 304, "Chest"), - LocationName.ValorForm: LocationData(0x1301AF, 286, "Chest"), - -} -TT2_Checks = { - LocationName.SeifersTrophy: LocationData(0x1301B0, 294, "Chest"), - LocationName.Oathkeeper: LocationData(0x1301B1, 265, "Chest"), - LocationName.LimitForm: LocationData(0x1301B2, 543, "Chest"), -} -TT3_Checks = { - LocationName.UndergroundConcourseMythrilGem: LocationData(0x1301B3, 479, "Chest"), - LocationName.UndergroundConcourseAPBoost: LocationData(0x1301B4, 481, "Chest"), - LocationName.UndergroundConcourseOrichalcum: LocationData(0x1301B5, 480, "Chest"), - LocationName.UndergroundConcourseMythrilCrystal: LocationData(0x1301B6, 482, "Chest"), - LocationName.TunnelwayOrichalcum: LocationData(0x1301B7, 477, "Chest"), - LocationName.TunnelwayMythrilCrystal: LocationData(0x1301B8, 478, "Chest"), - LocationName.SunsetTerraceOrichalcumPlus: LocationData(0x1301B9, 438, "Chest"), - LocationName.SunsetTerraceMythrilShard: LocationData(0x1301BA, 439, "Chest"), - LocationName.SunsetTerraceMythrilCrystal: LocationData(0x1301BB, 440, "Chest"), - LocationName.SunsetTerraceAPBoost: LocationData(0x1301BC, 441, "Chest"), - LocationName.MansionNobodies: LocationData(0x1301BD, 56, "Get Bonus"), - LocationName.MansionFoyerMythrilCrystal: LocationData(0x1301BE, 452, "Chest"), - LocationName.MansionFoyerMythrilStone: LocationData(0x1301BF, 453, "Chest"), - LocationName.MansionFoyerSerenityCrystal: LocationData(0x1301C0, 454, "Chest"), - LocationName.MansionDiningRoomMythrilCrystal: LocationData(0x1301C1, 457, "Chest"), - LocationName.MansionDiningRoomMythrilStone: LocationData(0x1301C2, 458, "Chest"), - LocationName.MansionLibraryOrichalcum: LocationData(0x1301C3, 460, "Chest"), - LocationName.BeamSecretAnsemReport10: LocationData(0x1301C4, 534, "Chest"), - LocationName.MansionBasementCorridorUltimateRecipe: LocationData(0x1301C5, 464, "Chest"), - LocationName.BetwixtandBetween: LocationData(0x1301C6, 63, "Get Bonus"), - LocationName.BetwixtandBetweenBondofFlame: LocationData(0x1301C7, 317, "Chest"), - LocationName.AxelDataMagicBoost: LocationData(0x1301C8, 561, "Chest"), + LocationName.OldMansionPotion: LocationData(447, "Chest"), + LocationName.OldMansionMythrilShard: LocationData(448, "Chest"), + LocationName.TheWoodsPotion: LocationData(442, "Chest"), + LocationName.TheWoodsMythrilShard: LocationData(443, "Chest"), + LocationName.TheWoodsHiPotion: LocationData(444, "Chest"), + LocationName.TramCommonHiPotion: LocationData(420, "Chest"), + LocationName.TramCommonAPBoost: LocationData(421, "Chest"), + LocationName.TramCommonTent: LocationData(422, "Chest"), + LocationName.TramCommonMythrilShard1: LocationData(423, "Chest"), + LocationName.TramCommonPotion1: LocationData(424, "Chest"), + LocationName.TramCommonMythrilShard2: LocationData(425, "Chest"), + LocationName.TramCommonPotion2: LocationData(484, "Chest"), + LocationName.StationPlazaSecretAnsemReport2: LocationData(526, "Chest"), + LocationName.MunnyPouchMickey: LocationData(290, "Chest"), + LocationName.CrystalOrb: LocationData(291, "Chest"), + LocationName.CentralStationTent: LocationData(431, "Chest"), + LocationName.TTCentralStationHiPotion: LocationData(432, "Chest"), + LocationName.CentralStationMythrilShard: LocationData(433, "Chest"), + LocationName.TheTowerPotion: LocationData(465, "Chest"), + LocationName.TheTowerHiPotion: LocationData(466, "Chest"), + LocationName.TheTowerEther: LocationData(522, "Chest"), + LocationName.TowerEntrywayEther: LocationData(467, "Chest"), + LocationName.TowerEntrywayMythrilShard: LocationData(468, "Chest"), + LocationName.SorcerersLoftTowerMap: LocationData(469, "Chest"), + LocationName.TowerWardrobeMythrilStone: LocationData(470, "Chest"), + LocationName.StarSeeker: LocationData(304, "Chest"), + LocationName.ValorForm: LocationData(286, "Chest"), + LocationName.SeifersTrophy: LocationData(294, "Chest"), + LocationName.Oathkeeper: LocationData(265, "Chest"), + LocationName.LimitForm: LocationData(543, "Chest"), + LocationName.UndergroundConcourseMythrilGem: LocationData(479, "Chest"), + LocationName.UndergroundConcourseAPBoost: LocationData(481, "Chest"), + LocationName.UndergroundConcourseOrichalcum: LocationData(480, "Chest"), + LocationName.UndergroundConcourseMythrilCrystal: LocationData(482, "Chest"), + LocationName.TunnelwayOrichalcum: LocationData(477, "Chest"), + LocationName.TunnelwayMythrilCrystal: LocationData(478, "Chest"), + LocationName.SunsetTerraceOrichalcumPlus: LocationData(438, "Chest"), + LocationName.SunsetTerraceMythrilShard: LocationData(439, "Chest"), + LocationName.SunsetTerraceMythrilCrystal: LocationData(440, "Chest"), + LocationName.SunsetTerraceAPBoost: LocationData(441, "Chest"), + LocationName.MansionNobodies: LocationData(56, "Get Bonus"), + LocationName.MansionFoyerMythrilCrystal: LocationData(452, "Chest"), + LocationName.MansionFoyerMythrilStone: LocationData(453, "Chest"), + LocationName.MansionFoyerSerenityCrystal: LocationData(454, "Chest"), + LocationName.MansionDiningRoomMythrilCrystal: LocationData(457, "Chest"), + LocationName.MansionDiningRoomMythrilStone: LocationData(458, "Chest"), + LocationName.MansionLibraryOrichalcum: LocationData(460, "Chest"), + LocationName.BeamSecretAnsemReport10: LocationData(534, "Chest"), + LocationName.MansionBasementCorridorUltimateRecipe: LocationData(464, "Chest"), + LocationName.BetwixtandBetween: LocationData(63, "Get Bonus"), + LocationName.BetwixtandBetweenBondofFlame: LocationData(317, "Chest"), + LocationName.AxelDataMagicBoost: LocationData(561, "Chest"), } TWTNW_Checks = { - LocationName.FragmentCrossingMythrilStone: LocationData(0x1301C9, 374, "Chest"), - LocationName.FragmentCrossingMythrilCrystal: LocationData(0x1301CA, 375, "Chest"), - LocationName.FragmentCrossingAPBoost: LocationData(0x1301CB, 376, "Chest"), - LocationName.FragmentCrossingOrichalcum: LocationData(0x1301CC, 377, "Chest"), - LocationName.Roxas: LocationData(0x1301CD, 69, "Double Get Bonus"), - LocationName.RoxasGetBonus: LocationData(0x1301CE, 69, "Second Get Bonus"), - LocationName.RoxasSecretAnsemReport8: LocationData(0x1301CF, 532, "Chest"), - LocationName.TwoBecomeOne: LocationData(0x1301D0, 277, "Chest"), - LocationName.MemorysSkyscaperMythrilCrystal: LocationData(0x1301D1, 391, "Chest"), - LocationName.MemorysSkyscaperAPBoost: LocationData(0x1301D2, 523, "Chest"), - LocationName.MemorysSkyscaperMythrilStone: LocationData(0x1301D3, 524, "Chest"), - LocationName.TheBrinkofDespairDarkCityMap: LocationData(0x1301D4, 335, "Chest"), - LocationName.TheBrinkofDespairOrichalcumPlus: LocationData(0x1301D5, 500, "Chest"), - LocationName.NothingsCallMythrilGem: LocationData(0x1301D6, 378, "Chest"), - LocationName.NothingsCallOrichalcum: LocationData(0x1301D7, 379, "Chest"), - LocationName.TwilightsViewCosmicBelt: LocationData(0x1301D8, 336, "Chest"), -} -TWTNW2_Checks = { - LocationName.XigbarBonus: LocationData(0x1301D9, 23, "Get Bonus"), - LocationName.XigbarSecretAnsemReport3: LocationData(0x1301DA, 527, "Chest"), - LocationName.NaughtsSkywayMythrilGem: LocationData(0x1301DB, 380, "Chest"), - LocationName.NaughtsSkywayOrichalcum: LocationData(0x1301DC, 381, "Chest"), - LocationName.NaughtsSkywayMythrilCrystal: LocationData(0x1301DD, 382, "Chest"), - LocationName.Oblivion: LocationData(0x1301DE, 278, "Chest"), - LocationName.CastleThatNeverWasMap: LocationData(0x1301DF, 496, "Chest"), - LocationName.Luxord: LocationData(0x1301E0, 24, "Double Get Bonus"), - LocationName.LuxordGetBonus: LocationData(0x1301E1, 24, "Second Get Bonus"), - LocationName.LuxordSecretAnsemReport9: LocationData(0x1301E2, 533, "Chest"), - LocationName.SaixBonus: LocationData(0x1301E3, 25, "Get Bonus"), - LocationName.SaixSecretAnsemReport12: LocationData(0x1301E4, 536, "Chest"), - LocationName.PreXemnas1SecretAnsemReport11: LocationData(0x1301E5, 535, "Chest"), - LocationName.RuinandCreationsPassageMythrilStone: LocationData(0x1301E6, 385, "Chest"), - LocationName.RuinandCreationsPassageAPBoost: LocationData(0x1301E7, 386, "Chest"), - LocationName.RuinandCreationsPassageMythrilCrystal: LocationData(0x1301E8, 387, "Chest"), - LocationName.RuinandCreationsPassageOrichalcum: LocationData(0x1301E9, 388, "Chest"), - LocationName.Xemnas1: LocationData(0x1301EA, 26, "Double Get Bonus"), - LocationName.Xemnas1GetBonus: LocationData(0x1301EB, 26, "Second Get Bonus"), - LocationName.Xemnas1SecretAnsemReport13: LocationData(0x1301EC, 537, "Chest"), - LocationName.FinalXemnas: LocationData(0x1301ED, 71, "Get Bonus"), - LocationName.XemnasDataPowerBoost: LocationData(0x1301EE, 554, "Chest"), + LocationName.FragmentCrossingMythrilStone: LocationData(374, "Chest"), + LocationName.FragmentCrossingMythrilCrystal: LocationData(375, "Chest"), + LocationName.FragmentCrossingAPBoost: LocationData(376, "Chest"), + LocationName.FragmentCrossingOrichalcum: LocationData(377, "Chest"), + LocationName.Roxas: LocationData(69, "Double Get Bonus"), + LocationName.RoxasGetBonus: LocationData(69, "Second Get Bonus"), + LocationName.RoxasSecretAnsemReport8: LocationData(532, "Chest"), + LocationName.TwoBecomeOne: LocationData(277, "Chest"), + LocationName.MemorysSkyscaperMythrilCrystal: LocationData(391, "Chest"), + LocationName.MemorysSkyscaperAPBoost: LocationData(523, "Chest"), + LocationName.MemorysSkyscaperMythrilStone: LocationData(524, "Chest"), + LocationName.TheBrinkofDespairDarkCityMap: LocationData(335, "Chest"), + LocationName.TheBrinkofDespairOrichalcumPlus: LocationData(500, "Chest"), + LocationName.NothingsCallMythrilGem: LocationData(378, "Chest"), + LocationName.NothingsCallOrichalcum: LocationData(379, "Chest"), + LocationName.TwilightsViewCosmicBelt: LocationData(336, "Chest"), + LocationName.XigbarBonus: LocationData(23, "Get Bonus"), + LocationName.XigbarSecretAnsemReport3: LocationData(527, "Chest"), + LocationName.NaughtsSkywayMythrilGem: LocationData(380, "Chest"), + LocationName.NaughtsSkywayOrichalcum: LocationData(381, "Chest"), + LocationName.NaughtsSkywayMythrilCrystal: LocationData(382, "Chest"), + LocationName.Oblivion: LocationData(278, "Chest"), + LocationName.CastleThatNeverWasMap: LocationData(496, "Chest"), + LocationName.Luxord: LocationData(24, "Double Get Bonus"), + LocationName.LuxordGetBonus: LocationData(24, "Second Get Bonus"), + LocationName.LuxordSecretAnsemReport9: LocationData(533, "Chest"), + LocationName.SaixBonus: LocationData(25, "Get Bonus"), + LocationName.SaixSecretAnsemReport12: LocationData(536, "Chest"), + LocationName.PreXemnas1SecretAnsemReport11: LocationData(535, "Chest"), + LocationName.RuinandCreationsPassageMythrilStone: LocationData(385, "Chest"), + LocationName.RuinandCreationsPassageAPBoost: LocationData(386, "Chest"), + LocationName.RuinandCreationsPassageMythrilCrystal: LocationData(387, "Chest"), + LocationName.RuinandCreationsPassageOrichalcum: LocationData(388, "Chest"), + LocationName.Xemnas1: LocationData(26, "Double Get Bonus"), + LocationName.Xemnas1GetBonus: LocationData(26, "Second Get Bonus"), + LocationName.Xemnas1SecretAnsemReport13: LocationData(537, "Chest"), + LocationName.FinalXemnas: LocationData(71, "Get Bonus"), + LocationName.XemnasDataPowerBoost: LocationData(554, "Chest"), } SoraLevels = { - LocationName.Lvl1: LocationData(0x1301EF, 1, "Levels"), - LocationName.Lvl2: LocationData(0x1301F0, 2, "Levels"), - LocationName.Lvl3: LocationData(0x1301F1, 3, "Levels"), - LocationName.Lvl4: LocationData(0x1301F2, 4, "Levels"), - LocationName.Lvl5: LocationData(0x1301F3, 5, "Levels"), - LocationName.Lvl6: LocationData(0x1301F4, 6, "Levels"), - LocationName.Lvl7: LocationData(0x1301F5, 7, "Levels"), - LocationName.Lvl8: LocationData(0x1301F6, 8, "Levels"), - LocationName.Lvl9: LocationData(0x1301F7, 9, "Levels"), - LocationName.Lvl10: LocationData(0x1301F8, 10, "Levels"), - LocationName.Lvl11: LocationData(0x1301F9, 11, "Levels"), - LocationName.Lvl12: LocationData(0x1301FA, 12, "Levels"), - LocationName.Lvl13: LocationData(0x1301FB, 13, "Levels"), - LocationName.Lvl14: LocationData(0x1301FC, 14, "Levels"), - LocationName.Lvl15: LocationData(0x1301FD, 15, "Levels"), - LocationName.Lvl16: LocationData(0x1301FE, 16, "Levels"), - LocationName.Lvl17: LocationData(0x1301FF, 17, "Levels"), - LocationName.Lvl18: LocationData(0x130200, 18, "Levels"), - LocationName.Lvl19: LocationData(0x130201, 19, "Levels"), - LocationName.Lvl20: LocationData(0x130202, 20, "Levels"), - LocationName.Lvl21: LocationData(0x130203, 21, "Levels"), - LocationName.Lvl22: LocationData(0x130204, 22, "Levels"), - LocationName.Lvl23: LocationData(0x130205, 23, "Levels"), - LocationName.Lvl24: LocationData(0x130206, 24, "Levels"), - LocationName.Lvl25: LocationData(0x130207, 25, "Levels"), - LocationName.Lvl26: LocationData(0x130208, 26, "Levels"), - LocationName.Lvl27: LocationData(0x130209, 27, "Levels"), - LocationName.Lvl28: LocationData(0x13020A, 28, "Levels"), - LocationName.Lvl29: LocationData(0x13020B, 29, "Levels"), - LocationName.Lvl30: LocationData(0x13020C, 30, "Levels"), - LocationName.Lvl31: LocationData(0x13020D, 31, "Levels"), - LocationName.Lvl32: LocationData(0x13020E, 32, "Levels"), - LocationName.Lvl33: LocationData(0x13020F, 33, "Levels"), - LocationName.Lvl34: LocationData(0x130210, 34, "Levels"), - LocationName.Lvl35: LocationData(0x130211, 35, "Levels"), - LocationName.Lvl36: LocationData(0x130212, 36, "Levels"), - LocationName.Lvl37: LocationData(0x130213, 37, "Levels"), - LocationName.Lvl38: LocationData(0x130214, 38, "Levels"), - LocationName.Lvl39: LocationData(0x130215, 39, "Levels"), - LocationName.Lvl40: LocationData(0x130216, 40, "Levels"), - LocationName.Lvl41: LocationData(0x130217, 41, "Levels"), - LocationName.Lvl42: LocationData(0x130218, 42, "Levels"), - LocationName.Lvl43: LocationData(0x130219, 43, "Levels"), - LocationName.Lvl44: LocationData(0x13021A, 44, "Levels"), - LocationName.Lvl45: LocationData(0x13021B, 45, "Levels"), - LocationName.Lvl46: LocationData(0x13021C, 46, "Levels"), - LocationName.Lvl47: LocationData(0x13021D, 47, "Levels"), - LocationName.Lvl48: LocationData(0x13021E, 48, "Levels"), - LocationName.Lvl49: LocationData(0x13021F, 49, "Levels"), - LocationName.Lvl50: LocationData(0x130220, 50, "Levels"), - LocationName.Lvl51: LocationData(0x130221, 51, "Levels"), - LocationName.Lvl52: LocationData(0x130222, 52, "Levels"), - LocationName.Lvl53: LocationData(0x130223, 53, "Levels"), - LocationName.Lvl54: LocationData(0x130224, 54, "Levels"), - LocationName.Lvl55: LocationData(0x130225, 55, "Levels"), - LocationName.Lvl56: LocationData(0x130226, 56, "Levels"), - LocationName.Lvl57: LocationData(0x130227, 57, "Levels"), - LocationName.Lvl58: LocationData(0x130228, 58, "Levels"), - LocationName.Lvl59: LocationData(0x130229, 59, "Levels"), - LocationName.Lvl60: LocationData(0x13022A, 60, "Levels"), - LocationName.Lvl61: LocationData(0x13022B, 61, "Levels"), - LocationName.Lvl62: LocationData(0x13022C, 62, "Levels"), - LocationName.Lvl63: LocationData(0x13022D, 63, "Levels"), - LocationName.Lvl64: LocationData(0x13022E, 64, "Levels"), - LocationName.Lvl65: LocationData(0x13022F, 65, "Levels"), - LocationName.Lvl66: LocationData(0x130230, 66, "Levels"), - LocationName.Lvl67: LocationData(0x130231, 67, "Levels"), - LocationName.Lvl68: LocationData(0x130232, 68, "Levels"), - LocationName.Lvl69: LocationData(0x130233, 69, "Levels"), - LocationName.Lvl70: LocationData(0x130234, 70, "Levels"), - LocationName.Lvl71: LocationData(0x130235, 71, "Levels"), - LocationName.Lvl72: LocationData(0x130236, 72, "Levels"), - LocationName.Lvl73: LocationData(0x130237, 73, "Levels"), - LocationName.Lvl74: LocationData(0x130238, 74, "Levels"), - LocationName.Lvl75: LocationData(0x130239, 75, "Levels"), - LocationName.Lvl76: LocationData(0x13023A, 76, "Levels"), - LocationName.Lvl77: LocationData(0x13023B, 77, "Levels"), - LocationName.Lvl78: LocationData(0x13023C, 78, "Levels"), - LocationName.Lvl79: LocationData(0x13023D, 79, "Levels"), - LocationName.Lvl80: LocationData(0x13023E, 80, "Levels"), - LocationName.Lvl81: LocationData(0x13023F, 81, "Levels"), - LocationName.Lvl82: LocationData(0x130240, 82, "Levels"), - LocationName.Lvl83: LocationData(0x130241, 83, "Levels"), - LocationName.Lvl84: LocationData(0x130242, 84, "Levels"), - LocationName.Lvl85: LocationData(0x130243, 85, "Levels"), - LocationName.Lvl86: LocationData(0x130244, 86, "Levels"), - LocationName.Lvl87: LocationData(0x130245, 87, "Levels"), - LocationName.Lvl88: LocationData(0x130246, 88, "Levels"), - LocationName.Lvl89: LocationData(0x130247, 89, "Levels"), - LocationName.Lvl90: LocationData(0x130248, 90, "Levels"), - LocationName.Lvl91: LocationData(0x130249, 91, "Levels"), - LocationName.Lvl92: LocationData(0x13024A, 92, "Levels"), - LocationName.Lvl93: LocationData(0x13024B, 93, "Levels"), - LocationName.Lvl94: LocationData(0x13024C, 94, "Levels"), - LocationName.Lvl95: LocationData(0x13024D, 95, "Levels"), - LocationName.Lvl96: LocationData(0x13024E, 96, "Levels"), - LocationName.Lvl97: LocationData(0x13024F, 97, "Levels"), - LocationName.Lvl98: LocationData(0x130250, 98, "Levels"), - LocationName.Lvl99: LocationData(0x130251, 99, "Levels"), + LocationName.Lvl2: LocationData(2, "Levels"), + LocationName.Lvl3: LocationData(3, "Levels"), + LocationName.Lvl4: LocationData(4, "Levels"), + LocationName.Lvl5: LocationData(5, "Levels"), + LocationName.Lvl6: LocationData(6, "Levels"), + LocationName.Lvl7: LocationData(7, "Levels"), + LocationName.Lvl8: LocationData(8, "Levels"), + LocationName.Lvl9: LocationData(9, "Levels"), + LocationName.Lvl10: LocationData(10, "Levels"), + LocationName.Lvl11: LocationData(11, "Levels"), + LocationName.Lvl12: LocationData(12, "Levels"), + LocationName.Lvl13: LocationData(13, "Levels"), + LocationName.Lvl14: LocationData(14, "Levels"), + LocationName.Lvl15: LocationData(15, "Levels"), + LocationName.Lvl16: LocationData(16, "Levels"), + LocationName.Lvl17: LocationData(17, "Levels"), + LocationName.Lvl18: LocationData(18, "Levels"), + LocationName.Lvl19: LocationData(19, "Levels"), + LocationName.Lvl20: LocationData(20, "Levels"), + LocationName.Lvl21: LocationData(21, "Levels"), + LocationName.Lvl22: LocationData(22, "Levels"), + LocationName.Lvl23: LocationData(23, "Levels"), + LocationName.Lvl24: LocationData(24, "Levels"), + LocationName.Lvl25: LocationData(25, "Levels"), + LocationName.Lvl26: LocationData(26, "Levels"), + LocationName.Lvl27: LocationData(27, "Levels"), + LocationName.Lvl28: LocationData(28, "Levels"), + LocationName.Lvl29: LocationData(29, "Levels"), + LocationName.Lvl30: LocationData(30, "Levels"), + LocationName.Lvl31: LocationData(31, "Levels"), + LocationName.Lvl32: LocationData(32, "Levels"), + LocationName.Lvl33: LocationData(33, "Levels"), + LocationName.Lvl34: LocationData(34, "Levels"), + LocationName.Lvl35: LocationData(35, "Levels"), + LocationName.Lvl36: LocationData(36, "Levels"), + LocationName.Lvl37: LocationData(37, "Levels"), + LocationName.Lvl38: LocationData(38, "Levels"), + LocationName.Lvl39: LocationData(39, "Levels"), + LocationName.Lvl40: LocationData(40, "Levels"), + LocationName.Lvl41: LocationData(41, "Levels"), + LocationName.Lvl42: LocationData(42, "Levels"), + LocationName.Lvl43: LocationData(43, "Levels"), + LocationName.Lvl44: LocationData(44, "Levels"), + LocationName.Lvl45: LocationData(45, "Levels"), + LocationName.Lvl46: LocationData(46, "Levels"), + LocationName.Lvl47: LocationData(47, "Levels"), + LocationName.Lvl48: LocationData(48, "Levels"), + LocationName.Lvl49: LocationData(49, "Levels"), + LocationName.Lvl50: LocationData(50, "Levels"), + LocationName.Lvl51: LocationData(51, "Levels"), + LocationName.Lvl52: LocationData(52, "Levels"), + LocationName.Lvl53: LocationData(53, "Levels"), + LocationName.Lvl54: LocationData(54, "Levels"), + LocationName.Lvl55: LocationData(55, "Levels"), + LocationName.Lvl56: LocationData(56, "Levels"), + LocationName.Lvl57: LocationData(57, "Levels"), + LocationName.Lvl58: LocationData(58, "Levels"), + LocationName.Lvl59: LocationData(59, "Levels"), + LocationName.Lvl60: LocationData(60, "Levels"), + LocationName.Lvl61: LocationData(61, "Levels"), + LocationName.Lvl62: LocationData(62, "Levels"), + LocationName.Lvl63: LocationData(63, "Levels"), + LocationName.Lvl64: LocationData(64, "Levels"), + LocationName.Lvl65: LocationData(65, "Levels"), + LocationName.Lvl66: LocationData(66, "Levels"), + LocationName.Lvl67: LocationData(67, "Levels"), + LocationName.Lvl68: LocationData(68, "Levels"), + LocationName.Lvl69: LocationData(69, "Levels"), + LocationName.Lvl70: LocationData(70, "Levels"), + LocationName.Lvl71: LocationData(71, "Levels"), + LocationName.Lvl72: LocationData(72, "Levels"), + LocationName.Lvl73: LocationData(73, "Levels"), + LocationName.Lvl74: LocationData(74, "Levels"), + LocationName.Lvl75: LocationData(75, "Levels"), + LocationName.Lvl76: LocationData(76, "Levels"), + LocationName.Lvl77: LocationData(77, "Levels"), + LocationName.Lvl78: LocationData(78, "Levels"), + LocationName.Lvl79: LocationData(79, "Levels"), + LocationName.Lvl80: LocationData(80, "Levels"), + LocationName.Lvl81: LocationData(81, "Levels"), + LocationName.Lvl82: LocationData(82, "Levels"), + LocationName.Lvl83: LocationData(83, "Levels"), + LocationName.Lvl84: LocationData(84, "Levels"), + LocationName.Lvl85: LocationData(85, "Levels"), + LocationName.Lvl86: LocationData(86, "Levels"), + LocationName.Lvl87: LocationData(87, "Levels"), + LocationName.Lvl88: LocationData(88, "Levels"), + LocationName.Lvl89: LocationData(89, "Levels"), + LocationName.Lvl90: LocationData(90, "Levels"), + LocationName.Lvl91: LocationData(91, "Levels"), + LocationName.Lvl92: LocationData(92, "Levels"), + LocationName.Lvl93: LocationData(93, "Levels"), + LocationName.Lvl94: LocationData(94, "Levels"), + LocationName.Lvl95: LocationData(95, "Levels"), + LocationName.Lvl96: LocationData(96, "Levels"), + LocationName.Lvl97: LocationData(97, "Levels"), + LocationName.Lvl98: LocationData(98, "Levels"), + LocationName.Lvl99: LocationData(99, "Levels"), } Form_Checks = { - LocationName.Valorlvl2: LocationData(0x130253, 2, "Forms", 1), - LocationName.Valorlvl3: LocationData(0x130254, 3, "Forms", 1), - LocationName.Valorlvl4: LocationData(0x130255, 4, "Forms", 1), - LocationName.Valorlvl5: LocationData(0x130256, 5, "Forms", 1), - LocationName.Valorlvl6: LocationData(0x130257, 6, "Forms", 1), - LocationName.Valorlvl7: LocationData(0x130258, 7, "Forms", 1), + LocationName.Valorlvl2: LocationData(2, "Forms", 1), + LocationName.Valorlvl3: LocationData(3, "Forms", 1), + LocationName.Valorlvl4: LocationData(4, "Forms", 1), + LocationName.Valorlvl5: LocationData(5, "Forms", 1), + LocationName.Valorlvl6: LocationData(6, "Forms", 1), + LocationName.Valorlvl7: LocationData(7, "Forms", 1), - LocationName.Wisdomlvl2: LocationData(0x13025A, 2, "Forms", 2), - LocationName.Wisdomlvl3: LocationData(0x13025B, 3, "Forms", 2), - LocationName.Wisdomlvl4: LocationData(0x13025C, 4, "Forms", 2), - LocationName.Wisdomlvl5: LocationData(0x13025D, 5, "Forms", 2), - LocationName.Wisdomlvl6: LocationData(0x13025E, 6, "Forms", 2), - LocationName.Wisdomlvl7: LocationData(0x13025F, 7, "Forms", 2), + LocationName.Wisdomlvl2: LocationData(2, "Forms", 2), + LocationName.Wisdomlvl3: LocationData(3, "Forms", 2), + LocationName.Wisdomlvl4: LocationData(4, "Forms", 2), + LocationName.Wisdomlvl5: LocationData(5, "Forms", 2), + LocationName.Wisdomlvl6: LocationData(6, "Forms", 2), + LocationName.Wisdomlvl7: LocationData(7, "Forms", 2), - LocationName.Limitlvl2: LocationData(0x130261, 2, "Forms", 3), - LocationName.Limitlvl3: LocationData(0x130262, 3, "Forms", 3), - LocationName.Limitlvl4: LocationData(0x130263, 4, "Forms", 3), - LocationName.Limitlvl5: LocationData(0x130264, 5, "Forms", 3), - LocationName.Limitlvl6: LocationData(0x130265, 6, "Forms", 3), - LocationName.Limitlvl7: LocationData(0x130266, 7, "Forms", 3), + LocationName.Limitlvl2: LocationData(2, "Forms", 3), + LocationName.Limitlvl3: LocationData(3, "Forms", 3), + LocationName.Limitlvl4: LocationData(4, "Forms", 3), + LocationName.Limitlvl5: LocationData(5, "Forms", 3), + LocationName.Limitlvl6: LocationData(6, "Forms", 3), + LocationName.Limitlvl7: LocationData(7, "Forms", 3), - LocationName.Masterlvl2: LocationData(0x130268, 2, "Forms", 4), - LocationName.Masterlvl3: LocationData(0x130269, 3, "Forms", 4), - LocationName.Masterlvl4: LocationData(0x13026A, 4, "Forms", 4), - LocationName.Masterlvl5: LocationData(0x13026B, 5, "Forms", 4), - LocationName.Masterlvl6: LocationData(0x13026C, 6, "Forms", 4), - LocationName.Masterlvl7: LocationData(0x13026D, 7, "Forms", 4), + LocationName.Masterlvl2: LocationData(2, "Forms", 4), + LocationName.Masterlvl3: LocationData(3, "Forms", 4), + LocationName.Masterlvl4: LocationData(4, "Forms", 4), + LocationName.Masterlvl5: LocationData(5, "Forms", 4), + LocationName.Masterlvl6: LocationData(6, "Forms", 4), + LocationName.Masterlvl7: LocationData(7, "Forms", 4), - LocationName.Finallvl2: LocationData(0x13026F, 2, "Forms", 5), - LocationName.Finallvl3: LocationData(0x130270, 3, "Forms", 5), - LocationName.Finallvl4: LocationData(0x130271, 4, "Forms", 5), - LocationName.Finallvl5: LocationData(0x130272, 5, "Forms", 5), - LocationName.Finallvl6: LocationData(0x130273, 6, "Forms", 5), - LocationName.Finallvl7: LocationData(0x130274, 7, "Forms", 5), + LocationName.Finallvl2: LocationData(2, "Forms", 5), + LocationName.Finallvl3: LocationData(3, "Forms", 5), + LocationName.Finallvl4: LocationData(4, "Forms", 5), + LocationName.Finallvl5: LocationData(5, "Forms", 5), + LocationName.Finallvl6: LocationData(6, "Forms", 5), + LocationName.Finallvl7: LocationData(7, "Forms", 5), +} +Summon_Checks = { + LocationName.Summonlvl2: LocationData(2, "Summons"), + LocationName.Summonlvl3: LocationData(3, "Summons"), + LocationName.Summonlvl4: LocationData(4, "Summons"), + LocationName.Summonlvl5: LocationData(5, "Summons"), + LocationName.Summonlvl6: LocationData(6, "Summons"), + LocationName.Summonlvl7: LocationData(7, "Summons"), } GoA_Checks = { - LocationName.GardenofAssemblageMap: LocationData(0x130275, 585, "Chest"), - LocationName.GoALostIllusion: LocationData(0x130276, 586, "Chest"), - LocationName.ProofofNonexistence: LocationData(0x130277, 590, "Chest"), + LocationName.GardenofAssemblageMap: LocationData(585, "Chest"), + LocationName.GoALostIllusion: LocationData(586, "Chest"), + LocationName.ProofofNonexistence: LocationData(590, "Chest"), } Keyblade_Slots = { - LocationName.FAKESlot: LocationData(0x130278, 116, "Keyblade"), - LocationName.DetectionSaberSlot: LocationData(0x130279, 83, "Keyblade"), - LocationName.EdgeofUltimaSlot: LocationData(0x13027A, 84, "Keyblade"), - LocationName.KingdomKeySlot: LocationData(0x13027B, 80, "Keyblade"), - LocationName.OathkeeperSlot: LocationData(0x13027C, 81, "Keyblade"), - LocationName.OblivionSlot: LocationData(0x13027D, 82, "Keyblade"), - LocationName.StarSeekerSlot: LocationData(0x13027E, 123, "Keyblade"), - LocationName.HiddenDragonSlot: LocationData(0x13027F, 124, "Keyblade"), - LocationName.HerosCrestSlot: LocationData(0x130280, 127, "Keyblade"), - LocationName.MonochromeSlot: LocationData(0x130281, 128, "Keyblade"), - LocationName.FollowtheWindSlot: LocationData(0x130282, 129, "Keyblade"), - LocationName.CircleofLifeSlot: LocationData(0x130283, 130, "Keyblade"), - LocationName.PhotonDebuggerSlot: LocationData(0x130284, 131, "Keyblade"), - LocationName.GullWingSlot: LocationData(0x130285, 132, "Keyblade"), - LocationName.RumblingRoseSlot: LocationData(0x130286, 133, "Keyblade"), - LocationName.GuardianSoulSlot: LocationData(0x130287, 134, "Keyblade"), - LocationName.WishingLampSlot: LocationData(0x130288, 135, "Keyblade"), - LocationName.DecisivePumpkinSlot: LocationData(0x130289, 136, "Keyblade"), - LocationName.SweetMemoriesSlot: LocationData(0x13028A, 138, "Keyblade"), - LocationName.MysteriousAbyssSlot: LocationData(0x13028B, 139, "Keyblade"), - LocationName.SleepingLionSlot: LocationData(0x13028C, 137, "Keyblade"), - LocationName.BondofFlameSlot: LocationData(0x13028D, 141, "Keyblade"), - LocationName.TwoBecomeOneSlot: LocationData(0x13028E, 148, "Keyblade"), - LocationName.FatalCrestSlot: LocationData(0x13028F, 140, "Keyblade"), - LocationName.FenrirSlot: LocationData(0x130290, 142, "Keyblade"), - LocationName.UltimaWeaponSlot: LocationData(0x130291, 143, "Keyblade"), - LocationName.WinnersProofSlot: LocationData(0x130292, 149, "Keyblade"), - LocationName.PurebloodSlot: LocationData(0x1302DB, 85, "Keyblade"), -} -# checks are given when talking to the computer in the GoA -Critical_Checks = { - LocationName.Crit_1: LocationData(0x130293, 1, "Critical"), - LocationName.Crit_2: LocationData(0x130294, 1, "Critical"), - LocationName.Crit_3: LocationData(0x130295, 1, "Critical"), - LocationName.Crit_4: LocationData(0x130296, 1, "Critical"), - LocationName.Crit_5: LocationData(0x130297, 1, "Critical"), - LocationName.Crit_6: LocationData(0x130298, 1, "Critical"), - LocationName.Crit_7: LocationData(0x130299, 1, "Critical"), + LocationName.FAKESlot: LocationData(116, "Keyblade"), + LocationName.DetectionSaberSlot: LocationData(83, "Keyblade"), + LocationName.EdgeofUltimaSlot: LocationData(84, "Keyblade"), + LocationName.KingdomKeySlot: LocationData(80, "Keyblade"), + LocationName.OathkeeperSlot: LocationData(81, "Keyblade"), + LocationName.OblivionSlot: LocationData(82, "Keyblade"), + LocationName.StarSeekerSlot: LocationData(123, "Keyblade"), + LocationName.HiddenDragonSlot: LocationData(124, "Keyblade"), + LocationName.HerosCrestSlot: LocationData(127, "Keyblade"), + LocationName.MonochromeSlot: LocationData(128, "Keyblade"), + LocationName.FollowtheWindSlot: LocationData(129, "Keyblade"), + LocationName.CircleofLifeSlot: LocationData(130, "Keyblade"), + LocationName.PhotonDebuggerSlot: LocationData(131, "Keyblade"), + LocationName.GullWingSlot: LocationData(132, "Keyblade"), + LocationName.RumblingRoseSlot: LocationData(133, "Keyblade"), + LocationName.GuardianSoulSlot: LocationData(134, "Keyblade"), + LocationName.WishingLampSlot: LocationData(135, "Keyblade"), + LocationName.DecisivePumpkinSlot: LocationData(136, "Keyblade"), + LocationName.SweetMemoriesSlot: LocationData(138, "Keyblade"), + LocationName.MysteriousAbyssSlot: LocationData(139, "Keyblade"), + LocationName.SleepingLionSlot: LocationData(137, "Keyblade"), + LocationName.BondofFlameSlot: LocationData(141, "Keyblade"), + LocationName.TwoBecomeOneSlot: LocationData(148, "Keyblade"), + LocationName.FatalCrestSlot: LocationData(140, "Keyblade"), + LocationName.FenrirSlot: LocationData(142, "Keyblade"), + LocationName.UltimaWeaponSlot: LocationData(143, "Keyblade"), + LocationName.WinnersProofSlot: LocationData(149, "Keyblade"), + LocationName.PurebloodSlot: LocationData(85, "Keyblade"), } Donald_Checks = { - LocationName.DonaldScreens: LocationData(0x13029A, 45, "Get Bonus", "Donald", 2), - LocationName.DonaldDemyxHBGetBonus: LocationData(0x13029B, 28, "Get Bonus", "Donald", 2), - LocationName.DonaldDemyxOC: LocationData(0x13029C, 58, "Get Bonus", "Donald", 2), - LocationName.DonaldBoatPete: LocationData(0x13029D, 16, "Double Get Bonus", "Donald", 2), - LocationName.DonaldBoatPeteGetBonus: LocationData(0x13029E, 16, "Second Get Bonus", "Donald", 2), - LocationName.DonaldPrisonKeeper: LocationData(0x13029F, 18, "Get Bonus", "Donald", 2), - LocationName.DonaldScar: LocationData(0x1302A0, 29, "Get Bonus", "Donald", 2), - LocationName.DonaldSolarSailer: LocationData(0x1302A1, 61, "Get Bonus", "Donald", 2), - LocationName.DonaldExperiment: LocationData(0x1302A2, 20, "Get Bonus", "Donald", 2), - LocationName.DonaldBoatFight: LocationData(0x1302A3, 62, "Get Bonus", "Donald", 2), - LocationName.DonaldMansionNobodies: LocationData(0x1302A4, 56, "Get Bonus", "Donald", 2), - LocationName.DonaldThresholder: LocationData(0x1302A5, 2, "Get Bonus", "Donald", 2), - LocationName.DonaldXaldinGetBonus: LocationData(0x1302A6, 4, "Get Bonus", "Donald", 2), - LocationName.DonaladGrimReaper2: LocationData(0x1302A7, 22, "Get Bonus", "Donald", 2), + LocationName.DonaldScreens: LocationData(45, "Get Bonus", "Donald", 2), + LocationName.DonaldDemyxHBGetBonus: LocationData(28, "Get Bonus", "Donald", 2), + LocationName.DonaldDemyxOC: LocationData(58, "Get Bonus", "Donald", 2), + LocationName.DonaldBoatPete: LocationData(16, "Double Get Bonus", "Donald", 2), + LocationName.DonaldBoatPeteGetBonus: LocationData(16, "Second Get Bonus", "Donald", 2), + LocationName.DonaldPrisonKeeper: LocationData(18, "Get Bonus", "Donald", 2), + LocationName.DonaldScar: LocationData(29, "Get Bonus", "Donald", 2), + LocationName.DonaldSolarSailer: LocationData(61, "Get Bonus", "Donald", 2), + LocationName.DonaldExperiment: LocationData(20, "Get Bonus", "Donald", 2), + LocationName.DonaldBoatFight: LocationData(62, "Get Bonus", "Donald", 2), + LocationName.DonaldMansionNobodies: LocationData(56, "Get Bonus", "Donald", 2), + LocationName.DonaldThresholder: LocationData(2, "Get Bonus", "Donald", 2), + LocationName.DonaldXaldinGetBonus: LocationData(4, "Get Bonus", "Donald", 2), + LocationName.DonaladGrimReaper2: LocationData(22, "Get Bonus", "Donald", 2), - LocationName.CometStaff: LocationData(0x1302A8, 90, "Keyblade", "Donald"), - LocationName.HammerStaff: LocationData(0x1302A9, 87, "Keyblade", "Donald"), - LocationName.LordsBroom: LocationData(0x1302AA, 91, "Keyblade", "Donald"), - LocationName.MagesStaff: LocationData(0x1302AB, 86, "Keyblade", "Donald"), - LocationName.MeteorStaff: LocationData(0x1302AC, 89, "Keyblade", "Donald"), - LocationName.NobodyLance: LocationData(0x1302AD, 94, "Keyblade", "Donald"), - LocationName.PreciousMushroom: LocationData(0x1302AE, 154, "Keyblade", "Donald"), - LocationName.PreciousMushroom2: LocationData(0x1302AF, 155, "Keyblade", "Donald"), - LocationName.PremiumMushroom: LocationData(0x1302B0, 156, "Keyblade", "Donald"), - LocationName.RisingDragon: LocationData(0x1302B1, 93, "Keyblade", "Donald"), - LocationName.SaveTheQueen2: LocationData(0x1302B2, 146, "Keyblade", "Donald"), - LocationName.ShamansRelic: LocationData(0x1302B3, 95, "Keyblade", "Donald"), - LocationName.VictoryBell: LocationData(0x1302B4, 88, "Keyblade", "Donald"), - LocationName.WisdomWand: LocationData(0x1302B5, 92, "Keyblade", "Donald"), - LocationName.Centurion2: LocationData(0x1302B6, 151, "Keyblade", "Donald"), - LocationName.DonaldAbuEscort: LocationData(0x1302B7, 42, "Get Bonus", "Donald", 2), - LocationName.DonaldStarting1: LocationData(0x1302B8, 2, "Critical", "Donald"), - LocationName.DonaldStarting2: LocationData(0x1302B9, 2, "Critical", "Donald"), + LocationName.CometStaff: LocationData(90, "Keyblade", "Donald"), + LocationName.HammerStaff: LocationData(87, "Keyblade", "Donald"), + LocationName.LordsBroom: LocationData(91, "Keyblade", "Donald"), + LocationName.MagesStaff: LocationData(86, "Keyblade", "Donald"), + LocationName.MeteorStaff: LocationData(89, "Keyblade", "Donald"), + LocationName.NobodyLance: LocationData(94, "Keyblade", "Donald"), + LocationName.PreciousMushroom: LocationData(154, "Keyblade", "Donald"), + LocationName.PreciousMushroom2: LocationData(155, "Keyblade", "Donald"), + LocationName.PremiumMushroom: LocationData(156, "Keyblade", "Donald"), + LocationName.RisingDragon: LocationData(93, "Keyblade", "Donald"), + LocationName.SaveTheQueen2: LocationData(146, "Keyblade", "Donald"), + LocationName.ShamansRelic: LocationData(95, "Keyblade", "Donald"), + LocationName.VictoryBell: LocationData(88, "Keyblade", "Donald"), + LocationName.WisdomWand: LocationData(92, "Keyblade", "Donald"), + LocationName.Centurion2: LocationData(151, "Keyblade", "Donald"), + LocationName.DonaldAbuEscort: LocationData(42, "Get Bonus", "Donald", 2), + # LocationName.DonaldStarting1: LocationData(2, "Critical", "Donald"), + # LocationName.DonaldStarting2: LocationData(2, "Critical", "Donald"), } Goofy_Checks = { - LocationName.GoofyBarbossa: LocationData(0x1302BA, 21, "Double Get Bonus", "Goofy", 3), - LocationName.GoofyBarbossaGetBonus: LocationData(0x1302BB, 21, "Second Get Bonus", "Goofy", 3), - LocationName.GoofyGrimReaper1: LocationData(0x1302BC, 59, "Get Bonus", "Goofy", 3), - LocationName.GoofyHostileProgram: LocationData(0x1302BD, 31, "Get Bonus", "Goofy", 3), - LocationName.GoofyHyenas1: LocationData(0x1302BE, 49, "Get Bonus", "Goofy", 3), - LocationName.GoofyHyenas2: LocationData(0x1302BF, 50, "Get Bonus", "Goofy", 3), - LocationName.GoofyLock: LocationData(0x1302C0, 40, "Get Bonus", "Goofy", 3), - LocationName.GoofyOogieBoogie: LocationData(0x1302C1, 19, "Get Bonus", "Goofy", 3), - LocationName.GoofyPeteOC: LocationData(0x1302C2, 6, "Get Bonus", "Goofy", 3), - LocationName.GoofyFuturePete: LocationData(0x1302C3, 17, "Get Bonus", "Goofy", 3), - LocationName.GoofyShanYu: LocationData(0x1302C4, 9, "Get Bonus", "Goofy", 3), - LocationName.GoofyStormRider: LocationData(0x1302C5, 10, "Get Bonus", "Goofy", 3), - LocationName.GoofyBeast: LocationData(0x1302C6, 12, "Get Bonus", "Goofy", 3), - LocationName.GoofyInterceptorBarrels: LocationData(0x1302C7, 39, "Get Bonus", "Goofy", 3), - LocationName.GoofyTreasureRoom: LocationData(0x1302C8, 46, "Get Bonus", "Goofy", 3), - LocationName.GoofyZexion: LocationData(0x1302C9, 66, "Get Bonus", "Goofy", 3), + LocationName.GoofyBarbossa: LocationData(21, "Double Get Bonus", "Goofy", 3), + LocationName.GoofyBarbossaGetBonus: LocationData(21, "Second Get Bonus", "Goofy", 3), + LocationName.GoofyGrimReaper1: LocationData(59, "Get Bonus", "Goofy", 3), + LocationName.GoofyHostileProgram: LocationData(31, "Get Bonus", "Goofy", 3), + LocationName.GoofyHyenas1: LocationData(49, "Get Bonus", "Goofy", 3), + LocationName.GoofyHyenas2: LocationData(50, "Get Bonus", "Goofy", 3), + LocationName.GoofyLock: LocationData(40, "Get Bonus", "Goofy", 3), + LocationName.GoofyOogieBoogie: LocationData(19, "Get Bonus", "Goofy", 3), + LocationName.GoofyPeteOC: LocationData(6, "Get Bonus", "Goofy", 3), + LocationName.GoofyFuturePete: LocationData(17, "Get Bonus", "Goofy", 3), + LocationName.GoofyShanYu: LocationData(9, "Get Bonus", "Goofy", 3), + LocationName.GoofyStormRider: LocationData(10, "Get Bonus", "Goofy", 3), + LocationName.GoofyBeast: LocationData(12, "Get Bonus", "Goofy", 3), + LocationName.GoofyInterceptorBarrels: LocationData(39, "Get Bonus", "Goofy", 3), + LocationName.GoofyTreasureRoom: LocationData(46, "Get Bonus", "Goofy", 3), + LocationName.GoofyZexion: LocationData(66, "Get Bonus", "Goofy", 3), + + LocationName.AdamantShield: LocationData(100, "Keyblade", "Goofy"), + LocationName.AkashicRecord: LocationData(107, "Keyblade", "Goofy"), + LocationName.ChainGear: LocationData(101, "Keyblade", "Goofy"), + LocationName.DreamCloud: LocationData(104, "Keyblade", "Goofy"), + LocationName.FallingStar: LocationData(103, "Keyblade", "Goofy"), + LocationName.FrozenPride2: LocationData(158, "Keyblade", "Goofy"), + LocationName.GenjiShield: LocationData(106, "Keyblade", "Goofy"), + LocationName.KnightDefender: LocationData(105, "Keyblade", "Goofy"), + LocationName.KnightsShield: LocationData(99, "Keyblade", "Goofy"), + LocationName.MajesticMushroom: LocationData(161, "Keyblade", "Goofy"), + LocationName.MajesticMushroom2: LocationData(162, "Keyblade", "Goofy"), + LocationName.NobodyGuard: LocationData(108, "Keyblade", "Goofy"), + LocationName.OgreShield: LocationData(102, "Keyblade", "Goofy"), + LocationName.SaveTheKing2: LocationData(147, "Keyblade", "Goofy"), + LocationName.UltimateMushroom: LocationData(163, "Keyblade", "Goofy"), + # LocationName.GoofyStarting1: LocationData(3, "Critical", "Goofy"), + # LocationName.GoofyStarting2: LocationData(3, "Critical", "Goofy"), +} + +Atlantica_Checks = { + LocationName.UnderseaKingdomMap: LocationData(367, "Chest"), + LocationName.MysteriousAbyss: LocationData(287, "Chest"), # needs 2 magnets + LocationName.MusicalBlizzardElement: LocationData(279, "Chest"), # 2 magnets all thunders + LocationName.MusicalOrichalcumPlus: LocationData(538, "Chest"), # 2 magnets all thunders +} + +event_location_to_item = { + LocationName.HostileProgramEventLocation: ItemName.HostileProgramEvent, + LocationName.McpEventLocation: ItemName.McpEvent, + # LocationName.ASLarxeneEventLocation: ItemName.ASLarxeneEvent, + LocationName.DataLarxeneEventLocation: ItemName.DataLarxeneEvent, + LocationName.BarbosaEventLocation: ItemName.BarbosaEvent, + LocationName.GrimReaper1EventLocation: ItemName.GrimReaper1Event, + LocationName.GrimReaper2EventLocation: ItemName.GrimReaper2Event, + LocationName.DataLuxordEventLocation: ItemName.DataLuxordEvent, + LocationName.DataAxelEventLocation: ItemName.DataAxelEvent, + LocationName.CerberusEventLocation: ItemName.CerberusEvent, + LocationName.OlympusPeteEventLocation: ItemName.OlympusPeteEvent, + LocationName.HydraEventLocation: ItemName.HydraEvent, + LocationName.OcPainAndPanicCupEventLocation: ItemName.OcPainAndPanicCupEvent, + LocationName.OcCerberusCupEventLocation: ItemName.OcCerberusCupEvent, + LocationName.HadesEventLocation: ItemName.HadesEvent, + # LocationName.ASZexionEventLocation: ItemName.ASZexionEvent, + LocationName.DataZexionEventLocation: ItemName.DataZexionEvent, + LocationName.Oc2TitanCupEventLocation: ItemName.Oc2TitanCupEvent, + LocationName.Oc2GofCupEventLocation: ItemName.Oc2GofCupEvent, + # LocationName.Oc2CupsEventLocation: ItemName.Oc2CupsEventLocation, + LocationName.HadesCupEventLocations: ItemName.HadesCupEvents, + LocationName.PrisonKeeperEventLocation: ItemName.PrisonKeeperEvent, + LocationName.OogieBoogieEventLocation: ItemName.OogieBoogieEvent, + LocationName.ExperimentEventLocation: ItemName.ExperimentEvent, + # LocationName.ASVexenEventLocation: ItemName.ASVexenEvent, + LocationName.DataVexenEventLocation: ItemName.DataVexenEvent, + LocationName.ShanYuEventLocation: ItemName.ShanYuEvent, + LocationName.AnsemRikuEventLocation: ItemName.AnsemRikuEvent, + LocationName.StormRiderEventLocation: ItemName.StormRiderEvent, + LocationName.DataXigbarEventLocation: ItemName.DataXigbarEvent, + LocationName.RoxasEventLocation: ItemName.RoxasEvent, + LocationName.XigbarEventLocation: ItemName.XigbarEvent, + LocationName.LuxordEventLocation: ItemName.LuxordEvent, + LocationName.SaixEventLocation: ItemName.SaixEvent, + LocationName.XemnasEventLocation: ItemName.XemnasEvent, + LocationName.ArmoredXemnasEventLocation: ItemName.ArmoredXemnasEvent, + LocationName.ArmoredXemnas2EventLocation: ItemName.ArmoredXemnas2Event, + # LocationName.FinalXemnasEventLocation: ItemName.FinalXemnasEvent, + LocationName.DataXemnasEventLocation: ItemName.DataXemnasEvent, + LocationName.ThresholderEventLocation: ItemName.ThresholderEvent, + LocationName.BeastEventLocation: ItemName.BeastEvent, + LocationName.DarkThornEventLocation: ItemName.DarkThornEvent, + LocationName.XaldinEventLocation: ItemName.XaldinEvent, + LocationName.DataXaldinEventLocation: ItemName.DataXaldinEvent, + LocationName.TwinLordsEventLocation: ItemName.TwinLordsEvent, + LocationName.GenieJafarEventLocation: ItemName.GenieJafarEvent, + # LocationName.ASLexaeusEventLocation: ItemName.ASLexaeusEvent, + LocationName.DataLexaeusEventLocation: ItemName.DataLexaeusEvent, + LocationName.ScarEventLocation: ItemName.ScarEvent, + LocationName.GroundShakerEventLocation: ItemName.GroundShakerEvent, + LocationName.DataSaixEventLocation: ItemName.DataSaixEvent, + LocationName.HBDemyxEventLocation: ItemName.HBDemyxEvent, + LocationName.ThousandHeartlessEventLocation: ItemName.ThousandHeartlessEvent, + LocationName.Mushroom13EventLocation: ItemName.Mushroom13Event, + LocationName.SephiEventLocation: ItemName.SephiEvent, + LocationName.DataDemyxEventLocation: ItemName.DataDemyxEvent, + LocationName.CorFirstFightEventLocation: ItemName.CorFirstFightEvent, + LocationName.CorSecondFightEventLocation: ItemName.CorSecondFightEvent, + LocationName.TransportEventLocation: ItemName.TransportEvent, + LocationName.OldPeteEventLocation: ItemName.OldPeteEvent, + LocationName.FuturePeteEventLocation: ItemName.FuturePeteEvent, + # LocationName.ASMarluxiaEventLocation: ItemName.ASMarluxiaEvent, + LocationName.DataMarluxiaEventLocation: ItemName.DataMarluxiaEvent, + LocationName.TerraEventLocation: ItemName.TerraEvent, + LocationName.TwilightThornEventLocation: ItemName.TwilightThornEvent, + LocationName.Axel1EventLocation: ItemName.Axel1Event, + LocationName.Axel2EventLocation: ItemName.Axel2Event, + LocationName.DataRoxasEventLocation: ItemName.DataRoxasEvent, +} +all_weapon_slot = { + LocationName.FAKESlot, + LocationName.DetectionSaberSlot, + LocationName.EdgeofUltimaSlot, + LocationName.KingdomKeySlot, + LocationName.OathkeeperSlot, + LocationName.OblivionSlot, + LocationName.StarSeekerSlot, + LocationName.HiddenDragonSlot, + LocationName.HerosCrestSlot, + LocationName.MonochromeSlot, + LocationName.FollowtheWindSlot, + LocationName.CircleofLifeSlot, + LocationName.PhotonDebuggerSlot, + LocationName.GullWingSlot, + LocationName.RumblingRoseSlot, + LocationName.GuardianSoulSlot, + LocationName.WishingLampSlot, + LocationName.DecisivePumpkinSlot, + LocationName.SweetMemoriesSlot, + LocationName.MysteriousAbyssSlot, + LocationName.SleepingLionSlot, + LocationName.BondofFlameSlot, + LocationName.TwoBecomeOneSlot, + LocationName.FatalCrestSlot, + LocationName.FenrirSlot, + LocationName.UltimaWeaponSlot, + LocationName.WinnersProofSlot, + LocationName.PurebloodSlot, + + LocationName.Centurion2, + LocationName.CometStaff, + LocationName.HammerStaff, + LocationName.LordsBroom, + LocationName.MagesStaff, + LocationName.MeteorStaff, + LocationName.NobodyLance, + LocationName.PreciousMushroom, + LocationName.PreciousMushroom2, + LocationName.PremiumMushroom, + LocationName.RisingDragon, + LocationName.SaveTheQueen2, + LocationName.ShamansRelic, + LocationName.VictoryBell, + LocationName.WisdomWand, + + LocationName.AdamantShield, + LocationName.AkashicRecord, + LocationName.ChainGear, + LocationName.DreamCloud, + LocationName.FallingStar, + LocationName.FrozenPride2, + LocationName.GenjiShield, + LocationName.KnightDefender, + LocationName.KnightsShield, + LocationName.MajesticMushroom, + LocationName.MajesticMushroom2, + LocationName.NobodyGuard, + LocationName.OgreShield, + LocationName.SaveTheKing2, + LocationName.UltimateMushroom, } + +all_locations = { + **TWTNW_Checks, + **TT_Checks, + **STT_Checks, + **PL_Checks, + **HB_Checks, + **HT_Checks, + **PR_Checks, + **PR_Checks, + **SP_Checks, + **BC_Checks, + **Oc_Checks, + **HundredAcre_Checks, + **DC_Checks, + **AG_Checks, + **LoD_Checks, + **SoraLevels, + **Form_Checks, + **GoA_Checks, + **Keyblade_Slots, + **Donald_Checks, + **Goofy_Checks, + **Atlantica_Checks, + **Summon_Checks, +} - LocationName.AdamantShield: LocationData(0x1302CA, 100, "Keyblade", "Goofy"), - LocationName.AkashicRecord: LocationData(0x1302CB, 107, "Keyblade", "Goofy"), - LocationName.ChainGear: LocationData(0x1302CC, 101, "Keyblade", "Goofy"), - LocationName.DreamCloud: LocationData(0x1302CD, 104, "Keyblade", "Goofy"), - LocationName.FallingStar: LocationData(0x1302CE, 103, "Keyblade", "Goofy"), - LocationName.FrozenPride2: LocationData(0x1302CF, 158, "Keyblade", "Goofy"), - LocationName.GenjiShield: LocationData(0x1302D0, 106, "Keyblade", "Goofy"), - LocationName.KnightDefender: LocationData(0x1302D1, 105, "Keyblade", "Goofy"), - LocationName.KnightsShield: LocationData(0x1302D2, 99, "Keyblade", "Goofy"), - LocationName.MajesticMushroom: LocationData(0x1302D3, 161, "Keyblade", "Goofy"), - LocationName.MajesticMushroom2: LocationData(0x1302D4, 162, "Keyblade", "Goofy"), - LocationName.NobodyGuard: LocationData(0x1302D5, 108, "Keyblade", "Goofy"), - LocationName.OgreShield: LocationData(0x1302D6, 102, "Keyblade", "Goofy"), - LocationName.SaveTheKing2: LocationData(0x1302D7, 147, "Keyblade", "Goofy"), - LocationName.UltimateMushroom: LocationData(0x1302D8, 163, "Keyblade", "Goofy"), - LocationName.GoofyStarting1: LocationData(0x1302D9, 3, "Critical", "Goofy"), - LocationName.GoofyStarting2: LocationData(0x1302DA, 3, "Critical", "Goofy"), +popups_set = { + LocationName.SweetMemories, + LocationName.SpookyCaveMap, + LocationName.StarryHillCureElement, + LocationName.StarryHillOrichalcumPlus, + LocationName.AgrabahMap, + LocationName.LampCharm, + LocationName.WishingLamp, + LocationName.DarkThornCureElement, + LocationName.RumblingRose, + LocationName.CastleWallsMap, + LocationName.SecretAnsemReport4, + LocationName.DisneyCastleMap, + LocationName.WindowofTimeMap, + LocationName.Monochrome, + LocationName.WisdomForm, + LocationName.LingeringWillProofofConnection, + LocationName.LingeringWillManifestIllusion, + LocationName.OogieBoogieMagnetElement, + LocationName.Present, + LocationName.DecoyPresents, + LocationName.DecisivePumpkin, + LocationName.MarketplaceMap, + LocationName.MerlinsHouseMembershipCard, + LocationName.MerlinsHouseBlizzardElement, + LocationName.BaileySecretAnsemReport7, + LocationName.BaseballCharm, + LocationName.AnsemsStudyMasterForm, + LocationName.AnsemsStudySkillRecipe, + LocationName.AnsemsStudySleepingLion, + LocationName.FFFightsCureElement, + LocationName.ThousandHeartlessSecretAnsemReport1, + LocationName.ThousandHeartlessIceCream, + LocationName.ThousandHeartlessPicture, + LocationName.WinnersProof, + LocationName.ProofofPeace, + LocationName.SephirothFenrir, + LocationName.EncampmentAreaMap, + LocationName.Mission3, + LocationName.VillageCaveAreaMap, + LocationName.HiddenDragon, + LocationName.ColiseumMap, + LocationName.SecretAnsemReport6, + LocationName.OlympusStone, + LocationName.HerosCrest, + LocationName.AuronsStatue, + LocationName.GuardianSoul, + LocationName.ProtectBeltPainandPanicCup, + LocationName.SerenityGemPainandPanicCup, + LocationName.RisingDragonCerberusCup, + LocationName.SerenityCrystalCerberusCup, + LocationName.GenjiShieldTitanCup, + LocationName.SkillfulRingTitanCup, + LocationName.FatalCrestGoddessofFateCup, + LocationName.OrichalcumPlusGoddessofFateCup, + LocationName.HadesCupTrophyParadoxCups, + LocationName.IsladeMuertaMap, + LocationName.FollowtheWind, + LocationName.SeadriftRowCursedMedallion, + LocationName.SeadriftRowShipGraveyardMap, + LocationName.SecretAnsemReport5, + LocationName.CircleofLife, + LocationName.ScarFireElement, + LocationName.TwilightTownMap, + LocationName.MunnyPouchOlette, + LocationName.JunkChampionBelt, + LocationName.JunkMedal, + LocationName.TheStruggleTrophy, + LocationName.NaminesSketches, + LocationName.MansionMap, + LocationName.PhotonDebugger, + LocationName.StationPlazaSecretAnsemReport2, + LocationName.MunnyPouchMickey, + LocationName.CrystalOrb, + LocationName.StarSeeker, + LocationName.ValorForm, + LocationName.SeifersTrophy, + LocationName.Oathkeeper, + LocationName.LimitForm, + LocationName.BeamSecretAnsemReport10, + LocationName.BetwixtandBetweenBondofFlame, + LocationName.TwoBecomeOne, + LocationName.RoxasSecretAnsemReport8, + LocationName.XigbarSecretAnsemReport3, + LocationName.Oblivion, + LocationName.CastleThatNeverWasMap, + LocationName.LuxordSecretAnsemReport9, + LocationName.SaixSecretAnsemReport12, + LocationName.PreXemnas1SecretAnsemReport11, + LocationName.Xemnas1SecretAnsemReport13, + LocationName.XemnasDataPowerBoost, + LocationName.AxelDataMagicBoost, + LocationName.RoxasDataMagicBoost, + LocationName.SaixDataDefenseBoost, + LocationName.DemyxDataAPBoost, + LocationName.LuxordDataAPBoost, + LocationName.VexenDataLostIllusion, + LocationName.LarxeneDataLostIllusion, + LocationName.XaldinDataDefenseBoost, + LocationName.MarluxiaDataLostIllusion, + LocationName.LexaeusDataLostIllusion, + LocationName.XigbarDataDefenseBoost, + LocationName.VexenASRoadtoDiscovery, + LocationName.LarxeneASCloakedThunder, + LocationName.ZexionASBookofShadows, + LocationName.ZexionDataLostIllusion, + LocationName.LexaeusASStrengthBeyondStrength, + LocationName.MarluxiaASEternalBlossom, + LocationName.UnderseaKingdomMap, + LocationName.MysteriousAbyss, + LocationName.MusicalBlizzardElement, + LocationName.MusicalOrichalcumPlus, } exclusion_table = { - "Popups": { - LocationName.SweetMemories, - LocationName.SpookyCaveMap, - LocationName.StarryHillCureElement, - LocationName.StarryHillOrichalcumPlus, - LocationName.AgrabahMap, - LocationName.LampCharm, - LocationName.WishingLamp, - LocationName.DarkThornCureElement, - LocationName.RumblingRose, - LocationName.CastleWallsMap, - LocationName.SecretAnsemReport4, - LocationName.DisneyCastleMap, - LocationName.WindowofTimeMap, - LocationName.Monochrome, - LocationName.WisdomForm, + "SuperBosses": { + LocationName.LingeringWillBonus, LocationName.LingeringWillProofofConnection, LocationName.LingeringWillManifestIllusion, - LocationName.OogieBoogieMagnetElement, - LocationName.Present, - LocationName.DecoyPresents, - LocationName.DecisivePumpkin, - LocationName.MarketplaceMap, - LocationName.MerlinsHouseMembershipCard, - LocationName.MerlinsHouseBlizzardElement, - LocationName.BaileySecretAnsemReport7, - LocationName.BaseballCharm, - LocationName.AnsemsStudyMasterForm, - LocationName.AnsemsStudySkillRecipe, - LocationName.AnsemsStudySleepingLion, - LocationName.FFFightsCureElement, - LocationName.ThousandHeartlessSecretAnsemReport1, - LocationName.ThousandHeartlessIceCream, - LocationName.ThousandHeartlessPicture, - LocationName.WinnersProof, - LocationName.ProofofPeace, + LocationName.SephirothBonus, LocationName.SephirothFenrir, - LocationName.EncampmentAreaMap, - LocationName.Mission3, - LocationName.VillageCaveAreaMap, - LocationName.HiddenDragon, - LocationName.ColiseumMap, - LocationName.SecretAnsemReport6, - LocationName.OlympusStone, - LocationName.HerosCrest, - LocationName.AuronsStatue, - LocationName.GuardianSoul, - LocationName.ProtectBeltPainandPanicCup, - LocationName.SerenityGemPainandPanicCup, - LocationName.RisingDragonCerberusCup, - LocationName.SerenityCrystalCerberusCup, - LocationName.GenjiShieldTitanCup, - LocationName.SkillfulRingTitanCup, - LocationName.FatalCrestGoddessofFateCup, - LocationName.OrichalcumPlusGoddessofFateCup, - LocationName.HadesCupTrophyParadoxCups, - LocationName.IsladeMuertaMap, - LocationName.FollowtheWind, - LocationName.SeadriftRowCursedMedallion, - LocationName.SeadriftRowShipGraveyardMap, - LocationName.SecretAnsemReport5, - LocationName.CircleofLife, - LocationName.ScarFireElement, - LocationName.TwilightTownMap, - LocationName.MunnyPouchOlette, - LocationName.JunkChampionBelt, - LocationName.JunkMedal, - LocationName.TheStruggleTrophy, - LocationName.NaminesSketches, - LocationName.MansionMap, - LocationName.PhotonDebugger, - LocationName.StationPlazaSecretAnsemReport2, - LocationName.MunnyPouchMickey, - LocationName.CrystalOrb, - LocationName.StarSeeker, - LocationName.ValorForm, - LocationName.SeifersTrophy, - LocationName.Oathkeeper, - LocationName.LimitForm, - LocationName.BeamSecretAnsemReport10, - LocationName.BetwixtandBetweenBondofFlame, - LocationName.TwoBecomeOne, - LocationName.RoxasSecretAnsemReport8, - LocationName.XigbarSecretAnsemReport3, - LocationName.Oblivion, - LocationName.CastleThatNeverWasMap, - LocationName.LuxordSecretAnsemReport9, - LocationName.SaixSecretAnsemReport12, - LocationName.PreXemnas1SecretAnsemReport11, - LocationName.Xemnas1SecretAnsemReport13, - LocationName.XemnasDataPowerBoost, - LocationName.AxelDataMagicBoost, - LocationName.RoxasDataMagicBoost, - LocationName.SaixDataDefenseBoost, - LocationName.DemyxDataAPBoost, - LocationName.LuxordDataAPBoost, - LocationName.VexenDataLostIllusion, - LocationName.LarxeneDataLostIllusion, - LocationName.XaldinDataDefenseBoost, - LocationName.MarluxiaDataLostIllusion, - LocationName.LexaeusDataLostIllusion, - LocationName.XigbarDataDefenseBoost, - LocationName.VexenASRoadtoDiscovery, - LocationName.LarxeneASCloakedThunder, - LocationName.ZexionASBookofShadows, - LocationName.ZexionDataLostIllusion, - LocationName.LexaeusASStrengthBeyondStrength, - LocationName.MarluxiaASEternalBlossom - }, - "Datas": { LocationName.XemnasDataPowerBoost, LocationName.AxelDataMagicBoost, LocationName.RoxasDataMagicBoost, @@ -985,13 +1106,7 @@ class LocationData(typing.NamedTuple): LocationName.ZexionDataLostIllusion, LocationName.ZexionBonus, LocationName.ZexionASBookofShadows, - }, - "SuperBosses": { - LocationName.LingeringWillBonus, - LocationName.LingeringWillProofofConnection, - LocationName.LingeringWillManifestIllusion, - LocationName.SephirothBonus, - LocationName.SephirothFenrir, + LocationName.GoofyZexion, }, # 23 checks spread through 50 levels @@ -1148,15 +1263,6 @@ class LocationData(typing.NamedTuple): LocationName.Lvl98, LocationName.Lvl99, }, - "Critical": { - LocationName.Crit_1, - LocationName.Crit_2, - LocationName.Crit_3, - LocationName.Crit_4, - LocationName.Crit_5, - LocationName.Crit_6, - LocationName.Crit_7, - }, "Hitlist": [ LocationName.XemnasDataPowerBoost, LocationName.AxelDataMagicBoost, @@ -1179,9 +1285,11 @@ class LocationData(typing.NamedTuple): LocationName.Limitlvl7, LocationName.Masterlvl7, LocationName.Finallvl7, + LocationName.Summonlvl7, LocationName.TransporttoRemembrance, LocationName.OrichalcumPlusGoddessofFateCup, LocationName.HadesCupTrophyParadoxCups, + LocationName.MusicalOrichalcumPlus, ], "Cups": { LocationName.ProtectBeltPainandPanicCup, @@ -1194,6 +1302,12 @@ class LocationData(typing.NamedTuple): LocationName.OrichalcumPlusGoddessofFateCup, LocationName.HadesCupTrophyParadoxCups, }, + "Atlantica": { + LocationName.MysteriousAbyss, + LocationName.MusicalOrichalcumPlus, + LocationName.MusicalBlizzardElement, + LocationName.UnderseaKingdomMap, + }, "WeaponSlots": { LocationName.FAKESlot: ItemName.ValorForm, LocationName.DetectionSaberSlot: ItemName.MasterForm, @@ -1244,536 +1358,6 @@ class LocationData(typing.NamedTuple): LocationName.Centurion2: ItemName.Centurion2, }, "Chests": { - LocationName.BambooGroveDarkShard, - LocationName.BambooGroveEther, - LocationName.BambooGroveMythrilShard, - LocationName.CheckpointHiPotion, - LocationName.CheckpointMythrilShard, - LocationName.MountainTrailLightningShard, - LocationName.MountainTrailRecoveryRecipe, - LocationName.MountainTrailEther, - LocationName.MountainTrailMythrilShard, - LocationName.VillageCaveAPBoost, - LocationName.VillageCaveDarkShard, - LocationName.RidgeFrostShard, - LocationName.RidgeAPBoost, - LocationName.ThroneRoomTornPages, - LocationName.ThroneRoomPalaceMap, - LocationName.ThroneRoomAPBoost, - LocationName.ThroneRoomQueenRecipe, - LocationName.ThroneRoomAPBoost2, - LocationName.ThroneRoomOgreShield, - LocationName.ThroneRoomMythrilCrystal, - LocationName.ThroneRoomOrichalcum, - LocationName.AgrabahDarkShard, - LocationName.AgrabahMythrilShard, - LocationName.AgrabahHiPotion, - LocationName.AgrabahAPBoost, - LocationName.AgrabahMythrilStone, - LocationName.AgrabahMythrilShard2, - LocationName.AgrabahSerenityShard, - LocationName.BazaarMythrilGem, - LocationName.BazaarPowerShard, - LocationName.BazaarHiPotion, - LocationName.BazaarAPBoost, - LocationName.BazaarMythrilShard, - LocationName.PalaceWallsSkillRing, - LocationName.PalaceWallsMythrilStone, - LocationName.CaveEntrancePowerStone, - LocationName.CaveEntranceMythrilShard, - LocationName.ValleyofStoneMythrilStone, - LocationName.ValleyofStoneAPBoost, - LocationName.ValleyofStoneMythrilShard, - LocationName.ValleyofStoneHiPotion, - LocationName.ChasmofChallengesCaveofWondersMap, - LocationName.ChasmofChallengesAPBoost, - LocationName.TreasureRoomAPBoost, - LocationName.TreasureRoomSerenityGem, - LocationName.RuinedChamberTornPages, - LocationName.RuinedChamberRuinsMap, - LocationName.DCCourtyardMythrilShard, - LocationName.DCCourtyardStarRecipe, - LocationName.DCCourtyardAPBoost, - LocationName.DCCourtyardMythrilStone, - LocationName.DCCourtyardBlazingStone, - LocationName.DCCourtyardBlazingShard, - LocationName.DCCourtyardMythrilShard2, - LocationName.LibraryTornPages, - LocationName.CornerstoneHillMap, - LocationName.CornerstoneHillFrostShard, - LocationName.PierMythrilShard, - LocationName.PierHiPotion, - LocationName.WaterwayMythrilStone, - LocationName.WaterwayAPBoost, - LocationName.WaterwayFrostStone, - LocationName.PoohsHouse100AcreWoodMap, - LocationName.PoohsHouseAPBoost, - LocationName.PoohsHouseMythrilStone, - LocationName.PigletsHouseDefenseBoost, - LocationName.PigletsHouseAPBoost, - LocationName.PigletsHouseMythrilGem, - LocationName.RabbitsHouseDrawRing, - LocationName.RabbitsHouseMythrilCrystal, - LocationName.RabbitsHouseAPBoost, - LocationName.KangasHouseMagicBoost, - LocationName.KangasHouseAPBoost, - LocationName.KangasHouseOrichalcum, - LocationName.SpookyCaveMythrilGem, - LocationName.SpookyCaveAPBoost, - LocationName.SpookyCaveOrichalcum, - LocationName.SpookyCaveGuardRecipe, - LocationName.SpookyCaveMythrilCrystal, - LocationName.SpookyCaveAPBoost2, - LocationName.StarryHillCosmicRing, - LocationName.StarryHillStyleRecipe, - LocationName.RampartNavalMap, - LocationName.RampartMythrilStone, - LocationName.RampartDarkShard, - LocationName.TownDarkStone, - LocationName.TownAPBoost, - LocationName.TownMythrilShard, - LocationName.TownMythrilGem, - LocationName.CaveMouthBrightShard, - LocationName.CaveMouthMythrilShard, - LocationName.PowderStoreAPBoost1, - LocationName.PowderStoreAPBoost2, - LocationName.MoonlightNookMythrilShard, - LocationName.MoonlightNookSerenityGem, - LocationName.MoonlightNookPowerStone, - LocationName.InterceptorsHoldFeatherCharm, - LocationName.SeadriftKeepAPBoost, - LocationName.SeadriftKeepOrichalcum, - LocationName.SeadriftKeepMeteorStaff, - LocationName.SeadriftRowSerenityGem, - LocationName.SeadriftRowKingRecipe, - LocationName.SeadriftRowMythrilCrystal, - LocationName.PassageMythrilShard, - LocationName.PassageMythrilStone, - LocationName.PassageEther, - LocationName.PassageAPBoost, - LocationName.PassageHiPotion, - LocationName.InnerChamberUnderworldMap, - LocationName.InnerChamberMythrilShard, - LocationName.UnderworldEntrancePowerBoost, - LocationName.CavernsEntranceLucidShard, - LocationName.CavernsEntranceAPBoost, - LocationName.CavernsEntranceMythrilShard, - LocationName.TheLostRoadBrightShard, - LocationName.TheLostRoadEther, - LocationName.TheLostRoadMythrilShard, - LocationName.TheLostRoadMythrilStone, - LocationName.AtriumLucidStone, - LocationName.AtriumAPBoost, - LocationName.TheLockCavernsMap, - LocationName.TheLockMythrilShard, - LocationName.TheLockAPBoost, - LocationName.BCCourtyardAPBoost, - LocationName.BCCourtyardHiPotion, - LocationName.BCCourtyardMythrilShard, - LocationName.BellesRoomCastleMap, - LocationName.BellesRoomMegaRecipe, - LocationName.TheEastWingMythrilShard, - LocationName.TheEastWingTent, - LocationName.TheWestHallHiPotion, - LocationName.TheWestHallPowerShard, - LocationName.TheWestHallMythrilShard2, - LocationName.TheWestHallBrightStone, - LocationName.TheWestHallMythrilShard, - LocationName.DungeonBasementMap, - LocationName.DungeonAPBoost, - LocationName.SecretPassageMythrilShard, - LocationName.SecretPassageHiPotion, - LocationName.SecretPassageLucidShard, - LocationName.TheWestHallAPBoostPostDungeon, - LocationName.TheWestWingMythrilShard, - LocationName.TheWestWingTent, - LocationName.TheBeastsRoomBlazingShard, - LocationName.PitCellAreaMap, - LocationName.PitCellMythrilCrystal, - LocationName.CanyonDarkCrystal, - LocationName.CanyonMythrilStone, - LocationName.CanyonMythrilGem, - LocationName.CanyonFrostCrystal, - LocationName.HallwayPowerCrystal, - LocationName.HallwayAPBoost, - LocationName.CommunicationsRoomIOTowerMap, - LocationName.CommunicationsRoomGaiaBelt, - LocationName.CentralComputerCoreAPBoost, - LocationName.CentralComputerCoreOrichalcumPlus, - LocationName.CentralComputerCoreCosmicArts, - LocationName.CentralComputerCoreMap, - LocationName.GraveyardMythrilShard, - LocationName.GraveyardSerenityGem, - LocationName.FinklesteinsLabHalloweenTownMap, - LocationName.TownSquareMythrilStone, - LocationName.TownSquareEnergyShard, - LocationName.HinterlandsLightningShard, - LocationName.HinterlandsMythrilStone, - LocationName.HinterlandsAPBoost, - LocationName.CandyCaneLaneMegaPotion, - LocationName.CandyCaneLaneMythrilGem, - LocationName.CandyCaneLaneLightningStone, - LocationName.CandyCaneLaneMythrilStone, - LocationName.SantasHouseChristmasTownMap, - LocationName.SantasHouseAPBoost, - LocationName.BoroughDriveRecovery, - LocationName.BoroughAPBoost, - LocationName.BoroughHiPotion, - LocationName.BoroughMythrilShard, - LocationName.BoroughDarkShard, - LocationName.PosternCastlePerimeterMap, - LocationName.PosternMythrilGem, - LocationName.PosternAPBoost, - LocationName.CorridorsMythrilStone, - LocationName.CorridorsMythrilCrystal, - LocationName.CorridorsDarkCrystal, - LocationName.CorridorsAPBoost, - LocationName.AnsemsStudyUkuleleCharm, - LocationName.RestorationSiteMoonRecipe, - LocationName.RestorationSiteAPBoost, - LocationName.CoRDepthsAPBoost, - LocationName.CoRDepthsPowerCrystal, - LocationName.CoRDepthsFrostCrystal, - LocationName.CoRDepthsManifestIllusion, - LocationName.CoRDepthsAPBoost2, - LocationName.CoRMineshaftLowerLevelDepthsofRemembranceMap, - LocationName.CoRMineshaftLowerLevelAPBoost, - LocationName.CrystalFissureTornPages, - LocationName.CrystalFissureTheGreatMawMap, - LocationName.CrystalFissureEnergyCrystal, - LocationName.CrystalFissureAPBoost, - LocationName.PosternGullWing, - LocationName.HeartlessManufactoryCosmicChain, - LocationName.CoRDepthsUpperLevelRemembranceGem, - LocationName.CoRMiningAreaSerenityGem, - LocationName.CoRMiningAreaAPBoost, - LocationName.CoRMiningAreaSerenityCrystal, - LocationName.CoRMiningAreaManifestIllusion, - LocationName.CoRMiningAreaSerenityGem2, - LocationName.CoRMiningAreaDarkRemembranceMap, - LocationName.CoRMineshaftMidLevelPowerBoost, - LocationName.CoREngineChamberSerenityCrystal, - LocationName.CoREngineChamberRemembranceCrystal, - LocationName.CoREngineChamberAPBoost, - LocationName.CoREngineChamberManifestIllusion, - LocationName.CoRMineshaftUpperLevelMagicBoost, - LocationName.CoRMineshaftUpperLevelAPBoost, - LocationName.GorgeSavannahMap, - LocationName.GorgeDarkGem, - LocationName.GorgeMythrilStone, - LocationName.ElephantGraveyardFrostGem, - LocationName.ElephantGraveyardMythrilStone, - LocationName.ElephantGraveyardBrightStone, - LocationName.ElephantGraveyardAPBoost, - LocationName.ElephantGraveyardMythrilShard, - LocationName.PrideRockMap, - LocationName.PrideRockMythrilStone, - LocationName.PrideRockSerenityCrystal, - LocationName.WildebeestValleyEnergyStone, - LocationName.WildebeestValleyAPBoost, - LocationName.WildebeestValleyMythrilGem, - LocationName.WildebeestValleyMythrilStone, - LocationName.WildebeestValleyLucidGem, - LocationName.WastelandsMythrilShard, - LocationName.WastelandsSerenityGem, - LocationName.WastelandsMythrilStone, - LocationName.JungleSerenityGem, - LocationName.JungleMythrilStone, - LocationName.JungleSerenityCrystal, - LocationName.OasisMap, - LocationName.OasisTornPages, - LocationName.OasisAPBoost, - LocationName.StationofCallingPotion, - LocationName.CentralStationPotion1, - LocationName.STTCentralStationHiPotion, - LocationName.CentralStationPotion2, - LocationName.SunsetTerraceAbilityRing, - LocationName.SunsetTerraceHiPotion, - LocationName.SunsetTerracePotion1, - LocationName.SunsetTerracePotion2, - LocationName.MansionFoyerHiPotion, - LocationName.MansionFoyerPotion1, - LocationName.MansionFoyerPotion2, - LocationName.MansionDiningRoomElvenBandanna, - LocationName.MansionDiningRoomPotion, - LocationName.MansionLibraryHiPotion, - LocationName.MansionBasementCorridorHiPotion, - LocationName.OldMansionPotion, - LocationName.OldMansionMythrilShard, - LocationName.TheWoodsPotion, - LocationName.TheWoodsMythrilShard, - LocationName.TheWoodsHiPotion, - LocationName.TramCommonHiPotion, - LocationName.TramCommonAPBoost, - LocationName.TramCommonTent, - LocationName.TramCommonMythrilShard1, - LocationName.TramCommonPotion1, - LocationName.TramCommonMythrilShard2, - LocationName.TramCommonPotion2, - LocationName.CentralStationTent, - LocationName.TTCentralStationHiPotion, - LocationName.CentralStationMythrilShard, - LocationName.TheTowerPotion, - LocationName.TheTowerHiPotion, - LocationName.TheTowerEther, - LocationName.TowerEntrywayEther, - LocationName.TowerEntrywayMythrilShard, - LocationName.SorcerersLoftTowerMap, - LocationName.TowerWardrobeMythrilStone, - LocationName.UndergroundConcourseMythrilGem, - LocationName.UndergroundConcourseAPBoost, - LocationName.UndergroundConcourseMythrilCrystal, - LocationName.UndergroundConcourseOrichalcum, - LocationName.TunnelwayOrichalcum, - LocationName.TunnelwayMythrilCrystal, - LocationName.SunsetTerraceOrichalcumPlus, - LocationName.SunsetTerraceMythrilShard, - LocationName.SunsetTerraceMythrilCrystal, - LocationName.SunsetTerraceAPBoost, - LocationName.MansionFoyerMythrilCrystal, - LocationName.MansionFoyerMythrilStone, - LocationName.MansionFoyerSerenityCrystal, - LocationName.MansionDiningRoomMythrilCrystal, - LocationName.MansionDiningRoomMythrilStone, - LocationName.MansionLibraryOrichalcum, - LocationName.MansionBasementCorridorUltimateRecipe, - LocationName.FragmentCrossingMythrilStone, - LocationName.FragmentCrossingMythrilCrystal, - LocationName.FragmentCrossingAPBoost, - LocationName.FragmentCrossingOrichalcum, - LocationName.MemorysSkyscaperMythrilCrystal, - LocationName.MemorysSkyscaperAPBoost, - LocationName.MemorysSkyscaperMythrilStone, - LocationName.TheBrinkofDespairDarkCityMap, - LocationName.TheBrinkofDespairOrichalcumPlus, - LocationName.NothingsCallMythrilGem, - LocationName.NothingsCallOrichalcum, - LocationName.TwilightsViewCosmicBelt, - LocationName.NaughtsSkywayMythrilGem, - LocationName.NaughtsSkywayOrichalcum, - LocationName.NaughtsSkywayMythrilCrystal, - LocationName.RuinandCreationsPassageMythrilStone, - LocationName.RuinandCreationsPassageAPBoost, - LocationName.RuinandCreationsPassageMythrilCrystal, - LocationName.RuinandCreationsPassageOrichalcum, - LocationName.GardenofAssemblageMap, - LocationName.GoALostIllusion, - LocationName.ProofofNonexistence, + location for location, data in all_locations.items() if location not in event_location_to_item.keys() and location not in popups_set and location != LocationName.StationofSerenityPotion and data.yml == "Chest" } } - -AllWeaponSlot = { - LocationName.FAKESlot, - LocationName.DetectionSaberSlot, - LocationName.EdgeofUltimaSlot, - LocationName.KingdomKeySlot, - LocationName.OathkeeperSlot, - LocationName.OblivionSlot, - LocationName.StarSeekerSlot, - LocationName.HiddenDragonSlot, - LocationName.HerosCrestSlot, - LocationName.MonochromeSlot, - LocationName.FollowtheWindSlot, - LocationName.CircleofLifeSlot, - LocationName.PhotonDebuggerSlot, - LocationName.GullWingSlot, - LocationName.RumblingRoseSlot, - LocationName.GuardianSoulSlot, - LocationName.WishingLampSlot, - LocationName.DecisivePumpkinSlot, - LocationName.SweetMemoriesSlot, - LocationName.MysteriousAbyssSlot, - LocationName.SleepingLionSlot, - LocationName.BondofFlameSlot, - LocationName.TwoBecomeOneSlot, - LocationName.FatalCrestSlot, - LocationName.FenrirSlot, - LocationName.UltimaWeaponSlot, - LocationName.WinnersProofSlot, - LocationName.PurebloodSlot, - LocationName.Centurion2, - LocationName.CometStaff, - LocationName.HammerStaff, - LocationName.LordsBroom, - LocationName.MagesStaff, - LocationName.MeteorStaff, - LocationName.NobodyLance, - LocationName.PreciousMushroom, - LocationName.PreciousMushroom2, - LocationName.PremiumMushroom, - LocationName.RisingDragon, - LocationName.SaveTheQueen2, - LocationName.ShamansRelic, - LocationName.VictoryBell, - LocationName.WisdomWand, - - LocationName.AdamantShield, - LocationName.AkashicRecord, - LocationName.ChainGear, - LocationName.DreamCloud, - LocationName.FallingStar, - LocationName.FrozenPride2, - LocationName.GenjiShield, - LocationName.KnightDefender, - LocationName.KnightsShield, - LocationName.MajesticMushroom, - LocationName.MajesticMushroom2, - LocationName.NobodyGuard, - LocationName.OgreShield, - LocationName.SaveTheKing2, - LocationName.UltimateMushroom, } -RegionTable = { - "FirstVisits": { - RegionName.LoD_Region, - RegionName.Ag_Region, - RegionName.Dc_Region, - RegionName.Pr_Region, - RegionName.Oc_Region, - RegionName.Bc_Region, - RegionName.Sp_Region, - RegionName.Ht_Region, - RegionName.Hb_Region, - RegionName.Pl_Region, - RegionName.STT_Region, - RegionName.TT_Region, - RegionName.Twtnw_Region, - }, - "SecondVisits": { - RegionName.LoD2_Region, - RegionName.Ag2_Region, - RegionName.Tr_Region, - RegionName.Pr2_Region, - RegionName.Oc2_Region, - RegionName.Bc2_Region, - RegionName.Sp2_Region, - RegionName.Ht2_Region, - RegionName.Hb2_Region, - RegionName.Pl2_Region, - RegionName.STT_Region, - RegionName.Twtnw2_Region, - }, - "ValorRegion": { - RegionName.LoD_Region, - RegionName.Ag_Region, - RegionName.Dc_Region, - RegionName.Pr_Region, - RegionName.Oc_Region, - RegionName.Bc_Region, - RegionName.Sp_Region, - RegionName.Ht_Region, - RegionName.Hb_Region, - RegionName.TT_Region, - RegionName.Twtnw_Region, - }, - "WisdomRegion": { - RegionName.LoD_Region, - RegionName.Ag_Region, - RegionName.Dc_Region, - RegionName.Pr_Region, - RegionName.Oc_Region, - RegionName.Bc_Region, - RegionName.Sp_Region, - RegionName.Ht_Region, - RegionName.Hb_Region, - RegionName.TT_Region, - RegionName.Twtnw_Region, - }, - "LimitRegion": { - RegionName.LoD_Region, - RegionName.Ag_Region, - RegionName.Dc_Region, - RegionName.Pr_Region, - RegionName.Oc_Region, - RegionName.Bc_Region, - RegionName.Sp_Region, - RegionName.Ht_Region, - RegionName.Hb_Region, - RegionName.TT_Region, - RegionName.Twtnw_Region, - RegionName.STT_Region, - }, - "MasterRegion": { - RegionName.LoD_Region, - RegionName.Ag_Region, - RegionName.Dc_Region, - RegionName.Pr_Region, - RegionName.Oc_Region, - RegionName.Bc_Region, - RegionName.Sp_Region, - RegionName.Ht_Region, - RegionName.Hb_Region, - RegionName.TT_Region, - RegionName.Twtnw_Region, - }, # could add lod2 and bc2 as an option since those spawns are rng - "FinalRegion": { - RegionName.TT3_Region, - RegionName.Twtnw_PostRoxas, - RegionName.Twtnw2_Region, - } -} - -all_locations = { - **TWTNW_Checks, - **TWTNW2_Checks, - **TT_Checks, - **TT2_Checks, - **TT3_Checks, - **STT_Checks, - **PL_Checks, - **PL2_Checks, - **CoR_Checks, - **HB_Checks, - **HB2_Checks, - **HT_Checks, - **HT2_Checks, - **PR_Checks, - **PR2_Checks, - **PR_Checks, - **PR2_Checks, - **SP_Checks, - **SP2_Checks, - **BC_Checks, - **BC2_Checks, - **Oc_Checks, - **Oc2_Checks, - **Oc2Cups, - **HundredAcre1_Checks, - **HundredAcre2_Checks, - **HundredAcre3_Checks, - **HundredAcre4_Checks, - **HundredAcre5_Checks, - **HundredAcre6_Checks, - **DC_Checks, - **TR_Checks, - **AG_Checks, - **AG2_Checks, - **LoD_Checks, - **LoD2_Checks, - **SoraLevels, - **Form_Checks, - **GoA_Checks, - **Keyblade_Slots, - **Critical_Checks, - **Donald_Checks, - **Goofy_Checks, -} - -location_table = {} - - -def setup_locations(): - totallocation_table = {**TWTNW_Checks, **TWTNW2_Checks, **TT_Checks, **TT2_Checks, **TT3_Checks, **STT_Checks, - **PL_Checks, **PL2_Checks, **CoR_Checks, **HB_Checks, **HB2_Checks, - **PR_Checks, **PR2_Checks, **PR_Checks, **PR2_Checks, **SP_Checks, **SP2_Checks, **BC_Checks, - **BC2_Checks, **HT_Checks, **HT2_Checks, - **Oc_Checks, **Oc2_Checks, **Oc2Cups, **Critical_Checks, **Donald_Checks, **Goofy_Checks, - **HundredAcre1_Checks, **HundredAcre2_Checks, **HundredAcre3_Checks, **HundredAcre4_Checks, - **HundredAcre5_Checks, **HundredAcre6_Checks, - **DC_Checks, **TR_Checks, **AG_Checks, **AG2_Checks, **LoD_Checks, **LoD2_Checks, - **SoraLevels, - **Form_Checks, **GoA_Checks, **Keyblade_Slots} - return totallocation_table - - -lookup_id_to_Location: typing.Dict[int, str] = {data.code: item_name for item_name, data in location_table.items() if - data.code} diff --git a/worlds/kh2/Logic.py b/worlds/kh2/Logic.py new file mode 100644 index 000000000000..1f13aa5f029c --- /dev/null +++ b/worlds/kh2/Logic.py @@ -0,0 +1,642 @@ +from .Names import ItemName, RegionName, LocationName + +# this file contains the dicts,lists and sets used for making rules in rules.py +base_tools = [ + ItemName.FinishingPlus, + ItemName.Guard, + ItemName.AerialRecovery +] +gap_closer = [ + ItemName.SlideDash, + ItemName.FlashStep +] +defensive_tool = [ + ItemName.ReflectElement, + ItemName.Guard +] +form_list = [ + ItemName.ValorForm, + ItemName.WisdomForm, + ItemName.LimitForm, + ItemName.MasterForm, + ItemName.FinalForm +] +form_list_without_final = [ + ItemName.ValorForm, + ItemName.WisdomForm, + ItemName.LimitForm, + ItemName.MasterForm +] +ground_finisher = [ + ItemName.GuardBreak, + ItemName.Explosion, + ItemName.FinishingLeap +] +party_limit = [ + ItemName.Fantasia, + ItemName.FlareForce, + ItemName.Teamwork, + ItemName.TornadoFusion +] +donald_limit = [ + ItemName.Fantasia, + ItemName.FlareForce +] +aerial_move = [ + ItemName.AerialDive, + ItemName.AerialSpiral, + ItemName.HorizontalSlash, + ItemName.AerialSweep, + ItemName.AerialFinish +] +level_3_form_loc = [ + LocationName.Valorlvl3, + LocationName.Wisdomlvl3, + LocationName.Limitlvl3, + LocationName.Masterlvl3, + LocationName.Finallvl3 +] +black_magic = [ + ItemName.FireElement, + ItemName.BlizzardElement, + ItemName.ThunderElement +] +magic = [ + ItemName.FireElement, + ItemName.BlizzardElement, + ItemName.ThunderElement, + ItemName.ReflectElement, + ItemName.CureElement, + ItemName.MagnetElement +] +summons = [ + ItemName.ChickenLittle, + ItemName.Stitch, + ItemName.Genie, + ItemName.PeterPan +] +three_proofs = [ + ItemName.ProofofConnection, + ItemName.ProofofPeace, + ItemName.ProofofNonexistence +] + +auto_form_dict = { + ItemName.FinalForm: ItemName.AutoFinal, + ItemName.MasterForm: ItemName.AutoMaster, + ItemName.LimitForm: ItemName.AutoLimit, + ItemName.WisdomForm: ItemName.AutoWisdom, + ItemName.ValorForm: ItemName.AutoValor, +} + +# could use comprehension for getting a list of the region objects but eh I like this more +drive_form_list = [RegionName.Valor, RegionName.Wisdom, RegionName.Limit, RegionName.Master, RegionName.Final, RegionName.Summon] + +easy_data_xigbar_tools = { + ItemName.FinishingPlus: 1, + ItemName.Guard: 1, + ItemName.AerialDive: 1, + ItemName.HorizontalSlash: 1, + ItemName.AirComboPlus: 2, + ItemName.FireElement: 3, + ItemName.ReflectElement: 3, +} +normal_data_xigbar_tools = { + ItemName.FinishingPlus: 1, + ItemName.Guard: 1, + ItemName.HorizontalSlash: 1, + ItemName.FireElement: 3, + ItemName.ReflectElement: 3, +} + +easy_data_lex_tools = { + ItemName.Guard: 1, + ItemName.FireElement: 3, + ItemName.ReflectElement: 2, + ItemName.SlideDash: 1, + ItemName.FlashStep: 1 +} +normal_data_lex_tools = { + ItemName.Guard: 1, + ItemName.FireElement: 3, + ItemName.ReflectElement: 1, +} + +easy_data_marluxia_tools = { + ItemName.Guard: 1, + ItemName.FireElement: 3, + ItemName.ReflectElement: 2, + ItemName.SlideDash: 1, + ItemName.FlashStep: 1, + ItemName.AerialRecovery: 1, +} +normal_data_marluxia_tools = { + ItemName.Guard: 1, + ItemName.FireElement: 3, + ItemName.ReflectElement: 1, + ItemName.AerialRecovery: 1, +} +easy_terra_tools = { + ItemName.SecondChance: 1, + ItemName.OnceMore: 1, + ItemName.SlideDash: 1, + ItemName.FlashStep: 1, + ItemName.Explosion: 1, + ItemName.ComboPlus: 2, + ItemName.FireElement: 3, + ItemName.Fantasia: 1, + ItemName.FlareForce: 1, + ItemName.ReflectElement: 1, + ItemName.Guard: 1, + ItemName.DodgeRoll: 3, + ItemName.AerialDodge: 3, + ItemName.Glide: 3 +} +normal_terra_tools = { + ItemName.SlideDash: 1, + ItemName.FlashStep: 1, + ItemName.Explosion: 1, + ItemName.ComboPlus: 2, + ItemName.Guard: 1, + ItemName.DodgeRoll: 2, + ItemName.AerialDodge: 2, + ItemName.Glide: 2 +} +hard_terra_tools = { + ItemName.Explosion: 1, + ItemName.ComboPlus: 2, + ItemName.DodgeRoll: 2, + ItemName.AerialDodge: 2, + ItemName.Glide: 2, + ItemName.Guard: 1 +} +easy_data_luxord_tools = { + ItemName.SlideDash: 1, + ItemName.FlashStep: 1, + ItemName.AerialDodge: 2, + ItemName.Glide: 2, + ItemName.ReflectElement: 3, + ItemName.Guard: 1, +} +easy_data_zexion = { + ItemName.FireElement: 3, + ItemName.SecondChance: 1, + ItemName.OnceMore: 1, + ItemName.Fantasia: 1, + ItemName.FlareForce: 1, + ItemName.ReflectElement: 3, + ItemName.Guard: 1, + ItemName.SlideDash: 1, + ItemName.FlashStep: 1, + ItemName.QuickRun: 3, +} +normal_data_zexion = { + ItemName.FireElement: 3, + ItemName.ReflectElement: 3, + ItemName.Guard: 1, + ItemName.QuickRun: 3 +} +hard_data_zexion = { + ItemName.FireElement: 2, + ItemName.ReflectElement: 1, + ItemName.QuickRun: 2, +} +easy_data_xaldin = { + ItemName.FireElement: 3, + ItemName.AirComboPlus: 2, + ItemName.FinishingPlus: 1, + ItemName.Guard: 1, + ItemName.ReflectElement: 3, + ItemName.FlareForce: 1, + ItemName.Fantasia: 1, + ItemName.HighJump: 3, + ItemName.AerialDodge: 3, + ItemName.Glide: 3, + ItemName.MagnetElement: 1, + ItemName.HorizontalSlash: 1, + ItemName.AerialDive: 1, + ItemName.AerialSpiral: 1, + ItemName.BerserkCharge: 1 +} +normal_data_xaldin = { + ItemName.FireElement: 3, + ItemName.FinishingPlus: 1, + ItemName.Guard: 1, + ItemName.ReflectElement: 3, + ItemName.FlareForce: 1, + ItemName.Fantasia: 1, + ItemName.HighJump: 3, + ItemName.AerialDodge: 3, + ItemName.Glide: 3, + ItemName.MagnetElement: 1, + ItemName.HorizontalSlash: 1, + ItemName.AerialDive: 1, + ItemName.AerialSpiral: 1, +} +hard_data_xaldin = { + ItemName.FireElement: 2, + ItemName.FinishingPlus: 1, + ItemName.Guard: 1, + ItemName.HighJump: 2, + ItemName.AerialDodge: 2, + ItemName.Glide: 2, + ItemName.MagnetElement: 1, + ItemName.AerialDive: 1 +} +easy_data_larxene = { + ItemName.FireElement: 3, + ItemName.SecondChance: 1, + ItemName.OnceMore: 1, + ItemName.Fantasia: 1, + ItemName.FlareForce: 1, + ItemName.ReflectElement: 3, + ItemName.Guard: 1, + ItemName.SlideDash: 1, + ItemName.FlashStep: 1, + ItemName.AerialDodge: 3, + ItemName.Glide: 3, + ItemName.GuardBreak: 1, + ItemName.Explosion: 1 +} +normal_data_larxene = { + ItemName.FireElement: 3, + ItemName.ReflectElement: 3, + ItemName.Guard: 1, + ItemName.AerialDodge: 3, + ItemName.Glide: 3, +} +hard_data_larxene = { + ItemName.FireElement: 2, + ItemName.ReflectElement: 1, + ItemName.Guard: 1, + ItemName.AerialDodge: 2, + ItemName.Glide: 2, +} +easy_data_vexen = { + ItemName.FireElement: 3, + ItemName.SecondChance: 1, + ItemName.OnceMore: 1, + ItemName.Fantasia: 1, + ItemName.FlareForce: 1, + ItemName.ReflectElement: 3, + ItemName.Guard: 1, + ItemName.SlideDash: 1, + ItemName.FlashStep: 1, + ItemName.AerialDodge: 3, + ItemName.Glide: 3, + ItemName.GuardBreak: 1, + ItemName.Explosion: 1, + ItemName.DodgeRoll: 3, + ItemName.QuickRun: 3, +} +normal_data_vexen = { + ItemName.FireElement: 3, + ItemName.ReflectElement: 3, + ItemName.Guard: 1, + ItemName.AerialDodge: 3, + ItemName.Glide: 3, + ItemName.DodgeRoll: 3, + ItemName.QuickRun: 3, +} +hard_data_vexen = { + ItemName.FireElement: 2, + ItemName.ReflectElement: 1, + ItemName.Guard: 1, + ItemName.AerialDodge: 2, + ItemName.Glide: 2, + ItemName.DodgeRoll: 3, + ItemName.QuickRun: 3, +} +easy_thousand_heartless_rules = { + ItemName.SecondChance: 1, + ItemName.OnceMore: 1, + ItemName.Guard: 1, + ItemName.MagnetElement: 2, +} +normal_thousand_heartless_rules = { + ItemName.LimitForm: 1, + ItemName.Guard: 1, +} +easy_data_demyx = { + ItemName.FormBoost: 1, + ItemName.ReflectElement: 2, + ItemName.FireElement: 3, + ItemName.FlareForce: 1, + ItemName.Guard: 1, + ItemName.SecondChance: 1, + ItemName.OnceMore: 1, + ItemName.FinishingPlus: 1, +} +normal_data_demyx = { + ItemName.ReflectElement: 2, + ItemName.FireElement: 3, + ItemName.FlareForce: 1, + ItemName.Guard: 1, + ItemName.FinishingPlus: 1, +} +hard_data_demyx = { + ItemName.ReflectElement: 1, + ItemName.FireElement: 2, + ItemName.FlareForce: 1, + ItemName.Guard: 1, + ItemName.FinishingPlus: 1, +} +easy_sephiroth_tools = { + ItemName.Guard: 1, + ItemName.ReflectElement: 3, + ItemName.SlideDash: 1, + ItemName.FlashStep: 1, + ItemName.GuardBreak: 1, + ItemName.Explosion: 1, + ItemName.DodgeRoll: 3, + ItemName.FinishingPlus: 1, + ItemName.SecondChance: 1, + ItemName.OnceMore: 1, +} +normal_sephiroth_tools = { + ItemName.Guard: 1, + ItemName.ReflectElement: 2, + ItemName.SlideDash: 1, + ItemName.FlashStep: 1, + ItemName.GuardBreak: 1, + ItemName.Explosion: 1, + ItemName.DodgeRoll: 3, + ItemName.FinishingPlus: 1, +} +hard_sephiroth_tools = { + ItemName.Guard: 1, + ItemName.ReflectElement: 1, + ItemName.DodgeRoll: 2, + ItemName.FinishingPlus: 1, +} + +not_hard_cor_tools_dict = { + ItemName.ReflectElement: 3, + ItemName.Stitch: 1, + ItemName.ChickenLittle: 1, + ItemName.MagnetElement: 2, + ItemName.Explosion: 1, + ItemName.FinishingLeap: 1, + ItemName.ThunderElement: 2, +} +transport_tools_dict = { + ItemName.ReflectElement: 3, + ItemName.Stitch: 1, + ItemName.ChickenLittle: 1, + ItemName.MagnetElement: 2, + ItemName.Explosion: 1, + ItemName.FinishingLeap: 1, + ItemName.ThunderElement: 3, + ItemName.Fantasia: 1, + ItemName.FlareForce: 1, + ItemName.Genie: 1, +} +easy_data_saix = { + ItemName.Guard: 1, + ItemName.SlideDash: 1, + ItemName.FlashStep: 1, + ItemName.ThunderElement: 1, + ItemName.BlizzardElement: 1, + ItemName.FlareForce: 1, + ItemName.Fantasia: 1, + ItemName.FireElement: 3, + ItemName.ReflectElement: 3, + ItemName.GuardBreak: 1, + ItemName.Explosion: 1, + ItemName.AerialDodge: 3, + ItemName.Glide: 3, + ItemName.SecondChance: 1, + ItemName.OnceMore: 1 +} +normal_data_saix = { + ItemName.Guard: 1, + ItemName.ThunderElement: 1, + ItemName.BlizzardElement: 1, + ItemName.FireElement: 3, + ItemName.ReflectElement: 3, + ItemName.AerialDodge: 3, + ItemName.Glide: 3, +} +hard_data_saix = { + ItemName.Guard: 1, + ItemName.BlizzardElement: 1, + ItemName.ReflectElement: 1, + ItemName.AerialDodge: 3, + ItemName.Glide: 3, +} +easy_data_roxas_tools = { + ItemName.Guard: 1, + ItemName.ReflectElement: 3, + ItemName.SlideDash: 1, + ItemName.FlashStep: 1, + ItemName.GuardBreak: 1, + ItemName.Explosion: 1, + ItemName.DodgeRoll: 3, + ItemName.FinishingPlus: 1, + ItemName.SecondChance: 1, + ItemName.OnceMore: 1, +} +normal_data_roxas_tools = { + ItemName.Guard: 1, + ItemName.ReflectElement: 2, + ItemName.SlideDash: 1, + ItemName.FlashStep: 1, + ItemName.GuardBreak: 1, + ItemName.Explosion: 1, + ItemName.DodgeRoll: 3, + ItemName.FinishingPlus: 1, +} +hard_data_roxas_tools = { + ItemName.Guard: 1, + ItemName.ReflectElement: 1, + ItemName.DodgeRoll: 2, + ItemName.FinishingPlus: 1, +} +easy_data_axel_tools = { + ItemName.Guard: 1, + ItemName.ReflectElement: 3, + ItemName.SlideDash: 1, + ItemName.FlashStep: 1, + ItemName.GuardBreak: 1, + ItemName.Explosion: 1, + ItemName.DodgeRoll: 3, + ItemName.FinishingPlus: 1, + ItemName.SecondChance: 1, + ItemName.OnceMore: 1, + ItemName.BlizzardElement: 3, +} +normal_data_axel_tools = { + ItemName.Guard: 1, + ItemName.ReflectElement: 2, + ItemName.SlideDash: 1, + ItemName.FlashStep: 1, + ItemName.GuardBreak: 1, + ItemName.Explosion: 1, + ItemName.DodgeRoll: 3, + ItemName.FinishingPlus: 1, + ItemName.BlizzardElement: 3, +} +hard_data_axel_tools = { + ItemName.Guard: 1, + ItemName.ReflectElement: 1, + ItemName.DodgeRoll: 2, + ItemName.FinishingPlus: 1, + ItemName.BlizzardElement: 2, +} +easy_roxas_tools = { + ItemName.AerialDodge: 1, + ItemName.Glide: 1, + ItemName.LimitForm: 1, + ItemName.ThunderElement: 1, + ItemName.ReflectElement: 2, + ItemName.GuardBreak: 1, + ItemName.SlideDash: 1, + ItemName.FlashStep: 1, + ItemName.FinishingPlus: 1, + ItemName.BlizzardElement: 1 +} +normal_roxas_tools = { + ItemName.ThunderElement: 1, + ItemName.ReflectElement: 2, + ItemName.GuardBreak: 1, + ItemName.SlideDash: 1, + ItemName.FlashStep: 1, + ItemName.FinishingPlus: 1, + ItemName.BlizzardElement: 1 +} +easy_xigbar_tools = { + ItemName.HorizontalSlash: 1, + ItemName.FireElement: 2, + ItemName.FinishingPlus: 1, + ItemName.Glide: 2, + ItemName.AerialDodge: 2, + ItemName.QuickRun: 2, + ItemName.ReflectElement: 1, + ItemName.Guard: 1, +} +normal_xigbar_tools = { + ItemName.FireElement: 2, + ItemName.FinishingPlus: 1, + ItemName.Glide: 2, + ItemName.AerialDodge: 2, + ItemName.QuickRun: 2, + ItemName.ReflectElement: 1, + ItemName.Guard: 1 +} +easy_luxord_tools = { + ItemName.AerialDodge: 1, + ItemName.Glide: 1, + ItemName.QuickRun: 2, + ItemName.Guard: 1, + ItemName.ReflectElement: 2, + ItemName.SlideDash: 1, + ItemName.FlashStep: 1, + ItemName.LimitForm: 1, +} +normal_luxord_tools = { + ItemName.AerialDodge: 1, + ItemName.Glide: 1, + ItemName.QuickRun: 2, + ItemName.Guard: 1, + ItemName.ReflectElement: 2, +} +easy_saix_tools = { + ItemName.AerialDodge: 1, + ItemName.Glide: 1, + ItemName.QuickRun: 2, + ItemName.Guard: 1, + ItemName.ReflectElement: 2, + ItemName.SlideDash: 1, + ItemName.FlashStep: 1, + ItemName.LimitForm: 1, +} +normal_saix_tools = { + ItemName.AerialDodge: 1, + ItemName.Glide: 1, + ItemName.QuickRun: 2, + ItemName.Guard: 1, + ItemName.ReflectElement: 2, +} +easy_xemnas_tools = { + ItemName.AerialDodge: 1, + ItemName.Glide: 1, + ItemName.QuickRun: 2, + ItemName.Guard: 1, + ItemName.ReflectElement: 2, + ItemName.SlideDash: 1, + ItemName.FlashStep: 1, + ItemName.LimitForm: 1, +} +normal_xemnas_tools = { + ItemName.AerialDodge: 1, + ItemName.Glide: 1, + ItemName.QuickRun: 2, + ItemName.Guard: 1, + ItemName.ReflectElement: 2, +} +easy_data_xemnas = { + ItemName.ComboMaster: 1, + ItemName.Slapshot: 1, + ItemName.ReflectElement: 3, + ItemName.SlideDash: 1, + ItemName.FlashStep: 1, + ItemName.FinishingPlus: 1, + ItemName.Guard: 1, + ItemName.TrinityLimit: 1, + ItemName.SecondChance: 1, + ItemName.OnceMore: 1, + ItemName.LimitForm: 1, +} +normal_data_xemnas = { + ItemName.ComboMaster: 1, + ItemName.Slapshot: 1, + ItemName.ReflectElement: 3, + ItemName.SlideDash: 1, + ItemName.FlashStep: 1, + ItemName.FinishingPlus: 1, + ItemName.Guard: 1, + ItemName.LimitForm: 1, +} +hard_data_xemnas = { + ItemName.ComboMaster: 1, + ItemName.Slapshot: 1, + ItemName.ReflectElement: 2, + ItemName.FinishingPlus: 1, + ItemName.Guard: 1, + ItemName.LimitForm: 1, +} +final_leveling_access = { + LocationName.MemorysSkyscaperMythrilCrystal, + LocationName.GrimReaper2, + LocationName.Xaldin, + LocationName.StormRider, + LocationName.SunsetTerraceAbilityRing +} + +multi_form_region_access = { + ItemName.CastleKey, + ItemName.BattlefieldsofWar, + ItemName.SwordoftheAncestor, + ItemName.BeastsClaw, + ItemName.BoneFist, + ItemName.SkillandCrossbones, + ItemName.Scimitar, + ItemName.MembershipCard, + ItemName.IceCream, + ItemName.WaytotheDawn, + ItemName.IdentityDisk, +} +limit_form_region_access = { + ItemName.CastleKey, + ItemName.BattlefieldsofWar, + ItemName.SwordoftheAncestor, + ItemName.BeastsClaw, + ItemName.BoneFist, + ItemName.SkillandCrossbones, + ItemName.Scimitar, + ItemName.MembershipCard, + ItemName.IceCream, + ItemName.WaytotheDawn, + ItemName.IdentityDisk, + ItemName.NamineSketches +} diff --git a/worlds/kh2/Names/ItemName.py b/worlds/kh2/Names/ItemName.py index 57cfcbe0606f..d7dbdb0ad30a 100644 --- a/worlds/kh2/Names/ItemName.py +++ b/worlds/kh2/Names/ItemName.py @@ -12,8 +12,7 @@ SecretAnsemsReport11 = "Secret Ansem's Report 11" SecretAnsemsReport12 = "Secret Ansem's Report 12" SecretAnsemsReport13 = "Secret Ansem's Report 13" - -# progression +# proofs, visit unlocks and forms ProofofConnection = "Proof of Connection" ProofofNonexistence = "Proof of Nonexistence" ProofofPeace = "Proof of Peace" @@ -32,51 +31,33 @@ NamineSketches = "Namine Sketches" CastleKey = "Disney Castle Key" TornPages = "Torn Page" -TornPages = "Torn Page" -TornPages = "Torn Page" -TornPages = "Torn Page" -TornPages = "Torn Page" ValorForm = "Valor Form" WisdomForm = "Wisdom Form" LimitForm = "Limit Form" MasterForm = "Master Form" FinalForm = "Final Form" - +AntiForm = "Anti Form" # magic and summons -FireElement = "Fire Element" - -BlizzardElement = "Blizzard Element" - -ThunderElement = "Thunder Element" - -CureElement = "Cure Element" - -MagnetElement = "Magnet Element" - -ReflectElement = "Reflect Element" +FireElement = "Fire Element" +BlizzardElement = "Blizzard Element" +ThunderElement = "Thunder Element" +CureElement = "Cure Element" +MagnetElement = "Magnet Element" +ReflectElement = "Reflect Element" Genie = "Genie" PeterPan = "Peter Pan" Stitch = "Stitch" ChickenLittle = "Chicken Little" -#movement +# movement HighJump = "High Jump" - - QuickRun = "Quick Run" - - AerialDodge = "Aerial Dodge" - - Glide = "Glide" - - DodgeRoll = "Dodge Roll" - -#keyblades +# keyblades Oathkeeper = "Oathkeeper" Oblivion = "Oblivion" StarSeeker = "Star Seeker" @@ -109,7 +90,6 @@ MeteorStaff = "Meteor Staff" CometStaff = "Comet Staff" Centurion2 = "Centurion+" -MeteorStaff = "Meteor Staff" NobodyLance = "Nobody Lance" PreciousMushroom = "Precious Mushroom" PreciousMushroom2 = "Precious Mushroom+" @@ -203,7 +183,7 @@ GrandRibbon = "Grand Ribbon" # usefull and stat incre -MickyMunnyPouch = "Mickey Munny Pouch" +MickeyMunnyPouch = "Mickey Munny Pouch" OletteMunnyPouch = "Olette Munny Pouch" HadesCupTrophy = "Hades Cup Trophy" UnknownDisk = "Unknown Disk" @@ -253,7 +233,6 @@ MagicLock = "Magic Lock-On" LeafBracer = "Leaf Bracer" CombinationBoost = "Combination Boost" -DamageDrive = "Damage Drive" OnceMore = "Once More" SecondChance = "Second Chance" @@ -313,10 +292,6 @@ DonaldFireBoost = "Donald Fire Boost" DonaldBlizzardBoost = "Donald Blizzard Boost" DonaldThunderBoost = "Donald Thunder Boost" -DonaldFireBoost = "Donald Fire Boost" -DonaldBlizzardBoost = "Donald Blizzard Boost" -DonaldThunderBoost = "Donald Thunder Boost" -DonaldMPRage = "Donald MP Rage" DonaldMPHastera = "Donald MP Hastera" DonaldAutoLimit = "Donald Auto Limit" DonaldHyperHealing = "Donald Hyper Healing" @@ -324,14 +299,7 @@ DonaldMPHastega = "Donald MP Hastega" DonaldItemBoost = "Donald Item Boost" DonaldDamageControl = "Donald Damage Control" -DonaldHyperHealing = "Donald Hyper Healing" -DonaldMPRage = "Donald MP Rage" DonaldMPHaste = "Donald MP Haste" -DonaldMPHastera = "Donald MP Hastera" -DonaldMPHastega = "Donald MP Hastega" -DonaldMPHaste = "Donald MP Haste" -DonaldDamageControl = "Donald Damage Control" -DonaldMPHastera = "Donald MP Hastera" DonaldDraw = "Donald Draw" # goofy abili @@ -353,27 +321,18 @@ GoofyAutoChange = "Goofy Auto Change" GoofyHyperHealing = "Goofy Hyper Healing" GoofyAutoHealing = "Goofy Auto Healing" -GoofyDefender = "Goofy Defender" -GoofyHyperHealing = "Goofy Hyper Healing" GoofyMPHaste = "Goofy MP Haste" GoofyMPHastera = "Goofy MP Hastera" -GoofyMPRage = "Goofy MP Rage" GoofyMPHastega = "Goofy MP Hastega" -GoofyItemBoost = "Goofy Item Boost" -GoofyDamageControl = "Goofy Damage Control" -GoofyProtect = "Goofy Protect" -GoofyProtera = "Goofy Protera" -GoofyProtega = "Goofy Protega" -GoofyDamageControl = "Goofy Damage Control" GoofyProtect = "Goofy Protect" GoofyProtera = "Goofy Protera" GoofyProtega = "Goofy Protega" Victory = "Victory" LuckyEmblem = "Lucky Emblem" -Bounty="Bounty" +Bounty = "Bounty" -UniversalKey="Universal Key" +# UniversalKey = "Universal Key" # Keyblade Slots FAKESlot = "FAKE (Slot)" DetectionSaberSlot = "Detection Saber (Slot)" @@ -402,3 +361,73 @@ FenrirSlot = "Fenrir (Slot)" UltimaWeaponSlot = "Ultima Weapon (Slot)" WinnersProofSlot = "Winner's Proof (Slot)" + +# events +HostileProgramEvent = "Hostile Program Event" +McpEvent = "Master Control Program Event" +ASLarxeneEvent = "AS Larxene Event" +DataLarxeneEvent = "Data Larxene Event" +BarbosaEvent = "Barbosa Event" +GrimReaper1Event = "Grim Reaper 1 Event" +GrimReaper2Event = "Grim Reaper 2 Event" +DataLuxordEvent = "Data Luxord Event" +DataAxelEvent = "Data Axel Event" +CerberusEvent = "Cerberus Event" +OlympusPeteEvent = "Olympus Pete Event" +HydraEvent = "Hydra Event" +OcPainAndPanicCupEvent = "Pain and Panic Cup Event" +OcCerberusCupEvent = "Cerberus Cup Event" +HadesEvent = "Hades Event" +ASZexionEvent = "AS Zexion Event" +DataZexionEvent = "Data Zexion Event" +Oc2TitanCupEvent = "Titan Cup Event" +Oc2GofCupEvent = "Goddess of Fate Cup Event" +Oc2CupsEvent = "Olympus Coliseum Cups Event" +HadesCupEvents = "Olympus Coliseum Hade's Paradox Event" +PrisonKeeperEvent = "Prison Keeper Event" +OogieBoogieEvent = "Oogie Boogie Event" +ExperimentEvent = "The Experiment Event" +ASVexenEvent = "AS Vexen Event" +DataVexenEvent = "Data Vexen Event" +ShanYuEvent = "Shan Yu Event" +AnsemRikuEvent = "Ansem Riku Event" +StormRiderEvent = "Storm Rider Event" +DataXigbarEvent = "Data Xigbar Event" +RoxasEvent = "Roxas Event" +XigbarEvent = "Xigbar Event" +LuxordEvent = "Luxord Event" +SaixEvent = "Saix Event" +XemnasEvent = "Xemnas Event" +ArmoredXemnasEvent = "Armored Xemnas Event" +ArmoredXemnas2Event = "Armored Xemnas 2 Event" +FinalXemnasEvent = "Final Xemnas Event" +DataXemnasEvent = "Data Xemnas Event" +ThresholderEvent = "Thresholder Event" +BeastEvent = "Beast Event" +DarkThornEvent = "Dark Thorn Event" +XaldinEvent = "Xaldin Event" +DataXaldinEvent = "Data Xaldin Event" +TwinLordsEvent = "Twin Lords Event" +GenieJafarEvent = "Genie Jafar Event" +ASLexaeusEvent = "AS Lexaeus Event" +DataLexaeusEvent = "Data Lexaeus Event" +ScarEvent = "Scar Event" +GroundShakerEvent = "Groundshaker Event" +DataSaixEvent = "Data Saix Event" +HBDemyxEvent = "Hollow Bastion Demyx Event" +ThousandHeartlessEvent = "Thousand Heartless Event" +Mushroom13Event = "Mushroom 13 Event" +SephiEvent = "Sephiroth Event" +DataDemyxEvent = "Data Demyx Event" +CorFirstFightEvent = "Cavern of Rememberance:Fight 1 Event" +CorSecondFightEvent = "Cavern of Rememberance:Fight 2 Event" +TransportEvent = "Transport to Rememberance Event" +OldPeteEvent = "Old Pete Event" +FuturePeteEvent = "Future Pete Event" +ASMarluxiaEvent = "AS Marluxia Event" +DataMarluxiaEvent = "Data Marluxia Event" +TerraEvent = "Terra Event" +TwilightThornEvent = "Twilight Thorn Event" +Axel1Event = "Axel 1 Event" +Axel2Event = "Axel 2 Event" +DataRoxasEvent = "Data Roxas Event" diff --git a/worlds/kh2/Names/LocationName.py b/worlds/kh2/Names/LocationName.py index 1a6c4d07fbdd..bcaf66455846 100644 --- a/worlds/kh2/Names/LocationName.py +++ b/worlds/kh2/Names/LocationName.py @@ -27,7 +27,7 @@ ThroneRoomMythrilCrystal = "(LoD2) Throne Room Mythril Crystal" ThroneRoomOrichalcum = "(LoD2) Throne Room Orichalcum" StormRider = "(LoD2) Storm Rider Bonus: Sora Slot 1" -XigbarDataDefenseBoost = "Data Xigbar" +XigbarDataDefenseBoost = "(Post LoD2: Summit) Data Xigbar" AgrabahMap = "(AG) Agrabah Map" AgrabahDarkShard = "(AG) Agrabah Dark Shard" @@ -62,9 +62,10 @@ RuinedChamberRuinsMap = "(AG2) Ruined Chamber Ruins Map" GenieJafar = "(AG2) Genie Jafar" WishingLamp = "(AG2) Wishing Lamp" -LexaeusBonus = "Lexaeus Bonus: Sora Slot 1" -LexaeusASStrengthBeyondStrength = "AS Lexaeus" -LexaeusDataLostIllusion = "Data Lexaeus" +LexaeusBonus = "(Post AG2: Peddler's Shop) Lexaeus Bonus: Sora Slot 1" +LexaeusASStrengthBeyondStrength = "(Post AG2: Peddler's Shop) AS Lexaeus" +LexaeusDataLostIllusion = "(Post AG2: Peddler's Shop) Data Lexaeus" + DCCourtyardMythrilShard = "(DC) Courtyard Mythril Shard" DCCourtyardStarRecipe = "(DC) Courtyard Star Recipe" DCCourtyardAPBoost = "(DC) Courtyard AP Boost" @@ -89,12 +90,15 @@ FuturePeteGetBonus = "(TR) Future Pete Bonus: Sora Slot 2" Monochrome = "(TR) Monochrome" WisdomForm = "(TR) Wisdom Form" -MarluxiaGetBonus = "Marluxia Bonus: Sora Slot 1" -MarluxiaASEternalBlossom = "AS Marluxia" -MarluxiaDataLostIllusion = "Data Marluxia" -LingeringWillBonus = "Lingering Will Bonus: Sora Slot 1" -LingeringWillProofofConnection = "Lingering Will Proof of Connection" -LingeringWillManifestIllusion = "Lingering Will Manifest Illusion" + +MarluxiaGetBonus = "(Post TR:Hall of the Cornerstone) Marluxia Bonus: Sora Slot 1" +MarluxiaASEternalBlossom = "(Post TR:Hall of the Cornerstone) AS Marluxia" +MarluxiaDataLostIllusion = "(Post TR:Hall of the Cornerstone) Data Marluxia" + +LingeringWillBonus = "(Post TR:Hall of the Cornerstone) Lingering Will Bonus: Sora Slot 1" +LingeringWillProofofConnection = "(Post TR:Hall of the Cornerstone) Lingering Will Proof of Connection" +LingeringWillManifestIllusion = "(Post TR:Hall of the Cornerstone) Lingering Will Manifest Illusion" + PoohsHouse100AcreWoodMap = "(100Acre) Pooh's House 100 Acre Wood Map" PoohsHouseAPBoost = "(100Acre) Pooh's House AP Boost" PoohsHouseMythrilStone = "(100Acre) Pooh's House Mythril Stone" @@ -119,6 +123,7 @@ StarryHillStyleRecipe = "(100Acre) Starry Hill Style Recipe" StarryHillCureElement = "(100Acre) Starry Hill Cure Element" StarryHillOrichalcumPlus = "(100Acre) Starry Hill Orichalcum+" + PassageMythrilShard = "(OC) Passage Mythril Shard" PassageMythrilStone = "(OC) Passage Mythril Stone" PassageEther = "(OC) Passage Ether" @@ -162,9 +167,9 @@ FatalCrestGoddessofFateCup = "Fatal Crest Goddess of Fate Cup" OrichalcumPlusGoddessofFateCup = "Orichalcum+ Goddess of Fate Cup" HadesCupTrophyParadoxCups = "Hades Cup Trophy Paradox Cups" -ZexionBonus = "Zexion Bonus: Sora Slot 1" -ZexionASBookofShadows = "AS Zexion" -ZexionDataLostIllusion = "Data Zexion" +ZexionBonus = "(Post OC2: Cave of the Dead Inner Chamber) Zexion Bonus: Sora Slot 1" +ZexionASBookofShadows = "(Post OC2: Cave of the Dead Inner Chamber) AS Zexion" +ZexionDataLostIllusion = "(Post OC2: Cave of the Dead Inner Chamber) Data Zexion" BCCourtyardAPBoost = "(BC) Courtyard AP Boost" @@ -198,7 +203,7 @@ Xaldin = "(BC2) Xaldin Bonus: Sora Slot 1" XaldinGetBonus = "(BC2) Xaldin Bonus: Sora Slot 2" SecretAnsemReport4 = "(BC2) Secret Ansem Report 4 (Xaldin)" -XaldinDataDefenseBoost = "Data Xaldin" +XaldinDataDefenseBoost = "(Post BC2: Ballroom) Data Xaldin" @@ -223,9 +228,9 @@ CentralComputerCoreMap = "(SP2) Central Computer Core Map" MCP = "(SP2) MCP Bonus: Sora Slot 1" MCPGetBonus = "(SP2) MCP Bonus: Sora Slot 2" -LarxeneBonus = "Larxene Bonus: Sora Slot 1" -LarxeneASCloakedThunder = "AS Larxene" -LarxeneDataLostIllusion = "Data Larxene" +LarxeneBonus = "(Post SP2: Central Computer Core) Larxene Bonus: Sora Slot 1" +LarxeneASCloakedThunder = "(Post SP2: Central Computer Core) AS Larxene" +LarxeneDataLostIllusion = "(Post SP2: Central Computer Core) Data Larxene" GraveyardMythrilShard = "(HT) Graveyard Mythril Shard" GraveyardSerenityGem = "(HT) Graveyard Serenity Gem" @@ -249,9 +254,9 @@ DecoyPresents = "(HT2) Decoy Presents" Experiment = "(HT2) Experiment Bonus: Sora Slot 1" DecisivePumpkin = "(HT2) Decisive Pumpkin" -VexenBonus = "Vexen Bonus: Sora Slot 1" -VexenASRoadtoDiscovery = "AS Vexen" -VexenDataLostIllusion = "Data Vexen" +VexenBonus = "(Post HT2: Yuletide Hill) Vexen Bonus: Sora Slot 1" +VexenASRoadtoDiscovery = "(Post HT2: Yuletide Hill) AS Vexen" +VexenDataLostIllusion = "(Post HT2: Yuletide Hill) Data Vexen" RampartNavalMap = "(PR) Rampart Naval Map" RampartMythrilStone = "(PR) Rampart Mythril Stone" @@ -286,7 +291,7 @@ GrimReaper2 = "(PR2) Grim Reaper 2 Bonus: Sora Slot 1" SecretAnsemReport6 = "(PR2) Secret Ansem Report 6 (Grim Reaper 2)" -LuxordDataAPBoost = "Data Luxord" +LuxordDataAPBoost = "(Post PR2: Treasure Heap) Data Luxord" MarketplaceMap = "(HB) Marketplace Map" BoroughDriveRecovery = "(HB) Borough Drive Recovery" @@ -329,7 +334,7 @@ SephirothFenrir = "Sephiroth Fenrir" WinnersProof = "(HB2) Winner's Proof" ProofofPeace = "(HB2) Proof of Peace" -DemyxDataAPBoost = "Data Demyx" +DemyxDataAPBoost = "(Post HB2: Restoration Site) Data Demyx" CoRDepthsAPBoost = "(CoR) Depths AP Boost" CoRDepthsPowerCrystal = "(CoR) Depths Power Crystal" @@ -386,7 +391,7 @@ Hyenas2 = "(PL2) Hyenas 2 Bonus: Sora Slot 1" Groundshaker = "(PL2) Groundshaker Bonus: Sora Slot 1" GroundshakerGetBonus = "(PL2) Groundshaker Bonus: Sora Slot 2" -SaixDataDefenseBoost = "Data Saix" +SaixDataDefenseBoost = "(Post PL2: Peak) Data Saix" TwilightTownMap = "(STT) Twilight Town Map" MunnyPouchOlette = "(STT) Munny Pouch Olette" @@ -415,7 +420,7 @@ MansionLibraryHiPotion = "(STT) Mansion Library Hi-Potion" Axel2 = "(STT) Axel 2" MansionBasementCorridorHiPotion = "(STT) Mansion Basement Corridor Hi-Potion" -RoxasDataMagicBoost = "Data Roxas" +RoxasDataMagicBoost = "(Post STT: Mansion Pod Room) Data Roxas" OldMansionPotion = "(TT) Old Mansion Potion" OldMansionMythrilShard = "(TT) Old Mansion Mythril Shard" @@ -468,46 +473,46 @@ MansionBasementCorridorUltimateRecipe = "(TT3) Mansion Basement Corridor Ultimate Recipe" BetwixtandBetween = "(TT3) Betwixt and Between" BetwixtandBetweenBondofFlame = "(TT3) Betwixt and Between Bond of Flame" -AxelDataMagicBoost = "Data Axel" +AxelDataMagicBoost = "(Post TT3: Betwixt and Between) Data Axel" FragmentCrossingMythrilStone = "(TWTNW) Fragment Crossing Mythril Stone" FragmentCrossingMythrilCrystal = "(TWTNW) Fragment Crossing Mythril Crystal" FragmentCrossingAPBoost = "(TWTNW) Fragment Crossing AP Boost" FragmentCrossingOrichalcum = "(TWTNW) Fragment Crossing Orichalcum" -Roxas = "(TWTNW) Roxas Bonus: Sora Slot 1" -RoxasGetBonus = "(TWTNW) Roxas Bonus: Sora Slot 2" -RoxasSecretAnsemReport8 = "(TWTNW) Roxas Secret Ansem Report 8" -TwoBecomeOne = "(TWTNW) Two Become One" -MemorysSkyscaperMythrilCrystal = "(TWTNW) Memory's Skyscaper Mythril Crystal" -MemorysSkyscaperAPBoost = "(TWTNW) Memory's Skyscaper AP Boost" -MemorysSkyscaperMythrilStone = "(TWTNW) Memory's Skyscaper Mythril Stone" -TheBrinkofDespairDarkCityMap = "(TWTNW) The Brink of Despair Dark City Map" -TheBrinkofDespairOrichalcumPlus = "(TWTNW) The Brink of Despair Orichalcum+" -NothingsCallMythrilGem = "(TWTNW) Nothing's Call Mythril Gem" -NothingsCallOrichalcum = "(TWTNW) Nothing's Call Orichalcum" -TwilightsViewCosmicBelt = "(TWTNW) Twilight's View Cosmic Belt" -XigbarBonus = "(TWTNW) Xigbar Bonus: Sora Slot 1" -XigbarSecretAnsemReport3 = "(TWTNW) Xigbar Secret Ansem Report 3" -NaughtsSkywayMythrilGem = "(TWTNW) Naught's Skyway Mythril Gem" -NaughtsSkywayOrichalcum = "(TWTNW) Naught's Skyway Orichalcum" -NaughtsSkywayMythrilCrystal = "(TWTNW) Naught's Skyway Mythril Crystal" -Oblivion = "(TWTNW) Oblivion" -CastleThatNeverWasMap = "(TWTNW) Castle That Never Was Map" -Luxord = "(TWTNW) Luxord" -LuxordGetBonus = "(TWTNW) Luxord Bonus: Sora Slot 1" -LuxordSecretAnsemReport9 = "(TWTNW) Luxord Secret Ansem Report 9" -SaixBonus = "(TWTNW) Saix Bonus: Sora Slot 1" -SaixSecretAnsemReport12 = "(TWTNW) Saix Secret Ansem Report 12" -PreXemnas1SecretAnsemReport11 = "(TWTNW) Secret Ansem Report 11 (Pre-Xemnas 1)" -RuinandCreationsPassageMythrilStone = "(TWTNW) Ruin and Creation's Passage Mythril Stone" -RuinandCreationsPassageAPBoost = "(TWTNW) Ruin and Creation's Passage AP Boost" -RuinandCreationsPassageMythrilCrystal = "(TWTNW) Ruin and Creation's Passage Mythril Crystal" -RuinandCreationsPassageOrichalcum = "(TWTNW) Ruin and Creation's Passage Orichalcum" -Xemnas1 = "(TWTNW) Xemnas 1 Bonus: Sora Slot 1" -Xemnas1GetBonus = "(TWTNW) Xemnas 1 Bonus: Sora Slot 2" -Xemnas1SecretAnsemReport13 = "(TWTNW) Xemnas 1 Secret Ansem Report 13" +Roxas = "(TWTNW2) Roxas Bonus: Sora Slot 1" +RoxasGetBonus = "(TWTNW2) Roxas Bonus: Sora Slot 2" +RoxasSecretAnsemReport8 = "(TWTNW2) Roxas Secret Ansem Report 8" +TwoBecomeOne = "(TWTNW2) Two Become One" +MemorysSkyscaperMythrilCrystal = "(TWTNW2) Memory's Skyscaper Mythril Crystal" +MemorysSkyscaperAPBoost = "(TWTNW2) Memory's Skyscaper AP Boost" +MemorysSkyscaperMythrilStone = "(TWTNW2) Memory's Skyscaper Mythril Stone" +TheBrinkofDespairDarkCityMap = "(TWTNW2) The Brink of Despair Dark City Map" +TheBrinkofDespairOrichalcumPlus = "(TWTNW2) The Brink of Despair Orichalcum+" +NothingsCallMythrilGem = "(TWTNW2) Nothing's Call Mythril Gem" +NothingsCallOrichalcum = "(TWTNW2) Nothing's Call Orichalcum" +TwilightsViewCosmicBelt = "(TWTNW2) Twilight's View Cosmic Belt" +XigbarBonus = "(TWTNW2) Xigbar Bonus: Sora Slot 1" +XigbarSecretAnsemReport3 = "(TWTNW2) Xigbar Secret Ansem Report 3" +NaughtsSkywayMythrilGem = "(TWTNW2) Naught's Skyway Mythril Gem" +NaughtsSkywayOrichalcum = "(TWTNW2) Naught's Skyway Orichalcum" +NaughtsSkywayMythrilCrystal = "(TWTNW2) Naught's Skyway Mythril Crystal" +Oblivion = "(TWTNW2) Oblivion" +CastleThatNeverWasMap = "(TWTNW2) Castle That Never Was Map" +Luxord = "(TWTNW2) Luxord Bonus: Sora Slot 2" +LuxordGetBonus = "(TWTNW2) Luxord Bonus: Sora Slot 1" +LuxordSecretAnsemReport9 = "(TWTNW2) Luxord Secret Ansem Report 9" +SaixBonus = "(TWTNW2) Saix Bonus: Sora Slot 1" +SaixSecretAnsemReport12 = "(TWTNW2) Saix Secret Ansem Report 12" +PreXemnas1SecretAnsemReport11 = "(TWTNW3) Secret Ansem Report 11 (Pre-Xemnas 1)" +RuinandCreationsPassageMythrilStone = "(TWTNW3) Ruin and Creation's Passage Mythril Stone" +RuinandCreationsPassageAPBoost = "(TWTNW3) Ruin and Creation's Passage AP Boost" +RuinandCreationsPassageMythrilCrystal = "(TWTNW3) Ruin and Creation's Passage Mythril Crystal" +RuinandCreationsPassageOrichalcum = "(TWTNW3) Ruin and Creation's Passage Orichalcum" +Xemnas1 = "(TWTNW3) Xemnas 1 Bonus: Sora Slot 1" +Xemnas1GetBonus = "(TWTNW3) Xemnas 1 Bonus: Sora Slot 2" +Xemnas1SecretAnsemReport13 = "(TWTNW3) Xemnas 1 Secret Ansem Report 13" FinalXemnas = "Final Xemnas" -XemnasDataPowerBoost = "Data Xemnas" +XemnasDataPowerBoost = "(Post TWTNW3: The Altar of Naught) Data Xemnas" Lvl1 ="Level 01" Lvl2 ="Level 02" Lvl3 ="Level 03" @@ -605,7 +610,7 @@ Lvl95 ="Level 95" Lvl96 ="Level 96" Lvl97 ="Level 97" -Lvl98 ="Level 98" +Lvl98 ="Level 98" Lvl99 ="Level 99" Valorlvl1 ="Valor level 1" Valorlvl2 ="Valor level 2" @@ -643,13 +648,28 @@ Finallvl6 ="Final level 6" Finallvl7 ="Final level 7" +Summonlvl2="Summon level 2" +Summonlvl3="Summon level 3" +Summonlvl4="Summon level 4" +Summonlvl5="Summon level 5" +Summonlvl6="Summon level 6" +Summonlvl7="Summon level 7" + + GardenofAssemblageMap ="Garden of Assemblage Map" GoALostIllusion ="GoA Lost Illusion" ProofofNonexistence ="Proof of Nonexistence Location" -test= "test" - +UnderseaKingdomMap ="(AT) Undersea Kingdom Map" +MysteriousAbyss ="(AT) Mysterious Abyss" +MusicalBlizzardElement ="(AT) Musical Blizzard Element" +MusicalOrichalcumPlus ="(AT) Musical Orichalcum+" +DonaldStarting1 ="Donald Starting Item 1" +DonaldStarting2 ="Donald Starting Item 2" +GoofyStarting1 ="Goofy Starting Item 1" +GoofyStarting2 ="Goofy Starting Item 2" +# TODO: remove in 4.3 Crit_1 ="Critical Starting Ability 1" Crit_2 ="Critical Starting Ability 2" Crit_3 ="Critical Starting Ability 3" @@ -657,14 +677,9 @@ Crit_5 ="Critical Starting Ability 5" Crit_6 ="Critical Starting Ability 6" Crit_7 ="Critical Starting Ability 7" -DonaldStarting1 ="Donald Starting Item 1" -DonaldStarting2 ="Donald Starting Item 2" -GoofyStarting1 ="Goofy Starting Item 1" -GoofyStarting2 ="Goofy Starting Item 2" - DonaldScreens ="(SP) Screens Bonus: Donald Slot 1" -DonaldDemyxHBGetBonus ="(HB) Demyx Bonus: Donald Slot 1" +DonaldDemyxHBGetBonus ="(HB2) Demyx Bonus: Donald Slot 1" DonaldDemyxOC ="(OC) Demyx Bonus: Donald Slot 1" DonaldBoatPete ="(TR) Boat Pete Bonus: Donald Slot 1" DonaldBoatPeteGetBonus ="(TR) Boat Pete Bonus: Donald Slot 2" @@ -694,7 +709,7 @@ GoofyBeast ="(BC) Beast Bonus: Goofy Slot 1" GoofyInterceptorBarrels ="(PR) Interceptor Barrels Bonus: Goofy Slot 1" GoofyTreasureRoom ="(AG) Treasure Room Heartless Bonus: Goofy Slot 1" -GoofyZexion ="Zexion Bonus: Goofy Slot 1" +GoofyZexion ="(Post OC2: Cave of the Dead Inner Chamber) Zexion Bonus: Goofy Slot 1" AdamantShield ="Adamant Shield Slot" @@ -760,4 +775,86 @@ WinnersProofSlot ="Winner's Proof Slot" PurebloodSlot ="Pureblood Slot" -#Final_Region ="Final Form" +Mushroom13_1 = "(Post TWTNW3: Memory's Skyscraper) Mushroom XIII No. 1" +Mushroom13_2 = "(Post HT2: Christmas Tree Plaza) Mushroom XIII No. 2" +Mushroom13_3 = "(Post BC2: Bridge) Mushroom XIII No. 3" +Mushroom13_4 = "(Post LOD2: Palace Gates) Mushroom XIII No. 4" +Mushroom13_5 = "(Post AG2: Treasure Room) Mushroom XIII No. 5" +Mushroom13_6 = "(Post OC2: Atrium) Mushroom XIII No. 6" +Mushroom13_7 = "(Post TT3: Tunnel way) Mushroom XIII No. 7" +Mushroom13_8 = "(Post TT3: Tower) Mushroom XIII No. 8" +Mushroom13_9 = "(Post HB2: Castle Gates) Mushroom XIII No. 9" +Mushroom13_10 = "(Post PR2: Moonlight Nook) Mushroom XIII No. 10" +Mushroom13_11 = "(Post TR: Waterway) Mushroom XIII No. 11" +Mushroom13_12 = "(Post TT3: Old Mansion) Mushroom XIII No. 12" + + +HostileProgramEventLocation = "Hostile Program Event Location" +McpEventLocation = "Master Control Program Event Location" +ASLarxeneEventLocation = "AS Larxene Event Location" +DataLarxeneEventLocation = "Data Larxene Event Location" +BarbosaEventLocation = "Barbosa Event Location" +GrimReaper1EventLocation = "Grim Reaper 1 Event Location" +GrimReaper2EventLocation = "Grim Reaper 2 Event Location" +DataLuxordEventLocation = "Data Luxord Event Location" +DataAxelEventLocation = "Data Axel Event Location" +CerberusEventLocation = "Cerberus Event Location" +OlympusPeteEventLocation = "Olympus Pete Event Location" +HydraEventLocation = "Hydra Event Location" +OcPainAndPanicCupEventLocation = "Pain and Panic Cup Event Location" +OcCerberusCupEventLocation = "Cerberus Cup Event Location" +HadesEventLocation = "Hades Event Location" +ASZexionEventLocation = "AS Zexion Event Location" +DataZexionEventLocation = "Data Zexion Event Location" +Oc2TitanCupEventLocation = "Titan Cup Event Location" +Oc2GofCupEventLocation = "Goddess of Fate Cup Event Location" +Oc2CupsEventLocation = "Olympus Coliseum Cups Event Location" +HadesCupEventLocations = "Olympus Coliseum Hade's Paradox Event Location" +PrisonKeeperEventLocation = "Prison Keeper Event Location" +OogieBoogieEventLocation = "Oogie Boogie Event Location" +ExperimentEventLocation = "The Experiment Event Location" +ASVexenEventLocation = "AS Vexen Event Location" +DataVexenEventLocation = "Data Vexen Event Location" +ShanYuEventLocation = "Shan Yu Event Location" +AnsemRikuEventLocation = "Ansem Riku Event Location" +StormRiderEventLocation = "Storm Rider Event Location" +DataXigbarEventLocation = "Data Xigbar Event Location" +RoxasEventLocation = "Roxas Event Location" +XigbarEventLocation = "Xigbar Event Location" +LuxordEventLocation = "Luxord Event Location" +SaixEventLocation = "Saix Event Location" +XemnasEventLocation = "Xemnas Event Location" +ArmoredXemnasEventLocation = "Armored Xemnas Event Location" +ArmoredXemnas2EventLocation = "Armored Xemnas 2 Event Location" +FinalXemnasEventLocation = "Final Xemnas Event Location" +DataXemnasEventLocation = "Data Xemnas Event Location" +ThresholderEventLocation = "Thresholder Event Location" +BeastEventLocation = "Beast Event Location" +DarkThornEventLocation = "Dark Thorn Event Location" +XaldinEventLocation = "Xaldin Event Location" +DataXaldinEventLocation = "Data Xaldin Event Location" +TwinLordsEventLocation = "Twin Lords Event Location" +GenieJafarEventLocation = "Genie Jafar Event Location" +ASLexaeusEventLocation = "AS Lexaeus Event Location" +DataLexaeusEventLocation = "Data Lexaeus Event Location" +ScarEventLocation = "Scar Event Location" +GroundShakerEventLocation = "Groundshaker Event Location" +DataSaixEventLocation = "Data Saix Event Location" +HBDemyxEventLocation = "Hollow Bastion Demyx Event Location" +ThousandHeartlessEventLocation = "Thousand Heartless Event Location" +Mushroom13EventLocation = "Mushroom 13 Event Location" +SephiEventLocation = "Sephiroth Event Location" +DataDemyxEventLocation = "Data Demyx Event Location" +CorFirstFightEventLocation = "Cavern of Rememberance:Fight 1 Event Location" +CorSecondFightEventLocation = "Cavern of Rememberance:Fight 2 Event Location" +TransportEventLocation = "Transport to Rememberance Event Location" +OldPeteEventLocation = "Old Pete Event Location" +FuturePeteEventLocation = "Future Pete Event Location" +ASMarluxiaEventLocation = "AS Marluxia Event Location" +DataMarluxiaEventLocation = "Data Marluxia Event Location" +TerraEventLocation = "Terra Event Location" +TwilightThornEventLocation = "Twilight Thorn Event Location" +Axel1EventLocation = "Axel 1 Event Location" +Axel2EventLocation = "Axel 2 Event Location" +DataRoxasEventLocation = "Data Roxas Event Location" + diff --git a/worlds/kh2/Names/RegionName.py b/worlds/kh2/Names/RegionName.py index d07b5d3de367..63ba6acdb878 100644 --- a/worlds/kh2/Names/RegionName.py +++ b/worlds/kh2/Names/RegionName.py @@ -1,90 +1,156 @@ -LoD_Region ="Land of Dragons" -LoD2_Region ="Land of Dragons 2" - -Ag_Region ="Agrabah" -Ag2_Region ="Agrabah 2" - -Dc_Region ="Disney Castle" -Tr_Region ="Timeless River" - -HundredAcre1_Region ="Pooh's House" -HundredAcre2_Region ="Piglet's House" -HundredAcre3_Region ="Rabbit's House" -HundredAcre4_Region ="Roo's House" -HundredAcre5_Region ="Spookey Cave" -HundredAcre6_Region ="Starry Hill" - -Pr_Region ="Port Royal" -Pr2_Region ="Port Royal 2" -Gr2_Region ="Grim Reaper 2" - -Oc_Region ="Olympus Coliseum" -Oc2_Region ="Olympus Coliseum 2" -Oc2_pain_and_panic_Region ="Pain and Panic Cup" -Oc2_titan_Region ="Titan Cup" -Oc2_cerberus_Region ="Cerberus Cup" -Oc2_gof_Region ="Goddest of Fate Cup" -Oc2Cups_Region ="Olympus Coliseum Cups" -HadesCups_Region ="Olympus Coliseum Hade's Paradox" - -Bc_Region ="Beast's Castle" -Bc2_Region ="Beast's Castle 2" -Xaldin_Region ="Xaldin" - -Sp_Region ="Space Paranoids" -Sp2_Region ="Space Paranoids 2" -Mcp_Region ="Master Control Program" - -Ht_Region ="Holloween Town" -Ht2_Region ="Holloween Town 2" - -Hb_Region ="Hollow Bastion" -Hb2_Region ="Hollow Bastion 2" -ThousandHeartless_Region ="Thousand Hearless" -Mushroom13_Region ="Mushroom 13" -CoR_Region ="Cavern of Rememberance" -Transport_Region ="Transport to Rememberance" - -Pl_Region ="Pride Lands" -Pl2_Region ="Pride Lands 2" - -STT_Region ="Simulated Twilight Town" - -TT_Region ="Twlight Town" -TT2_Region ="Twlight Town 2" -TT3_Region ="Twlight Town 3" - -Twtnw_Region ="The World That Never Was (First Visit)" -Twtnw_PostRoxas ="The World That Never Was (Post Roxas)" -Twtnw_PostXigbar ="The World That Never Was (Post Xigbar)" -Twtnw2_Region ="The World That Never Was (Second Visit)" #before riku transformation - -SoraLevels_Region ="Sora's Levels" -GoA_Region ="Garden Of Assemblage" -Keyblade_Region ="Keyblade Slots" - -Valor_Region ="Valor Form" -Wisdom_Region ="Wisdom Form" -Limit_Region ="Limit Form" -Master_Region ="Master Form" -Final_Region ="Final Form" - -Terra_Region ="Lingering Will" -Sephi_Region ="Sephiroth" -Marluxia_Region ="Marluxia" -Larxene_Region ="Larxene" -Vexen_Region ="Vexen" -Lexaeus_Region ="Lexaeus" -Zexion_Region ="Zexion" - -LevelsVS1 ="Levels Region (1 Visit Locking Item)" -LevelsVS3 ="Levels Region (3 Visit Locking Items)" -LevelsVS6 ="Levels Region (6 Visit Locking Items)" -LevelsVS9 ="Levels Region (9 Visit Locking Items)" -LevelsVS12 ="Levels Region (12 Visit Locking Items)" -LevelsVS15 ="Levels Region (15 Visit Locking Items)" -LevelsVS18 ="Levels Region (18 Visit Locking Items)" -LevelsVS21 ="Levels Region (21 Visit Locking Items)" -LevelsVS24 ="Levels Region (24 Visit Locking Items)" -LevelsVS26 ="Levels Region (26 Visit Locking Items)" - +Ha1 = "Pooh's House" +Ha2 = "Piglet's House" +Ha3 = "Rabbit's House" +Ha4 = "Roo's House" +Ha5 = "Spooky Cave" +Ha6 = "Starry Hill" + +SoraLevels = "Sora's Levels" +GoA = "Garden Of Assemblage" +Keyblade = "Weapon Slots" + +Valor = "Valor Form" +Wisdom = "Wisdom Form" +Limit = "Limit Form" +Master = "Master Form" +Final = "Final Form" +Summon = "Summons" +# sp +Sp = "Space Paranoids" +HostileProgram = "Hostile Program" +Sp2 = "Space Paranoids 2" +Mcp = "Master Control Program" +ASLarxene = "AS Larxene" +DataLarxene = "Data Larxene" + +# pr +Pr = "Port Royal" +Barbosa = "Barbosa" +Pr2 = "Port Royal 2" +GrimReaper1 = "Grim Reaper 1" +GrimReaper2 = "Grim Reaper 2" +DataLuxord = "Data Luxord" + +# tt +Tt = "Twilight Town" +Tt2 = "Twilight Town 2" +Tt3 = "Twilight Town 3" +DataAxel = "Data Axel" + +# oc +Oc = "Olympus Coliseum" +Cerberus = "Cerberus" +OlympusPete = "Olympus Pete" +Hydra = "Hydra" +OcPainAndPanicCup = "Pain and Panic Cup" +OcCerberusCup = "Cerberus Cup" +Oc2 = "Olympus Coliseum 2" +Hades = "Hades" +ASZexion = "AS Zexion" +DataZexion = "Data Zexion" +Oc2TitanCup = "Titan Cup" +Oc2GofCup = "Goddess of Fate Cup" +Oc2Cups = "Olympus Coliseum Cups" +HadesCups = "Olympus Coliseum Hade's Paradox" + +# ht +Ht = "Holloween Town" +PrisonKeeper = "Prison Keeper" +OogieBoogie = "Oogie Boogie" +Ht2 = "Holloween Town 2" +Experiment = "The Experiment" +ASVexen = "AS Vexen" +DataVexen = "Data Vexen" + +# lod +LoD = "Land of Dragons" +ShanYu = "Shan Yu" +LoD2 = "Land of Dragons 2" +AnsemRiku = "Ansem Riku" +StormRider = "Storm Rider" +DataXigbar = "Data Xigbar" + +# twtnw +Twtnw = "The World That Never Was (Pre Roxas)" +Roxas = "Roxas" +Xigbar = "Xigbar" +Luxord = "Luxord" +Saix = "Saix" +Twtnw2 = "The World That Never Was (Second Visit)" # Post riku transformation +Xemnas = "Xemnas" +ArmoredXemnas = "Armored Xemnas" +ArmoredXemnas2 = "Armored Xemnas 2" +FinalXemnas = "Final Xemnas" +DataXemnas = "Data Xemnas" + +# bc +Bc = "Beast's Castle" +Thresholder = "Thresholder" +Beast = "Beast" +DarkThorn = "Dark Thorn" +Bc2 = "Beast's Castle 2" +Xaldin = "Xaldin" +DataXaldin = "Data Xaldin" + +# ag +Ag = "Agrabah" +TwinLords = "Twin Lords" +Ag2 = "Agrabah 2" +GenieJafar = "Genie Jafar" +ASLexaeus = "AS Lexaeus" +DataLexaeus = "Data Lexaeus" + +# pl +Pl = "Pride Lands" +Scar = "Scar" +Pl2 = "Pride Lands 2" +GroundShaker = "Groundshaker" +DataSaix = "Data Saix" + +# hb +Hb = "Hollow Bastion" +Hb2 = "Hollow Bastion 2" +HBDemyx = "Hollow Bastion Demyx" +ThousandHeartless = "Thousand Heartless" +Mushroom13 = "Mushroom 13" +Sephi = "Sephiroth" +DataDemyx = "Data Demyx" + +# CoR +CoR = "Cavern of Rememberance" +CorFirstFight = "Cavern of Rememberance:Fight 1" +CorSecondFight = "Cavern of Rememberance:Fight 2" +Transport = "Transport to Rememberance" + +# dc +Dc = "Disney Castle" +Tr = "Timeless River" +OldPete = "Old Pete" +FuturePete = "Future Pete" +ASMarluxia = "AS Marluxia" +DataMarluxia = "Data Marluxia" +Terra = "Terra" + +# stt +Stt = "Simulated Twilight Town" +TwilightThorn = "Twilight Thorn" +Axel1 = "Axel 1" +Axel2 = "Axel 2" +DataRoxas = "Data Roxas" + +AtlanticaSongOne = "Atlantica First Song" +AtlanticaSongTwo = "Atlantica Second Song" +AtlanticaSongThree = "Atlantica Third Song" +AtlanticaSongFour = "Atlantica Fourth Song" + + +LevelsVS1 = "Levels Region (1 Visit Locking Item)" +LevelsVS3 = "Levels Region (3 Visit Locking Items)" +LevelsVS6 = "Levels Region (6 Visit Locking Items)" +LevelsVS9 = "Levels Region (9 Visit Locking Items)" +LevelsVS12 = "Levels Region (12 Visit Locking Items)" +LevelsVS15 = "Levels Region (15 Visit Locking Items)" +LevelsVS18 = "Levels Region (18 Visit Locking Items)" +LevelsVS21 = "Levels Region (21 Visit Locking Items)" +LevelsVS24 = "Levels Region (24 Visit Locking Items)" +LevelsVS26 = "Levels Region (26 Visit Locking Items)" diff --git a/worlds/kh2/OpenKH.py b/worlds/kh2/OpenKH.py index c3334dbb9949..6b0418c9976b 100644 --- a/worlds/kh2/OpenKH.py +++ b/worlds/kh2/OpenKH.py @@ -5,7 +5,7 @@ import Utils import zipfile -from .Items import item_dictionary_table, CheckDupingItems +from .Items import item_dictionary_table from .Locations import all_locations, SoraLevels, exclusion_table from .XPValues import lvlStats, formExp, soraExp from worlds.Files import APContainer @@ -15,7 +15,7 @@ class KH2Container(APContainer): game: str = 'Kingdom Hearts 2' def __init__(self, patch_data: dict, base_path: str, output_directory: str, - player=None, player_name: str = "", server: str = ""): + player=None, player_name: str = "", server: str = ""): self.patch_data = patch_data self.file_path = base_path container_path = os.path.join(output_directory, base_path + ".zip") @@ -24,12 +24,6 @@ def __init__(self, patch_data: dict, base_path: str, output_directory: str, def write_contents(self, opened_zipfile: zipfile.ZipFile) -> None: for filename, yml in self.patch_data.items(): opened_zipfile.writestr(filename, yml) - for root, dirs, files in os.walk(os.path.join(os.path.dirname(__file__), "mod_template")): - for file in files: - opened_zipfile.write(os.path.join(root, file), - os.path.relpath(os.path.join(root, file), - os.path.join(os.path.dirname(__file__), "mod_template"))) - # opened_zipfile.writestr(self.zpf_path, self.patch_data) super().write_contents(opened_zipfile) @@ -59,13 +53,6 @@ def increaseStat(i): formexp = None formName = None levelsetting = list() - slotDataDuping = set() - for values in CheckDupingItems.values(): - if isinstance(values, set): - slotDataDuping = slotDataDuping.union(values) - else: - for inner_values in values.values(): - slotDataDuping = slotDataDuping.union(inner_values) if self.multiworld.Keyblade_Minimum[self.player].value > self.multiworld.Keyblade_Maximum[self.player].value: logging.info( @@ -89,14 +76,19 @@ def increaseStat(i): levelsetting.extend(exclusion_table["Level99Sanity"]) mod_name = f"AP-{self.multiworld.seed_name}-P{self.player}-{self.multiworld.get_file_safe_player_name(self.player)}" - + all_valid_locations = {location for location, data in all_locations.items()} for location in self.multiworld.get_filled_locations(self.player): - - data = all_locations[location.name] - if location.item.player == self.player: - itemcode = item_dictionary_table[location.item.name].kh2id + if location.name in all_valid_locations: + data = all_locations[location.name] else: - itemcode = 90 # castle map + continue + if location.item: + if location.item.player == self.player: + itemcode = item_dictionary_table[location.item.name].kh2id + else: + itemcode = 90 # castle map + else: + itemcode = 90 if data.yml == "Chest": self.formattedTrsr[data.locid] = {"ItemId": itemcode} @@ -129,8 +121,8 @@ def increaseStat(i): elif data.yml == "Keyblade": self.formattedItem["Stats"].append({ "Id": data.locid, - "Attack": self.multiworld.per_slot_randoms[self.player].randint(keyblademin, keyblademax), - "Magic": self.multiworld.per_slot_randoms[self.player].randint(keyblademin, keyblademax), + "Attack": self.random.randint(keyblademin, keyblademax), + "Magic": self.random.randint(keyblademin, keyblademax), "Defense": 0, "Ability": itemcode, "AbilityPoints": 0, @@ -154,7 +146,8 @@ def increaseStat(i): 2: self.multiworld.Wisdom_Form_EXP[self.player].value, 3: self.multiworld.Limit_Form_EXP[self.player].value, 4: self.multiworld.Master_Form_EXP[self.player].value, - 5: self.multiworld.Final_Form_EXP[self.player].value} + 5: self.multiworld.Final_Form_EXP[self.player].value + } formexp = formDictExp[data.charName] formName = formDict[data.charName] self.formattedFmlv[formName] = [] @@ -174,7 +167,7 @@ def increaseStat(i): "GrowthAbilityLevel": 0, }) - # Summons have no checks on them so done fully locally + # Summons have no actual locations so done down here. self.formattedFmlv["Summon"] = [] for x in range(1, 7): self.formattedFmlv["Summon"].append({ @@ -185,17 +178,18 @@ def increaseStat(i): "GrowthAbilityLevel": 0, }) # levels done down here because of optional settings that can take locations out of the pool. - self.i = 1 + self.i = 2 for location in SoraLevels: - increaseStat(self.multiworld.per_slot_randoms[self.player].randint(0, 3)) + increaseStat(self.random.randint(0, 3)) if location in levelsetting: data = self.multiworld.get_location(location, self.player) - if data.item.player == self.player: - itemcode = item_dictionary_table[data.item.name].kh2id - else: - itemcode = 90 # castle map + if data.item: + if data.item.player == self.player: + itemcode = item_dictionary_table[data.item.name].kh2id + else: + itemcode = 90 # castle map else: - increaseStat(self.multiworld.per_slot_randoms[self.player].randint(0, 3)) + increaseStat(self.random.randint(0, 3)) itemcode = 0 self.formattedLvup["Sora"][self.i] = { "Exp": int(soraExp[self.i] / self.multiworld.Sora_Level_EXP[self.player].value), @@ -229,6 +223,193 @@ def increaseStat(i): "GeneralResistance": 100, "Unknown": 0 }) + self.formattedLvup["Sora"][1] = { + "Exp": int(soraExp[1] / self.multiworld.Sora_Level_EXP[self.player].value), + "Strength": 2, + "Magic": 6, + "Defense": 2, + "Ap": 0, + "SwordAbility": 0, + "ShieldAbility": 0, + "StaffAbility": 0, + "Padding": 0, + "Character": "Sora", + "Level": 1 + } + self.mod_yml = { + "assets": [ + { + 'method': 'binarc', + 'name': '00battle.bin', + 'source': [ + { + 'method': 'listpatch', + 'name': 'fmlv', + 'source': [ + { + 'name': 'FmlvList.yml', + 'type': 'fmlv' + } + ], + 'type': 'List' + }, + { + 'method': 'listpatch', + 'name': 'lvup', + 'source': [ + { + 'name': 'LvupList.yml', + 'type': 'lvup' + } + ], + 'type': 'List' + }, + { + 'method': 'listpatch', + 'name': 'bons', + 'source': [ + { + 'name': 'BonsList.yml', + 'type': 'bons' + } + ], + 'type': 'List' + } + ] + }, + { + 'method': 'binarc', + 'name': '03system.bin', + 'source': [ + { + 'method': 'listpatch', + 'name': 'trsr', + 'source': [ + { + 'name': 'TrsrList.yml', + 'type': 'trsr' + } + ], + 'type': 'List' + }, + { + 'method': 'listpatch', + 'name': 'item', + 'source': [ + { + 'name': 'ItemList.yml', + 'type': 'item' + } + ], + 'type': 'List' + } + ] + }, + { + 'name': 'msg/us/po.bar', + 'multi': [ + { + 'name': 'msg/fr/po.bar' + }, + { + 'name': 'msg/gr/po.bar' + }, + { + 'name': 'msg/it/po.bar' + }, + { + 'name': 'msg/sp/po.bar' + } + ], + 'method': 'binarc', + 'source': [ + { + 'name': 'po', + 'type': 'list', + 'method': 'kh2msg', + 'source': [ + { + 'name': 'po.yml', + 'language': 'en' + } + ] + } + ] + }, + { + 'name': 'msg/us/sys.bar', + 'multi': [ + { + 'name': 'msg/fr/sys.bar' + }, + { + 'name': 'msg/gr/sys.bar' + }, + { + 'name': 'msg/it/sys.bar' + }, + { + 'name': 'msg/sp/sys.bar' + } + ], + 'method': 'binarc', + 'source': [ + { + 'name': 'sys', + 'type': 'list', + 'method': 'kh2msg', + 'source': [ + { + 'name': 'sys.yml', + 'language': 'en' + } + ] + } + ] + }, + ], + 'title': 'Randomizer Seed' + } + + goal_to_text = { + 0: "Three Proofs", + 1: "Lucky Emblem", + 2: "Hitlist", + 3: "Lucky Emblem and Hitlist", + } + lucky_emblem_text = { + 0: "Your Goal is not Lucky Emblem. It is Hitlist or Three Proofs.", + 1: f"Lucky Emblem Required: {self.multiworld.LuckyEmblemsRequired[self.player]} out of {self.multiworld.LuckyEmblemsAmount[self.player]}", + 2: "Your Goal is not Lucky Emblem. It is Hitlist or Three Proofs.", + 3: f"Lucky Emblem Required: {self.multiworld.LuckyEmblemsRequired[self.player]} out of {self.multiworld.LuckyEmblemsAmount[self.player]}" + } + hitlist_text = { + 0: "Your Goal is not Hitlist. It is Lucky Emblem or Three Proofs", + 1: "Your Goal is not Hitlist. It is Lucky Emblem or Three Proofs", + 2: f"Bounties Required: {self.multiworld.BountyRequired[self.player]} out of {self.multiworld.BountyAmount[self.player]}", + 3: f"Bounties Required: {self.multiworld.BountyRequired[self.player]} out of {self.multiworld.BountyAmount[self.player]}", + } + + self.pooh_text = [ + { + 'id': 18326, + 'en': f"Your goal is {goal_to_text[self.multiworld.Goal[self.player].value]}" + }, + { + 'id': 18327, + 'en': lucky_emblem_text[self.multiworld.Goal[self.player].value] + }, + { + 'id': 18328, + 'en': hitlist_text[self.multiworld.Goal[self.player].value] + } + ] + self.level_depth_text = [ + { + 'id': 0x3BF1, + 'en': f"Your Level Depth is {self.multiworld.LevelDepth[self.player].current_option_name}" + } + ] mod_dir = os.path.join(output_directory, mod_name + "_" + Utils.__version__) openkhmod = { @@ -237,8 +418,11 @@ def increaseStat(i): "BonsList.yml": yaml.dump(self.formattedBons, line_break="\n"), "ItemList.yml": yaml.dump(self.formattedItem, line_break="\n"), "FmlvList.yml": yaml.dump(self.formattedFmlv, line_break="\n"), + "mod.yml": yaml.dump(self.mod_yml, line_break="\n"), + "po.yml": yaml.dump(self.pooh_text, line_break="\n"), + "sys.yml": yaml.dump(self.level_depth_text, line_break="\n"), } mod = KH2Container(openkhmod, mod_dir, output_directory, self.player, - self.multiworld.get_file_safe_player_name(self.player)) + self.multiworld.get_file_safe_player_name(self.player)) mod.write() diff --git a/worlds/kh2/Options.py b/worlds/kh2/Options.py index 7a6f106aa9b8..7ba7c0082d17 100644 --- a/worlds/kh2/Options.py +++ b/worlds/kh2/Options.py @@ -1,7 +1,8 @@ -from Options import Choice, Option, Range, Toggle, OptionSet -import typing +from dataclasses import dataclass -from worlds.kh2 import SupportAbility_Table, ActionAbility_Table +from Options import Choice, Range, Toggle, ItemDict, PerGameCommonOptions, StartInventoryPool + +from worlds.kh2 import default_itempool_option class SoraEXP(Range): @@ -107,23 +108,61 @@ class Visitlocking(Choice): First and Second Visit Locking: One item for First Visit Two For Second Visit""" display_name = "Visit locking" option_no_visit_locking = 0 # starts with 25 visit locking - option_second_visit_locking = 1 # starts with 13 (no icecream/picture) + option_second_visit_locking = 1 # starts with 12 visit locking option_first_and_second_visit_locking = 2 # starts with nothing default = 2 +class FightLogic(Choice): + """ + The level of logic to use when determining what fights in each KH2 world are beatable. + + Easy: For Players not very comfortable doing things without a lot of tools. + + Normal: For Players somewhat comfortable doing fights with some of the tools. + + Hard: For Players comfortable doing fights with almost no tools. + """ + display_name = "Fight Logic" + option_easy = 0 + option_normal = 1 + option_hard = 2 + default = 1 + + +class FinalFormLogic(Choice): + """Determines forcing final form logic + + No Light and Darkness: Light and Darkness is not in logic. + Light And Darkness: Final Forcing with light and darkness is in logic. + Just a Form: All that requires final forcing is another form. + """ + display_name = "Final Form Logic" + option_no_light_and_darkness = 0 + option_light_and_darkness = 1 + option_just_a_form = 2 + default = 1 + + +class AutoFormLogic(Toggle): + """ Have Auto Forms levels in logic. + """ + display_name = "Auto Form Logic" + default = False + + class RandomVisitLockingItem(Range): """Start with random amount of visit locking items.""" display_name = "Random Visit Locking Item" range_start = 0 range_end = 25 - default = 3 + default = 0 class SuperBosses(Toggle): - """Terra, Sephiroth and Data Fights Toggle.""" + """Terra Sephiroth and Data Fights Toggle.""" display_name = "Super Bosses" - default = False + default = True class Cups(Choice): @@ -135,7 +174,7 @@ class Cups(Choice): option_no_cups = 0 option_cups = 1 option_cups_and_hades_paradox = 2 - default = 1 + default = 0 class LevelDepth(Choice): @@ -157,67 +196,71 @@ class LevelDepth(Choice): default = 0 -class PromiseCharm(Toggle): - """Add Promise Charm to the Pool""" - display_name = "Promise Charm" - default = False +class DonaldGoofyStatsanity(Toggle): + """Toggles if on Donald and Goofy's Get Bonus locations can be any item""" + display_name = "Donald & Goofy Statsanity" + default = True -class KeybladeAbilities(Choice): - """ - Action: Action Abilities in the Keyblade Slot Pool. +class AtlanticaToggle(Toggle): + """Atlantica Toggle""" + display_name = "Atlantica Toggle" + default = False - Support: Support Abilities in the Keyblade Slot Pool. - Both: Action and Support Abilities in the Keyblade Slot Pool.""" - display_name = "Keyblade Abilities" - option_support = 0 - option_action = 1 - option_both = 2 - default = 0 +class PromiseCharm(Toggle): + """Add Promise Charm to the pool""" + display_name = "Promise Charm" + default = False -class BlacklistKeyblade(OptionSet): - """Black List these Abilities on Keyblades""" - display_name = "Blacklist Keyblade Abilities" - valid_keys = set(SupportAbility_Table.keys()).union(ActionAbility_Table.keys()) +class AntiForm(Toggle): + """Add Anti Form to the pool""" + display_name = "Anti Form" + default = False class Goal(Choice): """Win Condition - Three Proofs: Get a Gold Crown on Sora's Head. + Three Proofs: Find the 3 Proofs to unlock the final door. + + Lucky Emblem Hunt: Find required amount of Lucky Emblems. - Lucky Emblem Hunt: Find Required Amount of Lucky Emblems . + Hitlist (Bounty Hunt): Find required amount of Bounties. - Hitlist (Bounty Hunt): Find Required Amount of Bounties""" + Lucky Emblem and Hitlist: Find the required amount of Lucky Emblems and Bounties.""" display_name = "Goal" option_three_proofs = 0 option_lucky_emblem_hunt = 1 option_hitlist = 2 - default = 0 + option_hitlist_and_lucky_emblem = 3 + default = 1 class FinalXemnas(Toggle): """Kill Final Xemnas to Beat the Game. - This is in addition to your Goal. I.E. get three proofs+kill final Xemnas""" + + This is in addition to your Goal. + + I.E. get three proofs+kill final Xemnas""" display_name = "Final Xemnas" default = True class LuckyEmblemsRequired(Range): - """Number of Lucky Emblems to collect to Win/Unlock Final Xemnas Door. + """Number of Lucky Emblems to collect to Win/Unlock Final Xemnas' Door. - If Goal is not Lucky Emblem Hunt this does nothing.""" + If Goal is not Lucky Emblem Hunt or Lucky Emblem and Hitlist this does nothing.""" display_name = "Lucky Emblems Required" range_start = 1 range_end = 60 - default = 30 + default = 35 class LuckyEmblemsAmount(Range): """Number of Lucky Emblems that are in the pool. - If Goal is not Lucky Emblem Hunt this does nothing.""" + If Goal is not Lucky Emblem Hunt or Lucky Emblem and Hitlist this does nothing.""" display_name = "Lucky Emblems Available" range_start = 1 range_end = 60 @@ -227,48 +270,103 @@ class LuckyEmblemsAmount(Range): class BountyRequired(Range): """Number of Bounties to collect to Win/Unlock Final Xemnas Door. - If Goal is not Hitlist this does nothing.""" + If Goal is not Hitlist or Lucky Emblem and Hitlist this does nothing.""" display_name = "Bounties Required" range_start = 1 - range_end = 24 + range_end = 26 default = 7 class BountyAmount(Range): """Number of Bounties that are in the pool. - If Goal is not Hitlist this does nothing.""" + If Goal is not Hitlist or Lucky Emblem and Hitlist this does nothing.""" display_name = "Bounties Available" range_start = 1 - range_end = 24 - default = 13 - - -KH2_Options: typing.Dict[str, type(Option)] = { - "LevelDepth": LevelDepth, - "Sora_Level_EXP": SoraEXP, - "Valor_Form_EXP": ValorEXP, - "Wisdom_Form_EXP": WisdomEXP, - "Limit_Form_EXP": LimitEXP, - "Master_Form_EXP": MasterEXP, - "Final_Form_EXP": FinalEXP, - "Summon_EXP": SummonEXP, - "Schmovement": Schmovement, - "RandomGrowth": RandomGrowth, - "Promise_Charm": PromiseCharm, - "Goal": Goal, - "FinalXemnas": FinalXemnas, - "LuckyEmblemsAmount": LuckyEmblemsAmount, - "LuckyEmblemsRequired": LuckyEmblemsRequired, - "BountyAmount": BountyAmount, - "BountyRequired": BountyRequired, - "Keyblade_Minimum": KeybladeMin, - "Keyblade_Maximum": KeybladeMax, - "Visitlocking": Visitlocking, - "RandomVisitLockingItem": RandomVisitLockingItem, - "SuperBosses": SuperBosses, - "KeybladeAbilities": KeybladeAbilities, - "BlacklistKeyblade": BlacklistKeyblade, - "Cups": Cups, - -} + range_end = 26 + default = 10 + + +class BountyStartHint(Toggle): + """Start with Bounties Hinted""" + display_name = "Start with Bounties Hinted" + default = False + + +class WeaponSlotStartHint(Toggle): + """Start with Weapon Slots' Hinted""" + display_name = "Start with Weapon Slots Hinted" + default = False + + +class CorSkipToggle(Toggle): + """Toggle for Cor skip. + + Tools depend on which difficulty was chosen on Fight Difficulty. + + Toggle does not negate fight logic but is an alternative. + + Final Chest is also can be put into logic with this skip. + """ + display_name = "CoR Skip Toggle." + default = False + + +class CustomItemPoolQuantity(ItemDict): + """Add more of an item into the itempool. Note: You cannot take out items from the pool.""" + display_name = "Custom Item Pool" + verify_item_name = True + default = default_itempool_option + + +class FillerItemsLocal(Toggle): + """Make all dynamic filler classified items local. Recommended when playing with games with fewer locations than kh2""" + display_name = "Local Filler Items" + default = True + + +class SummonLevelLocationToggle(Toggle): + """Toggle Summon levels to have locations.""" + display_name = "Summon Level Locations" + default = False + + +# shamelessly stolen from the messanger +@dataclass +class KingdomHearts2Options(PerGameCommonOptions): + start_inventory: StartInventoryPool + LevelDepth: LevelDepth + Sora_Level_EXP: SoraEXP + Valor_Form_EXP: ValorEXP + Wisdom_Form_EXP: WisdomEXP + Limit_Form_EXP: LimitEXP + Master_Form_EXP: MasterEXP + Final_Form_EXP: FinalEXP + Summon_EXP: SummonEXP + Schmovement: Schmovement + RandomGrowth: RandomGrowth + AntiForm: AntiForm + Promise_Charm: PromiseCharm + Goal: Goal + FinalXemnas: FinalXemnas + LuckyEmblemsAmount: LuckyEmblemsAmount + LuckyEmblemsRequired: LuckyEmblemsRequired + BountyAmount: BountyAmount + BountyRequired: BountyRequired + BountyStartingHintToggle: BountyStartHint + Keyblade_Minimum: KeybladeMin + Keyblade_Maximum: KeybladeMax + WeaponSlotStartHint: WeaponSlotStartHint + FightLogic: FightLogic + FinalFormLogic: FinalFormLogic + AutoFormLogic: AutoFormLogic + DonaldGoofyStatsanity: DonaldGoofyStatsanity + FillerItemsLocal: FillerItemsLocal + Visitlocking: Visitlocking + RandomVisitLockingItem: RandomVisitLockingItem + SuperBosses: SuperBosses + Cups: Cups + SummonLevelLocationToggle: SummonLevelLocationToggle + AtlanticaToggle: AtlanticaToggle + CorSkipToggle: CorSkipToggle + CustomItemPoolQuantity: CustomItemPoolQuantity diff --git a/worlds/kh2/Regions.py b/worlds/kh2/Regions.py index 36fc0c046b5c..aceab97f37ce 100644 --- a/worlds/kh2/Regions.py +++ b/worlds/kh2/Regions.py @@ -1,35 +1,22 @@ import typing -from BaseClasses import MultiWorld, Region, Entrance +from BaseClasses import MultiWorld, Region -from .Locations import KH2Location, RegionTable -from .Names import LocationName, ItemName, RegionName +from .Locations import KH2Location, event_location_to_item +from . import LocationName, RegionName, Events_Table - -def create_regions(world, player: int, active_locations): - menu_region = create_region(world, player, active_locations, 'Menu', None) - - goa_region_locations = [ - LocationName.Crit_1, - LocationName.Crit_2, - LocationName.Crit_3, - LocationName.Crit_4, - LocationName.Crit_5, - LocationName.Crit_6, - LocationName.Crit_7, +KH2REGIONS: typing.Dict[str, typing.List[str]] = { + "Menu": [], + RegionName.GoA: [ LocationName.GardenofAssemblageMap, LocationName.GoALostIllusion, LocationName.ProofofNonexistence, - LocationName.DonaldStarting1, - LocationName.DonaldStarting2, - LocationName.GoofyStarting1, - LocationName.GoofyStarting2, - ] - - goa_region = create_region(world, player, active_locations, RegionName.GoA_Region, - goa_region_locations) - - lod_Region_locations = [ + # LocationName.DonaldStarting1, + # LocationName.DonaldStarting2, + # LocationName.GoofyStarting1, + # LocationName.GoofyStarting2 + ], + RegionName.LoD: [ LocationName.BambooGroveDarkShard, LocationName.BambooGroveEther, LocationName.BambooGroveMythrilShard, @@ -47,14 +34,16 @@ def create_regions(world, player: int, active_locations): LocationName.VillageCaveBonus, LocationName.RidgeFrostShard, LocationName.RidgeAPBoost, + ], + RegionName.ShanYu: [ LocationName.ShanYu, LocationName.ShanYuGetBonus, LocationName.HiddenDragon, LocationName.GoofyShanYu, - ] - lod_Region = create_region(world, player, active_locations, RegionName.LoD_Region, - lod_Region_locations) - lod2_Region_locations = [ + LocationName.ShanYuEventLocation + ], + RegionName.LoD2: [], + RegionName.AnsemRiku: [ LocationName.ThroneRoomTornPages, LocationName.ThroneRoomPalaceMap, LocationName.ThroneRoomAPBoost, @@ -63,13 +52,18 @@ def create_regions(world, player: int, active_locations): LocationName.ThroneRoomOgreShield, LocationName.ThroneRoomMythrilCrystal, LocationName.ThroneRoomOrichalcum, + LocationName.AnsemRikuEventLocation, + ], + RegionName.StormRider: [ LocationName.StormRider, - LocationName.XigbarDataDefenseBoost, LocationName.GoofyStormRider, - ] - lod2_Region = create_region(world, player, active_locations, RegionName.LoD2_Region, - lod2_Region_locations) - ag_region_locations = [ + LocationName.StormRiderEventLocation + ], + RegionName.DataXigbar: [ + LocationName.XigbarDataDefenseBoost, + LocationName.DataXigbarEventLocation + ], + RegionName.Ag: [ LocationName.AgrabahMap, LocationName.AgrabahDarkShard, LocationName.AgrabahMythrilShard, @@ -97,30 +91,30 @@ def create_regions(world, player: int, active_locations): LocationName.TreasureRoom, LocationName.TreasureRoomAPBoost, LocationName.TreasureRoomSerenityGem, + LocationName.GoofyTreasureRoom, + LocationName.DonaldAbuEscort + ], + RegionName.TwinLords: [ LocationName.ElementalLords, LocationName.LampCharm, - LocationName.GoofyTreasureRoom, - LocationName.DonaldAbuEscort, - ] - ag_region = create_region(world, player, active_locations, RegionName.Ag_Region, - ag_region_locations) - ag2_region_locations = [ + LocationName.TwinLordsEventLocation + ], + RegionName.Ag2: [ LocationName.RuinedChamberTornPages, LocationName.RuinedChamberRuinsMap, + ], + RegionName.GenieJafar: [ LocationName.GenieJafar, LocationName.WishingLamp, - ] - ag2_region = create_region(world, player, active_locations, RegionName.Ag2_Region, - ag2_region_locations) - lexaeus_region_locations = [ + LocationName.GenieJafarEventLocation, + ], + RegionName.DataLexaeus: [ LocationName.LexaeusBonus, LocationName.LexaeusASStrengthBeyondStrength, LocationName.LexaeusDataLostIllusion, - ] - lexaeus_region = create_region(world, player, active_locations, RegionName.Lexaeus_Region, - lexaeus_region_locations) - - dc_region_locations = [ + LocationName.DataLexaeusEventLocation + ], + RegionName.Dc: [ LocationName.DCCourtyardMythrilShard, LocationName.DCCourtyardStarRecipe, LocationName.DCCourtyardAPBoost, @@ -131,74 +125,65 @@ def create_regions(world, player: int, active_locations): LocationName.LibraryTornPages, LocationName.DisneyCastleMap, LocationName.MinnieEscort, - LocationName.MinnieEscortGetBonus, - ] - dc_region = create_region(world, player, active_locations, RegionName.Dc_Region, - dc_region_locations) - tr_region_locations = [ + LocationName.MinnieEscortGetBonus + ], + RegionName.Tr: [ LocationName.CornerstoneHillMap, LocationName.CornerstoneHillFrostShard, LocationName.PierMythrilShard, LocationName.PierHiPotion, + ], + RegionName.OldPete: [ LocationName.WaterwayMythrilStone, LocationName.WaterwayAPBoost, LocationName.WaterwayFrostStone, LocationName.WindowofTimeMap, LocationName.BoatPete, + LocationName.DonaldBoatPete, + LocationName.DonaldBoatPeteGetBonus, + LocationName.OldPeteEventLocation, + ], + RegionName.FuturePete: [ LocationName.FuturePete, LocationName.FuturePeteGetBonus, LocationName.Monochrome, LocationName.WisdomForm, - LocationName.DonaldBoatPete, - LocationName.DonaldBoatPeteGetBonus, LocationName.GoofyFuturePete, - ] - tr_region = create_region(world, player, active_locations, RegionName.Tr_Region, - tr_region_locations) - marluxia_region_locations = [ + LocationName.FuturePeteEventLocation + ], + RegionName.DataMarluxia: [ LocationName.MarluxiaGetBonus, LocationName.MarluxiaASEternalBlossom, LocationName.MarluxiaDataLostIllusion, - ] - marluxia_region = create_region(world, player, active_locations, RegionName.Marluxia_Region, - marluxia_region_locations) - terra_region_locations = [ + LocationName.DataMarluxiaEventLocation + ], + RegionName.Terra: [ LocationName.LingeringWillBonus, LocationName.LingeringWillProofofConnection, LocationName.LingeringWillManifestIllusion, - ] - terra_region = create_region(world, player, active_locations, RegionName.Terra_Region, - terra_region_locations) - - hundred_acre1_region_locations = [ + LocationName.TerraEventLocation + ], + RegionName.Ha1: [ LocationName.PoohsHouse100AcreWoodMap, LocationName.PoohsHouseAPBoost, - LocationName.PoohsHouseMythrilStone, - ] - hundred_acre1_region = create_region(world, player, active_locations, RegionName.HundredAcre1_Region, - hundred_acre1_region_locations) - hundred_acre2_region_locations = [ + LocationName.PoohsHouseMythrilStone + ], + RegionName.Ha2: [ LocationName.PigletsHouseDefenseBoost, LocationName.PigletsHouseAPBoost, - LocationName.PigletsHouseMythrilGem, - ] - hundred_acre2_region = create_region(world, player, active_locations, RegionName.HundredAcre2_Region, - hundred_acre2_region_locations) - hundred_acre3_region_locations = [ + LocationName.PigletsHouseMythrilGem + ], + RegionName.Ha3: [ LocationName.RabbitsHouseDrawRing, LocationName.RabbitsHouseMythrilCrystal, LocationName.RabbitsHouseAPBoost, - ] - hundred_acre3_region = create_region(world, player, active_locations, RegionName.HundredAcre3_Region, - hundred_acre3_region_locations) - hundred_acre4_region_locations = [ + ], + RegionName.Ha4: [ LocationName.KangasHouseMagicBoost, LocationName.KangasHouseAPBoost, LocationName.KangasHouseOrichalcum, - ] - hundred_acre4_region = create_region(world, player, active_locations, RegionName.HundredAcre4_Region, - hundred_acre4_region_locations) - hundred_acre5_region_locations = [ + ], + RegionName.Ha5: [ LocationName.SpookyCaveMythrilGem, LocationName.SpookyCaveAPBoost, LocationName.SpookyCaveOrichalcum, @@ -206,19 +191,15 @@ def create_regions(world, player: int, active_locations): LocationName.SpookyCaveMythrilCrystal, LocationName.SpookyCaveAPBoost2, LocationName.SweetMemories, - LocationName.SpookyCaveMap, - ] - hundred_acre5_region = create_region(world, player, active_locations, RegionName.HundredAcre5_Region, - hundred_acre5_region_locations) - hundred_acre6_region_locations = [ + LocationName.SpookyCaveMap + ], + RegionName.Ha6: [ LocationName.StarryHillCosmicRing, LocationName.StarryHillStyleRecipe, LocationName.StarryHillCureElement, - LocationName.StarryHillOrichalcumPlus, - ] - hundred_acre6_region = create_region(world, player, active_locations, RegionName.HundredAcre6_Region, - hundred_acre6_region_locations) - pr_region_locations = [ + LocationName.StarryHillOrichalcumPlus + ], + RegionName.Pr: [ LocationName.RampartNavalMap, LocationName.RampartMythrilStone, LocationName.RampartDarkShard, @@ -236,17 +217,20 @@ def create_regions(world, player: int, active_locations): LocationName.MoonlightNookMythrilShard, LocationName.MoonlightNookSerenityGem, LocationName.MoonlightNookPowerStone, + LocationName.DonaldBoatFight, + LocationName.GoofyInterceptorBarrels, + + ], + RegionName.Barbosa: [ LocationName.Barbossa, LocationName.BarbossaGetBonus, LocationName.FollowtheWind, - LocationName.DonaldBoatFight, LocationName.GoofyBarbossa, LocationName.GoofyBarbossaGetBonus, - LocationName.GoofyInterceptorBarrels, - ] - pr_region = create_region(world, player, active_locations, RegionName.Pr_Region, - pr_region_locations) - pr2_region_locations = [ + LocationName.BarbosaEventLocation, + ], + RegionName.Pr2: [], + RegionName.GrimReaper1: [ LocationName.GrimReaper1, LocationName.InterceptorsHoldFeatherCharm, LocationName.SeadriftKeepAPBoost, @@ -258,19 +242,19 @@ def create_regions(world, player: int, active_locations): LocationName.SeadriftRowCursedMedallion, LocationName.SeadriftRowShipGraveyardMap, LocationName.GoofyGrimReaper1, - - ] - pr2_region = create_region(world, player, active_locations, RegionName.Pr2_Region, - pr2_region_locations) - gr2_region_locations = [ + LocationName.GrimReaper1EventLocation, + ], + RegionName.GrimReaper2: [ LocationName.DonaladGrimReaper2, LocationName.GrimReaper2, LocationName.SecretAnsemReport6, + LocationName.GrimReaper2EventLocation, + ], + RegionName.DataLuxord: [ LocationName.LuxordDataAPBoost, - ] - gr2_region = create_region(world, player, active_locations, RegionName.Gr2_Region, - gr2_region_locations) - oc_region_locations = [ + LocationName.DataLuxordEventLocation + ], + RegionName.Oc: [ LocationName.PassageMythrilShard, LocationName.PassageMythrilStone, LocationName.PassageEther, @@ -278,6 +262,8 @@ def create_regions(world, player: int, active_locations): LocationName.PassageHiPotion, LocationName.InnerChamberUnderworldMap, LocationName.InnerChamberMythrilShard, + ], + RegionName.Cerberus: [ LocationName.Cerberus, LocationName.ColiseumMap, LocationName.Urns, @@ -297,56 +283,61 @@ def create_regions(world, player: int, active_locations): LocationName.TheLockCavernsMap, LocationName.TheLockMythrilShard, LocationName.TheLockAPBoost, + LocationName.CerberusEventLocation + ], + RegionName.OlympusPete: [ LocationName.PeteOC, + LocationName.DonaldDemyxOC, + LocationName.GoofyPeteOC, + LocationName.OlympusPeteEventLocation + ], + RegionName.Hydra: [ LocationName.Hydra, LocationName.HydraGetBonus, LocationName.HerosCrest, - LocationName.DonaldDemyxOC, - LocationName.GoofyPeteOC, - ] - oc_region = create_region(world, player, active_locations, RegionName.Oc_Region, - oc_region_locations) - oc2_region_locations = [ + LocationName.HydraEventLocation + ], + RegionName.Oc2: [ LocationName.AuronsStatue, + ], + RegionName.Hades: [ LocationName.Hades, LocationName.HadesGetBonus, LocationName.GuardianSoul, - - ] - oc2_region = create_region(world, player, active_locations, RegionName.Oc2_Region, - oc2_region_locations) - oc2_pain_and_panic_locations = [ + LocationName.HadesEventLocation + ], + RegionName.OcPainAndPanicCup: [ LocationName.ProtectBeltPainandPanicCup, LocationName.SerenityGemPainandPanicCup, - ] - oc2_titan_locations = [ - LocationName.GenjiShieldTitanCup, - LocationName.SkillfulRingTitanCup, - ] - oc2_cerberus_locations = [ + LocationName.OcPainAndPanicCupEventLocation + ], + RegionName.OcCerberusCup: [ LocationName.RisingDragonCerberusCup, LocationName.SerenityCrystalCerberusCup, - ] - oc2_gof_cup_locations = [ + LocationName.OcCerberusCupEventLocation + ], + RegionName.Oc2TitanCup: [ + LocationName.GenjiShieldTitanCup, + LocationName.SkillfulRingTitanCup, + LocationName.Oc2TitanCupEventLocation + ], + RegionName.Oc2GofCup: [ LocationName.FatalCrestGoddessofFateCup, LocationName.OrichalcumPlusGoddessofFateCup, + LocationName.Oc2GofCupEventLocation, + ], + RegionName.HadesCups: [ LocationName.HadesCupTrophyParadoxCups, - ] - zexion_region_locations = [ + LocationName.HadesCupEventLocations + ], + RegionName.DataZexion: [ LocationName.ZexionBonus, LocationName.ZexionASBookofShadows, LocationName.ZexionDataLostIllusion, LocationName.GoofyZexion, - ] - oc2_pain_and_panic_cup = create_region(world, player, active_locations, RegionName.Oc2_pain_and_panic_Region, - oc2_pain_and_panic_locations) - oc2_titan_cup = create_region(world, player, active_locations, RegionName.Oc2_titan_Region, oc2_titan_locations) - oc2_cerberus_cup = create_region(world, player, active_locations, RegionName.Oc2_cerberus_Region, - oc2_cerberus_locations) - oc2_gof_cup = create_region(world, player, active_locations, RegionName.Oc2_gof_Region, oc2_gof_cup_locations) - zexion_region = create_region(world, player, active_locations, RegionName.Zexion_Region, zexion_region_locations) - - bc_region_locations = [ + LocationName.DataZexionEventLocation + ], + RegionName.Bc: [ LocationName.BCCourtyardAPBoost, LocationName.BCCourtyardHiPotion, LocationName.BCCourtyardMythrilShard, @@ -359,6 +350,8 @@ def create_regions(world, player: int, active_locations): LocationName.TheWestHallMythrilShard2, LocationName.TheWestHallBrightStone, LocationName.TheWestHallMythrilShard, + ], + RegionName.Thresholder: [ LocationName.Thresholder, LocationName.DungeonBasementMap, LocationName.DungeonAPBoost, @@ -368,33 +361,37 @@ def create_regions(world, player: int, active_locations): LocationName.TheWestHallAPBoostPostDungeon, LocationName.TheWestWingMythrilShard, LocationName.TheWestWingTent, + LocationName.DonaldThresholder, + LocationName.ThresholderEventLocation + ], + RegionName.Beast: [ LocationName.Beast, LocationName.TheBeastsRoomBlazingShard, + LocationName.GoofyBeast, + LocationName.BeastEventLocation + ], + RegionName.DarkThorn: [ LocationName.DarkThorn, LocationName.DarkThornGetBonus, LocationName.DarkThornCureElement, - LocationName.DonaldThresholder, - LocationName.GoofyBeast, - ] - bc_region = create_region(world, player, active_locations, RegionName.Bc_Region, - bc_region_locations) - bc2_region_locations = [ + LocationName.DarkThornEventLocation, + ], + RegionName.Bc2: [ LocationName.RumblingRose, - LocationName.CastleWallsMap, - - ] - bc2_region = create_region(world, player, active_locations, RegionName.Bc2_Region, - bc2_region_locations) - xaldin_region_locations = [ + LocationName.CastleWallsMap + ], + RegionName.Xaldin: [ LocationName.Xaldin, LocationName.XaldinGetBonus, LocationName.DonaldXaldinGetBonus, LocationName.SecretAnsemReport4, + LocationName.XaldinEventLocation + ], + RegionName.DataXaldin: [ LocationName.XaldinDataDefenseBoost, - ] - xaldin_region = create_region(world, player, active_locations, RegionName.Xaldin_Region, - xaldin_region_locations) - sp_region_locations = [ + LocationName.DataXaldinEventLocation + ], + RegionName.Sp: [ LocationName.PitCellAreaMap, LocationName.PitCellMythrilCrystal, LocationName.CanyonDarkCrystal, @@ -406,41 +403,35 @@ def create_regions(world, player: int, active_locations): LocationName.HallwayAPBoost, LocationName.CommunicationsRoomIOTowerMap, LocationName.CommunicationsRoomGaiaBelt, + LocationName.DonaldScreens, + ], + RegionName.HostileProgram: [ LocationName.HostileProgram, LocationName.HostileProgramGetBonus, LocationName.PhotonDebugger, - LocationName.DonaldScreens, LocationName.GoofyHostileProgram, - - ] - sp_region = create_region(world, player, active_locations, RegionName.Sp_Region, - sp_region_locations) - sp2_region_locations = [ + LocationName.HostileProgramEventLocation + ], + RegionName.Sp2: [ LocationName.SolarSailer, LocationName.CentralComputerCoreAPBoost, LocationName.CentralComputerCoreOrichalcumPlus, LocationName.CentralComputerCoreCosmicArts, LocationName.CentralComputerCoreMap, - - LocationName.DonaldSolarSailer, - ] - - sp2_region = create_region(world, player, active_locations, RegionName.Sp2_Region, - sp2_region_locations) - mcp_region_locations = [ + LocationName.DonaldSolarSailer + ], + RegionName.Mcp: [ LocationName.MCP, LocationName.MCPGetBonus, - ] - mcp_region = create_region(world, player, active_locations, RegionName.Mcp_Region, - mcp_region_locations) - larxene_region_locations = [ + LocationName.McpEventLocation + ], + RegionName.DataLarxene: [ LocationName.LarxeneBonus, LocationName.LarxeneASCloakedThunder, LocationName.LarxeneDataLostIllusion, - ] - larxene_region = create_region(world, player, active_locations, RegionName.Larxene_Region, - larxene_region_locations) - ht_region_locations = [ + LocationName.DataLarxeneEventLocation + ], + RegionName.Ht: [ LocationName.GraveyardMythrilShard, LocationName.GraveyardSerenityGem, LocationName.FinklesteinsLabHalloweenTownMap, @@ -455,34 +446,37 @@ def create_regions(world, player: int, active_locations): LocationName.CandyCaneLaneMythrilStone, LocationName.SantasHouseChristmasTownMap, LocationName.SantasHouseAPBoost, + ], + RegionName.PrisonKeeper: [ LocationName.PrisonKeeper, + LocationName.DonaldPrisonKeeper, + LocationName.PrisonKeeperEventLocation, + ], + RegionName.OogieBoogie: [ LocationName.OogieBoogie, LocationName.OogieBoogieMagnetElement, - LocationName.DonaldPrisonKeeper, LocationName.GoofyOogieBoogie, - ] - ht_region = create_region(world, player, active_locations, RegionName.Ht_Region, - ht_region_locations) - ht2_region_locations = [ + LocationName.OogieBoogieEventLocation + ], + RegionName.Ht2: [ LocationName.Lock, LocationName.Present, LocationName.DecoyPresents, + LocationName.GoofyLock + ], + RegionName.Experiment: [ LocationName.Experiment, LocationName.DecisivePumpkin, - LocationName.DonaldExperiment, - LocationName.GoofyLock, - ] - ht2_region = create_region(world, player, active_locations, RegionName.Ht2_Region, - ht2_region_locations) - vexen_region_locations = [ + LocationName.ExperimentEventLocation, + ], + RegionName.DataVexen: [ LocationName.VexenBonus, LocationName.VexenASRoadtoDiscovery, LocationName.VexenDataLostIllusion, - ] - vexen_region = create_region(world, player, active_locations, RegionName.Vexen_Region, - vexen_region_locations) - hb_region_locations = [ + LocationName.DataVexenEventLocation + ], + RegionName.Hb: [ LocationName.MarketplaceMap, LocationName.BoroughDriveRecovery, LocationName.BoroughAPBoost, @@ -493,11 +487,9 @@ def create_regions(world, player: int, active_locations): LocationName.MerlinsHouseBlizzardElement, LocationName.Bailey, LocationName.BaileySecretAnsemReport7, - LocationName.BaseballCharm, - ] - hb_region = create_region(world, player, active_locations, RegionName.Hb_Region, - hb_region_locations) - hb2_region_locations = [ + LocationName.BaseballCharm + ], + RegionName.Hb2: [ LocationName.PosternCastlePerimeterMap, LocationName.PosternMythrilGem, LocationName.PosternAPBoost, @@ -511,18 +503,9 @@ def create_regions(world, player: int, active_locations): LocationName.AnsemsStudyUkuleleCharm, LocationName.RestorationSiteMoonRecipe, LocationName.RestorationSiteAPBoost, - LocationName.CoRDepthsAPBoost, - LocationName.CoRDepthsPowerCrystal, - LocationName.CoRDepthsFrostCrystal, - LocationName.CoRDepthsManifestIllusion, - LocationName.CoRDepthsAPBoost2, - LocationName.CoRMineshaftLowerLevelDepthsofRemembranceMap, - LocationName.CoRMineshaftLowerLevelAPBoost, + ], + RegionName.HBDemyx: [ LocationName.DonaldDemyxHBGetBonus, - ] - hb2_region = create_region(world, player, active_locations, RegionName.Hb2_Region, - hb2_region_locations) - onek_region_locations = [ LocationName.DemyxHB, LocationName.DemyxHBGetBonus, LocationName.FFFightsCureElement, @@ -530,30 +513,41 @@ def create_regions(world, player: int, active_locations): LocationName.CrystalFissureTheGreatMawMap, LocationName.CrystalFissureEnergyCrystal, LocationName.CrystalFissureAPBoost, + LocationName.HBDemyxEventLocation, + ], + RegionName.ThousandHeartless: [ LocationName.ThousandHeartless, LocationName.ThousandHeartlessSecretAnsemReport1, LocationName.ThousandHeartlessIceCream, LocationName.ThousandHeartlessPicture, LocationName.PosternGullWing, LocationName.HeartlessManufactoryCosmicChain, + LocationName.ThousandHeartlessEventLocation, + ], + RegionName.DataDemyx: [ LocationName.DemyxDataAPBoost, - ] - onek_region = create_region(world, player, active_locations, RegionName.ThousandHeartless_Region, - onek_region_locations) - mushroom_region_locations = [ + LocationName.DataDemyxEventLocation, + ], + RegionName.Mushroom13: [ LocationName.WinnersProof, LocationName.ProofofPeace, - ] - mushroom_region = create_region(world, player, active_locations, RegionName.Mushroom13_Region, - mushroom_region_locations) - sephi_region_locations = [ + LocationName.Mushroom13EventLocation, + ], + RegionName.Sephi: [ LocationName.SephirothBonus, LocationName.SephirothFenrir, - ] - sephi_region = create_region(world, player, active_locations, RegionName.Sephi_Region, - sephi_region_locations) - - cor_region_locations = [ + LocationName.SephiEventLocation + ], + RegionName.CoR: [ + LocationName.CoRDepthsAPBoost, + LocationName.CoRDepthsPowerCrystal, + LocationName.CoRDepthsFrostCrystal, + LocationName.CoRDepthsManifestIllusion, + LocationName.CoRDepthsAPBoost2, + LocationName.CoRMineshaftLowerLevelDepthsofRemembranceMap, + LocationName.CoRMineshaftLowerLevelAPBoost, + ], + RegionName.CorFirstFight: [ LocationName.CoRDepthsUpperLevelRemembranceGem, LocationName.CoRMiningAreaSerenityGem, LocationName.CoRMiningAreaAPBoost, @@ -561,22 +555,23 @@ def create_regions(world, player: int, active_locations): LocationName.CoRMiningAreaManifestIllusion, LocationName.CoRMiningAreaSerenityGem2, LocationName.CoRMiningAreaDarkRemembranceMap, + LocationName.CorFirstFightEventLocation, + ], + RegionName.CorSecondFight: [ LocationName.CoRMineshaftMidLevelPowerBoost, LocationName.CoREngineChamberSerenityCrystal, LocationName.CoREngineChamberRemembranceCrystal, LocationName.CoREngineChamberAPBoost, LocationName.CoREngineChamberManifestIllusion, LocationName.CoRMineshaftUpperLevelMagicBoost, - ] - cor_region = create_region(world, player, active_locations, RegionName.CoR_Region, - cor_region_locations) - transport_region_locations = [ - LocationName.CoRMineshaftUpperLevelAPBoost, + LocationName.CorSecondFightEventLocation, + ], + RegionName.Transport: [ + LocationName.CoRMineshaftUpperLevelAPBoost, # last chest LocationName.TransporttoRemembrance, - ] - transport_region = create_region(world, player, active_locations, RegionName.Transport_Region, - transport_region_locations) - pl_region_locations = [ + LocationName.TransportEventLocation, + ], + RegionName.Pl: [ LocationName.GorgeSavannahMap, LocationName.GorgeDarkGem, LocationName.GorgeMythrilStone, @@ -604,31 +599,40 @@ def create_regions(world, player: int, active_locations): LocationName.OasisAPBoost, LocationName.CircleofLife, LocationName.Hyenas1, + + LocationName.GoofyHyenas1 + ], + RegionName.Scar: [ LocationName.Scar, LocationName.ScarFireElement, LocationName.DonaldScar, - LocationName.GoofyHyenas1, - - ] - pl_region = create_region(world, player, active_locations, RegionName.Pl_Region, - pl_region_locations) - pl2_region_locations = [ + LocationName.ScarEventLocation, + ], + RegionName.Pl2: [ LocationName.Hyenas2, + LocationName.GoofyHyenas2 + ], + RegionName.GroundShaker: [ LocationName.Groundshaker, LocationName.GroundshakerGetBonus, + LocationName.GroundShakerEventLocation, + ], + RegionName.DataSaix: [ LocationName.SaixDataDefenseBoost, - LocationName.GoofyHyenas2, - ] - pl2_region = create_region(world, player, active_locations, RegionName.Pl2_Region, - pl2_region_locations) - - stt_region_locations = [ + LocationName.DataSaixEventLocation + ], + RegionName.Stt: [ LocationName.TwilightTownMap, LocationName.MunnyPouchOlette, LocationName.StationDusks, LocationName.StationofSerenityPotion, LocationName.StationofCallingPotion, + ], + RegionName.TwilightThorn: [ LocationName.TwilightThorn, + LocationName.TwilightThornEventLocation + ], + RegionName.Axel1: [ LocationName.Axel1, LocationName.JunkChampionBelt, LocationName.JunkMedal, @@ -648,14 +652,18 @@ def create_regions(world, player: int, active_locations): LocationName.NaminesSketches, LocationName.MansionMap, LocationName.MansionLibraryHiPotion, + LocationName.Axel1EventLocation + ], + RegionName.Axel2: [ LocationName.Axel2, LocationName.MansionBasementCorridorHiPotion, + LocationName.Axel2EventLocation + ], + RegionName.DataRoxas: [ LocationName.RoxasDataMagicBoost, - ] - stt_region = create_region(world, player, active_locations, RegionName.STT_Region, - stt_region_locations) - - tt_region_locations = [ + LocationName.DataRoxasEventLocation + ], + RegionName.Tt: [ LocationName.OldMansionPotion, LocationName.OldMansionMythrilShard, LocationName.TheWoodsPotion, @@ -682,18 +690,14 @@ def create_regions(world, player: int, active_locations): LocationName.SorcerersLoftTowerMap, LocationName.TowerWardrobeMythrilStone, LocationName.StarSeeker, - LocationName.ValorForm, - ] - tt_region = create_region(world, player, active_locations, RegionName.TT_Region, - tt_region_locations) - tt2_region_locations = [ + LocationName.ValorForm + ], + RegionName.Tt2: [ LocationName.SeifersTrophy, LocationName.Oathkeeper, - LocationName.LimitForm, - ] - tt2_region = create_region(world, player, active_locations, RegionName.TT2_Region, - tt2_region_locations) - tt3_region_locations = [ + LocationName.LimitForm + ], + RegionName.Tt3: [ LocationName.UndergroundConcourseMythrilGem, LocationName.UndergroundConcourseAPBoost, LocationName.UndergroundConcourseMythrilCrystal, @@ -715,22 +719,19 @@ def create_regions(world, player: int, active_locations): LocationName.MansionBasementCorridorUltimateRecipe, LocationName.BetwixtandBetween, LocationName.BetwixtandBetweenBondofFlame, + LocationName.DonaldMansionNobodies + ], + RegionName.DataAxel: [ LocationName.AxelDataMagicBoost, - LocationName.DonaldMansionNobodies, - ] - tt3_region = create_region(world, player, active_locations, RegionName.TT3_Region, - tt3_region_locations) - - twtnw_region_locations = [ + LocationName.DataAxelEventLocation, + ], + RegionName.Twtnw: [ LocationName.FragmentCrossingMythrilStone, LocationName.FragmentCrossingMythrilCrystal, LocationName.FragmentCrossingAPBoost, - LocationName.FragmentCrossingOrichalcum, - ] - - twtnw_region = create_region(world, player, active_locations, RegionName.Twtnw_Region, - twtnw_region_locations) - twtnw_postroxas_region_locations = [ + LocationName.FragmentCrossingOrichalcum + ], + RegionName.Roxas: [ LocationName.Roxas, LocationName.RoxasGetBonus, LocationName.RoxasSecretAnsemReport8, @@ -743,11 +744,9 @@ def create_regions(world, player: int, active_locations): LocationName.NothingsCallMythrilGem, LocationName.NothingsCallOrichalcum, LocationName.TwilightsViewCosmicBelt, - - ] - twtnw_postroxas_region = create_region(world, player, active_locations, RegionName.Twtnw_PostRoxas, - twtnw_postroxas_region_locations) - twtnw_postxigbar_region_locations = [ + LocationName.RoxasEventLocation + ], + RegionName.Xigbar: [ LocationName.XigbarBonus, LocationName.XigbarSecretAnsemReport3, LocationName.NaughtsSkywayMythrilGem, @@ -755,80 +754,100 @@ def create_regions(world, player: int, active_locations): LocationName.NaughtsSkywayMythrilCrystal, LocationName.Oblivion, LocationName.CastleThatNeverWasMap, + LocationName.XigbarEventLocation, + ], + RegionName.Luxord: [ LocationName.Luxord, LocationName.LuxordGetBonus, LocationName.LuxordSecretAnsemReport9, - ] - twtnw_postxigbar_region = create_region(world, player, active_locations, RegionName.Twtnw_PostXigbar, - twtnw_postxigbar_region_locations) - twtnw2_region_locations = [ + LocationName.LuxordEventLocation, + ], + RegionName.Saix: [ LocationName.SaixBonus, LocationName.SaixSecretAnsemReport12, + LocationName.SaixEventLocation, + ], + RegionName.Twtnw2: [ LocationName.PreXemnas1SecretAnsemReport11, LocationName.RuinandCreationsPassageMythrilStone, LocationName.RuinandCreationsPassageAPBoost, LocationName.RuinandCreationsPassageMythrilCrystal, - LocationName.RuinandCreationsPassageOrichalcum, + LocationName.RuinandCreationsPassageOrichalcum + ], + RegionName.Xemnas: [ LocationName.Xemnas1, LocationName.Xemnas1GetBonus, LocationName.Xemnas1SecretAnsemReport13, - LocationName.FinalXemnas, + LocationName.XemnasEventLocation + + ], + RegionName.ArmoredXemnas: [ + LocationName.ArmoredXemnasEventLocation + ], + RegionName.ArmoredXemnas2: [ + LocationName.ArmoredXemnas2EventLocation + ], + RegionName.FinalXemnas: [ + LocationName.FinalXemnas + ], + RegionName.DataXemnas: [ LocationName.XemnasDataPowerBoost, - ] - twtnw2_region = create_region(world, player, active_locations, RegionName.Twtnw2_Region, - twtnw2_region_locations) + LocationName.DataXemnasEventLocation + ], + RegionName.AtlanticaSongOne: [ + LocationName.UnderseaKingdomMap + ], + RegionName.AtlanticaSongTwo: [ - valor_region_locations = [ + ], + RegionName.AtlanticaSongThree: [ + LocationName.MysteriousAbyss + ], + RegionName.AtlanticaSongFour: [ + LocationName.MusicalBlizzardElement, + LocationName.MusicalOrichalcumPlus + ], + RegionName.Valor: [ LocationName.Valorlvl2, LocationName.Valorlvl3, LocationName.Valorlvl4, LocationName.Valorlvl5, LocationName.Valorlvl6, - LocationName.Valorlvl7, - ] - valor_region = create_region(world, player, active_locations, RegionName.Valor_Region, - valor_region_locations) - wisdom_region_locations = [ + LocationName.Valorlvl7 + ], + RegionName.Wisdom: [ LocationName.Wisdomlvl2, LocationName.Wisdomlvl3, LocationName.Wisdomlvl4, LocationName.Wisdomlvl5, LocationName.Wisdomlvl6, - LocationName.Wisdomlvl7, - ] - wisdom_region = create_region(world, player, active_locations, RegionName.Wisdom_Region, - wisdom_region_locations) - limit_region_locations = [ + LocationName.Wisdomlvl7 + ], + RegionName.Limit: [ LocationName.Limitlvl2, LocationName.Limitlvl3, LocationName.Limitlvl4, LocationName.Limitlvl5, LocationName.Limitlvl6, - LocationName.Limitlvl7, - ] - limit_region = create_region(world, player, active_locations, RegionName.Limit_Region, - limit_region_locations) - master_region_locations = [ + LocationName.Limitlvl7 + ], + RegionName.Master: [ LocationName.Masterlvl2, LocationName.Masterlvl3, LocationName.Masterlvl4, LocationName.Masterlvl5, LocationName.Masterlvl6, - LocationName.Masterlvl7, - ] - master_region = create_region(world, player, active_locations, RegionName.Master_Region, - master_region_locations) - final_region_locations = [ + LocationName.Masterlvl7 + ], + RegionName.Final: [ LocationName.Finallvl2, LocationName.Finallvl3, LocationName.Finallvl4, LocationName.Finallvl5, LocationName.Finallvl6, - LocationName.Finallvl7, - ] - final_region = create_region(world, player, active_locations, RegionName.Final_Region, - final_region_locations) - keyblade_region_locations = [ + LocationName.Finallvl7 + ], + RegionName.Keyblade: [ LocationName.FAKESlot, LocationName.DetectionSaberSlot, LocationName.EdgeofUltimaSlot, @@ -887,356 +906,256 @@ def create_regions(world, player: int, active_locations): LocationName.NobodyGuard, LocationName.OgreShield, LocationName.SaveTheKing2, - LocationName.UltimateMushroom, - ] - keyblade_region = create_region(world, player, active_locations, RegionName.Keyblade_Region, - keyblade_region_locations) + LocationName.UltimateMushroom + ], +} +level_region_list = [ + RegionName.LevelsVS1, + RegionName.LevelsVS3, + RegionName.LevelsVS6, + RegionName.LevelsVS9, + RegionName.LevelsVS12, + RegionName.LevelsVS15, + RegionName.LevelsVS18, + RegionName.LevelsVS21, + RegionName.LevelsVS24, + RegionName.LevelsVS26, +] + - world.regions += [ - lod_Region, - lod2_Region, - ag_region, - ag2_region, - lexaeus_region, - dc_region, - tr_region, - terra_region, - marluxia_region, - hundred_acre1_region, - hundred_acre2_region, - hundred_acre3_region, - hundred_acre4_region, - hundred_acre5_region, - hundred_acre6_region, - pr_region, - pr2_region, - gr2_region, - oc_region, - oc2_region, - oc2_pain_and_panic_cup, - oc2_titan_cup, - oc2_cerberus_cup, - oc2_gof_cup, - zexion_region, - bc_region, - bc2_region, - xaldin_region, - sp_region, - sp2_region, - mcp_region, - larxene_region, - ht_region, - ht2_region, - vexen_region, - hb_region, - hb2_region, - onek_region, - mushroom_region, - sephi_region, - cor_region, - transport_region, - pl_region, - pl2_region, - stt_region, - tt_region, - tt2_region, - tt3_region, - twtnw_region, - twtnw_postroxas_region, - twtnw_postxigbar_region, - twtnw2_region, - goa_region, - menu_region, - valor_region, - wisdom_region, - limit_region, - master_region, - final_region, - keyblade_region, - ] +def create_regions(self): # Level region depends on level depth. # for every 5 levels there should be +3 visit locking - levelVL1 = [] - levelVL3 = [] - levelVL6 = [] - levelVL9 = [] - levelVL12 = [] - levelVL15 = [] - levelVL18 = [] - levelVL21 = [] - levelVL24 = [] - levelVL26 = [] # level 50 - if world.LevelDepth[player] == "level_50": - levelVL1 = [LocationName.Lvl2, LocationName.Lvl4, LocationName.Lvl7, LocationName.Lvl9, LocationName.Lvl10] - levelVL3 = [LocationName.Lvl12, LocationName.Lvl14, LocationName.Lvl15, LocationName.Lvl17, - LocationName.Lvl20, ] - levelVL6 = [LocationName.Lvl23, LocationName.Lvl25, LocationName.Lvl28, LocationName.Lvl30] - levelVL9 = [LocationName.Lvl32, LocationName.Lvl34, LocationName.Lvl36, LocationName.Lvl39, LocationName.Lvl41] - levelVL12 = [LocationName.Lvl44, LocationName.Lvl46, LocationName.Lvl48] - levelVL15 = [LocationName.Lvl50] + multiworld = self.multiworld + player = self.player + active_locations = self.location_name_to_id + + for level_region_name in level_region_list: + KH2REGIONS[level_region_name] = [] + if multiworld.LevelDepth[player] == "level_50": + KH2REGIONS[RegionName.LevelsVS1] = [LocationName.Lvl2, LocationName.Lvl4, LocationName.Lvl7, LocationName.Lvl9, + LocationName.Lvl10] + KH2REGIONS[RegionName.LevelsVS3] = [LocationName.Lvl12, LocationName.Lvl14, LocationName.Lvl15, + LocationName.Lvl17, + LocationName.Lvl20] + KH2REGIONS[RegionName.LevelsVS6] = [LocationName.Lvl23, LocationName.Lvl25, LocationName.Lvl28, + LocationName.Lvl30] + KH2REGIONS[RegionName.LevelsVS9] = [LocationName.Lvl32, LocationName.Lvl34, LocationName.Lvl36, + LocationName.Lvl39, LocationName.Lvl41] + KH2REGIONS[RegionName.LevelsVS12] = [LocationName.Lvl44, LocationName.Lvl46, LocationName.Lvl48] + KH2REGIONS[RegionName.LevelsVS15] = [LocationName.Lvl50] + # level 99 - elif world.LevelDepth[player] == "level_99": - levelVL1 = [LocationName.Lvl7, LocationName.Lvl9, ] - levelVL3 = [LocationName.Lvl12, LocationName.Lvl15, LocationName.Lvl17, LocationName.Lvl20] - levelVL6 = [LocationName.Lvl23, LocationName.Lvl25, LocationName.Lvl28] - levelVL9 = [LocationName.Lvl31, LocationName.Lvl33, LocationName.Lvl36, LocationName.Lvl39] - levelVL12 = [LocationName.Lvl41, LocationName.Lvl44, LocationName.Lvl47, LocationName.Lvl49] - levelVL15 = [LocationName.Lvl53, LocationName.Lvl59] - levelVL18 = [LocationName.Lvl65] - levelVL21 = [LocationName.Lvl73] - levelVL24 = [LocationName.Lvl85] - levelVL26 = [LocationName.Lvl99] + elif multiworld.LevelDepth[player] == "level_99": + KH2REGIONS[RegionName.LevelsVS1] = [LocationName.Lvl7, LocationName.Lvl9] + KH2REGIONS[RegionName.LevelsVS3] = [LocationName.Lvl12, LocationName.Lvl15, LocationName.Lvl17, + LocationName.Lvl20] + KH2REGIONS[RegionName.LevelsVS6] = [LocationName.Lvl23, LocationName.Lvl25, LocationName.Lvl28] + KH2REGIONS[RegionName.LevelsVS9] = [LocationName.Lvl31, LocationName.Lvl33, LocationName.Lvl36, + LocationName.Lvl39] + KH2REGIONS[RegionName.LevelsVS12] = [LocationName.Lvl41, LocationName.Lvl44, LocationName.Lvl47, + LocationName.Lvl49] + KH2REGIONS[RegionName.LevelsVS15] = [LocationName.Lvl53, LocationName.Lvl59] + KH2REGIONS[RegionName.LevelsVS18] = [LocationName.Lvl65] + KH2REGIONS[RegionName.LevelsVS21] = [LocationName.Lvl73] + KH2REGIONS[RegionName.LevelsVS24] = [LocationName.Lvl85] + KH2REGIONS[RegionName.LevelsVS26] = [LocationName.Lvl99] # level sanity # has to be [] instead of {} for in - elif world.LevelDepth[player] in ["level_50_sanity", "level_99_sanity"]: - levelVL1 = [LocationName.Lvl2, LocationName.Lvl3, LocationName.Lvl4, LocationName.Lvl5, LocationName.Lvl6, - LocationName.Lvl7, LocationName.Lvl8, LocationName.Lvl9, LocationName.Lvl10] - levelVL3 = [LocationName.Lvl11, LocationName.Lvl12, LocationName.Lvl13, LocationName.Lvl14, LocationName.Lvl15, - LocationName.Lvl16, LocationName.Lvl17, LocationName.Lvl18, LocationName.Lvl19, LocationName.Lvl20] - levelVL6 = [LocationName.Lvl21, LocationName.Lvl22, LocationName.Lvl23, LocationName.Lvl24, LocationName.Lvl25, - LocationName.Lvl26, LocationName.Lvl27, LocationName.Lvl28, LocationName.Lvl29, LocationName.Lvl30] - levelVL9 = [LocationName.Lvl31, LocationName.Lvl32, LocationName.Lvl33, LocationName.Lvl34, LocationName.Lvl35, - LocationName.Lvl36, LocationName.Lvl37, LocationName.Lvl38, LocationName.Lvl39, LocationName.Lvl40] - levelVL12 = [LocationName.Lvl41, LocationName.Lvl42, LocationName.Lvl43, LocationName.Lvl44, LocationName.Lvl45, - LocationName.Lvl46, LocationName.Lvl47, LocationName.Lvl48, LocationName.Lvl49, LocationName.Lvl50] + elif multiworld.LevelDepth[player] in ["level_50_sanity", "level_99_sanity"]: + KH2REGIONS[RegionName.LevelsVS1] = [LocationName.Lvl2, LocationName.Lvl3, LocationName.Lvl4, LocationName.Lvl5, + LocationName.Lvl6, + LocationName.Lvl7, LocationName.Lvl8, LocationName.Lvl9, LocationName.Lvl10] + KH2REGIONS[RegionName.LevelsVS3] = [LocationName.Lvl11, LocationName.Lvl12, LocationName.Lvl13, + LocationName.Lvl14, LocationName.Lvl15, + LocationName.Lvl16, LocationName.Lvl17, LocationName.Lvl18, + LocationName.Lvl19, LocationName.Lvl20] + KH2REGIONS[RegionName.LevelsVS6] = [LocationName.Lvl21, LocationName.Lvl22, LocationName.Lvl23, + LocationName.Lvl24, LocationName.Lvl25, + LocationName.Lvl26, LocationName.Lvl27, LocationName.Lvl28, + LocationName.Lvl29, LocationName.Lvl30] + KH2REGIONS[RegionName.LevelsVS9] = [LocationName.Lvl31, LocationName.Lvl32, LocationName.Lvl33, + LocationName.Lvl34, LocationName.Lvl35, + LocationName.Lvl36, LocationName.Lvl37, LocationName.Lvl38, + LocationName.Lvl39, LocationName.Lvl40] + KH2REGIONS[RegionName.LevelsVS12] = [LocationName.Lvl41, LocationName.Lvl42, LocationName.Lvl43, + LocationName.Lvl44, LocationName.Lvl45, + LocationName.Lvl46, LocationName.Lvl47, LocationName.Lvl48, + LocationName.Lvl49, LocationName.Lvl50] # level 99 sanity - if world.LevelDepth[player] == "level_99_sanity": - levelVL15 = [LocationName.Lvl51, LocationName.Lvl52, LocationName.Lvl53, LocationName.Lvl54, - LocationName.Lvl55, LocationName.Lvl56, LocationName.Lvl57, LocationName.Lvl58, - LocationName.Lvl59, LocationName.Lvl60] - levelVL18 = [LocationName.Lvl61, LocationName.Lvl62, LocationName.Lvl63, LocationName.Lvl64, - LocationName.Lvl65, LocationName.Lvl66, LocationName.Lvl67, LocationName.Lvl68, - LocationName.Lvl69, LocationName.Lvl70] - levelVL21 = [LocationName.Lvl71, LocationName.Lvl72, LocationName.Lvl73, LocationName.Lvl74, - LocationName.Lvl75, LocationName.Lvl76, LocationName.Lvl77, LocationName.Lvl78, - LocationName.Lvl79, LocationName.Lvl80] - levelVL24 = [LocationName.Lvl81, LocationName.Lvl82, LocationName.Lvl83, LocationName.Lvl84, - LocationName.Lvl85, LocationName.Lvl86, LocationName.Lvl87, LocationName.Lvl88, - LocationName.Lvl89, LocationName.Lvl90] - levelVL26 = [LocationName.Lvl91, LocationName.Lvl92, LocationName.Lvl93, LocationName.Lvl94, - LocationName.Lvl95, LocationName.Lvl96, LocationName.Lvl97, LocationName.Lvl98, - LocationName.Lvl99] - - level_regionVL1 = create_region(world, player, active_locations, RegionName.LevelsVS1, - levelVL1) - level_regionVL3 = create_region(world, player, active_locations, RegionName.LevelsVS3, - levelVL3) - level_regionVL6 = create_region(world, player, active_locations, RegionName.LevelsVS6, - levelVL6) - level_regionVL9 = create_region(world, player, active_locations, RegionName.LevelsVS9, - levelVL9) - level_regionVL12 = create_region(world, player, active_locations, RegionName.LevelsVS12, - levelVL12) - level_regionVL15 = create_region(world, player, active_locations, RegionName.LevelsVS15, - levelVL15) - level_regionVL18 = create_region(world, player, active_locations, RegionName.LevelsVS18, - levelVL18) - level_regionVL21 = create_region(world, player, active_locations, RegionName.LevelsVS21, - levelVL21) - level_regionVL24 = create_region(world, player, active_locations, RegionName.LevelsVS24, - levelVL24) - level_regionVL26 = create_region(world, player, active_locations, RegionName.LevelsVS26, - levelVL26) - world.regions += [level_regionVL1, level_regionVL3, level_regionVL6, level_regionVL9, level_regionVL12, - level_regionVL15, level_regionVL18, level_regionVL21, level_regionVL24, level_regionVL26] + if multiworld.LevelDepth[player] == "level_99_sanity": + KH2REGIONS[RegionName.LevelsVS15] = [LocationName.Lvl51, LocationName.Lvl52, LocationName.Lvl53, + LocationName.Lvl54, + LocationName.Lvl55, LocationName.Lvl56, LocationName.Lvl57, + LocationName.Lvl58, + LocationName.Lvl59, LocationName.Lvl60] + KH2REGIONS[RegionName.LevelsVS18] = [LocationName.Lvl61, LocationName.Lvl62, LocationName.Lvl63, + LocationName.Lvl64, + LocationName.Lvl65, LocationName.Lvl66, LocationName.Lvl67, + LocationName.Lvl68, + LocationName.Lvl69, LocationName.Lvl70] + KH2REGIONS[RegionName.LevelsVS21] = [LocationName.Lvl71, LocationName.Lvl72, LocationName.Lvl73, + LocationName.Lvl74, + LocationName.Lvl75, LocationName.Lvl76, LocationName.Lvl77, + LocationName.Lvl78, + LocationName.Lvl79, LocationName.Lvl80] + KH2REGIONS[RegionName.LevelsVS24] = [LocationName.Lvl81, LocationName.Lvl82, LocationName.Lvl83, + LocationName.Lvl84, + LocationName.Lvl85, LocationName.Lvl86, LocationName.Lvl87, + LocationName.Lvl88, + LocationName.Lvl89, LocationName.Lvl90] + KH2REGIONS[RegionName.LevelsVS26] = [LocationName.Lvl91, LocationName.Lvl92, LocationName.Lvl93, + LocationName.Lvl94, + LocationName.Lvl95, LocationName.Lvl96, LocationName.Lvl97, + LocationName.Lvl98, LocationName.Lvl99] + KH2REGIONS[RegionName.Summon] = [] + if multiworld.SummonLevelLocationToggle[player]: + KH2REGIONS[RegionName.Summon] = [LocationName.Summonlvl2, + LocationName.Summonlvl3, + LocationName.Summonlvl4, + LocationName.Summonlvl5, + LocationName.Summonlvl6, + LocationName.Summonlvl7] + multiworld.regions += [create_region(multiworld, player, active_locations, region, locations) for region, locations in + KH2REGIONS.items()] + # fill the event locations with events + multiworld.worlds[player].item_name_to_id.update({event_name: None for event_name in Events_Table}) + for location, item in event_location_to_item.items(): + multiworld.get_location(location, player).place_locked_item( + multiworld.worlds[player].create_item(item)) -def connect_regions(world: MultiWorld, player: int): +def connect_regions(self): + multiworld = self.multiworld + player = self.player # connecting every first visit to the GoA + KH2RegionConnections: typing.Dict[str, typing.Set[str]] = { + "Menu": {RegionName.GoA}, + RegionName.GoA: {RegionName.Sp, RegionName.Pr, RegionName.Tt, RegionName.Oc, RegionName.Ht, + RegionName.LoD, + RegionName.Twtnw, RegionName.Bc, RegionName.Ag, RegionName.Pl, RegionName.Hb, + RegionName.Dc, RegionName.Stt, + RegionName.Ha1, RegionName.Keyblade, RegionName.LevelsVS1, + RegionName.Valor, RegionName.Wisdom, RegionName.Limit, RegionName.Master, + RegionName.Final, RegionName.Summon, RegionName.AtlanticaSongOne}, + RegionName.LoD: {RegionName.ShanYu}, + RegionName.ShanYu: {RegionName.LoD2}, + RegionName.LoD2: {RegionName.AnsemRiku}, + RegionName.AnsemRiku: {RegionName.StormRider}, + RegionName.StormRider: {RegionName.DataXigbar}, + RegionName.Ag: {RegionName.TwinLords}, + RegionName.TwinLords: {RegionName.Ag2}, + RegionName.Ag2: {RegionName.GenieJafar}, + RegionName.GenieJafar: {RegionName.DataLexaeus}, + RegionName.Dc: {RegionName.Tr}, + RegionName.Tr: {RegionName.OldPete}, + RegionName.OldPete: {RegionName.FuturePete}, + RegionName.FuturePete: {RegionName.Terra, RegionName.DataMarluxia}, + RegionName.Ha1: {RegionName.Ha2}, + RegionName.Ha2: {RegionName.Ha3}, + RegionName.Ha3: {RegionName.Ha4}, + RegionName.Ha4: {RegionName.Ha5}, + RegionName.Ha5: {RegionName.Ha6}, + RegionName.Pr: {RegionName.Barbosa}, + RegionName.Barbosa: {RegionName.Pr2}, + RegionName.Pr2: {RegionName.GrimReaper1}, + RegionName.GrimReaper1: {RegionName.GrimReaper2}, + RegionName.GrimReaper2: {RegionName.DataLuxord}, + RegionName.Oc: {RegionName.Cerberus}, + RegionName.Cerberus: {RegionName.OlympusPete}, + RegionName.OlympusPete: {RegionName.Hydra}, + RegionName.Hydra: {RegionName.OcPainAndPanicCup, RegionName.OcCerberusCup, RegionName.Oc2}, + RegionName.Oc2: {RegionName.Hades}, + RegionName.Hades: {RegionName.Oc2TitanCup, RegionName.Oc2GofCup, RegionName.DataZexion}, + RegionName.Oc2GofCup: {RegionName.HadesCups}, + RegionName.Bc: {RegionName.Thresholder}, + RegionName.Thresholder: {RegionName.Beast}, + RegionName.Beast: {RegionName.DarkThorn}, + RegionName.DarkThorn: {RegionName.Bc2}, + RegionName.Bc2: {RegionName.Xaldin}, + RegionName.Xaldin: {RegionName.DataXaldin}, + RegionName.Sp: {RegionName.HostileProgram}, + RegionName.HostileProgram: {RegionName.Sp2}, + RegionName.Sp2: {RegionName.Mcp}, + RegionName.Mcp: {RegionName.DataLarxene}, + RegionName.Ht: {RegionName.PrisonKeeper}, + RegionName.PrisonKeeper: {RegionName.OogieBoogie}, + RegionName.OogieBoogie: {RegionName.Ht2}, + RegionName.Ht2: {RegionName.Experiment}, + RegionName.Experiment: {RegionName.DataVexen}, + RegionName.Hb: {RegionName.Hb2}, + RegionName.Hb2: {RegionName.CoR, RegionName.HBDemyx}, + RegionName.HBDemyx: {RegionName.ThousandHeartless}, + RegionName.ThousandHeartless: {RegionName.Mushroom13, RegionName.DataDemyx, RegionName.Sephi}, + RegionName.CoR: {RegionName.CorFirstFight}, + RegionName.CorFirstFight: {RegionName.CorSecondFight}, + RegionName.CorSecondFight: {RegionName.Transport}, + RegionName.Pl: {RegionName.Scar}, + RegionName.Scar: {RegionName.Pl2}, + RegionName.Pl2: {RegionName.GroundShaker}, + RegionName.GroundShaker: {RegionName.DataSaix}, + RegionName.Stt: {RegionName.TwilightThorn}, + RegionName.TwilightThorn: {RegionName.Axel1}, + RegionName.Axel1: {RegionName.Axel2}, + RegionName.Axel2: {RegionName.DataRoxas}, + RegionName.Tt: {RegionName.Tt2}, + RegionName.Tt2: {RegionName.Tt3}, + RegionName.Tt3: {RegionName.DataAxel}, + RegionName.Twtnw: {RegionName.Roxas}, + RegionName.Roxas: {RegionName.Xigbar}, + RegionName.Xigbar: {RegionName.Luxord}, + RegionName.Luxord: {RegionName.Saix}, + RegionName.Saix: {RegionName.Twtnw2}, + RegionName.Twtnw2: {RegionName.Xemnas}, + RegionName.Xemnas: {RegionName.ArmoredXemnas, RegionName.DataXemnas}, + RegionName.ArmoredXemnas: {RegionName.ArmoredXemnas2}, + RegionName.ArmoredXemnas2: {RegionName.FinalXemnas}, + RegionName.LevelsVS1: {RegionName.LevelsVS3}, + RegionName.LevelsVS3: {RegionName.LevelsVS6}, + RegionName.LevelsVS6: {RegionName.LevelsVS9}, + RegionName.LevelsVS9: {RegionName.LevelsVS12}, + RegionName.LevelsVS12: {RegionName.LevelsVS15}, + RegionName.LevelsVS15: {RegionName.LevelsVS18}, + RegionName.LevelsVS18: {RegionName.LevelsVS21}, + RegionName.LevelsVS21: {RegionName.LevelsVS24}, + RegionName.LevelsVS24: {RegionName.LevelsVS26}, + RegionName.AtlanticaSongOne: {RegionName.AtlanticaSongTwo}, + RegionName.AtlanticaSongTwo: {RegionName.AtlanticaSongThree}, + RegionName.AtlanticaSongThree: {RegionName.AtlanticaSongFour}, + } - names: typing.Dict[str, int] = {} - - connect(world, player, names, "Menu", RegionName.Keyblade_Region) - connect(world, player, names, "Menu", RegionName.GoA_Region) - - connect(world, player, names, RegionName.GoA_Region, RegionName.LoD_Region, - lambda state: state.kh_lod_unlocked(player, 1)) - connect(world, player, names, RegionName.LoD_Region, RegionName.LoD2_Region, - lambda state: state.kh_lod_unlocked(player, 2)) - - connect(world, player, names, RegionName.GoA_Region, RegionName.Oc_Region, - lambda state: state.kh_oc_unlocked(player, 1)) - connect(world, player, names, RegionName.Oc_Region, RegionName.Oc2_Region, - lambda state: state.kh_oc_unlocked(player, 2)) - connect(world, player, names, RegionName.Oc2_Region, RegionName.Zexion_Region, - lambda state: state.kh_datazexion(player)) - - connect(world, player, names, RegionName.Oc2_Region, RegionName.Oc2_pain_and_panic_Region, - lambda state: state.kh_painandpanic(player)) - connect(world, player, names, RegionName.Oc2_Region, RegionName.Oc2_cerberus_Region, - lambda state: state.kh_cerberuscup(player)) - connect(world, player, names, RegionName.Oc2_Region, RegionName.Oc2_titan_Region, - lambda state: state.kh_titan(player)) - connect(world, player, names, RegionName.Oc2_Region, RegionName.Oc2_gof_Region, - lambda state: state.kh_gof(player)) - - connect(world, player, names, RegionName.GoA_Region, RegionName.Ag_Region, - lambda state: state.kh_ag_unlocked(player, 1)) - connect(world, player, names, RegionName.Ag_Region, RegionName.Ag2_Region, - lambda state: state.kh_ag_unlocked(player, 2) - and (state.has(ItemName.FireElement, player) - and state.has(ItemName.BlizzardElement, player) - and state.has(ItemName.ThunderElement, player))) - connect(world, player, names, RegionName.Ag2_Region, RegionName.Lexaeus_Region, - lambda state: state.kh_datalexaeus(player)) - - connect(world, player, names, RegionName.GoA_Region, RegionName.Dc_Region, - lambda state: state.kh_dc_unlocked(player, 1)) - connect(world, player, names, RegionName.Dc_Region, RegionName.Tr_Region, - lambda state: state.kh_dc_unlocked(player, 2)) - connect(world, player, names, RegionName.Tr_Region, RegionName.Marluxia_Region, - lambda state: state.kh_datamarluxia(player)) - connect(world, player, names, RegionName.Tr_Region, RegionName.Terra_Region, lambda state: state.kh_terra(player)) - - connect(world, player, names, RegionName.GoA_Region, RegionName.Pr_Region, - lambda state: state.kh_pr_unlocked(player, 1)) - connect(world, player, names, RegionName.Pr_Region, RegionName.Pr2_Region, - lambda state: state.kh_pr_unlocked(player, 2)) - connect(world, player, names, RegionName.Pr2_Region, RegionName.Gr2_Region, - lambda state: state.kh_gr2(player)) - - connect(world, player, names, RegionName.GoA_Region, RegionName.Bc_Region, - lambda state: state.kh_bc_unlocked(player, 1)) - connect(world, player, names, RegionName.Bc_Region, RegionName.Bc2_Region, - lambda state: state.kh_bc_unlocked(player, 2)) - connect(world, player, names, RegionName.Bc2_Region, RegionName.Xaldin_Region, - lambda state: state.kh_xaldin(player)) - - connect(world, player, names, RegionName.GoA_Region, RegionName.Sp_Region, - lambda state: state.kh_sp_unlocked(player, 1)) - connect(world, player, names, RegionName.Sp_Region, RegionName.Sp2_Region, - lambda state: state.kh_sp_unlocked(player, 2)) - connect(world, player, names, RegionName.Sp2_Region, RegionName.Mcp_Region, - lambda state: state.kh_mcp(player)) - connect(world, player, names, RegionName.Mcp_Region, RegionName.Larxene_Region, - lambda state: state.kh_datalarxene(player)) - - connect(world, player, names, RegionName.GoA_Region, RegionName.Ht_Region, - lambda state: state.kh_ht_unlocked(player, 1)) - connect(world, player, names, RegionName.Ht_Region, RegionName.Ht2_Region, - lambda state: state.kh_ht_unlocked(player, 2)) - connect(world, player, names, RegionName.Ht2_Region, RegionName.Vexen_Region, - lambda state: state.kh_datavexen(player)) - - connect(world, player, names, RegionName.GoA_Region, RegionName.Hb_Region, - lambda state: state.kh_hb_unlocked(player, 1)) - connect(world, player, names, RegionName.Hb_Region, RegionName.Hb2_Region, - lambda state: state.kh_hb_unlocked(player, 2)) - connect(world, player, names, RegionName.Hb2_Region, RegionName.ThousandHeartless_Region, - lambda state: state.kh_onek(player)) - connect(world, player, names, RegionName.ThousandHeartless_Region, RegionName.Mushroom13_Region, - lambda state: state.has(ItemName.ProofofPeace, player)) - connect(world, player, names, RegionName.ThousandHeartless_Region, RegionName.Sephi_Region, - lambda state: state.kh_sephi(player)) - - connect(world, player, names, RegionName.Hb2_Region, RegionName.CoR_Region, lambda state: state.kh_cor(player)) - connect(world, player, names, RegionName.CoR_Region, RegionName.Transport_Region, lambda state: - state.has(ItemName.HighJump, player, 3) - and state.has(ItemName.AerialDodge, player, 3) - and state.has(ItemName.Glide, player, 3)) - - connect(world, player, names, RegionName.GoA_Region, RegionName.Pl_Region, - lambda state: state.kh_pl_unlocked(player, 1)) - connect(world, player, names, RegionName.Pl_Region, RegionName.Pl2_Region, - lambda state: state.kh_pl_unlocked(player, 2) and ( - state.has(ItemName.BerserkCharge, player) or state.kh_reflect(player))) - - connect(world, player, names, RegionName.GoA_Region, RegionName.STT_Region, - lambda state: state.kh_stt_unlocked(player, 1)) - - connect(world, player, names, RegionName.GoA_Region, RegionName.TT_Region, - lambda state: state.kh_tt_unlocked(player, 1)) - connect(world, player, names, RegionName.TT_Region, RegionName.TT2_Region, - lambda state: state.kh_tt_unlocked(player, 2)) - connect(world, player, names, RegionName.TT2_Region, RegionName.TT3_Region, - lambda state: state.kh_tt_unlocked(player, 3)) - - connect(world, player, names, RegionName.GoA_Region, RegionName.Twtnw_Region, - lambda state: state.kh_twtnw_unlocked(player, 0)) - connect(world, player, names, RegionName.Twtnw_Region, RegionName.Twtnw_PostRoxas, - lambda state: state.kh_roxastools(player)) - connect(world, player, names, RegionName.Twtnw_PostRoxas, RegionName.Twtnw_PostXigbar, - lambda state: state.kh_basetools(player) and (state.kh_donaldlimit(player) or ( - state.has(ItemName.FinalForm, player) and state.has(ItemName.FireElement, player)))) - connect(world, player, names, RegionName.Twtnw_PostRoxas, RegionName.Twtnw2_Region, - lambda state: state.kh_twtnw_unlocked(player, 1)) - - hundredacrevisits = {RegionName.HundredAcre1_Region: 0, RegionName.HundredAcre2_Region: 1, - RegionName.HundredAcre3_Region: 2, - RegionName.HundredAcre4_Region: 3, RegionName.HundredAcre5_Region: 4, - RegionName.HundredAcre6_Region: 5} - for visit, tornpage in hundredacrevisits.items(): - connect(world, player, names, RegionName.GoA_Region, visit, - lambda state: (state.has(ItemName.TornPages, player, tornpage))) - - connect(world, player, names, RegionName.GoA_Region, RegionName.LevelsVS1, - lambda state: state.kh_visit_locking_amount(player, 1)) - connect(world, player, names, RegionName.LevelsVS1, RegionName.LevelsVS3, - lambda state: state.kh_visit_locking_amount(player, 3)) - connect(world, player, names, RegionName.LevelsVS3, RegionName.LevelsVS6, - lambda state: state.kh_visit_locking_amount(player, 6)) - connect(world, player, names, RegionName.LevelsVS6, RegionName.LevelsVS9, - lambda state: state.kh_visit_locking_amount(player, 9)) - connect(world, player, names, RegionName.LevelsVS9, RegionName.LevelsVS12, - lambda state: state.kh_visit_locking_amount(player, 12)) - connect(world, player, names, RegionName.LevelsVS12, RegionName.LevelsVS15, - lambda state: state.kh_visit_locking_amount(player, 15)) - connect(world, player, names, RegionName.LevelsVS15, RegionName.LevelsVS18, - lambda state: state.kh_visit_locking_amount(player, 18)) - connect(world, player, names, RegionName.LevelsVS18, RegionName.LevelsVS21, - lambda state: state.kh_visit_locking_amount(player, 21)) - connect(world, player, names, RegionName.LevelsVS21, RegionName.LevelsVS24, - lambda state: state.kh_visit_locking_amount(player, 24)) - connect(world, player, names, RegionName.LevelsVS24, RegionName.LevelsVS26, - lambda state: state.kh_visit_locking_amount(player, 25)) # 25 because of goa twtnw bugs with visit locking. - - for region in RegionTable["ValorRegion"]: - connect(world, player, names, region, RegionName.Valor_Region, - lambda state: state.has(ItemName.ValorForm, player)) - for region in RegionTable["WisdomRegion"]: - connect(world, player, names, region, RegionName.Wisdom_Region, - lambda state: state.has(ItemName.WisdomForm, player)) - for region in RegionTable["LimitRegion"]: - connect(world, player, names, region, RegionName.Limit_Region, - lambda state: state.has(ItemName.LimitForm, player)) - for region in RegionTable["MasterRegion"]: - connect(world, player, names, region, RegionName.Master_Region, - lambda state: state.has(ItemName.MasterForm, player) and state.has(ItemName.DriveConverter, player)) - for region in RegionTable["FinalRegion"]: - connect(world, player, names, region, RegionName.Final_Region, - lambda state: state.has(ItemName.FinalForm, player)) - - -# shamelessly stolen from the sa2b -def connect(world: MultiWorld, player: int, used_names: typing.Dict[str, int], source: str, target: str, - rule: typing.Optional[typing.Callable] = None): - source_region = world.get_region(source, player) - target_region = world.get_region(target, player) - - if target not in used_names: - used_names[target] = 1 - name = target - else: - used_names[target] += 1 - name = target + (' ' * used_names[target]) - - connection = Entrance(player, name, source_region) - - if rule: - connection.access_rule = rule + for source, target in KH2RegionConnections.items(): + source_region = multiworld.get_region(source, player) + source_region.add_exits(target) - source_region.exits.append(connection) - connection.connect(target_region) +# cave fight:fire/guard +# hades escape logic:fire,blizzard,slide dash, base tools +# windows:chicken little.fire element,base tools +# chasm of challenges:reflect, blizzard, trinity limit,chicken little +# living bones: magnet +# some things for barbosa(PR), chicken little +# hyneas(magnet,reflect) +# tt2: reflect,chicken,form, guard,aerial recovery,finising plus, +# corridors,dancers:chicken little or stitch +demyx tools +# 1k: guard,once more,limit form, +# snipers +before: stitch, magnet, finishing leap, base tools, reflect +# dragoons:stitch, magnet, base tools, reflect +# oc2 tournament thing: stitch, magnet, base tools, reflera +# lock,shock and barrel: reflect, base tools +# carpet section: magnera, reflect, base tools, +# sp2: reflera, stitch, basse tools, reflera, thundara, fantasia/duck flare,once more. +# tt3: stitch/chicken little, magnera,reflera,base tools,finishing leap,limit form +# cor -def create_region(world: MultiWorld, player: int, active_locations, name: str, locations=None): - ret = Region(name, player, world) +def create_region(multiworld, player: int, active_locations, name: str, locations=None): + ret = Region(name, player, multiworld) if locations: - for location in locations: - loc_id = active_locations.get(location, 0) - if loc_id: - location = KH2Location(player, location, loc_id.code, ret) - ret.locations.append(location) + loc_to_id = {loc: active_locations.get(loc, 0) for loc in locations if active_locations.get(loc, None)} + ret.add_locations(loc_to_id, KH2Location) + loc_to_event = {loc: active_locations.get(loc, None) for loc in locations if + not active_locations.get(loc, None)} + ret.add_locations(loc_to_event, KH2Location) return ret diff --git a/worlds/kh2/Rules.py b/worlds/kh2/Rules.py index b86ae4a2db4f..18375231a5a6 100644 --- a/worlds/kh2/Rules.py +++ b/worlds/kh2/Rules.py @@ -1,96 +1,1163 @@ +from typing import Dict, Callable, TYPE_CHECKING -from BaseClasses import MultiWorld - -from .Items import exclusionItem_table -from .Locations import STT_Checks, exclusion_table -from .Names import LocationName, ItemName -from ..generic.Rules import add_rule, forbid_items, set_rule - - -def set_rules(world: MultiWorld, player: int): - - add_rule(world.get_location(LocationName.RoxasDataMagicBoost, player), - lambda state: state.kh_dataroxas(player)) - add_rule(world.get_location(LocationName.DemyxDataAPBoost, player), - lambda state: state.kh_datademyx(player)) - add_rule(world.get_location(LocationName.SaixDataDefenseBoost, player), - lambda state: state.kh_datasaix(player)) - add_rule(world.get_location(LocationName.XaldinDataDefenseBoost, player), - lambda state: state.kh_dataxaldin(player)) - add_rule(world.get_location(LocationName.XemnasDataPowerBoost, player), - lambda state: state.kh_dataxemnas(player)) - add_rule(world.get_location(LocationName.XigbarDataDefenseBoost, player), - lambda state: state.kh_dataxigbar(player)) - add_rule(world.get_location(LocationName.VexenDataLostIllusion, player), - lambda state: state.kh_dataaxel(player)) - add_rule(world.get_location(LocationName.LuxordDataAPBoost, player), - lambda state: state.kh_dataluxord(player)) - - for slot, weapon in exclusion_table["WeaponSlots"].items(): - add_rule(world.get_location(slot, player), lambda state: state.has(weapon, player)) - formLogicTable = { - ItemName.ValorForm: [LocationName.Valorlvl4, - LocationName.Valorlvl5, - LocationName.Valorlvl6, - LocationName.Valorlvl7], - ItemName.WisdomForm: [LocationName.Wisdomlvl4, - LocationName.Wisdomlvl5, - LocationName.Wisdomlvl6, - LocationName.Wisdomlvl7], - ItemName.LimitForm: [LocationName.Limitlvl4, - LocationName.Limitlvl5, - LocationName.Limitlvl6, - LocationName.Limitlvl7], - ItemName.MasterForm: [LocationName.Masterlvl4, - LocationName.Masterlvl5, - LocationName.Masterlvl6, - LocationName.Masterlvl7], - ItemName.FinalForm: [LocationName.Finallvl4, - LocationName.Finallvl5, - LocationName.Finallvl6, - LocationName.Finallvl7] - } - - for form in formLogicTable: - for i in range(4): - location = world.get_location(formLogicTable[form][i], player) - set_rule(location, lambda state, i=i + 1, form=form: state.kh_amount_of_forms(player, i, form)) - - if world.Goal[player] == "three_proofs": - add_rule(world.get_location(LocationName.FinalXemnas, player), - lambda state: state.kh_three_proof_unlocked(player)) - if world.FinalXemnas[player]: - world.completion_condition[player] = lambda state: state.kh_victory(player) - else: - world.completion_condition[player] = lambda state: state.kh_three_proof_unlocked(player) - # lucky emblem hunt - elif world.Goal[player] == "lucky_emblem_hunt": - add_rule(world.get_location(LocationName.FinalXemnas, player), - lambda state: state.kh_lucky_emblem_unlocked(player, world.LuckyEmblemsRequired[player].value)) - if world.FinalXemnas[player]: - world.completion_condition[player] = lambda state: state.kh_victory(player) - else: - world.completion_condition[player] = lambda state: state.kh_lucky_emblem_unlocked(player, world.LuckyEmblemsRequired[player].value) - # hitlist if == 2 - else: - add_rule(world.get_location(LocationName.FinalXemnas, player), - lambda state: state.kh_hitlist(player, world.BountyRequired[player].value)) - if world.FinalXemnas[player]: - world.completion_condition[player] = lambda state: state.kh_victory(player) +from BaseClasses import CollectionState +from .Items import exclusion_item_table, visit_locking_dict, DonaldAbility_Table, GoofyAbility_Table +from .Locations import exclusion_table, popups_set, Goofy_Checks, Donald_Checks +from .Names import LocationName, ItemName, RegionName +from worlds.generic.Rules import add_rule, forbid_items, add_item_rule +from .Logic import * + +# I don't know what is going on here, but it works. +if TYPE_CHECKING: + from . import KH2World +else: + KH2World = object + + +# Shamelessly Stolen from Messanger + + +class KH2Rules: + player: int + world: KH2World + # World Rules: Rules for the visit locks + # Location Rules: Deterministic of player settings. + # Form Rules: Rules for Drive Forms and Summon levels. These Are Locations + # Fight Rules: Rules for fights. These are regions in the worlds. + world_rules: Dict[str, Callable[[CollectionState], bool]] + location_rules: Dict[str, Callable[[CollectionState], bool]] + + fight_rules: Dict[str, Callable[[CollectionState], bool]] + + def __init__(self, world: KH2World) -> None: + self.player = world.player + self.world = world + self.multiworld = world.multiworld + + def lod_unlocked(self, state: CollectionState, Amount) -> bool: + return state.has(ItemName.SwordoftheAncestor, self.player, Amount) + + def oc_unlocked(self, state: CollectionState, Amount) -> bool: + return state.has(ItemName.BattlefieldsofWar, self.player, Amount) + + def twtnw_unlocked(self, state: CollectionState, Amount) -> bool: + return state.has(ItemName.WaytotheDawn, self.player, Amount) + + def ht_unlocked(self, state: CollectionState, Amount) -> bool: + return state.has(ItemName.BoneFist, self.player, Amount) + + def tt_unlocked(self, state: CollectionState, Amount) -> bool: + return state.has(ItemName.IceCream, self.player, Amount) + + def pr_unlocked(self, state: CollectionState, Amount) -> bool: + return state.has(ItemName.SkillandCrossbones, self.player, Amount) + + def sp_unlocked(self, state: CollectionState, Amount) -> bool: + return state.has(ItemName.IdentityDisk, self.player, Amount) + + def stt_unlocked(self, state: CollectionState, Amount) -> bool: + return state.has(ItemName.NamineSketches, self.player, Amount) + + def dc_unlocked(self, state: CollectionState, Amount) -> bool: + return state.has(ItemName.CastleKey, self.player, Amount) # Using Dummy 13 for this + + def hb_unlocked(self, state: CollectionState, Amount) -> bool: + return state.has(ItemName.MembershipCard, self.player, Amount) + + def pl_unlocked(self, state: CollectionState, Amount) -> bool: + return state.has(ItemName.ProudFang, self.player, Amount) + + def ag_unlocked(self, state: CollectionState, Amount) -> bool: + return state.has(ItemName.Scimitar, self.player, Amount) + + def bc_unlocked(self, state: CollectionState, Amount) -> bool: + return state.has(ItemName.BeastsClaw, self.player, Amount) + + def at_three_unlocked(self, state: CollectionState) -> bool: + return state.has(ItemName.MagnetElement, self.player, 2) + + def at_four_unlocked(self, state: CollectionState) -> bool: + return state.has(ItemName.ThunderElement, self.player, 3) + + def hundred_acre_unlocked(self, state: CollectionState, amount) -> bool: + return state.has(ItemName.TornPages, self.player, amount) + + def level_locking_unlock(self, state: CollectionState, amount): + return amount <= sum([state.count(item_name, self.player) for item_name in visit_locking_dict["2VisitLocking"]]) + + def summon_levels_unlocked(self, state: CollectionState, amount) -> bool: + return amount <= sum([state.count(item_name, self.player) for item_name in summons]) + + def kh2_list_count_sum(self, item_name_set: list, state: CollectionState) -> int: + """ + Returns the sum of state.count() for each item in the list. + """ + return sum( + [state.count(item_name, self.player) for item_name in item_name_set] + ) + + def kh2_list_any_sum(self, list_of_item_name_list: list, state: CollectionState) -> int: + """ + Returns sum that increments by 1 if state.has_any + """ + return sum( + [1 for item_list in list_of_item_name_list if + state.has_any(set(item_list), self.player)] + ) + + def kh2_dict_count(self, item_name_to_count: dict, state: CollectionState) -> bool: + """ + simplifies count to a dictionary. + """ + return all( + [state.count(item_name, self.player) >= item_amount for item_name, item_amount in + item_name_to_count.items()] + ) + + def kh2_dict_one_count(self, item_name_to_count: dict, state: CollectionState) -> int: + """ + simplifies count to a dictionary. + """ + return sum( + [1 for item_name, item_amount in + item_name_to_count.items() if state.count(item_name, self.player) >= item_amount] + ) + + def kh2_can_reach_any(self, loc_set: list, state: CollectionState): + """ + Can reach any locations in the set. + """ + return any( + [self.kh2_can_reach(location, state) for location in + loc_set] + ) + + def kh2_can_reach_all(self, loc_list: list, state: CollectionState): + """ + Can reach all locations in the set. + """ + return all( + [self.kh2_can_reach(location, state) for location in loc_list] + ) + + def kh2_can_reach(self, loc: str, state: CollectionState): + """ + Returns bool instead of collection state. + """ + return state.can_reach(self.multiworld.get_location(loc, self.player), "location", self.player) + + def kh2_has_all(self, items: list, state: CollectionState): + """If state has at least one of all.""" + return state.has_all(set(items), self.player) + + def kh2_has_any(self, items: list, state: CollectionState): + return state.has_any(set(items), self.player) + + def form_list_unlock(self, state: CollectionState, parent_form_list, level_required, fight_logic=False) -> bool: + form_access = {parent_form_list} + if self.multiworld.AutoFormLogic[self.player] and state.has(ItemName.SecondChance, self.player) and not fight_logic: + if parent_form_list == ItemName.MasterForm: + if state.has(ItemName.DriveConverter, self.player): + form_access.add(auto_form_dict[parent_form_list]) + else: + form_access.add(auto_form_dict[parent_form_list]) + return state.has_any(form_access, self.player) \ + and self.get_form_level_requirement(state, level_required) + + def get_form_level_requirement(self, state, amount): + forms_available = 0 + form_list = [ItemName.ValorForm, ItemName.WisdomForm, ItemName.LimitForm, ItemName.MasterForm, + ItemName.FinalForm] + if self.world.multiworld.FinalFormLogic[self.player] != "no_light_and_darkness": + if self.world.multiworld.FinalFormLogic[self.player] == "light_and_darkness": + if state.has(ItemName.LightDarkness, self.player) and state.has_any(set(form_list), self.player): + forms_available += 1 + form_list.remove(ItemName.FinalForm) + else: # self.multiworld.FinalFormLogic=="just a form" + form_list.remove(ItemName.FinalForm) + if state.has_any(form_list, self.player): + forms_available += 1 + forms_available += sum([1 for form in form_list if state.has(form, self.player)]) + return forms_available >= amount + + +class KH2WorldRules(KH2Rules): + def __init__(self, kh2world: KH2World) -> None: + # These Rules are Always in effect + super().__init__(kh2world) + self.region_rules = { + RegionName.LoD: lambda state: self.lod_unlocked(state, 1), + RegionName.LoD2: lambda state: self.lod_unlocked(state, 2), + + RegionName.Oc: lambda state: self.oc_unlocked(state, 1), + RegionName.Oc2: lambda state: self.oc_unlocked(state, 2), + + RegionName.Twtnw2: lambda state: self.twtnw_unlocked(state, 2), + # These will be swapped and First Visit lock for twtnw is in development. + # RegionName.Twtnw1: lambda state: self.lod_unlocked(state, 2), + + RegionName.Ht: lambda state: self.ht_unlocked(state, 1), + RegionName.Ht2: lambda state: self.ht_unlocked(state, 2), + + RegionName.Tt: lambda state: self.tt_unlocked(state, 1), + RegionName.Tt2: lambda state: self.tt_unlocked(state, 2), + RegionName.Tt3: lambda state: self.tt_unlocked(state, 3), + + RegionName.Pr: lambda state: self.pr_unlocked(state, 1), + RegionName.Pr2: lambda state: self.pr_unlocked(state, 2), + + RegionName.Sp: lambda state: self.sp_unlocked(state, 1), + RegionName.Sp2: lambda state: self.sp_unlocked(state, 2), + + RegionName.Stt: lambda state: self.stt_unlocked(state, 1), + + RegionName.Dc: lambda state: self.dc_unlocked(state, 1), + RegionName.Tr: lambda state: self.dc_unlocked(state, 2), + # Terra is a fight and can have more than just this requirement. + # RegionName.Terra: lambda state:state.has(ItemName.ProofofConnection,self.player), + + RegionName.Hb: lambda state: self.hb_unlocked(state, 1), + RegionName.Hb2: lambda state: self.hb_unlocked(state, 2), + RegionName.Mushroom13: lambda state: state.has(ItemName.ProofofPeace, self.player), + + RegionName.Pl: lambda state: self.pl_unlocked(state, 1), + RegionName.Pl2: lambda state: self.pl_unlocked(state, 2), + + RegionName.Ag: lambda state: self.ag_unlocked(state, 1), + RegionName.Ag2: lambda state: self.ag_unlocked(state, 2), + + RegionName.Bc: lambda state: self.bc_unlocked(state, 1), + RegionName.Bc2: lambda state: self.bc_unlocked(state, 2), + + RegionName.AtlanticaSongThree: lambda state: self.at_three_unlocked(state), + RegionName.AtlanticaSongFour: lambda state: self.at_four_unlocked(state), + + RegionName.Ha1: lambda state: True, + RegionName.Ha2: lambda state: self.hundred_acre_unlocked(state, 1), + RegionName.Ha3: lambda state: self.hundred_acre_unlocked(state, 2), + RegionName.Ha4: lambda state: self.hundred_acre_unlocked(state, 3), + RegionName.Ha5: lambda state: self.hundred_acre_unlocked(state, 4), + RegionName.Ha6: lambda state: self.hundred_acre_unlocked(state, 5), + + RegionName.LevelsVS1: lambda state: self.level_locking_unlock(state, 1), + RegionName.LevelsVS3: lambda state: self.level_locking_unlock(state, 3), + RegionName.LevelsVS6: lambda state: self.level_locking_unlock(state, 6), + RegionName.LevelsVS9: lambda state: self.level_locking_unlock(state, 9), + RegionName.LevelsVS12: lambda state: self.level_locking_unlock(state, 12), + RegionName.LevelsVS15: lambda state: self.level_locking_unlock(state, 15), + RegionName.LevelsVS18: lambda state: self.level_locking_unlock(state, 18), + RegionName.LevelsVS21: lambda state: self.level_locking_unlock(state, 21), + RegionName.LevelsVS24: lambda state: self.level_locking_unlock(state, 24), + RegionName.LevelsVS26: lambda state: self.level_locking_unlock(state, 26), + } + + def set_kh2_rules(self) -> None: + for region_name, rules in self.region_rules.items(): + region = self.multiworld.get_region(region_name, self.player) + for entrance in region.entrances: + entrance.access_rule = rules + + self.set_kh2_goal() + + weapon_region = self.multiworld.get_region(RegionName.Keyblade, self.player) + for location in weapon_region.locations: + add_rule(location, lambda state: state.has(exclusion_table["WeaponSlots"][location.name], self.player)) + if location.name in Goofy_Checks: + add_item_rule(location, lambda item: item.player == self.player and item.name in GoofyAbility_Table.keys()) + elif location.name in Donald_Checks: + add_item_rule(location, lambda item: item.player == self.player and item.name in DonaldAbility_Table.keys()) + + def set_kh2_goal(self): + + final_xemnas_location = self.multiworld.get_location(LocationName.FinalXemnas, self.player) + if self.multiworld.Goal[self.player] == "three_proofs": + final_xemnas_location.access_rule = lambda state: self.kh2_has_all(three_proofs, state) + if self.multiworld.FinalXemnas[self.player]: + self.multiworld.completion_condition[self.player] = lambda state: state.has(ItemName.Victory, self.player, 1) + else: + self.multiworld.completion_condition[self.player] = lambda state: self.kh2_has_all(three_proofs, state) + # lucky emblem hunt + elif self.multiworld.Goal[self.player] == "lucky_emblem_hunt": + final_xemnas_location.access_rule = lambda state: state.has(ItemName.LuckyEmblem, self.player, self.multiworld.LuckyEmblemsRequired[self.player].value) + if self.multiworld.FinalXemnas[self.player]: + self.multiworld.completion_condition[self.player] = lambda state: state.has(ItemName.Victory, self.player, 1) + else: + self.multiworld.completion_condition[self.player] = lambda state: state.has(ItemName.LuckyEmblem, self.player, self.multiworld.LuckyEmblemsRequired[self.player].value) + # hitlist if == 2 + elif self.multiworld.Goal[self.player] == "hitlist": + final_xemnas_location.access_rule = lambda state: state.has(ItemName.Bounty, self.player, self.multiworld.BountyRequired[self.player].value) + if self.multiworld.FinalXemnas[self.player]: + self.multiworld.completion_condition[self.player] = lambda state: state.has(ItemName.Victory, self.player, 1) + else: + self.multiworld.completion_condition[self.player] = lambda state: state.has(ItemName.Bounty, self.player, self.multiworld.BountyRequired[self.player].value) else: - world.completion_condition[player] = lambda state: state.kh_hitlist(player, world.BountyRequired[player].value) + final_xemnas_location.access_rule = lambda state: state.has(ItemName.Bounty, self.player, self.multiworld.BountyRequired[self.player].value) and\ + state.has(ItemName.LuckyEmblem, self.player, self.multiworld.LuckyEmblemsRequired[self.player].value) + if self.multiworld.FinalXemnas[self.player]: + self.multiworld.completion_condition[self.player] = lambda state: state.has(ItemName.Victory, self.player, 1) + else: + self.multiworld.completion_condition[self.player] = lambda state: state.has(ItemName.Bounty, self.player, self.multiworld.BountyRequired[self.player].value) and \ + state.has(ItemName.LuckyEmblem, self.player, self.multiworld.LuckyEmblemsRequired[self.player].value) + + +class KH2FormRules(KH2Rules): + #: Dict[str, Callable[[CollectionState], bool]] + def __init__(self, world: KH2World) -> None: + super().__init__(world) + # access rules on where you can level a form. + + self.form_rules = { + LocationName.Valorlvl2: lambda state: self.form_list_unlock(state, ItemName.ValorForm, 0), + LocationName.Valorlvl3: lambda state: self.form_list_unlock(state, ItemName.ValorForm, 1), + LocationName.Valorlvl4: lambda state: self.form_list_unlock(state, ItemName.ValorForm, 2), + LocationName.Valorlvl5: lambda state: self.form_list_unlock(state, ItemName.ValorForm, 3), + LocationName.Valorlvl6: lambda state: self.form_list_unlock(state, ItemName.ValorForm, 4), + LocationName.Valorlvl7: lambda state: self.form_list_unlock(state, ItemName.ValorForm, 5), + LocationName.Wisdomlvl2: lambda state: self.form_list_unlock(state, ItemName.WisdomForm, 0), + LocationName.Wisdomlvl3: lambda state: self.form_list_unlock(state, ItemName.WisdomForm, 1), + LocationName.Wisdomlvl4: lambda state: self.form_list_unlock(state, ItemName.WisdomForm, 2), + LocationName.Wisdomlvl5: lambda state: self.form_list_unlock(state, ItemName.WisdomForm, 3), + LocationName.Wisdomlvl6: lambda state: self.form_list_unlock(state, ItemName.WisdomForm, 4), + LocationName.Wisdomlvl7: lambda state: self.form_list_unlock(state, ItemName.WisdomForm, 5), + LocationName.Limitlvl2: lambda state: self.form_list_unlock(state, ItemName.LimitForm, 0), + LocationName.Limitlvl3: lambda state: self.form_list_unlock(state, ItemName.LimitForm, 1), + LocationName.Limitlvl4: lambda state: self.form_list_unlock(state, ItemName.LimitForm, 2), + LocationName.Limitlvl5: lambda state: self.form_list_unlock(state, ItemName.LimitForm, 3), + LocationName.Limitlvl6: lambda state: self.form_list_unlock(state, ItemName.LimitForm, 4), + LocationName.Limitlvl7: lambda state: self.form_list_unlock(state, ItemName.LimitForm, 5), + LocationName.Masterlvl2: lambda state: self.form_list_unlock(state, ItemName.MasterForm, 0), + LocationName.Masterlvl3: lambda state: self.form_list_unlock(state, ItemName.MasterForm, 1), + LocationName.Masterlvl4: lambda state: self.form_list_unlock(state, ItemName.MasterForm, 2), + LocationName.Masterlvl5: lambda state: self.form_list_unlock(state, ItemName.MasterForm, 3), + LocationName.Masterlvl6: lambda state: self.form_list_unlock(state, ItemName.MasterForm, 4), + LocationName.Masterlvl7: lambda state: self.form_list_unlock(state, ItemName.MasterForm, 5), + LocationName.Finallvl2: lambda state: self.form_list_unlock(state, ItemName.FinalForm, 0), + LocationName.Finallvl3: lambda state: self.form_list_unlock(state, ItemName.FinalForm, 1), + LocationName.Finallvl4: lambda state: self.form_list_unlock(state, ItemName.FinalForm, 2), + LocationName.Finallvl5: lambda state: self.form_list_unlock(state, ItemName.FinalForm, 3), + LocationName.Finallvl6: lambda state: self.form_list_unlock(state, ItemName.FinalForm, 4), + LocationName.Finallvl7: lambda state: self.form_list_unlock(state, ItemName.FinalForm, 5), + LocationName.Summonlvl2: lambda state: self.summon_levels_unlocked(state, 1), + LocationName.Summonlvl3: lambda state: self.summon_levels_unlocked(state, 1), + LocationName.Summonlvl4: lambda state: self.summon_levels_unlocked(state, 2), + LocationName.Summonlvl5: lambda state: self.summon_levels_unlocked(state, 3), + LocationName.Summonlvl6: lambda state: self.summon_levels_unlocked(state, 4), + LocationName.Summonlvl7: lambda state: self.summon_levels_unlocked(state, 4), + } + self.form_region_rules = { + RegionName.Valor: lambda state: self.multi_form_region_access(), + RegionName.Wisdom: lambda state: self.multi_form_region_access(), + RegionName.Limit: lambda state: self.limit_form_region_access(), + RegionName.Master: lambda state: self.multi_form_region_access(), + RegionName.Final: lambda state: self.final_form_region_access(state) + } + + def final_form_region_access(self, state: CollectionState) -> bool: + """ + Can reach one of TT3,Twtnw post Roxas, BC2, LoD2 or PR2 + """ + # tt3 start, can beat roxas, can beat gr2, can beat xaldin, can beat storm rider. + + return any( + self.multiworld.get_location(location, self.player).can_reach(state) for location in + final_leveling_access + ) + + @staticmethod + def limit_form_region_access() -> bool: + """ + returns true since twtnw always is open and has enemies + """ + return True + + @staticmethod + def multi_form_region_access() -> bool: + """ + returns true since twtnw always is open and has enemies + Valor, Wisdom and Master Form region access. + Note: This does not account for having the drive form. See form_list_unlock + """ + # todo: if boss enemy start the player with oc stone because of cerb + return True + + def set_kh2_form_rules(self): + for region_name in drive_form_list: + if region_name == RegionName.Summon and not self.world.options.SummonLevelLocationToggle: + continue + # could get the location of each of these, but I feel like that would be less optimal + region = self.multiworld.get_region(region_name, self.player) + # if region_name in form_region_rules + if region_name != RegionName.Summon: + for entrance in region.entrances: + entrance.access_rule = self.form_region_rules[region_name] + for loc in region.locations: + loc.access_rule = self.form_rules[loc.name] + + +class KH2FightRules(KH2Rules): + player: int + world: KH2World + region_rules: Dict[str, Callable[[CollectionState], bool]] + location_rules: Dict[str, Callable[[CollectionState], bool]] + + # cor logic + # have 3 things for the logic + # region:movement_rules and (fight_rules or skip rules) + # if skip rules are of return false + def __init__(self, world: KH2World) -> None: + super().__init__(world) + self.fight_logic = self.multiworld.FightLogic[self.player].current_key + + self.fight_region_rules = { + RegionName.ShanYu: lambda state: self.get_shan_yu_rules(state), + RegionName.AnsemRiku: lambda state: self.get_ansem_riku_rules(state), + RegionName.StormRider: lambda state: self.get_storm_rider_rules(state), + RegionName.DataXigbar: lambda state: self.get_data_xigbar_rules(state), + RegionName.TwinLords: lambda state: self.get_fire_lord_rules(state) and self.get_blizzard_lord_rules(state), + RegionName.GenieJafar: lambda state: self.get_genie_jafar_rules(state), + RegionName.DataLexaeus: lambda state: self.get_data_lexaeus_rules(state), + RegionName.OldPete: lambda state: self.get_old_pete_rules(), + RegionName.FuturePete: lambda state: self.get_future_pete_rules(state), + RegionName.Terra: lambda state: self.get_terra_rules(state), + RegionName.DataMarluxia: lambda state: self.get_data_marluxia_rules(state), + RegionName.Barbosa: lambda state: self.get_barbosa_rules(state), + RegionName.GrimReaper1: lambda state: self.get_grim_reaper1_rules(), + RegionName.GrimReaper2: lambda state: self.get_grim_reaper2_rules(state), + RegionName.DataLuxord: lambda state: self.get_data_luxord_rules(state), + RegionName.Cerberus: lambda state: self.get_cerberus_rules(state), + RegionName.OlympusPete: lambda state: self.get_olympus_pete_rules(state), + RegionName.Hydra: lambda state: self.get_hydra_rules(state), + RegionName.Hades: lambda state: self.get_hades_rules(state), + RegionName.DataZexion: lambda state: self.get_data_zexion_rules(state), + RegionName.OcPainAndPanicCup: lambda state: self.get_pain_and_panic_cup_rules(state), + RegionName.OcCerberusCup: lambda state: self.get_cerberus_cup_rules(state), + RegionName.Oc2TitanCup: lambda state: self.get_titan_cup_rules(state), + RegionName.Oc2GofCup: lambda state: self.get_goddess_of_fate_cup_rules(state), + RegionName.HadesCups: lambda state: self.get_hades_cup_rules(state), + RegionName.Thresholder: lambda state: self.get_thresholder_rules(state), + RegionName.Beast: lambda state: self.get_beast_rules(), + RegionName.DarkThorn: lambda state: self.get_dark_thorn_rules(state), + RegionName.Xaldin: lambda state: self.get_xaldin_rules(state), + RegionName.DataXaldin: lambda state: self.get_data_xaldin_rules(state), + RegionName.HostileProgram: lambda state: self.get_hostile_program_rules(state), + RegionName.Mcp: lambda state: self.get_mcp_rules(state), + RegionName.DataLarxene: lambda state: self.get_data_larxene_rules(state), + RegionName.PrisonKeeper: lambda state: self.get_prison_keeper_rules(state), + RegionName.OogieBoogie: lambda state: self.get_oogie_rules(), + RegionName.Experiment: lambda state: self.get_experiment_rules(state), + RegionName.DataVexen: lambda state: self.get_data_vexen_rules(state), + RegionName.HBDemyx: lambda state: self.get_demyx_rules(state), + RegionName.ThousandHeartless: lambda state: self.get_thousand_heartless_rules(state), + RegionName.DataDemyx: lambda state: self.get_data_demyx_rules(state), + RegionName.Sephi: lambda state: self.get_sephiroth_rules(state), + RegionName.CorFirstFight: lambda state: self.get_cor_first_fight_movement_rules(state) and (self.get_cor_first_fight_rules(state) or self.get_cor_skip_first_rules(state)), + RegionName.CorSecondFight: lambda state: self.get_cor_second_fight_movement_rules(state), + RegionName.Transport: lambda state: self.get_transport_movement_rules(state), + RegionName.Scar: lambda state: self.get_scar_rules(state), + RegionName.GroundShaker: lambda state: self.get_groundshaker_rules(state), + RegionName.DataSaix: lambda state: self.get_data_saix_rules(state), + RegionName.TwilightThorn: lambda state: self.get_twilight_thorn_rules(), + RegionName.Axel1: lambda state: self.get_axel_one_rules(), + RegionName.Axel2: lambda state: self.get_axel_two_rules(), + RegionName.DataRoxas: lambda state: self.get_data_roxas_rules(state), + RegionName.DataAxel: lambda state: self.get_data_axel_rules(state), + RegionName.Roxas: lambda state: self.get_roxas_rules(state) and self.twtnw_unlocked(state, 1), + RegionName.Xigbar: lambda state: self.get_xigbar_rules(state), + RegionName.Luxord: lambda state: self.get_luxord_rules(state), + RegionName.Saix: lambda state: self.get_saix_rules(state), + RegionName.Xemnas: lambda state: self.get_xemnas_rules(state), + RegionName.ArmoredXemnas: lambda state: self.get_armored_xemnas_one_rules(state), + RegionName.ArmoredXemnas2: lambda state: self.get_armored_xemnas_two_rules(state), + RegionName.FinalXemnas: lambda state: self.get_final_xemnas_rules(state), + RegionName.DataXemnas: lambda state: self.get_data_xemnas_rules(state), + } + + def set_kh2_fight_rules(self) -> None: + for region_name, rules in self.fight_region_rules.items(): + region = self.multiworld.get_region(region_name, self.player) + for entrance in region.entrances: + entrance.access_rule = rules + + for loc_name in [LocationName.TransportEventLocation, LocationName.TransporttoRemembrance]: + location = self.multiworld.get_location(loc_name, self.player) + add_rule(location, lambda state: self.get_transport_fight_rules(state)) + + def get_shan_yu_rules(self, state: CollectionState) -> bool: + # easy: gap closer, defensive tool,drive form + # normal: 2 out of easy + # hard: defensive tool or drive form + shan_yu_rules = { + "easy": self.kh2_list_any_sum([gap_closer, defensive_tool, form_list], state) >= 3, + "normal": self.kh2_list_any_sum([gap_closer, defensive_tool, form_list], state) >= 2, + "hard": self.kh2_list_any_sum([defensive_tool, form_list], state) >= 1 + } + return shan_yu_rules[self.fight_logic] + + def get_ansem_riku_rules(self, state: CollectionState) -> bool: + # easy: gap closer,defensive tool,ground finisher/limit form + # normal: defensive tool and (gap closer/ground finisher/limit form) + # hard: defensive tool or limit form + ansem_riku_rules = { + "easy": self.kh2_list_any_sum([gap_closer, defensive_tool, [ItemName.LimitForm], ground_finisher], state) >= 3, + "normal": self.kh2_list_any_sum([gap_closer, defensive_tool, [ItemName.LimitForm], ground_finisher], state) >= 2, + "hard": self.kh2_has_any([ItemName.ReflectElement, ItemName.Guard, ItemName.LimitForm], state), + } + return ansem_riku_rules[self.fight_logic] + + def get_storm_rider_rules(self, state: CollectionState) -> bool: + # easy: has defensive tool,drive form, party limit,aerial move + # normal: has 3 of those things + # hard: has 2 of those things + storm_rider_rules = { + "easy": self.kh2_list_any_sum([defensive_tool, party_limit, aerial_move, form_list], state) >= 4, + "normal": self.kh2_list_any_sum([defensive_tool, party_limit, aerial_move, form_list], state) >= 3, + "hard": self.kh2_list_any_sum([defensive_tool, party_limit, aerial_move, form_list], state) >= 2, + } + return storm_rider_rules[self.fight_logic] + + def get_data_xigbar_rules(self, state: CollectionState) -> bool: + # easy:final 7,firaga,2 air combo plus,air gap closer, finishing plus,guard,reflega,horizontal slash,donald limit + # normal:final 7,firaga,finishing plus,guard,reflect horizontal slash,donald limit + # hard:((final 5, fira) or donald limit), finishing plus,guard/reflect + data_xigbar_rules = { + "easy": self.kh2_dict_count(easy_data_xigbar_tools, state) and self.form_list_unlock(state, ItemName.FinalForm, 5, True) and self.kh2_has_any(donald_limit, state), + "normal": self.kh2_dict_count(normal_data_xigbar_tools, state) and self.form_list_unlock(state, ItemName.FinalForm, 5, True) and self.kh2_has_any(donald_limit, state), + "hard": ((self.form_list_unlock(state, ItemName.FinalForm, 3, True) and state.has(ItemName.FireElement, self.player, 2)) or self.kh2_has_any(donald_limit, state)) + and state.has(ItemName.FinishingPlus, self.player) and self.kh2_has_any(defensive_tool, state) + } + return data_xigbar_rules[self.fight_logic] + + def get_fire_lord_rules(self, state: CollectionState) -> bool: + # easy: drive form,defensive tool,one black magic,party limit + # normal: 3 of those things + # hard:2 of those things + # duplicate of the other because in boss rando there will be to bosses in arena and these bosses can be split. + fire_lords_rules = { + "easy": self.kh2_list_any_sum([form_list, defensive_tool, black_magic, party_limit], state) >= 4, + "normal": self.kh2_list_any_sum([form_list, defensive_tool, black_magic, party_limit], state) >= 3, + "hard": self.kh2_list_any_sum([form_list, defensive_tool, black_magic, party_limit], state) >= 2, + } + return fire_lords_rules[self.fight_logic] + + def get_blizzard_lord_rules(self, state: CollectionState) -> bool: + # easy: drive form,defensive tool,one black magic,party limit + # normal: 3 of those things + # hard:2 of those things + # duplicate of the other because in boss rando there will be to bosses in arena and these bosses can be split. + blizzard_lords_rules = { + "easy": self.kh2_list_any_sum([form_list, defensive_tool, black_magic, party_limit], state) >= 4, + "normal": self.kh2_list_any_sum([form_list, defensive_tool, black_magic, party_limit], state) >= 3, + "hard": self.kh2_list_any_sum([form_list, defensive_tool, black_magic, party_limit], state) >= 2, + } + return blizzard_lords_rules[self.fight_logic] + + def get_genie_jafar_rules(self, state: CollectionState) -> bool: + # easy: defensive tool,black magic,ground finisher,finishing plus + # normal: defensive tool, ground finisher,finishing plus + # hard: defensive tool,finishing plus + genie_jafar_rules = { + "easy": self.kh2_list_any_sum([defensive_tool, black_magic, ground_finisher, {ItemName.FinishingPlus}], state) >= 4, + "normal": self.kh2_list_any_sum([defensive_tool, ground_finisher, {ItemName.FinishingPlus}], state) >= 3, + "hard": self.kh2_list_any_sum([defensive_tool, {ItemName.FinishingPlus}], state) >= 2, + } + return genie_jafar_rules[self.fight_logic] + + def get_data_lexaeus_rules(self, state: CollectionState) -> bool: + # easy:both gap closers,final 7,firaga,reflera,donald limit, guard + # normal:one gap closer,final 5,fira,reflect, donald limit,guard + # hard:defensive tool,gap closer + data_lexaues_rules = { + "easy": self.kh2_dict_count(easy_data_lex_tools, state) and self.form_list_unlock(state, ItemName.FinalForm, 5, True) and self.kh2_list_any_sum([donald_limit], state) >= 1, + "normal": self.kh2_dict_count(normal_data_lex_tools, state) and self.form_list_unlock(state, ItemName.FinalForm, 3, True) and self.kh2_list_any_sum([donald_limit, gap_closer], state) >= 2, + "hard": self.kh2_list_any_sum([defensive_tool, gap_closer], state) >= 2, + } + return data_lexaues_rules[self.fight_logic] + + @staticmethod + def get_old_pete_rules(): + # fight is free. + return True + + def get_future_pete_rules(self, state: CollectionState) -> bool: + # easy:defensive option,gap closer,drive form + # norma:2 of those things + # hard 1 of those things + future_pete_rules = { + "easy": self.kh2_list_any_sum([defensive_tool, gap_closer, form_list], state) >= 3, + "normal": self.kh2_list_any_sum([defensive_tool, gap_closer, form_list], state) >= 2, + "hard": self.kh2_list_any_sum([defensive_tool, gap_closer, form_list], state) >= 1, + } + return future_pete_rules[self.fight_logic] + + def get_data_marluxia_rules(self, state: CollectionState) -> bool: + # easy:both gap closers,final 7,firaga,reflera,donald limit, guard + # normal:one gap closer,final 5,fira,reflect, donald limit,guard + # hard:defensive tool,gap closer + data_marluxia_rules = { + "easy": self.kh2_dict_count(easy_data_marluxia_tools, state) and self.form_list_unlock(state, ItemName.FinalForm, 5, True) and self.kh2_list_any_sum([donald_limit], state) >= 1, + "normal": self.kh2_dict_count(normal_data_marluxia_tools, state) and self.form_list_unlock(state, ItemName.FinalForm, 3, True) and self.kh2_list_any_sum([donald_limit, gap_closer], state) >= 2, + "hard": self.kh2_list_any_sum([defensive_tool, gap_closer, [ItemName.AerialRecovery]], state) >= 3, + } + return data_marluxia_rules[self.fight_logic] + + def get_terra_rules(self, state: CollectionState) -> bool: + # easy:scom,gap closers,explosion,2 combo pluses,final 7,firaga, donald limits,reflect,guard,3 dodge roll,3 aerial dodge and 3glide + # normal:gap closers,explosion,2 combo pluses,2 dodge roll,2 aerial dodge and lvl 2glide,guard,donald limit, guard + # hard:1 gap closer,explosion,2 combo pluses,2 dodge roll,2 aerial dodge and lvl 2glide,guard + terra_rules = { + "easy": self.kh2_dict_count(easy_terra_tools, state) and self.form_list_unlock(state, ItemName.FinalForm, 5, True), + "normal": self.kh2_dict_count(normal_terra_tools, state) and self.kh2_list_any_sum([donald_limit], state) >= 1, + "hard": self.kh2_dict_count(hard_terra_tools, state) and self.kh2_list_any_sum([gap_closer], state) >= 1, + } + return terra_rules[self.fight_logic] + + def get_barbosa_rules(self, state: CollectionState) -> bool: + # easy:blizzara and thundara or one of each,defensive tool + # normal:(blizzard or thunder) and defensive tool + # hard: defensive tool + barbosa_rules = { + "easy": self.kh2_list_count_sum([ItemName.BlizzardElement, ItemName.ThunderElement], state) >= 2 and self.kh2_list_any_sum([defensive_tool], state) >= 1, + "normal": self.kh2_list_any_sum([defensive_tool, {ItemName.BlizzardElement, ItemName.ThunderElement}], state) >= 2, + "hard": self.kh2_list_any_sum([defensive_tool], state) >= 1, + } + return barbosa_rules[self.fight_logic] + + @staticmethod + def get_grim_reaper1_rules(): + # fight is free. + return True + + def get_grim_reaper2_rules(self, state: CollectionState) -> bool: + # easy:master form,thunder,defensive option + # normal:master form/stitch,thunder,defensive option + # hard:any black magic,defensive option. + gr2_rules = { + "easy": self.kh2_list_any_sum([defensive_tool, {ItemName.MasterForm, ItemName.ThunderElement}], state) >= 2, + "normal": self.kh2_list_any_sum([defensive_tool, {ItemName.MasterForm, ItemName.Stitch}, {ItemName.ThunderElement}], state) >= 3, + "hard": self.kh2_list_any_sum([black_magic, defensive_tool], state) >= 2 + } + return gr2_rules[self.fight_logic] + + def get_data_luxord_rules(self, state: CollectionState) -> bool: + # easy:gap closers,reflega,aerial dodge lvl 2,glide lvl 2,guard + # normal:1 gap closer,reflect,aerial dodge lvl 1,glide lvl 1,guard + # hard:quick run,defensive option + data_luxord_rules = { + "easy": self.kh2_dict_count(easy_data_luxord_tools, state), + "normal": self.kh2_has_all([ItemName.ReflectElement, ItemName.AerialDodge, ItemName.Glide, ItemName.Guard], state) and self.kh2_has_any(defensive_tool, state), + "hard": self.kh2_list_any_sum([{ItemName.QuickRun}, defensive_tool], state) + } + return data_luxord_rules[self.fight_logic] + + def get_cerberus_rules(self, state: CollectionState) -> bool: + # easy,normal:defensive option, offensive magic + # hard:defensive option + cerberus_rules = { + "easy": self.kh2_list_any_sum([defensive_tool, black_magic], state) >= 2, + "normal": self.kh2_list_any_sum([defensive_tool, black_magic], state) >= 2, + "hard": self.kh2_has_any(defensive_tool, state), + } + return cerberus_rules[self.fight_logic] + + def get_pain_and_panic_cup_rules(self, state: CollectionState) -> bool: + # easy:2 party limit,reflect + # normal:1 party limit,reflect + # hard:reflect + pain_and_panic_rules = { + "easy": self.kh2_list_count_sum(party_limit, state) >= 2 and state.has(ItemName.ReflectElement, self.player), + "normal": self.kh2_list_count_sum(party_limit, state) >= 1 and state.has(ItemName.ReflectElement, self.player), + "hard": state.has(ItemName.ReflectElement, self.player) + } + return pain_and_panic_rules[self.fight_logic] and (self.kh2_has_all([ItemName.FuturePeteEvent], state) or state.has(ItemName.HadesCupTrophy, self.player)) + + def get_cerberus_cup_rules(self, state: CollectionState) -> bool: + # easy:3 drive forms,reflect + # normal:2 drive forms,reflect + # hard:reflect + cerberus_cup_rules = { + "easy": self.kh2_can_reach_any([LocationName.Valorlvl5, LocationName.Wisdomlvl5, LocationName.Limitlvl5, LocationName.Masterlvl5, LocationName.Finallvl5], state) and state.has(ItemName.ReflectElement, self.player), + "normal": self.kh2_can_reach_any([LocationName.Valorlvl4, LocationName.Wisdomlvl4, LocationName.Limitlvl4, LocationName.Masterlvl4, LocationName.Finallvl4], state) and state.has(ItemName.ReflectElement, self.player), + "hard": state.has(ItemName.ReflectElement, self.player) + } + return cerberus_cup_rules[self.fight_logic] and (self.kh2_has_all([ItemName.ScarEvent, ItemName.OogieBoogieEvent, ItemName.TwinLordsEvent], state) or state.has(ItemName.HadesCupTrophy, self.player)) + + def get_titan_cup_rules(self, state: CollectionState) -> bool: + # easy:4 summons,reflera + # normal:4 summons,reflera + # hard:2 summons,reflera + titan_cup_rules = { + "easy": self.kh2_list_count_sum(summons, state) >= 4 and state.has(ItemName.ReflectElement, self.player, 2), + "normal": self.kh2_list_count_sum(summons, state) >= 3 and state.has(ItemName.ReflectElement, self.player, 2), + "hard": self.kh2_list_count_sum(summons, state) >= 2 and state.has(ItemName.ReflectElement, self.player, 2), + } + return titan_cup_rules[self.fight_logic] and (state.has(ItemName.HadesEvent, self.player) or state.has(ItemName.HadesCupTrophy, self.player)) + + def get_goddess_of_fate_cup_rules(self, state: CollectionState) -> bool: + # can beat all the other cups+xemnas 1 + return self.kh2_has_all([ItemName.OcPainAndPanicCupEvent, ItemName.OcCerberusCupEvent, ItemName.Oc2TitanCupEvent], state) + + def get_hades_cup_rules(self, state: CollectionState) -> bool: + # can beat goddess of fate cup + return state.has(ItemName.Oc2GofCupEvent, self.player) + + def get_olympus_pete_rules(self, state: CollectionState) -> bool: + # easy:gap closer,defensive option,drive form + # normal:2 of those things + # hard:1 of those things + olympus_pete_rules = { + "easy": self.kh2_list_any_sum([gap_closer, defensive_tool, form_list], state) >= 3, + "normal": self.kh2_list_any_sum([gap_closer, defensive_tool, form_list], state) >= 2, + "hard": self.kh2_list_any_sum([gap_closer, defensive_tool, form_list], state) >= 1, + } + return olympus_pete_rules[self.fight_logic] + + def get_hydra_rules(self, state: CollectionState) -> bool: + # easy:drive form,defensive option,offensive magic + # normal 2 of those things + # hard: one of those things + hydra_rules = { + "easy": self.kh2_list_any_sum([black_magic, defensive_tool, form_list], state) >= 3, + "normal": self.kh2_list_any_sum([black_magic, defensive_tool, form_list], state) >= 2, + "hard": self.kh2_list_any_sum([black_magic, defensive_tool, form_list], state) >= 1, + } + return hydra_rules[self.fight_logic] + + def get_hades_rules(self, state: CollectionState) -> bool: + # easy:drive form,summon,gap closer,defensive option + # normal:3 of those things + # hard:2 of those things + hades_rules = { + "easy": self.kh2_list_any_sum([gap_closer, summons, defensive_tool, form_list], state) >= 4, + "normal": self.kh2_list_any_sum([gap_closer, summons, defensive_tool, form_list], state) >= 3, + "hard": self.kh2_list_any_sum([gap_closer, summons, defensive_tool, form_list], state) >= 2, + } + return hades_rules[self.fight_logic] + + def get_data_zexion_rules(self, state: CollectionState) -> bool: + # easy: final 7,firaga,scom,both donald limits, Reflega ,guard,2 gap closers,quick run level 3 + # normal:final 7,firaga, donald limit, Reflega ,guard,1 gap closers,quick run level 3 + # hard:final 5,fira, donald limit, reflect,gap closer,quick run level 2 + data_zexion_rules = { + "easy": self.kh2_dict_count(easy_data_zexion, state) and self.form_list_unlock(state, ItemName.FinalForm, 5, True), + "normal": self.kh2_dict_count(normal_data_zexion, state) and self.form_list_unlock(state, ItemName.FinalForm, 5, True) and self.kh2_list_any_sum([donald_limit, gap_closer], state) >= 2, + "hard": self.kh2_dict_count(hard_data_zexion, state) and self.form_list_unlock(state, ItemName.FinalForm, 3, True) and self.kh2_list_any_sum([donald_limit, gap_closer], state) >= 2, + } + return data_zexion_rules[self.fight_logic] + + def get_thresholder_rules(self, state: CollectionState) -> bool: + # easy:drive form,black magic,defensive tool + # normal:2 of those things + # hard:defensive tool or drive form + thresholder_rules = { + "easy": self.kh2_list_any_sum([form_list, black_magic, defensive_tool], state) >= 3, + "normal": self.kh2_list_any_sum([form_list, black_magic, defensive_tool], state) >= 2, + "hard": self.kh2_list_any_sum([form_list, defensive_tool], state) >= 1, + } + return thresholder_rules[self.fight_logic] + + @staticmethod + def get_beast_rules(): + # fight is free + return True + + def get_dark_thorn_rules(self, state: CollectionState) -> bool: + # easy:drive form,defensive tool,gap closer + # normal:drive form,defensive tool + # hard:defensive tool + dark_thorn_rules = { + "easy": self.kh2_list_any_sum([form_list, gap_closer, defensive_tool], state) >= 3, + "normal": self.kh2_list_any_sum([form_list, defensive_tool], state) >= 2, + "hard": self.kh2_list_any_sum([defensive_tool], state) >= 1, + } + return dark_thorn_rules[self.fight_logic] + + def get_xaldin_rules(self, state: CollectionState) -> bool: + # easy:guard,2 aerial modifier,valor/master/final + # normal:guard,1 aerial modifier + # hard:guard + xaldin_rules = { + "easy": self.kh2_list_any_sum([[ItemName.Guard], [ItemName.ValorForm, ItemName.MasterForm, ItemName.FinalForm]], state) >= 2 and self.kh2_list_count_sum(aerial_move, state) >= 2, + "normal": self.kh2_list_any_sum([aerial_move], state) >= 1 and state.has(ItemName.Guard, self.player), + "hard": state.has(ItemName.Guard, self.player), + } + return xaldin_rules[self.fight_logic] + + def get_data_xaldin_rules(self, state: CollectionState) -> bool: + # easy:final 7,firaga,2 air combo plus, finishing plus,guard,reflega,donald limit,high jump aerial dodge glide lvl 3,magnet,aerial dive,aerial spiral,hori slash,berserk charge + # normal:final 7,firaga, finishing plus,guard,reflega,donald limit,high jump aerial dodge glide lvl 3,magnet,aerial dive,aerial spiral,hori slash + # hard:final 5, fira, party limit, finishing plus,guard,high jump aerial dodge glide lvl 2,magnet,aerial dive + data_xaldin_rules = { + "easy": self.kh2_dict_count(easy_data_xaldin, state) and self.form_list_unlock(state, ItemName.FinalForm, 5, True), + "normal": self.kh2_dict_count(normal_data_xaldin, state) and self.form_list_unlock(state, ItemName.FinalForm, 5, True), + "hard": self.kh2_dict_count(hard_data_xaldin, state) and self.form_list_unlock(state, ItemName.FinalForm, 3, True) and self.kh2_has_any(party_limit, state), + } + return data_xaldin_rules[self.fight_logic] + + def get_hostile_program_rules(self, state: CollectionState) -> bool: + # easy:donald limit,reflect,drive form,summon + # normal:3 of those things + # hard: 2 of those things + hostile_program_rules = { + "easy": self.kh2_list_any_sum([donald_limit, form_list, summons, {ItemName.ReflectElement}], state) >= 4, + "normal": self.kh2_list_any_sum([donald_limit, form_list, summons, {ItemName.ReflectElement}], state) >= 3, + "hard": self.kh2_list_any_sum([donald_limit, form_list, summons, {ItemName.ReflectElement}], state) >= 2, + } + return hostile_program_rules[self.fight_logic] + + def get_mcp_rules(self, state: CollectionState) -> bool: + # easy:donald limit,reflect,drive form,summon + # normal:3 of those things + # hard: 2 of those things + mcp_rules = { + "easy": self.kh2_list_any_sum([donald_limit, form_list, summons, {ItemName.ReflectElement}], state) >= 4, + "normal": self.kh2_list_any_sum([donald_limit, form_list, summons, {ItemName.ReflectElement}], state) >= 3, + "hard": self.kh2_list_any_sum([donald_limit, form_list, summons, {ItemName.ReflectElement}], state) >= 2, + } + return mcp_rules[self.fight_logic] + + def get_data_larxene_rules(self, state: CollectionState) -> bool: + # easy: final 7,firaga,scom,both donald limits, Reflega,guard,2 gap closers,2 ground finishers,aerial dodge 3,glide 3 + # normal:final 7,firaga, donald limit, Reflega ,guard,1 gap closers,1 ground finisher,aerial dodge 3,glide 3 + # hard:final 5,fira, donald limit, reflect,gap closer,aerial dodge 2,glide 2 + data_larxene_rules = { + "easy": self.kh2_dict_count(easy_data_larxene, state) and self.form_list_unlock(state, ItemName.FinalForm, 5, True), + "normal": self.kh2_dict_count(normal_data_larxene, state) and self.kh2_list_any_sum([gap_closer, ground_finisher, donald_limit], state) >= 3 and self.form_list_unlock(state, ItemName.FinalForm, 5, True), + "hard": self.kh2_dict_count(hard_data_larxene, state) and self.kh2_list_any_sum([gap_closer, donald_limit], state) >= 2 and self.form_list_unlock(state, ItemName.FinalForm, 3, True), + } + return data_larxene_rules[self.fight_logic] + + def get_prison_keeper_rules(self, state: CollectionState) -> bool: + # easy:defensive tool,drive form, party limit + # normal:two of those things + # hard:one of those things + prison_keeper_rules = { + "easy": self.kh2_list_any_sum([defensive_tool, form_list, party_limit], state) >= 3, + "normal": self.kh2_list_any_sum([defensive_tool, form_list, party_limit], state) >= 2, + "hard": self.kh2_list_any_sum([defensive_tool, form_list, party_limit], state) >= 1, + } + return prison_keeper_rules[self.fight_logic] + + @staticmethod + def get_oogie_rules(): + # fight is free + return True + + def get_experiment_rules(self, state: CollectionState) -> bool: + # easy:drive form,defensive tool,summon,party limit + # normal:3 of those things + # hard 2 of those things + experiment_rules = { + "easy": self.kh2_list_any_sum([form_list, defensive_tool, party_limit, summons], state) >= 4, + "normal": self.kh2_list_any_sum([form_list, defensive_tool, party_limit, summons], state) >= 3, + "hard": self.kh2_list_any_sum([form_list, defensive_tool, party_limit, summons], state) >= 2, + } + return experiment_rules[self.fight_logic] + + def get_data_vexen_rules(self, state: CollectionState) -> bool: + # easy: final 7,firaga,scom,both donald limits, Reflega,guard,2 gap closers,2 ground finishers,aerial dodge 3,glide 3,dodge roll 3,quick run 3 + # normal:final 7,firaga, donald limit, Reflega,guard,1 gap closers,1 ground finisher,aerial dodge 3,glide 3,dodge roll 3,quick run 3 + # hard:final 5,fira, donald limit, reflect,gap closer,aerial dodge 2,glide 2,dodge roll 2,quick run 2 + data_vexen_rules = { + "easy": self.kh2_dict_count(easy_data_vexen, state) and self.form_list_unlock(state, ItemName.FinalForm, 5, True), + "normal": self.kh2_dict_count(normal_data_vexen, state) and self.kh2_list_any_sum([gap_closer, ground_finisher, donald_limit], state) >= 3 and self.form_list_unlock(state, ItemName.FinalForm, 5, True), + "hard": self.kh2_dict_count(hard_data_vexen, state) and self.kh2_list_any_sum([gap_closer, donald_limit], state) >= 2 and self.form_list_unlock(state, ItemName.FinalForm, 3, True), + } + return data_vexen_rules[self.fight_logic] + + def get_demyx_rules(self, state: CollectionState) -> bool: + # defensive option,drive form,party limit + # defensive option,drive form + # defensive option + demyx_rules = { + "easy": self.kh2_list_any_sum([defensive_tool, form_list, party_limit], state) >= 3, + "normal": self.kh2_list_any_sum([defensive_tool, form_list], state) >= 2, + "hard": self.kh2_list_any_sum([defensive_tool], state) >= 1, + } + return demyx_rules[self.fight_logic] + + def get_thousand_heartless_rules(self, state: CollectionState) -> bool: + # easy:scom,limit form,guard,magnera + # normal:limit form, guard + # hard:guard + thousand_heartless_rules = { + "easy": self.kh2_dict_count(easy_thousand_heartless_rules, state), + "normal": self.kh2_dict_count(normal_thousand_heartless_rules, state), + "hard": state.has(ItemName.Guard, self.player), + } + return thousand_heartless_rules[self.fight_logic] + + def get_data_demyx_rules(self, state: CollectionState) -> bool: + # easy:wisdom 7,1 form boosts,reflera,firaga,duck flare,guard,scom,finishing plus + # normal:remove form boost and scom + # hard:wisdom 6,reflect,guard,duck flare,fira,finishing plus + data_demyx_rules = { + "easy": self.kh2_dict_count(easy_data_demyx, state) and self.form_list_unlock(state, ItemName.WisdomForm, 5, True), + "normal": self.kh2_dict_count(normal_data_demyx, state) and self.form_list_unlock(state, ItemName.WisdomForm, 5, True), + "hard": self.kh2_dict_count(hard_data_demyx, state) and self.form_list_unlock(state, ItemName.WisdomForm, 4, True), + } + return data_demyx_rules[self.fight_logic] + + def get_sephiroth_rules(self, state: CollectionState) -> bool: + # easy:both gap closers,limit 5,reflega,guard,both 2 ground finishers,3 dodge roll,finishing plus,scom + # normal:both gap closers,limit 5,reflera,guard,both 2 ground finishers,3 dodge roll,finishing plus + # hard:1 gap closers,reflect, guard,both 1 ground finisher,2 dodge roll,finishing plus + sephiroth_rules = { + "easy": self.kh2_dict_count(easy_sephiroth_tools, state) and self.kh2_can_reach(LocationName.Limitlvl5, state) and self.kh2_list_any_sum([donald_limit], state) >= 1, + "normal": self.kh2_dict_count(normal_sephiroth_tools, state) and self.kh2_can_reach(LocationName.Limitlvl5, state) and self.kh2_list_any_sum([donald_limit, gap_closer], state) >= 2, + "hard": self.kh2_dict_count(hard_sephiroth_tools, state) and self.kh2_list_any_sum([gap_closer, ground_finisher], state) >= 2, + } + return sephiroth_rules[self.fight_logic] + + def get_cor_first_fight_movement_rules(self, state: CollectionState) -> bool: + # easy: quick run 3 or wisdom 5 (wisdom has qr 3) + # normal: quick run 2 and aerial dodge 1 or wisdom 5 (wisdom has qr 3) + # hard: (quick run 1, aerial dodge 1) or (wisdom form and aerial dodge 1) + cor_first_fight_movement_rules = { + "easy": state.has(ItemName.QuickRun, self.player, 3) or self.form_list_unlock(state, ItemName.WisdomForm, 3, True), + "normal": self.kh2_dict_count({ItemName.QuickRun: 2, ItemName.AerialDodge: 1}, state) or self.form_list_unlock(state, ItemName.WisdomForm, 3, True), + "hard": self.kh2_has_all([ItemName.AerialDodge, ItemName.QuickRun], state) or self.kh2_has_all([ItemName.AerialDodge, ItemName.WisdomForm], state), + } + return cor_first_fight_movement_rules[self.fight_logic] + + def get_cor_first_fight_rules(self, state: CollectionState) -> bool: + # easy:have 5 of these things (reflega,stitch and chicken,final form,magnera,explosion,thundara) + # normal:have 3 of these things (reflega,stitch and chicken,final form,magnera,explosion,thundara) + # hard: reflect,stitch or chicken,final form + cor_first_fight_rules = { + "easy": self.kh2_dict_one_count(not_hard_cor_tools_dict, state) >= 5 or self.kh2_dict_one_count(not_hard_cor_tools_dict, state) >= 4 and self.form_list_unlock(state, ItemName.FinalForm, 1, True), + "normal": self.kh2_dict_one_count(not_hard_cor_tools_dict, state) >= 3 or self.kh2_dict_one_count(not_hard_cor_tools_dict, state) >= 2 and self.form_list_unlock(state, ItemName.FinalForm, 1, True), + "hard": state.has(ItemName.ReflectElement, self.player) and self.kh2_has_any([ItemName.Stitch, ItemName.ChickenLittle], state) and self.form_list_unlock(state, ItemName.FinalForm, 1, True), + } + return cor_first_fight_rules[self.fight_logic] + + def get_cor_skip_first_rules(self, state: CollectionState) -> bool: + # if option is not allow skips return false else run rules + if not self.multiworld.CorSkipToggle[self.player]: + return False + # easy: aerial dodge 3,master form,fire + # normal: aerial dodge 2, master form,fire + # hard:void cross(quick run 3,aerial dodge 1) + # or (quick run 2,aerial dodge 2 and magic) + # or (final form and (magic or combo master)) + # or (master form and (reflect or fire or thunder or combo master) + # wall rise(aerial dodge 1 and (final form lvl 3 or glide 2) or (master form and (1 of black magic or combo master) + void_cross_rules = { + "easy": state.has(ItemName.AerialDodge, self.player, 3) and self.kh2_has_all([ItemName.MasterForm, ItemName.FireElement], state), + "normal": state.has(ItemName.AerialDodge, self.player, 2) and self.kh2_has_all([ItemName.MasterForm, ItemName.FireElement], state), + "hard": (self.kh2_dict_count({ItemName.QuickRun: 3, ItemName.AerialDodge: 1}, state)) \ + or (self.kh2_dict_count({ItemName.QuickRun: 2, ItemName.AerialDodge: 2}, state) and self.kh2_has_any(magic, state)) \ + or (state.has(ItemName.FinalForm, self.player) and (self.kh2_has_any(magic, state) or state.has(ItemName.ComboMaster, self.player))) \ + or (state.has(ItemName.MasterForm, self.player) and (self.kh2_has_any([ItemName.ReflectElement, ItemName.FireElement, ItemName.ComboMaster], state))) + } + wall_rise_rules = { + "easy": True, + "normal": True, + "hard": state.has(ItemName.AerialDodge, self.player) and (self.form_list_unlock(state, ItemName.FinalForm, 1, True) or state.has(ItemName.Glide, self.player, 2)) + } + return void_cross_rules[self.fight_logic] and wall_rise_rules[self.fight_logic] + + def get_cor_second_fight_movement_rules(self, state: CollectionState) -> bool: + # easy: quick run 2, aerial dodge 3 or master form 5 + # normal: quick run 2, aerial dodge 2 or master 5 + # hard: (glide 1,aerial dodge 1 any magic) or (master 3 any magic) or glide 1 and aerial dodge 2 + + cor_second_fight_movement_rules = { + "easy": self.kh2_dict_count({ItemName.QuickRun: 2, ItemName.AerialDodge: 3}, state) or self.form_list_unlock(state, ItemName.MasterForm, 3, True), + "normal": self.kh2_dict_count({ItemName.QuickRun: 2, ItemName.AerialDodge: 2}, state) or self.form_list_unlock(state, ItemName.MasterForm, 3, True), + "hard": (self.kh2_has_all([ItemName.Glide, ItemName.AerialDodge], state) and self.kh2_has_any(magic, state)) \ + or (state.has(ItemName.MasterForm, self.player) and self.kh2_has_any(magic, state)) \ + or (state.has(ItemName.Glide, self.player) and state.has(ItemName.AerialDodge, self.player, 2)), + } + return cor_second_fight_movement_rules[self.fight_logic] + + def get_transport_fight_rules(self, state: CollectionState) -> bool: + # easy: reflega,stitch and chicken,final form,magnera,explosion,finishing leap,thundaga,2 donald limits + # normal: 7 of those things + # hard: 5 of those things + transport_fight_rules = { + "easy": self.kh2_dict_count(transport_tools_dict, state), + "normal": self.kh2_dict_one_count(transport_tools_dict, state) >= 7, + "hard": self.kh2_dict_one_count(transport_tools_dict, state) >= 5, + } + return transport_fight_rules[self.fight_logic] + + def get_transport_movement_rules(self, state: CollectionState) -> bool: + # easy:high jump 3,aerial dodge 3,glide 3 + # normal: high jump 2,glide 3,aerial dodge 2 + # hard: (hj 2,glide 2,ad 1,any magic) or hj 1,glide 2,ad 3 any magic or (any magic master form,ad) or hj lvl 1,glide 3,ad 1 + transport_movement_rules = { + "easy": self.kh2_dict_count({ItemName.HighJump: 3, ItemName.AerialDodge: 3, ItemName.Glide: 3}, state), + "normal": self.kh2_dict_count({ItemName.HighJump: 2, ItemName.AerialDodge: 2, ItemName.Glide: 3}, state), + "hard": (self.kh2_dict_count({ItemName.HighJump: 2, ItemName.AerialDodge: 1, ItemName.Glide: 2}, state) and self.kh2_has_any(magic, state)) \ + or (self.kh2_dict_count({ItemName.HighJump: 1, ItemName.Glide: 2, ItemName.AerialDodge: 3}, state) and self.kh2_has_any(magic, state)) \ + or (self.kh2_dict_count({ItemName.HighJump: 1, ItemName.Glide: 3, ItemName.AerialDodge: 1}, state)) \ + or (self.kh2_has_all([ItemName.MasterForm, ItemName.AerialDodge], state) and self.kh2_has_any(magic, state)), + } + return transport_movement_rules[self.fight_logic] + + def get_scar_rules(self, state: CollectionState) -> bool: + # easy: reflect,thunder,fire + # normal:reflect,fire + # hard:reflect + scar_rules = { + "easy": self.kh2_has_all([ItemName.ReflectElement, ItemName.ThunderElement, ItemName.FireElement], state), + "normal": self.kh2_has_all([ItemName.ReflectElement, ItemName.FireElement], state), + "hard": state.has(ItemName.ReflectElement, self.player), + } + return scar_rules[self.fight_logic] + + def get_groundshaker_rules(self, state: CollectionState) -> bool: + # easy:berserk charge,cure,2 air combo plus,reflect + # normal:berserk charge,reflect,cure + # hard:berserk charge or 2 air combo plus. reflect + groundshaker_rules = { + "easy": state.has(ItemName.AirComboPlus, self.player, 2) and self.kh2_has_all([ItemName.BerserkCharge, ItemName.CureElement, ItemName.ReflectElement], state), + "normal": self.kh2_has_all([ItemName.BerserkCharge, ItemName.ReflectElement, ItemName.CureElement], state), + "hard": (state.has(ItemName.BerserkCharge, self.player) or state.has(ItemName.AirComboPlus, self.player, 2)) and state.has(ItemName.ReflectElement, self.player), + } + return groundshaker_rules[self.fight_logic] + + def get_data_saix_rules(self, state: CollectionState) -> bool: + # easy:guard,2 gap closers,thunder,blizzard,2 donald limit,reflega,2 ground finisher,aerial dodge 3,glide 3,final 7,firaga,scom + # normal:guard,1 gap closers,thunder,blizzard,1 donald limit,reflega,1 ground finisher,aerial dodge 3,glide 3,final 7,firaga + # hard:aerial dodge 3,glide 3,guard,reflect,blizzard,1 gap closer,1 ground finisher + easy_data_rules = { + "easy": self.kh2_dict_count(easy_data_saix, state) and self.form_list_unlock(state, ItemName.FinalForm, 5), + "normal": self.kh2_dict_count(normal_data_saix, state) and self.kh2_list_any_sum([gap_closer, ground_finisher, donald_limit], state) >= 3 and self.form_list_unlock(state, ItemName.FinalForm, 5), + "hard": self.kh2_dict_count(hard_data_saix, state) and self.kh2_list_any_sum([gap_closer, ground_finisher], state) >= 2 + } + return easy_data_rules[self.fight_logic] + + @staticmethod + def get_twilight_thorn_rules() -> bool: + return True + + @staticmethod + def get_axel_one_rules() -> bool: + return True + + @staticmethod + def get_axel_two_rules() -> bool: + return True + + def get_data_roxas_rules(self, state: CollectionState) -> bool: + # easy:both gap closers,limit 5,reflega,guard,both 2 ground finishers,3 dodge roll,finishing plus,scom + # normal:both gap closers,limit 5,reflera,guard,both 2 ground finishers,3 dodge roll,finishing plus + # hard:1 gap closers,reflect, guard,both 1 ground finisher,2 dodge roll,finishing plus + data_roxas_rules = { + "easy": self.kh2_dict_count(easy_data_roxas_tools, state) and self.kh2_can_reach(LocationName.Limitlvl5, state) and self.kh2_list_any_sum([donald_limit], state) >= 1, + "normal": self.kh2_dict_count(normal_data_roxas_tools, state) and self.kh2_can_reach(LocationName.Limitlvl5, state) and self.kh2_list_any_sum([donald_limit, gap_closer], state) >= 2, + "hard": self.kh2_dict_count(hard_data_roxas_tools, state) and self.kh2_list_any_sum([gap_closer, ground_finisher], state) >= 2 + } + return data_roxas_rules[self.fight_logic] + + def get_data_axel_rules(self, state: CollectionState) -> bool: + # easy:both gap closers,limit 5,reflega,guard,both 2 ground finishers,3 dodge roll,finishing plus,scom,blizzaga + # normal:both gap closers,limit 5,reflera,guard,both 2 ground finishers,3 dodge roll,finishing plus,blizzaga + # hard:1 gap closers,reflect, guard,both 1 ground finisher,2 dodge roll,finishing plus,blizzara + data_axel_rules = { + "easy": self.kh2_dict_count(easy_data_axel_tools, state) and self.kh2_can_reach(LocationName.Limitlvl5, state) and self.kh2_list_any_sum([donald_limit], state) >= 1, + "normal": self.kh2_dict_count(normal_data_axel_tools, state) and self.kh2_can_reach(LocationName.Limitlvl5, state) and self.kh2_list_any_sum([donald_limit, gap_closer], state) >= 2, + "hard": self.kh2_dict_count(hard_data_axel_tools, state) and self.kh2_list_any_sum([gap_closer, ground_finisher], state) >= 2 + } + return data_axel_rules[self.fight_logic] + + def get_roxas_rules(self, state: CollectionState) -> bool: + # easy:aerial dodge 1,glide 1, limit form,thunder,reflera,guard break,2 gap closers,finishing plus,blizzard + # normal:thunder,reflera,guard break,2 gap closers,finishing plus,blizzard + # hard:guard + roxas_rules = { + "easy": self.kh2_dict_count(easy_roxas_tools, state), + "normal": self.kh2_dict_count(normal_roxas_tools, state), + "hard": state.has(ItemName.Guard, self.player), + } + return roxas_rules[self.fight_logic] + + def get_xigbar_rules(self, state: CollectionState) -> bool: + # easy:final 4,horizontal slash,fira,finishing plus,glide 2,aerial dodge 2,quick run 2,guard,reflect + # normal:final 4,fira,finishing plus,glide 2,aerial dodge 2,quick run 2,guard,reflect + # hard:guard,quick run,finishing plus + xigbar_rules = { + "easy": self.kh2_dict_count(easy_xigbar_tools, state) and self.form_list_unlock(state, ItemName.FinalForm, 1) and self.kh2_has_any([ItemName.LightDarkness, ItemName.FinalForm], state), + "normal": self.kh2_dict_count(normal_xigbar_tools, state) and self.form_list_unlock(state, ItemName.FinalForm, 1), + "hard": self.kh2_has_all([ItemName.Guard, ItemName.QuickRun, ItemName.FinishingPlus], state), + } + return xigbar_rules[self.fight_logic] + + def get_luxord_rules(self, state: CollectionState) -> bool: + # easy:aerial dodge 1,glide 1,quickrun 2,guard,reflera,2 gap closers,ground finisher,limit form + # normal:aerial dodge 1,glide 1,quickrun 2,guard,reflera,1 gap closers,ground finisher + # hard:quick run,guard + luxord_rules = { + "easy": self.kh2_dict_count(easy_luxord_tools, state) and self.kh2_has_any(ground_finisher, state), + "normal": self.kh2_dict_count(normal_luxord_tools, state) and self.kh2_list_any_sum([gap_closer, ground_finisher], state) >= 2, + "hard": self.kh2_has_all([ItemName.Guard, ItemName.QuickRun], state) + } + return luxord_rules[self.fight_logic] + + def get_saix_rules(self, state: CollectionState) -> bool: + # easy:aerial dodge 1,glide 1,quickrun 2,guard,reflera,2 gap closers,ground finisher,limit form + # normal:aerial dodge 1,glide 1,quickrun 2,guard,reflera,1 gap closers,ground finisher + # hard:,guard + + saix_rules = { + "easy": self.kh2_dict_count(easy_saix_tools, state) and self.kh2_has_any(ground_finisher, state), + "normal": self.kh2_dict_count(normal_saix_tools, state) and self.kh2_list_any_sum([gap_closer, ground_finisher], state) >= 2, + "hard": self.kh2_has_all([ItemName.Guard], state) + } + return saix_rules[self.fight_logic] + + def get_xemnas_rules(self, state: CollectionState) -> bool: + # easy:aerial dodge 1,glide 1,quickrun 2,guard,reflera,2 gap closers,ground finisher,limit form + # normal:aerial dodge 1,glide 1,quickrun 2,guard,reflera,1 gap closers,ground finisher + # hard:,guard + xemnas_rules = { + "easy": self.kh2_dict_count(easy_xemnas_tools, state) and self.kh2_has_any(ground_finisher, state), + "normal": self.kh2_dict_count(normal_xemnas_tools, state) and self.kh2_list_any_sum([gap_closer, ground_finisher], state) >= 2, + "hard": self.kh2_has_all([ItemName.Guard], state) + } + return xemnas_rules[self.fight_logic] - # Forbid Abilities on popups due to game limitations - for location in exclusion_table["Popups"]: - forbid_items(world.get_location(location, player), exclusionItem_table["Ability"]) - forbid_items(world.get_location(location, player), exclusionItem_table["StatUps"]) + def get_armored_xemnas_one_rules(self, state: CollectionState) -> bool: + # easy:donald limit,reflect,1 gap closer,ground finisher + # normal:reflect,gap closer,ground finisher + # hard:reflect + armored_xemnas_one_rules = { + "easy": self.kh2_list_any_sum([donald_limit, gap_closer, ground_finisher, {ItemName.ReflectElement}], state) >= 4, + "normal": self.kh2_list_any_sum([gap_closer, ground_finisher, {ItemName.ReflectElement}], state) >= 3, + "hard": state.has(ItemName.ReflectElement, self.player), + } + return armored_xemnas_one_rules[self.fight_logic] - for location in STT_Checks: - forbid_items(world.get_location(location, player), exclusionItem_table["StatUps"]) + def get_armored_xemnas_two_rules(self, state: CollectionState) -> bool: + # easy:donald limit,reflect,1 gap closer,ground finisher + # normal:reflect,gap closer,ground finisher + # hard:reflect + armored_xemnas_two_rules = { + "easy": self.kh2_list_any_sum([gap_closer, ground_finisher, {ItemName.ReflectElement}, {ItemName.ThunderElement}], state) >= 4, + "normal": self.kh2_list_any_sum([gap_closer, ground_finisher, {ItemName.ReflectElement}], state) >= 3, + "hard": state.has(ItemName.ReflectElement, self.player), + } + return armored_xemnas_two_rules[self.fight_logic] - # Santa's house also breaks with stat ups - for location in {LocationName.SantasHouseChristmasTownMap, LocationName.SantasHouseAPBoost}: - forbid_items(world.get_location(location, player), exclusionItem_table["StatUps"]) + def get_final_xemnas_rules(self, state: CollectionState) -> bool: + # easy:reflera,limit form,finishing plus,gap closer,guard + # normal:reflect,finishing plus,guard + # hard:guard + final_xemnas_rules = { + "easy": self.kh2_has_all([ItemName.LimitForm, ItemName.FinishingPlus, ItemName.Guard], state) and state.has(ItemName.ReflectElement, self.player, 2) and self.kh2_has_any(gap_closer, state), + "normal": self.kh2_has_all([ItemName.ReflectElement, ItemName.FinishingPlus, ItemName.Guard], state), + "hard": state.has(ItemName.Guard, self.player), + } + return final_xemnas_rules[self.fight_logic] - add_rule(world.get_location(LocationName.TransporttoRemembrance, player), - lambda state: state.kh_transport(player)) + def get_data_xemnas_rules(self, state: CollectionState) -> bool: + # easy:combo master,slapshot,reflega,2 ground finishers,both gap closers,finishing plus,guard,limit 5,scom,trinity limit + # normal:combo master,slapshot,reflega,2 ground finishers,both gap closers,finishing plus,guard,limit 5, + # hard:combo master,slapshot,reflera,1 ground finishers,1 gap closers,finishing plus,guard,limit form + data_xemnas_rules = { + "easy": self.kh2_dict_count(easy_data_xemnas, state) and self.kh2_list_count_sum(ground_finisher, state) >= 2 and self.kh2_can_reach(LocationName.Limitlvl5, state), + "normal": self.kh2_dict_count(normal_data_xemnas, state) and self.kh2_list_count_sum(ground_finisher, state) >= 2 and self.kh2_can_reach(LocationName.Limitlvl5, state), + "hard": self.kh2_dict_count(hard_data_xemnas, state) and self.kh2_list_any_sum([ground_finisher, gap_closer], state) >= 2 + } + return data_xemnas_rules[self.fight_logic] diff --git a/worlds/kh2/WorldLocations.py b/worlds/kh2/WorldLocations.py index 172874c2b71a..6df18fc800e3 100644 --- a/worlds/kh2/WorldLocations.py +++ b/worlds/kh2/WorldLocations.py @@ -96,6 +96,10 @@ class WorldLocationData(typing.NamedTuple): LocationName.LingeringWillBonus: WorldLocationData(0x370C, 6), LocationName.LingeringWillProofofConnection: WorldLocationData(0x370C, 6), LocationName.LingeringWillManifestIllusion: WorldLocationData(0x370C, 6), + + 'Lingering Will Bonus: Sora Slot 1': WorldLocationData(14092, 6), + 'Lingering Will Proof of Connection': WorldLocationData(14092, 6), + 'Lingering Will Manifest Illusion': WorldLocationData(14092, 6), } TR_Checks = { LocationName.CornerstoneHillMap: WorldLocationData(0x23B2, 0), @@ -226,6 +230,8 @@ class WorldLocationData(typing.NamedTuple): LocationName.DonaldXaldinGetBonus: WorldLocationData(0x3704, 4), LocationName.SecretAnsemReport4: WorldLocationData(0x1D31, 2), LocationName.XaldinDataDefenseBoost: WorldLocationData(0x1D34, 7), + + 'Data Xaldin': WorldLocationData(7476, 7), } SP_Checks = { LocationName.PitCellAreaMap: WorldLocationData(0x23CA, 2), @@ -351,6 +357,7 @@ class WorldLocationData(typing.NamedTuple): LocationName.RestorationSiteMoonRecipe: WorldLocationData(0x23C9, 3), LocationName.RestorationSiteAPBoost: WorldLocationData(0x23DB, 2), LocationName.DemyxHB: WorldLocationData(0x3707, 4), + '(HB) Demyx Bonus: Donald Slot 1': WorldLocationData(14087, 4), LocationName.DemyxHBGetBonus: WorldLocationData(0x3707, 4), LocationName.DonaldDemyxHBGetBonus: WorldLocationData(0x3707, 4), LocationName.FFFightsCureElement: WorldLocationData(0x1D14, 6), @@ -409,6 +416,25 @@ class WorldLocationData(typing.NamedTuple): LocationName.VexenASRoadtoDiscovery: WorldLocationData(0x370C, 0), LocationName.VexenDataLostIllusion: WorldLocationData(0x370C, 0), # LocationName.DemyxDataAPBoost: WorldLocationData(0x1D26, 5), + + 'Lexaeus Bonus: Sora Slot 1': WorldLocationData(14092, 1), + 'AS Lexaeus': WorldLocationData(14092, 1), + 'Data Lexaeus': WorldLocationData(14092, 1), + 'Marluxia Bonus: Sora Slot 1': WorldLocationData(14092, 3), + 'AS Marluxia': WorldLocationData(14092, 3), + 'Data Marluxia': WorldLocationData(14092, 3), + 'Zexion Bonus: Sora Slot 1': WorldLocationData(14092, 2), + 'Zexion Bonus: Goofy Slot 1': WorldLocationData(14092, 2), + 'AS Zexion': WorldLocationData(14092, 2), + 'Data Zexion': WorldLocationData(14092, 2), + 'Larxene Bonus: Sora Slot 1': WorldLocationData(14092, 4), + 'AS Larxene': WorldLocationData(14092, 4), + 'Data Larxene': WorldLocationData(14092, 4), + 'Vexen Bonus: Sora Slot 1': WorldLocationData(14092, 0), + 'AS Vexen': WorldLocationData(14092, 0), + 'Data Vexen': WorldLocationData(14092, 0), + 'Data Demyx': WorldLocationData(7462, 5), + LocationName.GardenofAssemblageMap: WorldLocationData(0x23DF, 1), LocationName.GoALostIllusion: WorldLocationData(0x23DF, 2), LocationName.ProofofNonexistence: WorldLocationData(0x23DF, 3), @@ -549,50 +575,97 @@ class WorldLocationData(typing.NamedTuple): LocationName.BetwixtandBetween: WorldLocationData(0x370B, 7), LocationName.BetwixtandBetweenBondofFlame: WorldLocationData(0x1CE9, 1), LocationName.AxelDataMagicBoost: WorldLocationData(0x1CEB, 4), + + 'Data Axel': WorldLocationData(7403, 4), } TWTNW_Checks = { - LocationName.FragmentCrossingMythrilStone: WorldLocationData(0x23CB, 4), - LocationName.FragmentCrossingMythrilCrystal: WorldLocationData(0x23CB, 5), - LocationName.FragmentCrossingAPBoost: WorldLocationData(0x23CB, 6), - LocationName.FragmentCrossingOrichalcum: WorldLocationData(0x23CB, 7), - LocationName.Roxas: WorldLocationData(0x370C, 5), - LocationName.RoxasGetBonus: WorldLocationData(0x370C, 5), - LocationName.RoxasSecretAnsemReport8: WorldLocationData(0x1ED1, 1), - LocationName.TwoBecomeOne: WorldLocationData(0x1ED1, 1), - LocationName.MemorysSkyscaperMythrilCrystal: WorldLocationData(0x23CD, 3), - LocationName.MemorysSkyscaperAPBoost: WorldLocationData(0x23DC, 0), - LocationName.MemorysSkyscaperMythrilStone: WorldLocationData(0x23DC, 1), - LocationName.TheBrinkofDespairDarkCityMap: WorldLocationData(0x23CA, 5), - LocationName.TheBrinkofDespairOrichalcumPlus: WorldLocationData(0x23DA, 2), - LocationName.NothingsCallMythrilGem: WorldLocationData(0x23CC, 0), - LocationName.NothingsCallOrichalcum: WorldLocationData(0x23CC, 1), - LocationName.TwilightsViewCosmicBelt: WorldLocationData(0x23CA, 6), - LocationName.XigbarBonus: WorldLocationData(0x3706, 7), - LocationName.XigbarSecretAnsemReport3: WorldLocationData(0x1ED2, 2), - LocationName.NaughtsSkywayMythrilGem: WorldLocationData(0x23CC, 2), - LocationName.NaughtsSkywayOrichalcum: WorldLocationData(0x23CC, 3), - LocationName.NaughtsSkywayMythrilCrystal: WorldLocationData(0x23CC, 4), - LocationName.Oblivion: WorldLocationData(0x1ED2, 4), - LocationName.CastleThatNeverWasMap: WorldLocationData(0x1ED2, 4), - LocationName.Luxord: WorldLocationData(0x3707, 0), - LocationName.LuxordGetBonus: WorldLocationData(0x3707, 0), - LocationName.LuxordSecretAnsemReport9: WorldLocationData(0x1ED2, 7), - LocationName.SaixBonus: WorldLocationData(0x3707, 1), - LocationName.SaixSecretAnsemReport12: WorldLocationData(0x1ED3, 2), - LocationName.PreXemnas1SecretAnsemReport11: WorldLocationData(0x1ED3, 6), - LocationName.RuinandCreationsPassageMythrilStone: WorldLocationData(0x23CC, 7), - LocationName.RuinandCreationsPassageAPBoost: WorldLocationData(0x23CD, 0), - LocationName.RuinandCreationsPassageMythrilCrystal: WorldLocationData(0x23CD, 1), - LocationName.RuinandCreationsPassageOrichalcum: WorldLocationData(0x23CD, 2), - LocationName.Xemnas1: WorldLocationData(0x3707, 2), - LocationName.Xemnas1GetBonus: WorldLocationData(0x3707, 2), - LocationName.Xemnas1SecretAnsemReport13: WorldLocationData(0x1ED4, 5), - LocationName.FinalXemnas: WorldLocationData(0x1ED8, 1), - LocationName.XemnasDataPowerBoost: WorldLocationData(0x1EDA, 2), - LocationName.XigbarDataDefenseBoost: WorldLocationData(0x1ED9, 7), - LocationName.SaixDataDefenseBoost: WorldLocationData(0x1EDA, 0), - LocationName.LuxordDataAPBoost: WorldLocationData(0x1EDA, 1), - LocationName.RoxasDataMagicBoost: WorldLocationData(0x1ED9, 6), + LocationName.FragmentCrossingMythrilStone: WorldLocationData(0x23CB, 4), + LocationName.FragmentCrossingMythrilCrystal: WorldLocationData(0x23CB, 5), + LocationName.FragmentCrossingAPBoost: WorldLocationData(0x23CB, 6), + LocationName.FragmentCrossingOrichalcum: WorldLocationData(0x23CB, 7), + LocationName.Roxas: WorldLocationData(0x370C, 5), + LocationName.RoxasGetBonus: WorldLocationData(0x370C, 5), + LocationName.RoxasSecretAnsemReport8: WorldLocationData(0x1ED1, 1), + LocationName.TwoBecomeOne: WorldLocationData(0x1ED1, 1), + LocationName.MemorysSkyscaperMythrilCrystal: WorldLocationData(0x23CD, 3), + LocationName.MemorysSkyscaperAPBoost: WorldLocationData(0x23DC, 0), + LocationName.MemorysSkyscaperMythrilStone: WorldLocationData(0x23DC, 1), + LocationName.TheBrinkofDespairDarkCityMap: WorldLocationData(0x23CA, 5), + LocationName.TheBrinkofDespairOrichalcumPlus: WorldLocationData(0x23DA, 2), + LocationName.NothingsCallMythrilGem: WorldLocationData(0x23CC, 0), + LocationName.NothingsCallOrichalcum: WorldLocationData(0x23CC, 1), + LocationName.TwilightsViewCosmicBelt: WorldLocationData(0x23CA, 6), + LocationName.XigbarBonus: WorldLocationData(0x3706, 7), + LocationName.XigbarSecretAnsemReport3: WorldLocationData(0x1ED2, 2), + LocationName.NaughtsSkywayMythrilGem: WorldLocationData(0x23CC, 2), + LocationName.NaughtsSkywayOrichalcum: WorldLocationData(0x23CC, 3), + LocationName.NaughtsSkywayMythrilCrystal: WorldLocationData(0x23CC, 4), + LocationName.Oblivion: WorldLocationData(0x1ED2, 4), + LocationName.CastleThatNeverWasMap: WorldLocationData(0x1ED2, 4), + LocationName.Luxord: WorldLocationData(0x3707, 0), + LocationName.LuxordGetBonus: WorldLocationData(0x3707, 0), + LocationName.LuxordSecretAnsemReport9: WorldLocationData(0x1ED2, 7), + LocationName.SaixBonus: WorldLocationData(0x3707, 1), + LocationName.SaixSecretAnsemReport12: WorldLocationData(0x1ED3, 2), + LocationName.PreXemnas1SecretAnsemReport11: WorldLocationData(0x1ED3, 6), + LocationName.RuinandCreationsPassageMythrilStone: WorldLocationData(0x23CC, 7), + LocationName.RuinandCreationsPassageAPBoost: WorldLocationData(0x23CD, 0), + LocationName.RuinandCreationsPassageMythrilCrystal: WorldLocationData(0x23CD, 1), + LocationName.RuinandCreationsPassageOrichalcum: WorldLocationData(0x23CD, 2), + LocationName.Xemnas1: WorldLocationData(0x3707, 2), + LocationName.Xemnas1GetBonus: WorldLocationData(0x3707, 2), + LocationName.Xemnas1SecretAnsemReport13: WorldLocationData(0x1ED4, 5), + LocationName.FinalXemnas: WorldLocationData(0x1ED8, 1), + LocationName.XemnasDataPowerBoost: WorldLocationData(0x1EDA, 2), + LocationName.XigbarDataDefenseBoost: WorldLocationData(0x1ED9, 7), + LocationName.SaixDataDefenseBoost: WorldLocationData(0x1EDA, 0), + LocationName.LuxordDataAPBoost: WorldLocationData(0x1EDA, 1), + LocationName.RoxasDataMagicBoost: WorldLocationData(0x1ED9, 6), + + "(TWTNW) Roxas Bonus: Sora Slot 1": WorldLocationData(14092, 5), + "(TWTNW) Roxas Bonus: Sora Slot 2": WorldLocationData(14092, 5), + "(TWTNW) Roxas Secret Ansem Report 8": WorldLocationData(7889, 1), + "(TWTNW) Two Become One": WorldLocationData(7889, 1), + "(TWTNW) Memory's Skyscaper Mythril Crystal": WorldLocationData(9165, 3), + "(TWTNW) Memory's Skyscaper AP Boost": WorldLocationData(9180, 0), + "(TWTNW) Memory's Skyscaper Mythril Stone": WorldLocationData(9180, 1), + "(TWTNW) The Brink of Despair Dark City Map": WorldLocationData(9162, 5), + "(TWTNW) The Brink of Despair Orichalcum+": WorldLocationData(9178, 2), + "(TWTNW) Nothing's Call Mythril Gem": WorldLocationData(9164, 0), + "(TWTNW) Nothing's Call Orichalcum": WorldLocationData(9164, 1), + "(TWTNW) Twilight's View Cosmic Belt": WorldLocationData(9162, 6), + "(TWTNW) Xigbar Bonus: Sora Slot 1": WorldLocationData(14086, 7), + "(TWTNW) Xigbar Secret Ansem Report 3": WorldLocationData(7890, 2), + "(TWTNW) Naught's Skyway Mythril Gem": WorldLocationData(9164, 2), + "(TWTNW) Naught's Skyway Orichalcum": WorldLocationData(9164, 3), + "(TWTNW) Naught's Skyway Mythril Crystal": WorldLocationData(9164, 4), + "(TWTNW) Oblivion": WorldLocationData(7890, 4), + "(TWTNW) Castle That Never Was Map": WorldLocationData(7890, 4), + "(TWTNW) Luxord": WorldLocationData(14087, 0), + "(TWTNW) Luxord Bonus: Sora Slot 1": WorldLocationData(14087, 0), + "(TWTNW) Luxord Secret Ansem Report 9": WorldLocationData(7890, 7), + "(TWTNW) Saix Bonus: Sora Slot 1": WorldLocationData(14087, 1), + "(TWTNW) Saix Secret Ansem Report 12": WorldLocationData(7891, 2), + "(TWTNW) Secret Ansem Report 11 (Pre-Xemnas 1)": WorldLocationData(7891, 6), + "(TWTNW) Ruin and Creation's Passage Mythril Stone": WorldLocationData(9164, 7), + "(TWTNW) Ruin and Creation's Passage AP Boost": WorldLocationData(9165, 0), + "(TWTNW) Ruin and Creation's Passage Mythril Crystal": WorldLocationData(9165, 1), + "(TWTNW) Ruin and Creation's Passage Orichalcum": WorldLocationData(9165, 2), + "(TWTNW) Xemnas 1 Bonus: Sora Slot 1": WorldLocationData(14087, 2), + "(TWTNW) Xemnas 1 Bonus: Sora Slot 2": WorldLocationData(14087, 2), + "(TWTNW) Xemnas 1 Secret Ansem Report 13": WorldLocationData(7892, 5), + "Data Xemnas": WorldLocationData(7898, 2), + "Data Xigbar": WorldLocationData(7897, 7), + "Data Saix": WorldLocationData(7898, 0), + "Data Luxord": WorldLocationData(7898, 1), + "Data Roxas": WorldLocationData(7897, 6), + +} +Atlantica_Checks = { + LocationName.UnderseaKingdomMap: WorldLocationData(0x1DF4, 2), + LocationName.MysteriousAbyss: WorldLocationData(0x1DF5, 3), + LocationName.MusicalOrichalcumPlus: WorldLocationData(0x1DF4, 1), + LocationName.MusicalBlizzardElement: WorldLocationData(0x1DF4, 1) } SoraLevels = { # LocationName.Lvl1: WorldLocationData(0xFFFF,1), @@ -743,6 +816,15 @@ class WorldLocationData(typing.NamedTuple): LocationName.Finallvl6: WorldLocationData(0x33D6, 6), LocationName.Finallvl7: WorldLocationData(0x33D6, 7), +} +SummonLevels = { + LocationName.Summonlvl2: WorldLocationData(0x3526, 2), + LocationName.Summonlvl3: WorldLocationData(0x3526, 3), + LocationName.Summonlvl4: WorldLocationData(0x3526, 4), + LocationName.Summonlvl5: WorldLocationData(0x3526, 5), + LocationName.Summonlvl6: WorldLocationData(0x3526, 6), + LocationName.Summonlvl7: WorldLocationData(0x3526, 7), + } weaponSlots = { LocationName.AdamantShield: WorldLocationData(0x35E6, 1), @@ -817,7 +899,6 @@ class WorldLocationData(typing.NamedTuple): all_world_locations = { **TWTNW_Checks, **TT_Checks, - **TT_Checks, **HB_Checks, **BC_Checks, **Oc_Checks, @@ -828,11 +909,9 @@ class WorldLocationData(typing.NamedTuple): **DC_Checks, **TR_Checks, **HT_Checks, - **HB_Checks, **PR_Checks, **SP_Checks, - **TWTNW_Checks, - **HB_Checks, + **Atlantica_Checks, } levels_locations = { diff --git a/worlds/kh2/__init__.py b/worlds/kh2/__init__.py index 23075a2084df..69f844f45a68 100644 --- a/worlds/kh2/__init__.py +++ b/worlds/kh2/__init__.py @@ -1,15 +1,25 @@ -from BaseClasses import Tutorial, ItemClassification import logging +from typing import List +from BaseClasses import Tutorial, ItemClassification +from Fill import fill_restrictive +from worlds.LauncherComponents import Component, components, Type, launch_subprocess +from worlds.AutoWorld import World, WebWorld from .Items import * -from .Locations import all_locations, setup_locations, exclusion_table, AllWeaponSlot -from .Names import ItemName, LocationName +from .Locations import * +from .Names import ItemName, LocationName, RegionName from .OpenKH import patch_kh2 -from .Options import KH2_Options +from .Options import KingdomHearts2Options from .Regions import create_regions, connect_regions -from .Rules import set_rules -from ..AutoWorld import World, WebWorld -from .logic import KH2Logic +from .Rules import * + + +def launch_client(): + from .Client import launch + launch_subprocess(launch, name="KH2Client") + + +components.append(Component("KH2 Client", "KH2Client", func=launch_client, component_type=Type.CLIENT)) class KingdomHearts2Web(WebWorld): @@ -23,99 +33,119 @@ class KingdomHearts2Web(WebWorld): )] -# noinspection PyUnresolvedReferences class KH2World(World): """ Kingdom Hearts II is an action role-playing game developed and published by Square Enix and released in 2005. It is the sequel to Kingdom Hearts and Kingdom Hearts: Chain of Memories, and like the two previous games, focuses on Sora and his friends' continued battle against the Darkness. """ - game: str = "Kingdom Hearts 2" + game = "Kingdom Hearts 2" web = KingdomHearts2Web() - data_version = 1 - required_client_version = (0, 4, 0) - option_definitions = KH2_Options - item_name_to_id = {name: data.code for name, data in item_dictionary_table.items()} - location_name_to_id = {item_name: data.code for item_name, data in all_locations.items() if data.code} + + required_client_version = (0, 4, 4) + options_dataclass = KingdomHearts2Options + options: KingdomHearts2Options + item_name_to_id = {item: item_id + for item_id, item in enumerate(item_dictionary_table.keys(), 0x130000)} + location_name_to_id = {item: location + for location, item in enumerate(all_locations.keys(), 0x130000)} item_name_groups = item_groups + visitlocking_dict: Dict[str, int] + plando_locations: Dict[str, str] + lucky_emblem_amount: int + lucky_emblem_required: int + bounties_required: int + bounties_amount: int + filler_items: List[str] + item_quantity_dict: Dict[str, int] + local_items: Dict[int, int] + sora_ability_dict: Dict[str, int] + goofy_ability_dict: Dict[str, int] + donald_ability_dict: Dict[str, int] + total_locations: int + + # growth_list: list[str] + def __init__(self, multiworld: "MultiWorld", player: int): super().__init__(multiworld, player) - self.valid_abilities = None - self.visitlocking_dict = None - self.plando_locations = None - self.luckyemblemamount = None - self.luckyemblemrequired = None - self.BountiesRequired = None - self.BountiesAmount = None - self.hitlist = None - self.LocalItems = {} - self.RandomSuperBoss = list() - self.filler_items = list() - self.item_quantity_dict = {} - self.donald_ability_pool = list() - self.goofy_ability_pool = list() - self.sora_keyblade_ability_pool = list() - self.keyblade_slot_copy = list(Locations.Keyblade_Slots.keys()) - self.keyblade_slot_copy.remove(LocationName.KingdomKeySlot) - self.totalLocations = len(all_locations.items()) + # random_super_boss_list List[str] + # has to be in __init__ or else other players affect each other's bounties + self.random_super_boss_list = list() self.growth_list = list() - for x in range(4): - self.growth_list.extend(Movement_Table.keys()) - self.slotDataDuping = set() - self.localItems = dict() + # lists of KH2Item + self.keyblade_ability_pool = list() + + self.goofy_get_bonus_abilities = list() + self.goofy_weapon_abilities = list() + self.donald_get_bonus_abilities = list() + self.donald_weapon_abilities = list() + + self.slot_data_goofy_weapon = dict() + self.slot_data_sora_weapon = dict() + self.slot_data_donald_weapon = dict() def fill_slot_data(self) -> dict: - for values in CheckDupingItems.values(): - if isinstance(values, set): - self.slotDataDuping = self.slotDataDuping.union(values) - else: - for inner_values in values.values(): - self.slotDataDuping = self.slotDataDuping.union(inner_values) - self.LocalItems = {location.address: item_dictionary_table[location.item.name].code - for location in self.multiworld.get_filled_locations(self.player) - if location.item.player == self.player - and location.item.name in self.slotDataDuping - and location.name not in AllWeaponSlot} - - return {"hitlist": self.hitlist, - "LocalItems": self.LocalItems, - "Goal": self.multiworld.Goal[self.player].value, - "FinalXemnas": self.multiworld.FinalXemnas[self.player].value, - "LuckyEmblemsRequired": self.multiworld.LuckyEmblemsRequired[self.player].value, - "BountyRequired": self.multiworld.BountyRequired[self.player].value} - - def create_item(self, name: str, ) -> Item: - data = item_dictionary_table[name] - if name in Progression_Dicts["Progression"]: + for ability in self.slot_data_sora_weapon: + if ability in self.sora_ability_dict and self.sora_ability_dict[ability] >= 1: + self.sora_ability_dict[ability] -= 1 + self.donald_ability_dict = {k: v.quantity for k, v in DonaldAbility_Table.items()} + for ability in self.slot_data_donald_weapon: + if ability in self.donald_ability_dict and self.donald_ability_dict[ability] >= 1: + self.donald_ability_dict[ability] -= 1 + self.goofy_ability_dict = {k: v.quantity for k, v in GoofyAbility_Table.items()} + for ability in self.slot_data_goofy_weapon: + if ability in self.goofy_ability_dict and self.goofy_ability_dict[ability] >= 1: + self.goofy_ability_dict[ability] -= 1 + + slot_data = self.options.as_dict("Goal", "FinalXemnas", "LuckyEmblemsRequired", "BountyRequired") + slot_data.update({ + "hitlist": [], # remove this after next update + "PoptrackerVersionCheck": 4.3, + "KeybladeAbilities": self.sora_ability_dict, + "StaffAbilities": self.donald_ability_dict, + "ShieldAbilities": self.goofy_ability_dict, + }) + return slot_data + + def create_item(self, name: str) -> Item: + """ + Returns created KH2Item + """ + # data = item_dictionary_table[name] + if name in progression_set: item_classification = ItemClassification.progression + elif name in useful_set: + item_classification = ItemClassification.useful else: item_classification = ItemClassification.filler - created_item = KH2Item(name, item_classification, data.code, self.player) + created_item = KH2Item(name, item_classification, self.item_name_to_id[name], self.player) return created_item def create_items(self) -> None: - self.visitlocking_dict = Progression_Dicts["AllVisitLocking"].copy() - if self.multiworld.Schmovement[self.player] != "level_0": - for _ in range(self.multiworld.Schmovement[self.player].value): - for name in {ItemName.HighJump, ItemName.QuickRun, ItemName.DodgeRoll, ItemName.AerialDodge, - ItemName.Glide}: + """ + Fills ItemPool and manages schmovement, random growth, visit locking and random starting visit locking. + """ + self.visitlocking_dict = visit_locking_dict["AllVisitLocking"].copy() + if self.options.Schmovement != "level_0": + for _ in range(self.options.Schmovement.value): + for name in Movement_Table.keys(): self.item_quantity_dict[name] -= 1 self.growth_list.remove(name) self.multiworld.push_precollected(self.create_item(name)) - if self.multiworld.RandomGrowth[self.player] != 0: - max_growth = min(self.multiworld.RandomGrowth[self.player].value, len(self.growth_list)) + if self.options.RandomGrowth: + max_growth = min(self.options.RandomGrowth.value, len(self.growth_list)) for _ in range(max_growth): - random_growth = self.multiworld.per_slot_randoms[self.player].choice(self.growth_list) + random_growth = self.random.choice(self.growth_list) self.item_quantity_dict[random_growth] -= 1 self.growth_list.remove(random_growth) self.multiworld.push_precollected(self.create_item(random_growth)) - if self.multiworld.Visitlocking[self.player] == "no_visit_locking": - for item, amount in Progression_Dicts["AllVisitLocking"].items(): + if self.options.Visitlocking == "no_visit_locking": + for item, amount in visit_locking_dict["AllVisitLocking"].items(): for _ in range(amount): self.multiworld.push_precollected(self.create_item(item)) self.item_quantity_dict[item] -= 1 @@ -123,19 +153,19 @@ def create_items(self) -> None: if self.visitlocking_dict[item] == 0: self.visitlocking_dict.pop(item) - elif self.multiworld.Visitlocking[self.player] == "second_visit_locking": - for item in Progression_Dicts["2VisitLocking"]: + elif self.options.Visitlocking == "second_visit_locking": + for item in visit_locking_dict["2VisitLocking"]: self.item_quantity_dict[item] -= 1 self.visitlocking_dict[item] -= 1 if self.visitlocking_dict[item] == 0: self.visitlocking_dict.pop(item) self.multiworld.push_precollected(self.create_item(item)) - for _ in range(self.multiworld.RandomVisitLockingItem[self.player].value): + for _ in range(self.options.RandomVisitLockingItem.value): if sum(self.visitlocking_dict.values()) <= 0: break visitlocking_set = list(self.visitlocking_dict.keys()) - item = self.multiworld.per_slot_randoms[self.player].choice(visitlocking_set) + item = self.random.choice(visitlocking_set) self.item_quantity_dict[item] -= 1 self.visitlocking_dict[item] -= 1 if self.visitlocking_dict[item] == 0: @@ -145,175 +175,258 @@ def create_items(self) -> None: itempool = [self.create_item(item) for item, data in self.item_quantity_dict.items() for _ in range(data)] # Creating filler for unfilled locations - itempool += [self.create_filler() - for _ in range(self.totalLocations - len(itempool))] + itempool += [self.create_filler() for _ in range(self.total_locations - len(itempool))] + self.multiworld.itempool += itempool def generate_early(self) -> None: - # Item Quantity dict because Abilities can be a problem for KH2's Software. + """ + Determines the quantity of items and maps plando locations to items. + """ + # Item: Quantity Map + # Example. Quick Run: 4 + self.total_locations = len(all_locations.keys()) + for x in range(4): + self.growth_list.extend(Movement_Table.keys()) + self.item_quantity_dict = {item: data.quantity for item, data in item_dictionary_table.items()} + self.sora_ability_dict = {k: v.quantity for dic in [SupportAbility_Table, ActionAbility_Table] for k, v in + dic.items()} # Dictionary to mark locations with their plandoed item # Example. Final Xemnas: Victory + # 3 random support abilities because there are left over slots + support_abilities = list(SupportAbility_Table.keys()) + for _ in range(6): + random_support_ability = self.random.choice(support_abilities) + self.item_quantity_dict[random_support_ability] += 1 + self.sora_ability_dict[random_support_ability] += 1 + self.plando_locations = dict() - self.hitlist = [] self.starting_invo_verify() + + for k, v in self.options.CustomItemPoolQuantity.value.items(): + # kh2's items cannot hold more than a byte + if 255 > v > self.item_quantity_dict[k] and k in default_itempool_option.keys(): + self.item_quantity_dict[k] = v + elif 255 <= v: + logging.warning( + f"{self.player} has too many {k} in their CustomItemPool setting. Setting to default quantity") # Option to turn off Promise Charm Item - if not self.multiworld.Promise_Charm[self.player]: - self.item_quantity_dict[ItemName.PromiseCharm] = 0 + if not self.options.Promise_Charm: + del self.item_quantity_dict[ItemName.PromiseCharm] + + if not self.options.AntiForm: + del self.item_quantity_dict[ItemName.AntiForm] self.set_excluded_locations() - if self.multiworld.Goal[self.player] == "lucky_emblem_hunt": - self.luckyemblemamount = self.multiworld.LuckyEmblemsAmount[self.player].value - self.luckyemblemrequired = self.multiworld.LuckyEmblemsRequired[self.player].value + if self.options.Goal not in ["hitlist", "three_proofs"]: + self.lucky_emblem_amount = self.options.LuckyEmblemsAmount.value + self.lucky_emblem_required = self.options.LuckyEmblemsRequired.value self.emblem_verify() # hitlist - elif self.multiworld.Goal[self.player] == "hitlist": - self.RandomSuperBoss.extend(exclusion_table["Hitlist"]) - self.BountiesAmount = self.multiworld.BountyAmount[self.player].value - self.BountiesRequired = self.multiworld.BountyRequired[self.player].value + if self.options.Goal not in ["lucky_emblem_hunt", "three_proofs"]: + self.random_super_boss_list.extend(exclusion_table["Hitlist"]) + self.bounties_amount = self.options.BountyAmount.value + self.bounties_required = self.options.BountyRequired.value self.hitlist_verify() - for bounty in range(self.BountiesAmount): - randomBoss = self.multiworld.per_slot_randoms[self.player].choice(self.RandomSuperBoss) - self.plando_locations[randomBoss] = ItemName.Bounty - self.hitlist.append(self.location_name_to_id[randomBoss]) - self.RandomSuperBoss.remove(randomBoss) - self.totalLocations -= 1 - - self.donald_fill() - self.goofy_fill() - self.keyblade_fill() + prio_hitlist = [location for location in self.multiworld.priority_locations[self.player].value if + location in self.random_super_boss_list] + for bounty in range(self.options.BountyAmount.value): + if prio_hitlist: + random_boss = self.random.choice(prio_hitlist) + prio_hitlist.remove(random_boss) + else: + random_boss = self.random.choice(self.random_super_boss_list) + self.plando_locations[random_boss] = ItemName.Bounty + self.random_super_boss_list.remove(random_boss) + self.total_locations -= 1 + + self.donald_gen_early() + self.goofy_gen_early() + self.keyblade_gen_early() if self.multiworld.FinalXemnas[self.player]: self.plando_locations[LocationName.FinalXemnas] = ItemName.Victory else: self.plando_locations[LocationName.FinalXemnas] = self.create_filler().name + self.total_locations -= 1 - # same item placed because you can only get one of these 2 locations - # they are both under the same flag so the player gets both locations just one of the two items - random_stt_item = self.create_filler().name - for location in {LocationName.JunkMedal, LocationName.JunkMedal}: - self.plando_locations[location] = random_stt_item - self.level_subtraction() - # subtraction from final xemnas and stt - self.totalLocations -= 3 + if self.options.WeaponSlotStartHint: + for location in all_weapon_slot: + self.multiworld.start_location_hints[self.player].value.add(location) + + if self.options.FillerItemsLocal: + for item in filler_items: + self.multiworld.local_items[self.player].value.add(item) + # By imitating remote this doesn't have to be plandoded filler anymore + # for location in {LocationName.JunkMedal, LocationName.JunkMedal}: + # self.plando_locations[location] = random_stt_item + if not self.options.SummonLevelLocationToggle: + self.total_locations -= 6 + + self.total_locations -= self.level_subtraction() def pre_fill(self): + """ + Plandoing Events and Fill_Restrictive for donald,goofy and sora + """ + self.donald_pre_fill() + self.goofy_pre_fill() + self.keyblade_pre_fill() + for location, item in self.plando_locations.items(): self.multiworld.get_location(location, self.player).place_locked_item( self.create_item(item)) def create_regions(self): - location_table = setup_locations() - create_regions(self.multiworld, self.player, location_table) - connect_regions(self.multiworld, self.player) + """ + Creates the Regions and Connects them. + """ + create_regions(self) + connect_regions(self) def set_rules(self): - set_rules(self.multiworld, self.player) + """ + Sets the Logic for the Regions and Locations. + """ + universal_logic = Rules.KH2WorldRules(self) + form_logic = Rules.KH2FormRules(self) + fight_rules = Rules.KH2FightRules(self) + fight_rules.set_kh2_fight_rules() + universal_logic.set_kh2_rules() + form_logic.set_kh2_form_rules() def generate_output(self, output_directory: str): + """ + Generates the .zip for OpenKH (The KH Mod Manager) + """ patch_kh2(self, output_directory) - def donald_fill(self): - for item in DonaldAbility_Table: - data = self.item_quantity_dict[item] - for _ in range(data): - self.donald_ability_pool.append(item) - self.item_quantity_dict[item] = 0 - # 32 is the amount of donald abilities - while len(self.donald_ability_pool) < 32: - self.donald_ability_pool.append( - self.multiworld.per_slot_randoms[self.player].choice(self.donald_ability_pool)) - # Placing Donald Abilities on donald locations - for donaldLocation in Locations.Donald_Checks.keys(): - random_ability = self.multiworld.per_slot_randoms[self.player].choice(self.donald_ability_pool) - self.plando_locations[donaldLocation] = random_ability - self.totalLocations -= 1 - self.donald_ability_pool.remove(random_ability) - - def goofy_fill(self): - for item in GoofyAbility_Table.keys(): - data = self.item_quantity_dict[item] - for _ in range(data): - self.goofy_ability_pool.append(item) - self.item_quantity_dict[item] = 0 - # 32 is the amount of goofy abilities - while len(self.goofy_ability_pool) < 33: - self.goofy_ability_pool.append( - self.multiworld.per_slot_randoms[self.player].choice(self.goofy_ability_pool)) - # Placing Goofy Abilities on goofy locations - for goofyLocation in Locations.Goofy_Checks.keys(): - random_ability = self.multiworld.per_slot_randoms[self.player].choice(self.goofy_ability_pool) - self.plando_locations[goofyLocation] = random_ability - self.totalLocations -= 1 - self.goofy_ability_pool.remove(random_ability) - - def keyblade_fill(self): - if self.multiworld.KeybladeAbilities[self.player] == "support": - self.sora_keyblade_ability_pool = { - **{item: data for item, data in self.item_quantity_dict.items() if item in SupportAbility_Table}, - **{ItemName.NegativeCombo: 1, ItemName.AirComboPlus: 1, ItemName.ComboPlus: 1, - ItemName.FinishingPlus: 1}} - - elif self.multiworld.KeybladeAbilities[self.player] == "action": - self.sora_keyblade_ability_pool = {item: data for item, data in self.item_quantity_dict.items() if - item in ActionAbility_Table} - # there are too little action abilities so 2 random support abilities are placed - for _ in range(3): - randomSupportAbility = self.multiworld.per_slot_randoms[self.player].choice( - list(SupportAbility_Table.keys())) - while randomSupportAbility in self.sora_keyblade_ability_pool: - randomSupportAbility = self.multiworld.per_slot_randoms[self.player].choice( - list(SupportAbility_Table.keys())) - self.sora_keyblade_ability_pool[randomSupportAbility] = 1 - else: - # both action and support on keyblades. - # TODO: make option to just exclude scom - self.sora_keyblade_ability_pool = { - **{item: data for item, data in self.item_quantity_dict.items() if item in SupportAbility_Table}, - **{item: data for item, data in self.item_quantity_dict.items() if item in ActionAbility_Table}, - **{ItemName.NegativeCombo: 1, ItemName.AirComboPlus: 1, ItemName.ComboPlus: 1, - ItemName.FinishingPlus: 1}} - - for ability in self.multiworld.BlacklistKeyblade[self.player].value: - if ability in self.sora_keyblade_ability_pool: - self.sora_keyblade_ability_pool.pop(ability) - - # magic number for amount of keyblades - if sum(self.sora_keyblade_ability_pool.values()) < 28: - raise Exception( - f"{self.multiworld.get_file_safe_player_name(self.player)} has too little Keyblade Abilities in the Keyblade Pool") - - self.valid_abilities = list(self.sora_keyblade_ability_pool.keys()) - # Kingdom Key cannot have No Experience so plandoed here instead of checking 26 times if its kingdom key - random_ability = self.multiworld.per_slot_randoms[self.player].choice(self.valid_abilities) - while random_ability == ItemName.NoExperience: - random_ability = self.multiworld.per_slot_randoms[self.player].choice(self.valid_abilities) - self.plando_locations[LocationName.KingdomKeySlot] = random_ability - self.item_quantity_dict[random_ability] -= 1 - self.sora_keyblade_ability_pool[random_ability] -= 1 - if self.sora_keyblade_ability_pool[random_ability] == 0: - self.valid_abilities.remove(random_ability) - self.sora_keyblade_ability_pool.pop(random_ability) - - # plando keyblades because they can only have abilities - for keyblade in self.keyblade_slot_copy: - random_ability = self.multiworld.per_slot_randoms[self.player].choice(self.valid_abilities) - self.plando_locations[keyblade] = random_ability + def donald_gen_early(self): + random_prog_ability = self.random.choice([ItemName.Fantasia, ItemName.FlareForce]) + donald_master_ability = [donald_ability for donald_ability in DonaldAbility_Table.keys() for _ in + range(self.item_quantity_dict[donald_ability]) if + donald_ability != random_prog_ability] + self.donald_weapon_abilities = [] + self.donald_get_bonus_abilities = [] + # fill goofy weapons first + for _ in range(15): + random_ability = self.random.choice(donald_master_ability) + donald_master_ability.remove(random_ability) + self.donald_weapon_abilities += [self.create_item(random_ability)] self.item_quantity_dict[random_ability] -= 1 - self.sora_keyblade_ability_pool[random_ability] -= 1 - if self.sora_keyblade_ability_pool[random_ability] == 0: - self.valid_abilities.remove(random_ability) - self.sora_keyblade_ability_pool.pop(random_ability) - self.totalLocations -= 1 + self.total_locations -= 1 + self.slot_data_donald_weapon = [item_name.name for item_name in self.donald_weapon_abilities] + if not self.multiworld.DonaldGoofyStatsanity[self.player]: + # pre plando donald get bonuses + self.donald_get_bonus_abilities += [self.create_item(random_prog_ability)] + self.total_locations -= 1 + for item_name in donald_master_ability: + self.donald_get_bonus_abilities += [self.create_item(item_name)] + self.item_quantity_dict[item_name] -= 1 + self.total_locations -= 1 + + def goofy_gen_early(self): + random_prog_ability = self.random.choice([ItemName.Teamwork, ItemName.TornadoFusion]) + goofy_master_ability = [goofy_ability for goofy_ability in GoofyAbility_Table.keys() for _ in + range(self.item_quantity_dict[goofy_ability]) if goofy_ability != random_prog_ability] + self.goofy_weapon_abilities = [] + self.goofy_get_bonus_abilities = [] + # fill goofy weapons first + for _ in range(15): + random_ability = self.random.choice(goofy_master_ability) + goofy_master_ability.remove(random_ability) + self.goofy_weapon_abilities += [self.create_item(random_ability)] + self.item_quantity_dict[random_ability] -= 1 + self.total_locations -= 1 + + self.slot_data_goofy_weapon = [item_name.name for item_name in self.goofy_weapon_abilities] + + if not self.options.DonaldGoofyStatsanity: + # pre plando goofy get bonuses + self.goofy_get_bonus_abilities += [self.create_item(random_prog_ability)] + self.total_locations -= 1 + for item_name in goofy_master_ability: + self.goofy_get_bonus_abilities += [self.create_item(item_name)] + self.item_quantity_dict[item_name] -= 1 + self.total_locations -= 1 + + def keyblade_gen_early(self): + keyblade_master_ability = [ability for ability in SupportAbility_Table.keys() if ability not in progression_set + for _ in range(self.item_quantity_dict[ability])] + self.keyblade_ability_pool = [] + + for _ in range(len(Keyblade_Slots)): + random_ability = self.random.choice(keyblade_master_ability) + keyblade_master_ability.remove(random_ability) + self.keyblade_ability_pool += [self.create_item(random_ability)] + self.item_quantity_dict[random_ability] -= 1 + self.total_locations -= 1 + self.slot_data_sora_weapon = [item_name.name for item_name in self.keyblade_ability_pool] + + def goofy_pre_fill(self): + """ + Removes donald locations from the location pool maps random donald items to be plandoded. + """ + goofy_weapon_location_list = [self.multiworld.get_location(location, self.player) for location in + Goofy_Checks.keys() if Goofy_Checks[location].yml == "Keyblade"] + # take one of the 2 out + # randomize the list with only + for location in goofy_weapon_location_list: + random_ability = self.random.choice(self.goofy_weapon_abilities) + location.place_locked_item(random_ability) + self.goofy_weapon_abilities.remove(random_ability) + + if not self.multiworld.DonaldGoofyStatsanity[self.player]: + # plando goofy get bonuses + goofy_get_bonus_location_pool = [self.multiworld.get_location(location, self.player) for location in + Goofy_Checks.keys() if Goofy_Checks[location].yml != "Keyblade"] + for location in goofy_get_bonus_location_pool: + self.random.choice(self.goofy_get_bonus_abilities) + random_ability = self.random.choice(self.goofy_get_bonus_abilities) + location.place_locked_item(random_ability) + self.goofy_get_bonus_abilities.remove(random_ability) + + def donald_pre_fill(self): + donald_weapon_location_list = [self.multiworld.get_location(location, self.player) for location in + Donald_Checks.keys() if Donald_Checks[location].yml == "Keyblade"] + + # take one of the 2 out + # randomize the list with only + for location in donald_weapon_location_list: + random_ability = self.random.choice(self.donald_weapon_abilities) + location.place_locked_item(random_ability) + self.donald_weapon_abilities.remove(random_ability) + + if not self.multiworld.DonaldGoofyStatsanity[self.player]: + # plando goofy get bonuses + donald_get_bonus_location_pool = [self.multiworld.get_location(location, self.player) for location in + Donald_Checks.keys() if Donald_Checks[location].yml != "Keyblade"] + for location in donald_get_bonus_location_pool: + random_ability = self.random.choice(self.donald_get_bonus_abilities) + location.place_locked_item(random_ability) + self.donald_get_bonus_abilities.remove(random_ability) + + def keyblade_pre_fill(self): + """ + Fills keyblade slots with abilities determined on player's setting + """ + keyblade_locations = [self.multiworld.get_location(location, self.player) for location in Keyblade_Slots.keys()] + state = self.multiworld.get_all_state(False) + keyblade_ability_pool_copy = self.keyblade_ability_pool.copy() + fill_restrictive(self.multiworld, state, keyblade_locations, keyblade_ability_pool_copy, True, True) def starting_invo_verify(self): + """ + Making sure the player doesn't put too many abilities in their starting inventory. + """ for item, value in self.multiworld.start_inventory[self.player].value.items(): if item in ActionAbility_Table \ - or item in SupportAbility_Table or exclusionItem_table["StatUps"] \ + or item in SupportAbility_Table or exclusion_item_table["StatUps"] \ or item in DonaldAbility_Table or item in GoofyAbility_Table: # cannot have more than the quantity for abilties if value > item_dictionary_table[item].quantity: @@ -324,78 +437,100 @@ def starting_invo_verify(self): self.item_quantity_dict[item] -= value def emblem_verify(self): - if self.luckyemblemamount < self.luckyemblemrequired: + """ + Making sure lucky emblems have amount>=required. + """ + if self.lucky_emblem_amount < self.lucky_emblem_required: logging.info( - f"Lucky Emblem Amount {self.multiworld.LuckyEmblemsAmount[self.player].value} is less than required " - f"{self.multiworld.LuckyEmblemsRequired[self.player].value} for player {self.multiworld.get_file_safe_player_name(self.player)}." - f" Setting amount to {self.multiworld.LuckyEmblemsRequired[self.player].value}") - luckyemblemamount = max(self.luckyemblemamount, self.luckyemblemrequired) - self.multiworld.LuckyEmblemsAmount[self.player].value = luckyemblemamount + f"Lucky Emblem Amount {self.options.LuckyEmblemsAmount.value} is less than required " + f"{self.options.LuckyEmblemsRequired.value} for player {self.multiworld.get_file_safe_player_name(self.player)}." + f" Setting amount to {self.options.LuckyEmblemsRequired.value}") + luckyemblemamount = max(self.lucky_emblem_amount, self.lucky_emblem_required) + self.options.LuckyEmblemsAmount.value = luckyemblemamount - self.item_quantity_dict[ItemName.LuckyEmblem] = self.multiworld.LuckyEmblemsAmount[self.player].value + self.item_quantity_dict[ItemName.LuckyEmblem] = self.options.LuckyEmblemsAmount.value # give this proof to unlock the final door once the player has the amount of lucky emblem required - self.item_quantity_dict[ItemName.ProofofNonexistence] = 0 + if ItemName.ProofofNonexistence in self.item_quantity_dict: + del self.item_quantity_dict[ItemName.ProofofNonexistence] def hitlist_verify(self): + """ + Making sure hitlist have amount>=required. + """ for location in self.multiworld.exclude_locations[self.player].value: - if location in self.RandomSuperBoss: - self.RandomSuperBoss.remove(location) + if location in self.random_super_boss_list: + self.random_super_boss_list.remove(location) + + if not self.options.SummonLevelLocationToggle: + self.random_super_boss_list.remove(LocationName.Summonlvl7) # Testing if the player has the right amount of Bounties for Completion. - if len(self.RandomSuperBoss) < self.BountiesAmount: + if len(self.random_super_boss_list) < self.bounties_amount: logging.info( f"{self.multiworld.get_file_safe_player_name(self.player)} has more bounties than bosses." - f" Setting total bounties to {len(self.RandomSuperBoss)}") - self.BountiesAmount = len(self.RandomSuperBoss) - self.multiworld.BountyAmount[self.player].value = self.BountiesAmount + f" Setting total bounties to {len(self.random_super_boss_list)}") + self.bounties_amount = len(self.random_super_boss_list) + self.options.BountyAmount.value = self.bounties_amount - if len(self.RandomSuperBoss) < self.BountiesRequired: + if len(self.random_super_boss_list) < self.bounties_required: logging.info(f"{self.multiworld.get_file_safe_player_name(self.player)} has too many required bounties." - f" Setting required bounties to {len(self.RandomSuperBoss)}") - self.BountiesRequired = len(self.RandomSuperBoss) - self.multiworld.BountyRequired[self.player].value = self.BountiesRequired + f" Setting required bounties to {len(self.random_super_boss_list)}") + self.bounties_required = len(self.random_super_boss_list) + self.options.BountyRequired.value = self.bounties_required - if self.BountiesAmount < self.BountiesRequired: - logging.info(f"Bounties Amount {self.multiworld.BountyAmount[self.player].value} is less than required " - f"{self.multiworld.BountyRequired[self.player].value} for player {self.multiworld.get_file_safe_player_name(self.player)}." - f" Setting amount to {self.multiworld.BountyRequired[self.player].value}") - self.BountiesAmount = max(self.BountiesAmount, self.BountiesRequired) - self.multiworld.BountyAmount[self.player].value = self.BountiesAmount + if self.bounties_amount < self.bounties_required: + logging.info( + f"Bounties Amount is less than required for player {self.multiworld.get_file_safe_player_name(self.player)}." + f" Swapping Amount and Required") + temp = self.options.BountyRequired.value + self.options.BountyRequired.value = self.options.BountyAmount.value + self.options.BountyAmount.value = temp - self.multiworld.start_hints[self.player].value.add(ItemName.Bounty) - self.item_quantity_dict[ItemName.ProofofNonexistence] = 0 + if self.options.BountyStartingHintToggle: + self.multiworld.start_hints[self.player].value.add(ItemName.Bounty) + + if ItemName.ProofofNonexistence in self.item_quantity_dict: + del self.item_quantity_dict[ItemName.ProofofNonexistence] def set_excluded_locations(self): + """ + Fills excluded_locations from player's settings. + """ # Option to turn off all superbosses. Can do this individually but its like 20+ checks - if not self.multiworld.SuperBosses[self.player] and not self.multiworld.Goal[self.player] == "hitlist": - for superboss in exclusion_table["Datas"]: - self.multiworld.exclude_locations[self.player].value.add(superboss) + if not self.options.SuperBosses: for superboss in exclusion_table["SuperBosses"]: self.multiworld.exclude_locations[self.player].value.add(superboss) # Option to turn off Olympus Colosseum Cups. - if self.multiworld.Cups[self.player] == "no_cups": + if self.options.Cups == "no_cups": for cup in exclusion_table["Cups"]: self.multiworld.exclude_locations[self.player].value.add(cup) # exclude only hades paradox. If cups and hades paradox then nothing is excluded - elif self.multiworld.Cups[self.player] == "cups": + elif self.options.Cups == "cups": self.multiworld.exclude_locations[self.player].value.add(LocationName.HadesCupTrophyParadoxCups) + if not self.options.AtlanticaToggle: + for loc in exclusion_table["Atlantica"]: + self.multiworld.exclude_locations[self.player].value.add(loc) + def level_subtraction(self): - # there are levels but level 1 is there for the yamls - if self.multiworld.LevelDepth[self.player] == "level_99_sanity": - # level 99 sanity - self.totalLocations -= 1 - elif self.multiworld.LevelDepth[self.player] == "level_50_sanity": + """ + Determine how many locations are on sora's levels. + """ + if self.options.LevelDepth == "level_50_sanity": # level 50 sanity - self.totalLocations -= 50 - elif self.multiworld.LevelDepth[self.player] == "level_1": + return 49 + elif self.options.LevelDepth == "level_1": # level 1. No checks on levels - self.totalLocations -= 99 + return 98 + elif self.options.LevelDepth in ["level_50", "level_99"]: + # could be if leveldepth!= 99 sanity but this reads better imo + return 75 else: - # level 50/99 since they contain the same amount of levels - self.totalLocations -= 76 + return 0 def get_filler_item_name(self) -> str: - return self.multiworld.random.choice( - [ItemName.PowerBoost, ItemName.MagicBoost, ItemName.DefenseBoost, ItemName.APBoost]) + """ + Returns random filler item name. + """ + return self.random.choice(filler_items) diff --git a/worlds/kh2/logic.py b/worlds/kh2/logic.py deleted file mode 100644 index 10af4144a7fb..000000000000 --- a/worlds/kh2/logic.py +++ /dev/null @@ -1,312 +0,0 @@ -from .Names import ItemName -from ..AutoWorld import LogicMixin - - -class KH2Logic(LogicMixin): - def kh_lod_unlocked(self, player, amount): - return self.has(ItemName.SwordoftheAncestor, player, amount) - - def kh_oc_unlocked(self, player, amount): - return self.has(ItemName.BattlefieldsofWar, player, amount) - - def kh_twtnw_unlocked(self, player, amount): - return self.has(ItemName.WaytotheDawn, player, amount) - - def kh_ht_unlocked(self, player, amount): - return self.has(ItemName.BoneFist, player, amount) - - def kh_tt_unlocked(self, player, amount): - return self.has(ItemName.IceCream, player, amount) - - def kh_pr_unlocked(self, player, amount): - return self.has(ItemName.SkillandCrossbones, player, amount) - - def kh_sp_unlocked(self, player, amount): - return self.has(ItemName.IdentityDisk, player, amount) - - def kh_stt_unlocked(self, player: int, amount): - return self.has(ItemName.NamineSketches, player, amount) - - # Using Dummy 13 for this - def kh_dc_unlocked(self, player: int, amount): - return self.has(ItemName.CastleKey, player, amount) - - def kh_hb_unlocked(self, player, amount): - return self.has(ItemName.MembershipCard, player, amount) - - def kh_pl_unlocked(self, player, amount): - return self.has(ItemName.ProudFang, player, amount) - - def kh_ag_unlocked(self, player, amount): - return self.has(ItemName.Scimitar, player, amount) - - def kh_bc_unlocked(self, player, amount): - return self.has(ItemName.BeastsClaw, player, amount) - - def kh_amount_of_forms(self, player, amount, requiredform="None"): - level = 0 - formList = [ItemName.ValorForm, ItemName.WisdomForm, ItemName.LimitForm, ItemName.MasterForm, - ItemName.FinalForm] - # required form is in the logic for region connections - if requiredform != "None": - formList.remove(requiredform) - for form in formList: - if self.has(form, player): - level += 1 - return level >= amount - - def kh_visit_locking_amount(self, player, amount): - visit = 0 - # torn pages are not added since you cannot get exp from that world - for item in {ItemName.CastleKey, ItemName.BattlefieldsofWar, ItemName.SwordoftheAncestor, ItemName.BeastsClaw, - ItemName.BoneFist, ItemName.ProudFang, ItemName.SkillandCrossbones, ItemName.Scimitar, - ItemName.MembershipCard, - ItemName.IceCream, ItemName.WaytotheDawn, - ItemName.IdentityDisk, ItemName.NamineSketches}: - visit += self.count(item, player) - return visit >= amount - - def kh_three_proof_unlocked(self, player): - return self.has(ItemName.ProofofConnection, player, 1) \ - and self.has(ItemName.ProofofNonexistence, player, 1) \ - and self.has(ItemName.ProofofPeace, player, 1) - - def kh_hitlist(self, player, amount): - return self.has(ItemName.Bounty, player, amount) - - def kh_lucky_emblem_unlocked(self, player, amount): - return self.has(ItemName.LuckyEmblem, player, amount) - - def kh_victory(self, player): - return self.has(ItemName.Victory, player, 1) - - def kh_summon(self, player, amount): - summonlevel = 0 - for summon in {ItemName.Genie, ItemName.ChickenLittle, ItemName.Stitch, ItemName.PeterPan}: - if self.has(summon, player): - summonlevel += 1 - return summonlevel >= amount - - # magic progression - def kh_fire(self, player): - return self.has(ItemName.FireElement, player, 1) - - def kh_fira(self, player): - return self.has(ItemName.FireElement, player, 2) - - def kh_firaga(self, player): - return self.has(ItemName.FireElement, player, 3) - - def kh_blizzard(self, player): - return self.has(ItemName.BlizzardElement, player, 1) - - def kh_blizzara(self, player): - return self.has(ItemName.BlizzardElement, player, 2) - - def kh_blizzaga(self, player): - return self.has(ItemName.BlizzardElement, player, 3) - - def kh_thunder(self, player): - return self.has(ItemName.ThunderElement, player, 1) - - def kh_thundara(self, player): - return self.has(ItemName.ThunderElement, player, 2) - - def kh_thundaga(self, player): - return self.has(ItemName.ThunderElement, player, 3) - - def kh_magnet(self, player): - return self.has(ItemName.MagnetElement, player, 1) - - def kh_magnera(self, player): - return self.has(ItemName.MagnetElement, player, 2) - - def kh_magnega(self, player): - return self.has(ItemName.MagnetElement, player, 3) - - def kh_reflect(self, player): - return self.has(ItemName.ReflectElement, player, 1) - - def kh_reflera(self, player): - return self.has(ItemName.ReflectElement, player, 2) - - def kh_reflega(self, player): - return self.has(ItemName.ReflectElement, player, 3) - - def kh_highjump(self, player, amount): - return self.has(ItemName.HighJump, player, amount) - - def kh_quickrun(self, player, amount): - return self.has(ItemName.QuickRun, player, amount) - - def kh_dodgeroll(self, player, amount): - return self.has(ItemName.DodgeRoll, player, amount) - - def kh_aerialdodge(self, player, amount): - return self.has(ItemName.AerialDodge, player, amount) - - def kh_glide(self, player, amount): - return self.has(ItemName.Glide, player, amount) - - def kh_comboplus(self, player, amount): - return self.has(ItemName.ComboPlus, player, amount) - - def kh_aircomboplus(self, player, amount): - return self.has(ItemName.AirComboPlus, player, amount) - - def kh_valorgenie(self, player): - return self.has(ItemName.Genie, player) and self.has(ItemName.ValorForm, player) - - def kh_wisdomgenie(self, player): - return self.has(ItemName.Genie, player) and self.has(ItemName.WisdomForm, player) - - def kh_mastergenie(self, player): - return self.has(ItemName.Genie, player) and self.has(ItemName.MasterForm, player) - - def kh_finalgenie(self, player): - return self.has(ItemName.Genie, player) and self.has(ItemName.FinalForm, player) - - def kh_rsr(self, player): - return self.has(ItemName.Slapshot, player, 1) and self.has(ItemName.ComboMaster, player) and self.kh_reflect( - player) - - def kh_gapcloser(self, player): - return self.has(ItemName.FlashStep, player, 1) or self.has(ItemName.SlideDash, player) - - # Crowd Control and Berserk Hori will be used when I add hard logic. - - def kh_crowdcontrol(self, player): - return self.kh_magnera(player) and self.has(ItemName.ChickenLittle, player) \ - or self.kh_magnega(player) and self.kh_mastergenie(player) - - def kh_berserkhori(self, player): - return self.has(ItemName.HorizontalSlash, player, 1) and self.has(ItemName.BerserkCharge, player) - - def kh_donaldlimit(self, player): - return self.has(ItemName.FlareForce, player, 1) or self.has(ItemName.Fantasia, player) - - def kh_goofylimit(self, player): - return self.has(ItemName.TornadoFusion, player, 1) or self.has(ItemName.Teamwork, player) - - def kh_basetools(self, player): - # TODO: if option is easy then add reflect,gap closer and second chance&once more. #option east scom option normal adds gap closer or combo master #hard is what is right now - return self.has(ItemName.Guard, player, 1) and self.has(ItemName.AerialRecovery, player, 1) \ - and self.has(ItemName.FinishingPlus, player, 1) - - def kh_roxastools(self, player): - return self.kh_basetools(player) and ( - self.has(ItemName.QuickRun, player) or self.has(ItemName.NegativeCombo, player, 2)) - - def kh_painandpanic(self, player): - return (self.kh_goofylimit(player) or self.kh_donaldlimit(player)) and self.kh_dc_unlocked(player, 2) - - def kh_cerberuscup(self, player): - return self.kh_amount_of_forms(player, 2) and self.kh_thundara(player) \ - and self.kh_ag_unlocked(player, 1) and self.kh_ht_unlocked(player, 1) \ - and self.kh_pl_unlocked(player, 1) - - def kh_titan(self, player: int): - return self.kh_summon(player, 2) and (self.kh_thundara(player) or self.kh_magnera(player)) \ - and self.kh_oc_unlocked(player, 2) - - def kh_gof(self, player): - return self.kh_titan(player) and self.kh_cerberuscup(player) \ - and self.kh_painandpanic(player) and self.kh_twtnw_unlocked(player, 1) - - def kh_dataroxas(self, player): - return self.kh_basetools(player) and \ - ((self.has(ItemName.LimitForm, player) and self.kh_amount_of_forms(player, 3) and self.has( - ItemName.TrinityLimit, player) and self.kh_gapcloser(player)) - or (self.has(ItemName.NegativeCombo, player, 2) or self.kh_quickrun(player, 2))) - - def kh_datamarluxia(self, player): - return self.kh_basetools(player) and self.kh_reflera(player) \ - and ((self.kh_amount_of_forms(player, 3) and self.has(ItemName.FinalForm, player) and self.kh_fira( - player)) or self.has(ItemName.NegativeCombo, player, 2) or self.kh_donaldlimit(player)) - - def kh_datademyx(self, player): - return self.kh_basetools(player) and self.kh_amount_of_forms(player, 5) and self.kh_firaga(player) \ - and (self.kh_donaldlimit(player) or self.kh_blizzard(player)) - - def kh_datalexaeus(self, player): - return self.kh_basetools(player) and self.kh_amount_of_forms(player, 3) and self.kh_reflera(player) \ - and (self.has(ItemName.NegativeCombo, player, 2) or self.kh_donaldlimit(player)) - - def kh_datasaix(self, player): - return self.kh_basetools(player) and (self.kh_thunder(player) or self.kh_blizzard(player)) \ - and self.kh_highjump(player, 2) and self.kh_aerialdodge(player, 2) and self.kh_glide(player, 2) and self.kh_amount_of_forms(player, 3) \ - and (self.kh_rsr(player) or self.has(ItemName.NegativeCombo, player, 2) or self.has(ItemName.PeterPan, - player)) - - def kh_dataxaldin(self, player): - return self.kh_basetools(player) and self.kh_donaldlimit(player) and self.kh_goofylimit(player) \ - and self.kh_highjump(player, 2) and self.kh_aerialdodge(player, 2) and self.kh_glide(player, - 2) and self.kh_magnet( - player) - # and (self.kh_form_level_unlocked(player, 3) or self.kh_berserkhori(player)) - - def kh_dataxemnas(self, player): - return self.kh_basetools(player) and self.kh_rsr(player) and self.kh_gapcloser(player) \ - and (self.has(ItemName.LimitForm, player) or self.has(ItemName.TrinityLimit, player)) - - def kh_dataxigbar(self, player): - return self.kh_basetools(player) and self.kh_donaldlimit(player) and self.has(ItemName.FinalForm, player) \ - and self.kh_amount_of_forms(player, 3) and self.kh_reflera(player) - - def kh_datavexen(self, player): - return self.kh_basetools(player) and self.kh_donaldlimit(player) and self.has(ItemName.FinalForm, player) \ - and self.kh_amount_of_forms(player, 4) and self.kh_reflera(player) and self.kh_fira(player) - - def kh_datazexion(self, player): - return self.kh_basetools(player) and self.kh_donaldlimit(player) and self.has(ItemName.FinalForm, player) \ - and self.kh_amount_of_forms(player, 3) \ - and self.kh_reflera(player) and self.kh_fira(player) - - def kh_dataaxel(self, player): - return self.kh_basetools(player) \ - and ((self.kh_reflera(player) and self.kh_blizzara(player)) or self.has(ItemName.NegativeCombo, player, 2)) - - def kh_dataluxord(self, player): - return self.kh_basetools(player) and self.kh_reflect(player) - - def kh_datalarxene(self, player): - return self.kh_basetools(player) and self.kh_reflera(player) \ - and ((self.has(ItemName.FinalForm, player) and self.kh_amount_of_forms(player, 4) and self.kh_fire( - player)) - or (self.kh_donaldlimit(player) and self.kh_amount_of_forms(player, 2))) - - def kh_sephi(self, player): - return self.kh_dataxemnas(player) - - def kh_onek(self, player): - return self.kh_reflect(player) or self.has(ItemName.Guard, player) - - def kh_terra(self, player): - return self.has(ItemName.ProofofConnection, player) and self.kh_basetools(player) \ - and self.kh_dodgeroll(player, 2) and self.kh_aerialdodge(player, 2) and self.kh_glide(player, 3) \ - and ((self.kh_comboplus(player, 2) and self.has(ItemName.Explosion, player)) or self.has( - ItemName.NegativeCombo, player, 2)) - - def kh_cor(self, player): - return self.kh_reflect(player) \ - and self.kh_highjump(player, 2) and self.kh_quickrun(player, 2) and self.kh_aerialdodge(player, 2) \ - and (self.has(ItemName.MasterForm, player) and self.kh_fire(player) - or (self.has(ItemName.ChickenLittle, player) and self.kh_donaldlimit(player) and self.kh_glide(player, - 2))) - - def kh_transport(self, player): - return self.kh_basetools(player) and self.kh_reflera(player) \ - and ((self.kh_mastergenie(player) and self.kh_magnera(player) and self.kh_donaldlimit(player)) - or (self.has(ItemName.FinalForm, player) and self.kh_amount_of_forms(player, 4) and self.kh_fira( - player))) - - def kh_gr2(self, player): - return (self.has(ItemName.MasterForm, player) or self.has(ItemName.Stitch, player)) \ - and (self.kh_fire(player) or self.kh_blizzard(player) or self.kh_thunder(player)) - - def kh_xaldin(self, player): - return self.kh_basetools(player) and (self.kh_donaldlimit(player) or self.kh_amount_of_forms(player, 1)) - - def kh_mcp(self, player): - return self.kh_reflect(player) and ( - self.has(ItemName.MasterForm, player) or self.has(ItemName.FinalForm, player)) diff --git a/worlds/kh2/mod_template/mod.yml b/worlds/kh2/mod_template/mod.yml deleted file mode 100644 index 4246132c2641..000000000000 --- a/worlds/kh2/mod_template/mod.yml +++ /dev/null @@ -1,38 +0,0 @@ -assets: -- method: binarc - name: 00battle.bin - source: - - method: listpatch - name: fmlv - source: - - name: FmlvList.yml - type: fmlv - type: List - - method: listpatch - name: lvup - source: - - name: LvupList.yml - type: lvup - type: List - - method: listpatch - name: bons - source: - - name: BonsList.yml - type: bons - type: List -- method: binarc - name: 03system.bin - source: - - method: listpatch - name: trsr - source: - - name: TrsrList.yml - type: trsr - type: List - - method: listpatch - name: item - source: - - name: ItemList.yml - type: item - type: List -title: Randomizer Seed diff --git a/worlds/kh2/test/TestGoal.py b/worlds/kh2/test/TestGoal.py deleted file mode 100644 index 97874da2d090..000000000000 --- a/worlds/kh2/test/TestGoal.py +++ /dev/null @@ -1,30 +0,0 @@ -from . import KH2TestBase -from ..Names import ItemName - - -class TestDefault(KH2TestBase): - options = {} - - def testEverything(self): - self.collect_all_but([ItemName.Victory]) - self.assertBeatable(True) - - -class TestLuckyEmblem(KH2TestBase): - options = { - "Goal": 1, - } - - def testEverything(self): - self.collect_all_but([ItemName.LuckyEmblem]) - self.assertBeatable(True) - - -class TestHitList(KH2TestBase): - options = { - "Goal": 2, - } - - def testEverything(self): - self.collect_all_but([ItemName.Bounty]) - self.assertBeatable(True) diff --git a/worlds/kh2/test/TestSlotData.py b/worlds/kh2/test/TestSlotData.py deleted file mode 100644 index 656cd48d5a6f..000000000000 --- a/worlds/kh2/test/TestSlotData.py +++ /dev/null @@ -1,21 +0,0 @@ -import unittest - -from test.general import setup_solo_multiworld -from . import KH2TestBase -from .. import KH2World, all_locations, item_dictionary_table, CheckDupingItems, AllWeaponSlot, KH2Item -from ..Names import ItemName -from ... import AutoWorldRegister -from ...AutoWorld import call_all - - -class TestLocalItems(KH2TestBase): - - def testSlotData(self): - gen_steps = ("generate_early", "create_regions", "create_items", "set_rules", "generate_basic", "pre_fill") - multiworld = setup_solo_multiworld(KH2World, gen_steps) - for location in multiworld.get_locations(): - if location.item is None: - location.place_locked_item(multiworld.worlds[1].create_item(ItemName.NoExperience)) - call_all(multiworld, "fill_slot_data") - slotdata = multiworld.worlds[1].fill_slot_data() - assert len(slotdata["LocalItems"]) > 0, f"{slotdata['LocalItems']} is empty" diff --git a/worlds/kh2/test/__init__.py b/worlds/kh2/test/__init__.py index dfef22762745..6cefe6e79197 100644 --- a/worlds/kh2/test/__init__.py +++ b/worlds/kh2/test/__init__.py @@ -1,4 +1,4 @@ -from test.TestBase import WorldTestBase +from test.bases import WorldTestBase class KH2TestBase(WorldTestBase): diff --git a/worlds/kh2/test/test_fight_logic.py b/worlds/kh2/test/test_fight_logic.py new file mode 100644 index 000000000000..0c47d132f0a0 --- /dev/null +++ b/worlds/kh2/test/test_fight_logic.py @@ -0,0 +1,19 @@ +from . import KH2TestBase + + +class TestEasy(KH2TestBase): + options = { + "FightLogic": 0 + } + + +class TestNormal(KH2TestBase): + options = { + "FightLogic": 1 + } + + +class TestHard(KH2TestBase): + options = { + "FightLogic": 2 + } diff --git a/worlds/kh2/test/test_form_logic.py b/worlds/kh2/test/test_form_logic.py new file mode 100644 index 000000000000..1cd850a985dd --- /dev/null +++ b/worlds/kh2/test/test_form_logic.py @@ -0,0 +1,214 @@ +from . import KH2TestBase +from ..Names import ItemName, LocationName + +global_all_possible_forms = [ItemName.ValorForm, ItemName.WisdomForm, ItemName.LimitForm, ItemName.MasterForm, ItemName.FinalForm] + [ItemName.AutoValor, ItemName.AutoWisdom, ItemName.AutoLimit, ItemName.AutoMaster, ItemName.AutoFinal] + + +class KH2TestFormBase(KH2TestBase): + allForms = [ItemName.ValorForm, ItemName.WisdomForm, ItemName.LimitForm, ItemName.MasterForm, ItemName.FinalForm] + autoForms = [ItemName.AutoValor, ItemName.AutoWisdom, ItemName.AutoLimit, ItemName.AutoMaster, ItemName.AutoFinal] + allLevel2 = [LocationName.Valorlvl2, LocationName.Wisdomlvl2, LocationName.Limitlvl2, LocationName.Masterlvl2, + LocationName.Finallvl2] + allLevel3 = [LocationName.Valorlvl3, LocationName.Wisdomlvl3, LocationName.Limitlvl3, LocationName.Masterlvl3, + LocationName.Finallvl3] + allLevel4 = [LocationName.Valorlvl4, LocationName.Wisdomlvl4, LocationName.Limitlvl4, LocationName.Masterlvl4, + LocationName.Finallvl4] + allLevel5 = [LocationName.Valorlvl5, LocationName.Wisdomlvl5, LocationName.Limitlvl5, LocationName.Masterlvl5, + LocationName.Finallvl5] + allLevel6 = [LocationName.Valorlvl6, LocationName.Wisdomlvl6, LocationName.Limitlvl6, LocationName.Masterlvl6, + LocationName.Finallvl6] + allLevel7 = [LocationName.Valorlvl7, LocationName.Wisdomlvl7, LocationName.Limitlvl7, LocationName.Masterlvl7, + LocationName.Finallvl7] + driveToAuto = { + ItemName.FinalForm: ItemName.AutoFinal, + ItemName.MasterForm: ItemName.AutoMaster, + ItemName.LimitForm: ItemName.AutoLimit, + ItemName.WisdomForm: ItemName.AutoWisdom, + ItemName.ValorForm: ItemName.AutoValor, + } + AutoToDrive = {Auto: Drive for Drive, Auto in driveToAuto.items()} + driveFormMap = { + ItemName.ValorForm: [LocationName.Valorlvl2, + LocationName.Valorlvl3, + LocationName.Valorlvl4, + LocationName.Valorlvl5, + LocationName.Valorlvl6, + LocationName.Valorlvl7], + ItemName.WisdomForm: [LocationName.Wisdomlvl2, + LocationName.Wisdomlvl3, + LocationName.Wisdomlvl4, + LocationName.Wisdomlvl5, + LocationName.Wisdomlvl6, + LocationName.Wisdomlvl7], + ItemName.LimitForm: [LocationName.Limitlvl2, + LocationName.Limitlvl3, + LocationName.Limitlvl4, + LocationName.Limitlvl5, + LocationName.Limitlvl6, + LocationName.Limitlvl7], + ItemName.MasterForm: [LocationName.Masterlvl2, + LocationName.Masterlvl3, + LocationName.Masterlvl4, + LocationName.Masterlvl5, + LocationName.Masterlvl6, + LocationName.Masterlvl7], + ItemName.FinalForm: [LocationName.Finallvl2, + LocationName.Finallvl3, + LocationName.Finallvl4, + LocationName.Finallvl5, + LocationName.Finallvl6, + LocationName.Finallvl7], + } + # global_all_possible_forms = allForms + autoForms + + +class TestDefaultForms(KH2TestFormBase): + """ + Test default form access rules. + """ + options = { + "AutoFormLogic": False, + "FinalFormLogic": "light_and_darkness" + } + + def test_default_Auto_Form_Logic(self): + allPossibleForms = global_all_possible_forms + # this tests with a light and darkness in the inventory. + self.collect_all_but(allPossibleForms) + for form in self.allForms: + self.assertFalse((self.can_reach_location(self.driveFormMap[form][0])), form) + self.collect(self.get_item_by_name(self.driveToAuto[form])) + self.assertFalse((self.can_reach_location(self.driveFormMap[form][0])), form) + + def test_default_Final_Form(self): + allPossibleForms = global_all_possible_forms + self.collect_all_but(allPossibleForms) + self.collect_by_name(ItemName.FinalForm) + self.assertTrue((self.can_reach_location(LocationName.Finallvl2))) + self.assertTrue((self.can_reach_location(LocationName.Finallvl3))) + self.assertFalse((self.can_reach_location(LocationName.Finallvl4))) + + def test_default_without_LnD(self): + allPossibleForms = self.allForms + self.collect_all_but(allPossibleForms) + for form, levels in self.driveFormMap.items(): + # final form is unique and breaks using this test. Tested above. + if levels[0] == LocationName.Finallvl2: + continue + for driveForm in self.allForms: + if self.count(driveForm) >= 1: + for _ in range(self.count(driveForm)): + self.remove(self.get_item_by_name(driveForm)) + allFormsCopy = self.allForms.copy() + allFormsCopy.remove(form) + self.collect(self.get_item_by_name(form)) + for _ in range(self.count(ItemName.LightDarkness)): + self.remove(self.get_item_by_name(ItemName.LightDarkness)) + self.assertTrue((self.can_reach_location(levels[0])), levels[0]) + self.assertTrue((self.can_reach_location(levels[1])), levels[1]) + self.assertFalse((self.can_reach_location(levels[2])), levels[2]) + for i in range(3): + self.collect(self.get_item_by_name(allFormsCopy[i])) + # for some reason after collecting a form it can pick up light and darkness + for _ in range(self.count(ItemName.LightDarkness)): + self.remove(self.get_item_by_name(ItemName.LightDarkness)) + + self.assertTrue((self.can_reach_location(levels[2 + i]))) + if i < 2: + self.assertFalse((self.can_reach_location(levels[3 + i]))) + else: + self.collect(self.get_item_by_name(allFormsCopy[i + 1])) + for _ in range(self.count(ItemName.LightDarkness)): + self.remove(self.get_item_by_name(ItemName.LightDarkness)) + self.assertTrue((self.can_reach_location(levels[3 + i]))) + + def test_default_with_lnd(self): + allPossibleForms = self.allForms + self.collect_all_but(allPossibleForms) + for form, levels in self.driveFormMap.items(): + if form != ItemName.FinalForm: + for driveForm in self.allForms: + for _ in range(self.count(driveForm)): + self.remove(self.get_item_by_name(driveForm)) + allFormsCopy = self.allForms.copy() + allFormsCopy.remove(form) + self.collect(self.get_item_by_name(ItemName.LightDarkness)) + self.assertFalse((self.can_reach_location(levels[0]))) + self.collect(self.get_item_by_name(form)) + + self.assertTrue((self.can_reach_location(levels[0]))) + self.assertTrue((self.can_reach_location(levels[1]))) + self.assertTrue((self.can_reach_location(levels[2]))) + self.assertFalse((self.can_reach_location(levels[3]))) + for i in range(2): + self.collect(self.get_item_by_name(allFormsCopy[i])) + self.assertTrue((self.can_reach_location(levels[i + 3]))) + if i <= 2: + self.assertFalse((self.can_reach_location(levels[i + 4]))) + + +class TestJustAForm(KH2TestFormBase): + # this test checks if you can unlock final form with just a form. + options = { + "AutoFormLogic": False, + "FinalFormLogic": "just_a_form" + } + + def test_just_a_form_connections(self): + allPossibleForms = self.allForms + self.collect_all_but(allPossibleForms) + allPossibleForms.remove(ItemName.FinalForm) + for form, levels in self.driveFormMap.items(): + for driveForm in self.allForms: + for _ in range(self.count(driveForm)): + self.remove(self.get_item_by_name(driveForm)) + if form != ItemName.FinalForm: + # reset the forms + allFormsCopy = self.allForms.copy() + allFormsCopy.remove(form) + self.assertFalse((self.can_reach_location(levels[0]))) + self.collect(self.get_item_by_name(form)) + self.assertTrue((self.can_reach_location(levels[0]))) + self.assertTrue((self.can_reach_location(levels[1]))) + self.assertTrue((self.can_reach_location(levels[2]))) + + # level 4 of a form. This tests if the player can unlock final form. + self.assertFalse((self.can_reach_location(levels[3]))) + # amount of forms left in the pool are 3. 1 already collected and one is final form. + for i in range(3): + allFormsCopy.remove(allFormsCopy[0]) + # so we don't accidentally collect another form like light and darkness in the above tests. + self.collect_all_but(allFormsCopy) + self.assertTrue((self.can_reach_location(levels[3 + i])), levels[3 + i]) + if i < 2: + self.assertFalse((self.can_reach_location(levels[4 + i])), levels[4 + i]) + + +class TestAutoForms(KH2TestFormBase): + options = { + "AutoFormLogic": True, + "FinalFormLogic": "light_and_darkness" + } + + def test_Nothing(self): + KH2TestBase() + + def test_auto_forms_level_progression(self): + allPossibleForms = self.allForms + [ItemName.LightDarkness] + # state has all auto forms + self.collect_all_but(allPossibleForms) + allPossibleFormsCopy = allPossibleForms.copy() + collectedDrives = [] + i = 0 + for form in allPossibleForms: + currentDriveForm = form + collectedDrives += [currentDriveForm] + allPossibleFormsCopy.remove(currentDriveForm) + self.collect_all_but(allPossibleFormsCopy) + for driveForm in self.allForms: + # +1 every iteration. + self.assertTrue((self.can_reach_location(self.driveFormMap[driveForm][i])), driveForm) + # making sure having the form still gives an extra drive level to its own form. + if driveForm in collectedDrives and i < 5: + self.assertTrue((self.can_reach_location(self.driveFormMap[driveForm][i + 1])), driveForm) + i += 1 diff --git a/worlds/kh2/test/test_goal.py b/worlds/kh2/test/test_goal.py new file mode 100644 index 000000000000..1a481ad3d91f --- /dev/null +++ b/worlds/kh2/test/test_goal.py @@ -0,0 +1,59 @@ +from . import KH2TestBase +from ..Names import ItemName + + +class TestDefault(KH2TestBase): + options = {} + + +class TestThreeProofs(KH2TestBase): + options = { + "Goal": 0, + } + + +class TestLuckyEmblem(KH2TestBase): + options = { + "Goal": 1, + } + + +class TestHitList(KH2TestBase): + options = { + "Goal": 2, + } + + +class TestLuckyEmblemHitlist(KH2TestBase): + options = { + "Goal": 3, + } + + +class TestThreeProofsNoXemnas(KH2TestBase): + options = { + "Goal": 0, + "FinalXemnas": False, + } + + +class TestLuckyEmblemNoXemnas(KH2TestBase): + options = { + "Goal": 1, + "FinalXemnas": False, + } + + +class TestHitListNoXemnas(KH2TestBase): + options = { + "Goal": 2, + "FinalXemnas": False, + } + + +class TestLuckyEmblemHitlistNoXemnas(KH2TestBase): + options = { + "Goal": 3, + "FinalXemnas": False, + } +