Scripting Style

This page discusses the scripting style that all members of the scripting team must follow for clarity and consistency. Specifically, the following topics are discussed here.

  • Commenting
  • Identifier Naming
  • Formatting
  • Forward Declaration

Commenting

All scripts must be properly commented to provide clear information to whoever reads them. The following sections deal with how commenting is to be done for this project.

Providing File Information

At the very beginning of each NSS file, a comment must appear that indicates the name of the file (without the NSS extension), a brief description of what the file is for, the original author of the file, and the date that the file was created. All dates must clearly indicate the day, month (at least the first three letters), and year in that order. An example showing the exact appearance of this type of comment is shown below.

//------------------------------------------------------------------------------
// m_n_blank_co
/*
    Description: A script that does nothing
*/
// Author: Frank Perez
// Date: 02 Oct 2008

Note that the first line above is exactly 80 characters long. This line serves as a guide for indicating the position of column 80 in the text.

Explaining Function Usage

All functions must be preceded by comments that explain their use. The comment must include a brief description of what the function does, the meaning of each parameter, an explanation of the return value (if any), and what the function does in case an error occurs. The following example shows how comments preceding function headers are to be written.

// Causes the caller to try to use the Hide in Plain Sight feat.
// Parameters:
//   * oTarget: The creature from which the caller is attempting to hide.
// Returns: One of the following constants.
//   * HIDE_ALREADY_HIDDEN: The caller is already hidden and therefore did not attempt to hide this round
//   * HIDE_THIS_ROUND: The caller can and will make the hide attempt this round
//   * HIDE_LATER_ROUND: The caller has a reasonable chance to hide but not this round
//   * HIDE_CANNOT: The caller has no reasonable chance of hiding from oTarget
// Errors:
//   If the caller or oTarget is not a creature, the function will return HIDE_CANNOT.
int aiHideInPlainSight(object oTarget);

Clarifying Complicated Code

Complicated sections of code must have accompanying comments to explain what the code is doing. Code that cannot be understood except by the author and code that not even the author may understand after some time has passed must be commented on sufficiently to make them comprehensible.

Identifier Naming

The first letter of all function names must be in lower case. This will help distinguish modder-made functions from the ones created by Bioware or Obsidian Entertainment.

In an include file, helper functions are not meant to be called by any function defined outside of the include file. To distinguish helper functions from all other functions in an include file, an underscore must precede the names of these functions. The following are examples of the names of helper functions.

int _inCombatRound();

void _turnCombatRoundOn(int bBool);

All variable identifiers must have a prefix in lower case that indicates the variable's type. The first letter after the prefix must be in upper case. The following prefixes shall be used:

Type Prefix
int (values of 0 or 1 only) b
int (wider range of values) n
float f
string s
object o
effect e
itemproperty ip
talent t
struct struct

The names of functions and variables, if made by joining two or more words, will have their word breaks indicated through the use of capital letters separating lower-case letters. Word breaks for these identifiers will never be indicated with the use of underscores. Some examples of proper identifiers for functions and variables follow.

// These are examples of function names.
announce
doDeathWard
getIsHarmfulAOE

// These are examples of variable names.
nSpellLevel
nMyDCModifier
oPersistentObject

All constant identifiers will be written completely in upper case. Underscores may be used as a separator for constant names that are composed of two or more words. No prefixes for indicating the constants' type will be provided. Nevertheless, it is recommended that the prefix "VAR" followed by an underscore be used for constants containing the names of local variables (such as the ones passed to the functions GetLocalInt or SetLocalFloat). Some examples follow.

const int HIDE_ALREADY_HIDDEN = 3;
const string VAR_HIPS = "HiPS";
const float HIPS_DURATION = 8.0;

Formatting

Curly braces must never appear in the same line as any other piece of code. Curly braces must be put in a separate line (although comments may accompany them on that line). The following example illustrates this rule.

void myFunction(int nVar)
{
    if (condition(nVar))
    {
        PrintString("Condition passed.");
        SendMessageToPC(GetFirstPC(), "Condition passed.");
    }
    else
    {
        PrintString("Condition failed.");
        SendMessageToPC(GetFirstPC(), "Condition failed.");
    }
}

All leading indents must be done using tabs, not spaces.

Matching curly braces must be on the same column of text, which is the same column as the statement that preceded the opening brace. The text within a matching pair of curly braces must be indented.

Function headers are never indented, and the entire header must never be broken across several lines. The toolset's help system shows only the first line of a function header when the name of the function is double-clicked in the scripting window. This is why breaking the header across two or more lines is not recommended.

There must be a single space separating the key words if, while, and for from the open parenthesis that follows them. There is no space separating an open parenthesis from the first parameter in it. Neither is there a space separating the last parameter and the closing parenthesis. The key words if, while, and for are not functions and should not be written as if they were. Note the following examples.

// Proper use of parentheses and spaces
if (oTarget == oCaster)
{
}
for (nIndex = 0; nIndex < MAX_ITER; ++nIndex)
{
}

// Improper use of parentheses and spaces
while( nCycle++ < MAX_CYCLE )
{
}
if( fDistance >= 10.0 )
{
}

Forward Declaration

In most cases, forward declaring functions is a matter of individual preferences and/or scripting convenience. Include files, however, must forward declare all functions that are defined in it. The comments that immediately precede the header in the function's definition must be copied to the function declaration. The following example illustrates this point.

//------------------------------------------------------------------------------
// m_inc_items
/*
    Description: Include file for functions regarding items
*/
// Author: Frank Perez
// Date: 01 Jan 2008

//------------------------------------------------------------------------------
// FUNCTION PROTOTYPES

// Returns the critical multiplier of an item of base item type nItemType.
int getCriticalMultiplier(int nItemType);

// Returns the critical range of an item of base item type nItemType.
int getCriticalRange(int nItemType);

//------------------------------------------------------------------------------
// FUNCTION DEFINITIONS

// Returns the critical multiplier of an item of base item type nItemType.
int getCriticalMultiplier(int nItemType)
{
    return StringToInt(Get2DAString("baseitems", "CritHitMult", nItemType));
}

// Returns the critical range of an item of base item type nItemType.
int getCriticalRange(int nItemType)
{
    return StringToInt(Get2DAString("baseitems", "CritThreat", nItemType));
}
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License