Jump to content

Como usar um mesmo onClientRender várias vezes simultâneas?


Recommended Posts

Estou fazendo um sistema de infobox do zero me baseando no Five-M, porém não consigo pensar em uma maneira de fazer com que caso tenha mais de 2 mensagens sendo exibidas ao player ao mesmo tempo não buga e de o erro no debug 'event is already handled'.

Até o momento eu fiz isso: 

local screenW, screenH = guiGetScreenSize()
local font = dxCreateFont("fontes/Roboto.ttf", 10)
local tipo = "warning"
local msg = "Você está com fome, precisa se alimentar o mais rápido possível!"
slotsUsed = {}

infos = {
    ["success"] = {"40", "175", "40", "gfx/success.png", "sfx/sound.mp3"},
    ["info"] = {"30", "144", "255", "gfx/info.png", "sfx/sound.mp3"},
    ["warning"] = {"200", "200", "0", "gfx/warning.png", "sfx/sound.mp3"},
    ["error"] = {"255", "40", "40", "gfx/error.png", "sfx/sound.mp3"},
    ["money"] = {"40", "175", "40", "gfx/money.png", "sfx/sound.mp3"},
    ["exp"] = {"30", "144", "255", "gfx/exp.png", "sfx/sound.mp3"},
}

posRectangle = {
    {screenW * 0.0073, screenH * 0.6758, screenW * 0.1779, screenH * 0.0573},
    {screenW * 0.0073, screenH * 0.6133, screenW * 0.1779, screenH * 0.0573},
    {screenW * 0.0073, screenH * 0.5508, screenW * 0.1779, screenH * 0.0573},
    {screenW * 0.0073, screenH * 0.4883, screenW * 0.1779, screenH * 0.0573},
    {screenW * 0.0073, screenH * 0.4258, screenW * 0.1779, screenH * 0.0573},
    {screenW * 0.0073, screenH * 0.3633, screenW * 0.1779, screenH * 0.0573},
    {screenW * 0.0073, screenH * 0.3008, screenW * 0.1779, screenH * 0.0573}, 
}

posIMG = {
    {screenW * 0.0102, screenH * 0.6810, screenW * 0.0256, screenH * 0.0456},
    {screenW * 0.0102, screenH * 0.6185, screenW * 0.0256, screenH * 0.0456},
    {screenW * 0.0102, screenH * 0.5560, screenW * 0.0256, screenH * 0.0456},
    {screenW * 0.0102, screenH * 0.4935, screenW * 0.0256, screenH * 0.0456},
    {screenW * 0.0102, screenH * 0.4310, screenW * 0.0256, screenH * 0.0456},
    {screenW * 0.0102, screenH * 0.3685, screenW * 0.0256, screenH * 0.0456},
    {screenW * 0.0102, screenH * 0.3060, screenW * 0.0256, screenH * 0.0456},
}

posText = {
    {screenW * 0.0432, screenH * 0.6758, screenW * 0.1852, screenH * 0.7331},
    {screenW * 0.0432, screenH * 0.6133, screenW * 0.1852, screenH * 0.6706},
    {screenW * 0.0432, screenH * 0.5508, screenW * 0.1852, screenH * 0.6081},
    {screenW * 0.0432, screenH * 0.4883, screenW * 0.1852, screenH * 0.5456},
    {screenW * 0.0432, screenH * 0.4258, screenW * 0.1852, screenH * 0.4831},
    {screenW * 0.0432, screenH * 0.3633, screenW * 0.1852, screenH * 0.4206},
    {screenW * 0.0432, screenH * 0.3008, screenW * 0.1852, screenH * 0.3581},
}

addEventHandler("onClientRender", root, function()
    for i, v in pairs(infos) do
        if i == tipo then
            local length = dxGetTextWidth(msg, 1, font)
            dxDrawRectangle(posRectangle[1][1], posRectangle[1][2], length + screenW/23, posRectangle[1][4], tocolor(10, 10, 10, 220), false)
            dxDrawImage(posIMG[1][1], posIMG[1][2], posIMG[1][3], posIMG[1][4], infos[i][4], 0, 0, 0, tocolor(infos[i][1], infos[i][2], infos[i][3], 255), false)
            dxDrawText(msg, posText[1][1], posText[1][2], posText[1][3], posText[1][4], tocolor(255, 255, 255, 255), 1.00, font, "left", "center", false, false, false, false, false)
            break
        end
    end
end)

