feat(automation): add automated raw material suppliers across all drug tiers
This commit is contained in:
parent
9ea0174d86
commit
10ddbb7049
3 changed files with 124 additions and 20 deletions
|
|
@ -1,18 +1,19 @@
|
||||||
import math
|
import math
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
# Drug Catalog mirroring config.js
|
||||||
# Drug Catalog mirroring config.js
|
# Drug Catalog mirroring config.js
|
||||||
DRUG_CONFIGS = {
|
DRUG_CONFIGS = {
|
||||||
'weed': {'rawCost': 10, 'sellPrice': 16, 'produceRate': 1.0, 'sellRate': 1.0, 'workerCost': 100, 'dealerCost': 150, 'unlockCost': 0},
|
'weed': {'rawCost': 10, 'sellPrice': 16, 'produceRate': 1.0, 'sellRate': 1.0, 'supplyRate': 1.0, 'supplierCost': 75, 'workerCost': 100, 'dealerCost': 150, 'unlockCost': 0},
|
||||||
'shrooms': {'rawCost': 35, 'sellPrice': 65, 'produceRate': 0.8, 'sellRate': 0.8, 'workerCost': 450, 'dealerCost': 650, 'unlockCost': 500},
|
'shrooms': {'rawCost': 35, 'sellPrice': 65, 'produceRate': 0.8, 'sellRate': 0.8, 'supplyRate': 0.8, 'supplierCost': 300, 'workerCost': 450, 'dealerCost': 650, 'unlockCost': 500},
|
||||||
'adderall': {'rawCost': 120, 'sellPrice': 240, 'produceRate': 0.6, 'sellRate': 0.6, 'workerCost': 2000, 'dealerCost': 3000, 'unlockCost': 2500},
|
'adderall': {'rawCost': 120, 'sellPrice': 240, 'produceRate': 0.6, 'sellRate': 0.6, 'supplyRate': 0.6, 'supplierCost': 1500, 'workerCost': 2000, 'dealerCost': 3000, 'unlockCost': 2500},
|
||||||
'meth': {'rawCost': 400, 'sellPrice': 950, 'produceRate': 0.5, 'sellRate': 0.5, 'workerCost': 8000, 'dealerCost': 12000, 'unlockCost': 10000},
|
'meth': {'rawCost': 400, 'sellPrice': 950, 'produceRate': 0.5, 'sellRate': 0.5, 'supplyRate': 0.5, 'supplierCost': 6000, 'workerCost': 8000, 'dealerCost': 12000, 'unlockCost': 10000},
|
||||||
'mdma': {'rawCost': 1200, 'sellPrice': 3200, 'produceRate': 0.4, 'sellRate': 0.4, 'workerCost': 28000, 'dealerCost': 40000, 'unlockCost': 35000},
|
'mdma': {'rawCost': 1200, 'sellPrice': 3200, 'produceRate': 0.4, 'sellRate': 0.4, 'supplyRate': 0.4, 'supplierCost': 20000, 'workerCost': 28000, 'dealerCost': 40000, 'unlockCost': 35000},
|
||||||
'ketamine': {'rawCost': 3800, 'sellPrice': 11000, 'produceRate': 0.35, 'sellRate': 0.35, 'workerCost': 95000, 'dealerCost': 140000, 'unlockCost': 120000},
|
'ketamine': {'rawCost': 3800, 'sellPrice': 11000, 'produceRate': 0.35, 'sellRate': 0.35, 'supplyRate': 0.35, 'supplierCost': 75000, 'workerCost': 95000, 'dealerCost': 140000, 'unlockCost': 120000},
|
||||||
'cocaine': {'rawCost': 12000, 'sellPrice': 38000, 'produceRate': 0.3, 'sellRate': 0.3, 'workerCost': 320000, 'dealerCost': 480000, 'unlockCost': 400000},
|
'cocaine': {'rawCost': 12000, 'sellPrice': 38000, 'produceRate': 0.3, 'sellRate': 0.3, 'supplyRate': 0.3, 'supplierCost': 250000, 'workerCost': 320000, 'dealerCost': 480000, 'unlockCost': 400000},
|
||||||
'crack': {'rawCost': 35000, 'sellPrice': 115000, 'produceRate': 0.25, 'sellRate': 0.25, 'workerCost': 900000, 'dealerCost': 1400000, 'unlockCost': 1200000},
|
'crack': {'rawCost': 35000, 'sellPrice': 115000, 'produceRate': 0.25, 'sellRate': 0.25, 'supplyRate': 0.25, 'supplierCost': 700000, 'workerCost': 900000, 'dealerCost': 1400000, 'unlockCost': 1200000},
|
||||||
'heroin': {'rawCost': 110000, 'sellPrice': 420000, 'produceRate': 0.2, 'sellRate': 0.2, 'workerCost': 3500000, 'dealerCost': 5500000, 'unlockCost': 4500000},
|
'heroin': {'rawCost': 110000, 'sellPrice': 420000, 'produceRate': 0.2, 'sellRate': 0.2, 'supplyRate': 0.2, 'supplierCost': 2800000, 'workerCost': 3500000, 'dealerCost': 5500000, 'unlockCost': 4500000},
|
||||||
'fentanyl': {'rawCost': 450000, 'sellPrice': 2100000, 'produceRate': 0.15, 'sellRate': 0.15, 'workerCost': 15000000, 'dealerCost': 24000000, 'unlockCost': 20000000}
|
'fentanyl': {'rawCost': 450000, 'sellPrice': 2100000, 'produceRate': 0.15, 'sellRate': 0.15, 'supplyRate': 0.15, 'supplierCost': 12000000, 'workerCost': 15000000, 'dealerCost': 24000000, 'unlockCost': 20000000}
|
||||||
}
|
}
|
||||||
|
|
||||||
SYNTHESIS_RECIPES = {
|
SYNTHESIS_RECIPES = {
|
||||||
|
|
@ -50,6 +51,7 @@ def get_initial_state() -> dict:
|
||||||
'unlocked': (drug_id == 'weed'),
|
'unlocked': (drug_id == 'weed'),
|
||||||
'raw': 0.0,
|
'raw': 0.0,
|
||||||
'product': 0.0,
|
'product': 0.0,
|
||||||
|
'suppliers': 0,
|
||||||
'workers': 0,
|
'workers': 0,
|
||||||
'dealers': 0
|
'dealers': 0
|
||||||
}
|
}
|
||||||
|
|
@ -93,7 +95,13 @@ def process_offline_and_ticks(state: dict) -> dict:
|
||||||
if not cfg or not data.get('unlocked'):
|
if not cfg or not data.get('unlocked'):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Workers production
|
# Suppliers automatic raw cultivation / procurement
|
||||||
|
suppliers = data.get('suppliers', 0)
|
||||||
|
if suppliers > 0:
|
||||||
|
supply_speed = suppliers * cfg.get('supplyRate', 1.0) * prod_m
|
||||||
|
data['raw'] = data.get('raw', 0.0) + (supply_speed * delta)
|
||||||
|
|
||||||
|
# Workers production (Refining raw -> product)
|
||||||
workers = data.get('workers', 0)
|
workers = data.get('workers', 0)
|
||||||
raw = data.get('raw', 0.0)
|
raw = data.get('raw', 0.0)
|
||||||
if workers > 0 and raw > 0:
|
if workers > 0 and raw > 0:
|
||||||
|
|
@ -102,7 +110,7 @@ def process_offline_and_ticks(state: dict) -> dict:
|
||||||
data['raw'] = max(0.0, raw - actual_prod)
|
data['raw'] = max(0.0, raw - actual_prod)
|
||||||
data['product'] = data.get('product', 0.0) + actual_prod
|
data['product'] = data.get('product', 0.0) + actual_prod
|
||||||
|
|
||||||
# Dealers selling
|
# Dealers selling (Product -> Cash)
|
||||||
dealers = data.get('dealers', 0)
|
dealers = data.get('dealers', 0)
|
||||||
product = data.get('product', 0.0)
|
product = data.get('product', 0.0)
|
||||||
if dealers > 0 and product > 0:
|
if dealers > 0 and product > 0:
|
||||||
|
|
@ -177,6 +185,14 @@ def apply_actions(state: dict, actions: list) -> dict:
|
||||||
state['totalEarned'] += profit
|
state['totalEarned'] += profit
|
||||||
state['heat'] = min(100.0, state.get('heat', 0.0) + (0.8 * actual))
|
state['heat'] = min(100.0, state.get('heat', 0.0) + (0.8 * actual))
|
||||||
|
|
||||||
|
elif action_type == 'hire_supplier' and drug_id in DRUG_CONFIGS:
|
||||||
|
cfg = DRUG_CONFIGS[drug_id]
|
||||||
|
count = state['drugs'][drug_id].get('suppliers', 0)
|
||||||
|
cost = math.floor(cfg.get('supplierCost', 75) * math.pow(1.15, count))
|
||||||
|
if state['cash'] >= cost:
|
||||||
|
state['cash'] -= cost
|
||||||
|
state['drugs'][drug_id]['suppliers'] = count + 1
|
||||||
|
|
||||||
elif action_type == 'hire_worker' and drug_id in DRUG_CONFIGS:
|
elif action_type == 'hire_worker' and drug_id in DRUG_CONFIGS:
|
||||||
cfg = DRUG_CONFIGS[drug_id]
|
cfg = DRUG_CONFIGS[drug_id]
|
||||||
count = state['drugs'][drug_id].get('workers', 0)
|
count = state['drugs'][drug_id].get('workers', 0)
|
||||||
|
|
@ -244,6 +260,7 @@ def apply_actions(state: dict, actions: list) -> dict:
|
||||||
d_data['unlocked'] = (d_id == 'weed')
|
d_data['unlocked'] = (d_id == 'weed')
|
||||||
d_data['raw'] = 0.0
|
d_data['raw'] = 0.0
|
||||||
d_data['product'] = 0.0
|
d_data['product'] = 0.0
|
||||||
|
d_data['suppliers'] = 0
|
||||||
d_data['workers'] = 0
|
d_data['workers'] = 0
|
||||||
d_data['dealers'] = 0
|
d_data['dealers'] = 0
|
||||||
|
|
||||||
|
|
@ -259,6 +276,7 @@ def sanitize_state(state: dict) -> dict:
|
||||||
for d_id, data in state.get('drugs', {}).items():
|
for d_id, data in state.get('drugs', {}).items():
|
||||||
data['raw'] = clean_round(data.get('raw', 0.0))
|
data['raw'] = clean_round(data.get('raw', 0.0))
|
||||||
data['product'] = clean_round(data.get('product', 0.0))
|
data['product'] = clean_round(data.get('product', 0.0))
|
||||||
|
data['suppliers'] = int(data.get('suppliers', 0))
|
||||||
data['workers'] = int(data.get('workers', 0))
|
data['workers'] = int(data.get('workers', 0))
|
||||||
data['dealers'] = int(data.get('dealers', 0))
|
data['dealers'] = int(data.get('dealers', 0))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,9 @@ const DRUG_CATALOG = [
|
||||||
rawCost: 10,
|
rawCost: 10,
|
||||||
sellPrice: 16,
|
sellPrice: 16,
|
||||||
unlockCost: 0,
|
unlockCost: 0,
|
||||||
|
supplierName: 'Seed Courier',
|
||||||
|
supplierCost: 75,
|
||||||
|
supplyRate: 1.0,
|
||||||
workerName: 'Grower',
|
workerName: 'Grower',
|
||||||
dealerName: 'Corner Pusher',
|
dealerName: 'Corner Pusher',
|
||||||
workerCost: 100,
|
workerCost: 100,
|
||||||
|
|
@ -30,6 +33,9 @@ const DRUG_CATALOG = [
|
||||||
rawCost: 35,
|
rawCost: 35,
|
||||||
sellPrice: 65,
|
sellPrice: 65,
|
||||||
unlockCost: 500,
|
unlockCost: 500,
|
||||||
|
supplierName: 'Spore Forager',
|
||||||
|
supplierCost: 300,
|
||||||
|
supplyRate: 0.8,
|
||||||
workerName: 'Mycologist',
|
workerName: 'Mycologist',
|
||||||
dealerName: 'Festival Plug',
|
dealerName: 'Festival Plug',
|
||||||
workerCost: 450,
|
workerCost: 450,
|
||||||
|
|
@ -49,6 +55,9 @@ const DRUG_CATALOG = [
|
||||||
rawCost: 120,
|
rawCost: 120,
|
||||||
sellPrice: 240,
|
sellPrice: 240,
|
||||||
unlockCost: 2500,
|
unlockCost: 2500,
|
||||||
|
supplierName: 'Pharmacy Diverter',
|
||||||
|
supplierCost: 1500,
|
||||||
|
supplyRate: 0.6,
|
||||||
workerName: 'Pharma Tech',
|
workerName: 'Pharma Tech',
|
||||||
dealerName: 'Campus Runner',
|
dealerName: 'Campus Runner',
|
||||||
workerCost: 2000,
|
workerCost: 2000,
|
||||||
|
|
@ -68,6 +77,9 @@ const DRUG_CATALOG = [
|
||||||
rawCost: 400,
|
rawCost: 400,
|
||||||
sellPrice: 950,
|
sellPrice: 950,
|
||||||
unlockCost: 10000,
|
unlockCost: 10000,
|
||||||
|
supplierName: 'Chemical Smuggler',
|
||||||
|
supplierCost: 6000,
|
||||||
|
supplyRate: 0.5,
|
||||||
workerName: 'Lab Cook',
|
workerName: 'Lab Cook',
|
||||||
dealerName: 'Trailer Boss',
|
dealerName: 'Trailer Boss',
|
||||||
workerCost: 8000,
|
workerCost: 8000,
|
||||||
|
|
@ -87,6 +99,9 @@ const DRUG_CATALOG = [
|
||||||
rawCost: 1200,
|
rawCost: 1200,
|
||||||
sellPrice: 3200,
|
sellPrice: 3200,
|
||||||
unlockCost: 35000,
|
unlockCost: 35000,
|
||||||
|
supplierName: 'Safrole Importer',
|
||||||
|
supplierCost: 20000,
|
||||||
|
supplyRate: 0.4,
|
||||||
workerName: 'Rave Chemist',
|
workerName: 'Rave Chemist',
|
||||||
dealerName: 'Club Promoter',
|
dealerName: 'Club Promoter',
|
||||||
workerCost: 28000,
|
workerCost: 28000,
|
||||||
|
|
@ -106,6 +121,9 @@ const DRUG_CATALOG = [
|
||||||
rawCost: 3800,
|
rawCost: 3800,
|
||||||
sellPrice: 11000,
|
sellPrice: 11000,
|
||||||
unlockCost: 120000,
|
unlockCost: 120000,
|
||||||
|
supplierName: 'Vet Clinic Insider',
|
||||||
|
supplierCost: 75000,
|
||||||
|
supplyRate: 0.35,
|
||||||
workerName: 'Vet Contact',
|
workerName: 'Vet Contact',
|
||||||
dealerName: 'Afterparty Plug',
|
dealerName: 'Afterparty Plug',
|
||||||
workerCost: 95000,
|
workerCost: 95000,
|
||||||
|
|
@ -125,6 +143,9 @@ const DRUG_CATALOG = [
|
||||||
rawCost: 12000,
|
rawCost: 12000,
|
||||||
sellPrice: 38000,
|
sellPrice: 38000,
|
||||||
unlockCost: 400000,
|
unlockCost: 400000,
|
||||||
|
supplierName: 'Jungle Smuggler',
|
||||||
|
supplierCost: 250000,
|
||||||
|
supplyRate: 0.3,
|
||||||
workerName: 'Cartel Chemist',
|
workerName: 'Cartel Chemist',
|
||||||
dealerName: 'VIP Broker',
|
dealerName: 'VIP Broker',
|
||||||
workerCost: 320000,
|
workerCost: 320000,
|
||||||
|
|
@ -144,6 +165,9 @@ const DRUG_CATALOG = [
|
||||||
rawCost: 35000,
|
rawCost: 35000,
|
||||||
sellPrice: 115000,
|
sellPrice: 115000,
|
||||||
unlockCost: 1200000,
|
unlockCost: 1200000,
|
||||||
|
supplierName: 'Base Sourcing Crew',
|
||||||
|
supplierCost: 700000,
|
||||||
|
supplyRate: 0.25,
|
||||||
workerName: 'Trap Master',
|
workerName: 'Trap Master',
|
||||||
dealerName: 'Block Captain',
|
dealerName: 'Block Captain',
|
||||||
workerCost: 900000,
|
workerCost: 900000,
|
||||||
|
|
@ -163,6 +187,9 @@ const DRUG_CATALOG = [
|
||||||
rawCost: 110000,
|
rawCost: 110000,
|
||||||
sellPrice: 420000,
|
sellPrice: 420000,
|
||||||
unlockCost: 4500000,
|
unlockCost: 4500000,
|
||||||
|
supplierName: 'Poppy Harvester',
|
||||||
|
supplierCost: 2800000,
|
||||||
|
supplyRate: 0.2,
|
||||||
workerName: 'Poppy Refiner',
|
workerName: 'Poppy Refiner',
|
||||||
dealerName: 'Network Distributor',
|
dealerName: 'Network Distributor',
|
||||||
workerCost: 3500000,
|
workerCost: 3500000,
|
||||||
|
|
@ -182,6 +209,9 @@ const DRUG_CATALOG = [
|
||||||
rawCost: 450000,
|
rawCost: 450000,
|
||||||
sellPrice: 2100000,
|
sellPrice: 2100000,
|
||||||
unlockCost: 20000000,
|
unlockCost: 20000000,
|
||||||
|
supplierName: 'Cartel Procurement Agent',
|
||||||
|
supplierCost: 12000000,
|
||||||
|
supplyRate: 0.15,
|
||||||
workerName: 'Hazmat Synthesizer',
|
workerName: 'Hazmat Synthesizer',
|
||||||
dealerName: 'Ghost Syndicate',
|
dealerName: 'Ghost Syndicate',
|
||||||
workerCost: 15000000,
|
workerCost: 15000000,
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ DRUG_CATALOG.forEach(d => {
|
||||||
unlocked: d.unlockedDefault,
|
unlocked: d.unlockedDefault,
|
||||||
raw: 0.0,
|
raw: 0.0,
|
||||||
product: 0.0,
|
product: 0.0,
|
||||||
|
suppliers: 0,
|
||||||
workers: 0,
|
workers: 0,
|
||||||
dealers: 0
|
dealers: 0
|
||||||
};
|
};
|
||||||
|
|
@ -106,6 +107,12 @@ function getDealerSpeedMultiplier() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cost scaling formulas
|
// Cost scaling formulas
|
||||||
|
function getSupplierCost(drugId) {
|
||||||
|
const config = DRUG_CATALOG.find(d => d.id === drugId);
|
||||||
|
const count = (G.drugs[drugId] && G.drugs[drugId].suppliers) || 0;
|
||||||
|
return Math.floor((config.supplierCost || 75) * Math.pow(1.15, count));
|
||||||
|
}
|
||||||
|
|
||||||
function getWorkerCost(drugId) {
|
function getWorkerCost(drugId) {
|
||||||
const config = DRUG_CATALOG.find(d => d.id === drugId);
|
const config = DRUG_CATALOG.find(d => d.id === drugId);
|
||||||
const count = G.drugs[drugId].workers;
|
const count = G.drugs[drugId].workers;
|
||||||
|
|
@ -166,8 +173,9 @@ function renderLabView() {
|
||||||
`;
|
`;
|
||||||
|
|
||||||
DRUG_CATALOG.forEach(d => {
|
DRUG_CATALOG.forEach(d => {
|
||||||
const data = G.drugs[d.id] || { raw: 0, product: 0, workers: 0, dealers: 0, unlocked: false };
|
const data = G.drugs[d.id] || { raw: 0, product: 0, suppliers: 0, workers: 0, dealers: 0, unlocked: false };
|
||||||
const rawCost = Math.floor(d.rawCost * getRawCostMultiplier());
|
const rawCost = Math.floor(d.rawCost * getRawCostMultiplier());
|
||||||
|
const supplierCost = getSupplierCost(d.id);
|
||||||
const workerCost = getWorkerCost(d.id);
|
const workerCost = getWorkerCost(d.id);
|
||||||
|
|
||||||
if (!data.unlocked) {
|
if (!data.unlocked) {
|
||||||
|
|
@ -196,6 +204,11 @@ function renderLabView() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const suppliers = data.suppliers || 0;
|
||||||
|
const supplyRate = d.supplyRate || 1.0;
|
||||||
|
const autoSupplySpeed = suppliers * supplyRate * getProductionMultiplier();
|
||||||
|
const autoProdSpeed = data.workers * d.produceRate * getProductionMultiplier();
|
||||||
|
|
||||||
html += `
|
html += `
|
||||||
<div class="card" style="border-left: 4px solid ${d.color};">
|
<div class="card" style="border-left: 4px solid ${d.color};">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
|
|
@ -205,10 +218,15 @@ function renderLabView() {
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="card-title">${d.name}</div>
|
<div class="card-title">${d.name}</div>
|
||||||
<div style="font-size: 0.68rem; color: var(--text-secondary); font-family: var(--font-mono);">
|
<div style="font-size: 0.68rem; color: var(--text-secondary); font-family: var(--font-mono); display: flex; flex-wrap: wrap; gap: 4px; align-items: center;">
|
||||||
|
<span id="val-supplier-count-${d.id}">${d.supplierName}s: ${suppliers}</span>
|
||||||
|
<span id="val-auto-supply-${d.id}" style="color: ${suppliers > 0 ? '#38bdf8' : '#8b949e'};">
|
||||||
|
(+${fmtNum(autoSupplySpeed)} r/s)
|
||||||
|
</span>
|
||||||
|
<span>•</span>
|
||||||
<span id="val-worker-count-${d.id}">${d.workerName}s: ${data.workers}</span>
|
<span id="val-worker-count-${d.id}">${d.workerName}s: ${data.workers}</span>
|
||||||
<span id="val-auto-prod-${d.id}" style="color: ${data.workers > 0 ? '#4ade80' : '#8b949e'}; margin-left: 6px;">
|
<span id="val-auto-prod-${d.id}" style="color: ${data.workers > 0 ? '#4ade80' : '#8b949e'};">
|
||||||
(${fmtNum(data.workers * d.produceRate * getProductionMultiplier())}g/s)
|
(${fmtNum(autoProdSpeed)}g/s)
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -246,13 +264,14 @@ function renderLabView() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="btn-grid-auto">
|
<div class="btn-grid-auto">
|
||||||
|
<button id="btn-hire-supplier-${d.id}" class="btn-tactical" onclick="hireSupplier('${d.id}')" ${G.cash < supplierCost ? 'disabled' : ''}>
|
||||||
|
Hire ${d.supplierName}
|
||||||
|
<span class="btn-subtext">$${supplierCost.toLocaleString()}</span>
|
||||||
|
</button>
|
||||||
<button id="btn-hire-worker-${d.id}" class="btn-tactical" onclick="hireWorker('${d.id}')" ${G.cash < workerCost ? 'disabled' : ''}>
|
<button id="btn-hire-worker-${d.id}" class="btn-tactical" onclick="hireWorker('${d.id}')" ${G.cash < workerCost ? 'disabled' : ''}>
|
||||||
Hire ${d.workerName}
|
Hire ${d.workerName}
|
||||||
<span class="btn-subtext">$${workerCost.toLocaleString()}</span>
|
<span class="btn-subtext">$${workerCost.toLocaleString()}</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="btn-tactical" style="opacity: 0.8; font-size: 0.65rem;" onclick="setTab('streets')">
|
|
||||||
Manage Dealers ->
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
@ -516,6 +535,19 @@ function sellManual(drugId, amount = 1) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hireSupplier(drugId) {
|
||||||
|
const cost = getSupplierCost(drugId);
|
||||||
|
if (G.cash >= cost) {
|
||||||
|
G.cash -= cost;
|
||||||
|
if (!G.drugs[drugId].suppliers) G.drugs[drugId].suppliers = 0;
|
||||||
|
G.drugs[drugId].suppliers += 1;
|
||||||
|
queueAction({ type: 'hire_supplier', drug_id: drugId });
|
||||||
|
checkAchievements();
|
||||||
|
renderViewport();
|
||||||
|
updateLiveInventory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function hireWorker(drugId) {
|
function hireWorker(drugId) {
|
||||||
const cost = getWorkerCost(drugId);
|
const cost = getWorkerCost(drugId);
|
||||||
if (G.cash >= cost) {
|
if (G.cash >= cost) {
|
||||||
|
|
@ -596,6 +628,7 @@ function launderMoney() {
|
||||||
unlocked: d.unlockedDefault,
|
unlocked: d.unlockedDefault,
|
||||||
raw: 0.0,
|
raw: 0.0,
|
||||||
product: 0.0,
|
product: 0.0,
|
||||||
|
suppliers: 0,
|
||||||
workers: 0,
|
workers: 0,
|
||||||
dealers: 0
|
dealers: 0
|
||||||
};
|
};
|
||||||
|
|
@ -702,6 +735,14 @@ function clientTick(deltaSec) {
|
||||||
const data = G.drugs[d.id];
|
const data = G.drugs[d.id];
|
||||||
if (!data || !data.unlocked) return;
|
if (!data || !data.unlocked) return;
|
||||||
|
|
||||||
|
// Auto Supply
|
||||||
|
const suppliers = data.suppliers || 0;
|
||||||
|
if (suppliers > 0) {
|
||||||
|
const supplyRate = d.supplyRate || 1.0;
|
||||||
|
const toSupply = suppliers * supplyRate * prodMulti * deltaSec;
|
||||||
|
data.raw = data.raw + toSupply;
|
||||||
|
}
|
||||||
|
|
||||||
// Auto Production
|
// Auto Production
|
||||||
if (data.workers > 0 && data.raw > 0) {
|
if (data.workers > 0 && data.raw > 0) {
|
||||||
const prodPerSec = data.workers * d.produceRate * prodMulti;
|
const prodPerSec = data.workers * d.produceRate * prodMulti;
|
||||||
|
|
@ -761,6 +802,7 @@ function updateLiveInventory() {
|
||||||
dom.heatBar.style.width = `${Math.min(100, Math.round(G.heat))}%`;
|
dom.heatBar.style.width = `${Math.min(100, Math.round(G.heat))}%`;
|
||||||
|
|
||||||
const rawCostMulti = getRawCostMultiplier();
|
const rawCostMulti = getRawCostMultiplier();
|
||||||
|
const prodMulti = getProductionMultiplier();
|
||||||
let stashChipsHtml = '';
|
let stashChipsHtml = '';
|
||||||
|
|
||||||
// Surgically update raw, product, buttons, and stash chips
|
// Surgically update raw, product, buttons, and stash chips
|
||||||
|
|
@ -789,24 +831,38 @@ function updateLiveInventory() {
|
||||||
const streetProdEl = document.getElementById(`val-prod-street-${d.id}`);
|
const streetProdEl = document.getElementById(`val-prod-street-${d.id}`);
|
||||||
if (streetProdEl) streetProdEl.textContent = `${fmtNum(drugData.product)}g`;
|
if (streetProdEl) streetProdEl.textContent = `${fmtNum(drugData.product)}g`;
|
||||||
|
|
||||||
|
const supplierCountEl = document.getElementById(`val-supplier-count-${d.id}`);
|
||||||
|
if (supplierCountEl) supplierCountEl.textContent = `${d.supplierName}s: ${drugData.suppliers || 0}`;
|
||||||
|
|
||||||
|
const autoSupplyEl = document.getElementById(`val-auto-supply-${d.id}`);
|
||||||
|
if (autoSupplyEl) {
|
||||||
|
const currentSupplySpeed = (drugData.suppliers || 0) * (d.supplyRate || 1.0) * prodMulti;
|
||||||
|
autoSupplyEl.textContent = `(+${fmtNum(currentSupplySpeed)} r/s)`;
|
||||||
|
autoSupplyEl.style.color = (drugData.suppliers || 0) > 0 ? '#38bdf8' : '#8b949e';
|
||||||
|
}
|
||||||
|
|
||||||
const workerCountEl = document.getElementById(`val-worker-count-${d.id}`);
|
const workerCountEl = document.getElementById(`val-worker-count-${d.id}`);
|
||||||
if (workerCountEl) workerCountEl.textContent = `${d.workerName}s: ${drugData.workers}`;
|
if (workerCountEl) workerCountEl.textContent = `${d.workerName}s: ${drugData.workers}`;
|
||||||
|
|
||||||
const autoProdEl = document.getElementById(`val-auto-prod-${d.id}`);
|
const autoProdEl = document.getElementById(`val-auto-prod-${d.id}`);
|
||||||
if (autoProdEl) {
|
if (autoProdEl) {
|
||||||
const currentSpeed = drugData.workers * d.produceRate * getProductionMultiplier();
|
const currentSpeed = drugData.workers * d.produceRate * prodMulti;
|
||||||
autoProdEl.textContent = `(${fmtNum(currentSpeed)}g/s)`;
|
autoProdEl.textContent = `(${fmtNum(currentSpeed)}g/s)`;
|
||||||
autoProdEl.style.color = (drugData.workers > 0 && drugData.raw > 0) ? '#4ade80' : '#8b949e';
|
autoProdEl.style.color = (drugData.workers > 0 && drugData.raw > 0) ? '#4ade80' : '#8b949e';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Live button state updates (enable/disable as resources change)
|
// Live button state updates (enable/disable as resources change)
|
||||||
const rawCost = Math.floor(d.rawCost * rawCostMulti);
|
const rawCost = Math.floor(d.rawCost * rawCostMulti);
|
||||||
|
const supplierCost = getSupplierCost(d.id);
|
||||||
const workerCost = getWorkerCost(d.id);
|
const workerCost = getWorkerCost(d.id);
|
||||||
const dealerCost = getDealerCost(d.id);
|
const dealerCost = getDealerCost(d.id);
|
||||||
|
|
||||||
const btnBuyRaw = document.getElementById(`btn-buy-raw-${d.id}`);
|
const btnBuyRaw = document.getElementById(`btn-buy-raw-${d.id}`);
|
||||||
if (btnBuyRaw) btnBuyRaw.disabled = (G.cash < rawCost);
|
if (btnBuyRaw) btnBuyRaw.disabled = (G.cash < rawCost);
|
||||||
|
|
||||||
|
const btnHireSupplier = document.getElementById(`btn-hire-supplier-${d.id}`);
|
||||||
|
if (btnHireSupplier) btnHireSupplier.disabled = (G.cash < supplierCost);
|
||||||
|
|
||||||
const btnMake = document.getElementById(`btn-make-${d.id}`);
|
const btnMake = document.getElementById(`btn-make-${d.id}`);
|
||||||
if (btnMake) btnMake.disabled = (drugData.raw < 1);
|
if (btnMake) btnMake.disabled = (drugData.raw < 1);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue