## Introduction

PythonDispatcher allows you to write GTA V mods using Python instead of C#. It uses the exact same SHVDN API — same classes, same methods, same everything.

✨ Key Benefits

- No compilation — just edit and save
- Hot-reload — see changes without restarting the game
- Cleaner syntax — less boilerplate code
- Same API — all SHVDN features available

## How It Works

PythonDispatcher uses IronPython, which runs Python directly on .NET. There's no translation layer or wrapper — your Python code calls the real SHVDN classes.

Your Script (.py) │ Game.Player.Character.Health = 200 │ ▼ IronPython Engine │ IronPython is NOT a bridge or translator. │ It's Python running directly ON .NET. │ │ Game.Player → Calls the real GTA.Game class │ (same object as C# would use) │ ▼ ScriptHookVDotNet (SHVDN) │ Receives standard .NET calls │ Can't tell if caller is C# or Python │ ▼ ScriptHookV + GTA V

## Installation

### Requirements

1. Install ScriptHookV
2. Install ScriptHookVDotNet
3. Download PythonDispatcher and extract to your GTA V folder

### Folder Structure

📁 Grand Theft Auto V
📁 scripts
📄 PythonDispatcher.dll
⚙️ PythonDispatcher.ini ← Configuration file
📄 PythonDispatcher.pdb ← Debug symbols (optional)
📁 scripts_py ← Your Python scripts go here
🐍 example.py

## Your First Script

Create a file `hello.py` in the `scripts_py` folder:

    from GTA.UI import Notification

    def on_start():
        Notification.Show("Hello from Python!")

Start the game — you should see the notification!

## Script Structure

A Python script can have these optional functions:

    # Optional: controls how often on_tick runs
    INTERVAL_MS = 100  # on_tick runs every 100ms instead of every frame

    def on_start():
        """Called ONCE when the script loads (after 3 seconds delay)"""
        pass

    def on_tick():
        """Called every frame (or every INTERVAL_MS if defined)"""
        pass

    def on_key_down(e):
        """Called when a key is pressed"""
        # e.KeyCode contains the key
        pass

    def on_aborted():
        """Called when the script unloads (reload or game exit)"""
        pass

ℹ️ Note
All functions are optional. Only define what you need.

### Available Functions

Function | When it's called | Parameter
--- | --- | ---
`on_start()` | Once, 3 seconds after load | None
`on_tick()` | Every frame (or INTERVAL_MS) | None
`on_key_down(e)` | When a key is pressed | KeyEventArgs
`on_aborted()` | When script unloads | None

## Imports

    # Core
    from GTA import Game, World

    # Entities
    from GTA import Ped, Vehicle, Prop, Entity

    # Math
    from GTA.Math import Vector3

    # UI
    from GTA.UI import Notification, Screen

    # Enums
    from GTA import VehicleSeat, WeaponHash, PedHash, VehicleHash
    from GTA import Blip, BlipColor, BlipSprite
    from GTA import Relationship, Gender

    # Natives
    from GTA.Native import Function, Hash

    # Keys
    from System.Windows.Forms import Keys

    # Drawing
    from System.Drawing import Color, Point, Size

    # LemonUI (if installed)
    from LemonUI import ObjectPool
    from LemonUI.Menus import NativeMenu, NativeItem

## Player

### Basic Access

    from GTA import Game

    # Shortcuts
    player = Game.Player           # The Player (controller)
    ped = Game.Player.Character    # The Ped (physical character)

### Player Properties

    Game.Player.Money                   # Money (get/set)
    Game.Player.WantedLevel             # Stars 0-5 (get/set)
    Game.Player.IsInvincible            # God mode (get/set)
    Game.Player.IgnoredByEveryone       # Ignored by NPCs (get/set)
    Game.Player.CanControlCharacter     # Can move (get/set)
    Game.Player.IsAlive                 # Is alive (get)
    Game.Player.IsDead                  # Is dead (get)
    Game.Player.IsAiming                # Is aiming (get)
    Game.Player.Name                    # "Michael", "Franklin", "Trevor" (get)

