pickpocket.lua
The complete default pickpocket.lua for Petty Crimes (sd-pettycrime). Use this as a reference or a starting point for your own configuration.
TIP
This is the full, unedited config file. For a detailed explanation of each option, see the Configuration page.
lua
return {
Enable = true, -- Master on/off switch for this crime. false = fully disabled (no targets, no events).
Time = 5, -- (Legacy) progress-bar duration — unused since the minigame replaced it. Kept for compat with any third-party readers.
Chance = 75, -- (Legacy) overall % chance to find anything — superseded by the minigame outcome.
BaseXP = 8, -- Base XP awarded on every successful pick.
-- When true, the target ped is tasked to stand still for the duration of the
-- attempt so it doesn't wander off while you stand there picking its pocket.
-- The hold is released once the attempt resolves (or the ped flees if caught).
FreezeTarget = true,
-- Minigame selector. `Start` runs when a pickpocket attempt begins; it
-- receives ctx (ctx.items = the server-rolled REAL loot slots, each
-- carrying its own rarity-sized zone) and returns the minigame result.
-- Swap the body for any other built-in (see client/minigame.lua: lockpick,
-- lockpickBar, holdSteady, mash, stealth, dial, wires, sequence) or your
-- own — without touching the crime code. Set Enable = false to skip it.
--
-- Note: only mg.pickpocket reports which slots were grabbed (partial
-- loot). Other minigames are pass/fail, so on success the player gets all
-- rolled items, otherwise none.
Minigame = {
Enable = true,
Start = function(ctx)
return Minigames.pickpocket({
items = ctx.items, -- real loot slots; count + rarity rolled server-side per tier/level
-- Extra EMPTY "???" decoy slots shuffled in among the real loot.
-- They look identical until grabbed, then reveal as empty and
-- give nothing (pure time-sink). Randomised per attempt;
-- { min = 0, max = 0 } disables them. (How many REAL items show,
-- and how rare they are, is set per tier/level in Tiers below.)
emptySlots = { min = 1, max = 3 },
-- Grab-zone width per slot, in degrees of the marker's full pass
-- (360°). Scales on rarity: the rarest rolled item gets `min`
-- (hardest), the most common gets `max` (easiest); empty decoys
-- use `max`. Widen the spread for an easier game, narrow it for a
-- harder one. A plain number (e.g. 30) gives every slot the same
-- width (no rarity scaling).
grabZoneDeg = { min = 12, max = 34 },
-- Marker speed in deg/sec (360° = one full pass across the bar).
rotationSpeedDegSec = 180,
-- Speed up (and flip direction) after each successful grab.
-- false = constant speed, only the direction flips.
speedUp = true,
-- Speed multiplier per grab — only applied when speedUp = true.
speedUpMultiplier = 1.35,
-- Time limit in seconds; running out = caught. 0 = no limit.
timeLimitSec = 15,
-- Per-item chance (0..1) a REAL card starts hidden as "???"
-- (empty slots are always hidden until grabbed).
mysteryChance = 0.5,
})
end,
},
GiveXPForItems = true, -- Adds the per-item XP value when an item drops.
GiveXPForCash = true, -- Adds 1 XP per $ stolen (set false for flat per-pick XP).
Logging = true, -- lib.logger entries on success/fail.
PoliceAlert = {
Enable = true,
Chance = 15, -- 0-100 chance an alert fires on a successful pick.
Send = function()
-- Police alerts route through this resource's dispatch bridge at
-- bridge/client/alert.lua, which auto-detects your dispatch system.
-- You can freely change this Send function to whatever you want.
Alert.send({
displayCode = '10-15',
title = 'Pickpocketing',
message = 'Pickpocketing reported',
description = 'Pickpocketing reported',
blipText = '911 - Pickpocketing',
sprite = 431,
colour = 3,
scale = 1.2,
})
end,
},
-- Tiered loot tables. Each tier carries its own cash range *and* a level-
-- keyed bucket (`[1]`, `[2]`, `[3]`). Each level bucket has:
-- lootCount : { min, max } — how many REAL loot slots to roll for a player
-- at that level in this tier (each becomes a card + grab zone).
-- items : the weighted pool the slots are drawn from (duplicates ok).
--
-- HOW WEIGHTED CHANCE WORKS
-- The `chance` field is a *weight*, not a percentage — higher weight =
-- proportionally more likely, AND it sizes the grab zone (rarer = smaller).
-- e.g. `chance=20` is twice as likely as `chance=10` in the same bucket.
Tiers = {
low = {
cash = { min = 4, max = 15 },
[1] = {
lootCount = { min = 2, max = 3 },
items = {
{ item = 'metalscrap', chance = 25, min = 1, max = 2, xp = 1 },
{ item = 'copper', chance = 15, min = 1, max = 1, xp = 2 },
},
},
[2] = {
lootCount = { min = 2, max = 4 },
items = {
{ item = 'metalscrap', chance = 20, min = 2, max = 3, xp = 1 },
{ item = 'copper', chance = 15, min = 1, max = 2, xp = 2 },
{ item = 'aluminum', chance = 10, min = 1, max = 1, xp = 3 },
},
},
[3] = {
lootCount = { min = 3, max = 5 },
items = {
{ item = 'metalscrap', chance = 18, min = 3, max = 4, xp = 1 },
{ item = 'copper', chance = 15, min = 2, max = 3, xp = 2 },
{ item = 'aluminum', chance = 12, min = 1, max = 2, xp = 3 },
{ item = 'steel', chance = 8, min = 1, max = 1, xp = 5 },
},
},
},
medium = {
cash = { min = 12, max = 32 },
[1] = {
lootCount = { min = 1, max = 2 },
items = {
{ item = 'rolex', chance = 15, min = 1, max = 1, xp = 8 },
{ item = 'phone', chance = 20, min = 1, max = 1, xp = 6 },
},
},
[2] = {
lootCount = { min = 2, max = 3 },
items = {
{ item = 'rolex', chance = 18, min = 1, max = 2, xp = 8 },
{ item = 'phone', chance = 15, min = 1, max = 1, xp = 6 },
{ item = 'goldchain', chance = 12, min = 1, max = 1, xp = 10 },
},
},
[3] = {
lootCount = { min = 2, max = 4 },
items = {
{ item = 'rolex', chance = 20, min = 1, max = 3, xp = 8 },
{ item = 'phone', chance = 15, min = 1, max = 2, xp = 6 },
{ item = 'goldchain', chance = 15, min = 1, max = 2, xp = 10 },
{ item = 'laptop', chance = 10, min = 1, max = 1, xp = 12 },
},
},
},
high = {
cash = { min = 25, max = 65 },
[1] = {
lootCount = { min = 1, max = 2 },
items = {
{ item = 'diamond_ring', chance = 12, min = 1, max = 1, xp = 15 },
{ item = 'goldchain', chance = 18, min = 1, max = 1, xp = 10 },
},
},
[2] = {
lootCount = { min = 1, max = 3 },
items = {
{ item = 'diamond_ring', chance = 15, min = 1, max = 1, xp = 15 },
{ item = 'goldchain', chance = 15, min = 1, max = 2, xp = 10 },
{ item = '10kgoldchain', chance = 10, min = 1, max = 1, xp = 20 },
},
},
[3] = {
lootCount = { min = 2, max = 4 },
items = {
{ item = 'diamond_ring', chance = 18, min = 1, max = 2, xp = 15 },
{ item = 'goldchain', chance = 15, min = 2, max = 3, xp = 10 },
{ item = '10kgoldchain', chance = 12, min = 1, max = 2, xp = 20 },
{ item = 'diamond', chance = 8, min = 1, max = 1, xp = 25 },
},
},
},
},
-- Zones grouped by tier. Keys are GTA's `GetNameOfZone()` short codes —
-- they have to match the engine return values exactly. Anything *not*
-- listed defaults to the `low` tier, so leaving a zone off gives it
-- the cheapest loot pool rather than no loot at all.
--
-- Re-tiering a zone is a one-line move between arrays.
ZoneTiers = {
high = {
'ROCKF', -- Rockford Hills
'CHIL', -- Vinewood Hills
'HAWICK', -- Hawick
'PBLUFF', -- Pacific Bluffs
'TONGVAH', -- Tongva Hills
'RGLEN', -- Richman Glen
'RICHM', -- Richman
'HORS', -- Vinewood Racetrack
'STAD', -- Maze Bank Arena
'MOVIE', -- Richards Majestic
'BHAMCA', -- Banham Canyon
'GOLF', -- GWC and Golfing Society
},
medium = {
'AIRP', -- Los Santos International Airport
'BEACH', -- Vespucci Beach
'DELBE', -- Del Perro Beach
'DELPE', -- Del Perro
'MIRR', -- Mirror Park
'MORN', -- Morningwood
'ALTA', -- Alta
'BURTON', -- Burton
'PBOX', -- Pillbox Hill
'LEGSQU', -- Legion Square
'KOREAT', -- Little Seoul
'VINE', -- Vinewood
'WVINE', -- West Vinewood
'DTVINE', -- Downtown Vinewood
'EAST_V', -- East Vinewood
'DOWNT', -- Downtown
'TEXTI', -- Textile City
'HARMO', -- Harmony
},
-- Everything else (Davis, Strawberry, Chamberlain, El Burro, Stab
-- City, Sandy Shores, Grapeseed, Paleto, the wilds, etc.) falls
-- through to the `low` tier automatically. Promote a zone by
-- adding its short code to one of the lists above.
},
}