浏览代码

Added new item bonuses:
* `bonus2 bHPGainRaceAttackRate,r,n;`: Heals +n% HP of inflicted damage on every hit when attacking an enemy of race r
* `bonus2 bSPGainRaceAttackRate,r,n;`: Heals +n% SP of inflicted damage on every hit when attacking an enemy of race r
* `bonus bAbsorbDmgMaxHP,n;`: If the damage received is more than n% of Max HP, the damage received is [TotalDamage] - [n% of MaxHP]
* Thank @nanakiwurtz.

Signed-off-by: Cydh Ramdh <cydh@pservero.com>

Cydh Ramdh 10 年之前
父节点
当前提交
6779058f77
共有 7 个文件被更改,包括 105 次插入7 次删除
  1. 3 0
      db/const.txt
  2. 5 0
      doc/item_bonus.txt
  3. 79 6
      src/map/battle.c
  4. 2 1
      src/map/map.h
  5. 11 0
      src/map/pc.c
  6. 3 0
      src/map/pc.h
  7. 2 0
      src/map/status.c

+ 3 - 0
db/const.txt

@@ -628,6 +628,9 @@ bAddMaxWeight	2072
 bAddItemGroupHealRate	2073
 bHPVanishRaceRate	2074
 bSPVanishRaceRate	2075
+bHPGainRaceAttackRate	2076
+bSPGainRaceAttackRate	2077
+bAbsorbDmgMaxHP	2078
 
 EQI_HEAD_TOP	1
 EQI_ARMOR	2

+ 5 - 0
doc/item_bonus.txt

@@ -230,6 +230,8 @@ bonus2 bAddMDefMonster,mid,x;     	+x% magical damage reduction against monster
 bonus2 bAddRace2,mr,x;			+x% damage against monster race mr
 bonus2 bSubRace2,mr,x;			+x% damage reduction against monster race mr
 
+bonus bAbsorbDmgMaxHP,n;		If the damage received is more than n% of Max HP, the damage received is [TotalDamage] - [n% of MaxHP]
+
 Atk/Def
 -------
 bonus bAtkEle,e;          		Gives the player's attacks element e
@@ -342,6 +344,9 @@ bonus3 bSPVanishRaceRate,r,n,x;		Add a n/100% chance of decreasing enemy's SP am
 bonus2 bHPGainRaceAttack,r,n;		Heals +n HP on every hit when attacking an enemy of race r
 bonus2 bSPGainRaceAttack,r,n;		Heals +n SP on every hit when attacking an enemy of race r
 
+bonus2 bHPGainRaceAttackRate,r,n;		Heals +n% HP of inflicted damage on every hit when attacking an enemy of race r
+bonus2 bSPGainRaceAttackRate,r,n;		Heals +n% SP of inflicted damage on every hit when attacking an enemy of race r
+
 bonus bHPGainValue,n;     		Heals +n HP when killing an enemy with a physical attack
 bonus bSPGainValue,n;     		Heals +n SP when killing an enemy with a physical attack
 bonus2 bSPGainRace,r,n;   		Heals +n SP when killing an enemy of race r with a physical attack

+ 79 - 6
src/map/battle.c

@@ -783,6 +783,52 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
 	return (int)(damage - original_damage);
 }
 
