• 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++ Check if a kill is unjustified

Joined
Apr 15, 2014
Messages
75
Reaction score
18
Hello I need to know how to check wether a kill was justified or not in the callback onKill. Could someone help?
 
Hello I need to know how to check wether a kill was justified or not in the callback onKill. Could someone help?
well you have 1, 2, 4 for the flag values
So you can check them all individually, I believe.
Code:
print("Starting checks..")
if bit.band(flags, 1) then
    print("isLast")
end
if bit.band(flags, 2) then
    print("isJustified")
end
if bit.band(flags, 4) then
    print("isNotJustified")
end
print("Finished checks.")

-- Sorry, large edit.

Code:
print("Starting checks..")
if bit.band(flags, 1) == 1 then
    print("isLast")
end
if bit.band(flags, 1) == 2 then
    print("isJustified")
end
if bit.band(flags, 1) == 4 then
    print("isNotJustified")
end
print("Finished checks.")
 
Last edited:
well you have 1, 2, 4 for the flag values
So you can check them all individually, I believe.
Code:
print("Starting checks..")
if bit.band(flags, 1) then
    print("isLast")
end
if bit.band(flags, 2) then
    print("isJustified")
end
if bit.band(flags, 4) then
    print("isNotJustified")
end
print("Finished checks.")

-- Sorry, large edit.

Code:
print("Starting checks..")
if bit.band(flags, 1) == 1 then
    print("isLast")
end
if bit.band(flags, 1) == 2 then
    print("isJustified")
end
if bit.band(flags, 1) == 4 then
    print("isNotJustified")
end
print("Finished checks.")

I tryied but no matter what I kill (monsters, skulled players or non-skulled players) it always prints 'isLast' and nothing more. Which means that for some reason bit.band(flags, 1) is always 1

And when I print(flags) it always prints 3
 
mm, guess I don't know the answer.
I'd have to do some tests on my home computer.

for now.. maybe check if flags is storing multiple values?

I think this is how you use unpack.. xD
Code:
print(f(unpack(flags)))
 
mm, guess I don't know the answer.
I'd have to do some tests on my home computer.

for now.. maybe check if flags is storing multiple values?

I think this is how you use unpack.. xD
Code:
print(f(unpack(flags)))

It only gives an error because flag is not a table but a number =X
 
do print(flags) and see
C++:
uint32_t CreatureEvent::executeKill(Creature* creature, Creature* target, const DeathEntry& entry)
{
    //onKill(cid, target, damage, flags)
    if(m_interface->reserveEnv())
    {
        uint32_t flags = 0;
        if(entry.isLast())
            flags |= 1;

        if(entry.isJustify())
            flags |= 2;

        if(entry.isUnjustified())
            flags |= 4;

        ScriptEnviroment* env = m_interface->getEnv();
        if(m_scripted == EVENT_SCRIPT_BUFFER)
        {
            env->setRealPos(creature->getPosition());
            std::stringstream scriptstream;
            scriptstream << "local cid = " << env->addThing(creature) << std::endl;

            scriptstream << "local target = " << env->addThing(target) << std::endl;
            scriptstream << "local damage = " << entry.getDamage() << std::endl;
            scriptstream << "local flags = " << flags << std::endl;
            scriptstream << "local war = " << entry.getWar().war << std::endl;

            if(m_scriptData)
                scriptstream << *m_scriptData;

            bool result = true;
            if(m_interface->loadBuffer(scriptstream.str()))
            {
                lua_State* L = m_interface->getState();
                result = m_interface->getGlobalBool(L, "_result", true);
            }

            m_interface->releaseEnv();
            return result;
        }
        else
        {
            #ifdef __DEBUG_LUASCRIPTS__
            std::stringstream desc;
            desc << creature->getName();
            env->setEvent(desc.str());
            #endif

            env->setScriptId(m_scriptId, m_interface);
            env->setRealPos(creature->getPosition());

            lua_State* L = m_interface->getState();
            m_interface->pushFunction(m_scriptId);

            lua_pushnumber(L, env->addThing(creature));
            lua_pushnumber(L, env->addThing(target));

            lua_pushnumber(L, entry.getDamage());
            lua_pushnumber(L, flags);
            lua_pushnumber(L, entry.getWar().war);

            bool result = m_interface->callFunction(5);
            m_interface->releaseEnv();
            return result;
        }
    }
    else
    {
        std::clog << "[Error - CreatureEvent::executeKill] Call stack overflow." << std::endl;
        return 0;
    }
}
C++:
uint32_t flags = 0;
        if(entry.isLast())
            flags |= 1;

        if(entry.isJustify())
            flags |= 2;

        if(entry.isUnjustified())
            flags |= 4;