### Character (Ped) Properties

    ped = Game.Player.Character

    ped.Health                   # Current health (get/set)
    ped.MaxHealth                # Max health (get/set)
    ped.Armor                    # Armor 0-100 (get/set)
    ped.Position                 # Vector3 position (get/set)
    ped.Rotation                 # Vector3 rotation (get/set)
    ped.Heading                  # Direction 0-360 (get/set)
    ped.IsAlive                  # Is alive (get)
    ped.IsInVehicle()            # Is in a vehicle (method)
    ped.IsOnFoot                 # Is on foot (get)
    ped.IsSwimming               # Is swimming (get)
    ped.IsFalling                # Is falling (get)
    ped.IsOnFire                 # Is on fire (get)
    ped.IsShooting               # Is shooting (get)

### Useful Vectors

    ped.Position                 # Current position
    ped.ForwardVector            # Direction forward
    ped.RightVector              # Direction right
    ped.UpVector                 # Direction up
    ped.Velocity                 # Current velocity

### Current Vehicle

    ped.CurrentVehicle           # Current vehicle (or None)
    ped.LastVehicle              # Last used vehicle

    if ped.IsInVehicle():
        car = ped.CurrentVehicle
        car.Speed                # Speed
        car.EngineRunning = True # Start engine

### Weapons

    from GTA import WeaponHash

    ped.Weapons.Current                                    # Current weapon
    ped.Weapons.Give(WeaponHash.Pistol, 100, True, True)  # Give weapon
    ped.Weapons.RemoveAll()                                # Remove all weapons

## Vehicles

### Creating a Vehicle

    from GTA import Game, World, VehicleSeat, VehicleHash
    from GTA.Math import Vector3

    # By name (string)
    car = World.CreateVehicle("zentorno", position)
    car = World.CreateVehicle("adder", position, heading)

    # By hash (enum)
    car = World.CreateVehicle(VehicleHash.Zentorno, position)

    # Position in front of player
    player = Game.Player.Character
    pos = player.Position + player.ForwardVector * 5
    car = World.CreateVehicle("zentorno", pos)

### Vehicle Properties

    car.Speed                    # Current speed (get/set)
    car.Health                   # Health (get/set)
    car.EngineHealth             # Engine health (get/set)
    car.BodyHealth               # Body health (get/set)
    car.IsDriveable              # Is driveable (get/set)
    car.IsOnFire                 # Is on fire (get)
    car.IsStopped                # Is stopped (get)

### Vehicle Control

    car.EngineRunning = True              # Start engine
    car.LightsOn = True                   # Turn on lights
    car.HandbrakeOn = True                # Handbrake
    car.IsInvincible = True               # Invincible
    car.CanTiresBurst = False             # Bulletproof tires

    car.Repair()                          # Fully repair
    car.Wash()                            # Wash
    car.PlaceOnGround()                   # Place on ground
    car.Explode()                         # Explode

### Teleport Player into Vehicle

    player.SetIntoVehicle(car, VehicleSeat.Driver)
    player.SetIntoVehicle(car, VehicleSeat.Passenger)

## Peds

### Creating a Ped

    from GTA import World, PedHash

    # By hash
    ped = World.CreatePed(PedHash.Business01AMY, position)

    # Near player
    player = Game.Player.Character
    pos = player.Position + player.ForwardVector * 3
    ped = World.CreatePed(PedHash.Cop01SMY, pos)

### Ped Properties

    ped.Health = 200
    ped.Armor = 100
    ped.Money = 500                       # Money on them
    ped.IsEnemy                           # Is hostile to player (get/set)
    ped.IsFleeing                         # Is fleeing
    ped.IsInCombat                        # Is in combat

### Ped Tasks

    ped.Task.GoTo(position)                        # Go to position
    ped.Task.RunTo(position)                       # Run to position
    ped.Task.FightAgainst(target_ped)              # Attack
    ped.Task.FleeFrom(target_ped)                  # Flee
    ped.Task.EnterVehicle(vehicle, VehicleSeat.Driver)  # Enter vehicle
    ped.Task.LeaveVehicle()                        # Exit vehicle
    ped.Task.WanderAround()                        # Wander
    ped.Task.ClearAll()                            # Cancel all tasks

### Ped Control

    ped.Kill()                            # Kill
    ped.Delete()                          # Remove from game
    ped.MarkAsNoLongerNeeded()            # Let game manage

