Author Topic: Proposed Sdk Changes  (Read 1640 times)

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Proposed Sdk Changes
« on: July 15, 2008, 09:59:56 AM »
I think the level SDK has become a bit dated. The more I look at it, the more I realize certain things are wrong with it. I'm starting this thread for anyone that feels something was implemented in an obscure way, or in a bad way, or is just plain wrong.

If you feel something needs to be explained better, or more sample code posted on some topic, then post about it here. Such as, the SDK needs to include more sample or template levels, particularly showing how to make an AI do <X>.


As for what I think is wrong with it, these things are mainly aimed at BlackBox to read over. You're welcome to read it, but if you get lost you should probably just ignore it.



First of all, I think the file division needs to change a bit. Groups.h should probably be split or renamed (ScStub.h maybe?). Currently it contains Triggers because they're also derived from ScStub, but they really have nothing to do with groups. Similar thought on Functions.h, which contains mostly Trigger related functions.


We should also redo RequiredExports.h. The way this header file is now, it forces all DLLs compiled with this API to be level DLLs, but there are other types of DLLs that we could make for Outpost2 that aren't levels. One example might be some sort of plugin AI project. I've worked on a few projects that used this API, but weren't level DLLs, and I needed some way to prevent declaring those exports. I used a hacked #define method to do it, or just avoided the API completely.

Instead, we should only define the needed structures and enumerations. (BufferDesc, SDescBlock/AIModDesc, and MissionTypes). We should also keep a macro to make exporting easier/cleaner looking, and it should be named something obvious. Perhaps:
Code: [Select]
#define Export extern "C" __declspec(dllexport)
Instead of the current:
Code: [Select]
#define SCRIPT_API extern "C" __declspec(dllexport)

We should also document the required (and standard, but not required) exports, both function and data. We should probably only do this as comments though, and not as actual declared exports.

Instead, the Export macro can be used when and where the data is declared. Such as in:
Code: [Select]
Export char MapName[]	= "on1_01.map";	// The .map file used for this level
Instead of the old way we've usually done it:
Code: [Select]
char MapName[]	= "on1_01.map";	// The .map file used for this level
Note that we didn't need to declare the variable as exported before, because it was already declared as exported in the header file. My suggestion is thus to move the Export from the header to the implementation file. This applies to both exported data and exported functions.


We should provide an easy level setup macro, and probably use the full AIModDesc structure. Perhaps using a syntax like:
Code: [Select]
ExportLevelDetails("Colony Builder - game description", "on1_01.map", "Multitek.txt", Colony, 2);

We can do this using the following macro:
Code: [Select]
#define ExportLevelDetails(levelDesc, mapName, techTreeName, missionType, numPlayers) \
Export char MapName[] = mapName; \
Export char LevelDesc[] = levelDesc; \
Export char TechtreeName[] = techTreeName; \
Export AIModDesc DescBlock = { missionType, numPlayers, (missionType > 0) ? missionType : 12, false, MapName, LevelDesc, TechtreeName, 0 }; \