Since it's using bit.bor.. doesn't that mean that the flag values possible should only be these?
Code:
-- 0 + nothing
0 = you attacked a monster and didn't kill it
-- 0 + 1
1 = you attacked a monster and dealt the killing blow
-- 0 + 2
2 = you attacked a player but didn't kill it
-- 1 + 4
5 = you attacked a player and dealt the killing blow
But like @Killua Real states, no matter how I test flags, it always produces unlogical results.

Lua:
function onKill(cid, target, damage, flags)
   for i = 1, 20 do
       if flags == i then
           print(i)
       end
   end
   return true
end
This results in the number 3 printed in any situation.
Monster = 3
Summoned Monster = 3
Killing an unskulled player = 3
Killing a skulled player = 3

Lua:
function onKill(cid, target, damage, flags)
   print("Starting checks..")
   if bit.band(flags, 1) ~= 0 then
       print("isLast")
   end
   if bit.band(flags, 2) ~= 0 then
       print("isJustified")
   end
   if bit.band(flags, 4) ~= 0 then
       print("isNotJustified")
   end
   print("Finished checks.")
   return true
end
This results in
Monster = "isLast" and "isJustified"
Summoned Monster = "isLast" and "isJustified"
Killing an unskulled player = "isLast" and "isJustified"
Killing a skulled player = "isLast" and "isJustified"

Then I got wild and tried this..
Lua:
function onKill(cid, target, damage, flags)
   for i = 1, 10 do
       print(bit.band(flags, i))
   end
   return true
end
Results in
Monster = 1, 2, 3, 0, 1, 2, 3, 0, 1, 2
Killing an unskulled player = 1, 2, 3, 0, 1, 2, 3, 0, 1, 2


So at this point I'm just baffled as to what is even happening. lol
What is flags even doing?
It results in 3 no matter what we do, and bit.band is just giving us random numbers that don't correspond to anything.

Honestly, I just feel retarded at this point.
 
Flags is a uint32_t which stores multiple flags (basically boolean values, 1 or 0). Each flag uses a bit of the flags variable.
To set a flag in the variable bitwise-or is used in conjunction with a power of two (the first flag uses 2^0 = 1, the second flag uses 2^1 = 2, .., the i-th flag uses 2^(i-1)).
To check whether a flag is set, you can use bit.band(flags, i) where i is a power of two.
You have to understand the binary representation of these numbers to understand it properly.

If flags is 3 that means that the kill was isLast and isJustified. I don't know why none of the kills are unjustified, but it might be an issue residing in the sources.

How to check flags:
Code:
for flag = 0, 10 do
   local isSet = bit.band(flags, math.pow(2, flag)) ~= 0
   print('Flag ' .. flag .. ' is ' .. (isSet and 'set' or 'not set'))
end
 
Flags is a uint32_t which stores multiple flags (basically boolean values, 1 or 0). Each flag uses a bit of the flags variable.
To set a flag in the variable bitwise-or is used in conjunction with a power of two (the first flag uses 2^0 = 1, the second flag uses 2^1 = 2, .., the i-th flag uses 2^(i-1)).
To check whether a flag is set, you can use bit.band(flags, i) where i is a power of two.
You have to understand the binary representation of these numbers to understand it properly.

If flags is 3 that means that the kill was isLast and isJustified. I don't know why none of the kills are unjustified, but it might be an issue residing in the sources.

How to check flags:
Code:
for flag = 0, 10 do
   local isSet = bit.band(flags, math.pow(2, flag)) ~= 0
   print('Flag ' .. flag .. ' is ' .. (isSet and 'set' or 'not set'))
end

Again the result is
Flag 0 is set
Flag 1 is set
Flag 2 is not set
Flag 3 is not set
Flag 4 is not set
Flag 5 is not set
Flag 6 is not set
Flag 7 is not set
Flag 8 is not set
Flag 9 is not set
Flag 10 is not set

No matter what I kill...

I was feeling retarded too @Xikini, but now i think neither of we are and it is just a source issue xD

Could you help with that, @Summ?
 
