Ir para conteúdo
  • 0

Obter items ao redor do player


LuckOake

Pergunta

Seguinte, tô fazendo uns scripts aqui pra liberar pra galera quando eu terminar, mas pra isso eu preciso de uma função que vê se existe tal item ao redor do player.

 

Fiz um modelo base, vejam:

 

function hasItems(cid)
items = {1234, 2345, 3456, 4567}
pos = getCreaturePos(cid)
a = {
{x = pos.x-2, y = pos.y, z = pos.z, stackpos = 0},
{x = pos.x+2, y = pos.y, z = pos.z, stackpos = 0},
{x = pos.x, y = pos.y-2, z = pos.z, stackpos = 0},
{x = pos.x, y = pos.y+2, z = pos.z, stackpos = 0},
}

for b, c in pairs(a) do
return isInArray(items, getThingFromPos(c).itemid) and true or false
end
end

 

O problema é que ela tá retornando true apenas se tiver os items em todas as posições declaradas na tabela a, ou seja, se tiver em apenas três das quatros posições o script retorna false.

 

Eu precisava do seguinte: o script ver se em alguma das posições da tabela a existe o item da tabela items, não sendo necessário ter items em todas as posições.

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

14 respostass a esta questão

Posts Recomendados

  • 0

function hasItems(position, rangex, rangey, ...)
local fromPosition = {x = position.x - rangex, y = position.y - rangey, z = position.z}
local toPosition = {x = position.x + rangex, y = position.y + rangey, z = position.z}
local items = {...}

local match = false
for x = fromPosition.x, toPosition.x do
	for y = fromPosition.y, toPosition.y do
		local p = {x = x, y = y, z = fromPosition.z}
		for _, item in ipairs(items) do
			local w = getTileItemById(p, item)
			if w.uid > 0 then
				match = true
			end
		end
	end
end
return match
end

 

Acabou de sair do forno.

 

Utilização:

 

hasItems(getThingPosition(cid), 1, 1, 2112, 2160, 2152, 2148)

 

Irá procurar em uma área de 3X3 ao redor do jogador pelos quatro itens especificados na função, caso ache qualquer um dos quatro, irá retornar true.

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

  • 0

soh pra complementar..

o teu script estava pegando o tile e n os itens no tile... stackpos 0 = tile ^^

e como vc colocou direto pra retornar true ou false.. soh iria da true se na 1* execuçao do for tivese algum dos itens...

quando se coloca 'return (qlqr coisa)' o script automaticamente para e retorna esse (qlqr coisa)... cancelando tudo q tiver depois...

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

  • 0

soh pra complementar..

o teu script estava pegando o tile e n os itens no tile... stackpos 0 = tile ^^

e como vc colocou direto pra retornar true ou false.. soh iria da true se na 1* execuçao do for tivese algum dos itens...

quando se coloca 'return (qlqr coisa)' o script automaticamente para e retorna esse (qlqr coisa)... cancelando tudo q tiver depois...

 

Na verdade, essa função não é exatamente pra pegar items. Eu camuflei ela, a função original é diferente da que eu postei aqui. Só a ideia que é parecida.

 

@Oneshot

 

Valeus, fiz umas adaptações aqui e funcionou, só que também tá pegando diagonal. Exemplo:

 

x x x x x x x

x x x y x x x

x x x y x x x

x y y y y y x

x x x y x x x

x x x y x x x

x x x x x x x

 

Azul: Área que a função detecta

Vermelho: Área em que a função também detecta, mas não devia detectar

 

Como arrumar isso?

Link para o comentário
Compartilhar em outros sites

  • 0

eu gosto muito dessa function..

 

------------------ Function getPosfromArea(cid,area) by Dokmos ------------------

function getPosfromArea(cid,area)

icenter = math.floor(table.getn(area)/2)+1

jcenter = math.floor(table.getn(area[1])/2)+1

center = area[icenter]

ivar = table.getn(area)

jvar = table.getn(area[1])

i = table.getn(area)^2

j = table.getn(area[1])^2

 

local mydir = isCreature(getMasterTarget(cid)) and getCreatureDirectionToTarget(cid, getMasterTarget(cid)) or getCreatureLookDir(cid)

 

