Przeglądaj źródła

- Made HLIF_HEAL a self skill that auto-selects target to caster's master.
- Implemented SC_BLOODLUST and SC_CHANGE, cleaned up HLIF_CHANGE
- Applied a correction to HVAN_EXPLOSION
- Fixed Homun ASPD calculation being able to underflow and give you min speed.
- Added monster_ai&128 to make aggressive mobs ignore that behaviour of always picking Homun targets above player targets regardless of who is closer.
- Fixed homun info packet being unable to display HP/SP correctly once the values are above 32k.


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

skotlex 19 lat temu
rodzic
commit
91b9fed6e3

+ 11 - 0
Changelog-Trunk.txt

@@ -4,6 +4,17 @@ 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/18
+	* Made HLIF_HEAL a self skill that auto-selects target to caster's master.
+	  [Skotlex]
+	* Implemented SC_BLOODLUST and SC_CHANGE, cleaned up HLIF_CHANGE [Skotlex]
+	* Applied a correction to HVAN_EXPLOSION [Skotlex]
+	* Fixed Homun ASPD calculation being able to underflow and give you min
+	  speed. [Skotlex]
+	* Added monster_ai&128 to make aggressive mobs ignore that behaviour of
+	  always picking Homun targets above player targets regardless of who is
+	  closer. [Skotlex]
+	* Fixed homun info packet being unable to display HP/SP correctly once the
+	  values are above 32k. [Skotlex]
 	* Applied Mpeg's work on ninja [Toms]
 	* Fixed @homlvup [Toms]
 	* Added guild_aura (skill.conf) setting so you can specify when it works

+ 3 - 0
conf-tmpl/Changelog.txt

@@ -1,6 +1,9 @@
 Date	Added
 
 2006/08/18
+	* Added monster_ai&128 to make aggressive mobs ignore that behaviour of
+	  always picking Homun targets above player targets regardless of who is
+	  closer. [Skotlex]
 	* Added guild_aura (skill.conf) setting so you can specify when it works
 	  and if it works on the guild-master itself. Defaults to working all the
 	  time on everyone except GM. [Skotlex]

+ 4 - 0
conf-tmpl/battle/monster.conf

@@ -54,6 +54,10 @@ monster_max_aspd: 199
 //    players on them, instead of only for mobs who are in the vecinity of players.
 //64: When set, when the mob's target changes map, the mob will walk towards
 //    any npc-warps in it's sight of view (use with mob_npc_warp below)
+//128: When set, aggressive mobs will give the same priority to Homuns and
+//    players and will go after the closest target instead of always picking
+//    the homunculus
+//    
 monster_ai: 0
 
 // Should mobs be able to be warped (add as needed)?

+ 2 - 0
db/Changelog.txt

@@ -20,6 +20,8 @@
 
 =========================
 08/18
+	* Made HLIF_HEAL a self skill that auto-selects target to caster's master.
+	  [Skotlex]
 	* Fixed Kouenka not having an aftercast delay on levels greater 1 [Playtester]
 08/17
 	* Gospel can't stack anymore [Playtester]

+ 1 - 1
db/skill_db.txt

@@ -591,7 +591,7 @@
 1019,9,6,1,4,1,0,1,1,yes,0,1,0,magic,0	//SA_ELEMENTWIND#Elemental Change Wind#
 
 //homunculus
-8001,9,6,16,0,1,0,5,1,no,0,0,0,magic,0	//HLIF_HEAL#Healing hand#
+8001,9,6,4,0,1,0,5,1,no,0,0,0,magic,0	//HLIF_HEAL#Healing hand#
 8002,0,6,4,0,3,-1,5,1,no,0,0,0,none,0	//HLIF_AVOID
 8003,0,0,0,0,0,1,5,0,no,0,0,0,none,0	//HLIF_BRAIN
 8004,0,6,4,0,1,0,3,0,no,0,0,0,none,0	//HLIF_CHANGE

+ 11 - 4
src/map/battle.c

@@ -404,6 +404,13 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
 		}
 
 		if (!damage) return 0;