Flags is a uint32_t which stores multiple flags (basically boolean values, 1 or 0). Each flag uses a bit of the flags variable.
To set a flag in the variable bitwise-or is used in conjunction with a power of two (the first flag uses 2^0 = 1, the second flag uses 2^1 = 2, .., the i-th flag uses 2^(i-1)).
To check whether a flag is set, you can use bit.band(flags, i) where i is a power of two.
You have to understand the binary representation of these numbers to understand it properly.

If flags is 3 that means that the kill was isLast and isJustified. I don't know why none of the kills are unjustified, but it might be an issue residing in the sources.

How to check flags:
Code:
for flag = 0, 10 do
   local isSet = bit.band(flags, math.pow(2, flag)) ~= 0
   print('Flag ' .. flag .. ' is ' .. (isSet and 'set' or 'not set'))
end
I can't see the server log at the moment so I'm not sure why your code as-is was erroring, but I just changed it slighty to test with blue text.
I guess it's an issue within the source, because I tried each scenario with a fresh character/(s) and this is how it resulted.
(Note: I didn't think it's do anything different, but I also tried a few times with "for flag = 0, 100 do" and everything was "not set" beyond 0 & 1)
Lua:
function onKill(cid, target, damage, flags)
   for flag = 0, 10 do
       if bit.band(flags, math.pow(2, flag)) ~= 0 then
           --print('Flag ' .. flag .. ' is ' .. (isSet and 'set' or 'not set'))
           doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, flag .. " set")
       else
           doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, flag .. " not set")
       end
   end
   return true
end
Code:
--kill white skull, with unskulled player
22:38 0 set
22:38 1 set
22:38 2 not set
22:38 3 not set
22:38 4 not set
22:38 5 not set
22:38 6 not set
22:38 7 not set
22:38 8 not set
22:38 9 not set
22:38 10 not set
Code:
-- kill player with no skull
22:39 0 set
22:39 1 set
22:39 2 not set
22:39 3 not set
22:39 4 not set
22:39 5 not set
22:39 6 not set
22:39 7 not set
22:39 8 not set
22:39 9 not set
22:39 10 not set
Code:
-- kill /m rat
22:41 0 set
22:41 1 set
22:41 2 not set
22:41 3 not set
22:41 4 not set
22:41 5 not set
22:41 6 not set
22:41 7 not set
22:41 8 not set
22:41 9 not set
22:41 10 not set
Code:
-- kill /summon rat
22:41 0 set
22:41 1 set
22:41 2 not set
22:41 3 not set
22:41 4 not set
22:41 5 not set
22:41 6 not set
22:41 7 not set
22:41 8 not set
22:41 9 not set
22:41 10 not set
Code:
--kill white skull, with unskulled player
-- but don't deal killing blow
22:46 0 not set
22:46 1 set
22:46 2 not set
22:46 3 not set
22:46 4 not set
22:46 5 not set
22:46 6 not set
22:46 7 not set
22:46 8 not set
22:46 9 not set
22:46 10 not set
Code:
-- kill player with no skull
-- but don't deal killing blow
22:48 0 not set
22:48 1 set
22:48 2 not set
22:48 3 not set
22:48 4 not set
22:48 5 not set
22:48 6 not set
22:48 7 not set
22:48 8 not set
22:48 9 not set
22:48 10 not set
Code:
-- kill /m rat
-- but don't deal killing blow
22:49 0 not set
22:49 1 set
22:49 2 not set
22:49 3 not set
22:49 4 not set
22:49 5 not set
22:49 6 not set
22:49 7 not set
22:49 8 not set
22:49 9 not set
22:49 10 not set
Code:
-- kill /summon rat
-- but don't deal killing blow
22:52 0 not set
22:52 1 set
22:52 2 not set
22:52 3 not set
22:52 4 not set
22:52 5 not set
22:52 6 not set
22:52 7 not set
22:52 8 not set
22:52 9 not set
22:52 10 not set

Sooo yeah. No idea what "1" is doing, since it triggered everytime, whether it was justified or unjustified, and whether it was player or creature.
The only thing that works, is confirming who did the killing blow to the creature, as far as I can tell. (but we knew this already. ._.)


I also checked this, just in case it was a spelling error in the functions..
I doubt it helps, but at least it rules out something. :rolleyes:
9pPdkZq.png

