API Lua

Les fonctions globales disponibles dans les scripts des addons et des gamemodes. L'API s'inspire de Garry's Mod, en mètres. Certaines n'existent que côté serveur ou côté client (voir Lua client et réseau).

Où tourne le Lua ?Dans deux royaumes, comme dans GMod : le serveur (le joueur qui héberge, ou le serveur dédié) fait les règles du jeu, et chaque joueur a un client pour son interface, son HUD et ses effets. Les fichiers client sont envoyés aux joueurs à leur arrivée. Le badge serveur marque les fonctions réservées au serveur. Voir Lua côté client.

Fonctions utilitaires

print(...)

Écrit ses valeurs (autant qu'on veut, séparées par une tabulation ; nil s'écrit nil) dans la console du jeu, préfixées par [Lua].

print("Joueurs connectés :", #player.GetAll())

PrintMessage(texte)

Envoie un message système (en bleu clair) dans le chat de tous les joueurs.

PrintMessage("La partie redémarre dans 30 secondes !")

CurTime() → nombre

Temps écoulé en secondes depuis le lancement du jeu. Pratique pour mesurer une durée.

Vector(x, y, z) → Vector

Crée un vecteur 3D (en mètres, Y vers le haut). Les valeurs absentes valent 0.

UtilisationRésultat
v.x, v.y, v.zLire ou modifier une composante (v.y = 10)
a + b, a - b, v * 2Opérations vectorielles
v:length()Longueur (mètres)
v:normalized()Vecteur de longueur 1
a:distance_to(b)Distance entre deux points
a:dot(b), a:cross(b)Produit scalaire, produit vectoriel
v:Length(), a:Distance(b), v:GetNormalized(), v:Angle(), v:ToScreen()…Noms Garry's Mod (voir Angles et vecteurs, ToScreen)
local haut = ply:GetPos() + Vector(0, 3, 0)  -- 3 mètres au-dessus du joueur

Angle(pitch, yaw, roll) → Angle

Un angle en degrés (un Vector, avec ang:Forward(), ang:Right(), ang:Up(), ang:RotateAroundAxis()). Pitch positif = vers le haut. Aides : Lerp, LerpVector, LerpAngle, math.Clamp, math.Round, math.Approach, math.Remap, math.NormalizeAngle, VectorRand, AngleRand. Voir Angles et vecteurs.

Color(r, g, b, a) → Color

Crée une couleur avec des composantes de 0 à 255 (comme GMod). a (opacité) vaut 255 par défaut.

prop:SetColor(Color(255, 120, 0))  -- orange
AttentionUne couleur lue (par exemple avec prop:GetColor()) a ses composantes entre 0 et 1, pas 0 et 255.

Msg(...), IsValid(objet) → booléen

Msg et MsgN écrivent leurs valeurs collées les unes aux autres (sans séparateur), sur une ligne. IsValid vaut true si le joueur ou l'entité existe encore (accepte aussi nil).

SERVER, CLIENT

Booléens : on est dans un script serveur ou client.

Variables réseau globales

SetGlobalInt(nom, valeur) (serveur) et GetGlobalInt(nom, défaut) (partout), ainsi que Float, Bool, String, Vector, Angle et Entity. Les noms SetGlobal2… / GetGlobal2… désignent les mêmes variables. Voir Variables NW et NW2 et Variables réseau.

Types, conversions et erreurs

FonctionRôle
isfunction, isstring, isnumber, istable, isbool, isvector, isangle, IsColor, isentity / IsEntity, ispanel, ismatrixLe type d'une valeur. Un angle étant un Vector, isvector et isangle acceptent les deux ; isentity vaut vrai pour une entité, un PNJ ou un joueur (ply:IsPlayer() pour les distinguer) ; ismatrix vaut toujours false.
tobool(v)false pour nil, false, 0, "0", "false" et "" ; true sinon.
ErrorNoHalt(...), ErrorNoHaltWithStack(...)Écrit [erreur] message dans la console sans arrêter le script (le second ajoute la pile d'appels).
PrintTable(t)Écrit une table et ses sous-tables, indentées et triées par clé.
AccessorFunc(tab, champ, nom, force)Crée tab:GetNom() et tab:SetNom(v) qui lisent et écrivent tab[champ]. force : FORCE_STRING, FORCE_NUMBER ou FORCE_BOOL convertissent la valeur ; FORCE_ANGLE, FORCE_COLOR et FORCE_VECTOR existent mais ne convertissent rien.
baseclass.Get(nom), baseclass.Set(nom, table)Tables de base partagées (le DEFINE_BASECLASS de GMod) : Get renvoie toujours la même table pour un nom, Set la remplit.
local PANNEAU = {}
AccessorFunc(PANNEAU, "m_iPrix", "Prix", FORCE_NUMBER)
PANNEAU:SetPrix("50")
print(PANNEAU:GetPrix() + 1)  -- 51

Aides

Texte : string.Explode(séparateur, texte, motif) (découpe ; motif = true : le séparateur est un motif Lua), string.Split(texte, séparateur), string.Implode(séparateur, liste), string.Trim(texte, caractères), string.TrimLeft, string.TrimRight, string.StartWith / StartsWith(texte, début), string.EndsWith(texte, fin), string.Left(texte, n), string.Right(texte, n), string.Replace(texte, cherché, remplacement) (sans motif), string.PatternSafe(texte) (échappe les caractères spéciaux des motifs), string.ToTable(texte) (un caractère par case).

string.FormattedTime(secondes) donne "mm:ss" ; table.Count(t), table.HasValue(t, v), table.Random(t), table.Copy(t) (copie profonde) ; unpack est le même que table.unpack. Les autres aides de Garry's Mod sont dans Bibliothèques table, math, string et bit.

Bibliothèques table, math, string et bit

Les extensions des bibliothèques standard que les addons GMod utilisent, avec les mêmes noms et le même comportement (des deux côtés).

BibliothèqueFonctions
tableMerge(dest, source) (récursif), Inherit(t, base) (remplit les clés absentes, t.BaseClass = base), GetKeys, IsEmpty, Empty, ClearKeys, KeyFromValue, KeysFromValue, RemoveByValue, SortByMember(t, membre, croissant), SortByKey(t, décroissant) (clés triées par valeur), Reverse, Add(dest, source), Shuffle, Flip (valeurs ↔ clés), IsSequential, GetFirstKey / GetFirstValue, GetLastKey / GetLastValue, GetWinningKey (clé de la plus grande valeur), MemberValuesFromKey, LowerKeyNames, FindNext / FindPrev (en boucle), ForceInsert, maxn, ToString(t, nom, joli), Sanitise
mathRand(min, max) (décimal), Truncate(n, chiffres), SnapTo(n, pas), TimeFraction(début, fin, t), AngleDifference(a, b), ApproachAngle, Dist, IsNearlyEqual(a, b, tolérance), EaseInOut, IntToBin / BinToInt, Factorial ; courbes math.ease.InSine, OutSine, InOutSine, InQuad, OutQuad, InOutQuad, InCubic, OutCubic, InOutCubic, InExpo, OutExpo, InBack, OutBack, OutElastic, InBounce, OutBounce (fraction de 0 à 1)
stringComma(n, séparateur) (1,234,567), NiceTime(s) (en français : "3 minutes"), NiceSize(octets) ("1.50 Ko"), ToMinutesSeconds, ToMinutesSecondsMilliseconds, ToColor("255 0 0 255"), FromColor(couleur) (texte de 0 à 255), GetExtensionFromFilename, GetFileFromFilename, GetPathFromFilename, StripExtension, SetChar, JavascriptSafe, Interpolate("{nom}", valeurs), CardinalToOrdinal ("1er", "2e"), NiceName, utf8len
bitOpérations sur 32 bits signés, comme LuaBitOp : tobit, band, bor, bxor, bnot, lshift, rshift, arshift, rol, ror, bswap, tohex(n, chiffres)
print(string.Comma(1500000))                          -- 1,500,000
print(string.NiceTime(7200))                          -- 2 heures
print(string.Interpolate("{nom} a {n} PV", { nom = "Alex", n = 80 }))
print(bit.band(0xFF, 0x0F), bit.tohex(255, 4))        -- 15  00ff
local x = Lerp(math.ease.OutBounce(0.5), 0, 100)

util, temps et engine

FonctionRôle
util.Compress(texte) / util.Decompress(texte, max)Compresse un texte (16 Mo au plus) en un texte base64, et l'inverse (nil si invalide ou plus grand que max octets). Format propre à PhysiCore : ne se lit pas avec le util.Decompress de GMod.
util.Base64Encode(texte, sansRetours) / util.Base64Decode(texte)Base64 (un retour à la ligne tous les 76 caractères, comme GMod, sauf si sansRetours).
util.CRC(texte)CRC-32, en texte (nombre positif).
util.SHA256(texte), util.SHA1, util.MD5Empreintes en hexadécimal.
util.SharedRandom(nom, min, max, graine)Nombre « au hasard » identique sur le serveur et chez chaque joueur pour le même nom et la même graine.
util.Stack()Une pile : :Push(v), :Pop(n), :PopMulti(n) (table), :Top(), :Size(), :Clear().
util.KeyValuesToTable(texte, échappements, garderCasse) / util.TableToKeyValues(t, racine)Format KeyValues de Valve ("clé" "valeur", blocs { }, commentaires //). Les clés sont mises en minuscules sauf si garderCasse ; les nombres sont convertis.
util.TypeToString(v) / util.StringToType(texte, type)Valeur ↔ texte ("1 2 3" pour un vecteur, "255 0 0 255" pour une couleur) ; type : "string", "number", "bool", "vector", "angle".
util.IsValidPhysicsObject(ent)Vrai si l'entité est valide et a un objet physique.
util.AddNetworkString(nom), util.NetworkStringToID, util.NetworkIDToStringRien à déclarer dans PhysiCore (tout nom de message net marche) : gardées pour que les scripts GMod tournent tels quels.
FrameTime(), RealFrameTime()Durée de la dernière image (secondes).
RealTime(), SysTime()Secondes depuis le lancement du jeu, avec une précision de la microseconde (pas l'horloge du serveur : voir CurTime).
engine.TickInterval(), engine.TickCount()Durée d'une image physique (1/60 s) ; nombre d'images physiques depuis le lancement.
engine.ActiveGamemode()Nom du gamemode en cours.

include et AddCSLuaFile

include("fichier.lua") lance un autre fichier du même addon ou gamemode et renvoie ce qu'il renvoie (return … en fin de fichier). Le chemin est cherché à côté du fichier en cours, puis depuis la racine (lua/ d'un addon, le dossier d'un gamemode) ; impossible de sortir de l'addon. À appeler depuis un fichier (pas depuis la console), 32 inclusions imbriquées au plus.

Côté client, include ne trouve que les fichiers que le serveur a envoyés : les fichiers client et partagés, et ceux que le serveur a marqués avec AddCSLuaFile("fichier.lua") (sans argument : le fichier en cours). Un fichier marqué est seulement envoyé, pas lancé : c'est include qui le lance chez le joueur.

-- lua/autorun/monaddon.lua (partagé)
AddCSLuaFile("monaddon/config.lua")
local config = include("monaddon/config.lua")  -- lua/monaddon/config.lua : return { prix = 50 }
print("Prix :", config.prix)

hook : événements

hook.Add(événement, identifiant, fonction)

Appelle fonction à chaque fois que l'événement se produit. L'identifiant est un nom unique (texte) : ajouter un hook avec le même événement et le même identifiant remplace le précédent. Liste des événements : Hooks.

hook.Add("PlayerDeath", "monaddon_mort", function(ply, cause)
	PrintMessage(ply:Name() .. " " .. cause .. " !")
end)

hook.Remove(événement, identifiant)

Retire un hook ajouté avec hook.Add.

Le jeu sait quels événements ont au moins un hook (ou une méthode du gamemode) : certains, comme les hooks de déplacement, ne sont appelés que s'ils sont utilisés et ne coûtent rien sinon.

hook.Run(événement, ...) → valeur

Déclenche toi-même un événement (avec jusqu'à 3 arguments), y compris un événement inventé pour faire communiquer tes addons. Renvoie la première valeur non nil renvoyée par un hook.

Rechargement à chaud, débogueur et profileur

Un fichier Lua d'addon ou de gamemode enregistré pendant la partie (dans l'éditeur de code ou ailleurs) est ré-exécuté seul, sur le serveur et chez chaque joueur, sans redémarrer : variables, joueurs et entités sont gardés, les fonctions de GM, ENT et SWEP sont remplacées en place, puis le hook OnReloaded est lancé. Un hook.Add ou un timer.Create avec le même identifiant remplace l'ancien. Voir Autorefresh.

L'éditeur de code a aussi un débogueur (points d'arrêt, pas à pas, variables locales, pause sur erreur) et un profileur (temps passé par fonction et par hook).

concommand : commandes de chat

concommand.Add(nom, fonction, autoComplete, aide, flags)

Crée une commande que les joueurs tapent dans le chat : /nom arguments…. Le nom est insensible à la casse. Existe des deux côtés : une commande créée côté serveur tourne sur le serveur ; une commande créée côté client tourne sur l'ordinateur du joueur qui la tape, sans rien envoyer au serveur (elle est essayée en premier). La fonction reçoit :

ArgumentContenu
plyLe Player qui a tapé la commande (côté client : son propre joueur)
argsTable des mots après la commande (args[1], args[2]…)
argStrTous les arguments en un seul texte
cmdLe nom de la commande (en minuscules)

L'ordre de Garry's Mod, function(ply, cmd, args, argStr), marche aussi : si le deuxième paramètre de la fonction s'appelle cmd, command, com, c, name, concommand… le jeu passe les arguments dans cet ordre-là.

autoComplete(cmd, texteArgs) (facultatif) renvoie une liste de lignes complètes ("nom arg") : pour une commande client, la touche Tab dans le chat complète avec ces lignes (sans fonction, Tab complète les noms des commandes client). aide et flags sont acceptés comme dans GMod.

concommand.Add("vie", function(ply, args)
	local valeur = tonumber(args[1]) or 100
	ply:SetHealth(valeur)
	ply:ChatPrint("Santé réglée à " .. valeur)
end)
-- En jeu : /vie 250

-- Côté client, à la façon de GMod, avec complétion par Tab.
concommand.Add("couleur_hud", function(ply, cmd, args)
	print("Couleur choisie :", args[1])
end, function(cmd, texte)
	return { cmd .. " rouge", cmd .. " vert", cmd .. " bleu" }
end, "Change la couleur du HUD")

concommand.Remove(nom), concommand.Run(ply, nom, args, argStr), concommand.GetTable()

Remove supprime une commande. Run lance une commande Lua de ce côté (false si elle n'existe pas). GetTable renvoie deux tables, comme GMod : les fonctions des commandes et leurs fonctions d'autocomplétion, par nom.

Commandes intégrées

CommandeEffet
/killLe joueur meurt (ragdoll), puis clique pour réapparaître.
/cleanupSupprime tous les props du joueur.

Pour lancer du Lua à la main, les admins ont /lua_run, /lua_openscript et /lua_run_cl (voir Commandes admin). Côté serveur, game.ConsoleCommand("commande arg\n") lance des lignes comme la console du serveur (plusieurs séparées par ; ou des retours à la ligne) : say texte, une ConVar (sbox_maxprops 300), une commande admin sans le / (kick, map…) ou une commande concommand.

Côté serveur, les commandes intégrées passent avant celles des addons : un addon ne peut pas les remplacer. Une commande client du même nom serait essayée avant, chez ce joueur seulement : évite ces noms. Une commande inconnue affiche « Commande inconnue ».

player : joueurs

player.GetAll() → table

Liste (table indexée à partir de 1) de tous les joueurs présents sur la carte, sous forme d'objets Player.

for _, ply in ipairs(player.GetAll()) do
	ply:ChatPrint("Coucou !")
end

player.GetByID(id) → Player ou nil

Le joueur dont l'identifiant réseau vaut id (voir ply:UserID() ; l'hôte vaut 1).

player.GetCount() → entier

Nombre de joueurs en jeu.

player.GetBySteamID(id) → Player ou nil

Le joueur dont ply:SteamID() vaut id (texte). Aussi player.GetBySteamID64.

ents : props et entités

ents.SpawnProp(modèle, position, lacet) → Prop ou nil

Fait apparaître un prop. modèle est un identifiant de prop ("builtin:crate", "addon:…" ; voir les identifiants), position un Vector, lacet une rotation autour de l'axe vertical en degrés (0 par défaut). Renvoie nil si le modèle n'existe pas.

Un prop créé par Lua appartient au « monde » : il ne compte dans la limite d'aucun joueur et ne peut pas être annulé avec la touche d'annulation.

local caisse = ents.SpawnProp("builtin:crate", Vector(0, 5, 0), 45)
if caisse then
	caisse:SetColor(Color(80, 160, 255))
end

ents.GetAll() → table

Tous les props présents (objets Entity), y compris les gadgets du toolgun et les entités scriptées.

ents.FindByClass(classe) → table

Les entités d'une classe ("prop_physics" pour les props ordinaires).

ents.Create(classe) → Entity serveur

Prépare une entité scriptée ; règle-la puis appelle ent:Spawn(). Aussi ents.Create("prop_ragdoll") (un corps en ragdoll) et les classes ENT.Base = "base_nextbot" (des PNJ pilotés en Lua : RunBehaviour, loco, Path, navmesh ; voir PNJ).

Entités scriptées : ENT.Type ("anim", "point", "brush"), ENT:Think des deux côtés avec ent:NextThink, ENT:StartTouch / Touch / EndTouch avec ent:SetTrigger et ent:SetCollisionBounds, ent:SetSolid, ent:PhysicsInit, ent:SetCustomCollisionCheck (hook ShouldCollide), santé (ent:Health, SetMaxHealth), frottement et rebond, et les contraintes constraint.Winch, Hydraulic, Muscle, Motor, Pulley, AdvBallsocket. Voir Entités scriptées et Monde et physique.

Recherche

ents.FindInSphere, ents.FindInBox(min, max), ents.FindInCone(origine, direction, distance, cosAngle), ents.FindByModel(id), ents.GetByIndex(index) et ents.FindByName(nom) (entités et zones placées dans une map). Voir Chercher des entités.

protection : protection des props

Les règles de la protection des props réglées par l'hôte dans le menu de spawn. Des deux côtés (le client connaît les règles du serveur et les amis de chacun) ; c'est le serveur qui fait foi.

protection.CanTouch(ply, ent, action) → booléen

Vrai si le joueur peut faire action sur ent (prop, véhicule ou PNJ) : "physgun", "toolgun", "use", "damage" ou "enter" (monter dans un véhicule). Tient compte du hook ProtectionCanTouch, des amis, des props de la carte et des admins. Toujours vrai en solo ou si la protection est désactivée.

protection.IsEnabled() → booléen, protection.GetSettings() → table

Si la protection agit (partie en ligne, activée par le serveur, pas coupée par GM.PropProtection = false), et une copie des règles : enabled, rules[action][type] ("owner", "buddies", "everyone" ; types "prop", "vehicle", "npc"), map[action] et unowned[action] ("nobody", "admins", "everyone"), admins[action] ("nobody", "superadmins", "admins"), sharing, cleanup_delay (secondes, -1 = jamais), cleanup_admins, notify.

CPPI

L'interface commune des protections de Garry's Mod, pour les addons qui l'utilisent : CPPI.GetName(), CPPI.GetVersion(), CPPI.GetInterfaceVersion(), CPPI.GetNameFromUID(id) ; sur un prop ou un PNJ, ent:CPPIGetOwner() (le joueur, ou nil), ent:CPPICanPhysgun(ply), ent:CPPICanPickup(ply), ent:CPPICanPunt(ply), ent:CPPICanTool(ply, outil), ent:CPPICanUse(ply), ent:CPPICanDamage(ply), ent:CPPICanEnter(ply), et côté serveur ent:CPPISetOwner(ply) ; sur un joueur, ply:CPPIGetFriends() (les joueurs qu'il autorise sur ses props pour au moins une action).

-- Un outil Lua qui ne marche que sur les props qu'on a le droit de toolgun.
function TOOL:LeftClick(trace)
	local ent = trace.Entity
	if not IsValid(ent) or not protection.CanTouch(self:GetOwner(), ent, "toolgun") then
		return false
	end
	-- …
end

team : équipes

team.SetUp(numéro, nom, couleur) (dans un fichier partagé), team.GetName, team.GetColor, team.Valid, team.GetAllTeams(), team.GetPlayers(n), team.NumPlayers(n), team.GetScore(n) ; côté serveur team.SetScore(n, s) et team.AddScore(n, points). Voir Équipes, points et manches.

net : messages réseau

net.Start(nom), net.Write…, puis un envoi ; l'autre côté reçoit avec net.Receive(nom, function(taille, ply) … end) et lit avec net.Read… dans le même ordre. Les noms ignorent la casse ("MonMessage" arrive à net.Receive("monmessage")) et n'ont pas besoin d'être déclarés. Guide et exemple : Messages net.

FonctionsRôle
WriteString, WriteInt(n, bits), WriteUInt(n, bits), WriteFloat, WriteDouble, WriteBool, WriteBit, WriteVector, WriteAngle, WriteNormal, WriteColor, WriteEntity, WriteTableÉcrire une valeur ; les Read… correspondants la relisent. WriteInt / WriteUInt bornent la valeur à ce que tiennent bits bits ; ReadBit renvoie 0 ou 1 ; WriteNormal envoie le vecteur normalisé.
WriteData(données, longueur) / ReadData(longueur)Octets bruts (contenu d'un fichier, texte compressé…), intacts même s'ils ne sont pas du texte valide.
WriteType(v) / ReadType()Une valeur avec son type : nil, nombre, texte, booléen, table, vecteur, couleur ou entité (pas un joueur : envoie-le avec WriteEntity). Constantes TYPE_NIL, TYPE_BOOL, TYPE_NUMBER, TYPE_STRING, TYPE_TABLE, TYPE_ENTITY, TYPE_VECTOR, TYPE_COLOR…
BytesWritten(), BytesLeft()Taille (approchée) déjà écrite / qui reste à lire : octets, puis bits en deuxième valeur.
Abort()Abandonne le message commencé.
Receive(nom, nil), net.ReceiversRetire un récepteur ; net.Receivers[nom en minuscules] liste les fonctions enregistrées.
Send(ply ou liste), Broadcast(), SendOmit(ply ou liste) serveurÀ ces joueurs, à tous, à tous sauf ceux-là.
SendPVS(pos), SendPAS(pos) serveurAux joueurs à moins de 250 m de pos (PhysiCore n'a pas d'ensembles de visibilité).
SendToServer() (client)Au serveur.

Limites : 256 valeurs et 64 Kio par message (et par texte), 60 messages par seconde pour chaque joueur.

-- serveur : envoie un fichier de données aux joueurs à moins de 250 m d'un point
net.Start("plan")
net.WriteType(CurTime())
net.WriteData(util.Compress(file.Read("plan.json") or ""))
net.SendPVS(Vector(0, 0, 0))

-- client
net.Receive("plan", function(taille)
	local quand = net.ReadType()
	local plan = util.Decompress(net.ReadData())
end)

Variables NW et NW2

Sur un joueur ou une entité : ent:SetNWInt(nom, v) (serveur) et ent:GetNWInt(nom, défaut) (partout), avec les types Int, Float, Bool, String, Vector, Angle et Entity (l'entité est retrouvée à la lecture, nil si elle n'existe plus). Les noms SetNW2… / GetNW2… (et SetGlobal2… / GetGlobal2…) désignent les mêmes variables.

FonctionRôle
ent:SetNWVarProxy(nom, fonction) (aussi SetNW2VarProxy)fonction(ent, nom, ancienne, nouvelle) est appelée quand la variable change, de ce côté (serveur, et chez chaque joueur à l'arrivée de la valeur). nil la retire.
ent:GetNWVarProxy(nom)La fonction enregistrée.
ent:GetNWVarTable() (aussi GetNW2VarTable)Toutes les variables de l'entité : { nom = valeur }.

Le hook EntityNetworkedVarChanged est lancé après le proxy, pour toutes les entités.

-- client : réagir au changement de son propre rôle sans tester à chaque image
hook.Add("ClientReady", "role_proxy", function()
	LocalPlayer():SetNWVarProxy("role", function(ply, nom, ancien, nouveau)
		chat.AddText("Tu deviens " .. tostring(nouveau))
	end)
end)

game et gamemode

game.ChangeMap(id, gamemode) (serveur) change de map et game.GetMapList() donne les maps disponibles (voir Changer de map). game.CleanUpMap() (serveur) supprime tous les props et remet ceux de la map ; game.GetMap() donne son nom ; game.GetServerSetting(clé) lit un réglage de partie du serveur ("pvp", "noclip", "prop_limit", "rotation_minutes"…) et game.IsDedicated() indique un serveur dédié. game.SinglePlayer() (serveur) est vrai dans une partie solo (lancée avec Solo, un seul joueur) et game.MaxPlayers() donne le nombre de places. gamemode.Get(nom) et gamemode.Call(fonction, ...) ; la table du gamemode en cours est GAMEMODE.

DeriveGamemode("base"), en début de ligne dans shared.lua, init.lua ou cl_init.lua, donne la base du gamemode quand gamemode.json n'a pas de champ "base" (qui reste prioritaire) : le jeu charge cette base d'abord, puis GM en hérite (GM.BaseClass). Erreur si le gamemode nommé n'est pas chargé. Voir Gamemodes.

Monde et physique

FonctionsRôle
util.TraceLine, util.TraceHull, util.QuickTrace, util.IsInWorld, MASK_*Rayons et boîtes : ce qu'on touche. Voir Traces.
ent:GetForward, ent:LocalToWorld, ent:GetPhysicsObject, ent:SetVelocity, ent:SetCollisionGroup, ent:SetParent…Repères, physique, collisions et attaches des entités. Voir Monde et physique.
constraint.Weld, Rope, Elastic, Axis, Ballsocket, Slider, Keepupright, NoCollide, Remove… serveurLiens entre props, comme le toolgun. Voir Contraintes.
util.BlastDamage(pos, rayon, dégâts, attaquant, force) serveurExplosion. Voir Explosions.
os.time, os.date, os.clock, os.difftimeDate et heure réelles (version sûre de os). Voir Date et heure.

map : points, zones et entités de map

map.GetPoints(tag), map.GetPoint(nom), map.GetTriggers(tag), map.GetTrigger(nom), map.IsInTrigger(nom, pos), ents.FindByName(nom), et les hooks TriggerStartTouch, TriggerEndTouch, InitPostEntity, PostCleanupMap : lire les repères, zones et entités placés dans l'éditeur de map. Voir Points, zones et entités de map.

Dessin et messages (client)

LocalPlayer(), ScrW(), ScrH(), ScreenScale(n) / ScreenScaleH(n) (taille relative à un écran de 640 × 480), draw.*, surface.*, chat.AddText, notification.AddLegacy(texte, type, durée), notification.AddProgress(id, texte, fraction) / notification.Kill(id), gui.OpenURL(url) (le joueur confirme d'abord). Voir Dessiner le HUD, Chat en couleurs et Tableau des scores.

Rendu 3D et effets (client)

FonctionsRôle
vec:ToScreen()Position d'un point du monde à l'écran
cam.Start3D2D(pos, ang, échelle), cam.End3D2D()Dessiner un panneau dans le monde
Material(chemin), surface.SetMaterial, surface.DrawTexturedRect, DrawTexturedRectRotated, DrawTexturedRectUVImages
surface.CreateFont, SetFont, GetTextSize, SetTextPos, SetTextColor, DrawTextPolices et texte
halo.AddContours autour des objets
render.DrawLine, DrawBox, DrawWireframeBox, DrawSphereFormes de débogage
effects.Particles, util.Effect, util.DecalParticules et décalcomanies
render.ScreenFade, render.SetColorModify, render.SetBlur, DrawColorModify, DrawBloom, DrawSharpen, DrawSobel, DrawToyTown…Effets d'écran (les Draw* dans le hook RenderScreenspaceEffects)
render.SetMaterial, DrawBeam, StartBeam, DrawSprite, DrawQuad, DrawQuadEasy, mesh.Begin, Mesh(), stencils, surface.DrawPolyDessin 3D de l'image (faisceaux, sprites, maillages)
ParticleEmitter, EFFECT (effects/), effects.Register, EffectData()Particules et effets scriptés
DynamicLight(id), ProjectedTexture()Lumières dynamiques et projecteurs
ClientsideModel(id)Modèle visible par ce joueur seulement

Voir Rendu 3D et effets. La caméra se remplace avec le hook CalcView ; hooks de l'image : PreRender, PostRender, RenderScreenspaceEffects.

Fenêtres et touches (client)

vgui.Create (dont DImage, DModelPanel, DColorMixer, RichText, DBinder, DTree, DHTML, DCollapsibleCategory, DCategoryList, DNumberWang, DColumnSheet, DHorizontalDivider, DGrid, DFileBrowser…), peaux Derma (derma.DefineSkin, derma.SkinHook, hook ForceDermaSkin), vgui.Register, DermaMenu, CloseDermaMenus, Derma_Message, Derma_Query, Derma_StringRequest, gui.EnableScreenClicker, input.IsKeyDown, input.IsMouseDown, input.GetKeyName, constantes KEY_* et MOUSE_* (des deux côtés). Voir Menus, clavier et souris.

Armes personnalisées

ply:Give(id) avec l'id d'une arme d'addon, weapons.GetList(), weapons.Get(id), weapons.Override(id, table) (serveur), ply:GetAmmo / SetAmmo / GiveAmmo / RemoveAllAmmo / GetClip, et les hooks PlayerFireWeapon, PlayerReload, WeaponExplosion. Voir Armes personnalisées.

Armes et outils en Lua

Armes en Lua (fichiers weapons/, table SWEP, weapons.Register, weapons.GetStored, weapons.IsLua), outils de toolgun (fichiers stools/, table TOOL, tool.Register, tool.Get, tool.GetList), armes au sol (ply:DropWeapon, ply:SelectWeapon, ply:GetWeapon) et hooks CanTool, PlayerUse, PlayerSwitchWeapon, PlayerCanPickupWeapon. Modèles de vue : SWEP.ViewModel, SWEP.UseHands, SWEP.ViewModelFlip, SWEP:GetViewModelPosition, SWEP:CalcViewModelView, SWEP:PreDrawViewModel, SWEP:DrawWorldModel et les hooks CalcViewModelView, PreDrawViewModel, PostDrawViewModel (client). Tirs : SWEP:FireBullets passe par le hook EntityFireBullets. Voir Armes et outils en Lua.

Bac à sable : annulation, nettoyage, dupes, menus

FonctionsRôle
undo.Create, undo.AddEntity, undo.AddFunction, undo.SetPlayer, undo.SetCustomUndoText, undo.Finish, undo.GetTable serveurEntrées de la touche Annuler. Voir Annulation.
cleanup.Register, cleanup.GetList, cleanup.Add, cleanup.ReplaceEntity, cleanup.CC_Cleanup, cleanup.CC_AdminCleanupCatégories de l'onglet Nettoyage. Voir Nettoyage.
duplicator.RegisterEntityClass, RegisterEntityModifier, StoreEntityModifier, ClearEntityModifier, Copy, Paste, CreateEntityFromTable, FindEntityClass serveurEntités scriptées et données dans les dupes. Voir Dupes.
list.Set, list.Add, list.Get, list.GetForEdit, list.HasEntry, list.Contains, list.GetTableListes nommées ("SpawnableEntities"). Voir Listes.
properties.Add, properties.CanBeTargeted, properties.List, properties.GetHovered (client)Actions du menu contextuel (N). Voir Menu contextuel.
spawnmenu.AddCreationTab, AddToolTab, AddToolCategory, AddToolMenuOption, GetToolMenu, GetTools, GetCreationTabs (client)Onglets du menu de spawn et panneaux d'options (DForm). Voir Menu de spawn.
Hooks StartCommand, CreateMove, SetupMove, Move, FinishMove (client), ply:SetMoveType (serveur), ply:GetMoveType, MOVETYPE_*Déplacement du joueur (CMoveData, CUserCmd ; cmd:GetMouseX() / GetMouseY() : mouvement de la souris en pixels depuis la commande précédente, côté client seulement, 0 sur le serveur). Voir Déplacement du joueur.

Entités du menu de spawn : ENT.Spawnable, ENT.AdminOnly, ENT:SpawnFunction ; voir Entités scriptées.

Os, données, web et rendu

FonctionsRôle
ent:LookupBone, GetBonePosition, GetBoneMatrix, ManipulateBone*, SetupBones / InvalidateBoneCache (recalcule la pose tout de suite : GetBonePosition à jour après un ManipulateBone*), GetAttachment, SetSequence, SetCycle, SetSubMaterial, SetRenderMode, Ignite, Dissolve, util.ScreenShakeOs, animations et effets des props, joueurs et PNJ. Voir Os, animations et effets.
ENT:SetupDataTables / NetworkVar, ENT:Draw / ent:DrawModel, ENT:UpdateTransmitState, ents.CreateClientProp, SafeRemoveEntityVoir Entités scriptées.
sql.Query, QueryRow, QueryValue, SQLStr…, ply:GetPData / SetPDataBase SQLite et données par joueur. Voir Base de données.
http.Fetch, http.Post, HTTP, sound.PlayURL (client)Requêtes web (désactivées par défaut). Voir Requêtes web.
CreateMaterial, GetRenderTarget, render.PushRenderTarget, render.RenderView (client), util.Decal(nom, début, fin)Matériaux, caméras et décalcomanies. Voir Rendu 3D et effets.
language.Add, language.GetPhrase (client)Traductions, "#clé" dans les fenêtres. Voir Traductions.
player_manager.RegisterClass, SetPlayerClass, RunClass…Classes de joueur. Voir Gamemodes.
drive.PlayerStartDriving, drive.Register…Piloter une entité. Voir Piloter une entité.

Véhicules

ents.CreateVehicle(id, position, angle) (serveur), veh:GetDriver(), veh:GetSpeed(), veh:SetThrottle(), ply:EnterVehicle()… et les hooks CanPlayerEnterVehicle, PlayerEnteredVehicle, PlayerLeaveVehicle. Voir Véhicules.

Sons, lumières et traces

ent:EmitSound, sound.Play, CreateSound, sons scriptés (sound.Add{ name = "Arme.Tir", sound = {…}, level, pitch, volume }, sound.GetTable, sound.GetProperties : le nom s'utilise partout à la place d'un fichier), surface.PlaySound et sound.PlayFile(chemin, drapeaux, fonction(canal, code, erreur)) (client), hook EntityEmitSound, ents.CreateClientLight (client), ents.FindInSphere, ply:GetEyeTrace, ply:EyePos, ply:GetAimVector. Voir Sons et lumières.

Soleil, ciel et brouillard

env.SetSunAngle, env.SetSunColor, env.SetSunBrightness, env.SetSkyColor, env.SetSkyTime, env.SetTimeScale, env.SetAmbient, env.SetFog, env.SetSkyTexture(chemin, rotation) (ciel panoramique d'un dossier materials/skybox/) et leurs env.Get…. Serveur : tous les joueurs ; client : effet local. Voir Soleil, ciel et brouillard.

Préchargement des modèles (client)

util.GetModelList(), util.PrecacheModel(id, fonction), util.IsModelPrecached(id) et le hook ClientReady : charger les modèles 3D en avance pour éviter les freezes. Voir Précharger les modèles.

killicon : fil des éliminations (client)

Le jeu affiche les morts en haut à droite (6 lignes, 6 secondes) : tueur [icône] victime, aux couleurs des équipes. L'icône est celle de la classe de l'arme en main du tueur, sinon de la cause : fall, explosion, burn, crush, drown, suicide, generic (icônes en texte par défaut). Une classe sans icône s'affiche [classe].

FonctionRôle
killicon.Add(classe, matériau, couleur)Une image (chemin comme Material()).
killicon.AddFont(classe, police, symbole, couleur), AddTexCode (même chose)Un texte ou symbole dans une police.
killicon.AddAlias(classe, autre)Utilise l'icône d'une autre classe.
killicon.Exists(classe), Get(classe), GetSize(classe) → l, hLire les icônes.
killicon.Draw(x, y, classe, alpha)Dessine l'icône centrée sur x (haut à y), dans HUDPaint.

Hooks AddDeathNotice et DrawDeathNotice pour remplacer ou cacher le fil. L'annonce dans le chat (PlayerDeathNotice) reste.

killicon.Add("arme_laser", "monaddon/killicons/laser.png", Color(255, 80, 80))  -- chemin comme Material()
killicon.AddAlias("arme_laser_lourd", "arme_laser")

steamworks et achievements (client)

Steam vu du joueur ; sans Steam lancé, les fonctions ne font rien (false, "", rappel avec nil). Les identifiants Workshop et SteamID64 sont des textes.

FonctionRôle
steamworks.IsSteamAvailable()Steam est-il lancé.
steamworks.IsSubscribed(id), steamworks.ShouldMountAddon(id)Le joueur est abonné à cet élément ; l'addon est activé.
steamworks.ViewFile(id)Ouvre la page Workshop dans l'overlay Steam.
steamworks.FileInfo(id, fonction(info))info = { id, title, description, owner, created, updated, size, tags, up, down, installed }, ou nil.
steamworks.DownloadUGC(id, fonction(dossier))Télécharge l'élément (sans abonnement ni activation) ; dossier = son dossier d'installation, ou nil.
steamworks.GetPlayerName(steamid64), steamworks.RequestPlayerInfo(steamid64, fonction(nom))Nom Steam d'un joueur (la demande répond au bout d'environ 1 s).
achievements.Count(), GetName(i), GetDesc(i), IsAchieved(i), GetCount(i), GetGoal(i)Les succès Steam de PhysiCore, en lecture seule (i à partir de 0). Les compteurs de GMod (achievements.SpawnedProp()…) existent mais ne font rien.

file, util et ConVars

file.Write, file.Read, file.Append, file.Exists, file.Delete, file.Find (deux tables : fichiers, dossiers), file.Open (lecture et écriture binaires), file.AsyncRead… (dans le dossier de données du gamemode ou de l'addon), util.TableToJSON, util.JSONToTable, CreateConVar, GetConVar, CreateClientConVar, cvars.AddChangeCallback, RunConsoleCommand. Voir Données et réglages.

timer : minuteries

timer.Simple(délai, fonction)

Appelle fonction une seule fois après délai secondes.

timer.Create(identifiant, délai, répétitions, fonction)

Appelle fonction toutes les délai secondes, répétitions fois (0 = à l'infini). Un identifiant déjà utilisé remplace l'ancienne minuterie.

timer.Remove(identifiant)

Arrête une minuterie créée avec timer.Create.

timer.Exists(identifiant), timer.TimeLeft(identifiant), timer.RepsLeft(identifiant)

La minuterie existe-t-elle ; secondes avant son prochain appel ; répétitions restantes (0 = à l'infini).

timer.Adjust(identifiant, délai, répétitions, fonction)

Change le délai, les répétitions ou la fonction d'une minuterie (nil = inchangé). Renvoie false si elle n'existe pas.

timer.Pause, timer.UnPause, timer.Toggle, timer.Stop, timer.Start

Met en pause / reprend / bascule une minuterie (le temps restant est gardé). Stop la met en pause et remet son compte à rebours au délai complet ; Start la relance, elle aussi pour un délai complet. Toutes renvoient false si la minuterie n'existe pas.

-- Fait pleuvoir des balles toutes les 2 secondes, 10 fois.
timer.Create("pluie", 2, 10, function()
	local x = math.random(-10, 10)
	local z = math.random(-10, 10)
	ents.SpawnProp("builtin:ball", Vector(x, 15, z))
end)
PrécisionLes minuteries avancent au rythme de la physique (60 fois par seconde) : un délai est précis à environ 1/60 s.

Bac à sable et sécurité

Les scripts tournent dans un environnement isolé, pour qu'un addon téléchargé ne puisse pas nuire aux joueurs.

DisponibleIndisponible
Fonctions de base (pairs, ipairs, tostring, tonumber, pcall, type, load pour du texte…), bibliothèques string, math, table, coroutine, utf8, debug.traceback (le seul élément de debug), include, types mathématiques de Godot (Vector3, Array, Dictionary…)io, os (sauf os.time, os.date, os.clock et os.difftime), require, dofile, loadfile, string.dump, load de code binaire, le reste de debug, et toute classe du moteur (nœuds, fichiers, réseau…)

Les seuls fichiers accessibles sont ceux du dossier de données du gamemode ou de l'addon, avec file.* (voir Données et réglages). Chaque fichier Lua tourne dans son propre environnement : ses variables globales vont dans _G comme d'habitude, mais file y désigne le dossier de son propriétaire.

Erreurs et pile d'appels

Une erreur dans un script ou dans un hook est interceptée : elle s'affiche dans le chat ([Lua] Erreur : …, ou [Lua client]) et dans la console de l'éditeur de code, sans arrêter le jeu ni les autres hooks. Les scripts client suivent les mêmes règles.

Le message est suivi de la pile d'appels (pile d'appels :, puis une ligne fichier:ligne: in … par fonction appelée), pour voir d'où vient l'erreur ; les lignes internes du jeu sont retirées. Dans ton propre code, xpcall(fonction, debug.traceback) et ErrorNoHaltWithStack donnent la même information.

local ok, err = xpcall(function() return nil + 1 end, debug.traceback)
if not ok then print(err) end  -- le message, puis « stack traceback: » et les lignes

Un script qui tourne plus de 5 secondes sans rendre la main (boucle infinie, calcul sans fin) est arrêté avec l'erreur script arrêté : il tournait depuis plus de 5 s…, au lieu de figer le serveur ou le jeu du joueur. Pour un long travail, découpe-le avec timer.Simple ou un Think qui en fait un peu à chaque image. La limite vaut aussi dans les coroutines (coroutine.create, coroutine.wrap).