Skip to content

Configuration

All configuration is done in config.lua, located in the root of the sd-yacht resource folder.

Locale

Change the language by editing line 2 of config.lua:

lua
SD.Locale.LoadLocale('en') -- Options: 'en', 'de', 'es', 'fr', 'ar'

General Settings

KeyTypeDefaultDescription
Config.YachtDebugbooleanfalseEnable PolyZone debug visualization for testing
Config.MinimumCopsnumber4Minimum on-duty police required to start the heist
Config.PoliceJobstable{'police'}Array of job names counted toward the police requirement
Config.HasSpawnedOnYachtbooleantrueInternal spawn flag. Set to false for testing only -- must be true on live servers
Config.Cooldownnumber180Cooldown between heists in minutes (3 hours)
Config.ResetYachtOnLeavebooleanfalseIf true, resets the yacht and cooldown when all players leave and codes have not been entered yet
Config.CheckForItembooleantrueRequire the YachtCodes item to trigger the robbery
Config.Interactionstring'target'Interaction mode: 'target' (qb-target/ox_target) or 'textui' (drawtext/ox_lib textui)
Config.AlertPoliceOnEnterbooleantrueIf true, alerts police when someone enters the zone. If false, alerts when yacht codes are input
Config.GiveHintsbooleantrueShow hint messages guiding players through the heist

WARNING

If you restart the script with Config.HasSpawnedOnYacht = true, the resource will not function correctly. Only set it to false for testing, and always change it back to true for your live server.

Police Alert

The police dispatch is configured via a function in the config. You can modify the alert details or replace the function entirely to integrate with your dispatch system.

lua
policeAlert = function()
    SD.PoliceDispatch({
        displayCode = "10-31D",
        title = 'Yacht Heist',
        description = "Yacht Heist in progress",
        message = "Multiple suspects reported near the Yacht",
        sprite = 108,
        scale = 1.0,
        colour = 1,
        blipText = "Yacht Heist",
        dispatchcodename = "yacht_heist" -- Used by ps-dispatch
    })
end
KeyTypeDefaultDescription
displayCodestring"10-31D"Dispatch code shown in alerts
titlestring'Yacht Heist'Title used in cd_dispatch/ps-dispatch
descriptionstring"Yacht Heist in progress"Description of the alert
messagestring"Multiple suspects reported near the Yacht"Additional message or information
spritenumber108Blip sprite for the dispatch marker
scalenumber1.0Dispatch blip size on the map
colournumber1Dispatch blip color
blipTextstring"Yacht Heist"Text on the dispatch blip
dispatchcodenamestring"yacht_heist"Code name used by ps-dispatch in sv_dispatchcodes.lua

Items Used

These are the items required throughout the heist:

lua
Config.UsedItems = {
    USB = 'default_gateway_override',
    YachtCodes = 'yachtcodes',
    CasinoCodes = 'casinocodes',
    Safe = 'secured_safe',
    ReviveKit = 'revivekit',
}
KeyTypeDefaultDescription
USBstring'default_gateway_override'Item used for hacking laptops
YachtCodesstring'yachtcodes'Item required to start the heist
CasinoCodesstring'casinocodes'Casino codes item (used in heist progression)
Safestring'secured_safe'Safe item found on the yacht
ReviveKitstring'revivekit'Item used to revive downed teammates

Final Items

Items awarded to the player upon completing the heist:

lua
Config.FinalItems = {'casinocodes'} -- Extend with additional items: {'casinocodes', 'another_item'}

You can add as many items as you like to the array.

Cash Payout

KeyTypeDefaultDescription
Config.CashoutTypestring'dirty'Payout mode: 'clean' (unmarked cash), 'dirty' (marked bills / dirty_money for ESX), or 'custom' (custom item)

For 'custom' mode, configure the following:

lua
Config.CustomCash = {
    CashItem = 'markedbills',   -- The item identifier to use as currency
    CashQuantity = false,       -- false = 1 item per $1; true = give CashAmount quantity of CashItem
    CashAmount = { min = 1, max = 2 }, -- Only used when CashQuantity = true
}
KeyTypeDefaultDescription
CashItemstring'markedbills'Item identifier used as currency
CashQuantitybooleanfalseIf false, each item = $1. If true, the number of items given equals CashAmount
CashAmounttable{min = 1, max = 2}Random quantity range of CashItem given when CashQuantity = true

TIP

For ESX servers using the default dirty_money, you can use 'dirty' mode instead of 'custom' since ESX dirty_money is already 1:1.

Screen Sequence & Yacht Codes