C++:
uint32_t CreatureEvent::executeKill(Creature* creature, Creature* target, const DeathEntry& entry)
{
    //onKill(cid, target, damage, flags)
    if(m_interface->reserveEnv())
    {
        uint32_t flags = 0;
        if(entry.isLast())
            flags |= 1;

        if(entry.isJustify())
            flags |= 2;

        if(entry.isUnjustified())
            flags |= 4;

        ScriptEnviroment* env = m_interface->getEnv();
        if(m_scripted == EVENT_SCRIPT_BUFFER)
        {
            env->setRealPos(creature->getPosition());
            std::stringstream scriptstream;
            scriptstream << "local cid = " << env->addThing(creature) << std::endl;

            scriptstream << "local target = " << env->addThing(target) << std::endl;
            scriptstream << "local damage = " << entry.getDamage() << std::endl;
            scriptstream << "local flags = " << flags << std::endl;
            scriptstream << "local war = " << entry.getWar().war << std::endl;

            if(m_scriptData)
                scriptstream << *m_scriptData;

            bool result = true;
            if(m_interface->loadBuffer(scriptstream.str()))
            {
                lua_State* L = m_interface->getState();
                result = m_interface->getGlobalBool(L, "_result", true);
            }

            m_interface->releaseEnv();
            return result;
        }
        else
        {
            #ifdef __DEBUG_LUASCRIPTS__
            std::stringstream desc;
            desc << creature->getName();
            env->setEvent(desc.str());
            #endif

            env->setScriptId(m_scriptId, m_interface);
            env->setRealPos(creature->getPosition());

            lua_State* L = m_interface->getState();
            m_interface->pushFunction(m_scriptId);

            lua_pushnumber(L, env->addThing(creature));
            lua_pushnumber(L, env->addThing(target));

            lua_pushnumber(L, entry.getDamage());
            lua_pushnumber(L, flags);
            lua_pushnumber(L, entry.getWar().war);

            bool result = m_interface->callFunction(5);
            m_interface->releaseEnv();
            return result;
        }
    }
    else
    {
        std::clog << "[Error - CreatureEvent::executeKill] Call stack overflow." << std::endl;
        return 0;
    }
}
 
Last edited:
I went a little deeper and tryied:

C++:
if(entry.isLast())
            flags |= 1;
            std::cout << "1";

        if(entry.isJustify())
            flags |= 2;
            std::cout << "2";

        if(entry.isUnjustified())
            flags |= 4;
            std::cout << "4";

