Procházet zdrojové kódy

- Sacrifice no longer shows damage to self.
- When Asura fails, the skill display will still come off.
- Cleaned up AM_CALLHOMUN so that the required item is specified on skill_require_db
- Cleaned up function merc_call_homun and added function merc_hom_vaporize to handle the respective cases.
- Cleaned up a bit unit_remove_map/unit_free on regards to homun. it will display the /sob emotion when the homun dies due to low intimacy. Moved removal of timers and all that to unit_free
- Cleaned up function merc_hom_dead
- Simplified lots of code around by using the new merc functions.


git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@8279 54d463be-8e91-2dee-dedb-b68131a5f0ec

skotlex před 19 roky
rodič
revize
6e5a887656
9 změnil soubory, kde provedl 134 přidání a 151 odebrání
  1. 5 0
      Changelog-Trunk.txt
  2. 1 1
      db/skill_require_db.txt
  3. 0 1
      src/map/battle.c
  4. 1 2
      src/map/map.c
  5. 77 80
      src/map/mercenary.c
  6. 1 1
      src/map/mercenary.h
  7. 3 9
      src/map/pc.c
  8. 15 27
      src/map/skill.c
  9. 31 30
      src/map/unit.c

+ 5 - 0
Changelog-Trunk.txt

@@ -4,6 +4,11 @@ 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/14
+	* Sacrifice no longer shows damage to self. [Skotlex]
+	* When Asura fails, the skill display will still come off. [Skotlex]
+	* Lots of cleaning of the Homun-code. Perhaps the crashes as of late will
+	  be fixed now (reusing AM_CALLHOMUN seems to be the cause of them)
+	  [Skotlex]
 	* Increased Run's walk speed bonus to 25->50% [Skotlex]
 	* Modified emergency_call setting to allow for more specific configuration
 	  (woe/non-woe, gvg-grounds/non-gvg-grounds, disable from nowarpto maps), see

+ 1 - 1
db/skill_require_db.txt

@@ -172,7 +172,7 @@
 236,0,0,25,0,0,0,99,0,0,none,0,7139,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//AM_CP_ARMOR#ケミカルア?マ?チャ?ジ#
 237,0,0,25,0,0,0,99,0,0,none,0,7139,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//AM_CP_HELM#ケミカルヘルムチャ?ジ#
 
-243,0,0,10,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//AM_CALLHOMUNCULUS
+243,0,0,10,0,0,0,99,0,0,none,0,7142,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//AM_CALLHOMUNCULUS
 244,0,0,50,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//AM_REST
 247,0,0,74:68:62:56:50,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//AM_RESURRECTHOMUN
 

+ 0 - 1
src/map/battle.c

@@ -1143,7 +1143,6 @@ static struct Damage battle_calc_weapon_attack(
 			case PA_SACRIFICE:
 				wd.damage = sstatus->max_hp* 9/100;
 				status_zap(src, wd.damage, 0);//Damage to self is always 9%
-				clif_damage(src,src, gettick(), 0, 0, wd.damage, 0 , 0, 0);
 				wd.damage2 = 0;
 
 				if (sc && sc->data[SC_SACRIFICE].timer != -1)

+ 1 - 2
src/map/map.c

@@ -1670,8 +1670,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, 2) ;
+		if (sd->hd) unit_free(&sd->hd->bl);
 		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]

+ 77 - 80
src/map/mercenary.c

@@ -113,44 +113,67 @@ 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->battle_status.hp = hd->master->homunculus.hp = 0 ;
-	clif_hominfo(hd->master,hd,0); // Send dead flag
+	struct map_session_data *sd = hd->master;
+	if (!sd)
+	{
+		clif_emotion(&hd->bl, 16) ;	//wah
+		return 7;
+	}
+
+	sd->homunculus.hp = 0 ;
+	clif_hominfo(sd,hd,0); // Send dead flag
+
 	if(!merc_hom_decrease_intimacy(hd, 100)) { // Intimacy was < 100
-		merc_stop_walking(hd, 1);
-		merc_stop_attack(hd);
-		clif_emotion(&hd->master->bl, 23) ;	//omg
-		merc_hom_delete(hd,1) ;
-		return 1 ;
+		clif_emotion(&sd->bl, 23) ;	//omg
+		return 7; //Delete from memory.
 	}
+
 	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);
+	clif_emotion(&sd->bl, 28) ;	//sob
+	return 3; //Remove from map.
+}
+
+//Vaporize a character's homun. If flag, HP needs to be 80% or above.
+int merc_hom_vaporize(struct map_session_data *sd, int flag)
+{
+	struct homun_data *hd;
 
-	return 1; // Removing is handled by merc_hom_delete
+	nullpo_retr(0, sd);
+
+	hd = sd->hd;
+	if (!hd || sd->homunculus.vaporize)
+		return 0;
+	
+	if (flag && hd->battle_status.hp < (hd->battle_status.max_hp*80/100))
+		return 0;
+
+	sd->homunculus.vaporize = 1;
+	clif_hominfo(sd, sd->hd, 0);
+	merc_save(hd);
+	return unit_remove_map(&hd->bl, 0);
 }
 