*As string tipo e msg é apenas para teste.

Link to comment

Você pode nomear a função que está no evento "onClientRender", cancelá-lo com removeEventHandler e logo em seguida chamá-lo novamente. Não sei se é a melhor saída.

function funcao_nomeada()
    for i, v in pairs(infos) do
        if i == tipo then
            local length = dxGetTextWidth(msg, 1, font)
            dxDrawRectangle(posRectangle[1][1], posRectangle[1][2], length + screenW/23, posRectangle[1][4], tocolor(10, 10, 10, 220), false)
            dxDrawImage(posIMG[1][1], posIMG[1][2], posIMG[1][3], posIMG[1][4], infos[i][4], 0, 0, 0, tocolor(infos[i][1], infos[i][2], infos[i][3], 255), false)
            dxDrawText(msg, posText[1][1], posText[1][2], posText[1][3], posText[1][4], tocolor(255, 255, 255, 255), 1.00, font, "left", "center", false, false, false, false, false)
            break
        end
    end
end

function adicionar_evento()
removeEventHandler("onClientRender", root, funcao_nomeada)
addEventHandler("onClientRender", root, funcao_nomeada)
 end

Foi mal, não pensei em nada mais criativo.

Edited by GSC
Link to comment
11 hours ago, GSC said:

Você pode nomear a função que está no evento "onClientRender", cancelá-lo com removeEventHandler e logo em seguida chamá-lo novamente. Não sei se é a melhor saída.



function funcao_nomeada()
    for i, v in pairs(infos) do
        if i == tipo then
            local length = dxGetTextWidth(msg, 1, font)
            dxDrawRectangle(posRectangle[1][1], posRectangle[1][2], length + screenW/23, posRectangle[1][4], tocolor(10, 10, 10, 220), false)
            dxDrawImage(posIMG[1][1], posIMG[1][2], posIMG[1][3], posIMG[1][4], infos[i][4], 0, 0, 0, tocolor(infos[i][1], infos[i][2], infos[i][3], 255), false)
            dxDrawText(msg, posText[1][1], posText[1][2], posText[1][3], posText[1][4], tocolor(255, 255, 255, 255), 1.00, font, "left", "center", false, false, false, false, false)
            break
        end
    end
end

function adicionar_evento()
removeEventHandler("onClientRender", root, funcao_nomeada)
addEventHandler("onClientRender", root, funcao_nomeada)
 end

Foi mal, não pensei em nada mais criativo.

Acho que isso não vai mudar nada, só vai fazer sumir e reaparecer a mensagem que estava na tela (vai ser tão rápido que será imperceptível)

On 06/11/2020 at 22:18, ber said:

Estou fazendo um sistema de infobox do zero me baseando no Five-M, porém não consigo pensar em uma maneira de fazer com que caso tenha mais de 2 mensagens sendo exibidas ao player ao mesmo tempo não buga e de o erro no debug 'event is already handled'.

Até o momento eu fiz isso: 



local screenW, screenH = guiGetScreenSize()
local font = dxCreateFont("fontes/Roboto.ttf", 10)
local tipo = "warning"
local msg = "Você está com fome, precisa se alimentar o mais rápido possível!"
slotsUsed = {}

infos = {
    ["success"] = {"40", "175", "40", "gfx/success.png", "sfx/sound.mp3"},
    ["info"] = {"30", "144", "255", "gfx/info.png", "sfx/sound.mp3"},
    ["warning"] = {"200", "200", "0", "gfx/warning.png", "sfx/sound.mp3"},
    ["error"] = {"255", "40", "40", "gfx/error.png", "sfx/sound.mp3"},
    ["money"] = {"40", "175", "40", "gfx/money.png", "sfx/sound.mp3"},
    ["exp"] = {"30", "144", "255", "gfx/exp.png", "sfx/sound.mp3"},
}

