Jump to content

Recommended Posts

  • Other Languages Moderators

Eae pessoal. Estou com uma dúvida rápida aqui.
Estou fazendo um sistema de level, nesse sistema existe um verificador server-side que verifica todos os jogadores a cada 1 segundo procurando por players AFK para pausar o Up do level.
Até então sem problemas, mas estou querendo colocar o tempo do up de cada jogador aparecer na tela deles, qual procedimento a seguir é MAIS LEVE para fazer isso?

  1. cria uma variável, salva o tempo nela e triggerClientEvent a cada 1 segundo, para enviar essa variável atualizada ao cliente.
  2. setElementData no jogador a cada 1 segundo, então o client irá sempre mostrar essa data na tela dele.
  3. setAccountData no jogador a cada 1 segundo. [Já vi que é inviável fazer assim, até porque não há como receber esse valor client-side]
  4. fazer o próprio client calcular o tempo de up?

A propósito, o timer em si é este: (server-side)

Spoiler

globalTimer = setTimer (function () -- Executa isso tudo a cada 1 segundo.
	for theKey, thePlayer in ipairs (getElementsByType ("player")) do -- Para cada jogador no server, faz isso:
		if not getElementData (thePlayer, "AFK") then -- Se o jogador não estiver AFK, então:
			local now = getTickCount () -- variável now, recebe o momento atual.
			local account = getPlayerAccount (thePlayer) -- variável account recebe a conta do jogador logado atualmente.
			if not isGuestAccount (account) then -- Se a conta dele não for deslogado, então:
				if (getPlayerIdleTime(thePlayer) >= 300000) then -- 5 min. Se o jogador estiver parado por mais de 5 minutos, então:
					triggerClientEvent (thePlayer, "showAFK", getRootElement()) -- Mostra mensagem de AFK na tela do jogador. (e lá, seta data "AFK" no jogador)
					setAccountData (account, "levelTimeLapsed", (getTickCount() - playerExpStart[thePlayer]) + getAccountData (account, "levelTimeLapsed")) -- Salva o up atual na conta do jogador. (momento atual - momento que começou a upar + tanto de tempo up que ele já tinha na conta)
				else -- Se o jogador não estiver AFK, então:
					playerLapsed[thePlayer] = now - playerExpStart[thePlayer] + getAccountData (account, "levelTimeLapsed") -- variável playerLapsed recebe o momento atual - o momento que começou a upar + o que ele já tem upado na conta.
					if playerLapsed[thePlayer] >= (60000 * tonumber (get ("minuteExp"))) then -- 720000 -- Se o tempo upado ao total passar de 12 minutos, então: (minuteExp = 12 na configuração)
						if playerExp[thePlayer] < 5 then -- O jogador upa de level ao atingir 5 de Exp, se o Exp atual for menor que 5, então:
							playerExp[thePlayer] = playerExp[thePlayer] + 1 -- Aumenta o Exp em 1 e mostra mensagem pra ele dizendo quanto de Exp ele tem agora.
							outputChatBox ("Você ganhou #00FF00+1 de Experiência#FFFFFF. Você tem agora #00FF00"..playerExp[thePlayer].."#FFFFFF /#00FF00 5#FFFFFF pontos de experiência.", thePlayer, 255, 255, 255, true)
						end
						if playerExp[thePlayer] == 5 then -- Se logo depois dele receber o Exp ele ficar com 5, então:
							playerExp[thePlayer] = 0 -- Zera o Exp dele.
							playerLevel[thePlayer] = playerLevel[thePlayer] + 1 -- Aumenta o level dele em 1.
							setElementData (thePlayer, "level", playerLevel[thePlayer]) -- Salva o novo level na conta do jogador. (isso acontece a cada 1 hora por padrão)
							outputChatBox ("Você avançou de nível! Seu nível agora é "..playerLevel[thePlayer]..".", thePlayer, 0, 255, 0, true) -- Avisa isso pra ele, dizendo quanto de level ele tem agora.
						end
						playerExpStart[thePlayer] = now -- Recomeça o tempo Up, setando o momento atual.
						setAccountData (account, "levelTimeLapsed", 0) -- Salva o tempo de Up em 0 na conta do jogador, já que ele está começando a upar um novo Exp.
					end
				end
			end
		end
	end
end, 1000, 0)

function continueUp () -- Executa isso no jogador depois q ele sai do AFK. 
	playerExpStart[client] = getTickCount() -- playerExpStart passa a ser o momento atual. (não é 0)
end
addEvent ("restaureLapse", true)
addEventHandler ("restaureLapse", getRootElement(), continueUp)

 

No script client, deverá ter um onClientRender que deverá mostrar o playerLapsed ao jogador. (só que no client, irá formatar os milisegundos em minutos/segundos.)

Edited by Lord Henry
Link to comment
  • Moderators

Pelo que eu vi, no loop, você verifica na 3ª linha se o jogador não está AFK para que o código prossiga. Por que você está fazendo outra checagem de 5 minutos inativo então? O AFK do element-data funciona de outra forma?

Dito isso, indo ao problema, creio que o que mais te impede de fazer o código de uma forma mais eficiente e organizada, é estar misturando essa verificação de AFK junto com o sistema de level dentro desse loop global.

Fiz aqui um código que você pode usar para a verificação da inatividade dos jogadores:

addEventHandler( "onResourceStart", resourceRoot, 
	function()
		setTimer( startMonitoringPlayers, 10000, 0 )
	end
)

