[C++] Unique Item System
testado: TFS - 0.3.6 (porém acredito que funcione em outros)
autor: Tony Araújo (OrochiElf)
contribuição: gristony
Olá galera, beleza? Então, tem tanto tempo que eu não faço minhas contribuições e hoje eu resolvi postar um sistema bastante simples, porém de extrema necessidade e importância nos servidores que dão items iniciais aos jogadores, especialmente os poketibias. Então com esse sistema o jogador fica impossibilitado de jogar o item fora e também de fazer trocas com outros jogadores, sendo literalmente únicos. Eu criei ele em cima do código do TFS 0.3.6, porém é um sistema com o código completamente simples, então acredito que se instalado atentamente em outras versões, funcione sem problemas.
Bom, sem mais delongas vamos ao que interessa.
Vá ao game.cpp e procure por esta função:
bool Game::playerMoveItem(uint32_t playerId, const Position& fromPos,
uint16_t spriteId, int16_t fromStackpos, const Position& toPos, uint8_t count)
Então, dentro desta mesma função, você procura por esta condição aqui.
if(!player->hasCustomFlag(PlayerCustomFlag_CanThrowAnywhere))
{
if((std::abs(playerPos.x - mapToPos.x) > item->getThrowRange()) ||
(std::abs(playerPos.y - mapToPos.y) > item->getThrowRange()) ||
(std::abs(mapFromPos.z - mapToPos.z) * 4 > item->getThrowRange()))
{
player->sendCancelMessage(RET_DESTINATIONOUTOFREACH);
return false;
}
}
E logo abaixo adicione esta condição:
Item* tmpItem = NULL;
Container* tmpContainer = NULL;
if(tmpContainer = item->getContainer())
{
for(ContainerIterator it = tmpContainer->begin(); it != tmpContainer->end(); ++it)
{
if(tmpItem = (*it)->getItem())
{
boost::any value = tmpItem->getAttribute("unique");
if(!value.empty() && getMap()->getTile(toPos))
{
player->sendCancel("Has a unique item in this bag, you can't drop this item.");
return false;
}
}
}
}
boost::any value = item->getAttribute("unique");
if(!value.empty() && (!toCylinder->getItem() && toCylinder != player && toCylinder->getParent() != player || toCylinder->getItem() && toCylinder->getItem()->isGroundTile() || toCylinder->getItem() && toCylinder->getItem()->getContainer() && !toCylinder->getItem()->getContainer()->getDepot() && toCylinder->getItem()->getParent() != player))
{
player->sendCancel("It is a unique item, you can't drop this item.");
return false;
}
Certo. Continuando no game.cpp, você vai procurar pela função:
ReturnValue Game::internalMoveItem(Creature* actor, Cylinder* fromCylinder, Cylinder* toCylinder,
int32_t index, Item* item, uint32_t count, Item** _moveItem, uint32_t flags /*= 0*/)
Dentro da função, você procura pela condição:
//update item(s)
if(item->isStackable())
E troque por esta:
//update item(s)
if(item->isStackable())
{
if(toItem && toItem->getID() == item->getID())
{
boost::any item_value = item->getAttribute("unique");
boost::any toItem_value = toItem->getAttribute("unique");
if(!item_value.empty() && !toItem_value.empty() || item_value.empty() && toItem_value.empty())
{
n = std::min((uint32_t)100 - toItem->getItemCount(), m);
toCylinder->__updateThing(toItem, toItem->getID(), toItem->getItemCount() + n);
updateItem = toItem;
}
}
if(m - n > 0)
{
moveItem = Item::CreateItem(item->getID(), m - n);
boost::any value = item->getAttribute("unique");
if(!value.empty())
moveItem->setAttribute("unique", 1);
}
else
moveItem = NULL;
if(item->isRemoved())
freeThing(item);
}
Sem sair do game.cpp, você procura pela função:
bool Game::playerRequestTrade(uint32_t playerId, const Position& pos, int16_t stackpos,
uint32_t tradePlayerId, uint16_t spriteId)
Dentro dela, você procura pela condição:
if(!tradeItem || tradeItem->getClientID() != spriteId || !tradeItem->isPickupable() || (tradeItem->isLoadedFromMap() &&
(tradeItem->getUniqueId() != 0 || (tradeItem->getActionId() != 0 && tradeItem->getContainer()))))
{
player->sendCancelMessage(RET_NOTPOSSIBLE);
return false;
}
E logo abaixo você adiciona a condição:
boost::any value = tradeItem->getAttribute("unique");
if(!value.empty())
{
player->sendTextMessage(MSG_INFO_DESCR, "It is a unique item, you can't trade this item.");
return false;
}
Item* tmpItem = NULL;
Container* tmpContainer = NULL;
if(tmpContainer = tradeItem->getContainer())
{
for(ContainerIterator it = tmpContainer->begin(); it != tmpContainer->end(); ++it)
{
if(tmpItem = (*it)->getItem())
{
boost::any value = tmpItem->getAttribute("unique");
if(!value.empty())
{
player->sendTextMessage(MSG_INFO_DESCR, "Has a unique item in this bag, you can't trade this item.");
return false;
}
}
}
}
Pronto, seu sistema de unique está instalado e pronto para ser utilizado. Para você setar o item unique, basta:
doItemSetAttribute(item.uid, "unique", 1)
Algumas imagens
- NÃO PODE DAR TRADE COM ITEMS UNIQUES
- E TAMBÉM NÃO PODE DAR TRADE COM BAGS QUE TENHAM UNIQUE ID DENTRO
-NÃO PODE JOGAR O ITEM NO CHÃO
- SE TENTAR JOGAR O ITEM NO CHÃO OU EM ALGUMA BAG NO CHÃO
- NEM MESMO SE TIVER DENTRO DE UMA BAG
-
- SÓ É POSSÍVEL GUARDAR DENTRO DO DEPOT
Bom, é isso galera, espero que gostem e façam bom proveito. ;D