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!

[v62] Third Person Crits (Willing to pay)

Newbie Spellweaver
Joined
May 31, 2012
Messages
37
Reaction score
0
I'm trying to work on v62 Third Person Crits. I know its controlled server sided and whatnot but I'm not sure how I could go about doing it because I'm not too familiar with working with packets. Basic to intermediate level Java stuff is fine but I just don't have much understanding with packets. This is something that's been plaguing for years now and I just want to figure it out already so if anyone knows how to do it, I'd be willing to pay someone to get this working with me. Thanks.
 
Last edited:
Newbie Spellweaver
Joined
Oct 12, 2010
Messages
30
Reaction score
18
Community consenus (and my personal opinion) seems to be that this is VERY hard.
To show a crit simply set the highest bit of the damage number to 1, this means send the negative damage -> -1000 = 1000 displayed as critical.
It's however not trivial to figure out what damage is critical and what isn't. At log-in (and channel switching) the server sends the client a seed for a prng (pseudo random number generator) you will need to replicate the prng number fetching that the client does on the serverside. At times nexon did not get this right and I'm not aware of any pservers getting it right either.
You can however pretty easily mark any numbers outside the legal non critical damange range as crit. You won't catch ALL crits that way though.
 
Upvote 0
Newbie Spellweaver
Joined
May 31, 2014
Messages
52
Reaction score
1
Obviously being able to see crits from other people, like watching an assassin get a critical hit on a mob.
 
Upvote 0
Skilled Illusionist
Joined
Jul 16, 2010
Messages
318
Reaction score
116
I know what crits are but the idea of your post is not giving me any meaning. You should probably look at the damage parsing and the attack oacket
It's not in the attack packet. The attack packet (server recv, that is) contains no information about critical hits. You have to do it entirely serversided, which is why it's so difficult.
 
Upvote 0
C# developer
Joined
Dec 4, 2013
Messages
656
Reaction score
80
It's not in the attack packet. The attack packet (server recv, that is) contains no information about critical hits. You have to do it entirely serversided, which is why it's so difficult.

How does this work exactly?
 
Last edited:
Upvote 0
Newbie Spellweaver
Joined
May 31, 2012
Messages
37
Reaction score
0
It's not in the attack packet. The attack packet (server recv, that is) contains no information about critical hits. You have to do it entirely serversided, which is why it's so difficult.

So I found this in damageParse in AbstractDealDamageHandler.

Code:
 if (ret.skill == 3221007) {
                    damage += 0x80000000; // Critical damage = 0x80000000 + damage
                }

I noticed that the Marksman skill Snipe did show its crit in the third person. So to test out if my theory was true I did ret.skill != 3221007 so that all my other skills would do third person crits, which it did. But now my normal attacks are not working (including Mortal Blow for Archers). I'm not sure why that happens.
 
Upvote 0
Junior Spellweaver
Joined
Jan 4, 2013
Messages
162
Reaction score
29
So I found this in damageParse in AbstractDealDamageHandler.

Code:
 if (ret.skill == 3221007) {
                    damage += 0x80000000; // Critical damage = 0x80000000 + damage
                }

I noticed that the Marksman skill Snipe did show its crit in the third person. So to test out if my theory was true I did ret.skill != 3221007 so that all my other skills would do third person crits, which it did. But now my normal attacks are not working (including Mortal Blow for Archers). I'm not sure why that happens.

Do you mean certain skills are not showing up as Crits or do you mean crit. damage isn't appearing when you do damage?
 
Upvote 0
C# developer
Joined
Dec 4, 2013
Messages
656
Reaction score
80
Do you mean certain skills are not showing up as Crits or do you mean crit. damage isn't appearing when you do damage?

He means that when he hit monsters and his damage is critical, only he can see it and others cant.
 
Upvote 0
Junior Spellweaver
Joined
Jan 4, 2013
Messages
162
Reaction score
29
I'm thinking its because his damagePurse() isn't including other skills that also does crits, to show up as crits for 3rd person, since Snipe worked. Like Critical Throw which only add damage on to my watk, and doesn't even do the success rate to show the critical damage.
 
