summaryrefslogtreecommitdiff
path: root/doc/script_commands.txt
diff options
context:
space:
mode:
Diffstat (limited to 'doc/script_commands.txt')
-rw-r--r--doc/script_commands.txt7752
1 files changed, 7752 insertions, 0 deletions
diff --git a/doc/script_commands.txt b/doc/script_commands.txt
new file mode 100644
index 000000000..2b1aa5d59
--- /dev/null
+++ b/doc/script_commands.txt
@@ -0,0 +1,7752 @@
+//===== rAthena Documentation ================================
+//= rAthena Script Commands
+//===== By: ==================================================
+//= rAthena Dev Team
+//===== Current Version: =====================================
+//= $Revision$
+//===== Last Updated: ========================================
+//= $LastChangedDate$
+//===== Description: =========================================
+//= A reference manual for the rAthena scripting language.
+//= Commands are sorted depending on their functionality.
+//============================================================
+
+This document is a reference manual for all the scripting commands and functions
+available in current rAthena SVN. It is not a simple tutorial. When people tell
+you to "Read The F***ing Manual", they mean this.
+
+The information was mostly acquired through looking up how things actually work
+in the source code of the server, which was written by many people over time,
+and lots of them don't speak English and never left any notes - or are otherwise
+not available for comments. As such, anything written in here might not be
+correct, it is only correct to the best of our knowledge, which is limited.
+
+This is not a place to teach you basic programming. This document will not teach
+you basic programming by itself. It's more of a reference for those who have at
+least a vague idea of what they want to do and want to know what tools they have
+available to do it. We've tried to keep it as simple as feasible, but if you
+don't understand it, getting a clear book on programming in general will help
+better than yelling around the forum for help.
+
+A little learning never caused anyone's head to explode.
+
+Structure
+---------
+
+The commands and functions are listed in no particular order:
+
+*Name of the command and how to call it.
+
+Descriptive text
+
+ Small example if possible. Will usually be incomplete, it's there just to
+ give you an idea of how it works in practice.
+
+To find a specific command, use Ctrl+F, (or whatever keys call up a search
+function in whatever you're reading this with) put an * followed by the command
+name, and it should find the command description for you.
+
+If you find anything omitted, please respond. :)
+
+Syntax
+------
+
+Throughout this document, wherever a command wants an argument, it is given in
+<angle brackets>. This doesn't mean you should type the angle brackets. :) If an
+argument of a command is optional, it is given in {curly brackets}. You've
+doubtlessly seen this convention somewhere, if you didn't, get used to it,
+that's how big boys do it. If a command can optionally take an unspecified
+number of arguments, you'll see a list like this:
+
+command <argument>{,<argument>...<argument>}
+
+This still means they will want to be separated by commas.
+
+Where a command wants a string, it will be given in "quotes", if it's a number,
+it will be given without them. Normally, you can put an expression, like a bunch
+of functions or operators returning a value, in (round brackets) instead of most
+numbers. Round brackets will not always be required, but they're often a good
+idea.
+
+Wherever you refer to a map name, it's always 'mapname' or 'mapname.gat'
+(Please, don't use .gat suffix anymore. It's useless.)
+
+
+Script loading structure
+------------------------
+
+Scripts are loaded by the map server as referenced in the 'conf/map_athena.conf'
+configuration file, but in the default configuration, it doesn't load any script
+files itself. Instead, it loads the file 'npc/scripts_main.conf' which itself
+contains references to other files. The actual scripts are loaded from txt
+files, which are linked up like this:
+
+npc: <path to a filename>
+
+Any line like this, invoked, ultimately, by 'map_athena.conf' will load up the
+script contained in this file, which will make the script available. No file
+will get loaded twice, to prevent possible errors.
+
+Another configuration file option of relevance is:
+
+delnpc: <path to a filename>
+
+This will unload a specified script filename from memory, which, while
+seemingly useless, may sometimes be required.
+
+Whenever '//' is encountered in a line upon reading, everything beyond this on
+that line is considered to be a comment and is ignored. This works wherever you
+place it.
+
+// This line will be ignored when processing the script.
+
+Block comments can also be used, where you can place /* and */ between any text you
+wish rAthena to ignore.
+
+Example:
+/* This text,
+ * no matter which new line you start
+ * is ignored, until the following
+ * symbol is encountered: */
+
+The asterisks (*) in front of each line is a personal preference, and is not required.
+
+Upon loading all the files, the server will execute all the top-level commands
+in them. No variables exist yet at this point, no commands can be called other
+than those given in this section. These commands set up the basic server script
+structure - create NPC objects, spawn monster objects, set map flags, etc. No
+code is actually executed at this point except them. The top-level commands the
+scripting are pretty confusing, since they aren't structured like you would
+expect commands, command name first, but rather, normally start with a map name.
+
+What's more confusing about the top-level commands is that most of them use a
+tab symbol to divide their arguments.
+
+To prevent problems and confusion, the tab symbols are written as '%TAB%'
+throughout this document, even though this makes the text a bit less readable.
+Using an invisible symbol to denote arguments is one of the bad things about
+this language, but we're stuck with it for now. :)
+
+Here is a list of valid top-level commands:
+
+** Set a map flag:
+
+<map name>%TAB%mapflag%TAB%<flag>
+
+This will, upon loading, set a specified map flag on a map you like. These are
+normally in files inside 'conf/mapflag' and are loaded first, so by the time the
+server's up, all the maps have the flags they should have. Map flags determine
+the behavior of the map regarding various common problems, for a better
+explanation, see 'setmapflag'.
+
+** Create a permanent monster spawn:
+
+<map name>,<x>,<y>,<xs>,<ys>%TAB%monster%TAB%<monster name>%TAB%<mob id>,<amount>,<delay1>,<delay2>,<event>{,<mob size>,<mob ai>}
+
+Map name is the name of the map the monsters will spawn on. x,y are the
+coordinates where the mob should spawn. If xs and ys are non-zero, they
+specify the 'radius' of a spawn-rectangle area centered at x,y.
+Putting zeros instead of these coordinates will spawn the monsters randomly.
+Note this is only the initial spawn zone, as mobs random-walk, they are free
+to move away from their specified spawn region.
+
+Monster name is the name the monsters will have on screen, and has no relation
+whatsoever to their names anywhere else. It's the mob id that counts, which
+identifies monster record in 'mob_db.txt' database of monsters. If the mob name
+is given as "--ja--", the 'japanese name' field from the monster database is
+used, (which, in rAthena, actually contains an English name) if it's "--en--",
+it's the 'english name' from the monster database (which contains an uppercase
+name used to summon the monster with a GM command).
+
+Amount is the amount of monsters that will be spawned when this command is
+executed, it is affected by spawn rates in 'battle_athena.conf'.
+
+Delay1 and delay2 control monster respawn delays - the first one is the fixed
+base respawn time, and the second is random variance on top of the base time.
+Both values are given in milliseconds (1000 = 1 second).
+Note that the server also enforces a minimum respawn delay of 5 seconds.
+
+You can specify a custom level to use for the mob different from the one of
+the database by adjoining the level after the name with a comma. eg:
+"Poring,50" for a name will spawn a monster with name Poring and level 50.
+
+Event is a script event to be executed when the mob is killed. The event must
+be in the form "NPCName::OnEventName" to execute, and the event name label
+should start with "On". As with all events, if the NPC is an on-touch NPC, the
+player who triggers the script must be within 'trigger' range for the event to
+work.
+
+There are two optional fields for monster size and AI. Size can be 0 (medium),
+1 (small), or 2 (big). AI can be 0 (default), 1 (attack/friendly), 2 (sphere),
+3 (flora), or 4 (zanzou).
+
+Alternately, a monster spawned using 'boss_monster' instead of 'monster' is able
+to be detected on the map with the SC_BOSSMAPINFO status (used by Convex Mirror).
+
+** NPC names
+
+/!\ WARNING: this applies to warps, NPCs, duplicates and shops /!\
+
+NPC names are kinda special and are formatted this way:
+
+<Display name>{::<Unique name>}
+
+All NPCs need to have a unique name that is used for identification purposes.
+When you have to identify a NPC by it's name, you should use <Unique name>.
+If <Unique name> is not provided, use <Display name> instead.
+
+The client has a special feature when displaying names:
+if the display name contains a '#' character, it hides that part of the name.
+ex: if your NPC is named 'Hunter#hunter1', it will be displayed as 'Hunter'
+
+<Display name> must be at most 24 characters in length.
+<Unique name> must be at most 24 characters in length.
+
+** Define a warp point
+
+<from map name>,<fromX>,<fromY>,<facing>%TAB%warp%TAB%<warp name>%TAB%<spanx>,<spany>,<to map name>,<toX>,<toY>
+
+This will define a warp NPC that will warp a player between maps, and while most
+arguments of that are obvious, some deserve special mention.
+
+SpanX and SpanY will make the warp sensitive to a character who didn't step
+directly on it, but walked into a zone which is centered on the warp from
+coordinates and is SpanX in each direction across the X axis and SpanY in each
+direction across the Y axis.
+
+Warp NPC objects also have a name, because you can use it to refer to them later
+with 'enablenpc'/'disablenpc'
+
+Facing of a warp object is irrelevant, it is not used in the code and all
+current scripts have a zero in there.
+
+** Define an NPC object.
+
+<map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,{<code>}
+<map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY>,{<code>}
+
+This will place an NPC object on a specified map at the specified location, and
+is a top-level command you will use the most in your custom scripting. The NPCs
+are triggered by clicking on them, and/or by walking in their trigger area, if
+defined, see that below.
+
+Facing is a direction the NPC sprite will face in. Not all NPC sprites have
+different images depending on the direction you look from, so for some facing
+will be meaningless. Facings are counted counterclockwise in increments of 45
+degrees, where 0 means facing towards the top of the map. (So to turn the sprite
+towards the bottom of the map, you use facing 4, and to make it look southeast
+it's facing 5.)
+
+Sprite id is the sprite number used to display this particular NPC. For a full
+list of sprite id numbers see http://kalen.s79.xrea.com/npc/npce.shtml You may
+also use a monster's ID number instead to display a monster sprite for this NPC.
+It is possible to use a job sprite as well, but you must first define it as a
+monster sprite in 'mob_avail.txt', a full description on how to do this is not
+in the scope of this manual.
+A '-1' sprite id will make the NPC invisible (and unclickable).
+A '111' sprite id will make an NPC which does not have a sprite, but is still
+clickable, which is useful if you want to make a clickable object of the 3D
+terrain.
+
+TriggerX and triggerY, if given, will define an area, centered on NPC and
+spanning triggerX cells in every direction across X and triggerY in every
+direction across Y. Walking into that area will trigger the NPC. If no
+'OnTouch:' special label is present in the NPC code, the execution will start
+from the beginning of the script, otherwise, it will start from the 'OnTouch:'
+label. Monsters can also trigger the NPC, though the label 'OnTouchNPC:' is
+used in this case.
+
+The code part is the script code that will execute whenever the NPC is
+triggered. It may contain commands and function calls, descriptions of which
+compose most of this document. It has to be in curly brackets, unlike elsewhere
+where we use curly brackets, these do NOT signify an optional parameter.
+
+** Define a 'floating' NPC object.
+
+-%TAB%script%TAB%<NPC Name>%TAB%-1,{<code>}
+
+This will define an NPC object not triggerable by normal means. This would
+normally mean it's pointless since it can't do anything, but there are
+exceptions, mostly related to running scripts at specified time, which is what
+these floating NPC objects are for. More on that below.
+
+** Define a shop/cashshop NPC.
+
+-%TAB%shop%TAB%<NPC Name>%TAB%<sprite id>,<itemid>:<price>{,<itemid>:<price>...}
+<map name>,<x>,<y>,<facing>%TAB%shop%TAB%<NPC Name>%TAB%<sprite id>,<itemid>:<price>{,<itemid>:<price>...}
+
+This will define a shop NPC, which, when triggered (which can only be done by
+clicking) will cause a shop window to come up. No code whatsoever runs in shop
+NPCs and you can't change the prices otherwise than by editing the script
+itself. (No variables even exist at this point of scripting, so don't even
+bother trying to use them.)
+
+The item id is the number of item in the 'item_db.txt' database. If Price is set
+to -1, the 'buy price' given in the item database will be used. Otherwise, the
+price you gave will be used for this item, which is how you create differing
+prices for items in different shops.
+
+Since trunk r12264 you can alternatively use "cashshop" in place of "shop"
+to use the Cash Shop interface, allowing you to buy items with special points
+(Currently stored as account vars in global_reg #CASHPOINTS and #KAFRAPOINTS.)
+This type of shop will not allow you to sell items at it, you may only
+purchase items here. The layout used to define sale items still count, and
+"<price>" refers to how many points will be spent purchasing the them.
+
+** Define an warp/shop/cashshop/NPC duplicate.
+
+warp: <map name>,<x>,<y>,<facing>%TAB%duplicate(<label>)%TAB%<NPC Name>%TAB%<spanx>,<spany>
+shop/cashshop/npc: -%TAB%duplicate(<label>)%TAB%<NPC Name>%TAB%<sprite id>
+shop/cashshop/npc: <map name>,<x>,<y>,<facing>%TAB%duplicate(<label>)%TAB%<NPC Name>%TAB%<sprite id>
+npc: -%TAB%duplicate(<label>)%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY>
+npc: <map name>,<x>,<y>,<facing>%TAB%duplicate(<label>)%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY>
+
+This will duplicate an warp/shop/cashshop/NPC referred to by 'label'.
+Warp duplicates inherit the target location.
+Shop/cashshop duplicates inherit the item list.
+NPC duplicates inherit the script code.
+The rest (name, location, facing, sprite ID, span/trigger area)
+is obtained from the definition of the duplicate (not inherited).
+
+** Define a function object
+
+function%TAB%script%TAB%<function name>%TAB%{<code>}
+
+This will define a function object, callable with the 'callfunc' command (see
+below). This object will load on every map server separately, so you can get at
+it from anywhere. It's not possible to call the code in this object by
+anything other than the 'callfunc' script command.
+
+The code part is the script code that will execute whenever the function is
+called with 'callfunc'. It has to be in curly brackets, unlike elsewhere where
+we use curly brackets, these do NOT signify an optional parameter.
+
+
+Once an object is defined which has a 'code' field to it's definition, it
+contains script commands which can actually be triggered and executed.
+
+~ RID? GID? ~
+
+What a RID is and why do you need to know
+-----------------------------------------
+
+Most scripting commands and functions will want to request data about a
+character, store variables referenced to that character, send stuff to the
+client connected to that specific character. Whenever a script is invoked by a
+character, it is passed a so-called RID - this is the account ID number of a
+character that caused the code to execute by clicking on it, walking into it's
+OnTouch zone, or otherwise.
+
+If you are only writing common NPCs, you don't need to bother with it. However,
+if you use functions, if you use timers, if you use clock-based script
+activation, you need to be aware of all cases when a script execution can be
+triggered without a RID attached. This will make a lot of commands and functions
+unusable, since they want data from a specific character, want to send stuff to
+a specific client, want to store variables specific to that character, and they
+would not know what character to work on if there's no RID.
+
+Unless you use 'attachrid' to explicitly attach a character to the script first.
+
+Whenever we say 'invoking character', we mean 'the character who's RID is
+attached to the running script. The script function "playerattached" can be
+used to check which is the currently attached player to the script (it will
+return 0 if the there is no player attached or the attached player no longer
+is logged on to the map-server).
+
+But what about GID?
+--- ---- ----- ----
+
+GID stands for the Game ID of something, this can either be the GID obtained
+through mobspawn (mob control commands) or the account ID of a character.
+Another way would be to right click on a mob,
+NPC or char as GM sprited char to view the GID.
+
+This is mostly used for the new version of skill and the mob control commands
+implemented (but NEVER documented by Lance. Shame on you...).
+
+Item and pet scripts
+--------------------
+
+Each item in the item database has three special fields - Script , OnEquip_Script
+and OnUnequip_Script. The first is script code run every time a character equips the item,
+with the RID of the equipping character. Every time they unequip an item, all
+temporary bonuses given by the script commands are cleared, and all the scripts
+are executed once again to rebuild them. This also happens in several other
+situations (like upon login) but the full list is currently unknown.
+
+OnEquip_Script is a piece of script code run whenever the item is used by a character
+by double-clicking on it. OnUnequip_Script runs whenever the
+equipment is unequip by a character
+
+Not all script commands work properly in the item scripts. Where commands and
+functions are known to be meant specifically for use in item scripts, they are
+described as such.
+
+Every pet in the pet database has a PetScript field, which determines pet
+behavior. It is invoked wherever a pet of the specified type is spawned.
+(hatched from an egg, or loaded from the char server when a character who had
+that pet following them connects) This may occur in some other situations as
+well. Don't expect anything other than commands definitely marked as usable in
+pet scripts to work in there reliably.
+
+Numbers
+-------
+
+Beside the common decimal numbers, which are nothing special whatsoever (though
+do not expect to use fractions, since ALL numbers are integer in this language),
+the script engine also handles hexadecimal numbers, which are otherwise
+identical. Writing a number like '0x<hex digits>' will make it recognized as a
+hexadecimal value. Notice that 0x10 is equal to 16. Also notice that if you try
+to 'mes 0x10' it will print '16'.
+
+This is not used much, but it pays to know about it.
+
+Variables
+---------
+
+The meat of every programming language is variables - places where you store
+data.
+
+In the rAthena scripting language, variable names are not case sensitive.
+
+Variables are divided into and uniquely identified by the combination of:
+prefix - determines the scope and extent (or lifetime) of the variable
+name - an identifier consisting of '_' and alphanumeric characters
+postfix - determines the type of the variable: integer or string
+
+Scope can be:
+global - global to all servers
+local - local to the server
+account - attached to the account of the character identified by RID
+character - attached to the character identified by RID
+npc - attached to the NPC
+scope - attached to the scope of the instance
+
+Extent can be:
+permanent - They still exist when the server resets.
+temporary - They cease to exist when the server resets.
+
+Prefix: scope and extent
+nothing - A permanent variable attached to the character, the default variable
+ type. They are stored with all the account data in "save\athena.txt"
+ in TXT versions and in the SQL versions in the `global_reg_value`
+ table using type 3.
+"@" - A temporary variable attached to the character.
+ SVN versions before 2094 revision and RC5 version will also treat
+ 'l' as a temporary variable prefix, so beware of having variable
+ names starting with 'l' if you want full backward compatibility.
+"$" - A global permanent variable.
+ They are stored in "save\mapreg.txt" or database table `mapreg`,
+ depending on server type.
+"$@" - A global temporary variable.
+ This is important for scripts which are called with no RID
+ attached, that is, not triggered by a specific character object.
+"." - A NPC variable.
+ They exist in the NPC and disappear when the server restarts or the
+ NPC is reloaded. Can be accessed from inside the NPC or by calling
+ 'getvariableofnpc'. Function objects can also have .variables which
+ are accessible from inside the function, however 'getvariableofnpc'
+ does NOT work on function objects.
+".@" - A scope variable.
+ They are unique to the instance and scope. Each instance has it's
+ own scope that ends when the script ends. Calling a function with
+ callsub/callfunc starts a new scope, returning from the function
+ ends it. When a scope ends, it's variables are converted to values
+ ('return .@var;' returns a value, not a reference).
+"'" - An instance variable
+ These are used with the instancing system, and are unique to each
+ party's instance.
+"#" - A permanent local account variable.
+ They are stored with all the account data in "save\accreg.txt" in
+ TXT versions and in the SQL versions in the 'global_reg_value'
+ table using type 2.
+"##" - A permanent global account variable stored by the login server.
+ They are stored in "save\account.txt" and in the SQL versions in the
+ 'global_reg_value' table, using type 1. The only difference you will
+ note from normal # variables is when you have multiple char-servers
+ connected to the same login server. The # variables are unique to
+ each char-server, while the ## variables are shared by all these
+ char-servers.
+
+Postfix: integer or string
+nothing - integer variable, can store positive and negative numbers, but only
+ whole numbers (so don't expect to do any fractional math)
+'$' - string variable, can store text
+
+Examples:
+ name - permanent character integer variable
+ name$ - permanent character string variable
+ @name - temporary character integer variable
+ @name$ - temporary character string variable
+ $name - permanent global integer variable
+ $name$ - permanent global string variable
+$@name - temporary global integer variable
+$@name$ - temporary global string variable
+ .name - NPC integer variable
+ .name$ - NPC string variable
+.@name - scope integer variable
+.@name$ - scope string variable
+ #name - permanent local account integer variable
+ #name$ - permanent local account string variable
+##name - permanent global account integer variable
+##name$ - permanent global account string variable
+
+If a variable was never set, it is considered to equal zero for integer
+variables or an empty string ("", nothing between the quotes) for string
+variables. Once you set it to that, the variable is as good as forgotten
+forever, and no trace remains of it even if it was stored with character or
+account data.
+
+Some variables are special, that is, they are already defined for you by the
+scripting engine. You can see the full list somewhere in 'db/const.txt', which
+is a file you should read, since it also allows you to replace lots of numbered
+arguments for many commands with easier to read text. The special variables most
+commonly used are all permanent character-based variables:
+
+Zeny - Amount of Zeny.
+Hp - Current amount of hit points.
+MaxHp - Maximum amount of hit points.
+Sp - Current spell points.
+MaxSp - Maximum amount of spell points.
+StatusPoint - Amount of status points remaining.
+SkillPoint - Amount of skill points remaining.
+BaseLevel - Character's base level.
+JobLevel - Character's job level.
+BaseExp - Amount of base experience points.
+JobExp - Amount of job experience points.
+NextBaseExp - Amount of base experience points needed to reach the next level.
+NextJobExp - Amount of job experience points needed to reach the next level.
+Weight - Amount of weight the character currently carries.
+MaxWeight - Maximum weight the character can carry.
+Sex - 0 if female, 1 if male.
+Class - Character's job.
+Upper - 0 if the character is a normal class, 1 if advanced, 2 if baby.
+BaseClass - The character's 1-1 'normal' job, regardless of Upper value.
+ For example, this will return Job_Acolyte for Acolyte, Priest/Monk,
+ High Priest/Champion, and Arch Bishop/Sura. If the character has not
+ reached a 1-1 class, it will return Job_Novice.
+BaseJob - The character's 'normal' job, regardless of Upper value.
+ For example, this will return Job_Acolyte for Acolyte,
+ Baby Acolyte, and High Acolyte.
+Karma - The character's karma. Karma system is not fully functional, but
+ this doesn't mean this doesn't work at all. Not tested.
+Manner - The character's manner rating. Becomes negative if the player
+ utters words forbidden through the use of 'manner.txt' client-side
+ file.
+
+While these behave as variables, do not always expect to just set them - it is
+not certain whether this will work for all of them. Whenever there is a command
+or a function to set something, it's usually preferable to use that instead. The
+notable exception is Zeny, which you can and often will address directly -
+setting it will make the character own this number of Zeny.
+If you try to set Zeny to a negative number, the script will be terminated with an error.
+
+Assigning variables
+--------- ---------
+
+As of rAthena revision 15982, variables can be accessed and assigned values directly
+without the use of the built-in 'set' function. This means that variables can be
+accessed and modified much like other programming languages.
+
+ @x = 100;
+ @x = @y = 100;
+
+Support for modifying variable values using 'set' is still supported (and required
+to exist for this new method to work) so previous scripts will continue to work.
+
+When assigning values, all operator methods are supported which exist in the below
+'Operators' section. For instance:
+
+ @x += 100;
+ @x -= 100;
+ @x *= 2;
+ @x /= 2;
+ @x %= 5;
+ @x >>= 2;
+ @x <<= 2;
+
+Will all work. For more information on available operators, see the Operators section
+described below. All operators listed there may be placed in-front of the '=' sign
+when modifying variables to perform the action as required.
+
+Note:
+
+ !! Currently the scripting engine does not support directly copying array variables.
+ !! In order to copy arrays between variables the use of 'copyarray' function is still
+ !! required.
+
+Strings
+-------
+
+To include symbol '"' in a string you should use prefix '\"'
+
+
+Arrays
+------
+
+Arrays (in rAthena at least) are essentially a set of variables going under the
+same name. You can tell between the specific variables of an array with an
+'array index', a number of a variable in that array:
+
+<variable name>[<array index>]
+
+Variables stored in this way, inside an array, are also called 'array elements'.
+Arrays are specifically useful for storing a set of similar data (like several
+item IDs for example) and then looping through it. You can address any array
+variable as if it was a normal variable:
+
+ set @arrayofnumbers[0],1;
+
+You can also do sneaky things like using a variable (or an expression, or even a
+value from an another array) to get at an array value:
+
+ set @x,100;
+ set @arrayofnumbers[@x],10;
+
+This will make @arrayofnumbers[100] equal to 10.
+
+Notice that index numbering always starts with 0. Arrays cannot hold more than
+128 variables. (So the last one can't have a number higher than 127)
+
+And array indexes probably can't be negative. Nobody tested what happens when
+you try to get a negatively numbered variable from an array, but it's not going
+to be pretty. :)
+
+Arrays can naturally store strings:
+
+@menulines$[0] is the 0th element of the @menulines$ array of strings. Notice
+the '$', normally denoting a string variable, before the square brackets that
+denotes an array index.
+
+Resume of the allowed variable and array scopes
+------ -- --- ------- -------- --- ----- ------
+
++==========+======+=======+
+|VarType | Norm | Array |
++==========+======+=======+
+|$Str$ | OK! | OK! |
++----------+------+-------+
+|$@Str$ | OK! | OK! |
++----------+------+-------+
+|@Str$ | OK! | OK! |
++----------+------+-------+
+|#Str$ | OK! | FAIL! |
++----------+------+-------+
+|Str$ | OK! | FAIL! |
++----------+------+-------+
+|$Int | OK! | OK! |
++----------+------+-------+
+|$@Int | OK! | OK! |
++----------+------+-------+
+|@Int | OK! | OK! |
++----------+------+-------+
+|#Int | OK! | FAIL! |
++----------+------+-------+
+|Int | OK! | FAIL! |
++----------+------+-------+
+|.Str$ | OK! | OK! |
++----------+------+-------+
+|.Int | OK! | OK! |
++----------+------+-------+
+|.@Str$ | OK! | OK! |
++----------+------+-------+
+|.@Int | OK! | OK! |
++----------+------+-------+
+
+Variable References
+-------------------
+
+//##TODO
+
+
+
+Operators
+---------
+
+Operators are things you can do to variables and numbers. They are either the
+common mathematical operations or conditional operators
+
++ - will add two numbers. If you try to add two strings, the result will be a
+ string glued together at the +. You can add a number to a string, and the
+ result will be a string. No other math operators work with strings.
+- - will subtract two numbers.
+* - will multiply two numbers.
+/ - will divide two numbers. Note that this is an integer division, i.e.
+ 7/2 is not equal 3.5, it's equal 3.
+% - will give you the remainder of the division. 7%2 is equal to 1.
+
+There are also conditional operators. This has to do with the conditional
+command 'if' and they are meant to return either 1 if the condition is satisfied
+and 0 if it isn't. (That's what they call 'boolean' variables. 0 means 'False'.
+Anything except the zero is 'True' Odd as it is, -1 and -5 and anything below
+zero will also be True.)
+
+You can compare numbers to each other and you compare strings to each other, but
+you can not compare numbers to strings.
+
+ == - Is true if both sides are equal. For strings, it means they are the same.
+ >= - True if the first value is equal to, or greater than, the second value.
+ <= - True if the first value is equal to, or less than, the second value
+ > - True if the first value greater than the second value
+ < - True if the first value is less than the second value
+ != - True if the first value IS NOT equal to the second one
+
+Examples:
+
+ 1==1 is True.
+ 1<2 is True while 1>2 is False.
+ @x>2 is True if @x is equal to 3. But it isn't true if @x is 2.
+
+Only '==' and '!=' have been tested for comparing strings. Since there's no way
+to code a seriously complex data structure in this language, trying to sort
+strings by alphabet would be pointless anyway.
+
+Comparisons can be stacked in the same condition:
+
+ && - Is True if and only if BOTH sides are true.
+ ('1==1 && 2==2' is true. '2==1 && 1==1' is false.)
+ || - Is True if either side of this expression is True.
+
+ 1==1 && 2==2 is True.
+ 1==1 && 2==1 is False.
+ 1==1 || 2==1 is True.
+
+Logical bitwise operators work only on numbers, and they are the following:
+
+ << - Left shift.
+ >> - Right shift.
+ Left shift moves the binary 1(s) of a number n positions to the left,
+ which is the same as multiplying by 2, n times.
+ In the other hand, Right shift moves the binary 1(s) of a number n positions
+ to the right, which is the same as dividing by 2, n times.
+ Example:
+ set b,2;
+ set a, b << 3;
+ mes a;
+ set a, a >> 2;
+ mes a;
+ The first mes command would display 16, which is the same as 2 x (2 x 2 x 2) = 16.
+ The second mes command would display 4, which is the same as 16 / 2 = 8. 8 / 2 = 4.
+ & - And.
+ | - Or.
+ The bitwise operator AND (&) is used to test two values against each other,
+ and results in setting bits which are active in both arguments. This can
+ be used for a few things, but in rAthena this operator is usually used to
+ create bit-masks in scripts.
+
+ The bitwise operator OR (|)sets to 1 a binary position if the binary position
+ of one of the numbers is 1. This way a variable can hold several values we can check,
+ known as bit-mask. A variable currently can hold up to 32 bit-masks (from position 0
+ to position 1). This is a cheap(skate) and easy way to avoid using arrays to store several checks
+ that a player can have.
+
+ A bit-mask basically is (ab)using the variables bits to set various options in
+ one variable. With the current limit if variables it is possible to store 32
+ different options in one variable (by using the bits on position 0 to 31).
+
+ Example(s):
+ - Basic example of the & operator, bit example:
+ 10 & 2 = 2
+ Why? :
+ 10 = 2^1 + 2^3 (2 + 8), so in bits, it would be 1010
+ 2 = 2^1 (2), so in bits (same size) it would be 0010
+ The & (AND) operator sets bits which are active (1) in both arguments, so in the
+ example 1010 & 0010, only the 2^1 bit is active (1) in both. Resulting in the bit
+ 0010, which is 2.
+ - Basic example of creating and using a bit-mask:
+ set @options,2|4|16; //(note: this is the same as 2+4+16, or 22)
+ if (@options & 1) mes "Option 1 is activated";
+ if (@options & 2) mes "Option 2 is activated";
+ if (@options & 4) mes "Option 3 is activated";
+ if (@options & 8) mes "Option 4 is activated";
+ if (@options & 16) mes "Options 5 is activated";
+ This would return the messages about option 2, 3 and 5 being shown (since we've set
+ the 2,4 and 16 bit to 1).
+ ^ - Xor.
+ The bitwise operator XOR (eXclusive OR) sets a binary position to 0 if both
+ numbers have the same value in the said position. On the other hand, it
+ sets to 1 if they have different values in the said binary position.
+ This is another way of setting and unsetting bits in bit-masks.
+
+ Example:
+ - First let's set the quests that are currently in progress:
+ set inProgress,1|8|16; // quest 1,8 and 16 are in progress
+ - After playing for a bit, the player starts another quest:
+ if( inProgress&2 == 0 ){
+ // this will set the bit for quest 2 (inProgress has that bit set to 0)
+ set inProgress,inProgress^2;
+ mes "Quest 2: find a newbie and be helpful to him for an hour.";
+ close;
+ }
+ - After spending some time reading info on Xor's, the player finally completes quest 1:
+ if( inProgress&1 && isComplete ){
+ // this will unset the bit for quest 1 (inProgress has that bit set to 1)
+ set inProgress,inProgress^1;
+ mes "Quest 1 complete!! You unlocked the secrets of the Xor dynasty, use them wisely.";
+ close;
+ }
+
+Unary operators with only with a single number, which follows the operator, and
+are following:
+
+ - - Negation.
+ The sign of the number will be reversed. If the number was positive, it will
+ become negative and vice versa.
+
+ Example:
+ set .@myvar,10;
+ mes "Negative 10 is "+(-.@myvar);
+
+ ! - Logical Not.
+ Reverses the boolean result of an expression. True will become false and
+ false will become true.
+
+ Example:
+ if(!callfunc("F_dosomething"))
+ {
+ mes "Doing something failed.";
+ close;
+ }
+
+ ~ - Bitwise Not.
+ Reverses each bit in a number, also known as one's complement. Cleared bits
+ are set, and set bits are cleared.
+
+ Example:
+ - Ensure, that quest 2 is disabled, while keeping all other active, if they are.
+ set inProgress,inProgress&(~2); // same as set inProgress,inProgress&0xfffffffd
+
+Ternary operators take three expressions (numbers, strings or boolean), and are
+following:
+
+ ?: - Conditional operator
+ Very useful e.g. to replace
+
+ if(Sex) mes "..."; else mes "...";
+
+ clauses with simple
+
+ mes "Welcome, " + (Sex?"Mr.":"Mrs.") + " " + strcharinfo(0);
+
+ or to replace any other simple if-else clauses. It might be worth
+ mentioning that ?: has low priority and has to be enclosed with
+ parenthesis in most (if not all) cases.
+
+Labels
+------
+
+Within executable script code, some lines can be labels:
+
+<label name>:
+
+Labels are points of reference in your script, which can be used to route
+execution with 'goto', 'menu' and 'jump_zero' commands, invoked with 'doevent'
+and 'donpcevent' commands and are otherwise essential. A label's name may not be
+longer than 22 characters. (23rd is the ':'.) There is some confusion in the
+source about whether it's 22, 23 or 24 all over the place, so keeping labels
+under 22 characters could be wise. It may only contain alphanumeric characters
+and underscore. In addition to labels you name yourself, there are also some
+special labels which the script engine will start execution from if a special
+event happens:
+
+OnClock<hour><minute>:
+OnMinute<minute>:
+OnHour<hour>:
+On<weekday><hour><minute>:
+OnDay<month><day>:
+
+This will execute when the server clock hits the specified date or time. Hours
+and minutes are given in military time. ('0105' will mean 01:05 AM). Weekdays
+are Sun,Mon,Tue,Wed,Thu,Fri,Sat. Months are 01 to 12, days are 01 to 31.
+Remember the zero. :)
+
+OnInit:
+OnInterIfInit:
+OnInterIfInitOnce:
+
+OnInit will execute every time the scripts loading is complete, including when
+they are reloaded with @reloadscript command. OnInterIfInit will execute when
+the map server connects to a char server, OnInterIfInitOnce will only execute
+once and will not execute if the map server reconnects to the char server later.
+
+OnAgitStart:
+OnAgitEnd:
+OnAgitInit:
+OnAgitStart2:
+OnAgitEnd2:
+OnAgitInit2:
+
+OnAgitStart will run whenever the server shifts into WoE mode, whether it is
+done with @agitstart GM command or with 'AgitStart' script command. OnAgitEnd
+will do likewise for the end of WoE.
+
+OnAgitInit will run when data for all castles and all guilds that hold a castle
+is received by map-server from the char-server after initial connect.
+
+No RID will be attached while any of the above mentioned labels are triggered, so
+no character or account-based variables will be accessible, until you attach a
+RID with 'attachrid' (see below).
+
+The above also applies to, the last three labels, the only difference is that
+these labels are used exclusively for WoE SE, and are called independently.
+
+OnTouch:
+
+This label will be executed if a trigger area is defined for the NPC object it's
+in. If it isn't present, the execution will start from the beginning of the NPC
+code. The RID of the triggering character object will be attached.
+
+OnTouch_:
+
+Similar to OnTouch, but will only run one instance. Another character is
+chosen once the triggering character leaves the area.
+
+OnPCLoginEvent:
+OnPCLogoutEvent:
+OnPCBaseLvUpEvent:
+OnPCJobLvUpEvent:
+
+It's pretty obvious when these four special labels will be invoked.
+
+OnPCDieEvent:
+
+This special label triggers when a player dies. The variable 'killerrid' is
+set to the ID of the killer.
+
+OnPCKillEvent:
+
+This special label triggers when a player kills another player. The variable
+'killedrid' is set to the ID of the player killed.
+
+OnNPCKillEvent:
+
+This special label triggers when a player kills a monster. The variable
+'killedrid' is set to the Class of the monster killed.
+
+OnPCLoadMapEvent:
+
+This special label will trigger once a player steps in a map marked with the
+'loadevent' mapflag and attach its RID. The fact that this label requires a
+mapflag for it to work is because, otherwise, it'd be server-wide and trigger
+every time a player would change maps. Imagine the server load with 1,000 players
+(oh the pain...)
+
+Only the special labels which are not associated with any script command are
+listed here. There are other kinds of labels which may be triggered in a similar
+manner, but they are described with their associated commands.
+
+On<label name>:
+
+These special labels are used with Mob scripts mostly, and script commands
+that requires you to point/link a command to a mob or another NPC, giving a label
+name to start from. The label name can be any of your liking, but must be
+
+Example:
+
+monster "prontera",123,42,"Poringz0rd",2341,23,"Master::OnThisMobDeath";
+
+amatsu,13,152,4 script Master 767,{
+ mes "Hi there";
+ close;
+
+OnThisMobDeath:
+ announce "Hey, "+strcharinfo(0)+" just killed a Poringz0rd!",bc_blue|bc_all;
+ end;
+}
+
+Each time you kill one, that announce will appear in blue to everyone.
+
+"Global" labels
+
+There's a catch with labels and doevent. If you call a label (using doevent)
+and called label is in NPC that has trigger area, that label must end with
+"Global" to work globally (i.e. if RID is outside of the trigger area, which
+usually happens since otherwise there would be no point calling the label with
+doevent, because OnTouch would do the job). For further reference look for
+npc_event in npc.c.
+
+Scripting commands and functions
+--------------------------------
+
+The commands and functions are listed here in no particular order. There's a
+difference between commands and functions - commands leave no 'return value'
+which might be used in a conditional statement, as a command argument, or stored
+in a variable. Calling commands as if they were functions will sometimes work,
+but is not advised, as this can lead to some hard to track errors. Calling
+functions as if they were commands will mess up the stack, so 'return' command
+will not return correctly after this happens in a particular script.
+
+All commands must end with a ';'. Actually, you may expect to have multiple
+commands on one line if you properly terminate them with a ';', but it's better
+if you don't, since it is not certain just whether the scripting engine will
+behave nicely if you do.
+
+-------------------------
+
+
+From here on, we will have the commands sorted as follow:
+
+1.- Basic commands.
+2.- Information-retrieving commands.
+3.- Checking commands.
+4.- Player-related commands.
+5.- Mob / NPC -related commands.
+6.- Other commands.
+7.- Instance commands.
+8.- Quest Log commands.
+9.- Battleground commands.
+10.- Mercenary commands.
+
+=====================
+|1.- Basic commands.|
+=====================
+---------------------------------------
+
+*mes "<string>";
+
+This command will displays a box on the screen for the invoking character, if no
+such box is displayed already, and will print the string specified into that
+box. There is normally no 'close' or 'next' button on this box, unless you
+create one with 'close' or 'next', and while it's open the player can't do much
+else, so it's important to create a button later. If the string is empty, it
+will show up as an empty line.
+
+ mes "Text that will appear in the box";
+
+Inside the string you may put color codes, which will alter the color of the
+text printed after them. The color codes are all '^<R><G><B>' and contain three
+hexadecimal numbers representing colors as if they were HTML colors - ^FF0000 is
+bright red, ^00FF00 is bright green, ^0000FF is bright blue, ^000000 is black.
+^FF00FF is a pure magenta, but it's also a color that is considered transparent
+whenever the client is drawing windows on screen, so printing text in that color
+will have kind of a weird effect. Once you've set a text's color to something,
+you have to set it back to black unless you want all the rest of the text be in
+that color:
+
+ mes "This is ^FF0000 red ^000000 and this is ^00FF00 green, ^000000 so.";
+
+Notice that the text coloring is handled purely by the client. If you use non-
+English characters, the color codes might get screwed if they stick to letters
+with no intervening space. Separating them with spaces from the letters on
+either side solves the problem.
+
+To display multiple lines of message while only using a single mes; command,
+use the script command in the following format:
+
+ mes "Line 1", "Line 2", "Line 3";
+
+This will display 3 different lines while only consuming a single line in
+the relevant script file.
+
+---------------------------------------
+
+*next;
+
+This command will display a 'next' button in the message window for the
+invoking character. Clicking on it will cause the window to clear and display
+a new one. Used to segment NPC-talking, next is often used in combination with
+'mes' and 'close'.
+
+If no window is currently on screen, one will be created, but once the invoking
+character clicks on it, a warning is thrown on the server console and the script
+will terminate.
+
+ mes "[Woman]";
+ mes "This would appear on the page";
+ next;
+ // This is needed cause it is a new page and the top will now be blank
+ mes "[Woman]";
+ mes "This would appear on the 2nd page";
+
+---------------------------------------
+
+*close;
+
+This command will create a 'close' button in the message window for the invoking
+character. If no window is currently on screen, the script execution will end. This is one
+of the ways to end a speech from an NPC. Once the button is clicked, the NPC
+script execution will end, and the message box will disappear.
+
+ mes "[Woman]";
+ mes "I am finished talking to you, click the close button";
+ close;
+ mes "This command will not run at all, cause the script has ended.";
+
+---------------------------------------
+
+*close2;
+
+This command will create a 'close' button in the message window for the invoking
+character. WARNING: If no window is currently on screen, the script execution will halt
+indefinitely! See 'close'. There is one important difference, though - even though
+the message box will have closed, the script execution will not stop, and commands after
+'close2' will still run, meaning an 'end' has to be used to stop the script, unless you
+make it stop in some other manner.
+
+ mes "[Woman]";
+ mes "I will warp you now";
+ close2;
+ warp "place",50,50;
+ end;
+
+Don't expect things to run smoothly if you don't make your scripts 'end'.
+
+---------------------------------------
+
+*end;
+
+This command will stop the execution for this particular script. The two
+versions are perfectly equivalent. It is the normal way to end a script which
+does not use 'mes'.
+
+ if (BaseLevel<=10) goto L_Lvl10;
+ if (BaseLevel<=20) goto L_Lvl20;
+ if (BaseLevel<=30) goto L_Lvl30;
+ if (BaseLevel<=40) goto L_Lvl40;
+ if (BaseLevel<=50) goto L_Lvl50;
+ if (BaseLevel<=60) goto L_Lvl60;
+ if (BaseLevel<=70) goto L_Lvl70;
+ L_Lvl10:
+ npctalk "Look at that you are still a n00b";
+ end;
+ L_Lvl20:
+ npctalk "Look at that you are getting better, but still a n00b";
+ end;
+ L_Lvl30:
+ npctalk "Look at that you are getting there, you are almost 2nd profession now right???";
+ end;
+ L_Lvl40:
+ npctalk "Look at that you are almost 2nd profession";
+ end;
+
+Without the use if 'end' it would travel through the labels until the end of the
+script. If you were lvl 10 or less, you would see all the speech lines, the use
+of 'end' stops this, and ends the script.
+
+---------------------------------------
+
+*set <variable>,<expression>;
+*set(<variable>,<expression>)
+
+This command will set a variable to the value that the expression results in.
+This is the only way to set a variable directly.
+
+This is the most basic script command and is used a lot whenever you try to do
+anything more advanced than just printing text into a message box.
+
+ set @x,100;
+
+will make @x equal 100.
+
+ set @x,1+5/8+9;
+
+will compute 1+5/8+9 (which is, surprisingly, 10 - remember, all numbers are
+integer in this language) and make @x equal it.
+
+Returns the variable reference (since trunk r12870).
+
+---------------------------------------
+
+*setd "<variable name>",<value>;
+
+Works almost identically as set, except the variable name is identified as a string
+and can thus be constructed dynamically.
+
+This command is equivalent to:
+ set getd("variable name"),<value>;
+
+Examples:
+
+ setd ".@var$", "Poporing";
+ mes .@var$; // Displays "Poporing".
+
+ setd ".@" + $var$ + "123$", "Poporing is cool";
+ mes .@Poporing123$; // Displays "Poporing is cool".
+
+---------------------------------------
+
+*getd("<variable name>")
+
+Returns a reference to a variable, the name can be constructed dynamically.
+Refer to 'setd' for usage.
+
+This can also be used to set an array dynamically:
+ setarray getd(".array[0]"), 1, 2, 3, 4, 5;
+
+Examples:
+
+ set getd("$varRefence"), 1;
+ set @i, getd("$" + "pikachu");
+
+---------------------------------------
+
+*getvariableofnpc(<variable>,"<npc name>")
+
+Returns a reference to a NPC variable (. prefix) from the target NPC.
+This can only be used to get . variables.
+
+Examples:
+
+//This will return the value of .var, note that this can't be used, since the value isn't caught.
+ getvariableofnpc(.var,"TargetNPC");
+
+//This will set the .v variable to the value of the TargetNPC's .var variable.
+ set .v,getvariableofnpc(.var,"TargetNPC");
+
+//This will set the .var variable of TargetNPC to 1.
+ set getvariableofnpc(.var,"TargetNPC"),1;
+
+Note: even though function objects can have .variables,
+getvariableofnpc will not work on them.
+
+---------------------------------------
+
+*goto <label>;
+
+This command will make the script jump to a label, usually used in conjunction
+with other command, such as "if", but often used on it's own.
+
+ ...
+ goto Label;
+ mes "This will not be seen";
+Label:
+ mes "This will be seen";
+
+Note by FlavioJS: goto's are "evil" and should be avoided if possible (ò_ó)
+
+---------------------------------------
+
+*menu "<option_text>",<target_label>{,"<option_text>",<target_label>,...};
+
+This command will create a selectable menu for the invoking character. Only one
+menu can be on screen at the same time.
+
+Depending on what the player picks from the menu, the script execution will
+continue from the corresponding label. (it's string-label pairs, not label-
+string)
+
+Options can be grouped together, separated by the character ':'.
+
+ menu "A:B",L_Wrong,"C",L_Right;
+
+It also sets a special temporary character variable @menu, which contains the
+number of option the player picked. (Numbering of options starts at 1.)
+This number is consistent with empty options and grouped options.
+
+ menu "A::B",L_Wrong,"",L_Impossible,"C",L_Right;
+ L_Wrong:
+ // If they click "A" or "B" they will end up here
+ // @menu == 1 if "A"
+ // @menu == 2 will never happen because the option is empty
+ // @menu == 3 if "B"
+ L_Impossible:
+ // Empty options are not displayed and therefore can't be selected
+ // this label will never be reached from the menu command
+ L_Right:
+ // If they click "C" they will end up here
+ // @menu == 5
+
+If a label is '-', the script execution will continue right after the menu
+command if that option is selected, this can be used to save you time, and
+optimize big scripts.
+
+ menu "A::B:",-,"C",L_Right;
+ // If they click "A" or "B" they will end up here
+ // @menu == 1 if "A"
+ // @menu == 3 if "B"
+ L_Right:
+ // If they click "C" they will end up here
+ // @menu == 5
+
+Both these examples will perform the exact same task.
+
+If you give an empty string as a menu item, the item will not display. This
+can effectively be used to script dynamic menus by using empty string for
+entries that should be unavailable at that time.
+
+You can do it by using arrays, but watch carefully - this trick isn't high
+wizardry, but minor magic at least. You can't expect to easily duplicate it
+until you understand how it works.
+
+Create a temporary array of strings to contain your menu items, and populate it
+with the strings that should go into the menu at this execution, making sure not
+to leave any gaps. Normally, you do it with a loop and an extra counter, like
+this:
+
+ setarray @possiblemenuitems$[0],<list of potential menu items>;
+ set @j,0; // That's the menu lines counter.
+
+ // We loop through the list of possible menu items.
+ // @i is our loop counter.
+ for( set @i,0; @i<getarraysize(@possiblemenuitems$) ; set @i,@i+1 )
+ {
+ // That 'condition' is whatever condition that determines whether
+ // a menu item number @i actually goes into the menu or not.
+
+ if (<condition>)
+ {
+ // We record the option into the list of options actually available.
+
+ set @menulist$[@j],@possiblemenuitems$[@i];
+
+ // We just copied the string, we do need it's number for later
+ // though, so we record it as well.
+
+ set @menureference[@j],@i;
+
+ // Since we've just added a menu item into the list, we increment
+ // the menu lines counter.
+
+ set @j,@j+1;
+ }
+
+ // We go on to the next possible menu item.
+ }
+
+This will create you an array @menulist$ which contains the text of all items
+that should actually go into the menu based on your condition, and an array
+@menureference, which contains their numbers in the list of possible menu items.
+(Remember, arrays start with 0.) There's less of them than the possible menu
+items you've defined, but the menu command can handle the empty lines - only if
+they are last in the list, and if it's made this way, they are. Now comes a
+dirty trick:
+
+ // X is whatever the most menu items you expect to handle.
+ menu @menulist$[0],-,@menulist$[1],-,....@menulist$[<X>],-;
+
+This calls up a menu of all your items. Since you didn't copy some of the
+possible menu items into the list, it's end is empty and so no menu items will
+show up past the end. But this menu call doesn't jump anywhere, it just
+continues execution right after the menu command. (And it's a good thing it
+doesn't, cause you can only explicitly define labels to jump to, and how do you
+know which ones to define if you don't know beforehand which options will end up
+where in your menu?)
+But how do you figure out which option the user picked? Enter the @menu.
+
+@menu contains the number of option that the user selected from the list,
+starting with 1 for the first option. You know now which option the user picked
+and which number in your real list of possible menu items it translated to:
+
+ mes "You selected "+@possiblemenuitems$[@menureference[@menu-1]]+"!";
+
+@menu is the number of option the user picked.
+@menu-1 is the array index for the list of actually used menu items that we
+made.
+@menureference[@menu-1] is the number of the item in the array of possible menu
+items that we've saved just for this purpose.
+
+And @possiblemenuitems$[@menureference[@menu-1]] is the string that we used to
+display the menu line the user picked. (Yes, it's a handful, but it works.)
+
+You can set up a bunch of 'if (@menureference[@menu-1]==X) goto Y' statements to
+route your execution based on the line selected and still generate a different
+menu every time, which is handy when you want to, for example, make users select
+items in any specific order before proceeding, or make a randomly shuffled menu.
+
+Kafra code bundled with the standard distribution uses a similar array-based
+menu technique for teleport lists, but it's much simpler and doesn't use @menu,
+probably since that wasn't documented anywhere.
+
+See also 'select', which is probably better in this particular case. Instead of
+menu, you could use 'select' like this:
+
+ set @dummy,select(@menulist$[0],@menulist$[1],....@menulist$[<X>]);
+
+For the purposes of the technique described above these two statements are
+perfectly equivalent.
+
+---------------------------------------
+
+*select("<option>"{,"<option>",...})
+*prompt("<option>"{,"<option>",...})
+
+This function is a handy replacement for 'menu' for some specific cases where
+you don't want a complex label structure - like, for example, asking simple yes-
+no questions. It will return the number of menu option picked, starting with 1.
+Like 'menu', it will also set the variable @menu to contain the option the user
+picked.
+
+ if (select("Yes:No")==1) mes "You said yes, I know.";
+
+And like 'menu', the selected option is consistent with grouped options
+and empty options.
+
+prompt works almost the same as select, except that when a character clicks
+the Cancel button, this function will return 255 instead.
+
+---------------------------------------
+
+*input(<variable>{,<min>{,<max>}})
+
+This command will make an input box pop up on the client connected to the
+invoking character, to allow entering of a number or a string. This has many
+uses, one example would be a guessing game, also making use of the 'rand'
+function:
+
+ mes "[Woman]";
+ mes "Try and guess the number I am thinking of.";
+ mes "The number will be between 1 and 10.";
+ next;
+ set @number, rand(1,10);
+ input @guess;
+ if(@guess==@number)
+ {
+ mes "[Woman]";
+ mes "Well done that was the number I was thinking of";
+ close;
+ }
+ else
+ {
+ mes "[Woman]";
+ mes "Sorry, that wasn't the number I was thinking of.";
+ close;
+ }
+
+If you give the input command a string variable to put the input in, it will
+allow the player to enter text. Otherwise, only numbers will be allowed.
+
+ mes "[Woman]";
+ mes "Please say HELLO";
+ next;
+ input @var$;
+ if(@var$=="HELLO")
+ {
+ mes "[Woman]";
+ mes "Well done you typed it correctly";
+ close;
+ }
+ else
+ {
+ mes "[Woman]";
+ mes "Sorry you got it wrong";
+ close;
+ }
+
+Normally you may not input a negative number with this command.
+This is done to prevent exploits in badly written scripts, which would
+let people, for example, put negative amounts of Zeny into a bank script and
+receive free Zeny as a result.
+
+Since trunk r12192 the command has two optional arguments and a return value.
+The default value of 'min' and 'max' can be set with 'input_min_value' and
+'input_max_value' in script_athena.conf.
+For numeric inputs the value is capped to the range [min,max]. Returns 1 if
+the value was higher than 'max', -1 if lower than 'min' and 0 otherwise.
+For string inputs it returns 1 if the string was longer than 'max', -1 is
+shorter than 'min' and 0 otherwise.
+
+---------------------------------------
+
+*callfunc "<function>"{,<argument>,...<argument>};
+*callfunc("<function>"{,<argument>,...<argument>})
+
+This command lets you call up a function NPC. A function NPC can be called from
+any script on any map server. Using the 'return' command it will come back to
+the place that called it.
+
+ place,50,50,6%TAB%script%TAB%Woman%TAB%115,{
+ mes "[Woman]"
+ mes "Lets see if you win";
+ callfunc "funcNPC";
+ mes "Well done you have won";
+ close;
+ }
+ function%TAB%script%TAB%funcNPC%TAB%{
+ set @win, rand(2);
+ if(@win==0) return;
+ mes "Sorry you lost";
+ end;
+ }
+
+You can pass arguments to your function - values telling it what exactly to do -
+which will be available there with getarg() (see 'getarg')
+Notice that returning is not mandatory, you can end execution right there.
+
+If you want to return a real value from inside your function NPC, it is better
+to write it in the function form, which will also work and will make the script
+generally cleaner:
+
+ place,50,50,6%TAB%script%TAB%Man%TAB%115,{
+ mes "[Man]"
+ mes "Gimme a number!";
+ next;
+ input @number;
+ if (callfunc("OddFunc",@number)) mes "It's Odd!";
+ close;
+ }
+ function%TAB%script%TAB%OddFunc%TAB%{
+ if (getarg(0)%2==0) return 0;// it's even
+ return 1;// it's odd
+ }
+
+Alternately, as of rAthena revision 15979 and 15981, user-defined functions
+may be called directly without the use of the 'callfunc' script command.
+
+ function<tab>script<tab>SayHello<tab>{
+ mes "Hello " + getarg(0);
+ return 0;
+ }
+
+ place,50,50,6<tab>script<tab>Man<tab>115,{
+ mes "[Man]";
+ SayHello strcharinfo(0);
+ close;
+ }
+
+Note:
+
+ !! A user-defined function must be declared /before/ a script attempts to
+ !! call it. That is to say, any functions should be placed above scripts or NPCs
+ !! (or loaded in a separate file first) before attempting to call them directly.
+
+---------------------------------------
+
+*callsub <label>{,<argument>,...<argument>};
+*callsub(<label>{,<argument>,...<argument>})
+
+This command will go to a specified label within the current script (do NOT use
+quotes around it) coming in as if it were a 'callfunc' call, and pass it
+arguments given, if any, which can be recovered there with 'getarg'. When done
+there, you should use the 'return' command to go back to the point from where
+this label was called. This is used when there is a specific thing the script
+will do over and over, this lets you use the same bit of code as many times as
+you like, to save space and time, without creating extra NPC objects which are
+needed with 'callfunc'. A label is not callable in this manner from another
+script.
+
+Example 1: callsub for checking (if checks pass, return to script)
+ callsub S_CheckFull, "guild_vs2",50;
+ switch( rand(4) ) {
+ case 0: warp "guild_vs2",9,50; end;
+ case 1: warp "guild_vs2",49,90; end;
+ case 2: warp "guild_vs2",90,50; end;
+ case 3: warp "guild_vs2",49,9; end;
+ }
+
+...
+
+S_CheckFull:
+ if (getmapusers(getarg(0)) >= getarg(1)) {
+ mes "I'm sorry, this arena is full. Please try again later.";
+ close;
+ }
+ return;
+
+Example 2: callsub used repeatedly, with different arguments
+// notice how the Zeny check/delete is reused, instead of copy-pasting for every warp
+ switch(select("Abyss Lake:Amatsu Dungeon:Anthell:Ayothaya Dungeon:Beacon Island, Pharos") {
+ case 1: callsub S_DunWarp,"hu_fild05",192,207;
+ case 2: callsub S_DunWarp,"ama_in02",119,181;
+ case 3: callsub S_DunWarp,"moc_fild20",164,145;
+ case 4: callsub S_DunWarp,"ayo_fild02",279,150;
+ case 5: callsub S_DunWarp,"cmd_fild07",132,125;
+ // etc
+ }
+
+...
+
+S_DunWarp:
+// getarg(0) = "mapname"
+// getarg(1) = x
+// getarg(2) = y
+ if (Zeny >= 100) {
+ set Zeny, Zeny-100;
+ warp getarg(0),getarg(1),getarg(2);
+ } else {
+ mes "Dungeon warp costs 100 Zeny.";
+ }
+ close;
+
+---------------------------------------
+
+*getarg(<index>{,<default_value>})
+
+This function is used when you use the 'callsub' or 'callfunc' commands. In the
+call you can specify variables that will make that call different from another
+one. This function will return an argument the function or subroutine was
+called with, and is the normal way to get them.
+This is another thing that can let you use the same code more than once.
+
+Argument numbering starts with 0, i.e. the first argument you gave is number 0.
+If no such argument was given, a zero is returned.
+
+ place,50,50,6%TAB%script%TAB%Woman1%TAB%115,{
+ mes "[Woman]";
+ mes "Lets see if you win";
+ callfunc "funcNPC",2;
+ mes "Well done you have won";
+
+ ...
+
+ place,52,50,6%TAB%script%TAB%Woman2%TAB%115,{
+ mes "[Woman]";
+ mes "Lets see if you win";
+ callfunc "funcNPC",5;
+ mes "Well done you have won";
+
+ ...
+
+ function%TAB%script%TAB%funcNPC%TAB%{
+ set @win, rand(getarg(0));
+ if(@win==0) return;
+ mes "Sorry you lost";
+
+"woman1" NPC object calls the funcNPC. The argument it gives in this call is
+stated as 2, so when the random number is generated by the 'rand' function, it
+can only be 0 or 1. Whereas "woman2" gives 5 as the argument number 0 when
+calling the function, so the random number could be 0, 1, 2, 3 or 4, this makes
+"woman2" less likely to say the player won.
+
+You can pass multiple arguments in a function call:
+
+ callfunc "funcNPC",5,4,3;
+
+getarg(0) would be 5, getarg(1) would be 4 and getarg(2) would be 3.
+
+Getarg has an optional argument since trunk r10773 and stable r10958.
+If the target argument exists, it is returned.
+Otherwise, if <default_value> is present it is returned instead,
+if not the script terminates immediately.
+
+in the previous example getarg(2,-1) would be 3 and getarg(3,-1) would be -1
+
+---------------------------------------
+
+*getargcount()
+
+This function is used when you use the 'callsub' or 'callfunc' commands. In the
+call you can specify arguments. This function will return the number of arguments
+provided.
+
+Example:
+ callfunc "funcNPC",5,4,3;
+ ...
+ function%TAB%script%TAB%funcNPC%TAB%{
+ set .@count, getargcount(); // 3
+ ...
+ }
+
+---------------------------------------
+
+*return {<value>};
+
+This command causes the script execution to leave previously called function
+with callfunc or script with callsub and return to the location, where the call
+originated from. Optionally a return value can be supplied, when the call was
+done using the function form.
+
+Using this command outside of functions or scripts referenced by callsub will
+result in error and termination of the script.
+
+ callfunc "<your function>";// when nothing is returned
+ set <variable>,callfunc("<your function>");// when a value is being returned
+
+---------------------------------------
+
+*function <function name>;
+*<function name>{(<argument>,...<argument>)};
+*function <function name> {
+<code>
+}
+
+This works like callfunc, and is used for cleaner and faster scripting. The function
+must be defined and used within a script, and works like a label with arguments.
+Note that the name may only contain alphanumeric characters and underscore.
+
+Usage:
+
+ 1. Declare the function.
+ function <function name>;
+ 2. Call the function anywhere within the script.
+ It can also return a value when used with parentheses.
+ <function name>;
+ 3. Define the function within the script.
+ <function name> {<code>}
+
+Example:
+
+prontera,154,189,4 script Item Seller 767,{
+ /* Function declaration */
+ function SF_Selling;
+
+ if (Zeny > 50) {
+ mes "Welcome!";
+ /* Function call */
+ SF_Selling;
+ }
+ else mes "You need 50z, sorry!";
+ close;
+
+ /* Function definition */
+ function SF_Selling {
+ mes "Would you like to buy a phracon for 50z?";
+ next;
+ if(select("Yes","No, thanks") == 1) {
+ set Zeny, Zeny-50;
+ getitem 1010,1;
+ mes "Thank you!";
+ }
+ return;
+ }
+}
+
+Example with parameters and return value:
+
+prontera,150,150,0 script TestNPC 123,{
+ /* Function declaration */
+ function MyAdd;
+
+ mes "Enter two numbers.";
+ next;
+ input .@a;
+ input .@b;
+ /* Function call */
+ mes .@a+" + "+.@b+" = "+MyAdd(.@a,.@b);
+ close;
+
+ /* Function definition */
+ function MyAdd {
+ return getarg(0)+getarg(1);
+ }
+}
+
+
+---------------------------------------
+
+*is_function("<function name>")
+
+This command checks whether a function exists.
+It returns 1 if function is found, or 0 if it isn't.
+
+Example:
+
+ function script try {
+ dothat;
+ }
+
+ - script test -1,{
+ set .@try, is_function("try"); // 1
+ set .@not, is_function("not"); // 0
+ }
+
+---------------------------------------
+
+*if (<condition>) <statement>;
+
+This is the basic conditional statement command, and just about the only one
+available in this scripting language.
+
+The condition can be any expression. All expressions resulting in a non-zero
+value will be considered True, including negative values. All expressions
+resulting in a zero are false.
+
+If the expression results in True, the statement will be executed. If it isn't
+true, nothing happens and we move on to the next line of the script.
+
+ if (1) mes "This will always print.";
+ if (0) mes "And this will never print.";
+ if (5) mes "This will also always print.";
+ if (-1) mes "Funny as it is, this will also print just fine.";
+
+For more information on conditional operators see the operators section above.
+Anything that is returned by a function can be used in a condition check without
+bothering to store it in a specific variable:
+
+ if (strcharinfo(0)=="Daniel Jackson") mes "It is true, you are Daniel!";
+
+More examples of using the 'if' command in the real world:
+
+Example 1:
+
+ set @var1,1;
+ input @var2;
+ if(@var1==@var2) goto L_Same;
+ mes "Sorry that is wrong";
+ close;
+ L_Same:
+ close;
+
+Example 2:
+
+ set @var1,1;
+ input @var2;
+ if(@var1!=@var2) mes "Sorry that is wrong";
+ close;
+
+(Notice examples 1 and 2 have the same effect.)
+
+Example 3:
+
+ set @var1,@var1+1;
+ mes "[Forgetfull Man]";
+ if (@var==1) mes "This is the first time you have talked to me";
+ if (@var==2) mes "This is the second time you have talked to me";
+ if (@var==3) mes "This is the third time you have talked to me";
+ if (@var==4) mes "This is the forth time you have talked to me, but I think I am getting amnesia, I have forgotten about you";
+ if (@var==4) set @var,0;
+ close;
+
+Example 4:
+
+ mes "[Quest Person]";
+ if(countitem(512)>=1) goto L_GiveApple;
+ // The number 512 was found from item_db, it is the item number for the Apple.
+ mes "Can you please bring me an apple?";
+ close;
+ L_GiveApple:
+ mes "Oh an apple, I didn't want it, I just wanted to see one";
+ close;
+
+Example 5:
+
+ mes "[Person Checker]";
+ if($name$!=null) goto L_Check;
+ mes "Please tell me someones name";
+ next;
+ input $name$;
+ set $name2$,strcharinfo(0);
+ mes "[Person Checker]";
+ mes "Thank you";
+ L_Check:
+ if($name$==strcharinfo(0) ) goto L_SameName;
+ mes "[Person Checker]";
+ mes "You are not the person that " +$name2$+ " mentioned";
+ L_End:
+ set $name$,null;
+ set $name2$,null;
+ close;
+ L_SameName:
+ mes "[Person Checker]";
+ mes "You are the person that " +$name2$+ " just mentioned";
+ mes "nice to meet you";
+ goto L_End;
+
+See 'strcharinfo' for explanation of what this function does.
+
+Example 6: Using complex conditions.
+
+ mes "[Multi Checker]";
+ if( (@queststarted==1) && (countitem(512)>=5) ) goto L_MultiCheck;
+ // Only if the quest has been started AND You have 5 apples will it goto "L_MultiCheck"
+ mes "Please get me 5 apples";
+ set @queststarted,1;
+ close;
+ L_MultiCheck:
+ mes "[Multi Checker]";
+ mes "Well done you have started the quest of got me 5 apples";
+ mes "Thank you";
+ set @queststarted,0;
+ delitem 512,5;
+ close;
+
+With the Advanced scripting engine, we got nested if's. That is:
+
+if (<condition>)
+ dothis;
+else
+ dothat;
+
+If the condition doesn't meet, it'll do the action following the else.
+We can also group several actions depending on a condition, the following way:
+
+if (<condition)
+{
+ dothis1;
+ dothis2;
+ dothis3;
+} else {
+ dothat1;
+ dothat2;
+ dothat3;
+ dothat4;
+}
+
+Remember that if you plan to do several actions upon the condition being false, and
+you forget to use the curly braces (the { } ), the second action will be executed regardless
+the output of the condition, unless of course, you stop the execution of the script if the
+condition is true (that is, in the first grouping using a return; , and end; or a close; )
+
+Also, you can have multiple conditions nested or chained, and don't worry about limits as to
+how many nested if you can have, there is no spoon ;)
+
+...
+if (<condition 1>)
+ dothis;
+else if (<condition 2>)
+{
+ dotheother;
+ do that;
+ end;
+} else
+ do this;
+...
+
+---------------------------------------
+
+*jump_zero (<condition>),<label>;
+
+This command works kinda like an 'if'+'goto' combination in one go. (See 'if').
+If the condition is false (equal to zero) this command will immediately jump to
+the specified label like in 'goto'. While 'if' is more generally useful, for
+some cases this could be an optimization.
+
+The main reason for this command is that other control statements, like
+'switch', 'for' or 'while', are disassembled into simple expressions together
+with this command when a script is parsed.
+
+---------------------------------------
+
+*while (<condition>) <statement>;
+
+This is probably the simplest and most frequently used loop structure. The 'while'
+statement can be interpreted as "while <condition> is true, perform <statement>".
+It is a pretest loop, meaning the conditional expression is tested before any of the
+statements in the body of the loop are performed. If the condition evaluates to
+false, the statement(s) in the body of the loop is/are never executed. If the
+condition evaluates to true, the statement(s) are executed, then control transfers
+back to the conditional expression, which is reevaluated and the cycle continues.
+
+Multiple statements can be grouped with { }, curly braces, just like with the 'if' statement.
+
+Example 1:
+ while (switch(select("Yes:No") == 2 ))
+ mes "You picked no.";
+
+Example 2: multiple statements
+ while (switch(select("Yes:No") == 2 )) {
+ mes "Why did you pick no?";
+ mes "You should pick yes instead!";
+ }
+
+Example 3: counter-controlled loop
+ set .@i, 1;
+ while (.@i <= 5) {
+ mes "This line will print 5 times.";
+ set .@i, .@i +1;
+ }
+
+Example 4: sentinel-controlled loop
+ mes "Input 0 to stop";
+ input .@num;
+ while (.@num != 0) {
+ mes "You entered " + .@num;
+ input .@num;
+ }
+ close;
+
+---------------------------------------
+
+*for (<variable initialization>; <condition>; <variable update>) <statement>;
+
+Another pretest looping structure is the 'for' statement. It is considered a
+specialized form of the 'while' statement, and is usually associated with counter-
+controlled loops. Here are the steps of the 'for' statement: the initialize
+statement is executed first and only once. The condition test is performed.
+When the condition evaluates to false, the rest of the for statement is skipped.
+When the condition evaluates to true, the body of the loop is executed, then the
+update statement is executed (this usually involves incrementing a variable).
+Then the condition is reevaluated and the cycle continues.
+
+Example 1:
+ for( set .@i, 1; .@i <= 5; set .@i, .@i +1 )
+ mes "This line will print 5 times.";
+
+Example 2:
+ mes "This will print the numbers 1 - 5.";
+ for( set .@i, 1; .@i <= 5; set .@i, .@i +1 )
+ mes .@i;
+
+---------------------------------------
+
+*do { <statement>; } while (<condition>);
+
+The 'do...while' is the only post-test loop structure available in this script
+language. With a post-test, the statements are executed once before the condition
+is tested. When the condition is true, the statement(s) are repeated. When the
+condition is false, control is transferred to the statement following the
+'do...while' loop expression.
+
+Example 1: sentinel-controlled loop
+ mes "This menu will keep appearing until you pick Cancel";
+ do {
+ set .@menu, select("One:Two:Three:Cancel");
+ } while (.@menu != 4);
+
+Example 2: counter-controlled loop
+ mes "This will countdown from 10 to 1.";
+ set .@i, 10;
+ do {
+ mes .@i;
+ set .@i, .@i - 1;
+ } while (.@i > 0);
+
+---------------------------------------
+
+*freeloop(<toggle>)
+
+Toggling this to enabled (1) allows the script instance to bypass the infinite loop
+protection, allowing your script to loop as much as it may need. Disabling (0) will
+warn you if an infinite loop is detected.
+
+Example:
+ freeloop(1); // enable script to loop freely
+
+ //Be aware with what you do here.
+ for ( set .@i,0; .@i<.@bigloop; set .@i, .@i+1 ) {
+ dothis;
+ // will sleep the script for 1ms when detect an infinity loop to
+ // let rAthena do what it need to do (socket, timer, process, etc.)
+ }
+
+ freeloop(0); // disable
+
+ for ( set .@i,0; .@i<.@bigloop; set .@i, .@i+1 ) {
+ dothis;
+ // throw an infinity loop error
+ }
+
+---------------------------------------
+
+*setarray <array name>[<first value>],<value>{,<value>...<value>};
+
+This command will allow you to quickly fill up an array in one go. Check the
+Kafra scripts in the distribution to see this used a lot.
+
+ setarray @array[0], 100, 200, 300, 400, 500, 600;
+
+First value is the index of the first element of the array to alter. For
+example:
+
+ setarray @array[0],200,200,200;
+ setarray @array[1],300,150;
+
+will produce:
+
+ @array[0]=200
+ @array[1]=300
+ @array[2]=150
+
+---------------------------------------
+
+*cleararray <array name>[<first value to alter>],<value>,<number of values to set>;
+
+This command will change many array values at the same time to the same value.
+
+ setarray @array[0], 100, 200, 300, 400, 500, 600;
+ // This will make all 6 values 0
+ cleararray @array[0],0,6;
+ // This will make array element 0 change to 245
+ cleararray @array[0],245,1;
+ // This will make elements 1 and 2 change to 345
+ cleararray @array[1],345,2;
+
+See 'setarray'.
+
+---------------------------------------
+
+*copyarray <destination array>[<first value>],<source array>[<first value>],<amount of data to copy>;
+
+This command lets you quickly shuffle a lot of data between arrays, which is in
+some cases invaluable.
+
+ setarray @array[0], 100, 200, 300, 400, 500, 600;
+ // So we have made @array[]
+ copyarray @array2[0],@array[2],2;
+
+ // Now, @array2[0] will be equal to @array[2] (300) and
+ // @array2[1] will be equal to @array[3].
+
+So using the examples above:
+ @array[0] = 100
+ @array[1] = 200
+ @array[2] = 300
+ @array[3] = 400
+ @array[4] = 500
+ @array[5] = 600
+
+New Array:
+ @array2[0] = 300
+ @array2[1] = 400
+ @array2[2] = 0
+ @array2[3] = 0
+
+Notice that @array[4] and @array[5] won't be copied to the second array, and it will return a
+0.
+
+---------------------------------------
+
+*deletearray <array name>[<first value>],<how much to delete>;
+
+This command will delete a specified number of array elements totally from an
+array, shifting all the elements beyond this towards the beginning.
+
+ // This will delete array element 0, and move all the other array elements
+ // up one place.
+ deletearray @array[0],1
+
+// This would delete array elements numbered 1, 2 and 3, leave element 0 in its
+// place, and move the other elements ups, so there are no gaps.
+
+ deletearray @array[1],3
+
+---------------------------------------
+
+======================================
+|2.- Information-retrieving commands.|
+======================================
+---------------------------------------
+
+*strcharinfo(<type>)
+
+This function will return either the name, party name or guild name for the
+invoking character. Whatever it returns is determined by type.
+
+ 0 - Character's name.
+ 1 - The name of the party they're in if any.
+ 2 - The name of the guild they're in if any.
+ 3 - The name of the map the character is in.
+
+If a character is not a member of any party or guild, an empty string will be
+returned when requesting that information.
+
+---------------------------------------
+
+*strnpcinfo(<type>)
+
+This function will return the various parts of the name of the calling NPC.
+Whatever it returns is determined by type.
+
+ 0 - The NPC's display name (visible#hidden)
+ 1 - The visible part of the NPC's display name
+ 2 - The hidden part of the NPC's display name
+ 3 - The NPC's unique name (::name)
+ 4 - The name of the map the NPC is in.
+
+---------------------------------------
+
+*getarraysize(<array name>)
+
+This function returns the number of values that are contained inside the
+specified array. Notice that zeros and empty strings at the end of this array
+are not counted towards this number.
+
+For example:
+
+ setarray @array[0], 100, 200, 300, 400, 500, 600;
+ set @arraysize,getarraysize(@array);
+
+This will make @arraysize == 6. But if you try this:
+
+ setarray @array[0], 100, 200, 300, 400, 500, 600, 0;
+ set @arraysize,getarraysize(@array);
+
+@arraysize will still equal 6, even though you've set 7 values.
+
+---------------------------------------
+
+*getelementofarray(<array name>,<index>)
+
+This command retrieves the value of the element of given array at given index.
+This is equivalent to using:
+
+ <array name>[<index>]
+
+The reason for this is, that this short form is internally converted into a call
+to getelementofarray, when the script is loaded.
+
+Also useful when passing arrays to functions or accessing another npc's arrays:
+ getelementofarray(getarg(0),<index>)
+ getelementofarray(getvariableofnpc(.var, "testNPC"),<index>)
+
+---------------------------------------
+
+*readparam(<parameter number>)
+
+This function will return the basic stats of an invoking character, referred to
+by the parameter number. Instead of a number, you can use a parameter name if it
+is defined in 'db/const.txt'.
+
+For reference, these things are defined:
+
+StatusPoint, BaseLevel, SkillPoint, Class, Upper, Zeny, Sex, Weight, MaxWeight,
+JobLevel, BaseExp, JobExp, NextBaseExp, NextJobExp, Hp, MaxHp, Sp, MaxSp,
+BaseJob, Karma, Manner, bVit, bDex, bAgi, bStr, bInt, bLuk
+
+All of these also behave as variables, but don't expect to be able to just 'set'
+them - some will not work for various internal reasons.
+
+Example 1:
+
+ // Returns how many status points you haven't spent yet.
+ mes "Unused status points: "+readparam(9);
+
+Using this particular information as a function call is not required. Typing this
+will return the same result:
+
+ mes "Unused status points: "+StatusPoint;
+
+Example 2:
+
+You can also use this command to get stat values.
+
+ if (readparam(bVit) > 77)
+ mes "Only people with over 77 Vit are reading this!";
+
+---------------------------------------
+
+*getcharid(<type>{,"<character name>"})
+
+This function will return a unique ID number of the invoking character, or, if a
+character name is specified, of that player.
+
+Type is the kind of associated ID number required:
+
+ 0 - Character ID number.
+ 1 - Party ID number.
+ 2 - Guild ID number.
+ 3 - Account ID number.
+ 4 - Battle ground ID
+
+For most purposes other than printing it, a number is better to have than a name
+(people do horrifying things to their character names).
+
+If the character is not in a party or not in a guild, the function will return 0
+if guild or party number is requested. If a name is specified and the character
+is not found, 0 is returned.
+
+If getcharid(0) returns a zero, the script got called not by a character and
+doesn't have an attached RID. Note that this will cause the map server to
+print "player not attached!" error messages, so it is preferred to use
+"playerattached" to check for the character attached to the script.
+
+if( getcharid(2) == 0 ) mes "Only members of a guild are allowed here!";
+
+---------------------------------------
+
+*getnpcid(<type>{,"<npc name>"});
+
+Retrieves IDs of the currently invoked NPC. If a unique npc name is
+given, IDs of that NPC are retrieved instead. Type specifies what ID
+to retrieve and can be one of the following:
+
+ 0 - Unit ID (GID)
+
+If an invalid type is given or the NPC does not exist, 0 is returned.
+
+---------------------------------------
+
+*getchildid()
+*getmotherid()
+*getfatherid()
+
+These functions return the character ID of the attached player's child,
+mother, mother, or father, respectively. It returns 0 if no ID is found.
+
+ if (getmotherid()) mes "Your mother's ID is: "+getmotherid();
+
+---------------------------------------
+
+*ispartneron()
+
+This function returns 1 if the invoking character's marriage partner is
+currently online and 0 if they are not or if the character has no partner.
+
+---------------------------------------
+
+*getpartnerid()
+
+This function returns the character ID of the invoking character's marriage
+partner, if any. If the invoking character is not married, it will return 0,
+which is a quick way to see if they are married:
+
+ if (getpartnerid()) mes "I'm not going to be your girlfriend!";
+ if (getpartnerid()) mes "You're married already!";
+
+---------------------------------------
+
+*getpartyname(<party id>)
+
+This function will return the name of a party that has the specified ID number.
+If there is no such party ID, "null" will be returned.
+
+Lets say the ID of a party was saved as a global variable:
+
+ // This would return the name of the party from the ID stored in a variable
+ mes "You're in the '"+getpartyname($@var)+"' party, I know!";
+
+---------------------------------------
+
+*getpartymember <party id>{,<type>};
+
+This command will find all members of a specified party and returns their names
+(or character id or account id depending on the value of "type") into an array
+of temporary global variables. There's actually quite a few commands like this
+which will fill a special variable with data upon execution and not do anything
+else.
+
+Upon executing this,
+
+$@partymembername$[] is a global temporary string array which contains all the
+ names of these party members
+ (only set when type is 0 or not specified)
+
+$@partymembercid[] is a global temporary number array which contains the
+ character id of these party members.
+ (only set when type is 1)
+
+$@partymemberaid[] is a global temporary number array which contains the
+ account id of these party members.
+ (only set when type is 2)
+
+$@partymembercount is the number of party members that were found.
+
+The party members will (apparently) be found regardless of whether they are
+online or offline. Note that the names come in no particular order.
+
+Be sure to use $@partymembercount to go through this array, and not
+'getarraysize', because it is not cleared between runs of 'getpartymember'. If
+someone with 7 party members invokes this script, the array would have 7
+elements. But if another person calls up the NPC, and he has a party of 5, the
+server will not clear the array for you, overwriting the values instead. So in
+addition to returning the 5 member names, the 6th and 7th elements from the last
+call remain, and you will get 5+2 members, of which the last 2 don't belong to
+the new guy's party. $@partymembercount will always contain the correct number,
+(5) unlike 'getarraysize()' which will return 7 in this case.
+
+Example 1: list party member names
+
+ // get the party member names
+ getpartymember getcharid(1),0;
+
+ // It's a good idea to copy the global temporary $@partymember*****
+ // variables to your own scope variables because if you have pauses in this
+ // script (sleep, sleep2, next, close2, input, menu, select, or prompt),
+ // another player could click this NPC, trigger 'getpartymember', and
+ // overwrite the $@partymember***** variables.
+ set .@count, $@partymembercount;
+ copyarray .@name$[0], $@partymembername$[0], $@partymembercount;
+
+ // list the party member names
+ for (set .@i,0; .@i < .@count; set .@i, .@i+1) {
+ mes (.@i +1) + ". ^0000FF" + .@name$[.@i] + "^000000";
+ }
+ close;
+
+
+Example 2: check party count (with a 'next' pause), before warping to event
+
+ set .register_num, 5; // How many party members are required?
+
+ // get the charID and accountID of character's party members
+ getpartymember getcharid(1), 1;
+ getpartymember getcharid(1), 2;
+
+ if ( $@partymembercount != .register_num ) {
+ mes "Please form a party of "+ .register_num +" to continue";
+ close;
+ }
+
+ // loop through both and use 'isloggedin' to count online party members
+ for ( set .@i, 0; .@i < $@partymembercount; set .@i, .@i +1 )
+ if ( isloggedin( $@partymemberaid[.@i], $@partymembercid[.@i] ) )
+ set .@count_online, .@count_online +1 ;
+ // We search accountID & charID because a single party can have multiple
+ // characters from the same account. Without searching through the charID,
+ // if a player has 2 characters from the same account inside the party but
+ // only 1 char online, it would count their online char twice.
+
+ if ( .@count_online != .register_num ) {
+ mes "All your party members must be online to continue";
+ close;
+ }
+
+ // copy the array to prevent players cheating the system
+ copyarray .@partymembercid, $@partymembercid, .register_num;
+
+ mes "Are you ready ?";
+ next; // careful here
+ select "Yes";
+
+ // When a script hits a next, menu, sleep or input that pauses the script,
+ // players can invite or /leave and make changes in their party. To prevent
+ // this, we call getpartymember again and compare with the original values.
+
+ getpartymember getcharid(1), 1;
+ if ( $@partymembercount != .register_num ) {
+ mes "You've made changes to your party !";
+ close;
+ }
+ for ( set .@i, 0; .@i < $@partymembercount; set .@i, .@i +1 ) {
+ if ( .@partymembercid[.@i] != $@partymembercid[.@i] ) {
+ mes "You've made changes to your party !";
+ close;
+ }
+ }
+
+ // Finally, it's safe to start the event!
+ warpparty "event_map", 0,0, getcharid(1);
+
+---------------------------------------
+
+*getpartyleader(<party id>{,<type>})
+
+This function returns some information about the given party-id's leader.
+When type is omitted, the default information retrieved is the leader's name.
+Possible types are:
+
+ 1: Leader account id
+ 2: Leader character id
+ 3: Leader's class
+ 4: Leader's current map name
+ 5: Leader's current level as stored on the party structure (may not be
+ current level if leader leveled up recently).
+
+If retrieval fails (leader not found or party does not exist), this function
+returns "null" instead of the character name, and -1 for the other types.
+
+---------------------------------------
+
+*getlook(<type>)
+
+This function will return the number for the current character look value
+specified by type. See 'setlook' for valid look types.
+
+This can be used to make a certain script behave differently for characters
+dressed in black. :)
+
+---------------------------------------
+
+*getsavepoint(<information type>)
+
+This function will return information about the invoking character's save point.
+You can use it to let a character swap between several recorded save points.
+Available information types are:
+
+ 0 - Map name (a string)
+ 1 - X coordinate
+ 2 - Y coordinate
+
+---------------------------------------
+
+*getcharip({"<character name>"|<account id>|<char id>})
+
+This function will return the IP address of the invoking character, or, if a player
+is specified, of that character. A blank string is returned if no player is attached.
+
+Examples:
+
+// Outputs IP address of attached player.
+ mes "Your IP: " + getcharip();
+
+// Outputs IP address of character "Silver".
+ mes "Silver's IP: " + getcharip("Silver");
+
+---------------------------------------
+\\
+2,2 Item-related commands
+\\
+---------------------------------------
+
+*getequipid(<equipment slot>)
+
+This function returns the item ID of the item equipped in the equipment slot
+specified on the invoking character. If nothing is equipped there, it returns -1.
+Valid equipment slots are:
+
+EQI_HEAD_TOP (1) - Upper head gear
+EQI_ARMOR (2) - Armor (Where you keep your Jackets and Robes)
+EQI_HAND_L (3) - What is in your Left hand.
+EQI_HAND_R (4) - What is in your Right hand.
+EQI_GARMENT (5) - The garment slot (Mufflers, Hoods, Manteaus)
+EQI_SHOES (6) - What foot gear the player has on.
+EQI_ACC_L (7) - Accessory 1.
+EQI_ACC_R (8) - Accessory 2.
+EQI_HEAD_MID (9) - Middle Headgear (masks and glasses)
+EQI_HEAD_LOW (10) - Lower Headgear (beards, some masks)
+
+Notice that a few items occupy several equipment slots, and if the character is
+wearing such an item, 'getequipid' will return it's ID number for either slot.
+
+Can be used to check if you have something equipped, or if you haven't got
+something equipped:
+
+ if(getequipid(EQI_HEAD_TOP)==2234) goto L_WearingTiara;
+ mes "Come back when you have a Tiara on";
+ close;
+ L_WearingTiara:
+ mes "What a lovely Tiara you have on";
+ close;
+
+You can also use it to make sure people don't pass a point before removing an
+item totally from them. Let's say you don't want people to wear Legion Plate
+armor, but also don't want them to equip if after the check, you would do this:
+
+ if ((getequipid(EQI_ARMOR) == 2341) || (getequipid(EQI_ARMOR) == 2342) goto L_EquipedLegionPlate;
+ // the || is used as an or argument, there is 2341 and 2342 cause there are
+ // two different legion plate armors, one with a slot one without.
+ if ((countitem(2341) > 0) || (countitem(2432) > 0) goto L_InventoryLegionPlate;
+ mes "I will lets you pass";
+ close2;
+ warp "place",50,50;
+ end;
+ L_EquipedLegionPlate:
+ mes "You are wearing some Legion Plate Armor, please drop that in your stash before continuing";
+ close;
+ L_InventoryLegionPlate:
+ mes "You have some Legion Plate Armor in your inventory, please drop that in your stash before continuing";
+ close;
+
+---------------------------------------
+
+*getequipname(<equpment slot>)
+
+Returns the jname of the item equipped in the specified equipment slot on the
+invoking character, or an empty string if nothing is equipped in that position.
+Does the same thing as getitemname(getequipid()). Useful for an NPC to state
+what your are wearing, or maybe saving as a string variable.
+See 'getequipid' for a full list of valid equipment slots.
+
+ if( getequipname(EQI_HEAD_TOP) != "" )
+ mes "So you are wearing a "+getequipname(EQI_HEAD_TOP)+" on your head";
+ else
+ mes "You are not wearing any head gear";
+
+---------------------------------------
+
+*getitemname(<item id>)
+
+Given the database ID number of an item, this function will return the text
+stored in the 'japanese name' field (which, in rAthena, stores an English name
+the players would normally see on screen.)
+
+---------------------------------------
+
+*getbrokenid(<number>)
+
+This function will search the invoking character's inventory for any broken
+items, and will return their item ID numbers. Since the character may have
+several broken items, 1 given as an argument will return the first one found, 2
+will return the second one, etc. Will return 0 if no such item is found.
+
+ // Let's see if they have anything broken:
+ if (getbrokenid(1)==0) goto Skip;
+ // They do, so let's print the name of the first broken item:
+ mes "Oh, I see you have a broken "+getitemname(getbrokenid(1))+" here!";
+ Skip:
+ mes "You don't have anything broken, quit bothering me.";
+
+---------------------------------------
+
+*getequipisequiped(<equipment slot>)
+
+This functions will return 1 if there is an equipment placed on the specified
+equipment slot and 0 otherwise. For a list of equipment slots
+see 'getequipid'. Function originally used by the refining NPCs:
+
+ if (getequipisequiped(EQI_HEAD_TOP)) goto L_equipped;
+ mes "[Refiner]";
+ mes "Do you want me to refine your dumb head?";
+ close;
+ L_equipped:
+ mes "[Refiner]";
+ mes "That's a fine hat you are wearing there...";
+ close;
+
+---------------------------------------
+
+*getequipisenableref(<equipment slot>)
+
+Will return 1 if the item equipped on the invoking character in the specified
+equipment slot is refinable, and 0 if it isn't. For a list of equipment slots
+see 'getequipid'.
+
+ if (getequipisenableref(EQI_HEAD_TOP)) goto L_Refine;
+ mes "[Refiner]";
+ mes "I can't refine this hat!...";
+ close;
+ L_Refine:
+ mes "[Refiner]";
+ mes "Ok I can refine this";
+ close;
+
+---------------------------------------
+
+*getequiprefinerycnt(<equipment slot>)
+
+Returns the current number of pluses for the item in the specified equipment
+slot. For a list of equipment slots see 'getequipid'.
+
+Can be used to check if you have reached a maximum refine value, default for
+this is +10:
+
+ if(getequiprefinerycnt(EQI_HEAD_TOP) < 10) goto L_Refine_HeadGear;
+ mes "Sorry, it's not possible to refine hats better than +10";
+ close;
+ L_Refine_HeadGear:
+ mes "I will now upgrade your "+getequipname(EQI_HEAD_TOP);
+
+---------------------------------------
+
+*getequipweaponlv(<equipment slot>)
+
+This function returns the weapon level for the weapon equipped in the specified
+equipment slot on the invoking character. For a list of equipment slots see
+'getequipid'.
+
+Only EQI_HAND_L and EQI_HAND_R normally make sense, since only weapons have
+a weapon level. You can, however, probably, use this field for other equippable
+custom items as a flag or something.
+
+If no item is equipped in this slot, or if it doesn't have a weapon level
+according to the database, 0 will be returned.
+
+Examples:
+
+// Right hand can only contain a weapon.
+ switch (getequipweaponlv(EQI_HAND_R)) {
+ case 1: mes "You are holding a lvl 1 weapon."; break;
+ case 2: mes "You are holding a lvl 2 weapon."; break;
+ case 3: mes "You are holding a lvl 3 weapon."; break;
+ case 4: mes "You are holding a lvl 4 weapon."; break;
+ case 5: mes "You are holding a lvl 5 weapon, hm, must be a custom design..."; break;
+ default: mes "Seems you don't have a weapon on."; break;
+ }
+
+// Left hand can hold either a weapon or shield.
+ if (getequipid(EQI_HAND_R) == 0) {
+ mes "Seems you have nothing equipped here.";
+ close;
+ }
+ switch (getequipweaponlv(EQI_HAND_L)) {
+ case 0: mes "You are holding a shield, so it doesn't have a level."; break;
+ case 1: mes "You are holding a lvl 1 weapon."; break;
+ case 2: mes "You are holding a lvl 2 weapon."; break;
+ case 3: mes "You are holding a lvl 3 weapon."; break;
+ case 4: mes "You are holding a lvl 4 weapon."; break;
+ case 5: mes "You are holding a lvl 5 weapon, hm, must be a custom design..."; break;
+ }
+
+---------------------------------------
+
+*getequippercentrefinery(<equipment slot>)
+
+This function calculates and returns the percent value chance to successfully
+refine the item found in the specified equipment slot of the invoking character
+by +1. There is no actual formula, the success rate for a given weapon level of
+a certain refine level is found in the db/refine_db.txt file. For a list of
+equipment slots see 'getequipid'.
+
+These values can be displayed for the player to see, or used to calculate the
+random change of a refine succeeding or failing and then going through with it
+(which is what the official NPC refinery scripts use it for)
+
+// This will find a random number from 0 - 99 and if that is equal to or more
+// than the value recovered by this command it will go to L_Fail
+ if (getequippercentrefinery(EQI_HAND_L)<=rand(100)) goto L_Fail;
+
+---------------------------------------
+
+*getareadropitem("<map name>",<x1>,<y1>,<x2>,<y2>,<item>)
+
+This function will count all the items with the specified ID number lying on the
+ground on the specified map within the x1/y1-x2/y2 square on it and return that
+number.
+
+This is the only function around where a parameter may be either a string or a
+number! If it's a number, it means that only the items with that item ID number
+will be counted. If it is a string, it is assumed to mean the 'english name'
+field from the item database. If you give it an empty string, or something that
+isn't found from the item database, it will count items number '512' (apples).
+
+---------------------------------------
+
+*getequipcardcnt(<equipment slot>)
+
+This function will return the number of cards that have been compounded onto a
+specific equipped item for the invoking character. See 'getequipid' for a list
+of possible equipment slots.
+
+---------------------------------------
+
+*getinventorylist;
+
+This command sets a bunch of arrays with a complete list of whatever the
+invoking character has in their inventory, including all the data needed to
+recreate these items perfectly if they are destroyed. Here's what you get:
+
+@inventorylist_id[] - array of item ids.
+@inventorylist_amount[] - their corresponding item amounts.
+@inventorylist_equip[] - whether the item is equipped or not.
+@inventorylist_refine[] - for how much it is refined.
+@inventorylist_identify[] - whether it is identified.
+@inventorylist_attribute[] - whether it is broken.
+@inventorylist_card1[] - These four arrays contain card data for the items.
+@inventorylist_card2[] These data slots are also used to store names
+@inventorylist_card3[] inscribed on the items, so you can explicitly check
+@inventorylist_card4[] if the character owns an item made by a specific
+ craftsman.
+@inventorylist_expire[] - expire time (Unix time stamp). 0 means never expires.
+@inventorylist_count - the number of items in these lists.
+
+This could be handy to save/restore a character's inventory, since no other
+command returns such a complete set of data, and could also be the only way to
+correctly handle an NPC trader for carded and named items who could resell them
+- since NPC objects cannot own items, so they have to store item data in
+variables and recreate the items.
+
+Notice that the variables this command generates are all temporary, attached to
+the character, and integer.
+
+Be sure to use @inventorylist_count to go through these arrays, and not
+'getarraysize', because the arrays are not automatically cleared between runs
+of 'getinventorylist'.
+
+---------------------------------------
+
+*cardscnt()
+
+This function will return the number of cards inserted into the weapon currently
+equipped on the invoking character.
+While this function was meant for item scripts, it will work outside them:
+
+ if (cardscnt()==4) mes "So you've stuck four cards into that weapon, think you're cool now?";
+
+---------------------------------------
+
+*getrefine()
+
+This function will return the number of pluses the weapon currently equipped on
+the invoking character has been refined for.
+While this function was meant for item scripts, it will work outside them:
+
+ if (getrefine()==10) mes "Wow. That's a murder weapon.";
+
+---------------------------------------
+
+*getnameditem(<item id>,"<name to inscribe>");
+*getnameditem("<item name>","<name to inscribe>");
+
+This function is equivalent to using 'getitem', however, it will not just give
+the character an item object, but will also inscribe it with a specified
+character's name. You may not inscribe items with arbitrary strings, only with
+names of characters that actually exist. While this isn't said anywhere
+specifically, apparently, named items may not have cards in them, slots or no -
+these data slots are taken by the character ID who's name is inscribed. Only one
+remains free and it's not quite clear if a card may be there.
+
+This function will return 1 if an item was successfully created and 0 if it
+wasn't for whatever reason. Like 'getitem', this function will also accept an
+'english name' from the item database as an item name and will return 0 if no
+such item exists.
+
+---------------------------------------
+
+*getitemslots(<item ID>)
+
+This function will look up the item with the specified ID number in the database
+and return the number of slots this kind of items has - 0 if they are not
+slotted. It will also be 0 for all non-equippable items, naturally, unless
+someone messed up the item database. It will return -1 if there is no such item.
+
+Example:
+
+//@slots now has the amount of slots of the item with ID 1205.
+ set @slots, getItemSlots(1205);
+
+---------------------------------------
+
+*getiteminfo(<item ID>,<type>)
+
+This function will look up the item with the specified ID number in the database
+and return the info set by TYPE argument.
+It will return -1 if there is no such item.
+
+Valid types are:
+ 0 - Buy Price; 1 - Sell Price; 2 - Item Type;
+ 3 - maxchance (Max drop chance of this item e.g. 1 = 0.01% , etc..
+ if = 0, then monsters don't drop it at all (rare or a quest item)
+ if = 10000, then this item is sold in NPC shops only
+ 4 - sex; 5 - equip; 6 - weight; 7 - atk; 8 - def; 9 - range;
+ 10 - slot; 11 - look; 12 - elv; 13 - wlv; 14 - view id
+
+ If RENEWAL is defined, 15 - matk
+
+Check sample in doc/sample/getiteminfo.txt
+
+---------------------------------------
+
+*getequipcardid(<equipment slot>,<card slot>)
+
+Returns value from equipped item slot in the indicated slot (0, 1, 2, or 3).
+
+This function returns CARD ID, 255,254,-255 (for card 0, if the item is produced).
+It's useful for when you want to check whether an item contains cards or if it's signed.
+
+---------------------------------------
+//
+2,1.- End of item-related commands.
+//
+---------------------------------------
+
+*getmapxy("<variable for map name>",<variable for x>,<variable for y>,<type>{,"<search string>"})
+
+This function will locate a character object, NPC object or pet's coordinates
+and place their coordinates into the variables specified when calling it. It
+will return 0 if the search was successful, and -1 if the parameters given were
+not variables or the search was not successful.
+
+Type is the type of object to search for:
+
+ 0 - Character object
+ 1 - NPC object
+ 2 - Pet object
+ 3 - Monster object
+ 4 - Homunculus object
+ 5 - Mercenary object
+ 6 - Elemental object
+
+While 3 is meant to look for a monster object, no searching will be done if you
+specify type 3, and the function will always return -1.
+
+The search string is optional. If it is not specified, the location of the
+invoking character will always be returned for types 0 and 2, the location of
+the NPC running this function for type 1.
+If a search string is specified, for types 0 and 1, the character or NPC with
+the specified name will be located. If type is 3, the search will locate the
+current pet of the character who's name is given in the search string, it will
+NOT locate a pet by name.
+
+What a mess. Example, a working and tested one now:
+
+ prontera,164,301,3%TAB%script%TAB%Meh%TAB%730,{
+ mes "My name is Meh. I'm here so that Nyah can find me.";
+ close;
+ }
+
+ prontera,164,299,3%TAB%script%TAB%Nyah%TAB%730,{
+ mes "My name is Nyah.";
+ mes "I will now search for Meh all across the world!";
+ if (getmapxy(@mapname$,@mapx,@mapy,1,"Meh")!=0) goto Notfound;
+ mes "And I found him on map "+@mapname$+" at X:"+@mapx+" Y:"+@mapy+" !";
+ close;
+ Notfound:
+ mes "I can't seem to find Meh anywhere!";
+ close;
+ }
+
+Notice that NPC objects disabled with 'disablenpc' will still be located.
+
+---------------------------------------
+
+*getgmlevel()
+
+This function will return the (GM) level of player group the account to which the
+invoking character belongs. If this is somehow executed from a console command,
+99 will be returned, and 0 will be returned if the account has no GM level.
+
+This allows you to make NPC's only accessible for certain GM levels, or behave
+specially when talked to by GMs.
+
+ if (getgmlevel()) mes "What is your command, your godhood?";
+ if (getgmlevel()) goto Wherever;
+
+---------------------------------------
+
+*getgroupid()
+
+This function will return the id of player group the account to which the
+invoking player belongs.
+
+---------------------------------------
+
+*gettimetick(<tick type>)
+
+This function will return the system time in UNIX epoch time (if tick type is 2)
+or the time since the start of the current day in seconds if tick type is 1.
+Passing 0 will make it return the server's tick, which is a measurement in
+milliseconds used by the server's timer system. The server's tick is an
+unsigned int which loops every ~50 days.
+
+Just in case you don't know, UNIX epoch time is the number of seconds elapsed
+since 1st of January 1970, and is useful to see, for example, for how long the
+character has been online with OnPCLoginEvent and OnPCLogoutEvent, which could allow
+you to make an 'online time counted for conviction only' jail script.
+
+---------------------------------------
+
+*gettime(<type>)
+
+This function will return specified information about the current system time.
+
+1 - Seconds (of a minute)
+2 - Minutes (of an hour)
+3 - Hour (of a day)
+4 - Week day (0 for Sunday, 6 is Saturday)
+5 - Day of the month.
+6 - Number of the month.
+7 - Year.
+8 - Day of the year.
+
+It will only return numbers.
+
+ if (gettime(4)==6) mes "It's a Saturday. I don't work on Saturdays.";
+
+---------------------------------------
+
+*gettimestr(<format string>,<max length>)
+
+This function will return a string containing time data as specified by the
+format string.
+
+This uses the C function 'strfmtime', which obeys special format characters. For
+a full description see, for example, the description of 'strfmtime' at
+http://www.delorie.com/gnu/docs/glibc/libc_437.html
+All the format characters given in there should properly work.
+Max length is the maximum length of a time string to generate.
+
+The example given in rAthena sample scripts works like this:
+
+ mes gettimestr("%Y-%m/%d %H:%M:%S",21);
+
+This will print a full date and time like 'YYYY-MM/DD HH:MM:SS'.
+
+---------------------------------------
+
+*getusers(<type>)
+
+This function will return a number of users on a map or the whole server. What
+it returns is specified by Type.
+
+Type can be one of the following values, which control what will be returned:
+
+ 0 - Count of all characters on the map of the invoking character.
+ 1 - Count of all characters in the entire server.
+ 8 - Count of all characters on the map of the NPC the script is
+ running in.
+
+---------------------------------------
+
+*getmapusers("<map name>")
+
+This function will return the number of users currently located on the specified
+map.
+
+Currently being used in the PVP scripts to check if a PVP room is full of not,
+if the number returned it equal to the maximum allowed it will not let you
+enter.
+
+---------------------------------------
+
+*getareausers("<map name>",<x1>,<y1>,<x2>,<y2>)
+
+This function will return the count of connected characters which are located
+within the specified area - an x1/y1-x2/y2 square on the specified map.
+
+This is useful for maps that are split into many buildings, such as all the
+"*_in" maps, due to all the shops and houses.
+
+---------------------------------------
+
+*getusersname;
+
+This command will give the invoking character a list of names of the connected
+characters (including themselves) into an NPC script message window (see 'mes')
+paging it by 10 names as if with the 'next' command.
+
+You need to put a 'close' after that yourself.
+
+---------------------------------------
+\\
+2,2.- Guild-related commands
+\\
+---------------------------------------
+*getguildname(<guild id>)
+
+This function returns a guild's name given an ID number. If there is no such
+guild, "null" will be returned;
+
+ // Would print what ever guild 10007 is, in my case this would return "AlcoROhics"
+ mes "The guild "+GetGuildName(10007)+" are all nice people.";
+
+ // This will do the same as above:
+ set @var,10007;
+ mes "We have some friends in "+GetGuildName(@var)+", you know.";
+
+This is used all over the WoE controlling scripts. You could also use it for a
+guild-based event.
+
+---------------------------------------
+
+*getguildmaster(<guild id>)
+
+This function return the name of the master of the guild which has the specified
+ID number. If there is no such guild, "null" will be returned.
+
+// Would return the guild master of guild 10007, whatever that might be.
+// In this example it would return "MissDjax" cause she owns "AlcoROhics" (10007)
+ mes getguildmaster(10007)+" runs "+getguildname(10007);
+
+Can be used to check if the character is the guild master of the specified guild.
+
+Maybe you want to make a room only guild masters can enter:
+
+ set @GID,getcharid(2);
+ if(@GID==0) goto L_NoGuild;
+ if(strcharinfo(0)==getguildmaster(@GID)) goto L_GuildMaster;
+ mes "Sorry you don't own the guild you are in";
+ close;
+ L_NoGuild:
+ mes "Sorry you are not in a guild";
+ close;
+ L_GuildMaster:
+ mes "Welcome guild master of "+GetGuildName(@GID);
+ close;
+
+
+---------------------------------------
+
+*getguildmasterid(<guild id>)
+
+This function will return the character ID number of the guild master of the
+guild specified by the ID. 0 if the character is not a guild master of any guild.
+
+---------------------------------------
+
+*getcastlename("<map name>")
+
+This function returns the name of the castle when given the map name for that
+castle. The data is read from 'db/castle_db.txt'.
+
+---------------------------------------
+
+*getcastledata("<map name>",<type of data>)
+*setcastledata "<map name>",<type of data>,<value>;
+
+This function returns the castle ownership information for the castle referred
+to by its map name. Castle information is stored in `guild_castle` SQL table.
+
+Types of data correspond to `guild_castle` table columns:
+
+ 1 - `guild_id` - Guild ID.
+ 2 - `economy` - Castle Economy score.
+ 3 - `defense` - Castle Defense score.
+ 4 - `triggerE` - Number of times the economy was invested in today.
+ 5 - `triggerD` - Number of times the defense was invested in today.
+ 6 - `nextTime` - unused
+ 7 - `payTime` - unused
+ 8 - `createTime` - unused
+ 9 - `visibleC` - Is 1 if a Kafra was hired for this castle, 0 otherwise.
+10 - `visibleG0` - Is 1 if the 1st guardian is present (Soldier Guardian)
+11 - `visibleG1` - Is 1 if the 2nd guardian is present (Soldier Guardian)
+12 - `visibleG2` - Is 1 if the 3rd guardian is present (Soldier Guardian)
+13 - `visibleG3` - Is 1 if the 4th guardian is present (Archer Guardian)
+14 - `visibleG4` - Is 1 if the 5th guardian is present (Archer Guardian)
+15 - `visibleG5` - Is 1 if the 6th guardian is present (Knight Guardian)
+16 - `visibleG6` - Is 1 if the 7th guardian is present (Knight Guardian)
+17 - `visibleG7` - Is 1 if the 8th guardian is present (Knight Guardian)
+
+All types of data have their meaning determined by War of Emperium scripts,
+with exception of:
+ - `guild_id` that is always considered ID of the guild that owns the castle,
+ - `defense` that is used in Guardians & Emperium HP calculations,
+ - `visibleG` that is always considered to hold guardian presence bits.
+
+The 'setcastledata' command will behave identically, but instead of returning
+values for the specified types of accessible data, it will alter them and cause
+them to be sent to the char-server for storage.
+
+Changing Guild ID or Castle Defense will trigger additional actions, like
+recalculating guardians' HP.
+
+---------------------------------------
+
+*getgdskilllv(<guild id>,<skill id>)
+*getgdskilllv(<guild id>,"<skill name>")
+
+This function returns the level of the skill <skill id> of the guild <guild id>.
+If the guild does not have that skill, 0 is returned.
+If the guild does not exist, -1 is returned.
+Refer to 'db/(pre-)re/skill_db.txt' for the full list of skills. (GD_* are guild skills)
+
+---------------------------------------
+
+*requestguildinfo <guild id>{,"<event label>"};
+
+This command requests the guild data from the char server and merrily continues
+with the execution. Whenever the guild information becomes available (which
+happens instantly if the guild information is already in memory, or later, if it
+isn't and the map server has to wait for the char server to reply) it will run
+the specified event as in a 'doevent' call.
+
+---------------------------------------
+
+*getmapguildusers(<mapname>,<guild id>)
+
+Returns the amount of characters from the specified guild on the given map.
+
+Example:
+
+mes "You have "+getMapGuildUsers("prontera",getcharid(2))+" guild members in Prontera.";
+
+---------------------------------------
+//
+2,2.- End of guild-related commands
+//
+---------------------------------------
+
+*getskilllv(<skill id>)
+*getskilllv("<skill name>")
+
+This function returns the level of the specified skill that the invoking
+character has. If they don't have the skill, 0 will be returned. The full list
+of character skills is available in 'db/(pre-)re/skill_db.txt'.
+
+There are two main uses for this function, it can check whether the character
+has a skill or not, and it can tell you if the level is high enough.
+
+Example 1:
+
+ if (getskilllv(152)) goto L_HasSkillThrowStone;
+ mes "You don't have Throw Stone";
+ close;
+ L_HasSkillThrowStone:
+ mes "You have got the skill Throw Stone";
+ close;
+
+Example 2:
+
+ if (getskilllv(28) >= 5) goto L_HasSkillHeallvl5orMore;
+ if (getskilllv(28) == 10) goto L_HasSkillHealMaxed;
+ mes "You heal skill is below lvl 5";
+ close;
+ L_HasSkillHeallvl6orMore:
+ mes "Your heal lvl is 5 or more";
+ close;
+ L_HasSkillHealMaxed:
+ mes "Your heal lvl has been maxed";
+ close;
+
+---------------------------------------
+
+*getskilllist;
+
+This command sets a bunch of arrays with a complete list of skills the
+invoking character has. Here's what you get:
+
+@skilllist_id[] - skill ids.
+@skilllist_lv[] - skill levels.
+@skilllist_flag[] - see 'skill' for the meaning of skill flags.
+@skilllist_count - number of skills in the above arrays.
+
+While 'getskillv' is probably more useful for most situations, this is the
+easiest way to store all the skills and make the character something else for a
+while. Advanced job for a day? :) This could also be useful to see how many
+skills a character has.
+
+---------------------------------------
+
+*getpetinfo(<type>)
+
+This function will return pet information for the pet the invoking character
+currently has active. Valid types are:
+
+ 0 - Unique pet ID number as stored by the char server and distinguishing it
+ from all other pets the characters actually have. This value is currently
+ useless, at most you can use it to tell pets apart reliably.
+ 1 - Pet class number as per 'db/pet_db.txt' - will tell you what kind of a pet it
+ is.
+ 2 - Pet name. Will return "null" if there's no pet.
+ 3 - Pet friendly level (intimacy score). 1000 is full loyalty.
+ 4 - Pet hungry level. 100 is completely full.
+ 5 - Pet rename flag. 0 means this pet has not been named yet.
+
+---------------------------------------
+
+*gethominfo(<type>)
+
+This function works as a direct counterpart of 'getpetinfo':
+ 0 - Homunculus unique ID
+ 1 - Homunculus Class
+ 2 - Name
+ 3 - Friendly level (intimacy score). 100000 is full loyalty.
+ 4 - Hungry level. 100 is completely full.
+ 5 - Rename flag. 0 means this homunculus has not been named yet.
+ 6 - Homunculus level
+
+---------------------------------------
+
+*petstat(<flag>)
+
+Returns current pet status, all are integers except name.
+Returns 0 or "" if the player doesn't have pets.
+
+Flags usable >>
+PET_CLASS
+PET_NAME
+PET_LEVEL
+PET_HUNGRY
+PET_INTIMATE
+
+Example:
+ set @i, petstat(PET_CLASS);
+
+---------------------------------------
+
+*getmonsterinfo(<mob ID>,<type>)
+
+This function will look up the monster with the specified ID number in the
+mob database and return the info set by TYPE argument.
+It will return -1 if there is no such monster (or the type value is invalid),
+or "null" if you requested the monster's name.
+
+Valid types are listed in const.txt:
+ MOB_NAME 0
+ MOB_LV 1
+ MOB_MAXHP 2
+ MOB_BASEEXP 3
+ MOB_JOBEXP 4
+ MOB_ATK1 5
+ MOB_ATK2 6
+ MOB_DEF 7
+ MOB_MDEF 8
+ MOB_STR 9
+ MOB_AGI 10
+ MOB_VIT 11
+ MOB_INT 12
+ MOB_DEX 13
+ MOB_LUK 14
+ MOB_RANGE 15
+ MOB_RANGE2 16
+ MOB_RANGE3 17
+ MOB_SIZE 18
+ MOB_RACE 19
+ MOB_ELEMENT 20
+ MOB_MODE 21
+ MOB_MVPEXP 22
+
+Check sample in doc/sample/getmonsterinfo.txt
+
+---------------------------------------
+
+*getmobdrops(<mob id>)
+
+This command will find all drops of the specified mob and return the item IDs
+and drop percentages into arrays of temporary global variables.
+'getmobdrops' returns 1 if successful and 0 if the mob ID doesn't exist.
+
+Upon executing this,
+
+$@MobDrop_item[] is a global temporary number array which contains the
+ item IDs of the monster's drops.
+
+$@MobDrop_rate[] is a global temporary number array which contains the
+ drop percentages of each item. (1 = .01%)
+
+$@MobDrop_count is the number of item drops found.
+
+Be sure to use $@MobDrop_count to go through the arrays, and not
+'getarraysize', because the temporary global arrays are not cleared between
+runs of 'getmobdrops'. If a mob with 7 item drops is looked up, the arrays would
+have 7 elements. But if another mob is looked up and it only has 5 item drops,
+the server will not clear the arrays for you, overwriting the values instead. So
+in addition to returning the 5 item drops, the 6th and 7th elements from the
+last call remain, and you will get 5+2 item drops, of which the last 2 don't
+belong to the new mob. $@MobDrop_count will always contain the correct number
+(5), unlike 'getarraysize()' which would return 7 in this case.
+
+Example:
+
+ // get a Mob ID from the user
+ input .@mob_id;
+
+ if (getmobdrops(.@mob_id)) { // 'getmobdrops' returns 1 on success
+ // immediately copy global temporary variables into scope variables,
+ // since we don't know when 'getmobdrops' will get called again for
+ // another mob, overwriting your global temporary variables
+ set .@count, $@MobDrop_count;
+ copyarray .@item[0],$@MobDrop_item[0],.@count;
+ copyarray .@rate[0],$@MobDrop_rate[0],.@count;
+
+ mes getmonsterinfo(.@mob_id,MOB_NAME) + " - " + .@count + " drops found:";
+ for( set .@i,0; .@i < .@count; set .@i,.@i +1 ) {
+ mes .@item[.@i] + " (" + getitemname(.@item[.@i]) + ") " + .@rate[.@i]/100 + ((.@rate[.@i]%100 < 10) ? ".0":".") + .@rate[.@i]%100 + "%";
+ }
+ } else {
+ mes "Unknown monster ID.";
+ }
+ close;
+
+---------------------------------------
+
+*skillpointcount()
+
+Returns the total amount of skill points a character possesses (SkillPoint+SP's used in skills)
+This command can be used to check the currently attached characters total amount of skill points.
+This means the skill points used in skill are counted, and added to SkillPoints (number of skill points not used).
+
+Example:
+
+//This will set the temp character variable @skillPoints to the amount of skill points,
+//and then tell the player the value.
+ set @skillPoints, skillPointCount();
+ mes "You have "+@skillPoints+" skill points in total!";
+
+//Self-explanatory... :P
+ if (skillPointCount() > 20)
+ mes "Wow, you have more then 20 Skill Points in total!";
+
+---------------------------------------
+
+*getscrate(<effect type>,<base rate>{,<GID>})
+
+This function will return the chance of a status effect affecting the invoking
+character, in percent, modified by the their current defense against said
+status. The 'base rate' is the base chance of the status effect being inflicted,
+in percent.
+
+ if (rand(100) > getscrate(Eff_Blind, 50)) goto BlindHimNow;
+
+You can see the full list of available effect types you can possibly inflict in
+'db/const.txt' under 'Eff_'.
+
+---------------------------------------
+
+========================
+|3.- Checking commands.|
+========================
+-------------------------
+
+*playerattached()
+
+Returns the ID of the player currently attached to the script. It will return
+0 if no one is attached, or if the attached player no longer exists on the map
+server. It is wise to check for the attached player in script functions that
+deal with timers as there's no guarantee the player will still be logged on
+when the timer triggers. Note that the ID of a player is actually their
+account ID.
+
+---------------------------------------
+
+*isloggedin(<account id>{,<char id>})
+
+This function returns 1 if the specified account is logged in and 0 if they
+aren't. You can also pass the char_id to check for both account and char id.
+
+---------------------------------------
+
+*checkweight(<item id>,<amount>{,<item id>,<amount>,<item id>,<amount>,...});
+*checkweight("<item name>",<amount>{,"<item name>",<amount>,"<item name>",<amount>,...});
+*checkweight2(<id_array>,<amount_array>);
+
+These functions will compute and return 1 if the total weight of the specified
+number of specific items does not exceed the invoking character's carrying
+capacity, and 0 otherwise. It is important to see if a player can carry the
+items you expect to give them, failing to do that may open your script up to
+abuse or create some very unfair errors.
+
+The second function will check an array of items and amounts, and also
+returns 1 on success and 0 on failure.
+
+The functions, in addition to checking to see if the player is capable of
+holding a set amount of items, also ensure the player has room in their
+inventory for the item(s) they will be receiving.
+
+Like 'getitem', this function will also accept an 'english name' from the
+database as an argument.
+
+Example 1:
+
+ if (checkweight(512,10)) {
+ getitem 512,10;
+ } else {
+ mes "Sorry, you cannot hold this amount of apples!";
+ }
+
+Example 2:
+
+ setarray .@item[0],512,513,514;
+ setarray .@amount[0],10,5,5;
+ if (!checkweight(.@item,.@amount)) {
+ mes "Sorry, you cannot hold this amount of fruit!";
+ }
+
+---------------------------------------
+
+*basicskillcheck()
+
+This function will return the state of the configuration option
+'basic_skill_check' in 'battle_athena.conf'. It returns 1 if the option is
+enabled and 0 if it isn't. If the 'basic_skill_check' option is enabled, which
+it is by default, characters must have a certain number of basic skill levels to
+sit, request a trade, use emotions, etc. Making your script behave differently
+depending on whether the characters must actually have the skill to do all these
+things might in some cases be required.
+
+---------------------------------------
+
+*checkoption(<option number>)
+*checkoption1(<option number>)
+*checkoption2(<option number>)
+*setoption <option number>{,<flag>};
+
+The 'setoption' series of functions check for a so-called option that is set on
+the invoking character. 'Options' are used to store status conditions and a lot
+of other non-permanent character data of the yes-no kind. For most common cases,
+it is better to use 'checkcart','checkfalcon','checkpeco' and other similar
+functions, but there are some options which you cannot get at this way. They
+return 1 if the option is set and 0 if the option is not set.
+
+Option numbers valid for the first (option) version of this command are:
+
+0x1 - Sight in effect.
+0x2 - Hide in effect.
+0x4 - Cloaking in effect.
+0x8 - Cart number 1 present.
+0x10 - Falcon present.
+0x20 - Peco Peco present.
+0x40 - GM Perfect Hide in effect.
+0x80 - Cart number 2 present.
+0x100 - Cart number 3 present.
+0x200 - Cart number 4 present.
+0x400 - Cart number 5 present.
+0x800 - Orc head present.
+0x1000 - The character is wearing a wedding sprite.
+0x2000 - Ruwach is in effect.
+0x4000 - Chasewalk in effect.
+0x8000 - Flying or Xmas suit.
+0x10000 - Sighttrasher.
+0x100000 - Warg present.
+0x200000 - The character is riding a warg.
+
+Option numbers valid for the second version (opt1) of this command are:
+
+1 - Petrified.
+2 - Frozen.
+3 - Stunned.
+4 - Sleeping.
+6 - Petrifying (the state where you can still walk)
+
+Option numbers valid for the third version (opt2) of this command are:
+
+0x1 - Poisoned.
+0x2 - Cursed.
+0x4 - Silenced.
+0x8 - Signum Crucis (plays a howl-like sound effect, but otherwise no visible effects are displayed)
+0x10 - Blinded.
+0x80 - Deadly poisoned.
+
+Option numbers (except for opt1) are bit-masks - you can add them up to check
+ for several states, but the functions will return true if at least one of them
+ is in effect.
+
+'setoption' will set options on the invoking character. There are no second and
+third versions of this command, so you can only change the values in the first
+list (cloak, cart, ruwach, etc). if flag is 1 (default when omitted),
+the option will be added to what the character currently has; if 0, the option is removed.
+
+This is definitely not a complete list of available option flag numbers. Ask a
+core developer (or read the source: src/map/status.h) for the full list.
+
+---------------------------------------
+
+*setcart {<type>};
+*checkcart()
+
+If <type> is 0 this command will remove the cart from the character.
+Otherwise it gives the invoking character a cart. The cart given will be
+cart number <type> and will work regardless of whether the character is a
+merchant class or not.
+Note: the character needs to have the skill MC_PUSHCART to gain a cart
+
+The accompanying function will return 1 if the invoking character has a cart
+(any kind of cart) and 0 if they don't.
+
+ if (checkcart()) mes "But you already have a cart!";
+
+---------------------------------------
+
+*setfalcon {<flag>};
+*checkfalcon()
+
+If <flag> is 0 this command will remove the falcon from the character.
+Otherwise it gives the invoking character a falcon. The falcon will be there
+regardless of whether the character is a hunter or not. It will (probably) not
+have any useful effects for non-hunters though.
+Note: the character needs to have the skill HT_FALCON to gain a falcon
+
+The accompanying function will return 1 if the invoking character has a falcon
+and 0 if they don't.
+
+ if (checkfalcon()) mes "But you already have a falcon!";
+
+---------------------------------------
+
+*setriding {<flag>};
+*checkriding()
+
+If <flag> is 0 this command will remove the mount from the character.
+Otherwise it gives the invoking character a PecoPeco (if they are a Knight
+series class), a GrandPeco (if they are a Crusader series class), or
+a Gryphon (if they are a Royal Guard). Unlike 'setfalcon' and 'setcart'
+this will not work at all if they aren't of a class which can ride.
+Note: the character needs to have the skill KN_RIDING to gain a mount
+
+The accompanying function will return 1 if the invoking character is riding a
+bird and 0 if they aren't.
+
+ if (checkriding()) mes "PLEASE leave your bird outside! No riding birds on the floor here!";
+
+---------------------------------------
+
+*setdragon {<color>};
+*checkdragon()
+
+The 'setdragon' function toggles mounting a dragon for the invoking character.
+It will return 1 if successful, 0 otherwise.
+
+If the character can mount a dragon, the <color> options are:
+ 1 - Green Dragon (default when omitted)
+ 2 - Brown Dragon
+ 3 - Gray Dragon
+ 4 - Blue Dragon
+ 5 - Red Dragon
+
+Note: the character must be a Rune Knight and have the skill RK_DRAGONTRAINING to gain a mount
+
+The accompanying function will return 1 if the invoking character is riding a
+dragon and 0 if they aren't.
+
+---------------------------------------
+
+*setmadogear {<flag>};
+*checkmadogear()
+
+If <flag> is 0 this command will remove the mount from the character.
+Otherwise it gives the invoking character a Mado (if they are a Mechanic).
+
+The accompanying function will return 1 if the invoking character has a
+Mado and 0 if they don't.
+
+---------------------------------------
+
+*setmounting;
+*ismounting()
+
+The 'setmounting' function toggles cash mount for the invoking character.
+It will return 1 if successful, 0 otherwise.
+
+Note: Character must not be mounting a non-cash mount (eg. dragon, peco, wug, etc.)
+
+The accompanying function will return 1 if the invoking character has a
+cash mount and 0 if they don't.
+
+---------------------------------------
+
+*checkwug()
+
+This function will return 1 if the invoking character has a
+warg and 0 if they don't.
+
+---------------------------------------
+
+*checkvending({"<player name>"})
+*checkchatting({"<Player Name>"})
+
+Checks if the player is vending or in a chatroom.
+Name is optional, and defaults to the attached player if omitted.
+
+Return values for 'checkvending' are
+ 0 = not vending
+ 1 = normal vending
+ 2 = vending using @autotrade
+
+'checkchatting' returns 1 if they are in a chat room, 0 if they are not.
+
+Examples:
+ //This will check if Aaron is vending, and if so, put a message in front
+ //of the attached player saying Aaron is vending.
+ if (checkvending("Aaron"))
+ mes "Aaron is currently vending!";
+
+ //This will check if the attached player in a chat room or not.
+ if (checkchatting())
+ mes "You are currently in a chat room!";
+
+---------------------------------------
+
+*agitcheck()
+*agitcheck2()
+
+These function will let you check whether the server is currently in WoE mode
+(or WoE SE mode if the second function is called) and will return 1 if War of
+Emperium is on and 0 if it isn't.
+
+---------------------------------------
+
+*isnight()
+*isday()
+
+These functions will return 1 or 0 depending on whether the server is in night
+mode or day mode. 'isnight' returns 1 if it's night and 0 if it isn't, 'isday'
+the other way around. They can be used interchangeably, pick the one you like
+more:
+
+ // These two are equivalent:
+ if (isday()) mes "I only prowl in the night.";
+ if (isnight()!=1) mes "I only prowl in the night.";
+
+---------------------------------------
+
+*checkre(<type>)
+
+Checks if a renewal feature is enabled or not in renewal.h, and returns 1 if enabled and 0 for disabled.
+The renewal feature to check is determined by type.
+
+ 0 - RENEWAL (game renewal server mode)
+ 1 - RENEWAL_CAST (renewal cast time)
+ 2 - RENEWAL_DROP (renewal drop rate algorithms)
+ 3 - RENEWAL_EXP (renewal exp rate algorithms)
+ 4 - RENEWAL_LVDMG (renewal level modifier on damage)
+ 5 - RENEWAL_EDP (renewal enchant deadly poison algorithm)
+ 6 - RENEWAL_ASPD (renewal ASPD)
+
+---------------------------------------
+\\
+3,1.- Item-related commands
+\\
+---------------------------------------
+*isequipped(<id>{,<id>{,<id>{,<id>}}})
+
+This function will return 1 if the invoking character has all of the item
+IDs given equipped (if card IDs are passed, then it checks if the cards are
+inserted into slots in the equipment they are currently wearing). Theoretically
+there is no limit to the number of items that may be tested for at the same time.
+If even one of the items given is not equipped, 0 will be returned.
+
+ // (Poring,Santa Poring,Poporing,Marin)
+ if (isequipped(4001,4005,4033,4196)) mes "Wow! You're wearing a full complement of possible poring cards!";
+ // (Poring)
+ if (isequipped(4001)) mes "A poring card is useful, don't you think?";
+
+The function was meant for item scripts to support the cards released by Gravity
+in February 2005, but it will work just fine in normal NPC scripts.
+
+---------------------------------------
+
+*isequippedcnt(<card id>{,<card id>{,<card id>{,<card id>}}})
+
+This function is similar to 'isequipped', but instead of 1 or 0, it will return
+the number of cards in the list given that were found on the invoking character.
+
+ if (isequippedcnt(4001,4005,4033,4196) == 4) mes "Finally got all four poring cards?";
+
+---------------------------------------
+
+*checkequipedcard(<card id>)
+
+This function will return 1 if the card specified by it's item ID number is
+inserted into any equipment they have in their inventory, currently equipped or
+not.
+
+---------------------------------------
+
+*getequipisidentify(<equipment slot>)
+
+This function will return 1 if an item in the specified equipment slot is
+identified and 0 if it isn't. Since you can't even equip unidentified equipment,
+there's a question of whether it can actually end up there, and it will normally
+return 1 all the time if there is an item in this equipment slot.
+Which is kinda pointless.
+For a list of equipment slots see 'getequipid'.
+
+---------------------------------------
+//
+3,1.- End of item-related commands
+//
+---------------------------------------
+
+==============================
+|4.- Player-related commands.|
+==============================
+-------------------------
+
+*attachrid(<account ID>)
+*detachrid;
+
+These commands allow the manipulation of the script's currently attached player.
+While attachrid allows attaching of a different player by using it's account id
+for the parameter rid, detachrid makes the following commands run, as if the
+script was never invoked by a player.
+
+In case, that the player cannot be attached, such as, when the player went
+offline in the mean time, attachrid returns 0, otherwise 1.
+
+---------------------------------------
+
+*rid2name(<rid>)
+
+Converts rid to name. Note: The player/monster/NPC must be online/enabled.
+Good for PCKillEvent where you can convert 'killedrid' to the name of the player.
+
+Note: rid2name may not produce correct character names since rid = account id.
+ It will return the current online character of the account only.
+
+---------------------------------------
+
+*message "<character name>","<message>";
+
+That command will send a message to the chat window of the character specified
+by name. The text will also appear above the head of that character. It will not
+be seen by anyone else.
+
+---------------------------------------
+
+*dispbottom "<message>";
+
+This command will send the given message into the invoking character's chat
+window.
+
+---------------------------------------
+
+*warp "<map name>",<x>,<y>;
+
+This command will take the invoking character to the specified map, and if
+wanted, specified coordinates too, but these can be random.
+
+ warp "place",50,55;
+
+This would take them to X 50 Y 55 on the map called "place". If your X and Y
+coordinates land on an unwalkable map square, it will send the warped character
+to a random place. Same will happen if they are both zero:
+
+ warp "place",0,0;
+
+Notice that while warping people to coordinates 0,0 will normally get them into
+a random place, it's not certain to always be so. Darned if I know where this is
+actually coded, it might be that this happens because square 0,0 is unwalkable
+on all official maps. If you're using custom maps, beware.
+
+There are also three special 'map names' you can use.
+
+"Random" will warp the player randomly on the current map.
+"Save" and "SavePoint" will warp the player back to their save point.
+
+---------------------------------------
+
+*areawarp "<from map name>",<x1>,<y1>,<x2>,<y2>,"<to map name>",<x3>,<y3>{,<x4>,<y4>};
+
+This command is similar to 'warp', however, it will not refer to the invoking
+character, but instead, all characters within a specified area, defined by the
+x1/y1-x2/y2 square, will be warped. Nobody outside the area will be affected,
+including the activating character, if they are outside the area.
+
+ areawarp "place",10,10,120,120,"place2",150,150;
+
+Everyone that is in the area between X 10 Y 10 and X 120 Y 120, in a square
+shape, on the map called "place", will be affected, and warped to "place2" X 150
+Y 150
+
+ areawarp "place",10,10,120,120,"place2",0,0;
+
+By using ,0,0; as the destination coordinates it will take all the characters in
+the affected area to a random set of co-ordinates on "place2".
+
+ areawarp "place",10,10,120,120,"place2",150,150,200,200;
+
+By using the optional x4 and y4 parameters, the destination coordinates will be a
+random place within the defined x3/y3-x4/y4 square.
+
+Like 'warp', areawarp will also explicitly warp characters randomly into the
+current map if you give the 'to map name' as "Random".
+
+See also 'warp'.
+
+---------------------------------------
+
+*warpparty "<to_mapname>",<x>,<y>,<party_id>,{"<from_mapname>"};
+
+Warps a party to specified map and coordinate given the party ID, which you can get with
+getcharid(1). You can also request another party id given a member's name with getcharid(1,<player_name>).
+
+You can use the following "map names" for special warping behavior:
+Random: All party members are randomly warped in their current map (as if they
+ all used a fly wing)
+SavePointAll: All party members are warped to their respective save point.
+SavePoint: All party members are warped to the save point of the currently
+ attached player (will fail if there's no player attached).
+Leader: All party members are warped to the leader's position. The leader must
+ be online and in the current map-server for this to work.
+
+If you specify a from_mapname, warpparty will only affect those on that map.
+
+Example:
+
+mes "[Party Warper]";
+mes "Here you go!";
+close2;
+set @id,getcharid(1);
+warpparty "prontera",150,100,@id;
+close;
+
+---------------------------------------
+
+*warpchar "<mapname>",<x>,<y>,<char_id>;
+
+Warps another player to specified map and coordinate given the char id, which you can get with
+getcharid(0,<player_name>). Obviously this is useless if you want to warp the same player that
+is executing this script, unless it's some kind of "chosen" script.
+
+Example:
+
+warpchar "prontera",150,100,150001;
+
+---------------------------------------
+
+*warpguild "<mapname>",<x>,<y>,<guild_id>;
+
+Warps a guild to specified map and coordinate given the guild id, which you can get with
+getcharid(2). You can also request another guild id given the member's name with getcharid(2,<player_name>).
+
+You can use the following "map names" for special warping behavior:
+Random: All guild members are randomly warped in their current map (as if they
+ all used a fly wing)
+SavePointAll: All guild members are warped to their respective save point.
+SavePoint: All guild members are warped to the save point of the currently
+ attached player (will fail if there's no player attached).
+
+Example:
+
+warpguild "prontera",x,y,Guild_ID;
+
+---------------------------------------
+
+*warppartner("<map name>",<x>,<y>);
+
+This function will find the invoking character's marriage partner, if any, and
+warp them to the map and coordinates given. Go kidnap that spouse. :) It will
+return 1 upon success and 0 if the partner is not online, the character is not
+married, or if there's no invoking character (no RID). 0,0 will, as usual,
+normally translate to random coordinates.
+
+---------------------------------------
+
+*savepoint "<map name>",<x>,<y>;
+*save "<map name>",<x>,<y>;
+
+This command saves where the invoking character will return to upon
+'return to save point', if dead or in some other cases. The two versions are
+equivalent. Map name, X coordinate and Y coordinate should be perfectly obvious.
+This ignores any and all map flags, and can make a character respawn where no
+teleportation is otherwise possible.
+
+ savepoint "place",350,75;
+
+---------------------------------------
+
+*heal <hp>,<sp>;
+
+This command will heal a set amount of HP and/or SP on the invoking character.
+
+ heal 30000,0; // This will heal 30,000 HP
+ heal 0,30000; // This will heal 30,000 SP
+ heal 300,300; // This will heal 300 HP and 300 SP
+
+This command just alters the hit points and spell points of the invoking
+character and produces no other output whatsoever.
+
+---------------------------------------
+
+*itemheal <hp>,<sp>;
+
+This command heals given absolute amounts of HP and/or SP on the invoking
+character. Unlike heal, this command is intended for use in item scripts. It
+applies potion-related bonuses, such as alchemist ranking, cards and status
+changes. When used inside an NPC script, certain bonuses are omitted.
+
+There is also a nice example on using this with the 'rand' function, to give you
+a random amount of healing.
+
+ // This will heal anything thing from 100 to 150 HP and no SP
+ itemheal rand(100,150),0;
+
+---------------------------------------
+
+*percentheal <hp>,<sp>;
+
+This command will heal the invoking character. It heals the character, but not
+by a set value - it adds percent of their maximum HP/SP.
+
+ percentheal 100,0; // This will heal 100% HP
+ percentheal 0,100; // This will heal 100% SP
+ percentheal 50,50; // This will heal 50% HP and 50% SP
+
+So the amount that this will heal will depend on the total amount of HP or SP
+you have maximum. Like 'heal', this will not call up any animations or effects.
+
+---------------------------------------
+
+*recovery;
+
+This command will revive and restore full HP and SP to all characters currently
+connected to the server.
+
+---------------------------------------
+
+*jobchange <job number>{,<upper flag>};
+
+This command will change the job class of the invoking character.
+
+ jobchange 1; // This would change your player into a Swordman
+ jobchange 4002; // This would change your player into a Swordman High
+
+This command does work with numbers, but you can also use job names. The full
+list of job names and the numbers they correspond to can be found in
+'db/const.txt'.
+
+ // This would change your player into a Swordman
+ jobchange Job_Swordman;
+ // This would change your player into a Swordman High
+ jobchange Job_Swordman_High;
+
+'upper flag' can alternatively be used to specify the type of job one changes
+to. For example, jobchange Job_Swordman,1; will change the character to a high
+swordsman. The upper values are:
+-1 (or when omitted): preserves the current job type.
+0: Normal/standard classes
+1: High/Advanced classes
+2: Baby classes
+
+This command will also set a permanent character-based variable
+'jobchange_level' which will contain the job level at the time right before
+changing jobs, which can be checked for later in scripts.
+
+---------------------------------------
+
+*jobname (<job number>)
+
+This command retrieves the name of the given job using the msg_athena entries 550->650.
+
+ mes "[Kid]";
+ mes "I never thought I'd met a "+jobname(Class)+" here of all places.";
+ close;
+
+---------------------------------------
+
+*eaclass ({<job number>})
+
+This commands returns the "eA job-number" corresponding to the given class (if none is given, it returns uses
+the invoking player's class as argument). The eA job-number is also a class number system, but it's one that
+comes with constants which make it easy to convert among classes. The command will return -1 if you pass it a
+job number which doesn't has a eA Job value equivalent.
+
+ set @eac, eaclass();
+ if ((@eac&EAJ_BASEMASK) == EAJ_SWORDMAN)
+ mes "You must be a swordman, knight, crusader, paladin, high swordman, lord knight, baby swordman,";
+ mes "baby knight or baby crusader.";
+ if (@eac&EAJL_UPPER)
+ mes "You are a rebirth job.";
+ if ((@eac&EAJ_UPPERMASK) == EAJ_SWORDMAN)
+ mes "You must be a Swordman, Baby Swordman or High Swordman.";
+
+For more information on the eA Job System, see the docs/ea_job_system.txt file.
+
+---------------------------------------
+*roclass <job number> {,<gender>}
+
+Does the opposite of eaclass. That is, given a eA Job class, it returns which is the corresponding RO class number.
+A gender is required because both Bard and Dancers share the same eA Job value (EAJ_BARDDANCER), if it isn't given, the
+gender of the executing player is taken (if there's no player running the script, male will be used by default).
+The command returns -1 when there isn't a valid class to represent the required job (for example, if you try to get the
+baby version of a Taekwon class).
+
+ set @eac, eaclass();
+ //Check if class is already rebirth
+ if (@eac&EAJL_UPPER) {
+ mes "You look strong.";
+ close;
+ }
+ set @eac, roclass(@eac|EAJL_UPPER);
+ //Check if class has a rebirth version
+ if (@eac != -1) {
+ mes "Bet you can't wait to become a "+jobname(@eac)+"!";
+ close;
+ }
+
+---------------------------------------
+
+*changebase <job ID number>;
+
+This will change the appearance of the invoking character to that of a specified
+job class. Nothing but appearance will change. This command is used in item
+scripts for "Wedding Dress" and "Tuxedo" so the character like job 22, which is
+the job number of the wedding sprites.
+
+It would be entered in the equip bonus section of an item
+
+2338,Wedding_Dress,Wedding Dress,5,43000,,500,,0,,0,119529470,7,0,16,,0,1,0,{ bonus bMdef,15; changebase 22; }
+
+---------------------------------------
+
+*classchange <view id>,<type>;
+
+This command is very ancient, it's origins are clouded in mystery.
+It will send a 'display id change' packet to everyone in the immediate area of
+the NPC object, which will supposedly make the NPC look like a different sprite,
+an NPC sprite ID, or a monster ID. This effect is not stored anywhere and will
+not persist (Which is odd, cause it would be relatively easy to make it do so)
+and most importantly, will not work at all since this command was broken with
+the introduction of advanced classes. The code is written with the assumption
+that the lowest sprite IDs are the job sprites and the anything beyond them is
+monster and NPC sprites, but since the advanced classes rolled in, they got the
+ID numbers on the other end of the number pool where monster sprites float.
+
+As a result it is currently impossible to call this command with a valid view
+id. It will do nothing whatsoever if the view ID is below 4047. Getting it to
+run will actually just crash the client.
+
+It could be a real gem if it can be gotten to actually do what it's supposed to
+do, but this will only happen in a later SVN revision.
+
+---------------------------------------
+
+*changesex;
+
+This command will change the gender for the attached character's account. If it
+was male, it will become female, if it was female, it will become male. The
+change will be written to the character server, the player will receive the
+message: "Need disconnection to perform change-sex request..." and the player
+will be immediately kicked to the login screen. When they log back in, they will
+be the opposite sex.
+
+If there are any Dancer/Gypsy or Bard/Clown characters on the account,
+they will also have their skills reset upon 'changesex'.
+
+---------------------------------------
+
+*getexp <base xp>,<job xp>;
+
+This command will give the invoking character a specified number of base and job
+experience points. Can be used as a quest reward. Negative values won't work.
+
+ getexp 10000,5000;
+
+You can also use the "set" command with the constants defined in 'db/const.txt':
+
+ // These 2 combined has the same effect as the above command
+ set BaseExp,BaseExp+10000;
+ set JobExp,JobExp+5000;
+
+You can also reduce the amount of experience points:
+
+ set BaseExp,BaseExp-10000;
+
+Note that 'getexp' is now subject to the 'quest_exp_rate' config option, which
+adjusts the gained value. If you want to bypass this, use the 'set' method.
+
+---------------------------------------
+
+*setlook <look type>,<look value>;
+*changelook <look type>,<look value>;
+
+'setlook' will alter the look data for the invoking character. It is used
+mainly for changing the palette used on hair and clothes: you specify which look
+type you want to change, then the palette you want to use. Make sure you specify
+a palette number that exists/is usable by the client you use.
+'changelook' works the same, but is only client side (it doesn't save the look value).
+
+ // This will change your hair(6), so that it uses palette 8, what ever your
+ // palette 8 is, your hair will use that color
+
+ setlook 6,8;
+
+ // This will change your clothes(7), so they are using palette 1, whatever
+ // your palette 1 is, your clothes will then use that set of colors.
+
+ setlook 7,1;
+
+Here are the possible look types:
+
+ 0 - Base sprite
+ 1 - Hairstyle
+ 2 - Weapon
+ 3 - Head bottom
+ 4 - Head top
+ 5 - Head mid
+ 6 - Hair color
+ 7 - Clothes color
+ 8 - Shield
+ 9 - Shoes
+
+Whatever 'shoes' means is anyone's guess, ask Gravity - the client does nothing
+with this value. It still wants it from the server though, so it is kept, but
+normally doesn't do a thing.
+
+Only the look data for hairstyle, hair color and clothes color are saved to the
+char server's database and will persist. The rest freely change as the character
+puts on and removes equipment, changes maps, logs in and out and otherwise you
+should not expect to set them. In fact, messing with them is generally
+hazardous, do it at your own risk, it is not tested what will this actually do -
+it won't cause database corruption and probably won't cause a server crash, but
+it's easy to crash the client with just about anything unusual.
+
+However, it might be an easy way to quickly check for empty view IDs for
+sprites, which is essential for making custom headgear.
+
+Since a lot of people have different palettes for hair and clothes, it's
+impossible to tell you what all the color numbers are. If you want a serious
+example, there is a Stylist script inside the default rAthena installation that
+you can look at: 'npc/custom/stylist.txt'
+
+---------------------------------------
+
+*pushpc <direction>,<cells>;
+
+This command will push the currently attached player to given direction by given
+amount of square cells. Direction is the same as used when declaring NPCs, and
+can be specified by using one of the DIR_* constants (db/const.txt).
+
+The knock-back is not restricted by items or map flags, only obstacles are taken
+into account. If there is not enough space to perform the push (e.g. due to a
+wall), the character is pushed only up to the obstacle.
+
+ // pushes the character 5 cells in 3 o'clock direction from it's
+ // current position.
+ pushpc DIR_EAST, 5;
+
+---------------------------------------
+
+*get_revision()
+
+This command will return the SVN revision number that the server is
+currently running on.
+
+ if ( get_revision() >= 15000 )
+ mes "Welcome rAthena!";
+
+---------------------------------------
+\\
+4,1.- Item-related commands
+\\
+---------------------------------------
+
+*getitem <item id>,<amount>{,<account ID>};
+*getitem "<item name>",<amount>{,<account ID>};
+
+This command will give a specific amount of specified items to the target
+character. If the character is not online, nothing will happen.
+If <account ID> is not specified, items will be created in the invoking
+character inventory instead.
+
+In the first and most commonly used version of this command, items are
+referred to by their database ID number found inside 'db/(pre-)re/item_db.txt'.
+
+ getitem 502,10 // The person will receive 10 apples
+ getitem 617,1 // The person will receive 1 Old Violet Box
+
+Giving an item ID of -1 will give a specified number of random items from the
+list of those that fall out of Old Blue Box. Unlike in all other cases, these
+will be unidentified, if they turn out to be equipment. This is exactly what's
+written in the Old Blue Box's item script.
+
+Other negative IDs also correspond to other random item generating item tables:
+
+Giving an item ID of -2 will produce the effects of Old Violet Box.
+Giving an item ID of -3 will produce the effects of Old Card Album.
+Giving an item ID of -4 will produce the effects of Gift Box.
+Giving an item ID of -5 will produce the effects of Worn Out Scroll, which, in
+current SVN, drops only Jellopies anyway.
+
+This transaction is logged if the log script generated transactions option is
+enabled.
+
+You may also create an item by it's name in the 'english name' field in the
+item database:
+
+ getitem "RED_POTION",10;
+
+Which will do what you'd expect. If it can't find that name in the database,
+apples will be created anyway. It is often a VERY GOOD IDEA to use it like this.
+
+This is used in pretty much all NPC scripts that have to do with items and
+quite a few item scripts. For more examples check just about any official script.
+
+---------------------------------------
+
+*getitem2 <item id>,<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>};
+*getitem2 "<item name>",<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>};
+
+This command will give an amount of specified items to the invoking character.
+If an optional account ID is specified, and the target character is currently
+online, items will be created in their inventory instead. If they are not
+online, nothing will happen. It works essentially the same as 'getitem' (it even
+works for negative ID numbers the same way) but is a lot more flexible.
+
+Those parameters that are different from 'getitem' are:
+
+identify - Whether you want the item to be identified (1) or not (0).
+refine - For how many pluses will it be refined.
+ It will not let you refine an item higher than the max refine.
+attribute - Whether the item is broken (1) or not (0).
+card1,2,3,4 - If you want a card compound to it, place the card ID number into
+ the specific card slot.
+
+Card1-card4 values are also used to store name information for named items, as
+well as the elemental property of weapons and armor. You can create a named item
+in this manner, however, if you just need a named piece of standard equipment,
+it is much easier to the 'getnameditem' function instead.
+
+You will need to keep these values if you want to destroy and then perfectly
+recreate a named item, for this see 'getinventorylist'.
+
+If you still want to try creating a named item with this command because
+'getnameditem' won't do it for you cause it's too limited, you can do it like
+this. Careful, minor magic ahead.
+
+ // First, let's get an ID of a character who's name will be on the item.
+ // Only an existing character's name may be there.
+ // Let's assume our character is 'Adam' and find his ID.
+
+ set @charid,getcharid(0,"Adam");
+
+ // Now we split the character ID number into two portions with a binary
+ // shift operation. If you don't understand what this does, just copy it.
+
+ set @card3, @charid & 65535;
+ set @card4, @charid >> 16;
+
+ // If you're inscribing non-equipment, @card1 must be 254.
+ // Arrows are also not equipment. :)
+ set @card1,254;
+
+ // For named equipment, card2 means the Star Crumbs and elemental
+ // crystals used to make this equipment. For everything else, it's 0.
+
+ set @card2,0;
+
+ // Now, let's give the character who invoked the script some
+ // Adam's Apples:
+
+ getitem2 512,1,1,0,0,@card1,@card2,@card3,@card4;
+
+This wasn't tested with all possible items, so I can't give any promises,
+experiment first before relying on it.
+
+To create equipment, continue this example it like this:
+
+ // We've already have card3 and card4 loaded with correct
+ // values so we'll just set up card1 and card2 with data
+ // for an Ice Stiletto.
+
+ // If you're inscribing equipment, @card1 must be 255.
+ set @card1,255;
+
+ // That's the number of star crumbs in a weapon.
+ set @sc,2;
+
+ // That's the number of elemental property of the weapon.
+ set @ele,1;
+
+ // And that's the wacky formula that makes them into
+ // a single number.
+ set @card2,@ele+((@sc*5)<<8);
+
+ // That will make us an Adam's +2 VVS Ice Stiletto:
+
+ getitem2 1216,1,1,2,0,@card1,@card2,@card3,@card4;
+
+Experiment with the number of star crumbs - I'm not certain just how much will
+work most and what it depends on. The valid element numbers are:
+
+ 1 - Ice, 2 - Earth 3 - Fire 4 - Wind.
+
+You can, apparently, even create duplicates of the same pet egg with this
+command, creating a pet which is the same, but simultaneously exists in two
+eggs, and may hatch from either, although, I'm not sure what kind of a mess will
+this really cause.
+
+---------------------------------------
+
+*getnameditem <item id>,<character name|character ID>;
+*getnameditem "<item name>",<character name|character ID>;
+
+Create an item signed with the given character's name.
+
+The command returns 1 when the item is created successfully, or 0 if it fails.
+Failure occurs when:
+- There is no player attached.
+- Item name or ID is not valid.
+- The given character ID/name is offline.
+
+Example:
+
+//This will give the currently attached player a Aaron's Apple (if Aaron is online).
+ getnameditem "Apple","Aaron";
+
+//Self-explanatory (I hope).
+ if (getnameitem("Apple","Aaron")) {
+ mes "You now have a Aaron's Apple!";
+ }
+
+---------------------------------------
+
+*rentitem <item id>,<time>;
+*rentitem "<item name>",<time>;
+
+Creates a rental item in the attached character's inventory. The item will expire
+in <time> seconds and be automatically deleted. When receiving a rental item,
+the character will receive a message in their chat window. The character will
+also receive warning messages in their chat window before the item disappears.
+
+This command can not be used to rent stackable items. Rental items cannot be
+dropped, traded, sold to NPCs, or placed in guild storage. (i.e. trade mask 75)
+Note: 'delitem' in an NPC script can still remove rental items.
+
+---------------------------------------
+
+*makeitem <item id>,<amount>,"<map name>",<X>,<Y>;
+*makeitem "<item name>",<amount>,"<map name>",<X>,<Y>;
+
+This command will create an item lying around on a specified map in the
+specified location.
+
+ itemid - Found in 'db/(pre-)re/item_db.txt'
+ amount - Amount you want produced
+ map name - The map name
+ X - The X coordinate
+ Y - The Y coordinate.
+
+This item will still disappear just like any other dropped item. Like 'getitem',
+it also accepts an 'english name' field from the database and creates apples if
+the name isn't found.
+If the map name is given as "this", the map the invoking character is on will be used.
+
+---------------------------------------
+
+*cleanarea "<map name>",<x1>,<y1>,<x2>,<y2>;
+*cleanmap "<map name>";
+
+These commands will clear all items lying on the ground on the specified map, either
+within the x1/y1-x2/y2 rectangle or across the entire map.
+
+---------------------------------------
+
+*searchitem <array name>,"<item name>";
+
+This command will fill the given array with the ID of items whose name matches
+the given one. It returns the number of items found. For performance reasons,
+the results array is limited to 10 items.
+
+ mes "What item are you looking for?";
+ input @name$;
+ set @qty, searchitem(@matches[0],@name$);
+ mes "I found "+@qty+" items:";
+ for (set @i, 0; @i < @qty; set @i, @i+1)
+ //Display name (eg: "Apple[0]")
+ mes getitemname(@matches[@i])+"["+getitemslots(@matches[@i])+"]";
+
+---------------------------------------
+
+*delitem <item id>,<amount>{,<account ID>};
+*delitem "<item name>",<amount>{,<account ID>};
+
+This command will take a specified amount of items from the invoking/target character.
+As all the item commands, this one uses the ID of the item found inside
+'db/(pre-)re/item_db.txt'. The items are destroyed - there is no way an NPC can simply
+own items and have an inventory of them, other as by destroying and recreating
+them when needed.
+
+ delitem 502,10 // The person will lose 10 apples
+ delitem 617,1 // The person will lose 1 Old Violet Box
+
+It is always a good idea to check if the player actually has the items before you delete them.
+If you try to delete more items that the player has, the player will lose the ones he/she has
+and the script will be terminated with an error.
+
+Like 'getitem' this command will also accept an 'english name' field from the
+database. If the name is not found, nothing will be deleted.
+
+---------------------------------------
+
+*delitem2 <item id>,<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>};
+*delitem2 "<item name>",<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>};
+
+This command will take a specified amount of items from the invoking/target character.
+Check 'getitem2' to understand its expanded parameters.
+
+---------------------------------------
+
+*countitem(<item id>)
+*countitem("<item name>")
+
+This function will return the number of items for the specified item ID that the
+invoking character has in the inventory.
+
+ mes "[Item Checker]";
+ mes "Hmmm, it seems you have "+countitem(502)+" apples";
+ close;
+
+Like 'getitem', this function will also accept an 'english name' from the
+database as an argument.
+
+If you want to state the number at the end of a sentence, you can do it by
+adding up strings:
+
+ mes "[Item Checker]";
+ mes "Hmmm, the total number of apples you are holding is "+countitem("APPLE");
+ close;
+
+---------------------------------------
+
+*countitem2(<item id>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>)
+*countitem2("<item name>",<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>)
+
+Expanded version of 'countitem' function, used for created/carded/forged items.
+
+This function will return the number of items for the specified item ID and
+other parameters that the invoking character has in the inventory.
+Check 'getitem2' to understand the arguments of the function.
+
+---------------------------------------
+
+*groupranditem <group id>;
+
+Returns the item_id of a random item picked from the group specified. The
+different groups and their group number are specified in 'db/(pre-)re/item_group_db.txt'.
+
+When used in conjunction with other functions, you can get a random item. For
+example, for a random pet lure:
+
+getitem groupranditem(15),1;
+
+---------------------------------------
+
+*getrandgroupitem <group id>,<quantity>;
+
+Similar to the above example, this command allows players to obtain the specified
+quantity of a random item from the group "<group id>". The different groups and
+their group number are specified in db/(pre-)re/item_group_db.txt
+
+For example, obtaining three of the same random item from Old Blue Box:
+
+getrandgroupitem(1,3);
+
+---------------------------------------
+
+*enable_items;
+*disable_items;
+
+These commands enable item usage while an NPC is running. When enable_items is
+run, items can be used during scripts until disable_items is called.
+To avoid possible exploits, when enable_items is invoked, it will only enable
+item usage while running that script in particular. Note that if a different
+script also calls enable_items, it will override the last call (so you may
+want to call this command at the start of your script without assuming the
+effect is still in effect).
+
+---------------------------------------
+
+*itemskill <skill id>,<skill level>;
+*itemskill "<skill name>",<skill level>;
+
+This command meant for item scripts to replicate single-use skills in usable
+items. It will not work properly, if there is a visible dialog window or menu.
+If the skill is self or auto-targeting, it will be used immediately otherwise a
+target cursor is shown.
+
+// When Anodyne is used, it will cast Endure (8), Level 1, as if the actual
+// skill has been used from skill tree.
+605,Anodyne,Anodyne,11,2000,0,100,,,,,10477567,2,,,,,{ itemskill 8,1; },{}
+
+
+---------------------------------------
+
+*produce <item level>;
+
+This command will open a crafting window on the client connected to the invoking
+character. The 'item level' is a number which determines what kind of a crafting
+window will pop-up.
+
+You can see the full list of such item levels in 'db/produce_db.txt' which determines
+what can actually be produced. The window will not be empty only if the invoking
+character can actually produce the items of that type and has the appropriate raw
+materials in their inventory.
+
+The success rate to produce the item is the same as the success rate of the skill
+associated with the item level. If there is no skill id, the success rate will be 50%.
+
+Valid item levels are:
+
+ 1 - Level 1 Weapons
+ 2 - Level 2 Weapons
+ 3 - Level 3 Weapons
+ 21 - Blacksmith's Stones and Metals
+ 22 - Alchemist's Potions, Holy Water, Assassin Cross's Deadly Poison
+ 23 - Elemental Converters
+
+---------------------------------------
+
+*cooking <dish level>;
+
+This command will open a produce window on the client connected to the invoking
+character. The 'dish level' is the number which determines what kind of dish
+level you can produce. You can see the full list of dishes that can be produced in
+'db/produce_db.txt'.
+
+The window will be shown empty if the invoking character does not have enough of
+the required incredients to cook a dish.
+
+Valid dish levels are:
+
+11 - Level 1 Dish
+12 - Level 2 Dish
+13 - Level 3 Dish
+14 - Level 4 Dish
+15 - Level 5 Dish
+16 - Level 6 Dish
+17 - Level 7 Dish
+18 - Level 8 Dish
+19 - Level 9 Dish
+20 - Level 10 Dish
+
+Although it's required to set a dish level, it doesn't matter if you set it to 1
+and you want to cook a level 10 dish, as long as you got the required incredients
+to cook the dish the command works.
+
+---------------------------------------
+
+*makerune <% success bonus>;
+
+This command will open a rune crafting window on the client connected to the
+invoking character. Since this command is officially used in rune ores, a bonus
+success rate must be specified (which adds to the base formula).
+
+You can see the full list of runes that can be produced in 'db/produce_db.txt'.
+The window will not be empty only if the invoking character can actually produce
+a rune and has the appropriate raw materials in their inventory.
+
+---------------------------------------
+
+*successremovecards <equipment slot>;
+
+This command will remove all cards from the item found in the specified
+equipment slot of the invoking character, create new card items and give them to
+the character. If any cards were removed in this manner, it will also show a
+success effect.
+
+---------------------------------------
+
+*failedremovecards <equipment slot>,<type>;
+
+This command will remove all cards from the item found in the specified
+equipment slot of the invoking character. 'type' determines what happens to the
+item and the cards:
+
+ 0 - will destroy both the item and the cards.
+ 1 - will keep the item, but destroy the cards.
+ 2 - will keep the cards, but destroy the item.
+
+Whatever the type is, it will also show a failure effect on screen.
+
+---------------------------------------
+
+*repair <broken item number>;
+
+This command repairs a broken piece of equipment, using the same list of broken
+items as available through 'getbrokenid'.
+
+The official scripts seem to use the repair command as a function instead:
+'repair(<number>)' but it returns nothing on the stack. Probably only Valaris,
+who made it, can answer why is it so.
+
+---------------------------------------
+
+*repairall;
+
+This command repairs all broken equipment in the attached player's inventory.
+A repair effect will be shown if any items are repaired, else the command will
+end silently.
+
+---------------------------------------
+
+*successrefitem <equipment slot>;
+
+This command will refine an item in the specified equipment slot of the invoking
+character by +1. For a list of equipment slots see 'getequipid'. This command
+will not only add the +1, but also display a 'refine success' effect on the
+character and put appropriate messages into their chat window. It will also give
+the character fame points if a weapon reached +10 this way, even though these
+will only take effect for blacksmith who will later forge a weapon.
+
+The official scripts seems to use the 'successrefitem' command as a function
+instead: 'successrefitem(<number>)' but it returns nothing on the stack.
+This is since jAthena, so probably nobody knows for sure why is it so.
+
+---------------------------------------
+
+*failedrefitem <equipment slot>;
+
+This command will fail to refine an item in the specified equipment slot of the
+invoking character. The item will be destroyed. This will also display a 'refine
+failure' effect on the character and put appropriate messages into their chat
+window.
+
+The official scripts seems to use the 'failedrefitem' command as a function
+instead: 'failedrefitem(<number>)' but it returns nothing on the stack. This is
+since jAthena, so probably nobody knows for sure why is it so.
+
+---------------------------------------
+
+*downrefitem <equipment slot>;
+
+This command will downgrade an item by - 1 in the specified equipment slot of the
+invoking character. So the item will not be destroyed unlike in the failedrefitem script command.
+This will also display a 'refine failure' effect on the character and put appropriate
+messages into their chat window.
+
+The official scripts seems to use the 'downrefitem' command as a function
+instead: 'downrefitem(<number>)' but it returns nothing on the stack. This is
+since jAthena, so probably nobody knows for sure why is it so.
+
+---------------------------------------
+
+*unequip <equipment slot>;
+
+This command will unequip whatever is currently equipped in the invoking
+character's specified equipment slot. For a full list of possible equipment
+slots see 'getequipid'.
+
+If an item occupies several equipment slots, it will get unequipped from all of
+them.
+
+---------------------------------------
+
+*clearitem;
+
+This command will destroy all items the invoking character has in their
+inventory (including equipped items). It will not affect anything else, like
+storage or cart.
+
+---------------------------------------
+
+*equip <item id>;
+*autoEquip <item id>,<option>;
+
+These commands are to equip a equipment on the attached character.
+The equip function will equip the item ID given when the player has
+this item in his/her inventory, while the autoequip function will
+equip the given item ID when this is looted. The option parameter of
+the autoequip is 1 or 0, 1 to turn it on, and 0 to turn it off.
+
+Examples:
+
+//This will equip a 1104 (falchion) on the character if this is in the inventory.
+ equip 1104;
+
+//The invoked character will now automatically equip a falchion when it's looted.
+ autoequip 1104,1;
+
+//The invoked character will no longer automatically equip a falchion.
+ autoequip 1104,0;
+
+---------------------------------------
+
+*buyingstore <slots>;
+
+Invokes buying store preparation window like the skill 'Open Buying Store',
+without the item requirement. Amount of slots is limited by the server to
+a maximum of 5 slots by default.
+
+Example:
+
+ // Gives the player opportunity to buy 4 different kinds of items.
+ buyingstore 4;
+
+---------------------------------------
+
+*searchstores <uses>,<effect>;
+
+Invokes the store search window, which allows to search for both vending
+and buying stores. Parameter uses indicates, how many searches can be
+started, before the window has to be reopened. Effect value affects,
+what happens, when a result item is double-clicked and can be one of the
+following:
+
+ 0 = Shows the store's position on the mini-map and highlights the
+ shop sign with yellow color, when the store is on same map
+ as the invoking player.
+ 1 = Directly opens the shop, regardless of distance.
+
+Example:
+
+ // Item Universal_Catalog_Gold (10 uses, effect: open shop)
+ searchstores 10,1;
+
+---------------------------------------
+//
+4,1.- End of item-related commands
+//
+---------------------------------------
+
+*openstorage;
+
+This will open character's Kafra storage window on the client connected to the
+invoking character. It can be used from any kind of NPC or item script, not just
+limited to Kafra Staff.
+
+The storage window opens regardless of whether there are open NPC dialogs or
+not, but it is preferred to close the dialog before displaying the storage
+window, to avoid any disruption when both windows overlap.
+
+ mes "I will now open your stash for you";
+ close2;
+ openstorage;
+ end;
+
+---------------------------------------
+
+*openmail;
+
+This will open a character's Mail window on the client connected to the
+invoking character.
+
+ mes "Close this window to open your mail inbox.";
+ close2;
+ openmail;
+ end;
+
+---------------------------------------
+
+*openauction;
+
+This will open the Auction window on the client connected to the invoking character.
+
+ mes "Close this window to open the Auction window.";
+ close2;
+ openauction;
+ end;
+
+---------------------------------------
+\\
+4,2.- Guild-related commands
+\\
+---------------------------------------
+
+*guildopenstorage()
+
+This function works the same as 'openstorage' but will open a guild storage
+window instead for the guild storage of the guild the invoking character belongs
+to. This is a function because it returns a value - 0 if the guild storage was
+opened successfully and 1 if it wasn't. (Notice, it's a ZERO upon success.)
+Since guild storage is only accessible to one character at one time, it may fail
+if another character is accessing the guild storage at the same time.
+
+This will also fail and return 2 if the character does not belong to any guild.
+
+---------------------------------------
+
+*guildchangegm(<guild id>,<new master's name>)
+
+This function will change the Guild Master of a guild. The ID is the guild's
+id, and the new guild master's name must be passed.
+
+Returns 1 on success, 0 otherwise.
+
+---------------------------------------
+
+*guildgetexp <amount>;
+
+This will give the specified amount of guild experience points to the guild the
+invoking character belongs to. It will silently fail if they do not belong to
+any guild.
+
+---------------------------------------
+
+*guildskill <skill id>,<level>
+*guildskill "<skill name>",<level>
+
+This command will bump up the specified guild skill by the specified number of
+levels. This refers to the invoking character and will only work if the invoking
+character is a member of a guild AND it's guild master, otherwise no failure
+message will be given and no error will occur, but nothing will happen - same
+about the guild skill trying to exceed the possible maximum. The full list of
+guild skills is available in 'db/(pre-)re/skill_db.txt', these are all the GD_ skills at
+the end.
+
+The flag parameter is currently not functional and it's a mystery of what it
+would actually do. (Though probably, like for character skills, it would allow
+temporary bumping.) Using this command will bump the guild skill up permanently.
+
+// This would give your character's guild one level of Approval (GD_APPROVAL ID
+// 10000). Notice that if you try to add two levels of Approval, or add
+// Approval when the guild already has it, it will only have one level of
+// Approval afterwards.
+ guildskill 10000,1,0;
+
+You might want to make a quest for getting a certain guild skill, make it hard
+enough that all the guild needs to help or something. Doing this for the Glory
+of the Guild skill, which allows your guild to use an emblem, is a good idea for
+a fun quest. (Wasting a level point on that is really annoying :D)
+
+---------------------------------------
+//
+4,2 End of guild-related commands.
+//
+---------------------------------------
+
+*resetlvl <action type>;
+
+This is a character reset command, meant mostly for rebirth script supporting
+Advanced jobs, which will reset the invoking character's stats and level
+depending on the action type given. Valid action types are:
+
+ 1 - Base level 1, Job level 1, 0 skill points, 0 base exp, 0 job exp, wipes the
+ status effects (only the ones settable by 'setoption'), sets all stats to 1.
+ If the new job is 'Novice High', give 100 status points, give First Aid and
+ Play Dead skills.
+ 2 - Base level 1, Job level 1, 0 skill points, 0 base exp, 0 job exp.
+ Skills and attribute values are not altered.
+ 3 - Base level 1, base exp 0. Nothing else is changed.
+ 4 - Job level 1, job exp 0. Nothing else is changed.
+
+In all cases everything the character has on will be unequipped.
+
+Even though it doesn't return a value, it is used as a function in the official
+rebirth scripts. Ask AppleGirl why.
+
+---------------------------------------
+
+*resetstatus;
+
+This is a character reset command, which will reset the stats on the invoking
+character and give back all the stat points used to raise them previously.
+Nothing will happen to any other numbers about the character.
+
+Used in reset NPC's (duh!)
+
+---------------------------------------
+
+*resetskill;
+
+This command takes off all the skill points on the invoking character, so they
+only have Basic Skill blanked out (lvl 0) left, and returns the points for them
+to spend again. Nothing else will change but the skills. Quest skills will also
+reset if 'quest_skill_reset' option is set to Yes in 'battle_athena.conf'. If
+the 'quest_skill_learn' option is set in there, the points in the quest skills
+will also count towards the total.
+
+Used in reset NPC's (duh!)
+
+---------------------------------------
+
+*sc_start <effect type>,<ticks>,<extra argument>{,<GID>};
+*sc_start2 <effect type>,<ticks>,<extra argument>,<percent chance>{,<GID>};
+*sc_start4 <effect type>,<ticks>,<value 1>,<value 2>,<value 3>,<value 4>{,<GID>};
+*sc_end <effect type>{,<GID>};
+
+These command bestow a status effect on the invoking character. This command is
+used a lot in the item scripts.
+
+ // This would poison them for 10 min
+ sc_start SC_Poison,600000,0;
+
+Effect type is a number of effect, 'db/const.txt' lists the common (mostly
+negative) status effect types as constants, starting with 'SC_'. You can also
+use this to give someone an effect of a player-cast spell:
+
+ // This will bless someone as if with Bless 10:
+ sc_start 10,240000,10;
+
+Extra argument's meaning differs depending on the effect type, for most effects
+caused by a player skill the extra argument means the level of the skill that
+would have been used to create that effect, for others it might have no meaning
+whatsoever. You can actually bless someone with a 0 bless spell level this way,
+which is fun, but weird.
+
+The GID, if given, will cause the status effect to appear on a
+specified character, instead of the one attached to the running script. This has
+not been properly tested.
+
+'sc_start2' is perfectly equivalent, but unlike 'sc_start', a status change
+effect will only occur with a specified percentage chance. 10000 given as the
+chance is equivalent to a 100% chance, 0 is a zero.
+
+'sc_start4' is just like sc_start, however it takes four parameters for the
+status change instead of one. What these values are depends on the status
+change in question. For example, elemental armor defense takes the following
+four values:
+- val1 is the first element, val2 is the resistance to the element val1.
+- val3 is the second element, val4 is the resistance to said element.
+eg: sc_start4 SC_DefEle,60000,Ele_Fire,20,Ele_Water,-15;
+
+'sc_end' will remove a specified status effect. If SC_All is used (-1), it will
+do a complete removal of all statuses (although permanent ones will re-apply).
+
+You can see the full list of status effects caused by skills in
+'src/map/status.h' - they are currently not fully documented, but most of that
+should be rather obvious.
+
+---------------------------------------
+
+*getstatus <effect type>{,<type>};
+
+Retrieve information about a specific status effect when called. Depending on <type>
+specified the function will return different information.
+
+Possible <type> values:
+ - 0 or undefined: whether the status is active
+ - 1: the val1 of the status
+ - 2: the val2 of the status
+ - 3: the val3 of the status
+ - 4: the val4 of the status
+ - 5: the amount of time in milliseconds that the status has remaining
+
+If <type> is not defined or is set to 0, then the script function will either
+return 1 if the status is active, or 0 if the status is not active. If the status
+is not active when any of the <type> fields are provided, this script function
+will always return 0.
+
+---------------------------------------
+
+*skilleffect <skill id>,<number>;
+*skilleffect "<skill name>",<number>;
+
+This command displays visual and aural effects of given skill on currently
+attached character. The number parameter is for skill whose visual effect
+involves displaying of a number (healing or damaging). Note, that this command
+will not actually use the skill, it is intended for scripts, which simulate
+skill usage by the NPC, such as buffs, by setting appropriate status and
+displaying the skill's effect.
+
+ mes "Be blessed!";
+ // Heal of 2000 HP
+ heal 2000,0;
+ skilleffect 28,2000;
+ // Blessing Level 10
+ sc_start 10,240000,10;
+ skilleffect 34,0;
+ // Increase AGI Level 5
+ sc_start 12,140000,5;
+ skilleffect 29,0;
+
+This will heal the character with 2000 HP, buff it with Blessing Lv 10 and
+Increase AGI Lv 5, and display appropriate effects.
+
+---------------------------------------
+
+*npcskilleffect <skill id>,<number>,<x>,<y>;
+*npcskilleffect "<skill name>",<number>,<x>,<y>;
+
+This command behaves identically to 'skilleffect', however, the effect will not
+be centered on the invoking character's sprite, nor on the NPC sprite, if any,
+but will be centered at map coordinates given on the same map as the invoking
+character.
+
+---------------------------------------
+
+*specialeffect <effect number>{,<send_target>{,"<NPC Name>"}};
+
+This command will display special effect with the given number, centered on the
+specified NPCs coordinates, if any. For a full list of special effect numbers
+known see 'doc/effect_list.txt'. Some effect numbers are known not to work in
+some client releases. (Notably, rain is absent from any client executables
+released after April 2005.)
+
+<NPC name> parameter will display <effect number> on another NPC. If the NPC
+specified does not exist, the command will do nothing. When specifying an NPC,
+<send_target> must be specified when specifying an <NPC Name>, specifying AREA
+will retain the default behavior of the command.
+
+ // this will make the NPC "John Doe#1"
+ // show the effect "EF_HIT1" specified by
+ // Jane Doe. I wonder what John did...
+ mes "[Jane Doe]";
+ mes "Well, I never!";
+ specialeffect EF_HIT1,AREA,"John Doe#1";
+ close;
+
+---------------------------------------
+
+*specialeffect2 <effect number>{,<send_target>{,"<Player Name>"}};
+
+This command behaves identically to the 'specialeffect', but the effect will be
+centered on the invoking character's sprite.
+
+<Player name> parameter will display <effect number> on another Player than the
+one currently attached to the script. Like with specialeffect, when specifying
+a player, <send_target> must be supplied, specifying AREA will retain the default
+behavior of the command.
+
+---------------------------------------
+
+*statusup <stat>;
+
+This command will bump a specified stat of the invoking character up by one
+permanently. Stats are to be given as number, but you can use these constants to
+replace them:
+
+bStr - Strength
+bVit - Vitality
+bInt - Intelligence
+bAgi - Agility
+bDex - Dexterity
+bLuk - Luck
+
+---------------------------------------
+
+*statusup2 <stat>,<amount>;
+
+This command will bump a specified stat of the invoking character up by the
+specified amount permanently. The amount can be negative. See 'statusup'.
+
+// This will decrease a character's Vit forever.
+ statusup bVit,-1;
+
+---------------------------------------
+
+*bonus <bonus type>,<val1>;
+*bonus2 <bonus type>,<val1>,<val2>;
+*bonus3 <bonus type>,<val1>,<val2>,<val3>;
+*bonus4 <bonus type>,<val1>,<val2>,<val3>,<val4>;
+*bonus5 <bonus type>,<val1>,<val2>,<val3>,<val4>,<val5>;
+
+These commands are meant to be used in item scripts. They will probably work
+outside item scripts, but the bonus will not persist for long. They, as
+expected, refer only to an invoking character.
+
+You can find the full list of possible bonuses and which command to use for each
+kind in 'doc/item_bonus.txt'.
+
+---------------------------------------
+
+*autobonus <bonus script>,<rate>,<duration>{,<flag>,{<other script>}};
+*autobonus2 <bonus script>,<rate>,<duration>{,<flag>,{<other script>}};
+*autobonus3 <bonus script>,<rate>,<duration>,<skill id>,{<other script>};
+*autobonus3 <bonus script>,<rate>,<duration>,"<skill name>",{<other script>};
+
+These commands are meant to be used in item scripts. They will probably work
+outside item scripts, but the bonus will not persist for long. They, as
+expected, refer only to an invoking character.
+
+What these commands do is 'attach' a script to the player which will get
+executed on attack (or when attacked in the case of autobonus2).
+
+Rate is the trigger rate of the script (1000 = 100%).
+
+Duration is the time that the bonus will last for since the script has triggered.
+
+Skill ID/skill name the skill which will be used as trigger to start the bonus. (autobonus3)
+
+The optional argument 'flag' is used to classify the type of attack where the script
+can trigger (it shares the same flags as the bAutoSpell bonus script):
+
+Range criteria:
+ BF_SHORT: Trigger on melee attack
+ BF_LONG: Trigger on ranged attack
+ Default: BF_SHORT+BF_LONG
+Attack type criteria:
+ BF_WEAPON: Trigger on weapon skills
+ BF_MAGIC: Trigger on magic skills
+ BF_MISC: Trigger on misc skills
+ Default: BF_WEAPON
+Skill criteria:
+ BF_NORMAL: Trigger on normal attacks
+ BF_SKILL: Trigger on skills
+ default: If the attack type is BF_WEAPON (only) BF_NORMAL is used,
+ otherwise BF_SKILL+BF_NORMAL is used.
+
+The difference between the optional argument 'other script' and the 'bonus script' is that,
+the former one triggers only when attacking(or attacked) and the latter one runs on
+status calculation as well, which makes sure, within the duration, the "bonus" that get
+lost on status calculation is restored. So, 'bonus script' is technically supposed to accept
+"bonus" command only. And we usually use 'other script' to show visual effects.
+
+In all cases, when the script triggers, the attached player will be the one
+who holds the bonus. There is currently no way of knowing within this script
+who was the other character (the attacker in autobonus2, or the target in
+autobonus and autobonus3).
+
+//Grants a 1% chance of starting the state "all stats +10" for 10 seconds when
+//using weapon or misc attacks (both melee and ranged skills) and shows a special
+//effect when the bonus is active.
+ autobonus "{ bonus bAllStats,10; }",10,10000,BF_WEAPON|BF_MISC,"{ specialeffect2 EF_FIRESPLASHHIT; }";
+
+---------------------------------------
+
+*skill <skill id>,<level>{,<flag>};
+*skill "<skill name>",<level>{,<flag>};
+*addtoskill <skill id>,<level>{,<flag>};
+*addtoskill "<skill name>",<level>{,<flag>};
+
+These commands will give the invoking character a specified skill. This is also
+used for item scripts.
+
+Level is obvious. Skill id is the ID number of the skill in question as per
+'db/(pre-)re/skill_db.txt'. It is not known for certain whether this can be used to give
+a character a monster's skill, but you're welcome to try with the numbers given
+in 'db/(pre-)re/mob_skill_db.txt'.
+
+Flag is 0 if the skill is given permanently (will get written with the character
+data) or 1 if it is temporary (will be lost eventually, this is meant for card
+item scripts usage.). The flag parameter is optional, and defaults to 1 in
+'skill' and to 2 in 'addtoskill'.
+
+Flag 2 means that the level parameter is to be interpreted as a stackable
+additional bonus to the skill level. If the character did not have that skill
+previously, they will now at 0+the level given.
+
+// This will permanently give the character Stone Throw (TF_THROWSTONE,152), at
+// level 1.
+ skill 152,1,0;
+
+---------------------------------------
+
+*nude;
+
+This command will unequip anything equipped on the invoking character.
+
+It is not required to do this when changing jobs since 'jobchange' will unequip
+everything not equippable by the new job class anyway.
+
+---------------------------------------
+
+*disguise <Monster ID>;
+*undisguise;
+
+This command disguises the current player with a monster sprite.
+The disguise lasts until 'undisguise' is issued or the player logs out.
+
+Example:
+
+disguise 1002; // Disguise character as a Poring.
+next;
+undisguise; // Return to normal character sprite.
+
+---------------------------------------
+\\
+4,3 Marriage-related commands
+\\
+---------------------------------------
+
+*marriage("<spouse name>");
+
+This function will marry two characters, the invoking character and the one
+referred to by name given, together, setting them up as each other's marriage
+partner. No second function call has to be issued (in current SVN at least) to
+make sure the marriage works both ways. The function returns 1 upon success, or
+0 if the marriage could not be completed, either because the other character
+wasn't found or because one of the two characters is already married.
+
+This will do nothing else for the marriage except setting up the spouse ID for
+both of these characters. No rings will be given and no effects will be shown.
+
+---------------------------------------
+
+*wedding;
+
+This command will call up wedding effects - the music and confetti - centered on
+the invoking character. Example can be found in the wedding script.
+
+---------------------------------------
+
+*divorce()
+
+This function will "un-marry" the invoking character from whoever they were
+married to. Both will no longer be each other's marriage partner, (at least in
+current SVN, which prevents the cases of multi-spouse problems). It will return
+1 upon success or 0 if the character was not married at all.
+
+This function will also destroy both wedding rings and send a message to both
+players, telling them they are now divorced.
+
+---------------------------------------
+//
+4,3.- End of marriage-related commands
+//
+---------------------------------------
+
+*pcfollow <id>,<target id>;
+*pcstopfollow <id>;
+
+Makes a character follow or stop following someone. This command does the same as the @follow command.
+The main difference is that @follow can use character names, and this commands needs the Account ID for the target.
+
+Examples:
+
+// This will make Aaron follow Bullah, when both of these characters are online.
+ PCFollow getCharID(3,"Aaron"),getCharID(3,"Bullah");
+
+// Makes Aaron stop following whoever he is following.
+ PCStopFollow getCharID(3,"Aaron");
+
+---------------------------------------
+
+*pcblockmove <id>,<option>;
+
+Prevents the given ID from moving when the option != 0, and 0 enables the ID to
+move again. The ID can either be the GID of a monster/NPC or account ID of a
+character, and will run for the attached player if zero is supplied.
+
+Examples:
+
+// Prevents the current char from moving away.
+ pcblockmove getcharid(3),1;
+
+// Enables the current char to move again.
+ pcblockmove getcharid(3),0;
+
+---------------------------------------
+
+==================================
+|5.- Mob / NPC -related commands.|
+==================================
+---------------------------------------
+
+*monster "<map name>",<x>,<y>,"<name to show>",<mob id>,<amount>{,"<event label>",<size>,<ai>};
+*areamonster "<map name>",<x1>,<y1>,<x2>,<y2>,"<name to show>",<mob id>,<amount>{,"<event label>",<size>,<ai>};
+
+This command will spawn a monster on the specified coordinates on the specified
+map. If the script is invoked by a character, a special map name, "this", will
+be recognized to mean the name of the map the invoking character is located at.
+This command works fine in the item scripts.
+
+The same command arguments mean the same things as described above in the
+beginning of this document when talking about permanent monster spawns. Monsters
+spawned in this manner will not respawn upon being killed.
+
+Unlike the permanent monster spawns, if the mob id is -1, a random monster will
+be picked from the entire database according to the rules configured in the
+server for dead branches. This will work for all other kinds of non-permanent
+monster spawns.
+
+The only very special thing about this command is an event label, which is an
+optional parameter. This label is written like '<NPC object name>::<label name>'
+and upon the monster being killed, it will execute the script inside of the
+specified NPC object starting from the label given. The RID of the player
+attached at this execution will be the RID of the killing character.
+
+<size> can be:
+ 0 = medium (default)
+ 1 = small
+ 2 = big
+
+<ai> can be:
+ 0 = none (default)
+ 1 = attack/friendly
+ 2 = sphere (Alchemist skill)
+ 3 = flora (Alchemist skill)
+ 4 = zanzou (Kagerou/Oboro skill)
+
+ monster "place",60,100,"Poring",1002,1,"NPCNAME::OnLabel";
+
+The coordinates of 0,0 will spawn the monster on a random place on the map.
+
+The 'areamonster' command works much like the 'monster' command and is not
+significantly different, but spawns the monsters within a square defined by
+x1/y1-x2/y2.
+
+Simple monster killing script:
+
+ <Normal NPC object definition. Let's assume you called him NPCNAME.>
+ mes "[Summon Man]";
+ mes "Want to start the kill?";
+ next;
+ menu "Yes",L_Yes,"No",-;
+ mes "[Summon Man]";
+ mes "Come back later";
+ close;
+ L_Yes:
+ monster "prontera",0,0,"Quest Poring",1002,10,"NPCNAME::OnPoringKilled";
+ // By using 0,0 it will spawn them in a random place.
+ mes "[Summon Man]";
+ mes "Now go and kill all the Poring I summoned";
+ // He summoned ten.
+ close;
+ OnPoringKilled:
+ set $PoringKilled,$PoringKilled+1;
+ if ($PoringKilled==10) goto L_AllDead;
+ end;
+ L_AllDead:
+ announce "Summon Man: Well done all the poring are dead",3;
+ set $PoringKilled,0;
+ end;
+
+For more good examples see just about any official 2-1 or 2-2 job quest script.
+
+---------------------------------------
+
+*areamobuseskill "<map name>",<x>,<y>,<range>,<mob id>,<skill id>,<skill level>,<cast time>,<cancelable>,<emotion>,<target type>;
+*areamobuseskill "<map name>",<x>,<y>,<range>,<mob id>,"<skill name>",<skill level>,<cast time>,<cancelable>,<emotion>,<target type>;
+
+This command will make all monsters of the specified mob ID in the specified
+area use the specified skill. Map name, x, and y define the center of the area,
+which extending <range> cells in each direction (ex: a range of 3 would create
+a 7x7 square). The skill can be specified by skill ID or name. <cast time> is in
+milliseconds (1000 = 1 second), and the rest should be self-explanatory.
+
+<target type> can be:
+ 0 = self
+ 1 = the mob's current target
+ 2 = the mob's master
+ 3 = random target
+
+Example:
+
+ // spawn 1 Shining Plant in the 5x5 area centered on (155,188)
+ areamonster "prontera",153,186,157,190,"Shining Plant",1083,1;
+ // make the plant cast level 10 Cold Bolt on a random target
+ areamobuseskill "prontera",155,188,2,1083,"MG_COLDBOLT",10,3000,1,e_gg,3;
+
+---------------------------------------
+
+*killmonster "<map name>","<event label>"{,<type>};
+
+This command will kill all monsters that were spawned with 'monster' or
+'addmonster' and have a specified event label attached to them. Commonly used to
+get rid of remaining quest monsters once the quest is complete.
+
+If the label is given as "All", all monsters which have their respawn times set
+to -1 (like all the monsters summoned with 'monster' or 'areamonster' script
+command, and all monsters summoned with GM commands, but no other ones - that
+is, all non-permanent monsters) on the specified map will be killed regardless
+of the event label value.
+
+As of r12876 killmonster now supports an optional argument type. Using 1 for type
+will make the command fire "OnMyMobDead" events from any monsters that do die
+as a result of this command.
+
+---------------------------------------
+
+*killmonsterall "<map name>"{,<type>};
+
+This command will kill all monsters on a specified map name, regardless of how
+they were spawned or what they are. As of r12873, The behavior has changed slightly.
+In light of a label behavior fix for mob spawning commands that will now allow the label to
+trigger when there is no player, killmonsterall has also been modified to support this.
+
+Using this the normal/old way means labels don't trigger when a player didn't
+attack/kill a monster. This is because it breaks compatibility with older scripts if
+forced to use the new method. However, if you wish to use the new label type with this
+command, simply use 1 for type. Any other number won't be recognized.
+
+---------------------------------------
+
+*strmobinfo(<type>,<monster id>);
+
+This function will return information about a monster record in the database, as
+per 'db/(pre-)re/mob_db.txt'. Type is the kind of information returned. Valid types are:
+
+ 1 - 'english name' field in the database, a string.
+ 2 - 'japanese name' field in the database, a string.
+ All other returned values are numbers:
+ 3 - Level.
+ 4 - Maximum HP.
+ 5 - Maximum SP.
+ 6 - Experience reward.
+ 7 - Job experience reward.
+
+---------------------------------------
+
+*mobcount("<map name>","<event label>")
+
+This function will count all the monsters on the specified map that have a given
+event label and return the number or 0 if it can't find any. Naturally, only
+monsters spawned with 'monster' and 'areamonster' script commands can have non-empty
+event label.
+If you pass this function an empty string for the event label, it will return
+the total count of monster without event label, including permanently spawning monsters.
+With the dynamic mobs system enabled, where mobs are not kept
+in memory for maps with no actual people playing on them, this will return a 0
+for any such map.
+If the event label is given as "all", all monsters will be counted, regardless of
+having any event label attached.
+
+If the map name is given as "this", the map the invoking character is on will
+be used. If the map is not found, or the invoker is not a character while the map
+is "this", it will return -1.
+
+---------------------------------------
+
+*clone "<map name>",<x>,<y>,"<event>",<char id>{,<master_id>{,<mode>{,<flag>,<duration>}}}
+
+This command creates a monster which is a copy of another player. The first
+four arguments serve the same purpose as in the monster script command, The
+<char id> is the character id of the player to clone (player must be online).
+If <master id> is given, the clone will be a 'slave/minion' of it. Master_id
+must be a character id of another online player.
+
+The mode can be specified to determine the behavior of the clone, it's
+values are the same as the ones used for the mode field in the mob_db. The
+default mode is aggressive, assists, can move, can attack.
+
+Flag can be either zero or one currently. If zero, the clone is a normal
+monster that'll target players, if one, it is considered a summoned monster,
+and as such, it'll target other monsters. Defaults to zero.
+
+The duration specifies how long the clone will live before it is auto-removed.
+Specified in seconds, defaults to no limit (zero).
+
+Returned value is the monster ID of the spawned clone. If command fails,
+returned value is zero.
+
+---------------------------------------
+
+*summon "Monster name",<monster id>{,<Time Out>{,"event label"}};
+
+This command will summon a monster. (see also 'monster') Unlike monsters spawned
+with other commands, this one will set up the monster to fight to protect the
+invoking character. Monster name and mob id obey the same rules as the one given
+at the beginning of this document for permanent monster spawns with the
+exceptions mentioned when describing 'monster' command.
+
+The effect for the skill 'Call Homunculus' will be displayed centered on the
+invoking character.
+
+Timeout is the time in milliseconds the summon lives, and is set default
+to 60000 (1 minute). Note that also the value 0 will set the timer to default,
+and it is not possible to create a spawn that lasts forever.
+If an event label is given, upon the monster being killed, the event label will
+run as if by 'donpcevent'.
+
+// Will summon a dead branch-style monster to fight for the character.
+summon "--ja--",-1;
+
+---------------------------------------
+
+*homevolution;
+
+This command will try to evolve the current player's homunculus.
+If it doesn't work, the /swt emotion is shown.
+
+To evolve a homunculus, the invoking player must have a homunculus,
+the homunculus must not be the last evolution and
+the homunculus must have above 91000 intimacy with its owner.
+
+---------------------------------------
+
+*hommutate {<ID>};
+
+This command will try to evolve the current player's homunculus into the
+new Homunculus S. If it doesn't work, the /swt emotion is shown.
+
+To mutate a homunculus, the invoking player must have an evolved
+homunculus and it must be at least level 99.
+
+If the optional parameter <ID> is set, the invoking player's homunculus will
+change into the given homunculus ID. Otherwise, a random Homunculus S
+will be chosen.
+
+---------------------------------------
+
+*unitwalk <GID>,<x>,<y>;
+*unitwalk <GID>,<mapid>;
+
+This is one command, but can be used in two ways. If only the first argument is given,
+the unit whose GID is given will start walking towards the map with the given mapid
+(we believe these are the map-indexes found in db/map_index.txt).
+
+When 2 arguments are passed, the given unit will walk to the given x,y coordinates on
+the map where the unit currently is.
+
+Examples:
+
+//Will move/walk the poring we made to the coordinates 150,150
+ unitwalk .GID,150,150;
+
+//Will move the poring towards alberta (if my assumed map-indexes are correct).
+ unitwalk .GID,3;
+
+---------------------------------------
+
+*unitkill <GID>;
+*unitwarp <GID>,<Mapname>,<x>,<y>;
+*unitattack <GID>,<Target ID>;
+*unitstop <GID>;
+*unittalk <GID>,<Text>;
+*unitemote <GID>,<Emote>;
+
+Okay, these commands should be fairly self explaining.
+For the emotions, you can look in db/const.txt for prefixes with e_
+PS: unitwarp supports a <GID> of zero, which causes the executor of the script to be affected. This can be used with OnTouchNPC to warp monsters:
+
+OnTouchNPC:
+ unitwarp 0,"this",-1,-1;
+
+---------------------------------------
+
+*disablenpc "<NPC object name>";
+*enablenpc "<NPC object name>";
+
+These two commands will disable and enable, respectively, an NPC object
+specified by name. The disabled NPC will disappear from sight and will no longer
+be triggerable in the normal way. It is not clear whether it will still be
+accessible through 'donpcevent' and other triggering commands, but it probably
+will be. You can disable even warp NPCs if you know their object names, which is
+an easy way to make a map only accessible through walking half the time. Then
+you 'enablenpc' them back.
+
+You can also use these commands to create the illusion of an NPC switching
+between several locations, which is often better than actually moving the NPC -
+create one NPC object with a visible and a hidden part to their name, make a few
+copies, and then disable all except one.
+
+---------------------------------------
+
+*hideonnpc "<NPC object name>";
+*hideoffnpc "<NPC object name>";
+
+These commands will make the NPC object specified display as hidden/visible,
+even though not actually disabled per se. Hidden as in thief Hide skill, but
+unfortunately, not detectable by Ruwach or Sight.
+
+As they are now, these commands are pointless, it is suggested to use
+'disablenpc'/'enablenpc', because these two commands actually unload the NPC
+sprite location and other accompanying data from memory when it is not used.
+However, you can use these for some quest ideas (such as cloaking NPCs talking
+while hidden then revealing.... you can wonder around =P
+
+---------------------------------------
+
+*doevent "<NPC object name>::<event label>";
+
+This command will start a new execution thread in a specified NPC object at the
+specified label. The execution of the script running this command will not stop,
+and the event called by the 'doevent' command will not run until the invoking
+script has terminated. No parameters may be passed with a doevent call.
+
+The script of the NPC object invoked in this manner will run as if it's been
+invoked by the RID that was active in the script that issued a 'doevent'. As
+such, the command will not work if an RID is not attached.
+
+ place,100,100,1%TAB%script%TAB%NPC%TAB%53,{
+ mes "This is what you will see when you click me";
+ close;
+ OnLabel:
+ mes "This is what you will see if the doevent is activated";
+ close;
+ }
+
+ ....
+
+ doevent "NPC::OnLabel";
+
+---------------------------------------
+
+*donpcevent "<NPC object name>::<event label>";
+
+This command invokes the event label code within an another NPC or NPCs. It
+starts a separate instance of execution, and the invoking NPC will resume
+execution its immediately.
+
+If the supplied event label has the form "NpcName::OnLabel", then only given
+NPC's event label will be invoked (much like 'goto' into another NPC). If the
+form is "::OnLabel" (NPC name omitted), the event code of all NPCs with given
+label will be invoked, one after another. In both cases the invoked script
+will run without an attached RID, whether or not the invoking script was
+attached to a player. The event label name is required to start with "On".
+
+This command can be used to make other NPCs act, as if they were responding to
+the invoking NPC's actions, such as using an emotion or talking.
+
+ place,100,100,1%TAB%script%TAB%NPC%TAB%53,{
+ mes "Hey NPC2 copy what I do";
+ close2;
+ set .@emote, rand(1,30);
+ donpcevent "NPC2::OnEmote";
+ OnEmote:
+ emotion .@emote;
+ end;
+ }
+
+ place,102,100,1%TAB%script%TAB%NPC2%TAB%53,{
+ mes "Hey NPC copy what I do";
+ close2;
+ set .@emote, rand(1,30);
+ donpcevent "NPC::OnEmote";
+ OnEmote:
+ emotion .@emote;
+ end;
+ }
+
+Whichever of the both NPCs is talked to, both will show a random emotion at the
+same time.
+
+As of r16564, command now returns 1 or 0 on success and failure.
+A debug message also shows on the console when no events are triggered.
+
+---------------------------------------
+
+*cmdothernpc "<npc name>","<command>";
+
+This is simply "donpcevent <npc name>::OnCommand<command>".
+It is an approximation of official server script language's 'cmdothernpc'.
+
+---------------------------------------
+
+*npctalk "<message>";
+
+This command will display a message to the surrounding area as if the NPC object
+running it was a player talking - that is, above their head and in the chat
+window. The display name of the NPC will get appended in front of the message to
+complete the effect.
+
+ // This will make everyone in the area see the NPC greet the character
+ // who just invoked it.
+ npctalk "Hello "+strcharinfo(0)+", how are you?";
+
+---------------------------------------
+
+*setnpcdisplay("<npc name>", "<display name>", <class id>, <size>)
+*setnpcdisplay("<npc name>", "<display name>", <class id>)
+*setnpcdisplay("<npc name>", "<display name>")
+*setnpcdisplay("<npc name>", <class id>)
+
+Changes the display name and/or display class of the target NPC.
+Returns 0 is successful, 1 if the NPC does not exist.
+Size is 0 = normal 1 = small 2 = big.
+
+---------------------------------------
+\\
+5,1.- Time-related commands
+\\
+---------------------------------------
+*addtimer <ticks>,"NPC::OnLabel";
+*deltimer "NPC::OnLabel";
+*addtimercount <ticks>,"NPC::OnLabel";
+
+These commands will create, destroy, and delay a countdown timer - 'addtimer' to
+create, 'deltimer' to destroy and 'addtimercount' to delay it by the specified
+number of ticks. For all three cases, the event label given is the identifier of
+that timer. The timer runs on the character object that is attached to the script,
+and can have multiple instances. When the label is run, it is run as if the player that
+the timer runs on has clicked the NPC.
+
+When this timer runs out, a new execution thread will start in the specified NPC
+object at the specified label.
+
+The ticks are given in 1/1000ths of a second.
+
+One more thing. These timers are stored as part of player data. If the player
+logs out, all of these get immediately deleted, without executing the script.
+If this behavior is undesirable, use some other timer mechanism (like 'sleep').
+
+Example:
+<NPC Header> {
+ dispbottom "Starting a 5 second timer...";
+ addtimer 5000, strnpcinfo(3)+"::On5secs";
+ end;
+On5secs:
+ dispbottom "5 seconds have passed!";
+ end;
+}
+
+---------------------------------------
+
+*initnpctimer{ "<NPC name>" {, <Attach Flag>} } |
+ { "<NPC name>" | <Attach Flag> };
+*stopnpctimer{ "<NPC name>" {, <Detach Flag>} } |
+ { "<NPC name>" | <Detach Flag> };
+*startnpctimer{ "<NPC name>" {, <Attach Flag>} } |
+ { "<NPC name>" | <Attach Flag> };
+*setnpctimer <tick>{,"<NPC name>"};
+*getnpctimer(<type of information>{,"<NPC name>"})
+*attachnpctimer {"<character name>"};
+*detachnpctimer {"<NPC name>"};
+
+This set of commands and functions will create and manage an NPC-based timer.
+The NPC name may be omitted, in which case the calling NPC is used as target.
+
+Contrary to addtimer/deltimer commands which let you have many different timers
+referencing different labels in the same NPC, each with their own countdown,
+'initnpctimer' can only have one per NPC object. But it can trigger many labels
+and let you know how many were triggered already and how many still remain.
+
+This timer is counting up from 0 in ticks of 1/1000ths of a second each. Upon
+creating this timer, the execution will not stop, but will happily continue
+onward. The timer will then invoke new execution threads at labels
+"OnTimer<time>:" in the NPC object it is attached to.
+
+To create the timer, use the 'initnpctimer', which will start it running.
+'stopnpctimer' will pause the timer, without clearing the current tick, while
+'startnpctimer' will let the paused timer continue.
+
+By default timers do not have a RID attached, which lets them continue even
+if the player that started them logs off. To attach a RID to a timer, you can
+either use the optional "attach flag" when using 'initnpctimer/startnpctimer',
+or do it manually by using 'attachnpctimer'. Likewise, the optional flag of
+stopnpctimer lets you detach any RID after stopping the timer, and by using
+'detachnpctimer' you can detach a RID at any time.
+
+Normally there is only a single timer per NPC, but as an exception, as long as
+you attach a player to the timer, you can have multiple timers running at once,
+because these will get stored on the players instead of the NPC.
+NOTE: You need to attach the RID before the timer _before_ you start it to
+get a player-attached timer. Otherwise it'll stay a NPC timer (no effect).
+
+If the player that is attached to the npctimer logs out, the "OnTimerQuit:"
+event label of that NPC will be triggered, so you can do the appropriate
+cleanup (the player is still attached when this event is triggered).
+
+The 'setnpctimer' command will explicitly set the timer to a given tick.
+'getnpctimer' provides timer information. Its parameter defines what type:
+
+ 0 - Will return the current tick count of the timer.
+ 1 - Will return 1 if there are remaining "OnTimer<ticks>:" labels in the
+ specified NPC waiting for execution.
+ 2 - Will return the number of times the timer has triggered and will trigger
+ an "OnTimer<tick>:" label in the specified NPC.
+
+Example 1:
+
+ <NPC Header> {
+ // We need to use attachnpctimer because the mes command below needs RID attach
+ attachnpctimer;
+ initnpctimer;
+ npctalk "I cant talk right now, give me 10 seconds";
+ end;
+ OnTimer5000:
+ npctalk "Ok 5 seconds more";
+ end;
+ OnTimer6000:
+ npctalk "4";
+ end;
+ OnTimer7000:
+ npctalk "3";
+ end;
+ OnTimer8000:
+ npctalk "2";
+ end;
+ OnTimer9000:
+ npctalk "1";
+ end;
+ OnTimer10000:
+ stopnpctimer;
+ mes "[Man]";
+ mes "Ok we can talk now";
+ detachnpctimer;
+ // and remember attachnpctimer and detachnpctimer can only use while the NPC timer is not running !
+ }
+
+Example 2:
+
+ OnTimer15000:
+ npctalk "Another 15 seconds have passed.";
+
+ // You have to use 'initnpctimer' instead of 'setnpctimer 0'.
+ // This is equal to 'setnpctimer 0' + 'startnpctimer'.
+ // Alternatively, you can also insert another 'OnTimer15001' label so that the timer won't stop. */
+ initnpctimer;
+ end;
+
+ // This OnInit label will run when the script is loaded, so that the timer
+ // is initialized immediately as the server starts. It is dropped back to 0
+ // every time the NPC says something, so it will cycle continuously.
+ OnInit:
+ initnpctimer;
+ end;
+
+Example 3:
+
+ mes "[Man]";
+ mes "I have been waiting "+(getnpctimer(0)/1000)+" seconds for you.";
+ // We divide the timer returned by 1000 to convert milliseconds to seconds.
+ close;
+
+Example 4:
+
+ mes "[Man]";
+ mes "Ok, I will let you have 30 more seconds...";
+ close2;
+ setnpctimer (getnpctimer(0)-30000);
+ // Notice the 'close2'. If there were a 'next' there the timer would be
+ // changed only after the player pressed the 'next' button.
+ end;
+
+---------------------------------------
+
+*sleep {<milliseconds>};
+*sleep2 {<milliseconds>};
+*awake "<NPC name>";
+
+These commands are used to control the pause of a NPC.
+sleep and sleep2 will pause the script for the given amount of milliseconds.
+Awake is used to cancel a sleep. When awake is called on a NPC it will run as
+if the sleep timer ran out, and thus making the script continue. Sleep and sleep2
+basically do the same, but the main difference is that sleep will not keep the rid,
+while sleep2 does.
+
+Examples:
+ sleep 10000; //pause the script for 10 seconds and ditch the RID (so no player is attached anymore)
+ sleep2 5000; //pause the script for 5 seconds, and continue with the RID attached.
+ awake "NPC"; //Cancels any running sleep timers on the NPC 'NPC'.
+
+---------------------------------------
+
+*progressbar "<color>",<seconds>;
+
+This command works almost like sleep2, but displays a progress bar
+above the head of the currently attached character (like cast bar).
+Once the given amount of seconds passes, the script resumes. If the
+character moves while the progress bar progresses, it is aborted and
+the script ends. The color format is in RGB (0xRRGGBB). The color is
+currently ignored by the client and appears always green.
+
+---------------------------------------
+//
+5,1.- End of time-related commands
+//
+
+*announce "<text>",<flag>{,<fontColor>{,<fontType>{,<fontSize>{,<fontAlign>{,<fontY>}}}}};
+
+This command will broadcast a message to all or most players, similar to
+@kami/@kamib GM commands.
+
+ announce "This will be shown to everyone at all in yellow.",0;
+
+The region the broadcast is heard in (target), source of the broadcast
+and the color the message will come up as is determined by the flags.
+
+The flag values are coded as constants in db/const.txt to make them easier to use.
+
+Target flags:
+- bc_all: Broadcast message is sent server-wide (default).
+- bc_map: Message is sent to everyone in the same map as the source of the broadcast (see below).
+- bc_area: Message is sent to players in the vicinity of the source.
+- bc_self: Message is sent only to current player.
+You cannot use more than one target flag.
+
+Source flags:
+- bc_pc: Broadcast source is the attached player (default).
+- bc_npc: Broadcast source is the NPC, not the player attached to the script
+ (useful when a player is not attached or the message should be sent to those
+ nearby the NPC).
+You cannot use more than one source flag.
+
+Special flags:
+- bc_yellow: Broadcast will be displayed in yellow color (default).
+- bc_blue: Broadcast will be displayed in blue color.
+- bc_woe: Indicates that this broadcast is 'WoE Information' that can be disabled client-side.
+Due to the way client handles broadcasts, it is impossible to set both bc_blue and bc_woe.
+
+The optional parameters allow usage of broadcasts in custom colors, font-weights, sizes etc.
+If any of the optional parameters is used, special flag is ignored.
+Optional parameters may not work well (or at all) depending on a game client used.
+
+The color parameter is a single number which can be in hexadecimal notation.
+For example:
+ announce "This will be shown to everyone at all in green.",bc_all,0x00FF00;
+Will display a global announce in green. The color format is in RGB (0xRRGGBB).
+
+In official scripts only two font-weights (types) are used:
+ - normal (FW_NORMAL = 400, default),
+ - bold (FW_BOLD = 700).
+
+Default font size is 12.
+
+Using this for private messages to players is probably not that good an idea,
+but it can be used instead in NPCs to "preview" an announce.
+
+ // This will be a private message to the player using the NPC that made the
+ // announcement
+ announce "This is my message just for you",bc_blue|bc_self;
+
+ // This will be shown on everyones screen that is in sight of the NPC.
+ announce "This is my message just for you people here",bc_npc|bc_area;
+
+---------------------------------------
+
+*mapannounce "<map name>","<text>",<flag>{,<fontColor>{,<fontType>{,<fontSize>{,<fontAlign>{,<fontY>}}}}}};
+
+This command will work like 'announce' but will only broadcast to characters
+currently residing on the specified map. The flag and optional parameters
+parameters are the same as in 'announce', but target and source flags are ignored.
+
+---------------------------------------
+
+*areaannounce "<map name>",<x1>,<y1>,<x2>,<y2>,"<text>",<flag>{,<fontColor>{,<fontType>{,<fontSize>{,<fontAlign>{,<fontY>}}}}}};
+
+This command works like 'announce' but will only broadcast to characters
+residing in the specified x1/y1-x2/y2 rectangle on the map given. The flags and
+optional parameters are the same as in 'announce', but target and source flags are ignored.
+
+ areaannounce "prt_church",0,0,350,350,"God's in his heaven, all right with the world",0;
+
+---------------------------------------
+
+*callshop "<name>",<option>;
+
+These are a series of commands used to create dynamic shops.
+The callshop function calls a invisible shop (view -1) as if the player clicked on it.
+
+For the options on callShop:
+ 0 = The normal window (buy, sell and cancel)
+ 1 = The buy window
+ 2 = The sell window
+
+Example:
+
+callshop "DaShop",1; //Will call the shop named DaShop and opens the buy menu.
+
+The shop which is called by callshop (as long as an npcshop* command is executed
+from that NPC (see note 1)) will trigger the labels OnBuyItem and OnSellitem. These
+labels can take over handling for relatively the buying of items from the shop
+and selling the items to a shop. Via these labels you can customize the way an item
+is bought or sold by a player.
+
+In the OnBuyItem, two arrays are set (@bought_nameid and @bought_quantity), which
+hold information about the name id (item id) sold and the amount sold of it. Same
+goes for the OnSellItem label, only the variables are named different
+(@sold_nameid, @sold_quantity, @sold_refine, @sold_attribute, @sold_identify,
+@sold_card1, @sold_card2, @sold_card3, @sold_card4). An example on a shop comes
+with rAthena, and can be found in the doc/sample/npc_dynamic_shop.txt file.
+
+This example shows how to use the labels and their set variables to create a dynamic shop.
+
+Note 1: These labels will only be triggered if a npcshop* command is executed, this is
+because these commands set a special data on the shop NPC,named master_nd in the source.
+The OnSellItem and OnBuyItem are triggered in the NPC whose master_nd is given in the shop.
+This was found out thanks to 'Hondacrx', noticing the OnBuyItem wasn't triggered unless
+npcshopitem was used. After rechecking the source, I found what caused this.
+
+---------------------------------------
+
+*npcshopitem "<name>",<item id>,<price>{,<item id>,<price>{,<item id>,<price>{,...}}}
+
+This command lets you override the contents of an existing NPC shop or cashshop. The
+current sell list will be wiped, and only the items specified with the price
+specified will be for sale.
+
+The function returns 1 if shop was updated successfully, or 0 if not found.
+
+Note that you cannot use -1 to specify default selling price!
+
+---------------------------------------
+
+*npcshopadditem "<name>",<item id>,<price>{,<item id>,<price>{,<item id>,<price>{,...}}}
+
+This command will add more items at the end of the selling list for the
+specified NPC shop or cashshop. If you specify an item already for sell, that item will
+appear twice on the sell list.
+
+The function returns 1 if shop was updated successfully, or 0 if not found.
+
+Note that you cannot use -1 to specify default selling price!
+
+---------------------------------------
+
+*npcshopdelitem "<name>",<item id>{,<item id>{,<item id>{,...}}}
+
+This command will remove items from the specified NPC shop or cashshop.
+If the item to remove exists more than once on the shop, all instances will be
+removed.
+
+Note that the function returns 1 even if no items were removed. The return
+value is only to confirm that the shop was indeed found.
+
+---------------------------------------
+
+*npcshopattach "<name>"{,<flag>}
+
+This command will attach the current script to the given NPC shop.
+When a script is attached to a shop, the events "OnBuyItem" and "OnSellItem"
+of your script will be executed whenever a player buys/sells from the shop.
+Additionally, the arrays @bought_nameid[], @bought_quantity[] or @sold_nameid[]
+and @sold_quantity[] will be filled up with the items and quantities
+bought/sold.
+
+The optional parameter specifies whether to attach ("1") or detach ("0") from
+the shop (the default is to attach). Note that detaching will detach any NPC
+attached to the shop, even if it's from another script, while attaching will
+override any other script that may be already attached.
+
+The function returns 0 if the shop was not found, 1 otherwise.
+
+---------------------------------------
+
+*waitingroom "<chatroom name>",<limit>{,<event label>,<trigger>,<required zeny>,<min lvl>,<max lvl>};
+
+This command will create a chat room, owned by the NPC object running this
+script and displayed above the NPC sprite.
+The maximum length of a chat room name is 60 letters.
+
+The limit is the maximum number of people allowed to enter the chat room.
+The attached NPC is included in this count. If the optional event and trigger
+parameters are given, the event label ("<NPC object name>::<label name>")
+will be invoked as if with a 'doevent' upon the number of people in the chat
+room reaching the given triggering amount.
+
+// The NPC will just show a box above its head that says "Hello World", clicking
+// it will do nothing, since the limit is zero.
+ waitingroom "Hello World",0;
+
+// The NPC will have a box above its head, it will say "Disco - Waiting Room"
+// and will have 8 waiting slots. Clicking this will enter the chat room, where
+// the player will be able to wait until 7 players accumulate. Once this happens,
+// it will cause the NPC "Bouncer" run the label "OnStart".
+
+ waitingroom "Disco - Waiting Room",8,"Bouncer::OnStart",7;
+
+// The NPC will have a box above its head, it will say "Party - Waiting Room"
+// and will have 8 waiting slots. Clicking this will allow a player who has
+// 5000 zeny and lvl 50~99 to enter the chat room, where the player will be
+// able to wait until 7 players accumulate. Once this happens, it will cause
+// the NPC "Bouncer" run the label "OnStart".
+
+ waitingroom "Party - Waiting Room",8,"Bouncer::OnStart",7,5000,50,99;
+
+Creating a waiting room does not stop the execution of the script and it will
+continue to the next line.
+
+For more examples see the 2-1 and 2-2 job quest scripts which make extensive use
+of waiting rooms.
+
+---------------------------------------
+
+*delwaitingroom {"<NPC object name"};
+
+This command will delete a waiting room. If no parameter is given, it will
+delete a waiting room attached to the NPC object running this command, if it is,
+it will delete a waiting room owned by another NPC object. This is the only way
+to get rid of a waiting room, nothing else will cause it to disappear.
+
+It's not clear what happens to a waiting room if the NPC is disabled with
+'disablenpc', by the way.
+
+---------------------------------------
+
+*enablewaitingroomevent {"<NPC object name>"};
+*disablewaitingroomevent {"<NPC object name>"};
+*enablearena;
+*disablearena;
+
+This will enable and disable triggering the waiting room event (see
+'waitingroom') respectively. Optionally giving an NPC object name will do that
+for a specified NPC object. The chat room will not disappear when triggering is
+disabled and enabled in this manner and players will not be kicked out of it.
+Enabling a chat room event will also cause it to immediately check whether the
+number of users in it exceeded the trigger amount and trigger the event
+accordingly.
+
+Normally, whenever a waiting room was created to make sure that only one
+character is, for example, trying to pass a job quest trial, and no other
+characters are present in the room to mess up the script.
+
+The 'enablearena'/'disablearena' commands are just aliases with no parameter.
+These are supposedly left here for compatibility with official server scripts,
+but no rAthena script uses these at the moment.
+
+---------------------------------------
+
+*getwaitingroomstate(<information type>{,"<NPC object name>"})
+
+This function will return information about the waiting room state for the
+attached waiting room or for a waiting room attached to the specified NPC if
+any.
+
+The valid information types are:
+
+ 0 - Number of users currently chatting.
+ 1 - Maximum number of users allowed.
+ 2 - Will return 1 if the waiting room has a trigger set.
+ 0 otherwise.
+ 3 - Will return 1 if the waiting room is currently disabled.
+ 0 otherwise.
+ 4 - The Title of the waiting room (string)
+ 5 - Password of the waiting room, if any. Pointless, since there is no way to
+ set a password on a waiting room right now.
+ 16 - Event name of the waiting room (string)
+ 32 - Whether or not the waiting room is full.
+ 33 - Whether the amount of users in the waiting room is higher than the trigger
+ number.
+
+---------------------------------------
+
+*warpwaitingpc "<map name>",<x>,<y>{,<number of people>};
+
+This command will warp the amount of characters equal to the trigger number of
+the waiting room chat attached to the NPC object running this command to the
+specified map and coordinates, kicking them out of the chat. Those waiting the
+longest will get warped first. It can also do a random warp on the same map
+("Random" instead of map name) and warp to the save point ("SavePoint").
+
+The list of characters to warp is taken from the list of the chat room members.
+Those not in the chat room will not be considered even if they are talking to
+the NPC in question. If the number of people is given, exactly this much people
+will be warped.
+
+This command can also keep track of who just got warped. It does this by setting
+special variables:
+
+$@warpwaitingpc[] is an array containing the account_id numbers of the
+ characters who were just warped.
+$@warpwaitingpcnum contains the number of the character it just warped.
+
+See also 'getpartymember' for advice on what to do with those variables.
+
+The obvious way of using this effectively would be to set up a waiting room for
+two characters to be warped onto a random PVP map for a one-on-one duel, for
+example.
+
+---------------------------------------
+
+*kickwaitingroomall {"<NPC object name>"};
+
+This command kicks everybody out of a specified waiting room chat.
+
+---------------------------------------
+
+*setmapflagnosave "<map name>","<alternate map name>",<x>,<y>;
+
+This command sets the 'nosave' flag for the specified map and also gives an
+alternate respawn-upon-relogin point.
+
+It does not make a map impossible to make a save point on as you would normally
+think, 'savepoint' will still work. It will, however, make the specified map
+kick the reconnecting players off to the alternate map given to the coordinates
+specified.
+
+---------------------------------------
+
+*setmapflag "<map name>",<flag>{,<zone>};
+
+This command marks a specified map with a map flag given. Map flags alter the
+behavior of the map, you can see the list of the available ones in
+'db/const.txt' under 'mf_'.
+
+The map flags alter the behavior of the map regarding teleporting (mf_nomemo,
+mf_noteleport, mf_nowarp, mf_nogo), storing location when disconnected
+(mf_nosave), dead branch usage (mf_nobranch), penalties upon death
+(mf_nopenalty, mf_nozenypenalty), PVP behavior (mf_pvp, mf_pvp_noparty,
+mf_pvp_noguild), WoE behavior (mf_gvg,mf_gvg_noparty), ability to use
+skills or open up trade deals (mf_notrade, mf_novending, mf_noskill, mf_noicewall),
+current weather effects (mf_snow, mf_fog, mf_sakura, mf_leaves, mf_rain, mf_clouds,
+mf_fireworks) and whether night will be in effect on this map (mf_nightenabled).
+
+The zone optional parameter is used to set the zone for restricted mapflags.
+
+---------------------------------------
+
+*removemapflag "<map name>",<flag>{,<zone>};
+
+This command removes a mapflag from a specified map.
+See 'setmapflag' for a list of mapflags.
+
+The zone optional parameter is used to remove the zone from restricted mapflags.
+
+---------------------------------------
+
+*getmapflag("<map name>",<flag>)
+
+This command checks the status of a given mapflag and returns the mapflag's state.
+0 means OFF, and 1 means ON. See 'setmapflag' for a list of mapflags.
+
+---------------------------------------
+
+*setbattleflag "<battle flag>",<value>;
+*getbattleflag("<battle flag>")
+
+Sets or gets the value of the given battle flag.
+Battle flags are the flags found in the battle/*.conf files and is also used in Lupus' variable rates script.
+
+Examples:
+
+// Will set the base experience rate to 20x (2000%)
+ setBattleFlag "base_exp_rate",2000;
+
+// Will return the value of the base experience rate (when used after the above example, it would print 2000).
+ mes getBattleFlag("base_exp_rate");
+
+---------------------------------------
+
+*warpportal <x>,<y>,"<mapname>",<x>,<y>;
+
+Creates a warp Portal as if a acolyte class character did it.
+The first x and y is the place of the warp portal on the map where the NPC is on
+The mapname and second x and y is the target area of the warp portal.
+
+Examples:
+
+// Will create a warp portal on the NPC's map at 150,150 leading to prontera, coords 150,180.
+ warpportal 150,150,"prontera",150,180;
+
+---------------------------------------
+
+*mapwarp "<from map>","<to map>",<x>,<y>{,<type>,<ID>};
+
+This command will collect all characters located on the From map and warp them
+wholesale to the same point on the To map, or randomly distribute them there if
+the coordinates are zero. "Random" is understood as a special To map name and
+will mean randomly shuffling everyone on the same map.
+
+Optionally, a type and ID can be specified. Available types are:
+
+ 0 - Everyone
+ 1 - Guild
+ 2 - Party
+
+Example:
+
+// Will warp all members of guild with ID 63 on map prontera to map alberta.
+ mapwarp "prontera","alberta",150,150,1,63;
+
+---------------------------------------
+\\
+5,2.- Guild-related Commands
+\\
+---------------------------------------
+
+*maprespawnguildid "<map name>",<guild id>,<flag>;
+
+This command goes through the specified map and for each player and monster
+found there does stuff.
+
+Flag is a bit-mask (add up numbers to get effects you want)
+ 1 - warp all guild members to their save points.
+ 2 - warp all non-guild members to their save points.
+ 4 - remove all monsters which are not guardian or Emperium.
+
+Flag 7 will, therefore, mean 'wipe all mobs but guardians and the Emperium and
+kick all characters out', which is what the official scripts do upon castle
+surrender. Upon start of WoE, the scripts do 2 (warp all intruders out).
+
+Characters not belonging to any guild will warp out regardless of the flag setting.
+
+For examples, check the WoE scripts in the distribution.
+
+---------------------------------------
+
+*agitstart;
+*agitend;
+*agitstart2;
+*agitend2;
+
+These four commands will start and end War of Emperium or War of Emperium SE.
+
+This is a bit more complex than it sounds, since the commands themselves won't
+actually do anything interesting, except causing all 'OnAgitStart:' and
+'OnAgitEnd:', or 'OnAgitStart2:' and 'OnAgitEnd2:' in the case of latter two
+commands, events to run everywhere, respectively. They are used as simple
+triggers to run a lot of complex scripts all across the server, and they,
+in turn, are triggered by clock with an 'OnClock<time>:' time-triggering label.
+
+---------------------------------------
+
+*gvgon "<map name>";
+*gvgoff "<map name>";
+
+These commands will turn GVG mode for the specified maps on and off, setting up
+appropriate map flags. In GVG mode, maps behave as if during the time of WoE,
+even though WoE itself may or may not actually be in effect.
+
+---------------------------------------
+
+*flagemblem <guild id>;
+
+This command only works when run by the NPC objects which have sprite id 722,
+which is a 3D guild flag sprite. If it isn't, the data will change, but nothing
+will be seen by anyone. If it is invoked in that manner, the emblem of the
+specified guild will appear on the flag, though, if any players are watching it
+at this moment, they will not see the emblem change until they move out of sight
+of the flag and return.
+
+This is commonly used in official guildwar scripts with a function call which
+returns a guild id:
+
+// This will change the emblem on the flag to that of the guild that owns
+// "guildcastle"
+
+ flagemblem GetCastleData("guildcastle",1);
+
+---------------------------------------
+
+*guardian "<map name>",<x>,<y>,"<name to show>",<mob id>{,"<event label>"{,<guardian index>}};
+
+This command is roughly equivalent to 'monster', but is meant to be used with
+castle guardian monsters and will only work with them. It will set the guardian
+characteristics up according to the castle's investment values and otherwise
+set the things up that only castle guardians need.
+
+Since trunk r12524:
+Returns the id of the mob or 0 if an error occurred.
+When 'guardian index' isn't supplied it produces a temporary guardian.
+Temporary guardians are not saved with the castle and can't be accessed by guardianinfo.
+
+---------------------------------------
+
+*guardianinfo("<map name>", <guardian number>, <type>);
+
+This function will return various info about the specified guardian, or -1
+if it fails for some reason. It is primarily used in the castle manager NPC.
+
+Map name and guardian number (value between 0 and 7) define the target.
+Type indicates what information to return:
+ 0 - visibility (whether the guardian is installed or not)
+ 1 - max. hp
+ 2 - current hp
+
+---------------------------------------
+//
+5,2.- End of guild-related commands
+//
+---------------------------------------
+
+*npcspeed <speed value>;
+*npcwalkto <x>,<y>;
+*npcstop;
+
+These commands will make the NPC object in question move around the map. As they
+currently are, they are a bit buggy and are not useful for much more than making
+an NPC move randomly around the map.
+
+'npcspeed' will set the NPCs walking speed to a specified value. As in the
+@speed GM command, 200 is the slowest possible speed while 0 is the fastest
+possible (instant motion). 100 is the default character walking speed.
+'npcwalkto' will start the NPC sprite moving towards the specified coordinates
+on the same map as it is currently on.
+'npcstop' will stop the motion.
+
+While in transit, the NPC will be clickable, but invoking it will cause it to
+stop motion, which will make it's coordinates different from what the client
+computed based on the speed and motion coordinates. The effect is rather
+unnerving.
+
+Only a few NPC sprites have walking animations, and those that do, do not get
+the animation invoked when moving the NPC, due to the problem in the NPC walking
+code, which looks a bit silly. You might have better success by defining a job-
+sprite based sprite id in 'db/mob_avail.txt' with this.
+
+---------------------------------------
+
+*movenpc "<NPC name>",<x>,<y>{,<dir>};
+
+This command looks like the NPCWalkToxy function,but is a little different.
+
+While NPCWalkToXY just makes the NPC 'walk' to the coordinates given (which
+sometimes gives problems if the path isn't a straight line without objects),
+this command just moves the NPC. It basically warps out and in on the current
+and given spot. Direction can be used to change the NPC's facing direction.
+
+Example:
+
+// This will move Bugga from to the coordinates 100,20 (if those coordinates are legit).
+ moveNPC "Bugga",100,20;
+
+---------------------------------------
+
+=====================
+|6.- Other commands.|
+=====================
+---------------------------------------
+
+*debugmes "<message>";
+
+This command will send the message to the server console (map-server window). It
+will not be displayed anywhere else.
+
+ // Displays "NAME has clicked me!" in the map-server window.
+ debugmes strcharinfo(0)+" has clicked me!";
+
+---------------------------------------
+
+*logmes "<message>";
+
+This command will write the message given to the map server NPC log file, as
+specified in 'conf/log_athena.conf'. In the TXT version of the server, the log
+file is 'log/npclog.log' by default. In the SQL version, if SQL logging is
+enabled, the message will go to the 'npclog' table, otherwise, it will go to the
+same log file.
+
+If logs are not enabled, nothing will happen.
+
+---------------------------------------
+
+*globalmes "<message>"{,"<NPC name>"};
+
+This command will send a message to the chat window of all currently connected
+characters.
+
+If NPC name is specified, the message will be sent as if the sender would be
+the NPC with the said name.
+
+---------------------------------------
+
+*rand(<number>{,<number>});
+
+This function returns a number ...
+(if you specify one) ... randomly positioned between 0 and the number you specify -1.
+(if you specify two) ... randomly positioned between the two numbers you specify.
+
+rand(10) would result in 0,1,2,3,4,5,6,7,8 or 9
+rand(0,9) would result in 0,1,2,3,4,5,6,7,8 or 9
+rand(2,5) would result in 2,3,4 or 5
+
+---------------------------------------
+
+*viewpoint <action>,<x>,<y>,<point number>,<color>;
+
+This command will mark places on the mini map in the client connected to the
+invoking character. It uses the normal X and Y coordinates from the main map.
+The colors of the marks are defined using a hexadecimal number, same as the ones
+used to color text in 'mes' output, but are written as hexadecimal numbers in C.
+(They look like 0x<six numbers>.)
+
+Action is what you want to do with a point, 1 will set it, while 2 will clear
+it. 0 will also set it, but automatically removes the point after 15 seconds.
+Point number is the number of the point - you can have several. If more than
+one point is drawn at the same coordinates, they will cycle, which can be used
+to create flashing marks.
+
+ // This command will show a mark at coordinates X 30 Y 40, is mark number 1,
+ // and will be red.
+
+ viewpoint 1,30,40,1,0xFF0000;
+
+This will create three points:
+
+ viewpoint 1,30,40,1,0xFF0000;
+ viewpoint 1,35,45,2,0xFF0000;
+ viewpoint 1,40,50,3,0xFF0000;
+
+And this is how you remove them:
+
+ viewpoint 2,30,40,1,0xFF0000;
+ viewpoint 2,35,45,2,0xFF0000;
+ viewpoint 2,40,50,3,0xFF0000;
+
+The client determines what it does with the points entirely, the server keeps no
+memory of where the points are set whatsoever.
+
+---------------------------------------
+
+*cutin "<filename>",<position>;
+
+This command will display a picture, usually an NPC illustration, also called
+cutin, for the currently attached client. The position parameter determines the
+placement of the illustration and takes following values:
+
+ 0 - bottom left corner
+ 1 - bottom middle
+ 2 - bottom right corner
+ 3 - middle of screen in a movable window with an empty title bar
+ 4 - middle of screen without the window header, but still movable
+
+The picture is read from data\texture\유저인터페이스\illust, from both the GRF archive
+and data folder, and is required to be a bitmap. The file extension .bmp can be
+omitted. Magenta color (#ff00ff) is considered transparent. There is no limit
+placed on the size of the illustrations by the client, although loading of large
+pictures (about 700x700 and larger) causes the client to freeze shortly (lag).
+Typically the size is about 320x480. New illustrations can be added by just
+putting the new file into the location above.
+
+The client is able to display only one cutin at the same time and each new one
+will cause the old one to disappear. To delete the currently displayed
+illustration without displaying a new one, an empty file name and position 255
+must be used.
+
+ // Displays the Comodo Kafra illustration in lower right corner.
+ cutin "kafra_07",2;
+
+ // Typical way to end a script, which displayed an illustration during a
+ // dialog with a player.
+ mes "See you.";
+ close2;
+ cutin "",255;
+ end;
+
+---------------------------------------
+
+*pet <pet id>;
+
+This command is used in all the item scripts for taming items. Running this
+command will make the pet catching cursor appear on the client connected to the
+invoking character, usable on the monsters with the specified pet ID number. It
+will still work outside an item script.
+
+A full list of pet IDs can be found inside 'db/pet_db.txt'
+
+---------------------------------------
+
+*emotion <emotion number>{,<target>{,"<target name>"}};
+
+This command makes an object display an emotion sprite above their own as
+if they were doing that emotion. For a full list of emotion numbers,
+see 'db/const.txt' under 'e_'. The not so obvious ones are 'e_what' (a question mark)
+and 'e_gasp' (the exclamation mark).
+
+The optional target parameter specifies who will get the emotion on top of
+their head. If 0 (the default if omitted), the NPC in current use will show
+the emotion, if 1, the player that is running the script will display it.
+
+Target name parameter allows to display emotion on top of other NPC/PC without
+event labels. If specified name is not found, command does nothing.
+
+---------------------------------------
+
+*misceffect <effect number>;
+
+This command, if run from an NPC object that has a sprite, will call up a
+specified effect number, centered on the NPC sprite. If the running code does
+not have an object ID (a 'floating' NPC) or is not running from an NPC object at
+all (an item script) the effect will be centered on the character who's RID got
+attached to the script, if any. For usable item scripts, this command will
+create an effect centered on the player using the item.
+
+A full list of known effects is found in 'doc/effect_list.txt'. The list of
+those that actually work may differ greatly between client versions.
+
+---------------------------------------
+
+*soundeffect "<effect filename>",<type>;
+*soundeffectall "<effect filename>",<type>{,"<map name>"}{,<x0>,<y0>,<x1>,<y1>};
+
+These two commands will play a sound effect to either the invoking character
+only ('soundeffect') or multiple characters ('soundeffectall'). If the running
+code does not have an object ID (a 'floating' NPC) or is not running from an NPC
+object at all (an item script) the sound will be centered on the character who's
+RID got attached to the script, if any. If it does, it will be centered on that
+object. (an NPC sprite)
+
+Effect filename is the filename in a GRF. It must have the .wav extension.
+
+It's not quite certain what the 'type' actually does, it is sent to the client
+directly. It probably determines which directory to play the effect from.
+It's certain that giving 0 for the number will play sound files from '\data\wav\',
+but where the other numbers will read from is unclear.
+
+The sound files themselves must be in the PCM format, and file names should also
+have a maximum length of 23 characters including the .wav extension:
+
+soundeffect "1234567890123456789.wav", 0; // this will play the soundeffect
+soundeffect "12345678901234567890.wav", 0; // throw gravity error
+
+You can add your own effects this way, naturally.
+
+---------------------------------------
+
+*playBGM "<BGM filename>";
+*playBGMall "<BGM filename>"{,"<map name>"{,<x0>,<y0>,<x1>,<y1>}};
+
+These two commands will play a Background Music to either the invoking character
+only ('playBGM') or multiple characters ('playBGMall').
+
+BGM filename is the filename in /BGM/ folder. It has to be in .mp3 extension.
+
+It's not required to specify the extension inside the script.
+If coordinates are omitted, BGM will be broadcasted on the entire map. If the map name
+is omitted as well the BGM will be played for the entire server.
+
+You can add your own BGMs this way, naturally.
+
+---------------------------------------
+
+*pvpon "<map name>";
+*pvpoff "<map name>";
+
+These commands will turn PVP mode for the specified maps on and off. Beside
+setting the flags referred to in 'setmapflag', 'pvpon' will also create a PVP
+timer and ranking as will @pvpon GM command do.
+
+---------------------------------------
+
+*atcommand "<command>";
+
+This command will run the given command line exactly as if it was typed in from
+the keyboard by the player connected to the invoking character, and that
+character belonged to an account which had GM level 99.
+
+ // This will ask the invoker for a character name and then use the '@nuke'
+ // GM command on them, killing them mercilessly.
+ input @player$;
+ atcommand "@nuke "+@player$;
+
+This command has a lot of good uses, I am sure you can have some fun with this
+one.
+
+---------------------------------------
+
+*charcommand "<command>";
+
+This command will run the given command line exactly as if it was typed in from
+the keyboard from a character that belonged to an account which had GM level 99.
+
+The commands can also run without an attached rid.
+
+ // This would do the same as above, but now
+ // it doesn't need a player attached by default.
+ charcommand "#option 0 0 0 Roy";
+
+---------------------------------------
+
+*bindatcmd "command","<NPC object name>::<event label>"{,<atcommand level>,<charcommand level>};
+
+This command will bind a NPC event label to an atcommand. Upon execution of the
+atcommand, the user will invoke the NPC event label. Each atcommand is only allowed
+one binding. If you rebind, it will override the original binding.
+
+The following variables are set upon execution:
+ .@atcmd_command$ = The name of the @command used.
+ .@atcmd_parameters$[] = Array containing the given parameters, starting from an index of 0.
+ .@atcmd_numparameters = The number of parameters defined.
+
+Example:
+
+When a user types the command "@test", an angel effect will be shown.
+
+- script atcmd_example -1,{
+OnInit:
+ bindatcmd "test",strnpcinfo(3)+"::OnAtcommand";
+ end;
+OnAtcommand:
+ specialeffect2 338;
+ end;
+}
+
+---------------------------------------
+
+*unbindatcmd "command";
+
+This command will unbind a NPC event label from an atcommand.
+
+---------------------------------------
+
+*useatcmd "command";
+
+This command will execute an atcommand binding on the attached RID from a script.
+The three .@atcmd_***** variables will NOT be set when invoking scripts-atcommands this way.
+
+---------------------------------------
+
+*unitskilluseid <GID>,<skill id>,<skill lvl>{,<target id>};
+*unitskilluseid <GID>,"<skill name>",<skill lvl>{,<target id>};
+*unitskillusepos <GID>,<skill id>,<skill lvl>,<x>,<y>;
+*unitskillusepos <GID>,"<skill name>",<skill lvl>,<x>,<y>;
+
+This is the replacement of the older commands, these use the same values for
+GID as the other unit* commands (See 'GID').
+
+Skill ID is the ID of the skill, skill level is the level of the skill.
+For the position, the x and y are given in the unitSkillUsePos.
+
+---------------------------------------
+
+*npcskill <skill id>,<skill lvl>,<stat point>,<NPC level>;
+*npcskill "<skill name>",<skill lvl>,<stat point>,<NPC level>;
+
+This command causes the attached NPC object to cast a skill on the attached
+player. The skill will have no cast time or cooldown. The player must be
+within the default skill range or the command will fail silently.
+
+The "stat point" parameter temporarily sets all NPC stats to the given value,
+and "NPC level" is the temporary level of the NPC (used in some skills).
+Neither value can be greater than the max level defined in config, and will
+not work properly if the NPC has a mob sprite.
+
+ // Casts Level 10 Heal on the attached player, calculated with
+ // all stats 99 and base level 60.
+ npcskill "AL_HEAL",10,99,60;
+
+---------------------------------------
+
+*day;
+*night;
+
+These two commands will switch the entire server between day and night mode
+respectively. If your server is set to cycle between day and night by
+configuration, it will eventually return to that cycle.
+
+Example:
+
+- script DayNight -1,{
+OnClock0600:
+ day;
+ end;
+OnInit:
+ // setting correct mode upon server start-up
+ if(gettime(3)>=6 && gettime(3)<18) end;
+OnClock1800:
+ night;
+ end;
+}
+
+This script allows to emulate the day/night cycle as the server does, but also
+allows triggering additional effects upon change, like announces, gifts, etc.
+The day/night cycle set by configuration should be disabled when this script is used.
+
+---------------------------------------
+
+*defpattern <set number>,"<regular expression pattern>","<event label>";
+*activatepset <set number>;
+*deactivatepset <set number>;
+*deletepset <set number>;
+
+This set of commands is only available if the server is compiled with regular
+expressions library enabled. Default compilation and most binary distributions
+aren't, which is probably bad, since these, while complex to use, are quite
+fascinating.
+
+They will make the NPC object listen for text spoken publicly by players and
+match it against regular expression patterns, then trigger labels associated
+with these regular expression patterns.
+
+Patterns are organized into sets, which are referred to by a set number. You can
+have multiple sets patterns, and multiple patterns may be active at once.
+Numbers for pattern sets start at 1.
+
+'defpattern' will associate a given regular expression pattern with an event
+label. This event will be triggered whenever something a player says is matched
+by this regular expression pattern, if the pattern is currently active.
+
+'activatepset' will make the pattern set specified active. An active pattern
+will enable triggering labels defined with 'defpattern', which will not happen
+by default.
+'deactivatepset' will deactivate a specified pattern set. Giving -1 as a pattern
+set number in this case will deactivate all pattern sets defined.
+
+'deletepset' will delete a pattern set from memory, so you can create a new
+pattern set in its place.
+
+Using regular expressions is high wizardry. But with this high wizardry comes
+unparalleled power of text manipulation. For an explanation of what a regular
+expression pattern is, see a few web pages:
+
+http://www.regular-expressions.info/
+http://www.weitz.de/regex-coach/
+
+For an example of this in use, see doc/sample/npc_test_pcre.txt
+
+With this you could, for example, automatically punish players for asking for
+Zeny in public places, or alternatively, automatically give them Zeny instead if
+they want it so much.
+
+---------------------------------------
+
+*pow(<number>,<power>)
+
+Returns the result of the calculation.
+
+Example:
+set @i, pow(2,3); // @i will be 8
+
+---------------------------------------
+
+*sqrt(<number>)
+
+Returns square-root of number.
+
+Example:
+set @i, sqrt(25); // @i will be 5
+
+---------------------------------------
+
+*distance(<x0>,<y0>,<x1>,<y1>)
+
+Returns distance between 2 points.
+
+Example:
+set @i, distance(100,200,101,202);
+
+---------------------------------------
+
+*md5("<string>")
+
+Returns the md5 checksum of a number or string.
+
+Example:
+ mes md5(12345);
+ mes md5("12345"); // Will both display 827ccb0eea8a706c4c34a16891f84e7b
+ mes md5("qwerty"); // Will display d8578edf8458ce06fbc5bb76a58c5ca4
+
+---------------------------------------
+
+*query_sql("your MySQL query"{, <array variable>{, <array variable>{, ...}}});
+*query_logsql("your MySQL query"{, <array variable>{, <array variable>{, ...}}});
+
+Executes an SQL query. A 'select' query can fill array variables with up to 128 rows of values,
+and will return the number of rows (i.e. array size).
+
+Note that 'query_sql' runs on the main database while 'query_logsql' runs on the log database.
+
+Example:
+set @nb, query_sql("select name,fame from `char` ORDER BY fame DESC LIMIT 5", @name$, @fame);
+mes "Hall Of Fame: TOP5";
+mes "1."+@name$[0]+"("+@fame[0]+")"; // Will return a person with the biggest fame value.
+mes "2."+@name$[1]+"("+@fame[1]+")";
+mes "3."+@name$[2]+"("+@fame[2]+")";
+mes "4."+@name$[3]+"("+@fame[3]+")";
+mes "5."+@name$[4]+"("+@fame[4]+")";
+
+---------------------------------------
+
+*escape_sql(<value>)
+
+Converts the value to a string and escapes special characters so that it is safe to use in query_sql().
+Returns the escaped form of the given value.
+
+Example:
+ set .@str$, "John's Laptop";
+ set .@esc_str$, escape_sql(.@name$); // Escaped string: John\'s Laptop
+
+---------------------------------------
+
+*setiteminfo(<item id>,<type>,<value>)
+
+This function will set some value of an item.
+Returns the new value on success, or -1 on fail (item_id not found or invalid type).
+
+Valid types are:
+ 0 - Buy Price; 1 - Sell Price; 2 - Item Type;
+ 3 - maxchance (Max drop chance of this item e.g. 1 = 0.01% , etc..
+ if = 0, then monsters don't drop it at all (rare or a quest item)
+ if = 10000, then this item is sold in NPC shops only
+ 4 - sex; 5 - equip; 6 - weight; 7 - atk; 8 - def; 9 - range;
+ 10 - slot; 11 - look; 12 - elv; 13 - wlv; 14 - view id
+
+Example:
+
+setiteminfo 7049,6,9990; // Stone now weighs 999.0
+
+---------------------------------------
+
+*setitemscript(<item id>,<"{ new item script }">{,<type>});
+
+Set a new script bonus to the Item. Very useful for game events.
+You can remove an item's itemscript by leaving the itemscript argument empty.
+Returns 1 on success, or 0 on fail (item_id not found or new item script is invalid).
+Type can optionally be used indicates which script to set (default is 0):
+ 0 - Script
+ 1 - OnEquip_Script
+ 2 - OnUnequip_Script
+
+Example:
+
+setitemscript 2637,"{ if(isequipped(2236)==0)end; if(getskilllv(26)){skill 40,1;}else{skill 26,1+isequipped(2636);} }";
+setitemscript 2637,"";
+
+---------------------------------------
+
+*atoi ("<string>")
+*axtoi ("<string>")
+
+These commands are used to convert strings to numbers. 'atoi' will interpret
+given string as a decimal number (base 10), while 'axtoi' interprets strings as
+hexadecimal numbers (base 16).
+
+Hexadecimal number set: {0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F}
+
+Example:
+
+set @var, atoi("11"); // Sets @var to 11
+set @var, axtoi("FF"); // Sets @var to 255
+mes axtoi("11"); // Displays 17 (1 = 1, 10 = 16)
+
+---------------------------------------
+
+*compare(<string>,<substring>)
+
+This command returns 1 or 0 when the substring is in the main string (1) or not (0).
+This command is not case sensitive.
+
+Examples:
+
+//dothis; will be executed ('Bloody Murderer' contains 'Blood').
+ if (compare("Bloody Murderer","Blood"))
+ dothis;
+//dothat; will not be executed ('Blood butterfly' does not contain 'Bloody').
+ if (compare("Blood Butterfly","Bloody"))
+ dothat;
+
+---------------------------------------
+
+*getstrlen("<string>")
+
+This function will return the length of the string given as an argument. It is
+useful to check if anything input by the player exceeds name length limits and
+other length limits and asking them to try to input something else.
+
+---------------------------------------
+
+*charisalpha("<string>",<position>)
+
+This function will return 1 if the character number Position in the given string
+is a letter, 0 if it isn't a letter but a digit or a space.
+The first letter is position 0.
+
+---------------------------------------
+
+*charat(<string>,<index>)
+
+Returns char at specified index. If index is out of range, returns empty string.
+
+Example:
+
+ charat("This is a string", 10); //returns "s"
+
+---------------------------------------
+
+*setchar(<string>,<char>,<index>)
+
+Returns the original string with the char at the specified index set to the
+specified char. If index out of range, the original string will be returned.
+Only the 1st char in the <char> parameter will be used.
+
+Example:
+
+ setchar("Cat", "B", 0); //returns "Bat"
+
+---------------------------------------
+
+*insertchar(<string>,<char>,<index>)
+
+Returns the original string with the specified char inserted at the specified
+index. If index is out of range, the char will be inserted on the end of the
+string that it is closest. Only the 1st char in the <char> parameter will be used.
+
+Example:
+
+ insertchar("laughter", "s", 0); //returns "slaughter"
+
+---------------------------------------
+
+*delchar(<string>,<index>)
+
+Returns the original string with the char at the specified index removed.
+If index is out of range, original string will be returned.
+
+Example:
+
+ delchar("Diet", 3); //returns "Die"
+
+---------------------------------------
+
+*strtoupper(<string>)
+*strtolower(<string>)
+
+Returns the specified string in it's uppercase/lowercase form.
+All non-alpha characters will be preserved.
+
+Example:
+
+ strtoupper("The duck is blue!!"); //returns "THE DUCK IS BLUE!!"
+
+---------------------------------------
+
+*charisupper(<string>,<index>)
+*charislower(<string>,<index>)
+
+Returns 1 if character at specified index of specified string is
+uppercase/lowercase. Otherwise, 0. Characters not of the alphabelt will return 0.
+
+Example:
+
+ charisupper("rAthena", 1); //returns 1
+
+---------------------------------------
+
+*substr(<string>,<start_index>,<end_index>)
+
+Returns the sub-string of the specified string inclusively between the set
+indexes. If indexes are out of range, or the start index is after the end
+index, an empty string will be returned.
+
+Example:
+
+ substr("foobar", 3, 5); //returns "bar"
+
+---------------------------------------
+
+*explode(<dest_array>,<string>,<delimiter>)
+
+Breaks a string up into substrings based on the specified delimiter. Substrings
+will be stored within the specified string array. Only the 1st char of the
+delimiter parameter will be used. If an empty string is passed as a delimiter,
+the string will be placed in the array in it's original form.
+
+Example:
+
+ explode(.@my_array$, "Explode:Test:1965:red:PIE", ":");
+ //.@my_array$ contents will be...
+ //.@my_array$[0]: "Explode"
+ //.@my_array$[1]: "Test"
+ //.@my_array$[2]: "1965"
+ //.@my_array$[3]: "red"
+ //.@my_array$[4]: "PIE"
+
+---------------------------------------
+
+*implode(<string_array>{,<glue>})
+
+Combines all substrings within the specified string array into a single string.
+If the glue parameter is specified, it will be inserted inbetween each substring.
+
+Example:
+ setarray .@my_array$[0], "This", "is", "a", "test";
+ implode(.@my_array$, " "); //returns "This is a test"
+
+---------------------------------------
+
+*sprintf(<format>[,param[,param[,...]]]) [Mirei]
+
+C style sprintf. The resulting string is returned same as in PHP. All C format
+specifiers are supported except %n. More info: sprintf @ www.cplusplus.com.
+The number of params is only limited by rA's script engine.
+
+Example:
+ .@format$ = 'The %s contains %d monkeys';
+ dispbottom(sprintf(.@format$, "zoo", 5)); //prints "The zoo contains 5 monkeys"
+ dispbottom(sprintf(.@format$, "barrel", 82)); //prints "The barrel contains 82 monkeys"
+
+---------------------------------------
+
+*sscanf(<string>,<format>[,param[,param[,...]]]) [Mirei]
+
+C style sscanf. All C format specifiers are supported.
+More info: sscanf @ www.cplusplus.com. The number of params is only limited
+by rA's script engine.
+
+Example:
+ sscanf("This is a test: 42 foobar", "This is a test: %d %s", .@num, .@str$);
+ dispbottom(.@num + " " + .@str$); //prints "42 foobar"
+
+---------------------------------------
+
+*strpos(<haystack>,<needle>{,<offset>})
+
+PHP style strpos. Finds a substring (needle) within a string (haystack).
+The offset parameter indicates the index of the string to start searching.
+Returns index of substring on successful search, else -1.
+Comparison is case sensitive.
+
+Example:
+ strpos("foobar", "bar", 0); //returns 3
+ strpos("foobarfoo", "foo", 0); //returns 0
+ strpos("foobarfoo", "foo", 1); //returns 6
+
+---------------------------------------
+
+*replacestr(<input>, <search>, <replace>{, <usecase>{, <count>}})
+
+Replaces all instances of a search string in the input with the specified
+replacement string. By default is case sensitive unless <usecase> is set
+to 0. If specified it will only replace as many instances as specified
+in the count parameter.
+
+Example:
+ replacestr("testing tester", "test", "dash"); //returns "dashing dasher"
+ replacestr("Donkey", "don", "mon", 0); //returns "monkey"
+ replacestr("test test test test test", "yay", 0, 3); //returns "yay yay yay test test"
+
+---------------------------------------
+
+*countstr(<input>, <search>{, <usecase>})
+
+Counts all instances of a search string in the input. By default is case
+sensitive unless <usecase> is set to 0.
+
+Example:
+ countstr("test test test Test", "test"); //returns 3
+ countstr("cake Cake", "Cake", 0); //returns 2
+
+---------------------------------------
+
+*setfont <font>;
+
+This command sets the current RO client interface font to one of the
+fonts stored in data\*.eot by using an ID of the font. When the ID
+of the currently used font is used, default interface font is used
+again.
+
+ 0 - Default
+ 1 - RixLoveangel
+ 2 - RixSquirrel
+ 3 - NHCgogo
+ 4 - RixDiary
+ 5 - RixMiniHeart
+ 6 - RixFreshman
+ 7 - RixKid
+ 8 - RixMagic
+ 9 - RixJJangu
+
+---------------------------------------
+
+*showdigit <value>{,<type>};
+
+Displays given numeric 'value' in large digital clock font on top of
+the screen. The optional parameter 'type' specifies visual aspects
+of the "clock" and can be one of the following values:
+
+ 0 - Displays the value for 5 seconds (default).
+ 1 - Incremental counter (1 tick/second).
+ 2 - Decremental counter (1 tick/second). Does not stop at zero,
+ but overflows.
+ 3 - Decremental counter (1 tick/second). Two digits only, stops
+ at zero.
+
+For type 1 and 2 the start value is set by using negative number of
+the one intended to set (ex. -10 starts the counter at 10 seconds).
+Except for type 3 the value is interpreted as seconds and formatted
+as time in days, hours, minutes and seconds. Note, that the official
+script command does not have the optional parameter.
+
+ // displays 23:59:59 for 5 seconds
+ showdigit 86399;
+
+ // counter that starts at 60 and runs for 60 seconds
+ showdigit 60,3;
+
+---------------------------------------
+
+* The Pet AI commands
+
+These commands will only work if the invoking character has a pet, and are meant
+to be executed from pet scripts. They will modify the pet AI decision-making for
+the current pet of the invoking character, and will NOT have any independent
+effect by themselves, which is why only one of them each may be in effect at any
+time for a specific pet. A pet may have 'petloot', 'petskillbonus',
+'petskillattack' OR 'petpetskillattack2' and 'petskillsupport' OR 'petheal' at
+the same time. 'petheal' is deprecated and is no longer used in the default pet
+scripts.
+
+*petskillbonus <bonus type>,<value>,<duration>,<delay>;
+
+This command will make the pet give a bonus to the owner's stat (bonus type -
+bInt,bVit,bDex,bAgi,bLuk,bStr,bSpeedRate - for a full list, see the values
+starting with 'b' in 'db/const.txt')
+
+*petrecovery <status type>,<delay>;
+
+This command will make the pet cure a specified status condition. The curing
+actions will occur once every Delay seconds. For a full list of status
+conditions that can be cured, see the list of 'SC_' status condition constants
+in 'db/const.txt'
+
+*petloot <max items>;
+
+This command will turn on pet looting, with a maximum number of items to loot
+specified. Pet will store items and return them when the maximum is reached or
+when pet performance is activated.
+
+*petskillsupport <skill id>,<skill level>,<delay>,<percent hp>,<percent sp>;
+*petskillsupport "<skill name>",<skill level>,<delay>,<percent hp>,<percent sp>;
+*petheal <level>,<delay>,<percent hp>,<percent sp>;
+
+This will make the pet use a specified support skill on the owner whenever the
+HP and SP are below the given percent values, with a specified delay time
+between activations. The skill numbers are as per 'db/(pre-)re/skill_db.txt'.
+'petheal' works the same as 'petskillsupport' but has the skill ID hard-coded to
+28 (Heal). This command is deprecated.
+It's not quite certain who's stats will be used for the skills cast, the
+character's or the pets. Probably, Skotlex can answer that question.
+
+*petskillattack <skill id>,<skill level>,<rate>,<bonusrate>;
+*petskillattack "<skill name>",<skill level>,<rate>,<bonusrate>;
+*petskillattack2 <skill id>,<damage>,<number of attacks>,<rate>,<bonusrate>;
+*petskillattack2 "<skill name>",<damage>,<number of attacks>,<rate>,<bonusrate>;
+
+These two commands will make the pet cast an attack skill on the enemy the pet's
+owner is currently fighting. Skill IDs and levels are as per 'petskillsupport'.
+'petskillattack2' will make the pet cast the skill with a fixed amount of damage
+inflicted and the specified number of attacks.
+
+All commands with delays and durations will only make the behavior active for
+the specified duration of seconds, with a delay of the specified number of
+seconds between activations. Rates are a chance of the effect occurring and are
+given in percent. 'bonusrate' is added to the normal rate if the pet intimacy is
+at the maximum possible.
+
+The behavior modified with the above mentioned commands will only be exhibited if
+the pet is loyal and appropriate configuration options are set in
+'battle_athena.conf'.
+
+Pet scripts in the database normally run whenever a pet of that type hatches
+from the egg. Other commands usable in item scripts (see 'bonus') will also
+happily run from pet scripts. Apparently, the pet-specific commands will also
+work in NPC scripts and modify the behavior of the current pet up until the pet
+is hatched again. (Which will also occur when the character is logged in again
+with the pet still out of the egg.) It is not certain for how long the effect of
+such command running from an NPC script will eventually persist, but apparently,
+it is possible to usefully employ them in usable item scripts to create pet
+buffing items.
+
+Nobody tried this before, so you're essentially on your own here.
+
+---------------------------------------
+
+*bpet;
+
+This command opens up a pet hatching window on the client connected to the
+invoking character. It is used in item script for the pet incubators and will
+let the player hatch an owned egg. If the character has no eggs, it will just
+open up an empty incubator window.
+This is still usable outside item scripts.
+
+---------------------------------------
+
+*makepet <pet id>;
+
+This command will create a pet egg and put it in the invoking character's
+inventory. The kind of pet is specified by pet ID numbers listed in
+'db/pet_db.txt'. The egg is created exactly as if the character just successfully
+caught a pet in the normal way.
+
+ // This will make you a poring:
+ makepet 1002;
+
+Notice that you absolutely have to create pet eggs with this command. If you try
+to give a pet egg with 'getitem', pet data will not be created by the char
+server and the egg will disappear when anyone tries to hatch it.
+
+---------------------------------------
+
+*homshuffle;
+
+This will recalculate the homunculus stats according to its level, of the
+current invoking character.
+
+---------------------------------------
+
+*setcell "<map name>",<x1>,<y1>,<x2>,<y2>,<type>,<flag>;
+
+Each map cell has several 'flags' that specify the properties of that cell.
+These include terrain properties (walkability, shootability, presence of water),
+skills (basilica, land protector, ...) and other (NPC nearby, no vending, ...).
+Each of these can be 'on' or 'off'. Together they define a cell's behavior.
+
+This command lets you alter these flags for all map cells in the specified
+(x1,y1)-(x2,y2) rectangle. The 'flag' can be 0 or 1 (0:clear flag, 1:set flag).
+The 'type' defines which flag to modify. Possible options include cell_walkable,
+cell_shootable, cell_basilica. For a full list, see const.txt.
+
+Example:
+
+ setcell "arena",0,0,300,300,cell_basilica,1;
+ setcell "arena",140,140,160,160,cell_basilica,0;
+ setcell "arena",135,135,165,165,cell_walkable,0;
+ setcell "arena",140,140,160,160,cell_walkable,1;
+
+This will add a makeshift ring into the center of the map. The ring will be
+surrounded by a 5-cell wide 'gap' to prevent interference from outside, and
+the rest of the map will be marked as 'basilica', preventing observers from
+casting any offensive skills or fighting among themselves. Note that the wall
+will not be shown nor known client-side, which may cause movement problems.
+
+Another example:
+
+OnBarricadeDeploy:
+ setcell "schg_cas05",114,51,125,51,cell_walkable,0;
+ end;
+OnBarricadeBreak:
+ setcell "schg_cas05",114,51,125,51,cell_walkable,1;
+ end;
+
+This could be a part of the WoE:SE script, where attackers are not allowed
+to proceed until all barricades are destroyed. This script would place and
+remove a nonwalkable row of cells after the barricade mobs.
+
+---------------------------------------
+
+*checkcell ("<map name>",<x>,<y>,<type>);
+
+This command will return 1 or 0, depending on whether the specified cell has
+the 'type' flag set or not. There are various types to check, all mimicking
+the server's cell_chk enumeration. The types can be found in db/const.txt.
+
+The meaning of the individual types can be confusing, so here's an overview:
+ - cell_chkwall/water/cliff
+ these check directly for the 'terrain component' of the specified cell
+ - cell_chkpass/reach/nopass/noreach
+ passable = not wall & not cliff, reachable = passable wrt. no-stacking mod
+ - cell_chknpc/basilica/landprotector/novending/nochat
+ these check for specific dynamic flags (their name indicates what they do)
+
+Example:
+
+ mes "Pick a destination map.";
+ input .@map$;
+ mes "Alright, now give me the coordinates.";
+ input .@x;
+ input .@y;
+ if( !checkcell(.@map$,.@x,.@y,cell_chkpass) )
+ {
+ mes "Can't warp you there, sorry!";
+ close;
+ }
+ else
+ {
+ mes "Ok, get ready...";
+ close2;
+ warp .@map$, .@x, .@y;
+ end;
+ }
+
+---------------------------------------
+
+*setwall "<map name>",<x>,<y>,<size>,<dir>,<shootable>,"<name>";
+*delwall "<name>";
+
+Creates an invisible wall, an array of "setcell" starting from x,y and doing a
+line of the given size in the given direction. The difference with setcell is
+this one update client part too to avoid the glitch problem. Directions are the
+same as NPC sprite facing directions: 0=north, 1=northwest, 2=west, etc.
+
+---------------------------------------
+
+*readbook <book id>,<page>;
+
+This will open a book item at the specified page
+
+---------------------------------------
+
+========================
+|7.- Instance commands.|
+========================
+---------------------------------------
+
+*instance_create("<instance name>",<party id>);
+
+Create an instance using the name "<instance name>" for the Party of <party id>.
+Most instance_* commands are used in conjunction with this command and depend
+on the ID this command returns.
+
+Example:
+ // Store the Party ID of the invoking character.
+ set .@party_id, getcharid(1);
+
+ // Attempt to create an instance using that party ID.
+ set .@id, instance_create("Endless Tower", .@party_id);
+ if (.@id == -1) { // Invalid type - not used anymore
+ ...
+ }
+ else if (.@id == -2) { // Invalid Party ID
+ ...
+ }
+ else if (.@id == -3) { // No free instances (MAX_INSTANCE exceeded)
+ ...
+ }
+ else if (.@id == -4) { // Already exists
+ ...
+ }
+ else (.@id < 0) { // Unspecified error while queuing instance.
+ ...
+ }
+
+---------------------------------------
+
+*instance_destroy {<instance id>};
+
+Destroys instance with the ID <instance id>. If no ID is specified, the instance
+the script is attached to is used. If the script is not attached to an instance,
+the instance of the currently attached player's party is used. If no player is
+currently attached, the command fails and causes the script to halt.
+
+---------------------------------------
+
+*instance_attachmap("<map name>",<instance id>{,<use base name>});
+
+Attaches the map "<map name>" to the instance specified with <instance id>. The
+optional parameter specifies, whether a map requires emulation for instancing (1)
+or not (0 = default).
+
+Returns the resulting map name on success or an empty string on failure.
+
+---------------------------------------
+
+*instance_detachmap "<map name>"{,<instance id>};
+
+Detach the map "<map name>" to the instance with the <instance id>. If no ID is
+specified, the instance the script is attached to is used. If the script is not
+attached to an instance, the instance of the currently attached player's party is
+used. If no player is currently attached, the command fails and causes the script
+to halt.
+
+---------------------------------------
+
+*instance_init <instance id>;
+
+Initializes the instance given by <instance id>. This copies all NPCs from the
+source maps to the instanced maps.
+
+---------------------------------------
+
+*instance_announce <instance id>,"<text>",<flag>{,<fontColor>{,<fontType>{,<fontSize>{,<fontAlign>{,<fontY>}}}}};
+
+Works like announce, but has the <instance id> parameter. If instance id is 0, the
+instance the script is attached to is used. If the script is not attached to an
+instance, the instance of the currently attached player's party is used. If no
+player is currently attached, the command fails and causes the script to halt.
+
+---------------------------------------
+
+*instance_attach <instance id>;
+
+Attaches the current script to the instance given by <instance id>.
+
+---------------------------------------
+
+*instance_npcname("<npc name>"{,<instance id>});
+
+Retrieves the unique name given to a copy of an NPC given by "<npc name>" in an
+instance specified <instance id>. If no ID is specified, the instance the script
+is attached to is used. If the script is not attached to an instance, the
+instance of the currently attached player's party is used. If no player is
+currently attached, the command fails and causes the script to halt.
+
+---------------------------------------
+
+*has_instance("<map name>"{,<instance id>});
+
+Checks whether or not the given map belongs to specified instance. If no ID is
+specified, the instance the script is attached to is used. If the script is not
+attached to an instance, the instance of the currently attached player's party
+is used. If no player is currently attached, the command fails and causes the
+script to halt.
+
+Returns the name of the instanced map on success, otherwise an empty string.
+
+---------------------------------------
+
+*instance_id({<type>});
+
+Retrieves the instance id, depending on <type>. If type is not given, it defaults
+to 0.
+
+Type:
+ 0 - Instance ID the script is attached to.
+ 1 - Instance ID of the currently attached player's party.
+
+---------------------------------------
+
+*instance_warpall "<map name>",<x>,<y>{,<instance id>};
+
+Warps all players in the instance <instance id> to <map name> at given
+coordinates. If no ID is specified, the instance the script is attached to
+is used. If the script is not attached to an instance, the instance of the
+currently attached player's party is used. If no player is currently attached,
+the command fails and causes the script to halt.
+
+---------------------------------------
+
+*instance_set_timeout <alive timeout>,<idle timeout>{,<instance id>};
+
+Sets the timeout values for an instance given by <instance id>. If no ID is
+specified, the instance the script is attached to is used. If the script is
+not attached to an instance, the instance of the currently attached player's
+party is used. If no player is currently attached, the command fails and causes
+the script to halt.
+
+Parameter <alive timeout> specifies the total amount of time the instance will
+exist. Parameter <idle timeout> specifies how long players have, when they are
+outside of the instance, until it is destroyed.
+
+Both timeout values are in seconds.
+
+---------------------------------------
+
+*instance_check_party(<party id>{,<amount>{,<min>{,<max>}}});
+
+This function checks if a party meets certain requirements, returning 1 if all
+conditions are met and 0 otherwise. It will only check online characters.
+
+amount - number of online party members (default is 1).
+min - minimum level of all characters in the party (default is 1).
+max - maximum level of all characters in the party (default is max level in conf).
+
+Example:
+
+if (instance_check_party(getcharid(1),2,2,149)) {
+ mes "Your party meets the Memorial Dungeon requirements.",
+ mes "All online members are between levels 1-150 and at least two are online.";
+ close;
+} else {
+ mes "Sorry, your party does not meet requirements.";
+ close;
+}
+
+---------------------------------------
+
+=========================
+|8.- Quest Log commands.|
+=========================
+---------------------------------------
+
+*setquest <ID>;
+
+Place quest of <ID> in the users quest log, the state of which is "active".
+
+---------------------------------------
+
+*completequest <ID>;
+
+Change the state for the given quest <ID> to "complete" and remove from the users quest log.
+
+---------------------------------------
+
+*erasequest <ID>;
+
+Remove the quest of the given <ID> from the user's quest log.
+
+---------------------------------------
+
+*changequest <ID>,<ID2>;
+
+Remove quest of the given <ID> from the user's quest log.
+Add quest of the <ID2> to the the quest log, and the state is "active".
+
+---------------------------------------
+
+*checkquest(<ID>{,PLAYTIME|HUNTING})
+
+If no additional argument supplied, return the state of the quest:
+ -1 = Quest not started (not in quest log)
+ 0 = Quest has been given, but the state is "inactive"
+ 1 = Quest has been given, and the state is "active"
+ 2 = Quest completed
+
+If parameter "PLAYTIME" is supplied:
+ -1 = Quest not started (not in quest log)
+ 0 = the time limit has not yet been reached
+ 1 = the time limit has not been reached but the quest is marked as complete
+ 2 = the time limit has been reached
+
+If parameter "HUNTING" is supplied:
+ -1 = Quest not started (not in quest log)
+ 0 = you haven't killed all of the target monsters and the time limit has not been reached.
+ 1 = you haven't killed all of the target monsters but the time limit has been reached.
+ 2 = you've killed all of the target monsters
+
+---------------------------------------
+
+*showevent <state>, <color>;
+
+Show a colored mark in the mini-map like "viewpoint" and an emotion on top of a NPC.
+This is used to indicate that a NPC has a quest or an event to certain player/s.
+
+state can be:
+ 0 = disable ( Used to disable and remove the mark and the emotion from the NPC. )
+ 1 = exclamation emotion ( Used to show an important quest event to certain player. )
+ 2 = interrogation emotion ( Used to show an non-important quest event to certain player. )
+ Other value may cause client crashes.
+
+color can be:
+ 0 = yellow "Quest"
+ 1 = orange "Job"
+ 2 = green "Event"
+ 3 = an MVP flag
+ other values show a transparent mark in the mini-map.
+
+----------------------------------------
+
+============================
+|9.- Battleground commands.|
+============================
+---------------------------------------
+
+*waitingroom2bg_single(<battle group>,"<mapname>",<x>,<y>,"<npc name>");
+
+Adds the first waiting player from the chat room of given NPC to an
+existing battleground group and warps it to specified coordinates on
+given map.
+
+---------------------------------------
+
+*waitingroom2bg("<mapname>",<x>,<y>,"<On Quit Event>","<On Death Event>"{,"<npc name>"});
+
+<Mapname> and X Y coordinates refer to where the "respawn" base is, where the player group will respawn when they die.
+<On Quit Event> refers to an NPC label that attaches to the character and is run when they relog.
+<On Death Event> refers to an NPC label that attaches to the character and is run when they die. Can be "" for empty.
+
+Unlike the prior command, the latter will attach a GROUP in a waiting room to the battleground, and
+sets the array $@arenamembers[0] where 0 holds the IDs of the first group, and 1 holds the IDs of the second.
+
+If the option parameter is left out, the waiting room of the current NPC is used.
+
+Example:
+ // Battle Group will be referred to as $@KvM01BG_id1, and when they die, respawn at bat_c01,52,129.
+ set $@KvM01BG_id1, waitingroom2bg("bat_c01",52,129,"KvM01_BG::OnGuillaumeQuit","KvM01_BG::OnGuillaumeDie");
+ end;
+
+----------------------------------------
+
+*bg_team_setxy <Battle Group ID>,<x>,<y>;
+
+Update the respawn point of the given battle group to x, y on the same map. The <Battle Group ID> can be retrieved using getcharid(4)
+
+Example:
+ bg_team_setxy getcharid(4),56,212;
+ mapannounce "bat_a01", "Group [1] has taken the work shop, and will now respawn there.",bc_map,"0xFFCE00";
+ end;
+
+----------------------------------------
+
+*bg_warp <Battle Group>,"<Mapname>",<x>,<y>;
+
+Similar to warp command.
+Place all members of <Battle Group> at <mapname> at x y.
+
+Example:
+ //place the battle group one for Tierra Gorge at starting position.
+ bg_warp $@TierraBG1_id1,"bat_a01",352,342;
+ end;
+
+----------------------------------------
+
+*bg_monster <Battle Group>,"<map name>",<x>,<y>,"<name to show>",<mob id>,"<event label>";
+*bg_monster(<Battle Group>,"<map name>",<x>,<y>,"<name to show>",<mob id>,"<event label>");
+
+Similar to monster script command.
+Spawn a monster with allegiance to the given battle group.
+Does not allow for the summoning of multiple monsters.
+Monsters are similar to that in War of Emperium, in that the specified Battle group is considered friendly.
+
+Example:
+ // It can be used in two different ways.
+ bg_monster $@TierraBG1_id2,"bat_a01",167,50,"Food Depot",1910,"Feed Depot#1::OnMyMobDead";
+ end;
+
+ // Alternatively, you can set an ID for the monster using "set".
+ // This becomes useful when used with the command below.
+ set $@Guardian_3, bg_monster($@TierraBG1_id2,"bat_a01",268,204,"Guardian",1949,"NPCNAME::OnMyMobDead");
+ end;
+
+----------------------------------------
+
+*bg_monster_set_team <GID>,<Battle Group>;
+
+This command will change the allegiance if a monster in a battle ground.
+GID can be set when spawning the monster via the bg_monster command.
+
+Example:
+
+ end;
+
+OnEnable:
+ mapannounce "A guardian has been summoned for Battle Group 2!",bc_map,"0xFFCE00";
+ set $@Guardian, bg_monster($@BG_2,"bat_a01",268,204,"Guardian",1949,"NPCNAME::OnMyMobDead");
+ initnpctimer;
+ end;
+
+OnTimer1000:
+ stopnpctimer;
+ mapannounce "Erm, sorry about that! This monster was meant for Battle Group 1.",bc_map,"0xFFCE00";
+ bg_monster_set_team $@Guardian, $@BG_1;
+ end;
+
+----------------------------------------
+
+*bg_leave;
+
+Removes attached player from their Battle Group.
+
+----------------------------------------
+
+*bg_destroy <Batte Group>;
+
+As the name says, destroys the battle group created for that battle ground.
+
+----------------------------------------
+
+*areapercentheal "<mapname>",<x1>,<y1>,<x2>,<y2>,<hp>,<sp>;
+
+Not exactly limited to battleground use, this will restore HP/SP in a defined area at a percentage.
+
+Example:
+ areapercentheal "bat_a01",52,208,61,217,100,100;
+ end;
+
+----------------------------------------
+
+*bg_get_data(<Battle Group>,<type>);
+
+Retrieves data related to given battle group. Type can be one of the following:
+
+ 0 - Amount of players currently belonging to the group.
+
+----------------------------------------
+
+*bg_getareausers(<battle group>,<map name>,<x0>,<y0>,<x1>,<y1>);
+
+Retrieves amount of players belonging to given battle group on given
+map within an specified rectangular area.
+
+----------------------------------------
+
+*bg_updatescore "<mapname>",<Guillaume Score>,<Croix Score>;
+
+This command will force the update of the displayed scoreboard.
+It is only usable when the map is defined as a Type 2 Battleground:
+mapflag <mapname> battleground 2
+
+----------------------------------------
+
+==========================
+|10.- Mercenary commands.|
+==========================
+---------------------------------------
+
+*mercenary_create <class>,<contract time>;
+
+This command summons a mercenary of given class, for given amount of
+time in milliseconds. Typically used in item scripts of mercenary
+scrolls.
+
+----------------------------------------
+
+*mercenary_heal <hp>,<sp>;
+
+This command works like 'heal', but affects the mercenary of the
+currently attached character.
+
+----------------------------------------
+
+*mercenary_sc_start <type>,<tick>,<val1>;
+
+This command works like 'sc_start', but affects the mercenary of the
+currently attached character.
+
+----------------------------------------
+
+*mercenary_get_calls(<guild>);
+*mercenary_set_calls <guild>,<value>;
+
+Sets or gets the mercenary calls value for given guild for currently
+attached character. Guild can be one or the following constants:
+
+ ARCH_MERC_GUILD
+ SPEAR_MERC_GUILD
+ SWORD_MERC_GUILD
+
+----------------------------------------
+
+*mercenary_get_faith(<guild>);
+*mercenary_set_faith <guild>,<value>;
+
+Sets or gets the mercenary faith value for given guild for currently
+attached character. Guild can be one or the following constants:
+
+ ARCH_MERC_GUILD
+ SPEAR_MERC_GUILD
+ SWORD_MERC_GUILD
+
+---------------------------------------
+
+*getmercinfo(<type>{,<char id>});
+
+Retrieves information about mercenary of the currently attached
+character. If char id is given, the information of that character is
+retrieved instead. Type specifies what information to retrieve and
+can be one of the following:
+
+ 0 - Database ID
+ 1 - Class
+ 2 - Name
+ 3 - Faith value for this mercenary's guild, if any
+ 4 - Calls value for this mercenary's guild, if any
+ 5 - Kill count
+ 6 - Remaining life time in msec
+ 7 - Level
+
+If the character does not have a mercenary, the command returns ""
+for name and 0 for all other types.
+
+----------------------------------------
+
+Whew.
+That's about all of them.