Data types
When you write a mod, you are constantly storing and asking questions about information: Is the player in a vehicle? How many seconds until the next check? What weather should we switch to? C# gives you specific types to hold each kind of value.
Primitive types you use every day
Four basic types form the bedrock of almost every mod:
bool: Holdstrueorfalse. Ideal for flags:private bool _isMissionActive;.int: A whole number (32 bits). Used for counters, timer timestamps in milliseconds, or indexes:private int _nextCheckTime;.float: A single-precision floating-point number. Essential in 3D games for speeds, distances, and headings. Always add thefsuffix in C#:private float _speed = 15.5f;.string: Text enclosed in double quotes. Used for notifications, model names, or log paths:string message = "Mission started";.
Game-specific types
SHVDN provides types specifically designed for the GTA V engine:
GTA.Math.Vector3: Represents a point or direction in 3D space withX,Y, andZcoordinates:Vector3 playerPos = Game.Player.Character.Position;GTA.Weather: An enumeration (enum) of all weather types recognized by the game:Weather currentWeather = World.Weather;World.Weather = Weather.ExtraSunny;
Local variables vs fields
Where you declare a variable determines how long it survives. This is where most beginners lose hours of debugging:
Local variables: temporary within a method
A local variable is declared inside a method. It is created when the method runs, and destroyed as soon as the method exits:
private void OnKeyDown(object sender, KeyEventArgs e)
{
// Created on key press, gone as soon as this block finishes
float distance = 10.0f;
}
Fields: persistent state across frames
Because OnTick runs sixty times per second, any variable declared inside OnTick resets every single frame. If you want to remember whether a mission has started or when you last showed a message, declare a field at the class level:
public sealed class WeatherWatch : Script
{
// These survive between frames and keypresses
private bool _hasAnnounced;
private int _nextUpdateTime;
private void OnTick(object sender, EventArgs e)
{
if (_hasAnnounced)
{
return;
}
if (Game.GameTime > _nextUpdateTime)
{
_hasAnnounced = true;
GTA.UI.Screen.ShowSubtitle("Welcome to Los Santos", 3000);
}
}
}
Notice the naming convention: fields private to a class start with an underscore (_hasAnnounced). It makes it instantly clear whether you are touching long-term state or a temporary calculation.
Next, we look at control flow: making decisions with if statements and loops.