KeyTypeDefaultDescription
Config.RandomizeYachtCodesbooleantrueGenerate a new 3-segment code on every server restart
Config.YachtCodeDefaultstring"21-65-31"Fallback code used when RandomizeYachtCodes is false
Config.CasinoCodesFirstHalfstring"Z892-25B6-14R4-"The first half of the casino codes displayed during the heist

The screen sequence (the order of bridge screens to hack) is randomized each robbery by default. To force a specific order, uncomment and set:

lua
-- Config.ScreenSequence = {3, 1, 2} -- Hack screen 3 first, then 1, then 2

INFO

If Config.ScreenSequence is not defined, the script automatically generates a random sequence each robbery.

Password Attempts

KeyTypeDefaultDescription
Config.PasswordAttemptsnumber2Number of password attempts allowed before the heist fails

Pressure Management

The yacht's engine pressure system is central to the heist. Pressure starts at 100 and auto-decreases over time. Players must manage two valves to keep it above the explosion threshold.

KeyTypeDefaultDescription
Config.EnableExplosionbooleantrueIf true, the yacht explodes when pressure falls to/below the threshold. If false, the yacht seizes up but does not explode
Config.PressureToExplodenumber15Pressure threshold at or below which the yacht explodes
Config.DecreaseTimenumber5How frequently (in seconds) pressure auto-decreases
Config.DecreaseAmountnumber1How much pressure decreases per DecreaseTime interval
Config.IncreasePressure1numbermath.random(3, 5)Amount valve 1 increases pressure (randomized between 3-5 per restart)
Config.IncreasePressure2numbermath.random(5, 8)Amount valve 2 increases pressure (randomized between 5-8 per restart)
Config.DecreasePressure1numbermath.random(1, 3)Amount valve 1 decreases pressure (randomized between 1-3 per restart)
Config.DecreasePressure2numbermath.random(5, 8)Amount valve 2 decreases pressure (randomized between 5-8 per restart)

TIP

You can replace the math.random() calls with fixed values if you want consistent pressure behavior (e.g., Config.IncreasePressure1 = 4).

Animation & Behavior Settings

KeyTypeDefaultDescription
Config.ForceAnimationbooleantrueForce the player into a carry/hold animation when holding certain heist items (e.g., safe on back, codes like a phone)
Config.WashUpOnBeachbooleantrueTeleport players to the beach after completing the heist
Config.SendToBeachOnSpawnbooleantrueIf a player spawns/logs in on the yacht, send them to the beach to prevent exploit re-entry
Config.SendBackOnResetbooleantrueSend players to the beach if they are in the yacht area when the cooldown resets
Config.UsingReviveKitsbooleantrueEnable revive kit functionality. If false, revive kits have no effect
Config.GiveAllbooleanfalseIf true, give all items from a searched cabin. If false, give one random item

Blip

lua
Config.Blip = {
    Enable = true,
    Location = vector3(-2031.6, -1038.13, 5.88),
    Sprite = 455,
    Display = 4,
    Scale = 0.6,
    Colour = 1,
    Name = "Secured Yacht",
    Radius = { Enable = true, Size = 100.0 },
}
KeyTypeDefaultDescription
EnablebooleantrueShow the yacht blip on the map
Locationvector3(-2031.6, -1038.13, 5.88)Map coordinates for the blip
Spritenumber455Blip icon sprite ID
Displaynumber4Blip display mode
Scalenumber0.6Blip size on the map
Colournumber1Blip color ID
Namestring"Secured Yacht"Text label for the blip
Radius.EnablebooleantrueShow a radius circle around the blip
Radius.Sizenumber100.0Size of the radius circle

Hacking Minigames

Two separate hacking configurations are available -- one for laptops and one for bridge terminals. Each supports 30+ minigame options from various resources.

Laptop Hacking

lua
Config.Hacking.Laptop = {
    Minigame = 'hacking-opengame', -- Active minigame
    Args = { ... },                -- Arguments for each supported minigame
}

Terminal Hacking

lua
Config.Hacking.Terminal = {
    Minigame = 'ps-circle', -- Active minigame
    Args = { ... },         -- Arguments for each supported minigame
}

Set the Minigame value to the name of the minigame you want to use. The Args table contains pre-configured arguments for every supported minigame -- only the one matching your Minigame selection is used.

Supported Minigames