-int merc_hom_delete(struct homun_data *hd, int flag)
+//delete a homunculus, completely "killing it". 
+//Emote is the emotion the master should use, send negative to disable.
+int merc_hom_delete(struct homun_data *hd, int emote)
 {
+	struct map_session_data *sd;
 	nullpo_retr(0, hd);
+	sd = hd->master;
 
-	if ((flag & 2) && hd->bl.prev == NULL)
-	{
-		// Homunc was already removed from map, so just free the bl
+	if (!sd)
 		return unit_free(&hd->bl);
-	}
 
-	// Delete homunculus
-	if ( flag&1 ) {	//sabbath
-		intif_homunculus_requestdelete(hd->master->homunculus.hom_id) ;
-		clif_emotion(&hd->bl, 28) ;	//sob
-		hd->master->status.hom_id = 0;
-		hd->master->homunculus.hom_id = 0;
-		chrif_save(hd->master,0);
-	} else
-		merc_save(hd);
+	if (emote >= 0)
+		clif_emotion(&sd->bl, emote);
 
-	return unit_remove_map(&hd->bl, 0);
+	//This makes it be deleted right away.
+	sd->homunculus.intimacy = 0;
+	// Send homunculus_dead to client
+	sd->homunculus.hp = 0;
+	clif_hominfo(sd, hd, 0);
+	return unit_free(&hd->bl);
 }
 
 int merc_hom_calc_skilltree(struct map_session_data *sd)
@@ -314,7 +337,7 @@ int merc_hom_evolution(struct homun_data *hd)
 		hd->master->homunculus.vaporize = 1;
 		merc_stop_walking(hd, 1);
 		merc_stop_attack(hd);
-		merc_hom_delete(hd, 0) ;
+		merc_hom_delete(hd, -1) ;
 		merc_call_homunculus(hd->master);
 		clif_emotion(&hd->master->bl, 21) ;	//no1
 		clif_misceffect2(&hd->bl,568);
@@ -442,10 +465,10 @@ static int merc_natural_heal_sub(struct homun_data *hd,int tick) {
 //	tick = va_arg(ap,int);
 
 // -- moonsoul (if conditions below altered to disallow natural healing if under berserk status)
-	if (  hd && ( status_isdead(&hd->bl) ||
+	if (  status_isdead(&hd->bl) ||
 		( ( hd->sc.count ) &&
 			( (hd->sc.data[SC_POISON].timer != -1 ) || ( hd->sc.data[SC_BLEEDING].timer != -1 ) )
-		) )
+		)
 	) { //Cannot heal neither natural or special.
 		hd->hp_sub = hd->inchealhptick = 0;
 		hd->sp_sub = hd->inchealsptick = 0;
@@ -578,7 +601,7 @@ int merc_menu(struct map_session_data *sd,int menunum)
 			merc_hom_food(sd, sd->hd);
 			break;
 		case 2:
-			merc_hom_delete(sd->hd, 1);
+			merc_hom_delete(sd->hd, -1);
 			break;
 		default:
 			ShowError("merc_menu : unknown menu choice : %d\n", menunum) ;
@@ -629,15 +652,9 @@ int merc_hom_food(struct map_session_data *sd, struct homun_data *hd)
 	clif_hom_food(sd,hd->homunculusDB->foodID,1);
        	
 	// Too much food :/
-	if(sd->homunculus.intimacy == 0) {  
-		merc_stop_walking(hd, 1);
-		merc_stop_attack(hd);
-		// Send homunculus_dead to client
-		sd->homunculus.hp = 0;
-		clif_hominfo(sd, hd, 0);
-		merc_hom_delete(hd,1);
-		clif_emotion(&sd->bl, 23);     //omg  
-  	}  
+	if(sd->homunculus.intimacy == 0)
+		return merc_hom_delete(sd->hd, 23); //omg  
+
 	return 0;
 }
 
@@ -674,18 +691,9 @@ static int merc_hom_hungry(int tid,unsigned int tick,int id,int data)
 	if(sd->homunculus.hunger < 0) {
 		sd->homunculus.hunger = 0;
 		// Delete the homunculus if intimacy <= 100
-		if ( !merc_hom_decrease_intimacy(hd, 100) ) {
-			merc_stop_walking(hd, 1);
-			merc_stop_attack(hd);
-			// Send homunculus_dead to client
-			sd->homunculus.hp = 0;
-			clif_hominfo(sd, hd, 0);
-			merc_hom_delete(hd,1);
-			clif_emotion(&sd->bl, 23) ;	//omg
-			return 0 ;
-		} else {
-			clif_send_homdata(sd,SP_INTIMATE,sd->homunculus.intimacy / 100);
-		}
+		if ( !merc_hom_decrease_intimacy(hd, 100) )
+			return merc_hom_delete(sd->hd, 23); //omg  
+		clif_send_homdata(sd,SP_INTIMATE,sd->homunculus.intimacy / 100);
 	}
 
 	clif_send_homdata(sd,SP_HUNGRY,sd->homunculus.hunger);
@@ -812,45 +820,34 @@ int merc_hom_data_init(struct map_session_data *sd)
 	return 0;
 }
 
