X2DownloadableContentInfo_DLC_Day60::UpdateMissionSpawningInfo has 2 conditions for forcing a re-roll:
- Ruler is present, but shouldn't be
- XComHQ tactical tags were changed by
XComGameState_AlienRulerManager::UpdateRulerSpawningData
This was probably fine in vanilla X2, but in WOTC this gets messy. The following 2 scenarios (that I'm aware of, there could be more) will cause the game to repeatedly re-roll the schedule (note that in unmodded game this requires the Shadow Chamber to be built, but this behaviour is only observable with SC built anyway):
Ruler waiting in a facility + "normal" mission
Suppose we are using the xpack integrated mode and the Viper King just activated. It will be waiting in a facility and all other missions (the "normal") will be without a ruler.
- Assume no prior leftover ruler tags in XComHQ
- Open facility blades
- Ruler is needed -> tags added -> re-roll
- Close facility blades
- Open normal mission blades
- No ruler is needed -> leftover ruler tag in XComHQ is removed -> tags are changed -> re-roll
- Open facility blades
- Ruler is needed -> tags added -> re-roll... Oh. We are back to step 2.
And the cycle will repeat endlessly
Cycling between GOps options with Chosen present
Suppose all active rulers are loose and can appear on any mission. A set of 3 GOps spawns. Some of them have a chosen, some do not (e.g. permanently killed already). Unlike integrated facilities (where rulers force out the chosen), loose rulers give priority to the chosen (i.e. cannot appear if a chosen is appearing).
|
private function bool CanRulerAppearOnMission(XComGameState_MissionSite MissionState) |
|
{ |
|
return (!ChosenOnMission(MissionState) && !MissionSitrepsBanRulers(MissionState)); |
|
} |
| Mission |
Chosen |
Ruler |
| 1st |
Yes |
No |
| 2nd |
Yes |
No |
| 3rd |
No |
Yes |
- Assume no prior leftover ruler tags in XComHQ
- Open mission blades and cycle through the 3 options
- First mission has no ruler -> DLC2 is chill
- Second mission has no ruler -> DLC2 is chill
- Third mission has a ruler -> tags added -> re-roll
- First mission has no ruler -> leftover ruler tag in XComHQ is removed -> tags are changed -> re-roll
- Second mission has no ruler -> DLC2 is chill
- Third mission has a ruler -> tags added -> re-roll
- We are back to step 5
As such, as we keep cycling between the options, we will keep getting different schedule/enemy selection
Potential solutions
It might be tempting to just check whether the ruler is present or not (vs the desired) and use that to drive the re-rolling decision. Unfortunately, that cannot work due to additional tags:
|
private function AddRulerAdditionalTacticalTags(XComGameState_HeadquartersXCom XComHQ, int NumAppearances, AlienRulerData RulerData) |
|
{ |
|
local int idx, MaxNumAppearances, MaxAppearanceIndex; |
|
|
|
if(RulerData.AdditionalTags.Length == 0) |
|
{ |
|
return; |
|
} |
|
|
|
MaxNumAppearances = 0; |
|
MaxAppearanceIndex = 0; |
|
|
|
for(idx = 0; idx < RulerData.AdditionalTags.Length; idx++) |
|
{ |
|
if(NumAppearances == RulerData.AdditionalTags[idx].NumTimesAppeared) |
|
{ |
|
XComHQ.TacticalGameplayTags.AddItem(RulerData.AdditionalTags[idx].TacticalTag); |
|
return; |
|
} |
|
|
|
if(RulerData.AdditionalTags[idx].NumTimesAppeared > MaxNumAppearances) |
|
{ |
|
MaxNumAppearances = RulerData.AdditionalTags[idx].NumTimesAppeared; |
|
MaxAppearanceIndex = idx; |
|
} |
|
} |
|
|
|
if(NumAppearances >= MaxNumAppearances) |
|
{ |
|
XComHQ.TacticalGameplayTags.AddItem(RulerData.AdditionalTags[MaxAppearanceIndex].TacticalTag); |
|
} |
|
} |
|
function ClearActiveRulerTags(XComGameState_HeadquartersXCom XComHQ) |
|
{ |
|
local int idx, i; |
|
|
|
for(idx = 0; idx < default.AlienRulerTemplates.Length; idx++) |
|
{ |
|
// Remove the active tag |
|
XComHQ.TacticalGameplayTags.RemoveItem(default.AlienRulerTemplates[idx].ActiveTacticalTag); |
|
|
|
// Remove any additional tags |
|
for(i = 0; i < default.AlienRulerTemplates[idx].AdditionalTags.Length; i++) |
|
{ |
|
XComHQ.TacticalGameplayTags.RemoveItem(default.AlienRulerTemplates[idx].AdditionalTags[i].TacticalTag); |
|
} |
|
} |
|
} |
Using the Viper King as an example:
+AlienRulerTemplates=(AlienRulerTemplateName="ViperKing", ForceLevel=4, ActiveTacticalTag="Ruler_ViperKingActive", DeadTacticalTag="Ruler_ViperKingDead", \\
AdditionalTags[0]=(NumTimesAppeared=2, TacticalTag="Ruler_ViperKing_02"), AdditionalTags[1]=(NumTimesAppeared=3, TacticalTag="Ruler_ViperKing_03"), AdditionalTags[2]=(NumTimesAppeared=4, TacticalTag="Ruler_ViperKing_04"))
+EncounterBuckets=(EncounterBucketID="LIST_RULER_Viper", \\
EncounterIDs[0]=(EncounterID="DLC2_ViperKingx4", \\
IncludeTacticalTag="Ruler_ViperKing_04"), \\
EncounterIDs[1]=(EncounterID="DLC2_ViperKingx3", \\
IncludeTacticalTag="Ruler_ViperKing_03"), \\
EncounterIDs[2]=(EncounterID="DLC2_ViperKingx2", \\
IncludeTacticalTag="Ruler_ViperKing_02"), \\
EncounterIDs[3]=(EncounterID="DLC2_ViperKingx1"), \\
)
+ConfigurableEncounters=(EncounterID="DLC2_ViperKingx1", \\
MaxSpawnCount=1, \\
ForceSpawnTemplateNames[0]="ViperKing", \\
bGroupDoesNotAwardLoot=true)
+ConfigurableEncounters=(EncounterID="DLC2_ViperKingx2", \\
MaxSpawnCount=2, \\
ForceSpawnTemplateNames[0]="ViperKing", \\
ForceSpawnTemplateNames[1]="Viper", \\
bGroupDoesNotAwardLoot=true)
Here we can see that the 2nd time you see the King, he will be accompanied by an escort of a single viper and this is achieved via the additional tags. Checking only the presence/absence of ViperKing will overlook this behaviour.
Ideally, we would just store the tags that were used to generate the current schedule (although the comparison logic won't be simple, since we can't just naively compare 1:1 like the current logic does), but everything is native, so we would need to do so via a game state component (or other similar means)
|
struct native X2SelectedMissionData |
|
{ |
|
// The Alert Level for which this mission data is valid |
|
var() int AlertLevel; |
|
|
|
// The Force Level for which this mission data is valid |
|
var() int ForceLevel; |
|
|
|
// The name of the mission schedule which has been selected for this mission |
|
var() Name SelectedMissionScheduleName; |
|
|
|
// The list of encounters which have been selected for this mission |
|
var() array<X2SelectedEncounterData> SelectedEncounters; |
|
}; |
|
|
|
// Mission data that has been selected for this Mission Site. |
|
var() X2SelectedMissionData SelectedMissionData; |
X2DownloadableContentInfo_DLC_Day60::UpdateMissionSpawningInfohas 2 conditions for forcing a re-roll:XComGameState_AlienRulerManager::UpdateRulerSpawningDataThis was probably fine in vanilla X2, but in WOTC this gets messy. The following 2 scenarios (that I'm aware of, there could be more) will cause the game to repeatedly re-roll the schedule (note that in unmodded game this requires the Shadow Chamber to be built, but this behaviour is only observable with SC built anyway):
Ruler waiting in a facility + "normal" mission
Suppose we are using the xpack integrated mode and the Viper King just activated. It will be waiting in a facility and all other missions (the "normal") will be without a ruler.
And the cycle will repeat endlessly
Cycling between GOps options with Chosen present
Suppose all active rulers are loose and can appear on any mission. A set of 3 GOps spawns. Some of them have a chosen, some do not (e.g. permanently killed already). Unlike integrated facilities (where rulers force out the chosen), loose rulers give priority to the chosen (i.e. cannot appear if a chosen is appearing).
X2WOTCCommunityHighlander/Components/DLC2CommunityHighlander/DLC2CommunityHighlander/Src/DLC_2/Classes/XComGameState_AlienRulerManager.uc
Lines 607 to 610 in e000ea3
As such, as we keep cycling between the options, we will keep getting different schedule/enemy selection
Potential solutions
It might be tempting to just check whether the ruler is present or not (vs the desired) and use that to drive the re-rolling decision. Unfortunately, that cannot work due to additional tags:
X2WOTCCommunityHighlander/Components/DLC2CommunityHighlander/DLC2CommunityHighlander/Src/DLC_2/Classes/XComGameState_AlienRulerManager.uc
Lines 151 to 182 in e000ea3
X2WOTCCommunityHighlander/Components/DLC2CommunityHighlander/DLC2CommunityHighlander/Src/DLC_2/Classes/XComGameState_AlienRulerManager.uc
Lines 387 to 402 in e000ea3
Using the Viper King as an example:
Here we can see that the 2nd time you see the King, he will be accompanied by an escort of a single viper and this is achieved via the additional tags. Checking only the presence/absence of
ViperKingwill overlook this behaviour.Ideally, we would just store the tags that were used to generate the current schedule (although the comparison logic won't be simple, since we can't just naively compare 1:1 like the current logic does), but everything is native, so we would need to do so via a game state component (or other similar means)
X2WOTCCommunityHighlander/X2WOTCCommunityHighlander/Src/XComGame/Classes/XComGameState_MissionSite.uc
Lines 81 to 97 in e000ea3