SourceMinigame KeyDefault ArgsDescription
ps_uips-circle{2, 20}Number of circles, time (ms)
ps_uips-maze{20}Time (seconds)
ps_uips-varhack{2, 3}Number of blocks, time (seconds)
ps_uips-thermite{10, 5, 3}Time (s), grid size, incorrect blocks
ps_uips-scrambler{'numeric', 30, 0}Type, time (s), mirrored option
memorygamememorygame-thermite{10, 3, 3, 10}Correct blocks, incorrect blocks, show time (s), lose time (s)
ranran-memorycard{360}Time (seconds)
ranran-openterminal{}No arguments
nopixelhacking-opengame{15, 4, 1}Time (s), number of blocks, number of repeats
howdyhowdy-begin{3, 5000}Number of icons, time (ms)
snsn-memorygame{3, 2, 10000}Keys needed, rounds, time (ms)
snsn-skillcheck{50, 5000, {'w','a','s','w'}, 2, 20, 3}Speed (ms), time (ms), keys, rounds, bars, safe bars
snsn-thermite{7, 5, 10000, 2, 2, 3000}Boxes, correct boxes, time (ms), lives, rounds, show time (ms)
snsn-keypad{999, 3000}Code number, time (ms)
snsn-colorpicker{3, 7000, 3000}Icons, type time (ms), view time (ms)
rainmadrm-typinggame{'easy', 20}Difficulty, duration (s)
rainmadrm-timedlockpick{200}Speed value
rainmadrm-timedaction{3}Number of locks
rainmadrm-quicktimeevent{'easy'}Difficulty
rainmadrm-combinationlock{'easy'}Difficulty
rainmadrm-buttonmashing{5, 10}Decay rate, increment rate
rainmadrm-angledlockpick{'easy'}Difficulty
rainmadrm-fingerprint{200, 5}Time (s), lives
rainmadrm-hotwirehack{10}Time (seconds)
rainmadrm-hackerminigame{5, 3}Length, lives
rainmadrm-safecrack{'easy'}Difficulty
bl_uibl-circlesum{3, {length = 4, duration = 5000}}Iterations, length, duration (ms)
bl_uibl-digitdazzle{3, {length = 4, duration = 5000}}Iterations, length, duration (ms)
bl_uibl-lightsout{3, {level = 2, duration = 5000}}Iterations, level, duration (ms)
bl_uibl-minesweeper{3, {grid = 4, duration = 10000, target = 4, previewDuration = 2000}}Iterations, grid, duration, target, preview (ms)
bl_uibl-pathfind{3, {numberOfNodes = 10, duration = 5000}}Iterations, nodes, duration (ms)
bl_uibl-printlock{3, {grid = 4, duration = 5000, target = 4}}Iterations, grid, duration, target
bl_uibl-untangle{3, {numberOfNodes = 10, duration = 5000}}Iterations, nodes, duration (ms)
bl_uibl-wavematch{3, {duration = 5000}}Iterations, duration (ms)
bl_uibl-wordwiz{3, {length = 4, duration = 5000}}Iterations, length, duration (ms)
glitchgl-firewall-pulse{3, 2, 10, 10, 40, 120, 10}Hacks, initial speed, max speed, time limit, min/max safe zone width, shrink amount
glitchgl-backdoor-sequence{3, 5, 15, 3, 1.0, 1, 3, keys, hint}Sequences, length, time limit, attempts, penalty, min/max keys, custom keys, hint text
glitchgl-circuit-rhythm{4, {'A','S','D','F'}, 150, 1000, 20, 'normal', 5, 3}Lanes, keys, note speed, spawn rate, required notes, difficulty, wrong keys, missed notes
glitchgl-surge-override{{'E'}, 50, 2, false, combos}Keys, presses, decay rate, multi-key mode, combinations
glitchgl-circuit-breaker{1, 0, 1000, 5000, 5000, 0, 0, 3000, 30000}Level, difficulty, delay, min/max fail delay, disconnect chance/rate, min/max reconnect time
glitchgl-data-crack{3}Difficulty
glitchgl-brute-force{}No args (default 5 lives)
glitchgl-var-hack{5, 5}Blocks, speed (s)

INFO

Both Laptop and Terminal support the same full list of minigames. Only the active Minigame value determines which one runs -- all other entries in Args are ignored at runtime.

Guards

KeyTypeDefaultDescription
Config.EnableGuardsbooleantrueEnable NPC guard spawning on the yacht
Config.EnableLootingbooleantrueAllow players to loot dead guards

Guard Parameters

