Here's the code:
zone/attack.cpp
Code:
if (damage > 0)
{
// Give the opportunity to throw back a defensive proc, if we are successful in affecting damage on our target
other->TriggerDefensiveProcs(this);
return true;
}
else
return false;
zone/mob.cpp
Code:
void Mob::TriggerDefensiveProcs(Mob *on)
{
if (this->HasDefensiveProcs()) {
this->TryDefensiveProc(on);
}
return;
}
zone/attack.cpp
Code:
bool Mob::HasDefensiveProcs() const
{
for (int i = 0; i < MAX_PROCS; i++)
if (DefensiveProcs[i].spellID != SPELL_UNKNOWN)
return true;
return false;
}
zone/attack.cpp
Code:
void Mob::TryDefensiveProc(Mob *on) {
// this should have already been checked, but just in case...
if (!this->HasDefensiveProcs())
return;
if (!on) {
SetTarget(NULL);
LogFile->write(EQEMuLog::Error, "A null Mob object was passed to Mob::TryDefensiveProc for evaluation!");
return;
}
// iterate through our defensive procs and try each of them
for (int i = 0; i < MAX_PROCS; i++) {
if (DefensiveProcs[i].spellID != SPELL_UNKNOWN &&
IsValidSpell(DefensiveProcs[i].spellID)) {
if (MakeRandomInt(0, 100) < MakeRandomInt(0, 20)) {
ExecWeaponProc(DefensiveProcs[i].spellID, on);
}
}
}
return;
}
zone/mob.cpp
Code:
void Mob::ExecWeaponProc(uint16 spell_id, Mob *on) {
// Trumpcard: Changed proc targets to look up based on the spells goodEffect flag.
// This should work for the majority of weapons.
if(spell_id == SPELL_UNKNOWN)
return;
if ( IsBeneficialSpell(spell_id) )
SpellFinished(spell_id, this, 10, 0);
else if(!(on->IsClient() && on->CastToClient()->dead)) //dont proc on dead clients
SpellFinished(spell_id, on, 10, 0);
}
From what I can see, it looks like the only thing that affects the probability of a reverse proc proccing (and maybe a woodchuck chucking?) is the random number generator. I must say though, creating 2 random numbers could create some funny odds of proccing, which may be the issue. I had to create a little program to calculate the probability, but using a sample size of 100,000,000 tries consistently gives a probability to proc of about 9.91% (specifically 9912469/100000000), at least on Windows:
Code:
#include <iostream>
using namespace std;
int MakeRandomInt(int low, int high) {
if(low >= high)
return(low);
return (rand()%(high-low+1) + (low));
}
int main() {
int l1 = 0;
int h1 = 100;
int l2 = 0;
int h2 = 20;
cout << "MakeRandomInt(" << l1 << ", " << h1 << ") < MakeRandomInt(" << l2 << ", " << h2 << ")" << endl;
int tries = 100000000; //100,000,000
int count_true = 0;
cout << "Running";
for (int i = 0; i < tries; i++) {
if ((i % 1000000) == 0)
cout << ".";
if (MakeRandomInt(l1, h1) < MakeRandomInt(l2, h2))
count_true++;
}
cout << endl;
int count_false = tries - count_true;
float percent_true = ((float)count_true / (float)tries) * 100;
float percent_false = ((float)count_false / (float)tries) * 100;
cout << "After " << tries << " tries, " << count_true << " (" << percent_true << "%) were true & " << count_false << " (" << percent_false << "%) were false." << endl;