Ir para conteúdo

Featured Replies

Postado
  • Este é um post popular.

Depois de milhões de anos sem programar porcaria nenhuma... Eu desenvolvi este sistema como um método de estudo. (C++)

Este sistema foi inspirado no Auto Loot System por @psychonaut. (OTland)
Criei o mesmo na versão mais recente do tfs. 

 

Auto Loot System for TFS 1.3

autoloot.png.a313e27f933b86aa8352830a89f1f3ec.png

 

Como funciona?
Simples, quando você mata um monstro e abre o corpo (você precisa clicar no corpo), os itens vão para o seu personagem.

autoloot.gif.fc83cbef064142d02832b8c8e78a5f85.gif

 

Instalando

em actions.cpp, encontre:

if (corpseOwner != 0 && !player->canOpenCorpse(corpseOwner)) {
    return RETURNVALUE_YOUARENOTTHEOWNER;
}

e mude isso para:
 

if (corpseOwner != 0 && !player->canOpenCorpse(corpseOwner)) {
	return RETURNVALUE_YOUARENOTTHEOWNER;
} else {
	if (player->canOpenCorpse(corpseOwner) && player->autoLootList.size() != 0) {
		if (player->getCapacity() > 100 * 100) { //Minimum of Capacity for autoloot works. (100 CAP)
			for (Item* item : container->getItemList()) {
				if (player->getItemFromAutoLoot(item->getID())) {
					std::ostringstream msgAutoLoot;
					msgAutoLoot << "You looted a " << item->getItemCount() << "x " << item->getName() << ".";
					g_game.internalMoveItem(container, player, CONST_SLOT_WHEREEVER, item, item->getItemCount(), nullptr);
					player->sendTextMessage(MESSAGE_INFO_DESCR, msgAutoLoot.str());
				}
			}
		} else {
			player->sendTextMessage(MESSAGE_INFO_DESCR, "Sorry, you don't have enough capacity to use auto loot, so it has been disabled. (100+ capacity is required)");
		}
	}
}

em player.h, abaixo de:

std::unordered_set<uint32_t> VIPList;

adicione isso:

std::set<uint32_t> autoLootList;

ainda em player.h encontre:

bool hasLearnedInstantSpell(const std::string& spellName) const;

adicione em baixo:

void addItemToAutoLoot(uint16_t itemId);
void removeItemFromAutoLoot(uint16_t itemId);
bool getItemFromAutoLoot(uint16_t itemId);

em player.cpp no final do arquivo, adicione:

void Player::addItemToAutoLoot(uint16_t itemId)
{
    autoLootList.insert(itemId);
}

void Player::removeItemFromAutoLoot(uint16_t itemId)
{
    autoLootList.erase(itemId);
}

bool Player::getItemFromAutoLoot(const uint16_t itemId)
{
    return autoLootList.find(itemId) != autoLootList.end();
}

em luascript.cpp encontre:

registerMethod("Player", "getFightMode", LuaScriptInterface::luaPlayerGetFightMode);

e adicione em baixo:

registerMethod("Player", "addItemToAutoLoot", LuaScriptInterface::luaPlayerAddItemToAutoLoot);
registerMethod("Player", "removeItemFromAutoLoot", LuaScriptInterface::luaPlayerRemoveItemFromAutoLoot);
registerMethod("Player", "getItemFromAutoLoot", LuaScriptInterface::luaPlayerGetItemFromAutoLoot);
registerMethod("Player", "getAutoLootList", LuaScriptInterface::luaPlayerGetAutoLootList);

ainda em luascript.cpp encontre essa função:

int LuaScriptInterface::luaPlayerGetFightMode(lua_State* L)
{
    // player:getFightMode()
    Player* player = getUserdata<Player>(L, 1);
    if (player) {
        lua_pushnumber(L, player->fightMode);
    } else {
        lua_pushnil(L);
    }
    return 1;
}

 

abaixo dela, adicione:

int LuaScriptInterface::luaPlayerAddItemToAutoLoot(lua_State* L)
{
    // player:addItemToAutoLoot(itemId)
    Player* player = getUserdata<Player>(L, 1);
    if (!player) {
        lua_pushnil(L);
        return 1;
    }

    uint16_t itemId;
    if (isNumber(L, 2)) {
        itemId = getNumber<uint16_t>(L, 2);
    } else {
        itemId = Item::items.getItemIdByName(getString(L, 2));
        if (itemId == 0) {
            lua_pushnil(L);
            return 1;
        }
    }
    player->addItemToAutoLoot(itemId);
    pushBoolean(L, true);
    return 1;
}

