Przeglądaj źródła

* 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://svn.code.sf.net/p/rathena/svn/trunk@14180 54d463be-8e91-2dee-dedb-b68131a5f0ec

Inkfish 15 lat temu
rodzic
commit
69bd8dced5
6 zmienionych plików z 103 dodań i 88 usunięć
  1. 5 0
      Changelog-Trunk.txt
  2. 29 35
      src/map/pc.c
  3. 2 4
      src/map/pc.h
  4. 66 48
      src/map/script.c
  5. 1 0
      src/map/script.h
  6. 0 1
      src/map/status.c

+ 5 - 0
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]

+ 29 - 35
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;
 

+ 2 - 4
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);

+ 66 - 48
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;

+ 1 - 0
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);

+ 0 - 1
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;
 		}