363 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			363 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
| from typing import Dict, FrozenSet, Union
 | |
| from BaseClasses import MultiWorld
 | |
| from Options import Choice, Option, Toggle, DefaultOnToggle, ItemSet, OptionSet, Range
 | |
| from .MissionTables import vanilla_mission_req_table
 | |
| 
 | |
| ORDER_VANILLA = 0
 | |
| ORDER_VANILLA_SHUFFLED = 1
 | |
| 
 | |
| class GameDifficulty(Choice):
 | |
|     """
 | |
|     The difficulty of the campaign, affects enemy AI, starting units, and game speed.
 | |
| 
 | |
|     For those unfamiliar with the Archipelago randomizer, the recommended settings are one difficulty level
 | |
|     lower than the vanilla game
 | |
|     """
 | |
|     display_name = "Game Difficulty"
 | |
|     option_casual = 0
 | |
|     option_normal = 1
 | |
|     option_hard = 2
 | |
|     option_brutal = 3
 | |
|     default = 1
 | |
| 
 | |
| class GameSpeed(Choice):
 | |
|     """Optional setting to override difficulty-based game speed."""
 | |
|     display_name = "Game Speed"
 | |
|     option_default = 0
 | |
|     option_slower = 1
 | |
|     option_slow = 2
 | |
|     option_normal = 3
 | |
|     option_fast = 4
 | |
|     option_faster = 5
 | |
|     default = option_default
 | |
| 
 | |
| class FinalMap(Choice):
 | |
|     """
 | |
|     Determines if the final map and goal of the campaign.
 | |
|     All in: You need to beat All-in map
 | |
|     Random Hard: A random hard mission is selected as a goal.
 | |
|                 Beat this mission in order to complete the game.
 | |
|                 All-in map won't be in the campaign
 | |
| 
 | |
|     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"
 | |
|     option_all_in = 0
 | |
|     option_random_hard = 1
 | |
| 
 | |
| class AllInMap(Choice):
 | |
|     """Determines what version of All-In (final map) that will be generated for the campaign."""
 | |
|     display_name = "All In Map"
 | |
|     option_ground = 0
 | |
|     option_air = 1
 | |
| 
 | |
| 
 | |
| class MissionOrder(Choice):
 | |
|     """
 | |
|     Determines the order the missions are played in.  The last three mission orders end in a random mission.
 | |
|     Vanilla (29): Keeps the standard mission order and branching from the WoL Campaign.
 | |
|     Vanilla Shuffled (29): Keeps same branching paths from the WoL Campaign but randomizes the order of missions within.
 | |
|     Mini Campaign (15): Shorter version of the campaign with randomized missions and optional branches.
 | |
|     Grid (16):  A 4x4 grid of random missions.  Start at the top-left and forge a path towards bottom-right mission to win.
 | |
|     Mini Grid (9):  A 3x3 version of Grid.  Complete the bottom-right mission to win.
 | |
|     Blitz (12):  12 random missions that open up very quickly.  Complete the bottom-right mission to win.
 | |
|     Gauntlet (7): Linear series of 7 random missions to complete the campaign.
 | |
|     Mini Gauntlet (4): Linear series of 4 random missions to complete the campaign.
 | |
|     Tiny Grid (4): A 2x2 version of Grid.  Complete the bottom-right mission to win.
 | |
|     """
 | |
|     display_name = "Mission Order"
 | |
|     option_vanilla = 0
 | |
|     option_vanilla_shuffled = 1
 | |
|     option_mini_campaign = 2
 | |
|     option_grid = 3
 | |
|     option_mini_grid = 4
 | |
|     option_blitz = 5
 | |
|     option_gauntlet = 6
 | |
|     option_mini_gauntlet = 7
 | |
|     option_tiny_grid = 8
 | |
| 
 | |
| 
 | |
| class PlayerColor(Choice):
 | |
|     """Determines in-game team color."""
 | |
|     display_name = "Player Color"
 | |
|     option_white = 0
 | |
|     option_red = 1
 | |
|     option_blue = 2
 | |
|     option_teal = 3
 | |
|     option_purple = 4
 | |
|     option_yellow = 5
 | |
|     option_orange = 6
 | |
|     option_green = 7
 | |
|     option_light_pink = 8
 | |
|     option_violet = 9
 | |
|     option_light_grey = 10
 | |
|     option_dark_green = 11
 | |
|     option_brown = 12
 | |
|     option_light_green = 13
 | |
|     option_dark_grey = 14
 | |
|     option_pink = 15
 | |
|     option_rainbow = 16
 | |
|     option_default = 17
 | |
|     default = option_default
 | |
| 
 | |
| 
 | |
| class ShuffleProtoss(DefaultOnToggle):
 | |
|     """Determines if the 3 protoss missions are included in the shuffle if Vanilla mission order is not enabled.
 | |
