Ir para conteúdo

Instanciando Mapas v1.0


Skulls

Posts Recomendados

Fala galera, tudo bem?

Semana passada abri uma dúvida perguntando se alguém conhecia algum jeito de players compartilharem o mesmo espaço no mapa sem interagirem entre si, como se fossem duas dimensões separadas. Ninguém soube me dar uma solução que fizesse exatamente isso, porém, o Danihcv me deu uma luz sugerindo que eu fizesse algo próximo de um instanciador de mapa. Ou seja, uma forma de clonar automaticamente um pedaço do mapa desejado sem ter que criar mil vezes no map editor.

Ainda estou trabalhando na automação do mesmo - pretendo fazer um sistema, sem ser talkaction, que sempre que for necessário ele instancia uma novo espaço para aquele mesmo mapa. Esta é uma primeira versão, feita em talkaction pois achei melhor de trabalhar num primeiro momento e testar todas as funções que eu queria adicionar, ela faz basicamente cópia de uma área do mapa. Pro projeto que eu pensei para esse sistema é suficiente que ele suporte somente mapas do mesmo tamanho e, portanto, foquei em atender esse requisito. Ainda sim, é possível trabalhar com mapas de tamanhos diferentes, desde que eles fiquem em linhas diferentes.

Vamos lá

 

Primeiramente, eu fiz um banco de funções que foram utilizadas ou serão úteis mais para frente.

Em lib, crie um arquivo chamado cloneMap.lua e adicione o código abaixo:

 

 

--Número de tiles por linha 2*side+1

function getNextCloneTile(emptySpaceBeginPos, side, i)
    local d = 2*side + 1
    local y = i%d
    local x = math.floor(i/d)
    return {x = emptySpaceBeginPos.x + x, y = emptySpaceBeginPos.y + y, z = emptySpaceBeginPos.z}
end

function deleteTile(pos)
    doCleanTile(pos,true)
    local tmp = getThingFromPos(pos)
    if(tmp.uid ~= 0) then
        if(isCreature(tmp.uid)) then
            return doRemoveCreature(tmp.uid)
        else
            return doRemoveItem(tmp.uid, math.min(math.max(1, tmp.type), 1))
        end
    end
end

function clearArea(center, side)
    for k, tile in pairs(getArea(center, side, side)) do
        if(getTileThingByPos(tile).itemid ~= 0) then
            deleteTile(tile)
        end
    end
end

function cloneMap(center, side, emptySpaceBeginPos)
    for k, tile in pairs(getArea(center, side, side)) do
        for i=0, 1 do
            tile.stackpos = i
            local tmp = getThingFromPos(tile)
            if tmp.uid ~= 0 then
                local nextTile = getNextCloneTile(emptySpaceBeginPos, side, k-1)
                if isCreature(tmp.uid) == true then
                    local creature = getCreatureName(tmp.uid)
                    doCreateMonster(creature, nextTile)
                else
                    local item_id = tmp.itemid
                    doCreateItem(tmp.itemid, 1, nextTile)
                end
            end
        end
    end
	return true
end

function cloneMultiDimensionalMaps(center, side, emptySpaceBeginPos, dim)
    for i = 0, dim do
        cloneMap(center, side, {x = emptySpaceBeginPos.x, y = emptySpaceBeginPos.y, z = emptySpaceBeginPos.z - i})
    end
end
 

 

 

 

As funções estão todas funcionando, porém algumas não foram utilizadas nessa versão, ficam de bônus pra vocês.

 

Depois disso, vá em talkactions.xml adicione a tag:

<talkaction words="!clonemap" event="script" value="cmap.lua"/>

Feito isso, crie dentro de scripts um arquivo chamado cmap.lua e adicione o código abaixo:

 

 

 

