diff options
-rw-r--r-- | Changelog-Trunk.txt | 5 | ||||
-rw-r--r-- | doc/script_commands.txt | 9 | ||||
-rw-r--r-- | src/map/script.c | 251 | ||||
-rw-r--r-- | src/map/status.c | 4 |
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); |