summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt5
-rw-r--r--doc/script_commands.txt9
-rw-r--r--src/map/script.c251
-rw-r--r--src/map/status.c4
4 files changed, 162 insertions, 107 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index fbcb96633..e5a1c8a46 100644
--- a/Changelog-Trunk.txt
+++ b/Changelog-Trunk.txt
@@ -3,6 +3,11 @@ Date Added
AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
+2007/06/15
+ * Fixed script command sc_end not supporting the extra argument as stated
+ in script_commands.txt.
+ * Script command getarg supports an extra argument with a default value
+ that is returned if the requested argument doesn't exist. [FlavioJS]
2007/06/11
* Fixed NPC_PROVOCATION (now the casting mob doesn't keep attacking)
* accumulated clif.c fixes [ultramage]
diff --git a/doc/script_commands.txt b/doc/script_commands.txt
index 15fad965a..9c9b75fb0 100644
--- a/doc/script_commands.txt
+++ b/doc/script_commands.txt
@@ -1402,7 +1402,7 @@ script.
---------------------------------------
-*getarg(<number>)
+*getarg(<index>{,<default_value>})
This function is used when you use the 'callsub' or 'callfunc' commands. In the
call you can specify variables that will make that call different from another
@@ -1446,6 +1446,13 @@ You can pass multiple arguments in a function call:
getarg(0) would be 5, getarg(1) would be 4 and getarg(2) would be 3.
+Getarg has an optional argument since trunk r10773.
+If the target argument exists, it is returned.
+Otherwise, if <default_value> is present it is returned instead,
+if not the script terminates immediately.
+
+in the previous example getarg(2,-1) would be 3 and getarg(3,-1) would be -1
+
---------------------------------------
*return {<value>};
diff --git a/src/map/script.c b/src/map/script.c
index 2248b3019..e44e426ca 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -51,6 +51,16 @@
#include <time.h>
#include <setjmp.h>
+///////////////////////////////////////////////////////////////////////////////
+//## TODO possible enhancements:
+// - 'callfunc' supporting labels in the current npc "::LabelName"
+// - 'callfunc' supporting labels in other npcs "NpcName::LabelName"
+// - 'function FuncName;' function declarations reverting to global functions
+// if local label isn't found
+// - join callfunc and callsub's functionality
+
+
+
//
// struct script_state* st;
//
@@ -3910,7 +3920,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(callsub,"i*"),
BUILDIN_DEF(callfunc,"s*"),
BUILDIN_DEF(return,"?"),
- BUILDIN_DEF(getarg,"i"),
+ BUILDIN_DEF(getarg,"i?"),
BUILDIN_DEF(jobchange,"i*"),
BUILDIN_DEF(jobname,"i"),
BUILDIN_DEF(input,"v"),
@@ -4031,10 +4041,10 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(disablearena,""), // Added by RoVeRT
BUILDIN_DEF(hideoffnpc,"s"),
BUILDIN_DEF(hideonnpc,"s"),
- BUILDIN_DEF(sc_start,"iii*"),
- BUILDIN_DEF(sc_start2,"iiii*"),
- BUILDIN_DEF(sc_start4,"iiiiii*"),
- BUILDIN_DEF(sc_end,"i"),
+ BUILDIN_DEF(sc_start,"iii?"),
+ BUILDIN_DEF(sc_start2,"iiii?"),
+ BUILDIN_DEF(sc_start4,"iiiiii?"),
+ BUILDIN_DEF(sc_end,"i?"),
BUILDIN_DEF(getscrate,"ii*"),
BUILDIN_DEF(debugmes,"s"),
BUILDIN_DEF2(catchpet,"pet","i"),
@@ -4685,26 +4695,38 @@ BUILDIN_FUNC(callsub)
return 0;
}
-/*==========================================
- * 引数の所得
- *------------------------------------------*/
+/// Retrieves an argument provided to callfunc/callsub.
+/// If the argument doesn't exist
+///
+/// getarg(<index>{,<default_value>}) -> <value>
BUILDIN_FUNC(getarg)
{
- int num=script_getnum(st,2);
- int max,stsp;
- if( st->stack->defsp<5 || st->stack->stack_data[st->stack->defsp-1].type!=C_RETINFO ){
- ShowWarning("script:getarg without callfunc or callsub!\n");
- st->state=END;
+ int idx;
+ int count;
+ int stsp;
+
+ if( st->stack->defsp < 5 || st->stack->stack_data[st->stack->defsp - 1].type != C_RETINFO )
+ {
+ ShowWarning("script:getarg: no callfunc or callsub!\n");
+ st->state = END;
return 1;
}
- max=conv_num(st,& (st->stack->stack_data[st->stack->defsp-5]));
- stsp=st->stack->defsp - max -5;
- if( num >= max ){
- ShowWarning("script:getarg arg1(%d) out of range(%d) !\n",num,max);
- st->state=END;
+ count = conv_num(st, &(st->stack->stack_data[st->stack->defsp - 5]));
+ stsp = st->stack->defsp - count - 5;
+
+ idx = script_getnum(st,2);
+
+ if( idx < count )
+ push_copy(st->stack, stsp + idx);
+ else if( script_hasdata(st,3) )
+ script_pushcopy(st, 3);
+ else
+ {
+ ShowWarning("script:getarg: index (idx=%d) out of range (count=%d) and no default value found\n", idx, count);
+ st->state = END;
return 1;
}
- push_copy(st->stack,stsp+num);
+
return 0;
}
@@ -8175,133 +8197,153 @@ BUILDIN_FUNC(hideonnpc)
npc_enable(str,4);
return 0;
}
-/*==========================================
- * 状態異常にかかる
- *------------------------------------------*/
+
+/// Starts a status effect on the target unit or on the attached player.
+///
+/// sc_start <effect_id>,<duration>,<val1>{,<unit_id>};
BUILDIN_FUNC(sc_start)
{
- struct block_list *bl;
- int type,tick,val1,val4=0;
- type=script_getnum(st,2);
- tick=script_getnum(st,3);
- val1=script_getnum(st,4);
- if( script_hasdata(st,5) ) //指定したキャラを状態異常にする
+ struct block_list* bl;
+ int type;
+ int tick;
+ int val1;
+ int val4 = 0;
+
+ type = script_getnum(st,2);
+ tick = script_getnum(st,3);
+ val1 = script_getnum(st,4);
+ if( script_hasdata(st,5) )
bl = map_id2bl(script_getnum(st,5));
else
bl = map_id2bl(st->rid);
- if (potion_flag==1 && potion_target) {
- bl = map_id2bl(potion_target);
- tick/=2; //Thrown potions only last half.
- val4 = 1; //Mark that this was a thrown sc_effect
+ if( tick == 0 && val1 > 0 && type >= 0 && type < SC_MAX && StatusSkillChangeTable[type] != 0 )
+ {// When there isn't a duration specified, try to get it from the skill_db
+ tick = skill_get_time(StatusSkillChangeTable[type], val1);
}
- if (type >= 0 && type < SC_MAX && val1 && !tick)
- { //When there isn't a duration specified, try to get it from the skill_db
- tick = StatusSkillChangeTable[type];
- if (tick)
- tick = skill_get_time(tick,val1);
- else //Failed to retrieve duration, reset to what it was.
- tick = 0;
+
+ if( potion_flag == 1 && potion_target )
+ {//##TODO how does this work [FlavioJS]
+ bl = map_id2bl(potion_target);
+ tick /= 2;// Thrown potions only last half.
+ val4 = 1;// Mark that this was a thrown sc_effect
}
- if (bl)
- status_change_start(bl,type,10000,val1,0,0,val4,tick,11);
+
+ if( bl )
+ status_change_start(bl, type, 10000, val1, 0, 0, val4, tick, 1|2|8);
return 0;
}
-/*==========================================
- * 状態異常にかかる(確率指定)
- *------------------------------------------*/
+/// Starts a status effect on the target unit or on the attached player.
+///
+/// sc_start2 <effect_id>,<duration>,<val1>,<percent chance>{,<unit_id>};
BUILDIN_FUNC(sc_start2)
{
- struct block_list *bl;
- int type,tick,val1,val4=0,per;
- type=script_getnum(st,2);
- tick=script_getnum(st,3);
- val1=script_getnum(st,4);
- per=script_getnum(st,5);
- if( script_hasdata(st,6) ) //指定したキャラを状態異常にする
+ struct block_list* bl;
+ int type;
+ int tick;
+ int val1;
+ int val4 = 0;
+ int rate;
+
+ type = script_getnum(st,2);
+ tick = script_getnum(st,3);
+ val1 = script_getnum(st,4);
+ rate = script_getnum(st,5);
+ if( script_hasdata(st,6) )
bl = map_id2bl(script_getnum(st,6));
else
bl = map_id2bl(st->rid);
- if (type >= 0 && type < SC_MAX && val1 && !tick)
- { //When there isn't a duration specified, try to get it from the skill_db
- tick = StatusSkillChangeTable[type];
- if (tick)
- tick = skill_get_time(tick,val1);
- else //Failed to retrieve duration, reset to what it was.
- tick = 0;
+ if( tick == 0 && val1 > 0 && type >= 0 && type < SC_MAX && StatusSkillChangeTable[type] != 0 )
+ {// When there isn't a duration specified, try to get it from the skill_db
+ tick = skill_get_time(StatusSkillChangeTable[type], val1);
}
- if (potion_flag==1 && potion_target) {
+ if( potion_flag == 1 && potion_target )
+ {//##TODO how does this work [FlavioJS]
bl = map_id2bl(potion_target);
- tick/=2;
- val4 = 1;
+ tick /= 2;// Thrown potions only last half.
+ val4 = 1;// Mark that this was a thrown sc_effect
}
- if(bl)
- status_change_start(bl,type,per,val1,0,0,val4,tick,11);
+ if( bl )
+ status_change_start(bl, type, rate, val1, 0, 0, val4, tick, 1|2|8);
+
return 0;
}
-/*==========================================
- * Starts a SC_ change with the four values passed. [Skotlex]
- * Final optional argument is the ID of player to affect.
- * sc_start4 type, duration, val1, val2, val3, val4, <id>;
- *------------------------------------------*/
+/// Starts a status effect on the target unit or on the attached player.
+///
+/// sc_start4 <effect_id>,<duration>,<val1>,<val2>,<val3>,<val4>{,<unit_id>};
BUILDIN_FUNC(sc_start4)
{
- struct block_list *bl;
- int type,tick,val1,val2,val3,val4;
- type=script_getnum(st,2);
- tick=script_getnum(st,3);
- val1=script_getnum(st,4);
- val2=script_getnum(st,5);
- val3=script_getnum(st,6);
- val4=script_getnum(st,7);
+ struct block_list* bl;
+ int type;
+ int tick;
+ int val1;
+ int val2;
+ int val3;
+ int val4;
+
+ type = script_getnum(st,2);
+ tick = script_getnum(st,3);
+ val1 = script_getnum(st,4);
+ val2 = script_getnum(st,5);
+ val3 = script_getnum(st,6);
+ val4 = script_getnum(st,7);
if( script_hasdata(st,8) )
bl = map_id2bl(script_getnum(st,8));
else
bl = map_id2bl(st->rid);
- if (type >= 0 && type < SC_MAX && val1 && !tick)
- { //When there isn't a duration specified, try to get it from the skill_db
- tick = StatusSkillChangeTable[type];
- if (tick)
- tick = skill_get_time(tick,val1);
- else //Failed to retrieve duration, reset to what it was.
- tick = 0;
+ if( tick == 0 && val1 > 0 && type >= 0 && type < SC_MAX && StatusSkillChangeTable[type] != 0 )
+ {// When there isn't a duration specified, try to get it from the skill_db
+ tick = skill_get_time(StatusSkillChangeTable[type], val1);
}
- if (potion_flag==1 && potion_target) {
+ if( potion_flag == 1 && potion_target )
+ {//##TODO how does this work [FlavioJS]
bl = map_id2bl(potion_target);
- tick/=2;
+ tick /= 2;// Thrown potions only last half.
}
- if (bl)
- status_change_start(bl,type,10000,val1,val2,val3,val4,tick,11);
+
+ if( bl )
+ status_change_start(bl, type, 10000, val1, val2, val3, val4, tick, 1|2|8);
+
return 0;
}
-/*==========================================
- * 状態異常が直る
- *------------------------------------------*/
+/// Ends one or all status effects on the target unit or on the attached player.
+///
+/// sc_end <effect_id>{,<unit_id>};
BUILDIN_FUNC(sc_end)
{
- struct block_list *bl;
+ struct block_list* bl;
int type;
- type=script_getnum(st,2);
- bl = map_id2bl(st->rid);
+
+ type = script_getnum(st,2);
+ if( script_hasdata(st,3) )
+ bl = map_id2bl(script_getnum(st,3));
+ else
+ bl = map_id2bl(st->rid);
- if (potion_flag==1 && potion_target)
+ if( potion_flag==1 && potion_target )
+ {//##TODO how does this work [FlavioJS]
bl = map_id2bl(potion_target);
+ }
+
+ if( bl )
+ {
+ if( type >= 0 )
+ status_change_end(bl, type, INVALID_TIMER);
+ else
+ status_change_clear(bl, 2);// remove all effects
+ }
- if (!bl) return 0;
- if (type >= 0)
- status_change_end(bl,type,-1);
- else
- status_change_clear(bl, 2);
return 0;
}
+
/*==========================================
* 状態異常耐性を計算した確率を返す
*------------------------------------------*/
@@ -13050,12 +13092,13 @@ BUILDIN_FUNC(unittalk)
bl = map_id2bl(unit_id);
if( bl != NULL )
{
- struct StringBuf* buf = StringBuf_Malloc();
- StringBuf_Printf(buf, "%s : %s", status_get_name(bl), message);
- clif_message(bl, StringBuf_Value(buf));
+ struct StringBuf sbuf;
+ StringBuf_Init(&sbuf);
+ StringBuf_Printf(&sbuf, "%s : %s", status_get_name(bl), message);
+ clif_message(bl, StringBuf_Value(&sbuf));
if( bl->type == BL_PC )
- clif_displaymessage(((TBL_PC*)bl)->fd, StringBuf_Value(buf));
- StringBuf_Free(buf);
+ clif_displaymessage(((TBL_PC*)bl)->fd, StringBuf_Value(&sbuf));
+ StringBuf_Destroy(&sbuf);
}
return 0;
diff --git a/src/map/status.c b/src/map/status.c
index 9b4e2cfd2..75f2cbdfe 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -6072,9 +6072,9 @@ int status_change_clear(struct block_list *bl,int type)
case SC_JAILED:
continue;
}
- status_change_end(bl, i, -1);
+ status_change_end(bl, i, INVALID_TIMER);
- if (type == 1 && sc->data[i].timer != -1)
+ if( type == 1 && sc->data[i].timer != INVALID_TIMER )
{ //If for some reason status_change_end decides to still keep the status when quitting. [Skotlex]
(sc->count)--;
delete_timer(sc->data[i].timer, status_change_timer);