Nice job.
Looks like you have reasonable code. Here are a few suggestions.
You can remove the {} around your CreateResearchTrigger lines. It's not technically wrong, but it's weird. The braces create a new code block, with a new scope for variables. There is no point to do this here. Blocks are mostly used to group code to control execution flow, such as around function bodies, if/else statements, for/do/while loops, and exception handler try/catch blocks. Unless you have a very good reason to control local variable scope and lifetime, you should probably avoid using {} outside of those contexts. In your case, there is no flow control there, and there are no local variables defined within the block, so it does nothing.
As for the comment "Forces a player to play as Eden", I find "force" sounds weird. There usually is no choice for things like colony games. The level chooses for the player. It's essentially a "set" method, to use a more common term. The level can always change the decision later by calling the method again. That would be weird to call it again though. Less weird would be to have the level use a random number and set the colony type using an if statement. In multiplayer, the method would override what the player chooses, so in that sense I suppose you're correct.
The ScriptGlobal code looks right. There still needs to be a GetSaveRegions export that tells Outpost 2 about that struct. In RequiredExports.h there is a macro to define that function for you. The macro definition looks like this:
// Generate function to return global variable struct to Outpost2.exe for game save/load
#define ExportSaveLoadData(globalVarStructName) \
Export void __cdecl GetSaveRegions(BufferDesc& bufferDesc) \
{ \
bufferDesc.bufferStart = &globalVarStructName; \
bufferDesc.length = sizeof(globalVarStructName); \
}
You can use this macro after defining your struct and declaring a variable of that struct type. You can even define the struct and declare a variable of that type together. Note the variable name at the end of the struct declaration, before the semicolon. This let's you save a line of code. After that, the macro expands to the function definition that Outpost 2 calls to find your struct.
struct ScriptGlobal
{
int researchChoice;
} scriptGlobal;
ExportSaveLoadData(scriptGlobal);
If you had no global data to save/load from saved game files, you could use the alternative macro:
// Generate function to return a lack of global variables for game save/load
#define ExportSaveLoadDataNone() \
Export void __cdecl GetSaveRegions(BufferDesc& bufferDesc) \
{ \
bufferDesc.bufferStart = 0; \
bufferDesc.length = 0; \
}
You might want to update some of the comments for the trigger callback functions.
For your example tech file, you can unlock the chosen research tree using:
// Unlock the chosen tech tree
Player[0].MarkResearchComplete(6102 + scriptGlobal.researchChoice);
That eliminates the key differences between your two methods. The other minor difference is removing the choice techs, but you can just remove both by marking them as complete, including the one that just finished. Having no differences allows you to extract the guts of the trigger callbacks into one common function with a parameter for researchChoice, like I alluded to in an earlier post.