Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

Implement Damage Calculation/Damage Check for Odin (Lithium base)

Initiate Mage
Joined
Feb 13, 2012
Messages
11
Reaction score
0
Thanks for point out the issues of my release. Yep, you right the "huge complicated procedure of rand" that you talking about is what i saw in ollyDBG, cause my v149'IDB cannot display(decompiled) that part :( Oh, and the swap min/max codes is from the decompiled code in IDA too. i just write all the things i saw in IDA to java without optimized it yet, for sure it working correctly.
.
qjagnsdldi : Unfortunately, this article not apply to old version below v92 like Eric said. In older version, it using a different things to calculate damage, You may need to re-analyze the client to find the formula to calculate damage for older version. And sure, it still using the Xorshift RNG algorithms with the seeds.

how does one find the DamageCalculation on v92 below? trying to search for v83 but can't seem to find anything
 
Joined
Jan 18, 2010
Messages
3,109
Reaction score
1,139
how does one find the DamageCalculation on v92 below? trying to search for v83 but can't seem to find anything

You apply the same calculations that BMS v53 uses on versions below v92. In v83, you still have the same CalcDamage::pDamage and CalcDamage::MDamage, the only difference is that v83 actually has Evan's implemented into the client and thus has critical rate calculations in CalcDamage::MDamage while BMS won't.

In pre-bb you won't actually see the client using a get_rand function because it simply performs the same formula all over the place. However, if you're implementing it server-side, it's cleaner and nicer to just call the "get_rand" function instead. If there were a function for get_rand in lower versions, it would simply be this:
PHP:
public static final double get_rand(long nRand, double f0, double f1) {
    // Pre-BB get_rand formula calculation.
    // Used to determine Critical Attacks and etc.
    double v320;
    if (f1 != f0) {
        // swap f1 with f0
        if (f1 > f0) {
            double Src = f1;
            f0 = f1;
            f1 = Src;
        }
        long v323 = nRand % 10000000;
        v320 = f1 + (f0 - f1) * v323 * 0.000000100000010000001;
    } else {
        v320 = f0;
    }
    return v320;
}

Where nRand will be aRandom[nIdx], aRandom will be a long[nRndSize] filled with Rand32.Random(), nRndSize will be 7 (total size of rands, const), and nIdx will be a counter starting from 0 (nIdx++ % 7). The f0 and f1 are also known as the fMin and fMax in which Nexon has various rates and formulas applied for each.

Here's small piece of how Nexon calculates criticals. Take note that the important part is that the index used for each get_rand must be in correct order, otherwise everything fails. This is the portion where they use rng to check if they could attack the mob against its avoidability, where afterwards they determine if the hit was a critical hit or not. There's a lot of checks both before and after that must be handled in order for it all to work though.
PHP:
final int nRndSize = 7;//const size of rand
long[] aRandom = new long[nRndSize];
int nIdx = 0;

// Fill random's
for (int i = 0; i < nRndSize; i++) { // do {
    aRandom[i] = pRndGenForCharacter.Random();
}

int nAmp = 5 * (bs.nINT / 10 + bs.nLUK / 10);//Magic Amplification base
double s;
if (ms.nLevel - bs.nLevel <= 0)//Level difference of mob->user
    s = 0;
else
    s = ms.nLevel - bs.nLevel;//Mob's Level - User's Level
s = (double)nAmp * 100.0d / ((double)s * 10.0d + 255.0d);

int v25 = ms.nEVA + ms.GetStat(MobStats.EVA).nOption;//Mob's Avoidability (base + buff)
if (v25 <= 0)
    v25 = 0;
if (v25 >= 999)
    v25 = 999;
int nMobMDD = v25;

int v35 = nIdx++ % 7;//the aRandom index
double b = s * 0.5d;//the minimum range
double v36 = s * 1.2d;//the maximum range
long v380 = aRandom[v35];//the random
v36 = get_rand(v380, b, v36);
if (v36 >= (double)nMobMDD) {// pass avoid rng check
    // if skill is cleric heal: perform rng
    // if skill is null or is not cleric heal: perform rng
    // if user has a critical attack property > 0:
        // if user has a critical attack parameter > 0:
            // perform rng
            // if rand < critical attack property, the hit was a critical:
                // assign abCritical to true at the index of the attack (attackinfo)
}
 
Initiate Mage
Joined
Feb 13, 2012
Messages
11
Reaction score
0
Very nice explanation, Thank you very much, and im sorry im dumb and i dont know how to express myself, i can't find the BMS v53 calculations/Leak , i wanted to find the CalcDamage::pDamage and CalcDamage::MDamage in the client using IDA, but i dont know where to get there, so i could look at the pseudo code and maybe do something similar
 
Back
Top