posRectangle = {
    {screenW * 0.0073, screenH * 0.6758, screenW * 0.1779, screenH * 0.0573},
    {screenW * 0.0073, screenH * 0.6133, screenW * 0.1779, screenH * 0.0573},
    {screenW * 0.0073, screenH * 0.5508, screenW * 0.1779, screenH * 0.0573},
    {screenW * 0.0073, screenH * 0.4883, screenW * 0.1779, screenH * 0.0573},
    {screenW * 0.0073, screenH * 0.4258, screenW * 0.1779, screenH * 0.0573},
    {screenW * 0.0073, screenH * 0.3633, screenW * 0.1779, screenH * 0.0573},
    {screenW * 0.0073, screenH * 0.3008, screenW * 0.1779, screenH * 0.0573}, 
}

posIMG = {
    {screenW * 0.0102, screenH * 0.6810, screenW * 0.0256, screenH * 0.0456},
    {screenW * 0.0102, screenH * 0.6185, screenW * 0.0256, screenH * 0.0456},
    {screenW * 0.0102, screenH * 0.5560, screenW * 0.0256, screenH * 0.0456},
    {screenW * 0.0102, screenH * 0.4935, screenW * 0.0256, screenH * 0.0456},
    {screenW * 0.0102, screenH * 0.4310, screenW * 0.0256, screenH * 0.0456},
    {screenW * 0.0102, screenH * 0.3685, screenW * 0.0256, screenH * 0.0456},
    {screenW * 0.0102, screenH * 0.3060, screenW * 0.0256, screenH * 0.0456},
}

posText = {
    {screenW * 0.0432, screenH * 0.6758, screenW * 0.1852, screenH * 0.7331},
    {screenW * 0.0432, screenH * 0.6133, screenW * 0.1852, screenH * 0.6706},
    {screenW * 0.0432, screenH * 0.5508, screenW * 0.1852, screenH * 0.6081},
    {screenW * 0.0432, screenH * 0.4883, screenW * 0.1852, screenH * 0.5456},
    {screenW * 0.0432, screenH * 0.4258, screenW * 0.1852, screenH * 0.4831},
    {screenW * 0.0432, screenH * 0.3633, screenW * 0.1852, screenH * 0.4206},
    {screenW * 0.0432, screenH * 0.3008, screenW * 0.1852, screenH * 0.3581},
}

addEventHandler("onClientRender", root, function()
    for i, v in pairs(infos) do
        if i == tipo then
            local length = dxGetTextWidth(msg, 1, font)
            dxDrawRectangle(posRectangle[1][1], posRectangle[1][2], length + screenW/23, posRectangle[1][4], tocolor(10, 10, 10, 220), false)
            dxDrawImage(posIMG[1][1], posIMG[1][2], posIMG[1][3], posIMG[1][4], infos[i][4], 0, 0, 0, tocolor(infos[i][1], infos[i][2], infos[i][3], 255), false)
            dxDrawText(msg, posText[1][1], posText[1][2], posText[1][3], posText[1][4], tocolor(255, 255, 255, 255), 1.00, font, "left", "center", false, false, false, false, false)
            break
        end
    end
end)

*As string tipo e msg é apenas para teste.

Eu fiz um sistema parecido com isso que era um log de mortes, tipo do Counter-strike, sempre que alguém matava, exibia pra todos em uma certa área quem matou, se foi HS e a arma.

Recomendo que você faça uma função pra cada texto e verifique: se o texto 1 estiver ativo, chame a função do texto 2, se a função do texto 2 estiver ativa, chame a função do texto 3 e assim em diante... Já que o número de textos é limitado, acho que esse é o jeito mais simples. Se não te atender deixa aí uma resposta de como posso ajudar...

Edited by Boechat
  • Like 1
Link to comment
On 09/11/2020 at 10:08, Boechat said:

Acho que isso não vai mudar nada, só vai fazer sumir e reaparecer a mensagem que estava na tela (vai ser tão rápido que será imperceptível)

