JSON is a new feature of NWN:EE that allows you to load templates to JSON or generate JSON directly from text.

These can be used to check a GFF object or alter data before creating things.

JSON is also used for the Nui system that can generate GUI elements.

Helper Include for GFF editing

Beamdog created an include file to help with JSON manipulation although you can replicate this yourself using the base game nwscript functions; nw_inc_gff.nss is the file.

Helper Pages on this wiki

There will be pages made for the fields list of each main GFF object available in the game to JSONfy:

Use these to find what fields to replace.

It's probably a better idea to use TemplateToJSON and edit it, not generate the entire object in nwscript unless you want to spend a lot of time and energy writing valid JSON structures.

You can save JSON text to SQL as well to load it back later. For instance you could have an editable / upgradable henchman which is stored when a player logs out into SQL and back again.

Checking JSON of GFF objects

A simple way to generate JSON from a template and check the text returned is to write it to server log nwclientLog1.txt

void main()
{
    json jChicken = TemplateToJson("nw_chicken", RESTYPE_UTC);

    string sChicken = JsonDump(jChicken, 2);

    WriteTimestampedLogEntry(sChicken);
}

This generates this output:


{
  "Appearance_Type": {
    "type": "word",
    "value": 31
  },
  "BodyBag": {
    "type": "byte",
    "value": 0
  },
  "CRAdjust": {
    "type": "int",
    "value": 0
  },
  "Cha": {
    "type": "byte",
    "value": 6
  },
  "ChallengeRating": {
    "type": "float",
    "value": 0.25
  },
  "ClassList": {
    "type": "list",
    "value": [
      {
        "Class": {
          "type": "int",
          "value": 12
        },
        "ClassLevel": {
          "type": "short",
          "value": 1
        },
        "__struct_id": 2
      }
    ]
  },
  "Comment": {
    "type": "cexostring",
    "value": ""
  },
  "Con": {
    "type": "byte",
    "value": 8
  },
  "Conversation": {
    "type": "resref",
    "value": ""
  },
  "CurrentHitPoints": {
    "type": "short",
    "value": 5
  },
  "Deity": {
    "type": "cexostring",
    "value": ""
  },
  "Description": {
    "type": "cexolocstring",
    "value": {
      "id": 12415
    }
  },
  "Dex": {
    "type": "byte",
    "value": 7
  },
  "Disarmable": {
    "type": "byte",
    "value": 0
  },
  "Equip_ItemList": {
    "type": "list",
    "value": []
  },
  "FactionID": {
    "type": "word",
    "value": 2
  },
  "FeatList": {
    "type": "list",
    "value": [
      {
        "Feat": {
          "type": "word",
          "value": 289
        },
        "__struct_id": 1
      }
    ]
  },
  "FirstName": {
    "type": "cexolocstring",
    "value": {
      "id": 12416
    }
  },
  "Gender": {
    "type": "byte",
    "value": 1
  },
  "GoodEvil": {
    "type": "byte",
    "value": 50
  },
  "HitPoints": {
    "type": "short",
    "value": 5
  },
  "Int": {
    "type": "byte",
    "value": 3
  },
  "Interruptable": {
    "type": "byte",
    "value": 1
  },
  "IsPC": {
    "type": "byte",
    "value": 0
  },
  "LastName": {
    "type": "cexolocstring",
    "value": {}
  },
  "LawfulChaotic": {
    "type": "byte",
    "value": 50
  },
  "MaxHitPoints": {
    "type": "short",
    "value": 6
  },
  "NaturalAC": {
    "type": "byte",
    "value": 0
  },
  "NoPermDeath": {
    "type": "byte",
    "value": 0
  },
  "PaletteID": {
    "type": "byte",
    "value": 6
  },
  "PerceptionRange": {
    "type": "byte",
    "value": 11
  },
  "Phenotype": {
    "type": "int",
    "value": 0
  },
  "Plot": {
    "type": "byte",
    "value": 0
  },
  "PortraitId": {
    "type": "word",
    "value": 168
  },
  "Race": {
    "type": "byte",
    "value": 8
  },
  "ScriptAttacked": {
    "type": "resref",
    "value": "nw_c2_default5"
  },
  "ScriptDamaged": {
    "type": "resref",
    "value": "nw_c2_default6"
  },
  "ScriptDeath": {
    "type": "resref",
    "value": "nw_c2_default7"
  },
  "ScriptDialogue": {
    "type": "resref",
    "value": "nw_c2_default4"
  },
  "ScriptDisturbed": {
    "type": "resref",
    "value": "nw_c2_default8"
  },
  "ScriptEndRound": {
    "type": "resref",
    "value": "nw_c2_default3"
  },
  "ScriptHeartbeat": {
    "type": "resref",
    "value": "nw_c2_default1"
  },
  "ScriptOnBlocked": {
    "type": "resref",
    "value": "nw_c2_defaulte"
  },
  "ScriptOnNotice": {
    "type": "resref",
    "value": "nw_c2_default2"
  },
  "ScriptRested": {
    "type": "resref",
    "value": "nw_c2_defaulta"
  },
  "ScriptSpawn": {
    "type": "resref",
    "value": "nw_c2_herbivore"
  },
  "ScriptSpellAt": {
    "type": "resref",
    "value": "nw_c2_defaultb"
  },
  "ScriptUserDefine": {
    "type": "resref",
    "value": "nw_c2_defaultd"
  },
  "SkillList": {
    "type": "list",
    "value": [
      {
        "Rank": {
          "type": "byte",
          "value": 0
        },
        "__struct_id": 0
      },
      {
        "Rank": {
          "type": "byte",
          "value": 0
        },
        "__struct_id": 0
      },
      {
        "Rank": {
          "type": "byte",
          "value": 0
        },
        "__struct_id": 0
      },
      {
        "Rank": {
          "type": "byte",
          "value": 0
        },
        "__struct_id": 0
      },
      {
        "Rank": {
          "type": "byte",
          "value": 0
        },
        "__struct_id": 0
      },
      {
        "Rank": {
          "type": "byte",
          "value": 0
        },
        "__struct_id": 0
      },
      {
        "Rank": {
          "type": "byte",
          "value": 2
        },
        "__struct_id": 0
      },
      {
        "Rank": {
          "type": "byte",
          "value": 0
        },
        "__struct_id": 0
      },
      {
        "Rank": {
          "type": "byte",
          "value": 0
        },
        "__struct_id": 0
      },
      {
        "Rank": {
          "type": "byte",
          "value": 0
        },
        "__struct_id": 0
      },
      {
        "Rank": {
          "type": "byte",
          "value": 0
        },
        "__struct_id": 0
      },
      {
        "Rank": {
          "type": "byte",
          "value": 0
        },
        "__struct_id": 0
      },
      {
        "Rank": {
          "type": "byte",
          "value": 0
        },
        "__struct_id": 0
      },
      {
        "Rank": {
          "type": "byte",
          "value": 0
        },
        "__struct_id": 0
      },
      {
        "Rank": {
          "type": "byte",
          "value": 0
        },
        "__struct_id": 0
      },
      {
        "Rank": {
          "type": "byte",
          "value": 0
        },
        "__struct_id": 0
      },
      {
        "Rank": {
          "type": "byte",
          "value": 0
        },
        "__struct_id": 0
      },
      {
        "Rank": {
          "type": "byte",
          "value": 2
        },
        "__struct_id": 0
      },
      {
        "Rank": {
          "type": "byte",
          "value": 0
        },
        "__struct_id": 0
      },
      {
        "Rank": {
          "type": "byte",
          "value": 0
        },
        "__struct_id": 0
      }
    ]
  },
  "SoundSetFile": {
    "type": "word",
    "value": 21
  },
  "SpecAbilityList": {
    "type": "list",
    "value": []
  },
  "Str": {
    "type": "byte",
    "value": 3
  },
  "Subrace": {
    "type": "cexostring",
    "value": ""
  },
  "Tag": {
    "type": "cexostring",
    "value": "NW_CHICKEN"
  },
  "Tail": {
    "type": "byte",
    "value": 0
  },
  "TemplateList": {
    "type": "list",
    "value": []
  },
  "TemplateResRef": {
    "type": "resref",
    "value": "nw_chicken"
  },
  "WalkRate": {
    "type": "int",
    "value": 7
  },
  "Wings": {
    "type": "byte",
    "value": 0
  },
  "Wis": {
    "type": "byte",
    "value": 8
  },
  "__data_type": "UTC ",
  "fortbonus": {
    "type": "short",
    "value": 0
  },
  "refbonus": {
    "type": "short",
    "value": 0
  },
  "willbonus": {
    "type": "short",
    "value": 0
  }
}


