Browse Source

Code cleanup on homunc, they stay in memory until player disconnect or homunc destruction

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@8241 54d463be-8e91-2dee-dedb-b68131a5f0ec
toms 19 years ago
parent
commit
d7e51241f8
6 changed files with 127 additions and 79 deletions
  1. 2 0
      Changelog-Trunk.txt
  2. 1 1
      src/map/map.c
  3. 93 63
      src/map/mercenary.c
  4. 3 1
      src/map/mercenary.h
  5. 4 4
      src/map/skill.c
  6. 24 10
      src/map/unit.c

+ 2 - 0
Changelog-Trunk.txt

@@ -4,6 +4,8 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
 2006/08/10
+	* Code cleanup on homunc, they stay in memory until player disconnect or 
+	  homunc destruction [Toms]
 	* Corrected Advanced Jobs HP bonus from 30% -> 25% [Skotlex]
 	* Hopefully fixed family-party-even-share not breaking when a member logs
 	  out. [Skotlex]

+ 1 - 1
src/map/map.c

@@ -1669,7 +1669,7 @@ int map_quit(struct map_session_data *sd) {
 		sd->state.waitingdisconnect = 1;
 		if (sd->pd) unit_free(&sd->pd->bl);
 		if(sd->status.hom_id > 0 && sd->hd)	//[orn]
-			merc_hom_delete(sd->hd, 0) ;
+			merc_hom_delete(sd->hd, 2) ;
 		unit_free(&sd->bl);
 		chrif_save(sd,1);
 	} else { //Try to free some data, without saving anything (this could be invoked on map server change. [Skotlex]

+ 93 - 63
src/map/mercenary.c

@@ -113,7 +113,7 @@ void merc_damage(struct homun_data *hd,struct block_list *src,int hp,int sp)
 
 int merc_hom_dead(struct homun_data *hd, struct block_list *src)
 {
-	hd->master->homunculus.hp = 0 ;
+	hd->battle_status.hp = hd->master->homunculus.hp = 0 ;
 	clif_hominfo(hd->master,hd,0); // Send dead flag
 	if(!merc_hom_decrease_intimacy(hd, 100)) { // Intimacy was < 100
 		merc_stop_walking(hd, 1);
@@ -122,16 +122,24 @@ int merc_hom_dead(struct homun_data *hd, struct block_list *src)
 		merc_hom_delete(hd,1) ;
 		return 1 ;
 	}
+	clif_send_homdata(hd->master,SP_INTIMATE,hd->master->homunculus.intimacy / 100);
 	clif_emotion(&hd->bl, 16) ;	//wah
 	clif_emotion(&hd->master->bl, 28) ;	//sob
 	merc_hom_delete(hd, 0);
 
-	return 3; //Remove it from map.
+	return 1; // Removing is handled by merc_hom_delete
 }
 
 int merc_hom_delete(struct homun_data *hd, int flag)
 {
 	nullpo_retr(0, hd);
+
+	if ((flag & 2) && hd->bl.prev == NULL)
+	{
+		// Homunc was already removed from map, so just free the bl
+		return unit_free(&hd->bl);
+	}
+
 	// Delete homunculus
 	if ( flag&1 ) {	//sabbath
 		intif_homunculus_requestdelete(hd->master->homunculus.hom_id) ;
@@ -140,9 +148,9 @@ int merc_hom_delete(struct homun_data *hd, int flag)
 		hd->master->homunculus.hom_id = 0;
 		chrif_save(hd->master,0);
 	} else
-		merc_save(hd) ;
+		merc_save(hd);
 
-	return unit_free(&hd->bl);
+	return unit_remove_map(&hd->bl, 0);
 }
 
 int merc_hom_calc_skilltree(struct map_session_data *sd)
@@ -456,23 +464,32 @@ static int merc_natural_heal_sub(struct homun_data *hd,int tick) {
 int merc_natural_heal(int tid,unsigned int tick,int id,int data)
 {
 	struct map_session_data *sd;
+	struct homun_data * hd;
 
 	sd=map_id2sd(id);
+	if(!sd)
+		return 1;
 
-	nullpo_retr(0, sd);
-	
-	sd->hd->natural_heal_timer = -1;
+	if(!sd->status.hom_id || !(hd = sd->hd))
+		return 1;
 
-	if(sd->homunculus.vaporize)
+	if(hd->natural_heal_timer != tid){
+		if(battle_config.error_log)
+			ShowError("merc_natural_heal %d != %d\n",hd->natural_heal_timer,tid);
 		return 1;
+	}
 
-	if(sd && sd->hd) {
-		natural_heal_diff_tick = DIFF_TICK(tick,natural_heal_prev_tick);
-		merc_natural_heal_sub(sd->hd, tick);
+	hd->natural_heal_timer = -1;
+
+	if(sd->homunculus.vaporize || sd->homunculus.hp == 0)
+		return 1;
 	
-		natural_heal_prev_tick = tick;
-		sd->hd->natural_heal_timer = add_timer(gettick()+battle_config.natural_healhp_interval, merc_natural_heal,sd->bl.id,0);
-	}
+	natural_heal_diff_tick = DIFF_TICK(tick,natural_heal_prev_tick);
+	merc_natural_heal_sub(hd, tick);
+	
+	natural_heal_prev_tick = tick;
+	sd->hd->natural_heal_timer = add_timer(gettick()+battle_config.natural_healhp_interval, merc_natural_heal,sd->bl.id,0);
+
 	return 0;
 }
 
@@ -721,7 +738,8 @@ int search_homunculusDB_index(int key,int type)
 	return -1;
 }
 
-int merc_hom_data_init(struct map_session_data *sd)
+// Create homunc structure
+int merc_hom_create(struct map_session_data *sd)
 {
 	struct homun_data *hd;
 	int i = 0 ;
@@ -737,12 +755,16 @@ int merc_hom_data_init(struct map_session_data *sd)
 	}
 	sd->hd = hd = (struct homun_data *)aCalloc(1,sizeof(struct homun_data));
 	hd->homunculusDB = &homunculus_db[i];
-	merc_calc_pos(hd,sd->bl.x,sd->bl.y,sd->ud.dir);
-	hd->bl.x = hd->ud.to_x;
-	hd->bl.y = hd->ud.to_y;
 	hd->master = sd;
+	return merc_hom_data_init(sd);
+}
+
+int merc_hom_data_init(struct map_session_data *sd)
+{
+	struct homun_data * hd = sd->hd;
+	int i;
 
-	sd->status.hom_id = sd->homunculus.hom_id ;
+	nullpo_retr(1, hd);
 
 	hd->bl.m=sd->bl.m;
 	hd->bl.x=sd->bl.x;
@@ -782,48 +804,56 @@ int merc_hom_data_init(struct map_session_data *sd)
 	
 	map_addiddb(&hd->bl);
 	status_calc_homunculus(hd,1);
-	//timer
-		hd->hungry_timer = add_timer(gettick()+hd->homunculusDB->hungryDelay,merc_hom_hungry,sd->bl.id,0);
-		natural_heal_prev_tick = gettick();
-		hd->natural_heal_timer = add_timer(gettick()+battle_config.natural_healhp_interval, merc_natural_heal,sd->bl.id,0);
-		
+
+	// Timers
+	hd->hungry_timer = add_timer(gettick()+hd->homunculusDB->hungryDelay,merc_hom_hungry,hd->master->bl.id,0);
+	natural_heal_prev_tick = gettick();
+	hd->natural_heal_timer = add_timer(gettick()+battle_config.natural_healhp_interval, merc_natural_heal,hd->master->bl.id,0);
 	return 0;
 }
