AGS 3.0 backwards compatibility for AGS_MAX_* constants

Started by monkey0506, Sun 11/11/2007 09:36:25

Previous topic - Next topic

monkey0506

One issue that has been brought up with AGS 3.0 is that in removing some of the static limits, some of the AGS_MAX_* constants have been removed. Namely AGS_MAX_CHARACTERS and AGS_MAX_GUIS are no longer available since these limits are no more.

The alternative method for arrays based on these values is to use dynamic arrays. The problem with this is that scripts using dynamic arrays aren't backwards compatible while scripts using the old AGS_MAX_* constants aren't forward-compatible. Short of using loads of #ifdef/#ifndef-s it seemed that our scripts would be restricted to "AGS 2.72-" or "AGS 3.0+" versions.

However, it is possible to future-proof your old AGS 2.72- modules for this change. Simply adding a few lines will make it possible to leave your scripts otherwise in-tact.

First you'll need to define the now-missing constants. If you used the old AGS_MAX_* constants in your script header you'll need to add these lines to the top of your header, otherwise it's best to just add them to the top of the main script:

Code: ags
#ifdef AGS_SUPPORTS_IFVER
#ifver 3.0
#define AGS_MAX_CHARACTERS // $AUTOCOMPLETEIGNORE$
#define AGS_MAX_GUIS // $AUTOCOMPLETEIGNORE$
#define IS_AGS_3_0 // $AUTOCOMPLETEIGNORE$
#endif
#endif


Adding the #define but ending it in a comment instead of a value means that the #define will be replaced by nothing. Hence:

Code: ags
int CharacterBuffer[AGS_MAX_CHARACTERS];


Would be interpreted as:

Code: ags
int CharacterBuffer[];


A dynamic array. Ending the lines in $AUTOCOMPLETEIGNORE$ simply makes sure that the autocomplete won't try to carry the values over to other scripts since we're going to destroy these temporary #define-s when we're done with them. The IS_AGS_3_0 #define simply gives us an easier way to check if we are using AGS 3.0 (i.e., checking 1 #define instead of checking a #define and then using #ifver again).

The next set of lines you'll need to add go into your main script's game_start function which is where you'll initialize any dynamic arrays (if the user is using AGS 3.0).

Code: ags
// inside game_start
#ifdef IS_AGS_3_0
CharacterBuffer = new int[Game.CharacterCount];
GUIBuffer = new int[Game.GUICount];
//etc.
#undef AGS_MAX_CHARACTERS
#undef AGS_MAX_GUIS
#define AGS_MAX_CHARACTERS Game.CharacterCount // $AUTOCOMPLETEIGNORE$
#define AGS_MAX_GUIS Game.GUICount // $AUTOCOMPLETEIGNORE$
#endif


These lines will allocate the memory for your dynamic array. Since there's no "max" value for Characters or GUIs in AGS 3.0, we can use the actual number of them in the game instead.

(Edit) I forgot that you may want to use the constants for something other than just creating the arrays. The above now assigns the constants useful values after the (dynamic) arrays have been created. ;)

(Edit^3) Tested it and assigning the values of Game.CharacterCount and Game.GUICount appear to work, but we have to remove the empty #define-s first before we can assign the new values.

And finally at the end of your main script you'll need to add these lines in:

Code: ags
#ifdef IS_AGS_3_0
#undef AGS_MAX_CHARACTERS
#undef AGS_MAX_GUIS
#undef IS_AGS_3_0
#endif


This will destroy our "temporary" #define-s now that we're done with them.

Note that this method will NOT work if you were using the AGS_MAX_* constants to create arrays of custom structs as AGS 3.0 does not currently allow for dynamic arrays of custom structs. With luck future versions will allow this, but until then the only alternatives for scripts relying on these custom struct arrays would be a) separate version-dependent scripts or b) reworking the script to not require the struct.

In any case, I hope perhaps some of my fellow moduleers will find this useful. ;)

Pumaman

Nice idea, that's a pretty good workaround for this situation.

SMF spam blocked by CleanTalk