Configuration

9 min readUpdated 2 weeks ago

Overview

  • shared/config.lua: Core settings, geiger items, battery, player effects, zones, vehicle/clothing protection, cure/immunity items
  • server/config_server.lua: Discord webhooks, admin permissions, rate limiting

Core Settings

shared/config.lua
1Config.Locale = 'en'
2Config.Movegeiger = 'movegeiger'
3Config.Debug = false
4Config.UseRealTime = false
5Config.ShowZoneNotifications = true
6Config.ZoneNotificationDuration = 15000
7Config.RequireGameplayReadyGate = false
8Config.HealthSystemIntegration = false
9Config.RealTerminalItem = false
  • Locale: Language code for translations
  • Movegeiger: Command to reposition the Geiger Counter HUD on screen
  • Debug: Enable debug prints in console
  • UseRealTime: Use real-world time instead of GTA game time on the Geiger display
  • ShowZoneNotifications: Show notifications when entering/leaving radiation zones (duration set by Config.ZoneNotificationDuration, default 15000 ms). Config.RequireGameplayReadyGate (default false) is an opt-in gate that suspends radiation processing during multicharacter/intro while ml_start reports that gameplay is not yet ready
  • HealthSystemIntegration: Delegate radiation damage and visual effects to ml_healthsystem. When true AND ml_healthsystem is running, the export handshake stays active; Config.HealthSystemSettings (disableDamage/disableVisuals) decides whether ml_radiation also cedes damage and visuals to ml_healthsystem. Default false = fully standalone
  • RealTerminalItem: true = Advanced mode (multiple Geiger items). Default false = Simple mode (single Geiger item), the shipped default

Geiger Counter Items

Advanced Mode

When Config.RealTerminalItem = true, each item opens a different Geiger Counter model and theme:

shared/config.lua
1Config.AdvancedItems = {
2    { item = "geiger_modern_green",    model = "model-modern",   theme = "theme-green",  batteryMax = 100, batteryDrain = 0.5 },
3    { item = "geiger_modern_blue",     model = "model-modern",   theme = "theme-blue",   batteryMax = 100, batteryDrain = 0.5 },
4    { item = "geiger_modern_orange",   model = "model-modern",   theme = "theme-orange", batteryMax = 100, batteryDrain = 0.5 },
5    { item = "geiger_standard_green",  model = "model-standard", theme = "theme-green",  batteryMax = 100, batteryDrain = 0.5 },
6    { item = "geiger_standard_blue",   model = "model-standard", theme = "theme-blue",   batteryMax = 100, batteryDrain = 0.5 },
7    { item = "geiger_standard_orange", model = "model-standard", theme = "theme-orange", batteryMax = 100, batteryDrain = 0.5 },
8    { item = "geiger_retro_green",     model = "model-retro",    theme = "theme-green",  batteryMax = 120, batteryDrain = 0.8 },
9    { item = "geiger_retro_blue",      model = "model-retro",    theme = "theme-blue",   batteryMax = 120, batteryDrain = 0.8 },
10    { item = "geiger_retro_orange",    model = "model-retro",    theme = "theme-orange", batteryMax = 120, batteryDrain = 0.8 },
11}
  • model: Display mode. Options:

- 'model-modern', 'model-standard', 'model-retro': Overlay mode: the interface renders as a screen overlay. Player can move freely, no prop or animation.

- 'dgm_geiger': DUI Prop mode: A physical 3D Geiger Counter object spawns and attaches to the player's chest. The interface renders directly onto the prop's texture via DUI texture replacement. The player plays a cellphone animation while holding the device.

  • theme: Color theme. Options: 'theme-green', 'theme-blue', 'theme-orange'
  • batteryMax: Maximum battery capacity (default 100, retro models use 120)
  • batteryDrain: Battery units consumed per real-time minute while the Geiger is active

Simple Mode

When Config.RealTerminalItem = false, only a single item is used:

shared/config.lua
1Config.SimpleMode = {
2    item = "dgm_geiger",
3    model = "dgm_geiger",
4    theme = "theme-green",
5    batteryMax = 100,
6    batteryDrain = 0.5,
7}

Display Modes

The model field determines how the Geiger Counter is displayed:

Overlay mode (model-modern, model-standard, model-retro): The Geiger UI renders as a screen overlay positioned via /movegeiger. No physical prop is created. The player can move and interact freely.

DUI Prop mode (dgm_geiger): A custom 3D model (dgm_geiger) spawns and attaches to the player's chest bone. The interface is rendered in real-time onto the prop's texture using DUI texture replacement. The player plays a holding animation while the Geiger is active. The prop is removed when the Geiger is closed.