int LuaScriptInterface::luaPlayerRemoveItemFromAutoLoot(lua_State* L)
{
    // player:removeItemFromAutoLoot(itemId)
    Player* player = getUserdata<Player>(L, 1);
    if (!player) {
        lua_pushnil(L);
        return 1;
    }

    uint16_t itemId;
    if (isNumber(L, 2)) {
        itemId = getNumber<uint16_t>(L, 2);
    } else {
        itemId = Item::items.getItemIdByName(getString(L, 2));
        if (itemId == 0) {
            lua_pushnil(L);
            return 1;
        }
    }

    player->removeItemFromAutoLoot(itemId);
    pushBoolean(L, true);

    return 1;
}

int LuaScriptInterface::luaPlayerGetItemFromAutoLoot(lua_State* L)
{
    // player:getItemFromAutoLoot(itemId)
    Player* player = getUserdata<Player>(L, 1);
    if (!player) {
        lua_pushnil(L);
        return 1;
    }

    uint16_t itemId;
    if (isNumber(L, 2)) {
        itemId = getNumber<uint16_t>(L, 2);
    } else {
        itemId = Item::items.getItemIdByName(getString(L, 2));
        if (itemId == 0) {
            lua_pushnil(L);
            return 1;
        }
    }

    if (player->getItemFromAutoLoot(itemId)) {
        pushBoolean(L, true);
    } else {
        pushBoolean(L, false);
    }

    return 1;
}

int LuaScriptInterface::luaPlayerGetAutoLootList(lua_State* L)
{
    // player:getAutoLootList()
    Player* player = getUserdata<Player>(L, 1);

    if (player) {
        std::set<uint32_t> value = player->autoLootList;
   
        if (value.size() == 0) {
          lua_pushnil(L);
          return 1;
        }

        int index = 0;
        lua_createtable(L, value.size(), 0);
        for(auto i : value) {
            lua_pushnumber(L, i);
            lua_rawseti(L, -2, ++index);
        }
   
    } else {
        lua_pushnil(L);
    }

    return 1;
}

 

em luascript.h encontre:

static int luaPlayerGetFightMode(lua_State* L);

 

adicione a baixo:

static int luaPlayerAddItemToAutoLoot(lua_State* L);
static int luaPlayerRemoveItemFromAutoLoot(lua_State* L);
static int luaPlayerGetItemFromAutoLoot(lua_State* L);
static int luaPlayerGetAutoLootList(lua_State* L);

 

em iologindata.cpp encontre:

    //load storage map
    query.str(std::string());
    query << "SELECT `key`, `value` FROM `player_storage` WHERE `player_id` = " << player->getGUID();
    if ((result = db.storeQuery(query.str()))) {
        do {
            player->addStorageValue(result->getNumber<uint32_t>("key"), result->getNumber<int32_t>("value"), true);
        } while (result->next());
    }

 

e adicione em baixo:

    query.str(std::string());
    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->getStream("autoloot_list", lootlistSize);
        PropStream propStreamList;
        propStreamList.init(autolootlist, lootlistSize);

        int16_t value;
        int16_t item = propStreamList.read<int16_t>(value);
        while (item) {
               player->addItemToAutoLoot(value);
            item = propStreamList.read<int16_t>(value);
        }
    }

 

acima de:

//save inbox items

adicione:

	query.str(std::string());
    query << "DELETE FROM `player_autoloot` WHERE `player_id` = " << player->getGUID();
    if (!db.executeQuery(query.str())) {
        return false;
    }

    PropWriteStream propWriteStreamAutoLoot;

    for (auto i : player->autoLootList) {
        propWriteStreamAutoLoot.write<uint16_t>(i);
    }

    size_t lootlistSize;
    const char* autolootlist = propWriteStreamAutoLoot.getStream(lootlistSize);

    query.str(std::string());

    DBInsert autolootQuery("INSERT INTO `player_autoloot` (`player_id`, `autoloot_list`) VALUES ");

    query << player->getGUID() << ',' << db.escapeBlob(autolootlist, lootlistSize);
    if (!autolootQuery.addRow(query)) {
        return false;
    }

    if (!autolootQuery.execute()) {
        return false;
    }

 

em sua database, execute esta query

CREATE TABLE player_autoloot (
    id int NOT NULL AUTO_INCREMENT,
    player_id int NOT NULL,
    autoloot_list blob,
    PRIMARY KEY (id)
);

 

agora vá em data/scripts/talkactions e crie esse arquivo LUA

 

autoloot.lua

local talk = TalkAction("!autoloot")

