Kh2 rc2 fixes (#1608)

This commit is contained in:
JaredWeakStrike 2023-03-27 13:17:06 -04:00 committed by GitHub
parent 21c6c28755
commit e62f989ce8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 121 additions and 75 deletions

View File

@ -119,7 +119,12 @@ class KH2Context(CommonContext):
"LimitLevel": 0, "LimitLevel": 0,
"MasterLevel": 0, "MasterLevel": 0,
"FinalLevel": 0, "FinalLevel": 0,
} },
"SoldEquipment": [],
"SoldBoosts": {"Power Boost": 0,
"Magic Boost": 0,
"Defense Boost": 0,
"AP Boost": 0}
} }
self.slotDataProgressionNames = {} self.slotDataProgressionNames = {}
self.kh2seedname = None self.kh2seedname = None
@ -137,23 +142,23 @@ class KH2Context(CommonContext):
self.finalxemnas = False self.finalxemnas = False
self.worldid = { self.worldid = {
# 1: {}, # world of darkness (story cutscenes) # 1: {}, # world of darkness (story cutscenes)
2: TT_Checks, 2: TT_Checks,
# 3: {}, # destiny island doesn't have checks to ima put tt checks here # 3: {}, # destiny island doesn't have checks to ima put tt checks here
4: HB_Checks, 4: HB_Checks,
5: BC_Checks, 5: BC_Checks,
6: Oc_Checks, 6: Oc_Checks,
7: AG_Checks, 7: AG_Checks,
8: LoD_Checks, 8: LoD_Checks,
9: HundredAcreChecks, 9: HundredAcreChecks,
10: PL_Checks, 10: PL_Checks,
11: DC_Checks, # atlantica isn't a supported world. if you go in atlantica it will check dc 11: DC_Checks, # atlantica isn't a supported world. if you go in atlantica it will check dc
12: DC_Checks, 12: DC_Checks,
13: TR_Checks, 13: TR_Checks,
14: HT_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 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, 16: PR_Checks,
17: SP_Checks, 17: SP_Checks,
18: TWTNW_Checks, 18: TWTNW_Checks,
# 255: {}, # starting screen # 255: {}, # starting screen
} }
# 0x2A09C00+0x40 is the sve anchor. +1 is the last saved room # 0x2A09C00+0x40 is the sve anchor. +1 is the last saved room
@ -412,7 +417,7 @@ class KH2Context(CommonContext):
logger.info(e) logger.info(e)
async def verifyLevel(self): async def verifyLevel(self):
for leveltype, anchor in {"SoraLevel": 0x24FF, for leveltype, anchor in {"SoraLevel": 0x24FF,
"ValorLevel": 0x32F6, "ValorLevel": 0x32F6,
"WisdomLevel": 0x332E, "WisdomLevel": 0x332E,
"LimitLevel": 0x3366, "LimitLevel": 0x3366,
@ -536,6 +541,34 @@ class KH2Context(CommonContext):
self.ui = KH2Manager(self) self.ui = KH2Manager(self)
self.ui_task = asyncio.create_task(self.ui.async_run(), name="UI") 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): async def verifyItems(self):
try: try:
local_amount = set(self.kh2seedsave["AmountInvo"]["LocalItems"]["Amount"].keys()) local_amount = set(self.kh2seedsave["AmountInvo"]["LocalItems"]["Amount"].keys())
@ -578,6 +611,8 @@ class KH2Context(CommonContext):
server_boost = set(self.kh2seedsave["AmountInvo"]["ServerItems"]["Boost"].keys()) server_boost = set(self.kh2seedsave["AmountInvo"]["ServerItems"]["Boost"].keys())
master_boost = local_boost | server_boost 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: for itemName in master_amount:
itemData = self.item_name_to_data[itemName] itemData = self.item_name_to_data[itemName]
amountOfItems = 0 amountOfItems = 0
@ -603,7 +638,8 @@ class KH2Context(CommonContext):
itemData = self.item_name_to_data[itemName] itemData = self.item_name_to_data[itemName]
# if the inventory slot for that keyblade is less than the amount they should have # 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), if int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + self.Save + itemData.memaddr, 1),
"big") <= 0: "big") != 1 and int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + 0x1CFF, 1),
"big") != 13:
# Checking form anchors for the keyblade # Checking form anchors for the keyblade
if self.kh2.read_short(self.kh2.base_address + self.Save + 0x24F0) == itemData.kh2id \ 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 + 0x32F4) == itemData.kh2id \
@ -618,7 +654,8 @@ class KH2Context(CommonContext):
itemData = self.item_name_to_data[itemName] itemData = self.item_name_to_data[itemName]
if int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + self.Save + itemData.memaddr, 1), if int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + self.Save + itemData.memaddr, 1),
"big") != 1 \ "big") != 1 \
and self.kh2.read_short(self.kh2.base_address + self.Save + 0x2604) != itemData.kh2id: 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, self.kh2.write_bytes(self.kh2.base_address + self.Save + itemData.memaddr,
(1).to_bytes(1, 'big'), 1) (1).to_bytes(1, 'big'), 1)
@ -626,7 +663,8 @@ class KH2Context(CommonContext):
itemData = self.item_name_to_data[itemName] itemData = self.item_name_to_data[itemName]
if int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + self.Save + itemData.memaddr, 1), if int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + self.Save + itemData.memaddr, 1),
"big") != 1 \ "big") != 1 \
and self.kh2.read_short(self.kh2.base_address + self.Save + 0x2718) != itemData.kh2id: 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, self.kh2.write_bytes(self.kh2.base_address + self.Save + itemData.memaddr,
(1).to_bytes(1, 'big'), 1) (1).to_bytes(1, 'big'), 1)
@ -679,16 +717,18 @@ class KH2Context(CommonContext):
Equipment_Anchor_List = self.Equipment_Anchor_Dict["Accessories"] Equipment_Anchor_List = self.Equipment_Anchor_Dict["Accessories"]
else: else:
Equipment_Anchor_List = self.Equipment_Anchor_Dict["Armor"] Equipment_Anchor_List = self.Equipment_Anchor_Dict["Armor"]
if int.from_bytes(self.kh2.read_bytes(self.kh2.base_address + self.Save + itemData.memaddr, 1),
"big") != 1:
# Checking form anchors for the equipment # Checking form anchors for the equipment
for slot in Equipment_Anchor_List: for slot in Equipment_Anchor_List:
if self.kh2.read_short(self.kh2.base_address + self.Save + slot) == itemData.kh2id: if self.kh2.read_short(self.kh2.base_address + self.Save + slot) == itemData.kh2id:
isThere = True 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, self.kh2.write_bytes(self.kh2.base_address + self.Save + itemData.memaddr,
(0).to_bytes(1, 'big'), 1) (0).to_bytes(1, 'big'), 1)
break break
if not isThere: 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, self.kh2.write_bytes(self.kh2.base_address + self.Save + itemData.memaddr,
(1).to_bytes(1, 'big'), 1) (1).to_bytes(1, 'big'), 1)
@ -736,7 +776,8 @@ class KH2Context(CommonContext):
# Ap Boots start at +50 for some reason # Ap Boots start at +50 for some reason
if itemName == "AP Boost": if itemName == "AP Boost":
amountOfUsedBoosts -= 50 amountOfUsedBoosts -= 50
if (amountOfBoostsInInvo + amountOfUsedBoosts) <= amountOfItems and amountOfBoostsInInvo < 255: 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, self.kh2.write_bytes(self.kh2.base_address + self.Save + itemData.memaddr,
(amountOfBoostsInInvo + 1).to_bytes(1, 'big'), 1) (amountOfBoostsInInvo + 1).to_bytes(1, 'big'), 1)
@ -821,9 +862,9 @@ async def kh2_watcher(ctx: KH2Context):
currentWorld = int.from_bytes(ctx.kh2.read_bytes(ctx.kh2.base_address + 0x0714DB8, 1), "big") currentWorld = int.from_bytes(ctx.kh2.read_bytes(ctx.kh2.base_address + 0x0714DB8, 1), "big")
if location not in ctx.kh2seedsave["worldIdChecks"][str(currentWorld)]: if location not in ctx.kh2seedsave["worldIdChecks"][str(currentWorld)]:
ctx.kh2seedsave["worldIdChecks"][str(currentWorld)].append(location) ctx.kh2seedsave["worldIdChecks"][str(currentWorld)].append(location)
if location in ctx.kh2LocalItems: if location in ctx.kh2LocalItems:
item = ctx.kh2slotdata["LocalItems"][str(location)] item = ctx.kh2slotdata["LocalItems"][str(location)]
await asyncio.create_task(ctx.give_item(item, "LocalItems")) await asyncio.create_task(ctx.give_item(item, "LocalItems"))
await ctx.send_msgs(message) await ctx.send_msgs(message)
elif not ctx.kh2connected and ctx.serverconneced: elif not ctx.kh2connected and ctx.serverconneced:
logger.info("Game is not open. Disconnecting from Server.") logger.info("Game is not open. Disconnecting from Server.")

