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