Browse Source

- Mercenary Bonus Status (currently activated each mob kill for testing).

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@13182 54d463be-8e91-2dee-dedb-b68131a5f0ec
zephyrus 16 years ago
parent
commit
3d3946138a
5 changed files with 137 additions and 27 deletions
  1. 9 0
      src/map/clif.c
  2. 12 1
      src/map/mercenary.c
  3. 4 2
      src/map/mob.c
  4. 96 24
      src/map/status.c
  5. 16 0
      src/map/status.h

+ 9 - 0
src/map/clif.c

@@ -12398,6 +12398,15 @@ void clif_mercenary_updatestatus(struct map_session_data *sd, int type)
 		case SP_MAXSP:
 			WFIFOL(fd,4) = md->battle_status.max_sp;
 			break;
+		case SP_MERCFLEE:
+			WFIFOL(fd,4) = md->battle_status.flee;
+			break;
+		case SP_ATK1:
+			WFIFOL(fd,4) = md->battle_status.rhw.atk + md->battle_status.rhw.atk2;
+			break;
+		case SP_HIT:
+			WFIFOL(fd,4) = md->battle_status.hit;
+			break;
 		case SP_MERCKILLS:
 			WFIFOL(fd,4) = md->mercenary.kill_count;
 			break;

+ 12 - 1
src/map/mercenary.c

@@ -87,7 +87,7 @@ int merc_create(struct map_session_data *sd, int class_, unsigned int lifetime)
 int mercenary_get_lifetime(struct mercenary_data *md)
 {
 	const struct TimerData * td;
-	if( md == NULL )
+	if( md == NULL || md->contract_timer == INVALID_TIMER )
 		return 0;
 
 	td = get_timer(md->contract_timer);
@@ -331,6 +331,15 @@ int mercenary_dead(struct mercenary_data *md, struct block_list *src)
 	return 0;
 }
 
+int mercenary_killbonus(struct mercenary_data *md)
+{
+	const enum sc_type scs[] = { SC_MERC_FLEEUP, SC_MERC_ATKUP, SC_MERC_HPUP, SC_MERC_SPUP, SC_MERC_HITUP };
+	int index = rand() % ARRAYLENGTH(scs);
+
+	status_change_start(&md->bl, scs[index], 10000, rand()%5, 0, 0, 0, 600000, 0);
+	return 0;
+}
+
 int mercenary_kills(struct mercenary_data *md)
 {
 	md->mercenary.kill_count++;
@@ -342,6 +351,8 @@ int mercenary_kills(struct mercenary_data *md)
 	if( md->master )
 		clif_mercenary_updatestatus(md->master, SP_MERCKILLS);
 
+	mercenary_killbonus(md);
+
 	return 0;
 }
 

+ 4 - 2
src/map/mob.c

@@ -1942,8 +1942,6 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 			}
 			pc_setglobalreg(sd,"TK_MISSION_COUNT", sd->mission_count);
 		}
-		if( sd->md && (md->level > sd->status.base_level / 2) )
-			mercenary_kills(sd->md);
 	}
 
 	// filter out entries not eligible for exp distribution
@@ -2324,8 +2322,12 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 			{
 				case BL_PET: sd = ((TBL_PET*)src)->msd; break;
 				case BL_HOM: sd = ((TBL_HOM*)src)->master; break;
+				case BL_MER: sd = ((TBL_MER*)src)->master; break;
 			}
 
+		if( sd && sd->md && src && src->type != BL_HOM )
+			mercenary_kills(sd->md);
+
 		if( md->npc_event[0] && !md->state.npc_killmonster )
 		{
 			if( sd && battle_config.mob_npc_event_type )

+ 96 - 24
src/map/status.c

@@ -457,6 +457,12 @@ void initChangeTables(void)
 	StatusIconChangeTable[SC_SPCOST_RATE] = SI_SPCOST_RATE;
 	StatusIconChangeTable[SC_COMMONSC_RESIST] = SI_COMMONSC_RESIST;
 	StatusIconChangeTable[SC_ARMOR_RESIST] = SI_ARMOR_RESIST;
+	// Mercenary Bonus Effects
+	StatusIconChangeTable[SC_MERC_FLEEUP] = SI_MERC_FLEEUP;
+	StatusIconChangeTable[SC_MERC_ATKUP] = SI_MERC_ATKUP;
+	StatusIconChangeTable[SC_MERC_HPUP] = SI_MERC_HPUP;
+	StatusIconChangeTable[SC_MERC_SPUP] = SI_MERC_SPUP;
+	StatusIconChangeTable[SC_MERC_HITUP] = SI_MERC_HITUP;
 
 	//Other SC which are not necessarily associated to skills.
 	StatusChangeFlagTable[SC_ASPDPOTION0] = SCB_ASPD;
@@ -503,8 +509,14 @@ void initChangeTables(void)
 	StatusChangeFlagTable[SC_ARMOR_RESIST] |= SCB_PC;
 	StatusChangeFlagTable[SC_SPCOST_RATE] |= SCB_PC;
 	StatusChangeFlagTable[SC_WALKSPEED] |= SCB_SPEED;
-
-	if (!battle_config.display_hallucination) //Disable Hallucination.
+	// Mercenary Bonus Effects
+	StatusChangeFlagTable[SC_MERC_FLEEUP] |= SCB_FLEE;
+	StatusChangeFlagTable[SC_MERC_ATKUP] |= SCB_WATK;
+	StatusChangeFlagTable[SC_MERC_HPUP] |= SCB_MAXHP;
+	StatusChangeFlagTable[SC_MERC_SPUP] |= SCB_MAXSP;
+	StatusChangeFlagTable[SC_MERC_HITUP] |= SCB_HIT;
+
+	if( !battle_config.display_hallucination ) //Disable Hallucination.
 		StatusIconChangeTable[SC_HALLUCINATION] = SI_BLANK;
 }
 