function startMonitoringPlayers()
	for _, player in pairs( getElementsByType("player") ) do
		local acc = getPlayerAccount(player)
		if not isGuestAccount(acc) and isPlayerAFK( player ) and getElementData( player, "playerAFKState" ) ~= true then
			setElementData( player, "playerAFKState", true )
		elseif not isGuestAccount(acc) and isPlayerAFK( player ) ~= true and getElementData( player, "playerAFKState" ) then
			setElementData( player, "playerAFKState", false )
		end
	end
end

function isPlayerAFK( player )
	if isElement(player) then
		return ( getPlayerIdleTime( player ) >= 300000 )
	end
	return false
end

Com o element-data atualizado para sincronizar com o client, você pode usá-lo no outro lado pra caso precisse. Na pior das hipóteses, vai demorar 10 segundos pra detectar o estado do jogador, mas você poder colocar um tempo mais baixo se achar conveniente.

Percebi também que você pausa o progresso do level quando fica inativo por 5 minutos. Você pode colocar no lugar do setElementData uma tabela individual e quando detectar se o jogador ficou AFK ou voltou ao jogo você pode colocar o triggerClientEvent que você usou na linha 9 do seu código.

Nessa chamada ao client, você pode saber no lado do client quando ele fica AFK e quando volta, acho que com essas informações, você pode fazer o código do level no lado client.

 

Link to comment
  • Other Languages Moderators

Então... na verdade quando o jogador fica AFK. Ele ativa uma função no cliente do jogador que irá gerar um código e mostrar na tela do jogador para que ele digite pra poder sair do AFK. Quando ele usar o código, vai se movimentar 0.01 posição pro lado, para reiniciar o getPlayerIdleTime e então seta a data "AFK" false no jogador. O objetivo é justamente fazer o jogador não querer ficar AFK. Se o jogador se mover sem acertar o código, a data "AFK" vai continuar lá e ele vai continuar bloqueado de upar até que digite o código que está mostrando na tela.

E eu coloquei verificador duplo de AFK ali no timer pois não quero q ele fique ativando o cliente a cada segundo, ele só deve ativar 1 vez e esperar o jogador desativá-lo.

Edited by Lord Henry
Link to comment
  • Moderators

Ah sim, agora entendi. Tem esta função útil que acredito que seja a mesma coisa que getPlayerIdleTime e você pode usar no lado client:

function isElementMoving (theElement )
   if isElement ( theElement ) then                                   -- First check if the given argument is an element
      return Vector3( getElementVelocity( theElement ) ).length ~= 0
   end
   return false
end

Como eu disse na outra resposta, você pode fazer o level no lado client também.

Link to comment
  • Other Languages Moderators

Mas e quando o jogador sair do servidor? Como eu vou fazer pra salvar os dados na conta dele? Faço um triggerClientEvent pra que o cliente envie os dados ao servidor usando um triggerServerEvent?

Estou usando isso para salvar os dados quando o resource para. Também faço isso quando o jogador da Quit ou desloga.
 

function saveAllLevels ()
	for theKey, thePlayer in ipairs (getElementsByType ("player")) do
		local acc = getPlayerAccount (thePlayer)
		if not isGuestAccount (acc) then
			setAccountData (acc, "level", playerLevel[thePlayer]) -- Variáveis que estou usando para guardar os dados o tempo todo.
			setAccountData (acc, "levelExp", playerExp[thePlayer])
			setAccountData (acc, "levelTimeLapsed", playerLapsed[thePlayer])
		end
	end
end
addEventHandler ("onResourceStop", getResourceRootElement(getThisResource()), saveAllLevels)

 

Link to comment
  • Moderators

Sim. onClientResourceStop + triggerServerEvent e envia os dados pra serem salvos na conta. onClientResourceStop vai funcionar substituindo os dois eventos do lado server - onPlayerQuit e onResourceStop.

Quando sair da conta, você pode usar onPlayerLogout mesmo e chamar um evento no client para salvar os dados chamando outro evento do lado server.

Edited by DNL291
Link to comment

fiz essa parte do client, só nao testei, nao tive tempo.

-- afk por ficar parado
local x,y = guiGetScreenSize()
local afk = {
	x = 0,
	y = 0,
	z = 0,
	tick = getTickCount(),
	state = false
}

function drawAfkMsg()
	dxDrawText("You Are AFK!",0,0,x,y,tocolor(255,255,255,255),1,"default","center","center",true)
end

function startAfk()
	local x,y,z = getElementPosition(localPlayer)
	if afk.x == x and afk.y == y and afk.z == z then
		local now = getTickCount() - afk.tick
		if now >= 10000 then
			if not afk.state then
				afk.state = true
				setElementData(localPlayer,"posAFK",true)
				removeEventHandler("onClientRender",root,drawAfkMsg)
				addEventHandler("onClientRender",root,drawAfkMsg)
			end
		end
	else
		clearAfk()
	end
end

function clearAfk()
    removeEventHandler("onClientRender",root,drawAfkMsg)
	local x,y,z = getElementPosition(localPlayer)
	setElementData(localPlayer,"posAFK",false)
	afk.x = x
	afk.y = y
	afk.z = z
    afk.tick = getTickCount()
	afk.state = false
end
setTimer(startAfk,1000,0)

-- afk por sair do jogo
addEventHandler("onClientMinimize",root,
function()
	setElementData(localPlayer,"tabAFK",true)
end
)

addEventHandler("onClientRestore",root,
function()
	setElementData(localPlayer,"tabAFK",false)
end
)

 

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...