if center[jcenter] == 3 then

if mydir == 0 then

signal = {-1,1,1,2}

elseif mydir == 1 then

signal = {1,-1,2,1}

elseif mydir == 2 then

signal = {1,-1,1,2}

elseif mydir == 3 then

signal = {-1,1,2,1}

end

else

signal = {-1,1,1,2}

end

 

POSITIONS = {}

P = 0

 

repeat

pvar = {0,0}

I = area[ivar]

J = I[jvar]

i = i-1

j = j-1

if J == 1 then

if jvar < jcenter then

pvar[signal[3]] = signal[1]*math.abs((jcenter-jvar))

elseif jvar > jcenter then

pvar[signal[3]] = signal[2]*math.abs((jcenter-jvar))

end

 

if ivar < icenter then

pvar[signal[4]] = signal[1]*math.abs((icenter-ivar))

elseif ivar > icenter then

pvar[signal[4]] = signal[2]*math.abs((icenter-ivar))

end

end

if jvar > 1 then

jvar = (jvar-1)

elseif ivar > 1 then

jvar = table.getn(area[1])

ivar = (ivar-1)

end

local pos = getThingPos(cid)

local areapos = {x=pos.x+(pvar[1]),y=pos.y+(pvar[2]),z=pos.z}

 

if pos.x ~= areapos.x or pos.y ~= areapos.y then

P = P+1

POSITIONS[P] = areapos

end

 

until i <= 0 and j <= 0

 

return POSITIONS

end

 

 

com ela vc pode usar uma area de spell pra verificaçao.. tpw...

cruz = {
{0, 0, 1, 0, 0},
{0, 0, 1, 0, 0},
{1, 1, 2, 1, 1},
{0, 0, 1, 0, 0},
{0, 0, 1, 0, 0}
}
function hasItems(cid)
local posis = getPosfromArea(cid, cruz)
local itens = {1111, 2222, 3333}
for a, b in ipairs(posis) do
for c, d in ipairs(itens) do
local item = getTileItemById(b, d)
if item.uid > 0 then
return true
end
end
end
return false
end

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

  • 0

/\

kk n vou discorda de ti... mas como n sei mexer com posiçoes muito bem.. prefiro deixar assim..

e o bom dela tb eh q se tu tiver uma area assim..

whips = {

{1, 1, 1},

{1, 1, 1},

{0, 3, 0},

{0, 0, 0}

}

o dano/efeito seja oq for, sai na direçao q tu esta virado.. no caso ali, em tese, soh iria sair o dano/efeito para cima... soh q como ta com 3 ali em vez de 2.. o player pode ta virado pra baixo e o dano/efeito saira pra baixo '--'

Link para o comentário
Compartilhar em outros sites

  • 0

Tá certo galera, mas e então, someone reduz a função? Aquela função ali tá gigante de mais, vai deixar a lib feia .-.

 

Ou então, há alguma outra forma de pegar a área definida sem pegar diagonais?

Link para o comentário
Compartilhar em outros sites

  • 0

eu n me habilito a tentar kkk eu joguei ela no final da lib de position kkk ta la esquecida...

o outro jeito de fazer seria q nem tu fez no 1* script.. colocando todas as areas numa tabela.. ;/ mas dai achu muito trabalhoso kkk

Link para o comentário
Compartilhar em outros sites

  • 0

Uma função que procura direto no formado de cruz:

 

 

function checkItems(itemsId, centerPos, range)
for direction = 0, 3 do
	for _range = 1, range do
		for _, itemid in pairs(itemsId) do
			local checkpos = getPosByDir(centerPos, direction, _range)
			if getTileItemById(checkpos, itemid).uid > 1 then return true end
		end
	end
end
return false
end

local items = {2148, 2160, 2142}

if checkItems(items, {x = 100, y = 100, z = 7}, 2) then
--[[
procura por itens na área:
{0, 0, 1, 0, 0},
{0, 0, 1, 0, 0},
{1, 1, 2, 1, 1},
{0, 0, 1, 0, 0},
{0, 0, 1, 0, 0},
sendo 2 a posição do segundo parâmetro
retorna true se encontrar algum dos itens em alguma dessas posições
]]
end

 

 