Last edited:
Upvote 0
Newbie Spellweaver
Joined
May 31, 2012
Messages
37
Reaction score
0
I'm thinking its because his damagePurse() isn't including other skills that also does crits, to show up as crits for 3rd person, since Snipe worked. Like Critical Throw which only add damage on to my watk, and doesn't even do the success rate to show the critical damage.

Does that mean that Critical Throw is handled by the client then? Because client sided there is an actual crit rate linked to it due to the player being able to see his own crit?
 
Upvote 0
Junior Spellweaver
Joined
Jan 4, 2013
Messages
162
Reaction score
29
I'm not sure about that, but I'm 100% for sure that damagePurse() is what handles the damage for other players and that 0x80000... will turn your damage to a negative, which will be display as a crit. The only problem would be to identify if your damage is crit, but I don't know that much about packets either, so I'm not sure if the client tells you if what damage is crit for damagePurse() to display 3rd person crit.



[strike]Hmm, I think I got it, this might be a wrong way to do it. Will post in a few mins once I fix up my stuff.[/strike]
[strike]For some reason I'm able to get a value of 1 for crit and a 0 for normal, but its only for 1st person.[/strike]
 
Last edited:
Upvote 0
Custom Title Activated
Loyal Member
Joined
Jan 18, 2010
Messages
3,109
Reaction score
1,139
I'm thinking its because his damagePurse() isn't including other skills that also does crits, to show up as crits, since Snipe worked. Like Critical Throw which only add damage on to my watk, and doesn't even do the success rate to show the critical damage.

First off, v62 didn't have DamageParse. Second off, DamageParse doesn't calculate REAL crits. Thirdly, fixing criticals isn't the hard part, calculating them is. I had fixed my criticals in my Development Source (for third person), however it just works the way Lithium did them which if I remember correctly it was through a sharp eye percent stat from PlayerStats or whatever.
 
Upvote 0
Junior Spellweaver
Joined
Jan 4, 2013
Messages
162
Reaction score
29
I thought he had DamageParse() since he posted "damageParse in AbstractDealDamageHandler". Maybe it was v83 and wasn't v62? I'm not going to try to calculate crit as seeing that is quite a hard thing to do, but just to display the crit colour text in 3rd person.



Crit. Colour Text Temp fix:

Place within parseDamage():
Code:
                ByteBuffer b = ByteBuffer.allocate(4);
                b.putInt(damage);

                byte[] result = b.array();
                if (result[1] > 0) {
                    damage += 0x80000000; //Critical
                }

Replace:
Code:
                if (ret.skill == Marksman.SNIPE) {
                    damage += 0x80000000; //Critical
                }

This is a cheating method, I can't promised that it will work 100%, but it seems to be working on my end atm.
This was tested on v83. ~
Maybe one day, I'll try to calculate crits, but atm I'm still inexperience, and still busy from time to time.

Credit to on stackoverflow for ByteBuffer example.
 
Last edited:
Upvote 0
Newbie Spellweaver
Joined
May 31, 2012
Messages
37
Reaction score
0
I thought he had DamageParse() since he posted "damageParse in AbstractDealDamageHandler". Maybe it was v83 and wasn't v62? I'm not going to try to calculate crit as seeing that is quite a hard thing to do, but just to display the crit colour text in 3rd person.



Crit. Colour Text Temp fix:

Place within parseDamage():
Code:
                ByteBuffer b = ByteBuffer.allocate(4);
                b.putInt(damage);

                byte[] result = b.array();
                if (result[1] > 0) {
                    damage += 0x80000000; //Critical
                }

Replace:
Code:
                if (ret.skill == Marksman.SNIPE) {
                    damage += 0x80000000; //Critical
                }

This is a cheating method, I can't promised that it will work 100%, but it seems to be working on my end atm.
This was tested on v83. ~
Maybe one day, I'll try to calculate crits, but atm I'm still inexperience, and still busy from time to time.

Credit to on stackoverflow for ByteBuffer example.

Thanks for trying to help, unfortunately its a no-go on my end. Doesn't display the crits at all. :\
 