Geiger UI

shared/config.lua
1Config.GeigerUI = {
2    ShowPlayerContaminationOnScreen = true,
3    StatusThresholds = {
4        Warning = 1.0,
5        Danger = 5.0,
6    },
7}
  • ShowPlayerContaminationOnScreen: Display the player's personal contamination level on the Geiger UI
  • StatusThresholds.Warning: Radiation level at which the UI shows a warning state
  • StatusThresholds.Danger: Radiation level at which the UI shows a danger state

Battery System

shared/config.lua
1Config.Battery = {
2    enabled = true,
3    drainPerMinute = 0.5,
4    lowThreshold = 20,
5    rechargeItem = 'battery',
6    rechargeAmount = 50,
7}
  • enabled: Enable/disable the battery system. When disabled, the Geiger runs indefinitely
  • drainPerMinute: Fallback drain rate (used when the item's batteryDrain is not set). Each item in Config.AdvancedItems can override this with its own batteryDrain
  • lowThreshold: Battery percentage at which a low battery warning notification appears
  • rechargeItem: Inventory item consumed to recharge the battery
  • rechargeAmount: Battery percentage restored per use (capped at 100)

Battery level is stored in item metadata (meta.battery) and persists across sessions. Drain ticks every 60 seconds while the Geiger is active, and auto-saves every 30 seconds. At 0 battery, the Geiger Counter closes automatically and a notification is shown. Players recharge by using the rechargeItem from their inventory.

Player Effects

shared/config.lua
1Config.PlayerEffects = {
2    Enabled = true,
3    MaxRadiation = 1000.0,
4    IncreaseSpeed = 200,
5    AutoRemove = {
6        Enabled = true,
7        Rate = 1.0,
8        SafeThreshold = 150.0,
9        GracePeriod = 12000,
10    },
11    Damage = {
12        Enabled = true,
13        Interval = 5000,
14        Thresholds = {
15            { level = 500.0, damage = 1 },
16            { level = 700.0, damage = 2 },
17            { level = 850.0, damage = 4 },
18            { level = 950.0, damage = 8 },
19        },
20    },
21}
  • MaxRadiation: Maximum radiation a player can accumulate
  • IncreaseSpeed: Higher = slower accumulation (used as a divisor)
  • AutoRemove.Enabled: Radiation decreases naturally when outside zones, but only below `SafeThreshold` and after the `GracePeriod` elapses with no new exposure. Default `true`
  • AutoRemove.Rate: Decrease rate per cycle when auto-remove is enabled. `SafeThreshold` = radiation only decays below this level (lower it for anti-abuse). `GracePeriod` = milliseconds of no new exposure before decay starts (default 12000)
  • Damage.Enabled: Enable periodic health damage from radiation
  • Damage.Interval: Milliseconds between damage ticks
  • Damage.Thresholds: Damage applied at each radiation level. Checked highest-first.

Visual Effects

Screen effects intensify as radiation increases:

shared/config.lua
1Config.PlayerEffects.Visuals = {
2    Enabled = true,
3    Thresholds = {
4        { level = 5.0,   effect = "MP_Bull_tost",     force = 0.20 },
5        { level = 25.0,  effect = "MP_Bull_tost",     force = 0.50 },
6        { level = 75.0,  effect = "MP_Bull_tost",     force = 0.85 },
7        { level = 175.0, effect = "torpedo",          force = 0.55 },
8        { level = 350.0, effect = "torpedo",          force = 0.90 },
9        { level = 550.0, effect = "DRUG_gas_huffin",  force = 0.65 },
10        { level = 800.0, effect = "DRUG_gas_huffin",  force = 1.00 },
11    },
12}

Radiation Sounds

The Geiger Counter plays audio based on zone radiation level:

shared/config.lua
1Config.RadiationSounds = {
2    Enabled = true,
3    Thresholds = {
4        { level = 100.0, sound = 'rad_high',   volume = 0.4 },
5        { level = 20.0,  sound = 'rad_medium', volume = 0.3 },
6        { level = 1.0,   sound = 'rad_low',    volume = 0.2 },
7    },
8}

Vehicle Protection

shared/config.lua
1Config.VehicleProtection = {
2    Enabled = true,
3    DefaultMultiplier = 0.6,
4    ExcludedClasses = { [8] = true, [13] = true, [14] = true, [15] = true, [16] = false },
5    SpecificVehicles = {
6        ['insurgent'] = 0.1,
7        ['apc'] = 0.05,
8        ['zentorno'] = 0.5,
9    },
10}
  • DefaultMultiplier: Radiation multiplier inside vehicles. 0.4 = player receives that fraction of radiation. Default is 0.6 (player receives 60% = 40% protection); lower it for stronger shielding
  • ExcludedClasses: Vehicle classes with no protection. Default excludes 8 (Motorcycles), 13 (Cycles), 14 (Boats), 15 (Helicopters); 16 (Planes) is set to `false` so planes do protect
  • SpecificVehicles: Override multiplier per vehicle model. 0.1 = 90% protection, 0.05 = 95% protection

Clothing Protection

shared/config.lua
1Config.ClothingProtection = {
2    Enabled = true,
3    RespectWear = true,
4    Suits = {
5        ['AntiRadSuit660'] = {
6            protection = 0.90,
7            male = { { component = 11, drawable = 660, texture = 0 } },
8        },
9        ['AntiRadMask244'] = {
10            protection = 0.60,
11            male = { { component = 1, drawable = 244, texture = 0 } },
12        },
13    },
14}
  • protection: Percentage of radiation blocked (0.70 = 70% protection)
  • male / female: Component/drawable/texture combinations that activate this suit. Add entries for both genders. `RespectWear = true` stops a worn-out suit/mask from protecting (ml_clothing wear). The default config ships AntiRad masks and suits already mapped

Cure Items

shared/config.lua
1Config.CureItems = {
2    Enabled = true,
3    Items = {
4        {
5            name = "radaway",
6            removeAmount = 550,
7            animation = {
8                duration = 5000,
9                label = 'Taking pills...',
10                dict = 'mp_player_intdrink',
11                clip = 'loop_bottle',
12                prop = {
13                    model = `prop_pill_container_01a`,
14                    bone = 60309,
15                    pos = vec3(0.1, -0.01, 0.0),
16                    rot = vec3(0.0, 0.0, -1.0),
17                },
18            },
19        },
20    },
21}
  • name: Inventory item name
  • removeAmount: Radiation points removed on use
  • animation: Optional animation with attached prop played during use

Immunity Items

shared/config.lua
1Config.ImmunityItems = {
2    Enabled = false,
3    Items = {
4        -- {
5        --     name = "iodine_pill",
6        --     protection = 1.0,
7        --     duration = 10,
8        --     animation = { ... },
9        -- },
10    },
11}
  • protection: Percentage of radiation blocked. 1.0 = 100% protection
  • duration: Duration in minutes. Item is consumed on use.

Radiation Zones

Three zone types are supported. All use ox_lib zones internally.

Sphere Zone

shared/config.lua
1{
2    type = 'sphere',
3    coords = vec3(3559.61, 3775.89, 30.06),
4    radius = 300.0,
5    maxRadiation = 1000.0,
6    dynamic = true,
7    force = 2.5,
8    debug = false,
9}

Box Zone

shared/config.lua
1{
2    type = 'box',
3    coords = vec3(447.12, -983.86, 30.68),
4    size = vec3(4.0, 4.0, 10.0),
5    rotation = 45.0,
6    maxRadiation = 8.5,
7    dynamic = false,
8    force = 2.5,
9    debug = false,
10}

Poly Zone

shared/config.lua
1{
2    type = 'poly',
3    points = {
4        vec3(-2048.81, 3128.59, 32.81),
5        vec3(-2045.18, 3140.89, 32.81),
6        vec3(-2058.42, 3145.24, 32.81),
7        vec3(-2061.85, 3132.88, 32.81),
8    },
9    thickness = 15.0,
10    maxRadiation = 50.0,
11    dynamic = true,
12    force = 1.0,
13    debug = false,
14}
  • type: Zone shape: 'sphere', 'box', or 'poly'
  • dynamic: true = radiation increases closer to center, false = flat radiation throughout
  • maxRadiation: Maximum radiation level inside the zone
  • force: Accumulation speed multiplier
  • debug: Show zone wireframe in-game

Server Configuration

server/config_server.lua
1ServerConfig.DiscordWebhook = ''
2ServerConfig.AdminWebhook = ''
3ServerConfig.AdminPermissions = { 'command', 'admin', 'god' }
  • DiscordWebhook: Webhook URL for player radiation events
  • AdminWebhook: Webhook URL for admin actions
  • AdminPermissions: ACE groups allowed to use admin commands
  • Rate limiting is applied per-event inside server/main.lua; there is no global cooldown key in config_server.lua.

Leave a webhook empty, or set it to the literal false, to disable that log. AdminPermissions ACE groups gate the admin notification path.