Prologue
When I first got into *Athena scripting, it would have been a great convenience to have a decent guide, teacher, or even a friend to learn with. Back then, the documentation for script commands wasn't very good (not that it's anything glamourous now), people didn't have the patience to sit down and go over the basics, and my friends who were into computers/gaming had no interest in anything remotely related to programming.
A lot has changed over the years, and it's been rather interesting to see myself push the limits of *Athena emulators through mere scripting; if you asked me to explain making source modifications for *Athena emulators, you'd hear me blabber things I learned in a C++ programming class I took over summer, and that's about as helpful as I can get - and *Athena emulators were written in C.
But enough about me; let's get back to why you're here.
I: Structure and Formatting
In this section, we'll cover basic script structure and formatting.
Sample script:
Let's break this down, piece by piece:
Location
Determine the location you would like your NPC to be on by moving to that area and typing '/where' in-game. If you would like your NPC to not have a physical location (known as a "floating" NPC), use a hyphen <->.
Object
Define the type of object you are writing, and its corresponding name(s).
Scripting
Like our header, the whitespace used to indent sections of our script are tabs, not spaces. Make a habit of indenting your script (especially if its nested/enclosed) with one tab; this improves readability and makes it easier for others to understand different sections of your script.
End of Script
II: Variables
As your scripts become more complex, you'll find yourself wanting ways to reduce repetitiveness and increase flexibility. Typing the same thing over and over again gets old fast; we can improve scripts by using variables to represent constant values within our script. Variables can also be used to represent temporary values within our script - or even permanent values that can be referred to by other scripts as well. Let's go over the various variable types and how we can use them. For the sake of shorthanding, let's name the example variable "var".
Types
There are two types of variables that determine what data can be stored in the variable.
Similar to a type, the extent of a variable indicates how long it can be used.
Variables have different ranges that they can effect; known as "scopes", these determine what they can be used for. When a variable is "attached", it means that variable is stuck with its attachment wherever they go or are invoked.
When I first got into *Athena scripting, it would have been a great convenience to have a decent guide, teacher, or even a friend to learn with. Back then, the documentation for script commands wasn't very good (not that it's anything glamourous now), people didn't have the patience to sit down and go over the basics, and my friends who were into computers/gaming had no interest in anything remotely related to programming.
A lot has changed over the years, and it's been rather interesting to see myself push the limits of *Athena emulators through mere scripting; if you asked me to explain making source modifications for *Athena emulators, you'd hear me blabber things I learned in a C++ programming class I took over summer, and that's about as helpful as I can get - and *Athena emulators were written in C.
But enough about me; let's get back to why you're here.
I: Structure and Formatting
In this section, we'll cover basic script structure and formatting.
Sample script:
prontera,144,174,3 script Test NPC#prt::testnpc 4_M_MOCASS2,{ mes "[Test NPC]"; mes "Text will be displayed here."; close; }
Let's break this down, piece by piece:
prontera,144,174,3 script Test NPC#prt::testnpc 4_M_MOCASS2,{
Location
Determine the location you would like your NPC to be on by moving to that area and typing '/where' in-game. If you would like your NPC to not have a physical location (known as a "floating" NPC), use a hyphen <->.
- prontera - the name of the map which the NPC will be located
- 144 - the x-coordinate of the target cell the NPC will be placed upon
- 174 - the y-coordinate of the target cell the NPC will be placed upon
- 3 - the direction which the NPC will be facing
[1][0][7] [2] [6] [3][4][5]
Object
Define the type of object you are writing, and its corresponding name(s).
- script - defines the object as an NPC script
- other objects include duplicates, shops, warps, mapflags, etc. - but we'll get into that later
- Test NPC - the visible part of an NPC's display name; if no other names are given, this defaults as the NPC's unique name as well
- #prt - the hidden part of an NPC's display name, prefixed with a pound sign <#>; it serves as an identifier to distinguish duplicates
- ::testnpc - the NPC's unique name, prefixed with two colons <::>; it is the name used when duplicating, warping to, or unloading NPCs
- 4_M_MOCASS2 - the NPC's sprite name constant which will be displayed; before 9f32aa9, this was commonly just the sprite ID
- Sprite IDs are still acceptable to use; if you want your NPC to be invisible, use -1
- A complete list of constants can be found in db/const.txt
- ,{ - this is the opening brace (also known as a "curly"), prefixed with a comma <,>; it ends the header and indicates the beginning of the script
- A common mistake is to forget that comma - so don't forget!
Scripting
mes "[Test NPC]"; mes "Text will be displayed here."; close;Let's tell our script what we want our NPC to do; write out your script commands! A complete list of script commands can be found in doc/script_commands.txt.
- mes - tells the script parser that we want to display a message in a dialogue box
- "[Test NPC]" - the NPC's name, enclosed in quotation marks <">; quotation marks won't be displayed
- This is simply a vanity; an NPC name is not required, but it looks nice
- Any text enclosed in quotation marks from a mes command will be displayed in a dialogue box
- ; - script commands MUST end with a semi-colon <;> to indicate the end of the command
- close - creates a close button and terminates the script once encountered
- Don't forget that trailing semi-colon; close is a command too!
Like our header, the whitespace used to indent sections of our script are tabs, not spaces. Make a habit of indenting your script (especially if its nested/enclosed) with one tab; this improves readability and makes it easier for others to understand different sections of your script.
End of Script
}The last thing you'll need to remember is to close that brace we opened earlier, when we wrote the header.
- } - the closing brace, which is complementary to the opening brace in the header; it encloses the script and indicates the end of the file
II: Variables
As your scripts become more complex, you'll find yourself wanting ways to reduce repetitiveness and increase flexibility. Typing the same thing over and over again gets old fast; we can improve scripts by using variables to represent constant values within our script. Variables can also be used to represent temporary values within our script - or even permanent values that can be referred to by other scripts as well. Let's go over the various variable types and how we can use them. For the sake of shorthanding, let's name the example variable "var".
Types
There are two types of variables that determine what data can be stored in the variable.
- Integer variables are not postfixed with anything, and can only store numerical values
var = 1;
- String variables are postfixed with a dollar <$> sign, and can store various letters, symbols, numerical values in the form of strings
var$ = "Some string of letters (abc), symbols ($#) and numbers (123).";
Similar to a type, the extent of a variable indicates how long it can be used.
- Temporary variables are prefixed with an at <@> sign, and only last as long as the variable's scope will allow
@var = 1;
- Permanent variables are not prefixed with anything other than their scope's prefix, and will last indefinitely unless they are cleared
var = 1;
Variables have different ranges that they can effect; known as "scopes", these determine what they can be used for. When a variable is "attached", it means that variable is stuck with its attachment wherever they go or are invoked.
- NPC
NPC variables are prefixed with a period <.> and are attached to the invoking script; temporary NPC variables are cleared when the script ends .var = 1; // Permanent NPC variable
.@var = 1; // Temporary NPC variable
- Character
Character variables are prefixed with nothing and are attached to the invoking player; temporary character variables are cleared when the player logs out
var = 1; // Permanent character variable
@var = 1; // Temporary character variable
- Account
Account variables are prefixed with a pound sign <#> and are attached to the invoking player's account; there is no temporary version of this scope
#var = 1; // Permanent account variable
- Global Account
Global account variables are prefixed with two pound signs <##> and are stored in the login server; the only differentiation this scope has from normal account variables is that global variables can be accessed across multiple character servers
##var = 1; // Permanent global account variable
- Global
Global variables are prefixed with a dollar sign <$> and can be accessed from any script; temporary global variables are cleared when the server is restarted
$var = 1; // Permanent global variable
$@var = 1; // Temporary global variable
- Instance
Instance variables are prefixed with an apostrophe <'> and are attached to the invoking party's instance; there is no temporary version of this scope
'var = 1; // Permanent instance variable
Awesome +1