diff options
Diffstat (limited to 'doc/script_commands.txt')
-rw-r--r-- | doc/script_commands.txt | 7752 |
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. |