CA

onDropLoot(cid, item)

Por caotic, 29 de mar. de 2014 em Linguagens de Programação

ondroploot
droploot
otserv
tibia
script
21
4.4k
caoticC
29 de março de 2014 às 01:20

Ola galera xtibianaaa.

Event droploot acontece quando um monstro ou player dropa 1 item.

 

Vamos la:

 

Vá em creatureevent.cpp e 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;
}

Logo em seguida coloque:

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;
}

Procure:

else if(tmpStr == "preparedeath")
m_type = CREATURE_EVENT_PREPAREDEATH;

Coloque em seguida:

else if(tmpStr == "droploot")
m_type = CREATURE_EVENT_DROPLOOT;

Logo apos procure:

case CREATURE_EVENT_PREPAREDEATH:
return "onPrepareDeath";

Coloque abaixo:

case CREATURE_EVENT_DROPLOOT:
return "onDropLoot";

Procure:

case CREATURE_EVENT_PREPAREDEATH:
return "cid, deathList";

Coloque embaixo:

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;
}
}

Coloque logo apos:

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;
}
}

Vá em creatureevent.h e procure:CREATURE_EVENT_PREPAREDEATH,

Coloque abaixo:

CREATURE_EVENT_DROPLOOT

Procure:

uint32_t executeTarget(Creature* creature, Creature* target);

Coloque abaixo:

uint32_t executeDropLoot(Creature* creature, Item* item);

Vá em player.h na função:

void Player::dropLoot(Container* corpse)

Troque por esta função:

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]);
     }
   }           
    }
}

Vá em monster.cpp e procure:

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());
}

Evento em uso:

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

 

 

 

Editado Março 30 por caotic

kttallanK
29 de março de 2014 às 01:38

Parabens você e um dos unicos menbros que colabora na area de c++, Com codigos inovadores como esse.

MaenilseM
29 de março de 2014 às 20:54

muito bom kra, realmente vai agradar boa parte do forum creio eu kra, continue assim movimentando a area

homersapiensH
29 de março de 2014 às 22:26

Uma Dúvida, o que isso Exatamente faz?

BananaFightB
30 de março de 2014 às 01:57

Ai eu te pergunto, porque diabos um gênio desses esta como "Assistente"...

TechrlzT
30 de março de 2014 às 03:06

Uma Dúvida, o que isso Exatamente faz?

 

Você pode usar isso por exemplo em 1 poketibia para avisar quando dropa 1 stone enviando 1 efeito para o personagem.

PasteelP
30 de março de 2014 às 08:59

Acho que daria para fazer um AutoLoot com essa função, enfim belo código :)


homersapiensH
30 de março de 2014 às 09:04

 

Uma Dúvida, o que isso Exatamente faz?

 

Você pode usar isso por exemplo em 1 poketibia para avisar quando dropa 1 stone enviando 1 efeito para o personagem.

 

hmm, vlw

@topic

ótimo conteúdo, obrigado por trazerao xtibia.

 

@banana

pensei a mesma coisa

JeanCristianJ
30 de março de 2014 às 19:36

alguem poderia fazer um auto loot para eu poder dar meus rep +? com essa funçao? u.u

xmaster0X
02 de abril de 2014 às 09:47

Só uma dúvida, isso não funciona em sources para poketibia não, certo?

eu tentei aqui mas da erro, e algumas das linhas que você pede pra procurar, nem existem nas sources do poketibia

Editado Abril 2 por xmaster0

LordfireL
02 de abril de 2014 às 11:52

Muito bom caotic. Acho que seria uma boa passar mais um parâmetro indicando de que creature o loot dropou.

Só funciona com creatures? Ou com players mortos também executa?

Ai eu te pergunto, porque diabos um gênio desses esta como "Assistente"...

Porque não sabe indentar kakakakak

 

 

Acho que daria para fazer um AutoLoot com essa função, enfim belo código :)

 

Exatamente, ou bloquear alguns itens em eventos especificos, ou trabalhar com a stamina por scripts e não pelas sources... inúmeras possibilidades :)

TechrlzT
03 de abril de 2014 às 13:25

 

Acho que daria para fazer um AutoLoot com essa função, enfim belo código :)

 

 

Sim, com essa função e possivel facilmente se fazer um AutoLoot como citado.

1 ano depois...
DeadpoolsD
02 de maio de 2015 às 13:19

Nessa parte:

"

Vá em monster.cpp e procure:

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());
}

"

faz o que aq? precisa add algo? depois disso


Aqui deu error:

 no `bool CreatureEvents::dropLoot(Creature*, Item*)' member function declared in class `CreatureEvents' 

Alguem sabe arrumar?

deu isso..


@UP

MartelixM
09 de maio de 2015 às 12:24

É pra TFS 0.4?

Obrigado.

caoticC
14 de maio de 2015 às 15:39

É pra TFS 0.4?

Obrigado.

tfs 0.3.6