SC2: 0.4.3 bugfixes (#2273)
Co-authored-by: Matthew <matthew.marinets@gmail.com>
This commit is contained in:
parent
504d09daf6
commit
154e17f4ff
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue