Professional Documents
Culture Documents
This document is a reference manual for all the scripting commands and
functions available in current Hercules GIT. 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.
Structure
---------
Descriptive text
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.
Syntax
------
The file contains a list of scripts to be loaded (or other configuration files
to be parsed, through the @include directive), in the following format:
npc_global_list: (
"npc/path/to/the/script/to/load.txt",
"npc/other/file.txt",
@include "npc/other_configuration_file.conf"
)
Any script will only get loaded once even if specified twice, to prevent
possible errors.
npc_removed_list: (
"npc/path/to/the/file/to/skip.txt",
)
Block comments can also be used, where you can place /* and */ between any
text you wish Hercules to ignore.
Example:
/* This text,
* no matter which new line you start
* is ignored, until the following
* symbol is encountered: */
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%'
or '<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. :)
<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 'npc/mapflag' and are loaded first, so by the
time the server's up, all the maps have the flags they should have. Map
flags determine the behavior of the map regarding various common problems,
for a better explanation, see 'setmapflag'.
Map name is the name of the map the monsters will spawn on. X,Y are the
coordinates where the mob should spawn. If X's and Y's are non-zero, they
specify the 'radius' of a spawn-rectangle area centered at x,y. Putting
zeros instead of these coordinates will spawn the monsters randomly. Note
this is only the initial spawn zone, as mobs random-walk, they are free to
move away from their specified spawn region.
Monster name is the name the monsters will have on screen, and has no
relation whatsoever to their names anywhere else. It's the mob id that
counts, which identifies monster record in 'mob_db.txt' database of
monsters. If the mob name is given as "--ja--", the 'japanese name' field
from the monster database is used, (which, in Hercules, actually contains
an English name) if it's "--en--", it's the 'english name' from the
monster database (which contains an uppercase name used to summon the
monster with a GM command).
Amount is the amount of monsters that will be spawned when this command is
executed, it is affected by spawn rates in 'conf/map/battle.conf'.
Delay1 and delay2 control monster respawn delays - the first one is the
fixed base respawn time, and the second is random variance on top of the
base time. Both values are given in milliseconds (1000 = 1 second). Note
that the server also enforces a minimum respawn delay of 5 seconds.
You can specify a custom level to use for the mob different from the one
of the database by adjoining the level after the name with a comma. eg:
"Poring,50" for a name will spawn a monster with name Poring and level 50.
Event is a script event to be executed when the mob is killed. The event
must be in the form "NPCName::OnEventName" to execute, and the event name
label should start with "On". As with all events, if the NPC is an
on-touch NPC, the player who triggers the script must be within 'trigger'
range for the event to work.
There are two optional fields for monster size and AI. Size can be 0
(medium), 1 (small), or 2 (big). AI can be 0 (default), 1
(attack/friendly), 2 (sphere), 3 (flora), or 4 (zanzou).
** NPC names
/!\ WARNING: this applies to warps, NPCs, duplicates and shops /!\
NPC names are kinda special and are formatted this way:
All NPCs need to have a unique name that is used for identification
purposes. When you have to identify a NPC by it's name, you should use
<Unique name>. If <Unique name> is not provided, use <Display name>
instead.
The client has a special feature when displaying names: if the display
name contains a '#' character, it hides that part of the name.
Ex: if your NPC is named 'Hunter#hunter1', it will be displayed as 'Hunter'
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.
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 is the sprite identifier used to display this particular NPC. For a
full list of sprite numbers see http://nn.ai4rei.net/dev/npclist/ as
well as doc/constants.md.
You may also use a monster's ID constant instead to display a monster sprite
for this NPC, in npcs that have view ids of mobs it's encouraged to use
OnTouch events with a 2,2 range and with an 'end' after the header to avoid
bugs (for more info on why see npc_click@map/npc.c). It is possible to use a job
sprite as well, but you must first define it as a monster sprite in
'mob_avail.txt',
a full description on how to do this is not in the scope of this manual.
A 'FAKE_NPC' sprite will make the NPC invisible (and unclickable).
A 'HIDDEN_NPC' sprite will make an NPC which does not have a sprite, but is
still clickable, which is useful if you want to make a clickable object of
the 3D terrain.
TriggerX and triggerY, if given, will define an area, centered on NPC and
spanning triggerX cells in every direction across X and triggerY in every
direction across Y. Walking into that area will trigger the NPC. If no
'OnTouch:' special label is present in the NPC code, the execution will
start from the beginning of the script, otherwise, it will start from the
'OnTouch:' label. Monsters can also trigger the NPC, though the label
'OnTouchNPC:' is used in this case, and using mobattached() will return
monster GID. If player left the area will trigger the label 'OnUnTouch'.
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.
-%TAB%script%TAB%<NPC Name>%TAB%FAKE_NPC,{<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.
-%TAB%shop%TAB%<NPC Name>%TAB%<sprite>,<itemid>:<price>{,<itemid>:<price>...}
<map name>,<x>,<y>,<facing>%TAB%shop%TAB%<NPC Name>%TAB
%<sprite>,<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).
You can alternatively use "cashshop" in place of "shop" to use the Cash
Shop interface, allowing you to buy items with special points (Currently
stored as account vars in #CASHPOINTS and #KAFRAPOINTS). This
type of shop will not allow you to sell items at it, you may only purchase
items here. The layout used to define sale items still count, and
"<price>" refers to how many points will be spent purchasing the them.
All the standards that are valid to script objects are also valid for trader
objects
(see ** Define an NPC object for more information).
This will define a trader NPC, which can cause a shop, cashshop or market window
to come up when clicked or called by other means. Unlike shop/cashshop NPCs this
type will run a code and can change the items that are being sold over time without
other NPC objects.
The types that a trader object can have are the following:
- NST_ZENY (0) Normal Zeny Shop (shop)
- NST_CASH (1) Normal Cash Shop (cashshop)
- NST_MARKET (2) Normal NPC Market Shop (where items have limited availability
and need to be refurbished)
- NST_CUSTOM (3) Custom Shop (any currency, item/var/etca, check sample)
- NST_BARTER (4) Barter Shop (each item with own item currency)
Unless otherwise specified via *tradertype an trader object will be defined as
NST_ZENY.
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.
~ RID? GID? ~
Most scripting commands and functions will want to request data about a
character, store variables referenced to that character, send stuff to the
client connected to that specific character. Whenever a script is invoked
by a character, it is passed a so-called RID - this is the account ID
number of a character that caused the code to execute by clicking on it,
walking into it's OnTouch zone, or otherwise.
If you are only writing common NPCs, you don't need to bother with it.
However, if you use functions, if you use timers, if you use clock-based
script activation, you need to be aware of all cases when a script
execution can be triggered without a RID attached. This will make a lot of
commands and functions unusable, since they want data from a specific
character, want to send stuff to a specific client, want to store
variables specific to that character, and they would not know what
character to work on if there's no RID.
GID stands for the Game ID of something, this can either be the GID of a
mob obtained through the monster() script command (if only summoned one),
the GID of a NPC obtained through the getnpcid() script command or the
account ID of a character (same as its RID). Another way would be to right
click on a mob, NPC or char as GM sprited char to view its GID.
Each item in the item database has three special fields - Script,
OnEquip_Script and OnUnequip_Script. The first is script code run every
time a character equips the item, with the RID of the equipping character.
Every time they unequip an item, all temporary bonuses given by the script
commands are cleared, and all the scripts are executed once again to
rebuild them. This also happens in several other situations (like upon
login) but the full list is currently unknown.
Not all script commands work properly in the item scripts. Where commands
and functions are known to be meant specifically for use in item scripts,
they are described as such.
Every pet in the pet database has a PetScript field, which determines pet
behavior. It is invoked wherever a pet of the specified type is spawned
(hatched from an egg, or loaded from the char server when a character who
had that pet following them connects). This may occur in some other
situations as well. Don't expect anything other than commands definitely
marked as usable in pet scripts to work in there reliably.
Numbers
-------
Beside the common decimal numbers, which are nothing special whatsoever
(though do not expect to use fractions, since ALL numbers are integer in
this language), the script engine also handles hexadecimal numbers, which
are otherwise identical. Writing a number like '0x<hex digits>' will make
it recognized as a hexadecimal value. Notice that 0x10 is equal to 16.
Also notice that if you try to 'mes 0x10' it will print '16'.
Number values can't exceed the limits of an integer variable: Any number
greater than INT_MAX (2147483647) or smaller than INT_MIN (-2147483648) will
be capped to those values and will cause a warning to be reported.
Variables
---------
In Hercules scripting language, variable names are case sensitive. Even though
at the current time the script engine accepts them even with the incorrect
case, it is not advised to rely on this behavior, as it may change at any
time.
Variables are divided into and uniquely identified by the combination of:
prefix - determines the scope and extent (or lifetime) of the variable
name - an identifier consisting of '_' and alphanumeric characters
postfix - determines the type of the variable: integer or string
Scope can be:
global - global to all servers
local - local to the server
account - attached to the account of the character identified by RID
character - attached to the character identified by RID
npc - attached to the NPC
scope - attached to the scope of the instance
Examples:
name - permanent character integer variable
name$ - permanent character string variable
@name - temporary character integer variable
@name$ - temporary character string variable
$name - permanent global integer variable
$name$ - permanent global string variable
$@name - temporary global integer variable
$@name$ - temporary global string variable
.name - NPC integer variable
.name$ - NPC string variable
.@name - scope integer variable
.@name$ - scope string variable
'name - instance integer variable
'name$ - instance 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
Some variables are special, that is, they are already defined for you by
the scripting engine. You can see the full list somewhere in
'doc/constants.md', 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:
Assigning variables
--------- ---------
Variables can be accessed and assigned values directly without the use of
the built-in 'set' function. This means that variables can be accessed and
modified much like other programming languages.
.@x = 100;
.@x = .@y = 100;
Support for modifying variable values using 'set' is still supported (and
required to exist for this method to work) so previous scripts will
continue working. Its usage, though, is deprecated, and it should never be
used in new scripts unless there are special reasons to do so.
When assigning values, all operator methods are supported which exist in
the below 'Operators' section. For instance:
.@x += 100;
.@x -= 100;
.@x *= 2;
.@x /= 2;
.@x %= 5;
.@x >>= 2;
.@x <<= 2;
Will all work. For more information on available operators, see the
Operators section described below. All operators listed there may be
placed in-front of the '=' sign when modifying variables to perform the
action as required.
Increment and decrement operators are also provided, for your convenience.
Pre-increment and pre-decrement operators:
.@x = 1;
.@y = ++.@x; // After this line is executed, both .@y and .@x will be 2
.@x = 1;
.@y = .@x++; // After this line is executed, .@y will be 1, .@x will be 2
Note: The pre-increment/pre-decrement operators are, by design, faster (or at
least not slower) than their respective post- equivalent.
Note:
!! Currently the scripting engine does not support directly copying array
!! variables. In order to copy arrays between variables the use of
!! 'copyarray' function is still required.
Strings
-------
Arrays
------
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:
.@arrayofnumbers[0] = 1;
You can use a variable (or an expression, or even a value from an another
array) as array index:
.@x = 100;
.@arrayofnumbers[.@x] = 10;
Index numbering always starts with 0 and arrays can hold over 2 billion
variables. As such, the (guaranteed) allowed values for indices are in the
range 0 ~ 2147483647.
Variable References
-------------------
//##TODO
Hard-coded constants
--------------------
Most of the constants defined by the scripting engine can be found in
'doc/constants.md' and have the same value independently of settings
that are core related, but there are constants that can be used to
retrieve core information that's set when the server is compiled.
Send targets and status options are also hard-coded and can be found
in 'doc/constants.md'.
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 raise the first number to the power of the second number.
/ - 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 contain
the same value.
>= - 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.
~= - True if the second value (as regular expression) matches the first
value. Both values must be strings. See the script function pcre_match()
for more details and advanced features.
~! - True if the second value (as regular expression) DOES NOT match the
first value. Both values must be strings. See script function pcre_match()
for more details and advanced features.
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.
Logical bitwise operators work only on numbers, and they are the following:
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:
.@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("Option 5 is activated");
This would print the messages about option 2, 3 and 5 (since we've set
the 2,4 and 16 bit to 1).
^ - Xor.
The bitwise operator XOR (eXclusive OR) sets a binary position to 0 if
both numbers have the same value in the said position. On the other
hand, it sets to 1 if they have different values in the said binary
position. This is another way of setting and unsetting bits in
bit-masks.
Example:
- First let's set the quests that are currently in progress:
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)
inProgress = inProgress^2;
mes("Quest 2: find a newbie and be helpful to him for an hour.");
close();
}
- After spending some time reading info on Xor's, the player finally
completes quest 1:
if (inProgress&1 && isComplete) {
// this will unset the bit for quest 1 (inProgress has that bit
set to 1)
inProgress = inProgress^1;
mes("Quest 1 complete!! You unlocked the secrets of the Xor
dynasty, use them wisely.");
close();
}
Unary operators with only with a single number, which follows the
operator, and are the following:
- - Negation.
The sign of the number will be reversed. If the number was positive,
it will become negative and vice versa.
Example:
.@myvar = 10;
mes("Negative 10 is "+(-.@myvar));
! - Logical Not.
Reverses the boolean result of an expression. True will become false
and false will become true.
Example:
if (!callfunc("F_dosomething")) {
mes("Doing something failed.");
close();
}
~ - Bitwise Not.
Reverses each bit in a number, also known as one's complement. Cleared
bits are set, and set bits are cleared.
Example:
- Ensure, that quest 2 is disabled, while keeping all other active, if
they are.
inProgress = inProgress&(~2);
// same as set inProgress, inProgress&0xfffffffd
?: - Conditional operator
Very useful e.g. to replace
if (Sex == SEX_MALE)
mes("You're Male.");
else
mes("You're Female.");
Operator precedence means some operators are evaluated before others. For
example, in 2 + 4 * 5 , the multiplication has higher precedence so 4 * 5 is
evaluated first yielding 2 + 20 == 22 and not 6 * 5 == 30 .
Labels
------
<label name>:
Labels are points of reference in your script, which can be used to route
execution with 'goto' and 'menu' commands, invoked with 'doevent', 'donpcevent'
and 'callsub' commands and are otherwise essential. A label's name may not be
longer than 23 characters. (24th is the ':'.) It may only contain alphanumeric
characters and underscore. In addition to labels you name yourself, there are
also some special labels which the script engine will start execution from if
a special event happens:
OnClock<hour><minute>:
OnMinute<minute>:
OnHour<hour>:
On<weekday><hour><minute>:
OnDay<month><day>:
This will execute when the server clock hits the specified date or time.
Hours and minutes are given in military time. ('0105' will mean 01:05 AM).
Weekdays are Sun, Mon, Tue, Wed, Thu, Fri, Sat. Months are 01 to 12, days are
01 to 31. Remember the zero. :)
OnInit:
OnInterIfInit:
OnInterIfInitOnce:
OnInit will execute every time the scripts loading is complete, including
when they are reloaded with @reloadscript command. OnInterIfInit will
execute when the map server connects to a char server, OnInterIfInitOnce
will only execute once and will not execute if the map server reconnects
to the char server later. Note that all those events will be executed upon
scripts reloading.
OnAgitStart:
OnAgitEnd:
OnAgitInit:
OnAgitStart2:
OnAgitEnd2:
OnAgitInit2:
OnAgitStart will run whenever the server shifts into WoE mode, whether it
is done with @agitstart GM command or with 'AgitStart' script command.
OnAgitEnd will do likewise for the end of WoE.
OnAgitInit will run when data for all castles and all guilds that hold a
castle is received by map-server from the char-server after initial
connect.
No RID will be attached while any of the above mentioned labels are
triggered, so no character or account-based variables will be accessible,
until you attach a RID with 'attachrid' (see below).
The above also applies to, the last three labels, the only difference is
that these labels are used exclusively for WoE SE, and are called
independently.
OnInstanceInit:
This label will be executed when an instance is created and initialized through
the 'instance_init' command. It will run again if @reloadscript is used while
an instance is in progress.
OnTouch:
This label will be executed if a trigger area is defined for the NPC
object it's in. If it isn't present, the execution will start from the
beginning of the NPC code. The RID of the triggering character object will
be attached.
OnTouch_:
Similar to OnTouch, but will only run one instance. Another character is
chosen once the triggering character leaves the area.
OnUnTouch:
This label will be executed if plater leave trigger area is defined for the NPC
object it's in. If it isn't present, nothing will happend.
The RID of the triggering character object will be attached.
OnPCLoginEvent:
OnPCLogoutEvent:
OnPCBaseLvUpEvent:
OnPCJobLvUpEvent:
It's pretty obvious when these four special labels will be invoked.
OnPCDieEvent:
This special label triggers when a player dies. The variable 'killerrid'
is set to the ID of the killer.
OnPCKillEvent:
This special label triggers when a player kills another player. The
variable 'killedrid' is set to the ID of the player killed.
OnNPCKillEvent:
This special label triggers when a player kills a monster. The variable
'killedrid' is set to the Class of the monster killed.
OnPCLoadMapEvent:
This special label will trigger once a player steps in a map marked with
the 'loadevent' mapflag and attach its RID. The fact that this label
requires a mapflag for it to work is because, otherwise, it'd be
server-wide and trigger every time a player would change maps. Imagine the
server load with 1,000 players (oh the pain...)
Only the special labels which are not associated with any script command
are listed here. There are other kinds of labels which may be triggered in
a similar manner, but they are described with their associated commands.
OnCountFunds:
This special label is triggered when a player opens a trader NPC object that
is NST_CUSTOM. It is used to define different currency types to the trader via
setcurrency(). Should be used along with OnPayFunds, see
doc/sample/npc_trader_sample.txt for more information.
OnPayFunds:
This special label is triggered when a purchase is made on a trader NPC object
that is NST_CUSTOM. Receives @price, total cost and @points, secondary input
field for cash windows. It is used to remove items that are set as currency.
Should be used along with OnCountFunds, see /doc/sample/npc_trader_sample.txt
for more information.
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 started with "On".
Example:
OnThisMobDeath:
announce("Hey, "+strcharinfo(PC_NAME)+" just killed a Poringz0rd!", bc_blue|
bc_all);
end;
}
Each time you kill one, that announce will appear in blue to everyone.
"Global" labels
There's a catch with labels and doevent(). If you call a label (using
doevent()) and called label is in NPC that has trigger area, that label must
end with "Global" to work globally (i.e. if RID is outside of the trigger area,
which usually happens since otherwise there would be no point calling the label
with doevent(), because OnTouch would do the job). For further reference look
for npc_event in npc.c.
All instructions must end with a ';'. Actually, you may expect to have multiple
instructions on one line if you properly terminate them with a ';', but it's
consider ill practice, since it impairs legibility of the script.
Please note that command and function names are case sensitive.
-------------------------
1 - Basic Commands
2 - Information-Retrieving Commands
-- 2.1 - Item-Related Commands
-- 2.2 - Guild-Related Commands
3 - Checking Commands
-- 3.1 - Checking Item-Related Commands
4 - Player-Related Commands
-- 4.1 - Player Item-Related Commands
-- 4.2 - Guild-Related Commands
-- 4.3 - Marriage-Related Commands
5 - Mob / NPC Related commands
-- 5.1 - Time-Related Commands
-- 5.2 - Guild-Related Commands
6 - Other Commands
7 - Instance-Related Commands
8 - Quest Log Commands
9 - Battleground Commands
10 - Mercenary Commands
11 - Queue Commands
12 - NPC Trader 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.
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. You may also use C_ constants accompany with "F_MesColor"
function for the color effect, see the full list of the available ones
in 'db/constants.conf' under 'C_'. 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.");
mesf("%sThis message is now in BLUE.", F_MesColor(C_BLUE));
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.
Will make the [Hat Maker] text clickable in the client and start a navigation
to that point.
This will allow you to visit 'Google' with the in-game browser using default
dimensions.
Clicking 'Bing!' will open the in-game browser using the specified dimensions.
(800x600)
If you're using client from 2013-01-30 onwards, you can also use <ITEMLINK> to show
the item's description. Gravity changed this into <ITEM> since 2015-07-29 onwards.
mes("Bring me an <ITEM>Apple<INFO>512</INFO></ITEM>.");
mesf("Bring me an %s.", F_MesItemInfo(Apple));
This will show the item name and a clickable link for the item description.
---------------------------------------
This command will display 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, after applying the same format-string replacements as sprintf().
Example:
---------------------------------------
*next()
This command will display a 'next' button in the message window for the
invoking character. Clicking on it will cause the window to clear and
display a new one. Used to segment NPC-talking, next() is often used in
combination with mes() and close().
mes("[Woman]");
mes("This would appear on the page");
next();
mes("[Woman]"); // This is needed since it is a new page and the top will now
be blank
mes("This would appear on the 2nd page");
---------------------------------------
*mesclear();
This command will clear the dialog text and continue the script without player
interaction.
Example:
mes("This is how the 'mesclear' script command works.");
sleep2 3000;
mesclear(); // This will clear the dialog and continue to the next one.
mes("I will show you again.");
sleep2 3000;
mesclear(); // This will clear the dialog and continue to the next one.
mes("Bye!");
---------------------------------------
*close()
This command will create a 'close' button in the message window for the
invoking character. If no window is currently on screen, the script
command 'end;' must be used. 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, since the script has ended.");
---------------------------------------
*close2()
This command will create a 'close' button in the message window for the
invoking character. WARNING: If no window is currently on screen, the
script execution will halt indefinitely! See 'close'. There is one
important difference, though - even though the message box will have
closed, the script execution will not stop, and commands after 'close2'
will still run, meaning an 'end' has to be used to stop the script, unless
you make it stop in some other manner.
mes("[Woman]");
mes("I will warp you now.");
close2();
warp("place", 50, 50);
end;
Don't expect things to run smoothly if you don't make your scripts 'end'.
---------------------------------------
*end
This instruction will stop the execution for this particular script.
Note that this is to be considered a special instruction (not a regular
command or function), and as such doesn't require parentheses.
Without the use of 'end' it would travel through the ifs 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 isn't the only way to set a variable directly: you can set them
much like any other programming language as stated before (refer to the
'Assigning variables' section).
Examples:
setd(".@var$", "Poporing");
mes(.@var$); // Displays "Poporing".
---------------------------------------
*getd("<variable name>")
Examples:
---------------------------------------
Examples:
//This will return the value of .var, note that this can't be used, since
//the value isn't caught.
getvariableofnpc(.var, "TargetNPC");
//This will set the .@v variable to the value of the TargetNPC's .var
//variable.
.@v = getvariableofnpc(.var, "TargetNPC");
---------------------------------------
*getvariableofpc(<variable>, <account id>{, <default value>})
Examples:
//This will return the value of @var, note that this can't be used, since
//the value isn't caught.
getvariableofpc(@var, getcharid(CHAR_ID_ACCOUNT, "player"));
//This will set the .@v variable to the value of the player's @var
//variable.
.@v = getvariableofpc(@var, getcharid(CHAR_ID_ACCOUNT, "player"));
---------------------------------------
*goto(<label>)
This command will make the script jump to a label, usually used in
conjunction with other instructions, such as "if", but often used on its own.
...
goto(Label);
mes("This will not be seen");
Label:
mes("This will be seen");
---------------------------------------
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.
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.
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.
if (<condition>) {
// We record the option into the list of options actually
// available.
.@menulist$[.@j] = .@possiblemenuitems$[.@i];
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:
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:
For the purposes of the technique described above these two statements are
perfectly equivalent.
---------------------------------------
This function is a handy replacement for 'menu' that doesn't use a complex
label structure. It will return the number of the menu option picked,
starting with 1. If the player presses cancel, the script is terminated.
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.
---------------------------------------
This function behaves exactly like select(), but when a player presses cancel
it returns MAX_MENU_OPTIONS and the script is not terminated. You almost always
want to use select() rather than prompt().
---------------------------------------
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();
.@number = rand(1, 10);
input(.@guess);
if (.@guess == .@number) {
mes("[Woman]");
mes("Well done that was the number I was thinking of");
close();
} else {
mes("[Woman]");
mes("Sorry, that wasn't the number I was thinking of.");
close();
}
If you give the input() command a string variable to put the input in, it
will allow the player to enter text. Otherwise, only numbers will be
allowed.
mes("[Woman]");
mes("Please say HELLO");
next();
input(.@var$);
if (.@var$ == "HELLO") {
mes("[Woman]");
mes("Well done you typed it correctly");
close();
} else {
mes("[Woman]");
mes("Sorry you got it wrong");
close();
}
Normally you may not input a negative number with this command.
This is done to prevent exploits in badly written scripts, which would let
people, for example, put negative amounts of Zeny into a bank script and
receive free Zeny as a result.
---------------------------------------
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' instruction 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%{
.@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, you
may do so:
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
}
function<TAB>script<TAB>SayHello<TAB>{
mes("Hello " + getarg(0));
return 0;
}
place,50,50,6<TAB>script<TAB>Man<TAB>115,{
mes("[Man]");
SayHello(strcharinfo(PC_NAME));
close();
}
Note:
---------------------------------------
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.
// ...
S_DunWarp:
// getarg(0) = "mapname"
// getarg(1) = x
// getarg(2) = y
if (Zeny >= 100) {
Zeny -= 100;
warp(getarg(0), getarg(1), getarg(2));
} else {
mes("Dungeon warp costs 100 Zeny.");
}
close();
---------------------------------------
*getarg(<index>{, <default_value>})
This function is used when you use the 'callsub' or 'callfunc' commands.
In the call you can specify variables that will make that call different
from another one. This function will return an argument the function or
subroutine was called with, and is the normal way to get them.
This is another thing that can let you use the same code more than once.
Argument numbering starts with 0, i.e. the first argument you gave is
number 0. If no such argument was given, a zero is returned.
place,50,50,6%TAB%script%TAB%Woman1%TAB%115,{
mes("[Woman]");
mes("Lets see if you win");
callfunc("funcNPC", 2);
mes("Well done you have won");
// ...
}
place,52,50,6%TAB%script%TAB%Woman2%TAB%115,{
mes("[Woman]");
mes("Lets see if you win");
callfunc("funcNPC", 5);
mes("Well done you have won");
// ...
}
function%TAB%script%TAB%funcNPC%TAB%{
.@win = rand(getarg(0));
if (.@win == 0)
return;
mes("Sorry you lost");
close();
}
"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.
callfunc("funcNPC", 5, 4, 3);
In previous example getarg(2, -1) would be 3 and getarg(3, -1) would be -1.
---------------------------------------
*getargcount()
This function is used when you use the 'callsub' or 'callfunc' commands.
In the call you can specify arguments. This function will return the
number of arguments provided.
Example:
callfunc("funcNPC", 5, 4, 3);
// ...
function%TAB%script%TAB%funcNPC%TAB%{
.@count = getargcount(); // 3
//...
}
---------------------------------------
*return {<value>}
---------------------------------------
This works like callfunc(), and is used for cleaner and faster scripting.
The function must be defined and used within a script, and works like a
label with arguments.
Note that the name may only contain alphanumeric characters and underscore.
Usage:
Example:
/* Function definition */
function SF_Selling {
mes("Would you like to buy a phracon for 50z?");
next();
if (select("Yes", "No, thanks") == 1) {
Zeny -= 50;
getitem(Phracon, 1);
mes("Thank you!");
}
return;
}
}
/* Function definition */
function MyAdd {
return(getarg(0)+getarg(1));
}
}
---------------------------------------
*is_function("<function name>")
This command checks whether or not a function exists and returns its type.
Returns false if it cannot be found.
return values:
Example:
func3:
end;
is_function("func1"); // FUNCTION_IS_GLOBAL
is_function("func2"); // FUNCTION_IS_LOCAL
is_function("func3"); // FUNCTION_IS_LABEL
is_function("select"); // FUNCTION_IS_COMMAND
is_function("invalid"); // false
}
---------------------------------------
if (true)
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.");
Example 1:
.@var1 = 1;
input(.@var2);
if (.@var1 == .@var2)
close();
mes("Sorry that is wrong");
close();
Example 2:
.@var1 = 1;
input(.@var2);
if (.@var1 != .@var2)
mes("Sorry that is wrong");
close();
Example 3:
++@var1;
mes("[Forgetfull Man]");
if (@var == 1)
mes("This is the first time you have talked to me");
if (@var == 2)
mes("This is the second time you have talked to me");
if (@var == 3)
mes("This is the third time you have talked to me");
if (@var == 4)
mes("This is the forth time you have talked to me, but I think I am
getting amnesia, I have forgotten about you");
if (@var == 4)
@var = 0;
close();
Example 4:
mes("[Quest Person]");
// The (AegisName) constant Apple comes from item_db, it is the item number
512.
if (countitem(Apple) >= 1) {
mes("Oh an apple, I didn't want it, I just wanted to see one");
close();
}
mes("Can you please bring me an apple?");
close();
mes("[Multi Checker]");
if ((queststarted == 1) && (countitem(Apple) >= 5)) {
// Executed only if the quest has been started AND You have 5 apples
mes("[Multi Checker]");
mes("Well done you have started the quest of got me 5 apples");
mes("Thank you");
queststarted = 0;
delitem(Apple, 5);
close();
}
mes("Please get me 5 apples");
queststarted = 1;
close();
If the condition doesn't meet, it'll do the action following the else.
We can also group several actions depending on a condition, this way:
if (<condition>) {
dothis1();
dothis2();
} else {
dothat1();
dothat2();
dothat3();
}
Example 6:
mes("[Person Checker]");
if ($name$ == "") {
mes("Please tell me someone's name");
next();
input($name$);
$name2$ = strcharinfo(PC_NAME);
mes("[Person Checker]");
mes("Thank you");
close();
}
if ($name$ == strcharinfo(PC_NAME)) {
mes("You are the person that " +$name2$+ " just mentioned");
mes("nice to meet you");
} else {
mes("You are not the person that " +$name2$+ " mentioned");
}
$name$ = "";
$name2$ = "";
close();
Remember that if you plan to do several actions upon the condition being
false, and you forget to use the curly braces (the { } ), the second
action will be executed regardless the output of the condition, unless of
course, you stop the execution of the script if the condition is true
(that is, in the first grouping using a return, and end or a close()).
Also, you can have multiple conditions nested or chained, and don't worry
about limits as to how many nested if you can have, there is no spoon ;).
...
if (<condition 1>) {
dothis();
} else if (<condition 2>) {
dotheother();
do_that();
end;
} else {
do_this();
}
...
---------------------------------------
This is probably the simplest and most frequently used loop structure. The
'while' statement can be interpreted as "while <condition> is true,
perform <statement>". It is a pretest loop, meaning the conditional
expression is tested before any of the statements in the body of the loop
are performed. If the condition evaluates to false, the statement(s) in
the body of the loop is/are never executed. If the condition evaluates to
true, the statement(s) are executed, then control transfers back to the
conditional expression, which is reevaluated and the cycle continues.
Multiple statements can be grouped with { }, curly braces, just like with
the 'if' statement.
Example 1:
while (select("Yes", "No") == 2)
mes("You picked no.");
---------------------------------------
Example 1:
for (.@i = 0; .@i < 5; ++.@i)
mes("This line will print 5 times.");
Example 2:
mes("This will print the numbers 1 - 5.");
for (.@i = 1; .@i <= 5; ++.@i)
mes(.@i);
---------------------------------------
---------------------------------------
*freeloop(<toggle>)
Toggling this to enabled (true) allows the script instance to bypass the
infinite loop protection, allowing your script to loop as much as it may
need. Disabling (false) may warn you if an infinite loop is detected if your
script is looping too many times.
Please note, once again, that this isn't a solution to all problems, and by
disabling this protection your Hercules server may become laggy or
unresponsive if the script it is used in is performing lenghty loop
operations.
Example:
freeloop(true); // enable script to loop freely
freeloop(false); // disable
---------------------------------------
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.
The index of the first element of the array to alter can be omitted if
zero. For example:
will produce:
.@array[0] = 200
.@array[1] = 300
.@array[2] = 150
---------------------------------------
This command will change many array values at the same time to the same
value.
See 'setarray'.
---------------------------------------
This command lets you quickly shuffle a lot of data between arrays, which
is in some cases invaluable.
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.
---------------------------------------
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 all elements of the array starting from 2, leaving
// element 0 and 1
deletearray(.@array[2]);
---------------------------------------
//=====================================
1 - End of Basic-Related Commands
//=====================================
---------------------------------------
---------------------------------------
//=====================================
2 - Information-retrieving Related Commands
//=====================================
---------------------------------------
This function will return either the name, party name or guild name for
the invoking character. Whatever it returns is determined by type.
(0) PC_NAME - Character's name.
(1) PC_PARTY - The name of the party they're in if any.
(2) PC_GUILD - The name of the guild they're in if any.
(3) PC_MAP - The name of the map the character is in.
(4) PC_CLAN - The name of the clan they're in if any.
If <GID> is passed, it will return the value of the specified player instead
the attached player. If the player is not found, it will return
<default value>, if any, or else return an empty string.
Note: Numbers can also be used in <type>, but their usage is disncouraged as
using only numbers reduces script readability
---------------------------------------
If <GID> is passed, it will return the value of the specified NPC instead of
the attached NPC. If the NPC is not found, it will return <default value>,
if any, or else return an empty string.
---------------------------------------
*charid2rid(<char id>)
This function returns the RID of the character with the given character ID.
---------------------------------------
*getarraysize(<array name>)
For example:
If you do this:
.@array[1000] = 1;
.@arraysize = getarraysize(.@array);
.@arraysize will be 1000, even though only one element has been set.
---------------------------------------
*getarrayindex(<array name>)
This command returns the index of the passed array. This is useful when
used in combination with getarg()
Example:
getarrayindex(.@foo[42]) // 42
---------------------------------------
This command retrieves the value of the element of given array at given
index. This is equivalent to using:
<array name>[<index>]
---------------------------------------
Example parameters:
All of these also behave as variables, but don't expect to be able to just
'set' them - some will not work for various internal reasons.
Example 1:
Example 2:
Example 3:
---------------------------------------
---------------------------------------
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 (getcharid(CHAR_ID_GUILD) == 0)
mes("Only members of a guild are allowed here!");
---------------------------------------
*getnpcid({"<npc name>"})
Retrieves IDs of the currently invoked NPC. If a unique npc name is given,
IDs of that NPC are retrieved instead.
---------------------------------------
*getchildid()
*getmotherid()
*getfatherid()
---------------------------------------
*ispartneron()
---------------------------------------
*getpartnerid()
if (getpartnerid() == 0)
mes("I'm not going to be your girlfriend!");
else
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.
// 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!");
---------------------------------------
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.
Example 2: check party count (with a next() pause), before warping to event
if ($@partymembercount != .register_num) {
mes("Please form a party of "+ .register_num +" to continue");
close();
}
// loop through both and use 'isloggedin' to count online party members
for (.@i = 0; .@i < $@partymembercount; ++.@i)
if (isloggedin($@partymemberaid[.@i], $@partymembercid[.@i]))
.@count_online++;
// We search accountID & charID because a single party can have
// multiple characters from the same account. Without searching
// through the charID, if a player has 2 characters from the same
// account inside the party but only 1 char online, it would count
// their online char twice.
if (.@count_online != .register_num) {
mes("All your party members must be online to continue");
close();
}
// When a script hits a next, menu, sleep or input that pauses the
// script, players can invite or /leave and make changes in their
// party. To prevent this, we call getpartymember again and compare
// with the original values.
getpartymember(getcharid(CHAR_ID_PARTY), 1);
if ($@partymembercount != .register_num) {
mes("You've made changes to your party !");
close();
}
for (.@i = 0; .@i < $@partymembercount; ++.@i) {
if (.@partymembercid[.@i] != $@partymembercid[.@i]) {
mes("You've made changes to your party !");
close();
}
}
---------------------------------------
This function returns some information about the given party-id's leader.
When type is omitted, the default information retrieved is the leader's
name. Possible types are:
1: Leader account id
2: Leader character id
3: Leader's class
4: Leader's current map name
5: Leader's current level as stored on the party structure (may not be
current level if leader leveled up recently).
If retrieval fails (leader not found or party does not exist), this
function returns "null" instead of the character name, and -1 for the
other types.
---------------------------------------
*getlook(<type>)
This function will return the number for the current character look value
specified by type. See 'setlook' for valid look types.
This can be used to make a certain script behave differently for
characters dressed in black. :)
---------------------------------------
*getsavepoint(<information type>)
This function will return information about the invoking character's save
point. You can use it to let a character swap between several recorded
save points. Available information types are:
---------------------------------------
*getcharip({"<character name>"})
*getcharip({<account id>})
*getcharip({<character id>})
This function will return the IP address of the invoking character, or, if
a player is specified, of that character. A blank string is returned if no
player is attached.
Examples:
---------------------------------------
*sit({"<character name>"})
*stand({"<character name>"})
---------------------------------------
*issit({"<character name>"})
This function will return a number depending on the character's sitting state.
If the character is sitting, it will return true, otherwise (standing) it will
return false.
In case no player is specified, the function will return the state of the attached
player.
---------------------------------------
//=====================================
2.1 - Item-Related Commands
//=====================================
---------------------------------------
*getequipid(<equipment slot>)
This function returns the item ID of the item equipped in the equipment
slot specified on the invoking character. If nothing is equipped there, it
returns -1. Valid equipment slots are:
Notice that a few items occupy several equipment slots, and if the
character is wearing such an item, 'getequipid' will return it's ID number
for either slot.
Can be used to check if you have something equipped, or if you haven't got
something equipped:
if (getequipid(EQI_HEAD_TOP) == Tiara) {
mes("What a lovely Tiara you have on");
close();
}
mes("Come back when you have a Tiara 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:
---------------------------------------
*getequipname(<equipment slot>)
Returns the jname of the item equipped in the specified equipment slot on
the invoking character, or an empty string if nothing is equipped in that
position.
Does the same thing as getitemname(getequipid()). Useful for an NPC to
state what your are wearing, or maybe saving as a string variable.
See getequipid() for a full list of valid equipment slots.
if (getequipid(EQI_HEAD_TOP) != 0)
mes("So you are wearing a "+getequipname(EQI_HEAD_TOP)+" on your
head");
else
mes("You are not wearing a head gear");
---------------------------------------
*getitemname(<item id>)
Given the database ID number of an item, this function will return the
text stored in the 'japanese name' field (which, in Hercules, stores an
English name the players would normally see on screen).
Return "null" if no such item exist.
---------------------------------------
*getbrokenid(<number>)
This function will search the invoking character's inventory for any
broken items, and will return their item ID numbers. Since the character
may have several broken items, 1 given as an argument will return the
first one found, 2 will return the second one, etc. Will return 0 if no
such item is found.
---------------------------------------
*getbrokencount()
This function will return the total amount of broken equipment on the
invoking character.
---------------------------------------
*getequipisequiped(<equipment slot>)
---------------------------------------
*getequipisenableref(<equipment slot>)
Will return true if the item equipped on the invoking character in the
specified equipment slot is refinable, and false if it isn't. For a list
of equipment slots see getequipid().
if (getequipisenableref(EQI_HEAD_TOP)) {
mes("[Refiner]");
mes("Ok I can refine this");
close();
}
mes("[Refiner]");
mes("I can't refine this hat!...");
close();
---------------------------------------
For example:
if (getequiprefinerycnt(EQI_HEAD_TOP) > 10) {
mes("You equipped a headgear (top) with above 10 refine.");
}
For example:
if (getequiprefinerycnt(EQI_ARMOR, EQI_SHOES) > 20) {
mes("Total refine of Armor and Shoes exceed 20.");
}
---------------------------------------
*getequipweaponlv(<equipment slot>)
This function returns the weapon level for the weapon equipped in the
specified equipment slot on the invoking character. For a list of
equipment slots see 'getequipid'.
Only EQI_HAND_L and EQI_HAND_R normally make sense, since only weapons
have a weapon level. You can, however, probably, use this field for other
equippable custom items as a flag or something.
---------------------------------------
---------------------------------------
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 (Apple).
---------------------------------------
*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 its inventory, including all the data needed to
recreate these items perfectly if they are destroyed. Here's what you get:
Notice that the variables this command generates are all temporary,
attached to the character, and integer.
---------------------------------------
*getcartinventorylist()
This command sets a bunch of arrays with a complete list of whatever the
invoking character has in its cart_inventory, including all the data needed to
recreate these items perfectly if they are destroyed. Here's what you get:
---------------------------------------
*setfavoriteitemidx(<idx>, <flag>)
Valid Parameters:
<idx> - inventory index, refer *getinventorylist()
<flag> - true/false (true = favorite item, false = otherwise)
---------------------------------------
*autofavoriteitem(<item_id>, <flag>)
This function will auto set an item as favorite when <item_id> is obtained.
If its favorite item, it will be auto moved to favorite tab, else move out from
favorite tab.
This setting affect not only attached player, but also everyone player globally.
Valid Parameters:
<item_id> - item ID
<flag> - true/false (true = favorite item, false = otherwise)
---------------------------------------
*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 refine count of the equipment from which
the function is called. This function is intended for use in item scripts.
if (getrefine() == 10)
mes("Wow. That's a murder weapon.");
---------------------------------------
*getitemslots(<item ID>)
This function will look up the item with the specified ID number in the
database and return the number of slots this kind of items has - 0 if they
are not slotted. It will also be 0 for all non-equippable items,
naturally, unless someone messed up the item database. It will return -1
if there is no such item.
Example:
//.@slots now has the amount of slots of the item with ID 1205.
.@slots = getitemslots(1205);
---------------------------------------
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.
The setiteminfo function will, instead, set the item's parameters. It returns
the new value on success, or -1 on failure (item_id not found).
Example:
---------------------------------------
*getequipisenableopt(<equipment slot>)
This function checks if the equipped item allows the use of bonus options.
---------------------------------------
*getequippedoptioninfo(<info_type>);
---------------------------------------
*getequipoption(<equip_index>,<slot>,<type>);
returns the value of the slot if exists or -1 for invalid slot, type or slots.
---------------------------------------
*setequipoption(<equip_index>,<slot>,<opt_index>,<value>);
Set an equipment's option index or value for the specified option slot.
---------------------------------------
Returns value for equipped item slot in the indicated slot (0, 1, 2, or 3).
This function returns CARD ID, 255, 254, -255 (for card 0, if the item is
produced). It's useful for when you want to check whether an item contains
cards or if it's signed.
---------------------------------------
This will set a Hat Effect onto the player. The state field allows you to
enable (true) or disable (false) the effect on the player.
---------------------------------------
*identify(<Item ID>)
This function identifies the first <Item ID> item in attached player's inventory.
---------------------------------------
*identifyidx(<Inventory Index>)
This will identify item at attached player's <Inventory Index> inventory index.
---------------------------------------
//=====================================
2.1 - End of Item-Related Commands
//=====================================
---------------------------------------
*getmapxy("<variable for map name>", <variable for x>, <variable for y>, <type>{,
"<search parameter>"})
To look for a monster object, monster GID is required. The function will
always return -1 when search using string.
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, UNITTYPE_NPC, "Meh") != 0) {
mes("I can't seem to find Meh anywhere!");
close();
}
mes("And I found him on map "+.@mapname$+" at X:"+.@mapx+" Y:"+.@mapy+"
!");
close();
}
Notice that NPC objects disabled with disablenpc() will still be located.
---------------------------------------
This command returns various information about a specific map. If the second
argument is omitted, it will try to use the map of the attached NPC, or the
map of the attached player if the NPC can't be found.
Examples:
getmapinfo(MAPINFO_ID, "map name"); // ID from name
getmapinfo(MAPINFO_NAME, 3); // name from ID
getmapinfo(MAPINFO_ZONE); // zone, ie Normal, PvP, Jail, ...
---------------------------------------
This function searches a whole map or area for units and adds their GID to
the provided <variable> array. It filters units by <type> and stops searching
after <limit> units have been found. Set <limit> to false (0) if you wish to
disable the limit altogether. If <map> is omitted, this command will search
on the whole server (slow). Returns the number of units added to the array.
Example:
The above example would search the map "prontera" for all PC and NPC units and
add them to the .@units array, while setting .@count to the amount of units
added to the array (useful in for() loops).
---------------------------------------
*getgmlevel()
This function will return the (GM) level of player group the account to
which the invoking character belongs. If this is somehow executed from a
console command, 99 will be returned, and 0 will be returned if the
account has no GM level.
This allows you to make NPC's only accessible for certain GM levels, or
behave specially when talked to by GMs.
if (getgmlevel() > 0)
mes("What is your command, your godhood?");
if (getgmlevel() < 99)
end;
---------------------------------------
This function will temporary adjust the id of player group the account to which the
player specified if the new group id is available.
Return true if successful, otherwise it will return false.
---------------------------------------
*getgroupid({<account id>})
This command returns the id of the group of the attached or specified player.
If the player is not found, returns -1.
---------------------------------------
*gettimetick(<type>)
---------------------------------------
*gettime(<type>)
This function returns specified information about the current system time.
Valid types:
1 - GETTIME_SECOND - Seconds (of a minute)
2 - GETTIME_MINUTE - Minutes (of an hour)
3 - GETTIME_HOUR - Hour (of a day)
4 - GETTIME_WEEKDAY - Week day (0 for Sunday, 6 is Saturday)
- Additional: SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY
5 - GETTIME_DAYOFMONTH - Day of the month.
6 - GETTIME_MONTH - Number of the month.
- Additional: JANUARY, FEBRUARY, MARCH, APRIL, MAY,
JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER
7 - GETTIME_YEAR - Year
8 - GETTIME_DAYOFYEAR - Day of the year.
---------------------------------------
This function returns the timestamp of the next ocurrence of given time.
Day of Month specifies a day between 1 and 31 in the future, by default its value
is -1 (don't use).
Day of Week specifies a day in the week and its valid values are:
0 - SUNDAY
1 - MONDAY
2 - TUESDAY
3 - WEDNESDAY
4 - THURSDAY
5 - FRIDAY
6 - SATURDAY
In order to use Day of Week, you must use Day of Month as -1.
If for some reason the command fails, it'll return -1.
Examples :
getcalendartime(19, 00); // Next 7 pm
getcalendartime(19, 00, 6); // Next day 6 of the month, at 7pm
getcalendartime(19, 10, -1, 1); // Next Monday, at 7:10pm
---------------------------------------
This will print a full date and time like 'YYYY-MM/DD HH:MM:SS'.
---------------------------------------
*getusers(<type>)
This function will return a number of users on a map or the whole server.
What it returns is specified by Type.
Type can be one of the following values, which control what is returned:
---------------------------------------
*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.
---------------------------------------
This function will return the count of connected characters which are
located within the specified area. Area can be x1/y1-x2/y2 square,
or radius from npc position. If map name missing, used attached player 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.
Examples:
// return players in area npc area on current map.
.@num = getareausers();
// return players in square (1, 1) - (10, 10)
.@num = "players: " + getareausers(1, 1, 10, 10);
---------------------------------------
*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.
---------------------------------------
//=====================================
2.2 - Guild-Related Commands
//=====================================
---------------------------------------
*getguildname(<guild id>)
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.
mes(getguildmaster(10007)+" runs "+getguildname(10007));
Can be used to check if the character is the guild master of the specified
guild.
Maybe you want to make a room only guild masters can enter:
.@GID = getcharid(CHAR_ID_GUILD);
if (.@GID == 0) {
mes("Sorry you are not in a guild");
close();
}
if (strcharinfo(PC_NAME) == getguildmaster(.@GID)) {
mes("Welcome guild master of "+getguildname(.@GID));
close();
}
mes("Sorry you don't own the guild you are in");
close();
---------------------------------------
*getguildmasterid(<guild id>)
This function will return the character ID number of the guild master of
the guild specified by the ID. 0 if the character is not a guild master of
any guild.
---------------------------------------
*getcastlename("<map name>")
This function returns the name of the castle when given the map name for
that castle. The data is read from 'db/castle_db.txt'.
---------------------------------------
This function returns the castle ownership information for the castle
referred to by its map name. Castle information is stored in
`guild_castle` SQL table.
---------------------------------------
This function returns the level of the skill <skill id> of the guild
<guild id>.
If the guild does not have that skill, 0 is returned.
If the guild does not exist, -1 is returned.
Refer to 'db/(pre-)re/skill_db.txt' for the full list of skills.
GD_* are guild skills
---------------------------------------
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.
---------------------------------------
Returns the amount of characters from the specified guild on the given map.
Example:
---------------------------------------
This command will find all members of a specified guild and returns their names
(or character id or account id depending on the value of "type") into an array
of temporary global variables.
The guild members will be found regardless of whether they are online or offline.
Note that the names come in no particular order.
---------------------------------------
---------------------------------------
//=====================================
2.2 - End of Guild-Related Commands
//=====================================
---------------------------------------
*getskilllv(<skill id>)
*getskilllv("<skill name>")
This function returns the level of the specified skill that the invoking
character has. If they don't have the skill, 0 will be returned. The full
list of character skills is available in 'db/(pre-)re/skill_db.txt'.
There are two main uses for this function, it can check whether the
character has a skill or not, and it can tell you if the level is high
enough.
Example 1:
if (getskilllv(TF_THROWSTONE)) {
// TF_THROWSTONE is defined in skill_db.txt and its value is 152
mes("You have got the skill Throw Stone");
close();
}
mes("You don't have Throw Stone");
close();
Example 2:
if (getskilllv(AL_HEAL) == 10) {
mes("Your heal lvl has been maxed");
close();
}
if (getskilllv(AL_HEAL) >= 5) {
mes("Your heal lvl is 5 or more");
close();
}
mes("You heal skill is below lvl 5");
close();
---------------------------------------
*getskilllist();
This command sets a bunch of arrays with a complete list of skills the
invoking character has. Here's what you get:
While getskilllv() 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 command will return the currently active pet information of the invoking
character.
These fields are associate in 'db/(pre-)re/pet_db.conf'. Valid types are:
PETINFO_ID - Pet Database ID, stored in `pet` table to distinguish
from other pets.
PETINFO_CLASS - Pet class ID. (Id field)
PETINFO_NAME - Pet Name, return "null" if there's no active pet.
PETINFO_INTIMACY - Pet Intimacy level. 1000 is full loyalty.
PETINFO_HUNGRY - Pet hungry level. 100 is completely full.
PETINFO_RENAME - Pet rename flag. 0 means this pet has not been named
yet.
PETINFO_GID - Pet Game ID
PETINFO_EGGITEM - Pet EggItem
PETINFO_FOODITEM - Pet FoodItem
PETINFO_ACCESSORYITEM - Pet AccessoryItem
PETINFO_ACCESSORYFLAG - return 1 if the pet currently equipping accessory,
return 0 otherwise.
PETINFO_EVO_EGGID - Pet Evolve EggID
PETINFO_AUTOFEED - Pet AutoFeed flag.
---------------------------------------
*petstat(<flag>)
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ /!\ This command is deprecated @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Flags usable:
PET_CLASS
PET_NAME
PET_LEVEL
PET_HUNGRY
PET_INTIMATE
Example:
.@i = petstat(PET_CLASS);
---------------------------------------
This function will look up the monster with the specified ID number in the
mob database and return the info set by TYPE argument.
It will return -1 if there is no such monster (or the type value is
invalid), or "null" if you requested the monster's name.
---------------------------------------
Both the monster and the item must be valid. Acceptable values for the drop
rate are in the range [1:10000].
Return value will be 1 in case of success (the item was added or its drop rate
was updated), and 0 otherwise (there were no free item drop slots).
Example:
// Add Poring Doll (741) to the Poring's (1002) drops, with 1% (100) rate
addmonsterdrop(PORING, Poring_Doll, 100);
---------------------------------------
Return value will be true in case of success (the item was removed), and
false otherwise (the monster didn't have the specified item in its drop
list).
Example:
// Remove Jellopy (909) from the Poring's (1002) drops
delmonsterdrop(PORING, Jellopy);
---------------------------------------
*getmobdrops(<mob id>)
This command will find all drops of the specified mob and return the item
IDs and drop percentages into arrays of temporary global variables.
getmobdrops() returns true if successful and false if the mob ID doesn't
exist.
Example:
---------------------------------------
*skillpointcount()
Example:
//This will set the temp character variable @skill_points to the amount of
//skill points, and then tell the player the value.
@skill_points = skillpointcount();
mes("You have "+@skill_points+" skill points in total!");
//Self-explanatory... :P
if (skillpointcount() > 20)
mes("Wow, you have more then 20 Skill Points in total!");
This command does not count skills which are set as flag 3 (permamently
granted) (e.g. ALL_BUYING_STORE/ALL_INCCARRY).
---------------------------------------
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.
You can see the full list of available effect types you can possibly
inflict in 'doc/constants.md' under 'Status effects'.
---------------------------------------
//=====================================
3 - Checking-Related Commands
//=====================================
---------------------------------------
*playerattached()
---------------------------------------
---------------------------------------
*checkweight(<item id>, <amount>{, <item id>, <amount>, <item id>, <amount>, ...})
*checkweight("<item name>", <amount>{, "<item name>", <amount>, "<item name>",
<amount>, ...})
*checkweight2(<id_array>, <amount_array>)
These functions will compute and return true if the total weight of the
specified number of specific items does not exceed the invoking
character's carrying capacity, and false otherwise. It is important to
see if a player can carry the items you expect to give them, failing to
do that may open your script up to abuse or create some very unfair
errors.
The second function will check an array of items and amounts, and also
returns true on success and false on failure.
Like getitem(), this function will also accept an 'english name' from
the database as an argument.
Example 1:
if (checkweight(Apple, 10)) {
getitem(Apple, 10);
} else {
mes("Sorry, you cannot hold this amount of apples!");
}
Example 2:
---------------------------------------
*basicskillcheck()
---------------------------------------
Option numbers valid for the first (option) version of this command are:
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:
0x01 -
Poisoned.
0x02 -
Cursed.
0x04 -
Silenced.
0x08 -
Signum Crucis (plays a howl-like sound effect, but otherwise no
visible effects are displayed)
0x10 - Blinded.
0x80 - Deadly poisoned.
Option numbers (except for opt1) are bit-masks - you can add them up to
check for several states, but the functions will return true if at least
one of them is in effect.
*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 true if the invoking character has a
cart (any kind of cart) and false 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 true if the invoking character has a
falcon and false if they don't.
if (checkfalcon())
mes("But you already have a falcon!");
---------------------------------------
*setmount({<flag>})
*checkmount()
If <flag> is MOUNT_NONE this command will remove the mount from the
character.
Otherwise it gives the invoking character the desired combat mount, where
allowed by their class and skills.
MOUNT_NONE:
- Dismount
MOUNT_PECO:
- PecoPeco (Knight series class)
- GrandPeco (Crusader series class)
- Gryphon (Royal Guard)
MOUNT_WUG:
- Warg (Ranger)
MOUNT_MADO:
- Mado Gear (Mechanic)
MOUNT_DRAGON:
MOUNT_DRAGON_GREEN:
MOUNT_DRAGON_BROWN:
MOUNT_DRAGON_GRAY:
MOUNT_DRAGON_BLUE:
MOUNT_DRAGON_RED:
- Dragon (Rune Knight)
if MOUNT_DRAGON is specified, a the default (green) dragon will be used.
Unlike 'setfalcon' and 'setcart' this will not work at all if they aren't of a
class which can ride a mount.
if (checkmount())
mes("Leave your mount outside! No riding mounts on the floor here!");
if (checkmount() == MOUNT_DRAGON)
mes("Wow, your dragon is cool! Can I pet it?");
---------------------------------------
*setcashmount()
*hascashmount()
The 'setcashmount' function toggles cash mount for the invoking character.
It will return true if successful, false otherwise.
Note: Character must not be mounting a non-cash mount (eg. dragon, peco,
wug, etc.)
The accompanying function will return true if the invoking character has a
cash mount and false if they don't.
---------------------------------------
*checkwug()
This function will return true if the invoking character has a warg and false if
they don't.
---------------------------------------
*checkvending({"<Player Name>"})
*checkchatting({"<Player Name>"})
Examples:
//This will check if Aaron is vending, and if so, put a message in
//front of the attached player saying Aaron is vending.
if (checkvending("Aaron"))
mes("Aaron is currently vending!");
---------------------------------------
*checkidle({"<Player Name>"})
Returns the time, in seconds, that the specified player has been idle.
Name is optional, and defaults to the attached player if omitted.
---------------------------------------
*agitcheck()
*agitcheck2()
These function will let you check whether the server is currently in WoE
mode (or WoE SE mode if the second function is called) and will return true
if War of Emperium is on and false if it isn't.
---------------------------------------
*isnight()
This functions will return true or false depending on whether the server is in
night mode or day mode:
if (!isnight())
mes("I only prowl in the night.");
---------------------------------------
//=====================================
3.1 - Checking Item-Related Commands
//=====================================
---------------------------------------
This function will return true if the invoking character has all of the item
IDs given equipped (if card IDs are passed, then it checks if the cards
are inserted into slots in the equipment they are currently wearing).
Theoretically there is no limit to the number of items that may be tested
for at the same time.
If even one of the items given is not equipped, false will be returned.
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.
---------------------------------------
---------------------------------------
*checkequipedcard(<card id>)
This function will return true if the card specified by it's item ID number
is inserted into any equipment they have in their inventory, currently
equipped or not.
---------------------------------------
*getequipisidentify(<equipment slot>)
This function will return true if an item in the specified equipment slot is
identified and false 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 true all the time if there is an item in this
equipment slot, which makes this script command kinda pointless.
For a list of equipment slots see getequipid().
---------------------------------------
//=====================================
3.0 & 3.1 - End of Checking/Item-Related Commands
//=====================================
---------------------------------------
---------------------------------------
//=====================================
4 - Player-Related Commands
//=====================================
---------------------------------------
*attachrid(<account ID>)
*detachrid()
---------------------------------------
*rid2name(<account id>)
Note: rid2name() may not produce correct character names since RID means
account id.
It will return the current online character of the account only.
---------------------------------------
That command will send a message to the chat window of the character
specified by account ID or name. The text will also appear above the head
of that character. It will not be seen by anyone else.
---------------------------------------
*dispbottom("<message>"{, <color>})
This command will send the given message into the invoking character's
chat window. The color format is in RGB (0xRRGGBB), and default to green
if <color> field is left out.
---------------------------------------
---------------------------------------
This command will take the invoking character to the specified map, and if
wanted, specified coordinates too, but these can be random.
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. Beware if you're using custom maps.
There are also three special 'map names' you can use:
---------------------------------------
*areawarp("<from map name>", <x1>, <y1>, <x2>, <y2>, "<to map name>", <x3>, <y3>{,
<x4>, <y4>})
areawarp("place", 10, 10, 120, 120, "place2", 150, 150, 200, 200);
Like warp(), areawarp() will also explicitly warp characters randomly into
the current map if you give the 'to map name' as "Random".
---------------------------------------
Warps a party to specified map and coordinate given the party ID, which
you can get with getcharid(CHAR_ID_PARTY). You can also request another party id
given
a member's name with getcharid(CHAR_ID_PARTY, <player_name>).
You can use the following "map names" for special warping behavior:
Random: All party members are randomly warped in their current map
(as if they all used a fly wing).
SavePointAll: All party members are warped to their respective save point.
SavePoint: All party members are warped to the save point of the
currently attached player (will fail if there's no player
attached).
Leader: All party members are warped to the leader's position. The
leader must be online and in the current map-server for
this to work.
You can exclude Party leader from warping, by keeping include_leader option as
false.
Example:
mes("[Party Warper]");
mes("Here you go!");
close2();
.@id = getcharid(CHAR_ID_PARTY);
warpparty("prontera", 150, 100, .@id, true);
close();
---------------------------------------
Warps another player to specified map and coordinate given the char id,
which you can get with getcharid(CHAR_ID_CHAR, <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:
---------------------------------------
Warps a guild to specified map and coordinate given the guild id, which
you can get with getcharid(CHAR_ID_GUILD). You can also request another guild id
given
the member's name with getcharid(CHAR_ID_GUILD, <player_name>).
You can use the following "map names" for special warping behavior:
Random: All guild members are randomly warped in their current map
(as if they all used a fly wing)
SavePointAll: All guild members are warped to their respective save point.
SavePoint: All guild members are warped to the save point of the
currently attached player (will fail if there's no player
attached).
If you specify a from_mapname, warpguild() will only affect those on that map.
Example:
warpguild("prontera", x, y, Guild_ID);
warpguild("prontera", x, y, Guild_ID, "payon"); // warp member from Payon map
only.
---------------------------------------
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 true upon success and false 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.
---------------------------------------
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.
---------------------------------------
*heal(<hp>, <sp>)
This command just alters the hit points and spell points of the invoking
character and produces no other output whatsoever.
---------------------------------------
*itemheal(<hp>, <sp>)
There is also a nice example on using this with the rand() function, to
give you a random amount of healing.
---------------------------------------
*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.
So the amount that this will heal will depend on the total amount of HP or
SP you have maximum. Like heal(), this will not call up any animations or
effects.
---------------------------------------
*recovery({<account id>})
*recovery("<map name>"{, <x1>, <y1>, <x2>, <y2>})
This command will revive and restore full HP and SP to all characters currently
connected to the server. If an account id is supplied, it will instead only
affect this character. If a map is supplied it will affect a whole map or area.
---------------------------------------
This command will change the job class of the invoking character.
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
'doc/constants.md'.
'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
---------------------------------------
*jobname(<job number>)
This command retrieves the name of the given job using the names defined
in messages.conf.
mes("[Kid]");
mes("I never thought I'd met a "+jobname(Class)+" here of all places.");
close();
---------------------------------------
*eaclass({<job number>})
.@eac = eaclass();
if ((.@eac&EAJ_BASEMASK) == EAJ_SWORDMAN)
mes("Your base job is Swordman.");
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.");
---------------------------------------
*roclass(<job number> {, <gender>})
.@eac = eaclass();
//Check if class is already rebirth
if (.@eac&EAJL_UPPER) {
mes("You look strong.");
close();
}
.@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 command will change the appearance of the invoking character to that
of a specified job class. Nothing but appearance will change.
Examples:
---------------------------------------
---------------------------------------
*changesex()
This command will change the gender for the attached character's account.
If it was male, it will become female, if it was female, it will become
male. The change will be written to the character server, the player will
receive the message: "Need disconnection to perform change-sex request..."
and the player will be immediately kicked to the login screen. When they
log back in, they will be the opposite sex.
---------------------------------------
*changecharsex()
This command will give the invoking character a specified number of base
and job experience points. Should be used as a quest reward. Negative values
won't work.
Is subject to EXP bonuses and to the `quest_exp_rate` config option.
getexp(10000, 5000);
BaseExp += 10000;
JobExp += 5000;
BaseExp -= 10000;
When setting the parameters directly no bonuses or config options are applied.
---------------------------------------
'setlook' will alter the look data for the invoking character. It is used
mainly for changing the palette used on hair and clothes: you specify
which look type you want to change, then the palette you want to use. Make
sure you specify a palette number that exists/is usable by the client you
use. 'changelook' works the same, but is only client side (it doesn't save
the look value).
// This will change your hair(6), so that it uses palette 8, what ever
// your palette 8 is, your hair will use that color.
setlook(LOOK_HAIR_COLOR, 8);
setlook(LOOK_CLOTHES_COLOR, 1);
Whatever 'shoes' means is anyone's guess, ask Gravity - the client does
nothing with this value. It still wants it from the server though, so it
is kept, but normally doesn't do a thing.
Only the look data for hairstyle, hair color and clothes color are saved
to the char server's database and will persist. The rest freely change as
the character puts on and removes equipment, changes maps, logs in and out
and otherwise you should not expect to set them. In fact, messing with
them is generally hazardous, do it at your own risk, it is not tested
what will this actually do - it won't cause database corruption and
probably won't cause a server crash, but it's easy to crash the client
with just about anything unusual.
However, it might be an easy way to quickly check for empty view IDs for
sprites, which is essential for making custom headgear.
Since a lot of people have different palettes for hair and clothes, it's
impossible to tell you what all the color numbers are. If you want a
serious example, there is a Stylist script inside the default Hercules
installation that you can look at: 'npc/custom/stylist.txt'
---------------------------------------
*pushpc(<direction>, <cells>)
This command will push the currently attached player to given direction by
given amount of square cells. Direction is the same as used when declaring
NPCs, and can be specified by using one of the DIR_* constants
(doc/constants.md).
The knock-back is not restricted by items or map flags, only obstacles are
taken into account. If there is not enough space to perform the push (e.g.
due to a wall), the character is pushed only up to the obstacle.
---------------------------------------
This command can transform your character into monster and you can still
use all your skills like a normal character.
Can only be removed when your killed or if you die or if duration is over.
for sc_type, val1, val2, val3, val4, see sc_start(), sc_start2(), sc_start4()
commands.
---------------------------------------
//=====================================
4.1 - Player Item-Related Commands
//=====================================
---------------------------------------
This command will give a specific amount of specified items to the target
character. If the character is not online, nothing will happen.
If <account ID> is not specified, items will be created in the invoking
character inventory instead.
In the first and most commonly used version of this command, items are
referred to by their database ID number found in 'db/(pre-)re/item_db.txt'.
Other negative IDs also correspond to other random item generating item
tables:
You may also create an item by it's name in the 'english name' field in
the item database:
Which will do what you'd expect. If it can't find that name in the
database, apples will be created anyway.
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.
---------------------------------------
identify - Whether you want the item to be identified (1) or not (0).
refine - For how many pluses will it be refined. It will not let you
refine an item higher than the max refine.
attribute - Whether the item is broken (1) or not (0).
card1,2,3,4 - If you want a card compound to it, place the card ID number
into the specific card slot.
Card1-card4 values are also used to store name information for named
items, as well as the elemental property of weapons and armor. You can
create a named item in this manner, however, if you just need a named
piece of standard equipment, it is much easier to the 'getnameditem'
function instead.
You will need to keep these values if you want to destroy and then
perfectly recreate a named item, for this see getinventorylist().
If you still want to try creating a named item with this command because
'getnameditem' won't do it for you cause it's too limited, you can do it
like this. Careful, minor magic ahead.
// For named equipment, card2 means the Star Crumbs and elemental
// crystals used to make this equipment. For everything else, it's 0.
.@card2 = 0;
// Now, let's give the character who invoked the script some
// Adam's Apples:
This wasn't tested with all possible items, so I can't give any promises,
experiment first before relying on it.
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:
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.
---------------------------------------
*getitembound(<item id>, <amount>, <bound type>{, <account ID>})
*getitembound("<item name>", <amount>, <bound type>{, <account ID>})
This command behaves identically to getitem(), but the items created will be
bound to the target character as specified by the bound type. All items created
in this manner cannot be dropped, sold, vended, auctioned, or mailed, and in
some cases cannot be traded or stored.
---------------------------------------
This command behaves identically to getitem2(), but the items created will be
bound to the target character as specified by the bound type. All items created
in this manner cannot be dropped, sold, vended, auctioned, or mailed, and in
some cases cannot be traded or stored.
---------------------------------------
*countbound({<bound type>})
This function will return the number of bounded items in the character's
inventory, and sets an array @bound_items[] containing all item IDs of the
counted items. If a bound type is specified, only those items will be counted.
Example:
mes("You currently have "+countbound()+" bound items.");
next();
mes("The list of bounded items include:");
for (.@i = 0; .@i < getarraysize(@bound_items); ++.@i)
mes(getitemname(@bound_items[.@i]));
close();
---------------------------------------
This command allows you to check whether or not the attached player has the
specified bound item in their inventory.
If a bound type is not specified or a bound type of 0 is used, it will search the
player's inventory for a bound item
of any type, so long as the other parameters match. In all cases, this command will
return the bound type of the
item found, or 0 if the specified item was not found.
Optional Parameters:
bound_type - checks to see if the item has the specified bound type.
refine - checks to see if the item is refined to the given number.
attribute - whether the item is broken (1) or not (0).
card 1,2,3,4 - checks to see if the specified cards are compounded on the item as
well.
Example:
// This will check if you have a bound (any type) 1205 (Cutter).
if (checkbound(Cutter)) {
mes("You have a bound Cutter");
} else {
mes("You do not have a bound Cutter");
}
close();
// This will also check if you have a bound (any type) 1205 (Cutter).
if (checkbound(Cutter, 0)) {
mes("You have a bound Cutter");
} else {
mes("You do not have a bound Cutter");
}
close();
// This will check if the player doesn't have a bound 1205 (Cutter).
if (!checkbound(Cutter)) {
mes("You do not have a bound Cutter");
} else {
mes("You do have a bound Cutter");
}
close();
// This will check if the item found, has a bound type of 2 (guild_bound)
if (checkbound(Cutter) == 2) {
mes("You have a guild_bound Cutter");
} else {
mes("You do not have a guild_bound Cutter.");
}
close();
The command returns true when the item is created successfully, or false
if it fails. Failure occurs when:
- There is no player attached.
- Item name or ID is not valid.
- The given character ID/name is offline.
Example:
//This will give the currently attached player a Aaron's Apple (if Aaron
//is online).
getnameditem(Apple, "Aaron");
//Self-explanatory (I hope).
if (getnameditem(Apple, "Aaron")) {
mes("You now have a Aaron's Apple!");
}
---------------------------------------
Creates a rental item in the attached character's inventory. The item will
expire in <time> seconds and be automatically deleted. When receiving a
rental item, the character will receive a message in their chat window.
The character will also receive warning messages in their chat window
before the item disappears.
This command can not be used to rent stackable items. Rental items cannot
be dropped, traded, sold to NPCs, or placed in guild storage (i.e. trade
mask 75).
Note: delitem() in an NPC script can still remove rental items.
---------------------------------------
This command will create an item lying around on a specified map in the
specified location.
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.
---------------------------------------
*makeitem2(<item
id>,<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>,{"<map
name>",<X>,<Y>,<range>})
*makeitem2("<item
name>",<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>,
{"<map name>",<X>,<Y>,<range>})
This script command work like 'makeitem', but it has additional parameters
to expand the usage of the scritp command.
Parameter List:
itemid - ID / Name of an item
amount - Amount you want produced (Value: 1~MAX_AMOUNT)
- if item type is Armor/Wepaon/PetEgg/PetArmor, amount will
be limit to 1
identify - Item to be identified (1) or not (0)
refine - Refine count of item. (Value: 0 ~ MAX_REFINE)
attribute - Item is broken (1) or not (0)
card1,2,3,4 - Card IDs that compound on each slot
*cleanarea("<map name>",<x1>,<y1>,<x2>,<y2>)
*cleanmap("<map name>")
These commands will clear all items lying on the ground on the specified
map, either within the x1/y1-x2/y2 rectangle or across the entire map.
---------------------------------------
This command will fill the given array with the ID of items whose name
matches the given one. It returns the number of items found. For
performance reasons, the results array is limited to 10 items.
---------------------------------------
This command will remove a specified amount of items from the invoking or
target character. Like all the item commands, it uses the item ID found
inside 'db/(pre-)re/item_db.txt'.
It is always a good idea to check if the player actually has the items
before you delete them. If you try to delete more items that the player
has, the player will lose the ones he/she has and the script will be
terminated with an error.
Like getitem() this command will also accept an 'english name' field from
the database. If the name is not found, nothing will be deleted.
---------------------------------------
This command will remove a specified amount of items from the invoking or
target character.
Check getitem2() to understand its expanded parameters.
---------------------------------------
If <amount> is not specified, this will remove all of the items at the specified
index.
Note that items with the 'ForceSerial' flag, not yet merged through 'mergeitem()',
will only
be removed at the given index.
The only way to get the inventory index is by using 'getinventorylist()'. After
deleting
an item at the given index, that index can remain empty until the player relogs, so
you
should recall 'getinventorylist()' again. If you try to delete an item at an
invalid index, the
script will terminate with an error.
Example:
---------------------------------------
*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(Apple)+" apples");
close;
Like getitem(), this function will also accept an 'english name' from the
database as an argument.
---------------------------------------
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.
---------------------------------------
This function will return the number of signed items for the specified item ID
that the invoking character has in their inventory.
mes("[Item Checker]");
if (countnameditem(Apple) > 0) {
mes("You have an apple with your name on it!");
} else {
mes("You do not have an apple with your name on it.");
}
next();
mes("[Item Checker]");
mesf("You have %d apples with John's name on it!", countnameditem(Apple,
"John"));
close();
Like getnameditem(), this function will also accept an 'english name' from the
database as an argument.
---------------------------------------
*groupranditem(<item id>)
Returns the item_id of a random item picked from the item container specified.
There
are different item containers and they are specified in
'db/(pre-)re/item_group.conf'.
Example:
getitem(groupranditem(Old_Blue_Box), 1);
---------------------------------------
Similar to the above example, this command allows players to obtain the specified
quantity of a random item from the container. The different containers
are specified in 'db/(pre-)re/item_group.conf'.
Example:
getrandgroupitem(Old_Blue_Box, 1);
---------------------------------------
*packageitem({item_id})
This command has only 1 param which is optional. If the package item_id is not
provided, it
will try to use the item id from the item it is being used from (if called from an
item script).
It runs a item package and grants the items accordingly to the attached player.
Example:
---------------------------------------
*enable_items()
*disable_items()
---------------------------------------
// When Anodyne is used, it will cast Endure, Level 1, as if the actual skill
// has been used from skill tree.
itemskill(SM_ENDURE, 1);
---------------------------------------
*itemeffect(<item id>)
*itemeffect("<item name>")
*consumeitem is an alias of itemeffect (added for compatibility)
This command will run the item script of the specified item on the
invoking character. The character does not need to posess the item, and
the item will not be deleted. While this command is intended for usable
items, it will run for any item type.
---------------------------------------
*produce(<item level>)
This command will open a crafting window on the client connected to the
invoking character. The 'item level' is a number which determines what
kind of a crafting window will pop-up.
You can see the full list of such item levels in 'db/produce_db.txt' which
determines what can actually be produced. The window will not be empty
only if the invoking character can actually produce the items of that type
and has the appropriate raw materials in their inventory.
The success rate to produce the item is the same as the success rate of
the skill associated with the item level. If there is no skill id, the
success rate will be 50%.
1 - Level 1 Weapons
2 - Level 2 Weapons
3 - Level 3 Weapons
21 - Blacksmith's Stones and Metals
22 - Alchemist's Potions, Holy Water, Assassin Cross's Deadly Poison
23 - Elemental Converters
---------------------------------------
*cooking(<dish level>)
This command will open a produce window on the client connected to the
invoking character. The 'dish level' is the number which determines what
kind of dish level you can produce. You can see the full list of dishes
that can be produced in 'db/produce_db.txt'.
The window will be shown empty if the invoking character does not have
enough of the required incredients to cook a dish.
11 - Level 1 Dish
12 - Level 2 Dish
13 - Level 3 Dish
14 - Level 4 Dish
15 - Level 5 Dish
16 - Level 6 Dish
17 - Level 7 Dish
18 - Level 8 Dish
19 - Level 9 Dish
20 - Level 10 Dish
Although it's required to set a dish level, it doesn't matter if you set
it to 1 and you want to cook a level 10 dish, as long as you got the
required ingredients to cook the dish the command works.
---------------------------------------
This command will open a rune crafting window on the client connected to
the invoking character. Since this command is officially used in rune
ores, a bonus success rate must be specified (which adds to the base
formula).
You can see the full list of runes that can be produced in
'db/produce_db.txt'. The window will not be empty only if the invoking
character can actually produce a rune and has the appropriate raw
materials in their inventory.
---------------------------------------
*successremovecards(<equipment slot>)
This command will remove all cards from the item found in the specified
equipment slot of the invoking character, create new card items and give
them to the character. If any cards were removed in this manner, it will
also show a success effect.
---------------------------------------
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:
Whatever the type is, it will also show a failure effect on screen.
---------------------------------------
This command repairs a broken piece of equipment, using the same list of
broken items as available through 'getbrokenid'.
The official scripts seem to use the repair command as a function instead:
'repair(<number>)' but it returns nothing on the stack. Probably only
Valaris, who made it, can answer why is it so.
---------------------------------------
*repairall()
---------------------------------------
This command will refine an item in the specified equipment slot of the
invoking character by +1 (unless <upgrade_count> is specified).
For a list of equipment slots see 'getequipid'.
This command will 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.
---------------------------------------
*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.
---------------------------------------
---------------------------------------
*unequip(<equipment slot>)
---------------------------------------
*clearitem()
This command will destroy all items the invoking character has in their
inventory (including equipped items). It will not affect anything else,
like storage or cart.
---------------------------------------
*equip(<item id>)
*equip2(<item id>, <refine>, <attribute>, <card1>, <card2>, <card3>, <card4>)
*autoequip(<item id>, <option>)
Examples:
//This will equip a +10 1104 (falchion) on the character if this is in the
//inventory.
equip2(Falchion, 10, 0, 0, 0, 0, 0);
//The invoked character will now automatically equip a falchion when it's
//looted.
autoequip(Falchion, 1);
---------------------------------------
*buyingstore(<slots>)
Invokes buying store preparation window like the skill 'Open Buying
Store', without the item requirement. Amount of slots is limited by the
server to a maximum of 5 slots by default.
Example:
---------------------------------------
*searchstores(<uses>, <effect>);
Invokes the store search window, which allows to search for both vending
and buying stores. Parameter uses indicates, how many searches can be
started, before the window has to be reopened. Effect value affects what
happens when a result item is double-clicked and can be one of the
following:
0 = Shows the store's position on the mini-map and highlights the shop
sign with yellow color, when the store is on same map as the
invoking player.
1 = Directly opens the shop, regardless of distance.
Example:
---------------------------------------
*mergeitem();
---------------------------------------
*delequip(<equipment slot>)
This command will destroy whatever is currently equipped in the invoking
character's specified equipment slot. For a full list of possible equipment
slots see getequipid().
It is always a good idea to check if the player actually has the item you want
before you use this command. If you try to delete in a position that the player
has no gear, script will be terminated with an error.
---------------------------------------
//=====================================
4.1 - End of Player Item-Related Commands
//=====================================
---------------------------------------
*openstorage()
This will open character's Kafra storage window on the client connected to
the invoking character. It can be used from any kind of NPC or item
script, not just limited to Kafra Staff.
The storage window opens regardless of whether there are open NPC dialogs
or not, but it is preferred to close the dialog before displaying the
storage window, to avoid any disruption when both windows overlap.
The mapflag 'nostorage' when set to type '2' (or 3), will not open the
account storage. Unless the character group has the permission 'bypass_nostorage'.
In case blocked by mapflag, returns 0.
---------------------------------------
*openmail()
This will open a character's Mail window on the client connected to the
invoking character.
---------------------------------------
*openauction()
This will open the Auction window on the client connected to the invoking
character.
---------------------------------------
*dressroom({<mode>})
This command controls the dressing room for the attached player. If no <mode>
is passed, DRESSROOM_OPEN is used by default.
Example:
mes("Close this window to open the Dress Room window.");
close2();
dressroom(DRESSROOM_OPEN);
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 attached character does not belong
to any guild.
The mapflag 'nogstorage' when set to type '2' (or 3), will not open the
guild storage. Unless the character group has the permission 'bypass_nostorage'.
In case blocked by mapflag, returns 1.
---------------------------------------
This function will change the Guild Master of a guild. The ID is the
guild's id, and the new guild master's name must be passed.
---------------------------------------
*guildgetexp(<amount>)
This will give the specified amount of guild experience points to the
guild the invoking character belongs to. It will silently fail if they do
not belong to any guild.
---------------------------------------
*guildskill(<skill id>, <level>)
*guildskill("<skill name>", <level>)
This command will bump up the specified guild skill by the specified
number of levels. This refers to the invoking character and will only work
if the invoking character is a member of a guild AND it's guild master,
otherwise no failure message will be given and no error will occur, but
nothing will happen. The full list of guild skills is available in
'db/(pre-)re/skill_db.txt', these are all the GD_ skills at the end.
If a level higher than the maximum is given as parameter the skill will be
leveled to the maximum and not above.
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>)
1 - Base level 1, Job level 1, 0 skill points, 0 base exp, 0 job exp,
wipes the status effects (only the ones settable by 'setoption'),
sets all stats to 1. If the new job is 'Novice High', give 100 status
points, give First Aid and Play Dead skills.
2 - Base level 1, Job level 1, 0 skill points, 0 base exp, 0 job exp.
Skills and attribute values are not altered.
3 - Base level 1, base exp 0. Nothing else is changed.
4 - Job level 1, job exp 0. Nothing else is changed.
---------------------------------------
*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.
---------------------------------------
*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 true in
'conf/map/battle.conf'. If the 'quest_skill_learn' option is set in there, the
points in the quest skills will also count towards the total.
---------------------------------------
The <effect type> determines which status is invoked. This can be either a number
or constant, with the common statuses (mostly negative) found in
'doc/constants.md' under 'Status Changes'. A full list is located in
'src/map/status.h', though they are not currently documented.
Certain status changes take an additional parameter <value 1>, which typically
modifies player stats by the given number or percentage. This differs for each
status, and is sometimes zero.
Optional value <rate> is the chance that the status will be invoked (10000 = 1%).
This is used primarily in item scripts. When used in an NPC script, a flag MUST
be defined for the rate to work.
Optional value <flag> is how the status change start will be handled (a bitmask).
SCFLAG_NONE = 0x00: No special behavior.
SCFLAG_NOAVOID = 0x01: Status change cannot be avoided.
SCFLAG_FIXEDTICK = 0x02: Tick cannot be reduced by stats (default).
SCFLAG_LOADED = 0x04: sc_data was loaded, no value will be altered.
SCFLAG_FIXEDRATE = 0x08: Rate cannot be reduced.
SCFLAG_NOICON = 0x10: Status icon (SI) won't be shown.
If a <GID> is given, the status change will be invoked on the specified character
instead of the one attached to the script. This can only be defined after setting
a rate and flag.
sc_start2() and sc_start4() allow extra parameters to be passed, and are used only
for effects that require them. The meaning of the extra values vary depending on
the
effect type.
sc_end() will remove a specified status effect. If SC_ALL (-1) is given, it will
perform a complete removal of all statuses (although permanent ones will re-apply).
Examples:
// This will poison the invoking character for 10 minutes at 50% chance.
sc_start(SC_POISON, 600000, 0, 5000);
// This will bestow the effect of Level 10 Blessing.
sc_start(SC_BLESSING, 240000, 10);
// This will end the Freezing status for the invoking character.
sc_end(SC_FREEZE);
---------------------------------------
---------------------------------------
This command displays visual and aural effects of given skill on currently
attached character. The number parameter is for skill whose visual effect
involves displaying of a number (healing or damaging). Note that this
command will not actually use the skill: it is intended for scripts which
simulate skill usage by the NPC, such as buffs, by setting appropriate
status and displaying the skill's effect.
mes("Be blessed!");
// Heal of 2000 HP
heal(2000, 0);
skilleffect(AL_HEAL, 2000);
// Blessing Level 10
sc_start(SC_BLESSING, 240000, 10);
skilleffect(AL_BLESSING, 0);
// Increase AGI Level 5
sc_start(SC_INC_AGI, 140000, 5);
skilleffect(AL_INCAGI, 0);
This will heal the character with 2000 HP, buff it with Blessing Lv 10 and
Increase AGI Lv 5, and display appropriate effects.
---------------------------------------
*npcskilleffect(<skill id>, <number>, <x>, <y>)
*npcskilleffect("<skill name>", <number>, <x>, <y>)
---------------------------------------
This command will display special effect with the given number, centered
on the specified NPCs coordinates, if any. For a full list of special
effect numbers known see 'doc/effect_list.txt'. Some effect numbers are
known not to work in some client releases. (Notably, rain is absent from
any client executables released after April 2005.)
<NPC name> parameter will display <effect number> on another NPC. If the
NPC specified does not exist, the command will do nothing. When specifying
an NPC, <send_target> must be specified when specifying an <NPC Name>,
specifying AREA will retain the default behavior of the command.
<unit id> behaves like <NPC Name> except it can display the effect on
any kind of unit, not just NPC, by specifying its GID.
When <send_target> is SELF you can specify which player to send the effect
to by passing <account id>.
Example usage:
---------------------------------------
Works for:
main client from version 2018-10-02
re client from version 2018-10-02
This command will remove special effect. All parameters same with specialeffect.
Examples and detailed explanation about parameters see in specialeffect.
---------------------------------------
*specialeffect2(<effect number>{, <send_target>{, "<Player Name>"}})
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ /!\ This command is deprecated @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
---------------------------------------
*statusup(<stat>)
bStr - Strength
bVit - Vitality
bInt - Intelligence
bAgi - Agility
bDex - Dexterity
bLuk - Luck
---------------------------------------
*statusup2(<stat>, <amount>)
---------------------------------------
*needed_status_point(<type>, <val>);
Returns the number of stat points needed to change the specified stat <type> by
<val>.
If <val> is negative, returns the number of stat points that would be needed to
raise the specified stat from (current value - <val>) to current value.
List of <type>:
bStr - Strength
bVit - Vitality
bInt - Intelligence
bAgi - Agility
bDex - Dexterity
bLuk - Luck
---------------------------------------
*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'.
---------------------------------------
These commands are meant to be used in item scripts. They will probably
work outside item scripts, but the bonus will not persist for long. They,
as expected, refer only to an invoking character.
What these commands do is 'attach' a script to the player which will get
executed on attack (or when attacked in the case of autobonus2()).
Duration is the time that the bonus will last for since the script has
triggered.
Skill ID/skill name the skill which will be used as trigger to start the
bonus (for autobonus3()).
The optional argument 'flag' is used to classify the type of attack where
the script can trigger (it shares the same flags as the bAutoSpell bonus
script):
Range criteria:
BF_SHORT: Trigger on melee attack
BF_LONG: Trigger on ranged attack
Default: BF_SHORT+BF_LONG
Attack type criteria:
BF_WEAPON: Trigger on weapon skills
BF_MAGIC: Trigger on magic skills
BF_MISC: Trigger on misc skills
Default: BF_WEAPON
Skill criteria:
BF_NORMAL: Trigger on normal attacks
BF_SKILL: Trigger on skills
default: If the attack type is BF_WEAPON (only) BF_NORMAL is used,
otherwise BF_SKILL+BF_NORMAL is used.
The difference between the optional argument 'other script' and the 'bonus
script' is that, the former one triggers only when attacking (or attacked)
and the latter one runs on status calculation as well, which makes sure,
within the duration, the "bonus" that get lost on status calculation is
restored. So, 'bonus script' is technically supposed to accept "bonus"
command only. And we usually use 'other script' to show visual effects.
In all cases, when the script triggers, the attached player will be the
one who holds the bonus. There is currently no way of knowing within this
script who was the other character (the attacker in autobonus2(), or the
target in autobonus() and autobonus3()).
//Grants a 1% chance of starting the state "all stats +10" for 10 seconds
//when using weapon or misc attacks (both melee and ranged skills) and
//shows a special effect when the bonus is active.
autobonus("{ bonus(bAllStats, 10); }", 10, 10000, BF_WEAPON|BF_MISC,
"{ specialeffect(EF_FIRESPLASHHIT, AREA, playerattached()); }");
---------------------------------------
These commands will give the invoking character a specified skill. This is
also used for item scripts.
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'.
---------------------------------------
*nude()
---------------------------------------
*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:
---------------------------------------
//=====================================
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 Git
at least) to make sure the marriage works both ways. The function returns
true upon success, or false if the marriage could not be completed, either
because the other character wasn't found or because one of the two
characters is already married.
This will do nothing else for the marriage except setting up the spouse ID
for both of these characters. No rings will be given and no effects will
be shown.
---------------------------------------
*wedding()
This command will call up wedding effects - the music and confetti -
centered on the invoking character. Example can be found in the wedding
script.
---------------------------------------
*divorce()
This function will "un-marry" the invoking character from whoever they
were married to. Both will no longer be each other's marriage partner,
(at least in current Git, which prevents the cases of multi-spouse
problems). It will return true upon success or false if the character
was not married at all.
This function will also destroy both wedding rings and send a message to
both players, telling them they are now divorced.
---------------------------------------
//=====================================
4.3 - End of Marriage-Related Commands
//=====================================
---------------------------------------
Examples:
// This will make Aaron follow Bullah, when both of these characters are
// online.
pcfollow(getcharid(CHAR_ID_ACCOUNT, "Aaron"), getcharid(CHAR_ID_ACCOUNT,
"Bullah"));
---------------------------------------
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ /!\ This command is deprecated @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Prevents the player from moving when the option != 0, and 0 enables the
player to move again. The player has to be the account ID of a character,
and will run for the attached player if zero is supplied.
Examples:
---------------------------------------
*setpcblock(<type>,<option>)
*checkpcblock()
For setpcblock, when the <option> is true(1) will block them, and false(0)
will allow those actions again.
---------------------------------------
//=====================================
4 - End of Player-Related Commands
//=====================================
---------------------------------------
---------------------------------------
//=====================================
5 - Mob / NPC Related Commands
//=====================================
---------------------------------------
*monster("<map name>", <x>, <y>, "<name to show>", <mob id>, <amount>{, "<event
label>"{, <size>{, <ai>}}})
*areamonster("<map name>", <x1>, <y1>, <x2>, <y2>, "<name to show>", <mob id>,
<amount>{, "<event label>"{, <size>{, <ai>}}})
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.
The coordinates of 0,0 will spawn the monster on a random place on the
map. Both 'monster' and 'areamonster' return the GID of the monster
spawned if there was ONLY ONE monster to be spawned. This is useful for
controlling each of the spawned mobs with the unit* commands shown below.
For example:
The way you can get the GID of more than only one monster is looping
through all the summons to get their individual GIDs and do whatever you
want with them. For example:
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.
For more examples see just about any official 2-1 or 2-2 job quest script.
---------------------------------------
*areamobuseskill("<map name>", <x>, <y>, <range>, <mob id>, <skill id>, <skill
level>, <cast time>, <cancelable>, <emotion>, <target type>)
*areamobuseskill("<map name>", <x>, <y>, <range>, <mob id>, "<skill name>", <skill
level>, <cast time>, <cancelable>, <emotion>, <target type>)
This command will make all monsters of the specified mob ID in the
specified area use the specified skill. Map name, x, and y define the
center of the area, which extending <range> cells in each direction (ex: a
range of 3 would create a 7x7 square). The skill can be specified by skill
ID or name. <cast time> is in milliseconds (1000 = 1 second), and the rest
should be self-explanatory.
Example:
---------------------------------------
This command will kill all monsters that were spawned with monster() or
areamonster() 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.
killmonster() supports an optional argument type. Using 1 for type will make
the command fire "OnMyMobDead" events from any monsters that do die as a
result of this command.
---------------------------------------
This command will kill all monsters on a specified map name, regardless of
how they were spawned or what they are without triggering any event label
attached to them, unless you specify 1 for type parameter. In this case,
mob death labels will be allowed totrigger when there is no player. Any
other number for this parameter won't be recognized.
---------------------------------------
*killmonstergid(<GID>);
This command will kill the specific monster GID. The difference between
this command and 'unitkill', is this command does not trigger monster's
event label.
---------------------------------------
---------------------------------------
This function will count all the monsters on the specified map that have a
given event label and return the number or 0 if it can't find any.
Naturally, only monsters spawned with 'monster' and 'areamonster' script
commands can have non-empty event label.
If you pass this function an empty string for the event label, it will
return the total count of monster without event label, including
permanently spawning monsters.
With the dynamic mobs system enabled, where mobs are not kept in memory
for maps with no actual people playing on them, this will return a 0 for
any such map.
If the 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.
---------------------------------------
The mode can be specified to determine the behavior of the clone, its
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).
---------------------------------------
This command will summon a monster. (see also monster()) Unlike monsters
spawned with other commands, this one will set up the monster to fight to
protect the invoking character. Monster name and mob id obey the same
rules as the one given at the beginning of this document for permanent
monster spawns with the exceptions mentioned when describing 'monster'
command.
The effect for the skill 'Call Homunculus' will be displayed centered on
the invoking character.
Timeout is the time in milliseconds the summon lives, and is set default
to 60000 (1 minute). Note that also the value 0 will set the timer to
default, and it is not possible to create a spawn that lasts forever.
If an event label is given, upon the monster being killed, the event label
will run as if by donpcevent().
---------------------------------------
*mobattached()
This command will return RID of the monster running from 'OnTouchNPC:' label.
// Kill any monster entering npc's trigger area
OnTouchNPC:
killmonstergid mobattached();
---------------------------------------
*homevolution()
---------------------------------------
*gethominfo(<type>)
If the attached player doesn't own a homunculus, this command will return
"null" for type 2, and return 0 for other types.
---------------------------------------
*morphembryo()
The command will fail if the invoking player does not have an evolved
Homunculus at level 99 or above. The /swt emotion is shown upon failure.
---------------------------------------
*hommutate({<ID>})
This command will try to mutate the invoking player's Homunculus into a
Homunculus S. The Strange Embryo (Strange_Embryo, ID 6415) is deleted
upon success.
The command will fail if the invoking player does not have an evolved
Homunculus at level 99 or above, if it is not in the embryo state
(from the morphembryo() command), or if the invoking player does not
possess a Strange Embryo. The /swt emotion is shown upon failure.
---------------------------------------
*checkhomcall()
---------------------------------------
*getunittype(<GID>)
Returns the type of object from the given Game ID. Returns -1 if the given GID
does not exist. The return values are :-
UNITTYPE_PC 0
UNITTYPE_NPC 1
UNITTYPE_PET 2
UNITTYPE_MOB 3
UNITTYPE_HOM 4
UNITTYPE_MER 5
UNITTYPE_ELEM 6
---------------------------------------
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 target whose GID is given.
When 2 arguments are passed, the given unit will walk to the given x,y
coordinates on the map where the unit currently is.
Examples:
---------------------------------------
*unitkill(<GID>)
*unitwarp(<GID>, <Mapname>, <x>, <y>)
*unitattack(<GID>, <Target ID>)
*unitstop(<GID>)
*unittalk(<GID>, <Text>{, show_name{, <send_target>{, <target_id>}}})
*unitemote(<GID>, <Emote>)
OnTouchNPC:
unitwarp(0, "this", -1, -1);
// display the text by the 1st player to the attached player only
unittalk(getcharid(CHAR_ID_ACCOUNT, "Name"), "foobar", true, SELF,
playerattached());
---------------------------------------
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.
---------------------------------------
These commands will make the NPC object specified display as hidden or
visible, even though not actually disabled per se. Hidden as in thief Hide
skill, but unfortunately, not detectable by Ruwach or Sight.
---------------------------------------
This command will start a new execution thread in a specified NPC object
at the specified label. The execution of the script running this command
will not stop, and the event called by the doevent() command will not run
until the invoking script has terminated. No parameters may be passed with
a doevent() call.
The script of the NPC object invoked in this manner will run as if it's
been invoked by the RID that was active in the script that issued a
'doevent'. As such, the command will not work if an RID is not attached.
place,100,100,1%TAB%script%TAB%NPC%TAB%53,{
mes("This is what you will see when you click me");
close();
OnLabel:
mes("This is what you will see if the doevent is activated");
close();
}
// ...
doevent("NPC::OnLabel");
---------------------------------------
This command invokes the event label code within an another NPC or NPCs.
It starts a separate instance of execution, and the invoking NPC will
resume execution its immediately.
If the supplied event label has the form "NpcName::OnLabel", then only
given NPC's event label will be invoked (much like goto() into another
NPC). If the form is "::OnLabel" (NPC name omitted), the event code of all
NPCs with given label will be invoked, one after another. In both cases
the invoked script will run without an attached RID, whether or not the
invoking script was attached to a player. The event label name is required
to start with "On".
This command can be used to make other NPCs act, as if they were
responding to the invoking NPC's actions, such as using an emotion or
talking.
place,100,100,1%TAB%script%TAB%NPC%TAB%53,{
mes("Hey NPC2 copy what I do");
close2();
@emote = rand(1, 30);
donpcevent("NPC2::OnEmote");
OnEmote:
emotion(@emote);
end;
}
place,102,100,1%TAB%script%TAB%NPC2%TAB%53,{
mes("Hey NPC copy what I do");
close2();
@emote = rand(1, 30);
donpcevent("NPC::OnEmote");
OnEmote:
emotion(@emote);
end;
}
Whichever of the both NPCs is talked to, both will show a random emotion
at the same time.
---------------------------------------
show_npcname values:
true: shows npc name (default)
false: hide npc name
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. If show_npcname is true the name of the NPC will get appended in
front of
the message, otherwise the npc name will not be shown.
// This will make everyone in the area see the NPC greet the character
// who just invoked it.
npctalk("Hello "+strcharinfo(PC_NAME)+", how are you?");
npctalk("Hello "+strcharinfo(PC_NAME)+", how are you?", "Another_NPC_Name");
---------------------------------------
Changes the display name and/or display class of the target NPC.
Returns 0 is successful, 1 if the NPC does not exist.
Size is 0 = normal 1 = small 2 = big.
---------------------------------------
//=====================================
5.1 - Time-Related Commands
//=====================================
---------------------------------------
When this timer runs out, a new execution thread will start in the
specified NPC object at the specified label.
One more thing. These timers are stored as part of player data. If the
player logs out, all of these get immediately deleted, without executing
the script. If this behavior is undesirable, use some other timer
mechanism (like sleep()).
Example:
<NPC Header> {
dispbottom("Starting a 5 second timer...");
addtimer(5000, strnpcinfo(NPC_NAME_UNIQUE)+"::On5secs");
end;
On5secs:
dispbottom("5 seconds have passed!");
end;
}
---------------------------------------
---------------------------------------
---------------------------------------
(0) TIMER_COUNT
Will return the total number of timers for the specified or
attached player. Can be filtered by <event>.
(1) TIMER_TICK_NEXT
Will return the number of ticks until the next timer runs
for the specified or attached player. Can be filtered by <event>.
(2) TIMER_TICK_LAST
Will return the number of ticks until the last timer runs
for the specified or attached player. Can be filtered by <event>.
---------------------------------------
This set of commands and functions will create and manage an NPC-based
timer. The NPC name may be omitted, in which case the calling NPC is used
as target.
To create the timer, use the initnpctimer(), which will start it running.
stopnpctimer() will pause the timer, without clearing the current tick,
while startnpctimer() will let the paused timer continue.
By default timers do not have a RID attached, which lets them continue
even if the player that started them logs off. To attach a RID to a timer,
you can either use the optional "attach flag" when using
initnpctimer()/startnpctimer(), or do it manually by using attachnpctimer().
Likewise, the optional flag of stopnpctimer() lets you detach any RID after
stopping the timer, and by using detachnpctimer() you can detach a RID at
any time.
The setnpctimer() command will explicitly set the timer to a given tick.
getnpctimer() provides timer information. Its parameter defines what type:
Example 1:
<NPC Header> {
// We need to use attachnpctimer() because the mes command below
// needs RID attach
attachnpctimer();
initnpctimer();
npctalk("I cant talk right now, give me 10 seconds");
end;
OnTimer5000:
npctalk("Ok 5 seconds more");
end;
OnTimer6000:
npctalk("4");
end;
OnTimer7000:
npctalk("3");
end;
OnTimer8000:
npctalk("2");
end;
OnTimer9000:
npctalk("1");
end;
OnTimer10000:
stopnpctimer();
mes("[Man]");
mes("Ok we can talk now");
detachnpctimer();
// and remember attachnpctimer() and detachnpctimer() can only be used
// while the NPC timer is not running!
}
Example 2:
OnTimer15000:
npctalk("Another 15 seconds have passed.");
Example 3:
mes("[Man]");
mes("I have been waiting "+(getnpctimer(0)/1000)+" seconds for you.");
// We divide the timer returned by 1000 to convert milliseconds to
// seconds.
close();
Example 4:
mes("[Man]");
mes("Ok, I will let you have 30 more seconds...");
close2();
setnpctimer(getnpctimer(0)-30000);
// Notice the close2(). If there were a next() there the timer would
// be changed only after the player pressed the next() button.
end;
---------------------------------------
*sleep(<milliseconds>)
*sleep2(<milliseconds>)
*awake("<NPC name>")
Examples:
// This will pause the script for 10 seconds and ditch the RID
// (so no player is attached anymore)
sleep(10000);
// Pauses the script for 5 seconds, and continue with the RID attached.
sleep2(5000);
//Cancels any running sleep timers on the NPC 'NPC'.
awake("NPC");
---------------------------------------
*progressbar("<color>", <seconds>)
*progressbar_unit("<color>", <seconds>{, <GID>})
This command works almost like sleep2(), but displays a progress bar above
the head of the currently attached character (like cast bar). Once the
given amount of seconds passes, the script resumes. If the character moves
while the progress bar progresses, it is aborted and the script ends. The
color format is in RGB (0xRRGGBB). The color is currently ignored by the
client and appears always green.
---------------------------------------
//=====================================
5.1 - End of Time-related commands
//=====================================
---------------------------------------
The region the broadcast is heard in (target), source of the broadcast and
the color the message will come up as is determined by the flags.
Target flags:
- bc_all: Broadcast message is sent server-wide (default).
- bc_map: Message is sent to everyone in the same map as the source of
the broadcast (see below).
- bc_area: Message is sent to players in the vicinity of the source.
- bc_self: Message is sent only to current player.
You cannot use more than one target flag.
Source flags:
- bc_pc: Broadcast source is the attached player (default).
- bc_npc: Broadcast source is the NPC, not the player attached to the
script (useful when a player is not attached or the message
should be sent to those nearby the NPC).
You cannot use more than one source flag.
Special flags:
- bc_yellow:Broadcast will be displayed in yellow color (default).
- bc_blue: Broadcast will be displayed in blue color.
- bc_woe: Indicates that this broadcast is 'WoE Information' that can
be disabled client-side.
Due to the way client handles broadcasts, it is impossible to set both
bc_blue and bc_woe.
Another example:
announce("This announcement will shown to everyone in purple.", bc_all,
C_PURPLE);
Using this for private messages to players is probably not that good an
idea, but it can be used instead in NPCs to "preview" an announce.
// This will be a private message to the player using the NPC that
// made the announcement
announce("This is my message just for you", bc_blue|bc_self);
---------------------------------------
This command will work like announce() but will only broadcast to
characters currently residing on the specified map. The flag and optional
parameters parameters are the same as in announce(), but target and source
flags are ignored.
---------------------------------------
This command works like 'announce' but will only broadcast to characters
residing in the specified x1/y1-x2/y2 rectangle on the map given. The
flags and optional parameters are the same as in announce(), but target
and source flags are ignored.
---------------------------------------
*callshop("<name>", <option>)
Example:
//Will call the shop named DaShop and opens the buy menu.
callshop("DaShop", 1);
This example shows how to use the labels and their set variables to create
a dynamic shop.
---------------------------------------
This command lets you override the contents of an existing NPC shop or
cashshop. The current sell list will be wiped, and only the items
specified with the price specified will be for sale.
The function returns true if shop was updated successfully, or false if not found.
---------------------------------------
This command will add more items at the end of the selling list for the
specified NPC shop or cashshop. If you specify an item already for sell,
that item will appear twice on the sell list.
The function returns true if shop was updated successfully, or false if not found.
---------------------------------------
*npcshopdelitem("<name>", <item id>{, <item id>{, <item id>{, ...}}})
This command will remove items from the specified NPC shop or cashshop.
If the item to remove exists more than once on the shop, all instances
will be removed.
Note that the function returns true 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 function returns false if the shop was not found, true otherwise.
---------------------------------------
This command will create a chat room, owned by the NPC object running this
script and displayed above the NPC sprite.
The maximum length of a chat room name is 60 letters.
The limit is the maximum number of people allowed to enter the chat room.
The attached NPC is included in this count. If the optional event and
trigger parameters are given, the event label
("<NPC object name>::<label name>") will be invoked as if with a donpcevent()
upon the number of people in the chat room reaching the given triggering
amount.
// The NPC will just show a box above its head that says "Hello World",
// clicking it will do nothing, since the limit is zero.
waitingroom("Hello World", 0);
// The NPC will have a box above its head, with "Disco - Waiting Room"
// written on it, and will have 8 waiting slots. Clicking this will enter
// the chat room, where the player will be able to wait until 7 players
// accumulate. Once this happens, it will cause the NPC "Bouncer" run the
// label "OnStart".
// The NPC will have a box above its head, with "Party - Waiting Room"
// written on it, and will have 8 waiting slots. Clicking this will allow
// a player who has 5000 zeny and lvl 50~99 to enter the chat room, where
// the player will be able to wait until 7 players accumulate. Once this
// happens, it will cause the NPC "Bouncer" run the label "OnStart".
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.
---------------------------------------
It's not clear what happens to a waiting room if the NPC is disabled with
disablenpc(), by the way.
---------------------------------------
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.
---------------------------------------
This function will return information about the waiting room state for the
attached waiting room or for a waiting room attached to the specified NPC
if any.
---------------------------------------
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:
---------------------------------------
---------------------------------------
This command sets the 'nosave' flag for the specified map and also gives
an alternate respawn-upon-relogin point.
It does not make a map impossible to make a save point on as you would
normally think, savepoint() will still work. It will, however, make the
specified map kick the reconnecting players off to the alternate map given
to the coordinates specified.
---------------------------------------
*setmapflag("<map name>", <flag>{, <val>})
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
'doc/constants.md' under 'Mapflags'.
The map flags alter the behavior of the map regarding teleporting
(mf_nomemo, mf_noteleport, mf_nowarp), storing location when
disconnected (mf_nosave), dead branch usage (mf_nobranch), penalties
upon death (mf_nopenalty, mf_nozenypenalty), PVP behavior (mf_pvp,
mf_pvp_noparty, mf_pvp_noguild), WoE behavior (mf_gvg, mf_gvg_noparty),
ability to use skills or open up trade deals (mf_notrade, mf_novending,
mf_noskill, mf_noicewall), current weather effects (mf_snow, mf_fog,
mf_sakura, mf_leaves, mf_clouds, mf_clouds2, mf_fireworks), whether
night will be in effect on this map (mf_nightenabled) and so on.
The val optional parameter is as the mapflags variable when one exists, it
may be a number or a string depending on the mapflag in question.
---------------------------------------
---------------------------------------
This command checks the status of a given mapflag and returns the
mapflag's state.
false means OFF, and true means ON. See setmapflag() for examples of mapflags.
---------------------------------------
Examples:
// Will return the value of the base experience rate (when used after the
// above example, it would print 2000).
mes(getbattleflag("base_exp_rate"));
---------------------------------------
---------------------------------------
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.
0 - Everyone
1 - Guild
2 - Party
Example:
---------------------------------------
//=====================================
5.2 - Guild-Related Commands
//=====================================
---------------------------------------
This command goes through the specified map and for each player and
monster found there does stuff.
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 out all people
not in the guild that owns the castle).
Characters not belonging to any guild will be warped out regardless of the
flag setting.
---------------------------------------
*agitstart()
*agitend()
*agitstart2()
*agitend2()
These four commands will start/end War of Emperium or War of Emperium SE.
This is a bit more complex than it sounds, since the commands themselves
won't actually do anything interesting, except causing all 'OnAgitStart:'
and 'OnAgitEnd:', or 'OnAgitStart2:' and 'OnAgitEnd2:' in the case of
latter two commands, events to run everywhere, respectively. They are used
as simple triggers to run a lot of complex scripts all across the server,
and they, in turn, are triggered by clock with an 'OnClock<time>:'
time-triggering label.
---------------------------------------
*gvgon("<map name>")
*gvgoff("<map name>")
These commands will turn GVG mode for the specified maps on and off,
setting up appropriate map flags. In GVG mode, maps behave as if during
the time of WoE, even though WoE itself may or may not actually be in
effect.
---------------------------------------
*flagemblem(<guild id>)
This command only works when run by the NPC objects which have sprite id
GUILD_FLAG (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 will change the emblem on the flag to that of the guild that owns
// "guildcastle"
flagemblem(getcastledata("guildcastle", 1));
---------------------------------------
*guardian("<map name>", <x>, <y>, "<name to show>", <mob id>{, "<event label>"{,
<guardian index>}})
---------------------------------------
Map name and guardian number (value between 0 and 7) define the target.
Type indicates what information to return:
0 - visibility (whether the guardian is installed or not)
1 - max. hp
2 - current hp
---------------------------------------
//=====================================
5.2 - End of Guild-Related Commands
//=====================================
---------------------------------------
*npcspeed(<speed value>)
*npcwalkto(<x>, <y>)
*npcstop()
These commands will make the NPC object in question move around the map.
As they currently are, they are a bit buggy and are not useful for much
more than making an NPC move randomly around the map.
npcspeed() will set the NPCs walking speed to a specified value. As in the
@speed GM command, 200 is the slowest possible speed while 0 is the
fastest possible (instant motion). 100 is the default character walking
speed.
npcwalkto() will start the NPC sprite moving towards the specified
coordinates on the same map as it is currently on. The script proceeds
immediately after the NPC begins moving.
npcstop() will stop the motion.
While in transit, the NPC will be clickable, but invoking it will cause it
to stop moving, 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.
---------------------------------------
This command looks like the npcwalktoxy function, but is a little different.
While npcwalktoxy just makes the NPC 'walk' to the coordinates given
(which sometimes gives problems if the path isn't a straight line without
objects), this command just moves the NPC. It basically warps out and in
on the current and given spot. Direction can be used to change the NPC's
facing direction.
Example:
// This will move Bugga from to the coordinates 100,20 (if those
// coordinates are legit).
movenpc("Bugga", 100, 20);
---------------------------------------
*navigateto("<map>"{,<x>,<y>,<flag>,<hide_window>,<monster_id>,<char_id>});
The flag specifies how the client will calculate the specific route.
The hide_window specifies whether to display (0) or hide (1) the navigation window.
By default the window is hidden.
You can specify the monster_id in combination with a mapname to make the
navigation system tell you, that you have reached the desired mob.
Note:
The client requires custom monster spawns be in the navigation file
for using the embedded client Navigation feature to work properly. In this
instance sending the player to the map where the monster spawns is a simpler
solution rather than sending the map and the monster_id.
---------------------------------------
//=====================================
6 - Other Commands
//=====================================
---------------------------------------
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ /!\ This command is deprecated @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
This command will print a message in the server console (map-server window),
after applying the same format-string replacements as sprintf(). It will not be
displayed anywhere else. Returns true on success.
Example:
This command will print a message in the server console (map-server window),
after applying the same format-string replacements as sprintf(). It will not be
displayed anywhere else. Returns true on success.
Example:
---------------------------------------
This command will write the message given to the map server log files, as
specified in 'conf/map/logs.conf'. If SQL logging is enabled, the message will
go to the specified log table. If logs are not enabled, nothing will happen.
Example:
logmes("foobar");
logmes("foobar", LOGMES_ATCOMMAND);
---------------------------------------
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.
---------------------------------------
*channelmes("<#channel>", "<message>")
---------------------------------------
*addchannelhandler("<#channel>", "<NPC::OnEvent>")
This command will trigger the specified event every time a player
talks in the specified channel, with said player as attached rid.
It assigns the message to @channelmes$
OnChannelMessage:
channelmes("#chan", "Echo: " + @channelmes$);
end;
OnInit:
addchannelhandler("#chan", "NPC::OnChannelMessage");
---------------------------------------
*removechannelhandler("<#channel>", "<NPC::OnEvent>")
---------------------------------------
*rand(<number>{, <number>})
---------------------------------------
This command will mark places on the mini map in the client connected to
the invoking character. It uses the normal X and Y coordinates from the
main map. The colors of the marks are defined using a hexadecimal number,
same as the ones used to color text in mes() output, but are written as
hexadecimal numbers in C. (They look like 0x<six numbers>.)
Action is what you want to do with a point, 1 will set it, while 2 will
clear it. 0 will also set it, but automatically removes the point after 15
seconds.
Point number is the number of the point - you can have several. If more
than one point is drawn at the same coordinates, they will cycle, which
can be used to create flashing marks.
// This command will show a mark at coordinates X 30 Y 40, is mark
// number 1, and will be red.
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>)
The client is able to display only one cutin at the same time and each new
one will cause the old one to disappear. To delete the currently displayed
illustration without displaying a new one, an empty file name and position
255 must be used.
---------------------------------------
*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.
---------------------------------------
This command makes an object display an emotion sprite above their own as
if they were doing that emotion. For a full list of emotion numbers, see
'doc/constants.md' under 'Emotes'. The not so obvious ones are 'e_what' (a
question mark) and 'e_gasp' (the exclamation mark).
The optional target parameter specifies who will get the emotion on top of
their head. If false (default if omitted), the NPC in current use will show
the emotion, if true, the player that is running the script will display it.
---------------------------------------
*misceffect(<effect number>)
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ /!\ This command is deprecated @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
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.
---------------------------------------
These two commands will play a sound effect to either the invoking
character only (soundeffect()) or multiple characters (soundeffectall()).
If the running code does not have an object ID (a 'floating' NPC) or is
not running from an NPC object at all (an item script) the sound will be
centered on the character who's RID got attached to the script, if any.
If it does, it will be centered on that object. (an NPC sprite)
Effect filename is the filename in a GRF. It must have the .wav extension.
It's not quite certain what the 'type' actually does, it is sent to the
client directly. It probably determines which directory to play the effect
from. It's certain that giving 0 for the number will play sound files from
'\data\wav\', but where the other numbers will read from is unclear.
The sound files themselves must be in the PCM format, and file names
should also have a maximum length of 23 characters including the .wav
extension:
---------------------------------------
*playbgm("<BGM filename>")
*playbgmall("<BGM filename>"{, "<map name>"{, <x0>, <y0>, <x1>, <y1>}})
These two commands will play a Background Music to either the invoking
character only (playbgm()) or multiple characters (playbgmall()).
---------------------------------------
*pvpon("<map name>")
*pvpoff("<map name>")
These commands will turn PVP mode for the specified maps on and off.
Beside setting the flags referred to in setmapflag(), pvpon() will also
create a PVP timer and ranking as will @pvpon GM command do.
---------------------------------------
*atcommand("<command>")
This command will run the given command line exactly as if it was typed in
from the keyboard by the player connected to the invoking character, and
that character belonged to an account which had GM level 99.
// This will ask the invoker for a character name and then use the
// '@nuke' GM command on them, killing them mercilessly.
input(.@player$);
atcommand("@nuke "+.@player$);
Use of this command is not recommended unless you know what you're
doing, since not all atcommands are intended to be used by the script
engine.
---------------------------------------
*charcommand("<command>")
This command will run the given command line exactly as if it was typed in
from the keyboard from a character that belonged to an account which had
GM level 99.
Use of this command is not recommended unless you know what you're
doing, since not all atcommands are intended to be used by the script
engine.
---------------------------------------
This command will bind a NPC event label to an atcommand. Upon execution
of the atcommand, the user will invoke the NPC event label. Each atcommand
is only allowed one binding. If you rebind, it will override the original
binding. If group level is provided, only users of that group level or
above will be able to access the command, if not provided, everyone will
be able to access the command.
"group level char" is the minimum group level required for the label to be
used on others like a char command would, e.g. "#command "target" params",
when not provided, "group level char" defaults to 99.
"log" whether to log the usages of this command with the atcommand log
(true = log, false = no log), default is to not log.
Parameters are split on spaces. Multiple spaces aren't grouped together, and
will create multiple (empty) arguments.
Any leading spaces before the first parameter will be omitted.
Usage example:
When a user types the command "@test", an angel effect will be shown.
The called event label needs to take care of joining arguments together, in
case it expects spaces. For example:
---------------------------------------
This command bypasses group inheritance, which means groups inheriting from
the specified <group id> will NOT inherit the specified permission. You should
use add_group_command() for every group you want to give permission to.
Example:
bindatcmd("foobar", "NPC::OnUseCommand", 99, 99, 0); // define the command
add_group_command("foobar", 2, true, false); // allow group 2 to use @foobar
add_group_command("foobar", 5, true, true); // allow group 5 to use @foobar
and #foobar
---------------------------------------
*unbindatcmd("command")
---------------------------------------
*useatcmd("command")
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ /!\ This command is deprecated @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
This command will execute an atcommand binding on the attached RID from a
script. The three .@atcmd_***** variables will NOT be set when invoking
scripts-atcommands this way.
---------------------------------------
---------------------------------------
PERM_TRADE
PERM_PARTY
PERM_ALL_SKILL
PERM_USE_ALL_EQUIPMENT
PERM_SKILL_UNCONDITIONAL
PERM_JOIN_ALL_CHAT
PERM_NO_CHAT_KICK
PERM_HIDE_SESSION
PERM_WHO_DISPLAY_AID
PERM_RECEIVE_HACK_INFO
PERM_WARP_ANYWHERE
PERM_VIEW_HPMETER
PERM_VIEW_EQUIPMENT
PERM_USE_CHECK
PERM_USE_CHANGEMAPTYPE
PERM_USE_ALL_COMMANDS
PERM_RECEIVE_REQUESTS
PERM_SHOW_BOSS
PERM_DISABLE_PVM
PERM_DISABLE_PVP
PERM_DISABLE_CMD_DEAD
PERM_HCHSYS_ADMIN
PERM_TRADE_BOUND
PERM_DISABLE_PICK_UP
PERM_DISABLE_STORE
PERM_DISABLE_EXP
PERM_DISABLE_SKILL_USAGE
PERM_BYPASS_NOSTORAGE
Example:
if (has_permission(PERM_WARP_ANYWHERE)) {
//do something
}
if (has_permission("show_version")) {
//do something
}
---------------------------------------
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.
---------------------------------------
This command causes the attached NPC object to cast a skill on the
attached player. The skill will have no cast time or cooldown. The player
must be within the default skill range or the command will fail silently.
The "stat point" parameter temporarily sets all NPC stats to the given
value, and "NPC level" is the temporary level of the NPC (used in some
skills). Neither value can be greater than the max level defined in
config, and will not work properly if the NPC has a mob sprite.
---------------------------------------
*setnpcdistance(<distance>)
This command can reduce distance from where npc can be clicked.
Usefull to use from OnInit event.
---------------------------------------
*getnpcdir({<name>})
Return current npc direction for parameter "name" or for attached npc
if it missing. If name missing and not attached npc, return -1.
Example:
.@dir = getnpcdir();
---------------------------------------
*setnpcdir({<name>, }<direction>)
Set npc direction. If npc name missing, will be used attached npc.
Example:
setnpcdir(DIR_WEST);
---------------------------------------
*getnpcclass({<name>})
Return npc class/sprite id for npc with given name or for attached npc.
If name missing and no attached npc, return -1.
Example:
.@class = getnpcclass();
---------------------------------------
*day();
*night();
These two commands will switch the entire server between day and night
mode respectively. If your server is set to cycle between day and night by
configuration, it will eventually return to that cycle.
Example:
This script allows to emulate the day/night cycle as the server does, but
also allows triggering additional effects upon change, like announces,
gifts, etc.
The day/night cycle set by configuration should be disabled when this
script is used.
---------------------------------------
*pcre_match("<string>", "<regex>")
The string <string> will be searched for a match to the regular expression
<regex>, and the number of matches will be returned.
An alternative way to invoke this command is to use the operators '~=' or '~!'.
The operator '~=' is exactly the same as pcre_match, while the operator '~!'
will return true if no matches were found, or false if at least a match was found.
if (pcre_match("string", "regex"))
mes("There was a match.");
if ("string" ~= "regex")
mes("There was a match.");
if ("string" ~! "regex")
mes("There were no matches.");
You can find more usage examples in the test script npc/custom/test.txt.
Using regular expressions is high wizardry. But with this high wizardry
comes unparalleled power of text manipulation. For an explanation of what
a regular expression pattern is, see a few web pages:
http://www.regular-expressions.info/
http://www.weitz.de/regex-coach/
---------------------------------------
They will make the NPC object listen for text spoken publicly by players
and match it against regular expression patterns, then trigger labels
associated with these regular expression patterns.
Patterns are organized into sets, which are referred to by a set number.
You can have multiple sets patterns, and multiple patterns may be active
at once. Numbers for pattern sets start at 1.
deletepset() will delete a pattern set from memory, so you can create a
new pattern set in its place.
With this you could, for example, automatically punish players for asking
for Zeny in public places, or alternatively, automatically give them Zeny
instead if they want it so much.
---------------------------------------
*pow(<number>, <power>)
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ /!\ This command is deprecated @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Example:
.@i = pow(2, 3); // .@i will be 8
---------------------------------------
*log10(<number>)
Example:
.@i = log10(100); // .@i will be 2
---------------------------------------
*sqrt(<number>)
Returns square-root of number.
Example:
.@i = sqrt(25); // .@i will be 5
---------------------------------------
Note: When Hercules is configured to use circular areas, the Euclidean distance
is returned, otherwise the Chebyshev distance. The value is truncated to
integer.
Example:
.@i = distance(100, 200, 101, 202);
---------------------------------------
*min(<number>{, <number>...<number>})
*max(<number>{, <number>...<number>})
Returns the smallest (or biggest) from the set of given numbers.
Example:
.@minimum = min(1, -6, -2, 8, 2); // .@minimum will be equal to -6
.@maximum = max(0, 5, 10, 4); // .@maximum will be equal to 10
.@level = min(BaseLevel, 70); // .@level will be the character's base level,
capped to 70
---------------------------------------
Example:
// capped between 0 ~ 100
.@value = cap_value(10, 0, 100); // .@value will be equal to 10
.@value = cap_value(1000, 0, 100); // .@value will be equal to 100
.@value = cap_value(-10, 3, 100); // .@value will be equal to 3
---------------------------------------
*md5("<string>")
Example:
mes md5(12345);
mes md5("12345"); // Will both display 827ccb0eea8a706c4c34a16891f84e7b
mes md5("qwerty");// Will display d8578edf8458ce06fbc5bb76a58c5ca4
---------------------------------------
*swap(<variable>, <variable>)
Swap the value of 2 variables. Both sides must be same integer or string type.
Example:
.@var1 = 111;
.@var2 = 222;
swap(.@var1, .@var2);
mes("var1 = "+ .@var1); // return 222
mes("var2 = "+ .@var2); // return 111
---------------------------------------
Executes an SQL query. A 'select' query can fill array variables with up
to 128 rows of values, and will return the number of rows (the array size).
Note that query_sql() runs on the main database while query_logsql() runs
on the log database.
Example:
.@nb = query_sql("select name, fame from `char` ORDER BY fame DESC LIMIT
5", .@name$, .@fame);
mes("Hall Of Fame: TOP5");
mes("1."+.@name$[0]+"("+.@fame[0]+")"); // Will return a person with the
biggest fame value.
mes("2."+.@name$[1]+"("+.@fame[1]+")");
mes("3."+.@name$[2]+"("+.@fame[2]+")");
mes("4."+.@name$[3]+"("+.@fame[3]+")");
mes("5."+.@name$[4]+"("+.@fame[4]+")");
---------------------------------------
*escape_sql(<value>)
Converts the value to a string and escapes special characters so that it's
safe to use in query_sql(). Returns the escaped form of the given value.
Example:
.@str$ = "John's Laptop";
.@esc_str$ = escape_sql(.@name$); // Escaped string: John\'s Laptop
---------------------------------------
Set a new script bonus to the Item. Very useful for game events.
You can remove an item's itemscript by leaving the itemscript argument
empty. Returns 1 on success, or 0 on fail (item_id not found or new item
script is invalid).
Type can optionally be used indicates which script to set (default is 0):
0 - Script
1 - OnEquip_Script
2 - OnUnequip_Script
Example:
---------------------------------------
*atoi("<string>")
*axtoi("<string>")
*strtol("string", base)
The atoi() and strtol() functions conform to the C functions with the same
names, and axtoi() is the same as strtol(), with a base of 16. Results are
clamped to signed 32 bit int range (INT_MIN ~ INT_MAX)
Example:
---------------------------------------
*compare("<string>", "<substring>")
This command returns true when the substring is in the main string or
false otherwise. This command is not case sensitive.
Examples:
---------------------------------------
*strcmp("<string>", "<string>")
Return Values:
>0 : String 1 > String 2
0 : Strings are equal
<0 : String 1 < String 2
Examples:
.@a = strcmp("abcdef", "ABCDEF");
if (.@a > 0){
mes(".@a is greater than 0."); //Output is this.
} else {
mes(".@a is less or equal to 0");
}
---------------------------------------
*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.
---------------------------------------
*isstr(<argument>)
Example:
isstr(69); // outputs 0
isstr("69"); // outputs 1
---------------------------------------
*getdatatype(<argument>)
This command returns the raw type of the given <argument>. Unlike
isstr, this command does not evaluate the argument. The returned type
is bitmasked.
types include:
DATATYPE_NIL
DATATYPE_STR
DATATYPE_INT
DATATYPE_CONST
DATATYPE_PARAM
DATATYPE_VAR
DATATYPE_LABEL
Example:
getdatatype() // DATATYPE_NIL
getdatatype("foo") // DATATYPE_STR
getdatatype(@foo$) // (DATATYPE_VAR | DATATYPE_STR)
---------------------------------------
*data_to_string(<data>)
Returns a string representation of the given data, similar to the .toString()
method in JavaScript.
Example:
data_to_string(DATATYPE_VAR) // "DATATYPE_VAR"
data_to_string(.@foo) // ".@foo"
---------------------------------------
*charisalpha("<string>", <position>)
This function will return true if the character number Position in the given
string is a letter, false if it isn't a letter but a digit or a space.
The first letter is position 0.
---------------------------------------
*charat(<string>, <index>)
Example:
---------------------------------------
*chr(<int>)
Example:
---------------------------------------
*ord(<chr>)
Example:
ord("c"); //returns 99
---------------------------------------
Returns the original string with the char at the specified index set to
the specified char. If index is out of range, the original string will be
returned. Only the 1st char in the <char> parameter will be used.
Example:
Returns the original string with the specified char inserted at the
specified index. If index is out of range, the char will be inserted on
the end of the string that it is closest. Only the 1st char in the <char>
parameter will be used.
Example:
---------------------------------------
*delchar(<string>, <index>)
Returns the original string with the char at the specified index removed.
If index is out of range, original string will be returned.
Example:
---------------------------------------
*strtoupper(<string>)
*strtolower(<string>)
Example:
---------------------------------------
*charisupper(<string>, <index>)
*charislower(<string>, <index>)
Example:
---------------------------------------
Returns the sub-string of the specified string inclusively between the set
indexes. If indexes are out of range, or the start index is after the end
index, an empty string will be returned.
Example:
substr("foobar", 3, 5); //returns "bar"
---------------------------------------
Example:
---------------------------------------
*implode(<string_array>{, <glue>})
Combines all substrings within the specified string array into a single
string. If the glue parameter is specified, it will be inserted inbetween
each substring.
Example:
setarray(.@my_array$[0], "This", "is", "a", "test");
implode(.@my_array$, " "); //returns "This is a test"
---------------------------------------
The format string can contain placeholders (format specifiers) using the
following structure:
%[parameter][flags][width]type
%%: Prints a literal '%' (special case, doesn't support parameter, flag, width)
%d, %i: Formats the specified value as a decimal signed number
%u: Formats the specified value as a decimal unsigned number
%x: Formats the specified value as a hexadecimal (lowercase) unsigned number
%X: Formats the specified value as a hexadecimal (uppercase) unsigned number
%o: Formats the specified value as an octal unsigned number
%s: Formats the specified value as a string
%c: Formats the specified value as a character (only uses the first character
of strings)
The following format specifier types are not supported:
// Job name is printed before the level, although they're specified in the
opposite order.
// Name, job name, level
mes(sprintf("Ciao, io sono %1$s, un %3$s di livello %2$d",
strcharinfo(PC_NAME), BaseLevel, jobname(Class)));
A field width may be specified, to ensure that 'at least' that many characters
are printed. If a star ('*') is specified as width, then the width is read as
argument to the sprintf() function. This also supports positional arguments.
Precision ('.X') and length ('hh', 'h', 'l', 'll', 'L', 'z', 'j', 't')
specifiers are not implemented (not necessary for the script engine purposes)
Example:
.@format$ = "The %s contains %d monkeys";
dispbottom(sprintf(.@format$, "zoo", 5));
//prints "The zoo contains 5 monkeys"
---------------------------------------
Example:
sscanf("This is a test: 42 foobar", "This is a test: %d %s", .@num, .@str$);
dispbottom(.@num + " " + .@str$); //prints "42 foobar"
---------------------------------------
Example:
strpos("foobar", "bar", 0); //returns 3
strpos("foobarfoo", "foo", 0); //returns 0
strpos("foobarfoo", "foo", 1); //returns 6
---------------------------------------
Replaces all instances of a search string in the input with the specified
replacement string. By default is case sensitive unless <usecase> is set
to false. If specified it will only replace as many instances as specified
in the count parameter.
Example:
replacestr("testing tester", "test", "dash"); //returns "dashing dasher"
replacestr("Donkey", "don", "mon", false); //returns "monkey"
replacestr("test test test test test", "test", "yay", false, 3); //returns
"yay yay yay test test"
---------------------------------------
Example:
countstr("test test test Test", "test"); //returns 3
countstr("cake Cake", "Cake", false); //returns 2
---------------------------------------
*setfont(<font>)
This command sets the current RO client interface font to one of the fonts
stored in data\*.eot by using an ID of the font. When the ID of the
currently used font is used, default interface font is used again.
0 - Default
1 - RixLoveangel
2 - RixSquirrel
3 - NHCgogo
4 - RixDiary
5 - RixMiniHeart
6 - RixFreshman
7 - RixKid
8 - RixMagic
9 - RixJJangu
---------------------------------------
*getfont()
---------------------------------------'
*showdigit(<value>{, <type>})
Displays given numeric 'value' in large digital clock font on top of the
screen. The optional parameter 'type' specifies visual aspects of the
"clock" and can be one of the following values:
For type 1 and 2 the start value is set by using negative number of the
one intended to set (ex. -10 starts the counter at 10 seconds). Except for
type 3 the value is interpreted as seconds and formatted as time in days,
hours, minutes and seconds. Note, that the official script command does
not have the optional parameter.
---------------------------------------
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() and petskillsupport() at the
same time.
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
'doc/constants.md' under 'Bonuses / Parameter IDs').
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 'Status Changes' status
condition constants in 'doc/constants.md'
*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.
This will make the pet use a specified support skill on the owner whenever
the HP and SP are below the given percent values, with a specified delay
time between activations. The skill numbers are as per
'db/(pre-)re/skill_db.txt'.
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.
This command 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().
If <number of attacks> is specified different than 0, it will make the pet cast
the skill with a fixed amount of damage inflicted and the specified number of
attacks. A value of zero uses the skill's defaults.
All commands with delays and durations will only make the behavior active
for the specified duration of seconds, with a delay of the specified
number of seconds between activations. Rates are a chance of the effect
occurring and are given in percent. 'bonusrate' is added to the normal
rate if the pet intimacy is at the maximum possible.
The behavior modified with the above mentioned commands will only be
exhibited if the pet is loyal and appropriate configuration options are
set in 'conf/map/battle.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.
---------------------------------------
*bpet()
This command opens up a pet hatching window on the client connected to the
invoking character. It is used in item script for the pet incubators and
will let the player hatch an owned egg. If the character has no eggs, it
will just open up an empty incubator window.
This is still usable outside item scripts.
---------------------------------------
*makepet(<pet id>)
This command will create a pet egg and put it in the invoking character's
inventory. The kind of pet is specified by pet ID numbers listed in
'db/pet_db.txt'. The egg is created exactly as if the character just
successfully caught a pet in the normal way.
Notice that you absolutely have to create pet eggs with this command. If
you try to give a pet egg with getitem(), pet data will not be created by
the char server and the egg will disappear when anyone tries to hatch it.
---------------------------------------
*homshuffle()
This will recalculate the homunculus stats according to its level, of the
current invoking character.
---------------------------------------
Each map cell has several 'flags' that specify the properties of that cell.
These include terrain properties (walkability, shootability, presence of
water), skills (basilica, land protector, ...) and other (NPC nearby, no
vending, ...).
Each of these can be 'on' or 'off'. Together they define a cell's behavior.
This command lets you alter these flags for all map cells in the specified
(x1,y1)-(x2,y2) rectangle.
'type' defines which flag to modify. Possible options include cell_walkable,
cell_shootable, cell_basilica. For a full list, see 'doc/constants.md'.
'flag' can be false (clear flat) or true (set flag).
Example:
This will add a makeshift ring into the center of the map. The ring will
be surrounded by a 5-cell wide 'gap' to prevent interference from outside,
and the rest of the map will be marked as 'basilica', preventing observers
from casting any offensive skills or fighting among themselves. Note that
the wall will not be shown nor known client-side, which may cause movement
problems.
Another example:
OnBarricadeDeploy:
setcell("schg_cas05", 114, 51, 125, 51, cell_walkable, false);
end;
OnBarricadeBreak:
setcell("schg_cas05", 114, 51, 125, 51, cell_walkable, true);
end;
This could be a part of the WoE:SE script, where attackers are not allowed
to proceed until all barricades are destroyed. This script would place and
remove a nonwalkable row of cells after the barricade mobs.
---------------------------------------
This command will return true or false, depending on whether the specified cell
has the 'type' flag set or not. There are various types to check, all
mimicking the server's cell_chk enumeration. The types can be found in
'doc/constants.md' under 'Cell checks'.
Example:
---------------------------------------
---------------------------------------
This will send a mail using the RoDEX mail system, in newer clients the message
will be marked as a NPC mail (that you can't reply).
If items and zeny are specified, they will be added as attachments to the message.
---------------------------------------
This will send a mail using the RoDEX mail system, in newer clients the message
will be marked as a NPC mail (that you can't reply).
If items and zeny are specified, they will be added as attachments to the message.
Check getitem2 command for more information of the extra parameters.
---------------------------------------
//=====================================
7 - Instance-Related Commands
//=====================================
---------------------------------------
Create an instance using the name "<instance name>" for the <owner_id> of
owner_type (when not provided, defaults to IOT_PARTY). Most instance_*
commands are used in conjunction with this command and depend on the
ID this command returns.
Example:
// Store the Party ID of the invoking character.
.@party_id = getcharid(CHAR_ID_PARTY);
---------------------------------------
*instance_destroy({<instance id>})
---------------------------------------
Example:
instance_attachmap("prontera", .@instance_id, true, "via");
^ the above creates a instance (or clone) of prontera, on a map called "via"
---------------------------------------
---------------------------------------
*instance_init(<instance id>)
Initializes the instance given by <instance id>. This copies all NPCs from
the source maps to the instanced maps.
---------------------------------------
Works like announce, but has the <instance id> parameter. If instance id
is -1, the instance the script is attached to is used. If in the
end no instance_id is found the command halts the script execution.
---------------------------------------
*instance_attach(<instance id>)
---------------------------------------
Retrieves the unique name given to a copy of an NPC given by "<npc name>"
in an instance specified <instance id>. If no ID is specified, the
instance the script is attached to is used. If in the end no instance_id,
is found the command halts the script execution.
---------------------------------------
---------------------------------------
*has_instance2("<map name>")
---------------------------------------
*instance_id()
---------------------------------------
Warps all players in the instance <instance id> to <map name> at given
coordinates. If no ID is specified, the instance the script is attached to
is used. If in the end no instance_id is found the command halts the,
script execution.
---------------------------------------
Parameter <alive timeout> specifies the total amount of time the instance
will exist. Parameter <idle timeout> specifies how long players have, when
they are outside of the instance, until it is destroyed.
---------------------------------------
Example:
if (instance_check_party(getcharid(CHAR_ID_PARTY), 2, 2, 149)) {
mes("Your party meets the Memorial Dungeon requirements.");
mes("All online members are between levels 1-150 and at least two are
online.");
close();
} else {
mes("Sorry, your party does not meet the requirements.");
close();
}
---------------------------------------
Example:
if (instance_check_guild(getcharid(CHAR_ID_GUILD), 2, 1, 150)) {
mes("Your guild meets the Memorial Dungeon requirements.");
mes("All online members are between levels 1-150 and at least two are
online.");
close();
} else {
mes("Sorry, your guild does not meet the requirements.");
close();
}
---------------------------------------
*instance_set_respawn(<map_name>, <x>, <y>{, <instance_id>})
If a player warps into a instance before this command has been used,
it will use the player's warp destination as the initial respawn point,
it can of course be modified by using this script command at any point.
---------------------------------------
*instance_mapname("<map name>"{, <instance id>})
---------------------------------------
//=====================================
7 - End of Instance-Related Commands
//=====================================
---------------------------------------
---------------------------------------
//=====================================
8 - Quest Log-Related Commands
//=====================================
---------------------------------------
This is esentially a showevent() that supports different conditions that can be set
using setquestinfo().
Use this only in an OnInit label.
For Icon, use one of the following:
No Icon : QTYPE_NONE
! Quest Icon : QTYPE_QUEST
? Quest Icon : QTYPE_QUEST2
! Job Icon : QTYPE_JOB
? Job Icon : QTYPE_JOB2
! Event Icon : QTYPE_EVENT
? Event Icon : QTYPE_EVENT2
Warg : QTYPE_WARG
Warg Face : QTYPE_WARG2 (Only for packetver >= 20120410 && packetver < 20170315)
Map Mark Color, when used, creates a mark in the user's mini map on the position of
the NPC,
the available color values are:
0 - No Marker
1 - Yellow Marker
2 - Green Marker
3 - Purple Marker
When a user shows up on a map, each NPC is checked for questinfo that has been set.
If questinfo is present, it will check if the quest has been started, if it has
not, the bubble will appear.
Example
izlude,100,100,4 script Test 844,{
mes("[Test]");
mes("Hello World.");
close();
OnInit:
questinfo(QTYPE_QUEST);
end;
}
---------------------------------------
*setquestinfo(<Type> {, <Values...>})
Place quest of <ID> in the users quest log, the state of which is "active".
If Time Limit is given, this quest will have its expire time set to <Time Limit>,
an UNIX epoch time,
ignoring quest_db setting.
If questinfo() is set, and the same ID is specified here, the icon will be cleared
when the quest is set.
---------------------------------------
*completequest(<ID>{, <ID2>})
Change the state for the given quest <ID> to "complete" and remove from
the users quest log.
If a second quest id of greater value is specified, all quests between the two
will be completed.
---------------------------------------
*erasequest(<ID>{, <ID2>})
Remove the quest of the given <ID> from the user's quest log.
If a second quest id of greater value is specified, all quests between the two
will be erased.
---------------------------------------
*changequest(<ID>, <ID2>)
Remove quest of the given <ID> from the user's quest log.
Add quest of the <ID2> to the the quest log, and the state is "active".
---------------------------------------
*questprogress(<ID>{, <type>})
---------------------------------------
*questactive(<ID>)
Returns true if the quest is active, false otherwise (quest not started,
inactive or completed)
---------------------------------------
Available Icons:
Mark Color:
0 - No Mark
1 - Yellow Mark
2 - Green Mark
3 - Purple Mark
---------------------------------------
//=====================================
8 - End of Quest Log-Related Commands
//=====================================
---------------------------------------
---------------------------------------
//=====================================
9 - Battlegrounds-Related Commands
//=====================================
---------------------------------------
Adds the first waiting player from the chat room of given NPC to an
existing battleground group and warps it to specified coordinates on given
map.
---------------------------------------
<Mapname> and X Y coordinates refer to where the "respawn" base is, where
the player group will respawn when they die.
<On Quit Event> refers to an NPC label that attaches to the character and
is run when they relog.
<On Death Event> refers to an NPC label that attaches to the character and
is run when they die. Can be "" for empty.
If "-" is supplied for <mapname>, this will remove the 1 second automatic
respawn on the battleground map. This allows for better manipulation of
<On Death Event>. The player will have to be warped to desired location
at the end of <On Death Event>.
Unlike the prior command, the latter will attach a GROUP in a waiting room
to the battleground, and sets the array $@arenamembers[0] where 0 holds
the IDs of the first group, and 1 holds the IDs of the second.
If the option parameter is left out, the waiting room of the current NPC
is used.
Example:
// Battle Group will be referred to as $@KvM01BG_id1, and when they
// die, respawn at bat_c01,52,129.
$@KvM01BG_id1 = waitingroom2bg("bat_c01", 52, 129,
"KvM01_BG::OnGuillaumeQuit", "KvM01_BG::OnGuillaumeDie");
end;
----------------------------------------
Update the respawn point of the given battle group to x, y on the same
map. The <Battle Group ID> can be retrieved using getcharid(CHAR_ID_BG).
Example:
bg_team_setxy(getcharid(CHAR_ID_BG), 56, 212);
mapannounce("bat_a01", "Group [1] has taken the work shop, and will now
respawn there.", bc_map, 0xFFCE00);
end;
----------------------------------------
Example:
//place the battle group one for Tierra Gorge at starting position.
bg_warp($@TierraBG1_id1, "bat_a01", 352, 342);
end;
----------------------------------------
*bg_monster(<Battle Group>, "<map name>", <x>, <y>, "<name to show>", <mob id>,
"<event label>")
Example:
// It can be used in two different ways.
bg_monster($@TierraBG1_id2, "bat_a01", 167, 50, "Food Depot", OBJ_B, "Feed
Depot#1::OnMyMobDead");
end;
----------------------------------------
Example:
OnEnable:
mapannounce("bat_b01", "A guardian has been summoned for Battle Group 2!",
bc_map, 0xFFCE00);
$@Guardian = bg_monster($@BG_2, "bat_a01", 268, 204, "Guardian",
B_S_GUARDIAN, "NPCNAME::OnMyMobDead");
initnpctimer();
end;
OnTimer1000:
stopnpctimer();
mapannounce("bat_b01", "Erm, sorry about that! This monster was meant for
Battle Group 1.", bc_map, 0xFFCE00);
bg_monster_set_team($@Guardian, $@BG_1);
end;
----------------------------------------
*bg_leave()
----------------------------------------
*bg_destroy(<Batte Group>)
As the name says, destroys the battle group created for that battle ground.
----------------------------------------
*areapercentheal("<mapname>", <x1>, <y1>, <x2>, <y2>, <hp>, <sp>)
Example:
areapercentheal("bat_a01", 52, 208, 61, 217, 100, 100);
end;
----------------------------------------
Retrieves data related to given battle group. Type can be one of the
following:
----------------------------------------
----------------------------------------
----------------------------------------
----------------------------------------
*bg_join_team(<Team_ID>{, <account_id>})
This command will make the attached player join to Team with ID as mentioned.
If account_id is provided, command will look for that player, instead of the
attached player.
----------------------------------------
*bg_match_over("<Arena Name>"{, <Cancelled>})
---------------------------------------
//=====================================
9 - End of Battlegrounds-Related Commands
//=====================================
---------------------------------------
---------------------------------------
//=====================================
10 - Mercenary Commands
//=====================================
---------------------------------------
This command summons a mercenary of given class, for given amount of time
in milliseconds. Typically used in item scripts of mercenary scrolls.
----------------------------------------
*mercenary_heal(<hp>, <sp>)
This command works like heal(), but affects the mercenary of the currently
attached character.
----------------------------------------
This command works like sc_start(), but affects the mercenary of the
currently attached character.
----------------------------------------
*mercenary_get_calls(<guild>)
*mercenary_set_calls(<guild>, <value>)
Sets or gets the mercenary calls value for given guild for currently
attached character. Guild can be one or the following constants:
ARCH_MERC_GUILD
SPEAR_MERC_GUILD
SWORD_MERC_GUILD
----------------------------------------
*mercenary_get_faith(<guild>)
*mercenary_set_faith(<guild>, <value>)
Sets or gets the mercenary faith value for given guild for currently
attached character. Guild can be one or the following constants:
ARCH_MERC_GUILD
SPEAR_MERC_GUILD
SWORD_MERC_GUILD
---------------------------------------
If the character does not have a mercenary, the command returns "" for
MERCINFO_NAME
and 0 for all other types.
---------------------------------------
//=====================================
10 - End of Mercenary-Related Commands
//=====================================
---------------------------------------
---------------------------------------
//=====================================
11 - Queue-Related Commands
//=====================================
---------------------------------------
*queue()
Creates a new queue instance and returns the created queue id.
---------------------------------------
*queuesize(<queue_id>)
---------------------------------------
*queueadd(<queue_id>, <var_id>)
---------------------------------------
*queueremove(<queue_id>, <var_id>)
---------------------------------------
Example:
queueopt(.@queue_id, QUEUEOPT_DEATH, "MyNPC::OnQueueMemberDeathEvent");
---------------------------------------
*queuedel(<queue_id>)
---------------------------------------
*queueiterator(<queue_id>)
---------------------------------------
*qicheck(<queue_iterator_id>)
---------------------------------------
*qiget(<queue_iterator_id>)
obtains the next member in the iterator's queue, returns the next member's
id or 0 when it doesnt exist.
Example:
for (.@elem = qiget(.@queue_iterator_id);
qicheck(.@queue_iterator_id); .@elem = qiget(.@queue_iterator_id)) {
//Do something
}
---------------------------------------
*qiclear(<queue_iterator_id>)
---------------------------------------
//=====================================
11 - End of Queue-Related Commands
//=====================================
---------------------------------------
---------------------------------------
//=====================================
12 - NPC Trader-Related Commands
//=====================================
Commands that control NPC Trader Shops
See /doc/sample/npc_trader_sample.txt
---------------------------------------
*openshop({NPC_Name})
---------------------------------------
currency_id and currency_amount can be used only with shop type NST_BARTER
---------------------------------------
*stopselling(<Item_ID>)
*stopselling(<Item_ID>{, <currency_id>, <currency_amount>})
---------------------------------------
*setcurrency(<Val1>{, <Val2>})
---------------------------------------
*tradertype(<Type>)
Modifies the npc trader type, item list is cleared upon modifiying the value.
By default, all npcs staart with tradertype(NST_ZENY);
---------------------------------------
*purchaseok()
Signs that the transaction (on a NST_CUSTOM trader) has been successful,
to be used within a "OnPayFunds" event of a NST_CUSTOM trader.
---------------------------------------
*shopcount(<Item_ID>)
---------------------------------------
Sets or alters the data in real-time for game objects of the following types -
NPCs, Pets, Monsters, Homunuculus', Mercenaries, Elementals.
---------------------------------------
*getunitdata (<GID>,<DataType>)
---------------------------------------
*getunitname(<GID>)
---------------------------------------
*setunitname(<GID>, <Name>)
---------------------------------------
//=====================================
13 - Clan System Related Commands
//=====================================
---------------------------------------
---------------------------------------
*clan_leave({<account id>})
---------------------------------------
*clan_master(<ClanID>)
---------------------------------------
//=====================================
13 - End of Clan System Related Commands
//=====================================
---------------------------------------
*airship_respond(<flag>)
---------------------------------------
*openstylist()
---------------------------------------
*msgtable(<message_id>{, <color>})
---------------------------------------
---------------------------------------
*camerainfo()
---------------------------------------
---------------------------------------
---------------------------------------
*itempreview(<index>)
---------------------------------------
---------------------------------------
That command will send a service message to the chat window of the character
specified by account ID or name, or to connected to npc player.
It will not be seen by anyone else.
Works for 20170830 RE and main and for any zero clients
---------------------------------------
*expandinventoryack(<result>{, <itemId>})
---------------------------------------
*expandinventoryresult(<result>)
---------------------------------------
*expandinventory(<value>)
---------------------------------------
*getinventorysize()
---------------------------------------
*getunittitle(<GID>)
---------------------------------------
*setunittitle(<GID>, <title>)
---------------------------------------
*closeroulette()
---------------------------------------
*openrefineryui()
---------------------------------------
*openlapineddukddakboxui(<item_id>)
---------------------------------------
prontera,153,180,4 script Option Master 4_DOG01,{
.@s = select( getequipid(EQI_HAND_R)? getequipname(EQI_HAND_R) : "") + 3;