Index: src/map/ai/ai_char_normal.cpp =================================================================== --- src/map/ai/ai_char_normal.cpp (revision 2112) +++ src/map/ai/ai_char_normal.cpp (working copy) @@ -835,7 +835,7 @@ { float pdif = battleutils::GetRangedPDIF(m_PChar,m_PBattleSubTarget); - if(rand()%100 < battleutils::GetCritHitRate(m_PChar,m_PBattleSubTarget, true)) + if(rand()%100 < battleutils::GetCritHitRate(m_PChar,m_PBattleSubTarget, true, true)) { pdif *= 1.25; //uncapped Action.speceffect = SPECEFFECT_CRITICAL_HIT; @@ -2438,7 +2438,7 @@ { bool ignoreSneakAttack = (i != 0); // Sneak attack critical effect should only be given on the first swing. bool ignoreTrickAttack = (i != 0); - bool isCritical = (rand()%100 < battleutils::GetCritHitRate(m_PChar, m_PBattleTarget, ignoreSneakAttack)); + bool isCritical = (rand()%100 < battleutils::GetCritHitRate(m_PChar, m_PBattleTarget, ignoreSneakAttack, ignoreTrickAttack)); float DamageRatio = battleutils::GetDamageRatio(m_PChar, m_PBattleTarget, isCritical, 0); @@ -2473,17 +2473,16 @@ { taChar = battleutils::getAvailableTrickAttackChar(m_PChar,m_PBattleTarget); if(taChar != NULL) bonusDMG += m_PChar->AGI(); + } //check if other jobs have trick attack active to change enmity lateron if(taChar == NULL && m_PChar->StatusEffectContainer->HasStatusEffect(EFFECT_TRICK_ATTACK) && (!ignoreTrickAttack)) taChar = battleutils::getAvailableTrickAttackChar(m_PChar,m_PBattleTarget); - - + damage = (uint16)(((PWeapon->getDamage() + bonusDMG + battleutils::GetFSTR(m_PChar, m_PBattleTarget,fstrslot)) * DamageRatio)); - // do soul eater effect damage = battleutils::doSoulEaterEffect(m_PChar, damage); Index: src/map/ai/ai_mob_dummy.cpp =================================================================== --- src/map/ai/ai_mob_dummy.cpp (revision 2112) +++ src/map/ai/ai_mob_dummy.cpp (working copy) @@ -1005,7 +1005,7 @@ Action.reaction = REACTION_NONE; Action.speceffect = SPECEFFECT_NONE; - bool isCritical = ( rand()%100 < battleutils::GetCritHitRate(m_PBattleTarget, m_PMob,false) ); + bool isCritical = ( rand()%100 < battleutils::GetCritHitRate(m_PBattleTarget, m_PMob, false, false) ); float DamageRatio = battleutils::GetDamageRatio(m_PBattleTarget, m_PMob,isCritical, 0); damage = (uint16)((m_PBattleTarget->m_Weapons[SLOT_MAIN]->getDamage() + battleutils::GetFSTR(m_PBattleTarget, m_PMob,SLOT_MAIN)) * DamageRatio); @@ -1014,7 +1014,7 @@ Action.flag = 2; } else{ - bool isCritical = ( rand()%100 < battleutils::GetCritHitRate(m_PMob, m_PBattleTarget,false) ); + bool isCritical = ( rand()%100 < battleutils::GetCritHitRate(m_PMob, m_PBattleTarget, false, false) ); if(m_PMob->StatusEffectContainer->HasStatusEffect(EFFECT_MIGHTY_STRIKES,0)){isCritical=true;} float DamageRatio = battleutils::GetDamageRatio(m_PMob, m_PBattleTarget,isCritical, 0); Index: src/map/ai/ai_pet_dummy.cpp =================================================================== --- src/map/ai/ai_pet_dummy.cpp (revision 2112) +++ src/map/ai/ai_pet_dummy.cpp (working copy) @@ -655,7 +655,7 @@ Action.speceffect = SPECEFFECT_HIT; Action.messageID = 1; - bool isCritical = ( rand()%100 < battleutils::GetCritHitRate(m_PPet, m_PBattleTarget, false) ); + bool isCritical = ( rand()%100 < battleutils::GetCritHitRate(m_PPet, m_PBattleTarget, false, false) ); float DamageRatio = battleutils::GetDamageRatio(m_PPet, m_PBattleTarget,isCritical, 0); if(isCritical) Index: src/map/battleutils.cpp =================================================================== --- src/map/battleutils.cpp (revision 2112) +++ src/map/battleutils.cpp (working copy) @@ -1459,19 +1459,26 @@ { int32 hitrate = 75; - if (PAttacker->objtype == TYPE_PC && PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_SNEAK_ATTACK)) - { - hitrate = 100; //attack with SA active cannot miss + //SA only has 100% hitrate when behind mob + if (PAttacker->objtype == TYPE_PC && PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_SNEAK_ATTACK) + && (abs(PDefender->loc.p.rotation - PAttacker->loc.p.rotation) < 23)) return 100; + + if (PAttacker->objtype == TYPE_PC && PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_TRICK_ATTACK) + && PAttacker->GetMJob() == JOB_THF && PAttacker->GetMLevel() >= 60) { + CBattleEntity* taChar = NULL; + + taChar = getAvailableTrickAttackChar(PAttacker, PDefender); + if (taChar != NULL) return 100; + } - else - { - int32 defendereva = (PDefender->getMod(MOD_EVA) * (100 + PDefender->getMod(MOD_EVAP)))/100 + PDefender->AGI()/2; - int32 attackeracc = (PAttacker->getMod(MOD_ACC) * (100 + PAttacker->getMod(MOD_ACCP)))/100 + PAttacker->DEX()/2; + + int32 defendereva = (PDefender->getMod(MOD_EVA) * (100 + PDefender->getMod(MOD_EVAP)))/100 + PDefender->AGI()/2; + int32 attackeracc = (PAttacker->getMod(MOD_ACC) * (100 + PAttacker->getMod(MOD_ACCP)))/100 + PAttacker->DEX()/2; - hitrate = hitrate + (attackeracc - defendereva) / 2 + (PAttacker->GetMLevel() - PDefender->GetMLevel())*2; + hitrate = hitrate + (attackeracc - defendereva) / 2 + (PAttacker->GetMLevel() - PDefender->GetMLevel())*2; - hitrate = dsp_cap(hitrate, 20, 95); - } + hitrate = dsp_cap(hitrate, 20, 95); + return (uint8)hitrate; } @@ -1485,19 +1492,25 @@ { int32 hitrate = 75; - if (PAttacker->objtype == TYPE_PC && PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_SNEAK_ATTACK)) - { - hitrate = 100; //attack with SA active cannot miss + //SA only has 100% hitrate when behind mob + if (PAttacker->objtype == TYPE_PC && PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_SNEAK_ATTACK) + && (abs(PDefender->loc.p.rotation - PAttacker->loc.p.rotation) < 23)) return 100; + + if (PAttacker->objtype == TYPE_PC && PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_TRICK_ATTACK) + && PAttacker->GetMJob() == JOB_THF && PAttacker->GetMLevel() >= 60) { + CBattleEntity* taChar = NULL; + + taChar = getAvailableTrickAttackChar(PAttacker, PDefender); + if (taChar != NULL) return 100; } - else - { - int32 defendereva = (PDefender->getMod(MOD_EVA) * (100 + PDefender->getMod(MOD_EVAP)))/100 + PDefender->AGI()/2; - int32 attackeracc = ((PAttacker->getMod(MOD_ACC) + accuracy) * (100 + PAttacker->getMod(MOD_ACCP)))/100 + PAttacker->DEX()/2; + + int32 defendereva = (PDefender->getMod(MOD_EVA) * (100 + PDefender->getMod(MOD_EVAP)))/100 + PDefender->AGI()/2; + int32 attackeracc = ((PAttacker->getMod(MOD_ACC) + accuracy) * (100 + PAttacker->getMod(MOD_ACCP)))/100 + PAttacker->DEX()/2; - hitrate = hitrate + (attackeracc - defendereva) / 2 + (PAttacker->GetMLevel() - PDefender->GetMLevel())*2; + hitrate = hitrate + (attackeracc - defendereva) / 2 + (PAttacker->GetMLevel() - PDefender->GetMLevel())*2; - hitrate = dsp_cap(hitrate, 20, 95); - } + hitrate = dsp_cap(hitrate, 20, 95); + return (uint8)hitrate; } @@ -1507,36 +1520,36 @@ * * ************************************************************************/ -uint8 GetCritHitRate(CBattleEntity* PAttacker, CBattleEntity* PDefender, bool ignoreSneakAttack) +uint8 GetCritHitRate(CBattleEntity* PAttacker, CBattleEntity* PDefender, bool ignoreSneakAttack, bool ignoreTrickAttack) { int32 crithitrate = 5; if(PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_MIGHTY_STRIKES,0) || - PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_MIGHTY_STRIKES)){ - return 100; - } - else if (PAttacker->objtype == TYPE_PC && (!ignoreSneakAttack) && PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_SNEAK_ATTACK)) - { - // TODO: WRONG CALCULATION OF A POSITION OF THE CHARACTER + PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_MIGHTY_STRIKES)) return 100; + + // TODO: WRONG CALCULATION OF A POSITION OF THE CHARACTER + if (PAttacker->objtype == TYPE_PC && (!ignoreSneakAttack) && PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_SNEAK_ATTACK) + && (abs(PDefender->loc.p.rotation - PAttacker->loc.p.rotation) < 23)) return 100; + + if (PAttacker->objtype == TYPE_PC && PAttacker->StatusEffectContainer->HasStatusEffect(EFFECT_TRICK_ATTACK) + && PAttacker->GetMJob() == JOB_THF && PAttacker->GetMLevel() >= 60) { + CBattleEntity* taChar = NULL; - if(abs(PDefender->loc.p.rotation - PAttacker->loc.p.rotation) < 23) - { - crithitrate = 100; - } + taChar = getAvailableTrickAttackChar(PAttacker, PDefender); + if (taChar != NULL) return 100; } - else - { - //apply merit mods - if (PAttacker->objtype == TYPE_PC) crithitrate += ((CCharEntity*)PAttacker)->PMeritPoints->GetMeritValue(MERIT_CRIT_HIT_RATE,PAttacker->GetMLevel()); - if (PDefender->objtype == TYPE_PC) crithitrate -= ((CCharEntity*)PDefender)->PMeritPoints->GetMeritValue(MERIT_ENEMY_CRIT_RATE,PDefender->GetMLevel()); + + //apply merit mods + if (PAttacker->objtype == TYPE_PC) crithitrate += ((CCharEntity*)PAttacker)->PMeritPoints->GetMeritValue(MERIT_CRIT_HIT_RATE,PAttacker->GetMLevel()); + if (PDefender->objtype == TYPE_PC) crithitrate -= ((CCharEntity*)PDefender)->PMeritPoints->GetMeritValue(MERIT_ENEMY_CRIT_RATE,PDefender->GetMLevel()); - int32 attackerdex = PAttacker->DEX(); - int32 defenderagi = PDefender->AGI(); + int32 attackerdex = PAttacker->DEX(); + int32 defenderagi = PDefender->AGI(); - int32 dDEX = dsp_cap(attackerdex - defenderagi,0,50); + int32 dDEX = dsp_cap(attackerdex - defenderagi,0,50); - crithitrate += (dDEX * 30) / 100 + PAttacker->getMod(MOD_CRITHITRATE) + PDefender->getMod(MOD_ENEMYCRITRATE); - crithitrate = dsp_cap(crithitrate,0,100); - } + crithitrate += (dDEX * 30) / 100 + PAttacker->getMod(MOD_CRITHITRATE) + PDefender->getMod(MOD_ENEMYCRITRATE); + crithitrate = dsp_cap(crithitrate,0,100); + return (uint8)crithitrate; } @@ -2507,8 +2520,7 @@ { for(uint8 i = 0; i < taUser->PParty->m_PAlliance->partyList.at(a)->members.size(); ++i) { - if (abs(taUser->PParty->m_PAlliance->partyList.at(a)->members.at(i)->loc.p.rotation - taUser->loc.p.rotation) < 23 && - abs(PMob->loc.p.rotation - taUser->PParty->m_PAlliance->partyList.at(a)->members.at(i)->loc.p.rotation) < 23) + if (abs(taUser->PParty->m_PAlliance->partyList.at(a)->members.at(i)->loc.p.rotation - taUser->loc.p.rotation) < 23) { float distancePartyChar = distance(taUser->PParty->m_PAlliance->partyList.at(a)->members.at(i)->loc.p,PMob->loc.p); @@ -2525,8 +2537,7 @@ }else{//no alliance for(uint8 i = 0; i < taUser->PParty->members.size(); ++i) { - if(abs(taUser->PParty->members.at(i)->loc.p.rotation - taUser->loc.p.rotation) < 23 && - abs(PMob->loc.p.rotation - taUser->PParty->members.at(i)->loc.p.rotation) < 23) + if(abs(taUser->PParty->members.at(i)->loc.p.rotation - taUser->loc.p.rotation) < 23) { float distancePartyChar = distance(taUser->PParty->members.at(i)->loc.p,PMob->loc.p); Index: src/map/battleutils.h =================================================================== --- src/map/battleutils.h (revision 2112) +++ src/map/battleutils.h (working copy) @@ -96,7 +96,7 @@ int32 GetFSTR(CBattleEntity* PAttacker, CBattleEntity* PDefender, uint8 SlotID); uint8 GetHitRate(CBattleEntity* PAttacker, CBattleEntity* PDefender); uint8 GetHitRateAccOffset(CBattleEntity* PAttacker, CBattleEntity* PDefender, uint32 accuracy); - uint8 GetCritHitRate(CBattleEntity* PAttacker, CBattleEntity* PDefender, bool ignoreSneakAttack); + uint8 GetCritHitRate(CBattleEntity* PAttacker, CBattleEntity* PDefender, bool ignoreSneakAttack, bool ignoreTrickAttack); uint8 CheckMultiHits(CBattleEntity* PEntity, CItemWeapon* PWeapon); uint8 GetBlockRate(CBattleEntity* PAttacker, CBattleEntity* PDefender); uint8 GetParryRate(CBattleEntity* PAttacker, CBattleEntity* PDefender);