diff --git a/worlds/sc2/locations.py b/worlds/sc2/locations.py index 63f1aa2eacc9..2cd65d5b8c78 100644 --- a/worlds/sc2/locations.py +++ b/worlds/sc2/locations.py @@ -1554,23 +1554,23 @@ def get_locations(world: Optional['SC2World']) -> Tuple[LocationData, ...]: logic.zerg_competent_comp_competent_aa ), make_location_data(SC2Mission.THE_RECKONING.mission_name, "Victory", SC2HOTS_LOC_ID_OFFSET + 2000, LocationType.VICTORY, - logic.the_reckoning_requirement + logic.zerg_the_reckoning_requirement ), make_location_data(SC2Mission.THE_RECKONING.mission_name, "South Lane", SC2HOTS_LOC_ID_OFFSET + 2001, LocationType.VANILLA, - logic.the_reckoning_requirement + logic.zerg_the_reckoning_requirement ), make_location_data(SC2Mission.THE_RECKONING.mission_name, "North Lane", SC2HOTS_LOC_ID_OFFSET + 2002, LocationType.VANILLA, - logic.the_reckoning_requirement + logic.zerg_the_reckoning_requirement ), make_location_data(SC2Mission.THE_RECKONING.mission_name, "East Lane", SC2HOTS_LOC_ID_OFFSET + 2003, LocationType.VANILLA, - logic.the_reckoning_requirement + logic.zerg_the_reckoning_requirement ), make_location_data(SC2Mission.THE_RECKONING.mission_name, "Odin", SC2HOTS_LOC_ID_OFFSET + 2004, LocationType.EXTRA, - logic.the_reckoning_requirement + logic.zerg_the_reckoning_requirement ), make_location_data(SC2Mission.THE_RECKONING.mission_name, "Trash the Odin Early", SC2HOTS_LOC_ID_OFFSET + 2005, LocationType.MASTERY, lambda state: ( - logic.the_reckoning_requirement(state) + logic.zerg_the_reckoning_requirement(state) and state.has_any({item_names.INFESTOR, item_names.DEFILER}, player) and (not logic.take_over_ai_allies or logic.terran_base_trasher(state))), flags=LocationFlag.SPEEDRUN @@ -4232,6 +4232,50 @@ def get_locations(world: Optional['SC2World']) -> Tuple[LocationData, ...]: make_location_data(SC2Mission.DEATH_FROM_ABOVE_P.mission_name, "Main Path Command Center", SC2_RACESWAP_LOC_ID_OFFSET + 9605, LocationType.EXTRA, logic.protoss_competent_comp ), + make_location_data(SC2Mission.THE_RECKONING_T.mission_name, "Victory", SC2_RACESWAP_LOC_ID_OFFSET + 9700, LocationType.VICTORY, + logic.terran_the_reckoning_requirement + ), + make_location_data(SC2Mission.THE_RECKONING_T.mission_name, "South Lane", SC2_RACESWAP_LOC_ID_OFFSET + 9701, LocationType.VANILLA, + logic.terran_the_reckoning_requirement + ), + make_location_data(SC2Mission.THE_RECKONING_T.mission_name, "North Lane", SC2_RACESWAP_LOC_ID_OFFSET + 9702, LocationType.VANILLA, + logic.terran_the_reckoning_requirement + ), + make_location_data(SC2Mission.THE_RECKONING_T.mission_name, "East Lane", SC2_RACESWAP_LOC_ID_OFFSET + 9703, LocationType.VANILLA, + logic.terran_the_reckoning_requirement + ), + make_location_data(SC2Mission.THE_RECKONING_T.mission_name, "Odin", SC2_RACESWAP_LOC_ID_OFFSET + 9704, LocationType.EXTRA, + logic.terran_the_reckoning_requirement + ), + make_location_data(SC2Mission.THE_RECKONING_T.mission_name, "Trash the Odin Early", SC2_RACESWAP_LOC_ID_OFFSET + 9705, LocationType.MASTERY, + lambda state: ( + logic.terran_the_reckoning_requirement(state) + and logic.terran_base_trasher(state) + ), + flags=LocationFlag.SPEEDRUN + ), + make_location_data(SC2Mission.THE_RECKONING_P.mission_name, "Victory", SC2_RACESWAP_LOC_ID_OFFSET + 9800, LocationType.VICTORY, + logic.protoss_the_reckoning_requirement + ), + make_location_data(SC2Mission.THE_RECKONING_P.mission_name, "South Lane", SC2_RACESWAP_LOC_ID_OFFSET + 9801, LocationType.VANILLA, + logic.protoss_the_reckoning_requirement + ), + make_location_data(SC2Mission.THE_RECKONING_P.mission_name, "North Lane", SC2_RACESWAP_LOC_ID_OFFSET + 9802, LocationType.VANILLA, + logic.protoss_the_reckoning_requirement + ), + make_location_data(SC2Mission.THE_RECKONING_P.mission_name, "East Lane", SC2_RACESWAP_LOC_ID_OFFSET + 9803, LocationType.VANILLA, + logic.protoss_the_reckoning_requirement + ), + make_location_data(SC2Mission.THE_RECKONING_P.mission_name, "Odin", SC2_RACESWAP_LOC_ID_OFFSET + 9804, LocationType.EXTRA, + logic.protoss_the_reckoning_requirement + ), + make_location_data(SC2Mission.THE_RECKONING_P.mission_name, "Trash the Odin Early", SC2_RACESWAP_LOC_ID_OFFSET + 9805, LocationType.MASTERY, + lambda state: ( + logic.protoss_the_reckoning_requirement(state) + and logic.protoss_fleet(state) + and (not logic.take_over_ai_allies or logic.terran_base_trasher(state))), + flags=LocationFlag.SPEEDRUN + ), ] beat_events = [] diff --git a/worlds/sc2/mission_tables.py b/worlds/sc2/mission_tables.py index 216ffce00b55..991eb1c870d8 100644 --- a/worlds/sc2/mission_tables.py +++ b/worlds/sc2/mission_tables.py @@ -152,7 +152,7 @@ def __init__(self, mission_id: int, name: str, campaign: SC2Campaign, area: str, CONVICTION = 46, "Conviction", SC2Campaign.HOTS, "Dominion Space", SC2Race.ANY, MissionPools.MEDIUM, "ap_conviction", MissionFlag.Zerg|MissionFlag.Kerrigan|MissionFlag.NoBuild|MissionFlag.VsTerran PLANETFALL = 47, "Planetfall (Zerg)", SC2Campaign.HOTS, "Korhal", SC2Race.ZERG, MissionPools.HARD, "ap_planetfall", MissionFlag.Zerg|MissionFlag.Kerrigan|MissionFlag.AutoScroller|MissionFlag.VsTerran|MissionFlag.HasRaceSwap DEATH_FROM_ABOVE = 48, "Death From Above (Zerg)", SC2Campaign.HOTS, "Korhal", SC2Race.ZERG, MissionPools.HARD, "ap_death_from_above", MissionFlag.Zerg|MissionFlag.Kerrigan|MissionFlag.VsTerran|MissionFlag.HasRaceSwap - THE_RECKONING = 49, "The Reckoning", SC2Campaign.HOTS, "Korhal", SC2Race.ZERG, MissionPools.VERY_HARD, "ap_the_reckoning", MissionFlag.Zerg|MissionFlag.Kerrigan|MissionFlag.VsTerran|MissionFlag.AiTerranAlly + THE_RECKONING = 49, "The Reckoning (Zerg)", SC2Campaign.HOTS, "Korhal", SC2Race.ZERG, MissionPools.VERY_HARD, "ap_the_reckoning", MissionFlag.Zerg|MissionFlag.Kerrigan|MissionFlag.VsTerran|MissionFlag.AiTerranAlly|MissionFlag.HasRaceSwap # Prologue DARK_WHISPERS = 50, "Dark Whispers", SC2Campaign.PROLOGUE, "_1", SC2Race.PROTOSS, MissionPools.EASY, "ap_dark_whispers", MissionFlag.Protoss|MissionFlag.Countdown|MissionFlag.VsTZ @@ -274,7 +274,42 @@ def __init__(self, mission_id: int, name: str, campaign: SC2Campaign, area: str, PLANETFALL_P = 177, "Planetfall (Protoss)", SC2Campaign.HOTS, "Korhal", SC2Race.PROTOSS, MissionPools.HARD, "ap_planetfall", MissionFlag.Protoss|MissionFlag.AutoScroller|MissionFlag.VsTerran|MissionFlag.RaceSwap DEATH_FROM_ABOVE_T = 178, "Death From Above (Terran)", SC2Campaign.HOTS, "Korhal", SC2Race.TERRAN, MissionPools.HARD, "ap_death_from_above", MissionFlag.Terran|MissionFlag.VsTerran|MissionFlag.RaceSwap DEATH_FROM_ABOVE_P = 179, "Death From Above (Protoss)", SC2Campaign.HOTS, "Korhal", SC2Race.PROTOSS, MissionPools.HARD, "ap_death_from_above", MissionFlag.Protoss|MissionFlag.VsTerran|MissionFlag.RaceSwap - # 180/181 - The Reckoning + THE_RECKONING_T = 180, "The Reckoning (Terran)", SC2Campaign.HOTS, "Korhal", SC2Race.TERRAN, MissionPools.VERY_HARD, "ap_the_reckoning", MissionFlag.Terran|MissionFlag.VsTerran|MissionFlag.AiTerranAlly|MissionFlag.RaceSwap + THE_RECKONING_P = 181, "The Reckoning (Protoss)", SC2Campaign.HOTS, "Korhal", SC2Race.PROTOSS, MissionPools.VERY_HARD, "ap_the_reckoning", MissionFlag.Protoss|MissionFlag.VsTerran|MissionFlag.AiTerranAlly|MissionFlag.RaceSwap + # 182/183 - Dark Whispers + # 184/185 - Ghosts in the Fog + # 186/187 - Evil Awoken + # 188/189 - For Aiur! + # 190/191 - The Growing Shadow + # 192/193 - The Spear of Adun + # 194/195 - Sky Shield + # 196/197 - Brothers in Arms + # 198/199 - Amon's Reach + # 200/201 - Last Stand + # 202/203 - Forbidden Weapon + # 204/205 - Temple of Unification + # 206/207 - The Infinite Cycle + # 208/209 - Harbinger of Oblivion + # 210/211 - Unsealing the Past + # 212/213 - Purification + # 214/215 - Steps of the Rite + # 216/217 - Rak'Shir + # 218/219 - Templar's Charge + # 220/221 - Templar's Return + # 222/223 - The Host + # 224/225 - Salvation + # 226/227 - Into the Void + # 228/229 - The Essence of Eternity + # 230/231 - Amon's Fall + # 232/233 - The Escape + # 234/235 - Sudden Strike + # 236/237 - Enemy Intelligence + # 238/239 - Trouble In Paradise + # 240/241 - Night Terrors + # 242/243 - Flashpoint + # 244/245 - In the Enemy's Shadow + # 246/247 - Dark Skies + # 248/249 - End Game class MissionConnection: diff --git a/worlds/sc2/options.py b/worlds/sc2/options.py index 82540bb73b6c..8dc87447b187 100644 --- a/worlds/sc2/options.py +++ b/worlds/sc2/options.py @@ -152,7 +152,7 @@ class MaximumCampaignSize(Range): """ display_name = "Maximum Campaign Size" range_start = 1 - range_end = 141 + range_end = 143 default = 83 diff --git a/worlds/sc2/rules.py b/worlds/sc2/rules.py index 3161b39ee537..bd4f99e08052 100644 --- a/worlds/sc2/rules.py +++ b/worlds/sc2/rules.py @@ -1105,7 +1105,7 @@ def protoss_infested_garrison_claimer(self, state: CollectionState) -> bool: or self.protoss_can_merge_dark_archon(state) ) - def the_reckoning_requirement(self, state: CollectionState) -> bool: + def zerg_the_reckoning_requirement(self, state: CollectionState) -> bool: if self.take_over_ai_allies: return ( self.terran_competent_comp(state) @@ -1123,6 +1123,25 @@ def the_reckoning_requirement(self, state: CollectionState) -> bool: and self.zerg_very_hard_mission_weapon_armor_level(state) ) + def terran_the_reckoning_requirement(self, state: CollectionState) -> bool: + return ( + self.terran_very_hard_mission_weapon_armor_level(state) + and self.terran_beats_protoss_deathball(state) + ) + + def protoss_the_reckoning_requirement(self, state: CollectionState) -> bool: + return ( + self.protoss_very_hard_mission_weapon_armor_level(state) + and self.protoss_competent_comp(state) + and ( + not self.take_over_ai_allies + or ( + self.terran_competent_comp(state) + and self.terran_very_hard_mission_weapon_armor_level(state) + ) + ) + ) + # LotV def protoss_army_weapon_armor_upgrade_min_level(self, state: CollectionState) -> int: count: int = WEAPON_ARMOR_UPGRADE_MAX_LEVEL + 1 # +1 for Quatro