Event droploot acontece quando um monstro ou player dropa 1 item.
Em creatureevent.cpp procure:
bool CreatureEvents::playerLogin(Player* player)
{
//fire global event if is registered
bool result = true;
for(CreatureEventList::iterator it = m_creatureEvents.begin(); it != m_creatureEvents.end(); ++it)
{
if(it->second->getEventType() == CREATURE_EVENT_LOGIN &&
!it->second->executeLogin(player) && result)
result = false;
}
return result;
Adicione abaixo:
bool CreatureEvents::dropLoot(Creature* creature, Item* item)
{
bool result = true;
for(CreatureEventList::iterator it = m_creatureEvents.begin(); it != m_creatureEvents.end(); ++it)
{
if(it->second->getEventType() == CREATURE_EVENT_DROPLOOT &&
!it->second->executeDropLoot(creature, item))
result = false;
}
return result;
}
Ainda em creatureevents.cpp procure:
else if(tmpStr == "preparedeath")
m_type = CREATURE_EVENT_PREPAREDEATH;
Adicione abaixo:
else if(tmpStr == "droploot")
m_type = CREATURE_EVENT_DROPLOOT;
Procure:
case CREATURE_EVENT_PREPAREDEATH:
return "onPrepareDeath";
Adicione abaixo:
case CREATURE_EVENT_DROPLOOT:
return "onDropLoot";
Procure:
case CREATURE_EVENT_PREPAREDEATH:
return "cid, deathList";
Adicione abaixo:
case CREATURE_EVENT_DROPLOOT:
return "cid, item";
Procure:
uint32_t CreatureEvent::executeLogout(Player* player, bool forceLogout)
{
//onLogout(cid, forceLogout)
if(m_interface->reserveEnv())
{
ScriptEnviroment* env = m_interface->getEnv();
if(m_scripted == EVENT_SCRIPT_BUFFER)
{
env->setRealPos(player->getPosition());
std::stringstream scriptstream;
scriptstream << "local cid = " << env->addThing(player) << std::endl;
scriptstream << "local forceLogout = " << (forceLogout ? "true" : "false") << std::endl;
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__
char desc[35];
sprintf(desc, "%s", player->getName().c_str());
env->setEventDesc(desc);
#endif
env->setScriptId(m_scriptId, m_interface);
env->setRealPos(player->getPosition());
lua_State* L = m_interface->getState();
m_interface->pushFunction(m_scriptId);
lua_pushnumber(L, env->addThing(player));
lua_pushboolean(L, forceLogout);
bool result = m_interface->callFunction(2);
m_interface->releaseEnv();
return result;
}
}
else
{
std::cout << "[Error - CreatureEvent::executeLogout] Call stack overflow." << std::endl;
return 0;
}
}
Adicione abaixo:
uint32_t CreatureEvent::executeDropLoot(Creature* creature, Item* item)
{
//onDropLoot(cid, item)
if(m_interface->reserveEnv())
{
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;
env->streamThing(scriptstream, "item", item, env->addThing(item));
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__
char desc[35];
sprintf(desc, "%s", player->getName().c_str());
env->setEventDesc(desc);
#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));
LuaScriptInterface::pushThing(L, item, env->addThing(item));
bool result = m_interface->callFunction(2);
m_interface->releaseEnv();
return result;
}
}
else
{
std::cout << "[Error - CreatureEvent::executeDropLoot] Call stack overflow." << std::endl;
return 0;
}
}
Em creatureevent.h procure:
CREATURE_EVENT_PREPAREDEATH,
Adicione abaixo:
CREATURE_EVENT_DROPLOOT
Procure:
uint32_t executeTarget(Creature* creature, Creature* target);
Adicione abaixo:
uint32_t executeDropLoot(Creature* creature, Item* item);
Agora em player.h procure a função:
void Player::dropLoot(Container* corpse)
Troque por:
void Player::dropLoot(Container* corpse)
{
if(!corpse || lootDrop != LOOT_DROP_FULL)
return;
uint32_t start = g_config.getNumber(ConfigManager::BLESS_REDUCTION_BASE), loss = lossPercent[LOSS_CONTAINERS], bless = getBlessings();
while(bless > 0 && loss > 0)
{
loss -= start;
start -= g_config.getNumber(ConfigManager::BLESS_REDUCTION_DECREAMENT);
bless--;
}
uint32_t itemLoss = (uint32_t)std::floor((5. + loss) * lossPercent[LOSS_ITEMS] / 1000.);
for(int32_t i = SLOT_FIRST; i < SLOT_LAST; ++i)
{
Item* item = inventory[i];
if(!item)
continue;
Creature* creature = NULL;
bool deny = false;item creature = g_game.getCreatureByID(getID());
CreatureEventList droploot = getCreatureEvents(CREATURE_EVENT_DROPLOOT);
for(CreatureEventList::iterator it = droploot.begin(); it != droploot.end(); ++it)
{
if(!(*it)->executeDropLoot(this, item))
deny = true;
}
if(!deny) {
uint32_t rand = random_range(1, 100);
if(skull > SKULL_WHITE || (item->getContainer() && rand < loss) || (!item->getContainer() && rand < itemLoss))
{
g_game.internalMoveItem(NULL, this, corpse, INDEX_WHEREEVER, item, item->getItemCount(), 0);
sendRemoveInventoryItem((slots_t)i, inventory[(slots_t)i]);
}
}
}
}
Em monster.cpp procure:
void MonsterType::dropLoot(Container* corpse)
{
if(corpse && lootDrop == LOOT_DROP_FULL)
mType->dropLoot(corpse);
}
Troque por:
void MonsterType::dropLoot(Container* corpse)
{
Item* tmpItem = NULL;
for(LootItems::const_iterator it = lootItems.begin(); it != lootItems.end() && !corpse->full(); ++it)
{
uint32_t owner = corpse->getCorpseOwner();
Creature* creature = g_game.getCreatureByID(owner);
if((tmpItem = createLoot(*it)) && g_creatureEvents->dropLoot(creature, tmpItem))
{
if(Container* container = tmpItem->getContainer())
{
if(createChildLoot(container, (*it)))
corpse->__internalAddThing(tmpItem);
else
delete container;
}
else
corpse->__internalAddThing(tmpItem);
}
}
corpse->__startDecaying();
uint32_t ownerId = corpse->getCorpseOwner();
if(!ownerId)
return;
Player* owner = g_game.getPlayerByID(ownerId);
if(!owner)
return;
LootMessage_t message = lootMessage;
if(message == LOOTMSG_IGNORE)
message = (LootMessage_t)g_config.getNumber(ConfigManager::LOOT_MESSAGE);
if(message < LOOTMSG_PLAYER)
return;
std::stringstream ss;
ss << "Loot of " << nameDescription << ": " << corpse->getContentDescription() << ".";
if(owner->getParty() && message > LOOTMSG_PLAYER)
owner->getParty()->broadcastMessage((MessageClasses)g_config.getNumber(ConfigManager::LOOT_MESSAGE_TYPE), ss.str());
else if(message == LOOTMSG_PLAYER || message == LOOTMSG_BOTH)
owner->sendTextMessage((MessageClasses)g_config.getNumber(ConfigManager::LOOT_MESSAGE_TYPE), ss.str());
}
Exemplo de uso da função:
function onDropLoot(cid, item)
local block = {2221, 1221, 2922}
for i=1, #block do
if item.itemid == block[i] then
return false
end
end
return true
end
Créditos: Caotic