+
 // FIX call_homunculus [albator]
 int merc_call_homunculus(struct map_session_data *sd)
 {
 	int class_ = 0 ;
 	nullpo_retr(0, sd);
 
+	if (!sd->status.hom_id)
+	{
+		class_ = 6000 + rand(1, 8) ;
+		return merc_create_homunculus(sd, class_) ;
+	}
+
+	// If homunc not yet loaded, load it, else just activate it
+	if (!sd->hd)
+		merc_hom_create(sd);
+	else
+		merc_hom_data_init(sd);
+
 	// call vaporized homunculus [albator]
 	if(sd->homunculus.vaporize == 1)
 	{
 		sd->homunculus.vaporize = 0;
-		merc_hom_data_init(sd);
-
-		if ( sd->homunculus.hp && sd->hd && sd->bl.prev != NULL) {
-			map_addblock(&sd->hd->bl);
-			clif_spawn(&sd->hd->bl);
-			clif_send_homdata(sd,SP_ACK,0);
-			clif_hominfo(sd,sd->hd,1);
-			clif_hominfo(sd,sd->hd,0); // send this x2. dunno why, but kRO does that [blackhole89]
-			clif_homskillinfoblock(sd);
-		}
-		// save
-		merc_save(sd->hd);
-		return 1;
-		
 	}
-
-	if ( sd->status.hom_id ) {
-		return merc_hom_recv_data(sd->status.account_id, &sd->homunculus, 1 ) ;
-	} else {
-		class_ = 6000 + rand(1, 8) ;
-		return merc_create_homunculus(sd, class_) ;
+	else
+	{
+		// Homunc was dead, set hp to 1
+		sd->homunculus.hp = 1 ;
 	}
 
-	
+	if ( sd->homunculus.hp && sd->hd && sd->bl.prev != NULL) {
+		map_addblock(&sd->hd->bl);
+		clif_spawn(&sd->hd->bl);
+		clif_send_homdata(sd,SP_ACK,0);
+		clif_hominfo(sd,sd->hd,1);
+		clif_hominfo(sd,sd->hd,0); // send this x2. dunno why, but kRO does that [blackhole89]
+		clif_homskillinfoblock(sd);
+	}
+	// save
+	merc_save(sd->hd);
+	return 1;
 }
+
 // Albator
 // Recv data of an homunculus after it loading
 int merc_hom_recv_data(int account_id, struct s_homunculus *sh, int flag)
@@ -840,13 +870,9 @@ int merc_hom_recv_data(int account_id, struct s_homunculus *sh, int flag)
 	}
 	memcpy(&sd->homunculus, sh, sizeof(struct s_homunculus));
 
