//===== rAthena Documentation================================ //= rAthena Script Commands //===== By:================================================== //= rAthena Dev Team //===== Last Updated:======================================== //= 20220308 //===== 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 rAthena. It is not a simple tutorial. When people tell you to "Read The F***ing Manual", they mean this. 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 possible, 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 script commands are listed in no particular order, but are grouped by relative function. *Name of the command and parameters (if any). 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 asterisk (*) followed by the command name, and it should find the command description for you. If you find anything missing, please let us know! Syntax ------ Throughout this document, wherever a command wants an argument, it is given in . 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 a command can optionally take an unspecified number of arguments, you'll see a list like this: command {,...} 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 'map name' (.gat suffix is deprecated). 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/(pre-)re/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: 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: 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 structure - create NPC objects, spawn monster objects, set map flags, etc. No code is actually executed at this point. The top-level commands are pretty confusing, since they aren't structured like you would expect (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. Here is a list of valid top-level commands: ** Set a map flag: %TAB%mapflag%TAB% This will, upon loading, set a specified map flag on a map you like. These are normally in files inside 'npc/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 in various situations. For more details, see 'setmapflag' and 'doc/mapflags.txt'. ** Create a permanent monster spawn: {,{,{,{,}}}}%TAB%monster%TAB%{,}%TAB%,{,{,{,{,{,}}}}} 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.yml' 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). 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. 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 1 second (See /conf/battle/monster.conf::mob_respawn_time). 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. Natural enemies for AI monsters are normal monsters. can be: Size_Small (0) Size_Medium (1) Size_Large (2) can be: AI_NONE (0) (default) AI_ATTACK (1) (attack/friendly) AI_SPHERE (2) (Alchemist skill) AI_FLORA (3) (Alchemist skill) AI_ZANZOU (4) (Kagerou/Oboro skill) AI_LEGION (5) (Sera skill) AI_FAW (6) (Mechanic skill) AI_WAVEMODE (7) Normal monsters will ignore attack from AI_WAVEMODE monsters 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: {::} All NPCs need to have a unique name that is used for identification purposes. When you have to identify a NPC by its name, you should use . If is not provided, use 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' must be at most 24 characters in length. must be at most 24 characters in length. ** Define a warp point ,,,%TAB%warp%TAB%%TAB%,,,, ,,,%TAB%warp2%TAB%%TAB%,,,, ,,,%TAB%warp()%TAB%%TAB%,,,, ,,,%TAB%warp2()%TAB%%TAB%,,,, 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. Unlike 'warp', 'warp2' will also be triggered by hidden player. The basic state of the warp can be defined in . Only one state can be defined at a time. Duplicate warps (including instance warps) inherit the of the original warp. Valid are: CLOAKED Make the warp specified cloaked. HIDDEN Make the warp specified hidden. DISABLED Make the warp specified disabled. ** Define an NPC object. ,,,%TAB%script%TAB%%TAB%,{} ,,,%TAB%script%TAB%%TAB%,,,{} ,,,%TAB%script()%TAB%%TAB%,{} ,,,%TAB%script()%TAB%%TAB%,,,{} 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.) works like the warp defined above, but for NPCs. Sprite ID is the sprite number or constant used to display this particular NPC. You may also use a monster's ID 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.yml', 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. Example of how works: // Define a cloaked NPC : lighthalzen,306,267,5 script Skia#ep162_04 4_EP16_SKIA,{ //... end; OnInit: cloakonnpc(); end; } // Another way to define a cloaked NPC using : lighthalzen,306,267,5 script(CLOAKED) Skia#ep162_04 4_EP16_SKIA,{ //... end; } ** Define a 'floating' NPC object. -%TAB%script%TAB%%TAB%-1,{} 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/itemshop/pointshop NPC. -%TAB%shop%TAB%%TAB%{,discount},:{,:...} ,,,%TAB%shop%TAB%%TAB%{,discount},:{,:...} -%TAB%cashshop%TAB%%TAB%,:{,:...} ,,,%TAB%cashshop%TAB%%TAB%,:{,:...} -%TAB%itemshop%TAB%%TAB%,{:},:{,:...} ,,,%TAB%itemshop%TAB%%TAB%,{:},:{,:...} -%TAB%pointshop%TAB%%TAB%,{:},:{,:...} ,,,%TAB%pointshop%TAB%%TAB%,{:},:{,:...} ,,,%TAB%marketshop%TAB%%TAB%,::{,::...} Note: Additionally barter shops can be defined in npc/barters.yml 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. The Item ID is the number of item in the 'db/item_db.yml' 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. Optionally you can specify the discount option and set it to "yes" or "no", to enable or disable discounting. There are other types of shops available: cashshop - use "cashshop" in place of "shop" to use the Cash Shop interface, allowing you to buy items with special points that are stored as account variables called #CASHPOINTS and #KAFRAPOINTS. This type of shop will not allow you to sell items at it, only make purchases. The layout used to define sale items still count, and "" refers to how many points will be spent purchasing the them. "itemshop" and "pointshop" use the Shop interface, allowing you to buy items with a specific item or special points from a variable. 'pointshop' only supports permanent character variables, temporary character variables, permanent local account variables or permanent global account variables. These variables must be of integer type, not string. 'discount' flag is an optional value which makes the price at that shop become affected by discount skill. "marketshop" can have limited quantity of an item in stock. Use -1 in the stock field to have unlimited stock in a marketshop. ** Define an warp/shop/cashshop/itemshop/pointshop/NPC duplicate. warp/warp2: ,,,%TAB%duplicate(