Ir para conteúdo

[Spells] Checando Interferências na Trajetória


Skulls

Posts Recomendados

Boa noite galera, tudo bem?

 

Venho compartilhar com vocês hoje um sisteminha que desenvolvi para as magias do tipo "shoot'. Foi feito inicialmente para funcionar com magias que usam a posição do mouse como referência e adaptei para cipclientes poderem usar em runas e magias de tiro.

 

O funcionamento do sistema é simples: Ao usar uma runa ou castar uma magia "shoot" com esse sistema criaturas e objetos no caminho irão interferir na trajetória, isto é, receberão o combate no lugar do alvo inicial.

 

Ilustrativo:

 

giphy.gif

 

 

Bom, vamos ao que interessa.

 

Vá em data/lib/ e crie um novo arquivo chamado spellsLib.lua (pode-se utilizar também o arquivo spells.lua contido em data/spells/lib).

 

Dentro dele inclua as seguintes funções:

 

IsWalkable (by Nord)

function isWalkable(pos, creature, proj, pz)-- by Nord
    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

GetPositionsAround (by Skulls)

function getPositionsAround(pos)
return {
[1] = {x = pos.x, y = pos.y - 1, z = pos.z, stackpos = 0},
[2] = {x = pos.x + 1, y = pos.y - 1, z = pos.z, stackpos = 0},
[3] = {x = pos.x + 1, y = pos.y, z = pos.z, stackpos = 0},
[4] = {x = pos.x + 1, y = pos.y + 1, z = pos.z, stackpos = 0},
[5] = {x = pos.x, y = pos.y + 1, z = pos.z, stackpos = 0},
[6] = {x = pos.x - 1, y = pos.y + 1, z = pos.z, stackpos = 0},
[7] = {x = pos.x - 1, y = pos.y, z = pos.z, stackpos = 0},
[8] = {x = pos.x - 1, y = pos.y - 1, z = pos.z, stackpos = 0}
}
end

 

CheckInterceptions (by Skulls)

 

 


function checkInterceptions(cid, pos, toPos, creature)
local p = pos
local dir = getDirectionTo(pos, toPos)
local d = getDistanceBetween(pos, toPos)
if dir < SOUTHWEST then
while d > 0 do
dir = getDirectionTo(p, toPos)
p = getPosByDir(p, dir, 1)
d = getDistanceBetween(p, toPos)
if not isWalkable(p, creature, true, true) then
return p
end
end
else
local nextPositions = {pos}
local tam = 1
while d > 0 do
local i = tam
if tam > 2 then tam = 2 end
local positions = getPositionsAround(nextPositions[tam])
if (dir == SOUTHWEST and (nextPositions[tam].x < toPos.x or nextPositions[tam].y > toPos.y))
or (dir == NORTHEAST and (nextPositions[tam].x > toPos.x or nextPositions[tam].y < toPos.y)) then
positions = getPositionsAround(nextPositions[tam+1])
end
if dir == SOUTHEAST and (nextPositions[tam].x > toPos.x or nextPositions[tam].y > toPos.y)
or (dir == NORTHWEST and (nextPositions[tam].x < toPos.x or nextPositions[tam].y < toPos.y)) then
positions = getPositionsAround(nextPositions[tam-1])
end
d = getDistanceBetween(nextPositions[tam], toPos)
tam = 0
if d == 0 then break end
local sum = 0
if dir == SOUTHWEST then sum = 4
elseif dir == SOUTHEAST then sum = 2
elseif dir == NORTHWEST then sum = 6
elseif dir == SOUTHEAST then sum = 0 end
for j=1, 3 do
local index = j+sum
local check = 0
if index > #positions then index = 1 end
if dir == SOUTHWEST and (positions[index].x < toPos.x or positions[index].y > toPos.y)
or (dir == SOUTHEAST and (positions[index].x > toPos.x or positions[index].y > toPos.y))
or (dir == NORTHWEST and (positions[index].x < toPos.x or positions[index].y < toPos.y))
or (dir == NORTHEAST and (positions[index].x > toPos.x or positions[index].y < toPos.y)) then
check = 1
end
local dx, dy = math.abs(positions[index].x - toPos.x) , math.abs(positions[index].y - toPos.y)
if dx == dy and (positions[index].x == pos.x or positions[index].y == pos.y)
and ((getDistanceBetween(positions[index], pos) > 1 and getDistanceBetween(positions[index], toPos) > 1)
or getDistanceBetween(positions[index], pos) > 5 and getDistanceBetween(positions[index], toPos) > 0)then
check = 1
end
if getDistanceBetween(positions[index], toPos) == 0 then return toPos end
if getDistanceBetween(positions[index], toPos) < d and check == 0 then
if not isWalkable(positions[index], creature, true, true) then
return positions[index]
end
tam = tam + 1
nextPositions[tam] = positions[index]
end
end
end
end
return toPos
end

 

 

 

SetSpellTarget (by Skulls)

 

 


function setSpellTarget(cid, var)
local target = getCreatureTarget(cid)
var.pos = checkInterceptions(cid, getPlayerPosition(cid), getCreaturePosition(target), true)
if isCreature(getThingFromPos(var.pos).uid) then
var.number = getThingFromPos(var.pos).uid
else
var.number = false
end
return var
end

 

 

 

Feito isso, está tudo configurado. Basta agora adicionar às magias que você queira.

Abra o .lua da magia, por exemplo death strike.lua.

Lá você terá, entre outras coisas, a função onCastSpell como abaixo:

