diff options
-rw-r--r-- | src/map/atcommand.c | 4 | ||||
-rw-r--r-- | src/map/battle.c | 654 | ||||
-rw-r--r-- | src/map/battle.h | 1 | ||||
-rw-r--r-- | src/map/clif.c | 8 | ||||
-rw-r--r-- | src/map/map.h | 2 | ||||
-rw-r--r-- | src/map/mob.c | 2 | ||||
-rw-r--r-- | src/map/pc.c | 12 | ||||
-rw-r--r-- | src/map/pc.h | 16 | ||||
-rw-r--r-- | src/map/skill.c | 64 | ||||
-rw-r--r-- | src/map/status.c | 211 | ||||
-rw-r--r-- | src/map/status.h | 19 |
11 files changed, 550 insertions, 443 deletions
diff --git a/src/map/atcommand.c b/src/map/atcommand.c index b2cbab558..3436f274c 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -3644,7 +3644,7 @@ ACMD_FUNC(guildrecall) if (sd->status.account_id != pl_sd->status.account_id && pl_sd->status.guild_id == g->guild_id) { if (pc_get_group_level(pl_sd) > pc_get_group_level(sd) || (pl_sd->bl.m == sd->bl.m && pl_sd->bl.x == sd->bl.x && pl_sd->bl.y == sd->bl.y)) - continue; // Skip GMs greater than you... and chars already on the cell + continue; // Skip GMs greater than you... or chars already on the cell if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) count++; else @@ -3703,7 +3703,7 @@ ACMD_FUNC(partyrecall) if (sd->status.account_id != pl_sd->status.account_id && pl_sd->status.party_id == p->party.party_id) { if (pc_get_group_level(pl_sd) > pc_get_group_level(sd) || (pl_sd->bl.m == sd->bl.m && pl_sd->bl.x == sd->bl.x && pl_sd->bl.y == sd->bl.y)) - continue; // Skip GMs greater than you... and chars already on the cell + continue; // Skip GMs greater than you... or chars already on the cell if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) count++; else diff --git a/src/map/battle.c b/src/map/battle.c index 36d8051ef..ed832106f 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -407,6 +407,316 @@ int battle_attr_fix(struct block_list *src, struct block_list *target, int damag } return damage*ratio/100; } +/*========================================== + * Calculates card bonuses damage adjustments. + *------------------------------------------*/ +int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int damage, int left, int flag){ + struct map_session_data *sd, *tsd; + short cardfix = 1000, t_class, s_class, s_race2, t_race2; + struct status_data *sstatus, *tstatus; + int i; + + sd = BL_CAST(BL_PC, src); + tsd = BL_CAST(BL_PC, target); + t_class = status_get_class(target); + s_class = status_get_class(src); + sstatus = status_get_status_data(src); + tstatus = status_get_status_data(target); + s_race2 = status_get_race2(src); + t_race2 = status_get_race2(target); + + if( !damage ) + return 0; + + switch(attack_type){ + case BF_MAGIC: + if ( sd && !(nk&NK_NO_CARDFIX_ATK) ) { + cardfix=cardfix*(100+sd->magic_addrace[tstatus->race])/100; + if (!(nk&NK_NO_ELEFIX)) + cardfix=cardfix*(100+sd->magic_addele[tstatus->def_ele])/100; + cardfix=cardfix*(100+sd->magic_addsize[tstatus->size])/100; + cardfix=cardfix*(100+sd->magic_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/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; + continue; + } + } + if (cardfix != 1000) + damage = damage * cardfix / 1000; + } + + if( tsd && !(nk&NK_NO_CARDFIX_DEF) ) + { // Target cards. + if (!(nk&NK_NO_ELEFIX)) + { + int ele_fix = tsd->subele[s_ele]; + for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) + { + if(tsd->subele2[i].ele != s_ele) continue; + if(!(tsd->subele2[i].flag&flag&BF_WEAPONMASK && + tsd->subele2[i].flag&flag&BF_RANGEMASK && + tsd->subele2[i].flag&flag&BF_SKILLMASK)) + continue; + ele_fix += tsd->subele2[i].rate; + } + cardfix=cardfix*(100-ele_fix)/100; + } + cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100; + cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; + cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; + cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; + if( sstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/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; + break; + } + } + //It was discovered that ranged defense also counts vs magic! [Skotlex] + if ( flag&BF_SHORT ) + cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100; + else + cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100; + + cardfix = cardfix * ( 100 - tsd->bonus.magic_def_rate ) / 100; + + if( tsd->sc.data[SC_MDEF_RATE] ) + cardfix = cardfix * ( 100 - tsd->sc.data[SC_MDEF_RATE]->val1 ) / 100; + + if (cardfix != 1000) + damage = damage * cardfix / 1000; + } + break; + case BF_WEAPON: + if( sd && !(nk&NK_NO_CARDFIX_ATK) && (left&2) ) + { + short cardfix_ = 1000; + if(sd->state.arrow_atk) + { + cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->arrow_addrace[tstatus->race])/100; + if (!(nk&NK_NO_ELEFIX)) + { + int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->arrow_addele[tstatus->def_ele]; + 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) 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)) + continue; + ele_fix += sd->right_weapon.addele2[i].rate; + } + cardfix=cardfix*(100+ele_fix)/100; + } + cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->arrow_addsize[tstatus->size])/100; + cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100; + cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]+sd->arrow_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; + if( tstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN]+sd->arrow_addrace[RC_NONDEMIHUMAN])/100; + } + else + { // Melee attack + if( !battle_config.left_cardfix_to_right ) + { + cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race])/100; + if (!(nk&NK_NO_ELEFIX)) { + int ele_fix = sd->right_weapon.addele[tstatus->def_ele]; + 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) 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)) + continue; + ele_fix += sd->right_weapon.addele2[i].rate; + } + cardfix=cardfix*(100+ele_fix)/100; + } + cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size])/100; + cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100; + cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; + if( tstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN])/100; + + if( left&1 ) + { + cardfix_=cardfix_*(100+sd->left_weapon.addrace[tstatus->race])/100; + if (!(nk&NK_NO_ELEFIX)) { + int ele_fix_lh = sd->left_weapon.addele[tstatus->def_ele]; + 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) 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)) + continue; + ele_fix_lh += sd->left_weapon.addele2[i].rate; + } + cardfix=cardfix*(100+ele_fix_lh)/100; + } + cardfix_=cardfix_*(100+sd->left_weapon.addsize[tstatus->size])/100; + cardfix_=cardfix_*(100+sd->left_weapon.addrace2[t_race2])/100; + cardfix_=cardfix_*(100+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; + if( tstatus->race != RC_DEMIHUMAN ) + cardfix_=cardfix_*(100+sd->left_weapon.addrace[RC_NONDEMIHUMAN])/100; + } + } + else + { + int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->left_weapon.addele[tstatus->def_ele]; + 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) 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)) + continue; + ele_fix += sd->right_weapon.addele2[i].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) 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)) + continue; + ele_fix += sd->left_weapon.addele2[i].rate; + } + + cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->left_weapon.addrace[tstatus->race])/100; + cardfix=cardfix*(100+ele_fix)/100; + cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->left_weapon.addsize[tstatus->size])/100; + cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2]+sd->left_weapon.addrace2[t_race2])/100; + cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; + if( tstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN]+sd->left_weapon.addrace[RC_NONDEMIHUMAN])/100; + } + } + 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; + 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; + break; + } + } + } + + if( flag&BF_LONG ) + cardfix = cardfix * ( 100 + sd->bonus.long_attack_atk_rate ) / 100; +#ifdef RENEWAL_EDP + if( sd->sc.data[SC_EDP] ){ + cardfix = cardfix * (100 + sd->sc.data[SC_EDP]->val1 * 60 ) / 100; + cardfix_ = cardfix_ * (100 + sd->sc.data[SC_EDP]->val1 * 60 ) / 100; + } +#endif + if( (left&1) && cardfix_ != 1000 ) + damage = damage * cardfix_ / 1000; + else if( cardfix != 1000 ) + damage = damage * cardfix / 1000; + + }else if( tsd && !(nk&NK_NO_CARDFIX_DEF) ){ + if( !(nk&NK_NO_ELEFIX) ) + { + int ele_fix = tsd->subele[s_ele]; + for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) + { + if(tsd->subele2[i].ele != s_ele) continue; + if(!(tsd->subele2[i].flag&flag&BF_WEAPONMASK && + tsd->subele2[i].flag&flag&BF_RANGEMASK && + tsd->subele2[i].flag&flag&BF_SKILLMASK)) + continue; + ele_fix += tsd->subele2[i].rate; + } + cardfix=cardfix*(100-ele_fix)/100; + if( left&1 && s_ele_ != s_ele ) + { + int ele_fix_lh = tsd->subele[s_ele_]; + for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) + { + if(tsd->subele2[i].ele != s_ele_) continue; + if(!(tsd->subele2[i].flag&flag&BF_WEAPONMASK && + tsd->subele2[i].flag&flag&BF_RANGEMASK && + tsd->subele2[i].flag&flag&BF_SKILLMASK)) + continue; + ele_fix_lh += tsd->subele2[i].rate; + } + cardfix=cardfix*(100-ele_fix_lh)/100; + } + } + cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100; + cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; + cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; + cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; + if( sstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/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; + break; + } + } + + if( flag&BF_SHORT ) + cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100; + else // BF_LONG (there's no other choice) + cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100; + + if( tsd->sc.data[SC_DEF_RATE] ) + cardfix = cardfix * ( 100 - tsd->sc.data[SC_DEF_RATE]->val1 ) / 100; + + if( cardfix != 1000 ) + damage = damage * cardfix / 1000; + } + break; + case BF_MISC: + if( tsd && !(nk&NK_NO_CARDFIX_DEF) ){ + // misc damage reduction from equipment + if (!(nk&NK_NO_ELEFIX)) + { + int ele_fix = tsd->subele[s_ele]; + for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) + { + if(tsd->subele2[i].ele != s_ele) continue; + if(!(tsd->subele2[i].flag&flag&BF_WEAPONMASK && + tsd->subele2[i].flag&flag&BF_RANGEMASK && + tsd->subele2[i].flag&flag&BF_SKILLMASK)) + continue; + ele_fix += tsd->subele2[i].rate; + } + cardfix=cardfix*(100-ele_fix)/100; + } + cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100; + cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; + cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; + cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; + if( sstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100; + + cardfix = cardfix * ( 100 - tsd->bonus.misc_def_rate ) / 100; + if( flag&BF_SHORT ) + cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100; + else // BF_LONG (there's no other choice) + cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100; + + if (cardfix != 10000) + damage = (int)( (int64)damage * cardfix / 1000); + } + break; + } + + return damage; +} /*========================================== * Check dammage trough status. @@ -3027,139 +3337,9 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo } //Card Fix, sd side - if( (wd.damage || wd.damage2) && !(nk&NK_NO_CARDFIX_ATK) ) - { - int cardfix = 1000, cardfix_ = 1000; - int t_race2 = status_get_race2(target); - if(sd->state.arrow_atk) - { - cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->arrow_addrace[tstatus->race])/100; - if (!(nk&NK_NO_ELEFIX)) - { - int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->arrow_addele[tstatus->def_ele]; - 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) continue; - if(!(sd->right_weapon.addele2[i].flag&wd.flag&BF_WEAPONMASK && - sd->right_weapon.addele2[i].flag&wd.flag&BF_RANGEMASK && - sd->right_weapon.addele2[i].flag&wd.flag&BF_SKILLMASK)) - continue; - ele_fix += sd->right_weapon.addele2[i].rate; - } - cardfix=cardfix*(100+ele_fix)/100; - } - cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->arrow_addsize[tstatus->size])/100; - cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100; - cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]+sd->arrow_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; - if( tstatus->race != RC_DEMIHUMAN ) - cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN]+sd->arrow_addrace[RC_NONDEMIHUMAN])/100; - } - else - { // Melee attack - if( !battle_config.left_cardfix_to_right ) - { - cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race])/100; - if (!(nk&NK_NO_ELEFIX)) { - int ele_fix = sd->right_weapon.addele[tstatus->def_ele]; - 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) continue; - if(!(sd->right_weapon.addele2[i].flag&wd.flag&BF_WEAPONMASK && - sd->right_weapon.addele2[i].flag&wd.flag&BF_RANGEMASK && - sd->right_weapon.addele2[i].flag&wd.flag&BF_SKILLMASK)) - continue; - ele_fix += sd->right_weapon.addele2[i].rate; - } - cardfix=cardfix*(100+ele_fix)/100; - } - cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size])/100; - cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100; - cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; - if( tstatus->race != RC_DEMIHUMAN ) - cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN])/100; - - if( flag.lh ) - { - cardfix_=cardfix_*(100+sd->left_weapon.addrace[tstatus->race])/100; - if (!(nk&NK_NO_ELEFIX)) { - int ele_fix_lh = sd->left_weapon.addele[tstatus->def_ele]; - 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) continue; - if(!(sd->left_weapon.addele2[i].flag&wd.flag&BF_WEAPONMASK && - sd->left_weapon.addele2[i].flag&wd.flag&BF_RANGEMASK && - sd->left_weapon.addele2[i].flag&wd.flag&BF_SKILLMASK)) - continue; - ele_fix_lh += sd->left_weapon.addele2[i].rate; - } - cardfix=cardfix*(100+ele_fix_lh)/100; - } - cardfix_=cardfix_*(100+sd->left_weapon.addsize[tstatus->size])/100; - cardfix_=cardfix_*(100+sd->left_weapon.addrace2[t_race2])/100; - cardfix_=cardfix_*(100+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; - if( tstatus->race != RC_DEMIHUMAN ) - cardfix_=cardfix_*(100+sd->left_weapon.addrace[RC_NONDEMIHUMAN])/100; - } - } - else - { - int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->left_weapon.addele[tstatus->def_ele]; - 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) continue; - if(!(sd->right_weapon.addele2[i].flag&wd.flag&BF_WEAPONMASK && - sd->right_weapon.addele2[i].flag&wd.flag&BF_RANGEMASK && - sd->right_weapon.addele2[i].flag&wd.flag&BF_SKILLMASK)) - continue; - ele_fix += sd->right_weapon.addele2[i].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) continue; - if(!(sd->left_weapon.addele2[i].flag&wd.flag&BF_WEAPONMASK && - sd->left_weapon.addele2[i].flag&wd.flag&BF_RANGEMASK && - sd->left_weapon.addele2[i].flag&wd.flag&BF_SKILLMASK)) - continue; - ele_fix += sd->left_weapon.addele2[i].rate; - } - - cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->left_weapon.addrace[tstatus->race])/100; - cardfix=cardfix*(100+ele_fix)/100; - cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->left_weapon.addsize[tstatus->size])/100; - cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2]+sd->left_weapon.addrace2[t_race2])/100; - cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; - if( tstatus->race != RC_DEMIHUMAN ) - cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN]+sd->left_weapon.addrace[RC_NONDEMIHUMAN])/100; - } - } - - 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; - break; - } - } - - if( flag.lh ) - { - 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; - break; - } - } - } - - if( wd.flag&BF_LONG ) - cardfix = cardfix * ( 100 + sd->bonus.long_attack_atk_rate ) / 100; -#ifdef RENEWAL_EDP - if( sc && sc->data[SC_EDP] ){ - cardfix = cardfix * (100 + sc->data[SC_EDP]->val1 * 60 ) / 100; - cardfix_ = cardfix_ * (100 + sc->data[SC_EDP]->val1 * 60 ) / 100; - } -#endif - if( cardfix != 1000 || cardfix_ != 1000 ) - ATK_RATE2(cardfix/10, cardfix_/10); //What happens if you use right-to-left and there's no right weapon, only left? - } + wd.damage = battle_calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage, 2, wd.flag); + if( flag.lh ) + wd.damage2 = battle_calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage2, 3, wd.flag); if( skill_num == CR_SHIELDBOOMERANG || skill_num == PA_SHIELDCHAIN ) { //Refine bonus applies after cards and elements. @@ -3169,68 +3349,9 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo } } //if (sd) - //Card Fix, tsd sid - if( tsd && !(nk&NK_NO_CARDFIX_DEF) ) - { - short s_race2,s_class; - short cardfix=1000; - - s_race2 = status_get_race2(src); - s_class = status_get_class(src); - - if( !(nk&NK_NO_ELEFIX) ) - { - int ele_fix = tsd->subele[s_ele]; - for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) - { - if(tsd->subele2[i].ele != s_ele) continue; - if(!(tsd->subele2[i].flag&wd.flag&BF_WEAPONMASK && - tsd->subele2[i].flag&wd.flag&BF_RANGEMASK && - tsd->subele2[i].flag&wd.flag&BF_SKILLMASK)) - continue; - ele_fix += tsd->subele2[i].rate; - } - cardfix=cardfix*(100-ele_fix)/100; - if( flag.lh && s_ele_ != s_ele ) - { - int ele_fix_lh = tsd->subele[s_ele_]; - for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) - { - if(tsd->subele2[i].ele != s_ele_) continue; - if(!(tsd->subele2[i].flag&wd.flag&BF_WEAPONMASK && - tsd->subele2[i].flag&wd.flag&BF_RANGEMASK && - tsd->subele2[i].flag&wd.flag&BF_SKILLMASK)) - continue; - ele_fix_lh += tsd->subele2[i].rate; - } - cardfix=cardfix*(100-ele_fix_lh)/100; - } - } - cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100; - cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; - cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; - cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; - if( sstatus->race != RC_DEMIHUMAN ) - cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/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; - break; - } - } - - if( wd.flag&BF_SHORT ) - cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100; - else // BF_LONG (there's no other choice) - cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100; - - if( tsd->sc.data[SC_DEF_RATE] ) - cardfix = cardfix * ( 100 - tsd->sc.data[SC_DEF_RATE]->val1 ) / 100; - - if( cardfix != 1000 ) - ATK_RATE( cardfix / 10 ); - } + //Card Fix, tsd side + if(tsd) + wd.damage = battle_calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage, flag.lh, wd.flag); if( flag.infdef ) { //Plants receive 1 damage when hit @@ -3402,7 +3523,6 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list return ad; } //Initial Values - ad.damage = 1; ad.div_=skill_get_num(skill_num,skill_lv); ad.amotion=skill_get_inf(skill_num)&INF_GROUND_SKILL?0:sstatus->amotion; //Amotion should be 0 for ground skills. ad.dmotion=tstatus->dmotion; @@ -3518,7 +3638,12 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list ad.damage = tstatus->hp; else { #ifdef RENEWAL - ad.damage = skill_lv * (sstatus->matk_min + sstatus->matk_max); + if (sstatus->matk_max > sstatus->matk_min) { + MATK_ADD(sstatus->matk_min+rnd()%(sstatus->matk_max-sstatus->matk_min)); + } else { + MATK_ADD(sstatus->matk_min); + } + MATK_RATE(skill_lv); #else ad.damage = status_get_lv(src) + sstatus->int_ + skill_lv * 10; #endif @@ -3534,25 +3659,14 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list //Damage calculation from iRO wiki. [Jobbie] ad.damage = (int)((15 * status_get_lv(src)) + (1.5 * sstatus->int_)); break; - default: - { - #ifdef RENEWAL //Renewal MATK Appliance according to doddler (?title=Renewal_Changes#Upgrade_MATK) - /** - * min: (weaponMATK+upgradeMATK) * 2 + 1.5 * statusMATK - * max: [weaponMATK+upgradeMATK+(wMatk*wLvl)/10] * 2 + 1.5 * statusMATK - * yes this formula MATCHES their site: matk_max already holds weaponmatk+upgradematk, and - * -> statusMATK holds the %Matk modifier stuff from earlier and lastly: - * -> the mdef part is not applied at this point, but later. - **/ //1:bugreport:5101 //1:bugreport:5101 - MATK_ADD((1+sstatus->matk_max) * 2 + 15/10 * sstatus->matk_min + rnd()% ( sstatus->matk_max + (1 + (sstatus->matk_max*sstatus->wlv) / 10 * 2 + 10/15 * sstatus->matk_min ) )); - #else //Ancient MATK Appliance - if (sstatus->matk_max > sstatus->matk_min) { - MATK_ADD(sstatus->matk_min+rnd()%(1+sstatus->matk_max-sstatus->matk_min)); - } else { - MATK_ADD(sstatus->matk_min); - } - #endif - if(nk&NK_SPLASHSPLIT){ // Divide MATK in case of multiple targets skill + default: { + if (sstatus->matk_max > sstatus->matk_min) { + MATK_ADD(sstatus->matk_min+rnd()%(sstatus->matk_max-sstatus->matk_min)); + } else { + MATK_ADD(sstatus->matk_min); + } + + if (nk&NK_SPLASHSPLIT) { // Divide MATK in case of multiple targets skill if(mflag>0) ad.damage/= mflag; else @@ -3958,7 +4072,9 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list MATK_ADD(50); } } - +#ifdef RENEWAL + ad.damage = battle_calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag); +#endif if(sd) { //Damage bonuses if ((i = pc_skillatk_bonus(sd, skill_num))) @@ -4030,72 +4146,9 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list } } - if (sd && !(nk&NK_NO_CARDFIX_ATK)) { - short t_class = status_get_class(target); - short cardfix=1000; - - cardfix=cardfix*(100+sd->magic_addrace[tstatus->race])/100; - if (!(nk&NK_NO_ELEFIX)) - cardfix=cardfix*(100+sd->magic_addele[tstatus->def_ele])/100; - cardfix=cardfix*(100+sd->magic_addsize[tstatus->size])/100; - cardfix=cardfix*(100+sd->magic_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/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; - continue; - } - } - if (cardfix != 1000) - MATK_RATE(cardfix/10); - } - - if( tsd && !(nk&NK_NO_CARDFIX_DEF) ) - { // Target cards. - short s_race2 = status_get_race2(src); - short s_class= status_get_class(src); - int cardfix=1000; - - if (!(nk&NK_NO_ELEFIX)) - { - int ele_fix = tsd->subele[s_ele]; - for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) - { - if(tsd->subele2[i].ele != s_ele) continue; - if(!(tsd->subele2[i].flag&ad.flag&BF_WEAPONMASK && - tsd->subele2[i].flag&ad.flag&BF_RANGEMASK && - tsd->subele2[i].flag&ad.flag&BF_SKILLMASK)) - continue; - ele_fix += tsd->subele2[i].rate; - } - cardfix=cardfix*(100-ele_fix)/100; - } - cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100; - cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; - cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; - cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; - if( sstatus->race != RC_DEMIHUMAN ) - cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/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; - break; - } - } - //It was discovered that ranged defense also counts vs magic! [Skotlex] - if ( ad.flag&BF_SHORT ) - cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100; - else - cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100; - - cardfix = cardfix * ( 100 - tsd->bonus.magic_def_rate ) / 100; - - if( tsd->sc.data[SC_MDEF_RATE] ) - cardfix = cardfix * ( 100 - tsd->sc.data[SC_MDEF_RATE]->val1 ) / 100; - - if (cardfix != 1000) - MATK_RATE( cardfix / 10 ); - } +#ifndef RENEWAL + ad.damage = battle_calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag); +#endif } damage_div_fix(ad.damage, ad.div_); @@ -4374,40 +4427,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * } } - if( md.damage && tsd && !(nk&NK_NO_CARDFIX_DEF) ) - {// misc damage reduction from equipment - int cardfix = 10000; - int race2 = status_get_race2(src); - if (!(nk&NK_NO_ELEFIX)) - { - int ele_fix = tsd->subele[s_ele]; - for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) - { - if(tsd->subele2[i].ele != s_ele) continue; - if(!(tsd->subele2[i].flag&md.flag&BF_WEAPONMASK && - tsd->subele2[i].flag&md.flag&BF_RANGEMASK && - tsd->subele2[i].flag&md.flag&BF_SKILLMASK)) - continue; - ele_fix += tsd->subele2[i].rate; - } - cardfix=cardfix*(100-ele_fix)/100; - } - cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100; - cardfix=cardfix*(100-tsd->subrace2[race2])/100; - cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; - cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; - if( sstatus->race != RC_DEMIHUMAN ) - cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100; - - cardfix = cardfix * ( 100 - tsd->bonus.misc_def_rate ) / 100; - if( md.flag&BF_SHORT ) - cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100; - else // BF_LONG (there's no other choice) - cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100; - - if (cardfix != 10000) - md.damage= (int)( (int64)md.damage * cardfix / 10000 ); - } + md.damage = battle_calc_cardfix(BF_MISC, src, target, nk, s_ele, 0, md.damage, 0, md.flag); if (sd && (i = pc_skillatk_bonus(sd, skill_num))) md.damage += md.damage*i/100; diff --git a/src/map/battle.h b/src/map/battle.h index b901644de..800aab2b2 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -41,6 +41,7 @@ void battle_drain(struct map_session_data *sd, struct block_list *tbl, int rdama int battle_attr_ratio(int atk_elem,int def_type, int def_lv); int battle_attr_fix(struct block_list *src, struct block_list *target, int damage,int atk_elem,int def_type, int def_lv); +int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int damage, int left, int flag); // Final calculation Damage int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damage *d,int damage,int skill_num,int skill_lv); diff --git a/src/map/clif.c b/src/map/clif.c index ec818e5d3..385aaff13 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -2835,10 +2835,10 @@ void clif_updatestatus(struct map_session_data *sd,int type) WFIFOL(fd,4)=sd->battle_status.cri/10; break; case SP_MATK1: - WFIFOL(fd,4)=sd->battle_status.matk_max; + WFIFOL(fd,4)=pc_rightside_matk(sd); break; case SP_MATK2: - WFIFOL(fd,4)=sd->battle_status.matk_min; + WFIFOL(fd,4)=pc_leftside_matk(sd); break; @@ -3169,8 +3169,8 @@ void clif_initialstatus(struct map_session_data *sd) WBUFW(buf,16) = pc_leftside_atk(sd); WBUFW(buf,18) = pc_rightside_atk(sd); - WBUFW(buf,20) = sd->battle_status.matk_max; - WBUFW(buf,22) = sd->battle_status.matk_min; + WBUFW(buf,20) = pc_rightside_matk(sd); + WBUFW(buf,22) = pc_leftside_matk(sd); WBUFW(buf,24) = pc_leftside_def(sd); WBUFW(buf,26) = pc_rightside_def(sd); WBUFW(buf,28) = pc_leftside_mdef(sd); diff --git a/src/map/map.h b/src/map/map.h index b011c8193..89e52dea3 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -404,7 +404,7 @@ enum _sp { SP_UNSTRIPABLE_WEAPON,SP_UNSTRIPABLE_ARMOR,SP_UNSTRIPABLE_HELM,SP_UNSTRIPABLE_SHIELD, // 2034-2037 SP_INTRAVISION, SP_ADD_MONSTER_DROP_ITEMGROUP, SP_SP_LOSS_RATE, // 2038-2040 SP_ADD_SKILL_BLOW, SP_SP_VANISH_RATE, SP_MAGIC_SP_GAIN_VALUE, SP_MAGIC_HP_GAIN_VALUE, SP_ADD_CLASS_DROP_ITEM, //2041-2045 - SP_WEAPON_MATK, SP_BASE_MATK, SP_SP_GAIN_RACE_ATTACK, SP_HP_GAIN_RACE_ATTACK, SP_SKILL_USE_SP_RATE, //2046-2050 + SP_EMATK, SP_SP_GAIN_RACE_ATTACK, SP_HP_GAIN_RACE_ATTACK, SP_SKILL_USE_SP_RATE, //2046-2049 SP_SKILL_COOLDOWN,SP_SKILL_FIXEDCAST, SP_SKILL_VARIABLECAST, SP_FIXCASTRATE, SP_VARCASTRATE, //2051-2055 SP_SKILL_USE_SP //2056 }; diff --git a/src/map/mob.c b/src/map/mob.c index a1a5ea311..c112c5666 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -2252,7 +2252,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) else job_exp = (unsigned int)cap_value(md->db->job_exp * per * bonus/100. * map[m].jexp/100., 1, UINT_MAX); - if ((temp = tmpsd[i]->status.party_id)>0 /*&& !md->dmglog[i].flag == MDLF_HOMUN*/) { //Homun-done damage (flag 1) is given to party + if ((temp = tmpsd[i]->status.party_id)>0 /*&& !md->dmglog[i].flag == MDLF_HOMUN*/) //Homun-done damage (flag 1) is given to party { int j; for(j=0;j<pnum && pt[j].id!=temp;j++); //Locate party. diff --git a/src/map/pc.c b/src/map/pc.c index e1ef92d00..1bc94c147 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -2589,14 +2589,10 @@ int pc_bonus(struct map_session_data *sd,int type,int val) if(sd->state.lr_flag != 2) sd->bonus.itemhealrate2 += val; break; - case SP_WEAPON_MATK: - if(sd->state.lr_flag != 2) - sd->bonus.sp_weapon_matk += val; - break; - case SP_BASE_MATK: - if(sd->state.lr_flag != 2) - sd->bonus.sp_base_matk += val; - break; + case SP_EMATK: + if(sd->state.lr_flag != 2) + sd->bonus.ematk += val; + break; case SP_FIXCASTRATE: if(sd->state.lr_flag != 2) sd->bonus.fixcastrate -= val; diff --git a/src/map/pc.h b/src/map/pc.h index bc8a76f2a..a4bcb7723 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -314,11 +314,11 @@ struct map_session_data { short sp_gain_value, hp_gain_value, magic_sp_gain_value, magic_hp_gain_value; short sp_vanish_rate; short sp_vanish_per; - short sp_weapon_matk,sp_base_matk; unsigned short unbreakable; // chance to prevent ANY equipment breaking [celest] unsigned short unbreakable_equip; //100% break resistance on certain equipment unsigned short unstripable_equip; int fixcastrate,varcastrate; + int ematk; // matk bonus from equipment } bonus; // zeroed vars end here. @@ -645,6 +645,8 @@ enum equip_index { #define pc_rightside_def(sd) ((sd)->battle_status.def) #define pc_leftside_mdef(sd) ((sd)->battle_status.mdef2) #define pc_rightside_mdef(sd) ((sd)->battle_status.mdef) +#define pc_leftside_matk(sd) (status_base_matk(status_get_status_data(&(sd)->bl), (sd)->status.base_level)) +#define pc_rightside_matk(sd) ((sd)->battle_status.rhw.matk+(sd)->bonus.ematk) #else #define pc_leftside_atk(sd) ((sd)->battle_status.batk + (sd)->battle_status.rhw.atk + (sd)->battle_status.lhw.atk) #define pc_rightside_atk(sd) ((sd)->battle_status.rhw.atk2 + (sd)->battle_status.lhw.atk2) @@ -652,6 +654,18 @@ enum equip_index { #define pc_rightside_def(sd) ((sd)->battle_status.def2) #define pc_leftside_mdef(sd) ((sd)->battle_status.mdef) #define pc_rightside_mdef(sd) ( (sd)->battle_status.mdef2 - ((sd)->battle_status.vit>>1) ) +#define pc_leftside_matk(sd) \ + (\ + ((sd)->sc.data[SC_MAGICPOWER] && (sd)->sc.data[SC_MAGICPOWER]->val4) \ + ?((sd)->battle_status.matk_min * 100 + 50) / ((sd)->sc.data[SC_MAGICPOWER]->val3+100) \ + :(sd)->battle_status.matk_min \ + ) +#define pc_rightside_matk(sd) \ + (\ + ((sd)->sc.data[SC_MAGICPOWER] && (sd)->sc.data[SC_MAGICPOWER]->val4) \ + ?((sd)->battle_status.matk_max * 100 + 50) / ((sd)->sc.data[SC_MAGICPOWER]->val3+100) \ + :(sd)->battle_status.matk_max \ + ) #endif int pc_class2idx(int class_); diff --git a/src/map/skill.c b/src/map/skill.c index e19326bad..f81053c3d 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -397,13 +397,11 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, int skill if (skill_lv >= battle_config.max_heal_lv) return battle_config.max_heal; #ifdef RENEWAL - /** - * Renewal Heal Formula (from Doddler) - * TODO: whats that( 1+ %Modifier / 100 ) ? currently using 'x1' (100/100) until found out - * - Min = ( [ ( BaseLvl + INT ) / 5 ] * 30 ) * (1+( %Modifier / 100)) * (HealLvl * 0.1) + StatusMATK + EquipMATK - [(WeaponMATK * WeaponLvl) / 10] - * - Max = ( [ ( BaseLvl + INT ) / 5 ] * 30 ) * (1+( %Modifier / 100)) * (HealLvl * 0.1) + StatusMATK + EquipMATK + [(WeaponMATK * WeaponLvl) / 10] - **/ - hp = ( ( ( ( status_get_lv(src) + status_get_int(src) ) / 5 ) * 3 ) * skill_lv + status_get_matk_min(src) + status_get_matk_max(src) - ( ( status_get_matk_max(src) * status_get_wlv(src) ) / 10 ) ) + rnd()%( ( ( ( status_get_lv(src) + status_get_int(src) ) / 5 ) * 3 ) * skill_lv + status_get_matk_min(src) + status_get_matk_max(src) + ( ( status_get_matk_max(src) * status_get_wlv(src) ) / 10 ) ); + /** + * Renewal Heal Formula + * Formula: ( [(Base Level + INT) / 5] × 30 ) × (Heal Level / 10) × (Modifiers) + MATK + **/ + hp = (status_get_lv(src) + status_get_int(src)) / 5 * 30 * skill_lv / 10; #else hp = ( status_get_lv(src) + status_get_int(src) ) / 8 * (4 + ( skill_id == AB_HIGHNESSHEAL ? ( sd ? pc_checkskill(sd,AL_HEAL) : 10 ) : skill_lv ) * 8); #endif @@ -434,7 +432,41 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, int skill if( sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 2) hp += hp / 10; } + +#ifdef RENEWAL + // MATK part of the RE heal formula [malufett] + // Note: in this part matk bonuses from items or skills are not applied + switch( skill_id ) { + case BA_APPLEIDUN: case PR_SANCTUARY: + case NPC_EVILLAND: break; + default: + { + struct status_data *status = status_get_status_data(src); + int min, max, wMatk, variance; + + min = max = status_base_matk(status, status_get_lv(src)); + if( status->rhw.matk > 0 ){ + wMatk = status->rhw.matk; + variance = wMatk * status->rhw.wlv / 10; + min += wMatk - variance; + max += wMatk + variance; + } + + if( sc && sc->data[SC_RECOGNIZEDSPELL] ) + min = max; + + if( sd && sd->right_weapon.overrefine > 0 ){ + min++; + max += sd->right_weapon.overrefine - 1; + } + if(max > min) + hp += min+rnd()%(max-min); + else + hp += min; + } + } +#endif return hp; } @@ -8575,10 +8607,22 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case SO_EL_ACTION: if( sd ) { + int duration = 3000; if( !sd->ed ) break; elemental_action(sd->ed, bl, tick); clif_skill_nodamage(src,bl,skillid,skilllv,1); + switch(sd->ed->db->class_){ + case 2115:case 2124: + case 2118:case 2121: + duration = 6000; + break; + case 2116:case 2119: + case 2122:case 2125: + duration = 9000; + break; + } + skill_blockpc_start(sd, skillid, duration); } break; @@ -16481,6 +16525,12 @@ static void skill_toggle_magicpower(struct block_list *bl, short skillid) { sc->data[SC_MAGICPOWER]->val4 = 1; status_calc_bl(bl, status_sc2scb_flag(SC_MAGICPOWER)); +#ifndef RENEWAL + if(bl->type == BL_PC){// update current display. + clif_updatestatus(((TBL_PC *)bl),SP_MATK1); + clif_updatestatus(((TBL_PC *)bl),SP_MATK2); + } +#endif } } } diff --git a/src/map/status.c b/src/map/status.c index 4a3a6b0d8..2f83caf52 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -587,7 +587,7 @@ void initChangeTables(void) { add_sc( WL_WHITEIMPRISON , SC_WHITEIMPRISON ); set_sc_with_vfx( WL_FROSTMISTY , SC_FREEZING , SI_FROSTMISTY , SCB_ASPD|SCB_SPEED|SCB_DEF|SCB_DEF2 ); set_sc( WL_MARSHOFABYSS , SC_MARSHOFABYSS , SI_MARSHOFABYSS , SCB_SPEED|SCB_FLEE|SCB_DEF|SCB_MDEF ); - set_sc( WL_RECOGNIZEDSPELL , SC_RECOGNIZEDSPELL , SI_RECOGNIZEDSPELL , SCB_NONE ); + set_sc(WL_RECOGNIZEDSPELL , SC_RECOGNIZEDSPELL , SI_RECOGNIZEDSPELL , SCB_MATK); set_sc( WL_STASIS , SC_STASIS , SI_STASIS , SCB_NONE ); /** * Ranger @@ -1901,29 +1901,12 @@ static unsigned short status_base_atk(const struct block_list *bl, const struct return cap_value(str, 0, USHRT_MAX); } - -static inline unsigned short status_base_matk_max(const struct status_data* status) -{ -#ifdef RENEWAL - return status->matk_max; // in RE maximum MATK signs weapon matk, which we store in this var -#else - return status->int_+(status->int_/5)*(status->int_/5); -#endif -} - -#ifdef RENEWAL -static inline unsigned short status_base_matk_min(const struct status_data* status, int lvl) -#else -static inline unsigned short status_base_matk_min(const struct status_data* status) -#endif -{ -#ifdef RENEWAL - return status->int_+(status->int_/2)+(status->dex/5)+(status->luk/3)+(lvl/4); +#ifndef RENEWAL +static inline unsigned short status_base_matk_min(const struct status_data* status){ return status->int_+(status->int_/7)*(status->int_/7); } +static inline unsigned short status_base_matk_max(const struct status_data* status){ return status->int_+(status->int_/5)*(status->int_/5); } #else - return status->int_+(status->int_/7)*(status->int_/7); +unsigned short status_base_matk(const struct status_data* status, int level){ return status->int_+(status->int_/2)+(status->dex/5)+(status->luk/3)+(level/4); } #endif -} - //Fills in the misc data that can be calculated from the other status info (except for level) void status_calc_misc(struct block_list *bl, struct status_data *status, int level) @@ -1934,19 +1917,16 @@ void status_calc_misc(struct block_list *bl, struct status_data *status, int lev status->hit = status->flee = status->def2 = status->mdef2 = status->cri = status->flee2 = 0; -#ifdef RENEWAL - status->matk_min = status_base_matk_min(status, level); -#else - status->matk_min = status_base_matk_min(status); -#endif - status->matk_max = status_base_matk_max(status); #ifdef RENEWAL // renewal formulas - status->hit += level + status->dex + status->luk/3 + 175; //base level + ( every 1 dex = +1 hit ) + (every 3 luk = +1 hit) + 175 - status->flee += level + status->agi + status->luk/5 + 100; //base level + ( every 1 agi = +1 flee ) + (every 5 luk = +1 flee) + 100 - status->def2 += (int)(((float)level + status->vit)/2 + ((float)status->agi/5)); //base level + (every 2 vit = +1 def) + (every 5 agi = +1 def) - status->mdef2 += (int)(status->int_ + ((float)level/4) + ((float)status->dex/5) + ((float)status->vit/5)); //(every 4 base level = +1 mdef) + (every 1 int = +1 mdef) + (every 5 dex = +1 mdef) + (every 5 vit = +1 mdef) + status->matk_min = status->matk_max = status_base_matk(status, level); + status->hit += level + status->dex + status->luk/3 + 175; //base level + ( every 1 dex = +1 hit ) + (every 3 luk = +1 hit) + 175 + status->flee += level + status->agi + status->luk/5 + 100; //base level + ( every 1 agi = +1 flee ) + (every 5 luk = +1 flee) + 100 + status->def2 += (int)(((float)level + status->vit)/2 + ((float)status->agi/5)); //base level + (every 2 vit = +1 def) + (every 5 agi = +1 def) + status->mdef2 += (int)(status->int_ + ((float)level/4) + ((float)status->dex/5) + ((float)status->vit/5)); //(every 4 base level = +1 mdef) + (every 1 int = +1 mdef) + (every 5 dex = +1 mdef) + (every 5 vit = +1 mdef) #else + status->matk_min = status_base_matk_min(status); + status->matk_max = status_base_matk_max(status); status->hit += level + status->dex; status->flee += level + status->agi; status->def2 += status->vit; @@ -2492,16 +2472,10 @@ int status_calc_pc_(struct map_session_data* sd, bool first) wa->atk2 = refine_info[wlv].bonus[r-1] / 100; #ifdef RENEWAL - // in renewal max MATK is the weapon MATK - status->matk_max += sd->inventory_data[index]->matk; - - if( r ) - {// renewal magic attack refine bonus - status->matk_max += refine_info[wlv].bonus[r-1] / 100; - } - - // record the weapon level for future usage - status->wlv = wlv; + wa->matk += sd->inventory_data[index]->matk; + wa->wlv = wlv; + if( r ) // renewal magic attack refine bonus + wa->matk += refine_info[wlv].bonus[r-1] / 100; #endif //Overrefine bonus. @@ -2575,11 +2549,6 @@ int status_calc_pc_(struct map_session_data* sd, bool first) status->def += (refinedef+50)/100; -#ifdef RENEWAL - // increment the weapon ATK using the MATK max value - status->matk_max += sd->bonus.sp_weapon_matk; -#endif - //Parse Cards for(i=0;i<EQI_MAX-1;i++) { current_equip_item_index = index = sd->equip_index[i]; //We pass INDEX to current_equip_item_index - for EQUIP_SCRIPT (new cards solution) [Lupus] @@ -3287,6 +3256,9 @@ static unsigned int status_calc_maxsp(struct block_list *,struct status_change * static unsigned char status_calc_element(struct block_list *bl, struct status_change *sc, int element); static unsigned char status_calc_element_lv(struct block_list *bl, struct status_change *sc, int lv); static unsigned short status_calc_mode(struct block_list *bl, struct status_change *sc, int mode); +#ifdef RENEWAL +static unsigned short status_calc_ematk(struct block_list *,struct status_change *,int); +#endif //Calculates base regen values. void status_calc_regen(struct block_list *bl, struct status_data *status, struct regen_data *regen) @@ -3787,32 +3759,50 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) } if(flag&SCB_MATK) { -#ifdef RENEWAL - status->matk_min = status_base_matk_min(status,status_get_lv(bl)); - if( sd ) - status->matk_min += sd->bonus.sp_base_matk; +#ifndef RENEWAL + status->matk_min = status_base_matk_min(status) + (sd?sd->bonus.ematk:0); + status->matk_max = status_base_matk_max(status) + (sd?sd->bonus.ematk:0); #else - status->matk_min = status_base_matk_min(status); + /** + * RE MATK Formula (from irowiki:http://irowiki.org/wiki/MATK) + * MATK = (sMATK + wMATK + eMATK) * Multiplicative Modifiers + **/ + status->matk_min = status->matk_max = status_base_matk(status, status_get_lv(bl)); + if( bl->type&BL_PC ){ + // Any +MATK you get from skills and cards, including cards in weapon, is added here. + if( sd->bonus.ematk > 0 ){ + status->matk_max += sd->bonus.ematk; + status->matk_min += sd->bonus.ematk; + } + status->matk_min = status_calc_ematk(bl, sc, status->matk_min); + status->matk_max = status_calc_ematk(bl, sc, status->matk_max); + //This is the only portion in MATK that varies depending on the weapon level and refinement rate. + if( status->rhw.matk > 0 ){ + int wMatk = status->rhw.matk; + int variance = wMatk * status->rhw.wlv / 10; + status->matk_min += wMatk - variance; + status->matk_max += wMatk + variance; + } + } #endif - status->matk_max = status_base_matk_max(status); - - if( bl->type&BL_PC && sd->matk_rate != 100 ) - { - //Bonuses from previous matk -#ifndef RENEWAL // only changed in non-renewal [Ind] + if (bl->type&BL_PC && sd->matk_rate != 100) { status->matk_max = status->matk_max * sd->matk_rate/100; -#endif status->matk_min = status->matk_min * sd->matk_rate/100; } status->matk_min = status_calc_matk(bl, sc, status->matk_min); - -#ifndef RENEWAL // only changed in non-renewal [Ind] status->matk_max = status_calc_matk(bl, sc, status->matk_max); -#endif - if( bl->type&BL_HOM && battle_config.hom_setting&0x20 ) //Hom Min Matk is always the same as Max Matk - status->matk_min = status->matk_max; + if ((bl->type&BL_HOM && battle_config.hom_setting&0x20) //Hom Min Matk is always the same as Max Matk + || sc->data[SC_RECOGNIZEDSPELL]) + status->matk_min = status->matk_max; + +#ifdef RENEWAL + if( sd && sd->right_weapon.overrefine > 0){ + status->matk_min++; + status->matk_max += sd->right_weapon.overrefine - 1; + } +#endif } @@ -4000,10 +3990,17 @@ void status_calc_bl_(struct block_list* bl, enum scb_flag flag, bool first) clif_updatestatus(sd,SP_FLEE2); if(b_status.cri != status->cri) clif_updatestatus(sd,SP_CRITICAL); +#ifndef RENEWAL if(b_status.matk_max != status->matk_max) clif_updatestatus(sd,SP_MATK1); if(b_status.matk_min != status->matk_min) + clif_updatestatus(sd,SP_MATK2); +#else + if(b_status.matk_max != status->matk_max || b_status.matk_min != status->matk_min){ clif_updatestatus(sd,SP_MATK2); + clif_updatestatus(sd,SP_MATK1); + } +#endif if(b_status.mdef != status->mdef){ clif_updatestatus(sd,SP_MDEF1); #ifdef RENEWAL @@ -4531,28 +4528,16 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan return (unsigned short)cap_value(watk,0,USHRT_MAX); } - -static unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc, int matk) +#ifdef RENEWAL +static unsigned short status_calc_ematk(struct block_list *bl, struct status_change *sc, int matk) { - if(!sc || !sc->count) - return cap_value(matk,0,USHRT_MAX); - - if(sc->data[SC_MATKPOTION]) - matk += sc->data[SC_MATKPOTION]->val1; - if(sc->data[SC_MATKFOOD]) - matk += sc->data[SC_MATKFOOD]->val1; - if(sc->data[SC_MAGICPOWER] && sc->data[SC_MAGICPOWER]->val4) - matk += matk * sc->data[SC_MAGICPOWER]->val3/100; - if(sc->data[SC_MINDBREAKER]) - matk += matk * sc->data[SC_MINDBREAKER]->val2/100; - if(sc->data[SC_INCMATKRATE]) - matk += matk * sc->data[SC_INCMATKRATE]->val1/100; - if(sc->data[SC_MOONLITSERENADE]) - matk += matk * sc->data[SC_MOONLITSERENADE]->val2/100; - if(sc->data[SC_MELODYOFSINK]) - matk += matk * sc->data[SC_MELODYOFSINK]->val3/100; - if(sc->data[SC_BEYONDOFWARCRY]) - matk -= matk * sc->data[SC_BEYONDOFWARCRY]->val3/100; + + if (!sc || !sc->count) + return cap_value(matk,0,USHRT_MAX); + if (sc->data[SC_MATKPOTION]) + matk += sc->data[SC_MATKPOTION]->val1; + if (sc->data[SC_MATKFOOD]) + matk += sc->data[SC_MATKFOOD]->val1; if(sc->data[SC_MANA_PLUS]) matk += sc->data[SC_MANA_PLUS]->val1; if(sc->data[SC_AQUAPLAY_OPTION]) @@ -4567,6 +4552,46 @@ static unsigned short status_calc_matk(struct block_list *bl, struct status_chan matk += 40 + 30 * sc->data[SC_ODINS_POWER]->val1; //70 lvl1, 100lvl2 if(sc->data[SC_IZAYOI]) matk += 50 * sc->data[SC_IZAYOI]->val1; + return (unsigned short)cap_value(matk,0,USHRT_MAX); +} +#endif +static unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc, int matk) +{ + if(!sc || !sc->count) + return cap_value(matk,0,USHRT_MAX); +#ifndef RENEWAL + // take note fixed value first before % modifiers + if (sc->data[SC_MATKPOTION]) + matk += sc->data[SC_MATKPOTION]->val1; + if (sc->data[SC_MATKFOOD]) + matk += sc->data[SC_MATKFOOD]->val1; + if (sc->data[SC_MANA_PLUS]) + matk += sc->data[SC_MANA_PLUS]->val1; + if (sc->data[SC_AQUAPLAY_OPTION]) + matk += sc->data[SC_AQUAPLAY_OPTION]->val2; + if (sc->data[SC_CHILLY_AIR_OPTION]) + matk += sc->data[SC_CHILLY_AIR_OPTION]->val2; + if (sc->data[SC_WATER_BARRIER]) + matk -= sc->data[SC_WATER_BARRIER]->val3; + if (sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 3) + matk += 50; + if (sc->data[SC_ODINS_POWER]) + matk += 40 + 30 * sc->data[SC_ODINS_POWER]->val1; //70 lvl1, 100lvl2 + if (sc->data[SC_IZAYOI]) + matk += 50 * sc->data[SC_IZAYOI]->val1; +#endif + if (sc->data[SC_MAGICPOWER]) + matk += matk * sc->data[SC_MAGICPOWER]->val3/100; + if (sc->data[SC_MINDBREAKER]) + matk += matk * sc->data[SC_MINDBREAKER]->val2/100; + if (sc->data[SC_INCMATKRATE]) + matk += matk * sc->data[SC_INCMATKRATE]->val1/100; + if (sc->data[SC_MOONLITSERENADE]) + matk += matk * sc->data[SC_MOONLITSERENADE]->val2/100; + if (sc->data[SC_MELODYOFSINK]) + matk += matk * sc->data[SC_MELODYOFSINK]->val3/100; + if (sc->data[SC_BEYONDOFWARCRY]) + matk -= matk * sc->data[SC_BEYONDOFWARCRY]->val3/100; if( sc->data[SC_ZANGETSU] ) matk += matk * sc->data[SC_ZANGETSU]->val2 / 100; @@ -6160,6 +6185,14 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti //No defense against it (buff). rate -= (status_get_lv(bl) / 5 + status->vit / 4 + status->agi / 10)*100; // Lineal Reduction of Rate break; + case SC_MARSHOFABYSS: + //5 second (Fixed) + 25 second - {( INT + LUK ) / 20 second } + tick -= (status->int_ + status->luk) / 20 * 1000; + break; + case SC_STASIS: + //5 second (fixed) + { Stasis Skill level * 5 - (Target�s VIT + DEX) / 20 } + tick -= (status->vit + status->dex) / 20 * 1000; + break; case SC_WHITEIMPRISON: if( tick == 5000 ) // 100% on caster break; @@ -6941,6 +6974,9 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_INVINCIBLEOFF: status_change_end(bl, SC_INVINCIBLE, INVALID_TIMER); break; + case SC_MAGICPOWER: + status_change_end(bl, type, INVALID_TIMER); + break; } //Check for overlapping fails @@ -10563,15 +10599,10 @@ int status_change_clear_buffs (struct block_list* bl, int type) if (!sc || !sc->count) return 0; - if (type&6) //Debuffs for (i = SC_COMMON_MIN; i <= SC_COMMON_MAX; i++) status_change_end(bl, (sc_type)i, INVALID_TIMER); - for (i = SC_COMMON_MAX+1; i < SC_MAX; i++) { - if (!sc->data[i]) - continue; - for( i = SC_COMMON_MAX+1; i < SC_MAX; i++ ) { if(!sc->data[i]) diff --git a/src/map/status.h b/src/map/status.h index 402dfc690..82bd7ba8a 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -1567,6 +1567,9 @@ struct weapon_atk { unsigned short atk, atk2; unsigned short range; unsigned char ele; +#ifdef RENEWAL + unsigned short matk, wlv; +#endif }; @@ -1596,12 +1599,6 @@ struct status_data { unsigned char def_ele, ele_lv, -#ifdef RENEWAL - /** - * in RE weapon level is used in several areas, keeping it here saves performance - **/ - wlv, -#endif size, race; struct weapon_atk rhw, lhw; //Right Hand/Left Hand Weapon. @@ -1752,12 +1749,6 @@ unsigned char status_calc_attack_element(struct block_list *bl, struct status_ch #define status_get_race(bl) status_get_status_data(bl)->race #define status_get_size(bl) status_get_status_data(bl)->size #define status_get_mode(bl) status_get_status_data(bl)->mode -#ifdef RENEWAL - /** - * in RE weapon level is used in several areas, keeping it here saves performance - **/ - #define status_get_wlv(bl) status_get_status_data(bl)->wlv -#endif int status_get_party_id(struct block_list *bl); int status_get_guild_id(struct block_list *bl); int status_get_emblem_id(struct block_list *bl); @@ -1812,6 +1803,10 @@ int status_check_visibility(struct block_list *src, struct block_list *target); int status_change_spread( struct block_list *src, struct block_list *bl ); +#ifdef RENEWAL +unsigned short status_base_matk(const struct status_data* status, int level); +#endif + int status_readdb(void); int do_init_status(void); void do_final_status(void); |