@@ -3443,6 +3455,8 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan
 		watk -= watk * 25/100;
 	if(sc->data[SC_STRIPWEAPON])
 		watk -= watk * sc->data[SC_STRIPWEAPON]->val2/100;
+	if(sc->data[SC_MERC_ATKUP])
+		watk += sc->data[SC_MERC_ATKUP]->val2;
 
 	return (unsigned short)cap_value(watk,0,USHRT_MAX);
 }
@@ -3509,7 +3523,9 @@ static signed short status_calc_hit(struct block_list *bl, struct status_change
 		hit -= 30;
 	if(sc->data[SC_INCREASING])
 		hit += 20; // RockmanEXE; changed based on updated [Reddozen]
-	
+	if(sc->data[SC_MERC_HITUP])
+		hit += sc->data[SC_MERC_HITUP]->val2;
+
 	return (short)cap_value(hit,1,SHRT_MAX);
 }
 
@@ -3548,7 +3564,9 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change
 	if(sc->data[SC_GATLINGFEVER])
 		flee -= sc->data[SC_GATLINGFEVER]->val4;
 	if(sc->data[SC_SPEED])
-		flee += 10 + sc->data[SC_SPEED]->val1 * 10 ;
+		flee += 10 + sc->data[SC_SPEED]->val1 * 10;
+	if(sc->data[SC_MERC_FLEEUP])
+		flee += sc->data[SC_MERC_FLEEUP]->val2;
 
 	return (short)cap_value(flee,1,SHRT_MAX);
 }
@@ -3946,6 +3964,8 @@ static unsigned int status_calc_maxhp(struct block_list *bl, struct status_chang
 		maxhp += maxhp * sc->data[SC_DELUGE]->val2/100;
 	if(sc->data[SC_BERSERK])
 		maxhp += maxhp * 2;
+	if(sc->data[SC_MERC_HPUP])
+		maxhp += maxhp * sc->data[SC_MERC_HPUP]->val2/100;
 
 	return cap_value(maxhp,1,UINT_MAX);
 }
@@ -3959,6 +3979,8 @@ static unsigned int status_calc_maxsp(struct block_list *bl, struct status_chang
 		maxsp += maxsp * sc->data[SC_INCMSPRATE]->val1/100;
 	if(sc->data[SC_SERVICE4U])
 		maxsp += maxsp * sc->data[SC_SERVICE4U]->val2/100;
+	if(sc->data[SC_MERC_SPUP])
+		maxsp += maxsp * sc->data[SC_MERC_SPUP]->val2/100;
 
 	return cap_value(maxsp,1,UINT_MAX);
 }
@@ -4835,6 +4857,14 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 		}
 		if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC
 	break;
+	case SC_MERC_FLEEUP:
+	case SC_MERC_ATKUP:
+	case SC_MERC_HPUP:
+	case SC_MERC_SPUP:
+	case SC_MERC_HITUP:
+		if( bl->type != BL_MER )
+			return 0; // Stats only for Mercenaries
+	break;
 	}
 
 	//Check for BOSS resistances
@@ -4958,21 +4988,28 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 		status_change_end(bl,SC_BLESSING,-1);
 		status_change_end(bl,SC_INCREASEAGI,-1);
 		break;
-		
 	}
 
 	//Check for overlapping fails
