• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Create random item on the map

darcioantonio

www.adventurerpg.com.br
Joined
Jul 30, 2013
Messages
165
Solutions
1
Reaction score
4
Location
Brasil
Twitch
darcio_
YouTube
UCEXCOEw_dYchojHNz
I've created this script to generate random items on the map, but it's currently placing them inside walls, on top of rivers, etc. Is there a possibility to limit the placement to areas where the player can walk?"

OTX 0.4 (OTX Server Version: (2.15))


Lua:
local config = {
    topoEsquerdo = {x = 93, y = 1035, z = 7},
    sulDireito = {x = 278, y = 1281, z = 7},
    itensCreate = {13785, 13786},
    itensQuant = 3000,
}

function isWalkable(cid, pos)
    local closest = getClosestFreeTile(cid, pos)
    return type(closest) == "table" and doComparePositions(closest, pos)
end

function isWithinArea(pos)
    return pos.x >= config.topoEsquerdo.x and pos.x <= config.sulDireito.x
        and pos.y >= config.topoEsquerdo.y and pos.y <= config.sulDireito.y
        and pos.z == config.topoEsquerdo.z
end

function getItemCountFromPosition(item, pos)
    local item_pos = {x = pos.x, y = pos.y, z = pos.z}
    local item_count = 0
    for i = 1, 255 do
        local check_pos = {x = item_pos.x, y = item_pos.y, z = item_pos.z, stackpos = i}
        if getThingFromPos(check_pos).itemid <= 0 then
            break
        elseif getThingFromPos(check_pos).itemid == item then
            if isItemStackable(getThingFromPos(check_pos).itemid) == true then
                item_count = item_count + getThingFromPos(check_pos).type
            else
                item_count = item_count + 1
            end
        end
    end
    return item_count
end

