/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Button = Container.expand(function (text, color, width, height) { var self = Container.call(this); var buttonGraphics = self.attachAsset('buyButton', { anchorX: 0.5, anchorY: 0.5, width: width || 300, height: height || 120 }); buttonGraphics.tint = color || 0x27ae60; var buttonText = new Text2(text, { size: 32, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); buttonText.x = 0; buttonText.y = 0; self.addChild(buttonText); self.down = function (x, y, obj) { buttonGraphics.scaleX = 0.9; buttonGraphics.scaleY = 0.9; }; self.up = function (x, y, obj) { buttonGraphics.scaleX = 1.0; buttonGraphics.scaleY = 1.0; }; return self; }); var Vehicle = Container.expand(function (carData, isMotorcycle, isVan) { var self = Container.call(this); self.carData = carData; self.inspected = false; self.repaired = false; self.isMotorcycle = isMotorcycle || false; self.isVan = isVan || false; var assetPrefix = self.isVan ? 'van' : self.isMotorcycle ? 'moto' : 'car'; var assetSuffix = carData.condition === 'damaged' ? 'Damaged' : 'Offer'; var carGraphics = self.attachAsset(assetPrefix + assetSuffix, { anchorX: 0.5, anchorY: 0.5 }); var carText = new Text2(carData.make + ' ' + carData.model, { size: 36, fill: 0xFFFFFF }); carText.anchor.set(0.5, 0.5); carText.x = 0; carText.y = -80; self.addChild(carText); var priceText = new Text2('$' + carData.price.toLocaleString(), { size: 40, fill: 0xFFFF00 }); priceText.anchor.set(0.5, 0.5); priceText.x = 0; priceText.y = -40; self.addChild(priceText); var conditionText = new Text2(carData.condition + ' - ' + carData.mileage + 'k miles', { size: 28, fill: 0xFFFFFF }); conditionText.anchor.set(0.5, 0.5); conditionText.x = 0; conditionText.y = 10; self.addChild(conditionText); self.updateDisplay = function () { carGraphics.visible = false; self.removeChild(carGraphics); var assetPrefix = self.isVan ? 'van' : self.isMotorcycle ? 'moto' : 'car'; var assetType = assetPrefix + 'Offer'; if (self.carData.actualCondition === 'damaged' && !self.repaired) { assetType = assetPrefix + 'Damaged'; } else if (self.repaired) { assetType = assetPrefix + 'Repaired'; } carGraphics = self.attachAsset(assetType, { anchorX: 0.5, anchorY: 0.5 }); // Re-create and re-add text elements to ensure they are properly displayed if (carText && carText.parent) { self.removeChild(carText); } carText = new Text2(self.carData.make + ' ' + self.carData.model, { size: 36, fill: 0xFFFFFF }); carText.anchor.set(0.5, 0.5); carText.x = 0; carText.y = -80; self.addChild(carText); if (priceText && priceText.parent) { self.removeChild(priceText); } priceText = new Text2('$' + self.carData.price.toLocaleString(), { size: 40, fill: 0xFFFF00 }); priceText.anchor.set(0.5, 0.5); priceText.x = 0; priceText.y = -40; self.addChild(priceText); if (conditionText && conditionText.parent) { self.removeChild(conditionText); } // Use actual condition and mileage for display var displayCondition = self.repaired ? 'good' : self.carData.actualCondition; var displayMileage = self.carData.actualMileage || self.carData.mileage; conditionText = new Text2(displayCondition + ' - ' + displayMileage + 'k miles', { size: 28, fill: 0xFFFFFF }); conditionText.anchor.set(0.5, 0.5); conditionText.x = 0; conditionText.y = 10; self.addChild(conditionText); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x34495e }); /**** * Game Code ****/ // Game state variables var playerMoney = storage.playerMoney || 50000; var currentDay = storage.currentDay || 1; var playerDebt = storage.playerDebt || 0; var dailyInterestRate = 0.05; // 5% daily interest var creditLimit = storage.creditLimit || 50000; // Maximum credit limit var loanTakenDay = storage.loanTakenDay || 0; // Day when last loan was taken var totalLoansOutstanding = storage.totalLoansOutstanding || 0; // Total amount in loans var taxDebt = storage.taxDebt || 0; var taxDueDate = storage.taxDueDate || 0; var taxOverdueDate = storage.taxOverdueDate || 0; var lastTaxDay = storage.lastTaxDay || 0; var ownedVehicles = []; var vehiclesInRepair = []; // Track vehicles currently being repaired var motorcycleUnlocked = storage.motorcycleUnlocked || false; var vanUnlocked = storage.vanUnlocked || false; var soundEffectsEnabled = storage.soundEffectsEnabled !== undefined ? storage.soundEffectsEnabled : true; var ownedMotorcycles = []; var ownedVans = []; var motorcyclesInRepair = []; // Track motorcycles currently being repaired var vansInRepair = []; // Track vans currently being repaired var dailyMotoOffers = []; var vehicleType = 'cars'; // 'cars' or 'motorcycles' // Load owned vehicles from storage if (storage.vehicleCount) { for (var i = 0; i < storage.vehicleCount; i++) { ownedVehicles.push({ make: storage.vehicleMakes[i], model: storage.vehicleModels[i], condition: storage.vehicleConditions[i], actualCondition: storage.vehicleActualConditions[i], mileage: storage.vehicleMileages[i], actualMileage: storage.vehicleActualMileages[i] || storage.vehicleMileages[i], price: storage.vehiclePrices[i], marketValue: storage.vehicleMarketValues[i], sellerLying: storage.vehicleSellerLying[i], id: storage.vehicleIds[i], repaired: storage.vehicleRepaired[i], inRepair: storage.vehicleInRepair ? storage.vehicleInRepair[i] : false, repairCompletionDay: storage.vehicleRepairCompletionDay ? storage.vehicleRepairCompletionDay[i] : 0 }); } } // Load repair shop data if (storage.vehiclesInRepairCount) { for (var r = 0; r < storage.vehiclesInRepairCount; r++) { vehiclesInRepair.push({ vehicleId: storage.repairVehicleIds[r], completionDay: storage.repairCompletionDays[r], repairDuration: storage.repairDurations[r] }); } } // Load owned motorcycles from storage if (storage.motorcycleCount) { for (var m = 0; m < storage.motorcycleCount; m++) { ownedMotorcycles.push({ make: storage.motorcycleMakes[m], model: storage.motorcycleModels[m], condition: storage.motorcycleConditions[m], actualCondition: storage.motorcycleActualConditions[m], mileage: storage.motorcycleMileages[m], actualMileage: storage.motorcycleActualMileages[m] || storage.motorcycleMileages[m], price: storage.motorcyclePrices[m], marketValue: storage.motorcycleMarketValues[m], sellerLying: storage.motorcycleSellerLying[m], id: storage.motorcycleIds[m], repaired: storage.motorcycleRepaired[m], inRepair: storage.motorcycleInRepair ? storage.motorcycleInRepair[m] : false, repairCompletionDay: storage.motorcycleRepairCompletionDay ? storage.motorcycleRepairCompletionDay[m] : 0 }); } } // Load motorcycle repair shop data if (storage.motorcyclesInRepairCount) { for (var mr = 0; mr < storage.motorcyclesInRepairCount; mr++) { motorcyclesInRepair.push({ vehicleId: storage.repairMotoVehicleIds[mr], completionDay: storage.repairMotoCompletionDays[mr], repairDuration: storage.repairMotoDurations[mr] }); } } // Load owned vans from storage if (storage.vanCount) { for (var v = 0; v < storage.vanCount; v++) { ownedVans.push({ make: storage.vanMakes[v], model: storage.vanModels[v], condition: storage.vanConditions[v], actualCondition: storage.vanActualConditions[v], mileage: storage.vanMileages[v], actualMileage: storage.vanActualMileages[v] || storage.vanMileages[v], price: storage.vanPrices[v], marketValue: storage.vanMarketValues[v], sellerLying: storage.vanSellerLying[v], id: storage.vanIds[v], repaired: storage.vanRepaired[v], inRepair: storage.vanInRepair ? storage.vanInRepair[v] : false, repairCompletionDay: storage.vanRepairCompletionDay ? storage.vanRepairCompletionDay[v] : 0 }); } } // Load van repair shop data if (storage.vansInRepairCount) { for (var vr = 0; vr < storage.vansInRepairCount; vr++) { vansInRepair.push({ vehicleId: storage.repairVanVehicleIds[vr], completionDay: storage.repairVanCompletionDays[vr], repairDuration: storage.repairVanDurations[vr] }); } } var dailyOffers = []; var selectedVehicle = null; var gameState = 'daily_offers'; // 'daily_offers', 'vehicle_selected', 'owned_vehicles' // Car data arrays var carMakes = ['Toyota', 'Honda', 'Ford', 'Chevrolet', 'BMW', 'Mercedes', 'Audi', 'Nissan', 'Volkswagen', 'Hyundai']; var carModels = ['Sedan', 'SUV', 'Coupe', 'Hatchback', 'Wagon', 'Convertible', 'Truck', 'Compact']; var conditions = ['excellent', 'good', 'fair', 'poor', 'damaged']; // Motorcycle data arrays var motoMakes = ['Harley-Davidson', 'Yamaha', 'Honda', 'Kawasaki', 'Suzuki', 'Ducati', 'BMW', 'Triumph', 'Indian', 'KTM']; var motoModels = ['Cruiser', 'Sport', 'Touring', 'Adventure', 'Naked', 'Chopper', 'Cafe Racer', 'Scooter']; // Van data arrays var vanMakes = ['Ford', 'Chevrolet', 'Mercedes', 'Nissan', 'Isuzu', 'Ram', 'Iveco', 'Volkswagen', 'Toyota', 'Peugeot']; var vanModels = ['Transit', 'Express', 'Sprinter', 'ProMaster', 'NV200', 'Cargo Van', 'Panel Van', 'Box Truck']; // UI Elements var moneyText = new Text2('Money: $' + playerMoney.toLocaleString(), { size: 50, fill: 0x2ECC71 }); moneyText.anchor.set(0, 0); moneyText.x = 120; moneyText.y = 50; LK.gui.topLeft.addChild(moneyText); var dayText = new Text2('Day ' + currentDay, { size: 50, fill: 0xFFFFFF }); dayText.anchor.set(1, 0); dayText.x = 0; dayText.y = 50; LK.gui.topRight.addChild(dayText); var debtText = new Text2('Debt: $' + playerDebt.toLocaleString(), { size: 40, fill: 0xe74c3c }); debtText.anchor.set(0, 0); debtText.x = 120; debtText.y = 110; LK.gui.topLeft.addChild(debtText); var taxText = new Text2('Tax: $' + taxDebt.toLocaleString(), { size: 40, fill: 0xe74c3c }); taxText.anchor.set(0, 0); taxText.x = 120; taxText.y = 170; LK.gui.topLeft.addChild(taxText); var titleText = new Text2('Car Dealer Tycoon', { size: 80, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0); titleText.x = 2048 / 2; titleText.y = 150; game.addChild(titleText); var stateText = new Text2('Daily Vehicle Offers', { size: 50, fill: 0xECF0F1 }); stateText.anchor.set(0.5, 0); stateText.x = 2048 / 2; stateText.y = 250; game.addChild(stateText); // Action buttons var inspectButton = game.addChild(new Button('Inspect ($500)', 0xf39c12)); inspectButton.x = 2048 / 2 - 400; inspectButton.y = 2200; inspectButton.visible = false; var buyButton = game.addChild(new Button('Buy Vehicle', 0x27ae60)); buyButton.x = 2048 / 2 - 150; buyButton.y = 2200; buyButton.visible = false; var negotiateButton = game.addChild(new Button('Negotiate', 0x34495e)); negotiateButton.x = 2048 / 2 + 150; negotiateButton.y = 2200; negotiateButton.visible = false; var repairButton = game.addChild(new Button('Repair (Dynamic)', 0xe67e22)); repairButton.x = 2048 / 2 - 150; repairButton.y = 2200; repairButton.visible = false; var sellButton = game.addChild(new Button('Sell', 0x8e44ad)); sellButton.x = 2048 / 2 + 150; sellButton.y = 2200; sellButton.visible = false; var nextDayButton = game.addChild(new Button('Next Day', 0x2c3e50, 400, 140)); nextDayButton.x = 2048 / 2; nextDayButton.y = 2350; var viewOwnedButton = game.addChild(new Button('View Owned Cars', 0x95a5a6)); viewOwnedButton.x = 2048 / 2; viewOwnedButton.y = 2200; var loanButton = game.addChild(new Button('Take Loan ($10,000)', 0x3498db)); loanButton.x = 2048 / 2 - 450; loanButton.y = 2550; var payDebtButton = game.addChild(new Button('Pay Debt', 0x27ae60)); payDebtButton.x = 2048 / 2 + 3; payDebtButton.y = 2500; var payTaxButton = game.addChild(new Button('Pay Tax', 0x27ae60)); payTaxButton.x = 2048 / 2 + 450; payTaxButton.y = 2550; var vehicleLocksButton = game.addChild(new Button('Vehicle Locks', 0x7f8c8d, 300, 120)); vehicleLocksButton.x = 1600; vehicleLocksButton.y = 2400; vehicleLocksButton.visible = !motorcycleUnlocked || !vanUnlocked; var settingsButton = game.addChild(new Button('Settings', 0x7f8c8d, 300, 120)); settingsButton.x = -200; settingsButton.y = 200; LK.gui.topRight.addChild(settingsButton); // Switch vehicle button removed - vehicles are now mixed together // Vehicle display containers var vehicleContainer = new Container(); vehicleContainer.x = 2048 / 2; vehicleContainer.y = 800; game.addChild(vehicleContainer); var infoText = new Text2('', { size: 32, fill: 0xFFFFFF }); infoText.anchor.set(0.5, 0.5); infoText.x = 2048 / 2; infoText.y = 1800; game.addChild(infoText); // Generate random vehicle data function generateRandomVehicle() { var make = carMakes[Math.floor(Math.random() * carMakes.length)]; var model = carModels[Math.floor(Math.random() * carModels.length)]; var condition = conditions[Math.floor(Math.random() * conditions.length)]; var mileage = Math.floor(Math.random() * 200) + 20; var basePrice = Math.floor(Math.random() * 40000) + 10000; // Sellers may lie about condition - both ways var actualCondition = condition; var actualMileage = mileage; var sellerLying = Math.random() < 0.4; // 40% chance of lying if (sellerLying) { // 70% chance they claim better condition, 30% chance they hide damage if (Math.random() < 0.7 && condition !== 'damaged') { // Claim better condition than actual var betterConditions = conditions.slice(0, conditions.indexOf(condition)); if (betterConditions.length > 0) { condition = betterConditions[Math.floor(Math.random() * betterConditions.length)]; } } else { // Hide damage - claim undamaged when actually damaged var worseConditions = conditions.slice(conditions.indexOf(condition) + 1); if (worseConditions.length > 0) { actualCondition = worseConditions[Math.floor(Math.random() * worseConditions.length)]; // If actual condition becomes damaged, they claim it's not if (actualCondition === 'damaged') { condition = 'poor'; // They claim it's just poor condition } } } } // 30% chance they also lie about mileage if (Math.random() < 0.3) { // They claim lower mileage than actual var mileageReduction = Math.floor(Math.random() * 50) + 10; // 10-60k miles less actualMileage = mileage + mileageReduction; // Cap at reasonable maximum if (actualMileage > 300) { actualMileage = 300; } } // Adjust price based on condition var priceMultiplier = 1; switch (actualCondition) { case 'excellent': priceMultiplier = 1.2; break; case 'good': priceMultiplier = 1.0; break; case 'fair': priceMultiplier = 0.8; break; case 'poor': priceMultiplier = 0.6; break; case 'damaged': priceMultiplier = 0.4; break; } var price = Math.floor(basePrice * priceMultiplier * (1 - mileage / 300)); // 15% chance that this seller is a scammer var isScammer = Math.random() < 0.15; return { make: make, model: model, condition: condition, actualCondition: actualCondition, mileage: mileage, actualMileage: actualMileage, price: price, marketValue: Math.floor(price * 1.5), sellerLying: sellerLying, isScammer: isScammer, id: Math.random().toString(36).substr(2, 9) }; } // Generate random motorcycle data function generateRandomMotorcycle() { var make = motoMakes[Math.floor(Math.random() * motoMakes.length)]; var model = motoModels[Math.floor(Math.random() * motoModels.length)]; var condition = conditions[Math.floor(Math.random() * conditions.length)]; var mileage = Math.floor(Math.random() * 150) + 10; // Lower mileage for motorcycles var basePrice = Math.floor(Math.random() * 30000) + 5000; // Lower price range for motorcycles // Sellers may lie about condition - both ways var actualCondition = condition; var actualMileage = mileage; var sellerLying = Math.random() < 0.4; // 40% chance of lying if (sellerLying) { // 70% chance they claim better condition, 30% chance they hide damage if (Math.random() < 0.7 && condition !== 'damaged') { // Claim better condition than actual var betterConditions = conditions.slice(0, conditions.indexOf(condition)); if (betterConditions.length > 0) { condition = betterConditions[Math.floor(Math.random() * betterConditions.length)]; } } else { // Hide damage - claim undamaged when actually damaged var worseConditions = conditions.slice(conditions.indexOf(condition) + 1); if (worseConditions.length > 0) { actualCondition = worseConditions[Math.floor(Math.random() * worseConditions.length)]; // If actual condition becomes damaged, they claim it's not if (actualCondition === 'damaged') { condition = 'poor'; // They claim it's just poor condition } } } } // 30% chance they also lie about mileage if (Math.random() < 0.3) { // They claim lower mileage than actual var mileageReduction = Math.floor(Math.random() * 40) + 10; // 10-50k miles less actualMileage = mileage + mileageReduction; // Cap at reasonable maximum if (actualMileage > 200) { actualMileage = 200; } } // Adjust price based on condition var priceMultiplier = 1; switch (actualCondition) { case 'excellent': priceMultiplier = 1.2; break; case 'good': priceMultiplier = 1.0; break; case 'fair': priceMultiplier = 0.8; break; case 'poor': priceMultiplier = 0.6; break; case 'damaged': priceMultiplier = 0.4; break; } var price = Math.floor(basePrice * priceMultiplier * (1 - mileage / 200)); // 15% chance that this seller is a scammer var isScammer = Math.random() < 0.15; return { make: make, model: model, condition: condition, actualCondition: actualCondition, mileage: mileage, actualMileage: actualMileage, price: price, marketValue: Math.floor(price * 1.5), sellerLying: sellerLying, isScammer: isScammer, id: Math.random().toString(36).substr(2, 9) }; } // Generate random van data function generateRandomVan() { var make = vanMakes[Math.floor(Math.random() * vanMakes.length)]; var model = vanModels[Math.floor(Math.random() * vanModels.length)]; var condition = conditions[Math.floor(Math.random() * conditions.length)]; var mileage = Math.floor(Math.random() * 250) + 30; // Higher mileage for vans var basePrice = Math.floor(Math.random() * 50000) + 20000; // Higher price range for vans // Sellers may lie about condition - both ways var actualCondition = condition; var actualMileage = mileage; var sellerLying = Math.random() < 0.4; // 40% chance of lying if (sellerLying) { // 70% chance they claim better condition, 30% chance they hide damage if (Math.random() < 0.7 && condition !== 'damaged') { // Claim better condition than actual var betterConditions = conditions.slice(0, conditions.indexOf(condition)); if (betterConditions.length > 0) { condition = betterConditions[Math.floor(Math.random() * betterConditions.length)]; } } else { // Hide damage - claim undamaged when actually damaged var worseConditions = conditions.slice(conditions.indexOf(condition) + 1); if (worseConditions.length > 0) { actualCondition = worseConditions[Math.floor(Math.random() * worseConditions.length)]; // If actual condition becomes damaged, they claim it's not if (actualCondition === 'damaged') { condition = 'poor'; // They claim it's just poor condition } } } } // 30% chance they also lie about mileage if (Math.random() < 0.3) { // They claim lower mileage than actual var mileageReduction = Math.floor(Math.random() * 60) + 20; // 20-80k miles less actualMileage = mileage + mileageReduction; // Cap at reasonable maximum if (actualMileage > 400) { actualMileage = 400; } } // Adjust price based on condition var priceMultiplier = 1; switch (actualCondition) { case 'excellent': priceMultiplier = 1.2; break; case 'good': priceMultiplier = 1.0; break; case 'fair': priceMultiplier = 0.8; break; case 'poor': priceMultiplier = 0.6; break; case 'damaged': priceMultiplier = 0.4; break; } var price = Math.floor(basePrice * priceMultiplier * (1 - mileage / 400)); // 15% chance that this seller is a scammer var isScammer = Math.random() < 0.15; return { make: make, model: model, condition: condition, actualCondition: actualCondition, mileage: mileage, actualMileage: actualMileage, price: price, marketValue: Math.floor(price * 1.5), sellerLying: sellerLying, isScammer: isScammer, id: Math.random().toString(36).substr(2, 9), isVan: true }; } // Generate daily offers (mixed cars and motorcycles if unlocked) function generateDailyOffers() { dailyOffers = []; var numOffers = Math.floor(Math.random() * 3) + 2; for (var i = 0; i < numOffers; i++) { var randomType = Math.random(); // If both motorcycles and vans are unlocked if (motorcycleUnlocked && vanUnlocked) { if (randomType < 0.3) { // 30% chance for motorcycle var motoOffer = generateRandomMotorcycle(); motoOffer.isMotorcycle = true; dailyOffers.push(motoOffer); } else if (randomType < 0.5) { // 20% chance for van var vanOffer = generateRandomVan(); vanOffer.isVan = true; dailyOffers.push(vanOffer); } else { // 50% chance for car dailyOffers.push(generateRandomVehicle()); } } else if (motorcycleUnlocked && Math.random() < 0.4) { // 40% chance for motorcycle var motoOffer = generateRandomMotorcycle(); motoOffer.isMotorcycle = true; // Mark as motorcycle dailyOffers.push(motoOffer); } else if (vanUnlocked && Math.random() < 0.3) { // 30% chance for van var vanOffer = generateRandomVan(); vanOffer.isVan = true; dailyOffers.push(vanOffer); } else { dailyOffers.push(generateRandomVehicle()); } } } // Generate daily motorcycle offers function generateDailyMotoOffers() { dailyMotoOffers = []; var numOffers = Math.floor(Math.random() * 3) + 2; for (var i = 0; i < numOffers; i++) { dailyMotoOffers.push(generateRandomMotorcycle()); } } // Display vehicles function displayVehicles(vehicles) { vehicleContainer.removeChildren(); for (var i = 0; i < vehicles.length; i++) { var isMotorcycle = vehicles[i].isMotorcycle || false; var isVan = vehicles[i].isVan || false; var vehicle = new Vehicle(vehicles[i], isMotorcycle, isVan); vehicle.x = i % 2 * 600 - 300; vehicle.y = Math.floor(i / 2) * 380; vehicleContainer.addChild(vehicle); vehicle.vehicleData = vehicles[i]; vehicle.down = function (x, y, obj) { selectedVehicle = obj.vehicleData; updateUI(); }; // Add buy button for each vehicle var vehicleBuyButton = new Button('Buy', 0x27ae60, 200, 80); vehicleBuyButton.x = 0; vehicleBuyButton.y = 150; vehicle.addChild(vehicleBuyButton); // Store vehicle data directly on the button using closure (function (vehicleData, vehicleIndex) { vehicleBuyButton.up = function (x, y, obj) { if (vehicleData && playerMoney >= vehicleData.price) { playerMoney -= vehicleData.price; // Check if this seller is a scammer if (vehicleData.isScammer) { // Player loses money but gets no vehicle infoText.setText('SCAMMED! The seller took your money and disappeared!\nYou lost $' + vehicleData.price.toLocaleString() + '!'); LK.effects.flashScreen(0xff0000, 1500); // Red flash for scam } else { // Normal purchase - Create a copy of the vehicle data for owned vehicles var ownedVehicleData = { make: vehicleData.make, model: vehicleData.model, condition: vehicleData.condition, actualCondition: vehicleData.actualCondition, mileage: vehicleData.mileage, actualMileage: vehicleData.actualMileage, price: vehicleData.price, marketValue: vehicleData.marketValue, sellerLying: vehicleData.sellerLying, id: vehicleData.id, repaired: false }; if (vehicleData.isMotorcycle) { ownedMotorcycles.push(ownedVehicleData); } else if (vehicleData.isVan) { ownedVans.push(ownedVehicleData); } else { ownedVehicles.push(ownedVehicleData); } if (soundEffectsEnabled) LK.getSound('purchase').play(); } // Remove from daily offers in both cases for (var j = 0; j < dailyOffers.length; j++) { if (dailyOffers[j].id === vehicleData.id) { dailyOffers.splice(j, 1); break; } } selectedVehicle = null; updateMoneyDisplay(); displayVehicles(dailyOffers); updateUI(); saveGame(); } }; })(vehicles[i], i); } } // Update UI based on game state function updateUI() { inspectButton.visible = false; buyButton.visible = false; negotiateButton.visible = false; repairButton.visible = false; sellButton.visible = false; expertiseButton.visible = false; if (gameState === 'daily_offers' && selectedVehicle) { inspectButton.visible = true; buyButton.visible = true; negotiateButton.visible = true; expertiseButton.visible = true; // Calculate expertise cost based on vehicle price (15-20% of price) var expertiseCost = Math.floor(selectedVehicle.price * (Math.random() * 0.05 + 0.15)); // Minimum expertise cost of $1000 if (expertiseCost < 1000) { expertiseCost = 1000; } // Update expertise button text with dynamic cost expertiseButton.children[0].setText('Expertise ($' + expertiseCost.toLocaleString() + ')'); infoText.setText('Selected: ' + selectedVehicle.make + ' ' + selectedVehicle.model + '\nCondition: ' + selectedVehicle.condition + '\nMileage: ' + selectedVehicle.mileage + 'k miles' + '\nPrice: $' + selectedVehicle.price.toLocaleString()); } else if (gameState === 'owned_vehicles' && selectedVehicle) { if (selectedVehicle.actualCondition === 'damaged' && !selectedVehicle.repaired) { repairButton.visible = true; } else { sellButton.visible = true; } infoText.setText('Owned: ' + selectedVehicle.make + ' ' + selectedVehicle.model + '\nCondition: ' + selectedVehicle.actualCondition + '\nMileage: ' + selectedVehicle.actualMileage + 'k miles' + '\nMarket Value: $' + selectedVehicle.marketValue.toLocaleString()); } else { infoText.setText('Select a vehicle to view options'); } } // Add expertise button var expertiseButton = game.addChild(new Button('Expertise (Dynamic)', 0x9b59b6)); expertiseButton.x = 2048 / 2 + 400; expertiseButton.y = 2200; expertiseButton.visible = false; // Button event handlers inspectButton.up = function (x, y, obj) { if (selectedVehicle && playerMoney >= 500) { playerMoney -= 500; selectedVehicle.inspected = true; selectedVehicle.condition = selectedVehicle.actualCondition; if (soundEffectsEnabled) LK.getSound('inspect').play(); updateMoneyDisplay(); displayVehicles(dailyOffers); updateUI(); if (selectedVehicle.sellerLying || selectedVehicle.mileage !== selectedVehicle.actualMileage) { var lieText = 'Inspection revealed the seller was lying!\n'; if (selectedVehicle.sellerLying) { lieText += 'Actual condition: ' + selectedVehicle.actualCondition + '\n'; } if (selectedVehicle.mileage !== selectedVehicle.actualMileage) { lieText += 'Actual mileage: ' + selectedVehicle.actualMileage + 'k miles'; } infoText.setText(lieText); } else { infoText.setText('Inspection confirmed seller was honest.'); } } }; expertiseButton.up = function (x, y, obj) { if (selectedVehicle) { // Calculate expertise cost based on vehicle price (15-20% of price) var expertiseCost = Math.floor(selectedVehicle.price * (Math.random() * 0.05 + 0.15)); // Minimum expertise cost of $1000 if (expertiseCost < 1000) { expertiseCost = 1000; } if (playerMoney >= expertiseCost) { playerMoney -= expertiseCost; selectedVehicle.inspected = true; selectedVehicle.condition = selectedVehicle.actualCondition; if (soundEffectsEnabled) LK.getSound('inspect').play(); updateMoneyDisplay(); displayVehicles(dailyOffers); updateUI(); var detailsText = 'EXPERTISE REPORT (Cost: $' + expertiseCost.toLocaleString() + '):\n'; detailsText += 'True Condition: ' + selectedVehicle.actualCondition + '\n'; detailsText += 'Claimed Mileage: ' + selectedVehicle.mileage + 'k miles\n'; detailsText += 'Actual Mileage: ' + selectedVehicle.actualMileage + 'k miles\n'; detailsText += 'Mileage Honest: ' + (selectedVehicle.mileage === selectedVehicle.actualMileage ? 'YES' : 'NO') + '\n'; detailsText += 'Seller Honest: ' + (selectedVehicle.sellerLying ? 'NO' : 'YES') + '\n'; detailsText += 'Market Value: $' + selectedVehicle.marketValue.toLocaleString() + '\n'; detailsText += 'Seller Trustworthy: ' + (selectedVehicle.isScammer ? 'SUSPICIOUS - POSSIBLE SCAMMER!' : 'YES') + '\n'; detailsText += 'Recommended Action: '; if (selectedVehicle.isScammer) { detailsText += 'AVOID - HIGH SCAM RISK!'; } else if (selectedVehicle.price < selectedVehicle.marketValue * 0.8) { detailsText += 'BUY - Good Deal'; } else if (selectedVehicle.price > selectedVehicle.marketValue * 1.2) { detailsText += 'AVOID - Overpriced'; } else { detailsText += 'NEGOTIATE - Fair Price'; } infoText.setText(detailsText); } else { infoText.setText('Not enough money! Expertise costs $' + expertiseCost.toLocaleString()); } } }; buyButton.up = function (x, y, obj) { if (selectedVehicle && playerMoney >= selectedVehicle.price) { playerMoney -= selectedVehicle.price; // Check if this seller is a scammer if (selectedVehicle.isScammer) { // Player loses money but gets no vehicle infoText.setText('SCAMMED! The seller took your money and disappeared!\nYou lost $' + selectedVehicle.price.toLocaleString() + '!'); LK.effects.flashScreen(0xff0000, 1500); // Red flash for scam } else { // Normal purchase selectedVehicle.actualCondition = selectedVehicle.actualCondition; if (selectedVehicle.isMotorcycle) { ownedMotorcycles.push(selectedVehicle); } else if (selectedVehicle.isVan) { ownedVans.push(selectedVehicle); } else { ownedVehicles.push(selectedVehicle); } if (soundEffectsEnabled) LK.getSound('purchase').play(); } // Remove from daily offers in both cases for (var i = 0; i < dailyOffers.length; i++) { if (dailyOffers[i].id === selectedVehicle.id) { dailyOffers.splice(i, 1); break; } } selectedVehicle = null; updateMoneyDisplay(); displayVehicles(dailyOffers); updateUI(); saveGame(); } }; negotiateButton.up = function (x, y, obj) { if (selectedVehicle) { var reduction = Math.floor(selectedVehicle.price * (Math.random() * 0.2 + 0.05)); selectedVehicle.price -= reduction; displayVehicles(dailyOffers); updateUI(); infoText.setText('Negotiated $' + reduction.toLocaleString() + ' off the price!'); } }; repairButton.up = function (x, y, obj) { if (selectedVehicle) { // Calculate repair cost based on vehicle price (10-25% of price) var repairCost = Math.floor(selectedVehicle.price * (Math.random() * 0.15 + 0.10)); // Minimum repair cost of $1000 if (repairCost < 1000) { repairCost = 1000; } if (playerMoney >= repairCost) { playerMoney -= repairCost; // Calculate repair duration based on damage level var repairDuration = 1; // Default 1 day if (selectedVehicle.actualCondition === 'damaged') { repairDuration = Math.floor(Math.random() * 3) + 1; // 1-3 days for damaged } else if (selectedVehicle.actualCondition === 'poor') { repairDuration = 1; // 1 day for poor } // Move vehicle to repair shop var repairData = { vehicleId: selectedVehicle.id, completionDay: currentDay + repairDuration, repairDuration: repairDuration }; vehiclesInRepair.push(repairData); // Mark vehicle as in repair but not completed for (var k = 0; k < ownedVehicles.length; k++) { if (ownedVehicles[k].id === selectedVehicle.id) { ownedVehicles[k].inRepair = true; ownedVehicles[k].repairCompletionDay = currentDay + repairDuration; break; } } if (soundEffectsEnabled) LK.getSound('repair').play(); updateMoneyDisplay(); displayOwnedVehicles(); updateUI(); saveGame(); infoText.setText('Vehicle sent to repair shop for $' + repairCost.toLocaleString() + '!\nWill be ready in ' + repairDuration + ' day(s).'); } else { infoText.setText('Not enough money! Repair costs $' + repairCost.toLocaleString()); } } }; sellButton.up = function (x, y, obj) { if (selectedVehicle) { var salePrice = Math.floor(selectedVehicle.marketValue * (Math.random() * 0.3 + 0.8)); playerMoney += salePrice; // Remove from owned vehicles for (var i = 0; i < ownedVehicles.length; i++) { if (ownedVehicles[i].id === selectedVehicle.id) { ownedVehicles.splice(i, 1); break; } } if (soundEffectsEnabled) LK.getSound('sale').play(); selectedVehicle = null; updateMoneyDisplay(); displayOwnedVehicles(); updateUI(); saveGame(); infoText.setText('Sold for $' + salePrice.toLocaleString() + '!'); } }; nextDayButton.up = function (x, y, obj) { currentDay++; selectedVehicle = null; generateDailyOffers(); gameState = 'daily_offers'; stateText.setText('Daily Vehicle Offers'); dayText.setText('Day ' + currentDay); displayVehicles(dailyOffers); updateUI(); // Add random daily expenses var dailyExpenses = Math.floor(Math.random() * 5000) + 1000; // Between $1000-$6000 playerMoney -= dailyExpenses; var expenseText = 'Daily expenses: $' + dailyExpenses.toLocaleString() + ' (rent, utilities, staff wages)'; // Add maintenance costs for owned vehicles var maintenanceCosts = applyMaintenanceCosts(); if (maintenanceCosts > 0) { expenseText += '\nVehicle maintenance: $' + maintenanceCosts.toLocaleString(); } // Add insurance costs based on number of owned vehicles var insuranceCost = ownedVehicles.length * 150; if (insuranceCost > 0) { playerMoney -= insuranceCost; expenseText += '\nInsurance: $' + insuranceCost.toLocaleString(); } // Random unexpected repairs (10% chance per owned vehicle) var unexpectedRepairs = 0; for (var i = 0; i < ownedVehicles.length; i++) { if (Math.random() < 0.1) { var repairCost = Math.floor(Math.random() * 2000) + 500; unexpectedRepairs += repairCost; } } if (unexpectedRepairs > 0) { playerMoney -= unexpectedRepairs; expenseText += '\nUnexpected repairs: $' + unexpectedRepairs.toLocaleString(); } // Apply vehicle depreciation applyVehicleDepreciation(); // Update repair progress and check for completed repairs var completedRepairs = []; for (var r = vehiclesInRepair.length - 1; r >= 0; r--) { // Decrease remaining repair days vehiclesInRepair[r].repairDuration--; // Update vehicle repair completion day display for (var v = 0; v < ownedVehicles.length; v++) { if (ownedVehicles[v].id === vehiclesInRepair[r].vehicleId) { ownedVehicles[v].repairCompletionDay = currentDay + vehiclesInRepair[r].repairDuration; break; } } // Check if repair is completed (0 days remaining) if (vehiclesInRepair[r].repairDuration <= 0) { completedRepairs.push(vehiclesInRepair[r]); vehiclesInRepair.splice(r, 1); } } // Complete repairs and update vehicle data for (var c = 0; c < completedRepairs.length; c++) { var completedRepair = completedRepairs[c]; for (var v = 0; v < ownedVehicles.length; v++) { if (ownedVehicles[v].id === completedRepair.vehicleId) { ownedVehicles[v].repaired = true; ownedVehicles[v].actualCondition = 'good'; ownedVehicles[v].marketValue = Math.floor(ownedVehicles[v].marketValue * 1.5); ownedVehicles[v].inRepair = false; delete ownedVehicles[v].repairCompletionDay; break; } } } // Update motorcycle repair progress and check for completed repairs var completedMotoRepairs = []; for (var mr = motorcyclesInRepair.length - 1; mr >= 0; mr--) { // Decrease remaining repair days motorcyclesInRepair[mr].repairDuration--; // Update motorcycle repair completion day display for (var mv = 0; mv < ownedMotorcycles.length; mv++) { if (ownedMotorcycles[mv].id === motorcyclesInRepair[mr].vehicleId) { ownedMotorcycles[mv].repairCompletionDay = currentDay + motorcyclesInRepair[mr].repairDuration; break; } } // Check if repair is completed (0 days remaining) if (motorcyclesInRepair[mr].repairDuration <= 0) { completedMotoRepairs.push(motorcyclesInRepair[mr]); motorcyclesInRepair.splice(mr, 1); } } // Complete motorcycle repairs and update motorcycle data for (var mc = 0; mc < completedMotoRepairs.length; mc++) { var completedMotoRepair = completedMotoRepairs[mc]; for (var mv = 0; mv < ownedMotorcycles.length; mv++) { if (ownedMotorcycles[mv].id === completedMotoRepair.vehicleId) { ownedMotorcycles[mv].repaired = true; ownedMotorcycles[mv].actualCondition = 'good'; ownedMotorcycles[mv].marketValue = Math.floor(ownedMotorcycles[mv].marketValue * 1.5); ownedMotorcycles[mv].inRepair = false; delete ownedMotorcycles[mv].repairCompletionDay; break; } } } // Show repair completion message var totalCompletedRepairs = completedRepairs.length + completedMotoRepairs.length; if (totalCompletedRepairs > 0) { expenseText += '\n' + totalCompletedRepairs + ' vehicle(s) completed repair and ready for sale!'; LK.effects.flashScreen(0x2ecc71, 1000); // Green flash for completed repairs } // Apply daily interest on debt var interestCharge = 0; if (playerDebt > 0) { interestCharge = Math.floor(playerDebt * dailyInterestRate); playerDebt += interestCharge; expenseText += '\nDebt interest: $' + interestCharge.toLocaleString(); } // Check for loan seizure (5 days after loan was taken) if (playerDebt > 0 && loanTakenDay > 0 && currentDay > loanTakenDay + 5) { var seizureAmount = Math.floor(playerDebt * 1.5); // 50% more than debt var actualSeizureAmount = 0; var seizedVehicles = []; // First seize money if (playerMoney > 0) { var moneySeized = Math.min(playerMoney, seizureAmount); playerMoney -= moneySeized; actualSeizureAmount += moneySeized; seizureAmount -= moneySeized; } // Then seize vehicles if more seizure needed if (seizureAmount > 0) { // Seize cars for (var i = ownedVehicles.length - 1; i >= 0 && seizureAmount > 0; i--) { var vehicle = ownedVehicles[i]; if (vehicle.marketValue <= seizureAmount) { seizedVehicles.push(vehicle.make + ' ' + vehicle.model); actualSeizureAmount += vehicle.marketValue; seizureAmount -= vehicle.marketValue; ownedVehicles.splice(i, 1); } } // Seize motorcycles for (var i = ownedMotorcycles.length - 1; i >= 0 && seizureAmount > 0; i--) { var vehicle = ownedMotorcycles[i]; if (vehicle.marketValue <= seizureAmount) { seizedVehicles.push(vehicle.make + ' ' + vehicle.model + ' (Motorcycle)'); actualSeizureAmount += vehicle.marketValue; seizureAmount -= vehicle.marketValue; ownedMotorcycles.splice(i, 1); } } // Seize vans for (var i = ownedVans.length - 1; i >= 0 && seizureAmount > 0; i--) { var vehicle = ownedVans[i]; if (vehicle.marketValue <= seizureAmount) { seizedVehicles.push(vehicle.make + ' ' + vehicle.model + ' (Van)'); actualSeizureAmount += vehicle.marketValue; seizureAmount -= vehicle.marketValue; ownedVans.splice(i, 1); } } } // Clear debt and reset loan tracking after seizure playerDebt = 0; totalLoansOutstanding = 0; loanTakenDay = 0; var seizureText = 'LOAN SEIZURE! Assets worth $' + actualSeizureAmount.toLocaleString() + ' seized for unpaid loans!'; if (seizedVehicles.length > 0) { seizureText += '\nVehicles seized: ' + seizedVehicles.join(', '); } expenseText += '\n' + seizureText; LK.effects.flashScreen(0xff0000, 2000); // Red flash for seizure // Update displays after seizure if (gameState === 'owned_vehicles') { displayOwnedVehicles(); } } // Tax system - every 7 days if (currentDay % 7 === 1 && currentDay > lastTaxDay) { // Calculate total vehicle value var totalVehicleValue = 0; for (var i = 0; i < ownedVehicles.length; i++) { totalVehicleValue += ownedVehicles[i].marketValue; } // Tax is 8% of total assets (money + vehicles) var taxAmount = Math.floor((playerMoney + totalVehicleValue) * 0.08); taxDebt += taxAmount; taxDueDate = currentDay + 2; // 2 days to pay taxOverdueDate = currentDay + 2; // Start charging interest after 2 days lastTaxDay = currentDay; expenseText += '\nTAX DUE: $' + taxAmount.toLocaleString() + ' (due in 2 days)'; LK.effects.flashScreen(0xffa500, 1000); // Orange flash for tax notice } // Apply tax interest if overdue (after 2 days) if (taxDebt > 0 && currentDay > taxOverdueDate) { var taxInterest = Math.floor(taxDebt * 0.15); // 15% daily interest taxDebt += taxInterest; expenseText += '\nTax interest: $' + taxInterest.toLocaleString() + ' (15% daily)'; } // Tax seizure after 14 days of unpaid tax debt if (taxDebt > 0 && currentDay > taxDueDate + 14) { var seizureAmount = Math.floor(taxDebt * 1.5); // 50% more than tax debt var actualSeizureAmount = 0; // First seize money if (playerMoney > 0) { var moneySeized = Math.min(playerMoney, seizureAmount); playerMoney -= moneySeized; actualSeizureAmount += moneySeized; seizureAmount -= moneySeized; } // Then seize vehicles if more seizure needed if (seizureAmount > 0 && ownedVehicles.length > 0) { var vehiclesSeized = []; for (var i = ownedVehicles.length - 1; i >= 0 && seizureAmount > 0; i--) { var vehicle = ownedVehicles[i]; if (vehicle.marketValue <= seizureAmount) { vehiclesSeized.push(vehicle.make + ' ' + vehicle.model); actualSeizureAmount += vehicle.marketValue; seizureAmount -= vehicle.marketValue; ownedVehicles.splice(i, 1); } } } // Clear tax debt after seizure taxDebt = 0; taxDueDate = 0; taxOverdueDate = 0; var seizureText = 'TAX SEIZURE! Assets worth $' + actualSeizureAmount.toLocaleString() + ' seized for unpaid taxes!'; if (vehiclesSeized.length > 0) { seizureText += '\nVehicles seized: ' + vehiclesSeized.join(', '); } expenseText += '\n' + seizureText; LK.effects.flashScreen(0xff0000, 2000); // Red flash for seizure // Update displays after seizure if (gameState === 'owned_vehicles') { displayOwnedVehicles(); } } updateMoneyDisplay(); updateDebtDisplay(); updateTaxDisplay(); infoText.setText(expenseText); saveGame(); }; viewOwnedButton.up = function (x, y, obj) { if (gameState === 'daily_offers') { gameState = 'owned_vehicles'; stateText.setText('Owned Vehicles & Motorcycles'); displayOwnedVehicles(); } else { gameState = 'daily_offers'; stateText.setText('Daily Vehicle Offers'); displayVehicles(dailyOffers); } selectedVehicle = null; updateUI(); }; loanButton.up = function (x, y, obj) { var loanAmount = 10000; // Check if player can take more loans (credit limit) if (totalLoansOutstanding + loanAmount > creditLimit) { infoText.setText('Loan denied! Credit limit reached.\nCredit limit: $' + creditLimit.toLocaleString() + '\nOutstanding loans: $' + totalLoansOutstanding.toLocaleString()); return; } playerMoney += loanAmount; playerDebt += loanAmount; totalLoansOutstanding += loanAmount; loanTakenDay = currentDay; // Track when loan was taken updateMoneyDisplay(); updateDebtDisplay(); saveGame(); infoText.setText('Loan approved! You received $' + loanAmount.toLocaleString() + '\nDaily interest: 5%\nDue in 5 days or 50% penalty applies'); }; payDebtButton.up = function (x, y, obj) { if (playerDebt > 0 && playerMoney > 0) { var paymentAmount = Math.min(playerMoney, playerDebt); playerMoney -= paymentAmount; playerDebt -= paymentAmount; totalLoansOutstanding -= paymentAmount; // Reduce outstanding loans if (totalLoansOutstanding < 0) totalLoansOutstanding = 0; updateMoneyDisplay(); updateDebtDisplay(); saveGame(); infoText.setText('Paid $' + paymentAmount.toLocaleString() + ' towards debt!\nRemaining debt: $' + playerDebt.toLocaleString()); } else if (playerDebt <= 0) { infoText.setText('You have no debt to pay!'); } else { infoText.setText('You need money to pay your debt!'); } }; payTaxButton.up = function (x, y, obj) { if (taxDebt > 0 && playerMoney > 0) { var paymentAmount = Math.min(playerMoney, taxDebt); playerMoney -= paymentAmount; taxDebt -= paymentAmount; updateMoneyDisplay(); updateTaxDisplay(); saveGame(); infoText.setText('Paid $' + paymentAmount.toLocaleString() + ' towards tax!\nRemaining tax: $' + taxDebt.toLocaleString()); } else if (taxDebt <= 0) { infoText.setText('You have no tax to pay!'); } else { infoText.setText('You need money to pay your tax!'); } }; settingsButton.up = function (x, y, obj) { // Show settings menu gameState = 'settings'; stateText.setText('Settings'); vehicleContainer.removeChildren(); // Create sound effects toggle button var soundToggleText = soundEffectsEnabled ? 'Sound Effects: ON' : 'Sound Effects: OFF'; var soundToggleBtn = new Button(soundToggleText, soundEffectsEnabled ? 0x2ecc71 : 0xe74c3c, 400, 120); soundToggleBtn.x = 0; soundToggleBtn.y = -150; vehicleContainer.addChild(soundToggleBtn); soundToggleBtn.up = function () { soundEffectsEnabled = !soundEffectsEnabled; saveGame(); // Refresh settings menu settingsButton.up(); }; // Create reset game button with warning var resetBtn = new Button('Reset Game', 0xe74c3c, 400, 120); resetBtn.x = 0; resetBtn.y = 150; vehicleContainer.addChild(resetBtn); resetBtn.up = function () { // Show confirmation warning gameState = 'reset_confirmation'; stateText.setText('Reset Confirmation'); vehicleContainer.removeChildren(); var warningText = new Text2('WARNING!\nThis will delete ALL your progress!\nAre you sure?', { size: 48, fill: 0xff0000 }); warningText.anchor.set(0.5, 0.5); warningText.x = 0; warningText.y = -100; vehicleContainer.addChild(warningText); var confirmBtn = new Button('YES - Reset Everything', 0xe74c3c, 400, 120); confirmBtn.x = -250; confirmBtn.y = 100; vehicleContainer.addChild(confirmBtn); confirmBtn.up = function () { // Clear all stored data delete storage.playerMoney; delete storage.currentDay; delete storage.playerDebt; delete storage.creditLimit; delete storage.loanTakenDay; delete storage.totalLoansOutstanding; delete storage.taxDebt; delete storage.taxDueDate; delete storage.taxOverdueDate; delete storage.lastTaxDay; delete storage.vehicleCount; delete storage.vehicleMakes; delete storage.vehicleModels; delete storage.vehicleConditions; delete storage.vehicleActualConditions; delete storage.vehicleMileages; delete storage.vehicleActualMileages; delete storage.vehiclePrices; delete storage.vehicleMarketValues; delete storage.vehicleSellerLying; delete storage.vehicleIds; delete storage.vehicleRepaired; delete storage.vehicleInRepair; delete storage.vehicleRepairCompletionDay; delete storage.vehiclesInRepairCount; delete storage.repairVehicleIds; delete storage.repairCompletionDays; delete storage.repairDurations; delete storage.motorcycleUnlocked; delete storage.motorcycleCount; delete storage.motorcycleMakes; delete storage.motorcycleModels; delete storage.motorcycleConditions; delete storage.motorcycleActualConditions; delete storage.motorcycleMileages; delete storage.motorcycleActualMileages; delete storage.motorcyclePrices; delete storage.motorcycleMarketValues; delete storage.motorcycleSellerLying; delete storage.motorcycleIds; delete storage.motorcycleRepaired; delete storage.motorcycleInRepair; delete storage.motorcycleRepairCompletionDay; delete storage.motorcyclesInRepairCount; delete storage.repairMotoVehicleIds; delete storage.repairMotoCompletionDays; delete storage.repairMotoDurations; delete storage.vanUnlocked; delete storage.vanCount; delete storage.vanMakes; delete storage.vanModels; delete storage.vanConditions; delete storage.vanActualConditions; delete storage.vanMileages; delete storage.vanActualMileages; delete storage.vanPrices; delete storage.vanMarketValues; delete storage.vanSellerLying; delete storage.vanIds; delete storage.vanRepaired; delete storage.vanInRepair; delete storage.vanRepairCompletionDay; delete storage.vansInRepairCount; delete storage.repairVanVehicleIds; delete storage.repairVanCompletionDays; delete storage.repairVanDurations; delete storage.soundEffectsEnabled; // Reset game state to initial values playerMoney = 50000; currentDay = 1; playerDebt = 0; creditLimit = 50000; loanTakenDay = 0; totalLoansOutstanding = 0; taxDebt = 0; taxDueDate = 0; taxOverdueDate = 0; lastTaxDay = 0; ownedVehicles = []; vehiclesInRepair = []; motorcycleUnlocked = false; vanUnlocked = false; ownedMotorcycles = []; ownedVans = []; motorcyclesInRepair = []; vansInRepair = []; vehicleType = 'cars'; selectedVehicle = null; gameState = 'daily_offers'; soundEffectsEnabled = true; vehicleLocksButton.visible = true; // Update UI stateText.setText('Daily Vehicle Offers'); dayText.setText('Day ' + currentDay); updateMoneyDisplay(); updateDebtDisplay(); updateTaxDisplay(); generateDailyOffers(); displayVehicles(dailyOffers); updateUI(); }; var cancelBtn = new Button('NO - Keep Progress', 0x2ecc71, 400, 120); cancelBtn.x = 250; cancelBtn.y = 100; vehicleContainer.addChild(cancelBtn); cancelBtn.up = function () { // Return to settings settingsButton.up(); }; }; var backBtn = new Button('Back', 0x95a5a6, 200, 80); backBtn.x = 0; backBtn.y = 300; vehicleContainer.addChild(backBtn); backBtn.up = function () { gameState = 'daily_offers'; stateText.setText('Daily Vehicle Offers'); displayVehicles(dailyOffers); updateUI(); }; selectedVehicle = null; updateUI(); }; vehicleLocksButton.up = function (x, y, obj) { // Show vehicle locks menu gameState = 'vehicle_locks'; stateText.setText('Vehicle Locks'); vehicleContainer.removeChildren(); // Create unlock buttons for motorcycles and vans if (!motorcycleUnlocked) { var unlockMotoBtn = new Button('Unlock Motorcycles ($100,000)', 0x9b59b6, 400, 120); unlockMotoBtn.x = 0; unlockMotoBtn.y = -100; vehicleContainer.addChild(unlockMotoBtn); unlockMotoBtn.up = function () { if (playerMoney >= 100000) { playerMoney -= 100000; motorcycleUnlocked = true; updateMoneyDisplay(); saveGame(); infoText.setText('Motorcycles unlocked! Motorcycle offers will now appear mixed with car offers.'); LK.effects.flashScreen(0x2ecc71, 1000); // Return to main menu gameState = 'daily_offers'; stateText.setText('Daily Vehicle Offers'); displayVehicles(dailyOffers); updateUI(); vehicleLocksButton.visible = !motorcycleUnlocked || !vanUnlocked; } else { infoText.setText('Not enough money! Need $100,000 to unlock motorcycles.'); } }; } if (!vanUnlocked) { var unlockVanBtn = new Button('Unlock Vans ($250,000)', 0x34495e, 400, 120); unlockVanBtn.x = 0; unlockVanBtn.y = motorcycleUnlocked ? -100 : 50; vehicleContainer.addChild(unlockVanBtn); unlockVanBtn.up = function () { if (playerMoney >= 250000) { playerMoney -= 250000; vanUnlocked = true; updateMoneyDisplay(); saveGame(); infoText.setText('Vans unlocked! Van offers will now appear mixed with other vehicle offers.'); LK.effects.flashScreen(0x2ecc71, 1000); // Return to main menu gameState = 'daily_offers'; stateText.setText('Daily Vehicle Offers'); displayVehicles(dailyOffers); updateUI(); vehicleLocksButton.visible = !motorcycleUnlocked || !vanUnlocked; } else { infoText.setText('Not enough money! Need $250,000 to unlock vans.'); } }; } var backBtn = new Button('Back', 0x95a5a6, 200, 80); backBtn.x = 0; backBtn.y = 200; vehicleContainer.addChild(backBtn); backBtn.up = function () { gameState = 'daily_offers'; stateText.setText('Daily Vehicle Offers'); displayVehicles(dailyOffers); updateUI(); }; selectedVehicle = null; updateUI(); }; // Switch vehicle button functionality removed - vehicles are now mixed together function displayOwnedVehicles() { vehicleContainer.removeChildren(); var allOwnedVehicles = ownedVehicles.concat(ownedMotorcycles).concat(ownedVans); for (var i = 0; i < allOwnedVehicles.length; i++) { var vehicleData = allOwnedVehicles[i]; var isMotorcycle = i >= ownedVehicles.length && i < ownedVehicles.length + ownedMotorcycles.length; var isVan = i >= ownedVehicles.length + ownedMotorcycles.length; var vehicle = new Vehicle(vehicleData, isMotorcycle, isVan); if (vehicleData.repaired) { vehicle.repaired = true; vehicle.updateDisplay(); } vehicle.x = i % 2 * 600 - 300; vehicle.y = Math.floor(i / 2) * 380; vehicleContainer.addChild(vehicle); vehicle.vehicleData = vehicleData; vehicle.down = function (x, y, obj) { selectedVehicle = obj.vehicleData; updateUI(); }; // Add action buttons for each owned vehicle if (vehicleData.inRepair) { // Vehicle is in repair - show status and prevent actions var daysRemaining = 0; // Find repair data to get remaining days var repairArray = isMotorcycle ? motorcyclesInRepair : vehiclesInRepair; for (var rr = 0; rr < repairArray.length; rr++) { if (repairArray[rr].vehicleId === vehicleData.id) { daysRemaining = repairArray[rr].repairDuration; break; } } var repairStatusText = new Text2('IN REPAIR - ' + daysRemaining + ' day(s) remaining', { size: 24, fill: 0xf39c12 }); repairStatusText.anchor.set(0.5, 0.5); repairStatusText.x = 0; repairStatusText.y = 150; vehicle.addChild(repairStatusText); } else if (vehicleData.actualCondition === 'damaged' && !vehicleData.repaired) { // Add repair button with dynamic cost var repairCost = Math.floor(vehicleData.price * (Math.random() * 0.15 + 0.10)); var minRepairCost = isMotorcycle ? 500 : 1000; if (repairCost < minRepairCost) { repairCost = minRepairCost; } var vehicleRepairButton = new Button('Repair ($' + repairCost.toLocaleString() + ')', 0xe67e22, 200, 60); vehicleRepairButton.x = -150; vehicleRepairButton.y = 150; vehicle.addChild(vehicleRepairButton); (function (vehicleData, isMotorcycle) { vehicleRepairButton.up = function (x, y, obj) { // Calculate repair cost based on vehicle price (10-25% of price) var repairCost = Math.floor(vehicleData.price * (Math.random() * 0.15 + 0.10)); // Minimum repair cost based on vehicle type var minRepairCost = isMotorcycle ? 500 : 1000; if (repairCost < minRepairCost) { repairCost = minRepairCost; } if (playerMoney >= repairCost) { playerMoney -= repairCost; // Calculate repair duration based on damage level var repairDuration = 1; // Default 1 day if (vehicleData.actualCondition === 'damaged') { repairDuration = Math.floor(Math.random() * 3) + 1; // 1-3 days for damaged } else if (vehicleData.actualCondition === 'poor') { repairDuration = 1; // 1 day for poor } // Move vehicle to repair shop var repairData = { vehicleId: vehicleData.id, completionDay: currentDay + repairDuration, repairDuration: repairDuration }; if (isMotorcycle) { motorcyclesInRepair.push(repairData); // Update the vehicle data in the ownedMotorcycles array for (var k = 0; k < ownedMotorcycles.length; k++) { if (ownedMotorcycles[k].id === vehicleData.id) { ownedMotorcycles[k].inRepair = true; ownedMotorcycles[k].repairCompletionDay = currentDay + repairDuration; break; } } } else { vehiclesInRepair.push(repairData); // Update the vehicle data in the ownedVehicles array for (var k = 0; k < ownedVehicles.length; k++) { if (ownedVehicles[k].id === vehicleData.id) { ownedVehicles[k].inRepair = true; ownedVehicles[k].repairCompletionDay = currentDay + repairDuration; break; } } } if (soundEffectsEnabled) LK.getSound('repair').play(); updateMoneyDisplay(); displayOwnedVehicles(); updateUI(); saveGame(); infoText.setText('Vehicle sent to repair shop for $' + repairCost.toLocaleString() + '!\nWill be ready in ' + repairDuration + ' day(s).'); } else { infoText.setText('Not enough money! Repair costs $' + repairCost.toLocaleString()); } }; })(vehicleData, isMotorcycle); // Add sell button for damaged vehicles (sell as-is for low price) var damagedSalePrice = Math.floor(vehicleData.marketValue * (Math.random() * 0.20 + 0.30)); var vehicleSellDamagedButton = new Button('Sell LOW ($' + damagedSalePrice.toLocaleString() + ')', 0x8e44ad, 200, 60); vehicleSellDamagedButton.x = 50; vehicleSellDamagedButton.y = 150; vehicle.addChild(vehicleSellDamagedButton); (function (vehicleData, displayedSalePrice, isMotorcycle) { vehicleSellDamagedButton.up = function (x, y, obj) { var salePrice = displayedSalePrice; playerMoney += salePrice; // Remove from appropriate owned vehicles array if (isMotorcycle) { for (var j = 0; j < ownedMotorcycles.length; j++) { if (ownedMotorcycles[j].id === vehicleData.id) { ownedMotorcycles.splice(j, 1); break; } } } else { for (var j = 0; j < ownedVehicles.length; j++) { if (ownedVehicles[j].id === vehicleData.id) { ownedVehicles.splice(j, 1); break; } } } if (soundEffectsEnabled) LK.getSound('sale').play(); selectedVehicle = null; updateMoneyDisplay(); displayOwnedVehicles(); updateUI(); saveGame(); infoText.setText('Sold damaged vehicle for $' + salePrice.toLocaleString() + '! (Low Price - Could have repaired for higher profit)'); }; })(vehicleData, damagedSalePrice, isMotorcycle); } else { // Add sell button with sale price - different pricing for repaired vs unrepaired var salePrice; if (vehicleData.repaired) { // Repaired vehicles sell for 80-95% of market value (high price) salePrice = Math.floor(vehicleData.marketValue * (Math.random() * 0.15 + 0.80)); } else if (vehicleData.actualCondition === 'damaged') { // Damaged vehicles sell for 30-50% of market value (low price) salePrice = Math.floor(vehicleData.marketValue * (Math.random() * 0.20 + 0.30)); } else { // Other conditions sell for 60-80% of market value (medium price) salePrice = Math.floor(vehicleData.marketValue * (Math.random() * 0.20 + 0.60)); } var sellButtonText = 'Sell ($' + salePrice.toLocaleString() + ')'; if (vehicleData.repaired) { sellButtonText += ' HIGH'; } else if (vehicleData.actualCondition === 'damaged') { sellButtonText += ' LOW'; } var vehicleSellButton = new Button(sellButtonText, 0x8e44ad, 200, 60); vehicleSellButton.x = -100; vehicleSellButton.y = 150; vehicle.addChild(vehicleSellButton); (function (vehicleData, displayedSalePrice, isMotorcycle) { vehicleSellButton.up = function (x, y, obj) { var salePrice = displayedSalePrice; playerMoney += salePrice; // Remove from appropriate owned vehicles array if (isMotorcycle) { for (var j = 0; j < ownedMotorcycles.length; j++) { if (ownedMotorcycles[j].id === vehicleData.id) { ownedMotorcycles.splice(j, 1); break; } } } else { for (var j = 0; j < ownedVehicles.length; j++) { if (ownedVehicles[j].id === vehicleData.id) { ownedVehicles.splice(j, 1); break; } } } if (soundEffectsEnabled) LK.getSound('sale').play(); selectedVehicle = null; updateMoneyDisplay(); displayOwnedVehicles(); updateUI(); saveGame(); var sellMessage = 'Sold for $' + salePrice.toLocaleString() + '!'; if (vehicleData.repaired) { sellMessage += ' (Repaired - High Price)'; } else if (vehicleData.actualCondition === 'damaged') { sellMessage += ' (Damaged - Low Price)'; } infoText.setText(sellMessage); }; })(vehicleData, salePrice, isMotorcycle); } } } function displayOwnedMotorcycles() { vehicleContainer.removeChildren(); for (var i = 0; i < ownedMotorcycles.length; i++) { var vehicle = new Vehicle(ownedMotorcycles[i], true); if (ownedMotorcycles[i].repaired) { vehicle.repaired = true; vehicle.updateDisplay(); } vehicle.x = i % 2 * 600 - 300; vehicle.y = Math.floor(i / 2) * 380; vehicleContainer.addChild(vehicle); vehicle.vehicleData = ownedMotorcycles[i]; vehicle.down = function (x, y, obj) { selectedVehicle = obj.vehicleData; updateUI(); }; // Add action buttons for each owned motorcycle if (ownedMotorcycles[i].inRepair) { // Motorcycle is in repair - show status and prevent actions var daysRemaining = 0; // Find repair data to get remaining days for (var rr = 0; rr < motorcyclesInRepair.length; rr++) { if (motorcyclesInRepair[rr].vehicleId === ownedMotorcycles[i].id) { daysRemaining = motorcyclesInRepair[rr].repairDuration; break; } } var repairStatusText = new Text2('IN REPAIR - ' + daysRemaining + ' day(s) remaining', { size: 24, fill: 0xf39c12 }); repairStatusText.anchor.set(0.5, 0.5); repairStatusText.x = 0; repairStatusText.y = 150; vehicle.addChild(repairStatusText); } else if (ownedMotorcycles[i].actualCondition === 'damaged' && !ownedMotorcycles[i].repaired) { // Add repair button with dynamic cost var repairCost = Math.floor(ownedMotorcycles[i].price * (Math.random() * 0.15 + 0.10)); if (repairCost < 500) { repairCost = 500; } var vehicleRepairButton = new Button('Repair ($' + repairCost.toLocaleString() + ')', 0xe67e22, 200, 60); vehicleRepairButton.x = -150; vehicleRepairButton.y = 150; vehicle.addChild(vehicleRepairButton); (function (vehicleData) { vehicleRepairButton.up = function (x, y, obj) { // Calculate repair cost based on vehicle price (10-25% of price) var repairCost = Math.floor(vehicleData.price * (Math.random() * 0.15 + 0.10)); // Minimum repair cost of $500 for motorcycles if (repairCost < 500) { repairCost = 500; } if (playerMoney >= repairCost) { playerMoney -= repairCost; // Calculate repair duration based on damage level var repairDuration = 1; // Default 1 day if (vehicleData.actualCondition === 'damaged') { repairDuration = Math.floor(Math.random() * 3) + 1; // 1-3 days for damaged } else if (vehicleData.actualCondition === 'poor') { repairDuration = 1; // 1 day for poor } // Move motorcycle to repair shop var repairData = { vehicleId: vehicleData.id, completionDay: currentDay + repairDuration, repairDuration: repairDuration }; motorcyclesInRepair.push(repairData); // Update the motorcycle data in the ownedMotorcycles array for (var k = 0; k < ownedMotorcycles.length; k++) { if (ownedMotorcycles[k].id === vehicleData.id) { ownedMotorcycles[k].inRepair = true; ownedMotorcycles[k].repairCompletionDay = currentDay + repairDuration; break; } } if (soundEffectsEnabled) LK.getSound('repair').play(); updateMoneyDisplay(); displayOwnedMotorcycles(); updateUI(); saveGame(); infoText.setText('Motorcycle sent to repair shop for $' + repairCost.toLocaleString() + '!\nWill be ready in ' + repairDuration + ' day(s).'); } else { infoText.setText('Not enough money! Repair costs $' + repairCost.toLocaleString()); } }; })(ownedMotorcycles[i]); // Add sell button for damaged motorcycles (sell as-is for low price) var damagedSalePrice = Math.floor(ownedMotorcycles[i].marketValue * (Math.random() * 0.20 + 0.30)); var vehicleSellDamagedButton = new Button('Sell LOW ($' + damagedSalePrice.toLocaleString() + ')', 0x8e44ad, 200, 60); vehicleSellDamagedButton.x = 50; vehicleSellDamagedButton.y = 150; vehicle.addChild(vehicleSellDamagedButton); (function (vehicleData, displayedSalePrice) { vehicleSellDamagedButton.up = function (x, y, obj) { var salePrice = displayedSalePrice; playerMoney += salePrice; // Remove from owned motorcycles for (var j = 0; j < ownedMotorcycles.length; j++) { if (ownedMotorcycles[j].id === vehicleData.id) { ownedMotorcycles.splice(j, 1); break; } } if (soundEffectsEnabled) LK.getSound('sale').play(); selectedVehicle = null; updateMoneyDisplay(); displayOwnedMotorcycles(); updateUI(); saveGame(); infoText.setText('Sold damaged motorcycle for $' + salePrice.toLocaleString() + '! (Low Price - Could have repaired for higher profit)'); }; })(ownedMotorcycles[i], damagedSalePrice); } else { // Add sell button with sale price - different pricing for repaired vs unrepaired var salePrice; if (ownedMotorcycles[i].repaired) { // Repaired motorcycles sell for 80-95% of market value (high price) salePrice = Math.floor(ownedMotorcycles[i].marketValue * (Math.random() * 0.15 + 0.80)); } else if (ownedMotorcycles[i].actualCondition === 'damaged') { // Damaged motorcycles sell for 30-50% of market value (low price) salePrice = Math.floor(ownedMotorcycles[i].marketValue * (Math.random() * 0.20 + 0.30)); } else { // Other conditions sell for 60-80% of market value (medium price) salePrice = Math.floor(ownedMotorcycles[i].marketValue * (Math.random() * 0.20 + 0.60)); } var sellButtonText = 'Sell ($' + salePrice.toLocaleString() + ')'; if (ownedMotorcycles[i].repaired) { sellButtonText += ' HIGH'; } else if (ownedMotorcycles[i].actualCondition === 'damaged') { sellButtonText += ' LOW'; } var vehicleSellButton = new Button(sellButtonText, 0x8e44ad, 200, 60); vehicleSellButton.x = -100; vehicleSellButton.y = 150; vehicle.addChild(vehicleSellButton); (function (vehicleData, displayedSalePrice) { vehicleSellButton.up = function (x, y, obj) { var salePrice = displayedSalePrice; playerMoney += salePrice; // Remove from owned motorcycles for (var j = 0; j < ownedMotorcycles.length; j++) { if (ownedMotorcycles[j].id === vehicleData.id) { ownedMotorcycles.splice(j, 1); break; } } if (soundEffectsEnabled) LK.getSound('sale').play(); selectedVehicle = null; updateMoneyDisplay(); displayOwnedMotorcycles(); updateUI(); saveGame(); var sellMessage = 'Sold for $' + salePrice.toLocaleString() + '!'; if (vehicleData.repaired) { sellMessage += ' (Repaired - High Price)'; } else if (vehicleData.actualCondition === 'damaged') { sellMessage += ' (Damaged - Low Price)'; } infoText.setText(sellMessage); }; })(ownedMotorcycles[i], salePrice); } } } function updateMoneyDisplay() { moneyText.setText('Money: $' + playerMoney.toLocaleString()); } function updateDebtDisplay() { debtText.setText('Debt: $' + playerDebt.toLocaleString()); if (playerDebt > 0) { debtText.tint = 0xe74c3c; // Red for debt } else { debtText.tint = 0x2ecc71; // Green for no debt } } function updateTaxDisplay() { taxText.setText('Tax: $' + taxDebt.toLocaleString()); if (taxDebt > 0) { taxText.tint = 0xe74c3c; // Red for tax debt } else { taxText.tint = 0x2ecc71; // Green for no tax } } function saveGame() { storage.playerMoney = playerMoney; storage.currentDay = currentDay; storage.playerDebt = playerDebt; storage.creditLimit = creditLimit; storage.loanTakenDay = loanTakenDay; storage.totalLoansOutstanding = totalLoansOutstanding; storage.taxDebt = taxDebt; storage.taxDueDate = taxDueDate; storage.taxOverdueDate = taxOverdueDate; storage.lastTaxDay = lastTaxDay; storage.motorcycleUnlocked = motorcycleUnlocked; storage.vanUnlocked = vanUnlocked; storage.soundEffectsEnabled = soundEffectsEnabled; // Store each vehicle property as separate arrays to avoid nested objects var vehicleCount = ownedVehicles.length; storage.vehicleCount = vehicleCount; storage.vehicleMakes = []; storage.vehicleModels = []; storage.vehicleConditions = []; storage.vehicleActualConditions = []; storage.vehicleMileages = []; storage.vehicleActualMileages = []; storage.vehiclePrices = []; storage.vehicleMarketValues = []; storage.vehicleSellerLying = []; storage.vehicleIds = []; storage.vehicleRepaired = []; storage.vehicleInRepair = []; storage.vehicleRepairCompletionDay = []; for (var i = 0; i < ownedVehicles.length; i++) { var vehicle = ownedVehicles[i]; storage.vehicleMakes.push(vehicle.make); storage.vehicleModels.push(vehicle.model); storage.vehicleConditions.push(vehicle.condition); storage.vehicleActualConditions.push(vehicle.actualCondition); storage.vehicleMileages.push(vehicle.mileage); storage.vehicleActualMileages.push(vehicle.actualMileage); storage.vehiclePrices.push(vehicle.price); storage.vehicleMarketValues.push(vehicle.marketValue); storage.vehicleSellerLying.push(vehicle.sellerLying); storage.vehicleIds.push(vehicle.id); storage.vehicleRepaired.push(vehicle.repaired || false); storage.vehicleInRepair.push(vehicle.inRepair || false); storage.vehicleRepairCompletionDay.push(vehicle.repairCompletionDay || 0); } // Save repair shop data storage.vehiclesInRepairCount = vehiclesInRepair.length; storage.repairVehicleIds = []; storage.repairCompletionDays = []; storage.repairDurations = []; for (var r = 0; r < vehiclesInRepair.length; r++) { storage.repairVehicleIds.push(vehiclesInRepair[r].vehicleId); storage.repairCompletionDays.push(vehiclesInRepair[r].completionDay); storage.repairDurations.push(vehiclesInRepair[r].repairDuration); } // Save motorcycle data var motorcycleCount = ownedMotorcycles.length; storage.motorcycleCount = motorcycleCount; storage.motorcycleMakes = []; storage.motorcycleModels = []; storage.motorcycleConditions = []; storage.motorcycleActualConditions = []; storage.motorcycleMileages = []; storage.motorcycleActualMileages = []; storage.motorcyclePrices = []; storage.motorcycleMarketValues = []; storage.motorcycleSellerLying = []; storage.motorcycleIds = []; storage.motorcycleRepaired = []; storage.motorcycleInRepair = []; storage.motorcycleRepairCompletionDay = []; for (var m = 0; m < ownedMotorcycles.length; m++) { var motorcycle = ownedMotorcycles[m]; storage.motorcycleMakes.push(motorcycle.make); storage.motorcycleModels.push(motorcycle.model); storage.motorcycleConditions.push(motorcycle.condition); storage.motorcycleActualConditions.push(motorcycle.actualCondition); storage.motorcycleMileages.push(motorcycle.mileage); storage.motorcycleActualMileages.push(motorcycle.actualMileage); storage.motorcyclePrices.push(motorcycle.price); storage.motorcycleMarketValues.push(motorcycle.marketValue); storage.motorcycleSellerLying.push(motorcycle.sellerLying); storage.motorcycleIds.push(motorcycle.id); storage.motorcycleRepaired.push(motorcycle.repaired || false); storage.motorcycleInRepair.push(motorcycle.inRepair || false); storage.motorcycleRepairCompletionDay.push(motorcycle.repairCompletionDay || 0); } // Save motorcycle repair shop data storage.motorcyclesInRepairCount = motorcyclesInRepair.length; storage.repairMotoVehicleIds = []; storage.repairMotoCompletionDays = []; storage.repairMotoDurations = []; for (var mr = 0; mr < motorcyclesInRepair.length; mr++) { storage.repairMotoVehicleIds.push(motorcyclesInRepair[mr].vehicleId); storage.repairMotoCompletionDays.push(motorcyclesInRepair[mr].completionDay); storage.repairMotoDurations.push(motorcyclesInRepair[mr].repairDuration); } // Save van data var vanCount = ownedVans.length; storage.vanCount = vanCount; storage.vanMakes = []; storage.vanModels = []; storage.vanConditions = []; storage.vanActualConditions = []; storage.vanMileages = []; storage.vanActualMileages = []; storage.vanPrices = []; storage.vanMarketValues = []; storage.vanSellerLying = []; storage.vanIds = []; storage.vanRepaired = []; storage.vanInRepair = []; storage.vanRepairCompletionDay = []; for (var v = 0; v < ownedVans.length; v++) { var van = ownedVans[v]; storage.vanMakes.push(van.make); storage.vanModels.push(van.model); storage.vanConditions.push(van.condition); storage.vanActualConditions.push(van.actualCondition); storage.vanMileages.push(van.mileage); storage.vanActualMileages.push(van.actualMileage); storage.vanPrices.push(van.price); storage.vanMarketValues.push(van.marketValue); storage.vanSellerLying.push(van.sellerLying); storage.vanIds.push(van.id); storage.vanRepaired.push(van.repaired || false); storage.vanInRepair.push(van.inRepair || false); storage.vanRepairCompletionDay.push(van.repairCompletionDay || 0); } // Save van repair shop data storage.vansInRepairCount = vansInRepair.length; storage.repairVanVehicleIds = []; storage.repairVanCompletionDays = []; storage.repairVanDurations = []; for (var vr = 0; vr < vansInRepair.length; vr++) { storage.repairVanVehicleIds.push(vansInRepair[vr].vehicleId); storage.repairVanCompletionDays.push(vansInRepair[vr].completionDay); storage.repairVanDurations.push(vansInRepair[vr].repairDuration); } } // Add maintenance costs for owned vehicles function applyMaintenanceCosts() { var totalMaintenanceCost = 0; for (var i = 0; i < ownedVehicles.length; i++) { var vehicle = ownedVehicles[i]; // Higher maintenance cost for damaged vehicles var baseCost = vehicle.actualCondition === 'damaged' ? 200 : 100; var maintenanceCost = Math.floor(Math.random() * baseCost) + 50; totalMaintenanceCost += maintenanceCost; } if (totalMaintenanceCost > 0) { playerMoney -= totalMaintenanceCost; return totalMaintenanceCost; } return 0; } // Apply vehicle depreciation function applyVehicleDepreciation() { for (var i = 0; i < ownedVehicles.length; i++) { var vehicle = ownedVehicles[i]; // Vehicles lose 2-5% of their market value each day var depreciationRate = Math.random() * 0.03 + 0.02; vehicle.marketValue = Math.floor(vehicle.marketValue * (1 - depreciationRate)); // Minimum market value floor if (vehicle.marketValue < 1000) { vehicle.marketValue = 1000; } } } // Initialize game updateDebtDisplay(); updateTaxDisplay(); generateDailyOffers(); if (motorcycleUnlocked) { generateDailyMotoOffers(); } displayVehicles(dailyOffers); updateUI(); // Game restart function function restartGame() { // Reset all game state variables to initial values playerMoney = 50000; currentDay = 1; playerDebt = 0; taxDebt = 0; taxDueDate = 0; taxOverdueDate = 0; lastTaxDay = 0; ownedVehicles = []; vehiclesInRepair = []; motorcycleUnlocked = false; ownedMotorcycles = []; motorcyclesInRepair = []; vehicleType = 'cars'; selectedVehicle = null; gameState = 'daily_offers'; vehicleLocksButton.visible = !motorcycleUnlocked || !vanUnlocked; // Clear storage delete storage.playerMoney; delete storage.currentDay; delete storage.playerDebt; delete storage.taxDebt; delete storage.taxDueDate; delete storage.taxOverdueDate; delete storage.lastTaxDay; delete storage.vehicleCount; delete storage.vehicleMakes; delete storage.vehicleModels; delete storage.vehicleConditions; delete storage.vehicleActualConditions; delete storage.vehicleMileages; delete storage.vehicleActualMileages; delete storage.vehiclePrices; delete storage.vehicleMarketValues; delete storage.vehicleSellerLying; delete storage.vehicleIds; delete storage.vehicleRepaired; delete storage.vehicleInRepair; delete storage.vehicleRepairCompletionDay; delete storage.vehiclesInRepairCount; delete storage.repairVehicleIds; delete storage.repairCompletionDays; delete storage.repairDurations; delete storage.motorcycleUnlocked; delete storage.motorcycleCount; delete storage.motorcycleMakes; delete storage.motorcycleModels; delete storage.motorcycleConditions; delete storage.motorcycleActualConditions; delete storage.motorcycleMileages; delete storage.motorcycleActualMileages; delete storage.motorcyclePrices; delete storage.motorcycleMarketValues; delete storage.motorcycleSellerLying; delete storage.motorcycleIds; delete storage.motorcycleRepaired; delete storage.motorcycleInRepair; delete storage.motorcycleRepairCompletionDay; delete storage.motorcyclesInRepairCount; delete storage.repairMotoVehicleIds; delete storage.repairMotoCompletionDays; delete storage.repairMotoDurations; // Update UI elements stateText.setText('Daily Vehicle Offers'); dayText.setText('Day ' + currentDay); updateMoneyDisplay(); updateDebtDisplay(); updateTaxDisplay(); generateDailyOffers(); displayVehicles(dailyOffers); updateUI(); infoText.setText('Game restarted! Welcome back to Car Dealer Tycoon!'); } // Game update loop game.update = function () { // Check for game over condition if (playerMoney < 0) { LK.showGameOver(); // Reset game state for restart restartGame(); } // Check for winning condition if (playerMoney >= 500000) { LK.showYouWin(); // Reset game state for restart restartGame(); } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Button = Container.expand(function (text, color, width, height) {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
width: width || 300,
height: height || 120
});
buttonGraphics.tint = color || 0x27ae60;
var buttonText = new Text2(text, {
size: 32,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
buttonText.x = 0;
buttonText.y = 0;
self.addChild(buttonText);
self.down = function (x, y, obj) {
buttonGraphics.scaleX = 0.9;
buttonGraphics.scaleY = 0.9;
};
self.up = function (x, y, obj) {
buttonGraphics.scaleX = 1.0;
buttonGraphics.scaleY = 1.0;
};
return self;
});
var Vehicle = Container.expand(function (carData, isMotorcycle, isVan) {
var self = Container.call(this);
self.carData = carData;
self.inspected = false;
self.repaired = false;
self.isMotorcycle = isMotorcycle || false;
self.isVan = isVan || false;
var assetPrefix = self.isVan ? 'van' : self.isMotorcycle ? 'moto' : 'car';
var assetSuffix = carData.condition === 'damaged' ? 'Damaged' : 'Offer';
var carGraphics = self.attachAsset(assetPrefix + assetSuffix, {
anchorX: 0.5,
anchorY: 0.5
});
var carText = new Text2(carData.make + ' ' + carData.model, {
size: 36,
fill: 0xFFFFFF
});
carText.anchor.set(0.5, 0.5);
carText.x = 0;
carText.y = -80;
self.addChild(carText);
var priceText = new Text2('$' + carData.price.toLocaleString(), {
size: 40,
fill: 0xFFFF00
});
priceText.anchor.set(0.5, 0.5);
priceText.x = 0;
priceText.y = -40;
self.addChild(priceText);
var conditionText = new Text2(carData.condition + ' - ' + carData.mileage + 'k miles', {
size: 28,
fill: 0xFFFFFF
});
conditionText.anchor.set(0.5, 0.5);
conditionText.x = 0;
conditionText.y = 10;
self.addChild(conditionText);
self.updateDisplay = function () {
carGraphics.visible = false;
self.removeChild(carGraphics);
var assetPrefix = self.isVan ? 'van' : self.isMotorcycle ? 'moto' : 'car';
var assetType = assetPrefix + 'Offer';
if (self.carData.actualCondition === 'damaged' && !self.repaired) {
assetType = assetPrefix + 'Damaged';
} else if (self.repaired) {
assetType = assetPrefix + 'Repaired';
}
carGraphics = self.attachAsset(assetType, {
anchorX: 0.5,
anchorY: 0.5
});
// Re-create and re-add text elements to ensure they are properly displayed
if (carText && carText.parent) {
self.removeChild(carText);
}
carText = new Text2(self.carData.make + ' ' + self.carData.model, {
size: 36,
fill: 0xFFFFFF
});
carText.anchor.set(0.5, 0.5);
carText.x = 0;
carText.y = -80;
self.addChild(carText);
if (priceText && priceText.parent) {
self.removeChild(priceText);
}
priceText = new Text2('$' + self.carData.price.toLocaleString(), {
size: 40,
fill: 0xFFFF00
});
priceText.anchor.set(0.5, 0.5);
priceText.x = 0;
priceText.y = -40;
self.addChild(priceText);
if (conditionText && conditionText.parent) {
self.removeChild(conditionText);
}
// Use actual condition and mileage for display
var displayCondition = self.repaired ? 'good' : self.carData.actualCondition;
var displayMileage = self.carData.actualMileage || self.carData.mileage;
conditionText = new Text2(displayCondition + ' - ' + displayMileage + 'k miles', {
size: 28,
fill: 0xFFFFFF
});
conditionText.anchor.set(0.5, 0.5);
conditionText.x = 0;
conditionText.y = 10;
self.addChild(conditionText);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x34495e
});
/****
* Game Code
****/
// Game state variables
var playerMoney = storage.playerMoney || 50000;
var currentDay = storage.currentDay || 1;
var playerDebt = storage.playerDebt || 0;
var dailyInterestRate = 0.05; // 5% daily interest
var creditLimit = storage.creditLimit || 50000; // Maximum credit limit
var loanTakenDay = storage.loanTakenDay || 0; // Day when last loan was taken
var totalLoansOutstanding = storage.totalLoansOutstanding || 0; // Total amount in loans
var taxDebt = storage.taxDebt || 0;
var taxDueDate = storage.taxDueDate || 0;
var taxOverdueDate = storage.taxOverdueDate || 0;
var lastTaxDay = storage.lastTaxDay || 0;
var ownedVehicles = [];
var vehiclesInRepair = []; // Track vehicles currently being repaired
var motorcycleUnlocked = storage.motorcycleUnlocked || false;
var vanUnlocked = storage.vanUnlocked || false;
var soundEffectsEnabled = storage.soundEffectsEnabled !== undefined ? storage.soundEffectsEnabled : true;
var ownedMotorcycles = [];
var ownedVans = [];
var motorcyclesInRepair = []; // Track motorcycles currently being repaired
var vansInRepair = []; // Track vans currently being repaired
var dailyMotoOffers = [];
var vehicleType = 'cars'; // 'cars' or 'motorcycles'
// Load owned vehicles from storage
if (storage.vehicleCount) {
for (var i = 0; i < storage.vehicleCount; i++) {
ownedVehicles.push({
make: storage.vehicleMakes[i],
model: storage.vehicleModels[i],
condition: storage.vehicleConditions[i],
actualCondition: storage.vehicleActualConditions[i],
mileage: storage.vehicleMileages[i],
actualMileage: storage.vehicleActualMileages[i] || storage.vehicleMileages[i],
price: storage.vehiclePrices[i],
marketValue: storage.vehicleMarketValues[i],
sellerLying: storage.vehicleSellerLying[i],
id: storage.vehicleIds[i],
repaired: storage.vehicleRepaired[i],
inRepair: storage.vehicleInRepair ? storage.vehicleInRepair[i] : false,
repairCompletionDay: storage.vehicleRepairCompletionDay ? storage.vehicleRepairCompletionDay[i] : 0
});
}
}
// Load repair shop data
if (storage.vehiclesInRepairCount) {
for (var r = 0; r < storage.vehiclesInRepairCount; r++) {
vehiclesInRepair.push({
vehicleId: storage.repairVehicleIds[r],
completionDay: storage.repairCompletionDays[r],
repairDuration: storage.repairDurations[r]
});
}
}
// Load owned motorcycles from storage
if (storage.motorcycleCount) {
for (var m = 0; m < storage.motorcycleCount; m++) {
ownedMotorcycles.push({
make: storage.motorcycleMakes[m],
model: storage.motorcycleModels[m],
condition: storage.motorcycleConditions[m],
actualCondition: storage.motorcycleActualConditions[m],
mileage: storage.motorcycleMileages[m],
actualMileage: storage.motorcycleActualMileages[m] || storage.motorcycleMileages[m],
price: storage.motorcyclePrices[m],
marketValue: storage.motorcycleMarketValues[m],
sellerLying: storage.motorcycleSellerLying[m],
id: storage.motorcycleIds[m],
repaired: storage.motorcycleRepaired[m],
inRepair: storage.motorcycleInRepair ? storage.motorcycleInRepair[m] : false,
repairCompletionDay: storage.motorcycleRepairCompletionDay ? storage.motorcycleRepairCompletionDay[m] : 0
});
}
}
// Load motorcycle repair shop data
if (storage.motorcyclesInRepairCount) {
for (var mr = 0; mr < storage.motorcyclesInRepairCount; mr++) {
motorcyclesInRepair.push({
vehicleId: storage.repairMotoVehicleIds[mr],
completionDay: storage.repairMotoCompletionDays[mr],
repairDuration: storage.repairMotoDurations[mr]
});
}
}
// Load owned vans from storage
if (storage.vanCount) {
for (var v = 0; v < storage.vanCount; v++) {
ownedVans.push({
make: storage.vanMakes[v],
model: storage.vanModels[v],
condition: storage.vanConditions[v],
actualCondition: storage.vanActualConditions[v],
mileage: storage.vanMileages[v],
actualMileage: storage.vanActualMileages[v] || storage.vanMileages[v],
price: storage.vanPrices[v],
marketValue: storage.vanMarketValues[v],
sellerLying: storage.vanSellerLying[v],
id: storage.vanIds[v],
repaired: storage.vanRepaired[v],
inRepair: storage.vanInRepair ? storage.vanInRepair[v] : false,
repairCompletionDay: storage.vanRepairCompletionDay ? storage.vanRepairCompletionDay[v] : 0
});
}
}
// Load van repair shop data
if (storage.vansInRepairCount) {
for (var vr = 0; vr < storage.vansInRepairCount; vr++) {
vansInRepair.push({
vehicleId: storage.repairVanVehicleIds[vr],
completionDay: storage.repairVanCompletionDays[vr],
repairDuration: storage.repairVanDurations[vr]
});
}
}
var dailyOffers = [];
var selectedVehicle = null;
var gameState = 'daily_offers'; // 'daily_offers', 'vehicle_selected', 'owned_vehicles'
// Car data arrays
var carMakes = ['Toyota', 'Honda', 'Ford', 'Chevrolet', 'BMW', 'Mercedes', 'Audi', 'Nissan', 'Volkswagen', 'Hyundai'];
var carModels = ['Sedan', 'SUV', 'Coupe', 'Hatchback', 'Wagon', 'Convertible', 'Truck', 'Compact'];
var conditions = ['excellent', 'good', 'fair', 'poor', 'damaged'];
// Motorcycle data arrays
var motoMakes = ['Harley-Davidson', 'Yamaha', 'Honda', 'Kawasaki', 'Suzuki', 'Ducati', 'BMW', 'Triumph', 'Indian', 'KTM'];
var motoModels = ['Cruiser', 'Sport', 'Touring', 'Adventure', 'Naked', 'Chopper', 'Cafe Racer', 'Scooter'];
// Van data arrays
var vanMakes = ['Ford', 'Chevrolet', 'Mercedes', 'Nissan', 'Isuzu', 'Ram', 'Iveco', 'Volkswagen', 'Toyota', 'Peugeot'];
var vanModels = ['Transit', 'Express', 'Sprinter', 'ProMaster', 'NV200', 'Cargo Van', 'Panel Van', 'Box Truck'];
// UI Elements
var moneyText = new Text2('Money: $' + playerMoney.toLocaleString(), {
size: 50,
fill: 0x2ECC71
});
moneyText.anchor.set(0, 0);
moneyText.x = 120;
moneyText.y = 50;
LK.gui.topLeft.addChild(moneyText);
var dayText = new Text2('Day ' + currentDay, {
size: 50,
fill: 0xFFFFFF
});
dayText.anchor.set(1, 0);
dayText.x = 0;
dayText.y = 50;
LK.gui.topRight.addChild(dayText);
var debtText = new Text2('Debt: $' + playerDebt.toLocaleString(), {
size: 40,
fill: 0xe74c3c
});
debtText.anchor.set(0, 0);
debtText.x = 120;
debtText.y = 110;
LK.gui.topLeft.addChild(debtText);
var taxText = new Text2('Tax: $' + taxDebt.toLocaleString(), {
size: 40,
fill: 0xe74c3c
});
taxText.anchor.set(0, 0);
taxText.x = 120;
taxText.y = 170;
LK.gui.topLeft.addChild(taxText);
var titleText = new Text2('Car Dealer Tycoon', {
size: 80,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0);
titleText.x = 2048 / 2;
titleText.y = 150;
game.addChild(titleText);
var stateText = new Text2('Daily Vehicle Offers', {
size: 50,
fill: 0xECF0F1
});
stateText.anchor.set(0.5, 0);
stateText.x = 2048 / 2;
stateText.y = 250;
game.addChild(stateText);
// Action buttons
var inspectButton = game.addChild(new Button('Inspect ($500)', 0xf39c12));
inspectButton.x = 2048 / 2 - 400;
inspectButton.y = 2200;
inspectButton.visible = false;
var buyButton = game.addChild(new Button('Buy Vehicle', 0x27ae60));
buyButton.x = 2048 / 2 - 150;
buyButton.y = 2200;
buyButton.visible = false;
var negotiateButton = game.addChild(new Button('Negotiate', 0x34495e));
negotiateButton.x = 2048 / 2 + 150;
negotiateButton.y = 2200;
negotiateButton.visible = false;
var repairButton = game.addChild(new Button('Repair (Dynamic)', 0xe67e22));
repairButton.x = 2048 / 2 - 150;
repairButton.y = 2200;
repairButton.visible = false;
var sellButton = game.addChild(new Button('Sell', 0x8e44ad));
sellButton.x = 2048 / 2 + 150;
sellButton.y = 2200;
sellButton.visible = false;
var nextDayButton = game.addChild(new Button('Next Day', 0x2c3e50, 400, 140));
nextDayButton.x = 2048 / 2;
nextDayButton.y = 2350;
var viewOwnedButton = game.addChild(new Button('View Owned Cars', 0x95a5a6));
viewOwnedButton.x = 2048 / 2;
viewOwnedButton.y = 2200;
var loanButton = game.addChild(new Button('Take Loan ($10,000)', 0x3498db));
loanButton.x = 2048 / 2 - 450;
loanButton.y = 2550;
var payDebtButton = game.addChild(new Button('Pay Debt', 0x27ae60));
payDebtButton.x = 2048 / 2 + 3;
payDebtButton.y = 2500;
var payTaxButton = game.addChild(new Button('Pay Tax', 0x27ae60));
payTaxButton.x = 2048 / 2 + 450;
payTaxButton.y = 2550;
var vehicleLocksButton = game.addChild(new Button('Vehicle Locks', 0x7f8c8d, 300, 120));
vehicleLocksButton.x = 1600;
vehicleLocksButton.y = 2400;
vehicleLocksButton.visible = !motorcycleUnlocked || !vanUnlocked;
var settingsButton = game.addChild(new Button('Settings', 0x7f8c8d, 300, 120));
settingsButton.x = -200;
settingsButton.y = 200;
LK.gui.topRight.addChild(settingsButton);
// Switch vehicle button removed - vehicles are now mixed together
// Vehicle display containers
var vehicleContainer = new Container();
vehicleContainer.x = 2048 / 2;
vehicleContainer.y = 800;
game.addChild(vehicleContainer);
var infoText = new Text2('', {
size: 32,
fill: 0xFFFFFF
});
infoText.anchor.set(0.5, 0.5);
infoText.x = 2048 / 2;
infoText.y = 1800;
game.addChild(infoText);
// Generate random vehicle data
function generateRandomVehicle() {
var make = carMakes[Math.floor(Math.random() * carMakes.length)];
var model = carModels[Math.floor(Math.random() * carModels.length)];
var condition = conditions[Math.floor(Math.random() * conditions.length)];
var mileage = Math.floor(Math.random() * 200) + 20;
var basePrice = Math.floor(Math.random() * 40000) + 10000;
// Sellers may lie about condition - both ways
var actualCondition = condition;
var actualMileage = mileage;
var sellerLying = Math.random() < 0.4; // 40% chance of lying
if (sellerLying) {
// 70% chance they claim better condition, 30% chance they hide damage
if (Math.random() < 0.7 && condition !== 'damaged') {
// Claim better condition than actual
var betterConditions = conditions.slice(0, conditions.indexOf(condition));
if (betterConditions.length > 0) {
condition = betterConditions[Math.floor(Math.random() * betterConditions.length)];
}
} else {
// Hide damage - claim undamaged when actually damaged
var worseConditions = conditions.slice(conditions.indexOf(condition) + 1);
if (worseConditions.length > 0) {
actualCondition = worseConditions[Math.floor(Math.random() * worseConditions.length)];
// If actual condition becomes damaged, they claim it's not
if (actualCondition === 'damaged') {
condition = 'poor'; // They claim it's just poor condition
}
}
}
}
// 30% chance they also lie about mileage
if (Math.random() < 0.3) {
// They claim lower mileage than actual
var mileageReduction = Math.floor(Math.random() * 50) + 10; // 10-60k miles less
actualMileage = mileage + mileageReduction;
// Cap at reasonable maximum
if (actualMileage > 300) {
actualMileage = 300;
}
}
// Adjust price based on condition
var priceMultiplier = 1;
switch (actualCondition) {
case 'excellent':
priceMultiplier = 1.2;
break;
case 'good':
priceMultiplier = 1.0;
break;
case 'fair':
priceMultiplier = 0.8;
break;
case 'poor':
priceMultiplier = 0.6;
break;
case 'damaged':
priceMultiplier = 0.4;
break;
}
var price = Math.floor(basePrice * priceMultiplier * (1 - mileage / 300));
// 15% chance that this seller is a scammer
var isScammer = Math.random() < 0.15;
return {
make: make,
model: model,
condition: condition,
actualCondition: actualCondition,
mileage: mileage,
actualMileage: actualMileage,
price: price,
marketValue: Math.floor(price * 1.5),
sellerLying: sellerLying,
isScammer: isScammer,
id: Math.random().toString(36).substr(2, 9)
};
}
// Generate random motorcycle data
function generateRandomMotorcycle() {
var make = motoMakes[Math.floor(Math.random() * motoMakes.length)];
var model = motoModels[Math.floor(Math.random() * motoModels.length)];
var condition = conditions[Math.floor(Math.random() * conditions.length)];
var mileage = Math.floor(Math.random() * 150) + 10; // Lower mileage for motorcycles
var basePrice = Math.floor(Math.random() * 30000) + 5000; // Lower price range for motorcycles
// Sellers may lie about condition - both ways
var actualCondition = condition;
var actualMileage = mileage;
var sellerLying = Math.random() < 0.4; // 40% chance of lying
if (sellerLying) {
// 70% chance they claim better condition, 30% chance they hide damage
if (Math.random() < 0.7 && condition !== 'damaged') {
// Claim better condition than actual
var betterConditions = conditions.slice(0, conditions.indexOf(condition));
if (betterConditions.length > 0) {
condition = betterConditions[Math.floor(Math.random() * betterConditions.length)];
}
} else {
// Hide damage - claim undamaged when actually damaged
var worseConditions = conditions.slice(conditions.indexOf(condition) + 1);
if (worseConditions.length > 0) {
actualCondition = worseConditions[Math.floor(Math.random() * worseConditions.length)];
// If actual condition becomes damaged, they claim it's not
if (actualCondition === 'damaged') {
condition = 'poor'; // They claim it's just poor condition
}
}
}
}
// 30% chance they also lie about mileage
if (Math.random() < 0.3) {
// They claim lower mileage than actual
var mileageReduction = Math.floor(Math.random() * 40) + 10; // 10-50k miles less
actualMileage = mileage + mileageReduction;
// Cap at reasonable maximum
if (actualMileage > 200) {
actualMileage = 200;
}
}
// Adjust price based on condition
var priceMultiplier = 1;
switch (actualCondition) {
case 'excellent':
priceMultiplier = 1.2;
break;
case 'good':
priceMultiplier = 1.0;
break;
case 'fair':
priceMultiplier = 0.8;
break;
case 'poor':
priceMultiplier = 0.6;
break;
case 'damaged':
priceMultiplier = 0.4;
break;
}
var price = Math.floor(basePrice * priceMultiplier * (1 - mileage / 200));
// 15% chance that this seller is a scammer
var isScammer = Math.random() < 0.15;
return {
make: make,
model: model,
condition: condition,
actualCondition: actualCondition,
mileage: mileage,
actualMileage: actualMileage,
price: price,
marketValue: Math.floor(price * 1.5),
sellerLying: sellerLying,
isScammer: isScammer,
id: Math.random().toString(36).substr(2, 9)
};
}
// Generate random van data
function generateRandomVan() {
var make = vanMakes[Math.floor(Math.random() * vanMakes.length)];
var model = vanModels[Math.floor(Math.random() * vanModels.length)];
var condition = conditions[Math.floor(Math.random() * conditions.length)];
var mileage = Math.floor(Math.random() * 250) + 30; // Higher mileage for vans
var basePrice = Math.floor(Math.random() * 50000) + 20000; // Higher price range for vans
// Sellers may lie about condition - both ways
var actualCondition = condition;
var actualMileage = mileage;
var sellerLying = Math.random() < 0.4; // 40% chance of lying
if (sellerLying) {
// 70% chance they claim better condition, 30% chance they hide damage
if (Math.random() < 0.7 && condition !== 'damaged') {
// Claim better condition than actual
var betterConditions = conditions.slice(0, conditions.indexOf(condition));
if (betterConditions.length > 0) {
condition = betterConditions[Math.floor(Math.random() * betterConditions.length)];
}
} else {
// Hide damage - claim undamaged when actually damaged
var worseConditions = conditions.slice(conditions.indexOf(condition) + 1);
if (worseConditions.length > 0) {
actualCondition = worseConditions[Math.floor(Math.random() * worseConditions.length)];
// If actual condition becomes damaged, they claim it's not
if (actualCondition === 'damaged') {
condition = 'poor'; // They claim it's just poor condition
}
}
}
}
// 30% chance they also lie about mileage
if (Math.random() < 0.3) {
// They claim lower mileage than actual
var mileageReduction = Math.floor(Math.random() * 60) + 20; // 20-80k miles less
actualMileage = mileage + mileageReduction;
// Cap at reasonable maximum
if (actualMileage > 400) {
actualMileage = 400;
}
}
// Adjust price based on condition
var priceMultiplier = 1;
switch (actualCondition) {
case 'excellent':
priceMultiplier = 1.2;
break;
case 'good':
priceMultiplier = 1.0;
break;
case 'fair':
priceMultiplier = 0.8;
break;
case 'poor':
priceMultiplier = 0.6;
break;
case 'damaged':
priceMultiplier = 0.4;
break;
}
var price = Math.floor(basePrice * priceMultiplier * (1 - mileage / 400));
// 15% chance that this seller is a scammer
var isScammer = Math.random() < 0.15;
return {
make: make,
model: model,
condition: condition,
actualCondition: actualCondition,
mileage: mileage,
actualMileage: actualMileage,
price: price,
marketValue: Math.floor(price * 1.5),
sellerLying: sellerLying,
isScammer: isScammer,
id: Math.random().toString(36).substr(2, 9),
isVan: true
};
}
// Generate daily offers (mixed cars and motorcycles if unlocked)
function generateDailyOffers() {
dailyOffers = [];
var numOffers = Math.floor(Math.random() * 3) + 2;
for (var i = 0; i < numOffers; i++) {
var randomType = Math.random();
// If both motorcycles and vans are unlocked
if (motorcycleUnlocked && vanUnlocked) {
if (randomType < 0.3) {
// 30% chance for motorcycle
var motoOffer = generateRandomMotorcycle();
motoOffer.isMotorcycle = true;
dailyOffers.push(motoOffer);
} else if (randomType < 0.5) {
// 20% chance for van
var vanOffer = generateRandomVan();
vanOffer.isVan = true;
dailyOffers.push(vanOffer);
} else {
// 50% chance for car
dailyOffers.push(generateRandomVehicle());
}
} else if (motorcycleUnlocked && Math.random() < 0.4) {
// 40% chance for motorcycle
var motoOffer = generateRandomMotorcycle();
motoOffer.isMotorcycle = true; // Mark as motorcycle
dailyOffers.push(motoOffer);
} else if (vanUnlocked && Math.random() < 0.3) {
// 30% chance for van
var vanOffer = generateRandomVan();
vanOffer.isVan = true;
dailyOffers.push(vanOffer);
} else {
dailyOffers.push(generateRandomVehicle());
}
}
}
// Generate daily motorcycle offers
function generateDailyMotoOffers() {
dailyMotoOffers = [];
var numOffers = Math.floor(Math.random() * 3) + 2;
for (var i = 0; i < numOffers; i++) {
dailyMotoOffers.push(generateRandomMotorcycle());
}
}
// Display vehicles
function displayVehicles(vehicles) {
vehicleContainer.removeChildren();
for (var i = 0; i < vehicles.length; i++) {
var isMotorcycle = vehicles[i].isMotorcycle || false;
var isVan = vehicles[i].isVan || false;
var vehicle = new Vehicle(vehicles[i], isMotorcycle, isVan);
vehicle.x = i % 2 * 600 - 300;
vehicle.y = Math.floor(i / 2) * 380;
vehicleContainer.addChild(vehicle);
vehicle.vehicleData = vehicles[i];
vehicle.down = function (x, y, obj) {
selectedVehicle = obj.vehicleData;
updateUI();
};
// Add buy button for each vehicle
var vehicleBuyButton = new Button('Buy', 0x27ae60, 200, 80);
vehicleBuyButton.x = 0;
vehicleBuyButton.y = 150;
vehicle.addChild(vehicleBuyButton);
// Store vehicle data directly on the button using closure
(function (vehicleData, vehicleIndex) {
vehicleBuyButton.up = function (x, y, obj) {
if (vehicleData && playerMoney >= vehicleData.price) {
playerMoney -= vehicleData.price;
// Check if this seller is a scammer
if (vehicleData.isScammer) {
// Player loses money but gets no vehicle
infoText.setText('SCAMMED! The seller took your money and disappeared!\nYou lost $' + vehicleData.price.toLocaleString() + '!');
LK.effects.flashScreen(0xff0000, 1500); // Red flash for scam
} else {
// Normal purchase - Create a copy of the vehicle data for owned vehicles
var ownedVehicleData = {
make: vehicleData.make,
model: vehicleData.model,
condition: vehicleData.condition,
actualCondition: vehicleData.actualCondition,
mileage: vehicleData.mileage,
actualMileage: vehicleData.actualMileage,
price: vehicleData.price,
marketValue: vehicleData.marketValue,
sellerLying: vehicleData.sellerLying,
id: vehicleData.id,
repaired: false
};
if (vehicleData.isMotorcycle) {
ownedMotorcycles.push(ownedVehicleData);
} else if (vehicleData.isVan) {
ownedVans.push(ownedVehicleData);
} else {
ownedVehicles.push(ownedVehicleData);
}
if (soundEffectsEnabled) LK.getSound('purchase').play();
}
// Remove from daily offers in both cases
for (var j = 0; j < dailyOffers.length; j++) {
if (dailyOffers[j].id === vehicleData.id) {
dailyOffers.splice(j, 1);
break;
}
}
selectedVehicle = null;
updateMoneyDisplay();
displayVehicles(dailyOffers);
updateUI();
saveGame();
}
};
})(vehicles[i], i);
}
}
// Update UI based on game state
function updateUI() {
inspectButton.visible = false;
buyButton.visible = false;
negotiateButton.visible = false;
repairButton.visible = false;
sellButton.visible = false;
expertiseButton.visible = false;
if (gameState === 'daily_offers' && selectedVehicle) {
inspectButton.visible = true;
buyButton.visible = true;
negotiateButton.visible = true;
expertiseButton.visible = true;
// Calculate expertise cost based on vehicle price (15-20% of price)
var expertiseCost = Math.floor(selectedVehicle.price * (Math.random() * 0.05 + 0.15));
// Minimum expertise cost of $1000
if (expertiseCost < 1000) {
expertiseCost = 1000;
}
// Update expertise button text with dynamic cost
expertiseButton.children[0].setText('Expertise ($' + expertiseCost.toLocaleString() + ')');
infoText.setText('Selected: ' + selectedVehicle.make + ' ' + selectedVehicle.model + '\nCondition: ' + selectedVehicle.condition + '\nMileage: ' + selectedVehicle.mileage + 'k miles' + '\nPrice: $' + selectedVehicle.price.toLocaleString());
} else if (gameState === 'owned_vehicles' && selectedVehicle) {
if (selectedVehicle.actualCondition === 'damaged' && !selectedVehicle.repaired) {
repairButton.visible = true;
} else {
sellButton.visible = true;
}
infoText.setText('Owned: ' + selectedVehicle.make + ' ' + selectedVehicle.model + '\nCondition: ' + selectedVehicle.actualCondition + '\nMileage: ' + selectedVehicle.actualMileage + 'k miles' + '\nMarket Value: $' + selectedVehicle.marketValue.toLocaleString());
} else {
infoText.setText('Select a vehicle to view options');
}
}
// Add expertise button
var expertiseButton = game.addChild(new Button('Expertise (Dynamic)', 0x9b59b6));
expertiseButton.x = 2048 / 2 + 400;
expertiseButton.y = 2200;
expertiseButton.visible = false;
// Button event handlers
inspectButton.up = function (x, y, obj) {
if (selectedVehicle && playerMoney >= 500) {
playerMoney -= 500;
selectedVehicle.inspected = true;
selectedVehicle.condition = selectedVehicle.actualCondition;
if (soundEffectsEnabled) LK.getSound('inspect').play();
updateMoneyDisplay();
displayVehicles(dailyOffers);
updateUI();
if (selectedVehicle.sellerLying || selectedVehicle.mileage !== selectedVehicle.actualMileage) {
var lieText = 'Inspection revealed the seller was lying!\n';
if (selectedVehicle.sellerLying) {
lieText += 'Actual condition: ' + selectedVehicle.actualCondition + '\n';
}
if (selectedVehicle.mileage !== selectedVehicle.actualMileage) {
lieText += 'Actual mileage: ' + selectedVehicle.actualMileage + 'k miles';
}
infoText.setText(lieText);
} else {
infoText.setText('Inspection confirmed seller was honest.');
}
}
};
expertiseButton.up = function (x, y, obj) {
if (selectedVehicle) {
// Calculate expertise cost based on vehicle price (15-20% of price)
var expertiseCost = Math.floor(selectedVehicle.price * (Math.random() * 0.05 + 0.15));
// Minimum expertise cost of $1000
if (expertiseCost < 1000) {
expertiseCost = 1000;
}
if (playerMoney >= expertiseCost) {
playerMoney -= expertiseCost;
selectedVehicle.inspected = true;
selectedVehicle.condition = selectedVehicle.actualCondition;
if (soundEffectsEnabled) LK.getSound('inspect').play();
updateMoneyDisplay();
displayVehicles(dailyOffers);
updateUI();
var detailsText = 'EXPERTISE REPORT (Cost: $' + expertiseCost.toLocaleString() + '):\n';
detailsText += 'True Condition: ' + selectedVehicle.actualCondition + '\n';
detailsText += 'Claimed Mileage: ' + selectedVehicle.mileage + 'k miles\n';
detailsText += 'Actual Mileage: ' + selectedVehicle.actualMileage + 'k miles\n';
detailsText += 'Mileage Honest: ' + (selectedVehicle.mileage === selectedVehicle.actualMileage ? 'YES' : 'NO') + '\n';
detailsText += 'Seller Honest: ' + (selectedVehicle.sellerLying ? 'NO' : 'YES') + '\n';
detailsText += 'Market Value: $' + selectedVehicle.marketValue.toLocaleString() + '\n';
detailsText += 'Seller Trustworthy: ' + (selectedVehicle.isScammer ? 'SUSPICIOUS - POSSIBLE SCAMMER!' : 'YES') + '\n';
detailsText += 'Recommended Action: ';
if (selectedVehicle.isScammer) {
detailsText += 'AVOID - HIGH SCAM RISK!';
} else if (selectedVehicle.price < selectedVehicle.marketValue * 0.8) {
detailsText += 'BUY - Good Deal';
} else if (selectedVehicle.price > selectedVehicle.marketValue * 1.2) {
detailsText += 'AVOID - Overpriced';
} else {
detailsText += 'NEGOTIATE - Fair Price';
}
infoText.setText(detailsText);
} else {
infoText.setText('Not enough money! Expertise costs $' + expertiseCost.toLocaleString());
}
}
};
buyButton.up = function (x, y, obj) {
if (selectedVehicle && playerMoney >= selectedVehicle.price) {
playerMoney -= selectedVehicle.price;
// Check if this seller is a scammer
if (selectedVehicle.isScammer) {
// Player loses money but gets no vehicle
infoText.setText('SCAMMED! The seller took your money and disappeared!\nYou lost $' + selectedVehicle.price.toLocaleString() + '!');
LK.effects.flashScreen(0xff0000, 1500); // Red flash for scam
} else {
// Normal purchase
selectedVehicle.actualCondition = selectedVehicle.actualCondition;
if (selectedVehicle.isMotorcycle) {
ownedMotorcycles.push(selectedVehicle);
} else if (selectedVehicle.isVan) {
ownedVans.push(selectedVehicle);
} else {
ownedVehicles.push(selectedVehicle);
}
if (soundEffectsEnabled) LK.getSound('purchase').play();
}
// Remove from daily offers in both cases
for (var i = 0; i < dailyOffers.length; i++) {
if (dailyOffers[i].id === selectedVehicle.id) {
dailyOffers.splice(i, 1);
break;
}
}
selectedVehicle = null;
updateMoneyDisplay();
displayVehicles(dailyOffers);
updateUI();
saveGame();
}
};
negotiateButton.up = function (x, y, obj) {
if (selectedVehicle) {
var reduction = Math.floor(selectedVehicle.price * (Math.random() * 0.2 + 0.05));
selectedVehicle.price -= reduction;
displayVehicles(dailyOffers);
updateUI();
infoText.setText('Negotiated $' + reduction.toLocaleString() + ' off the price!');
}
};
repairButton.up = function (x, y, obj) {
if (selectedVehicle) {
// Calculate repair cost based on vehicle price (10-25% of price)
var repairCost = Math.floor(selectedVehicle.price * (Math.random() * 0.15 + 0.10));
// Minimum repair cost of $1000
if (repairCost < 1000) {
repairCost = 1000;
}
if (playerMoney >= repairCost) {
playerMoney -= repairCost;
// Calculate repair duration based on damage level
var repairDuration = 1; // Default 1 day
if (selectedVehicle.actualCondition === 'damaged') {
repairDuration = Math.floor(Math.random() * 3) + 1; // 1-3 days for damaged
} else if (selectedVehicle.actualCondition === 'poor') {
repairDuration = 1; // 1 day for poor
}
// Move vehicle to repair shop
var repairData = {
vehicleId: selectedVehicle.id,
completionDay: currentDay + repairDuration,
repairDuration: repairDuration
};
vehiclesInRepair.push(repairData);
// Mark vehicle as in repair but not completed
for (var k = 0; k < ownedVehicles.length; k++) {
if (ownedVehicles[k].id === selectedVehicle.id) {
ownedVehicles[k].inRepair = true;
ownedVehicles[k].repairCompletionDay = currentDay + repairDuration;
break;
}
}
if (soundEffectsEnabled) LK.getSound('repair').play();
updateMoneyDisplay();
displayOwnedVehicles();
updateUI();
saveGame();
infoText.setText('Vehicle sent to repair shop for $' + repairCost.toLocaleString() + '!\nWill be ready in ' + repairDuration + ' day(s).');
} else {
infoText.setText('Not enough money! Repair costs $' + repairCost.toLocaleString());
}
}
};
sellButton.up = function (x, y, obj) {
if (selectedVehicle) {
var salePrice = Math.floor(selectedVehicle.marketValue * (Math.random() * 0.3 + 0.8));
playerMoney += salePrice;
// Remove from owned vehicles
for (var i = 0; i < ownedVehicles.length; i++) {
if (ownedVehicles[i].id === selectedVehicle.id) {
ownedVehicles.splice(i, 1);
break;
}
}
if (soundEffectsEnabled) LK.getSound('sale').play();
selectedVehicle = null;
updateMoneyDisplay();
displayOwnedVehicles();
updateUI();
saveGame();
infoText.setText('Sold for $' + salePrice.toLocaleString() + '!');
}
};
nextDayButton.up = function (x, y, obj) {
currentDay++;
selectedVehicle = null;
generateDailyOffers();
gameState = 'daily_offers';
stateText.setText('Daily Vehicle Offers');
dayText.setText('Day ' + currentDay);
displayVehicles(dailyOffers);
updateUI();
// Add random daily expenses
var dailyExpenses = Math.floor(Math.random() * 5000) + 1000; // Between $1000-$6000
playerMoney -= dailyExpenses;
var expenseText = 'Daily expenses: $' + dailyExpenses.toLocaleString() + ' (rent, utilities, staff wages)';
// Add maintenance costs for owned vehicles
var maintenanceCosts = applyMaintenanceCosts();
if (maintenanceCosts > 0) {
expenseText += '\nVehicle maintenance: $' + maintenanceCosts.toLocaleString();
}
// Add insurance costs based on number of owned vehicles
var insuranceCost = ownedVehicles.length * 150;
if (insuranceCost > 0) {
playerMoney -= insuranceCost;
expenseText += '\nInsurance: $' + insuranceCost.toLocaleString();
}
// Random unexpected repairs (10% chance per owned vehicle)
var unexpectedRepairs = 0;
for (var i = 0; i < ownedVehicles.length; i++) {
if (Math.random() < 0.1) {
var repairCost = Math.floor(Math.random() * 2000) + 500;
unexpectedRepairs += repairCost;
}
}
if (unexpectedRepairs > 0) {
playerMoney -= unexpectedRepairs;
expenseText += '\nUnexpected repairs: $' + unexpectedRepairs.toLocaleString();
}
// Apply vehicle depreciation
applyVehicleDepreciation();
// Update repair progress and check for completed repairs
var completedRepairs = [];
for (var r = vehiclesInRepair.length - 1; r >= 0; r--) {
// Decrease remaining repair days
vehiclesInRepair[r].repairDuration--;
// Update vehicle repair completion day display
for (var v = 0; v < ownedVehicles.length; v++) {
if (ownedVehicles[v].id === vehiclesInRepair[r].vehicleId) {
ownedVehicles[v].repairCompletionDay = currentDay + vehiclesInRepair[r].repairDuration;
break;
}
}
// Check if repair is completed (0 days remaining)
if (vehiclesInRepair[r].repairDuration <= 0) {
completedRepairs.push(vehiclesInRepair[r]);
vehiclesInRepair.splice(r, 1);
}
}
// Complete repairs and update vehicle data
for (var c = 0; c < completedRepairs.length; c++) {
var completedRepair = completedRepairs[c];
for (var v = 0; v < ownedVehicles.length; v++) {
if (ownedVehicles[v].id === completedRepair.vehicleId) {
ownedVehicles[v].repaired = true;
ownedVehicles[v].actualCondition = 'good';
ownedVehicles[v].marketValue = Math.floor(ownedVehicles[v].marketValue * 1.5);
ownedVehicles[v].inRepair = false;
delete ownedVehicles[v].repairCompletionDay;
break;
}
}
}
// Update motorcycle repair progress and check for completed repairs
var completedMotoRepairs = [];
for (var mr = motorcyclesInRepair.length - 1; mr >= 0; mr--) {
// Decrease remaining repair days
motorcyclesInRepair[mr].repairDuration--;
// Update motorcycle repair completion day display
for (var mv = 0; mv < ownedMotorcycles.length; mv++) {
if (ownedMotorcycles[mv].id === motorcyclesInRepair[mr].vehicleId) {
ownedMotorcycles[mv].repairCompletionDay = currentDay + motorcyclesInRepair[mr].repairDuration;
break;
}
}
// Check if repair is completed (0 days remaining)
if (motorcyclesInRepair[mr].repairDuration <= 0) {
completedMotoRepairs.push(motorcyclesInRepair[mr]);
motorcyclesInRepair.splice(mr, 1);
}
}
// Complete motorcycle repairs and update motorcycle data
for (var mc = 0; mc < completedMotoRepairs.length; mc++) {
var completedMotoRepair = completedMotoRepairs[mc];
for (var mv = 0; mv < ownedMotorcycles.length; mv++) {
if (ownedMotorcycles[mv].id === completedMotoRepair.vehicleId) {
ownedMotorcycles[mv].repaired = true;
ownedMotorcycles[mv].actualCondition = 'good';
ownedMotorcycles[mv].marketValue = Math.floor(ownedMotorcycles[mv].marketValue * 1.5);
ownedMotorcycles[mv].inRepair = false;
delete ownedMotorcycles[mv].repairCompletionDay;
break;
}
}
}
// Show repair completion message
var totalCompletedRepairs = completedRepairs.length + completedMotoRepairs.length;
if (totalCompletedRepairs > 0) {
expenseText += '\n' + totalCompletedRepairs + ' vehicle(s) completed repair and ready for sale!';
LK.effects.flashScreen(0x2ecc71, 1000); // Green flash for completed repairs
}
// Apply daily interest on debt
var interestCharge = 0;
if (playerDebt > 0) {
interestCharge = Math.floor(playerDebt * dailyInterestRate);
playerDebt += interestCharge;
expenseText += '\nDebt interest: $' + interestCharge.toLocaleString();
}
// Check for loan seizure (5 days after loan was taken)
if (playerDebt > 0 && loanTakenDay > 0 && currentDay > loanTakenDay + 5) {
var seizureAmount = Math.floor(playerDebt * 1.5); // 50% more than debt
var actualSeizureAmount = 0;
var seizedVehicles = [];
// First seize money
if (playerMoney > 0) {
var moneySeized = Math.min(playerMoney, seizureAmount);
playerMoney -= moneySeized;
actualSeizureAmount += moneySeized;
seizureAmount -= moneySeized;
}
// Then seize vehicles if more seizure needed
if (seizureAmount > 0) {
// Seize cars
for (var i = ownedVehicles.length - 1; i >= 0 && seizureAmount > 0; i--) {
var vehicle = ownedVehicles[i];
if (vehicle.marketValue <= seizureAmount) {
seizedVehicles.push(vehicle.make + ' ' + vehicle.model);
actualSeizureAmount += vehicle.marketValue;
seizureAmount -= vehicle.marketValue;
ownedVehicles.splice(i, 1);
}
}
// Seize motorcycles
for (var i = ownedMotorcycles.length - 1; i >= 0 && seizureAmount > 0; i--) {
var vehicle = ownedMotorcycles[i];
if (vehicle.marketValue <= seizureAmount) {
seizedVehicles.push(vehicle.make + ' ' + vehicle.model + ' (Motorcycle)');
actualSeizureAmount += vehicle.marketValue;
seizureAmount -= vehicle.marketValue;
ownedMotorcycles.splice(i, 1);
}
}
// Seize vans
for (var i = ownedVans.length - 1; i >= 0 && seizureAmount > 0; i--) {
var vehicle = ownedVans[i];
if (vehicle.marketValue <= seizureAmount) {
seizedVehicles.push(vehicle.make + ' ' + vehicle.model + ' (Van)');
actualSeizureAmount += vehicle.marketValue;
seizureAmount -= vehicle.marketValue;
ownedVans.splice(i, 1);
}
}
}
// Clear debt and reset loan tracking after seizure
playerDebt = 0;
totalLoansOutstanding = 0;
loanTakenDay = 0;
var seizureText = 'LOAN SEIZURE! Assets worth $' + actualSeizureAmount.toLocaleString() + ' seized for unpaid loans!';
if (seizedVehicles.length > 0) {
seizureText += '\nVehicles seized: ' + seizedVehicles.join(', ');
}
expenseText += '\n' + seizureText;
LK.effects.flashScreen(0xff0000, 2000); // Red flash for seizure
// Update displays after seizure
if (gameState === 'owned_vehicles') {
displayOwnedVehicles();
}
}
// Tax system - every 7 days
if (currentDay % 7 === 1 && currentDay > lastTaxDay) {
// Calculate total vehicle value
var totalVehicleValue = 0;
for (var i = 0; i < ownedVehicles.length; i++) {
totalVehicleValue += ownedVehicles[i].marketValue;
}
// Tax is 8% of total assets (money + vehicles)
var taxAmount = Math.floor((playerMoney + totalVehicleValue) * 0.08);
taxDebt += taxAmount;
taxDueDate = currentDay + 2; // 2 days to pay
taxOverdueDate = currentDay + 2; // Start charging interest after 2 days
lastTaxDay = currentDay;
expenseText += '\nTAX DUE: $' + taxAmount.toLocaleString() + ' (due in 2 days)';
LK.effects.flashScreen(0xffa500, 1000); // Orange flash for tax notice
}
// Apply tax interest if overdue (after 2 days)
if (taxDebt > 0 && currentDay > taxOverdueDate) {
var taxInterest = Math.floor(taxDebt * 0.15); // 15% daily interest
taxDebt += taxInterest;
expenseText += '\nTax interest: $' + taxInterest.toLocaleString() + ' (15% daily)';
}
// Tax seizure after 14 days of unpaid tax debt
if (taxDebt > 0 && currentDay > taxDueDate + 14) {
var seizureAmount = Math.floor(taxDebt * 1.5); // 50% more than tax debt
var actualSeizureAmount = 0;
// First seize money
if (playerMoney > 0) {
var moneySeized = Math.min(playerMoney, seizureAmount);
playerMoney -= moneySeized;
actualSeizureAmount += moneySeized;
seizureAmount -= moneySeized;
}
// Then seize vehicles if more seizure needed
if (seizureAmount > 0 && ownedVehicles.length > 0) {
var vehiclesSeized = [];
for (var i = ownedVehicles.length - 1; i >= 0 && seizureAmount > 0; i--) {
var vehicle = ownedVehicles[i];
if (vehicle.marketValue <= seizureAmount) {
vehiclesSeized.push(vehicle.make + ' ' + vehicle.model);
actualSeizureAmount += vehicle.marketValue;
seizureAmount -= vehicle.marketValue;
ownedVehicles.splice(i, 1);
}
}
}
// Clear tax debt after seizure
taxDebt = 0;
taxDueDate = 0;
taxOverdueDate = 0;
var seizureText = 'TAX SEIZURE! Assets worth $' + actualSeizureAmount.toLocaleString() + ' seized for unpaid taxes!';
if (vehiclesSeized.length > 0) {
seizureText += '\nVehicles seized: ' + vehiclesSeized.join(', ');
}
expenseText += '\n' + seizureText;
LK.effects.flashScreen(0xff0000, 2000); // Red flash for seizure
// Update displays after seizure
if (gameState === 'owned_vehicles') {
displayOwnedVehicles();
}
}
updateMoneyDisplay();
updateDebtDisplay();
updateTaxDisplay();
infoText.setText(expenseText);
saveGame();
};
viewOwnedButton.up = function (x, y, obj) {
if (gameState === 'daily_offers') {
gameState = 'owned_vehicles';
stateText.setText('Owned Vehicles & Motorcycles');
displayOwnedVehicles();
} else {
gameState = 'daily_offers';
stateText.setText('Daily Vehicle Offers');
displayVehicles(dailyOffers);
}
selectedVehicle = null;
updateUI();
};
loanButton.up = function (x, y, obj) {
var loanAmount = 10000;
// Check if player can take more loans (credit limit)
if (totalLoansOutstanding + loanAmount > creditLimit) {
infoText.setText('Loan denied! Credit limit reached.\nCredit limit: $' + creditLimit.toLocaleString() + '\nOutstanding loans: $' + totalLoansOutstanding.toLocaleString());
return;
}
playerMoney += loanAmount;
playerDebt += loanAmount;
totalLoansOutstanding += loanAmount;
loanTakenDay = currentDay; // Track when loan was taken
updateMoneyDisplay();
updateDebtDisplay();
saveGame();
infoText.setText('Loan approved! You received $' + loanAmount.toLocaleString() + '\nDaily interest: 5%\nDue in 5 days or 50% penalty applies');
};
payDebtButton.up = function (x, y, obj) {
if (playerDebt > 0 && playerMoney > 0) {
var paymentAmount = Math.min(playerMoney, playerDebt);
playerMoney -= paymentAmount;
playerDebt -= paymentAmount;
totalLoansOutstanding -= paymentAmount; // Reduce outstanding loans
if (totalLoansOutstanding < 0) totalLoansOutstanding = 0;
updateMoneyDisplay();
updateDebtDisplay();
saveGame();
infoText.setText('Paid $' + paymentAmount.toLocaleString() + ' towards debt!\nRemaining debt: $' + playerDebt.toLocaleString());
} else if (playerDebt <= 0) {
infoText.setText('You have no debt to pay!');
} else {
infoText.setText('You need money to pay your debt!');
}
};
payTaxButton.up = function (x, y, obj) {
if (taxDebt > 0 && playerMoney > 0) {
var paymentAmount = Math.min(playerMoney, taxDebt);
playerMoney -= paymentAmount;
taxDebt -= paymentAmount;
updateMoneyDisplay();
updateTaxDisplay();
saveGame();
infoText.setText('Paid $' + paymentAmount.toLocaleString() + ' towards tax!\nRemaining tax: $' + taxDebt.toLocaleString());
} else if (taxDebt <= 0) {
infoText.setText('You have no tax to pay!');
} else {
infoText.setText('You need money to pay your tax!');
}
};
settingsButton.up = function (x, y, obj) {
// Show settings menu
gameState = 'settings';
stateText.setText('Settings');
vehicleContainer.removeChildren();
// Create sound effects toggle button
var soundToggleText = soundEffectsEnabled ? 'Sound Effects: ON' : 'Sound Effects: OFF';
var soundToggleBtn = new Button(soundToggleText, soundEffectsEnabled ? 0x2ecc71 : 0xe74c3c, 400, 120);
soundToggleBtn.x = 0;
soundToggleBtn.y = -150;
vehicleContainer.addChild(soundToggleBtn);
soundToggleBtn.up = function () {
soundEffectsEnabled = !soundEffectsEnabled;
saveGame();
// Refresh settings menu
settingsButton.up();
};
// Create reset game button with warning
var resetBtn = new Button('Reset Game', 0xe74c3c, 400, 120);
resetBtn.x = 0;
resetBtn.y = 150;
vehicleContainer.addChild(resetBtn);
resetBtn.up = function () {
// Show confirmation warning
gameState = 'reset_confirmation';
stateText.setText('Reset Confirmation');
vehicleContainer.removeChildren();
var warningText = new Text2('WARNING!\nThis will delete ALL your progress!\nAre you sure?', {
size: 48,
fill: 0xff0000
});
warningText.anchor.set(0.5, 0.5);
warningText.x = 0;
warningText.y = -100;
vehicleContainer.addChild(warningText);
var confirmBtn = new Button('YES - Reset Everything', 0xe74c3c, 400, 120);
confirmBtn.x = -250;
confirmBtn.y = 100;
vehicleContainer.addChild(confirmBtn);
confirmBtn.up = function () {
// Clear all stored data
delete storage.playerMoney;
delete storage.currentDay;
delete storage.playerDebt;
delete storage.creditLimit;
delete storage.loanTakenDay;
delete storage.totalLoansOutstanding;
delete storage.taxDebt;
delete storage.taxDueDate;
delete storage.taxOverdueDate;
delete storage.lastTaxDay;
delete storage.vehicleCount;
delete storage.vehicleMakes;
delete storage.vehicleModels;
delete storage.vehicleConditions;
delete storage.vehicleActualConditions;
delete storage.vehicleMileages;
delete storage.vehicleActualMileages;
delete storage.vehiclePrices;
delete storage.vehicleMarketValues;
delete storage.vehicleSellerLying;
delete storage.vehicleIds;
delete storage.vehicleRepaired;
delete storage.vehicleInRepair;
delete storage.vehicleRepairCompletionDay;
delete storage.vehiclesInRepairCount;
delete storage.repairVehicleIds;
delete storage.repairCompletionDays;
delete storage.repairDurations;
delete storage.motorcycleUnlocked;
delete storage.motorcycleCount;
delete storage.motorcycleMakes;
delete storage.motorcycleModels;
delete storage.motorcycleConditions;
delete storage.motorcycleActualConditions;
delete storage.motorcycleMileages;
delete storage.motorcycleActualMileages;
delete storage.motorcyclePrices;
delete storage.motorcycleMarketValues;
delete storage.motorcycleSellerLying;
delete storage.motorcycleIds;
delete storage.motorcycleRepaired;
delete storage.motorcycleInRepair;
delete storage.motorcycleRepairCompletionDay;
delete storage.motorcyclesInRepairCount;
delete storage.repairMotoVehicleIds;
delete storage.repairMotoCompletionDays;
delete storage.repairMotoDurations;
delete storage.vanUnlocked;
delete storage.vanCount;
delete storage.vanMakes;
delete storage.vanModels;
delete storage.vanConditions;
delete storage.vanActualConditions;
delete storage.vanMileages;
delete storage.vanActualMileages;
delete storage.vanPrices;
delete storage.vanMarketValues;
delete storage.vanSellerLying;
delete storage.vanIds;
delete storage.vanRepaired;
delete storage.vanInRepair;
delete storage.vanRepairCompletionDay;
delete storage.vansInRepairCount;
delete storage.repairVanVehicleIds;
delete storage.repairVanCompletionDays;
delete storage.repairVanDurations;
delete storage.soundEffectsEnabled;
// Reset game state to initial values
playerMoney = 50000;
currentDay = 1;
playerDebt = 0;
creditLimit = 50000;
loanTakenDay = 0;
totalLoansOutstanding = 0;
taxDebt = 0;
taxDueDate = 0;
taxOverdueDate = 0;
lastTaxDay = 0;
ownedVehicles = [];
vehiclesInRepair = [];
motorcycleUnlocked = false;
vanUnlocked = false;
ownedMotorcycles = [];
ownedVans = [];
motorcyclesInRepair = [];
vansInRepair = [];
vehicleType = 'cars';
selectedVehicle = null;
gameState = 'daily_offers';
soundEffectsEnabled = true;
vehicleLocksButton.visible = true;
// Update UI
stateText.setText('Daily Vehicle Offers');
dayText.setText('Day ' + currentDay);
updateMoneyDisplay();
updateDebtDisplay();
updateTaxDisplay();
generateDailyOffers();
displayVehicles(dailyOffers);
updateUI();
};
var cancelBtn = new Button('NO - Keep Progress', 0x2ecc71, 400, 120);
cancelBtn.x = 250;
cancelBtn.y = 100;
vehicleContainer.addChild(cancelBtn);
cancelBtn.up = function () {
// Return to settings
settingsButton.up();
};
};
var backBtn = new Button('Back', 0x95a5a6, 200, 80);
backBtn.x = 0;
backBtn.y = 300;
vehicleContainer.addChild(backBtn);
backBtn.up = function () {
gameState = 'daily_offers';
stateText.setText('Daily Vehicle Offers');
displayVehicles(dailyOffers);
updateUI();
};
selectedVehicle = null;
updateUI();
};
vehicleLocksButton.up = function (x, y, obj) {
// Show vehicle locks menu
gameState = 'vehicle_locks';
stateText.setText('Vehicle Locks');
vehicleContainer.removeChildren();
// Create unlock buttons for motorcycles and vans
if (!motorcycleUnlocked) {
var unlockMotoBtn = new Button('Unlock Motorcycles ($100,000)', 0x9b59b6, 400, 120);
unlockMotoBtn.x = 0;
unlockMotoBtn.y = -100;
vehicleContainer.addChild(unlockMotoBtn);
unlockMotoBtn.up = function () {
if (playerMoney >= 100000) {
playerMoney -= 100000;
motorcycleUnlocked = true;
updateMoneyDisplay();
saveGame();
infoText.setText('Motorcycles unlocked! Motorcycle offers will now appear mixed with car offers.');
LK.effects.flashScreen(0x2ecc71, 1000);
// Return to main menu
gameState = 'daily_offers';
stateText.setText('Daily Vehicle Offers');
displayVehicles(dailyOffers);
updateUI();
vehicleLocksButton.visible = !motorcycleUnlocked || !vanUnlocked;
} else {
infoText.setText('Not enough money! Need $100,000 to unlock motorcycles.');
}
};
}
if (!vanUnlocked) {
var unlockVanBtn = new Button('Unlock Vans ($250,000)', 0x34495e, 400, 120);
unlockVanBtn.x = 0;
unlockVanBtn.y = motorcycleUnlocked ? -100 : 50;
vehicleContainer.addChild(unlockVanBtn);
unlockVanBtn.up = function () {
if (playerMoney >= 250000) {
playerMoney -= 250000;
vanUnlocked = true;
updateMoneyDisplay();
saveGame();
infoText.setText('Vans unlocked! Van offers will now appear mixed with other vehicle offers.');
LK.effects.flashScreen(0x2ecc71, 1000);
// Return to main menu
gameState = 'daily_offers';
stateText.setText('Daily Vehicle Offers');
displayVehicles(dailyOffers);
updateUI();
vehicleLocksButton.visible = !motorcycleUnlocked || !vanUnlocked;
} else {
infoText.setText('Not enough money! Need $250,000 to unlock vans.');
}
};
}
var backBtn = new Button('Back', 0x95a5a6, 200, 80);
backBtn.x = 0;
backBtn.y = 200;
vehicleContainer.addChild(backBtn);
backBtn.up = function () {
gameState = 'daily_offers';
stateText.setText('Daily Vehicle Offers');
displayVehicles(dailyOffers);
updateUI();
};
selectedVehicle = null;
updateUI();
};
// Switch vehicle button functionality removed - vehicles are now mixed together
function displayOwnedVehicles() {
vehicleContainer.removeChildren();
var allOwnedVehicles = ownedVehicles.concat(ownedMotorcycles).concat(ownedVans);
for (var i = 0; i < allOwnedVehicles.length; i++) {
var vehicleData = allOwnedVehicles[i];
var isMotorcycle = i >= ownedVehicles.length && i < ownedVehicles.length + ownedMotorcycles.length;
var isVan = i >= ownedVehicles.length + ownedMotorcycles.length;
var vehicle = new Vehicle(vehicleData, isMotorcycle, isVan);
if (vehicleData.repaired) {
vehicle.repaired = true;
vehicle.updateDisplay();
}
vehicle.x = i % 2 * 600 - 300;
vehicle.y = Math.floor(i / 2) * 380;
vehicleContainer.addChild(vehicle);
vehicle.vehicleData = vehicleData;
vehicle.down = function (x, y, obj) {
selectedVehicle = obj.vehicleData;
updateUI();
};
// Add action buttons for each owned vehicle
if (vehicleData.inRepair) {
// Vehicle is in repair - show status and prevent actions
var daysRemaining = 0;
// Find repair data to get remaining days
var repairArray = isMotorcycle ? motorcyclesInRepair : vehiclesInRepair;
for (var rr = 0; rr < repairArray.length; rr++) {
if (repairArray[rr].vehicleId === vehicleData.id) {
daysRemaining = repairArray[rr].repairDuration;
break;
}
}
var repairStatusText = new Text2('IN REPAIR - ' + daysRemaining + ' day(s) remaining', {
size: 24,
fill: 0xf39c12
});
repairStatusText.anchor.set(0.5, 0.5);
repairStatusText.x = 0;
repairStatusText.y = 150;
vehicle.addChild(repairStatusText);
} else if (vehicleData.actualCondition === 'damaged' && !vehicleData.repaired) {
// Add repair button with dynamic cost
var repairCost = Math.floor(vehicleData.price * (Math.random() * 0.15 + 0.10));
var minRepairCost = isMotorcycle ? 500 : 1000;
if (repairCost < minRepairCost) {
repairCost = minRepairCost;
}
var vehicleRepairButton = new Button('Repair ($' + repairCost.toLocaleString() + ')', 0xe67e22, 200, 60);
vehicleRepairButton.x = -150;
vehicleRepairButton.y = 150;
vehicle.addChild(vehicleRepairButton);
(function (vehicleData, isMotorcycle) {
vehicleRepairButton.up = function (x, y, obj) {
// Calculate repair cost based on vehicle price (10-25% of price)
var repairCost = Math.floor(vehicleData.price * (Math.random() * 0.15 + 0.10));
// Minimum repair cost based on vehicle type
var minRepairCost = isMotorcycle ? 500 : 1000;
if (repairCost < minRepairCost) {
repairCost = minRepairCost;
}
if (playerMoney >= repairCost) {
playerMoney -= repairCost;
// Calculate repair duration based on damage level
var repairDuration = 1; // Default 1 day
if (vehicleData.actualCondition === 'damaged') {
repairDuration = Math.floor(Math.random() * 3) + 1; // 1-3 days for damaged
} else if (vehicleData.actualCondition === 'poor') {
repairDuration = 1; // 1 day for poor
}
// Move vehicle to repair shop
var repairData = {
vehicleId: vehicleData.id,
completionDay: currentDay + repairDuration,
repairDuration: repairDuration
};
if (isMotorcycle) {
motorcyclesInRepair.push(repairData);
// Update the vehicle data in the ownedMotorcycles array
for (var k = 0; k < ownedMotorcycles.length; k++) {
if (ownedMotorcycles[k].id === vehicleData.id) {
ownedMotorcycles[k].inRepair = true;
ownedMotorcycles[k].repairCompletionDay = currentDay + repairDuration;
break;
}
}
} else {
vehiclesInRepair.push(repairData);
// Update the vehicle data in the ownedVehicles array
for (var k = 0; k < ownedVehicles.length; k++) {
if (ownedVehicles[k].id === vehicleData.id) {
ownedVehicles[k].inRepair = true;
ownedVehicles[k].repairCompletionDay = currentDay + repairDuration;
break;
}
}
}
if (soundEffectsEnabled) LK.getSound('repair').play();
updateMoneyDisplay();
displayOwnedVehicles();
updateUI();
saveGame();
infoText.setText('Vehicle sent to repair shop for $' + repairCost.toLocaleString() + '!\nWill be ready in ' + repairDuration + ' day(s).');
} else {
infoText.setText('Not enough money! Repair costs $' + repairCost.toLocaleString());
}
};
})(vehicleData, isMotorcycle);
// Add sell button for damaged vehicles (sell as-is for low price)
var damagedSalePrice = Math.floor(vehicleData.marketValue * (Math.random() * 0.20 + 0.30));
var vehicleSellDamagedButton = new Button('Sell LOW ($' + damagedSalePrice.toLocaleString() + ')', 0x8e44ad, 200, 60);
vehicleSellDamagedButton.x = 50;
vehicleSellDamagedButton.y = 150;
vehicle.addChild(vehicleSellDamagedButton);
(function (vehicleData, displayedSalePrice, isMotorcycle) {
vehicleSellDamagedButton.up = function (x, y, obj) {
var salePrice = displayedSalePrice;
playerMoney += salePrice;
// Remove from appropriate owned vehicles array
if (isMotorcycle) {
for (var j = 0; j < ownedMotorcycles.length; j++) {
if (ownedMotorcycles[j].id === vehicleData.id) {
ownedMotorcycles.splice(j, 1);
break;
}
}
} else {
for (var j = 0; j < ownedVehicles.length; j++) {
if (ownedVehicles[j].id === vehicleData.id) {
ownedVehicles.splice(j, 1);
break;
}
}
}
if (soundEffectsEnabled) LK.getSound('sale').play();
selectedVehicle = null;
updateMoneyDisplay();
displayOwnedVehicles();
updateUI();
saveGame();
infoText.setText('Sold damaged vehicle for $' + salePrice.toLocaleString() + '! (Low Price - Could have repaired for higher profit)');
};
})(vehicleData, damagedSalePrice, isMotorcycle);
} else {
// Add sell button with sale price - different pricing for repaired vs unrepaired
var salePrice;
if (vehicleData.repaired) {
// Repaired vehicles sell for 80-95% of market value (high price)
salePrice = Math.floor(vehicleData.marketValue * (Math.random() * 0.15 + 0.80));
} else if (vehicleData.actualCondition === 'damaged') {
// Damaged vehicles sell for 30-50% of market value (low price)
salePrice = Math.floor(vehicleData.marketValue * (Math.random() * 0.20 + 0.30));
} else {
// Other conditions sell for 60-80% of market value (medium price)
salePrice = Math.floor(vehicleData.marketValue * (Math.random() * 0.20 + 0.60));
}
var sellButtonText = 'Sell ($' + salePrice.toLocaleString() + ')';
if (vehicleData.repaired) {
sellButtonText += ' HIGH';
} else if (vehicleData.actualCondition === 'damaged') {
sellButtonText += ' LOW';
}
var vehicleSellButton = new Button(sellButtonText, 0x8e44ad, 200, 60);
vehicleSellButton.x = -100;
vehicleSellButton.y = 150;
vehicle.addChild(vehicleSellButton);
(function (vehicleData, displayedSalePrice, isMotorcycle) {
vehicleSellButton.up = function (x, y, obj) {
var salePrice = displayedSalePrice;
playerMoney += salePrice;
// Remove from appropriate owned vehicles array
if (isMotorcycle) {
for (var j = 0; j < ownedMotorcycles.length; j++) {
if (ownedMotorcycles[j].id === vehicleData.id) {
ownedMotorcycles.splice(j, 1);
break;
}
}
} else {
for (var j = 0; j < ownedVehicles.length; j++) {
if (ownedVehicles[j].id === vehicleData.id) {
ownedVehicles.splice(j, 1);
break;
}
}
}
if (soundEffectsEnabled) LK.getSound('sale').play();
selectedVehicle = null;
updateMoneyDisplay();
displayOwnedVehicles();
updateUI();
saveGame();
var sellMessage = 'Sold for $' + salePrice.toLocaleString() + '!';
if (vehicleData.repaired) {
sellMessage += ' (Repaired - High Price)';
} else if (vehicleData.actualCondition === 'damaged') {
sellMessage += ' (Damaged - Low Price)';
}
infoText.setText(sellMessage);
};
})(vehicleData, salePrice, isMotorcycle);
}
}
}
function displayOwnedMotorcycles() {
vehicleContainer.removeChildren();
for (var i = 0; i < ownedMotorcycles.length; i++) {
var vehicle = new Vehicle(ownedMotorcycles[i], true);
if (ownedMotorcycles[i].repaired) {
vehicle.repaired = true;
vehicle.updateDisplay();
}
vehicle.x = i % 2 * 600 - 300;
vehicle.y = Math.floor(i / 2) * 380;
vehicleContainer.addChild(vehicle);
vehicle.vehicleData = ownedMotorcycles[i];
vehicle.down = function (x, y, obj) {
selectedVehicle = obj.vehicleData;
updateUI();
};
// Add action buttons for each owned motorcycle
if (ownedMotorcycles[i].inRepair) {
// Motorcycle is in repair - show status and prevent actions
var daysRemaining = 0;
// Find repair data to get remaining days
for (var rr = 0; rr < motorcyclesInRepair.length; rr++) {
if (motorcyclesInRepair[rr].vehicleId === ownedMotorcycles[i].id) {
daysRemaining = motorcyclesInRepair[rr].repairDuration;
break;
}
}
var repairStatusText = new Text2('IN REPAIR - ' + daysRemaining + ' day(s) remaining', {
size: 24,
fill: 0xf39c12
});
repairStatusText.anchor.set(0.5, 0.5);
repairStatusText.x = 0;
repairStatusText.y = 150;
vehicle.addChild(repairStatusText);
} else if (ownedMotorcycles[i].actualCondition === 'damaged' && !ownedMotorcycles[i].repaired) {
// Add repair button with dynamic cost
var repairCost = Math.floor(ownedMotorcycles[i].price * (Math.random() * 0.15 + 0.10));
if (repairCost < 500) {
repairCost = 500;
}
var vehicleRepairButton = new Button('Repair ($' + repairCost.toLocaleString() + ')', 0xe67e22, 200, 60);
vehicleRepairButton.x = -150;
vehicleRepairButton.y = 150;
vehicle.addChild(vehicleRepairButton);
(function (vehicleData) {
vehicleRepairButton.up = function (x, y, obj) {
// Calculate repair cost based on vehicle price (10-25% of price)
var repairCost = Math.floor(vehicleData.price * (Math.random() * 0.15 + 0.10));
// Minimum repair cost of $500 for motorcycles
if (repairCost < 500) {
repairCost = 500;
}
if (playerMoney >= repairCost) {
playerMoney -= repairCost;
// Calculate repair duration based on damage level
var repairDuration = 1; // Default 1 day
if (vehicleData.actualCondition === 'damaged') {
repairDuration = Math.floor(Math.random() * 3) + 1; // 1-3 days for damaged
} else if (vehicleData.actualCondition === 'poor') {
repairDuration = 1; // 1 day for poor
}
// Move motorcycle to repair shop
var repairData = {
vehicleId: vehicleData.id,
completionDay: currentDay + repairDuration,
repairDuration: repairDuration
};
motorcyclesInRepair.push(repairData);
// Update the motorcycle data in the ownedMotorcycles array
for (var k = 0; k < ownedMotorcycles.length; k++) {
if (ownedMotorcycles[k].id === vehicleData.id) {
ownedMotorcycles[k].inRepair = true;
ownedMotorcycles[k].repairCompletionDay = currentDay + repairDuration;
break;
}
}
if (soundEffectsEnabled) LK.getSound('repair').play();
updateMoneyDisplay();
displayOwnedMotorcycles();
updateUI();
saveGame();
infoText.setText('Motorcycle sent to repair shop for $' + repairCost.toLocaleString() + '!\nWill be ready in ' + repairDuration + ' day(s).');
} else {
infoText.setText('Not enough money! Repair costs $' + repairCost.toLocaleString());
}
};
})(ownedMotorcycles[i]);
// Add sell button for damaged motorcycles (sell as-is for low price)
var damagedSalePrice = Math.floor(ownedMotorcycles[i].marketValue * (Math.random() * 0.20 + 0.30));
var vehicleSellDamagedButton = new Button('Sell LOW ($' + damagedSalePrice.toLocaleString() + ')', 0x8e44ad, 200, 60);
vehicleSellDamagedButton.x = 50;
vehicleSellDamagedButton.y = 150;
vehicle.addChild(vehicleSellDamagedButton);
(function (vehicleData, displayedSalePrice) {
vehicleSellDamagedButton.up = function (x, y, obj) {
var salePrice = displayedSalePrice;
playerMoney += salePrice;
// Remove from owned motorcycles
for (var j = 0; j < ownedMotorcycles.length; j++) {
if (ownedMotorcycles[j].id === vehicleData.id) {
ownedMotorcycles.splice(j, 1);
break;
}
}
if (soundEffectsEnabled) LK.getSound('sale').play();
selectedVehicle = null;
updateMoneyDisplay();
displayOwnedMotorcycles();
updateUI();
saveGame();
infoText.setText('Sold damaged motorcycle for $' + salePrice.toLocaleString() + '! (Low Price - Could have repaired for higher profit)');
};
})(ownedMotorcycles[i], damagedSalePrice);
} else {
// Add sell button with sale price - different pricing for repaired vs unrepaired
var salePrice;
if (ownedMotorcycles[i].repaired) {
// Repaired motorcycles sell for 80-95% of market value (high price)
salePrice = Math.floor(ownedMotorcycles[i].marketValue * (Math.random() * 0.15 + 0.80));
} else if (ownedMotorcycles[i].actualCondition === 'damaged') {
// Damaged motorcycles sell for 30-50% of market value (low price)
salePrice = Math.floor(ownedMotorcycles[i].marketValue * (Math.random() * 0.20 + 0.30));
} else {
// Other conditions sell for 60-80% of market value (medium price)
salePrice = Math.floor(ownedMotorcycles[i].marketValue * (Math.random() * 0.20 + 0.60));
}
var sellButtonText = 'Sell ($' + salePrice.toLocaleString() + ')';
if (ownedMotorcycles[i].repaired) {
sellButtonText += ' HIGH';
} else if (ownedMotorcycles[i].actualCondition === 'damaged') {
sellButtonText += ' LOW';
}
var vehicleSellButton = new Button(sellButtonText, 0x8e44ad, 200, 60);
vehicleSellButton.x = -100;
vehicleSellButton.y = 150;
vehicle.addChild(vehicleSellButton);
(function (vehicleData, displayedSalePrice) {
vehicleSellButton.up = function (x, y, obj) {
var salePrice = displayedSalePrice;
playerMoney += salePrice;
// Remove from owned motorcycles
for (var j = 0; j < ownedMotorcycles.length; j++) {
if (ownedMotorcycles[j].id === vehicleData.id) {
ownedMotorcycles.splice(j, 1);
break;
}
}
if (soundEffectsEnabled) LK.getSound('sale').play();
selectedVehicle = null;
updateMoneyDisplay();
displayOwnedMotorcycles();
updateUI();
saveGame();
var sellMessage = 'Sold for $' + salePrice.toLocaleString() + '!';
if (vehicleData.repaired) {
sellMessage += ' (Repaired - High Price)';
} else if (vehicleData.actualCondition === 'damaged') {
sellMessage += ' (Damaged - Low Price)';
}
infoText.setText(sellMessage);
};
})(ownedMotorcycles[i], salePrice);
}
}
}
function updateMoneyDisplay() {
moneyText.setText('Money: $' + playerMoney.toLocaleString());
}
function updateDebtDisplay() {
debtText.setText('Debt: $' + playerDebt.toLocaleString());
if (playerDebt > 0) {
debtText.tint = 0xe74c3c; // Red for debt
} else {
debtText.tint = 0x2ecc71; // Green for no debt
}
}
function updateTaxDisplay() {
taxText.setText('Tax: $' + taxDebt.toLocaleString());
if (taxDebt > 0) {
taxText.tint = 0xe74c3c; // Red for tax debt
} else {
taxText.tint = 0x2ecc71; // Green for no tax
}
}
function saveGame() {
storage.playerMoney = playerMoney;
storage.currentDay = currentDay;
storage.playerDebt = playerDebt;
storage.creditLimit = creditLimit;
storage.loanTakenDay = loanTakenDay;
storage.totalLoansOutstanding = totalLoansOutstanding;
storage.taxDebt = taxDebt;
storage.taxDueDate = taxDueDate;
storage.taxOverdueDate = taxOverdueDate;
storage.lastTaxDay = lastTaxDay;
storage.motorcycleUnlocked = motorcycleUnlocked;
storage.vanUnlocked = vanUnlocked;
storage.soundEffectsEnabled = soundEffectsEnabled;
// Store each vehicle property as separate arrays to avoid nested objects
var vehicleCount = ownedVehicles.length;
storage.vehicleCount = vehicleCount;
storage.vehicleMakes = [];
storage.vehicleModels = [];
storage.vehicleConditions = [];
storage.vehicleActualConditions = [];
storage.vehicleMileages = [];
storage.vehicleActualMileages = [];
storage.vehiclePrices = [];
storage.vehicleMarketValues = [];
storage.vehicleSellerLying = [];
storage.vehicleIds = [];
storage.vehicleRepaired = [];
storage.vehicleInRepair = [];
storage.vehicleRepairCompletionDay = [];
for (var i = 0; i < ownedVehicles.length; i++) {
var vehicle = ownedVehicles[i];
storage.vehicleMakes.push(vehicle.make);
storage.vehicleModels.push(vehicle.model);
storage.vehicleConditions.push(vehicle.condition);
storage.vehicleActualConditions.push(vehicle.actualCondition);
storage.vehicleMileages.push(vehicle.mileage);
storage.vehicleActualMileages.push(vehicle.actualMileage);
storage.vehiclePrices.push(vehicle.price);
storage.vehicleMarketValues.push(vehicle.marketValue);
storage.vehicleSellerLying.push(vehicle.sellerLying);
storage.vehicleIds.push(vehicle.id);
storage.vehicleRepaired.push(vehicle.repaired || false);
storage.vehicleInRepair.push(vehicle.inRepair || false);
storage.vehicleRepairCompletionDay.push(vehicle.repairCompletionDay || 0);
}
// Save repair shop data
storage.vehiclesInRepairCount = vehiclesInRepair.length;
storage.repairVehicleIds = [];
storage.repairCompletionDays = [];
storage.repairDurations = [];
for (var r = 0; r < vehiclesInRepair.length; r++) {
storage.repairVehicleIds.push(vehiclesInRepair[r].vehicleId);
storage.repairCompletionDays.push(vehiclesInRepair[r].completionDay);
storage.repairDurations.push(vehiclesInRepair[r].repairDuration);
}
// Save motorcycle data
var motorcycleCount = ownedMotorcycles.length;
storage.motorcycleCount = motorcycleCount;
storage.motorcycleMakes = [];
storage.motorcycleModels = [];
storage.motorcycleConditions = [];
storage.motorcycleActualConditions = [];
storage.motorcycleMileages = [];
storage.motorcycleActualMileages = [];
storage.motorcyclePrices = [];
storage.motorcycleMarketValues = [];
storage.motorcycleSellerLying = [];
storage.motorcycleIds = [];
storage.motorcycleRepaired = [];
storage.motorcycleInRepair = [];
storage.motorcycleRepairCompletionDay = [];
for (var m = 0; m < ownedMotorcycles.length; m++) {
var motorcycle = ownedMotorcycles[m];
storage.motorcycleMakes.push(motorcycle.make);
storage.motorcycleModels.push(motorcycle.model);
storage.motorcycleConditions.push(motorcycle.condition);
storage.motorcycleActualConditions.push(motorcycle.actualCondition);
storage.motorcycleMileages.push(motorcycle.mileage);
storage.motorcycleActualMileages.push(motorcycle.actualMileage);
storage.motorcyclePrices.push(motorcycle.price);
storage.motorcycleMarketValues.push(motorcycle.marketValue);
storage.motorcycleSellerLying.push(motorcycle.sellerLying);
storage.motorcycleIds.push(motorcycle.id);
storage.motorcycleRepaired.push(motorcycle.repaired || false);
storage.motorcycleInRepair.push(motorcycle.inRepair || false);
storage.motorcycleRepairCompletionDay.push(motorcycle.repairCompletionDay || 0);
}
// Save motorcycle repair shop data
storage.motorcyclesInRepairCount = motorcyclesInRepair.length;
storage.repairMotoVehicleIds = [];
storage.repairMotoCompletionDays = [];
storage.repairMotoDurations = [];
for (var mr = 0; mr < motorcyclesInRepair.length; mr++) {
storage.repairMotoVehicleIds.push(motorcyclesInRepair[mr].vehicleId);
storage.repairMotoCompletionDays.push(motorcyclesInRepair[mr].completionDay);
storage.repairMotoDurations.push(motorcyclesInRepair[mr].repairDuration);
}
// Save van data
var vanCount = ownedVans.length;
storage.vanCount = vanCount;
storage.vanMakes = [];
storage.vanModels = [];
storage.vanConditions = [];
storage.vanActualConditions = [];
storage.vanMileages = [];
storage.vanActualMileages = [];
storage.vanPrices = [];
storage.vanMarketValues = [];
storage.vanSellerLying = [];
storage.vanIds = [];
storage.vanRepaired = [];
storage.vanInRepair = [];
storage.vanRepairCompletionDay = [];
for (var v = 0; v < ownedVans.length; v++) {
var van = ownedVans[v];
storage.vanMakes.push(van.make);
storage.vanModels.push(van.model);
storage.vanConditions.push(van.condition);
storage.vanActualConditions.push(van.actualCondition);
storage.vanMileages.push(van.mileage);
storage.vanActualMileages.push(van.actualMileage);
storage.vanPrices.push(van.price);
storage.vanMarketValues.push(van.marketValue);
storage.vanSellerLying.push(van.sellerLying);
storage.vanIds.push(van.id);
storage.vanRepaired.push(van.repaired || false);
storage.vanInRepair.push(van.inRepair || false);
storage.vanRepairCompletionDay.push(van.repairCompletionDay || 0);
}
// Save van repair shop data
storage.vansInRepairCount = vansInRepair.length;
storage.repairVanVehicleIds = [];
storage.repairVanCompletionDays = [];
storage.repairVanDurations = [];
for (var vr = 0; vr < vansInRepair.length; vr++) {
storage.repairVanVehicleIds.push(vansInRepair[vr].vehicleId);
storage.repairVanCompletionDays.push(vansInRepair[vr].completionDay);
storage.repairVanDurations.push(vansInRepair[vr].repairDuration);
}
}
// Add maintenance costs for owned vehicles
function applyMaintenanceCosts() {
var totalMaintenanceCost = 0;
for (var i = 0; i < ownedVehicles.length; i++) {
var vehicle = ownedVehicles[i];
// Higher maintenance cost for damaged vehicles
var baseCost = vehicle.actualCondition === 'damaged' ? 200 : 100;
var maintenanceCost = Math.floor(Math.random() * baseCost) + 50;
totalMaintenanceCost += maintenanceCost;
}
if (totalMaintenanceCost > 0) {
playerMoney -= totalMaintenanceCost;
return totalMaintenanceCost;
}
return 0;
}
// Apply vehicle depreciation
function applyVehicleDepreciation() {
for (var i = 0; i < ownedVehicles.length; i++) {
var vehicle = ownedVehicles[i];
// Vehicles lose 2-5% of their market value each day
var depreciationRate = Math.random() * 0.03 + 0.02;
vehicle.marketValue = Math.floor(vehicle.marketValue * (1 - depreciationRate));
// Minimum market value floor
if (vehicle.marketValue < 1000) {
vehicle.marketValue = 1000;
}
}
}
// Initialize game
updateDebtDisplay();
updateTaxDisplay();
generateDailyOffers();
if (motorcycleUnlocked) {
generateDailyMotoOffers();
}
displayVehicles(dailyOffers);
updateUI();
// Game restart function
function restartGame() {
// Reset all game state variables to initial values
playerMoney = 50000;
currentDay = 1;
playerDebt = 0;
taxDebt = 0;
taxDueDate = 0;
taxOverdueDate = 0;
lastTaxDay = 0;
ownedVehicles = [];
vehiclesInRepair = [];
motorcycleUnlocked = false;
ownedMotorcycles = [];
motorcyclesInRepair = [];
vehicleType = 'cars';
selectedVehicle = null;
gameState = 'daily_offers';
vehicleLocksButton.visible = !motorcycleUnlocked || !vanUnlocked;
// Clear storage
delete storage.playerMoney;
delete storage.currentDay;
delete storage.playerDebt;
delete storage.taxDebt;
delete storage.taxDueDate;
delete storage.taxOverdueDate;
delete storage.lastTaxDay;
delete storage.vehicleCount;
delete storage.vehicleMakes;
delete storage.vehicleModels;
delete storage.vehicleConditions;
delete storage.vehicleActualConditions;
delete storage.vehicleMileages;
delete storage.vehicleActualMileages;
delete storage.vehiclePrices;
delete storage.vehicleMarketValues;
delete storage.vehicleSellerLying;
delete storage.vehicleIds;
delete storage.vehicleRepaired;
delete storage.vehicleInRepair;
delete storage.vehicleRepairCompletionDay;
delete storage.vehiclesInRepairCount;
delete storage.repairVehicleIds;
delete storage.repairCompletionDays;
delete storage.repairDurations;
delete storage.motorcycleUnlocked;
delete storage.motorcycleCount;
delete storage.motorcycleMakes;
delete storage.motorcycleModels;
delete storage.motorcycleConditions;
delete storage.motorcycleActualConditions;
delete storage.motorcycleMileages;
delete storage.motorcycleActualMileages;
delete storage.motorcyclePrices;
delete storage.motorcycleMarketValues;
delete storage.motorcycleSellerLying;
delete storage.motorcycleIds;
delete storage.motorcycleRepaired;
delete storage.motorcycleInRepair;
delete storage.motorcycleRepairCompletionDay;
delete storage.motorcyclesInRepairCount;
delete storage.repairMotoVehicleIds;
delete storage.repairMotoCompletionDays;
delete storage.repairMotoDurations;
// Update UI elements
stateText.setText('Daily Vehicle Offers');
dayText.setText('Day ' + currentDay);
updateMoneyDisplay();
updateDebtDisplay();
updateTaxDisplay();
generateDailyOffers();
displayVehicles(dailyOffers);
updateUI();
infoText.setText('Game restarted! Welcome back to Car Dealer Tycoon!');
}
// Game update loop
game.update = function () {
// Check for game over condition
if (playerMoney < 0) {
LK.showGameOver();
// Reset game state for restart
restartGame();
}
// Check for winning condition
if (playerMoney >= 500000) {
LK.showYouWin();
// Reset game state for restart
restartGame();
}
};