Slight update for anyone finding this. The newer version of the SDK uses "Export" rathre than "SCRIPT_API".
I took another look at the code that processes the "DescBlockEx" export today.
Details:
The DescBlockEx related code does not exist in the CD version of Outpost 2 (1.2.0.5). Outpost2.exe does not reference it. No levels from the CD install contain a "DescBlockEx" export. It was added in the official Sierra release update pack 1 (1.2.0.7). In the update, the executable file, and two levels (
ml2_21.dll and
ml4_21.dll) use "DescBlockEx".
From the most recent executable, the DescBlockEx export is referenced in exactly 1 place, in the method:
00402780 Function: GetNumAiPlayers([ECX] char* scriptName):int* numAiPlayers
In this method, the code retrieves a pointer to the "DescBlockEx" export, then allocates 4 bytes of memory, and copies the first 4 bytes from DescBlockEx export into the allocated buffer, and returns a pointer to this buffer. As this is the only reference to "DescBlockEx" in the executable file, it seems only the first 4 bytes are ever used.
Looking at the two DLL files, the struct is a maximum of 32 bytes. In both DLLs there is another unrelated global variable 32 bytes beyond the DescBlockEx export. In both DLLs, there is a lack of references to the addresses between the start of the DescBlock export, and the next referenced variable 32 bytes later. This suggests there are no other global variables in that region, and strongly implies all 32 bytes belong to the same DescBlockEx variable, or are padding/alignment bytes after/between variables. As neither the DescBlockEx export, nor the following global variable are 32-byte aligned, and the following variable has no need of anything more than 4-byte alignment, it is unlikely all this empty data is purely for padding/alignment. The size is likely 29-32 bytes, most likely being the full 32 bytes. A size of 32 bytes can hold 8
ints.
In both DLLs, the first 4 bytes contain the value 1 (numAiPlayers), and the remainder are filled with 0. The DescBlockEx export appeared immediately after the DescBlock export (though that is not a requirement, just an obvious place to put it).
Summary:
You could get away with only exporting 4 bytes (a bit messy):
Export int DescBlockEx = 1; // numAiPlayers
Though I would recommend exporting the full struct (the struct name is arbitrary):
struct WhateverStructNameYouWant {
int numAiPlayers;
int unused1;
int unused2;
int unused3;
int unused4;
int unused5;
int unused6;
int unused7;
};
Export WhateverStructNameYouWant DescBlockEx = { 1, 0, 0, 0, 0, 0, 0, 0 };
A more compact looking, yet full sized struct and initialization is:
struct SDescBlockEx {
int numAiPlayers;
int unused[7];
};
Export SDescBlockEx DescBlockEx = { 1 };
In the last example, the unused fields are collapsed into a single array in the struct, and the export definition uses automatic 0 filling of fields that are not explicitly set. It's also updated to use the "Export" macro, rather than "SCRIPT_API".