function onUse(cid, item, frompos, item2, topos)
    local createdItems = 0 -- Inicializar contador de itens criados

    while createdItems < config.itensQuant do
        local randomX = math.random(config.topoEsquerdo.x, config.sulDireito.x)
        local randomY = math.random(config.topoEsquerdo.y, config.sulDireito.y)
        local randomZ = config.topoEsquerdo.z -- Você pode ajustar isso se quiser um intervalo diferente de Z

        local randomPos = {x = randomX, y = randomY, z = randomZ}

        if isWithinArea(randomPos) and isWalkable(cid, randomPos) then
            local itemToCreate = config.itensCreate[math.random(1, #config.itensCreate)]
            if getItemCountFromPosition(itemToCreate, randomPos) == 0 then
                doCreateItem(itemToCreate, 1, randomPos)
                createdItems = createdItems + 1 -- Incrementar contador de itens criados
            end
        end
    end
end
 
You can check the properties

Lua:
function onUse(cid, item, frompos, item2, topos)
    local createdItems = 0 -- Inicializar contador de itens criados

    while createdItems < config.itensQuant do
        local randomX = math.random(config.topoEsquerdo.x, config.sulDireito.x)
        local randomY = math.random(config.topoEsquerdo.y, config.sulDireito.y)
        local randomZ = config.topoEsquerdo.z -- Você pode ajustar isso se quiser um intervalo diferente de Z

        local randomPos = {x = randomX, y = randomY, z = randomZ}

        local canAdd = Tile(randomPos) and not Tile(randomPos):hasProperty(CONST_PROP_IMMOVABLEBLOCKSOLID) or false
        if canAdd and  and isWithinArea(randomPos) and isWalkable(cid, randomPos) then
            local itemToCreate = config.itensCreate[math.random(1, #config.itensCreate)]
            if getItemCountFromPosition(itemToCreate, randomPos) == 0 then
                doCreateItem(itemToCreate, 1, randomPos)
                createdItems = createdItems + 1 -- Incrementar contador de itens criados
            end
        end
    end
end
 
I managed to do it this way, and the code is there for anyone who wants to use it!
Lua:
-- Configurações do script
local config = {
    topoEsquerdo = {x = 1471, y = 376, z = 7},
    sulDireito = {x = 1488, y = 387, z = 7},
    itensCreate = {13785, 13786},
    itensQuant = 1000,
}


-- Função para verificar se uma posição é caminhável
function isWalkable(pos, creature, proj, pz)
    if getTileThingByPos({x = pos.x, y = pos.y, z = pos.z, stackpos = 0}).itemid == 0 then return false end
    if getTopCreature(pos).uid > 0 and creature then return false end
    if getTileInfo(pos).protection and pz then return false, true end
    local n = not proj and 3 or 2
    for i = 0, 255 do
        pos.stackpos = i
        local tile = getTileThingByPos(pos)
        if tile.itemid ~= 0 and not isCreature(tile.uid) then
            if hasProperty(tile.uid, n) or hasProperty(tile.uid, 7) then
                return false
            end
        end
    end
    return true
end

-- Conta item no sqm
function getItemCountFromPosition(item, pos)
    local item_pos = {x = pos.x, y = pos.y, z = pos.z}
    local item_count = 0
    for i = 1, 255 do
        local check_pos = {x = item_pos.x, y = item_pos.y, z = item_pos.z, stackpos = i}
        if getThingFromPos(check_pos).itemid <= 0 then
            break
        elseif getThingFromPos(check_pos).itemid == item then
            if isItemStackable(getThingFromPos(check_pos).itemid) == true then
                item_count = item_count + getThingFromPos(check_pos).type
            else
                item_count = item_count + 1
            end
        end
    end
    return item_count
end

-- Função para criar itens em posições caminháveis, evitando sobreposição de itens diferentes
function createItemsInWalkablePositions()
    local createdItems = 0
    local maxAttempts = 100 -- Limite de tentativas para encontrar uma posição vazia

    while createdItems < config.itensQuant do
        local randomX = math.random(config.topoEsquerdo.x, config.sulDireito.x)
        local randomY = math.random(config.topoEsquerdo.y, config.sulDireito.y)
        local randomZ = config.topoEsquerdo.z

        local randomPos = {x = randomX, y = randomY, z = randomZ}
        local isPositionWalkable, isPositionInProtectionZone = isWalkable(randomPos, true, false, true)
        local topCreature = getTopCreature(randomPos)
        local tileThing = getTileThingByPos(randomPos)

        if isPositionWalkable and topCreature.uid == 0 and not isPositionInProtectionZone then
            -- Verifica se já existe algum item do array na posição
            local isItemAlreadyPresent = isItemPresentInPosition(config.itensCreate, randomPos)

            -- Se nenhum dos itens estiver presente na posição, cria um novo
            if not isItemAlreadyPresent then
                local itemToCreate = config.itensCreate[math.random(#config.itensCreate)] -- Escolhe um item aleatório do array
                doCreateItem(itemToCreate, 1, randomPos)
                createdItems = createdItems + 1
            end
        else
            -- Se a posição não for caminhável ou estiver em uma zona de proteção, contabilize uma tentativa
            maxAttempts = maxAttempts - 1
        end

        -- Se atingir o limite de tentativas, pare o loop para evitar travamentos
        if maxAttempts <= 0 then
            print("Limite de tentativas atingido. Não foi possível criar todos os itens.")
            break
        end
    end
end


-- Função para verificar se um determinado item está presente em uma posição
function isItemPresentInPosition(itemIDs, pos)
    for _, itemID in ipairs(itemIDs) do
        local itemCount = getItemCountFromPosition(itemID, pos)
        if itemCount > 0 then
            return true -- Retorna true se o item estiver presente em qualquer uma das posições
        end
    end
    return false -- Retorna false se o item não estiver presente em nenhuma das posições
end

-- Função chamada quando o item é usado
function onUse(cid, item, frompos, itemEx, topos)
    createItemsInWalkablePositions()
end
Post automatically merged:

I made this modification so if you want to use it in several areas and floors, just add it to the config.

Lua:
-- Configurações do script
local config = {
    areas = {
        {
            topLeft = {x = 1431, y = 342, z = 7},
            bottomRight = {x = 1435, y = 346, z = 7},
            itemCount = 3
        },
        {
            topLeft = {x = 1448, y = 345, z = 6},
            bottomRight = {x = 1454, y = 351, z = 6},
            itemCount = 10
        },
        {
            topLeft = {x = 1433, y = 351, z = 5},
            bottomRight = {x = 1439, y = 357, z = 5},
            itemCount = 5
        }
    },
    itensCreate = {13785, 13786, 13882, 13883, 13885, 13886}
}

-- Função para verificar se uma posição é caminhável
function isWalkable(pos, creature, proj, pz)
    if getTileThingByPos({x = pos.x, y = pos.y, z = pos.z, stackpos = 0}).itemid == 0 then return false end
    if getTopCreature(pos).uid > 0 and creature then return false end
    if getTileInfo(pos).protection and pz then return false, true end
    local n = not proj and 3 or 2
    for i = 0, 255 do
        pos.stackpos = i
        local tile = getTileThingByPos(pos)
        if tile.itemid ~= 0 and not isCreature(tile.uid) then
            if hasProperty(tile.uid, n) or hasProperty(tile.uid, 7) then
                return false
            end
        end
    end
    return true
end

-- Conta item no sqm
function getItemCountFromPosition(item, pos)
    local item_pos = {x = pos.x, y = pos.y, z = pos.z}
    local item_count = 0
    for i = 1, 255 do
        local check_pos = {x = item_pos.x, y = item_pos.y, z = item_pos.z, stackpos = i}
        if getThingFromPos(check_pos).itemid <= 0 then
            break
        elseif getThingFromPos(check_pos).itemid == item then
            if isItemStackable(getThingFromPos(check_pos).itemid) == true then
                item_count = item_count + getThingFromPos(check_pos).type
            else
                item_count = item_count + 1
            end
        end
    end
    return item_count
end

-- Função para criar itens em posições caminháveis, evitando sobreposição de itens diferentes
function createItemsInWalkablePositions()
    local createdItems = 0
    local maxAttempts = 1000 -- Limite de tentativas para encontrar uma posição vazia

    while createdItems < getTotalItemsToCreate(config.areas) do
        local randomArea = config.areas[math.random(#config.areas)]
        local randomX = math.random(randomArea.topLeft.x, randomArea.bottomRight.x)
        local randomY = math.random(randomArea.topLeft.y, randomArea.bottomRight.y)
        local randomZ = randomArea.topLeft.z

        local randomPos = {x = randomX, y = randomY, z = randomZ}
        local isPositionWalkable, isPositionInProtectionZone = isWalkable(randomPos, true, false, true)
        local topCreature = getTopCreature(randomPos)

        if isPositionWalkable and topCreature.uid == 0 and not isPositionInProtectionZone then
            local isItemAlreadyPresent = isItemPresentInPosition(config.itensCreate, randomPos)
            if not isItemAlreadyPresent then
                local itemToCreate = config.itensCreate[math.random(#config.itensCreate)]
                doCreateItem(itemToCreate, 1, randomPos)
                createdItems = createdItems + 1
            end
        else
            maxAttempts = maxAttempts - 1
        end

        if maxAttempts <= 0 then
            print("Limite de tentativas atingido. Não foi possível criar todos os itens.")
            break
        end
    end
end

-- Função para verificar se um determinado item está presente em uma posição
function isItemPresentInPosition(itemIDs, pos)
    for _, itemID in ipairs(itemIDs) do
        local itemCount = getItemCountFromPosition(itemID, pos)
        if itemCount > 0 then
            return true -- Retorna true se o item estiver presente em qualquer uma das posições
        end
    end
    return false -- Retorna false se o item não estiver presente em nenhuma das posições
end

-- Função auxiliar para calcular o total de itens a serem criados em todas as áreas
function getTotalItemsToCreate(areas)
    local totalItems = 0
    for _, area in ipairs(areas) do
        totalItems = totalItems + area.itemCount
    end
    return totalItems
end

-- Função chamada quando o item é usado
function onUse(cid, item, frompos, itemEx, topos)
    createItemsInWalkablePositions()
end
 
Last edited:
Back
Top