-	if((sce=sc->data[type]))
+	if( (sce = sc->data[type]) )
 	{
-		switch (type)
+		switch( type )
 		{
+			case SC_MERC_FLEEUP:
+			case SC_MERC_ATKUP:
+			case SC_MERC_HPUP:
+			case SC_MERC_SPUP:
+			case SC_MERC_HITUP:
+				if( sce->val1 > val1 )
+					val1 = sce->val1;
+				break;
 			case SC_ADRENALINE:
 			case SC_ADRENALINE2:
 			case SC_WEAPONPERFECTION:
 			case SC_OVERTHRUST:
 				if (sce->val2 > val2)
 					return 0;
-			break;
+				break;
 			case SC_HPREGEN:
 			case SC_SPREGEN:
 			case SC_BOSSMAPINFO:
@@ -5933,6 +5970,17 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 			//Place here SCs that have no SCB_* data, no skill associated, no ICON
 			//associated, and yet are not wrong/unknown. [Skotlex]
 			break;
+
+		case SC_MERC_FLEEUP:
+		case SC_MERC_ATKUP:
+		case SC_MERC_HITUP:
+			val2 = 15 * val1;
+			break;
+		case SC_MERC_HPUP:
+		case SC_MERC_SPUP:
+			val2 = 5 * val1;
+			break;
+
 		default:
 			if( calc_flag == SCB_NONE && StatusSkillChangeTable[type] == 0 && StatusIconChangeTable[type] == 0 )
 			{	//Status change with no calc, no icon, and no skill associated...? 
@@ -6139,9 +6187,9 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 		calc_flag&=~SCB_DYE;
 	}
 
-	if (vd && pcdb_checkid(vd->class_)) //Only for players sprites, client crashes if they receive this for a mob o.O [Skotlex]
+	if( vd && (pcdb_checkid(vd->class_) || bl->type == BL_MER ) ) //Only for players sprites, client crashes if they receive this for a mob o.O [Skotlex]
 		clif_status_change(bl,StatusIconChangeTable[type],1);
-	else if (sd) //Send packet to self otherwise (disguised player?)
+	else if( sd ) //Send packet to self otherwise (disguised player?)
 		clif_status_load(bl,StatusIconChangeTable[type],1);
 
 	//Don't trust the previous sce assignment, in case the SC ended somewhere between there and here.
@@ -6170,22 +6218,46 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 	if(sd && sd->pd)
 		pet_sc_check(sd, type); //Skotlex: Pet Status Effect Healing
 
-	if (type==SC_BERSERK) {
-		sce->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/SP
-		status_percent_heal(bl, 100, 100);
-
-	if (type==SC_RUN) {
-		struct unit_data *ud = unit_bl2ud(bl);
-		if (ud)
-			ud->state.running = unit_run(bl);
+	switch( type )
+	{
+		case SC_BERSERK:
+			sce->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
+			break;
+		case SC_CHANGE:
+			status_percent_heal(bl, 100, 100);
+			break;
+		case SC_RUN:
+			{
+				struct unit_data *ud = unit_bl2ud(bl);
+				if( ud )
+					ud->state.running = unit_run(bl);
+			}
+			break;
+		case SC_BOSSMAPINFO:
+			if( boss_md != NULL )
+				clif_bossmapinfo(sd->fd, boss_md, 0); // First Message
+			break;
+		case SC_MERC_HPUP:
+			clif_mercenary_updatestatus(((TBL_MER*)bl)->master, SP_MAXHP);
+			status_percent_heal(bl, 100, 0); // Recover Full HP
+			break;
+		case SC_MERC_SPUP:
+			clif_mercenary_updatestatus(((TBL_MER*)bl)->master, SP_MAXSP);
+			status_percent_heal(bl, 0, 100); // Recover Full SP
+			break;
+		case SC_MERC_FLEEUP:
+			clif_mercenary_updatestatus(((TBL_MER*)bl)->master, SP_MERCFLEE);
+			break;
+		case SC_MERC_ATKUP:
+			clif_mercenary_updatestatus(((TBL_MER*)bl)->master, SP_ATK1);
+			break;
+		case SC_MERC_HITUP:
+			clif_mercenary_updatestatus(((TBL_MER*)bl)->master, SP_HIT);
+			break;
 	}
 
-	if( boss_md != NULL )
-		clif_bossmapinfo(sd->fd, boss_md, 0); // First Message
-
 	return 1;
 }
 /*==========================================

+ 16 - 0
src/map/status.h

@@ -295,6 +295,14 @@ typedef enum sc_type {
 	SC_DEF_RATE,
 	SC_SPREGEN,
 	SC_WALKSPEED,
+
+	// Mercenary Only Bonus Effects
+	SC_MERC_FLEEUP,
+	SC_MERC_ATKUP,
+	SC_MERC_HPUP,
+	SC_MERC_SPUP,
+	SC_MERC_HITUP,
+
 	SC_MAX, //Automatically updated max, used in for's to check we are within bounds.
 } sc_type;
 
@@ -457,6 +465,14 @@ enum si_type {
 	//SI_FOODDEX		= 274, //Same as 244
 	//SI_FOODINT		= 275, //Same as 245
 	//SI_FOODLUK		= 276, //Same as 246
+
+	// Mercenary Only
+	SI_MERC_FLEEUP	= 277,
+	SI_MERC_ATKUP	= 278,
+	SI_MERC_HPUP	= 279,
+	SI_MERC_SPUP	= 280,
+	SI_MERC_HITUP	= 281,
+
 	SI_SLOWCAST		= 282,
 	SI_CRITICALWOUND	= 286,
 	SI_DEF_RATE		= 290,