eu fiz uma lib que converte uma array com 0, 1, 2 e 3 numa array de positions

detalhe: acho muito difícil fazer uma função parecida em poucas linhas, pelo menos em lua acho que não rola...

o que eu não fiz ainda foi vasculhar as sources pra ver como é feita essa conversão em spells e traduzir pra lua, essa aqui fiz sem basear em nada:

 

 

function newXYvar(x, y, voltas_horarias)
while voltas_horarias > 3 do
	voltas_horarias = voltas_horarias - 4
end
if voltas_horarias <= 0 then
	return x, y
elseif voltas_horarias == 1 then
	return -y, x
elseif voltas_horarias == 2 then
	return -x, -y
elseif voltas_horarias == 3 then
	return y, -x
end
return 0, 0
end

function arrayToPositions(array, center, n_horario)
if not center or not center.x or not center.y or not center.z then return {} end
local voltas, mp, ret, iIs, x, y = n_horario and math.max(0, n_horario) or 0, {}, {}, {}, 1, 1
if voltas > 0 then
   local maxC = 0
   for lines = 1, #array do if maxC < #array[lines] then maxC = #array[lines] end end
   if maxC < #array then maxC = #array end
   for a = 1, maxC do iIs[a] = {} for b = 1, maxC do table.insert(iIs[a], 0) end end
end
while #mp == 0 do
	local check = array[y][x]
	if check > 1 then
		mp = {x, y}
		if voltas > 0 then iIs[y][x] = check end
		if check == 3 then table.insert(ret, center) end
		break
	end
	x = x + 1
	if x > #array[y] then
		y, x = y + 1, 1
		if y > #array then break end
	end
end
for ly, ny in pairs (array) do
	for lx, nx in pairs (ny) do
		if nx == 1 then
			local dx, dy = lx - mp[1], ly - mp[2]
			local newX, newY = newXYvar(dx, dy, voltas)
			local newPos = {x = center.x + newX, y = center.y + newY, z = center.z}
			table.insert(ret, newPos)
		end
	end
end
return ret
end

 

 

Exemplo de uso dela:

 

 

local arr = {
{0, 1},
{1, 2, 1},
{0, 0, 0, 0, 1}}

local positions = arrayToPositions(arr, {x = 100, y = 50, z = 7})

for _, pos in pairs (positions) do
print(pos.x.." / "..pos.y)
end

--[[
imprime na tela:
x: 100 / y: 49
x: 99 / y: 50
x: 101 / y: 50
x: 103 / y: 51
]]

 

 

O bom dessa função que fiz é que a array não precisa ser simetrica/quadrada

o primeiro parâmetro é o array contendo os nº (0 até 3, 0 não é nada, 1 é trnasformado em posição, 2 é o centro só que não é incluído no return da função, 3 é o centro e é incluído no retorno), o segundo array é a posição centro e o 3º parâmetro é o nº de voltas que o array vai dar, exemplo:

 

 

{0, 1, 0}
{0, 2, 0}
{1, 0, 0}

essa array com o terceiro argumento como 0 retorna ela mesmo (em posições, óbvio)
com o terceiro argumento como 1 ela vira para a direita, ficando:

{1, 0, 0}
{0, 2, 1}
{0, 0, 0}

com o terceiro argumento como 2 ela vira para o sul, ficando:

{0, 0, 1}
{0, 2, 0}
{0, 1, 0}

e assim vai...

 

 

Um exemplo de como uma magia que seria um raio para frente usando essa lib:

 

 

local arr = {
{1},
{1},
{1},
{1},
{1},
{2}}

local positions = arrayToPositions(arr, getThingPos(cid), getCreatureLookDir(cid))

for _, pos in pairs (positions) do
doCombatAreaHealth(cid, ...)
end

 

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

  • 0

opa, nessa parte aqui do script:

 

if getTileItemById(checkpos, itemid) then return true end

 

substitui por isso:

 

if getTileItemById(checkpos, itemid).uid > 1 then return true end

 

ja mudei lá em cima

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

×
×
  • Criar Novo...