local config = {
    map = {center = {x = 102, y = 182, z = 7}, side = 5},
    emptySpaceBeginPos = {x = 84, y = 247, z = 7},
    storages = {x = 5546, y = 5547, z = 5548},
    safe_dist = 15
}
--params {1 CenterX, 2 CenterY, 3 CenterZ, 4 Side, 5 Dimensions}
--!clonemap CenterX CenterY CenterZ Side Dimensions

function onSay(cid, words, param)
    if getPlayerGroupId(cid) == 6 then
        if(getGlobalStorageValue(config.storages.x) == -1) then setGlobalStorageValue(config.storages.x, config.emptySpaceBeginPos.x) end
        if(getGlobalStorageValue(config.storages.y) == -1) then setGlobalStorageValue(config.storages.y, config.emptySpaceBeginPos.y) end
        if(getGlobalStorageValue(config.storages.z) == -1) then setGlobalStorageValue(config.storages.z, config.emptySpaceBeginPos.z) end

        local data = string.split(param)
        if data then
            if #data < 5 then
                doPlayerSendCancel(cid, "!clonemap needs 5 parameters: x, y, z, side and dimensions")
                return false
            else
                if tonumber(data[1]) ~= nil and tonumber(data[2]) ~= nil and tonumber(data[3]) ~= nil and tonumber(data[4]) ~= nil and tonumber(data[5]) ~= nil then
                    local pos = {x = getGlobalStorageValue(config.storages.x),
                                y = getGlobalStorageValue(config.storages.y),
                                z = getGlobalStorageValue(config.storages.z)}
                    if (pos.x + config.safe_dist + 2*data[4]) > 2048 then
                        if((pos.y + config.safe_dist + 2*data[4]) > 2048) then
                            doPlayerSendCancel(cid, "Your free area is full.")
                            return false
                        end
                        pos.x = config.emptySpaceBeginPos.x
                        pos.y = pos.y + config.safe_dist + 2*data[4]
                    end
                    cloneMultiDimensionalMaps({x = data[1], y = data[2], z = data[3]}, data[4], pos, (data[5] - 1))
                    setGlobalStorageValue(config.storages.x, pos.x + config.safe_dist + 2*data[4])
                    setGlobalStorageValue(config.storages.y, pos.y)
                else
                    doPlayerSendCancel(cid, "!clonemap parameters must be numbers.")
                    return false
                end
            end
        else
            doPlayerSendCancel(cid, "You must define at least 5 parameters to !clonemap.")
            return false
        end
    else
        doPlayerSendCancel(cid, "You must be a GOD to cast !clonemap.")
        return false
    end
    --clearArea({x = config.emptySpaceBeginPos.x + config.map.side, y = config.emptySpaceBeginPos.y + config.map.side, z = 7}, config.map.side)
end
 

 

 

 

Por último, vá em globalevents/scripts e abra o arquivo start.lua.

Dentro da função onStartup(), antes do return true, adicione as 3 linhas a seguir:

setGlobalStorageValue(5546, -1)
setGlobalStorageValue(5547, -1)
setGlobalStorageValue(5548, -1)

Pronto.

 

Agora algumas configurações que você deve fazer de acordo com seu mapa:

 

emptySpaceBeginPos - É a posição no mapa onde começa a área vazia que você determinou para a criação das instâncias (Canto superior esquerdo da área, ela cresce para direita até o fim do mapa e depois para baixo e se encerra quando o mapa acaba).

 

Storages - Storages globais onde serão armazenadas os próximos valores X, Y e Z a serem utilizados. (A progressão no eixo z ainda não foi implementada, mas a lógica é a mesma).

 

safe_dist - É a distância entre os mapas, você pode variar de acordo com a utilização que vai dar ao mapa.

 

Feito isso, está pronto para utilizar o Instanciador de Mapas V1.0.

 

Como funciona:

 

!clonemap CenterX CenterY CenterZ Side Floors

 