## World

### Time & Weather

    from GTA import World, Weather
    from System import TimeSpan

    # Set time to noon
    World.CurrentDayTime = TimeSpan(12, 0, 0)

    # Weather
    World.Weather = Weather.Clear
    World.Weather = Weather.Raining
    World.Weather = Weather.ThunderStorm
    World.Weather = Weather.Snowing

### Finding Nearby Entities

    # Get all nearby vehicles
    vehicles = World.GetNearbyVehicles(position, radius)
    peds = World.GetNearbyPeds(position, radius)
    props = World.GetNearbyProps(position, radius)

    # Example: turn off all engines nearby
    player = Game.Player.Character
    nearby_cars = World.GetNearbyVehicles(player.Position, 50.0)
    for car in nearby_cars:
        car.EngineRunning = False

### Waypoint

    waypoint = World.WaypointPosition     # Marker position (or None)

    # Teleport to waypoint
    if waypoint:
        player.Position = waypoint

### Explosions

    from GTA import ExplosionType

    World.AddExplosion(position, ExplosionType.Grenade, 10.0, 1.0)
    # AddExplosion(position, type, radius, camera_shake)

## Positions & Vectors

### Creating Vectors

    from GTA.Math import Vector3

    pos = Vector3(100.0, 200.0, 50.0)     # x, y, z
    pos = Vector3.Zero                     # 0, 0, 0

### Operations

    a = Vector3(1, 2, 3)
    b = Vector3(4, 5, 6)

    c = a + b                # Addition
    c = a - b                # Subtraction
    c = a * 2.0              # Scalar multiplication

### Properties & Methods

    pos.X                    # X component
    pos.Y                    # Y component
    pos.Z                    # Z component

    distance = a.DistanceTo(b)            # Distance between two points
    distance2d = a.DistanceTo2D(b)        # 2D distance (ignores Z)
    length = a.Length()                   # Vector length
    normalized = a.Normalized             # Normalized vector (length 1)

### Practical Examples

    player = Game.Player.Character

    # Position 5 meters in front
    front = player.Position + player.ForwardVector * 5

    # Position 3 meters to the right
    right = player.Position + player.RightVector * 3

    # Position 10 meters above
    above = player.Position + Vector3(0, 0, 10)

    # Distance check
    distance = player.Position.DistanceTo(some_position)
    if distance < 10:
        Notification.Show("You are close!")

## UI & Notifications

### Notifications

    from GTA.UI import Notification, Screen

    # Show a notification (phone-style popup)
    Notification.Show("Message here")

    # With blinking
    Notification.Show("Important message!", True)

### Screen Text

    # Must be called each frame in on_tick
    Screen.ShowSubtitle("Subtitle text")
    Screen.ShowSubtitle("Subtitle text", 1000)  # Duration in ms

    Screen.ShowHelpText("Press ~INPUT_CONTEXT~ to interact")

### Screen Effects

    Screen.FadeOut(500)                   # Fade to black (ms)
    Screen.FadeIn(500)                    # Fade from black (ms)
    Screen.IsFadedOut                     # Is fully black?
    Screen.IsFadedIn                      # Is fully visible?

## Controls & Keys

### Keyboard Keys (in on_key_down)

    from System.Windows.Forms import Keys

    def on_key_down(e):
        if e.KeyCode == Keys.F9:
            # Action for F9
            pass
        elif e.KeyCode == Keys.NumPad1:
            # Action for NumPad1
            pass

        # With modifiers
        if e.KeyCode == Keys.R and e.Control:
            # Ctrl + R
            pass

        if e.KeyCode == Keys.F1 and e.Shift:
            # Shift + F1
            pass

### Common Keys

    Keys.F1, Keys.F2, ..., Keys.F12       # Function keys
    Keys.NumPad0, ..., Keys.NumPad9       # Numpad
    Keys.A, Keys.B, ..., Keys.Z           # Letters
    Keys.D0, Keys.D1, ..., Keys.D9        # Number row
    Keys.Space, Keys.Enter, Keys.Escape
    Keys.Up, Keys.Down, Keys.Left, Keys.Right

