diff --git a/worlds/sc2/item_descriptions.py b/worlds/sc2/item_descriptions.py index 573eefa89926..3db569ae1f53 100644 --- a/worlds/sc2/item_descriptions.py +++ b/worlds/sc2/item_descriptions.py @@ -750,6 +750,7 @@ def _ability_desc(unit_name_plural: str, ability_name: str, ability_description: item_names.ARBITER: "Army support craft. Has the Stasis Field and Recall abilities. Cloaks nearby units.", item_names.ORACLE: "Flying caster. Can use the Revelation and Stasis Ward abilities.", item_names.SKYLORD: "Capital ship. Builds and launches Interceptors that attack enemy targets. Can use Tactical Jump ability.", + item_names.PURGER: "Capital ship. Builds and launches Interceptors that attack enemy targets. Has Solar Beam weapon.", item_names.PROGRESSIVE_PROTOSS_GROUND_WEAPON: GENERIC_UPGRADE_TEMPLATE.format("damage", PROTOSS, "ground units"), item_names.PROGRESSIVE_PROTOSS_GROUND_ARMOR: GENERIC_UPGRADE_TEMPLATE.format("armor", PROTOSS, "ground units"), item_names.PROGRESSIVE_PROTOSS_SHIELDS: GENERIC_UPGRADE_TEMPLATE.format("shields", PROTOSS, "units"), @@ -798,8 +799,8 @@ def _ability_desc(unit_name_plural: str, ability_name: str, ability_description: item_names.ARBITER_SPACETIME_ANCHOR: "Arbiter Stasis Field lasts 50 seconds longer.", item_names.ARBITER_RESOURCE_EFFICIENCY: _get_resource_efficiency_desc(item_names.ARBITER), item_names.ARBITER_ENHANCED_CLOAK_FIELD: "Increases Arbiter Cloaking Field range.", - item_names.CARRIER_SKYLORD_GRAVITON_CATAPULT: "Carriers can launch Interceptors more quickly.", - item_names.CARRIER_SKYLORD_HULL_OF_PAST_GLORIES: "Carriers gain +2 armour.", + item_names.CARRIER_SKYLORD_PURGER_GRAVITON_CATAPULT: "Carriers can launch Interceptors more quickly.", + item_names.CARRIER_SKYLORD_PURGER_HULL_OF_PAST_GLORIES: "Carriers gain +2 armour.", item_names.VOID_RAY_DESTROYER_WARP_RAY_SCORCHER_FLUX_VANES: "Increases Void Ray and Destroyer movement speed.", item_names.DESTROYER_REFORGED_BLOODSHARD_CORE: "When fully charged, the Destroyer's Destruction Beam weapon does full damage to secondary targets.", item_names.WARP_PRISM_GRAVITIC_DRIVE: "Increases the movement speed of Warp Prisms.", diff --git a/worlds/sc2/item_groups.py b/worlds/sc2/item_groups.py index fb0d0417eb4d..f98a99f06264 100644 --- a/worlds/sc2/item_groups.py +++ b/worlds/sc2/item_groups.py @@ -533,7 +533,7 @@ def get_all_group_names(cls) -> typing.Set[str]: item_name_groups[ItemGroupNames.STARGATE_UNITS] = stargate_units = [ item_names.PHOENIX, item_names.MIRAGE, item_names.CORSAIR, item_names.VOID_RAY, item_names.DESTROYER, item_names.WARP_RAY, item_names.SCORCHER, - item_names.CARRIER, item_names.SKYLORD, + item_names.CARRIER, item_names.SKYLORD, item_names.PURGER, item_names.TEMPEST, item_names.SCOUT, item_names.MOTHERSHIP, item_names.ARBITER, item_names.ORACLE, ] @@ -559,7 +559,7 @@ def get_all_group_names(cls) -> typing.Set[str]: item_name_groups[ItemGroupNames.PURIFIER_UNITS] = [ item_names.SENTINEL, item_names.ADEPT, item_names.INSTIGATOR, item_names.ENERGIZER, item_names.STALWART, item_names.COLOSSUS, item_names.DISRUPTOR, - item_names.MIRAGE, item_names.SCORCHER, item_names.TEMPEST, + item_names.MIRAGE, item_names.SCORCHER, item_names.PURGER, item_names.TEMPEST, ] item_name_groups[ItemGroupNames.SOA_ITEMS] = soa_items = [ *[item_name for item_name, item_data in items.item_table.items() if item_data.type == items.ProtossItemType.Spear_Of_Adun], diff --git a/worlds/sc2/item_names.py b/worlds/sc2/item_names.py index 52becf5d6140..491102c12426 100644 --- a/worlds/sc2/item_names.py +++ b/worlds/sc2/item_names.py @@ -540,6 +540,7 @@ VOID_RAY = "Void Ray" CARRIER = "Carrier" SKYLORD = "Skylord" +PURGER = "Purger" OBSERVER = "Observer" CENTURION = "Centurion" SENTINEL = "Sentinel" @@ -630,8 +631,8 @@ ARBITER_SPACETIME_ANCHOR = "Spacetime Anchor (Arbiter)" ARBITER_RESOURCE_EFFICIENCY = "Resource Efficiency (Arbiter)" ARBITER_ENHANCED_CLOAK_FIELD = "Enhanced Cloak Field (Arbiter)" -CARRIER_SKYLORD_GRAVITON_CATAPULT = "Graviton Catapult (Carrier/Skylord)" -CARRIER_SKYLORD_HULL_OF_PAST_GLORIES = "Hull of Past Glories (Carrier/Skylord)" +CARRIER_SKYLORD_PURGER_GRAVITON_CATAPULT = "Graviton Catapult (Carrier/Skylord/Purger)" +CARRIER_SKYLORD_PURGER_HULL_OF_PAST_GLORIES = "Hull of Past Glories (Carrier/Skylord/Purger)" VOID_RAY_DESTROYER_WARP_RAY_SCORCHER_FLUX_VANES = "Flux Vanes (Void Ray/Destroyer/Warp Ray/Scorcher)" DESTROYER_REFORGED_BLOODSHARD_CORE = "Reforged Bloodshard Core (Destroyer)" WARP_PRISM_GRAVITIC_DRIVE = "Gravitic Drive (Warp Prism)" diff --git a/worlds/sc2/items.py b/worlds/sc2/items.py index 466c6cb08378..3c7818db485c 100644 --- a/worlds/sc2/items.py +++ b/worlds/sc2/items.py @@ -1590,6 +1590,9 @@ def get_full_item_list(): item_names.SKYLORD: ItemData(33 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Unit_2, 12, SC2Race.PROTOSS, classification=ItemClassification.progression, origin={"ext"}), + item_names.PURGER: + ItemData(34 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Unit_2, 13, SC2Race.PROTOSS, + classification=ItemClassification.progression, origin={"ext"}), # Protoss Upgrades item_names.PROGRESSIVE_PROTOSS_GROUND_WEAPON: ItemData(100 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Upgrade, 0, SC2Race.PROTOSS, quantity=WEAPON_ARMOR_UPGRADE_MAX_LEVEL, origin={"wol", "lotv"}), @@ -1643,9 +1646,9 @@ def get_full_item_list(): item_names.ARBITER_SPACETIME_ANCHOR: ItemData(330 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_2, 0, SC2Race.PROTOSS, origin={"bw"}, parent_item=item_names.ARBITER), item_names.ARBITER_RESOURCE_EFFICIENCY: ItemData(331 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_2, 1, SC2Race.PROTOSS, classification=ItemClassification.filler, origin={"bw"}, parent_item=item_names.ARBITER), item_names.ARBITER_ENHANCED_CLOAK_FIELD: ItemData(332 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_2, 2, SC2Race.PROTOSS, classification=ItemClassification.filler, origin={"bw"}, parent_item=item_names.ARBITER), - item_names.CARRIER_SKYLORD_GRAVITON_CATAPULT: + item_names.CARRIER_SKYLORD_PURGER_GRAVITON_CATAPULT: ItemData(333 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_2, 3, SC2Race.PROTOSS, origin={"wol"}), - item_names.CARRIER_SKYLORD_HULL_OF_PAST_GLORIES: + item_names.CARRIER_SKYLORD_PURGER_HULL_OF_PAST_GLORIES: ItemData(334 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_2, 4, SC2Race.PROTOSS, origin={"bw"}), item_names.VOID_RAY_DESTROYER_WARP_RAY_SCORCHER_FLUX_VANES: ItemData(335 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_2, 5, SC2Race.PROTOSS, classification=ItemClassification.filler, diff --git a/worlds/sc2/pool_filter.py b/worlds/sc2/pool_filter.py index 23c3ca28f68c..da8a73f40c63 100644 --- a/worlds/sc2/pool_filter.py +++ b/worlds/sc2/pool_filter.py @@ -510,9 +510,9 @@ def attempt_removal(item: Item) -> bool: if not {item_names.VOID_RAY, item_names.DESTROYER, item_names.WARP_RAY, item_names.SCORCHER} & logical_inventory_set: inventory = [item for item in inventory if not item.name.endswith("(Void Ray/Destroyer/Warp Ray/Scorcher)")] unused_items = [item_name for item_name in unused_items if not item_name.endswith("(Void Ray/Destroyer/Warp Ray/Scorcher)")] - if not {item_names.CARRIER, item_names.SKYLORD} & logical_inventory_set: - inventory = [item for item in inventory if not item.name.endswith("(Carrier/Skylord)")] - unused_items = [item_name for item_name in unused_items if not item_name.endswith("(Carrier/Skylord)")] + if not {item_names.CARRIER, item_names.SKYLORD, item_names.PURGER} & logical_inventory_set: + inventory = [item for item in inventory if not item.name.endswith("(Carrier/Skylord/Purger)")] + unused_items = [item_name for item_name in unused_items if not item_name.endswith("(Carrier/Skylord/Purger)")] if not {item_names.IMMORTAL, item_names.ANNIHILATOR, item_names.STALWART} & logical_inventory_set: inventory = [item for item in inventory if not item.name.endswith("(Immortal/Annihilator/Stalwart)")] unused_items = [item_name for item_name in unused_items if not item_name.endswith("(Immortal/Annihilator/Stalwart)")] diff --git a/worlds/sc2/rules.py b/worlds/sc2/rules.py index 2ebfdcf74714..58b983a4c19f 100644 --- a/worlds/sc2/rules.py +++ b/worlds/sc2/rules.py @@ -501,7 +501,7 @@ def protoss_anti_light_anti_air(self, state: CollectionState) -> bool: def protoss_competent_anti_air(self, state: CollectionState) -> bool: return state.has_any({ item_names.STALKER, item_names.SLAYER, item_names.INSTIGATOR, item_names.DRAGOON, item_names.ADEPT, - item_names.VOID_RAY, item_names.DESTROYER, item_names.TEMPEST + item_names.VOID_RAY, item_names.DESTROYER, item_names.TEMPEST, item_names.PURGER }, self.player) \ or ( state.has_any({ @@ -525,8 +525,8 @@ def protoss_has_blink(self, state: CollectionState) -> bool: def protoss_can_attack_behind_chasm(self, state: CollectionState) -> bool: return state.has_any({ - item_names.SCOUT, item_names.TEMPEST, item_names.CARRIER, item_names.SKYLORD, item_names.VOID_RAY, - item_names.DESTROYER, item_names.WARP_RAY, item_names.SCORCHER, item_names.MOTHERSHIP + item_names.SCOUT, item_names.TEMPEST, item_names.CARRIER, item_names.SKYLORD, item_names.PURGER, + item_names.VOID_RAY, item_names.DESTROYER, item_names.WARP_RAY, item_names.SCORCHER, item_names.MOTHERSHIP }, self.player) \ or self.protoss_has_blink(state) \ or (state.has(item_names.WARP_PRISM, self.player) @@ -536,8 +536,8 @@ def protoss_can_attack_behind_chasm(self, state: CollectionState) -> bool: def protoss_fleet(self, state: CollectionState) -> bool: return state.has_any({ - item_names.CARRIER, item_names.SKYLORD, item_names.TEMPEST, item_names.VOID_RAY, item_names.DESTROYER, - item_names.WARP_RAY, item_names.SCORCHER + item_names.CARRIER, item_names.SKYLORD, item_names.PURGER, item_names.TEMPEST, item_names.VOID_RAY, + item_names.DESTROYER, item_names.WARP_RAY, item_names.SCORCHER }, self.player) def templars_return_requirement(self, state: CollectionState) -> bool: @@ -577,11 +577,17 @@ def protoss_hybrid_counter(self, state: CollectionState) -> bool: """ Ground Hybrids """ - return state.has_any( - {item_names.ANNIHILATOR, item_names.ASCENDANT, item_names.TEMPEST, item_names.CARRIER, item_names.SKYLORD, - item_names.VOID_RAY, item_names.WARP_RAY, item_names.WRATHWALKER, item_names.VANGUARD}, self.player) \ - or (state.has_any({item_names.IMMORTAL, item_names.STALWART}, self.player) or self.advanced_tactics) and state.has_any( - {item_names.STALKER, item_names.DRAGOON, item_names.ADEPT, item_names.INSTIGATOR, item_names.SLAYER}, self.player) + return ( + state.has_any({ + item_names.ANNIHILATOR, item_names.ASCENDANT, item_names.TEMPEST, item_names.CARRIER, + item_names.SKYLORD, item_names.PURGER, item_names.VOID_RAY, item_names.WARP_RAY, + item_names.WRATHWALKER, item_names.VANGUARD + }, self.player) + or (state.has_any({item_names.IMMORTAL, item_names.STALWART}, self.player) or self.advanced_tactics) + and state.has_any({ + item_names.STALKER, item_names.DRAGOON, item_names.ADEPT, item_names.INSTIGATOR, item_names.SLAYER + }, self.player) + ) def the_infinite_cycle_requirement(self, state: CollectionState) -> bool: return self.story_tech_granted \ @@ -703,7 +709,7 @@ def amons_fall_requirement(self, state: CollectionState) -> bool: if self.take_over_ai_allies: return ( ( - state.has_any({item_names.BATTLECRUISER, item_names.CARRIER, item_names.SKYLORD}, self.player) + state.has_any({item_names.BATTLECRUISER, item_names.CARRIER, item_names.SKYLORD, item_names.PURGER}, self.player) ) or (state.has(item_names.ULTRALISK, self.player) and self.protoss_competent_anti_air(state)