Ir para conteúdo

Featured Replies

Postado

Estou tentando criar um quickloot para meu servidor, onde o jogador clicar no corpo da criatura, todos os itens são puxados para a bag. Consegui parcialmente, os itens vão para bag, mas tenho que ficar clicando no corpo da criatura até todos os itens serem coletados, como faço para coletar todos de uma só vez? 

 

function onUse(cid, item, fromPosition, itemEx, toPosition)
    if getItemAttribute(item.uid, "corpseowner") ~= getPlayerGUID(cid) then
        return doPlayerSendCancel(cid, "Esse corpo foi morto por outro jogador")
    end
    
    local items = {}
    for i = 1, getContainerSize(item.uid) do
        local it = getContainerItem(item.uid, i - 1)
        if it.uid > 0 then
            table.insert(items, {it.itemid, it.type})
            doRemoveItem(it.uid)
        end
    end
    
    if #items > 0 then
        for k = 1, #items do
            local playerItem = getPlayerItemById(cid, true, items[k][1])
            if playerItem.uid > 0 then
                local totalType = playerItem.type + items[k][2]
                if totalType > 100 then
                    doPlayerAddItem(cid, items[k][1], totalType - 100)
                    doTransformItem(playerItem.uid, items[k][1], 100)
                else
                    doTransformItem(playerItem.uid, items[k][1], totalType)
                end
            else
                doPlayerAddItem(cid, items[k][1], items[k][2])
            end
        end
        return true
    end
    
    return false
end

 

  • 1 year later...
Postado

O problema ocorre porque você remove os itens enquanto ainda está iterando o container. Em servidores OT (especialmente base TFS 0.x / 8.60), quando você remove um item de um container, os índices mudam. Então o loop pula itens e você precisa clicar novamente.

Por que acontece

Exemplo:

Container:

slot 0: gold
slot 1: sword
slot 2: shield

Loop:

  1. pega slot 0 → remove gold

  2. container vira:

slot 0: sword
slot 1: shield
  1. loop vai para i = 2 → shield
    ➡️ sword foi pulada

Por isso você precisa clicar várias vezes.


Solução correta

Sempre remova do último slot para o primeiro.

Assim os índices não mudam para os itens que ainda não foram processados.

Script corrigido

function onUse(cid, item, fromPosition, itemEx, toPosition)

    if getItemAttribute(item.uid, "corpseowner") ~= getPlayerGUID(cid) then
        return doPlayerSendCancel(cid, "Esse corpo foi morto por outro jogador")
    end

    local items = {}
    local size = getContainerSize(item.uid)

    -- percorre de trás para frente
    for i = size - 1, 0, -1 do
        local it = getContainerItem(item.uid, i)
        if it.uid > 0 then
            table.insert(items, {it.itemid, it.type})
            doRemoveItem(it.uid)
        end
    end

    if #items > 0 then
        for k = 1, #items do
            local playerItem = getPlayerItemById(cid, true, items[k][1])

            if playerItem.uid > 0 then
                local totalType = playerItem.type + items[k][2]

                if totalType > 100 then
                    doPlayerAddItem(cid, items[k][1], totalType - 100)
                    doTransformItem(playerItem.uid, items[k][1], 100)
                else
                    doTransformItem(playerItem.uid, items[k][1], totalType)
                end
            else
                doPlayerAddItem(cid, items[k][1], items[k][2])
            end
        end
    end

    return true
end

Melhorias recomendadas (muito importantes)

Para OTServer 8.60 eu recomendo também:

1️⃣ evitar limite manual de stack

O servidor já controla stack automaticamente.

Você pode simplificar MUITO:

doPlayerAddItem(cid, items[k][1], items[k][2])

Sem precisar de:

  • getPlayerItemById

  • doTransformItem

  • limite 100


2️⃣ Versão muito mais limpa

Esta versão já funciona como quick loot real:

function onUse(cid, item, fromPosition, itemEx, toPosition)

    if getItemAttribute(item.uid, "corpseowner") ~= getPlayerGUID(cid) then
        return doPlayerSendCancel(cid, "Esse corpo foi morto por outro jogador")
    end

    local size = getContainerSize(item.uid)

    for i = size - 1, 0, -1 do
        local it = getContainerItem(item.uid, i)
        if it.uid > 0 then
            doPlayerAddItem(cid, it.itemid, it.type)
            doRemoveItem(it.uid)
        end
    end

    return true
end

Resultado

Clicou no corpo 1 vez
Todos os itens vão para a bag
Nenhum item é pulado
Código muito mais simples

Fonte: ChatGPT

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.1k
  • Posts 512.5k

Informação Importante

Confirmação de Termo