Other Languages Moderators Lord Henry Posted February 12, 2018 Other Languages Moderators Share Posted February 12, 2018 (edited) 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? cria uma variável, salva o tempo nela e triggerClientEvent a cada 1 segundo, para enviar essa variável atualizada ao cliente. setElementData no jogador a cada 1 segundo, então o client irá sempre mostrar essa data na tela dele. 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] 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 February 12, 2018 by Lord Henry Link to comment
DNL291 Posted February 13, 2018 Share Posted February 13, 2018 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 Lord Henry Posted February 13, 2018 Author Other Languages Moderators Share Posted February 13, 2018 (edited) 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 February 13, 2018 by Lord Henry Link to comment
DNL291 Posted February 13, 2018 Share Posted February 13, 2018 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 Lord Henry Posted February 13, 2018 Author Other Languages Moderators Share Posted February 13, 2018 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
DNL291 Posted February 13, 2018 Share Posted February 13, 2018 (edited) 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 February 13, 2018 by DNL291 Link to comment
DNL291 Posted February 13, 2018 Share Posted February 13, 2018 Como está indo o script? @Lord Henry Link to comment
Other Languages Moderators Lord Henry Posted February 14, 2018 Author Other Languages Moderators Share Posted February 14, 2018 (edited) Ainda estou tentando fazer client-side. Estou tendo que mudar a lógica de tudo, passar todas as variáveis pro client. Edited February 14, 2018 by Lord Henry Link to comment
Gw8 Posted February 14, 2018 Share Posted February 14, 2018 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
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now