|     If turned off, the 3 protoss missions will not appear and Protoss units are removed from the pool."""
 | |
|     display_name = "Shuffle Protoss Missions"
 | |
| 
 | |
| 
 | |
| class ShuffleNoBuild(DefaultOnToggle):
 | |
|     """Determines if the 5 no-build missions are included in the shuffle if Vanilla mission order is not enabled.
 | |
|     If turned off, the 5 no-build missions will not appear."""
 | |
|     display_name = "Shuffle No-Build Missions"
 | |
| 
 | |
| 
 | |
| class EarlyUnit(DefaultOnToggle):
 | |
|     """
 | |
|     Guarantees that the first mission will contain a unit.
 | |
| 
 | |
|     Each mission available to be the first mission has a pre-defined location where the unit should spawn.
 | |
|     This location gets overriden over any exclusion. It's guaranteed to be reachable with an empty inventory.
 | |
|     """
 | |
|     display_name = "Early Unit"
 | |
| 
 | |
| 
 | |
| class RequiredTactics(Choice):
 | |
|     """Determines the maximum tactical difficulty of the seed (separate from mission difficulty).  Higher settings
 | |
|     increase randomness.
 | |
| 
 | |
|     Standard:  All missions can be completed with good micro and macro.
 | |
|     Advanced:  Completing missions may require relying on starting units and micro-heavy units.
 | |
|     No Logic:  Units and upgrades may be placed anywhere.  LIKELY TO RENDER THE RUN IMPOSSIBLE ON HARDER DIFFICULTIES!"""
 | |
|     display_name = "Required Tactics"
 | |
|     option_standard = 0
 | |
|     option_advanced = 1
 | |
|     option_no_logic = 2
 | |
| 
 | |
| 
 | |
| class UnitsAlwaysHaveUpgrades(DefaultOnToggle):
 | |
|     """
 | |
|     If turned on, all upgrades will be present for each unit and structure in the seed.
 | |
|     This usually results in fewer units.
 | |
| 
 | |
|     See also: Max Number of Upgrades
 | |
|     """
 | |
|     display_name = "Units Always Have Upgrades"
 | |
| 
 | |
| 
 | |
| class GenericUpgradeMissions(Range):
 | |
|     """Determines the percentage of missions in the mission order that must be completed before
 | |
|     level 1 of all weapon and armor upgrades is unlocked.  Level 2 upgrades require double the amount of missions,
 | |
|     and level 3 requires triple the amount.  The required amounts are always rounded down.
 | |
|     If set to 0, upgrades are instead added to the item pool and must be found to be used."""
 | |
|     display_name = "Generic Upgrade Missions"
 | |
|     range_start = 0
 | |
|     range_end = 100
 | |
|     default = 0
 | |
| 
 | |
| 
 | |
| class GenericUpgradeResearch(Choice):
 | |
|     """Determines how weapon and armor upgrades affect missions once unlocked.
 | |
| 
 | |
|     Vanilla:  Upgrades must be researched as normal.
 | |
|     Auto In No-Build:  In No-Build missions, upgrades are automatically researched.
 | |
|     In all other missions, upgrades must be researched as normal.
 | |
|     Auto In Build:  In No-Build missions, upgrades are unavailable as normal.
 | |
|     In all other missions, upgrades are automatically researched.
 | |
|     Always Auto:  Upgrades are automatically researched in all missions."""
 | |
|     display_name = "Generic Upgrade Research"
 | |
|     option_vanilla = 0
 | |
|     option_auto_in_no_build = 1
 | |
|     option_auto_in_build = 2
 | |
|     option_always_auto = 3
 | |
| 
 | |
| 
 | |
| class GenericUpgradeItems(Choice):
 | |
|     """Determines how weapon and armor upgrades are split into items.  All options produce 3 levels of each item.
 | |