View File

@ -856,31 +856,19 @@ Progression_Dicts = {
ItemName.NamineSketches ItemName.NamineSketches
}, },
"AllVisitLocking": { "AllVisitLocking": {
ItemName.CastleKey, ItemName.CastleKey: 2,
ItemName.CastleKey, ItemName.BattlefieldsofWar: 2,
ItemName.BattlefieldsofWar, ItemName.SwordoftheAncestor: 2,
ItemName.BattlefieldsofWar, ItemName.BeastsClaw: 2,
ItemName.SwordoftheAncestor, ItemName.BoneFist: 2,
ItemName.SwordoftheAncestor, ItemName.ProudFang: 2,
ItemName.BeastsClaw, ItemName.SkillandCrossbones: 2,
ItemName.BeastsClaw, ItemName.Scimitar: 2,
ItemName.BoneFist, ItemName.MembershipCard: 2,
ItemName.BoneFist, ItemName.WaytotheDawn: 1,
ItemName.ProudFang, ItemName.IdentityDisk: 2,
ItemName.ProudFang, ItemName.IceCream: 3,
ItemName.SkillandCrossbones, ItemName.NamineSketches: 1,
ItemName.SkillandCrossbones,
ItemName.Scimitar,
ItemName.Scimitar,
ItemName.MembershipCard,
ItemName.MembershipCard,
ItemName.WaytotheDawn,
ItemName.IdentityDisk,
ItemName.IdentityDisk,
ItemName.IceCream,
ItemName.IceCream,
ItemName.IceCream,
ItemName.NamineSketches,
} }
} }

