Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SC2: 0.4.3 bugfixes #2273

Merged
merged 13 commits into from
Nov 8, 2023
Merged
9 changes: 7 additions & 2 deletions worlds/sc2wol/Client.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import os.path
import re
import sys
import tempfile
import typing
import queue
import zipfile
Expand Down Expand Up @@ -286,6 +287,8 @@ async def server_auth(self, password_requested: bool = False):
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"}:
Expand Down Expand Up @@ -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.")
Expand Down
8 changes: 4 additions & 4 deletions worlds/sc2wol/Locations.py
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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)),
Expand Down
8 changes: 4 additions & 4 deletions worlds/sc2wol/Options.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand All @@ -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"
Expand All @@ -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"
Expand All @@ -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"
Expand Down
35 changes: 23 additions & 12 deletions worlds/sc2wol/PoolFilter.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -15,7 +16,7 @@
]

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"}
Expand Down Expand Up @@ -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


Expand Down Expand Up @@ -138,13 +142,13 @@ def attempt_removal(item: Item) -> bool:
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 = {}
Expand Down Expand Up @@ -197,15 +201,16 @@ def attempt_removal(item: Item) -> bool:
# 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())
Expand All @@ -216,7 +221,13 @@ def attempt_removal(item: Item) -> bool:

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
Expand Down Expand Up @@ -245,7 +256,7 @@ def attempt_removal(item: Item) -> bool:
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)
Expand Down
2 changes: 1 addition & 1 deletion worlds/sc2wol/Starcraft2.kv
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
markup: True
halign: 'center'
valign: 'middle'
padding_x: 5
padding: [5,0,5,0]
markup: True
outline_width: 1
4 changes: 2 additions & 2 deletions worlds/sc2wol/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)}
Expand All @@ -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)
Expand Down