This page is a hands–on reference for the actual math that drives DDS1's hidden systems — client pricing, satisfaction, overdose, addiction, reputation, quality, exposition (heat), Eddie's supply cap, and XP. Every formula here was extracted from the game's decompiled Blueprint Kismet bytecode. No invented constants. No tiers. No "0–100 DEA scale". Just the equations the runtime evaluates, with worked examples.
Datamined & Verified:
All formulas were extracted via the DataTablePatcher decompile command, which feeds CUE4Parse–extracted
.uasset Blueprint exports through UAssetAPI's KismetSerializer to produce JSON instruction lists.
Source classes: baseNPC_C, salesManager_C, statisticsManager_C,
policeManager_C, BlueprintHelpers_C.
Replaces older page: This page replaces an earlier Hidden Mechanics & Formulas article that was fabricated end–to–end — invented a 0–100 DEA heat scale, fake satisfaction tiers ("Loyal / Satisfied / Unhappy / Lost"), an addiction purchase–counter, gang territory–control percentages, and quality formulas that contradicted the bytecode. None of those mechanics exist in the actual game.
1. Sale Price Acceptance
Source: salesManager_C.checkClientInterested().
A client rejects a price if priceFactor exceeds their reputation–based threshold.
priceFactor = (priceRatio - 1.0) / priceMultiplierDef
Dealer: repThreshold = rep/100 + 0.075
Normal (not hooked): repThreshold = rep/100 + 0.20
Addicted to drug: repThreshold = rep/100 + 0.05
Fallback: repThreshold = rep/100 + 0.15
priceTooHigh = (priceFactor > repThreshold)
Non–dealer/non–addict also rolls a 70% interest gate even when price is OK
repThreshold = 60/100 + 0.20 = 0.80. You list cocaine at $90 when expected is $45.
priceRatio = 2.0, so before the divisor priceFactor is +1.0/priceMultiplierDef.
Even if priceMultiplierDef is 1.0 (so priceFactor = 1.0), 1.0 > 0.80 — the client refuses.
Drop the price to $75: priceRatio = 1.67, priceFactor = 0.67, which is < 0.80 — the client
might accept (still subject to the 70% interest gate).
2. Client Satisfaction Delta
Source: baseNPC_C.processReceivedDrugs().
Each sale produces a delta that is added to the running generalSatisfaction for that client. The asymmetric clamp
means it is twice as easy to lose satisfaction as it is to gain it.
rawSatisfaction = (endProductQuality / adjustedExpectation) - 0.95
satisfactionDelta = Clamp(rawSatisfaction × 0.3, -0.5, +0.25)
generalSatisfaction = Clamp(current + satisfactionDelta, -1.0, +3.0)
adjustedExpectation = 0.80 (clamped). You deliver
endProductQuality = 0.90 (pure cocaine with strength bonus).
rawSat = 0.90/0.80 - 0.95 = 1.125 - 0.95 = 0.175,
delta = 0.175 × 0.3 = +0.0525. The client gains +0.05 satisfaction.
If instead you sold them 0.40 quality product:
rawSat = 0.40/0.80 - 0.95 = -0.45, delta = -0.135 — loses 0.14 satisfaction. Bad sales hurt
much more than good ones help.
3. Overdose Chance (Two–Branch)
Source: baseNPC_C.processReceivedDrugs().
Below 3.9 toxicity nothing happens. Between 3.9 and 12.0 it scales smoothly. At 12.0 or above the chance snaps to a flat 25%.
highToxLevel = 12.0
if drugReceived.toxicity ≤ 3.9:
ODchance = 0 # zero, no roll
elif drugReceived.toxicity ≥ 12.0:
ODchance = 0.25 # flat 25%
else: # 3.9 < tox < 12.0
ODchance = Clamp( ((tox - 3.9) / 3.9) / 20.0, 0.001, 0.08 )
DrugProperties struct). Pure cocaine:
((6.0-3.9)/3.9)/20 = (2.1/3.9)/20 = 0.027 = 2.7% OD chance per sale.
Mix it 50/50 with toxic filler that brings the product up to toxicity 13.0 — you now hit the high–tox branch:
flat 25% OD per sale, no matter how much higher the toxicity goes.
The bytecode also defines
lowToxOdPercent = 0.1 but never uses it — dead code from an earlier design.
4. Addiction Probability Per Sale
Source: baseNPC_C.processReceivedDrugs().
Each sale rolls an independent probability based on the drug's addictiveness. There is no counter, no streak, no purchase
threshold. The roll is gated by the longNewDrugsTaskID quest being active.
addictChance = Clamp( ((addictiveness - 0.5) / 13.0) / 3.0, 0.01, 0.12 )
if RandomBoolWithWeight(addictChance):
clientsDrugAddictedTo[ClientID] = drugIndex
((5.0 - 0.5) / 13) / 3 = (4.5/13)/3 = 0.346/3 = 0.115 ≈ 11.5% chance per sale.
That's clamped within [0.01, 0.12], so heroin caps near 12% per sale. A weak filler with addictiveness 1.5
yields ((1.5-0.5)/13)/3 = 0.0256 ≈ 2.6% per sale.
Once hooked, the client's price tolerance threshold shifts from +0.20 to +0.05 — they accept
higher markups, and their order quantities are multiplied by 1.25.
5. Reputation Change Per Sale
Source: baseNPC_C.saleReputationUpdate(productQuality).
Reputation moves a tiny amount per sale — max +0.175, min −0.175. Pure product (quality 1.0) gives the maximum positive
nudge.
statisticsManager.modifyReputation(rep_change)
# Difficulty scaling in modifyReputation:
Easy: rep += amount × 1.12 # +12% bonus, NO CLAMP
Normal/Hard/Hardcore: rep = Clamp(rep + amount, -range, +range)
Reputation also decays over time toward zero at reputationZeroingPS per second (both positive and negative).
On Easy the per–sale change is unclamped — so your reputation can exceed the
normal range. On Normal+ it is clamped to the difficulty's reputation window.
6. Product Quality Formula
Source: baseNPC_C.processReceivedDrugs().
The quality the client perceives is the proportion of the expected drug in the received mix, plus a bonus of up to +30% if the mix
is stronger than expected.
strengthRatio = drugReceived.strength / drugExpected.strength
clampedStrength = Clamp(strengthRatio, 0.0, 1.5)
endProductQuality = contentRatio + (contentRatio × 0.2 × clampedStrength)
contentRatio = 0.5.
strengthRatio ends up > 1.0 because the filler dragged total strength up
(computed by the weighted–sum in MixToDrugData). If strengthRatio = 1.5 (clamp ceiling):
endProductQuality = 0.5 + (0.5 × 0.2 × 1.5) = 0.5 + 0.15 = 0.65. The client perceives 65% quality
rather than 50%, because the mix punches above its weight.
With no strength bonus (filler same strength):
endProductQuality = 0.5 + (0.5 × 0.2 × 1.0) = 0.60.
Even neutral filler still produces +0.10 quality because strengthRatio = 1.0 still triggers the bonus term.
7. XP Threshold Curve (Quadratic)
Source: statisticsManager_C.calcExpForLevelUp().
The cost to reach level L is quadratic in L — each level needs roughly twice the XP of the previous one at low levels.
# Expanded:
XP_threshold(L) = levelExpFirstLevel × L + levelExpFirstLevel × levelExpRaiseRatio × L²
Quick Learner bonus:
actual_xp = amount × (1.0 + (skillLevel / skillMax) / 2.5) — max +40% XP at 5/5 Quick Learner.
Quick Learner rank 3+ (skill ≥ 50) also grants +2 bonus skill points per level.
Night tasks (10 PM–6 AM) award +15% bonus XP.
Per–sale XP from baseNPC_C.calcSaleExp():
clamped = Clamp(raw, 30.0, 800.0)
Client / sample: XP = 100.0 + clamped # 130–900 XP per sale
Dealer cash pickup: XP = (100.0 + clamped) / 3.0 # 43–300 XP, 3× less
XP is based on quantity only — purity is irrelevant for XP. A 5g pure cocaine sale and a 5g 97%–filler sale both award 210 XP to the player.
8. Exposition (Real Heat Math)
Source: statisticsManager_C.UpdateExpositionLevel().
Exposition is the weighted average of:
- Recent
ExpoEvententries (arrests, raids, tasers, etc. fromExpoEventsDatabase) - Recent sale exposure (from
calcSaleExposure():Clamp(50 + qty×10, 60, 200), ×1.2 at night) - A baseline inactivity term weighted by
EXPO-BASE-INACTIVITY-MEDIANE = 6.00
# Each event contributes (ExpoEventValue × MedianePoints) to the numerator,
# MedianePoints to the denominator (weighted average).
expoFactorLevel = Clamp(weightedAvg, expoFactorMin, expoFactorMax) × ExpoFactorMultiplier
# Difficulty params:
Easy: min=35, mult=0.70, DEA@600
Normal: min=50, mult=1.00, DEA@500
Hard/HC: min=80, mult=1.20, DEA@400
Night attenuation: sales count for 70% (EXPO-NIGHT-SALE-MULTIPLIER) and events count for 60%
(EXPO-NIGHT-EVENT-MULTIPLIER) of normal weight during night hours (9 PM–6 AM).
Per–area exposure (territory respect) is separate. From saleAreaManager_C.addAreaExposure():
boosted = scaled × (1.0 + sprayRespectBoost)
saleAreaExposure[i] = Clamp(current + boosted, 0.0, exposureMaxLevel)
buffer = Clamp(amount × 0.3, 20, 80) # shields exposure from decay first
# Per-second decay (dropExposure):
respectDropBoost = Clamp(saleAreaRespectDropBoost, 0.0, 0.7) # max 70%
dropAmount = Delta × 0.04 × exposureDropMultiplier × (current/max) × (1 - respectDropBoost)
# RESPECT-DROP-PS = 0.04 per second
9. Eddie Supply Limit
Source: two BalanceFlags entries read via
GetBalanceFlag(). Eddie's per–order cap scales linearly with player level:
= 150.0 + 45.0 × playerLevel
EddieLimitBoosters tier multipliers (2×, 4×, 6×, 12×, 15×, 20× at levels 5/10/15/20/25/35)
are separate, applied to other limit values — not to this base supply formula.
10. Player Order Limit
Source: mainComputer_C.GetPlayerOrderLimit().
The number of unit orders the player can have queued at once:
L1 = 4, L7 = 16, L14+ = hard cap 30. Each completed gang order also raises the player order limit by +$2,000 (separate from the unit cap above).
11. Dealer Arrest Chance
Source: salesManager_C.GetClientArrestChance().
Your dealers' arrest chance scales with global exposition and is reduced as the dealer levels up:
levelFactor = Clamp(dealerLevel / 2.0, 1.0, 3.5)
rawChance = MapRangeClamped(expoLevel - levelReduction, 200.0, 1000.0, 0.005, 0.11)
arrestChance = rawChance / levelFactor
L0 dealer: 0.5–11% arrest chance depending on expo. L7+ dealer: divided by 3.5, effectively ~0.14–3.1%. Below expo 200,
chance bottoms out at the minimum. Bail = daysRemaining × $300, max $1,200.
12. Police Patrol Spawning
Source: policeManager_C.checkWorldStatus().
The patrol count formula:
rawPatrols = maxPatrolsTotal × (expoFactorLevel / expoFactorMax) × policeMult
patrols = Clamp(Round(rawPatrols), minPatrols, maxPatrolsTotal)
# Day/Night minimums:
Easy: day=5, night=7 (8PM–5AM)
Normal: day=6, night=8
Hard/HC: day=7, night=10
# Dog patrols: expoFactorLevel > 500 AND playerLevel > 7, 30% spawn chance per patrol
# Early player (L ≤ 5): clamped to 2–4 patrols
# Before second map: halved, clamped 3–6
13. Sample Client Area Exposure
Source: baseNPC_C.processReceivedDrugs() (sample client branch).
Samples are a real sale through the normal pipeline (just free) — they DO award XP and reputation. They additionally add
area respect:
areaRespect = Clamp(drugReceivedQuantity × 40 × totalPercDrug, 50.0, 250.0)
saleAreaManager.addAreaExposure(samplePerson.sampleAreaAffected, areaRespect)
Samples also fire CLIENT-SAMPLE event into the global exposition system (value 500, weight 1.0), so they add
police heat too. 1–gram pure samples are highly XP–efficient (182 XP/g) but mixed samples are strictly worse for respect
(capped at the 50 floor).
Summary: All Constants In One Place
| Constant | Value | Where used |
|---|---|---|
| minODToxicity | 3.9 | Below: zero OD chance |
| highToxLevel | 12.0 | At/above: flat 25% OD |
| highToxOdPercent | 0.25 | Flat OD rate above 12.0 tox |
| Satisfaction delta clamp | [−0.5, +0.25] | Per–sale change |
| General satisfaction clamp | [−1.0, +3.0] | Running total per client |
| Adjusted expectation | Clamp(expected+0.2, 0.4, 0.9) | Quality benchmark for satisfaction |
| Quality strength bonus | +0–30% (× clampedRatio) | contentRatio × 0.2 × Clamp(strRatio, 0, 1.5) |
| Addiction chance range | [0.01, 0.12] | 1–12% per sale |
| Reputation per sale | (quality − 0.5) × 0.35 | Range −0.175 to +0.175 |
| Sale exposure base | Clamp(50 + qty×10, 60, 200) | Per–sale heat contribution |
| Sample area respect | Clamp(qty × 40 × drugPct, 50, 250) | Sample client area exposure |
| Night multiplier | 1.2× | 9 PM–6 AM sale exposure |
| XP clamp range | [30, 800] | Pre–base XP per sale (qty×10) |
| Eddie limit base | $150.0 | EDDIE-LIMIT-BASE |
| Eddie limit per level | +$45.0/level | EDDIE-LIMIT-PER-LEVEL |
| Dealer XP/gram | 14.0 | DEALER-XP-PER-GRAM |
| Respect drop / second | 0.04 | RESPECT-DROP-PS |
| Order interval (client) | 360–600 sec | CLIENT-ORDER-INTERVAL-MIN/MAX |
Decompiled formulas verified against baseNPC_C, salesManager_C, statisticsManager_C,
policeManager_C, gangManager_C, BlueprintHelpers_C, and mainComputer_C in the
DDS1 game pak. Last updated May 2026.
💬 Discussion