The eScript and Distro Style Guide
eScript Style and Distro submission Guide
This is a suggested guide for those writing eScript programs and a required guide for those on the Distro team or for those wishing to submit eScript programs or packages to the Distro. I want to thank Austin for creating the original style guide. I'm pretty sure it was his handy work. If not, then my thanks to whomever created it. I changed a few things but most of this guide was taken from the original.
In this guide I will almost always use the word program when referring to an eScript script.
Naming Conventions:
-------------------
FileNames:
All single word or single word and partial word file names should be lower case.
With filenames containing multiple words, the letter of the first word is lowercase, while the first letter of each additional word is capitalized. This naming convention is known as camelCase. All file extensions are lowercase.
The case of the file name is important on non-Windows systems such as Linux. On Linux systems npcBackpack.inc and NPCBackpack.inc are interpreted as different files.
Note: I will concede that abbreviations in a file name can be uppercase eg. NPCBackpack.inc. Just make certain that your references to those files in scripts match the same case as the file name.
Variable Declaration:
Regular variables:
Note on variable declarations: Because eScript is a loosely typed language, with regular variables you do not need to assign a value to a variable, or specify its type, when you declare it. The code is legal in the following example:
Changing the type of value stored in a variable is not good coding practice but in eScript, it is allowed. It also can be convenient and that's why you might see it done in some scripts. Do not do it in any code submitted to the Distro! It can create issues and it is harder to debug.
Please give your variables names that are relevant to the values they might hold. For example, if your variable might contain the amount of gold found in a character's backpack name it something like char_gold or mobile_gold. Longer variable names are allowed. Do not be afraid to use long names, if necessary, to be descriptive. Remember, you, or someone else, may need to review the code at some point in the future. Descriptive variable names will help in understanding what your program is doing. Variables used for iterations in for loops can be single characters eg. i, j, k unless they are used later in your code and need to be descriptive. Variables are not case sensitive. The variable names “Time” and “time” will be interpreted by eCompile as the same variable.
Constants:
Constants should be in all caps (all capitalized) and words are separated using the underscore character '_'.
Note: Core constants, such as MOVEOBJECT_FORCELOCATION, do not always separate, or delimit, each word with an underscore character.
Note: Also, an oddity with eScript is that constants are case sensitive.
In the following example, eCompile will interpret the two constants as unique:
Special Variables:
There are three, variable types that must have their type declared in the var declaration, arrays, structs, and dicts (dictionaries).
Arrays:
Structs:
Dictionaries:
Functions:
All functions should use the PascalCase convention, which as you can see has the first
letter of each word capitalized.
Exceptions:
If the function/s is part of a special package it can include a small prefix to define its origin i.e. AP_GetSkill( who, skill_name ), which is a function in the attributes package.
Programs:
Please be descriptive with the name of the program. Here I am referring to the name given after the keyword “program” in your code. That name does not need to be the same as the file name but the names should be similar. Please use 'PascalCase' naming conventions for the program name within your code.
You can use any name after the program keyword of course. If the program is a text command you could append command_ or textcmd_ to the beginning of the name or if it is a spell program, append spell_ to the name. That is not a requirement but it does help for quickly determining what the code is intended to do.
Note: When it comes to your code, eCompile and the eScript language is case neutral, unlike certain other languages. The case of a program name or variable does not affect compilation or execution of your programs. The only exception, which I noted above, are constants.
These guidelines are intended to promote readability of source code. File names are a different matter as they are sent to the operating system and on some systems case is important. Also, remember that with in-game text commands, the command is the file name. The command info, for example, is compiled from the file info.src to an executable file, info.ecl. So whatever you name the file for a text command, that will be the name you type in-game to execute the command, without the .ecl extension.
=== Other Formatting ===
Math:
This example is addressing general rules regarding order of operation than styles. In it, do you want the addition to be done before the multiplication? If so, then enclose the 4 + 3 in parenthesis.
This is how an expression should be formatted for the Distro:
Please note that I do not prefer spaces between parenthesis and values, or parenthesis and another parenthesis. However a case could be made for readability when having the spaces present. So we won't have a hard and fast rule regarding this. However spacing between values and operators is strongly encouraged.
Either of the following will be acceptable:
Strings:
The same rule applies to operators when used with strings. Always place a space between to operator and the string.
Function Usage:
Functions and method naming conventions for the Distro are PascalCase. Each word should begin with a capital letter. Even if the function name is a single word or part of the function name is an abbreviation. Methods should never contain the word “Method” in their name. Context will indicate that it is a method.
Properties:
Comments:
A word about comments in your code, you can never have too many comments documenting what your code is doing but you can certainly have too few. Remember, even though you wrote the code, you might need to make changes months or years afterward. By that time you may have forgotten a lot about how your program functios. Those comments will save you a lot of time when trying to understand what your code does. If you are contributing to an open source project, such as the Distro, good commenting of code will be invaluable to others who want to understand your program.
Whenever possible you should provide a comment block preceding a function like the example below.
Taken from Austin's damage.inc file:
If, While, etc. Stuff:
Please take note of the indentation inside the conditional statements (if and case) and the loops (while, do, repeat, and for etc.). This is important for readability so others can look at your code and understand it. You should always indent 4 spaces inside each if or loop.
The if block examples:
The or operator ( || ):
The and operator ( && ):
An example of nested if statements:
The case block:
The while block:
Thedo block:
The foreach block:
The for block:
Other Notes:
* If at all possible do not use spaces for indents, use tabs. Set your tab stop to the equivalent of 4 spaces. If you must use spaces indent 4 spaces.
All Distro scripts that use gumps, can use the gumps package to build them but this is not a hard and fast rule.
Additional Distro submission guidelines:
Follow as closely as possible the eScript guidelines for coding.
General use include files (*.inc) can be placed in /scripts/include. Examples are client.inc, itemtypes.inc etc.
All specialised include files specific to a package shall be included in the package that requires them. Under the package directory, create a sub-directory named include to hold those include files.
Packages:
Going forward, packages should be as self-contained as possible. This means that if at all humanly possible a package should be able to be dropped in without modifying any other packages or scripts outside the package. This is especially important if you are submitting an optional package that shard devs can, should they choose, add to their server. If you need to add or modify some function in an existing Distro include file, copy that include file to your package and modify it there. Please add comments in your copy of the file indicating where the changes were made. This will help keep the Distro as simple as possible.
Packages will follow the "Austin" format:
/pkg/packagename
<main scripts go here> start.src, logon.src, reconnect.src etc.
/pkg/packagename/commands
<any command specific to this package>
Commands need to be placed in sub directories in the /commands directory that pertain to the level of the intended user. In the Distro the folders must be named player, councilor (or coun), seer, gm, admin, developer (or dev), test. You only need to create the sub-directories that will actually contain commands.
/pkg/packagename/config
<cfg files> itemdesc.cfg, icp.cfg, npcdesc.cfg (for any custom NPCs your package may need) or any cfg files specific to the package.
/pkg/packagename/include
<include.inc files specific to this package>
/pkg/packagename/itemname
<method and use scripts required for an item defined in the package> Create additional itemname directories for additional items as required. The use script for an item should be named use.src and the method script should be named methods.src
Also familiarize yourself with the control package in \pkg\utils\control and create an icp.cfg file for your package. Try to be as thorough as possible when adding the info to the icp file.
If you do want to help by contributing to the Distro you can send me a personal message on the POL forums.
eScript Style and Distro submission Guide
This is a suggested guide for those writing eScript programs and a required guide for those on the Distro team or for those wishing to submit eScript programs or packages to the Distro. I want to thank Austin for creating the original style guide. I'm pretty sure it was his handy work. If not, then my thanks to whomever created it. I changed a few things but most of this guide was taken from the original.
In this guide I will almost always use the word program when referring to an eScript script.
Naming Conventions:
-------------------
FileNames:
All single word or single word and partial word file names should be lower case.
Code: Select all
initialize.src
getreg.src
Code: Select all
Examples:
npcBackpack.inc
myIncludeFile.inc
showAll.src
Exceptions:
Commands are all lowercase.
Core files, such as itemdesc.cfg, serverspecopt.cfg,npcdesc.cfg, etc., are all lowercase.
Note: I will concede that abbreviations in a file name can be uppercase eg. NPCBackpack.inc. Just make certain that your references to those files in scripts match the same case as the file name.
Variable Declaration:
Regular variables:
Note on variable declarations: Because eScript is a loosely typed language, with regular variables you do not need to assign a value to a variable, or specify its type, when you declare it. The code is legal in the following example:
Code: Select all
var something;
something := 1234;
something := "A string literal";
Please give your variables names that are relevant to the values they might hold. For example, if your variable might contain the amount of gold found in a character's backpack name it something like char_gold or mobile_gold. Longer variable names are allowed. Do not be afraid to use long names, if necessary, to be descriptive. Remember, you, or someone else, may need to review the code at some point in the future. Descriptive variable names will help in understanding what your program is doing. Variables used for iterations in for loops can be single characters eg. i, j, k unless they are used later in your code and need to be descriptive. Variables are not case sensitive. The variable names “Time” and “time” will be interpreted by eCompile as the same variable.
Code: Select all
Examples:
var stuff;
var my_integer;
var my_string;
var layer_array;
var counter i;
Constants should be in all caps (all capitalized) and words are separated using the underscore character '_'.
Code: Select all
CONST MY_CONSTANT := 10.0;
CONST NUMBER_OF_GUARDS := 100;
Note: Also, an oddity with eScript is that constants are case sensitive.
In the following example, eCompile will interpret the two constants as unique:
Code: Select all
const TIME := 1600;
const Time := 2200;
There are three, variable types that must have their type declared in the var declaration, arrays, structs, and dicts (dictionaries).
Arrays:
Code: Select all
// Preferred.
var a := {};
var a := array{1, 2, 3};
Code: Select all
// Struct setup
var my_var := struct; // This is preferred for readability. Assign members and values separately.
my_var.+member := something;
my_var.+member2;
// Or...
var my_var := struct{"member":=something, "member2"};
Code: Select all
// Dictionary Setup
var my_var := dict; // This is preferred for readability. Assign members and values separately.
var my_var := dictionary{"key"->value, "key2"->value};
All functions should use the PascalCase convention, which as you can see has the first
letter of each word capitalized.
Code: Select all
Examples:
function ListOnlineDrow(who)
function GetLastName(who, num_of_letters)
Methods:
object.MethodFunction(arguments)
If the function/s is part of a special package it can include a small prefix to define its origin i.e. AP_GetSkill( who, skill_name ), which is a function in the attributes package.
Programs:
Please be descriptive with the name of the program. Here I am referring to the name given after the keyword “program” in your code. That name does not need to be the same as the file name but the names should be similar. Please use 'PascalCase' naming conventions for the program name within your code.
Code: Select all
Examples:
(FileName is "bardInst.src"), thus the program should be named:
program BardInstruments(item)
(FileName is "enumTowns.src), thus the program should be named:
program EnumerateTowns(who, uX, uY, lX, lY, realm)
Note: When it comes to your code, eCompile and the eScript language is case neutral, unlike certain other languages. The case of a program name or variable does not affect compilation or execution of your programs. The only exception, which I noted above, are constants.
These guidelines are intended to promote readability of source code. File names are a different matter as they are sent to the operating system and on some systems case is important. Also, remember that with in-game text commands, the command is the file name. The command info, for example, is compiled from the file info.src to an executable file, info.ecl. So whatever you name the file for a text command, that will be the name you type in-game to execute the command, without the .ecl extension.
=== Other Formatting ===
Math:
This example is addressing general rules regarding order of operation than styles. In it, do you want the addition to be done before the multiplication? If so, then enclose the 4 + 3 in parenthesis.
Code: Select all
var math := 4 + 3 * 10;
var pemdas := ( ( 4 * 4 ) + ( 8 / ( 3 + 2 ) ) ) - ( 100 + some_var );
Code: Select all
var pemdas := ( ( 4 * 4 ) + ( 8 / ( 3 + 2 ) ) ) - ( 100 + some_var );
Either of the following will be acceptable:
Code: Select all
var pemdas := ((4 * 4) + (8 / (3 + 2))) - (100 + some_var);
var pemdas := ( ( 4 * 4 ) + ( 8 / ( 3 + 2 ) ) ) - ( 100 + some_var );
Strings:
The same rule applies to operators when used with strings. Always place a space between to operator and the string.
Code: Select all
var string := "Hello there " + "Stephen." + " I am " + math + " years old.";
Functions and method naming conventions for the Distro are PascalCase. Each word should begin with a capital letter. Even if the function name is a single word or part of the function name is an abbreviation. Methods should never contain the word “Method” in their name. Context will indicate that it is a method.
Code: Select all
var random_weapon := PickRandWeap();
var value := SomeFunction(argument_1, argument_2);
var other_value := object.SomeFunction(argument_1); // This is an example of a call to an object’s method.
Code: Select all
object.somepropery := some_value;
Code: Select all
// Do unto others as you would have them do unto you.
// Matthew 7:12
/*
* This is another option
* When creating multi line comments.
*
*/
A word about comments in your code, you can never have too many comments documenting what your code is doing but you can certainly have too few. Remember, even though you wrote the code, you might need to make changes months or years afterward. By that time you may have forgotten a lot about how your program functios. Those comments will save you a lot of time when trying to understand what your code does. If you are contributing to an open source project, such as the Distro, good commenting of code will be invaluable to others who want to understand your program.
Whenever possible you should provide a comment block preceding a function like the example below.
Taken from Austin's damage.inc file:
Code: Select all
/*
* ApplySpellDamageEX(mobile, amount, type, source, circle)
*
* Purpose: Does spell damage to mobile taking into account mobile's AR
*
* Parameters
* mobile: Victim
* amount: Raw damage
* type: Fire, cold, energy, poison or physical
* source: Source of the damage
* circle: Circle or level of spell. Basic spells are 1 through 8.
*
* Return value: damage amount done
*
*/
Please take note of the indentation inside the conditional statements (if and case) and the loops (while, do, repeat, and for etc.). This is important for readability so others can look at your code and understand it. You should always indent 4 spaces inside each if or loop.
The if block examples:
Code: Select all
if ( something )
Code here;
endif
Code: Select all
if ( this || that ) // Don't use 'or' spelled out.
Code: Select all
if ( this && that ) // Don't use 'and' spelled out.
if ( this || ( one && two ) ) // Parenthesis are important for order of operations.
Code: Select all
if(something)
this gets done...
if(this happens)
this other stuff gets done
else
do this stuff
endif
endif
Code: Select all
case ( something )
value: code;
break;
default: code;
break;
endcase
Code: Select all
while ( something )
code here;
sleepms(2);
endwhile
Code: Select all
do
codehere;
sleepms(2);
dowhile ( case );
Code: Select all
foreach iteration in ( iterated )
codehere;
sleepms(2);
endforeach
Code: Select all
for i:=1 to value
codehere;
sleepms(2);
endfor
* If at all possible do not use spaces for indents, use tabs. Set your tab stop to the equivalent of 4 spaces. If you must use spaces indent 4 spaces.
All Distro scripts that use gumps, can use the gumps package to build them but this is not a hard and fast rule.
Additional Distro submission guidelines:
Follow as closely as possible the eScript guidelines for coding.
General use include files (*.inc) can be placed in /scripts/include. Examples are client.inc, itemtypes.inc etc.
All specialised include files specific to a package shall be included in the package that requires them. Under the package directory, create a sub-directory named include to hold those include files.
Packages:
Going forward, packages should be as self-contained as possible. This means that if at all humanly possible a package should be able to be dropped in without modifying any other packages or scripts outside the package. This is especially important if you are submitting an optional package that shard devs can, should they choose, add to their server. If you need to add or modify some function in an existing Distro include file, copy that include file to your package and modify it there. Please add comments in your copy of the file indicating where the changes were made. This will help keep the Distro as simple as possible.
Packages will follow the "Austin" format:
/pkg/packagename
<main scripts go here> start.src, logon.src, reconnect.src etc.
/pkg/packagename/commands
<any command specific to this package>
Commands need to be placed in sub directories in the /commands directory that pertain to the level of the intended user. In the Distro the folders must be named player, councilor (or coun), seer, gm, admin, developer (or dev), test. You only need to create the sub-directories that will actually contain commands.
/pkg/packagename/config
<cfg files> itemdesc.cfg, icp.cfg, npcdesc.cfg (for any custom NPCs your package may need) or any cfg files specific to the package.
/pkg/packagename/include
<include.inc files specific to this package>
/pkg/packagename/itemname
<method and use scripts required for an item defined in the package> Create additional itemname directories for additional items as required. The use script for an item should be named use.src and the method script should be named methods.src
Also familiarize yourself with the control package in \pkg\utils\control and create an icp.cfg file for your package. Try to be as thorough as possible when adding the info to the icp file.
If you do want to help by contributing to the Distro you can send me a personal message on the POL forums.