summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorInkfish <Inkfish@54d463be-8e91-2dee-dedb-b68131a5f0ec>2009-12-02 10:30:10 +0000
committerInkfish <Inkfish@54d463be-8e91-2dee-dedb-b68131a5f0ec>2009-12-02 10:30:10 +0000
commit4afe95f6ad237ebddbc913f9e02dd1bbd4fb28b9 (patch)
tree3bb5818ac995b3853d9f0cd46de07542eddc2c4e
parentaefb12e53cbeed61558283309a5f8e2f31963fdb (diff)
downloadhercules-4afe95f6ad237ebddbc913f9e02dd1bbd4fb28b9.tar.gz
hercules-4afe95f6ad237ebddbc913f9e02dd1bbd4fb28b9.tar.bz2
hercules-4afe95f6ad237ebddbc913f9e02dd1bbd4fb28b9.tar.xz
hercules-4afe95f6ad237ebddbc913f9e02dd1bbd4fb28b9.zip
* 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
-rw-r--r--Changelog-Trunk.txt5
-rw-r--r--src/map/pc.c64
-rw-r--r--src/map/pc.h6
-rw-r--r--src/map/script.c114
-rw-r--r--src/map/script.h1
-rw-r--r--src/map/status.c1
6 files changed, 103 insertions, 88 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index 54c11eaed..fa5daf7e2 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.
+2009/12/02
+ * Autobonus code cleanups. [Inkfish]
+ - introduced a global cache for autobonus scripts so that we don't have to allocate and deallocate scripts everytime invoking status_calc_bl.
+ - removed the 'script_parsed' flag to fix the issues with combo items.
+ - fixed such script commands as 'getrefine()' not working inside autobonus scripts.
2009/11/26
* Moved log_sql_init() call up in map-server-init to after after map_sql_init() call to prevent unnecessary processing before a potential quit. [Paradox924X]
* NPC event code cleanups. [Inkfish]
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;
}