* 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.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@10773 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
FlavioJS 2007-06-15 21:26:17 +00:00
parent 2c86752e59
commit 2d1ad607c3
4 changed files with 163 additions and 108 deletions

View File

@ -3,6 +3,11 @@ Date Added
AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK. 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. 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 2007/06/11
* Fixed NPC_PROVOCATION (now the casting mob doesn't keep attacking) * Fixed NPC_PROVOCATION (now the casting mob doesn't keep attacking)
* accumulated clif.c fixes [ultramage] * accumulated clif.c fixes [ultramage]

View File

@ -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 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 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(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>}; *return {<value>};

View File

@ -51,6 +51,16 @@
#include <time.h> #include <time.h>
#include <setjmp.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; // struct script_state* st;
// //
@ -3910,7 +3920,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(callsub,"i*"), BUILDIN_DEF(callsub,"i*"),
BUILDIN_DEF(callfunc,"s*"), BUILDIN_DEF(callfunc,"s*"),
BUILDIN_DEF(return,"?"), BUILDIN_DEF(return,"?"),
BUILDIN_DEF(getarg,"i"), BUILDIN_DEF(getarg,"i?"),
BUILDIN_DEF(jobchange,"i*"), BUILDIN_DEF(jobchange,"i*"),
BUILDIN_DEF(jobname,"i"), BUILDIN_DEF(jobname,"i"),
BUILDIN_DEF(input,"v"), BUILDIN_DEF(input,"v"),
@ -4031,10 +4041,10 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(disablearena,""), // Added by RoVeRT BUILDIN_DEF(disablearena,""), // Added by RoVeRT
BUILDIN_DEF(hideoffnpc,"s"), BUILDIN_DEF(hideoffnpc,"s"),
BUILDIN_DEF(hideonnpc,"s"), BUILDIN_DEF(hideonnpc,"s"),
BUILDIN_DEF(sc_start,"iii*"), BUILDIN_DEF(sc_start,"iii?"),
BUILDIN_DEF(sc_start2,"iiii*"), BUILDIN_DEF(sc_start2,"iiii?"),
BUILDIN_DEF(sc_start4,"iiiiii*"), BUILDIN_DEF(sc_start4,"iiiiii?"),
BUILDIN_DEF(sc_end,"i"), BUILDIN_DEF(sc_end,"i?"),
BUILDIN_DEF(getscrate,"ii*"), BUILDIN_DEF(getscrate,"ii*"),
BUILDIN_DEF(debugmes,"s"), BUILDIN_DEF(debugmes,"s"),
BUILDIN_DEF2(catchpet,"pet","i"), BUILDIN_DEF2(catchpet,"pet","i"),
@ -4685,26 +4695,38 @@ BUILDIN_FUNC(callsub)
return 0; return 0;
} }
/*========================================== /// Retrieves an argument provided to callfunc/callsub.
* /// If the argument doesn't exist
*------------------------------------------*/ ///
/// getarg(<index>{,<default_value>}) -> <value>
BUILDIN_FUNC(getarg) BUILDIN_FUNC(getarg)
{ {
int num=script_getnum(st,2); int idx;
int max,stsp; int count;
if( st->stack->defsp<5 || st->stack->stack_data[st->stack->defsp-1].type!=C_RETINFO ){ int stsp;
ShowWarning("script:getarg without callfunc or callsub!\n");
st->state=END; 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; return 1;
} }
max=conv_num(st,& (st->stack->stack_data[st->stack->defsp-5])); count = conv_num(st, &(st->stack->stack_data[st->stack->defsp - 5]));
stsp=st->stack->defsp - max -5; stsp = st->stack->defsp - count - 5;
if( num >= max ){
ShowWarning("script:getarg arg1(%d) out of range(%d) !\n",num,max); idx = script_getnum(st,2);
st->state=END;
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; return 1;
} }
push_copy(st->stack,stsp+num);
return 0; return 0;
} }
@ -8175,133 +8197,153 @@ BUILDIN_FUNC(hideonnpc)
npc_enable(str,4); npc_enable(str,4);
return 0; 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) BUILDIN_FUNC(sc_start)
{ {
struct block_list *bl; struct block_list* bl;
int type,tick,val1,val4=0; int type;
type=script_getnum(st,2); int tick;
tick=script_getnum(st,3); int val1;
val1=script_getnum(st,4); int val4 = 0;
if( script_hasdata(st,5) ) //指定したキャラを状態異常にする
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)); bl = map_id2bl(script_getnum(st,5));
else else
bl = map_id2bl(st->rid); bl = map_id2bl(st->rid);
if (potion_flag==1 && potion_target) { 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 )
{//##TODO how does this work [FlavioJS]
bl = map_id2bl(potion_target); bl = map_id2bl(potion_target);
tick/=2; //Thrown potions only last half. tick /= 2;// Thrown potions only last half.
val4 = 1; //Mark that this was a thrown sc_effect val4 = 1;// Mark that this was a thrown sc_effect
} }
if (type >= 0 && type < SC_MAX && val1 && !tick)
{ //When there isn't a duration specified, try to get it from the skill_db if( bl )
tick = StatusSkillChangeTable[type]; status_change_start(bl, type, 10000, val1, 0, 0, val4, tick, 1|2|8);
if (tick)
tick = skill_get_time(tick,val1);
else //Failed to retrieve duration, reset to what it was.
tick = 0;
}
if (bl)
status_change_start(bl,type,10000,val1,0,0,val4,tick,11);
return 0; 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) BUILDIN_FUNC(sc_start2)
{ {
struct block_list *bl; struct block_list* bl;
int type,tick,val1,val4=0,per; int type;
type=script_getnum(st,2); int tick;
tick=script_getnum(st,3); int val1;
val1=script_getnum(st,4); int val4 = 0;
per=script_getnum(st,5); int rate;
if( script_hasdata(st,6) ) //指定したキャラを状態異常にする
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)); bl = map_id2bl(script_getnum(st,6));
else else
bl = map_id2bl(st->rid); bl = map_id2bl(st->rid);
if (type >= 0 && type < SC_MAX && val1 && !tick) 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 {// When there isn't a duration specified, try to get it from the skill_db
tick = StatusSkillChangeTable[type]; tick = skill_get_time(StatusSkillChangeTable[type], val1);
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) { if( potion_flag == 1 && potion_target )
{//##TODO how does this work [FlavioJS]
bl = map_id2bl(potion_target); bl = map_id2bl(potion_target);
tick/=2; tick /= 2;// Thrown potions only last half.
val4 = 1; val4 = 1;// Mark that this was a thrown sc_effect
} }
if(bl) if( bl )
status_change_start(bl,type,per,val1,0,0,val4,tick,11); status_change_start(bl, type, rate, val1, 0, 0, val4, tick, 1|2|8);
return 0; return 0;
} }
/*========================================== /// Starts a status effect on the target unit or on the attached player.
* Starts a SC_ change with the four values passed. [Skotlex] ///
* Final optional argument is the ID of player to affect. /// sc_start4 <effect_id>,<duration>,<val1>,<val2>,<val3>,<val4>{,<unit_id>};
* sc_start4 type, duration, val1, val2, val3, val4, <id>;
*------------------------------------------*/
BUILDIN_FUNC(sc_start4) BUILDIN_FUNC(sc_start4)
{ {
struct block_list *bl; struct block_list* bl;
int type,tick,val1,val2,val3,val4; int type;
type=script_getnum(st,2); int tick;
tick=script_getnum(st,3); int val1;
val1=script_getnum(st,4); int val2;
val2=script_getnum(st,5); int val3;
val3=script_getnum(st,6); int val4;
val4=script_getnum(st,7);
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) ) if( script_hasdata(st,8) )
bl = map_id2bl(script_getnum(st,8)); bl = map_id2bl(script_getnum(st,8));
else else
bl = map_id2bl(st->rid); bl = map_id2bl(st->rid);
if (type >= 0 && type < SC_MAX && val1 && !tick) 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 {// When there isn't a duration specified, try to get it from the skill_db
tick = StatusSkillChangeTable[type]; tick = skill_get_time(StatusSkillChangeTable[type], val1);
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) { if( potion_flag == 1 && potion_target )
{//##TODO how does this work [FlavioJS]
bl = map_id2bl(potion_target); 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; 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) BUILDIN_FUNC(sc_end)
{ {
struct block_list *bl; struct block_list* bl;
int type; int type;
type=script_getnum(st,2);
bl = map_id2bl(st->rid);
if (potion_flag==1 && potion_target) type = script_getnum(st,2);
bl = map_id2bl(potion_target); if( script_hasdata(st,3) )
bl = map_id2bl(script_getnum(st,3));
if (!bl) return 0;
if (type >= 0)
status_change_end(bl,type,-1);
else else
status_change_clear(bl, 2); bl = map_id2bl(st->rid);
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
}
return 0; return 0;
} }
/*========================================== /*==========================================
* *
*------------------------------------------*/ *------------------------------------------*/
@ -13050,12 +13092,13 @@ BUILDIN_FUNC(unittalk)
bl = map_id2bl(unit_id); bl = map_id2bl(unit_id);
if( bl != NULL ) if( bl != NULL )
{ {
struct StringBuf* buf = StringBuf_Malloc(); struct StringBuf sbuf;
StringBuf_Printf(buf, "%s : %s", status_get_name(bl), message); StringBuf_Init(&sbuf);
clif_message(bl, StringBuf_Value(buf)); StringBuf_Printf(&sbuf, "%s : %s", status_get_name(bl), message);
clif_message(bl, StringBuf_Value(&sbuf));
if( bl->type == BL_PC ) if( bl->type == BL_PC )
clif_displaymessage(((TBL_PC*)bl)->fd, StringBuf_Value(buf)); clif_displaymessage(((TBL_PC*)bl)->fd, StringBuf_Value(&sbuf));
StringBuf_Free(buf); StringBuf_Destroy(&sbuf);
} }
return 0; return 0;

View File

@ -6072,9 +6072,9 @@ int status_change_clear(struct block_list *bl,int type)
case SC_JAILED: case SC_JAILED:
continue; 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] { //If for some reason status_change_end decides to still keep the status when quitting. [Skotlex]
(sc->count)--; (sc->count)--;
delete_timer(sc->data[i].timer, status_change_timer); delete_timer(sc->data[i].timer, status_change_timer);