-	if ( flag == 2 ) {
-		sh->hp = 1 ; 
-		sd->homunculus.hp = 1 ;
-	}
-	if(sd->homunculus.hp && sh->vaporize!=1)
+	if(sd->homunculus.hp && sd->homunculus.vaporize!=1)
 	{
-		merc_hom_data_init(sd);
+		merc_hom_create(sd);
 		
 		if ( sd->hd && sd->bl.prev != NULL) {
 			map_addblock(&sd->hd->bl);
@@ -907,19 +933,23 @@ int merc_hom_revive(struct map_session_data *sd, int per)
 {
 	nullpo_retr(0, sd);
 
-	merc_hom_data_init(sd);
+	// Homunc not already loaded, load it, else just init timers
+	if (!sd->hd)
+		merc_hom_create(sd);
+	else
+		merc_hom_data_init(sd);
 
-		if ( sd->hd && sd->bl.prev != NULL) {
-			sd->homunculus.hp = sd->hd->base_status.hp = sd->hd->battle_status.hp = 1 ;
-			status_heal(&sd->hd->bl, sd->homunculus.max_hp*per/100, 0, 1) ;
-			map_addblock(&sd->hd->bl);
-			clif_spawn(&sd->hd->bl);
-			clif_send_homdata(sd,SP_ACK,0);
-			clif_hominfo(sd,sd->hd,1);
-			clif_hominfo(sd,sd->hd,0);
-			clif_homskillinfoblock(sd);
-			clif_specialeffect(&sd->hd->bl,77,AREA) ;	//resurrection angel
-		}
+	if ( sd->hd && sd->bl.prev != NULL) {
+		sd->homunculus.hp = sd->hd->base_status.hp = sd->hd->battle_status.hp = 1 ;
+		status_heal(&sd->hd->bl, sd->homunculus.max_hp*per/100, 0, 1) ;
+		map_addblock(&sd->hd->bl);
+		clif_spawn(&sd->hd->bl);
+		clif_send_homdata(sd,SP_ACK,0);
+		clif_hominfo(sd,sd->hd,1);
+		clif_hominfo(sd,sd->hd,0);
+		clif_homskillinfoblock(sd);
+		clif_specialeffect(&sd->hd->bl,77,AREA) ;	//resurrection angel
+	}
 
 	return 1 ;
 }

+ 3 - 1
src/map/mercenary.h

@@ -46,7 +46,8 @@ enum {
 	SP_INTIMATE 	= 0x100,
 	SP_HUNGRY 		= 0x200
 };
-
+// merc_is_hom_alive(struct homun_data *)
+#define merc_is_hom_active(x) (x && x->master && x->master->homunculus.vaporize != 1 && x->battle_status.hp != 0)
 int do_init_merc(void);
 int merc_hom_recv_data(int account_id, struct s_homunculus *sh, int flag); //albator
 void merc_load_sub(struct homun_data *hd, struct map_session_data *sd);
@@ -79,3 +80,4 @@ int read_homunculusdb(void);
 int merc_hom_increase_intimacy(struct homun_data * hd, unsigned int value);
 int merc_hom_decrease_intimacy(struct homun_data * hd, unsigned int value);
 int merc_skill_tree_get_max(int id, int b_class);
+int merc_hom_data_init(struct map_session_data *sd);

+ 4 - 4
src/map/skill.c

@@ -5489,7 +5489,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 	case AM_CALLHOMUN:	//[orn]
 		if (sd)
 		{
-			if ((sd->status.hom_id == 0 || sd->homunculus.vaporize == 1)) {
+			if (sd->status.hom_id == 0 || sd->homunculus.vaporize == 1) {
 				if (sd->status.hom_id == 0) {
 					i = pc_search_inventory(sd,7142);
 					if(i < 0) {
@@ -5509,12 +5509,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 	{
 		if (sd)
 		{
-			if (sd->hd && ( sd->hd->battle_status.hp >= (sd->hd->battle_status.max_hp * 80 / 100 ) ) ) {
+			if (sd->hd && !sd->homunculus.vaporize && ( sd->hd->battle_status.hp >= (sd->hd->battle_status.max_hp * 80 / 100 ) ) ) {
 				sd->homunculus.vaporize = 1;
 				clif_hominfo(sd, sd->hd, 0);
 				merc_hom_delete(sd->hd, 0) ;
-			}
-			clif_skill_fail(sd,skillid,0,0);
+			} else
+				clif_skill_fail(sd,skillid,0,0);
 		}
 		break;
 	}

+ 24 - 10
src/map/unit.c

@@ -1605,6 +1605,30 @@ int unit_remove_map(struct block_list *bl, int clrtype) {
 			map_freeblock_unlock();
 			return 0;
 		}
+	} else if (bl->type == BL_HOM) {
+		struct homun_data *hd = (struct homun_data *) bl;
+		struct map_session_data *sd = hd->master;
+		
+		// Desactive timers
+		merc_hom_hungry_timer_delete(hd);
+		merc_natural_heal_timer_delete(hd);
+
+		if(!sd) {
+			map_delblock(bl);
+			unit_free(bl);
+			map_freeblock_unlock();
+			return 0;
+		}
+
+		// Homunc was deleted or player is leaving the server, remove it from memory
+		if (sd->homunculus.hom_id == 0 || sd->state.waitingdisconnect)
+		{	//Remove pet.
+			map_delblock(bl);
+			unit_free(bl);
+			sd->hd = NULL;
+			map_freeblock_unlock();
+			return 1;
+		}
 	}
 	map_delblock(bl);
 	map_freeblock_unlock();
@@ -1770,16 +1794,6 @@ int unit_free(struct block_list *bl) {
 		}
 		if(mob_is_clone(md->class_))
 			mob_clone_delete(md->class_);
-	} else if( bl->type == BL_HOM ) {	//[orn]
-		struct homun_data *hd = (struct homun_data*)bl;
-		struct map_session_data *sd = hd->master;
-		merc_hom_hungry_timer_delete(hd);
-		merc_natural_heal_timer_delete(hd) ;
-		if (sd) {
-//			if(hd->intimacy > 0)
-//				intif_save_mercdata(sd->status.account_id,&sd->hom);
-			sd->hd = NULL;
-		}
 	}
 
 	skill_clear_unitgroup(bl);