function onCastSpell(cid, var)
return doCombat(cid, combat, var)
end

Substitua isso por:


local range = 5
function onCastSpell(cid, var)
if getCreatureTarget(cid) == 0 then
doPlayerSendCancel(cid, "Please choose a target.")
doSendMagicEffect(getCreaturePosition(cid), CONST_ME_POFF)
return false
end
if getDistanceBetween(getPlayerPosition(cid), getCreaturePosition(getCreatureTarget(cid))) > range then
doPlayerSendCancel(cid, "Target is not reachable.")
doSendMagicEffect(getCreaturePosition(cid), CONST_ME_POFF)
return false
end
return doCombat(cid, combat, setSpellTarget(cid, var)) end
Retire qualquer tag que esteja relacionada a target (needtarget, casterTargetOrDirection, etc)
Pronto, a sua magia "Exori Mort" será parada por criaturas ou obstáculos (qualquer item que não seja móvel).
Bom é isso, espero que gostem.
Queria agradecer ao @@nightwolf e ao @Caronte pelas ajudas tentando entender alguns parâmetros e me dando algumas luzes. Ao @@nightwolf, ainda, um agradecimento especial pela maravilhosa lib dele *-*.
Abraços,

 

Um exemplo de magia que utiliza esse sistema: http://www.xtibia.com/forum/topic/239460-exori-grab-vis/


@@Daniel, na verdade move pra mim pra Downloads Spells, acho que seria mais correto.

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

Nas funções CheckInterceptions e SetSpellTarget o final delas ta com 'end' colado no return. a CheckInterceptions ta 'return toPosend' e a SetSpellTarget está 'return varend'.

 

Arrumado, obrigado.

Link para o comentário
Compartilhar em outros sites

bem que o @Daniel poderia habilitar REP pelo celular.

Muito bom o conteúdo. :)

Obrigado! Da pra dar rep pelo cel, só colocar na versão completa la embaixo ^^ hahaha

Link para o comentário
Compartilhar em outros sites

ficou realmente muito bom, meus parabéns. Você botou na cabeça que queria fazer e foi atrás de conseguir. O resultado veio com o esforço, obrigado por me citar e por contribuir ainda mais com a comunidade do Open Tibia. Abraços meu amigo.

Link para o comentário
Compartilhar em outros sites

ficou realmente muito bom, meus parabéns. Você botou na cabeça que queria fazer e foi atrás de conseguir. O resultado veio com o esforço, obrigado por me citar e por contribuir ainda mais com a comunidade do Open Tibia. Abraços meu amigo.

Obrigado wolf, não teria conseguido sem você! :p

 

Parabéns pelo belo sistema.

Valeu!

Adicionado um exemplo de uso.

Link para o comentário
Compartilhar em outros sites

Muito bom skulls, essa função pode ajudar até em fazer um getCreaturePathTo(...) por lua...

 

Script muito bom.

 

ficou realmente muito bom, meus parabéns. Você botou na cabeça que queria fazer e foi atrás de conseguir. O resultado veio com o esforço, obrigado por me citar e por contribuir ainda mais com a comunidade do Open Tibia. Abraços meu amigo.

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

interessante seria também,ignorar a interferencia que tem na frente,porém da metade do dano no da frente,e todo o dano no de trás.

 

tipo o orc da frente recebe 50 de dano e o de trás 100,um exemplo,ficaria show,rep+

 

dai é claro,sem interferencia,como na sua giff.

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

interessante seria também,ignorar a interferencia que tem na frente,porém da metade do dano no da frente,e todo o dano no de trás.

 

tipo o orc da frente recebe 50 de dano e o de trás 100,um exemplo,ficaria show,rep+

 

dai é claro,sem interferencia,como na sua giff.

 

Boa ideia, também seria interessante puxar os dois kkkkk.

Link para o comentário
Compartilhar em outros sites

@@Caronte, acho q ele quis dizer estilo o Q da miss fortune no league of legends... qnd vc dá um tiro e mata o bixo o tiro rebate com dobro de dano se tiver alguém atrás (seguindo a direção), ficaria muito legal ter algo nesse sentido tb.

Link para o comentário
Compartilhar em outros sites

Muito bom skulls, essa função pode ajudar até em fazer um getCreaturePathTo(...) por lua...

 

Script muito bom.

 

Realmente, da para usar. Ja existe uma função de path do wolf, mas talvez com essa logica fique bom também rs. O grande problema é que, para paths, você não checa só na direção que você quer andar e sim em todas, caso a sua esteja sem passagem, né? xD

 

interessante seria também,ignorar a interferencia que tem na frente,porém da metade do dano no da frente,e todo o dano no de trás.

 

tipo o orc da frente recebe 50 de dano e o de trás 100,um exemplo,ficaria show,rep+

 

dai é claro,sem interferencia,como na sua giff.

 

Sim, da pra fazer muita coisa. Da para fazer damage reduction tb (quanto mais alvos a magia atravessar, menos dano ela da).

 

@@Caronte, acho q ele quis dizer estilo o Q da miss fortune no league of legends... qnd vc dá um tiro e mata o bixo o tiro rebate com dobro de dano se tiver alguém atrás (seguindo a direção), ficaria muito legal ter algo nesse sentido tb.

Da tambem, basta a spell ser com range fixo (por exemplo sempre que usar ela vai do player até a direção que ele mandou 5 sqm para frente) e fazer a checagem. Se tiver uma interferencia ativa o combat1 se tiver duas o combat2 ^^

Link para o comentário
Compartilhar em outros sites

×
×
  • Criar Novo...