Wiki / DDS1 / Datamined Content

Hidden Mechanics & Formulas

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.

priceRatio = salePrice / expectedPrice
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
Worked example. Your reputation is 60. A non–addicted regular client has 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.

adjustedExpectation = Clamp(expectedQuality + 0.2, 0.4, 0.9)
rawSatisfaction = (endProductQuality / adjustedExpectation) - 0.95
satisfactionDelta = Clamp(rawSatisfaction × 0.3, -0.5, +0.25)
generalSatisfaction = Clamp(current + satisfactionDelta, -1.0, +3.0)
Worked example. Client expects 0.60 quality (Downtown area). 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%.

minODToxicity = 3.9
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 )
Worked example. Cocaine has toxicity around 6.0 (from 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.

if drugReceived.addictiveness > 1.0 AND longNewDrugsTaskID active:
  addictChance = Clamp( ((addictiveness - 0.5) / 13.0) / 3.0, 0.01, 0.12 )
  if RandomBoolWithWeight(addictChance):
    clientsDrugAddictedTo[ClientID] = drugIndex
Worked example. Heroin has addictiveness ~5.0. Per sale: ((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.

rep_change = (productQuality - 0.5) × 0.35
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.

contentRatio = proportion of expected drug in received product
strengthRatio = drugReceived.strength / drugExpected.strength
clampedStrength = Clamp(strengthRatio, 0.0, 1.5)

endProductQuality = contentRatio + (contentRatio × 0.2 × clampedStrength)
Worked example. 50% cocaine + 50% strong filler (filler has higher strength than cocaine). 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.

XP_threshold(L) = L × levelExpFirstLevel × (1 + L × levelExpRaiseRatio)

# 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():

raw = drugReceivedQuantity × 10.0
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 ExpoEvent entries (arrests, raids, tasers, etc. from ExpoEventsDatabase)
  • 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
# Events / sales older than 200 timecodes are pruned.
# 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():

scaled = amount × areaRespectMultiplier # per–area, e.g. SLUMS = 1.50
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:

EddieLimit($) = EDDIE-LIMIT-BASE + EDDIE-LIMIT-PER-LEVEL × playerLevel
        = 150.0 + 45.0 × playerLevel
Quick reference. L1 = $195, L5 = $375, L10 = $600, L15 = $825, L20 = $1,050, L25 = $1,275, L30 = $1,500. 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:

orderLimit = Min(playerLevel × 2 + 2, 30)

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:

levelReduction = dealerLevel × 25.0
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:

policeMult: Easy=1.3, Normal=1.6, Hard/HC=2.1
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:

totalPercDrug = sum of proportions of known drugs in the mix (excluding filler)
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
minODToxicity3.9Below: zero OD chance
highToxLevel12.0At/above: flat 25% OD
highToxOdPercent0.25Flat 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 expectationClamp(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.35Range −0.175 to +0.175
Sale exposure baseClamp(50 + qty×10, 60, 200)Per–sale heat contribution
Sample area respectClamp(qty × 40 × drugPct, 50, 250)Sample client area exposure
Night multiplier1.2×9 PM–6 AM sale exposure
XP clamp range[30, 800]Pre–base XP per sale (qty×10)
Eddie limit base$150.0EDDIE-LIMIT-BASE
Eddie limit per level+$45.0/levelEDDIE-LIMIT-PER-LEVEL
Dealer XP/gram14.0DEALER-XP-PER-GRAM
Respect drop / second0.04RESPECT-DROP-PS
Order interval (client)360–600 secCLIENT-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.

Was this article helpful?
🖨 Print
Created by Mifsopo Last edited by mifsopo 2 revisions Published February 17, 2026

💬 Discussion