Parcourir la source

- Updated the HP/SP leech structures to have race-data attached to them.
- Merged all leeching code to battle_drain function.
- Added an enum for races (they match the RC entries in const.txt, except they are in all caps)
- Cleaned up atk_mods and aspd_base to be MAX_WEAPON_TYPE sized rather than MAX_WEAPON_TYPE+1
- Simplified a bit the code for Signum Crucis
- Added script bonuses:
bonus3 bHPDrainRateRace,<Race>,<Activation Rate>,<Drain %>
bonus3 bSPDrainRateRace,<Race>,<Activation Rate>,<Drain %>
bonus2 bHPDrainValueRace,<Race>,<Value>
bonus2 bSPDrainValueRace,<Race>,<Value>


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

skotlex il y a 19 ans
Parent
commit
3ffd7ebdb9
8 fichiers modifiés avec 255 ajouts et 176 suppressions
  1. 9 0
      Changelog-Trunk.txt
  2. 4 2
      db/const.txt
  3. 76 53
      src/map/battle.c
  4. 1 0
      src/map/battle.h
  5. 36 21
      src/map/map.h
  6. 95 34
      src/map/pc.c
  7. 12 33
      src/map/skill.c
  8. 22 33
      src/map/status.c

+ 9 - 0
Changelog-Trunk.txt

@@ -4,6 +4,15 @@ 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/04/21
+	* Updated the HP/SP leech structures to have race-data attached to them.
+	  [Skotlex]
+	* Merged all leeching code to new battle_drain function. [Skotlex]
+	* Simplified a bit the code for Signum Crucis [Skotlex]
+	* Added script bonuses: [Skotlex]
+		bonus3 bHPDrainRateRace,<Race>,<Activation Rate>,<Drain %>;
+		bonus3 bSPDrainRateRace,<Race>,<Activation Rate>,<Drain %>;
+		bonus2 bHPDrainValueRace,<Race>,<Value>;
+		bonus2 bSPDrainValueRace,<Race>,<Value>;
 	* Fixed items not really getting unequipped when they should. [Skotlex]
 2006/04/20
 	* Fixed the equip/unequip scripts not triggering for compounded cards.

+ 4 - 2
db/const.txt

@@ -264,6 +264,8 @@ bSPDrainValue	1080
 bWeaponAtk	1081
 bWeaponAtkRate	1082
 bDelayrate	1083
+bHPDrainRateRace	1084
+bSPDrainRateRace	1085
 
 bRestartFullRecover	2000
 bNoCastCancel	2001
@@ -292,9 +294,9 @@ bHPLossRate	2023
 bAddRace2	2024
 bHPGainValue	2025
 bSubSize	2026
-
+bHPDrainValueRace	2027
 bAddItemHealRate	2028
-
+bSPDrainValueRace	2029
 bExpAddRace	2030
 bSPGainRace	2031
 bSPSubRace2	2032

+ 76 - 53
src/map/battle.c

@@ -653,13 +653,10 @@ int battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int dama
  * HP/SP‹zŽû‚ÌŒvŽZ
  *------------------------------------------
  */
-int battle_calc_drain(int damage, int rate, int per, int val)
+static int battle_calc_drain(int damage, int rate, int per)
 {
 	int diff = 0;
 
-	if (damage <= 0)
-		return 0;
-
 	if (per && rand()%1000 < rate) {
 		diff = (damage * per) / 100;
 		if (diff == 0) {
@@ -669,10 +666,6 @@ int battle_calc_drain(int damage, int rate, int per, int val)
 				diff = -1;
 		}
 	}
-
-	if (val /*&& rand()%1000 < rate*/) { //Absolute leech/penalties have 100% chance. [Skotlex]
-		diff += val;
-	}
 	return diff;
 }
 