|     Does nothing if upgrades are unlocked by completed mission counts.
 | |
| 
 | |
|     Individual Items:  All weapon and armor upgrades are each an item,
 | |
|     resulting in 18 total upgrade items.
 | |
|     Bundle Weapon And Armor:  All types of weapon upgrades are one item,
 | |
|     and all types of armor upgrades are one item,
 | |
|     resulting in 6 total items.
 | |
|     Bundle Unit Class:  Weapon and armor upgrades are merged,
 | |
|     but Infantry, Vehicle, and Starship upgrades are bundled separately,
 | |
|     resulting in 9 total items.
 | |
|     Bundle All:  All weapon and armor upgrades are one item,
 | |
|     resulting in 3 total items."""
 | |
|     display_name = "Generic Upgrade Items"
 | |
|     option_individual_items = 0
 | |
|     option_bundle_weapon_and_armor = 1
 | |
|     option_bundle_unit_class = 2
 | |
|     option_bundle_all = 3
 | |
| 
 | |
| 
 | |
| class NovaCovertOpsItems(Toggle):
 | |
|     """If turned on, the equipment upgrades from Nova Covert Ops may be present in the world."""
 | |
|     display_name = "Nova Covert Ops Items"
 | |
|     default = Toggle.option_true
 | |
| 
 | |
| 
 | |
| class BroodWarItems(Toggle):
 | |
|     """If turned on, returning items from StarCraft: Brood War may appear in the world."""
 | |
|     display_name = "Brood War Items"
 | |
|     default = Toggle.option_true
 | |
| 
 | |
| 
 | |
| class ExtendedItems(Toggle):
 | |
|     """If turned on, original items that did not appear in Campaign mode may appear in the world."""
 | |
|     display_name = "Extended Items"
 | |
|     default = Toggle.option_true
 | |
| 
 | |
| 
 | |
| class MaxNumberOfUpgrades(Range):
 | |
|     """
 | |
|     Set a maximum to the number of upgrades a unit/structure can have. -1 is used to define unlimited.
 | |
|     Note that most unit have 4 or 6 upgrades.
 | |
| 
 | |
|     If used with Units Always Have Upgrades, each unit has this given amount of upgrades (if there enough upgrades exist)
 | |
| 
 | |
|     See also: Units Always Have Upgrades
 | |
|     """
 | |
|     display_name = "Maximum number of upgrades per unit/structure"
 | |
|     range_start = -1
 | |
|     # Do not know the maximum, but it is less than 123!
 | |
|     range_end = 123
 | |
|     default = -1
 | |
| 
 | |
| 
 | |
| class LockedItems(ItemSet):
 | |
|     """Guarantees that these items will be unlockable"""
 | |
|     display_name = "Locked Items"
 | |
| 
 | |
| 
 | |
| class ExcludedItems(ItemSet):
 | |
|     """Guarantees that these items will not be unlockable"""
 | |
|     display_name = "Excluded Items"
 | |
| 
 | |
| 
 | |
| class ExcludedMissions(OptionSet):
 | |
|     """Guarantees that these missions will not appear in the campaign
 | |
|     Doesn't apply to vanilla mission order.
 | |
|     It may be impossible to build a valid campaign if too many missions are excluded."""
 | |
|     display_name = "Excluded Missions"
 | |
|     valid_keys = {mission_name for mission_name in vanilla_mission_req_table.keys() if mission_name != 'All-In'}
 | |
| 
 | |
| 
 | |
| class LocationInclusion(Choice):
 | |
|     option_enabled = 0
 | |
|     option_trash = 1
 | |
|     option_nothing = 2
 | |
| 
 | |
| 
 | |
| class MissionProgressLocations(LocationInclusion):
 | |
|     """
 | |
|     Enables or disables item rewards for progressing (not finishing) a mission.
 | |
|     Progressing a mission is usually a task of completing or progressing into a main objective.
 | |
|     Clearing an expansion base also counts here.
 | |
| 
 | |
|     Enabled: All locations fitting into this do their normal rewards
 | |
|     Trash: Forces a trash item in
 | |
|     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.
 | |
