X2CommunityCore / X2WOTCCommunityHighlander

https://steamcommunity.com/workshop/filedetails/?id=1134256495
MIT License
60 stars 69 forks source link

No valid maps cause an infinite geoscape hang on mission generation #1302

Open Tedster59 opened 8 months ago

Tedster59 commented 8 months ago

In XComGameState_MissionSite, Sitreps are added to missions before a map is rolled. This causes an issue when mods allow for multiple sitreps, which can mark plot types as excluded.

XComGameState_MissionSite.SelectBiomeAndPlotDefinition has this while loop:

image

SelectPlotDefinition excludes maps based on biome, so once it goes through all maps in a biome, it calls SelectBiome to select the next one. However, SelectBiome returns an empty string if no valid Biomes exist instead of a biome, meaning the loops safety condition is never hit and it will infinitely loop calling SelectPlotDefinition again and again.

(Debugging done in LW code that duplicates the function) Note the blank string being added to the exclude list in the below logging.

image

Options to fix:

  1. Bugfix: Fix the short circuit condition. Solves the infinite hang but results in a potentially invalid map for the mission type as it just defaults to the very first thing in the arrPlots array.
  2. Enhancement: Create logic to select an alternative map and then remove sitreps invalid for that plot type from the mission after the fact. I've implemented this in LWoTC beta. Commit here
  3. Alternative: Redo mission generation so plot is rolled before sitrep choice, and sitreps are chosen afterwards based on the plot selected.
Tedster59 commented 8 months ago

So the fix I implemented in LWoTC requires modifying the parameters of SelectBiomeAndPlotDefinition and SelectPlotDefinition to be able to pass through an additional array parameter for sitreps to remove. I'm not sure where that sits on CHL backwards compatibility policy as changing those would break other mods using them, so it might require an alternative implementation using variables that exist at the gamestate object level instead.