Eu fiz um sistema parecido com isso que era um log de mortes, tipo do Counter-strike, sempre que alguém matava, exibia pra todos em uma certa área quem matou, se foi HS e a arma.

Recomendo que você faça uma função pra cada texto e verifique: se o texto 1 estiver ativo, chame a função do texto 2, se a função do texto 2 estiver ativa, chame a função do texto 3 e assim em diante... Já que o número de textos é limitado, acho que esse é o jeito mais simples. Se não te atender deixa aí uma resposta de como posso ajudar...

Sim, eu pensei nessa possibilidade mas achei que poderia encontrar alguma maneira mais simples, mas pelo visto esse é o único jeito. Obrigado ;) 

Link to comment
7 hours ago, ber said:

Sim, eu pensei nessa possibilidade mas achei que poderia encontrar alguma maneira mais simples, mas pelo visto esse é o único jeito. Obrigado ;) 

Você também pode colocar condições dentro da função dx, por exemplo: 

function dx ()
  	--TODO O CÓDIGO 
  	--QUE É COMUM 
  	--ENTRE AS JANELAS
	if janelaAtual == 'ligacoes' then
    	--CODIGO DA JANELA DE LIGACOES
    elseif janelaAtual == 'mensagens' then
  		--CODIGO DA JANELA DE MENSAGENS
  	end
end
addEventHandler('onClientRender', root, dx)

Eu fiz isso com um inventário que eu criei, já que tinha muitas coisas iguais entre as abas de comida, drogas e tal...

Link to comment

Na verdade vocês estão interpretando o sistema errado.

Para voce criar um sistema onde pode aparecer uma lista de mensagens, primeiramente voce deve salvar estas mensagens em uma lista. Depois disso para voce deve montar um o dx das mensagens dentro de um FOR para que consiga atualizar as posicoes do dx confome à lista.

Com isso voces conseguem fazer a lista de um tamanho infinito e garantir que o usuario veja todas as mensagens, da forma que voces pensaram pode ocorrer de sobre a mensagem ou até nao formar uma lista.