lua
Config.PedParameters = {
    Ped = "mp_m_bogdangoon",
    Health = 200,
    Weapon = {"WEAPON_PISTOL", "WEAPON_SMG", "WEAPON_ASSAULTRIFLE"},
    MinArmor = 50,
    MaxArmor = 100,
    Headshots = true,
    CombatAbility = 100,
    Accuracy = 60,
    CombatRange = 2,
    CombatMovement = 2,
    CanRagdoll = true,
}
KeyTypeDefaultDescription
Pedstring"mp_m_bogdangoon"Ped model for the guards
Healthnumber200Maximum and initial health of guards
Weapontable{"WEAPON_PISTOL", "WEAPON_SMG", "WEAPON_ASSAULTRIFLE"}List of weapons randomly assigned to guards
MinArmornumber50Minimum armor value for guards
MaxArmornumber100Maximum armor value for guards
HeadshotsbooleantrueWhether guards can receive critical hits (headshots)
CombatAbilitynumber100Combat ability (0-100, higher = better)
Accuracynumber60Shot accuracy (0-100, higher = more accurate)
CombatRangenumber2Engagement range: 0 = short, 1 = medium, 2 = long
CombatMovementnumber2Movement style: 0 = calm, 1 = normal, 2 = aggressive
CanRagdollbooleantrueWhether guards can be ragdolled from player impact

Guard Spawn Locations

The config defines 10 guard spawn positions in Config.Guards. Each entry is a vector4 with x, y, z, and heading. You can add, remove, or reposition guards by editing the coords table.

Guard Loot Rewards

lua
Config.Rewards = {
    weaponChance = 60,
    itemRange = { min = 2, max = 3 },
    PistolRewards  = { items = {"weapon_heavypistol", "weapon_pistol", "weapon_pistol_mk2"}, chance = 37, isGunReward = true },
    RareRewards    = { items = {"weapon_assaultrifle", "weapon_compactrifle", "weapon_mg"}, chance = 15, isGunReward = true },
    SMGRewards     = { items = {"weapon_assaultsmg", "weapon_minismg", "weapon_combatpdw"}, chance = 32, isGunReward = true },
    ShotgunRewards = { items = {"weapon_sawnoffshotgun", "weapon_pumpshotgun", "weapon_dbshotgun"}, chance = 25, isGunReward = true },
    AmmoRewards    = { items = {"pistol_ammo", "shotgun_ammo", "rifle_ammo", "smg_ammo"}, chance = 45, amount = {min = 1, max = 2} },
    MedicRewards   = { items = {"bandage", "revivekit"}, chance = 45, amount = {min = 1, max = 2} },
}
KeyTypeDefaultDescription
weaponChancenumber60Overall percentage chance of receiving any gun-related reward
itemRangetable{min = 2, max = 3}Min/max number of items a player receives per loot
PistolRewards.chancenumber37Weighted chance for pistol category
RareRewards.chancenumber15Weighted chance for rare weapon category
SMGRewards.chancenumber32Weighted chance for SMG category
ShotgunRewards.chancenumber25Weighted chance for shotgun category
AmmoRewards.chancenumber45Weighted chance for ammo category
AmmoRewards.amounttable{min = 1, max = 2}Random quantity of ammo items given
MedicRewards.chancenumber45Weighted chance for medical supply category
MedicRewards.amounttable{min = 1, max = 2}Random quantity of medical items given

INFO

The chance values are relative weights, not percentages that must add to 100. A category with chance = 45 is three times more likely than one with chance = 15. Only one gun reward (isGunReward = true) can be selected per loot. Non-gun categories can stack freely within itemRange.

Puzzle Configuration

The puzzle state table tracks progression through the heist. These are default values and reset each robbery.

lua
Config.Puzzle = {
    [1]  = { screens = false },   -- Whether the screen sequence has been completed
    [2]  = { one = false },       -- Screen 1 hacked
    [3]  = { two = false },       -- Screen 2 hacked
    [4]  = { three = false },     -- Screen 3 hacked
    [5]  = { four = false },      -- Screen 4 state
    [6]  = { pressure = 100 },    -- Starting pressure (psi)
    [7]  = { bricked = false },   -- Whether the system has been bricked (failed)
    [8]  = { word = math.random(1, 4) }, -- Random password word index (1-4)
    [9]  = { button = false },    -- Engine start button pressed
    [10] = { vault = false },     -- Vault opened
    [11] = { case = false },      -- Briefcase collected
    [12] = { codes = false },     -- Codes entered
}

WARNING

Do not modify Config.Puzzle unless you fully understand the heist flow. Incorrect changes can break the progression system.

Cabin Rewards

Five searchable cabins are defined in Config.Cabins. Each cabin has a location, search animation, and item pool.

