Determining game version inside script

I am sure this is an FAQ, but I am not seeing it, so…

How do I determine the current game version from inside of a script? For example, if I want some code to do one thing in versions before version X.YY and something different in a later version, how can I check what version the engine is running from inside the script?

In the previous version of the CCOH I tried to determine the game version by checking 2da values since usually new NWN versions also made changes to 2da files (e.g. new columns). However the problem was that the player might use old haks containing outdated versions of these 2da files. So in the current version I run some scripting commands that do not exist in older versions. For example GetPCChatMessage() was introduced in 1.69 so if a call to GetPCChatMessage() terminates the script I know that the game version is 1.68 or lower:

Summary
void MK_VERSION_VersionToLocal(int nMajor, int nMinor, object oPC)
{
    SetLocalInt(oPC, "MK_NWN_VERSION_MAJOR", nMajor);
    SetLocalInt(oPC, "MK_NWN_VERSION_MINOR", nMinor);
}

void MK_VERSION_DetectGameVersion(object oPC)
{
    int nReturn;
    string sReturn;
    MK_VERSION_VersionToLocal(1, 22, oPC);

    // The follwing function was added in 1.23
    // int GetStealthMode(object oCreature);
    // if we crash we're not running NWN 1.23
    nReturn = GetStealthMode(oPC);
    MK_VERSION_VersionToLocal(1, 23, oPC);

    // No new command in 1.24 unfortunately

    // The follwing function was added in 1.25
    // string GetResRef(object oObject);
    // if we crash we're not running NWN 1.25
    sReturn = GetResRef(oPC);
    MK_VERSION_VersionToLocal(1, 25, oPC);

    // No new command in 1.26 unfortunately

    // The follwing function was added in 1.27
    // int GetDroppableFlag(object oItem);
    // if we crash we're not running NWN 1.27
    nReturn = GetDroppableFlag(oPC);
    MK_VERSION_VersionToLocal(1, 27, oPC);

    // The follwing function was added in 1.28
    // object CopyObject(object oSource, location locLocation, object oOwner = OBJECT_INVALID, string sNewTag = "");
    // if we crash we're not running NWN 1.28
    CopyObject(OBJECT_INVALID, GetLocation(oPC));
    MK_VERSION_VersionToLocal(1, 28, oPC);

    // No new command in 1.29 unfortunately

    // The follwing function was added in 1.30
    // int GetAppearanceType(object oCreature);
    // if we crash we're not running NWN 1.30
    nReturn = GetAppearanceType(oPC);
    MK_VERSION_VersionToLocal(1, 30, oPC);

    // The follwing function was added in 1.31
    // int GetWeather(object oArea);
    // if we crash we're not running NWN 1.31
    nReturn = GetWeather(GetArea(oPC));
    MK_VERSION_VersionToLocal(1, 31, oPC);

    // No new command in 1.32 unfortunately

    // The follwing function was added in 1.61
    // int GetIsCreatureDisarmable(object oCreature)
    // if we crash we're not running NWN 1.61
    nReturn = GetIsCreatureDisarmable(oPC);
    MK_VERSION_VersionToLocal(1, 61, oPC);

    // No new command in 1.62 unfortunately

    // No patch notes for 1.63 (did it acutually exist?)

    // The follwing function was added in 1.64
    // int GetPhenoType(object oCreature)
    // if we crash we're not running NWN 1.64
    nReturn = GetPhenoType(oPC);
    MK_VERSION_VersionToLocal(1, 64, oPC);

    // The follwing function was added in 1.65
    // int GetSkyBox(object oArea=OBJECT_INVALID)
    // if we crash we're not running NWN 1.65
    nReturn = GetSkyBox();
    MK_VERSION_VersionToLocal(1, 65, oPC);

    // The follwing function was added in 1.66
    // int GetPickpocketableFlag(object oItem)
    // if we crash we're not running NWN 1.66
    nReturn = GetPickpocketableFlag(oPC);
    MK_VERSION_VersionToLocal(1, 66, oPC);

    // The follwing function was added in 1.67
    // int GetCreatureWingType(object oCreature=OBJECT_SELF)
    // if we crash we're not running NWN 1.67
    nReturn = GetCreatureWingType(oPC);
    MK_VERSION_VersionToLocal(1, 67, oPC);

    // The follwing function was added in 1.68
    // void SetUseableFlag(object oPlaceable, int nUseableFlag);
    // if we crash we're not running NWN 1.68
    SetUseableFlag(OBJECT_INVALID, FALSE);
    MK_VERSION_VersionToLocal(1, 68, oPC);

    // The follwing function was added in 1.69
    // string GetPCChatMessage()
    // if we crash we're not running NWN 1.69
    sReturn = GetPCChatMessage();
    MK_VERSION_VersionToLocal(1, 69, oPC);

    // The follwing function was added in 1.74
    // object GetFirstArea();
    // if we crash we're not running NWN 1.74
    GetFirstArea();
    MK_VERSION_VersionToLocal(1, 74, oPC);

    // The follwing function was added in 1.75
    // float GetObjectVisualTransform(object oObject, int nTransform);
    // if we crash we're not running NWN 1.75
    GetObjectVisualTransform(oPC, OBJECT_VISUAL_TRANSFORM_SCALE);
    MK_VERSION_VersionToLocal(1, 75, oPC);

    // no idea how to detect 1.76
    // no idea how to detect 1.77
    // no idea how to detect 1.78

    // The follwing function was added in 1.79
    // string GetRandomUUID();
    // if we crash we're not running NWN 1.79
    sReturn = GetRandomUUID();
    MK_VERSION_VersionToLocal(1, 79, oPC);
}

void main()
{
    MK_VERSION_DetectGameVersion(OBJECT_SELF);
}

Call this script within another script with ExcecuteScript() and you will have the game version in two locals.

The drawback is that player with older version get an ugly message in the chat window. So if there’s a better way I’m very interested too.

To check if the player runs NWN EE you could use SetItemCharges() as EE has set max item charges to 250: create an item somewhere, call SetItemCharges(oItem, 250) and if (GetItemCharges(oItem)==250) is TRUE then NWN EE is running.

Thanks for that reply! Checking the item charges is a good technique. That may be what I go with and it will probably work for me, though it isn’t as fine-grained as I was thinking. I was hoping there was a #define somewhere that set the version as one or more constants that specified which build was running. Maybe even a function that returned that as a string…

Specifically, I was looking to check if the version of EE is running that applies RDD ability bonuses the old way (that weren’t always properly removed when the PC lost enough XP to lose a level) or the newer way set in 2DAs that caused some confusion a few months ago when it rendered some RDD builds invalid to ELC checks. And, yes, your other suggestion of checking 2DAs might do just this thing.

Why not log in over on the BD forums and suggest just that?

TR