-// FIX call_homunculus [albator]
 int merc_call_homunculus(struct map_session_data *sd)
 {
-	int class_ = 0 ;
-	nullpo_retr(0, sd);
+	struct homun_data *hd;
 
-	if (!sd->status.hom_id)
-	{
-		class_ = 6000 + rand(1, 8) ;
-		return merc_create_homunculus(sd, class_) ;
-	}
+	if (!sd->status.hom_id) //Create a new homun.
+		return merc_create_homunculus(sd, 6000 + rand(1, 8)) ;
 
-	// If homunc not yet loaded, load it, else just activate it
+	//Recall homunculus to you.
+	if (sd->homunculus.vaporize)
+		return 0; //Can't use this when homun was vaporized.
+
+	// If homunc not yet loaded, load 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;
-	}
-	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);
+	hd = sd->hd;
+	if (hd->bl.prev == NULL)
+	{	//Spawn him
+		map_addblock(&hd->bl);
+		clif_spawn(&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_hominfo(sd,hd,1);
+		clif_hominfo(sd,hd,0); // send this x2. dunno why, but kRO does that [blackhole89]
 		clif_homskillinfoblock(sd);
-	}
-	// save
-	merc_save(sd->hd);
+		merc_save(hd); 
+	} else
+		//Warp him to master.
+		unit_warp(&hd->bl,sd->bl.m,sd->bl.x,sd->bl.y,0);
 	return 1;
 }
 

+ 1 - 1
src/map/mercenary.h

@@ -62,7 +62,7 @@ int merc_hom_gainexp(struct homun_data *hd,int exp) ;
 int merc_hom_levelup(struct homun_data *hd) ;
 int merc_hom_evolution(struct homun_data *hd) ;
 void merc_hom_heal(struct homun_data *hd,int hp,int sp);
-int merc_hom_delete(struct homun_data *hd, int flag) ;
+int merc_hom_vaporize(struct map_session_data *sd, int flag);
 int merc_hom_revive(struct map_session_data *sd, int per);
 void merc_save(struct homun_data *hd);
 int merc_call_homunculus(struct map_session_data *sd);

+ 3 - 9
src/map/pc.c

@@ -671,7 +671,7 @@ int pc_authok(struct map_session_data *sd, int login_id2, time_t connect_until_t
 
 	// Homunculus [albator]
 	if (sd->status.hom_id > 0)	
-			intif_homunculus_requestload(sd->status.account_id, sd->status.hom_id);
+		intif_homunculus_requestload(sd->status.account_id, sd->status.hom_id);
 
 	// パ?ティ、ギルドデ?タの要求
 	if (sd->status.party_id > 0 && party_search(sd->status.party_id) == NULL)
@@ -4783,14 +4783,8 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
 			pet_unlocktarget(sd->pd);
 	}
 
-	if(sd->status.hom_id > 0 && sd->hd)	//orn
-	{
-		sd->homunculus.vaporize = 1;
-		clif_hominfo(sd,sd->hd,0);
-		merc_stop_walking(sd->hd, 1) ;
-		merc_stop_attack(sd->hd) ;
-		merc_hom_delete(sd->hd,0);
-	}
+	if(sd->status.hom_id > 0)	//orn
+		merc_hom_vaporize(sd, 0);
 
 	// Leave duel if you die [LuzZza]
 	if(battle_config.duel_autoleave_when_die) {

+ 15 - 27
src/map/skill.c

@@ -5487,37 +5487,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 		break;
 	
 	case AM_CALLHOMUN:	//[orn]
-		if (sd)
-		{
-			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) {
-						clif_skill_fail(sd,skillid,0,0);
-						break ;
-					}
-					pc_delitem(sd,i,1,0);
-				}
-				if (merc_call_homunculus(sd))
-					break;
-			}
+		if (sd && !merc_call_homunculus(sd))
 			clif_skill_fail(sd,skillid,0,0);
-		}
 		break;
 
 	case AM_REST:	//[orn]
-	{
-		if (sd)
-		{
-			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) ;
-			} else
-				clif_skill_fail(sd,skillid,0,0);
-		}
+		if (sd && !merc_hom_vaporize(sd,1))
+			clif_skill_fail(sd,skillid,0,0);
 		break;
