Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 14/12/20 in Posts

  1. Debugging Do you know what debugging is? You might think you do, but unfortunately (in my opinion) only ~15% of the scripters in the community do know the full definition of it. Many people think that debugging code is the same as looking in to the Debug Console and waiting for warning + errors to show up. That's indeed debugging and yet it never provide all information you need to build your scripts. It only can say what goes wrong at a certain line. With other words, the Debug Console by default will only show a limited amount of mistakes you have made in your code. So what is next? You fixed all warnings and errors and yet it doesn't work. You start with making your code visible! I guess 70% would think: Making code visible? Ehhh how??? Let me write it down a little bit different: By using Debug Information making the behaviour of the code visible. I guess 50% would think: Eh what? behaviour of code????? Let me give you an example. Example: (1) outputDebugString("the script has started") -- < this is a debug line if true then outputDebugString("code works here") -- < this is a debug line else outputDebugString("code shouldn't be working here") -- < this is a debug line end Debug console "the script has started" "code works here" The debug console is NOT information for players, it is information for YOU developers! BTW this is a debug line outputDebugString("test") -- < this is a debug line In this case it is just a piece of code that shows information in the debug console. Example: (2) local playerName1 = "snake1" local playerName2 = "cow" if playerName1 == playerName2 then outputDebugString("players playerName1 and playerName2 do share the same name. Name: " .. tostring(playerName1)) -- < this is a debug line else outputDebugString("players playerName1 and playerName2 do NOT share the same name. playerName1: " .. tostring(playerName1) .. ", playerName2: " .. tostring(playerName2)) -- < this is a debug line end Debug console "players playerName1 and playerName2 do NOT share the same name. playerName1: snake1, playerName2: cow" Easy isn't? The concept behind this debug method is to see what the code does / doesn't execute. Is this method handy? It is actually the very basic of debugging, for code that doesn't contain any errors/warnings. I would say it is handy and it is a very powerful method too. It is also handy for people who do not know how to script. If you want people to help you with your code, but you do not know what is wrong with it. You can add those debug lines and point out to where the code stops working. This will make it more efficient for you and the scripter to work out the problem, because the scripter knows where to look. How much debug lines do you have to add to your script? 1? 10? 100? 1000? You could start with around 100 debug lines and as you learn how to script, you can reduce it to 10+ debug lines. Too much debug lines are not always good, because they will give you too much information and it will cost time to manually filter them. So I recommend you to remove some of them afterwards. When you are finished with the tested code, you can remove 90+% of them. Feel free to disable them instead of removing them, if you know that you are going to need them again. For complex code, I use around 25 debug lines, SO DON'T HOLD BACK! Render events It is strongly recommended to remove debug lines that are executed on onClientRender/render events when you are finished with your code. Because that can have influence on the smooth fps.(It will not drop much of the fps, but it can make it feel unsmooth) Clearing the debug console? /cleardebug Know your tools: outputDebugString -- Show a message on the Debug Console bool outputDebugString ( string text, [ int level=3, int red=255, int green=255, int blue=255 ] ) --- outputConsole -- Show a message on the F8 panel. bool outputConsole ( string text ) -- client bool outputConsole ( string text, [ element visibleTo=getRootElement() ] ) -- server --- inspect -- Convert one mixed value to a string. string inspect ( mixed var ) --- print -- Show a message on the terminal / serverwindow / Debug Console. bool print ( string var1[, string var2, string var3...] ) --- tostring() -- Convert a value in to a string. (but for objects/elements, inspect works better) --- iprint -- Show a message on the terminal / serverwindow / Debug Console (convert multiple mixed values automatic to string, no need for tostring or inspect) bool iprint ( mixed var1[, mixed var2, mixed var3...] ) --- outputChatBox -- You can also debug with outputChatBox (even though it is less efficient) bool outputChatBox ( string text [, int r=231, int g=217, int b=176, bool colorCoded=false ] ) -- client bool outputChatBox ( string text [, element visibleTo=getRootElement(), int r=231, int g=217, int b=176, bool colorCoded=false ] ) -- server Debug message levels 0: Custom message 1: Error message 2: Warning message 3: Information message (default) Addition by @Hale https://wiki.multitheftauto.com/wiki/OutputDebugString Advanced tools: local line = debug.getinfo(1).currentline -- get the line of the script where the code has been executed. 1 = current function. (can be useful if you want to get the line where this function has been called from) https://www.lua.org/pil/23.1.html WIKI MTA: WIKI MTA debugging tutorial/information. https://wiki.multitheftauto.com/wiki/Debugging
    1 point
  2. We have an announcement to make regarding certain services and technologies, like "Cloud Gaming" platforms and various cloud / cloud VM and hypervisor based services and software. Unfortunately, the majority of such services can no longer be used with MTA starting today. After observing a growing trend of abuse, such as server ban evading (serials related) we have enabled the same type of security, known as MTA serial verification - which usually applies to the most common consumer VM software - to all VM types and cloud services that we know of. This means that the procedure from https://updatesa.multitheftauto.com/sa/trouble/?tr=serial-validation must be followed on all relevant services, not just the aforementioned. Because most cloud & VM hosting services won't provide users access to the host machine (that hosts the VM), we expect that most "cloud gaming" users will no longer be able to play MTA using said service. Not that MTA is an attractive game to play in cloud gaming though, we advise you to use MTA like a normal user (on your own PC) and understand that we care about servers being able to reliably ban players. Cloud gaming, for instance.. would constantly offer you a new so-called environment, allowing infinite serial swaps, making you hard to ban. It's possible for some people still being able to use relevant services, as these measures will only apply to newly generated MTA serials (not retroactively). This is intended. This topic is also relevant to the "There was a problem validating your serial" error and "Banned by MTA" with reason PROHIBITED VM TYPE / SECURITY VIOLATION
    1 point
  3. Olá pessoal, hoje vamos falar de algo que destrói a cabeça de novatos no MTA: Quando e onde devo usar source? Então vamos a primeira pergunta que surge, mas o que diabos é source no MTA? source nada mais é do que: parâmetro determinado por uma função ou evento. Você agora você deve estar perguntando o que é parâmetro. É muito simples, pense comigo na função addCommandHandler. Ela tem 2 parâmetros predeterminados que são (Quem_Executou, Nome_Do_Comando), como na imagem abaixo: Como você pode ver na imagem, ela tem os 2 parâmetros citados acima. Lembrando que: a própria wiki fala sobre os parâmetros. playerSource: O jogador que acionou o comando ou o console do servidor. Se não for acionado por um jogador (por exemplo, por administrador) ou console de servidor, isso será falso. commandName: O nome do comando que foi acionado. Isso é útil se vários comandos passarem por uma mesma função. Mesmo o parâmetro sendo predeterminado, você pode botar o nome que você quiser, por ex: O parâmetro de quem executou o comando é playerSource, mas você pode botar qualquer nome como: p, player, sujeito, shuppinga e etc.... da mesma maneira o commandName (nome do comando), você pode botar (nome_do_comando, comando). Como você prefere. (mas é claro, siga um padrão a qual os outros programadores possam entender seu código !!) _____________________________________________________________ Mas quando devo usar source então? Simples, quando não existe o parâmetro que indique o sujeito. Por exemplo, o evento onPlayerWasted. O evento onPlayerWasted tem o seguintes parâmetros: totalAmmo - A munição total que a vitima tinha quando morreu, killer - O assassino que matou a vitima, killerWeapon - O id da arma do assassino, bodyPart - A parte do corpo da vítima que foi atingida quando ela morreu, stealth - Um valor booleano representando se esta foi ou não uma morte furtiva. Note que não existe o parâmetro vítima. Então aqui que entra o source. Mas como saber o que é o source? A própria wiki diz, basta ler A source deste evento é o jogador que morreu ou foi morto. Então o tutorial fica por aqui :), bye bye. (lembrando que essas fontes são próprias, então pode ser um conteúdo incorreto, mas espero ter ajudado a tirar a dúvida, lembrando que ela pode ser corrigida por alguém de bom conhecimento sobre do conteúdo.)
    1 point
  4. Assim está melhor. function getPlayerID(id) v = false for i, player in ipairs (getElementsByType("player")) do if getElementData(player, "ID") == id then v = player break end end return v end function playerHasItem(player, itemID) for i, v in pairs(getElementData(player, 'TS:InventarioInfo')) do if type(v) == 'table' then if v['Item'] == tonumber(itemID) then return true end end end return false end function returnQntdItem(player, itemID) if (player) then for i, v in pairs(getElementData(player, "TS:InventarioInfo")) do if (type(v) == "table") then if (v['Item'] == tonumber(itemID)) then return v['Quantidade'] end end end end return false end function verificarDistancia (player, abordado) if player and abordado then local x,y,z = getElementPosition(player) local x2,y2,z2 = getElementPosition(abordado) local distancia = getDistanceBetweenPoints3D(x,y,z,x2,y2,z2) if distancia then return distancia end end end local itens = { [10] = "Bandeide(s)", [11] = "Kit(s) de Reparo", [12] = "Maconha(s)", [13] = "Armamento(s) AK-47", [14] = "Munição(ões) 762", [15] = "Armamento(s) FALL", [16] = "Munição(ões) 762", -- Repete mesmo? [17] = "Armamento(s) MP5", [18] = "Munição(ões) 9mm", [19] = "Armamento(s) TEC-9", [20] = "Armamento(s) UZI", [21] = "Armamento(s) Revólver-38", [22] = "Armamento(s) Glock", [23] = "Munição(ões) 45", [24] = "Faca(s)", [25] = "Armamento(s) AK-47-VIP", [26] = "Armamento(s) AK-47-VIP", -- Repete mesmo? [27] = "Munição(ões) Sniper", [28] = "Armamento(s) AWP-VIP", [30] = "Colete(s)", [31] = "Dinheiro Sujo(s)", [32] = "Galão(ões)", [33] = "Lockpick(s)", } function revista (thePlayer, commandName, id) -- Não use source como parâmetro de função. if (tonumber(id)) then local targetPlayer = getPlayerID(tonumber(id)) if (targetPlayer) then if (verificarDistancia (thePlayer, targetPlayer) > 5) then -- Se a distância pro jogador for maior que 5, manda o feedback e nada acontece. outputChatBox ("O jogador com este ID não está perto o suficiente para ser revistado.", thePlayer, 255, 150, 0) -- Sempre dê feedback em caso de erro. return end for i, item in pairs (itens) do -- Tabela de itens com seus ids indexados, pra não precisar entupir de if. if (playerHasItem (targetPlayer, i) == true) then outputChatBox ("✘#ffffffINFO#0037FF✘➺ #ffffff O Cidadão tem "..returnQntdItem (targetPlayer, i).." "..item.." em sua mochila!", thePlayer, 0, 55, 255, true) end end else outputChatBox ("Nenhum jogador com este ID foi encontrado.", thePlayer, 255, 150, 0) end else outputChatBox ("Sintaxe: /revistar <playerID>", thePlayer, 255, 150, 0) end end addCommandHandler ("revistar", revista) -- Não use o nome da função igual ao comando.
    1 point
  5. ss local distanciaMaxima = 5 function getPlayerID(id) v = false for i, player in ipairs (getElementsByType("player")) do if getElementData(player, "ID") == id then v = player break end end return v end function playerHasItem(player, itemID) for i, v in pairs(getElementData(player, 'TS:InventarioInfo')) do if type(v) == 'table' then if v['Item'] == tonumber(itemID) then return true end end end return false end function returnQntdItem(player, itemID) if (player) then for i, v in pairs(getElementData(player, "TS:InventarioInfo")) do if (type(v) == "table") then if (v['Item'] == tonumber(itemID)) then return v['Quantidade'] end end end end return false end function verificarDistancia(player, abordado) if player and abordado then local x,y,z = getElementPosition(player) local x2,y2,z2 = getElementPosition(abordado) local distancia = getDistanceBetweenPoints3D(x,y,z,x2,y2,z2) if distancia then return distancia end end end itemsTable = { -- item id, item name {10, 'Bandages'}, {11, 'Kits reparos'}, {12, 'Maconhas'}, {13, 'Armamentos de AK-47'}, {14, 'Munições de 762'}, {15, 'Munições de FALL'}, {16, 'Munições de 762'}, {17, 'Armamento de MP5'}, {18, 'Armamento de 9mm'}, {19, 'Armamento de TEC-9'}, {20, 'Armamento de Uzi'}, {21, 'Armamento de REVOLVER-38'}, {22, 'Armamento de GLOCK'}, {23, 'Armamento de 45'}, {24, 'Facas'}, {25, 'Armamentos de AK-47-VIP'}, {26, 'Armamentos de AWP'}, {27, 'Munições de Sniper'}, {28, 'Armamentos de AWP-VIP'}, {30, 'Coletes'}, {31, 'de Dinheiro Sujo'}, {32, 'Galoes de gasolina'}, {33, 'Lockpicks'}, } function revistar(source, commandName, id) if (id) then local playerID = tonumber(id) if (playerID) then local targetPlayer, targetPlayerName = getPlayerID(playerID) if (targetPlayer) then if verificarDistancia(source, targetPlayer) > 5 then return outputChatBox("#0037FF✘#ffffffERROR#0037FF✘➺ #ffffff Chegue mais perto do abordado!",source,255,0,0,true) end for i,v in ipairs( itemsTable ) do local item = returnQntdItem(source, v[1]) if playerHasItem(targetPlayer, v[1]) == true then outputChatBox("#0037FF✘#ffffffINFO#0037FF✘➺ #ffffff O Cidadão tem "..item.." "..v[2].." em sua mochila!",source,255,0,0,true) return end end end end end end addCommandHandler("revistar", revistar) Está aí amigo. Mas uma dica, melhore esse código, não tem necessidade fazer esse tanto de function sendo que dar para fazer em apenas 1, e outra dica é aprender a mexer com tabelas !. Espero te lhe ajudado.
    1 point
  6. تم تحديث اسعار وخطط خوادم اللينكس و خوادم الويندوز https://tapleto-host.net/ar/LinuxVPS.php https://tapleto-host.net/ar/WinVPS.php
    1 point
  7. Não. O mais próximo seriam esses: Client-side onClientObjectDamage - Evento ativado quando algum objeto próximo toma dano. onClientObjectBreak - Evento ativado quando algum objeto próximo é quebrado. Server-side onPlayerContact - Evento ativado sempre que o jogador começa a pisar em um elemento diferente do que ele estava pisando antes.
    1 point
  8. Pra criar um log, você precisa fazer com que o servidor escreva mensagens em um arquivo de texto. Vou dar um exemplo genérico de um log que marca o instante e o nick quando alguém usar o comando /ptr. (Script server-side.) addCommandHandler ("ptr", function (thePlayer, cmd, state) if (state == "iniciar" or state == "finalizar") then -- Verifica se o comando é seguido por um parâmetro válido. local name = getPlayerName (thePlayer) -- Obtém o nick de quem executou o comando. local horario = showTime() -- Obtém o horário atual do servidor por meio de uma função útil. if (fileExists ("logPTR.txt")) then -- Se já existe um arquivo de texto com este nome neste resource, então: newFile = fileOpen ("logPTR.txt") -- Abre o arquivo para poder editá-lo. fileSetPos (newFile, fileGetSize (newFile)) -- Coloca o cursor de escrita no fim do arquivo, caso contrário ele vai começar a escrever no começo dele, antes do que já estiver escrito no arquivo. if (state == "iniciar") then -- Se o parâmetro que o jogador usou após o comando foi "iniciar" então: outputChatBox ("Patrulha iniciada.", thePlayer) -- Apenas pra saber q o comando funcionou, normalmente teria as verificações antes de permissões e se já está em patrulha. fileWrite (newFile, "["..horario.."] "name.." Iniciou sua patrulha.\n") -- Escreve isso no documento. O \n pula para a linha seguinte após a mensagem. elseif (state == "finalizar") then outputChatBox ("Patrulha finalizada.", thePlayer) fileWrite (newFile, "["..horario.."] "name.." Finalizou sua patrulha.\n") end fileClose (newFile) -- Para todo fileOpen ou fileCreate, é necessário um fileClose pois enquanto arquivos estiverem abertos, eles podem ser corrompidos e os dados serão perdidos. else -- Se o arquivo ainda não existe, então: newFile = fileCreate ("logPTR.txt") -- Cria o arquivo de texto dentro deste resource e abre ele. (se já existisse um arquivo com esse nome, substituiria por um novo em branco) if (newFile) then -- Se conseguiu criar o arquivo, então: (as vezes pode dar erro de permissão no servidor, então use isso para evitar erros.) fileSetPos (newFile, fileGetSize (newFile)) if (state == "iniciar") then outputChatBox ("Patrulha iniciada.", thePlayer) fileWrite (newFile, "["..horario.."] "name.." Iniciou sua patrulha.\n") elseif (state == "finalizar") then outputChatBox ("Patrulha finalizada.", thePlayer) fileWrite (newFile, "["..horario.."] "name.." Finalizou sua patrulha.\n") end fileClose (newFile) else -- Se não conseguiu criar o arquivo, então: debug ("ERRO: Impossivel criar arquivo 'logPTR.txt' no servidor.") end end else -- Se não usou nenhum parâmetro após o comando ou então usou um parâmetro incorreto, então: outputChatBox ("Sintaxe: /ptr <iniciar / finalizar>", thePlayer, 255, 255, 0) end end) function showtime () -- Função que apenas retorna o horário atual. local time = getRealTime() local hours = time.hour local minutes = time.minute local seconds = time.second -- Make sure to add a 0 to the front of single digits. if (hours < 10) then hours = "0"..hours end if (minutes < 10) then minutes = "0"..minutes end if (seconds < 10) then seconds = "0"..seconds end return hours..":"..minutes..":"..seconds end Sobre a parte de tornar obrigatório a finalização da patrulha antes de começar outra, você tem 2 modos: Sete um elementData no jogador após ele iniciar uma patrulha. Sempre que ele tentar iniciar uma nova patrulha, verifique se ele já tem essa elementData. Se tiver, bloqueia e pede pra finalizar a patrulha atual. Ao finalizar uma patrulha, remove o elementData do jogador (setando o valor dela como false). Utilize tabelas. Quando alguém inicia uma patrulha, adiciona a conta dele na tabela e quando ele finaliza, remove ele da tabela. É mais leve do que elementData mas vc precisa adicionar verificadores de logout/quit/disconnect do servidor. Caso contrário o jogador pode sair do servidor e sua patrulha ainda vai estar ativa na tabela do resource. Além disso, todas as patrulhas são perdidas ao reiniciar o resource.
    1 point
  9. function isMouseInPosition ( x, y, width, height ) -- Função útil. Serve pra verificar se o mouse está dentro de determinada área ou não. if ( not isCursorShowing( ) ) then return false end local sx, sy = guiGetScreenSize ( ) local cx, cy = getCursorPosition ( ) local cx, cy = ( cx * sx ), ( cy * sy ) return ( ( cx >= x and cx <= x + width ) and ( cy >= y and cy <= y + height ) ) end addEventHandler ("onClientRender", root, function () dxDrawImage (x*400, y*100, x*233, y*214, "teste.png", 0, 0, 0, (isMouseInPosition (x*400, y*100, x*233, y*214) and tocolor (255, 255, 255, 240) or tocolor (255, 255, 255, 100))) end) -- O alpha do botão ficará em 240 quando o mouse estiver em cima da imagem e 100 quando não estiver.
    1 point
  10. O setPlayerTeam atribui um time ao player, lembrando que antes de setar você deve criar um time com o createTeam. O getPlayerTeam você pega o time do player, afim de comparação ou alguma checagem. Exemplo de uso: server-side local cv = createTeam ( "CV" , 255, 0, 0 ) local markerEntrarCV = createMarker ( 1213, -500, 13, "cylinder", 1.5, 255, 255, 0, 170 ) local markerChecarCV = createMarker ( 1213, -400, 13, "cylinder", 1.5, 255, 255, 0, 170 ) function setTeam (player, team) setPlayerTeam ( player, team ) outputChatBox ('Você entrou para '..getTeamName(team), player) end function checkTeam (player, team) local teamPlayer = getPlayerTeam (player) if teamPlayer == team then return true else outputChatBox ('Você não faz parte do '..getTeamName(team), player) end return false end addEventHandler ("onMarkerHit", markerEntrarCV, function(hitElement, matchingDimension) if isElement (hitElement) and getElementType(hitElement) == 'player' then setTeam (hitElement, cv) end end) addEventHandler ("onMarkerHit", markerChecarCV, function(hitElement, matchingDimension) if isElement (hitElement) and getElementType(hitElement) == 'player' then if checkTeam (hitElement, cv) then outputChatBox ('Você é do CV', hitElement) else outputChatBox ('Você não é do CV', hitElement) end end end) Lembrando que eu não testei, digitei tudo pelo fórum mesmo e nunca mexi com times também, pode haver algum errinho ou outro mas acho que assim funcionará, teste e qualquer coisa posta aí.
    1 point
×
×
  • Create New...