diff --git a/src/map/battle.c b/src/map/battle.c index b205d6df98..e8f6e7c430 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -40,9 +40,10 @@ int attr_fix_table[4][ELE_NONE][ELE_NONE]; struct Battle_Config battle_config; static struct eri *delay_damage_ers; //For battle delay damage structures. -#define DAMAGE_RATE(a){damage = (int64)damage * (a)/100;} -#define DAMAGE_SUBRATE(a){damage -= (int64)damage * (a)/100;} -#define DAMAGE_ADDRATE(a){damage += (int64)damage * (a)/100;} +#define DAMAGE_RATE(a) { damage = (int64)damage * (a) / 100; } +#define DAMAGE_SUBRATE(a) { damage -= (int64)damage * (a) / 100; } +#define DAMAGE_ADDRATE(a) { damage += (int64)damage * (a) / 100; } + int battle_getcurrentskill(struct block_list *bl) { //Returns the current/last skill in use by this bl. struct unit_data *ud; @@ -362,7 +363,7 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d if( tsc && tsc->count ) { //increase dmg by target status - switch(atk_elem){ + switch(atk_elem) { case ELE_FIRE: if( tsc->data[SC_SPIDERWEB]) { tsc->data[SC_SPIDERWEB]->val1 = 0; // free to move now @@ -1043,14 +1044,16 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam //Reduction: 6% + 6% every 20% DAMAGE_SUBRATE(6 * (1+per)) } + if(sc->data[SC_GRANITIC_ARMOR]) DAMAGE_SUBRATE(sc->data[SC_GRANITIC_ARMOR]->val2) - if(sc->data[SC_PAIN_KILLER]){ - damage -= sc->data[SC_PAIN_KILLER]->val3; - damage = max(1,damage); - } - if( sc->data[SC_DARKCROW] && ((flag&(BF_WEAPON|BF_SHORT))==(BF_WEAPON|BF_SHORT)) ) + + if(sc->data[SC_PAIN_KILLER]) + DAMAGE_SUBRATE(sc->data[SC_PAIN_KILLER]->val3); + + if( sc->data[SC_DARKCROW] && (flag&(BF_SHORT|BF_MAGIC)) == BF_SHORT ) DAMAGE_ADDRATE(sc->data[SC_DARKCROW]->val2); + if( (sce=sc->data[SC_MAGMA_FLOW]) && (rnd()%100 <= sce->val2) ) skill_castend_damage_id(bl,src,MH_MAGMA_FLOW,sce->val1,gettick(),0); @@ -1064,12 +1067,10 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam status_change_end(bl, SC_STONEHARDSKIN, INVALID_TIMER); } - #ifdef RENEWAL // Renewal: steel body reduces all incoming damage to 1/10 [helvetica] - if( sc->data[SC_STEELBODY] ) { + if( sc->data[SC_STEELBODY] ) damage = damage > 10 ? damage / 10 : 1; - } #endif //Finally added to remove the status of immobile when Aimed Bolt is used. [Jobbie] @@ -1096,12 +1097,14 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam damage = 0; - if (!damage) return 0; + if (!damage) + return 0; if( (sce = sc->data[SC_LIGHTNINGWALK]) && flag&BF_LONG && rnd()%100 < sce->val1 ) { int dx[8]={0,-1,-1,-1,0,1,1,1}; int dy[8]={1,1,0,-1,-1,-1,0,1}; uint8 dir = map_calc_dir(bl, src->x, src->y); + if( unit_movepos(bl, src->x-dx[dir], src->y-dy[dir], 1, 1) ) { clif_slide(bl,src->x-dx[dir],src->y-dy[dir]); unit_setdir(bl, dir); @@ -1119,10 +1122,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam if( sd && (sce = sc->data[SC_FORCEOFVANGUARD]) && flag&BF_WEAPON && rnd()%100 < sce->val2 ) pc_addspiritball(sd,skill_get_time(LG_FORCEOFVANGUARD,sce->val1),sce->val3); - if (sc->data[SC_STYLE_CHANGE] && sc->data[SC_STYLE_CHANGE]->val1 == MH_MD_GRAPPLING) { - TBL_HOM *hd = BL_CAST(BL_HOM,bl); // We add a sphere for when the Homunculus is being hit - if (hd && (rnd()%100<50) ) hom_addspiritball(hd, 10); // According to WarpPortal, this is a flat 50% chance - } + if( sd && (sce = sc->data[SC_GT_ENERGYGAIN]) && flag&BF_WEAPON && rnd()%100 < sce->val2 ) { int spheres = 5; @@ -1131,6 +1131,13 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam pc_addspiritball(sd, skill_get_time2(SR_GENTLETOUCH_ENERGYGAIN, sce->val1), spheres); } + if (sc->data[SC_STYLE_CHANGE] && sc->data[SC_STYLE_CHANGE]->val1 == MH_MD_GRAPPLING) { + TBL_HOM *hd = BL_CAST(BL_HOM,bl); // We add a sphere for when the Homunculus is being hit + + if (hd && (rnd()%100<50) ) // According to WarpPortal, this is a flat 50% chance + hom_addspiritball(hd, 10); + } + if( sc->data[SC__DEADLYINFECT] && (flag&(BF_SHORT|BF_MAGIC)) == BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * sc->data[SC__DEADLYINFECT]->val1 ) status_change_spread(bl, src); // Deadly infect attacked side @@ -1168,14 +1175,18 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam skill_break_equip(src,bl, EQP_ARMOR, 10000, BCT_ENEMY); // 100% chance (http://irowiki.org/wiki/Shield_Spell#Level_3_spells_.28refine_based.29) status_change_end(src,SC_SHIELDSPELL_REF,INVALID_TIMER); } + if( sc->data[SC_POISONINGWEAPON] && ((flag&BF_WEAPON) && (!skill_id || skill_id == GC_VENOMPRESSURE)) //check skill type poison_smoke is a unit && (damage > 0 && rnd()%100 < sc->data[SC_POISONINGWEAPON]->val3 )) //did some damage and chance ok (why no additional effect ??) sc_start(src,bl,(enum sc_type)sc->data[SC_POISONINGWEAPON]->val2,100,sc->data[SC_POISONINGWEAPON]->val1,skill_get_time2(GC_POISONINGWEAPON, 1)); + if( sc->data[SC__DEADLYINFECT] && (flag&(BF_SHORT|BF_MAGIC)) == BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * sc->data[SC__DEADLYINFECT]->val1 ) status_change_spread(src, bl); + if (sc->data[SC_STYLE_CHANGE] && sc->data[SC_STYLE_CHANGE]->val1 == MH_MD_FIGHTING) { TBL_HOM *hd = BL_CAST(BL_HOM,src); //when attacking + if (hd && (rnd()%100<50) ) hom_addspiritball(hd, 10); // According to WarpPortal, this is a flat 50% chance } } //End of caster SC_ check @@ -1222,8 +1233,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam else if( (sstatus = status_get_status_data(src)) ) { element = sstatus->rhw.ele; } - } - else if( element == -2 ) //Use enchantment's element + } else if( element == -2 ) //Use enchantment's element element = status_get_attack_sc_element(src,status_get_sc(src)); else if( element == -3 ) //Use random element element = rnd()%ELE_ALL; @@ -1253,8 +1263,10 @@ int64 battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int64 if( map[bl->m].flag.battleground && (md->mob_id == MOBID_BLUE_CRYST || md->mob_id == MOBID_PINK_CRYST) && flag&BF_SKILL ) return 0; // Crystal cannot receive skill damage on battlegrounds } + if(skill_get_inf2(skill_id)&INF2_NO_BG_DMG) return damage; //skill that ignore bg map reduction + if( flag&BF_SKILL ) { //Skills get a different reduction than non-skills. [Skotlex] if( flag&BF_WEAPON ) DAMAGE_RATE(battle_config.bg_weapon_damage_rate) @@ -1262,8 +1274,7 @@ int64 battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int64 DAMAGE_RATE(battle_config.bg_magic_damage_rate) if( flag&BF_MISC ) DAMAGE_RATE(battle_config.bg_misc_damage_rate) - } - else { //Normal attacks get reductions based on range. + } else { //Normal attacks get reductions based on range. if( flag&BF_SHORT ) DAMAGE_RATE(battle_config.bg_short_damage_rate) if( flag&BF_LONG ) @@ -1309,9 +1320,8 @@ int64 battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int64 if (skill_get_inf2(skill_id)&INF2_NO_GVG_DMG) //Skills with no gvg damage reduction. return damage; /* Uncomment if you want god-mode Emperiums at 100 defense. [Kisuka] - if (md && md->guardian_data) { + if (md && md->guardian_data) damage -= damage * (md->guardian_data->castle->defense/100) * battle_config.castle_defense_rate/100; - } */ if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex] if (flag&BF_WEAPON) @@ -1393,6 +1403,7 @@ int64 battle_addmastery(struct map_session_data *sd,struct block_list *target,in weapon = sd->weapontype1; else weapon = sd->weapontype2; + switch(weapon) { case W_1HSWORD: #ifdef RENEWAL @@ -1502,22 +1513,25 @@ static int battle_calc_base_weapon_attack(struct block_list *src, struct status_ if (sd->equip_index[type] >= 0 && sd->inventory_data[sd->equip_index[type]]) { int variance = wa->atk * (sd->inventory_data[sd->equip_index[type]]->wlv*5)/100; - atkmin = max(0,atkmin-variance); - atkmax = min(UINT16_MAX,atkmax+variance); + + atkmin = max(0, atkmin - variance); + atkmax = min(UINT16_MAX, atkmax + variance); if (sc && sc->data[SC_MAXIMIZEPOWER]) damage = atkmax; else - damage = rnd_value(atkmin,atkmax); + damage = rnd_value(atkmin, atkmax); } if (sc && sc->data[SC_WEAPONPERFECTION]) weapon_perfection = 1; + damage = (int)battle_calc_sizefix(damage, sd, tstatus->size, type, weapon_perfection); return damage; } #endif + /*========================================== * Calculates the standard damage of a normal attack assuming it hits, * it calculates nothing extra fancy, is needed for magnum break's WATK_ELEMENT bonus. [Skotlex] @@ -1634,7 +1648,8 @@ static int64 battle_calc_base_damage(struct status_data *status, struct weapon_a */ void battle_consume_ammo(TBL_PC*sd, int skill, int lv) { - int qty=1; + int qty = 1; + if (!battle_config.arrow_decrement) return; @@ -1826,9 +1841,11 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * static bool target_has_infinite_defense(struct block_list *target, int skill_id) { struct status_data *tstatus = status_get_status_data(target); - if(target->type == BL_SKILL){ - TBL_SKILL *su = (TBL_SKILL*)target; - if( su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) ) + + if(target->type == BL_SKILL) { + TBL_SKILL *su = ((TBL_SKILL*)target); + + if (su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD)) return true; } return (tstatus->mode&MD_PLANT && skill_id != RA_CLUSTERBOMB @@ -1851,6 +1868,7 @@ static bool is_skill_using_arrow(struct block_list *src, int skill_id) if(src != NULL) { struct status_data *sstatus = status_get_status_data(src); struct map_session_data *sd = BL_CAST(BL_PC, src); + return ((sd && sd->state.arrow_atk) || (!sd && ((skill_id && skill_get_ammotype(skill_id)) || sstatus->rhw.range>3)) || (skill_id == HT_PHANTASMIC)); } else return false; @@ -1928,13 +1946,12 @@ static bool is_attack_critical(struct Damage wd, struct block_list *src, struct if (skill_id == NPC_CRITICALSLASH || skill_id == LG_PINPOINTATTACK) //Always critical skills return true; - if( !(wd.type&0x08) && sstatus->cri && - (!skill_id || - skill_id == KN_AUTOCOUNTER || - skill_id == SN_SHARPSHOOTING || skill_id == MA_SHARPSHOOTING || - skill_id == NJ_KIRIKAGE)) + if( !(wd.type&0x08) && sstatus->cri && (!skill_id || + skill_id == KN_AUTOCOUNTER || skill_id == SN_SHARPSHOOTING || + skill_id == MA_SHARPSHOOTING || skill_id == NJ_KIRIKAGE)) { short cri = sstatus->cri; + if (sd) { cri += sd->critaddrace[tstatus->race] + sd->critaddrace[RC_ALL]; if(is_skill_using_arrow(src, skill_id)) @@ -2050,14 +2067,11 @@ static bool is_attack_hitting(struct Damage wd, struct block_list *src, struct b struct status_change *sc = status_get_sc(src); struct status_change *tsc = status_get_sc(target); struct map_session_data *sd = BL_CAST(BL_PC, src); - int nk; + int nk = battle_skill_get_damage_properties(skill_id, wd.miscflag); short flee, hitrate; if (!first_call) return (wd.dmg_lv != ATK_FLEE); - - nk = battle_skill_get_damage_properties(skill_id, wd.miscflag); - if (is_attack_critical(wd, src, target, skill_id, skill_lv, false)) return true; else if(sd && sd->bonus.perfect_hit > 0 && rnd()%100 < sd->bonus.perfect_hit) @@ -2088,84 +2102,87 @@ static bool is_attack_hitting(struct Damage wd, struct block_list *src, struct b if(attacker_count >= battle_config.agi_penalty_count) { if (battle_config.agi_penalty_type == 1) - flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100; + flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1)) * battle_config.agi_penalty_num)) / 100; else //assume type 2: absolute reduction - flee -= (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num; - if(flee < 1) flee = 1; + flee -= (attacker_count - (battle_config.agi_penalty_count - 1)) * battle_config.agi_penalty_num; + if(flee < 1) + flee = 1; } } - hitrate+= sstatus->hit - flee; + hitrate += sstatus->hit - flee; - if(wd.flag&BF_LONG && !skill_id && //Fogwall's hit penalty is only for normal ranged attacks. - tsc && tsc->data[SC_FOGWALL]) + //Fogwall's hit penalty is only for normal ranged attacks. + if ((wd.flag&(BF_LONG|BF_MAGIC)) == BF_LONG && !skill_id && tsc && tsc->data[SC_FOGWALL]) hitrate -= 50; if(sd && is_skill_using_arrow(src, skill_id)) hitrate += sd->bonus.arrow_hit; + #ifdef RENEWAL - if( sd ) //in Renewal hit bonus from Vultures Eye is not anymore shown in status window + if (sd) //in Renewal hit bonus from Vultures Eye is not anymore shown in status window hitrate += pc_checkskill(sd,AC_VULTURE); #endif - if(skill_id) - switch(skill_id) { //Hit skill modifiers - //It is proven that bonus is applied on final hitrate, not hit. - case SM_BASH: - case MS_BASH: - hitrate += hitrate * 5 * skill_lv / 100; - break; - case MS_MAGNUM: - case SM_MAGNUM: - hitrate += hitrate * 10 * skill_lv / 100; - break; - case KN_AUTOCOUNTER: - case PA_SHIELDCHAIN: - case NPC_WATERATTACK: - case NPC_GROUNDATTACK: - case NPC_FIREATTACK: - case NPC_WINDATTACK: - case NPC_POISONATTACK: - case NPC_HOLYATTACK: - case NPC_DARKNESSATTACK: - case NPC_UNDEADATTACK: - case NPC_TELEKINESISATTACK: - case NPC_BLEEDING: - hitrate += hitrate * 20 / 100; - break; - case KN_PIERCE: - case ML_PIERCE: - hitrate += hitrate * 5 * skill_lv / 100; - break; - case AS_SONICBLOW: - if(sd && pc_checkskill(sd,AS_SONICACCEL)>0) - hitrate += hitrate * 50 / 100; - break; - case MC_CARTREVOLUTION: - case GN_CART_TORNADO: - case GN_CARTCANNON: - if( sd && pc_checkskill(sd, GN_REMODELING_CART) ) - hitrate += pc_checkskill(sd, GN_REMODELING_CART) * 4; - break; - case LG_BANISHINGPOINT: - hitrate += 3 * skill_lv; - break; - case GC_VENOMPRESSURE: - hitrate += 10 + 4 * skill_lv; - break; - case SC_FATALMENACE: - hitrate -= 35 - 5 * skill_lv; - break; - case RL_SLUGSHOT: - if (distance_bl(src,target) > 3) - hitrate -= (10 - (skill_lv - 1)); - break; - } - else if( sd && wd.type&0x08 && wd.div_ == 2 ) // +1 hit per level of Double Attack on a successful double attack (making sure other multi attack skills do not trigger this) [helvetica] + if(skill_id) { + switch(skill_id) { //Hit skill modifiers + //It is proven that bonus is applied on final hitrate, not hit. + case SM_BASH: + case MS_BASH: + hitrate += hitrate * 5 * skill_lv / 100; + break; + case MS_MAGNUM: + case SM_MAGNUM: + hitrate += hitrate * 10 * skill_lv / 100; + break; + case KN_AUTOCOUNTER: + case PA_SHIELDCHAIN: + case NPC_WATERATTACK: + case NPC_GROUNDATTACK: + case NPC_FIREATTACK: + case NPC_WINDATTACK: + case NPC_POISONATTACK: + case NPC_HOLYATTACK: + case NPC_DARKNESSATTACK: + case NPC_UNDEADATTACK: + case NPC_TELEKINESISATTACK: + case NPC_BLEEDING: + hitrate += hitrate * 20 / 100; + break; + case KN_PIERCE: + case ML_PIERCE: + hitrate += hitrate * 5 * skill_lv / 100; + break; + case AS_SONICBLOW: + if(sd && pc_checkskill(sd,AS_SONICACCEL) > 0) + hitrate += hitrate * 50 / 100; + break; + case MC_CARTREVOLUTION: + case GN_CART_TORNADO: + case GN_CARTCANNON: + if (sd && pc_checkskill(sd, GN_REMODELING_CART)) + hitrate += pc_checkskill(sd, GN_REMODELING_CART) * 4; + break; + case LG_BANISHINGPOINT: + hitrate += 3 * skill_lv; + break; + case GC_VENOMPRESSURE: + hitrate += 10 + 4 * skill_lv; + break; + case SC_FATALMENACE: + hitrate -= 35 - 5 * skill_lv; + break; + case RL_SLUGSHOT: + if (distance_bl(src,target) > 3) + hitrate -= (10 - (skill_lv - 1)); + break; + } + } else if (sd && wd.type&0x08 && wd.div_ == 2) // +1 hit per level of Double Attack on a successful double attack (making sure other multi attack skills do not trigger this) [helvetica] hitrate += pc_checkskill(sd,TF_DOUBLE); - if( sd ) { + if (sd) { int skill = 0; + #ifdef RENEWAL // Weaponry Research hidden bonus if ((skill = pc_checkskill(sd,BS_WEAPONRESEARCH)) > 0) @@ -2177,12 +2194,15 @@ static bool is_attack_hitting(struct Damage wd, struct block_list *src, struct b hitrate += 3 * skill; } + if(sc && sc->data[SC_MTF_ASPD]) + hitrate += 5; + hitrate = cap_value(hitrate, battle_config.min_hitrate, battle_config.max_hitrate); return (rnd()%100 < hitrate); } /*========================================== - * If attack ignores def.. + * If attack ignores def. *------------------------------------------ * Credits: * Original coder Skoltex @@ -2194,8 +2214,8 @@ static bool attack_ignores_def(struct Damage wd, struct block_list *src, struct struct status_data *tstatus = status_get_status_data(target); struct status_change *sc = status_get_sc(src); struct map_session_data *sd = BL_CAST(BL_PC, src); - int nk = battle_skill_get_damage_properties(skill_id, wd.miscflag); + #ifndef RENEWAL if (is_attack_critical(wd, src, target, skill_id, skill_lv, false)) return true; @@ -2263,11 +2283,13 @@ static bool battle_skill_stacks_masteries_vvs(uint16 skill_id) static int battle_calc_equip_attack(struct block_list *src, int skill_id) { if(src != NULL) { - int eatk=0; + int eatk = 0; struct status_data *status = status_get_status_data(src); struct map_session_data *sd = BL_CAST(BL_PC, src); - if(sd) eatk += is_skill_using_arrow(src, skill_id) ? sd->bonus.arrow_atk : 0; // add arrow atk if using an applicable skill + if (sd) // add arrow atk if using an applicable skill + eatk += (is_skill_using_arrow(src, skill_id) ? sd->bonus.arrow_atk : 0); + return eatk + status->eatk; } return 0; // shouldn't happen but just in case @@ -2288,7 +2310,6 @@ static int battle_get_weapon_element(struct Damage wd, struct block_list *src, s struct status_change *sc = status_get_sc(src); struct status_data *sstatus = status_get_status_data(src); uint8 i; - int nk = battle_skill_get_damage_properties(skill_id, wd.miscflag); int element = skill_get_ele(skill_id, skill_lv); //Take weapon's element @@ -2299,20 +2320,17 @@ static int battle_get_weapon_element(struct Damage wd, struct block_list *src, s element = sstatus->lhw.ele; if(is_skill_using_arrow(src, skill_id) && sd && sd->bonus.arrow_ele && weapon_position == EQI_HAND_R) element = sd->bonus.arrow_ele; - if( battle_config.attack_attr_none&src->type ) - element = ELE_NONE; //Weapon's element is "not elemental" // on official endows override all other elements [helvetica] - if( sd ){ //Summoning 10 talisman will endow your weapon. + if (sd) { //Summoning 10 talisman will endow your weapon. ARR_FIND(1, 6, i, sd->talisman[i] >= 10); - if( i < 5 ) + if (i < 5) element = i; - if(sc) { // check for endows + if (sc) { // check for endows if(sc->data[SC_ENCHANTARMS]) element = sc->data[SC_ENCHANTARMS]->val2; } } - } - else if( element == -2 ) //Use enchantment's element + } else if( element == -2 ) //Use enchantment's element element = status_get_attack_sc_element(src,sc); else if( element == -3 ) //Use random element element = rnd()%ELE_ALL; @@ -2335,21 +2353,16 @@ static int battle_get_weapon_element(struct Damage wd, struct block_list *src, s break; } - if (!(nk & NK_NO_ELEFIX) && element != ELE_NONE) - if (src->type == BL_HOM) - element = ELE_NONE; //skill is "not elemental" - - if (sc && sc->data[SC_GOLDENE_FERSE] && ((!skill_id && (rnd() % 100 < sc->data[SC_GOLDENE_FERSE]->val4)) || skill_id == MH_STAHL_HORN)) { + if (sc && sc->data[SC_GOLDENE_FERSE] && ((!skill_id && (rnd() % 100 < sc->data[SC_GOLDENE_FERSE]->val4)) || skill_id == MH_STAHL_HORN)) element = ELE_HOLY; - } // calc_flag means the element should be calculated for damage only -if (calc_for_damage_only) - return element; + if (calc_for_damage_only) + return element; #ifdef RENEWAL - if (skill_id == CR_SHIELDBOOMERANG) - element = ELE_NEUTRAL; + if (skill_id == CR_SHIELDBOOMERANG) + element = ELE_NEUTRAL; #endif return element; @@ -2369,21 +2382,29 @@ static struct Damage battle_calc_element_damage(struct Damage wd, struct block_l struct status_change *sc = status_get_sc(src); struct status_data *sstatus = status_get_status_data(src); struct status_data *tstatus = status_get_status_data(target); + int element = skill_get_ele(skill_id, skill_lv); int left_element = battle_get_weapon_element(wd, src, target, skill_id, skill_lv, EQI_HAND_L, true); int right_element = battle_get_weapon_element(wd, src, target, skill_id, skill_lv, EQI_HAND_R, true); - int nk = battle_skill_get_damage_properties(skill_id, wd.miscflag); - if( !(nk&NK_NO_ELEFIX) && right_element != ELE_NONE ) - { //Elemental attribute fix - if( wd.damage > 0 ) - { + //Elemental attribute fix + if(!(nk&NK_NO_ELEFIX)) { + //Non-pc physical melee attacks (mob, pet, homun) are "non elemental", they deal 100% to all target elements + //However the "non elemental" attacks still get reduced by "Neutral resistance" + //Also non-pc units have only a defending element, but can inflict elemental attacks using skills [exneval] + if(battle_config.attack_attr_none&src->type) + if(((!skill_id && !right_element) || (skill_id && (element == -1 || !right_element))) && + (wd.flag&(BF_SHORT|BF_WEAPON)) == (BF_SHORT|BF_WEAPON)) + return wd; + if(wd.damage > 0) { + //Forced to its element wd.damage = battle_attr_fix(src, target, wd.damage, right_element, tstatus->def_ele, tstatus->ele_lv); switch( skill_id ) { - case MC_CARTREVOLUTION: //Cart Revolution apply the element fix once more with neutral element + case MC_CARTREVOLUTION: case SR_GATEOFHELL: case KO_BAKURETSU: + //Forced to neutral element wd.damage = battle_attr_fix(src, target, wd.damage, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv); break; case GS_GROUNDDRIFT: @@ -2397,15 +2418,14 @@ static struct Damage battle_calc_element_damage(struct Damage wd, struct block_l break; } } - if( is_attack_left_handed(src, skill_id) && wd.damage2 > 0 ) + if (is_attack_left_handed(src, skill_id) && wd.damage2 > 0) wd.damage2 = battle_attr_fix(src, target, wd.damage2, left_element ,tstatus->def_ele, tstatus->ele_lv); - if( sc && sc->data[SC_WATK_ELEMENT] ) - { // Descriptions indicate this means adding a percent of a normal attack in another element. [Skotlex] + if (sc && sc->data[SC_WATK_ELEMENT]) { + // Descriptions indicate this means adding a percent of a normal attack in another element. [Skotlex] int64 damage = battle_calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, (is_skill_using_arrow(src, skill_id)?2:0)) * sc->data[SC_WATK_ELEMENT]->val2 / 100; - wd.damage += battle_attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv); - if( is_attack_left_handed(src, skill_id) ) - { + wd.damage += battle_attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv); + if (is_attack_left_handed(src, skill_id)) { damage = battle_calc_base_damage(sstatus, &sstatus->lhw, sc, tstatus->size, sd, (is_skill_using_arrow(src, skill_id)?2:0)) * sc->data[SC_WATK_ELEMENT]->val2 / 100; wd.damage2 += battle_attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv); } @@ -2414,25 +2434,25 @@ static struct Damage battle_calc_element_damage(struct Damage wd, struct block_l return wd; } -#define ATK_RATE(damage, damage2, a ) {damage= damage*(a)/100 ; if(is_attack_left_handed(src, skill_id)) damage2= damage2*(a)/100; } -#define ATK_RATE2(damage, damage2, a , b ) { damage= damage*(a)/100 ; if(is_attack_left_handed(src, skill_id)) damage2= damage2*(b)/100; } -#define ATK_RATER(damage, a){ damage = (int64)damage*(a)/100;} -#define ATK_RATEL(damage2, a){ damage2 = (int64)damage2*(a)/100;} +#define ATK_RATE(damage, damage2, a) { damage = damage * (a) / 100; if(is_attack_left_handed(src, skill_id)) damage2 = damage2 * (a) / 100; } +#define ATK_RATE2(damage, damage2, a , b) { damage = damage *(a) / 100; if(is_attack_left_handed(src, skill_id)) damage2 = damage2 * (b) / 100; } +#define ATK_RATER(damage, a) { damage = damage * (a) / 100; } +#define ATK_RATEL(damage2, a) { damage2 = damage2 * (a) / 100; } //Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage -#define ATK_ADDRATE(damage, damage2, a ) { damage+= damage*(a)/100 ; if(is_attack_left_handed(src, skill_id)) damage2+= damage2*(a)/100; } -#define ATK_ADDRATE2(damage, damage2, a , b ) { damage+= damage*(a)/100 ; if(is_attack_left_handed(src, skill_id)) damage2+= damage2*(b)/100; } +#define ATK_ADDRATE(damage, damage2, a) { damage += damage * (a) / 100; if(is_attack_left_handed(src, skill_id)) damage2 += damage2 *(a) / 100; } +#define ATK_ADDRATE2(damage, damage2, a , b) { damage += damage * (a) / 100; if(is_attack_left_handed(src, skill_id)) damage2 += damage2 * (b) / 100; } //Adds an absolute value to damage. 100 = +100 damage -#define ATK_ADD(damage, damage2, a ) { damage+= a; if (is_attack_left_handed(src, skill_id)) damage2+= a; } -#define ATK_ADD2(damage, damage2, a , b ) { damage+= a; if (is_attack_left_handed(src, skill_id)) damage2+= b; } +#define ATK_ADD(damage, damage2, a) { damage += a; if(is_attack_left_handed(src, skill_id)) damage2 += a; } +#define ATK_ADD2(damage, damage2, a , b) { damage += a; if(is_attack_left_handed(src, skill_id)) damage2 += b; } #ifdef RENEWAL -#define RE_ALLATK_ADD(wd, a ) {ATK_ADD(wd.statusAtk, wd.statusAtk2, a); ATK_ADD(wd.weaponAtk, wd.weaponAtk2, a); ATK_ADD(wd.equipAtk, wd.equipAtk2, a); ATK_ADD(wd.masteryAtk, wd.masteryAtk2, a); } -#define RE_ALLATK_RATE(wd, a ) {ATK_RATE(wd.statusAtk, wd.statusAtk2, a); ATK_RATE(wd.weaponAtk, wd.weaponAtk2, a); ATK_RATE(wd.equipAtk, wd.equipAtk2, a); ATK_RATE(wd.masteryAtk, wd.masteryAtk2, a); } -#define RE_ALLATK_ADDRATE(wd, a ) {ATK_ADDRATE(wd.statusAtk, wd.statusAtk2, a); ATK_ADDRATE(wd.weaponAtk, wd.weaponAtk2, a); ATK_ADDRATE(wd.equipAtk, wd.equipAtk2, a); ATK_ADDRATE(wd.masteryAtk, wd.masteryAtk2, a); } + #define RE_ALLATK_ADD(wd, a) { ATK_ADD(wd.statusAtk, wd.statusAtk2, a); ATK_ADD(wd.weaponAtk, wd.weaponAtk2, a); ATK_ADD(wd.equipAtk, wd.equipAtk2, a); ATK_ADD(wd.masteryAtk, wd.masteryAtk2, a); } + #define RE_ALLATK_RATE(wd, a) { ATK_RATE(wd.statusAtk, wd.statusAtk2, a); ATK_RATE(wd.weaponAtk, wd.weaponAtk2, a); ATK_RATE(wd.equipAtk, wd.equipAtk2, a); ATK_RATE(wd.masteryAtk, wd.masteryAtk2, a); } + #define RE_ALLATK_ADDRATE(wd, a) { ATK_ADDRATE(wd.statusAtk, wd.statusAtk2, a); ATK_ADDRATE(wd.weaponAtk, wd.weaponAtk2, a); ATK_ADDRATE(wd.equipAtk, wd.equipAtk2, a); ATK_ADDRATE(wd.masteryAtk, wd.masteryAtk2, a); } #else -#define RE_ALLATK_ADD(wd, a ) {;} -#define RE_ALLATK_RATE(wd, a ) {;} -#define RE_ALLATK_ADDRATE(wd, a ) {;} + #define RE_ALLATK_ADD(wd, a) {;} + #define RE_ALLATK_RATE(wd, a) {;} + #define RE_ALLATK_ADDRATE(wd, a) {;} #endif /*================================== @@ -2501,7 +2521,7 @@ static struct Damage battle_calc_attack_masteries(struct Damage wd, struct block if (i == 2) skillratio += sstatus->str; //Star Anger if (skill < 4) - skillratio /= 12-3*skill; + skillratio /= 12 - 3 * skill; ATK_ADDRATE(wd.damage, wd.damage2, skillratio); #ifdef RENEWAL ATK_ADDRATE(wd.masteryAtk, wd.masteryAtk2, skillratio); @@ -2517,9 +2537,9 @@ static struct Damage battle_calc_attack_masteries(struct Damage wd, struct block } if (skill_id == NJ_SYURIKEN && (skill = pc_checkskill(sd,NJ_TOBIDOUGU)) > 0) { - ATK_ADD(wd.damage, wd.damage2, 3*skill); + ATK_ADD(wd.damage, wd.damage2, 3 * skill); #ifdef RENEWAL - ATK_ADD(wd.masteryAtk, wd.masteryAtk2, 3*skill); + ATK_ADD(wd.masteryAtk, wd.masteryAtk2, 3 * skill); #endif } } @@ -2570,6 +2590,8 @@ struct Damage battle_calc_damage_parts(struct Damage wd, struct block_list *src, wd.equipAtk2 += battle_calc_equip_attack(src, skill_id); wd.equipAtk2 = (int)battle_attr_fix(src, target, wd.equipAtk2, left_element, tstatus->def_ele, tstatus->ele_lv); + //Mastery ATK is a special kind of ATK that has no elemental properties + //Because masteries are not elemental, they are unaffected by Ghost armors or Raydric Card wd = battle_calc_attack_masteries(wd, src, target, skill_id, skill_lv); wd.damage = 0; @@ -2913,11 +2935,7 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s skillratio += sc->data[SC_P_ALTER]->val2; } - switch( skill_id ) - { - case GC_DARKCROW: - skillratio += 100 * (skill_lv - 1); - break; + switch( skill_id ) { case SM_BASH: case MS_BASH: skillratio += 30*skill_lv; @@ -3205,19 +3223,14 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s skillratio += 20*(skill_lv-1); #endif break; -#ifdef RENEWAL - case NJ_KUNAI: - skillratio *= 3; // 3x300% ATK - break; -#endif case NJ_HUUMA: skillratio += 50 + 150*skill_lv; break; case NJ_TATAMIGAESHI: + skillratio += 10 * skill_lv; #ifdef RENEWAL skillratio += 200; #endif - skillratio += 10*skill_lv; break; case NJ_KASUMIKIRI: skillratio += 10*skill_lv; @@ -3225,6 +3238,9 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s case NJ_KIRIKAGE: skillratio += 100*(skill_lv-1); break; + case NJ_KUNAI: + skillratio += 200; + break; case KN_CHARGEATK: { int k = (wd.miscflag-1)/3; //+100% every 3 cells of distance @@ -3304,7 +3320,6 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s //ATK [{(Skill Level x 100) + 300} x Caster's Base Level / 120]% + ATK [(AGI x 2) + (Caster's Job Level x 4)]% skillratio += 200 + (100 * skill_lv); RE_LVL_DMOD(120); - skillratio += status_get_agi(src) * 2 + (sd?sd->status.job_level:0) * 4; break; case GC_ROLLINGCUTTER: skillratio += -50 + 50 * skill_lv; @@ -3316,6 +3331,9 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s if( sc && sc->data[SC_ROLLINGCUTTER] ) skillratio += sc->data[SC_ROLLINGCUTTER]->val1 * status_get_agi(src); break; + case GC_DARKCROW: + skillratio += 100 * (skill_lv - 1); + break; /** * Arch Bishop **/ @@ -3803,16 +3821,7 @@ static int battle_calc_skill_constant_addition(struct Damage wd, struct block_li //Constant/misc additions from skills switch (skill_id) { case MO_EXTREMITYFIST: - atk = 250 + 150*skill_lv; - break; - case TK_DOWNKICK: - case TK_STORMKICK: - case TK_TURNKICK: - case TK_COUNTER: - case TK_JUMPKICK: - //TK_RUN kick damage bonus. - if(sd && sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST) - atk = 10*pc_checkskill(sd, TK_RUN); + atk = 250 + 150 * skill_lv; break; case GS_MAGICALBULLET: if(sstatus->matk_max>sstatus->matk_min) @@ -3823,10 +3832,12 @@ static int battle_calc_skill_constant_addition(struct Damage wd, struct block_li case NJ_SYURIKEN: atk = 4*skill_lv; break; +#ifdef RENEWAL case HT_FREEZINGTRAP: if(sd) atk = ( 40 * pc_checkskill(sd, RA_RESEARCHTRAP) ); break; +#endif case RA_WUGDASH: if( sd && sd->weight ) atk = (sd->weight / 8) + (30 * pc_checkskill(sd,RA_TOOTHOFWUG)); @@ -3836,6 +3847,9 @@ static int battle_calc_skill_constant_addition(struct Damage wd, struct block_li if(sd) atk = (30 * pc_checkskill(sd, RA_TOOTHOFWUG)); break; + case GC_COUNTERSLASH: + atk = sstatus->agi * 2 + (sd ? sd->status.job_level * 4 : 0); + break; case LG_SHIELDPRESS: if (sd) { int damagevalue = 0; @@ -3904,8 +3918,11 @@ struct Damage battle_attack_sc_bonus(struct Damage wd, struct block_list *src, s } //The following are applied on top of current damage and are stackable. - if ( sc ) { + if (sc) { #ifdef RENEWAL + if(sc->data[SC_WATK_ELEMENT]) + if(skill_id != ASC_METEORASSAULT) + ATK_ADDRATE(wd.weaponAtk, wd.weaponAtk2, sc->data[SC_WATK_ELEMENT]->val2); if(sc->data[SC_IMPOSITIO]) ATK_ADD(wd.equipAtk, wd.equipAtk2, sc->data[SC_IMPOSITIO]->val2); if(sc->data[SC_VOLCANO]) @@ -4133,50 +4150,64 @@ struct Damage battle_calc_defense_reduction(struct Damage wd, struct block_list short vit_def; defType def1 = status_get_def(target); //Don't use tstatus->def1 due to skill timer reductions. short def2 = tstatus->def2; + #ifdef RENEWAL if( tsc && tsc->data[SC_ASSUMPTIO] ) def1 <<= 1; // only eDEF is doubled #endif - if( sd ) { - int i = sd->ignore_def_by_race[tstatus->race] + sd->ignore_def_by_race[RC_ALL]; + + if (sd) { int type; - if( i ) { - if( i > 100 ) i = 100; + int i = sd->ignore_def_by_race[tstatus->race] + sd->ignore_def_by_race[RC_ALL]; + + if (i) { + i = min(i,100); //cap it to 100 for 0 def min def1 -= def1 * i / 100; def2 -= def2 * i / 100; } //Kagerou/Oboro Earth Charm effect +5% eDEF ARR_FIND(1, 6, type, sd->talisman[type] > 0); - if( type == 2 ) { + if (type == 2) { short i = 5 * sd->talisman[type]; def1 = (def1 * (100 + i)) / 100; } } - if( sc && sc->data[SC_EXPIATIO] ){ + if (sc && sc->data[SC_EXPIATIO]) { short i = 5 * sc->data[SC_EXPIATIO]->val1; // 5% per level + i = min(i,100); //cap it to 100 for 0 def min def1 = (def1*(100-i))/100; def2 = (def2*(100-i))/100; } - if( tsc && tsc->data[SC_GT_REVITALIZE] && tsc->data[SC_GT_REVITALIZE]->val2 ) - def2 += tsc->data[SC_GT_REVITALIZE]->val4; + if (tsc) { + if (tsc->data[SC_FORCEOFVANGUARD]) { + short i = 2 * tsc->data[SC_FORCEOFVANGUARD]->val1; - if (tsc->data[SC_OVERED_BOOST] && target->type == BL_PC) - def1 = (def1 * tsc->data[SC_OVERED_BOOST]->val4) / 100; + def1 = (def1 * (100 + i)) / 100; + } - if( tsc && tsc->data[SC_CAMOUFLAGE] ){ - short i = 5 * tsc->data[SC_CAMOUFLAGE]->val3; //5% per second - i = min(i,100); //cap it to 100 for 0 def min - def1 = (def1*(100-i))/100; - def2 = (def2*(100-i))/100; + if( tsc->data[SC_CAMOUFLAGE] ){ + short i = 5 * tsc->data[SC_CAMOUFLAGE]->val3; //5% per second + + i = min(i,100); //cap it to 100 for 0 def min + def1 = (def1*(100-i))/100; + def2 = (def2*(100-i))/100; + } + + if (tsc->data[SC_GT_REVITALIZE] && tsc->data[SC_GT_REVITALIZE]->val2) + def2 += tsc->data[SC_GT_REVITALIZE]->val4; + + if (tsc->data[SC_OVERED_BOOST] && target->type == BL_PC) + def1 = (def1 * tsc->data[SC_OVERED_BOOST]->val4) / 100; } if( battle_config.vit_penalty_type && battle_config.vit_penalty_target&target->type ) { unsigned char target_count; //256 max targets should be a sane max + target_count = unit_counttargeted(target); if(target_count >= battle_config.vit_penalty_count) { if(battle_config.vit_penalty_type == 1) { @@ -4189,12 +4220,18 @@ struct Damage battle_calc_defense_reduction(struct Damage wd, struct block_list def2 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num; } } - if(skill_id == AM_ACIDTERROR) def1 = 0; //Acid Terror ignores only armor defense. [Skotlex] - if(def2 < 1) def2 = 1; + if (skill_id == AM_ACIDTERROR) +#ifdef RENEWAL + def2 = 0; //Ignore only status defense. [FatalEror] +#else + def1 = 0; //Ignores only armor defense. [Skotlex] +#endif + if(def2 < 1) + def2 = 1; } + //Vitality reduction from rodatazone: http://rodatazone.simgaming.net/mechanics/substats.php#def - if (tsd) //Sd vit-eq - { + if (tsd) { //Sd vit-eq int skill; #ifndef RENEWAL //[VIT*0.5] + rnd([VIT*0.3], max([VIT*0.3],[VIT^2/150]-1)) @@ -4209,12 +4246,14 @@ struct Damage battle_calc_defense_reduction(struct Damage wd, struct block_list if( src->type == BL_MOB && (skill=pc_checkskill(tsd,RA_RANGERMAIN))>0 && (sstatus->race == RC_BRUTE || sstatus->race == RC_FISH || sstatus->race == RC_PLANT) ) vit_def += skill*5; + if( src->type == BL_MOB && (skill = pc_checkskill(tsd, NC_RESEARCHFE)) > 0 && + (sstatus->def_ele == ELE_FIRE || sstatus->def_ele == ELE_EARTH) ) + vit_def += skill * 10; if( src->type == BL_MOB && //Only affected from mob tsc && tsc->count && tsc->data[SC_P_ALTER] && //If the Platinum Alter is activated (battle_check_undead(sstatus->race,sstatus->def_ele) || sstatus->race==RC_UNDEAD) ) //Undead attacker vit_def += tsc->data[SC_P_ALTER]->val3; - } - else { //Mob-Pet vit-eq + } else { //Mob-Pet vit-eq #ifndef RENEWAL //VIT + rnd(0,[VIT/20]^2-1) vit_def = (def2/20)*(def2/20); @@ -4230,13 +4269,13 @@ struct Damage battle_calc_defense_reduction(struct Damage wd, struct block_list vit_def += def1*battle_config.weapon_defense_type; def1 = 0; } + #ifdef RENEWAL /** * RE DEF Reduction * Damage = Attack * (4000+eDEF)/(4000+eDEF*10) - sDEF * Pierce defence gains 1 atk per def/2 **/ - if( def1 == -400 ) /* being hit by a gazillion units, -400 creates a division by 0 and subsequently crashes */ def1 = -399; ATK_ADD2(wd.damage, wd.damage2, @@ -4310,11 +4349,6 @@ struct Damage battle_calc_attack_post_defense(struct Damage wd, struct block_lis if (is_attack_right_handed(src, skill_id) && wd.damage < 1) wd.damage = 1; if (is_attack_left_handed(src, skill_id) && wd.damage2 < 1) wd.damage2 = 1; - if (skill_id == NJ_KUNAI) { - RE_ALLATK_ADD(wd, 60); - ATK_ADD(wd.damage, wd.damage2, 60); - } - switch (skill_id) { case AS_SONICBLOW: @@ -4343,12 +4377,11 @@ struct Damage battle_calc_attack_plant(struct Damage wd, struct block_list *src, { struct status_data *tstatus = status_get_status_data(target); bool attack_hits = is_attack_hitting(wd, src, target, skill_id, skill_lv, false); - int right_element = battle_get_weapon_element(wd, src, target, skill_id, skill_lv, EQI_HAND_R, false); int left_element = battle_get_weapon_element(wd, src, target, skill_id, skill_lv, EQI_HAND_L, false); + short class_ = status_get_class(target); //Plants receive 1 damage when hit - short class_ = status_get_class(target); if( attack_hits || wd.damage > 0 ) wd.damage = wd.div_; // In some cases, right hand no need to have a weapon to increase damage if( is_attack_left_handed(src, skill_id) && (attack_hits || wd.damage2 > 0) ) @@ -4361,16 +4394,16 @@ struct Damage battle_calc_attack_plant(struct Damage wd, struct block_list *src, wd.damage = wd.damage2 = 0; return wd; } - if( wd.damage2 > 0 ) { + if (wd.damage > 0) { + wd.damage = battle_attr_fix(src, target, wd.damage, right_element, tstatus->def_ele, tstatus->ele_lv); + wd.damage = battle_calc_gvg_damage(src, target, wd.damage, wd.div_, skill_id, skill_lv, wd.flag); + } else if (wd.damage2 > 0) { wd.damage2 = battle_attr_fix(src, target, wd.damage2, left_element, tstatus->def_ele, tstatus->ele_lv); wd.damage2 = battle_calc_gvg_damage(src, target, wd.damage2, wd.div_, skill_id, skill_lv, wd.flag); } - else if( wd.damage > 0 ) { - wd.damage = battle_attr_fix(src, target, wd.damage, right_element, tstatus->def_ele, tstatus->ele_lv); - wd.damage = battle_calc_gvg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); - } return wd; } + //if( !(battle_config.skill_min_damage&1) ) //Do not return if you are supposed to deal greater damage to plants than 1. [Skotlex] return wd; @@ -4390,15 +4423,14 @@ struct Damage battle_calc_attack_left_right_hands(struct Damage wd, struct block if (sd) { int skill; + if (!is_attack_right_handed(src, skill_id) && is_attack_left_handed(src, skill_id)) { wd.damage = wd.damage2; wd.damage2 = 0; - } - else if(sd->status.weapon == W_KATAR && !skill_id) { //Katars (offhand damage only applies to normal attacks, tested on Aegis 10.2) + } else if(sd->status.weapon == W_KATAR && !skill_id) { //Katars (offhand damage only applies to normal attacks, tested on Aegis 10.2) skill = pc_checkskill(sd,TF_DOUBLE); wd.damage2 = (int64)wd.damage * (1 + (skill * 2))/100; - } - else if(is_attack_right_handed(src, skill_id) && is_attack_left_handed(src, skill_id)) { //Dual-wield + } else if(is_attack_right_handed(src, skill_id) && is_attack_left_handed(src, skill_id)) { //Dual-wield if (wd.damage) { if( (sd->class_&MAPID_BASEMASK) == MAPID_THIEF ) { skill = pc_checkskill(sd,AS_RIGHT); @@ -4408,7 +4440,8 @@ struct Damage battle_calc_attack_left_right_hands(struct Damage wd, struct block skill = pc_checkskill(sd,KO_RIGHT); ATK_RATER(wd.damage, 70 + (skill * 10)) } - if(wd.damage < 1) wd.damage = 1; + if(wd.damage < 1) + wd.damage = 1; } if (wd.damage2) { if( (sd->class_&MAPID_BASEMASK) == MAPID_THIEF) { @@ -4419,7 +4452,8 @@ struct Damage battle_calc_attack_left_right_hands(struct Damage wd, struct block skill = pc_checkskill(sd,KO_LEFT); ATK_RATEL(wd.damage2, 50 + (skill * 10)) } - if(wd.damage2 < 1) wd.damage2 = 1; + if(wd.damage2 < 1) + wd.damage2 = 1; } } } @@ -4757,8 +4791,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl memset(&wd,0,sizeof(wd)); - if(src==NULL || target==NULL) - { + if (src == NULL || target == NULL) { nullpo_info(NLP_MARK); return wd; } @@ -4776,11 +4809,12 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl sd = BL_CAST(BL_PC, src); tsd = BL_CAST(BL_PC, target); - if ( (!skill_id || skill_id == PA_SACRIFICE) && tstatus->flee2 && rnd()%1000 < tstatus->flee2 ) - { //Check for Lucky Dodge - wd.type=0x0b; - wd.dmg_lv=ATK_LUCKY; - if (wd.div_ < 0) wd.div_*=-1; + //Check for Lucky Dodge + if ((!skill_id || skill_id == PA_SACRIFICE) && tstatus->flee2 && rnd()%1000 < tstatus->flee2) { + wd.type = 0x0b; + wd.dmg_lv = ATK_LUCKY; + if(wd.div_ < 0) + wd.div_ *= -1; return wd; } @@ -4795,7 +4829,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl if(!is_attack_hitting(wd, src, target, skill_id, skill_lv, true)) wd.dmg_lv = ATK_FLEE; else if(!target_has_infinite_defense(target, skill_id)) { //no need for math against plants - int ratio, i; + int ratio, i = 0; wd = battle_calc_skill_base_damage(wd, src, target, skill_id, skill_lv); // base skill damage ratio = battle_calc_attack_skill_ratio(wd, src, target, skill_id, skill_lv); // skill level ratios @@ -4806,10 +4840,12 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl ratio = battle_calc_skill_constant_addition(wd, src, target, skill_id, skill_lv); // other skill bonuses ATK_ADD(wd.damage, wd.damage2, ratio); + RE_ALLATK_ADD(wd, ratio); + #ifdef RENEWAL - ATK_ADD(wd.equipAtk, wd.equipAtk2, ratio); // equip ATK gets modified by skill bonuses as well [helvetica] if(skill_id == HW_MAGICCRASHER) { // Add weapon attack for MATK onto Magic Crasher struct status_data *sstatus = status_get_status_data(src); + if (sstatus->matk_max > sstatus->matk_min) { ATK_ADD(wd.weaponAtk, wd.weaponAtk2, sstatus->matk_min+rnd()%(sstatus->matk_max-sstatus->matk_min)); } else @@ -4827,7 +4863,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl //Card Fix for attacker (sd), 2 is added to the "left" flag meaning "attacker cards only" wd.weaponAtk += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.weaponAtk, 2, wd.flag); wd.equipAtk += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.equipAtk, 2, wd.flag); - if( is_attack_left_handed(src, skill_id )) { + if (is_attack_left_handed(src, skill_id)) { wd.weaponAtk2 += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.weaponAtk2, 3, wd.flag); wd.equipAtk2 += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.equipAtk2, 3, wd.flag); } @@ -4838,22 +4874,23 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl if (sd) { //monsters, homuns and pets have their damage computed directly wd.damage = wd.statusAtk + wd.weaponAtk + wd.equipAtk + wd.masteryAtk; wd.damage2 = wd.statusAtk2 + wd.weaponAtk2 + wd.equipAtk2 + wd.masteryAtk2; - - if( wd.flag&BF_LONG ) // Long damage rate addition doesn't use weapon + equip attack, what about others? - wd.damage = wd.damage * ( 100 + sd->bonus.long_attack_atk_rate ) / 100; + if(wd.flag&BF_LONG) //Long damage rate addition doesn't use weapon + equip attack + ATK_ADDRATE(wd.damage, wd.damage2, sd->bonus.long_attack_atk_rate); + //Custom fix for "a hole" in renewal attack calculation [exneval] + ATK_ADDRATE(wd.damage, wd.damage2, 6); } #else // final attack bonuses that aren't affected by cards wd = battle_attack_sc_bonus(wd, src, target, skill_id); #endif - // check if attack ignores DEF - if (!attack_ignores_def(wd, src, target, skill_id, skill_lv, EQI_HAND_L) || !attack_ignores_def(wd, src, target, skill_id, skill_lv, EQI_HAND_R)) - wd = battle_calc_defense_reduction(wd, src, target, skill_id, skill_lv); + if (wd.damage + wd.damage2) { //Check if attack ignores DEF + if(!attack_ignores_def(wd, src, target, skill_id, skill_lv, EQI_HAND_L) || !attack_ignores_def(wd, src, target, skill_id, skill_lv, EQI_HAND_R)) + wd = battle_calc_defense_reduction(wd, src, target, skill_id, skill_lv); - wd = battle_calc_attack_post_defense(wd, src, target, skill_id, skill_lv); - } - else if(wd.div_ < 0) //Since the attack missed... + wd = battle_calc_attack_post_defense(wd, src, target, skill_id, skill_lv); + } + } else if(wd.div_ < 0) //Since the attack missed. wd.div_ *= -1; //WS_CARTTERMINATION never be missed because of flee, deals damage from BS_WEAPONRESEARCH [Cydh] @@ -4876,16 +4913,44 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl return wd; //Enough, rest is not needed. #ifdef RENEWAL - if(is_attack_critical(wd, src, target, skill_id, skill_lv, false)) { - if(sd) { // check for player so we don't crash out, monsters don't have bonus crit rates [helvetica] - wd.damage = (int)floor((double)(wd.damage * 1.4 * (100 + sd->bonus.crit_atk_rate)) / 100); - } - else - wd.damage = (int)floor((double)wd.damage * 1.4); + if (is_attack_critical(wd, src, target, skill_id, skill_lv, false)) { + if (sd) { //Check for player so we don't crash out, monsters don't have bonus crit rates [helvetica] + wd.damage = (int)floor((float)((wd.damage * 140) / 100 * (100 + sd->bonus.crit_atk_rate)) / 100); + if (is_attack_left_handed(src, skill_id)) + wd.damage2 = (int)floor((float)((wd.damage2 * 140) / 100 * (100 + sd->bonus.crit_atk_rate)) / 100); + } else + wd.damage = (int)floor((float)(wd.damage * 140) / 100); } #endif - switch(skill_id) { +#ifndef RENEWAL + if (skill_id == NJ_KUNAI) { + short nk = battle_skill_get_damage_properties(skill_id, wd.miscflag); + + ATK_ADD(wd.damage, wd.damage2, 90); + nk |= NK_IGNORE_DEF; + } +#endif + + switch (skill_id) { + case TK_DOWNKICK: + case TK_STORMKICK: + case TK_TURNKICK: + case TK_COUNTER: + case TK_JUMPKICK: + if(sd && pc_checkskill(sd,TK_RUN)) { + uint8 i; + uint16 skill = pc_checkskill(sd,TK_RUN); + + switch(skill) { + case 1: case 4: case 7: case 10: i = 1; break; + case 2: case 5: case 8: i = 2; break; + default: i = 0; break; + } + if(sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST) + ATK_ADD(wd.damage, wd.damage2, 10 * skill - i); + } + break; case SR_GATEOFHELL: { struct status_data *sstatus = status_get_status_data(src); @@ -4900,8 +4965,10 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl if(sd) { #ifndef RENEWAL - if (pc_checkskill(sd, BS_WEAPONRESEARCH) > 0) - ATK_ADD(wd.damage, wd.damage2, skill_lv * 2); + uint16 skill; + + if ((skill = pc_checkskill(sd, BS_WEAPONRESEARCH)) > 0) + ATK_ADD(wd.damage, wd.damage2, skill * 2); if (skill_id == TF_POISON) ATK_ADD(wd.damage, wd.damage2, 15 * skill_lv); if (skill_id != CR_SHIELDBOOMERANG) //Only Shield boomerang doesn't takes the Star Crumbs bonus. @@ -4913,14 +4980,12 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl } else ATK_ADD(wd.damage, wd.damage2, wd.div_ * sd->spiritball * 3); #endif + if( skill_id == CR_SHIELDBOOMERANG || skill_id == PA_SHIELDCHAIN ) { //Refine bonus applies after cards and elements. + short index = sd->equip_index[EQI_HAND_L]; - if( skill_id == CR_SHIELDBOOMERANG || skill_id == PA_SHIELDCHAIN ) - { //Refine bonus applies after cards and elements. - short index= sd->equip_index[EQI_HAND_L]; if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR ) ATK_ADD(wd.damage, wd.damage2, 10*sd->status.inventory[index].refine); } - #ifndef RENEWAL //Card Fix for attacker (sd), 2 is added to the "left" flag meaning "attacker cards only" wd.damage += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.damage, 2, wd.flag); @@ -4930,15 +4995,15 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl } if(tsd) { // Card Fix for target (tsd), 2 is not added to the "left" flag meaning "target cards only" - switch(skill_id) { // These skills will do a card fix later + switch(skill_id) { #ifdef RENEWAL case NJ_ISSEN: case ASC_BREAKER: case CR_ACIDDEMONSTRATION: case GN_FIRE_EXPANSION_ACID: #endif - case KO_HAPPOKUNAI: - break; + case SO_VARETYR_SPEAR: + break; //These skills will do a card fix later default: wd.damage += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.damage, 0, wd.flag); if(is_attack_left_handed(src, skill_id)) @@ -4955,8 +5020,8 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl case MC_CARTREVOLUTION: case MO_INVESTIGATE: case CR_ACIDDEMONSTRATION: - case GN_FIRE_EXPANSION_ACID: case SR_GATEOFHELL: + case GN_FIRE_EXPANSION_ACID: case KO_BAKURETSU: // Forced to neutral element wd.damage = battle_attr_fix(src, target, wd.damage, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv); @@ -5008,15 +5073,15 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl wd = battle_calc_attack_left_right_hands(wd, src, target, skill_id, skill_lv); - switch (skill_id) { // These skills will do a GVG fix later + switch (skill_id) { #ifdef RENEWAL case NJ_ISSEN: case ASC_BREAKER: case CR_ACIDDEMONSTRATION: case GN_FIRE_EXPANSION_ACID: #endif - case KO_HAPPOKUNAI: - return wd; + case SO_VARETYR_SPEAR: + return wd; //These skills will do a GVG fix later default: wd = battle_calc_attack_gvg_bg(wd, src, target, skill_id, skill_lv); break; @@ -5205,16 +5270,22 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list case AB_RENOVATIO: ad.damage = status_get_lv(src) * 10 + sstatus->int_; break; -#ifndef RENEWAL case GN_FIRE_EXPANSION_ACID: +#ifdef RENEWAL + { + struct Damage wd = battle_calc_weapon_attack(src, target, skill_id, skill_lv, 0); + + ad.damage = (int64)(7 * ((wd.damage / skill_lv + ad.damage / skill_lv) * tstatus->vit / 100)); + } +#else if(tstatus->vit + sstatus->int_) ad.damage = (int64)(7 * tstatus->vit * sstatus->int_ * sstatus->int_ / (10 * (tstatus->vit + sstatus->int_))); else ad.damage = 0; if(tsd) ad.damage >>= 1; - break; #endif + break; default: { if (sstatus->matk_max > sstatus->matk_min) { MATK_ADD(sstatus->matk_min+rnd()%(sstatus->matk_max-sstatus->matk_min)); @@ -5731,17 +5802,28 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list if (!(nk&NK_NO_ELEFIX)) ad.damage=battle_attr_fix(src, target, ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv); - if( skill_id == CR_GRANDCROSS || skill_id == NPC_GRANDDARKNESS ) - { //Apply the physical part of the skill's damage. [Skotlex] - struct Damage wd = battle_calc_weapon_attack(src,target,skill_id,skill_lv,mflag); - ad.damage = battle_attr_fix(src, target, wd.damage + ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv) * (100 + 40*skill_lv)/100; - if( src == target ) - { - if( src->type == BL_PC ) - ad.damage = ad.damage/2; - else - ad.damage = 0; - } + //Apply the physical part of the skill's damage. [Skotlex] + switch(skill_id) { + case CR_GRANDCROSS: + case NPC_GRANDDARKNESS: + { + struct Damage wd = battle_calc_weapon_attack(src,target,skill_id,skill_lv,mflag); + + ad.damage = battle_attr_fix(src, target, wd.damage + ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv) * (100 + 40 * skill_lv) / 100; + if(src == target) { + if(src->type == BL_PC) + ad.damage = ad.damage / 2; + else + ad.damage = 0; + } + } + break; + case SO_VARETYR_SPEAR: { + struct Damage wd = battle_calc_weapon_attack(src, target, skill_id, skill_lv, mflag); + + ad.damage += wd.damage; + } + break; } #ifndef RENEWAL @@ -5766,25 +5848,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list ad.damage=battle_calc_gvg_damage(src,target,ad.damage,ad.div_,skill_id,skill_lv,ad.flag); else if( map[target->m].flag.battleground ) ad.damage=battle_calc_bg_damage(src,target,ad.damage,ad.div_,skill_id,skill_lv,ad.flag); - } - - switch( skill_id ) { /* post-calc modifiers */ - case SO_VARETYR_SPEAR: { // Physical damage. - struct Damage wd = battle_calc_weapon_attack(src,target,skill_id,skill_lv,mflag); - if(!flag.infdef && ad.damage > 1) - ad.damage += wd.damage; - } - break; -#ifdef RENEWAL - case GN_FIRE_EXPANSION_ACID: { - struct Damage wd = battle_calc_weapon_attack(src, target, skill_id, skill_lv, 0); - - ad.damage = (int64)(7 * ((wd.damage / skill_lv + ad.damage / skill_lv) * tstatus->vit / 100)); - damage_div_fix(ad.damage, ad.div_); - } - break; -#endif - //case HM_ERASER_CUTTER: + break; } /* Skill damage adjustment */ @@ -5942,11 +6006,6 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * if (tsd) md.damage>>=1; #endif break; -#ifndef RENEWAL - case NJ_KUNAI: - md.damage = 90; // 3x90 unreducable, unavoidable, and neutral damage. - break; -#endif case NJ_ZENYNAGE: case KO_MUCHANAGE: md.damage = skill_get_zeny(skill_id, skill_lv); @@ -7819,14 +7878,14 @@ void rAthena_report(char* date, char *time_c) { WBUFL(buf,6 + 12 + 9 + 24 + 4 + 4 + 4 + 4 + BFLAG_LENGTH + ( i * ( BFLAG_LENGTH + 4 ) ) ) = *battle_data[i].val; } - chrif_send_report(buf, 6 + 12 + 9 + 24 + 4 + 4 + 4 + 4 + ( bd_size * ( BFLAG_LENGTH + 4 ) ) ); + chrif_send_report(buf, 6 + 12 + 9 + 24 + 4 + 4 + 4 + 4 + ( bd_size * ( BFLAG_LENGTH + 4 ) ) ); aFree(buf); #undef BFLAG_LENGTH } static int rAthena_report_timer(int tid, unsigned int tick, int id, intptr_t data) { - if( chrif_isconnected() ) {/* char server relays it, so it must be online. */ + if( chrif_isconnected() ) { /* char server relays it, so it must be online. */ rAthena_report(__DATE__,__TIME__); } return 0; @@ -7845,8 +7904,7 @@ int battle_set_value(const char* w1, const char* w2) if (i == ARRAYLENGTH(battle_data)) return 0; // not found - if (val < battle_data[i].min || val > battle_data[i].max) - { + if (val < battle_data[i].min || val > battle_data[i].max) { ShowWarning("Value for setting '%s': %s is invalid (min:%i max:%i)! Defaulting to %i...\n", w1, w2, battle_data[i].min, battle_data[i].max, battle_data[i].defval); val = battle_data[i].defval; } @@ -7854,6 +7912,7 @@ int battle_set_value(const char* w1, const char* w2) *battle_data[i].val = val; return 1; } + /*=========================== * Get battle settings *---------------------------*/ @@ -7882,19 +7941,19 @@ void battle_set_defaults() *----------------------------------*/ void battle_adjust_conf() { - battle_config.monster_max_aspd = 2000 - battle_config.monster_max_aspd*10; - battle_config.max_aspd = 2000 - battle_config.max_aspd*10; - battle_config.max_third_aspd = 2000 - battle_config.max_third_aspd*10; - battle_config.max_walk_speed = 100*DEFAULT_WALK_SPEED/battle_config.max_walk_speed; + battle_config.monster_max_aspd = 2000 - battle_config.monster_max_aspd * 10; + battle_config.max_aspd = 2000 - battle_config.max_aspd * 10; + battle_config.max_third_aspd = 2000 - battle_config.max_third_aspd * 10; + battle_config.max_walk_speed = 100 * DEFAULT_WALK_SPEED / battle_config.max_walk_speed; battle_config.max_cart_weight *= 10; - if(battle_config.max_def > 100 && !battle_config.weapon_defense_type) // added by [Skotlex] + if (battle_config.max_def > 100 && !battle_config.weapon_defense_type) // added by [Skotlex] battle_config.max_def = 100; - if(battle_config.min_hitrate > battle_config.max_hitrate) + if (battle_config.min_hitrate > battle_config.max_hitrate) battle_config.min_hitrate = battle_config.max_hitrate; - if(battle_config.pet_max_atk1 > battle_config.pet_max_atk2) //Skotlex + if (battle_config.pet_max_atk1 > battle_config.pet_max_atk2) //Skotlex battle_config.pet_max_atk1 = battle_config.pet_max_atk2; if (battle_config.day_duration && battle_config.day_duration < 60000) // added by [Yor] @@ -7903,21 +7962,29 @@ void battle_adjust_conf() battle_config.night_duration = 60000; #if PACKETVER < 20100427 - if( battle_config.feature_buying_store ) { - ShowWarning("conf/battle/feature.conf buying_store is enabled but it requires PACKETVER 2010-04-27 or newer, disabling...\n"); + if (battle_config.feature_buying_store) { + ShowWarning("conf/battle/feature.conf:buying_store is enabled but it requires PACKETVER 2010-04-27 or newer, disabling...\n"); battle_config.feature_buying_store = 0; } #endif #if PACKETVER < 20100803 - if( battle_config.feature_search_stores ) { - ShowWarning("conf/battle/feature.conf search_stores is enabled but it requires PACKETVER 2010-08-03 or newer, disabling...\n"); + if (battle_config.feature_search_stores) { + ShowWarning("conf/battle/feature.conf:search_stores is enabled but it requires PACKETVER 2010-08-03 or newer, disabling...\n"); battle_config.feature_search_stores = 0; } #endif +#if PACKETVER > 20120000 && PACKETVER < 20130515 /* Exact date (when it started) not known */ + if (battle_config.feature_auction) { + ShowWarning("conf/battle/feature.conf:feature.auction is enabled but it is not stable on PACKETVER "EXPAND_AND_QUOTE(PACKETVER)", disabling...\n"); + ShowWarning("conf/battle/feature.conf:feature.auction change value to '2' to silence this warning and maintain it enabled\n"); + battle_config.feature_auction = 0; + } +#endif + #if PACKETVER < 20130724 - if( battle_config.feature_banking ) { + if (battle_config.feature_banking) { ShowWarning("conf/battle/feature.conf banking is enabled but it requires PACKETVER 2013-07-24 or newer, disabling...\n"); battle_config.feature_banking = 0; } @@ -7945,19 +8012,18 @@ int battle_config_read(const char* cfgName) fp = fopen(cfgName,"r"); if (fp == NULL) ShowError("File not found: %s\n", cfgName); - else - { + else { char line[1024], w1[1024], w2[1024]; - while(fgets(line, sizeof(line), fp)) - { + + while(fgets(line, sizeof(line), fp)) { if (line[0] == '/' && line[1] == '/') continue; if (sscanf(line, "%1023[^:]:%1023s", w1, w2) != 2) continue; if (strcmpi(w1, "import") == 0) battle_config_read(w2); - else - if (battle_set_value(w1, w2) == 0) + else if + (battle_set_value(w1, w2) == 0) ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); } @@ -7982,7 +8048,7 @@ void do_init_battle(void) #ifndef STATS_OPT_OUT add_timer_func_list(rAthena_report_timer, "rAthena_report_timer"); - add_timer_interval(gettick()+30000, rAthena_report_timer, 0, 0, 60000 * 30); + add_timer_interval(gettick() + 30000, rAthena_report_timer, 0, 0, 60000 * 30); #endif } diff --git a/src/map/skill.c b/src/map/skill.c index e6e023614f..1f931908de 100755 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -4192,6 +4192,19 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint short x, y, i = 2; // Move 2 cells (From target) short dir = map_calc_dir(src,bl->x,bl->y); + skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + if (skill_id == MO_EXTREMITYFIST) { + status_set_sp(src, 0, 0); + status_change_end(src, SC_EXPLOSIONSPIRITS, INVALID_TIMER); + status_change_end(src, SC_BLADESTOP, INVALID_TIMER); +#ifdef RENEWAL + sc_start(src,src,SC_EXTREMITYFIST2,100,skill_lv,skill_get_time(skill_id,skill_lv)); +#endif + } else { + status_set_hp(src, 1, 0); + status_change_end(src, SC_NEN, INVALID_TIMER); + status_change_end(src, SC_HIDING, INVALID_TIMER); + } if (skill_id == MO_EXTREMITYFIST) { mbl = src; // For MO_EXTREMITYFIST i = 3; // Move 3 cells (From caster) @@ -4211,23 +4224,10 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint // Ashura Strike still has slide effect in GVG if ((mbl == src || (!map_flag_gvg2(src->m) && !map[src->m].flag.battleground)) && unit_movepos(src, mbl->x + x, mbl->y + y, 1, 1)) { - clif_slide(src, mbl->x + x, mbl->y + y); + clif_slide(src, src->x, src->y); clif_fixpos(src); clif_spiritball(src); } - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - if (skill_id == MO_EXTREMITYFIST) { - status_set_sp(src, 0, 0); - status_change_end(src, SC_EXPLOSIONSPIRITS, INVALID_TIMER); - status_change_end(src, SC_BLADESTOP, INVALID_TIMER); -#ifdef RENEWAL - sc_start(src,src,SC_EXTREMITYFIST2,100,skill_lv,skill_get_time(skill_id,skill_lv)); -#endif - } else { - status_set_hp(src, 1, 0); - status_change_end(src, SC_NEN, INVALID_TIMER); - status_change_end(src, SC_HIDING, INVALID_TIMER); - } } break; @@ -5953,8 +5953,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui { if( unit_movepos(src, bl->x, bl->y, 1, 1) ) { - clif_slide(src,bl->x,bl->y); skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + clif_slide(src, bl->x, bl->y); } } else @@ -10475,8 +10475,8 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) y = 3; else y = 0; - if( unit_movepos(src,src->x + x,src->y + y,1,1) ) { //Display movement + animation. - clif_slide(src,src->x + x,src->y + y); + if( unit_movepos(src, src->x + x, src->y + y, 1, 1) ) { //Display movement + animation. + clif_slide(src, src->x, src->y); clif_fixpos(src); clif_spiritball(src); } @@ -12263,8 +12263,10 @@ static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, un if( td ) sec = DIFF_TICK(td->tick, tick); if( knockback_immune ) { - if( battle_config.skill_trap_type && !map_flag_gvg2(bl->m) ) { - map_moveblock(bl, src->bl.x, src->bl.y, tick); + if( !battle_config.skill_trap_type && map_flag_gvg2(bl->m) ) + ; + else { + map_moveblock(bl,src->bl.x,src->bl.y,tick); clif_fixpos(bl); } } @@ -12452,19 +12454,19 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns struct skill_unit_group_tickset *ts; enum sc_type type; uint16 skill_id; - int diff=0; + int diff = 0; nullpo_ret(src); nullpo_ret(bl); - if (bl->prev==NULL || !src->alive || status_isdead(bl)) + if (bl->prev == NULL || !src->alive || status_isdead(bl)) return 0; - nullpo_ret(sg=src->group); - nullpo_ret(ss=map_id2bl(sg->src_id)); + nullpo_ret(sg = src->group); + nullpo_ret(ss = map_id2bl(sg->src_id)); + tsd = BL_CAST(BL_PC, bl); tsc = status_get_sc(bl); - tstatus = status_get_status_data(bl); type = status_skill2sc(sg->skill_id); skill_id = sg->skill_id; @@ -12499,7 +12501,8 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns switch (sg->unit_id) { case UNT_FIREWALL: case UNT_KAEN: { - int count=0; + int count = 0; + const int x = bl->x, y = bl->y; if (skill_id == GN_WALLOFTHORN && battle_check_target(ss, bl, BCT_ENEMY) <= 0) @@ -12511,7 +12514,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns while(--src->val2 && x == bl->x && y == bl->y && ++count < SKILLUNITTIMER_INTERVAL/sg->interval && !status_isdead(bl)); - if (src->val2<=0) + if (src->val2 <= 0) skill_delunit(src); } break; @@ -12553,6 +12556,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns skill_attack(BF_MISC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); } else { int heal = skill_calc_heal(ss,bl,sg->skill_id,sg->skill_lv,true); + if (tstatus->hp >= tstatus->max_hp) break; if (status_isimmune(bl)) @@ -12601,14 +12605,14 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns /** * The storm gust counter was dropped in renewal **/ - #ifndef RENEWAL +#ifndef RENEWAL case WZ_STORMGUST: //SG counter does not reset per stormgust. IE: One hit from a SG and two hits from another will freeze you. if (tsc) tsc->sg_counter++; //SG hit counter. if (skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0) <= 0 && tsc) tsc->sg_counter=0; //Attack absorbed. break; - #endif +#endif case GS_DESPERADO: if (rnd()%100 < src->val1) skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); @@ -12629,8 +12633,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns skill_delunit(src); break; - case UNT_SKIDTRAP: - { + case UNT_SKIDTRAP: { skill_blown(&src->bl,bl,skill_get_blewcount(sg->skill_id,sg->skill_lv),unit_getdir(bl),0); sg->unit_id = UNT_USED_TRAPS; clif_changetraplook(&src->bl, UNT_USED_TRAPS); @@ -12646,7 +12649,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns int sec = skill_get_time2(sg->skill_id,sg->skill_lv); if( status_change_start(ss, bl,type,10000,sg->skill_lv,sg->group_id,0,0,sec, 8) ) { - const struct TimerData* td = tsc->data[type]?get_timer(tsc->data[type]->timer):NULL; + const struct TimerData* td = (tsc->data[type] ? get_timer(tsc->data[type]->timer) : NULL); int range = skill_get_unit_range(skill_id, sg->skill_lv); int knockback_immune = (tsd ? !tsd->special_state.no_knockback : !(tstatus->mode&(MD_KNOCKBACK_IMMUNE|MD_BOSS))); @@ -12654,15 +12657,17 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns sec = DIFF_TICK(td->tick, tick); if ((sg->unit_id == UNT_MANHOLE && distance_xy(src->bl.x,src->bl.y,bl->x,bl->y) <= range && src->bl.x != bl->x && src->bl.y != bl->y) || knockback_immune) { - if( sg->unit_id == UNT_MANHOLE || battle_config.skill_trap_type || !map_flag_gvg(src->bl.m) ) { - unit_movepos(bl, src->bl.x, src->bl.y, 0, 0); + if (sg->unit_id != UNT_MANHOLE && !battle_config.skill_trap_type && map_flag_gvg2(bl->m)) + ; + else { + unit_movepos(bl,src->bl.x,src->bl.y,0,0); clif_fixpos(bl); } } sg->val2 = bl->id; } else sec = 3000; //Couldn't trap it? - if( sg->unit_id == UNT_ANKLESNARE ) { + if (sg->unit_id == UNT_ANKLESNARE) { clif_skillunit_update(&src->bl); /** * If you're snared from a trap that was invisible this makes the trap be @@ -12695,7 +12700,6 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns status_change_start(ss, bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); break; - case UNT_MAGENTATRAP: case UNT_COBALTTRAP: case UNT_MAIZETRAP: @@ -12708,30 +12712,30 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns if( bl->id == ss->id )// it won't trigger on caster break; case UNT_LANDMINE: - case UNT_CLAYMORETRAP: case UNT_BLASTMINE: case UNT_SHOCKWAVE: case UNT_SANDMAN: case UNT_FLASHER: case UNT_FREEZINGTRAP: case UNT_FIREPILLAR_ACTIVE: + case UNT_CLAYMORETRAP: if (tsc && tsc->data[SC__MANHOLE]) break; - if( sg->unit_id == UNT_FIRINGTRAP || sg->unit_id == UNT_ICEBOUNDTRAP || sg->unit_id == UNT_CLAYMORETRAP ) - map_foreachinrange(skill_trap_splash,&src->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag|BL_SKILL|~BCT_SELF, &src->bl,tick); + if (sg->unit_id == UNT_FIRINGTRAP || sg->unit_id == UNT_ICEBOUNDTRAP || sg->unit_id == UNT_CLAYMORETRAP) + map_foreachinrange(skill_trap_splash, &src->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag|BL_SKILL|~BCT_SELF, &src->bl, tick); else - map_foreachinrange(skill_trap_splash,&src->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick); + map_foreachinrange(skill_trap_splash, &src->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl, tick); if (sg->unit_id != UNT_FIREPILLAR_ACTIVE) - clif_changetraplook(&src->bl, sg->unit_id==UNT_LANDMINE?UNT_FIREPILLAR_ACTIVE:UNT_USED_TRAPS); - sg->limit=DIFF_TICK(tick,sg->tick)+1500 + - (sg->unit_id== UNT_CLUSTERBOMB || sg->unit_id== UNT_ICEBOUNDTRAP?1000:0);// Cluster Bomb/Icebound has 1s to disappear once activated. + clif_changetraplook(&src->bl,(sg->unit_id == UNT_LANDMINE ? UNT_FIREPILLAR_ACTIVE : UNT_USED_TRAPS)); sg->unit_id = UNT_USED_TRAPS; //Changed ID so it does not invoke a for each in area again. + sg->limit = DIFF_TICK(tick, sg->tick) + 1500 + + (sg->unit_id == UNT_CLUSTERBOMB || sg->unit_id == UNT_ICEBOUNDTRAP ? 1000 : 0); // Cluster Bomb/Icebound has 1s to disappear once activated. break; case UNT_TALKIEBOX: if (sg->src_id == bl->id) break; - if (sg->val2 == 0){ + if (sg->val2 == 0) { clif_talkiebox(&src->bl, sg->valstr); sg->unit_id = UNT_USED_TRAPS; clif_changetraplook(&src->bl, UNT_USED_TRAPS); @@ -12755,23 +12759,23 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns skill_attack(BF_MISC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); break; - case UNT_APPLEIDUN: //Apple of Idun [Skotlex] - { - int heal; + case UNT_APPLEIDUN: { //Apple of Idun [Skotlex] + int heal; #ifdef RENEWAL - struct mob_data *md = BL_CAST(BL_MOB, bl); - if( md && md->mob_id == MOBID_EMPERIUM ) - break; + struct mob_data *md = BL_CAST(BL_MOB, bl); + + if (md && md->mob_id == MOBID_EMPERIUM) + break; #endif - if( sg->src_id == bl->id && !(tsc && tsc->data[SC_SPIRIT] && tsc->data[SC_SPIRIT]->val2 == SL_BARDDANCER) ) - break; // affects self only when soullinked - heal = skill_calc_heal(ss,bl,sg->skill_id, sg->skill_lv, true); - if( tsc->data[SC_AKAITSUKI] && heal ) - heal = ~heal + 1; - clif_skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); - status_heal(bl, heal, 0, 0); + if (sg->src_id == bl->id && !(tsc && tsc->data[SC_SPIRIT] && tsc->data[SC_SPIRIT]->val2 == SL_BARDDANCER)) + break; // affects self only when soullinked + heal = skill_calc_heal(ss,bl,sg->skill_id, sg->skill_lv, true); + if (tsc->data[SC_AKAITSUKI] && heal) + heal = ~heal + 1; + clif_skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); + status_heal(bl, heal, 0, 0); + } break; - } case UNT_TATAMIGAESHI: case UNT_DEMONSTRATION: @@ -13203,8 +13207,7 @@ int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned in type = status_skill2sc(sg->skill_id); sce = (sc && type != -1)?sc->data[type]:NULL; - if( bl->prev==NULL || - (status_isdead(bl) && sg->unit_id != UNT_ANKLESNARE && sg->unit_id != UNT_SPIDERWEB) ) //Need to delete the trap if the source died. + if( bl->prev==NULL || (status_isdead(bl) && sg->unit_id != UNT_ANKLESNARE && sg->unit_id != UNT_SPIDERWEB) ) //Need to delete the trap if the source died. return 0; switch(sg->unit_id){ @@ -16665,6 +16668,7 @@ int skill_delunit (struct skill_unit* unit) { switch (group->skill_id) { case HT_ANKLESNARE: { struct block_list* target = map_id2bl(group->val2); + if( target ) status_change_end(target, SC_ANKLE, INVALID_TIMER); } @@ -16685,6 +16689,7 @@ int skill_delunit (struct skill_unit* unit) { break; case RA_ELECTRICSHOCKER: { struct block_list* target = map_id2bl(group->val2); + if( target ) status_change_end(target, SC_ELECTRICSHOCKER, INVALID_TIMER); } @@ -17059,8 +17064,7 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) case UNT_ANKLESNARE: case UNT_ELECTRICSHOCKER: - if( group->val2 > 0 ) { - // Used Trap don't returns back to item + if( group->val2 > 0 || group->val3 == SC_ESCAPE ) { //Used Trap doesn't return back to item skill_delunit(unit); break; } @@ -17191,7 +17195,7 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) if( group->unit_id == UNT_ANKLESNARE && group->val2 > 0 ) skill_delunit(unit); else { - clif_changetraplook(bl, group->unit_id==UNT_LANDMINE?UNT_FIREPILLAR_ACTIVE:UNT_USED_TRAPS); + clif_changetraplook(bl, group->unit_id == UNT_LANDMINE ? UNT_FIREPILLAR_ACTIVE : UNT_USED_TRAPS); group->limit = DIFF_TICK(tick, group->tick) + 1500; group->unit_id = UNT_USED_TRAPS; } @@ -19203,7 +19207,11 @@ int skill_block_check(struct block_list *bl, sc_type type , uint16 skill_id) { inf3 = skill_get_inf3(skill_id); - switch(type){ + switch (type) { + case SC_ANKLE: + if (skill_id == AL_TELEPORT) + return 1; + break; case SC_STASIS: inf = skill_get_inf2(skill_id); if( inf == INF2_SONG_DANCE || skill_get_inf2(skill_id) == INF2_CHORUS_SKILL || inf == INF2_SPIRIT_SKILL ) @@ -19225,7 +19233,7 @@ int skill_block_check(struct block_list *bl, sc_type type , uint16 skill_id) { */ int skill_disable_check(struct status_change *sc, uint16 skill_id) { - switch( skill_id ){ // HP & SP Consumption Check + switch( skill_id ) { //HP & SP Consumption Check case BS_MAXIMIZE: case NV_TRICKDEAD: case TF_HIDING: diff --git a/src/map/status.c b/src/map/status.c index d3be96fbbc..839d2b922e 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -333,11 +333,7 @@ void initChangeTables(void) set_sc( MO_STEELBODY , SC_STEELBODY , SI_STEELBODY , SCB_DEF|SCB_MDEF|SCB_ASPD|SCB_SPEED ); add_sc( MO_BLADESTOP , SC_BLADESTOP_WAIT ); set_sc( MO_BLADESTOP , SC_BLADESTOP , SI_BLADESTOP , SCB_NONE ); - set_sc( MO_EXPLOSIONSPIRITS , SC_EXPLOSIONSPIRITS , SI_EXPLOSIONSPIRITS , SCB_CRI -#ifndef RENEWAL - |SCB_REGEN -#endif - ); + set_sc( MO_EXPLOSIONSPIRITS , SC_EXPLOSIONSPIRITS , SI_EXPLOSIONSPIRITS , SCB_CRI|SCB_REGEN ); set_sc( MO_EXTREMITYFIST , SC_EXTREMITYFIST , SI_BLANK , SCB_REGEN ); #ifdef RENEWAL set_sc( MO_EXTREMITYFIST , SC_EXTREMITYFIST2 , SI_EXTREMITYFIST , SCB_NONE ); @@ -685,7 +681,7 @@ void initChangeTables(void) set_sc( LG_EXEEDBREAK , SC_EXEEDBREAK , SI_EXEEDBREAK , SCB_NONE ); set_sc( LG_PRESTIGE , SC_PRESTIGE , SI_PRESTIGE , SCB_DEF ); set_sc( LG_BANDING , SC_BANDING , SI_BANDING , -#ifndef RENWAL +#ifndef RENEWAL SCB_DEF ); #else SCB_DEF2 ); @@ -9948,8 +9944,10 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty int knockback_immune = (sd ? !sd->special_state.no_knockback : !(status->mode&(MD_KNOCKBACK_IMMUNE|MD_BOSS))); if (knockback_immune) { - if (battle_config.skill_trap_type && !map_flag_gvg2(bl->m)) - unit_stop_walking(bl, 1); + if (!battle_config.skill_trap_type && map_flag_gvg2(bl->m)) + break; + else + unit_stop_walking(bl,1); } } break; @@ -12389,7 +12387,7 @@ int status_change_spread( struct block_list *src, struct block_list *bl ) /** * Applying natural heal bonuses (sit, skill, homun, etc...) -* TODO: the va_list doesn't see to be used, safe to remove? +* TODO: the va_list doesn't seem to be used, safe to remove? * @param bl: Object applying bonuses to [PC|HOM|MER|ELEM] * @param args: va_list arguments * @return which regeneration bonuses have been applied (flag) @@ -12451,6 +12449,13 @@ static int status_natural_heal(struct block_list* bl, va_list args) } if(flag&(RGN_SSP)) { // Sitting SP regen val = natural_heal_diff_tick * sregen->rate.sp; + +#ifdef RENEWAL + if (bl->type == BL_PC && (((TBL_PC*)bl)->class_&MAPID_UPPERMASK) == MAPID_MONK && + sc->data[SC_EXPLOSIONSPIRITS] && (!sc->data[SC_SPIRIT] || sc->data[SC_SPIRIT]->val2 != SL_MONK)) + val >>= 1; // Half as fast when in Fury State +#endif + if (regen->state.overweight) val>>=1; // Half as fast when overweight. sregen->tick.sp += val; @@ -12513,12 +12518,6 @@ static int status_natural_heal(struct block_list* bl, va_list args) // Homun SP regen fix (they should regen as if they were sitting (twice as fast) if(bl->type==BL_HOM) rate *=2; -#ifdef RENEWAL - if (bl->type == BL_PC && (((TBL_PC*)bl)->class_&MAPID_UPPERMASK) == MAPID_MONK && - sc->data[SC_EXPLOSIONSPIRITS] && (!sc->data[SC_SPIRIT] || sc->data[SC_SPIRIT]->val2 != SL_MONK)) - rate /= 2; // Half as fast when in Fury State -#endif - regen->tick.sp += rate; if(regen->tick.sp >= (unsigned int)battle_config.natural_healsp_interval) {