-	}
+
 	case AM_RESURRECTHOMUN:	//[orn]
 	{
 		if (sd)
@@ -5821,8 +5799,10 @@ int skill_castend_id (int tid, unsigned int tick, int id, int data)
 			else if(dy < 0) dy--;
 			
 			if (unit_movepos(src, src->x+dx, src->y+dy, 1, 1))
+			{	//Display movement + animation.
 				clif_slide(src,src->x,src->y);
-
+				clif_skill_damage(src,target,tick,sd->battle_status.amotion,0,0,1,ud->skillid, ud->skilllv, 5);
+			}
 			clif_skill_fail(sd,ud->skillid,0,0);
 		}
 	}
@@ -8320,6 +8300,14 @@ int skill_check_condition (struct map_session_data *sd, int skill, int lv, int t
 		}
 		zeny = 0; //Zeny is reduced on skill_attack.
 		break;
+	case AM_CALLHOMUN: //Can't summon if a hom is already out (vaporized also counts).
+		if (sd->status.hom_id || sd->homunculus.vaporize) {
+			clif_skill_fail(sd,skill,0,0);
+			return 0;
+		}
+		if (sd->status.hom_id) //Don't delete items when hom is already out.
+			delitem_flag = 0;
+		break;
 	}
 
 	if(!(type&2)){

+ 31 - 30
src/map/unit.c

@@ -1497,7 +1497,6 @@ int unit_remove_map(struct block_list *bl, int clrtype) {
 		unit_skillcastcancel(bl,0);
 // Do not reset can-act delay. [Skotlex]
 	ud->attackabletime = ud->canmove_tick /*= ud->canact_tick*/ = gettick();
-	clif_clearchar_area(bl,clrtype);
 	
 	if(sc && sc->count ) { //map-change/warp dispells.
 		if(sc->data[SC_BLADESTOP].timer!=-1)
@@ -1588,18 +1587,8 @@ int unit_remove_map(struct block_list *bl, int clrtype) {
 		struct pet_data *pd = (struct pet_data*)bl;
 		struct map_session_data *sd = pd->msd;
 		
-		if(!sd) {
-			map_delblock(bl);
-			unit_free(bl);
-			map_freeblock_unlock();
-			return 0;
-		}
-		if (sd->pet.intimate <= 0)
-		{	//Remove pet.
-			intif_delete_petdata(sd->status.pet_id);
-			sd->status.pet_id = 0;
-			sd->pd = NULL;
-			pd->msd = NULL;
+		if(!sd || sd->pet.intimate <= 0) {
+			clif_clearchar_area(bl,clrtype);
 			map_delblock(bl);
 			unit_free(bl);
 			map_freeblock_unlock();
@@ -1608,28 +1597,17 @@ int unit_remove_map(struct block_list *bl, int clrtype) {
 	} 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) {
+		if(!sd || !sd->homunculus.intimacy)
+	  	{	//He's going to be deleted.
+			clif_emotion(bl, 28) ;	//sob
+			clif_clearchar_area(bl,clrtype);
 			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;
-		}
 	}
+	clif_clearchar_area(bl,clrtype);
 	map_delblock(bl);
 	map_freeblock_unlock();
 	return 1;
@@ -1761,9 +1739,14 @@ int unit_free(struct block_list *bl) {
 			pd->loot = NULL;
 		}
 		if (sd) {
+			sd->pd = NULL;
 			if(sd->pet.intimate > 0)
 				intif_save_petdata(sd->status.account_id,&sd->pet);
-			sd->pd = NULL;
+			else
+			{	//Remove pet.
+				intif_delete_petdata(sd->status.pet_id);
+				sd->status.pet_id = 0;
+			}
 		}
 	} else if(bl->type == BL_MOB) {
 		struct mob_data *md = (struct mob_data*)bl;
@@ -1794,6 +1777,24 @@ int unit_free(struct block_list *bl) {
 		}
 		if(mob_is_clone(md->class_))
 			mob_clone_delete(md->class_);
+	} else if(bl->type == BL_HOM) {
+		struct homun_data *hd = (TBL_HOM*)bl;
+		struct map_session_data *sd = hd->master;
+		// Desactive timers
+		merc_hom_hungry_timer_delete(hd);
+		merc_natural_heal_timer_delete(hd);
+		if(sd) {
+			sd->hd = NULL;
+			hd->master = NULL;
+			if (sd->homunculus.intimacy > 0)
+				merc_save(hd); 
+			else
+			{
+				intif_homunculus_requestdelete(sd->homunculus.hom_id) ;
+				sd->status.hom_id = 0;
+				sd->homunculus.hom_id = 0;
+			}
+		}
 	}
 
 	skill_clear_unitgroup(bl);