SC2: 0.4.3 bugfixes (#2273)
Co-authored-by: Matthew <matthew.marinets@gmail.com>
This commit is contained in:
		| @@ -9,6 +9,7 @@ import multiprocessing | ||||
| import os.path | ||||
| import re | ||||
| import sys | ||||
| import tempfile | ||||
| import typing | ||||
| import queue | ||||
| import zipfile | ||||
| @@ -286,6 +287,8 @@ class SC2Context(CommonContext): | ||||
|             await super(SC2Context, self).server_auth(password_requested) | ||||
|         await self.get_username() | ||||
|         await self.send_connect() | ||||
|         if self.ui: | ||||
|             self.ui.first_check = True | ||||
|  | ||||
|     def on_package(self, cmd: str, args: dict): | ||||
|         if cmd in {"Connected"}: | ||||
| @@ -1166,10 +1169,12 @@ def download_latest_release_zip(owner: str, repo: str, api_version: str, metadat | ||||
|  | ||||
|     r2 = requests.get(download_url, headers=headers) | ||||
|     if r2.status_code == 200 and zipfile.is_zipfile(io.BytesIO(r2.content)): | ||||
|         with open(f"{repo}.zip", "wb") as fh: | ||||
|         tempdir = tempfile.gettempdir() | ||||
|         file = tempdir + os.sep + f"{repo}.zip" | ||||
|         with open(file, "wb") as fh: | ||||
|             fh.write(r2.content) | ||||
|         sc2_logger.info(f"Successfully downloaded {repo}.zip.") | ||||
|         return f"{repo}.zip", latest_metadata | ||||
|         return file, latest_metadata | ||||
|     else: | ||||
|         sc2_logger.warning(f"Status code: {r2.status_code}") | ||||
|         sc2_logger.warning("Download failed.") | ||||
|   | ||||
| @@ -68,10 +68,10 @@ def get_locations(multiworld: Optional[MultiWorld], player: Optional[int]) -> Tu | ||||
|                      lambda state: state._sc2wol_has_common_unit(multiworld, player) and | ||||
|                                    (logic_level > 0 and state._sc2wol_has_anti_air(multiworld, player) | ||||
|                                     or state._sc2wol_has_competent_anti_air(multiworld, player))), | ||||
|         LocationData("Evacuation", "Evacuation: First Chrysalis", SC2WOL_LOC_ID_OFFSET + 401, LocationType.BONUS), | ||||
|         LocationData("Evacuation", "Evacuation: Second Chrysalis", SC2WOL_LOC_ID_OFFSET + 402, LocationType.BONUS, | ||||
|         LocationData("Evacuation", "Evacuation: North Chrysalis", SC2WOL_LOC_ID_OFFSET + 401, LocationType.BONUS), | ||||
|         LocationData("Evacuation", "Evacuation: West Chrysalis", SC2WOL_LOC_ID_OFFSET + 402, LocationType.BONUS, | ||||
|                      lambda state: state._sc2wol_has_common_unit(multiworld, player)), | ||||
|         LocationData("Evacuation", "Evacuation: Third Chrysalis", SC2WOL_LOC_ID_OFFSET + 403, LocationType.BONUS, | ||||
|         LocationData("Evacuation", "Evacuation: East Chrysalis", SC2WOL_LOC_ID_OFFSET + 403, LocationType.BONUS, | ||||
|                      lambda state: state._sc2wol_has_common_unit(multiworld, player)), | ||||
|         LocationData("Evacuation", "Evacuation: Reach Hanson", SC2WOL_LOC_ID_OFFSET + 404, LocationType.MISSION_PROGRESS), | ||||
|         LocationData("Evacuation", "Evacuation: Secret Resource Stash", SC2WOL_LOC_ID_OFFSET + 405, LocationType.BONUS), | ||||
| @@ -419,7 +419,7 @@ def get_locations(multiworld: Optional[MultiWorld], player: Optional[int]) -> Tu | ||||
|                      lambda state: state._sc2wol_has_protoss_medium_units(multiworld, player)), | ||||
|         LocationData("A Sinister Turn", "A Sinister Turn: Northeast Base", SC2WOL_LOC_ID_OFFSET + 2304, LocationType.MISSION_PROGRESS, | ||||
|                      lambda state: state._sc2wol_has_protoss_medium_units(multiworld, player)), | ||||
|         LocationData("A Sinister Turn", "A Sinister Turn: Southeast Base", SC2WOL_LOC_ID_OFFSET + 2305, LocationType.MISSION_PROGRESS, | ||||
|         LocationData("A Sinister Turn", "A Sinister Turn: Southwest Base", SC2WOL_LOC_ID_OFFSET + 2305, LocationType.MISSION_PROGRESS, | ||||
|                      lambda state: state._sc2wol_has_protoss_medium_units(multiworld, player)), | ||||
|         LocationData("A Sinister Turn", "A Sinister Turn: Maar", SC2WOL_LOC_ID_OFFSET + 2306, LocationType.MISSION_PROGRESS, | ||||
|                      lambda state: logic_level > 0 or state._sc2wol_has_protoss_medium_units(multiworld, player)), | ||||
|   | ||||
| @@ -41,6 +41,10 @@ class FinalMap(Choice): | ||||
|  | ||||
|     Vanilla mission order always ends with All in mission! | ||||
|  | ||||
|     Warning: Using All-in with a short mission order (7 or fewer missions) is not recommended, | ||||
|         as there might not be enough locations to place all the required items, | ||||
|         any excess required items will be placed into the player's starting inventory! | ||||
|  | ||||
|     This option is short-lived. It may be changed in the future | ||||
|     """ | ||||
|     display_name = "Final Map" | ||||
| @@ -265,7 +269,6 @@ class MissionProgressLocations(LocationInclusion): | ||||
|     Nothing: No rewards for this type of tasks, effectively disabling such locations | ||||
|  | ||||
|     Note: Individual locations subject to plando are always enabled, so the plando can be placed properly. | ||||
|     Warning: The generation may fail if too many locations are excluded by this way. | ||||
|     See also: Excluded Locations, Item Plando (https://archipelago.gg/tutorial/Archipelago/plando/en#item-plando) | ||||
|     """ | ||||
|     display_name = "Mission Progress Locations" | ||||
| @@ -282,7 +285,6 @@ class BonusLocations(LocationInclusion): | ||||
|     Nothing: No rewards for this type of tasks, effectively disabling such locations | ||||
|  | ||||
|     Note: Individual locations subject to plando are always enabled, so the plando can be placed properly. | ||||
|     Warning: The generation may fail if too many locations are excluded by this way. | ||||
|     See also: Excluded Locations, Item Plando (https://archipelago.gg/tutorial/Archipelago/plando/en#item-plando) | ||||
|     """ | ||||
|     display_name = "Bonus Locations" | ||||
| @@ -300,7 +302,6 @@ class ChallengeLocations(LocationInclusion): | ||||
|     Nothing: No rewards for this type of tasks, effectively disabling such locations | ||||
|  | ||||
|     Note: Individual locations subject to plando are always enabled, so the plando can be placed properly. | ||||
|     Warning: The generation may fail if too many locations are excluded by this way. | ||||
|     See also: Excluded Locations, Item Plando (https://archipelago.gg/tutorial/Archipelago/plando/en#item-plando) | ||||
|     """ | ||||
|     display_name = "Challenge Locations" | ||||
| @@ -317,7 +318,6 @@ class OptionalBossLocations(LocationInclusion): | ||||
|     Nothing: No rewards for this type of tasks, effectively disabling such locations | ||||
|  | ||||
|     Note: Individual locations subject to plando are always enabled, so the plando can be placed properly. | ||||
|     Warning: The generation may fail if too many locations are excluded by this way. | ||||
|     See also: Excluded Locations, Item Plando (https://archipelago.gg/tutorial/Archipelago/plando/en#item-plando) | ||||
|     """ | ||||
|     display_name = "Optional Boss Locations" | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| from typing import Callable, Dict, List, Set | ||||
| from BaseClasses import MultiWorld, ItemClassification, Item, Location | ||||
| from .Items import get_full_item_list, spider_mine_sources, second_pass_placeable_items, filler_items | ||||
| from .Items import get_full_item_list, spider_mine_sources, second_pass_placeable_items, filler_items, \ | ||||
|     progressive_if_nco | ||||
| from .MissionTables import no_build_regions_list, easy_regions_list, medium_regions_list, hard_regions_list,\ | ||||
|     mission_orders, MissionInfo, alt_final_mission_locations, MissionPools | ||||
| from .Options import get_option_value, MissionOrder, FinalMap, MissionProgressLocations, LocationInclusion | ||||
| @@ -15,7 +16,7 @@ UPGRADABLE_ITEMS = [ | ||||
| ] | ||||
|  | ||||
| BARRACKS_UNITS = {"Marine", "Medic", "Firebat", "Marauder", "Reaper", "Ghost", "Spectre"} | ||||
| FACTORY_UNITS = {"Hellion", "Vulture", "Goliath", "Diamondback", "Siege Tank", "Thor", "Predator", "Widow Mine"} | ||||
| FACTORY_UNITS = {"Hellion", "Vulture", "Goliath", "Diamondback", "Siege Tank", "Thor", "Predator", "Widow Mine", "Cyclone"} | ||||
| STARPORT_UNITS = {"Medivac", "Wraith", "Viking", "Banshee", "Battlecruiser", "Hercules", "Science Vessel", "Raven", "Liberator", "Valkyrie"} | ||||
|  | ||||
| PROTOSS_REGIONS = {"A Sinister Turn", "Echoes of the Future", "In Utter Darkness"} | ||||
| @@ -93,7 +94,10 @@ def get_item_upgrades(inventory: List[Item], parent_item: Item or str): | ||||
|     ] | ||||
|  | ||||
|  | ||||
| def get_item_quantity(item): | ||||
| def get_item_quantity(item: Item, multiworld: MultiWorld, player: int): | ||||
|     if (not get_option_value(multiworld, player, "nco_items")) \ | ||||
|             and item.name in progressive_if_nco: | ||||
|         return 1 | ||||
|     return get_full_item_list()[item.name].quantity | ||||
|  | ||||
|  | ||||
| @@ -138,13 +142,13 @@ class ValidInventory: | ||||
|                 if not all(requirement(self) for requirement in requirements): | ||||
|                     # If item cannot be removed, lock or revert | ||||
|                     self.logical_inventory.add(item.name) | ||||
|                     for _ in range(get_item_quantity(item)): | ||||
|                     for _ in range(get_item_quantity(item, self.multiworld, self.player)): | ||||
|                         locked_items.append(copy_item(item)) | ||||
|                     return False | ||||
|             return True | ||||
|          | ||||
|  | ||||
|         # Limit the maximum number of upgrades  | ||||
|         maxUpgrad = get_option_value(self.multiworld, self.player,  | ||||
|         maxUpgrad = get_option_value(self.multiworld, self.player, | ||||
|                             "max_number_of_upgrades") | ||||
|         if maxUpgrad != -1: | ||||
|             unit_avail_upgrades = {} | ||||
| @@ -197,15 +201,16 @@ class ValidInventory: | ||||
|                     # Don't process general upgrades, they may have been pre-locked per-level | ||||
|                     for item in items_to_lock: | ||||
|                         if item in inventory: | ||||
|                             item_quantity = inventory.count(item) | ||||
|                             # Unit upgrades, lock all levels | ||||
|                             for _ in range(inventory.count(item)): | ||||
|                             for _ in range(item_quantity): | ||||
|                                 inventory.remove(item) | ||||
|                             if item not in locked_items: | ||||
|                                 # Lock all the associated items if not already locked | ||||
|                                 for _ in range(get_item_quantity(item)): | ||||
|                                 for _ in range(item_quantity): | ||||
|                                     locked_items.append(copy_item(item)) | ||||
|                     if item in existing_items: | ||||
|                         existing_items.remove(item) | ||||
|                         if item in existing_items: | ||||
|                             existing_items.remove(item) | ||||
|  | ||||
|         if self.min_units_per_structure > 0 and self.has_units_per_structure(): | ||||
|             requirements.append(lambda state: state.has_units_per_structure()) | ||||
| @@ -216,7 +221,13 @@ class ValidInventory: | ||||
|  | ||||
|         while len(inventory) + len(locked_items) > inventory_size: | ||||
|             if len(inventory) == 0: | ||||
|                 raise Exception("Reduced item pool generation failed - not enough locations available to place items.") | ||||
|                 # There are more items than locations and all of them are already locked due to YAML or logic. | ||||
|                 # Random items from locked ones will go to starting items | ||||
|                 self.multiworld.random.shuffle(locked_items) | ||||
|                 while len(locked_items) > inventory_size: | ||||
|                     item: Item = locked_items.pop() | ||||
|                     self.multiworld.push_precollected(item) | ||||
|                 break | ||||
|             # Select random item from removable items | ||||
|             item = self.multiworld.random.choice(inventory) | ||||
|             # Cascade removals to associated items | ||||
| @@ -245,7 +256,7 @@ class ValidInventory: | ||||
|                             for _ in range(inventory.count(transient_item)): | ||||
|                                 inventory.remove(transient_item) | ||||
|                         if transient_item not in locked_items: | ||||
|                             for _ in range(get_item_quantity(transient_item)): | ||||
|                             for _ in range(get_item_quantity(transient_item, self.multiworld, self.player)): | ||||
|                                 locked_items.append(copy_item(transient_item)) | ||||
|                         if transient_item.classification in (ItemClassification.progression, ItemClassification.progression_skip_balancing): | ||||
|                             self.logical_inventory.add(transient_item.name) | ||||
|   | ||||
| @@ -11,6 +11,6 @@ | ||||
|     markup: True | ||||
|     halign: 'center' | ||||
|     valign: 'middle' | ||||
|     padding_x: 5 | ||||
|     padding: [5,0,5,0] | ||||
|     markup: True | ||||
|     outline_width: 1 | ||||
|   | ||||
| @@ -34,7 +34,7 @@ class SC2WoLWorld(World): | ||||
|  | ||||
|     game = "Starcraft 2 Wings of Liberty" | ||||
|     web = Starcraft2WoLWebWorld() | ||||
|     data_version = 4 | ||||
|     data_version = 5 | ||||
|  | ||||
|     item_name_to_id = {name: data.code for name, data in get_full_item_list().items()} | ||||
|     location_name_to_id = {location.name: location.code for location in get_locations(None, None)} | ||||
| @@ -46,7 +46,7 @@ class SC2WoLWorld(World): | ||||
|     mission_req_table = {} | ||||
|     final_mission_id: int | ||||
|     victory_item: str | ||||
|     required_client_version = 0, 3, 6 | ||||
|     required_client_version = 0, 4, 3 | ||||
|  | ||||
|     def __init__(self, multiworld: MultiWorld, player: int): | ||||
|         super(SC2WoLWorld, self).__init__(multiworld, player) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Ziktofel
					Ziktofel