> For the complete documentation index, see [llms.txt](https://patriot-studios.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://patriot-studios.gitbook.io/docs/scripts/money-wash/advanced-config.md).

# Advanced Config

1.0.0

This is the default config.lua code for the most up to date version of the Patriot Money Wash: Advanced script. As part of the config file are code comments which explain the settings & allow you to customise the script how you see fit.

```lua
Config = {}

Config.Debug = false

Config.Framework = 'auto'     -- 'auto', 'esx', 'qbcore', 'qbox'
Config.Inventory = 'auto'     -- 'auto', 'ox_inventory', 'qb-inventory', 'framework'

Config.MenuColor = '#D12DFF'  -- Main Color for UI (must be in hex code form)
Config.NotifyDurationSecs = 5 -- how long notifications stay visible

-- Clean money payout account for NPC washes (cash by default)
Config.CleanMoneyAccount = 'cash' -- ESX: 'money' mapped in bridge when 'cash'

-- Dirty money sources (bridge sums all configured entries)
Config.DirtyMoneyItems = {
    { item = 'black_money', type = 'item' },
    { item = 'markedbills', type = 'item', worthKey = 'worth' },
}

Config.WashingMachineItem = 'washing_machine'

-- Interaction distances (meters)
Config.InteractDistance = 2.5
Config.ApproachDistance = 10.0

-- Cooldown between wash/deposit attempts (seconds)
Config.ActionCooldownSecs = 0.5

-- Money Wash NPC
Config.NPC = {
    model = 'a_m_y_downtown_01',
    interactionLabel = 'Talk to Washer',
    coords = vector4(105.9375, -1566.5363, 29.6027, 268.7397),
    taxRate = 0.20,
    processTimeSecs = 10,
    minAmount = 10,
    maxAmount = 10000000,

    policeAlertChance = 10,
    washMaxDistance = 10,  -- cancels wash & refunds dirty money if player goes farther than this from NPC
    scenario = 'WORLD_HUMAN_SMOKING',
    machinePrice = 150000, -- how much dirty money it cost to buy a portable washing machine

    blipEnabled = true,
    blipSprite = 77,
    blipColor = 27,
    blipScale = 0.85,
    blipVisibleDistance = 150.0,                        -- how many meters before the blip appears on the minimap (always visible on pause map)
    blipLabel = 'Laundromat (Search Area)',
    blipCoords = vector3(83.5788, -1551.4508, 29.5978), -- map blip position (independent of NPC coords)

    blipArrivalHintEnabled = true,
    blipArrivalRadius = 35.0, -- how many meters from blipCoords before the arrival hint is shown
    blipArrivalHint = "You've reached the laundromat. Look around the building to find the washer.",
}

-- Bitcoin ATMs
Config.BTM = {
    model = 'patriot_moneywash_atm',
    taxRate = 0.50,
    processingTimeSecs = 86400,  -- 24 hours
    payoutPollIntervalSecs = 15, -- fallback DB poll for offline/restart payouts
    minAmount = 10,
    maxAmount = 1000000,

    witnessAlertChance = 45,
    witnessDialDurationSecs = 6,   -- total time to interrupt before the witness connects the call
    witnessSpeechLine = 'PHONE_CALL_COPS',
    witnessSpeechTimeoutSecs = 12, -- max wait for the voiceline to finish
    witnessSpawnDistance = 3.0,    -- meters behind the player when witness appears
    witnessSpawnRetries = 6,       -- alternate behind positions tried when a spot is blocked
    witnessDespawnDelaySecs = 30,  -- how many seconds after a completed call before witness is removed (walks away first)

    silentAlertThreshold = 50000,

    blipEnabled = true,
    blipSprite = 108,
    blipColor = 27,
    blipScale = 1,
    blipVisibleDistance = 150.0, -- how many meters before the blip appears on the minimap (always visible on pause map)
    blipLabel = 'Crypto ATM',    -- map label used for every BTM blip
    locations = {
        { label = 'Rodeo Drive',    coords = vector4(-741.6750, -115.8693, 37.8176, 119.4012) },
        { label = 'Diamond Casino', coords = vector4(929.0645, 54.4786, 81.0961, 56.0330) },
        { label = 'Stadium',        coords = vector4(-280.8966, -1916.9071, 29.9460, 317.1974) },
        { label = 'El Burro',       coords = vector4(1312.3363, -1649.3029, 52.1456, 303.8862) },
        { label = 'Legion Square',  coords = vector4(258.2782, -784.6592, 30.4836, 67.5212) },
        { label = 'Pier',           coords = vector4(-1634.3119, -1064.8864, 13.1526, 229.6501) },
        { label = 'LS Airport',     coords = vector4(-1055.9849, -2764.3240, 4.6397, 236.7133) },
        { label = 'Paleto Bay',     coords = vector4(-216.1514, 6216.8242, 31.4911, 226.3396) },
        { label = 'Grapeseed',      coords = vector4(1684.2621, 4834.8765, 42.0185, 187.4646) },
        { label = 'Sandy Shores',   coords = vector4(1979.5981, 3064.2368, 47.1540, 239.1066) },
        { label = 'Right Highway',  coords = vector4(2547.3240, 339.1227, 108.4566, 356.6692) },
        { label = 'Left Highway',   coords = vector4(-3426.5928, 967.7913, 8.3467, 266.9625) },
    },
}

-- Portable washing machine
Config.Machine = {
    model = 'patriot_moneywash_machine',
    taxRate = 0.10,
    processTimeSecs = 300,

    soundEnabled = true,
    soundRadius = 40.0,
    soundVolume = 0.35, -- max volume (0.0–1.0)
    soundFile = 'washing_machine_sound.ogg',
    -- soundUrl = '', -- optional external URL (xsound only)

    packUpTimeSecs = 3,
    placementForwardOffset = 1.75,       -- how many meters in front of player during placement preview
    placementRotationLockDefault = true, -- starts with 90° rotation snap enabled
    minAmount = 10,
    maxAmount = 300000,
    payoutAccount = 'cash', -- clean money account for completed machine washes
    maxPlacedPerPlayer = 3, -- max machines placed in the world per player; 0 = unlimited
    allowPublicUse = true,  -- false = only the owner can wash at their machine
}

-- Police
Config.Police = {
    Jobs = { 'police' },
    PolicePerm = 'police.alert',
    DispatchMode = 'integrated', -- 'integrated' or 'external'

    BlipSprite = 58,
    BlipColor = 1,
    BlipScale = 1.0,
    blipDurationSecs = 30,

    SearchCircleRadius = 150.0,
    searchCircleDurationSecs = 90,

    confiscateRewardEnabled = true,
    confiscateRewardAmount = 1500,
    confiscateRewardAccount = 'cash', -- 'cash' or 'bank'

    -- false (default): machine & any dirty money in an active wash is destroyed
    -- true: machine item & dirty money are added to the confiscating officer's inventory (evidence)
    confiscateEvidenceMode = false,

    -- BTM witness 911 call (when a spawned witness completes their police call)
    btmWitness = {
        dispatchMessage = '911 CALL: Witness reports suspicious crypto ATM activity near %s.',
        blipLabel = 'Witness 911 Call',
        blipSprite = 480,
        blipColor = 1,
        minCallSecs = 3, -- how many seconds on the line the NPC has to be before police are alerted
        -- blipScale optional — falls back to Config.Police.BlipScale
    },
}

-- Noise complaint (the portable washing machine alerts to police)
Config.NoiseComplaint = {
    zones = {
        { label = 'industrial1',            coords = vector3(850.4526, -2235.6946, 30.2646),   radius = 400.0, complaintChance = 0 },
        { label = 'industrial2',            coords = vector3(913.0782, -1571.9706, 30.7631),   radius = 300.0, complaintChance = 0 },
        { label = 'industrial3',            coords = vector3(1045.3336, -1041.3014, 27.9009),  radius = 300.0, complaintChance = 0 },
        { label = 'industrial4',            coords = vector3(1240.5522, -1364.8113, 35.1436),  radius = 200.0, complaintChance = 0 },
        { label = 'industrial5',            coords = vector3(698.9337, -1207.4415, 27.8386),   radius = 200.0, complaintChance = 0 },
        { label = 'industrial6',            coords = vector3(768.0790, -803.2810, 26.3421),    radius = 200.0, complaintChance = 0 },
        { label = 'industrial7',            coords = vector3(707.6125, -3041.4609, 6.2550),    radius = 800.0, complaintChance = 0 },
        { label = 'industrial8',            coords = vector3(-515.2653, -2433.9924, 20.9834),  radius = 700.0, complaintChance = 0 },
        { label = 'industrial9',            coords = vector3(219.7840, -2256.8367, 10.7159),   radius = 200.0, complaintChance = 0 },
        { label = 'industrial10',           coords = vector3(-1573.7504, -2973.4805, 14.3139), radius = 600.0, complaintChance = 0 },
        { label = 'industrial11',           coords = vector3(-891.9996, -3356.3098, 14.2728),  radius = 500.0, complaintChance = 0 },
        { label = 'industrial12',           coords = vector3(-1280.3103, -2119.5310, 13.9249), radius = 300.0, complaintChance = 0 },
        { label = 'industrial zone',        coords = vector3(2767.7205, 1531.9485, 30.7861),   radius = 200.0, complaintChance = 0 },
        { label = 'commercial',             coords = vector3(200.0, -900.0, 30.0),             radius = 500.0, complaintChance = 10 },
        { label = 'commercial2',            coords = vector3(240.5770, -43.7856, 69.7196),     radius = 450.0, complaintChance = 10 },
        { label = 'commercial3',            coords = vector3(986.2874, 10.3386, 80.9903),      radius = 300.0, complaintChance = 10 },
        { label = 'commercial4',            coords = vector3(-1285.3434, -507.4314, 33.1250),  radius = 300.0, complaintChance = 10 },
        { label = 'commercial5',            coords = vector3(-539.3151, -325.9439, 35.1148),   radius = 400.0, complaintChance = 10 },
        { label = 'grapeseed commercial',   coords = vector3(1678.1383, 4766.8857, 41.9955),   radius = 200.0, complaintChance = 10 },
        { label = 'paleto bay commercial1', coords = vector3(-367.1426, 6011.7900, 31.2775),   radius = 100.0, complaintChance = 10 },
        { label = 'paleto bay commercial2', coords = vector3(-223.7904, 6155.1309, 31.1994),   radius = 100.0, complaintChance = 10 },
    },
    defaultChance = 20, -- the chance outside defined zones; 0 = none
    dispatchMessage = 'Noise complaint: residents report a loud appliance noise near %s.',

    previewEnabled = true,
    previewCommand = 'previewnoisezones',
    previewAce = 'command.previewnoisezones',
    previewDurationSecs = 60,

    blipLabel = 'Noise Complaint',
    blipColor = 3,
    -- blipSprite / blipScale optional — falls back to Config.Police.BlipSprite / BlipScale
}

-- Power outage (when multiple machines are running nearby)
Config.PowerOutage = {
    proximityRadius = 100.0,     -- how close running machines must be to each other to trigger
    minMachinesRunning = 3,      -- the amount of machines that must be running to trigger outageChance
    outageChance = 30,           -- percent chance to trigger an outage when cluster conditions are met

    clusterCooldownSecs = 300,   -- 5 minutes — per-cluster re-trigger delay
    clusterDurationSecs = 120,   -- 2 minutes — how long a local blackout lasts
    effectRadius = 150.0,        -- players within this range of the cluster center see the blackout
    maxConcurrentOutages = 0,    -- 0 = unlimited simultaneous zones; raise to cap map-wide outages
    clusterCooldownRadius = nil, -- per-cluster cooldown radius (defaults to effectRadius)

    notifyMessage = 'Localized power outage detected in the area!',
    dispatchMessage = 'Grid overload reported near %s. Possible illegal high-draw operation.',

    blipLabel = 'Power Grid Alert',
    blipColor = 46,
    blipSprite = 769,
    blipScale = 1.0,
    publicMapBlip = false,          -- local outage map blip visible to police only (set true for all players)

    searchCircleRadius = 150.0,     -- local police search radius (falls back to Config.Police.SearchCircleRadius)
    searchCircleDurationSecs = nil, -- nil = use Config.Police.searchCircleDurationSecs

    cityWide = {
        enabled = true,
        outagesRequired = 3,

        windowSecs = 1800,   -- 30 minutes — local outages must occur within this window
        durationSecs = 1200, --20 minute city-wide blackout length
        cooldownSecs = 7200, -- 2 hours — min time between city-wide triggers
        notifyMessage = 'City-wide power grid failure!',
        dispatchLocationLabel = 'city grid',
        dispatchMessage = 'GRID ALERT: City-wide power failure reported near %s.',

        blipLabel = 'City Grid Failure',
        blipColor = 46,
        blipSprite = 769,
        blipScale = 1.0,
        blipCoords = vector3(0.0, 0.0, 72.0), -- center for map-wide search circle
        publicMapBlip = true,                 -- city-wide map blip shown to everyone

        searchCircleRadius = 3000.0,          -- large search radius for all players
        searchCircleDurationSecs = nil,       -- nil = use durationSecs
    },
}

-- Admin
Config.Admin = {
    removeMachineCommand = 'removewashmachine', -- /removewashmachine (removes machine you are facing)
    removeMachineAce = 'command.removewashmachine',
    removeMachineMaxDistance = 5.0,             -- meters
}

-- Staff Discord logging (single webhook, four embed categories)
Config.Logs = {
    enabled = true,
    webhook = 'place your webhook here', -- paste your Discord webhook URL here (keep private — rotate if exposed)
    console = false,                     -- set true if you want to print logs to server console / txAdmin
    botName = 'Patriot Money Wash',
    colors = {
        civilian = 10181046, -- purple in decimal
        police = 3447003,    -- blue in decimal
        staff = 15158332,    -- red in decimal
        power = 16776960,    -- bright yellow in decimal
    },
    events = {
        -- Civilian
        npc_wash_start = true,
        npc_wash_complete = true,
        npc_wash_cancel = true,
        btm_deposit = true,
        btm_payout = true,
        machine_purchase = true,
        machine_place = true,
        machine_pack = true,
        machine_steal = true,
        machine_wash_start = true,
        machine_wash_complete = true,

        -- Police
        police_npc_alert = true,
        police_btm_silent = true,
        police_btm_witness = true,
        police_machine_area = true,
        police_confiscate = true,

        -- Power outages
        power_outage_local = true,
        power_outage_city = true,

        -- Staff
        admin_remove_machine = true,
    },
}
```
