vitorbertolucci
Member
- 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?
well you have 1, 2, 4 for the flag valuesHello I need to know how to check wether a kill was justified or not in the callback onKill. Could someone help?
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.")
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.")
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.")
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)))
Can you explain what bit.band does?Lua:if bit.band(flags, 4) ~= 0 then -- unjustified end
Understanding Bitwise OperatorsCan you explain what bit.band does?
I guess I don't understand it.
Lua:if bit.band(flags, 4) ~= 0 then -- unjustified end
do print(flags) and see
do print(flags) and see
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;
}
}
uint32_t flags = 0;
if(entry.isLast())
flags |= 1;
if(entry.isJustify())
flags |= 2;
if(entry.isUnjustified())
flags |= 4;
-- 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
function onKill(cid, target, damage, flags)
for i = 1, 20 do
if flags == i then
print(i)
end
end
return true
end
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
function onKill(cid, target, damage, flags)
for i = 1, 10 do
print(bit.band(flags, i))
end
return true
end
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
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
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.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
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
--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
-- 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
-- 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
-- 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
--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
-- 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
-- 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
-- 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
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;
}
}
if(entry.isLast())
flags |= 1;
std::cout << "1";
if(entry.isJustify())
flags |= 2;
std::cout << "2";
if(entry.isUnjustified())
flags |= 4;
std::cout << "4";
bool isUnjustified() const {return unjustified;}
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;
};
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;
}
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: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, dunno
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)
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";
}