
* menu/select/prompt script functions support grouped and empty options. The selected option number is consistent with them. * More work on ticket #41. git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@10316 54d463be-8e91-2dee-dedb-b68131a5f0ec
6025 lines
224 KiB
Plaintext
6025 lines
224 KiB
Plaintext
//===== Athena Doc ========================================
|
||
//= eAthena Script Commands
|
||
//===== By ================================================
|
||
//= Fredzilla
|
||
//===== Helped By =========================================
|
||
//= Terminal Vertex & Z3R0 - Helped define getmapxy
|
||
//= HappyDenn - Gave everything to do with getpartymember
|
||
//= a great help
|
||
//= Maeki Rika - A section on general concepts and lots of
|
||
//= other updates and additions.
|
||
//===== Version ===========================================
|
||
//= 3.05.20070423
|
||
//=========================================================
|
||
//= 1.0 - First release, filled will as much info as I could
|
||
//= remember or figure out, most likely there are errors,
|
||
//= and things I have missed out
|
||
//= 1.1 - Added better discription for "getmapxy"
|
||
//= 1.2b- Added a description for getpartymember
|
||
//= (+few spelling mistakes corrected)
|
||
//= 2.0 - +79kb extra stuff and numerous corrections by
|
||
//= Maeki Rika.
|
||
//= 2.1 - Small but important corrections, more proofreading.
|
||
//= Some important discoveries in item functions, the
|
||
//= secret of making VVS weapons with 'getitem2' and
|
||
//= other news. (Rika again) +10kb :)
|
||
//= 2.2 - added getItemInfo description [Lupus]
|
||
//= 2.3 - added plenty of info for recent (and not so) script commands I added
|
||
//= [Skotlex]
|
||
//= 2.4 - Explained the upper parameter of jobchange. [Skotlex]
|
||
//= 2.5 - Added pow, sqrt and distance. [Lance]
|
||
//= 2.6 - Added setd and getd. [Lance]
|
||
//= 2.7 - petstat command. [Lance]
|
||
//= 2.7a- delitem2, countitems2 commands [Lupus]
|
||
//= 2.7b- clone command [Skotlex]
|
||
//= 2.7c- disguise / undisguise, query_sql commands [Lupus]
|
||
//= 2.8 - Deleted a copy of the nude command. Added axtoi command (needing a
|
||
//= clearer explanation of atoi.Gave a better explanation of OnLabels
|
||
//= and modified monster explanation due that L_Label isn't working with
|
||
//= monster.
|
||
//= 2.9.20061230 - Updated getitem and guardian. [FlavioJS]
|
||
//= 2.10.20070101 - added sleep,sleep2,awake and updated the variables section.
|
||
//= [FlavioJS]
|
||
//= 2.11.20070109 - removed the unused flag argument in guildskill, added an
|
||
//= optional argument to setcart,setfalcon,setriding and other cleanups
|
||
//= [FlavioJS]
|
||
//= 2.12.20070201 - Added npcshopitem, npcshopadditem, npcshopdelitem and
|
||
//= npcshopattach [Skotlex]
|
||
//= 3.00.20070208
|
||
//= - Explained Logical Bitwise Operators.
|
||
//= Dj-Yhn contributed to AND (&) operator, rest by myself. [erKURITA]
|
||
//= - Added a resume of allowed variable and arrays scopes. [erKURITA]
|
||
//= - Re-organized the script commands, and grouped them depending
|
||
//= on what they do. [erKURITA]
|
||
//= - Added a packload of commands that were missing,
|
||
//= and corrected some of the wrong ones [Dj-Yhn, erKURITA & Trancid]
|
||
//= 3.01.20070209
|
||
//= Updated 'cutin' (removed lies, removed outdated bmp list) [ultramage]
|
||
//= Removed 'cutincard' since eA no longer implements it
|
||
//= 3.02.20070209
|
||
//= Corrected/updated info on Xor/setd/getd/callfunc/callsub/return and
|
||
//= updated some examples to use "better" code. [FlavioJS]
|
||
//= 3.03.20070216
|
||
//= Expanded/clarified information on npc timers, added info about the
|
||
//= new attach flag for script commands startnpctimer/ stopnpctimer/
|
||
//= initnpctimer [Skotlex]
|
||
//= 3.03.20070226
|
||
//= Updated makeitem and how to include " in strings [Lupus]
|
||
//= 3.03.20070228
|
||
//= Added info on OnTimerQuit label to npctimer section. [Skotlex]
|
||
//= 3.04.20070317
|
||
//= Removed all .gat refferences from the examples [Lupus]
|
||
//= 3.04.20070330
|
||
//= Adjusted the 'itemskill' description due to recent change [ultramage]
|
||
//= 3.04.20070409
|
||
//= Fixed the incorrect order of parameters in 'makeitem' [ultramage]
|
||
//= 3.05.20070423
|
||
//= menu/select/prompt produce consistent results for grouped and empty
|
||
//= options [FlavioJS]
|
||
//===== Description =======================================
|
||
//= A reference manual for the eAthena scripting language,
|
||
//= sorted out depending on their functionality.
|
||
//=========================================================
|
||
|
||
This document is a reference manual for all the scripting commands and functions
|
||
available in current eAthena 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 specifiled 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.
|
||
|
||
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>
|
||
|
||
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 diameters of a spawn-rectangle area who's center is 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 eAthena, 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).
|
||
|
||
If you add 20000 to the monster ID, the monster will be spawned in a 'big
|
||
version', (monster size class will increase) and if you add 10000, the 'tiny
|
||
version' of the monster will be created. However, this method is deprecated
|
||
and not recommended, as the values to add can change at a later time (20000
|
||
and 10000 actually stand for 2*MAX_MOB_DB and MAX_MOB_DB respectively, which
|
||
is defined on mob.h, and can change in the future as more mobs are created).
|
||
The recommended way to change a mob's size is to use the event-field (see
|
||
below).
|
||
|
||
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 are the monster respawn delays - the first one counts the time
|
||
since a monster defined in this spawn was last respawned and the second one
|
||
counts the time since the monster of this spawn was last killed. Whichever turns
|
||
out to be higher will be used. If the resulting number is smaller than a random
|
||
value between 5 and 10 seconds, this value will be used instead. (Which is
|
||
normally the case if both delay values are zero.) The times are given in
|
||
1/1000ths of a second.
|
||
|
||
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.
|
||
|
||
The Event field can be used alternatively to specify other mob properties. Use
|
||
2 to specify that the mob should be small, 4 for big monsters, and 8 for
|
||
special ai mobs (which by default attack other monsters instead of players).
|
||
You can add these, so using 10 will spawn small monsters that attack other
|
||
mobs (if you specify both 2 and 4, the small version takes priority).
|
||
|
||
** 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 for
|
||
another 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.
|
||
|
||
NPC name is kinda special, because it's not only the name of NPC you will see on
|
||
screen. It's formatted this way:
|
||
|
||
<Screen name>{#<Extra name identifier>}{::<Label name>}
|
||
|
||
The extra identifier is there that you can make an npc with an invisible name
|
||
(just omit the screen name, but keep the identifier name) and so that you can
|
||
refer to several NPCs which have the same name on screen, which is useful to
|
||
make an NPC that relocates depending on special conditions, for example - you
|
||
define several NPC objects and hide all except one.
|
||
('Hunter#hunter1','Hunter#hunter2'...) The extra name identifiers will let your
|
||
code tell them apart.
|
||
|
||
Label name is used to duplicate NPC objects (more on that below).
|
||
|
||
The complete NPC name (Screen name + extra identifier) may not exceed 24
|
||
characters. The label name is counted separately but also limited to 24
|
||
characters.
|
||
|
||
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 an NPC duplicate.
|
||
|
||
<map name>,<x>,<y>,<facing>%TAB%duplicate(<NPC label>)%TAB%<sprite id>
|
||
<map name>,<x>,<y>,<facing>%TAB%duplicate(<NPC label>)%TAB%<sprite id>,<triggerX>,<triggerY>
|
||
|
||
This will duplicate an NPC referred to by the label. The duplicate runs the same
|
||
code as the NPC it refers to, but may have different location, facing and sprite
|
||
ID. Whether it may actually have it's own size of trigger area is unclear at the
|
||
moment - if you need that, try it and tell us of the results.
|
||
|
||
** 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 NPC.
|
||
|
||
<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.
|
||
|
||
** 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.
|
||
|
||
** Alter a map cell
|
||
|
||
<map name>%TAB%setcell%TAB%<type>,<x1>,<y1>,<x2>,<y2>
|
||
|
||
This is sneaky, and isn't used in any official scripts, but it will let you
|
||
define an area (x1/y1-x2/y2 square) of a map as having cell type 'type', where
|
||
type is a number, which, among other things, defines whether the area is
|
||
walkable or not, whether it has Basilica working in it or not, and some other
|
||
things. This is a solution just itching for a problem and there's a number of
|
||
interesting things you could use it for. Further investigation on what types are
|
||
valid and mean what exactly is pending.
|
||
|
||
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 character 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 commmands
|
||
implemented (but NEVER documented by Lance. Shame on you...).
|
||
|
||
Item and pet scripts
|
||
--------------------
|
||
|
||
Each item in the item database has two special fields - EquipScript and
|
||
UseScript. 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.
|
||
|
||
UseScript is a piece of script code run whenever the item is used by a character
|
||
by doubleclicking on it.
|
||
|
||
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 recognised 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.
|
||
|
||
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 alfanumeric 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
|
||
|
||
Extent can be:
|
||
permanent - Permanent NPC variables exist while the server is running.
|
||
Others still exist when the server resets.
|
||
temporary - Temporary NPC variables exist while the script instance is running.
|
||
Others cease to exist when the server resets.
|
||
|
||
Prefix: scope and extent
|
||
nothing - A permanent variable attached to the character, the default
|
||
variable type.
|
||
"@" - 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" file and are the only kind of
|
||
variables stored in a text file in the SQL version.
|
||
"$@" - 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 variable that exists on the NPC as long as the server is running.
|
||
They are only accessible from inside the NPC or by calling
|
||
'getvariableofnpc'.
|
||
".@" - A temporary variable that exists until the script instance ends.
|
||
They are only accessible in that NPC 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 - permanent npc integer variable
|
||
.name$ - permanent npc string variable
|
||
.@name - temporary npc integer variable
|
||
.@name$ - temporary npc 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:
|
||
|
||
StatusPoint - Amount of status points remaining.
|
||
BaseLevel - Current base level
|
||
SkillPoint - Amount of skill points remaining
|
||
Class - Current job
|
||
Upper - 1 if the character is an advanced job class.
|
||
Zeny - Current amount of zeny
|
||
Sex - Character's gender, 0 if female, 1 if male.
|
||
Weight - The weight the character currently carries.
|
||
MaxWeight - The maximum weight the character can carry.
|
||
JobLevel - Character's job level
|
||
BaseExp - The amount of base experience points the character has.
|
||
Notice that it's zero (or close) if the character just got a level.
|
||
JobExp - Same for job levels
|
||
NextBaseExp - Amount of experience points needed to reach the next base level.
|
||
NextJobExp - Same for job levels.
|
||
Hp - Current amount of hit points.
|
||
MaxHp - Maximum amount of hit points.
|
||
Sp - Current spell points.
|
||
MaxSp - Maximum amount of spell points.
|
||
BaseJob - This is sneaky, apparently meant for baby class support.
|
||
This will supposedly equal Job_Acolyte regardless of whether the
|
||
character is an acolyte or a baby acolyte, for example.
|
||
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.
|
||
|
||
Strings
|
||
-------
|
||
|
||
To include symbol '"' in a string you should use prefix '\"'
|
||
|
||
|
||
Arrays
|
||
------
|
||
|
||
Arrays (in eAthena 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 indices 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 naturaly 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 eachother,
|
||
and results in setting bits which are active in both arguments. This can
|
||
be used for a few things, but in eAthena this operator is usually used to
|
||
create bitmasks 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 bitmaks. A variable currently can hold up to 32 bitmasks (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 bitmask 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 bitmasks.
|
||
|
||
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 helpfull 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 dinasty, use them wisely.";
|
||
close;
|
||
}
|
||
|
||
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. 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>:
|
||
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:
|
||
|
||
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 castle data is
|
||
loaded from the char-server by the map server.
|
||
|
||
No RID will be attached while any of the abovementioned labels are triggered, so
|
||
no character or account-based variables will be accessible, until you attach a
|
||
RID with 'attachrid' (see below).
|
||
|
||
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.
|
||
|
||
OnPCDieEvent:
|
||
OnPCKillEvent:
|
||
OnPCLogoutEvent:
|
||
OnPCLoginEvent:
|
||
|
||
These four special labels will be invoked if you have set 'event_script_type'
|
||
value in your 'script_athena.conf' to 1, and you can change their names by
|
||
altering the configuration options in 'script_athena.conf'. It's pretty obvious
|
||
when those will get triggered. For more information, see
|
||
'npc/sample/PCLoginEvent.txt'
|
||
|
||
OnPCLoadMapEvent:
|
||
|
||
This special label will trigger once a player steps in a map marked with the
|
||
'loadmap' 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
|
||
everytime 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.
|
||
|
||
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.
|
||
|
||
=====================
|
||
|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.
|
||
|
||
---------------------------------------
|
||
|
||
*next;
|
||
|
||
This command will create a 'next' button in the message window for the invoking
|
||
character. If no window is currently on screen, it will be created. Used to
|
||
segment NPC talking, this command is used A LOT. See 'mes'.
|
||
|
||
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, it will be created. 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. If no window is currently on screen, it will be created. 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 prefectly 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>;
|
||
|
||
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 messagebox.
|
||
|
||
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.
|
||
|
||
---------------------------------------
|
||
|
||
*setd "<variable name>",<value>;
|
||
|
||
Works almost identical as set, just that the variable name is identified as a string,
|
||
thus can be constructed dynamically.
|
||
This command is equivalent to:
|
||
set getd("variable name"),<value>;
|
||
|
||
Example:
|
||
set $var$, "Poring";
|
||
|
||
setd "$var$", "Poporing";
|
||
mes $var$; // Will return Poporing
|
||
|
||
setd "$" + $var$ + "123$", "Poporing is cool";
|
||
mes $Poporing123$; // Will return Poporing is cool.
|
||
|
||
---------------------------------------
|
||
|
||
*getd("<variable name>")
|
||
|
||
Returns a reference to a variable, the name can be constructed dynamically.
|
||
Refer to setd for usage.
|
||
|
||
Example:
|
||
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.
|
||
Example(s):
|
||
|
||
//This will return the value of .var, note that this can't be used, since the value isn't catched.
|
||
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;
|
||
|
||
---------------------------------------
|
||
|
||
*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 (<28>_<EFBFBD>)
|
||
|
||
---------------------------------------
|
||
|
||
*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>;
|
||
|
||
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;
|
||
}
|
||
|
||
Notice that in current SVN, you may not input a negative number with this
|
||
command. This was 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. Unfortunately it limits the uses of the 'input'
|
||
command quite a bit.
|
||
|
||
---------------------------------------
|
||
|
||
*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
|
||
}
|
||
|
||
---------------------------------------
|
||
|
||
*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.
|
||
|
||
mes "[Woman]"
|
||
mes "Lets see if you win";
|
||
callsub Check;
|
||
mes "Well done you have won";
|
||
close;
|
||
Check:
|
||
set @win, rand(2);
|
||
if(@win==0) return;
|
||
mes "Sorry you lost";
|
||
close;
|
||
|
||
---------------------------------------
|
||
|
||
*getarg(<number>)
|
||
|
||
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.
|
||
|
||
---------------------------------------
|
||
|
||
*return {<value>};
|
||
|
||
When you use callsub or callfunc, this command allows you to go back to the
|
||
calling script. You can optionally return with a value telling the calling
|
||
program what exactly happened.
|
||
|
||
callfunc "<your function>";// when nothing is returned
|
||
set <variable>,callfunc("<your function>");// when a value is being returned
|
||
|
||
---------------------------------------
|
||
|
||
*function <function name>;
|
||
*<function name>;
|
||
*function <function name> {
|
||
<code>
|
||
}
|
||
|
||
(Skotlex stop being so selfish and give us all the commands T~T! J/k lol :P)
|
||
|
||
This works like callfunc, but doesn't support arguments like callfunc. It's used for cleaner
|
||
and fast script that doesn't require arguments for it to work. Also they must be inside a script.
|
||
They're not separated scripts and they work more like labels.
|
||
|
||
Note it looks like the normal declaration
|
||
|
||
Usage:
|
||
|
||
You first Declare the function with function <function name>;.
|
||
|
||
Put the rest of your code. You can use then <function name>; to call the function. If it returns a value is unsure,
|
||
test it if you want and give us some comments ;3
|
||
|
||
And at least, but inside the script itself, put the function <function name> {<code>}.
|
||
|
||
Example:
|
||
|
||
prontera,154,189,4 script Item seller 767,{
|
||
|
||
function SF_Selling;
|
||
|
||
mes "I'll open this now if you have more than 50z and you are level 50 or bigger";
|
||
next;
|
||
|
||
if (Zeny > 50) && (BaseLevel > 50) {
|
||
mes "Welcome";
|
||
next;
|
||
SF_Selling;
|
||
close;
|
||
} else
|
||
|
||
set @needed,50-BaseLevel;
|
||
mes "You either are Level "+BaseLevel+", thus you need "+@needed+" more levels";
|
||
mes "to be able to use this npc; or you don't have enough zeny, so get some please";
|
||
close;
|
||
|
||
function SF_Selling {
|
||
|
||
mes "Would you like to buy a phracon for 50z?";
|
||
switch(select("Yes","No, thanks")) {
|
||
|
||
case 1:
|
||
mes "Ok, how many?";
|
||
input @quantity;
|
||
set @check,Zeny/50;
|
||
if (@quantity > @check) {
|
||
mes "Sorry but you can only have "+@check+" Phracons with "+Zeny;
|
||
close;
|
||
} else
|
||
next;
|
||
mes "here you have";
|
||
set Zeny,Zeny-@quantity*50;
|
||
getitem 1010,@quantity;
|
||
close;
|
||
case 2:
|
||
mes "Good bye then";
|
||
close;
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
---------------------------------------
|
||
|
||
*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 forgoten 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 didnt 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 curlies (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
|
||
optimisation.
|
||
|
||
---------------------------------------
|
||
|
||
*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
|
||
|
||
IMPORTANT: deletarray is horribly broken since the earliest days of jAthena. It
|
||
tends to merrily remove much more variables than it's told to remove, which
|
||
makes it pretty much useless for anything other than removing an array from
|
||
memory entirely. This would be very handy, if it always worked.
|
||
|
||
---------------------------------------
|
||
|
||
======================================
|
||
|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.
|
||
|
||
If a character is not a member of any party or guild, an empty string will be
|
||
returned when requesting that information.
|
||
|
||
---------------------------------------
|
||
|
||
*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 function will return an array's element when given an index.
|
||
|
||
// This will find the 2nd array value
|
||
getelementofarray(@array,1)
|
||
|
||
Pretty pointless now when we have
|
||
|
||
@array[1]
|
||
|
||
which has the same effect.
|
||
|
||
---------------------------------------
|
||
|
||
*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, in there 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'
|
||
all of them - some will not work for various internal reasons.
|
||
|
||
// This would return how many status points you haven't spent yet
|
||
readparam(9)
|
||
|
||
Using this particular information as a function call is not required. Just
|
||
putting
|
||
|
||
StatusPoint
|
||
|
||
will give you the same result, and some of these parameters work just like
|
||
variables (i.e. you can 'set Zeny,100' to make the character have 100 zeny,
|
||
destroying whatever zeny they had before, or 'set Zeny,Zeny+100' to give them
|
||
100 zeny)
|
||
|
||
You can also use this command to get stat values:
|
||
|
||
readparam(bVit)
|
||
if(readparam(bVit)<=77) goto L_End;
|
||
mes "Only people with over 77 Vit are reading this";
|
||
L_End:
|
||
close;
|
||
|
||
---------------------------------------
|
||
|
||
*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 character.
|
||
|
||
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.
|
||
|
||
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)) mes "Only members of a guild are allowed beyond this point!";
|
||
|
||
---------------------------------------
|
||
|
||
*getchildid()
|
||
*getmotherid()
|
||
*getfatherid()
|
||
|
||
These functions return the characters (shild/mother/father) ID
|
||
|
||
if (getmotherid()) mes "Oh... I know your mother's ID:"+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>};
|
||
|
||
Thank you to HappyDenn for all this information.
|
||
|
||
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 stringarray 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:
|
||
|
||
// get the character's party ID
|
||
getpartymember(getcharid(1));
|
||
|
||
// immediately copy $@partymembercount value to a new variable, since
|
||
// you don't know when 'getpartymember' will get called again for someone
|
||
// else's party, overwriting your global array.
|
||
set @partymembercount,$@partymembercount;
|
||
|
||
// copy $@partymembername array to a new array
|
||
copyarray @partymembername$[0],$@partymembername$[0],@partymembercount;
|
||
|
||
//list the party members in NPC dialog
|
||
set @count,0;
|
||
L_DisplayMember:
|
||
if(@count == @partymembercount) goto L_DisplayMemberEnd;
|
||
mes (@count + 1) + ". ^0000FF" + @partymembername$[@count] + "^000000";
|
||
set @count,@count+1;
|
||
goto L_DisplayMember;
|
||
L_DisplayMemberEnd:
|
||
close;
|
||
|
||
---------------------------------------
|
||
|
||
*getpartyleader <party id>,{<type>};
|
||
|
||
This function returns some information about the given party-id's leader.
|
||
When type is ommitted, 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 currentcharacter 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 savepoints.
|
||
Available information types are:
|
||
|
||
0 - Map name (a string)
|
||
1 - X coordinate
|
||
2 - Y coordinate
|
||
|
||
---------------------------------------
|
||
\\
|
||
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 equpped there, it returns -1.
|
||
Valid equipment slots are:
|
||
|
||
1 - Upper head gear
|
||
2 - Armor (Where you keep your Jackets and Robes)
|
||
3 - What is in your Left hand.
|
||
4 - What is in your Right hand.
|
||
5 - The garment slot (Mufflers, Hoods, Manteaus)
|
||
6 - What foot gear the player has on.
|
||
7 - Accessory 1.
|
||
8 - Accessory 2.
|
||
9 - Middle Headgear (masks and glasses)
|
||
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 equiped, or if you haven't got
|
||
something equiped:
|
||
|
||
if(getequipid(1)==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(2) == 2341) || (getequipid(2) == 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>)
|
||
|
||
This function will return the name of the item equipped in the specified
|
||
equipment slot on the invoking character. Almost identical to 'getequipid', good
|
||
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(1)==0) goto L_No_HeadGear;
|
||
mes "So you are wearing a "+getequipname(1)+" on your head";
|
||
close;
|
||
L_No_HeadGear:
|
||
mes "You are not wearing any head gear";
|
||
close;
|
||
|
||
---------------------------------------
|
||
|
||
*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 eAthena, 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, 0 given as an argument will return the first one found, 1
|
||
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(0)==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(0))+" 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(1)) 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(1)) 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 plusses 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(1) < 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(1);
|
||
|
||
---------------------------------------
|
||
|
||
*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 3 (Left hand) and 4 (Right hand) 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.
|
||
|
||
if(getequipweaponlv(4)==0) mes "Seems you don't have a weapon on";
|
||
if(getequipweaponlv(4)==1) mes "You are holding a lvl 1 weapon";
|
||
if(getequipweaponlv(4)==2) mes "You are holding a lvl 2 weapon";
|
||
if(getequipweaponlv(4)==3) mes "You are holding a lvl 3 weapon";
|
||
if(getequipweaponlv(4)==4) mes "You are holding a lvl 4 weapon";
|
||
if(getequipweaponlv(4)==5) mes "You are holding a lvl 5 weapon, hm, must be a custom design";
|
||
|
||
Or for the left hand, cause it can hold a weapon or a shield:
|
||
|
||
if(getequipid(3)==0) goto L_NothingEquiped;
|
||
if(getequipweaponlv(3)==0) mes "You are holding a shield, so it doesnt have a level";
|
||
if(getequipweaponlv(3)==1) mes "You are holding a lvl 1 weapon";
|
||
if(getequipweaponlv(3)==2) mes "You are holding a lvl 2 weapon";
|
||
if(getequipweaponlv(3)==3) mes "You are holding a lvl 3 weapon";
|
||
if(getequipweaponlv(3)==4) mes "You are holding a lvl 4 weapon";
|
||
if(getequipweaponlv(3)==5) mes "You are holding a lvl 5 weapon, hm, must be a custom design";
|
||
close;
|
||
L_NothingEquiped:
|
||
mes "Seems you have nothing equiped";
|
||
close;
|
||
|
||
---------------------------------------
|
||
|
||
*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. The actual formula is beyond the scope of this document, however, it is
|
||
calculated as if the character was a blacksmith trying to refine this particular
|
||
weapon, and depends on lots and lots of stuff. 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 recoverd by this command it will go to L_Fail
|
||
if (getequippercentrefinery(3)<=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's refined.
|
||
@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_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 local and numeric.
|
||
|
||
---------------------------------------
|
||
|
||
*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 plusses 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.
|
||
|
||
---------------------------------------
|
||
|
||
*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;
|
||
|
||
Check sample in nps\sample\getiteminfo.txt
|
||
|
||
---------------------------------------
|
||
|
||
*getequipcardid (<equipment slot>,<card slot>);
|
||
|
||
Returns value from equipped item slot in the indicated slot:
|
||
|
||
getequipcardid(num,slot)
|
||
|
||
where:
|
||
num = eqip position slot
|
||
slot = 0,1,2,3 (Card Slot N)
|
||
|
||
This func returns CARD ID, 255,254,-255 (for card 0, if the item is produced) it's useful
|
||
when you want to check item cards or if it's signed. Useful for such quests as
|
||
"Sign this refined item with players name" etc;
|
||
Hat[0] +4 -> Player's Hat[0] +4
|
||
|
||
--------------------------------------
|
||
|
||
*getitemslots (<item id>);
|
||
|
||
Returns the amount of slots the item has.
|
||
|
||
Example(s):
|
||
|
||
//@slots now has the amount of slots of the item with ID 1205.
|
||
set @slots, getItemSlots(1205);
|
||
|
||
--------------------------------------
|
||
//
|
||
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.
|
||
|
||
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 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 accessable 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;
|
||
|
||
---------------------------------------
|
||
|
||
*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 eAthena 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 is a bitmask, add up to get the effects you want:
|
||
|
||
8 - This will count all characters on the same map as the current NPC.
|
||
(By default, it will count people on the same map as the character)
|
||
7 - Return the amount of players for the entire server.
|
||
(By default, only the players on the map will be counted.)
|
||
|
||
So 'getusers(0)' will return the number of characters on the same map as the
|
||
invoking character, while 'getusers(7)' will give the count for entire server.
|
||
|
||
---------------------------------------
|
||
|
||
*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 guildmaster of the specified guild.
|
||
|
||
Maybe you want to make a room only guildmasters 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 guildmaster of the
|
||
guild specified by the ID. 0 if the character is not a guildmaster 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 it's map name. Castle information stored in 'save\castle.txt' for the TXT
|
||
version of the server and in 'guild_castle' table for the SQL version.
|
||
|
||
Valid types of data are:
|
||
|
||
0 - Will make the map server request the castle data from the char server, and
|
||
always return 0. This, apparently, will also cause indirectly the execution
|
||
of an 'OnAgitInit:' event mentioned at the beginning of this document.
|
||
1 - Guild ID
|
||
2 - Castle Economy score.
|
||
3 - Castle Defence score.
|
||
4 - Number of times the economy was invested in today.
|
||
5 - Number of times the defence was invested in today.
|
||
9 - Will return 1 if a Kafra was hired for this castle, 0 otherwise.
|
||
10 - Is 1 if the 1st guardian is present (Soldier Guardian)
|
||
11 - Is 1 if the 2nd guardian is present (Soldier Guardian)
|
||
12 - Is 1 if the 3rd guardian is present (Soldier Guardian)
|
||
13 - Is 1 if the 4th guardian is present (Archer Guardian)
|
||
14 - Is 1 if the 5th guardian is present (Archer Guardian)
|
||
15 - Is 1 if the 6th guardian is present (Knight Guardian)
|
||
16 - Is 1 if the 7th guardian is present (Knight Guardian)
|
||
17 - Is 1 if the 8th guardian is present (Knight Guardian)
|
||
|
||
18-25 types of data will return current hit point values for guardians 1-8
|
||
respectively.
|
||
|
||
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. Data type of 0 won't do
|
||
anything, obviously.
|
||
|
||
---------------------------------------
|
||
|
||
*getgdskilllv(<guild id>,<skill id>)
|
||
|
||
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/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 persons from the given guild that are on the given map.
|
||
Example(s):
|
||
|
||
//Will set the @persons variable to the amount of persons from the guild
|
||
//which ID's = 10 and are at prontera.
|
||
|
||
set @persons,getMapGuildUsers "prontera",10;
|
||
|
||
---------------------------------------
|
||
//
|
||
2,2.- End of guild-related commands
|
||
//
|
||
---------------------------------------
|
||
|
||
*getskilllv(<skill id>)
|
||
|
||
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/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:
|
||
|
||
f (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 ID 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.
|
||
---------------------------------------
|
||
|
||
*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(<item ID>,<type>)
|
||
|
||
This function will look up the monster 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. Due to specific of MOB DB routines,
|
||
it's better to check monster name. It'd return "Dummy" for a non-existing monster.
|
||
|
||
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 JOB_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
|
||
|
||
Check sample in nps\sample\getmonsterinfo.txt
|
||
|
||
---------------------------------------
|
||
|
||
*getmapmobs("<map name>")
|
||
|
||
This function will return the total count of monsters currently located on the
|
||
specified map. 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.
|
||
|
||
---------------------------------------
|
||
|
||
*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.
|
||
|
||
---------------------------------------
|
||
|
||
*skillpointcount;
|
||
|
||
Returns the total amount of skill points a character posesses (SkillPoint+SP's used in skills)
|
||
This command can be used to check the currently attached characters total amount of skillpoints.
|
||
This means the skillpoints 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 skillpoints,
|
||
//and then tell the player the value.
|
||
set @skillPoints, skillPointCount();
|
||
mes "You have "+@skillPoints+" skillpoints in total!";
|
||
|
||
//Self-explanatory... :P
|
||
if (skillPointCount() > 20)
|
||
mes "Wow, you have more then 20 Skill Points in total!";
|
||
|
||
---------------------------------------
|
||
|
||
*getscrate(<effect type>,<base rate>{,<target ID number>})
|
||
|
||
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_'.
|
||
|
||
It is pretty certain that addressing the target by an ID number will not
|
||
currently work due to a bug.
|
||
|
||
---------------------------------------
|
||
|
||
========================
|
||
|3.- Checking commands.|
|
||
========================
|
||
-------------------------
|
||
|
||
*playerattached;
|
||
|
||
Returns the ID of the player currently attached to the script. It will return
|
||
0 if noone 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>)
|
||
|
||
This function returns 1 if the specified account is logged in and 0 if they
|
||
aren't.
|
||
|
||
---------------------------------------
|
||
|
||
*checkweight(<item id>,<amount>)
|
||
*checkweight("<item name>",<amount>)
|
||
|
||
This function will compute and return 1 if the total weight of a 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.
|
||
|
||
Like 'getitem', this function will also accept an 'english name' from the
|
||
database as an argument.
|
||
|
||
checkweight(502,10) // 10 apples
|
||
|
||
if (checkweight(502,10) == 0 ) goto L_OverWeight;
|
||
getitem 502,10;
|
||
close;
|
||
L_OverWeight:
|
||
mes "Sorry you cannot hold this ammount of apples";
|
||
close;
|
||
|
||
Or to put this another way:
|
||
|
||
if (checkweight("APPLE",10)) goto L_Getapples;
|
||
mes "Sorry you cannot hold this ammount of apples";
|
||
close;
|
||
L_Getapples:
|
||
getitem 502,10;
|
||
close;
|
||
|
||
Both these examples have the same effect.
|
||
|
||
---------------------------------------
|
||
|
||
*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 emoticons, 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.
|
||
|
||
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 bitmasks - 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 give the invoking character a PecoPeco (if they are a Knight
|
||
series class) or a GrandPeco (if they are a Crusader seriesclass). 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 don't.
|
||
|
||
if (checkriding()) mes "PLEASE leave your bird outside! No riding birds on the floor here!";
|
||
|
||
---------------------------------------
|
||
|
||
*checkvending ({"<player name>"})
|
||
*checkchatting ({"<Player Name>"})
|
||
|
||
If the player's name is given, this command checks for that player
|
||
to be online and wether he/she is chatting or vending.
|
||
When no name is given, the attached player is used for checking.
|
||
Returns true or false (1 or 0) when the player is chatting/vending or not.
|
||
|
||
Example(s):
|
||
if (checkVending("Aaron")) mes "Aaron is currently vending!";
|
||
//This will check if Aaron is vending, and if so, put a message in front
|
||
//of the attached player saying Aaron is vending.
|
||
|
||
if (checkChatting()) mes "You are currently chatting!";
|
||
//This will check if you're in a chat room or not
|
||
|
||
---------------------------------------
|
||
|
||
*agitcheck()
|
||
|
||
This function will let you check whether the server is currently in WoE mode.
|
||
It will return 1 if the 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.";
|
||
|
||
---------------------------------------
|
||
\\
|
||
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). Theorically
|
||
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.
|
||
|
||
---------------------------------------
|
||
|
||
*hasitems(0)
|
||
|
||
This function will return 1 if the invoking character has anything at all in
|
||
their inventory and 0 if they do not. Even though the argument is not used for
|
||
anything, it is required.
|
||
|
||
---------------------------------------
|
||
|
||
*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(<character ID>)
|
||
*detachrid;
|
||
|
||
A 'RID' is an ID of a character who caused the NPC script to run, as has been
|
||
explained above in the introduction section. Quite a bit of commands want a RID
|
||
to work, since they wouldn't know where to send information otherwise. And in
|
||
quite a few cases the script gets invoked with a RID of zero (like through
|
||
OnTime special labels). If an NPC script needs this, it can attach a specified
|
||
character's id to itself. by calling the 'attachrid' function.
|
||
|
||
'attachrid' returns 1 if the character was found online and 0 if it wasn't.
|
||
|
||
This could also be used, while running in a script invoked by a character
|
||
through talking to an NPC, to mess with other characters.
|
||
Detaching the RID will make the RID of the script zero.
|
||
|
||
---------------------------------------
|
||
|
||
*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 specifed 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 savepoint.
|
||
|
||
---------------------------------------
|
||
|
||
*areawarp "<from map name>",<x1>,<y1>,<x2>,<y2>,"<to map name>",<x3>,<y3>;
|
||
|
||
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".
|
||
|
||
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 "<mapname>",<x>,<y>,<party_id>;
|
||
|
||
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>).
|
||
|
||
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,20000001;
|
||
|
||
---------------------------------------
|
||
|
||
*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>).
|
||
|
||
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 works on the invoking character like 'heal', however, it is not
|
||
normally used in NPC scripts and will not work as expected there, but is used
|
||
all over in item scripts.
|
||
|
||
Unlike 'heal', which just alters hp/sp and doesn't do anything else at all, this
|
||
command also shows healing animations for potions and other stuff, checks
|
||
whether the potion was made by a famous alchemist and alters the amount healed,
|
||
etc, etc. Since which kind of effect is shown depends on what item was used,
|
||
using it in an NPC script will not have a desired effect.
|
||
|
||
There is also a nice example on using this with the 'rand' function, to give you
|
||
a random ammount 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 ammount 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; }
|
||
|
||
This command only works when inside item scripts.
|
||
|
||
---------------------------------------
|
||
|
||
*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, but there is no way to send this
|
||
information to the client, so the player will continue to see their character as
|
||
the gender it previously was. What the other players will see before the
|
||
relogin is not clear.
|
||
|
||
If the character currently connected when this command was invoked was a
|
||
Dancer/Gypsy or Bard/Clown, they will become a Swordman upon 'changesex'.
|
||
Whatever happens to their skills is not clear. Whatever happens if another
|
||
character on the same account was a gender-specific class is not clear either,
|
||
but it's likely that the client will have serious issues with that, since no
|
||
other characters on the same account will get altered.
|
||
|
||
There's good reasons to be very careful when using this command.
|
||
|
||
---------------------------------------
|
||
|
||
*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 amounts of experience
|
||
were not tested but should 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 ammount of experience points:
|
||
|
||
set BaseExp,BaseExp-10000;
|
||
|
||
---------------------------------------
|
||
|
||
*setlook <look type>,<look value>;
|
||
|
||
This command 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.
|
||
|
||
// This will change your hair(6), so that it uses palette 8, what ever your
|
||
// palette 8 is your hair will use that colour
|
||
|
||
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 colours.
|
||
|
||
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 anybody'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 colour numbers are. If you want a serious
|
||
example, there is a Stylist script inside the default eAthena installation that
|
||
you can look at, this may help you create a Stylist of your own:
|
||
'custom\dye.txt'
|
||
|
||
---------------------------------------
|
||
\\
|
||
4,1.- Item-related commands
|
||
\\
|
||
---------------------------------------
|
||
|
||
*getitem <item id>,<amount>{,<character ID>};
|
||
*getitem "<item name>",<amount>{,<character 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 <character 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/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>{,<character ID>};
|
||
*getitem2 "<Item name>",<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<character ID>};
|
||
|
||
This command will give an amount of specified items to the invoking character.
|
||
If an optional character ID is specified, and that 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, which is kinda silly) but is a lot
|
||
more flexible, since it allows you to give the player an item altered with it's
|
||
specific properties.
|
||
|
||
Those parameters that are different from 'getitem' are:
|
||
|
||
identify - Whether you want the item to be identified or not, 0 unidentified,
|
||
1 identified.
|
||
refine - For how many plusses will it be refined.
|
||
It will not let you refine an item higher than +10, if you
|
||
specify more it'll still be 10.
|
||
attribute - Whether the item is broken (1) or not (0) and NOT an elemental
|
||
attribute.
|
||
card1,2,3,4 - If you want a card compound to it, place the card ID number into
|
||
the specific card slot. Card ID numbers also found in
|
||
'db/item_db.txt'
|
||
|
||
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 name|item id>,<Character name|character ID>;
|
||
|
||
-Note: there's a total of 4 possible combinations of this command.
|
||
E.g: item name and character name, or with character id, etc...
|
||
|
||
Create a item signed with the given character's name.
|
||
This is the same as using the hard(ly) explained way with getitem2.
|
||
|
||
The command returns 1 when the item is created succesfully, or 0 when failed.
|
||
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!";
|
||
}
|
||
|
||
---------------------------------------
|
||
|
||
*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/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.
|
||
|
||
---------------------------------------
|
||
|
||
*delitem <item id>,<amount>;
|
||
*delitem "<item name>",<amount>;
|
||
|
||
This command will take a specified amount of items from the invoking character.
|
||
As all the item commands, this one uses the ID of the item found inside
|
||
'db/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 to check if the player actually has the item before
|
||
you take it from them, Otherwise, you could try to delete items which the
|
||
players don't actually have, which won't fail and won't give an error message,
|
||
but might open up ways to exploit your script.
|
||
|
||
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>{,<character ID>};
|
||
*delitem2 "<Item name>",<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<character ID>};
|
||
|
||
This command will take a specified amount of items from the invoking 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/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;
|
||
|
||
---------------------------------------
|
||
|
||
*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>;
|
||
|
||
This is a command meant for item scripts to replicate single-use skills. It will
|
||
not work properly in NPC scripts a lot of the time because casting a skill is
|
||
not allowed when there is a message window or menu on screen. If there isn't one
|
||
cause you've made sure to run this when they already closed it, it should work
|
||
just fine and even show a targeting pointer if this is a targeting skill.
|
||
|
||
// When you use Anodyne, you will cast Endure(8) level 1,
|
||
// and "Endure" will appear above your head as you use it.
|
||
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.
|
||
|
||
Valid item levels are:
|
||
|
||
1 - Level 1 Weapons
|
||
2 - Level 2 Weapons
|
||
3 - Level 3 Weapons
|
||
16 - Blacksmith's Stones and Metals
|
||
32 - Alchemist's Potions
|
||
64 - Whitesmith's Coins
|
||
123 - Whitesmith's Nuggets
|
||
256 - Assassin Cross's Deadly Poison
|
||
|
||
---------------------------------------
|
||
|
||
*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 peice 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.
|
||
|
||
---------------------------------------
|
||
|
||
*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 seem 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 seem 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.
|
||
|
||
|
||
---------------------------------------
|
||
|
||
*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. (Which is a good thing.)
|
||
|
||
---------------------------------------
|
||
|
||
*clearitem;
|
||
|
||
This command will destroy all items the invoking character has in their
|
||
inventory. (that includes 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.
|
||
|
||
Example(s):
|
||
|
||
//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;
|
||
|
||
---------------------------------------
|
||
//
|
||
4,1.- End of item-related commands
|
||
//
|
||
---------------------------------------
|
||
|
||
*openstorage;
|
||
|
||
This will open a character's Kafra storage window on the client connected to the
|
||
invoking character. It does not check wherever it is run from, so you can allow
|
||
any feasible NPC to open a kafra storage. (It's not certain whether this works
|
||
in item scripts, but if it does, it could be interesting.)
|
||
|
||
The storage window might not open if a message box or a trade deal is present on
|
||
screen already, so you should at least make sure the message box is closed
|
||
before you open storage.
|
||
|
||
mes "I will now open your stash for you";
|
||
close2;
|
||
openstorage;
|
||
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 guildmaster'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>
|
||
|
||
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 guildmaster, 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/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 xp, 0 job xp, wipes the
|
||
status effects, 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 XP/JXP. Skills and attribute
|
||
values are not altered.
|
||
3 - Base level 1, base xp 0. Nothing else is changed.
|
||
4 - Job level 1, job xp 0. Nothing else is changed.
|
||
|
||
In all cases it will also unequip everything the character has on.
|
||
|
||
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>{,<target ID number>};
|
||
*sc_start2 <effect type>,<ticks>,<extra argument>,<percent chance>{,<target ID number>};
|
||
*sc_start4 <effect type>,<ticks>,<value 1>,<value 2>,<value 3>,<value 4>{,<target ID number>};
|
||
*sc_end <effect type>{,<target ID number>};
|
||
|
||
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 target ID number, 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.
|
||
|
||
---------------------------------------
|
||
|
||
*skilleffect <skill id>,<number>;
|
||
|
||
This command will display the visual and sound effects of a specified skill (see
|
||
'db/skill_db.txt' for a full list of skills) on the invoking character's sprite.
|
||
Nothing but the special effects and animation will happen. If the skill's normal
|
||
effect displays a floating number, the number given will float up.
|
||
|
||
// This will heal the character with 2000 hp, buff with
|
||
// Bless 10 and Increase AGI 5, and display appropriate
|
||
// effects.
|
||
mes "Blessed be!";
|
||
skilleffect 28,2000;
|
||
heal 2000,0;
|
||
skilleffect 34,0;
|
||
// That's bless 10.
|
||
sc_start 10,240000,10;
|
||
skilleffect 29,0;
|
||
// That's agi 5
|
||
sc_start 12,140000,5;
|
||
|
||
---------------------------------------
|
||
|
||
*npcskilleffect <skill id>,<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>;
|
||
|
||
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.)
|
||
|
||
---------------------------------------
|
||
|
||
*specialeffect2 <effect number>;
|
||
|
||
This command behaves identically to the 'specialeffect', but the effect will be
|
||
centered on the invoking character's sprite.
|
||
|
||
---------------------------------------
|
||
|
||
*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'.
|
||
|
||
---------------------------------------
|
||
|
||
*skill <skill id>,<level>{,<flag>};
|
||
*addtoskill <skill id>,<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/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/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:
|
||
|
||
disquise 1002; //Yay! You're a Poring!!!
|
||
next;
|
||
undisquise; //Yay!!!! You're a human again!!
|
||
|
||
---------------------------------------
|
||
\\
|
||
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.
|
||
|
||
---------------------------------------
|
||
|
||
*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.
|
||
|
||
---------------------------------------
|
||
|
||
*adopt "<parent name>","<parent name>","<novice name>";
|
||
*adopt("<parent name>","<parent name>","<novice name>")
|
||
|
||
This command will set up a novice as a baby of a married couple. All three are
|
||
referred to by character name. The correct variables are set on all three
|
||
characters in the same call. The command will unequip anything the novice has
|
||
equipped and make them a Job_Baby class, as well as send them a 'your job has
|
||
been changed' message.
|
||
|
||
Beware of calling this from inside a 'callfunc' function, cause upon successful
|
||
adoption, this command returns a zero, as if it were a function. This is likely
|
||
to screw up execution of a 'return' command. You may try to call it as a
|
||
function instead, but it doesn't return anything upon an error, which may also
|
||
cause script execution to throw up errors.
|
||
|
||
Nothing will happen (and nothing will be returned either) if either future
|
||
parent is below base level 70 and/or if any of the three characters is not found
|
||
online.
|
||
|
||
---------------------------------------
|
||
//
|
||
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.
|
||
|
||
Example(s):
|
||
|
||
//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, 0 enables the ID to move again.
|
||
ID should be able to be GID of a monster/npc or AID from a character.
|
||
|
||
Example(s):
|
||
|
||
//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>"};
|
||
*areamonster "<map name>",<x1>,<y1>,<x2>,<y2>,"<monster name>",<amount>{,"<event label>"};
|
||
|
||
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 recognised 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.
|
||
|
||
monster "place",60,100,"Poring",1002,1,"NPCNAME::OnLabel";
|
||
|
||
If you do not specify any event label, a label in the NPC object that ran this
|
||
command, called 'OnMyMobDead:' will execute anyway, if present.
|
||
|
||
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;
|
||
L_PoringKilled:
|
||
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.
|
||
|
||
---------------------------------------
|
||
|
||
*killmonster "<map name>","<event label>";
|
||
|
||
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.
|
||
|
||
---------------------------------------
|
||
|
||
*killmonsterall "<map name>";
|
||
|
||
This command will kill all monsters on a specified map name, regardless of how
|
||
they were spawned or what they are.
|
||
|
||
---------------------------------------
|
||
|
||
*strmobinfo(<type>,<monster id>);
|
||
|
||
This function will return information about a monster record in the database, as
|
||
per 'db/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 be like
|
||
this.
|
||
|
||
However, apparently, if you pass this function an empty string for the event
|
||
label, it should return the total count of normal permanently respawning
|
||
monsters instead. With the current dynamic mobs system, 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.
|
||
|
||
---------------------------------------
|
||
|
||
*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 behaviour 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 Homonuculus' 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 lastst 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;
|
||
|
||
---------------------------------------
|
||
|
||
* homunculus_evolution;
|
||
|
||
This command will try to evolve the current player's homunculus.
|
||
If it doesn't work, the /swt emoticon 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 be on at least 91000/100000 intimacy with it's owner.
|
||
|
||
---------------------------------------
|
||
------------------------------------------------
|
||
//===========================================\\
|
||
|| Mob Control Suit Commands ||
|
||
\\===========================================//
|
||
------------------------------------------------
|
||
|
||
---------------------------------------
|
||
|
||
* mobspawn (<monster name>,<monster ID>,<mapname>,<x>,<y>)
|
||
* mobRemove <GID>;
|
||
|
||
This is used to spawn a monster and return it's Game ID, to be used
|
||
in the unit/mobcontrol commands.
|
||
|
||
Note, I will use the stuff here in the examples for the unitcontrol.
|
||
|
||
Example(s):
|
||
|
||
//Spawns a poring named poi poi and put's it's GID in .GID.
|
||
set .GID,mobspawn("Poi Poi",1002,"prontera",160,180);
|
||
//would kill our poring.
|
||
mobRemove .GID;
|
||
|
||
---------------------------------------
|
||
|
||
* getmobdata (<GID>,<arrayname>)
|
||
* setmobdata <GID>,<parameter>,<new value>;
|
||
|
||
This is used to get and set special data related to the monster.
|
||
With getmobdata, the array given will be filled with the current data. In setmobdata
|
||
the indexes in the array would be used to set that data on the monster.
|
||
Parameters (indexes) are:
|
||
|
||
0 = class (big, small, normal) 7 = y 14 = hair style 21 = weapon
|
||
1 = level 8 = speed 15 = hair color 22 = shield (again)
|
||
2 = HP 9 = mode (see doc/mob_db_mode_list.txt) 16 = head gear bottom 23 = looking dir
|
||
3 = max HP 10 = special AI state (?) 17 = head gear middle 24 = killer state (1 or 0)
|
||
4 = master ID (aid of the master, summon) 11 = SC option 18 = head gear top 25 = callback flag
|
||
5 = map index 12 = sex 19 = cloth color 26 = no random walk (1 or 0)
|
||
6 = x 13 = class (Monster ID, Job ID) 20 = shield
|
||
|
||
Example(s):
|
||
|
||
//this will set all the mobdata in the @array variable. (@array[1] being level, @array[13] class etc)
|
||
getmobdata .GID,@array;
|
||
|
||
//set the max hp of our poring to 1000.
|
||
setmobdata .GID,3,1000;
|
||
|
||
---------------------------------------
|
||
|
||
* mobassist <GID>,<target id>;
|
||
This will make the monster assist the Target ID as if it was a summon of it.
|
||
Example(s):
|
||
|
||
/this will make our poring assist the current attached player! >:3
|
||
mobassist .GID,getcharid(3);
|
||
|
||
---------------------------------------
|
||
|
||
* mobattach <GID>{,"<NPC Name>"};
|
||
|
||
GID is the GID of a monster, NPC or account id. The NPC running or
|
||
he NPC name given is used to attach the monster.
|
||
|
||
By attaching a monster, the NPC to which it is attached is ran on special actions by the monster.
|
||
The system will set specific data in the .ai_action variable array on the NPC invoked.
|
||
The special AI actions types are set in the .ai_action at place AI_ACTION_TAR_TYPE
|
||
|
||
More AI_ vars are set in const.txt, and you can also look at sample/monstercontroller.cpp:
|
||
|
||
---------------------------------------
|
||
|
||
* 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 mapindexes 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.
|
||
|
||
Example(s):
|
||
|
||
//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 mapindexes are correct).
|
||
unitwalk .GID,3;
|
||
|
||
---------------------------------------
|
||
|
||
* unitkill <GID>;
|
||
* unitwarp <GID>,<Mapname>,<x>,<y>;
|
||
* unitattack <GID>,<Target ID>;
|
||
* unitstop <GID>;
|
||
* unittalk <GID>,<Text>;
|
||
* unitemote <GID>,<Emote>;
|
||
* unitdeadsit <GID>,<Action?>;
|
||
|
||
Okay, these commands should be fairly self explaining.
|
||
|
||
For the emotions, you can look in db/const.txt for prefixes with e_
|
||
The unitdeadsit uses an action, not exactly sure why it's named unitdeadsit...
|
||
|
||
Anyhoo: actions are
|
||
0: normal attack
|
||
1: pick stone like
|
||
2: normal sit
|
||
3: nothing?
|
||
|
||
---------------------------------------
|
||
|
||
------------------------------------------------
|
||
//===========================================\\
|
||
|| End of Mob Control Suit Commands ||
|
||
\\===========================================//
|
||
------------------------------------------------
|
||
---------------------------------------
|
||
|
||
*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.
|
||
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'.
|
||
|
||
place,100,100,1%TAB%script%TAB%NPC%TAB%53,{
|
||
mes "This is what you will see when you click me";
|
||
close;
|
||
Label:
|
||
mes "This is what you will see if the doevent is activated";
|
||
close;
|
||
}
|
||
|
||
....
|
||
|
||
doevent "NPC::Label";
|
||
|
||
---------------------------------------
|
||
|
||
*donpcevent "{NPC NAME}::<event label>";
|
||
|
||
This command is kinda confusing cause it performs in two completely different
|
||
ways.
|
||
|
||
If the event label is phrased like "::<label name>", all NPC objects that have a
|
||
specified label in them will be invoked as if by a 'doevent', but no RID
|
||
whatsoever will be attached while they execute.
|
||
|
||
Otherwise, if the label is given as "<NPC name>::<label name>", a label within
|
||
the NPC object that runs this command will be called, but as if it was running
|
||
inside another, specified NPC object. No RID will be attached to it in this case
|
||
either.
|
||
|
||
This can be used for making another NPC react to an action that you have done
|
||
with the NPC that has this command in it, i.e. show an emotion, or say
|
||
something.
|
||
|
||
place,100,100,1%TAB%script%TAB%NPC%TAB%53,{
|
||
mes "Hey NPC2 copy what I do";
|
||
close2;
|
||
set @emo, rand(1,30);
|
||
donpcevent "NPC2::Emo";
|
||
Emo:
|
||
emotion @emo;
|
||
end;
|
||
}
|
||
|
||
place,102,100,1%TAB%script%TAB%NPC2%TAB%53,{
|
||
mes "Hey NPC copy what I do";
|
||
close2;
|
||
set @emo, rand(1,30);
|
||
donpcevent "NPC::Emo";
|
||
Emo:
|
||
emotion @emo;
|
||
end;
|
||
}
|
||
|
||
This will make both NPC perform the same random emotion from 1 to 30, and the
|
||
emotion will appear above each of their heads.
|
||
|
||
---------------------------------------
|
||
|
||
*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";
|
||
|
||
---------------------------------------
|
||
\\
|
||
5,1.- Time-related commands
|
||
\\
|
||
---------------------------------------
|
||
*addtimer <ticks>,"<NPC object name>::<label>";
|
||
*deltimer "<NPC object name>::<event label>";
|
||
*addtimercount <ticks>,"<NPC object name>::<event label>";
|
||
|
||
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.
|
||
|
||
When this timer runs out, a new execution thread will start in the specified NPC
|
||
object at the specified label. If no such label is found in the NPC object, it
|
||
will run as if clicked. In either case, no RID will be attached during
|
||
execution.
|
||
|
||
The ticks are given in 1/1000ths of a second.
|
||
|
||
---------------------------------------
|
||
|
||
*stoptimer;
|
||
*inittimer;
|
||
*enablearena;
|
||
*disablearena;
|
||
*cmdothernpc "<npc name?>","<command?>";
|
||
|
||
This set of commands is marked as added by someone going under the nickname
|
||
'RoVeRT', as mentioned the source code comments, and has to do with timers and
|
||
scheduling working entirely unlike any other timing commands. It is not certain
|
||
that they actually even work properly anymore, and most of these read no
|
||
arguments, though the 'inittimer'/'stoptimer' pair of commands has to do
|
||
something with an 'OnTimer' label and will probably invoke it and 'cmdothernpc'
|
||
will execute starting with the label 'OnCommand'. Whatever they actually do, the
|
||
other commands can most likely do it better. The two arena commands definitely
|
||
do not do anything useful at all.
|
||
|
||
None of these commands are used in any scripts bundled with eAthena. Most
|
||
probably they are deprecated and left in by mistake.
|
||
|
||
Unless RoVeRT can be found and asked to clarify what these were made for, that
|
||
is.
|
||
|
||
---------------------------------------
|
||
|
||
*initnpctimer{ "<NPC object name>" {, <Attach Flag>} } |
|
||
{"<NPC object name>" | <Attach Flag> };
|
||
*stopnpctimer{ "<NPC object name>" {, <Detach Flag>} } |
|
||
{ "<NPC object name>" | <Detach Flag> };
|
||
*startnpctimer{ "<NPC object name>" {, <Attach Flag>} } |
|
||
{ "<NPC object name>" | <Attach Flag> };
|
||
*setnpctimer <tick>{,"<NPC object name>"};
|
||
*getnpctimer(<type of information>{,"<NPC object name>"});
|
||
*attachnpctimer {"<character name>"};
|
||
*detachnpctimer {"<NPC object name>"};
|
||
|
||
This set of commands and functions will create and manage an NPC-object based
|
||
timer. The NPC object may be declared by name, or the name in all cases may be
|
||
omitted, in that case this timer will be based in the object the current script
|
||
is running in.
|
||
|
||
Why is it actually part of an NPCs structure we aren't sure, but it is, and
|
||
while 'addtimer'/'deltimer' commands will let you have many different timers
|
||
referencing different labels in the same NPC, one each and each with their own
|
||
countdown, 'initnpctimer' can only have one per NPC object. But it can trigger
|
||
many labels and it can 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 the timers continue even
|
||
if the player that started them logs off. To attach a RID to a timer, you can
|
||
either use the "attach flag" optional value when using initnpctimer/startnpctimer,
|
||
likewise, the optional flag of stopnpctimer detaches any RID after stopping
|
||
the timer. Once a player is attached to a timer, it stays attached to all
|
||
timers from that script until detached manually. You can have multiple
|
||
npctimers going on at the same time as long as each one has a different player
|
||
attached (think of each RID being used as an independant timer).
|
||
|
||
The other method to attach/detach a RID is through the script commands
|
||
'attachnpctimer' and 'detachnpctimer'. Once attached, that will make the
|
||
character the target for all character-referencing commands and functions,
|
||
not to mention variables.
|
||
|
||
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 appropiate
|
||
cleanup (the player is still attached when this event is triggered).
|
||
|
||
'setnpctimer' will explicitly set the timer to a given tick. To make it useful,
|
||
you will need the 'getnpctimer' function, which the type of information argument
|
||
means:
|
||
|
||
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 an "OnTimer<tick>:"
|
||
label in the specified NPC.
|
||
|
||
Example 1:
|
||
|
||
<NPC Header> {
|
||
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";
|
||
}
|
||
|
||
Example 2:
|
||
|
||
OnTimer15000:
|
||
set $quote,rand(5);
|
||
if($quote == 0) goto Lquote0;
|
||
if($quote == 1) goto Lquote1;
|
||
if($quote == 2) goto Lquote2;
|
||
if($quote == 3) goto Lquote3;
|
||
if($quote == 4) goto Lquote4;
|
||
Lquote0:
|
||
npctalk "If 0 is randomly picked you will see this";
|
||
setnpctimer 0;
|
||
end;
|
||
Lquote1:
|
||
npctalk "If 1 is randomly picked you will see this";
|
||
setnpctimer 0;
|
||
end;
|
||
Lquote2:
|
||
npctalk "If 2 is randomly picked you will see this";
|
||
setnpctimer 0;
|
||
end;
|
||
Lquote3:
|
||
npctalk "If 3 is randomly picked you will see this";
|
||
setnpctimer 0;
|
||
end;
|
||
Lquote4:
|
||
npctalk "If 4 is randomly picked you will see this";
|
||
setnpctimer 0;
|
||
end;
|
||
|
||
// This OnInit label will run when the script is loaded, so that the timer
|
||
// is initialised immediately as the server starts. It is dropped back to 0
|
||
// every time the NPC says something, so it will cycle continiously.
|
||
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 cause it will be displayed in
|
||
// milliseconds otherwise
|
||
close;
|
||
|
||
Example 4:
|
||
|
||
mes "[Man]";
|
||
mes "Ok I will let you have 30 sec more";
|
||
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 callen 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'.
|
||
|
||
---------------------------------------
|
||
//
|
||
5,1.- End of time-related commands
|
||
//
|
||
|
||
*announce "<text>",<flag>{,<color>};
|
||
|
||
This command will broadcast a message to all or most players, similar to
|
||
@kami/@kamib GM commands.
|
||
|
||
The region the broadcast is heard in and the color the message will come up as
|
||
will be determined by the flags:
|
||
|
||
announce "This will be shown to everyone at all in yellow.",0;
|
||
|
||
The flag values are coded as constants in db/const.txt to make them easier to use:
|
||
- bc_all: Broadcast message is sent server-wide
|
||
- bc_map: Message is sent to everyone in the same map
|
||
- bc_area: Message is sent to players in the vecinity of the source.
|
||
- bc_self: Message is sent only to current player.
|
||
|
||
- 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)
|
||
|
||
- bc_yellow: The default is to send broadcasts in yellow color.
|
||
- bc_blue: Alternate broadcast is displayed in blue color.
|
||
|
||
The optional parameter, color, allows usage of broadcasts in any custom color.
|
||
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 yellow.",bc_all,0xFFFF00;
|
||
Will display a global announce in yellow. The color format is in RGB (0xRRGGBB).
|
||
|
||
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
|
||
// annonucement
|
||
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_area;
|
||
|
||
---------------------------------------
|
||
|
||
*mapannounce "<map name>","<text>",<flag>{,<color>};
|
||
|
||
This command will work like 'announce' but will only broadcast to characters
|
||
currently residing on the specified map. The flag and optional color
|
||
parameters are the same as in 'announce', even though the only ones that make
|
||
sense are the color related ones.
|
||
|
||
---------------------------------------
|
||
|
||
*areaannounce "<map name>",<x1>,<y1>,<x2>,<y2>,"<text>",<flag>[,<color>];
|
||
|
||
This command works like 'announce' but will only broadcast to characters
|
||
residing in the specified x1/y1-x2/y2 square on the map given. The flags and
|
||
color parameter given are the same as in 'announce', but only the color
|
||
related ones have effect.
|
||
|
||
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(s):
|
||
|
||
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 @bough_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 and @sold_quantity). An example on a shop comes with eAthena, and
|
||
can be found in the npc/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. 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. 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.
|
||
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>};
|
||
|
||
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 chatroom name is 60 letters.
|
||
|
||
The limit is the maximum number of people allowed to enter the chat room. 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.
|
||
|
||
It's funny, but for compatibility with jAthena, you can swap the event label and
|
||
the trigger parameters, and it will still work.
|
||
|
||
// 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 8 people accumulate. Once this happens,
|
||
// it will cause the NPC "Bouncer" run the label "OnStart"
|
||
|
||
waitingroom "Disco - Waiting Room",8,"Bouncer::OnStart",8;
|
||
|
||
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>"};
|
||
|
||
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.
|
||
|
||
---------------------------------------
|
||
|
||
*getwaitingroomstate(<information type>{,"<NPC object name>"})
|
||
|
||
This function will return information about the wating 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 character 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.
|
||
|
||
---------------------------------------
|
||
|
||
*waitingroomkickall {"<NPC object name>"};
|
||
|
||
This command would kick everybody out of a specified waiting room chat. IF it
|
||
was properly linked into the script interpreter which it isn't, even though the
|
||
code for it is in place. Expect this to become available in upcoming SVN
|
||
releases.
|
||
|
||
---------------------------------------
|
||
|
||
*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 savepoint 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>;
|
||
|
||
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, mf_nopvp), 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 day/night will be in effect on this map (mf_indoors).
|
||
|
||
---------------------------------------
|
||
|
||
*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.
|
||
|
||
Example(s):
|
||
|
||
//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 return 2000).
|
||
getBattleFlag "base_exp_rate";
|
||
|
||
---------------------------------------
|
||
|
||
*removemapflag "<map name>",<flag>;
|
||
|
||
This command removes a mapflag from a specified map. See 'setmapflag'.
|
||
|
||
---------------------------------------
|
||
|
||
*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.
|
||
|
||
Example(s):
|
||
|
||
//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>;
|
||
|
||
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.
|
||
|
||
---------------------------------------
|
||
\\
|
||
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 bitmask (add up numbers to get effects you want)
|
||
1 - warp all guild members to their savepoints.
|
||
2 - warp all non-guild members to their savepoints.
|
||
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 intruiders 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;
|
||
|
||
These two commands will start and end War of Emperium.
|
||
|
||
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:' 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>,<amount>{,"<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.
|
||
|
||
---------------------------------------
|
||
|
||
*guardianinfo(<guardian number>)
|
||
|
||
This function will return the current hit point value for the specified guardian
|
||
number, if such guardian is currently installed. This function will only work if
|
||
the invoking character is on a castle map, and will refer only to the guardians
|
||
of that castle, regardless of anything else, i.e. whether the character is a
|
||
member of the guild owning the castle, etc, etc.
|
||
If no guardian is installed in this slot, the function will return -1.
|
||
|
||
---------------------------------------
|
||
//
|
||
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. (see 'npc/custom/devnpc.txt' for an example
|
||
of such usage)
|
||
|
||
'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;
|
||
|
||
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.
|
||
|
||
Example(s):
|
||
|
||
//This will move Bugga from it's current position to the coords 100,20 (if those coords are walkable (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.
|
||
|
||
debugmes strcharinfo(0)+" has just done this that and the other";
|
||
// You would see in the map-server window "NAME has just done this that and
|
||
// the other"
|
||
|
||
---------------------------------------
|
||
|
||
*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, randomly positioned between 0 and the number you
|
||
specify (if you only specify one) and the two numbers you specify if you give it
|
||
two.
|
||
|
||
rand(10) would result in 0,1,2,3,4,5,6,7,8 or 9
|
||
|
||
rand(2,10) would result in 2,3,4,5,6,7,8,9 or 10
|
||
|
||
---------------------------------------
|
||
|
||
*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 hexidecimal 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. 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 stored in the GRF file in the client for the
|
||
player.
|
||
|
||
The files are taken from '\data\texture\A_A<5F>AI<41>I<EFBFBD><49>AI<41><49>\illust' directory in the
|
||
GRF file. Also it seems that card cutins from \cardbmp will work here as well.
|
||
Only bitmaps (images stored in the bitmap format) will actually get displayed.
|
||
The '.bmp' extension is optional.
|
||
The client has no problem rendering huge 4096x4096 bitmaps, but usually they're
|
||
around 500x500. Bright magenta (color FF00FF) is considered to be transparent in
|
||
these pictures. You can easily add and alter them, but how to do this is outside
|
||
of the scope of this document.
|
||
|
||
The position determines just where on screen the picture will appear:
|
||
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.
|
||
255 - will remove the cutin previously displayed.
|
||
|
||
Giving an empty string for the filename and 255 for the position will remove all
|
||
cutin pictures. Any other position value will not cause a script error but will
|
||
cause the player's client to curl up and die. Only one cutin may be on screen at
|
||
any given time, any new cutins will replace it.
|
||
|
||
// This will display the picture of the 7th kafra,
|
||
// the one in orange and the mini-skirt :P
|
||
cutin "kafra_7",2;
|
||
|
||
// This will remove the displayed picture.
|
||
cutin "Kafra_7",255;
|
||
|
||
// This will remove all pictures displayed.
|
||
cutin "",255;
|
||
|
||
---------------------------------------
|
||
|
||
*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};
|
||
|
||
This command makes an object display an emoticon 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 inobvious 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.
|
||
|
||
---------------------------------------
|
||
|
||
*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>",<number>
|
||
*soundeffectall "<effect filename>",<number>
|
||
|
||
These two commands will play a sound effect to either the invoking character
|
||
only 'soundeffect' or everyone around ('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 of the wav in GRF. It must have an extension.
|
||
|
||
It's not quite certain what the number actually does, it is sent to the client
|
||
directly, probably it determines which directory of the GRF the effect is played
|
||
from - the sound effect type. 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.
|
||
|
||
You can add your own effects 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 line>";
|
||
|
||
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>;
|
||
|
||
NOTE: This command is changed a bit on newer trunk versions,
|
||
scroll down a bit for the new version!
|
||
|
||
On older trunk versions and stable:
|
||
|
||
command is the name of the current character (strcharinfo(0))
|
||
followed by ':' and the command and it's parameters.
|
||
|
||
Example(s):
|
||
|
||
//Will be executed as if a lvl 99 GM done the #option command.
|
||
charCommand strcharinfo(0)+":#option 0 0 0 Roy";
|
||
|
||
Newer Trunk version:
|
||
|
||
The big change is that the character name is no longer needed.
|
||
This also enabled the commands to run without a player attached (according to Lance).
|
||
|
||
Example(s):
|
||
|
||
//this would do the same as above, but now doesn't need a player attached by default.
|
||
charCommand "#option 0 0 0 Roy";
|
||
|
||
---------------------------------------
|
||
|
||
*unitskilluseid <GID>,<skill id>,<skill lvl>;
|
||
*unitskillusepos <GID>,<skill id>,<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.
|
||
|
||
---------------------------------------
|
||
|
||
*day;
|
||
*night;
|
||
|
||
These two commands will switch the entire server between day and night mode.
|
||
Depending on the configuration, it may cause differing client effects. If your
|
||
server is set to cycle between day and night, it will eventually return to that
|
||
cycle.
|
||
|
||
This example will set the night time to start at 03 AM and end at 08 AM, and the
|
||
nighttime will persist if the server restarts during the night, if the automated
|
||
day/night switching is turned off in the configuration files. Figure it out on
|
||
your own:
|
||
|
||
-%TAB%script%TAB%DayNight%TAB%-1,{
|
||
|
||
end;
|
||
|
||
OnClock0300:
|
||
|
||
OnClock0800:
|
||
|
||
OnInit:
|
||
|
||
set $@minutesfrommidnight, gettime(3)*60+gettime(2);
|
||
|
||
set $@night_start, 180; // 03:00
|
||
set $@night_end, 480; // 08:00
|
||
|
||
if ($@minutesfrommidnight>=$@night_start && $@minutesfrommidnight<$@night_end) goto StartNight;
|
||
|
||
goto StartDay;
|
||
StartNight:
|
||
night;
|
||
end;
|
||
StartDay:
|
||
day;
|
||
end; }
|
||
|
||
---------------------------------------
|
||
|
||
*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 organised 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 it's place.
|
||
|
||
Using regular expressions is high wizardry. But with this high wizardry comes
|
||
unparallelled 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 'npc\sample\npc_pcre.txt'.
|
||
|
||
With this you could, for example, automagically punish players for asking for
|
||
zeny in public places, or alternatively, automagically 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.
|
||
|
||
Examlpe:
|
||
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);
|
||
|
||
---------------------------------------
|
||
|
||
*query_sql "your MySQL query", <array name>{,<array name>{;
|
||
|
||
Returns up to 127 values into array and return the number of row
|
||
|
||
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]+")";
|
||
|
||
Note: In the TXT version it doesn't fill the array and always return -1.
|
||
Note: Use $ as suffix in the array to receive all data as text.
|
||
|
||
---------------------------------------
|
||
|
||
*setitemscript(<ItemID>,<"{ new item script }">);
|
||
|
||
Set a new script bonus to the Item. Very useful for game events.
|
||
You can remove an item's itemscript by leaving empty the itemscript argument.
|
||
|
||
Example:
|
||
|
||
setitemscript 2637,"{ bonus bDamageWhenUnequip,40; if(isequipped(2236)==0)end; if(getskilllv(26)){skill 40,1;}else{skill 26,1+isequipped(2636);} }";
|
||
setitemscript 2639,"";
|
||
|
||
---------------------------------------
|
||
|
||
*atoi ("<string>")
|
||
*axtoi ("<string>")
|
||
|
||
These commands are used to convert strings to numbers.
|
||
atoi will convert string using normal number (0,1,2,3,etc) while axtoi converts them to
|
||
hexadecimal numbers (0,1,11,01).
|
||
|
||
Example:
|
||
|
||
mes atoi("11"); // Will display 11 (can also be used to set a @var to 11)
|
||
set @var, axtoi("FF"); // Will set the @var to 255
|
||
mes axtoi("11"); // Will display 17 (1 = 1, 10 = 16,
|
||
// hexadecimal number set: {0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F})
|
||
|
||
---------------------------------------
|
||
|
||
*compare (<string>,<substring>)
|
||
|
||
This command returns 1 or 0 when a the substring is in the main string (1) or not (0).
|
||
This command is not case sensitive.
|
||
|
||
Example(s):
|
||
|
||
//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;
|
||
|
||
--------------------------------------
|
||
|
||
*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.
|
||
|
||
---------------------------------------
|
||
|
||
*wedding_effect;
|
||
Starts the effect used when a wedding is done (music and everything else)
|
||
Example can be found in the wedding script.
|
||
|
||
--------------------------------------
|
||
|
||
* 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>;
|
||
*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/skill_db.txt'.
|
||
'petheal' works the same as 'petskillsupport' but has the skill ID hardcoded 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>;
|
||
*petskillattack2 <skill id>,<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 occuring 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 abovementioned commands will only be exibited 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 successfuly
|
||
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.
|
||
|
||
---------------------------------------
|
||
|
||
Whew.
|
||
That's about all of them.
|