### Game Controls (in on_tick)

    from GTA import Game, Control

    def on_tick():
        # Is control currently pressed?
        if Game.IsControlPressed(Control.Aim):
            pass

        # Just pressed this frame?
        if Game.IsControlJustPressed(Control.Jump):
            pass

        # Just released?
        if Game.IsControlJustReleased(Control.Attack):
            pass

        # Disable a control
        Game.DisableControlThisFrame(Control.Phone)

### Common Controls

    Control.Aim                 # Aim (right click)
    Control.Attack              # Attack (left click)
    Control.Jump                # Jump (Space)
    Control.Sprint              # Sprint (Shift)
    Control.Enter               # Enter vehicle (F)
    Control.VehicleAccelerate   # Accelerate (W)
    Control.VehicleBrake        # Brake (S)
    Control.Phone               # Phone (Up)
    Control.Context             # Interaction (E)

## Native Functions

### Calling Natives

    from GTA.Native import Function, Hash
    from GTA import Game

    player = Game.Player.Character

    # Without return value
    Function.Call(Hash.SET_ENTITY_ALPHA, player, 100, False)

    # With return value
    health = Function.Call[int](Hash.GET_ENTITY_HEALTH, player)
    is_dead = Function.Call[bool](Hash.IS_ENTITY_DEAD, player)

### Common Examples

    # Make transparent
    Function.Call(Hash.SET_ENTITY_ALPHA, player, 100, False)

    # Reset transparency
    Function.Call(Hash.RESET_ENTITY_ALPHA, player)

    # Ragdoll
    Function.Call(Hash.SET_PED_TO_RAGDOLL, player, 1000, 1000, 0, True, True, False)

    # Set time
    Function.Call(Hash.SET_CLOCK_TIME, 12, 0, 0)

📚 Native Reference

Find all natives at: nativedb.dotindustries.dev/gta5

## LemonUI Menus

    from LemonUI import ObjectPool
    from LemonUI.Menus import NativeMenu, NativeItem, NativeCheckboxItem
    from System.Windows.Forms import Keys
    from GTA.UI import Notification
    from GTA import Game

    pool = None
    menu = None

    def on_start():
        global pool, menu

        # Create the pool (manages all menus)
        pool = ObjectPool()

        # Create the menu
        menu = NativeMenu("Title", "Subtitle")
        pool.Add(menu)

        # Simple item
        item1 = NativeItem("Restore Health")
        item1.Description = "Restores your health to full"
        menu.Add(item1)
        item1.Activated += on_health_clicked

        # Checkbox
        checkbox = NativeCheckboxItem("God Mode", False)
        menu.Add(checkbox)
        checkbox.CheckboxChanged += on_godmode_changed

    def on_health_clicked(sender, e):
        Game.Player.Character.Health = 200
        Notification.Show("Health restored!")

    def on_godmode_changed(sender, e):
        Game.Player.IsInvincible = sender.Checked
        status = "ON" if sender.Checked else "OFF"
        Notification.Show(f"God Mode: {status}")

    def on_tick():
        # IMPORTANT: call Process each frame
        if pool:
            pool.Process()

    def on_key_down(e):
        if e.KeyCode == Keys.F5:
            menu.Visible = not menu.Visible

## Blips

Blips are markers displayed on the map and minimap.

### Creating Blips

    from GTA import World, BlipSprite, BlipColor
    from GTA.Math import Vector3

    # Create a blip at a position
    blip = World.CreateBlip(Vector3(100, 200, 50))

    # Create a blip on an entity (follows it)
    blip = car.AddBlip()
    blip = ped.AddBlip()

### Blip Properties

    blip.Sprite = BlipSprite.PersonalVehicleCar   # Icon
    blip.Color = BlipColor.Red                     # Color
    blip.Name = "My Marker"                        # Name in legend
    blip.ShowRoute = True                          # Show GPS route
    blip.IsFlashing = True                         # Blinking effect
    blip.Scale = 1.5                               # Size multiplier
    blip.Alpha = 200                               # Transparency 0-255

### Common Sprites

    BlipSprite.Standard              # Default dot
    BlipSprite.PersonalVehicleCar    # Car icon
    BlipSprite.Waypoint              # Waypoint flag
    BlipSprite.Enemy                 # Red enemy
    BlipSprite.Friend                # Blue friend
    BlipSprite.Garage                # Garage
    BlipSprite.AmmuNation            # Gun shop
    BlipSprite.LosSantosCustoms      # Car shop

