Skip to content

Commit

Permalink
Merge pull request Ziktofel#331 from Ziktofel/weapon_armor_upgrade_logic
Browse files Browse the repository at this point in the history
Add initial logic featuring weapon/armor upgrades
  • Loading branch information
Ziktofel authored Oct 25, 2024
2 parents bb41193 + ecae3dc commit c7c4c0f
Show file tree
Hide file tree
Showing 8 changed files with 633 additions and 84 deletions.
57 changes: 56 additions & 1 deletion worlds/sc2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
from math import floor, ceil
from dataclasses import dataclass
from BaseClasses import Item, MultiWorld, Location, Tutorial, ItemClassification, CollectionState
from Fill import fill_restrictive, FillError
from Options import Accessibility
from worlds.AutoWorld import WebWorld, World
from . import item_names
from .items import (
StarcraftItem, filler_items, get_full_item_list, ProtossItemType,
ItemData, kerrigan_actives, kerrigan_passives,
not_balanced_starting_units,
not_balanced_starting_units, WEAPON_ARMOR_UPGRADE_MAX_LEVEL,
)
from . import items
from . import item_groups
Expand All @@ -33,6 +34,8 @@
)
from .regions import create_mission_order
from .mission_order.structs import SC2MissionOrder
from ..stardew_valley import true_
from ..v6 import location_table

logger = logging.getLogger("Starcraft 2")

Expand Down Expand Up @@ -118,6 +121,14 @@ class SC2World(World):
final_missions: List[int]
required_client_version = 0, 4, 5
custom_mission_order: SC2MissionOrder
has_barracks_unit: bool = True
has_factory_unit: bool = True
has_starport_unit: bool = True
has_zerg_melee_unit: bool = True
has_zerg_ranged_unit: bool = True
has_zerg_air_unit: bool = True
has_protoss_ground_unit: bool = True
has_protoss_air_unit: bool = True

def __init__(self, multiworld: MultiWorld, player: int):
super(SC2World, self).__init__(multiworld, player)
Expand Down Expand Up @@ -160,6 +171,26 @@ def create_items(self):

self.multiworld.itempool += pool

# Tell the logic which unit classes are used for required W/A upgrades
used_item_names: Set[str] = {item.name for item in item_list}
used_item_names = used_item_names.union(item.name for item in self.multiworld.itempool if item.player == self.player)
if used_item_names.isdisjoint(item_groups.barracks_wa_group):
self.has_barracks_unit = False
if used_item_names.isdisjoint(item_groups.factory_wa_group):
self.has_factory_unit = False
if used_item_names.isdisjoint(item_groups.starport_wa_group):
self.has_starport_unit = False
if used_item_names.isdisjoint(item_groups.zerg_melee_wa):
self.has_zerg_melee_unit = False
if used_item_names.isdisjoint(item_groups.zerg_ranged_wa):
self.has_zerg_ranged_unit = False
if used_item_names.isdisjoint(item_groups.zerg_air_units):
self.has_zerg_air_unit = False
if used_item_names.isdisjoint(item_groups.protoss_ground_wa):
self.has_protoss_ground_unit = False
if used_item_names.isdisjoint(item_groups.protoss_air_wa):
self.has_protoss_air_unit = False

def set_rules(self) -> None:
if self.options.required_tactics == RequiredTactics.option_no_logic:
# Forcing completed goal and minimal accessibility on no logic
Expand Down Expand Up @@ -192,6 +223,30 @@ def fill_slot_data(self):
slot_data["kerrigan_presence"] = KerriganPresence.option_not_present
return slot_data

def pre_fill(self) -> None:
if self.options.generic_upgrade_missions > 0\
and self.options.required_tactics != options.RequiredTactics.option_no_logic:
# Attempt to resolve situation when the option is too high for the mission order rolled
# TODO: Attempt to resolve Kerrigan levels too
weapon_armor_item_names = [
item_names.PROGRESSIVE_TERRAN_WEAPON_ARMOR_UPGRADE,
item_names.PROGRESSIVE_ZERG_WEAPON_ARMOR_UPGRADE,
item_names.PROGRESSIVE_PROTOSS_WEAPON_ARMOR_UPGRADE
]
for attempt in range(0, WEAPON_ARMOR_UPGRADE_MAX_LEVEL):
all_state: CollectionState = self.multiworld.get_all_state(False)
location_failed = False
for location in self.location_cache:
if not (all_state.can_reach_location(location.name, self.player)
and all_state.can_reach_region(location.parent_region.name, self.player)):
location_failed = True
break
if location_failed:
for item_name in weapon_armor_item_names:
item = self.multiworld.create_item(item_name, self.player)
self.multiworld.push_precollected(item)



