mirror of
https://github.com/HerculesWS/Hercules
synced 2026-08-15 12:23:13 -04:00
11224 lines
396 KiB
Text
11224 lines
396 KiB
Text
//===== Hercules Documentation ===============================
|
|
//= Hercules Script Commands
|
|
//===== By: ==================================================
|
|
//= Hercules Dev Team
|
|
//===== Description: =========================================
|
|
//= A reference manual for the Hercules scripting language.
|
|
//= Commands are sorted depending on their functionality.
|
|
//============================================================
|
|
|
|
This document is a reference manual for all the scripting commands and
|
|
functions available in current 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.
|
|
|
|
A little learning never caused anyone's head to explode.
|
|
|
|
Structure
|
|
---------
|
|
|
|
The commands and functions are listed in no particular order:
|
|
|
|
*Name of the command and how to call it.
|
|
|
|
Descriptive text
|
|
|
|
Small example if possible. Will usually be incomplete, it's there just
|
|
to give you an idea of how it works in practice.
|
|
|
|
To find a specific command, use Ctrl+F, (or whatever keys call up a search
|
|
function in whatever you're reading this with) put an * followed by the
|
|
command name, and it should find the command description for you.
|
|
|
|
If you find anything omitted, please tell us. :)
|
|
|
|
Syntax
|
|
------
|
|
|
|
Throughout this document, wherever a command wants an argument, it is
|
|
given in <angle brackets>. This doesn't mean you should type the angle
|
|
brackets. :) If an argument of a command is optional, it is given in
|
|
{curly brackets}. You've doubtlessly seen this convention somewhere, if
|
|
you didn't, get used to it, that's how big boys do it. If a command can
|
|
optionally take an unspecified number of arguments, you'll see a list like
|
|
this:
|
|
|
|
command(<argument>{, <argument>...<argument>})
|
|
|
|
This still means they will want to be separated by commas.
|
|
|
|
Where a command wants a string, it will be given in "quotes", if it's a
|
|
number, it will be given without them. Normally, you can put an
|
|
expression, like a bunch of functions or operators returning a value, in
|
|
(round brackets) instead of most numbers. Round brackets will not always
|
|
be required, but they're often a good idea.
|
|
|
|
Wherever you refer to a map, use 'mapname' instead of 'mapname.gat'.
|
|
|
|
|
|
Script loading structure
|
|
------------------------
|
|
|
|
Scripts are loaded by the map server as referenced in the
|
|
'npc/(pre-)re/scripts_main.conf' configuration file.
|
|
|
|
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.
|
|
|
|
It's possible to specify scripts to exclude from loading, by inserting them
|
|
(using the same syntax) in the list available in npc/scripts_removed.conf:
|
|
|
|
npc_removed_list: (
|
|
"npc/path/to/the/file/to/skip.txt",
|
|
)
|
|
|
|
Script file format
|
|
------------------
|
|
|
|
Whenever '//' is encountered in a line upon reading, everything beyond
|
|
this on that line is considered to be a comment and is ignored. This works
|
|
wherever you place it.
|
|
|
|
// This line will be ignored when processing the script.
|
|
|
|
Block comments can also be used, where you can place /* and */ between any
|
|
text you wish Hercules to ignore.
|
|
|
|
Example:
|
|
/* This text,
|
|
* no matter which new line you start
|
|
* is ignored, until the following
|
|
* symbol is encountered: */
|
|
|
|
The asterisks (*) in front of each line is a personal preference, and is
|
|
not required.
|
|
|
|
Upon loading all the files, the server will execute all the top-level
|
|
commands in them. No variables exist yet at this point, no commands can be
|
|
called other than those given in this section. These commands set up the
|
|
basic server script structure - create NPC objects, spawn monster objects,
|
|
set map flags, etc. No code is actually executed at this point except
|
|
them. The top-level commands the scripting are pretty confusing, since
|
|
they aren't structured like you would expect commands, command name first,
|
|
but rather, normally start with a map name.
|
|
|
|
What's more confusing about the top-level commands is that most of them
|
|
use a tab symbol to divide their arguments.
|
|
|
|
To prevent problems and confusion, the tab symbols are written as '%TAB%'
|
|
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. :)
|
|
|
|
Here is a list of valid top-level commands:
|
|
|
|
** Set a map flag:
|
|
|
|
<map name>%TAB%mapflag%TAB%<flag>
|
|
|
|
This will, upon loading, set a specified map flag on a map you like. These
|
|
are normally in files inside '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'.
|
|
|
|
** Create a permanent monster spawn:
|
|
|
|
<map name>,<x>,<y>,<xs>,<ys>%TAB%monster%TAB%<monster name>%TAB%<mob id>,<amount>,<delay1>,<delay2>,<event>{,<mob size>,<mob ai>}
|
|
|
|
Map name is the name of the map the monsters will spawn on. X,Y are the
|
|
coordinates where the mob should spawn. If 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 'db/(pre-)re/mob_db.conf' 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/monster.conf'.
|
|
|
|
Delay1 and delay2 control monster respawn delays - the first one is the
|
|
fixed base respawn time, and the second is random variance on top of the
|
|
base time. Both values are given in milliseconds (1000 = 1 second). Note
|
|
that the server also enforces a minimum respawn delay of 5 seconds.
|
|
|
|
You can specify a custom level to use for the mob different from the one
|
|
of the database by adjoining the level after the name with a comma. eg:
|
|
"Poring,50" for a name will spawn a monster with name Poring and level 50.
|
|
|
|
Event is a script event to be executed when the mob is killed. The event
|
|
must be in the form "NPCName::OnEventName" to execute, and the event name
|
|
label should start with "On". As with all events, if the NPC is an
|
|
on-touch NPC, the player who triggers the script must be within 'trigger'
|
|
range for the event to work.
|
|
|
|
There are two optional fields for monster size and AI. Size can be 0
|
|
(medium), 1 (small), or 2 (big). AI can be 0 (default), 1
|
|
(attack/friendly), 2 (sphere), 3 (flora), or 4 (zanzou).
|
|
|
|
Alternately, a monster spawned using 'boss_monster' instead of 'monster' is able to be
|
|
detected on the map with the SC_CASH_BOSS_ALARM status (used by Convex Mirror, item ID# 12214).
|
|
A monster spawned using 'miniboss_monster' is spawn monster as mini boss view.
|
|
|
|
** NPC names
|
|
|
|
/!\ WARNING: this applies to warps, NPCs, duplicates and shops /!\
|
|
|
|
NPC names are kinda special and are formatted this way:
|
|
|
|
<Display name>{::<Unique name>}
|
|
|
|
All NPCs need to have a unique name that is used for identification
|
|
purposes. When you have to identify a NPC by it's name, you should use
|
|
<Unique name>. If <Unique name> is not provided, use <Display name>
|
|
instead.
|
|
|
|
The client has a special feature when displaying names: if the display
|
|
name contains a '#' character, it hides that part of the name.
|
|
Ex: if your NPC is named 'Hunter#hunter1', it will be displayed as 'Hunter'
|
|
|
|
<Display name> must be at most 24 characters in length.
|
|
<Unique name> must be at most 24 characters in length.
|
|
|
|
** Define a warp point
|
|
|
|
<from map name>,<fromX>,<fromY>{,<facing>}%TAB%warp%TAB%<warp name>%TAB%<spanx>,<spany>,<to map name>,<toX>,<toY>
|
|
|
|
This will define a warp NPC that will warp a player between maps, and
|
|
while most arguments of that are obvious, some deserve special mention.
|
|
|
|
SpanX and SpanY will make the warp sensitive to a character who didn't
|
|
step directly on it, but walked into a zone which is centered on the warp
|
|
from coordinates and is SpanX in each direction across the X axis and
|
|
SpanY in each direction across the Y axis.
|
|
|
|
Warp NPC objects also have a name, because you can use it to refer to them
|
|
later with 'enablenpc'/'disablenpc'.
|
|
|
|
Facing of a warp object is irrelevant, it is not used in the code and all
|
|
current scripts have a zero in there.
|
|
|
|
** Define an NPC object.
|
|
|
|
<map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite>,{<code>}
|
|
<map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite>,<triggerX>,<triggerY>,{<code>}
|
|
|
|
This will place an NPC object on a specified map at the specified
|
|
location, and is a top-level command you will use the most in your custom
|
|
scripting. The NPCs are triggered by clicking on them, and/or by walking
|
|
in their trigger area, if defined. See that below.
|
|
|
|
Facing is a direction the NPC sprite will face in. Not all NPC sprites
|
|
have different images depending on the direction you look from, so for
|
|
some facing will be meaningless. Facings are counted counterclockwise in
|
|
increments of 45 degrees, where 0 means facing towards the top of the map.
|
|
(So to turn the sprite towards the bottom of the map, you use facing 4,
|
|
and to make it look southeast it's facing 5.)
|
|
|
|
Sprite 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_(pre-)re.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,
|
|
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.
|
|
|
|
** Define a 'floating' NPC object.
|
|
|
|
-%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.
|
|
|
|
** Define a shop/cashshop NPC.
|
|
|
|
-%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).
|
|
|
|
The item id is the number of item in the 'db/(pre-)re/item_db.conf' database. If Price
|
|
is set to -1, the 'buy price' given in the item database will be used.
|
|
Otherwise, the price you gave will be used for this item, which is how you
|
|
create differing prices for items in different shops.
|
|
|
|
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.
|
|
|
|
** Define a trader NPC
|
|
<map name>,<x>,<y>,<facing>%TAB%trader%TAB%<NPC Name>%TAB%<sprite>,{<code>}
|
|
-%TAB%trader%TAB%<NPC Name>%TAB%FAKE_NPC,{<code>}
|
|
|
|
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)
|
|
- NST_EXPANDED_BARTER (5) Expanded Barter Shop (buy items and spend zeny and items)
|
|
Unless otherwise specified via *tradertype an trader object will be defined as
|
|
NST_ZENY.
|
|
|
|
Note: NST_MARKET is only available with PACKETVER 20131223 or newer.
|
|
Note: NST_BARTER is only available with PACKETVER 20190116 main or 20190116 RE or 20181226 zero or newer.
|
|
Note: NST_EXPANDED_BARTER is only available with PACKETVER 20190904 main or 20190904 RE or 20190828 zero or newer.
|
|
See '12 - NPC Trader-Related Commands' and /doc/sample/npc_trader_sample.txt for
|
|
more information regarding how to use this NPC type.
|
|
|
|
** Define an warp/shop/cashshop/NPC duplicate.
|
|
|
|
warp: <map name>,<x>,<y>{,<facing>}%TAB%duplicate(<label>)%TAB%<NPC Name>%TAB%<spanx>,<spany>
|
|
shop/cashshop/npc: -%TAB%duplicate(<label>)%TAB%<NPC Name>%TAB%<sprite>
|
|
shop/cashshop/npc: <map name>,<x>,<y>,<facing>%TAB%duplicate(<label>)%TAB%<NPC Name>%TAB%<sprite>
|
|
npc: -%TAB%duplicate(<label>)%TAB%<NPC Name>%TAB%<sprite>,<triggerX>,<triggerY>
|
|
npc: <map name>,<x>,<y>,<facing>%TAB%duplicate(<label>)%TAB%<NPC Name>%TAB%<sprite>,<triggerX>,<triggerY>
|
|
|
|
This will duplicate an warp/shop/cashshop/NPC referred to by 'label'.
|
|
Warp duplicates inherit the target location.
|
|
Shop/cashshop duplicates inherit the item list.
|
|
NPC duplicates inherit the script code.
|
|
The rest (name, location, facing, sprite, span/trigger area) is
|
|
obtained from the definition of the duplicate (not inherited).
|
|
|
|
** Define a function object
|
|
|
|
function%TAB%script%TAB%<function name>%TAB%{<code>}
|
|
|
|
This will define a function object, callable with the 'callfunc' command
|
|
(see below). This object will load on every map server separately, so you
|
|
can get at it from anywhere. It's not possible to call the code in this
|
|
object by anything other than the 'callfunc' script command.
|
|
|
|
The code part is the script code that will execute whenever the function
|
|
is called with 'callfunc'. It has to be in curly brackets, unlike
|
|
elsewhere where we use curly brackets, these do NOT signify an optional
|
|
parameter.
|
|
|
|
Once an object is defined which has a 'code' field to it's definition, it
|
|
contains script commands which can actually be triggered and executed.
|
|
|
|
Conditional comments
|
|
--------------------
|
|
|
|
An extension of the block comment syntax can be used for conditional comments.
|
|
A conditional comment is treated as a block comment when the specified flag is
|
|
not defined and as a normal block of code if it is, in a similar way to #ifdef
|
|
blocks in the C preprocessor. This can be useful to make
|
|
parts of scripts (including top-level commands) optional depending on a server
|
|
feature, a setting or a plugin.
|
|
|
|
A conditional comment begins with /*@CONDITION followed by whitespace or */ and
|
|
ends with the first */ sequence encountered on a separate line, but the sequence
|
|
//@*/ at the beginning of a line (optionally with indentation) is recommended as
|
|
a terminator, since it provides compatibility with older versions of the script
|
|
engine that don't support conditional comments. The condition flag can be
|
|
negated by prefixing it with an exclamation mark (!). Condition flags consist of
|
|
an uppercase letter followed by a sequence of uppercase letters, digits and
|
|
underscores and are at least three characters long.
|
|
|
|
The following block is only parsed if FLAG is defined. If not defined, or when
|
|
loaded by an older engine, the block is treated as a block comment:
|
|
|
|
/*@FLAG
|
|
.@x = 1;
|
|
//@*/
|
|
|
|
The following block is only parsed if FLAG is not defined. If defined, or when
|
|
loaded by an older engine, the block is treated as a block comment:
|
|
|
|
/*@!FLAG
|
|
.@x = 1;
|
|
//@*/
|
|
|
|
The following block is only parsed if FLAG is defined. If not defined, the block
|
|
is treated as a block comment. When loaded by an older engine, the block is also
|
|
parsed:
|
|
|
|
/*@FLAG*/
|
|
.@x = 1;
|
|
//@*/
|
|
|
|
The following block is only parsed if FLAG is not defined. If defined, the block
|
|
is treated as a block comment. When loaded by an older engine, the block is also
|
|
parsed.
|
|
|
|
/*@!FLAG*/
|
|
.@x = 1;
|
|
//@*/
|
|
|
|
The Hercules core provides the following conditional comment flags (plugins may
|
|
provide more):
|
|
|
|
- TRUE - always defined
|
|
- HERCULES - always defined
|
|
- FALSE - never defined
|
|
- RENEWAL - only defined when compiled in renewal mode
|
|
- PRERENEWAL - only defined when compiled in pre-renewal mode
|
|
- LOADGMSCRIPTS - only defined when script_configuration.load_gm_scripts is true
|
|
|
|
Note: conditional comments cannot be nested.
|
|
|
|
~ RID? GID? ~
|
|
|
|
What a RID is and why do you need to know
|
|
-----------------------------------------
|
|
|
|
Most scripting commands and functions will want to request data about a
|
|
character, store variables referenced to that character, send stuff to the
|
|
client connected to that specific character. Whenever a script is invoked
|
|
by a character, it is passed a so-called RID - this is the account ID
|
|
number of a character that caused the code to execute by clicking on it,
|
|
walking into it's OnTouch zone, or otherwise.
|
|
|
|
If you are only writing common NPCs, you don't need to bother with it.
|
|
However, if you use functions, if you use timers, if you use clock-based
|
|
script activation, you need to be aware of all cases when a script
|
|
execution can be triggered without a RID attached. This will make a lot of
|
|
commands and functions unusable, since they want data from a specific
|
|
character, want to send stuff to a specific client, want to store
|
|
variables specific to that character, and they would not know what
|
|
character to work on if there's no RID.
|
|
|
|
Unless you use 'attachrid' to explicitly attach a character to the script
|
|
first (see player-related commands).
|
|
|
|
Whenever we say 'invoking character', we mean 'the character who's RID is
|
|
attached to the running script. The script function playerattached() can
|
|
be used to check which is the currently attached player to the script (it
|
|
will return 0 if the there is no player attached or the attached player no
|
|
longer is logged on to the map-server).
|
|
|
|
But what about GID?
|
|
--- ---- ----- ----
|
|
|
|
GID stands for the Game ID of something, this can either be the GID 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.
|
|
|
|
Item and pet scripts
|
|
--------------------
|
|
|
|
Each item in the item database has three special fields - Script,
|
|
OnEquip_Script and OnUnequip_Script. The first is script code run every
|
|
time a character equips the item, with the RID of the equipping character.
|
|
Every time they unequip an item, all temporary bonuses given by the script
|
|
commands are cleared, and all the scripts are executed once again to
|
|
rebuild them. This also happens in several other situations (like upon
|
|
login) but the full list is currently unknown.
|
|
|
|
OnEquip_Script is a piece of script code run whenever the item is used by
|
|
a character by double-clicking on it. OnUnequip_Script runs whenever the
|
|
equipment is unequipped by a character.
|
|
|
|
Not all script commands work properly in the item scripts. Where commands
|
|
and functions are known to be meant specifically for use in item scripts,
|
|
they are described as such.
|
|
|
|
Every pet in the pet database has a PetScript field, which determines pet
|
|
behavior. It is invoked wherever a pet of the specified type is spawned
|
|
(hatched from an egg, or loaded from the char server when a character who
|
|
had that pet following them connects). This may occur in some other
|
|
situations as well. Don't expect anything other than commands definitely
|
|
marked as usable in pet scripts to work in there reliably.
|
|
|
|
Numbers
|
|
-------
|
|
|
|
The Hercules scripting engine supports 4 types of number literals:
|
|
|
|
type base syntax
|
|
----------------------------------------------
|
|
decimal 10 255
|
|
hexadecimal 16 0xFF
|
|
octal 8 0o377
|
|
binary 2 0b11111111
|
|
|
|
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'. If you wish
|
|
to make calculations in base 8, you can also use the octal notation like
|
|
'0o<octal digits>'. To make calculations in base 2 (binary), you can use
|
|
the binary notation like '0b<binary digits>'.
|
|
|
|
The following are all equivalent:
|
|
255 == 0xFF == 0o377 == 0b11111111
|
|
|
|
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.
|
|
|
|
Underscores can also be used as visual separators for digit grouping purposes:
|
|
2_147_483_647
|
|
0x7FFF_FFFF
|
|
|
|
Keep in mind that number literals cannot start or end with a separator and no
|
|
more than one separator can be used in a row (so 12_3___456 is illegal).
|
|
|
|
Variables
|
|
---------
|
|
|
|
The meat of every programming language is variables - places where you
|
|
store data.
|
|
|
|
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
|
|
|
|
Extent can be:
|
|
permanent - They still exist when the server resets.
|
|
temporary - They cease to exist when the server resets.
|
|
|
|
Prefix: scope and extent
|
|
nothing - A permanent variable attached to the character, the default
|
|
variable type.
|
|
"@" - A temporary variable attached to the character.
|
|
They disappear when the character logs out.
|
|
"$" - A global permanent variable.
|
|
They are stored in database table `mapreg`.
|
|
"$@" - A global temporary variable.
|
|
They are important for scripts which are called with no RID
|
|
attached, that is, not triggered by a specific character object.
|
|
"." - A NPC variable.
|
|
They exist in the NPC and disappear when the server restarts or
|
|
the NPC is reloaded. Can be accessed from inside the NPC or by
|
|
calling 'getvariableofnpc'. Function objects can also have
|
|
.variables which are accessible from inside the function,
|
|
however 'getvariableofnpc' does NOT work on function objects.
|
|
".@" - A scope variable.
|
|
They are unique to the character, script and scope. Each script
|
|
execution has its own scope that ends when the script ends.
|
|
Calling a function with callsub()/callfunc() starts a new scope,
|
|
returning from the function ends it. When a scope ends, its
|
|
variables are converted to values ('return .@var;' returns a
|
|
value, not a reference).
|
|
"'" - An instance variable.
|
|
These are used with the instancing system, and are unique to
|
|
each instance.
|
|
"#" - A permanent local account variable.
|
|
"##" - A permanent global account variable stored by the login server.
|
|
The only difference you will note from normal # variables is
|
|
when you have multiple char-servers connected to the same
|
|
login-server. The # variables are unique to each char-server,
|
|
while the ## variables are shared by all these char-servers.
|
|
|
|
Postfix: integer or string
|
|
nothing - integer variable, can store positive and negative numbers, but
|
|
only whole numbers (so don't expect to do any fractional math).
|
|
'$' - string variable, can store text.
|
|
|
|
Examples:
|
|
name - permanent character integer variable
|
|
name$ - permanent character string variable
|
|
@name - temporary character integer variable
|
|
@name$ - temporary character string variable
|
|
$name - permanent global integer variable
|
|
$name$ - permanent global string variable
|
|
$@name - temporary global integer variable
|
|
$@name$ - temporary global string variable
|
|
.name - NPC integer variable
|
|
.name$ - NPC string variable
|
|
.@name - scope integer variable
|
|
.@name$ - scope string variable
|
|
'name - 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
|
|
|
|
If a variable was never set, it is considered to equal zero for integer
|
|
variables or an empty string ("", nothing between the quotes) for string
|
|
variables. Once you set it to that, the variable is as good as forgotten
|
|
forever, and no trace remains of it even if it was stored with character
|
|
or account data. The maximum length of variable name including prefix and
|
|
suffix is 32. Permanent string variables (name$, $name$, #name$, ##name$)
|
|
can store text with a maximum length of 255 characters. All other string
|
|
type variables have no such limitation.
|
|
|
|
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_(pre-)re.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:
|
|
|
|
Zeny - Amount of Zeny in the inventory.
|
|
BankVault - Amount of Zeny in the bank.
|
|
Hp - Current amount of hit points.
|
|
MaxHp - Maximum amount of hit points.
|
|
Sp - Current spell points.
|
|
MaxSp - Maximum amount of spell points.
|
|
StatusPoint - Amount of status points remaining.
|
|
SkillPoint - Amount of skill points remaining.
|
|
BaseLevel - Character's base level.
|
|
JobLevel - Character's job level.
|
|
BaseExp - Amount of base experience points.
|
|
JobExp - Amount of job experience points.
|
|
NextBaseExp - Amount of base experience points needed to reach next level.
|
|
NextJobExp - Amount of job experience points needed to reach next level.
|
|
Weight - Amount of weight the character currently carries.
|
|
Display as in Weight/10.
|
|
MaxWeight - Maximum weight the character can carry.
|
|
Display as in MaxWeight/10.
|
|
Sex - Character's gender (SEX_MALE or SEX_FEMALE).
|
|
Class - Character's job.
|
|
Upper - 0 if the character is normal class, 1 if advanced, 2 if baby.
|
|
BaseClass - The character's 1-1 'normal' job, regardless of Upper value.
|
|
For example, this will return Job_Acolyte for Acolyte,
|
|
Priest/Monk, High Priest/Champion, and Arch Bishop/Sura.
|
|
If the character has not reached a 1-1 class, it will return
|
|
Job_Novice.
|
|
BaseJob - The character's 'normal' job, regardless of Upper value.
|
|
For example, this will return Job_Acolyte for Acolyte,
|
|
Baby Acolyte, and High Acolyte.
|
|
Karma - The character's karma. Karma system is not fully functional,
|
|
but this doesn't mean this doesn't work at all. Not tested.
|
|
Manner - The character's manner rating. Becomes negative if the
|
|
player utters words forbidden through the use of
|
|
'manner.txt' client-side file.
|
|
|
|
While these behave as variables, do not always expect to just set them -
|
|
it is not certain whether this will work for all of them. Whenever there
|
|
is a command or a function to set something, it's usually preferable to
|
|
use that instead. The notable exception is Zeny, which you can and often
|
|
will address directly - setting it will make the character own this number
|
|
of Zeny. If you try to set Zeny to a negative number, the script will be
|
|
terminated with an error.
|
|
|
|
Assigning variables
|
|
--------- ---------
|
|
|
|
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; // same as .@x = .@x + 1
|
|
--.@x; // same as .@x = .@x - 1
|
|
|
|
Post-increment and post-decrement operators:
|
|
|
|
.@x++; // similar to .@x = .@x + 1
|
|
.@x--; // similar to .@x = .@x - 1
|
|
|
|
The difference between pre- and post- increment/decrement operators is that,
|
|
when used in an expression, the pre- ones will be executed before evaluating
|
|
the expression, while the post- ones will be executed after. For example:
|
|
|
|
.@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
|
|
-------
|
|
|
|
Strings are enclosed in "double quotes". To include the literal double
|
|
quote symbol (") in a string you need to escape it with a backslash:
|
|
|
|
.@string$ = "This string contains some \"double quote\" symbols";
|
|
|
|
Arrays
|
|
------
|
|
|
|
Arrays (in Hercules at least) are essentially a set of variables going
|
|
under the same name. You can tell between the specific variables of an
|
|
array with an 'array index', a number of a variable in that array:
|
|
|
|
<variable name>[<array index>]
|
|
|
|
All variable types can be used as 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;
|
|
|
|
This will make .@arrayofnumbers[100] equal to 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.
|
|
|
|
If the array index is omitted, it defaults to zero. Writing
|
|
.@arrayofnumbers is perfectly equivalent to writing .@arrayofnumbers[0].
|
|
|
|
Arrays can naturally store strings:
|
|
|
|
.@menulines$[0] is the 0th element of the .@menulines$ array of strings.
|
|
Notice the '$', normally denoting a string variable, before the square
|
|
brackets that denotes an array index.
|
|
|
|
Variable References
|
|
-------------------
|
|
|
|
//##TODO
|
|
|
|
Hard-coded constants
|
|
--------------------
|
|
Most of the constants defined by the scripting engine can be found in
|
|
'doc/constants_(pre-)re.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.
|
|
|
|
PACKETVER - Server packet version
|
|
MAX_LEVEL - Maximum level
|
|
MAX_STORAGE - Maximum storage items
|
|
MAX_GUILD_STORAGE - Maximum guild storage items
|
|
MAX_CART - Maximum cart items
|
|
MAX_INVENTORY - Maximum inventory items
|
|
MAX_ZENY - Maximum Zeny in the inventory
|
|
MAX_BANK_ZENY - Maximum Zeny in the bank
|
|
MAX_BG_MEMBERS - Maximum BattleGround members
|
|
MAX_CHAT_USERS - Maximum Chat users
|
|
MAX_REFINE - Maximum Refine level
|
|
MAX_ITEM_GRADE - Maximum Grade level
|
|
MAX_ITEM_ID - Maximum Item ID
|
|
MAX_MENU_OPTIONS - Maximum NPC menu options
|
|
MAX_MENU_LENGTH - Maximum NPC menu string length
|
|
MOB_CLONE_START - Clone ID start from this range
|
|
MOB_CLONE_END - Clone ID end with this range
|
|
|
|
Send targets and status options are also hard-coded and can be found
|
|
in 'doc/constants_(pre-)re.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.
|
|
|
|
Comparisons can be stacked in the same condition:
|
|
|
|
&& - Is True if and only if BOTH sides are true.
|
|
('1==1 && 2==2' is true. '2==1 && 1==1' is false.)
|
|
|| - Is True if either side of this expression is True.
|
|
|
|
1==1 && 2==2 is True.
|
|
1==1 && 2==1 is False.
|
|
1==1 || 2==1 is True.
|
|
|
|
Logical bitwise operators work only on numbers, and they are the following:
|
|
|
|
<< - Left shift.
|
|
>> - Right shift.
|
|
Left shift moves the binary 1(s) of a number n positions to the left,
|
|
which is the same as multiplying by 2, n times.
|
|
In the other hand, Right shift moves the binary 1(s) of a number n
|
|
positions to the right, which is the same as dividing by 2, n times.
|
|
Example:
|
|
b = 2;
|
|
a = b << 3;
|
|
mes(a);
|
|
a = a >> 2;
|
|
mes(a);
|
|
The first mes() command would display 16, which is the same as:
|
|
2 x (2 x 2 x 2) = 16.
|
|
The second mes() command would display 4, which is the same as:
|
|
16 / 2 = 8; 8 / 2 = 4.
|
|
& - And.
|
|
| - Or.
|
|
The bitwise operator AND (&) is used to test two values against each
|
|
other, and results in setting bits which are active in both arguments.
|
|
This can be used for a few things, but in Hercules this operator is
|
|
usually used to create bit-masks in scripts.
|
|
|
|
The bitwise operator OR (|) sets to 1 a binary position if the binary
|
|
position of one of the numbers is 1. This way a variable can hold
|
|
several values we can check, known as bit-mask. A variable currently
|
|
can hold up to 32 bit-masks (from position 0 to position 1). This is a
|
|
cheap(skate) and easy way to avoid using arrays to store several
|
|
checks that a player can have.
|
|
|
|
A bit-mask basically is (ab)using the variables bits to set various
|
|
options in one variable. With the current limit in variables it is
|
|
possible to store 32 different options in one variable (by using the
|
|
bits on position 0 to 31).
|
|
|
|
Example(s):
|
|
- Basic example of the & operator, bit example:
|
|
10 & 2 = 2
|
|
Why? :
|
|
10 = 2^1 + 2^3 (2 + 8), so in bits, it would be 1010
|
|
2 = 2^1 (2), so in bits (same size) it would be 0010
|
|
The & (AND) operator sets bits which are active (1) in both
|
|
arguments, so in the example 1010 & 0010, only the 2^1 bit is
|
|
active (1) in both. Resulting in the bit 0010, which is 2.
|
|
- Basic example of creating and using a bit-mask:
|
|
.@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
|
|
|
|
Ternary operators take three expressions (numbers, strings or boolean),
|
|
and are the following:
|
|
|
|
?: - Conditional operator
|
|
Very useful e.g. to replace
|
|
|
|
if (Sex == SEX_MALE)
|
|
mes("You're Male.");
|
|
else
|
|
mes("You're Female.");
|
|
|
|
clauses with simple
|
|
|
|
mes("Welcome, " + (Sex == SEX_MALE ? "Mr." : "Mrs.") + " " + strcharinfo(PC_NAME));
|
|
|
|
or to replace any other simple if-else clauses. It might be worth
|
|
mentioning that ?: has low priority and has to be enclosed with
|
|
parenthesis in most (if not all) cases.
|
|
|
|
Operator Precedence and Associativity
|
|
|
|
Operator precedence and associativity work more or less like they do in
|
|
mathematics. The rules can be summarized with the following table:
|
|
|
|
Precedence | Description | Associativity
|
|
---------------------------------------------------------------------------
|
|
1 (highest) | [] Array subscripting | None
|
|
---------------------------------------------------------------------------
|
|
2 | ++ Increment | None
|
|
| -- Decrement |
|
|
---------------------------------------------------------------------------
|
|
2 | - Unary minus | Right to left
|
|
| ! Logical NOT |
|
|
| ~ Bitwise NOT (One's Complement) |
|
|
---------------------------------------------------------------------------
|
|
3 | ** Exponentiation | Left to right
|
|
---------------------------------------------------------------------------
|
|
4 | * Multiplication | Left to right
|
|
| / Division |
|
|
| % Modulo (remainder) |
|
|
---------------------------------------------------------------------------
|
|
5 | + Addition | Left to right
|
|
| - Subtraction |
|
|
---------------------------------------------------------------------------
|
|
6 | << Bitwise left shift | Left to right
|
|
| >> Bitwise right shift |
|
|
---------------------------------------------------------------------------
|
|
7 | < Less than | Left to right
|
|
| <= Less than or equal to |
|
|
| > Greater than |
|
|
| >= Greater than or equal to |
|
|
---------------------------------------------------------------------------
|
|
8 | == Equal to | Left to right
|
|
| != Not equal to |
|
|
| ~= Regexp match |
|
|
| ~! Regexp non-match |
|
|
---------------------------------------------------------------------------
|
|
9 | & Bitwise AND | Left to right
|
|
---------------------------------------------------------------------------
|
|
10 | ^ Bitwise XOR (exclusive or) | Left to right
|
|
---------------------------------------------------------------------------
|
|
11 | | Bitwise OR (inclusive or) | Left to right
|
|
---------------------------------------------------------------------------
|
|
12 | && Logical AND | Left to right
|
|
---------------------------------------------------------------------------
|
|
13 | || Logical OR | Left to right
|
|
---------------------------------------------------------------------------
|
|
14 | ?: Ternary conditional | Right to left
|
|
---------------------------------------------------------------------------
|
|
15 | = Direct assignment | Right to left
|
|
(lowest) | += Assignment by sum |
|
|
| -= Assignment by difference |
|
|
| *= Assignment by product |
|
|
| **= Assignment by power |
|
|
| /= Assignment by quotient |
|
|
| %= Assignment by remainder |
|
|
| <<= Assignment by bitwise left shift |
|
|
| >>= Assignment by bitwise right shift |
|
|
| &= Assignment by bitwise AND |
|
|
| ^= Assignment by bitwise XOR |
|
|
| |= Assignment by bitwise OR |
|
|
|
|
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 .
|
|
|
|
Operator associativity defines what happens if a sequence of the same
|
|
operators is used one after another: whether the evaluator will evaluate the
|
|
left operations first or the right. For example, in 8 - 4 - 2 , subtraction is
|
|
left associative so the expression is evaluated left to right. 8 - 4 is
|
|
evaluated first making the expression 4 - 2 == 2 and not 8 - 2 == 6 .
|
|
|
|
Labels
|
|
------
|
|
|
|
Within executable script code, some lines can be labels:
|
|
|
|
<label name>:
|
|
|
|
Labels are points of reference in your script, which can be used to route
|
|
execution with 'goto' 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.
|
|
|
|
OnNPCUnload:
|
|
|
|
OnNPCUnload will be executed when a NPC is unloaded.
|
|
OnNPCUnload is called when @reloadscript, @reloadnpc, @unloadnpc or @unloadnpcfile is used.
|
|
|
|
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 happen.
|
|
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:
|
|
|
|
monster("prontera", 123, 42, "Poringz0rd", 2341, 23, "Master::OnThisMobDeath");
|
|
|
|
amatsu,13,152,4 script Master 767,{
|
|
mes("Hi there");
|
|
close();
|
|
|
|
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.
|
|
|
|
Scripting commands and functions
|
|
--------------------------------
|
|
|
|
The commands and functions are listed here in no particular order. There's
|
|
a difference between commands and functions - commands leave no 'return
|
|
value' which might be used in a conditional statement, as a command
|
|
argument, or stored in a variable.
|
|
|
|
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.
|
|
|
|
-------------------------
|
|
|
|
|
|
From here on, we will have the commands sorted as followed:
|
|
|
|
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.
|
|
|
|
mes("Text that will appear in the box");
|
|
|
|
Inside the string you may put color codes, which will alter the color of
|
|
the text printed after them. The color codes are all '^<R><G><B>' and
|
|
contain three hexadecimal numbers representing colors as if they were
|
|
HTML colors - ^FF0000 is bright red, ^00FF00 is bright green, ^0000FF is
|
|
bright blue, ^000000 is black. ^FF00FF is a pure magenta, but it's also
|
|
a color that is considered transparent whenever the client is drawing
|
|
windows on screen, so printing text in that color will have kind of a
|
|
weird effect. 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.
|
|
|
|
If you're using a client from 2011-10-10aRagexe.exe onwards, you can also
|
|
use automatic navigation and open URLs in browser by using some HTML-like
|
|
labels. For example:
|
|
|
|
mes("go to <NAVI>[Hat Maker]<INFO>izlude,131,148,</INFO></NAVI> to make hats");
|
|
|
|
Will make the [Hat Maker] text clickable in the client and start a navigation
|
|
to that point.
|
|
|
|
mes("You can <URL>Google<INFO>http://www.google.com/</INFO></URL> anything");
|
|
|
|
This will allow you to visit 'Google' with the in-game browser using default dimensions.
|
|
|
|
mes("You can <URL>Bing!<INFO>http://www.bing.com/,800,600</INFO></URL> anything");
|
|
|
|
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.
|
|
|
|
---------------------------------------
|
|
|
|
*mesf("<format>"{, <param>{, <param>{, ...}}})
|
|
|
|
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:
|
|
|
|
mesf("Hello, I'm %s, a level %d %s", strcharinfo(PC_NAME), BaseLevel, jobname(Class));
|
|
// is equivalent to:
|
|
mes(sprintf("Hello, I'm %s, a level %d %s", strcharinfo(PC_NAME), BaseLevel, jobname(Class)));
|
|
|
|
This command is a combination of mes() and sprintf(). See their documentation
|
|
for more details.
|
|
|
|
---------------------------------------
|
|
|
|
*zmes1f("<format>"{, <param>{, <param>{, ...}}})
|
|
|
|
This command will displays a box on the screen for the invoking character, with zero ui at bottom.
|
|
Works same as *mesf* except zero ui.
|
|
|
|
Works only in zero clients starting from 20210721.
|
|
|
|
---------------------------------------
|
|
|
|
*zmes2f("<format>"{, <param>{, <param>{, ...}}})
|
|
|
|
This command will displays a box on the screen for the invoking character, with zero ui at center.
|
|
Works same as *mesf* except zero ui.
|
|
|
|
Works only in zero clients starting from 20210721.
|
|
|
|
---------------------------------------
|
|
|
|
*zmes1("<string>")
|
|
|
|
This command will displays a box on the screen for the invoking character, with zero ui at bottom.
|
|
Works same as *mes* except zero ui.
|
|
|
|
Works only in zero clients starting from 20210721.
|
|
|
|
---------------------------------------
|
|
|
|
*zmes2("<string>")
|
|
|
|
This command will displays a box on the screen for the invoking character, with zero ui at center.
|
|
Works same as *mes* except zero ui.
|
|
|
|
Works only in zero clients starting from 20210721.
|
|
|
|
---------------------------------------
|
|
|
|
*mes2("<string>"{, type})
|
|
|
|
This command will displays a box on the screen for the invoking character.
|
|
Work same as *mes* except positioning window with text at bottom.
|
|
|
|
Works only on main client starting from 20220504.
|
|
|
|
---------------------------------------
|
|
|
|
*mes2f("<format>"{, <param>{, <param>{, ...{, type}}}})
|
|
|
|
This command will displays a box on the screen for the invoking character.
|
|
Works same as *mesf* except positioning window with text at bottom.
|
|
|
|
Works only on main client starting from 20220504.
|
|
|
|
---------------------------------------
|
|
|
|
*next()
|
|
|
|
This command will display a 'next' button in the message window for the
|
|
invoking character. Clicking on it will cause the window to clear and
|
|
display a new one. Used to segment NPC-talking, next() is often used in
|
|
combination with mes() and close().
|
|
|
|
If no window is currently on screen, one will be created, but once the
|
|
invoking character clicks on it, a warning is thrown on the server console
|
|
and the script will terminate.
|
|
|
|
mes("[Woman]");
|
|
mes("This would appear on the page");
|
|
next();
|
|
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");
|
|
|
|
---------------------------------------
|
|
|
|
*next2()
|
|
*next2(type)
|
|
|
|
This command will display a 'next' button in the message window for the
|
|
invoking character.
|
|
Work same as *next* but should be used with *mes2*.
|
|
|
|
Works only on main client starting from 20220504.
|
|
|
|
---------------------------------------
|
|
|
|
*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.
|
|
|
|
if (BaseLevel <= 10) {
|
|
npctalk("Look at that you are still a n00b");
|
|
end;
|
|
}
|
|
if (BaseLevel <= 20) {
|
|
npctalk("Look at that you are getting better, but still a n00b");
|
|
end;
|
|
}
|
|
if (BaseLevel <= 30) {
|
|
npctalk("Look at that you are getting there, you are almost 2nd profession now right???");
|
|
end;
|
|
}
|
|
if (BaseLevel <= 40) {
|
|
npctalk("Look at that you are almost 2nd profession");
|
|
end;
|
|
}
|
|
|
|
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).
|
|
|
|
This command is deprecated and it shouldn't be used in new scripts, except
|
|
some special cases (mostly, set(getvariableofnpc(), <value>)). Use direct value
|
|
assignment instead.
|
|
|
|
---------------------------------------
|
|
|
|
*setd("<variable name>", <value>)
|
|
|
|
Works almost identically as set(), except the variable name is
|
|
identified as a string and can thus be constructed dynamically.
|
|
|
|
This command is equivalent to:
|
|
set(getd("variable name"), <value>);
|
|
|
|
Examples:
|
|
|
|
setd(".@var$", "Poporing");
|
|
mes(.@var$); // Displays "Poporing".
|
|
|
|
setd(".@" + .@var$ + "123$", "Poporing is cool");
|
|
mes(.@Poporing123$); // Displays "Poporing is cool".
|
|
|
|
---------------------------------------
|
|
|
|
*getd("<variable name>")
|
|
|
|
Returns a reference to a variable, the name can be constructed dynamically.
|
|
Refer to setd() for usage.
|
|
|
|
This can also be used to set an array dynamically:
|
|
setarray(getd(".array[0]"), 1, 2, 3, 4, 5);
|
|
|
|
Examples:
|
|
|
|
mes("The value of $varReference is: " + getd("$varRefence"));
|
|
set(.@i, getd("$" + "pikachu"));
|
|
|
|
---------------------------------------
|
|
|
|
*getvariableofnpc(<variable>, "<npc name>")
|
|
|
|
Returns a reference to a NPC variable (. prefix) from the target NPC.
|
|
This can only be used to get . variables.
|
|
|
|
Examples:
|
|
|
|
//This will return the value of .var, note that this can't be used, since
|
|
//the value isn't caught.
|
|
getvariableofnpc(.var, "TargetNPC");
|
|
|
|
//This will set the .@v variable to the value of the TargetNPC's .var
|
|
//variable.
|
|
.@v = getvariableofnpc(.var, "TargetNPC");
|
|
|
|
//This will set the .var variable of TargetNPC to 1.
|
|
set(getvariableofnpc(.var, "TargetNPC"), 1);
|
|
|
|
Note: even though function objects can have .variables,
|
|
getvariableofnpc() should not be used on them.
|
|
|
|
---------------------------------------
|
|
|
|
*getvariableofpc(<variable>, <account id>{, <default value>})
|
|
|
|
Returns a reference to a PC variable from the target player.
|
|
If <default value> is passed, it will return this value if the player is
|
|
not found.
|
|
|
|
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"));
|
|
|
|
//This will set the @var variable of the player to 1.
|
|
set(getvariableofpc(@var, getcharid(CHAR_ID_ACCOUNT, "player")), 1);
|
|
|
|
---------------------------------------
|
|
|
|
*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");
|
|
|
|
Gotos are considered to be harmful and should be avoided whenever possible.
|
|
|
|
---------------------------------------
|
|
|
|
*menu("<option_text>", <target_label>{, "<option_text>", <target_label>, ...})
|
|
|
|
This command will create a selectable menu for the invoking character.
|
|
Only one menu can be on screen at the same time.
|
|
|
|
Depending on what the player picks from the menu, the script execution
|
|
will continue from the corresponding label. It's string-label pairs, not
|
|
label-string.
|
|
|
|
This command is deprecated and it should not be used in new scripts, as it
|
|
is likely to be removed at a later time. Please consider using select() or
|
|
prompt() instead.
|
|
|
|
Options can be grouped together, separated by the character ':'.
|
|
|
|
menu("A:B", L_Wrong, "C", L_Right);
|
|
|
|
It also sets a special temporary character variable @menu, which contains
|
|
the number of option the player picked. Numbering of options starts at 1.
|
|
This number is consistent with empty options and grouped options.
|
|
|
|
menu("A::B", L_Wrong, "", L_Impossible, "C", L_Right);
|
|
L_Wrong:
|
|
// If they click "A" or "B" they will end up here
|
|
// @menu == 1 if "A"
|
|
// @menu == 2 will never happen because the option is empty
|
|
// @menu == 3 if "B"
|
|
L_Impossible:
|
|
// Empty options are not displayed and therefore can't be selected
|
|
// this label will never be reached from the menu command
|
|
L_Right:
|
|
// If they click "C" they will end up here
|
|
// @menu == 5
|
|
|
|
If a label is '-', the script execution will continue right after the menu
|
|
command if that option is selected, this can be used to save you time, and
|
|
optimize big scripts.
|
|
|
|
menu("A::B:", -, "C", L_Right);
|
|
// If they click "A" or "B" they will end up here
|
|
// @menu == 1 if "A"
|
|
// @menu == 3 if "B"
|
|
L_Right:
|
|
// If they click "C" they will end up here
|
|
// @menu == 5
|
|
|
|
Both these examples will perform the exact same task.
|
|
|
|
If you give an empty string as a menu item, the item will not display.
|
|
This can effectively be used to script dynamic menus by using empty string
|
|
for entries that should be unavailable at that time.
|
|
|
|
You can do it by using arrays, but watch carefully - this trick isn't high
|
|
wizardry, but minor magic at least. You can't expect to easily duplicate
|
|
it until you understand how it works.
|
|
|
|
Create a temporary array of strings to contain your menu items, and
|
|
populate it with the strings that should go into the menu at this
|
|
execution, making sure not to leave any gaps. Normally, you do it with a
|
|
loop and an extra counter, like this:
|
|
|
|
setarray(.@possiblemenuitems$[0], <list of potential menu items>);
|
|
.@j = 0; // That's the menu lines counter.
|
|
|
|
// We loop through the list of possible menu items.
|
|
// .@i is our loop counter.
|
|
for (.@i = 0; .@i < getarraysize(.@possiblemenuitems$); ++.@i) {
|
|
// That 'condition' is whatever condition that determines whether
|
|
// a menu item number .@i actually goes into the menu or not.
|
|
|
|
if (<condition>) {
|
|
// We record the option into the list of options actually
|
|
// available.
|
|
.@menulist$[.@j] = .@possiblemenuitems$[.@i];
|
|
|
|
// We just copied the string, we do need it's number for later
|
|
// though, so we record it as well.
|
|
.@menureference[.@j] = .@i;
|
|
|
|
// Since we've just added a menu item into the list, we
|
|
// increment the menu lines counter.
|
|
++.@j;
|
|
}
|
|
|
|
// We go on to the next possible menu item.
|
|
}
|
|
|
|
This will create you an array .@menulist$ which contains the text of all
|
|
items that should actually go into the menu based on your condition, and
|
|
an array .@menureference, which contains their numbers in the list of
|
|
possible menu items. Remember, arrays start with 0. There's less of them
|
|
than the possible menu items you've defined, but the menu() command can
|
|
handle the empty lines - only if they are last in the list, and if it's
|
|
made this way, they are. Now comes a dirty trick:
|
|
|
|
// X is whatever the most menu items you expect to handle.
|
|
menu(.@menulist$[0], -, .@menulist$[1], -, ..., .@menulist$[<X>], -);
|
|
|
|
This calls up a menu of all your items. Since you didn't copy some of the
|
|
possible menu items into the list, it's end is empty and so no menu items
|
|
will show up past the end. But this menu() call doesn't jump anywhere, it
|
|
just continues execution right after the menu() command. (And it's a good
|
|
thing it doesn't, cause you can only explicitly define labels to jump to,
|
|
and how do you know which ones to define if you don't know beforehand
|
|
which options will end up where in your menu?)
|
|
But how do you figure out which option the user picked? Enter the @menu.
|
|
|
|
@menu contains the number of option that the user selected from the list,
|
|
starting with 1 for the first option. You know now which option the user
|
|
picked and which number in your real list of possible menu items it
|
|
translated to:
|
|
|
|
mes("You selected "+.@possiblemenuitems$[.@menureference[@menu-1]]+"!");
|
|
|
|
@menu is the number of option the user picked.
|
|
@menu-1 is the array index for the list of actually used menu items that
|
|
we made.
|
|
.@menureference[@menu-1] is the number of the item in the array of possible
|
|
menu items that we've saved just for this purpose.
|
|
|
|
And .@possiblemenuitems$[.@menureference[@menu-1]] is the string that we
|
|
used to display the menu line the user picked. (Yes, it's a handful, but
|
|
it works.)
|
|
|
|
You can set up a bunch of 'if (.@menureference[@menu-1]==X) goto(Y)'
|
|
statements to route your execution based on the line selected and still
|
|
generate a different menu every time, which is handy when you want to, for
|
|
example, make users select items in any specific order before proceeding,
|
|
or make a randomly shuffled menu.
|
|
|
|
Kafra code bundled with the standard distribution uses a similar
|
|
array-based menu technique for teleport lists, but it's much simpler and
|
|
doesn't use @menu, probably since that wasn't documented anywhere.
|
|
|
|
See also 'select', which is probably better in this particular case.
|
|
Instead of menu(), you could use select() like this:
|
|
|
|
.@dummy = select(.@menulist$[0], .@menulist$[1], ..., .@menulist$[<X>]);
|
|
|
|
For the purposes of the technique described above these two statements are
|
|
perfectly equivalent.
|
|
|
|
---------------------------------------
|
|
|
|
*zmenu("<option_text>", <target_label>{, "<option_text>", <target_label>, ...})
|
|
|
|
Same as *menu* but for zero npc dialogs.
|
|
Works only in zero clients starting from 20210721.
|
|
|
|
---------------------------------------
|
|
|
|
*select("<option>"{, "<option>", ...})
|
|
|
|
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.
|
|
|
|
---------------------------------------
|
|
|
|
*zselect("<option>"{, "<option>", ...})
|
|
|
|
Same as *select* but for zero npc dialogs.
|
|
Works only in zero clients starting from 20210721.
|
|
|
|
---------------------------------------
|
|
|
|
*prompt("<option>"{, "<option>", ...})
|
|
|
|
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().
|
|
|
|
---------------------------------------
|
|
|
|
*zprompt("<option>"{, "<option>", ...})
|
|
|
|
Same as *prompt* but for zero npc dialogs.
|
|
Works only in zero clients starting from 20210721.
|
|
|
|
---------------------------------------
|
|
|
|
*input(<variable>{, <min>{, <max>}})
|
|
|
|
This command will make an input box pop up on the client connected to the
|
|
invoking character, to allow entering of a number or a string. This has
|
|
many uses, one example would be a guessing game, also making use of the
|
|
'rand' function:
|
|
|
|
mes("[Woman]");
|
|
mes("Try and guess the number I am thinking of.");
|
|
mes("The number will be between 1 and 10.");
|
|
next();
|
|
.@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.
|
|
|
|
The command has two optional arguments and a return value.
|
|
The default value of 'min' and 'max' can be set with 'input_min_value' and
|
|
'input_max_value' in conf/map/script.conf.
|
|
For numeric inputs the value is capped to the range [min, max]. Returns 1
|
|
if the value was higher than 'max', -1 if lower than 'min' and 0 otherwise.
|
|
For string inputs it returns 1 if the string was longer than 'max', -1 is
|
|
shorter than 'min' and 0 otherwise. Note that an input string has a maximum
|
|
length of 70 characters.
|
|
|
|
---------------------------------------
|
|
|
|
*callfunc("<function>"{, <argument>, ...<argument>})
|
|
|
|
This command lets you call up a function NPC. A function NPC can be called
|
|
from any script on any map server. Using the 'return' 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
|
|
}
|
|
|
|
Alternately, user-defined functions may be called directly without the use
|
|
of the callfunc() script command.
|
|
|
|
function<TAB>script<TAB>SayHello<TAB>{
|
|
mes("Hello " + getarg(0));
|
|
return 0;
|
|
}
|
|
|
|
place,50,50,6<TAB>script<TAB>Man<TAB>115,{
|
|
mes("[Man]");
|
|
SayHello(strcharinfo(PC_NAME));
|
|
close();
|
|
}
|
|
|
|
Note:
|
|
|
|
!! A user-defined function must be declared /before/ a script attempts to
|
|
!! call it. That is to say, any functions should be placed above scripts
|
|
!! or NPCs (or loaded in a separate file first) before attempting to call
|
|
!! them directly.
|
|
|
|
---------------------------------------
|
|
|
|
*callsub(<label>{, <argument>, ...<argument>})
|
|
|
|
This command will go to a specified label within the current script (do
|
|
NOT use quotes around it) coming in as if it were a 'callfunc' call, and
|
|
pass it arguments given, if any, which can be recovered there with
|
|
'getarg'. When done there, you should use the 'return' command to go back
|
|
to the point from where this label was called. This is used when there is
|
|
a specific thing the script will do over and over, this lets you use the
|
|
same bit of code as many times as you like, to save space and time,
|
|
without creating extra NPC objects which are needed with 'callfunc'. A
|
|
label is not callable in this manner from another script.
|
|
|
|
Example 1: callsub for checking (if checks pass, return to script)
|
|
callsub(S_CheckFull, "guild_vs2", 50);
|
|
switch (rand(4)) {
|
|
case 0:
|
|
warp("guild_vs2", 9, 50);
|
|
end;
|
|
case 1:
|
|
warp("guild_vs2", 49, 90);
|
|
end;
|
|
case 2:
|
|
warp("guild_vs2", 90, 50);
|
|
end;
|
|
case 3:
|
|
warp("guild_vs2", 49, 9);
|
|
end;
|
|
}
|
|
end;
|
|
|
|
S_CheckFull:
|
|
if (getmapusers(getarg(0)) >= getarg(1)) {
|
|
mes("I'm sorry, this arena is full. Please try again later.");
|
|
close();
|
|
}
|
|
return;
|
|
|
|
Example 2: callsub used repeatedly, with different arguments
|
|
// notice how the Zeny check/delete is reused, instead of copy-pasting for
|
|
// every warp.
|
|
switch (select("Abyss Lake", "Amatsu Dungeon", "Anthell", "Ayothaya Dungeon", "Beacon Island, Pharos")) {
|
|
case 1:
|
|
callsub(S_DunWarp, "hu_fild05", 192, 207);
|
|
break;
|
|
case 2:
|
|
callsub(S_DunWarp, "ama_in02", 119, 181);
|
|
break;
|
|
case 3:
|
|
callsub(S_DunWarp, "moc_fild20", 164, 145);
|
|
break;
|
|
case 4:
|
|
callsub(S_DunWarp, "ayo_fild02", 279, 150);
|
|
break;
|
|
case 5:
|
|
callsub(S_DunWarp, "cmd_fild07", 132, 125);
|
|
break;
|
|
// etc
|
|
}
|
|
|
|
// ...
|
|
|
|
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.
|
|
|
|
You can pass multiple arguments in a function call:
|
|
|
|
callfunc("funcNPC", 5, 4, 3);
|
|
|
|
getarg(0) would be 5, getarg(1) would be 4 and getarg(2) would be 3.
|
|
|
|
Getarg also has an optional argument:
|
|
If the target argument exists, it is returned.
|
|
Otherwise, if <default_value> is present it is returned instead, if not
|
|
the script terminates immediately.
|
|
|
|
In 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 instruction causes the script execution to leave previously called
|
|
function with callfunc() or script with callsub() and return to the
|
|
location, where the call originated from. Optionally a return value can
|
|
be supplied.
|
|
|
|
Using this command outside of functions or scripts referenced by callsub
|
|
will result in error and termination of the script.
|
|
|
|
callfunc("<your function>"); // when nothing is returned
|
|
<variable> = callfunc("<your function>"); // when a value is being returned
|
|
|
|
---------------------------------------
|
|
|
|
{public | private} *function <function name>;
|
|
{public | private} *function <function name> {
|
|
<code>
|
|
}
|
|
|
|
In its first form, this syntax declares a local function so it can later be
|
|
defined. In its second form, the syntax both declares and defines a local
|
|
function. Local functions must be defined before being used. Note that the name
|
|
may only contain alphanumeric characters and underscore. Once defined, they can
|
|
be called from the current script as if they were regular built-in commands, and
|
|
can also be called from other scripts if they are marked as public. Local
|
|
functions may be marked as public by simply adding "public" prior to the
|
|
function definition. Functions not marked as public are private by default and
|
|
cannot be called from another script.
|
|
|
|
Usage:
|
|
|
|
1. Declare the function.
|
|
function <function name>;
|
|
2. Call the function anywhere within the script.
|
|
<function name>();
|
|
3. Define the function by adding its script.
|
|
<function name> {<code>}
|
|
|
|
Step 1 is optional if the function is defined prior to being called.
|
|
|
|
Example:
|
|
|
|
/* Function declaration */
|
|
function MyFunction;
|
|
|
|
/* Function call */
|
|
MyFunction();
|
|
|
|
/* Function definition */
|
|
function MyFunction {
|
|
// (do something)
|
|
return;
|
|
}
|
|
|
|
|
|
Example with public functions:
|
|
|
|
/* Function declaration + definition */
|
|
public function myFunction {
|
|
/* notice the "public" before the "function" keyword */
|
|
return;
|
|
}
|
|
|
|
/* Local call */
|
|
myFunction();
|
|
|
|
/* Call from another script */
|
|
"npc name"::myFunction();
|
|
|
|
|
|
Example with parameters and return value:
|
|
|
|
/* Function declaration */
|
|
function MyAdd;
|
|
|
|
mes("Enter two numbers.");
|
|
next();
|
|
input(.@a);
|
|
input(.@b);
|
|
/* Function call */
|
|
mesf("%i + %i = %i", .@a, .@b, MyAdd(.@a, .@b));
|
|
close();
|
|
|
|
/* Function definition */
|
|
function MyAdd {
|
|
return (getarg(0) + getarg(1));
|
|
}
|
|
|
|
|
|
---------------------------------------
|
|
|
|
*<function name>({<arg>...})
|
|
*"<npc name>"::<function name>({<arg>...})
|
|
*callfunctionofnpc("<function name>", "<npc name>"{, <arg>...});
|
|
|
|
In its first form, calls a previously defined local function. In its second
|
|
form, calls a previously defined public local function of another NPC. If the
|
|
name of the target NPC or the name of the local function is not known
|
|
beforehand, callfunctionofnpc() can be used instead of the second form.
|
|
See function() above for more details.
|
|
|
|
Example:
|
|
|
|
MyFunction(arg1, arg2, arg3);
|
|
"MyNPC"::MyFunction(arg1, arg2, arg3);
|
|
callfunctionofnpc("MyNPC", "MyFunction", arg1, arg2, arg3);
|
|
|
|
---------------------------------------
|
|
|
|
*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:
|
|
|
|
FUNCTION_IS_COMMAND - built-in script command (eg: mes, select, ...)
|
|
FUNCTION_IS_GLOBAL - user-defined global function (callable with callfunc)
|
|
FUNCTION_IS_LOCAL - user-defined local function
|
|
FUNCTION_IS_LABEL - user-defined label function (callable with callsub)
|
|
|
|
Example:
|
|
|
|
function script func1 {
|
|
dothat();
|
|
}
|
|
|
|
- script test FAKE_NPC,{
|
|
function func2 {
|
|
do_something();
|
|
}
|
|
|
|
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 (<condition>) <statement or block>
|
|
|
|
This is the basic conditional command.
|
|
|
|
The condition can be any expression. All expressions resulting in a
|
|
non-zero value will be considered True, including negative values. All
|
|
expressions resulting in a zero are false.
|
|
|
|
If the expression results in True, the statement will be executed. If it
|
|
isn't true, nothing happens and we move on to the next line of the script.
|
|
|
|
if (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.");
|
|
|
|
For more information on conditional operators see the operators section
|
|
above.
|
|
Anything that is returned by a function can be used in a condition check
|
|
without bothering to store it in a specific variable:
|
|
|
|
if (strcharinfo(PC_NAME) == "Daniel Jackson")
|
|
mes("It is true, you are Daniel!");
|
|
|
|
More examples of using the 'if' command in the real world:
|
|
|
|
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();
|
|
|
|
(Notice examples 1 and 2 have the same effect.)
|
|
|
|
Example 3:
|
|
|
|
++@var1;
|
|
mes("[Forgetful 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();
|
|
|
|
Example 5: Using complex conditions.
|
|
|
|
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();
|
|
|
|
See strcharinfo() for explanation of what this function does.
|
|
|
|
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();
|
|
}
|
|
...
|
|
|
|
---------------------------------------
|
|
|
|
*while (<condition>) <statement or block>
|
|
|
|
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 2: multiple statements
|
|
while (select("Yes", "No") == 2) {
|
|
mes("Why did you pick no?");
|
|
mes("You should pick yes instead!");
|
|
}
|
|
|
|
Example 3: counter-controlled loop
|
|
.@i = 1;
|
|
while (.@i <= 5) {
|
|
mes("This line will print 5 times.");
|
|
++.@i;
|
|
}
|
|
|
|
Example 4: sentinel-controlled loop
|
|
mes("Input 0 to stop");
|
|
input(.@num);
|
|
while (.@num != 0) {
|
|
mes("You entered " + .@num);
|
|
input(.@num);
|
|
}
|
|
close();
|
|
|
|
---------------------------------------
|
|
|
|
*for (<variable initialization>; <condition>; <variable update>) <statement or block>
|
|
|
|
Another pretest looping structure is the 'for' statement. It is considered
|
|
a specialized form of the 'while' statement, and is usually associated
|
|
with counter-controlled loops. Here are the steps of the 'for' statement:
|
|
the initialize statement is executed first and only once. The condition
|
|
test is performed. When the condition evaluates to false, the rest of the
|
|
for statement is skipped. When the condition evaluates to true, the body
|
|
of the loop is executed, then the update statement is executed (this
|
|
usually involves incrementing a variable). Then the condition is
|
|
reevaluated and the cycle continues.
|
|
|
|
Example 1:
|
|
for (.@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);
|
|
|
|
---------------------------------------
|
|
|
|
*do { <statements>; } while (<condition>)
|
|
|
|
The 'do...while' is the only post-test loop structure available in this
|
|
script language. With a post-test, the statements are executed once before
|
|
the condition is tested. When the condition is true, the statement(s) are
|
|
repeated. When the condition is false, control is transferred to the
|
|
statement following the 'do...while' loop expression.
|
|
|
|
Example 1: sentinel-controlled loop
|
|
mes("This menu will keep appearing until you pick Cancel");
|
|
do {
|
|
.@choice = select("One:Two:Three:Cancel");
|
|
} while (.@choice != 4);
|
|
|
|
Example 2: counter-controlled loop
|
|
mes("This will countdown from 10 to 1.");
|
|
.@i = 10;
|
|
do {
|
|
mes(.@i--);
|
|
} while (.@i > 0);
|
|
|
|
---------------------------------------
|
|
|
|
*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 lengthy loop
|
|
operations.
|
|
|
|
Example:
|
|
freeloop(true); // enable script to loop freely
|
|
|
|
//Be aware with what you do here.
|
|
for (.@i = 0; .@i < .@bigloop; ++.@i) {
|
|
dothis();
|
|
// will sleep the script for 1ms when detect an infinity loop to
|
|
// let Hercules do what it need to do (socket, timer, process,
|
|
// etc.)
|
|
}
|
|
|
|
freeloop(false); // disable
|
|
|
|
for (.@i = 0; .@i < .@bigloop; ++.@i) {
|
|
dothis();
|
|
// throw an infinity loop error
|
|
}
|
|
|
|
---------------------------------------
|
|
|
|
*setarray(<array name>[<first value>], <value>{, <value>...<value>})
|
|
|
|
This command will allow you to quickly fill up an array in one go. Check
|
|
the Kafra scripts in the distribution to see this used a lot.
|
|
|
|
setarray(.@array[0], 100, 200, 300, 400, 500, 600);
|
|
|
|
The index of the first element of the array to alter can be omitted if
|
|
zero. For example:
|
|
|
|
setarray(.@array, 200, 200, 200);
|
|
setarray(.@array[1], 300, 150);
|
|
|
|
will produce:
|
|
|
|
.@array[0] = 200
|
|
.@array[1] = 300
|
|
.@array[2] = 150
|
|
|
|
---------------------------------------
|
|
|
|
*cleararray(<array name>[<first value to alter>], <value>, <number of values to set>)
|
|
|
|
This command will change many array values at the same time to the same
|
|
value.
|
|
|
|
setarray(.@array, 100, 200, 300, 400, 500, 600);
|
|
// This will make all 6 values 0
|
|
cleararray(.@array[0], 0, 6);
|
|
// This will make array element 0 change to 245
|
|
cleararray(.@array[0], 245, 1);
|
|
// This is equivalent to the above
|
|
cleararray(.@array, 245, 1);
|
|
// This will make elements 1 and 2 change to 345
|
|
cleararray(.@array[1], 345, 2);
|
|
|
|
See 'setarray'.
|
|
|
|
---------------------------------------
|
|
|
|
*copyarray(<destination array>[<first value>], <source array>[<first value>], <amount of data to copy>)
|
|
|
|
This command lets you quickly shuffle a lot of data between arrays, which
|
|
is in some cases invaluable.
|
|
|
|
setarray(.@array, 100, 200, 300, 400, 500, 600);
|
|
// So we have made .@array[]
|
|
copyarray(.@array2[0], .@array[2], 2);
|
|
|
|
// Now, .@array2[0] will be equal to .@array[2] (300) and
|
|
// .@array2[1] will be equal to .@array[3].
|
|
|
|
So using the examples above:
|
|
.@array[0] = 100
|
|
.@array[1] = 200
|
|
.@array[2] = 300
|
|
.@array[3] = 400
|
|
.@array[4] = 500
|
|
.@array[5] = 600
|
|
|
|
New Array:
|
|
.@array2[0] = 300
|
|
.@array2[1] = 400
|
|
.@array2[2] = 0
|
|
.@array2[3] = 0
|
|
|
|
Notice that .@array[4] and .@array[5] won't be copied to the second array,
|
|
and it will return a 0.
|
|
|
|
---------------------------------------
|
|
|
|
*deletearray(<array name>[<first value>], <how much to delete>)
|
|
|
|
This command will delete a specified number of array elements totally from
|
|
an array, shifting all the elements beyond this towards the beginning.
|
|
|
|
// This will delete array element 0, and move all the other array
|
|
// elements up one place.
|
|
deletearray(.@array[0], 1);
|
|
|
|
// This would delete array elements numbered 1, 2 and 3, leave element 0
|
|
// in its place, and move the other elements ups, so there are no gaps.
|
|
deletearray(.@array[1], 3);
|
|
|
|
If the amount of items to delete is not specified, all elements of the
|
|
array starting from the specified one to the end, are deleted. If no
|
|
starting element is specified either, the the entire array will be
|
|
deleted.
|
|
|
|
// This would delete all elements of the array starting from 2, leaving
|
|
// element 0 and 1
|
|
deletearray(.@array[2]);
|
|
|
|
// This would delete all elements of the array
|
|
deletearray(.@array);
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
1.1 - Message formatting commands (tags)
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
*mesnavigation("<label>", "<map>"{, <x>{, <y>{, <show_window>{, <mode>{, <services_flag>{, <monster_id>}}}}}});
|
|
|
|
Generates and returns a <NAVI> tag with the given parameters. A <NAVI> tag when written to certain windows,
|
|
such as the one from "mes" command, will create a highlighted and clickable text, which when clicked,
|
|
starts the navigation system for the specified values.
|
|
|
|
It is important to note that for most "<modes>" values, it is expected that your client has proper navigation
|
|
files which includes the target NPC/monster, or they will fail.
|
|
|
|
If the current client doesn't support NAVI tags, returns a fall back text which generally looks like:
|
|
<label> (<map_name> <x>, <y>)
|
|
|
|
Parameters:
|
|
- label: (string, required)
|
|
The visible and clickable text. (example: "Hat maker")
|
|
|
|
- map: (string, required)
|
|
Target map name. (example: "prontera")
|
|
Note: when service_flag is NAV_WINDOW_SEARCH (-222) this becomes the search string.
|
|
|
|
- x: (int, optional, defaults to 0)
|
|
Target map X position
|
|
Note: does nothing when used with modes NAV_MODE_MAP or NAV_MODE_MOB
|
|
|
|
- y: (int, optional, defaults to 0)
|
|
Target map Y position
|
|
Note: does nothing when used with modes NAV_MODE_MAP or NAV_MODE_MOB
|
|
|
|
- show_window: (bool, optional, defaults to false)
|
|
Whether to open the navigation UI (true) or not (false) when clicking the label.
|
|
|
|
- mode: (int, optional, defaults to NAV_MODE_ALL (0))
|
|
The kind of navigation being performed. This mainly affects the messages shown by the client when you reach the map.
|
|
- NAV_MODE_ALL (0): "You have reached your destination"
|
|
- NAV_MODE_MAP (1): "You have reached the target map"
|
|
- NAV_MODE_NPC (2): "You have reached the map the NPC is at" / "You have reached the target NPC"
|
|
- NAV_MODE_MOB (3): "You have reached the map where the monster appears"
|
|
|
|
Notes:
|
|
- NAV_MODE_NPC requires client navigation files to have a NPC in the exact position or an error is shown
|
|
- NAV_MODE_MOB requires client navigation files to have <monster_id> spawn in the given map or an error is shown.
|
|
|
|
- services_flag: (int, optional, defaults to NAV_KAFRA_AND_AIRSHIP (101))
|
|
The kinds of services that may be used when calculating the route.
|
|
|
|
The following values may be summed up:
|
|
- NAV_AIRSHIP_ONLY (1): Include airships
|
|
- NAV_SCROLL_ONLY (10): Include scrolls
|
|
- NAV_KAFRA_ONLY (100): Include kafras
|
|
|
|
Summed values:
|
|
- NAV_AIRSHIP_AND_SCROLL (11)
|
|
- NAV_KAFRA_AND_AIRSHIP (101)
|
|
- NAV_KAFRA_AND_SCROLL (110)
|
|
- NAV_ALL (111)
|
|
|
|
Special values:
|
|
- NAV_WINDOW_SEARCH (-222)
|
|
This is a special value that can't be summed with others and when used,
|
|
"map" becomes a search string in the navigation UI. And client performs a search
|
|
with the special keyword "$$DB".
|
|
It is only known to work together with mode = NAV_MODE_MOB and using monster Sprite Name
|
|
as "map".
|
|
When using NAV_WINDOW_SEARCH, prefer using mesmobspawn instead.
|
|
|
|
- monster_id: (int, optional, defaults to 0)
|
|
To be used with mode = NAV_MODE_MOB. The ID of the monster being looked for.
|
|
|
|
---------------------------------------
|
|
|
|
*mesmobspawn(<monster_id>{, "<label>"})
|
|
|
|
Generates and returns a <NAVI> tag that opens the Navigation UI listing the places where <monster_id> monster spawns.
|
|
|
|
This will only work if your client navigation files are properly configured with the <monster_id> spawns.
|
|
|
|
If the current client doesn't support this feature, returns the value of <label>.
|
|
|
|
Parameters:
|
|
- monster_id: (int, required)
|
|
The ID of the monster being looked for.
|
|
|
|
- label: (string, optional, defaults to <monster_id> name)
|
|
The visible and clickable text. (example: "Target monster")
|
|
|
|
---------------------------------------
|
|
|
|
*mesurl("<label>", "url"{, <width>, <height>})
|
|
|
|
Generates and returns a <URL> tag. When presented in certain places (like with "mes" and "mesf"),
|
|
this will display a clickable text (<label>) which when clicked, opens <url> in the in-game browser
|
|
or default browser (depending on client version).
|
|
|
|
If the current client doesn't support this feature, returns a basic string in the following format:
|
|
<label> (<url>)
|
|
|
|
Parameters:
|
|
- label: (string, required)
|
|
The visible and clickable text. (example: "My site")
|
|
|
|
- url: (string, required)
|
|
The site that will open when <label> is clicked
|
|
|
|
- width: (int, optional, defaults to -1)
|
|
The width of the browser window (when using in-game browser).
|
|
When not provided (or -1), width/height is not specified.
|
|
|
|
- height: (int, optional, defaults to -1)
|
|
The height of the browser window (when using in-game browser).
|
|
When not provided (or -1), width/height is not specified.
|
|
|
|
---------------------------------------
|
|
|
|
*mestipbox("<label>", <tip_id>)
|
|
|
|
Generates and returns a <TIPBOX> tag. When presented in certain places (like with "mes" and "mesf"),
|
|
this will display a clickable text (<label>) which when clicked, opens the TipBox UI with the given <tip_id>.
|
|
|
|
If the current client doesn't support this feature, returns a simple string with "<label>"
|
|
|
|
Parameters:
|
|
- label: (string, required)
|
|
The visible and clickable text. (example: "Super Tip")
|
|
|
|
- tip_id: (int, required)
|
|
The tip ID (as set in TipBox lua file)
|
|
If 0, it shows a random tipbox
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
1 - End of Basic-Related Commands
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
2 - Information-retrieving Related Commands
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
*strcharinfo(<type>{, <default value>{, <GID>}})
|
|
|
|
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.
|
|
|
|
If a character is not a member of any party or guild, an empty string will
|
|
be returned when requesting that information.
|
|
|
|
Note: Numbers can also be used in <type>, but their usage is discouraged as
|
|
using only numbers reduces script readability
|
|
|
|
---------------------------------------
|
|
|
|
*strnpcinfo(<type>{, <default value>{, <GID>}})
|
|
|
|
This function will return the various parts of the name of the calling NPC.
|
|
Whatever it returns is determined by type.
|
|
|
|
(0) NPC_NAME - The NPC's display name (visible#hidden)
|
|
(1) NPC_NAME_VISIBLE - The visible part of the NPC's display name
|
|
(2) NPC_NAME_HIDDEN - The hidden part of the NPC's display name
|
|
(3) NPC_NAME_UNIQUE - The NPC's unique name (::name)
|
|
(4) NPC_MAP - The name of the map the NPC is in.
|
|
|
|
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.
|
|
|
|
If the character is offline or doesn't exist, 0 is returned.
|
|
|
|
---------------------------------------
|
|
|
|
*getarraysize(<array name>)
|
|
|
|
This function returns highest index of the array that is filled.
|
|
Notice that zeros and empty strings at the end of this array are not
|
|
counted towards this number.
|
|
|
|
For example:
|
|
|
|
setarray(.@array, 100, 200, 300, 400, 500, 600);
|
|
.@arraysize = getarraysize(.@array);
|
|
|
|
This will make .@arraysize == 6. But if you try this:
|
|
|
|
setarray(.@array, 100, 200, 300, 400, 500, 600, 0);
|
|
.@arraysize = getarraysize(.@array);
|
|
|
|
.@arraysize will still equal 6, even though you've set 7 values.
|
|
|
|
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
|
|
|
|
---------------------------------------
|
|
|
|
*getelementofarray(<array name>, <index>)
|
|
|
|
This command retrieves the value of the element of given array at given
|
|
index. This is equivalent to using:
|
|
|
|
<array name>[<index>]
|
|
|
|
Also useful when passing arrays to functions or accessing another npc's
|
|
arrays:
|
|
getelementofarray(getarg(0), <index>)
|
|
getelementofarray(getvariableofnpc(.var, "testNPC"), <index>)
|
|
|
|
---------------------------------------
|
|
|
|
*readparam(<parameter number>{, "<player name>"})
|
|
*readparam(<parameter number>{, <account id>})
|
|
|
|
This function will return the basic stats of an invoking character,
|
|
referred to by the parameter number. Instead of a number, you can use a
|
|
parameter name if it is defined in 'doc/constants_(pre-)re.md'.
|
|
|
|
Example parameters:
|
|
|
|
StatusPoint, BaseLevel, SkillPoint, Class, Upper, Zeny, Sex, Weight,
|
|
MaxWeight, JobLevel, BaseExp, JobExp, NextBaseExp, NextJobExp, Hp, MaxHp,
|
|
Sp, MaxSp, BaseJob, Karma, Manner, bVit, bDex, bAgi, bStr, bInt, bLuk
|
|
|
|
All of these also behave as variables, but don't expect to be able to just
|
|
'set' them - some will not work for various internal reasons.
|
|
|
|
Example 1:
|
|
|
|
// Returns how many status points you haven't spent yet.
|
|
mes("Unused status points: "+readparam(9)); // [!]
|
|
|
|
Using this particular information as a function call is not required.
|
|
Typing this will return the same result:
|
|
|
|
mes("Unused status points: "+StatusPoint);
|
|
|
|
Example 2:
|
|
|
|
You can also use this command to get stat values.
|
|
|
|
if (readparam(bVit) > 77)
|
|
mes("Only people with over 77 Vit are reading this!");
|
|
|
|
Example 3:
|
|
|
|
// Display your current weight
|
|
mes("Your current weight is "+ (Weight/10) + "/" + (MaxWeight/10));
|
|
|
|
---------------------------------------
|
|
|
|
*setparam(<parameter number>, <value>{, "<player name>"})
|
|
*setparam(<parameter number>, <value>{, <account id>})
|
|
|
|
Sets a parameter on the given player. See readparam() for more info about
|
|
parameters. Keep in mind that not all read-able parameters are also set-able.
|
|
|
|
Parameters that can be modified include:
|
|
|
|
StatusPoint, BaseLevel, SkillPoint, Zeny, Sex, Weight, MaxWeight, JobLevel,
|
|
BaseExp, JobExp, Hp, MaxHp, Sp, MaxSp, Karma, Manner, Fame, bVit, bDex, bAgi,
|
|
bStr, bInt, bLuk
|
|
|
|
|
|
---------------------------------------
|
|
|
|
*getcharid(<type>{, "<character name>"})
|
|
*getcharid(<type>{, <account id>})
|
|
|
|
This function will return a unique ID number of the invoking character,
|
|
or, if a character name is specified, of that player.
|
|
|
|
Type is the kind of associated ID number required:
|
|
|
|
(0) CHAR_ID_CHAR - Character ID number.
|
|
(1) CHAR_ID_PARTY - Party ID number.
|
|
(2) CHAR_ID_GUILD - Guild ID number.
|
|
(3) CHAR_ID_ACCOUNT - Account ID number.
|
|
(4) CHAR_ID_BG - Battle ground ID
|
|
(5) CHAR_ID_CLAN - Clan ID number.
|
|
|
|
For most purposes other than printing it, a number is better to have than
|
|
a name (people do horrifying things to their character names).
|
|
|
|
If the character is not in a party or not in a guild, the function will
|
|
return 0 if guild or party number is requested. If a name is specified and
|
|
the character is not found, 0 is returned.
|
|
|
|
If getcharid(CHAR_ID_CHAR) returns a zero, the script got called not by a character
|
|
and doesn't have an attached RID. Note that this will cause the map server
|
|
to print "player not attached!" error messages, so it is preferred to use
|
|
playerattached() to check for the character attached to the script.
|
|
|
|
if (getcharid(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.
|
|
|
|
If the NPC does not exist, 0 is returned.
|
|
|
|
---------------------------------------
|
|
|
|
*getchildid()
|
|
*getmotherid()
|
|
*getfatherid()
|
|
|
|
These functions return the character ID of the attached player's child,
|
|
mother, mother, or father, respectively. It returns 0 if no ID is found.
|
|
|
|
if (getmotherid() != 0)
|
|
mes("Your mother's ID is: "+getmotherid());
|
|
|
|
---------------------------------------
|
|
|
|
*ispartneron()
|
|
|
|
This function returns true if the invoking character's marriage partner
|
|
is currently online and false if they are not or if the character has no
|
|
partner.
|
|
|
|
---------------------------------------
|
|
|
|
*getpartnerid()
|
|
|
|
This function returns the character ID of the invoking character's
|
|
marriage partner, if any. If the invoking character is not married, it
|
|
will return 0, which is a quick way to see if they are married:
|
|
|
|
if (getpartnerid() == 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.
|
|
|
|
Lets say the ID of a party was saved as a global variable:
|
|
|
|
// This would return the name of the party from the ID stored in a
|
|
// variable
|
|
mes("You're in the '"+getpartyname($@var)+"' party, I know!");
|
|
|
|
---------------------------------------
|
|
|
|
*getpartymember(<party_id>, <type>, <array>)
|
|
|
|
This command will find all members of a specified <party_id>, copy their
|
|
names (or character id or account id) depending on the <type> into <array>
|
|
and returns the number of party members that were found.
|
|
|
|
Valid <type> are:
|
|
|
|
PT_MEMBER_NAME - Party member names
|
|
PT_MEMBER_CHARID - Party member character ID
|
|
PT_MEMBER_ACCID - Party member account ID
|
|
|
|
Make sure to use string variable for PT_MEMBER_NAME and
|
|
int variable for PT_MEMBER_CHARID and PT_MEMBER_ACCID
|
|
|
|
Example 1: Listing party member names
|
|
|
|
// get the party member names
|
|
.@count = getpartymember(getcharid(CHAR_ID_PARTY), PT_MEMBER_NAME, .@name$);
|
|
|
|
// list the party member names
|
|
for (.@i = 0; .@i < .@count; ++.@i) {
|
|
mes((.@i +1) + ". ^0000FF" + .@name$[.@i] + "^000000");
|
|
}
|
|
close();
|
|
|
|
Example 2: Get online count
|
|
|
|
// get the charID and accountID of character's party members
|
|
// we only need to count the member once so we assign that
|
|
// to the our second command call
|
|
getpartymember(getcharid(CHAR_ID_PARTY), PT_MEMBER_CHARID, .@charid);
|
|
.@count = getpartymember(getcharid(CHAR_ID_PARTY), PT_MEMBER_ACCID, .@accid);
|
|
|
|
for (.@i = 0; .@i < .@count; ++.@i) {
|
|
if (isloggedin(.@accid[.@i], .@charid[.@i]))
|
|
.@count_online++;
|
|
}
|
|
end;
|
|
|
|
---------------------------------------
|
|
|
|
*getpartyleader(<party id>{, <type>})
|
|
|
|
This function returns some information about the given party-id's leader.
|
|
When type is omitted, the default information retrieved is the leader's
|
|
name. Possible types are:
|
|
|
|
1: Leader account id
|
|
2: Leader character id
|
|
3: Leader's class
|
|
4: Leader's current map name
|
|
5: Leader's current level as stored on the party structure (may not be
|
|
current level if leader leveled up recently).
|
|
|
|
If retrieval fails (leader not found or party does not exist), this
|
|
function returns "null" instead of the character name, and -1 for the
|
|
other types.
|
|
|
|
---------------------------------------
|
|
|
|
*getlook(<type>)
|
|
|
|
This function will return the number for the current character look value
|
|
specified by type. See 'setlook' for valid look types.
|
|
|
|
This can be used to make a certain script behave differently for
|
|
characters dressed in black. :)
|
|
|
|
---------------------------------------
|
|
|
|
*getsavepoint(<information type>)
|
|
|
|
This function will return information about the invoking character's save
|
|
point. You can use it to let a character swap between several recorded
|
|
save points. Available information types are:
|
|
|
|
0 - Map name (a string)
|
|
1 - X coordinate
|
|
2 - Y coordinate
|
|
|
|
---------------------------------------
|
|
|
|
*getcharip({"<character name>"})
|
|
*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:
|
|
|
|
// Outputs IP address of attached player.
|
|
mes("Your IP: " + getcharip());
|
|
|
|
// Outputs IP address of character "Silver".
|
|
mes("Silver's IP: " + getcharip("Silver"));
|
|
|
|
---------------------------------------
|
|
|
|
*getunitparam(<param type>{, <class>{, <maxlv array>, <value array>}})
|
|
|
|
Thi will return the requested parameter's value or fill the required arrays in
|
|
the case of UNIT_PARAM_MAX_HP.
|
|
|
|
<param type>:
|
|
- UNIT_PARAM_NAME ^= name of unit_parameters_db.conf entry used by class.
|
|
- UNIT_PARAM_NATHEAL_WEIGHT_RATE ^= NaturalHealWeightRate value
|
|
- UNIT_PARAM_MAX_ASPD ^= MaxASPD
|
|
- UNIT_PARAM_MAX_HP ^= MaxHP
|
|
- UNIT_PARAM_MAX_STATS ^= MaxStats
|
|
|
|
<class> can be -1 if attached players class is desired, such as in the case of UNIT_PARAM_MAX_HP,
|
|
where <class> is mandatory.
|
|
|
|
Examples:
|
|
|
|
// Outputs the possible maximum ASPD of attached player.
|
|
mesf("MAX_ASPD: %d", getunitparam(UNIT_PARAM_MAX_ASPD));
|
|
|
|
// Outputs the possible maximum stats of Job_Baby.
|
|
mesf("MAX_STATS: %d", getunitparam(UNIT_PARAM_MAX_STATS, Job_Baby));
|
|
|
|
// Saves the entries for MAXHP per level ranges of JOB_SUPER_NOVICE into the given arrays and prints them.
|
|
.@count = getunitparam(UNIT_PARAM_MAX_ASPD, JOB_SUPER_NOVICE, .@max_lv, .@max_hp);
|
|
for (.@i = 0; .@i < .@count; ++.@i) {
|
|
mesf("max_lv: %d, max_hp: %d", .@max_lv[.@i], .@max_hp[.@i]);
|
|
}
|
|
|
|
---------------------------------------
|
|
|
|
*sit({"<character name>"})
|
|
*stand({"<character name>"})
|
|
|
|
This function will force a character to sit/stand if it is standing/sitting.
|
|
If no player is specified, the attached player will be used.
|
|
|
|
---------------------------------------
|
|
|
|
*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:
|
|
|
|
EQI_HEAD_TOP (1) - Upper head gear
|
|
EQI_ARMOR (2) - Armor (Where you keep your Jackets and Robes)
|
|
EQI_HAND_L (3) - What is in your Left hand.
|
|
EQI_HAND_R (4) - What is in your Right hand.
|
|
EQI_GARMENT (5) - The garment slot (Mufflers, Hoods, Manteaus)
|
|
EQI_SHOES (6) - What foot gear the player has on.
|
|
EQI_ACC_L (7) - Accessory 1.
|
|
EQI_ACC_R (8) - Accessory 2.
|
|
EQI_HEAD_MID (9) - Middle Headgear (masks and glasses)
|
|
EQI_HEAD_LOW (10) - Lower Headgear (beards, some masks)
|
|
EQI_COSTUME_HEAD_LOW (11) - Lower Costume Headgear
|
|
EQI_COSTUME_HEAD_MID (12) - Middle Costume Headgear
|
|
EQI_COSTUME_HEAD_TOP (13) - Upper Costume Headgear
|
|
EQI_COSTUME_GARMENT (14) - Costume Garment
|
|
EQI_SHADOW_ARMOR (15) - Shadow Armor
|
|
EQI_SHADOW_WEAPON (16) - Shadow Weapon
|
|
EQI_SHADOW_SHIELD (17) - Shadow Shield
|
|
EQI_SHADOW_SHOES (18) - Shadow Shoes
|
|
EQI_SHADOW_ACC_R (19) - Shadow Accessory 2
|
|
EQI_SHADOW_ACC_L (20) - Shadow Accessory 1
|
|
|
|
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:
|
|
|
|
if (getequipid(EQI_ARMOR) == Full_Plate_Armor || getequipid(EQI_ARMOR) == Full_Plate_Armor_) {
|
|
mes("You are wearing some Legion Plate Armor, please drop that in your stash before continuing");
|
|
close();
|
|
}
|
|
if (countitem(Full_Plate_Armor) > 0 || countitem(Full_Plate_Armor_) > 0) {
|
|
mes("You have some Legion Plate Armor in your inventory, please drop that in your stash before continuing");
|
|
close();
|
|
}
|
|
mes("I will lets you pass");
|
|
close2();
|
|
warp("place", 50, 50);
|
|
end;
|
|
|
|
---------------------------------------
|
|
|
|
*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.
|
|
|
|
// Let's see if they have anything broken:
|
|
if (getbrokenid(1) == 0)
|
|
mes("You don't have anything broken, quit bothering me.");
|
|
else // They do, so let's print the name of the first broken item:
|
|
mes("Oh, I see you have a broken "+getitemname(getbrokenid(1))+" here!");
|
|
|
|
---------------------------------------
|
|
|
|
*getbrokencount()
|
|
|
|
This function will return the total amount of broken equipment on the
|
|
invoking character.
|
|
|
|
---------------------------------------
|
|
|
|
*getequipisequiped(<equipment slot>)
|
|
|
|
This functions will return 1 if there is an equipment placed on the
|
|
specified equipment slot and 0 otherwise. For a list of equipment slots
|
|
see 'getequipid'. Function originally used by the refining NPCs:
|
|
|
|
if (getequipisequiped(EQI_HEAD_TOP)) {
|
|
mes("[Refiner]");
|
|
mes("That's a fine hat you are wearing there...");
|
|
close();
|
|
}
|
|
mes("[Refiner]");
|
|
mes("Do you want me to refine your dumb head?");
|
|
close();
|
|
|
|
---------------------------------------
|
|
|
|
*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();
|
|
|
|
---------------------------------------
|
|
|
|
*getequiprefinerycnt(<equipment slot>{, <equipment slot>{, <equipment slot>}})
|
|
|
|
Returns the total of refine of item equipped in the equipment slots.
|
|
For a list of equipment slots, see 'getequipid'.
|
|
|
|
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.
|
|
|
|
If no item is equipped in this slot, or if it doesn't have a weapon level
|
|
according to the database, 0 will be returned.
|
|
|
|
Examples:
|
|
|
|
// Right hand can only contain a weapon.
|
|
switch (getequipweaponlv(EQI_HAND_R)) {
|
|
case 1:
|
|
mes("You are holding a lvl 1 weapon.");
|
|
break;
|
|
case 2:
|
|
mes("You are holding a lvl 2 weapon.");
|
|
break;
|
|
case 3:
|
|
mes("You are holding a lvl 3 weapon.");
|
|
break;
|
|
case 4:
|
|
mes("You are holding a lvl 4 weapon.");
|
|
break;
|
|
case 5:
|
|
mes("You are holding a lvl 5 weapon, hm, must be a custom design...");
|
|
break;
|
|
default:
|
|
mes("Seems you don't have a weapon on.");
|
|
break;
|
|
}
|
|
|
|
// Left hand can hold either a weapon or shield.
|
|
if (getequipid(EQI_HAND_R) == 0) {
|
|
mes("Seems you have nothing equipped here.");
|
|
close();
|
|
}
|
|
switch (getequipweaponlv(EQI_HAND_L)) {
|
|
case 0:
|
|
mes("You are holding a shield, so it doesn't have a level.");
|
|
break;
|
|
case 1:
|
|
mes("You are holding a lvl 1 weapon.");
|
|
break;
|
|
case 2:
|
|
mes("You are holding a lvl 2 weapon.");
|
|
break;
|
|
case 3:
|
|
mes("You are holding a lvl 3 weapon.");
|
|
break;
|
|
case 4:
|
|
mes("You are holding a lvl 4 weapon.");
|
|
break;
|
|
case 5:
|
|
mes("You are holding a lvl 5 weapon, hm, must be a custom design...");
|
|
break;
|
|
}
|
|
|
|
---------------------------------------
|
|
|
|
*getequippercentrefinery(<equipment slot>{, <type>})
|
|
|
|
This function calculates and returns the percent value chance to
|
|
successfully refine the item found in the specified equipment slot of the
|
|
invoking character by +1. Refine rates are defined in the 'db/(pre-)re//refine_db.conf'
|
|
files. For a list of equipment slots see getequipid().
|
|
|
|
These values can be displayed for the player to see, or used to calculate
|
|
the random change of a refine succeeding or failing and then going through
|
|
with it (which is what the official NPC refinery scripts use it for).
|
|
|
|
Refine Chance Type Constants -
|
|
REFINE_CHANCE_TYPE_NORMAL: 0 (Normal Ores)
|
|
REFINE_CHANCE_TYPE_ENRICHED: 1 (Enriched Ores)
|
|
REFINE_CHANCE_TYPE_E_NORMAL: 2 (Event Normal Ores)
|
|
REFINE_CHANCE_TYPE_E_ENRICHED: 3 (Event Enriched Ores)
|
|
|
|
Refine rate information -
|
|
Normal Ores: http://ro.gnjoy.com/news/probability/View.asp?category=4&seq=1941553&curpage=1
|
|
Enriched Ores: http://ro.gnjoy.com/news/probability/View.asp?category=4&seq=1941565&curpage=1
|
|
Event Normal Ores: http://ro.gnjoy.com/news/probability/View.asp?category=4&seq=1941558&curpage=1
|
|
Event Enriched Ores: http://ro.gnjoy.com/news/probability/View.asp?category=4&seq=1941567&curpage=1
|
|
|
|
// This will find a random number from 0 - 99 and if that is equal to or
|
|
// more than the value recovered by this command it will show a message
|
|
if (getequippercentrefinery(EQI_HAND_L, REFINE_CHANCE_TYPE_NORMAL) <= rand(100))
|
|
mes("Aww");
|
|
|
|
---------------------------------------
|
|
|
|
*getareadropitem("<map name>", <x1>, <y1>, <x2>, <y2>, <item>)
|
|
|
|
This function will count all the items with the specified ID number lying
|
|
on the ground on the specified map within the x1/y1-x2/y2 square on it and
|
|
return that number.
|
|
|
|
This is the only function around where a parameter may be either a string
|
|
or a number! If it's a number, it means that only the items with that item
|
|
ID number will be counted. If it is a string, it is assumed to mean the
|
|
'english name' field from the item database. If you give it an empty
|
|
string, or something that isn't found from the item database, it will
|
|
count items number 512 (Apple).
|
|
|
|
---------------------------------------
|
|
|
|
*getequipcardcnt(<equipment slot>)
|
|
|
|
This function will return the number of items/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:
|
|
|
|
@inventorylist_id[] - array of item ids.
|
|
@inventorylist_idx[] - array of item inventory index.
|
|
@inventorylist_amount[] - their corresponding item amounts.
|
|
@inventorylist_equip[] - will return the slot the item is equipped on, if at all.
|
|
@inventorylist_refine[] - for how much it is refined.
|
|
@inventorylist_grade[] - for grade levels.
|
|
@inventorylist_identify[] - whether it is identified.
|
|
@inventorylist_attribute[] - whether it is broken.
|
|
@inventorylist_card1[] - These four arrays contain card data for the items.
|
|
@inventorylist_card2[] These data slots are also used to store names inscribed
|
|
@inventorylist_card3[] on the items, so you can explicitly check if the character
|
|
@inventorylist_card4[] owns an item made by a specific craftsman.
|
|
@inventorylist_expire[] - expire time (Unix time stamp). 0 means never expires.
|
|
@inventorylist_bound[] - whether it is an account bounded item or not.
|
|
@inventorylist_favorite[] - whether it is favorite (inside favorite tab) or not.
|
|
@inventorylist_opt_id1~5[] - array of random option id.
|
|
@inventorylist_opt_val1~5[] - array of random option val.
|
|
@inventorylist_opt_param1~5[] - array of random option param.
|
|
@inventorylist_count - the number of items in these lists.
|
|
|
|
This could be handy to save/restore a character's inventory, since no
|
|
other command returns such a complete set of data, and could also be the
|
|
only way to correctly handle an NPC trader for carded and named items who
|
|
could resell them - since NPC objects cannot own items, so they have to
|
|
store item data in variables and recreate the items.
|
|
|
|
Notice that the variables this command generates are all temporary,
|
|
attached to the character, and integer.
|
|
|
|
Be sure to use @inventorylist_count to go through these arrays, and not
|
|
getarraysize(), because the arrays are not automatically cleared between
|
|
runs of getinventorylist().
|
|
|
|
---------------------------------------
|
|
|
|
*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:
|
|
|
|
@cartinventorylist_id[] - array of item ids.
|
|
@cartinventorylist_amount[] - their corresponding item amounts.
|
|
@cartinventorylist_refine[] - for how much it is refined.
|
|
@cartinventorylist_grade[] - for grade levels.
|
|
@cartinventorylist_identify[] - whether it is identified.
|
|
@cartinventorylist_attribute[] - whether it is broken.
|
|
@cartinventorylist_card1[] - These four arrays contain card data for the items.
|
|
@cartinventorylist_card2[] These data slots are also used to store names inscribed on the items,
|
|
@cartinventorylist_card3[] so you can explicitly check if the character owns an item
|
|
@cartinventorylist_card4[] made by a specific craftsman.
|
|
@cartinventorylist_expire[] - expire time (Unix time stamp). 0 means never expires.
|
|
@cartinventorylist_bound - whether it is an account bound item or not.
|
|
@cartinventorylist_opt_id1~5[] - array of random option id.
|
|
@cartinventorylist_opt_val1~5[] - array of random option val.
|
|
@cartinventorylist_opt_param1~5[] - array of random option param.
|
|
@cartinventorylist_count - the number of items in these lists.
|
|
|
|
This could be handy to save/restore a character's cart_inventory, since no
|
|
other command returns such a complete set of data, and could also be the
|
|
only way to correctly handle an NPC trader for carded and named items who
|
|
could resell them - since NPC objects cannot own items, so they have to
|
|
store item data in variables and recreate the items.
|
|
|
|
Notice that the variables this command generates are all temporary,
|
|
attached to the character, and integer.
|
|
|
|
Be sure to use @cartinventorylist_count to go through these arrays, and not
|
|
getarraysize(), because the arrays are not automatically cleared between
|
|
runs of getcartinventorylist().
|
|
|
|
---------------------------------------
|
|
|
|
*setfavoriteitemidx(<idx>, <flag>)
|
|
|
|
This function will set an item in inventory as favorite or not.
|
|
If its favorite item, it will be moved to favorite tab, else move out from favorite tab.
|
|
Note: Cant change favorite flag of an equipped item.
|
|
|
|
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);
|
|
|
|
---------------------------------------
|
|
|
|
*getiteminfo(<item ID>, <type>)
|
|
*getiteminfo("<item name>", <type>)
|
|
*setiteminfo(<item ID>, <type>, <value>)
|
|
|
|
This function will look up the item with the specified ID number in the
|
|
database and return the info set by TYPE argument.
|
|
It will return -1 if there is no such item.
|
|
|
|
Valid types are:
|
|
|
|
ITEMINFO_ID - Item ID (getiteminfo() only!)
|
|
ITEMINFO_AEGISNAME - Unique name to reference the item (getiteminfo() only!)
|
|
ITEMINFO_NAME - Display name (getiteminfo() only!)
|
|
ITEMINFO_BUYPRICE - Buy Price
|
|
ITEMINFO_SELLPRICE - Sell Price
|
|
ITEMINFO_TYPE - Item Type
|
|
ITEMINFO_MAXCHANCE - Max drop chance of this item e.g. 1 = 0.01% , etc..
|
|
if = 0, then monsters don't drop it at all (rare or a quest item)
|
|
if = 10000, then this item is sold in NPC shops only
|
|
ITEMINFO_SEX - Sex
|
|
ITEMINFO_LOC - Equip location
|
|
ITEMINFO_WEIGHT - Weight (note: 1/10 of unit)
|
|
ITEMINFO_ATK - Attack
|
|
ITEMINFO_DEF - Defense
|
|
ITEMINFO_RANGE - Range
|
|
ITEMINFO_SLOTS - Slots
|
|
ITEMINFO_SUBTYPE - Item subtype
|
|
ITEMINFO_ELV - Equip min. level
|
|
ITEMINFO_ELV_MAX - Equip max. level
|
|
ITEMINFO_WLV - Weapon level
|
|
ITEMINFO_VIEWID - View ID ("Sprite" field in the Item DB)
|
|
ITEMINFO_MATK - MATK (only relevant if RENEWAL is set)
|
|
ITEMINFO_VIEWSPRITE - View Sprite ("ViewSprite" field in the Item DB)
|
|
ITEMINFO_TRADE - Trade Restriction (see "doc/constant.md": item trade restriction)
|
|
ITEMINFO_DELAY - Delay
|
|
ITEMINFO_DROPEFFECT_MODE - Drop effect mode
|
|
ITEMINFO_CLASS_BASE_1 - Class base 1
|
|
ITEMINFO_CLASS_BASE_2 - Class base 2
|
|
ITEMINFO_CLASS_BASE_3 - Class base 3
|
|
ITEMINFO_CLASS_UPPER - Class Upper
|
|
ITEMINFO_FLAG_NO_REFINE - No refine flag
|
|
ITEMINFO_FLAG_NO_GRADE - No grade flag
|
|
ITEMINFO_FLAG_DELAY_CONSUME - Delay consume flag
|
|
ITEMINFO_FLAG_AUTOEQUIP - Auto equip flag
|
|
ITEMINFO_FLAG_AUTO_FAVORITE - Auto favorite flag
|
|
ITEMINFO_FLAG_BUYINGSTORE - Buying store flag
|
|
ITEMINFO_FLAG_BINDONEQUIP - Bind on equip flag
|
|
ITEMINFO_FLAG_KEEPAFTERUSE - Keep after use flag
|
|
ITEMINFO_FLAG_FORCE_SERIAL - Force serial flag
|
|
ITEMINFO_FLAG_NO_OPTIONS - No random item options flag
|
|
ITEMINFO_FLAG_DROP_ANNOUNCE - Drop announce flag
|
|
ITEMINFO_FLAG_SHOWDROPEFFECT - Show drop effect flag
|
|
ITEMINFO_STACK_AMOUNT - Stack amount
|
|
ITEMINFO_STACK_FLAG - Stack amount flag (1: inventory, 2: cart, 4: storage, 8: guild storage)
|
|
ITEMINFO_ITEM_USAGE_FLAG - Item usage flag
|
|
ITEMINFO_ITEM_USAGE_OVERRIDE - Item usage override
|
|
ITEMINFO_GM_LV_TRADE_OVERRIDE - Min. GM level override trade restriction
|
|
ITEMINFO_FLAG_SELECT_PACKAGE - Selection packages flag
|
|
|
|
Check sample in doc/sample/getiteminfo.txt
|
|
|
|
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:
|
|
|
|
setiteminfo(Stone, ITEMINFO_WEIGHT, 9990); // Stone now weighs 999.0
|
|
|
|
---------------------------------------
|
|
|
|
*getitemlink(<item_id>{, <refine = 0>{, <cards_array = 0>{, <options_array = 0>{, <grade = 0>}}}})
|
|
*getitemlink("<item_name>"{, <refine = 0>{, <cards_array = 0>{, <options_array = 0>{, <grade = 0>}}}})
|
|
|
|
Get specially formatted client string that represents an item with the given properties.
|
|
|
|
Parameters:
|
|
- item_id: Item DB id. May be the constant (e.g.: 4001 or Poring_Card)
|
|
- item_name: Item DB name.
|
|
- refine: Item refine amount (optional, defaults to 0)
|
|
- cards_array: An array containing the cards item IDs. (optional, defaults to 0 / no cards)
|
|
- options_array: An array containing option information. (optional, defaults to 0 / no options)
|
|
Structure: <idx1>, <val1>, <param1>, <idx2>, <val2>, <param2>, ... <idx5>, <val5>, <param5>
|
|
- grade: Item grade (optional, defaults to 0)
|
|
|
|
|
|
Example:
|
|
|
|
setarray(.@cards, Fabre_Card, 0, 0, Agility1);
|
|
setarray(.@options,
|
|
VAR_MAXHPAMOUNT, 10, 0, // option 1
|
|
VAR_MAXSPAMOUNT, 20, 0 // option 2
|
|
);
|
|
|
|
// In a recent client, shows something like:
|
|
// Here is my very dangerous item: <+10 Vital Knife [Agi +1]>
|
|
//
|
|
// The text between <> is made by the client and is clickable, showing the item options and grade too.
|
|
dispbottom(sprintf("Here is my very dangerous item: %s", getitemlink(Knife, 10, .@cards, .@options, 3)));
|
|
end;
|
|
|
|
|
|
Client support:
|
|
- PACKETVER_MAIN_NUM < 20150923 and PACKETVER_RE_NUM < 20150819
|
|
Only item name is returned. As pure string.
|
|
- PACKETVER_MAIN_NUM < 20200916, PACKETVER_RE_NUM < 20200723, PACKETVER_ZERO
|
|
Grade is ignored. Returns a clickable text.
|
|
- PACKETVER_MAIN_NUM >= 20200916, PACKETVER_RE_NUM >= 20200723
|
|
Grade is also supported. Returns a clickable text.
|
|
|
|
Note: The clickable text also depends on where it is used. For example, a "mes" will properly format the item name,
|
|
but it won't be clickable. While a "dispbottom" shows it formatted and clickable. This is client-defined.
|
|
|
|
---------------------------------------
|
|
|
|
*getequipisenableopt(<equipment slot>)
|
|
|
|
This function checks if the equipped item allows the use of bonus options.
|
|
|
|
Returns 1 if allowed, 0 if not.
|
|
|
|
---------------------------------------
|
|
|
|
*getequippedoptioninfo(<info_type>);
|
|
|
|
This function is to be used with the scripts of contents listed in
|
|
db/item_options.conf only.
|
|
|
|
Returns the value of the current equipment being parsed.
|
|
If the equip was not found or the type is invalid, -1 is returned.
|
|
|
|
---------------------------------------
|
|
|
|
*getequipoption(<equip_index>,<slot>,<type>);
|
|
|
|
Gets the option information of an equipment.
|
|
|
|
<equipment_index> For a list of equipment indexes see getequipid().
|
|
<option_slot> can range from 1 to MAX_ITEM_OPTIONS
|
|
<type> can be IT_OPT_INDEX (the ID of the option bonus, @see "Id" or "Name" in db/item_options.conf)
|
|
or IT_OPT_VALUE (the value of the bonus script of the equipment, @see "Script" in db_item_options.conf).
|
|
|
|
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.
|
|
|
|
<equipment_index> For a list of equipment indexes see getequipid().
|
|
<option_slot> can range from 1 to MAX_ITEM_OPTIONS
|
|
<type> can be IT_OPT_INDEX (the ID of the option bonus, @see "Id" or "Name" in db/item_options.conf)
|
|
removes the equip option if type is 0.
|
|
<value> The value of the type to be set.
|
|
|
|
returns 0 if value couldn't be set, 1 on success.
|
|
|
|
---------------------------------------
|
|
|
|
*getequipcardid(<equipment slot>, <card 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.
|
|
|
|
---------------------------------------
|
|
|
|
*hateffect(<Hat Effect ID>, <State>)
|
|
|
|
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.
|
|
|
|
Returns -2 if an error happens, -1 if no unidentified <Item ID> was found.
|
|
Otherwise, returns the idx of the identified item.
|
|
|
|
---------------------------------------
|
|
|
|
*identifyidx(<Inventory Index>)
|
|
|
|
This will identify item at attached player's <Inventory Index> inventory index.
|
|
|
|
Returns true if the item was identified, false otherwise.
|
|
Note: If the item was already identified, it returns false.
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
2.1 - End of Item-Related Commands
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
*getmapxy("<variable for map name>", <variable for x>, <variable for y>, <type>{, "<search parameter>"})
|
|
|
|
This function will locate a character object, NPC object or pet's
|
|
coordinates and place their coordinates into the variables specified when
|
|
calling it. It will return 0 if the search was successful, and -1 if the
|
|
parameters given were not variables or the search was not successful.
|
|
|
|
Type is the type of object to search for:
|
|
|
|
UNITTYPE_PC - Character object
|
|
UNITTYPE_NPC - NPC object
|
|
UNITTYPE_PET - Pet object
|
|
UNITTYPE_MOB - Monster object
|
|
UNITTYPE_HOM - Homunculus object
|
|
UNITTYPE_MER - Mercenary object
|
|
UNITTYPE_ELEM - Elemental object
|
|
|
|
To look for a monster object, monster GID is required. The function will
|
|
always return -1 when search using string.
|
|
|
|
The search parameter is optional. If it is not specified, the location of the
|
|
invoking character will always be returned for UNITTYPE_PC, the location of the
|
|
NPC running this function for UNITTYPE_NPC. If a search parameter is specified,
|
|
for UNITTYPE_PC and UNITTYPE_NPC, the character or NPC with the specified name
|
|
or GID will be located.
|
|
|
|
If type is UNITTYPE_PET, UNITTYPE_HOM, UNITTYPE_MER or UNITTYPE_ELEM the search
|
|
will locate the owner's pet/homun/mercenary/elementals if the search parameter
|
|
is not provided. It will NOT locate these object by name, but can be done if GID
|
|
is provided.
|
|
|
|
What a mess. Example, a working and tested one now:
|
|
|
|
prontera,164,301,3%TAB%script%TAB%Meh%TAB%730,{
|
|
mes("My name is Meh. I'm here so that Nyah can find me.");
|
|
close();
|
|
}
|
|
|
|
prontera,164,299,3%TAB%script%TAB%Nyah%TAB%730,{
|
|
mes("My name is Nyah.");
|
|
mes("I will now search for Meh all across the world!");
|
|
if (getmapxy(.@mapname$, .@mapx, .@mapy, 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.
|
|
|
|
---------------------------------------
|
|
|
|
*getmapinfo(<info>{, "<map name>"})
|
|
*getmapinfo(<info>{, <map id>})
|
|
|
|
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.
|
|
|
|
Valid <info> are:
|
|
MAPINFO_NAME name of the map
|
|
MAPINFO_ID numeric ID of the map
|
|
MAPINFO_ZONE name of the zone used by the map
|
|
MAPINFO_SIZE_X width of the map (cells on the x axis)
|
|
MAPINFO_SIZE_Y height of the map (cells on the y axis)
|
|
MAPINFO_NPC_COUNT total number of NPC in the map
|
|
|
|
Examples:
|
|
getmapinfo(MAPINFO_ID, "map name"); // ID from name
|
|
getmapinfo(MAPINFO_NAME, 3); // name from ID
|
|
getmapinfo(MAPINFO_ZONE); // zone, ie Normal, PvP, Jail, ...
|
|
|
|
---------------------------------------
|
|
|
|
*getunits(<type>, <variable>, <limit>{, "<map>"{, <x1>, <y1>, <x2>, <y2>}})
|
|
|
|
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.
|
|
|
|
Type is the type of unit to search for:
|
|
|
|
BL_PC - Character object
|
|
BL_MOB - Monster object
|
|
BL_PET - Pet object
|
|
BL_HOM - Homunculus object
|
|
BL_MER - Mercenary object
|
|
BL_ITEM - Item object (item drops)
|
|
BL_SKILL - Skill object (skill fx & sfx)
|
|
BL_NPC - NPC object
|
|
BL_CHAT - Chat object
|
|
BL_ELEM - Elemental object
|
|
BL_CHAR - Shorthand for (BL_PC|BL_MOB|BL_HOM|BL_MER|BL_ELEM)
|
|
BL_ALL - Any kind of object
|
|
|
|
** Do NOT use UNITTYPE_ constants here, they have different values.
|
|
|
|
** If battle_config.dynamic_mobs is enabled and no player has entered the map
|
|
yet, the mobs will not have spawned in the map yet, so getunits() will be
|
|
unable to find them when searching for BL_MOB.
|
|
|
|
Example:
|
|
|
|
.@count = getunits((BL_PC | BL_NPC), .@units, false, "prontera");
|
|
|
|
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;
|
|
|
|
---------------------------------------
|
|
|
|
*setgroupid(<new group id>{, "<character name>"})
|
|
*setgroupid(<new group id>{, <account id>})
|
|
|
|
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>)
|
|
|
|
Valid types are :
|
|
0 - GETTIMETICK_SYSTEM_MS - server's tick (milliseconds), unsigned int, loops every ~25 days
|
|
1 - GETTIMETICK_HOUROFDAY_S - time since the start of the current day in seconds
|
|
- Note: this only considers the value of the current hour and disregards daylight savings.
|
|
- On the day DST starts and ends, this value will have discontinuties.
|
|
2 - GETTIMETICK_UNIXTIME - UNIX epoch time (number of seconds elapsed since 1st of January 1970)
|
|
|
|
---------------------------------------
|
|
|
|
*gettime(<type>{, <is_localtime>})
|
|
|
|
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.
|
|
|
|
If <is_localtime> is true (or omitted), the output refers to the current timezone and daylight savings.
|
|
Otherwise it is in UTC.
|
|
|
|
It will only return numbers based on types.
|
|
Example :
|
|
if (gettime(GETTIME_WEEKDAY) == SATURDAY) {
|
|
mes("It's a Saturday. I don't work on Saturdays.");
|
|
} else if (gettime(GETTIME_MONTH) == JANUARY) {
|
|
mes("It's January. I don't work on January.");
|
|
} else if (gettime(GETTIME_MONTH) == OCTOBER && gettime(GETTIME_DAYOFMONTH) == 31) {
|
|
mes("It's Halloween.");
|
|
}
|
|
|
|
---------------------------------------
|
|
|
|
*getcalendartime(<hour>, <minute>{, <day of month>{, <day of week>{, <input_is_localtime>}}})
|
|
|
|
This function returns the timestamp of the next occurrence of a given time.
|
|
If this time is later today, it will stay in the same day, otherwise, it will adjust to a future
|
|
day as needed.
|
|
|
|
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.
|
|
|
|
If <input_is_localtime> is true (or omitted), then the hour and minute are interpreted according to the current timezone
|
|
and daylight savings. Otherwise they're treated as UTC.
|
|
|
|
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
|
|
getcalendartime(19, 00, -1, -1, false); // Next 7 pm UTC
|
|
|
|
Note: If supplied with the current hour and minute, you will get the timestamp for the same
|
|
hour and minute in the next day. For example, if is now August 1st 7:00pm and you use:
|
|
getcalendartime(gettime(GETTIME_HOUR), gettime(GETTIME_MINUTE));
|
|
|
|
You will get August 2nd 7pm
|
|
|
|
---------------------------------------
|
|
|
|
*gettimestr(<format string>, <max length>{, <timestamp>})
|
|
|
|
This function will return a string containing time data as specified by
|
|
the format string.
|
|
|
|
This uses the C function 'strftime', which obeys special format
|
|
characters. For a full description see, for example, the description of
|
|
'strftime' at <https://man7.org/linux/man-pages/man3/strftime.3.html>
|
|
All the format characters given in there should properly work.
|
|
Max length is the maximum length of a time string to generate.
|
|
|
|
The example given in Hercules sample scripts works like this:
|
|
|
|
mes(gettimestr("%Y-%m/%d %H:%M:%S", 21));
|
|
mes(gettimestr("%Y-%m/%d %H:%M:%S", 21, getcalendartime(0, 0)));
|
|
|
|
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:
|
|
|
|
0 - Count of all characters on the map of the invoking character.
|
|
1 - Count of all characters in the entire server.
|
|
8 - Count of all characters on the map of the NPC the script is
|
|
running in.
|
|
|
|
---------------------------------------
|
|
|
|
*getmapusers("<map name>")
|
|
|
|
This function will return the number of users currently located on the
|
|
specified map.
|
|
|
|
Currently being used in the PVP scripts to check if a PVP room is full of
|
|
not, if the number returned it equal to the maximum allowed it will not
|
|
let you enter.
|
|
|
|
Return -1 if the map name is invalid.
|
|
|
|
---------------------------------------
|
|
|
|
*getareausers({"<map name>", }{<x1>, <y1>, <x2>, <y2>})
|
|
*getareausers({"<map name>", }{<radius>})
|
|
|
|
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.
|
|
|
|
You need to put a 'close' after that yourself.
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
2.2 - Guild-Related Commands
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
*getguildinfo(<info type>{, <guild id>})
|
|
*getguildinfo(<info type>{, "<guild name>"})
|
|
|
|
This command returns misc info about the guild of the attached player. If a
|
|
guild id or guild name is specified it will be used instead. If the target guild
|
|
does not exist it returns an empty string or -1 depending on whether a string
|
|
or an integer was requested.
|
|
|
|
Valid <info type> are:
|
|
GUILDINFO_NAME - guild name
|
|
GUILDINFO_ID - guild id
|
|
GUILDINFO_LEVEL - current level
|
|
GUILDINFO_EXP - current exp
|
|
GUILDINFO_NEXT_EXP - exp required to reach the next level
|
|
GUILDINFO_SKILL_POINTS - available skill points
|
|
GUILDINFO_ONLINE - number of online members
|
|
GUILDINFO_AV_LEVEL - average member level
|
|
GUILDINFO_MAX_MEMBERS - guild capacity
|
|
GUILDINFO_MASTER_NAME - name of the guild master
|
|
GUILDINFO_MASTER_CID - char id of the guild master
|
|
|
|
Example:
|
|
getguildinfo(GUILDINFO_MASTER_NAME, getcharid(CHAR_ID_GUILD, "Haru"))
|
|
|
|
---------------------------------------
|
|
|
|
*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.conf'.
|
|
|
|
---------------------------------------
|
|
|
|
*getcastledata("<map name>", <type of data>)
|
|
*setcastledata("<map name>", <type of data>, <value>);
|
|
|
|
This function returns the castle ownership information for the castle
|
|
referred to by its map name. Castle information is stored in
|
|
`guild_castle` SQL table.
|
|
|
|
Types of data correspond to `guild_castle` table columns:
|
|
|
|
1 - `guild_id` - Guild ID.
|
|
2 - `economy` - Castle Economy score.
|
|
3 - `defense` - Castle Defense score.
|
|
4 - `triggerE` - Number of times the economy was invested in today.
|
|
5 - `triggerD` - Number of times the defense was invested in today.
|
|
6 - `nextTime` - Unused
|
|
7 - `payTime` - Unused
|
|
8 - `createTime` - Unused
|
|
9 - `visibleC` - Returns 1 if a Kafra was hired for this castle, 0 otherwise.
|
|
10 - `visibleG0` - Returns 1 if the 1st guardian is present (Soldier Guardian)
|
|
11 - `visibleG1` - Returns 1 if the 2nd guardian is present (Soldier Guardian)
|
|
12 - `visibleG2` - Returns 1 if the 3rd guardian is present (Soldier Guardian)
|
|
13 - `visibleG3` - Returns 1 if the 4th guardian is present (Archer Guardian)
|
|
14 - `visibleG4` - Returns 1 if the 5th guardian is present (Archer Guardian)
|
|
15 - `visibleG5` - Returns 1 if the 6th guardian is present (Knight Guardian)
|
|
16 - `visibleG6` - Returns 1 if the 7th guardian is present (Knight Guardian)
|
|
17 - `visibleG7` - Returns 1 if the 8th guardian is present (Knight Guardian)
|
|
|
|
All types of data have their meaning determined by War of Emperium
|
|
scripts, with exception of:
|
|
- `guild_id` that is always the ID of the guild that owns the castle,
|
|
- `defense` that is used in Guardians & Emperium HP calculations,
|
|
- `visibleG` that is always considered to hold guardian presence bits.
|
|
|
|
The setcastledata() command will behave identically, but instead of
|
|
returning values for the specified types of accessible data, it will alter
|
|
them and cause them to be sent to the char-server for storage.
|
|
|
|
Changing Guild ID or Castle Defense will trigger additional actions, like
|
|
recalculating guardians' HP.
|
|
|
|
---------------------------------------
|
|
|
|
*getgdskilllv(<guild id>, <skill id>)
|
|
*getgdskilllv(<guild id>, "<skill name>")
|
|
|
|
This function returns the level of the skill <skill id> of the guild
|
|
<guild id>.
|
|
If the guild does not have that skill, 0 is returned.
|
|
If the guild does not exist, -1 is returned.
|
|
Refer to 'db/(pre-)re/skill_db.conf' for the full list of skills.
|
|
GD_* are guild skills
|
|
|
|
---------------------------------------
|
|
|
|
*requestguildinfo(<guild id>{, "<event label>"});
|
|
|
|
This command requests the guild data from the char server and merrily
|
|
continues with the execution. Whenever the guild information becomes
|
|
available (which happens instantly if the guild information is already in
|
|
memory, or later, if it isn't and the map server has to wait for the char
|
|
server to reply) it will run the specified event as in a 'doevent' call.
|
|
|
|
---------------------------------------
|
|
|
|
*getmapguildusers(<mapname>, <guild id>)
|
|
|
|
Returns the amount of characters from the specified guild on the given map.
|
|
|
|
Example:
|
|
|
|
mes("You have "+getmapguildusers("prontera", getcharid(CHAR_ID_GUILD))+" guild members in Prontera.");
|
|
|
|
---------------------------------------
|
|
|
|
*getguildmember(<guild id>, <type>, <array>);
|
|
|
|
This command will find all members of a specified <guild_id>, copy their
|
|
names (or character id or account id) depending on the <type> into <array>
|
|
and returns the number of guild members that were found.
|
|
|
|
Valid <type> are:
|
|
|
|
GD_MEMBER_NAME - Guild member names
|
|
GD_MEMBER_CHARID - Guild member character ID
|
|
GD_MEMBER_ACCID - Guild member account ID
|
|
|
|
The guild members will be found regardless of whether they are online or offline.
|
|
Note that the results come in no particular order.
|
|
|
|
Make sure to use string variable for GD_MEMBER_NAME and
|
|
int variable for GD_MEMBER_CHARID and GD_MEMBER_ACCID
|
|
|
|
For usage examples, see getpartymember().
|
|
|
|
---------------------------------------
|
|
|
|
*getguildonline(<guild id>{, <type>});
|
|
|
|
Returns the amount of players online in the specified guild id.
|
|
Returns -1 if the guild was not found.
|
|
|
|
Valid <type> are:
|
|
GUILD_ONLINE_ALL Returns the total amount of players online in the guild.
|
|
GUILD_ONLINE_VENDOR Returns the total amount of vendors online in the guild.
|
|
GUILD_ONLINE_NO_VENDOR Returns the total amount of non-vendors online in the guild.
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
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.conf'.
|
|
|
|
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 'db/(pre-)re/skill_db.conf' 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:
|
|
|
|
@skilllist_id[] - skill ids.
|
|
@skilllist_lv[] - skill levels.
|
|
@skilllist_flag[] - see 'skill' for the meaning of skill flags.
|
|
@skilllist_count - number of skills in the above arrays.
|
|
|
|
While 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 "" 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.
|
|
|
|
If the invoking player doesn't own a pet, this command will
|
|
return "" for type PETINFO_NAME, and return 0 for other types.
|
|
|
|
---------------------------------------
|
|
|
|
*getmonsterinfo(<mob ID>, <type>)
|
|
|
|
This function will look up the monster with the specified ID number in the
|
|
mob database and return the info set by TYPE argument.
|
|
It will return -1 if there is no such monster (or the type value is
|
|
invalid), or "null" if you requested the monster's name.
|
|
|
|
Valid types are listed in doc/constants_(pre-)re.md:
|
|
MOB_NAME 0
|
|
MOB_LV 1
|
|
MOB_MAXHP 2
|
|
MOB_BASEEXP 3
|
|
MOB_JOBEXP 4
|
|
MOB_ATK1 5
|
|
MOB_ATK2 6
|
|
MOB_DEF 7
|
|
MOB_MDEF 8
|
|
MOB_STR 9
|
|
MOB_AGI 10
|
|
MOB_VIT 11
|
|
MOB_INT 12
|
|
MOB_DEX 13
|
|
MOB_LUK 14
|
|
MOB_RANGE 15
|
|
MOB_RANGE2 16
|
|
MOB_RANGE3 17
|
|
MOB_SIZE 18
|
|
MOB_RACE 19
|
|
MOB_ELEMENT 20
|
|
MOB_MODE 21
|
|
MOB_MVPEXP 22
|
|
MOB_DMG_TAKEN_RATE 23
|
|
|
|
Check sample in doc/sample/getmonsterinfo.txt
|
|
|
|
---------------------------------------
|
|
|
|
*addmonsterdrop(<mob id or name>, <item id>, <rate>)
|
|
|
|
This command will temporarily add a drop to an existing monster. If the
|
|
monster already drops the specified item, its drop rate will be updated to the
|
|
given value.
|
|
|
|
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);
|
|
|
|
---------------------------------------
|
|
|
|
*delmonsterdrop(<mob id or name>, <item id>)
|
|
|
|
This command will temporarily remove a drop from an existing monster.
|
|
|
|
Both the monster and the item must be valid.
|
|
|
|
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>, <item_id_array>{, <drop_rate_array>});
|
|
|
|
This command will find drops information of the specified <mob_id>, copy the
|
|
item ids on to <item_id_array> and drop rate on to <drop_rate_array> if provided.
|
|
Returns the number of items found. Will return 0 if <mob_id> is invalid.
|
|
|
|
Example:
|
|
// get a Mob ID from the user
|
|
input(.@mob_id);
|
|
|
|
.@count = getmobdrops(.@mob_id, .@item, .@rate);
|
|
|
|
if (.@count == 0) {
|
|
mes("No drops found.");
|
|
} else {
|
|
mes(getmonsterinfo(.@mob_id, MOB_NAME) + " - " + .@count + " drops found:");
|
|
for (.@i = 0; .@i < .@count; ++.@i) {
|
|
mes(.@item[.@i] + " (" + getitemname(.@item[.@i]) + ") " + .@rate[.@i]/100 + ((.@rate[.@i]%100 < 10) ? ".0":".") + .@rate[.@i]%100 + "%");
|
|
}
|
|
}
|
|
close();
|
|
|
|
---------------------------------------
|
|
|
|
*skillpointcount()
|
|
|
|
Returns the total amount of skill points a character possesses
|
|
(SkillPoint + skill points used in skills) This command can be used to
|
|
check the currently attached characters total amount of skill points.
|
|
This means the skill points used in skill are counted, and added to
|
|
SkillPoints (number of skill points not used).
|
|
|
|
Example:
|
|
|
|
//This will set the temp character variable @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 (permanently
|
|
granted) (e.g. ALL_BUYING_STORE/ALL_INCCARRY).
|
|
---------------------------------------
|
|
|
|
*getscrate(<effect type>, <base rate>{, <GID>})
|
|
|
|
This function will return the chance of a status effect affecting the
|
|
invoking character, in percent, modified by the their current defense
|
|
against said status. The 'base rate' is the base chance of the status
|
|
effect being inflicted, in percent.
|
|
|
|
if (rand(100) > getscrate(Eff_Blind, 50)) {
|
|
// do something
|
|
}
|
|
|
|
You can see the full list of available effect types you can possibly
|
|
inflict in 'doc/constants_(pre-)re.md' under 'Status effects'.
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
3 - Checking-Related Commands
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
*playerattached()
|
|
|
|
Returns the ID of the player currently attached to the script. It will
|
|
return 0 if no one is attached, or if the attached player no longer exists
|
|
on the map server. It is wise to check for the attached player in script
|
|
functions that deal with timers as there's no guarantee the player will
|
|
still be logged on when the timer triggers. Note that the ID of a player
|
|
is actually their account ID.
|
|
|
|
---------------------------------------
|
|
|
|
*isloggedin(<account id>{, <char id>})
|
|
|
|
This function returns true if the specified account is logged in and
|
|
false if they aren't. You can also pass the char_id to check for both
|
|
account and char id.
|
|
|
|
---------------------------------------
|
|
|
|
*checkweight(<item id>, <amount>{, <item id>, <amount>, <item id>, <amount>, ...})
|
|
*checkweight("<item name>", <amount>{, "<item name>", <amount>, "<item name>", <amount>, ...})
|
|
*checkweight2(<id_array>, <amount_array>)
|
|
|
|
These functions will compute and return 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.
|
|
|
|
The functions, in addition to checking to see if the player is capable of
|
|
holding a set amount of items, also ensure the player has room in their
|
|
inventory for the item(s) they will be receiving.
|
|
|
|
Like getitem(), this function will also accept an 'english name' from
|
|
the database as an argument.
|
|
|
|
Example 1:
|
|
|
|
if (checkweight(Apple, 10)) {
|
|
getitem(Apple, 10);
|
|
} else {
|
|
mes("Sorry, you cannot hold this amount of apples!");
|
|
}
|
|
|
|
Example 2:
|
|
|
|
setarray(.@item[0], 512, 513, 514);
|
|
setarray(.@amount[0], 10, 5, 5);
|
|
if (!checkweight(.@item, .@amount)) {
|
|
mes("Sorry, you cannot hold this amount of fruit!");
|
|
}
|
|
|
|
---------------------------------------
|
|
|
|
*basicskillcheck()
|
|
|
|
This function will return the state of the configuration option
|
|
'basic_skill_check' in 'conf/map/battle.conf'. Returns true if the
|
|
option is enabled and false if it isn't. If the 'basic_skill_check'
|
|
option is enabled, which it is by default, characters must have a
|
|
certain number of basic skill levels to sit, request a trade, use
|
|
emotions, etc. Making your script behave differently depending on
|
|
whether the characters must actually have the skill to do all these
|
|
things might in some cases be required.
|
|
|
|
---------------------------------------
|
|
|
|
*checkoption(<option number>{, <account id>})
|
|
*checkoption1(<option number>{, <account id>})
|
|
*checkoption2(<option number>{, <account id>})
|
|
*setoption(<option number>{, <flag>{, <account id>}});
|
|
|
|
The setoption() series of functions check for a so-called option that is
|
|
set on the invoking character. 'Options' are used to store status
|
|
conditions and a lot of other non-permanent character data of the yes-no
|
|
kind. For most common cases, it is better to use checkcart(),
|
|
checkfalcon(), checkmount() and other similar functions, but there are
|
|
some options which you cannot get at this way. If <account id> is given,
|
|
this player will be used instead of the invoking character.
|
|
|
|
Option numbers valid for the first (option) version of this command are:
|
|
|
|
0x00000000 Option_Nothing - No options
|
|
0x00000001 Option_Sight - Sight in effect
|
|
0x00000002 Option_Hide - Hide in effect
|
|
0x00000004 Option_Cloak - Cloaking in effect
|
|
0x00000008 - Cart 1
|
|
0x00000010 Option_Falcon - Falcon present
|
|
0x00000020 Option_Riding - Peco Peco present
|
|
0x00000040 Option_Invisible - GM Perfect Hide in effect
|
|
0x00000080 - Cart 2
|
|
0x00000100 - Cart 3
|
|
0x00000200 - Cart 4
|
|
0x00000400 - Cart 5
|
|
0x00000800 Option_Orcish - Orc head present
|
|
0x00001000 Option_Wedding - The character is wearing a wedding costume
|
|
0x00002000 Option_Ruwach - Ruwach is in effect
|
|
0x00004000 Option_Chasewalk - Chasewalk in effect
|
|
0x00008000 Option_Flying - Flying. // Note that clientside Flying and Xmas are 0x8000 for clients prior to 2007.
|
|
0x00010000 Option_Xmas - Xmas costume
|
|
0x00020000 Option_Transform
|
|
0x00040000 Option_Summer - Summer costume
|
|
0x00080000 Option_Dragon1 - Dragon 1
|
|
0x00100000 Option_Wug - Warg present
|
|
0x00200000 Option_Wugrider - The character is riding a Warg
|
|
0x00400000 Option_Madogear - The character is using Madogear
|
|
0x00800000 Option_Dragon2 - Dragon 2
|
|
0x01000000 Option_Dragon3 - Dragon 3
|
|
0x02000000 Option_Dragon4 - Dragon 4
|
|
0x04000000 Option_Dragon5 - Dragon 5
|
|
0x08000000 Option_Hanbok - Hanbok costume
|
|
0x10000000 Option_Oktoberfest - Oktoberfest costume
|
|
0x20000000 Option_Summer2 - Summer 2 costume
|
|
|
|
|
|
There are also compounds status option to check for dragon and costume:
|
|
|
|
- Option_Dragon
|
|
- Option_Costume
|
|
|
|
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)
|
|
7 - Burning
|
|
8 - Imprison
|
|
9 - Crystalize
|
|
|
|
Option numbers valid for the third version (opt2) of this command are:
|
|
|
|
0x0001 - Poison
|
|
0x0002 - Curse
|
|
0x0004 - Silence
|
|
0x0008 - Signum Crucis (plays a howl-like sound effect, but otherwise no
|
|
visible effects are displayed)
|
|
0x0010 - Blind
|
|
0x0020 - Angelus
|
|
0x0040 - Bleeding
|
|
0x0080 - Deadly poison
|
|
0x0100 - Fear
|
|
|
|
Option numbers (except for opt1) are bit-masks - you can add them up to
|
|
check for several states, but the functions will return true if at least
|
|
one of them is in effect.
|
|
|
|
setoption() will set options on the invoking character. There are no
|
|
second and third versions of this command, so you can only change the
|
|
values in the first list (cloak, cart, ruwach, etc). If flag is 1 (default
|
|
when omitted), the option will be added to what the character currently
|
|
has; if 0, the option is removed.
|
|
|
|
---------------------------------------
|
|
|
|
*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>{, <type>}})
|
|
*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.
|
|
|
|
If no flag is specified, the mount is automatically chosen according to the
|
|
character's class and skills.
|
|
|
|
The following flag values are accepted:
|
|
|
|
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.
|
|
|
|
For clients PACKETVER_MAIN_NUM >= 20191120 || PACKETVER_RE_NUM >= 20191106
|
|
you can pass a <type> flag which specifies the madogear wanted.
|
|
The Available types:
|
|
MADO_ROBOT
|
|
MADO_SUITE
|
|
|
|
The accompanying function will return MOUNT_NONE if the invoking
|
|
character is not on a mount, and a non-zero value (according to the
|
|
above constants) if they are.
|
|
Note: in case of dragons, the returned value will always be MOUNT_DRAGON,
|
|
regardless of color.
|
|
|
|
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.
|
|
|
|
---------------------------------------
|
|
|
|
*checkhiding({<account id>};
|
|
|
|
This function returns true if the invoking character is hidden (including
|
|
Hiding, Cloaking and Chase Walk, but excluding GM Perfect Hide) and false
|
|
otherwise.
|
|
|
|
If <account id> is given, this character will be checked instead of the invoking
|
|
character.
|
|
|
|
---------------------------------------
|
|
|
|
*checkvending({"<Player Name>"})
|
|
*checkchatting({"<Player Name>"})
|
|
|
|
Checks if the player is vending or in a chatroom.
|
|
Name is optional, and defaults to the attached player if omitted.
|
|
|
|
Return values for 'checkvending' are
|
|
0 = not vending
|
|
1 = normal vending
|
|
2 = vending using @autotrade
|
|
|
|
checkchatting() returns true if they are in a chat room, false if they are not.
|
|
|
|
Examples:
|
|
//This will check if Aaron is vending, and if so, put a message in
|
|
//front of the attached player saying Aaron is vending.
|
|
if (checkvending("Aaron"))
|
|
mes("Aaron is currently vending!");
|
|
|
|
//This will check if the attached player in a chat room or not.
|
|
if (checkchatting())
|
|
mes("You are currently in a chat room!");
|
|
|
|
---------------------------------------
|
|
|
|
*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 functions 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
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
*isequipped(<item id>{, <item id>{, <item id>{, <item id>}}})
|
|
|
|
This function will return true if the invoking character has all of the item
|
|
IDs given equipped (if item/card IDs are passed, then it checks if the item/card
|
|
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.
|
|
|
|
// (Poring, Santa Poring, Poporing, Marin)
|
|
if (isequipped(Poring_Card, Poring__Card, Poporing_Card, Marin_Card))
|
|
mes("Wow! You're wearing a full complement of possible poring cards!");
|
|
// (Poring)
|
|
if (isequipped(Poring_Card))
|
|
mes("A poring card is useful, don't you think?");
|
|
// (Earring)
|
|
if (isequipped(Earring_))
|
|
mes("You got a pair of nice Earring.");
|
|
|
|
The function was meant for item scripts to support the cards released by
|
|
Gravity in February 2005, but it will work just fine in normal NPC scripts.
|
|
|
|
---------------------------------------
|
|
|
|
*isequippedcnt(<item id>{, <item id>{, <item id>{, <item id>}}})
|
|
|
|
This function is similar to isequipped(), but instead of true or false, it will
|
|
return the number of equipped items/cards in the list given that were found on the
|
|
invoking character.
|
|
|
|
if (isequippedcnt(Poring_Card, Poring__Card, Poporing_Card, Marin_Card) == 4)
|
|
mes("Finally got all four poring cards?");
|
|
if (isequippedcnt(Helm_Of_Sun_, Earring_) == 2)
|
|
mes("You equipped both Helm of Sun and Earring.");
|
|
|
|
---------------------------------------
|
|
|
|
*checkequipedcard(<item id>)
|
|
|
|
This function will return true if the item/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()
|
|
|
|
These commands allow the manipulation of the script's currently attached
|
|
player. While attachrid() allows attaching of a different player by using
|
|
its account id for the parameter rid, detachrid() makes the following
|
|
commands run as if the script was never invoked by a player.
|
|
|
|
In case, that the player cannot be attached, such as, when the player went
|
|
offline in the mean time, attachrid() returns false, otherwise true.
|
|
|
|
---------------------------------------
|
|
|
|
*rid2name(<account id>)
|
|
|
|
Converts rid to name. Note: The player/monster/NPC must be online/enabled.
|
|
Good for PCKillEvent where you can convert 'killedrid' to the name of the
|
|
player.
|
|
|
|
Note: rid2name() may not produce correct character names since RID means
|
|
account id.
|
|
It will return the current online character of the account only.
|
|
|
|
---------------------------------------
|
|
|
|
*message(<account ID>, "<message>")
|
|
*message("<character name>", "<message>")
|
|
|
|
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.
|
|
|
|
---------------------------------------
|
|
|
|
*showscript("<message>"{, <GID>{, <send_target>}})
|
|
|
|
Makes the attached player or GID, display a message similar to a chat,
|
|
this will be seen by everyone near the invoking character but will not
|
|
be displayed in the chat window.
|
|
send_target: (optional)
|
|
AREA: show the message to everyone within the view range (default)
|
|
SELF: show the message to the given unit GID only
|
|
|
|
---------------------------------------
|
|
|
|
*warp("<map name>", <x>, <y>{, <flag>})
|
|
|
|
This command will take the invoking character to the specified map, and if
|
|
wanted, specified coordinates too, but these can be random.
|
|
|
|
warp("place", 50, 55);
|
|
|
|
This would take them to X 50 Y 55 on the map called "place". If your X and
|
|
Y coordinates land on an unwalkable map square, it will send the warped
|
|
character to a random place. Same will happen if they are both zero:
|
|
|
|
warp("place", 0, 0);
|
|
|
|
Notice that while warping people to coordinates 0,0 will normally get them
|
|
into a random place, it's not certain to always be so. Darned if I know
|
|
where this is actually coded, it might be that this happens because square
|
|
0,0 is unwalkable on all official maps. Beware if you're using custom maps.
|
|
|
|
There are also three special 'map names' you can use:
|
|
|
|
"Random" will warp the player randomly on the current map.
|
|
"Save" and "SavePoint" will warp the player back to their save point.
|
|
|
|
If flag parameter is set to 0, after player warped will be not stopped
|
|
current running npc script. Running script after warp can be issue for
|
|
Gravity client if warp to other maps.
|
|
|
|
---------------------------------------
|
|
|
|
*areawarp("<from map name>", <x1>, <y1>, <x2>, <y2>, "<to map name>", <x3>, <y3>{, <x4>, <y4>})
|
|
|
|
This command is similar to 'warp', however, it will not refer to the
|
|
invoking character, but instead, all characters within a specified area,
|
|
defined by the x1/y1-x2/y2 square, will be warped. Nobody outside the area
|
|
will be affected, including the activating character, if they are outside
|
|
the area.
|
|
|
|
areawarp("place", 10, 10, 120, 120, "place2", 150, 150);
|
|
|
|
Everyone that is in the area between X 10 Y 10 and X 120 Y 120, in a
|
|
square shape, on the map called "place", will be affected, and warped to
|
|
"place2" X 150 Y 150.
|
|
|
|
areawarp("place", 10, 10, 120, 120, "place2", 0, 0);
|
|
|
|
By using 0,0; as the destination coordinates it will take all the
|
|
characters in the affected area to a random set of co-ordinates on the
|
|
"place2" map.
|
|
|
|
areawarp("place", 10, 10, 120, 120, "place2", 150, 150, 200, 200);
|
|
|
|
By using the optional x4 and y4 parameters, the destination coordinates
|
|
will be a random place within the defined x3/y3-x4/y4 square.
|
|
|
|
Like warp(), areawarp() will also explicitly warp characters randomly into
|
|
the current map if you give the 'to map name' as "Random".
|
|
|
|
See also warp().
|
|
|
|
---------------------------------------
|
|
|
|
*warpparty("<to map name>", <x>, <y>, <party id>{{, <ignore mapflags>}, "<from map name>"{, <include leader>}})
|
|
|
|
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 <to map name> for special warping behavior:
|
|
Random: All party members are randomly warped in their current map
|
|
(as if they all used a fly wing).
|
|
SavePointAll: All party members are warped to their respective save point.
|
|
SavePoint: All party members are warped to the save point of the
|
|
currently attached player (will fail if there's no player
|
|
attached).
|
|
Leader: All party members are warped to the leader's position. The
|
|
leader must be online and in the current map-server for
|
|
this to work.
|
|
|
|
If <ignore mapflags> is not 0, warpparty() ignores nowarp/noreturn restrictions
|
|
of the warped character's current map. <ignore mapflags> defaults to 0.
|
|
|
|
If you specify a <from map name>, warpparty() will only affect those on that map.
|
|
|
|
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();
|
|
|
|
---------------------------------------
|
|
|
|
*warpchar("<mapname>", <x>, <y>, <char_id>)
|
|
|
|
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:
|
|
|
|
warpchar("prontera", 150, 100, 150001);
|
|
|
|
---------------------------------------
|
|
|
|
*warpguild("<to map name>", <x>, <y>, <guild id>{{, <ignore mapflags>}, "<from map name>"})
|
|
|
|
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 <to map name> 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 <ignore mapflags> is not 0, warpguild() ignores nowarp/noreturn restrictions
|
|
of the warped character's current map. <ignore mapflags> defaults to 0.
|
|
|
|
If you specify a <from map name>, warpguild() will only affect those on that map.
|
|
|
|
Example:
|
|
|
|
warpguild("prontera", x, y, Guild_ID); // Warp all guild members to Prontera,
|
|
// but check nowarp/noreturn restriction of their current map.
|
|
warpguild("prontera", x, y, Guild_ID, 1); // Warp all guild members to Prontera.
|
|
warpguild("prontera", x, y, Guild_ID, "payon"); // Warp guild members from Payon to Prontera,
|
|
// but check nowarp/noreturn restriction of Payon.
|
|
warpguild("prontera", x, y, Guild_ID, 1, "payon"); // Warp guild members from Payon to Prontera.
|
|
|
|
---------------------------------------
|
|
|
|
*warppartner("<map name>", <x>, <y>)
|
|
|
|
This function will find the invoking character's marriage partner, if any,
|
|
and warp them to the map and coordinates given. Go kidnap that spouse. :)
|
|
It will return 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.
|
|
|
|
---------------------------------------
|
|
|
|
*savepoint("<map name>", <x>, <y>)
|
|
|
|
This command saves where the invoking character will return to upon
|
|
'return to save point', if dead or in some other cases. The two versions
|
|
are equivalent. Map name, X coordinate and Y coordinate should be
|
|
perfectly obvious. This ignores any and all map flags, and can make a
|
|
character respawn where no teleportation is otherwise possible.
|
|
|
|
savepoint("place", 350, 75);
|
|
|
|
---------------------------------------
|
|
|
|
*heal(<hp>, <sp>)
|
|
|
|
This command will heal a set amount of HP and/or SP on the invoking
|
|
character.
|
|
|
|
heal(30000, 0) // This will heal 30,000 HP
|
|
heal(0, 30000) // This will heal 30,000 SP
|
|
heal(300, 300) // This will heal 300 HP and 300 SP
|
|
|
|
This command just alters the hit points and spell points of the invoking
|
|
character and produces no other output whatsoever.
|
|
|
|
---------------------------------------
|
|
|
|
*itemheal(<hp>, <sp>)
|
|
|
|
This command heals given relative amounts of HP and/or SP on the invoking
|
|
character. Unlike heal, this command is intended for use in item scripts.
|
|
It applies potion-related bonuses, such as alchemist ranking, cards,
|
|
status changes.
|
|
It also applies a sp/vit-related bonus that is calculated by:
|
|
heal = heal*[(100+STATUS*2)/100]
|
|
So if a player has 99 vit and the script is 'itemheal 5, 0':
|
|
heal(hp) = 5*[(100+99*2)/100]
|
|
heal(hp) = 14.9
|
|
heal(hp) = 14
|
|
heal(sp) = 0
|
|
|
|
When used inside an NPC script, potion-related bonuses are omitted.
|
|
|
|
There is also a nice example on using this with the rand() function, to
|
|
give you a random amount of healing.
|
|
|
|
// If the player has 50 vit and no bonuses this will heal
|
|
// anything from 200 to 300 HP and 5 SP
|
|
itemheal(rand(100, 150), 5);
|
|
|
|
---------------------------------------
|
|
|
|
*percentheal(<hp>, <sp>)
|
|
|
|
This command will heal the invoking character. It heals the character, but
|
|
not by a set value - it adds percent of their maximum HP/SP.
|
|
|
|
percentheal(100, 0); // This will heal 100% HP
|
|
percentheal(0, 100); // This will heal 100% SP
|
|
percentheal(50, 50); // This will heal 50% HP and 50% SP
|
|
|
|
So the amount that this will heal will depend on the total amount of HP or
|
|
SP you have maximum. Like heal(), this will not call up any animations or
|
|
effects.
|
|
|
|
---------------------------------------
|
|
|
|
*recovery({<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.
|
|
|
|
---------------------------------------
|
|
|
|
*jobchange(<job number>{, <upper flag>})
|
|
|
|
This command will change the job class of the invoking character.
|
|
|
|
jobchange(Job_Swordman); // This would change your player into a Swordman
|
|
jobchange(Job_Swordman_High); // This would change your player into a Swordman High
|
|
|
|
This command does work with numbers, but you can also use job names. The
|
|
full list of job names and the numbers they correspond to can be found in
|
|
'doc/constants_(pre-)re.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
|
|
|
|
This command will also set a permanent character-based variable
|
|
'jobchange_level' which will contain the job level at the time right
|
|
before changing jobs, which can be checked for later in scripts.
|
|
|
|
---------------------------------------
|
|
|
|
*jobname(<job number>)
|
|
|
|
This command retrieves the name of the given job using the 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>})
|
|
|
|
This commands returns the "eA job-number" corresponding to the given
|
|
class, and uses the invoking player's class if none is given. The eA
|
|
job-number is also a class number system, but it's one that comes with
|
|
constants which make it easy to convert among classes. The command will
|
|
return -1 if you pass it a job number which doesn't have an eA job-number
|
|
equivalent.
|
|
|
|
.@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.");
|
|
|
|
For more information on the eA Job System, see the docs/ea_job_system.txt
|
|
file.
|
|
|
|
---------------------------------------
|
|
*roclass(<job number> {, <gender>})
|
|
|
|
Does the opposite of eaclass(). That is, given an eA job-number, it returns
|
|
the corresponding RO class number. A gender is required because both Bard
|
|
and Dancers share the same eA job-number (EAJ_BARDDANCER), and uses the
|
|
invoking player's gender if none is given (if no player is attached,
|
|
male will be used by default). The command will return -1 if there is no
|
|
valid class to represent the specified job (for example, if you try to get
|
|
the baby version of a Taekwon class).
|
|
|
|
.@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:
|
|
|
|
/* This example is an item script in the item db */
|
|
{
|
|
Id: 2338
|
|
AegisName: "Wedding_Dress"
|
|
Name: "Wedding Dress"
|
|
Type: 5
|
|
Buy: 43000
|
|
Weight: 500
|
|
Job: 0xFFFFFFFE
|
|
Loc: 16
|
|
Script: <"
|
|
bonus(bMdef, 15);
|
|
changebase(Job_Wedding);
|
|
">
|
|
},
|
|
|
|
changebase(Job_Novice); // Changes player to Novice sprite.
|
|
|
|
changebase(Class); // Changes player back to default sprite.
|
|
|
|
---------------------------------------
|
|
|
|
*classchange(<view id>, <type> {, <char id>})
|
|
|
|
This command is very ancient, it's origins are clouded in mystery.
|
|
It will send a 'display id change' packet to player with given char ID
|
|
or to everyone in the immediate area of the NPC object if char ID is 0 or
|
|
not passed, which will make the NPC look like a different sprite, an NPC
|
|
sprite ID, or a monster ID. This effect is not stored anywhere and will
|
|
not persist.
|
|
Note that you can't send a Job sprite ID
|
|
|
|
type is not used and should always be 0.
|
|
|
|
---------------------------------------
|
|
|
|
*changesex()
|
|
|
|
This command will change the gender for the attached character's account.
|
|
If it was male, it will become female, if it was female, it will become
|
|
male. The change will be written to the character server, the player will
|
|
receive the message: "Need disconnection to perform change-sex request..."
|
|
and the player will be immediately kicked to the login screen. When they
|
|
log back in, they will be the opposite sex.
|
|
|
|
If there are any Dancer/Gypsy or Bard/Clown characters on the account,
|
|
they will also have their skills reset upon 'changesex'.
|
|
|
|
---------------------------------------
|
|
|
|
*changecharsex()
|
|
|
|
This command is exactly same as changesex(), with an exception that,
|
|
character sex will be changed instead of account sex.
|
|
Requires client 2014-10-22 or greater.
|
|
|
|
---------------------------------------
|
|
|
|
*getexp(<base xp>, <job xp>)
|
|
|
|
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);
|
|
|
|
You can also assign directly to the parameters defined in
|
|
'doc/constants_(pre-)re.md':
|
|
|
|
BaseExp += 10000;
|
|
JobExp += 5000;
|
|
|
|
You can also reduce the amount of experience points:
|
|
|
|
BaseExp -= 10000;
|
|
|
|
When setting the parameters directly no bonuses or config options are applied.
|
|
|
|
---------------------------------------
|
|
|
|
*setlook(<look type>, <look value>)
|
|
*changelook(<look type>, <look value>)
|
|
|
|
'setlook' will alter the look data for the invoking character. It is used
|
|
mainly for changing the palette used on hair and clothes: you specify
|
|
which look type you want to change, then the palette you want to use. Make
|
|
sure you specify a palette number that exists/is usable by the client you
|
|
use. 'changelook' works the same, but is only client side (it doesn't save
|
|
the look value).
|
|
|
|
// This will change your hair(6), so that it uses palette 8, what ever
|
|
// your palette 8 is, your hair will use that color.
|
|
|
|
setlook(LOOK_HAIR_COLOR, 8);
|
|
|
|
// This will change your clothes(7), so they are using palette 1,
|
|
// whatever your palette 1 is, your clothes will then use that set of
|
|
// colors.
|
|
|
|
setlook(LOOK_CLOTHES_COLOR, 1);
|
|
|
|
Here are the possible look types:
|
|
|
|
0 - LOOK_BASE Base sprite
|
|
1 - LOOK_HAIR Hairstyle
|
|
2 - LOOK_WEAPON Weapon
|
|
3 - LOOK_HEAD_BOTTOM Head bottom
|
|
4 - LOOK_HEAD_TOP Head top
|
|
5 - LOOK_HEAD_MID Head mid
|
|
6 - LOOK_HAIR_COLOR Hair color
|
|
7 - LOOK_CLOTHES_COLOR Clothes color
|
|
8 - LOOK_SHIELD Shield
|
|
9 - LOOK_SHOES Shoes
|
|
10 - LOOK_BODY Body(N/A)
|
|
11 - LOOK_FLOOR FLOOR(N/A)
|
|
12 - LOOK_ROBE Robe
|
|
13 - LOOK_BODY2 Body style
|
|
|
|
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_(pre-)re.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.
|
|
|
|
// pushes the character 5 cells in 3 o'clock direction from it's
|
|
// current position.
|
|
pushpc(DIR_EAST, 5);
|
|
|
|
---------------------------------------
|
|
|
|
*montransform(<monster id>, <duration>{, <sc_type>{, <val1>{, <val2>{, <val3>{, <val4>}}}}})
|
|
*montransform("<monster name>", <duration>{, <sc_type>{, <val1>{, <val2>{, <val3>{, <val4>}}}}})
|
|
*active_transform(<monster id>, <duration>{, <sc_type>{, <val1>{, <val2>{, <val3>{, <val4>}}}}})
|
|
*active_transform("<monster name>", <duration>{, <sc_type>{, <val1>{, <val2>{, <val3>{, <val4>}}}}})
|
|
|
|
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 you die or if duration is over.
|
|
|
|
active_transform works in the same way but it stacks with montransform, and is displayed first.
|
|
This means that you may have a montransform, that effect and an active_transform effect at
|
|
the same time, and the monster from active_transform will show first, once it ends, your appearance
|
|
changes back to the montransform one, if it is still active.
|
|
|
|
for sc_type, val1, val2, val3, val4, see sc_start(), sc_start2(), sc_start4() commands.
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
4.1 - Player Item-Related Commands
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
*getitem(<item id>, <amount>{, <account ID>})
|
|
*getitem("<item name>", <amount>{, <account ID>})
|
|
|
|
This command will give a specific amount of specified items to the target
|
|
character. If the character is not online, nothing will happen.
|
|
If <account ID> is not specified, items will be created in the invoking
|
|
character inventory instead.
|
|
|
|
In the first and most commonly used version of this command, items are
|
|
referred to by their database ID number found in 'db/(pre-)re/item_db.conf'.
|
|
|
|
getitem(Apple, 10); // The person will receive 10 apples
|
|
getitem(Old_Violet_Box, 1); // The person will receive 1 Old Violet Box
|
|
|
|
Giving an item ID of -1 will give a specified number of random items from
|
|
the list of those that fall out of Old Blue Box. Unlike in all other
|
|
cases, these will be unidentified, if they turn out to be equipment. This
|
|
is exactly what's written in the Old Blue Box's item script.
|
|
|
|
Other negative IDs also correspond to other random item generating item
|
|
tables:
|
|
|
|
Giving an item ID of -2 will produce the effects of Old Violet Box.
|
|
Giving an item ID of -3 will produce the effects of Old Card Album.
|
|
Giving an item ID of -4 will produce the effects of Gift Box.
|
|
Giving an item ID of -5 will produce the effects of Worn Out Scroll,
|
|
which, in current Git, drops only Jellopies anyway.
|
|
|
|
This transaction is logged if the log script generated transactions option
|
|
is enabled.
|
|
|
|
You may also create an item by it's name in the 'english name' field in
|
|
the item database:
|
|
|
|
getitem("Red_Potion", 10); // Not recommended, use Red_Potion instead of "Red_Potion"
|
|
|
|
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.
|
|
|
|
---------------------------------------
|
|
|
|
*getitem2(<item id>, <amount>, <identify>, <refine>, <attribute>, <card1>, <card2>, <card3>, <card4>{, <account ID>})
|
|
*getitem2("<item name>", <amount>, <identify>, <refine>, <attribute>, <card1>, <card2>, <card3>, <card4>{, <account ID>})
|
|
|
|
This command will give an amount of specified items to the invoking
|
|
character. If an optional account ID is specified, and the target
|
|
character is currently online, items will be created in their inventory
|
|
instead. If they are not online, nothing will happen. It works essentially
|
|
the same as 'getitem' (it even works for negative ID numbers the same way)
|
|
but is a lot more flexible.
|
|
|
|
Those parameters that are different from getitem() are:
|
|
|
|
identify - Whether you want the item to be identified (1) or not (0).
|
|
refine - For how many pluses will it be refined. It will not let you
|
|
refine an item higher than the max refine.
|
|
attribute - Whether the item is broken (1) or not (0).
|
|
card1,2,3,4 - If you want a card compound to it, place the card ID number
|
|
into the specific card slot.
|
|
|
|
Card1-card4 values are also used to store name information for named
|
|
items, as well as the elemental property of weapons and armor. You can
|
|
create a named item in this manner, however, if you just need a named
|
|
piece of standard equipment, it is much easier to the 'getnameditem'
|
|
function instead.
|
|
|
|
You will need to keep these values if you want to destroy and then
|
|
perfectly recreate a named item, for this see getinventorylist().
|
|
|
|
If you still want to try creating a named item with this command because
|
|
'getnameditem' won't do it for you cause it's too limited, you can do it
|
|
like this. Careful, minor magic ahead.
|
|
|
|
// First, let's get an ID of a character who's name will be on the
|
|
// item. Only an existing character's name may be there.
|
|
// Let's assume our character is 'Adam' and find his ID.
|
|
|
|
.@charid = getcharid(CHAR_ID_CHAR, "Adam");
|
|
|
|
// Now we split the character ID number into two portions with a
|
|
// binary shift operation. If you don't understand what this does,
|
|
// just copy it.
|
|
|
|
.@card3 = .@charid & 65535;
|
|
.@card4 = .@charid >> 16;
|
|
|
|
// If you're inscribing non-equipment, .@card1 must be 254.
|
|
// Arrows are also not equipment. :)
|
|
.@card1 = 254;
|
|
|
|
// 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:
|
|
|
|
getitem2(Apple, 1, 1, 0, 0, .@card1, .@card2, .@card3, .@card4);
|
|
|
|
This wasn't tested with all possible items, so I can't give any promises,
|
|
experiment first before relying on it.
|
|
|
|
To create equipment, continue this example it like this:
|
|
|
|
// We've already have card3 and card4 loaded with correct
|
|
// values so we'll just set up card1 and card2 with data
|
|
// for an Ice Stiletto.
|
|
|
|
// If you're inscribing equipment, .@card1 must be 255.
|
|
.@card1 = 255;
|
|
|
|
// That's the number of star crumbs in a weapon.
|
|
.@sc = 2;
|
|
|
|
// That's the number of elemental property of the weapon.
|
|
.@ele = 1;
|
|
|
|
// And that's the wacky formula that makes them into
|
|
// a single number.
|
|
.@card2 = .@ele+((.@sc*5)<<8);
|
|
|
|
// That will make us an Adam's +2 VVS Ice Stiletto:
|
|
|
|
getitem2(Stiletto, 1, 1, 2, 0, .@card1, .@card2, .@card3, .@card4);
|
|
|
|
Experiment with the number of star crumbs - I'm not certain just how much
|
|
will work most and what it depends on. The valid element numbers are:
|
|
|
|
1 - Ice, 2 - Earth 3 - Fire 4 - Wind.
|
|
|
|
You can, apparently, even create duplicates of the same pet egg with this
|
|
command, creating a pet which is the same, but simultaneously exists in
|
|
two eggs, and may hatch from either, although, I'm not sure what kind of a
|
|
mess will this really cause.
|
|
|
|
---------------------------------------
|
|
*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.
|
|
|
|
Valid item bound types are:
|
|
1 - IBT_ACCOUNT - Account Bound
|
|
2 - IBT_GUILD - Guild Bound
|
|
3 - IBT_PARTY - Party Bound
|
|
4 - IBT_CHARACTER - Character Bound
|
|
|
|
---------------------------------------
|
|
|
|
*getitembound2(<item id>, <amount>, <identify>, <refine>, <attribute>, <card1>, <card2>, <card3>, <card4>, <bound type>)
|
|
*getitembound2("<item name>", <amount>, <identify>, <refine>, <attribute>, <card1>, <card2>, <card3>, <card4>, <bound type>)
|
|
|
|
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.
|
|
|
|
For a list of bound types see getitembound().
|
|
|
|
---------------------------------------
|
|
|
|
*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.
|
|
|
|
For a list of bound types see 'getitembound'.
|
|
|
|
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();
|
|
|
|
---------------------------------------
|
|
|
|
*checkbound(<item_id>{, <bound_type>{, <refine>{, <attribute>{, <card_1>{, <card_2>{, <card_3>{, <card_4>}}}}}}})
|
|
|
|
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.
|
|
|
|
Valid item bound types are:
|
|
0 - IBT_ANY - Any Bound
|
|
1 - IBT_ACCOUNT - Account Bound
|
|
2 - IBT_GUILD - Guild Bound
|
|
3 - IBT_PARTY - Party Bound
|
|
4 - IBT_CHARACTER - Character Bound
|
|
|
|
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, IBT_ANY)) {
|
|
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 IBT_GUILD
|
|
if (checkbound(Cutter) == IBT_GUILD) {
|
|
mes("You have a guild_bound Cutter");
|
|
} else {
|
|
mes("You do not have a guild_bound Cutter.");
|
|
}
|
|
close();
|
|
|
|
// This will check if you have a 'guild_bound' +7 1205 (Cutter).
|
|
if (checkbound(Cutter, IBT_GUILD, 7)) {
|
|
mes("You have a +7 guild_bound Cutter.");
|
|
} else {
|
|
mes("You don't have the required item.");
|
|
}
|
|
close();
|
|
---------------------------------------
|
|
|
|
*getnameditem(<item id>, "<character name>")
|
|
*getnameditem(<item id>, <character ID>)
|
|
*getnameditem("<item name>", "<character name>")
|
|
*getnameditem("<item name>", <character ID>)
|
|
|
|
Create an item signed with the given character's name.
|
|
|
|
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!");
|
|
}
|
|
|
|
---------------------------------------
|
|
|
|
*rentitem(<item id>, <time>)
|
|
*rentitem("<item name>", <time>)
|
|
|
|
Creates a rental item in the attached character's inventory. The item will
|
|
expire in <time> seconds and be automatically deleted. When receiving a
|
|
rental item, the character will receive a message in their chat window.
|
|
The character will also receive warning messages in their chat window
|
|
before the item disappears.
|
|
|
|
This command can not be used to rent stackable items. Rental items cannot
|
|
be dropped, traded, sold to NPCs, or placed in guild storage (i.e. trade
|
|
mask 75).
|
|
Note: delitem() in an NPC script can still remove rental items.
|
|
|
|
---------------------------------------
|
|
|
|
*makeitem(<item id>, <amount>, "<map name>", <x>, <y> {,<showdropeffect>})
|
|
*makeitem("<item name>", <amount>, "<map name>", <x>, <y>)
|
|
|
|
This command will create an item lying around on a specified map in the
|
|
specified location.
|
|
|
|
item id/name - Found in 'db/(pre-)re/item_db.conf'
|
|
amount - Amount you want produced
|
|
map name - The map name
|
|
y - The x coordinate
|
|
y - The y coordinate.
|
|
showdropeffect - enable pillar effect on the dropped item (default: 0)
|
|
|
|
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 script 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
|
|
|
|
Optional Parameter List:
|
|
map name - Map name (Default to attached player map)
|
|
X,Y - The coordinate of item will be dropped
|
|
If value = 0, it's drop random across the map
|
|
If value = -1, its drop around player
|
|
range - Range of item drop around player. (Value: 1 ~ battle_config.area_size, Default: 3)
|
|
Default value will be used if no player are attached to the script.
|
|
|
|
---------------------------------------
|
|
|
|
*cleanarea("<map name>",<x1>,<y1>,<x2>,<y2>)
|
|
*cleanmap("<map name>")
|
|
|
|
These commands will clear all items lying on the ground on the specified
|
|
map, either within the x1/y1-x2/y2 rectangle or across the entire map.
|
|
|
|
---------------------------------------
|
|
|
|
*searchitem(<array name>, "<item name>")
|
|
|
|
This command will fill the given array with the ID of items whose name
|
|
matches the given one. It returns the number of items found. For
|
|
performance reasons, the results array is limited to 10 items.
|
|
|
|
mes("What item are you looking for?");
|
|
input(.@name$);
|
|
.@qty = searchitem(.@matches[0], .@name$);
|
|
mes("I found "+.@qty+" items:");
|
|
for (.@i = 0; .@i < .@qty; ++.@i)
|
|
//Display name (eg: "Apple[0]")
|
|
mes(getitemname(.@matches[.@i])+"["+getitemslots(.@matches[.@i])+"]");
|
|
|
|
---------------------------------------
|
|
|
|
*delitem(<item id>, <amount>{, <account ID>})
|
|
*delitem("<item name>", <amount>{, <account ID>})
|
|
|
|
This command will 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.conf'.
|
|
|
|
delitem(Apple, 10); // The person will lose 10 apples
|
|
delitem(Old_Violet_Box, 1); // The person will lose 1 Old Violet Box
|
|
|
|
It is always a good idea to check if the player actually has the items
|
|
before you delete them. If you try to delete more items that the player
|
|
has, the player will lose the ones he/she has and the script will be
|
|
terminated with an error.
|
|
|
|
Like getitem() this command will also accept an 'english name' field from
|
|
the database. If the name is not found, nothing will be deleted.
|
|
|
|
---------------------------------------
|
|
|
|
*delitem2(<item id>, <amount>, <identify>, <refine>, <attribute>, <card1>, <card2>, <card3>, <card4>{, <account ID>})
|
|
*delitem2("<item name>", <amount>, <identify>, <refine>, <attribute>, <card1>, <card2>, <card3>, <card4>{, <account ID>})
|
|
|
|
This command will remove a specified amount of items from the invoking or
|
|
target character.
|
|
Check getitem2() to understand its expanded parameters.
|
|
|
|
---------------------------------------
|
|
|
|
*delitemidx(<index>{, <amount>{, <account id>}})
|
|
|
|
This command will remove an item at the given inventory index. Unlike the
|
|
'delitem()' counterpart, this doesn't check invalid Item ID, making it useful to remove
|
|
invalid item IDs in player's inventory.
|
|
|
|
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.
|
|
|
|
This command is also useful to remove rental/bound items because 'delitem()'
|
|
does not discriminate at choosing which item to remove.
|
|
|
|
Example:
|
|
|
|
// This will remove all invalid Item ID in player's inventory
|
|
getinventorylist();
|
|
for (.@i = 0; .@i < @inventorylist_count; ++.@i)
|
|
if (getiteminfo(@inventorylist_id[.@i], ITEMINFO_TYPE) == -1)
|
|
delitemidx(@inventorylist_idx[.@i]);
|
|
|
|
---------------------------------------
|
|
|
|
*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.
|
|
|
|
---------------------------------------
|
|
|
|
*countitem2(<item id>, <identify>, <refine>, <attribute>, <card1>, <card2>, <card3>, <card4>)
|
|
*countitem2("<item name>", <identify>, <refine>, <attribute>, <card1>, <card2>, <card3>, <card4>)
|
|
|
|
Expanded version of countitem() function, used for created/carded/forged
|
|
items.
|
|
|
|
This function will return the number of items for the specified item ID
|
|
and other parameters that the invoking character has in the inventory.
|
|
Check getitem2() to understand the arguments of the function.
|
|
|
|
---------------------------------------
|
|
|
|
*countnameditem(<item id>, "<character name>")
|
|
*countnameditem(<item id>, <character ID>)
|
|
*countnameditem("<item name>", "<character name>")
|
|
*countnameditem("<item name>", <character ID>)
|
|
|
|
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);
|
|
|
|
---------------------------------------
|
|
|
|
*getrandgroupitem(<item id>, <quantity>)
|
|
|
|
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:
|
|
|
|
/* This example is an item script from the item db */
|
|
{
|
|
Id: 12477
|
|
AegisName: "Gift_Bundle"
|
|
Name: "Gift Bundle"
|
|
Type: 2
|
|
Buy: 0
|
|
Script: <" packageitem(); ">
|
|
},
|
|
|
|
---------------------------------------
|
|
|
|
*enable_items({<flag>})
|
|
*enableitemuse({<flag>})
|
|
*disable_items({<flag>})
|
|
*disableitemuse({<flag>})
|
|
|
|
These commands enable/disable item actions while interacting with a NPC.
|
|
When disable_items() is invoked, item actions defined by <flag> are disabled
|
|
during scripts until enable_items() is called or the script has terminated.
|
|
To avoid possible exploits, when disable_items() is invoked, it will only
|
|
disable item actions while running that script in particular.
|
|
Note that if a different script also invokes disable_items(), it will override
|
|
the last call so you may want to call this command at the start of your
|
|
script without assuming the effect is still in effect.
|
|
If <flag> is omitted all item actions will be disabled.
|
|
The enable_items() command enables item actions defined by <flag> during
|
|
scripts until disable_items() is invoked or the script has terminated.
|
|
If <flag> is omitted it defaults to 'item_enabled_npc' battle flag.
|
|
For a list of supported flags have a look at the description of
|
|
'item_enabled_npc' battle flag in 'conf/map/battle/items.conf'.
|
|
Unless disable_items() or enable_items() is invoked the script will use
|
|
'item_enabled_npc' battle flag by default.
|
|
|
|
Example:
|
|
|
|
// This will disable changing equipment during this script.
|
|
disable_items(ITEMENABLEDNPC_EQUIP);
|
|
|
|
---------------------------------------
|
|
|
|
*itemskill(<skill id>, <skill level>{, <flag>})
|
|
*itemskill("<skill name>", <skill level>{, <flag>})
|
|
|
|
This command meant for item scripts to replicate single-use skills in
|
|
usable items. It will not work properly if there is a visible dialog
|
|
window or menu.
|
|
If the skill is self or auto-targeting, it will be used immediately.
|
|
Otherwise, a target cursor is shown.
|
|
By default, all skill requirements are ignored.
|
|
Optional argument <flag> is a bitmask to manipulate how the skill is cast.
|
|
Since <flag> is a bitmask, the flags can be summed up.
|
|
Possible flags are:
|
|
- 0x00 - ISF_NONE - Skill is cast as if it has been used from skill tree.
|
|
(Same like <flag> was omitted.)
|
|
- 0x01 - ISF_CHECKCONDITIONS - Skill requirements are checked and consumed.
|
|
(SP are never checked/consumed.)
|
|
- 0x02 - ISF_INSTANTCAST - Skill is cast instantaneously.
|
|
- 0x04 - ISF_CASTONSELF - Skill is forcefully cast on invoking character,
|
|
without showing the target selection cursor.
|
|
|
|
Important: Items which use itemskill() should be of type IT_USABLE.
|
|
If the item type is IT_DELAYCONSUME and ISF_CHECKCONDITIONS isn't set,
|
|
the item won't be consumed when using the item!
|
|
|
|
// 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);
|
|
|
|
// Instantaneously cast Level 10 Increase Agility on invoking character,
|
|
// with checking/consuming skill requirements (15 HP).
|
|
itemskill(AL_INCAGI, 10, ISF_CHECKCONDITIONS | ISF_INSTANTCAST | ISF_CASTONSELF);
|
|
// Instead of using the constants, one could also do it like this:
|
|
itemskill(AL_INCAGI, 10, 7);
|
|
|
|
---------------------------------------
|
|
|
|
*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%.
|
|
|
|
Valid item levels are:
|
|
|
|
1 - Level 1 Weapons
|
|
2 - Level 2 Weapons
|
|
3 - Level 3 Weapons
|
|
21 - Blacksmith's Stones and Metals
|
|
22 - Alchemist's Potions, Holy Water, Assassin Cross's Deadly Poison
|
|
23 - Elemental Converters
|
|
|
|
---------------------------------------
|
|
|
|
*cooking(<dish level>)
|
|
|
|
This command will open a produce window on the client connected to the
|
|
invoking character. The 'dish level' is the number which determines what
|
|
kind of dish level you can produce. You can see the full list of dishes
|
|
that can be produced in 'db/produce_db.txt'.
|
|
|
|
The window will be shown empty if the invoking character does not have
|
|
enough of the required ingredients to cook a dish.
|
|
|
|
Valid dish levels are:
|
|
|
|
11 - Level 1 Dish
|
|
12 - Level 2 Dish
|
|
13 - Level 3 Dish
|
|
14 - Level 4 Dish
|
|
15 - Level 5 Dish
|
|
16 - Level 6 Dish
|
|
17 - Level 7 Dish
|
|
18 - Level 8 Dish
|
|
19 - Level 9 Dish
|
|
20 - Level 10 Dish
|
|
|
|
Although it's required to set a dish level, it doesn't matter if you set
|
|
it to 1 and you want to cook a level 10 dish, as long as you got the
|
|
required ingredients to cook the dish the command works.
|
|
|
|
---------------------------------------
|
|
|
|
*makerune(<% success bonus>)
|
|
|
|
This command will open a rune crafting window on the client connected to
|
|
the invoking character. Since this command is officially used in rune
|
|
ores, a bonus success rate must be specified (which adds to the base
|
|
formula).
|
|
|
|
You can see the full list of runes that can be produced in
|
|
'db/produce_db.txt'. The window will not be empty only if the invoking
|
|
character can actually produce a rune and has the appropriate raw
|
|
materials in their inventory.
|
|
|
|
---------------------------------------
|
|
|
|
*successremovecards(<equipment slot>)
|
|
|
|
This command will remove all cards from the item found in the specified
|
|
equipment slot of the invoking character, create new card items and give
|
|
them to the character. If any cards were removed in this manner, it will
|
|
also show a success effect.
|
|
|
|
---------------------------------------
|
|
|
|
*failedremovecards(<equipment slot>, <type>)
|
|
|
|
This command will remove all cards from the item found in the specified
|
|
equipment slot of the invoking character. 'type' determines what happens
|
|
to the item and the cards:
|
|
|
|
0 - will destroy both the item and the cards.
|
|
1 - will keep the item, but destroy the cards.
|
|
2 - will keep the cards, but destroy the item.
|
|
|
|
Whatever the type is, it will also show a failure effect on screen.
|
|
|
|
---------------------------------------
|
|
|
|
*repair(<broken item number>)
|
|
|
|
This command repairs a broken piece of equipment, using the same list of
|
|
broken items as available through 'getbrokenid'.
|
|
|
|
The official scripts seem to use the repair command as a function instead:
|
|
'repair(<number>)' but it returns nothing on the stack. Probably only
|
|
Valaris, who made it, can answer why is it so.
|
|
|
|
---------------------------------------
|
|
|
|
*repairall()
|
|
|
|
This command repairs all broken equipment in the attached player's
|
|
inventory. A repair effect will be shown if any items are repaired, else
|
|
the command will end silently.
|
|
|
|
---------------------------------------
|
|
|
|
*successrefitem(<equipment slot>{, <upgrade_count>})
|
|
|
|
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.
|
|
|
|
---------------------------------------
|
|
|
|
*downrefitem(<equipment slot>{, <downgrade_count>})
|
|
|
|
This command will downgrade an item by - 1 (unless optional <downgrade_count> is provided)
|
|
in the specified equipment slot of the invoking character.
|
|
So the item will not be destroyed unlike in the failedrefitem() script
|
|
command. This will also display a 'refine failure' effect on the
|
|
character and put appropriate messages into their chat window.
|
|
|
|
---------------------------------------
|
|
|
|
*unequip(<equipment slot>)
|
|
|
|
This command will unequip whatever is currently equipped in the invoking
|
|
character's specified equipment slot. For a full list of possible
|
|
equipment slots see 'getequipid'.
|
|
|
|
If an item occupies several equipment slots, it will get unequipped from
|
|
all of them.
|
|
|
|
---------------------------------------
|
|
|
|
*clearitem()
|
|
|
|
This command will destroy all items the invoking character has in their
|
|
inventory (including equipped items). It will not affect anything else,
|
|
like storage or cart.
|
|
|
|
---------------------------------------
|
|
|
|
*equip(<item id>)
|
|
*equip2(<item id>, <refine>, <attribute>, <card1>, <card2>, <card3>, <card4>)
|
|
*autoequip(<item id>, <option>)
|
|
|
|
These commands are to equip a equipment on the attached character.
|
|
The equip function will equip the item ID given when the player has this
|
|
item in his/her inventory, while the autoequip function will equip the
|
|
given item ID when this is looted. The option parameter of the autoequip
|
|
is 1 or 0, 1 to turn it on, and 0 to turn it off.
|
|
|
|
Examples:
|
|
|
|
//This will equip a 1104 (falchion) on the character if this is in the
|
|
//inventory.
|
|
equip(Falchion);
|
|
|
|
//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);
|
|
|
|
//The invoked character will no longer automatically equip a falchion.
|
|
autoequip(Falchion, 0);
|
|
|
|
---------------------------------------
|
|
|
|
*buyingstore(<slots>)
|
|
|
|
Invokes buying store preparation window like the skill 'Open Buying
|
|
Store', without the item requirement. Amount of slots is limited by the
|
|
server to a maximum of 5 slots by default.
|
|
|
|
Example:
|
|
|
|
// Gives the player opportunity to buy 4 different kinds of items.
|
|
buyingstore(4);
|
|
|
|
---------------------------------------
|
|
|
|
*searchstores(<uses>, <effect>);
|
|
|
|
Invokes the store search window, which allows to search for both vending
|
|
and buying stores. Parameter uses indicates, how many searches can be
|
|
started, before the window has to be reopened. Effect value affects what
|
|
happens when a result item is double-clicked and can be one of the
|
|
following:
|
|
|
|
0 = Shows the store's position on the mini-map and highlights the shop
|
|
sign with yellow color, when the store is on same map as the
|
|
invoking player.
|
|
1 = Directly opens the shop, regardless of distance.
|
|
|
|
Example:
|
|
|
|
// Item Universal_Catalog_Gold (10 uses, effect: open shop)
|
|
searchstores(10, 1);
|
|
|
|
---------------------------------------
|
|
|
|
*mergeitem();
|
|
|
|
mergeitem() opens the item merge window,
|
|
The Item merge window shows all stackable item(same ItemID) with different
|
|
serial, that can be merged into one stack.
|
|
Check sample: npc/other/item_merge.txt
|
|
|
|
---------------------------------------
|
|
|
|
*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(<storage_constant>{, <storage_mode>});
|
|
|
|
This command opens the specified <storage_constant> storage window on the client
|
|
connected to the invoking character. It can be used from any kind of NPC or
|
|
item script and is not limited to Kafra Staff interactions.
|
|
|
|
The storage window will open regardless of whether there are open NPC dialogs,
|
|
but it is recommended to close any dialogs before displaying the storage window
|
|
to avoid overlapping interface elements, which could disrupt the user experience.
|
|
|
|
Parameters:
|
|
<storage_constant>: Specifies which storage to open (e.g., STORAGE_TYPE_MAIN).
|
|
Constants are declared in conf/storage.conf
|
|
<storage_mode> (optional): Defines the access permissions for the storage window.
|
|
|
|
Storage Modes (bitmask):
|
|
STORAGE_ACCESS_VIEW: View storage only.
|
|
STORAGE_ACCESS_GET: Allow retrieving items from storage.
|
|
STORAGE_ACCESS_PUT: Allow depositing items into storage.
|
|
STORAGE_ACCESS_ALL: (Default mode) Full access for viewing, retrieving,
|
|
and depositing items.
|
|
|
|
Example Usage:
|
|
mes("I will now open your stash for you");
|
|
close2();
|
|
openstorage(STORAGE_TYPE_MAIN);
|
|
end;
|
|
|
|
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.
|
|
|
|
mes("Close this window to open your mail inbox.");
|
|
close2();
|
|
openmail();
|
|
end;
|
|
|
|
---------------------------------------
|
|
|
|
*openauction()
|
|
|
|
This will open the Auction window on the client connected to the invoking
|
|
character.
|
|
|
|
mes("Close this window to open the Auction window.");
|
|
close2();
|
|
openauction();
|
|
end;
|
|
|
|
---------------------------------------
|
|
|
|
*dressroom({<mode>})
|
|
|
|
This command controls the dressing room for the attached player. If no <mode>
|
|
is passed, DRESSROOM_OPEN is used by default.
|
|
|
|
Valid <mode> for dressroom() are:
|
|
DRESSROOM_OPEN opens the dressing room window
|
|
DRESSROOM_CLOSE closes the dressing room window
|
|
|
|
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.
|
|
Expected return values:
|
|
|
|
0 Success (Opens storage)
|
|
1 Storage is already open
|
|
2 Player has no guild / guild information hasn't arrived yet
|
|
3 Player's guild doesn't have GD_GUILD_STORAGE (only if OFFICIAL_GUILD_STORAGE is enabled - automatically enabled on PACKETVER >= 20131223)
|
|
4 Player doesn't have permission to use storage (only on PACKETVER >= 20140205)
|
|
|
|
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.
|
|
|
|
---------------------------------------
|
|
|
|
*guildchangegm(<guild id>, <new master's name>)
|
|
|
|
This function will change the Guild Master of a guild. The ID is the
|
|
guild's id, and the new guild master's name must be passed.
|
|
|
|
Returns true on success, false otherwise.
|
|
|
|
---------------------------------------
|
|
|
|
*guildgetexp(<amount>)
|
|
|
|
This will give the specified amount of guild experience points to the
|
|
guild the invoking character belongs to. It will silently fail if they do
|
|
not belong to any guild.
|
|
|
|
---------------------------------------
|
|
|
|
*guildskill(<skill id>, <level>)
|
|
*guildskill("<skill name>", <level>)
|
|
|
|
This command will bump up the specified guild skill by the specified
|
|
number of levels. This refers to the invoking character and will only work
|
|
if the invoking character is a member of a guild AND it's guild master,
|
|
otherwise no failure message will be given and no error will occur, but
|
|
nothing will happen. The full list of guild skills is available in
|
|
'db/(pre-)re/skill_db.conf', 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.
|
|
|
|
// This would give your character's guild one level of Approval
|
|
// (GD_APPROVAL ID 10000). Notice that if you try to add two levels of
|
|
// Approval, or add Approval when the guild already has it, it will only
|
|
// have one level of Approval afterwards.
|
|
guildskill(GD_APPROVAL, 1);
|
|
|
|
You might want to make a quest for getting a certain guild skill, make it
|
|
hard enough that all the guild needs to help or something. Doing this for
|
|
the Glory of the Guild skill, which allows your guild to use an emblem, is
|
|
a good idea for a fun quest. (Wasting a level point on that is really
|
|
annoying :D)
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
4.2 - End of Guild-Related Commands
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
*resetlvl(<action type>)
|
|
|
|
This is a character reset command, meant mostly for rebirth script
|
|
supporting Advanced jobs, which will reset the invoking character's stats
|
|
and level depending on the action type given. Valid action types are:
|
|
|
|
1 - Base level 1, Job level 1, 0 skill points, 0 base exp, 0 job exp,
|
|
wipes the status effects (only the ones settable by 'setoption'),
|
|
sets all stats to 1. If the new job is 'Novice High', give 100 status
|
|
points, give First Aid and Play Dead skills.
|
|
2 - Base level 1, Job level 1, 0 skill points, 0 base exp, 0 job exp.
|
|
Skills and attribute values are not altered.
|
|
3 - Base level 1, base exp 0. Nothing else is changed.
|
|
4 - Job level 1, job exp 0. Nothing else is changed.
|
|
|
|
In all cases everything the character has on will be unequipped.
|
|
|
|
---------------------------------------
|
|
|
|
*resetstatus()
|
|
|
|
This is a character reset command, which will reset the stats on the
|
|
invoking character and give back all the stat points used to raise them
|
|
previously. Nothing will happen to any other numbers about the character.
|
|
|
|
Used in reset NPC's (duh!).
|
|
|
|
---------------------------------------
|
|
|
|
*resetskill()
|
|
|
|
This command takes off all the skill points on the invoking character, so
|
|
they only have Basic Skill blanked out (lvl 0) left, and returns the
|
|
points for them to spend again. Nothing else will change but the skills.
|
|
Quest skills will also reset if 'quest_skill_reset' option is set to 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.
|
|
|
|
Used in reset NPC's (duh!).
|
|
|
|
---------------------------------------
|
|
|
|
*resetfeel({<account id>})
|
|
*resethate({<account id>})
|
|
|
|
The first resets a character's 'Feeling' maps.
|
|
The second resets a character's 'Hatred' targets.
|
|
|
|
If no RID is given, will run with the current attached player.
|
|
|
|
---------------------------------------
|
|
|
|
*sc_start(<effect type>, <ticks>, <value 1>{, <rate>, <flag>{, <GID>}})
|
|
*sc_start2(<effect type>, <ticks>, <value 1>, <value 2>{, <rate>, <flag>{, <GID>}})
|
|
*sc_start4(<effect type>, <ticks>, <value 1>, <value 2>, <value 3>, <value 4>{, <rate>, <flag>{, <GID>}})
|
|
*sc_end(<effect type>{, <GID>})
|
|
|
|
These commands will bestow a status effect on a character.
|
|
|
|
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_(pre-)re.md' under 'Status Changes'. A full list is located in
|
|
'src/map/status.h', though they are not currently documented.
|
|
|
|
The duration of the status is given in <ticks>, or milliseconds.
|
|
|
|
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 (100 = 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);
|
|
|
|
Note: to use SC_NOCHAT you should alter Manner
|
|
Manner = -5; // Will mute a user for 5 minutes
|
|
Manner = 0; // Will unmute a user
|
|
Manner = 5; // Will unmute a user and prevent the next use of 'Manner'
|
|
|
|
---------------------------------------
|
|
|
|
*getstatus(<effect type>{, <type>})
|
|
|
|
Retrieve information about a specific status effect when called. Depending
|
|
on <type> specified the function will return different information.
|
|
|
|
Possible <type> values:
|
|
- 0 or undefined: whether the status is active
|
|
- 1: the val1 of the status
|
|
- 2: the val2 of the status
|
|
- 3: the val3 of the status
|
|
- 4: the val4 of the status
|
|
- 5: the amount of time in milliseconds that the status has remaining
|
|
|
|
If <type> is not defined or is set to 0, then the script function will
|
|
either return 1 if the status is active, or 0 if the status is not active.
|
|
If the status is not active when any of the <type> fields are provided,
|
|
this script function will always return 0.
|
|
|
|
---------------------------------------
|
|
|
|
*skilleffect(<skill id>, <number>)
|
|
*skilleffect("<skill name>", <number>)
|
|
|
|
This command displays visual and aural effects of given skill on currently
|
|
attached character. The number parameter is for skill whose visual effect
|
|
involves displaying of a number (healing or damaging). Note that this
|
|
command will not actually use the skill: it is intended for scripts which
|
|
simulate skill usage by the NPC, such as buffs, by setting appropriate
|
|
status and displaying the skill's effect.
|
|
|
|
mes("Be blessed!");
|
|
// Heal of 2000 HP
|
|
heal(2000, 0);
|
|
skilleffect(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 behaves identically to skilleffect(), however, the effect
|
|
will not be centered on the invoking character's sprite, nor on the NPC
|
|
sprite, if any, but will be centered at map coordinates given on the same
|
|
map as the invoking character.
|
|
|
|
---------------------------------------
|
|
|
|
*specialeffect(<effect number>{, <send_target>{, <unit id>{, <account id>}}})
|
|
*specialeffect(<effect number>{, <send_target>{, "<NPC Name>"{, <account id>}}})
|
|
|
|
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.md'. 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:
|
|
|
|
// To make a NPC do an effect and show it to everyone:
|
|
specialeffect(EF_HIT1, AREA, "John Doe#1");
|
|
|
|
// To make a player do an effect and show it to everyone:
|
|
specialeffect(EF_HIT1, AREA, getcharid(CHAR_ID_ACCOUNT, "player"));
|
|
|
|
// To make a NPC do an effect and show it only to the attached player:
|
|
specialeffect(EF_HIT1, SELF, "John Doe#1");
|
|
|
|
// To make a NPC do an effect and show it only to another player:
|
|
specialeffect(EF_HIT1, SELF, "John Doe#1", getcharid(CHAR_ID_ACCOUNT, "player"));
|
|
|
|
---------------------------------------
|
|
|
|
*specialeffectnum(<effect number>, <num1>, <num2>{, <send_target>{, <unit id>{, <account id>}}})
|
|
*specialeffectnum(<effect number>, <num1>, <num2>{, <send_target>{, "<NPC Name>"{, <account id>}}})
|
|
|
|
Works same as specialeffect but also send effect numbers to client.
|
|
For PACKETVER >= 20191127 support two numbers (num1, num2).
|
|
For older packet versions only num1 supported.
|
|
|
|
---------------------------------------
|
|
|
|
*removespecialeffect(<effect number>{, <send_target>{, <unit id>{, <account id>}}})
|
|
*removespecialeffect(<effect number>{, <send_target>{, "<NPC Name>"{, <account id>}}})
|
|
|
|
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.
|
|
|
|
---------------------------------------
|
|
|
|
*statusup(<stat>)
|
|
|
|
This command will bump a specified stat of the invoking character up by
|
|
one permanently using status points to do so, if there aren't enough to perform
|
|
the change nothing will happen.
|
|
Stats are to be given as number, but you can use these constants to replace them:
|
|
|
|
bStr - Strength
|
|
bVit - Vitality
|
|
bInt - Intelligence
|
|
bAgi - Agility
|
|
bDex - Dexterity
|
|
bLuk - Luck
|
|
|
|
---------------------------------------
|
|
|
|
*statusup2(<stat>, <amount>)
|
|
|
|
This command will bump a specified stat of the invoking character up by
|
|
the specified amount permanently without using status points.
|
|
Amount can be negative. See statusup().
|
|
|
|
// This will decrease a character's Vit forever.
|
|
statusup(bVit, -1);
|
|
|
|
---------------------------------------
|
|
|
|
*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'.
|
|
|
|
---------------------------------------
|
|
|
|
*autobonus(<bonus script>, <rate>, <duration>{, <flag>, {<other script>}})
|
|
*autobonus2(<bonus script>, <rate>, <duration>{, <flag>, {<other script>}})
|
|
*autobonus3(<bonus script>, <rate>, <duration>, <skill id>, {<other script>})
|
|
*autobonus3(<bonus script>, <rate>, <duration>, "<skill name>", {<other script>})
|
|
|
|
These commands are meant to be used in item scripts. They will probably
|
|
work outside item scripts, but the bonus will not persist for long. They,
|
|
as expected, refer only to an invoking character.
|
|
|
|
What these commands do is 'attach' a script to the player which will get
|
|
executed on attack (or when attacked in the case of autobonus2()).
|
|
|
|
Rate is the trigger rate of the script (1000 = 100%).
|
|
|
|
Duration is the time that the bonus will last for since the script has
|
|
triggered.
|
|
|
|
Skill ID/skill name the skill which will be used as trigger to start the
|
|
bonus (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()); }");
|
|
|
|
---------------------------------------
|
|
|
|
*skill(<skill id>, <level>{, <flag>})
|
|
*skill("<skill name>", <level>{, <flag>})
|
|
*addtoskill(<skill id>, <level>{, <flag>})
|
|
*addtoskill("<skill name>", <level>{, <flag>})
|
|
|
|
These commands will give the invoking character a specified skill. This is
|
|
also used for item scripts.
|
|
|
|
Level is obvious. Skill id is the ID number of the skill in question as
|
|
per 'db/(pre-)re/skill_db.conf'. It is not known for certain whether this
|
|
can be used to give a character a monster's skill, but you're welcome to
|
|
try with the numbers given in 'db/(pre-)re/mob_skill_db.conf'.
|
|
|
|
Flag is 0 if the skill is given permanently (will get written with the
|
|
character data) or 1 if it is temporary (will be lost eventually, this is
|
|
meant for card item scripts usage.). The flag parameter is optional, and
|
|
defaults to 1 in 'skill' and to 2 in 'addtoskill'.
|
|
|
|
Flag 2 means that the level parameter is to be interpreted as a stackable
|
|
additional bonus to the skill level. If the character did not have that
|
|
skill previously, they will now at 0+the level given.
|
|
|
|
// This will permanently give the character Stone Throw
|
|
// (TF_THROWSTONE, 152), at level 1.
|
|
skill(TF_THROWSTONE, 1, 0);
|
|
|
|
Flag 3 is the same as flag 0 in that it saves to the database. However,
|
|
these skills are ignored when any action is taken that adjusts the skill
|
|
tree (reset/job change).
|
|
|
|
---------------------------------------
|
|
|
|
*nude()
|
|
|
|
This command will unequip anything equipped on the invoking character.
|
|
|
|
It is not required to do this when changing jobs since jobchange() will
|
|
unequip everything not equippable by the new job class anyway.
|
|
|
|
---------------------------------------
|
|
|
|
*disguise(<Monster ID>)
|
|
*undisguise()
|
|
|
|
This command disguises the current player with a monster sprite.
|
|
The disguise lasts until undisguise() is issued or the player logs out.
|
|
|
|
Example:
|
|
|
|
disguise(PORING); // Disguise character as a Poring.
|
|
next();
|
|
undisguise(); // Return to normal character sprite.
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
4.3 - Marriage-Related Commands
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
*marriage("<spouse name>")
|
|
|
|
This function will marry two characters, the invoking character and the
|
|
one referred to by name given, together, setting them up as each other's
|
|
marriage partner. No second function call has to be issued (in current 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
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
*pcfollow(<id>, <target id>)
|
|
*pcstopfollow(<id>)
|
|
|
|
Makes a character follow or stop following someone. This command does the
|
|
same as the @follow command. The main difference is that @follow can use
|
|
character names, and this commands needs the Account ID for the target.
|
|
|
|
Examples:
|
|
|
|
// This will make Aaron follow Bullah, when both of these characters are
|
|
// online.
|
|
pcfollow(getcharid(CHAR_ID_ACCOUNT, "Aaron"), getcharid(CHAR_ID_ACCOUNT, "Bullah"));
|
|
|
|
// Makes Aaron stop following whoever he is following.
|
|
pcstopfollow(getcharid(CHAR_ID_ACCOUNT, "Aaron"));
|
|
|
|
---------------------------------------
|
|
|
|
*setpcblock(<type>, <option>{, <account id>})
|
|
*checkpcblock({<account id>})
|
|
|
|
Prevents a character from doing the following action.
|
|
|
|
For setpcblock, when the <option> is true(1) will block them, and false(0)
|
|
will allow those actions again.
|
|
|
|
The setpcblock command returns 1 on success or 0 if no character was attached.
|
|
|
|
The checkpcblock command returned value is a bit mask of the currently
|
|
enabled block flags (or PCBLOCK_NONE when none is set).
|
|
|
|
Parameter <account id> is optional for both commands.
|
|
If omitted, the currently attached character is used.
|
|
|
|
The <type> listed are a bit mask of the following:
|
|
PCBLOCK_NONE (only used by checkpcblock)
|
|
PCBLOCK_MOVE
|
|
PCBLOCK_ATTACK
|
|
PCBLOCK_SKILL
|
|
PCBLOCK_USEITEM
|
|
PCBLOCK_CHAT
|
|
PCBLOCK_IMMUNE
|
|
PCBLOCK_SITSTAND
|
|
PCBLOCK_COMMANDS
|
|
PCBLOCK_NPC
|
|
|
|
Examples:
|
|
|
|
// Make the current attached player invulnerable, same as @monsterignore
|
|
setpcblock(PCBLOCK_IMMUNE, true);
|
|
|
|
// Prevents the current char from attacking or using skills
|
|
setpcblock(PCBLOCK_ATTACK|PCBLOCK_SKILL, true);
|
|
|
|
// Re-enables attack, skills and item use
|
|
setpcblock(PCBLOCK_ATTACK|PCBLOCK_SKILL|PCBLOCK_USEITEM, false);
|
|
|
|
// checkpcblock related checks
|
|
if ((checkpcblock() & PCBLOCK_IMMUNE) != 0)
|
|
mes "You are invulnerable!";
|
|
|
|
if ((checkpcblock() & (PCBLOCK_MOVE|PCBLOCK_SITSTAND)) == (PCBLOCK_MOVE|PCBLOCK_SITSTAND))
|
|
mes "You can't walk or sit";
|
|
|
|
if ((checkpcblock() & (PCBLOCK_ATTACK|PCBLOCK_SKILL)) == PCBLOCK_NONE)
|
|
mes "You can attack and use skills";
|
|
|
|
if ((checkpcblock() & PCBLOCK_CHAT) == PCBLOCK_NONE)
|
|
mes "You can't chat";
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
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>}}})
|
|
|
|
This command will spawn a monster on the specified coordinates on the
|
|
specified map. If the script is invoked by a character, a special map
|
|
name, "this", will be recognized to mean the name of the map the invoking
|
|
character is located at. This command works fine in the item scripts.
|
|
|
|
The same command arguments mean the same things as described above in the
|
|
beginning of this document when talking about permanent monster spawns.
|
|
Monsters spawned in this manner will not respawn upon being killed.
|
|
|
|
Unlike the permanent monster spawns, if the mob id is -1, a random monster
|
|
will be picked from the entire database according to the rules configured
|
|
in the server for dead branches. This will work for all other kinds of
|
|
non-permanent monster spawns.
|
|
|
|
The only very special thing about this command is an event label, which is
|
|
an optional parameter. This label is written like
|
|
'<NPC object name>::<label name>' and upon the monster being killed, it
|
|
will execute the script inside of the specified NPC object starting from
|
|
the label given. The RID of the player attached at this execution will be
|
|
the RID of the killing character.
|
|
|
|
<size> can be:
|
|
Size_Medium = medium (default)
|
|
Size_Small = small
|
|
Size_Large = big
|
|
|
|
<ai> can be:
|
|
0 = none (default)
|
|
1 = attack/friendly
|
|
2 = sphere (Alchemist skill)
|
|
3 = flora (Alchemist skill)
|
|
4 = zanzou (Kagerou/Oboro skill)
|
|
|
|
monster("place", 60, 100, "Poring", PORING, 1, "NPCNAME::OnLabel");
|
|
|
|
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:
|
|
|
|
// We'll make a poring which will automatically attack invoking player:
|
|
.@mobGID = monster("prontera", 150, 150, "Poring", PORING, 1); // PORING is defined in the mob db and its value is 1002
|
|
unitattack(.@mobGID, getcharid(CHAR_ID_ACCOUNT)); // Attacker GID, attacked GID
|
|
|
|
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:
|
|
|
|
// We want to summon .mobnumber porings which will give us a kiss
|
|
for (.@i = 0; .@i < .mobnumber; ++.@i) {
|
|
.@mobGID = monster("map", .x, .y, "Kisser Poring", PORING, 1);
|
|
unitemote(.@mobGID, e_kis);
|
|
}
|
|
|
|
Refer to the unit* commands below.
|
|
|
|
The areamonster() command works much like the monster() command and is not
|
|
significantly different, but spawns the monsters within a square defined
|
|
by x1/y1-x2/y2.
|
|
|
|
Simple monster killing script:
|
|
|
|
<NPC object definition. Let's assume you called him NPCNAME.>
|
|
mes("[Summon Man]");
|
|
mes("Want to start the kill?");
|
|
next();
|
|
if (select("Yes", "No") != 1) {
|
|
mes("[Summon Man]");
|
|
mes("Come back later");
|
|
close();
|
|
}
|
|
monster("prontera", 0, 0, "Quest Poring", PORING, 10, "NPCNAME::OnPoringKilled");
|
|
// By using 0,0 it will spawn them in a random place.
|
|
mes("[Summon Man]");
|
|
mes("Now go and kill all the Poring I summoned");
|
|
// He summoned ten.
|
|
close();
|
|
OnPoringKilled:
|
|
++$poring_killed;
|
|
if ($poring_killed == 10) {
|
|
announce("Summon Man: Well done all the poring are dead", bc_self);
|
|
$poring_killed = 0;
|
|
}
|
|
end;
|
|
|
|
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.
|
|
|
|
<target type> can be:
|
|
0 = self
|
|
1 = the mob's current target
|
|
2 = the mob's master
|
|
3 = random target
|
|
|
|
Example:
|
|
|
|
// spawn 1 Shining Plant in the 5x5 area centered on (155,188)
|
|
areamonster("prontera", 153, 186, 157, 190, "Shining Plant", SHINING_PLANT, 1);
|
|
// make the plant cast level 10 Cold Bolt on a random target
|
|
areamobuseskill("prontera", 155, 188, 2, SHINING_PLANT, MG_COLDBOLT, 10, 3000, 1, e_gg, 3)
|
|
|
|
---------------------------------------
|
|
|
|
*killmonster("<map name>", "<event label>"{, <type>})
|
|
|
|
This command will kill all monsters that were spawned with monster() or
|
|
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.
|
|
|
|
---------------------------------------
|
|
|
|
*killmonsterall("<map name>"{, <type>})
|
|
|
|
This command will kill all monsters on a specified map name, regardless of
|
|
how they were spawned or what they are without triggering any event label
|
|
attached to them, unless you specify 1 for type parameter. In this case,
|
|
mob death labels will be allowed to trigger 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.
|
|
|
|
---------------------------------------
|
|
|
|
*strmobinfo(<type>, <monster id>)
|
|
|
|
This function will return information about a monster record in the
|
|
database, as per 'db/(pre-)re/mob_db.conf'. Type is the kind of information
|
|
returned. Valid types are:
|
|
|
|
1 - 'english name' field in the database, a string.
|
|
2 - 'japanese name' field in the database, a string.
|
|
All other returned values are numbers:
|
|
3 - Level.
|
|
4 - Maximum HP.
|
|
5 - Maximum SP.
|
|
6 - Experience reward.
|
|
7 - Job experience reward.
|
|
|
|
---------------------------------------
|
|
|
|
*mobcount("<map name>", "<event label>")
|
|
|
|
This function will count all the monsters on the specified map that have a
|
|
given event label and return the number or 0 if it can't find any.
|
|
Naturally, only monsters spawned with 'monster' and 'areamonster' script
|
|
commands can have non-empty event label.
|
|
If you pass this function an empty string for the event label, it will
|
|
return the total count of monster without event label, including
|
|
permanently spawning monsters.
|
|
|
|
With the dynamic mobs system enabled, where mobs are not kept in memory
|
|
for maps with no actual people playing on them, this will return a 0 for
|
|
any such map.
|
|
|
|
If the event label is given as "all", all monsters will be counted,
|
|
regardless of having any event label attached.
|
|
|
|
If the map name is given as "this", the map the invoking character is on
|
|
will be used. If the map is not found, or the invoker is not a character
|
|
while the map is "this", it will return -1.
|
|
|
|
---------------------------------------
|
|
|
|
*clone("<map name>", <x>, <y>, "<event>", <char id>{, <master_id>{, <mode>{, <flag>, <duration>}}})
|
|
|
|
This command creates a monster which is a copy of another player. The
|
|
first four arguments serve the same purpose as in the monster script
|
|
command, The <char id> is the character id of the player to clone (player
|
|
must be online).
|
|
If <master id> is given, the clone will be a 'slave/minion' of it.
|
|
Master_id must be a character id of another online player.
|
|
|
|
The mode can be specified to determine the behavior of the clone, 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).
|
|
|
|
Returned value is the monster ID of the spawned clone. If command fails,
|
|
returned value is zero.
|
|
|
|
---------------------------------------
|
|
|
|
*summon("Monster name", <monster id>{, <Time Out>{, "event label"}})
|
|
|
|
This command will summon a monster. (see also monster()) Unlike monsters
|
|
spawned with other commands, this one will set up the monster to fight to
|
|
protect the invoking character. Monster name and mob id obey the same
|
|
rules as the one given at the beginning of this document for permanent
|
|
monster spawns with the exceptions mentioned when describing 'monster'
|
|
command.
|
|
|
|
The effect for the skill 'Call Homunculus' will be displayed centered on
|
|
the invoking character.
|
|
|
|
Timeout is the time in milliseconds the summon lives, and is set default
|
|
to 60000 (1 minute). Note that also the value 0 will set the timer to
|
|
default, and it is not possible to create a spawn that lasts forever.
|
|
If an event label is given, upon the monster being killed, the event label
|
|
will run as if by donpcevent().
|
|
|
|
// Will summon a poring to fight for the character.
|
|
summon("--ja--", PORING);
|
|
|
|
---------------------------------------
|
|
|
|
*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()
|
|
|
|
This command will try to evolve the current player's homunculus.
|
|
If it doesn't work, the /swt emotion is shown.
|
|
|
|
To evolve a homunculus, the invoking player must have a homunculus, the
|
|
homunculus must not be the last evolution and the homunculus must have
|
|
above 91000 intimacy with its owner.
|
|
|
|
---------------------------------------
|
|
|
|
*gethominfo(<type>)
|
|
|
|
This function works as a direct counterpart of 'getpetinfo':
|
|
HOMINFO_ID - Homunculus unique ID
|
|
HOMINFO_CLASS - Homunculus Class
|
|
HOMINFO_NAME - Name
|
|
HOMINFO_INTIMACY - Friendly level (intimacy score). 100000 is full loyalty.
|
|
HOMINFO_HUNGRY - Hungry level. 100 is completely full.
|
|
HOMINFO_RENAME - Rename flag. 0 means this homunculus has not been named yet.
|
|
HOMINFO_LEVEL - Homunculus level
|
|
|
|
If the attached player doesn't own a homunculus, this command will return
|
|
"null" for type HOMINFO_NAME, and return 0 for other types.
|
|
|
|
---------------------------------------
|
|
|
|
*morphembryo()
|
|
|
|
This command will try to put the invoking player's Homunculus in an
|
|
uncallable state, required for mutation into a Homunculus S. The player
|
|
will also receive a Strange Embryo (ID 6415) in their inventory if
|
|
successful, which is deleted upon mutation.
|
|
|
|
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.
|
|
|
|
Returns 1 upon success and 0 for all failures.
|
|
|
|
---------------------------------------
|
|
|
|
*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.
|
|
|
|
If the optional parameter <ID> is set, the invoking player's Homunculus
|
|
will change into the specified Homunculus ID. Otherwise, a random Homunculus S
|
|
will be chosen. See 'db/(pre-)re/homunculus_db.conf' for a full list of IDs.
|
|
|
|
Returns true upon success and false for all failures.
|
|
|
|
---------------------------------------
|
|
|
|
*checkhomcall()
|
|
|
|
This function checks if the attached player's Homunculus is active,
|
|
and will return the following values:
|
|
-1: The player has no Homunculus.
|
|
0: The player's Homunculus is active.
|
|
1: The player's Homunculus is vaporized.
|
|
2: The player's Homunculus is in morph state.
|
|
|
|
---------------------------------------
|
|
|
|
*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
|
|
|
|
---------------------------------------
|
|
|
|
*unitwalk(<GID>, <x>, <y>)
|
|
*unitwalk(<GID>, <target_GID>)
|
|
|
|
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:
|
|
|
|
//Will move/walk the poring we made to the coordinates 150,150
|
|
unitwalk(.GID, 150, 150);
|
|
|
|
//NPC will move towards the attached player.
|
|
unitwalk(.GID, getcharid(CHAR_ID_ACCOUNT));//a player's GID is their account ID
|
|
|
|
---------------------------------------
|
|
|
|
*unitiswalking({<GID>})
|
|
|
|
This command checks, if a unit is walking or not.
|
|
If <GID> is omitted, the currently attached character is used.
|
|
Returns 1 if the unit is walking, 0 if the unit is not walking and -1 on error.
|
|
|
|
Note: There's no differentiation between script and client initiated walking.
|
|
|
|
Example:
|
|
|
|
prontera,155,185,5 script Check Walking 1_F_MARIA,{
|
|
mes("Enter character name.");
|
|
mes("");
|
|
input(.@name$);
|
|
.@GID = getcharid(CHAR_ID_ACCOUNT, .@name$);
|
|
if (.@GID != 0) {
|
|
.@iswalking = unitiswalking(.@GID);
|
|
if (.@iswalking == 1)
|
|
mesf("%s is walking.", .@name$);
|
|
else if (.@iswalking == 0)
|
|
mesf("%s is not walking.", .@name$);
|
|
else
|
|
mesf("Can't get %s's walking state.", .@name$);
|
|
} else {
|
|
mesf("%s not found!", .@name$);
|
|
}
|
|
close();
|
|
}
|
|
|
|
---------------------------------------
|
|
|
|
*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>)
|
|
|
|
Okay, these commands should be fairly self explaining.
|
|
For the emotions, you can look in 'doc/constants_(pre-)re.md' under 'Emotes'
|
|
PS: unitwarp() supports a <GID> of zero, which causes the executor of the
|
|
PS: unittalk() can receive 3 extra parameters:
|
|
show_name:
|
|
true: Shows Unit name like "UnitName : Message" (default)
|
|
false: Hides Unit name
|
|
send_target:
|
|
AREA_CHAT_WOC: sends the message to everyone in view range including the attached unit (default)
|
|
SELF: sends the message to the given unit gid only
|
|
target_id:
|
|
if send_target is set to SELF, the message will be shown by the given gid,
|
|
target_id allows changing the unit that will see the message.
|
|
script to be affected. This can be used with OnTouchNPC to warp
|
|
monsters:
|
|
|
|
OnTouchNPC:
|
|
unitwarp(0, "this", -1, -1);
|
|
|
|
// hide the npc name from the text
|
|
unittalk(getnpcid(0), "foobar", false);
|
|
|
|
// display by npc to everyone
|
|
unittalk(getnpcid(0), "foobar", true);
|
|
|
|
// display by npc to npc
|
|
unittalk(getnpcid(0), "foobar", true, SELF);
|
|
|
|
// display the text by the npc to the attached player only
|
|
unittalk(getnpcid(0), "foobar", true, SELF, playerattached());
|
|
|
|
// display by player to everyone
|
|
unittalk(playerattached(), "foobar", true);
|
|
|
|
// display by player to himself only
|
|
unittalk(playerattached(), "foobar", true, SELF);
|
|
|
|
// display the text by the 1st player to the attached player only
|
|
unittalk(getcharid(CHAR_ID_ACCOUNT, "Name"), "foobar", true, SELF, playerattached());
|
|
|
|
---------------------------------------
|
|
|
|
*disablenpc("<NPC object name>")
|
|
*enablenpc("<NPC object name>")
|
|
|
|
These two commands will disable and enable, respectively, an NPC object
|
|
specified by name. The disabled NPC will disappear from sight and will no
|
|
longer be triggerable in the normal way. It is not clear whether it will
|
|
still be accessible through donpcevent() and other triggering commands,
|
|
but it probably will be. You can disable even warp NPCs if you know their
|
|
object names, which is an easy way to make a map only accessible through
|
|
walking half the time. Then you 'enablenpc' them back.
|
|
|
|
You can also use these commands to create the illusion of an NPC switching
|
|
between several locations, which is often better than actually moving the
|
|
NPC - create one NPC object with a visible and a hidden part to their
|
|
name, make a few copies, and then disable all except one.
|
|
|
|
---------------------------------------
|
|
|
|
*hideonnpc("<NPC object name>")
|
|
*hideoffnpc("<NPC object name>")
|
|
|
|
These commands will make the NPC object specified display as hidden or
|
|
visible, even though not actually disabled per se. Hidden as in thief Hide
|
|
skill, but unfortunately, not detectable by Ruwach or Sight.
|
|
|
|
As they are now, these commands are pointless, it is suggested to use
|
|
'disablenpc'/'enablenpc', because these two commands actually unload the
|
|
NPC sprite location and other accompanying data from memory when it is not
|
|
used. However, you can use these for some quest ideas (such as cloaking
|
|
NPCs talking while hidden then revealing... you can wonder around =P).
|
|
|
|
---------------------------------------
|
|
|
|
*cloakonnpc("<NPC object name>"{, <account_id>})
|
|
*cloakoffnpc("<NPC object name>"{, <account_id>})
|
|
|
|
These commands are used to apply the cloaking effect on npcs
|
|
this is a visual effect only and it does NOT stop the player
|
|
from interacting with the npc.
|
|
|
|
If an account_id is specified then the effect will only display to the given id,
|
|
otherwise it's displayed to the entire npc area.
|
|
|
|
---------------------------------------
|
|
|
|
*doevent("<NPC object name>::<event label>")
|
|
|
|
This command will start a new execution thread in a specified NPC object
|
|
at the specified label. The execution of the script running this command
|
|
will not stop, and the event called by the doevent() command will not run
|
|
until the invoking script has terminated. No parameters may be passed with
|
|
a doevent() call.
|
|
|
|
The script of the NPC object invoked in this manner will run as if it's
|
|
been invoked by the RID that was active in the script that issued a
|
|
'doevent'. As such, the command will not work if an RID is not attached.
|
|
|
|
place,100,100,1%TAB%script%TAB%NPC%TAB%53,{
|
|
mes("This is what you will see when you click me");
|
|
close();
|
|
OnLabel:
|
|
mes("This is what you will see if the doevent is activated");
|
|
close();
|
|
}
|
|
|
|
// ...
|
|
|
|
doevent("NPC::OnLabel");
|
|
|
|
---------------------------------------
|
|
|
|
*donpcevent("<NPC object name>::<event label>")
|
|
|
|
This command invokes the event label code within an another NPC or NPCs.
|
|
It starts a separate instance of execution, and the invoking NPC will
|
|
resume execution its immediately.
|
|
|
|
If the supplied event label has the form "NpcName::OnLabel", then only
|
|
given NPC's event label will be invoked (much like goto() into another
|
|
NPC). If the form is "::OnLabel" (NPC name omitted), the event code of all
|
|
NPCs with given label will be invoked, one after another. In both cases
|
|
the invoked script will run without an attached RID, whether or not the
|
|
invoking script was attached to a player. The event label name is required
|
|
to start with "On".
|
|
|
|
This command can be used to make other NPCs act, as if they were
|
|
responding to the invoking NPC's actions, such as using an emotion or
|
|
talking.
|
|
|
|
place,100,100,1%TAB%script%TAB%NPC%TAB%53,{
|
|
mes("Hey NPC2 copy what I do");
|
|
close2();
|
|
@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.
|
|
|
|
Command returns true or false on success and failure.
|
|
A debug message also shows on the console when no events are triggered.
|
|
|
|
---------------------------------------
|
|
|
|
*npctalk("<message>"{, "<npc name>"{, <show_name>}})
|
|
|
|
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");
|
|
|
|
---------------------------------------
|
|
|
|
*setnpcdisplay("<npc name>", "<display name>", <class id>, <size>)
|
|
*setnpcdisplay("<npc name>", "<display name>", <class id>)
|
|
*setnpcdisplay("<npc name>", "<display name>")
|
|
*setnpcdisplay("<npc name>", <class id>)
|
|
|
|
Changes the display name and/or display class of the target NPC.
|
|
Returns 0 is successful, 1 if the NPC does not exist or is a floating npc.
|
|
Size is 0 = normal 1 = small 2 = big.
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
5.1 - Time-Related Commands
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
*addtimer(<ticks>, "NPC::OnLabel"{, <account id>})
|
|
|
|
This command will create a countdown timer.
|
|
The event label given is the identifier of that timer.
|
|
The timer runs on the character object that is attached to the script,
|
|
and can have multiple instances. If <acccount id> is passed, this player
|
|
will be used instead. When the label is run, it is run as if the player
|
|
that the timer runs on has clicked the NPC.
|
|
|
|
When this timer runs out, a new execution thread will start in the
|
|
specified NPC object at the specified label.
|
|
|
|
The ticks are given in 1/1000ths of a second.
|
|
|
|
One more thing. These timers are stored as part of player data. If the
|
|
player logs out, all of these get immediately deleted, without executing
|
|
the script. If this behavior is undesirable, use some other timer
|
|
mechanism (like sleep()).
|
|
|
|
Example:
|
|
<NPC Header> {
|
|
dispbottom("Starting a 5 second timer...");
|
|
addtimer(5000, strnpcinfo(NPC_NAME_UNIQUE)+"::On5secs");
|
|
end;
|
|
On5secs:
|
|
dispbottom("5 seconds have passed!");
|
|
end;
|
|
}
|
|
|
|
---------------------------------------
|
|
|
|
*deltimer("NPC::OnLabel"{, <account id>})
|
|
|
|
Deletes timers created by addtimer() that matches the given event
|
|
label. Refer to addtimer() for additional information.
|
|
|
|
---------------------------------------
|
|
|
|
*addtimercount("NPC::OnLabel", <ticks>{, <account id>})
|
|
|
|
Delays a timer that was created with addtimer() by <ticks> ticks
|
|
if it matches the given event label. Refer to addtimer() for additional
|
|
information.
|
|
|
|
---------------------------------------
|
|
|
|
*gettimer(<type>{, <account id>{, "<event>"}})
|
|
|
|
Returns informations on timers that were created by addtimer().
|
|
|
|
valid <type> for gettimer() are:
|
|
|
|
(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>.
|
|
|
|
---------------------------------------
|
|
|
|
*initnpctimer({"<NPC name>"{, <Attach Flag>}})
|
|
*initnpctimer({<Attach Flag>})
|
|
*stopnpctimer({"<NPC name>"{, <Detach Flag>}})
|
|
*stopnpctimer({<Detach Flag>}})
|
|
*startnpctimer({"<NPC name>"{, <Attach Flag>}})
|
|
*startnpctimer({<Attach Flag>})
|
|
*setnpctimer(<tick>{, "<NPC name>"})
|
|
*getnpctimer(<type of information>{, "<NPC name>"})
|
|
*attachnpctimer({"<character name>"})
|
|
*detachnpctimer({"<NPC name>"})
|
|
|
|
This set of commands and functions will create and manage an NPC-based
|
|
timer. The NPC name may be omitted, in which case the calling NPC is used
|
|
as target.
|
|
|
|
Contrary to addtimer()/deltimer() commands which let you have many different
|
|
timers referencing different labels in the same NPC, each with their own
|
|
countdown, initnpctimer() can only have one per NPC object. But it can
|
|
trigger many labels and let you know how many were triggered already and
|
|
how many still remain.
|
|
|
|
This timer is counting up from 0 in ticks of 1/1000ths of a second each.
|
|
Upon creating this timer, the execution will not stop, but will happily
|
|
continue onward. The timer will then invoke new execution threads at
|
|
labels "OnTimer<time>:" in the NPC object it is attached to.
|
|
|
|
To create the timer, use the initnpctimer(), which will start it running.
|
|
stopnpctimer() will pause the timer, without clearing the current tick,
|
|
while startnpctimer() will let the paused timer continue.
|
|
|
|
By default timers do not have a RID attached, which lets them continue
|
|
even if the player that started them logs off. To attach a RID to a timer,
|
|
you can either use the optional "attach flag" when using
|
|
initnpctimer()/startnpctimer(), or do it manually by using attachnpctimer().
|
|
Likewise, the optional flag of stopnpctimer() lets you detach any RID after
|
|
stopping the timer, and by using detachnpctimer() you can detach a RID at
|
|
any time.
|
|
|
|
Normally there is only a single timer per NPC, but as an exception, as
|
|
long as you attach a player to the timer, you can have multiple timers
|
|
running at once, because these will get stored on the players instead of
|
|
the NPC.
|
|
NOTE: You need to attach the RID before the timer _before_ you start it to
|
|
get a player-attached timer. Otherwise it'll stay a NPC timer (no effect).
|
|
|
|
If the player that is attached to the npctimer logs out, the
|
|
"OnTimerQuit:" event label of that NPC will be triggered, so you can do
|
|
the appropriate cleanup (the player is still attached when this event is
|
|
triggered).
|
|
|
|
The setnpctimer() command will explicitly set the timer to a given tick.
|
|
getnpctimer() provides timer information. Its parameter defines what type:
|
|
|
|
0 - Will return the current tick count of the timer.
|
|
1 - Will return 1 if there are remaining "OnTimer<ticks>:" labels in the
|
|
specified NPC waiting for execution.
|
|
2 - Will return the number of times the timer has triggered and will
|
|
trigger an "OnTimer<tick>:" label in the specified NPC.
|
|
|
|
Example 1:
|
|
|
|
<NPC Header> {
|
|
// We need to use attachnpctimer() because the mes command below
|
|
// needs RID attach
|
|
attachnpctimer();
|
|
initnpctimer();
|
|
npctalk("I cant talk right now, give me 10 seconds");
|
|
end;
|
|
OnTimer5000:
|
|
npctalk("Ok 5 seconds more");
|
|
end;
|
|
OnTimer6000:
|
|
npctalk("4");
|
|
end;
|
|
OnTimer7000:
|
|
npctalk("3");
|
|
end;
|
|
OnTimer8000:
|
|
npctalk("2");
|
|
end;
|
|
OnTimer9000:
|
|
npctalk("1");
|
|
end;
|
|
OnTimer10000:
|
|
stopnpctimer();
|
|
mes("[Man]");
|
|
mes("Ok we can talk now");
|
|
detachnpctimer();
|
|
// and remember attachnpctimer() and detachnpctimer() can only be used
|
|
// while the NPC timer is not running!
|
|
}
|
|
|
|
Example 2:
|
|
|
|
OnTimer15000:
|
|
npctalk("Another 15 seconds have passed.");
|
|
|
|
// You have to use initnpctimer() instead of setnpctimer(0).
|
|
// This is equal to setnpctimer(0); startnpctimer();.
|
|
// Alternatively, you can also insert another 'OnTimer15001:' label
|
|
// so that the timer won't stop.
|
|
initnpctimer();
|
|
end;
|
|
|
|
// This OnInit label will run when the script is loaded, so that the
|
|
// timer is initialized immediately as the server starts. It is
|
|
// dropped back to 0 every time the NPC says something, so it will
|
|
// cycle continuously.
|
|
OnInit:
|
|
initnpctimer();
|
|
end;
|
|
|
|
Example 3:
|
|
|
|
mes("[Man]");
|
|
mes("I have been waiting "+(getnpctimer(0)/1000)+" seconds for you.");
|
|
// We divide the timer returned by 1000 to convert milliseconds to
|
|
// seconds.
|
|
close();
|
|
|
|
Example 4:
|
|
|
|
mes("[Man]");
|
|
mes("Ok, I will let you have 30 more seconds...");
|
|
close2();
|
|
setnpctimer(getnpctimer(0)-30000);
|
|
// Notice the close2(). If there were a next() there the timer would
|
|
// be changed only after the player pressed the next() button.
|
|
end;
|
|
|
|
---------------------------------------
|
|
|
|
*sleep(<milliseconds>)
|
|
*sleep2(<milliseconds>)
|
|
*awake("<NPC name>")
|
|
|
|
These commands are used to control the pause of a NPC.
|
|
sleep() and sleep2() will pause the script for the given amount of
|
|
milliseconds.
|
|
awake() is used to cancel a sleep(). When awake() is called on a NPC it will run
|
|
as if the sleep timer ran out, and thus making the script continue. sleep()
|
|
and sleep2() basically do the same, but the main difference is that sleep()
|
|
will not keep the rid, while sleep2() does.
|
|
|
|
Examples:
|
|
// 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.
|
|
|
|
progressbar_unit works only for PACKETVER >= 20130821
|
|
The progressbar will show on the given unit id but it will not
|
|
put the unit in timeout (the progressbar would be just an animation).
|
|
if GID is not given use the attached player.
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
5.1 - End of Time-related commands
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
*loudhailer("<message>"{, "<color>"})
|
|
|
|
Announces a colored text in '<char_name> Shouts : <message>' format.
|
|
<color> must be a string in "RRGGBB" format. If <color> is omitted,
|
|
white ("FFFFFF") will be used.
|
|
This command is specially created for the Megaphone_ item (12221),
|
|
but will work in NPCs, too.
|
|
|
|
---------------------------------------
|
|
|
|
*announce("<text>", <flag>{, <fontColor>{, <fontType>{, <fontSize>{, <fontAlign>{, <fontY>}}}}})
|
|
|
|
This command will broadcast a message to all or most players, similar to
|
|
@kami/@kamib GM commands.
|
|
|
|
announce("This will be shown to everyone at all in yellow.", bc_all);
|
|
|
|
The region the broadcast is heard in (target), source of the broadcast and
|
|
the color the message will come up as is determined by the flags.
|
|
|
|
The flag values are coded as constants in doc/constants_(pre-)re.md to make them
|
|
easier to use.
|
|
|
|
Target flags:
|
|
- bc_all: Broadcast message is sent server-wide (default).
|
|
- bc_map: Message is sent to everyone in the same map as the source of
|
|
the broadcast (see below).
|
|
- bc_area: Message is sent to players in the vicinity of the source.
|
|
- bc_self: Message is sent only to current player.
|
|
You cannot use more than one target flag.
|
|
|
|
Source flags:
|
|
- bc_pc: Broadcast source is the attached player (default).
|
|
- bc_npc: Broadcast source is the NPC, not the player attached to the
|
|
script (useful when a player is not attached or the message
|
|
should be sent to those nearby the NPC).
|
|
You cannot use more than one source flag.
|
|
|
|
Special flags:
|
|
- bc_yellow:Broadcast will be displayed in yellow color (default).
|
|
- bc_blue: Broadcast will be displayed in blue color.
|
|
- bc_woe: Indicates that this broadcast is 'WoE Information' that can
|
|
be disabled client-side.
|
|
Due to the way client handles broadcasts, it is impossible to set both
|
|
bc_blue and bc_woe.
|
|
|
|
The optional parameters allow usage of broadcasts in custom colors,
|
|
font-weights, sizes etc. If any of the optional parameters is used,
|
|
special flag is ignored. Optional parameters may not work well (or at all)
|
|
depending on a game client used.
|
|
|
|
The color parameter is a single number which can be in hexadecimal
|
|
notation. C_ constant can also be used for color effects, see the full list
|
|
of the available ones in 'db/constants.conf' under 'C_'.
|
|
|
|
For example:
|
|
announce("This announcement will be shown to everyone in green.", bc_all, 0x00FF00);
|
|
Will display a global announce in green. The color format is in RGB
|
|
(0xRRGGBB).
|
|
|
|
Another example:
|
|
announce("This announcement will shown to everyone in purple.", bc_all, C_PURPLE);
|
|
|
|
In official scripts only two font-weights (types) are used:
|
|
- normal (FW_NORMAL = 400, default),
|
|
- bold (FW_BOLD = 700).
|
|
|
|
Default font size is 12.
|
|
|
|
Using this for private messages to players is probably not that good an
|
|
idea, but it can be used instead in NPCs to "preview" an announce.
|
|
|
|
// This will be a private message to the player using the NPC that
|
|
// made the announcement
|
|
announce("This is my message just for you", bc_blue|bc_self);
|
|
|
|
// This will be shown on everyones screen that is in sight of the NPC.
|
|
announce("This is my message just for you people here", bc_npc|bc_area);
|
|
|
|
---------------------------------------
|
|
|
|
*mapannounce("<map name>", "<text>", <flag>{, <fontColor>{, <fontType>{, <fontSize>{, <fontAlign>{, <fontY>}}}}}})
|
|
|
|
This command will work like announce() but will only broadcast to
|
|
characters currently residing on the specified map. The flag and optional
|
|
parameters parameters are the same as in announce(), but target and source
|
|
flags are ignored.
|
|
|
|
---------------------------------------
|
|
|
|
*areaannounce("<map name>", <x1>, <y1>, <x2>, <y2>, "<text>", <flag>{, <fontColor>{, <fontType>{, <fontSize>{, <fontAlign>{, <fontY>}}}}}})
|
|
|
|
This command works like 'announce' but will only broadcast to characters
|
|
residing in the specified x1/y1-x2/y2 rectangle on the map given. The
|
|
flags and optional parameters are the same as in announce(), but target
|
|
and source flags are ignored.
|
|
|
|
areaannounce("prt_church", 0, 0, 350, 350, "God's in his heaven, all right with the world", 0);
|
|
|
|
---------------------------------------
|
|
|
|
*callshop("<name>", <option>)
|
|
|
|
These are a series of commands used to create dynamic shops.
|
|
The callshop() function calls an invisible shop (FAKE_NPC) as if the player
|
|
clicked on it.
|
|
|
|
For the options on callShop:
|
|
0 = The normal window (buy, sell and cancel)
|
|
1 = The buy window
|
|
2 = The sell window
|
|
|
|
Example:
|
|
|
|
//Will call the shop named DaShop and opens the buy menu.
|
|
callshop("DaShop", 1);
|
|
|
|
|
|
The shop which is called by callshop() (as long as an npcshop* command is
|
|
executed from that NPC (see note 1)) will trigger the labels OnBuyItem and
|
|
OnSellitem. These labels can take over handling for relatively the buying
|
|
of items from the shop and selling the items to a shop. Via these labels
|
|
you can customize the way an item is bought or sold by a player.
|
|
|
|
In the OnBuyItem, two arrays are filled (@bought_nameid and
|
|
@bought_quantity) with information about the name id (item id) sold
|
|
and the amount sold of it. Same goes for the OnSellItem label, only the
|
|
variables are named different (@sold_nameid, @sold_quantity, @sold_refine,
|
|
@sold_attribute, @sold_identify, @sold_card1, @sold_card2, @sold_card3,
|
|
@sold_card4, @sold_opt_id1~5, @sold_opt_val1~5, @sold_opt_param1~5).
|
|
An example on a shop comes with Hercules, and can be found
|
|
in the doc/sample/npc_dynamic_shop.txt file.
|
|
|
|
This example shows how to use the labels and their set variables to create
|
|
a dynamic shop.
|
|
|
|
Note 1: These labels will only be triggered if a npcshop* command is
|
|
executed, this is because these commands set a special data on the shop
|
|
NPC, named master_nd in the source.
|
|
The OnSellItem and OnBuyItem are triggered in the NPC whose master_nd is
|
|
given in the shop.
|
|
|
|
---------------------------------------
|
|
|
|
*npcshopitem("<name>", <item id>, <price>{, <item id>, <price>{, <item id>, <price>{, ...}}})
|
|
|
|
This command lets you override the contents of an existing NPC shop or
|
|
cashshop. The current sell list will be wiped, and only the items
|
|
specified with the price specified will be for sale.
|
|
|
|
The function returns true if shop was updated successfully, or false if not found.
|
|
|
|
Note that you cannot use -1 to specify default selling price!
|
|
|
|
---------------------------------------
|
|
|
|
*npcshopadditem("<name>", <item id>, <price>{, <item id>, <price>{, <item id>, <price>{, ...}}})
|
|
|
|
This command will add more items at the end of the selling list for the
|
|
specified NPC shop or cashshop. If you specify an item already for sell,
|
|
that item will appear twice on the sell list.
|
|
|
|
The function returns true if shop was updated successfully, or false if not found.
|
|
|
|
Note that you cannot use -1 to specify default selling price!
|
|
|
|
---------------------------------------
|
|
|
|
*npcshopdelitem("<name>", <item id>{, <item id>{, <item id>{, ...}}})
|
|
|
|
This command will remove items from the specified NPC shop or cashshop.
|
|
If the item to remove exists more than once on the shop, all instances
|
|
will be removed.
|
|
|
|
Note that the function returns 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 optional parameter specifies whether to attach (true) or detach (false)
|
|
from the shop (the default is to attach). Note that detaching will detach
|
|
any NPC attached to the shop, even if it's from another script, while
|
|
attaching will override any other script that may be already attached.
|
|
|
|
The function returns false if the shop was not found, true otherwise.
|
|
|
|
---------------------------------------
|
|
|
|
*waitingroom("<chatroom name>", <limit>{, <event label>, <trigger>, <required zeny>, <min lvl>, <max lvl>, "<NPC Object Name>"})
|
|
|
|
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".
|
|
|
|
waitingroom("Disco - Waiting Room", 8, "Bouncer::OnStart", 7);
|
|
|
|
// 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".
|
|
|
|
waitingroom("Party - Waiting Room", 8, "Bouncer::OnStart", 7, 5000, 50, 99);
|
|
|
|
Creating a waiting room does not stop the execution of the script and it
|
|
will continue to the next line.
|
|
|
|
For more examples see the 2-1 and 2-2 job quest scripts which make
|
|
extensive use of waiting rooms.
|
|
|
|
---------------------------------------
|
|
|
|
*delwaitingroom({"<NPC object name"})
|
|
|
|
This command will delete a waiting room. If no parameter is given, it will
|
|
delete a waiting room attached to the NPC object running this command, if
|
|
it is, it will delete a waiting room owned by another NPC object. This is
|
|
the only way to get rid of a waiting room, nothing else will cause it to
|
|
disappear.
|
|
|
|
It's not clear what happens to a waiting room if the NPC is disabled with
|
|
disablenpc(), by the way.
|
|
|
|
---------------------------------------
|
|
|
|
*enablewaitingroomevent({"<NPC object name>"})
|
|
*disablewaitingroomevent({"<NPC object name>"})
|
|
|
|
This will enable and disable triggering the waiting room event (see
|
|
waitingroom()) respectively. Optionally giving an NPC object name will do
|
|
that for a specified NPC object. The chat room will not disappear when
|
|
triggering is disabled and enabled in this manner and players will not be
|
|
kicked out of it. Enabling a chat room event will also cause it to
|
|
immediately check whether the number of users in it exceeded the trigger
|
|
amount and trigger the event accordingly.
|
|
|
|
Normally, whenever a waiting room was created to make sure that only one
|
|
character is, for example, trying to pass a job quest trial, and no other
|
|
characters are present in the room to mess up the script.
|
|
|
|
---------------------------------------
|
|
|
|
*getwaitingroomstate(<information type>{, "<NPC object name>"})
|
|
|
|
This function will return information about the waiting room state for the
|
|
attached waiting room or for a waiting room attached to the specified NPC
|
|
if any.
|
|
|
|
The valid information types are:
|
|
|
|
0 - Number of users currently in the waiting room
|
|
$@chatmembers[] - list of user account_id
|
|
1 - Maximum number of users allowed.
|
|
2 - Will return 1 if the waiting room has a trigger set.
|
|
0 otherwise.
|
|
3 - Will return 1 if the waiting room is currently disabled.
|
|
0 otherwise.
|
|
4 - The Title of the waiting room (string)
|
|
5 - Password of the waiting room, if any. Pointless, since there is no
|
|
way to set a password on a waiting room right now.
|
|
16 - Event name of the waiting room (string)
|
|
32 - Whether or not the waiting room is full.
|
|
33 - Whether the amount of users in the waiting room is higher than the
|
|
trigger number.
|
|
34 - Minimum Base Level to enter waiting room.
|
|
35 - Maximum Base Level to enter waiting room.
|
|
36 - Minimum Zeny to enter waiting room.
|
|
|
|
---------------------------------------
|
|
|
|
*warpwaitingpc("<map name>", <x>, <y>{, <number of people>{, "<NPC object name>"}})
|
|
|
|
This command will warp the amount of characters equal to the trigger
|
|
number of the waiting room chat attached to the NPC object running this
|
|
command to the specified map and coordinates, kicking them out of the
|
|
chat. Those waiting the longest will get warped first. It can also do a
|
|
random warp on the same map ("Random" instead of map name) and warp to the
|
|
save point ("SavePoint").
|
|
|
|
The list of characters to warp is taken from the list of the chat room
|
|
members. Those not in the chat room will not be considered even if they
|
|
are talking to the NPC in question. If the number of people is given,
|
|
exactly this much people will be warped.
|
|
|
|
This command can also keep track of who just got warped. It does this by
|
|
setting special variables:
|
|
|
|
$@warpwaitingpc[] is an array containing the account_id numbers of the
|
|
characters who were just warped.
|
|
$@warpwaitingpcnum contains the number of the character it just warped.
|
|
|
|
See also 'getpartymember' for advice on what to do with those variables.
|
|
|
|
The obvious way of using this effectively would be to set up a waiting
|
|
room for two characters to be warped onto a random PVP map for a
|
|
one-on-one duel, for example.
|
|
|
|
---------------------------------------
|
|
|
|
*waitingroomkick({"<NPC object name>"{,"<player name>"|<account_id>}})
|
|
|
|
This command kicks target player(s) out of a waiting room chat of specific NPC if any.
|
|
|
|
Example 1:
|
|
// This will kick all players in the waitingroom
|
|
waitingroomkick();
|
|
|
|
Example 2:
|
|
// Kick the last player enter the waitingroom
|
|
.@num = getwaitingroomstate(0);
|
|
waitingroomkick(strnpcinfo(NPC_NAME), $@chatmembers[.@num - 1]);
|
|
|
|
---------------------------------------
|
|
|
|
*setmapflagnosave("<map name>", "<alternate map name>", <x>, <y>)
|
|
|
|
This command sets the 'nosave' flag for the specified map and also gives
|
|
an alternate respawn-upon-relogin point.
|
|
|
|
It does not make a map impossible to make a save point on as you would
|
|
normally think, savepoint() will still work. It will, however, make the
|
|
specified map kick the reconnecting players off to the alternate map given
|
|
to the coordinates specified.
|
|
|
|
---------------------------------------
|
|
|
|
*setmapflag("<map name>", <flag>{, <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_(pre-)re.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.
|
|
|
|
---------------------------------------
|
|
|
|
*removemapflag("<map name>", <flag>)
|
|
|
|
This command removes a mapflag from a specified map.
|
|
See setmapflag() for examples of mapflags.
|
|
|
|
---------------------------------------
|
|
|
|
*getmapflag("<map name>", <flag>)
|
|
|
|
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.
|
|
|
|
---------------------------------------
|
|
|
|
*setbattleflag("<battle flag>", <value>)
|
|
*getbattleflag("<battle flag>")
|
|
|
|
Sets or gets the value of the given battle flag.
|
|
Battle flags are the flags found in the conf/map/battle/*.conf files and is
|
|
also used in Lupus' variable rates script.
|
|
|
|
Examples:
|
|
|
|
// Will set the base experience rate to 20x (2000%)
|
|
setbattleflag("base_exp_rate", 2000);
|
|
|
|
// Will return the value of the base experience rate (when used after the
|
|
// above example, it would print 2000).
|
|
mes(getbattleflag("base_exp_rate"));
|
|
|
|
---------------------------------------
|
|
|
|
*warpportal(<x>, <y>, "<mapname>", <x>, <y>)
|
|
|
|
Creates a warp Portal as if a acolyte class character did it.
|
|
The first x and y is the place of the warp portal on the map where the NPC
|
|
is on the mapname and second x and y is the target area of the warp portal.
|
|
|
|
Examples:
|
|
|
|
// Will create a warp portal on the NPC's map at 150,150
|
|
// leading to prontera, coords 150,180.
|
|
warpportal(150, 150, "prontera", 150, 180);
|
|
|
|
---------------------------------------
|
|
|
|
*mapwarp("<from map>", "<to map>", <x>, <y>{, <type>, <ID>})
|
|
|
|
This command will collect all characters located on the From map and warp
|
|
them wholesale to the same point on the To map, or randomly distribute
|
|
them there if the coordinates are zero. "Random" is understood as a
|
|
special To map name and will mean randomly shuffling everyone on the same
|
|
map.
|
|
|
|
Optionally, a type and ID can be specified. Available types are:
|
|
|
|
0 - Everyone
|
|
1 - Guild
|
|
2 - Party
|
|
|
|
Example:
|
|
|
|
// Will warp all members of guild with ID 63 on map prontera to alberta.
|
|
mapwarp("prontera", "alberta", 150, 150, 1, 63);
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
5.2 - Guild-Related Commands
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
*maprespawnguildid("<map name>", <guild id>, <flag>)
|
|
|
|
This command goes through the specified map and for each player and
|
|
monster found there does stuff.
|
|
|
|
Flag is a bit-mask (add up numbers to get effects you want)
|
|
1 - warp all guild members to their save points.
|
|
2 - warp all non-guild members to their save points.
|
|
4 - remove all monsters which are not guardian or Emperium.
|
|
|
|
Flag 7 will, therefore, mean 'wipe all mobs but guardians and the Emperium
|
|
and kick all characters out', which is what the official scripts do upon
|
|
castle surrender. Upon start of WoE, the scripts do 2 (warp 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.
|
|
|
|
For examples, check the WoE scripts in the distribution.
|
|
|
|
---------------------------------------
|
|
|
|
*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 is commonly used in official guildwar scripts with a function call
|
|
which returns a guild id:
|
|
|
|
// This will change the emblem on the flag to that of the guild that owns
|
|
// "guildcastle"
|
|
|
|
flagemblem(getcastledata("guildcastle", 1));
|
|
|
|
---------------------------------------
|
|
|
|
*guardian("<map name>", <x>, <y>, "<name to show>", <mob id>{, "<event label>"{, <guardian index>}})
|
|
|
|
This command is roughly equivalent to monster(), but is meant to be used
|
|
with castle guardian monsters and will only work with them. It will set
|
|
the guardian characteristics up according to the castle's investment
|
|
values and otherwise set the things up that only castle guardians need.
|
|
|
|
Returns the id of the mob or 0 if an error occurred.
|
|
When 'guardian index' isn't supplied it produces a temporary guardian.
|
|
Temporary guardians are not saved with the castle and can't be accessed by
|
|
guardianinfo.
|
|
|
|
---------------------------------------
|
|
|
|
*guardianinfo("<map name>", <guardian number>, <type>)
|
|
|
|
This function will return various info about the specified guardian, or -1
|
|
if it fails for some reason. It is primarily used in the castle manager
|
|
NPC.
|
|
|
|
Map name and guardian number (value between 0 and 7) define the target.
|
|
Type indicates what information to return:
|
|
0 - visibility (whether the guardian is installed or not)
|
|
1 - max. hp
|
|
2 - current hp
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
5.2 - End of Guild-Related Commands
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
*npcspeed(<speed value>)
|
|
*npcwalkto(<x>, <y>)
|
|
*npcstop()
|
|
|
|
These commands will make the NPC object in question move around the map.
|
|
As they currently are, they are a bit buggy and are not useful for much
|
|
more than making an NPC move randomly around the map.
|
|
|
|
npcspeed() will set the NPCs walking speed to a specified value. As in the
|
|
@speed GM command, 200 is the slowest possible speed while 0 is the
|
|
fastest possible (instant motion). 100 is the default character walking
|
|
speed.
|
|
npcwalkto() will start the NPC sprite moving towards the specified
|
|
coordinates on the same map as it is currently on. 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 with this.
|
|
|
|
---------------------------------------
|
|
|
|
*movenpc("<NPC name>", <x>, <y>{, <dir>})
|
|
|
|
This command looks like the npcwalktoxy function, but is a little different.
|
|
|
|
While npcwalktoxy just makes the NPC 'walk' to the coordinates given
|
|
(which sometimes gives problems if the path isn't a straight line without
|
|
objects), this command just moves the NPC. It basically warps out and in
|
|
on the current and given spot. Direction can be used to change the NPC's
|
|
facing direction.
|
|
|
|
Example:
|
|
|
|
// This will move Bugga from to the coordinates 100,20 (if those
|
|
// coordinates are legit).
|
|
movenpc("Bugga", 100, 20);
|
|
|
|
---------------------------------------
|
|
|
|
*navigateto("<map>"{,<x>,<y>,<flag>,<hide_window>,<monster_id>,<char_id>});
|
|
|
|
Generates a navigation for attached or specified character. Requires client
|
|
2011-10-10aRagEXE or newer.
|
|
|
|
The flag specifies how the client will calculate the specific route.
|
|
|
|
Valid flags are:
|
|
NAV_NONE - No services
|
|
NAV_AIRSHIP_ONLY - Airship only
|
|
NAV_SCROLL_ONLY - Scroll only
|
|
NAV_AIRSHIP_AND_SCROLL - Airship and Scroll
|
|
NAV_KAFRA_ONLY - Kafra only
|
|
NAV_KAFRA_AND_AIRSHIP - Kafra and Airship
|
|
NAV_KAFRA_AND_SCROLL - Kafra and Scroll
|
|
NAV_ALL - All services
|
|
|
|
When flag is not specified, the default value is NAV_KAFRA_AND_AIRSHIP.
|
|
|
|
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
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
*consolemes("<type>", "<format string>"{,<param>{, ...}})
|
|
|
|
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.
|
|
|
|
List of available <type> are:
|
|
CONSOLEMES_DEBUG = 0
|
|
CONSOLEMES_ERROR = 1
|
|
CONSOLEMES_WARNING = 2
|
|
CONSOLEMES_INFO = 3
|
|
CONSOLEMES_STATUS = 4
|
|
CONSOLEMES_NOTICE = 5
|
|
|
|
Example:
|
|
|
|
// Displays "NAME has clicked me!" in the map-server window.
|
|
consolemes(CONSOLEMES_DEBUG, "%s has clicked me!", strcharinfo(PC_NAME));
|
|
|
|
consolemes(CONSOLEMES_DEBUG, "\033[0;32mHello World"); // supports ANSI escape sequences
|
|
|
|
---------------------------------------
|
|
|
|
*logmes("<message>"{, <log type>})
|
|
|
|
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.
|
|
|
|
Log types are:
|
|
|
|
LOGMES_NPC - log to the 'npclog' table (Default)
|
|
LOGMES_ATCOMMAND - log to the 'atcommandlog' table
|
|
|
|
Example:
|
|
|
|
logmes("foobar");
|
|
logmes("foobar", LOGMES_ATCOMMAND);
|
|
|
|
---------------------------------------
|
|
|
|
*globalmes("<message>"{, "<NPC name>"})
|
|
|
|
This command will send a message to the chat window of all currently
|
|
connected characters.
|
|
|
|
If NPC name is specified, the message will be sent as if the sender would
|
|
be the NPC with the said name.
|
|
|
|
---------------------------------------
|
|
|
|
*channelmes("<#channel>", "<message>")
|
|
|
|
This command will send a message to the specified chat channel.
|
|
|
|
The sent message will not include any character's names.
|
|
|
|
For special channels, such as #map and #ally, the attached RID's map or guild
|
|
will be used.
|
|
|
|
If the channel doesn't exist (or, in the case of a character-specific channel,
|
|
no RID is attached), false will be returned. In case of success, true is
|
|
returned.
|
|
|
|
---------------------------------------
|
|
|
|
*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>")
|
|
|
|
Removes a channel handler added by addchannelhandler()
|
|
|
|
---------------------------------------
|
|
*rand(<number>{, <number>})
|
|
|
|
This function returns a number ...
|
|
(if you specify one) ... randomly positioned between 0 and the number you
|
|
specify -1.
|
|
(if you specify two) ... randomly positioned between the two numbers you
|
|
specify.
|
|
|
|
rand(10) would result in 0, 1, 2, 3, 4, 5, 6, 7, 8 or 9
|
|
rand(0, 9) would result in 0, 1, 2, 3, 4, 5, 6, 7, 8 or 9
|
|
rand(2, 5) would result in 2, 3, 4 or 5
|
|
|
|
---------------------------------------
|
|
|
|
*viewpoint(<action>, <x>, <y>, <point number>, <color>)
|
|
|
|
This command will mark places on the mini map in the client connected to
|
|
the invoking character. It uses the normal X and Y coordinates from the
|
|
main map. The colors of the marks are defined using a hexadecimal number,
|
|
same as the ones used to color text in mes() output, but are written as
|
|
hexadecimal numbers in C. (They look like 0x<six numbers>.)
|
|
|
|
Action is what you want to do with a point, 1 will set it, while 2 will
|
|
clear it. 0 will also set it, but automatically removes the point after 15
|
|
seconds.
|
|
Point number is the number of the point - you can have several. If more
|
|
than one point is drawn at the same coordinates, they will cycle, which
|
|
can be used to create flashing marks.
|
|
|
|
// This command will show a mark at coordinates X 30 Y 40, is mark
|
|
// number 1, and will be red.
|
|
|
|
viewpoint(1, 30, 40, 1, 0xFF0000);
|
|
|
|
This will create three points:
|
|
|
|
viewpoint(1, 30, 40, 1, 0xFF0000);
|
|
viewpoint(1, 35, 45, 2, 0xFF0000);
|
|
viewpoint(1, 40, 50, 3, 0xFF0000);
|
|
|
|
And this is how you remove them:
|
|
|
|
viewpoint(2, 30, 40, 1, 0xFF0000);
|
|
viewpoint(2, 35, 45, 2, 0xFF0000);
|
|
viewpoint(2, 40, 50, 3, 0xFF0000);
|
|
|
|
The client determines what it does with the points entirely, the server
|
|
keeps no memory of where the points are set whatsoever.
|
|
|
|
---------------------------------------
|
|
|
|
*cutin("<filename>", <position>)
|
|
|
|
This command will display a picture, usually an NPC illustration, also
|
|
called cutin, for the currently attached client. The position parameter
|
|
determines the placement of the illustration and takes following values:
|
|
|
|
0 - bottom left corner
|
|
1 - bottom middle
|
|
2 - bottom right corner
|
|
3 - middle of screen in a movable window with an empty title bar
|
|
4 - middle of screen without the window header, but still movable
|
|
|
|
The picture is read from data\texture\유저인터페이스\illust, from both the
|
|
GRF archive and data folder, and is required to be a bitmap. The file
|
|
extension .bmp can be omitted. Magenta color (#ff00ff) is considered
|
|
transparent. There is no limit placed on the size of the illustrations
|
|
by the client, although loading of large pictures (about 700x700 and
|
|
larger) causes the client to freeze shortly (lag). Typically the size is
|
|
about 320x480. New illustrations can be added by just putting the new file
|
|
into the location above.
|
|
|
|
The client is able to display only one cutin at the same time and each new
|
|
one will cause the old one to disappear. To delete the currently displayed
|
|
illustration without displaying a new one, an empty file name and position
|
|
255 must be used.
|
|
|
|
// Displays the Comodo Kafra illustration in lower right corner.
|
|
cutin("kafra_07", 2);
|
|
|
|
// Typical way to end a script, which displayed an illustration during a
|
|
// dialog with a player.
|
|
mes("See you.");
|
|
close2();
|
|
cutin("", 255);
|
|
end;
|
|
|
|
---------------------------------------
|
|
|
|
*pet(<pet id>)
|
|
|
|
This command is used in all the item scripts for taming items. Running
|
|
this command will make the pet catching cursor appear on the client
|
|
connected to the invoking character, usable on the monsters with the
|
|
specified pet ID number. It will still work outside an item script.
|
|
|
|
A full list of pet IDs can be found inside 'db/(pre-)re/pet_db.conf'
|
|
|
|
---------------------------------------
|
|
|
|
*emotion(<emotion number>{, <target>{, "<target name>"}})
|
|
|
|
This command makes an object display an emotion sprite above their own as
|
|
if they were doing that emotion. For a full list of emotion numbers, see
|
|
'doc/constants_(pre-)re.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.
|
|
|
|
Target name parameter allows to display emotion on top of other NPC/PC
|
|
without event labels. If specified name is not found, command does nothing.
|
|
|
|
---------------------------------------
|
|
|
|
*soundeffect("<effect filename>", <type>{, <term>})
|
|
*soundeffectall("<effect filename>", <type>{, "<map name>"}{, <x0>, <y0>, <x1>, <y1>})
|
|
*soundeffectall2("<effect filename>", <type>{, <term>{, "<map name>"}}{, <x0>, <y0>, <x1>, <y1>})
|
|
|
|
These two commands will play a sound effect to either the invoking
|
|
character only (soundeffect()) or multiple characters (soundeffectall()).
|
|
If the running code does not have an object ID (a 'floating' NPC) or is
|
|
not running from an NPC object at all (an item script) the sound will be
|
|
centered on the character who's RID got attached to the script, if any.
|
|
If it does, it will be centered on that object. (an NPC sprite)
|
|
|
|
Effect filename is the filename in a GRF. It must have the .wav extension.
|
|
|
|
Possible values for type:
|
|
PLAY_SOUND_ONCE - play sound file once (default)
|
|
PLAY_SOUND_REPEAT - play sound in repeat mode. Term parameter set delay before next sound play.
|
|
PLAY_SOUND_STOP - stop repeated sound. Not stop already playing sound but terminate future repeats.
|
|
|
|
Term parameter make sense only for type PLAY_SOUND_REPEAT.
|
|
|
|
The sound files themselves must be in the PCM format, and file names
|
|
should also have a maximum length of 23 characters including the .wav
|
|
extension:
|
|
|
|
soundeffect("1234567890123456789.wav", 0); // will play the soundeffect
|
|
soundeffect("12345678901234567890.wav", 0); // throws gravity error
|
|
|
|
You can add your own effects this way, naturally.
|
|
|
|
---------------------------------------
|
|
|
|
*playbgm("<BGM filename>"{, <type>})
|
|
*playbgmall("<BGM filename>"{, "<map name>"{, <x0>, <y0>, <x1>, <y1>}})
|
|
*playbgmall2("<BGM filename>"{, <type>{, "<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(), playbgmall2()).
|
|
|
|
BGM filename is the filename in /BGM/ folder. It has to be in .mp3
|
|
extension, but it's not required to specify the extension in the script.
|
|
|
|
type set play type and can be:
|
|
PLAY_BGM_LOOP - play music in loop
|
|
PLAY_BGM_ONCE - play music once
|
|
PLAY_BGM_STOP - stop music
|
|
|
|
Parameter type make sense only for clients main 20220504 and newer.
|
|
|
|
If coordinates are omitted, BGM will be broadcasted on the entire map. If
|
|
the map name is also omitted the BGM will be played for the entire server.
|
|
|
|
You can add your own BGMs this way, naturally.
|
|
|
|
---------------------------------------
|
|
|
|
*pvpon("<map name>")
|
|
*pvpoff("<map name>")
|
|
|
|
These commands will turn PVP mode for the specified maps on and off.
|
|
Beside setting the flags referred to in setmapflag(), pvpon() will also
|
|
create a PVP timer and ranking as will @pvpon GM command do.
|
|
|
|
---------------------------------------
|
|
|
|
*atcommand("<command>")
|
|
|
|
This command will run the given command line exactly as if it was typed in
|
|
from the keyboard by the player connected to the invoking character, and
|
|
that character belonged to an account which had GM level 99.
|
|
|
|
// This will ask the invoker for a character name and then use the
|
|
// '@nuke' GM command on them, killing them mercilessly.
|
|
input(.@player$);
|
|
atcommand("@nuke "+.@player$);
|
|
|
|
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.
|
|
|
|
The commands can also run without an attached rid.
|
|
|
|
// This would do the same as above, but now
|
|
// it doesn't need a player attached by default.
|
|
charcommand("#option 0 0 0 Roy");
|
|
|
|
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.
|
|
|
|
---------------------------------------
|
|
|
|
*bindatcmd("command", "<NPC object name>::<event label>"{, <group level>, <group level char>, <log>})
|
|
|
|
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.
|
|
|
|
The following variables are set upon execution:
|
|
.@atcmd_command$ = The name of the @command used.
|
|
.@atcmd_parameters$[] = Array containing the given parameters,
|
|
starting from an index of 0.
|
|
.@atcmd_numparameters = The number of parameters defined.
|
|
|
|
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.
|
|
|
|
- script atcmd_example FAKE_NPC,{
|
|
OnInit:
|
|
bindatcmd("test", strnpcinfo(NPC_NAME_UNIQUE)+"::OnAtcommand");
|
|
end;
|
|
OnAtcommand:
|
|
specialeffect(EF_ANGEL2, AREA, playerattached());
|
|
end;
|
|
}
|
|
|
|
Parameter splitting example:
|
|
@mycommand
|
|
.@atcmd_numparameters -> 0
|
|
.@atcmd_parameters$ -> { }
|
|
@mycommand<space><space>
|
|
.@atcmd_numparameters -> 0
|
|
.@atcmd_parameters$ -> { }
|
|
@mycommand<space>foo
|
|
.@atcmd_numparameters -> 1
|
|
.@atcmd_parameters$ -> { "foo" }
|
|
@mycommand<space><space>foo
|
|
.@atcmd_numparameters -> 1
|
|
.@atcmd_parameters$ -> { "foo" }
|
|
@mycommand<space>foo<space>bar
|
|
.@atcmd_numparameters -> 2
|
|
.@atcmd_parameters$ -> { "foo", "bar" }
|
|
@mycommand<space>foo<space><space>bar
|
|
.@atcmd_numparameters -> 3
|
|
.@atcmd_parameters$ -> { "foo", "", "bar" }
|
|
@mycommand<space>foo<space>
|
|
.@atcmd_numparameters -> 2
|
|
.@atcmd_parameters$ -> { "foo", "" }
|
|
@mycommand<space>foo<space><space>
|
|
.@atcmd_numparameters -> 3
|
|
.@atcmd_parameters$ -> { "foo", "", "" }
|
|
|
|
The called event label needs to take care of joining arguments together, in
|
|
case it expects spaces. For example:
|
|
|
|
- script atcmd_example FAKE_NPC,{
|
|
OnInit:
|
|
bindatcmd("test", strnpcinfo(NPC_NAME_UNIQUE)+"::OnAtcommand");
|
|
end;
|
|
OnAtcommand:
|
|
// This command expects a character name (that may contain spaces) as
|
|
// the only parameter.
|
|
.@name$ = "";
|
|
for (.@i = 0; .@i < .@atcmd_numparameters; ++.@i) {
|
|
.@name$ += (.@i > 0 ? " " : "") + .@atcmd_parameters$[.@i];
|
|
}
|
|
dispbottom("The specified name is: '" + .@name$ + "'");
|
|
end;
|
|
}
|
|
|
|
---------------------------------------
|
|
|
|
*add_group_command("<command>", <group id>, <use on self>, <use on other>)
|
|
|
|
Allows to explicitly change the command permissions for a specific group.
|
|
|
|
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")
|
|
|
|
This command will unbind a NPC event label from an atcommand.
|
|
|
|
---------------------------------------
|
|
|
|
*can_use_command("<command>"{, <account id>})
|
|
|
|
Checks if the attached or specified player can use the specified
|
|
atcommand and returns true or false accordingly. Works for both
|
|
built-in atcommands and custom atcommands.
|
|
|
|
---------------------------------------
|
|
|
|
*has_permission(<permission>{, <account id>})
|
|
*has_permission("<permission>"{, <account id>})
|
|
|
|
Check if the attached or specified player has the specified permission
|
|
and returns true or false accordingly. See doc/permissions.md for
|
|
details about permissions.
|
|
|
|
Valid <permission> are:
|
|
|
|
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
|
|
}
|
|
|
|
It is also possible to pass a string for plugin permissions:
|
|
|
|
if (has_permission("show_version")) {
|
|
//do something
|
|
}
|
|
|
|
** Passing a string is slower than passing a constant because
|
|
the engine has to loop through the array to find the permission.
|
|
In most cases you should use the PERM_ constants.
|
|
|
|
---------------------------------------
|
|
|
|
*unitskilluseid(<GID>, <skill id>, <skill lvl>{, <target id>})
|
|
*unitskilluseid(<GID>, "<skill name>", <skill lvl>{, <target id>})
|
|
*unitskillusepos(<GID>, <skill id>, <skill lvl>, <x>, <y>)
|
|
*unitskillusepos(<GID>, "<skill name>", <skill lvl>, <x>, <y>)
|
|
|
|
This is the replacement of the older commands, these use the same values
|
|
for GID as the other unit* commands (See 'GID').
|
|
|
|
Skill ID is the ID of the skill, skill level is the level of the skill.
|
|
For the position, the x and y are given in the unitskillusepos.
|
|
|
|
---------------------------------------
|
|
|
|
*npcskill(<skill id>, <skill lvl>, <stat point>, <NPC level>)
|
|
*npcskill("<skill name>", <skill lvl>, <stat point>, <NPC level>)
|
|
|
|
This command causes the attached NPC object to cast a skill on the
|
|
attached player. The skill will have no cast time or cooldown. The player
|
|
must be within the default skill range or the command will fail silently.
|
|
|
|
The "stat point" parameter temporarily sets all NPC stats to the given
|
|
value, and "NPC level" is the temporary level of the NPC (used in some
|
|
skills). Neither value can be greater than the max level defined in
|
|
config, and will not work properly if the NPC has a mob sprite.
|
|
|
|
// Casts Level 10 Heal on the attached player, calculated with
|
|
// all stats 99 and base level 60.
|
|
npcskill(AL_HEAL, 10, 99, 60);
|
|
|
|
---------------------------------------
|
|
|
|
*setnpcdistance(<distance>)
|
|
|
|
This command can reduce distance from where npc can be clicked.
|
|
Useful to use from OnInit event.
|
|
|
|
// Set distance to one tile on server load
|
|
OnInit:
|
|
setnpcdistance(1);
|
|
|
|
---------------------------------------
|
|
|
|
*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:
|
|
|
|
- script DayNight FAKE_NPC,{
|
|
OnClock0600:
|
|
day();
|
|
end;
|
|
OnInit:
|
|
// setting correct mode upon server start-up
|
|
if (gettime(GETTIME_HOUR) >= 6 && gettime(GETTIME_HOUR) < 18)
|
|
end;
|
|
OnClock1800:
|
|
night();
|
|
end;
|
|
}
|
|
|
|
This script allows to emulate the day/night cycle as the server does, but
|
|
also allows triggering additional effects upon change, like announces,
|
|
gifts, etc.
|
|
The day/night cycle set by configuration should be disabled when this
|
|
script is used.
|
|
|
|
---------------------------------------
|
|
|
|
*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, visit the website bellow:
|
|
|
|
https://www.regular-expressions.info/
|
|
|
|
There is also a website where you can try regular expressions in real time:
|
|
https://regexr.com/
|
|
|
|
Additionally, the following temporary variables will be filled (unless the
|
|
command is invoked as '~!'):
|
|
|
|
- $@regexmatchcount: The number of matches detected, including any
|
|
parenthesized capture-groups.
|
|
- $@regexmatch$[0]: The part of <string> That matched the full <regex> pattern.
|
|
- $@regexmatch$[1 .. $@regexmatchcount]: The parts of <string> that matched
|
|
each of the parenthesized capture-groups in <pattern>.
|
|
|
|
A capture group is a part of a regex enclosed in (parentheses) in order to
|
|
store in a variable the part of the expression that was matched by that part of
|
|
the regex. For more details, see the links above, as this is not intended to be
|
|
a regex tutorial.
|
|
|
|
---------------------------------------
|
|
|
|
*defpattern(<set number>, "<regular expression pattern>", "<event label>")
|
|
*activatepset(<set number>)
|
|
*deactivatepset(<set number>)
|
|
*deletepset(<set number>)
|
|
|
|
They will make the NPC object listen for text spoken publicly by players
|
|
and match it against regular expression patterns, then trigger labels
|
|
associated with these regular expression patterns.
|
|
|
|
Patterns are organized into sets, which are referred to by a set number.
|
|
You can have multiple sets patterns, and multiple patterns may be active
|
|
at once. Numbers for pattern sets start at 1.
|
|
|
|
defpattern() will associate a given regular expression pattern with an
|
|
event label. This event will be triggered whenever something a player says
|
|
is matched by this regular expression pattern, if the pattern is currently
|
|
active.
|
|
|
|
activatepset() will make the pattern set specified active. An active
|
|
pattern will enable triggering labels defined with defpattern(), which
|
|
will not happen by default.
|
|
deactivatepset() will deactivate a specified pattern set. Giving -1 as a
|
|
pattern set number in this case will deactivate all pattern sets defined.
|
|
|
|
deletepset() will delete a pattern set from memory, so you can create a
|
|
new pattern set in its place.
|
|
|
|
For an example of this in use, see doc/sample/npc_test_pcre.txt
|
|
|
|
With this you could, for example, automatically punish players for asking
|
|
for Zeny in public places, or alternatively, automatically give them Zeny
|
|
instead if they want it so much.
|
|
|
|
---------------------------------------
|
|
|
|
*log10(<number>)
|
|
|
|
Returns log base 10 of the number.
|
|
|
|
Note: The value is truncated to integer.
|
|
|
|
Example:
|
|
.@i = log10(100); // .@i will be 2
|
|
|
|
---------------------------------------
|
|
|
|
*sqrt(<number>)
|
|
|
|
Returns square-root of number.
|
|
|
|
Note: The value is truncated to integer.
|
|
|
|
Example:
|
|
.@i = sqrt(25); // .@i will be 5
|
|
|
|
---------------------------------------
|
|
|
|
*distance(<x0>, <y0>, <x1>, <y1>)
|
|
|
|
Returns distance between 2 points.
|
|
|
|
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
|
|
|
|
---------------------------------------
|
|
|
|
*cap_value(<number>, <min>, <max>)
|
|
|
|
Returns the number but capped between <min> and <max>.
|
|
|
|
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>")
|
|
|
|
Returns the md5 checksum of a number or string.
|
|
|
|
Example:
|
|
mes md5(12345);
|
|
mes md5("12345"); // Will both display 827ccb0eea8a706c4c34a16891f84e7b
|
|
mes md5("qwerty");// Will display d8578edf8458ce06fbc5bb76a58c5ca4
|
|
|
|
---------------------------------------
|
|
|
|
*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
|
|
|
|
---------------------------------------
|
|
|
|
*query_sql("your MySQL query"{, <array variable>{, <array variable>{, ...}}})
|
|
*query_logsql("your MySQL query"{, <array variable>{, <array variable>{, ...}}})
|
|
|
|
Executes an SQL query. A 'select' query can fill array variables with up
|
|
to 128 rows of values, and will return the number of rows (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
|
|
|
|
---------------------------------------
|
|
|
|
*setitemscript(<item id>, <"{ new item script }">{, <type>})
|
|
|
|
Set a new script bonus to the Item. Very useful for game events.
|
|
You can remove an item's itemscript by leaving the itemscript argument
|
|
empty. Returns 1 on success, or 0 on fail (item_id not found or new item
|
|
script is invalid).
|
|
Type can optionally be used indicates which script to set (default is 0):
|
|
0 - Script
|
|
1 - OnEquip_Script
|
|
2 - OnUnequip_Script
|
|
|
|
Example:
|
|
|
|
setitemscript(Silver_Ring_, "{ if (isequipped(Santa's_Hat) == 0) end; if (getskilllv(AL_TELEPORT)) { skill(MC_IDENTIFY, 1); } else { skill(AL_TELEPORT, 1+isequipped(Santa's_Hat)); } }");
|
|
setitemscript(Silver_Ring_, "");
|
|
|
|
---------------------------------------
|
|
|
|
*atoi("<string>")
|
|
*axtoi("<string>")
|
|
*strtol("string", base)
|
|
|
|
These commands are used to convert strings to numbers. atoi() will
|
|
interpret given string as a decimal number (base 10), while axtoi()
|
|
interprets strings as hexadecimal numbers (base 16). strtol() lets
|
|
the user specify a base (valid range is between 2 and 36 inclusive,
|
|
or the special value0, which means auto-detection).
|
|
|
|
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:
|
|
|
|
.@var = atoi("11"); // Sets .@var to 11
|
|
.@var = axtoi("FF"); // Sets .@var to 255
|
|
mes(axtoi("11")); // Displays 17 (1 = 1, 10 = 16)
|
|
.@var = strtol("11", 10); // Sets .@var to 11 (11 base 10)
|
|
.@var = strtol("11", 16); // Sets .@var to 17 (11 base 16)
|
|
.@var = strtol("11", 0); // Sets .@var to 11 (11 base 10, auto-detected)
|
|
.@var = strtol("0x11", 0); // Sets .@var to 17 (11 base 16, auto-detected because of the "0x" prefix)
|
|
.@var = strtol("011", 0); // Sets .@var to 9 (11 base 8, auto-detected because of the "0" prefix)
|
|
.@var = strtol("11", 2); // Sets .@var to 3 (binary 11)
|
|
|
|
---------------------------------------
|
|
|
|
*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:
|
|
|
|
//dothis(); will be executed ('Bloody Murderer' contains 'Blood').
|
|
if (compare("Bloody Murderer", "Blood"))
|
|
dothis();
|
|
//dothat(); will not be executed ('Blood butterfly' does not contain 'Bloody').
|
|
if (compare("Blood Butterfly", "Bloody"))
|
|
dothat();
|
|
|
|
---------------------------------------
|
|
|
|
*strcmp("<string>", "<string>")
|
|
|
|
This command compares two strings and is similar to strcmp in C.
|
|
|
|
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>)
|
|
|
|
This command checks if the given <argument> is a string (1),
|
|
an integer (0) or something else (2).
|
|
|
|
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>)
|
|
|
|
Returns char at specified index. If index is out of range, returns an
|
|
empty string.
|
|
|
|
Example:
|
|
|
|
charat("This is a string", 10); //returns "s"
|
|
|
|
---------------------------------------
|
|
|
|
*chr(<int>)
|
|
|
|
Returns a char from its ASCII value.
|
|
|
|
Example:
|
|
|
|
chr(99); //returns "c"
|
|
|
|
---------------------------------------
|
|
|
|
*ord(<chr>)
|
|
|
|
Returns the ASCII value of char <chr>.
|
|
|
|
Example:
|
|
|
|
ord("c"); //returns 99
|
|
|
|
---------------------------------------
|
|
|
|
*setchar(<string>, <char>, <index>)
|
|
|
|
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:
|
|
|
|
setchar("Cat", "B", 0); //returns "Bat"
|
|
|
|
---------------------------------------
|
|
|
|
*insertchar(<string>, <char>, <index>)
|
|
|
|
Returns the original string with the specified char inserted at the
|
|
specified index. If index is out of range, the char will be inserted on
|
|
the end of the string that it is closest. Only the 1st char in the <char>
|
|
parameter will be used.
|
|
|
|
Example:
|
|
|
|
insertchar("laughter", "s", 0); //returns "slaughter"
|
|
|
|
---------------------------------------
|
|
|
|
*delchar(<string>, <index>)
|
|
|
|
Returns the original string with the char at the specified index removed.
|
|
If index is out of range, original string will be returned.
|
|
|
|
Example:
|
|
|
|
delchar("Diet", 3); //returns "Die"
|
|
|
|
---------------------------------------
|
|
|
|
*strtoupper(<string>)
|
|
*strtolower(<string>)
|
|
|
|
Returns the specified string in it's uppercase/lowercase form.
|
|
All non-alpha characters will be preserved.
|
|
|
|
Example:
|
|
|
|
strtoupper("The duck is blue!!"); //returns "THE DUCK IS BLUE!!"
|
|
|
|
---------------------------------------
|
|
|
|
*charisupper(<string>, <index>)
|
|
*charislower(<string>, <index>)
|
|
|
|
Returns true if character at specified index of specified string is
|
|
uppercase for charisupper() or lowercase for charislower(). Otherwise, false.
|
|
Characters not in the alphabet will return false.
|
|
|
|
Example:
|
|
|
|
charisupper("Hercules", 0); //returns 1
|
|
|
|
---------------------------------------
|
|
|
|
*substr(<string>, <start_index>, <end_index>)
|
|
|
|
Returns the sub-string of the specified string inclusively between the set
|
|
indexes. If indexes are out of range, or the start index is after the end
|
|
index, an empty string will be returned.
|
|
|
|
Example:
|
|
|
|
substr("foobar", 3, 5); //returns "bar"
|
|
|
|
---------------------------------------
|
|
|
|
*explode(<dest_array>, <string>, <delimiter>)
|
|
|
|
Breaks a string up into substrings based on the specified delimiter.
|
|
Substrings will be stored within the specified string array. Only the 1st
|
|
char of the delimiter parameter will be used. If an empty string is passed
|
|
as a delimiter, the string will be placed in the array in its original
|
|
form, without any changes. Return the number of elements written to
|
|
<dest_array>.
|
|
|
|
Example:
|
|
|
|
.@num_elements = explode(.@my_array$, "Explode:Test:1965:red:PIE", ":");
|
|
//.@my_array$ contents will be...
|
|
//.@my_array$[0]: "Explode"
|
|
//.@my_array$[1]: "Test"
|
|
//.@my_array$[2]: "1965"
|
|
//.@my_array$[3]: "red"
|
|
//.@my_array$[4]: "PIE"
|
|
//.@num_elements: 5
|
|
|
|
---------------------------------------
|
|
|
|
*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 in between
|
|
each substring.
|
|
|
|
Example:
|
|
setarray(.@my_array$[0], "This", "is", "a", "test");
|
|
implode(.@my_array$, " "); //returns "This is a test"
|
|
|
|
---------------------------------------
|
|
|
|
*sprintf(<format>{, param{, param{, ...}}})
|
|
|
|
C style sprintf. The resulting string is returned.
|
|
|
|
The format string can contain placeholders (format specifiers) using the
|
|
following structure:
|
|
|
|
%[parameter][flags][width]type
|
|
|
|
The following format specifier types are supported:
|
|
|
|
%%: 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:
|
|
|
|
%n (not implemented due to safety concerns)
|
|
%f, %F, %e, %E, %g, %G (the script engine doesn't use floating point values)
|
|
%p (the script engine doesn't use pointers)
|
|
%a, %A (not supported, use 0x%x and 0x%X respectively instead)
|
|
|
|
An ordinal parameter can be specified in the form 'x$' (where x is a number),
|
|
to reorder the output (this may be useful in translated strings, where the
|
|
sentence order may be different from the original order). Example:
|
|
|
|
// Name, level, job name
|
|
mes(sprintf("Hello, I'm %s, a level %d %s", strcharinfo(PC_NAME), BaseLevel, jobname(Class)));
|
|
|
|
When translating the sentence to other languages (for example Italian),
|
|
swapping some arguments may be appropriate, and it may be desirable to keep the
|
|
actual arguments in the same order (i.e. when translating through the HULD):
|
|
|
|
// 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)));
|
|
|
|
The supported format specifier flags are:
|
|
|
|
- (minus): Left-align the output of this format specifier. (the default is to
|
|
right-align the output).
|
|
+ (plus): Prepends a plus for positive signed-numeric types. positive = '+',
|
|
negative = '-'.
|
|
(space): Prepends a space for positive signed-numeric types. positive = ' ',
|
|
negative = '-'. This flag is ignored if the '+' flag exists.
|
|
0 (zero): When a field width option is specified, prepends zeros for numeric
|
|
types. (the default prepends spaces).
|
|
A field width can be specified.
|
|
|
|
mes(sprintf("The temperature is %+d degrees Celsius", .@temperature)); // Keeps the '+' sign in front of positive values
|
|
.@map_name$ = sprintf("quiz_%02d", .@i); // Keeps the leading 0 in "quiz_00", etc
|
|
|
|
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.
|
|
|
|
sprintf("%04d", 10) // Returns "0010"
|
|
sprintf("%0*d", 5, 10) // Returns "00010"
|
|
sprintf("%5d", 10) // Returns " 10"
|
|
sprintf("%-5d", 10) // Returns "10 "
|
|
sprintf("%10s", "Hello") // Returns " Hello";
|
|
sprintf("%-10s", "Hello") // Returns "Hello ";
|
|
|
|
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"
|
|
|
|
dispbottom(sprintf(.@format$, "barrel", 82));
|
|
//prints "The barrel contains 82 monkeys"
|
|
|
|
---------------------------------------
|
|
|
|
*sscanf(<string>, <format>{, param{, param{, ...}}})
|
|
|
|
C style sscanf. All C format specifiers are supported.
|
|
More info: https://cplusplus.com/reference/cstdio/sscanf/
|
|
The number of params is only limited by Hercules' script engine.
|
|
|
|
Example:
|
|
sscanf("This is a test: 42 foobar", "This is a test: %d %s", .@num, .@str$);
|
|
dispbottom(.@num + " " + .@str$); //prints "42 foobar"
|
|
|
|
---------------------------------------
|
|
|
|
*strpos(<haystack>, <needle>{, <offset>})
|
|
|
|
PHP style strpos. Finds a substring (needle) within a string (haystack).
|
|
The offset parameter indicates the index of the string to start searching.
|
|
Returns index of substring on successful search, else -1.
|
|
Comparison is case sensitive.
|
|
|
|
Example:
|
|
strpos("foobar", "bar", 0); //returns 3
|
|
strpos("foobarfoo", "foo", 0); //returns 0
|
|
strpos("foobarfoo", "foo", 1); //returns 6
|
|
|
|
---------------------------------------
|
|
|
|
*replacestr(<input>, <search>, <replace>{, <usecase>{, <count>}})
|
|
|
|
Replaces all instances of a search string in the input with the specified
|
|
replacement string. By default is case sensitive unless <usecase> is set
|
|
to 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"
|
|
|
|
---------------------------------------
|
|
|
|
*countstr(<input>, <search>{, <usecase>})
|
|
|
|
Counts all instances of a search string in the input. By default is case
|
|
sensitive unless <usecase> is set to false.
|
|
|
|
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()
|
|
|
|
This command return the player's current font.
|
|
if no player is attached it would always return a 0, which is also the default font.
|
|
|
|
---------------------------------------'
|
|
*showdigit(<value>{, <type>})
|
|
|
|
Displays given numeric 'value' in large digital clock font on top of the
|
|
screen. The optional parameter 'type' specifies visual aspects of the
|
|
"clock" and can be one of the following values:
|
|
|
|
0 - Displays the value for 5 seconds (default).
|
|
1 - Incremental counter (1 tick/second).
|
|
2 - Decremental counter (1 tick/second). Does not stop at zero, but
|
|
overflows.
|
|
3 - Decremental counter (1 tick/second). Two digits only, stops at
|
|
zero.
|
|
|
|
For type 1 and 2 the start value is set by using negative number of the
|
|
one intended to set (ex. -10 starts the counter at 10 seconds). Except for
|
|
type 3 the value is interpreted as seconds and formatted as time in days,
|
|
hours, minutes and seconds. Note, that the official script command does
|
|
not have the optional parameter.
|
|
|
|
// displays 23:59:59 for 5 seconds
|
|
showdigit(86399);
|
|
|
|
// counter that starts at 60 and runs for 60 seconds
|
|
showdigit(60, 3);
|
|
|
|
---------------------------------------
|
|
|
|
* The Pet AI commands
|
|
|
|
These commands will only work if the invoking character has a pet, and are
|
|
meant to be executed from pet scripts. They will modify the pet AI
|
|
decision-making for the current pet of the invoking character, and will
|
|
NOT have any independent effect by themselves, which is why only one of
|
|
them each may be in effect at any time for a specific pet. A pet may
|
|
have petloot(), petskillbonus(), petskillattack() and petskillsupport() at the
|
|
same time.
|
|
|
|
*petskillbonus(<bonus type>, <value>, <duration>, <delay>)
|
|
|
|
This command will make the pet give a bonus to the owner's stat (bonus
|
|
type - bInt, bVit, bDex, bAgi, bLuk, bStr, bSpeedRate - for a full list, see the
|
|
'doc/constants_(pre-)re.md' under 'Bonuses / Parameter IDs').
|
|
|
|
*petrecovery(<status type>, <delay>)
|
|
|
|
This command will make the pet cure a specified status condition. The
|
|
curing actions will occur once every <delay> seconds. For a full list of
|
|
status conditions that can be cured, see the list of 'Status Changes' status
|
|
condition constants in 'doc/constants_(pre-)re.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.
|
|
|
|
*petskillsupport(<skill id>, <skill level>, <delay>, <percent hp>, <percent sp>)
|
|
*petskillsupport("<skill name>", <skill level>, <delay>, <percent hp>, <percent sp>)
|
|
|
|
This will make the pet use a specified support skill on the owner whenever
|
|
the HP and SP are below the given percent values, with a specified delay
|
|
time between activations. The skill numbers are as per
|
|
'db/(pre-)re/skill_db.conf'.
|
|
It's not quite certain who's stats will be used for the skills cast, the
|
|
character's or the pets. Probably, Skotlex can answer that question.
|
|
|
|
*petskillattack(<skill id>, <damage>, <number of attacks>, <rate>, <bonusrate>)
|
|
*petskillattack("<skill name>", <damage>, <number of attacks>, <rate>, <bonusrate>)
|
|
|
|
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.
|
|
|
|
Nobody tried this before, so you're essentially on your own here.
|
|
|
|
---------------------------------------
|
|
|
|
*bpet()
|
|
|
|
This command opens up a pet hatching window on the client connected to the
|
|
invoking character. It is used in item script for the pet incubators and
|
|
will let the player hatch an owned egg. If the character has no eggs, it
|
|
will just open up an empty incubator window.
|
|
This is still usable outside item scripts.
|
|
|
|
---------------------------------------
|
|
|
|
*makepet(<pet id>)
|
|
|
|
This command will create a pet egg and put it in the invoking character's
|
|
inventory. The kind of pet is specified by pet ID numbers listed in
|
|
'db/(pre-)re/pet_db.conf'. The egg is created exactly as if the character just
|
|
successfully caught a pet in the normal way.
|
|
|
|
// This will make you a poring:
|
|
makepet(PORING);
|
|
|
|
Notice that you absolutely have to create pet eggs with this command. If
|
|
you try to give a pet egg with getitem(), pet data will not be created by
|
|
the char server and the egg will disappear when anyone tries to hatch it.
|
|
|
|
---------------------------------------
|
|
|
|
*homshuffle()
|
|
|
|
This will recalculate the homunculus stats according to its level, of the
|
|
current invoking character.
|
|
|
|
---------------------------------------
|
|
|
|
*setcell("<map name>", <x1>, <y1>, <x2>, <y2>, <type>, <flag>)
|
|
|
|
Each map cell has several 'flags' that specify the properties of that cell.
|
|
These include terrain properties (walkability, shootability, presence of
|
|
water), skills (basilica, land protector, ...) and other (NPC nearby, no
|
|
vending, ...).
|
|
Each of these can be 'on' or 'off'. Together they define a cell's behavior.
|
|
|
|
This command lets you alter these flags for all map cells in the specified
|
|
(x1,y1)-(x2,y2) rectangle.
|
|
'type' defines which flag to modify. Possible options include cell_walkable,
|
|
cell_shootable, cell_basilica. For a full list, see 'doc/constants_(pre-)re.md'.
|
|
'flag' can be false (clear flat) or true (set flag).
|
|
|
|
Example:
|
|
|
|
setcell("arena", 0, 0, 300, 300, cell_basilica, true);
|
|
setcell("arena", 140, 140, 160, 160, cell_basilica, false);
|
|
setcell("arena", 135, 135, 165, 165, cell_walkable, false);
|
|
setcell("arena", 140, 140, 160, 160, cell_walkable, true);
|
|
|
|
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.
|
|
|
|
---------------------------------------
|
|
|
|
*checkcell("<map name>", <x>, <y>, <type>)
|
|
|
|
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_(pre-)re.md' under 'Cell checks'.
|
|
|
|
The meaning of the individual types can be confusing, so here's an
|
|
overview:
|
|
- cell_chkwall/water/cliff
|
|
these check directly for the 'terrain component' of the specified cell
|
|
- cell_chkpass/reach/nopass/noreach
|
|
passable = not wall & not cliff, reachable = passable
|
|
wrt. no-stacking mod
|
|
- cell_chknpc/basilica/landprotector/novending/nochat
|
|
these check for specific dynamic flags (name indicates what they do)
|
|
|
|
Example:
|
|
|
|
mes("Pick a destination map.");
|
|
input(.@map$);
|
|
mes("Alright, now give me the coordinates.");
|
|
input(.@x);
|
|
input(.@y);
|
|
if (!checkcell(.@map$, .@x, .@y, cell_chkpass)) {
|
|
mes("Can't warp you there, sorry!");
|
|
close();
|
|
} else {
|
|
mes("Ok, get ready...");
|
|
close2();
|
|
warp(.@map$, .@x, .@y);
|
|
end;
|
|
}
|
|
|
|
---------------------------------------
|
|
|
|
*setwall("<map name>", <x>, <y>, <size>, <dir>, <shootable>, "<name>")
|
|
*delwall("<name>")
|
|
|
|
Creates an invisible wall, an array of setcell() starting from x,y and
|
|
doing a line of the given size in the given direction. The difference with
|
|
setcell is this one update client part too to avoid the glitch problem.
|
|
Directions are the same as NPC sprite facing directions: (DIR_ constants).
|
|
|
|
---------------------------------------
|
|
|
|
*readbook(<book id>, <page>)
|
|
|
|
This will open a book item at the specified page.
|
|
|
|
---------------------------------------
|
|
|
|
*rodex_sendmail(<char id>, "<sender name>", "<title>", "<body>"{, <zeny>{, <item1>, <amount1>{, <item2>, <amount2>{, <item3>, <amount3>{, <item4>, <amount4>{, <item5>, <amount5>}}}}}})
|
|
*rodex_sendmail2(<char id>, "<sender name>", "<title>", "<body>"{, <zeny>{, <item1>, <amount1>, <refine1>, <attribute1>, <card0_1>, <card1_1>, <card2_1>, <card3_1>{,<item2>, <amount2>, <refine2>, <attribute2>, <card0_2>, <card1_2>, <card2_2>, <card3_2>{,<item3>, <amount3>, <refine3>, <attribute3>, <card0_3>, <card1_3>, <card2_3>, <card3_3>{,<item4>, <amount4>, <refine4>, <attribute4>, <card0_4>, <card1_4>, <card2_4>, <card3_4>{,<item5>, <amount5>, <refine5>, <attribute5>, <card0_5>, <card1_5>, <card2_5>, <card3_5>}}}}}})
|
|
|
|
*rodex_sendmail_acc(<account id>, "<sender name>", "<title>", "<body>"{, <zeny>{, <item1>, <amount1>{, <item2>, <amount2>{, <item3>, <amount3>{, <item4>, <amount4>{, <item5>, <amount5>}}}}}})
|
|
*rodex_sendmail_acc2(<account id>, "<sender name>", "<title>", "<body>"{, <zeny>{, <item1>, <amount1>, <refine1>, <attribute1>, <card0_1>, <card1_1>, <card2_1>, <card3_1>{,<item2>, <amount2>, <refine2>, <attribute2>, <card0_2>, <card1_2>, <card2_2>, <card3_2>{,<item3>, <amount3>, <refine3>, <attribute3>, <card0_3>, <card1_3>, <card2_3>, <card3_3>{,<item4>, <amount4>, <refine4>, <attribute4>, <card0_4>, <card1_4>, <card2_4>, <card3_4>{,<item5>, <amount5>, <refine5>, <attribute5>, <card0_5>, <card1_5>, <card2_5>, <card3_5>}}}}}})
|
|
|
|
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.
|
|
For examples of usage, see /doc/sample/npc_rodex.txt
|
|
|
|
rodex_sendmail2 and rodex_sendmail_acc2 are more flexible versions.
|
|
Check getitem2 command for more information of the extra parameters.
|
|
|
|
Important: rodex_sendmail_acc (and rodex_sendmail_acc2) requires clients from 2016-03-23 or newer.
|
|
Additionally, it requires enabling "rodex_use_accountmail" on conf/map/battle/feature.conf.
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
7 - Instance-Related Commands
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
*instance_create("<instance_name>", <owner_id>{, <owner_type>})
|
|
|
|
Creates 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.
|
|
|
|
Valid <owner_type> values:
|
|
- IOT_NONE (0) - <owner_id> can be any arbitrary number.
|
|
- IOT_CHAR (1) - <owner_id> is account ID.
|
|
- IOT_PARTY (2) - <owner_id> is party ID.
|
|
- IOT_GUILD (3) - <owner_id> is guild ID.
|
|
|
|
Example:
|
|
// Store the Party ID of the invoking character.
|
|
.@party_id = getcharid(CHAR_ID_PARTY);
|
|
|
|
// Attempt to create an instance using that party ID.
|
|
.@id = instance_create("Endless Tower", .@party_id);
|
|
if (.@id == -1) { // Invalid type - not used anymore
|
|
// ...
|
|
} else if (.@id == -2) { // Invalid Party ID
|
|
// ...
|
|
} else if (.@id == -4) { // Already exists
|
|
// ...
|
|
} else if (.@id < 0) { // Unspecified error while queuing instance.
|
|
// ...
|
|
}
|
|
|
|
---------------------------------------
|
|
|
|
*instance_destroy({<instance id>})
|
|
|
|
Destroys instance with the ID <instance id>. If no ID is specified, the
|
|
instance the script is attached to is used. If in the end no instance_id,
|
|
is found the command halts the script execution.
|
|
|
|
---------------------------------------
|
|
|
|
*instance_attachmap("<map name>", <instance id>{, <use base name>{, "<new map name>"}})
|
|
|
|
Attaches the map "<map name>" to the instance specified with
|
|
<instance id>. The optional parameter specifies, whether a map requires
|
|
emulation for instancing (true) or not (false = default). if use base name is specified,
|
|
and "<new map name>" too the server will instance the map under the "<new map name>",
|
|
name.
|
|
|
|
Returns the resulting map name on success or an empty string on failure.
|
|
|
|
Example:
|
|
instance_attachmap("prontera", .@instance_id, true, "via");
|
|
^ the above creates a instance (or clone) of prontera, on a map called "via"
|
|
|
|
---------------------------------------
|
|
|
|
*instance_detachmap("<map name>"{, <instance id>})
|
|
|
|
Detach the map "<map name>" to the instance with the <instance id>. If no
|
|
ID is specified, the instance the script is attached to is used. If in the
|
|
end no instance_id is found the command halts the script execution.
|
|
|
|
---------------------------------------
|
|
|
|
*instance_init(<instance id>)
|
|
|
|
Initializes the instance given by <instance id>. This copies all NPCs from
|
|
the source maps to the instanced maps.
|
|
|
|
---------------------------------------
|
|
|
|
*instance_announce(<instance id>, "<text>", <flag>{, <fontColor>{, <fontType>{, <fontSize>{, <fontAlign>{, <fontY>}}}}})
|
|
|
|
Works like announce, but has the <instance id> parameter. If instance id
|
|
is -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>)
|
|
|
|
Attaches the current script to the instance given by <instance id>.
|
|
|
|
---------------------------------------
|
|
|
|
*instance_npcname("<npc name>"{, <instance id>})
|
|
|
|
Retrieves the unique name given to a copy of an NPC given by "<npc name>"
|
|
in an instance specified <instance id>. If no ID is specified, the
|
|
instance the script is attached to is used. If in the end no instance_id,
|
|
is found the command halts the script execution.
|
|
|
|
---------------------------------------
|
|
|
|
*has_instance("<map name>"{, <instance id>})
|
|
|
|
Checks whether or not the given map belongs to specified instance. If no
|
|
ID is specified, the instance the script is attached to is used. If the
|
|
script is not attached to an instance, it'll try to check whether the,
|
|
player attached to the script possesses an instance with a map matching
|
|
"<map name>". If in the end no instance_id is found the command halts the,
|
|
script execution.
|
|
|
|
Returns name of the instanced map on success, otherwise an empty string.
|
|
|
|
---------------------------------------
|
|
|
|
*has_instance2("<map name>")
|
|
|
|
Same as has_instance, with exception it returns the instance id of the map,
|
|
as long as the user is assigned to a instance containing that map.
|
|
It will return -1 upon failure, valid instance ids are >= 0.
|
|
|
|
---------------------------------------
|
|
|
|
*instance_id()
|
|
|
|
Retrieves the instance id of the script it is being run on.
|
|
|
|
---------------------------------------
|
|
|
|
*instance_warpall("<map name>", <x>, <y>{, <instance id>})
|
|
|
|
Warps all players in the instance <instance id> to <map name> at given
|
|
coordinates. If no ID is specified, the instance the script is attached to
|
|
is used. If in the end no instance_id is found the command halts the,
|
|
script execution.
|
|
|
|
---------------------------------------
|
|
|
|
*instance_set_timeout(<alive timeout>, <idle timeout>{, <instance id>})
|
|
|
|
Sets the timeout values for an instance given by <instance id>. If no ID
|
|
is specified, the instance the script is attached to is used. If 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.
|
|
|
|
Both timeout values are in seconds.
|
|
|
|
---------------------------------------
|
|
|
|
*instance_check_party(<party id>{, <amount>{, <min>{, <max>}}})
|
|
|
|
This function checks if a party meets certain requirements, returning true if
|
|
all conditions are met and false otherwise. It will only check online
|
|
characters.
|
|
|
|
amount - number of online party members (default is 1).
|
|
min - minimum level of all characters in the party (default is 1).
|
|
max - maximum level of all characters in the party (default is max
|
|
level in conf).
|
|
|
|
Example:
|
|
|
|
if (instance_check_party(getcharid(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();
|
|
}
|
|
|
|
---------------------------------------
|
|
|
|
*instance_check_guild(<guild_id>{, <amount>{, <min>{, <max>}}})
|
|
|
|
This function checks if a guild meets certain requirements, returning true if
|
|
all conditions are met and false otherwise. it will only check online characters.
|
|
|
|
amount - number of online guild members (default is 1).
|
|
min - minimum level of all characters in the guild (default is 1).
|
|
max - maximum level of all characters in the guild (default is max level in conf).
|
|
|
|
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>})
|
|
|
|
Updates the 'reload spawn' position of a instance,
|
|
that is where players in the instance are sent to upon @reloadscript,
|
|
uses the npc instance (if any) when instance_id is not provided,
|
|
handy to update a instance's progress so that when/if @reloadscript happens
|
|
the damage to the players progress is reduced.
|
|
It is most effective when used with instance variables (which are @reloadscript persistent)
|
|
|
|
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>})
|
|
|
|
Returns the unique name of the instanced map. If no instance ID is specified,
|
|
the instance the script is attached to is used. If the script is not attached to
|
|
an instance, the instance of the currently attached player's party is used. If
|
|
that fails, the command returns an empty string instead.
|
|
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
7 - End of Instance-Related Commands
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
8 - Quest Log-Related Commands
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
*questinfo(<Icon> {, <Map Mark Color>})
|
|
|
|
This is essentially 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)
|
|
|
|
- Only for packetver >= 20170315
|
|
Click Me Icon : QTYPE_CLICKME
|
|
! Daily Quest Icon : QTYPE_DAILYQUEST
|
|
! Green Event Icon : QTYPE_EVENT3
|
|
! Job Quest Icon : QTYPE_JOBQUEST
|
|
Jumping Poring : QTYPE_JUMPING_PORING
|
|
|
|
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...>})
|
|
|
|
Use this command ONLY after a questinfo()
|
|
it allows you to set multiple required conditions for the quest bubble to show up.
|
|
|
|
supported types: values
|
|
QINFO_JOB: job_id
|
|
QINFO_SEX: sex
|
|
QINFO_BASE_LEVEL: min, max
|
|
QINFO_JOB_LEVEL: min, max
|
|
QINFO_ITEM: item_id, min amount, max amount // append to the items list on each use
|
|
QINFO_HOMUN_LEVEL: min
|
|
QINFO_HOMUN_TYPE: homunculus_type (0 - regular, 1 - evolved, 2 - S)
|
|
QINFO_QUEST: quest_id, state // append to the quests list on each use
|
|
QINFO_MERCENARY_CLASS: mercenary_class
|
|
|
|
---------------------------------------
|
|
|
|
*setquest(<ID>{, <Time Limit>})
|
|
|
|
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>})
|
|
|
|
If no additional argument supplied, return the state of the quest:
|
|
0 = Quest not started (not in quest log)
|
|
1 = Quest has been given
|
|
2 = Quest completed
|
|
|
|
If <type> PLAYTIME is supplied:
|
|
0 = Quest not started (not in quest log)
|
|
1 = The time limit has not yet been reached
|
|
2 = The time limit has been reached
|
|
|
|
If <type> HUNTING is supplied:
|
|
0 = Quest not started (not in quest log)
|
|
1 = Player hasn't killed all of the target monsters
|
|
2 = Player has killed all of the target monsters
|
|
|
|
---------------------------------------
|
|
|
|
*questactive(<ID>)
|
|
|
|
Check whether the given quest is in its active state.
|
|
|
|
Returns true if the quest is active, false otherwise (quest not started,
|
|
inactive or completed)
|
|
|
|
---------------------------------------
|
|
|
|
*showevent(<icon>{, <mark color>})
|
|
|
|
Show an emotion on top of a NPC, and optionally,
|
|
a colored mark in the mini-map like viewpoint().
|
|
This is used to indicate that a NPC has a quest or an event to
|
|
a certain player.
|
|
|
|
Available Icons:
|
|
|
|
Remove 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)
|
|
|
|
- Only for packetver >= 20170315
|
|
Click Me Icon : QTYPE_CLICKME
|
|
! Daily Quest Icon : QTYPE_DAILYQUEST
|
|
! Green Event Icon : QTYPE_EVENT3
|
|
! Job Quest Icon : QTYPE_JOBQUEST
|
|
Jumping Poring : QTYPE_JUMPING_PORING
|
|
|
|
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
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
*waitingroom2bg_single(<battle group>, "<mapname>", <x>, <y>, "<npc name>")
|
|
|
|
Adds the first waiting player from the chat room of given NPC to an
|
|
existing battleground group and warps it to specified coordinates on given
|
|
map.
|
|
|
|
---------------------------------------
|
|
|
|
*waitingroom2bg("<mapname>", <x>, <y>, "<On Quit Event>", "<On Death Event>"{, "<npc name>"})
|
|
|
|
<Mapname> and X Y coordinates refer to where the "respawn" base is, where
|
|
the player group will respawn when they die.
|
|
<On Quit Event> refers to an NPC label that attaches to the character and
|
|
is run when they relog.
|
|
<On Death Event> refers to an NPC label that attaches to the character and
|
|
is run when they die. Can be "" for empty.
|
|
|
|
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;
|
|
|
|
----------------------------------------
|
|
|
|
*bg_team_setxy(<Battle Group ID>, <x>, <y>)
|
|
|
|
Update the respawn point of the given battle group to x, y on the same
|
|
map. The <Battle Group ID> can be retrieved using getcharid(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;
|
|
|
|
----------------------------------------
|
|
|
|
*bg_warp(<Battle Group>, "<Mapname>", <x>, <y>)
|
|
|
|
Similar to warp command.
|
|
Place all members of <Battle Group> at <mapname> at x y.
|
|
|
|
Example:
|
|
//place the battle group one for Tierra Gorge at starting position.
|
|
bg_warp($@TierraBG1_id1, "bat_a01", 352, 342);
|
|
end;
|
|
|
|
----------------------------------------
|
|
|
|
*bg_monster(<Battle Group>, "<map name>", <x>, <y>, "<name to show>", <mob id>, "<event label>")
|
|
|
|
Similar to monster() script command.
|
|
Spawn a monster with allegiance to the given battle group.
|
|
Does not allow for the summoning of multiple monsters.
|
|
Monsters are similar to that in War of Emperium, in that the specified
|
|
Battle group is considered friendly.
|
|
|
|
Example:
|
|
// It can be used in two different ways.
|
|
bg_monster($@TierraBG1_id2, "bat_a01", 167, 50, "Food Depot", OBJ_B, "Feed Depot#1::OnMyMobDead");
|
|
end;
|
|
|
|
// Alternatively, you can set an ID for the monster using "set".
|
|
// This becomes useful when used with the command below.
|
|
$@Guardian_3 = bg_monster($@TierraBG1_id2, "bat_a01", 268, 204, "Guardian", B_S_GUARDIAN, "NPCNAME::OnMyMobDead");
|
|
end;
|
|
|
|
----------------------------------------
|
|
|
|
*bg_monster_set_team(<GID>, <Battle Group>)
|
|
|
|
This command will change the allegiance if a monster in a battle ground.
|
|
GID can be set when spawning the monster via the bg_monster() command.
|
|
|
|
Example:
|
|
|
|
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()
|
|
|
|
Removes attached player from their Battle Group.
|
|
|
|
----------------------------------------
|
|
|
|
*bg_destroy(<Battle Group>)
|
|
|
|
As the name says, destroys the battle group created for that battle ground.
|
|
|
|
----------------------------------------
|
|
|
|
*areapercentheal("<mapname>", <x1>, <y1>, <x2>, <y2>, <hp>, <sp>)
|
|
|
|
Not exactly limited to battleground use, this will restore HP/SP in a
|
|
defined area at a percentage.
|
|
|
|
Example:
|
|
areapercentheal("bat_a01", 52, 208, 61, 217, 100, 100);
|
|
end;
|
|
|
|
----------------------------------------
|
|
|
|
*bg_get_data(<Battle Group>, <type>)
|
|
|
|
Retrieves data related to given battle group. Type can be one of the
|
|
following:
|
|
|
|
0 - Amount of players currently belonging to the group.
|
|
|
|
----------------------------------------
|
|
|
|
*bg_getareausers(<battle group>, "<map_name>", <x0>, <y0>, <x1>, <y1>)
|
|
|
|
Retrieves amount of players belonging to given battle group on given map
|
|
within an specified rectangular area.
|
|
|
|
----------------------------------------
|
|
|
|
*bg_updatescore("<map_name>", <Guillaume Score>, <Croix Score>)
|
|
|
|
This command will force the update of the displayed scoreboard.
|
|
It is only usable when the map is defined as a Type 2 Battleground:
|
|
mapflag%TAB%<map_name>%TAB%battleground%TAB%2
|
|
|
|
----------------------------------------
|
|
|
|
*bg_create_team("<map_name>", <Respawn X>, <Respawn Y>)
|
|
|
|
This command will create a new BG Team.
|
|
When player dies, they will be respawned map_name,X,Y as mentioned.
|
|
If "-" is supplied for the map name, this will remove the 1 second automatic
|
|
respawn on the battleground map.
|
|
|
|
Command will return -1 if BG Creation is failed,
|
|
else it will return the BG ID(Also known as TeamID).
|
|
|
|
----------------------------------------
|
|
|
|
*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.
|
|
|
|
Command will return -1 if Player is not found, 0 if join is failed, 1 upon successful.
|
|
|
|
----------------------------------------
|
|
|
|
*bg_match_over("<Arena Name>"{, <canceled>})
|
|
|
|
This command will end the battleground Arena
|
|
(Arena Name as referred to, in conf/battlegrounds.conf)
|
|
If canceled is not provided, it will set the join delay, as mentioned in conf/battlegrounds.conf
|
|
else, it will just destroy the Teams and queue's.
|
|
|
|
Command will return 0 when successful, else it will return 1.
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
9 - End of Battlegrounds-Related Commands
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
10 - Mercenary Commands
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
*mercenary_create(<class>, <contract time>)
|
|
|
|
This command summons a mercenary of given class, for given amount of time
|
|
in milliseconds. Typically used in item scripts of mercenary scrolls.
|
|
|
|
----------------------------------------
|
|
|
|
*mercenary_delete({<char_id>, <type>})
|
|
|
|
Remove mercenary from the attached character. Default value of <type> is MERC_DELETE_REMOVED.
|
|
|
|
Valid types are:
|
|
MERC_DELETE_EXPIRED - Mercenary soldier's duty fulfilled until contract expiration. Loyalty +1.
|
|
MERC_DELETE_KILLED - Mercenary died before fulfilling its contract. Loyalty -1.
|
|
MERC_DELETE_REMOVED - Mercenary removed by the user. Loyalty +0.
|
|
MERC_DELETE_RANAWAY - Mercenary left because the player died or was hit by the SC__GROOMY status. Loyalty +0.
|
|
|
|
---------------------------------------
|
|
|
|
*mercenary_heal(<hp>, <sp>)
|
|
|
|
This command works like heal(), but affects the mercenary of the currently
|
|
attached character.
|
|
|
|
----------------------------------------
|
|
|
|
*mercenary_sc_start(<type>, <tick>, <val1>)
|
|
|
|
This command works like sc_start(), but affects the mercenary of the
|
|
currently attached character.
|
|
|
|
----------------------------------------
|
|
|
|
*mercenary_get_calls(<guild>)
|
|
*mercenary_set_calls(<guild>, <value>)
|
|
|
|
Sets or gets the mercenary calls value for given guild for currently
|
|
attached character. Guild can be one or the following constants:
|
|
|
|
ARCH_MERC_GUILD
|
|
SPEAR_MERC_GUILD
|
|
SWORD_MERC_GUILD
|
|
|
|
----------------------------------------
|
|
|
|
*mercenary_get_faith(<guild>)
|
|
*mercenary_set_faith(<guild>, <value>)
|
|
|
|
Sets or gets the mercenary faith value for given guild for currently
|
|
attached character. Guild can be one or the following constants:
|
|
|
|
ARCH_MERC_GUILD
|
|
SPEAR_MERC_GUILD
|
|
SWORD_MERC_GUILD
|
|
|
|
---------------------------------------
|
|
|
|
*getmercinfo(<type>{, <char id>})
|
|
|
|
Retrieves information about mercenary of the currently attached character.
|
|
If char id is given, the information of that character is retrieved
|
|
instead. Type specifies what information to retrieve and can be one of the
|
|
following:
|
|
|
|
MERCINFO_ID - Mercenary Database ID
|
|
MERCINFO_CLASS - Mercenary Class
|
|
MERCINFO_NAME - Mercenary Name
|
|
MERCINFO_FAITH - Mercenary faith value for this mercenary's guild, if any
|
|
MERCINFO_CALLS - Mercenary calls value for this mercenary's guild, if any
|
|
MERCINFO_KILLCOUNT - Mercenary kill count
|
|
MERCINFO_LIFETIME - Mercenary remaining life time in millisecond
|
|
MERCINFO_LEVEL - Mercenary Level
|
|
MERCINFO_GID - Mercenary Game ID
|
|
|
|
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>)
|
|
|
|
Returns the amount of entries in the queue instance of <queue_id>.
|
|
|
|
---------------------------------------
|
|
|
|
*queueadd(<queue_id>, <var_id>)
|
|
|
|
Adds <var_id> to queue of <queue_id>.
|
|
|
|
Returns false if <var_id> couldn't be added (was already present in the queue),
|
|
true otherwise.
|
|
|
|
---------------------------------------
|
|
|
|
*queueremove(<queue_id>, <var_id>)
|
|
|
|
Removes <var_id> from queue of <queue_id>.
|
|
|
|
Returns false if <var_id> couldn't be removed (wasn't present in the queue),
|
|
true otherwise.
|
|
|
|
---------------------------------------
|
|
|
|
*queueopt(<queue_id>, <optionType>{, <event label})
|
|
|
|
Modifies <queue_id>'s <optionType>. When <event label> is not present
|
|
<optionType> is removed from <queue_id>. When present it will execute the
|
|
<event label> when the <queue_id>'s <optionType> condition is met.
|
|
|
|
Returns true on success, false on failure.
|
|
|
|
Currently 3 options are available:
|
|
- QUEUEOPT_DEATH (1)
|
|
- QUEUEOPT_LOGOUT (2)
|
|
- QUEUEOPT_MAPCHANGE (3)
|
|
|
|
When the QUEUEOPT_MAPCHANGE event is triggered, it sets a temp char var
|
|
@Queue_Destination_Map$ with the destination map name.
|
|
|
|
Example:
|
|
queueopt(.@queue_id, QUEUEOPT_DEATH, "MyNPC::OnQueueMemberDeathEvent");
|
|
|
|
---------------------------------------
|
|
|
|
*queuedel(<queue_id>)
|
|
|
|
Deletes the queue <queue_id>.
|
|
|
|
Returns false if the queue wasn't found, true otherwise.
|
|
|
|
---------------------------------------
|
|
|
|
*queueiterator(<queue_id>)
|
|
|
|
Creates a new queue iterator instance.
|
|
A queue iterator is not a reference to a queue's actual members, it copies
|
|
the queues members when initialized, this way you can loop through them
|
|
even if you remove them from the queue.
|
|
|
|
---------------------------------------
|
|
|
|
*qicheck(<queue_iterator_id>)
|
|
|
|
Checks whether the current member in the iterator's queue exists.
|
|
|
|
Returns true when it does, false otherwise.
|
|
|
|
---------------------------------------
|
|
|
|
*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>)
|
|
|
|
Deletes a queue iterator from memory.
|
|
|
|
Returns false when it fails, otherwise true is returned.
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
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})
|
|
|
|
opens the trader shop from the currently-attached npc unless,
|
|
when the optional NPC_Name param is used.
|
|
|
|
---------------------------------------
|
|
|
|
*sellitem(<Item_ID>{, <price>{, <qty>}})
|
|
*sellitem(<Item_ID>, <qty>, <currency_id>, <currency_amount>)
|
|
*sellitem(<Item_ID>, <zeny>, <qty>{, <currency_id1>, <currency_amount1>{, <currency_refine1>}{, ...}})
|
|
|
|
adds (or modifies) <Item_ID> data to the shop,
|
|
when <price> is not provided (or when it is -1) item_db default is used.
|
|
qty is only necessary for NST_MARKET trader types.
|
|
|
|
when <Item_ID> is already in the shop,
|
|
the previous data (price/qty), is overwritten with the new.
|
|
|
|
currency_id and currency_amount can be used only with shop type NST_BARTER.
|
|
zeny, currency_id1, currency_amount1, currency_refine1, can be used only with
|
|
shop type NST_EXPANDED_BARTER.
|
|
|
|
---------------------------------------
|
|
|
|
*startsellitem(<Item_ID>, <zeny>, <qty>)
|
|
|
|
Starts adding item into expanded barter shop (NST_EXPANDED_BARTER).
|
|
Before this command possible to use commands *sellitemcurrency.
|
|
Need PACKETVER 20190904 main or 20190904 RE or 20190828 zero or newer.
|
|
|
|
Alternative way for add item to expanded barter shop is *sellitem with
|
|
currency parameters.
|
|
|
|
---------------------------------------
|
|
|
|
*sellitemcurrency(<Item_ID>, <qty>{, <refine>})
|
|
|
|
adds <Item_ID> as currency into expanded barter shop (NST_EXPANDED_BARTER)
|
|
If <refine> set to -1, mean for any refine level.
|
|
if <refine> missing used value -1.
|
|
|
|
Need PACKETVER 20190904 main or 20190904 RE or 20190828 zero or newer.
|
|
|
|
---------------------------------------
|
|
|
|
*endsellitem()
|
|
|
|
Complete adding item into expanded barter shop (NST_EXPANDED_BARTER).
|
|
Need PACKETVER 20190904 main or 20190904 RE or 20190828 zero or newer.
|
|
|
|
---------------------------------------
|
|
|
|
*stopselling(<Item_ID>)
|
|
*stopselling(<Item_ID>{, <currency_id>, <currency_amount>})
|
|
|
|
attempts to remove <Item_ID> from the current shop list.
|
|
currency_id and currency_amount can be used only with shop type NST_BARTER
|
|
|
|
---------------------------------------
|
|
|
|
*setcurrency(<Val1>{, <Val2>})
|
|
|
|
updates the currently attached player shop funds,
|
|
to be used within a "OnCountFunds" event of a NST_CUSTOM trader type.
|
|
|
|
<Val1> is the value used in the *Cash* Points field
|
|
<Val2> is the value used in the Kafra Points field
|
|
|
|
---------------------------------------
|
|
|
|
*tradertype(<Type>)
|
|
|
|
Modifies the npc trader type, item list is cleared upon modifying the value.
|
|
By default, all npcs staart with tradertype(NST_ZENY);
|
|
|
|
- NST_ZENY (0) Normal Zeny Shop
|
|
- NST_CASH (1) Normal Cash Shop
|
|
- 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/etc, check sample)
|
|
|
|
---------------------------------------
|
|
|
|
*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>)
|
|
|
|
Returns the amount of still-available <Item_ID> in the shop (on a NST_MARKET trader).
|
|
|
|
---------------------------------------
|
|
|
|
*setunitdata(<GID>, <DataType>, <Val>)
|
|
|
|
Sets or alters the data in real-time for game objects of the following types -
|
|
NPCs, Pets, Monsters, Homunuculus', Mercenaries, Elementals.
|
|
|
|
Applicable Data Types (available as constants) -
|
|
Data Types Description (parameter type)
|
|
UDT_SIZE: Unit Size
|
|
UDT_LEVEL: Level
|
|
UDT_HP: Current HP
|
|
UDT_MAXHP: Max HP
|
|
UDT_SP: SP
|
|
UDT_MAXSP: MAX SP
|
|
UDT_MASTERAID: Master Account ID (for Summons)
|
|
UDT_MASTERCID: Master Char ID (for Summons)
|
|
UDT_SPEED: Unit Speed.
|
|
UDT_MODE: Mode (Mobs only)
|
|
UDT_AI: Unit AI Type (see doc/constants_(pre-)re.md for Unit AI Types)
|
|
UDT_SCOPTION: Status Options. (see doc/constants_(pre-)re.md for Unit Option Types)
|
|
UDT_SEX: Gender of the unit. (see doc/constants_(pre-)re.md for Genders)
|
|
UDT_CLASS: Class of the unit. (Monster ID)
|
|
UDT_HAIRSTYLE: Hair Style ID.
|
|
UDT_HAIRCOLOR: Hair Color ID.
|
|
UDT_HEADBOTTOM: Headgear Bottom Sprite ID.
|
|
UDT_HEADMIDDLE: Headgear Middle Sprite ID.
|
|
UDT_HEADTOP: Headgear Top Sprite ID.
|
|
UDT_CLOTHCOLOR: Cloth Color ID.
|
|
UDT_SHIELD: Shield Sprite ID.
|
|
UDT_WEAPON: Weapon Sprite ID.
|
|
UDT_LOOKDIR: Face direction.
|
|
UDT_CANMOVETICK: Stop a unit from move for n seconds.
|
|
UDT_STR: Unit STR.
|
|
UDT_AGI: Unit AGI.
|
|
UDT_VIT: Unit VIT.
|
|
UDT_INT: Unit INT.
|
|
UDT_DEX: Unit DEX.
|
|
UDT_LUK: Unit LUK.
|
|
UDT_ATKRANGE: Attack range of a unit.
|
|
UDT_ATKMIN: Min Atk of a unit.
|
|
UDT_ATKMAX: Max Atk of a unit.
|
|
UDT_MATKMIN: Min MATK of a unit.
|
|
UDT_MATKMAX: Max MATK of a unit.
|
|
UDT_DEF: DEF.
|
|
UDT_MDEF: MDEF.
|
|
UDT_HIT: HIT.
|
|
UDT_FLEE: FLEE.
|
|
UDT_PDODGE: Perfect Dodge.
|
|
UDT_CRIT: Critical Rate.
|
|
UDT_RACE: Race. (Eg. constants RC_DemiHuman or Integer 7).
|
|
UDT_ELETYPE: Element. (Eg. constants Ele_Neutral or Integer 0).
|
|
UDT_ELELEVEL: Element Level.
|
|
UDT_AMOTION: AMotion Rate.
|
|
UDT_ADELAY: ADelay Rate.
|
|
UDT_DMOTION: DMotion Rate.
|
|
UDT_HUNGER: Hunger Rate - for summons.
|
|
UDT_INTIMACY: Intimacy Rate - for summons.
|
|
UDT_LIFETIME: LifeTime - for summons.
|
|
UDT_MERC_KILLCOUNT: Kill count for mercenaries
|
|
UDT_STATADD: Status Points - for NPCs.
|
|
UDT_GROUP: group id
|
|
UDT_DAMAGE_TAKEN_RATE: damage taken rate of a unit.
|
|
UDT_OPTIONS: options
|
|
|
|
returns 0 if value could not be set, 1 if successful.
|
|
|
|
---------------------------------------
|
|
|
|
*getunitdata (<GID>,<DataType>)
|
|
|
|
Retrieves real-time data of a game object.
|
|
|
|
Applicable Data types (available as constants) -
|
|
Data Types Description (return type)
|
|
UDT_SIZE: Unit Size
|
|
UDT_LEVEL: Level
|
|
UDT_HP: Current HP
|
|
UDT_MAXHP: Max HP
|
|
UDT_SP: SP
|
|
UDT_MAXSP: MAX SP
|
|
UDT_MASTERAID: Master Account ID (for Summons)
|
|
UDT_MASTERCID: Master Char ID (for Summons)
|
|
UDT_SPEED: Unit Speed.
|
|
UDT_MODE: Mode (Mobs only)
|
|
UDT_AI: Unit AI Type (see doc/constants_(pre-)re.md for Unit AI Types)
|
|
UDT_SCOPTION: Status Options. (see doc/constants_(pre-)re.md for Unit Option Types)
|
|
UDT_SEX: Gender of the unit. (see doc/constants_(pre-)re.md for Genders)
|
|
UDT_CLASS: Class of the unit. (Monster ID)
|
|
UDT_HAIRSTYLE: Hair Style ID.
|
|
UDT_HAIRCOLOR: Hair Color ID.
|
|
UDT_HEADBOTTOM: Headgear Bottom Sprite ID.
|
|
UDT_HEADMIDDLE: Headgear Middle Sprite ID.
|
|
UDT_HEADTOP: Headgear Top Sprite ID.
|
|
UDT_CLOTHCOLOR: Cloth Color ID.
|
|
UDT_SHIELD: Shield Sprite ID.
|
|
UDT_WEAPON: Weapon Sprite ID.
|
|
UDT_LOOKDIR: Face direction.
|
|
UDT_CANMOVETICK: Stop a unit from move for n seconds.
|
|
UDT_STR: Unit STR.
|
|
UDT_AGI: Unit AGI.
|
|
UDT_VIT: Unit VIT.
|
|
UDT_INT: Unit INT.
|
|
UDT_DEX: Unit DEX.
|
|
UDT_LUK: Unit LUK.
|
|
UDT_ATKRANGE: Attack range of a unit.
|
|
UDT_ATKMIN: Min Atk of a unit.
|
|
UDT_ATKMAX: Max Atk of a unit.
|
|
UDT_MATKMIN: Min MATK of a unit.
|
|
UDT_MATKMAX: Max MATK of a unit.
|
|
UDT_DEF: DEF.
|
|
UDT_MDEF: MDEF.
|
|
UDT_HIT: HIT.
|
|
UDT_FLEE: FLEE.
|
|
UDT_PDODGE: Perfect Dodge.
|
|
UDT_CRIT: Critical Rate.
|
|
UDT_RACE: Race. (Eg. constants RC_DemiHuman or Integer 7).
|
|
UDT_ELETYPE: Element. (Eg. constants Ele_Neutral or Integer 0).
|
|
UDT_ELELEVEL: Element Level.
|
|
UDT_AMOTION: AMotion Rate.
|
|
UDT_ADELAY: ADelay Rate.
|
|
UDT_DMOTION: DMotion Rate.
|
|
UDT_HUNGER: Hunger Rate - for summons.
|
|
UDT_INTIMACY: Intimacy Rate - for summons.
|
|
UDT_LIFETIME: LifeTime - for summons.
|
|
UDT_MERC_KILLCOUNT: Kill count for mercenaries.
|
|
UDT_GROUP: group id
|
|
UDT_DAMAGE_TAKEN_RATE: damage taken rate of a unit.
|
|
UDT_OPTIONS: options
|
|
|
|
returns -1 if value could not be retrieved.
|
|
|
|
---------------------------------------
|
|
|
|
*getunitname(<GID>)
|
|
|
|
Retrieve the name of a unit.
|
|
|
|
returns "Unknown" if the value could not be retrieved.
|
|
|
|
---------------------------------------
|
|
|
|
*setunitname(<GID>, <Name>)
|
|
|
|
Changes the name of a unit.
|
|
|
|
Supported Types - [ MOB | HOM | PET ].
|
|
|
|
returns 1 on success, 0 on failure.
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
13 - Clan System Related Commands
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
*join_clan(<ClanID>{, <account id>})
|
|
|
|
Joins a player into the given clan.
|
|
If no RID is given, will run with the current attached player.
|
|
|
|
returns true on success, false on failure.
|
|
|
|
---------------------------------------
|
|
|
|
*clan_leave({<account id>})
|
|
|
|
Removes a player from its clan.
|
|
If no RID is given, will run with the current attached player.
|
|
|
|
returns true on success, false on failure.
|
|
|
|
---------------------------------------
|
|
|
|
*clan_master(<ClanID>)
|
|
|
|
Enables the Emblem of the given Clan to the current NPC
|
|
|
|
---------------------------------------
|
|
//=====================================
|
|
13 - End of Clan System Related Commands
|
|
//=====================================
|
|
---------------------------------------
|
|
|
|
*airship_respond(<flag>)
|
|
|
|
Send client respond to different private airship status.
|
|
the available flags are:
|
|
P_AIRSHIP_NONE
|
|
P_AIRSHIP_RETRY
|
|
P_AIRSHIP_INVALID_START_MAP
|
|
P_AIRSHIP_INVALID_END_MAP
|
|
P_AIRSHIP_ITEM_NOT_ENOUGH
|
|
P_AIRSHIP_ITEM_INVALID
|
|
|
|
---------------------------------------
|
|
|
|
*openstylist()
|
|
|
|
Opens the styling shop on client
|
|
|
|
---------------------------------------
|
|
|
|
*openbank()
|
|
|
|
Opens the Bank UI on client.
|
|
|
|
---------------------------------------
|
|
|
|
*openquestui({<quest_id>})
|
|
|
|
Opens the Quest UI on client with the most recent added quest in this playing session selected.
|
|
- If <quest_id> is set, shows this quest instead.
|
|
- If the player did not receive new quests in this playing session, or <quest_id> is 0,
|
|
the Quest UI is open with no selected quest.
|
|
|
|
---------------------------------------
|
|
|
|
*opentipboxui({<tip_id = 0>})
|
|
|
|
Opens the TipBox UI on client.
|
|
- If <tip_id> is set, shows this specific tip.
|
|
- If <tip_id> is not set or 0, shows a random tip.
|
|
|
|
---------------------------------------
|
|
|
|
*msgtable(<message_id>{, <color>})
|
|
|
|
Show in client message by <message_id> from msg string table
|
|
with optional <color>.
|
|
|
|
---------------------------------------
|
|
|
|
*msgtable2(<message_id>, <param>{, <color>})
|
|
|
|
Show in client message by <message_id> from msg string table.
|
|
<param> is parameter for this message. Can be string or int.
|
|
Optional <color> can be used for set color for whole message.
|
|
|
|
---------------------------------------
|
|
|
|
*camerainfo()
|
|
|
|
Show or hide camera info window.
|
|
Works for 20160525 clients or newer.
|
|
|
|
---------------------------------------
|
|
|
|
*changecamera(<range>, <rotation>, <latitude>{, <target>})
|
|
|
|
Change camera range, rotation, latitude.
|
|
The optional target parameter specifies who will get changed
|
|
camera.
|
|
Works for 20160525 clients or newer.
|
|
|
|
---------------------------------------
|
|
|
|
*achievement_progress(<ach_id>, <obj_idx>, <progress>, <incremental>{, <account_id>});
|
|
|
|
Make the player progress in the specified achievement.
|
|
aid - achievement ID
|
|
obj_idx - achievement objective index.
|
|
progress - objective progress towards goal.
|
|
incremental - (boolean) true to add the progress towards the goal,
|
|
false to use the progress only as a comparator.
|
|
account_id - (optional) AID to perform on (default to attached player).
|
|
|
|
returns progress on success and false on failure
|
|
|
|
---------------------------------------
|
|
|
|
*achievement_iscompleted(<ach_id>{, <account_id>})
|
|
|
|
Checks whether the attached player have completed all the given achievement objectives.
|
|
|
|
returns true if yes and false if no.
|
|
|
|
---------------------------------------
|
|
|
|
*itempreview(<index>)
|
|
|
|
Update already opened preview window with item from
|
|
inventory with given index.
|
|
Works for 20181017 RE and main clients or newer.
|
|
|
|
---------------------------------------
|
|
|
|
*enchantitem(<equip_pos>, <card_slot>, <card_id>);
|
|
|
|
Insert card into equipped item in EQI_* slot.
|
|
card_slot - can be 0 to 3.
|
|
card_id - any card item id.
|
|
|
|
returns true if all parameters correct
|
|
false in other case.
|
|
Works for 20160831 main, 20151118 RE, any zero version
|
|
|
|
---------------------------------------
|
|
|
|
*servicemessage("<message>", <color>{, <account_id>})
|
|
*servicemessage("<message>", <color>{, <player_name>})
|
|
|
|
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>})
|
|
|
|
Send initial inventory expansion result.
|
|
Normally this function should be called from script label
|
|
inventory_expansion::OnInventoryExpandRequest.
|
|
|
|
Valid result statuses:
|
|
EXPAND_INVENTORY_ASK_CONFIRMATION - force client to ask player about inventory expansion
|
|
EXPAND_INVENTORY_FAILED - other failed reason
|
|
EXPAND_INVENTORY_OTHER_WORK - failed because player busy with other work
|
|
EXPAND_INVENTORY_MISSING_ITEM - failed because missing item
|
|
EXPAND_INVENTORY_MAX_SIZE - failed because inventory size already maximum
|
|
|
|
ItemId make sense only if result is EXPAND_INVENTORY_ASK_CONFIRMATION
|
|
Works for 20181212 zero clients
|
|
|
|
---------------------------------------
|
|
|
|
*expandinventoryresult(<result>)
|
|
|
|
Send final inventory expansion result.
|
|
Normally this function should be called from script label
|
|
inventory_expansion::OnInventoryExpandConfirmed.
|
|
|
|
Valid result values:
|
|
EXPAND_INVENTORY_RESULT_SUCCESS - success message
|
|
EXPAND_INVENTORY_RESULT_FAILED - other failed reason
|
|
EXPAND_INVENTORY_RESULT_OTHER_WORK - failed because player busy with other work
|
|
EXPAND_INVENTORY_RESULT_MISSING_ITEM - failed because missing item
|
|
EXPAND_INVENTORY_RESULT_MAX_SIZE - failed because inventory size already maximum
|
|
|
|
Works for 20181212 zero clients
|
|
|
|
---------------------------------------
|
|
|
|
*expandinventory(<value>)
|
|
|
|
Adjust player inventory to given value.
|
|
Maximum inventory size is MAX_INVENTORY.
|
|
Minimum inventory size is FIXED_INVENTORY_SIZE.
|
|
For supported clients it send inventory change packet. For old clients,
|
|
this change is silent.
|
|
Current max inventory size can be read by function getInventorySize().
|
|
|
|
---------------------------------------
|
|
|
|
*getinventorysize()
|
|
|
|
Return current player max inventory size.
|
|
This value always smaller or equal to MAX_INVENTORY.
|
|
Size can be changed by group of functions expandInventory*
|
|
|
|
---------------------------------------
|
|
|
|
*getunittitle(<GID>)
|
|
|
|
Return unit title string.
|
|
Works for 20180207 main clients, 20171129 re clients, 20171130 zero clients
|
|
|
|
---------------------------------------
|
|
|
|
*setunittitle(<GID>, <title>)
|
|
|
|
Set unit title string.
|
|
Invisible for players, because current implementation using title id only.
|
|
Works for 20180207 main clients, 20171129 re clients, 20171130 zero clients
|
|
|
|
---------------------------------------
|
|
|
|
*closeroulette()
|
|
|
|
Force close roulette window.
|
|
Works for 20141008 main clients, 20140903 re, any zero.
|
|
|
|
---------------------------------------
|
|
*openrefineryui()
|
|
|
|
Opens refinery user interface for the player
|
|
returns true on success and false on failure
|
|
|
|
---------------------------------------
|
|
*openlapineddukddakboxui({<item_id>})
|
|
*openlapineddukddakboxui({<item_name>})
|
|
|
|
Opens lapine ddukddak user interface for the player
|
|
returns true on success and false on failure
|
|
|
|
---------------------------------------
|
|
*openlapineupgradeui({<item_id>})
|
|
*openlapineupgradeui({<item_name>})
|
|
|
|
Opens lapine ddukddak upgrade user interface for the player
|
|
returns true on success and false on failure
|
|
|
|
---------------------------------------
|
|
*getgrade()
|
|
|
|
This function will return the grade level of the equipment from which
|
|
the function is called. This function is intended for use in item scripts.
|
|
|
|
if (getgrade() == 1)
|
|
mes("Wow. That's a 1st grade weapon.");
|
|
|
|
---------------------------------------
|
|
*getequipisenablegrade(<equipment slot>)
|
|
|
|
Will return true if the item equipped on the invoking character in the
|
|
specified equipment slot is gradable, and false if it isn't. For a list
|
|
of equipment slots see getequipid().
|
|
|
|
---------------------------------------
|
|
*getequipgrade(<equipment slot>);
|
|
|
|
Gets the grade level of an equipment.
|
|
|
|
---------------------------------------
|
|
*setdialogalign(<align>);
|
|
|
|
Set vertical or horizontal align in npc dialog.
|
|
Valid aligns:
|
|
horizontal align:
|
|
DIALOG_ALIGN_LEFT
|
|
DIALOG_ALIGN_RIGHT
|
|
DIALOG_ALIGN_CENTER
|
|
vertical align:
|
|
DIALOG_ALIGN_TOP
|
|
DIALOG_ALIGN_MIDDLE
|
|
DIALOG_ALIGN_BOTTOM
|
|
|
|
Works from clients: main 20210203, re 20211103
|
|
|
|
---------------------------------------
|
|
|
|
*setdialogsize(<width>, <height>)
|
|
|
|
Set size for npc dialog.
|
|
|
|
Works from clients: main 20220504.
|
|
|
|
---------------------------------------
|
|
|
|
*setdialogpos(<x>, <y>)
|
|
|
|
Set position for npc dialog in pixels.
|
|
|
|
Works from clients: main 20220504.
|
|
|
|
---------------------------------------
|
|
|
|
*setdialogpospercent(<x>, <y>)
|
|
|
|
Set position for npc dialog in screen size percent.
|
|
|
|
Works from clients: main 20220504.
|
|
|
|
---------------------------------------
|
|
|
|
*opengradeui()
|
|
|
|
Opens Grade Enchant user interface for the player
|
|
returns true on success and false on failure
|
|
|
|
---------------------------------------
|
|
*calldynamicnpc("<npc name>");
|
|
|
|
Creates a dynamic npc copy in range of the player with certain criteria:
|
|
- Only the owner of the npc can see and interact with the npc
|
|
- The npc will despawn after a certain period of inactivity
|
|
|
|
a dynamic npc cannot be created from a FAKE_NPC source
|
|
and it does not run OnInit event when created but rather uses OnDynamicNpcInit.
|
|
returns true on success and false on failure
|
|
|
|
---------------------------------------
|
|
*openreformui(<item id>)
|
|
|
|
Opens Item Reform user interface for the given item
|
|
returns true on success and false on failure
|
|
|
|
---------------------------------------
|
|
*specialpopup(<popup id>)
|
|
|
|
Open popup or/and show chat text by id from list configured in file spopup.lub
|
|
Popup and text visible only if player warped from one map to another map with different name.
|
|
|
|
Works from clients: main 20221005.
|
|
|
|
---------------------------------------
|
|
|
|
*dynamicnpccreateresult(<result>)
|
|
|
|
Send DynamicNPC create request result.
|
|
Normally this function should be called from script label
|
|
dynamicnpc_create::OnRequest.
|
|
|
|
Valid result values:
|
|
- DYNAMICNPC_RESULT_SUCCESS - success (no message)
|
|
- DYNAMICNPC_RESULT_UNKNOWN - shows error "dynamic npc create error (unknown)"
|
|
- DYNAMICNPC_RESULT_NOT_EXIST - shows error "dynamic npc not found"
|
|
- DYNAMICNPC_RESULT_DUPLICATED - shows error from message string MSG_DYNAMICNPC_FAIL_DUPLICATENAME
|
|
(message: "Is already in service. Please try again in a few minutes.")
|
|
|
|
Works for clients 20140430 and newer (any type)
|
|
|
|
---------------------------------------
|
|
|
|
*setgoldpcmode(<mode>{, <played_time>})
|
|
|
|
Changes attached player's current active GoldPC mode to <mode>.
|
|
Optionally, forces the already played time to <played_time> seconds.
|
|
|
|
<mode> may be any Id or Const defined in `db/goldpc_db.conf` or 0 to disabled GoldPC for this character.
|
|
|
|
When <played_time> is not provided, it defaults to -1, and the current played time will be kept.
|
|
|
|
Note: GoldPC changes only applies for current play session, and in the next log in the player's GoldPC will
|
|
be changed back to the one defined in `goldpc/default_mode` feature config (`conf/features.conf`).
|
|
If keeping the GoldPC mode between sessions is desired, you may use OnPCLoginEvent.
|
|
|
|
Check out some examples in `doc/sample/goldpc.txt`.
|
|
|
|
|
|
---------------------------------------
|
|
|
|
*getitemgroupitems(<item_id_array>, <item_group_id>)
|
|
|
|
Fills the array <item_id_array> with the IDs of the items from the <item_group_id> item group, without duplicates.
|
|
|
|
Returns the amount of items inserted into the array.
|
|
|
|
Note: The array will not be automatically cleared. It's recommended to use the returned value to loop over the array instead of relying on getarraysize.
|
|
|
|
The possible values for <item_group_id> can be found in `db/(pre-)re/item_group.conf`
|
|
|
|
Example:
|
|
|
|
.@count = getitemgroupitems(.@item_list[0], Old_Card_Album);
|
|
for (.@i = 0; .@i < .@count; ++.@i) {
|
|
mesf("^1E56BD\t%s^000000", getitemname(.@item_list[.@i]));
|
|
}
|