local sx,sy = guiGetScreenSize()
notify = {
	cache = {},
	tick = getTickCount(),
	create = function(type,img,title,msg)
				if type and img and title and msg then
					notify.tick = getTickCount(),
					table.insert(notify.cache,1,{type=type,img=img,title=title,msg=msg,posX=sx,posY=-resY(60),alpha=1,tick=getTickCount()})
				end
			end,
	render = function()
				for i,info in ipairs(notify.cache) do
					local progress = math.min((getTickCount()-notify.tick)/1500,1)
					local pg2 = 0
					if progress >= 1 then
						pg2 = math.min((getTickCount()-(notify.tick+1500))/1500,1)
					end
					local check = getTickCount()-info.tick
					local posY = resY(61)*i-resY(61)+resY(5)
					local w = dxGetTextWidth(info.msg:gsub("#%x%x%x%x%x%x",""),1,createFont("default",12),false)+resX(25)
					local _w = resX(180)
					local h = resY(52)
					if w < _w then
						w = _w
					end
					info.posX,info.posY = interpolateBetween(info.posX,info.posY,0,sx-w-resY(5),posY,0,progress,"Linear")
					if progress == 1 and check >= 7000 then
						local progress = math.min((check-7000)/1500,1)
						info.alpha = interpolateBetween(info.alpha,0,0,0,0,0,progress,"Linear")
						if info.alpha <= 0.1 then
							table.remove(notify.cache,i)
						end
					end
					if info.type == "error" then
						r,g,b = 255,0,0
						--playSound("files/error_notification.mp3")
					elseif info.type == "info" then
						r,g,b = 255,255,255
						--playSound("files/notification.mp3")
					elseif info.type == "success" then
						r,g,b = 0,255,0
						--playSound("files/success_notification.mp3")
					elseif info.type == "warning" then
						r,g,b = 255,190,0
						--playSound("files/warning_notification.mp3")
					else
						r,g,b = 255,255,255
						--playSound("files/error_notification.mp3")
					end
					-- background
					dxDrawImageSection(info.posX,info.posY,w,h,10,10,1,1,"img/border.png",0,0,0,tocolor(0,0,0,220*info.alpha),true) -- backgroud
					-- img bell
					dxDrawImage(info.posX+resY(5)-resX(7)*pg2,info.posY+resY(5)-resY(7)*pg2,resX(13)+resX(13)*pg2,resY(13)+resX(13)*pg2,"img/bell.png",0,0,0,tocolor(255,255,255,(220-220*pg2)*info.alpha),true)
					dxDrawImage(info.posX+resY(5),info.posY+resY(5),resX(13),resY(13),"img/bell.png",0,0,0,tocolor(255,255,255,220*info.alpha),true)
					-- title
					dxDrawText(info.title:upper(),info.posX+resX(25)+1,info.posY+resY(5)+1,info.posX+resX(1)+w-resX(3)+1,info.posY+resY(61)+1,tocolor(0,0,0,220*info.alpha),1,createFont("default",14),"left","top",true,false,true,true)
					dxDrawText(info.title:upper(),info.posX+resX(25),info.posY+resY(5),info.posX+resX(1)+w-resX(3),info.posY+resY(61),tocolor(240,240,240,220*info.alpha),1,createFont("default",14),"left","top",true,false,true,true)
					-- msg
					dxDrawText(info.msg:gsub("#%x%x%x%x%x%x","#000000"),info.posX+resX(25)+1,info.posY+resY(30)+1,info.posX+resX(1)+w-resX(3)+1,info.posY+resY(61)+1,tocolor(0,0,0,220*info.alpha),1,createFont("default",12),"left","top",true,false,true,true)
					dxDrawText(info.msg,info.posX+resX(25),info.posY+resY(30),info.posX+resX(1)+w-resX(3),info.posY+resY(61),tocolor(255,255,255,220*info.alpha),1,createFont("default",12),"left","top",true,false,true,true)
					--border
					dxRectangleLine(info.posX,info.posY,w,h,tocolor(r,g,b,20*info.alpha),true)
				end
			end
}

addEventHandler("onClientRender",root,notify.render)
function createNotification(type,img,title,msg)
    notify.create(type,img,title,msg)
end
addEvent("createNotification",true)
addEventHandler("createNotification",root,createNotification)

Não teste este código, pois ele não vai funcionar no seu sistema, mas a lógica de criação da mensagem que você deve implementar é a mesma.

Duvidas só manda é nois.

 

Link to comment
1 hour ago, Gw8 said:

Na verdade vocês estão interpretando o sistema errado.

Para voce criar um sistema onde pode aparecer uma lista de mensagens, primeiramente voce deve salvar estas mensagens em uma lista. Depois disso para voce deve montar um o dx das mensagens dentro de um FOR para que consiga atualizar as posicoes do dx confome à lista.

Com isso voces conseguem fazer a lista de um tamanho infinito e garantir que o usuario veja todas as mensagens, da forma que voces pensaram pode ocorrer de sobre a mensagem ou até nao formar uma lista.


