summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2015-11-22 00:22:24 +0100
committerHaru <haru@dotalux.com>2015-12-06 15:18:59 +0100
commit4dc82e03a7e41d93e3d0518a136830693e4daf82 (patch)
treef2a502c91e899a8cb240a9e91e3f89c0b27e7f66
parent260918b18dfd8a355100a98ac077f08f2e5f24ab (diff)
downloadhercules-4dc82e03a7e41d93e3d0518a136830693e4daf82.tar.gz
hercules-4dc82e03a7e41d93e3d0518a136830693e4daf82.tar.bz2
hercules-4dc82e03a7e41d93e3d0518a136830693e4daf82.tar.xz
hercules-4dc82e03a7e41d93e3d0518a136830693e4daf82.zip
Fixed issues with compound races in bonuses where they're handled as arrays
- Corrected handling of RC_ALL in: * bAddRace * bSubRace * bMagicAddRace * bWeaponComaRace * bCriticalAddRace * bExpAddRace * bSPGainRace * bHPDrainValueRace * bSPDrainValueRace * bSPGainRaceAttack * bHPGainRaceAttack * bRaceTolerance * bHPDrainRateRace * bSPDrainRateRace * bSetDefRace * bSetMDefRace - Corrected out of bound array accesses (memory corruption) in: * bIgnoreMdefRate * bIgnoreDefRate Signed-off-by: Haru <haru@dotalux.com>
-rw-r--r--src/map/pc.c526
1 files changed, 203 insertions, 323 deletions
diff --git a/src/map/pc.c b/src/map/pc.c
index 29a7fd3d4..5ef0075bc 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -1960,7 +1960,7 @@ int pc_bonus_addeff_onskill(struct s_addeffectonskill* effect, int max, enum sc_
return 1;
}
-int pc_bonus_item_drop(struct s_add_drop *drop, const short max, short id, short group, int race, int rate) {
+int pc_bonus_item_drop(struct s_add_drop *drop, const short max, short id, short group, int race_mask, int rate) {
int i;
//Apply config rate adjustment settings.
@@ -1978,12 +1978,10 @@ int pc_bonus_item_drop(struct s_add_drop *drop, const short max, short id, short
rate = -1;
}
for(i = 0; i < max && (drop[i].id || drop[i].group); i++) {
- if(
- ((id && drop[i].id == id) ||
- (group && drop[i].group == group))
- && race > 0
+ if (((id && drop[i].id == id) || (group && drop[i].group == group))
+ && race_mask != RCMASK_NONE
) {
- drop[i].race |= race;
+ drop[i].race |= race_mask;
if (drop[i].rate > 0 && rate > 0) {
//Both are absolute rates.
if (drop[i].rate < rate)
@@ -2004,7 +2002,7 @@ int pc_bonus_item_drop(struct s_add_drop *drop, const short max, short id, short
}
drop[i].id = id;
drop[i].group = group;
- drop[i].race |= race;
+ drop[i].race |= race_mask;
drop[i].rate = rate;
return 1;
}
@@ -2179,6 +2177,17 @@ int pc_bonus_subele(struct map_session_data* sd, unsigned char ele, short rate,
return 0;
}
+/**
+ * Loops through the fields in a race bitmask (enum RaceMask => enum Race)
+ *
+ * To be used in pc_bonus functions with races represented in array form.
+ */
+#define BONUS_FOREACH_RCARRAY_FROMMASK(loop_counter, mask) \
+ for ((loop_counter) = RC_FORMLESS; (loop_counter) < RC_MAX; ++(loop_counter)) \
+ if (((mask) & 1<<(loop_counter)) == RCMASK_NONE) { \
+ continue; \
+ } else
+
/*==========================================
* Add a bonus(type) to player sd
*------------------------------------------*/
@@ -2874,33 +2883,22 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
}
break;
case SP_ADDRACE:
- if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){
- ShowWarning("pc_bonus2: SP_ADDRACE: Invalid Race(%d)\n",type2);
+ {
+ uint32 race_mask = map->race_id2mask(type2);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus2: SP_ADDRACE: Invalid Race (%d)\n", type2);
break;
}
- if ( type2 >= RC_MAX ) {
- for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) {
- if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) ||
- (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) ||
- (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) ||
- (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN))
- )
- continue;
- if ( !sd->state.lr_flag )
- sd->right_weapon.addrace[i] += val;
- else if ( sd->state.lr_flag == 1 )
- sd->left_weapon.addrace[i] += val;
- else if ( sd->state.lr_flag == 2 )
- sd->arrow_addrace[i] += val;
+ BONUS_FOREACH_RCARRAY_FROMMASK(i, race_mask) {
+ if (sd->state.lr_flag == 0) {
+ sd->right_weapon.addrace[i] += val;
+ } else if (sd->state.lr_flag == 1) {
+ sd->left_weapon.addrace[i] += val;
+ } else if (sd->state.lr_flag == 2) {
+ sd->arrow_addrace[i] += val;
}
- } else {
- if(!sd->state.lr_flag)
- sd->right_weapon.addrace[type2] += val;
- else if(sd->state.lr_flag == 1)
- sd->left_weapon.addrace[type2] += val;
- else if(sd->state.lr_flag == 2)
- sd->arrow_addrace[type2] += val;
}
+ }
break;
case SP_ADDSIZE:
if(!sd->state.lr_flag)
@@ -2926,25 +2924,18 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
}
break;
case SP_SUBRACE:
- if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){
- ShowWarning("pc_bonus2: SP_SUBRACE: Invalid Race(%d)\n",type2);
+ {
+ uint32 race_mask = map->race_id2mask(type2);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus2: SP_SUBRACE: Invalid Race (%d)\n", type2);
break;
}
- if(sd->state.lr_flag != 2) {
- if (type2 >= RC_MAX ) {
- for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) {
- if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) ||
- (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) ||
- (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) ||
- (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN))
- )
- continue;
- sd->subrace[i] += val;
- }
- } else {
- sd->subrace[type2]+=val;
- }
+ if (sd->state.lr_flag == 2)
+ break;
+ BONUS_FOREACH_RCARRAY_FROMMASK(i, race_mask) {
+ sd->subrace[i] += val;
}
+ }
break;
case SP_ADDEFF:
if (type2 > SC_MAX) {
@@ -2987,25 +2978,18 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
}
break;
case SP_MAGIC_ADDRACE:
- if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){
- ShowWarning("pc_bonus2: SP_MAGIC_ADDRACE: Invalid Race(%d)\n",type2);
+ {
+ uint32 race_mask = map->race_id2mask(type2);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus2: SP_MAGIC_ADDRACE: Invalid Race (%d)\n", type2);
break;
}
- if(sd->state.lr_flag != 2){
- if ( type2 >= RC_MAX ){
- for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) {
- if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) ||
- (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) ||
- (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) ||
- (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN))
- )
- continue;
- sd->magic_addrace[i] += val;
- }
- } else {
- sd->magic_addrace[type2]+=val;
- }
+ if (sd->state.lr_flag == 2)
+ break;
+ BONUS_FOREACH_RCARRAY_FROMMASK(i, race_mask) {
+ sd->magic_addrace[i] += val;
}
+ }
break;
case SP_MAGIC_ADDSIZE:
if(sd->state.lr_flag != 2)
@@ -3191,26 +3175,19 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
sd->special_state.bonus_coma = 1;
break;
case SP_WEAPON_COMA_RACE:
- if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){
- ShowWarning("pc_bonus2: SP_WEAPON_COMA_RACE: Invalid Race(%d)\n",type2);
+ {
+ uint32 race_mask = map->race_id2mask(type2);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus2: SP_WEAPON_COMA_RACE: Invalid Race (%d)\n", type2);
break;
}
if(sd->state.lr_flag == 2)
break;
- if ( type2 >= RC_MAX ) {
- for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) {
- if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) ||
- (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) ||
- (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) ||
- (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN))
- )
- continue;
- sd->weapon_coma_race[i] += val;
- }
- } else {
- sd->weapon_coma_race[type2] += val;
+ BONUS_FOREACH_RCARRAY_FROMMASK(i, race_mask) {
+ sd->weapon_coma_race[i] += val;
}
sd->special_state.bonus_coma = 1;
+ }
break;
case SP_WEAPON_ATK:
if(sd->state.lr_flag != 2)
@@ -3221,25 +3198,18 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
sd->weapon_atk_rate[type2]+=val;
break;
case SP_CRITICAL_ADDRACE:
- if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){
- ShowWarning("pc_bonus2: SP_CRITICAL_ADDRACE: Invalid Race(%d)\n",type2);
+ {
+ uint32 race_mask = map->race_id2mask(type2);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus2: SP_CRITICAL_ADDRACE: Invalid Race (%d)\n", type2);
break;
}
- if(sd->state.lr_flag != 2){
- if ( type2 >= RC_MAX ){
- for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) {
- if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) ||
- (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) ||
- (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) ||
- (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN))
- )
- continue;
- sd->critaddrace[i] += val*10;
- }
- } else {
- sd->critaddrace[type2] += val*10;
- }
+ if (sd->state.lr_flag == 2)
+ break;
+ BONUS_FOREACH_RCARRAY_FROMMASK(i, race_mask) {
+ sd->critaddrace[i] += val*10;
}
+ }
break;
case SP_ADDEFF_WHENHIT:
if (type2 > SC_MAX) {
@@ -3404,46 +3374,32 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
sd->itemhealrate[i].rate += val;
break;
case SP_EXP_ADDRACE:
- if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){
- ShowWarning("pc_bonus2: SP_EXP_ADDRACE: Invalid Race(%d)\n",type2);
+ {
+ uint32 race_mask = map->race_id2mask(type2);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus2: SP_EXP_ADDRACE: Invalid Race (%d)\n", type2);
break;
}
- if(sd->state.lr_flag != 2) {
- if ( type2 >= RC_MAX ){
- for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) {
- if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) ||
- (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) ||
- (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) ||
- (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN))
- )
- continue;
- sd->expaddrace[i] += val;
- }
- } else {
- sd->expaddrace[type2] += val;
- }
+ if (sd->state.lr_flag == 2)
+ break;
+ BONUS_FOREACH_RCARRAY_FROMMASK(i, race_mask) {
+ sd->expaddrace[i] += val;
}
+ }
break;
case SP_SP_GAIN_RACE:
- if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){
- ShowWarning("pc_bonus2: SP_SP_GAIN_RACE: Invalid Race(%d)\n",type2);
+ {
+ uint32 race_mask = map->race_id2mask(type2);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus2: SP_SP_GAIN_RACE: Invalid Race (%d)\n", type2);
break;
}
- if(sd->state.lr_flag != 2) {
- if ( type2 >= RC_MAX ){
- for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) {
- if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) ||
- (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) ||
- (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) ||
- (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN))
- )
- continue;
- sd->sp_gain_race[i] += val;
- }
- } else {
- sd->sp_gain_race[type2] += val;
- }
+ if (sd->state.lr_flag == 2)
+ break;
+ BONUS_FOREACH_RCARRAY_FROMMASK(i, race_mask) {
+ sd->sp_gain_race[i] += val;
}
+ }
break;
case SP_ADD_MONSTER_DROP_ITEM:
if (sd->state.lr_flag != 2)
@@ -3462,112 +3418,90 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
}
break;
case SP_HP_DRAIN_VALUE_RACE:
- if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){
- ShowWarning("pc_bonus2: SP_HP_DRAIN_VALUE_RACE: Invalid Race(%d)\n",type2);
+ {
+ uint32 race_mask = map->race_id2mask(type2);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus2: SP_HP_DRAIN_VALUE_RACE: Invalid Race (%d)\n", type2);
break;
}
- if ( type2 >= RC_MAX ){
- for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) {
- if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) ||
- (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) ||
- (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) ||
- (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN))
- )
- continue;
- if(!sd->state.lr_flag) {
- sd->right_weapon.hp_drain[i].value += val;
- }
- else if(sd->state.lr_flag == 1) {
- sd->left_weapon.hp_drain[i].value += val;
- }
- }
- } else {
- 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;
- }
+ BONUS_FOREACH_RCARRAY_FROMMASK(i, race_mask) {
+ if (sd->state.lr_flag == 0)
+ sd->right_weapon.hp_drain[i].value += val;
+ else if(sd->state.lr_flag == 1)
+ sd->left_weapon.hp_drain[i].value += val;
}
+ }
break;
case SP_SP_DRAIN_VALUE_RACE:
- if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){
- ShowWarning("pc_bonus2: SP_SP_DRAIN_VALUE_RACE: Invalid Race(%d)\n",type2);
+ {
+ uint32 race_mask = map->race_id2mask(type2);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus2: SP_SP_DRAIN_VALUE_RACE: Invalid Race (%d)\n", type2);
break;
}
- if ( type2 >= RC_MAX ){
- for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) {
- if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) ||
- (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) ||
- (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) ||
- (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN))
- )
- continue;
- if(!sd->state.lr_flag) {
- sd->right_weapon.sp_drain[i].value += val;
- }
- else if(sd->state.lr_flag == 1) {
- sd->left_weapon.sp_drain[i].value += val;
- }
- }
- } else {
- 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;
- }
+ BONUS_FOREACH_RCARRAY_FROMMASK(i, race_mask) {
+ if (sd->state.lr_flag == 0)
+ sd->right_weapon.sp_drain[i].value += val;
+ else if (sd->state.lr_flag == 1)
+ sd->left_weapon.sp_drain[i].value += val;
}
+ }
break;
case SP_IGNORE_MDEF_RATE:
- if(sd->state.lr_flag != 2)
- sd->ignore_mdef[type2] += val;
+ {
+ uint32 race_mask = map->race_id2mask(type2);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus2: SP_IGNORE_MDEF_RATE: Invalid Race (%d)\n", type2);
+ break;
+ }
+ if (sd->state.lr_flag == 2)
+ break;
+ BONUS_FOREACH_RCARRAY_FROMMASK(i, race_mask) {
+ sd->ignore_mdef[i] += val;
+ }
+ }
break;
case SP_IGNORE_DEF_RATE:
- if(sd->state.lr_flag != 2)
- sd->ignore_def[type2] += val;
+ {
+ uint32 race_mask = map->race_id2mask(type2);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus2: SP_IGNORE_DEF_RATE: Invalid Race (%d)\n", type2);
+ break;
+ }
+ if (sd->state.lr_flag == 2)
+ break;
+ BONUS_FOREACH_RCARRAY_FROMMASK(i, race_mask) {
+ sd->ignore_def[i] += val;
+ }
+ }
break;
case SP_SP_GAIN_RACE_ATTACK:
- if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){
- ShowWarning("pc_bonus2: SP_SP_GAIN_RACE_ATTACK: Invalid Race(%d)\n",type2);
+ {
+ uint32 race_mask = map->race_id2mask(type2);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus2: SP_SP_GAIN_RACE_ATTACK: Invalid Race (%d)\n", type2);
break;
}
- if(sd->state.lr_flag != 2) {
- if ( type2 >= RC_MAX ) {
- for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) {
- if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) ||
- (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) ||
- (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) ||
- (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN))
- )
- continue;
- sd->sp_gain_race_attack[i] = cap_value(sd->sp_gain_race_attack[i] + val, 0, INT16_MAX);
- }
- } else {
- sd->sp_gain_race_attack[type2] = cap_value(sd->sp_gain_race_attack[type2] + val, 0, INT16_MAX);
- }
+ if (sd->state.lr_flag == 2)
+ break;
+ BONUS_FOREACH_RCARRAY_FROMMASK(i, race_mask) {
+ sd->sp_gain_race_attack[i] = cap_value(sd->sp_gain_race_attack[i] + val, 0, INT16_MAX);
}
+ }
break;
case SP_HP_GAIN_RACE_ATTACK:
- if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){
- ShowWarning("pc_bonus2: SP_HP_GAIN_RACE_ATTACK: Invalid Race(%d)\n",type2);
+ {
+ uint32 race_mask = map->race_id2mask(type2);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus2: SP_HP_GAIN_RACE_ATTACK: Invalid Race (%d)\n", type2);
break;
}
- if(sd->state.lr_flag != 2) {
- if ( type2 >= RC_MAX ) {
- for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) {
- if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) ||
- (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) ||
- (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) ||
- (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN))
- )
- continue;
- sd->hp_gain_race_attack[i] = cap_value(sd->hp_gain_race_attack[i] + val, 0, INT16_MAX);
- }
- } else {
- sd->hp_gain_race_attack[type2] = cap_value(sd->hp_gain_race_attack[type2] + val, 0, INT16_MAX);
- }
+ if (sd->state.lr_flag == 2)
+ break;
+ BONUS_FOREACH_RCARRAY_FROMMASK(i, race_mask) {
+ sd->hp_gain_race_attack[i] = cap_value(sd->hp_gain_race_attack[i] + val, 0, INT16_MAX);
}
+ }
break;
case SP_SKILL_USE_SP_RATE: //bonus2 bSkillUseSPrate,n,x;
if(sd->state.lr_flag == 2)
@@ -3680,24 +3614,16 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
break;
#ifdef RENEWAL
case SP_RACE_TOLERANCE:
- if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){
- ShowWarning("pc_bonus2: SP_RACE_TOLERANCE: Invalid Race(%d)\n",type2);
+ {
+ uint32 race_mask = map->race_id2mask(type2);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus2: SP_RACE_TOLERANCE: Invalid Race (%d)\n", type2);
break;
}
- if(sd->state.lr_flag != 2) {
- if ( type2 >= RC_MAX ) {
- for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) {
- if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) ||
- (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) ||
- (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) ||
- (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN))
- )
- continue;
- sd->race_tolerance[i] += val;
- }
- } else {
- sd->race_tolerance[type2] += val;
- }
+ if (sd->state.lr_flag == 2)
+ break;
+ BONUS_FOREACH_RCARRAY_FROMMASK(i, race_mask)
+ sd->race_tolerance[i] += val;
}
break;
#endif
@@ -3767,70 +3693,40 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
}
break;
case SP_HP_DRAIN_RATE_RACE:
- if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){
- ShowWarning("pc_bonus3: SP_HP_DRAIN_RATE_RACE: Invalid Race(%d)\n",type2);
+ {
+ uint32 race_mask = map->race_id2mask(type2);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus3: SP_HP_DRAIN_RATE_RACE: Invalid Race (%d)\n", type2);
break;
}
- if ( type2 >= RC_MAX ) {
- for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) {
- if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) ||
- (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) ||
- (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) ||
- (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN))
- )
- continue;
- if(!sd->state.lr_flag) {
- sd->right_weapon.hp_drain[i].rate += type3;
- sd->right_weapon.hp_drain[i].per += val;
- }
- else if(sd->state.lr_flag == 1) {
- sd->left_weapon.hp_drain[i].rate += type3;
- sd->left_weapon.hp_drain[i].per += val;
- }
- }
- } else {
- 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;
+ BONUS_FOREACH_RCARRAY_FROMMASK(i, race_mask) {
+ if (sd->state.lr_flag == 0) {
+ sd->right_weapon.hp_drain[i].rate += type3;
+ sd->right_weapon.hp_drain[i].per += val;
+ } else if(sd->state.lr_flag == 1) {
+ sd->left_weapon.hp_drain[i].rate += type3;
+ sd->left_weapon.hp_drain[i].per += val;
}
}
+ }
break;
case SP_SP_DRAIN_RATE_RACE:
- if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){
- ShowWarning("pc_bonus3: SP_SP_DRAIN_RATE_RACE: Invalid Race(%d)\n",type2);
+ {
+ uint32 race_mask = map->race_id2mask(type2);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus3: SP_SP_DRAIN_RATE_RACE: Invalid Race (%d)\n", type2);
break;
}
- if ( type2 >= RC_MAX ) {
- for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) {
- if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) ||
- (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) ||
- (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) ||
- (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN))
- )
- continue;
- if(!sd->state.lr_flag) {
- sd->right_weapon.sp_drain[i].rate += type3;
- sd->right_weapon.sp_drain[i].per += val;
- }
- else if(sd->state.lr_flag == 1) {
- sd->left_weapon.sp_drain[i].rate += type3;
- sd->left_weapon.sp_drain[i].per += val;
- }
- }
- } else {
- 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;
+ BONUS_FOREACH_RCARRAY_FROMMASK(i, race_mask) {
+ if (sd->state.lr_flag == 0) {
+ sd->right_weapon.sp_drain[i].rate += type3;
+ sd->right_weapon.sp_drain[i].per += val;
+ } else if(sd->state.lr_flag == 1) {
+ sd->left_weapon.sp_drain[i].rate += type3;
+ sd->left_weapon.sp_drain[i].per += val;
}
}
+ }
break;
case SP_ADDEFF:
if (type2 > SC_MAX) {
@@ -3938,55 +3834,37 @@ int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4
break;
case SP_SET_DEF_RACE: //bonus4 bSetDefRace,n,x,r,y;
- if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){
- ShowWarning("pc_bonus4: SP_SET_DEF_RACE: Invalid Race(%d)\n",type2);
+ {
+ uint32 race_mask = map->race_id2mask(type2);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus4: SP_SET_DEF_RACE: Invalid Race (%d)\n", type2);
break;
}
- if(sd->state.lr_flag == 2)
+ if (sd->state.lr_flag == 2)
break;
- if ( type2 >= RC_MAX ) {
- for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) {
- if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) ||
- (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) ||
- (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) ||
- (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN))
- )
- continue;
- sd->def_set_race[i].rate = type3;
- sd->def_set_race[i].tick = type4;
- sd->def_set_race[i].value = val;
- }
- } else {
- sd->def_set_race[type2].rate = type3;
- sd->def_set_race[type2].tick = type4;
- sd->def_set_race[type2].value = val;
+ BONUS_FOREACH_RCARRAY_FROMMASK(i, race_mask) {
+ sd->def_set_race[i].rate = type3;
+ sd->def_set_race[i].tick = type4;
+ sd->def_set_race[i].value = val;
}
+ }
break;
case SP_SET_MDEF_RACE: //bonus4 bSetMDefRace,n,x,r,y;
- if (type2 == RC_MAX || (type2 > RC_NONDEMIPLAYER && type2 != RC_ALL) || type2 < RC_FORMLESS ){
- ShowWarning("pc_bonus4: SP_SET_MDEF_RACE: Invalid Race(%d)\n",type2);
+ {
+ uint32 race_mask = map->race_id2mask(type2);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus4: SP_SET_MDEF_RACE: Invalid Race (%d)\n", type2);
break;
}
- if(sd->state.lr_flag == 2)
+ if (sd->state.lr_flag == 2)
break;
- if ( type2 >= RC_MAX ) {
- for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) {
- if ( (type2 == RC_NONPLAYER && i == RC_PLAYER) ||
- (type2 == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) ||
- (type2 == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) ||
- (type2 == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN))
- )
- continue;
- sd->mdef_set_race[i].rate = type3;
- sd->mdef_set_race[i].tick = type4;
- sd->mdef_set_race[i].value = val;
- }
- } else {
- sd->mdef_set_race[type2].rate = type3;
- sd->mdef_set_race[type2].tick = type4;
- sd->mdef_set_race[type2].value = val;
+ BONUS_FOREACH_RCARRAY_FROMMASK(i, race_mask) {
+ sd->mdef_set_race[i].rate = type3;
+ sd->mdef_set_race[i].tick = type4;
+ sd->mdef_set_race[i].value = val;
}
+ }
break;
case SP_ADDEFF:
@@ -4043,6 +3921,8 @@ int pc_bonus5(struct map_session_data *sd,int type,int type2,int type3,int type4
return 0;
}
+#undef BONUS_FOREACH_RCARRAY_FROMMASK
+
/*==========================================
* Grants a player a given skill.
* Flag values: @see enum pc_skill_flag
@@ -10588,17 +10468,17 @@ int pc_level_penalty_mod(int diff, unsigned char race, unsigned short mode, int
if( diff < 0 )
diff = MAX_LEVEL + ( ~diff + 1 );
- for(i=0; i<RC_MAX; i++){
+ for (i = RC_FORMLESS; i < RC_MAX; i++) {
int tmp;
- if( race != i ){
- if( mode&MD_BOSS && i < RC_BOSS )
+ if (race != i) {
+ if (mode&MD_BOSS && i < RC_BOSS)
i = RC_BOSS;
- else if( i <= RC_BOSS )
+ else if (i <= RC_BOSS)
continue;
}
- if( (tmp=pc->level_penalty[type][i][diff]) > 0 ){
+ if ((tmp=pc->level_penalty[type][i][diff]) > 0) {
rate = tmp;
break;
}
@@ -10812,7 +10692,7 @@ bool pc_readdb_levelpenalty(char* fields[], int columns, int current) {
return false;
}
- if( race < 0 || race > RC_MAX ){
+ if (race < RC_FORMLESS || race > RC_MAX) {
ShowWarning("pc_readdb_levelpenalty: Invalid race %d specified.\n", race);
return false;
}
@@ -10920,7 +10800,7 @@ int pc_readdb(void) {
#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
sv->readdb(map->db_path, "re/level_penalty.txt", ',', 4, 4, -1, pc->readdb_levelpenalty);
for( k=1; k < 3; k++ ){ // fill in the blanks
- for( j = 0; j < RC_MAX; j++ ){
+ for (j = RC_FORMLESS; j < RC_MAX; j++) {
int tmp = 0;
for( i = 0; i < MAX_LEVEL*2; i++ ){
if( i == MAX_LEVEL+1 )