Introduction

NWScript is the scripting language developed by BioWare and is used in the role-playing video game Neverwinter Nights 2. It is based on the C programming language and is implemented in the Aurora / Electron toolset. NWScript is also used in Neverwinter Nights 1, The Witcher, Star Wars: Knights of the Old Republic and Star Wars: Knights of the Old Republic II The Sith Lords, which use the Odyssey Engine. ,

Syntax

While based on C, NWScript does not have many functions from the C family, excluding logical and binary / ternary operators and some mathematical functions. Function source code is not accessible to the end-user, but the correct syntax is defined in a script file called nwscript.nss.

The users can create their own functions, and these can be included in other scripts through the #include directive. #includes are handled almost exactly like in C languages - i.e. the contents of the included file is copied in - except that each file is only included once. (Treated as if #pragma once is always at the top)


void main()
{
    SendMessageToPC(GetEnteringObject(), "Hello world");
}

Data types

NWScript allows structs, but not objects. The following common data types are available in NWScript:

NWScript has also introduced some data types for purposes of the Neverwinter Nights game:

  • object (refers to game objects, such as NPCs and placeable objects).
  • location (refers to the in-game location of an object, consisting of an area object reference, a vector and a float describing the position and facing within the area).
  • vector (refers to coordinates of an object, and is a construct of three floats).
  • itemproperty (refers to abilities on items such as weapons for use in the game).
  • effect (refers to game-mechanics-altering effects on objects; for example effects created by spells, diseases, and displayed visual effects).

File format

When saving a script, the Aurora Toolset saves the plain text of the script as a file with a .nss filename extension. When compiling the script, a .ncs containing Bytecode to be run on the NWScript Virtual Machine file is created. If turned on, a debug information file with an .ndb extension is also created. The game uses only the .ncs file (and the .ndb file if called).


Deeper Look (Byte Code Execution)

NCS (Neverwinter Compiled Source) files store the Bytecode that is executed by the state machine of the engine. All scripts that are being executed are given a "Time Slice" and processed in a queue. Bytecode operates identically to a traditional assembly language but with a subset of the opcodes you would expect to find in x86 or Freescale. Important note - all jump offsets are 32bit in NW Bytecode.

The Nwscript State machine or virtual machine executes the Bytecode utilizing an internal stack fully equipped with Pointer Registers (But not Data Registers). This decision was likely a performance choice as the concept and performance gains behind data registers only works when the hardware is optimized for using them, artificially adding registers would be a waste of cycles.


Because NWScript Bytecode does not support data registers the assembly syntax can sometimes be a little quirky to follow at first but not too complicated.

Example
// Example NWScript Function

int add(int a, int b) 
{ 
	int c; 
	c = a + b; 
	return c; 
}



// Resulting NCS (Bytecode)

RESERVE_INT // reserve stack space for C
COPY_TO_TOP_INT BP[0] // copy from BP[0] to top of stack
COPY_TO_TOP_INT BP[4] // copy from BP[4] to top of stack
ADD_INTINT  // Add two ints from top of stack. Args are removed, result is pushed to top
COPY_DOWN BP[-4]  // store top of stack to location for C
// if we had any other code, it'd go here
COPY BP[-4], BP[8] // storage for return value was allocated by the caller
RET


Reference Material

Wiki Article (Used For Introduction) -

https://en.wikipedia.org/wiki/NWScript


Additional Reading: Registers -

https://www.tutorialspoint.com/assembly_programming/assembly_registers.htm


  • No labels