KH2: New Unit Test and better keyblade fill (#1744)
__init__: - Added exception for if the player has too many excluded abilities on keyblades. - Fixed Action Abilities only on keyblades from breaking. - Added proper support for ability quantity's instead of 1 of the ability - Moved filling the localitems slot data to init instead of generate_output so I could easily unit test it TestSlotData: - Checks if the "localItems" part of slot data is filled. This is used for keeping track of local items and making sure nothing dupes
This commit is contained in:
parent
62a265cc31
commit
06a25a903e
|
@ -6,8 +6,7 @@ import Utils
|
||||||
import zipfile
|
import zipfile
|
||||||
|
|
||||||
from .Items import item_dictionary_table, CheckDupingItems
|
from .Items import item_dictionary_table, CheckDupingItems
|
||||||
from .Locations import all_locations, SoraLevels, exclusion_table, AllWeaponSlot
|
from .Locations import all_locations, SoraLevels, exclusion_table
|
||||||
from .Names import LocationName
|
|
||||||
from .XPValues import lvlStats, formExp, soraExp
|
from .XPValues import lvlStats, formExp, soraExp
|
||||||
from worlds.Files import APContainer
|
from worlds.Files import APContainer
|
||||||
|
|
||||||
|
@ -83,7 +82,7 @@ def patch_kh2(self, output_directory):
|
||||||
elif self.multiworld.LevelDepth[self.player] == "level_99":
|
elif self.multiworld.LevelDepth[self.player] == "level_99":
|
||||||
levelsetting.extend(exclusion_table["Level99"])
|
levelsetting.extend(exclusion_table["Level99"])
|
||||||
|
|
||||||
elif self.multiworld.LevelDepth[self.player] in ["level_50_sanity", "level_99_sanity"]:
|
elif self.multiworld.LevelDepth[self.player] != "level_1":
|
||||||
levelsetting.extend(exclusion_table["Level50Sanity"])
|
levelsetting.extend(exclusion_table["Level50Sanity"])
|
||||||
|
|
||||||
if self.multiworld.LevelDepth[self.player] == "level_99_sanity":
|
if self.multiworld.LevelDepth[self.player] == "level_99_sanity":
|
||||||
|
@ -96,9 +95,6 @@ def patch_kh2(self, output_directory):
|
||||||
data = all_locations[location.name]
|
data = all_locations[location.name]
|
||||||
if location.item.player == self.player:
|
if location.item.player == self.player:
|
||||||
itemcode = item_dictionary_table[location.item.name].kh2id
|
itemcode = item_dictionary_table[location.item.name].kh2id
|
||||||
if location.item.name in slotDataDuping and \
|
|
||||||
location.name not in AllWeaponSlot:
|
|
||||||
self.LocalItems[location.address] = item_dictionary_table[location.item.name].code
|
|
||||||
else:
|
else:
|
||||||
itemcode = 90 # castle map
|
itemcode = 90 # castle map
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ from BaseClasses import Tutorial, ItemClassification
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from .Items import *
|
from .Items import *
|
||||||
from .Locations import all_locations, setup_locations, exclusion_table
|
from .Locations import all_locations, setup_locations, exclusion_table, AllWeaponSlot
|
||||||
from .Names import ItemName, LocationName
|
from .Names import ItemName, LocationName
|
||||||
from .OpenKH import patch_kh2
|
from .OpenKH import patch_kh2
|
||||||
from .Options import KH2_Options
|
from .Options import KH2_Options
|
||||||
|
@ -62,8 +62,22 @@ class KH2World(World):
|
||||||
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.slotDataDuping = set()
|
||||||
|
self.localItems = dict()
|
||||||
|
|
||||||
def fill_slot_data(self) -> 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,
|
return {"hitlist": self.hitlist,
|
||||||
"LocalItems": self.LocalItems,
|
"LocalItems": self.LocalItems,
|
||||||
"Goal": self.multiworld.Goal[self.player].value,
|
"Goal": self.multiworld.Goal[self.player].value,
|
||||||
|
@ -132,7 +146,7 @@ class KH2World(World):
|
||||||
|
|
||||||
# Creating filler for unfilled locations
|
# Creating filler for unfilled locations
|
||||||
itempool += [self.create_filler()
|
itempool += [self.create_filler()
|
||||||
for _ in range(self.totalLocations-len(itempool))]
|
for _ in range(self.totalLocations - len(itempool))]
|
||||||
self.multiworld.itempool += itempool
|
self.multiworld.itempool += itempool
|
||||||
|
|
||||||
def generate_early(self) -> None:
|
def generate_early(self) -> None:
|
||||||
|
@ -245,13 +259,15 @@ class KH2World(World):
|
||||||
ItemName.FinishingPlus: 1}}
|
ItemName.FinishingPlus: 1}}
|
||||||
|
|
||||||
elif self.multiworld.KeybladeAbilities[self.player] == "action":
|
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}
|
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
|
# there are too little action abilities so 2 random support abilities are placed
|
||||||
for _ in range(3):
|
for _ in range(3):
|
||||||
randomSupportAbility = self.multiworld.per_slot_randoms[self.player].choice(list(SupportAbility_Table.keys()))
|
randomSupportAbility = self.multiworld.per_slot_randoms[self.player].choice(
|
||||||
|
list(SupportAbility_Table.keys()))
|
||||||
while randomSupportAbility in self.sora_keyblade_ability_pool:
|
while randomSupportAbility in self.sora_keyblade_ability_pool:
|
||||||
randomSupportAbility = self.multiworld.per_slot_randoms[self.player].choice(
|
randomSupportAbility = self.multiworld.per_slot_randoms[self.player].choice(
|
||||||
list(SupportAbility_Table.keys()))
|
list(SupportAbility_Table.keys()))
|
||||||
self.sora_keyblade_ability_pool[randomSupportAbility] = 1
|
self.sora_keyblade_ability_pool[randomSupportAbility] = 1
|
||||||
else:
|
else:
|
||||||
# both action and support on keyblades.
|
# both action and support on keyblades.
|
||||||
|
@ -259,7 +275,8 @@ class KH2World(World):
|
||||||
self.sora_keyblade_ability_pool = {
|
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 SupportAbility_Table},
|
||||||
**{item: data for item, data in self.item_quantity_dict.items() if item in ActionAbility_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}}
|
**{ItemName.NegativeCombo: 1, ItemName.AirComboPlus: 1, ItemName.ComboPlus: 1,
|
||||||
|
ItemName.FinishingPlus: 1}}
|
||||||
|
|
||||||
for ability in self.multiworld.BlacklistKeyblade[self.player].value:
|
for ability in self.multiworld.BlacklistKeyblade[self.player].value:
|
||||||
if ability in self.sora_keyblade_ability_pool:
|
if ability in self.sora_keyblade_ability_pool:
|
||||||
|
@ -267,7 +284,8 @@ class KH2World(World):
|
||||||
|
|
||||||
# magic number for amount of keyblades
|
# magic number for amount of keyblades
|
||||||
if sum(self.sora_keyblade_ability_pool.values()) < 28:
|
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")
|
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())
|
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
|
# Kingdom Key cannot have No Experience so plandoed here instead of checking 26 times if its kingdom key
|
||||||
|
@ -379,4 +397,5 @@ class KH2World(World):
|
||||||
self.totalLocations -= 76
|
self.totalLocations -= 76
|
||||||
|
|
||||||
def get_filler_item_name(self) -> str:
|
def get_filler_item_name(self) -> str:
|
||||||
return self.multiworld.random.choice([ItemName.PowerBoost, ItemName.MagicBoost, ItemName.DefenseBoost, ItemName.APBoost])
|
return self.multiworld.random.choice(
|
||||||
|
[ItemName.PowerBoost, ItemName.MagicBoost, ItemName.DefenseBoost, ItemName.APBoost])
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
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"
|
Loading…
Reference in New Issue