|     See also: Excluded Locations, Item Plando (https://archipelago.gg/tutorial/Archipelago/plando/en#item-plando)
 | |
|     """
 | |
|     display_name = "Mission Progress Locations"
 | |
| 
 | |
| 
 | |
| class BonusLocations(LocationInclusion):
 | |
|     """
 | |
|     Enables or disables item rewards for completing bonus tasks.
 | |
|     Bonus tasks are those giving you a campaign-wide or mission-wide bonus in vanilla game:
 | |
|     Research, credits, bonus units or resources, etc.
 | |
| 
 | |
|     Enabled: All locations fitting into this do their normal rewards
 | |
|     Trash: Forces a trash item in
 | |
|     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.
 | |
|     See also: Excluded Locations, Item Plando (https://archipelago.gg/tutorial/Archipelago/plando/en#item-plando)
 | |
|     """
 | |
|     display_name = "Bonus Locations"
 | |
| 
 | |
| 
 | |
| class ChallengeLocations(LocationInclusion):
 | |
|     """
 | |
|     Enables or disables item rewards for completing challenge tasks.
 | |
|     Challenges are tasks that have usually higher requirements to be completed
 | |
|     than to complete the mission they're in successfully.
 | |
|     You might be required to visit the same mission later when getting stronger in order to finish these tasks.
 | |
| 
 | |
|     Enabled: All locations fitting into this do their normal rewards
 | |
|     Trash: Forces a trash item in
 | |
|     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.
 | |
|     See also: Excluded Locations, Item Plando (https://archipelago.gg/tutorial/Archipelago/plando/en#item-plando)
 | |
|     """
 | |
|     display_name = "Challenge Locations"
 | |
| 
 | |
| 
 | |
| class OptionalBossLocations(LocationInclusion):
 | |
|     """
 | |
|     Enables or disables item rewards for defeating optional bosses.
 | |
|     An optional boss is any boss that's not required to kill in order to finish the mission successfully.
 | |
|     All Brutalisks, Loki, etc. belongs here.
 | |
| 
 | |
|     Enabled: All locations fitting into this do their normal rewards
 | |
|     Trash: Forces a trash item in
 | |
|     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.
 | |
|     See also: Excluded Locations, Item Plando (https://archipelago.gg/tutorial/Archipelago/plando/en#item-plando)
 | |
|     """
 | |
|     display_name = "Optional Boss Locations"
 | |
| 
 | |
| 
 | |
| # noinspection PyTypeChecker
 | |
| sc2wol_options: Dict[str, Option] = {
 | |
|     "game_difficulty": GameDifficulty,
 | |
|     "game_speed": GameSpeed,
 | |
|     "all_in_map": AllInMap,
 | |
|     "final_map": FinalMap,
 | |
|     "mission_order": MissionOrder,
 | |
|     "player_color": PlayerColor,
 | |
|     "shuffle_protoss": ShuffleProtoss,
 | |
|     "shuffle_no_build": ShuffleNoBuild,
 | |
|     "early_unit": EarlyUnit,
 | |
|     "required_tactics": RequiredTactics,
 | |
|     "units_always_have_upgrades": UnitsAlwaysHaveUpgrades,
 | |
|     "max_number_of_upgrades": MaxNumberOfUpgrades,
 | |
|     "generic_upgrade_missions": GenericUpgradeMissions,
 | |
|     "generic_upgrade_research": GenericUpgradeResearch,
 | |
|     "generic_upgrade_items": GenericUpgradeItems,
 | |
|     "locked_items": LockedItems,
 | |
|     "excluded_items": ExcludedItems,
 | |
|     "excluded_missions": ExcludedMissions,
 | |
|     "nco_items": NovaCovertOpsItems,
 | |
|     "bw_items": BroodWarItems,
 | |
|     "ext_items": ExtendedItems,
 | |
|     "mission_progress_locations": MissionProgressLocations,
 | |
|     "bonus_locations": BonusLocations,
 | |
|     "challenge_locations": ChallengeLocations,
 | |
|     "optional_boss_locations": OptionalBossLocations
 | |
| }
 | |
| 
 | |
| 
 | |
| def get_option_value(multiworld: MultiWorld, player: int, name: str) -> Union[int,  FrozenSet]:
 | |
|     if multiworld is None:
 | |
|         return sc2wol_options[name].default
 | |
| 
 | |
|     player_option = getattr(multiworld, name)[player]
 | |
| 
 | |
|     return player_option.value
 |