lua
Config.Cabins = {
    [1] = {
        coords = vector4(-2050.86, -1024.12, 8.8, 335.89),
        isSearched = false,
        isBusy = false,
        animDic = 'veh@break_in@0h@p_m_one@',
        animName = 'low_force_entry_ds',
        ['items'] = {
            [1] = { item_name = 'rolex', item_amount = 1 },
            [2] = { item_name = 'rolex', item_amount = 2 },
        }
    },
    -- Cabins 2-5 follow the same structure
}

Default Cabin Item Pools

CabinItemsAmounts
1rolex1 or 2
2rolex1 or 2
3rolex, 10kgoldchain1 or 2
4goldbar, 10kgoldchain1 each
510kgoldchain, tablet2 or 1

TIP

When Config.GiveAll = false (default), the player receives one random item from the cabin's pool. Set it to true to give all listed items.

Scattered Valuables

Eight pickupable items are placed around the yacht in Config.Items. These include champagne, watches, and a safe.

IndexModelItemLabel
1prop_champ_01bexpensive_champagneChampagne
2prop_champ_01bexpensive_champagneChampagne
3prop_champ_01bexpensive_champagneChampagne
4prop_champ_01bexpensive_champagneChampagne
5p_watch_05rolexWatch
6p_watch_05rolexWatch
7prop_champ_01bexpensive_champagneChampagne
8prop_ld_int_safe_01(safe -- hardcoded)Safe

Cash Tray Settings

Three cash tray locations are defined, each spawning a cash stack prop on a desk.

lua
Config.CashTrays = {
    [1] = {
        coords = vector4(-2099.54, -1020.7, 5.38, 162.57),
        isSearched = false,
        model = 'h4_prop_h4_cash_stack_01a',
        tabel_model = 'prop_office_desk_01',
        min = 5000,
        max = 10000,
    },
    -- Trays 2 and 3 use the same models and payout range
}
KeyTypeDefaultDescription
coordsvector4(per tray)World position and heading of the cash tray
isSearchedbooleanfalseTracks whether this tray has been looted (resets each robbery)
modelstring'h4_prop_h4_cash_stack_01a'Prop model for the cash stack
tabel_modelstring'prop_office_desk_01'Prop model for the desk under the cash
minnumber5000Minimum cash payout from this tray
maxnumber10000Maximum cash payout from this tray

INFO

The payout amount from each tray is randomized between min and max. The payout type (clean, dirty, or custom) is controlled by Config.CashoutType.

Screen Symbols

Config.Screens defines 30 symbol images used in the screen puzzle. Entries 1-14 are English letter symbols (R, L, G, D, U, E, O, N, P, F, W, M, I, A), and entries 15-30 are non-English character symbols. Each entry contains a url pointing to the image hosted externally.

You can replace these URLs with your own images to customize the puzzle appearance.

Locations

All interactable positions are defined in Config.Locations:

lua
Config.Locations = {
    BeachWashup = vector4(-1839.39, -885.44, 1.68, 117.33),
    Screen_One = vector3(-2086.77, -1019.86, 12.53),
    Screen_Two = vector3(-2086.66, -1017.5, 12.5),
    Screen_Three = vector3(-2085.31, -1015.74, 12.27),
    PuzzleStart = vector3(-2029.52, -1033.62, 2.8),
    PressureValve_One = vector3(-2063.6, -1025.01, 2.5),
    PressureValve_Two = vector3(-2052.57, -1032.55, 3.29),
    CheckPressure = vector3(-2068.92, -1023.55, 3.1),
    AttemptPassword = vector4(-2074.1, -1024.5, 11.62, 251.28),
    RedButton = vector3(-2030.78, -1037.69, 2.8),
    EnterVault = vector3(-2071.36, -1018.63, 3.24),
    ExitVault = vector3(-2072.83, -1018.49, 2.62),
    EnterVaultPlayer = vector4(-2072.94, -1018.59, 1.46, 72.14),
    ExitVaultPlayer = vector4(-2071.04, -1018.72, 1.95, 246.56),
    FinalBriefcase = vector4(-2074.31, -1018.11, 2.0, 72.12),
    Hack_1 = vector3(-2079.38, -1015.88, 5.91),
    Hack_2 = vector3(-2081.64, -1022.54, 8.38),
    Hack_3 = vector3(-2072.3, -1019.0, 11.82),
    Hack_4 = vector3(-2072.3, -1021.66, 2.99),
}

Yacht Area Detection

The yacht area is defined as a sphere for player-in-zone detection:

lua
Config.Points = {
    yacht = {
        coords = vector3(-2044.17, -1011.93, 0.0),
        distance = 60.0,
    }
}
KeyTypeDefaultDescription
coordsvector3(-2044.17, -1011.93, 0.0)Approximate center of the yacht
distancenumber60.0Detection radius around the center point