From 4afe95f6ad237ebddbc913f9e02dd1bbd4fb28b9 Mon Sep 17 00:00:00 2001 From: Inkfish Date: Wed, 2 Dec 2009 10:30:10 +0000 Subject: * Autobonus code cleanups. - removed the 'script_parsed' flag to fix the issues with combo items. - introduced a global cache for autobonus scripts so that we don't have to parse scripts everytime invoking status_calc_bl. - fixed such script commands as 'getrefine()' not working inside autobonus scripts. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@14180 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/pc.c | 64 ++++++++++++++----------------- src/map/pc.h | 6 +-- src/map/script.c | 114 ++++++++++++++++++++++++++++++++----------------------- src/map/script.h | 1 + src/map/status.c | 1 - 5 files changed, 98 insertions(+), 88 deletions(-) (limited to 'src') diff --git a/src/map/pc.c b/src/map/pc.c index b2db9858d..5f724012f 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1622,7 +1622,7 @@ static int pc_bonus_item_drop(struct s_add_drop *drop, const short max, short id return 1; } -int pc_addautobonus(struct s_autobonus *bonus,char max,struct script_code *script,short rate,unsigned int dur,short flag,struct script_code *other_script,unsigned short pos,bool onskill) +int pc_addautobonus(struct s_autobonus *bonus,char max,const char *script,short rate,unsigned int dur,short flag,const char *other_script,unsigned short pos,bool onskill) { int i; @@ -1653,8 +1653,8 @@ int pc_addautobonus(struct s_autobonus *bonus,char max,struct script_code *scrip bonus[i].active = INVALID_TIMER; bonus[i].atk_type = flag; bonus[i].pos = pos; - bonus[i].bonus_script = script; - bonus[i].other_script = other_script; + bonus[i].bonus_script = aStrdup(script); + bonus[i].other_script = other_script?aStrdup(other_script):NULL; return 1; } @@ -1665,31 +1665,30 @@ int pc_delautobonus(struct map_session_data* sd, struct s_autobonus *autobonus,c for( i = 0; i < max; i++ ) { - if( autobonus[i].active != INVALID_TIMER && !(restore && sd->state.autobonus&autobonus[i].pos) ) - { // Logout / Unequipped an item with an activated bonus - delete_timer(autobonus[i].active,pc_endautobonus); - autobonus[i].active = INVALID_TIMER; - } - - if( restore && sd->state.autobonus&autobonus[i].pos ) + if( autobonus[i].active != INVALID_TIMER ) { - if( autobonus[i].active != INVALID_TIMER && autobonus[i].bonus_script ) - run_script(autobonus[i].bonus_script,0,sd->bl.id,0); - continue; + if( restore && sd->state.autobonus&autobonus[i].pos ) + { + if( autobonus[i].bonus_script ) + { + int j; + ARR_FIND( 0, EQI_MAX-1, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == autobonus[i].pos ); + if( j < EQI_MAX-1 ) + script_run_autobonus(autobonus[i].bonus_script,sd->bl.id,sd->equip_index[j]); + } + continue; + } + else + { // Logout / Unequipped an item with an activated bonus + delete_timer(autobonus[i].active,pc_endautobonus); + autobonus[i].active = INVALID_TIMER; + } } - if( sd->state.autocast ) - continue; - - if( autobonus[i].pos&sd->state.script_parsed && restore ) - continue; - - if( autobonus[i].bonus_script ) - script_free_code(autobonus[i].bonus_script); - if( autobonus[i].other_script ) - script_free_code(autobonus[i].other_script); - autobonus[i].rate = autobonus[i].atk_type = autobonus[i].duration = autobonus[i].pos = 0; + if( autobonus[i].bonus_script ) aFree(autobonus[i].bonus_script); + if( autobonus[i].other_script ) aFree(autobonus[i].other_script); autobonus[i].bonus_script = autobonus[i].other_script = NULL; + autobonus[i].rate = autobonus[i].atk_type = autobonus[i].duration = autobonus[i].pos = 0; autobonus[i].active = INVALID_TIMER; } @@ -1703,9 +1702,10 @@ int pc_exeautobonus(struct map_session_data *sd,struct s_autobonus *autobonus) if( autobonus->other_script ) { - sd->state.autocast = 1; - run_script(autobonus->other_script,0,sd->bl.id,0); - sd->state.autocast = 0; + int j; + ARR_FIND( 0, EQI_MAX-1, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == autobonus->pos ); + if( j < EQI_MAX-1 ) + script_run_autobonus(autobonus->other_script,sd->bl.id,sd->equip_index[j]); } autobonus->active = add_timer(gettick()+autobonus->duration, pc_endautobonus, sd->bl.id, (intptr)autobonus); @@ -7001,7 +7001,6 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) * 0 - only unequip * 1 - calculate status after unequipping * 2 - force unequip - * 4 - ignore autobonus flags *------------------------------------------*/ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { @@ -7074,13 +7073,8 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) status_change_end(&sd->bl, SC_ARMOR_RESIST, -1); } - if( !(flag&4) ) - { - if( sd->state.script_parsed&sd->status.inventory[n].equip ) - sd->state.script_parsed &= ~sd->status.inventory[n].equip; - if( sd->state.autobonus&sd->status.inventory[n].equip ) - sd->state.autobonus &= ~sd->status.inventory[n].equip; //Check for activated autobonus [Inkfish] - } + if( sd->state.autobonus&sd->status.inventory[n].equip ) + sd->state.autobonus &= ~sd->status.inventory[n].equip; //Check for activated autobonus [Inkfish] sd->status.inventory[n].equip=0; diff --git a/src/map/pc.h b/src/map/pc.h index ab26721fd..7a6afd78c 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -70,8 +70,7 @@ struct s_add_drop { struct s_autobonus { short rate,atk_type; unsigned int duration; - struct script_code *bonus_script; - struct script_code *other_script; + char *bonus_script, *other_script; int active; unsigned short pos; }; @@ -130,7 +129,6 @@ struct map_session_data { unsigned int bg_id; unsigned skillonskill : 1; unsigned short user_font; - unsigned short script_parsed; //flag to indicate if the script of an autobonus is parsed. [Inkfish] unsigned short autobonus; //flag to indicate if an autobonus is activated. [Inkfish] } state; struct { @@ -585,7 +583,7 @@ bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd, int pc_updateweightstatus(struct map_session_data *sd); -int pc_addautobonus(struct s_autobonus *bonus,char max,struct script_code *script,short rate,unsigned int dur,short atk_type,struct script_code *other_script,unsigned short pos,bool onskill); +int pc_addautobonus(struct s_autobonus *bonus,char max,const char *script,short rate,unsigned int dur,short atk_type,const char *o_script,unsigned short pos,bool onskill); int pc_exeautobonus(struct map_session_data* sd,struct s_autobonus *bonus); int pc_endautobonus(int tid, unsigned int tick, int id, intptr data); int pc_delautobonus(struct map_session_data* sd,struct s_autobonus *bonus,char max,bool restore); diff --git a/src/map/script.c b/src/map/script.c index 2a506068e..6ef06c2a2 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -199,13 +199,16 @@ int str_hash[SCRIPT_HASH_SIZE]; //#define SCRIPT_HASH_SDBM #define SCRIPT_HASH_ELF - static DBMap* scriptlabel_db=NULL; // const char* label_name -> int script_pos static DBMap* userfunc_db=NULL; // const char* func_name -> struct script_code* static int parse_options=0; DBMap* script_get_label_db(){ return scriptlabel_db; } DBMap* script_get_userfunc_db(){ return userfunc_db; } +// Caches compiled autoscript item code. +// Note: This is not cleared when reloading itemdb. +static DBMap* autobonus_db=NULL; // char* script -> char* bytecode + struct Script_Config script_config = { 1, 65535, 2048, //warn_func_mismatch_paramnum/check_cmdcount/check_gotocount 0, INT_MAX, // input_min_value/input_max_value @@ -3360,6 +3363,38 @@ static int do_final_userfunc_sub (DBKey key,void *data,va_list ap) return 0; } +static int do_final_autobonus_sub (DBKey key,void *data,va_list ap) +{ + struct script_code *script = (struct script_code *)data; + + if( script ) + script_free_code(script); + + return 0; +} + +void script_run_autobonus(const char *autobonus, int id, int pos) +{ + struct script_code *script = (struct script_code *)strdb_get(autobonus_db, autobonus); + + if( script ) + { + current_equip_item_index = pos; + run_script(script,0,id,0); + } +} + +void script_add_autobonus(const char *autobonus) +{ + if( strdb_get(autobonus_db, autobonus) == NULL ) + { + struct script_code *script = parse_script(autobonus, "autobonus", 0, 0); + + if( script ) + strdb_put(autobonus_db, autobonus, script); + } +} + /*========================================== * I *------------------------------------------*/ @@ -3424,6 +3459,7 @@ int do_final_script() scriptlabel_db->destroy(scriptlabel_db,NULL); userfunc_db->destroy(userfunc_db,do_final_userfunc_sub); + autobonus_db->destroy(autobonus_db, do_final_autobonus_sub); if(sleep_db) { struct linkdb_node *n = (struct linkdb_node *)sleep_db; while(n) { @@ -3448,6 +3484,7 @@ int do_init_script() { userfunc_db=strdb_alloc(DB_OPT_DUP_KEY,0); scriptlabel_db=strdb_alloc((DBOptions)(DB_OPT_DUP_KEY|DB_OPT_ALLOW_NULL_DATA),50); + autobonus_db = strdb_alloc(DB_OPT_DUP_KEY,0); mapreg_init(); @@ -3473,7 +3510,6 @@ int script_reload() return 0; } - //----------------------------------------------------------------------------- // buildin functions // @@ -6440,7 +6476,7 @@ BUILDIN_FUNC(successrefitem) log_pick_pc(sd, "N", sd->status.inventory[i].nameid, -1, &sd->status.inventory[i]); sd->status.inventory[i].refine++; - pc_unequipitem(sd,i,2|4); // status calc will happen in pc_equipitem() below + pc_unequipitem(sd,i,2); // status calc will happen in pc_equipitem() below clif_refine(sd->fd,0,i,sd->status.inventory[i].refine); clif_delitem(sd,i,1); @@ -6632,38 +6668,32 @@ BUILDIN_FUNC(autobonus) short rate; short atk_type = 0; TBL_PC* sd; - struct script_code *bonus_script; - struct script_code *other_script = NULL; + const char *bonus_script, *other_script = NULL; sd = script_rid2sd(st); if( sd == NULL ) return 0; // no player attached - if( sd->state.autocast ) - return 0; + if( sd->state.autobonus&sd->status.inventory[current_equip_item_index].equip ) return 0; - if( sd->state.script_parsed&sd->status.inventory[current_equip_item_index].equip ) - return 0; rate = script_getnum(st,3); dur = script_getnum(st,4); - if( !rate || !dur ) - return 0; - bonus_script = parse_script(script_getstr(st,2), "autobonus bonus", 0, 0); - if( !bonus_script ) + bonus_script = script_getstr(st,2); + if( !rate || !dur || !bonus_script ) return 0; if( script_hasdata(st,5) ) atk_type = script_getnum(st,5); if( script_hasdata(st,6) ) - other_script = parse_script(script_getstr(st,6), "autobonus other", 0, 0); + other_script = script_getstr(st,6); - if( !pc_addautobonus(sd->autobonus,ARRAYLENGTH(sd->autobonus),bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,false) ) + if( pc_addautobonus(sd->autobonus,ARRAYLENGTH(sd->autobonus), + bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,false) ) { - if( bonus_script ) - script_free_code(bonus_script); + script_add_autobonus(bonus_script); if( other_script ) - script_free_code(other_script); + script_add_autobonus(other_script); } return 0; @@ -6675,38 +6705,32 @@ BUILDIN_FUNC(autobonus2) short rate; short atk_type = 0; TBL_PC* sd; - struct script_code *bonus_script; - struct script_code *other_script = NULL; + const char *bonus_script, *other_script = NULL; sd = script_rid2sd(st); if( sd == NULL ) return 0; // no player attached - if( sd->state.autocast ) - return 0; + if( sd->state.autobonus&sd->status.inventory[current_equip_item_index].equip ) return 0; - if( sd->state.script_parsed&sd->status.inventory[current_equip_item_index].equip ) - return 0; rate = script_getnum(st,3); dur = script_getnum(st,4); - if( !rate || !dur ) - return 0; - bonus_script = parse_script(script_getstr(st,2), "autobonus2 bonus", 0, 0); - if( !bonus_script ) + bonus_script = script_getstr(st,2); + if( !rate || !dur || !bonus_script ) return 0; if( script_hasdata(st,5) ) atk_type = script_getnum(st,5); if( script_hasdata(st,6) ) - other_script = parse_script(script_getstr(st,6), "autobonus2 other", 0, 0); + other_script = script_getstr(st,6); - if( !pc_addautobonus(sd->autobonus2,ARRAYLENGTH(sd->autobonus2),bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,false) ) + if( pc_addautobonus(sd->autobonus2,ARRAYLENGTH(sd->autobonus2), + bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,false) ) { - if( bonus_script ) - script_free_code(bonus_script); + script_add_autobonus(bonus_script); if( other_script ) - script_free_code(other_script); + script_add_autobonus(other_script); } return 0; @@ -6717,37 +6741,31 @@ BUILDIN_FUNC(autobonus3) unsigned int dur; short rate,atk_type; TBL_PC* sd; - struct script_code *bonus_script; - struct script_code *other_script = NULL; + const char *bonus_script, *other_script = NULL; sd = script_rid2sd(st); if( sd == NULL ) return 0; // no player attached - if( sd->state.autocast ) - return 0; + if( sd->state.autobonus&sd->status.inventory[current_equip_item_index].equip ) return 0; - if( sd->state.script_parsed&sd->status.inventory[current_equip_item_index].equip ) - return 0; rate = script_getnum(st,3); dur = script_getnum(st,4); atk_type = ( script_isstring(st,5) ? skill_name2id(script_getstr(st,5)) : script_getnum(st,5) ); - if( !rate || !dur || !atk_type ) - return 0; - bonus_script = parse_script(script_getstr(st,2), "autobonus3 bonus", 0, 0); - if( !bonus_script ) + bonus_script = script_getstr(st,2); + if( !rate || !dur || !atk_type || !bonus_script ) return 0; if( script_hasdata(st,6) ) - other_script = parse_script(script_getstr(st,6), "autobonus3 other", 0, 0); + other_script = script_getstr(st,6); - if( !pc_addautobonus(sd->autobonus3,ARRAYLENGTH(sd->autobonus3),bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,true) ) + if( pc_addautobonus(sd->autobonus3,ARRAYLENGTH(sd->autobonus3), + bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,true) ) { - if( bonus_script ) - script_free_code(bonus_script); + script_add_autobonus(bonus_script); if( other_script ) - script_free_code(other_script); + script_add_autobonus(other_script); } return 0; diff --git a/src/map/script.h b/src/map/script.h index 84f2b34a1..aa6b85140 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -161,6 +161,7 @@ void script_free_state(struct script_state* st); struct DBMap* script_get_label_db(void); struct DBMap* script_get_userfunc_db(void); +void script_run_autobonus(const char *autobonus,int id, int pos); int script_config_read(char *cfgName); int do_init_script(void); diff --git a/src/map/status.c b/src/map/status.c index 0870340eb..2017a12fc 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -1871,7 +1871,6 @@ int status_calc_pc_(struct map_session_data* sd, bool first) if(first && sd->inventory_data[index]->equip_script) { //Execute equip-script on login run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0); - sd->state.script_parsed |= sd->status.inventory[index].equip; if (!calculating) return 1; } -- cgit v1.2.3-60-g2f50