• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

C++ function information

mackerel

Well-Known Member
Joined
Apr 26, 2017
Messages
398
Solutions
18
Reaction score
72
Hi, in this link otland/forgottenserver

you can see the function I need help with (just some explanation).

There are 3 if statements that are important to me but I am just curious about 1

The first one will execute once you deselect the target by yourself. The third one will execute if you cannot select the target, in this case that could be an NPC. But I am not sure about the second one as I couldn't really print anything to the console

this one here:
C++:
Creature* attackCreature = getCreatureByID(creatureId);
if (!attackCreature) {

If anyone could provide me with some info that would be great

C++:
if (player->getAttackedCreature() && creatureId == 0) {
        player->setAttackedCreature(nullptr);
        player->sendCancelTarget();
        return;
    }

    Creature* attackCreature = getCreatureByID(creatureId);
    if (!attackCreature) {
        player->setAttackedCreature(nullptr);
        player->sendCancelTarget();
        return;
    }

    ReturnValue ret = Combat::canTargetCreature(player, attackCreature);
    if (ret != RETURNVALUE_NOERROR) {
        player->sendCancelMessage(ret);
        player->sendCancelTarget();
        player->setAttackedCreature(nullptr);
        return;
}
 
Solution
To expand on what @samco said, the main purpose of getCreatureById() is to make sure a creature with that id actually exists in memory. If it exists, a pointer to the creature is returned, otherwise nullptr is returned. Without the check to see if a valid pointer is returned [if (!attackCreature)] then Combat::canTargetCreature() would crash the server because of a null-pointer-dereference.

One way you could test this is to craft your own AttackCreature packet client-side and pass an invalid creature id (like 0). There's multiple ways of doing this, but none are simple unless you know how to inject a DLL into the client and hook the AttackCreature packet constructor, or set up a proxy and capture the AttackCreature packet and...
Hi, in this link otland/forgottenserver

you can see the function I need help with (just some explanation).

There are 3 if statements that are important to me but I am just curious about 1

The first one will execute once you deselect the target by yourself. The third one will execute if you cannot select the target, in this case that could be an NPC. But I am not sure about the second one as I couldn't really print anything to the console

this one here:
C++:
Creature* attackCreature = getCreatureByID(creatureId);
if (!attackCreature) {

If anyone could provide me with some info that would be great

C++:
if (player->getAttackedCreature() && creatureId == 0) {
        player->setAttackedCreature(nullptr);
        player->sendCancelTarget();
        return;
    }

    Creature* attackCreature = getCreatureByID(creatureId);
    if (!attackCreature) {
        player->setAttackedCreature(nullptr);
        player->sendCancelTarget();
        return;
    }

    ReturnValue ret = Combat::canTargetCreature(player, attackCreature);
    if (ret != RETURNVALUE_NOERROR) {
        player->sendCancelMessage(ret);
        player->sendCancelTarget();
        player->setAttackedCreature(nullptr);
        return;
}
I think its just a control in case the creature is killed at the same moment you target it.
 
To expand on what @samco said, the main purpose of getCreatureById() is to make sure a creature with that id actually exists in memory. If it exists, a pointer to the creature is returned, otherwise nullptr is returned. Without the check to see if a valid pointer is returned [if (!attackCreature)] then Combat::canTargetCreature() would crash the server because of a null-pointer-dereference.

One way you could test this is to craft your own AttackCreature packet client-side and pass an invalid creature id (like 0). There's multiple ways of doing this, but none are simple unless you know how to inject a DLL into the client and hook the AttackCreature packet constructor, or set up a proxy and capture the AttackCreature packet and modify it.
 
Solution
To expand on what @samco said, the main purpose of getCreatureById() is to make sure a creature with that id actually exists in memory. If it exists, a pointer to the creature is returned, otherwise nullptr is returned. Without the check to see if a valid pointer is returned [if (!attackCreature)] then Combat::canTargetCreature() would crash the server because of a null-pointer-dereference.

One way you could test this is to craft your own AttackCreature packet client-side and pass an invalid creature id (like 0). There's multiple ways of doing this, but none are simple unless you know how to inject a DLL into the client and hook the AttackCreature packet constructor, or set up a proxy and capture the AttackCreature packet and modify it.
Or if you are compiling in VS, just attach the process to the debugger, and set the attackCreature to null
 
Back
Top