diff --git a/src/map/battle.cpp b/src/map/battle.cpp index 1f44d7f027..6d33980536 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -615,7 +615,6 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li struct status_data *sstatus, ///< Attacker status data *tstatus; ///< Target status data int64 original_damage; - int i; if( !damage ) return 0; @@ -647,9 +646,9 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li } cardfix = cardfix * (100 + sd->magic_addsize[tstatus->size] + sd->magic_addsize[SZ_ALL]) / 100; cardfix = cardfix * (100 + sd->magic_addclass[tstatus->class_] + sd->magic_addclass[CLASS_ALL]) / 100; - for( i = 0; i < ARRAYLENGTH(sd->add_mdmg) && sd->add_mdmg[i].rate; i++ ) { - if( sd->add_mdmg[i].class_ == t_class ) { - cardfix = cardfix * (100 + sd->add_mdmg[i].rate) / 100; + for (const auto &it : sd->add_mdmg) { + if (it.id == t_class) { + cardfix = cardfix * (100 + it.val) / 100; break; } } @@ -663,14 +662,14 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses int ele_fix = tsd->subele[rh_ele] + tsd->subele[ELE_ALL] + tsd->subele_script[rh_ele] + tsd->subele_script[ELE_ALL]; - for( i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++ ) { - if( tsd->subele2[i].ele != rh_ele ) + for (const auto &it : tsd->subele2) { + if (it.ele != rh_ele) continue; - if( !(((tsd->subele2[i].flag)&flag)&BF_WEAPONMASK && - ((tsd->subele2[i].flag)&flag)&BF_RANGEMASK && - ((tsd->subele2[i].flag)&flag)&BF_SKILLMASK) ) + if (!(((it.flag)&flag)&BF_WEAPONMASK && + ((it.flag)&flag)&BF_RANGEMASK && + ((it.flag)&flag)&BF_SKILLMASK)) continue; - ele_fix += tsd->subele2[i].rate; + ele_fix += it.rate; } if (s_defele != ELE_NONE) ele_fix += tsd->subdefele[s_defele] + tsd->subdefele[ELE_ALL]; @@ -681,9 +680,9 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li cardfix = cardfix * (100 - tsd->subrace[sstatus->race] - tsd->subrace[RC_ALL]) / 100; cardfix = cardfix * (100 - tsd->subclass[sstatus->class_] - tsd->subclass[CLASS_ALL]) / 100; - for( i = 0; i < ARRAYLENGTH(tsd->add_mdef) && tsd->add_mdef[i].rate; i++ ) { - if( tsd->add_mdef[i].class_ == s_class ) { - cardfix = cardfix * (100 - tsd->add_mdef[i].rate) / 100; + for (const auto &it : tsd->add_mdef) { + if (it.id == s_class) { + cardfix = cardfix * (100 - it.val) / 100; break; } } @@ -714,14 +713,14 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->arrow_addele[tstatus->def_ele] + sd->right_weapon.addele[ELE_ALL] + sd->arrow_addele[ELE_ALL]; - for( i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++ ) { - if( sd->right_weapon.addele2[i].ele != tstatus->def_ele ) + for (const auto &it : sd->right_weapon.addele2) { + if (it.ele != tstatus->def_ele) continue; - if( !(((sd->right_weapon.addele2[i].flag)&flag)&BF_WEAPONMASK && - ((sd->right_weapon.addele2[i].flag)&flag)&BF_RANGEMASK && - ((sd->right_weapon.addele2[i].flag)&flag)&BF_SKILLMASK) ) + if (!(((it.flag)&flag)&BF_WEAPONMASK && + ((it.flag)&flag)&BF_RANGEMASK && + ((it.flag)&flag)&BF_SKILLMASK)) continue; - ele_fix += sd->right_weapon.addele2[i].rate; + ele_fix += it.rate; } cardfix = cardfix * (100 + ele_fix) / 100; } @@ -740,14 +739,14 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->right_weapon.addele[ELE_ALL]; - for( i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++ ) { - if( sd->right_weapon.addele2[i].ele != tstatus->def_ele ) + for (const auto &it : sd->right_weapon.addele2) { + if (it.ele != tstatus->def_ele) continue; - if( !(((sd->right_weapon.addele2[i].flag)&flag)&BF_WEAPONMASK && - ((sd->right_weapon.addele2[i].flag)&flag)&BF_RANGEMASK && - ((sd->right_weapon.addele2[i].flag)&flag)&BF_SKILLMASK) ) + if (!(((it.flag)&flag)&BF_WEAPONMASK && + ((it.flag)&flag)&BF_RANGEMASK && + ((it.flag)&flag)&BF_SKILLMASK)) continue; - ele_fix += sd->right_weapon.addele2[i].rate; + ele_fix += it.rate; } cardfix = cardfix * (100 + ele_fix) / 100; } @@ -760,14 +759,14 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses int ele_fix_lh = sd->left_weapon.addele[tstatus->def_ele] + sd->left_weapon.addele[ELE_ALL]; - for( i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++ ) { - if( sd->left_weapon.addele2[i].ele != tstatus->def_ele ) + for (const auto &it : sd->left_weapon.addele2) { + if (it.ele != tstatus->def_ele) continue; - if( !(((sd->left_weapon.addele2[i].flag)&flag)&BF_WEAPONMASK && - ((sd->left_weapon.addele2[i].flag)&flag)&BF_RANGEMASK && - ((sd->left_weapon.addele2[i].flag)&flag)&BF_SKILLMASK) ) + if (!(((it.flag)&flag)&BF_WEAPONMASK && + ((it.flag)&flag)&BF_RANGEMASK && + ((it.flag)&flag)&BF_SKILLMASK)) continue; - ele_fix_lh += sd->left_weapon.addele2[i].rate; + ele_fix_lh += it.rate; } cardfix_ = cardfix_ * (100 + ele_fix_lh) / 100; } @@ -783,23 +782,23 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->left_weapon.addele[tstatus->def_ele] + sd->right_weapon.addele[ELE_ALL] + sd->left_weapon.addele[ELE_ALL]; - for( i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++ ) { - if( sd->right_weapon.addele2[i].ele != tstatus->def_ele ) + for (const auto &it : sd->right_weapon.addele2) { + if (it.ele != tstatus->def_ele) continue; - if( !(((sd->right_weapon.addele2[i].flag)&flag)&BF_WEAPONMASK && - ((sd->right_weapon.addele2[i].flag)&flag)&BF_RANGEMASK && - ((sd->right_weapon.addele2[i].flag)&flag)&BF_SKILLMASK) ) + if (!(((it.flag)&flag)&BF_WEAPONMASK && + ((it.flag)&flag)&BF_RANGEMASK && + ((it.flag)&flag)&BF_SKILLMASK)) continue; - ele_fix += sd->right_weapon.addele2[i].rate; + ele_fix += it.rate; } - for( i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++ ) { - if( sd->left_weapon.addele2[i].ele != tstatus->def_ele ) + for (const auto &it : sd->left_weapon.addele2) { + if (it.ele != tstatus->def_ele) continue; - if( !(((sd->left_weapon.addele2[i].flag)&flag)&BF_WEAPONMASK && - ((sd->left_weapon.addele2[i].flag)&flag)&BF_RANGEMASK && - ((sd->left_weapon.addele2[i].flag)&flag)&BF_SKILLMASK) ) + if (!(((it.flag)&flag)&BF_WEAPONMASK && + ((it.flag)&flag)&BF_RANGEMASK && + ((it.flag)&flag)&BF_SKILLMASK)) continue; - ele_fix += sd->left_weapon.addele2[i].rate; + ele_fix += it.rate; } cardfix = cardfix * (100 + ele_fix) / 100; //} @@ -816,16 +815,16 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li } //! CHECKME: These right & left hand weapon ignores 'left_cardfix_to_right'? - for( i = 0; i < ARRAYLENGTH(sd->right_weapon.add_dmg) && sd->right_weapon.add_dmg[i].rate; i++ ) { - if( sd->right_weapon.add_dmg[i].class_ == t_class ) { - cardfix = cardfix * (100 + sd->right_weapon.add_dmg[i].rate) / 100; + for (const auto &it : sd->right_weapon.add_dmg) { + if (it.id == t_class) { + cardfix = cardfix * (100 + it.val) / 100; break; } } if( left&1 ) { - for( i = 0; i < ARRAYLENGTH(sd->left_weapon.add_dmg) && sd->left_weapon.add_dmg[i].rate; i++ ) { - if( sd->left_weapon.add_dmg[i].class_ == t_class ) { - cardfix_ = cardfix_ * (100 + sd->left_weapon.add_dmg[i].rate) / 100; + for (const auto &it : sd->left_weapon.add_dmg) { + if (it.id == t_class) { + cardfix_ = cardfix_ * (100 + it.val) / 100; break; } } @@ -845,28 +844,28 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses int ele_fix = tsd->subele[rh_ele] + tsd->subele[ELE_ALL] + tsd->subele_script[rh_ele] + tsd->subele_script[ELE_ALL]; - for( i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++ ) { - if( tsd->subele2[i].ele != rh_ele ) + for (const auto &it : tsd->subele2) { + if (it.ele != rh_ele) continue; - if( !(((tsd->subele2[i].flag)&flag)&BF_WEAPONMASK && - ((tsd->subele2[i].flag)&flag)&BF_RANGEMASK && - ((tsd->subele2[i].flag)&flag)&BF_SKILLMASK) ) + if (!(((it.flag)&flag)&BF_WEAPONMASK && + ((it.flag)&flag)&BF_RANGEMASK && + ((it.flag)&flag)&BF_SKILLMASK)) continue; - ele_fix += tsd->subele2[i].rate; + ele_fix += it.rate; } cardfix = cardfix * (100 - ele_fix) / 100; if( left&1 && lh_ele != rh_ele ) { int ele_fix_lh = tsd->subele[lh_ele] + tsd->subele[ELE_ALL] + tsd->subele_script[lh_ele] + tsd->subele_script[ELE_ALL]; - for( i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++ ) { - if( tsd->subele2[i].ele != lh_ele ) + for (const auto &it : tsd->subele2) { + if (it.ele != lh_ele) continue; - if( !(((tsd->subele2[i].flag)&flag)&BF_WEAPONMASK && - ((tsd->subele2[i].flag)&flag)&BF_RANGEMASK && - ((tsd->subele2[i].flag)&flag)&BF_SKILLMASK) ) + if (!(((it.flag)&flag)&BF_WEAPONMASK && + ((it.flag)&flag)&BF_RANGEMASK && + ((it.flag)&flag)&BF_SKILLMASK)) continue; - ele_fix_lh += tsd->subele2[i].rate; + ele_fix_lh += it.rate; } cardfix = cardfix * (100 - ele_fix_lh) / 100; } @@ -877,9 +876,9 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li cardfix = cardfix * (100 - tsd->subrace2[s_race2]) / 100; cardfix = cardfix * (100 - tsd->subrace[sstatus->race] - tsd->subrace[RC_ALL]) / 100; cardfix = cardfix * (100 - tsd->subclass[sstatus->class_] - tsd->subclass[CLASS_ALL]) / 100; - for( i = 0; i < ARRAYLENGTH(tsd->add_def) && tsd->add_def[i].rate; i++ ) { - if( tsd->add_def[i].class_ == s_class ) { - cardfix = cardfix * (100 - tsd->add_def[i].rate) / 100; + for (const auto &it : tsd->add_def) { + if (it.id == s_class) { + cardfix = cardfix * (100 - it.val) / 100; break; } } @@ -899,14 +898,14 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses int ele_fix = tsd->subele[rh_ele] + tsd->subele[ELE_ALL] + tsd->subele_script[rh_ele] + tsd->subele_script[ELE_ALL]; - for( i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++ ) { - if( tsd->subele2[i].ele != rh_ele ) + for (const auto &it : tsd->subele2) { + if (it.ele != rh_ele) continue; - if( !(((tsd->subele2[i].flag)&flag)&BF_WEAPONMASK && - ((tsd->subele2[i].flag)&flag)&BF_RANGEMASK && - ((tsd->subele2[i].flag)&flag)&BF_SKILLMASK)) + if (!(((it.flag)&flag)&BF_WEAPONMASK && + ((it.flag)&flag)&BF_RANGEMASK && + ((it.flag)&flag)&BF_SKILLMASK)) continue; - ele_fix += tsd->subele2[i].rate; + ele_fix += it.rate; } if (s_defele != ELE_NONE) ele_fix += tsd->subdefele[s_defele] + tsd->subdefele[ELE_ALL]; @@ -2158,13 +2157,12 @@ static int battle_range_type(struct block_list *src, struct block_list *target, static int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id) { - uint8 i; - if (!sd->skillblown[0].id) + if (sd->skillblown.empty()) return 0; //Apply the bonus blewcount. [Skotlex] - for (i = 0; i < ARRAYLENGTH(sd->skillblown) && sd->skillblown[i].id; i++) { - if (sd->skillblown[i].id == skill_id) - return sd->skillblown[i].val; + for (const auto &it : sd->skillblown) { + if (it.id == skill_id) + return it.val; } return 0; } diff --git a/src/map/mob.cpp b/src/map/mob.cpp index f48be6c75c..10b8692170 100644 --- a/src/map/mob.cpp +++ b/src/map/mob.cpp @@ -2779,28 +2779,28 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) // process script-granted extra drop bonuses uint16 dropid = 0; - for (i = 0; i < ARRAYLENGTH(sd->add_drop); i++) { + for (const auto &it : sd->add_drop) { struct s_mob_drop mobdrop; - if (!&sd->add_drop[i] || (!sd->add_drop[i].nameid && !sd->add_drop[i].group)) + if (!&it || (!it.nameid && !it.group)) continue; - if ((sd->add_drop[i].race < RC_NONE_ && sd->add_drop[i].race == -md->mob_id) || //Race < RC_NONE_, use mob_id - (sd->add_drop[i].race == RC_ALL || sd->add_drop[i].race == status->race) || //Matched race - (sd->add_drop[i].class_ == CLASS_ALL || sd->add_drop[i].class_ == status->class_)) //Matched class + if ((it.race < RC_NONE_ && it.race == -md->mob_id) || //Race < RC_NONE_, use mob_id + (it.race == RC_ALL || it.race == status->race) || //Matched race + (it.class_ == CLASS_ALL || it.class_ == status->class_)) //Matched class { //Check if the bonus item drop rate should be multiplied with mob level/10 [Lupus] - if (sd->add_drop[i].rate < 0) { + if (it.rate < 0) { //It's negative, then it should be multiplied. with mob_level/10 //rate = base_rate * (mob_level/10) + 1 - drop_rate = (-sd->add_drop[i].rate) * md->level / 10 + 1; + drop_rate = (-it.rate) * md->level / 10 + 1; drop_rate = cap_value(drop_rate, max(battle_config.item_drop_adddrop_min,1), min(battle_config.item_drop_adddrop_max,10000)); } else //it's positive, then it goes as it is - drop_rate = sd->add_drop[i].rate; + drop_rate = it.rate; if (rnd()%10000 >= drop_rate) continue; - dropid = (sd->add_drop[i].nameid > 0) ? sd->add_drop[i].nameid : itemdb_searchrandomid(sd->add_drop[i].group,1); + dropid = (it.nameid > 0) ? it.nameid : itemdb_searchrandomid(it.group,1); memset(&mobdrop, 0, sizeof(struct s_mob_drop)); mobdrop.nameid = dropid; diff --git a/src/map/pc.cpp b/src/map/pc.cpp index f270a0fa63..bcfd2042c2 100755 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -79,7 +79,6 @@ int day_timer_tid = INVALID_TIMER; int night_timer_tid = INVALID_TIMER; struct eri *pc_sc_display_ers = NULL; -struct eri *pc_itemgrouphealrate_ers = NULL; struct eri *num_reg_ers; struct eri *str_reg_ers; int pc_expiration_tid = INVALID_TIMER; @@ -1200,12 +1199,6 @@ bool pc_authok(struct map_session_data *sd, uint32 login_id2, time_t expiration_ for(i = 0; i < MAX_SPIRITBALL; i++) sd->spirit_timer[i] = INVALID_TIMER; - for(i = 0; i < ARRAYLENGTH(sd->autobonus); i++) - sd->autobonus[i].active = INVALID_TIMER; - for(i = 0; i < ARRAYLENGTH(sd->autobonus2); i++) - sd->autobonus2[i].active = INVALID_TIMER; - for(i = 0; i < ARRAYLENGTH(sd->autobonus3); i++) - sd->autobonus3[i].active = INVALID_TIMER; if (battle_config.item_auto_get) sd->state.autoloot = 10000; @@ -2076,157 +2069,183 @@ int pc_disguise(struct map_session_data *sd, int class_) /// Check for valid SC, break & show error message if invalid SC #define PC_BONUS_CHK_SC(sc,bonus) { if ((sc) <= SC_NONE || (sc) >= SC_MAX) { PC_BONUS_SHOW_ERROR((bonus),Effect,(sc)); }} -static void pc_bonus_autospell(struct s_autospell *spell, int max, short id, short lv, short rate, short flag, unsigned short card_id) +/** + * Add auto spell bonus for player while attacking/attacked + * @param spell: Spell array + * @param id: Skill to cast + * @param lv: Skill level + * @param rate: Success chance + * @param flag: Battle flag + * @param card_id: Used to prevent card stacking + */ +static void pc_bonus_autospell(std::vector &spell, short id, short lv, short rate, short flag, unsigned short card_id) { - uint8 i; + if (spell.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus_autospell: Reached max (%d) number of autospells per character!\n", MAX_PC_BONUS); + return; + } - if( !rate ) + if (!rate) return; - for( i = 0; i < max && spell[i].id; i++ ) - { - if( (spell[i].card_id == card_id || spell[i].rate < 0 || rate < 0) && spell[i].id == id && spell[i].lv == lv ) - { - if( !battle_config.autospell_stacking && spell[i].rate > 0 && rate > 0 ) + if (!(flag&BF_RANGEMASK)) + flag |= BF_SHORT | BF_LONG; //No range defined? Use both. + if (!(flag&BF_WEAPONMASK)) + flag |= BF_WEAPON; //No attack type defined? Use weapon. + if (!(flag&BF_SKILLMASK)) { + if (flag&(BF_MAGIC | BF_MISC)) + flag |= BF_SKILL; //These two would never trigger without BF_SKILL + if (flag&BF_WEAPON) + flag |= BF_NORMAL; //By default autospells should only trigger on normal weapon attacks. + } + + if (!battle_config.autospell_stacking && rate > 0) // Stacking disabled, make a new entry + ; + else { + for (auto &it : spell) { + if ((it.card_id == card_id || it.rate < 0 || rate < 0) && it.id == id && it.lv == lv && it.flag == flag) { + it.rate += rate; return; - rate += spell[i].rate; - break; + } } } - if (i == max) { - ShowWarning("pc_bonus_autospell: Reached max (%d) number of autospells per character!\n", max); - return; - } - spell[i].id = id; - spell[i].lv = lv; - spell[i].rate = rate; - //Auto-update flag value. - if (!(flag&BF_RANGEMASK)) flag|=BF_SHORT|BF_LONG; //No range defined? Use both. - if (!(flag&BF_WEAPONMASK)) flag|=BF_WEAPON; //No attack type defined? Use weapon. - if (!(flag&BF_SKILLMASK)) { - if (flag&(BF_MAGIC|BF_MISC)) flag|=BF_SKILL; //These two would never trigger without BF_SKILL - if (flag&BF_WEAPON) flag|=BF_NORMAL; //By default autospells should only trigger on normal weapon attacks. - } - spell[i].flag|= flag; - spell[i].card_id = card_id; -} -static void pc_bonus_autospell_onskill(struct s_autospell *spell, int max, short src_skill, short id, short lv, short rate, unsigned short card_id) -{ - uint8 i; + struct s_autospell entry; - if( !rate ) - return; + entry.id = id; + entry.lv = lv; + entry.rate = rate; + entry.flag = flag; + entry.card_id = card_id; - for( i = 0; i < max && spell[i].id; i++ ) - { - ; // each autospell works independently - } - - if( i == max ) - { - ShowWarning("pc_bonus_autospell_onskill: Reached max (%d) number of autospells per character!\n", max); - return; - } - - spell[i].flag = src_skill; - spell[i].id = id; - spell[i].lv = lv; - spell[i].rate = rate; - spell[i].card_id = card_id; - return; + spell.push_back(entry); } /** - * Add inflict effect bonus for player while attacking/atatcked - * @param effect Effect array - * @param pmax Max array - * @param sc SC/Effect type - * @param rate Success chance - * @param arrow_rate success chance if bonus comes from arrow-type item - * @param flag Target flag - * @param duration Duration. If 0 use default duration lookup for associated skill with level 7 - **/ -static void pc_bonus_addeff(struct s_addeffect* effect, int pmax, enum sc_type sc, short rate, short arrow_rate, unsigned char flag, unsigned int duration) + * Add auto spell bonus for player while using skills + * @param spell: Spell array + * @param src_skill: Trigger skill + * @param id: Support or target type + * @param lv: Skill level + * @param rate: Success chance + * @param card_id: Used to prevent card stacking + */ +static void pc_bonus_autospell_onskill(std::vector spell, short src_skill, short id, short lv, short rate, unsigned short card_id) { - uint16 i; + if (spell.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus_autospell_onskill: Reached max (%d) number of autospells per character!\n", MAX_PC_BONUS); + return; + } - if (!(flag&(ATF_SHORT|ATF_LONG))) - flag |= ATF_SHORT|ATF_LONG; //Default range: both - if (!(flag&(ATF_TARGET|ATF_SELF))) + if (!rate) + return; + + struct s_autospell entry; + + entry.flag = src_skill; + entry.id = id; + entry.lv = lv; + entry.rate = rate; + entry.card_id = card_id; + + spell.push_back(entry); +} + +/** + * Add inflict effect bonus for player while attacking/attacked + * @param effect: Effect array + * @param sc: SC/Effect type + * @param rate: Success chance + * @param arrow_rate: success chance if bonus comes from arrow-type item + * @param flag: Target flag + * @param duration: Duration. If 0 use default duration lookup for associated skill with level 7 + */ +static void pc_bonus_addeff(std::vector &effect, enum sc_type sc, short rate, short arrow_rate, unsigned char flag, unsigned int duration) +{ + if (effect.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus_addeff: Reached max (%d) number of add effects per character!\n", MAX_PC_BONUS); + return; + } + + if (!(flag&(ATF_SHORT | ATF_LONG))) + flag |= ATF_SHORT | ATF_LONG; //Default range: both + if (!(flag&(ATF_TARGET | ATF_SELF))) flag |= ATF_TARGET; //Default target: enemy. - if (!(flag&(ATF_WEAPON|ATF_MAGIC|ATF_MISC))) + if (!(flag&(ATF_WEAPON | ATF_MAGIC | ATF_MISC))) flag |= ATF_WEAPON; //Default type: weapon. if (!duration) - duration =(unsigned int) skill_get_time2(status_sc2skill(sc),7); + duration = (unsigned int)skill_get_time2(status_sc2skill(sc), 7); - for (i = 0; i < pmax && effect[i].flag; i++) { - if (effect[i].sc == sc && effect[i].flag == flag) { - effect[i].rate += rate; - effect[i].arrow_rate += arrow_rate; - effect[i].duration = umax(effect[i].duration, duration); + for (auto &it : effect) { + if (it.sc == sc && it.flag == flag) { + it.rate += rate; + it.arrow_rate += arrow_rate; + it.duration = umax(it.duration, duration); return; } } - if (i == pmax) { - ShowWarning("pc_bonus_addeff: Reached max (%d) number of add effects per character!\n", pmax); - return; - } - effect[i].sc = sc; - effect[i].rate = rate; - effect[i].arrow_rate = arrow_rate; - effect[i].flag = flag; - effect[i].duration = duration; + + struct s_addeffect entry; + + entry.sc = sc; + entry.rate = rate; + entry.arrow_rate = arrow_rate; + entry.flag = flag; + entry.duration = duration; + + effect.push_back(entry); } /** * Add inflict effect bonus for player while attacking using skill - * @param effect Effect array - * @param pmax Max array - * @param sc SC/Effect type - * @param rate Success chance - * @param flag Target flag - * @param duration Duration. If 0 use default duration lookup for associated skill with level 7 - **/ -static void pc_bonus_addeff_onskill(struct s_addeffectonskill* effect, int pmax, enum sc_type sc, short rate, short skill_id, unsigned char target, unsigned int duration) + * @param effect: Effect array + * @param sc: SC/Effect type + * @param rate: Success chance + * @param skill_id: Skill to cast + * @param target: Target type + * @param duration: Duration. If 0 use default duration lookup for associated skill with level 7 + */ +static void pc_bonus_addeff_onskill(std::vector &effect, enum sc_type sc, short rate, short skill_id, unsigned char target, unsigned int duration) { - uint8 i; + if (effect.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus_addeff_onskill: Reached max (%d) number of add effects per character!\n", MAX_PC_BONUS); + return; + } if (!duration) - duration =(unsigned int) skill_get_time2(status_sc2skill(sc),7); + duration = (unsigned int)skill_get_time2(status_sc2skill(sc), 7); - for( i = 0; i < pmax && effect[i].skill_id; i++ ) { - if( effect[i].sc == sc && effect[i].skill_id == skill_id && effect[i].target == target ) { - effect[i].rate += rate; - effect[i].duration = umax(effect[i].duration, duration); + for (auto &it : effect) { + if (it.sc == sc && it.skill_id == skill_id && it.target == target) { + it.rate += rate; + it.duration = umax(it.duration, duration); return; } } - if( i == pmax ) { - ShowWarning("pc_bonus_addeff_onskill: Reached max (%d) number of add effects on skill per character!\n", pmax); - return; - } - effect[i].sc = sc; - effect[i].rate = rate; - effect[i].skill_id = skill_id; - effect[i].target = target; - effect[i].duration = duration; + + struct s_addeffectonskill entry; + + entry.sc = sc; + entry.rate = rate; + entry.skill_id = skill_id; + entry.target = target; + entry.duration = duration; + + effect.push_back(entry); } -/** Adjust/add drop rate modifier for player -* @param drop: Player's sd->add_drop (struct s_add_drop) -* @param max: Max bonus can be received -* @param nameid: item id that will be dropped -* @param group: group id -* @param class_: target class -* @param race: target race. if < 0, means monster_id -* @param rate: rate value: 1 ~ 10000. If < 0, it will be multiplied with mob level/10 -*/ -static void pc_bonus_item_drop(struct s_add_drop *drop, const short max, unsigned short nameid, uint16 group, int class_, short race, int rate) +/** + * Adjust/add drop rate modifier for player + * @param drop: Player's sd->add_drop (struct s_add_drop) + * @param nameid: item id that will be dropped + * @param group: group id + * @param class_: target class + * @param race: target race. if < 0, means monster_id + * @param rate: rate value: 1 ~ 10000. If < 0, it will be multiplied with mob level/10 + */ +static void pc_bonus_item_drop(std::vector &drop, unsigned short nameid, uint16 group, int class_, short race, int rate) { - uint8 i; - if (!nameid && !group) { ShowWarning("pc_bonus_item_drop: No Item ID nor Item Group ID specified.\n"); return; @@ -2240,6 +2259,11 @@ static void pc_bonus_item_drop(struct s_add_drop *drop, const short max, unsigne return; } + if (drop.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus_item_drop: Reached max (%d) number of added drops per character! (nameid: %hu group: %d class_: %d race: %d rate: %d)\n", MAX_PC_BONUS, nameid, group, class_, race, rate); + return; + } + //Apply config rate adjustment settings. if (rate >= 0) { //Absolute drop. if (battle_config.item_rate_adddrop != 100) @@ -2255,115 +2279,119 @@ static void pc_bonus_item_drop(struct s_add_drop *drop, const short max, unsigne rate = -1; } - //Find match entry, and adjust the rate only - for (i = 0; i < max; i++) { - if (!&drop[i] || (!drop[i].nameid && !drop[i].group)) - continue; - if (drop[i].nameid == nameid && - drop[i].group == group && - drop[i].race == race && - drop[i].class_ == class_ - ) - { - //Adjust the rate if it has same classification - if ((rate < 0 && drop[i].rate < 0) || - (rate > 0 && drop[i].rate > 0)) - { - drop[i].rate += rate; - return; - } + for (auto &it : drop) { + if (it.nameid == nameid && it.group == group && it.race == race && it.class_ == class_) { + if ((rate < 0 && it.rate < 0) || (rate > 0 && it.rate > 0)) //Adjust the rate if it has same classification + it.rate += rate; + return; } } - ARR_FIND(0,max,i,!&drop[i] || (drop[i].nameid == 0 && drop[i].group == 0)); - if (i >= max) { - ShowWarning("pc_bonus_item_drop: Reached max (%d) number of added drops per character! (nameid:%hu group:%d class_:%d race:%d rate:%d)\n",max,nameid,group,class_,race,rate); - return; - } - drop[i].nameid = nameid; - drop[i].group = group; - drop[i].race = race; - drop[i].class_ = class_; - drop[i].rate = rate; + + struct s_add_drop entry; + + entry.nameid = nameid; + entry.group = group; + entry.race = race; + entry.class_ = class_; + entry.rate = rate; + + drop.push_back(entry); } -bool pc_addautobonus(struct s_autobonus *bonus,char max,const char *script,short rate,unsigned int dur,short flag,const char *other_script,unsigned int pos,bool onskill) +/** + * Add autobonus to player when attacking/attacked + * @param bonus: Bonus array + * @param script: Script to execute + * @param rate: Success chance + * @param dur: Duration + * @param flag: Battle flag + * @param other_script: Secondary script to execute + * @param pos: Item equip position + * @param onskill: Skill used to trigger autobonus + * @return True on success or false otherwise + */ +bool pc_addautobonus(std::vector &bonus, const char *script, short rate, unsigned int dur, short flag, const char *other_script, unsigned int pos, bool onskill) { - int i; - - ARR_FIND(0, max, i, bonus[i].rate == 0); - if( i == max ) - { - ShowWarning("pc_addautobonus: Reached max (%d) number of autobonus per character!\n", max); + if (bonus.size() == MAX_PC_BONUS) { + ShowWarning("pc_addautobonus: Reached max (%d) number of autobonus per character!\n", MAX_PC_BONUS); return false; } - if( !onskill ) - { - if( !(flag&BF_RANGEMASK) ) - flag|=BF_SHORT|BF_LONG; //No range defined? Use both. - if( !(flag&BF_WEAPONMASK) ) - flag|=BF_WEAPON; //No attack type defined? Use weapon. - if( !(flag&BF_SKILLMASK) ) - { - if( flag&(BF_MAGIC|BF_MISC) ) - flag|=BF_SKILL; //These two would never trigger without BF_SKILL - if( flag&BF_WEAPON ) - flag|=BF_NORMAL|BF_SKILL; + if (!onskill) { + if (!(flag&BF_RANGEMASK)) + flag |= BF_SHORT | BF_LONG; //No range defined? Use both. + if (!(flag&BF_WEAPONMASK)) + flag |= BF_WEAPON; //No attack type defined? Use weapon. + if (!(flag&BF_SKILLMASK)) { + if (flag&(BF_MAGIC | BF_MISC)) + flag |= BF_SKILL; //These two would never trigger without BF_SKILL + if (flag&BF_WEAPON) + flag |= BF_NORMAL | BF_SKILL; } } - bonus[i].rate = rate; - bonus[i].duration = dur; - bonus[i].active = INVALID_TIMER; - bonus[i].atk_type = flag; - bonus[i].pos = pos; - bonus[i].bonus_script = aStrdup(script); - bonus[i].other_script = other_script?aStrdup(other_script):NULL; + struct s_autobonus entry; + + entry.rate = rate; + entry.duration = dur; + entry.active = INVALID_TIMER; + entry.atk_type = flag; + entry.pos = pos; + entry.bonus_script = aStrdup(script); + entry.other_script = (other_script ? aStrdup(other_script) : NULL); + + bonus.push_back(entry); + return true; } -void pc_delautobonus(struct map_session_data* sd, struct s_autobonus *autobonus,char max,bool restore) +/** + * Remove an autobonus from player + * @param sd: Player data + * @param bonus: Autobonus array + * @param restore: Run script on clearing or not + */ +void pc_delautobonus(struct map_session_data* sd, std::vector &bonus, bool restore) { - int i; if (!sd) return; - for( i = 0; i < max; i++ ) - { - if( autobonus[i].active != INVALID_TIMER ) - { - if( restore && (sd->state.autobonus&autobonus[i].pos) == autobonus[i].pos) - { - if( autobonus[i].bonus_script ) - { - int j; + for (uint8 i = 0; i < bonus.size(); i++) { + if (bonus[i].active != INVALID_TIMER) { + if (restore && (sd->state.autobonus&bonus[i].pos) == bonus[i].pos) { + if (bonus[i].bonus_script) { unsigned int equip_pos_idx = 0; - //Create a list of all equipped positions to see if all items needed for the autobonus are still present [Playtester] - for(j = 0; j < EQI_MAX; j++) { - if(sd->equip_index[j] >= 0) + + // Create a list of all equipped positions to see if all items needed for the autobonus are still present [Playtester] + for (uint8 j = 0; j < EQI_MAX; j++) { + if (sd->equip_index[j] >= 0) equip_pos_idx |= sd->inventory.u.items_inventory[sd->equip_index[j]].equip; } - if((equip_pos_idx&autobonus[i].pos) == autobonus[i].pos) - script_run_autobonus(autobonus[i].bonus_script,sd,autobonus[i].pos); + + if ((equip_pos_idx&bonus[i].pos) == bonus[i].pos) + script_run_autobonus(bonus[i].bonus_script, sd, bonus[i].pos); } continue; - } - else - { // Logout / Unequipped an item with an activated bonus - delete_timer(autobonus[i].active,pc_endautobonus); - autobonus[i].active = INVALID_TIMER; + } else { // Logout / Unequipped an item with an activated bonus + delete_timer(bonus[i].active, pc_endautobonus); + bonus[i].active = INVALID_TIMER; } } - if( autobonus[i].bonus_script ) aFree(autobonus[i].bonus_script); - if( autobonus[i].other_script ) aFree(autobonus[i].other_script); - autobonus[i].bonus_script = autobonus[i].other_script = NULL; - autobonus[i].rate = autobonus[i].atk_type = autobonus[i].duration = autobonus[i].pos = 0; - autobonus[i].active = INVALID_TIMER; + if (bonus[i].bonus_script) + aFree(bonus[i].bonus_script); + if (bonus[i].other_script) + aFree(bonus[i].other_script); } + bonus.clear(); } -void pc_exeautobonus(struct map_session_data *sd,struct s_autobonus *autobonus) +/** + * Execute autobonus on player + * @param sd: Player data + * @param autobonus: Autobonus to run + */ +void pc_exeautobonus(struct map_session_data *sd, struct s_autobonus *autobonus) { if (!sd || !autobonus) return; @@ -2389,6 +2417,9 @@ void pc_exeautobonus(struct map_session_data *sd,struct s_autobonus *autobonus) status_calc_pc(sd,SCO_FORCE); } +/** + * Remove autobonus timer from player + */ TIMER_FUNC(pc_endautobonus){ struct map_session_data *sd = map_id2sd(id); struct s_autobonus *autobonus = (struct s_autobonus *)data; @@ -2402,115 +2433,112 @@ TIMER_FUNC(pc_endautobonus){ return 0; } +/** + * Add element bonus to player when attacking + * @param sd: Player data + * @param ele: Element to adjust + * @param rate: Success chance + * @param flag: Battle flag + */ static void pc_bonus_addele(struct map_session_data* sd, unsigned char ele, short rate, short flag) { - uint8 i; - struct weapon_data* wd; + struct weapon_data *wd = (sd->state.lr_flag ? &sd->left_weapon : &sd->right_weapon); + struct s_addele2 entry; - wd = (sd->state.lr_flag ? &sd->left_weapon : &sd->right_weapon); - - ARR_FIND(0, MAX_PC_BONUS, i, wd->addele2[i].rate == 0); - - if (i == MAX_PC_BONUS) - { - ShowWarning("pc_bonus_addele: Reached max (%d) possible bonuses for this player.\n", MAX_PC_BONUS); + if (wd->addele2.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus_addele: Reached max (%d) number of add element damage bonuses per character!\n", MAX_PC_BONUS); return; } if (!(flag&BF_RANGEMASK)) - flag |= BF_SHORT|BF_LONG; + flag |= BF_SHORT | BF_LONG; if (!(flag&BF_WEAPONMASK)) flag |= BF_WEAPON; - if (!(flag&BF_SKILLMASK)) - { - if (flag&(BF_MAGIC|BF_MISC)) + if (!(flag&BF_SKILLMASK)) { + if (flag&(BF_MAGIC | BF_MISC)) flag |= BF_SKILL; if (flag&BF_WEAPON) - flag |= BF_NORMAL|BF_SKILL; + flag |= BF_NORMAL | BF_SKILL; } - wd->addele2[i].ele = ele; - wd->addele2[i].rate = rate; - wd->addele2[i].flag = flag; + for (auto &it : wd->addele2) { + if (it.ele == ele) { + it.rate += rate; + it.flag = flag; + return; + } + } + + entry.ele = ele; + entry.rate = rate; + entry.flag = flag; + + wd->addele2.push_back(entry); } +/** + * Reduce element bonus to player when attacking + * @param sd: Player data + * @param ele: Element to adjust + * @param rate: Success chance + * @param flag: Battle flag + */ static void pc_bonus_subele(struct map_session_data* sd, unsigned char ele, short rate, short flag) { - uint8 i; + struct s_addele2 entry; - ARR_FIND(0, MAX_PC_BONUS, i, sd->subele2[i].rate == 0); - - if (i == MAX_PC_BONUS) - { - ShowWarning("pc_bonus_subele: Reached max (%d) possible bonuses for this player.\n", MAX_PC_BONUS); + if (sd->subele2.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus_subele: Reached max (%d) number of resist element damage bonuses per character!\n", MAX_PC_BONUS); return; } if (!(flag&BF_RANGEMASK)) - flag |= BF_SHORT|BF_LONG; + flag |= BF_SHORT | BF_LONG; if (!(flag&BF_WEAPONMASK)) flag |= BF_WEAPON; - if (!(flag&BF_SKILLMASK)) - { - if (flag&(BF_MAGIC|BF_MISC)) + if (!(flag&BF_SKILLMASK)) { + if (flag&(BF_MAGIC | BF_MISC)) flag |= BF_SKILL; if (flag&BF_WEAPON) - flag |= BF_NORMAL|BF_SKILL; + flag |= BF_NORMAL | BF_SKILL; } - sd->subele2[i].ele = ele; - sd->subele2[i].rate = rate; - sd->subele2[i].flag = flag; + for (auto &it : sd->subele2) { + if (it.ele == ele) { + it.rate += rate; + it.flag = flag; + return; + } + } + + entry.ele = ele; + entry.rate = rate; + entry.flag = flag; + + sd->subele2.push_back(entry); } -/** Add item group heal rate bonus to player -* @param sd Player -* @param group_id Item Group ID -* @param rate -* @author Cydh -*/ -void pc_itemgrouphealrate(struct map_session_data *sd, uint16 group_id, short rate) { - struct s_pc_itemgrouphealrate *entry; - uint8 i; +/** + * General item bonus for player + * @param bonus: Bonus array + * @param id: Key + * @param val: Value + */ +static void pc_bonus_itembonus(std::vector &bonus, uint16 id, int val) +{ + struct s_item_bonus entry; - for (i = 0; i < sd->itemgrouphealrate_count; i++) { - if (sd->itemgrouphealrate[i]->group_id == group_id) - break; + for (auto &it : bonus) { + if (it.id == id) { + it.val += val; + return; + } } - if (i != sd->itemgrouphealrate_count) { - sd->itemgrouphealrate[i]->rate += rate; - return; - } + entry.id = id; + entry.val = val; - if (i >= UINT8_MAX) { - ShowError("pc_itemgrouphealrate_add: Reached max (%d) possible bonuses for this player %d\n", UINT8_MAX, sd->status.char_id); - return; - } - - entry = ers_alloc(pc_itemgrouphealrate_ers, struct s_pc_itemgrouphealrate); - entry->group_id = group_id; - entry->rate = rate; - - RECREATE(sd->itemgrouphealrate, struct s_pc_itemgrouphealrate *, sd->itemgrouphealrate_count+1); - sd->itemgrouphealrate[sd->itemgrouphealrate_count++] = entry; -} - -/** Clear item group heal rate from player -* @param sd Player -* @author Cydh -*/ -void pc_itemgrouphealrate_clear(struct map_session_data *sd) { - if (!sd || !sd->itemgrouphealrate_count) - return; - else { - uint8 i; - for( i = 0; i < sd->itemgrouphealrate_count; i++ ) - ers_free(pc_itemgrouphealrate_ers, sd->itemgrouphealrate[i]); - sd->itemgrouphealrate_count = 0; - aFree(sd->itemgrouphealrate); - sd->itemgrouphealrate = NULL; - } + bonus.push_back(entry); } /*========================================== @@ -3165,8 +3193,6 @@ void pc_bonus(struct map_session_data *sd,int type,int val) *------------------------------------------*/ void pc_bonus2(struct map_session_data *sd,int type,int type2,int val) { - int i; - nullpo_retv(sd); switch(type){ @@ -3223,23 +3249,22 @@ void pc_bonus2(struct map_session_data *sd,int type,int type2,int val) break; case SP_ADDEFF: // bonus2 bAddEff,eff,n; PC_BONUS_CHK_SC(type2,SP_ADDEFF); - pc_bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2, - sd->state.lr_flag != 2 ? val : 0, sd->state.lr_flag == 2 ? val : 0, 0, 0); + pc_bonus_addeff(sd->addeff, (sc_type)type2, sd->state.lr_flag != 2 ? val : 0, sd->state.lr_flag == 2 ? val : 0, 0, 0); break; case SP_ADDEFF2: // bonus2 bAddEff2,eff,n; PC_BONUS_CHK_SC(type2,SP_ADDEFF2); - pc_bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2, - sd->state.lr_flag != 2 ? val : 0, sd->state.lr_flag == 2 ? val : 0, ATF_SELF, 0); + pc_bonus_addeff(sd->addeff, (sc_type)type2, sd->state.lr_flag != 2 ? val : 0, sd->state.lr_flag == 2 ? val : 0, ATF_SELF, 0); break; case SP_RESEFF: // bonus2 bResEff,eff,n; - if (type2 < SC_COMMON_MIN || type2 > SC_COMMON_MAX) { - ShowError("pc_bonus2: SP_RESEFF: %d is invalid effect.\n", type2); - break; - } if(sd->state.lr_flag == 2) break; - i = sd->reseff[type2]+val; - sd->reseff[type2]= cap_value(i, -10000, 10000); + if (sd->reseff.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus2: SP_RESEFF: Reached max (%d) number of resistance bonuses per character!\n", MAX_PC_BONUS); + break; + } + + val = cap_value(val, -10000, 10000); + pc_bonus_itembonus(sd->reseff, type2, val); break; case SP_MAGIC_ADDELE: // bonus2 bMagicAddEle,e,x; PC_BONUS_CHK_ELEMENT(type2,SP_MAGIC_ADDELE); @@ -3266,75 +3291,46 @@ void pc_bonus2(struct map_session_data *sd,int type,int type2,int val) if(sd->state.lr_flag != 2) sd->magic_atk_ele[type2]+=val; break; - case SP_ADD_DAMAGE_CLASS: // bonus2 bAddDamageClass,mid,x; - switch (sd->state.lr_flag) { - case 0: //Right hand - ARR_FIND(0, ARRAYLENGTH(sd->right_weapon.add_dmg), i, sd->right_weapon.add_dmg[i].rate == 0 || sd->right_weapon.add_dmg[i].class_ == type2); - if (i == ARRAYLENGTH(sd->right_weapon.add_dmg)) - { - ShowError("pc_bonus2: SP_ADD_DAMAGE_CLASS: Reached max (%d) number of add Class dmg bonuses per character!\n", ARRAYLENGTH(sd->right_weapon.add_dmg)); - break; - } - sd->right_weapon.add_dmg[i].class_ = type2; - sd->right_weapon.add_dmg[i].rate += val; - if (!sd->right_weapon.add_dmg[i].rate) //Shift the rest of elements up. - memmove(&sd->right_weapon.add_dmg[i], &sd->right_weapon.add_dmg[i+1], sizeof(sd->right_weapon.add_dmg) - (i+1)*sizeof(sd->right_weapon.add_dmg[0])); - break; - case 1: //Left hand - ARR_FIND(0, ARRAYLENGTH(sd->left_weapon.add_dmg), i, sd->left_weapon.add_dmg[i].rate == 0 || sd->left_weapon.add_dmg[i].class_ == type2); - if (i == ARRAYLENGTH(sd->left_weapon.add_dmg)) - { - ShowError("pc_bonus2: SP_ADD_DAMAGE_CLASS: Reached max (%d) number of add Class dmg bonuses per character!\n", ARRAYLENGTH(sd->left_weapon.add_dmg)); - break; - } - sd->left_weapon.add_dmg[i].class_ = type2; - sd->left_weapon.add_dmg[i].rate += val; - if (!sd->left_weapon.add_dmg[i].rate) //Shift the rest of elements up. - memmove(&sd->left_weapon.add_dmg[i], &sd->left_weapon.add_dmg[i+1], sizeof(sd->left_weapon.add_dmg) - (i+1)*sizeof(sd->left_weapon.add_dmg[0])); + case SP_ADD_DAMAGE_CLASS: { // bonus2 bAddDamageClass,mid,x; + struct weapon_data *wd = (sd->state.lr_flag ? &sd->left_weapon : &sd->right_weapon); + + if (wd->add_dmg.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus2: SP_ADD_DAMAGE_CLASS: Reached max (%d) number of add class damage bonuses per character!\n", MAX_PC_BONUS); break; } + + pc_bonus_itembonus(wd->add_dmg, type2, val); + } break; case SP_ADD_MAGIC_DAMAGE_CLASS: // bonus2 bAddMagicDamageClass,mid,x; if(sd->state.lr_flag == 2) break; - ARR_FIND(0, ARRAYLENGTH(sd->add_mdmg), i, sd->add_mdmg[i].rate == 0 || sd->add_mdmg[i].class_ == type2); - if (i == ARRAYLENGTH(sd->add_mdmg)) - { - ShowError("pc_bonus2: SP_ADD_MAGIC_DAMAGE_CLASS: Reached max (%d) number of add Class magic dmg bonuses per character!\n", ARRAYLENGTH(sd->add_mdmg)); + if (sd->add_mdmg.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus2: SP_ADD_MAGIC_DAMAGE_CLASS: Reached max (%d) number of add class magic dmg bonuses per character!\n", MAX_PC_BONUS); break; } - sd->add_mdmg[i].class_ = type2; - sd->add_mdmg[i].rate += val; - if (!sd->add_mdmg[i].rate) //Shift the rest of elements up. - memmove(&sd->add_mdmg[i], &sd->add_mdmg[i+1], sizeof(sd->add_mdmg) - (i+1)*sizeof(sd->add_mdmg[0])); + + pc_bonus_itembonus(sd->add_mdmg, type2, val); break; case SP_ADD_DEF_MONSTER: // bonus2 bAddDefMonster,mid,x; if(sd->state.lr_flag == 2) break; - ARR_FIND(0, ARRAYLENGTH(sd->add_def), i, sd->add_def[i].rate == 0 || sd->add_def[i].class_ == type2); - if (i == ARRAYLENGTH(sd->add_def)) - { - ShowError("pc_bonus2: SP_ADD_DEF_MONSTER: Reached max (%d) number of add Class def bonuses per character!\n", ARRAYLENGTH(sd->add_def)); + if (sd->add_def.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus2: SP_ADD_DEF_MONSTER: Reached max (%d) number of add class def bonuses per character!\n", MAX_PC_BONUS); break; } - sd->add_def[i].class_ = type2; - sd->add_def[i].rate += val; - if (!sd->add_def[i].rate) //Shift the rest of elements up. - memmove(&sd->add_def[i], &sd->add_def[i+1], sizeof(sd->add_def) - (i+1)*sizeof(sd->add_def[0])); + + pc_bonus_itembonus(sd->add_def, type2, val); break; case SP_ADD_MDEF_MONSTER: // bonus2 bAddMDefMonster,mid,x; if(sd->state.lr_flag == 2) break; - ARR_FIND(0, ARRAYLENGTH(sd->add_mdef), i, sd->add_mdef[i].rate == 0 || sd->add_mdef[i].class_ == type2); - if (i == ARRAYLENGTH(sd->add_mdef)) - { - ShowError("pc_bonus2: SP_ADD_MDEF_MONSTER: Reached max (%d) number of add Class mdef bonuses per character!\n", ARRAYLENGTH(sd->add_mdef)); + if (sd->add_mdef.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus2: SP_ADD_MDEF_MONSTER: Reached max (%d) number of add class mdef bonuses per character!\n", MAX_PC_BONUS); break; } - sd->add_mdef[i].class_ = type2; - sd->add_mdef[i].rate += val; - if (!sd->add_mdef[i].rate) //Shift the rest of elements up. - memmove(&sd->add_mdef[i], &sd->add_mdef[i+1], sizeof(sd->add_mdef) - (i+1)*sizeof(sd->add_mdef[0])); + + pc_bonus_itembonus(sd->add_mdef, type2, val); break; case SP_HP_DRAIN_RATE: // bonus2 bHPDrainRate,x,n; if(!sd->state.lr_flag) { @@ -3417,71 +3413,47 @@ void pc_bonus2(struct map_session_data *sd,int type,int type2,int val) case SP_ADDEFF_WHENHIT: // bonus2 bAddEffWhenHit,eff,n; PC_BONUS_CHK_SC(type2,SP_ADDEFF_WHENHIT); if(sd->state.lr_flag != 2) - pc_bonus_addeff(sd->addeff_atked, ARRAYLENGTH(sd->addeff_atked), (sc_type)type2, val, 0, 0, 0); + pc_bonus_addeff(sd->addeff_atked, (sc_type)type2, val, 0, 0, 0); break; case SP_SKILL_ATK: // bonus2 bSkillAtk,sk,n; if(sd->state.lr_flag == 2) break; - ARR_FIND(0, ARRAYLENGTH(sd->skillatk), i, sd->skillatk[i].id == 0 || sd->skillatk[i].id == type2); - if (i == ARRAYLENGTH(sd->skillatk)) - { //Better mention this so the array length can be updated. [Skotlex] - ShowError("pc_bonus2: SP_SKILL_ATK: Reached max (%d) number of skills per character, bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillatk), type2, val); + if (sd->skillatk.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus2: SP_SKILL_ATK: Reached max (%d) number of skills per character, bonus skill %d (+%d%%) lost.\n", MAX_PC_BONUS, type2, val); break; } - if (sd->skillatk[i].id == type2) - sd->skillatk[i].val += val; - else { - sd->skillatk[i].id = type2; - sd->skillatk[i].val = val; - } + + pc_bonus_itembonus(sd->skillatk, type2, val); break; case SP_SKILL_HEAL: // bonus2 bSkillHeal,sk,n; if(sd->state.lr_flag == 2) break; - ARR_FIND(0, ARRAYLENGTH(sd->skillheal), i, sd->skillheal[i].id == 0 || sd->skillheal[i].id == type2); - if (i == ARRAYLENGTH(sd->skillheal)) - { // Better mention this so the array length can be updated. [Skotlex] - ShowError("pc_bonus2: SP_SKILL_HEAL: Reached max (%d) number of skills per character, bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillheal), type2, val); + if (sd->skillheal.size() == MAX_PC_BONUS) { // Better mention this so the array length can be updated. [Skotlex] + ShowWarning("pc_bonus2: SP_SKILL_HEAL: Reached max (%d) number of skills per character, bonus skill %d (+%d%%) lost.\n", MAX_PC_BONUS, type2, val); break; } - if (sd->skillheal[i].id == type2) - sd->skillheal[i].val += val; - else { - sd->skillheal[i].id = type2; - sd->skillheal[i].val = val; - } + + pc_bonus_itembonus(sd->skillheal, type2, val); break; case SP_SKILL_HEAL2: // bonus2 bSkillHeal2,sk,n; if(sd->state.lr_flag == 2) break; - ARR_FIND(0, ARRAYLENGTH(sd->skillheal2), i, sd->skillheal2[i].id == 0 || sd->skillheal2[i].id == type2); - if (i == ARRAYLENGTH(sd->skillheal2)) - { // Better mention this so the array length can be updated. [Skotlex] - ShowError("pc_bonus2: SP_SKILL_HEAL2: Reached max (%d) number of skills per character, bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillheal2), type2, val); + if (sd->skillheal2.size() == MAX_PC_BONUS) { // Better mention this so the array length can be updated. [Skotlex] + ShowWarning("pc_bonus2: SP_SKILL_HEAL2: Reached max (%d) number of skills per character, bonus skill %d (+%d%%) lost.\n", MAX_PC_BONUS, type2, val); break; } - if (sd->skillheal2[i].id == type2) - sd->skillheal2[i].val += val; - else { - sd->skillheal2[i].id = type2; - sd->skillheal2[i].val = val; - } + + pc_bonus_itembonus(sd->skillheal2, type2, val); break; case SP_ADD_SKILL_BLOW: // bonus2 bAddSkillBlow,sk,n; if(sd->state.lr_flag == 2) break; - ARR_FIND(0, ARRAYLENGTH(sd->skillblown), i, sd->skillblown[i].id == 0 || sd->skillblown[i].id == type2); - if (i == ARRAYLENGTH(sd->skillblown)) - { //Better mention this so the array length can be updated. [Skotlex] - ShowError("pc_bonus2: SP_ADD_SKILL_BLOW: Reached max (%d) number of skills per character, bonus skill %d (%d) lost.\n", ARRAYLENGTH(sd->skillblown), type2, val); + if (sd->skillblown.size() == MAX_PC_BONUS) { //Better mention this so the array length can be updated. [Skotlex] + ShowWarning("pc_bonus2: SP_ADD_SKILL_BLOW: Reached max (%d) number of skills per character, bonus skill %d (%d) lost.\n", MAX_PC_BONUS, type2, val); break; } - if(sd->skillblown[i].id == type2) - sd->skillblown[i].val += val; - else { - sd->skillblown[i].id = type2; - sd->skillblown[i].val = val; - } + + pc_bonus_itembonus(sd->skillblown, type2, val); break; case SP_HP_LOSS_RATE: // bonus2 bHPLossRate,n,t; if(sd->state.lr_flag != 2) { @@ -3528,25 +3500,29 @@ void pc_bonus2(struct map_session_data *sd,int type,int type2,int val) if(sd->state.lr_flag == 2) break; if (!itemdb_exists(type2)) { - ShowError("pc_bonus2: SP_ADD_ITEM_HEAL_RATE Invalid item with id %d\n", type2); + ShowWarning("pc_bonus2: SP_ADD_ITEM_HEAL_RATE Invalid item with id %d\n", type2); break; } - for(i=0; i < ARRAYLENGTH(sd->itemhealrate) && sd->itemhealrate[i].nameid && sd->itemhealrate[i].nameid != type2; i++); - if(i == ARRAYLENGTH(sd->itemhealrate)) { - ShowError("pc_bonus2: SP_ADD_ITEM_HEAL_RATE: Reached max (%d) number of item heal bonuses per character!\n", ARRAYLENGTH(sd->itemhealrate)); + if (sd->itemhealrate.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus2: SP_ADD_ITEM_HEAL_RATE: Reached max (%d) number of item heal bonuses per character!\n", MAX_PC_BONUS); break; } - sd->itemhealrate[i].nameid = type2; - sd->itemhealrate[i].rate += val; + + pc_bonus_itembonus(sd->itemhealrate, type2, val); break; case SP_ADD_ITEMGROUP_HEAL_RATE: // bonus2 bAddItemGroupHealRate,ig,n; if (sd->state.lr_flag == 2) break; if (!type2 || !itemdb_group_exists(type2)) { - ShowError("pc_bonus2: SP_ADD_ITEMGROUP_HEAL_RATE: Invalid item group with id %d\n", type2); + ShowWarning("pc_bonus2: SP_ADD_ITEMGROUP_HEAL_RATE: Invalid item group with id %d\n", type2); break; } - pc_itemgrouphealrate(sd, type2, val); + if (sd->itemhealrate.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus2: SP_ADD_ITEMGROUP_HEAL_RATE: Reached max (%d) number of item heal bonuses per character!\n", MAX_PC_BONUS); + break; + } + + pc_bonus_itembonus(sd->itemgrouphealrate, type2, val); break; case SP_EXP_ADDRACE: // bonus2 bExpAddRace,r,x; PC_BONUS_CHK_RACE(type2,SP_EXP_ADDRACE); @@ -3565,11 +3541,11 @@ void pc_bonus2(struct map_session_data *sd,int type,int type2,int val) break; case SP_ADD_MONSTER_DROP_ITEM: // bonus2 bAddMonsterDropItem,iid,n; if (sd->state.lr_flag != 2) - pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, CLASS_ALL, RC_NONE_, val); + pc_bonus_item_drop(sd->add_drop, type2, 0, CLASS_ALL, RC_NONE_, val); break; case SP_ADD_MONSTER_DROP_ITEMGROUP: // bonus2 bAddMonsterDropItemGroup,ig,n; if (sd->state.lr_flag != 2) - pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), 0, type2, CLASS_ALL, RC_NONE_, val); + pc_bonus_item_drop(sd->add_drop, 0, type2, CLASS_ALL, RC_NONE_, val); break; case SP_SP_LOSS_RATE: // bonus2 bSPLossRate,n,t; if(sd->state.lr_flag != 2) { @@ -3642,114 +3618,74 @@ void pc_bonus2(struct map_session_data *sd,int type,int type2,int val) case SP_SKILL_USE_SP_RATE: // bonus2 bSkillUseSPrate,sk,n; if(sd->state.lr_flag == 2) break; - ARR_FIND(0, ARRAYLENGTH(sd->skillusesprate), i, sd->skillusesprate[i].id == 0 || sd->skillusesprate[i].id == type2); - if (i == ARRAYLENGTH(sd->skillusesprate)) { - ShowError("pc_bonus2: SP_SKILL_USE_SP_RATE: Reached max (%d) number of skills per character, bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillusesprate), type2, val); + if (sd->skillusesprate.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus2: SP_SKILL_USE_SP_RATE: Reached max (%d) number of skills per character, bonus skill %d (+%d%%) lost.\n", MAX_PC_BONUS, type2, val); break; } - if (sd->skillusesprate[i].id == type2) - sd->skillusesprate[i].val += val; - else { - sd->skillusesprate[i].id = type2; - sd->skillusesprate[i].val = val; - } + + pc_bonus_itembonus(sd->skillusesprate, type2, val); break; case SP_SKILL_DELAY: if(sd->state.lr_flag == 2) break; - ARR_FIND(0, ARRAYLENGTH(sd->skilldelay), i, sd->skilldelay[i].id == 0 || sd->skilldelay[i].id == type2); - if (i == ARRAYLENGTH(sd->skilldelay)) { - ShowError("pc_bonus2: SP_SKILL_DELAY: Reached max (%d) number of skills per character, bonus skill %d (%d) lost.\n", ARRAYLENGTH(sd->skilldelay), type2, val); + if (sd->skilldelay.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus2: SP_SKILL_DELAY: Reached max (%d) number of skills per character, bonus skill %d (%d) lost.\n", MAX_PC_BONUS, type2, val); break; } - if (sd->skilldelay[i].id == type2) - sd->skilldelay[i].val += val; - else { - sd->skilldelay[i].id = type2; - sd->skilldelay[i].val = val; - } + + pc_bonus_itembonus(sd->skilldelay, type2, val); break; case SP_SKILL_COOLDOWN: // bonus2 bSkillCooldown,sk,t; if(sd->state.lr_flag == 2) break; - ARR_FIND(0, ARRAYLENGTH(sd->skillcooldown), i, sd->skillcooldown[i].id == 0 || sd->skillcooldown[i].id == type2); - if (i == ARRAYLENGTH(sd->skillcooldown)) - { - ShowError("pc_bonus2: SP_SKILL_COOLDOWN: Reached max (%d) number of skills per character, bonus skill %d (%d) lost.\n", ARRAYLENGTH(sd->skillcooldown), type2, val); + if (sd->skillcooldown.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus2: SP_SKILL_COOLDOWN: Reached max (%d) number of skills per character, bonus skill %d (%d) lost.\n", MAX_PC_BONUS, type2, val); break; } - if (sd->skillcooldown[i].id == type2) - sd->skillcooldown[i].val += val; - else { - sd->skillcooldown[i].id = type2; - sd->skillcooldown[i].val = val; - } + + pc_bonus_itembonus(sd->skillcooldown, type2, val); break; #ifdef RENEWAL_CAST case SP_SKILL_FIXEDCAST: // bonus2 bSkillFixedCast,sk,t; if(sd->state.lr_flag == 2) break; - ARR_FIND(0, ARRAYLENGTH(sd->skillfixcast), i, sd->skillfixcast[i].id == 0 || sd->skillfixcast[i].id == type2); - if (i == ARRAYLENGTH(sd->skillfixcast)) - { - ShowError("pc_bonus2: SP_SKILL_FIXEDCAST: Reached max (%d) number of skills per character, bonus skill %d (%d) lost.\n", ARRAYLENGTH(sd->skillfixcast), type2, val); + if (sd->skillfixcast.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus2: SP_SKILL_FIXEDCAST: Reached max (%d) number of skills per character, bonus skill %d (%d) lost.\n", MAX_PC_BONUS, type2, val); break; } - if (sd->skillfixcast[i].id == type2) - sd->skillfixcast[i].val += val; - else { - sd->skillfixcast[i].id = type2; - sd->skillfixcast[i].val = val; - } + + pc_bonus_itembonus(sd->skillfixcast, type2, val); break; case SP_SKILL_VARIABLECAST: // bonus2 bSkillVariableCast,sk,t; if(sd->state.lr_flag == 2) break; - ARR_FIND(0, ARRAYLENGTH(sd->skillvarcast), i, sd->skillvarcast[i].id == 0 || sd->skillvarcast[i].id == type2); - if (i == ARRAYLENGTH(sd->skillvarcast)) - { - ShowError("pc_bonus2: SP_SKILL_VARIABLECAST: Reached max (%d) number of skills per character, bonus skill %d (%d) lost.\n", ARRAYLENGTH(sd->skillvarcast), type2, val); + if (sd->skillvarcast.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus2: SP_SKILL_VARIABLECAST: Reached max (%d) number of skills per character, bonus skill %d (%d) lost.\n", MAX_PC_BONUS, type2, val); break; } - if (sd->skillvarcast[i].id == type2) - sd->skillvarcast[i].val += val; - else { - sd->skillvarcast[i].id = type2; - sd->skillvarcast[i].val = val; - } + + pc_bonus_itembonus(sd->skillvarcast, type2, val); break; case SP_CASTRATE: // bonus2 bCastrate,sk,n; case SP_VARCASTRATE: // bonus2 bVariableCastrate,sk,n; if(sd->state.lr_flag == 2) break; - ARR_FIND(0, ARRAYLENGTH(sd->skillcastrate), i, sd->skillcastrate[i].id == 0 || sd->skillcastrate[i].id == type2); - if (i == ARRAYLENGTH(sd->skillcastrate)) - { - ShowError("pc_bonus2: SP_VARCASTRATE: Reached max (%d) number of skills per character, bonus skill %d (%d%%) lost.\n",ARRAYLENGTH(sd->skillcastrate), type2, val); + if (sd->skillcastrate.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus2: SP_VARCASTRATE: Reached max (%d) number of skills per character, bonus skill %d (%d%%) lost.\n", MAX_PC_BONUS, type2, val); break; } - if(sd->skillcastrate[i].id == type2) - sd->skillcastrate[i].val -= val; - else { - sd->skillcastrate[i].id = type2; - sd->skillcastrate[i].val -= val; - } + + pc_bonus_itembonus(sd->skillcastrate, type2, -val); // Send inversed value here break; case SP_FIXCASTRATE: // bonus2 bFixedCastrate,sk,n; if(sd->state.lr_flag == 2) break; - ARR_FIND(0, ARRAYLENGTH(sd->skillfixcastrate), i, sd->skillfixcastrate[i].id == 0 || sd->skillfixcastrate[i].id == type2); - if (i == ARRAYLENGTH(sd->skillfixcastrate)) - { - ShowError("pc_bonus2: SP_FIXCASTRATE: Reached max (%d) number of skills per character, bonus skill %d (%d%%) lost.\n", ARRAYLENGTH(sd->skillfixcastrate), type2, val); + if (sd->skillfixcastrate.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus2: SP_FIXCASTRATE: Reached max (%d) number of skills per character, bonus skill %d (%d%%) lost.\n", MAX_PC_BONUS, type2, val); break; } - if(sd->skillfixcastrate[i].id == type2) - sd->skillfixcastrate[i].val -= val; - else { - sd->skillfixcastrate[i].id = type2; - sd->skillfixcastrate[i].val -= val; - } + + pc_bonus_itembonus(sd->skillcastrate, type2, -val); // Send inversed value here break; #else case SP_SKILL_FIXEDCAST: // bonus2 bSkillFixedCast,sk,t; @@ -3761,48 +3697,31 @@ void pc_bonus2(struct map_session_data *sd,int type,int type2,int val) case SP_CASTRATE: // bonus2 bCastrate,sk,n; if(sd->state.lr_flag == 2) break; - ARR_FIND(0, ARRAYLENGTH(sd->skillcastrate), i, sd->skillcastrate[i].id == 0 || sd->skillcastrate[i].id == type2); - if (i == ARRAYLENGTH(sd->skillcastrate)) - { //Better mention this so the array length can be updated. [Skotlex] - ShowError("pc_bonus2: %s: Reached max (%d) number of skills per character, bonus skill %d (%d%%) lost.\n", - (type == SP_CASTRATE) ? "SP_CASTRATE" : "SP_VARCASTRATE", ARRAYLENGTH(sd->skillcastrate), type2, val); + if (sd->skillcastrate.size() == MAX_PC_BONUS) { //Better mention this so the array length can be updated. [Skotlex] + ShowWarning("pc_bonus2: %s: Reached max (%d) number of skills per character, bonus skill %d (%d%%) lost.\n", (type == SP_CASTRATE) ? "SP_CASTRATE" : "SP_VARCASTRATE", MAX_PC_BONUS, type2, val); break; } - if(sd->skillcastrate[i].id == type2) - sd->skillcastrate[i].val += val; - else { - sd->skillcastrate[i].id = type2; - sd->skillcastrate[i].val = val; - } + + pc_bonus_itembonus(sd->skillcastrate, type2, val); break; #endif case SP_SKILL_USE_SP: // bonus2 bSkillUseSP,sk,n; if(sd->state.lr_flag == 2) break; - ARR_FIND(0, ARRAYLENGTH(sd->skillusesp), i, sd->skillusesp[i].id == 0 || sd->skillusesp[i].id == type2); - if (i == ARRAYLENGTH(sd->skillusesp)) { - ShowError("pc_bonus2: SP_SKILL_USE_SP: Reached max (%d) number of skills per character, bonus skill %d (%d) lost.\n", ARRAYLENGTH(sd->skillusesp), type2, val); + if (sd->skillusesp.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus2: SP_SKILL_USE_SP: Reached max (%d) number of skills per character, bonus skill %d (%d) lost.\n", MAX_PC_BONUS, type2, val); break; } - if (sd->skillusesp[i].id == type2) - sd->skillusesp[i].val += val; - else { - sd->skillusesp[i].id = type2; - sd->skillusesp[i].val = val; - } + + pc_bonus_itembonus(sd->skillusesp, type2, val); break; case SP_SUB_SKILL: // bonus2 bSubSkill,sk,n; - ARR_FIND(0, ARRAYLENGTH(sd->subskill), i, sd->subskill[i].id == type2 || sd->subskill[i].id == 0); - if (i == ARRAYLENGTH(sd->subskill)) { - ShowError("pc_bonus2: SP_SUB_SKILL: Reached max (%d) number of skills per character, bonus skill %d (%d) lost.\n", ARRAYLENGTH(sd->subskill), type2, val); + if (sd->subskill.size() == MAX_PC_BONUS) { + ShowWarning("pc_bonus2: SP_SUB_SKILL: Reached max (%d) number of skills per character, bonus skill %d (%d) lost.\n", MAX_PC_BONUS, type2, val); break; } - if (sd->subskill[i].id == type2) - sd->subskill[i].val += val; - else { - sd->subskill[i].id = type2; - sd->subskill[i].val = val; - } + + pc_bonus_itembonus(sd->subskill, type2, val); break; case SP_SUBDEF_ELE: // bonus2 bSubDefEle,e,x; PC_BONUS_CHK_ELEMENT(type2,SP_SUBDEF_ELE); @@ -3869,23 +3788,22 @@ void pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) switch(type){ case SP_ADD_MONSTER_DROP_ITEM: // bonus3 bAddMonsterDropItem,iid,r,n; if(sd->state.lr_flag != 2) - pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, CLASS_NONE, type3, val); + pc_bonus_item_drop(sd->add_drop, type2, 0, CLASS_NONE, type3, val); break; case SP_ADD_MONSTER_ID_DROP_ITEM: // bonus3 bAddMonsterIdDropItem,iid,mid,n; if(sd->state.lr_flag != 2) - pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, CLASS_NONE, -type3, val); + pc_bonus_item_drop(sd->add_drop, type2, 0, CLASS_NONE, -type3, val); break; case SP_ADD_CLASS_DROP_ITEM: // bonus3 bAddClassDropItem,iid,c,n; if(sd->state.lr_flag != 2) - pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, type3, RC_NONE_, val); + pc_bonus_item_drop(sd->add_drop, type2, 0, type3, RC_NONE_, val); break; case SP_AUTOSPELL: // bonus3 bAutoSpell,sk,y,n; if(sd->state.lr_flag != 2) { int target = skill_get_inf(type2); //Support or Self (non-auto-target) skills should pick self. target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill_get_inf2(type2)&INF2_NO_TARGET_SELF)); - pc_bonus_autospell(sd->autospell, ARRAYLENGTH(sd->autospell), - target?-type2:type2, type3, val, 0, current_equip_card_id); + pc_bonus_autospell(sd->autospell, target?-type2:type2, type3, val, 0, current_equip_card_id); } break; case SP_AUTOSPELL_WHENHIT: // bonus3 bAutoSpellWhenHit,sk,y,n; @@ -3893,35 +3811,33 @@ void pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) { int target = skill_get_inf(type2); //Support or Self (non-auto-target) skills should pick self. target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill_get_inf2(type2)&INF2_NO_TARGET_SELF)); - pc_bonus_autospell(sd->autospell2, ARRAYLENGTH(sd->autospell2), - target?-type2:type2, type3, val, BF_NORMAL|BF_SKILL, current_equip_card_id); + pc_bonus_autospell(sd->autospell2, target?-type2:type2, type3, val, BF_NORMAL|BF_SKILL, current_equip_card_id); } break; case SP_ADD_MONSTER_DROP_ITEMGROUP: // bonus3 bAddMonsterDropItemGroup,ig,r,n; if (sd->state.lr_flag != 2) - pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), 0, type2, CLASS_NONE, type3, val); + pc_bonus_item_drop(sd->add_drop, 0, type2, CLASS_NONE, type3, val); break; case SP_ADD_CLASS_DROP_ITEMGROUP: // bonus3 bAddClassDropItemGroup,ig,c,n; if (sd->state.lr_flag != 2) - pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), 0, type2, type3, RC_NONE_, val); + pc_bonus_item_drop(sd->add_drop, 0, type2, type3, RC_NONE_, val); break; case SP_ADDEFF: // bonus3 bAddEff,eff,n,y; PC_BONUS_CHK_SC(type2,SP_ADDEFF); - pc_bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2, - sd->state.lr_flag != 2 ? type3 : 0, sd->state.lr_flag == 2 ? type3 : 0, val, 0); + pc_bonus_addeff(sd->addeff, (sc_type)type2, sd->state.lr_flag != 2 ? type3 : 0, sd->state.lr_flag == 2 ? type3 : 0, val, 0); break; case SP_ADDEFF_WHENHIT: // bonus3 bAddEffWhenHit,eff,n,y; PC_BONUS_CHK_SC(type2,SP_ADDEFF_WHENHIT); if(sd->state.lr_flag != 2) - pc_bonus_addeff(sd->addeff_atked, ARRAYLENGTH(sd->addeff_atked), (sc_type)type2, type3, 0, val, 0); + pc_bonus_addeff(sd->addeff_atked, (sc_type)type2, type3, 0, val, 0); break; case SP_ADDEFF_ONSKILL: // bonus3 bAddEffOnSkill,sk,eff,n; PC_BONUS_CHK_SC(type2,SP_ADDEFF_ONSKILL); if( sd->state.lr_flag != 2 ) - pc_bonus_addeff_onskill(sd->addeff_onskill, ARRAYLENGTH(sd->addeff_onskill), (sc_type)type3, val, type2, ATF_TARGET, 0); + pc_bonus_addeff_onskill(sd->addeff_onskill, (sc_type)type3, val, type2, ATF_TARGET, 0); break; case SP_ADDELE: // bonus3 bAddEle,e,x,bf; @@ -3996,12 +3912,12 @@ void pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type switch(type){ case SP_AUTOSPELL: // bonus4 bAutoSpell,sk,y,n,i; if(sd->state.lr_flag != 2) - pc_bonus_autospell(sd->autospell, ARRAYLENGTH(sd->autospell), (val&1?type2:-type2), (val&2?-type3:type3), type4, 0, current_equip_card_id); + pc_bonus_autospell(sd->autospell, (val&1?type2:-type2), (val&2?-type3:type3), type4, 0, current_equip_card_id); break; case SP_AUTOSPELL_WHENHIT: // bonus4 bAutoSpellWhenHit,sk,y,n,i; if(sd->state.lr_flag != 2) - pc_bonus_autospell(sd->autospell2, ARRAYLENGTH(sd->autospell2), (val&1?type2:-type2), (val&2?-type3:type3), type4, BF_NORMAL|BF_SKILL, current_equip_card_id); + pc_bonus_autospell(sd->autospell2, (val&1?type2:-type2), (val&2?-type3:type3), type4, BF_NORMAL|BF_SKILL, current_equip_card_id); break; case SP_AUTOSPELL_ONSKILL: // bonus4 bAutoSpellOnSkill,sk,x,y,n; @@ -4010,26 +3926,25 @@ void pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type int target = skill_get_inf(type3); //Support or Self (non-auto-target) skills should pick self. target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill_get_inf2(type3)&INF2_NO_TARGET_SELF)); - pc_bonus_autospell_onskill(sd->autospell3, ARRAYLENGTH(sd->autospell3), type2, target?-type3:type3, type4, val, current_equip_card_id); + pc_bonus_autospell_onskill(sd->autospell3, type2, target?-type3:type3, type4, val, current_equip_card_id); } break; case SP_ADDEFF: // bonus4 bAddEff,eff,n,y,t; PC_BONUS_CHK_SC(type2,SP_ADDEFF); - pc_bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2, - sd->state.lr_flag != 2 ? type3 : 0, sd->state.lr_flag == 2 ? type3 : 0, type4, val); + pc_bonus_addeff(sd->addeff, (sc_type)type2, sd->state.lr_flag != 2 ? type3 : 0, sd->state.lr_flag == 2 ? type3 : 0, type4, val); break; case SP_ADDEFF_WHENHIT: // bonus4 bAddEffWhenHit,eff,n,y,t; PC_BONUS_CHK_SC(type2,SP_ADDEFF_WHENHIT); if (sd->state.lr_flag != 2) - pc_bonus_addeff(sd->addeff_atked, ARRAYLENGTH(sd->addeff_atked), (sc_type)type2, type3, 0, type4, val); + pc_bonus_addeff(sd->addeff_atked, (sc_type)type2, type3, 0, type4, val); break; case SP_ADDEFF_ONSKILL: // bonus4 bAddEffOnSkill,sk,eff,n,y; PC_BONUS_CHK_SC(type3,SP_ADDEFF_ONSKILL); if( sd->state.lr_flag != 2 ) - pc_bonus_addeff_onskill(sd->addeff_onskill, ARRAYLENGTH(sd->addeff_onskill), (sc_type)type3, type4, type2, val, 0); + pc_bonus_addeff_onskill(sd->addeff_onskill, (sc_type)type3, type4, type2, val, 0); break; case SP_SET_DEF_RACE: // bonus4 bSetDefRace,r,n,t,y; @@ -4083,23 +3998,23 @@ void pc_bonus5(struct map_session_data *sd,int type,int type2,int type3,int type switch(type){ case SP_AUTOSPELL: // bonus5 bAutoSpell,sk,y,n,bf,i; if(sd->state.lr_flag != 2) - pc_bonus_autospell(sd->autospell, ARRAYLENGTH(sd->autospell), (val&1?type2:-type2), (val&2?-type3:type3), type4, type5, current_equip_card_id); + pc_bonus_autospell(sd->autospell, (val&1?type2:-type2), (val&2?-type3:type3), type4, type5, current_equip_card_id); break; case SP_AUTOSPELL_WHENHIT: // bonus5 bAutoSpellWhenHit,sk,y,n,bf,i; if(sd->state.lr_flag != 2) - pc_bonus_autospell(sd->autospell2, ARRAYLENGTH(sd->autospell2), (val&1?type2:-type2), (val&2?-type3:type3), type4, type5, current_equip_card_id); + pc_bonus_autospell(sd->autospell2, (val&1?type2:-type2), (val&2?-type3:type3), type4, type5, current_equip_card_id); break; case SP_AUTOSPELL_ONSKILL: // bonus5 bAutoSpellOnSkill,sk,x,y,n,i; if(sd->state.lr_flag != 2) - pc_bonus_autospell_onskill(sd->autospell3, ARRAYLENGTH(sd->autospell3), type2, (val&1?-type3:type3), (val&2?-type4:type4), type5, current_equip_card_id); + pc_bonus_autospell_onskill(sd->autospell3, type2, (val&1?-type3:type3), (val&2?-type4:type4), type5, current_equip_card_id); break; case SP_ADDEFF_ONSKILL: // bonus5 bAddEffOnSkill,sk,eff,n,y,t; PC_BONUS_CHK_SC(type3,SP_ADDEFF_ONSKILL); if( sd->state.lr_flag != 2 ) - pc_bonus_addeff_onskill(sd->addeff_onskill, ARRAYLENGTH(sd->addeff_onskill), (sc_type)type3, type4, type2, type5, val); + pc_bonus_addeff_onskill(sd->addeff_onskill, (sc_type)type3, type4, type2, type5, val); break; default: @@ -5774,9 +5689,8 @@ bool pc_memo(struct map_session_data* sd, int pos) * @return player skill cooldown */ int pc_get_skillcooldown(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv) { - uint8 i; uint16 idx = skill_get_index(skill_id); - int cooldown = 0, cooldownlen = ARRAYLENGTH(sd->skillcooldown); + int cooldown = 0; if (!idx) return 0; if (skill_db[idx]->cooldown[skill_lv - 1]) @@ -5784,10 +5698,12 @@ int pc_get_skillcooldown(struct map_session_data *sd, uint16 skill_id, uint16 sk if (skill_id == SU_TUNABELLY && pc_checkskill(sd, SU_SPIRITOFSEA)) cooldown -= skill_get_time(SU_TUNABELLY, skill_lv); - ARR_FIND(0, cooldownlen, i, sd->skillcooldown[i].id == skill_id); - if (i < cooldownlen) { - cooldown += sd->skillcooldown[i].val; - cooldown = max(0,cooldown); + for (auto &it : sd->skillcooldown) { + if (it.id == skill_id) { + cooldown += it.val; + cooldown = max(0, cooldown); + break; + } } return cooldown; } @@ -7563,34 +7479,44 @@ int pc_resethate(struct map_session_data* sd) int pc_skillatk_bonus(struct map_session_data *sd, uint16 skill_id) { - int i, bonus = 0; + int bonus = 0; + nullpo_ret(sd); skill_id = skill_dummy2skill_id(skill_id); - ARR_FIND(0, ARRAYLENGTH(sd->skillatk), i, sd->skillatk[i].id == skill_id); - if( i < ARRAYLENGTH(sd->skillatk) ) - bonus = sd->skillatk[i].val; + for (auto &it : sd->skillatk) { + if (it.id == skill_id) { + bonus += it.val; + break; + } + } return bonus; } int pc_sub_skillatk_bonus(struct map_session_data *sd, uint16 skill_id) { - int i, bonus = 0; + int bonus = 0; + nullpo_ret(sd); skill_id = skill_dummy2skill_id(skill_id); - ARR_FIND(0, ARRAYLENGTH(sd->subskill), i, sd->subskill[i].id == skill_id); - if( i < ARRAYLENGTH(sd->subskill) ) - bonus = sd->subskill[i].val; + for (auto &it : sd->subskill) { + if (it.id == skill_id) { + bonus += it.val; + break; + } + } return bonus; } int pc_skillheal_bonus(struct map_session_data *sd, uint16 skill_id) { - int i, bonus = sd->bonus.add_heal_rate; + int bonus = sd->bonus.add_heal_rate; + + nullpo_ret(sd); skill_id = skill_dummy2skill_id(skill_id); @@ -7604,23 +7530,27 @@ int pc_skillheal_bonus(struct map_session_data *sd, uint16 skill_id) { } } - ARR_FIND(0, ARRAYLENGTH(sd->skillheal), i, sd->skillheal[i].id == skill_id); - - if( i < ARRAYLENGTH(sd->skillheal) ) - bonus += sd->skillheal[i].val; + for (auto &it : sd->skillheal) { + if (it.id == skill_id) { + bonus += it.val; + break; + } + } return bonus; } int pc_skillheal2_bonus(struct map_session_data *sd, uint16 skill_id) { - int i, bonus = sd->bonus.add_heal2_rate; + int bonus = sd->bonus.add_heal2_rate; skill_id = skill_dummy2skill_id(skill_id); - ARR_FIND(0, ARRAYLENGTH(sd->skillheal2), i, sd->skillheal2[i].id == skill_id); - - if( i < ARRAYLENGTH(sd->skillheal2) ) - bonus += sd->skillheal2[i].val; + for (auto &it : sd->skillheal2) { + if (it.id == skill_id) { + bonus += it.val; + break; + } + } return bonus; } @@ -8485,8 +8415,6 @@ int pc_itemheal(struct map_session_data *sd, int itemid, int hp, int sp) int bonus, tmp, penalty = 0; if (hp) { - int i; - bonus = 100 + (sd->battle_status.vit << 1) + pc_checkskill(sd, SM_RECOVERY) * 10 + pc_checkskill(sd, AM_LEARNINGPOTION) * 5; // A potion produced by an Alchemist in the Fame Top 10 gets +50% effect [DracoRPG] if (potion_flag == 2) { @@ -8499,9 +8427,9 @@ int pc_itemheal(struct map_session_data *sd, int itemid, int hp, int sp) //Item Group bonuses bonus += pc_get_itemgroup_bonus(sd, itemid); //Individual item bonuses. - for(i = 0; i < ARRAYLENGTH(sd->itemhealrate) && sd->itemhealrate[i].nameid; i++) { - if (sd->itemhealrate[i].nameid == itemid) { - bonus += sd->itemhealrate[i].rate; + for(const auto &it : sd->itemhealrate) { + if (it.id == itemid) { + bonus += it.val; break; } } @@ -12267,20 +12195,21 @@ short pc_maxaspd(struct map_session_data *sd) { * @return Heal rate **/ short pc_get_itemgroup_bonus(struct map_session_data* sd, unsigned short nameid) { - short bonus = 0; - uint8 i; + if (sd->itemgrouphealrate.empty()) + return 0; - if (!sd->itemgrouphealrate_count) - return bonus; - for (i = 0; i < sd->itemgrouphealrate_count; i++) { - uint16 group_id = sd->itemgrouphealrate[i]->group_id, j; + short bonus = 0; + + for (const auto &it : sd->itemgrouphealrate) { + uint16 group_id = it.id, i; struct s_item_group_db *group = NULL; + if (!group_id || !(group = itemdb_group_exists(group_id))) continue; - for (j = 0; j < group->random[0].data_qty; j++) { - if (group->random[0].data[j].nameid == nameid) { - bonus += sd->itemgrouphealrate[i]->rate; + for (i = 0; i < group->random[0].data_qty; i++) { + if (group->random[0].data[i].nameid == nameid) { + bonus += it.val; break; } } @@ -12295,16 +12224,14 @@ short pc_get_itemgroup_bonus(struct map_session_data* sd, unsigned short nameid) * @return Heal rate **/ short pc_get_itemgroup_bonus_group(struct map_session_data* sd, uint16 group_id) { - short bonus = 0; - uint8 i; + if (sd->itemgrouphealrate.empty()) + return 0; - if (!sd->itemgrouphealrate_count) - return bonus; - for (i = 0; i < sd->itemgrouphealrate_count; i++) { - if (sd->itemgrouphealrate[i]->group_id == group_id) - return sd->itemgrouphealrate[i]->rate; + for (const auto &it : sd->itemgrouphealrate) { + if (it.id == group_id) + return it.val; } - return bonus; + return 0; } /** @@ -12878,7 +12805,6 @@ void do_final_pc(void) { do_final_pc_groups(); ers_destroy(pc_sc_display_ers); - ers_destroy(pc_itemgrouphealrate_ers); ers_destroy(num_reg_ers); ers_destroy(str_reg_ers); @@ -12925,7 +12851,6 @@ void do_init_pc(void) { do_init_pc_groups(); pc_sc_display_ers = ers_new(sizeof(struct sc_display_entry), "pc.cpp:pc_sc_display_ers", ERS_OPT_FLEX_CHUNK); - pc_itemgrouphealrate_ers = ers_new(sizeof(struct s_pc_itemgrouphealrate), "pc.cpp:pc_itemgrouphealrate_ers", ERS_OPT_NONE); num_reg_ers = ers_new(sizeof(struct script_reg_num), "pc.cpp:num_reg_ers", (ERSOptions)(ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK)); str_reg_ers = ers_new(sizeof(struct script_reg_str), "pc.cpp:str_reg_ers", (ERSOptions)(ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK)); diff --git a/src/map/pc.hpp b/src/map/pc.hpp index 6b61fd3c0e..e51d999d71 100644 --- a/src/map/pc.hpp +++ b/src/map/pc.hpp @@ -26,7 +26,7 @@ enum AtCommandType : uint8; enum e_log_pick_type : uint32; enum sc_type : int16; -#define MAX_PC_BONUS 10 /// Max bonus, usually used by item bonus +#define MAX_PC_BONUS 50 /// Max bonus, usually used by item bonus #define MAX_PC_SKILL_REQUIRE 5 /// Max skill tree requirement #define MAX_PC_FEELHATE 3 /// Max feel hate info #define DAMAGELOG_SIZE_PC 100 /// Damage log @@ -92,10 +92,41 @@ enum prevent_logout_trigger { PLT_DAMAGE = 8 }; +struct skill_cooldown_entry { + unsigned short skill_id; + int timer; +}; + +#ifdef VIP_ENABLE +struct vip_info { + unsigned int enabled : 1; + time_t time; + bool disableshowrate; //State to disable clif_display_pinfo(). [Cydh] +}; +#endif + +enum npc_timeout_type { + NPCT_INPUT = 0, + NPCT_MENU = 1, + NPCT_WAIT = 2, +}; + extern unsigned int equip_bitmask[EQI_MAX]; #define equip_index_check(i) ( (i) >= EQI_ACC_L && (i) < EQI_MAX ) +/// Miscellaneous item bonus struct +struct s_item_bonus { + uint16 id; + int val; +}; + +/// AddEle bonus struct +struct s_addele2 { + short flag, rate; + unsigned char ele; +}; + struct weapon_data { int atkmods[3]; // all the variables except atkmods get zero'ed in each call of status_calc_pc @@ -124,16 +155,11 @@ struct weapon_data { short per; ///< Drain value/rate per attack } hp_drain_rate, sp_drain_rate; - struct { - short class_, rate; - } add_dmg[MAX_PC_BONUS]; - - struct { - short flag, rate; - unsigned char ele; - } addele2[MAX_PC_BONUS]; + std::vector add_dmg; + std::vector addele2; }; +/// AutoSpell bonus struct struct s_autospell { short id, lv, rate, flag; unsigned short card_id; @@ -164,9 +190,10 @@ struct s_add_drop { group; ///Group ID int rate; ///Rate, 1 ~ 10000, -1 ~ -100000 short race; ///Target Race, bitwise value of 1< autospell, autospell2, autospell3; + std::vector addeff, addeff_atked; + std::vector addeff_onskill; + std::vector skillatk, skillusesprate, skillusesp, skillheal, skillheal2, skillblown, skillcastrate, skillfixcastrate, subskill, skillcooldown, skillfixcast, + skillvarcast, skilldelay, itemhealrate, add_def, add_mdef, add_mdmg, reseff, itemgrouphealrate; + std::vector add_drop; + std::vector subele2; + std::vector autobonus, autobonus2, autobonus3; //Auto script on attack, when attacked, on skill usage - struct s_skill_bonus { //skillatk raises bonus dmg% of skills, skillheal increases heal%, skillblown increases bonus blewcount for some skills. - unsigned short id; - short val; - } skillatk[MAX_PC_BONUS], skillusesprate[MAX_PC_BONUS], skillusesp[MAX_PC_BONUS], skillheal[MAX_PC_BONUS], - skillheal2[MAX_PC_BONUS], skillblown[MAX_PC_BONUS], skillcastrate[MAX_PC_BONUS], - skillfixcastrate[MAX_PC_BONUS], subskill[MAX_PC_BONUS]; - struct s_skill_bonus_i32 { - uint16 id; - int32 val; - } skillcooldown[MAX_PC_BONUS], skillfixcast[MAX_PC_BONUS], skillvarcast[MAX_PC_BONUS], skilldelay[MAX_PC_BONUS]; + // zeroed structures start here struct s_regen { short value; int rate; int tick; } hp_loss, sp_loss, hp_regen, sp_regen, percent_hp_regen, percent_sp_regen; - struct { - short class_, rate; - } add_def[MAX_PC_BONUS], add_mdef[MAX_PC_BONUS], add_mdmg[MAX_PC_BONUS]; - struct s_add_drop add_drop[MAX_PC_BONUS]; - struct s_healrate { - unsigned short nameid; - int rate; - } itemhealrate[MAX_PC_BONUS]; - struct s_subele2 { - short flag, rate; - unsigned char ele; - } subele2[MAX_PC_BONUS]; struct { short value; int rate, tick; @@ -452,10 +443,6 @@ struct map_session_data { } hp_vanish_race[RC_MAX], sp_vanish_race[RC_MAX]; // zeroed structures end here - // manually zeroed structures start here. - struct s_autobonus autobonus[MAX_PC_BONUS], autobonus2[MAX_PC_BONUS], autobonus3[MAX_PC_BONUS]; //Auto script on attack, when attacked, on skill usage - // manually zeroed structures end here. - // zeroed vars start here. struct s_bonus { int hp, sp; @@ -707,9 +694,6 @@ struct map_session_data { uint16 count; } bonus_script; - struct s_pc_itemgrouphealrate **itemgrouphealrate; /// List of Item Group Heal rate bonus - uint8 itemgrouphealrate_count; /// Number of rate bonuses - /* Expiration Timer ID */ int expiration_tid; time_t expiration_time; @@ -745,7 +729,6 @@ struct map_session_data { }; extern struct eri *pc_sc_display_ers; /// Player's SC display table -extern struct eri *pc_itemgrouphealrate_ers; /// Player's Item Group Heal Rate table /** * ERS for the bulk of pc vars @@ -1084,10 +1067,10 @@ bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd, void pc_updateweightstatus(struct map_session_data *sd); -bool pc_addautobonus(struct s_autobonus *bonus,char max,const char *script,short rate,unsigned int dur,short atk_type,const char *o_script,unsigned int pos,bool onskill); -void pc_exeautobonus(struct map_session_data* sd,struct s_autobonus *bonus); +bool pc_addautobonus(std::vector &bonus, const char *script, short rate, unsigned int dur, short atk_type, const char *o_script, unsigned int pos, bool onskill); +void pc_exeautobonus(struct map_session_data* sd, struct s_autobonus *bonus); TIMER_FUNC(pc_endautobonus); -void pc_delautobonus(struct map_session_data* sd,struct s_autobonus *bonus,char max,bool restore); +void pc_delautobonus(struct map_session_data* sd, std::vector &bonus, bool restore); void pc_bonus(struct map_session_data *sd, int type, int val); void pc_bonus2(struct map_session_data *sd, int type, int type2, int val); @@ -1320,7 +1303,6 @@ void pc_bonus_script_clear(struct map_session_data *sd, uint16 flag); void pc_cell_basilica(struct map_session_data *sd); -void pc_itemgrouphealrate_clear(struct map_session_data *sd); short pc_get_itemgroup_bonus(struct map_session_data* sd, unsigned short nameid); short pc_get_itemgroup_bonus_group(struct map_session_data* sd, uint16 group_id); diff --git a/src/map/script.cpp b/src/map/script.cpp index 40c5639a37..46c337293f 100644 --- a/src/map/script.cpp +++ b/src/map/script.cpp @@ -9268,8 +9268,7 @@ BUILDIN_FUNC(autobonus) if( script_hasdata(st,6) ) other_script = script_getstr(st,6); - if( pc_addautobonus(sd->autobonus,ARRAYLENGTH(sd->autobonus), - bonus_script,rate,dur,atk_type,other_script,pos,false) ) + if( pc_addautobonus(sd->autobonus, bonus_script, rate, dur, atk_type, other_script, pos, false) ) { script_add_autobonus(bonus_script); if( other_script ) @@ -9309,8 +9308,7 @@ BUILDIN_FUNC(autobonus2) if( script_hasdata(st,6) ) other_script = script_getstr(st,6); - if( pc_addautobonus(sd->autobonus2,ARRAYLENGTH(sd->autobonus2), - bonus_script,rate,dur,atk_type,other_script,pos,false) ) + if( pc_addautobonus(sd->autobonus2, bonus_script, rate,dur, atk_type, other_script, pos, false) ) { script_add_autobonus(bonus_script); if( other_script ) @@ -9351,8 +9349,7 @@ BUILDIN_FUNC(autobonus3) if( script_hasdata(st,6) ) other_script = script_getstr(st,6); - if( pc_addautobonus(sd->autobonus3,ARRAYLENGTH(sd->autobonus3), - bonus_script,rate,dur,atk_type,other_script,pos,true) ) + if( pc_addautobonus(sd->autobonus3, bonus_script, rate, dur, atk_type, other_script, pos, true) ) { script_add_autobonus(bonus_script); if( other_script ) diff --git a/src/map/skill.cpp b/src/map/skill.cpp index e897faf770..68efd22d66 100755 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -1108,39 +1108,39 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 if( skill_id != WS_CARTTERMINATION && skill_id != AM_DEMONSTRATION && skill_id != CR_REFLECTSHIELD && skill_id != MS_REFLECTSHIELD && skill_id != ASC_BREAKER ) { // Trigger status effects enum sc_type type; - uint8 i; - unsigned int time = 0; - for( i = 0; i < ARRAYLENGTH(sd->addeff) && sd->addeff[i].flag; i++ ) { - rate = sd->addeff[i].rate; + unsigned int time; + + for (const auto &it : sd->addeff) { + rate = it.rate; if( attack_type&BF_LONG ) // Any ranged physical attack takes status arrows into account (Grimtooth...) [DracoRPG] - rate += sd->addeff[i].arrow_rate; + rate += it.arrow_rate; if( !rate ) continue; - if( (sd->addeff[i].flag&(ATF_WEAPON|ATF_MAGIC|ATF_MISC)) != (ATF_WEAPON|ATF_MAGIC|ATF_MISC) ) { + if ((it.flag&(ATF_WEAPON|ATF_MAGIC|ATF_MISC)) != (ATF_WEAPON|ATF_MAGIC|ATF_MISC)) { // Trigger has attack type consideration. - if( (sd->addeff[i].flag&ATF_WEAPON && attack_type&BF_WEAPON) || - (sd->addeff[i].flag&ATF_MAGIC && attack_type&BF_MAGIC) || - (sd->addeff[i].flag&ATF_MISC && attack_type&BF_MISC) ) + if ((it.flag&ATF_WEAPON && attack_type&BF_WEAPON) || + (it.flag&ATF_MAGIC && attack_type&BF_MAGIC) || + (it.flag&ATF_MISC && attack_type&BF_MISC)) ; else continue; } - if( (sd->addeff[i].flag&(ATF_LONG|ATF_SHORT)) != (ATF_LONG|ATF_SHORT) ) { + if ((it.flag&(ATF_LONG|ATF_SHORT)) != (ATF_LONG|ATF_SHORT)) { // Trigger has range consideration. - if((sd->addeff[i].flag&ATF_LONG && !(attack_type&BF_LONG)) || - (sd->addeff[i].flag&ATF_SHORT && !(attack_type&BF_SHORT))) + if ((it.flag&ATF_LONG && !(attack_type&BF_LONG)) || + (it.flag&ATF_SHORT && !(attack_type&BF_SHORT))) continue; //Range Failed. } - type = sd->addeff[i].sc; - time = sd->addeff[i].duration; + type = it.sc; + time = it.duration; - if (sd->addeff[i].flag&ATF_TARGET) + if (it.flag&ATF_TARGET) status_change_start(src,bl,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,time,SCSTART_NONE); - if (sd->addeff[i].flag&ATF_SELF) + if (it.flag&ATF_SELF) status_change_start(src,src,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,time,SCSTART_NONE); } } @@ -1148,18 +1148,18 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 if( skill_id ) { // Trigger status effects on skills enum sc_type type; - uint8 i; - unsigned int time = 0; - for( i = 0; i < ARRAYLENGTH(sd->addeff_onskill) && sd->addeff_onskill[i].skill_id; i++ ) { - if( skill_id != sd->addeff_onskill[i].skill_id || !sd->addeff_onskill[i].rate ) - continue; - type = sd->addeff_onskill[i].sc; - time = sd->addeff_onskill[i].duration; + unsigned int time; - if( sd->addeff_onskill[i].target&ATF_TARGET ) - status_change_start(src,bl,type,sd->addeff_onskill[i].rate,7,0,0,0,time,SCSTART_NONE); - if( sd->addeff_onskill[i].target&ATF_SELF ) - status_change_start(src,src,type,sd->addeff_onskill[i].rate,7,0,0,0,time,SCSTART_NONE); + for (const auto &it : sd->addeff_onskill) { + if (skill_id != it.skill_id || !it.rate) + continue; + type = it.sc; + time = it.duration; + + if (it.target&ATF_TARGET) + status_change_start(src,bl,type,it.rate,7,0,0,0,time,SCSTART_NONE); + if (it.target&ATF_SELF) + status_change_start(src,src,type,it.rate,7,0,0,0,time,SCSTART_NONE); } //"While the damage can be blocked by Pneuma, the chance to break armor remains", irowiki. [Cydh] if (dmg_lv == ATK_BLOCK && skill_id == AM_ACIDTERROR) { @@ -2075,20 +2075,19 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 } // Autospell when attacking - if( sd && !status_isdead(bl) && sd->autospell[0].id ) + if( sd && !status_isdead(bl) && !sd->autospell.empty() ) { struct block_list *tbl; struct unit_data *ud; - int i, autospl_skill_lv, type; + int autospl_skill_lv, type; - for (i = 0; i < ARRAYLENGTH(sd->autospell) && sd->autospell[i].id; i++) { - - if(!( ((sd->autospell[i].flag)&attack_type)&BF_WEAPONMASK && - ((sd->autospell[i].flag)&attack_type)&BF_RANGEMASK && - ((sd->autospell[i].flag)&attack_type)&BF_SKILLMASK)) + for (const auto &it : sd->autospell) { + if (!(((it.flag)&attack_type)&BF_WEAPONMASK && + ((it.flag)&attack_type)&BF_RANGEMASK && + ((it.flag)&attack_type)&BF_SKILLMASK)) continue; // one or more trigger conditions were not fulfilled - skill = (sd->autospell[i].id > 0) ? sd->autospell[i].id : -sd->autospell[i].id; + skill = (it.id > 0) ? it.id : -it.id; sd->state.autocast = 1; if ( skill_isNotOk(skill, sd) ) { @@ -2097,15 +2096,15 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 } sd->state.autocast = 0; - autospl_skill_lv = sd->autospell[i].lv?sd->autospell[i].lv:1; + autospl_skill_lv = it.lv?it.lv:1; if (autospl_skill_lv < 0) autospl_skill_lv = 1+rnd()%(-autospl_skill_lv); - rate = (!sd->state.arrow_atk) ? sd->autospell[i].rate : sd->autospell[i].rate / 2; + rate = (!sd->state.arrow_atk) ? it.rate : it.rate / 2; if (rnd()%1000 >= rate) continue; - tbl = (sd->autospell[i].id < 0) ? src : bl; + tbl = (it.id < 0) ? src : bl; if( (type = skill_get_casttype(skill)) == CAST_GROUND ) { int maxcount = 0; @@ -2169,18 +2168,16 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 } //Autobonus when attacking - if( sd && sd->autobonus[0].rate ) + if( sd && !sd->autobonus.empty() ) { - int i; - for( i = 0; i < ARRAYLENGTH(sd->autobonus); i++ ) - { - if( rnd()%1000 >= sd->autobonus[i].rate ) + for(auto &it : sd->autobonus) { + if (rnd()%1000 >= it.rate) continue; - if(!( ((sd->autobonus[i].atk_type)&attack_type)&BF_WEAPONMASK && - ((sd->autobonus[i].atk_type)&attack_type)&BF_RANGEMASK && - ((sd->autobonus[i].atk_type)&attack_type)&BF_SKILLMASK)) + if (!(((it.atk_type)&attack_type)&BF_WEAPONMASK && + ((it.atk_type)&attack_type)&BF_RANGEMASK && + ((it.atk_type)&attack_type)&BF_SKILLMASK)) continue; // one or more trigger conditions were not fulfilled - pc_exeautobonus(sd,&sd->autobonus[i]); + pc_exeautobonus(sd, &it); } } @@ -2198,21 +2195,21 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 } int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint16 skill_id, unsigned int tick) { - uint8 i; struct block_list *tbl; if( sd == NULL || !skill_id ) return 0; - for( i = 0; i < ARRAYLENGTH(sd->autospell3) && sd->autospell3[i].flag; i++ ) { + for (auto &it : sd->autospell3) { int skill, skill_lv, type; - if( sd->autospell3[i].flag != skill_id ) + + if (it.flag != skill_id) continue; - if( sd->autospell3[i].lock ) + if (it.lock) continue; // autospell already being executed - skill = sd->autospell3[i].id; + skill = it.id; sd->state.autocast = 1; //set this to bypass sd->canskill_tick check if( skill_isNotOk((skill > 0) ? skill : skill*-1, sd) ) { @@ -2224,10 +2221,10 @@ int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint1 if( skill >= 0 && bl == NULL ) continue; // No target - if( rnd()%1000 >= sd->autospell3[i].rate ) + if( rnd()%1000 >= it.rate ) continue; - skill_lv = sd->autospell3[i].lv ? sd->autospell3[i].lv : 1; + skill_lv = it.lv ? it.lv : 1; if( skill < 0 ) { tbl = &sd->bl; skill *= -1; @@ -2263,24 +2260,24 @@ int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint1 continue; sd->state.autocast = 1; - sd->autospell3[i].lock = true; + it.lock = true; skill_consume_requirement(sd,skill,skill_lv,1); switch( type ) { case CAST_GROUND: skill_castend_pos2(&sd->bl, tbl->x, tbl->y, skill, skill_lv, tick, 0); break; case CAST_NODAMAGE: skill_castend_nodamage_id(&sd->bl, tbl, skill, skill_lv, tick, 0); break; case CAST_DAMAGE: skill_castend_damage_id(&sd->bl, tbl, skill, skill_lv, tick, 0); break; } - sd->autospell3[i].lock = false; + it.lock = false; sd->state.autocast = 0; } - if( sd && sd->autobonus3[0].rate ) { - for( i = 0; i < ARRAYLENGTH(sd->autobonus3); i++ ) { - if( rnd()%1000 >= sd->autobonus3[i].rate ) + if( sd && !sd->autobonus3.empty() ) { + for (auto &it : sd->autobonus3) { + if (rnd()%1000 >= it.rate) continue; - if( sd->autobonus3[i].atk_type != skill_id ) + if (it.atk_type != skill_id) continue; - pc_exeautobonus(sd,&sd->autobonus3[i]); + pc_exeautobonus(sd, &it); } } @@ -2311,28 +2308,27 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * if(dstsd && attack_type&BF_WEAPON) { //Counter effects. enum sc_type type; - uint8 i; - unsigned int time = 0; + unsigned int time; - for (i = 0; i < ARRAYLENGTH(dstsd->addeff_atked) && dstsd->addeff_atked[i].flag; i++) { - rate = dstsd->addeff_atked[i].rate; + for (const auto &it : dstsd->addeff_atked) { + rate = it.rate; if (attack_type&BF_LONG) - rate += dstsd->addeff_atked[i].arrow_rate; + rate += it.arrow_rate; if (!rate) continue; - if ((dstsd->addeff_atked[i].flag&(ATF_LONG|ATF_SHORT)) != (ATF_LONG|ATF_SHORT)) { //Trigger has range consideration. - if((dstsd->addeff_atked[i].flag&ATF_LONG && !(attack_type&BF_LONG)) || - (dstsd->addeff_atked[i].flag&ATF_SHORT && !(attack_type&BF_SHORT))) + if ((it.flag&(ATF_LONG|ATF_SHORT)) != (ATF_LONG|ATF_SHORT)) { //Trigger has range consideration. + if((it.flag&ATF_LONG && !(attack_type&BF_LONG)) || + (it.flag&ATF_SHORT && !(attack_type&BF_SHORT))) continue; //Range Failed. } - type = dstsd->addeff_atked[i].sc; - time = dstsd->addeff_atked[i].duration; + type = it.sc; + time = it.duration; - if (dstsd->addeff_atked[i].flag&ATF_TARGET && src != bl) + if (it.flag&ATF_TARGET && src != bl) status_change_start(src,src,type,rate,7,0,0,0,time,SCSTART_NONE); - if (dstsd->addeff_atked[i].flag&ATF_SELF && !status_isdead(bl)) + if (it.flag&ATF_SELF && !status_isdead(bl)) status_change_start(src,bl,type,rate,7,0,0,0,time,SCSTART_NONE); } } @@ -2414,25 +2410,24 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * } // Trigger counter-spells to retaliate against damage causing skills. - if(dstsd && !status_isdead(bl) && dstsd->autospell2[0].id && + if(dstsd && !status_isdead(bl) && !dstsd->autospell2.empty() && !(skill_id && skill_get_nk(skill_id)&NK_NO_DAMAGE)) { struct block_list *tbl; struct unit_data *ud; - int i, autospl_skill_id, autospl_skill_lv, autospl_rate, type; + int autospl_skill_id, autospl_skill_lv, autospl_rate, type; - for (i = 0; i < ARRAYLENGTH(dstsd->autospell2) && dstsd->autospell2[i].id; i++) { - - if(!( ((dstsd->autospell2[i].flag)&attack_type)&BF_WEAPONMASK && - ((dstsd->autospell2[i].flag)&attack_type)&BF_RANGEMASK && - ((dstsd->autospell2[i].flag)&attack_type)&BF_SKILLMASK)) + for (const auto &it : dstsd->autospell2) { + if (!(((it.flag)&attack_type)&BF_WEAPONMASK && + ((it.flag)&attack_type)&BF_RANGEMASK && + ((it.flag)&attack_type)&BF_SKILLMASK)) continue; // one or more trigger conditions were not fulfilled - autospl_skill_id = (dstsd->autospell2[i].id > 0) ? dstsd->autospell2[i].id : -dstsd->autospell2[i].id; - autospl_skill_lv = dstsd->autospell2[i].lv?dstsd->autospell2[i].lv:1; + autospl_skill_id = (it.id > 0) ? it.id : -it.id; + autospl_skill_lv = it.lv ? it.lv : 1; if (autospl_skill_lv < 0) autospl_skill_lv = 1+rnd()%(-autospl_skill_lv); - autospl_rate = dstsd->autospell2[i].rate; + autospl_rate = it.rate; //Physical range attacks only trigger autospells half of the time if ((attack_type&(BF_WEAPON|BF_LONG)) == (BF_WEAPON|BF_LONG)) autospl_rate>>=1; @@ -2447,7 +2442,7 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * if (rnd()%1000 >= autospl_rate) continue; - tbl = (dstsd->autospell2[i].id < 0) ? bl : src; + tbl = (it.id < 0) ? bl : src; if( (type = skill_get_casttype(autospl_skill_id)) == CAST_GROUND ) { int maxcount = 0; if( !(BL_PC&battle_config.skill_reiteration) && @@ -2505,16 +2500,15 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * } //Autobonus when attacked - if( dstsd && !status_isdead(bl) && dstsd->autobonus2[0].rate && !(skill_id && skill_get_nk(skill_id)&NK_NO_DAMAGE) ) { - int i; - for( i = 0; i < ARRAYLENGTH(dstsd->autobonus2); i++ ) { - if( rnd()%1000 >= dstsd->autobonus2[i].rate ) + if( dstsd && !status_isdead(bl) && !dstsd->autobonus2.empty() && !(skill_id && skill_get_nk(skill_id)&NK_NO_DAMAGE) ) { + for (auto &it : dstsd->autobonus2) { + if (rnd()%1000 >= it.rate) continue; - if(!( ((dstsd->autobonus2[i].atk_type)&attack_type)&BF_WEAPONMASK && - ((dstsd->autobonus2[i].atk_type)&attack_type)&BF_RANGEMASK && - ((dstsd->autobonus2[i].atk_type)&attack_type)&BF_SKILLMASK)) + if (!(((it.atk_type)&attack_type)&BF_WEAPONMASK && + ((it.atk_type)&attack_type)&BF_RANGEMASK && + ((it.atk_type)&attack_type)&BF_SKILLMASK)) continue; // one or more trigger conditions were not fulfilled - pc_exeautobonus(dstsd,&dstsd->autobonus2[i]); + pc_exeautobonus(dstsd, &it); } } @@ -16228,12 +16222,19 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 if( sd->dsprate != 100 ) req.sp = req.sp * sd->dsprate / 100; - ARR_FIND(0, ARRAYLENGTH(sd->skillusesprate), i, sd->skillusesprate[i].id == skill_id); - if( i < ARRAYLENGTH(sd->skillusesprate) ) - sp_skill_rate_bonus += sd->skillusesprate[i].val; - ARR_FIND(0, ARRAYLENGTH(sd->skillusesp), i, sd->skillusesp[i].id == skill_id); - if( i < ARRAYLENGTH(sd->skillusesp) ) - req.sp -= sd->skillusesp[i].val; + for (auto &it : sd->skillusesprate) { + if (it.id == skill_id) { + sp_skill_rate_bonus += it.val; + break; + } + } + + for (auto &it : sd->skillusesp) { + if (it.id == skill_id) { + req.sp -= it.val; + break; + } + } if (skill_id == sd->status.skill[sd->reproduceskill_idx].id) req.sp += req.sp * 30 / 100; @@ -16503,14 +16504,12 @@ int skill_castfix(struct block_list *bl, uint16 skill_id, uint16 skill_lv) { // Calculate cast time reduced by item/card bonuses if (sd) { - int i; - if (!(flag&4) && sd->castrate != 100) reduce_cast_rate += 100 - sd->castrate; // Skill-specific reductions work regardless of flag - for(i = 0; i < ARRAYLENGTH(sd->skillcastrate) && sd->skillcastrate[i].id; i++) { - if (sd->skillcastrate[i].id == skill_id) { - time += time * sd->skillcastrate[i].val / 100; + for (const auto &it : sd->skillcastrate) { + if (it.id == skill_id) { + time += time * it.val / 100; break; } } @@ -16605,7 +16604,7 @@ int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16 struct status_change *sc = status_get_sc(bl); struct map_session_data *sd = BL_CAST(BL_PC,bl); int fixed = skill_get_fixed_cast(skill_id, skill_lv), fixcast_r = 0, varcast_r = 0, reduce_cast_rate = 0; - uint8 i = 0, flag = skill_get_castnodex(skill_id); + uint8 flag = skill_get_castnodex(skill_id); nullpo_ret(bl); @@ -16632,27 +16631,27 @@ int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16 time += sd->bonus.add_varcast; // bonus bVariableCast if (sd->bonus.add_fixcast != 0) fixed += sd->bonus.add_fixcast; // bonus bFixedCast - for (i = 0; i < ARRAYLENGTH(sd->skillfixcast) && sd->skillfixcast[i].id; i++) { - if (sd->skillfixcast[i].id == skill_id) { // bonus2 bSkillFixedCast - fixed += sd->skillfixcast[i].val; + for (const auto &it : sd->skillfixcast) { + if (it.id == skill_id) { // bonus2 bSkillFixedCast + fixed += it.val; break; } } - for (i = 0; i < ARRAYLENGTH(sd->skillvarcast) && sd->skillvarcast[i].id; i++) { - if (sd->skillvarcast[i].id == skill_id) { // bonus2 bSkillVariableCast - time += sd->skillvarcast[i].val; + for (const auto &it : sd->skillvarcast) { + if (it.id == skill_id) { // bonus2 bSkillVariableCast + time += it.val; break; } } - for (i = 0; i < ARRAYLENGTH(sd->skillcastrate) && sd->skillcastrate[i].id; i++) { - if (sd->skillcastrate[i].id == skill_id) { // bonus2 bVariableCastrate - reduce_cast_rate += sd->skillcastrate[i].val; + for (const auto &it : sd->skillcastrate) { + if (it.id == skill_id) { // bonus2 bVariableCastrate + reduce_cast_rate += it.val; break; } } - for (i = 0; i < ARRAYLENGTH(sd->skillfixcastrate) && sd->skillfixcastrate[i].id; i++) { - if (sd->skillfixcastrate[i].id == skill_id) { // bonus2 bFixedCastrate - fixcast_r = max(fixcast_r, sd->skillfixcastrate[i].val); + for (const auto &it : sd->skillfixcastrate) { + if (it.id == skill_id) { // bonus2 bFixedCastrate + fixcast_r = max(fixcast_r, it.val); break; } } @@ -16800,15 +16799,14 @@ int skill_delayfix(struct block_list *bl, uint16 skill_id, uint16 skill_lv) } if (!(delaynodex&4) && sd) { - uint8 i, len = ARRAYLENGTH(sd->skilldelay); - if (sd->delayrate != 100) time = time * sd->delayrate / 100; - if (len) { - ARR_FIND(0, len, i, sd->skilldelay[i].id == skill_id); - if (i < len) - time += sd->skilldelay[i].val; + for (auto &it : sd->skilldelay) { + if (it.id == skill_id) { + time += it.val; + break; + } } } diff --git a/src/map/status.cpp b/src/map/status.cpp index 3c612d8f68..d11b52ca63 100644 --- a/src/map/status.cpp +++ b/src/map/status.cpp @@ -3447,7 +3447,6 @@ int status_calc_pc_sub(struct map_session_data* sd, enum e_status_calc_opt opt) + sizeof(sd->subclass) + sizeof(sd->subrace2) + sizeof(sd->subsize) - + sizeof(sd->reseff) + sizeof(sd->coma_class) + sizeof(sd->coma_race) + sizeof(sd->weapon_coma_ele) @@ -3518,53 +3517,52 @@ int status_calc_pc_sub(struct map_session_data* sd, enum e_status_calc_opt opt) base_status->race = ((battle_config.summoner_trait&1) && (sd->class_&MAPID_BASEMASK) == MAPID_SUMMONER) ? RC_BRUTE : RC_PLAYER; base_status->class_ = CLASS_NORMAL; + sd->autospell.clear(); + sd->autospell2.clear(); + sd->autospell3.clear(); + sd->addeff.clear(); + sd->addeff_atked.clear(); + sd->addeff_onskill.clear(); + sd->skillatk.clear(); + sd->skillusesprate.clear(); + sd->skillusesp.clear(); + sd->skillheal.clear(); + sd->skillheal2.clear(); + sd->skillblown.clear(); + sd->skillcastrate.clear(); + sd->skillfixcastrate.clear(); + sd->subskill.clear(); + sd->skillcooldown.clear(); + sd->skillfixcast.clear(); + sd->skillvarcast.clear(); + sd->add_def.clear(); + sd->add_mdef.clear(); + sd->add_mdmg.clear(); + sd->reseff.clear(); + sd->itemgrouphealrate.clear(); + sd->add_drop.clear(); + sd->itemhealrate.clear(); + sd->subele2.clear(); + sd->skilldelay.clear(); + // Zero up structures... - memset(&sd->autospell, 0, sizeof(sd->autospell) - + sizeof(sd->autospell2) - + sizeof(sd->autospell3) - + sizeof(sd->addeff) - + sizeof(sd->addeff_atked) - + sizeof(sd->addeff_onskill) - + sizeof(sd->skillatk) - + sizeof(sd->skillusesprate) - + sizeof(sd->skillusesp) - + sizeof(sd->skillheal) - + sizeof(sd->skillheal2) - + sizeof(sd->skillblown) - + sizeof(sd->skillcastrate) - + sizeof(sd->skillfixcastrate) - + sizeof(sd->subskill) - + sizeof(sd->skillcooldown) - + sizeof(sd->skillfixcast) - + sizeof(sd->skillvarcast) - + sizeof(sd->hp_loss) - + sizeof(sd->sp_loss) + memset(&sd->hp_loss, 0, sizeof(sd->sp_loss) + sizeof(sd->hp_regen) + sizeof(sd->sp_regen) + sizeof(sd->percent_hp_regen) + sizeof(sd->percent_sp_regen) - + sizeof(sd->add_def) - + sizeof(sd->add_mdef) - + sizeof(sd->add_mdmg) - + sizeof(sd->add_drop) - + sizeof(sd->itemhealrate) - + sizeof(sd->subele2) + sizeof(sd->def_set_race) + sizeof(sd->mdef_set_race) + sizeof(sd->norecover_state_race) + sizeof(sd->hp_vanish_race) + sizeof(sd->sp_vanish_race) - + sizeof(sd->skilldelay) + + sizeof(sd->bonus) ); - memset (&sd->bonus, 0, sizeof(sd->bonus)); - // Autobonus - pc_delautobonus(sd,sd->autobonus,ARRAYLENGTH(sd->autobonus),true); - pc_delautobonus(sd,sd->autobonus2,ARRAYLENGTH(sd->autobonus2),true); - pc_delautobonus(sd,sd->autobonus3,ARRAYLENGTH(sd->autobonus3),true); - - pc_itemgrouphealrate_clear(sd); + pc_delautobonus(sd, sd->autobonus, true); + pc_delautobonus(sd, sd->autobonus2, true); + pc_delautobonus(sd, sd->autobonus3, true); running_npc_stat_calc_event = true; npc_script_event(sd, NPCE_STATCALC); @@ -8288,10 +8286,12 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ } // Item resistance (only applies to rate%) - if(sd && SC_COMMON_MIN <= type && type <= SC_COMMON_MAX) { - if( sd->reseff[type-SC_COMMON_MIN] ) - rate -= rate*sd->reseff[type-SC_COMMON_MIN]/10000; - if( sd->sc.data[SC_COMMONSC_RESIST] ) + if (sd) { + for (const auto &it : sd->reseff) { + if (it.id == type) + rate -= rate * it.val / 10000; + } + if (sd->sc.data[SC_COMMONSC_RESIST] && SC_COMMON_MIN <= type && type <= SC_COMMON_MAX) rate -= rate*sd->sc.data[SC_COMMONSC_RESIST]->val1/100; } diff --git a/src/map/unit.cpp b/src/map/unit.cpp index 86edf2433f..0207310ad1 100644 --- a/src/map/unit.cpp +++ b/src/map/unit.cpp @@ -3187,9 +3187,10 @@ int unit_free(struct block_list *bl, clr_type clrtype) pc_setrestartvalue(sd,2); pc_delinvincibletimer(sd); - pc_delautobonus(sd,sd->autobonus,ARRAYLENGTH(sd->autobonus),false); - pc_delautobonus(sd,sd->autobonus2,ARRAYLENGTH(sd->autobonus2),false); - pc_delautobonus(sd,sd->autobonus3,ARRAYLENGTH(sd->autobonus3),false); + + pc_delautobonus(sd, sd->autobonus, false); + pc_delautobonus(sd, sd->autobonus2, false); + pc_delautobonus(sd, sd->autobonus3, false); if( sd->followtimer != INVALID_TIMER ) pc_stop_following(sd); @@ -3257,8 +3258,6 @@ int unit_free(struct block_list *bl, clr_type clrtype) // Clearing... if (sd->bonus_script.head) pc_bonus_script_clear(sd, BSF_REM_ALL); - - pc_itemgrouphealrate_clear(sd); break; } case BL_PET: {