function talk.onSay(player, words, param)
	local i = player:getAutoLootList()
	local cache = "Check your loot list: "
	local split = param:split(",")
	local action = split[1]

	if param == "list" then
		if i then
			for _, item in ipairs(i) do
				cache = cache .. (ItemType(item)):getName() .. ", "
			end
		else
			player:sendTextMessage(MESSAGE_INFO_DESCR, "Your list is empty! Add some item and try again.")
			return false
		end

		player:sendTextMessage(MESSAGE_INFO_DESCR, cache:sub(1, -3))
		return false
	end

   if action == "add" then
        local item = split[2]:gsub("%s+", "", 1)
        local itemType = ItemType(item)
	    if itemType:getId() == 0 then
	        itemType = ItemType(tonumber(item))
	        if itemType:getName() == '' then
	            player:sendCancelMessage("There is no item with that id or name.")
	            return false
	        end
	    end

		if player:getItemFromAutoLoot(itemType:getId()) then
        	player:sendCancelMessage("You're already autolooting this item.")
        	return false
    	end

        player:addItemToAutoLoot(itemType:getId())
        player:sendTextMessage(MESSAGE_INFO_DESCR, "You're now auto looting " .. itemType:getName())
        return false
    elseif action == "remove" then
        local item = split[2]:gsub("%s+", "", 1)
        local itemType = ItemType(item)
	    if itemType:getId() == 0 then
	        itemType = ItemType(tonumber(item))
	        if itemType:getName() == '' then
	            player:sendCancelMessage("There is no item with that id or name.")
	            return false
	        end
	    end

	    if player:getItemFromAutoLoot(itemType:getId()) then
	        player:removeItemFromAutoLoot(itemType:getId())
	        player:sendTextMessage(MESSAGE_INFO_DESCR, "You removed the " .. itemType:getName() .. " from your loot list.")
	    else
	        player:sendCancelMessage("This item does not exist in your loot list.")
	    end
	    return false       	
    end


	player:sendTextMessage(MESSAGE_EVENT_ORANGE, "Auto Loot commands (items are automatically moved to your bp if you open monster corpse):"..'\n'.."!addloot add, nameItem - add item to auto loot by name"..'\n'.."!autoloot remove, itemName - remove item from auto loot by name"..'\n'.."!autoloot list - list your current auto loot items")
	return false
end

talk:separator(" ")
talk:register()

 

 

É isso, espero que gostem do sisteminha =D

Se você encontrar algum bug, deixe-me saber.

Falta fazer:
Optimizar a mensagem de loot.

Adicionar ModalWindow.
 

Cheers~

 

commands.png

Editado por Pedriinz
update (veja o histórico de edições)

  • Respostas 30
  • Visualizações 10.8k
  • Created
  • Última resposta

Top Posters In This Topic

Most Popular Posts

  • Yo! Acabei de realizar algumas atualizações no código. As mudanças foram:   Junção de todos os scripts LUA em um só, resultando em um único comando para administrar o sistema de autoloot.

  • Tente usar o meu auto loot e me diga se o erro acontece, caso aconteça... veremos isso! Se você prefere utilizar o dele, então sugiro que procure o thread do sistema dele e peça ajuda lá! Outra opçã

  • @Pedriinz Você é um monstro! Pegou com o rewardboss aqui sem dar crash. Muito obrigado.   Rep+

Posted Images

Postado

Parabéns, seu tópico de conteúdo foi aprovado!
Muito obrigado pela sua contribuição, nós do Tibia King agradecemos.
Seu conteúdo com certeza ajudará à muitos outros, você recebeu +1 REP.

Spoiler

Congratulations, your content has been approved!
Thank you for your contribution, we of Tibia King we are grateful.
Your content will help many other users, you received +1 REP.

 

Postado

Muito bom, cara, para quem gosta do Autoloot dessa forma, vai ser de grande ajuda. As sugestões que iria dá, você já comentou no que "falta fazer", seria bacana tudo isso com modal e como você está utilizando revscript para o talkactions, tudo no mesmo script ficaria ótimo para quem apenas quer instalar no servidor.

Postado
  • Autor
5 minutos atrás, lordzetros disse:

Muito bom, cara, para quem gosta do Autoloot dessa forma, vai ser de grande ajuda. As sugestões que iria dá, você já comentou no que "falta fazer", seria bacana tudo isso com modal e como você está utilizando revscript para o talkactions, tudo no mesmo script ficaria ótimo para quem apenas quer instalar no servidor.

 

 

Fiz esse código ontem "rápido" focando em outras partes dele como estudo... mas ainda hoje eu faço a mudança dos arquivos talk.

E sobre o modal, talvez hoje também já saia algo... basta apenas que eu DURMA um pouco G_G

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.

Visitante
Responder

Quem Está Navegando 0

  • Nenhum usuário registrado visualizando esta página.

Estatísticas dos Fóruns

  • Tópicos 96.9k
  • Posts 519.6k

Informação Importante

Confirmação de Termo