### Removing Blips

    blip.Delete()                    # Remove from map

    # Clean up in on_aborted
    def on_aborted():
        if blip and blip.Exists():
            blip.Delete()

## Props

Props are objects in the world (barrels, cones, furniture, etc.).

### Creating Props

    from GTA import World, Game
    from GTA.Math import Vector3

    # By model name
    prop = World.CreateProp("prop_barrel_02a", position, True)
    # CreateProp(model, position, dynamic)
    # dynamic = True means it can be pushed/moved

    # With rotation
    prop = World.CreateProp("prop_barrier_work01a", position, rotation, True)

### Prop Properties

    prop.Position                    # Get/set position
    prop.Rotation                    # Get/set rotation
    prop.Heading                     # Get/set heading (0-360)
    prop.IsVisible                   # Show/hide
    prop.HasCollision                # Enable/disable collision
    prop.IsInvincible                # Can't be destroyed
    prop.IsPersistent                # Won't despawn

### Physics

    # Apply force (push)
    prop.ApplyForce(Vector3(0, 0, 10))    # Push upward

    # Freeze in place
    prop.FreezePosition = True

    # Check if on ground
    prop.IsInAir                         # Is floating?

### Removing Props

    prop.Delete()                    # Remove from world
    prop.MarkAsNoLongerNeeded()      # Let game manage

💡 Finding Prop Names

Find prop model names at: gta-objects.xyz/objects

## Audio

Play sounds using native functions.

