Postado Março 30, 2022 3 anos Este é um post popular. salve rapaziada, do TK, esses tempos eu tava a procura de um autoloot bom e eficiente, e como vocês devem saber, o autoloot usado nos scripts .lua são bem "pesados" o @Naze fez um excelentíssimo trabalho e disponibilizou um script de autoloot na source, porém como a vida é dificil, ele tem alguns bugs de função e um deles é no "remove autoloot" que quando o player digita "!autoloot remove, nome-do-item" nada acontece, eu decidi mexer e vim disponibilizar arrumado pra vcs. LEMBRANDO QUE 100% DOS CRÉDITOS SÃO AO @Naze porém se vc procurar no tópico dele ainda vai estar bugado, então resolvi deixar aqui certinho pra ajudar quem precisar. Link do tópico do naze: https://tibiaking.com/forums/topic/101086-otimizado-autoloot-in-sources-for-otx2-ou-menor/ Mostrar conteúdo oculto Localize no arquivo "configmanager.h" os enum de string: enum string_config_t { DUMMY_STR = 0, CONFIG_FILE, MAP_NAME, HOUSE_RENT_PERIOD, E Adicione: enum string_config_t { AUTOLOOT_BLOCKIDS, //autoloot by naze#3578 AUTOLOOT_MONEYIDS, //autoloot by naze#3578 DUMMY_STR = 0, CONFIG_FILE, MAP_NAME, HOUSE_RENT_PERIOD, No mesmo arquivo localize o enum de number: enum number_config_t { LOGIN_TRIES = 0, RETRY_TIMEOUT, LOGIN_TIMEOUT, LOGIN_PORT, E adicione: enum number_config_t { AUTOLOOT_MAXITEM, //autoloot by naze#3578 LOGIN_TRIES = 0, RETRY_TIMEOUT, LOGIN_TIMEOUT, LOGIN_PORT, Localize no arquivo "configmanager.cpp" : m_confString[MAP_AUTHOR] = getGlobalString("mapAuthor", "Unknown"); m_confNumber[LOGIN_TRIES] = getGlobalNumber("loginTries", 3); E adicione: m_confString[AUTOLOOT_BLOCKIDS] = getGlobalString("AutoLoot_BlockIDs", ""); //autoloot by naze#3578 m_confString[AUTOLOOT_MONEYIDS] = getGlobalString("AutoLoot_MoneyIDs", "2148;2152;2160"); //autoloot by naze#3578 m_confNumber[AUTOLOOT_MAXITEM] = getGlobalNumber("AutoLoot_MaxItem", 100); //autoloot by naze#3578 m_confString[MAP_AUTHOR] = getGlobalString("mapAuthor", "Unknown"); m_confNumber[LOGIN_TRIES] = getGlobalNumber("loginTries", 3); Localize no arquivo "iologindata.cpp" : //load storage map query.str(""); query << "SELECT `key`, `value` FROM `player_storage` WHERE `player_id` = " << player->getGUID(); if((result = db->storeQuery(query.str()))) { do player->setStorage(result->getDataString("key"), result->getDataString("value")); while(result->next()); result->free(); } E adicione a baixo : //load autoloot query.str(""); query << "SELECT `autoloot_list` FROM `player_autoloot` WHERE `player_id` = " << player->getGUID(); if ((result = db->storeQuery(query.str()))) { unsigned long lootListSize; const char* autoLootList = result->getDataStream("autoloot_list", lootListSize); // PropStream &propStream; PropStream propStream; propStream.init(autoLootList, lootListSize); uint16_t value; uint16_t item = propStream.getType<uint16_t>(value); while (item) { player->addAutoLoot(value); item = propStream.getType<uint16_t>(value); } } player->updateStatusAutoLoot(true); std::string msg = g_config.getString(ConfigManager::AUTOLOOT_MONEYIDS); StringVec strVector = explodeString(msg, ";"); for(StringVec::iterator it = strVector.begin(); it != strVector.end(); ++it) { uint16_t id = atoi((*it).c_str()); player->addAutoLoot(id); } vai ficar da seguinte forma: Mostrar conteúdo oculto //load storage map query.str(""); query << "SELECT `key`, `value` FROM `player_storage` WHERE `player_id` = " << player->getGUID(); if((result = db->storeQuery(query.str()))) { do player->setStorage(result->getDataString("key"), result->getDataString("value")); while(result->next()); result->free(); } //load autoloot query.str(""); query << "SELECT `autoloot_list` FROM `player_autoloot` WHERE `player_id` = " << player->getGUID(); if ((result = db->storeQuery(query.str()))) { unsigned long lootListSize; const char* autoLootList = result->getDataStream("autoloot_list", lootListSize); // PropStream &propStream; PropStream propStream; propStream.init(autoLootList, lootListSize); uint16_t value; uint16_t item = propStream.getType<uint16_t>(value); while (item) { player->addAutoLoot(value); item = propStream.getType<uint16_t>(value); } } player->updateStatusAutoLoot(true); std::string msg = g_config.getString(ConfigManager::AUTOLOOT_MONEYIDS); StringVec strVector = explodeString(msg, ";"); for(StringVec::iterator it = strVector.begin(); it != strVector.end(); ++it) { uint16_t id = atoi((*it).c_str()); player->addAutoLoot(id); } no mesmo arquivo localize: query.str(""); //save vip list if(!g_config.getBool(ConfigManager::VIPLIST_PER_PLAYER)) query << "DELETE FROM `account_viplist` WHERE `account_id` = " << player->getAccount() << " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID); else query << "DELETE FROM `player_viplist` WHERE `player_id` = " << player->getGUID(); if(!db->query(query.str())) return false; E Acima adicione: //save autoloot query.str(""); query << "DELETE FROM `player_autoloot` WHERE `player_id` = " << player->getGUID(); if(!db->query(query.str())) return false; PropWriteStream PWS_AutoLoot; std::list<uint16_t> autoLootList = player->getAutoLoot(); for (std::list<uint16_t>::iterator it = autoLootList.begin(); it != autoLootList.end(); ++it) { PWS_AutoLoot.addShort(*it); } uint32_t PWS_Size = 0; const char* autoLoot = PWS_AutoLoot.getStream(PWS_Size); query.str(""); stmt.setQuery("INSERT INTO `player_autoloot` (`player_id`, `autoloot_list`) VALUES "); query << player->getGUID() << ',' << db->escapeBlob(autoLoot, PWS_Size); if (!stmt.addRow(query)) { return false; } if (!stmt.execute()) { return false; } vai ficar da seguinte forma: Mostrar conteúdo oculto /save autoloot query.str(""); query << "DELETE FROM `player_autoloot` WHERE `player_id` = " << player->getGUID(); if(!db->query(query.str())) return false; PropWriteStream PWS_AutoLoot; std::list<uint16_t> autoLootList = player->getAutoLoot(); for (std::list<uint16_t>::iterator it = autoLootList.begin(); it != autoLootList.end(); ++it) { PWS_AutoLoot.addShort(*it); } uint32_t PWS_Size = 0; const char* autoLoot = PWS_AutoLoot.getStream(PWS_Size); query.str(""); stmt.setQuery("INSERT INTO `player_autoloot` (`player_id`, `autoloot_list`) VALUES "); query << player->getGUID() << ',' << db->escapeBlob(autoLoot, PWS_Size); if (!stmt.addRow(query)) { return false; } if (!stmt.execute()) { return false; } query.str(""); //save vip list if(!g_config.getBool(ConfigManager::VIPLIST_PER_PLAYER)) query << "DELETE FROM `account_viplist` WHERE `account_id` = " << player->getAccount() << " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID); else query << "DELETE FROM `player_viplist` WHERE `player_id` = " << player->getGUID(); if(!db->query(query.str())) return false; Agora no arquivo "monsters.cpp" localize toda a função "dropLoot" : (ATENÇÃO: não confunda com "monster.cpp") void MonsterType::dropLoot(Container* corpse) { ItemList items; for(LootItems::const_iterator it = lootItems.begin(); it != lootItems.end() && !corpse->full(); ++it) { items = createLoot(*it); if(items.empty()) continue; for(ItemList::iterator iit = items.begin(); iit != items.end(); ++iit) { Item* tmpItem = *iit; 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.getPlayerByGuid(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()); } e substitua com atenção ela toda por essa: oid MonsterType::dropLoot(Container* corpse) { uint32_t money = 0; ItemList items; std::stringstream str; for(LootItems::const_iterator it = lootItems.begin(); it != lootItems.end() && !corpse->full(); ++it) { items = createLoot(*it); if(items.empty()) continue; for(ItemList::iterator iit = items.begin(); iit != items.end(); ++iit) { Item* tmpItem = *iit; if(Container* container = tmpItem->getContainer()) { Player* tmpPlayer = g_game.getPlayerByGuid(corpse->getCorpseOwner()); if(createChildLoot(container, (*it), money, str, tmpPlayer)) { corpse->__internalAddThing(tmpItem); } else { delete container; } } else { bool LootCatch = false; Player* tmpPlayer = g_game.getPlayerByGuid(corpse->getCorpseOwner()); if(tmpPlayer) { if(tmpPlayer->statusAutoLoot() == "On") { LootCatch = tmpPlayer->checkAutoLoot(tmpItem->getID()); if(LootCatch) { if(tmpPlayer->isMoneyAutoLoot(tmpItem, money)) { continue; } g_game.internalPlayerAddItem(NULL, tmpPlayer, tmpItem); str << " " << tmpItem->getNameDescription() << ","; continue; } } } corpse->__internalAddThing(tmpItem); } } } corpse->__startDecaying(); uint32_t ownerId = corpse->getCorpseOwner(); if(!ownerId) return; Player* owner = g_game.getPlayerByGuid(ownerId); if(!owner) return; if(money != 0) { if(owner->statusAutoMoneyCollect() == "Bank"){ owner->balance += money; } else { g_game.addMoney(owner, money); } str << " " << money << "x gold coins."; } else { str << " nothing gold coins."; } 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->statusAutoLoot() == "On") { ss << "\nAutoLoot Colleted:" << str.str(); } 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()); } No mesmo arquivo localize a função a baixo chamada "createChildLoot": bool MonsterType::createChildLoot(Container* parent, const LootBlock& lootBlock) { LootItems::const_iterator it = lootBlock.childLoot.begin(); if(it == lootBlock.childLoot.end()) return true; ItemList items; for(; it != lootBlock.childLoot.end() && !parent->full(); ++it) { items = createLoot(*it); if(items.empty()) continue; for(ItemList::iterator iit = items.begin(); iit != items.end(); ++iit) { Item* tmpItem = *iit; if(Container* container = tmpItem->getContainer()) { if(createChildLoot(container, *it)) parent->__internalAddThing(tmpItem); else delete container; } else parent->__internalAddThing(tmpItem); } } return !parent->empty(); } E substitua por essa: bool MonsterType::createChildLoot(Container* parent, const LootBlock& lootBlock, uint32_t& money, std::stringstream& str, Player* player) { LootItems::const_iterator it = lootBlock.childLoot.begin(); if(it == lootBlock.childLoot.end()) return true; ItemList items; for(; it != lootBlock.childLoot.end() && !parent->full(); ++it) { items = createLoot(*it); if(items.empty()) continue; for(ItemList::iterator iit = items.begin(); iit != items.end(); ++iit) { Item* tmpItem = *iit; if(Container* container = tmpItem->getContainer()) { if(createChildLoot(container, *it, money, str, player)) parent->__internalAddThing(tmpItem); else delete container; } else { bool LootCatch = false; if(player && (player->statusAutoLoot() == "On")) { LootCatch = player->checkAutoLoot(tmpItem->getID()); } if(LootCatch) { if(player->isMoneyAutoLoot(tmpItem, money)) { continue; } g_game.internalPlayerAddItem(NULL, player, tmpItem); str << " " << tmpItem->getNameDescription() << ","; continue; } parent->__internalAddThing(tmpItem); } } } return !parent->empty(); } Agora no arquivo "monsters.h" altera apenas uma linha: Encontre: bool createChildLoot(Container* parent, const LootBlock& lootBlock); e troque por: bool createChildLoot(Container* parent, const LootBlock& lootBlock, uint32_t& money, std::stringstream& str, Player* player); Agora no arquivo "player.h" encontre nas funções public: void learnInstantSpell(const std::string& name); void unlearnInstantSpell(const std::string& name); bool hasLearnedInstantSpell(const std::string& name) const; E adicione abaixo: //Autoloot by: Naze std::list<uint16_t> getAutoLoot() { return AutoLoot; } void clearAutoLoot() { AutoLoot.clear(); } void addAutoLoot(uint16_t id); void removeAutoLoot(uint16_t id); bool limitAutoLoot(); bool checkAutoLoot(uint16_t id); bool isMoneyAutoLoot(Item* item, uint32_t& count); std::string statusAutoLoot() { return (autoLootStatus ? "On" : "Off"); } void updateStatusAutoLoot(bool status){ autoLootStatus = status; } std::string statusAutoMoneyCollect() { return (autoMoneyCollect ? "Bank" : "Bag"); } void updateMoneyCollect(bool status) { autoMoneyCollect = status; } Localize no mesmo arquivo as declarações private: private: bool is_spectating; bool talkState[13]; bool inventoryAbilities[SLOT_LAST]; bool pzLocked; e adicione 3 variáveis: private: bool autoLootStatus; //autoloot by naze bool autoMoneyCollect; //autoloot by naze std::list<uint16_t> AutoLoot; //autoloot by naze bool is_spectating; bool talkState[13]; bool inventoryAbilities[SLOT_LAST]; bool pzLocked; Agora no arquivo "player.cpp" localize no começo a função: Player::Player(const std::string& _name, ProtocolGame* p): Creature(), transferContainer(ITEM_LOCKER), name(_name), nameDescription(_name), client(p) { if(client) client->setPlayer(this); pzLocked = isConnecting = addAttackSkillPoint = requestedOutfit = false; saving = true; lastAttackBlockType = BLOCK_NONE; e adicione: Player::Player(const std::string& _name, ProtocolGame* p): Creature(), transferContainer(ITEM_LOCKER), name(_name), nameDescription(_name), client(p) { if(client) client->setPlayer(this); pzLocked = isConnecting = addAttackSkillPoint = requestedOutfit = false; saving = true; autoLootStatus = true; //autoloot by naze autoMoneyCollect = true; //autoloot by naze lastAttackBlockType = BLOCK_NONE; Ainda em "player.cpp" vá até as ultimas função: void Player::sendCritical() const { if(g_config.getBool(ConfigManager::DISPLAY_CRITICAL_HIT)) g_game.addAnimatedText(getPosition(), COLOR_DARKRED, "CRITICAL!"); } void Player::setPlayerExtraAttackSpeed(uint32_t speed) { extraAttackSpeed = speed; } E adicione abaixo: void Player::addAutoLoot(uint16_t id) { if(checkAutoLoot(id)) { return; } AutoLoot.push_back(id); } /*Parte do autoloot remove que foi arrumado*/ void Player::removeAutoLoot(uint16_t id) { if(!checkAutoLoot(id)) return; for(std::list<uint16_t>::iterator it = AutoLoot.begin(); it != AutoLoot.end(); ++it) { if((*it) == id) { AutoLoot.erase(it); break; } } } bool Player::limitAutoLoot() { std::list<uint16_t> list = getAutoLoot(); if((uint16_t)list.size() >= g_config.getNumber(ConfigManager::AUTOLOOT_MAXITEM)) { return true; } return false; } bool Player::checkAutoLoot(uint16_t id) { if(Item::items[id].isContainer()) { return true; } std::string msg = g_config.getString(ConfigManager::AUTOLOOT_BLOCKIDS); StringVec strVector = explodeString(msg, ";"); for(StringVec::iterator it = strVector.begin(); it != strVector.end(); ++it) { if(atoi((*it).c_str()) == id) { return true; } } for(std::list<uint16_t>::iterator it = AutoLoot.begin(); it != AutoLoot.end(); ++it) { if((*it) == id) { return true; } } return false; } bool Player::isMoneyAutoLoot(Item* item, uint32_t& count) { bool isMoney = false; std::string msg = g_config.getString(ConfigManager::AUTOLOOT_MONEYIDS); StringVec strVector = explodeString(msg, ";"); for(StringVec::iterator it = strVector.begin(); it != strVector.end(); ++it) { if(item->getID() == atoi((*it).c_str())) { isMoney = true; break; } } if(!isMoney) { return false; } count += item->getWorth(); return true; } Agora quase finalizando no arquivo "talkactions.h" localize: static TalkFunction diagnostics; static TalkFunction addSkill; static TalkFunction ghost; static TalkFunction software; E adicione: static TalkFunction diagnostics; static TalkFunction addSkill; static TalkFunction autoLoot; //autoloot by naze static TalkFunction ghost; static TalkFunction software; Encontre no arquivo "talkactions.cpp" : else if(m_functionName == "diagnostics") m_function = diagnostics; else if(m_functionName == "addskill") m_function = addSkill; else if(m_functionName == "ghost") m_function = ghost; else if(m_functionName == "software") m_function = software; E Adicione: else if(m_functionName == "diagnostics") m_function = diagnostics; else if(m_functionName == "addskill") m_function = addSkill; else if(m_functionName == "autoloot") //autoloot by naze m_function = autoLoot; else if(m_functionName == "ghost") m_function = ghost; else if(m_functionName == "software") m_function = software; Ainda em "talkactions.cpp" encontre o começo de ghost: bool TalkAction::ghost(Creature* creature, const std::string&, const std::string&) { Player* player = creature->getPlayer(); if(!player) return false; E adicione a cima a seguinte função: bool TalkAction::autoLoot(Creature* creature, const std::string&, const std::string& param) { Player* player = creature->getPlayer(); if(!player) return false; StringVec params = explodeString(param, ","); std::stringstream info; if(params[0] == "on" or params[0] == "off") { player->updateStatusAutoLoot((params[0] == "on" ? true : false)); info << "Autoloot-> Status: " << (player->statusAutoLoot()) << "."; player->sendTextMessage(MSG_STATUS_CONSOLE_BLUE, info.str()); return true; } if(params[0] == "clear" or params[0] == "clean") { player->clearAutoLoot(); info << "Autoloot-> Todos itens removidos."; player->sendTextMessage(MSG_STATUS_CONSOLE_BLUE, info.str()); return true; } if(params[0] == "list" or params[0] == "lista") { std::list<uint16_t> list = player->getAutoLoot(); std::list<uint16_t>::iterator it = list.begin(); std::string msg = g_config.getString(ConfigManager::AUTOLOOT_MONEYIDS); StringVec strVector = explodeString(msg, ";"); for(StringVec::iterator itt = strVector.begin(); itt != strVector.end(); ++itt) { ++it; } uint16_t i = 1; for(; it != list.end(); ++it) { info << i << ": " << Item::items[(*it)].name << std::endl; ++i; } player->sendFYIBox((info.str() == "" ? "Nada Adicionado." : info.str())); return true; } if(params.size() <= 1) { info << "_____Perfect AutoLoot System_____\nAutoLoot Status: " << player->statusAutoLoot() << "\nAutoMoney Mode: " << player->statusAutoMoneyCollect() << "\n\nComandos:\n!autoloot on/off\n!autoloot money, bank/bag\n!autoloot add, item name, item name, item name...\n!autoloot remove, item name, item name, item name...\n!autoloot list\n!autoloot clear\n\n\n (Sistema livre de bugs e gratuito no TibiaKing!)"; player->sendFYIBox(info.str()); return true; } if(params[0] == "money") { for(StringVec::iterator it = params.begin(); it != params.end(); ++it) { if((*it) == "money") { continue; } char param[150]; sprintf(param, "%s", (*it).c_str()); int len = strlen(param); for (int i = 0, pos = 0; i < len; i++, pos++) { if (param[0] == ' '){ pos++; } param[i] = param[pos]; } if((strcmp(param, "bank") == 0) or (strcmp(param, "bag") == 0)) { player->updateMoneyCollect((strcmp(param, "bank") == 0) ? true : false); info << "AutoMoney-> Collect Mode: " << (player->statusAutoMoneyCollect()) << "."; player->sendTextMessage(MSG_STATUS_CONSOLE_BLUE, info.str()); return true; } } } if(params[0] == "add") { std::stringstream add, err; uint8_t addCount = 0, errCount = 0; std::stringstream ss; for(StringVec::iterator it = params.begin(); it != params.end(); ++it) { if((*it) == "add") { continue; } char name[150]; sprintf(name, "%s", (*it).c_str()); int len = strlen(name); for (int i = 0, pos = 0; i < len; i++, pos++) { if (name[0] == ' '){ pos++; } name[i] = name[pos]; } int32_t itemId = Item::items.getItemIdByName(name); if(!player->checkAutoLoot(itemId)) { if(itemId > 0) { std::string str = addCount > 0 ? ", " : ""; ++addCount; add << str << name; player->addAutoLoot(itemId); continue; } } std::string str = errCount > 0 ? ", " : ""; ++errCount; err << str << name; } ss << "AutoLoot-> Adicionados: " << ((add.str() == "") ? "Nenhum" : add.str()) << ". Erros: " << ((err.str() == "") ? "Nenhum" : err.str()) << "."; player->sendTextMessage(MSG_STATUS_CONSOLE_RED, ss.str()); return true; } if(params[0] == "remove") { std::stringstream remove, err; uint8_t removeCount = 0, errCount = 0; std::stringstream ss; for(StringVec::iterator it = params.begin(); it != params.end(); ++it) { if((*it) == "remove") { continue; } char name[150]; sprintf(name, "%s", (*it).c_str()); int len = strlen(name); for (int i = 0, pos = 0; i < len; i++, pos++) { if (name[0] == ' '){ pos++; } name[i] = name[pos]; } int32_t itemId = Item::items.getItemIdByName(name); if(player->checkAutoLoot(itemId)) { if(itemId > 0) { std::string str = removeCount > 0 ? ", " : ""; ++removeCount; remove << str << name; player->removeAutoLoot(itemId); continue; } } std::string str = errCount > 0 ? ", " : ""; ++errCount; err << str << name; } ss << "AutoLoot-> Removidos: " << ((remove.str() == "") ? "Nenhum" : remove.str()) << ". Erros: " << ((err.str() == "") ? "Nenhum" : err.str()) << "."; player->sendTextMessage(MSG_STATUS_CONSOLE_ORANGE, ss.str()); return true; } return true; } Com isso toda parte na source está instalada, agora vá até seu config.lua e adicione onde achar melhor as seguintes linhas: AutoLoot_BlockIDs = "" -- adicione ids separado por ; ex: "1111;2222;3333" AutoLoot_MoneyIDs = "2148;2152;2160" -- adicione os ids dos itens moeda, caso seja os 3 normais pode retirar essa linha AutoLoot_MaxItem = 100 -- quantidade de itens maximo na lista Agora para finalizar abra o data/talkactions/talkactions.xml e adicione a seguinte tag: <talkaction words="/autoloot;!autoloot" event="function" value="autoloot"/> E execute a seguinte query em seu banco de dados: CREATE TABLE player_autoloot ( id int NOT NULL AUTO_INCREMENT, player_id int NOT NULL, autoloot_list blob, PRIMARY KEY (id) ); caso alguém ja utilize esse autoloot e esteja com o problema de remover items do autoloot só ir em player.cpp e trocar isso: void Player::removeAutoLoot(uint16_t id) { if(checkAutoLoot(id)) { return; } AutoLoot.remove(id); } por isso: void Player::removeAutoLoot(uint16_t id) { if(!checkAutoLoot(id)) return; for(std::list<uint16_t>::iterator it = AutoLoot.begin(); it != AutoLoot.end(); ++it) { if((*it) == id) { AutoLoot.erase(it); break; } } } todos os créditos ao Naze, não sei se alguém mais fez esse código, mas como peguei do link citado acima que é post dele deixo aqui o autoloot 100% funcional direto nas sources
Postado Novembro 10, 2022 2 anos Em 30/03/2022 em 08:14, FeeTads disse: salve rapaziada, do TK, esses tempos eu tava a procura de um autoloot bom e eficiente, e como vocês devem saber, o autoloot usado nos scripts .lua são bem "pesados" o @Naze fez um excelentíssimo trabalho e disponibilizou um script de autoloot na source, porém como a vida é dificil, ele tem alguns bugs de função e um deles é no "remove autoloot" que quando o player digita "!autoloot remove, nome-do-item" nada acontece, eu decidi mexer e vim disponibilizar arrumado pra vcs. LEMBRANDO QUE 100% DOS CRÉDITOS SÃO AO @Naze porém se vc procurar no tópico dele ainda vai estar bugado, então resolvi deixar aqui certinho pra ajudar quem precisar. Link do tópico do naze: https://tibiaking.com/forums/topic/101086-otimizado-autoloot-in-sources-for-otx2-ou-menor/ Mostrar conteúdo oculto Mostrar conteúdo oculto Localize no arquivo "configmanager.h" os enum de string: enum string_config_t { DUMMY_STR = 0, CONFIG_FILE, MAP_NAME, HOUSE_RENT_PERIOD, E Adicione: enum string_config_t { AUTOLOOT_BLOCKIDS, //autoloot by naze#3578 AUTOLOOT_MONEYIDS, //autoloot by naze#3578 DUMMY_STR = 0, CONFIG_FILE, MAP_NAME, HOUSE_RENT_PERIOD, No mesmo arquivo localize o enum de number: enum number_config_t { LOGIN_TRIES = 0, RETRY_TIMEOUT, LOGIN_TIMEOUT, LOGIN_PORT, E adicione: enum number_config_t { AUTOLOOT_MAXITEM, //autoloot by naze#3578 LOGIN_TRIES = 0, RETRY_TIMEOUT, LOGIN_TIMEOUT, LOGIN_PORT, Localize no arquivo "configmanager.cpp" : m_confString[MAP_AUTHOR] = getGlobalString("mapAuthor", "Unknown"); m_confNumber[LOGIN_TRIES] = getGlobalNumber("loginTries", 3); E adicione: m_confString[AUTOLOOT_BLOCKIDS] = getGlobalString("AutoLoot_BlockIDs", ""); //autoloot by naze#3578 m_confString[AUTOLOOT_MONEYIDS] = getGlobalString("AutoLoot_MoneyIDs", "2148;2152;2160"); //autoloot by naze#3578 m_confNumber[AUTOLOOT_MAXITEM] = getGlobalNumber("AutoLoot_MaxItem", 100); //autoloot by naze#3578 m_confString[MAP_AUTHOR] = getGlobalString("mapAuthor", "Unknown"); m_confNumber[LOGIN_TRIES] = getGlobalNumber("loginTries", 3); Localize no arquivo "iologindata.cpp" : //load storage map query.str(""); query << "SELECT `key`, `value` FROM `player_storage` WHERE `player_id` = " << player->getGUID(); if((result = db->storeQuery(query.str()))) { do player->setStorage(result->getDataString("key"), result->getDataString("value")); while(result->next()); result->free(); } E adicione a baixo : //load autoloot query.str(""); query << "SELECT `autoloot_list` FROM `player_autoloot` WHERE `player_id` = " << player->getGUID(); if ((result = db->storeQuery(query.str()))) { unsigned long lootListSize; const char* autoLootList = result->getDataStream("autoloot_list", lootListSize); // PropStream &propStream; PropStream propStream; propStream.init(autoLootList, lootListSize); uint16_t value; uint16_t item = propStream.getType<uint16_t>(value); while (item) { player->addAutoLoot(value); item = propStream.getType<uint16_t>(value); } } player->updateStatusAutoLoot(true); std::string msg = g_config.getString(ConfigManager::AUTOLOOT_MONEYIDS); StringVec strVector = explodeString(msg, ";"); for(StringVec::iterator it = strVector.begin(); it != strVector.end(); ++it) { uint16_t id = atoi((*it).c_str()); player->addAutoLoot(id); } vai ficar da seguinte forma: Mostrar conteúdo oculto Mostrar conteúdo oculto //load storage map query.str(""); query << "SELECT `key`, `value` FROM `player_storage` WHERE `player_id` = " << player->getGUID(); if((result = db->storeQuery(query.str()))) { do player->setStorage(result->getDataString("key"), result->getDataString("value")); while(result->next()); result->free(); } //load autoloot query.str(""); query << "SELECT `autoloot_list` FROM `player_autoloot` WHERE `player_id` = " << player->getGUID(); if ((result = db->storeQuery(query.str()))) { unsigned long lootListSize; const char* autoLootList = result->getDataStream("autoloot_list", lootListSize); // PropStream &propStream; PropStream propStream; propStream.init(autoLootList, lootListSize); uint16_t value; uint16_t item = propStream.getType<uint16_t>(value); while (item) { player->addAutoLoot(value); item = propStream.getType<uint16_t>(value); } } player->updateStatusAutoLoot(true); std::string msg = g_config.getString(ConfigManager::AUTOLOOT_MONEYIDS); StringVec strVector = explodeString(msg, ";"); for(StringVec::iterator it = strVector.begin(); it != strVector.end(); ++it) { uint16_t id = atoi((*it).c_str()); player->addAutoLoot(id); } no mesmo arquivo localize: query.str(""); //save vip list if(!g_config.getBool(ConfigManager::VIPLIST_PER_PLAYER)) query << "DELETE FROM `account_viplist` WHERE `account_id` = " << player->getAccount() << " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID); else query << "DELETE FROM `player_viplist` WHERE `player_id` = " << player->getGUID(); if(!db->query(query.str())) return false; E Acima adicione: //save autoloot query.str(""); query << "DELETE FROM `player_autoloot` WHERE `player_id` = " << player->getGUID(); if(!db->query(query.str())) return false; PropWriteStream PWS_AutoLoot; std::list<uint16_t> autoLootList = player->getAutoLoot(); for (std::list<uint16_t>::iterator it = autoLootList.begin(); it != autoLootList.end(); ++it) { PWS_AutoLoot.addShort(*it); } uint32_t PWS_Size = 0; const char* autoLoot = PWS_AutoLoot.getStream(PWS_Size); query.str(""); stmt.setQuery("INSERT INTO `player_autoloot` (`player_id`, `autoloot_list`) VALUES "); query << player->getGUID() << ',' << db->escapeBlob(autoLoot, PWS_Size); if (!stmt.addRow(query)) { return false; } if (!stmt.execute()) { return false; } vai ficar da seguinte forma: Mostrar conteúdo oculto Mostrar conteúdo oculto /save autoloot query.str(""); query << "DELETE FROM `player_autoloot` WHERE `player_id` = " << player->getGUID(); if(!db->query(query.str())) return false; PropWriteStream PWS_AutoLoot; std::list<uint16_t> autoLootList = player->getAutoLoot(); for (std::list<uint16_t>::iterator it = autoLootList.begin(); it != autoLootList.end(); ++it) { PWS_AutoLoot.addShort(*it); } uint32_t PWS_Size = 0; const char* autoLoot = PWS_AutoLoot.getStream(PWS_Size); query.str(""); stmt.setQuery("INSERT INTO `player_autoloot` (`player_id`, `autoloot_list`) VALUES "); query << player->getGUID() << ',' << db->escapeBlob(autoLoot, PWS_Size); if (!stmt.addRow(query)) { return false; } if (!stmt.execute()) { return false; } query.str(""); //save vip list if(!g_config.getBool(ConfigManager::VIPLIST_PER_PLAYER)) query << "DELETE FROM `account_viplist` WHERE `account_id` = " << player->getAccount() << " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID); else query << "DELETE FROM `player_viplist` WHERE `player_id` = " << player->getGUID(); if(!db->query(query.str())) return false; Agora no arquivo "monsters.cpp" localize toda a função "dropLoot" : (ATENÇÃO: não confunda com "monster.cpp") void MonsterType::dropLoot(Container* corpse) { ItemList items; for(LootItems::const_iterator it = lootItems.begin(); it != lootItems.end() && !corpse->full(); ++it) { items = createLoot(*it); if(items.empty()) continue; for(ItemList::iterator iit = items.begin(); iit != items.end(); ++iit) { Item* tmpItem = *iit; 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.getPlayerByGuid(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()); } e substitua com atenção ela toda por essa: oid MonsterType::dropLoot(Container* corpse) { uint32_t money = 0; ItemList items; std::stringstream str; for(LootItems::const_iterator it = lootItems.begin(); it != lootItems.end() && !corpse->full(); ++it) { items = createLoot(*it); if(items.empty()) continue; for(ItemList::iterator iit = items.begin(); iit != items.end(); ++iit) { Item* tmpItem = *iit; if(Container* container = tmpItem->getContainer()) { Player* tmpPlayer = g_game.getPlayerByGuid(corpse->getCorpseOwner()); if(createChildLoot(container, (*it), money, str, tmpPlayer)) { corpse->__internalAddThing(tmpItem); } else { delete container; } } else { bool LootCatch = false; Player* tmpPlayer = g_game.getPlayerByGuid(corpse->getCorpseOwner()); if(tmpPlayer) { if(tmpPlayer->statusAutoLoot() == "On") { LootCatch = tmpPlayer->checkAutoLoot(tmpItem->getID()); if(LootCatch) { if(tmpPlayer->isMoneyAutoLoot(tmpItem, money)) { continue; } g_game.internalPlayerAddItem(NULL, tmpPlayer, tmpItem); str << " " << tmpItem->getNameDescription() << ","; continue; } } } corpse->__internalAddThing(tmpItem); } } } corpse->__startDecaying(); uint32_t ownerId = corpse->getCorpseOwner(); if(!ownerId) return; Player* owner = g_game.getPlayerByGuid(ownerId); if(!owner) return; if(money != 0) { if(owner->statusAutoMoneyCollect() == "Bank"){ owner->balance += money; } else { g_game.addMoney(owner, money); } str << " " << money << "x gold coins."; } else { str << " nothing gold coins."; } 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->statusAutoLoot() == "On") { ss << "\nAutoLoot Colleted:" << str.str(); } 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()); } No mesmo arquivo localize a função a baixo chamada "createChildLoot": bool MonsterType::createChildLoot(Container* parent, const LootBlock& lootBlock) { LootItems::const_iterator it = lootBlock.childLoot.begin(); if(it == lootBlock.childLoot.end()) return true; ItemList items; for(; it != lootBlock.childLoot.end() && !parent->full(); ++it) { items = createLoot(*it); if(items.empty()) continue; for(ItemList::iterator iit = items.begin(); iit != items.end(); ++iit) { Item* tmpItem = *iit; if(Container* container = tmpItem->getContainer()) { if(createChildLoot(container, *it)) parent->__internalAddThing(tmpItem); else delete container; } else parent->__internalAddThing(tmpItem); } } return !parent->empty(); } E substitua por essa: bool MonsterType::createChildLoot(Container* parent, const LootBlock& lootBlock, uint32_t& money, std::stringstream& str, Player* player) { LootItems::const_iterator it = lootBlock.childLoot.begin(); if(it == lootBlock.childLoot.end()) return true; ItemList items; for(; it != lootBlock.childLoot.end() && !parent->full(); ++it) { items = createLoot(*it); if(items.empty()) continue; for(ItemList::iterator iit = items.begin(); iit != items.end(); ++iit) { Item* tmpItem = *iit; if(Container* container = tmpItem->getContainer()) { if(createChildLoot(container, *it, money, str, player)) parent->__internalAddThing(tmpItem); else delete container; } else { bool LootCatch = false; if(player && (player->statusAutoLoot() == "On")) { LootCatch = player->checkAutoLoot(tmpItem->getID()); } if(LootCatch) { if(player->isMoneyAutoLoot(tmpItem, money)) { continue; } g_game.internalPlayerAddItem(NULL, player, tmpItem); str << " " << tmpItem->getNameDescription() << ","; continue; } parent->__internalAddThing(tmpItem); } } } return !parent->empty(); } Agora no arquivo "monsters.h" altera apenas uma linha: Encontre: bool createChildLoot(Container* parent, const LootBlock& lootBlock); e troque por: bool createChildLoot(Container* parent, const LootBlock& lootBlock, uint32_t& money, std::stringstream& str, Player* player); Agora no arquivo "player.h" encontre nas funções public: void learnInstantSpell(const std::string& name); void unlearnInstantSpell(const std::string& name); bool hasLearnedInstantSpell(const std::string& name) const; E adicione abaixo: //Autoloot by: Naze std::list<uint16_t> getAutoLoot() { return AutoLoot; } void clearAutoLoot() { AutoLoot.clear(); } void addAutoLoot(uint16_t id); void removeAutoLoot(uint16_t id); bool limitAutoLoot(); bool checkAutoLoot(uint16_t id); bool isMoneyAutoLoot(Item* item, uint32_t& count); std::string statusAutoLoot() { return (autoLootStatus ? "On" : "Off"); } void updateStatusAutoLoot(bool status){ autoLootStatus = status; } std::string statusAutoMoneyCollect() { return (autoMoneyCollect ? "Bank" : "Bag"); } void updateMoneyCollect(bool status) { autoMoneyCollect = status; } Localize no mesmo arquivo as declarações private: private: bool is_spectating; bool talkState[13]; bool inventoryAbilities[SLOT_LAST]; bool pzLocked; e adicione 3 variáveis: private: bool autoLootStatus; //autoloot by naze bool autoMoneyCollect; //autoloot by naze std::list<uint16_t> AutoLoot; //autoloot by naze bool is_spectating; bool talkState[13]; bool inventoryAbilities[SLOT_LAST]; bool pzLocked; Agora no arquivo "player.cpp" localize no começo a função: Player::Player(const std::string& _name, ProtocolGame* p): Creature(), transferContainer(ITEM_LOCKER), name(_name), nameDescription(_name), client(p) { if(client) client->setPlayer(this); pzLocked = isConnecting = addAttackSkillPoint = requestedOutfit = false; saving = true; lastAttackBlockType = BLOCK_NONE; e adicione: Player::Player(const std::string& _name, ProtocolGame* p): Creature(), transferContainer(ITEM_LOCKER), name(_name), nameDescription(_name), client(p) { if(client) client->setPlayer(this); pzLocked = isConnecting = addAttackSkillPoint = requestedOutfit = false; saving = true; autoLootStatus = true; //autoloot by naze autoMoneyCollect = true; //autoloot by naze lastAttackBlockType = BLOCK_NONE; Ainda em "player.cpp" vá até as ultimas função: void Player::sendCritical() const { if(g_config.getBool(ConfigManager::DISPLAY_CRITICAL_HIT)) g_game.addAnimatedText(getPosition(), COLOR_DARKRED, "CRITICAL!"); } void Player::setPlayerExtraAttackSpeed(uint32_t speed) { extraAttackSpeed = speed; } E adicione abaixo: void Player::addAutoLoot(uint16_t id) { if(checkAutoLoot(id)) { return; } AutoLoot.push_back(id); } /*Parte do autoloot remove que foi arrumado*/ void Player::removeAutoLoot(uint16_t id) { if(!checkAutoLoot(id)) return; for(std::list<uint16_t>::iterator it = AutoLoot.begin(); it != AutoLoot.end(); ++it) { if((*it) == id) { AutoLoot.erase(it); break; } } } bool Player::limitAutoLoot() { std::list<uint16_t> list = getAutoLoot(); if((uint16_t)list.size() >= g_config.getNumber(ConfigManager::AUTOLOOT_MAXITEM)) { return true; } return false; } bool Player::checkAutoLoot(uint16_t id) { if(Item::items[id].isContainer()) { return true; } std::string msg = g_config.getString(ConfigManager::AUTOLOOT_BLOCKIDS); StringVec strVector = explodeString(msg, ";"); for(StringVec::iterator it = strVector.begin(); it != strVector.end(); ++it) { if(atoi((*it).c_str()) == id) { return true; } } for(std::list<uint16_t>::iterator it = AutoLoot.begin(); it != AutoLoot.end(); ++it) { if((*it) == id) { return true; } } return false; } bool Player::isMoneyAutoLoot(Item* item, uint32_t& count) { bool isMoney = false; std::string msg = g_config.getString(ConfigManager::AUTOLOOT_MONEYIDS); StringVec strVector = explodeString(msg, ";"); for(StringVec::iterator it = strVector.begin(); it != strVector.end(); ++it) { if(item->getID() == atoi((*it).c_str())) { isMoney = true; break; } } if(!isMoney) { return false; } count += item->getWorth(); return true; } Agora quase finalizando no arquivo "talkactions.h" localize: static TalkFunction diagnostics; static TalkFunction addSkill; static TalkFunction ghost; static TalkFunction software; E adicione: static TalkFunction diagnostics; static TalkFunction addSkill; static TalkFunction autoLoot; //autoloot by naze static TalkFunction ghost; static TalkFunction software; Encontre no arquivo "talkactions.cpp" : else if(m_functionName == "diagnostics") m_function = diagnostics; else if(m_functionName == "addskill") m_function = addSkill; else if(m_functionName == "ghost") m_function = ghost; else if(m_functionName == "software") m_function = software; E Adicione: else if(m_functionName == "diagnostics") m_function = diagnostics; else if(m_functionName == "addskill") m_function = addSkill; else if(m_functionName == "autoloot") //autoloot by naze m_function = autoLoot; else if(m_functionName == "ghost") m_function = ghost; else if(m_functionName == "software") m_function = software; Ainda em "talkactions.cpp" encontre o começo de ghost: bool TalkAction::ghost(Creature* creature, const std::string&, const std::string&) { Player* player = creature->getPlayer(); if(!player) return false; E adicione a cima a seguinte função: bool TalkAction::autoLoot(Creature* creature, const std::string&, const std::string& param) { Player* player = creature->getPlayer(); if(!player) return false; StringVec params = explodeString(param, ","); std::stringstream info; if(params[0] == "on" or params[0] == "off") { player->updateStatusAutoLoot((params[0] == "on" ? true : false)); info << "Autoloot-> Status: " << (player->statusAutoLoot()) << "."; player->sendTextMessage(MSG_STATUS_CONSOLE_BLUE, info.str()); return true; } if(params[0] == "clear" or params[0] == "clean") { player->clearAutoLoot(); info << "Autoloot-> Todos itens removidos."; player->sendTextMessage(MSG_STATUS_CONSOLE_BLUE, info.str()); return true; } if(params[0] == "list" or params[0] == "lista") { std::list<uint16_t> list = player->getAutoLoot(); std::list<uint16_t>::iterator it = list.begin(); std::string msg = g_config.getString(ConfigManager::AUTOLOOT_MONEYIDS); StringVec strVector = explodeString(msg, ";"); for(StringVec::iterator itt = strVector.begin(); itt != strVector.end(); ++itt) { ++it; } uint16_t i = 1; for(; it != list.end(); ++it) { info << i << ": " << Item::items[(*it)].name << std::endl; ++i; } player->sendFYIBox((info.str() == "" ? "Nada Adicionado." : info.str())); return true; } if(params.size() <= 1) { info << "_____Perfect AutoLoot System_____\nAutoLoot Status: " << player->statusAutoLoot() << "\nAutoMoney Mode: " << player->statusAutoMoneyCollect() << "\n\nComandos:\n!autoloot on/off\n!autoloot money, bank/bag\n!autoloot add, item name, item name, item name...\n!autoloot remove, item name, item name, item name...\n!autoloot list\n!autoloot clear\n\n\n (Sistema livre de bugs e gratuito no TibiaKing!)"; player->sendFYIBox(info.str()); return true; } if(params[0] == "money") { for(StringVec::iterator it = params.begin(); it != params.end(); ++it) { if((*it) == "money") { continue; } char param[150]; sprintf(param, "%s", (*it).c_str()); int len = strlen(param); for (int i = 0, pos = 0; i < len; i++, pos++) { if (param[0] == ' '){ pos++; } param[i] = param[pos]; } if((strcmp(param, "bank") == 0) or (strcmp(param, "bag") == 0)) { player->updateMoneyCollect((strcmp(param, "bank") == 0) ? true : false); info << "AutoMoney-> Collect Mode: " << (player->statusAutoMoneyCollect()) << "."; player->sendTextMessage(MSG_STATUS_CONSOLE_BLUE, info.str()); return true; } } } if(params[0] == "add") { std::stringstream add, err; uint8_t addCount = 0, errCount = 0; std::stringstream ss; for(StringVec::iterator it = params.begin(); it != params.end(); ++it) { if((*it) == "add") { continue; } char name[150]; sprintf(name, "%s", (*it).c_str()); int len = strlen(name); for (int i = 0, pos = 0; i < len; i++, pos++) { if (name[0] == ' '){ pos++; } name[i] = name[pos]; } int32_t itemId = Item::items.getItemIdByName(name); if(!player->checkAutoLoot(itemId)) { if(itemId > 0) { std::string str = addCount > 0 ? ", " : ""; ++addCount; add << str << name; player->addAutoLoot(itemId); continue; } } std::string str = errCount > 0 ? ", " : ""; ++errCount; err << str << name; } ss << "AutoLoot-> Adicionados: " << ((add.str() == "") ? "Nenhum" : add.str()) << ". Erros: " << ((err.str() == "") ? "Nenhum" : err.str()) << "."; player->sendTextMessage(MSG_STATUS_CONSOLE_RED, ss.str()); return true; } if(params[0] == "remove") { std::stringstream remove, err; uint8_t removeCount = 0, errCount = 0; std::stringstream ss; for(StringVec::iterator it = params.begin(); it != params.end(); ++it) { if((*it) == "remove") { continue; } char name[150]; sprintf(name, "%s", (*it).c_str()); int len = strlen(name); for (int i = 0, pos = 0; i < len; i++, pos++) { if (name[0] == ' '){ pos++; } name[i] = name[pos]; } int32_t itemId = Item::items.getItemIdByName(name); if(player->checkAutoLoot(itemId)) { if(itemId > 0) { std::string str = removeCount > 0 ? ", " : ""; ++removeCount; remove << str << name; player->removeAutoLoot(itemId); continue; } } std::string str = errCount > 0 ? ", " : ""; ++errCount; err << str << name; } ss << "AutoLoot-> Removidos: " << ((remove.str() == "") ? "Nenhum" : remove.str()) << ". Erros: " << ((err.str() == "") ? "Nenhum" : err.str()) << "."; player->sendTextMessage(MSG_STATUS_CONSOLE_ORANGE, ss.str()); return true; } return true; } Com isso toda parte na source está instalada, agora vá até seu config.lua e adicione onde achar melhor as seguintes linhas: AutoLoot_BlockIDs = "" -- adicione ids separado por ; ex: "1111;2222;3333" AutoLoot_MoneyIDs = "2148;2152;2160" -- adicione os ids dos itens moeda, caso seja os 3 normais pode retirar essa linha AutoLoot_MaxItem = 100 -- quantidade de itens maximo na lista Agora para finalizar abra o data/talkactions/talkactions.xml e adicione a seguinte tag: <talkaction words="/autoloot;!autoloot" event="function" value="autoloot"/> E execute a seguinte query em seu banco de dados: CREATE TABLE player_autoloot ( id int NOT NULL AUTO_INCREMENT, player_id int NOT NULL, autoloot_list blob, PRIMARY KEY (id) ); caso alguém ja utilize esse autoloot e esteja com o problema de remover items do autoloot só ir em player.cpp e trocar isso: void Player::removeAutoLoot(uint16_t id) { if(checkAutoLoot(id)) { return; } AutoLoot.remove(id); } por isso: void Player::removeAutoLoot(uint16_t id) { if(!checkAutoLoot(id)) return; for(std::list<uint16_t>::iterator it = AutoLoot.begin(); it != AutoLoot.end(); ++it) { if((*it) == id) { AutoLoot.erase(it); break; } } } todos os créditos ao Naze, não sei se alguém mais fez esse código, mas como peguei do link citado acima que é post dele deixo aqui o autoloot 100% funcional direto nas sources esse nao pega em tfs ne?
Postado Novembro 10, 2022 2 anos Autor Em 10/11/2022 em 11:05, mullino disse: esse nao pega em tfs ne? esse não me engano funciona em tfs 0.x e OTX 2.x, em TFS 1.x, creio que eh usado o sistema de quick loot veja aqui. creio que esse autoloot funciona em qualquer TFS tbm, só testar, eh o mesmo do naze.
Postado Novembro 10, 2022 2 anos Em 10/11/2022 em 12:44, FeeTads disse: esse não me engano funciona em tfs 0.x e OTX 2.x, em TFS 1.x, creio que eh usado o sistema de quick loot veja aqui. creio que esse autoloot funciona em qualquer TFS tbm, só testar, eh o mesmo do naze. The TFS Version: (1.2.X.SERIES - a minha é essa
Postado Novembro 10, 2022 2 anos Autor Em 10/11/2022 em 12:45, mullino disse: The TFS Version: (1.2.X.SERIES - a minha é essa acho que funciona sim, tenta procurar as funções, ve se são parecidas, n custa tentar kkkkkk, mas creio que funciona sim.
Participe da conversa
Você pode postar agora e se cadastrar mais tarde. Se você tem uma conta, faça o login para postar com sua conta.