local sx,sy = guiGetScreenSize()
notify = {
	cache = {},
	tick = getTickCount(),
	create = function(type,img,title,msg)
				if type and img and title and msg then
					notify.tick = getTickCount(),
					table.insert(notify.cache,1,{type=type,img=img,title=title,msg=msg,posX=sx,posY=-resY(60),alpha=1,tick=getTickCount()})
				end
			end,
	render = function()
				for i,info in ipairs(notify.cache) do
					local progress = math.min((getTickCount()-notify.tick)/1500,1)
					local pg2 = 0
					if progress >= 1 then
						pg2 = math.min((getTickCount()-(notify.tick+1500))/1500,1)
					end
					local check = getTickCount()-info.tick
					local posY = resY(61)*i-resY(61)+resY(5)
					local w = dxGetTextWidth(info.msg:gsub("#%x%x%x%x%x%x",""),1,createFont("default",12),false)+resX(25)
					local _w = resX(180)
					local h = resY(52)
					if w < _w then
						w = _w
					end
					info.posX,info.posY = interpolateBetween(info.posX,info.posY,0,sx-w-resY(5),posY,0,progress,"Linear")
					if progress == 1 and check >= 7000 then
						local progress = math.min((check-7000)/1500,1)
						info.alpha = interpolateBetween(info.alpha,0,0,0,0,0,progress,"Linear")
						if info.alpha <= 0.1 then
							table.remove(notify.cache,i)
						end
					end
					if info.type == "error" then
						r,g,b = 255,0,0
						--playSound("files/error_notification.mp3")
					elseif info.type == "info" then
						r,g,b = 255,255,255
						--playSound("files/notification.mp3")
					elseif info.type == "success" then
						r,g,b = 0,255,0
						--playSound("files/success_notification.mp3")
					elseif info.type == "warning" then
						r,g,b = 255,190,0
						--playSound("files/warning_notification.mp3")
					else
						r,g,b = 255,255,255
						--playSound("files/error_notification.mp3")
					end
					-- background
					dxDrawImageSection(info.posX,info.posY,w,h,10,10,1,1,"img/border.png",0,0,0,tocolor(0,0,0,220*info.alpha),true) -- backgroud
					-- img bell
					dxDrawImage(info.posX+resY(5)-resX(7)*pg2,info.posY+resY(5)-resY(7)*pg2,resX(13)+resX(13)*pg2,resY(13)+resX(13)*pg2,"img/bell.png",0,0,0,tocolor(255,255,255,(220-220*pg2)*info.alpha),true)
					dxDrawImage(info.posX+resY(5),info.posY+resY(5),resX(13),resY(13),"img/bell.png",0,0,0,tocolor(255,255,255,220*info.alpha),true)
					-- title
					dxDrawText(info.title:upper(),info.posX+resX(25)+1,info.posY+resY(5)+1,info.posX+resX(1)+w-resX(3)+1,info.posY+resY(61)+1,tocolor(0,0,0,220*info.alpha),1,createFont("default",14),"left","top",true,false,true,true)
					dxDrawText(info.title:upper(),info.posX+resX(25),info.posY+resY(5),info.posX+resX(1)+w-resX(3),info.posY+resY(61),tocolor(240,240,240,220*info.alpha),1,createFont("default",14),"left","top",true,false,true,true)
					-- msg
					dxDrawText(info.msg:gsub("#%x%x%x%x%x%x","#000000"),info.posX+resX(25)+1,info.posY+resY(30)+1,info.posX+resX(1)+w-resX(3)+1,info.posY+resY(61)+1,tocolor(0,0,0,220*info.alpha),1,createFont("default",12),"left","top",true,false,true,true)
					dxDrawText(info.msg,info.posX+resX(25),info.posY+resY(30),info.posX+resX(1)+w-resX(3),info.posY+resY(61),tocolor(255,255,255,220*info.alpha),1,createFont("default",12),"left","top",true,false,true,true)
					--border
					dxRectangleLine(info.posX,info.posY,w,h,tocolor(r,g,b,20*info.alpha),true)
				end
			end
}

addEventHandler("onClientRender",root,notify.render)
function createNotification(type,img,title,msg)
    notify.create(type,img,title,msg)
end
addEvent("createNotification",true)
addEventHandler("createNotification",root,createNotification)

Não teste este código, pois ele não vai funcionar no seu sistema, mas a lógica de criação da mensagem que você deve implementar é a mesma.

Duvidas só manda é nois.

 

Teria um problema ter mensagens "ilimitadas" porque pode ficar um spam enorme da tela do jogador né, acho que o ideial (foi o que eu fiz no mod que mencionei acima de log de morte) seria colocar um limite e ir subindo as mensagens, por exemplo:

Limite 5 mensagens

1 = oi

2 = sucesso

3 = abobrinha

4 = jujuba 

5 = foda-se

se chegar uma 6° mensagem "churreia", excluir a 1° mensagem e fazer uma substituição recursiva , ficando:

1 = sucesso

2 = abobrinha

3 = jujuba 

4 = foda-se

5 = churreia

  • Haha 1
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...