### Playing Sounds

    from GTA.Native import Function, Hash
    from GTA import Game

    # Play a sound from a sound set
    Function.Call(Hash.PLAY_SOUND_FRONTEND, -1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", True)

    # Common UI sounds
    Function.Call(Hash.PLAY_SOUND_FRONTEND, -1, "NAV_UP_DOWN", "HUD_FRONTEND_DEFAULT_SOUNDSET", True)
    Function.Call(Hash.PLAY_SOUND_FRONTEND, -1, "ERROR", "HUD_FRONTEND_DEFAULT_SOUNDSET", True)
    Function.Call(Hash.PLAY_SOUND_FRONTEND, -1, "CANCEL", "HUD_FRONTEND_DEFAULT_SOUNDSET", True)

### Sound at Position

    # Play sound at a 3D position
    Function.Call(Hash.PLAY_SOUND_FROM_COORD, -1, "EXPLOSION",
                  pos.X, pos.Y, pos.Z, "SOUNDS", True, 0, False)

### Sound on Entity

    # Play sound attached to an entity
    Function.Call(Hash.PLAY_SOUND_FROM_ENTITY, -1, "SIREN",
                  vehicle, "VEHICLE_SOUNDS", True, 0)

### Stopping Sounds

    # Get the sound ID when playing
    sound_id = Function.Call[int](Hash.GET_SOUND_ID)
    Function.Call(Hash.PLAY_SOUND_FRONTEND, sound_id, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", True)

    # Stop the sound
    Function.Call(Hash.STOP_SOUND, sound_id)
    Function.Call(Hash.RELEASE_SOUND_ID, sound_id)

## Animations

Play animations on peds.

### Playing Animations

    from GTA import Game, AnimationFlags
    from GTA.Native import Function, Hash

    ped = Game.Player.Character

    # Request the animation dictionary first
    Function.Call(Hash.REQUEST_ANIM_DICT, "amb@world_human_cheering@male_a")
    Script.Wait(100)  # Wait for it to load

    # Play the animation
    ped.Task.PlayAnimation("amb@world_human_cheering@male_a", "base")

### Animation with Flags

    # With duration and flags
    ped.Task.PlayAnimation(
        "amb@world_human_drinking@coffee@male@idle_a",  # Dictionary
        "idle_a",                                        # Animation name
        8.0,                                             # Blend in speed
        -8.0,                                            # Blend out speed
        -1,                                              # Duration (-1 = full)
        AnimationFlags.Loop,                             # Flags
        0.0                                              # Playback rate
    )

### Animation Flags

    AnimationFlags.None              # Default
    AnimationFlags.Loop              # Repeat
    AnimationFlags.StayInEndFrame    # Freeze at end
    AnimationFlags.UpperBodyOnly     # Only upper body
    AnimationFlags.AllowRotation     # Can turn during anim
    AnimationFlags.CancelableWithMovement  # Stop on move

### Stopping Animations

    # Stop specific animation
    ped.Task.ClearAnimation("amb@world_human_cheering@male_a", "base")

    # Stop all animations
    ped.Task.ClearAll()

💡 Finding Animations

Find animation names at: alexguirre.github.io/animations-list

## Camera

Create and control custom cameras.

### Creating a Camera

    from GTA import World, GameplayCamera
    from GTA.Math import Vector3

    # Create a camera at position
    cam = World.CreateCamera(position, rotation, fov)
    # fov = field of view (default ~50)

    # Example
    cam = World.CreateCamera(
        Vector3(100, 200, 50),    # Position
        Vector3(0, 0, 0),        # Rotation
        50.0                      # FOV
    )

### Camera Properties

    cam.Position                     # Get/set position
    cam.Rotation                     # Get/set rotation
    cam.FieldOfView                  # Get/set FOV
    cam.FarClip                      # Render distance
    cam.NearClip                     # Near clip plane
    cam.IsShaking                    # Is currently shaking

### Activating the Camera

    # Switch to custom camera
    World.RenderingCamera = cam

    # Smooth transition (1 second)
    cam.IsActive = True
    World.RenderingCamera = cam

    # Back to gameplay camera
    World.RenderingCamera = None

### Camera Effects

    # Shake the camera
    cam.Shake("HAND_SHAKE", 1.0)      # type, amplitude
    cam.StopShaking()

    # Point at entity
    cam.PointAt(target_entity)
    cam.StopPointing()

### Gameplay Camera Info

    # Get current gameplay camera info
    GameplayCamera.Position          # Current position
    GameplayCamera.Rotation          # Current rotation
    GameplayCamera.Direction         # Forward vector
    GameplayCamera.FieldOfView       # Current FOV

### Cleanup

    def on_aborted():
        # Always restore gameplay camera
        World.RenderingCamera = None
        if cam:
            cam.Delete()

## Raycasting

Cast rays to detect what's in front of the player or camera.

### Basic Raycast

    from GTA import World, Game, IntersectFlags
    from GTA.Math import Vector3

    ped = Game.Player.Character

    # Cast a ray from player forward
    start = ped.Position + Vector3(0, 0, 0.5)  # Slightly above ground
    end = start + ped.ForwardVector * 100       # 100 meters forward

    result = World.Raycast(start, end, IntersectFlags.Everything, ped)

### Raycast Result

    if result.DidHit:
        result.HitPosition           # Vector3 where ray hit
        result.SurfaceNormal         # Normal of surface hit
        result.HitEntity             # Entity hit (or None)

        # Check what type of entity
        if result.HitEntity:
            entity = result.HitEntity
            if entity.EntityType == EntityType.Ped:
                Notification.Show("Looking at a person!")
            elif entity.EntityType == EntityType.Vehicle:
                Notification.Show("Looking at a vehicle!")

### Intersect Flags

    IntersectFlags.Everything        # Hit anything
    IntersectFlags.Map               # World geometry only
    IntersectFlags.Vehicles          # Vehicles only
    IntersectFlags.Peds              # Peds only
    IntersectFlags.Objects           # Props only
    IntersectFlags.Water             # Water surfaces

    # Combine flags
    flags = IntersectFlags.Vehicles | IntersectFlags.Peds

### Camera Raycast

    from GTA import GameplayCamera

    # Raycast from camera (what player is looking at)
    cam_pos = GameplayCamera.Position
    cam_dir = GameplayCamera.Direction

    result = World.Raycast(cam_pos, cam_pos + cam_dir * 100,
                            IntersectFlags.Everything, ped)

### Practical Example

    # Highlight entity player is aiming at
    def on_tick():
        ped = Game.Player.Character
        cam_pos = GameplayCamera.Position
        cam_dir = GameplayCamera.Direction

        result = World.Raycast(cam_pos, cam_pos + cam_dir * 50,
                               IntersectFlags.Everything, ped)

        if result.DidHit and result.HitEntity:
            Screen.ShowSubtitle(f"Looking at: {result.HitEntity.Model}")

## Model Loading

Some models need to be loaded before spawning.

### Why Load Models?

GTA V doesn't keep all models in memory. If you spawn a rare vehicle or ped, you need to request it first.

### Using Model Class

    from GTA import Model, World, VehicleHash

    # Create a Model object
    model = Model(VehicleHash.Zentorno)
    # or by name
    model = Model("zentorno")

    # Request and wait for load
    model.Request()
    while not model.IsLoaded:
        Script.Wait(10)

    # Now spawn
    car = World.CreateVehicle(model, position)

    # Release when done
    model.MarkAsNoLongerNeeded()

### Model Properties

    model.IsValid                    # Is a valid model
    model.IsLoaded                   # Is currently loaded
    model.IsInCdImage                # Exists in game files
    model.IsVehicle                  # Is a vehicle model
    model.IsPed                      # Is a ped model
    model.IsProp                     # Is a prop model

### With Timeout

    # Request with timeout (safer)
    model = Model(VehicleHash.Adder)

    if model.Request(1000):  # Wait up to 1000ms
        car = World.CreateVehicle(model, position)
        model.MarkAsNoLongerNeeded()
    else:
        Notification.Show("Failed to load model!")

### Helper Function

    def spawn_vehicle(model_name, position):
        """Safely spawn a vehicle with model loading"""
        model = Model(model_name)

        if not model.IsInCdImage:
            Notification.Show(f"Model {model_name} doesn't exist!")
            return None

        if model.Request(1000):
            vehicle = World.CreateVehicle(model, position)
            model.MarkAsNoLongerNeeded()
            return vehicle

        return None

⚠️ Important

Always call `model.MarkAsNoLongerNeeded()` after spawning to free memory. Don't keep models loaded indefinitely.

## Python vs C# Syntax

Here's how the same functionality looks in both languages:

C#

    using GTA;
    using GTA.UI;
    using System.Windows.Forms;

    public class MyMod : Script
    {
        public MyMod()
        {
            Tick += OnTick;
            KeyDown += OnKeyDown;
        }

        private void OnTick(object s, EventArgs e)
        {
            Ped player = Game.Player.Character;
            if (player.IsInVehicle())
            {
                Notification.Show("In vehicle!");
            }
        }

        private void OnKeyDown(object s, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.F10)
            {
                Game.Player.Character.Health = 200;
            }
        }
    }

Python

    from GTA import Game
    from GTA.UI import Notification
    from System.Windows.Forms import Keys

    def on_tick():
        player = Game.Player.Character
        if player.IsInVehicle():
            Notification.Show("In vehicle!")

    def on_key_down(e):
        if e.KeyCode == Keys.F10:
            Game.Player.Character.Health = 200

## Configuration

Edit `PythonDispatcher.ini` in your GTA V folder:

    [PythonDispatcher]

    # Key to reload all scripts (see Keys enum)
    ReloadKey=F9

    # Auto-reload scripts when file changes (true/false)
    AutoReload=false

    # Hot-reload check interval in seconds
    HotReloadInterval=2

    # Show debug messages (true/false)
    DebugMode=false

### Reload Methods

- Manual: Press F9 (or your configured key)
- Auto-reload: Set `AutoReload=true` — scripts reload automatically when saved

## FAQ & Troubleshooting

### My script doesn't load!

- Check that the file is in `scripts_py/` folder
- Check for Python syntax errors (use a code editor)
- Enable `DebugMode=true` in the INI file

### I get "module not found" error

- Make sure you're importing from the right namespace
- Example: `from GTA import Game` not `import GTA`

### How do I use external Python libraries?

- Only pure-Python libraries compatible with IronPython work
- Place them in `scripts_py/Lib/`
- NumPy, requests, etc. will NOT work (they need CPython)

### Performance issues?

- Use `INTERVAL_MS` to reduce on_tick frequency
- Don't do heavy work every frame
- For performance-critical mods, use C#

### Can I use multiple script files?

- Yes! Each `.py` file in `scripts_py/` is loaded separately
- You can also import between them: `from my_utils import helper`