diff --git a/worlds/sc2/client.py b/worlds/sc2/client.py index fb6c0e4f1aea..c17c2284d664 100644 --- a/worlds/sc2/client.py +++ b/worlds/sc2/client.py @@ -35,7 +35,7 @@ VanillaLocations, DisableForcedCamera, SkipCutscenes, GrantStoryTech, GrantStoryLevels, TakeOverAIAllies, RequiredTactics, SpearOfAdunPresence, SpearOfAdunPresentInNoBuild, SpearOfAdunAutonomouslyCastAbilityPresence, - SpearOfAdunAutonomouslyCastPresentInNoBuild, EnableVoidTrade + SpearOfAdunAutonomouslyCastPresentInNoBuild, EnableVoidTrade, DifficultyDamageModifier ) from .mission_order.structs import CampaignSlotData, LayoutSlotData, MissionSlotData, MissionEntryRules from .mission_order.entry_rules import SubRuleRuleData, CountMissionsRuleData @@ -394,12 +394,13 @@ def _cmd_option(self, option_name: str = "", option_value: str = "") -> None: ConfigurableOptionInfo('no_forced_camera', 'disable_forced_camera', options.DisableForcedCamera), ConfigurableOptionInfo('skip_cutscenes', 'skip_cutscenes', options.SkipCutscenes), ConfigurableOptionInfo('enable_morphling', 'enable_morphling', options.EnableMorphling, can_break_logic=True), + ConfigurableOptionInfo('difficulty_damage_modifier', 'difficulty_damage_modifier', options.DifficultyDamageModifier), ) WARNING_COLOUR = "salmon" CMD_COLOUR = "slateblue" boolean_option_map = { - 'y': 'true', 'yes': 'true', 'n': 'false', 'no': 'false', + 'y': 'true', 'yes': 'true', 'n': 'false', 'no': 'false', 'true': 'true', 'false': 'false', } help_message = ColouredMessage(inspect.cleandoc(""" @@ -419,7 +420,7 @@ def _cmd_option(self, option_name: str = "", option_value: str = "") -> None: return for option in configurable_options: if option_name == option.name: - option_value = boolean_option_map.get(option_value, option_value) + option_value = boolean_option_map.get(option_value.lower(), option_value) if not option_value: pass elif option.option_type == ConfigurableOptionType.ENUM and option_value in option.option_class.options: @@ -630,6 +631,7 @@ def __init__(self, *args, **kwargs) -> None: self.trade_lock_wait: int = 0 self.trade_lock_start: typing.Optional[int] = None self.trade_response: typing.Optional[str] = None + self.difficulty_damage_modifier: int = DifficultyDamageModifier.default async def server_auth(self, password_requested: bool = False) -> None: self.game = STARCRAFT2 @@ -781,6 +783,7 @@ def on_package(self, cmd: str, args: dict) -> None: self.maximum_supply_per_item = args["slot_data"].get("maximum_supply_per_item", 2) self.nova_covert_ops_only = args["slot_data"].get("nova_covert_ops_only", False) self.trade_enabled = args["slot_data"].get("enable_void_trade", EnableVoidTrade.option_false) + self.difficulty_damage_modifier = args["slot_data"].get("difficulty_damage_modifier", DifficultyDamageModifier.option_true) if self.required_tactics == RequiredTactics.option_no_logic: # Locking Grant Story Tech/Levels if no logic @@ -1542,6 +1545,7 @@ async def on_step(self, iteration: int): f" {self.ctx.enable_morphling}" f" {mission_variant}" f" {self.ctx.trade_enabled}" + f" {self.ctx.difficulty_damage_modifier}" ) await self.update_resources(start_items) await self.update_terran_tech(start_items) diff --git a/worlds/sc2/options.py b/worlds/sc2/options.py index 75b415edcdf9..234d2dbc8cd8 100644 --- a/worlds/sc2/options.py +++ b/worlds/sc2/options.py @@ -91,6 +91,14 @@ class GameDifficulty(Choice): default = 1 +class DifficultyDamageModifier(DefaultOnToggle): + """ + Enables or disables vanilla difficulty-based damage received modifier + Handles the 1.25 Brutal damage modifier in HotS and Prologue and 0.5 Casual damage modifier outside WoL and Prophecy + """ + display_name = "Difficulty Damage Modifier" + + class GameSpeed(Choice): """Optional setting to override difficulty-based game speed.""" display_name = "Game Speed" @@ -1029,6 +1037,7 @@ class MaximumSupplyPerItem(Range): class Starcraft2Options(PerGameCommonOptions): start_inventory: Sc2StartInventory game_difficulty: GameDifficulty + difficulty_damage_modifier: DifficultyDamageModifier game_speed: GameSpeed disable_forced_camera: DisableForcedCamera skip_cutscenes: SkipCutscenes