SC2: Fix Conviction logic for Grant Story Tech (#5419)
* Fix Conviction logic for Grant Story Tech - Kinetic Blast and Crushing Grip is available for the mission if story tech is granted * Review updates
This commit is contained in:
@@ -2341,8 +2341,7 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
||||
SC2HOTS_LOC_ID_OFFSET + 200,
|
||||
LocationType.VICTORY,
|
||||
lambda state: logic.basic_kerrigan(state)
|
||||
or kerriganless
|
||||
or logic.grant_story_tech == GrantStoryTech.option_grant,
|
||||
or kerriganless,
|
||||
hard_rule=logic.zerg_any_units_back_in_the_saddle_requirement,
|
||||
),
|
||||
make_location_data(
|
||||
@@ -2351,8 +2350,7 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
||||
SC2HOTS_LOC_ID_OFFSET + 201,
|
||||
LocationType.EXTRA,
|
||||
lambda state: logic.basic_kerrigan(state)
|
||||
or kerriganless
|
||||
or logic.grant_story_tech == GrantStoryTech.option_grant,
|
||||
or kerriganless,
|
||||
hard_rule=logic.zerg_any_units_back_in_the_saddle_requirement,
|
||||
),
|
||||
make_location_data(
|
||||
@@ -2379,8 +2377,7 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
||||
SC2HOTS_LOC_ID_OFFSET + 205,
|
||||
LocationType.EXTRA,
|
||||
lambda state: logic.basic_kerrigan(state)
|
||||
or kerriganless
|
||||
or logic.grant_story_tech == GrantStoryTech.option_grant,
|
||||
or kerriganless,
|
||||
hard_rule=logic.zerg_any_units_back_in_the_saddle_requirement,
|
||||
),
|
||||
make_location_data(
|
||||
@@ -2446,7 +2443,7 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
||||
lambda state: (
|
||||
logic.zerg_competent_comp(state)
|
||||
and logic.zerg_competent_anti_air(state)
|
||||
and (logic.basic_kerrigan(state) or kerriganless)
|
||||
and (logic.basic_kerrigan(state, False) or kerriganless)
|
||||
and logic.zerg_defense_rating(state, False, False) >= 3
|
||||
and logic.zerg_power_rating(state) >= 5
|
||||
),
|
||||
@@ -3530,7 +3527,7 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
||||
kerriganless
|
||||
or (
|
||||
logic.two_kerrigan_actives(state)
|
||||
and (logic.basic_kerrigan(state) or logic.grant_story_tech == GrantStoryTech.option_grant)
|
||||
and logic.basic_kerrigan(state)
|
||||
and logic.kerrigan_levels(state, 25)
|
||||
)
|
||||
),
|
||||
@@ -3554,7 +3551,7 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
||||
kerriganless
|
||||
or (
|
||||
logic.two_kerrigan_actives(state)
|
||||
and (logic.basic_kerrigan(state) or logic.grant_story_tech == GrantStoryTech.option_grant)
|
||||
and logic.basic_kerrigan(state)
|
||||
and logic.kerrigan_levels(state, 25)
|
||||
)
|
||||
),
|
||||
|
||||
@@ -1127,8 +1127,10 @@ class SC2Logic:
|
||||
|
||||
return levels >= target
|
||||
|
||||
def basic_kerrigan(self, state: CollectionState) -> bool:
|
||||
# One active ability that can be used to defeat enemies directly on Standard
|
||||
def basic_kerrigan(self, state: CollectionState, story_tech_available=True) -> bool:
|
||||
if story_tech_available and self.grant_story_tech == GrantStoryTech.option_grant:
|
||||
return True
|
||||
# One active ability that can be used to defeat enemies directly
|
||||
if not state.has_any(
|
||||
(
|
||||
item_names.KERRIGAN_LEAPING_STRIKE,
|
||||
@@ -1149,7 +1151,9 @@ class SC2Logic:
|
||||
return True
|
||||
return False
|
||||
|
||||
def two_kerrigan_actives(self, state: CollectionState) -> bool:
|
||||
def two_kerrigan_actives(self, state: CollectionState, story_tech_available=True) -> bool:
|
||||
if story_tech_available and self.grant_story_tech == GrantStoryTech.option_grant:
|
||||
return True
|
||||
count = 0
|
||||
for i in range(7):
|
||||
if state.has_any(kerrigan_logic_active_abilities, self.player):
|
||||
@@ -2396,7 +2400,7 @@ class SC2Logic:
|
||||
return (
|
||||
self.zerg_competent_comp(state)
|
||||
and (self.zerg_competent_anti_air(state) or self.advanced_tactics and self.zerg_moderate_anti_air(state))
|
||||
and (self.basic_kerrigan(state) or self.zerg_power_rating(state) >= 4)
|
||||
and (self.basic_kerrigan(state, False) or self.zerg_power_rating(state) >= 4)
|
||||
)
|
||||
|
||||
def protoss_hand_of_darkness_requirement(self, state: CollectionState) -> bool:
|
||||
@@ -2412,7 +2416,7 @@ class SC2Logic:
|
||||
return self.protoss_deathball(state) and self.protoss_power_rating(state) >= 8
|
||||
|
||||
def zerg_the_reckoning_requirement(self, state: CollectionState) -> bool:
|
||||
if not (self.zerg_power_rating(state) >= 6 or self.basic_kerrigan(state)):
|
||||
if not (self.zerg_power_rating(state) >= 6 or self.basic_kerrigan(state, False)):
|
||||
return False
|
||||
if self.take_over_ai_allies:
|
||||
return (
|
||||
@@ -2460,20 +2464,22 @@ class SC2Logic:
|
||||
|
||||
def the_infinite_cycle_requirement(self, state: CollectionState) -> bool:
|
||||
return (
|
||||
self.grant_story_tech == GrantStoryTech.option_grant
|
||||
or not self.kerrigan_unit_available
|
||||
or (
|
||||
state.has_any(
|
||||
(
|
||||
item_names.KERRIGAN_KINETIC_BLAST,
|
||||
item_names.KERRIGAN_SPAWN_BANELINGS,
|
||||
item_names.KERRIGAN_LEAPING_STRIKE,
|
||||
item_names.KERRIGAN_SPAWN_LEVIATHAN,
|
||||
),
|
||||
self.player,
|
||||
self.kerrigan_levels(state, 70)
|
||||
and (
|
||||
self.grant_story_tech == GrantStoryTech.option_grant
|
||||
or not self.kerrigan_unit_available
|
||||
or (
|
||||
state.has_any(
|
||||
(
|
||||
item_names.KERRIGAN_KINETIC_BLAST,
|
||||
item_names.KERRIGAN_SPAWN_BANELINGS,
|
||||
item_names.KERRIGAN_LEAPING_STRIKE,
|
||||
item_names.KERRIGAN_SPAWN_LEVIATHAN,
|
||||
),
|
||||
self.player,
|
||||
)
|
||||
and self.basic_kerrigan(state)
|
||||
)
|
||||
and self.basic_kerrigan(state)
|
||||
and self.kerrigan_levels(state, 70)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
Unit tests for world generation
|
||||
"""
|
||||
from typing import *
|
||||
|
||||
from .test_base import Sc2SetupTestBase
|
||||
|
||||
from .. import mission_groups, mission_tables, options, locations, SC2Mission, SC2Campaign, SC2Race, unreleased_items, \
|
||||
|
||||
@@ -6,7 +6,9 @@ from .test_base import Sc2SetupTestBase
|
||||
from .. import get_all_missions, mission_tables, options
|
||||
from ..item import item_groups, item_tables, item_names
|
||||
from ..mission_tables import SC2Race, SC2Mission, SC2Campaign, MissionFlag
|
||||
from ..options import EnabledCampaigns, MasteryLocations
|
||||
from ..options import EnabledCampaigns, MasteryLocations, MissionOrder, EnableRaceSwapVariants, ShuffleCampaigns, \
|
||||
ShuffleNoBuild, StarterUnit, RequiredTactics, KerriganPresence, KerriganLevelItemDistribution, GrantStoryTech, \
|
||||
GrantStoryLevels
|
||||
|
||||
|
||||
class TestSupportedUseCases(Sc2SetupTestBase):
|
||||
@@ -490,3 +492,39 @@ class TestSupportedUseCases(Sc2SetupTestBase):
|
||||
|
||||
self.assertTupleEqual(terran_nonmerc_units, ())
|
||||
self.assertTupleEqual(zerg_nonmerc_units, ())
|
||||
|
||||
def test_all_kerrigan_missions_are_nobuild_and_grant_story_tech_is_on(self) -> None:
|
||||
# The actual situation the bug got caught
|
||||
world_options = {
|
||||
'mission_order': MissionOrder.option_vanilla_shuffled,
|
||||
'selected_races': [
|
||||
SC2Race.TERRAN.get_title(),
|
||||
SC2Race.ZERG.get_title(),
|
||||
SC2Race.PROTOSS.get_title(),
|
||||
],
|
||||
'enabled_campaigns': [
|
||||
SC2Campaign.WOL.campaign_name,
|
||||
SC2Campaign.PROPHECY.campaign_name,
|
||||
SC2Campaign.HOTS.campaign_name,
|
||||
SC2Campaign.PROLOGUE.campaign_name,
|
||||
SC2Campaign.LOTV.campaign_name,
|
||||
SC2Campaign.EPILOGUE.campaign_name,
|
||||
SC2Campaign.NCO.campaign_name,
|
||||
],
|
||||
'enable_race_swap': EnableRaceSwapVariants.option_shuffle_all_non_vanilla, # Causes no build Kerrigan missions to be present, only nobuilds remain
|
||||
'shuffle_campaigns': ShuffleCampaigns.option_true,
|
||||
'shuffle_no_build': ShuffleNoBuild.option_true,
|
||||
'starter_unit': StarterUnit.option_balanced,
|
||||
'required_tactics': RequiredTactics.option_standard,
|
||||
'kerrigan_presence': KerriganPresence.option_vanilla,
|
||||
'kerrigan_levels_per_mission_completed': 0,
|
||||
'kerrigan_levels_per_mission_completed_cap': -1,
|
||||
'kerrigan_level_item_sum': 87,
|
||||
'kerrigan_level_item_distribution': KerriganLevelItemDistribution.option_size_7,
|
||||
'kerrigan_total_level_cap': -1,
|
||||
'start_primary_abilities': 0,
|
||||
'grant_story_tech': GrantStoryTech.option_grant,
|
||||
'grant_story_levels': GrantStoryLevels.option_additive,
|
||||
}
|
||||
self.generate_world(world_options)
|
||||
# Just check that the world itself generates under those rules and no exception is thrown
|
||||
|
||||
Reference in New Issue
Block a user