From 40f89873a06131d6759fdbb98ad0bb88b5e4585f Mon Sep 17 00:00:00 2001 From: SamOgon-one <114773312+SamOgon-one@users.noreply.github.com> Date: Sat, 20 Dec 2025 16:24:29 +0100 Subject: [PATCH 1/6] Fix Terran mech armor research ID issues Prevent research bugs, where Terran mech armor research does not start due to an incorrect exact_id from the protobuf Hardcode correct IDs for some reason 'exact_id' for UpgradeId.TERRANVEHICLEANDSHIPARMORSLEVEL1 is returning the ability ID 'ARMORYRESEARCHSWARM_TERRANVEHICLEANDSHIPPLATINGLEVEL1' in the protobuf, Similar for upgrade level 2 and 3 UpgradeId.TERRANVEHICLEANDSHIPARMORSLEVEL1 AbilityId.ARMORYRESEARCHSWARM_TERRANVEHICLEANDSHIPPLATINGLEVEL1 UpgradeId.TERRANVEHICLEANDSHIPARMORSLEVEL2 AbilityId.ARMORYRESEARCHSWARM_TERRANVEHICLEANDSHIPPLATINGLEVEL2 UpgradeId.TERRANVEHICLEANDSHIPARMORSLEVEL3 AbilityId.ARMORYRESEARCHSWARM_TERRANVEHICLEANDSHIPPLATINGLEVEL3 --- sc2/unit.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/sc2/unit.py b/sc2/unit.py index 07b63e90..cf754925 100644 --- a/sc2/unit.py +++ b/sc2/unit.py @@ -1337,6 +1337,32 @@ def research( :param queue: :param can_afford_check: """ + # Avoid a bug where Terran mech armor research does not start due to an incorrect exact_id from the protobuf. + # Hardcode the correct ID. + if upgrade == UpgradeId.TERRANVEHICLEANDSHIPARMORSLEVEL1: + return self( + AbilityId.ARMORYRESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL1, + queue=queue, + subtract_cost=True, + can_afford_check=can_afford_check, + ) + + if upgrade == UpgradeId.TERRANVEHICLEANDSHIPARMORSLEVEL2: + return self( + AbilityId.ARMORYRESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL2, + queue=queue, + subtract_cost=True, + can_afford_check=can_afford_check, + ) + + if upgrade == UpgradeId.TERRANVEHICLEANDSHIPARMORSLEVEL3: + return self( + AbilityId.ARMORYRESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL3, + queue=queue, + subtract_cost=True, + can_afford_check=can_afford_check, + ) + return self( self._bot_object.game_data.upgrades[upgrade.value].research_ability.exact_id, queue=queue, From 05b7ab1380a68658cd4587fbee57cc47667b06f3 Mon Sep 17 00:00:00 2001 From: SamOgon-one <114773312+SamOgon-one@users.noreply.github.com> Date: Sat, 20 Dec 2025 16:30:28 +0100 Subject: [PATCH 2/6] Fix hardcoded upgrade IDs for Terran armor research Correct hardcoded IDs for Terran vehicle and ship armor upgrades. --- sc2/unit.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sc2/unit.py b/sc2/unit.py index cf754925..08c26966 100644 --- a/sc2/unit.py +++ b/sc2/unit.py @@ -1341,24 +1341,24 @@ def research( # Hardcode the correct ID. if upgrade == UpgradeId.TERRANVEHICLEANDSHIPARMORSLEVEL1: return self( - AbilityId.ARMORYRESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL1, - queue=queue, + AbilityId.ARMORYRESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL1, + queue=queue, subtract_cost=True, can_afford_check=can_afford_check, ) if upgrade == UpgradeId.TERRANVEHICLEANDSHIPARMORSLEVEL2: return self( - AbilityId.ARMORYRESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL2, - queue=queue, + AbilityId.ARMORYRESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL2, + queue=queue, subtract_cost=True, can_afford_check=can_afford_check, ) if upgrade == UpgradeId.TERRANVEHICLEANDSHIPARMORSLEVEL3: return self( - AbilityId.ARMORYRESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL3, - queue=queue, + AbilityId.ARMORYRESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL3, + queue=queue, subtract_cost=True, can_afford_check=can_afford_check, ) From 1693ece14729af93af9d32b2891c7dea0e3ad2d7 Mon Sep 17 00:00:00 2001 From: SamOgon-one <114773312+SamOgon-one@users.noreply.github.com> Date: Thu, 5 Nov 2026 14:08:32 +0100 Subject: [PATCH 3/6] Update unit.py --- sc2/unit.py | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/sc2/unit.py b/sc2/unit.py index 08c26966..07b63e90 100644 --- a/sc2/unit.py +++ b/sc2/unit.py @@ -1337,32 +1337,6 @@ def research( :param queue: :param can_afford_check: """ - # Avoid a bug where Terran mech armor research does not start due to an incorrect exact_id from the protobuf. - # Hardcode the correct ID. - if upgrade == UpgradeId.TERRANVEHICLEANDSHIPARMORSLEVEL1: - return self( - AbilityId.ARMORYRESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL1, - queue=queue, - subtract_cost=True, - can_afford_check=can_afford_check, - ) - - if upgrade == UpgradeId.TERRANVEHICLEANDSHIPARMORSLEVEL2: - return self( - AbilityId.ARMORYRESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL2, - queue=queue, - subtract_cost=True, - can_afford_check=can_afford_check, - ) - - if upgrade == UpgradeId.TERRANVEHICLEANDSHIPARMORSLEVEL3: - return self( - AbilityId.ARMORYRESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL3, - queue=queue, - subtract_cost=True, - can_afford_check=can_afford_check, - ) - return self( self._bot_object.game_data.upgrades[upgrade.value].research_ability.exact_id, queue=queue, From b9c4a4c1d2c976ae25b4a7d63c45a092371989ff Mon Sep 17 00:00:00 2001 From: SamOgon-one <114773312+SamOgon-one@users.noreply.github.com> Date: Thu, 5 Nov 2026 14:22:07 +0100 Subject: [PATCH 4/6] Implement upgrade research ability ID overrides Added a workaround for incorrect ability IDs returned by Blizzard protobuf for certain upgrades. --- sc2/game_data.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/sc2/game_data.py b/sc2/game_data.py index 3bc4fc78..168fbef7 100644 --- a/sc2/game_data.py +++ b/sc2/game_data.py @@ -8,6 +8,7 @@ from sc2.data import Attribute, Race from sc2.ids.ability_id import AbilityId +from sc2.ids.upgrade_id import UpgradeId from sc2.ids.unit_typeid import UnitTypeId from sc2.unit_command import UnitCommand @@ -278,6 +279,12 @@ def morph_cost(self) -> Cost | None: self._proto.build_time, ) +# Workaround for Blizzard protobuf returning wrong ability IDs (ARMORYRESEARCHSWARM_...) +UPGRADE_RESEARCH_OVERRIDES: dict[UpgradeId, AbilityId] = { + UpgradeId.TERRANVEHICLEANDSHIPARMORSLEVEL1: AbilityId.ARMORYRESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL1, + UpgradeId.TERRANVEHICLEANDSHIPARMORSLEVEL2: AbilityId.ARMORYRESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL2, + UpgradeId.TERRANVEHICLEANDSHIPARMORSLEVEL3: AbilityId.ARMORYRESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL3, +} class UpgradeData: def __init__(self, game_data: GameData, proto) -> None: @@ -296,7 +303,15 @@ def name(self) -> str: return self._proto.name @property - def research_ability(self) -> AbilityData | None: + def id(self) -> UpgradeId: + return UpgradeId(self._proto.upgrade_id) + + @property + def research_ability(self) -> Optional[AbilityData]: + # Check if the upgrade has a known protobuf ability ID bug + if self.id in UPGRADE_RESEARCH_OVERRIDES: + ability_id = UPGRADE_RESEARCH_OVERRIDES[self.id].value + return self._game_data.abilities.get(ability_id) if self._proto.ability_id == 0: return None if self._proto.ability_id not in self._game_data.abilities: From aa61317f52945eadeb4a7059a68b163fec70c139 Mon Sep 17 00:00:00 2001 From: SamOgon-one <114773312+SamOgon-one@users.noreply.github.com> Date: Thu, 5 Nov 2026 14:26:37 +0100 Subject: [PATCH 5/6] Refactor research_ability to return AbilityData or None Update research_ability property to use union type for return value. --- sc2/game_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sc2/game_data.py b/sc2/game_data.py index 168fbef7..6a90ad62 100644 --- a/sc2/game_data.py +++ b/sc2/game_data.py @@ -307,7 +307,7 @@ def id(self) -> UpgradeId: return UpgradeId(self._proto.upgrade_id) @property - def research_ability(self) -> Optional[AbilityData]: + def research_ability(self) -> AbilityData | None: # Check if the upgrade has a known protobuf ability ID bug if self.id in UPGRADE_RESEARCH_OVERRIDES: ability_id = UPGRADE_RESEARCH_OVERRIDES[self.id].value From 806121cd674bb54f586db073ee29ea3aaeee025e Mon Sep 17 00:00:00 2001 From: SamOgon-one <114773312+SamOgon-one@users.noreply.github.com> Date: Thu, 5 Nov 2026 14:44:22 +0100 Subject: [PATCH 6/6] Add workaround for incorrect ability IDs in game data --- sc2/game_data.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sc2/game_data.py b/sc2/game_data.py index 6a90ad62..98e12e61 100644 --- a/sc2/game_data.py +++ b/sc2/game_data.py @@ -279,6 +279,7 @@ def morph_cost(self) -> Cost | None: self._proto.build_time, ) + # Workaround for Blizzard protobuf returning wrong ability IDs (ARMORYRESEARCHSWARM_...) UPGRADE_RESEARCH_OVERRIDES: dict[UpgradeId, AbilityId] = { UpgradeId.TERRANVEHICLEANDSHIPARMORSLEVEL1: AbilityId.ARMORYRESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL1, @@ -286,6 +287,7 @@ def morph_cost(self) -> Cost | None: UpgradeId.TERRANVEHICLEANDSHIPARMORSLEVEL3: AbilityId.ARMORYRESEARCH_TERRANVEHICLEANDSHIPPLATINGLEVEL3, } + class UpgradeData: def __init__(self, game_data: GameData, proto) -> None: """