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.
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.
See separate page on Nui.
There will be pages made for the fields list of each main GFF object available in the game to JSONfy:
RESTYPE_CAF (and RESTYPE_ARE, RESTYPE_GIT, RESTYPE_GIC)
RESTYPE_UTC - Creature JSON
RESTYPE_UTI
RESTYPE_UTT
RESTYPE_UTP
RESTYPE_UTD
RESTYPE_UTW
RESTYPE_UTE
RESTYPE_UTM
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.
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:
|
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.
Note however there are two kinds of GFF - the one on the template file and the in-game struct, which you can get with ObjectToJson. These can differ quite significantly sometimes.
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)));
} |
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));
} |