Note that I made a few assumptions in this macro. Namely, bUnitOnlyMission is set to false, and techLevel is set to the campaign level number (if it's positive), or 12 for any multiplayer or colony games. As these two options don't seem to be changed much, this simplification seems useful. If you want to specify those extra two parameters for some special level that needs them, then we can provide an alternate macro such as:
Code: [Select]
#define ExportLevelDetailsEx(levelDesc, mapName, techTreeName, missionType, numPlayers, maxTechLevel, bUnitOnlyMission) \
Export char MapName[] = mapName; \
Export char LevelDesc[] = levelDesc; \
Export char TechtreeName[] = techTreeName; \
Export AIModDesc DescBlock = { missionType, numPlayers, maxTechLevel, bUnitOnlyMission, MapName, LevelDesc, TechtreeName, 0 };


By building a template project where DllMain is seperated into it's own file, we could potentially reduce compile times. Having to parse all of windows.h can take a noticable amount of time. This header is usually only used to help with DllMain. By keeping all the Outpost2 specific stuff seperate, people can work on their level without having to recompile whatever file DllMain is stuck into. Yet, it's still available for those cases when you need to edit it. (Don't go sticking it in a library please).


We should standardize header access between DevStudio and CodeBlocks. This is actually an easy one. We just need to specify additional include folders in the project setup. Then it doesn't matter if the headers have to be moved between the two environments, since the extra include folders will catch the SDK headers. It'd be nice if code people gave you actually compiled in your environment without having to go through all the headers and fix the paths. The only problem, is getting people to "fix" their existing projects.


Maybe we should add a function for SetLavaPossible, that is compatible with how the original Sierra levels works? It's not a particularly great method, but it might be nice to have in some sort of extra section, such as OP2Helper.


We need to fix a few errors. Was it CreateEscapeTrigger that has a parameter listed wrong? I can't remember now. I also found another typo in my headers that's been there since forever. The UnitClassifications enum had a typo.


Some functions or classes probably also need a few more comments describing how to use them.


We need to complete some of the info in there. We have left a number of unknowns that we could actually determine. We mostly just haven't bothered, probably due to lack of interest. It seems that not all of the SDK has really been explored by very many.


I'm finding reasons to reuse some enums between the ForcedExport project and the standard SDK. I used to have some issues with name clashes, and still have some compatability issues when mixing functions. If I declare an enum in a namespace, which also exists in the SDK, then they won't be treated as the same since their names are different. The exported names in the SDK obviously can't be put into namespaces, since this affects their name decoration. It'd be nice to somehow seperate the enums from the rest of the SDK so they could be reused, and more enums could be added for other projects. It would be helpful if just the enums could be included without bringing in the rest.


The SDK should include certain sample code. At least one blank template. One simple multiplayer mission with no AI. Maybe even a sandbox colony game without AI? It would also be good to include something with a bit of AI in it. Just using the standard functions, and a cheating AI. Perhaps we can reverse engineer an existing DLL and rewrite it in C++. I've got a large part of CPS2.dll worked out. Source for CES1.dll would also be nice, as well as the two multi maps ml2_21.dll and ml4_21.dll. (This is partly why I suggesting code to implement the SetLavaPossible function, the way Sierra does it).


Better base layout/creation utility functions. (OP2Helper type thing). There were some limitations in the last release that were discovered pretty fast, but were never fixed. A few people wrote their own solutions, and some nonstandard code got passed around. It'd be nice to just fix the API and make something better. (Suggestions?)




And of course try to make it nicer to use for the non-coders. I've seen a few people mention the SDK could use some more work, but not so much why or how. Ideas?
 

Offline Hidiot

  • Hero Member
  • *****
  • Posts: 1018
Proposed Sdk Changes
« Reply #1 on: July 17, 2008, 01:32:25 PM »
I think a sample code for passing function values generated in the dll to the game output for checking would do good.

I haven't really tried that yet, but I don't see me succeeding with the current details.
"Nothing from nowhere, I'm no one at all"

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Proposed Sdk Changes
« Reply #2 on: July 17, 2008, 02:29:55 PM »
Hmm, like a MessageLog.printf? I suppose we could do something to reduce that to 1 line instead of 3 or so. That would actually be fairly convenient.
 

Offline Hidiot

  • Hero Member
  • *****
  • Posts: 1018
Proposed Sdk Changes
« Reply #3 on: August 01, 2008, 02:37:05 PM »
Maybe a function that reads a line entered in the in-game messages by a player ([Enter] <message> [Enter], just to be clear :) ) ? All it needs is to take the message and put it into a string for the .dll to process. If it could search for keywords in messages before retrieving the message as a string, it might save some time.

It could be useful for adding customizable things to maps. Things like giving the AI different strategies according to the hosts decisions during a multi player game.
"Nothing from nowhere, I'm no one at all"

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Proposed Sdk Changes
« Reply #4 on: August 01, 2008, 03:00:15 PM »
Hmm, yes, I've thought of something like this before. Not too sure how it'd work though. I once had code to catch text messages by installing a code hook. I'm not sure if I'd want a solution like that in the SDK though. It requires more setup and teardown to work, and programmer errors will likely cause crashes. But then people don't have to use it. Might as well have it for people that know how to use it. The other alternative might be to scan the message log. It'd have to scan a few entries back though, since more than one message can appear at once. This way seems clunkier and less efficient, but easier to use.

Btw, the text  catching code was originally one of the first cheat detection programs tested before we disabled the cheats. It captured the messages and printed them to a debug log, or forced it to be visible to all players, so you couldn't hide the "WOOF! WOOF!" by removing chat to that player. It had the unfortunate effect of revealing all private allied chat though (from your opponents).