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.c1318
1 files changed, 1084 insertions, 234 deletions
diff --git a/src/map/script.c b/src/map/script.c
index 0f3c09e1e..2ffcad83c 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -171,8 +171,16 @@ enum { LABEL_NEXTLINE=1,LABEL_START };
static unsigned char* script_buf = NULL;
static int script_pos = 0, script_size = 0;
-#define GETVALUE(buf,i) ((int)MakeDWord(MakeWord((buf)[i],(buf)[i+1]),MakeWord((buf)[i+2],0)))
-#define SETVALUE(buf,i,n) ((buf)[i]=GetByte(n,0),(buf)[i+1]=GetByte(n,1),(buf)[i+2]=GetByte(n,2))
+static inline int GETVALUE(const unsigned char* buf, int i)
+{
+ return (int)MakeDWord(MakeWord(buf[i], buf[i+1]), MakeWord(buf[i+2], 0));
+}
+static inline void SETVALUE(unsigned char* buf, int i, int n)
+{
+ buf[i] = GetByte(n, 0);
+ buf[i+1] = GetByte(n, 1);
+ buf[i+2] = GetByte(n, 2);
+}
// String buffer structures.
// str_data stores string information
@@ -317,7 +325,10 @@ enum {
MF_FOG,
MF_SAKURA,
MF_LEAVES,
- MF_RAIN, //20
+ /**
+ * No longer available, keeping here just in case it's back someday. [Ind]
+ **/
+ //MF_RAIN, //20
// 21 free
MF_NOGO = 22,
MF_CLOUDS,
@@ -3357,7 +3368,18 @@ static void script_detach_state(struct script_state* st, bool dequeue_event)
{
sd->st = st->bk_st;
sd->npc_id = st->bk_npcid;
-
+ /**
+ * For the Secure NPC Timeout option (check config/Secure.h) [RR]
+ **/
+ #if SECURE_NPCTIMEOUT
+ /**
+ * We're done with this NPC session, so we cancel the timer (if existent) and move on
+ **/
+ if( sd->npc_idle_timer != INVALID_TIMER ) {
+ delete_timer(sd->npc_idle_timer,npc_rr_secure_timeout_timer);
+ sd->npc_idle_timer = INVALID_TIMER;
+ }
+ #endif
if(st->bk_st)
{
//Remove tag for removal.
@@ -3399,6 +3421,14 @@ static void script_attach_state(struct script_state* st)
}
sd->st = st;
sd->npc_id = st->oid;
+/**
+ * For the Secure NPC Timeout option (check config/Secure.h) [RR]
+ **/
+#if SECURE_NPCTIMEOUT
+ if( sd->npc_idle_timer == INVALID_TIMER )
+ sd->npc_idle_timer = add_timer(gettick() + (SECURE_NPCTIMEOUT_INTERVAL*1000),npc_rr_secure_timeout_timer,sd->bl.id,0);
+ sd->npc_idle_tick = gettick();
+#endif
}
}
@@ -7022,8 +7052,7 @@ BUILDIN_FUNC(bonus)
case SP_ADD_SKILL_BLOW:
case SP_CASTRATE:
case SP_ADDEFF_ONSKILL:
- case SP_FIXEDCASTRATE:
- // these bonuses support skill names
+ // these bonuses support skill names
val1 = ( script_isstring(st,3) ? skill_name2id(script_getstr(st,3)) : script_getnum(st,3) );
break;
default:
@@ -7426,7 +7455,7 @@ BUILDIN_FUNC(setoption)
flag = script_getnum(st,3);
else if( !option ){// Request to remove everything.
flag = 0;
- option = OPTION_CART|OPTION_FALCON|OPTION_RIDING|OPTION_DRAGON;
+ option = OPTION_CART|OPTION_FALCON|OPTION_RIDING;
}
if( flag ){// Add option
if( option&OPTION_WEDDING && !battle_config.wedding_modifydisplay )
@@ -7542,7 +7571,7 @@ BUILDIN_FUNC(checkriding)
if( sd == NULL )
return 0;// no player attached, report source
- if( pc_isriding(sd) || pc_isdragon(sd) )
+ if( pc_isriding(sd) || sd->sc.option&OPTION_MOUNTING )
script_pushint(st, 1);
else
script_pushint(st, 0);
@@ -7571,31 +7600,6 @@ BUILDIN_FUNC(setriding)
return 0;
}
-/// Sets if the player is riding a dragon.
-/// <flag> defaults to 1
-/// <color> defaults to 0
-///
-/// setdragon <flag>{,<color>};
-/// setdragon <flag>;
-/// setdragon;
-BUILDIN_FUNC(setdragon)
-{
- int flag = 1, color = 0;
- TBL_PC* sd;
-
- sd = script_rid2sd(st);
- if( sd == NULL )
- return 0;// no player attached, report source
-
- if( script_hasdata(st,2) )
- flag = script_getnum(st,2);
- if( script_hasdata(st,3) )
- color = cap_value(script_getnum(st,3),0,4);
-
- pc_setdragon(sd, flag, color);
- return 0;
-}
-
/// Sets the save point of the player.
///
/// save "<map name>",<x>,<y>
@@ -7787,31 +7791,9 @@ BUILDIN_FUNC(produce)
sd = script_rid2sd(st);
if( sd == NULL )
return 0;
-
- if( script_hasdata(st,3) )
- { // only used with Rune Knights RK_RUNEMASTERY as part of the calculation.
- struct item_data* id = NULL;
- struct script_data* data;
-
- data = script_getdata(st,3);
- get_val(st, data);
-
- if( data_isstring(data) )
- id = itemdb_searchname(conv_str(st, data));
- else
- id = itemdb_exists(conv_num(st, data));
-
- if( id == NULL )
- {
- ShowError("buildin_produce: Invalid item '%s'.\n", script_getstr(st,3));
- return 1;
- }
- else
- sd->produce_itemusedid = id->nameid;
- }
trigger=script_getnum(st,2);
- clif_skill_produce_mix_list(sd, trigger);
+ clif_skill_produce_mix_list(sd, -1, trigger);
return 0;
}
/*==========================================
@@ -9186,7 +9168,7 @@ BUILDIN_FUNC(roclass)
}
/*==========================================
- *Œg‘Ñ—‘›z‰»‹@Žg—p
+ * Tells client to open a hatching window, used for pet incubator
*------------------------------------------*/
BUILDIN_FUNC(birthpet)
{
@@ -9634,6 +9616,7 @@ BUILDIN_FUNC(getmapflag)
switch(i) {
case MF_NOMEMO: script_pushint(st,map[m].flag.nomemo); break;
case MF_NOTELEPORT: script_pushint(st,map[m].flag.noteleport); break;
+ case MF_NOSAVE: script_pushint(st,map[m].flag.nosave); break;
case MF_NOBRANCH: script_pushint(st,map[m].flag.nobranch); break;
case MF_NOPENALTY: script_pushint(st,map[m].flag.noexppenalty); break;
case MF_NOZENYPENALTY: script_pushint(st,map[m].flag.nozenypenalty); break;
@@ -9642,23 +9625,26 @@ BUILDIN_FUNC(getmapflag)
case MF_PVP_NOGUILD: script_pushint(st,map[m].flag.pvp_noguild); break;
case MF_GVG: script_pushint(st,map[m].flag.gvg); break;
case MF_GVG_NOPARTY: script_pushint(st,map[m].flag.gvg_noparty); break;
- case MF_GVG_DUNGEON: script_pushint(st,map[m].flag.gvg_dungeon); break;
- case MF_GVG_CASTLE: script_pushint(st,map[m].flag.gvg_castle); break;
case MF_NOTRADE: script_pushint(st,map[m].flag.notrade); break;
- case MF_NODROP: script_pushint(st,map[m].flag.nodrop); break;
case MF_NOSKILL: script_pushint(st,map[m].flag.noskill); break;
case MF_NOWARP: script_pushint(st,map[m].flag.nowarp); break;
+ case MF_PARTYLOCK: script_pushint(st,map[m].flag.partylock); break;
case MF_NOICEWALL: script_pushint(st,map[m].flag.noicewall); break;
case MF_SNOW: script_pushint(st,map[m].flag.snow); break;
- case MF_CLOUDS: script_pushint(st,map[m].flag.clouds); break;
- case MF_CLOUDS2: script_pushint(st,map[m].flag.clouds2); break;
case MF_FOG: script_pushint(st,map[m].flag.fog); break;
- case MF_FIREWORKS: script_pushint(st,map[m].flag.fireworks); break;
case MF_SAKURA: script_pushint(st,map[m].flag.sakura); break;
case MF_LEAVES: script_pushint(st,map[m].flag.leaves); break;
- case MF_RAIN: script_pushint(st,map[m].flag.rain); break;
- case MF_NIGHTENABLED: script_pushint(st,map[m].flag.nightenabled); break;
+ /**
+ * No longer available, keeping here just in case it's back someday. [Ind]
+ **/
+ //case MF_RAIN: script_pushint(st,map[m].flag.rain); break;
case MF_NOGO: script_pushint(st,map[m].flag.nogo); break;
+ case MF_CLOUDS: script_pushint(st,map[m].flag.clouds); break;
+ case MF_CLOUDS2: script_pushint(st,map[m].flag.clouds2); break;
+ case MF_FIREWORKS: script_pushint(st,map[m].flag.fireworks); break;
+ case MF_GVG_CASTLE: script_pushint(st,map[m].flag.gvg_castle); break;
+ case MF_GVG_DUNGEON: script_pushint(st,map[m].flag.gvg_dungeon); break;
+ case MF_NIGHTENABLED: script_pushint(st,map[m].flag.nightenabled); break;
case MF_NOBASEEXP: script_pushint(st,map[m].flag.nobaseexp); break;
case MF_NOJOBEXP: script_pushint(st,map[m].flag.nojobexp); break;
case MF_NOMOBLOOT: script_pushint(st,map[m].flag.nomobloot); break;
@@ -9668,12 +9654,13 @@ BUILDIN_FUNC(getmapflag)
case MF_NIGHTMAREDROP: script_pushint(st,map[m].flag.pvp_nightmaredrop); break;
case MF_RESTRICTED: script_pushint(st,map[m].flag.restricted); break;
case MF_NOCOMMAND: script_pushint(st,map[m].nocommand); break;
+ case MF_NODROP: script_pushint(st,map[m].flag.nodrop); break;
case MF_JEXP: script_pushint(st,map[m].jexp); break;
case MF_BEXP: script_pushint(st,map[m].bexp); break;
case MF_NOVENDING: script_pushint(st,map[m].flag.novending); break;
case MF_LOADEVENT: script_pushint(st,map[m].flag.loadevent); break;
case MF_NOCHAT: script_pushint(st,map[m].flag.nochat); break;
- case MF_PARTYLOCK: script_pushint(st,map[m].flag.partylock); break;
+ case MF_NOEXPPENALTY: script_pushint(st,map[m].flag.noexppenalty ); break;
case MF_GUILDLOCK: script_pushint(st,map[m].flag.guildlock); break;
case MF_TOWN: script_pushint(st,map[m].flag.town); break;
case MF_AUTOTRADE: script_pushint(st,map[m].flag.autotrade); break;
@@ -9681,7 +9668,7 @@ BUILDIN_FUNC(getmapflag)
case MF_MONSTER_NOTELEPORT: script_pushint(st,map[m].flag.monster_noteleport); break;
case MF_PVP_NOCALCRANK: script_pushint(st,map[m].flag.pvp_nocalcrank); break;
case MF_BATTLEGROUND: script_pushint(st,map[m].flag.battleground); break;
- case MF_RESET: script_pushint(st,map[m].flag.reset); break;
+ case MF_RESET: script_pushint(st,map[m].flag.reset); break;
}
}
@@ -9702,56 +9689,61 @@ BUILDIN_FUNC(setmapflag)
m = map_mapname2mapid(str);
if(m >= 0) {
switch(i) {
- case MF_NOMEMO: map[m].flag.nomemo=1; break;
- case MF_NOTELEPORT: map[m].flag.noteleport=1; break;
- case MF_NOBRANCH: map[m].flag.nobranch=1; break;
- case MF_NOPENALTY: map[m].flag.noexppenalty=1; map[m].flag.nozenypenalty=1; break;
- case MF_NOZENYPENALTY: map[m].flag.nozenypenalty=1; break;
- case MF_PVP: map[m].flag.pvp=1; break;
- case MF_PVP_NOPARTY: map[m].flag.pvp_noparty=1; break;
- case MF_PVP_NOGUILD: map[m].flag.pvp_noguild=1; break;
- case MF_GVG: map[m].flag.gvg=1; break;
- case MF_GVG_NOPARTY: map[m].flag.gvg_noparty=1; break;
- case MF_GVG_DUNGEON: map[m].flag.gvg_dungeon=1; break;
- case MF_GVG_CASTLE: map[m].flag.gvg_castle=1; break;
- case MF_NOTRADE: map[m].flag.notrade=1; break;
- case MF_NODROP: map[m].flag.nodrop=1; break;
- case MF_NOSKILL: map[m].flag.noskill=1; break;
- case MF_NOWARP: map[m].flag.nowarp=1; break;
- case MF_NOICEWALL: map[m].flag.noicewall=1; break;
- case MF_SNOW: map[m].flag.snow=1; break;
- case MF_CLOUDS: map[m].flag.clouds=1; break;
- case MF_CLOUDS2: map[m].flag.clouds2=1; break;
- case MF_FOG: map[m].flag.fog=1; break;
- case MF_FIREWORKS: map[m].flag.fireworks=1; break;
- case MF_SAKURA: map[m].flag.sakura=1; break;
- case MF_LEAVES: map[m].flag.leaves=1; break;
- case MF_RAIN: map[m].flag.rain=1; break;
- case MF_NIGHTENABLED: map[m].flag.nightenabled=1; break;
- case MF_NOGO: map[m].flag.nogo=1; break;
- case MF_NOBASEEXP: map[m].flag.nobaseexp=1; break;
- case MF_NOJOBEXP: map[m].flag.nojobexp=1; break;
- case MF_NOMOBLOOT: map[m].flag.nomobloot=1; break;
- case MF_NOMVPLOOT: map[m].flag.nomvploot=1; break;
- case MF_NORETURN: map[m].flag.noreturn=1; break;
- case MF_NOWARPTO: map[m].flag.nowarpto=1; break;
- case MF_NIGHTMAREDROP: map[m].flag.pvp_nightmaredrop=1; break;
- case MF_RESTRICTED: map[m].flag.restricted=1; break;
+ case MF_NOMEMO: map[m].flag.nomemo = 1; break;
+ case MF_NOTELEPORT: map[m].flag.noteleport = 1; break;
+ case MF_NOSAVE: map[m].flag.nosave = 1; break;
+ case MF_NOBRANCH: map[m].flag.nobranch = 1; break;
+ case MF_NOPENALTY: map[m].flag.noexppenalty = 1; map[m].flag.nozenypenalty = 1; break;
+ case MF_NOZENYPENALTY: map[m].flag.nozenypenalty = 1; break;
+ case MF_PVP: map[m].flag.pvp = 1; break;
+ case MF_PVP_NOPARTY: map[m].flag.pvp_noparty = 1; break;
+ case MF_PVP_NOGUILD: map[m].flag.pvp_noguild = 1; break;
+ case MF_GVG: map[m].flag.gvg = 1; break;
+ case MF_GVG_NOPARTY: map[m].flag.gvg_noparty = 1; break;
+ case MF_NOTRADE: map[m].flag.notrade = 1; break;
+ case MF_NOSKILL: map[m].flag.noskill = 1; break;
+ case MF_NOWARP: map[m].flag.nowarp = 1; break;
+ case MF_PARTYLOCK: map[m].flag.partylock = 1; break;
+ case MF_NOICEWALL: map[m].flag.noicewall = 1; break;
+ case MF_SNOW: map[m].flag.snow = 1; break;
+ case MF_FOG: map[m].flag.fog = 1; break;
+ case MF_SAKURA: map[m].flag.sakura = 1; break;
+ case MF_LEAVES: map[m].flag.leaves = 1; break;
+ /**
+ * No longer available, keeping here just in case it's back someday. [Ind]
+ **/
+ //case MF_RAIN: map[m].flag.rain = 1; break;
+ case MF_NOGO: map[m].flag.nogo = 1; break;
+ case MF_CLOUDS: map[m].flag.clouds = 1; break;
+ case MF_CLOUDS2: map[m].flag.clouds2 = 1; break;
+ case MF_FIREWORKS: map[m].flag.fireworks = 1; break;
+ case MF_GVG_CASTLE: map[m].flag.gvg_castle = 1; break;
+ case MF_GVG_DUNGEON: map[m].flag.gvg_dungeon = 1; break;
+ case MF_NIGHTENABLED: map[m].flag.nightenabled = 1; break;
+ case MF_NOBASEEXP: map[m].flag.nobaseexp = 1; break;
+ case MF_NOJOBEXP: map[m].flag.nojobexp = 1; break;
+ case MF_NOMOBLOOT: map[m].flag.nomobloot = 1; break;
+ case MF_NOMVPLOOT: map[m].flag.nomvploot = 1; break;
+ case MF_NORETURN: map[m].flag.noreturn = 1; break;
+ case MF_NOWARPTO: map[m].flag.nowarpto = 1; break;
+ case MF_NIGHTMAREDROP: map[m].flag.pvp_nightmaredrop = 1; break;
+ case MF_RESTRICTED: map[m].flag.restricted = 1; break;
case MF_NOCOMMAND: map[m].nocommand = (!val || atoi(val) <= 0) ? 100 : atoi(val); break;
+ case MF_NODROP: map[m].flag.nodrop = 1; break;
case MF_JEXP: map[m].jexp = (!val || atoi(val) < 0) ? 100 : atoi(val); break;
case MF_BEXP: map[m].bexp = (!val || atoi(val) < 0) ? 100 : atoi(val); break;
- case MF_NOVENDING: map[m].flag.novending=1; break;
- case MF_LOADEVENT: map[m].flag.loadevent=1; break;
- case MF_NOCHAT: map[m].flag.nochat=1; break;
- case MF_PARTYLOCK: map[m].flag.partylock=1; break;
- case MF_GUILDLOCK: map[m].flag.guildlock=1; break;
- case MF_TOWN: map[m].flag.town=1; break;
- case MF_AUTOTRADE: map[m].flag.autotrade=1; break;
- case MF_ALLOWKS: map[m].flag.allowks=1; break;
- case MF_MONSTER_NOTELEPORT: map[m].flag.monster_noteleport=1; break;
- case MF_PVP_NOCALCRANK: map[m].flag.pvp_nocalcrank=1; break;
- case MF_BATTLEGROUND: map[m].flag.battleground = (!val || atoi(val) < 0 || atoi(val) > 2) ? 1 : atoi(val); break;
- case MF_RESET: map[m].flag.reset=1; break;
+ case MF_NOVENDING: map[m].flag.novending = 1; break;
+ case MF_LOADEVENT: map[m].flag.loadevent = 1; break;
+ case MF_NOCHAT: map[m].flag.nochat = 1; break;
+ case MF_NOEXPPENALTY: map[m].flag.noexppenalty = 1; break;
+ case MF_GUILDLOCK: map[m].flag.guildlock = 1; break;
+ case MF_TOWN: map[m].flag.town = 1; break;
+ case MF_AUTOTRADE: map[m].flag.autotrade = 1; break;
+ case MF_ALLOWKS: map[m].flag.allowks = 1; break;
+ case MF_MONSTER_NOTELEPORT: map[m].flag.monster_noteleport = 1; break;
+ case MF_PVP_NOCALCRANK: map[m].flag.pvp_nocalcrank = 1; break;
+ case MF_BATTLEGROUND: (!val || atoi(val) < 0 || atoi(val) > 2) ? 1 : atoi(val); break;
+ case MF_RESET: map[m].flag.reset = 1; break;
}
}
@@ -9768,57 +9760,61 @@ BUILDIN_FUNC(removemapflag)
m = map_mapname2mapid(str);
if(m >= 0) {
switch(i) {
- case MF_NOMEMO: map[m].flag.nomemo=0; break;
- case MF_NOTELEPORT: map[m].flag.noteleport=0; break;
- case MF_NOSAVE: map[m].flag.nosave=0; break;
- case MF_NOBRANCH: map[m].flag.nobranch=0; break;
- case MF_NOPENALTY: map[m].flag.noexppenalty=0; map[m].flag.nozenypenalty=0; break;
- case MF_PVP: map[m].flag.pvp=0; break;
- case MF_PVP_NOPARTY: map[m].flag.pvp_noparty=0; break;
- case MF_PVP_NOGUILD: map[m].flag.pvp_noguild=0; break;
- case MF_GVG: map[m].flag.gvg=0; break;
- case MF_GVG_NOPARTY: map[m].flag.gvg_noparty=0; break;
- case MF_GVG_DUNGEON: map[m].flag.gvg_dungeon=0; break;
- case MF_GVG_CASTLE: map[m].flag.gvg_castle=0; break;
- case MF_NOZENYPENALTY: map[m].flag.nozenypenalty=0; break;
- case MF_NOTRADE: map[m].flag.notrade=0; break;
- case MF_NODROP: map[m].flag.nodrop=0; break;
- case MF_NOSKILL: map[m].flag.noskill=0; break;
- case MF_NOWARP: map[m].flag.nowarp=0; break;
- case MF_NOICEWALL: map[m].flag.noicewall=0; break;
- case MF_SNOW: map[m].flag.snow=0; break;
- case MF_CLOUDS: map[m].flag.clouds=0; break;
- case MF_CLOUDS2: map[m].flag.clouds2=0; break;
- case MF_FOG: map[m].flag.fog=0; break;
- case MF_FIREWORKS: map[m].flag.fireworks=0; break;
- case MF_SAKURA: map[m].flag.sakura=0; break;
- case MF_LEAVES: map[m].flag.leaves=0; break;
- case MF_RAIN: map[m].flag.rain=0; break;
- case MF_NIGHTENABLED: map[m].flag.nightenabled=0; break;
- case MF_NOGO: map[m].flag.nogo=0; break;
- case MF_NOBASEEXP: map[m].flag.nobaseexp=0; break;
- case MF_NOJOBEXP: map[m].flag.nojobexp=0; break;
- case MF_NOMOBLOOT: map[m].flag.nomobloot=0; break;
- case MF_NOMVPLOOT: map[m].flag.nomvploot=0; break;
- case MF_NORETURN: map[m].flag.noreturn=0; break;
- case MF_NOWARPTO: map[m].flag.nowarpto=0; break;
- case MF_NIGHTMAREDROP: map[m].flag.pvp_nightmaredrop=0; break;
- case MF_RESTRICTED: map[m].flag.restricted=0; break;
- case MF_NOCOMMAND: map[m].nocommand=0; break;
- case MF_JEXP: map[m].jexp=100; break;
- case MF_BEXP: map[m].bexp=100; break;
- case MF_NOVENDING: map[m].flag.novending=0; break;
- case MF_LOADEVENT: map[m].flag.loadevent=0; break;
- case MF_NOCHAT: map[m].flag.nochat=0; break;
- case MF_PARTYLOCK: map[m].flag.partylock=0; break;
- case MF_GUILDLOCK: map[m].flag.guildlock=0; break;
- case MF_TOWN: map[m].flag.town=0; break;
- case MF_AUTOTRADE: map[m].flag.autotrade=0; break;
- case MF_ALLOWKS: map[m].flag.allowks=0; break;
- case MF_MONSTER_NOTELEPORT: map[m].flag.monster_noteleport=0; break;
- case MF_PVP_NOCALCRANK: map[m].flag.pvp_nocalcrank=0; break;
- case MF_BATTLEGROUND: map[m].flag.battleground=0; break;
- case MF_RESET: map[m].flag.reset=0; break;
+ case MF_NOMEMO: map[m].flag.nomemo = 0; break;
+ case MF_NOTELEPORT: map[m].flag.noteleport = 0; break;
+ case MF_NOSAVE: map[m].flag.nosave = 0; break;
+ case MF_NOBRANCH: map[m].flag.nobranch = 0; break;
+ case MF_NOPENALTY: map[m].flag.noexppenalty = 0; map[m].flag.nozenypenalty = 0; break;
+ case MF_NOZENYPENALTY: map[m].flag.nozenypenalty = 0; break;
+ case MF_PVP: map[m].flag.pvp = 0; break;
+ case MF_PVP_NOPARTY: map[m].flag.pvp_noparty = 0; break;
+ case MF_PVP_NOGUILD: map[m].flag.pvp_noguild = 0; break;
+ case MF_GVG: map[m].flag.gvg = 0; break;
+ case MF_GVG_NOPARTY: map[m].flag.gvg_noparty = 0; break;
+ case MF_NOTRADE: map[m].flag.notrade = 0; break;
+ case MF_NOSKILL: map[m].flag.noskill = 0; break;
+ case MF_NOWARP: map[m].flag.nowarp = 0; break;
+ case MF_PARTYLOCK: map[m].flag.partylock = 0; break;
+ case MF_NOICEWALL: map[m].flag.noicewall = 0; break;
+ case MF_SNOW: map[m].flag.snow = 0; break;
+ case MF_FOG: map[m].flag.fog = 0; break;
+ case MF_SAKURA: map[m].flag.sakura = 0; break;
+ case MF_LEAVES: map[m].flag.leaves = 0; break;
+ /**
+ * No longer available, keeping here just in case it's back someday. [Ind]
+ **/
+ //case MF_RAIN: map[m].flag.rain = 0; break;
+ case MF_NOGO: map[m].flag.nogo = 0; break;
+ case MF_CLOUDS: map[m].flag.clouds = 0; break;
+ case MF_CLOUDS2: map[m].flag.clouds2 = 0; break;
+ case MF_FIREWORKS: map[m].flag.fireworks = 0; break;
+ case MF_GVG_CASTLE: map[m].flag.gvg_castle = 0; break;
+ case MF_GVG_DUNGEON: map[m].flag.gvg_dungeon = 0; break;
+ case MF_NIGHTENABLED: map[m].flag.nightenabled = 0; break;
+ case MF_NOBASEEXP: map[m].flag.nobaseexp = 0; break;
+ case MF_NOJOBEXP: map[m].flag.nojobexp = 0; break;
+ case MF_NOMOBLOOT: map[m].flag.nomobloot = 0; break;
+ case MF_NOMVPLOOT: map[m].flag.nomvploot = 0; break;
+ case MF_NORETURN: map[m].flag.noreturn = 0; break;
+ case MF_NOWARPTO: map[m].flag.nowarpto = 0; break;
+ case MF_NIGHTMAREDROP: map[m].flag.pvp_nightmaredrop = 0; break;
+ case MF_RESTRICTED: map[m].flag.restricted = 0; break;
+ case MF_NOCOMMAND: map[m].nocommand = 0; break;
+ case MF_NODROP: map[m].flag.nodrop = 0; break;
+ case MF_JEXP: map[m].jexp = 0; break;
+ case MF_BEXP: map[m].bexp = 0; break;
+ case MF_NOVENDING: map[m].flag.novending = 0; break;
+ case MF_LOADEVENT: map[m].flag.loadevent = 0; break;
+ case MF_NOCHAT: map[m].flag.nochat = 0; break;
+ case MF_NOEXPPENALTY: map[m].flag.noexppenalty = 0; break;
+ case MF_GUILDLOCK: map[m].flag.guildlock = 0; break;
+ case MF_TOWN: map[m].flag.town = 0; break;
+ case MF_AUTOTRADE: map[m].flag.autotrade = 0; break;
+ case MF_ALLOWKS: map[m].flag.allowks = 0; break;
+ case MF_MONSTER_NOTELEPORT: map[m].flag.monster_noteleport = 0; break;
+ case MF_PVP_NOCALCRANK: map[m].flag.pvp_nocalcrank = 0; break;
+ case MF_BATTLEGROUND: map[m].flag.battleground = 0; break;
+ case MF_RESET: map[m].flag.reset = 0; break;
}
}
@@ -12583,6 +12579,792 @@ BUILDIN_FUNC(charisalpha)
return 0;
}
+//=======================================================
+// charisupper <str>, <index>
+//-------------------------------------------------------
+BUILDIN_FUNC(charisupper)
+{
+ const char *str = script_getstr(st,2);
+ int pos = script_getnum(st,3);
+
+ int val = ( str && pos >= 0 && (unsigned int)pos < strlen(str) ) ? ISUPPER( str[pos] ) : 0;
+
+ script_pushint(st,val);
+ return 0;
+}
+
+//=======================================================
+// charislower <str>, <index>
+//-------------------------------------------------------
+BUILDIN_FUNC(charislower)
+{
+ const char *str = script_getstr(st,2);
+ int pos = script_getnum(st,3);
+
+ int val = ( str && pos >= 0 && (unsigned int)pos < strlen(str) ) ? ISLOWER( str[pos] ) : 0;
+
+ script_pushint(st,val);
+ return 0;
+}
+
+//=======================================================
+// charat <str>, <index>
+//-------------------------------------------------------
+BUILDIN_FUNC(charat)
+{
+ const char *str = script_getstr(st,2);
+ int pos = script_getnum(st,3);
+ char *output;
+
+ output = (char*)aMallocA(2*sizeof(char));
+ output[0] = '\0';
+
+ if(str && pos >= 0 && (unsigned int)pos < strlen(str))
+ sprintf(output, "%c", str[pos]);
+
+ script_pushstr(st, output);
+ return 0;
+}
+
+//=======================================================
+// setchar <string>, <char>, <index>
+//-------------------------------------------------------
+BUILDIN_FUNC(setchar)
+{
+ const char *str = script_getstr(st,2);
+ const char *c = script_getstr(st,3);
+ int index = script_getnum(st,4);
+ char *output;
+ size_t len = strlen(str);
+
+ output = (char*)aMallocA(len + 1);
+ memcpy(output, str, len);
+ output[len] = '\0';
+
+ if(index >= 0 && index < len)
+ output[index] = c[0];
+
+ script_pushstr(st, output);
+ return 0;
+}
+
+//=======================================================
+// insertchar <string>, <char>, <index>
+//-------------------------------------------------------
+BUILDIN_FUNC(insertchar)
+{
+ const char *str = script_getstr(st,2);
+ const char *c = script_getstr(st,3);
+ int index = script_getnum(st,4);
+ char *output;
+ size_t len = strlen(str);
+
+ if(index < 0)
+ index = 0;
+ else if(index > len)
+ index = len;
+
+ output = (char*)aMallocA(len + 2);
+
+ memcpy(output, str, index);
+ output[index] = c[0];
+ memcpy(&output[index+1], &str[index], len - index);
+ output[len+1] = '\0';
+
+ script_pushstr(st, output);
+ return 0;
+}
+
+//=======================================================
+// delchar <string>, <index>
+//-------------------------------------------------------
+BUILDIN_FUNC(delchar)
+{
+ const char *str = script_getstr(st,2);
+ int index = script_getnum(st,3);
+ char *output;
+ size_t len = strlen(str);
+
+ if(index < 0 || index > len) {
+ //return original
+ ++len;
+ output = (char*)aMallocA(len);
+ memcpy(output, str, len);
+ script_pushstr(st, output);
+ return 0;
+ }
+
+ output = (char*)aMallocA(len);
+
+ memcpy(output, str, index);
+ memcpy(&output[index], &str[index+1], len - index);
+
+ script_pushstr(st, output);
+ return 0;
+}
+
+//=======================================================
+// strtoupper <str>
+//-------------------------------------------------------
+BUILDIN_FUNC(strtoupper)
+{
+ const char *str = script_getstr(st,2);
+ char *output;
+ int i = 0;
+
+ output = (char*)aMallocA(strlen(str) + 1);
+
+ while(str[i] != '\0')
+ output[i++] = TOUPPER(str[i]);
+ output[i] = '\0';
+
+ script_pushstr(st, output);
+ return 0;
+}
+
+//=======================================================
+// strtolower <str>
+//-------------------------------------------------------
+BUILDIN_FUNC(strtolower)
+{
+ const char *str = script_getstr(st,2);
+ char *output;
+ int i = 0;
+
+ output = (char*)aMallocA(strlen(str) + 1);
+
+ while(str[i] != '\0')
+ output[i++] = TOLOWER(str[i]);
+ output[i] = '\0';
+
+ script_pushstr(st, output);
+ return 0;
+}
+
+//=======================================================
+// substr <str>, <start>, <end>
+//-------------------------------------------------------
+BUILDIN_FUNC(substr)
+{
+ const char *str = script_getstr(st,2);
+ char *output;
+ int start = script_getnum(st,3);
+ int end = script_getnum(st,4);
+
+ int len = 0;
+
+ if(start >= 0 && end < strlen(str) && start <= end) {
+ len = end - start + 1;
+ output = (char*)aMallocA(len + 1);
+ memcpy(output, &str[start], len);
+ } else
+ output = (char*)aMallocA(1);
+
+ output[len] = '\0';
+
+ script_pushstr(st, output);
+ return 0;
+}
+
+//=======================================================
+// explode <dest_string_array>, <str>, <delimiter>
+// Note: delimiter is limited to 1 char
+//-------------------------------------------------------
+BUILDIN_FUNC(explode)
+{
+ struct script_data* data = script_getdata(st, 2);
+ const char *str = script_getstr(st,3);
+ const char delimiter = script_getstr(st, 4)[0];
+ int32 id;
+ size_t len = strlen(str);
+ int i = 0, j = 0;
+ int start;
+
+
+ char *temp;
+ const char* name;
+
+ TBL_PC* sd = NULL;
+
+ temp = (char*)aMallocA(len + 1);
+
+ if( !data_isreference(data) )
+ {
+ ShowError("script:explode: not a variable\n");
+ script_reportdata(data);
+ st->state = END;
+ return 1;// not a variable
+ }
+
+ id = reference_getid(data);
+ start = reference_getindex(data);
+ name = reference_getname(data);
+
+ if( not_array_variable(*name) )
+ {
+ ShowError("script:explode: illegal scope\n");
+ script_reportdata(data);
+ st->state = END;
+ return 1;// not supported
+ }
+
+ if( !is_string_variable(name) )
+ {
+ ShowError("script:explode: not string array\n");
+ script_reportdata(data);
+ st->state = END;
+ return 1;// data type mismatch
+ }
+
+ if( not_server_variable(*name) )
+ {
+ sd = script_rid2sd(st);
+ if( sd == NULL )
+ return 0;// no player attached
+ }
+
+ while(str[i] != '\0') {
+ if(str[i] == delimiter && start < 127) { //break at delimiter but ignore after reaching last array index
+ temp[j] = '\0';
+ set_reg(st, sd, reference_uid(id, start++), name, (void*)temp, reference_getref(data));
+ j = 0;
+ ++i;
+ } else {
+ temp[j++] = str[i++];
+ }
+ }
+ //set last string
+ temp[j] = '\0';
+ set_reg(st, sd, reference_uid(id, start), name, (void*)temp, reference_getref(data));
+
+ aFree(temp);
+ return 0;
+}
+
+//=======================================================
+// implode <string_array>
+// implode <string_array>, <glue>
+//-------------------------------------------------------
+BUILDIN_FUNC(implode)
+{
+ struct script_data* data = script_getdata(st, 2);
+ const char *glue = NULL, *name, *temp;
+ int32 glue_len = 0, array_size, id;
+ size_t len = 0;
+ int i, k = 0;
+
+ TBL_PC* sd = NULL;
+
+ char *output;
+
+ if( !data_isreference(data) )
+ {
+ ShowError("script:implode: not a variable\n");
+ script_reportdata(data);
+ st->state = END;
+ return 1;// not a variable
+ }
+
+ id = reference_getid(data);
+ name = reference_getname(data);
+
+ if( not_array_variable(*name) )
+ {
+ ShowError("script:implode: illegal scope\n");
+ script_reportdata(data);
+ st->state = END;
+ return 1;// not supported
+ }
+
+ if( !is_string_variable(name) )
+ {
+ ShowError("script:implode: not string array\n");
+ script_reportdata(data);
+ st->state = END;
+ return 1;// data type mismatch
+ }
+
+ if( not_server_variable(*name) )
+ {
+ sd = script_rid2sd(st);
+ if( sd == NULL )
+ return 0;// no player attached
+ }
+
+ //count chars
+ array_size = getarraysize(st, id, reference_getindex(data), is_string_variable(name), reference_getref(data)) - 1;
+
+ if(array_size == -1) //empty array check (AmsTaff)
+ {
+ ShowWarning("script:implode: array length = 0\n");
+ output = (char*)aMallocA(sizeof(char)*5);
+ sprintf(output,"%s","NULL");
+ } else {
+ for(i = 0; i <= array_size; ++i) {
+ temp = (char*) get_val2(st, reference_uid(id, i), reference_getref(data));
+ len += strlen(temp);
+ script_removetop(st, -1, 0);
+ }
+
+ //allocate mem
+ if( script_hasdata(st,3) ) {
+ glue = script_getstr(st,3);
+ glue_len = strlen(glue);
+ len += glue_len * (array_size);
+ }
+ output = (char*)aMallocA(len + 1);
+
+ //build output
+ for(i = 0; i < array_size; ++i) {
+ temp = (char*) get_val2(st, reference_uid(id, i), reference_getref(data));
+ len = strlen(temp);
+ memcpy(&output[k], temp, len);
+ k += len;
+ if(glue_len != 0) {
+ memcpy(&output[k], glue, glue_len);
+ k += glue_len;
+ }
+ script_removetop(st, -1, 0);
+ }
+ temp = (char*) get_val2(st, reference_uid(id, array_size), reference_getref(data));
+ len = strlen(temp);
+ memcpy(&output[k], temp, len);
+ k += len;
+ script_removetop(st, -1, 0);
+
+ output[k] = '\0';
+ }
+
+ script_pushstr(st, output);
+ return 0;
+}
+
+//=======================================================
+// sprintf(<format>, ...);
+// Implements C sprintf, except format %n. The resulting string is
+// returned, instead of being saved in variable by reference.
+//-------------------------------------------------------
+BUILDIN_FUNC(sprintf)
+{
+ unsigned int len, argc = 0, arg = 0, buf2_len = 0;
+ const char* format;
+ char* p;
+ char* q;
+ char* buf = NULL;
+ char* buf2 = NULL;
+ struct script_data* data;
+ StringBuf final_buf;
+
+ // Fetch init data
+ format = script_getstr(st, 2);
+ argc = script_lastdata(st)-2;
+ len = strlen(format);
+
+ // Skip parsing, where no parsing is required.
+ if(len==0){
+ script_pushconststr(st,"");
+ return 0;
+ }
+
+ // Pessimistic alloc
+ CREATE(buf, char, len+1);
+
+ // Need not be parsed, just solve stuff like %%.
+ if(argc==0){
+ sprintf(buf, format);
+ script_pushstrcopy(st, buf);
+ aFree(buf);
+ return 0;
+ }
+
+ safestrncpy(buf, format, len+1);
+
+ // Issue sprintf for each parameter
+ StringBuf_Init(&final_buf);
+ q = buf;
+ while((p = strchr(q, '%'))!=NULL){
+ if(p!=q){
+ len = p-q+1;
+ if(buf2_len<len){
+ RECREATE(buf2, char, len);
+ buf2_len = len;
+ }
+ safestrncpy(buf2, q, len);
+ StringBuf_AppendStr(&final_buf, buf2);
+ q = p;
+ }
+ p = q+1;
+ if(*p=='%'){ // %%
+ StringBuf_AppendStr(&final_buf, "%");
+ q+=2;
+ continue;
+ }
+ if(*p=='n'){ // %n
+ ShowWarning("buildin_sprintf: Format %%n not supported! Skipping...\n");
+ script_reportsrc(st);
+ q+=2;
+ continue;
+ }
+ if(arg>=argc){
+ ShowError("buildin_sprintf: Not enough arguments passed!\n");
+ if(buf) aFree(buf);
+ if(buf2) aFree(buf2);
+ StringBuf_Destroy(&final_buf);
+ script_pushconststr(st,"");
+ return 1;
+ }
+ if((p = strchr(q+1, '%'))==NULL){
+ p = strchr(q, 0); // EOS
+ }
+ len = p-q+1;
+ if(buf2_len<len){
+ RECREATE(buf2, char, len);
+ buf2_len = len;
+ }
+ safestrncpy(buf2, q, len);
+ q = p;
+
+ // Note: This assumes the passed value being the correct
+ // type to the current format specifier. If not, the server
+ // probably crashes or returns anything else, than expected,
+ // but it would behave in normal code the same way so it's
+ // the scripter's responsibility.
+ data = script_getdata(st, arg+3);
+ if(data_isstring(data)){ // String
+ StringBuf_Printf(&final_buf, buf2, script_getstr(st, arg+3));
+ }else if(data_isint(data)){ // Number
+ StringBuf_Printf(&final_buf, buf2, script_getnum(st, arg+3));
+ }else if(data_isreference(data)){ // Variable
+ char* name = reference_getname(data);
+ if(name[strlen(name)-1]=='$'){ // var Str
+ StringBuf_Printf(&final_buf, buf2, script_getstr(st, arg+3));
+ }else{ // var Int
+ StringBuf_Printf(&final_buf, buf2, script_getnum(st, arg+3));
+ }
+ }else{ // Unsupported type
+ ShowError("buildin_sprintf: Unknown argument type!\n");
+ if(buf) aFree(buf);
+ if(buf2) aFree(buf2);
+ StringBuf_Destroy(&final_buf);
+ script_pushconststr(st,"");
+ return 1;
+ }
+ arg++;
+ }
+
+ // Append anything left
+ if(*q){
+ StringBuf_AppendStr(&final_buf, q);
+ }
+
+ // Passed more, than needed
+ if(arg<argc){
+ ShowWarning("buildin_sprintf: Unused arguments passed.\n");
+ script_reportsrc(st);
+ }
+
+ script_pushstrcopy(st, StringBuf_Value(&final_buf));
+
+ if(buf) aFree(buf);
+ if(buf2) aFree(buf2);
+ StringBuf_Destroy(&final_buf);
+
+ return 0;
+}
+
+//=======================================================
+// sscanf(<str>, <format>, ...);
+// Implements C sscanf.
+//-------------------------------------------------------
+BUILDIN_FUNC(sscanf){
+ unsigned int argc, arg = 0, len;
+ struct script_data* data;
+ struct map_session_data* sd = NULL;
+ const char* str;
+ const char* format;
+ const char* p;
+ const char* q;
+ char* buf = NULL;
+ char* buf_p;
+ char* ref_str = NULL;
+ int ref_int;
+
+ // Get data
+ str = script_getstr(st, 2);
+ format = script_getstr(st, 3);
+ argc = script_lastdata(st)-3;
+
+ len = strlen(format);
+ CREATE(buf, char, len*2+1);
+
+ // Issue sscanf for each parameter
+ *buf = 0;
+ q = format;
+ while((p = strchr(q, '%'))){
+ if(p!=q){
+ strncat(buf, q, (size_t)(p-q));
+ q = p;
+ }
+ p = q+1;
+ if(*p=='*' || *p=='%'){ // Skip
+ strncat(buf, q, 2);
+ q+=2;
+ continue;
+ }
+ if(arg>=argc){
+ ShowError("buildin_sscanf: Not enough arguments passed!\n");
+ script_pushint(st, -1);
+ if(buf) aFree(buf);
+ if(ref_str) aFree(ref_str);
+ return 1;
+ }
+ if((p = strchr(q+1, '%'))==NULL){
+ p = strchr(q, 0); // EOS
+ }
+ len = p-q;
+ strncat(buf, q, len);
+ q = p;
+
+ // Validate output
+ data = script_getdata(st, arg+4);
+ if(!data_isreference(data) || !reference_tovariable(data)){
+ ShowError("buildin_sscanf: Target argument is not a variable!\n");
+ script_pushint(st, -1);
+ if(buf) aFree(buf);
+ if(ref_str) aFree(ref_str);
+ return 1;
+ }
+ buf_p = reference_getname(data);
+ if(not_server_variable(*buf_p) && (sd = script_rid2sd(st))==NULL){
+ script_pushint(st, -1);
+ if(buf) aFree(buf);
+ if(ref_str) aFree(ref_str);
+ return 0;
+ }
+
+ // Save value if any
+ if(buf_p[strlen(buf_p)-1]=='$'){ // String
+ if(ref_str==NULL){
+ CREATE(ref_str, char, strlen(str)+1);
+ }
+ if(sscanf(str, buf, ref_str)==0){
+ break;
+ }
+ set_reg(st, sd, add_str(buf_p), buf_p, (void *)(ref_str), reference_getref(data));
+ }else{ // Number
+ if(sscanf(str, buf, &ref_int)==0){
+ break;
+ }
+ set_reg(st, sd, add_str(buf_p), buf_p, (void *)(ref_int), reference_getref(data));
+ }
+ arg++;
+
+ // Disable used format (%... -> %*...)
+ buf_p = strchr(buf, 0);
+ memmove(buf_p-len+2, buf_p-len+1, len);
+ *(buf_p-len+1) = '*';
+ }
+
+ // Passed more, than needed
+ if(arg<argc){
+ ShowWarning("buildin_sscanf: Unused arguments passed.\n");
+ script_reportsrc(st);
+ }
+
+ script_pushint(st, arg);
+ if(buf) aFree(buf);
+ if(ref_str) aFree(ref_str);
+
+ return 0;
+}
+
+//=======================================================
+// strpos(<haystack>, <needle>)
+// strpos(<haystack>, <needle>, <offset>)
+//
+// Implements PHP style strpos. Adapted from code from
+// http://www.daniweb.com/code/snippet313.html, Dave Sinkula
+//-------------------------------------------------------
+BUILDIN_FUNC(strpos) {
+ const char *haystack = script_getstr(st,2);
+ const char *needle = script_getstr(st,3);
+ int i;
+ size_t len;
+
+ if( script_hasdata(st,4) )
+ i = script_getnum(st,4);
+ else
+ i = 0;
+
+ if ( strlen(needle) == 0 ) {
+ script_pushint(st, -1);
+ return 0;
+ }
+
+ len = strlen(haystack);
+ for ( ; i < len; ++i ) {
+ if ( haystack[i] == *needle ) {
+ // matched starting char -- loop through remaining chars
+ const char *h, *n;
+ for ( h = &haystack[i], n = needle; *h && *n; ++h, ++n ) {
+ if ( *h != *n ) {
+ break;
+ }
+ }
+ if ( !*n ) { // matched all of 'needle' to null termination
+ script_pushint(st, i);
+ return 0;
+ }
+ }
+ }
+ script_pushint(st, -1);
+ return 0;
+}
+
+//===============================================================
+// replacestr <input>, <search>, <replace>{, <usecase>{, <count>}}
+//
+// Note: Finds all instances of <search> in <input> and replaces
+// with <replace>. If specified will only replace as many
+// instances as specified in <count>. By default will be case
+// sensitive.
+//---------------------------------------------------------------
+BUILDIN_FUNC(replacestr)
+{
+ const char *input = script_getstr(st, 2);
+ const char *find = script_getstr(st, 3);
+ const char *replace = script_getstr(st, 4);
+ size_t inputlen = strlen(input);
+ size_t findlen = strlen(find);
+ struct StringBuf output;
+ bool usecase = true;
+
+ int count = 0;
+ int numFinds = 0;
+ int i = 0, f = 0;
+
+ if(findlen == 0) {
+ ShowError("script:replacestr: Invalid search length.\n");
+ st->state = END;
+ return 1;
+ }
+
+ if(script_hasdata(st, 5)) {
+ if(script_isint(st,5))
+ usecase = script_getnum(st, 5) != 0;
+ else {
+ ShowError("script:replacestr: Invalid usecase value. Expected int got string\n");
+ st->state = END;
+ return 1;
+ }
+ }
+
+ if(script_hasdata(st, 6)) {
+ if(script_isint(st,6))
+ count = script_getnum(st, 6);
+ else {
+ ShowError("script:replacestr: Invalid count value. Expected int got string\n");
+ st->state = END;
+ return 1;
+ }
+ }
+
+ StringBuf_Init(&output);
+
+ for(; i < inputlen; i++) {
+ if(count && count == numFinds) { //found enough, stop looking
+ break;
+ }
+
+ for(f = 0; f <= findlen; f++) {
+ if(f == findlen) { //complete match
+ numFinds++;
+ StringBuf_AppendStr(&output, replace);
+
+ i += findlen - 1;
+ break;
+ } else {
+ if(usecase) {
+ if((i + f) > inputlen || input[i + f] != find[f]) {
+ StringBuf_Printf(&output, "%c", input[i]);
+ break;
+ }
+ } else {
+ if(((i + f) > inputlen || input[i + f] != find[f]) && TOUPPER(input[i+f]) != TOUPPER(find[f])) {
+ StringBuf_Printf(&output, "%c", input[i]);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ //append excess after enough found
+ if(i < inputlen)
+ StringBuf_AppendStr(&output, &(input[i]));
+
+ script_pushstrcopy(st, StringBuf_Value(&output));
+ StringBuf_Destroy(&output);
+ return 0;
+}
+
+//========================================================
+// countstr <input>, <search>{, <usecase>}
+//
+// Note: Counts the number of times <search> occurs in
+// <input>. By default will be case sensitive.
+//--------------------------------------------------------
+BUILDIN_FUNC(countstr)
+{
+ const char *input = script_getstr(st, 2);
+ const char *find = script_getstr(st, 3);
+ size_t inputlen = strlen(input);
+ size_t findlen = strlen(find);
+ bool usecase = true;
+
+ int numFinds = 0;
+ int i = 0, f = 0;
+
+ if(findlen == 0) {
+ ShowError("script:countstr: Invalid search length.\n");
+ st->state = END;
+ return 1;
+ }
+
+ if(script_hasdata(st, 4)) {
+ if(script_isint(st,4))
+ usecase = script_getnum(st, 4) != 0;
+ else {
+ ShowError("script:countstr: Invalid usecase value. Expected int got string\n");
+ st->state = END;
+ return 1;
+ }
+ }
+
+ for(; i < inputlen; i++) {
+ for(f = 0; f <= findlen; f++) {
+ if(f == findlen) { //complete match
+ numFinds++;
+ i += findlen - 1;
+ break;
+ } else {
+ if(usecase) {
+ if((i + f) > inputlen || input[i + f] != find[f]) {
+ break;
+ }
+ } else {
+ if(((i + f) > inputlen || input[i + f] != find[f]) && TOUPPER(input[i+f]) != TOUPPER(find[f])) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ script_pushint(st, numFinds);
+ return 0;
+}
+
+
/// Changes the display name and/or display class of the npc.
/// Returns 0 is successful, 1 if the npc does not exist.
///
@@ -13122,7 +13904,7 @@ BUILDIN_FUNC(setitemscript)
n=script_getnum(st,4);
i_data = itemdb_exists(item_id);
- if (!i_data || script==NULL || script[0]!='{') {
+ if (!i_data || script==NULL || ( script[0] && script[0]!='{' )) {
script_pushint(st,0);
return 0;
}
@@ -13140,7 +13922,7 @@ BUILDIN_FUNC(setitemscript)
if(*dstscript)
script_free_code(*dstscript);
- *dstscript = parse_script(script, "script_setitemscript", 0, 0);
+ *dstscript = script[0] ? parse_script(script, "script_setitemscript", 0, 0) : NULL;
script_pushint(st,1);
return 0;
}
@@ -14991,87 +15773,133 @@ BUILDIN_FUNC(searchstores)
searchstore_open(sd, uses, effect);
return 0;
}
-
-/// Returns the successful use of a Rune Knight Runestone.
-///
-/// SuccessRuneUse()
-///
-BUILDIN_FUNC(successruneuse)
+/// Displays a number as large digital clock.
+/// showdigit <value>[,<type>];
+BUILDIN_FUNC(showdigit)
{
- struct item_data* id = NULL;
+ unsigned int type = 0;
+ int value;
struct map_session_data* sd;
- struct script_data* data;
if( ( sd = script_rid2sd(st) ) == NULL )
- return 0; // no player attached, report source
-
- data = script_getdata(st,2);
- get_val(st, data); // convert into value in case of a variable
-
- if( data_isstring(data) )
- id = itemdb_searchname(conv_str(st, data));
- else
- id = itemdb_exists(conv_num(st, data));
-
- if( id == NULL )
{
- ShowError("buildin_successruneuse: Invalid item '%s'.\n", script_getstr(st,2));
- script_pushint(st,0);
- return 1;
+ return 0;
}
- if( (sd->class_&~(JOBL_UPPER|JOBL_BABY)) == MAPID_RUNE_KNIGHT )
+ value = script_getnum(st,2);
+
+ if( script_hasdata(st,3) )
{
- int skilllv = pc_checkskill(sd,RK_RUNEMASTERY);
- int i = (sd->status.dex + sd->status.luk ) / 20 + (skilllv?55+skilllv:0) + 30;
+ type = script_getnum(st,3);
- if (rand() % 100 < i)
- script_pushint(st, 1);
- else
+ if( type > 3 )
{
- script_pushint(st, 0);
+ ShowError("buildin_showdigit: Invalid type %u.\n", type);
+ return 1;
+ }
+ }
- i = rand() % 100; // reroll for fail effects
- if( i < 3 )
- {
- long damage = (1000 * id->weight) - (sd->battle_status.mdef + sd->battle_status.mdef2);
- clif_damage(&sd->bl, &sd->bl, gettick(), 0, 0, damage, 0, 0, 0);
- status_damage(&sd->bl, &sd->bl, damage, 0, 0, 0);
- }
- else if( i < 13 )
- { // Random status effect
- struct {
- sc_type type;
- int duration;
- } effects[] = {
- { SC_FREEZE, 30000 },
- { SC_STUN, 5000 },
- { SC_SLEEP, 20000 },
- { SC_SILENCE, 20000 },
- { SC_BLIND, 20000 },
- };
- i = rand()%ARRAYLENGTH(effects); // redesignate i to random status effect+duration.
- sc_start(&sd->bl, effects[i].type, 100, 1, effects[i].duration);
- }
- else if( i < 15 )
- pc_randomwarp(sd, CLR_TELEPORT);
- else if( i < 18 )
- ; // Unknown effect, however weight of the item used is taken into account.
- else if( i < 19 )
- {
- if (!status_isimmune(&sd->bl))
- status_percent_heal(&sd->bl, 100, 100);
+ clif_showdigit(sd, (unsigned char)type, value);
+ return 0;
+}
+/**
+ * Rune Knight
+ **/
+BUILDIN_FUNC(makerune) {
+ TBL_PC* sd;
+ if( (sd = script_rid2sd(st)) == NULL )
+ return 0;
+ clif_skill_produce_mix_list(sd,RK_RUNEMASTERY,24);
+ sd->itemid = script_getnum(st,2);
+ return 0;
+}
+/**
+ * checkdragon() returns 1 if mounting a dragon or 0 otherwise.
+ **/
+BUILDIN_FUNC(checkdragon) {
+ TBL_PC* sd;
+ if( (sd = script_rid2sd(st)) == NULL )
+ return 0;
+ if( sd->sc.option&OPTION_DRAGON )
+ script_pushint(st,1);
+ else
+ script_pushint(st,0);
+ return 0;
+}
+/**
+ * setdragon({optional Color}) returns 1 on success or 0 otherwise
+ * - Toggles the dragon on a RK if he can mount;
+ * @param Color - when not provided uses the green dragon;
+ * - 1 : Green Dragon
+ * - 2 : Brown Dragon
+ * - 3 : Gray Dragon
+ * - 4 : Blue Dragon
+ * - 5 : Red Dragon
+ **/
+BUILDIN_FUNC(setdragon) {
+ TBL_PC* sd;
+ int color = script_hasdata(st,2) ? script_getnum(st,2) : 0;
+ unsigned int option = OPTION_DRAGON1;
+ if( (sd = script_rid2sd(st)) == NULL )
+ return 0;
+ if( !pc_checkskill(sd,RK_DRAGONTRAINING) || (sd->class_&MAPID_THIRDMASK) != MAPID_RUNE_KNIGHT )
+ script_pushint(st,0);//Doesn't have the skill or it's not a Rune Knight
+ else if ( sd->sc.option&OPTION_DRAGON ) {//Is mounted; release
+ pc_setoption(sd, sd->sc.option&~OPTION_DRAGON);
+ script_pushint(st,1);
+ } else {//Not mounted; Mount now.
+ if( color ) {
+ option = ( color == 1 ? OPTION_DRAGON1 :
+ color == 2 ? OPTION_DRAGON2 :
+ color == 3 ? OPTION_DRAGON3 :
+ color == 4 ? OPTION_DRAGON4 :
+ color == 5 ? OPTION_DRAGON5 : 0);
+ if( !option ) {
+ ShowWarning("script_setdragon: Unknown Color %d used; changing to green (1)\n",color);
+ option = OPTION_DRAGON1;
}
- else if( i >= 20 )
- ; // Unknown effect
}
+ pc_setoption(sd, sd->sc.option|option);
+ script_pushint(st,1);
}
- else
- script_pushint(st, 0);
+ return 0;
+}
+/**
+ * ismounting() returns 1 if mounting a new mount or 0 otherwise
+ **/
+BUILDIN_FUNC(ismounting) {
+ TBL_PC* sd;
+ if( (sd = script_rid2sd(st)) == NULL )
+ return 0;
+ if( sd->sc.option&OPTION_MOUNTING )
+ script_pushint(st,1);
+ else
+ script_pushint(st,0);
return 0;
}
+/**
+ * setmounting() returns 1 on success or 0 otherwise
+ * - Toggles new mounts on a player when he can mount
+ * - Will fail if the player is mounting a non-new mount, e.g. dragon, peco, wug, etc.
+ * - Will unmount the player is he is already mounting
+ **/
+BUILDIN_FUNC(setmounting) {
+ TBL_PC* sd;
+ if( (sd = script_rid2sd(st)) == NULL )
+ return 0;
+ if( sd->sc.option&(OPTION_WUGRIDER|OPTION_RIDING|OPTION_DRAGON|OPTION_MADOGEAR) )
+ script_pushint(st,0);//can't mount with one of these
+ else {
+ if( sd->sc.option&OPTION_MOUNTING )
+ pc_setoption(sd, sd->sc.option&~OPTION_MOUNTING);//release mount
+ else
+ pc_setoption(sd, sd->sc.option|OPTION_MOUNTING);//mount
+ script_pushint(st,1);//in both cases, return 1.
+ }
+ return 0;
+}
// declarations that were supposed to be exported from npc_chat.c
#ifdef PCRE_SUPPORT
BUILDIN_FUNC(defpattern);
@@ -15180,7 +16008,6 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(setfalcon,"?"),
BUILDIN_DEF(checkfalcon,""),
BUILDIN_DEF(setriding,"?"),
- BUILDIN_DEF(setdragon,"??"),
BUILDIN_DEF(checkriding,""),
BUILDIN_DEF2(savepoint,"save","sii"),
BUILDIN_DEF(savepoint,"sii"),
@@ -15190,7 +16017,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(openstorage,""),
BUILDIN_DEF(guildopenstorage,""),
BUILDIN_DEF(itemskill,"vi"),
- BUILDIN_DEF(produce,"i?"),
+ BUILDIN_DEF(produce,"i"),
BUILDIN_DEF(cooking,"i"),
BUILDIN_DEF(monster,"siisii?"),
BUILDIN_DEF(getmobdrops,"i"),
@@ -15354,6 +16181,22 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(unequip,"i"), // unequip command [Spectre]
BUILDIN_DEF(getstrlen,"s"), //strlen [Valaris]
BUILDIN_DEF(charisalpha,"si"), //isalpha [Valaris]
+ BUILDIN_DEF(charat,"si"),
+ BUILDIN_DEF(setchar,"ssi"),
+ BUILDIN_DEF(insertchar,"ssi"),
+ BUILDIN_DEF(delchar,"si"),
+ BUILDIN_DEF(strtoupper,"s"),
+ BUILDIN_DEF(strtolower,"s"),
+ BUILDIN_DEF(charisupper, "si"),
+ BUILDIN_DEF(charislower, "si"),
+ BUILDIN_DEF(substr,"sii"),
+ BUILDIN_DEF(explode, "rss"),
+ BUILDIN_DEF(implode, "r?"),
+ BUILDIN_DEF(sprintf,"s*"), // [Mirei]
+ BUILDIN_DEF(sscanf,"ss*"), // [Mirei]
+ BUILDIN_DEF(strpos,"ss?"),
+ BUILDIN_DEF(replacestr,"sss??"),
+ BUILDIN_DEF(countstr,"ss?"),
BUILDIN_DEF(setnpcdisplay,"sv??"),
BUILDIN_DEF(compare,"ss"), // Lordalfa - To bring strstr to scripting Engine.
BUILDIN_DEF(getiteminfo,"ii"), //[Lupus] returns Items Buy / sell Price, etc info
@@ -15437,7 +16280,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(pushpc,"ii"),
BUILDIN_DEF(buyingstore,"i"),
BUILDIN_DEF(searchstores,"ii"),
- BUILDIN_DEF(successruneuse,"?"),
+ BUILDIN_DEF(showdigit,"i?"),
// WoE SE
BUILDIN_DEF(agitstart2,""),
BUILDIN_DEF(agitend2,""),
@@ -15469,7 +16312,14 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(instance_npcname,"s?"),
BUILDIN_DEF(has_instance,"s?"),
BUILDIN_DEF(instance_warpall,"sii?"),
-
+ /**
+ * 3rd-related
+ **/
+ BUILDIN_DEF(makerune,"i"),
+ BUILDIN_DEF(checkdragon,""),//[Ind]
+ BUILDIN_DEF(setdragon,"?"),//[Ind]
+ BUILDIN_DEF(ismounting,""),//[Ind]
+ BUILDIN_DEF(setmounting,""),//[Ind]
//Quest Log System [Inkfish]
BUILDIN_DEF(setquest, "i"),
BUILDIN_DEF(erasequest, "i"),