summaryrefslogtreecommitdiff
path: root/src/map/script.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/script.c')
-rw-r--r--src/map/script.c583
1 files changed, 445 insertions, 138 deletions
diff --git a/src/map/script.c b/src/map/script.c
index 75f747fb6..c23a335c3 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -30,6 +30,7 @@
#include "map/chat.h"
#include "map/chrif.h"
#include "map/clif.h"
+#include "map/date.h"
#include "map/elemental.h"
#include "map/guild.h"
#include "map/homunculus.h"
@@ -136,6 +137,7 @@ const char* script_op2name(int op) {
RETURN_OP_NAME(C_ADD);
RETURN_OP_NAME(C_SUB);
RETURN_OP_NAME(C_MUL);
+ RETURN_OP_NAME(C_POW);
RETURN_OP_NAME(C_DIV);
RETURN_OP_NAME(C_MOD);
RETURN_OP_NAME(C_NEG);
@@ -1035,6 +1037,7 @@ const char* parse_variable(const char* p)
|| ( p[0] == '|' && p[1] == '=' && (type = C_OR, true) ) // |=
|| ( p[0] == '&' && p[1] == '=' && (type = C_AND, true) ) // &=
|| ( p[0] == '*' && p[1] == '=' && (type = C_MUL, true) ) // *=
+ || ( p[0] == '*' && p[1] == '*' && p[2] == '=' && (type = C_POW, true) ) // **=
|| ( p[0] == '/' && p[1] == '=' && (type = C_DIV, true) ) // /=
|| ( p[0] == '%' && p[1] == '=' && (type = C_MOD, true) ) // %=
|| ( p[0] == '+' && p[1] == '+' && (type = C_ADD_POST, true) ) // post ++
@@ -1058,6 +1061,7 @@ const char* parse_variable(const char* p)
case C_L_SHIFT: // <<=
case C_R_SHIFT: // >>=
+ case C_POW: // **=
p = script->skip_space( &p[3] );
break;
@@ -1424,6 +1428,7 @@ const char* script_parse_subexpr(const char* p,int limit)
(op=C_OP3, opl=0, len=1,*p=='?') // ?:
|| (op=C_ADD, opl=9, len=1,*p=='+') // +
|| (op=C_SUB, opl=9, len=1,*p=='-') // -
+ || (op=C_POW, opl=11,len=2,*p=='*' && p[1]=='*') // **
|| (op=C_MUL, opl=10,len=1,*p=='*') // *
|| (op=C_DIV, opl=10,len=1,*p=='/') // /
|| (op=C_MOD, opl=10,len=1,*p=='%') // %
@@ -4146,6 +4151,7 @@ void op_2num(struct script_state* st, int op, int i1, int i2)
case C_ADD: ret = i1 + i2; ret64 = (int64)i1 + i2; break;
case C_SUB: ret = i1 - i2; ret64 = (int64)i1 - i2; break;
case C_MUL: ret = i1 * i2; ret64 = (int64)i1 * i2; break;
+ case C_POW: ret = (int)pow((double)i1, (double)i2); ret64 = (int64)pow((double)i1, (double)i2); break;
default:
ShowError("script:op_2num: unexpected number operator %s i1=%d i2=%d\n", script->op2name(op), i1, i2);
script->reportsrc(st);
@@ -4683,6 +4689,7 @@ void run_script_main(struct script_state *st) {
case C_ADD:
case C_SUB:
case C_MUL:
+ case C_POW:
case C_DIV:
case C_MOD:
case C_EQ:
@@ -5027,6 +5034,8 @@ void do_final_script(void)
aFree(script->str_buf);
for( i = 0; i < atcommand->binding_count; i++ ) {
+ aFree(atcommand->binding[i]->at_groups);
+ aFree(atcommand->binding[i]->char_groups);
aFree(atcommand->binding[i]);
}
@@ -5561,6 +5570,8 @@ int script_reload(void)
script->label_count = 0;
for( i = 0; i < atcommand->binding_count; i++ ) {
+ aFree(atcommand->binding[i]->at_groups);
+ aFree(atcommand->binding[i]->char_groups);
aFree(atcommand->binding[i]);
}
@@ -7028,6 +7039,7 @@ BUILDIN(__setr)
int64 num;
const char* name;
char prefix;
+ struct reg_db *ref;
data = script_getdata(st,2);
//datavalue = script_getdata(st,3);
@@ -7040,11 +7052,11 @@ BUILDIN(__setr)
num = reference_getuid(data);
name = reference_getname(data);
+ ref = reference_getref(data);
prefix = *name;
if (not_server_variable(prefix)) {
- sd = script->rid2sd(st);
- if (sd == NULL) {
+ if (ref == NULL && (sd = script->rid2sd(st)) == NULL) {
ShowError("script:set: no player attached for player variable '%s'\n", name);
return true;
}
@@ -7092,9 +7104,9 @@ BUILDIN(__setr)
}
if (is_string_variable(name))
- script->set_reg(st, sd, num, name, script_getstr(st, 3), script_getref(st, 2));
+ script->set_reg(st, sd, num, name, script_getstr(st, 3), ref);
else
- script->set_reg(st, sd, num, name, (const void *)h64BPTRSIZE(script_getnum(st, 3)), script_getref(st, 2));
+ script->set_reg(st, sd, num, name, (const void *)h64BPTRSIZE(script_getnum(st, 3)), ref);
return true;
}
@@ -7314,6 +7326,22 @@ int script_array_index_cmp(const void *a, const void *b)
return (*(const unsigned int *)a - *(const unsigned int *)b); // FIXME: Is the unsigned difference really intended here?
}
+BUILDIN(getarrayindex)
+{
+ struct script_data *data = script_getdata(st, 2);
+
+ if (!data_isreference(data) || reference_toconstant(data))
+ {
+ ShowError("script:getarrayindex: not a variable\n");
+ script->reportdata(data);
+ st->state = END;
+ return false;// not a variable
+ }
+
+ script_pushint(st, reference_getindex(data));
+ return true;
+}
+
/// Deletes count or all the elements in an array, from the starting index.
/// ex: deletearray arr[4],2;
///
@@ -8568,20 +8596,26 @@ BUILDIN(disableitemuse)
BUILDIN(readparam) {
int type;
struct map_session_data *sd;
+ struct script_data *data = script_getdata(st, 2);
- type=script_getnum(st,2);
- if (script_hasdata(st,3))
- sd = script->nick2sd(st, script_getstr(st,3));
- else
- sd=script->rid2sd(st);
+ if (reference_toparam(data)) {
+ type = reference_getparamtype(data);
+ } else {
+ type = script->conv_num(st, data);
+ }
+
+ if (script_hasdata(st, 3)) {
+ sd = script->nick2sd(st, script_getstr(st, 3));
+ } else {
+ sd = script->rid2sd(st);
+ }
if (sd == NULL) {
- script_pushint(st,-1);
+ script_pushint(st, -1);
return true;
}
- script_pushint(st,pc->readparam(sd,type));
-
+ script_pushint(st, pc->readparam(sd, type));
return true;
}
@@ -9338,20 +9372,32 @@ BUILDIN(getequipweaponlv)
* 0 : false (max refine level or unequip..)
*------------------------------------------*/
BUILDIN(getequippercentrefinery) {
- int i = -1,num;
+ int i = -1, num;
struct map_session_data *sd;
+ int type = 0;
+
+ num = script_getnum(st, 2);
+ type = (script_hasdata(st, 3)) ? script_getnum(st, 3) : REFINE_CHANCE_TYPE_NORMAL;
- num = script_getnum(st,2);
sd = script->rid2sd(st);
- if( sd == NULL )
+ if (sd == NULL)
return true;
+ if (type < REFINE_CHANCE_TYPE_NORMAL || type >= REFINE_CHANCE_TYPE_MAX) {
+ ShowError("buildin_getequippercentrefinery: Invalid type (%d) provided!\n", type);
+ script_pushint(st, 0);
+ return false;
+ }
+
+
if (num > 0 && num <= ARRAYLENGTH(script->equip))
- i=pc->checkequip(sd,script->equip[num-1]);
- if(i >= 0 && sd->status.inventory[i].nameid && sd->status.inventory[i].refine < MAX_REFINE)
- script_pushint(st,status->get_refine_chance(itemdb_wlv(sd->status.inventory[i].nameid), (int)sd->status.inventory[i].refine));
+ i = pc->checkequip(sd, script->equip[num - 1]);
+
+ if (i >= 0 && sd->status.inventory[i].nameid != 0 && sd->status.inventory[i].refine < MAX_REFINE)
+ script_pushint(st,
+ status->get_refine_chance(itemdb_wlv(sd->status.inventory[i].nameid), (int) sd->status.inventory[i].refine, (enum refine_chance_type) type));
else
- script_pushint(st,0);
+ script_pushint(st, 0);
return true;
}
@@ -10591,7 +10637,7 @@ BUILDIN(guildchangegm)
if (sd == NULL)
script_pushint(st,0);
else
- script_pushint(st,guild->gm_change(guild_id, sd));
+ script_pushint(st, guild->gm_change(guild_id, sd->status.char_id));
return true;
}
@@ -13415,113 +13461,98 @@ BUILDIN(getequipcardcnt)
/// Removes all cards from the item found in the specified equipment slot of the invoking character,
/// and give them to the character. If any cards were removed in this manner, it will also show a success effect.
-/// successremovecards <slot>;
+/// successremovecards(<slot>);
BUILDIN(successremovecards)
{
- int i=-1,c,cardflag=0;
+ int i = -1, c, cardflag = 0;
struct map_session_data *sd = script->rid2sd(st);
- int num = script_getnum(st,2);
+ int num = script_getnum(st, 2);
if (sd == NULL)
return true;
if (num > 0 && num <= ARRAYLENGTH(script->equip))
- i=pc->checkequip(sd,script->equip[num-1]);
+ i = pc->checkequip(sd,script->equip[num - 1]);
- if (i < 0 || !sd->inventory_data[i]) {
+ if (i < 0 || sd->inventory_data[i] == NULL)
return true;
- }
- if(itemdb_isspecial(sd->status.inventory[i].card[0]))
+ if (itemdb_isspecial(sd->status.inventory[i].card[0]))
return true;
- for( c = sd->inventory_data[i]->slot - 1; c >= 0; --c ) {
- if( sd->status.inventory[i].card[c] && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD ) {// extract this card from the item
+ for (c = sd->inventory_data[i]->slot - 1; c >= 0; --c) {
+ if (sd->status.inventory[i].card[c] > 0 && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD) {
int flag;
struct item item_tmp;
- memset(&item_tmp,0,sizeof(item_tmp));
+
+ memset(&item_tmp, 0, sizeof(item_tmp));
+
cardflag = 1;
- item_tmp.nameid = sd->status.inventory[i].card[c];
+ item_tmp.nameid = sd->status.inventory[i].card[c];
item_tmp.identify = 1;
+ sd->status.inventory[i].card[c] = 0;
- if((flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))) {
- // get back the cart in inventory
- clif->additem(sd,0,0,flag);
+ if ((flag = pc->additem(sd, &item_tmp, 1, LOG_TYPE_SCRIPT))) {
+ clif->additem(sd, 0, 0, flag);
map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
}
}
}
if (cardflag == 1) {
- //if card was remove replace item with no card
- int flag, j;
- struct item item_tmp;
- memset(&item_tmp,0,sizeof(item_tmp));
-
- item_tmp.nameid = sd->status.inventory[i].nameid;
- item_tmp.identify = 1;
- item_tmp.refine = sd->status.inventory[i].refine;
- item_tmp.attribute = sd->status.inventory[i].attribute;
- item_tmp.expire_time = sd->status.inventory[i].expire_time;
- item_tmp.bound = sd->status.inventory[i].bound;
-
- for (j = sd->inventory_data[i]->slot; j < MAX_SLOTS; j++)
- item_tmp.card[j]=sd->status.inventory[i].card[j];
-
- pc->delitem(sd, i, 1, 0, DELITEM_MATERIALCHANGE, LOG_TYPE_SCRIPT);
- if ((flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))) {
- //chk if can be spawn in inventory otherwise put on floor
- clif->additem(sd,0,0,flag);
- map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
- }
-
+ pc->unequipitem(sd, i, PCUNEQUIPITEM_FORCE);
+ clif->delitem(sd, i, 1, DELITEM_MATERIALCHANGE);
+ clif->additem(sd, i, 1, 0);
+ pc->equipitem(sd, i, sd->status.inventory[i].equip);
clif->misceffect(&sd->bl,3);
}
return true;
}
/// Removes all cards from the item found in the specified equipment slot of the invoking character.
-/// failedremovecards <slot>, <type>;
+/// failedremovecards(<slot>, <type>);
/// <type>=0 : will destroy both the item and the cards.
/// <type>=1 : will keep the item, but destroy the cards.
/// <type>=2 : will keep the cards, but destroy the item.
-/// <type>=? : will just display the failure effect.
+/// <type>=3 : will just display the failure effect.
BUILDIN(failedremovecards)
{
- int i=-1,c,cardflag=0;
+ int i = -1, c, cardflag = 0;
+ int num = script_getnum(st, 2);
+ int typefail = script_getnum(st, 3);
struct map_session_data *sd = script->rid2sd(st);
- int num = script_getnum(st,2);
- int typefail = script_getnum(st,3);
if (sd == NULL)
return true;
if (num > 0 && num <= ARRAYLENGTH(script->equip))
- i=pc->checkequip(sd,script->equip[num-1]);
+ i = pc->checkequip(sd, script->equip[num - 1]);
- if (i < 0 || !sd->inventory_data[i])
+ if (i < 0 || sd->inventory_data[i] == NULL)
return true;
- if(itemdb_isspecial(sd->status.inventory[i].card[0]))
+ if (itemdb_isspecial(sd->status.inventory[i].card[0]))
return true;
- for( c = sd->inventory_data[i]->slot - 1; c >= 0; --c ) {
- if( sd->status.inventory[i].card[c] && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD ) {
+ for (c = sd->inventory_data[i]->slot - 1; c >= 0; --c) {
+ if (sd->status.inventory[i].card[c] > 0 && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD) {
cardflag = 1;
- if(typefail == 2) {// add cards to inventory, clear
+ sd->status.inventory[i].card[c] = 0;
+
+ if (typefail == 2) { // add cards to inventory, clear
int flag;
struct item item_tmp;
- memset(&item_tmp,0,sizeof(item_tmp));
+ memset(&item_tmp, 0, sizeof(item_tmp));
- item_tmp.nameid = sd->status.inventory[i].card[c];
+ item_tmp.nameid = sd->status.inventory[i].card[c];
item_tmp.identify = 1;
- if((flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))) {
- clif->additem(sd,0,0,flag);
+ if ((flag = pc->additem(sd, &item_tmp, 1, LOG_TYPE_SCRIPT))) {
+ clif->additem(sd, 0, 0, flag);
map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
}
}
@@ -13529,35 +13560,16 @@ BUILDIN(failedremovecards)
}
if (cardflag == 1) {
- if (typefail == 0 || typefail == 2) {
- // destroy the item
+ if (typefail == 0 || typefail == 2) { // destroy the item
pc->delitem(sd, i, 1, 0, DELITEM_FAILREFINE, LOG_TYPE_SCRIPT);
} else if (typefail == 1) {
- // destroy the card
- int flag, j;
- struct item item_tmp;
-
- memset(&item_tmp,0,sizeof(item_tmp));
-
- item_tmp.nameid = sd->status.inventory[i].nameid;
- item_tmp.identify = 1;
- item_tmp.refine = sd->status.inventory[i].refine;
- item_tmp.attribute = sd->status.inventory[i].attribute;
- item_tmp.expire_time = sd->status.inventory[i].expire_time;
- item_tmp.bound = sd->status.inventory[i].bound;
-
- for (j = sd->inventory_data[i]->slot; j < MAX_SLOTS; j++)
- item_tmp.card[j]=sd->status.inventory[i].card[j];
-
- pc->delitem(sd, i, 1, 0, DELITEM_FAILREFINE, LOG_TYPE_SCRIPT);
-
- if((flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))) {
- clif->additem(sd,0,0,flag);
- map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0);
- }
+ pc->unequipitem(sd, i, PCUNEQUIPITEM_FORCE);
+ clif->delitem(sd, i, 1, DELITEM_MATERIALCHANGE);
+ clif->additem(sd, i, 1, 0);
+ pc->equipitem(sd, i, sd->status.inventory[i].equip);
}
- clif->misceffect(&sd->bl,2);
}
+ clif->misceffect(&sd->bl, 2);
return true;
}
@@ -14054,7 +14066,7 @@ BUILDIN(getequippedoptioninfo)
/**
* Gets the option information of an equipment.
- * *getequipoptioninfo(<equip_index>,<slot>,<type>);
+ * *getequipoption(<equip_index>,<slot>,<type>);
*
* @param equip_index as the Index of the Equipment.
* @param slot as the slot# of the Item Option (1 to MAX_ITEM_OPTIONS)
@@ -14071,24 +14083,24 @@ BUILDIN(getequipoption)
if (sd == NULL) {
script_pushint(st, -1);
- ShowError("buildin_getequipoptioninfo: Player not attached!\n");
+ ShowError("buildin_getequipoption: Player not attached!\n");
return false;
}
if (slot <= 0 || slot > MAX_ITEM_OPTIONS) {
script_pushint(st, -1);
- ShowError("buildin_getequipoptioninfo: Invalid option slot %d (Min: 1, Max: %d) provided.\n", slot, MAX_ITEM_OPTIONS);
+ ShowError("buildin_getequipoption: Invalid option slot %d (Min: 1, Max: %d) provided.\n", slot, MAX_ITEM_OPTIONS);
return false;
}
if (equip_index > 0 && equip_index <= ARRAYLENGTH(script->equip)) {
if ((i = pc->checkequip(sd, script->equip[equip_index - 1])) == -1) {
- ShowError("buildin_getequipoptioninfo: No equipment is equipped in the given index %d.\n", equip_index);
+ ShowError("buildin_getequipoption: No equipment is equipped in the given index %d.\n", equip_index);
script_pushint(st, -1);
return false;
}
} else {
- ShowError("buildin_getequipoptioninfo: Invalid equipment index %d provided.\n", equip_index);
+ ShowError("buildin_getequipoption: Invalid equipment index %d provided.\n", equip_index);
script_pushint(st, 0);
return false;
}
@@ -14102,7 +14114,7 @@ BUILDIN(getequipoption)
val = sd->status.inventory[i].option[slot-1].value;
break;
default:
- ShowError("buildin_geteqiupoptioninfo: Invalid option data type %d provided.\n", opt_type);
+ ShowError("buildin_getequipoption: Invalid option data type %d provided.\n", opt_type);
script_pushint(st, -1);
break;
}
@@ -14850,24 +14862,40 @@ BUILDIN(npcskilleffect) {
*------------------------------------------*/
BUILDIN(specialeffect) {
struct block_list *bl = NULL;
- int type = script_getnum(st,2);
- enum send_target target = script_hasdata(st,3) ? (send_target)script_getnum(st,3) : AREA;
+ int type = script_getnum(st, 2);
+ enum send_target target = AREA;
- if (script_hasdata(st,4)) {
- struct npc_data *nd = npc->name2id(script_getstr(st,4));
- if (nd != NULL)
- bl = &nd->bl;
+ if (script_hasdata(st, 3)) {
+ target = script_getnum(st, 3);
+ }
+
+ if (script_hasdata(st, 4)) {
+ if (script_isstringtype(st, 4)) {
+ struct npc_data *nd = npc->name2id(script_getstr(st, 4));
+ if (nd != NULL) {
+ bl = &nd->bl;
+ }
+ } else {
+ bl = map->id2bl(script_getnum(st, 4));
+ }
} else {
bl = map->id2bl(st->oid);
}
- if (bl == NULL)
+ if (bl == NULL) {
return true;
+ }
if (target == SELF) {
- struct map_session_data *sd = script->rid2sd(st);
- if (sd != NULL)
+ struct map_session_data *sd;
+ if (script_hasdata(st, 5)) {
+ sd = map->id2sd(script_getnum(st, 5));
+ } else {
+ sd = script->rid2sd(st);
+ }
+ if (sd != NULL) {
clif->specialeffect_single(bl, type, sd->fd);
+ }
} else {
clif->specialeffect(bl, type, target);
}
@@ -14983,22 +15011,62 @@ BUILDIN(dispbottom)
* All The Players Full Recovery
* (HP/SP full restore and resurrect if need)
*------------------------------------------*/
+int buildin_recovery_sub(struct map_session_data *sd)
+{
+ nullpo_retr(0, sd);
+
+ if (pc_isdead(sd)) {
+ status->revive(&sd->bl, 100, 100);
+ } else {
+ status_percent_heal(&sd->bl, 100, 100);
+ }
+
+ return 0;
+}
+
+int buildin_recovery_pc_sub(struct map_session_data *sd, va_list ap)
+{
+ return script->buildin_recovery_sub(sd);
+}
+
+int buildin_recovery_bl_sub(struct block_list *bl, va_list ap)
+{
+ return script->buildin_recovery_sub(BL_CAST(BL_PC, bl));
+}
+
BUILDIN(recovery)
{
- struct map_session_data *sd;
- struct s_mapiterator* iter;
+ if (script_hasdata(st, 2)) {
+ if (script_isstringtype(st, 2)) {
+ int16 m = map->mapname2mapid(script_getstr(st, 2));
- iter = mapit_getallusers();
- for (sd = BL_UCAST(BL_PC, mapit->first(iter)); mapit->exists(iter); sd = BL_UCAST(BL_PC, mapit->next(iter))) {
- if(pc_isdead(sd))
- status->revive(&sd->bl, 100, 100);
- else
- status_percent_heal(&sd->bl, 100, 100);
- clif->message(sd->fd,msg_sd(sd,880)); // "You have been recovered!"
+ if (m == -1) {
+ ShowWarning("script:recovery: invalid map!\n");
+ return false;
+ }
+
+ if (script_hasdata(st, 6)) {
+ int16 x1 = script_getnum(st, 3);
+ int16 y1 = script_getnum(st, 4);
+ int16 x2 = script_getnum(st, 5);
+ int16 y2 = script_getnum(st, 6);
+ map->foreachinarea(script->buildin_recovery_bl_sub, m, x1, y1, x2, y2, BL_PC);
+ } else {
+ map->foreachinmap(script->buildin_recovery_bl_sub, m, BL_PC);
+ }
+ } else {
+ struct map_session_data *sd = script->id2sd(st, script_getnum(st, 2));
+
+ if (sd != NULL) {
+ script->buildin_recovery_sub(sd);
+ }
+ }
+ } else {
+ map->foreachpc(script->buildin_recovery_pc_sub);
}
- mapit->free(iter);
return true;
}
+
/*==========================================
* Get your pet info: getpetinfo(n)
* n -> 0:pet_id 1:pet_class 2:pet_name
@@ -16132,6 +16200,80 @@ BUILDIN(charat) {
}
//=======================================================
+// isstr <argument>
+//
+// returns type:
+// 0 - int
+// 1 - string
+// 2 - other
+//-------------------------------------------------------
+BUILDIN(isstr)
+{
+ if (script_isinttype(st, 2)) {
+ script_pushint(st, 0);
+ } else if (script_isstringtype(st, 2)) {
+ script_pushint(st, 1);
+ } else {
+ script_pushint(st, 2);
+ }
+ return true;
+}
+
+enum datatype {
+ DATATYPE_NIL = 1 << 7, // we don't start at 1, to leave room for primitives
+ DATATYPE_STR = 1 << 8,
+ DATATYPE_INT = 1 << 9,
+ DATATYPE_CONST = 1 << 10,
+ DATATYPE_PARAM = 1 << 11,
+ DATATYPE_VAR = 1 << 12,
+ DATATYPE_LABEL = 1 << 13,
+};
+
+BUILDIN(getdatatype) {
+ int type;
+
+ if (script_hasdata(st, 2)) {
+ struct script_data *data = script_getdata(st, 2);
+
+ if (data_isstring(data)) {
+ type = DATATYPE_STR;
+ if (data->type == C_CONSTSTR) {
+ type |= DATATYPE_CONST;
+ }
+ } else if (data_isint(data)) {
+ type = DATATYPE_INT;
+ } else if (data_islabel(data)) {
+ type = DATATYPE_LABEL;
+ } else if (data_isreference(data)) {
+ if (reference_toconstant(data)) {
+ type = DATATYPE_CONST | DATATYPE_INT;
+ } else if (reference_toparam(data)) {
+ type = DATATYPE_PARAM | DATATYPE_INT;
+ } else if (reference_tovariable(data)) {
+ type = DATATYPE_VAR;
+ if (is_string_variable(reference_getname(data))) {
+ type |= DATATYPE_STR;
+ } else {
+ type |= DATATYPE_INT;
+ }
+ } else {
+ ShowError("script:getdatatype: Unknown reference type!\n");
+ script->reportdata(data);
+ st->state = END;
+ return false;
+ }
+ } else {
+ type = data->type; // fallback to primitive type if unknown
+ }
+ } else {
+ type = DATATYPE_NIL; // nothing was passed
+ }
+
+ script_pushint(st, type);
+ return true;
+}
+
+//=======================================================
// chr <int>
//-------------------------------------------------------
BUILDIN(chr)
@@ -16952,6 +17094,7 @@ BUILDIN(swap)
{
struct map_session_data *sd = NULL;
struct script_data *data1, *data2;
+ struct reg_db *ref1, *ref2;
const char *varname1, *varname2;
int64 uid1, uid2;
@@ -16992,6 +17135,8 @@ BUILDIN(swap)
uid1 = reference_getuid(data1);
uid2 = reference_getuid(data2);
+ ref1 = reference_getref(data1);
+ ref2 = reference_getref(data2);
if (is_string_variable(varname1)) {
const char *value1, *value2;
@@ -17000,8 +17145,8 @@ BUILDIN(swap)
value2 = script_getstr(st,3);
if (strcmpi(value1, value2)) {
- script->set_reg(st, sd, uid1, varname1, value2, script_getref(st,3));
- script->set_reg(st, sd, uid2, varname2, value1, script_getref(st,2));
+ script->set_reg(st, sd, uid1, varname1, value2, ref1);
+ script->set_reg(st, sd, uid2, varname2, value1, ref2);
}
}
else {
@@ -17011,8 +17156,8 @@ BUILDIN(swap)
value2 = script_getnum(st,3);
if (value1 != value2) {
- script->set_reg(st, sd, uid1, varname1, (const void *)h64BPTRSIZE(value2), script_getref(st,3));
- script->set_reg(st, sd, uid2, varname2, (const void *)h64BPTRSIZE(value1), script_getref(st,2));
+ script->set_reg(st, sd, uid1, varname1, (const void *)h64BPTRSIZE(value2), ref1);
+ script->set_reg(st, sd, uid2, varname2, (const void *)h64BPTRSIZE(value1), ref2);
}
}
return true;
@@ -20193,19 +20338,21 @@ BUILDIN(setquest)
{
unsigned short i;
int quest_id;
+ unsigned int time_limit;
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
return true;
quest_id = script_getnum(st, 2);
+ time_limit = script_hasdata(st, 3) ? script_getnum(st, 3) : 0;
- quest->add(sd, quest_id);
+ quest->add(sd, quest_id, time_limit);
// If questinfo is set, remove quest bubble once quest is set.
- for(i = 0; i < map->list[sd->bl.m].qi_count; i++) {
+ for (i = 0; i < map->list[sd->bl.m].qi_count; i++) {
struct questinfo *qi = &map->list[sd->bl.m].qi_data[i];
- if( qi->quest_id == quest_id ) {
+ if (qi->quest_id == quest_id) {
#if PACKETVER >= 20120410
clif->quest_show_event(sd, &qi->nd->bl, 9999, 0);
#else
@@ -21499,6 +21646,43 @@ BUILDIN(issit)
return true;
}
+BUILDIN(add_group_command)
+{
+ AtCommandInfo *acmd_d;
+ struct atcmd_binding_data *bcmd_d;
+ GroupSettings *group;
+ int group_index;
+ const char *atcmd = script_getstr(st, 2);
+ int group_id = script_getnum(st, 3);
+ bool self_perm = (script_getnum(st, 4) == 1);
+ bool char_perm = (script_getnum(st, 5) == 1);
+
+ if (!pcg->exists(group_id)) {
+ ShowWarning("script:add_group_command: group does not exist: %i\n", group_id);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ group = pcg->id2group(group_id);
+ group_index = pcg->get_idx(group);
+
+ if ((bcmd_d = atcommand->get_bind_byname(atcmd)) != NULL) {
+ bcmd_d->at_groups[group_index] = self_perm;
+ bcmd_d->char_groups[group_index] = char_perm;
+ script_pushint(st, 1);
+ return true;
+ } else if ((acmd_d = atcommand->get_info_byname(atcmd)) != NULL) {
+ acmd_d->at_groups[group_index] = self_perm;
+ acmd_d->char_groups[group_index] = char_perm;
+ script_pushint(st, 1);
+ return true;
+ }
+
+ ShowWarning("script:add_group_command: command does not exist: %s\n", atcmd);
+ script_pushint(st, 0);
+ return false;
+}
+
/**
* @commands (script based)
**/
@@ -21548,6 +21732,8 @@ BUILDIN(bindatcmd)
atcommand->binding[i]->group_lv = group_lv;
atcommand->binding[i]->group_lv_char = group_lv_char;
atcommand->binding[i]->log = log;
+ CREATE(atcommand->binding[i]->at_groups, char, db_size(pcg->db));
+ CREATE(atcommand->binding[i]->char_groups, char, db_size(pcg->db));
}
return true;
@@ -21571,6 +21757,8 @@ BUILDIN(unbindatcmd)
ARR_FIND(0, atcommand->binding_count, i, strcmp(atcommand->binding[i]->command, atcmd) == 0);
if( i < atcommand->binding_count ) {
int cursor = 0;
+ aFree(atcommand->binding[i]->at_groups);
+ aFree(atcommand->binding[i]->char_groups);
aFree(atcommand->binding[i]);
atcommand->binding[i] = NULL;
/* compact the list now that we freed a slot somewhere */
@@ -22918,7 +23106,7 @@ BUILDIN(shopcount)
*/
BUILDIN(channelmes)
{
- struct map_session_data *sd = script->rid2sd(st);
+ struct map_session_data *sd = map->id2sd(st->rid);
const char *channelname = script_getstr(st, 2);
struct channel_data *chan = channel->search(channelname, sd);
@@ -22936,9 +23124,10 @@ BUILDIN(channelmes)
BUILDIN(addchannelhandler)
{
int i;
+ struct map_session_data *sd = map->id2sd(st->rid);
const char *channelname = script_getstr(st, 2);
const char *eventname = script_getstr(st, 3);
- struct channel_data *chan = channel->search(channelname, NULL);
+ struct channel_data *chan = channel->search(channelname, sd);
if (!chan) {
script_pushint(st, 0);
@@ -22961,9 +23150,10 @@ BUILDIN(addchannelhandler)
BUILDIN(removechannelhandler)
{
int i;
+ struct map_session_data *sd = map->id2sd(st->rid);
const char *channelname = script_getstr(st, 2);
const char *eventname = script_getstr(st, 3);
- struct channel_data *chan = channel->search(channelname, NULL);
+ struct channel_data *chan = channel->search(channelname, sd);
if (!chan) {
script_pushint(st, 0);
@@ -23025,6 +23215,100 @@ BUILDIN(mergeitem)
return true;
}
+// getcalendartime(<day of month>, <day of week>{, <hour>{, <minute>}});
+// Returns the UNIX Timestamp of next ocurrency of given time
+BUILDIN(getcalendartime)
+{
+ struct tm info = { 0 };
+ int day_of_month = script_hasdata(st, 4) ? script_getnum(st, 4) : -1;
+ int day_of_week = script_hasdata(st, 5) ? script_getnum(st, 5) : -1;
+ int year = date_get_year();
+ int month = date_get_month();
+ int day = date_get_day();
+ int cur_hour = date_get_hour();
+ int cur_min = date_get_min();
+ int hour = script_getnum(st, 2);
+ int minute = script_getnum(st, 3);
+
+ info.tm_sec = 0;
+ info.tm_min = minute;
+ info.tm_hour = hour;
+ info.tm_mday = day;
+ info.tm_mon = month - 1;
+ info.tm_year = year - 1900;
+
+ if (day_of_month > -1 && day_of_week > -1) {
+ ShowError("script:getcalendartime: You must only specify a day_of_week or a day_of_month, not both\n");
+ script_pushint(st, -1);
+ return false;
+ }
+ if (day_of_month > -1 && (day_of_month < 1 || day_of_month > 31)) {
+ ShowError("script:getcalendartime: Day of Month in invalid range. Must be between 1 and 31.\n");
+ script_pushint(st, -1);
+ return false;
+ }
+ if (day_of_week > -1 && (day_of_week < 0 || day_of_week > 6)) {
+ ShowError("script:getcalendartime: Day of Week in invalid range. Must be between 0 and 6.\n");
+ script_pushint(st, -1);
+ return false;
+ }
+ if (hour > -1 && (hour > 23)) {
+ ShowError("script:getcalendartime: Hour in invalid range. Must be between 0 and 23.\n");
+ script_pushint(st, -1);
+ return false;
+ }
+ if (minute > -1 && (minute > 59)) {
+ ShowError("script:getcalendartime: Minute in invalid range. Must be between 0 and 59.\n");
+ script_pushint(st, -1);
+ return false;
+ }
+ if (hour == -1 || minute == -1) {
+ ShowError("script:getcalendartime: Minutes and Hours are required\n");
+ script_pushint(st, -1);
+ return false;
+ }
+
+ if (day_of_month > -1) {
+ if (day_of_month < day) { // Next Month
+ info.tm_mon++;
+ } else if (day_of_month == day) { // Today
+ if (hour < cur_hour || (hour == cur_hour && minute < cur_min)) { // But past time, next month
+ info.tm_mon++;
+ }
+ }
+
+ // Loops until month has finding a month that has day_of_month
+ do {
+ time_t t;
+ struct tm *lt;
+ info.tm_mday = day_of_month;
+ t = mktime(&info);
+ lt = localtime(&t);
+ info = *lt;
+ } while (info.tm_mday != day_of_month);
+ } else if (day_of_week > -1) {
+ int cur_wday = date_get_dayofweek();
+
+ if (day_of_week > cur_wday) { // This week
+ info.tm_mday += (day_of_week - cur_wday);
+ } else if (day_of_week == cur_wday) { // Today
+ if (hour < cur_hour || (hour == cur_hour && minute <= cur_min)) {
+ info.tm_mday += 7; // Next week
+ }
+ } else if (day_of_week < cur_wday) { // Next week
+ info.tm_mday += (7 - cur_wday + day_of_week);
+ }
+ } else if (day_of_week == -1 && day_of_month == -1) { // Next occurence of hour/min
+ if (hour < cur_hour || (hour == cur_hour && minute < cur_min)) {
+ info.tm_mday++;
+ }
+ }
+
+ script_pushint(st, mktime(&info));
+
+ return true;
+}
+
/** place holder for the translation macro **/
BUILDIN(_)
{
@@ -23277,6 +23561,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(cleararray,"rvi"),
BUILDIN_DEF(copyarray,"rri"),
BUILDIN_DEF(getarraysize,"r"),
+ BUILDIN_DEF(getarrayindex,"r"),
BUILDIN_DEF(deletearray,"r?"),
BUILDIN_DEF(getelementofarray,"ri"),
BUILDIN_DEF(getitem,"vi?"),
@@ -23324,7 +23609,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(getequipisidentify,"i"),
BUILDIN_DEF(getequiprefinerycnt,"i"),
BUILDIN_DEF(getequipweaponlv,"i"),
- BUILDIN_DEF(getequippercentrefinery,"i"),
+ BUILDIN_DEF(getequippercentrefinery,"i?"),
BUILDIN_DEF(successrefitem,"i?"),
BUILDIN_DEF(failedrefitem,"i"),
BUILDIN_DEF(downrefitem,"i?"),
@@ -23464,7 +23749,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(getskilllist,""),
BUILDIN_DEF(clearitem,""),
BUILDIN_DEF(classchange,"ii?"),
- BUILDIN_DEF(misceffect,"i"),
+ BUILDIN_DEF_DEPRECATED(misceffect,"i"),
BUILDIN_DEF(playbgm,"s"),
BUILDIN_DEF(playbgmall,"s?????"),
BUILDIN_DEF(soundeffect,"si"),
@@ -23479,8 +23764,8 @@ void script_parse_builtin(void) {
BUILDIN_DEF(petskillsupport,"viiii"), // [Skotlex]
BUILDIN_DEF(skilleffect,"vi"), // skill effect [Celest]
BUILDIN_DEF(npcskilleffect,"viii"), // npc skill effect [Valaris]
- BUILDIN_DEF(specialeffect,"i??"), // npc skill effect [Valaris]
- BUILDIN_DEF(specialeffect2,"i??"), // skill effect on players[Valaris]
+ BUILDIN_DEF(specialeffect,"i???"), // npc skill effect [Valaris]
+ BUILDIN_DEF_DEPRECATED(specialeffect2,"i??"), // skill effect on players[Valaris]
BUILDIN_DEF(nude,""), // nude command [Valaris]
BUILDIN_DEF(mapwarp,"ssii??"), // Added by RoVeRT
BUILDIN_DEF(atcommand,"s"), // [MouseJstr]
@@ -23519,7 +23804,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(pcre_match,"ss"),
BUILDIN_DEF(dispbottom,"s?"), //added from jA [Lupus]
BUILDIN_DEF(getusersname,""),
- BUILDIN_DEF(recovery,""),
+ BUILDIN_DEF(recovery,"?????"),
BUILDIN_DEF(getpetinfo,"i"),
BUILDIN_DEF(gethominfo,"i"),
BUILDIN_DEF(getmercinfo,"i?"),
@@ -23529,6 +23814,8 @@ void script_parse_builtin(void) {
BUILDIN_DEF(getstrlen,"s"), //strlen [Valaris]
BUILDIN_DEF(charisalpha,"si"), //isalpha [Valaris]
BUILDIN_DEF(charat,"si"),
+ BUILDIN_DEF(isstr,"v"),
+ BUILDIN_DEF(getdatatype, "?"),
BUILDIN_DEF(chr,"i"),
BUILDIN_DEF(ord,"s"),
BUILDIN_DEF(setchar,"ssi"),
@@ -23559,7 +23846,7 @@ void script_parse_builtin(void) {
// List of mathematics commands --->
BUILDIN_DEF(log10,"i"),
BUILDIN_DEF(sqrt,"i"), //[zBuffer]
- BUILDIN_DEF(pow,"ii"), //[zBuffer]
+ BUILDIN_DEF_DEPRECATED(pow,"ii"), //[zBuffer]
BUILDIN_DEF(distance,"iiii"), //[zBuffer]
// <--- List of mathematics commands
BUILDIN_DEF(min, "i*"),
@@ -23719,6 +24006,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(useatcmd, "s"),
BUILDIN_DEF(has_permission, "v?"),
BUILDIN_DEF(can_use_command, "s?"),
+ BUILDIN_DEF(add_group_command, "siii"),
/**
* Item bound [Xantara] [Akinari] [Mhalicot/Hercules]
@@ -23730,7 +24018,7 @@ void script_parse_builtin(void) {
//Quest Log System [Inkfish]
BUILDIN_DEF(questinfo, "ii??"),
- BUILDIN_DEF(setquest, "i"),
+ BUILDIN_DEF(setquest, "i?"),
BUILDIN_DEF(erasequest, "i?"),
BUILDIN_DEF(completequest, "i?"),
BUILDIN_DEF(questprogress, "i?"),
@@ -23782,6 +24070,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(removechannelhandler, "ss"),
BUILDIN_DEF(showscript, "s?"),
BUILDIN_DEF(mergeitem,""),
+ BUILDIN_DEF(getcalendartime, "ii??"),
BUILDIN_DEF(_,"s"),
BUILDIN_DEF2(_, "_$", "s"),
};
@@ -23967,6 +24256,12 @@ void script_hardcoded_constants(void)
script->set_constant("BL_CHAR",BL_CHAR,false, false);
script->set_constant("BL_ALL",BL_ALL,false, false);
+ script->constdb_comment("Refine Chance Types");
+ script->set_constant("REFINE_CHANCE_TYPE_NORMAL", REFINE_CHANCE_TYPE_NORMAL, false, false);
+ script->set_constant("REFINE_CHANCE_TYPE_ENRICHED", REFINE_CHANCE_TYPE_ENRICHED, false, false);
+ script->set_constant("REFINE_CHANCE_TYPE_E_NORMAL", REFINE_CHANCE_TYPE_E_NORMAL, false, false);
+ script->set_constant("REFINE_CHANCE_TYPE_E_ENRICHED", REFINE_CHANCE_TYPE_E_ENRICHED, false, false);
+
script->constdb_comment("Player permissions");
script->set_constant("PERM_TRADE", PC_PERM_TRADE, false, false);
script->set_constant("PERM_PARTY", PC_PERM_PARTY, false, false);
@@ -23995,6 +24290,15 @@ void script_hardcoded_constants(void)
script->set_constant("PERM_DISABLE_EXP", PC_PERM_DISABLE_EXP, false, false);
script->set_constant("PERM_DISABLE_SKILL_USAGE", PC_PERM_DISABLE_SKILL_USAGE, false, false);
+ script->constdb_comment("Data types");
+ script->set_constant("DATATYPE_NIL", DATATYPE_NIL, false, false);
+ script->set_constant("DATATYPE_STR", DATATYPE_STR, false, false);
+ script->set_constant("DATATYPE_INT", DATATYPE_INT, false, false);
+ script->set_constant("DATATYPE_CONST", DATATYPE_CONST, false, false);
+ script->set_constant("DATATYPE_PARAM", DATATYPE_PARAM, false, false);
+ script->set_constant("DATATYPE_VAR", DATATYPE_VAR, false, false);
+ script->set_constant("DATATYPE_LABEL", DATATYPE_LABEL, false, false);
+
script->constdb_comment("Renewal");
#ifdef RENEWAL
script->set_constant("RENEWAL", 1, false, false);
@@ -24247,6 +24551,9 @@ void script_defaults(void)
script->db_free_code_sub = db_script_free_code_sub;
script->add_autobonus = script_add_autobonus;
script->menu_countoptions = menu_countoptions;
+ script->buildin_recovery_sub = buildin_recovery_sub;
+ script->buildin_recovery_pc_sub = buildin_recovery_pc_sub;
+ script->buildin_recovery_bl_sub = buildin_recovery_bl_sub;
script->buildin_areawarp_sub = buildin_areawarp_sub;
script->buildin_areapercentheal_sub = buildin_areapercentheal_sub;
script->buildin_delitem_delete = buildin_delitem_delete;