View File

@ -1483,7 +1483,6 @@ exclusion_table = {
LocationName.OasisMap, LocationName.OasisMap,
LocationName.OasisTornPages, LocationName.OasisTornPages,
LocationName.OasisAPBoost, LocationName.OasisAPBoost,
LocationName.StationofSerenityPotion,
LocationName.StationofCallingPotion, LocationName.StationofCallingPotion,
LocationName.CentralStationPotion1, LocationName.CentralStationPotion1,
LocationName.STTCentralStationHiPotion, LocationName.STTCentralStationHiPotion,

View File

@ -59,7 +59,7 @@ class SummonEXP(Range):
class Schmovement(Choice): class Schmovement(Choice):
"""Level of Growth You Start With""" """Level of Progressive Movement You Start With"""
display_name = "Schmovement" display_name = "Schmovement"
option_level_0 = 0 option_level_0 = 0
option_level_1 = 1 option_level_1 = 1
@ -106,9 +106,10 @@ class Visitlocking(Choice):
class RandomVisitLockingItem(Range): class RandomVisitLockingItem(Range):
"""Start with random amount of visit locking items."""
display_name = "Random Visit Locking Item" display_name = "Random Visit Locking Item"
range_start = 0 range_start = 0
range_end = 27 range_end = 25
default = 3 default = 3
@ -191,7 +192,7 @@ class LuckyEmblemsRequired(Range):
"""Number of Lucky Emblems to collect to Open The Final Door bosses. """Number of Lucky Emblems to collect to Open The Final Door bosses.
If Goal is not Lucky Emblem Hunt this does nothing.""" If Goal is not Lucky Emblem Hunt this does nothing."""
display_name = "Lucky Emblems Required" display_name = "Lucky Emblems Required"
range_start = 0 range_start = 1
range_end = 60 range_end = 60
default = 25 default = 25
@ -200,7 +201,7 @@ class LuckyEmblemsAmount(Range):
"""Number of Lucky Emblems that are in the pool. """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 this does nothing."""
display_name = "Lucky Emblems Available" display_name = "Lucky Emblems Available"
range_start = 0 range_start = 1
range_end = 60 range_end = 60
default = 40 default = 40
@ -209,7 +210,7 @@ class BountyRequired(Range):
"""Number of Bounties that are Required. """Number of Bounties that are Required.
If Goal is not Hitlist this does nothing.""" If Goal is not Hitlist this does nothing."""
display_name = "Bounties Required" display_name = "Bounties Required"
range_start = 0 range_start = 1
range_end = 24 range_end = 24
default = 7 default = 7
@ -218,7 +219,7 @@ class BountyAmount(Range):
"""Number of Bounties that are in the pool. """Number of Bounties that are in the pool.
If Goal is not Hitlist this does nothing.""" If Goal is not Hitlist this does nothing."""
display_name = "Bounties Available" display_name = "Bounties Available"
range_start = 0 range_start = 1
range_end = 24 range_end = 24
default = 13 default = 13

View File

@ -52,12 +52,12 @@ class KH2World(World):
self.goofy_ability_pool = list() self.goofy_ability_pool = list()
self.sora_keyblade_ability_pool = list() self.sora_keyblade_ability_pool = list()
self.keyblade_slot_copy = list(Locations.Keyblade_Slots.keys()) self.keyblade_slot_copy = list(Locations.Keyblade_Slots.keys())
self.keyblade_slot_copy.remove(LocationName.KingdomKeySlot)
self.totalLocations = len(all_locations.items()) self.totalLocations = len(all_locations.items())
self.growth_list = list() self.growth_list = list()
for x in range(4): for x in range(4):
self.growth_list.extend(Movement_Table.keys()) self.growth_list.extend(Movement_Table.keys())
self.visitlockingitem = list() self.visitlocking_dict = Progression_Dicts["AllVisitLocking"]
self.visitlockingitem.extend(Progression_Dicts["AllVisitLocking"])
def fill_slot_data(self) -> dict: def fill_slot_data(self) -> dict:
return {"hitlist": self.hitlist, return {"hitlist": self.hitlist,
@ -94,7 +94,7 @@ class KH2World(World):
self.sora_keyblade_ability_pool.extend(SupportAbility_Table.keys()) self.sora_keyblade_ability_pool.extend(SupportAbility_Table.keys())
for item, value in self.multiworld.start_inventory[self.player].value.items(): for item, value in self.multiworld.start_inventory[self.player].value.items():
if item in ActionAbility_Table.keys() or item in SupportAbility_Table.keys(): if item in ActionAbility_Table.keys() or item in SupportAbility_Table.keys() or exclusionItem_table["StatUps"]:
# cannot have more than the quantity for abilties # cannot have more than the quantity for abilties
if value > item_dictionary_table[item].quantity: if value > item_dictionary_table[item].quantity:
logging.info(f"{self.multiworld.get_file_safe_player_name(self.player)} cannot have more than {item_dictionary_table[item].quantity} of {item}" logging.info(f"{self.multiworld.get_file_safe_player_name(self.player)} cannot have more than {item_dictionary_table[item].quantity} of {item}"
@ -216,6 +216,15 @@ class KH2World(World):
self.RandomSuperBoss.remove(randomBoss) self.RandomSuperBoss.remove(randomBoss)
self.totalLocations -= 1 self.totalLocations -= 1
# 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.sora_keyblade_ability_pool)
while random_ability == ItemName.NoExperience:
random_ability = self.multiworld.per_slot_randoms[self.player].choice(self.sora_keyblade_ability_pool)
self.multiworld.get_location(LocationName.KingdomKeySlot, self.player).place_locked_item(self.create_item(random_ability))
self.item_quantity_dict[random_ability] -= 1
self.sora_keyblade_ability_pool.remove(random_ability)
self.totalLocations -= 1
# plando keyblades because they can only have abilities # plando keyblades because they can only have abilities
for keyblade in self.keyblade_slot_copy: for keyblade in self.keyblade_slot_copy:
random_ability = self.multiworld.per_slot_randoms[self.player].choice(self.sora_keyblade_ability_pool) random_ability = self.multiworld.per_slot_randoms[self.player].choice(self.sora_keyblade_ability_pool)
@ -266,25 +275,33 @@ class KH2World(World):
# no visit locking # no visit locking
if self.multiworld.Visitlocking[self.player] == "no_visit_locking": if self.multiworld.Visitlocking[self.player] == "no_visit_locking":
for item in self.visitlockingitem: for item, amount in Progression_Dicts["AllVisitLocking"].items():
self.multiworld.push_precollected(self.create_item(item)) for _ in range(amount):
self.item_quantity_dict[item] -= 1 self.multiworld.push_precollected(self.create_item(item))
self.visitlockingitem.remove(item) self.item_quantity_dict[item] -= 1
if self.visitlocking_dict[item] == 0:
self.visitlocking_dict.pop(item)
self.visitlocking_dict[item] -= 1
# first and second visit locking # first and second visit locking
elif self.multiworld.Visitlocking[self.player] == "second_visit_locking": elif self.multiworld.Visitlocking[self.player] == "second_visit_locking":
for item in Progression_Dicts["2VisitLocking"]: for item in Progression_Dicts["2VisitLocking"]:
self.item_quantity_dict[item] -= 1 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)) self.multiworld.push_precollected(self.create_item(item))
self.visitlockingitem.remove(item)
for _ in range(self.multiworld.RandomVisitLockingItem[self.player].value): for _ in range(self.multiworld.RandomVisitLockingItem[self.player].value):
if len(self.visitlockingitem) <= 0: if sum(self.visitlocking_dict.values()) <= 0:
break break
item = self.multiworld.per_slot_randoms[self.player].choice(self.visitlockingitem) visitlocking_set = list(self.visitlocking_dict.keys())
item = self.multiworld.per_slot_randoms[self.player].choice(visitlocking_set)
self.item_quantity_dict[item] -= 1 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)) self.multiworld.push_precollected(self.create_item(item))
self.visitlockingitem.remove(item)
# there are levels but level 1 is there to keep code clean # there are levels but level 1 is there to keep code clean
if self.multiworld.LevelDepth[self.player] == "level_99_sanity": if self.multiworld.LevelDepth[self.player] == "level_99_sanity":