User prompt
Long titled buttons are overlapping
User prompt
Make the spaces between each button even smaller and make sure sandbox unlocks every designs, system. Also consider adding a arrow that collapses it ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Add boat designs and consider resizing various words on the buttons because it goes past the button
User prompt
make sure article goes in front of the buttons and the higher the lifespan number the faster the days go down so players dont need to wait to see it go to zero. Also buttons are going past boundaries squeeze it a bot
User prompt
Add even more materials like alloys, graphene, heavy motor, and more like safety systems and a whole new class players could add crew type now. Make sure none of the materials or designs or safety or crew needs boats launched, only lifespan, also add a sandbox button to unlock everything ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
When players do various combos or reach a high amount of lifespan on a ship to unlock materials, propulsions, safety systems, and designs. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Add propulsion and safety systems as selectable options to boost ship lifespan even more
User prompt
Let players also have the option to add propulsion and safety systems
User prompt
Pretend survival time is in months, years, and days.
User prompt
Timelapse how long it lasted, example randomizing lifespan based on accidents.
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'var localPos = self.toLocal(obj.parent.toGlobal(obj.position));' Line Number: 83
User prompt
Still does not work.
User prompt
fix article
User prompt
Doesnt work make a modular article system also make sure article color is brown.
User prompt
Things work, but result doesn’t, make it so that after the player makes the boat a news article appears and a red x can be used to exit the article
User prompt
The Ui keeps flashing from blue to black, set ui to black and white
User prompt
Please fix the bug: 'Timeout.tick error: null is not an object (evaluating 'materialData.name')' in or related to this line: 'newsPanel.showNews(materialData.name, designData.name, survivalTime, disaster);' Line Number: 363
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'var savedLaunches = storage.get('launches') || [];' Line Number: 343
User prompt
Completely revamp building system. Were players chose one material, one design, and then see it a news article about were it died, how long it lasted and a procedurally generated reason of accident and problems
Code edit (1 edits merged)
Please save this source code
User prompt
Faithless
Initial prompt
Make a game called Faithless, about making boats and seeing horrible accidents go on with them.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Article = Container.expand(function (title, content) { var self = Container.call(this); self.visible = false; var background = self.attachAsset('newsPanel', { anchorX: 0.5, anchorY: 0.5 }); background.tint = 0x8b4513; // Brown color var titleText = new Text2(title, { size: 60, fill: 0xffffff }); titleText.anchor.set(0.5, 0); titleText.y = -550; self.addChild(titleText); var contentText = new Text2(content, { size: 40, fill: 0xffffff, wordWrap: true, wordWrapWidth: 1600 }); contentText.anchor.set(0.5, 0); contentText.y = -400; self.addChild(contentText); var closeButton = self.attachAsset('materialButton', { anchorX: 0.5, anchorY: 0.5, x: 800, y: -550, scaleX: 0.5, scaleY: 0.5 }); closeButton.tint = 0xff0000; var closeText = new Text2('X', { size: 60, fill: 0xffffff }); closeText.anchor.set(0.5, 0.5); closeText.x = 800; closeText.y = -550; self.addChild(closeText); self.updateContent = function (newTitle, newContent) { if (titleText && contentText) { titleText.setText(newTitle); contentText.setText(newContent); console.log('Article content updated:', newTitle, newContent); } else { console.log('Text objects not available for update'); } }; self.show = function () { console.log('Showing article, current visibility:', self.visible); self.visible = true; self.alpha = 1; console.log('Article visibility set to:', self.visible); LK.getSound('newspaper').play(); }; self.hide = function () { self.visible = false; }; self.down = function (x, y, obj) { if (self.visible) { // Check if click is near the X button (top right area) // Use the passed x, y coordinates directly as they are already in local space if (x > 700 && x < 900 && y > -600 && y < -500) { self.hide(); } } }; return self; }); var CrewButton = Container.expand(function (crewType, crewName, x, y) { var self = Container.call(this); self.crewType = crewType; self.crewName = crewName; self.selected = false; var background = self.attachAsset('designButton', { anchorX: 0.5, anchorY: 0.5 }); background.tint = 0x9932cc; // Dark orchid for crew var nameText = new Text2(crewName, { size: 18, fill: 0xffffff }); nameText.anchor.set(0.5, 0.5); self.addChild(nameText); self.x = x; self.y = y; self.updateVisual = function () { if (self.selected) { background.tint = 0x00ff00; } else { background.tint = 0x9932cc; } }; self.down = function (x, y, obj) { selectCrew(self.crewType); }; return self; }); var DesignButton = Container.expand(function (designType, designName, x, y) { var self = Container.call(this); self.designType = designType; self.designName = designName; self.selected = false; var background = self.attachAsset('designButton', { anchorX: 0.5, anchorY: 0.5 }); var nameText = new Text2(designName, { size: 18, fill: 0xffffff }); nameText.anchor.set(0.5, 0.5); self.addChild(nameText); self.x = x; self.y = y; self.updateVisual = function () { if (self.selected) { background.tint = 0x00ff00; } else { background.tint = 0xffffff; } }; self.down = function (x, y, obj) { selectDesign(self.designType); }; return self; }); var MaterialButton = Container.expand(function (materialType, materialName, x, y) { var self = Container.call(this); self.materialType = materialType; self.materialName = materialName; self.selected = false; var background = self.attachAsset('materialButton', { anchorX: 0.5, anchorY: 0.5 }); var nameText = new Text2(materialName, { size: 18, fill: 0xffffff }); nameText.anchor.set(0.5, 0.5); self.addChild(nameText); self.x = x; self.y = y; self.updateVisual = function () { if (self.selected) { background.tint = 0x00ff00; } else { background.tint = 0xffffff; } }; self.down = function (x, y, obj) { selectMaterial(self.materialType); }; return self; }); var NewsPanel = Container.expand(function () { var self = Container.call(this); self.currentArticle = null; self.formatSurvivalTime = function (timeInTicks) { var totalDays = Math.floor(timeInTicks / 60); var years = Math.floor(totalDays / 365); var remainingDays = totalDays % 365; var months = Math.floor(remainingDays / 30); var days = remainingDays % 30; var timeStr = ''; if (years > 0) timeStr += years + ' years, '; if (months > 0) timeStr += months + ' months, '; timeStr += days + ' days'; return timeStr; }; self.showNews = function (material, design, survivalTime, disaster) { var title = 'MARITIME DISASTER REPORT'; var content = 'VESSEL SPECIFICATIONS:\n'; content += 'Material: ' + material + '\n'; content += 'Design: ' + design + '\n\n'; content += 'SURVIVAL TIME: ' + self.formatSurvivalTime(survivalTime) + '\n\n'; content += 'CAUSE OF DISASTER:\n' + disaster; console.log('Showing news with:', title, content); if (self.currentArticle) { self.currentArticle.updateContent(title, content); self.currentArticle.show(); console.log('Article shown successfully'); } else { console.log('No article available to show news'); } }; return self; }); var PropulsionButton = Container.expand(function (propulsionType, propulsionName, x, y) { var self = Container.call(this); self.propulsionType = propulsionType; self.propulsionName = propulsionName; self.selected = false; var background = self.attachAsset('designButton', { anchorX: 0.5, anchorY: 0.5 }); background.tint = 0x4169e1; // Steel blue for propulsion var nameText = new Text2(propulsionName, { size: 18, fill: 0xffffff }); nameText.anchor.set(0.5, 0.5); self.addChild(nameText); self.x = x; self.y = y; self.updateVisual = function () { if (self.selected) { background.tint = 0x00ff00; } else { background.tint = 0x4169e1; } }; self.down = function (x, y, obj) { selectPropulsion(self.propulsionType); }; return self; }); var SafetyButton = Container.expand(function (safetyType, safetyName, x, y) { var self = Container.call(this); self.safetyType = safetyType; self.safetyName = safetyName; self.selected = false; var background = self.attachAsset('materialButton', { anchorX: 0.5, anchorY: 0.5 }); background.tint = 0xff6347; // Tomato red for safety var nameText = new Text2(safetyName, { size: 18, fill: 0xffffff }); nameText.anchor.set(0.5, 0.5); self.addChild(nameText); self.x = x; self.y = y; self.updateVisual = function () { if (self.selected) { background.tint = 0x00ff00; } else { background.tint = 0xff6347; } }; self.down = function (x, y, obj) { selectSafety(self.safetyType); }; return self; }); var TimerDisplay = Container.expand(function () { var self = Container.call(this); self.visible = false; self.currentTime = 0; self.maxTime = 0; self.isActive = false; var background = self.attachAsset('timerPanel', { anchorX: 0.5, anchorY: 0.5 }); var titleText = new Text2('VESSEL STATUS', { size: 32, fill: 0xffffff }); titleText.anchor.set(0.5, 0.5); titleText.y = -60; self.addChild(titleText); var timeText = new Text2('0.0s', { size: 48, fill: 0x00ff00 }); timeText.anchor.set(0.5, 0.5); timeText.y = -10; self.addChild(timeText); var statusText = new Text2('OPERATIONAL', { size: 28, fill: 0x00ff00 }); statusText.anchor.set(0.5, 0.5); statusText.y = 40; self.addChild(statusText); self.formatTime = function (timeInTicks) { // Convert ticks to days (assuming 1 tick = 1 day for dramatic effect) var totalDays = Math.floor(timeInTicks / 60); var years = Math.floor(totalDays / 365); var remainingDays = totalDays % 365; var months = Math.floor(remainingDays / 30); var days = remainingDays % 30; var timeStr = ''; if (years > 0) timeStr += years + 'y '; if (months > 0) timeStr += months + 'm '; timeStr += days + 'd'; return timeStr; }; self.startTimer = function (maxSurvivalTime) { self.currentTime = maxSurvivalTime; self.maxTime = maxSurvivalTime; self.isActive = true; self.visible = true; timeText.setText(self.formatTime(self.currentTime)); timeText.tint = 0x00ff00; statusText.setText('OPERATIONAL'); statusText.tint = 0x00ff00; // Position timer in top right area self.x = 1700; self.y = 200; }; self.update = function () { if (self.isActive && self.currentTime > 0) { // Calculate speed multiplier based on total survival time // Higher survival time = faster countdown for better UX var speedMultiplier = 1; if (self.maxTime > 3600) { // More than 1 hour (60 days) speedMultiplier = 5; } else if (self.maxTime > 1800) { // More than 30 minutes (30 days) speedMultiplier = 3; } else if (self.maxTime > 600) { // More than 10 minutes (10 days) speedMultiplier = 2; } self.currentTime -= speedMultiplier; if (self.currentTime < 0) self.currentTime = 0; timeText.setText(self.formatTime(self.currentTime)); // Change color based on remaining time var timeRatio = self.currentTime / self.maxTime; if (timeRatio > 0.5) { timeText.tint = 0x00ff00; // Green statusText.tint = 0x00ff00; } else if (timeRatio > 0.25) { timeText.tint = 0xffff00; // Yellow statusText.tint = 0xffff00; statusText.setText('CRITICAL'); } else { timeText.tint = 0xff0000; // Red statusText.tint = 0xff0000; statusText.setText('FAILING'); } // Play tick sound every second (60 ticks) if (self.currentTime % 60 === 0 && self.currentTime > 0) { LK.getSound('tick').play(); } // When time runs out if (self.currentTime <= 0) { self.isActive = false; timeText.setText('0d'); timeText.tint = 0xff0000; statusText.setText('DESTROYED'); statusText.tint = 0xff0000; LK.getSound('explosion').play(); LK.effects.flashScreen(0xff0000, 1000); // Hide timer after 3 seconds LK.setTimeout(function () { self.visible = false; }, 3000); } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Game state variables var selectedMaterial = null; var selectedDesign = null; var selectedPropulsion = null; var selectedSafety = null; var selectedCrew = null; var totalBoatsLaunched = 0; var materialButtons = []; var designButtons = []; var propulsionButtons = []; var safetyButtons = []; var crewButtons = []; var newsPanel = null; var timerDisplay = null; // Initialize storage for unlockables var unlockedMaterials = storage.unlockedMaterials || ['wood', 'plastic']; var unlockedDesigns = storage.unlockedDesigns || ['fishing']; var unlockedPropulsion = storage.unlockedPropulsion || ['basic']; var unlockedSafety = storage.unlockedSafety || ['basic']; var unlockedCrew = storage.unlockedCrew || ['rookie']; var bestSurvivalTime = storage.bestSurvivalTime || 0; var totalCombos = storage.totalCombos || 0; // Crew system data var crewSystems = [{ type: 'rookie', name: 'Rookie Crew', skill: 1.0, boost: 1.1 }, { type: 'experienced', name: 'Experienced Crew', skill: 1.3, boost: 1.4 }, { type: 'elite', name: 'Elite Crew', skill: 1.6, boost: 1.7 }, { type: 'captain', name: 'Legendary Captain', skill: 2.0, boost: 2.2 }, { type: 'ai_crew', name: 'AI Crew', skill: 2.5, boost: 2.7 }, { type: 'super_human', name: 'Super Human Crew', skill: 3.0, boost: 3.2 }]; // Material data var materials = [{ type: 'wood', name: 'Wood', durability: 50, cost: 25 }, { type: 'steel', name: 'Steel', durability: 80, cost: 45 }, { type: 'plastic', name: 'Plastic', durability: 30, cost: 15 }, { type: 'aluminum', name: 'Aluminum', durability: 70, cost: 35 }, { type: 'titanium', name: 'Titanium', durability: 120, cost: 85 }, { type: 'carbon_fiber', name: 'Carbon Fiber', durability: 140, cost: 100 }, { type: 'graphene', name: 'Graphene', durability: 200, cost: 150 }, { type: 'alloy_composite', name: 'Alloy Composite', durability: 160, cost: 120 }, { type: 'bio_material', name: 'Bio Material', durability: 90, cost: 60 }]; // Design data var designs = [{ type: 'fishing', name: 'Fishing Boat', stability: 60, speed: 40 }, { type: 'yacht', name: 'Luxury Yacht', stability: 40, speed: 80 }, { type: 'cargo', name: 'Cargo Ship', stability: 80, speed: 20 }, { type: 'speedboat', name: 'Speed Boat', stability: 30, speed: 90 }, { type: 'submarine', name: 'Submarine', stability: 90, speed: 50 }, { type: 'battleship', name: 'Battleship', stability: 95, speed: 35 }, { type: 'catamaran', name: 'Catamaran', stability: 75, speed: 70 }, { type: 'icebreaker', name: 'Icebreaker', stability: 100, speed: 25 }, { type: 'hovercraft', name: 'Hovercraft', stability: 45, speed: 85 }]; // Propulsion system data var propulsionSystems = [{ type: 'basic', name: 'Basic Motor', reliability: 1.0, boost: 1.1 }, { type: 'advanced', name: 'Advanced Engine', reliability: 1.2, boost: 1.3 }, { type: 'hybrid', name: 'Hybrid System', reliability: 1.4, boost: 1.5 }, { type: 'nuclear', name: 'Nuclear Reactor', reliability: 1.8, boost: 2.0 }, { type: 'heavy_motor', name: 'Heavy Motor', reliability: 1.6, boost: 1.7 }, { type: 'plasma_drive', name: 'Plasma Drive', reliability: 2.2, boost: 2.4 }, { type: 'ion_drive', name: 'Ion Drive', reliability: 2.8, boost: 3.0 }, { type: 'antimatter_engine', name: 'Antimatter Engine', reliability: 3.5, boost: 3.8 }]; // Safety system data var safetySystems = [{ type: 'basic', name: 'Life Jackets', protection: 1.0, boost: 1.1 }, { type: 'standard', name: 'Emergency Kit', protection: 1.2, boost: 1.3 }, { type: 'advanced', name: 'Auto-Pilot', protection: 1.5, boost: 1.6 }, { type: 'military', name: 'Military Grade', protection: 2.0, boost: 2.2 }, { type: 'emergency_beacon', name: 'Emergency Beacon', protection: 1.3, boost: 1.4 }, { type: 'hull_reinforcement', name: 'Hull Reinforcement', protection: 1.8, boost: 1.9 }, { type: 'ai_navigation', name: 'AI Navigation', protection: 2.5, boost: 2.7 }, { type: 'shield_system', name: 'Shield System', protection: 3.0, boost: 3.2 }]; // Disaster scenarios var disasters = ['Structural failure due to poor material choice', 'Capsized in rough waters due to design instability', 'Engine explosion caused by manufacturing defects', 'Hull breach from collision with debris', 'Overloading beyond design capacity', 'Fire spread rapidly through cheap materials', 'Steering system malfunction in storm', 'Crew error compounded by design flaws']; // Create UI var scoreText = new Text2('Boats Launched: 0', { size: 60, fill: 0xffffff }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); var instructionText = new Text2('Select material, design, propulsion, safety, and crew to launch!', { size: 40, fill: 0xffffff }); instructionText.anchor.set(0.5, 0); instructionText.y = 80; LK.gui.top.addChild(instructionText); // Create material selection area var materialTitle = new Text2('SELECT MATERIAL:', { size: 50, fill: 0xffffff }); materialTitle.anchor.set(0.5, 0.5); materialTitle.x = 1024; materialTitle.y = 400; game.addChild(materialTitle); // Create material buttons var materialIndex = 0; for (var i = 0; i < materials.length; i++) { if (unlockedMaterials.indexOf(materials[i].type) !== -1) { var materialButton = new MaterialButton(materials[i].type, materials[i].name, 200 + materialIndex * 150, 550); game.addChild(materialButton); materialButtons.push(materialButton); materialIndex++; } } // Create design selection area var designTitle = new Text2('SELECT DESIGN:', { size: 50, fill: 0xffffff }); designTitle.anchor.set(0.5, 0.5); designTitle.x = 1024; designTitle.y = 800; game.addChild(designTitle); // Create design buttons var designIndex = 0; for (var i = 0; i < designs.length; i++) { if (unlockedDesigns.indexOf(designs[i].type) !== -1) { var designButton = new DesignButton(designs[i].type, designs[i].name, 200 + designIndex * 150, 950); game.addChild(designButton); designButtons.push(designButton); designIndex++; } } // Create propulsion selection area var propulsionTitle = new Text2('SELECT PROPULSION:', { size: 50, fill: 0xffffff }); propulsionTitle.anchor.set(0.5, 0.5); propulsionTitle.x = 1024; propulsionTitle.y = 1200; game.addChild(propulsionTitle); // Create propulsion buttons var propulsionIndex = 0; for (var i = 0; i < propulsionSystems.length; i++) { if (unlockedPropulsion.indexOf(propulsionSystems[i].type) !== -1) { var propulsionButton = new PropulsionButton(propulsionSystems[i].type, propulsionSystems[i].name, 200 + propulsionIndex * 150, 1350); game.addChild(propulsionButton); propulsionButtons.push(propulsionButton); propulsionIndex++; } } // Create safety selection area var safetyTitle = new Text2('SELECT SAFETY SYSTEM:', { size: 50, fill: 0xffffff }); safetyTitle.anchor.set(0.5, 0.5); safetyTitle.x = 1024; safetyTitle.y = 1600; game.addChild(safetyTitle); // Create safety buttons var safetyIndex = 0; for (var i = 0; i < safetySystems.length; i++) { if (unlockedSafety.indexOf(safetySystems[i].type) !== -1) { var safetyButton = new SafetyButton(safetySystems[i].type, safetySystems[i].name, 200 + safetyIndex * 150, 1750); game.addChild(safetyButton); safetyButtons.push(safetyButton); safetyIndex++; } } // Create crew selection area var crewTitle = new Text2('SELECT CREW:', { size: 50, fill: 0xffffff }); crewTitle.anchor.set(0.5, 0.5); crewTitle.x = 1024; crewTitle.y = 2000; game.addChild(crewTitle); // Create crew buttons var crewIndex = 0; for (var i = 0; i < crewSystems.length; i++) { if (unlockedCrew.indexOf(crewSystems[i].type) !== -1) { var crewButton = new CrewButton(crewSystems[i].type, crewSystems[i].name, 200 + crewIndex * 150, 2150); game.addChild(crewButton); crewButtons.push(crewButton); crewIndex++; } } // Create launch button var launchButton = game.addChild(LK.getAsset('launchButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 2400 })); var launchText = new Text2('LAUNCH VESSEL', { size: 50, fill: 0xffffff }); launchText.anchor.set(0.5, 0.5); launchText.x = 1024; launchText.y = 2400; game.addChild(launchText); // Create news panel with article system newsPanel = new NewsPanel(); // Create timer display timerDisplay = new TimerDisplay(); game.addChild(timerDisplay); // Create sandbox button var sandboxButton = game.addChild(LK.getAsset('materialButton', { anchorX: 0.5, anchorY: 0.5, x: 1700, y: 2600, scaleX: 0.8, scaleY: 0.8 })); sandboxButton.tint = 0xffd700; // Gold color var sandboxText = new Text2('SANDBOX', { size: 32, fill: 0x000000 }); sandboxText.anchor.set(0.5, 0.5); sandboxText.x = 1700; sandboxText.y = 2600; game.addChild(sandboxText); function selectMaterial(materialType) { selectedMaterial = materialType; // Update button visuals for (var i = 0; i < materialButtons.length; i++) { materialButtons[i].selected = materialButtons[i].materialType === materialType; materialButtons[i].updateVisual(); } } function selectDesign(designType) { selectedDesign = designType; // Update button visuals for (var i = 0; i < designButtons.length; i++) { designButtons[i].selected = designButtons[i].designType === designType; designButtons[i].updateVisual(); } } function selectPropulsion(propulsionType) { selectedPropulsion = propulsionType; // Update button visuals for (var i = 0; i < propulsionButtons.length; i++) { propulsionButtons[i].selected = propulsionButtons[i].propulsionType === propulsionType; propulsionButtons[i].updateVisual(); } } function selectSafety(safetyType) { selectedSafety = safetyType; // Update button visuals for (var i = 0; i < safetyButtons.length; i++) { safetyButtons[i].selected = safetyButtons[i].safetyType === safetyType; safetyButtons[i].updateVisual(); } } function getMaterialData(materialType) { for (var i = 0; i < materials.length; i++) { if (materials[i].type === materialType) { return materials[i]; } } return null; } function getDesignData(designType) { for (var i = 0; i < designs.length; i++) { if (designs[i].type === designType) { return designs[i]; } } return null; } function getPropulsionData(propulsionType) { for (var i = 0; i < propulsionSystems.length; i++) { if (propulsionSystems[i].type === propulsionType) { return propulsionSystems[i]; } } return null; } function getSafetyData(safetyType) { for (var i = 0; i < safetySystems.length; i++) { if (safetySystems[i].type === safetyType) { return safetySystems[i]; } } return null; } function selectCrew(crewType) { selectedCrew = crewType; // Update button visuals for (var i = 0; i < crewButtons.length; i++) { crewButtons[i].selected = crewButtons[i].crewType === crewType; crewButtons[i].updateVisual(); } } function getCrewData(crewType) { for (var i = 0; i < crewSystems.length; i++) { if (crewSystems[i].type === crewType) { return crewSystems[i]; } } return null; } function unlockEverything() { // Unlock all materials unlockedMaterials = []; for (var i = 0; i < materials.length; i++) { unlockedMaterials.push(materials[i].type); } // Unlock all designs unlockedDesigns = []; for (var i = 0; i < designs.length; i++) { unlockedDesigns.push(designs[i].type); } // Unlock all propulsion unlockedPropulsion = []; for (var i = 0; i < propulsionSystems.length; i++) { unlockedPropulsion.push(propulsionSystems[i].type); } // Unlock all safety unlockedSafety = []; for (var i = 0; i < safetySystems.length; i++) { unlockedSafety.push(safetySystems[i].type); } // Unlock all crew unlockedCrew = []; for (var i = 0; i < crewSystems.length; i++) { unlockedCrew.push(crewSystems[i].type); } // Save to storage storage.unlockedMaterials = unlockedMaterials; storage.unlockedDesigns = unlockedDesigns; storage.unlockedPropulsion = unlockedPropulsion; storage.unlockedSafety = unlockedSafety; storage.unlockedCrew = unlockedCrew; } function checkUnlocks(survivalTime) { var newUnlocks = []; // Track best survival time if (survivalTime > bestSurvivalTime) { bestSurvivalTime = survivalTime; storage.bestSurvivalTime = bestSurvivalTime; } // Track total combos tried totalCombos++; storage.totalCombos = totalCombos; // Unlock everything based on survival time only (in ticks, 60 ticks = 1 day) var daysSurvived = Math.floor(survivalTime / 60); var bestDays = Math.floor(bestSurvivalTime / 60); // Unlock materials based on survival time if (daysSurvived >= 5 && unlockedMaterials.indexOf('steel') === -1) { unlockedMaterials.push('steel'); newUnlocks.push('Steel material'); } if (daysSurvived >= 15 && unlockedMaterials.indexOf('aluminum') === -1) { unlockedMaterials.push('aluminum'); newUnlocks.push('Aluminum material'); } if (bestDays >= 25 && unlockedMaterials.indexOf('titanium') === -1) { unlockedMaterials.push('titanium'); newUnlocks.push('Titanium material'); } if (bestDays >= 40 && unlockedMaterials.indexOf('carbon_fiber') === -1) { unlockedMaterials.push('carbon_fiber'); newUnlocks.push('Carbon Fiber material'); } if (bestDays >= 60 && unlockedMaterials.indexOf('alloy_composite') === -1) { unlockedMaterials.push('alloy_composite'); newUnlocks.push('Alloy Composite material'); } if (bestDays >= 80 && unlockedMaterials.indexOf('bio_material') === -1) { unlockedMaterials.push('bio_material'); newUnlocks.push('Bio Material material'); } if (bestDays >= 100 && unlockedMaterials.indexOf('graphene') === -1) { unlockedMaterials.push('graphene'); newUnlocks.push('Graphene material'); } // Unlock designs based on survival time if (bestDays >= 8 && unlockedDesigns.indexOf('yacht') === -1) { unlockedDesigns.push('yacht'); newUnlocks.push('Luxury Yacht design'); } if (bestDays >= 20 && unlockedDesigns.indexOf('cargo') === -1) { unlockedDesigns.push('cargo'); newUnlocks.push('Cargo Ship design'); } if (bestDays >= 35 && unlockedDesigns.indexOf('speedboat') === -1) { unlockedDesigns.push('speedboat'); newUnlocks.push('Speed Boat design'); } if (bestDays >= 50 && unlockedDesigns.indexOf('submarine') === -1) { unlockedDesigns.push('submarine'); newUnlocks.push('Submarine design'); } if (bestDays >= 70 && unlockedDesigns.indexOf('catamaran') === -1) { unlockedDesigns.push('catamaran'); newUnlocks.push('Catamaran design'); } if (bestDays >= 90 && unlockedDesigns.indexOf('battleship') === -1) { unlockedDesigns.push('battleship'); newUnlocks.push('Battleship design'); } if (bestDays >= 110 && unlockedDesigns.indexOf('hovercraft') === -1) { unlockedDesigns.push('hovercraft'); newUnlocks.push('Hovercraft design'); } if (bestDays >= 130 && unlockedDesigns.indexOf('icebreaker') === -1) { unlockedDesigns.push('icebreaker'); newUnlocks.push('Icebreaker design'); } // Unlock propulsion based on survival time if (bestDays >= 10 && unlockedPropulsion.indexOf('advanced') === -1) { unlockedPropulsion.push('advanced'); newUnlocks.push('Advanced Engine propulsion'); } if (bestDays >= 30 && unlockedPropulsion.indexOf('hybrid') === -1) { unlockedPropulsion.push('hybrid'); newUnlocks.push('Hybrid System propulsion'); } if (bestDays >= 50 && unlockedPropulsion.indexOf('heavy_motor') === -1) { unlockedPropulsion.push('heavy_motor'); newUnlocks.push('Heavy Motor propulsion'); } if (bestDays >= 70 && unlockedPropulsion.indexOf('nuclear') === -1) { unlockedPropulsion.push('nuclear'); newUnlocks.push('Nuclear Reactor propulsion'); } if (bestDays >= 90 && unlockedPropulsion.indexOf('plasma_drive') === -1) { unlockedPropulsion.push('plasma_drive'); newUnlocks.push('Plasma Drive propulsion'); } if (bestDays >= 120 && unlockedPropulsion.indexOf('ion_drive') === -1) { unlockedPropulsion.push('ion_drive'); newUnlocks.push('Ion Drive propulsion'); } if (bestDays >= 150 && unlockedPropulsion.indexOf('antimatter_engine') === -1) { unlockedPropulsion.push('antimatter_engine'); newUnlocks.push('Antimatter Engine propulsion'); } // Unlock safety systems based on survival time if (bestDays >= 12 && unlockedSafety.indexOf('standard') === -1) { unlockedSafety.push('standard'); newUnlocks.push('Emergency Kit safety'); } if (bestDays >= 25 && unlockedSafety.indexOf('emergency_beacon') === -1) { unlockedSafety.push('emergency_beacon'); newUnlocks.push('Emergency Beacon safety'); } if (bestDays >= 40 && unlockedSafety.indexOf('advanced') === -1) { unlockedSafety.push('advanced'); newUnlocks.push('Auto-Pilot safety'); } if (bestDays >= 65 && unlockedSafety.indexOf('hull_reinforcement') === -1) { unlockedSafety.push('hull_reinforcement'); newUnlocks.push('Hull Reinforcement safety'); } if (bestDays >= 85 && unlockedSafety.indexOf('military') === -1) { unlockedSafety.push('military'); newUnlocks.push('Military Grade safety'); } if (bestDays >= 110 && unlockedSafety.indexOf('ai_navigation') === -1) { unlockedSafety.push('ai_navigation'); newUnlocks.push('AI Navigation safety'); } if (bestDays >= 140 && unlockedSafety.indexOf('shield_system') === -1) { unlockedSafety.push('shield_system'); newUnlocks.push('Shield System safety'); } // Unlock crew based on survival time if (bestDays >= 18 && unlockedCrew.indexOf('experienced') === -1) { unlockedCrew.push('experienced'); newUnlocks.push('Experienced Crew'); } if (bestDays >= 45 && unlockedCrew.indexOf('elite') === -1) { unlockedCrew.push('elite'); newUnlocks.push('Elite Crew'); } if (bestDays >= 75 && unlockedCrew.indexOf('captain') === -1) { unlockedCrew.push('captain'); newUnlocks.push('Legendary Captain'); } if (bestDays >= 105 && unlockedCrew.indexOf('ai_crew') === -1) { unlockedCrew.push('ai_crew'); newUnlocks.push('AI Crew'); } if (bestDays >= 135 && unlockedCrew.indexOf('super_human') === -1) { unlockedCrew.push('super_human'); newUnlocks.push('Super Human Crew'); } // Save unlocks to storage storage.unlockedMaterials = unlockedMaterials; storage.unlockedDesigns = unlockedDesigns; storage.unlockedPropulsion = unlockedPropulsion; storage.unlockedSafety = unlockedSafety; storage.unlockedCrew = unlockedCrew; // Show unlock notifications if (newUnlocks.length > 0) { var unlockMessage = 'NEW UNLOCKS:\n' + newUnlocks.join('\n'); LK.setTimeout(function () { if (newsPanel && newsPanel.currentArticle) { newsPanel.currentArticle.updateContent('UNLOCKS ACHIEVED!', unlockMessage); newsPanel.currentArticle.show(); } }, 4000); } return newUnlocks.length > 0; } function calculateSurvivalTime(material, design, propulsion, safety, crew) { var materialData = getMaterialData(material); var designData = getDesignData(design); if (!materialData || !designData) return 60; // Default 1 second // Base survival time with some randomness var baseTime = 180 + Math.random() * 600; // 3-13 seconds // Material affects durability baseTime *= materialData.durability / 50; // Design affects stability baseTime *= designData.stability / 50; // Apply propulsion system boost if (propulsion) { var propulsionData = getPropulsionData(propulsion); if (propulsionData) { baseTime *= propulsionData.boost; } } // Apply safety system boost if (safety) { var safetyData = getSafetyData(safety); if (safetyData) { baseTime *= safetyData.boost; } } // Apply crew boost if (crew) { var crewData = getCrewData(crew); if (crewData) { baseTime *= crewData.boost; } } // Add some chaos baseTime *= 0.5 + Math.random(); return Math.floor(baseTime); } function generateDisasterReport(material, design, survivalTime) { var materialData = getMaterialData(material); var designData = getDesignData(design); var randomDisaster = disasters[Math.floor(Math.random() * disasters.length)]; // Format survival time var totalDays = Math.floor(survivalTime / 60); var years = Math.floor(totalDays / 365); var remainingDays = totalDays % 365; var months = Math.floor(remainingDays / 30); var days = remainingDays % 30; var timeStr = ''; if (years > 0) timeStr += years + ' years, '; if (months > 0) timeStr += months + ' months, '; timeStr += days + ' days'; // Create more specific disaster based on choices var specificCause = ''; if (materialData.durability < 40) { specificCause = 'The cheap ' + materialData.name.toLowerCase() + ' construction proved inadequate for maritime conditions. '; } else if (designData.stability < 50) { specificCause = 'The ' + designData.name.toLowerCase() + ' design showed inherent stability issues. '; } return specificCause + randomDisaster + '. The vessel lasted ' + timeStr + ' before meeting its inevitable fate.'; } function launchVessel() { if (!selectedMaterial || !selectedDesign || !selectedPropulsion || !selectedSafety || !selectedCrew) { return; // Can't launch without all selections } totalBoatsLaunched++; scoreText.setText('Boats Launched: ' + totalBoatsLaunched); // Calculate how long this boat will survive var survivalTime = calculateSurvivalTime(selectedMaterial, selectedDesign, selectedPropulsion, selectedSafety, selectedCrew); // Generate disaster report var disaster = generateDisasterReport(selectedMaterial, selectedDesign, survivalTime); // Show launch effect LK.getSound('launch').play(); LK.effects.flashScreen(0x0000ff, 500); // Start the timelapse timer timerDisplay.startTimer(survivalTime); // Store this launch for potential leaderboard var launchData = { material: selectedMaterial, design: selectedDesign, survivalTime: survivalTime, disaster: disaster, timestamp: Date.now() }; var savedLaunches = []; try { savedLaunches = storage.get('launches') || []; } catch (e) { console.log('Storage not available, using empty array'); savedLaunches = []; } savedLaunches.push(launchData); if (savedLaunches.length > 50) { savedLaunches = savedLaunches.slice(-50); // Keep only last 50 } try { storage.set('launches', savedLaunches); } catch (e) { console.log('Could not save to storage'); } // Get material and design data before resetting selections var materialData = getMaterialData(selectedMaterial); var designData = getDesignData(selectedDesign); // Show news report after a delay LK.setTimeout(function () { newsPanel.showNews(materialData.name, designData.name, survivalTime, disaster); }, 2000); // Reset selections selectedMaterial = null; selectedDesign = null; selectedPropulsion = null; selectedSafety = null; selectedCrew = null; for (var i = 0; i < materialButtons.length; i++) { materialButtons[i].selected = false; materialButtons[i].updateVisual(); } for (var i = 0; i < designButtons.length; i++) { designButtons[i].selected = false; designButtons[i].updateVisual(); } for (var i = 0; i < propulsionButtons.length; i++) { propulsionButtons[i].selected = false; propulsionButtons[i].updateVisual(); } for (var i = 0; i < safetyButtons.length; i++) { safetyButtons[i].selected = false; safetyButtons[i].updateVisual(); } for (var i = 0; i < crewButtons.length; i++) { crewButtons[i].selected = false; crewButtons[i].updateVisual(); } // Check for unlocks var hasNewUnlocks = checkUnlocks(survivalTime); // Refresh UI if new unlocks were achieved if (hasNewUnlocks) { // Remove old buttons for (var i = 0; i < materialButtons.length; i++) { materialButtons[i].destroy(); } for (var i = 0; i < designButtons.length; i++) { designButtons[i].destroy(); } for (var i = 0; i < propulsionButtons.length; i++) { propulsionButtons[i].destroy(); } for (var i = 0; i < safetyButtons.length; i++) { safetyButtons[i].destroy(); } for (var i = 0; i < crewButtons.length; i++) { crewButtons[i].destroy(); } // Clear arrays materialButtons = []; designButtons = []; propulsionButtons = []; safetyButtons = []; crewButtons = []; // Recreate buttons with new unlocks var materialIndex = 0; for (var i = 0; i < materials.length; i++) { if (unlockedMaterials.indexOf(materials[i].type) !== -1) { var materialButton = new MaterialButton(materials[i].type, materials[i].name, 200 + materialIndex * 150, 550); game.addChild(materialButton); materialButtons.push(materialButton); materialIndex++; } } var designIndex = 0; for (var i = 0; i < designs.length; i++) { if (unlockedDesigns.indexOf(designs[i].type) !== -1) { var designButton = new DesignButton(designs[i].type, designs[i].name, 200 + designIndex * 150, 950); game.addChild(designButton); designButtons.push(designButton); designIndex++; } } var propulsionIndex = 0; for (var i = 0; i < propulsionSystems.length; i++) { if (unlockedPropulsion.indexOf(propulsionSystems[i].type) !== -1) { var propulsionButton = new PropulsionButton(propulsionSystems[i].type, propulsionSystems[i].name, 200 + propulsionIndex * 150, 1350); game.addChild(propulsionButton); propulsionButtons.push(propulsionButton); propulsionIndex++; } } var safetyIndex = 0; for (var i = 0; i < safetySystems.length; i++) { if (unlockedSafety.indexOf(safetySystems[i].type) !== -1) { var safetyButton = new SafetyButton(safetySystems[i].type, safetySystems[i].name, 200 + safetyIndex * 150, 1750); game.addChild(safetyButton); safetyButtons.push(safetyButton); safetyIndex++; } } var crewIndex = 0; for (var i = 0; i < crewSystems.length; i++) { if (unlockedCrew.indexOf(crewSystems[i].type) !== -1) { var crewButton = new CrewButton(crewSystems[i].type, crewSystems[i].name, 200 + crewIndex * 150, 2150); game.addChild(crewButton); crewButtons.push(crewButton); crewIndex++; } } } // Check for achievement if (totalBoatsLaunched >= 10) { LK.showYouWin(); } } // Event handlers launchButton.down = function (x, y, obj) { launchVessel(); }; sandboxButton.down = function (x, y, obj) { unlockEverything(); // Refresh all buttons for (var i = 0; i < materialButtons.length; i++) { materialButtons[i].destroy(); } for (var i = 0; i < designButtons.length; i++) { designButtons[i].destroy(); } for (var i = 0; i < propulsionButtons.length; i++) { propulsionButtons[i].destroy(); } for (var i = 0; i < safetyButtons.length; i++) { safetyButtons[i].destroy(); } for (var i = 0; i < crewButtons.length; i++) { crewButtons[i].destroy(); } // Clear arrays materialButtons = []; designButtons = []; propulsionButtons = []; safetyButtons = []; crewButtons = []; // Recreate all buttons var materialIndex = 0; for (var i = 0; i < materials.length; i++) { if (unlockedMaterials.indexOf(materials[i].type) !== -1) { var materialButton = new MaterialButton(materials[i].type, materials[i].name, 200 + materialIndex * 150, 550); game.addChild(materialButton); materialButtons.push(materialButton); materialIndex++; } } var designIndex = 0; for (var i = 0; i < designs.length; i++) { if (unlockedDesigns.indexOf(designs[i].type) !== -1) { var designButton = new DesignButton(designs[i].type, designs[i].name, 200 + designIndex * 150, 950); game.addChild(designButton); designButtons.push(designButton); designIndex++; } } var propulsionIndex = 0; for (var i = 0; i < propulsionSystems.length; i++) { if (unlockedPropulsion.indexOf(propulsionSystems[i].type) !== -1) { var propulsionButton = new PropulsionButton(propulsionSystems[i].type, propulsionSystems[i].name, 200 + propulsionIndex * 150, 1350); game.addChild(propulsionButton); propulsionButtons.push(propulsionButton); propulsionIndex++; } } var safetyIndex = 0; for (var i = 0; i < safetySystems.length; i++) { if (unlockedSafety.indexOf(safetySystems[i].type) !== -1) { var safetyButton = new SafetyButton(safetySystems[i].type, safetySystems[i].name, 200 + safetyIndex * 150, 1750); game.addChild(safetyButton); safetyButtons.push(safetyButton); safetyIndex++; } } var crewIndex = 0; for (var i = 0; i < crewSystems.length; i++) { if (unlockedCrew.indexOf(crewSystems[i].type) !== -1) { var crewButton = new CrewButton(crewSystems[i].type, crewSystems[i].name, 200 + crewIndex * 150, 2150); game.addChild(crewButton); crewButtons.push(crewButton); crewIndex++; } } }; // Create article at the end to ensure it appears in front of all buttons var article = new Article('', ''); article.x = 1024; article.y = 1366; game.addChild(article); newsPanel.currentArticle = article; game.update = function () { // Background stays consistently black - no flashing // Update timer display if (timerDisplay) { timerDisplay.update(); } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Article = Container.expand(function (title, content) {
var self = Container.call(this);
self.visible = false;
var background = self.attachAsset('newsPanel', {
anchorX: 0.5,
anchorY: 0.5
});
background.tint = 0x8b4513; // Brown color
var titleText = new Text2(title, {
size: 60,
fill: 0xffffff
});
titleText.anchor.set(0.5, 0);
titleText.y = -550;
self.addChild(titleText);
var contentText = new Text2(content, {
size: 40,
fill: 0xffffff,
wordWrap: true,
wordWrapWidth: 1600
});
contentText.anchor.set(0.5, 0);
contentText.y = -400;
self.addChild(contentText);
var closeButton = self.attachAsset('materialButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 800,
y: -550,
scaleX: 0.5,
scaleY: 0.5
});
closeButton.tint = 0xff0000;
var closeText = new Text2('X', {
size: 60,
fill: 0xffffff
});
closeText.anchor.set(0.5, 0.5);
closeText.x = 800;
closeText.y = -550;
self.addChild(closeText);
self.updateContent = function (newTitle, newContent) {
if (titleText && contentText) {
titleText.setText(newTitle);
contentText.setText(newContent);
console.log('Article content updated:', newTitle, newContent);
} else {
console.log('Text objects not available for update');
}
};
self.show = function () {
console.log('Showing article, current visibility:', self.visible);
self.visible = true;
self.alpha = 1;
console.log('Article visibility set to:', self.visible);
LK.getSound('newspaper').play();
};
self.hide = function () {
self.visible = false;
};
self.down = function (x, y, obj) {
if (self.visible) {
// Check if click is near the X button (top right area)
// Use the passed x, y coordinates directly as they are already in local space
if (x > 700 && x < 900 && y > -600 && y < -500) {
self.hide();
}
}
};
return self;
});
var CrewButton = Container.expand(function (crewType, crewName, x, y) {
var self = Container.call(this);
self.crewType = crewType;
self.crewName = crewName;
self.selected = false;
var background = self.attachAsset('designButton', {
anchorX: 0.5,
anchorY: 0.5
});
background.tint = 0x9932cc; // Dark orchid for crew
var nameText = new Text2(crewName, {
size: 18,
fill: 0xffffff
});
nameText.anchor.set(0.5, 0.5);
self.addChild(nameText);
self.x = x;
self.y = y;
self.updateVisual = function () {
if (self.selected) {
background.tint = 0x00ff00;
} else {
background.tint = 0x9932cc;
}
};
self.down = function (x, y, obj) {
selectCrew(self.crewType);
};
return self;
});
var DesignButton = Container.expand(function (designType, designName, x, y) {
var self = Container.call(this);
self.designType = designType;
self.designName = designName;
self.selected = false;
var background = self.attachAsset('designButton', {
anchorX: 0.5,
anchorY: 0.5
});
var nameText = new Text2(designName, {
size: 18,
fill: 0xffffff
});
nameText.anchor.set(0.5, 0.5);
self.addChild(nameText);
self.x = x;
self.y = y;
self.updateVisual = function () {
if (self.selected) {
background.tint = 0x00ff00;
} else {
background.tint = 0xffffff;
}
};
self.down = function (x, y, obj) {
selectDesign(self.designType);
};
return self;
});
var MaterialButton = Container.expand(function (materialType, materialName, x, y) {
var self = Container.call(this);
self.materialType = materialType;
self.materialName = materialName;
self.selected = false;
var background = self.attachAsset('materialButton', {
anchorX: 0.5,
anchorY: 0.5
});
var nameText = new Text2(materialName, {
size: 18,
fill: 0xffffff
});
nameText.anchor.set(0.5, 0.5);
self.addChild(nameText);
self.x = x;
self.y = y;
self.updateVisual = function () {
if (self.selected) {
background.tint = 0x00ff00;
} else {
background.tint = 0xffffff;
}
};
self.down = function (x, y, obj) {
selectMaterial(self.materialType);
};
return self;
});
var NewsPanel = Container.expand(function () {
var self = Container.call(this);
self.currentArticle = null;
self.formatSurvivalTime = function (timeInTicks) {
var totalDays = Math.floor(timeInTicks / 60);
var years = Math.floor(totalDays / 365);
var remainingDays = totalDays % 365;
var months = Math.floor(remainingDays / 30);
var days = remainingDays % 30;
var timeStr = '';
if (years > 0) timeStr += years + ' years, ';
if (months > 0) timeStr += months + ' months, ';
timeStr += days + ' days';
return timeStr;
};
self.showNews = function (material, design, survivalTime, disaster) {
var title = 'MARITIME DISASTER REPORT';
var content = 'VESSEL SPECIFICATIONS:\n';
content += 'Material: ' + material + '\n';
content += 'Design: ' + design + '\n\n';
content += 'SURVIVAL TIME: ' + self.formatSurvivalTime(survivalTime) + '\n\n';
content += 'CAUSE OF DISASTER:\n' + disaster;
console.log('Showing news with:', title, content);
if (self.currentArticle) {
self.currentArticle.updateContent(title, content);
self.currentArticle.show();
console.log('Article shown successfully');
} else {
console.log('No article available to show news');
}
};
return self;
});
var PropulsionButton = Container.expand(function (propulsionType, propulsionName, x, y) {
var self = Container.call(this);
self.propulsionType = propulsionType;
self.propulsionName = propulsionName;
self.selected = false;
var background = self.attachAsset('designButton', {
anchorX: 0.5,
anchorY: 0.5
});
background.tint = 0x4169e1; // Steel blue for propulsion
var nameText = new Text2(propulsionName, {
size: 18,
fill: 0xffffff
});
nameText.anchor.set(0.5, 0.5);
self.addChild(nameText);
self.x = x;
self.y = y;
self.updateVisual = function () {
if (self.selected) {
background.tint = 0x00ff00;
} else {
background.tint = 0x4169e1;
}
};
self.down = function (x, y, obj) {
selectPropulsion(self.propulsionType);
};
return self;
});
var SafetyButton = Container.expand(function (safetyType, safetyName, x, y) {
var self = Container.call(this);
self.safetyType = safetyType;
self.safetyName = safetyName;
self.selected = false;
var background = self.attachAsset('materialButton', {
anchorX: 0.5,
anchorY: 0.5
});
background.tint = 0xff6347; // Tomato red for safety
var nameText = new Text2(safetyName, {
size: 18,
fill: 0xffffff
});
nameText.anchor.set(0.5, 0.5);
self.addChild(nameText);
self.x = x;
self.y = y;
self.updateVisual = function () {
if (self.selected) {
background.tint = 0x00ff00;
} else {
background.tint = 0xff6347;
}
};
self.down = function (x, y, obj) {
selectSafety(self.safetyType);
};
return self;
});
var TimerDisplay = Container.expand(function () {
var self = Container.call(this);
self.visible = false;
self.currentTime = 0;
self.maxTime = 0;
self.isActive = false;
var background = self.attachAsset('timerPanel', {
anchorX: 0.5,
anchorY: 0.5
});
var titleText = new Text2('VESSEL STATUS', {
size: 32,
fill: 0xffffff
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -60;
self.addChild(titleText);
var timeText = new Text2('0.0s', {
size: 48,
fill: 0x00ff00
});
timeText.anchor.set(0.5, 0.5);
timeText.y = -10;
self.addChild(timeText);
var statusText = new Text2('OPERATIONAL', {
size: 28,
fill: 0x00ff00
});
statusText.anchor.set(0.5, 0.5);
statusText.y = 40;
self.addChild(statusText);
self.formatTime = function (timeInTicks) {
// Convert ticks to days (assuming 1 tick = 1 day for dramatic effect)
var totalDays = Math.floor(timeInTicks / 60);
var years = Math.floor(totalDays / 365);
var remainingDays = totalDays % 365;
var months = Math.floor(remainingDays / 30);
var days = remainingDays % 30;
var timeStr = '';
if (years > 0) timeStr += years + 'y ';
if (months > 0) timeStr += months + 'm ';
timeStr += days + 'd';
return timeStr;
};
self.startTimer = function (maxSurvivalTime) {
self.currentTime = maxSurvivalTime;
self.maxTime = maxSurvivalTime;
self.isActive = true;
self.visible = true;
timeText.setText(self.formatTime(self.currentTime));
timeText.tint = 0x00ff00;
statusText.setText('OPERATIONAL');
statusText.tint = 0x00ff00;
// Position timer in top right area
self.x = 1700;
self.y = 200;
};
self.update = function () {
if (self.isActive && self.currentTime > 0) {
// Calculate speed multiplier based on total survival time
// Higher survival time = faster countdown for better UX
var speedMultiplier = 1;
if (self.maxTime > 3600) {
// More than 1 hour (60 days)
speedMultiplier = 5;
} else if (self.maxTime > 1800) {
// More than 30 minutes (30 days)
speedMultiplier = 3;
} else if (self.maxTime > 600) {
// More than 10 minutes (10 days)
speedMultiplier = 2;
}
self.currentTime -= speedMultiplier;
if (self.currentTime < 0) self.currentTime = 0;
timeText.setText(self.formatTime(self.currentTime));
// Change color based on remaining time
var timeRatio = self.currentTime / self.maxTime;
if (timeRatio > 0.5) {
timeText.tint = 0x00ff00; // Green
statusText.tint = 0x00ff00;
} else if (timeRatio > 0.25) {
timeText.tint = 0xffff00; // Yellow
statusText.tint = 0xffff00;
statusText.setText('CRITICAL');
} else {
timeText.tint = 0xff0000; // Red
statusText.tint = 0xff0000;
statusText.setText('FAILING');
}
// Play tick sound every second (60 ticks)
if (self.currentTime % 60 === 0 && self.currentTime > 0) {
LK.getSound('tick').play();
}
// When time runs out
if (self.currentTime <= 0) {
self.isActive = false;
timeText.setText('0d');
timeText.tint = 0xff0000;
statusText.setText('DESTROYED');
statusText.tint = 0xff0000;
LK.getSound('explosion').play();
LK.effects.flashScreen(0xff0000, 1000);
// Hide timer after 3 seconds
LK.setTimeout(function () {
self.visible = false;
}, 3000);
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game state variables
var selectedMaterial = null;
var selectedDesign = null;
var selectedPropulsion = null;
var selectedSafety = null;
var selectedCrew = null;
var totalBoatsLaunched = 0;
var materialButtons = [];
var designButtons = [];
var propulsionButtons = [];
var safetyButtons = [];
var crewButtons = [];
var newsPanel = null;
var timerDisplay = null;
// Initialize storage for unlockables
var unlockedMaterials = storage.unlockedMaterials || ['wood', 'plastic'];
var unlockedDesigns = storage.unlockedDesigns || ['fishing'];
var unlockedPropulsion = storage.unlockedPropulsion || ['basic'];
var unlockedSafety = storage.unlockedSafety || ['basic'];
var unlockedCrew = storage.unlockedCrew || ['rookie'];
var bestSurvivalTime = storage.bestSurvivalTime || 0;
var totalCombos = storage.totalCombos || 0;
// Crew system data
var crewSystems = [{
type: 'rookie',
name: 'Rookie Crew',
skill: 1.0,
boost: 1.1
}, {
type: 'experienced',
name: 'Experienced Crew',
skill: 1.3,
boost: 1.4
}, {
type: 'elite',
name: 'Elite Crew',
skill: 1.6,
boost: 1.7
}, {
type: 'captain',
name: 'Legendary Captain',
skill: 2.0,
boost: 2.2
}, {
type: 'ai_crew',
name: 'AI Crew',
skill: 2.5,
boost: 2.7
}, {
type: 'super_human',
name: 'Super Human Crew',
skill: 3.0,
boost: 3.2
}];
// Material data
var materials = [{
type: 'wood',
name: 'Wood',
durability: 50,
cost: 25
}, {
type: 'steel',
name: 'Steel',
durability: 80,
cost: 45
}, {
type: 'plastic',
name: 'Plastic',
durability: 30,
cost: 15
}, {
type: 'aluminum',
name: 'Aluminum',
durability: 70,
cost: 35
}, {
type: 'titanium',
name: 'Titanium',
durability: 120,
cost: 85
}, {
type: 'carbon_fiber',
name: 'Carbon Fiber',
durability: 140,
cost: 100
}, {
type: 'graphene',
name: 'Graphene',
durability: 200,
cost: 150
}, {
type: 'alloy_composite',
name: 'Alloy Composite',
durability: 160,
cost: 120
}, {
type: 'bio_material',
name: 'Bio Material',
durability: 90,
cost: 60
}];
// Design data
var designs = [{
type: 'fishing',
name: 'Fishing Boat',
stability: 60,
speed: 40
}, {
type: 'yacht',
name: 'Luxury Yacht',
stability: 40,
speed: 80
}, {
type: 'cargo',
name: 'Cargo Ship',
stability: 80,
speed: 20
}, {
type: 'speedboat',
name: 'Speed Boat',
stability: 30,
speed: 90
}, {
type: 'submarine',
name: 'Submarine',
stability: 90,
speed: 50
}, {
type: 'battleship',
name: 'Battleship',
stability: 95,
speed: 35
}, {
type: 'catamaran',
name: 'Catamaran',
stability: 75,
speed: 70
}, {
type: 'icebreaker',
name: 'Icebreaker',
stability: 100,
speed: 25
}, {
type: 'hovercraft',
name: 'Hovercraft',
stability: 45,
speed: 85
}];
// Propulsion system data
var propulsionSystems = [{
type: 'basic',
name: 'Basic Motor',
reliability: 1.0,
boost: 1.1
}, {
type: 'advanced',
name: 'Advanced Engine',
reliability: 1.2,
boost: 1.3
}, {
type: 'hybrid',
name: 'Hybrid System',
reliability: 1.4,
boost: 1.5
}, {
type: 'nuclear',
name: 'Nuclear Reactor',
reliability: 1.8,
boost: 2.0
}, {
type: 'heavy_motor',
name: 'Heavy Motor',
reliability: 1.6,
boost: 1.7
}, {
type: 'plasma_drive',
name: 'Plasma Drive',
reliability: 2.2,
boost: 2.4
}, {
type: 'ion_drive',
name: 'Ion Drive',
reliability: 2.8,
boost: 3.0
}, {
type: 'antimatter_engine',
name: 'Antimatter Engine',
reliability: 3.5,
boost: 3.8
}];
// Safety system data
var safetySystems = [{
type: 'basic',
name: 'Life Jackets',
protection: 1.0,
boost: 1.1
}, {
type: 'standard',
name: 'Emergency Kit',
protection: 1.2,
boost: 1.3
}, {
type: 'advanced',
name: 'Auto-Pilot',
protection: 1.5,
boost: 1.6
}, {
type: 'military',
name: 'Military Grade',
protection: 2.0,
boost: 2.2
}, {
type: 'emergency_beacon',
name: 'Emergency Beacon',
protection: 1.3,
boost: 1.4
}, {
type: 'hull_reinforcement',
name: 'Hull Reinforcement',
protection: 1.8,
boost: 1.9
}, {
type: 'ai_navigation',
name: 'AI Navigation',
protection: 2.5,
boost: 2.7
}, {
type: 'shield_system',
name: 'Shield System',
protection: 3.0,
boost: 3.2
}];
// Disaster scenarios
var disasters = ['Structural failure due to poor material choice', 'Capsized in rough waters due to design instability', 'Engine explosion caused by manufacturing defects', 'Hull breach from collision with debris', 'Overloading beyond design capacity', 'Fire spread rapidly through cheap materials', 'Steering system malfunction in storm', 'Crew error compounded by design flaws'];
// Create UI
var scoreText = new Text2('Boats Launched: 0', {
size: 60,
fill: 0xffffff
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var instructionText = new Text2('Select material, design, propulsion, safety, and crew to launch!', {
size: 40,
fill: 0xffffff
});
instructionText.anchor.set(0.5, 0);
instructionText.y = 80;
LK.gui.top.addChild(instructionText);
// Create material selection area
var materialTitle = new Text2('SELECT MATERIAL:', {
size: 50,
fill: 0xffffff
});
materialTitle.anchor.set(0.5, 0.5);
materialTitle.x = 1024;
materialTitle.y = 400;
game.addChild(materialTitle);
// Create material buttons
var materialIndex = 0;
for (var i = 0; i < materials.length; i++) {
if (unlockedMaterials.indexOf(materials[i].type) !== -1) {
var materialButton = new MaterialButton(materials[i].type, materials[i].name, 200 + materialIndex * 150, 550);
game.addChild(materialButton);
materialButtons.push(materialButton);
materialIndex++;
}
}
// Create design selection area
var designTitle = new Text2('SELECT DESIGN:', {
size: 50,
fill: 0xffffff
});
designTitle.anchor.set(0.5, 0.5);
designTitle.x = 1024;
designTitle.y = 800;
game.addChild(designTitle);
// Create design buttons
var designIndex = 0;
for (var i = 0; i < designs.length; i++) {
if (unlockedDesigns.indexOf(designs[i].type) !== -1) {
var designButton = new DesignButton(designs[i].type, designs[i].name, 200 + designIndex * 150, 950);
game.addChild(designButton);
designButtons.push(designButton);
designIndex++;
}
}
// Create propulsion selection area
var propulsionTitle = new Text2('SELECT PROPULSION:', {
size: 50,
fill: 0xffffff
});
propulsionTitle.anchor.set(0.5, 0.5);
propulsionTitle.x = 1024;
propulsionTitle.y = 1200;
game.addChild(propulsionTitle);
// Create propulsion buttons
var propulsionIndex = 0;
for (var i = 0; i < propulsionSystems.length; i++) {
if (unlockedPropulsion.indexOf(propulsionSystems[i].type) !== -1) {
var propulsionButton = new PropulsionButton(propulsionSystems[i].type, propulsionSystems[i].name, 200 + propulsionIndex * 150, 1350);
game.addChild(propulsionButton);
propulsionButtons.push(propulsionButton);
propulsionIndex++;
}
}
// Create safety selection area
var safetyTitle = new Text2('SELECT SAFETY SYSTEM:', {
size: 50,
fill: 0xffffff
});
safetyTitle.anchor.set(0.5, 0.5);
safetyTitle.x = 1024;
safetyTitle.y = 1600;
game.addChild(safetyTitle);
// Create safety buttons
var safetyIndex = 0;
for (var i = 0; i < safetySystems.length; i++) {
if (unlockedSafety.indexOf(safetySystems[i].type) !== -1) {
var safetyButton = new SafetyButton(safetySystems[i].type, safetySystems[i].name, 200 + safetyIndex * 150, 1750);
game.addChild(safetyButton);
safetyButtons.push(safetyButton);
safetyIndex++;
}
}
// Create crew selection area
var crewTitle = new Text2('SELECT CREW:', {
size: 50,
fill: 0xffffff
});
crewTitle.anchor.set(0.5, 0.5);
crewTitle.x = 1024;
crewTitle.y = 2000;
game.addChild(crewTitle);
// Create crew buttons
var crewIndex = 0;
for (var i = 0; i < crewSystems.length; i++) {
if (unlockedCrew.indexOf(crewSystems[i].type) !== -1) {
var crewButton = new CrewButton(crewSystems[i].type, crewSystems[i].name, 200 + crewIndex * 150, 2150);
game.addChild(crewButton);
crewButtons.push(crewButton);
crewIndex++;
}
}
// Create launch button
var launchButton = game.addChild(LK.getAsset('launchButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2400
}));
var launchText = new Text2('LAUNCH VESSEL', {
size: 50,
fill: 0xffffff
});
launchText.anchor.set(0.5, 0.5);
launchText.x = 1024;
launchText.y = 2400;
game.addChild(launchText);
// Create news panel with article system
newsPanel = new NewsPanel();
// Create timer display
timerDisplay = new TimerDisplay();
game.addChild(timerDisplay);
// Create sandbox button
var sandboxButton = game.addChild(LK.getAsset('materialButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1700,
y: 2600,
scaleX: 0.8,
scaleY: 0.8
}));
sandboxButton.tint = 0xffd700; // Gold color
var sandboxText = new Text2('SANDBOX', {
size: 32,
fill: 0x000000
});
sandboxText.anchor.set(0.5, 0.5);
sandboxText.x = 1700;
sandboxText.y = 2600;
game.addChild(sandboxText);
function selectMaterial(materialType) {
selectedMaterial = materialType;
// Update button visuals
for (var i = 0; i < materialButtons.length; i++) {
materialButtons[i].selected = materialButtons[i].materialType === materialType;
materialButtons[i].updateVisual();
}
}
function selectDesign(designType) {
selectedDesign = designType;
// Update button visuals
for (var i = 0; i < designButtons.length; i++) {
designButtons[i].selected = designButtons[i].designType === designType;
designButtons[i].updateVisual();
}
}
function selectPropulsion(propulsionType) {
selectedPropulsion = propulsionType;
// Update button visuals
for (var i = 0; i < propulsionButtons.length; i++) {
propulsionButtons[i].selected = propulsionButtons[i].propulsionType === propulsionType;
propulsionButtons[i].updateVisual();
}
}
function selectSafety(safetyType) {
selectedSafety = safetyType;
// Update button visuals
for (var i = 0; i < safetyButtons.length; i++) {
safetyButtons[i].selected = safetyButtons[i].safetyType === safetyType;
safetyButtons[i].updateVisual();
}
}
function getMaterialData(materialType) {
for (var i = 0; i < materials.length; i++) {
if (materials[i].type === materialType) {
return materials[i];
}
}
return null;
}
function getDesignData(designType) {
for (var i = 0; i < designs.length; i++) {
if (designs[i].type === designType) {
return designs[i];
}
}
return null;
}
function getPropulsionData(propulsionType) {
for (var i = 0; i < propulsionSystems.length; i++) {
if (propulsionSystems[i].type === propulsionType) {
return propulsionSystems[i];
}
}
return null;
}
function getSafetyData(safetyType) {
for (var i = 0; i < safetySystems.length; i++) {
if (safetySystems[i].type === safetyType) {
return safetySystems[i];
}
}
return null;
}
function selectCrew(crewType) {
selectedCrew = crewType;
// Update button visuals
for (var i = 0; i < crewButtons.length; i++) {
crewButtons[i].selected = crewButtons[i].crewType === crewType;
crewButtons[i].updateVisual();
}
}
function getCrewData(crewType) {
for (var i = 0; i < crewSystems.length; i++) {
if (crewSystems[i].type === crewType) {
return crewSystems[i];
}
}
return null;
}
function unlockEverything() {
// Unlock all materials
unlockedMaterials = [];
for (var i = 0; i < materials.length; i++) {
unlockedMaterials.push(materials[i].type);
}
// Unlock all designs
unlockedDesigns = [];
for (var i = 0; i < designs.length; i++) {
unlockedDesigns.push(designs[i].type);
}
// Unlock all propulsion
unlockedPropulsion = [];
for (var i = 0; i < propulsionSystems.length; i++) {
unlockedPropulsion.push(propulsionSystems[i].type);
}
// Unlock all safety
unlockedSafety = [];
for (var i = 0; i < safetySystems.length; i++) {
unlockedSafety.push(safetySystems[i].type);
}
// Unlock all crew
unlockedCrew = [];
for (var i = 0; i < crewSystems.length; i++) {
unlockedCrew.push(crewSystems[i].type);
}
// Save to storage
storage.unlockedMaterials = unlockedMaterials;
storage.unlockedDesigns = unlockedDesigns;
storage.unlockedPropulsion = unlockedPropulsion;
storage.unlockedSafety = unlockedSafety;
storage.unlockedCrew = unlockedCrew;
}
function checkUnlocks(survivalTime) {
var newUnlocks = [];
// Track best survival time
if (survivalTime > bestSurvivalTime) {
bestSurvivalTime = survivalTime;
storage.bestSurvivalTime = bestSurvivalTime;
}
// Track total combos tried
totalCombos++;
storage.totalCombos = totalCombos;
// Unlock everything based on survival time only (in ticks, 60 ticks = 1 day)
var daysSurvived = Math.floor(survivalTime / 60);
var bestDays = Math.floor(bestSurvivalTime / 60);
// Unlock materials based on survival time
if (daysSurvived >= 5 && unlockedMaterials.indexOf('steel') === -1) {
unlockedMaterials.push('steel');
newUnlocks.push('Steel material');
}
if (daysSurvived >= 15 && unlockedMaterials.indexOf('aluminum') === -1) {
unlockedMaterials.push('aluminum');
newUnlocks.push('Aluminum material');
}
if (bestDays >= 25 && unlockedMaterials.indexOf('titanium') === -1) {
unlockedMaterials.push('titanium');
newUnlocks.push('Titanium material');
}
if (bestDays >= 40 && unlockedMaterials.indexOf('carbon_fiber') === -1) {
unlockedMaterials.push('carbon_fiber');
newUnlocks.push('Carbon Fiber material');
}
if (bestDays >= 60 && unlockedMaterials.indexOf('alloy_composite') === -1) {
unlockedMaterials.push('alloy_composite');
newUnlocks.push('Alloy Composite material');
}
if (bestDays >= 80 && unlockedMaterials.indexOf('bio_material') === -1) {
unlockedMaterials.push('bio_material');
newUnlocks.push('Bio Material material');
}
if (bestDays >= 100 && unlockedMaterials.indexOf('graphene') === -1) {
unlockedMaterials.push('graphene');
newUnlocks.push('Graphene material');
}
// Unlock designs based on survival time
if (bestDays >= 8 && unlockedDesigns.indexOf('yacht') === -1) {
unlockedDesigns.push('yacht');
newUnlocks.push('Luxury Yacht design');
}
if (bestDays >= 20 && unlockedDesigns.indexOf('cargo') === -1) {
unlockedDesigns.push('cargo');
newUnlocks.push('Cargo Ship design');
}
if (bestDays >= 35 && unlockedDesigns.indexOf('speedboat') === -1) {
unlockedDesigns.push('speedboat');
newUnlocks.push('Speed Boat design');
}
if (bestDays >= 50 && unlockedDesigns.indexOf('submarine') === -1) {
unlockedDesigns.push('submarine');
newUnlocks.push('Submarine design');
}
if (bestDays >= 70 && unlockedDesigns.indexOf('catamaran') === -1) {
unlockedDesigns.push('catamaran');
newUnlocks.push('Catamaran design');
}
if (bestDays >= 90 && unlockedDesigns.indexOf('battleship') === -1) {
unlockedDesigns.push('battleship');
newUnlocks.push('Battleship design');
}
if (bestDays >= 110 && unlockedDesigns.indexOf('hovercraft') === -1) {
unlockedDesigns.push('hovercraft');
newUnlocks.push('Hovercraft design');
}
if (bestDays >= 130 && unlockedDesigns.indexOf('icebreaker') === -1) {
unlockedDesigns.push('icebreaker');
newUnlocks.push('Icebreaker design');
}
// Unlock propulsion based on survival time
if (bestDays >= 10 && unlockedPropulsion.indexOf('advanced') === -1) {
unlockedPropulsion.push('advanced');
newUnlocks.push('Advanced Engine propulsion');
}
if (bestDays >= 30 && unlockedPropulsion.indexOf('hybrid') === -1) {
unlockedPropulsion.push('hybrid');
newUnlocks.push('Hybrid System propulsion');
}
if (bestDays >= 50 && unlockedPropulsion.indexOf('heavy_motor') === -1) {
unlockedPropulsion.push('heavy_motor');
newUnlocks.push('Heavy Motor propulsion');
}
if (bestDays >= 70 && unlockedPropulsion.indexOf('nuclear') === -1) {
unlockedPropulsion.push('nuclear');
newUnlocks.push('Nuclear Reactor propulsion');
}
if (bestDays >= 90 && unlockedPropulsion.indexOf('plasma_drive') === -1) {
unlockedPropulsion.push('plasma_drive');
newUnlocks.push('Plasma Drive propulsion');
}
if (bestDays >= 120 && unlockedPropulsion.indexOf('ion_drive') === -1) {
unlockedPropulsion.push('ion_drive');
newUnlocks.push('Ion Drive propulsion');
}
if (bestDays >= 150 && unlockedPropulsion.indexOf('antimatter_engine') === -1) {
unlockedPropulsion.push('antimatter_engine');
newUnlocks.push('Antimatter Engine propulsion');
}
// Unlock safety systems based on survival time
if (bestDays >= 12 && unlockedSafety.indexOf('standard') === -1) {
unlockedSafety.push('standard');
newUnlocks.push('Emergency Kit safety');
}
if (bestDays >= 25 && unlockedSafety.indexOf('emergency_beacon') === -1) {
unlockedSafety.push('emergency_beacon');
newUnlocks.push('Emergency Beacon safety');
}
if (bestDays >= 40 && unlockedSafety.indexOf('advanced') === -1) {
unlockedSafety.push('advanced');
newUnlocks.push('Auto-Pilot safety');
}
if (bestDays >= 65 && unlockedSafety.indexOf('hull_reinforcement') === -1) {
unlockedSafety.push('hull_reinforcement');
newUnlocks.push('Hull Reinforcement safety');
}
if (bestDays >= 85 && unlockedSafety.indexOf('military') === -1) {
unlockedSafety.push('military');
newUnlocks.push('Military Grade safety');
}
if (bestDays >= 110 && unlockedSafety.indexOf('ai_navigation') === -1) {
unlockedSafety.push('ai_navigation');
newUnlocks.push('AI Navigation safety');
}
if (bestDays >= 140 && unlockedSafety.indexOf('shield_system') === -1) {
unlockedSafety.push('shield_system');
newUnlocks.push('Shield System safety');
}
// Unlock crew based on survival time
if (bestDays >= 18 && unlockedCrew.indexOf('experienced') === -1) {
unlockedCrew.push('experienced');
newUnlocks.push('Experienced Crew');
}
if (bestDays >= 45 && unlockedCrew.indexOf('elite') === -1) {
unlockedCrew.push('elite');
newUnlocks.push('Elite Crew');
}
if (bestDays >= 75 && unlockedCrew.indexOf('captain') === -1) {
unlockedCrew.push('captain');
newUnlocks.push('Legendary Captain');
}
if (bestDays >= 105 && unlockedCrew.indexOf('ai_crew') === -1) {
unlockedCrew.push('ai_crew');
newUnlocks.push('AI Crew');
}
if (bestDays >= 135 && unlockedCrew.indexOf('super_human') === -1) {
unlockedCrew.push('super_human');
newUnlocks.push('Super Human Crew');
}
// Save unlocks to storage
storage.unlockedMaterials = unlockedMaterials;
storage.unlockedDesigns = unlockedDesigns;
storage.unlockedPropulsion = unlockedPropulsion;
storage.unlockedSafety = unlockedSafety;
storage.unlockedCrew = unlockedCrew;
// Show unlock notifications
if (newUnlocks.length > 0) {
var unlockMessage = 'NEW UNLOCKS:\n' + newUnlocks.join('\n');
LK.setTimeout(function () {
if (newsPanel && newsPanel.currentArticle) {
newsPanel.currentArticle.updateContent('UNLOCKS ACHIEVED!', unlockMessage);
newsPanel.currentArticle.show();
}
}, 4000);
}
return newUnlocks.length > 0;
}
function calculateSurvivalTime(material, design, propulsion, safety, crew) {
var materialData = getMaterialData(material);
var designData = getDesignData(design);
if (!materialData || !designData) return 60; // Default 1 second
// Base survival time with some randomness
var baseTime = 180 + Math.random() * 600; // 3-13 seconds
// Material affects durability
baseTime *= materialData.durability / 50;
// Design affects stability
baseTime *= designData.stability / 50;
// Apply propulsion system boost
if (propulsion) {
var propulsionData = getPropulsionData(propulsion);
if (propulsionData) {
baseTime *= propulsionData.boost;
}
}
// Apply safety system boost
if (safety) {
var safetyData = getSafetyData(safety);
if (safetyData) {
baseTime *= safetyData.boost;
}
}
// Apply crew boost
if (crew) {
var crewData = getCrewData(crew);
if (crewData) {
baseTime *= crewData.boost;
}
}
// Add some chaos
baseTime *= 0.5 + Math.random();
return Math.floor(baseTime);
}
function generateDisasterReport(material, design, survivalTime) {
var materialData = getMaterialData(material);
var designData = getDesignData(design);
var randomDisaster = disasters[Math.floor(Math.random() * disasters.length)];
// Format survival time
var totalDays = Math.floor(survivalTime / 60);
var years = Math.floor(totalDays / 365);
var remainingDays = totalDays % 365;
var months = Math.floor(remainingDays / 30);
var days = remainingDays % 30;
var timeStr = '';
if (years > 0) timeStr += years + ' years, ';
if (months > 0) timeStr += months + ' months, ';
timeStr += days + ' days';
// Create more specific disaster based on choices
var specificCause = '';
if (materialData.durability < 40) {
specificCause = 'The cheap ' + materialData.name.toLowerCase() + ' construction proved inadequate for maritime conditions. ';
} else if (designData.stability < 50) {
specificCause = 'The ' + designData.name.toLowerCase() + ' design showed inherent stability issues. ';
}
return specificCause + randomDisaster + '. The vessel lasted ' + timeStr + ' before meeting its inevitable fate.';
}
function launchVessel() {
if (!selectedMaterial || !selectedDesign || !selectedPropulsion || !selectedSafety || !selectedCrew) {
return; // Can't launch without all selections
}
totalBoatsLaunched++;
scoreText.setText('Boats Launched: ' + totalBoatsLaunched);
// Calculate how long this boat will survive
var survivalTime = calculateSurvivalTime(selectedMaterial, selectedDesign, selectedPropulsion, selectedSafety, selectedCrew);
// Generate disaster report
var disaster = generateDisasterReport(selectedMaterial, selectedDesign, survivalTime);
// Show launch effect
LK.getSound('launch').play();
LK.effects.flashScreen(0x0000ff, 500);
// Start the timelapse timer
timerDisplay.startTimer(survivalTime);
// Store this launch for potential leaderboard
var launchData = {
material: selectedMaterial,
design: selectedDesign,
survivalTime: survivalTime,
disaster: disaster,
timestamp: Date.now()
};
var savedLaunches = [];
try {
savedLaunches = storage.get('launches') || [];
} catch (e) {
console.log('Storage not available, using empty array');
savedLaunches = [];
}
savedLaunches.push(launchData);
if (savedLaunches.length > 50) {
savedLaunches = savedLaunches.slice(-50); // Keep only last 50
}
try {
storage.set('launches', savedLaunches);
} catch (e) {
console.log('Could not save to storage');
}
// Get material and design data before resetting selections
var materialData = getMaterialData(selectedMaterial);
var designData = getDesignData(selectedDesign);
// Show news report after a delay
LK.setTimeout(function () {
newsPanel.showNews(materialData.name, designData.name, survivalTime, disaster);
}, 2000);
// Reset selections
selectedMaterial = null;
selectedDesign = null;
selectedPropulsion = null;
selectedSafety = null;
selectedCrew = null;
for (var i = 0; i < materialButtons.length; i++) {
materialButtons[i].selected = false;
materialButtons[i].updateVisual();
}
for (var i = 0; i < designButtons.length; i++) {
designButtons[i].selected = false;
designButtons[i].updateVisual();
}
for (var i = 0; i < propulsionButtons.length; i++) {
propulsionButtons[i].selected = false;
propulsionButtons[i].updateVisual();
}
for (var i = 0; i < safetyButtons.length; i++) {
safetyButtons[i].selected = false;
safetyButtons[i].updateVisual();
}
for (var i = 0; i < crewButtons.length; i++) {
crewButtons[i].selected = false;
crewButtons[i].updateVisual();
}
// Check for unlocks
var hasNewUnlocks = checkUnlocks(survivalTime);
// Refresh UI if new unlocks were achieved
if (hasNewUnlocks) {
// Remove old buttons
for (var i = 0; i < materialButtons.length; i++) {
materialButtons[i].destroy();
}
for (var i = 0; i < designButtons.length; i++) {
designButtons[i].destroy();
}
for (var i = 0; i < propulsionButtons.length; i++) {
propulsionButtons[i].destroy();
}
for (var i = 0; i < safetyButtons.length; i++) {
safetyButtons[i].destroy();
}
for (var i = 0; i < crewButtons.length; i++) {
crewButtons[i].destroy();
}
// Clear arrays
materialButtons = [];
designButtons = [];
propulsionButtons = [];
safetyButtons = [];
crewButtons = [];
// Recreate buttons with new unlocks
var materialIndex = 0;
for (var i = 0; i < materials.length; i++) {
if (unlockedMaterials.indexOf(materials[i].type) !== -1) {
var materialButton = new MaterialButton(materials[i].type, materials[i].name, 200 + materialIndex * 150, 550);
game.addChild(materialButton);
materialButtons.push(materialButton);
materialIndex++;
}
}
var designIndex = 0;
for (var i = 0; i < designs.length; i++) {
if (unlockedDesigns.indexOf(designs[i].type) !== -1) {
var designButton = new DesignButton(designs[i].type, designs[i].name, 200 + designIndex * 150, 950);
game.addChild(designButton);
designButtons.push(designButton);
designIndex++;
}
}
var propulsionIndex = 0;
for (var i = 0; i < propulsionSystems.length; i++) {
if (unlockedPropulsion.indexOf(propulsionSystems[i].type) !== -1) {
var propulsionButton = new PropulsionButton(propulsionSystems[i].type, propulsionSystems[i].name, 200 + propulsionIndex * 150, 1350);
game.addChild(propulsionButton);
propulsionButtons.push(propulsionButton);
propulsionIndex++;
}
}
var safetyIndex = 0;
for (var i = 0; i < safetySystems.length; i++) {
if (unlockedSafety.indexOf(safetySystems[i].type) !== -1) {
var safetyButton = new SafetyButton(safetySystems[i].type, safetySystems[i].name, 200 + safetyIndex * 150, 1750);
game.addChild(safetyButton);
safetyButtons.push(safetyButton);
safetyIndex++;
}
}
var crewIndex = 0;
for (var i = 0; i < crewSystems.length; i++) {
if (unlockedCrew.indexOf(crewSystems[i].type) !== -1) {
var crewButton = new CrewButton(crewSystems[i].type, crewSystems[i].name, 200 + crewIndex * 150, 2150);
game.addChild(crewButton);
crewButtons.push(crewButton);
crewIndex++;
}
}
}
// Check for achievement
if (totalBoatsLaunched >= 10) {
LK.showYouWin();
}
}
// Event handlers
launchButton.down = function (x, y, obj) {
launchVessel();
};
sandboxButton.down = function (x, y, obj) {
unlockEverything();
// Refresh all buttons
for (var i = 0; i < materialButtons.length; i++) {
materialButtons[i].destroy();
}
for (var i = 0; i < designButtons.length; i++) {
designButtons[i].destroy();
}
for (var i = 0; i < propulsionButtons.length; i++) {
propulsionButtons[i].destroy();
}
for (var i = 0; i < safetyButtons.length; i++) {
safetyButtons[i].destroy();
}
for (var i = 0; i < crewButtons.length; i++) {
crewButtons[i].destroy();
}
// Clear arrays
materialButtons = [];
designButtons = [];
propulsionButtons = [];
safetyButtons = [];
crewButtons = [];
// Recreate all buttons
var materialIndex = 0;
for (var i = 0; i < materials.length; i++) {
if (unlockedMaterials.indexOf(materials[i].type) !== -1) {
var materialButton = new MaterialButton(materials[i].type, materials[i].name, 200 + materialIndex * 150, 550);
game.addChild(materialButton);
materialButtons.push(materialButton);
materialIndex++;
}
}
var designIndex = 0;
for (var i = 0; i < designs.length; i++) {
if (unlockedDesigns.indexOf(designs[i].type) !== -1) {
var designButton = new DesignButton(designs[i].type, designs[i].name, 200 + designIndex * 150, 950);
game.addChild(designButton);
designButtons.push(designButton);
designIndex++;
}
}
var propulsionIndex = 0;
for (var i = 0; i < propulsionSystems.length; i++) {
if (unlockedPropulsion.indexOf(propulsionSystems[i].type) !== -1) {
var propulsionButton = new PropulsionButton(propulsionSystems[i].type, propulsionSystems[i].name, 200 + propulsionIndex * 150, 1350);
game.addChild(propulsionButton);
propulsionButtons.push(propulsionButton);
propulsionIndex++;
}
}
var safetyIndex = 0;
for (var i = 0; i < safetySystems.length; i++) {
if (unlockedSafety.indexOf(safetySystems[i].type) !== -1) {
var safetyButton = new SafetyButton(safetySystems[i].type, safetySystems[i].name, 200 + safetyIndex * 150, 1750);
game.addChild(safetyButton);
safetyButtons.push(safetyButton);
safetyIndex++;
}
}
var crewIndex = 0;
for (var i = 0; i < crewSystems.length; i++) {
if (unlockedCrew.indexOf(crewSystems[i].type) !== -1) {
var crewButton = new CrewButton(crewSystems[i].type, crewSystems[i].name, 200 + crewIndex * 150, 2150);
game.addChild(crewButton);
crewButtons.push(crewButton);
crewIndex++;
}
}
};
// Create article at the end to ensure it appears in front of all buttons
var article = new Article('', '');
article.x = 1024;
article.y = 1366;
game.addChild(article);
newsPanel.currentArticle = article;
game.update = function () {
// Background stays consistently black - no flashing
// Update timer display
if (timerDisplay) {
timerDisplay.update();
}
};