Upvote 0
Junior Spellweaver
Joined
Jan 4, 2013
Messages
162
Reaction score
29
Thanks for trying to help, unfortunately its a no-go on my end. Doesn't display the crits at all. :\
Just making sure, but can you post your whole parseDamage() if you have one that is o-o?
 
Upvote 0
Newbie Spellweaver
Joined
May 31, 2012
Messages
37
Reaction score
0
Just making sure, but can you post your whole parseDamage() if you have one that is o-o?

Code:
public AttackInfo parseDamage(LittleEndianAccessor lea, boolean ranged) {
                // TODO we need information if an attack was a crit or not but it does not seem to be in this packet - find out
        // if it is o.o
        // noncrit strafe
        // 24 00
        // 01
        // 14
        // FE FE 30 00
        // 00
        // 97
        // 04 06 99 2F EE 00 04 00 00 00 41
        // 6B 00 00 00
        // 06 81 00 01 00 00 5F 00 00 00 5F 00 D2 02
        // A3 19 00 00 43 0C 00 00 AD 0B 00 00 DB 12 00 00 64 00 5F 00
        //
        // fullcrit strafe:
        // 24 00
        // 01
        // 14
        // FE FE 30 00
        // 00
        // 97
        // 04 06 F5 C3 EE 00 04 00 00 00 41
        // 6B 00 00 00
        // 06 81 00 01 00 00 5F 00 00 00 5F 00 D2 02
        // 6E 0F 00 00 EA 12 00 00 58 15 00 00 56 11 00 00 64 00 5F 00
        AttackInfo ret = new AttackInfo();

        lea.readByte();
        ret.numAttackedAndDamage = lea.readByte();
        ret.numAttacked = (ret.numAttackedAndDamage >>> 4) & 0xF; // guess why there are no skills damaging more than 15 monsters...
        ret.numDamage = ret.numAttackedAndDamage & 0xF; // how often each single monster was attacked o.o
        ret.allDamage = new ArrayList<Pair<Integer, List<Integer>>>();
        ret.skill = lea.readInt();

        switch (ret.skill) {
            case 2121001:
            case 2221001:
            case 2321001:
            case 5101004:
            case 5201002:
                ret.charge = lea.readInt();
                break;
            default:
                ret.charge = 0;
                break;
        }

        if (ret.skill == 1221011) {
            ret.isHH = true;
        }
        lea.readByte(); // always 0 (?)
        ret.stance = lea.readByte();

        if (ret.skill == 4211006) {
            return parseMesoExplosion(lea, ret);
        }

        if (ranged) {
            lea.readByte();
            ret.speed = lea.readByte();
            lea.readByte();
            ret.direction = lea.readByte(); // contains direction on some 4th job skills
            lea.skip(7);
            // hurricane and pierce have extra 4 bytes :/
            switch (ret.skill) {
                case 3121004:
                case 3221001:
                case 5221004:
                    lea.skip(4);
                    break;
                default:
                    break;
            }
        } else {
            lea.readByte();
            ret.speed = lea.readByte();
            lea.skip(4);
        }

        for (int i = 0; i < ret.numAttacked; i++) {
            int oid = lea.readInt();
            // System.out.println("Unk2: " + HexTool.toString(lea.read(14)));
            lea.skip(14); // seems to contain some position info o.o

            List<Integer> allDamageNumbers = new ArrayList<Integer>();
            for (int j = 0; j < ret.numDamage; j++) {
                int damage = lea.readInt();
                // System.out.println("Damage: " + damage);
                if (ret.skill == 3221007) {
                    damage += 0x80000000; // Critical damage = 0x80000000 + damage
                }
                allDamageNumbers.add(Integer.valueOf(damage));
            }
            if (ret.skill != 5221004) {
                lea.skip(4);
            }
            ret.allDamage.add(new Pair<Integer, List<Integer>>(Integer.valueOf(oid), allDamageNumbers));
        }
        // System.out.println("Unk3: " + HexTool.toString(lea.read(4)));
        return ret;
    }

I tried your fix with this code, but no go.
 
Upvote 0
Back
Top