@@ -690,12 +683,12 @@ int battle_addmastery(struct map_session_data *sd,struct block_list *target,int
 	nullpo_retr(0, sd);
 
 	// ƒf?[ƒ‚ƒ“ƒxƒCƒ“(+3 ?` +30) vs •sŽ€ or ˆ«–‚ (Ž€?l‚͊܂߂Ȃ¢?H)
-	if((skill = pc_checkskill(sd,AL_DEMONBANE)) > 0 && (battle_check_undead(race,status_get_elem_type(target)) || race==6) )
+	if((skill = pc_checkskill(sd,AL_DEMONBANE)) > 0 && (battle_check_undead(race,status_get_elem_type(target)) || race==RC_DEMON) )
 		damage += (skill*(int)(3+(sd->status.base_level+1)*0.05));	// submitted by orn
 		//damage += (skill * 3);
 
 	// ƒr?[ƒXƒgƒxƒCƒ“(+4 ?` +40) vs “®•¨ or ?©’Ž
-	if((skill = pc_checkskill(sd,HT_BEASTBANE)) > 0 && (race==2 || race==4) ) {
+	if((skill = pc_checkskill(sd,HT_BEASTBANE)) > 0 && (race==RC_BRUTE || race==RC_INSECT) ) {
 		damage += (skill * 4);
 		if (sd->sc.data[SC_SPIRIT].timer != -1 && sd->sc.data[SC_SPIRIT].val2 == SL_HUNTER)
 			damage += sd->status.str;
@@ -1916,7 +1909,7 @@ static struct Damage battle_calc_weapon_attack(
 				vit_def = def2*(def2-15)/150;
 				vit_def = def2/2 + (vit_def>0?rand()%vit_def:0);
 				
-				if((battle_check_undead(s_race,status_get_elem_type(src)) || s_race==6) &&
+				if((battle_check_undead(s_race,status_get_elem_type(src)) || s_race==RC_DEMON) &&
 					(skill=pc_checkskill(tsd,AL_DP)) >0)
 					vit_def += skill*(int)(3 +(tsd->status.base_level+1)*0.04);   // submitted by orn
 			} else { //Mob-Pet vit-eq
@@ -3021,6 +3014,69 @@ int battle_calc_return_damage(struct block_list *bl, int *damage, int flag) {
 	}
 	return rdamage;
 }
+
+void battle_drain(TBL_PC *sd, TBL_PC* tsd, int rdamage, int ldamage, int race, int boss)
+{
+	struct weapon_data *wd;
+	int type, thp = 0, tsp = 0, rhp = 0, rsp = 0, hp, sp, i, *damage;
+	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;
+		//First and Third iterations: race, other two boss/nonboss state
+		if (i == 0 || i == 2) 
+			type = race;
+		else
+			type = boss?RC_BOSS:RC_NONBOSS;
+		
+		hp = wd->hp_drain[type].value;
+		if (wd->hp_drain[type].rate)
+			hp += battle_calc_drain(*damage,
+				wd->hp_drain[type].rate,
+		  		wd->hp_drain[type].per);
+
+		sp = wd->sp_drain[type].value;
+		if (wd->sp_drain[type].rate)
+			sp += battle_calc_drain(*damage,
+				wd->sp_drain[type].rate,
+			  	wd->sp_drain[type].per);
+
+		if (hp) {
+			if (wd->hp_drain[type].type)
+				rhp += hp;
+			thp += hp;
+		}
+		if (sp) {
+			if (wd->sp_drain[type].type)
+				rsp += sp;
+			tsp += sp;
+		}
+	}
+	if (!thp && !tsp) return;
+	
+	pc_heal(sd, thp, tsp);
+	
+	if (battle_config.show_hp_sp_drain && sd->fd)
+	{	//Display gained values only when they are positive [Skotlex]
+		if (thp && thp > sd->status.max_hp - sd->status.hp)
+			thp = sd->status.max_hp - sd->status.hp;
+		if (tsp && tsp > sd->status.max_sp - sd->status.sp)
+			tsp = sd->status.max_sp - sd->status.sp;
+		
+		if (thp > 0)
+			clif_heal(sd->fd, SP_HP, thp);
+		if (tsp > 0)
+			clif_heal(sd->fd, SP_SP, tsp);
+	}
+
+	if (tsd) {
+		if (rhp || rsp)
+			pc_heal(tsd, -rhp, -rsp);
+		if (rand()%1000 < sd->sp_vanish_rate)
+			pc_damage_sp(tsd, 0, sd->sp_vanish_per);
+	}
+}
 /*==========================================
  * ’Ê?í?UŒ‚?ˆ—?‚܂Ƃß
  *------------------------------------------
@@ -3123,7 +3179,7 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
 
 	wd.dmotion = clif_damage(src, target, tick, wd.amotion, wd.dmotion, wd.damage, wd.div_ , wd.type, wd.damage2);
 	//“ñ“?—¬?¶Žè‚ƃJƒ^?[ƒ‹’ÇŒ‚‚̃~ƒX•\ަ(–³—?‚â‚è?`)
-	if(sd && sd->status.weapon >= MAX_WEAPON_TYPE && wd.damage2 == 0)
+	if(sd && sd->status.weapon > MAX_WEAPON_TYPE && wd.damage2 == 0)
 		clif_damage(src, target, tick+10, wd.amotion, wd.dmotion,0, 1, 0, 0);
 
 	if (sd && sd->splash_range > 0 && damage > 0)
@@ -3141,8 +3197,8 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
 				rate += sd->weapon_coma_ele[ele];
 			if (sd->weapon_coma_race[race] > 0)
 				rate += sd->weapon_coma_race[race];
-			if (sd->weapon_coma_race[boss?10:11] > 0)
-				rate += sd->weapon_coma_race[boss?10:11];
+			if (sd->weapon_coma_race[boss?RC_BOSS:RC_NONBOSS] > 0)
+				rate += sd->weapon_coma_race[boss?RC_BOSS:RC_NONBOSS];
 			if (rate)
 				status_change_start(target, SC_COMA, rate, 0, 0, 0, 0, 0, 0);
 		}
@@ -3177,43 +3233,10 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
 	}
 	if (sd) {
 		if (wd.flag & BF_WEAPON && src != target && damage > 0) {
-			int hp = 0, sp = 0;
-			if (!battle_config.left_cardfix_to_right) { // “ñ“?—¬?¶ŽèƒJ?[ƒh‚Ì‹zŽûŒnŒø‰Ê‚ð‰EŽè‚ɒljÁ‚µ‚È‚¢?ê?‡
-				hp += battle_calc_drain(wd.damage, sd->right_weapon.hp_drain_rate, sd->right_weapon.hp_drain_per, sd->right_weapon.hp_drain_value);
-				hp += battle_calc_drain(wd.damage2, sd->left_weapon.hp_drain_rate, sd->left_weapon.hp_drain_per, sd->left_weapon.hp_drain_value);
-				sp += battle_calc_drain(wd.damage, sd->right_weapon.sp_drain_rate, sd->right_weapon.sp_drain_per, sd->right_weapon.sp_drain_value);
-				sp += battle_calc_drain(wd.damage2, sd->left_weapon.sp_drain_rate, sd->left_weapon.sp_drain_per, sd->left_weapon.sp_drain_value);
-			} else { // “ñ“?—¬?¶ŽèƒJ?[ƒh‚Ì‹zŽûŒnŒø‰Ê‚ð‰EŽè‚ɒljÁ‚·‚é?ê?‡
-				int hp_drain_rate = sd->right_weapon.hp_drain_rate + sd->left_weapon.hp_drain_rate;
-				int hp_drain_per = sd->right_weapon.hp_drain_per + sd->left_weapon.hp_drain_per;
-				int hp_drain_value = sd->right_weapon.hp_drain_value + sd->left_weapon.hp_drain_value;
-				int sp_drain_rate = sd->right_weapon.sp_drain_rate + sd->left_weapon.sp_drain_rate;
-				int sp_drain_per = sd->right_weapon.sp_drain_per + sd->left_weapon.sp_drain_per;
-				int sp_drain_value = sd->right_weapon.sp_drain_value + sd->left_weapon.sp_drain_value;
-				hp += battle_calc_drain(wd.damage, hp_drain_rate, hp_drain_per, hp_drain_value);
-				sp += battle_calc_drain(wd.damage, sp_drain_rate, sp_drain_per, sp_drain_value);
-			}
-			if (hp && hp + sd->status.hp > sd->status.max_hp)
-				hp = sd->status.max_hp - sd->status.hp;
-			if (sp && sp + sd->status.sp > sd->status.max_sp)
-				sp = sd->status.max_sp - sd->status.sp;
-			
-			if (hp || sp)
-				pc_heal(sd, hp, sp);
-
-			if (battle_config.show_hp_sp_drain)
-			{	//Display gained values only when they are positive [Skotlex]
-				if (hp > 0)
-					clif_heal(sd->fd, SP_HP, hp);
-				if (sp > 0)
-					clif_heal(sd->fd, SP_SP, sp);
-			}
-
-			if (tsd && sd->sp_drain_type)
-				pc_damage_sp(tsd, sp, 0);
-
-			if (tsd && rand()%1000 < sd->sp_vanish_rate)
-				pc_damage_sp(tsd, 0, sd->sp_vanish_per);
+			if (battle_config.left_cardfix_to_right)
+				battle_drain(sd, tsd, wd.damage, wd.damage, race, is_boss(target));
+			else
+				battle_drain(sd, tsd, wd.damage, wd.damage2, race, is_boss(target));
 		}
 	}
 	if (rdamage > 0) //By sending attack type "none" skill_additional_effect won't be invoked. [Skotlex]
@@ -3246,11 +3269,11 @@ int battle_check_undead(int race,int element)
 			return 1;
 	}
 	else if(battle_config.undead_detect_type == 1) {
-		if(race == 1)
+		if(race == RC_UNDEAD)
 			return 1;
 	}
 	else {
-		if(element == 9 || race == 1)
+		if(element == 9 || race == RC_UNDEAD)
 			return 1;
 	}
 	return 0;

+ 1 - 0
src/map/battle.h

@@ -26,6 +26,7 @@ struct block_list;
 struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct block_list *target,int skill_num,int skill_lv,int flag);
 
 int battle_calc_return_damage(struct block_list *bl, int *damage, int flag);
+void battle_drain(struct map_session_data *sd, struct map_session_data *tsd, int rdamage, int ldamage, int race, int boss);
 
 int battle_attr_fix(struct block_list *src, struct block_list *target, int damage,int atk_elem,int def_elem);
 

+ 36 - 21
src/map/map.h

@@ -282,6 +282,22 @@ enum {
 
 enum { WARP, SHOP, SCRIPT, MONS };
 
+enum {
+	RC_FORMLESS=0,
+	RC_UNDEAD,
+	RC_BRUTE,
+	RC_PLANT,
+	RC_INSECT,
+	RC_FISH,
+	RC_DEMON,
+	RC_DEMIHUMAN,
+	RC_ANGEL,
+	RC_DRAGON,
+	RC_BOSS,
+	RC_NONBOSS,
+	RC_MAX
+};
+
 struct block_list {
 	struct block_list *next,*prev;
 	int id;
@@ -417,17 +433,18 @@ struct weapon_data {
 	int def_ratio_atk_ele;
 	int def_ratio_atk_race;
 	int addele[10];
-	int addrace[12];
-	int addrace2[12];
+	int addrace[RC_MAX];
+	int addrace2[RC_MAX];
 	int addsize[3];
 
 	short ignore_def_mob;
-	short hp_drain_rate;
-	short hp_drain_per;
-	short hp_drain_value;
-	short sp_drain_rate;
-	short sp_drain_per;
-	short sp_drain_value;
+	struct drain_data {
+		short rate;
+		short per;
+		short value;
+		unsigned type:1;
+	} hp_drain[RC_MAX], sp_drain[RC_MAX];
+
 	short add_damage_classid[MAX_PC_BONUS];
 	int add_damage_classrate[MAX_PC_BONUS];
 	int add_damage_class_count;
@@ -579,30 +596,30 @@ struct map_session_data {
 	int paramb[6];
 	int parame[6];
 	int subele[10];
-	int subrace[12];
-	int subrace2[12];
+	int subrace[RC_MAX];
+	int subrace2[RC_MAX];
 	int subsize[3];
 	int addeff[SC_COMMON_MAX-SC_COMMON_MIN+1];
 	int addeff2[SC_COMMON_MAX-SC_COMMON_MIN+1];
 	int reseff[SC_COMMON_MAX-SC_COMMON_MIN+1];
 	int weapon_coma_ele[10];
-	int weapon_coma_race[12];
+	int weapon_coma_race[RC_MAX];
 	int weapon_atk[16];
 	int weapon_atk_rate[16];
 	int arrow_addele[10];
-	int arrow_addrace[12];
+	int arrow_addrace[RC_MAX];
 	int arrow_addsize[3];
 	int arrow_addeff[SC_COMMON_MAX-SC_COMMON_MIN+1];
 	int arrow_addeff2[SC_COMMON_MAX-SC_COMMON_MIN+1];
 	int magic_addele[10];
-	int magic_addrace[12];
+	int magic_addrace[RC_MAX];
 	int magic_addsize[3];
-	int critaddrace[12];
-	int expaddrace[12];
+	int critaddrace[RC_MAX];
+	int expaddrace[RC_MAX];
 	int itemhealrate[7];
 	int addeff3[SC_COMMON_MAX-SC_COMMON_MIN+1];
 	short addeff3_type[SC_COMMON_MAX-SC_COMMON_MIN+1];
-	short sp_gain_race[12];
+	short sp_gain_race[RC_MAX];
 	// zeroed arrays end here.
 	// zeroed structures start here
 	struct s_autospell{
@@ -658,7 +675,6 @@ struct map_session_data {
 	short hp_loss_value;
 	short sp_loss_value;
 	short hp_loss_type;
-	short sp_drain_type;
 	short sp_gain_value, hp_gain_value;
 	short sp_vanish_rate;
 	short sp_vanish_per;	
@@ -1105,8 +1121,8 @@ enum {
 	SP_DISGUISE,SP_CLASSCHANGE, // 1077-1078
 	SP_HP_DRAIN_VALUE,SP_SP_DRAIN_VALUE, // 1079-1080
 	SP_WEAPON_ATK,SP_WEAPON_ATK_RATE, // 1081-1082
-	SP_DELAYRATE,	// 1083
-
+	SP_DELAYRATE,SP_HP_DRAIN_RATE_RACE,SP_SP_DRAIN_RATE_RACE, // 1083-1085
+	
 	SP_RESTART_FULL_RECOVER=2000,SP_NO_CASTCANCEL,SP_NO_SIZEFIX,SP_NO_MAGIC_DAMAGE,SP_NO_WEAPON_DAMAGE,SP_NO_GEMSTONE, // 2000-2005
 	SP_NO_CASTCANCEL2,SP_INFINITE_ENDURE,SP_UNBREAKABLE_WEAPON,SP_UNBREAKABLE_ARMOR, SP_UNBREAKABLE_HELM, // 2006-2010
 	SP_UNBREAKABLE_SHIELD, SP_LONG_ATK_RATE, // 2011-2012
@@ -1114,12 +1130,11 @@ enum {
 	SP_CRIT_ATK_RATE, SP_CRITICAL_ADDRACE, SP_NO_REGEN, SP_ADDEFF_WHENHIT, SP_AUTOSPELL_WHENHIT, // 2013-2017
 	SP_SKILL_ATK, SP_UNSTRIPABLE, SP_ADD_DAMAGE_BY_CLASS, // 2018-2020
 	SP_SP_GAIN_VALUE, SP_IGNORE_DEF_MOB, SP_HP_LOSS_RATE, SP_ADDRACE2, SP_HP_GAIN_VALUE, // 2021-2025
-	SP_SUBSIZE, SP_FREE, SP_ADD_ITEM_HEAL_RATE, SP_FREE2, SP_EXP_ADDRACE,	// 2026-2030
+	SP_SUBSIZE, SP_HP_DRAIN_VALUE_RACE, SP_ADD_ITEM_HEAL_RATE, SP_SP_DRAIN_VALUE_RACE, SP_EXP_ADDRACE,	// 2026-2030
 	SP_SP_GAIN_RACE, SP_SUBRACE2, SP_ADDEFF_WHENHIT_SHORT,	// 2031-2033
 	SP_UNSTRIPABLE_WEAPON,SP_UNSTRIPABLE_ARMOR,SP_UNSTRIPABLE_HELM,SP_UNSTRIPABLE_SHIELD,  // 2034-2037
 	SP_INTRAVISION, SP_ADD_MONSTER_DROP_ITEMGROUP, SP_SP_LOSS_RATE, // 2038-2040
 	SP_ADD_SKILL_BLOW, SP_SP_VANISH_RATE //2041
-	//Before you add more here, notice that 2027&2029 are available.
 };
 
 enum {

+ 95 - 34
src/map/pc.c

@@ -1613,18 +1613,22 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
 		break;
 	case SP_HP_DRAIN_VALUE:
 		if(!sd->state.lr_flag) {
-			sd->right_weapon.hp_drain_value += val;
+			sd->right_weapon.hp_drain[RC_NONBOSS].value += val;
+			sd->right_weapon.hp_drain[RC_BOSS].value += val;
 		}
 		else if(sd->state.lr_flag == 1) {
-			sd->left_weapon.hp_drain_value += val;
+			sd->right_weapon.hp_drain[RC_NONBOSS].value += val;
+			sd->right_weapon.hp_drain[RC_BOSS].value += val;
 		}
 		break;
 	case SP_SP_DRAIN_VALUE:
 		if(!sd->state.lr_flag) {
-			sd->right_weapon.sp_drain_value += val;
+			sd->right_weapon.sp_drain[RC_NONBOSS].value += val;
+			sd->right_weapon.sp_drain[RC_BOSS].value += val;
 		}
 		else if(sd->state.lr_flag == 1) {
-			sd->left_weapon.sp_drain_value += val;
+			sd->left_weapon.sp_drain[RC_NONBOSS].value += val;
+			sd->left_weapon.sp_drain[RC_BOSS].value += val;
 		}
 		break;
 	case SP_SP_GAIN_VALUE:
@@ -1807,42 +1811,59 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
 		break;
 	case SP_HP_DRAIN_RATE:
 		if(!sd->state.lr_flag) {
-			sd->right_weapon.hp_drain_rate += type2;
-			sd->right_weapon.hp_drain_per += val;
+			sd->right_weapon.hp_drain[RC_NONBOSS].rate += type2;
+			sd->right_weapon.hp_drain[RC_NONBOSS].per += val;
+			sd->right_weapon.hp_drain[RC_BOSS].rate += type2;
+			sd->right_weapon.hp_drain[RC_BOSS].per += val;
 		}
 		else if(sd->state.lr_flag == 1) {
-			sd->left_weapon.hp_drain_rate += type2;
-			sd->left_weapon.hp_drain_per += val;
+			sd->left_weapon.hp_drain[RC_NONBOSS].rate += type2;
+			sd->left_weapon.hp_drain[RC_NONBOSS].per += val;
+			sd->left_weapon.hp_drain[RC_BOSS].rate += type2;
+			sd->left_weapon.hp_drain[RC_BOSS].per += val;
 		}
 		break;
 	case SP_HP_DRAIN_VALUE:
 		if(!sd->state.lr_flag) {
-			sd->right_weapon.hp_drain_value += type2;
+			sd->right_weapon.hp_drain[RC_NONBOSS].value += type2;
+			sd->right_weapon.hp_drain[RC_NONBOSS].type = val;
+			sd->right_weapon.hp_drain[RC_BOSS].value += type2;
+			sd->right_weapon.hp_drain[RC_BOSS].type = val;
 		}
 		else if(sd->state.lr_flag == 1) {
-			sd->left_weapon.hp_drain_value += type2;
+			sd->left_weapon.hp_drain[RC_NONBOSS].value += type2;
+			sd->left_weapon.hp_drain[RC_NONBOSS].type = val;
+			sd->left_weapon.hp_drain[RC_BOSS].value += type2;
+			sd->left_weapon.hp_drain[RC_BOSS].type = val;
 		}
-		sd->sp_drain_type = val;
 		break;
 	case SP_SP_DRAIN_RATE:
 		if(!sd->state.lr_flag) {
-			sd->right_weapon.sp_drain_rate += type2;
-			sd->right_weapon.sp_drain_per += val;
+			sd->right_weapon.sp_drain[RC_NONBOSS].rate += type2;
+			sd->right_weapon.sp_drain[RC_NONBOSS].per += val;
+			sd->right_weapon.sp_drain[RC_BOSS].rate += type2;
+			sd->right_weapon.sp_drain[RC_BOSS].per += val;
 		}
 		else if(sd->state.lr_flag == 1) {
-			sd->left_weapon.sp_drain_rate += type2;
-			sd->left_weapon.sp_drain_per += val;
+			sd->left_weapon.sp_drain[RC_NONBOSS].rate += type2;
+			sd->left_weapon.sp_drain[RC_NONBOSS].per += val;
+			sd->left_weapon.sp_drain[RC_BOSS].rate += type2;
+			sd->left_weapon.sp_drain[RC_BOSS].per += val;
 		}
-		sd->sp_drain_type = 0;
 		break;
 	case SP_SP_DRAIN_VALUE:
 		if(!sd->state.lr_flag) {
-			sd->right_weapon.sp_drain_value += type2;
+			sd->right_weapon.sp_drain[RC_NONBOSS].value += type2;
+			sd->right_weapon.sp_drain[RC_NONBOSS].type = val;
+			sd->right_weapon.sp_drain[RC_BOSS].value += type2;
+			sd->right_weapon.sp_drain[RC_BOSS].type = val;
 		}
 		else if(sd->state.lr_flag == 1) {
-			sd->left_weapon.sp_drain_value += type2;
+			sd->left_weapon.sp_drain[RC_NONBOSS].value += type2;
+			sd->left_weapon.sp_drain[RC_NONBOSS].type = val;
+			sd->left_weapon.sp_drain[RC_BOSS].value += type2;
+			sd->left_weapon.sp_drain[RC_BOSS].type = val;
 		}
-		sd->sp_drain_type = val;
 		break;
 	case SP_SP_VANISH_RATE:
 		if(sd->state.lr_flag != 2) {
@@ -2005,6 +2026,22 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
 			sd->sp_loss_rate = val;
 		}
 		break;
+	case SP_HP_DRAIN_VALUE_RACE:
+		if(!sd->state.lr_flag) {
+			sd->right_weapon.hp_drain[type2].value += val;
+		}
+		else if(sd->state.lr_flag == 1) {
+			sd->left_weapon.hp_drain[type2].value += val;
+		}
+		break;
+	case SP_SP_DRAIN_VALUE_RACE:
+		if(!sd->state.lr_flag) {
+			sd->right_weapon.sp_drain[type2].value += val;
+		}
+		else if(sd->state.lr_flag == 1) {
+			sd->left_weapon.sp_drain[type2].value += val;
+		}
+		break;
 
 	default:
 		if(battle_config.error_log)
@@ -2040,14 +2077,42 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
 		break;
 	case SP_SP_DRAIN_RATE:
 		if(!sd->state.lr_flag) {
-			sd->right_weapon.sp_drain_rate += type2;
-			sd->right_weapon.sp_drain_per += type3;
+			sd->right_weapon.sp_drain[RC_NONBOSS].rate += type2;
+			sd->right_weapon.sp_drain[RC_NONBOSS].per += type3;
+			sd->right_weapon.sp_drain[RC_NONBOSS].type = val;
+			sd->right_weapon.sp_drain[RC_BOSS].rate += type2;
+			sd->right_weapon.sp_drain[RC_BOSS].per += type3;
+			sd->right_weapon.sp_drain[RC_BOSS].type = val;
+
 		}
 		else if(sd->state.lr_flag == 1) {
-			sd->left_weapon.sp_drain_rate += type2;
-			sd->left_weapon.sp_drain_per += type3;
+			sd->left_weapon.sp_drain[RC_NONBOSS].rate += type2;
+			sd->left_weapon.sp_drain[RC_NONBOSS].per += type3;
+			sd->left_weapon.sp_drain[RC_NONBOSS].type = val;
+			sd->left_weapon.sp_drain[RC_BOSS].rate += type2;
+			sd->left_weapon.sp_drain[RC_BOSS].per += type3;
+			sd->left_weapon.sp_drain[RC_BOSS].type = val;
+		}
+		break;
+	case SP_HP_DRAIN_RATE_RACE:
+		if(!sd->state.lr_flag) {
+			sd->right_weapon.hp_drain[type2].rate += type3;
+			sd->right_weapon.hp_drain[type2].per += val;
+		}
+		else if(sd->state.lr_flag == 1) {
+			sd->left_weapon.hp_drain[type2].rate += type3;
+			sd->left_weapon.hp_drain[type2].per += val;
+		}
+		break;
+	case SP_SP_DRAIN_RATE_RACE:
+		if(!sd->state.lr_flag) {
+			sd->right_weapon.sp_drain[type2].rate += type3;
+			sd->right_weapon.sp_drain[type2].per += val;
+		}
+		else if(sd->state.lr_flag == 1) {
+			sd->left_weapon.sp_drain[type2].rate += type3;
+			sd->left_weapon.sp_drain[type2].per += val;
 		}
-		sd->sp_drain_type = val;
 		break;
 	case SP_ADD_MONSTER_DROP_ITEMGROUP:
 		if (sd->state.lr_flag != 2)
@@ -6226,12 +6291,6 @@ int pc_equipitem(struct map_session_data *sd,int n,int pos)
 				run_script(data->equip_script,0,sd->bl.id,0);
 		}
 	}
-
-	if(sd->sc.count) {
-		if (sd->sc.data[SC_SIGNUMCRUCIS].timer != -1 && !battle_check_undead(7,sd->def_ele))
-			status_change_end(&sd->bl,SC_SIGNUMCRUCIS,-1);
-	}
-
 	return 0;
 }
 
@@ -6301,11 +6360,12 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag)
 		pc_checkallowskill(sd);
 	if(sd->weapontype1 == 0 && sd->weapontype2 == 0)
 		skill_enchant_elemental_end(&sd->bl,-1);  //武器持ち誓えは無?件で?性付?解除
-	if(flag&1) {
+	if(flag&1)
 		status_calc_pc(sd,0);
-		if(sd->sc.count && sd->sc.data[SC_SIGNUMCRUCIS].timer != -1 && !battle_check_undead(7,sd->def_ele))
-			status_change_end(&sd->bl,SC_SIGNUMCRUCIS,-1);
-	}
+
+	if(sd->sc.count && sd->sc.data[SC_SIGNUMCRUCIS].timer != -1 && !battle_check_undead(RC_DEMIHUMAN,sd->def_ele))
+		status_change_end(&sd->bl,SC_SIGNUMCRUCIS,-1);
+
 	//OnUnEquip script [Skotlex]
 	if (sd->inventory_data[n]) {
 		struct item_data *data;
@@ -6325,6 +6385,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag)
 				run_script(data->unequip_script,0,sd->bl.id,0);
 		}
 	}
+
 	return 0;
 }
 

+ 12 - 33
src/map/skill.c

@@ -1099,7 +1099,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
 	case NPC_GRANDDARKNESS:	/*ˆÅƒOƒ‰ƒ“ƒhƒNƒ?ƒX*/
 		{
 			int race = status_get_race(bl);
-			if(battle_check_undead(race,status_get_elem_type(bl)) || race == 6)
+			if(battle_check_undead(race,status_get_elem_type(bl)) || race == RC_DEMON)
 				sc_start(bl,SC_BLIND,100,skilllv,skill_get_time2(skillid,skilllv));
 		}
 		break;
@@ -1206,7 +1206,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
 		{
 			//?Œ?‚ª—Ç‚­•ª‚©‚ç‚È‚¢‚̂œK?‚É
 			int race = status_get_race(bl);
-			if (!(battle_check_undead(race, status_get_elem_type(bl)) || race == 6))
+			if (!(battle_check_undead(race, status_get_elem_type(bl)) || race == RC_DEMON))
 				sc_start(bl, SC_BLEEDING,50, skilllv, skill_get_time2(skillid,skilllv));
 		}
 		break;
@@ -1877,7 +1877,7 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
 			case AC_DOUBLE:
 			{
 				int race = status_get_race(bl);
-				if((race == 2 || race == 4) && damage < status_get_hp(bl) && pc_checkskill(sd, HT_POWER)) {
+				if((race == RC_BRUTE || race == RC_INSECT) && damage < status_get_hp(bl) && pc_checkskill(sd, HT_POWER)) {
 					//TODO: This code was taken from Triple Blows,is this even how it should be? [Skotlex]
 					sc_start4(src,SC_COMBO,100,HT_POWER,bl->id,0,0,2000);
 					clif_combo_delay(src,2000);
@@ -2018,31 +2018,10 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds
 	}
 
 	if(sd && dmg.flag&BF_WEAPON && src != bl && src == dsrc && damage > 0) {
-		int hp = 0,sp = 0;
-		if(sd->right_weapon.hp_drain_rate && sd->right_weapon.hp_drain_per > 0 && dmg.damage > 0 && rand()%1000 < sd->right_weapon.hp_drain_rate) {
-			hp += (dmg.damage * sd->right_weapon.hp_drain_per)/100;
-			if(sd->right_weapon.hp_drain_rate > 0 && hp < 1) hp = 1;
-			else if(sd->right_weapon.hp_drain_rate < 0 && hp > -1) hp = -1;
-		}
-		if(sd->left_weapon.hp_drain_rate && sd->left_weapon.hp_drain_per > 0 && dmg.damage2 > 0 && rand()%1000 < sd->left_weapon.hp_drain_rate) {
-			hp += (dmg.damage2 * sd->left_weapon.hp_drain_per)/100;
-			if(sd->left_weapon.hp_drain_rate > 0 && hp < 1) hp = 1;
-			else if(sd->left_weapon.hp_drain_rate < 0 && hp > -1) hp = -1;
-		}
-		if(sd->right_weapon.sp_drain_rate > 0 && sd->right_weapon.sp_drain_per > 0 && dmg.damage > 0 && rand()%1000 < sd->right_weapon.sp_drain_rate) {
-			sp += (dmg.damage * sd->right_weapon.sp_drain_per)/100;
-			if(sd->right_weapon.sp_drain_rate > 0 && sp < 1) sp = 1;
-			else if(sd->right_weapon.sp_drain_rate < 0 && sp > -1) sp = -1;
-		}
-		if(sd->left_weapon.sp_drain_rate > 0 && sd->left_weapon.sp_drain_per > 0 && dmg.damage2 > 0 && rand()%1000 < sd->left_weapon.sp_drain_rate) {
-			sp += (dmg.damage2 * sd->left_weapon.sp_drain_per)/100;
-			if(sd->left_weapon.sp_drain_rate > 0 && sp < 1) sp = 1;
-			else if(sd->left_weapon.sp_drain_rate < 0 && sp > -1) sp = -1;
-		}
-		if(hp || sp)
-			pc_heal(sd,hp,sp);
-		if (sd->sp_drain_type && tsd)
-			pc_damage_sp(tsd,sp,0);
+		if (battle_config.left_cardfix_to_right)
+			battle_drain(sd, tsd, dmg.damage, dmg.damage, status_get_race(bl), status_get_mode(bl)&MD_BOSS);
+		else
+			battle_drain(sd, tsd, dmg.damage, dmg.damage2, status_get_race(bl), status_get_mode(bl)&MD_BOSS);
 	}
 
 	if (rdamage>0) {
@@ -2881,7 +2860,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl,int s
 	case PR_BENEDICTIO:			/* ?¹??~•Ÿ */
 	{	//Should attack undead and demons. [Skotlex]
 		int race = status_get_race(bl);
-		if (battle_check_undead(race, status_get_elem_type(bl)) || race == 6)
+		if (battle_check_undead(race, status_get_elem_type(bl)) || race == RC_DEMON)
 			skill_attack(BF_MAGIC, src, src, bl, skillid, skilllv, tick, flag);
 	}
 	break;
@@ -3044,7 +3023,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl,int s
 	case GS_BULLSEYE:
 		{
 		int race = status_get_race(bl);
-		if(race == 2 || race == 7)
+		if(race == RC_BRUTE || race == RC_DEMIHUMAN)
 			skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
 		else
 			clif_skill_fail(sd,skillid,0,0);
@@ -4259,7 +4238,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 		}else if(dstmd)
 		{
 			int race = status_get_race(bl);
-			if(status_get_lv(src)>status_get_lv(bl) && (race == 6 || race == 7 || race == 8)) {
+			if(status_get_lv(src)>status_get_lv(bl) && (race == RC_DEMON || race == RC_DEMIHUMAN || race == RC_ANGEL)) {
 				clif_skill_nodamage(src,bl,skillid,skilllv,
 					sc_start(bl,type,70,skilllv,skill_get_time(skillid,skilllv)));
 			} else{
@@ -6802,7 +6781,7 @@ int skill_unit_onplace_timer(struct skill_unit *src,struct block_list *bl,unsign
 		{
 			int race = status_get_race(bl);
 
-			if (battle_check_undead(race, status_get_elem_type(bl)) || race==6) {
+			if (battle_check_undead(race, status_get_elem_type(bl)) || race==RC_DEMON) {
 				if (skill_attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0)) {
 					// reduce healing count if this was meant for damaging [hekate]
 					sg->val1 -= 2;
@@ -6826,7 +6805,7 @@ int skill_unit_onplace_timer(struct skill_unit *src,struct block_list *bl,unsign
 	case UNT_MAGNUS:
 		{
 			int race = status_get_race(bl);
-			if (!battle_check_undead(race,status_get_elem_type(bl)) && race!=6)
+			if (!battle_check_undead(race,status_get_elem_type(bl)) && race!=RC_DEMON)
 				break;
 			skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
 			break;

+ 22 - 33
src/map/status.c

@@ -37,11 +37,11 @@ static int hp_coefficient[MAX_PC_CLASS];
 static int hp_coefficient2[MAX_PC_CLASS];
 static int hp_sigma_val[MAX_PC_CLASS][MAX_LEVEL];
 static int sp_coefficient[MAX_PC_CLASS];
-static int aspd_base[MAX_PC_CLASS][MAX_WEAPON_TYPE+1];	//[blackhole89]
+static int aspd_base[MAX_PC_CLASS][MAX_WEAPON_TYPE];	//[blackhole89]
 #define MAX_REFINE_BONUS 5
 static int refinebonus[MAX_REFINE_BONUS][3];	// 精錬ボーナステーブル(refine_db.txt)
 int percentrefinery[5][MAX_REFINE+1];	// 精錬成功率(refine_db.txt)
-static int atkmods[3][MAX_WEAPON_TYPE+1];	// 武器ATKサイズ修正(size_fix.txt)
+static int atkmods[3][MAX_WEAPON_TYPE];	// 武器ATKサイズ修正(size_fix.txt)
 static char job_bonus[MAX_PC_CLASS][MAX_LEVEL];
 
 int current_equip_item_index; //Contains inventory index of an equipped item. To pass it into the EQUP_SCRIPT [Lupus]
@@ -501,7 +501,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int
 			if (pc_isinvisible(sd))
 				return 0;
 			if (tsc->option&hide_flag
-				&& (sd->state.perfect_hiding || !(race == 4 || race == 6 || mode&MD_DETECTOR))
+				&& (sd->state.perfect_hiding || !(race == RC_INSECT || race == RC_DEMON || mode&MD_DETECTOR))
 				&& !(mode&MD_BOSS))
 				return 0;
 		}
@@ -516,7 +516,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int
 		//Check for chase-walk/hiding/cloaking opponents.
 		if (tsc && !(mode&MD_BOSS))
 		{
-			if (tsc->option&hide_flag && !(race == 4 || race == 6 || mode&MD_DETECTOR))
+			if (tsc->option&hide_flag && !(race == RC_INSECT || race == RC_DEMON || mode&MD_DETECTOR))
 				return 0;
 		}
 	}
@@ -785,7 +785,6 @@ int status_calc_pc(struct map_session_data* sd,int first)
 		+ sizeof(sd->hp_loss_value)
 		+ sizeof(sd->sp_loss_value)
 		+ sizeof(sd->hp_loss_type)
-		+ sizeof(sd->sp_drain_type)
 		+ sizeof(sd->hp_gain_value)
 		+ sizeof(sd->sp_gain_value)
 		+ sizeof(sd->add_drop_count)
@@ -1559,10 +1558,10 @@ int status_calc_pc(struct map_session_data* sd,int first)
 	}
 	if((skill=pc_checkskill(sd,SA_DRAGONOLOGY))>0 ){
 		skill = skill*4;
-		sd->right_weapon.addrace[9]+=skill;
-		sd->left_weapon.addrace[9]+=skill;
-		sd->magic_addrace[9]+=skill;
-		sd->subrace[9]+=skill;
+		sd->right_weapon.addrace[RC_DRAGON]+=skill;
+		sd->left_weapon.addrace[RC_DRAGON]+=skill;
+		sd->magic_addrace[RC_DRAGON]+=skill;
+		sd->subrace[RC_DRAGON]+=skill;
 	}
 
 	if(sd->sc.count){
@@ -1579,7 +1578,7 @@ int status_calc_pc(struct map_session_data* sd,int first)
 		}
 		if(sd->sc.data[SC_PROVIDENCE].timer!=-1){
 			sd->subele[6] += sd->sc.data[SC_PROVIDENCE].val2;
-			sd->subrace[6] += sd->sc.data[SC_PROVIDENCE].val2;
+			sd->subrace[RC_DEMON] += sd->sc.data[SC_PROVIDENCE].val2;
 		}
 	}
 
@@ -1686,7 +1685,7 @@ int status_calc_str(struct block_list *bl, int str)
 			str += 10; //Bonus is +!0 regardless of skill level
 		if(sc->data[SC_BLESSING].timer != -1){
 			int race = status_get_race(bl);
-			if(battle_check_undead(race,status_get_elem_type(bl)) || race == 6)
+			if(battle_check_undead(race,status_get_elem_type(bl)) || race == RC_DEMON)
 				str >>= 1;
 			else str += sc->data[SC_BLESSING].val1;
 		}
@@ -1766,7 +1765,7 @@ int status_calc_int(struct block_list *bl, int int_)
 			int_ += 5;
 		if(sc->data[SC_BLESSING].timer != -1){
 			int race = status_get_race(bl);
-			if(battle_check_undead(race,status_get_elem_type(bl)) || race == 6)
+			if(battle_check_undead(race,status_get_elem_type(bl)) || race == RC_DEMON)
 				int_ >>= 1;
 			else int_ += sc->data[SC_BLESSING].val1;
 		}
@@ -1798,7 +1797,7 @@ int status_calc_dex(struct block_list *bl, int dex)
 			dex -= sc->data[SC_QUAGMIRE].val1*(bl->type==BL_PC?5:10);
 		if(sc->data[SC_BLESSING].timer != -1){
 			int race = status_get_race(bl);
-			if(battle_check_undead(race,status_get_elem_type(bl)) || race == 6)
+			if(battle_check_undead(race,status_get_elem_type(bl)) || race == RC_DEMON)
 				dex >>= 1;
 			else dex += sc->data[SC_BLESSING].val1;
 		}
@@ -3202,7 +3201,7 @@ int status_get_race(struct block_list *bl)
 	if(bl->type==BL_MOB)
 		return ((struct mob_data *)bl)->db->race;
 	if(bl->type==BL_PC)
-		return 7;
+		return RC_DEMIHUMAN;
 	if(bl->type==BL_PET)
 		return ((struct pet_data *)bl)->db->race;
 	return 0;
@@ -3696,12 +3695,12 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val
 		break;
 		case SC_COMA:
 			//Dark elementals and Demons are inmune to coma.
-			if((elem == 7 || race == 6) && !(flag&1))
+			if((elem == 7 || race == RC_DEMON) && !(flag&1))
 				return 0;
 		break;
 		case SC_SIGNUMCRUCIS:
 			//Only affects demons and undead.
-			if(race != 6 && !undead_flag)
+			if(race != RC_DEMON && !undead_flag)
 				return 0;
 			break;
 		case SC_AETERNA:
@@ -3759,7 +3758,7 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val
 			 return 0;
 		 switch (type) {
 			case SC_BLESSING:
-			  if (!undead_flag || race != 6)
+			  if (!undead_flag || race != RC_DEMON)
 				  break;
 			case SC_QUAGMIRE:
 			case SC_DECREASEAGI:
@@ -3774,7 +3773,7 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val
 	//Before overlapping fail, one must check for status cured.
 	switch (type) {
 	case SC_BLESSING:
-		if (!undead_flag && race!=6) {
+		if (!undead_flag && race!=RC_DEMON) {
 			if (sc->data[SC_CURSE].timer!=-1)
 				status_change_end(bl,SC_CURSE,-1);
 			if (sc->data[SC_STONE].timer!=-1 && sc->data[SC_STONE].val2==0)
@@ -5412,16 +5411,6 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
 		}
 		break;
 
-	case SC_SIGNUMCRUCIS:		/* シグナムクルシス */
-		{
-			int race = status_get_race(bl);
-			if(race == 6 || battle_check_undead(race,status_get_elem_type(bl))) {
-				sc->data[type].timer=add_timer(1000*600+tick,status_change_timer, bl->id, data );
-				return 0;
-			}
-		}
-		break;
-
 	case SC_WARM: //SG skills [Komurka]
 		if( (--sc->data[type].val2)>0){
 			map_foreachinrange( status_change_timer_sub, bl,
@@ -5540,6 +5529,7 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
 	case SC_DODGE:
 	case SC_AUTOBERSERK: //continues until triggered off manually. [Skotlex]
 	case SC_NEN:
+	case SC_SIGNUMCRUCIS:		/* シグナムクルシス */
 		sc->data[type].timer=add_timer( 1000*600+tick,status_change_timer, bl->id, data );
 		return 0;
 
@@ -5948,7 +5938,7 @@ int status_readdb(void) {
 
 	// サイズ補正テ?ブル
 	for(i=0;i<3;i++)
-		for(j=0;j<=MAX_WEAPON_TYPE;j++)
+		for(j=0;j<MAX_WEAPON_TYPE;j++)
 			atkmods[i][j]=100;
 	sprintf(path, "%s/size_fix.txt", db_path);
 	fp=fopen(path,"r");
@@ -5958,19 +5948,18 @@ int status_readdb(void) {
 	}
 	i=0;
 	while(fgets(line, sizeof(line)-1, fp)){
-		char *split[MAX_WEAPON_TYPE+1];
+		char *split[MAX_WEAPON_TYPE];
 		if(line[0]=='/' && line[1]=='/')
 			continue;
 		if(atoi(line)<=0)
 			continue;
 		memset(split,0,sizeof(split));
-		for(j=0,p=line;j<=MAX_WEAPON_TYPE && p;j++){
+		for(j=0,p=line;j<MAX_WEAPON_TYPE && p;j++){
 			split[j]=p;
 			p=strchr(p,',');
 			if(p) *p++=0;
-		}
-		for(j=0;j<=MAX_WEAPON_TYPE && split[j];j++)
 			atkmods[i][j]=atoi(split[j]);
+		}
 		i++;
 	}
 	fclose(fp);