From 4dcd977321b13a577e749445cf78b249d5a5146c Mon Sep 17 00:00:00 2001 From: Matthew Date: Sat, 27 Jul 2024 00:17:26 -0700 Subject: [PATCH 1/6] sc2: Skirmisher war council upgrade -- peer contempt --- worlds/sc2/client.py | 1 + worlds/sc2/item_descriptions.py | 20 ++++++++++++++++++++ worlds/sc2/item_names.py | 8 ++++++++ worlds/sc2/items.py | 9 +++++++++ 4 files changed, 38 insertions(+) diff --git a/worlds/sc2/client.py b/worlds/sc2/client.py index 8da95011e520..feab82a0ff36 100644 --- a/worlds/sc2/client.py +++ b/worlds/sc2/client.py @@ -917,6 +917,7 @@ def calculate_items(ctx: SC2Context) -> typing.Dict[SC2Race, typing.List[int]]: # War council option if not ctx.nerf_unit_baselines: accumulators[SC2Race.PROTOSS][ProtossItemType.War_Council.flag_word] = (1 << 30) - 1 + accumulators[SC2Race.PROTOSS][ProtossItemType.War_Council_2.flag_word] = (1 << 30) - 1 # Deprecated Orbital Command handling (Backwards compatibility): if orbital_command_count > 0: diff --git a/worlds/sc2/item_descriptions.py b/worlds/sc2/item_descriptions.py index 3cad3a5a18b3..21fd817937e1 100644 --- a/worlds/sc2/item_descriptions.py +++ b/worlds/sc2/item_descriptions.py @@ -870,7 +870,27 @@ def _ability_desc(unit_name_plural: str, ability_name: str, ability_description: item_names.ENERGIZER_MOBILE_CHRONO_BEAM: "Energizer War Council upgrade. Allows Energizers to use Chrono Beam in Mobile Mode.", item_names.HAVOC_ENDURING_SIGHT: "Havoc War Council upgrade. Havoc Squad Sight stays up indefinitely and no longer takes energy.", item_names.HIGH_TEMPLAR_PLASMA_SURGE: "High Templar War Council upgrade. High Templar Psionic Storm will heal fiendly protoss shields under it.", + # Signifier + # Ascendant item_names.DARK_ARCHON_INDOMITABLE_WILL: "Dark Archon War Council upgrade. Casting Mind Control will no longer deplete the Dark Archon's shields.", + # Immortal + # Annihilator + # Vanguard + # Stalwart + # Colossus + # Wrathwalker + # Reaver + # Disruptor + # Warp Prism + # Observer + # Phoenix + # Corsair + # Mirage + item_names.SKIRMISHER_PEER_CONTEMPT: "Skirmisher War Council upgrade. Allows Skirmishers to target air units.", + # Void Ray + # Destroyer + # Warp Ray + # Dawnbringer item_names.SOA_CHRONO_SURGE: "The Spear of Adun increases a target structure's unit warp in and research speeds by +1000% for 20 seconds.", item_names.SOA_PROGRESSIVE_PROXY_PYLON: inspect.cleandoc(""" Level 1: The Spear of Adun quickly warps in a Pylon to a target location. diff --git a/worlds/sc2/item_names.py b/worlds/sc2/item_names.py index 6fb78ba15cd0..ce36f2302cc7 100644 --- a/worlds/sc2/item_names.py +++ b/worlds/sc2/item_names.py @@ -717,6 +717,14 @@ # Disruptor # Warp Prism # Observer +# Phoenix +# Corsair +# Mirage +SKIRMISHER_PEER_CONTEMPT = "Peer Contempt (Skirmisher)" +# Void Ray +# Destroyer +# Warp Ray +# Dawnbringer # Spear Of Adun SOA_CHRONO_SURGE = "Chrono Surge (Spear of Adun Calldown)" diff --git a/worlds/sc2/items.py b/worlds/sc2/items.py index e40adbfed342..b23acd38ed39 100644 --- a/worlds/sc2/items.py +++ b/worlds/sc2/items.py @@ -79,6 +79,7 @@ class ProtossItemType(ItemTypeEnum): Forge_3 = "Forge", 9 """General Protoss unit upgrades""" War_Council = "War Council", 10 + War_Council_2 = "War Council", 11 class FactionlessItemType(ItemTypeEnum): @@ -1760,6 +1761,14 @@ def get_full_item_list(): # 525 reserved for Disruptor # 526 reserved for Warp Prism # 527 reserved for Observer + # 530 reserved for Phoenix + # 531 reserved for Corsair + # 532 reserved for Mirage + item_names.SKIRMISHER_PEER_CONTEMPT: ItemData(533 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.War_Council_2, 3, SC2Race.PROTOSS, parent_item=item_names.SKIRMISHER), + # 534 reserved for Void Ray + # 535 reserved for Destroyer + # 536 reserved for Warp Ray + # 537 reserved for Dawnbringer # SoA Calldown powers item_names.SOA_CHRONO_SURGE: ItemData(700 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Spear_Of_Adun, 0, SC2Race.PROTOSS, origin={"lotv"}), From 778988c3538b62c71d7f38a781ebba7cf3b81100 Mon Sep 17 00:00:00 2001 From: Matthew Date: Sat, 27 Jul 2024 18:13:55 -0700 Subject: [PATCH 2/6] sc2: Added Vanguard war council upgrades -- Fusion Mortars and Rapidfire Cannons --- worlds/sc2/item_descriptions.py | 3 ++- worlds/sc2/item_names.py | 3 ++- worlds/sc2/items.py | 17 +++++++++-------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/worlds/sc2/item_descriptions.py b/worlds/sc2/item_descriptions.py index 21fd817937e1..ec45c8b7580c 100644 --- a/worlds/sc2/item_descriptions.py +++ b/worlds/sc2/item_descriptions.py @@ -875,7 +875,8 @@ def _ability_desc(unit_name_plural: str, ability_name: str, ability_description: item_names.DARK_ARCHON_INDOMITABLE_WILL: "Dark Archon War Council upgrade. Casting Mind Control will no longer deplete the Dark Archon's shields.", # Immortal # Annihilator - # Vanguard + item_names.VANGUARD_RAPIDFIRE_CANNON: "Vanguard War Council upgrade. Vanguards attack 37% faster.", + item_names.VANGUARD_FUSION_MORTARS: "Vanguard War Council upgrade. Vanguards deal +7 damage to armored targets per attack.", # Stalwart # Colossus # Wrathwalker diff --git a/worlds/sc2/item_names.py b/worlds/sc2/item_names.py index ce36f2302cc7..c76c7c5092eb 100644 --- a/worlds/sc2/item_names.py +++ b/worlds/sc2/item_names.py @@ -709,7 +709,8 @@ DARK_ARCHON_INDOMITABLE_WILL = "Indomitable Will (Dark Archon)" # IMMORTAL_IMPROVED_BARRIER = "Improved Barrier (Immortal)" # Annihilator -# Vanguard +VANGUARD_RAPIDFIRE_CANNON = "Rapid-Fire Cannon (Vanguard)" +VANGUARD_FUSION_MORTARS = "Fusion Mortars (Vanguard)" # Stalwart # Colossus # Wrathwalker diff --git a/worlds/sc2/items.py b/worlds/sc2/items.py index b23acd38ed39..5c4260aa6ab2 100644 --- a/worlds/sc2/items.py +++ b/worlds/sc2/items.py @@ -1753,14 +1753,15 @@ def get_full_item_list(): item_names.DARK_ARCHON_INDOMITABLE_WILL: ItemData(518 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.War_Council, 18, SC2Race.PROTOSS), # 518 reserved for Immortal # 519 reserved for Annihilator - # 520 reserved for Vanguard - # 521 reserved for Stalwart - # 522 reserved for Colossus - # 523 reserved for Wrathwalker - # 524 reserved for Reaver - # 525 reserved for Disruptor - # 526 reserved for Warp Prism - # 527 reserved for Observer + item_names.VANGUARD_RAPIDFIRE_CANNON: ItemData(520 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.War_Council, 20, SC2Race.PROTOSS, parent_item=item_names.VANGUARD), + item_names.VANGUARD_FUSION_MORTARS: ItemData(521 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.War_Council, 21, SC2Race.PROTOSS, parent_item=item_names.VANGUARD), + # 522 reserved for Stalwart + # 523 reserved for Colossus + # 524 reserved for Wrathwalker + # 525 reserved for Reaver + # 526 reserved for Disruptor + # 527 reserved for Warp Prism + # 528 reserved for Observer # 530 reserved for Phoenix # 531 reserved for Corsair # 532 reserved for Mirage From 3ac805888fceda9c52b5526ad3f33ed0faa25f9c Mon Sep 17 00:00:00 2001 From: Matthew Date: Sat, 27 Jul 2024 18:15:40 -0700 Subject: [PATCH 3/6] sc2: Fixing off-by-one in vanguard rapidfire cannon description --- worlds/sc2/item_descriptions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worlds/sc2/item_descriptions.py b/worlds/sc2/item_descriptions.py index ec45c8b7580c..390c347428e6 100644 --- a/worlds/sc2/item_descriptions.py +++ b/worlds/sc2/item_descriptions.py @@ -875,7 +875,7 @@ def _ability_desc(unit_name_plural: str, ability_name: str, ability_description: item_names.DARK_ARCHON_INDOMITABLE_WILL: "Dark Archon War Council upgrade. Casting Mind Control will no longer deplete the Dark Archon's shields.", # Immortal # Annihilator - item_names.VANGUARD_RAPIDFIRE_CANNON: "Vanguard War Council upgrade. Vanguards attack 37% faster.", + item_names.VANGUARD_RAPIDFIRE_CANNON: "Vanguard War Council upgrade. Vanguards attack 38% faster.", item_names.VANGUARD_FUSION_MORTARS: "Vanguard War Council upgrade. Vanguards deal +7 damage to armored targets per attack.", # Stalwart # Colossus From 49e31257da1d52ee866317043fdafeb58e3d106c Mon Sep 17 00:00:00 2001 From: Matthew Date: Sat, 27 Jul 2024 20:17:08 -0700 Subject: [PATCH 4/6] sc2: Fixed duplicate key in options --- worlds/sc2/options.py | 1 - 1 file changed, 1 deletion(-) diff --git a/worlds/sc2/options.py b/worlds/sc2/options.py index 7ae8238bdc5b..9fa0e4acdd53 100644 --- a/worlds/sc2/options.py +++ b/worlds/sc2/options.py @@ -935,7 +935,6 @@ class StartingSupplyPerItem(Range): @dataclass class Starcraft2Options(PerGameCommonOptions): - selected_races: SelectRaces game_difficulty: GameDifficulty game_speed: GameSpeed disable_forced_camera: DisableForcedCamera From 4cc5da5a94bc4812db64fab2569f2db9291b138b Mon Sep 17 00:00:00 2001 From: Matthew Date: Sun, 28 Jul 2024 01:05:22 -0700 Subject: [PATCH 5/6] sc2: Updating phoenix-class items to properly include skirmisher in description, name, and filtering logic --- worlds/sc2/item_descriptions.py | 4 ++-- worlds/sc2/item_names.py | 4 ++-- worlds/sc2/items.py | 4 ++-- worlds/sc2/pool_filter.py | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/worlds/sc2/item_descriptions.py b/worlds/sc2/item_descriptions.py index 3cad3a5a18b3..78a9c84ea061 100644 --- a/worlds/sc2/item_descriptions.py +++ b/worlds/sc2/item_descriptions.py @@ -793,8 +793,8 @@ def _ability_desc(unit_name_plural: str, ability_name: str, ability_description: item_names.TEMPEST_TECTONIC_DESTABILIZERS: "Tempests deal increased damage to buildings.", item_names.TEMPEST_QUANTIC_REACTOR: "Tempests deal increased damage to massive units.", item_names.TEMPEST_GRAVITY_SLING: "Tempests gain +8 range against air targets.", - item_names.PHOENIX_MIRAGE_IONIC_WAVELENGTH_FLUX: "Increases Phoenix and Mirage weapon damage by +2.", - item_names.PHOENIX_MIRAGE_ANION_PULSE_CRYSTALS: "Increases Phoenix and Mirage range by +2.", + item_names.PHOENIX_CLASS_IONIC_WAVELENGTH_FLUX: "Increases Phoenix, Mirage, and Skirmisher weapon damage by +2.", + item_names.PHOENIX_CLASS_ANION_PULSE_CRYSTALS: "Increases Phoenix, Mirage, and Skirmiser range by +2.", item_names.CORSAIR_STEALTH_DRIVE: "Corsairs become permanently cloaked.", item_names.CORSAIR_ARGUS_JEWEL: "Corsairs can store 2 charges of disruption web.", item_names.CORSAIR_SUSTAINING_DISRUPTION: "Corsair disruption webs last longer.", diff --git a/worlds/sc2/item_names.py b/worlds/sc2/item_names.py index 6fb78ba15cd0..ac60dc2478db 100644 --- a/worlds/sc2/item_names.py +++ b/worlds/sc2/item_names.py @@ -625,8 +625,8 @@ TEMPEST_TECTONIC_DESTABILIZERS = "Tectonic Destabilizers (Tempest)" TEMPEST_QUANTIC_REACTOR = "Quantic Reactor (Tempest)" TEMPEST_GRAVITY_SLING = "Gravity Sling (Tempest)" -PHOENIX_MIRAGE_IONIC_WAVELENGTH_FLUX = "Ionic Wavelength Flux (Phoenix/Mirage)" -PHOENIX_MIRAGE_ANION_PULSE_CRYSTALS = "Anion Pulse-Crystals (Phoenix/Mirage)" +PHOENIX_CLASS_IONIC_WAVELENGTH_FLUX = "Ionic Wavelength Flux (Phoenix/Mirage/Skirmisher)" +PHOENIX_CLASS_ANION_PULSE_CRYSTALS = "Anion Pulse-Crystals (Phoenix/Mirage/Skirmisher)" CORSAIR_STEALTH_DRIVE = "Stealth Drive (Corsair)" CORSAIR_ARGUS_JEWEL = "Argus Jewel (Corsair)" CORSAIR_SUSTAINING_DISRUPTION = "Sustaining Disruption (Corsair)" diff --git a/worlds/sc2/items.py b/worlds/sc2/items.py index e40adbfed342..da2694700660 100644 --- a/worlds/sc2/items.py +++ b/worlds/sc2/items.py @@ -1657,8 +1657,8 @@ def get_full_item_list(): item_names.TEMPEST_TECTONIC_DESTABILIZERS: ItemData(316 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_1, 16, SC2Race.PROTOSS, classification=ItemClassification.filler, origin={"ext"}, parent_item=item_names.TEMPEST), item_names.TEMPEST_QUANTIC_REACTOR: ItemData(317 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_1, 17, SC2Race.PROTOSS, classification=ItemClassification.filler, origin={"ext"}, parent_item=item_names.TEMPEST), item_names.TEMPEST_GRAVITY_SLING: ItemData(318 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_1, 18, SC2Race.PROTOSS, origin={"ext"}, parent_item=item_names.TEMPEST), - item_names.PHOENIX_MIRAGE_IONIC_WAVELENGTH_FLUX: ItemData(319 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_1, 19, SC2Race.PROTOSS, origin={"ext"}), - item_names.PHOENIX_MIRAGE_ANION_PULSE_CRYSTALS: ItemData(320 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_1, 20, SC2Race.PROTOSS, origin={"ext"}), + item_names.PHOENIX_CLASS_IONIC_WAVELENGTH_FLUX: ItemData(319 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_1, 19, SC2Race.PROTOSS, origin={"ext"}), + item_names.PHOENIX_CLASS_ANION_PULSE_CRYSTALS: ItemData(320 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_1, 20, SC2Race.PROTOSS, origin={"ext"}), item_names.CORSAIR_STEALTH_DRIVE: ItemData(321 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_1, 21, SC2Race.PROTOSS, origin={"ext"}, parent_item=item_names.CORSAIR), item_names.CORSAIR_ARGUS_JEWEL: ItemData(322 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_1, 22, SC2Race.PROTOSS, origin={"bw"}, parent_item=item_names.CORSAIR), item_names.CORSAIR_SUSTAINING_DISRUPTION: ItemData(323 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_1, 23, SC2Race.PROTOSS, origin={"bw"}, parent_item=item_names.CORSAIR), diff --git a/worlds/sc2/pool_filter.py b/worlds/sc2/pool_filter.py index 31e7ebf873dc..c2ebd002676f 100644 --- a/worlds/sc2/pool_filter.py +++ b/worlds/sc2/pool_filter.py @@ -509,9 +509,9 @@ def attempt_removal(item: Item) -> bool: if not {item_names.STALKER, item_names.INSTIGATOR, item_names.SLAYER} & logical_inventory_set: inventory = [item for item in inventory if not item.name.endswith("(Stalker/Instigator/Slayer)")] unused_items = [item_name for item_name in unused_items if not item_name.endswith("(Stalker/Instigator/Slayer)")] - if not {item_names.PHOENIX, item_names.MIRAGE} & logical_inventory_set: - inventory = [item for item in inventory if not item.name.endswith("(Phoenix/Mirage)")] - unused_items = [item_name for item_name in unused_items if not item_name.endswith("(Phoenix/Mirage)")] + if not {item_names.PHOENIX, item_names.MIRAGE, item_names.SKIRMISHER} & logical_inventory_set: + inventory = [item for item in inventory if not item.name.endswith("(Phoenix/Mirage/Skirmisher)")] + unused_items = [item_name for item_name in unused_items if not item_name.endswith("(Phoenix/Mirage/Skirmisher)")] if not {item_names.VOID_RAY, item_names.DESTROYER, item_names.WARP_RAY, item_names.DAWNBRINGER} & logical_inventory_set: inventory = [item for item in inventory if not item.name.endswith("(Void Ray/Destroyer/Warp Ray/Dawnbringer)")] unused_items = [item_name for item_name in unused_items if not item_name.endswith("(Void Ray/Destroyer/Warp Ray/Dawnbringer)")] From 0d80d73b54b487996161585ddde80f9430d34408 Mon Sep 17 00:00:00 2001 From: Matthew Date: Sun, 28 Jul 2024 01:18:37 -0700 Subject: [PATCH 6/6] sc2: Updated logic so skirmisher is only considered AA with peer contempt --- worlds/sc2/items.py | 2 +- worlds/sc2/rules.py | 32 +++++++++++++++++++------------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/worlds/sc2/items.py b/worlds/sc2/items.py index 5c4260aa6ab2..895f54592d96 100644 --- a/worlds/sc2/items.py +++ b/worlds/sc2/items.py @@ -1765,7 +1765,7 @@ def get_full_item_list(): # 530 reserved for Phoenix # 531 reserved for Corsair # 532 reserved for Mirage - item_names.SKIRMISHER_PEER_CONTEMPT: ItemData(533 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.War_Council_2, 3, SC2Race.PROTOSS, parent_item=item_names.SKIRMISHER), + item_names.SKIRMISHER_PEER_CONTEMPT: ItemData(533 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.War_Council_2, 3, SC2Race.PROTOSS, classification=ItemClassification.progression, parent_item=item_names.SKIRMISHER), # 534 reserved for Void Ray # 535 reserved for Destroyer # 536 reserved for Warp Ray diff --git a/worlds/sc2/rules.py b/worlds/sc2/rules.py index 504e5f6d09df..d8a98d630f49 100644 --- a/worlds/sc2/rules.py +++ b/worlds/sc2/rules.py @@ -584,28 +584,34 @@ def protoss_anti_armor_anti_air(self, state: CollectionState) -> bool: and state.has(item_names.IMMORTAL_ANNIHILATOR_STALWART_ADVANCED_TARGETING_MECHANICS, self.player)) def protoss_anti_light_anti_air(self, state: CollectionState) -> bool: - return self.protoss_competent_anti_air(state) \ + return ( + self.protoss_competent_anti_air(state) or state.has_any({ - item_names.PHOENIX, item_names.MIRAGE, item_names.SKIRMISHER, item_names.CORSAIR, item_names.CARRIER, + item_names.PHOENIX, item_names.MIRAGE, item_names.CORSAIR, item_names.CARRIER, }, self.player) + or state.has_all((item_names.SKIRMISHER, item_names.SKIRMISHER_PEER_CONTEMPT), self.player) + ) 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.SKYLORD, item_names.PURGER - }, self.player) \ - or ( + 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.SKYLORD, item_names.PURGER + }, self.player) + or (( state.has_any({ - item_names.PHOENIX, item_names.MIRAGE, item_names.SKIRMISHER, - item_names.CORSAIR, item_names.CARRIER, - }, self.player) - and state.has_any({ - item_names.SCOUT, item_names.WRATHWALKER, item_names.WARP_RAY + item_names.PHOENIX, item_names.MIRAGE, item_names.CORSAIR, item_names.CARRIER, }, self.player) - ) \ + or state.has_all((item_names.SKIRMISHER, item_names.SKIRMISHER_PEER_CONTEMPT), self.player) + ) + and state.has_any({ + item_names.SCOUT, item_names.WRATHWALKER, item_names.WARP_RAY + }, self.player) + ) or (self.advanced_tactics and state.has_any({item_names.IMMORTAL, item_names.ANNIHILATOR, item_names.STALWART}, self.player) and state.has(item_names.IMMORTAL_ANNIHILATOR_STALWART_ADVANCED_TARGETING_MECHANICS, self.player)) + ) def protoss_has_blink(self, state: CollectionState) -> bool: return state.has_any({item_names.STALKER, item_names.INSTIGATOR, item_names.SLAYER}, self.player) \