+
+		//Probably not the most correct place, but it'll do here
+		//(since battle_drain is strictly for players currently)
+		if (sc->data[SC_BLOODLUST].timer != -1 && flag&BF_WEAPON && damage > 0 &&
+			rand()%100 < sc->data[SC_BLOODLUST].val3)
+			status_heal(src, damage*sc->data[SC_BLOODLUST].val4/100, 0, 3);
+
 	}
 	//SC effects from caster side. Currently none.
 /*	
@@ -1030,7 +1037,6 @@ static struct Damage battle_calc_weapon_attack(
 				case GS_GROUNDDRIFT:
 				case NJ_TATAMIGAESHI:
 				case NJ_ISSEN:
-				case HVAN_EXPLOSION:	//[orn]
 					flag.hit = 1;
 					break;
 				case CR_SHIELDBOOMERANG:
@@ -1195,6 +1201,7 @@ static struct Damage battle_calc_weapon_attack(
 				i = (flag.cri?1:0)|
 					(flag.arrow?2:0)|
 					(skill_num == HW_MAGICCRASHER?4:0)|
+					(!skill_num && sc && sc->data[SC_CHANGE].timer!=-1?4:0)|
 					(skill_num == MO_EXTREMITYFIST?8:0)|
 					(sc && sc->data[SC_WEAPONPERFECTION].timer!=-1?8:0);
 				if (flag.arrow && sd)
@@ -2504,7 +2511,7 @@ struct Damage  battle_calc_misc_attack(
 	case CR_ACIDDEMONSTRATION:
 		md.flag = (md.flag&~BF_RANGEMASK)|BF_LONG;
 		break;
-	case HVAN_EXPLOSION:	//[orn]
+	case HVAN_EXPLOSION:
 	case NPC_SELFDESTRUCTION:
 	case NPC_SMOKING:
 		flag.elefix = flag.cardfix = 0;
@@ -2726,8 +2733,8 @@ int battle_calc_return_damage(struct block_list *bl, int *damage, int flag) {
 	struct map_session_data *sd=NULL;
 	struct status_change *sc;
 	int rdamage = 0;
-	
-	if (bl->type == BL_PC) sd = (struct map_session_data*)bl;
+
+	BL_CAST(BL_PC, bl, sd);
 	sc = status_get_sc(bl);
 
 	if(flag&BF_WEAPON) {

+ 16 - 6
src/map/clif.c

@@ -1466,14 +1466,14 @@ int clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag)
 	memset(buf,0,packet_len_table[0x22e]);
 	WBUFW(buf,0)=0x22e;
 	memcpy(WBUFP(buf,2),sd->homunculus.name,NAME_LENGTH);
-	WBUFB(buf,26)=sd->homunculus.rename_flag * 2;
+//	WBUFB(buf,26)=sd->homunculus.rename_flag * 2;
 	// Bit field, bit 0 : rename_flag (1 = already renamed), bit 1 : homunc vaporized (1 = true), bit 2 : homunc dead (1 = true)
 	WBUFB(buf,26)=sd->homunculus.rename_flag | (sd->homunculus.vaporize << 1) | (sd->homunculus.hp?0:4);
 	WBUFW(buf,27)=sd->homunculus.level;
 	WBUFW(buf,29)=sd->homunculus.hunger;
 	WBUFW(buf,31)=(unsigned short) (sd->homunculus.intimacy / 100) ;
 	WBUFW(buf,33)=0; // equip id
-	WBUFW(buf,35)=status->rhw.atk2;
+	WBUFW(buf,35)=status->rhw.atk2+status->batk;
 	WBUFW(buf,37)=status->matk_max;
 	WBUFW(buf,39)=status->hit;
 	WBUFW(buf,41)=status->cri/10;	//crit is a +1 decimal value!
@@ -1481,10 +1481,20 @@ int clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag)
 	WBUFW(buf,45)=status->mdef;
 	WBUFW(buf,47)=status->flee;
 	WBUFW(buf,49)=(flag)?0:status->amotion;
-	WBUFW(buf,51)=status->hp;
-	WBUFW(buf,53)=status->max_hp;
-	WBUFW(buf,55)=status->sp;
-	WBUFW(buf,57)=status->max_sp;
+	if (status->max_hp > SHRT_MAX) {
+		WBUFW(buf,51) = status->hp/(status->max_hp/100);
+		WBUFW(buf,53) = 100;
+	} else {
+		WBUFW(buf,51)=status->hp;
+		WBUFW(buf,53)=status->max_hp;
+	}
+	if (status->max_sp > SHRT_MAX) {
+		WBUFW(buf,55) = status->sp/(status->max_sp/100);
+		WBUFW(buf,57) = 100;
+	} else {
+		WBUFW(buf,55)=status->sp;
+		WBUFW(buf,57)=status->max_sp;
+	}
 	WBUFL(buf,59)=sd->homunculus.exp;
 	WBUFL(buf,63)=hd->exp_next;
 	WBUFW(buf,67)=sd->homunculus.skillpts;

+ 1 - 1
src/map/mob.c

@@ -774,7 +774,7 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap)
 			!(status_get_mode(&md->bl)&MD_BOSS))
 			return 0; //Gangster paradise protection.
 	default:
-		if ((*target) && (*target)->type == BL_HOM && bl->type != BL_HOM)
+		if (!(battle_config.mob_ai&128) && (*target) && (*target)->type == BL_HOM && bl->type != BL_HOM)
 			return 0; //For some reason Homun targets are never overriden.
 
 		if((dist=distance_bl(&md->bl, bl)) < md->db->range2 &&

+ 8 - 10
src/map/skill.c

@@ -3091,12 +3091,12 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
 	case CR_ACIDDEMONSTRATION:
 	case TF_THROWSTONE:
 	case NPC_SMOKING:
-	case HVAN_EXPLOSION:	//[orn]
 	case GS_FLING:
 	case NJ_ZENYNAGE:
 		skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag);
 		break;
 
+	case HVAN_EXPLOSION:
 	case NPC_SELFDESTRUCTION:
 		if (src != bl)
 			skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag);
@@ -4063,7 +4063,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 	case NPC_SELFDESTRUCTION:
 		//Self Destruction hits everyone in range (allies+enemies)
 		//Except for Summoned Marine spheres on non-versus maps, where it's just enemy.
-		i = (md && md->special_state.ai == 2 && !map_flag_vs(src->m))?
+		i = ((hd || (md && md->special_state.ai == 2)) && !map_flag_vs(src->m))?
 			BCT_ENEMY:BCT_ALL;
 		clif_skill_nodamage(src, src, skillid, -1, 1);
 		map_foreachinrange(skill_area_sub, bl,
@@ -5554,14 +5554,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 				clif_skill_fail(hd->master,skillid,0,0);
 		break;
 	case HLIF_CHANGE:	//[orn]
-		if ( hd ) {
-			clif_skill_nodamage(src,bl,skillid,skilllv,
-				sc_start(&hd->bl,type,100,skilllv,skill_get_time(skillid,skilllv))) ;
-			status_heal(&hd->bl, hd->master->homunculus.max_hp, 0, 0);
-			skill_blockmerc_start(hd, skillid, skill_get_time2(skillid,skilllv)) ;
-		}
-		else
-				clif_skill_fail(hd->master,skillid,0,0);
+		clif_skill_nodamage(src,bl,skillid,skilllv,
+			sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)));
+		if (sd)
+			skill_blockpc_start(sd, skillid, skill_get_time2(skillid,skilllv));
+		if (hd)
+			skill_blockmerc_start(hd, skillid, skill_get_time2(skillid,skilllv));
 		break;
 
 	default:

+ 31 - 8
src/map/status.c

@@ -376,7 +376,7 @@ void initChangeTables(void) {
 	add_sc(SA_ELEMENTWIND, SC_ELEMENTALCHANGE);
 
 	set_sc(HLIF_AVOID, SC_AVOID, SI_BLANK, SCB_SPEED);
-	set_sc(HLIF_CHANGE, SC_CHANGE, SI_BLANK, SCB_INT);
+	set_sc(HLIF_CHANGE, SC_CHANGE, SI_BLANK, SCB_MAXHP|SCB_MAXSP);
 	set_sc(HFLI_FLEET, SC_FLEET, SI_BLANK, SCB_ASPD|SCB_BATK|SCB_WATK);
 	set_sc(HFLI_SPEED, SC_SPEED, SI_BLANK, SCB_FLEE);	//[orn]
 	set_sc(HAMI_DEFENCE, SC_DEFENCE, SI_BLANK, SCB_DEF);	//[orn]
@@ -2255,6 +2255,14 @@ int status_calc_homunculus(struct homun_data *hd, int first)
 	status->rhw.atk = status->dex;
 	status->rhw.atk2 = status->str + hom->level;
 
+	status->aspd_rate = 1000;
+
+	skill = (1000 -4*status->agi -status->dex)
+			*hd->homunculusDB->baseASPD/1000;
+	
+	status->amotion = cap_value(skill,battle_config.max_aspd,2000);
+	status->adelay = 2*status->amotion;
+
 	status_calc_misc(status, BL_HOM, hom->level);
 	status_calc_bl(&hd->bl, SCB_ALL); //Status related changes.
 
@@ -2725,14 +2733,15 @@ void status_calc_bl_sub_hom(struct homun_data *hd, unsigned long flag)	//[orn]
 
 	if(flag&(SCB_ASPD|SCB_AGI|SCB_DEX)) {
 		flag|=SCB_ASPD;
-		status->amotion = hd->homunculusDB->baseASPD - ((status->agi*4+status->dex)* hd->homunculusDB->baseASPD / 1000);
 
+		skill = (1000 -4*status->agi -status->dex)
+			*hd->homunculusDB->baseASPD/1000;
+		
 		status->aspd_rate = status_calc_aspd_rate(&hd->bl, &hd->sc , b_status->aspd_rate);
 		if(status->aspd_rate != 1000)
-			status->amotion = status->amotion *status->aspd_rate/1000;
-
-		status->amotion = cap_value(status->amotion,battle_config.max_aspd,2000);
+			skill = skill*status->aspd_rate/1000;
 
+		status->amotion = cap_value(skill,battle_config.max_aspd,2000);
 		status->adelay = 2*status->amotion;
 	}
 	
@@ -3109,8 +3118,6 @@ static unsigned short status_calc_int(struct block_list *bl, struct status_chang
 		int_ -= int_ * sc->data[SC_STRIPHELM].val2/100;
 	if(sc->data[SC_NEN].timer!=-1)
 		int_ += sc->data[SC_NEN].val1;
-	if(sc->data[SC_CHANGE].timer!=-1)
-		int_ += 60;
 	if(sc->data[SC_MARIONETTE].timer!=-1)
 		int_ -= (sc->data[SC_MARIONETTE].val4>>16)&0xFF;
 	if(sc->data[SC_MARIONETTE2].timer!=-1)
@@ -3686,6 +3693,8 @@ static unsigned int status_calc_maxhp(struct block_list *bl, struct status_chang
 	if(!sc || !sc->count)
 		return cap_value(maxhp,1,UINT_MAX);
 
+	if(sc->data[SC_CHANGE].timer!=-1)
+		maxhp = sc->data[SC_CHANGE].val3;
 	if(sc->data[SC_INCMHPRATE].timer!=-1)
 		maxhp += maxhp * sc->data[SC_INCMHPRATE].val1/100;
 	if(sc->data[SC_APPLEIDUN].timer!=-1)
@@ -3703,6 +3712,8 @@ static unsigned int status_calc_maxsp(struct block_list *bl, struct status_chang
 	if(!sc || !sc->count)
 		return cap_value(maxsp,1,UINT_MAX);
 
+	if(sc->data[SC_CHANGE].timer!=-1)
+		maxsp = sc->data[SC_CHANGE].val2;
 	if(sc->data[SC_INCMSPRATE].timer!=-1)
 		maxsp += maxsp * sc->data[SC_INCMSPRATE].val1/100;
 	if(sc->data[SC_SERVICE4U].timer!=-1)
@@ -5459,6 +5470,8 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val
 			break;
 		case SC_BLOODLUST:
 			val2 = 20+10*val1; //Atk rate change.
+			val3 = 3*val1; //Leech chance
+			val4 = 20; //Leech percent
 			break;
 		case SC_FLEET:
 			val2 = 30*val1; //Aspd change
@@ -5494,6 +5507,14 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val
 		case SC_BUNSINJYUTSU:
 			val2=(val1+1)/2; // number of hits blocked
 			break;
+		case SC_CHANGE:
+			{
+				struct status_data *status = status_get_base_status(bl);
+				if (!status) return 0;
+				val2= status->max_hp; //Base Max HP
+				val3= status->max_sp; //Base Max SP
+			}
+			break;
 		default:
 			if (calc_flag == SCB_NONE && StatusSkillChangeTable[type]==0)
 			{	//Status change with no calc, and no skill associated...? unknown?
@@ -5717,7 +5738,9 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val
 		sc->data[type].val2 = 5*status->max_hp/100;
 		status_heal(bl, status->max_hp, 0, 1); //Do not use percent_heal as this healing must override BERSERK's block.
 		status_set_sp(bl, 0, 0); //Damage all SP
-	}
+	} else if (type==SC_CHANGE) //Heal all HP
+		status_percent_heal(bl, 100, 0);
+
 
 	if (type==SC_RUN) {
 		struct unit_data *ud = unit_bl2ud(bl);

+ 1 - 0
src/map/unit.c

@@ -784,6 +784,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, int skill_num, int
 	if (src->type==BL_HOM)
 	switch(skill_num)
 	{ //Homun-auto-target skills.
+		case HLIF_HEAL:
 		case HLIF_AVOID:
 		case HAMI_DEFENCE:
 		case HAMI_CASTLE: