Ho creato questa guida per tutti quei bravi scripter di pawno che fanno gamemode per SA-MP e vorrebbero passare su MTA, visto che su MTA si puo fare praticamente tutto, come è stato detto piu' volte, anche importare modelli DFF,TXD,COL e i suoni personalizzati.
Nella speranza che la community di gta sa online conosca anche questo multiplayer, che supera di gran lunga sa-mp, in modo da risollevare la voglia di conoscere, apprendere e giocare a MTA..
[B]Pre-Introduzione: Materiali e Risorse[/B]
Per scriptare in lua abbiamo bisogno di questi materiali e risorse.
- [B]NEW:[/B] MTA Script Editor >Link programma molto utile per i principianti per scriptare.
- LuaEdit >Download Altro prog. per scriptare in LUA.
- MTA Wiki >Link Wiki in inglese, ma completa con tutte le funzioni, eventi, eccetera.
- MTA Wiki Italiana >Link Wiki italiana, ma ancora incompleta.
- MTA Resources >Link Pagina contenente le resource piu' utili e piu votate del momento.
- Cartella Server. Una volta installato lo troverete nella directory di MTA, servirà per testare le nostre resources.
- Manuale Server >Link per imparare ad aprire server in locale e avviare/fermare le resources.
[B]Introduzione: Resources, Lua e differenze dal Pawno[/B]
Resource(in italiano, risorsa) è il termine usato da mta per definire una cartella o un archivio zip contentete vari files(tra cui lo script).
Una resource potrebbe essere una gamemode(es. deathmatch, race..) oppure un semplice script contentete comandi o funzioni utili.
Insomma, una resource puo' essere come una gamemode o un filterscript di samp, possono essere avviate e fermate, inoltre possono esserci anche 2 o piu resource avviate contemporaneamente.
Il linguaggio utilizzato per scriptare su MTA è il lua, mentre su SA:MP è il Pawno, ci sono varie differenze e non me le ricordo tutte, posso solo riassumere un po dicendo che il pawno puo' essere anche piu veloce e immediato, ma il lua comunque è piu completo e ti fa avere un controllo migliore delle resources, per fare qualche esempio delle differenze,
nel lua per chiudere gli eventi o funzioni non serve la parentesi graffa "{}" , oppure mentre su samp quando un player muore viene respawnato automaticamente, su mta bisogna scriptare l'evento del respawn.. Stessa cosa per la scelta del team all'inizio della gm o all'entrata del giocatore, su mta biosgna sempre scriptare ogni evento.
Su MTA ci 2 tipi di scripting, ovvero la parte scriptata dal server, e quella del client:
Sullo script del server-side ci sono le normali funzioni e comandi, mentre nel client, possiamo introdurre gli elementi GUI, che riguardano l'interfaccia, ovvero i menù e gli effetti visivi e l'importazione di suoni personalizzati o modelli DFF / TXD personalizzati.(In pratica a sostituzione di veicoli o di oggetti di gioco).
Ovviamente si puo' fare in modo che i 2 script comunicano fra di loro tramite le funzioni "Trigger" che vedremo piu avanti.
[B]Scripting: Elementi, Eventi e Funzioni[/B]
Nello scripting di MTA è fondamentale sapere cosa sono gli elementi, gli eventi e le funzioni.
[B]
- Elementi:
[/B]
Su MTA gli elementi rappresentano quasi tutti i tipi di entita di GTA SA, sono una classe generica.
Un elemento potrebbe essere un Player, un veicolo, un oggetto, un pickup, un Marker, un Blip(segnalino radar) un proiettile(missili/granade) o semplicemente un team.
[B]Lista elementi MTA >Link[/B]
[B]
- Eventi:
[/B] Gli eventi determinano un azione compiuta dal player o dal server, ad esempio quando un player si connette(onPlayerJoin), quando un player colpisce un altro player(onPlayerDamage) oppure semplicemente quando una resource viene avviata(onResourceStart) eccetera.. Gli eventi sono davvero importanti, perché possiamo fare in modo che quando un evento viene "chiamato"(Ovvero, quando succede l'azione in questione), succederà qualcosa scriptata da noi. Ad esempio si può scrivere un messaggio di benvenuto quando un player si connette, oppure quando la resource viene avviata, ovviamente come ho già detto, esistono gli eventi del server, e quelli del client, piu avanti faremo tutti gli esempi.
Ecco la lista degli eventi di MTA.
[B]
- Funzioni:
[/B]
Le Funzioni invece sono da inserire dentro gli eventi chiamati, è molto semplice, posso farvi alcuni esempi di funzioni semplici:
setElementHealth: imposta il valore della vita di un elemento.
setElementAlpha: modifica l'alpha dell'elemento selezionato (valore va da 0 a 255). Se impostato su 0, l'elemento diventa totalmente invisibile, mentre se impostato su 255, diventa visibile.
killPed: semplicissima funzione che uccide il player.
setPedSkin: semplice funzione che imposta una skin al player
setPedStat: un altra chicca, imposta le stats al player, che variano dalla muscolatura, grasso, stamina, sex appeal alle abilità con le armi, l'abilità del gioco d'azzardo e perfino le abilità di guida con i veicoli, eccetera.
queste sono solo un assaggio di tutte quelle funzioni che esistono su MTA che sembrano infinite, giusto per farvi un idea, ecco la lista delle funzioni MTA
[B]NOTA:[/B] mentre su samp si scrive con la maiuscola all'inizio di ogni funzione o evento, su mta si inizia SEMPRE con la minuscola.
SAMP : [B]G[/B]etPlayerWeapon
MTA : [B]g[/B]etPlayerWeapon
In caso se scriverete con la maiuscola, la console vi darà errore.
[B]Scrivere una resource: Introduzione[/B]
Come ho detto prima, una resource è una cartella o un archivio zip contenente i files della nostra gamemode o script, quindi, creiamo una cartella con il nome "[B]myresource[/B]", visto che dovremmo testarla, bisognerà inserirla insieme alle altre resource presenti nel nostro server, quindi spostate la cartella in:
[B]modsdeathmatchresource
Per prima cosa creiamo il file [B]meta.xml[/B]
Questo è il file piu importante di ogni resource, contiene le informazioni della resource, gli script, e tutti i files da usare.
Ad esempio, dovete scrivere in questo file il nome degli script e i file da caricare, che possono essere delle immagini png, modelli dff, texture TXD, collision COL oppure i suoni personalizzati, cioe ogni cosa che aggiungerete nella cartella della vostra resource deve essere scritta qua, in modo da essere caricata all'avvio della resource.
Ora invece occupiamoci della nostra resource, che per ora, conterrà solo lo script server side, quindi creiamo il file meta.xml e apriamolo con word o con il blocco note.
* *Dopo aver creato questo file abbiamo già stabilito il nome dell'autore, il tipo(gamemode) il nome della resource e una breve descrizione.* * < script src="script.lua" />
[B]Tutte le informazioni sul meta.xml le trovate >Qui.[/B]
Ora invece, create appunto il file "script.lua" ovvero, lo script server side.
Bene, per primo bisogna stabilire gli obbiettivi o quello che contiene la resource, in questo caso, faremo in modo che il player venga spawnato quando la resource inizia, quando un player entra e scripteremo il respawn alla morte.
Iniziamo, ora scriptiamo cosa succede all'inizio della resource, ovvero quando la resource viene avviata con l'evento "onResourceStart"
function resourceStarting ( ) outputChatBox ( "La resource è stata caricata" ) end addEventHandler ( "onResourceStart", getResourceRootElement(), resourceStarting )Esaminiamo bene questa parte
[B]function resourceStarting( )[/B] : "resourceStarting" è il nome che ho dato a questa funzione personalizzata, al suo interno puo' contenere altre funzioni.
[B]outputChatBox ( "La resource è stata caricata" )[/B] : funzione che permette di mandare messaggi nella chatbox. In questo caso, manda un messaggio a tutti i players, avvisando che la resource è stata caricata.
[B]end[/B] : "end" serve per chiudere la nostra funzione.
[B]addEventHandler ( "onResourceStart", getResourceRootElement(), resourceStarting )[/B] : E infine, aggiungiamo l'evento tramite addEventHandler, come potete notare la funzione addEventHandler chiama gli eventi, nelle parentesi potete notare i 3 argomenti fondamentali:
- onResourceStart : l'evento da chiamare.
- getResourceRootElement() : l'elemento a cui è legato l'evento in questione, in questo caso è getResourceRootElement() ovvero la resource stessa.
Di solito viene usato getRootElement() ma cosi facendo l'evento viene chiamato ogni volta che una resource, anche all'infuori di questa, viene caricata. - resourceStarting : la funzione che da attivare quando viene chiamato l'evento.
Bene, ora iniziamo a scriptare una funzione personalizzata che spawna il player, per iniziare, dobbiamo fare in modo che quando la resource inizia tutti i player vengono spawnati, quindi aggiungiamo nuove righe al nostro precedente codice:
function resourceStarting ( ) outputChatBox ( "La resource è stata caricata" ) for i,player in ipairs(getElementsByType("player")) do *spawnThePlayer(player) end end addEventHandler ( "onResourceStart", getResourceRootElement(), resourceStarting )[B]for i,player in ipairs(getElementsByType("player")) do[/B] : questo fa in modo che le funzioni qui dentro vengano chiamate per tutti i players
[B]spawnThePlayer(player)[/B] : attiva la funzione spawnThePlayer, che stiamo per creare.
[B]end[/B] : come avete notato, ci sono 2 end, il primo chiude il "for i,player[...]", il secondo e ultimo invece, chiude la nostra funzione(resourceStarting).
Ora ci tocca creare la funzione "spawnThePlayer" che abbiamo inserito prima, faremo in modo che quando questa funzione viene chiamata, il player viene spawnato all'entrata dell'aereoporto di Las Venturas.
function spawnThePlayer(player) spawnPlayer(player, 1718.408, 1612.0, 10.0) fadeCamera(player, true) setCameraTarget(player, player) end *[B]function spawnThePlayer(player) [/B] : il nome della funzione
[B]spawnPlayer(player, 1718.408, 1612.0, 10.0)[/B] : spawna il player alle seguenti cordinate (x,y,z)
[B]fadeCamera(player, true) [/B] : sbiadisce la telecamera quando il valore è "True"
[B]setCameraTarget(player, player) [/B] : imposta come bersaglio della telecamera il player stesso.
Dopo aver effettuato quest'operazione, ogni volta che la resource viene avviata tutti i players spawneranno all'aereoporto di LV, però dobbiamo fare in modo che il player spawni anche quando si connette al server e che ogni volta che muore venga rispawnato.
Partiamo dal far spawnare il player quando si connette, inoltre mandiamo un messaggio di benvenuto.
function playerJoins( ) spawnThePlayer(source) local connectedPlayerName = getPlayerName ( source ) local serverName = getServerName( ) -- stessa cosa di prima, ma questa volta si parla del nome del server. outputChatBox ( "Benvenuto " .. connectedPlayerName .. " su " .. serverName .. "!" , source, 255, 255, 255 ) end addEventHandler ( "onPlayerJoin", getRootElement(), playerJoins)[B]NOTA[/B]: "source" è l'elemento che ha chiamato l'evento, in questo caso, è il player che è entrato nel server.
[B]NOTA_2[/B]: Nell'addEventHandler ho scritto: getRootElement() perche l'evento è legato all'elemento(il player), non alla resource.
[B]spawnThePlayer(source)[/B]: Attiva la funzione all'elemento "source" ovvero il player(vedi sopra)
Se avete notato, ho aggiunto un "outputChatBox" che manda un messaggio tipo "Benvenuto
è bastato usare 2 funzioni, ovvero getPlayerName(source) e getServerName().
Prendiamo ad esempio [B]local serverName = getServerName( )[/B] : Ho fatto in modo che, solo per questa funzione(grazie a "local") scrivere "serverName" equivale a scrivere getServerName( ).
Per ultimo facciamo in modo che quando il player muore, respawna, visto che come ho già detto, a differenza di samp dove il player respawna automaticamente dopo la sua morte, qui c'è da scriptare l'evento, quindi ora farò in modo che dopo 2 secondi dalla morte del player, si attivi la nostra funzione che spawna il player.
function onPlayerDeath( ) setTimer(spawnThePlayer, 2000, 1, source) end addEventHandler ( "onPlayerWasted", getRootElement(), onPlayerDeath )Mi è bastato usare un semplice timer per provocare il respawn del player.
Una volta finito, salvate il file (CTRL + S oppure File -> Save) avremmo completato la nostra prima resource([B]*[/B]), ripetendo quello che abbiamo scriptato abbiamo fatto in modo che:
- Quando la resource inizia tutti i player connessi vengono spawnati
- Ogni player che entra anche dopo lo start della resource verra spawnato con un messaggio di benvenuto.
- Alla morte del player, ci sarà il respawn.
(*) = Visto che stiamo scriptando in lua e non in pawno, non c'è il bisogno di compilare.
Ora abbiamo creato una base per scrivere una resource-gamemode.
[B]Potete trovare lo script di questa resource su pastebin >Link[/B]
[B]Scrivere una resource: I Command Handler[/B]
Sono semplicemente gli eventi che vengono chiamati su comando, ad esempio: /heal, /me ...
La sintassi per aggiungere il command handler è questa:
addCommandHandler ( "comando", funzione, ristretto(vero/falso), case sensitive(vero/falso))
il commando deve essere scritto senza il '/', faccio un esempio:
Giusto: addCommandHandler ( "buy", negozioArmi)
Sbagliato: addCommandHandler ( "[B]/[/B]buy", negozioArmi)
Potete aggiungere questi Command Handler sullo script di prima senza creare un altra resource..
E ora si fa un po di pratica con 2 tipi di command handler, quello che si attiva scrivendo il semplice senza argomenti come "/vita", e quello un po piu' complessi con vari argomenti tipo "/creaveicolo
Iniziamo con un semplice comando "/vita" che ripristina l'energia del player, è manda un messaggio di errore se il player non ne ha bisogno.
function ripristinaVita (source) local hp = getElementHealth(source) if hp < 100 then outputChatBox ("La tua vita è stata ripristinata", source, 255, 255, 255, true ) setElementHealth (source, 100) else outputChatBox ("Non hai bisogno di ripristinare la tua vita.", source, 255, 255, 255, true ) end end addCommandHandler ( "vita", ripristinaVita )[B]local hp = getElementHealth(source)[/B]: facciamo in modo che "hp" equivale a scrivere "getElementHealth(source)"
[B]if hp < 100 then [/B]: funzione del lua, "se hp < 100 allora" che significa, se gli hp del player, sono meno di 100[B]...[/B]
[B]setElementHealth (source, 100)[/B]: [B]...[/B]imposta 100hp al player
[B]else[/B]: altrimenti[B]...[/B] (se il player non ha meno di 100 hp)
[B]outputChatBox[...][/B]: [B]...[/B] manda un messaggio al player scrivendo che non ne ha bisogno.
[B]end[/B]: il primo serve a chiudere il "IF, ELSE" e il secondo a chiudere la funzione.
Ora abbiamo creato il comando "/vita" che imposta la vita a 100hp se il player stesso che esegue il comando, ha meno di 100hp.
Ora invece occupiamoci di creare un comando che crea un veicolo e imposta i 2 colori principali
Per fare questo, ci basterà aggiungere gli argomenti alla funzione del comando.
infatti, bastera aggiungere dei nuovi argomenti delle parentesi, oltre al "source" dovete aggiungere il nome del comando e poi gli argomenti che vengono dopo, ad esempio:
function funzioneComando (source, nomeCmd, argomento1, argomento2, argomento3)
per chi non ha ancora capito, ogni volta che il player esegue il comando, si ha questo:
/nomeCmd argomento1 argomento2 argomento3
In questo caso abbiamo scelto 3 argomenti, ma possiamo sceglierne di piu o di meno.
[B]NOTA[/B]: i nomi degli argomenti possono essere personalizzati, come potete vedere sotto nel codice:
function creaVeicolo (source, nomeComando, modello, colore1, colore2) end addCommandHandler ( "creaveicolo", creaVeicolo)Oltre a source(il player che esegue il comando) e nomeComando("creaveicolo") ho aggiunto altri 3 argomenti che ho rinominato a mio piacere per non fare confusione:
[B]modello[/B]: "Argomento 1" id del modello del veicolo.
[B]colore1[/B]: "Argomento 2" id del primo colore.
[B]colore2[/B]: "Argomento 3" id del secondo colore.
Facciamo in modo che il veicolo venga spawnato vicino e non sul player:
function creaVeicolo (source, nomeComando, modello, colore1, colore2) local x,y,z = getElementPosition(source) x = x + 4 local veicoloCreato = createVehicle(tonumber(modello),x,y,z) end addCommandHandler ( "creaveicolo", creaVeicolo)
local x,y,z = getElementPosition(source): Prende le cordinate del player
x = x + 4 : Aggiunge 4 unita alla variabile x del player (in modo spawni vicino e non sul player)
local veicoloCreato = createVehicle(tonumber(modello),x,y,z): veicoloCreato è veicolo che abbiamo appena creato.
Ora per ultimo, facciamo in modo che se il veicolo non puo essere creato oppure se il valore dei colori è errato:
function creaVeicolo (source, nomeComando, modello, colore1, colore2) local x,y,z = getElementPosition(source) x = x + 4 local veicoloCreato = createVehicle(tonumber(modello),x,y,z) if (veicoloCreato *== false ) then *outputChatBox("Errore nella creazione del veicolo.",source) * * outputChatBox("Uso: /creaveicolo [id veicolo] [colore1] [colore2] ",source) * elseif (veicoloCreato and colore1 ~= nil and colore2 ~= nil) then setVehicleColor ( veicoloCreato, tonumber(colore1), tonumber(colore2), 0, 0) end end addCommandHandler ( "creaveicolo", creaVeicolo)[color=yellow]if (veicoloCreato == false ) then: "se (veicoloCreato == falso) allora" -> se il veicolo non esiste o non e stato creato allora...
outputChatBox[...]: ... manda un messaggio di errore e uno per informare al player come usare il commando..
elseif (veicoloCreato and colore1 ~= nil and colore2 ~= nil) then: "invece se (veicoloCreato e colore1
setVehicleColor ( veicoloCreato, tonumber(colore1), tonumber(colore2), 0, 0): ...imposta i 2 colori all'auto.
Altro:
tonumber: come avrete notato, ho usato la funzione del lua "tonumber" per il modello e i colori dell'auto, in quanto sono numeri. Questa funzione converte in numero l'argomento (quando l'argomento non è un numero) altrimenti argomento risulta nullo.
E con questo, il comando è pronto e funzionante.
Script di base con i 2 command handler aggiunti disponibile su Pastebin! >Link
Funzioni utili per uno script: comunicazione tra script server-side e script client-side, i triggers
Usando come base la resource di prima, creiamo il file script_client.lua e apriamo il file meta.xml e inseriamo questa riga
< script src="script_client.lua" type="client" />quindi abbiamo definito che script_client.lua è dal lato client.
Per fare un esempio veloce, creeremo un command handler dal lato server che una volta eseguito, innesca per il player un evento sul lato client(trigger)
quindi, dal lato server scriptiamo il command handler, che una volta eseguito chiama un evento creato sul lato client.
function cmdFuoco ( ilPlayer, nomeCmd ) * *triggerClientEvent ( "onCallingFire", ilPlayer) end addCommandHandler ( "fuoco", cmdFuoco )triggerClientEvent : La funzione che chiama un evento che si trova dal lato client.
"onCallingFire" : è l'evento da chiamare, in questo caso è un evento personalizzato e quindi dal lato client si usa la funzione "AddEvent" come vedremo piu' avanti.
ilPlayer : l'origine della funzione.
ora creiamo l'evento e la funzione dal lato client.
function creaFuoco () local pX, pY, pZ = getElementPosition ( getLocalPlayer()) createExplosion ( pX, pY, pZ, 12, false,0.0, false) end addEvent( "onCallingFire", true ) addEventHandler( "onCallingFire", getRootElement(), creaFuoco )Partiamo col dire che addEvent registra un evento personalizzato, e AddEventHandler lo aggiunge, infatti il trigger va a "chiamare" l'evento aggiunto "onCallingFire".
invece, createExplosion ( pX, pY, pZ, 12, false,0.0, false) crea una piccola esplosione, che non fa rumore e non danneggia il player.
Riepilogando, ogni volta che il player esegue il comando /fuoco viene chiamato un evento dal lato client, che crea una piccola esplosione indolore sul player.
Per ora la mia guida finisce qua, se avete qualche domanda su qualcosa che non vi è chiaro scrivete pure in questo topic e se notate qualche errore nella guida sarei grato se me la segnalate.
Guida creata interamente dal sottoscritto MarkGta, ringraziamenti vanno ad: Alex26(Aiuti/Consigli vari), il team MTA e i traduttori della wiki italiana.
This work is licensed under a Creative Commons Attribuzione-Non commerciale-Non opere derivate 3.0 Unported License.
Messaggio modificato da MarkGta il 30 aprile 2010 - 19:58