nim-tools

Another alternative to look through GFF information is to use offline tools, this can be done with the nim-tools that output identical JSON to the game:

https://github.com/niv/neverwinter.nim

These can be run on a GFF file (eg chicken.utc as above) for similar output.

Finding Values Example

A simple example to find a usually inaccessible field. This doesn't use nw_inc_gff.nss so explains step by step the process of parsing the array of information.

const int SOUNDSET_INVALID = -1;

// Retrieves the line in soundset.2da
// Returns SOUNDSET_INVALID if they have no soundset assigned or on error.
// * oCreature - Creature to check
int GetCreatureSoundset(object oCreature)
{
    if(GetObjectType(oCreature) != OBJECT_TYPE_CREATURE) return SOUNDSET_INVALID;

    // Convert to JSON
    json jGet = ObjectToJson(oCreature);

    // Retrieve the key
    jGet = JsonObjectGet(jGet, "SoundSetFile");

    if(JsonGetType(jGet) == JSON_TYPE_NULL) return SOUNDSET_INVALID;

    // Retrieve the value
    jGet = JsonObjectGet(jGet, "value");

    if(JsonGetType(jGet) != JSON_TYPE_INTEGER) return SOUNDSET_INVALID;

    return JsonGetInt(jGet);
}

It can be simplified with the include:

#include "nw_inc_gff"

const int SOUNDSET_INVALID = -1;

// Retrieves the SOUNDSET_* constant, a line in soundset.2da
// Returns SOUNDSET_INVALID if they have no soundset assigned or on error.
// * oCreature - Creature to check
int GetCreatureSoundset(object oCreature)
{
    if(GetObjectType(oCreature) != OBJECT_TYPE_CREATURE) return SOUNDSET_INVALID;

    // Return the soundset variable
    return JsonGetInt(GffGetWord(ObjectToJson(oCreature), "SoundSetFile"));
}

void main()
{
    SpeakString("My soundset: " + IntToString(GetCreatureSoundset(OBJECT_SELF)));
}

Altering Values Example

A simple example for how to edit some JSON on a field and creating that object, in this case a placeable having it's appearance field changed so when it's spawned in it is different:

#include "nw_inc_gff"
void main()
{
    // Generate JSON from resref template
    json jPlaceable = TemplateToJson("plc_armoire", RESTYPE_UTP);
 
    // Change to appearance 390
    jPlaceable = GffReplaceDword(jPlaceable, "Appearance", 33);
 
    // Spawn
    JsonToObject(jPlaceable, GetLocation(OBJECT_SELF));
}