Centers (X, Y e Z) são as coordenadas centrais do seu mapa (e Z é o floor mais baixo do mapa, caso ele seja multi floor, isto é o floor de valor mais alto - ex, se o seu mapa vai de z=7 até z =10, use CenterZ = 10).

 

Side é a distância entre o centro e uma das bordas (Caso o mapa não seja quadrado, basta usar a maior distância. É possível implementar usando a mesma lógica um SideX e SideY, mas eu não tive tempo de fazê-lo).

 

Floors é o número de andares que tem o seu mapa, se ele ocupa só um andar floor = 1, 2 floor = 2 e assim por diante.

 

Bom é isso, espero que gostem e que seja útil para vocês.
Agora vou empenhar no sistema completo, assim que terminar eu posto a versão 2.0 do instanciador com muito mais recursos.

 

Algumas Imagens

 

14yab8x.png

28k6be8.png

ml1agy.png

5kn32e.png

qrmezd.png

15edc8n.png

2jb02kj.png

2pywe9k.png

 

 

 

OBSERVAÇÃO IMPORTANTE
Quando você utilizar o comando ingame, esteja longe da área onde o mapa será criado, senão o seu cliente irá debugar. Nada acontece, na verdade, acho que é algum problema do cliente, assim que você abre o tibia novamente tudo se estabiliza, mas é chato ficar re-abrindo então evite isso.\

 

Grande abraço.

 

ps: Lembrando, novamente dos Créditos ao Danihcv pela ideia, sem o brainstorm por ele promovido no meu tópico isso não seria possível :p

Editado por Skulls
Link para o comentário
Compartilhar em outros sites

Genial cara! Mais genial ainda você querer compartilhar.

:biggrin: :biggrin:

Valeu Daniel!

Passei da minha época já, hoje em dia faço por hobbie quando to atoa. Tenho uma pequena ideia em mente, vou tocando ela devagarzinho em sigilo, mas o sistemas que a envolvem eu vou compartilhando com vocês! :p

 

@Topic

Adicionei algumas imagens e fixei um bug estranho.

Link para o comentário
Compartilhar em outros sites

Esperando pra ver a versão final. shausahuashu

(y)

 

*ps: os créditos são pra vc, isso sim. Vc que desenvolveu o script. sahusahusa

Editado por Danihcv
Link para o comentário
Compartilhar em outros sites

Esperando pra ver a versão final. shausahuashu

(y)

 

*ps: os créditos são pra vc, isso sim. Vc que desenvolveu o script. sahusahusa

Po calma, to te dando os créditos da ideia. Ta certo, eu fiz. Mas o que é o mundo sem as ideias? hahaha

Se tudo der certo acho que esse mes sai a v2.0, inclusive se quiser me ajudar a pensar em funcionalidades para o mesmo, estou aberto à sugestões :p

 

obs: Editei pra adicionar um reset nos storages toda vez que o server for iniciado, isso impede que o server salve com várias instâncias criadas e a posição '0' mude de lugar.

Editado por Skulls
Link para o comentário
Compartilhar em outros sites

Amigo, recomendo fazer isso pela source, você cria esses espaços com o RME, e carrega eles em uma lista de instancias, assim quando precisar não fica criando esses tiles, e se torna muito mais simples e pratico.



Vou explicar detalhadamente o que você precisa fazer.



1° Criar um vetor ( Recomendo std::map ) de mapas do tibia


2° Criar um método em c++ que carrega esses maps e insere ele no vetor


3° criar um método que transporta o player para o seu map


4° criar um método que salve a oldPos do players, para quando ele deslogar / morrer, ele voltar pro map principal.



com um conhecimento razoável em c++ é possível fazer isso, porem acho que pode ser um pouco trabalhoso.



Com esse sistema você pode criar mapas para dungeons, houses etc, e sem contar que você pode transportar vários players para esses locais.


Editado por BananaFight
Link para o comentário
Compartilhar em outros sites

×
×
  • Criar Novo...