(This code is correct, right?)
I compiled it with no problem and tested, but it never prints anything... (At least I think that's how to do a print in there, Im not good with C++)

So, if my code is correct, it means entry.isUnjustified() doesn't ever recognizes wether a kill is justified or not and that the problem would be in there.

The function isUnjustified is declared in ceature.h like this:
C++:
bool isUnjustified() const {return unjustified;}

And this is the DeathEntry structure that is called in the onKill callback:
C++:
struct DeathEntry
{
        DeathEntry(std::string name, int32_t dmg):
            data(name), damage(dmg), last(false), justify(false), unjustified(false) {}
        DeathEntry(Creature* killer, int32_t dmg):
            data(killer), damage(dmg), last(false), justify(false), unjustified(false) {}

        bool isCreatureKill() const {return data.type() == typeid(Creature*);}
        bool isNameKill() const {return !isCreatureKill();}

        void setWar(War_t v) {war = v;}
        War_t getWar() const {return war;}

        void setLast() {last = true;}
        bool isLast() const {return last;}

        void setJustify() {justify = true;}
        bool isJustify() const {return justify;}

        void setUnjustified() {unjustified = true;}
        bool isUnjustified() const {return unjustified;}

        const std::type_info& getKillerType() const {return data.type();}
        int32_t getDamage() const {return damage;}

        Creature* getKillerCreature() const {return boost::any_cast<Creature*>(data);}
        std::string getKillerName() const {return boost::any_cast<std::string>(data);}

    protected:
        friend struct DeathLessThan;

        boost::any data;
        int32_t damage;
        War_t war;

        bool last;
        bool justify;
        bool unjustified;
};

The function that calls the callback on kill is Creature::eek:nKilledCreature(Creature* target, DeathEntry& entry):
C++:
bool Creature::onKilledCreature(Creature* target, DeathEntry& entry)
{
    bool ret = true;
    if(master)
        ret = master->onKilledCreature(target, entry);

    CreatureEventList killEvents = getCreatureEvents(CREATURE_EVENT_KILL);
    if(!entry.isLast())
    {
        for(CreatureEventList::iterator it = killEvents.begin(); it != killEvents.end(); ++it)
            (*it)->executeKill(this, target, entry);

        return true;
    }

    for(CreatureEventList::iterator it = killEvents.begin(); it != killEvents.end(); ++it)
    {
        if(!(*it)->executeKill(this, target, entry) && ret)
            ret = false;
    }

    return ret;
}

But it doesn't set the kill as unjustified anywhere...
Sorry if I misinformed something, I'm really in a rush because my bus leaves in 30 minutes xD
 
I went a little deeper and tryied:

C++:
if(entry.isLast())
            flags |= 1;
            std::cout << "1";

        if(entry.isJustify())
            flags |= 2;
            std::cout << "2";

        if(entry.isUnjustified())
            flags |= 4;
            std::cout << "4";

(This code is correct, right?)
I compiled it with no problem and tested, but it never prints anything... (At least I think that's how to do a print in there, Im not good with C++)

So, if my code is correct, it means entry.isUnjustified() doesn't ever recognizes wether a kill is justified or not and that the problem would be in there.

The function isUnjustified is declared in ceature.h like this:
C++:
bool isUnjustified() const {return unjustified;}

And this is the DeathEntry structure that is called in the onKill callback:
C++:
struct DeathEntry
{
        DeathEntry(std::string name, int32_t dmg):
            data(name), damage(dmg), last(false), justify(false), unjustified(false) {}
        DeathEntry(Creature* killer, int32_t dmg):
            data(killer), damage(dmg), last(false), justify(false), unjustified(false) {}

        bool isCreatureKill() const {return data.type() == typeid(Creature*);}
        bool isNameKill() const {return !isCreatureKill();}

        void setWar(War_t v) {war = v;}
        War_t getWar() const {return war;}

        void setLast() {last = true;}
        bool isLast() const {return last;}

        void setJustify() {justify = true;}
        bool isJustify() const {return justify;}

        void setUnjustified() {unjustified = true;}
        bool isUnjustified() const {return unjustified;}

        const std::type_info& getKillerType() const {return data.type();}
        int32_t getDamage() const {return damage;}

        Creature* getKillerCreature() const {return boost::any_cast<Creature*>(data);}
        std::string getKillerName() const {return boost::any_cast<std::string>(data);}

    protected:
        friend struct DeathLessThan;

        boost::any data;
        int32_t damage;
        War_t war;

        bool last;
        bool justify;
        bool unjustified;
};

The function that calls the callback on kill is Creature::eek:nKilledCreature(Creature* target, DeathEntry& entry):
C++:
bool Creature::onKilledCreature(Creature* target, DeathEntry& entry)
{
    bool ret = true;
    if(master)
        ret = master->onKilledCreature(target, entry);

    CreatureEventList killEvents = getCreatureEvents(CREATURE_EVENT_KILL);
    if(!entry.isLast())
    {
        for(CreatureEventList::iterator it = killEvents.begin(); it != killEvents.end(); ++it)
            (*it)->executeKill(this, target, entry);

        return true;
    }

    for(CreatureEventList::iterator it = killEvents.begin(); it != killEvents.end(); ++it)
    {
        if(!(*it)->executeKill(this, target, entry) && ret)
            ret = false;
    }

    return ret;
}

But it doesn't set the kill as unjustified anywhere...
Sorry if I misinformed something, I'm really in a rush because my bus leaves in 30 minutes xD

I believe it doesnt print anything because 2 statenents on an if statement without curly bois {} may cause unexpected behavior?
Is it bad practice to use an if-statement without brackets?

edit: or it probably doesn't matter in this case (since you said that it didn't print anything at all)
 
Last edited:
I believe it doesnt print anything because 2 statenents on an if statement without curly bois {} may cause unexpected behavior?
Is it bad practice to use an if-statement without brackets?

edit: or it probably doesn't matter in this case (since you said that it didn't print anything at all)

I recompiled it with brackets and still doen't print anything
C++:
uint32_t flags = 0;
        if(entry.isLast())
        {
            flags |= 1;
            std::cout << "1";
        }

        if(entry.isJustify())
        {
            flags |= 2;
            std::cout << "2";
        }

        if(entry.isUnjustified())
        {
            flags |= 4;
            std::cout << "4";
        }
 
Back
Top