diff options
Diffstat (limited to 'src/map/script.c')
-rw-r--r-- | src/map/script.c | 1318 |
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"), |