def setup_events(player: int, locked_locations: List[str], location_cache: List[Location]):
for location in location_cache:
Expand Down
65 changes: 60 additions & 5 deletions worlds/sc2/item_groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,18 +189,30 @@ def get_all_group_names(cls) -> typing.Set[str]:
item_name for item_name, item_data in items.item_table.items()
if item_data.type == items.TerranItemType.Upgrade
]
item_name_groups[ItemGroupNames.BARRACKS_UNITS] = barracks_units = [
item_names.MARINE, item_names.MEDIC, item_names.FIREBAT, item_names.MARAUDER,
barracks_wa_group = [
item_names.MARINE, item_names.FIREBAT, item_names.MARAUDER,
item_names.REAPER, item_names.GHOST, item_names.SPECTRE, item_names.HERC, item_names.AEGIS_GUARD,
item_names.EMPERORS_SHADOW, item_names.DOMINION_TROOPER, item_names.SON_OF_KORHAL,
item_names.FIELD_RESPONSE_THETA,
]
item_name_groups[ItemGroupNames.FACTORY_UNITS] = factory_units = [
item_name_groups[ItemGroupNames.BARRACKS_UNITS] = barracks_units = (barracks_wa_group + [
item_names.MEDIC,
item_names.FIELD_RESPONSE_THETA,
])
factory_wa_group = [
item_names.HELLION, item_names.VULTURE, item_names.GOLIATH, item_names.DIAMONDBACK,
item_names.SIEGE_TANK, item_names.THOR, item_names.PREDATOR, item_names.WIDOW_MINE,
item_names.SIEGE_TANK, item_names.THOR, item_names.PREDATOR,
item_names.CYCLONE, item_names.WARHOUND, item_names.SHOCK_DIVISION, item_names.BLACKHAMMER,
item_names.BULWARK_COMPANY,
]
item_name_groups[ItemGroupNames.FACTORY_UNITS] = factory_units = (factory_wa_group + [
item_names.WIDOW_MINE,
])
starport_wa_group = [
item_names.WRAITH, item_names.VIKING, item_names.BANSHEE,
item_names.BATTLECRUISER, item_names.RAVEN_HUNTER_SEEKER_WEAPON,
item_names.LIBERATOR, item_names.VALKYRIE, item_names.PRIDE_OF_AUGUSTRGRAD, item_names.SKY_FURY,
item_names.EMPERORS_GUARDIAN, item_names.NIGHT_HAWK, item_names.NIGHT_WOLF,
]
item_name_groups[ItemGroupNames.STARPORT_UNITS] = starport_units = [
item_names.MEDIVAC, item_names.WRAITH, item_names.VIKING, item_names.BANSHEE,
item_names.BATTLECRUISER, item_names.HERCULES, item_names.SCIENCE_VESSEL, item_names.RAVEN,
Expand Down Expand Up @@ -416,6 +428,30 @@ def get_all_group_names(cls) -> typing.Set[str]:
if item_data.type in (items.ZergItemType.Unit, items.ZergItemType.Mercenary, items.ZergItemType.Morph)
and item_name not in zerg_buildings
]
# For W/A upgrades
zerg_ground_units = [
item_names.ZERGLING, item_names.SWARM_QUEEN, item_names.ROACH, item_names.HYDRALISK, item_names.ABERRATION,
item_names.SWARM_HOST, item_names.INFESTOR, item_names.ULTRALISK, item_names.ZERGLING_BANELING_ASPECT,
item_names.HYDRALISK_LURKER_ASPECT, item_names.HYDRALISK_IMPALER_ASPECT, item_names.ULTRALISK_TYRANNOZOR_ASPECT,
item_names.ROACH_RAVAGER_ASPECT, item_names.DEFILER, item_names.ROACH_PRIMAL_IGNITER_ASPECT,
item_names.INFESTED_MARINE, item_names.INFESTED_BUNKER, item_names.INFESTED_DIAMONDBACK,
item_names.INFESTED_SIEGE_TANK,
]
zerg_melee_wa = [
item_names.ZERGLING, item_names.ABERRATION, item_names.ULTRALISK, item_names.ZERGLING_BANELING_ASPECT,
item_names.ULTRALISK_TYRANNOZOR_ASPECT, item_names.INFESTED_BUNKER,
]
zerg_ranged_wa = [
item_names.SWARM_QUEEN, item_names.ROACH, item_names.HYDRALISK, item_names.SWARM_HOST,
item_names.HYDRALISK_LURKER_ASPECT, item_names.HYDRALISK_IMPALER_ASPECT, item_names.ULTRALISK_TYRANNOZOR_ASPECT,
item_names.ROACH_RAVAGER_ASPECT, item_names.ROACH_PRIMAL_IGNITER_ASPECT, item_names.INFESTED_MARINE,
item_names.INFESTED_BUNKER, item_names.INFESTED_DIAMONDBACK, item_names.INFESTED_SIEGE_TANK,
]
zerg_air_units = [
item_names.MUTALISK, item_names.MUTALISK_CORRUPTOR_VIPER_ASPECT, item_names.MUTALISK_CORRUPTOR_BROOD_LORD_ASPECT,
item_names.CORRUPTOR, item_names.BROOD_QUEEN, item_names.SCOURGE, item_names.MUTALISK_CORRUPTOR_GUARDIAN_ASPECT,
item_names.MUTALISK_CORRUPTOR_DEVOURER_ASPECT, item_names.INFESTED_BANSHEE, item_names.INFESTED_LIBERATOR,
]
item_name_groups[ItemGroupNames.ZERG_GENERIC_UPGRADES] = zerg_generic_upgrades = [
item_name for item_name, item_data in items.item_table.items()
if item_data.type == items.ZergItemType.Upgrade
Expand Down Expand Up @@ -547,6 +583,25 @@ def get_all_group_names(cls) -> typing.Set[str]:
item_name for item_name, item_data in items.item_table.items()
if item_data.type in (items.ProtossItemType.Unit, items.ProtossItemType.Unit_2)
]
protoss_ground_wa = [
item_names.ZEALOT, item_names.CENTURION, item_names.SENTINEL, item_names.SUPPLICANT,
item_names.SENTRY, item_names.ENERGIZER,
item_names.STALKER, item_names.INSTIGATOR, item_names.SLAYER, item_names.DRAGOON, item_names.ADEPT,
item_names.HIGH_TEMPLAR, item_names.SIGNIFIER, item_names.ASCENDANT,
item_names.DARK_TEMPLAR, item_names.BLOOD_HUNTER, item_names.AVENGER,
item_names.DARK_ARCHON,
item_names.IMMORTAL, item_names.ANNIHILATOR, item_names.VANGUARD, item_names.STALWART,
item_names.COLOSSUS, item_names.WRATHWALKER,
item_names.REAVER,
]
protoss_air_wa = [
item_names.WARP_PRISM_PHASE_BLASTER,
item_names.PHOENIX, item_names.MIRAGE, item_names.CORSAIR, item_names.SKIRMISHER,
item_names.VOID_RAY, item_names.DESTROYER, item_names.WARP_RAY, item_names.DAWNBRINGER,
item_names.CARRIER, item_names.SKYLORD, item_names.TRIREME,
item_names.SCOUT, item_names.TEMPEST, item_names.MOTHERSHIP,
item_names.ARBITER, item_names.ORACLE,
]
item_name_groups[ItemGroupNames.PROTOSS_GENERIC_UPGRADES] = protoss_generic_upgrades = [
item_name for item_name, item_data in items.item_table.items()
if item_data.type == items.ProtossItemType.Upgrade
Expand Down
Loading

0 comments on commit c7c4c0f

Please sign in to comment.