SC2: 0.4.3 bugfixes ()

Co-authored-by: Matthew <matthew.marinets@gmail.com>
This commit is contained in:
Ziktofel 2023-11-08 19:00:55 +01:00 committed by GitHub
parent 504d09daf6
commit 154e17f4ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 41 additions and 25 deletions

View File

@ -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.")

View File

@ -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)),

View File

@ -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"

View File

@ -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)

View File

@ -11,6 +11,6 @@
markup: True
halign: 'center'
valign: 'middle'
padding_x: 5
padding: [5,0,5,0]
markup: True
outline_width: 1

View File

@ -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)