+/**
+* Absorb damage based on criteria
+* @param bl
+* @param d Damage
+**/
+static void battle_absorb_damage(struct block_list *bl, struct Damage *d) {
+	int64 dmg_ori = 0, dmg_new = 0;
+
+	nullpo_retv(bl);
+	nullpo_retv(d);
+
+	if (!d->damage && !d->damage2)
+		return;
+
+	switch (bl->type) {
+		case BL_PC:
+			{
+				struct map_session_data *sd = BL_CAST(BL_PC, bl);
+				if (!sd)
+					return;
+				if (sd->bonus.absorb_dmg_maxhp) {
+					int hp = sd->bonus.absorb_dmg_maxhp * status_get_max_hp(bl) / 100;
+					dmg_ori = dmg_new = d->damage + d->damage2;
+					if (dmg_ori > hp)
+						dmg_new = dmg_ori - hp;
+				}
+			}
+			break;
+	}
+
+	if (dmg_ori == dmg_new)
+		return;
+
+	if (!d->damage2)
+		d->damage = dmg_new;
+	else if (!d->damage)
+		d->damage2 = dmg_new;
+	else {
+		d->damage = dmg_new;
+		d->damage2 = dmg_new * d->damage2 / dmg_ori / 100;
+		if (d->damage2 < 1)
+			d->damage2 = 1;
+		d->damage = d->damage - d->damage2;
+	}
+}
+
 /**
  * Check damage through status.
  * ATK may be MISS, BLOCKED FAIL, reduc, increase, end status.
@@ -5299,6 +5345,8 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
 
 	wd = battle_calc_weapon_final_atk_modifiers(wd, src, target, skill_id, skill_lv);
 
+	battle_absorb_damage(target, &wd);
+
 	battle_do_reflect(BF_WEAPON,&wd, src, target, skill_id, skill_lv); //WIP [lighta]
 
 	return wd;
@@ -6059,6 +6107,8 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 		MATK_ADDRATE(skill_damage);
 #endif
 
+	battle_absorb_damage(target, &ad);
+
 	//battle_do_reflect(BF_MAGIC,&ad, src, target, skill_id, skill_lv); //WIP [lighta] Magic skill has own handler at skill_attack
 	return ad;
 }
@@ -6428,6 +6478,8 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 		md.damage += (int64)md.damage * skill_damage / 100;
 #endif
 
+	battle_absorb_damage(target, &md);
+
 	battle_do_reflect(BF_MISC,&md, src, target, skill_id, skill_lv); //WIP [lighta]
 
 	return md;
@@ -6569,7 +6621,11 @@ void battle_drain(TBL_PC *sd, struct block_list *tbl, int64 rdamage, int64 ldama
 {
 	struct weapon_data *wd;
 	int64 *damage;
-	int thp = 0, tsp = 0, rhp = 0, rsp = 0, hp = 0, sp = 0;
+	int thp = 0, // HP gained by attacked
+		tsp = 0, // SP gained by attacked
+		rhp = 0, // HP reduced from target
+		rsp = 0, // SP reduced from target
+		hp = 0, sp = 0;
 	uint8 i = 0;
 	short vrate_hp = 0, vrate_sp = 0, v_hp = 0, v_sp = 0;
 
@@ -6577,11 +6633,15 @@ void battle_drain(TBL_PC *sd, struct block_list *tbl, int64 rdamage, int64 ldama
 		return;
 
 	// Check for vanish HP/SP. !CHECKME: Which first, drain or vanish?
-	vrate_hp = cap_value(sd->bonus.hp_vanish_rate + sd->vanish_race[race].hp_rate + sd->vanish_race[RC_ALL].hp_rate, SHRT_MIN, SHRT_MAX);
-	v_hp = cap_value(sd->bonus.hp_vanish_per + sd->vanish_race[race].hp_per + sd->vanish_race[RC_ALL].hp_per, INT8_MIN, INT8_MAX);
+	hp = sd->bonus.hp_vanish_rate + sd->vanish_race[race].hp_rate + sd->vanish_race[RC_ALL].hp_rate;
+	vrate_hp = cap_value(hp, SHRT_MIN, SHRT_MAX);
+	hp = sd->bonus.hp_vanish_per + sd->vanish_race[race].hp_per + sd->vanish_race[RC_ALL].hp_per;
+	v_hp = cap_value(hp, INT8_MIN, INT8_MAX);
 
-	vrate_sp = cap_value(sd->bonus.sp_vanish_rate + sd->vanish_race[race].sp_rate + sd->vanish_race[RC_ALL].sp_rate, SHRT_MIN, SHRT_MAX);
-	v_sp = cap_value(sd->bonus.sp_vanish_per + sd->vanish_race[race].sp_per + sd->vanish_race[RC_ALL].sp_per, INT8_MIN, INT8_MAX);
+	sp = sd->bonus.sp_vanish_rate + sd->vanish_race[race].sp_rate + sd->vanish_race[RC_ALL].sp_rate;
+	vrate_sp = cap_value(sp, SHRT_MIN, SHRT_MAX);
+	sp = sd->bonus.sp_vanish_per + sd->vanish_race[race].sp_per + sd->vanish_race[RC_ALL].sp_per;
+	v_sp = cap_value(sp, INT8_MIN, INT8_MAX);
 
 	if (v_hp > 0 && vrate_hp > 0 && (vrate_hp >= 10000 || rnd()%10000 < vrate_hp))
 		i |= 1;
@@ -6590,12 +6650,14 @@ void battle_drain(TBL_PC *sd, struct block_list *tbl, int64 rdamage, int64 ldama
 	if (i)
 		status_percent_damage(&sd->bl, tbl, (i&1 ? (int8)v_hp: 0), (i&2 ? (int8)v_sp : 0), false);
 
-	i = 0;
+	hp = sp = i = 0;
 	for (i = 0; i < 4; i++) {
 		//First two iterations: Right hand
 		if (i < 2) { wd = &sd->right_weapon; damage = &rdamage; }
 		else { wd = &sd->left_weapon; damage = &ldamage; }
+
 		if (*damage <= 0) continue;
+
 		if( i == 1 || i == 3 ) {
 			hp = wd->hp_drain_class[class_].value + wd->hp_drain_class[CLASS_ALL].value;
 			if (wd->hp_drain_class[class_].rate)
@@ -6659,11 +6721,22 @@ void battle_drain(TBL_PC *sd, struct block_list *tbl, int64 rdamage, int64 ldama
 		tsp += sd->sp_gain_race_attack[race];
 	if( sd->sp_gain_race_attack[RC_ALL] )
 		tsp += sd->sp_gain_race_attack[RC_ALL];
+
 	if( sd->hp_gain_race_attack[race] )
 		thp += sd->hp_gain_race_attack[race];
 	if( sd->hp_gain_race_attack[RC_ALL] )
 		thp += sd->hp_gain_race_attack[RC_ALL];
 
+	if (sd->hp_gain_race_attack_rate[race])
+		thp += (int)((rdamage+ldamage) * sd->hp_gain_race_attack_rate[race] / 100);
+	if (sd->hp_gain_race_attack_rate[RC_ALL])
+		thp += (int)((rdamage+ldamage) * sd->hp_gain_race_attack_rate[RC_ALL] / 100);
+
+	if (sd->sp_gain_race_attack_rate[race])
+		tsp += (int)((rdamage+ldamage) * sd->sp_gain_race_attack_rate[race] / 100);
+	if (sd->sp_gain_race_attack_rate[RC_ALL])
+		tsp += (int)((rdamage+ldamage) * sd->sp_gain_race_attack_rate[RC_ALL] / 100);
+
 	if (!thp && !tsp)
 		return;
 

+ 2 - 1
src/map/map.h

@@ -499,7 +499,8 @@ enum _sp {
 	SP_IGNORE_DEF_CLASS, SP_DEF_RATIO_ATK_CLASS, SP_ADDCLASS, SP_SUBCLASS, SP_MAGIC_ADDCLASS, //2062-2066
 	SP_WEAPON_COMA_CLASS, SP_IGNORE_MDEF_CLASS_RATE, SP_EXP_ADDCLASS, SP_ADD_CLASS_DROP_ITEM, //2067-2070
 	SP_ADD_CLASS_DROP_ITEMGROUP, SP_ADDMAXWEIGHT, SP_ADD_ITEMGROUP_HEAL_RATE,  // 2071-2073
-	SP_HP_VANISH_RACE_RATE, SP_SP_VANISH_RACE_RATE, // 2074-2075
+	SP_HP_VANISH_RACE_RATE, SP_SP_VANISH_RACE_RATE, SP_HP_GAIN_RACE_ATTACK_RATE, SP_SP_GAIN_RACE_ATTACK_RATE, // 2074-2077
+	SP_ABSORB_DMG_MAXHP, // 2078
 };
 
 enum _look {

+ 11 - 0
src/map/pc.c

@@ -2977,6 +2977,9 @@ void pc_bonus(struct map_session_data *sd,int type,int val)
 			if (sd->state.lr_flag != 2)
 				sd->max_weight += val;
 			break;
+		case SP_ABSORB_DMG_MAXHP:
+			sd->bonus.absorb_dmg_maxhp = max(sd->bonus.absorb_dmg_maxhp, val);
+			break;
 		default:
 			ShowWarning("pc_bonus: unknown type %d %d !\n",type,val);
 			break;
@@ -3642,6 +3645,14 @@ void pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
 			sd->skillusesp[i].val = val;
 		}
 		break;
+	case SP_HP_GAIN_RACE_ATTACK_RATE: // bonus2 bHPGainRaceAttackRate,r,n;
+		PC_BONUS_CHK_RACE(type2,SP_HP_GAIN_RACE_ATTACK_RATE);
+		sd->hp_gain_race_attack_rate[type2] += val;
+		break;
+	case SP_SP_GAIN_RACE_ATTACK_RATE: // bonus2 bSPGainRaceAttackRate,r,n;
+		PC_BONUS_CHK_RACE(type2,SP_SP_GAIN_RACE_ATTACK_RATE);
+		sd->sp_gain_race_attack_rate[type2] += val;
+		break;
 	default:
 		ShowWarning("pc_bonus2: unknown type %d %d %d!\n",type,type2,val);
 		break;

+ 3 - 0
src/map/pc.h

@@ -349,6 +349,8 @@ struct map_session_data {
 	short sp_gain_race[RC_MAX];
 	short sp_gain_race_attack[RC_MAX];
 	short hp_gain_race_attack[RC_MAX];
+	short hp_gain_race_attack_rate[RC_MAX];
+	short sp_gain_race_attack_rate[RC_MAX];
 	// zeroed arrays end here.
 
 	// zeroed structures start here
@@ -433,6 +435,7 @@ struct map_session_data {
 		int add_fixcast, add_varcast; // in milliseconds
 		int ematk; // matk bonus from equipment
 		int eatk; // atk bonus from equipment
+		uint8 absorb_dmg_maxhp; // [Cydh]
 	} bonus;
 	// zeroed vars end here.
 

+ 2 - 0
src/map/status.c

@@ -3009,6 +3009,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
 		+ sizeof(sd->sp_gain_race)
 		+ sizeof(sd->sp_gain_race_attack)
 		+ sizeof(sd->hp_gain_race_attack)
+		+ sizeof(sd->hp_gain_race_attack_rate)
+		+ sizeof(sd->sp_gain_race_attack_rate)
 		);
 
 	memset (&sd->right_weapon.overrefine, 0, sizeof(sd->right_weapon) - sizeof(sd->right_weapon.atkmods));