Search the Community
Showing results for tags 'tutorial'.
-
Hi!, my name is Laxante101, I'm a .Lua developer, And today I will try to help you understand SQlite WHAT IS SQLITE? SQLite is a relational database management system (RDBMS) that does not require a separate server to function. Unlike database systems like MySQL or PostgreSQL, which need an active server process, SQLite is "embedded" (that is, the database is stored in a local file on disk), and operations with they are made directly within the program that uses it. Luckily for us, SQLite is already built into the MTA. This means that you can use SQLite databases directly in your MTA Lua codes without having to install anything additional "external" or configure an external database server. SQLite support is native to MTA, facilitating the use of databases for persistent storage of in game information. It is normally used on servers that do not use the login panel, they use SQlite so their information that would be saved in accounts is now saved in the .db file. Or on servers that don't use the original game money, they create other types of “money” like diamonds, stars which are all saved every day, well that's usually the case IMPORTANT DETAILS • Simplicity: Doesn't require anything other than a notepad • Portabilidade: Data is stored in a single .db file, which makes backup and migration easier. SQlite Global Structure Connect to Database with dbConnect Execute Queries using dbExec to modify data and dbQuery to recover data. 3. Manipulate Results with dbPoll and process the returned data. Connection to the Database the database file can be created automatically when connecting. The database file is saved in the server's root folder. local db = dbConnect("sqlite", "storage.db") or if you want to automatically create a folder for your file, or to save your .db files, if it is not created it creates it automatically, if it is created it just puts the file in the path. local db = dbConnect("sqlite", "db/storage.db") in this case the "db" folder will be created Creating Tablese data, you first need to create tables in the database. This is done using normal SQL commands like consulta local = [[ CREATE TABLE IF NOT EXISTS players ( id INTEGER PRIMARY KEY AUTOINCREMENT , name TEXT , score INTEGER ) ]] dbExec ( db , query ) Create a player table if it doesn't already exist In this case, we are creating a players table with three columns: ID Name Score Table Structure TEXT: STRINGS INTEGER: STORAGE NUMBERS REAL:STORES FLOATING POINT NUMBERS BLOB: STORES BINARY DATA (images, files). NULL: NIL VALUE If you don't understand what a string or Boolean values are, learn about data types VIDEO HERE Entering Data To add data to the database we use the SQL command INSERT INTO function AddPlayerLX1(name, score) local query = "INSERT INTO jogadores (name, score) VALUES (?, ?)" dbExec(db, query, name, score) end AddPlayerLX1("juninho", 100) The INSERT INTO command inserts a new player with the name "juninho" and score 100 into the players table. Note: The question marks (?) are placeholders for the values that will be passed to dbExec. This helps prevent SQL injection. Deleting Data To remove data from the database, we use the SQL DELETE command DELETE function DeletePlayerLX2(name) local query = "DELETE FROM players WHERE name = ?" dbExec(db, query, name) end DeletePlayerLX2("juninho") Error Handling It is important to verify that database operations were successful. MTA doesn't automatically return detailed errors other than "/debugscript (1, 2, 3)" so let's add checks. function AddPlayerLX3(name, score) local query = "INSERT INTO jogadores (name, score) VALUES (?, ?)" local sucess = dbExec(db, query, name, score) if sucess then outputDebugString("Sucess.") else outputDebugString("Error.") end end IF SUCESS THEN the success variable stores the result of the dbExec function. If the SQL command execution was successful (i.e. the player was added to the database), success will be true. If success is true, the code inside the if block will be executed. else If the success value is false (that is, if the player's insertion fails for some reason, such as an error in the database connection or SQL query), the code inside the else block will be executed Optimizations and Best Practices Optimizations are great for your day-to-day life as a developer, this makes your code more beautiful, less likely to give you server overload errors, etc... Remember to use dbFree to flush queries after use, especially if you are not using dbPoll. local LX4 = dbQuery(db, "SELECT * FROM players") dbFree(LX4) There are several ways to create clean code, I left just one of them Let's be clear: Since the SQLite database is a flat file, you can back it up by simply copying the .db file. To restore the database, simply replace the old file, this is a big advantage of using SQlite instead of using external databases. OBS: All codes were made based on an example of player name and id points, not made in a real project. (just to make it clear That's all I remembered, if there's anything I didn't make clear here you can say it and I'll edit it or respond to you
-
O que é espaçamento? Termo genérico cujo significado varia dependendo do contexto. Na programação, se refere aos espaços dados no início das linhas para definir os escopos das funções e condições. Normalmente são dados 4 espaços de uma vez. Utiliza a tecla SPACE. O que é tabulação? É o termo usado para atribuir espaços no início das linhas com a tecla TAB do teclado em vez do SPACE. Ao apertar TAB, ele insere um espaço único e grande, seu tamanho varia de acordo com o programa que está sendo usado para escrever o script. Ele pode ter o tamanho de 2, 4, 8 espaços. Quando usar cada tipo? E por quê? A tabulação é mais comum e útil em textos normais, como redação por exemplo. Utilizada para dar aquele espaço no início da primeira linha de um parágrafo no tamanho exato. É melhor e mais fácil do que ficar contando uma quantidade exata de espaços. Já na programação, você deve configurar o editor de scripts para inserir espaçamentos em vez de tabulações ao apertar a tecla TAB para evitar tabulações no script. É preferível o uso de espaços pois estes possuem sempre o mesmo tamanho, independente do editor de scripts que você use para ler seu código. Já a tabulação possui diferentes tamanhos dependendo de onde o código estiver sendo mostrado. Vou mostrar um exemplo prático do que acontece se você usar tabulação em um script em vez de espaços. Como ele está no editor de scripts: (notepad++) Como ele aparece no fórum: function QualquerCoisa() print("tabulação") print("espaçamento") end No script acima, ambos aparecem com o mesmo tamanho (4 espaços) no editor de scripts. Mas no fórum, a tabulação assume o tamanho de 8 espaços, o que acaba ficando grande demais e diferente do espaçamento. (selecione o script acima com seu mouse e veja como a seleção se comporta, perceba que antes do primeiro print, existe 1 único espaço grande, é uma tabulação. E no segundo print temos 4 espaços.) Essa diferença de espaços prejudica a indentação do script, que acaba ficando ilegível. Normalmente acontece quando o script tem partes de código copiadas de algum lugar com uma forma e o resto programado pelo usuário de outra forma. Você não é obrigado a programar com espaços, mas é preferível que se use espaços do que tabulações para evitar diferenças de tamanhos. Usar espaçamentos em vez de tabulações é considerada uma boa prática de programação, assim como a indentação. Curtiu este conteúdo? Achou ele útil para você ou para alguém? Deixe seu like neste tópico clicando no coração abaixo. \/
- 1 reply
-
- 1
-
- espaçamento
- tabulação
-
(and 2 more)
Tagged with:
-
[TUT] Scaling DX The reason why I am creating this topic, is because there are a lot of people asking this question: And to be honest there is no best practice for. But here you have my recommendation as guidance for display them the ~s~a~m~e~ for all screen formats. There are two important factors while dealing with screen formats 1. Pixel density Indication: PPI(Pixels Per Inch) and some also use the term DPI(Dots Per Inch) They do not have to be the same while talking about printing stuff. This indication tells us about how many pixels are used per inch. Which more or less tells us how sharp/smooth things like text can be looking. PPI doesn't really play a big role, but to display something nicely you need enough pixels to display it. Else it will be either too small or too crispy. So be careful to not scale things (especially text) too small. 2. Display aspect ratio Wiki The difference between resolution X and resolution Y as a ratio. A list of common ratios: 4:3 5:4 3:2 16:10 16:9 So for example if we take: fHD: 1920x1080 Which has the ratio 16:9 that is calculated like this: 1920 / 16 = 120 120 * 9 = 1080 Scaling without ratio Before I am going to explain any of this, I am going to ask you an important question: Like this: (vertical) ▮ Or horizontal? ▅ I assume most people would agree to play MTA horizontal, else you are probably reading a book or document. p.s If you play MTA on a vertical screen, then we developers do not like you at all, sorry. So what does this tell us? You can assume that the X-resolution is never going to be smaller than the Y-resolution. Useful? You will figure it out. Doing the scaling Note: This part is ABOUT SCALING and not positioning. So what we are going to do is: Calculating a scale which can display the same DX on multiple screen formats > without messing with the ratio. Example: A computer runs MTA at a resolution of 1920 x 1080. Lets define that! local devScreenX = 1920 local devScreenY = 1080 If this code is used by a different pc, we also need to know on which resolution it is running: local screenX, screenY = guiGetScreenSize() For the next step we have to look at this screenshot: I have cut out of the wide-screen format a square. Squares have the ratio 1:1, which means that we have removed our ratio difference from this screen resolution. It is very easy to do, as our Y * Y resolution makes exactly that beautiful square! The next thing we have to do is creating our scaling value. This value is required for adjust our resolution values so that they match to every screen format. So to use our ratio 1:1, we use the Y resolution to achieve that: local scaleValue = screenY / devScreenY And as last we can create a rectangle shape that is displayed at the center of every screen format, perfectly! local devScreenX = 1920 local devScreenY = 1080 local screenX, screenY = guiGetScreenSize() local scaleValue = screenY / devScreenY addEventHandler("onClientRender", root, function () -- create a scaled size local sizeX = scaleValue * 300 -- 300px local sizeY = scaleValue * 50 -- 50px -- get the center of the screen local centerX = screenX / 2 local centerY = screenY / 2 -- calculate the starting point of the rectangle local startRectangleX = centerX - (sizeX / 2) local startRectangleY = centerY - (sizeY / 2) dxDrawRectangle ( startRectangleX, startRectangleY, sizeX, sizeY, tocolor ( 255, 255, 255, 255 ) ) end) Lower limit What if we have a resolution of 800x600? And the text is getting too small? Making sure that the pixel density is OK, is very important. So to counter that we have to make sure that the text is not getting too small. Our development Y resolution is 1080 pixels. And we are dealing with an Y resolution 600 pixels. The first thing we are going to look at, is what the scale is going to be at that point. 600 / 1080 = 0.55555555555555555555555555555556 It is not very nice to have your text scaled to 55.5% of the original size, when having low resolution already. But without scaling, the DX stuff might fill up the entire screen and that is just as bad. So what we now need is a limit, in this case a lower limit. scaleValue = math.max(scaleValue, 0.65) The math.max function returns the highest value of all the arguments you put in to it. In this case it contains the: scaleValue: 0.555 And the lower limit of: 0.65 This will make sure that the DX stuff is not getting smaller than 65%. This might make text read able for a 800x600 resolution. Positioning Do you want to place your dx-effects at a specific place on your screen? See the following useful function: https://wiki.multitheftauto.com/wiki/GetScreenStartPositionFromBox
- 24 replies
-
- 15
-
Lua tables are a fundamental data structure that allows you to store key-value pairs and create complex data structures. Tables in Lua are versatile and can contain values of different types. Let's dive into a detailed explanation with examples : Table Creation: To create a table in Lua, you use curly braces { } and separate the elements with commas. Here's an example: local table = {1, 2, 3, 4, 5} -- table crt In the above example, we created a table named table and populated it with values 1, 2, 3, 4, and 5. Accessing Table Elements: You can access table elements by using square brackets [ ]. Indices in Lua start from 1. Here's an example: -- Accessing table elements print(table[1]) --output : 1 print(table[3]) --output : 3 In the above example, we access the value at the 1st index (1) and the 3rd index (3) of the table. Adding Elements to a Table: To add a new element to a table, you specify the index and the value. If the specified index already exists in the table, the value will be overwritten. Here's an example: -- Removing elements from a table table[3] = nil In the above example, we remove the element at the 3rd index of the table. Getting the Size of a Table: To get the size of a table (i.e., the number of elements), you can use the # operator. Here's an example: -- Getting the size of a table print(#table) -- 5 In the above example, we print the size of the table using the # operator. Table Iteration: You can iterate over the elements in a table using the ipairs or pairs functions. ipairs provides index-based iteration, while pairs provides key-based iteration. Here's an example: -- Table iteration for index, value in ipairs(table) do print(index, value) end In the above example, we iterate over the table using ipairs and print the index and value of each element. +---------------------------------------------------+ | Game Settings | +---------------------------------------------------+ | Difficulty: | Hard | | Sound Volume: | 80% | | Controls: | Keyboard & Mouse | | Graphics Quality: | High | +---------------------------------------------------+ In the above example, an ASCII art representation is used to display a Lua table representing game settings. The table consists of different elements representing various game settings. Here's the Lua code that represents the table: local gameSettings = { difficulty = "Hard", soundVolume = "80%", controls = "Keyboard & Mouse", graphicsQuality = "High" } In the Lua code, a table named "gameSettings" is created, and different elements representing game settings such as difficulty, sound volume, controls, and graphics quality are added to the table. local person = { name = "Eren", age = 20, occupation = "Software Engineer", country = "Germany" } local tableFormat = [[ +-----------------------+ | Person Info | +-----------------------+ | Name: %s | | Age: %d | | Occupation: %s | | Country: %s | +-----------------------+ ]] local formattedTable = string.format(tableFormat, person.name, person.age, person.occupation, person.country) print(formattedTable) In the example above, we create a Lua table named "person" and populate it with some sample information about a person. We then define a string format named "tableFormat" which represents an ASCII table structure. We use placeholders like %s and %d to indicate the places where the values from the "person" table will be inserted. Finally, we use the string.format function to fill in the format with the data from the "person" table and store it in the variable "formattedTable". We print the "formattedTable" to display the final result. I explained string methods in the previous tutorial, here is the link: string methods LINK Output : +-----------------------+ | Person Info | +-----------------------+ | Name: Eren | | Age: 20 | | Occupation: Software Engineer | | Country: Germany | +-----------------------+ Nested Tables: Tables can contain other tables, allowing you to create nested or multidimensional data structures. Here's an example: -- Nested tables local team = { name = "Team A", players = { { name = "Eren", age = 20 }, { name = "Emily", age = 27 }, { name = "Angela", age = 23 } } } print(team.name) -- Team A print(team.players[2].name) -- Emily In the above example, we created a table named team with two elements: name and players. The players element is a nested table that contains information about individual players. We access the name element of the team table and the name of the player at the 2nd index of the players table. Table Insertion and Removal: Lua provides various functions for inserting and removing elements from tables. Here's an example that demonstrates these operations: -- Table insertion and removal local fruits = {"apple", "banana"} table.insert(fruits, "orange") -- Insert an element at the end table.insert(fruits, 2, "grape") -- Insert an element at the 2nd index table.remove(fruits, 1) -- Remove the element at the 1st index for index, fruit in ipairs(fruits) do print(index, fruit) end In the above example, we start with a table named fruits containing two elements. Using table.insert, we add an element at the end and another element at the 2nd index. Then, using table.remove, we remove the element at the 1st index. Finally, we iterate over the modified fruits table and print the index and value of each element. Table Concatenation: Lua allows you to concatenate tables using the .. operator. Here's an example: -- Table concatenation local table1 = {1, 2, 3} local table2 = {4, 5, 6} local mergedTable = {} for _, value in ipairs(table1) do table.insert(mergedTable, value) end for _, value in ipairs(table2) do table.insert(mergedTable, value) end for index, value in ipairs(mergedTable) do print(index, value) end In the above example, we have two tables named table1 and table2. We create an empty table named mergedTable and use table.insert to concatenate the elements from table1 and table2 into mergedTable. Finally, we iterate over mergedTable and print the index and value of each element. for MTA:SA Player Information: Lua tables can be used to store player information in MTA:SA. Below is an example of a player table that contains details such as the player's name, level, and score: local player = { name = "Eren", level = 5, score = 1000 } In the above example, we create a table named "player" and populate it with the player's name, level, and score. Vehicle List: Lua tables can be utilized to store data related to vehicles in MTA:SA. Here's an example of a vehicle table that includes the model names and colors of the vehicles: local vehicles = { { model = "Infernus", color = {255, 0, 0} }, { model = "Bullet", color = {0, 0, 255} }, { model = "Sultan", color = {0, 255, 0} } } In the above example, we create a table named "vehicles" and store each vehicle as a separate table with its model name and color data. Colors are represented using RGB values. NPC (Non-Player Character) List: Lua tables can be used to store in-game NPCs in MTA:SA. Here's an example of an NPC list table that includes the model IDs and coordinates of the NPCs: local npcs = { { model = 23, x = 100, y = 200, z = 10 }, { model = 56, x = 150, y = 250, z = 15 }, { model = 89, x = 200, y = 300, z = 20 } } In the above example, we create a table named "npcs" and store each NPC as a separate table with their model ID and coordinates. I hope you will like it
-
Neste tutorial irei explicar qual a diferença entre um loop usando pairs e um loop usando ipairs. Mas antes de prosseguir, é necessário entender o que é uma tabela indexada e uma tabela não indexada. Tabela indexada é aquela cujos itens tem seu índice declarado. Os índices podem ser números, textos ou elementos. Tabela não indexada é aquela cujos itens não tem seu índice declarado. Porém a linguagem Lua automaticamente indexará essas tabelas com inteiros sequenciais. local tabela = {"1", 2, "três", 0.4, false, 0} -- Tabela não indexada. -- O MTA vai considerar a tabela acima dessa forma: local tabela = { -- Tabela indexada com inteiros sequenciais. [1] = "1", [2] = 2, [3] = "três", [4] = 0.4, [5] = false, [6] = 0 } -- Escrevi a tabela na vertical para facilitar a leitura, não faz diferença escrever tudo na mesma linha. É importante saber disso pois ipairs leva em consideração os índices dos itens de uma tabela, como veremos a seguir. CONCEITO Tanto o pairs quanto o ipairs são utilizados para fazer loops que percorrem uma tabela usando o laço de repetição for. Mas existem situações em que um ipairs não funciona e também há situações em que o pairs não atende ao objetivo que o scripter precisa. Basicamente, o pairs percorre os itens de uma tabela mas não garante a mesma ordem em que eles foram declarados e nem a sequência de seus índices. Sem qualquer ordem específica, ele não exige que a tabela seja indexada por inteiros sequenciais, já que ele não leva em consideração a ordem dos índices da tabela. Enquanto o ipairs (significado: index-value pairs) percorre os itens de uma tabela sempre seguindo a sequência de seus índices. Verificando primeiro o item de índice 1, depois o item de índice 2 e assim por diante. Se um índice da sequência estiver faltando, ele não percorrerá o resto e vai parar de verificar. Também não importa a ordem em que os índices são declarados. Se você declara o item de índice 2 e depois o item de índice 1, mesmo assim ele vai ler o item de índice 1 primeiro e depois o item de índice 2. O ipairs também não é capaz de verificar itens cujo índice não seja um inteiro, pois ele não sabe a sequência que ele pertence, portanto itens de índice string não são verificados pelo ipairs. EXEMPLOS Usando o pairs: (note que o exemplo é server-side, mas tanto o pairs quanto o ipairs podem ser usados client-side também) Server-side addCommandHandler("eae", function(thePlayer, cmd) -- Vamos setar algumas elementDatas em si mesmo só para testes. setElementData(thePlayer, "vida", 100) setElementData(thePlayer, "colete", 90) -- (Datas fictícias, não alteram de verdade a vida nem colete do jogador). setElementData(thePlayer, "vivo", true) setElementData(thePlayer, "procurado", false) setElementData(thePlayer, "emprego", "Mecânico") local datas = getAllElementData(thePlayer) -- Obtém uma tabela com todas as elementDatas do jogador que executou o comando /eae -- A tabela retornada seria assim: (supondo que o jogador não tenha outras elementDatas setadas nele) --[[ local datas = { ["vida"] = 100, ["colete"] = 90, ["vivo"] = true, ["procurado"] = false, -- Este é o único jeito de saber se uma elementData false existe mesmo. ["emprego"] = "Mecânico" } --]] -- Para verificar cada item dessa tabela, o pairs precisa ser usado pois os índices são strings enquanto o ipairs só funciona com índices inteiros sequenciais. for name, value in pairs(datas) do print(name.." = "..tostring(value)) end -- Não há qualquer garantia de que os itens sejam verificados na mesma ordem em que foram declarados. Consideramos isso aleatório. end) Obs: O pairs também funciona em tabelas com índices inteiros sequenciais como o ipairs, porém percorre de maneira aleatória enquanto o ipairs segue a sequência dos índices. 1) Se trocar o pairs por um ipairs, nenhum item será verificado. Pois não foi encontrado o índice 1. Obs2: Mesmo se você definir uma elementData com nome "1", o índice continuará sendo uma string, não sendo lido pelo ipairs. Vimos acima um exemplo que precisa usar pairs pois o ipairs não funcionaria. Agora veremos um exemplo onde o ipairs seria mais adequado. Client-side local palavras = { [1] = "Neste ", [2] = "caso ", [3] = "a ", [4] = "ordem ", [6] = "importa " -- Esqueci do índice 5 de propósito. } local mensagem = "" for i, v in ipairs(palavras) do mensagem = mensagem..v end print(mensagem) Faça os seguintes testes: 1) Execute o código acima do jeito que está, veremos que a mensagem final aparece incompleta. Pois ele não encontrou o índice 5 e parou de verificar o resto dos itens. Retornando a mensagem "Neste caso a ordem " 2) Se trocarmos o ipairs por um pairs, veremos que a mensagem ficará bagunçada, pois os itens foram verificados de maneira aleatória. Porém desta vez todas as palavras serão verificadas, pois o índice não é levado em consideração pelo pairs, somente pelo ipairs. 3) Troque o pairs pelo ipairs de volta e substitua o índice 6 por 5. A mensagem aparecerá completa e com as palavras em ordem. Já que não haverá nenhum índice faltando na sequência. 4) Troque a ordem dos itens da tabela dessa forma: (preste atenção na vírgula, ela é obrigatória em todos os itens, exceto no último) local palavras = { [4] = "ordem ", [2] = "caso ", [5] = "importa ", [1] = "Neste ", [3] = "a " } Veremos que o ipairs continuará verificando cada item na ordem correta. Já que o que importa para ele são os índices e não a ordem em que os itens foram declarados na tabela.
-
Hi I wanted to learn how to create my own shaders for this game from lighting starting to moving texture on the wall. I would really like someone to give me a link to a page where I can find all the functions or if someone wants to explain to me what it is all about
-
Como Instalar La GM DOWNTOWN Para local host Video Explicativo +ARCHIVOS LINK:
-
O tutorial de hoje é sobre tabelas! Tabelas irão facilitar a sua vida na hora de programar. Além de economizar dezenas de linhas de código, ele ficará muito mais fácil de ser lido por outras pessoas, e também por você mesmo, depois de um certo tempo sem ter contato com o código. Não só essas coisas, como irá te abrir um mar de possibilidades. Clique no texto abaixo para ir diretamente ao site onde o tutorial está. Optei por escrevê-lo no Gist (do GitHub), como uma forma de organizar um pouco melhor. Ir para o tutorial ?
-
Passo a passo de como indentar um código que veio sem indentação: Exemplo qualquer: 1. Adicione 4 espaços em tudo que estiver dentro da função principal, exceto a própria função e o end dela. Ela deve ficar assim: 2. Adicione mais 4 espaços em tudo que estiver depois do primeiro if, exceto o penúltimo end que pertence a ele. 3. Faça o mesmo com todos os if que tiverem dentro deste, um de cada vez. Vale lembrar que isso se aprende ao estudar lógica de programação e algoritmos. Curtiu este conteúdo? Achou ele útil para você ou para alguém? Deixe seu like neste tópico clicando no coração abaixo. \/
-
- 2
-
- indentação
- dicas
-
(and 2 more)
Tagged with:
-
spanish: Hola, puedes hacerme el favor de ayudarme con este script, ya logré recuperar el equipo anterior cuando salí del servidor pero ahora no consigo que el equipo me salve al reiniciar el recurso adjunto al código del script english: Hello, can you do me the favor of helping me with this script, I already managed to recover the previous team when I left the server but now I cannot get the team to save me when restarting the resource attached to the script code server empresa = createTeam("EMPRESA", 0, 255, 0) --team oldTeam = {} -- Tabela para salvar o Team antigo. addEvent('setSERV',true) --contratar, addEventHandler('setSERV',root, function() local playerTeam = getPlayerTeam(source) if playerTeam then local serial = getPlayerSerial(source) oldTeam[serial] = getTeamName(playerTeam) setPlayerTeam ( source, empresa ) else setPlayerTeam ( source, empresa ) end end) addEvent('setSERVNo',true) --despedir addEventHandler('setSERVNo',root, function(_) local playeraccount = getPlayerAccount ( source ) local serial = getPlayerSerial(source) LoadTeam = getAccountData ( playeraccount, "oldTeam" ) if oldTeam[serial] and getTeamFromName(oldTeam[serial]) then setPlayerTeam(source, getTeamFromName(oldTeam[serial])) elseif ( LoadTeam ) then teamLoad = getTeamFromName ( LoadTeam ) setPlayerTeam ( source, teamLoad ) else setPlayerTeam ( source, nil ) end end) function onPlayQuit ( ) local playeraccount = getPlayerAccount ( source ) if ( playeraccount ) and not isGuestAccount ( playeraccount ) then -- if the player is logged in local serial = getPlayerSerial(source) if oldTeam[serial] and getTeamFromName(oldTeam[serial]) then setAccountData ( playeraccount, "oldTeam", getTeamFromName(oldTeam[serial]) ) -- save it in his account end end end addEventHandler ( "onPlayerQuit", getRootElement ( ), onPlayQuit ) function onResstop ( ) local playeraccount = getPlayerAccount ( source ) if ( playeraccount ) and not isGuestAccount ( playeraccount ) then -- if the player is logged in local serial = getPlayerSerial(source) if oldTeam[serial] and getTeamFromName(oldTeam[serial]) then setAccountData ( playeraccount, "oldTeam", getTeamFromName(oldTeam[serial]) ) -- save it in his account end end end addEventHandler ( "onResourceStop", getRootElement ( ), onResstop )
-
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.)
-
Fala, galera. Pra quem sempre quis saber como escrever os próprios scripts para MTA, mas nunca conseguiu se organizar para começar, eu trago a solução. Estou construindo uma playlist de vídeos relacionados a script para MTA. O foco principal é ensinar a API do MTA e não necessariamente programação em Lua, portanto, para aqueles que desejam acompanhar melhor é recomendado que já saiba programar em Lua. Por outro lado, não sinta-se incapaz de seguir a playlist mesmo não sabendo Lua. Você pode tentar entrar de cabeça, sem ter esse background muito sólido. Vai ser mais difícil, mas não é impossível. Eu já vi alguns gringos fazendo um post numa espécie de thread para seus próprios vídeos, mas não sei se é contra as regras. Se for, desculpe. Eu vou ir mantendo o vídeo mais atualizado no topo. Mas a playlist pode ser conferida aqui. MTA SCRIPT #22: Sistema de Exports MTA SCRIPT #21: Introdução à tabelas e OOP MTA SCRIPT #20: DX Scripting - Exibindo imagens na tela MTA SCRIPT #19: DX Scripting - Animações com InterpolateBetween MTA SCRIPT #18: DX Scripting - OnClientCursorMove MTA SCRIPT #17: DX Scripting - OnClientClick MTA SCRIPT #16: DX Scripting - Posição e Escala pt.2 MTA SCRIPT #15: DX Scripting - Posição e Escala pt.1 MTA SCRIPT #14: DX Scripting - Introdução MTA SCRIPT #13: Solucionando problemas de código MTA SCRIPT #12: Controle de Acesso (ACL) MTA SCRIPT #11: Pickups MTA SCRIPT #10: Markers MTA SCRIPT #09: Bind de teclas MTA SCRIPT #08: Manipulando eventos pt.2 MTA SCRIPT #07: Manipulando eventos pt.1 MTA SCRIPT #06: Variáveis globais predefinidas e Árvore de elementos MTA SCRIPT #05: Introdução aos comandos MTA SCRIPT #04: Script de Cliente x Servidor x Compartilhado MTA SCRIPT #03: Escrevendo seu primeiro resource MTA SCRIPT #02: Administrando o servidor MTA SCRIPT #01: Preparando o ambiente
-
O que é? Pra que serve? Um banco de dados é onde ficam salvos diversos tipos de dados que são usados entre as sessões dos jogadores e do servidor, isto significa que mesmo se o jogador relogar no servidor ou até mesmo o servidor reiniciar, os dados salvos no banco de dados não são perdidos. (se o script que salvou lá foi feito corretamente). O que posso salvar neles? O MTA já cria 2 bancos de dados padrão quando vc cria seu servidor, são eles: internal.db - Onde são salvos todos os dados das contas dos jogadores, login, senha, grana do bolso, posição do jogador quando deslogou, vida, colete, skin, armas, munição, etc. registry.db - Onde são salvos todos os dados que são utilizados pelos resources, como por exemplo melhores pontuações das corridas (race gamemode), proprietários das casas, dados bancários dos jogadores, saldo bancário dos jogadores, carros comprados pelos jogadores, roupas compradas pelos jogadores, empresas adquiridas pelos jogadores, etc. Onde eles estão? Estes dois bancos de dados estão na pasta deathmatch do seu servidor, estão na linguagem SQLite. Você ainda pode criar outros bancos de dados externos, para serem usados pelos resources, mas na minha opinião isso não é recomendável, uma vez que vc usaria MySQL, que é mais complexo e exige certos cuidados de acesso e domínio, mas alguns servidores profissionais precisam fazer assim pois fizeram os bancos de dados ficarem fora do servidor em outro IP por segurança, dai é necessário ter bancos de dados externos. Nesse tutorial vamos tratar somente dos bancos de dados nativos do MTA, por serem mais fáceis de entender. Como mexo neles? Para salvar alguma coisa na conta do jogador, isto é, no internal.db, você usa setAccountData, e para obter esses dados depois, use getAccountData. É extremamente simples, funciona da mesma forma que um setElementData, mas em vez de salvar uma data temporária em um elemento, salva uma data permanente numa conta. Porém, para salvar alguma coisa no registry.db, é um pouco mais complicado, uma vez que vc vai precisar criar uma tabela nova para cada resource. Por exemplo, vc acabou de criar um resource de ranking por kills/deaths e você deseja salvar esse ranking no banco de dados para que ao reiniciar o resource ou o servidor, o ranking não seja perdido. Para isso vc vai precisar primeiramente criar uma tabela no banco de dados registry.db, essa tabela será acessada pelo resource, que irá salvar os dados dele lá. Para fazer qualquer coisa neste banco de dados (criar tabelas, inserir, alterar, remover, deletar, inserir colunas em determinada tabela, etc) vc vai precisar usar isso: executeSQLQuery. Aqui, será necessário conhecimento em SQL para fazer isso, mas é mais fácil do que aprender uma linguagem de programação nova, pois suas opções e sintaxes são menores do que uma linguagem inteira de programação, você não vai inventar nenhum sistema novo aqui, apenas criar e gerenciar tabelas e dados. Criar tabela nova no banco de dados: (o Caps Lock não é uma regra, mas é melhor para entender o que é código e o que é nome) [Os seguintes códigos só funcionam server-side] executeSQLQuery ("CREATE TABLE IF NOT EXISTS nomedatabela (nomecoluna1 TEXT, nomecoluna2 REAL, nomecoluna3 INTEGER)") TEXT = Valores desta coluna serão textos. Podem ter símbolos, números e espaços. REAL = Valores desta coluna serão numéricos reais. (números decimais, positivos, negativos e 0.0) INTEGER = Valores desta coluna serão numéricos inteiros. (positivos, negativos e 0) (não existe tipo BOOLEAN, use TEXT e insira valor "false" ou "true") (existe valor NULL, é diferente de vazio e diferente de 0. NULL significa ausência de dados. O NULL aparece quando você cria uma linha ou coluna nova sem atribuir valores a elas.) Deletar tabela do banco de dados: executeSQLQuery ("DROP TABLE nomedatabela") Todas as linhas, colunas, células e valores desta tabela são deletados junto. Deletar linhas da tabela: (as células não ficarão NULL) executeSQLQuery ("DELETE FROM nomedatabela WHERE colunaespecífica=?", valorDaCelulaEspecifica) O ? indica que o valor está após a declaração do SQL. Você poderia colocar o valor direto no lugar do ?. Mas por alguma razão, as vezes isso gera erro. Além disso, se o valor da célula estiver em uma variável no seu script, você não pode declarar a variável no lugar do ?. Ali só pode ser o valor direto, pois a declaração SQL inteira se trata de uma string. Por isso o uso do ?, que está recebendo o valor da variável que está depois da vírgula. Obs: Para verificar se uma célula tem valor nulo, não se usa os operadores lógicos de ==, <= >=. Para isso, usa-se IS NULL ou IS NOT NULL. Ex: executeSQLQuery ("DELETE nomecoluna1,nomecoluna2 FROM nomedatabela WHERE nomecoluna3 IS NULL") Isso vai deletar todas as células da coluna 1 e coluna 2 onde a coluna 3 tem uma célula de valor NULL. Se a coluna 3 não tiver nenhuma célula de valor NULL, nada acontece. Inserir nova linha de valores: (ele vai criar automaticamente uma nova linha com novas células) executeSQLQuery ("INSERT INTO nomedatabela(nomecoluna1,nomecoluna2,nomecoluna3) VALUES(?,?,?)", valorCelulaColuna1, valorCelulaColuna2, valorCelulaColuna3) Neste caso, ele está inserindo 3 novos valores, cada valor em uma coluna. Se você não declarar os nomes das colunas, ele vai preencher na ordem das colunas automaticamente. Você pode deixar de declarar uma coluna se não quiser atribuir valor na célula daquela coluna. Se o tipo de valor da variável não for do tipo de dado daquela coluna, dará erro. Atualizar valores de células que já existem em uma tabela: (não é possível alterar os tipos de valores, é necessário editar o tipo da coluna se quiser fazer isso) executeSQLQuery ("UPDATE nomedatabela SET nomecoluna2=?,nomecoluna3=? WHERE nomecoluna1=?", valorCelulaColuna2, valorCelulaColuna3, valorCelulaColuna1) No caso acima, ele vai atualizar as células das colunas 2 e 3 onde o valor da célula da coluna 1 for igual ao valor de valorColunaCelula1. OBS: Nada impede que você coloque as primeiras variáveis junto à declaração SQL, mas para fazer isso você deve "cortar" a string, inserir as variáveis e depois continuar a string, Ex: executeSQLQuery ("UPDATE nomedatabela SET nomecoluna2= '".. valorCelulaColuna2 .."',nomecoluna3='".. valorCelulaColuna2 .."' WHERE nomecoluna1=?", valorCelulaColuna1) Lembrando que o valor destas variáveis também são strings na declaração, portanto use aspas simples antes e depois de cada corte para transformar os valores em string. Os dois pontos (..) significam que estes valores fazem parte do argumento SQL. Da mesma forma, se vc usar "1" .. "1", será igual a "11". (Por isso acho muito mais fácil deixar tudo ? na declaração SQL e colocar as variáveis todas após a string.) Selecionar determinadas células da tabela: (usado geralmente para obter os valores destas células para usar no script, você pode selecionar somente 1 célula ou várias) executeSQLQuery ("SELECT nomecoluna1,nomecoluna2 FROM nomedatabela WHERE nomecoluna3=?", valorCelulaColuna3) Neste exemplo, ele vai selecionar a célula da coluna 1 e a célula da coluna 2, na linha onde a célula da coluna 3 for igual a valorCelulaColuna3. Alterar a tabela (adicionar coluna nova) [SQLite não suporta deletar coluna nem editar tipo de coluna] executeSQLQuery ("ALTER TABLE nomedatabela ADD nomecoluna4 REAL") Devido a limitações do SQLite, ALTER TABLE não pode ser usado para deletar uma coluna nem para editar seu tipo. Para fazer isso é necessário recriar a tabela inteira com as novas alterações. No exemplo acima, ele vai adicionar uma nova coluna chamada "nomecoluna4". Tá, mas como ficaria tudo isso dentro de um script? Fiz um código com vários testes de banco de dados. Cada comando faz alguma coisa. É possível mexer em um banco de dados manualmente sem usar scripts? Sim, é possível. Eu mesmo costumo fazer isso para corrigir algumas coisas rápidas sem precisar programar mais nada. Para poder abrir os bancos de dados (internal.db e registry.db) você deve usar um programa chamado DB Browser for SQLite. Um programa gratuito, leve e bem fácil de entender. Nele você consegue acessar todas as tabelas do banco de dados e editar os valores como se fosse em uma planilha do Excel. Basta ir na aba Navegar dados, selecionar a tabela que deseja modificar, clicar em cima da célula cujo valor deseja atualizar, digitar o novo valor, clicar em Aplicar e depois clicar em Escrever modificações (salvar banco de dados). Pronto! E tem mais! Se você já tiver conhecimento avançado com a linguagem SQL, você também pode fazer alterações avançadas via código dentro do programa. Basta acessar a aba Executar SQL, escrever o comando SQL corretamente e depois clicar no botão de Play. Espero ter ajudado.
- 14 replies
-
- 16
-
- sql
- banco de dados
-
(and 3 more)
Tagged with:
-
Hello fellas. This topic will be updated - might not be regularly, but what's planned below will be out in some days/months/years. As for now I upload two parts of MTA Racing Tutorials, which I think might be useful for your cruises through SA. PART 1 - HOW TO SET UP YOUR OWN SERVER FOR TRAINING PURPOSES PART 2 - 45 CUTS FOR SAN ANDREAS RACING PART 3 (TBA) - USEFUL WAYS: LINES, BUGROADS AND MORE PART 4 (TBA) - OVERVIEW OF TIPS&TRICKS PART 5 (TBA) - HYDRA RACING & STUNTING GUIDE PART 6 (TBA) - PAD VERSUS KEYBOARD - THE NEVERENDING BATTLE. OVERVIEW OF CONTROL METHODS
-
Yesterday evening, I started my apprenticeship with db, I always wanted to learn, because with it, I can do mods, which I could not do without. My introduction with Database was done by adapting a System ID to the DB in the login panel. I did this using the server-side of my login panel. The first thing we do, is to use dbConnect (Wiki), which will make the connection to the db file. local db = dbConnect("sqlite", "db/royalusers.db") It will create the "db" folder, in the resource files, and inside the folder, the "royalusers.db" file. After that, we create a table using the SQL functions. local newTable = dbExec(db, "CREATE TABLE IF NOT EXISTS RoyalUsers (id INT, name TEXT, login TEXT, pass TEXT, serial TEXT)") RoyalUsers - Table-name id INT, name TEXT, login TEXT, pass TEXT, serial TEXT - columns of the table. INT - INTERNAL NUMBER Now the part of using the table defined in the database. function registerPlayer(user, pass, conf) if user == "" then outputLoginMsg(source, "Preencha todos os campos!", "error") else if pass == "" then outputLoginMsg(source, "Preencha todos os campos!", "error") else if conf == "" then outputLoginMsg(source, "Preencha todos os campos!", "error") else if conf == pass then addAccount(tostring(user),tostring(pass)) triggerClientEvent(source, "onRoyalRegister", source) local query = dbPoll(dbQuery(db, "SELECT * FROM RoyalUsers WHERE login=?", user),-1) if #query == 0 then dbExec(db, "INSERT INTO RoyalUsers VALUES (?, ?, ?, ?, ?)", countIDs(), getPlayerName(source), user, pass, getPlayerSerial(source)) end outputLoginMsg(source, "Conta criada com sucesso! Aguarde...", "success") if not getAccount(user, pass) then outputLoginMsg(source, "Esta conta já está sendo utilizada!", "error") end else outputLoginMsg(source, "As senhas não estão iguais.", "error") end end end end end addEvent("onPlayerRequestRegister", true) addEventHandler("onPlayerRequestRegister", root, registerPlayer) function countIDs() local table = dbPoll(dbQuery(db, "SELECT * FROM RoyalUsers"), -1) local count = 1 for i, result in pairs(table) do count = count + 1 end return count end The login variable returns a table, it selects (SELECT) all the columns of the table, and checks if the login defined in the function does not exist in it, if it does not exist, it will add those information, the columns of the table RoyalUsers (INSERT INTO). VALUES (?, ?, ?, ?, ?) - "?" It is the amount of arguments that will be used to insert into the column. countIDs() - Function that returns the number of IDs in the table, and adds one more. getPlayerName(source) - Gets the player's name, and adds the "name" column of the table. user - Adds the user defined in the function, the column "login". pass - Adds the password set in the function, the "pass" column. getPlayerSerial(source) - Gets the player's serial, and adds the "serial" column of the table. Having the part in which the data that the player registers, are saved in the database, this part is ready. Now, just set the ID added to the database login, when the player logs in. function loginPlayer(source, user, pass) if user == "" then outputLoginMsg(source, "Preencha todos os campos!", "error") else if pass == "" then outputLoginMsg(source, "Preencha todos os campos!", "error") else local account = getAccount(user, pass) if account then logIn(source, account, pass) local queryTable = dbPoll(dbQuery(db, "SELECT * FROM RoyalUsers WHERE login='"..getAccountName(getPlayerAccount(source)).."'"), -1) for i, id in pairs(queryTable) do setElementData(source, "ID", id["id"]) end setTimer(setCameraTarget, 3000, 1, source, source) setTimer(triggerClientEvent, 14000, 1, source, "renderRoyalID", source) triggerClientEvent(source, "onRoyalLogin", source) outputLoginMsg(source, "Logado com sucesso! Aguarde...", "success") else outputLoginMsg(source, "Usuário ou senha incorretos!", "error") end end end end addEvent("onPlayerRequestLogin", true) The queryTable gets all the columns of the table, where the login = login of the player. After that, we loop the tables returned by the queryTable, and set the date "ID" to the player, according to the ID returned from the table defined in the loop. I want to make it clear that the tutorial did not go well explained, I just want to share, what I learned yesterday, and if I did something wrong, please let me know.
-
So I wanted to ask if someone would explain to me how to make my own shaders, I immediately say that I know there is an MTA page with examples but I don't understand anything of them so I prefer someone to explain it to me and what it is and how to create although the easiest script with shaders
-
I started scripting with GUI / dxDraw and would like to do some panning or alpha animation. And the question is how this animate works, I know it is shown on the MTA wiki, but I don't quite understand how, If someone would explain it to me, I would be grateful. By the way, I am sending the function I am talking about ... https://wiki.multitheftauto.com/wiki/Animate
-
hola, alguien me puede ayudar a hacer un setTimer el cual mate al jugador
-
I would like to know something about ElementData, the most about these two commands {getElementData, setElementData}, could someone help me understand these two things. For example, write a guide that would help me a lot and give me a heart
-
tengo una duda he creado este panel para cambiar de team es decir que yo le cambie el team a un jugador pero cuando le doy "CONTRATAR" me cambia el team a mi que hago? Client function empre() local screenW, screenH = guiGetScreenSize() contrataciones = guiCreateWindow((screenW - 628) / 2, (screenH - 430) / 2, 628, 430, "NOMBRE DE LA EMPRESA", false) guiSetProperty(contrataciones, "CaptionColour", "FF0036FE") jugador = guiCreateGridList(44, 43, 233, 338, false, contrataciones) guiGridListAddColumn(jugador, "Jugadores", 0.9) for _, player in ipairs(getElementsByType("player")) do guiGridListAddRow(jugador, getPlayerName(player)) end contrar = guiCreateButton(368, 107, 176, 43, "CONTRATAR", false, contrataciones) guiSetProperty(contrar, "NormalTextColour", "FF2FFD00") x = guiCreateButton(574, 33, 44, 42, "X", false, contrataciones) guiSetProperty(x, "NormalTextColour", "FFFC0000") despe = guiCreateButton(368, 251, 176, 43, "DESPEDIR", false, contrataciones) guiSetProperty(despe, "NormalTextColour", "FFFC0000") showCursor (true) end addEvent( "onEmpresa", true ) addEventHandler( "onEmpresa", localPlayer, empre ) addEventHandler('onClientGUIClick',root, function() if source == contrar then triggerServerEvent('setEmpresa',localPlayer) guiSetVisible(contrataciones,false) showCursor(false) end end) addEventHandler('onClientGUIClick',root, function() if source == despe then triggerServerEvent('setEmpresaNo',localPlayer) guiSetVisible(contrataciones,false) showCursor(false) end end) addEventHandler('onClientGUIClick',root, function() if source == x then guiSetVisible(contrataciones,false) showCursor(false) end end) Server empresa = createTeam("TEAM", 0, 255, 0) --team addEvent('setEmpresa',true) --contratar, addEventHandler('setEmpresa',root, function() local teamPlayer = getPlayerTeam ( source ) if teamPlayer then setPlayerTeam ( source, nil ) setPlayerTeam ( source, empresa ) else setPlayerTeam ( source, empresa ) end end) addEvent('setEmpresaNo',true) --despedir addEventHandler('setEmpresaNo',root, function() local playerTeam = getPlayerTeam( source ) if ( getTeamName( playerTeam ) == "TEAM" ) then --team setPlayerTeam ( source, nil ) end end) addCommandHandler ("empresa", --Comando, no confundir con teleport function ( playerSource ) account = getPlayerAccount(playerSource) accname = getAccountName(account) if( accname == "Juan_Camilo" ) then -- lo que esta dentro de las comillas es el nombre de la cuenta que tiene permitido usar el comando. triggerClientEvent ( playerSource, "onEmpresa", playerSource) end end )
-
hola gente, me podrian ayudar con una cosa. Ya he hecho que al pasar por un marker me salga un panel pero debido a un pickup que estado probando pero me toco dejarlo encima del marker para que funcione bien la funcion pero ahora necesito que al pasar la primera vez me aparesca el panel pero al pasar la segunda no aparescan como hago para hacer eso? gracias
-
Como van Gente, soy un poco nuevo en esto de los scripts, ya he logrado hacer un panel de cambio de skin de policial pero me falta una función que con un addCommandHandler se devuelva a la skin que tenia antes el jugador. Si me ayudaran se los agradeciria muchisimo
-
hola, tengo una duda acerca de un bug que me surgió, he estado haciendo un script de teleports y he hecho 2 markers de entrada en diferente posicion al mismo interior pero a difrente dimension, al utilizar el maker para salir del interior me manda a la primera salida que asigne que hago en ese caso
-
hola, me harian el favor de ayudarme con una funcion que actue para todos los jugadores, es decir lo que estoy tratando de hacer es que al presionar un boton en un panel le quite las armas a todos lo jugadores gracias