summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2015-12-06 17:28:19 +0300
committerAndrei Karas <akaras@inbox.ru>2015-12-06 17:28:19 +0300
commit60497e4a95836f3a6989d1cac940fd962224172c (patch)
tree67cb2529c39c8a8ad2d062b8a1092fc70ba60b09 /src
parentcea55140cc2b5d1012813f8abc028ba04bd625c6 (diff)
parentd7d6e7214cc1af22dab0b28fdde218ea7d37f05f (diff)
downloadhercules-60497e4a95836f3a6989d1cac940fd962224172c.tar.gz
hercules-60497e4a95836f3a6989d1cac940fd962224172c.tar.bz2
hercules-60497e4a95836f3a6989d1cac940fd962224172c.tar.xz
hercules-60497e4a95836f3a6989d1cac940fd962224172c.zip
Merge pull request #905 from HerculesWS/races-fix
Races fix
Diffstat (limited to 'src')
-rw-r--r--src/common/nullpo.h13
-rw-r--r--src/map/battle.c32
-rw-r--r--src/map/map.c34
-rw-r--r--src/map/map.h79
-rw-r--r--src/map/mob.c4
-rw-r--r--src/map/pc.c686
6 files changed, 401 insertions, 447 deletions
diff --git a/src/common/nullpo.h b/src/common/nullpo.h
index 52e9fba39..8abeb4af9 100644
--- a/src/common/nullpo.h
+++ b/src/common/nullpo.h
@@ -27,10 +27,23 @@
#include <crtdbg.h>
#endif // !DEFCPP && WIN && !MINGW
#define Assert(EX) assert(EX)
+/**
+ * Reports an assertion failure if the passed expression is false.
+ *
+ * @param EX The expression to test.
+ * @return false if the passed expression is true, false otherwise.
+ */
#define Assert_chk(EX) ( (EX) ? false : (nullpo->assert_report(__FILE__, __LINE__, __func__, #EX, "failed assertion"), true) )
+/**
+ * Reports an assertion failure (without actually checking it).
+ *
+ * @param EX the expression to report.
+ */
+#define Assert_report(EX) (nullpo->assert_report(__FILE__, __LINE__, __func__, #EX, "failed assertion"))
#else // ! ASSERT_CHECK
#define Assert(EX) (EX)
#define Assert_chk(EX) ((EX), false)
+#define Assert_report(EX) ((void)(EX))
#endif // ASSERT_CHECK
#if defined(NULLPO_CHECK)
diff --git a/src/map/battle.c b/src/map/battle.c
index d1cdd19c4..7fbbcd0d5 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -3714,8 +3714,8 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
//Ignore Defense?
if (!flag.imdef && (
sd->bonus.ignore_mdef_ele & ( 1 << tstatus->def_ele ) ||
- sd->bonus.ignore_mdef_race & ( 1 << tstatus->race ) ||
- sd->bonus.ignore_mdef_race & ( is_boss(target) ? 1 << RC_BOSS : 1 << RC_NONBOSS )
+ sd->bonus.ignore_mdef_race & map->race_id2mask(tstatus->race) ||
+ sd->bonus.ignore_mdef_race & map->race_id2mask(is_boss(target) ? RC_BOSS : RC_NONBOSS)
))
flag.imdef = 1;
}
@@ -5195,19 +5195,19 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
if( (i=pc->checkskill(sd,AB_EUCHARISTICA)) > 0 &&
(tstatus->race == RC_DEMON || tstatus->def_ele == ELE_DARK) )
ATK_ADDRATE(-i);
- if( skill_id != PA_SACRIFICE && skill_id != MO_INVESTIGATE && skill_id != CR_GRANDCROSS && skill_id != NPC_GRANDDARKNESS && skill_id != PA_SHIELDCHAIN && !flag.cri )
- { //Elemental/Racial adjustments
- if( sd->right_weapon.def_ratio_atk_ele & (1<<tstatus->def_ele) ||
- sd->right_weapon.def_ratio_atk_race & (1<<tstatus->race) ||
- sd->right_weapon.def_ratio_atk_race & (1<<(is_boss(target)?RC_BOSS:RC_NONBOSS))
+ if (skill_id != PA_SACRIFICE && skill_id != MO_INVESTIGATE && skill_id != CR_GRANDCROSS && skill_id != NPC_GRANDDARKNESS && skill_id != PA_SHIELDCHAIN && !flag.cri) {
+ //Elemental/Racial adjustments
+ if (sd->right_weapon.def_ratio_atk_ele & (1<<tstatus->def_ele)
+ || sd->right_weapon.def_ratio_atk_race & map->race_id2mask(tstatus->race)
+ || sd->right_weapon.def_ratio_atk_race & map->race_id2mask(is_boss(target) ? RC_BOSS : RC_NONBOSS)
)
flag.pdef = 1;
- if( sd->left_weapon.def_ratio_atk_ele & (1<<tstatus->def_ele) ||
- sd->left_weapon.def_ratio_atk_race & (1<<tstatus->race) ||
- sd->left_weapon.def_ratio_atk_race & (1<<(is_boss(target)?RC_BOSS:RC_NONBOSS))
- )
- { //Pass effect onto right hand if configured so. [Skotlex]
+ if (sd->left_weapon.def_ratio_atk_ele & (1<<tstatus->def_ele)
+ || sd->left_weapon.def_ratio_atk_race & map->race_id2mask(tstatus->race)
+ || sd->left_weapon.def_ratio_atk_race & map->race_id2mask(is_boss(target) ? RC_BOSS : RC_NONBOSS)
+ ) {
+ //Pass effect onto right hand if configured so. [Skotlex]
if (battle_config.left_cardfix_to_right && flag.rh)
flag.pdef = 1;
else
@@ -5219,15 +5219,15 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
//Ignore Defense?
if (!flag.idef && (
sd->right_weapon.ignore_def_ele & (1<<tstatus->def_ele) ||
- sd->right_weapon.ignore_def_race & (1<<tstatus->race) ||
- sd->right_weapon.ignore_def_race & (is_boss(target)?1<<RC_BOSS:1<<RC_NONBOSS)
+ sd->right_weapon.ignore_def_race & map->race_id2mask(tstatus->race) ||
+ sd->right_weapon.ignore_def_race & map->race_id2mask(is_boss(target) ? RC_BOSS : RC_NONBOSS)
))
flag.idef = 1;
if (!flag.idef2 && (
sd->left_weapon.ignore_def_ele & (1<<tstatus->def_ele) ||
- sd->left_weapon.ignore_def_race & (1<<tstatus->race) ||
- sd->left_weapon.ignore_def_race & (is_boss(target)?1<<RC_BOSS:1<<RC_NONBOSS)
+ sd->left_weapon.ignore_def_race & map->race_id2mask(tstatus->race) ||
+ sd->left_weapon.ignore_def_race & map->race_id2mask(is_boss(target) ? RC_BOSS : RC_NONBOSS)
)) {
if(battle_config.left_cardfix_to_right && flag.rh) //Move effect to right hand. [Skotlex]
flag.idef = 1;
diff --git a/src/map/map.c b/src/map/map.c
index fff1593a4..e1bf5232a 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -2040,6 +2040,39 @@ struct mob_data * map_id2boss(int id)
return (struct mob_data*)idb_get(map->bossid_db,id);
}
+/**
+ * Returns the equivalent bitmask to the given race ID.
+ *
+ * @param race A race identifier (@see enum Race)
+ *
+ * @return The equivalent race bitmask.
+ */
+uint32 map_race_id2mask(int race)
+{
+ if (race >= RC_FORMLESS && race < RC_MAX)
+ return 1 << race;
+
+ if (race == RC_ALL)
+ return RCMASK_ALL;
+
+ if (race == RC_NONPLAYER)
+ return RCMASK_NONPLAYER;
+
+ if (race == RC_NONDEMIHUMAN)
+ return RCMASK_NONDEMIHUMAN;
+
+ if (race == RC_DEMIPLAYER)
+ return RCMASK_DEMIPLAYER;
+
+ if (race == RC_NONDEMIPLAYER)
+ return RCMASK_NONDEMIPLAYER;
+
+ ShowWarning("map_race_id2mask: Invalid race: %d\n", race);
+ Assert_report((race >= RC_FORMLESS && race < RC_NONDEMIPLAYER) || race == RC_ALL);
+
+ return RCMASK_NONE;
+}
+
/// Applies func to all the players in the db.
/// Stops iterating if func returns -1.
void map_vforeachpc(int (*func)(struct map_session_data* sd, va_list args), va_list args) {
@@ -6127,6 +6160,7 @@ void map_defaults(void) {
map->nick2sd = map_nick2sd;
map->getmob_boss = map_getmob_boss;
map->id2boss = map_id2boss;
+ map->race_id2mask = map_race_id2mask;
// reload config file looking only for npcs
map->reloadnpc = map_reloadnpc;
diff --git a/src/map/map.h b/src/map/map.h
index 974fbc4ba..8f0bbca39 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -251,26 +251,64 @@ enum bl_type {
enum npc_subtype { WARP, SHOP, SCRIPT, CASHSHOP, TOMB };
-enum {
- RC_FORMLESS=0,
- RC_UNDEAD,
- RC_BRUTE,
- RC_PLANT,
- RC_INSECT,
- RC_FISH,
- RC_DEMON,
- RC_DEMIHUMAN,
- RC_ANGEL,
- RC_DRAGON,
- RC_PLAYER,
- RC_BOSS,
- RC_NONBOSS,
- RC_MAX,
- RC_NONDEMIHUMAN,
- RC_NONPLAYER,
- RC_DEMIPLAYER,
- RC_NONDEMIPLAYER,
- RC_ALL = 0xFF
+/**
+ * Race type IDs.
+ *
+ * Mostly used by scripts/bonuses.
+ */
+enum Race {
+ // Base Races
+ RC_FORMLESS = 0, ///< Formless
+ RC_UNDEAD, ///< Undead
+ RC_BRUTE, ///< Beast/Brute
+ RC_PLANT, ///< Plant
+ RC_INSECT, ///< Insect
+ RC_FISH, ///< Fish
+ RC_DEMON, ///< Demon
+ RC_DEMIHUMAN, ///< Demi-Human (not including Player)
+ RC_ANGEL, ///< Angel
+ RC_DRAGON, ///< Dragon
+ RC_PLAYER, ///< Player
+ // Boss
+ RC_BOSS, ///< Boss
+ RC_NONBOSS, ///< Non-boss
+
+ RC_MAX, // Array size delimiter (keep before the combination races)
+
+ // Combination Races
+ RC_NONDEMIHUMAN, ///< Every race except Demi-Human (including Player)
+ RC_NONPLAYER, ///< Every non-player race
+ RC_DEMIPLAYER, ///< Demi-Human (including Player)
+ RC_NONDEMIPLAYER, ///< Every race except Demi-Human (and except Player)
+ RC_ALL = 0xFF, ///< Every race (implemented as equivalent to RC_BOSS and RC_NONBOSS)
+};
+
+/**
+ * Race type bitmasks.
+ *
+ * Used by several bonuses internally, to simplify handling of race combinations.
+ */
+enum RaceMask {
+ RCMASK_NONE = 0,
+ RCMASK_FORMLESS = 1<<RC_FORMLESS,
+ RCMASK_UNDEAD = 1<<RC_UNDEAD,
+ RCMASK_BRUTE = 1<<RC_BRUTE,
+ RCMASK_PLANT = 1<<RC_PLANT,
+ RCMASK_INSECT = 1<<RC_INSECT,
+ RCMASK_FISH = 1<<RC_FISH,
+ RCMASK_DEMON = 1<<RC_DEMON,
+ RCMASK_DEMIHUMAN = 1<<RC_DEMIHUMAN,
+ RCMASK_ANGEL = 1<<RC_ANGEL,
+ RCMASK_DRAGON = 1<<RC_DRAGON,
+ RCMASK_PLAYER = 1<<RC_PLAYER,
+ RCMASK_BOSS = 1<<RC_BOSS,
+ RCMASK_NONBOSS = 1<<RC_NONBOSS,
+ RCMASK_NONDEMIPLAYER = RCMASK_FORMLESS | RCMASK_UNDEAD | RCMASK_BRUTE | RCMASK_PLANT | RCMASK_INSECT | RCMASK_FISH | RCMASK_DEMON | RCMASK_ANGEL | RCMASK_DRAGON,
+ RCMASK_NONDEMIHUMAN = RCMASK_NONDEMIPLAYER | RCMASK_PLAYER,
+ RCMASK_NONPLAYER = RCMASK_NONDEMIPLAYER | RCMASK_DEMIHUMAN,
+ RCMASK_DEMIPLAYER = RCMASK_DEMIHUMAN | RCMASK_PLAYER,
+ RCMASK_ALL = RCMASK_BOSS | RCMASK_NONBOSS,
+ RCMASK_ANY = RCMASK_NONPLAYER | RCMASK_PLAYER,
};
enum {
@@ -1010,6 +1048,7 @@ END_ZEROED_BLOCK;
struct map_session_data * (*nick2sd) (const char *nick);
struct mob_data * (*getmob_boss) (int16 m);
struct mob_data * (*id2boss) (int id);
+ uint32 (*race_id2mask) (int race);
// reload config file looking only for npcs
void (*reloadnpc) (bool clear);
diff --git a/src/map/mob.c b/src/map/mob.c
index 6cbbd3a2a..d9a3f6776 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -2411,8 +2411,8 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
{
if ( sd->add_drop[i].race == -md->class_ ||
( sd->add_drop[i].race > 0 && (
- sd->add_drop[i].race & (1<<mstatus->race) ||
- sd->add_drop[i].race & (1<<((mstatus->mode&MD_BOSS)?RC_BOSS:RC_NONBOSS))
+ sd->add_drop[i].race & map->race_id2mask(mstatus->race) ||
+ sd->add_drop[i].race & map->race_id2mask((mstatus->mode&MD_BOSS) ? RC_BOSS : RC_NONBOSS)
)))
{
//check if the bonus item drop rate should be multiplied with mob level/10 [Lupus]
diff --git a/src/map/pc.c b/src/map/pc.c
index b0a8ca62f..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
*------------------------------------------*/
@@ -2455,29 +2464,17 @@ int pc_bonus(struct map_session_data *sd,int type,int val) {
}
break;
case SP_IGNORE_DEF_RACE:
- if (val == RC_MAX || (val > RC_NONDEMIPLAYER && val != RC_ALL) || val < RC_FORMLESS ) {
- ShowWarning("pc_bonus: SP_IGNORE_DEF_RACE: Invalid Race(%d)\n",val);
+ {
+ uint32 race_mask = map->race_id2mask(val);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus: SP_IGNORE_DEF_RACE: Invalid Race (%d)\n", val);
break;
}
- if ( val >= RC_MAX ) {
- for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) {
- if ( (val == RC_NONPLAYER && i == RC_PLAYER) ||
- (val == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) ||
- (val == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) ||
- (val == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN))
- )
- continue;
- if(!sd->state.lr_flag)
- sd->right_weapon.ignore_def_race |= 1<<i;
- else if(sd->state.lr_flag == 1)
- sd->left_weapon.ignore_def_race |= 1<<i;
- }
- } else {
- if(!sd->state.lr_flag)
- sd->right_weapon.ignore_def_race |= 1<<val;
- else if(sd->state.lr_flag == 1)
- sd->left_weapon.ignore_def_race |= 1<<val;
- }
+ if (!sd->state.lr_flag)
+ sd->right_weapon.ignore_def_race |= race_mask;
+ else if (sd->state.lr_flag == 1)
+ sd->left_weapon.ignore_def_race |= race_mask;
+ }
break;
case SP_ATK_RATE:
if(sd->state.lr_flag != 2)
@@ -2492,7 +2489,8 @@ int pc_bonus(struct map_session_data *sd,int type,int val) {
sd->bonus.misc_def_rate += val;
break;
case SP_IGNORE_MDEF_RATE:
- if(sd->state.lr_flag != 2) {
+ if (sd->state.lr_flag != 2) {
+ // Decomposed RC_ALL:
sd->ignore_mdef[RC_NONBOSS] += val;
sd->ignore_mdef[RC_BOSS] += val;
}
@@ -2513,25 +2511,16 @@ int pc_bonus(struct map_session_data *sd,int type,int val) {
}
break;
case SP_IGNORE_MDEF_RACE:
- if (val == RC_MAX || (val > RC_NONDEMIPLAYER && val != RC_ALL) || val < RC_FORMLESS ) {
- ShowWarning("pc_bonus: SP_IGNORE_MDEF_RACE: Invalid Race(%d)\n",val);
+ {
+ uint32 race_mask = map->race_id2mask(val);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus: SP_IGNORE_MDEF_RACE: Invalid Race (%d)\n", val);
break;
}
- if(sd->state.lr_flag != 2) {
- if ( val >= RC_MAX ) {
- for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) {
- if ( (val == RC_NONPLAYER && i == RC_PLAYER) ||
- (val == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) ||
- (val == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) ||
- (val == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN))
- )
- continue;
- sd->bonus.ignore_mdef_race |= 1<<i;
- }
- } else {
- sd->bonus.ignore_mdef_race |= 1<<val;
- }
+ if (sd->state.lr_flag != 2) {
+ sd->bonus.ignore_mdef_race |= race_mask;
}
+ }
break;
case SP_PERFECT_HIT_RATE:
if(sd->state.lr_flag != 2 && sd->bonus.perfect_hit < val)
@@ -2565,29 +2554,17 @@ int pc_bonus(struct map_session_data *sd,int type,int val) {
}
break;
case SP_DEF_RATIO_ATK_RACE:
- if (val == RC_MAX || (val > RC_NONDEMIPLAYER && val != RC_ALL) || val < RC_FORMLESS ) {
- ShowWarning("pc_bonus: SP_DEF_RATIO_ATK_RACE: Invalid Race(%d)\n",val);
+ {
+ uint32 race_mask = map->race_id2mask(val);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus: SP_DEF_RATIO_ATK_RACE: Invalid Race (%d)\n", val);
break;
}
- if ( val >= RC_MAX ) {
- for ( i = RC_FORMLESS; i < RC_BOSS; i++ ) {
- if ( (val == RC_NONPLAYER && i == RC_PLAYER) ||
- (val == RC_NONDEMIHUMAN && i == RC_DEMIHUMAN) ||
- (val == RC_DEMIPLAYER && (i != RC_PLAYER && i != RC_DEMIHUMAN)) ||
- (val == RC_NONDEMIPLAYER && (i == RC_PLAYER || i == RC_DEMIHUMAN))
- )
- continue;
- if(!sd->state.lr_flag)
- sd->right_weapon.def_ratio_atk_race |= 1<<i;
- else if(sd->state.lr_flag == 1)
- sd->left_weapon.def_ratio_atk_race |= 1<<i;
- }
- } else {
- if(!sd->state.lr_flag)
- sd->right_weapon.def_ratio_atk_race |= 1<<val;
- else if(sd->state.lr_flag == 1)
- sd->left_weapon.def_ratio_atk_race |= 1<<val;
- }
+ if (!sd->state.lr_flag)
+ sd->right_weapon.def_ratio_atk_race |= race_mask;
+ else if (sd->state.lr_flag == 1)
+ sd->left_weapon.def_ratio_atk_race |= race_mask;
+ }
break;
case SP_HIT_RATE:
if(sd->state.lr_flag != 2)
@@ -2789,21 +2766,23 @@ int pc_bonus(struct map_session_data *sd,int type,int val) {
sd->bonus.unstripable_equip |= EQP_SHIELD;
break;
case SP_HP_DRAIN_VALUE:
- if(!sd->state.lr_flag) {
+ if (sd->state.lr_flag == 0) {
+ // Decomposed RC_ALL:
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) {
+ } else if (sd->state.lr_flag == 1) {
+ // Decomposed RC_ALL:
sd->left_weapon.hp_drain[RC_NONBOSS].value += val;
sd->left_weapon.hp_drain[RC_BOSS].value += val;
}
break;
case SP_SP_DRAIN_VALUE:
- if(!sd->state.lr_flag) {
+ if (sd->state.lr_flag == 0) {
+ // Decomposed RC_ALL:
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) {
+ } else if (sd->state.lr_flag == 1) {
+ // Decomposed RC_ALL:
sd->left_weapon.sp_drain[RC_NONBOSS].value += val;
sd->left_weapon.sp_drain[RC_BOSS].value += val;
}
@@ -2861,7 +2840,7 @@ int pc_bonus(struct map_session_data *sd,int type,int val) {
#endif
case SP_ADD_MONSTER_DROP_CHAINITEM:
if (sd->state.lr_flag != 2)
- pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), 0, val, (1<<RC_BOSS)|(1<<RC_NONBOSS), 10000);
+ pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), 0, val, map->race_id2mask(RC_ALL), 10000);
break;
default:
ShowWarning("pc_bonus: unknown type %d %d !\n",type,val);
@@ -2904,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)
@@ -2956,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) {
@@ -3017,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)
@@ -3127,13 +3081,14 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
memmove(&sd->add_mdef[i], &sd->add_mdef[i+1], sizeof(sd->add_mdef) - (i+1)*sizeof(sd->add_mdef[0]));
break;
case SP_HP_DRAIN_RATE:
- if(!sd->state.lr_flag) {
+ if (sd->state.lr_flag == 0) {
+ // Decomposed RC_ALL:
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) {
+ } else if (sd->state.lr_flag == 1) {
+ // Decomposed RC_ALL:
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;
@@ -3141,13 +3096,14 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
}
break;
case SP_HP_DRAIN_VALUE:
- if(!sd->state.lr_flag) {
+ if (sd->state.lr_flag == 0) {
+ // Decomposed RC_ALL:
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) {
+ } else if (sd->state.lr_flag == 1) {
+ // Decomposed RC_ALL:
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;
@@ -3155,13 +3111,14 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
}
break;
case SP_SP_DRAIN_RATE:
- if(!sd->state.lr_flag) {
+ if (sd->state.lr_flag == 0) {
+ // Decomposed RC_ALL:
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) {
+ } else if (sd->state.lr_flag == 1) {
+ // Decomposed RC_ALL:
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;
@@ -3169,13 +3126,14 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
}
break;
case SP_SP_DRAIN_VALUE:
- if(!sd->state.lr_flag) {
+ if (sd->state.lr_flag == 0) {
+ // Decomposed RC_ALL:
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) {
+ } else if (sd->state.lr_flag == 1) {
+ // Decomposed RC_ALL:
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;
@@ -3217,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)
@@ -3247,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) {
@@ -3430,50 +3374,36 @@ 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)
- pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, (1<<RC_BOSS)|(1<<RC_NONBOSS), val);
+ pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, map->race_id2mask(RC_ALL), val);
break;
case SP_SP_LOSS_RATE:
if(sd->state.lr_flag != 2) {
@@ -3488,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)
@@ -3694,29 +3602,28 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
}
break;
case SP_ADD_MONSTER_DROP_CHAINITEM:
+ {
+ uint32 race_mask = map->race_id2mask(type2);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus2: SP_ADD_MONSTER_DROP_CHAINITEM: Invalid Race (%d)\n", type2);
+ break;
+ }
if (sd->state.lr_flag != 2)
- pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), 0, val, 1<<type2, 10000);
+ pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), 0, val, race_mask, 10000);
+ }
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
@@ -3734,8 +3641,15 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
switch(type){
case SP_ADD_MONSTER_DROP_ITEM:
- if(sd->state.lr_flag != 2)
- pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, 1<<type3, val);
+ {
+ uint32 race_mask = map->race_id2mask(type2);
+ if (race_mask == RCMASK_NONE) {
+ ShowWarning("pc_bonus2: SP_ADD_MONSTER_DROP_ITEM: Invalid Race (%d)\n", type3);
+ break;
+ }
+ if (sd->state.lr_flag != 2)
+ pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, race_mask, val);
+ }
break;
case SP_ADD_CLASS_DROP_ITEM:
if(sd->state.lr_flag != 2)
@@ -3760,16 +3674,16 @@ 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) {
+ if (sd->state.lr_flag == 0) {
+ // Decomposed RC_ALL:
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) {
+ } else if (sd->state.lr_flag == 1) {
+ // Decomposed RC_ALL:
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;
@@ -3779,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) {
@@ -3950,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:
@@ -4055,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
@@ -10600,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;
}
@@ -10824,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;
}
@@ -10932,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 )