Even though I thought that code looked good, it isn't right yet. Looks like I will have to review everything that Mob::CheckHitChance is doing:
Code:
bool Mob::CheckHitChance(Mob* other, SkillType skillinuse, int Hand)
{
/*
Father Nitwit:
Reworked a lot of this code to achieve better balance at higher levels.
The old code basically meant that any in high level (50+) combat,
both parties always had 95% chance to hit the other one.
*/
Mob *attacker=other;
Mob *defender=this;
float chancetohit = 54.0f;
#if ATTACK_DEBUG>=11
LogFile->write(EQEMuLog::Debug, "CheckHitChance(%s) attacked by %s", defender->GetName(), attacker->GetName());
#endif
bool pvpmode = false;
if(IsClient() && other->IsClient())
pvpmode = true;
float bonus;
////////////////////////////////////////////////////////
// To hit calcs go here
////////////////////////////////////////////////////////
int8 attacker_level = attacker->GetLevel() ? attacker->GetLevel() : 1;
int8 defender_level = defender->GetLevel() ? defender->GetLevel() : 1;
//Calculate the level difference
sint32 level_difference = attacker_level - defender_level;
if(level_difference < -20) level_difference = -20;
if(level_difference > 20) level_difference = 20;
chancetohit += (145 * level_difference / 100);
chancetohit -= ((float)defender->GetAGI() * 0.015);
if(attacker->IsClient()){
int skilldiff = defender->GetSkill(DEFENSE) - attacker->GetSkill(skillinuse);
bonus = 0;
if(pvpmode){
if(skilldiff > 10){
bonus = -(2 + ((defender->GetSkill(DEFENSE) - attacker->GetSkill(skillinuse) - 10) / 10));
}
else if(skilldiff <= 10 && skilldiff > 0){
bonus = -(1 + ((defender->GetSkill(DEFENSE) - attacker->GetSkill(skillinuse)) / 25));
}
else{
bonus = (attacker->GetSkill(skillinuse) - defender->GetSkill(DEFENSE)) / 25;
}
}
else{
if(skilldiff > 10){
bonus = -(4 + ((defender->GetSkill(DEFENSE) - attacker->GetSkill(skillinuse) - 10) * 1 / 5));
}
else if(skilldiff <= 10 && skilldiff > 0){
bonus = -(2 + ((defender->GetSkill(DEFENSE) - attacker->GetSkill(skillinuse)) / 10));
}
else{
bonus = 1 + (((attacker->GetSkill(skillinuse) - defender->GetSkill(DEFENSE)) / 25));
}
}
chancetohit += bonus;
}
else{
//some class combos have odd caps, base our attack skill based off of a warriors 1hslash since
//it scales rather evenly across all levels for warriors, based on the defenders level so things like
//light blues can still hit their target.
uint16 atkSkill = (database.GetSkillCap(WARRIOR, (SkillType)_1H_SLASHING, defender->GetLevel()) + 5);
int skilldiff = defender->GetSkill(DEFENSE) - atkSkill;
bonus = 0;
if(skilldiff > 10){
bonus = -(4 + ((defender->GetSkill(DEFENSE) - atkSkill - 10) * 1 / 5));
}
else if(skilldiff <= 10 && skilldiff > 0){
bonus = -(2 + ((defender->GetSkill(DEFENSE) - atkSkill) / 10));
}
else{
bonus = 1 + ((atkSkill - defender->GetSkill(DEFENSE)) / 25);
}
chancetohit += bonus;
}
//I dont think this is 100% correct, but at least it does something...
if(attacker->spellbonuses.MeleeSkillCheckSkill == skillinuse || attacker->spellbonuses.MeleeSkillCheckSkill == 255) {
chancetohit += attacker->spellbonuses.MeleeSkillCheck;
mlog(COMBAT__TOHIT, "Applied spell melee skill bonus %d, yeilding %.2f", attacker->spellbonuses.MeleeSkillCheck, chancetohit);
}
if(attacker->itembonuses.MeleeSkillCheckSkill == skillinuse || attacker->itembonuses.MeleeSkillCheckSkill == 255) {
chancetohit += attacker->itembonuses.MeleeSkillCheck;
mlog(COMBAT__TOHIT, "Applied item melee skill bonus %d, yeilding %.2f", attacker->spellbonuses.MeleeSkillCheck, chancetohit);
}
//subtract off avoidance by the defender
bonus = defender->spellbonuses.AvoidMeleeChance + defender->itembonuses.AvoidMeleeChance;
if(bonus > 0) {
chancetohit -= (bonus) / 10;
mlog(COMBAT__TOHIT, "Applied avoidance chance %.2f/10, yeilding %.2f", bonus, chancetohit);
}
if(attacker->IsNPC())
chancetohit += (chancetohit * attacker->CastToNPC()->GetAccuracyRating() / 1000);
uint16 AA_mod = 0;
switch(GetAA(aaCombatAgility))
{
case 1:
AA_mod = 2;
break;
case 2:
AA_mod = 5;
break;
case 3:
AA_mod = 10;
break;
}
AA_mod += 3*GetAA(aaPhysicalEnhancement);
AA_mod += 2*GetAA(aaLightningReflexes);
AA_mod += GetAA(aaReflexiveMastery);
chancetohit -= chancetohit * AA_mod / 100;
//add in our hit chance bonuses if we are using the right skill
//does the hit chance cap apply to spell bonuses from disciplines?
if(attacker->spellbonuses.HitChanceSkill == 255 || attacker->spellbonuses.HitChanceSkill == skillinuse) {
chancetohit += (chancetohit * (attacker->spellbonuses.HitChance / 15.0f) / 100);
mlog(COMBAT__TOHIT, "Applied spell melee hit chance %d/15, yeilding %.2f", attacker->spellbonuses.HitChance, chancetohit);
}
if(attacker->itembonuses.HitChanceSkill == 255 || attacker->itembonuses.HitChanceSkill == skillinuse) {
chancetohit += (chancetohit * (attacker->itembonuses.HitChance / 15.0f) / 100);
mlog(COMBAT__TOHIT, "Applied item melee hit chance %d/15, yeilding %.2f", attacker->itembonuses.HitChance, chancetohit);
}
// Chance to hit; Max 95%, Min 30%
if(chancetohit > 1000) {
//if chance to hit is crazy high, that means a discipline is in use, and let it stay there
}
else if(chancetohit > 99) {
chancetohit = 99;
}
else if(chancetohit < 5) {
chancetohit = 5;
}
//I dont know the best way to handle a garunteed hit discipline being used
//agains a garunteed riposte (for example) discipline... for now, garunteed hit wins
#if EQDEBUG>=11
LogFile->write(EQEMuLog::Debug, "3 FINAL calculated chance to hit is: %5.2f", chancetohit);
#endif
//
// Did we hit?
//
float tohit_roll = MakeRandomFloat(0, 100);
mlog(COMBAT__TOHIT, "Final hit chance: %.2f%%. Hit roll %.2f", chancetohit, tohit_roll);
return(tohit_roll <= chancetohit);
}