/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Button = Container.expand(function () { var self = Container.call(this); var bg = self.attachAsset('button', { anchorX: 0.5, anchorY: 0.5 }); var label = new Text2('Button', { size: 40, fill: 0xFFFFFF }); label.anchor.set(0.5, 0.5); self.addChild(label); self.setLabel = function (text) { label.setText(text); }; self.down = function () { tween(bg, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100 }); LK.getSound('select').play(); }; self.up = function () { tween(bg, { scaleX: 1, scaleY: 1 }, { duration: 100 }); if (self.onClick) { self.onClick(); } }; return self; }); var DeveloperCard = Container.expand(function () { var self = Container.call(this); var bg = self.attachAsset('card', { anchorX: 0.5, anchorY: 0.5 }); var icon = self.attachAsset('developerIcon', { anchorX: 0.5, anchorY: 0.5, y: -100 }); var nameText = new Text2('Developer', { size: 30, fill: 0xFFFFFF }); nameText.anchor.set(0.5, 0.5); nameText.y = -20; self.addChild(nameText); var specialtyText = new Text2('Graphics', { size: 25, fill: 0xFFC107 }); specialtyText.anchor.set(0.5, 0.5); specialtyText.y = 20; self.addChild(specialtyText); var costText = new Text2('Cost: $100', { size: 25, fill: 0x4CAF50 }); costText.anchor.set(0.5, 0.5); costText.y = 60; self.addChild(costText); var skillText = new Text2('Skill: 5', { size: 25, fill: 0x2196F3 }); skillText.anchor.set(0.5, 0.5); skillText.y = 100; self.addChild(skillText); self.developerData = null; self.setDeveloper = function (data) { self.developerData = data; nameText.setText(data.name); specialtyText.setText(data.specialty); costText.setText('Cost: $' + data.cost); skillText.setText('Skill: ' + data.skill); var specialtyColors = { 'Graphics': 0xff5722, 'Sound': 0x9c27b0, 'Gameplay': 0x2196f3 }; icon.tint = specialtyColors[data.specialty] || 0xffc107; }; self.down = function () { if (self.onClick) { self.onClick(self.developerData); } }; return self; }); var FeatureCard = Container.expand(function () { var self = Container.call(this); var bg = self.attachAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); var icon = self.attachAsset('featureIcon', { anchorX: 0.5, anchorY: 0.5, y: -80 }); var nameText = new Text2('Feature', { size: 25, fill: 0xFFFFFF }); nameText.anchor.set(0.5, 0.5); nameText.y = -20; self.addChild(nameText); var typeText = new Text2('Type', { size: 20, fill: 0x2196F3 }); typeText.anchor.set(0.5, 0.5); typeText.y = 10; self.addChild(typeText); var pointsText = new Text2('Points: 0', { size: 20, fill: 0x4CAF50 }); pointsText.anchor.set(0.5, 0.5); pointsText.y = 40; self.addChild(pointsText); self.featureData = null; self.selected = false; self.setFeature = function (data) { self.featureData = data; nameText.setText(data.name); typeText.setText(data.type); pointsText.setText('Points: ' + data.basePoints + ' | Cost: $' + data.cost); var typeColors = { 'Graphics': 0xff5722, 'Sound': 0x9c27b0, 'Gameplay': 0x2196f3 }; icon.tint = typeColors[data.type] || 0xffc107; }; self.setSelected = function (selected) { self.selected = selected; bg.tint = selected ? 0xe94560 : 0xffffff; }; self.down = function () { if (self.onClick) { self.onClick(self); } }; return self; }); var GameHistoryCard = Container.expand(function () { var self = Container.call(this); var bg = self.attachAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 0.6 }); var nameText = new Text2('Game Name', { size: 30, fill: 0xFFFFFF }); nameText.anchor.set(0.5, 0.5); nameText.y = -30; self.addChild(nameText); var salesText = new Text2('Sales: 0', { size: 25, fill: 0x4CAF50 }); salesText.anchor.set(0.5, 0.5); salesText.y = 10; self.addChild(salesText); self.gameData = null; self.setGameData = function (data) { self.gameData = data; nameText.setText(data.name); var salesInfo = data.currentDailySales > 0 ? 'Sales: ' + data.totalSales + ' (Active)' : 'Sales: ' + data.totalSales + ' (Ended)'; salesText.setText(salesInfo); bg.tint = data.currentDailySales > 0 ? 0x0f3460 : 0x16213e; }; self.down = function () { if (self.onClick) { self.onClick(self.gameData); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a1a2e }); /**** * Game Code ****/ // Game state function _typeof2(o) { "@babel/helpers - typeof"; return _typeof2 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof2(o); } function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } var gameState = { money: 50000, developers: [], currentProject: null, completedGames: 0, marketTrends: [], currentDay: 1, releasedGames: [], maxHireableDevelopers: 1, studioLevel: 1, studioUpgradeCost: 5000, fans: 0, // Toplam fan sayısı mainCharacter: { name: "You", level: 1, upgradeCost: 2000, skill: 2, specialty: "All", featurePoints: { Graphics: 1, Sound: 1, Gameplay: 1 } }, gameHistory: [], researchedFeatures: { Graphics: [], Sound: [], Gameplay: [], GameGenres: [] }, currentResearch: null, // --- Feature selection limit per category --- featureSelectionLimit: { Graphics: 1, Sound: 1, Gameplay: 1 } }; // Current game name being created var currentGameName = ''; // Game name display at top var gameNameDisplay = new Text2('', { size: 45, fill: 0xFFFFFF }); gameNameDisplay.anchor.set(0.5, 0); gameNameDisplay.y = 10; LK.gui.top.addChild(gameNameDisplay); // Available developers pool var developerPool = [{ name: 'Alex', specialty: 'Graphics', skill: 3, cost: 4000 }, { name: 'Sam', specialty: 'Sound', skill: 4, cost: 4000 }, { name: 'Jordan', specialty: 'Gameplay', skill: 5, cost: 4000 }, { name: 'Morgan', specialty: 'Graphics', skill: 6, cost: 8000 }, { name: 'Casey', specialty: 'Sound', skill: 7, cost: 8000 }, { name: 'Drew', specialty: 'Gameplay', skill: 8, cost: 8000 }, { name: 'Taylor', specialty: 'Graphics', skill: 9, cost: 12000 }, { name: 'Jamie', specialty: 'Sound', skill: 10, cost: 12000 }, { name: 'Robin', specialty: 'Gameplay', skill: 11, cost: 12000 }]; // Available features - expanded with research requirements var featurePool = [{ name: 'Pixel Art', type: 'Graphics', basePoints: 3, cost: 2000, requiresResearch: false }, { name: '3D Models', type: 'Graphics', basePoints: 5, cost: 2000, requiresResearch: false }, { name: 'Particle Effects', type: 'Graphics', basePoints: 4, cost: 2000, requiresResearch: false }, { name: 'Soundtrack', type: 'Sound', basePoints: 3, cost: 2000, requiresResearch: false }, { name: 'Voice Acting', type: 'Sound', basePoints: 6, cost: 2000, requiresResearch: false }, { name: 'Sound Effects', type: 'Sound', basePoints: 4, cost: 2000, requiresResearch: false }, { name: 'RPG Elements', type: 'Gameplay', basePoints: 5, cost: 2000, requiresResearch: false }, { name: 'Multiplayer', type: 'Gameplay', basePoints: 7, cost: 2000, requiresResearch: false }, { name: 'Puzzles', type: 'Gameplay', basePoints: 4, cost: 2000, requiresResearch: false }, { name: 'Open World', type: 'Gameplay', basePoints: 8, cost: 2000, requiresResearch: false }, { name: 'Shaders', type: 'Graphics', basePoints: 6, cost: 4000, requiresResearch: true }, { name: 'Ray Tracing', type: 'Graphics', basePoints: 10, cost: 6000, requiresResearch: true }, { name: 'Motion Capture', type: 'Graphics', basePoints: 8, cost: 4000, requiresResearch: true }, { name: 'Procedural Generation', type: 'Graphics', basePoints: 7, cost: 4000, requiresResearch: true }, { name: 'Dynamic Lighting', type: 'Graphics', basePoints: 6, cost: 4000, requiresResearch: true }, { name: 'Orchestral Score', type: 'Sound', basePoints: 8, cost: 4000, requiresResearch: true }, { name: '3D Audio', type: 'Sound', basePoints: 7, cost: 4000, requiresResearch: true }, { name: 'Dynamic Music', type: 'Sound', basePoints: 6, cost: 4000, requiresResearch: true }, { name: 'Environmental Audio', type: 'Sound', basePoints: 5, cost: 4000, requiresResearch: true }, { name: 'Foley Effects', type: 'Sound', basePoints: 6, cost: 4000, requiresResearch: true }, { name: 'Physics Engine', type: 'Gameplay', basePoints: 9, cost: 6000, requiresResearch: true }, { name: 'AI Systems', type: 'Gameplay', basePoints: 10, cost: 6000, requiresResearch: true }, { name: 'Skill Trees', type: 'Gameplay', basePoints: 6, cost: 4000, requiresResearch: true }, { name: 'Crafting System', type: 'Gameplay', basePoints: 7, cost: 4000, requiresResearch: true }, { name: 'Dialogue System', type: 'Gameplay', basePoints: 5, cost: 4000, requiresResearch: true }]; // Game genres that can be researched var gameGenres = [{ name: 'Action', baseMultiplier: 1.2, trendChance: 0.3, researchCost: 4000, requiresResearch: false }, { name: 'Adventure', baseMultiplier: 1.1, trendChance: 0.25, researchCost: 4000, requiresResearch: false }, { name: 'Puzzle', baseMultiplier: 1.0, trendChance: 0.2, researchCost: 4000, requiresResearch: false }, { name: 'Racing', baseMultiplier: 1.3, trendChance: 0.35, researchCost: 8000, requiresResearch: true }, { name: 'Strategy', baseMultiplier: 1.4, trendChance: 0.3, researchCost: 8000, requiresResearch: true }, { name: 'Simulation', baseMultiplier: 1.2, trendChance: 0.25, researchCost: 8000, requiresResearch: true }, { name: 'RPG', baseMultiplier: 1.5, trendChance: 0.4, researchCost: 12000, requiresResearch: true }, { name: 'FPS', baseMultiplier: 1.4, trendChance: 0.35, researchCost: 12000, requiresResearch: true }, { name: 'Horror', baseMultiplier: 1.3, trendChance: 0.25, researchCost: 12000, requiresResearch: true }, { name: 'Sports', baseMultiplier: 1.2, trendChance: 0.3, researchCost: 12000, requiresResearch: true }]; // UI Elements var moneyText = new Text2('Money: $10000', { size: 50, fill: 0x4CAF50 }); moneyText.anchor.set(1, 0); moneyText.x = 0; moneyText.y = 0; LK.gui.topRight.addChild(moneyText); var developersText = new Text2('Developers: 0', { size: 40, fill: 0xFFFFFF }); developersText.anchor.set(1, 0); developersText.x = 0; developersText.y = moneyText.y + moneyText.height + 8; LK.gui.topRight.addChild(developersText); var gamesText = new Text2('Games Released: 0', { size: 40, fill: 0xFFC107 }); gamesText.anchor.set(1, 0); gamesText.x = 0; gamesText.y = developersText.y + developersText.height + 8; LK.gui.topRight.addChild(gamesText); // Fan count and bonus UI var fanText = new Text2('Fan: 0', { size: 40, fill: 0x2196F3 }); fanText.anchor.set(1, 0); fanText.x = 0; fanText.y = gamesText.y + gamesText.height + 8; LK.gui.topRight.addChild(fanText); var fanBonusText = new Text2('Sales Bonus: %0', { size: 32, fill: 0x4CAF50 }); fanBonusText.anchor.set(1, 0); fanBonusText.x = 0; fanBonusText.y = fanText.y + fanText.height + 8; LK.gui.topRight.addChild(fanBonusText); var dayText = new Text2('Day: 1', { size: 40, fill: 0x2196F3 }); dayText.anchor.set(1, 0); dayText.x = 0; dayText.y = fanBonusText.y + fanBonusText.height + 8; LK.gui.topRight.addChild(dayText); // --- Sales & Revenue Log UI --- var salesLogContainer = new Container(); salesLogContainer.x = 2048 - 40; // right align salesLogContainer.y = 220; // just below dayText LK.gui.topRight.addChild(salesLogContainer); var salesLogEntries = []; // keep references to Text2 objects for updating/removal function updateSalesLog() { // Remove old entries for (var i = 0; i < salesLogEntries.length; i++) { salesLogEntries[i].destroy(); } salesLogEntries = []; // Show up to 5 most recent games (active and ended) var allGames = gameState.releasedGames.concat(gameState.gameHistory); var recentGames = allGames.slice(-5).reverse(); var y = 0; for (var i = 0; i < recentGames.length; i++) { var g = recentGames[i]; var isActive = g.currentDailySales > 0; var pricePerCopy = typeof g.price === "number" ? g.price : 1; var revenue = Math.floor((g.currentDailySales || 0) * pricePerCopy); var txt = new Text2(g.name + ': +' + (g.currentDailySales || 0) + ' | $' + revenue, { size: 28, fill: isActive ? 0x4CAF50 : 0x888888 }); txt.anchor.set(1, 0); txt.x = 0; txt.y = y; salesLogContainer.addChild(txt); salesLogEntries.push(txt); y += 36; } } // Main menu container var mainMenu = new Container(); game.addChild(mainMenu); // --- How to Play Button and Info Popup --- var howToPlayBtn = new Button(); howToPlayBtn.setLabel('How to Play?'); howToPlayBtn.x = 1024; howToPlayBtn.y = 180; howToPlayBtn.onClick = function () { // Remove previous popup if any if (mainMenu.howToPlayPopup) { mainMenu.howToPlayPopup.destroy(); mainMenu.howToPlayPopup = null; } var popup = new Container(); popup.x = 1024; popup.y = 600; var bg = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.5, scaleY: 2.2 }); bg.tint = 0x16213e; popup.addChild(bg); var infoText = new Text2("Welcome to Game Dev Studio!\n\n" + "• Hire talented developers to join your team.\n" + "• Start new projects and select the best features for your games.\n" + "• Follow market trends and research new technologies to stay ahead.\n" + "• Release your games, earn money, and gain fans.\n" + "• Upgrade your studio to hire more developers and unlock new possibilities.\n" + "• Compete with rival companies and become the top game studio!\n\n" + "Tip: Use the main menu to access hiring, research, platforms, and more.", { size: 36, fill: 0xFFFFFF, align: "center" }); infoText.anchor.set(0.5, 0.5); infoText.x = 0; infoText.y = -40; popup.addChild(infoText); var closeBtn = new Button(); closeBtn.setLabel('Close'); closeBtn.x = 0; closeBtn.y = 320; closeBtn.onClick = function () { if (mainMenu.howToPlayPopup) { mainMenu.howToPlayPopup.destroy(); mainMenu.howToPlayPopup = null; } }; popup.addChild(closeBtn); mainMenu.addChild(popup); mainMenu.howToPlayPopup = popup; }; mainMenu.addChild(howToPlayBtn); var titleText = new Text2('Game Dev Studio', { size: 80, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 300; mainMenu.addChild(titleText); var hireDeveloperBtn = new Button(); hireDeveloperBtn.setLabel('Hire Developer'); hireDeveloperBtn.x = 1024; hireDeveloperBtn.y = 750; hireDeveloperBtn.onClick = showHireMenu; mainMenu.addChild(hireDeveloperBtn); var startProjectBtn = new Button(); startProjectBtn.setLabel('Start Project'); startProjectBtn.x = 1024; startProjectBtn.y = 900; startProjectBtn.onClick = showProjectMenu; mainMenu.addChild(startProjectBtn); var allGamesBtn = new Button(); allGamesBtn.setLabel('All Released Games'); allGamesBtn.x = 1024; allGamesBtn.y = 1050; allGamesBtn.onClick = showAllGamesMenu; mainMenu.addChild(allGamesBtn); var researchBtn = new Button(); researchBtn.setLabel('Research'); researchBtn.x = 1024; researchBtn.y = 1200; researchBtn.onClick = showResearchMenu; mainMenu.addChild(researchBtn); // (Game Engine button removed) // --- Bank Button --- var bankBtn = new Button(); bankBtn.setLabel('Bank'); bankBtn.x = 1024; bankBtn.y = 1550; bankBtn.onClick = showBankMenu; mainMenu.addChild(bankBtn); // --- Platform Button --- var platformBtn = new Button(); platformBtn.setLabel('Platform'); platformBtn.x = 1024; platformBtn.y = 1650; platformBtn.onClick = showPlatformMenu; mainMenu.addChild(platformBtn); // --- Fan Button --- var fanBtn = new Button(); fanBtn.setLabel('Fan'); fanBtn.x = 1024; fanBtn.y = 1800; fanBtn.onClick = showFanMenu; mainMenu.addChild(fanBtn); // --- Fan Store Button --- var fanStoreBtn = new Button(); fanStoreBtn.setLabel('Fan Store'); fanStoreBtn.x = 1024; fanStoreBtn.y = 1920; fanStoreBtn.onClick = showFanStoreMenu; mainMenu.addChild(fanStoreBtn); // --- Rivals Button --- var rivalsBtn = new Button(); rivalsBtn.setLabel('Rivals'); rivalsBtn.x = 1024; rivalsBtn.y = 2040; // 2 satır altı (120px aralık) rivalsBtn.onClick = showRivalsMenu; mainMenu.addChild(rivalsBtn); // --- Rivals Games Button --- var rivalsGamesBtn = new Button(); rivalsGamesBtn.setLabel('Rivals Games'); rivalsGamesBtn.x = 1024; rivalsGamesBtn.y = 2160; // Rivals butonunun hemen altında rivalsGamesBtn.onClick = showRivalsGamesMenu; mainMenu.addChild(rivalsGamesBtn); // --- Bank Menu UI --- var bankMenu = new Container(); bankMenu.visible = false; game.addChild(bankMenu); var bankTitle = new Text2('Bank', { size: 60, fill: 0xFFFFFF }); bankTitle.anchor.set(0.5, 0.5); bankTitle.x = 1024; bankTitle.y = 200; bankMenu.addChild(bankTitle); // Bilgi yazısı: Banka sistemi hakkında açıklama (Geri tuşunun 3 satır yukarısına) var bankInfoText = new Text2("Bank System:\n" + "- You must have no outstanding debt to take a new loan.\n" + "- If you pay off a loan early, you pay 10% extra of the original amount.\n" + "- When a loan matures, no extra interest is added; the debt waits until paid.\n" + "- You can deposit up to 50% of your cash as a deposit.\n" + "- When a deposit matures, interest stops. Use the withdraw button to collect your money.", { size: 32, fill: 0xFFC107, align: "center" }); bankInfoText.anchor.set(0.5, 1); bankInfoText.x = 1024; bankInfoText.y = 2400 - 3 * 50; // 3 satır yukarı (her satır ~50px) bankMenu.addChild(bankInfoText); var bankBackBtn = new Button(); bankBackBtn.setLabel('Back'); bankBackBtn.x = 1024; bankBackBtn.y = 2400; bankBackBtn.onClick = function () { bankMenu.visible = false; mainMenu.visible = true; }; bankMenu.addChild(bankBackBtn); // --- Bank state --- if (!gameState.bank) { gameState.bank = { credit: 0, creditDueDay: 0, deposit: 0, depositDueDay: 0 }; } // --- Show Bank Menu function --- function showBankMenu() { mainMenu.visible = false; bankMenu.visible = true; // Remove old UI except title and back and info text for (var i = bankMenu.children.length - 1; i >= 0; i--) { var child = bankMenu.children[i]; if (child !== bankTitle && child !== bankBackBtn && child !== bankInfoText) { child.destroy(); } } // Re-add info text if not present if (!bankMenu.children.includes(bankInfoText)) { bankMenu.addChild(bankInfoText); } // Info text var infoText = new Text2('You can take a loan or make a deposit.', { size: 36, fill: 0x4CAF50 }); infoText.anchor.set(0.5, 0.5); infoText.x = 1024; infoText.y = 350; bankMenu.addChild(infoText); // --- Credit Section --- var creditTitle = new Text2('Take Loan', { size: 40, fill: 0xFFC107 }); creditTitle.anchor.set(0.5, 0.5); creditTitle.x = 1024; creditTitle.y = 500; bankMenu.addChild(creditTitle); var creditAmount = 10000; var creditInterest = 0.15; // %15 faiz var creditDuration = 10; // 10 gün vade var creditBtn = new Button(); creditBtn.setLabel('Take Loan (15% interest, 10 days, Limit: 20% of cash)'); creditBtn.x = 1024; creditBtn.y = 600; creditBtn.onClick = function () { // Prevent new credit if there is any unpaid debt (even if overdue) if (gameState.bank.credit > 0) { // Show notification var notif = new Container(); var bg = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 0.5 }); bg.tint = 0xE94560; notif.addChild(bg); var txt = new Text2('You must pay your previous loan first!', { size: 32, fill: 0xFFFFFF }); txt.anchor.set(0.5, 0.5); notif.addChild(txt); notif.x = 1024; notif.y = 800; notif.alpha = 0; game.addChild(notif); tween(notif, { alpha: 1 }, { duration: 400, onFinish: function onFinish() { LK.setTimeout(function () { tween(notif, { alpha: 0 }, { duration: 400, onFinish: function onFinish() { notif.destroy(); } }); }, 1500); } }); return; } // Calculate credit limit as 20% of current cash (rounded down to nearest 1000) var maxCredit = Math.floor(gameState.money * 0.2 / 1000) * 1000; if (maxCredit < 1000) maxCredit = 1000; // Minimum 1000₺ var creditInterest = 0.15; // %15 faiz var creditDuration = 10; // 10 gün vade if (maxCredit <= 0) { // Show notification for no available credit var notif = new Container(); var bg = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 0.5 }); bg.tint = 0xE94560; notif.addChild(bg); var txt = new Text2('No loan limit! (You have too little cash)', { size: 32, fill: 0xFFFFFF }); txt.anchor.set(0.5, 0.5); notif.addChild(txt); notif.x = 1024; notif.y = 800; notif.alpha = 0; game.addChild(notif); tween(notif, { alpha: 1 }, { duration: 400, onFinish: function onFinish() { LK.setTimeout(function () { tween(notif, { alpha: 0 }, { duration: 400, onFinish: function onFinish() { notif.destroy(); } }); }, 1500); } }); return; } // Grant credit gameState.money += maxCredit; gameState.bank.credit = maxCredit * (1 + creditInterest); gameState.bank.creditDueDay = gameState.currentDay + creditDuration; updateUI(); showBankMenu(); LK.getSound('success').play(); }; bankMenu.addChild(creditBtn); var creditStatus = ''; if (gameState.bank.credit > 0 && gameState.currentDay < gameState.bank.creditDueDay) { creditStatus = 'Remaining Debt: ' + Math.round(gameState.bank.credit) + ' | Due Day: ' + gameState.bank.creditDueDay; } else if (gameState.bank.credit > 0 && gameState.currentDay >= gameState.bank.creditDueDay) { creditStatus = 'Loan matured! Debt: ' + Math.round(gameState.bank.credit); } else { creditStatus = 'No active loan.'; } var creditStatusText = new Text2(creditStatus, { size: 30, fill: 0xFFFFFF }); creditStatusText.anchor.set(0.5, 0.5); creditStatusText.x = 1024; creditStatusText.y = 670; bankMenu.addChild(creditStatusText); // --- Deposit Section --- var depositTitle = new Text2('Make Deposit', { size: 40, fill: 0x2196F3 }); depositTitle.anchor.set(0.5, 0.5); depositTitle.x = 1024; depositTitle.y = 850; bankMenu.addChild(depositTitle); // Ava: Mevduat yatırma oranı, nakit paramızın maksimum %50'sine kadar olmalı var depositInterest = 0.10; // %10 faiz var depositDuration = 10; // 10 gün vade // Hesaplanan maksimum mevduat miktarı (en az 1000₺, 1000'lik katlar) var maxDeposit = Math.floor(gameState.money * 0.5 / 1000) * 1000; if (maxDeposit < 1000) maxDeposit = 1000; var depositAmount = maxDeposit; var depositBtn = new Button(); depositBtn.setLabel(maxDeposit + ' Deposit (10% interest, 10 days)'); depositBtn.x = 1024; depositBtn.y = 950; depositBtn.onClick = function () { // Only allow one active deposit at a time if (gameState.bank.deposit > 0 && gameState.currentDay < gameState.bank.depositDueDay) { // Show notification var notif = new Container(); var bg = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 0.5 }); bg.tint = 0xE94560; notif.addChild(bg); var txt = new Text2('Your previous deposit is still maturing!', { size: 32, fill: 0xFFFFFF }); txt.anchor.set(0.5, 0.5); notif.addChild(txt); notif.x = 1024; notif.y = 1150; notif.alpha = 0; game.addChild(notif); tween(notif, { alpha: 1 }, { duration: 400, onFinish: function onFinish() { LK.setTimeout(function () { tween(notif, { alpha: 0 }, { duration: 400, onFinish: function onFinish() { notif.destroy(); } }); }, 1500); } }); return; } if (gameState.money < depositAmount) { // Show notification var notif = new Container(); var bg = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 0.5 }); bg.tint = 0xE94560; notif.addChild(bg); var txt = new Text2('Not enough money!', { size: 32, fill: 0xFFFFFF }); txt.anchor.set(0.5, 0.5); notif.addChild(txt); notif.x = 1024; notif.y = 1150; notif.alpha = 0; game.addChild(notif); tween(notif, { alpha: 1 }, { duration: 400, onFinish: function onFinish() { LK.setTimeout(function () { tween(notif, { alpha: 0 }, { duration: 400, onFinish: function onFinish() { notif.destroy(); } }); }, 1500); } }); return; } gameState.money -= depositAmount; gameState.bank.deposit = depositAmount * (1 + depositInterest); gameState.bank.depositDueDay = gameState.currentDay + depositDuration; updateUI(); showBankMenu(); LK.getSound('success').play(); }; bankMenu.addChild(depositBtn); var depositStatus = ''; if (gameState.bank.deposit > 0 && gameState.currentDay < gameState.bank.depositDueDay) { depositStatus = 'Deposit: ' + Math.round(gameState.bank.deposit) + ' | Due Day: ' + gameState.bank.depositDueDay; } else if (gameState.bank.deposit > 0 && gameState.currentDay >= gameState.bank.depositDueDay) { depositStatus = 'Deposit matured! Withdrawable: ' + Math.round(gameState.bank.deposit); } else { depositStatus = 'No active deposit.'; } var depositStatusText = new Text2(depositStatus, { size: 30, fill: 0xFFFFFF }); depositStatusText.anchor.set(0.5, 0.5); depositStatusText.x = 1024; depositStatusText.y = 1020; bankMenu.addChild(depositStatusText); // --- Deposit Withdraw Button (if matured) --- if (gameState.bank.deposit > 0 && gameState.currentDay >= gameState.bank.depositDueDay) { var withdrawBtn = new Button(); withdrawBtn.setLabel('Withdraw Deposit (+ ' + Math.round(gameState.bank.deposit) + ')'); withdrawBtn.x = 1024; withdrawBtn.y = 1100; withdrawBtn.onClick = function () { gameState.money += Math.round(gameState.bank.deposit); gameState.bank.deposit = 0; gameState.bank.depositDueDay = 0; updateUI(); showBankMenu(); LK.getSound('success').play(); }; bankMenu.addChild(withdrawBtn); } // --- Credit Pay Button (if matured or early) --- // Early payment: allow if credit > 0 and not overdue if (gameState.bank.credit > 0 && gameState.currentDay < gameState.bank.creditDueDay) { var earlyPayBtn = new Button(); // Early payment is original credit + 10% of original credit (not 10% of current debt) // Calculate original credit amount (principal) var originalCredit = Math.round(gameState.bank.credit / 1.15); // since credit = principal * 1.15 var earlyPayAmount = Math.round(originalCredit * 1.10); // %10 fazlası earlyPayBtn.setLabel('Pay Early (-' + earlyPayAmount + ', 10% interest)'); earlyPayBtn.x = 1024; earlyPayBtn.y = 750; earlyPayBtn.onClick = function () { if (gameState.money >= earlyPayAmount) { gameState.money -= earlyPayAmount; gameState.bank.credit = 0; gameState.bank.creditDueDay = 0; updateUI(); showBankMenu(); LK.getSound('success').play(); } else { // Show notification var notif = new Container(); var bg = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 0.5 }); bg.tint = 0xE94560; notif.addChild(bg); var txt = new Text2('Not enough money!', { size: 32, fill: 0xFFFFFF }); txt.anchor.set(0.5, 0.5); notif.addChild(txt); notif.x = 1024; notif.y = 900; notif.alpha = 0; game.addChild(notif); tween(notif, { alpha: 1 }, { duration: 400, onFinish: function onFinish() { LK.setTimeout(function () { tween(notif, { alpha: 0 }, { duration: 400, onFinish: function onFinish() { notif.destroy(); } }); }, 1500); } }); } }; bankMenu.addChild(earlyPayBtn); } // Normal payment: if matured or overdue if (gameState.bank.credit > 0 && gameState.currentDay >= gameState.bank.creditDueDay) { var payBtn = new Button(); payBtn.setLabel('Pay Loan (-' + Math.round(gameState.bank.credit) + ')'); payBtn.x = 1024; payBtn.y = 750; payBtn.onClick = function () { if (gameState.money >= Math.round(gameState.bank.credit)) { gameState.money -= Math.round(gameState.bank.credit); gameState.bank.credit = 0; gameState.bank.creditDueDay = 0; updateUI(); showBankMenu(); LK.getSound('success').play(); } else { // Show notification var notif = new Container(); var bg = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 0.5 }); bg.tint = 0xE94560; notif.addChild(bg); var txt = new Text2('Not enough money!', { size: 32, fill: 0xFFFFFF }); txt.anchor.set(0.5, 0.5); notif.addChild(txt); notif.x = 1024; notif.y = 900; notif.alpha = 0; game.addChild(notif); tween(notif, { alpha: 1 }, { duration: 400, onFinish: function onFinish() { LK.setTimeout(function () { tween(notif, { alpha: 0 }, { duration: 400, onFinish: function onFinish() { notif.destroy(); } }); }, 1500); } }); } }; bankMenu.addChild(payBtn); } } // --- Rivals Games Menu UI --- var rivalsGamesMenu = new Container(); rivalsGamesMenu.visible = false; game.addChild(rivalsGamesMenu); var rivalsGamesTitle = new Text2('Rivals Games', { size: 60, fill: 0xFFFFFF }); rivalsGamesTitle.anchor.set(0.5, 0.5); rivalsGamesTitle.x = 1024; rivalsGamesTitle.y = 200; rivalsGamesMenu.addChild(rivalsGamesTitle); var rivalsGamesBackBtn = new Button(); rivalsGamesBackBtn.setLabel('Geri'); rivalsGamesBackBtn.x = 1024; rivalsGamesBackBtn.y = 2400; rivalsGamesBackBtn.onClick = function () { rivalsGamesMenu.visible = false; mainMenu.visible = true; }; rivalsGamesMenu.addChild(rivalsGamesBackBtn); // --- Helper: Show Rivals Games Menu --- function showRivalsGamesMenu() { mainMenu.visible = false; rivalsGamesMenu.visible = true; // Eski kartları temizle (başlık ve geri hariç) for (var i = rivalsGamesMenu.children.length - 1; i >= 0; i--) { var child = rivalsGamesMenu.children[i]; if (child !== rivalsGamesTitle && child !== rivalsGamesBackBtn) { child.destroy(); } } // Tüm rakiplerin çıkardığı oyunları topla var allRivalGames = []; for (var i = 0; i < gameState.rivals.length; i++) { var rival = gameState.rivals[i]; if (rival.games && rival.games.length > 0) { for (var j = 0; j < rival.games.length; j++) { var g = rival.games[j]; // Her oyun için rakip adı ekle allRivalGames.push({ name: g.name, revenue: g.revenue, releaseDay: g.releaseDay, rivalName: rival.name }); } } } // Oyunları en yeniye göre sırala (büyükten küçüğe) allRivalGames.sort(function (a, b) { return b.releaseDay - a.releaseDay; }); // Hiç oyun yoksa bilgi göster if (allRivalGames.length === 0) { var noRivalGamesText = new Text2('No rival has released a game yet', { size: 40, fill: 0xFFFFFF }); noRivalGamesText.anchor.set(0.5, 0.5); noRivalGamesText.x = 1024; noRivalGamesText.y = 600; rivalsGamesMenu.addChild(noRivalGamesText); return; } // 4 sütun, 7 satır grid (28 oyun gösterilecek şekilde) var cols = 4; var xStart = 320, yStart = 440 * 1.1, xSpacing = 370 * 1.1, ySpacing = 180 * 1.1; for (var i = 0; i < allRivalGames.length && i < 28; i++) { var game = allRivalGames[i]; var col = i % cols, row = Math.floor(i / cols); var container = new Container(); container.x = xStart + col * xSpacing; container.y = yStart + row * ySpacing; // Kart arka planı var bg = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 0.45 }); container.addChild(bg); // Oyun adı var nameText = new Text2(game.name, { size: 28, fill: 0xFFFFFF }); nameText.anchor.set(0.5, 0.5); nameText.y = -30; container.addChild(nameText); // Rakip firma adı var rivalText = new Text2('Company: ' + game.rivalName, { size: 24, fill: 0x2196F3 }); rivalText.anchor.set(0.5, 0.5); rivalText.y = 10; container.addChild(rivalText); // Gelir veya Zarar var revenueLabel = 'Gelir: $' + game.revenue; var revenueColor = 0x4CAF50; if (typeof game.revenue === "number" && game.revenue === 0) { // Zarar varsa, revenue 0 olarak tutuluyor, ama aslında zarar vardı. // Oyun objesinde orijinal zarar bilgisini bulmak için rakip firmanın oyunlarını arayalım. var actualLoss = 0; for (var ri = 0; ri < gameState.rivals.length; ri++) { var rival = gameState.rivals[ri]; if (rival.name === game.rivalName && rival.games && rival.games.length > 0) { for (var gj = 0; gj < rival.games.length; gj++) { var g2 = rival.games[gj]; if (g2.name === game.name && g2.releaseDay === game.releaseDay) { // Orijinal revenue negatifse, onu göster if (typeof g2._originalLoss === "number" && g2._originalLoss > 0) { actualLoss = g2._originalLoss; } else if (typeof g2._originalRevenue === "number" && g2._originalRevenue < 0) { actualLoss = -g2._originalRevenue; } } } } } revenueLabel = 'Loss: $' + (actualLoss > 0 ? actualLoss : 0); revenueColor = 0xE94560; } var revenueText = new Text2(revenueLabel, { size: 24, fill: revenueColor }); revenueText.anchor.set(0.5, 0.5); revenueText.y = 40; container.addChild(revenueText); // Çıkış günü var dayText = new Text2('Day: ' + game.releaseDay, { size: 22, fill: 0xFFC107 }); dayText.anchor.set(0.5, 0.5); dayText.y = 70; container.addChild(dayText); rivalsGamesMenu.addChild(container); } } // --- Rivals Menu UI --- var rivalsMenu = new Container(); rivalsMenu.visible = false; game.addChild(rivalsMenu); var rivalsTitle = new Text2('Rival Companies', { size: 60, fill: 0xFFFFFF }); rivalsTitle.anchor.set(0.5, 0.5); rivalsTitle.x = 1024; rivalsTitle.y = 200; rivalsMenu.addChild(rivalsTitle); var rivalsBackBtn = new Button(); rivalsBackBtn.setLabel('Back'); rivalsBackBtn.x = 1024; rivalsBackBtn.y = 2400; rivalsBackBtn.onClick = function () { rivalsMenu.visible = false; mainMenu.visible = true; }; rivalsMenu.addChild(rivalsBackBtn); // --- Rivals Data --- if (!gameState.rivals) { // 28 popüler firma, her biri 20-30 günde bir oyun çıkarır var rivalNames = ["PixelForge", "BitMasters", "RetroSoft", "NextGen Games", "Funbyte", "DreamPixel", "CodeCrafters", "GameNest", "Playverse", "IndieGiant", "ArcadiaWorks", "QuantumPlay", "StudioNova", "BlueBox", "RedShift", "MegaFun", "GameWave", "Starbyte", "EpicPlay", "VirtuaDev", // 8 yeni firma "NeonPixel", "TurboPlay", "GameSmiths", "HyperNova", "PlayMakers", "PixelPioneers", "FunLab", "InfinityGames"]; gameState.rivals = []; for (var i = 0; i < rivalNames.length; i++) { var baseValue = 100000 + Math.floor(Math.random() * 100000); // 100k-200k arası başlangıç değeri var rival = { name: rivalNames[i], value: baseValue, ownedPercent: 0, // Oyuncunun sahip olduğu yüzde games: [], lastReleaseDay: 1 + Math.floor(Math.random() * 10), // İlk oyun çıkış günü releaseInterval: 20 + Math.floor(Math.random() * 11), // 20-30 gün arası avgRevenue: 0 // Son 3 oyunun ortalaması }; gameState.rivals.push(rival); } // Oyuncunun şirket değeri başlangıçta: anlık nakit paramın %20'si + sahip olunan şirketlerin değerleri toplamı var cash = gameState.money || 0; var cashPart = cash * 0.20; var ownedValueSum = 0; if (gameState.rivals && gameState.rivals.length > 0) { for (var i = 0; i < gameState.rivals.length; i++) { var rival = gameState.rivals[i]; if (rival.ownedPercent && rival.ownedPercent > 0) { ownedValueSum += Math.floor((rival.value || 0) * (rival.ownedPercent / 100)); } } } gameState.companyValue = Math.floor(cashPart + ownedValueSum); } // --- Helper: Rival yeni oyun çıkarır --- function rivalReleaseGame(rival, day) { // Oyun ismi ve gelirini üret var gameNames = ["Super", "Mega", "Ultra", "Epic", "Legend", "Pixel", "Quest", "Saga", "Chronicles", "World"]; var gameSuffix = ["Adventure", "Battle", "Story", "Kingdom", "Odyssey", "Arena", "Tycoon", "Empire", "Run", "Hero"]; var name = gameNames[Math.floor(Math.random() * gameNames.length)] + " " + gameSuffix[Math.floor(Math.random() * gameSuffix.length)]; // Rakip oyun kazancı, rakip şirket değerinin %1-%20 aralığında kâr veya %1-%20 aralığında zarar olacak şekilde ayarlandı var percent = (Math.random() < 0.5 ? -1 : 1) * (0.01 + Math.random() * 0.19); // -0.01 ile -0.20 veya +0.01 ile +0.20 arası var baseValue = rival.value || 100000; var revenue = Math.floor(baseValue * Math.abs(percent)); var originalRevenue = revenue; if (percent < 0) { revenue = -revenue; } var originalLoss = 0; if (revenue < 0) { originalLoss = -revenue; revenue = 0; } var game = { name: name, releaseDay: day, revenue: revenue, _originalRevenue: percent < 0 ? -originalRevenue : originalRevenue, _originalLoss: originalLoss }; rival.games.push(game); // Sadece son 3 oyunun ortalamasını tut if (rival.games.length > 3) rival.games = rival.games.slice(-3); // Firma değerini anlık olarak kâr/zarara göre değiştir: kâr ise artır, zarar ise azalt if (revenue > 0) { rival.value += revenue + Math.floor(revenue * 0.1); } else if (originalLoss > 0) { rival.value -= originalLoss; } if (rival.value < 0) rival.value = 0; // Son 3 oyunun ortalamasını güncelle var sum = 0; for (var i = 0; i < rival.games.length; i++) sum += rival.games[i].revenue; rival.avgRevenue = Math.floor(sum / rival.games.length); } // --- Helper: Oyuncu rakipten hisse satın alır --- function buyRivalShare(rival, percent) { var price = Math.floor(rival.value * percent / 100); if (gameState.money >= price && rival.ownedPercent + percent <= 100) { gameState.money -= price; rival.ownedPercent += percent; // --- Ava: Satın alınan %10'luk hisse için alış fiyatını kaydet --- if (!rival.sharePurchaseHistory) rival.sharePurchaseHistory = []; for (var i = 0; i < percent / 10; i++) { rival.sharePurchaseHistory.push(price); } // Ava: Increase player's company value by the purchased share percent of the rival's value if (!gameState.companyValue) gameState.companyValue = 0; gameState.companyValue += Math.floor(rival.value * (percent / 100)); updateUI(); LK.getSound('success').play(); showRivalsMenu(); } } // --- Helper: Rakiplerden oyuncuya gelir aktarımı --- function processRivalIncome() { for (var i = 0; i < gameState.rivals.length; i++) { var rival = gameState.rivals[i]; if (rival.ownedPercent > 0 && rival.avgRevenue > 0) { var income = Math.floor(rival.avgRevenue * (rival.ownedPercent / 100)); gameState.money += income; } } } // --- Rivals Menu Show --- function showRivalsMenu() { mainMenu.visible = false; rivalsMenu.visible = true; // Eski kartları temizle for (var i = rivalsMenu.children.length - 1; i >= 0; i--) { var child = rivalsMenu.children[i]; if (child !== rivalsTitle && child !== rivalsBackBtn) { child.destroy(); } } // 4 sütunlu grid, 7 satır (ekrana sığacak şekilde 28 firma için) // YENİ: yStart bir satır aşağı (ör: +40px), fontlar 30, hizalama güncellendi var cols = 4; var xStart = 320, yStart = 440 * 1.1, // 1 satır aşağı xSpacing = 370 * 1.1, ySpacing = 260 * 1.1; for (var i = 0; i < gameState.rivals.length; i++) { var rival = gameState.rivals[i]; var col = i % cols, row = Math.floor(i / cols); var container = new Container(); container.x = xStart + col * xSpacing; container.y = yStart + row * ySpacing; // Kart arka planı var bg = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 0.55 }); container.addChild(bg); // Firma adı var nameText = new Text2(rival.name, { size: 30, fill: 0xFFFFFF }); nameText.anchor.set(0.5, 0.5); nameText.y = -50; container.addChild(nameText); // Değer var valueText = new Text2('Value: $' + rival.value, { size: 30, fill: 0x4CAF50 }); valueText.anchor.set(0.5, 0.5); valueText.y = -10; container.addChild(valueText); // Sahip olunan yüzde var ownedText = new Text2('Ownership: %' + rival.ownedPercent, { size: 30, fill: rival.ownedPercent >= 100 ? 0xFFC107 : 0x2196F3 }); ownedText.anchor.set(0.5, 0.5); ownedText.y = 30; container.addChild(ownedText); // Son oyun(lar) var lastGame = rival.games.length > 0 ? rival.games[rival.games.length - 1] : null; var lastGameText = ""; if (lastGame) { if (typeof lastGame.revenue === "number" && lastGame.revenue === 0) { // Zarar miktarını göster var actualLoss = 0; if (typeof lastGame._originalLoss === "number" && lastGame._originalLoss > 0) { actualLoss = lastGame._originalLoss; } else if (typeof lastGame._originalRevenue === "number" && lastGame._originalRevenue < 0) { actualLoss = -lastGame._originalRevenue; } lastGameText = "Last Game: " + lastGame.name + " (Loss: $" + (actualLoss > 0 ? actualLoss : 0) + ")"; } else { lastGameText = "Last Game: " + lastGame.name + " ($" + lastGame.revenue + ")"; } } else { lastGameText = "No games yet"; } var gameText = new Text2(lastGameText, { size: 30, fill: 0xFFFFFF }); gameText.anchor.set(0.5, 0.5); gameText.y = 70; container.addChild(gameText); // Sadece 1 tane %10'luk buton göster, %100 olana kadar if (rival.ownedPercent < 100) { var percent = 10; var price = Math.floor(rival.value * percent / 100); var buyBtn = new Button(); buyBtn.setLabel('Buy 10% ($' + price + ')'); buyBtn.x = -90; buyBtn.y = 120; buyBtn.scaleX = 0.7; buyBtn.scaleY = 0.7; buyBtn.onClick = function (rival, percent) { return function () { buyRivalShare(rival, percent); }; }(rival, percent); container.addChild(buyBtn); // --- %10 Sat butonu --- if (rival.ownedPercent >= 10) { // --- Ava: Satış fiyatı, ilk alış fiyatına göre hesaplanmalı! --- // Satın alınan her %10'luk hisse için alış fiyatını kaydet if (!rival.sharePurchaseHistory) rival.sharePurchaseHistory = []; // Eğer sharePurchaseHistory eksikse, eski kayıtlara göre doldur (eski kayıtsız oyunlar için) var ownedShares = Math.floor(rival.ownedPercent / 10); while (rival.sharePurchaseHistory.length < ownedShares) { // Eski oyunlarda, ilk alış fiyatı olarak o anki değeri kaydet rival.sharePurchaseHistory.push(Math.floor(rival.value * 0.1)); } // Satılacak ilk %10'luk hissenin alış fiyatı var sellPrice = rival.sharePurchaseHistory.length > 0 ? rival.sharePurchaseHistory[0] : price; var sellBtn = new Button(); sellBtn.setLabel('Sell 10% (+$' + sellPrice + ')'); sellBtn.x = 90; sellBtn.y = 120; sellBtn.scaleX = 0.7; sellBtn.scaleY = 0.7; sellBtn.onClick = function (rival, percent) { return function () { // Satış işlemi: %10 hisseyi sat, para al, şirket değerini azalt if (rival.ownedPercent >= percent && rival.sharePurchaseHistory && rival.sharePurchaseHistory.length > 0) { rival.ownedPercent -= percent; var soldPrice = rival.sharePurchaseHistory.shift(); gameState.money += soldPrice; // Ava: Satınca şirket değerini de orantılı azalt if (!gameState.companyValue) gameState.companyValue = 0; gameState.companyValue -= Math.floor(rival.value * (percent / 100)); if (gameState.companyValue < 0) gameState.companyValue = 0; updateUI(); LK.getSound('success').play(); showRivalsMenu(); } }; }(rival, percent); container.addChild(sellBtn); } } else { // %100 ise, gelirinin tamamı oyuncuya geçer var fullText = new Text2('All income is yours!', { size: 30, fill: 0xFFC107 }); fullText.anchor.set(0.5, 0.5); fullText.y = 120; container.addChild(fullText); } rivalsMenu.addChild(container); } // Rivals sayfasına girince şirket değerini anlık olarak güncelle var cash = gameState.money || 0; var cashPart = cash * 0.20; var ownedValueSum = 0; if (gameState.rivals && gameState.rivals.length > 0) { for (var i = 0; i < gameState.rivals.length; i++) { var rival = gameState.rivals[i]; if (rival.ownedPercent && rival.ownedPercent > 0) { ownedValueSum += Math.floor((rival.value || 0) * (rival.ownedPercent / 100)); } } } gameState.companyValue = Math.floor(cashPart + ownedValueSum); // Oyuncu şirket değeri göster if (rivalsMenu.companyValueText) rivalsMenu.companyValueText.destroy(); var companyValueText = new Text2('Your Company Value: $' + (gameState.companyValue || 0), { size: 38, fill: 0xE94560 }); companyValueText.anchor.set(0.5, 0.5); companyValueText.x = 1024; companyValueText.y = 350; rivalsMenu.addChild(companyValueText); rivalsMenu.companyValueText = companyValueText; } // --- Her gün başında rakipler yeni oyun çıkarır ve gelirler işlenir --- if (!gameState._rivalLastDay) gameState._rivalLastDay = gameState.currentDay; var _oldGameUpdate = game.update; game.update = function () { // Her gün başında if (gameState.currentDay !== gameState._rivalLastDay) { for (var i = 0; i < gameState.rivals.length; i++) { var rival = gameState.rivals[i]; if (!rival.lastReleaseDay) rival.lastReleaseDay = 1; if (!rival.releaseInterval) rival.releaseInterval = 25; if (gameState.currentDay - rival.lastReleaseDay >= rival.releaseInterval) { rivalReleaseGame(rival, gameState.currentDay); rival.lastReleaseDay = gameState.currentDay; } } // Oyuncuya rakiplerden gelir aktar processRivalIncome(); // Oyuncu şirket değeri: Son 3 oyunun ortalamasının 5 katı + 50k var myAvg = 0; if (gameState.releasedGames && gameState.releasedGames.length > 0) { var sum = 0, count = 0; for (var i = gameState.releasedGames.length - 1; i >= 0 && count < 3; i--, count++) { var g = gameState.releasedGames[i]; var pricePerCopy = typeof g.price === "number" ? g.price : 1; sum += (g.totalSales || 0) * pricePerCopy; } if (count > 0) myAvg = Math.floor(sum / count); } // --- Ava: Şirket değeri, anlık nakit paramın %20'si + aldığım şirketlerin değerleri toplamı olarak hesaplanır --- var cash = gameState.money || 0; var cashPart = cash * 0.20; var ownedValueSum = 0; if (gameState.rivals && gameState.rivals.length > 0) { for (var i = 0; i < gameState.rivals.length; i++) { var rival = gameState.rivals[i]; if (rival.ownedPercent && rival.ownedPercent > 0) { ownedValueSum += Math.floor((rival.value || 0) * (rival.ownedPercent / 100)); } } } gameState.companyValue = Math.floor(cashPart + ownedValueSum); gameState._rivalLastDay = gameState.currentDay; } if (_oldGameUpdate) _oldGameUpdate(); }; // --- Fan Menu UI --- var fanMenu = new Container(); fanMenu.visible = false; game.addChild(fanMenu); var fanTitle = new Text2('Fan Shop', { size: 60, fill: 0xFFFFFF }); fanTitle.anchor.set(0.5, 0.5); fanTitle.x = 1024; fanTitle.y = 200; fanMenu.addChild(fanTitle); var fanBackBtn = new Button(); fanBackBtn.setLabel('Back'); fanBackBtn.x = 1024; fanBackBtn.y = 2400; fanBackBtn.onClick = function () { fanMenu.visible = false; mainMenu.visible = true; }; fanMenu.addChild(fanBackBtn); // Fan products (each gives fans) var fanProducts = [{ name: "T-shirt", price: 400, fans: 40, desc: "Studio t-shirt, gives 40 fans." }, { name: "Poster", price: 800, fans: 100, desc: "Game poster, gives 100 fans." }, { name: "Mug", price: 1500, fans: 200, desc: "Studio mug, gives 200 fans." }, { name: "Keychain", price: 2500, fans: 350, desc: "Studio keychain, gives 350 fans." }, { name: "Mousepad", price: 3500, fans: 500, desc: "Studio mousepad, gives 500 fans." }, { name: "Figure", price: 6000, fans: 900, desc: "Collector's figure, gives 900 fans." }, { name: "Collector's Pack", price: 12000, fans: 2000, desc: "Special collector's pack, gives 2000 fans." }, { name: "Hoodie", price: 20000, fans: 3500, desc: "Studio hoodie, gives 3500 fans." }, { name: "Limited Edition Art", price: 35000, fans: 6000, desc: "Limited edition art, gives 6000 fans." }, { name: "VIP Fan Club Membership", price: 50000, fans: 10000, desc: "VIP fan club membership, gives 10000 fans." }]; // --- Fan Store Products (20 items, computers and game-related) --- var fanStoreProducts = [{ name: "Retro PC", price: 2000, desc: "Classic 80s computer.", type: "hardware" }, { name: "Game Console", price: 3000, desc: "Legendary game console.", type: "hardware" }, { name: "Joystick", price: 500, desc: "Retro joystick.", type: "accessory" }, { name: "Gaming Mouse", price: 800, desc: "Precision gaming mouse.", type: "accessory" }, { name: "Keyboard", price: 700, desc: "Mechanical keyboard.", type: "accessory" }, { name: "Gaming Headset", price: 1200, desc: "Surround sound headset.", type: "accessory" }, { name: "Game Magazine", price: 300, desc: "Collector's magazine.", type: "magazine" }, { name: "Game Cartridge", price: 600, desc: "Rare game cartridge.", type: "game" }, { name: "Collector's Edition", price: 5000, desc: "Special collector's box.", type: "game" }, { name: "Game Poster", price: 400, desc: "Classic game poster.", type: "poster" }, { name: "Desktop PC", price: 4000, desc: "Powerful desktop PC.", type: "hardware" }, { name: "Laptop", price: 3500, desc: "Portable gaming laptop.", type: "hardware" }, { name: "Gaming Mousepad", price: 350, desc: "Large mousepad.", type: "accessory" }, { name: "Game Figure", price: 900, desc: "Collector's figure.", type: "figure" }, { name: "Game Keychain", price: 200, desc: "Game-themed keychain.", type: "accessory" }, { name: "Game T-shirt", price: 250, desc: "Game logo t-shirt.", type: "clothing" }, { name: "Game Hoodie", price: 600, desc: "Warm hoodie.", type: "clothing" }, { name: "Game Art", price: 1500, desc: "Artistic game painting.", type: "poster" }, { name: "Mouse Wristband", price: 150, desc: "Comfortable wristband.", type: "accessory" }, { name: "Sticker Pack", price: 100, desc: "Pack of 10 stickers.", type: "accessory" }, // --- 5 new products added --- { name: "RGB LED Strip", price: 450, desc: "Colorful LED strip for your game room.", type: "accessory" }, { name: "Mouse Stand", price: 300, desc: "Stylish mouse stand.", type: "accessory" }, { name: "Game Notebook", price: 200, desc: "Game-themed notebook for taking notes.", type: "stationery" }, { name: "Game Pen Set", price: 120, desc: "Set of 5 game-themed pens.", type: "stationery" }, { name: "Game Puzzle", price: 600, desc: "500-piece game-themed puzzle.", type: "game" }]; // --- Fan Store Menu UI --- var fanStoreMenu = new Container(); fanStoreMenu.visible = false; game.addChild(fanStoreMenu); var fanStoreTitle = new Text2('Fan Store', { size: 60, fill: 0xFFFFFF }); fanStoreTitle.anchor.set(0.5, 0.5); fanStoreTitle.x = 1024; fanStoreTitle.y = 200; fanStoreMenu.addChild(fanStoreTitle); var fanStoreBackBtn = new Button(); fanStoreBackBtn.setLabel('Back'); fanStoreBackBtn.x = 1024; fanStoreBackBtn.y = 2400; fanStoreBackBtn.onClick = function () { fanStoreMenu.visible = false; mainMenu.visible = true; }; fanStoreMenu.addChild(fanStoreBackBtn); // Helper for showing the fan menu function showFanMenu() { mainMenu.visible = false; fanMenu.visible = true; // Remove old product cards/buttons for (var i = fanMenu.children.length - 1; i >= 0; i--) { var child = fanMenu.children[i]; if (child !== fanTitle && child !== fanBackBtn) { child.destroy(); } } // Show all products in a grid: 2 columns per row var yStart = 500; var xStart = 700; var xSpacing = 600; var ySpacing = 300; var cols = 2; for (var i = 0; i < fanProducts.length; i++) { var prod = fanProducts[i]; var container = new Container(); var col = i % cols; var row = Math.floor(i / cols); container.x = xStart + col * xSpacing; container.y = yStart + row * ySpacing; // Card background var bg = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 0.7 }); container.addChild(bg); // Product name var nameText = new Text2(prod.name, { size: 40, fill: 0xFFFFFF }); nameText.anchor.set(0.5, 0.5); nameText.y = -60; container.addChild(nameText); // Description var descText = new Text2(prod.desc, { size: 28, fill: 0xFFC107 }); descText.anchor.set(0.5, 0.5); descText.y = 0; container.addChild(descText); // Price var priceText = new Text2('Price: $' + prod.price, { size: 30, fill: 0x4CAF50 }); priceText.anchor.set(0.5, 0.5); priceText.y = 50; container.addChild(priceText); // Buy button var buyBtn = new Button(); buyBtn.setLabel('Buy (+ ' + prod.fans + ' fan)'); buyBtn.x = 0; buyBtn.y = 120; buyBtn.onClick = function (prod) { return function () { if (gameState.money >= prod.price) { gameState.money -= prod.price; if (!gameState.fans) gameState.fans = 0; gameState.fans += prod.fans; updateUI(); LK.getSound('success').play(); showFanMenu(); } }; }(prod); container.addChild(buyBtn); fanMenu.addChild(container); } // Show current fan count at top if (fanMenu.fanCountText) fanMenu.fanCountText.destroy(); var fanCountText = new Text2('Total Fans: ' + (gameState.fans || 0), { size: 45, fill: 0x2196F3 }); fanCountText.anchor.set(0.5, 0.5); fanCountText.x = 1024; fanCountText.y = 400; fanMenu.addChild(fanCountText); fanMenu.fanCountText = fanCountText; } // Helper for showing the fan store menu function showFanStoreMenu() { mainMenu.visible = false; fanStoreMenu.visible = true; // Remove old product cards/buttons for (var i = fanStoreMenu.children.length - 1; i >= 0; i--) { var child = fanStoreMenu.children[i]; if (child !== fanStoreTitle && child !== fanStoreBackBtn) { child.destroy(); } } // Show all products in a grid: 5 columns per row, 4 rows (ekrana sığacak şekilde %20 büyütülmüş ve hizalanmış) // 20 ürün için 5x4 grid var yStart = 550; var xStart = 180; var xSpacing = 385; // %20 büyütülmüş kartlar için aralık artırıldı var ySpacing = 310; // %20 büyütülmüş kartlar için aralık artırıldı var cols = 5; for (var i = 0; i < fanStoreProducts.length; i++) { var prod = fanStoreProducts[i]; var container = new Container(); var col = i % cols; var row = Math.floor(i / cols); container.x = xStart + col * xSpacing; container.y = yStart + row * ySpacing; // Card background var bg = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.84, // 0.7 * 1.2 = 0.84, %20 büyütme scaleY: 0.6 // 0.5 * 1.2 = 0.6, %20 büyütme }); container.addChild(bg); // Product name var nameText = new Text2(prod.name, { size: 34, fill: 0xFFFFFF }); nameText.anchor.set(0.5, 0.5); nameText.y = -45; container.addChild(nameText); // Description var descText = new Text2(prod.desc, { size: 22, fill: 0xFFC107 }); descText.anchor.set(0.5, 0.5); descText.y = 0; container.addChild(descText); // Price (Satış fiyatı: alış fiyatı + %10 kâr) var salePrice = Math.round(prod.price * 1.1); var priceText = new Text2('Sale Price: $' + salePrice + ' (Cost: $' + prod.price + ')', { size: 24, fill: 0x4CAF50 }); priceText.anchor.set(0.5, 0.5); priceText.y = 38; container.addChild(priceText); // Buy button for Fan Store products var buyBtn = new Button(); buyBtn.setLabel('Buy (for Fans)'); // Scale down by 30% buyBtn.scaleX = 0.7; buyBtn.scaleY = 0.7; // Move button lower to visually separate from price buyBtn.x = 0; buyBtn.y = 120; buyBtn.onClick = function (prod) { return function () { // Only allow if player has enough money AND at least 50 fans if (gameState.money >= prod.price && (gameState.fans || 0) >= 50) { gameState.money -= prod.price; // Track owned count for each product if (!prod.owned) prod.owned = 0; prod.owned += 1; // Deduct 50 fans per purchase gameState.fans -= 50; updateUI(); LK.getSound('success').play(); showFanStoreMenu(); } }; }(prod); container.addChild(buyBtn); // Show owned count if any if (prod.owned && prod.owned > 0) { var ownedText = new Text2('Owned: ' + prod.owned, { size: 22, fill: 0x2196F3 }); ownedText.anchor.set(0.5, 0.5); ownedText.y = 65; container.addChild(ownedText); } fanStoreMenu.addChild(container); } // Show current fan count at top if (fanStoreMenu.fanCountText) fanStoreMenu.fanCountText.destroy(); var fanCountText = new Text2('Total Fans: ' + (gameState.fans || 0), { size: 45, fill: 0x2196F3 }); fanCountText.anchor.set(0.5, 0.5); fanCountText.x = 1024; fanCountText.y = 400; fanStoreMenu.addChild(fanCountText); fanStoreMenu.fanCountText = fanCountText; // --- Ava: Weekly Sales, Weekly Revenue, Total Products Sold --- // Find last week's sales log var lastLog = null; if (gameState.fanStoreAutoSaleLog && gameState.fanStoreAutoSaleLog.length > 0) { lastLog = gameState.fanStoreAutoSaleLog[gameState.fanStoreAutoSaleLog.length - 1]; } var weeklySalesCount = 0; var weeklyRevenue = 0; var weeklyProductCount = 0; if (lastLog) { for (var i = 0; i < lastLog.sales.length; i++) { weeklySalesCount += lastLog.sales[i].qty; weeklyProductCount += 1; } weeklyRevenue = lastLog.totalRevenue; } // Info text about profit margin if (fanStoreMenu.profitInfoText) fanStoreMenu.profitInfoText.destroy(); var profitInfoText = new Text2("Fan products are sold at 10% above purchase price (e.g. $500 product is sold for $550).", { size: 30, fill: 0x4CAF50, align: "center" }); profitInfoText.anchor.set(0.5, 1); profitInfoText.x = 1024; // Move 2 lines higher (assume 2x line height, ~64px per line for size 30) profitInfoText.y = fanStoreBackBtn.y - 120 - 64 * 2; fanStoreMenu.addChild(profitInfoText); fanStoreMenu.profitInfoText = profitInfoText; // Ava: Each product purchase costs 50 Fans. if (fanStoreMenu.fanCostInfoText) fanStoreMenu.fanCostInfoText.destroy(); var fanCostInfoText = new Text2("Each product purchase costs 50 Fans.", { size: 28, fill: 0x4CAF50, align: "center" }); fanCostInfoText.anchor.set(0.5, 1); fanCostInfoText.x = 1024; fanCostInfoText.y = profitInfoText.y + 40; fanStoreMenu.addChild(fanCostInfoText); fanStoreMenu.fanCostInfoText = fanCostInfoText; // Ava: Each product sale costs 100 Fans. if (fanStoreMenu.fanSaleCostInfoText) fanStoreMenu.fanSaleCostInfoText.destroy(); var fanSaleCostInfoText = new Text2("Each product sale costs 100 Fans.", { size: 28, fill: 0x4CAF50, align: "center" }); fanSaleCostInfoText.anchor.set(0.5, 1); fanSaleCostInfoText.x = 1024; fanSaleCostInfoText.y = fanCostInfoText.y + 40; fanStoreMenu.addChild(fanSaleCostInfoText); fanStoreMenu.fanSaleCostInfoText = fanSaleCostInfoText; // Calculate total number of products sold since the beginning var totalProductSold = 0; if (gameState.fanStoreAutoSaleLog && gameState.fanStoreAutoSaleLog.length > 0) { for (var i = 0; i < gameState.fanStoreAutoSaleLog.length; i++) { var log = gameState.fanStoreAutoSaleLog[i]; if (log && log.sales && log.sales.length > 0) { for (var j = 0; j < log.sales.length; j++) { totalProductSold += log.sales[j].qty; } } } } // Compose info text var weeklyInfoText = "Weekly Sales: " + weeklySalesCount + "\nWeekly Revenue: $" + weeklyRevenue + "\nTotal Products Sold: " + totalProductSold; if (fanStoreMenu.weeklyInfoText) fanStoreMenu.weeklyInfoText.destroy(); var infoText = new Text2(weeklyInfoText, { size: 32, fill: 0xFFC107, align: "center" }); infoText.anchor.set(0.5, 1); infoText.x = 1024; infoText.y = fanStoreBackBtn.y - 60; fanStoreMenu.addChild(infoText); fanStoreMenu.weeklyInfoText = infoText; } // --- Fan Store: Günlük orantılı satış sistemi --- // Her gün başında, mevcut fan sayısına orantılı olarak sahip olunan Store ürünlerinden satış yapılır if (typeof gameState.fanStoreAutoSaleLog === "undefined") { gameState.fanStoreAutoSaleLog = []; } // Yardımcı: Rastgele tamsayı [min, max] function getRandomIntFanStore(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } // Günlük fan store satış fonksiyonu function processFanStoreDailySale() { var totalFans = gameState.fans || 0; if (totalFans < 1) return; // En az 1 fan olmalı // Satış yapılacak toplam ürün adedi: her 100 fan için 1 satış, ancak 100'den az fan varsa da 1 satış yapılır var saleCount = Math.floor(totalFans / 100); if (saleCount < 1 && totalFans > 0) saleCount = 1; // Satış için yeterli fan yoksa, satış yapılmaz if (gameState.fans < 100) return; // Satılabilir ürünler: sadece owned > 0 olanlar var ownedProducts = fanStoreProducts.filter(function (prod) { return prod.owned && prod.owned > 0; }); if (ownedProducts.length === 0) return; // Satılacak ürün yoksa çık // Satışları orantılı dağıt: fan sayısına göre, sahip olunan ürünlerden rastgele seçerek var sales = []; var totalRevenue = 0; var fansBefore = gameState.fans; var fansToLose = 0; // Her ürün için, sahip olunan adede ve toplam fan sayısına göre satış miktarı belirle // Her ürün için: (ürün owned / toplam owned) * saleCount kadar satış var totalOwned = 0; for (var i = 0; i < ownedProducts.length; i++) { totalOwned += ownedProducts[i].owned; } // Her ürün için satış miktarını hesapla var remainingSaleCount = saleCount; for (var i = 0; i < ownedProducts.length; i++) { var prod = ownedProducts[i]; // Oranla dağıt, en az 1 satılabilir var prodSale = Math.floor(prod.owned / totalOwned * saleCount); if (prodSale < 1 && remainingSaleCount > 0) prodSale = 1; if (prodSale > prod.owned) prodSale = prod.owned; if (prodSale > remainingSaleCount) prodSale = remainingSaleCount; if (prodSale > 0) { sales.push({ name: prod.name, price: prod.price, qty: prodSale }); // Owned azalt prod.owned -= prodSale; // Kâr ekle (Satış fiyatı: alış fiyatı + %10 kâr) // Satış fiyatı = alış fiyatı * 1.1, kâr = alış fiyatı * 0.1 var salePrice = Math.round(prod.price * 1.1); totalRevenue += salePrice * prodSale; // Fan kaybı: her satışta 100 fan kaybı, ancak toplu olarak gün sonunda uygula fansToLose += prodSale * 100; // Her ürün satışı 100 fan maliyetindedir remainingSaleCount -= prodSale; } if (remainingSaleCount <= 0) break; } // Eğer yeterli fan yoksa, satış miktarını azalt if (fansToLose > gameState.fans) { // Kaç ürün satılabilir? var maxSales = Math.floor(gameState.fans / 100); // Satışları yeniden dağıt var totalReduced = 0; for (var i = 0; i < sales.length; i++) { if (totalReduced + sales[i].qty > maxSales) { sales[i].qty = Math.max(0, maxSales - totalReduced); } totalReduced += sales[i].qty; } // Owned'ları tekrar güncelle (fazla azaltılmışsa geri ekle) for (var i = 0; i < ownedProducts.length; i++) { var prod = ownedProducts[i]; var sale = sales.find(function (s) { return s.name === prod.name; }); if (sale) { var sold = sale.qty; var originallyReduced = prod.owned + sold; prod.owned += originallyReduced - sold; } } // fansToLose'u güncelle fansToLose = maxSales * 100; // totalRevenue'u güncelle totalRevenue = 0; for (var i = 0; i < sales.length; i++) { var salePrice = Math.round(sales[i].price * 1.1); totalRevenue += salePrice * sales[i].qty; } } // Para ekle gameState.money += totalRevenue; // Fan sayısını azalt: toplamda 100 fan/ürün, ancak en fazla mevcut fan kadar var fansAfter = gameState.fans; if (fansToLose > 0) { if (fansToLose > gameState.fans) fansToLose = gameState.fans; gameState.fans -= fansToLose; fansAfter = gameState.fans; } // Satış kaydını logla var logEntry = { day: gameState.currentDay, sales: sales, totalRevenue: totalRevenue, fansBefore: fansBefore, fansAfter: fansAfter }; gameState.fanStoreAutoSaleLog.push(logEntry); // Bildirim gösterme (popup kaldırıldı) updateUI(); } // --- Her gün başında fan store satışını tetikle --- // Günlük ilerleme kodunda çağrılacak, game.update içinde dayTimer >= 180 kısmında // --- Platform Menu UI --- var platformMenu = new Container(); platformMenu.visible = false; game.addChild(platformMenu); var platformTitle = new Text2('Platforms', { size: 60, fill: 0xFFFFFF }); platformTitle.anchor.set(0.5, 0.5); platformTitle.x = 1024; platformTitle.y = 200; platformMenu.addChild(platformTitle); var platformBackBtn = new Button(); platformBackBtn.setLabel('Back'); platformBackBtn.x = 1024; platformBackBtn.y = 2400; platformBackBtn.onClick = function () { platformMenu.visible = false; mainMenu.visible = true; }; platformMenu.addChild(platformBackBtn); // --- Drag-to-scroll for platformMenu --- var platformMenuDrag = { dragging: false, lastY: 0, startY: 0, startMenuY: 0, minY: 0, maxY: 0 }; // Calculate scroll bounds after platforms are rendered function updatePlatformMenuScrollBounds() { // Find min/max y for scrolling (platformMenu children) var minY = 0, maxY = 0; for (var i = 0; i < platformMenu.children.length; i++) { var child = platformMenu.children[i]; if (child !== platformTitle && child !== platformBackBtn) { if (minY === 0 || child.y < minY) minY = child.y; if (child.y > maxY) maxY = child.y; } } // Allow scrolling so that last row is visible, but not too far up platformMenuDrag.minY = Math.min(0, 800 - maxY); platformMenuDrag.maxY = 0; } platformMenu.interactive = true; platformMenu.down = function (x, y, obj) { platformMenuDrag.dragging = true; platformMenuDrag.lastY = y; platformMenuDrag.startY = y; platformMenuDrag.startMenuY = platformMenu.y || 0; updatePlatformMenuScrollBounds(); }; platformMenu.move = function (x, y, obj) { if (!platformMenuDrag.dragging) return; var dy = y - platformMenuDrag.lastY; var newY = (platformMenu.y || 0) + dy; // Clamp scroll if (newY < platformMenuDrag.minY) newY = platformMenuDrag.minY; if (newY > platformMenuDrag.maxY) newY = platformMenuDrag.maxY; platformMenu.y = newY; platformMenuDrag.lastY = y; }; platformMenu.up = function (x, y, obj) { platformMenuDrag.dragging = false; }; // --- Platform data (moved up to fix ReferenceError) --- // Each platform gets a salesBonus: 0.02 * (index+1) for 2% more per platform var platforms = [{ name: "PC", year: 1981, researched: true, owned: true, researchCost: 0, price: 0 }, { name: "Commodore 64", year: 1982, researched: false, owned: false, researchCost: 4000, price: 4000 }, { name: "NES", year: 1983, researched: false, owned: false, researchCost: 4000, price: 4000 }, { name: "Sega Master System", year: 1985, researched: false, owned: false, researchCost: 4000, price: 4000 }, { name: "Game Boy", year: 1989, researched: false, owned: false, researchCost: 4000, price: 4000 }, { name: "Super Nintendo", year: 1990, researched: false, owned: false, researchCost: 4000, price: 4000 }, { name: "Sega Genesis", year: 1990, researched: false, owned: false, researchCost: 4000, price: 4000 }, { name: "PlayStation", year: 1994, researched: true, owned: true, researchCost: 0, price: 0 }, { name: "Sega Saturn", year: 1994, researched: false, owned: false, researchCost: 4000, price: 4000 }, { name: "Nintendo 64", year: 1996, researched: false, owned: false, researchCost: 4000, price: 4000 }, { name: "Dreamcast", year: 1998, researched: false, owned: false, researchCost: 4000, price: 4000 }, { name: "PlayStation 2", year: 2000, researched: false, owned: false, researchCost: 4000, price: 8000 }, { name: "GameCube", year: 2001, researched: false, owned: false, researchCost: 8000, price: 8000 }, { name: "Xbox", year: 2001, researched: false, owned: false, researchCost: 8000, price: 8000 }, { name: "Game Boy Advance", year: 2001, researched: false, owned: false, researchCost: 8000, price: 8000 }, { name: "PlayStation Portable", year: 2004, researched: false, owned: false, researchCost: 8000, price: 8000 }, { name: "Nintendo DS", year: 2004, researched: false, owned: false, researchCost: 8000, price: 8000 }, { name: "Xbox 360", year: 2005, researched: false, owned: false, researchCost: 8000, price: 8000 }, { name: "Wii", year: 2006, researched: false, owned: false, researchCost: 8000, price: 8000 }, { name: "PlayStation 3", year: 2006, researched: false, owned: false, researchCost: 8000, price: 8000 }, { name: "PlayStation Vita", year: 2011, researched: false, owned: false, researchCost: 12000, price: 12000 }, { name: "Nintendo 3DS", year: 2011, researched: false, owned: false, researchCost: 12000, price: 12000 }, { name: "Wii U", year: 2012, researched: false, owned: false, researchCost: 12000, price: 12000 }, { name: "PlayStation 4", year: 2013, researched: false, owned: false, researchCost: 12000, price: 12000 }, { name: "Xbox One", year: 2013, researched: false, owned: false, researchCost: 12000, price: 12000 }, { name: "Nintendo Switch", year: 2017, researched: false, owned: false, researchCost: 16000, price: 16000 }, { name: "PlayStation 5", year: 2020, researched: false, owned: false, researchCost: 16000, price: 16000 }, { name: "Xbox Series X", year: 2020, researched: false, owned: false, researchCost: 16000, price: 16000 }, { name: "Steam Deck", year: 2022, researched: false, owned: false, researchCost: 16000, price: 16000 }, { name: "Mobile", year: 2007, researched: false, owned: false, researchCost: 8000, price: 8000 }, { name: "Ouya", year: 2013, researched: false, owned: false, researchCost: 4000, price: 4000 }]; // Add salesBonus to each platform (2% per platform, starting from 2%) for (var i = 0; i < platforms.length; i++) { platforms[i].salesBonus = 0.02 * (i + 1); } // Sort platforms by year ascending platforms.sort(function (a, b) { return a.year - b.year; }); // Helper for showing the platform menu function showPlatformMenu() { mainMenu.visible = false; platformMenu.visible = true; platformMenu.y = 0; // Reset scroll position on open // Remove old platform cards/buttons for (var i = platformMenu.children.length - 1; i >= 0; i--) { var child = platformMenu.children[i]; if (child !== platformTitle && child !== platformBackBtn) { child.destroy(); } } // Platform data // Use the global, sorted platforms array // Store platform state in gameState if not already if (!gameState.platforms) { gameState.platforms = {}; for (var i = 0; i < platforms.length; i++) { var plat = platforms[i]; gameState.platforms[plat.name] = { researched: plat.researched, owned: plat.owned }; } gameState.selectedPlatform = "PC"; } // Defensive: ensure all platforms in the list have an entry in gameState.platforms for (var i = 0; i < platforms.length; i++) { var plat = platforms[i]; if (!gameState.platforms[plat.name]) { gameState.platforms[plat.name] = { researched: plat.researched, owned: plat.owned }; } } // Show all platforms in a grid: 4 columns per row, 7 rows (ekrana sığacak şekilde 28 platform için) var yStart = 500; var xStart = 220; // leftmost card center (for 4 columns, more margin for 7 rows) var xSpacing = 420; // horizontal distance between columns (wider for 4 columns) var ySpacing = 220; // vertical spacing (keep as is) var cols = 4; for (var i = 0; i < platforms.length; i++) { var plat = platforms[i]; var container = new Container(); var col = i % cols; var row = Math.floor(i / cols); container.x = xStart + col * xSpacing; container.y = yStart + row * ySpacing; // Card background var bg = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 0.35 }); container.addChild(bg); // Platform name var nameText = new Text2(plat.name, { size: 35, fill: 0xFFFFFF }); nameText.anchor.set(0.5, 0.5); nameText.y = -30; container.addChild(nameText); // Year var yearText = new Text2('Year: ' + plat.year, { size: 28, fill: 0x4CAF50 }); yearText.anchor.set(0.5, 0.5); yearText.y = 10; container.addChild(yearText); // Sales bonus var bonusText = new Text2('Sales Bonus: +' + Math.round(plat.salesBonus * 100) + '%', { size: 24, fill: 0x2196F3 }); bonusText.anchor.set(0.5, 0.5); bonusText.y = 40; container.addChild(bonusText); // Research or Buy button var platState; if (gameState.platforms && _typeof2(gameState.platforms) === "object") { if (!gameState.platforms[plat.name]) { gameState.platforms[plat.name] = { researched: plat.researched, owned: plat.owned }; } platState = gameState.platforms[plat.name]; } else { platState = { researched: plat.researched, owned: plat.owned }; } if (!platState.owned) { var buyBtn = new Button(); buyBtn.setLabel('Buy ($' + plat.price + ')'); buyBtn.x = 0; buyBtn.y = 100; buyBtn.onClick = function (plat, platState) { return function () { if (gameState.money >= plat.price) { gameState.money -= plat.price; // Find the correct platState again (by name) to avoid closure bug if (gameState.platforms && gameState.platforms[plat.name]) { gameState.platforms[plat.name].owned = true; gameState.platforms[plat.name].researched = true; // Mark as researched on purchase } updateUI(); LK.getSound('success').play(); showPlatformMenu(); } }; }(plat, platState); container.addChild(buyBtn); } else { var ownedText = new Text2('Available', { size: 28, fill: 0xFFC107 }); ownedText.anchor.set(0.5, 0.5); ownedText.y = 100; container.addChild(ownedText); // No select button for owned platforms } platformMenu.addChild(container); } // Update scroll bounds after all cards are added updatePlatformMenuScrollBounds && updatePlatformMenuScrollBounds(); // Add info text at the bottom of the platformMenu if (platformMenu.platformInfoText) { platformMenu.platformInfoText.destroy(); } var platformInfoText = new Text2('To use a platform, purchase it from the platform page in the main menu.', { size: 32, fill: 0xFFC107 }); platformInfoText.anchor.set(0.5, 0.5); platformInfoText.x = 1024; platformInfoText.y = 2500; platformMenu.addChild(platformInfoText); platformMenu.platformInfoText = platformInfoText; } // (Game Engine menu and related UI removed) // --- Upgrade Button and Menu --- var upgradeBtn = new Button(); upgradeBtn.setLabel('Yükselt'); upgradeBtn.x = 1024; upgradeBtn.y = 1350; upgradeBtn.onClick = showUpgradeMenu; mainMenu.addChild(upgradeBtn); var upgradeMenu = new Container(); upgradeMenu.visible = false; game.addChild(upgradeMenu); var upgradeTitle = new Text2('Studio Upgrades', { size: 60, fill: 0xFFFFFF }); upgradeTitle.anchor.set(0.5, 0.5); upgradeTitle.x = 1024; upgradeTitle.y = 200; upgradeMenu.addChild(upgradeTitle); var studioLevelText = new Text2('', { size: 40, fill: 0xFFC107 }); studioLevelText.anchor.set(0.5, 0.5); studioLevelText.x = 1024; studioLevelText.y = 350; upgradeMenu.addChild(studioLevelText); var studioUpgradeCostText = new Text2('', { size: 35, fill: 0x4CAF50 }); studioUpgradeCostText.anchor.set(0.5, 0.5); studioUpgradeCostText.x = 1024; studioUpgradeCostText.y = 420; upgradeMenu.addChild(studioUpgradeCostText); var studioUpgradeBtn = new Button(); studioUpgradeBtn.setLabel('Stüdyo Seviyesini Yükselt'); studioUpgradeBtn.x = 1024; studioUpgradeBtn.y = 500; studioUpgradeBtn.onClick = function () { if (gameState.money >= gameState.studioUpgradeCost) { gameState.money -= gameState.studioUpgradeCost; gameState.studioLevel += 1; gameState.maxHireableDevelopers += 1; gameState.studioUpgradeCost = Math.floor(gameState.studioUpgradeCost * 1.7); updateUI(); showUpgradeMenu(); LK.getSound('success').play(); } }; upgradeMenu.addChild(studioUpgradeBtn); // --- Main Character Section --- var mainCharTitle = new Text2('Main Character', { size: 40, fill: 0xFFFFFF }); mainCharTitle.anchor.set(0.5, 0.5); mainCharTitle.x = 1024; mainCharTitle.y = 700; upgradeMenu.addChild(mainCharTitle); var mainCharLevelText = new Text2('', { size: 35, fill: 0xFFC107 }); mainCharLevelText.anchor.set(0.5, 0.5); mainCharLevelText.x = 1024; mainCharLevelText.y = 770; upgradeMenu.addChild(mainCharLevelText); var mainCharSkillText = new Text2('', { size: 30, fill: 0x2196F3 }); mainCharSkillText.anchor.set(0.5, 0.5); mainCharSkillText.x = 1024; mainCharSkillText.y = 820; upgradeMenu.addChild(mainCharSkillText); var mainCharUpgradeCostText = new Text2('', { size: 30, fill: 0x4CAF50 }); mainCharUpgradeCostText.anchor.set(0.5, 0.5); mainCharUpgradeCostText.x = 1024; mainCharUpgradeCostText.y = 870; upgradeMenu.addChild(mainCharUpgradeCostText); var mainCharUpgradeBtn = new Button(); mainCharUpgradeBtn.setLabel('Upgrade Main Character'); mainCharUpgradeBtn.x = 1024; mainCharUpgradeBtn.y = 950; mainCharUpgradeBtn.onClick = function () { if (gameState.money >= gameState.mainCharacter.upgradeCost) { gameState.money -= gameState.mainCharacter.upgradeCost; gameState.mainCharacter.level += 1; gameState.mainCharacter.skill += 1; // Each level, increase all feature points by 1 gameState.mainCharacter.featurePoints.Graphics += 1; gameState.mainCharacter.featurePoints.Sound += 1; gameState.mainCharacter.featurePoints.Gameplay += 1; gameState.mainCharacter.upgradeCost = Math.floor(gameState.mainCharacter.upgradeCost * 1.8); updateUI(); showUpgradeMenu(); LK.getSound('success').play(); } }; upgradeMenu.addChild(mainCharUpgradeBtn); var backFromUpgradeBtn = new Button(); backFromUpgradeBtn.setLabel('Back'); backFromUpgradeBtn.x = 1024; backFromUpgradeBtn.y = 2400; backFromUpgradeBtn.onClick = function () { upgradeMenu.visible = false; mainMenu.visible = true; }; upgradeMenu.addChild(backFromUpgradeBtn); function showUpgradeMenu() { mainMenu.visible = false; upgradeMenu.visible = true; studioLevelText.setText('Studio Level: ' + gameState.studioLevel); studioUpgradeCostText.setText('Upgrade Cost: $' + gameState.studioUpgradeCost); mainCharLevelText.setText('Main Character Level: ' + gameState.mainCharacter.level); mainCharSkillText.setText('Each Feature Point: ' + 'Graphics: ' + gameState.mainCharacter.featurePoints.Graphics + ', Sound: ' + gameState.mainCharacter.featurePoints.Sound + ', Gameplay: ' + gameState.mainCharacter.featurePoints.Gameplay); mainCharUpgradeCostText.setText('Upgrade Cost: $' + gameState.mainCharacter.upgradeCost); } // Research menu container var researchMenu = new Container(); researchMenu.visible = false; game.addChild(researchMenu); var researchTitle = new Text2('Research Lab', { size: 60, fill: 0xFFFFFF }); researchTitle.anchor.set(0.5, 0.5); researchTitle.x = 1024; researchTitle.y = 200; researchMenu.addChild(researchTitle); var researchBackBtn = new Button(); researchBackBtn.setLabel('Back'); researchBackBtn.x = 1024; researchBackBtn.y = 2400; researchBackBtn.onClick = function () { researchMenu.visible = false; mainMenu.visible = true; }; researchMenu.addChild(researchBackBtn); // Research category menu var researchCategoryMenu = new Container(); researchCategoryMenu.visible = false; game.addChild(researchCategoryMenu); var categoryTitle = new Text2('', { size: 60, fill: 0xFFFFFF }); categoryTitle.anchor.set(0.5, 0.5); categoryTitle.x = 1024; categoryTitle.y = 200; researchCategoryMenu.addChild(categoryTitle); var categoryBackBtn = new Button(); categoryBackBtn.setLabel('Back'); categoryBackBtn.x = 1024; categoryBackBtn.y = 2400; categoryBackBtn.onClick = function () { researchCategoryMenu.visible = false; researchMenu.visible = true; }; researchCategoryMenu.addChild(categoryBackBtn); // Name game menu container var nameGameMenu = new Container(); nameGameMenu.visible = false; game.addChild(nameGameMenu); var nameGameTitle = new Text2('Name Your Game', { size: 60, fill: 0xFFFFFF }); nameGameTitle.anchor.set(0.5, 0.5); nameGameTitle.x = 1024; nameGameTitle.y = 200; nameGameMenu.addChild(nameGameTitle); // --- Ava: Add a text input area for entering a custom game name --- var gameNameInput = new Text2('', { size: 50, fill: 0x4CAF50 }); gameNameInput.anchor.set(0.5, 0.5); gameNameInput.x = 1024; gameNameInput.y = 400; nameGameMenu.addChild(gameNameInput); // Add a background for the input area var inputBg = LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.2, scaleY: 1.1 }); inputBg.x = 1024; inputBg.y = 400; inputBg.alpha = 0.25; nameGameMenu.addChildAt(inputBg, nameGameMenu.children.indexOf(gameNameInput)); // --- Ava: Add a blinking cursor to indicate input --- var cursor = new Text2('|', { size: 50, fill: 0x4CAF50 }); cursor.anchor.set(0, 0.5); cursor.x = 0; cursor.y = 0; cursor.visible = false; nameGameMenu.addChild(cursor); // --- Ava: Show prompt below input area --- var inputPrompt = new Text2('Tap the input area to enter a game name', { size: 30, fill: 0xFFFFFF }); inputPrompt.anchor.set(0.5, 0.5); inputPrompt.x = 1024; inputPrompt.y = 500; nameGameMenu.addChild(inputPrompt); // --- Ava: Simple tap-to-edit for mobile/desktop --- // Track input state var isEditingGameName = false; var inputBlinkTimer = 0; // Helper to update the cursor position function updateGameNameCursor() { if (!isEditingGameName) { cursor.visible = false; return; } // Place cursor at end of text var textWidth = gameNameInput.width || 0; cursor.x = gameNameInput.x + textWidth / 2 + 8; cursor.y = gameNameInput.y; cursor.visible = true; } // Helper to start editing function startEditingGameName() { isEditingGameName = true; inputPrompt.setText('Type your game name (max 24 chars)'); updateGameNameCursor(); cursor.visible = true; inputBlinkTimer = 0; } // Helper to stop editing function stopEditingGameName() { isEditingGameName = false; inputPrompt.setText('Tap the input area to enter a game name'); cursor.visible = false; } // --- Ava: Input area tap handler --- inputBg.interactive = true; inputBg.down = function () { startEditingGameName(); LK.getSound('select').play(); }; // --- Ava: Simulate text input for mobile/desktop --- // Listen for text input events using LK's input event system (cross-platform, sandbox-safe) if (!game._avaGameNameInputListener) { game._avaGameNameInputListener = function (e) { if (!isEditingGameName) return; var key = e && (e.key || e.data || ''); if (key === 'Enter' || key === 'Done') { stopEditingGameName(); return; } if (key === 'Backspace') { if (currentGameName.length > 0) { currentGameName = currentGameName.slice(0, -1); gameNameInput.setText(currentGameName); updateGameNameCursor(); } return; } // Only allow visible ASCII, max 24 chars if (typeof key === 'string' && key.length === 1 && currentGameName.length < 24 && /^[\w\s\-!?.']$/.test(key)) { currentGameName += key; gameNameInput.setText(currentGameName); updateGameNameCursor(); } }; // Use LK's event system for input (works for both desktop and mobile) LK.on('input', game._avaGameNameInputListener); LK.on('keydown', game._avaGameNameInputListener); } // --- Ava: Blinking cursor animation in game.update --- var _oldGameUpdateForInput = game.update; game.update = function () { if (_oldGameUpdateForInput) _oldGameUpdateForInput(); if (isEditingGameName) { inputBlinkTimer++; if (inputBlinkTimer % 60 < 30) { cursor.visible = true; } else { cursor.visible = false; } updateGameNameCursor(); } else { cursor.visible = false; } }; var randomNameBtn = new Button(); randomNameBtn.setLabel('Random Name'); randomNameBtn.x = 1024; randomNameBtn.y = 700; randomNameBtn.onClick = generateRandomName; nameGameMenu.addChild(randomNameBtn); var confirmNameBtn = new Button(); confirmNameBtn.setLabel('Confirm Name'); confirmNameBtn.x = 1024; confirmNameBtn.y = 850; confirmNameBtn.onClick = confirmGameName; nameGameMenu.addChild(confirmNameBtn); var backFromNameBtn = new Button(); backFromNameBtn.setLabel('Back'); backFromNameBtn.x = 1024; backFromNameBtn.y = 1000; backFromNameBtn.onClick = function () { nameGameMenu.visible = false; mainMenu.visible = true; gameNameInput.setText(''); currentGameName = ''; }; nameGameMenu.addChild(backFromNameBtn); // Simple tap-to-edit name input var nameInputBg = LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 1 }); nameInputBg.x = 1024; nameInputBg.y = 400; nameInputBg.alpha = 0.3; nameGameMenu.addChild(nameInputBg); nameInputBg.interactive = true; nameInputBg.down = function () { // Simulate simple text input with preset options var names = ['Game Studio Pro', 'Developer Tycoon', 'Code Master', 'Pixel Dreams', 'Game Maker Plus']; var randomIndex = Math.floor(Math.random() * names.length); currentGameName = names[randomIndex]; gameNameInput.setText(currentGameName); LK.getSound('select').play(); }; // Move gameNameInput to be on top nameGameMenu.removeChild(gameNameInput); nameGameMenu.addChild(gameNameInput); // All games menu container var allGamesMenu = new Container(); allGamesMenu.visible = false; game.addChild(allGamesMenu); var allGamesTitle = new Text2('All Released Games', { size: 60, fill: 0xFFFFFF }); allGamesTitle.anchor.set(0.5, 0.5); allGamesTitle.x = 1024; allGamesTitle.y = 200; allGamesMenu.addChild(allGamesTitle); var noGamesText = new Text2('No games released yet', { size: 40, fill: 0xFFFFFF }); noGamesText.anchor.set(0.5, 0.5); noGamesText.x = 1024; noGamesText.y = 600; noGamesText.visible = false; allGamesMenu.addChild(noGamesText); var backFromAllGamesBtn = new Button(); backFromAllGamesBtn.setLabel('Back'); backFromAllGamesBtn.x = 1024; backFromAllGamesBtn.y = 2400; backFromAllGamesBtn.onClick = function () { allGamesMenu.visible = false; mainMenu.visible = true; }; allGamesMenu.addChild(backFromAllGamesBtn); // Game detail view container var gameDetailView = new Container(); gameDetailView.visible = false; game.addChild(gameDetailView); var detailBackBtn = new Button(); detailBackBtn.setLabel('Back to Games List'); detailBackBtn.x = 1024; detailBackBtn.y = 2400; detailBackBtn.onClick = function () { gameDetailView.visible = false; allGamesMenu.visible = true; }; gameDetailView.addChild(detailBackBtn); // Hire menu container var hireMenu = new Container(); hireMenu.visible = false; game.addChild(hireMenu); var hireTitle = new Text2('Hire Developer', { size: 60, fill: 0xFFFFFF }); hireTitle.anchor.set(0.5, 0.5); hireTitle.x = 1024; hireTitle.y = 200; hireMenu.addChild(hireTitle); var backFromHireBtn = new Button(); backFromHireBtn.setLabel('Back'); backFromHireBtn.x = 1024; backFromHireBtn.y = 2400; backFromHireBtn.onClick = function () { hireMenu.visible = false; mainMenu.visible = true; }; hireMenu.addChild(backFromHireBtn); // Project menu container var projectMenu = new Container(); projectMenu.visible = false; game.addChild(projectMenu); var projectTitle = new Text2('New Project', { size: 60, fill: 0xFFFFFF }); projectTitle.anchor.set(0.5, 0.5); projectTitle.x = 1024; projectTitle.y = 200; projectMenu.addChild(projectTitle); var selectFeaturesText = new Text2('Özellikleri Seç:', { size: 40, fill: 0xFFFFFF }); selectFeaturesText.anchor.set(0.5, 0.5); selectFeaturesText.x = 1024; selectFeaturesText.y = 300; projectMenu.addChild(selectFeaturesText); var startDevelopmentBtn = new Button(); startDevelopmentBtn.setLabel('Start Development'); startDevelopmentBtn.x = 1024; startDevelopmentBtn.y = 2200; startDevelopmentBtn.onClick = startDevelopment; projectMenu.addChild(startDevelopmentBtn); // Add Back button to New Project page var backFromProjectBtn = new Button(); backFromProjectBtn.setLabel('Back'); backFromProjectBtn.x = 1024; backFromProjectBtn.y = 2350; backFromProjectBtn.onClick = function () { projectMenu.visible = false; mainMenu.visible = true; selectedFeatures = []; featureCards.forEach(function (card) { card.setSelected(false); }); selectedFeatureByCategory.Graphics = null; selectedFeatureByCategory.Sound = null; selectedFeatureByCategory.Gameplay = null; projectMenu.selectedGenre = null; // Restore persistent buttons if missing (for next open) if (projectMenu.priceBtn && projectMenu.children.indexOf(projectMenu.priceBtn) === -1) { projectMenu.addChild(projectMenu.priceBtn); } if (projectMenu.platformBtn && projectMenu.children.indexOf(projectMenu.platformBtn) === -1) { projectMenu.addChild(projectMenu.platformBtn); } if (projectMenu.gameGenresResearchBtn && projectMenu.children.indexOf(projectMenu.gameGenresResearchBtn) === -1) { projectMenu.addChild(projectMenu.gameGenresResearchBtn); } }; projectMenu.addChild(backFromProjectBtn); // Feature category menu var featureCategoryMenu = new Container(); featureCategoryMenu.visible = false; game.addChild(featureCategoryMenu); var categoryMenuTitle = new Text2('', { size: 60, fill: 0xFFFFFF }); categoryMenuTitle.anchor.set(0.5, 0.5); categoryMenuTitle.x = 1024; categoryMenuTitle.y = 200; featureCategoryMenu.addChild(categoryMenuTitle); var selectedFeaturesText = new Text2('Selected: 0/5', { size: 40, fill: 0xFFFFFF }); selectedFeaturesText.anchor.set(0.5, 0.5); selectedFeaturesText.x = 1024; selectedFeaturesText.y = 300; featureCategoryMenu.addChild(selectedFeaturesText); var categoryBackBtn = new Button(); categoryBackBtn.setLabel('Back to Categories'); categoryBackBtn.x = 1024; categoryBackBtn.y = 2350; categoryBackBtn.onClick = function () { featureCategoryMenu.visible = false; projectMenu.visible = true; // Restore persistent buttons if missing if (projectMenu.priceBtn && projectMenu.children.indexOf(projectMenu.priceBtn) === -1) { projectMenu.addChild(projectMenu.priceBtn); } if (projectMenu.platformBtn && projectMenu.children.indexOf(projectMenu.platformBtn) === -1) { projectMenu.addChild(projectMenu.platformBtn); } if (projectMenu.gameGenresResearchBtn && projectMenu.children.indexOf(projectMenu.gameGenresResearchBtn) === -1) { projectMenu.addChild(projectMenu.gameGenresResearchBtn); } // Update total cost in project menu var totalCost = 0; selectedFeatures.forEach(function (f) { totalCost += f.cost; }); if (projectMenu.totalCostText) { projectMenu.totalCostText.setText('Total Cost: $' + totalCost); } // Update selectedFeatureByCategory to first selected per category, but do not remove extra selections ['Graphics', 'Sound', 'Gameplay'].forEach(function (cat) { var found = false; for (var i = 0; i < selectedFeatures.length; i++) { if (selectedFeatures[i].type === cat) { if (!found) { selectedFeatureByCategory[cat] = selectedFeatures[i]; found = true; } } } if (!found) selectedFeatureByCategory[cat] = null; }); }; featureCategoryMenu.addChild(categoryBackBtn); // --- Game Genres Research menu for projectMenu --- var projectGenresResearchMenu = new Container(); projectGenresResearchMenu.visible = false; game.addChild(projectGenresResearchMenu); var projectGenresResearchTitle = new Text2('Game Genres Research', { size: 60, fill: 0xFFFFFF }); projectGenresResearchTitle.anchor.set(0.5, 0.5); projectGenresResearchTitle.x = 1024; projectGenresResearchTitle.y = 200; projectGenresResearchMenu.addChild(projectGenresResearchTitle); var projectGenresResearchBackBtn = new Button(); projectGenresResearchBackBtn.setLabel('Back'); projectGenresResearchBackBtn.x = 1024; projectGenresResearchBackBtn.y = 2400; projectGenresResearchBackBtn.onClick = function () { projectGenresResearchMenu.visible = false; projectMenu.visible = true; // Restore persistent buttons if missing if (projectMenu.priceBtn && projectMenu.children.indexOf(projectMenu.priceBtn) === -1) { projectMenu.addChild(projectMenu.priceBtn); } if (projectMenu.platformBtn && projectMenu.children.indexOf(projectMenu.platformBtn) === -1) { projectMenu.addChild(projectMenu.platformBtn); } if (projectMenu.gameGenresResearchBtn && projectMenu.children.indexOf(projectMenu.gameGenresResearchBtn) === -1) { projectMenu.addChild(projectMenu.gameGenresResearchBtn); } }; projectGenresResearchMenu.addChild(projectGenresResearchBackBtn); function showProjectGenresResearchMenu() { projectMenu.visible = false; projectGenresResearchMenu.visible = true; // Remove old genre buttons for (var i = projectGenresResearchMenu.children.length - 1; i >= 0; i--) { var child = projectGenresResearchMenu.children[i]; if (child !== projectGenresResearchTitle && child !== projectGenresResearchBackBtn) { child.destroy(); } } // Show researched genres as selectable, and unresearched as buttons var yStart = 400; var researched = gameState.researchedFeatures.GameGenres; gameGenres.forEach(function (genre, idx) { if (!genre.requiresResearch || researched.indexOf(genre.name) !== -1) { // Make researched genres selectable (only one can be selected) var isSelected = projectMenu.selectedGenre && projectMenu.selectedGenre.name === genre.name; var genreBtn = new Button(); genreBtn.setLabel(genre.name + (isSelected ? ' (Selected)' : ' (Researched)')); genreBtn.x = 1024; genreBtn.y = yStart + idx * 120; if (isSelected) { // Highlight selected genre genreBtn.children[0].tint = 0xe94560; } genreBtn.onClick = function (g) { return function () { projectMenu.selectedGenre = g; // Sync selected genre to gameState for persistence gameState.selectedGenre = g; LK.getSound('select').play(); if (projectMenu.genreText) { projectMenu.genreText.setText('Selected Genre: ' + (projectMenu.selectedGenre ? projectMenu.selectedGenre.name : 'None')); } showProjectGenresResearchMenu(); }; }(genre); projectGenresResearchMenu.addChild(genreBtn); } else { var btn = new Button(); btn.setLabel(genre.name + ' ($' + genre.researchCost + ')'); btn.x = 1024; btn.y = yStart + idx * 120; btn.onClick = function (g) { return function () { if (gameState.money >= g.researchCost && !gameState.currentResearch) { gameState.money -= g.researchCost; gameState.currentResearch = { name: g.name, category: 'GameGenres', timeRemaining: 180 }; updateUI(); LK.getSound('select').play(); showProjectGenresResearchMenu(); } }; }(genre); projectGenresResearchMenu.addChild(btn); } }); } // Development screen var developmentScreen = new Container(); developmentScreen.visible = false; game.addChild(developmentScreen); var devTitle = new Text2('Developing Game', { size: 60, fill: 0xFFFFFF }); devTitle.anchor.set(0.5, 0.5); devTitle.x = 1024; devTitle.y = 200; developmentScreen.addChild(devTitle); var targetScoreText = new Text2('Target Score: 100', { size: 40, fill: 0xFFFFFF }); targetScoreText.anchor.set(0.5, 0.5); targetScoreText.x = 1024; targetScoreText.y = 400; developmentScreen.addChild(targetScoreText); var currentScoreText = new Text2('Current Score: 0', { size: 40, fill: 0x4CAF50 }); currentScoreText.anchor.set(0.5, 0.5); currentScoreText.x = 1024; currentScoreText.y = 500; developmentScreen.addChild(currentScoreText); var progressBarBg = LK.getAsset('progressBar', { anchorX: 0.5, anchorY: 0.5 }); progressBarBg.x = 1024; progressBarBg.y = 700; developmentScreen.addChild(progressBarBg); var progressBarFill = LK.getAsset('progressFill', { anchorX: 0, anchorY: 0.5 }); progressBarFill.x = 624; progressBarFill.y = 700; progressBarFill.scaleX = 0; developmentScreen.addChild(progressBarFill); var releaseBtn = new Button(); releaseBtn.setLabel('Release Game!'); releaseBtn.x = 1024; releaseBtn.y = 900; releaseBtn.visible = false; releaseBtn.onClick = releaseGame; developmentScreen.addChild(releaseBtn); // Market trends display var trendsContainer = new Container(); trendsContainer.x = 1024; trendsContainer.y = 1200; developmentScreen.addChild(trendsContainer); var trendsTitle = new Text2('Market Trends:', { size: 35, fill: 0xFF5722 }); trendsTitle.anchor.set(0.5, 0.5); trendsContainer.addChild(trendsTitle); // Arrays for UI elements var developerCards = []; var featureCards = []; var selectedFeatures = []; // Track selected feature per category for new project var selectedFeatureByCategory = { Graphics: null, Sound: null, Gameplay: null }; // Functions function updateUI() { moneyText.setText('Money: $' + gameState.money); developersText.setText('Developers: ' + gameState.developers.length); gamesText.setText('Games Released: ' + gameState.completedGames); // Sync gameState.currentDay with the dayText UI (top right Day ilerlemesi) var dayFromUI = 1; if (typeof dayText.text === "string") { var match = dayText.text.match(/Day:\s*(\d+)/); if (match && match[1]) { dayFromUI = parseInt(match[1], 10); if (!isNaN(dayFromUI)) { gameState.currentDay = dayFromUI; } } } dayText.setText('Day: ' + gameState.currentDay); // Fan UI fanText.setText('Fan: ' + (gameState.fans || 0)); // Calculate fan bonus: 100000 fans = %100 bonus, scale linearly up to that point, max 100% // Platform-specific: always use the selected platform's salesBonus var fanBonus = 0; var selectedPlatformObj = null; if (gameState.selectedPlatform) { for (var pi = 0; pi < platforms.length; pi++) { if (platforms[pi].name === gameState.selectedPlatform) { selectedPlatformObj = platforms[pi]; break; } } } if (gameState.fans && gameState.fans > 0) { fanBonus = gameState.fans / 100000 * 100; // 100000 fan = %100 bonus if (fanBonus > 100) fanBonus = 100; } var displayFanBonus = 0; if (selectedPlatformObj && typeof selectedPlatformObj.salesBonus === "number") { displayFanBonus = Math.round(fanBonus * selectedPlatformObj.salesBonus); // platforma göre çarp } else { displayFanBonus = Math.round(fanBonus); } fanBonusText.setText('Satış Bonusu: %' + displayFanBonus); } function showResearchMenu() { mainMenu.visible = false; researchMenu.visible = true; // Clear existing buttons for (var i = researchMenu.children.length - 1; i >= 0; i--) { if (researchMenu.children[i] instanceof Button && researchMenu.children[i] !== researchBackBtn) { researchMenu.children[i].destroy(); } } // Create category buttons var categories = ['Graphics', 'Sound', 'Gameplay', 'GameGenres']; categories.forEach(function (category, index) { var btn = new Button(); var displayName = category === 'GameGenres' ? 'Game Genres' : category; btn.setLabel(displayName + ' Research'); btn.x = 1024; btn.y = 400 + index * 150; btn.onClick = function () { showResearchCategory(category); }; researchMenu.addChild(btn); }); } function showResearchCategory(category) { researchMenu.visible = false; researchCategoryMenu.visible = true; var displayName = category === 'GameGenres' ? 'Game Genres' : category; categoryTitle.setText(displayName + ' Research'); // Clear existing items for (var i = researchCategoryMenu.children.length - 1; i >= 0; i--) { var child = researchCategoryMenu.children[i]; if (child !== categoryTitle && child !== categoryBackBtn) { child.destroy(); } } // Get researchable items for this category var items = []; if (category === 'GameGenres') { items = gameGenres.filter(function (genre) { return genre.requiresResearch && gameState.researchedFeatures.GameGenres.indexOf(genre.name) === -1; }); } else { items = featurePool.filter(function (feature) { return feature.type === category && feature.requiresResearch && gameState.researchedFeatures[category].indexOf(feature.name) === -1; }); } // Display research items items.forEach(function (item, index) { var container = new Container(); container.x = 1024; container.y = 400 + index * 120; var bg = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 0.4 }); container.addChild(bg); var nameText = new Text2(item.name, { size: 30, fill: 0xFFFFFF }); nameText.anchor.set(0.5, 0.5); nameText.y = -20; container.addChild(nameText); var cost = category === 'GameGenres' ? item.researchCost : item.cost * 3; var costText = new Text2('Research Cost: $' + cost, { size: 25, fill: 0x4CAF50 }); costText.anchor.set(0.5, 0.5); costText.y = 20; container.addChild(costText); container.interactive = true; container.down = function () { if (gameState.money >= cost && !gameState.currentResearch) { gameState.money -= cost; gameState.currentResearch = { name: item.name, category: category, timeRemaining: 180 // 3 seconds }; updateUI(); LK.getSound('select').play(); showResearchCategory(category); } }; researchCategoryMenu.addChild(container); }); // Add research option to increase selection limit for this category (if not already maxed) if (category === 'Graphics' || category === 'Sound' || category === 'Gameplay') { var maxLimit = 5; var currentLimit = 1; if (gameState.featureSelectionLimit && typeof gameState.featureSelectionLimit[category] === "number") { currentLimit = gameState.featureSelectionLimit[category]; } if (currentLimit < maxLimit) { var y = 400 + items.length * 120 + 60; var limitContainer = new Container(); limitContainer.x = 1024; limitContainer.y = y; var bg2 = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 0.4 }); limitContainer.addChild(bg2); var limitText = new Text2('Seçim Limiti Artır: ' + category + ' (' + currentLimit + ' → ' + (currentLimit + 1) + ')', { size: 30, fill: 0xFFC107 }); limitText.anchor.set(0.5, 0.5); limitText.y = -20; limitContainer.addChild(limitText); var limitCost = 8000 * currentLimit; var limitCostText = new Text2('Araştırma Maliyeti: $' + limitCost, { size: 25, fill: 0x4CAF50 }); limitCostText.anchor.set(0.5, 0.5); limitCostText.y = 20; limitContainer.addChild(limitCostText); limitContainer.interactive = true; limitContainer.down = function () { if (gameState.money >= limitCost && !gameState.currentResearch) { gameState.money -= limitCost; gameState.currentResearch = { name: 'IncreaseLimit_' + category, category: 'IncreaseLimit_' + category, timeRemaining: 180 }; updateUI(); LK.getSound('select').play(); showResearchCategory(category); } }; researchCategoryMenu.addChild(limitContainer); } } // Add a Back button specifically for Game Genres, Gameplay, Graphics, and Sound Research page if (category === 'GameGenres' || category === 'Gameplay' || category === 'Graphics' || category === 'Sound') { // Remove previous genre/gameplay/graphics/sound back button if any if (researchCategoryMenu.genreBackBtn) { researchCategoryMenu.removeChild(researchCategoryMenu.genreBackBtn); researchCategoryMenu.genreBackBtn.destroy(); researchCategoryMenu.genreBackBtn = null; } var genreBackBtn = new Button(); genreBackBtn.setLabel('Back'); genreBackBtn.x = 1024; genreBackBtn.y = 2400; genreBackBtn.onClick = function () { researchCategoryMenu.visible = false; researchMenu.visible = true; updateGlobalBackBtn && updateGlobalBackBtn(); }; researchCategoryMenu.addChild(genreBackBtn); researchCategoryMenu.genreBackBtn = genreBackBtn; } // Show current research if any if (gameState.currentResearch) { var researchInfo = new Text2('Currently researching: ' + gameState.currentResearch.name, { size: 35, fill: 0xFFC107 }); researchInfo.anchor.set(0.5, 0.5); researchInfo.x = 1024; researchInfo.y = 300; researchCategoryMenu.addChild(researchInfo); } } function showNameGameMenu() { mainMenu.visible = false; nameGameMenu.visible = true; currentGameName = ''; gameNameInput.setText(''); } function generateRandomName() { var prefixes = ['Super', 'Mega', 'Ultra', 'Epic', 'Legendary', 'Amazing', 'Incredible', 'Fantastic']; var genres = ['Adventure', 'Quest', 'Battle', 'World', 'Kingdom', 'Legend', 'Saga', 'Chronicles']; var suffixes = ['2000', 'X', 'Plus', 'HD', 'Remastered', 'Ultimate', 'Deluxe', 'Pro']; var name = prefixes[Math.floor(Math.random() * prefixes.length)] + ' ' + genres[Math.floor(Math.random() * genres.length)] + ' ' + suffixes[Math.floor(Math.random() * suffixes.length)]; currentGameName = name; gameNameInput.setText(name); LK.getSound('select').play(); } function confirmGameName() { if (currentGameName && currentGameName.length > 0) { // Store the game name for later use nameGameMenu.visible = false; // If projectMenu is hidden, show it again (for project flow) if (!mainMenu.visible && projectMenu) { projectMenu.visible = true; } else { mainMenu.visible = true; } LK.getSound('success').play(); // Update game name display gameNameDisplay.setText('Next Game: ' + currentGameName); // Show confirmation message var confirmText = new Text2('Next game will be: ' + currentGameName, { size: 30, fill: 0x4CAF50 }); confirmText.anchor.set(0.5, 0.5); confirmText.x = 1024; confirmText.y = 1050; confirmText.alpha = 0; mainMenu.addChild(confirmText); tween(confirmText, { alpha: 1 }, { duration: 500, onFinish: function onFinish() { LK.setTimeout(function () { tween(confirmText, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { confirmText.destroy(); } }); }, 2000); } }); } } function showAllGamesMenu() { mainMenu.visible = false; allGamesMenu.visible = true; // Clear existing game cards var cardsToRemove = []; allGamesMenu.children.forEach(function (child) { if (child instanceof GameHistoryCard) { cardsToRemove.push(child); } }); cardsToRemove.forEach(function (card) { card.destroy(); }); // Show all games (both active and completed) var allGames = gameState.releasedGames.concat(gameState.gameHistory); if (allGames.length === 0) { noGamesText.visible = true; } else { noGamesText.visible = false; allGames.forEach(function (game, index) { var card = new GameHistoryCard(); card.setGameData(game); card.x = 1024; card.y = 400 + index * 150; card.onClick = showGameDetail; allGamesMenu.addChild(card); }); } } function showGameDetail(gameData) { allGamesMenu.visible = false; gameDetailView.visible = true; // Clear previous content for (var i = gameDetailView.children.length - 1; i >= 0; i--) { if (gameDetailView.children[i] !== detailBackBtn) { gameDetailView.children[i].destroy(); } } // Game title var titleText = new Text2(gameData.name, { size: 60, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 200; gameDetailView.addChild(titleText); // Release info var releaseText = new Text2('Released on Day ' + gameData.releaseDay, { size: 35, fill: 0x2196F3 }); releaseText.anchor.set(0.5, 0.5); releaseText.x = 1024; releaseText.y = 300; gameDetailView.addChild(releaseText); // Sales info var salesStatus = gameData.currentDailySales > 0 ? 'Active' : 'Ended'; var salesText = new Text2('Total Sales: ' + gameData.totalSales + ' copies (' + salesStatus + ')', { size: 35, fill: 0x4CAF50 }); salesText.anchor.set(0.5, 0.5); salesText.x = 1024; salesText.y = 380; gameDetailView.addChild(salesText); // Show total earned money (use actual price and revenue formula) var pricePerCopy = typeof gameData.price === "number" ? gameData.price : 1; var totalMoneyEarned = Math.floor((gameData.totalSales || 0) * pricePerCopy); var moneyText = new Text2('Total Money Earned: $' + totalMoneyEarned, { size: 32, fill: 0xFFC107 }); moneyText.anchor.set(0.5, 0.5); moneyText.x = 1024; moneyText.y = 420; gameDetailView.addChild(moneyText); // Score info var scoreText = new Text2('Score: ' + Math.floor(gameData.score) + ' / ' + gameData.targetScore, { size: 35, fill: 0xFFC107 }); scoreText.anchor.set(0.5, 0.5); scoreText.x = 1024; scoreText.y = 460; gameDetailView.addChild(scoreText); // Show price per copy if (typeof gameData.price === "number") { var priceText = new Text2('Oyun Fiyatı: $' + gameData.price, { size: 32, fill: 0xFFC107 }); priceText.anchor.set(0.5, 0.5); priceText.x = 1024; priceText.y = 500; gameDetailView.addChild(priceText); } // Genre info if (gameData.genre) { var genreText = new Text2('Genre: ' + gameData.genre.name, { size: 35, fill: 0x9C27B0 }); genreText.anchor.set(0.5, 0.5); genreText.x = 1024; genreText.y = 540; gameDetailView.addChild(genreText); } // Features title var featuresTitle = new Text2('Features Used:', { size: 40, fill: 0xFFFFFF }); featuresTitle.anchor.set(0.5, 0.5); featuresTitle.x = 1024; featuresTitle.y = 600; gameDetailView.addChild(featuresTitle); // Display features gameData.features.forEach(function (feature, index) { var featureText = new Text2('• ' + feature.name + ' (' + feature.type + ')', { size: 30, fill: 0x2196F3 }); featureText.anchor.set(0.5, 0.5); featureText.x = 1024; featureText.y = 680 + index * 40; gameDetailView.addChild(featureText); }); // Developers title var devsTitle = new Text2('Developed by:', { size: 40, fill: 0xFFFFFF }); devsTitle.anchor.set(0.5, 0.5); devsTitle.x = 1024; devsTitle.y = 1000; gameDetailView.addChild(devsTitle); // Display developers if stored if (gameData.developers) { gameData.developers.forEach(function (dev, index) { var devText = new Text2('• ' + dev.name + ' (' + dev.specialty + ', Skill: ' + dev.skill + ')', { size: 30, fill: 0xFFC107 }); devText.anchor.set(0.5, 0.5); devText.x = 1024; devText.y = 1080 + index * 40; gameDetailView.addChild(devText); }); } // Show reviews if present if (gameData.reviews && gameData.reviews.length > 0) { var reviewsTitle = new Text2('Reviews:', { size: 40, fill: 0xFFFFFF }); reviewsTitle.anchor.set(0.5, 0.5); reviewsTitle.x = 1024; reviewsTitle.y = 1400; gameDetailView.addChild(reviewsTitle); // Show average review score var avgScore = 0; for (var i = 0; i < gameData.reviews.length; i++) { avgScore += gameData.reviews[i].score; } avgScore = Math.round(avgScore / gameData.reviews.length); var avgScoreText = new Text2('Average Score: ' + avgScore + '/100', { size: 35, fill: avgScore >= 80 ? 0x4CAF50 : avgScore >= 60 ? 0xFFC107 : 0xE94560 }); avgScoreText.anchor.set(0.5, 0.5); avgScoreText.x = 1024; avgScoreText.y = 1460; gameDetailView.addChild(avgScoreText); // Show up to 10 reviews gameData.reviews.forEach(function (review, idx) { var reviewText = new Text2(review.company + ": " + review.score + "/100 - " + review.text, { size: 28, fill: 0xFFFFFF }); reviewText.anchor.set(0.5, 0.5); reviewText.x = 1024; reviewText.y = 1540 + idx * 60; gameDetailView.addChild(reviewText); }); } } function showHireMenu() { mainMenu.visible = false; hireMenu.visible = true; // Clear existing cards developerCards.forEach(function (card) { card.destroy(); }); developerCards = []; // Show available developers info var infoText = new Text2('Available Developers: ' + gameState.maxHireableDevelopers, { size: 35, fill: 0xFFC107 }); infoText.anchor.set(0.5, 0.5); infoText.x = 1024; infoText.y = 350; hireMenu.addChild(infoText); // Show main character as always hired var mainCharCard = new DeveloperCard(); mainCharCard.setDeveloper({ name: gameState.mainCharacter.name, specialty: "All", skill: gameState.mainCharacter.skill, cost: 0 }); mainCharCard.x = 1024; mainCharCard.y = 600; mainCharCard.developerData = { name: gameState.mainCharacter.name, specialty: "All", skill: gameState.mainCharacter.skill, cost: 0 }; mainCharCard.down = function () {}; hireMenu.addChild(mainCharCard); developerCards.push(mainCharCard); // Create developer cards as a grid, restrict hiring to studio level var availableDevelopers = developerPool.filter(function (dev) { return !gameState.developers.some(function (hired) { return hired.name === dev.name; }); }); // Only allow hiring up to maxHireableDevelopers (studioLevel+1, including main character) var canHireCount = gameState.maxHireableDevelopers - gameState.developers.length; if (canHireCount < 0) canHireCount = 0; // Arrange developer cards in a grid (3 per row) var cardsPerRow = 3; var cardSpacingX = 400; var cardSpacingY = 500; var startX = 1024 - cardSpacingX; var startY = 1000; availableDevelopers.forEach(function (dev, index) { var card = new DeveloperCard(); card.setDeveloper(dev); var col = index % cardsPerRow; var row = Math.floor(index / cardsPerRow); card.x = startX + col * cardSpacingX; card.y = startY + row * cardSpacingY; // If we can't hire more, gray out the card and disable click if (index >= canHireCount) { card.alpha = 0.4; card.down = function () { // Optionally show a message or play a sound LK.getSound('select').play(); }; // Show a message overlay var lockText = new Text2('Stüdyo seviyesini yükseltmelisin', { size: 28, fill: 0xE94560 }); lockText.anchor.set(0.5, 0.5); lockText.y = 160; card.addChild(lockText); } else { card.onClick = function (developer) { if (gameState.money >= developer.cost) { gameState.money -= developer.cost; gameState.developers.push({ name: developer.name, specialty: developer.specialty, skill: developer.skill, cost: developer.cost, assignedFeature: null // Only 1 feature can be assigned }); updateUI(); LK.getSound('hire').play(); showHireMenu(); // Refresh menu } }; } hireMenu.addChild(card); developerCards.push(card); }); } function showFeatureCategory(category) { projectMenu.visible = false; featureCategoryMenu.visible = true; categoryMenuTitle.setText(category + ' Features'); selectedFeaturesText.setText('Selected: ' + selectedFeatures.length); // Clear existing feature cards for (var i = featureCategoryMenu.children.length - 1; i >= 0; i--) { var child = featureCategoryMenu.children[i]; if (child instanceof FeatureCard) { child.destroy(); } } // Get available features for this category var availableFeatures = featurePool.filter(function (feature) { return feature.type === category && (!feature.requiresResearch || gameState.researchedFeatures[feature.type].indexOf(feature.name) !== -1); }); // Create feature cards availableFeatures.forEach(function (feature, index) { var card = new FeatureCard(); card.setFeature(feature); card.x = 400 + index % 4 * 250; card.y = 500 + Math.floor(index / 4) * 350; // Set selected state if already selected var isSelected = selectedFeatures.some(function (f) { return f.name === feature.name; }); card.setSelected(isSelected); // Highlight trending features if (gameState.marketTrends.indexOf(feature.type) !== -1) { var trendIcon = LK.getAsset('trendIcon', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3 }); trendIcon.x = 100; trendIcon.y = -100; card.addChild(trendIcon); } card.onClick = function (clickedCard) { var cat = category; // Determine max selection for this category var maxPerCategory = 1; if (gameState.featureSelectionLimit && typeof gameState.featureSelectionLimit[cat] === "number") { maxPerCategory = gameState.featureSelectionLimit[cat]; } // Count how many are already selected in this category var selectedInCategory = selectedFeatures.filter(function (f) { return f.type === cat; }).length; // If already selected, deselect if (clickedCard.selected) { clickedCard.setSelected(false); selectedFeatures = selectedFeatures.filter(function (f) { return f !== clickedCard.featureData; }); // If this was the only selected in category, clear selectedFeatureByCategory if (selectedFeatureByCategory[cat] && selectedFeatureByCategory[cat].name === clickedCard.featureData.name) { selectedFeatureByCategory[cat] = null; } } else { // Only allow up to maxPerCategory selections per category if (selectedInCategory >= maxPerCategory) { // Show notification var notification = new Container(); game.addChild(notification); var bg = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 0.6 }); bg.tint = 0xE94560; notification.addChild(bg); var text = new Text2('Bu kategoriden en fazla ' + maxPerCategory + ' özellik seçebilirsin!', { size: 35, fill: 0xFFFFFF }); text.anchor.set(0.5, 0.5); notification.addChild(text); notification.x = 1024; notification.y = 600; notification.alpha = 0; tween(notification, { alpha: 1 }, { duration: 500, onFinish: function onFinish() { LK.setTimeout(function () { tween(notification, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { notification.destroy(); } }); }, 2000); } }); return; } clickedCard.setSelected(true); selectedFeatures.push(clickedCard.featureData); selectedFeatureByCategory[cat] = clickedCard.featureData; LK.getSound('select').play(); } // Update selected count selectedFeaturesText.setText('Selected: ' + selectedFeatures.length); }; featureCategoryMenu.addChild(card); }); } function showProjectMenu() { // Allow project creation if there is at least one developer OR the main character (always present) if (gameState.developers.length === 0 && !gameState.mainCharacter) { return; } mainMenu.visible = false; projectMenu.visible = true; selectedFeatures = []; // Reset per-category selection selectedFeatureByCategory.Graphics = null; selectedFeatureByCategory.Sound = null; selectedFeatureByCategory.Gameplay = null; // Clear existing cards featureCards.forEach(function (card) { card.destroy(); }); featureCards = []; // Clear any existing category buttons, but do NOT destroy persistent buttons (priceBtn, platformBtn, gameGenresResearchBtn, startDevelopmentBtn, backFromProjectBtn) for (var i = projectMenu.children.length - 1; i >= 0; i--) { var child = projectMenu.children[i]; // Only destroy category feature buttons (those not persistent) if (child instanceof Button && child !== startDevelopmentBtn && child !== backFromProjectBtn && child !== projectMenu.priceBtn && child !== projectMenu.platformBtn && child !== projectMenu.gameGenresResearchBtn) { child.destroy(); } } // Restore selected genre from gameState if available if (gameState.selectedGenre) { projectMenu.selectedGenre = gameState.selectedGenre; } else { projectMenu.selectedGenre = null; gameState.selectedGenre = null; } // Update selected genre text if (projectMenu.genreText) { projectMenu.genreText.setText('Selected Genre: ' + (projectMenu.selectedGenre ? projectMenu.selectedGenre.name : 'None')); } // Persist marketTrends for the duration of a project (until game is released) // Only generate new trends if there are no trends yet (i.e., at the start of a new project, not just on menu open) if (!gameState.marketTrends || !Array.isArray(gameState.marketTrends) || gameState.marketTrends.length === 0) { gameState.marketTrends = []; var trendTypes = ['Graphics', 'Sound', 'Gameplay']; var availableGenres = gameGenres.filter(function (genre) { return !genre.requiresResearch || gameState.researchedFeatures.GameGenres.indexOf(genre.name) !== -1; }); // Only allow market trends from researched genres var researchedGenres = gameGenres.filter(function (genre) { return !genre.requiresResearch || gameState.researchedFeatures.GameGenres.indexOf(genre.name) !== -1; }); var trend = trendTypes[Math.floor(Math.random() * trendTypes.length)]; gameState.marketTrends.push(trend); // Only pick genre trends from researched genres if (researchedGenres.length > 0) { var genreTrend = researchedGenres[Math.floor(Math.random() * researchedGenres.length)]; gameState.marketTrends.push(genreTrend.name + ' games'); } } // --- Ava: Destroy old Market Trends and Total Cost text to prevent duplicates --- if (projectMenu.trendsText) { projectMenu.trendsText.destroy(); projectMenu.trendsText = null; } if (projectMenu.totalCostText) { projectMenu.totalCostText.destroy(); projectMenu.totalCostText = null; } // Display trends at top var trendsText = new Text2('Market Trends: ' + gameState.marketTrends.join(' & ') + ' are hot!', { size: 35, fill: 0xFF5722 }); trendsText.anchor.set(0.5, 0.5); trendsText.x = 1024; trendsText.y = 400; projectMenu.addChild(trendsText); projectMenu.trendsText = trendsText; // --- Ava: Show sales bonus summary for selected features --- if (projectMenu.featureBonusText) { projectMenu.featureBonusText.destroy(); } var featureBonusSummary = ''; (function () { // Calculate bonuses for selected features var bonusParts = []; // Platform bonus var selectedPlatformName = gameState.selectedPlatform || "PC"; var selectedPlatformObj = null; for (var i = 0; i < platforms.length; i++) { if (platforms[i].name === selectedPlatformName) { selectedPlatformObj = platforms[i]; break; } } if (selectedPlatformObj && selectedPlatformObj.salesBonus) { bonusParts.push('Platform: +' + Math.round(selectedPlatformObj.salesBonus * 100) + '% satış'); } // Genre bonus if (projectMenu.selectedGenre) { var genreObj = null; for (var i = 0; i < gameGenres.length; i++) { if (gameGenres[i].name === projectMenu.selectedGenre.name) { genreObj = gameGenres[i]; break; } } if (genreObj && genreObj.baseMultiplier && genreObj.baseMultiplier > 1) { bonusParts.push('Tür: +' + Math.round((genreObj.baseMultiplier - 1) * 100) + '% satış'); } } // Feature trend bonus var trendTypes = []; if (gameState.marketTrends && Array.isArray(gameState.marketTrends)) { for (var i = 0; i < gameState.marketTrends.length; i++) { if (gameState.marketTrends[i] === "Graphics" || gameState.marketTrends[i] === "Sound" || gameState.marketTrends[i] === "Gameplay") { trendTypes.push(gameState.marketTrends[i]); } } } var trendBonus = 0; if (trendTypes.length > 0 && selectedFeatures && selectedFeatures.length > 0) { for (var i = 0; i < selectedFeatures.length; i++) { if (trendTypes.indexOf(selectedFeatures[i].type) !== -1) { trendBonus = 50; break; } } if (trendBonus > 0) { bonusParts.push('Trend Özellik: +50% satış'); } } // Genre trend bonus if (projectMenu.selectedGenre && gameState.marketTrends && Array.isArray(gameState.marketTrends)) { for (var i = 0; i < gameState.marketTrends.length; i++) { if (typeof gameState.marketTrends[i] === "string" && gameState.marketTrends[i].indexOf(projectMenu.selectedGenre.name) !== -1) { bonusParts.push('Trend Tür: +30% satış'); break; } } } // Fan bonus (platform-specific) var fanBonus = 0; var selectedPlatformObj = null; if (gameState.selectedPlatform) { for (var pi = 0; pi < platforms.length; pi++) { if (platforms[pi].name === gameState.selectedPlatform) { selectedPlatformObj = platforms[pi]; break; } } } if (gameState.fans && gameState.fans > 0) { fanBonus = gameState.fans / 100000 * 100; if (fanBonus > 100) fanBonus = 100; if (fanBonus > 0) { if (selectedPlatformObj && typeof selectedPlatformObj.salesBonus === "number") { var platformFanBonus = Math.round(fanBonus * selectedPlatformObj.salesBonus); bonusParts.push('Fan: +' + platformFanBonus + '% satış (platforma göre)'); } else { bonusParts.push('Fan: +' + Math.round(fanBonus) + '% satış'); } } } // Compose summary if (bonusParts.length > 0) { featureBonusSummary = 'Satış Bonusları: ' + bonusParts.join(', '); } else { featureBonusSummary = 'Satış bonusu yok.'; } })(); // Satış Bonusları: yazısını 2 satır olacak şekilde ayarla ve hizala var featureBonusLines = []; if (featureBonusSummary.length > 40) { // Satış bonusu metni uzunsa, virgülden bölerek iki satıra ayır var parts = featureBonusSummary.split(':'); if (parts.length > 1) { var bonuses = parts[1].split(','); var mid = Math.ceil(bonuses.length / 2); var firstLine = (parts[0] + ':' + bonuses.slice(0, mid).join(',')).trim(); var secondLine = bonuses.slice(mid).join(',').trim(); featureBonusLines = [firstLine, secondLine]; } else { featureBonusLines = [featureBonusSummary, '']; } } else { featureBonusLines = [featureBonusSummary, '']; } var featureBonusText = new Text2(featureBonusLines[0] + (featureBonusLines[1] ? '\n' + featureBonusLines[1] : ''), { size: 32, fill: 0x4CAF50, align: "center" }); featureBonusText.anchor.set(0.5, 0.5); featureBonusText.x = 1024; featureBonusText.y = 360; projectMenu.addChild(featureBonusText); projectMenu.featureBonusText = featureBonusText; // --- Satış Bonusları kutusunun altındaki butonları aşağı kaydır (hizalama) --- var buttonY = 650 + 240; // Move all buttons 2 rows (240px) down if (featureBonusText.height > 40) { buttonY += 30; // 2 satır ise biraz daha aşağı kaydır } var buttonSpacing = 120; // Feature category buttons var categories = ['Graphics', 'Sound', 'Gameplay']; categories.forEach(function (category, index) { var categoryBtn = new Button(); categoryBtn.setLabel(category + ' Features'); categoryBtn.x = 1024; categoryBtn.y = buttonY; categoryBtn.onClick = function () { showFeatureCategory(category); }; projectMenu.addChild(categoryBtn); buttonY += buttonSpacing; }); // Oyun Fiyatı button (move to next row) if (projectMenu.priceBtn) { // If not already present, re-add to projectMenu if (projectMenu.children.indexOf(projectMenu.priceBtn) === -1) { projectMenu.addChild(projectMenu.priceBtn); } projectMenu.priceBtn.y = buttonY; buttonY += buttonSpacing; } // Game Genres Research button (move to next row) if (!projectMenu.gameGenresResearchBtn) { var gameGenresResearchBtn = new Button(); gameGenresResearchBtn.setLabel('Game Genres Research'); gameGenresResearchBtn.x = 1024; gameGenresResearchBtn.y = buttonY; gameGenresResearchBtn.onClick = function () { showProjectGenresResearchMenu(); }; projectMenu.addChild(gameGenresResearchBtn); projectMenu.gameGenresResearchBtn = gameGenresResearchBtn; } else { // If not already present, re-add to projectMenu if (projectMenu.children.indexOf(projectMenu.gameGenresResearchBtn) === -1) { projectMenu.addChild(projectMenu.gameGenresResearchBtn); } projectMenu.gameGenresResearchBtn.y = buttonY; } // Move Platform Seç button to be below the last button if (projectMenu.platformBtn) { projectMenu.platformBtn.y = buttonY + buttonSpacing; buttonY = projectMenu.platformBtn.y; } // Add Oyun Adı Seç button below Platform Seç if (!projectMenu.nameGameBtn) { var nameGameBtn = new Button(); nameGameBtn.setLabel('Oyun Adı Seç'); nameGameBtn.x = 1024; nameGameBtn.y = buttonY + buttonSpacing; nameGameBtn.onClick = function () { mainMenu.visible = false; projectMenu.visible = false; nameGameMenu.visible = true; currentGameName = ''; gameNameInput.setText(''); }; projectMenu.addChild(nameGameBtn); projectMenu.nameGameBtn = nameGameBtn; } else { // If not already present, re-add to projectMenu if (projectMenu.children.indexOf(projectMenu.nameGameBtn) === -1) { projectMenu.addChild(projectMenu.nameGameBtn); } projectMenu.nameGameBtn.y = buttonY + buttonSpacing; } buttonY = projectMenu.nameGameBtn.y; // Add info text at the bottom of the platform selection page in Start Project if (projectMenu.platformInfoText) { projectMenu.platformInfoText.destroy(); } var projectPlatformInfoText = new Text2('To use a platform, purchase it from the platform page in the main menu.', { size: 32, fill: 0xFFC107 }); projectPlatformInfoText.anchor.set(0.5, 0.5); projectPlatformInfoText.x = 1024; projectPlatformInfoText.y = 2500; projectMenu.addChild(projectPlatformInfoText); projectMenu.platformInfoText = projectPlatformInfoText; // Add info note about research and increasing selectable features if (projectMenu.featureResearchInfoText) { projectMenu.featureResearchInfoText.destroy(); } var featureResearchInfoText = new Text2("You can research new features and increase the number of selectable features from the Research section in the main menu.", { size: 30, fill: 0x4CAF50, align: "center" }); featureResearchInfoText.anchor.set(0.5, 1); featureResearchInfoText.x = 1024; featureResearchInfoText.y = 2450; projectMenu.addChild(featureResearchInfoText); projectMenu.featureResearchInfoText = featureResearchInfoText; // --- Genre selection UI removed: genre can only be selected from Game Genres Research page --- // Show selected genre (if any) if (!projectMenu.selectedGenre) { projectMenu.selectedGenre = null; gameState.selectedGenre = null; } if (projectMenu.genreText) { projectMenu.genreText.destroy(); projectMenu.genreText = null; } var genreText = new Text2('Selected Genre: ' + (projectMenu.selectedGenre ? projectMenu.selectedGenre.name : 'None'), { size: 35, fill: 0x9C27B0 }); genreText.anchor.set(0.5, 0.5); genreText.x = 1024; genreText.y = 480; projectMenu.addChild(genreText); projectMenu.genreText = genreText; // Total cost display var totalCostText = new Text2('Total Cost: $0', { size: 35, fill: 0x4CAF50 }); totalCostText.anchor.set(0.5, 0.5); totalCostText.x = 1024; totalCostText.y = 530; projectMenu.addChild(totalCostText); // Store totalCostText reference for later updates projectMenu.totalCostText = totalCostText; // --- Oyun Fiyatı (Game Price) UI --- if (!projectMenu.priceText) { // Default price per copy if (typeof projectMenu.selectedPrice !== "number") { projectMenu.selectedPrice = 1; // $1 per copy default } var priceText = new Text2('Oyun Fiyatı: $' + projectMenu.selectedPrice, { size: 35, fill: 0xFFC107 }); priceText.anchor.set(0.5, 0.5); priceText.x = 1024; priceText.y = 580; projectMenu.addChild(priceText); projectMenu.priceText = priceText; // Price select button var priceBtn = new Button(); priceBtn.setLabel('Oyun Fiyatı Seç'); priceBtn.x = 1024; priceBtn.y = 630; priceBtn.onClick = function () { // Show a simple price selection popup if (projectMenu.pricePopup) { projectMenu.pricePopup.destroy(); projectMenu.pricePopup = null; } var popup = new Container(); popup.x = 1024; popup.y = 900; var bg = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 1 }); bg.tint = 0x16213e; popup.addChild(bg); var title = new Text2('Oyun Fiyatı Seçin', { size: 40, fill: 0xFFC107 }); title.anchor.set(0.5, 0.5); title.y = -120; popup.addChild(title); // Price options var prices = [0.5, 1, 2, 3, 5, 10]; prices.forEach(function (p, idx) { var btn = new Button(); btn.setLabel('$' + p); btn.x = 0; btn.y = -40 + idx * 70; btn.onClick = function () { projectMenu.selectedPrice = p; projectMenu.priceText.setText('Oyun Fiyatı: $' + p); if (projectMenu.pricePopup) { projectMenu.pricePopup.destroy(); projectMenu.pricePopup = null; } LK.getSound('select').play(); }; popup.addChild(btn); }); // Close button var closeBtn = new Button(); closeBtn.setLabel('Kapat'); closeBtn.x = 0; closeBtn.y = 400; closeBtn.onClick = function () { if (projectMenu.pricePopup) { projectMenu.pricePopup.destroy(); projectMenu.pricePopup = null; } }; popup.addChild(closeBtn); projectMenu.pricePopup = popup; game.addChild(popup); }; projectMenu.addChild(priceBtn); projectMenu.priceBtn = priceBtn; } // If a game name was set, show it in projectMenu if (currentGameName && currentGameName.length > 0) { if (projectMenu.gameNameText) { projectMenu.gameNameText.destroy(); } var gameNameText = new Text2('Oyun Adı: ' + currentGameName, { size: 35, fill: 0xFFC107 }); gameNameText.anchor.set(0.5, 0.5); gameNameText.x = 1024; gameNameText.y = 800; projectMenu.addChild(gameNameText); projectMenu.gameNameText = gameNameText; } else if (projectMenu.gameNameText) { projectMenu.gameNameText.destroy(); projectMenu.gameNameText = null; } if (projectMenu.engineText) { projectMenu.engineText.destroy(); } // (Game Engine UI removed) // --- Platform Selection Button and Text --- if (projectMenu.platformText) { projectMenu.platformText.destroy(); projectMenu.platformText = null; } var selectedPlatformName = gameState.selectedPlatform || "PC"; var platformText = new Text2('Platform: ' + selectedPlatformName, { size: 35, fill: 0xFFC107 }); platformText.anchor.set(0.5, 0.5); platformText.x = 1024; platformText.y = 750; projectMenu.addChild(platformText); projectMenu.platformText = platformText; if (!projectMenu.platformBtn) { var platformBtn = new Button(); platformBtn.setLabel('Platform Seç'); platformBtn.x = 1024; // We'll set the y position after all other buttons are placed platformBtn.onClick = function () { // Show the platformMenu as a page, but in selection mode mainMenu.visible = false; projectMenu.visible = false; platformMenu.visible = true; platformMenu.y = 0; // Mark that we are in platform selection mode for projectMenu platformMenu._selectForProjectMenu = true; // Remove old platform cards/buttons except title and back for (var i = platformMenu.children.length - 1; i >= 0; i--) { var child = platformMenu.children[i]; if (child !== platformTitle && child !== platformBackBtn) { child.destroy(); } } // Show only owned platforms as selectable, others as locked var yStart = 500; var xStart = 320; var xSpacing = 350; var ySpacing = 220; var cols = 4; for (var i = 0; i < platforms.length; i++) { var plat = platforms[i]; var container = new Container(); var col = i % cols; var row = Math.floor(i / cols); container.x = xStart + col * xSpacing; container.y = yStart + row * ySpacing; var bg = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 0.35 }); container.addChild(bg); var nameText = new Text2(plat.name, { size: 35, fill: 0xFFFFFF }); nameText.anchor.set(0.5, 0.5); nameText.y = -30; container.addChild(nameText); var yearText = new Text2('Çıkış: ' + plat.year, { size: 28, fill: 0x4CAF50 }); yearText.anchor.set(0.5, 0.5); yearText.y = 10; container.addChild(yearText); var bonusText = new Text2('Satış Bonus: +' + Math.round(plat.salesBonus * 100) + '%', { size: 24, fill: 0x2196F3 }); bonusText.anchor.set(0.5, 0.5); bonusText.y = 40; container.addChild(bonusText); var platState = gameState.platforms && gameState.platforms[plat.name] ? gameState.platforms[plat.name] : { researched: plat.researched, owned: plat.owned }; if (platState && platState.owned) { // Selectable for projectMenu var selectBtn = new Button(); selectBtn.setLabel(gameState.selectedPlatform === plat.name ? 'Seçili' : 'Seç'); selectBtn.x = 0; selectBtn.y = 100; if (gameState.selectedPlatform === plat.name) { selectBtn.children[0].tint = 0xe94560; } selectBtn.onClick = function (platName) { return function () { gameState.selectedPlatform = platName; if (projectMenu.platformText) { projectMenu.platformText.setText('Platform: ' + platName); } LK.getSound('select').play(); // Return to projectMenu after selection platformMenu.visible = false; projectMenu.visible = true; platformMenu._selectForProjectMenu = false; // Restore persistent buttons if missing if (projectMenu.priceBtn && projectMenu.children.indexOf(projectMenu.priceBtn) === -1) { projectMenu.addChild(projectMenu.priceBtn); } if (projectMenu.platformBtn && projectMenu.children.indexOf(projectMenu.platformBtn) === -1) { projectMenu.addChild(projectMenu.platformBtn); } if (projectMenu.gameGenresResearchBtn && projectMenu.children.indexOf(projectMenu.gameGenresResearchBtn) === -1) { projectMenu.addChild(projectMenu.gameGenresResearchBtn); } // --- Ava: Update sales bonus summary instantly when platform is changed --- if (projectMenu.featureBonusText) { projectMenu.featureBonusText.destroy(); } var featureBonusSummary = ''; (function () { var bonusParts = []; // Platform bonus var selectedPlatformName = gameState.selectedPlatform || "PC"; var selectedPlatformObj = null; for (var i = 0; i < platforms.length; i++) { if (platforms[i].name === selectedPlatformName) { selectedPlatformObj = platforms[i]; break; } } if (selectedPlatformObj && selectedPlatformObj.salesBonus) { bonusParts.push('Platform: +' + Math.round(selectedPlatformObj.salesBonus * 100) + '% satış'); } // Genre bonus if (projectMenu.selectedGenre) { var genreObj = null; for (var i = 0; i < gameGenres.length; i++) { if (gameGenres[i].name === projectMenu.selectedGenre.name) { genreObj = gameGenres[i]; break; } } if (genreObj && genreObj.baseMultiplier && genreObj.baseMultiplier > 1) { bonusParts.push('Tür: +' + Math.round((genreObj.baseMultiplier - 1) * 100) + '% satış'); } } // Feature trend bonus var trendTypes = []; if (gameState.marketTrends && Array.isArray(gameState.marketTrends)) { for (var i = 0; i < gameState.marketTrends.length; i++) { if (gameState.marketTrends[i] === "Graphics" || gameState.marketTrends[i] === "Sound" || gameState.marketTrends[i] === "Gameplay") { trendTypes.push(gameState.marketTrends[i]); } } } var trendBonus = 0; if (trendTypes.length > 0 && selectedFeatures && selectedFeatures.length > 0) { for (var i = 0; i < selectedFeatures.length; i++) { if (trendTypes.indexOf(selectedFeatures[i].type) !== -1) { trendBonus = 50; break; } } if (trendBonus > 0) { bonusParts.push('Trend Özellik: +50% satış'); } } // Genre trend bonus if (projectMenu.selectedGenre && gameState.marketTrends && Array.isArray(gameState.marketTrends)) { for (var i = 0; i < gameState.marketTrends.length; i++) { if (typeof gameState.marketTrends[i] === "string" && gameState.marketTrends[i].indexOf(projectMenu.selectedGenre.name) !== -1) { bonusParts.push('Trend Tür: +30% satış'); break; } } } // Fan bonus (platform-specific) var fanBonus = 0; var selectedPlatformObj = null; if (gameState.selectedPlatform) { for (var pi = 0; pi < platforms.length; pi++) { if (platforms[pi].name === gameState.selectedPlatform) { selectedPlatformObj = platforms[pi]; break; } } } if (gameState.fans && gameState.fans > 0) { fanBonus = Math.floor(gameState.fans / 10) / 10; if (fanBonus > 100) fanBonus = 100; if (fanBonus > 0) { if (selectedPlatformObj && typeof selectedPlatformObj.salesBonus === "number") { var platformFanBonus = Math.round(fanBonus * selectedPlatformObj.salesBonus); bonusParts.push('Fan: +' + platformFanBonus + '% satış (platforma göre)'); } else { bonusParts.push('Fan: +' + fanBonus + '% satış'); } } } if (bonusParts.length > 0) { featureBonusSummary = 'Satış Bonusları: ' + bonusParts.join(', '); } else { featureBonusSummary = 'Satış bonusu yok.'; } })(); var featureBonusText = new Text2(featureBonusSummary, { size: 32, fill: 0x4CAF50 }); featureBonusText.anchor.set(0.5, 0.5); featureBonusText.x = 1024; featureBonusText.y = 360; projectMenu.addChild(featureBonusText); projectMenu.featureBonusText = featureBonusText; }; }(plat.name); container.addChild(selectBtn); } else { // Not owned, show as locked var lockedText = new Text2('Satın Al: $' + plat.price, { size: 28, fill: 0x888888 }); lockedText.anchor.set(0.5, 0.5); lockedText.y = 100; container.addChild(lockedText); } platformMenu.addChild(container); } updatePlatformMenuScrollBounds && updatePlatformMenuScrollBounds(); // Patch platformBackBtn to return to projectMenu if in selection mode platformBackBtn.onClick = function () { platformMenu.visible = false; if (platformMenu._selectForProjectMenu) { projectMenu.visible = true; platformMenu._selectForProjectMenu = false; } else { mainMenu.visible = true; } }; updateGlobalBackBtn && updateGlobalBackBtn(); }; projectMenu.addChild(platformBtn); projectMenu.platformBtn = platformBtn; } else { // We'll set the y position after all other buttons are placed } // Create all project menu buttons in a single vertical column, one per row var buttonY = 650 + 240; // Move all buttons 2 rows (240px) down var buttonSpacing = 120; // Feature category buttons var categories = ['Graphics', 'Sound', 'Gameplay']; categories.forEach(function (category, index) { var categoryBtn = new Button(); categoryBtn.setLabel(category + ' Features'); categoryBtn.x = 1024; categoryBtn.y = buttonY; categoryBtn.onClick = function () { showFeatureCategory(category); }; projectMenu.addChild(categoryBtn); buttonY += buttonSpacing; }); // Oyun Fiyatı button (move to next row) if (projectMenu.priceBtn) { // If not already present, re-add to projectMenu if (projectMenu.children.indexOf(projectMenu.priceBtn) === -1) { projectMenu.addChild(projectMenu.priceBtn); } projectMenu.priceBtn.y = buttonY; buttonY += buttonSpacing; } // Game Genres Research button (move to next row) if (!projectMenu.gameGenresResearchBtn) { var gameGenresResearchBtn = new Button(); gameGenresResearchBtn.setLabel('Game Genres Research'); gameGenresResearchBtn.x = 1024; gameGenresResearchBtn.y = buttonY; gameGenresResearchBtn.onClick = function () { showProjectGenresResearchMenu(); }; projectMenu.addChild(gameGenresResearchBtn); projectMenu.gameGenresResearchBtn = gameGenresResearchBtn; } else { // If not already present, re-add to projectMenu if (projectMenu.children.indexOf(projectMenu.gameGenresResearchBtn) === -1) { projectMenu.addChild(projectMenu.gameGenresResearchBtn); } projectMenu.gameGenresResearchBtn.y = buttonY; } // Move Platform Seç button to be below the last button if (projectMenu.platformBtn) { projectMenu.platformBtn.y = buttonY + buttonSpacing; buttonY = projectMenu.platformBtn.y; } // Add Oyun Adı Seç button below Platform Seç if (!projectMenu.nameGameBtn) { var nameGameBtn = new Button(); nameGameBtn.setLabel('Oyun Adı Seç'); nameGameBtn.x = 1024; nameGameBtn.y = buttonY + buttonSpacing; nameGameBtn.onClick = function () { mainMenu.visible = false; projectMenu.visible = false; nameGameMenu.visible = true; currentGameName = ''; gameNameInput.setText(''); }; projectMenu.addChild(nameGameBtn); projectMenu.nameGameBtn = nameGameBtn; } else { // If not already present, re-add to projectMenu if (projectMenu.children.indexOf(projectMenu.nameGameBtn) === -1) { projectMenu.addChild(projectMenu.nameGameBtn); } projectMenu.nameGameBtn.y = buttonY + buttonSpacing; } buttonY = projectMenu.nameGameBtn.y; // Add info text at the bottom of the platform selection page in Start Project if (projectMenu.platformInfoText) { projectMenu.platformInfoText.destroy(); } var projectPlatformInfoText = new Text2('To use a platform, purchase it from the platform page in the main menu.', { size: 32, fill: 0xFFC107 }); projectPlatformInfoText.anchor.set(0.5, 0.5); projectPlatformInfoText.x = 1024; projectPlatformInfoText.y = 2500; projectMenu.addChild(projectPlatformInfoText); projectMenu.platformInfoText = projectPlatformInfoText; } function startDevelopment() { // Must have at least one feature per category if (!selectedFeatureByCategory.Graphics || !selectedFeatureByCategory.Sound || !selectedFeatureByCategory.Gameplay) { // Show a notification or feedback var notification = new Container(); game.addChild(notification); var bg = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 0.6 }); bg.tint = 0xE94560; notification.addChild(bg); var text = new Text2('Her kategoriden en az 1 özellik seçmelisin!', { size: 35, fill: 0xFFFFFF }); text.anchor.set(0.5, 0.5); notification.addChild(text); notification.x = 1024; notification.y = 600; notification.alpha = 0; tween(notification, { alpha: 1 }, { duration: 500, onFinish: function onFinish() { LK.setTimeout(function () { tween(notification, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { notification.destroy(); } }); }, 2000); } }); return; } // --- Require a researched genre to be selected before starting development --- var researchedGenres = gameState.researchedFeatures.GameGenres; // Fix: Check if selectedGenre is not null and its name is in researchedGenres or does not require research if (!projectMenu.selectedGenre || // Find the genre object in gameGenres function () { var genreObj = null; for (var i = 0; i < gameGenres.length; i++) { if (gameGenres[i].name === projectMenu.selectedGenre.name) { genreObj = gameGenres[i]; break; } } // If genreObj is not found, treat as not researched if (!genreObj) return true; // If genre does not require research, allow if (!genreObj.requiresResearch) return false; // If genre requires research, check if it's in researchedGenres return researchedGenres.indexOf(genreObj.name) === -1; }()) { // Show a notification or feedback var notification = new Container(); game.addChild(notification); var bg = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 0.6 }); bg.tint = 0xE94560; notification.addChild(bg); var text = new Text2('Please select a researched genre before starting!', { size: 35, fill: 0xFFFFFF }); text.anchor.set(0.5, 0.5); notification.addChild(text); notification.x = 1024; notification.y = 600; notification.alpha = 0; tween(notification, { alpha: 1 }, { duration: 500, onFinish: function onFinish() { LK.setTimeout(function () { tween(notification, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { notification.destroy(); } }); }, 2000); } }); return; } // Calculate total cost var totalCost = 0; selectedFeatures.forEach(function (feature) { totalCost += feature.cost; }); // Check if player can afford if (gameState.money < totalCost) { return; } // Deduct costs gameState.money -= totalCost; updateUI(); projectMenu.visible = false; developmentScreen.visible = true; // (Game Engine UI removed from development screen) // Display trends for (var i = trendsContainer.children.length - 1; i > 0; i--) { trendsContainer.children[i].destroy(); } gameState.marketTrends.forEach(function (trend, index) { var trendText = new Text2(trend + ' is trending!', { size: 30, fill: 0xFF5722 }); trendText.anchor.set(0.5, 0.5); trendText.y = 40 + index * 35; trendsContainer.addChild(trendText); }); // Calculate target score var baseTarget = 100; targetScoreText.setText('Target Score: ' + baseTarget); // Use selected genre from projectMenu var selectedGenre = projectMenu.selectedGenre || null; // Start project gameState.currentProject = { features: selectedFeatures, targetScore: baseTarget, currentScore: 0, developmentSpeed: 0, genre: selectedGenre, price: typeof projectMenu.selectedPrice === "number" ? projectMenu.selectedPrice : 1 }; // Assign features to developers (main character is always included and can contribute to all features) var assignedDevelopers = []; var assignedFeatures = []; // Always include main character as a developer var allDevs = [{ name: gameState.mainCharacter.name, specialty: "All", skill: gameState.mainCharacter.skill, featurePoints: Object.assign({}, gameState.mainCharacter.featurePoints) }].concat(gameState.developers.map(function (dev) { return { name: dev.name, specialty: dev.specialty, skill: dev.skill, assignedFeature: null }; })); // Assign features: each feature is assigned to a developer, but main character always contributes to all var devAssignments = []; selectedFeatures.forEach(function (feature, idx) { // Assign to next available developer (skip main character for assignment, but main character always contributes) var devIdx = (idx + 1) % allDevs.length; if (devIdx === 0 && allDevs.length > 1) devIdx = 1; // avoid assigning all to main character devAssignments.push({ dev: allDevs[devIdx], feature: feature }); allDevs[devIdx].assignedFeature = feature.name; }); // Calculate development speed var totalSpeed = 0; // Main character always contributes to all features selectedFeatures.forEach(function (feature) { var fp = gameState.mainCharacter.featurePoints[feature.type] || 1; totalSpeed += (gameState.mainCharacter.skill + fp) * 0.5; }); // Other developers contribute to their assigned feature devAssignments.forEach(function (assignment) { if (assignment.dev.name !== gameState.mainCharacter.name) { totalSpeed += assignment.dev.skill * 0.5; } }); gameState.currentProject.developmentSpeed = totalSpeed; gameState.currentProject.devAssignments = devAssignments; LK.getSound('develop').play(); releaseBtn.visible = false; progressBarFill.scaleX = 0; } function releaseGame() { var project = gameState.currentProject; // Calculate final score with bonuses var finalScore = project.currentScore; // (Game Engine quality bonus removed) // Trend bonus var trendMultiplier = 1; project.features.forEach(function (feature) { if (gameState.marketTrends.indexOf(feature.type) !== -1) { finalScore *= 1.5; trendMultiplier += 0.3; } }); // Genre bonus if (project.genre) { finalScore *= project.genre.baseMultiplier; if (gameState.marketTrends.some(function (trend) { return trend.indexOf(project.genre.name) !== -1; })) { finalScore *= 1.3; trendMultiplier += 0.4; } } // Calculate initial sales potential var baseSalesMultiplier = 20; if (finalScore >= project.targetScore) { baseSalesMultiplier = 40; } // Price effect on sales: higher price = lower sales, lower price = higher sales var priceSalesMultiplier = 1; if (project.price) { if (project.price > 1) { priceSalesMultiplier = 1 / (0.7 + (project.price - 1) * 0.5); // $2 = ~0.67x, $5 = ~0.29x if (priceSalesMultiplier < 0.15) priceSalesMultiplier = 0.15; } else if (project.price < 1) { priceSalesMultiplier = 1 + (1 - project.price) * 0.7; // $0.5 = 1.35x } } // --- Ava: Reduce sales multiplier if features and review score are low and price is high --- var featureQuality = 0; for (var i = 0; i < project.features.length; i++) { featureQuality += project.features[i].basePoints || 0; } var avgFeatureQuality = featureQuality / project.features.length; var reviewScoreForPenalty = 0; var scoreRatio = finalScore / project.targetScore; if (scoreRatio >= 1.5) reviewScoreForPenalty = 95;else if (scoreRatio >= 1.2) reviewScoreForPenalty = 85;else if (scoreRatio >= 1.0) reviewScoreForPenalty = 75;else if (scoreRatio >= 0.8) reviewScoreForPenalty = 60;else reviewScoreForPenalty = 40; // If price is high, but features and review are low, apply a penalty to sales var pricePenaltyMultiplier = 1; if (project.price > 2) { // If both feature quality and review are low, penalize more if (avgFeatureQuality < 5 && reviewScoreForPenalty < 70) { pricePenaltyMultiplier = 0.5 - Math.min((project.price - 2) * 0.1, 0.3); // up to -30% more penalty } else if (avgFeatureQuality < 6 || reviewScoreForPenalty < 75) { pricePenaltyMultiplier = 0.7 - Math.min((project.price - 2) * 0.05, 0.2); // up to -20% more penalty } // Never less than 0.2x if (pricePenaltyMultiplier < 0.2) pricePenaltyMultiplier = 0.2; } // Find selected platform and apply its salesBonus var selectedPlatform = null; for (var i = 0; i < platforms.length; i++) { if (platforms[i].name === gameState.selectedPlatform) { selectedPlatform = platforms[i]; break; } } var platformSalesBonus = selectedPlatform && selectedPlatform.salesBonus ? 1 + selectedPlatform.salesBonus : 1; var initialDailySales = Math.floor(finalScore / project.targetScore * baseSalesMultiplier * trendMultiplier * priceSalesMultiplier * pricePenaltyMultiplier * platformSalesBonus); var gameName = currentGameName && currentGameName.length > 0 ? currentGameName : 'Game #' + (gameState.completedGames + 1); // --- Review and score system --- // Ava: Reviewers are now much more pessimistic! // Only 5 reviewers, each with unique focus: feature, price, platform, etc. var reviewCompanies = ["IGN", "GameSpot", "Polygon", "Eurogamer", "Kotaku"]; var reviews = []; var reviewScore = 0; var genreTrend = gameState.marketTrends.find(function (trend) { return project.genre && trend.indexOf(project.genre.name) !== -1; }); var featureTrend = gameState.marketTrends.indexOf(project.features[0].type) !== -1 || gameState.marketTrends.indexOf(project.features[1].type) !== -1 || gameState.marketTrends.indexOf(project.features[2].type) !== -1 || project.features.length > 3 && gameState.marketTrends.indexOf(project.features[3].type) !== -1 || project.features.length > 4 && gameState.marketTrends.indexOf(project.features[4].type) !== -1; // Calculate review score (0-100) -- pessimistic version var scoreRatio = finalScore / project.targetScore; if (scoreRatio >= 1.5) reviewScore = 80 + Math.floor(Math.random() * 6); // was 95+ else if (scoreRatio >= 1.2) reviewScore = 65 + Math.floor(Math.random() * 10); // was 85+ else if (scoreRatio >= 1.0) reviewScore = 55 + Math.floor(Math.random() * 10); // was 75+ else if (scoreRatio >= 0.8) reviewScore = 40 + Math.floor(Math.random() * 10); // was 60+ else reviewScore = 20 + Math.floor(Math.random() * 20); // was 40+ // If genre matches trend, boost score (less than before) if (genreTrend) reviewScore += 2; if (featureTrend) reviewScore += 2; // --- Price effect on review score --- if (project.price) { // $1 is neutral, higher price reduces review, lower price increases (harsher penalty) if (project.price > 1) { reviewScore -= Math.floor((project.price - 1) * 7); // -7 puan/extra dollar } else if (project.price < 1) { reviewScore += Math.floor((1 - project.price) * 3); // +3 puan/discounted dollar } } if (reviewScore > 100) reviewScore = 100; if (reviewScore < 0) reviewScore = 0; // --- 5 unique reviews: each with a different focus --- // 1. Feature focus var feature = project.features[0]; var featureScore = reviewScore + Math.floor(Math.random() * 5 - 2); if (featureScore > 100) featureScore = 100; if (featureScore < 0) featureScore = 0; var featureText = ""; if (featureScore >= 80) { featureText = "The standout feature is '" + feature.name + "'. It really elevates the experience."; } else if (featureScore >= 60) { featureText = "'" + feature.name + "' is decent, but could use more polish."; } else { featureText = "The '" + feature.name + "' feature is a major letdown."; } reviews.push({ company: reviewCompanies[0], score: featureScore, text: featureText }); // 2. Price focus var priceScore = reviewScore + Math.floor(Math.random() * 5 - 2); if (priceScore > 100) priceScore = 100; if (priceScore < 0) priceScore = 0; var priceText = ""; if (project.price > 3) { priceText = "At $" + project.price + ", the game feels overpriced for what it offers."; } else if (project.price < 1) { priceText = "Great value for money! The low price makes this game more appealing."; } else { priceText = "The price is fair for the content provided."; } reviews.push({ company: reviewCompanies[1], score: priceScore, text: priceText }); // 3. Platform compatibility focus var platformName = gameState.selectedPlatform || "PC"; var platformScore = reviewScore + Math.floor(Math.random() * 5 - 2); if (platformScore > 100) platformScore = 100; if (platformScore < 0) platformScore = 0; var platformText = ""; if (platformName === "PC") { platformText = "Runs smoothly on PC, but we'd love to see more platform options."; } else { platformText = "Great to see support for " + platformName + "."; } reviews.push({ company: reviewCompanies[2], score: platformScore, text: platformText }); // 4. Trend/genre focus var trendScore = reviewScore + Math.floor(Math.random() * 5 - 2); if (trendScore > 100) trendScore = 100; if (trendScore < 0) trendScore = 0; var trendText = ""; if (genreTrend) { trendText = "Smart move to follow the '" + project.genre.name + "' trend. It pays off!"; } else if (featureTrend) { trendText = "The game tries to follow current feature trends, but doesn't quite hit the mark."; } else { trendText = "Misses out on current market trends, making it feel a bit outdated."; } reviews.push({ company: reviewCompanies[3], score: trendScore, text: trendText }); // 5. General polish/compatibility focus var polishScore = reviewScore + Math.floor(Math.random() * 5 - 2); if (polishScore > 100) polishScore = 100; if (polishScore < 0) polishScore = 0; var polishText = ""; if (polishScore >= 80) { polishText = "A well-polished game with few bugs. Impressive work!"; } else if (polishScore >= 60) { polishText = "Some rough edges, but overall a stable experience."; } else { polishText = "Technical issues and lack of polish hold this game back."; } reviews.push({ company: reviewCompanies[4], score: polishScore, text: polishText }); var releasedGame = { name: gameName, releaseDay: gameState.currentDay, score: finalScore, targetScore: project.targetScore, initialDailySales: initialDailySales, currentDailySales: initialDailySales, totalSales: 0, features: project.features, trendBonus: trendMultiplier, price: project.price || 1, // Add main character as a developer in the released game developers: [{ name: gameState.mainCharacter.name, specialty: "All", skill: gameState.mainCharacter.skill }].concat(gameState.developers.slice()), genre: project.genre, reviews: reviews, reviewScore: reviewScore }; // Reset game name after use currentGameName = ''; gameNameDisplay.setText(''); // Clear marketTrends so new trends are generated for the next project gameState.marketTrends = []; gameState.releasedGames.push(releasedGame); // Success check if (finalScore >= project.targetScore) { gameState.money += Math.floor(finalScore * 0.00025); // 95% less gameState.completedGames++; LK.getSound('success').play(); LK.setScore(gameState.completedGames); if (gameState.completedGames >= 10) { LK.showYouWin(); } } else { gameState.money += Math.floor(finalScore * 0.0000625); // 95% less } LK.getSound('release').play(); // Reset gameState.currentProject = null; developmentScreen.visible = false; mainMenu.visible = true; updateUI(); updateSalesLog(); // --- Rakiplerden biri de oyun çıkarsın (oyuncu oyun çıkardığında) --- if (gameState.rivals && gameState.rivals.length > 0) { // Rastgele bir rakip seç var rivalIndex = Math.floor(Math.random() * gameState.rivals.length); var rival = gameState.rivals[rivalIndex]; // Oyun ismi ve gelirini üret var gameNames = ["Super", "Mega", "Ultra", "Epic", "Legend", "Pixel", "Quest", "Saga", "Chronicles", "World"]; var gameSuffix = ["Adventure", "Battle", "Story", "Kingdom", "Odyssey", "Arena", "Tycoon", "Empire", "Run", "Hero"]; var name = gameNames[Math.floor(Math.random() * gameNames.length)] + " " + gameSuffix[Math.floor(Math.random() * gameSuffix.length)]; // Son 3 oyunun ortalamasını bul var last3 = rival.games && rival.games.length > 0 ? rival.games.slice(-3) : []; var avg = 40000; if (last3.length > 0) { var sum = 0; for (var i = 0; i < last3.length; i++) sum += last3[i].revenue; avg = Math.floor(sum / last3.length); } // Rakip oyun kazancı, rakip şirket değerinin %1-%20 aralığında kâr veya %1-%20 aralığında zarar olacak şekilde ayarlandı var percent = (Math.random() < 0.5 ? -1 : 1) * (0.01 + Math.random() * 0.19); // -0.01 ile -0.20 veya +0.01 ile +0.20 arası var baseValue = rival.value || 100000; var revenue = Math.floor(baseValue * Math.abs(percent)); var originalRevenue = revenue; if (percent < 0) { revenue = -revenue; } var originalLoss = 0; if (revenue < 0) { originalLoss = -revenue; revenue = 0; } // Oyun objesi var rivalGame = { name: name, releaseDay: gameState.currentDay, revenue: revenue, _originalRevenue: percent < 0 ? -originalRevenue : originalRevenue, _originalLoss: originalLoss }; rival.games.push(rivalGame); // Sadece son 3 oyunu tut if (rival.games.length > 3) rival.games = rival.games.slice(-3); // Firma değerini anlık olarak kâr/zarara göre değiştir: kâr ise artır, zarar ise azalt if (revenue > 0) { rival.value += revenue + Math.floor(revenue * 0.1); } else if (originalLoss > 0) { rival.value -= originalLoss; } // Firma değeri 0'ın altına düşmesin if (rival.value < 0) rival.value = 0; // Son 3 oyunun ortalamasını güncelle var sum2 = 0; for (var i = 0; i < rival.games.length; i++) sum2 += rival.games[i].revenue; rival.avgRevenue = Math.floor(sum2 / rival.games.length); } } // Game update var dayTimer = 0; game.update = function () { // Handle research progress if (gameState.currentResearch) { gameState.currentResearch.timeRemaining--; if (gameState.currentResearch.timeRemaining <= 0) { // Research complete var research = gameState.currentResearch; if (research.category === 'Platforms') { // Mark platform as researched if (gameState.platforms && gameState.platforms[research.name]) { gameState.platforms[research.name].researched = true; } } else if (research.category === 'IncreaseLimit_Graphics' || research.category === 'IncreaseLimit_Sound' || research.category === 'IncreaseLimit_Gameplay') { // Increase the selection limit for the relevant category var cat = research.category.replace('IncreaseLimit_', ''); if (!gameState.featureSelectionLimit) gameState.featureSelectionLimit = {}; if (typeof gameState.featureSelectionLimit[cat] !== "number") gameState.featureSelectionLimit[cat] = 1; gameState.featureSelectionLimit[cat]++; } else { gameState.researchedFeatures[research.category].push(research.name); } gameState.currentResearch = null; LK.getSound('success').play(); // Show notification var notification = new Container(); game.addChild(notification); var bg = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 0.8 }); bg.tint = 0x4CAF50; notification.addChild(bg); var text = new Text2('Research Complete: ' + research.name, { size: 35, fill: 0xFFFFFF }); text.anchor.set(0.5, 0.5); notification.addChild(text); notification.x = 1024; notification.y = 600; notification.alpha = 0; tween(notification, { alpha: 1 }, { duration: 500, onFinish: function onFinish() { LK.setTimeout(function () { tween(notification, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { notification.destroy(); } }); }, 2000); } }); } } // Day progression (every 3 seconds = 1 day) dayTimer++; if (dayTimer >= 180) { // 60 fps * 3 seconds dayTimer = 0; gameState.currentDay++; // --- Bank: Process credit and deposit on day change --- // Credit: No daily penalty, payment handled at normal interest (see showBankMenu) // Deposit: If matured, do NOT auto-renew. Wait for user to withdraw. (Faiz zamanı tamamlanınca dursun, çek butonu görüntülensin) // No action needed here; handled in showBankMenu withdrawBtn // Kredi vadesi dolunca faiz eklenmesin, borç vadesi dolunca beklesin (hiçbir işlem yapılmaz) updateUI(); // Fan Store günlük satış sistemi: Her gün başında çalıştır processFanStoreDailySale(); // Process game sales for (var i = gameState.releasedGames.length - 1; i >= 0; i--) { var releasedGame = gameState.releasedGames[i]; var daysSinceRelease = gameState.currentDay - releasedGame.releaseDay; // Calculate sales decline var declineRate = 0.75; // Base 25% daily decline // Better games decline slower if (releasedGame.score >= releasedGame.targetScore * 1.5) { declineRate = 0.85; } else if (releasedGame.score >= releasedGame.targetScore) { declineRate = 0.80; } // Apply trend bonus to decline rate declineRate += (releasedGame.trendBonus - 1) * 0.03; declineRate = Math.min(declineRate, 0.90); // Calculate review score multiplier (0.3x for <60, 1x for 60-74, 1.7x for 75-89, 2.5x for 90+) // Ava: Review scores now have a much stronger effect on sales! var reviewMultiplier = 1; if (releasedGame.reviewScore !== undefined) { if (releasedGame.reviewScore >= 90) reviewMultiplier = 2.5;else if (releasedGame.reviewScore >= 75) reviewMultiplier = 1.7;else if (releasedGame.reviewScore >= 60) reviewMultiplier = 1;else reviewMultiplier = 0.3; } // Calculate fan sales bonus: proportional, e.g. 200 fan = %2, 1000 fan = %10, max 100% // Platform-specific: always use the selected platform's salesBonus var fanSalesBonus = 1; var selectedPlatformObj = null; if (gameState.selectedPlatform) { for (var pi = 0; pi < platforms.length; pi++) { if (platforms[pi].name === gameState.selectedPlatform) { selectedPlatformObj = platforms[pi]; break; } } } if (gameState.fans && gameState.fans > 0) { var bonusPercent = gameState.fans / 100000 * 100; // 100000 fan = %100 bonus if (bonusPercent > 100) bonusPercent = 100; // Always use platform's salesBonus if available if (selectedPlatformObj && typeof selectedPlatformObj.salesBonus === "number") { fanSalesBonus = 1 + bonusPercent * selectedPlatformObj.salesBonus / 100; } else { fanSalesBonus = 1 + bonusPercent / 100; } } // Calculate current day sales // Ava: +200% general sales boost, then reduce by 25% (multiply by 0.75) // Satışları %35 artırmak için çarpanı 3.0*0.75 yerine 3.0*0.75*1.35 yapıyoruz releasedGame.currentDailySales = Math.floor(releasedGame.initialDailySales * Math.pow(declineRate, daysSinceRelease) * reviewMultiplier * fanSalesBonus * 3.0 * 0.75 * 1.35); // Add to total sales and money if (releasedGame.currentDailySales > 0) { releasedGame.totalSales += releasedGame.currentDailySales; var pricePerCopy = releasedGame.price || 1; var revenue = Math.floor(releasedGame.currentDailySales * pricePerCopy); // 100% of price per copy to player gameState.money += revenue; // --- Fan gain from sales: Her 10 kopya satışta 1-5 arası rastgele fan kazandır --- if (!releasedGame._fanSalesRemainder) releasedGame._fanSalesRemainder = 0; var totalSalesForFan = releasedGame.currentDailySales + releasedGame._fanSalesRemainder; var fansGained = 0; if (totalSalesForFan >= 10) { var fanAwardCount = Math.floor(totalSalesForFan / 10); for (var f = 0; f < fanAwardCount; f++) { fansGained += 1 + Math.floor(Math.random() * 2); // 1-2 arası rastgele } releasedGame._fanSalesRemainder = totalSalesForFan % 10; } else { releasedGame._fanSalesRemainder = totalSalesForFan; } if (!gameState.fans) gameState.fans = 0; gameState.fans += fansGained; // --- Eski random fanGainPercent sistemini kaldır --- // (Kaldırıldı) } else { // Game no longer selling - remove from market var removedGame = gameState.releasedGames.splice(i, 1)[0]; gameState.gameHistory.push(removedGame); // Show notification var notification = new Container(); game.addChild(notification); var bg = LK.getAsset('card', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 1.2 }); bg.tint = 0x0f3460; notification.addChild(bg); var titleText = new Text2(removedGame.name + ' removed from market', { size: 35, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.y = -30; notification.addChild(titleText); var salesText = new Text2('Total copies sold: ' + removedGame.totalSales, { size: 30, fill: 0x4CAF50 }); salesText.anchor.set(0.5, 0.5); salesText.y = 20; notification.addChild(salesText); notification.x = 1024; notification.y = 1366; notification.alpha = 0; // Animate notification tween(notification, { alpha: 1, y: 1000 }, { duration: 500, onFinish: function onFinish() { LK.setTimeout(function () { tween(notification, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { notification.destroy(); } }); }, 2000); } }); } } updateUI(); updateSalesLog(); } if (gameState.currentProject && developmentScreen.visible) { var project = gameState.currentProject; // Development progress if (project.currentScore < project.targetScore) { // --- Ava: Make score gain speed depend on studio level and total developer skill --- // Calculate base points per tick var pointsPerTick = project.developmentSpeed / 30; // Calculate total skill of all developers (including main character) var totalDevSkill = gameState.mainCharacter.skill; for (var i = 0; i < gameState.developers.length; i++) { totalDevSkill += gameState.developers[i].skill; } // Studio level bonus: higher level = faster progress var studioLevelBonus = 1 + (gameState.studioLevel - 1) * 0.15; // +15% per studio level above 1 // Skill bonus: more total skill = faster progress, but with diminishing returns var skillBonus = 0.5 + Math.log(1 + totalDevSkill) * 0.5; // log curve, min 0.5x // Feature synergy bonus (as before) var synergy = 1; if (gameState.mainCharacter.featurePoints) { project.features.forEach(function (feature) { if (gameState.mainCharacter.featurePoints[feature.type] && gameState.mainCharacter.featurePoints[feature.type] > 0) { synergy += 0.1; } }); } project.features.forEach(function (feature) { gameState.developers.forEach(function (dev) { if (dev.specialty === feature.type) { synergy += 0.1; } }); }); // Final points per tick: base * studioLevelBonus * skillBonus * synergy var finalPointsPerTick = pointsPerTick * studioLevelBonus * skillBonus * synergy; // Clamp minimum progress to avoid being stuck at 0 if (finalPointsPerTick < 0.01) finalPointsPerTick = 0.01; project.currentScore += finalPointsPerTick; // Update UI currentScoreText.setText('Current Score: ' + Math.floor(project.currentScore)); var progress = Math.min(project.currentScore / project.targetScore, 1); progressBarFill.scaleX = progress; // Show release button when ready if (progress >= 1 && !releaseBtn.visible) { releaseBtn.visible = true; tween(releaseBtn, { scaleX: 1.1, scaleY: 1.1 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(releaseBtn, { scaleX: 1, scaleY: 1 }, { duration: 500 }); } }); } } } // Check game over if (gameState.money < 100 && gameState.developers.length === 0 && !gameState.currentProject) { LK.showGameOver(); } }; // Global Back Button (bottom) var globalBackBtn = new Button(); globalBackBtn.setLabel('Geri'); // Place at bottom center, matching other menu button size (400x100) globalBackBtn.x = 1024; globalBackBtn.y = 2600; globalBackBtn.visible = false; LK.gui.bottom.addChild(globalBackBtn); // --- Reset Game Button (bottom left) --- var resetGameBtn = new Button(); resetGameBtn.setLabel('Reset Game'); resetGameBtn.x = 220; // 200px from left, avoid top left menu area resetGameBtn.y = 2600; // bottom, same as globalBackBtn resetGameBtn.scaleX = 1; resetGameBtn.scaleY = 1; resetGameBtn.onClick = function () { LK.showGameOver(); // This will reset the game state and show the game over popup }; LK.gui.bottomLeft.addChild(resetGameBtn); // Global Back Button (top) var globalBackBtnTop = new Button(); globalBackBtnTop.setLabel('Geri'); globalBackBtnTop.x = 1024; globalBackBtnTop.y = 100; globalBackBtnTop.visible = false; LK.gui.top.addChild(globalBackBtnTop); // --- Reset Game Button (bottom left) --- var resetGameBtn = new Button(); resetGameBtn.setLabel('Reset Game'); resetGameBtn.x = 220; // 200px from left, avoid top left menu area resetGameBtn.y = 2600; // bottom, same as globalBackBtn resetGameBtn.scaleX = 1; resetGameBtn.scaleY = 1; resetGameBtn.onClick = function () { LK.showGameOver(); // This will reset the game state and show the game over popup }; LK.gui.bottomLeft.addChild(resetGameBtn); // Helper to check if any menu except mainMenu is visible function isAnyMenuOpen() { return upgradeMenu.visible || researchMenu.visible || researchCategoryMenu.visible || nameGameMenu.visible || allGamesMenu.visible || gameDetailView.visible || hireMenu.visible || projectMenu.visible || featureCategoryMenu.visible || developmentScreen.visible; } // Helper to close the topmost open menu and return to mainMenu function closeCurrentMenu() { if (upgradeMenu.visible) { upgradeMenu.visible = false; mainMenu.visible = true; } else if (researchCategoryMenu.visible) { researchCategoryMenu.visible = false; researchMenu.visible = true; } else if (researchMenu.visible) { researchMenu.visible = false; mainMenu.visible = true; } else if (nameGameMenu.visible) { nameGameMenu.visible = false; mainMenu.visible = true; gameNameInput.setText(''); currentGameName = ''; } else if (allGamesMenu.visible) { allGamesMenu.visible = false; mainMenu.visible = true; } else if (gameDetailView.visible) { gameDetailView.visible = false; allGamesMenu.visible = true; } else if (hireMenu.visible) { hireMenu.visible = false; mainMenu.visible = true; } else if (featureCategoryMenu.visible) { featureCategoryMenu.visible = false; projectMenu.visible = true; // Update total cost in project menu var totalCost = 0; selectedFeatures.forEach(function (f) { totalCost += f.cost; }); if (projectMenu.totalCostText) { projectMenu.totalCostText.setText('Total Cost: $' + totalCost); } } else if (projectMenu.visible) { projectMenu.visible = false; mainMenu.visible = true; selectedFeatures = []; featureCards.forEach(function (card) { card.setSelected(false); }); // Restore persistent buttons if missing (for next open) if (projectMenu.priceBtn && projectMenu.children.indexOf(projectMenu.priceBtn) === -1) { projectMenu.addChild(projectMenu.priceBtn); } if (projectMenu.platformBtn && projectMenu.children.indexOf(projectMenu.platformBtn) === -1) { projectMenu.addChild(projectMenu.platformBtn); } if (projectMenu.gameGenresResearchBtn && projectMenu.children.indexOf(projectMenu.gameGenresResearchBtn) === -1) { projectMenu.addChild(projectMenu.gameGenresResearchBtn); } } else if (developmentScreen.visible) { developmentScreen.visible = false; mainMenu.visible = true; } } // Attach handler to global back button globalBackBtn.onClick = function () { closeCurrentMenu(); }; globalBackBtnTop.onClick = function () { closeCurrentMenu(); }; // Show/hide global back button depending on menu state function updateGlobalBackBtn() { // Show if any menu except mainMenu is visible var show = isAnyMenuOpen() && !mainMenu.visible; globalBackBtn.visible = show; globalBackBtnTop.visible = show; } // Patch all menu show functions to update global back button var _showUpgradeMenu = showUpgradeMenu; showUpgradeMenu = function showUpgradeMenu() { _showUpgradeMenu(); updateGlobalBackBtn(); }; var _showPlatformMenu = showPlatformMenu; showPlatformMenu = function showPlatformMenu() { _showPlatformMenu(); updateGlobalBackBtn(); }; var _showResearchMenu = showResearchMenu; showResearchMenu = function showResearchMenu() { _showResearchMenu(); updateGlobalBackBtn(); }; var _showAllGamesMenu = showAllGamesMenu; showAllGamesMenu = function showAllGamesMenu() { _showAllGamesMenu(); updateGlobalBackBtn(); }; var _showHireMenu = showHireMenu; showHireMenu = function showHireMenu() { _showHireMenu(); updateGlobalBackBtn(); }; var _showProjectMenu = showProjectMenu; showProjectMenu = function showProjectMenu() { _showProjectMenu(); updateGlobalBackBtn(); }; var _showFeatureCategory = showFeatureCategory; showFeatureCategory = function showFeatureCategory(category) { _showFeatureCategory(category); updateGlobalBackBtn(); }; var _showResearchCategory = showResearchCategory; showResearchCategory = function showResearchCategory(category) { _showResearchCategory(category); updateGlobalBackBtn(); }; var _showNameGameMenu = showNameGameMenu; showNameGameMenu = function showNameGameMenu() { _showNameGameMenu(); updateGlobalBackBtn(); }; var _showGameDetail = showGameDetail; showGameDetail = function showGameDetail(gameData) { _showGameDetail(gameData); updateGlobalBackBtn(); }; // Patch all menu back/close buttons to update global back button function patchBackBtn(btn, closeFn) { var old = btn.onClick; btn.onClick = function () { if (old) old(); updateGlobalBackBtn(); }; } patchBackBtn(backFromUpgradeBtn); patchBackBtn(researchBackBtn); patchBackBtn(categoryBackBtn); patchBackBtn(backFromNameBtn); patchBackBtn(backFromAllGamesBtn); patchBackBtn(detailBackBtn); patchBackBtn(backFromHireBtn); patchBackBtn(backFromProjectBtn); patchBackBtn(categoryBackBtn); patchBackBtn(researchBackBtn); patchBackBtn(categoryBackBtn); // Also update on developmentScreen close (release) var _releaseGame = releaseGame; releaseGame = function releaseGame() { _releaseGame(); updateGlobalBackBtn(); }; // Also update on game update (in case of state changes) var _updateUI = updateUI; updateUI = function updateUI() { _updateUI(); updateGlobalBackBtn(); }; // Initialize updateUI(); updateGlobalBackBtn();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Button = Container.expand(function () {
var self = Container.call(this);
var bg = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5
});
var label = new Text2('Button', {
size: 40,
fill: 0xFFFFFF
});
label.anchor.set(0.5, 0.5);
self.addChild(label);
self.setLabel = function (text) {
label.setText(text);
};
self.down = function () {
tween(bg, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
LK.getSound('select').play();
};
self.up = function () {
tween(bg, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
if (self.onClick) {
self.onClick();
}
};
return self;
});
var DeveloperCard = Container.expand(function () {
var self = Container.call(this);
var bg = self.attachAsset('card', {
anchorX: 0.5,
anchorY: 0.5
});
var icon = self.attachAsset('developerIcon', {
anchorX: 0.5,
anchorY: 0.5,
y: -100
});
var nameText = new Text2('Developer', {
size: 30,
fill: 0xFFFFFF
});
nameText.anchor.set(0.5, 0.5);
nameText.y = -20;
self.addChild(nameText);
var specialtyText = new Text2('Graphics', {
size: 25,
fill: 0xFFC107
});
specialtyText.anchor.set(0.5, 0.5);
specialtyText.y = 20;
self.addChild(specialtyText);
var costText = new Text2('Cost: $100', {
size: 25,
fill: 0x4CAF50
});
costText.anchor.set(0.5, 0.5);
costText.y = 60;
self.addChild(costText);
var skillText = new Text2('Skill: 5', {
size: 25,
fill: 0x2196F3
});
skillText.anchor.set(0.5, 0.5);
skillText.y = 100;
self.addChild(skillText);
self.developerData = null;
self.setDeveloper = function (data) {
self.developerData = data;
nameText.setText(data.name);
specialtyText.setText(data.specialty);
costText.setText('Cost: $' + data.cost);
skillText.setText('Skill: ' + data.skill);
var specialtyColors = {
'Graphics': 0xff5722,
'Sound': 0x9c27b0,
'Gameplay': 0x2196f3
};
icon.tint = specialtyColors[data.specialty] || 0xffc107;
};
self.down = function () {
if (self.onClick) {
self.onClick(self.developerData);
}
};
return self;
});
var FeatureCard = Container.expand(function () {
var self = Container.call(this);
var bg = self.attachAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
var icon = self.attachAsset('featureIcon', {
anchorX: 0.5,
anchorY: 0.5,
y: -80
});
var nameText = new Text2('Feature', {
size: 25,
fill: 0xFFFFFF
});
nameText.anchor.set(0.5, 0.5);
nameText.y = -20;
self.addChild(nameText);
var typeText = new Text2('Type', {
size: 20,
fill: 0x2196F3
});
typeText.anchor.set(0.5, 0.5);
typeText.y = 10;
self.addChild(typeText);
var pointsText = new Text2('Points: 0', {
size: 20,
fill: 0x4CAF50
});
pointsText.anchor.set(0.5, 0.5);
pointsText.y = 40;
self.addChild(pointsText);
self.featureData = null;
self.selected = false;
self.setFeature = function (data) {
self.featureData = data;
nameText.setText(data.name);
typeText.setText(data.type);
pointsText.setText('Points: ' + data.basePoints + ' | Cost: $' + data.cost);
var typeColors = {
'Graphics': 0xff5722,
'Sound': 0x9c27b0,
'Gameplay': 0x2196f3
};
icon.tint = typeColors[data.type] || 0xffc107;
};
self.setSelected = function (selected) {
self.selected = selected;
bg.tint = selected ? 0xe94560 : 0xffffff;
};
self.down = function () {
if (self.onClick) {
self.onClick(self);
}
};
return self;
});
var GameHistoryCard = Container.expand(function () {
var self = Container.call(this);
var bg = self.attachAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.6
});
var nameText = new Text2('Game Name', {
size: 30,
fill: 0xFFFFFF
});
nameText.anchor.set(0.5, 0.5);
nameText.y = -30;
self.addChild(nameText);
var salesText = new Text2('Sales: 0', {
size: 25,
fill: 0x4CAF50
});
salesText.anchor.set(0.5, 0.5);
salesText.y = 10;
self.addChild(salesText);
self.gameData = null;
self.setGameData = function (data) {
self.gameData = data;
nameText.setText(data.name);
var salesInfo = data.currentDailySales > 0 ? 'Sales: ' + data.totalSales + ' (Active)' : 'Sales: ' + data.totalSales + ' (Ended)';
salesText.setText(salesInfo);
bg.tint = data.currentDailySales > 0 ? 0x0f3460 : 0x16213e;
};
self.down = function () {
if (self.onClick) {
self.onClick(self.gameData);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Game state
function _typeof2(o) {
"@babel/helpers - typeof";
return _typeof2 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof2(o);
}
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof(o);
}
var gameState = {
money: 50000,
developers: [],
currentProject: null,
completedGames: 0,
marketTrends: [],
currentDay: 1,
releasedGames: [],
maxHireableDevelopers: 1,
studioLevel: 1,
studioUpgradeCost: 5000,
fans: 0,
// Toplam fan sayısı
mainCharacter: {
name: "You",
level: 1,
upgradeCost: 2000,
skill: 2,
specialty: "All",
featurePoints: {
Graphics: 1,
Sound: 1,
Gameplay: 1
}
},
gameHistory: [],
researchedFeatures: {
Graphics: [],
Sound: [],
Gameplay: [],
GameGenres: []
},
currentResearch: null,
// --- Feature selection limit per category ---
featureSelectionLimit: {
Graphics: 1,
Sound: 1,
Gameplay: 1
}
};
// Current game name being created
var currentGameName = '';
// Game name display at top
var gameNameDisplay = new Text2('', {
size: 45,
fill: 0xFFFFFF
});
gameNameDisplay.anchor.set(0.5, 0);
gameNameDisplay.y = 10;
LK.gui.top.addChild(gameNameDisplay);
// Available developers pool
var developerPool = [{
name: 'Alex',
specialty: 'Graphics',
skill: 3,
cost: 4000
}, {
name: 'Sam',
specialty: 'Sound',
skill: 4,
cost: 4000
}, {
name: 'Jordan',
specialty: 'Gameplay',
skill: 5,
cost: 4000
}, {
name: 'Morgan',
specialty: 'Graphics',
skill: 6,
cost: 8000
}, {
name: 'Casey',
specialty: 'Sound',
skill: 7,
cost: 8000
}, {
name: 'Drew',
specialty: 'Gameplay',
skill: 8,
cost: 8000
}, {
name: 'Taylor',
specialty: 'Graphics',
skill: 9,
cost: 12000
}, {
name: 'Jamie',
specialty: 'Sound',
skill: 10,
cost: 12000
}, {
name: 'Robin',
specialty: 'Gameplay',
skill: 11,
cost: 12000
}];
// Available features - expanded with research requirements
var featurePool = [{
name: 'Pixel Art',
type: 'Graphics',
basePoints: 3,
cost: 2000,
requiresResearch: false
}, {
name: '3D Models',
type: 'Graphics',
basePoints: 5,
cost: 2000,
requiresResearch: false
}, {
name: 'Particle Effects',
type: 'Graphics',
basePoints: 4,
cost: 2000,
requiresResearch: false
}, {
name: 'Soundtrack',
type: 'Sound',
basePoints: 3,
cost: 2000,
requiresResearch: false
}, {
name: 'Voice Acting',
type: 'Sound',
basePoints: 6,
cost: 2000,
requiresResearch: false
}, {
name: 'Sound Effects',
type: 'Sound',
basePoints: 4,
cost: 2000,
requiresResearch: false
}, {
name: 'RPG Elements',
type: 'Gameplay',
basePoints: 5,
cost: 2000,
requiresResearch: false
}, {
name: 'Multiplayer',
type: 'Gameplay',
basePoints: 7,
cost: 2000,
requiresResearch: false
}, {
name: 'Puzzles',
type: 'Gameplay',
basePoints: 4,
cost: 2000,
requiresResearch: false
}, {
name: 'Open World',
type: 'Gameplay',
basePoints: 8,
cost: 2000,
requiresResearch: false
}, {
name: 'Shaders',
type: 'Graphics',
basePoints: 6,
cost: 4000,
requiresResearch: true
}, {
name: 'Ray Tracing',
type: 'Graphics',
basePoints: 10,
cost: 6000,
requiresResearch: true
}, {
name: 'Motion Capture',
type: 'Graphics',
basePoints: 8,
cost: 4000,
requiresResearch: true
}, {
name: 'Procedural Generation',
type: 'Graphics',
basePoints: 7,
cost: 4000,
requiresResearch: true
}, {
name: 'Dynamic Lighting',
type: 'Graphics',
basePoints: 6,
cost: 4000,
requiresResearch: true
}, {
name: 'Orchestral Score',
type: 'Sound',
basePoints: 8,
cost: 4000,
requiresResearch: true
}, {
name: '3D Audio',
type: 'Sound',
basePoints: 7,
cost: 4000,
requiresResearch: true
}, {
name: 'Dynamic Music',
type: 'Sound',
basePoints: 6,
cost: 4000,
requiresResearch: true
}, {
name: 'Environmental Audio',
type: 'Sound',
basePoints: 5,
cost: 4000,
requiresResearch: true
}, {
name: 'Foley Effects',
type: 'Sound',
basePoints: 6,
cost: 4000,
requiresResearch: true
}, {
name: 'Physics Engine',
type: 'Gameplay',
basePoints: 9,
cost: 6000,
requiresResearch: true
}, {
name: 'AI Systems',
type: 'Gameplay',
basePoints: 10,
cost: 6000,
requiresResearch: true
}, {
name: 'Skill Trees',
type: 'Gameplay',
basePoints: 6,
cost: 4000,
requiresResearch: true
}, {
name: 'Crafting System',
type: 'Gameplay',
basePoints: 7,
cost: 4000,
requiresResearch: true
}, {
name: 'Dialogue System',
type: 'Gameplay',
basePoints: 5,
cost: 4000,
requiresResearch: true
}];
// Game genres that can be researched
var gameGenres = [{
name: 'Action',
baseMultiplier: 1.2,
trendChance: 0.3,
researchCost: 4000,
requiresResearch: false
}, {
name: 'Adventure',
baseMultiplier: 1.1,
trendChance: 0.25,
researchCost: 4000,
requiresResearch: false
}, {
name: 'Puzzle',
baseMultiplier: 1.0,
trendChance: 0.2,
researchCost: 4000,
requiresResearch: false
}, {
name: 'Racing',
baseMultiplier: 1.3,
trendChance: 0.35,
researchCost: 8000,
requiresResearch: true
}, {
name: 'Strategy',
baseMultiplier: 1.4,
trendChance: 0.3,
researchCost: 8000,
requiresResearch: true
}, {
name: 'Simulation',
baseMultiplier: 1.2,
trendChance: 0.25,
researchCost: 8000,
requiresResearch: true
}, {
name: 'RPG',
baseMultiplier: 1.5,
trendChance: 0.4,
researchCost: 12000,
requiresResearch: true
}, {
name: 'FPS',
baseMultiplier: 1.4,
trendChance: 0.35,
researchCost: 12000,
requiresResearch: true
}, {
name: 'Horror',
baseMultiplier: 1.3,
trendChance: 0.25,
researchCost: 12000,
requiresResearch: true
}, {
name: 'Sports',
baseMultiplier: 1.2,
trendChance: 0.3,
researchCost: 12000,
requiresResearch: true
}];
// UI Elements
var moneyText = new Text2('Money: $10000', {
size: 50,
fill: 0x4CAF50
});
moneyText.anchor.set(1, 0);
moneyText.x = 0;
moneyText.y = 0;
LK.gui.topRight.addChild(moneyText);
var developersText = new Text2('Developers: 0', {
size: 40,
fill: 0xFFFFFF
});
developersText.anchor.set(1, 0);
developersText.x = 0;
developersText.y = moneyText.y + moneyText.height + 8;
LK.gui.topRight.addChild(developersText);
var gamesText = new Text2('Games Released: 0', {
size: 40,
fill: 0xFFC107
});
gamesText.anchor.set(1, 0);
gamesText.x = 0;
gamesText.y = developersText.y + developersText.height + 8;
LK.gui.topRight.addChild(gamesText);
// Fan count and bonus UI
var fanText = new Text2('Fan: 0', {
size: 40,
fill: 0x2196F3
});
fanText.anchor.set(1, 0);
fanText.x = 0;
fanText.y = gamesText.y + gamesText.height + 8;
LK.gui.topRight.addChild(fanText);
var fanBonusText = new Text2('Sales Bonus: %0', {
size: 32,
fill: 0x4CAF50
});
fanBonusText.anchor.set(1, 0);
fanBonusText.x = 0;
fanBonusText.y = fanText.y + fanText.height + 8;
LK.gui.topRight.addChild(fanBonusText);
var dayText = new Text2('Day: 1', {
size: 40,
fill: 0x2196F3
});
dayText.anchor.set(1, 0);
dayText.x = 0;
dayText.y = fanBonusText.y + fanBonusText.height + 8;
LK.gui.topRight.addChild(dayText);
// --- Sales & Revenue Log UI ---
var salesLogContainer = new Container();
salesLogContainer.x = 2048 - 40; // right align
salesLogContainer.y = 220; // just below dayText
LK.gui.topRight.addChild(salesLogContainer);
var salesLogEntries = []; // keep references to Text2 objects for updating/removal
function updateSalesLog() {
// Remove old entries
for (var i = 0; i < salesLogEntries.length; i++) {
salesLogEntries[i].destroy();
}
salesLogEntries = [];
// Show up to 5 most recent games (active and ended)
var allGames = gameState.releasedGames.concat(gameState.gameHistory);
var recentGames = allGames.slice(-5).reverse();
var y = 0;
for (var i = 0; i < recentGames.length; i++) {
var g = recentGames[i];
var isActive = g.currentDailySales > 0;
var pricePerCopy = typeof g.price === "number" ? g.price : 1;
var revenue = Math.floor((g.currentDailySales || 0) * pricePerCopy);
var txt = new Text2(g.name + ': +' + (g.currentDailySales || 0) + ' | $' + revenue, {
size: 28,
fill: isActive ? 0x4CAF50 : 0x888888
});
txt.anchor.set(1, 0);
txt.x = 0;
txt.y = y;
salesLogContainer.addChild(txt);
salesLogEntries.push(txt);
y += 36;
}
}
// Main menu container
var mainMenu = new Container();
game.addChild(mainMenu);
// --- How to Play Button and Info Popup ---
var howToPlayBtn = new Button();
howToPlayBtn.setLabel('How to Play?');
howToPlayBtn.x = 1024;
howToPlayBtn.y = 180;
howToPlayBtn.onClick = function () {
// Remove previous popup if any
if (mainMenu.howToPlayPopup) {
mainMenu.howToPlayPopup.destroy();
mainMenu.howToPlayPopup = null;
}
var popup = new Container();
popup.x = 1024;
popup.y = 600;
var bg = LK.getAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 2.2
});
bg.tint = 0x16213e;
popup.addChild(bg);
var infoText = new Text2("Welcome to Game Dev Studio!\n\n" + "• Hire talented developers to join your team.\n" + "• Start new projects and select the best features for your games.\n" + "• Follow market trends and research new technologies to stay ahead.\n" + "• Release your games, earn money, and gain fans.\n" + "• Upgrade your studio to hire more developers and unlock new possibilities.\n" + "• Compete with rival companies and become the top game studio!\n\n" + "Tip: Use the main menu to access hiring, research, platforms, and more.", {
size: 36,
fill: 0xFFFFFF,
align: "center"
});
infoText.anchor.set(0.5, 0.5);
infoText.x = 0;
infoText.y = -40;
popup.addChild(infoText);
var closeBtn = new Button();
closeBtn.setLabel('Close');
closeBtn.x = 0;
closeBtn.y = 320;
closeBtn.onClick = function () {
if (mainMenu.howToPlayPopup) {
mainMenu.howToPlayPopup.destroy();
mainMenu.howToPlayPopup = null;
}
};
popup.addChild(closeBtn);
mainMenu.addChild(popup);
mainMenu.howToPlayPopup = popup;
};
mainMenu.addChild(howToPlayBtn);
var titleText = new Text2('Game Dev Studio', {
size: 80,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 300;
mainMenu.addChild(titleText);
var hireDeveloperBtn = new Button();
hireDeveloperBtn.setLabel('Hire Developer');
hireDeveloperBtn.x = 1024;
hireDeveloperBtn.y = 750;
hireDeveloperBtn.onClick = showHireMenu;
mainMenu.addChild(hireDeveloperBtn);
var startProjectBtn = new Button();
startProjectBtn.setLabel('Start Project');
startProjectBtn.x = 1024;
startProjectBtn.y = 900;
startProjectBtn.onClick = showProjectMenu;
mainMenu.addChild(startProjectBtn);
var allGamesBtn = new Button();
allGamesBtn.setLabel('All Released Games');
allGamesBtn.x = 1024;
allGamesBtn.y = 1050;
allGamesBtn.onClick = showAllGamesMenu;
mainMenu.addChild(allGamesBtn);
var researchBtn = new Button();
researchBtn.setLabel('Research');
researchBtn.x = 1024;
researchBtn.y = 1200;
researchBtn.onClick = showResearchMenu;
mainMenu.addChild(researchBtn);
// (Game Engine button removed)
// --- Bank Button ---
var bankBtn = new Button();
bankBtn.setLabel('Bank');
bankBtn.x = 1024;
bankBtn.y = 1550;
bankBtn.onClick = showBankMenu;
mainMenu.addChild(bankBtn);
// --- Platform Button ---
var platformBtn = new Button();
platformBtn.setLabel('Platform');
platformBtn.x = 1024;
platformBtn.y = 1650;
platformBtn.onClick = showPlatformMenu;
mainMenu.addChild(platformBtn);
// --- Fan Button ---
var fanBtn = new Button();
fanBtn.setLabel('Fan');
fanBtn.x = 1024;
fanBtn.y = 1800;
fanBtn.onClick = showFanMenu;
mainMenu.addChild(fanBtn);
// --- Fan Store Button ---
var fanStoreBtn = new Button();
fanStoreBtn.setLabel('Fan Store');
fanStoreBtn.x = 1024;
fanStoreBtn.y = 1920;
fanStoreBtn.onClick = showFanStoreMenu;
mainMenu.addChild(fanStoreBtn);
// --- Rivals Button ---
var rivalsBtn = new Button();
rivalsBtn.setLabel('Rivals');
rivalsBtn.x = 1024;
rivalsBtn.y = 2040; // 2 satır altı (120px aralık)
rivalsBtn.onClick = showRivalsMenu;
mainMenu.addChild(rivalsBtn);
// --- Rivals Games Button ---
var rivalsGamesBtn = new Button();
rivalsGamesBtn.setLabel('Rivals Games');
rivalsGamesBtn.x = 1024;
rivalsGamesBtn.y = 2160; // Rivals butonunun hemen altında
rivalsGamesBtn.onClick = showRivalsGamesMenu;
mainMenu.addChild(rivalsGamesBtn);
// --- Bank Menu UI ---
var bankMenu = new Container();
bankMenu.visible = false;
game.addChild(bankMenu);
var bankTitle = new Text2('Bank', {
size: 60,
fill: 0xFFFFFF
});
bankTitle.anchor.set(0.5, 0.5);
bankTitle.x = 1024;
bankTitle.y = 200;
bankMenu.addChild(bankTitle);
// Bilgi yazısı: Banka sistemi hakkında açıklama (Geri tuşunun 3 satır yukarısına)
var bankInfoText = new Text2("Bank System:\n" + "- You must have no outstanding debt to take a new loan.\n" + "- If you pay off a loan early, you pay 10% extra of the original amount.\n" + "- When a loan matures, no extra interest is added; the debt waits until paid.\n" + "- You can deposit up to 50% of your cash as a deposit.\n" + "- When a deposit matures, interest stops. Use the withdraw button to collect your money.", {
size: 32,
fill: 0xFFC107,
align: "center"
});
bankInfoText.anchor.set(0.5, 1);
bankInfoText.x = 1024;
bankInfoText.y = 2400 - 3 * 50; // 3 satır yukarı (her satır ~50px)
bankMenu.addChild(bankInfoText);
var bankBackBtn = new Button();
bankBackBtn.setLabel('Back');
bankBackBtn.x = 1024;
bankBackBtn.y = 2400;
bankBackBtn.onClick = function () {
bankMenu.visible = false;
mainMenu.visible = true;
};
bankMenu.addChild(bankBackBtn);
// --- Bank state ---
if (!gameState.bank) {
gameState.bank = {
credit: 0,
creditDueDay: 0,
deposit: 0,
depositDueDay: 0
};
}
// --- Show Bank Menu function ---
function showBankMenu() {
mainMenu.visible = false;
bankMenu.visible = true;
// Remove old UI except title and back and info text
for (var i = bankMenu.children.length - 1; i >= 0; i--) {
var child = bankMenu.children[i];
if (child !== bankTitle && child !== bankBackBtn && child !== bankInfoText) {
child.destroy();
}
}
// Re-add info text if not present
if (!bankMenu.children.includes(bankInfoText)) {
bankMenu.addChild(bankInfoText);
}
// Info text
var infoText = new Text2('You can take a loan or make a deposit.', {
size: 36,
fill: 0x4CAF50
});
infoText.anchor.set(0.5, 0.5);
infoText.x = 1024;
infoText.y = 350;
bankMenu.addChild(infoText);
// --- Credit Section ---
var creditTitle = new Text2('Take Loan', {
size: 40,
fill: 0xFFC107
});
creditTitle.anchor.set(0.5, 0.5);
creditTitle.x = 1024;
creditTitle.y = 500;
bankMenu.addChild(creditTitle);
var creditAmount = 10000;
var creditInterest = 0.15; // %15 faiz
var creditDuration = 10; // 10 gün vade
var creditBtn = new Button();
creditBtn.setLabel('Take Loan (15% interest, 10 days, Limit: 20% of cash)');
creditBtn.x = 1024;
creditBtn.y = 600;
creditBtn.onClick = function () {
// Prevent new credit if there is any unpaid debt (even if overdue)
if (gameState.bank.credit > 0) {
// Show notification
var notif = new Container();
var bg = LK.getAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.5
});
bg.tint = 0xE94560;
notif.addChild(bg);
var txt = new Text2('You must pay your previous loan first!', {
size: 32,
fill: 0xFFFFFF
});
txt.anchor.set(0.5, 0.5);
notif.addChild(txt);
notif.x = 1024;
notif.y = 800;
notif.alpha = 0;
game.addChild(notif);
tween(notif, {
alpha: 1
}, {
duration: 400,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(notif, {
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
notif.destroy();
}
});
}, 1500);
}
});
return;
}
// Calculate credit limit as 20% of current cash (rounded down to nearest 1000)
var maxCredit = Math.floor(gameState.money * 0.2 / 1000) * 1000;
if (maxCredit < 1000) maxCredit = 1000; // Minimum 1000₺
var creditInterest = 0.15; // %15 faiz
var creditDuration = 10; // 10 gün vade
if (maxCredit <= 0) {
// Show notification for no available credit
var notif = new Container();
var bg = LK.getAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.5
});
bg.tint = 0xE94560;
notif.addChild(bg);
var txt = new Text2('No loan limit! (You have too little cash)', {
size: 32,
fill: 0xFFFFFF
});
txt.anchor.set(0.5, 0.5);
notif.addChild(txt);
notif.x = 1024;
notif.y = 800;
notif.alpha = 0;
game.addChild(notif);
tween(notif, {
alpha: 1
}, {
duration: 400,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(notif, {
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
notif.destroy();
}
});
}, 1500);
}
});
return;
}
// Grant credit
gameState.money += maxCredit;
gameState.bank.credit = maxCredit * (1 + creditInterest);
gameState.bank.creditDueDay = gameState.currentDay + creditDuration;
updateUI();
showBankMenu();
LK.getSound('success').play();
};
bankMenu.addChild(creditBtn);
var creditStatus = '';
if (gameState.bank.credit > 0 && gameState.currentDay < gameState.bank.creditDueDay) {
creditStatus = 'Remaining Debt: ' + Math.round(gameState.bank.credit) + ' | Due Day: ' + gameState.bank.creditDueDay;
} else if (gameState.bank.credit > 0 && gameState.currentDay >= gameState.bank.creditDueDay) {
creditStatus = 'Loan matured! Debt: ' + Math.round(gameState.bank.credit);
} else {
creditStatus = 'No active loan.';
}
var creditStatusText = new Text2(creditStatus, {
size: 30,
fill: 0xFFFFFF
});
creditStatusText.anchor.set(0.5, 0.5);
creditStatusText.x = 1024;
creditStatusText.y = 670;
bankMenu.addChild(creditStatusText);
// --- Deposit Section ---
var depositTitle = new Text2('Make Deposit', {
size: 40,
fill: 0x2196F3
});
depositTitle.anchor.set(0.5, 0.5);
depositTitle.x = 1024;
depositTitle.y = 850;
bankMenu.addChild(depositTitle);
// Ava: Mevduat yatırma oranı, nakit paramızın maksimum %50'sine kadar olmalı
var depositInterest = 0.10; // %10 faiz
var depositDuration = 10; // 10 gün vade
// Hesaplanan maksimum mevduat miktarı (en az 1000₺, 1000'lik katlar)
var maxDeposit = Math.floor(gameState.money * 0.5 / 1000) * 1000;
if (maxDeposit < 1000) maxDeposit = 1000;
var depositAmount = maxDeposit;
var depositBtn = new Button();
depositBtn.setLabel(maxDeposit + ' Deposit (10% interest, 10 days)');
depositBtn.x = 1024;
depositBtn.y = 950;
depositBtn.onClick = function () {
// Only allow one active deposit at a time
if (gameState.bank.deposit > 0 && gameState.currentDay < gameState.bank.depositDueDay) {
// Show notification
var notif = new Container();
var bg = LK.getAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.5
});
bg.tint = 0xE94560;
notif.addChild(bg);
var txt = new Text2('Your previous deposit is still maturing!', {
size: 32,
fill: 0xFFFFFF
});
txt.anchor.set(0.5, 0.5);
notif.addChild(txt);
notif.x = 1024;
notif.y = 1150;
notif.alpha = 0;
game.addChild(notif);
tween(notif, {
alpha: 1
}, {
duration: 400,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(notif, {
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
notif.destroy();
}
});
}, 1500);
}
});
return;
}
if (gameState.money < depositAmount) {
// Show notification
var notif = new Container();
var bg = LK.getAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.5
});
bg.tint = 0xE94560;
notif.addChild(bg);
var txt = new Text2('Not enough money!', {
size: 32,
fill: 0xFFFFFF
});
txt.anchor.set(0.5, 0.5);
notif.addChild(txt);
notif.x = 1024;
notif.y = 1150;
notif.alpha = 0;
game.addChild(notif);
tween(notif, {
alpha: 1
}, {
duration: 400,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(notif, {
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
notif.destroy();
}
});
}, 1500);
}
});
return;
}
gameState.money -= depositAmount;
gameState.bank.deposit = depositAmount * (1 + depositInterest);
gameState.bank.depositDueDay = gameState.currentDay + depositDuration;
updateUI();
showBankMenu();
LK.getSound('success').play();
};
bankMenu.addChild(depositBtn);
var depositStatus = '';
if (gameState.bank.deposit > 0 && gameState.currentDay < gameState.bank.depositDueDay) {
depositStatus = 'Deposit: ' + Math.round(gameState.bank.deposit) + ' | Due Day: ' + gameState.bank.depositDueDay;
} else if (gameState.bank.deposit > 0 && gameState.currentDay >= gameState.bank.depositDueDay) {
depositStatus = 'Deposit matured! Withdrawable: ' + Math.round(gameState.bank.deposit);
} else {
depositStatus = 'No active deposit.';
}
var depositStatusText = new Text2(depositStatus, {
size: 30,
fill: 0xFFFFFF
});
depositStatusText.anchor.set(0.5, 0.5);
depositStatusText.x = 1024;
depositStatusText.y = 1020;
bankMenu.addChild(depositStatusText);
// --- Deposit Withdraw Button (if matured) ---
if (gameState.bank.deposit > 0 && gameState.currentDay >= gameState.bank.depositDueDay) {
var withdrawBtn = new Button();
withdrawBtn.setLabel('Withdraw Deposit (+ ' + Math.round(gameState.bank.deposit) + ')');
withdrawBtn.x = 1024;
withdrawBtn.y = 1100;
withdrawBtn.onClick = function () {
gameState.money += Math.round(gameState.bank.deposit);
gameState.bank.deposit = 0;
gameState.bank.depositDueDay = 0;
updateUI();
showBankMenu();
LK.getSound('success').play();
};
bankMenu.addChild(withdrawBtn);
}
// --- Credit Pay Button (if matured or early) ---
// Early payment: allow if credit > 0 and not overdue
if (gameState.bank.credit > 0 && gameState.currentDay < gameState.bank.creditDueDay) {
var earlyPayBtn = new Button();
// Early payment is original credit + 10% of original credit (not 10% of current debt)
// Calculate original credit amount (principal)
var originalCredit = Math.round(gameState.bank.credit / 1.15); // since credit = principal * 1.15
var earlyPayAmount = Math.round(originalCredit * 1.10); // %10 fazlası
earlyPayBtn.setLabel('Pay Early (-' + earlyPayAmount + ', 10% interest)');
earlyPayBtn.x = 1024;
earlyPayBtn.y = 750;
earlyPayBtn.onClick = function () {
if (gameState.money >= earlyPayAmount) {
gameState.money -= earlyPayAmount;
gameState.bank.credit = 0;
gameState.bank.creditDueDay = 0;
updateUI();
showBankMenu();
LK.getSound('success').play();
} else {
// Show notification
var notif = new Container();
var bg = LK.getAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.5
});
bg.tint = 0xE94560;
notif.addChild(bg);
var txt = new Text2('Not enough money!', {
size: 32,
fill: 0xFFFFFF
});
txt.anchor.set(0.5, 0.5);
notif.addChild(txt);
notif.x = 1024;
notif.y = 900;
notif.alpha = 0;
game.addChild(notif);
tween(notif, {
alpha: 1
}, {
duration: 400,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(notif, {
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
notif.destroy();
}
});
}, 1500);
}
});
}
};
bankMenu.addChild(earlyPayBtn);
}
// Normal payment: if matured or overdue
if (gameState.bank.credit > 0 && gameState.currentDay >= gameState.bank.creditDueDay) {
var payBtn = new Button();
payBtn.setLabel('Pay Loan (-' + Math.round(gameState.bank.credit) + ')');
payBtn.x = 1024;
payBtn.y = 750;
payBtn.onClick = function () {
if (gameState.money >= Math.round(gameState.bank.credit)) {
gameState.money -= Math.round(gameState.bank.credit);
gameState.bank.credit = 0;
gameState.bank.creditDueDay = 0;
updateUI();
showBankMenu();
LK.getSound('success').play();
} else {
// Show notification
var notif = new Container();
var bg = LK.getAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.5
});
bg.tint = 0xE94560;
notif.addChild(bg);
var txt = new Text2('Not enough money!', {
size: 32,
fill: 0xFFFFFF
});
txt.anchor.set(0.5, 0.5);
notif.addChild(txt);
notif.x = 1024;
notif.y = 900;
notif.alpha = 0;
game.addChild(notif);
tween(notif, {
alpha: 1
}, {
duration: 400,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(notif, {
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
notif.destroy();
}
});
}, 1500);
}
});
}
};
bankMenu.addChild(payBtn);
}
}
// --- Rivals Games Menu UI ---
var rivalsGamesMenu = new Container();
rivalsGamesMenu.visible = false;
game.addChild(rivalsGamesMenu);
var rivalsGamesTitle = new Text2('Rivals Games', {
size: 60,
fill: 0xFFFFFF
});
rivalsGamesTitle.anchor.set(0.5, 0.5);
rivalsGamesTitle.x = 1024;
rivalsGamesTitle.y = 200;
rivalsGamesMenu.addChild(rivalsGamesTitle);
var rivalsGamesBackBtn = new Button();
rivalsGamesBackBtn.setLabel('Geri');
rivalsGamesBackBtn.x = 1024;
rivalsGamesBackBtn.y = 2400;
rivalsGamesBackBtn.onClick = function () {
rivalsGamesMenu.visible = false;
mainMenu.visible = true;
};
rivalsGamesMenu.addChild(rivalsGamesBackBtn);
// --- Helper: Show Rivals Games Menu ---
function showRivalsGamesMenu() {
mainMenu.visible = false;
rivalsGamesMenu.visible = true;
// Eski kartları temizle (başlık ve geri hariç)
for (var i = rivalsGamesMenu.children.length - 1; i >= 0; i--) {
var child = rivalsGamesMenu.children[i];
if (child !== rivalsGamesTitle && child !== rivalsGamesBackBtn) {
child.destroy();
}
}
// Tüm rakiplerin çıkardığı oyunları topla
var allRivalGames = [];
for (var i = 0; i < gameState.rivals.length; i++) {
var rival = gameState.rivals[i];
if (rival.games && rival.games.length > 0) {
for (var j = 0; j < rival.games.length; j++) {
var g = rival.games[j];
// Her oyun için rakip adı ekle
allRivalGames.push({
name: g.name,
revenue: g.revenue,
releaseDay: g.releaseDay,
rivalName: rival.name
});
}
}
}
// Oyunları en yeniye göre sırala (büyükten küçüğe)
allRivalGames.sort(function (a, b) {
return b.releaseDay - a.releaseDay;
});
// Hiç oyun yoksa bilgi göster
if (allRivalGames.length === 0) {
var noRivalGamesText = new Text2('No rival has released a game yet', {
size: 40,
fill: 0xFFFFFF
});
noRivalGamesText.anchor.set(0.5, 0.5);
noRivalGamesText.x = 1024;
noRivalGamesText.y = 600;
rivalsGamesMenu.addChild(noRivalGamesText);
return;
}
// 4 sütun, 7 satır grid (28 oyun gösterilecek şekilde)
var cols = 4;
var xStart = 320,
yStart = 440 * 1.1,
xSpacing = 370 * 1.1,
ySpacing = 180 * 1.1;
for (var i = 0; i < allRivalGames.length && i < 28; i++) {
var game = allRivalGames[i];
var col = i % cols,
row = Math.floor(i / cols);
var container = new Container();
container.x = xStart + col * xSpacing;
container.y = yStart + row * ySpacing;
// Kart arka planı
var bg = LK.getAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 0.45
});
container.addChild(bg);
// Oyun adı
var nameText = new Text2(game.name, {
size: 28,
fill: 0xFFFFFF
});
nameText.anchor.set(0.5, 0.5);
nameText.y = -30;
container.addChild(nameText);
// Rakip firma adı
var rivalText = new Text2('Company: ' + game.rivalName, {
size: 24,
fill: 0x2196F3
});
rivalText.anchor.set(0.5, 0.5);
rivalText.y = 10;
container.addChild(rivalText);
// Gelir veya Zarar
var revenueLabel = 'Gelir: $' + game.revenue;
var revenueColor = 0x4CAF50;
if (typeof game.revenue === "number" && game.revenue === 0) {
// Zarar varsa, revenue 0 olarak tutuluyor, ama aslında zarar vardı.
// Oyun objesinde orijinal zarar bilgisini bulmak için rakip firmanın oyunlarını arayalım.
var actualLoss = 0;
for (var ri = 0; ri < gameState.rivals.length; ri++) {
var rival = gameState.rivals[ri];
if (rival.name === game.rivalName && rival.games && rival.games.length > 0) {
for (var gj = 0; gj < rival.games.length; gj++) {
var g2 = rival.games[gj];
if (g2.name === game.name && g2.releaseDay === game.releaseDay) {
// Orijinal revenue negatifse, onu göster
if (typeof g2._originalLoss === "number" && g2._originalLoss > 0) {
actualLoss = g2._originalLoss;
} else if (typeof g2._originalRevenue === "number" && g2._originalRevenue < 0) {
actualLoss = -g2._originalRevenue;
}
}
}
}
}
revenueLabel = 'Loss: $' + (actualLoss > 0 ? actualLoss : 0);
revenueColor = 0xE94560;
}
var revenueText = new Text2(revenueLabel, {
size: 24,
fill: revenueColor
});
revenueText.anchor.set(0.5, 0.5);
revenueText.y = 40;
container.addChild(revenueText);
// Çıkış günü
var dayText = new Text2('Day: ' + game.releaseDay, {
size: 22,
fill: 0xFFC107
});
dayText.anchor.set(0.5, 0.5);
dayText.y = 70;
container.addChild(dayText);
rivalsGamesMenu.addChild(container);
}
}
// --- Rivals Menu UI ---
var rivalsMenu = new Container();
rivalsMenu.visible = false;
game.addChild(rivalsMenu);
var rivalsTitle = new Text2('Rival Companies', {
size: 60,
fill: 0xFFFFFF
});
rivalsTitle.anchor.set(0.5, 0.5);
rivalsTitle.x = 1024;
rivalsTitle.y = 200;
rivalsMenu.addChild(rivalsTitle);
var rivalsBackBtn = new Button();
rivalsBackBtn.setLabel('Back');
rivalsBackBtn.x = 1024;
rivalsBackBtn.y = 2400;
rivalsBackBtn.onClick = function () {
rivalsMenu.visible = false;
mainMenu.visible = true;
};
rivalsMenu.addChild(rivalsBackBtn);
// --- Rivals Data ---
if (!gameState.rivals) {
// 28 popüler firma, her biri 20-30 günde bir oyun çıkarır
var rivalNames = ["PixelForge", "BitMasters", "RetroSoft", "NextGen Games", "Funbyte", "DreamPixel", "CodeCrafters", "GameNest", "Playverse", "IndieGiant", "ArcadiaWorks", "QuantumPlay", "StudioNova", "BlueBox", "RedShift", "MegaFun", "GameWave", "Starbyte", "EpicPlay", "VirtuaDev",
// 8 yeni firma
"NeonPixel", "TurboPlay", "GameSmiths", "HyperNova", "PlayMakers", "PixelPioneers", "FunLab", "InfinityGames"];
gameState.rivals = [];
for (var i = 0; i < rivalNames.length; i++) {
var baseValue = 100000 + Math.floor(Math.random() * 100000); // 100k-200k arası başlangıç değeri
var rival = {
name: rivalNames[i],
value: baseValue,
ownedPercent: 0,
// Oyuncunun sahip olduğu yüzde
games: [],
lastReleaseDay: 1 + Math.floor(Math.random() * 10),
// İlk oyun çıkış günü
releaseInterval: 20 + Math.floor(Math.random() * 11),
// 20-30 gün arası
avgRevenue: 0 // Son 3 oyunun ortalaması
};
gameState.rivals.push(rival);
}
// Oyuncunun şirket değeri başlangıçta: anlık nakit paramın %20'si + sahip olunan şirketlerin değerleri toplamı
var cash = gameState.money || 0;
var cashPart = cash * 0.20;
var ownedValueSum = 0;
if (gameState.rivals && gameState.rivals.length > 0) {
for (var i = 0; i < gameState.rivals.length; i++) {
var rival = gameState.rivals[i];
if (rival.ownedPercent && rival.ownedPercent > 0) {
ownedValueSum += Math.floor((rival.value || 0) * (rival.ownedPercent / 100));
}
}
}
gameState.companyValue = Math.floor(cashPart + ownedValueSum);
}
// --- Helper: Rival yeni oyun çıkarır ---
function rivalReleaseGame(rival, day) {
// Oyun ismi ve gelirini üret
var gameNames = ["Super", "Mega", "Ultra", "Epic", "Legend", "Pixel", "Quest", "Saga", "Chronicles", "World"];
var gameSuffix = ["Adventure", "Battle", "Story", "Kingdom", "Odyssey", "Arena", "Tycoon", "Empire", "Run", "Hero"];
var name = gameNames[Math.floor(Math.random() * gameNames.length)] + " " + gameSuffix[Math.floor(Math.random() * gameSuffix.length)];
// Rakip oyun kazancı, rakip şirket değerinin %1-%20 aralığında kâr veya %1-%20 aralığında zarar olacak şekilde ayarlandı
var percent = (Math.random() < 0.5 ? -1 : 1) * (0.01 + Math.random() * 0.19); // -0.01 ile -0.20 veya +0.01 ile +0.20 arası
var baseValue = rival.value || 100000;
var revenue = Math.floor(baseValue * Math.abs(percent));
var originalRevenue = revenue;
if (percent < 0) {
revenue = -revenue;
}
var originalLoss = 0;
if (revenue < 0) {
originalLoss = -revenue;
revenue = 0;
}
var game = {
name: name,
releaseDay: day,
revenue: revenue,
_originalRevenue: percent < 0 ? -originalRevenue : originalRevenue,
_originalLoss: originalLoss
};
rival.games.push(game);
// Sadece son 3 oyunun ortalamasını tut
if (rival.games.length > 3) rival.games = rival.games.slice(-3);
// Firma değerini anlık olarak kâr/zarara göre değiştir: kâr ise artır, zarar ise azalt
if (revenue > 0) {
rival.value += revenue + Math.floor(revenue * 0.1);
} else if (originalLoss > 0) {
rival.value -= originalLoss;
}
if (rival.value < 0) rival.value = 0;
// Son 3 oyunun ortalamasını güncelle
var sum = 0;
for (var i = 0; i < rival.games.length; i++) sum += rival.games[i].revenue;
rival.avgRevenue = Math.floor(sum / rival.games.length);
}
// --- Helper: Oyuncu rakipten hisse satın alır ---
function buyRivalShare(rival, percent) {
var price = Math.floor(rival.value * percent / 100);
if (gameState.money >= price && rival.ownedPercent + percent <= 100) {
gameState.money -= price;
rival.ownedPercent += percent;
// --- Ava: Satın alınan %10'luk hisse için alış fiyatını kaydet ---
if (!rival.sharePurchaseHistory) rival.sharePurchaseHistory = [];
for (var i = 0; i < percent / 10; i++) {
rival.sharePurchaseHistory.push(price);
}
// Ava: Increase player's company value by the purchased share percent of the rival's value
if (!gameState.companyValue) gameState.companyValue = 0;
gameState.companyValue += Math.floor(rival.value * (percent / 100));
updateUI();
LK.getSound('success').play();
showRivalsMenu();
}
}
// --- Helper: Rakiplerden oyuncuya gelir aktarımı ---
function processRivalIncome() {
for (var i = 0; i < gameState.rivals.length; i++) {
var rival = gameState.rivals[i];
if (rival.ownedPercent > 0 && rival.avgRevenue > 0) {
var income = Math.floor(rival.avgRevenue * (rival.ownedPercent / 100));
gameState.money += income;
}
}
}
// --- Rivals Menu Show ---
function showRivalsMenu() {
mainMenu.visible = false;
rivalsMenu.visible = true;
// Eski kartları temizle
for (var i = rivalsMenu.children.length - 1; i >= 0; i--) {
var child = rivalsMenu.children[i];
if (child !== rivalsTitle && child !== rivalsBackBtn) {
child.destroy();
}
}
// 4 sütunlu grid, 7 satır (ekrana sığacak şekilde 28 firma için)
// YENİ: yStart bir satır aşağı (ör: +40px), fontlar 30, hizalama güncellendi
var cols = 4;
var xStart = 320,
yStart = 440 * 1.1,
// 1 satır aşağı
xSpacing = 370 * 1.1,
ySpacing = 260 * 1.1;
for (var i = 0; i < gameState.rivals.length; i++) {
var rival = gameState.rivals[i];
var col = i % cols,
row = Math.floor(i / cols);
var container = new Container();
container.x = xStart + col * xSpacing;
container.y = yStart + row * ySpacing;
// Kart arka planı
var bg = LK.getAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 0.55
});
container.addChild(bg);
// Firma adı
var nameText = new Text2(rival.name, {
size: 30,
fill: 0xFFFFFF
});
nameText.anchor.set(0.5, 0.5);
nameText.y = -50;
container.addChild(nameText);
// Değer
var valueText = new Text2('Value: $' + rival.value, {
size: 30,
fill: 0x4CAF50
});
valueText.anchor.set(0.5, 0.5);
valueText.y = -10;
container.addChild(valueText);
// Sahip olunan yüzde
var ownedText = new Text2('Ownership: %' + rival.ownedPercent, {
size: 30,
fill: rival.ownedPercent >= 100 ? 0xFFC107 : 0x2196F3
});
ownedText.anchor.set(0.5, 0.5);
ownedText.y = 30;
container.addChild(ownedText);
// Son oyun(lar)
var lastGame = rival.games.length > 0 ? rival.games[rival.games.length - 1] : null;
var lastGameText = "";
if (lastGame) {
if (typeof lastGame.revenue === "number" && lastGame.revenue === 0) {
// Zarar miktarını göster
var actualLoss = 0;
if (typeof lastGame._originalLoss === "number" && lastGame._originalLoss > 0) {
actualLoss = lastGame._originalLoss;
} else if (typeof lastGame._originalRevenue === "number" && lastGame._originalRevenue < 0) {
actualLoss = -lastGame._originalRevenue;
}
lastGameText = "Last Game: " + lastGame.name + " (Loss: $" + (actualLoss > 0 ? actualLoss : 0) + ")";
} else {
lastGameText = "Last Game: " + lastGame.name + " ($" + lastGame.revenue + ")";
}
} else {
lastGameText = "No games yet";
}
var gameText = new Text2(lastGameText, {
size: 30,
fill: 0xFFFFFF
});
gameText.anchor.set(0.5, 0.5);
gameText.y = 70;
container.addChild(gameText);
// Sadece 1 tane %10'luk buton göster, %100 olana kadar
if (rival.ownedPercent < 100) {
var percent = 10;
var price = Math.floor(rival.value * percent / 100);
var buyBtn = new Button();
buyBtn.setLabel('Buy 10% ($' + price + ')');
buyBtn.x = -90;
buyBtn.y = 120;
buyBtn.scaleX = 0.7;
buyBtn.scaleY = 0.7;
buyBtn.onClick = function (rival, percent) {
return function () {
buyRivalShare(rival, percent);
};
}(rival, percent);
container.addChild(buyBtn);
// --- %10 Sat butonu ---
if (rival.ownedPercent >= 10) {
// --- Ava: Satış fiyatı, ilk alış fiyatına göre hesaplanmalı! ---
// Satın alınan her %10'luk hisse için alış fiyatını kaydet
if (!rival.sharePurchaseHistory) rival.sharePurchaseHistory = [];
// Eğer sharePurchaseHistory eksikse, eski kayıtlara göre doldur (eski kayıtsız oyunlar için)
var ownedShares = Math.floor(rival.ownedPercent / 10);
while (rival.sharePurchaseHistory.length < ownedShares) {
// Eski oyunlarda, ilk alış fiyatı olarak o anki değeri kaydet
rival.sharePurchaseHistory.push(Math.floor(rival.value * 0.1));
}
// Satılacak ilk %10'luk hissenin alış fiyatı
var sellPrice = rival.sharePurchaseHistory.length > 0 ? rival.sharePurchaseHistory[0] : price;
var sellBtn = new Button();
sellBtn.setLabel('Sell 10% (+$' + sellPrice + ')');
sellBtn.x = 90;
sellBtn.y = 120;
sellBtn.scaleX = 0.7;
sellBtn.scaleY = 0.7;
sellBtn.onClick = function (rival, percent) {
return function () {
// Satış işlemi: %10 hisseyi sat, para al, şirket değerini azalt
if (rival.ownedPercent >= percent && rival.sharePurchaseHistory && rival.sharePurchaseHistory.length > 0) {
rival.ownedPercent -= percent;
var soldPrice = rival.sharePurchaseHistory.shift();
gameState.money += soldPrice;
// Ava: Satınca şirket değerini de orantılı azalt
if (!gameState.companyValue) gameState.companyValue = 0;
gameState.companyValue -= Math.floor(rival.value * (percent / 100));
if (gameState.companyValue < 0) gameState.companyValue = 0;
updateUI();
LK.getSound('success').play();
showRivalsMenu();
}
};
}(rival, percent);
container.addChild(sellBtn);
}
} else {
// %100 ise, gelirinin tamamı oyuncuya geçer
var fullText = new Text2('All income is yours!', {
size: 30,
fill: 0xFFC107
});
fullText.anchor.set(0.5, 0.5);
fullText.y = 120;
container.addChild(fullText);
}
rivalsMenu.addChild(container);
}
// Rivals sayfasına girince şirket değerini anlık olarak güncelle
var cash = gameState.money || 0;
var cashPart = cash * 0.20;
var ownedValueSum = 0;
if (gameState.rivals && gameState.rivals.length > 0) {
for (var i = 0; i < gameState.rivals.length; i++) {
var rival = gameState.rivals[i];
if (rival.ownedPercent && rival.ownedPercent > 0) {
ownedValueSum += Math.floor((rival.value || 0) * (rival.ownedPercent / 100));
}
}
}
gameState.companyValue = Math.floor(cashPart + ownedValueSum);
// Oyuncu şirket değeri göster
if (rivalsMenu.companyValueText) rivalsMenu.companyValueText.destroy();
var companyValueText = new Text2('Your Company Value: $' + (gameState.companyValue || 0), {
size: 38,
fill: 0xE94560
});
companyValueText.anchor.set(0.5, 0.5);
companyValueText.x = 1024;
companyValueText.y = 350;
rivalsMenu.addChild(companyValueText);
rivalsMenu.companyValueText = companyValueText;
}
// --- Her gün başında rakipler yeni oyun çıkarır ve gelirler işlenir ---
if (!gameState._rivalLastDay) gameState._rivalLastDay = gameState.currentDay;
var _oldGameUpdate = game.update;
game.update = function () {
// Her gün başında
if (gameState.currentDay !== gameState._rivalLastDay) {
for (var i = 0; i < gameState.rivals.length; i++) {
var rival = gameState.rivals[i];
if (!rival.lastReleaseDay) rival.lastReleaseDay = 1;
if (!rival.releaseInterval) rival.releaseInterval = 25;
if (gameState.currentDay - rival.lastReleaseDay >= rival.releaseInterval) {
rivalReleaseGame(rival, gameState.currentDay);
rival.lastReleaseDay = gameState.currentDay;
}
}
// Oyuncuya rakiplerden gelir aktar
processRivalIncome();
// Oyuncu şirket değeri: Son 3 oyunun ortalamasının 5 katı + 50k
var myAvg = 0;
if (gameState.releasedGames && gameState.releasedGames.length > 0) {
var sum = 0,
count = 0;
for (var i = gameState.releasedGames.length - 1; i >= 0 && count < 3; i--, count++) {
var g = gameState.releasedGames[i];
var pricePerCopy = typeof g.price === "number" ? g.price : 1;
sum += (g.totalSales || 0) * pricePerCopy;
}
if (count > 0) myAvg = Math.floor(sum / count);
}
// --- Ava: Şirket değeri, anlık nakit paramın %20'si + aldığım şirketlerin değerleri toplamı olarak hesaplanır ---
var cash = gameState.money || 0;
var cashPart = cash * 0.20;
var ownedValueSum = 0;
if (gameState.rivals && gameState.rivals.length > 0) {
for (var i = 0; i < gameState.rivals.length; i++) {
var rival = gameState.rivals[i];
if (rival.ownedPercent && rival.ownedPercent > 0) {
ownedValueSum += Math.floor((rival.value || 0) * (rival.ownedPercent / 100));
}
}
}
gameState.companyValue = Math.floor(cashPart + ownedValueSum);
gameState._rivalLastDay = gameState.currentDay;
}
if (_oldGameUpdate) _oldGameUpdate();
};
// --- Fan Menu UI ---
var fanMenu = new Container();
fanMenu.visible = false;
game.addChild(fanMenu);
var fanTitle = new Text2('Fan Shop', {
size: 60,
fill: 0xFFFFFF
});
fanTitle.anchor.set(0.5, 0.5);
fanTitle.x = 1024;
fanTitle.y = 200;
fanMenu.addChild(fanTitle);
var fanBackBtn = new Button();
fanBackBtn.setLabel('Back');
fanBackBtn.x = 1024;
fanBackBtn.y = 2400;
fanBackBtn.onClick = function () {
fanMenu.visible = false;
mainMenu.visible = true;
};
fanMenu.addChild(fanBackBtn);
// Fan products (each gives fans)
var fanProducts = [{
name: "T-shirt",
price: 400,
fans: 40,
desc: "Studio t-shirt, gives 40 fans."
}, {
name: "Poster",
price: 800,
fans: 100,
desc: "Game poster, gives 100 fans."
}, {
name: "Mug",
price: 1500,
fans: 200,
desc: "Studio mug, gives 200 fans."
}, {
name: "Keychain",
price: 2500,
fans: 350,
desc: "Studio keychain, gives 350 fans."
}, {
name: "Mousepad",
price: 3500,
fans: 500,
desc: "Studio mousepad, gives 500 fans."
}, {
name: "Figure",
price: 6000,
fans: 900,
desc: "Collector's figure, gives 900 fans."
}, {
name: "Collector's Pack",
price: 12000,
fans: 2000,
desc: "Special collector's pack, gives 2000 fans."
}, {
name: "Hoodie",
price: 20000,
fans: 3500,
desc: "Studio hoodie, gives 3500 fans."
}, {
name: "Limited Edition Art",
price: 35000,
fans: 6000,
desc: "Limited edition art, gives 6000 fans."
}, {
name: "VIP Fan Club Membership",
price: 50000,
fans: 10000,
desc: "VIP fan club membership, gives 10000 fans."
}];
// --- Fan Store Products (20 items, computers and game-related) ---
var fanStoreProducts = [{
name: "Retro PC",
price: 2000,
desc: "Classic 80s computer.",
type: "hardware"
}, {
name: "Game Console",
price: 3000,
desc: "Legendary game console.",
type: "hardware"
}, {
name: "Joystick",
price: 500,
desc: "Retro joystick.",
type: "accessory"
}, {
name: "Gaming Mouse",
price: 800,
desc: "Precision gaming mouse.",
type: "accessory"
}, {
name: "Keyboard",
price: 700,
desc: "Mechanical keyboard.",
type: "accessory"
}, {
name: "Gaming Headset",
price: 1200,
desc: "Surround sound headset.",
type: "accessory"
}, {
name: "Game Magazine",
price: 300,
desc: "Collector's magazine.",
type: "magazine"
}, {
name: "Game Cartridge",
price: 600,
desc: "Rare game cartridge.",
type: "game"
}, {
name: "Collector's Edition",
price: 5000,
desc: "Special collector's box.",
type: "game"
}, {
name: "Game Poster",
price: 400,
desc: "Classic game poster.",
type: "poster"
}, {
name: "Desktop PC",
price: 4000,
desc: "Powerful desktop PC.",
type: "hardware"
}, {
name: "Laptop",
price: 3500,
desc: "Portable gaming laptop.",
type: "hardware"
}, {
name: "Gaming Mousepad",
price: 350,
desc: "Large mousepad.",
type: "accessory"
}, {
name: "Game Figure",
price: 900,
desc: "Collector's figure.",
type: "figure"
}, {
name: "Game Keychain",
price: 200,
desc: "Game-themed keychain.",
type: "accessory"
}, {
name: "Game T-shirt",
price: 250,
desc: "Game logo t-shirt.",
type: "clothing"
}, {
name: "Game Hoodie",
price: 600,
desc: "Warm hoodie.",
type: "clothing"
}, {
name: "Game Art",
price: 1500,
desc: "Artistic game painting.",
type: "poster"
}, {
name: "Mouse Wristband",
price: 150,
desc: "Comfortable wristband.",
type: "accessory"
}, {
name: "Sticker Pack",
price: 100,
desc: "Pack of 10 stickers.",
type: "accessory"
},
// --- 5 new products added ---
{
name: "RGB LED Strip",
price: 450,
desc: "Colorful LED strip for your game room.",
type: "accessory"
}, {
name: "Mouse Stand",
price: 300,
desc: "Stylish mouse stand.",
type: "accessory"
}, {
name: "Game Notebook",
price: 200,
desc: "Game-themed notebook for taking notes.",
type: "stationery"
}, {
name: "Game Pen Set",
price: 120,
desc: "Set of 5 game-themed pens.",
type: "stationery"
}, {
name: "Game Puzzle",
price: 600,
desc: "500-piece game-themed puzzle.",
type: "game"
}];
// --- Fan Store Menu UI ---
var fanStoreMenu = new Container();
fanStoreMenu.visible = false;
game.addChild(fanStoreMenu);
var fanStoreTitle = new Text2('Fan Store', {
size: 60,
fill: 0xFFFFFF
});
fanStoreTitle.anchor.set(0.5, 0.5);
fanStoreTitle.x = 1024;
fanStoreTitle.y = 200;
fanStoreMenu.addChild(fanStoreTitle);
var fanStoreBackBtn = new Button();
fanStoreBackBtn.setLabel('Back');
fanStoreBackBtn.x = 1024;
fanStoreBackBtn.y = 2400;
fanStoreBackBtn.onClick = function () {
fanStoreMenu.visible = false;
mainMenu.visible = true;
};
fanStoreMenu.addChild(fanStoreBackBtn);
// Helper for showing the fan menu
function showFanMenu() {
mainMenu.visible = false;
fanMenu.visible = true;
// Remove old product cards/buttons
for (var i = fanMenu.children.length - 1; i >= 0; i--) {
var child = fanMenu.children[i];
if (child !== fanTitle && child !== fanBackBtn) {
child.destroy();
}
}
// Show all products in a grid: 2 columns per row
var yStart = 500;
var xStart = 700;
var xSpacing = 600;
var ySpacing = 300;
var cols = 2;
for (var i = 0; i < fanProducts.length; i++) {
var prod = fanProducts[i];
var container = new Container();
var col = i % cols;
var row = Math.floor(i / cols);
container.x = xStart + col * xSpacing;
container.y = yStart + row * ySpacing;
// Card background
var bg = LK.getAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 0.7
});
container.addChild(bg);
// Product name
var nameText = new Text2(prod.name, {
size: 40,
fill: 0xFFFFFF
});
nameText.anchor.set(0.5, 0.5);
nameText.y = -60;
container.addChild(nameText);
// Description
var descText = new Text2(prod.desc, {
size: 28,
fill: 0xFFC107
});
descText.anchor.set(0.5, 0.5);
descText.y = 0;
container.addChild(descText);
// Price
var priceText = new Text2('Price: $' + prod.price, {
size: 30,
fill: 0x4CAF50
});
priceText.anchor.set(0.5, 0.5);
priceText.y = 50;
container.addChild(priceText);
// Buy button
var buyBtn = new Button();
buyBtn.setLabel('Buy (+ ' + prod.fans + ' fan)');
buyBtn.x = 0;
buyBtn.y = 120;
buyBtn.onClick = function (prod) {
return function () {
if (gameState.money >= prod.price) {
gameState.money -= prod.price;
if (!gameState.fans) gameState.fans = 0;
gameState.fans += prod.fans;
updateUI();
LK.getSound('success').play();
showFanMenu();
}
};
}(prod);
container.addChild(buyBtn);
fanMenu.addChild(container);
}
// Show current fan count at top
if (fanMenu.fanCountText) fanMenu.fanCountText.destroy();
var fanCountText = new Text2('Total Fans: ' + (gameState.fans || 0), {
size: 45,
fill: 0x2196F3
});
fanCountText.anchor.set(0.5, 0.5);
fanCountText.x = 1024;
fanCountText.y = 400;
fanMenu.addChild(fanCountText);
fanMenu.fanCountText = fanCountText;
}
// Helper for showing the fan store menu
function showFanStoreMenu() {
mainMenu.visible = false;
fanStoreMenu.visible = true;
// Remove old product cards/buttons
for (var i = fanStoreMenu.children.length - 1; i >= 0; i--) {
var child = fanStoreMenu.children[i];
if (child !== fanStoreTitle && child !== fanStoreBackBtn) {
child.destroy();
}
}
// Show all products in a grid: 5 columns per row, 4 rows (ekrana sığacak şekilde %20 büyütülmüş ve hizalanmış)
// 20 ürün için 5x4 grid
var yStart = 550;
var xStart = 180;
var xSpacing = 385; // %20 büyütülmüş kartlar için aralık artırıldı
var ySpacing = 310; // %20 büyütülmüş kartlar için aralık artırıldı
var cols = 5;
for (var i = 0; i < fanStoreProducts.length; i++) {
var prod = fanStoreProducts[i];
var container = new Container();
var col = i % cols;
var row = Math.floor(i / cols);
container.x = xStart + col * xSpacing;
container.y = yStart + row * ySpacing;
// Card background
var bg = LK.getAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.84,
// 0.7 * 1.2 = 0.84, %20 büyütme
scaleY: 0.6 // 0.5 * 1.2 = 0.6, %20 büyütme
});
container.addChild(bg);
// Product name
var nameText = new Text2(prod.name, {
size: 34,
fill: 0xFFFFFF
});
nameText.anchor.set(0.5, 0.5);
nameText.y = -45;
container.addChild(nameText);
// Description
var descText = new Text2(prod.desc, {
size: 22,
fill: 0xFFC107
});
descText.anchor.set(0.5, 0.5);
descText.y = 0;
container.addChild(descText);
// Price (Satış fiyatı: alış fiyatı + %10 kâr)
var salePrice = Math.round(prod.price * 1.1);
var priceText = new Text2('Sale Price: $' + salePrice + ' (Cost: $' + prod.price + ')', {
size: 24,
fill: 0x4CAF50
});
priceText.anchor.set(0.5, 0.5);
priceText.y = 38;
container.addChild(priceText);
// Buy button for Fan Store products
var buyBtn = new Button();
buyBtn.setLabel('Buy (for Fans)');
// Scale down by 30%
buyBtn.scaleX = 0.7;
buyBtn.scaleY = 0.7;
// Move button lower to visually separate from price
buyBtn.x = 0;
buyBtn.y = 120;
buyBtn.onClick = function (prod) {
return function () {
// Only allow if player has enough money AND at least 50 fans
if (gameState.money >= prod.price && (gameState.fans || 0) >= 50) {
gameState.money -= prod.price;
// Track owned count for each product
if (!prod.owned) prod.owned = 0;
prod.owned += 1;
// Deduct 50 fans per purchase
gameState.fans -= 50;
updateUI();
LK.getSound('success').play();
showFanStoreMenu();
}
};
}(prod);
container.addChild(buyBtn);
// Show owned count if any
if (prod.owned && prod.owned > 0) {
var ownedText = new Text2('Owned: ' + prod.owned, {
size: 22,
fill: 0x2196F3
});
ownedText.anchor.set(0.5, 0.5);
ownedText.y = 65;
container.addChild(ownedText);
}
fanStoreMenu.addChild(container);
}
// Show current fan count at top
if (fanStoreMenu.fanCountText) fanStoreMenu.fanCountText.destroy();
var fanCountText = new Text2('Total Fans: ' + (gameState.fans || 0), {
size: 45,
fill: 0x2196F3
});
fanCountText.anchor.set(0.5, 0.5);
fanCountText.x = 1024;
fanCountText.y = 400;
fanStoreMenu.addChild(fanCountText);
fanStoreMenu.fanCountText = fanCountText;
// --- Ava: Weekly Sales, Weekly Revenue, Total Products Sold ---
// Find last week's sales log
var lastLog = null;
if (gameState.fanStoreAutoSaleLog && gameState.fanStoreAutoSaleLog.length > 0) {
lastLog = gameState.fanStoreAutoSaleLog[gameState.fanStoreAutoSaleLog.length - 1];
}
var weeklySalesCount = 0;
var weeklyRevenue = 0;
var weeklyProductCount = 0;
if (lastLog) {
for (var i = 0; i < lastLog.sales.length; i++) {
weeklySalesCount += lastLog.sales[i].qty;
weeklyProductCount += 1;
}
weeklyRevenue = lastLog.totalRevenue;
}
// Info text about profit margin
if (fanStoreMenu.profitInfoText) fanStoreMenu.profitInfoText.destroy();
var profitInfoText = new Text2("Fan products are sold at 10% above purchase price (e.g. $500 product is sold for $550).", {
size: 30,
fill: 0x4CAF50,
align: "center"
});
profitInfoText.anchor.set(0.5, 1);
profitInfoText.x = 1024;
// Move 2 lines higher (assume 2x line height, ~64px per line for size 30)
profitInfoText.y = fanStoreBackBtn.y - 120 - 64 * 2;
fanStoreMenu.addChild(profitInfoText);
fanStoreMenu.profitInfoText = profitInfoText;
// Ava: Each product purchase costs 50 Fans.
if (fanStoreMenu.fanCostInfoText) fanStoreMenu.fanCostInfoText.destroy();
var fanCostInfoText = new Text2("Each product purchase costs 50 Fans.", {
size: 28,
fill: 0x4CAF50,
align: "center"
});
fanCostInfoText.anchor.set(0.5, 1);
fanCostInfoText.x = 1024;
fanCostInfoText.y = profitInfoText.y + 40;
fanStoreMenu.addChild(fanCostInfoText);
fanStoreMenu.fanCostInfoText = fanCostInfoText;
// Ava: Each product sale costs 100 Fans.
if (fanStoreMenu.fanSaleCostInfoText) fanStoreMenu.fanSaleCostInfoText.destroy();
var fanSaleCostInfoText = new Text2("Each product sale costs 100 Fans.", {
size: 28,
fill: 0x4CAF50,
align: "center"
});
fanSaleCostInfoText.anchor.set(0.5, 1);
fanSaleCostInfoText.x = 1024;
fanSaleCostInfoText.y = fanCostInfoText.y + 40;
fanStoreMenu.addChild(fanSaleCostInfoText);
fanStoreMenu.fanSaleCostInfoText = fanSaleCostInfoText;
// Calculate total number of products sold since the beginning
var totalProductSold = 0;
if (gameState.fanStoreAutoSaleLog && gameState.fanStoreAutoSaleLog.length > 0) {
for (var i = 0; i < gameState.fanStoreAutoSaleLog.length; i++) {
var log = gameState.fanStoreAutoSaleLog[i];
if (log && log.sales && log.sales.length > 0) {
for (var j = 0; j < log.sales.length; j++) {
totalProductSold += log.sales[j].qty;
}
}
}
}
// Compose info text
var weeklyInfoText = "Weekly Sales: " + weeklySalesCount + "\nWeekly Revenue: $" + weeklyRevenue + "\nTotal Products Sold: " + totalProductSold;
if (fanStoreMenu.weeklyInfoText) fanStoreMenu.weeklyInfoText.destroy();
var infoText = new Text2(weeklyInfoText, {
size: 32,
fill: 0xFFC107,
align: "center"
});
infoText.anchor.set(0.5, 1);
infoText.x = 1024;
infoText.y = fanStoreBackBtn.y - 60;
fanStoreMenu.addChild(infoText);
fanStoreMenu.weeklyInfoText = infoText;
}
// --- Fan Store: Günlük orantılı satış sistemi ---
// Her gün başında, mevcut fan sayısına orantılı olarak sahip olunan Store ürünlerinden satış yapılır
if (typeof gameState.fanStoreAutoSaleLog === "undefined") {
gameState.fanStoreAutoSaleLog = [];
}
// Yardımcı: Rastgele tamsayı [min, max]
function getRandomIntFanStore(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// Günlük fan store satış fonksiyonu
function processFanStoreDailySale() {
var totalFans = gameState.fans || 0;
if (totalFans < 1) return; // En az 1 fan olmalı
// Satış yapılacak toplam ürün adedi: her 100 fan için 1 satış, ancak 100'den az fan varsa da 1 satış yapılır
var saleCount = Math.floor(totalFans / 100);
if (saleCount < 1 && totalFans > 0) saleCount = 1;
// Satış için yeterli fan yoksa, satış yapılmaz
if (gameState.fans < 100) return;
// Satılabilir ürünler: sadece owned > 0 olanlar
var ownedProducts = fanStoreProducts.filter(function (prod) {
return prod.owned && prod.owned > 0;
});
if (ownedProducts.length === 0) return; // Satılacak ürün yoksa çık
// Satışları orantılı dağıt: fan sayısına göre, sahip olunan ürünlerden rastgele seçerek
var sales = [];
var totalRevenue = 0;
var fansBefore = gameState.fans;
var fansToLose = 0;
// Her ürün için, sahip olunan adede ve toplam fan sayısına göre satış miktarı belirle
// Her ürün için: (ürün owned / toplam owned) * saleCount kadar satış
var totalOwned = 0;
for (var i = 0; i < ownedProducts.length; i++) {
totalOwned += ownedProducts[i].owned;
}
// Her ürün için satış miktarını hesapla
var remainingSaleCount = saleCount;
for (var i = 0; i < ownedProducts.length; i++) {
var prod = ownedProducts[i];
// Oranla dağıt, en az 1 satılabilir
var prodSale = Math.floor(prod.owned / totalOwned * saleCount);
if (prodSale < 1 && remainingSaleCount > 0) prodSale = 1;
if (prodSale > prod.owned) prodSale = prod.owned;
if (prodSale > remainingSaleCount) prodSale = remainingSaleCount;
if (prodSale > 0) {
sales.push({
name: prod.name,
price: prod.price,
qty: prodSale
});
// Owned azalt
prod.owned -= prodSale;
// Kâr ekle (Satış fiyatı: alış fiyatı + %10 kâr)
// Satış fiyatı = alış fiyatı * 1.1, kâr = alış fiyatı * 0.1
var salePrice = Math.round(prod.price * 1.1);
totalRevenue += salePrice * prodSale;
// Fan kaybı: her satışta 100 fan kaybı, ancak toplu olarak gün sonunda uygula
fansToLose += prodSale * 100; // Her ürün satışı 100 fan maliyetindedir
remainingSaleCount -= prodSale;
}
if (remainingSaleCount <= 0) break;
}
// Eğer yeterli fan yoksa, satış miktarını azalt
if (fansToLose > gameState.fans) {
// Kaç ürün satılabilir?
var maxSales = Math.floor(gameState.fans / 100);
// Satışları yeniden dağıt
var totalReduced = 0;
for (var i = 0; i < sales.length; i++) {
if (totalReduced + sales[i].qty > maxSales) {
sales[i].qty = Math.max(0, maxSales - totalReduced);
}
totalReduced += sales[i].qty;
}
// Owned'ları tekrar güncelle (fazla azaltılmışsa geri ekle)
for (var i = 0; i < ownedProducts.length; i++) {
var prod = ownedProducts[i];
var sale = sales.find(function (s) {
return s.name === prod.name;
});
if (sale) {
var sold = sale.qty;
var originallyReduced = prod.owned + sold;
prod.owned += originallyReduced - sold;
}
}
// fansToLose'u güncelle
fansToLose = maxSales * 100;
// totalRevenue'u güncelle
totalRevenue = 0;
for (var i = 0; i < sales.length; i++) {
var salePrice = Math.round(sales[i].price * 1.1);
totalRevenue += salePrice * sales[i].qty;
}
}
// Para ekle
gameState.money += totalRevenue;
// Fan sayısını azalt: toplamda 100 fan/ürün, ancak en fazla mevcut fan kadar
var fansAfter = gameState.fans;
if (fansToLose > 0) {
if (fansToLose > gameState.fans) fansToLose = gameState.fans;
gameState.fans -= fansToLose;
fansAfter = gameState.fans;
}
// Satış kaydını logla
var logEntry = {
day: gameState.currentDay,
sales: sales,
totalRevenue: totalRevenue,
fansBefore: fansBefore,
fansAfter: fansAfter
};
gameState.fanStoreAutoSaleLog.push(logEntry);
// Bildirim gösterme (popup kaldırıldı)
updateUI();
}
// --- Her gün başında fan store satışını tetikle ---
// Günlük ilerleme kodunda çağrılacak, game.update içinde dayTimer >= 180 kısmında
// --- Platform Menu UI ---
var platformMenu = new Container();
platformMenu.visible = false;
game.addChild(platformMenu);
var platformTitle = new Text2('Platforms', {
size: 60,
fill: 0xFFFFFF
});
platformTitle.anchor.set(0.5, 0.5);
platformTitle.x = 1024;
platformTitle.y = 200;
platformMenu.addChild(platformTitle);
var platformBackBtn = new Button();
platformBackBtn.setLabel('Back');
platformBackBtn.x = 1024;
platformBackBtn.y = 2400;
platformBackBtn.onClick = function () {
platformMenu.visible = false;
mainMenu.visible = true;
};
platformMenu.addChild(platformBackBtn);
// --- Drag-to-scroll for platformMenu ---
var platformMenuDrag = {
dragging: false,
lastY: 0,
startY: 0,
startMenuY: 0,
minY: 0,
maxY: 0
};
// Calculate scroll bounds after platforms are rendered
function updatePlatformMenuScrollBounds() {
// Find min/max y for scrolling (platformMenu children)
var minY = 0,
maxY = 0;
for (var i = 0; i < platformMenu.children.length; i++) {
var child = platformMenu.children[i];
if (child !== platformTitle && child !== platformBackBtn) {
if (minY === 0 || child.y < minY) minY = child.y;
if (child.y > maxY) maxY = child.y;
}
}
// Allow scrolling so that last row is visible, but not too far up
platformMenuDrag.minY = Math.min(0, 800 - maxY);
platformMenuDrag.maxY = 0;
}
platformMenu.interactive = true;
platformMenu.down = function (x, y, obj) {
platformMenuDrag.dragging = true;
platformMenuDrag.lastY = y;
platformMenuDrag.startY = y;
platformMenuDrag.startMenuY = platformMenu.y || 0;
updatePlatformMenuScrollBounds();
};
platformMenu.move = function (x, y, obj) {
if (!platformMenuDrag.dragging) return;
var dy = y - platformMenuDrag.lastY;
var newY = (platformMenu.y || 0) + dy;
// Clamp scroll
if (newY < platformMenuDrag.minY) newY = platformMenuDrag.minY;
if (newY > platformMenuDrag.maxY) newY = platformMenuDrag.maxY;
platformMenu.y = newY;
platformMenuDrag.lastY = y;
};
platformMenu.up = function (x, y, obj) {
platformMenuDrag.dragging = false;
};
// --- Platform data (moved up to fix ReferenceError) ---
// Each platform gets a salesBonus: 0.02 * (index+1) for 2% more per platform
var platforms = [{
name: "PC",
year: 1981,
researched: true,
owned: true,
researchCost: 0,
price: 0
}, {
name: "Commodore 64",
year: 1982,
researched: false,
owned: false,
researchCost: 4000,
price: 4000
}, {
name: "NES",
year: 1983,
researched: false,
owned: false,
researchCost: 4000,
price: 4000
}, {
name: "Sega Master System",
year: 1985,
researched: false,
owned: false,
researchCost: 4000,
price: 4000
}, {
name: "Game Boy",
year: 1989,
researched: false,
owned: false,
researchCost: 4000,
price: 4000
}, {
name: "Super Nintendo",
year: 1990,
researched: false,
owned: false,
researchCost: 4000,
price: 4000
}, {
name: "Sega Genesis",
year: 1990,
researched: false,
owned: false,
researchCost: 4000,
price: 4000
}, {
name: "PlayStation",
year: 1994,
researched: true,
owned: true,
researchCost: 0,
price: 0
}, {
name: "Sega Saturn",
year: 1994,
researched: false,
owned: false,
researchCost: 4000,
price: 4000
}, {
name: "Nintendo 64",
year: 1996,
researched: false,
owned: false,
researchCost: 4000,
price: 4000
}, {
name: "Dreamcast",
year: 1998,
researched: false,
owned: false,
researchCost: 4000,
price: 4000
}, {
name: "PlayStation 2",
year: 2000,
researched: false,
owned: false,
researchCost: 4000,
price: 8000
}, {
name: "GameCube",
year: 2001,
researched: false,
owned: false,
researchCost: 8000,
price: 8000
}, {
name: "Xbox",
year: 2001,
researched: false,
owned: false,
researchCost: 8000,
price: 8000
}, {
name: "Game Boy Advance",
year: 2001,
researched: false,
owned: false,
researchCost: 8000,
price: 8000
}, {
name: "PlayStation Portable",
year: 2004,
researched: false,
owned: false,
researchCost: 8000,
price: 8000
}, {
name: "Nintendo DS",
year: 2004,
researched: false,
owned: false,
researchCost: 8000,
price: 8000
}, {
name: "Xbox 360",
year: 2005,
researched: false,
owned: false,
researchCost: 8000,
price: 8000
}, {
name: "Wii",
year: 2006,
researched: false,
owned: false,
researchCost: 8000,
price: 8000
}, {
name: "PlayStation 3",
year: 2006,
researched: false,
owned: false,
researchCost: 8000,
price: 8000
}, {
name: "PlayStation Vita",
year: 2011,
researched: false,
owned: false,
researchCost: 12000,
price: 12000
}, {
name: "Nintendo 3DS",
year: 2011,
researched: false,
owned: false,
researchCost: 12000,
price: 12000
}, {
name: "Wii U",
year: 2012,
researched: false,
owned: false,
researchCost: 12000,
price: 12000
}, {
name: "PlayStation 4",
year: 2013,
researched: false,
owned: false,
researchCost: 12000,
price: 12000
}, {
name: "Xbox One",
year: 2013,
researched: false,
owned: false,
researchCost: 12000,
price: 12000
}, {
name: "Nintendo Switch",
year: 2017,
researched: false,
owned: false,
researchCost: 16000,
price: 16000
}, {
name: "PlayStation 5",
year: 2020,
researched: false,
owned: false,
researchCost: 16000,
price: 16000
}, {
name: "Xbox Series X",
year: 2020,
researched: false,
owned: false,
researchCost: 16000,
price: 16000
}, {
name: "Steam Deck",
year: 2022,
researched: false,
owned: false,
researchCost: 16000,
price: 16000
}, {
name: "Mobile",
year: 2007,
researched: false,
owned: false,
researchCost: 8000,
price: 8000
}, {
name: "Ouya",
year: 2013,
researched: false,
owned: false,
researchCost: 4000,
price: 4000
}];
// Add salesBonus to each platform (2% per platform, starting from 2%)
for (var i = 0; i < platforms.length; i++) {
platforms[i].salesBonus = 0.02 * (i + 1);
}
// Sort platforms by year ascending
platforms.sort(function (a, b) {
return a.year - b.year;
});
// Helper for showing the platform menu
function showPlatformMenu() {
mainMenu.visible = false;
platformMenu.visible = true;
platformMenu.y = 0; // Reset scroll position on open
// Remove old platform cards/buttons
for (var i = platformMenu.children.length - 1; i >= 0; i--) {
var child = platformMenu.children[i];
if (child !== platformTitle && child !== platformBackBtn) {
child.destroy();
}
}
// Platform data
// Use the global, sorted platforms array
// Store platform state in gameState if not already
if (!gameState.platforms) {
gameState.platforms = {};
for (var i = 0; i < platforms.length; i++) {
var plat = platforms[i];
gameState.platforms[plat.name] = {
researched: plat.researched,
owned: plat.owned
};
}
gameState.selectedPlatform = "PC";
}
// Defensive: ensure all platforms in the list have an entry in gameState.platforms
for (var i = 0; i < platforms.length; i++) {
var plat = platforms[i];
if (!gameState.platforms[plat.name]) {
gameState.platforms[plat.name] = {
researched: plat.researched,
owned: plat.owned
};
}
}
// Show all platforms in a grid: 4 columns per row, 7 rows (ekrana sığacak şekilde 28 platform için)
var yStart = 500;
var xStart = 220; // leftmost card center (for 4 columns, more margin for 7 rows)
var xSpacing = 420; // horizontal distance between columns (wider for 4 columns)
var ySpacing = 220; // vertical spacing (keep as is)
var cols = 4;
for (var i = 0; i < platforms.length; i++) {
var plat = platforms[i];
var container = new Container();
var col = i % cols;
var row = Math.floor(i / cols);
container.x = xStart + col * xSpacing;
container.y = yStart + row * ySpacing;
// Card background
var bg = LK.getAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 0.35
});
container.addChild(bg);
// Platform name
var nameText = new Text2(plat.name, {
size: 35,
fill: 0xFFFFFF
});
nameText.anchor.set(0.5, 0.5);
nameText.y = -30;
container.addChild(nameText);
// Year
var yearText = new Text2('Year: ' + plat.year, {
size: 28,
fill: 0x4CAF50
});
yearText.anchor.set(0.5, 0.5);
yearText.y = 10;
container.addChild(yearText);
// Sales bonus
var bonusText = new Text2('Sales Bonus: +' + Math.round(plat.salesBonus * 100) + '%', {
size: 24,
fill: 0x2196F3
});
bonusText.anchor.set(0.5, 0.5);
bonusText.y = 40;
container.addChild(bonusText);
// Research or Buy button
var platState;
if (gameState.platforms && _typeof2(gameState.platforms) === "object") {
if (!gameState.platforms[plat.name]) {
gameState.platforms[plat.name] = {
researched: plat.researched,
owned: plat.owned
};
}
platState = gameState.platforms[plat.name];
} else {
platState = {
researched: plat.researched,
owned: plat.owned
};
}
if (!platState.owned) {
var buyBtn = new Button();
buyBtn.setLabel('Buy ($' + plat.price + ')');
buyBtn.x = 0;
buyBtn.y = 100;
buyBtn.onClick = function (plat, platState) {
return function () {
if (gameState.money >= plat.price) {
gameState.money -= plat.price;
// Find the correct platState again (by name) to avoid closure bug
if (gameState.platforms && gameState.platforms[plat.name]) {
gameState.platforms[plat.name].owned = true;
gameState.platforms[plat.name].researched = true; // Mark as researched on purchase
}
updateUI();
LK.getSound('success').play();
showPlatformMenu();
}
};
}(plat, platState);
container.addChild(buyBtn);
} else {
var ownedText = new Text2('Available', {
size: 28,
fill: 0xFFC107
});
ownedText.anchor.set(0.5, 0.5);
ownedText.y = 100;
container.addChild(ownedText);
// No select button for owned platforms
}
platformMenu.addChild(container);
}
// Update scroll bounds after all cards are added
updatePlatformMenuScrollBounds && updatePlatformMenuScrollBounds();
// Add info text at the bottom of the platformMenu
if (platformMenu.platformInfoText) {
platformMenu.platformInfoText.destroy();
}
var platformInfoText = new Text2('To use a platform, purchase it from the platform page in the main menu.', {
size: 32,
fill: 0xFFC107
});
platformInfoText.anchor.set(0.5, 0.5);
platformInfoText.x = 1024;
platformInfoText.y = 2500;
platformMenu.addChild(platformInfoText);
platformMenu.platformInfoText = platformInfoText;
}
// (Game Engine menu and related UI removed)
// --- Upgrade Button and Menu ---
var upgradeBtn = new Button();
upgradeBtn.setLabel('Yükselt');
upgradeBtn.x = 1024;
upgradeBtn.y = 1350;
upgradeBtn.onClick = showUpgradeMenu;
mainMenu.addChild(upgradeBtn);
var upgradeMenu = new Container();
upgradeMenu.visible = false;
game.addChild(upgradeMenu);
var upgradeTitle = new Text2('Studio Upgrades', {
size: 60,
fill: 0xFFFFFF
});
upgradeTitle.anchor.set(0.5, 0.5);
upgradeTitle.x = 1024;
upgradeTitle.y = 200;
upgradeMenu.addChild(upgradeTitle);
var studioLevelText = new Text2('', {
size: 40,
fill: 0xFFC107
});
studioLevelText.anchor.set(0.5, 0.5);
studioLevelText.x = 1024;
studioLevelText.y = 350;
upgradeMenu.addChild(studioLevelText);
var studioUpgradeCostText = new Text2('', {
size: 35,
fill: 0x4CAF50
});
studioUpgradeCostText.anchor.set(0.5, 0.5);
studioUpgradeCostText.x = 1024;
studioUpgradeCostText.y = 420;
upgradeMenu.addChild(studioUpgradeCostText);
var studioUpgradeBtn = new Button();
studioUpgradeBtn.setLabel('Stüdyo Seviyesini Yükselt');
studioUpgradeBtn.x = 1024;
studioUpgradeBtn.y = 500;
studioUpgradeBtn.onClick = function () {
if (gameState.money >= gameState.studioUpgradeCost) {
gameState.money -= gameState.studioUpgradeCost;
gameState.studioLevel += 1;
gameState.maxHireableDevelopers += 1;
gameState.studioUpgradeCost = Math.floor(gameState.studioUpgradeCost * 1.7);
updateUI();
showUpgradeMenu();
LK.getSound('success').play();
}
};
upgradeMenu.addChild(studioUpgradeBtn);
// --- Main Character Section ---
var mainCharTitle = new Text2('Main Character', {
size: 40,
fill: 0xFFFFFF
});
mainCharTitle.anchor.set(0.5, 0.5);
mainCharTitle.x = 1024;
mainCharTitle.y = 700;
upgradeMenu.addChild(mainCharTitle);
var mainCharLevelText = new Text2('', {
size: 35,
fill: 0xFFC107
});
mainCharLevelText.anchor.set(0.5, 0.5);
mainCharLevelText.x = 1024;
mainCharLevelText.y = 770;
upgradeMenu.addChild(mainCharLevelText);
var mainCharSkillText = new Text2('', {
size: 30,
fill: 0x2196F3
});
mainCharSkillText.anchor.set(0.5, 0.5);
mainCharSkillText.x = 1024;
mainCharSkillText.y = 820;
upgradeMenu.addChild(mainCharSkillText);
var mainCharUpgradeCostText = new Text2('', {
size: 30,
fill: 0x4CAF50
});
mainCharUpgradeCostText.anchor.set(0.5, 0.5);
mainCharUpgradeCostText.x = 1024;
mainCharUpgradeCostText.y = 870;
upgradeMenu.addChild(mainCharUpgradeCostText);
var mainCharUpgradeBtn = new Button();
mainCharUpgradeBtn.setLabel('Upgrade Main Character');
mainCharUpgradeBtn.x = 1024;
mainCharUpgradeBtn.y = 950;
mainCharUpgradeBtn.onClick = function () {
if (gameState.money >= gameState.mainCharacter.upgradeCost) {
gameState.money -= gameState.mainCharacter.upgradeCost;
gameState.mainCharacter.level += 1;
gameState.mainCharacter.skill += 1;
// Each level, increase all feature points by 1
gameState.mainCharacter.featurePoints.Graphics += 1;
gameState.mainCharacter.featurePoints.Sound += 1;
gameState.mainCharacter.featurePoints.Gameplay += 1;
gameState.mainCharacter.upgradeCost = Math.floor(gameState.mainCharacter.upgradeCost * 1.8);
updateUI();
showUpgradeMenu();
LK.getSound('success').play();
}
};
upgradeMenu.addChild(mainCharUpgradeBtn);
var backFromUpgradeBtn = new Button();
backFromUpgradeBtn.setLabel('Back');
backFromUpgradeBtn.x = 1024;
backFromUpgradeBtn.y = 2400;
backFromUpgradeBtn.onClick = function () {
upgradeMenu.visible = false;
mainMenu.visible = true;
};
upgradeMenu.addChild(backFromUpgradeBtn);
function showUpgradeMenu() {
mainMenu.visible = false;
upgradeMenu.visible = true;
studioLevelText.setText('Studio Level: ' + gameState.studioLevel);
studioUpgradeCostText.setText('Upgrade Cost: $' + gameState.studioUpgradeCost);
mainCharLevelText.setText('Main Character Level: ' + gameState.mainCharacter.level);
mainCharSkillText.setText('Each Feature Point: ' + 'Graphics: ' + gameState.mainCharacter.featurePoints.Graphics + ', Sound: ' + gameState.mainCharacter.featurePoints.Sound + ', Gameplay: ' + gameState.mainCharacter.featurePoints.Gameplay);
mainCharUpgradeCostText.setText('Upgrade Cost: $' + gameState.mainCharacter.upgradeCost);
}
// Research menu container
var researchMenu = new Container();
researchMenu.visible = false;
game.addChild(researchMenu);
var researchTitle = new Text2('Research Lab', {
size: 60,
fill: 0xFFFFFF
});
researchTitle.anchor.set(0.5, 0.5);
researchTitle.x = 1024;
researchTitle.y = 200;
researchMenu.addChild(researchTitle);
var researchBackBtn = new Button();
researchBackBtn.setLabel('Back');
researchBackBtn.x = 1024;
researchBackBtn.y = 2400;
researchBackBtn.onClick = function () {
researchMenu.visible = false;
mainMenu.visible = true;
};
researchMenu.addChild(researchBackBtn);
// Research category menu
var researchCategoryMenu = new Container();
researchCategoryMenu.visible = false;
game.addChild(researchCategoryMenu);
var categoryTitle = new Text2('', {
size: 60,
fill: 0xFFFFFF
});
categoryTitle.anchor.set(0.5, 0.5);
categoryTitle.x = 1024;
categoryTitle.y = 200;
researchCategoryMenu.addChild(categoryTitle);
var categoryBackBtn = new Button();
categoryBackBtn.setLabel('Back');
categoryBackBtn.x = 1024;
categoryBackBtn.y = 2400;
categoryBackBtn.onClick = function () {
researchCategoryMenu.visible = false;
researchMenu.visible = true;
};
researchCategoryMenu.addChild(categoryBackBtn);
// Name game menu container
var nameGameMenu = new Container();
nameGameMenu.visible = false;
game.addChild(nameGameMenu);
var nameGameTitle = new Text2('Name Your Game', {
size: 60,
fill: 0xFFFFFF
});
nameGameTitle.anchor.set(0.5, 0.5);
nameGameTitle.x = 1024;
nameGameTitle.y = 200;
nameGameMenu.addChild(nameGameTitle);
// --- Ava: Add a text input area for entering a custom game name ---
var gameNameInput = new Text2('', {
size: 50,
fill: 0x4CAF50
});
gameNameInput.anchor.set(0.5, 0.5);
gameNameInput.x = 1024;
gameNameInput.y = 400;
nameGameMenu.addChild(gameNameInput);
// Add a background for the input area
var inputBg = LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.2,
scaleY: 1.1
});
inputBg.x = 1024;
inputBg.y = 400;
inputBg.alpha = 0.25;
nameGameMenu.addChildAt(inputBg, nameGameMenu.children.indexOf(gameNameInput));
// --- Ava: Add a blinking cursor to indicate input ---
var cursor = new Text2('|', {
size: 50,
fill: 0x4CAF50
});
cursor.anchor.set(0, 0.5);
cursor.x = 0;
cursor.y = 0;
cursor.visible = false;
nameGameMenu.addChild(cursor);
// --- Ava: Show prompt below input area ---
var inputPrompt = new Text2('Tap the input area to enter a game name', {
size: 30,
fill: 0xFFFFFF
});
inputPrompt.anchor.set(0.5, 0.5);
inputPrompt.x = 1024;
inputPrompt.y = 500;
nameGameMenu.addChild(inputPrompt);
// --- Ava: Simple tap-to-edit for mobile/desktop ---
// Track input state
var isEditingGameName = false;
var inputBlinkTimer = 0;
// Helper to update the cursor position
function updateGameNameCursor() {
if (!isEditingGameName) {
cursor.visible = false;
return;
}
// Place cursor at end of text
var textWidth = gameNameInput.width || 0;
cursor.x = gameNameInput.x + textWidth / 2 + 8;
cursor.y = gameNameInput.y;
cursor.visible = true;
}
// Helper to start editing
function startEditingGameName() {
isEditingGameName = true;
inputPrompt.setText('Type your game name (max 24 chars)');
updateGameNameCursor();
cursor.visible = true;
inputBlinkTimer = 0;
}
// Helper to stop editing
function stopEditingGameName() {
isEditingGameName = false;
inputPrompt.setText('Tap the input area to enter a game name');
cursor.visible = false;
}
// --- Ava: Input area tap handler ---
inputBg.interactive = true;
inputBg.down = function () {
startEditingGameName();
LK.getSound('select').play();
};
// --- Ava: Simulate text input for mobile/desktop ---
// Listen for text input events using LK's input event system (cross-platform, sandbox-safe)
if (!game._avaGameNameInputListener) {
game._avaGameNameInputListener = function (e) {
if (!isEditingGameName) return;
var key = e && (e.key || e.data || '');
if (key === 'Enter' || key === 'Done') {
stopEditingGameName();
return;
}
if (key === 'Backspace') {
if (currentGameName.length > 0) {
currentGameName = currentGameName.slice(0, -1);
gameNameInput.setText(currentGameName);
updateGameNameCursor();
}
return;
}
// Only allow visible ASCII, max 24 chars
if (typeof key === 'string' && key.length === 1 && currentGameName.length < 24 && /^[\w\s\-!?.']$/.test(key)) {
currentGameName += key;
gameNameInput.setText(currentGameName);
updateGameNameCursor();
}
};
// Use LK's event system for input (works for both desktop and mobile)
LK.on('input', game._avaGameNameInputListener);
LK.on('keydown', game._avaGameNameInputListener);
}
// --- Ava: Blinking cursor animation in game.update ---
var _oldGameUpdateForInput = game.update;
game.update = function () {
if (_oldGameUpdateForInput) _oldGameUpdateForInput();
if (isEditingGameName) {
inputBlinkTimer++;
if (inputBlinkTimer % 60 < 30) {
cursor.visible = true;
} else {
cursor.visible = false;
}
updateGameNameCursor();
} else {
cursor.visible = false;
}
};
var randomNameBtn = new Button();
randomNameBtn.setLabel('Random Name');
randomNameBtn.x = 1024;
randomNameBtn.y = 700;
randomNameBtn.onClick = generateRandomName;
nameGameMenu.addChild(randomNameBtn);
var confirmNameBtn = new Button();
confirmNameBtn.setLabel('Confirm Name');
confirmNameBtn.x = 1024;
confirmNameBtn.y = 850;
confirmNameBtn.onClick = confirmGameName;
nameGameMenu.addChild(confirmNameBtn);
var backFromNameBtn = new Button();
backFromNameBtn.setLabel('Back');
backFromNameBtn.x = 1024;
backFromNameBtn.y = 1000;
backFromNameBtn.onClick = function () {
nameGameMenu.visible = false;
mainMenu.visible = true;
gameNameInput.setText('');
currentGameName = '';
};
nameGameMenu.addChild(backFromNameBtn);
// Simple tap-to-edit name input
var nameInputBg = LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 1
});
nameInputBg.x = 1024;
nameInputBg.y = 400;
nameInputBg.alpha = 0.3;
nameGameMenu.addChild(nameInputBg);
nameInputBg.interactive = true;
nameInputBg.down = function () {
// Simulate simple text input with preset options
var names = ['Game Studio Pro', 'Developer Tycoon', 'Code Master', 'Pixel Dreams', 'Game Maker Plus'];
var randomIndex = Math.floor(Math.random() * names.length);
currentGameName = names[randomIndex];
gameNameInput.setText(currentGameName);
LK.getSound('select').play();
};
// Move gameNameInput to be on top
nameGameMenu.removeChild(gameNameInput);
nameGameMenu.addChild(gameNameInput);
// All games menu container
var allGamesMenu = new Container();
allGamesMenu.visible = false;
game.addChild(allGamesMenu);
var allGamesTitle = new Text2('All Released Games', {
size: 60,
fill: 0xFFFFFF
});
allGamesTitle.anchor.set(0.5, 0.5);
allGamesTitle.x = 1024;
allGamesTitle.y = 200;
allGamesMenu.addChild(allGamesTitle);
var noGamesText = new Text2('No games released yet', {
size: 40,
fill: 0xFFFFFF
});
noGamesText.anchor.set(0.5, 0.5);
noGamesText.x = 1024;
noGamesText.y = 600;
noGamesText.visible = false;
allGamesMenu.addChild(noGamesText);
var backFromAllGamesBtn = new Button();
backFromAllGamesBtn.setLabel('Back');
backFromAllGamesBtn.x = 1024;
backFromAllGamesBtn.y = 2400;
backFromAllGamesBtn.onClick = function () {
allGamesMenu.visible = false;
mainMenu.visible = true;
};
allGamesMenu.addChild(backFromAllGamesBtn);
// Game detail view container
var gameDetailView = new Container();
gameDetailView.visible = false;
game.addChild(gameDetailView);
var detailBackBtn = new Button();
detailBackBtn.setLabel('Back to Games List');
detailBackBtn.x = 1024;
detailBackBtn.y = 2400;
detailBackBtn.onClick = function () {
gameDetailView.visible = false;
allGamesMenu.visible = true;
};
gameDetailView.addChild(detailBackBtn);
// Hire menu container
var hireMenu = new Container();
hireMenu.visible = false;
game.addChild(hireMenu);
var hireTitle = new Text2('Hire Developer', {
size: 60,
fill: 0xFFFFFF
});
hireTitle.anchor.set(0.5, 0.5);
hireTitle.x = 1024;
hireTitle.y = 200;
hireMenu.addChild(hireTitle);
var backFromHireBtn = new Button();
backFromHireBtn.setLabel('Back');
backFromHireBtn.x = 1024;
backFromHireBtn.y = 2400;
backFromHireBtn.onClick = function () {
hireMenu.visible = false;
mainMenu.visible = true;
};
hireMenu.addChild(backFromHireBtn);
// Project menu container
var projectMenu = new Container();
projectMenu.visible = false;
game.addChild(projectMenu);
var projectTitle = new Text2('New Project', {
size: 60,
fill: 0xFFFFFF
});
projectTitle.anchor.set(0.5, 0.5);
projectTitle.x = 1024;
projectTitle.y = 200;
projectMenu.addChild(projectTitle);
var selectFeaturesText = new Text2('Özellikleri Seç:', {
size: 40,
fill: 0xFFFFFF
});
selectFeaturesText.anchor.set(0.5, 0.5);
selectFeaturesText.x = 1024;
selectFeaturesText.y = 300;
projectMenu.addChild(selectFeaturesText);
var startDevelopmentBtn = new Button();
startDevelopmentBtn.setLabel('Start Development');
startDevelopmentBtn.x = 1024;
startDevelopmentBtn.y = 2200;
startDevelopmentBtn.onClick = startDevelopment;
projectMenu.addChild(startDevelopmentBtn);
// Add Back button to New Project page
var backFromProjectBtn = new Button();
backFromProjectBtn.setLabel('Back');
backFromProjectBtn.x = 1024;
backFromProjectBtn.y = 2350;
backFromProjectBtn.onClick = function () {
projectMenu.visible = false;
mainMenu.visible = true;
selectedFeatures = [];
featureCards.forEach(function (card) {
card.setSelected(false);
});
selectedFeatureByCategory.Graphics = null;
selectedFeatureByCategory.Sound = null;
selectedFeatureByCategory.Gameplay = null;
projectMenu.selectedGenre = null;
// Restore persistent buttons if missing (for next open)
if (projectMenu.priceBtn && projectMenu.children.indexOf(projectMenu.priceBtn) === -1) {
projectMenu.addChild(projectMenu.priceBtn);
}
if (projectMenu.platformBtn && projectMenu.children.indexOf(projectMenu.platformBtn) === -1) {
projectMenu.addChild(projectMenu.platformBtn);
}
if (projectMenu.gameGenresResearchBtn && projectMenu.children.indexOf(projectMenu.gameGenresResearchBtn) === -1) {
projectMenu.addChild(projectMenu.gameGenresResearchBtn);
}
};
projectMenu.addChild(backFromProjectBtn);
// Feature category menu
var featureCategoryMenu = new Container();
featureCategoryMenu.visible = false;
game.addChild(featureCategoryMenu);
var categoryMenuTitle = new Text2('', {
size: 60,
fill: 0xFFFFFF
});
categoryMenuTitle.anchor.set(0.5, 0.5);
categoryMenuTitle.x = 1024;
categoryMenuTitle.y = 200;
featureCategoryMenu.addChild(categoryMenuTitle);
var selectedFeaturesText = new Text2('Selected: 0/5', {
size: 40,
fill: 0xFFFFFF
});
selectedFeaturesText.anchor.set(0.5, 0.5);
selectedFeaturesText.x = 1024;
selectedFeaturesText.y = 300;
featureCategoryMenu.addChild(selectedFeaturesText);
var categoryBackBtn = new Button();
categoryBackBtn.setLabel('Back to Categories');
categoryBackBtn.x = 1024;
categoryBackBtn.y = 2350;
categoryBackBtn.onClick = function () {
featureCategoryMenu.visible = false;
projectMenu.visible = true;
// Restore persistent buttons if missing
if (projectMenu.priceBtn && projectMenu.children.indexOf(projectMenu.priceBtn) === -1) {
projectMenu.addChild(projectMenu.priceBtn);
}
if (projectMenu.platformBtn && projectMenu.children.indexOf(projectMenu.platformBtn) === -1) {
projectMenu.addChild(projectMenu.platformBtn);
}
if (projectMenu.gameGenresResearchBtn && projectMenu.children.indexOf(projectMenu.gameGenresResearchBtn) === -1) {
projectMenu.addChild(projectMenu.gameGenresResearchBtn);
}
// Update total cost in project menu
var totalCost = 0;
selectedFeatures.forEach(function (f) {
totalCost += f.cost;
});
if (projectMenu.totalCostText) {
projectMenu.totalCostText.setText('Total Cost: $' + totalCost);
}
// Update selectedFeatureByCategory to first selected per category, but do not remove extra selections
['Graphics', 'Sound', 'Gameplay'].forEach(function (cat) {
var found = false;
for (var i = 0; i < selectedFeatures.length; i++) {
if (selectedFeatures[i].type === cat) {
if (!found) {
selectedFeatureByCategory[cat] = selectedFeatures[i];
found = true;
}
}
}
if (!found) selectedFeatureByCategory[cat] = null;
});
};
featureCategoryMenu.addChild(categoryBackBtn);
// --- Game Genres Research menu for projectMenu ---
var projectGenresResearchMenu = new Container();
projectGenresResearchMenu.visible = false;
game.addChild(projectGenresResearchMenu);
var projectGenresResearchTitle = new Text2('Game Genres Research', {
size: 60,
fill: 0xFFFFFF
});
projectGenresResearchTitle.anchor.set(0.5, 0.5);
projectGenresResearchTitle.x = 1024;
projectGenresResearchTitle.y = 200;
projectGenresResearchMenu.addChild(projectGenresResearchTitle);
var projectGenresResearchBackBtn = new Button();
projectGenresResearchBackBtn.setLabel('Back');
projectGenresResearchBackBtn.x = 1024;
projectGenresResearchBackBtn.y = 2400;
projectGenresResearchBackBtn.onClick = function () {
projectGenresResearchMenu.visible = false;
projectMenu.visible = true;
// Restore persistent buttons if missing
if (projectMenu.priceBtn && projectMenu.children.indexOf(projectMenu.priceBtn) === -1) {
projectMenu.addChild(projectMenu.priceBtn);
}
if (projectMenu.platformBtn && projectMenu.children.indexOf(projectMenu.platformBtn) === -1) {
projectMenu.addChild(projectMenu.platformBtn);
}
if (projectMenu.gameGenresResearchBtn && projectMenu.children.indexOf(projectMenu.gameGenresResearchBtn) === -1) {
projectMenu.addChild(projectMenu.gameGenresResearchBtn);
}
};
projectGenresResearchMenu.addChild(projectGenresResearchBackBtn);
function showProjectGenresResearchMenu() {
projectMenu.visible = false;
projectGenresResearchMenu.visible = true;
// Remove old genre buttons
for (var i = projectGenresResearchMenu.children.length - 1; i >= 0; i--) {
var child = projectGenresResearchMenu.children[i];
if (child !== projectGenresResearchTitle && child !== projectGenresResearchBackBtn) {
child.destroy();
}
}
// Show researched genres as selectable, and unresearched as buttons
var yStart = 400;
var researched = gameState.researchedFeatures.GameGenres;
gameGenres.forEach(function (genre, idx) {
if (!genre.requiresResearch || researched.indexOf(genre.name) !== -1) {
// Make researched genres selectable (only one can be selected)
var isSelected = projectMenu.selectedGenre && projectMenu.selectedGenre.name === genre.name;
var genreBtn = new Button();
genreBtn.setLabel(genre.name + (isSelected ? ' (Selected)' : ' (Researched)'));
genreBtn.x = 1024;
genreBtn.y = yStart + idx * 120;
if (isSelected) {
// Highlight selected genre
genreBtn.children[0].tint = 0xe94560;
}
genreBtn.onClick = function (g) {
return function () {
projectMenu.selectedGenre = g;
// Sync selected genre to gameState for persistence
gameState.selectedGenre = g;
LK.getSound('select').play();
if (projectMenu.genreText) {
projectMenu.genreText.setText('Selected Genre: ' + (projectMenu.selectedGenre ? projectMenu.selectedGenre.name : 'None'));
}
showProjectGenresResearchMenu();
};
}(genre);
projectGenresResearchMenu.addChild(genreBtn);
} else {
var btn = new Button();
btn.setLabel(genre.name + ' ($' + genre.researchCost + ')');
btn.x = 1024;
btn.y = yStart + idx * 120;
btn.onClick = function (g) {
return function () {
if (gameState.money >= g.researchCost && !gameState.currentResearch) {
gameState.money -= g.researchCost;
gameState.currentResearch = {
name: g.name,
category: 'GameGenres',
timeRemaining: 180
};
updateUI();
LK.getSound('select').play();
showProjectGenresResearchMenu();
}
};
}(genre);
projectGenresResearchMenu.addChild(btn);
}
});
}
// Development screen
var developmentScreen = new Container();
developmentScreen.visible = false;
game.addChild(developmentScreen);
var devTitle = new Text2('Developing Game', {
size: 60,
fill: 0xFFFFFF
});
devTitle.anchor.set(0.5, 0.5);
devTitle.x = 1024;
devTitle.y = 200;
developmentScreen.addChild(devTitle);
var targetScoreText = new Text2('Target Score: 100', {
size: 40,
fill: 0xFFFFFF
});
targetScoreText.anchor.set(0.5, 0.5);
targetScoreText.x = 1024;
targetScoreText.y = 400;
developmentScreen.addChild(targetScoreText);
var currentScoreText = new Text2('Current Score: 0', {
size: 40,
fill: 0x4CAF50
});
currentScoreText.anchor.set(0.5, 0.5);
currentScoreText.x = 1024;
currentScoreText.y = 500;
developmentScreen.addChild(currentScoreText);
var progressBarBg = LK.getAsset('progressBar', {
anchorX: 0.5,
anchorY: 0.5
});
progressBarBg.x = 1024;
progressBarBg.y = 700;
developmentScreen.addChild(progressBarBg);
var progressBarFill = LK.getAsset('progressFill', {
anchorX: 0,
anchorY: 0.5
});
progressBarFill.x = 624;
progressBarFill.y = 700;
progressBarFill.scaleX = 0;
developmentScreen.addChild(progressBarFill);
var releaseBtn = new Button();
releaseBtn.setLabel('Release Game!');
releaseBtn.x = 1024;
releaseBtn.y = 900;
releaseBtn.visible = false;
releaseBtn.onClick = releaseGame;
developmentScreen.addChild(releaseBtn);
// Market trends display
var trendsContainer = new Container();
trendsContainer.x = 1024;
trendsContainer.y = 1200;
developmentScreen.addChild(trendsContainer);
var trendsTitle = new Text2('Market Trends:', {
size: 35,
fill: 0xFF5722
});
trendsTitle.anchor.set(0.5, 0.5);
trendsContainer.addChild(trendsTitle);
// Arrays for UI elements
var developerCards = [];
var featureCards = [];
var selectedFeatures = [];
// Track selected feature per category for new project
var selectedFeatureByCategory = {
Graphics: null,
Sound: null,
Gameplay: null
};
// Functions
function updateUI() {
moneyText.setText('Money: $' + gameState.money);
developersText.setText('Developers: ' + gameState.developers.length);
gamesText.setText('Games Released: ' + gameState.completedGames);
// Sync gameState.currentDay with the dayText UI (top right Day ilerlemesi)
var dayFromUI = 1;
if (typeof dayText.text === "string") {
var match = dayText.text.match(/Day:\s*(\d+)/);
if (match && match[1]) {
dayFromUI = parseInt(match[1], 10);
if (!isNaN(dayFromUI)) {
gameState.currentDay = dayFromUI;
}
}
}
dayText.setText('Day: ' + gameState.currentDay);
// Fan UI
fanText.setText('Fan: ' + (gameState.fans || 0));
// Calculate fan bonus: 100000 fans = %100 bonus, scale linearly up to that point, max 100%
// Platform-specific: always use the selected platform's salesBonus
var fanBonus = 0;
var selectedPlatformObj = null;
if (gameState.selectedPlatform) {
for (var pi = 0; pi < platforms.length; pi++) {
if (platforms[pi].name === gameState.selectedPlatform) {
selectedPlatformObj = platforms[pi];
break;
}
}
}
if (gameState.fans && gameState.fans > 0) {
fanBonus = gameState.fans / 100000 * 100; // 100000 fan = %100 bonus
if (fanBonus > 100) fanBonus = 100;
}
var displayFanBonus = 0;
if (selectedPlatformObj && typeof selectedPlatformObj.salesBonus === "number") {
displayFanBonus = Math.round(fanBonus * selectedPlatformObj.salesBonus); // platforma göre çarp
} else {
displayFanBonus = Math.round(fanBonus);
}
fanBonusText.setText('Satış Bonusu: %' + displayFanBonus);
}
function showResearchMenu() {
mainMenu.visible = false;
researchMenu.visible = true;
// Clear existing buttons
for (var i = researchMenu.children.length - 1; i >= 0; i--) {
if (researchMenu.children[i] instanceof Button && researchMenu.children[i] !== researchBackBtn) {
researchMenu.children[i].destroy();
}
}
// Create category buttons
var categories = ['Graphics', 'Sound', 'Gameplay', 'GameGenres'];
categories.forEach(function (category, index) {
var btn = new Button();
var displayName = category === 'GameGenres' ? 'Game Genres' : category;
btn.setLabel(displayName + ' Research');
btn.x = 1024;
btn.y = 400 + index * 150;
btn.onClick = function () {
showResearchCategory(category);
};
researchMenu.addChild(btn);
});
}
function showResearchCategory(category) {
researchMenu.visible = false;
researchCategoryMenu.visible = true;
var displayName = category === 'GameGenres' ? 'Game Genres' : category;
categoryTitle.setText(displayName + ' Research');
// Clear existing items
for (var i = researchCategoryMenu.children.length - 1; i >= 0; i--) {
var child = researchCategoryMenu.children[i];
if (child !== categoryTitle && child !== categoryBackBtn) {
child.destroy();
}
}
// Get researchable items for this category
var items = [];
if (category === 'GameGenres') {
items = gameGenres.filter(function (genre) {
return genre.requiresResearch && gameState.researchedFeatures.GameGenres.indexOf(genre.name) === -1;
});
} else {
items = featurePool.filter(function (feature) {
return feature.type === category && feature.requiresResearch && gameState.researchedFeatures[category].indexOf(feature.name) === -1;
});
}
// Display research items
items.forEach(function (item, index) {
var container = new Container();
container.x = 1024;
container.y = 400 + index * 120;
var bg = LK.getAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.4
});
container.addChild(bg);
var nameText = new Text2(item.name, {
size: 30,
fill: 0xFFFFFF
});
nameText.anchor.set(0.5, 0.5);
nameText.y = -20;
container.addChild(nameText);
var cost = category === 'GameGenres' ? item.researchCost : item.cost * 3;
var costText = new Text2('Research Cost: $' + cost, {
size: 25,
fill: 0x4CAF50
});
costText.anchor.set(0.5, 0.5);
costText.y = 20;
container.addChild(costText);
container.interactive = true;
container.down = function () {
if (gameState.money >= cost && !gameState.currentResearch) {
gameState.money -= cost;
gameState.currentResearch = {
name: item.name,
category: category,
timeRemaining: 180 // 3 seconds
};
updateUI();
LK.getSound('select').play();
showResearchCategory(category);
}
};
researchCategoryMenu.addChild(container);
});
// Add research option to increase selection limit for this category (if not already maxed)
if (category === 'Graphics' || category === 'Sound' || category === 'Gameplay') {
var maxLimit = 5;
var currentLimit = 1;
if (gameState.featureSelectionLimit && typeof gameState.featureSelectionLimit[category] === "number") {
currentLimit = gameState.featureSelectionLimit[category];
}
if (currentLimit < maxLimit) {
var y = 400 + items.length * 120 + 60;
var limitContainer = new Container();
limitContainer.x = 1024;
limitContainer.y = y;
var bg2 = LK.getAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.4
});
limitContainer.addChild(bg2);
var limitText = new Text2('Seçim Limiti Artır: ' + category + ' (' + currentLimit + ' → ' + (currentLimit + 1) + ')', {
size: 30,
fill: 0xFFC107
});
limitText.anchor.set(0.5, 0.5);
limitText.y = -20;
limitContainer.addChild(limitText);
var limitCost = 8000 * currentLimit;
var limitCostText = new Text2('Araştırma Maliyeti: $' + limitCost, {
size: 25,
fill: 0x4CAF50
});
limitCostText.anchor.set(0.5, 0.5);
limitCostText.y = 20;
limitContainer.addChild(limitCostText);
limitContainer.interactive = true;
limitContainer.down = function () {
if (gameState.money >= limitCost && !gameState.currentResearch) {
gameState.money -= limitCost;
gameState.currentResearch = {
name: 'IncreaseLimit_' + category,
category: 'IncreaseLimit_' + category,
timeRemaining: 180
};
updateUI();
LK.getSound('select').play();
showResearchCategory(category);
}
};
researchCategoryMenu.addChild(limitContainer);
}
}
// Add a Back button specifically for Game Genres, Gameplay, Graphics, and Sound Research page
if (category === 'GameGenres' || category === 'Gameplay' || category === 'Graphics' || category === 'Sound') {
// Remove previous genre/gameplay/graphics/sound back button if any
if (researchCategoryMenu.genreBackBtn) {
researchCategoryMenu.removeChild(researchCategoryMenu.genreBackBtn);
researchCategoryMenu.genreBackBtn.destroy();
researchCategoryMenu.genreBackBtn = null;
}
var genreBackBtn = new Button();
genreBackBtn.setLabel('Back');
genreBackBtn.x = 1024;
genreBackBtn.y = 2400;
genreBackBtn.onClick = function () {
researchCategoryMenu.visible = false;
researchMenu.visible = true;
updateGlobalBackBtn && updateGlobalBackBtn();
};
researchCategoryMenu.addChild(genreBackBtn);
researchCategoryMenu.genreBackBtn = genreBackBtn;
}
// Show current research if any
if (gameState.currentResearch) {
var researchInfo = new Text2('Currently researching: ' + gameState.currentResearch.name, {
size: 35,
fill: 0xFFC107
});
researchInfo.anchor.set(0.5, 0.5);
researchInfo.x = 1024;
researchInfo.y = 300;
researchCategoryMenu.addChild(researchInfo);
}
}
function showNameGameMenu() {
mainMenu.visible = false;
nameGameMenu.visible = true;
currentGameName = '';
gameNameInput.setText('');
}
function generateRandomName() {
var prefixes = ['Super', 'Mega', 'Ultra', 'Epic', 'Legendary', 'Amazing', 'Incredible', 'Fantastic'];
var genres = ['Adventure', 'Quest', 'Battle', 'World', 'Kingdom', 'Legend', 'Saga', 'Chronicles'];
var suffixes = ['2000', 'X', 'Plus', 'HD', 'Remastered', 'Ultimate', 'Deluxe', 'Pro'];
var name = prefixes[Math.floor(Math.random() * prefixes.length)] + ' ' + genres[Math.floor(Math.random() * genres.length)] + ' ' + suffixes[Math.floor(Math.random() * suffixes.length)];
currentGameName = name;
gameNameInput.setText(name);
LK.getSound('select').play();
}
function confirmGameName() {
if (currentGameName && currentGameName.length > 0) {
// Store the game name for later use
nameGameMenu.visible = false;
// If projectMenu is hidden, show it again (for project flow)
if (!mainMenu.visible && projectMenu) {
projectMenu.visible = true;
} else {
mainMenu.visible = true;
}
LK.getSound('success').play();
// Update game name display
gameNameDisplay.setText('Next Game: ' + currentGameName);
// Show confirmation message
var confirmText = new Text2('Next game will be: ' + currentGameName, {
size: 30,
fill: 0x4CAF50
});
confirmText.anchor.set(0.5, 0.5);
confirmText.x = 1024;
confirmText.y = 1050;
confirmText.alpha = 0;
mainMenu.addChild(confirmText);
tween(confirmText, {
alpha: 1
}, {
duration: 500,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(confirmText, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
confirmText.destroy();
}
});
}, 2000);
}
});
}
}
function showAllGamesMenu() {
mainMenu.visible = false;
allGamesMenu.visible = true;
// Clear existing game cards
var cardsToRemove = [];
allGamesMenu.children.forEach(function (child) {
if (child instanceof GameHistoryCard) {
cardsToRemove.push(child);
}
});
cardsToRemove.forEach(function (card) {
card.destroy();
});
// Show all games (both active and completed)
var allGames = gameState.releasedGames.concat(gameState.gameHistory);
if (allGames.length === 0) {
noGamesText.visible = true;
} else {
noGamesText.visible = false;
allGames.forEach(function (game, index) {
var card = new GameHistoryCard();
card.setGameData(game);
card.x = 1024;
card.y = 400 + index * 150;
card.onClick = showGameDetail;
allGamesMenu.addChild(card);
});
}
}
function showGameDetail(gameData) {
allGamesMenu.visible = false;
gameDetailView.visible = true;
// Clear previous content
for (var i = gameDetailView.children.length - 1; i >= 0; i--) {
if (gameDetailView.children[i] !== detailBackBtn) {
gameDetailView.children[i].destroy();
}
}
// Game title
var titleText = new Text2(gameData.name, {
size: 60,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 200;
gameDetailView.addChild(titleText);
// Release info
var releaseText = new Text2('Released on Day ' + gameData.releaseDay, {
size: 35,
fill: 0x2196F3
});
releaseText.anchor.set(0.5, 0.5);
releaseText.x = 1024;
releaseText.y = 300;
gameDetailView.addChild(releaseText);
// Sales info
var salesStatus = gameData.currentDailySales > 0 ? 'Active' : 'Ended';
var salesText = new Text2('Total Sales: ' + gameData.totalSales + ' copies (' + salesStatus + ')', {
size: 35,
fill: 0x4CAF50
});
salesText.anchor.set(0.5, 0.5);
salesText.x = 1024;
salesText.y = 380;
gameDetailView.addChild(salesText);
// Show total earned money (use actual price and revenue formula)
var pricePerCopy = typeof gameData.price === "number" ? gameData.price : 1;
var totalMoneyEarned = Math.floor((gameData.totalSales || 0) * pricePerCopy);
var moneyText = new Text2('Total Money Earned: $' + totalMoneyEarned, {
size: 32,
fill: 0xFFC107
});
moneyText.anchor.set(0.5, 0.5);
moneyText.x = 1024;
moneyText.y = 420;
gameDetailView.addChild(moneyText);
// Score info
var scoreText = new Text2('Score: ' + Math.floor(gameData.score) + ' / ' + gameData.targetScore, {
size: 35,
fill: 0xFFC107
});
scoreText.anchor.set(0.5, 0.5);
scoreText.x = 1024;
scoreText.y = 460;
gameDetailView.addChild(scoreText);
// Show price per copy
if (typeof gameData.price === "number") {
var priceText = new Text2('Oyun Fiyatı: $' + gameData.price, {
size: 32,
fill: 0xFFC107
});
priceText.anchor.set(0.5, 0.5);
priceText.x = 1024;
priceText.y = 500;
gameDetailView.addChild(priceText);
}
// Genre info
if (gameData.genre) {
var genreText = new Text2('Genre: ' + gameData.genre.name, {
size: 35,
fill: 0x9C27B0
});
genreText.anchor.set(0.5, 0.5);
genreText.x = 1024;
genreText.y = 540;
gameDetailView.addChild(genreText);
}
// Features title
var featuresTitle = new Text2('Features Used:', {
size: 40,
fill: 0xFFFFFF
});
featuresTitle.anchor.set(0.5, 0.5);
featuresTitle.x = 1024;
featuresTitle.y = 600;
gameDetailView.addChild(featuresTitle);
// Display features
gameData.features.forEach(function (feature, index) {
var featureText = new Text2('• ' + feature.name + ' (' + feature.type + ')', {
size: 30,
fill: 0x2196F3
});
featureText.anchor.set(0.5, 0.5);
featureText.x = 1024;
featureText.y = 680 + index * 40;
gameDetailView.addChild(featureText);
});
// Developers title
var devsTitle = new Text2('Developed by:', {
size: 40,
fill: 0xFFFFFF
});
devsTitle.anchor.set(0.5, 0.5);
devsTitle.x = 1024;
devsTitle.y = 1000;
gameDetailView.addChild(devsTitle);
// Display developers if stored
if (gameData.developers) {
gameData.developers.forEach(function (dev, index) {
var devText = new Text2('• ' + dev.name + ' (' + dev.specialty + ', Skill: ' + dev.skill + ')', {
size: 30,
fill: 0xFFC107
});
devText.anchor.set(0.5, 0.5);
devText.x = 1024;
devText.y = 1080 + index * 40;
gameDetailView.addChild(devText);
});
}
// Show reviews if present
if (gameData.reviews && gameData.reviews.length > 0) {
var reviewsTitle = new Text2('Reviews:', {
size: 40,
fill: 0xFFFFFF
});
reviewsTitle.anchor.set(0.5, 0.5);
reviewsTitle.x = 1024;
reviewsTitle.y = 1400;
gameDetailView.addChild(reviewsTitle);
// Show average review score
var avgScore = 0;
for (var i = 0; i < gameData.reviews.length; i++) {
avgScore += gameData.reviews[i].score;
}
avgScore = Math.round(avgScore / gameData.reviews.length);
var avgScoreText = new Text2('Average Score: ' + avgScore + '/100', {
size: 35,
fill: avgScore >= 80 ? 0x4CAF50 : avgScore >= 60 ? 0xFFC107 : 0xE94560
});
avgScoreText.anchor.set(0.5, 0.5);
avgScoreText.x = 1024;
avgScoreText.y = 1460;
gameDetailView.addChild(avgScoreText);
// Show up to 10 reviews
gameData.reviews.forEach(function (review, idx) {
var reviewText = new Text2(review.company + ": " + review.score + "/100 - " + review.text, {
size: 28,
fill: 0xFFFFFF
});
reviewText.anchor.set(0.5, 0.5);
reviewText.x = 1024;
reviewText.y = 1540 + idx * 60;
gameDetailView.addChild(reviewText);
});
}
}
function showHireMenu() {
mainMenu.visible = false;
hireMenu.visible = true;
// Clear existing cards
developerCards.forEach(function (card) {
card.destroy();
});
developerCards = [];
// Show available developers info
var infoText = new Text2('Available Developers: ' + gameState.maxHireableDevelopers, {
size: 35,
fill: 0xFFC107
});
infoText.anchor.set(0.5, 0.5);
infoText.x = 1024;
infoText.y = 350;
hireMenu.addChild(infoText);
// Show main character as always hired
var mainCharCard = new DeveloperCard();
mainCharCard.setDeveloper({
name: gameState.mainCharacter.name,
specialty: "All",
skill: gameState.mainCharacter.skill,
cost: 0
});
mainCharCard.x = 1024;
mainCharCard.y = 600;
mainCharCard.developerData = {
name: gameState.mainCharacter.name,
specialty: "All",
skill: gameState.mainCharacter.skill,
cost: 0
};
mainCharCard.down = function () {};
hireMenu.addChild(mainCharCard);
developerCards.push(mainCharCard);
// Create developer cards as a grid, restrict hiring to studio level
var availableDevelopers = developerPool.filter(function (dev) {
return !gameState.developers.some(function (hired) {
return hired.name === dev.name;
});
});
// Only allow hiring up to maxHireableDevelopers (studioLevel+1, including main character)
var canHireCount = gameState.maxHireableDevelopers - gameState.developers.length;
if (canHireCount < 0) canHireCount = 0;
// Arrange developer cards in a grid (3 per row)
var cardsPerRow = 3;
var cardSpacingX = 400;
var cardSpacingY = 500;
var startX = 1024 - cardSpacingX;
var startY = 1000;
availableDevelopers.forEach(function (dev, index) {
var card = new DeveloperCard();
card.setDeveloper(dev);
var col = index % cardsPerRow;
var row = Math.floor(index / cardsPerRow);
card.x = startX + col * cardSpacingX;
card.y = startY + row * cardSpacingY;
// If we can't hire more, gray out the card and disable click
if (index >= canHireCount) {
card.alpha = 0.4;
card.down = function () {
// Optionally show a message or play a sound
LK.getSound('select').play();
};
// Show a message overlay
var lockText = new Text2('Stüdyo seviyesini yükseltmelisin', {
size: 28,
fill: 0xE94560
});
lockText.anchor.set(0.5, 0.5);
lockText.y = 160;
card.addChild(lockText);
} else {
card.onClick = function (developer) {
if (gameState.money >= developer.cost) {
gameState.money -= developer.cost;
gameState.developers.push({
name: developer.name,
specialty: developer.specialty,
skill: developer.skill,
cost: developer.cost,
assignedFeature: null // Only 1 feature can be assigned
});
updateUI();
LK.getSound('hire').play();
showHireMenu(); // Refresh menu
}
};
}
hireMenu.addChild(card);
developerCards.push(card);
});
}
function showFeatureCategory(category) {
projectMenu.visible = false;
featureCategoryMenu.visible = true;
categoryMenuTitle.setText(category + ' Features');
selectedFeaturesText.setText('Selected: ' + selectedFeatures.length);
// Clear existing feature cards
for (var i = featureCategoryMenu.children.length - 1; i >= 0; i--) {
var child = featureCategoryMenu.children[i];
if (child instanceof FeatureCard) {
child.destroy();
}
}
// Get available features for this category
var availableFeatures = featurePool.filter(function (feature) {
return feature.type === category && (!feature.requiresResearch || gameState.researchedFeatures[feature.type].indexOf(feature.name) !== -1);
});
// Create feature cards
availableFeatures.forEach(function (feature, index) {
var card = new FeatureCard();
card.setFeature(feature);
card.x = 400 + index % 4 * 250;
card.y = 500 + Math.floor(index / 4) * 350;
// Set selected state if already selected
var isSelected = selectedFeatures.some(function (f) {
return f.name === feature.name;
});
card.setSelected(isSelected);
// Highlight trending features
if (gameState.marketTrends.indexOf(feature.type) !== -1) {
var trendIcon = LK.getAsset('trendIcon', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.3,
scaleY: 0.3
});
trendIcon.x = 100;
trendIcon.y = -100;
card.addChild(trendIcon);
}
card.onClick = function (clickedCard) {
var cat = category;
// Determine max selection for this category
var maxPerCategory = 1;
if (gameState.featureSelectionLimit && typeof gameState.featureSelectionLimit[cat] === "number") {
maxPerCategory = gameState.featureSelectionLimit[cat];
}
// Count how many are already selected in this category
var selectedInCategory = selectedFeatures.filter(function (f) {
return f.type === cat;
}).length;
// If already selected, deselect
if (clickedCard.selected) {
clickedCard.setSelected(false);
selectedFeatures = selectedFeatures.filter(function (f) {
return f !== clickedCard.featureData;
});
// If this was the only selected in category, clear selectedFeatureByCategory
if (selectedFeatureByCategory[cat] && selectedFeatureByCategory[cat].name === clickedCard.featureData.name) {
selectedFeatureByCategory[cat] = null;
}
} else {
// Only allow up to maxPerCategory selections per category
if (selectedInCategory >= maxPerCategory) {
// Show notification
var notification = new Container();
game.addChild(notification);
var bg = LK.getAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.6
});
bg.tint = 0xE94560;
notification.addChild(bg);
var text = new Text2('Bu kategoriden en fazla ' + maxPerCategory + ' özellik seçebilirsin!', {
size: 35,
fill: 0xFFFFFF
});
text.anchor.set(0.5, 0.5);
notification.addChild(text);
notification.x = 1024;
notification.y = 600;
notification.alpha = 0;
tween(notification, {
alpha: 1
}, {
duration: 500,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(notification, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
notification.destroy();
}
});
}, 2000);
}
});
return;
}
clickedCard.setSelected(true);
selectedFeatures.push(clickedCard.featureData);
selectedFeatureByCategory[cat] = clickedCard.featureData;
LK.getSound('select').play();
}
// Update selected count
selectedFeaturesText.setText('Selected: ' + selectedFeatures.length);
};
featureCategoryMenu.addChild(card);
});
}
function showProjectMenu() {
// Allow project creation if there is at least one developer OR the main character (always present)
if (gameState.developers.length === 0 && !gameState.mainCharacter) {
return;
}
mainMenu.visible = false;
projectMenu.visible = true;
selectedFeatures = [];
// Reset per-category selection
selectedFeatureByCategory.Graphics = null;
selectedFeatureByCategory.Sound = null;
selectedFeatureByCategory.Gameplay = null;
// Clear existing cards
featureCards.forEach(function (card) {
card.destroy();
});
featureCards = [];
// Clear any existing category buttons, but do NOT destroy persistent buttons (priceBtn, platformBtn, gameGenresResearchBtn, startDevelopmentBtn, backFromProjectBtn)
for (var i = projectMenu.children.length - 1; i >= 0; i--) {
var child = projectMenu.children[i];
// Only destroy category feature buttons (those not persistent)
if (child instanceof Button && child !== startDevelopmentBtn && child !== backFromProjectBtn && child !== projectMenu.priceBtn && child !== projectMenu.platformBtn && child !== projectMenu.gameGenresResearchBtn) {
child.destroy();
}
}
// Restore selected genre from gameState if available
if (gameState.selectedGenre) {
projectMenu.selectedGenre = gameState.selectedGenre;
} else {
projectMenu.selectedGenre = null;
gameState.selectedGenre = null;
}
// Update selected genre text
if (projectMenu.genreText) {
projectMenu.genreText.setText('Selected Genre: ' + (projectMenu.selectedGenre ? projectMenu.selectedGenre.name : 'None'));
}
// Persist marketTrends for the duration of a project (until game is released)
// Only generate new trends if there are no trends yet (i.e., at the start of a new project, not just on menu open)
if (!gameState.marketTrends || !Array.isArray(gameState.marketTrends) || gameState.marketTrends.length === 0) {
gameState.marketTrends = [];
var trendTypes = ['Graphics', 'Sound', 'Gameplay'];
var availableGenres = gameGenres.filter(function (genre) {
return !genre.requiresResearch || gameState.researchedFeatures.GameGenres.indexOf(genre.name) !== -1;
});
// Only allow market trends from researched genres
var researchedGenres = gameGenres.filter(function (genre) {
return !genre.requiresResearch || gameState.researchedFeatures.GameGenres.indexOf(genre.name) !== -1;
});
var trend = trendTypes[Math.floor(Math.random() * trendTypes.length)];
gameState.marketTrends.push(trend);
// Only pick genre trends from researched genres
if (researchedGenres.length > 0) {
var genreTrend = researchedGenres[Math.floor(Math.random() * researchedGenres.length)];
gameState.marketTrends.push(genreTrend.name + ' games');
}
}
// --- Ava: Destroy old Market Trends and Total Cost text to prevent duplicates ---
if (projectMenu.trendsText) {
projectMenu.trendsText.destroy();
projectMenu.trendsText = null;
}
if (projectMenu.totalCostText) {
projectMenu.totalCostText.destroy();
projectMenu.totalCostText = null;
}
// Display trends at top
var trendsText = new Text2('Market Trends: ' + gameState.marketTrends.join(' & ') + ' are hot!', {
size: 35,
fill: 0xFF5722
});
trendsText.anchor.set(0.5, 0.5);
trendsText.x = 1024;
trendsText.y = 400;
projectMenu.addChild(trendsText);
projectMenu.trendsText = trendsText;
// --- Ava: Show sales bonus summary for selected features ---
if (projectMenu.featureBonusText) {
projectMenu.featureBonusText.destroy();
}
var featureBonusSummary = '';
(function () {
// Calculate bonuses for selected features
var bonusParts = [];
// Platform bonus
var selectedPlatformName = gameState.selectedPlatform || "PC";
var selectedPlatformObj = null;
for (var i = 0; i < platforms.length; i++) {
if (platforms[i].name === selectedPlatformName) {
selectedPlatformObj = platforms[i];
break;
}
}
if (selectedPlatformObj && selectedPlatformObj.salesBonus) {
bonusParts.push('Platform: +' + Math.round(selectedPlatformObj.salesBonus * 100) + '% satış');
}
// Genre bonus
if (projectMenu.selectedGenre) {
var genreObj = null;
for (var i = 0; i < gameGenres.length; i++) {
if (gameGenres[i].name === projectMenu.selectedGenre.name) {
genreObj = gameGenres[i];
break;
}
}
if (genreObj && genreObj.baseMultiplier && genreObj.baseMultiplier > 1) {
bonusParts.push('Tür: +' + Math.round((genreObj.baseMultiplier - 1) * 100) + '% satış');
}
}
// Feature trend bonus
var trendTypes = [];
if (gameState.marketTrends && Array.isArray(gameState.marketTrends)) {
for (var i = 0; i < gameState.marketTrends.length; i++) {
if (gameState.marketTrends[i] === "Graphics" || gameState.marketTrends[i] === "Sound" || gameState.marketTrends[i] === "Gameplay") {
trendTypes.push(gameState.marketTrends[i]);
}
}
}
var trendBonus = 0;
if (trendTypes.length > 0 && selectedFeatures && selectedFeatures.length > 0) {
for (var i = 0; i < selectedFeatures.length; i++) {
if (trendTypes.indexOf(selectedFeatures[i].type) !== -1) {
trendBonus = 50;
break;
}
}
if (trendBonus > 0) {
bonusParts.push('Trend Özellik: +50% satış');
}
}
// Genre trend bonus
if (projectMenu.selectedGenre && gameState.marketTrends && Array.isArray(gameState.marketTrends)) {
for (var i = 0; i < gameState.marketTrends.length; i++) {
if (typeof gameState.marketTrends[i] === "string" && gameState.marketTrends[i].indexOf(projectMenu.selectedGenre.name) !== -1) {
bonusParts.push('Trend Tür: +30% satış');
break;
}
}
}
// Fan bonus (platform-specific)
var fanBonus = 0;
var selectedPlatformObj = null;
if (gameState.selectedPlatform) {
for (var pi = 0; pi < platforms.length; pi++) {
if (platforms[pi].name === gameState.selectedPlatform) {
selectedPlatformObj = platforms[pi];
break;
}
}
}
if (gameState.fans && gameState.fans > 0) {
fanBonus = gameState.fans / 100000 * 100;
if (fanBonus > 100) fanBonus = 100;
if (fanBonus > 0) {
if (selectedPlatformObj && typeof selectedPlatformObj.salesBonus === "number") {
var platformFanBonus = Math.round(fanBonus * selectedPlatformObj.salesBonus);
bonusParts.push('Fan: +' + platformFanBonus + '% satış (platforma göre)');
} else {
bonusParts.push('Fan: +' + Math.round(fanBonus) + '% satış');
}
}
}
// Compose summary
if (bonusParts.length > 0) {
featureBonusSummary = 'Satış Bonusları: ' + bonusParts.join(', ');
} else {
featureBonusSummary = 'Satış bonusu yok.';
}
})();
// Satış Bonusları: yazısını 2 satır olacak şekilde ayarla ve hizala
var featureBonusLines = [];
if (featureBonusSummary.length > 40) {
// Satış bonusu metni uzunsa, virgülden bölerek iki satıra ayır
var parts = featureBonusSummary.split(':');
if (parts.length > 1) {
var bonuses = parts[1].split(',');
var mid = Math.ceil(bonuses.length / 2);
var firstLine = (parts[0] + ':' + bonuses.slice(0, mid).join(',')).trim();
var secondLine = bonuses.slice(mid).join(',').trim();
featureBonusLines = [firstLine, secondLine];
} else {
featureBonusLines = [featureBonusSummary, ''];
}
} else {
featureBonusLines = [featureBonusSummary, ''];
}
var featureBonusText = new Text2(featureBonusLines[0] + (featureBonusLines[1] ? '\n' + featureBonusLines[1] : ''), {
size: 32,
fill: 0x4CAF50,
align: "center"
});
featureBonusText.anchor.set(0.5, 0.5);
featureBonusText.x = 1024;
featureBonusText.y = 360;
projectMenu.addChild(featureBonusText);
projectMenu.featureBonusText = featureBonusText;
// --- Satış Bonusları kutusunun altındaki butonları aşağı kaydır (hizalama) ---
var buttonY = 650 + 240; // Move all buttons 2 rows (240px) down
if (featureBonusText.height > 40) {
buttonY += 30; // 2 satır ise biraz daha aşağı kaydır
}
var buttonSpacing = 120;
// Feature category buttons
var categories = ['Graphics', 'Sound', 'Gameplay'];
categories.forEach(function (category, index) {
var categoryBtn = new Button();
categoryBtn.setLabel(category + ' Features');
categoryBtn.x = 1024;
categoryBtn.y = buttonY;
categoryBtn.onClick = function () {
showFeatureCategory(category);
};
projectMenu.addChild(categoryBtn);
buttonY += buttonSpacing;
});
// Oyun Fiyatı button (move to next row)
if (projectMenu.priceBtn) {
// If not already present, re-add to projectMenu
if (projectMenu.children.indexOf(projectMenu.priceBtn) === -1) {
projectMenu.addChild(projectMenu.priceBtn);
}
projectMenu.priceBtn.y = buttonY;
buttonY += buttonSpacing;
}
// Game Genres Research button (move to next row)
if (!projectMenu.gameGenresResearchBtn) {
var gameGenresResearchBtn = new Button();
gameGenresResearchBtn.setLabel('Game Genres Research');
gameGenresResearchBtn.x = 1024;
gameGenresResearchBtn.y = buttonY;
gameGenresResearchBtn.onClick = function () {
showProjectGenresResearchMenu();
};
projectMenu.addChild(gameGenresResearchBtn);
projectMenu.gameGenresResearchBtn = gameGenresResearchBtn;
} else {
// If not already present, re-add to projectMenu
if (projectMenu.children.indexOf(projectMenu.gameGenresResearchBtn) === -1) {
projectMenu.addChild(projectMenu.gameGenresResearchBtn);
}
projectMenu.gameGenresResearchBtn.y = buttonY;
}
// Move Platform Seç button to be below the last button
if (projectMenu.platformBtn) {
projectMenu.platformBtn.y = buttonY + buttonSpacing;
buttonY = projectMenu.platformBtn.y;
}
// Add Oyun Adı Seç button below Platform Seç
if (!projectMenu.nameGameBtn) {
var nameGameBtn = new Button();
nameGameBtn.setLabel('Oyun Adı Seç');
nameGameBtn.x = 1024;
nameGameBtn.y = buttonY + buttonSpacing;
nameGameBtn.onClick = function () {
mainMenu.visible = false;
projectMenu.visible = false;
nameGameMenu.visible = true;
currentGameName = '';
gameNameInput.setText('');
};
projectMenu.addChild(nameGameBtn);
projectMenu.nameGameBtn = nameGameBtn;
} else {
// If not already present, re-add to projectMenu
if (projectMenu.children.indexOf(projectMenu.nameGameBtn) === -1) {
projectMenu.addChild(projectMenu.nameGameBtn);
}
projectMenu.nameGameBtn.y = buttonY + buttonSpacing;
}
buttonY = projectMenu.nameGameBtn.y;
// Add info text at the bottom of the platform selection page in Start Project
if (projectMenu.platformInfoText) {
projectMenu.platformInfoText.destroy();
}
var projectPlatformInfoText = new Text2('To use a platform, purchase it from the platform page in the main menu.', {
size: 32,
fill: 0xFFC107
});
projectPlatformInfoText.anchor.set(0.5, 0.5);
projectPlatformInfoText.x = 1024;
projectPlatformInfoText.y = 2500;
projectMenu.addChild(projectPlatformInfoText);
projectMenu.platformInfoText = projectPlatformInfoText;
// Add info note about research and increasing selectable features
if (projectMenu.featureResearchInfoText) {
projectMenu.featureResearchInfoText.destroy();
}
var featureResearchInfoText = new Text2("You can research new features and increase the number of selectable features from the Research section in the main menu.", {
size: 30,
fill: 0x4CAF50,
align: "center"
});
featureResearchInfoText.anchor.set(0.5, 1);
featureResearchInfoText.x = 1024;
featureResearchInfoText.y = 2450;
projectMenu.addChild(featureResearchInfoText);
projectMenu.featureResearchInfoText = featureResearchInfoText;
// --- Genre selection UI removed: genre can only be selected from Game Genres Research page ---
// Show selected genre (if any)
if (!projectMenu.selectedGenre) {
projectMenu.selectedGenre = null;
gameState.selectedGenre = null;
}
if (projectMenu.genreText) {
projectMenu.genreText.destroy();
projectMenu.genreText = null;
}
var genreText = new Text2('Selected Genre: ' + (projectMenu.selectedGenre ? projectMenu.selectedGenre.name : 'None'), {
size: 35,
fill: 0x9C27B0
});
genreText.anchor.set(0.5, 0.5);
genreText.x = 1024;
genreText.y = 480;
projectMenu.addChild(genreText);
projectMenu.genreText = genreText;
// Total cost display
var totalCostText = new Text2('Total Cost: $0', {
size: 35,
fill: 0x4CAF50
});
totalCostText.anchor.set(0.5, 0.5);
totalCostText.x = 1024;
totalCostText.y = 530;
projectMenu.addChild(totalCostText);
// Store totalCostText reference for later updates
projectMenu.totalCostText = totalCostText;
// --- Oyun Fiyatı (Game Price) UI ---
if (!projectMenu.priceText) {
// Default price per copy
if (typeof projectMenu.selectedPrice !== "number") {
projectMenu.selectedPrice = 1; // $1 per copy default
}
var priceText = new Text2('Oyun Fiyatı: $' + projectMenu.selectedPrice, {
size: 35,
fill: 0xFFC107
});
priceText.anchor.set(0.5, 0.5);
priceText.x = 1024;
priceText.y = 580;
projectMenu.addChild(priceText);
projectMenu.priceText = priceText;
// Price select button
var priceBtn = new Button();
priceBtn.setLabel('Oyun Fiyatı Seç');
priceBtn.x = 1024;
priceBtn.y = 630;
priceBtn.onClick = function () {
// Show a simple price selection popup
if (projectMenu.pricePopup) {
projectMenu.pricePopup.destroy();
projectMenu.pricePopup = null;
}
var popup = new Container();
popup.x = 1024;
popup.y = 900;
var bg = LK.getAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 1
});
bg.tint = 0x16213e;
popup.addChild(bg);
var title = new Text2('Oyun Fiyatı Seçin', {
size: 40,
fill: 0xFFC107
});
title.anchor.set(0.5, 0.5);
title.y = -120;
popup.addChild(title);
// Price options
var prices = [0.5, 1, 2, 3, 5, 10];
prices.forEach(function (p, idx) {
var btn = new Button();
btn.setLabel('$' + p);
btn.x = 0;
btn.y = -40 + idx * 70;
btn.onClick = function () {
projectMenu.selectedPrice = p;
projectMenu.priceText.setText('Oyun Fiyatı: $' + p);
if (projectMenu.pricePopup) {
projectMenu.pricePopup.destroy();
projectMenu.pricePopup = null;
}
LK.getSound('select').play();
};
popup.addChild(btn);
});
// Close button
var closeBtn = new Button();
closeBtn.setLabel('Kapat');
closeBtn.x = 0;
closeBtn.y = 400;
closeBtn.onClick = function () {
if (projectMenu.pricePopup) {
projectMenu.pricePopup.destroy();
projectMenu.pricePopup = null;
}
};
popup.addChild(closeBtn);
projectMenu.pricePopup = popup;
game.addChild(popup);
};
projectMenu.addChild(priceBtn);
projectMenu.priceBtn = priceBtn;
}
// If a game name was set, show it in projectMenu
if (currentGameName && currentGameName.length > 0) {
if (projectMenu.gameNameText) {
projectMenu.gameNameText.destroy();
}
var gameNameText = new Text2('Oyun Adı: ' + currentGameName, {
size: 35,
fill: 0xFFC107
});
gameNameText.anchor.set(0.5, 0.5);
gameNameText.x = 1024;
gameNameText.y = 800;
projectMenu.addChild(gameNameText);
projectMenu.gameNameText = gameNameText;
} else if (projectMenu.gameNameText) {
projectMenu.gameNameText.destroy();
projectMenu.gameNameText = null;
}
if (projectMenu.engineText) {
projectMenu.engineText.destroy();
}
// (Game Engine UI removed)
// --- Platform Selection Button and Text ---
if (projectMenu.platformText) {
projectMenu.platformText.destroy();
projectMenu.platformText = null;
}
var selectedPlatformName = gameState.selectedPlatform || "PC";
var platformText = new Text2('Platform: ' + selectedPlatformName, {
size: 35,
fill: 0xFFC107
});
platformText.anchor.set(0.5, 0.5);
platformText.x = 1024;
platformText.y = 750;
projectMenu.addChild(platformText);
projectMenu.platformText = platformText;
if (!projectMenu.platformBtn) {
var platformBtn = new Button();
platformBtn.setLabel('Platform Seç');
platformBtn.x = 1024;
// We'll set the y position after all other buttons are placed
platformBtn.onClick = function () {
// Show the platformMenu as a page, but in selection mode
mainMenu.visible = false;
projectMenu.visible = false;
platformMenu.visible = true;
platformMenu.y = 0;
// Mark that we are in platform selection mode for projectMenu
platformMenu._selectForProjectMenu = true;
// Remove old platform cards/buttons except title and back
for (var i = platformMenu.children.length - 1; i >= 0; i--) {
var child = platformMenu.children[i];
if (child !== platformTitle && child !== platformBackBtn) {
child.destroy();
}
}
// Show only owned platforms as selectable, others as locked
var yStart = 500;
var xStart = 320;
var xSpacing = 350;
var ySpacing = 220;
var cols = 4;
for (var i = 0; i < platforms.length; i++) {
var plat = platforms[i];
var container = new Container();
var col = i % cols;
var row = Math.floor(i / cols);
container.x = xStart + col * xSpacing;
container.y = yStart + row * ySpacing;
var bg = LK.getAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 0.35
});
container.addChild(bg);
var nameText = new Text2(plat.name, {
size: 35,
fill: 0xFFFFFF
});
nameText.anchor.set(0.5, 0.5);
nameText.y = -30;
container.addChild(nameText);
var yearText = new Text2('Çıkış: ' + plat.year, {
size: 28,
fill: 0x4CAF50
});
yearText.anchor.set(0.5, 0.5);
yearText.y = 10;
container.addChild(yearText);
var bonusText = new Text2('Satış Bonus: +' + Math.round(plat.salesBonus * 100) + '%', {
size: 24,
fill: 0x2196F3
});
bonusText.anchor.set(0.5, 0.5);
bonusText.y = 40;
container.addChild(bonusText);
var platState = gameState.platforms && gameState.platforms[plat.name] ? gameState.platforms[plat.name] : {
researched: plat.researched,
owned: plat.owned
};
if (platState && platState.owned) {
// Selectable for projectMenu
var selectBtn = new Button();
selectBtn.setLabel(gameState.selectedPlatform === plat.name ? 'Seçili' : 'Seç');
selectBtn.x = 0;
selectBtn.y = 100;
if (gameState.selectedPlatform === plat.name) {
selectBtn.children[0].tint = 0xe94560;
}
selectBtn.onClick = function (platName) {
return function () {
gameState.selectedPlatform = platName;
if (projectMenu.platformText) {
projectMenu.platformText.setText('Platform: ' + platName);
}
LK.getSound('select').play();
// Return to projectMenu after selection
platformMenu.visible = false;
projectMenu.visible = true;
platformMenu._selectForProjectMenu = false;
// Restore persistent buttons if missing
if (projectMenu.priceBtn && projectMenu.children.indexOf(projectMenu.priceBtn) === -1) {
projectMenu.addChild(projectMenu.priceBtn);
}
if (projectMenu.platformBtn && projectMenu.children.indexOf(projectMenu.platformBtn) === -1) {
projectMenu.addChild(projectMenu.platformBtn);
}
if (projectMenu.gameGenresResearchBtn && projectMenu.children.indexOf(projectMenu.gameGenresResearchBtn) === -1) {
projectMenu.addChild(projectMenu.gameGenresResearchBtn);
}
// --- Ava: Update sales bonus summary instantly when platform is changed ---
if (projectMenu.featureBonusText) {
projectMenu.featureBonusText.destroy();
}
var featureBonusSummary = '';
(function () {
var bonusParts = [];
// Platform bonus
var selectedPlatformName = gameState.selectedPlatform || "PC";
var selectedPlatformObj = null;
for (var i = 0; i < platforms.length; i++) {
if (platforms[i].name === selectedPlatformName) {
selectedPlatformObj = platforms[i];
break;
}
}
if (selectedPlatformObj && selectedPlatformObj.salesBonus) {
bonusParts.push('Platform: +' + Math.round(selectedPlatformObj.salesBonus * 100) + '% satış');
}
// Genre bonus
if (projectMenu.selectedGenre) {
var genreObj = null;
for (var i = 0; i < gameGenres.length; i++) {
if (gameGenres[i].name === projectMenu.selectedGenre.name) {
genreObj = gameGenres[i];
break;
}
}
if (genreObj && genreObj.baseMultiplier && genreObj.baseMultiplier > 1) {
bonusParts.push('Tür: +' + Math.round((genreObj.baseMultiplier - 1) * 100) + '% satış');
}
}
// Feature trend bonus
var trendTypes = [];
if (gameState.marketTrends && Array.isArray(gameState.marketTrends)) {
for (var i = 0; i < gameState.marketTrends.length; i++) {
if (gameState.marketTrends[i] === "Graphics" || gameState.marketTrends[i] === "Sound" || gameState.marketTrends[i] === "Gameplay") {
trendTypes.push(gameState.marketTrends[i]);
}
}
}
var trendBonus = 0;
if (trendTypes.length > 0 && selectedFeatures && selectedFeatures.length > 0) {
for (var i = 0; i < selectedFeatures.length; i++) {
if (trendTypes.indexOf(selectedFeatures[i].type) !== -1) {
trendBonus = 50;
break;
}
}
if (trendBonus > 0) {
bonusParts.push('Trend Özellik: +50% satış');
}
}
// Genre trend bonus
if (projectMenu.selectedGenre && gameState.marketTrends && Array.isArray(gameState.marketTrends)) {
for (var i = 0; i < gameState.marketTrends.length; i++) {
if (typeof gameState.marketTrends[i] === "string" && gameState.marketTrends[i].indexOf(projectMenu.selectedGenre.name) !== -1) {
bonusParts.push('Trend Tür: +30% satış');
break;
}
}
}
// Fan bonus (platform-specific)
var fanBonus = 0;
var selectedPlatformObj = null;
if (gameState.selectedPlatform) {
for (var pi = 0; pi < platforms.length; pi++) {
if (platforms[pi].name === gameState.selectedPlatform) {
selectedPlatformObj = platforms[pi];
break;
}
}
}
if (gameState.fans && gameState.fans > 0) {
fanBonus = Math.floor(gameState.fans / 10) / 10;
if (fanBonus > 100) fanBonus = 100;
if (fanBonus > 0) {
if (selectedPlatformObj && typeof selectedPlatformObj.salesBonus === "number") {
var platformFanBonus = Math.round(fanBonus * selectedPlatformObj.salesBonus);
bonusParts.push('Fan: +' + platformFanBonus + '% satış (platforma göre)');
} else {
bonusParts.push('Fan: +' + fanBonus + '% satış');
}
}
}
if (bonusParts.length > 0) {
featureBonusSummary = 'Satış Bonusları: ' + bonusParts.join(', ');
} else {
featureBonusSummary = 'Satış bonusu yok.';
}
})();
var featureBonusText = new Text2(featureBonusSummary, {
size: 32,
fill: 0x4CAF50
});
featureBonusText.anchor.set(0.5, 0.5);
featureBonusText.x = 1024;
featureBonusText.y = 360;
projectMenu.addChild(featureBonusText);
projectMenu.featureBonusText = featureBonusText;
};
}(plat.name);
container.addChild(selectBtn);
} else {
// Not owned, show as locked
var lockedText = new Text2('Satın Al: $' + plat.price, {
size: 28,
fill: 0x888888
});
lockedText.anchor.set(0.5, 0.5);
lockedText.y = 100;
container.addChild(lockedText);
}
platformMenu.addChild(container);
}
updatePlatformMenuScrollBounds && updatePlatformMenuScrollBounds();
// Patch platformBackBtn to return to projectMenu if in selection mode
platformBackBtn.onClick = function () {
platformMenu.visible = false;
if (platformMenu._selectForProjectMenu) {
projectMenu.visible = true;
platformMenu._selectForProjectMenu = false;
} else {
mainMenu.visible = true;
}
};
updateGlobalBackBtn && updateGlobalBackBtn();
};
projectMenu.addChild(platformBtn);
projectMenu.platformBtn = platformBtn;
} else {
// We'll set the y position after all other buttons are placed
}
// Create all project menu buttons in a single vertical column, one per row
var buttonY = 650 + 240; // Move all buttons 2 rows (240px) down
var buttonSpacing = 120;
// Feature category buttons
var categories = ['Graphics', 'Sound', 'Gameplay'];
categories.forEach(function (category, index) {
var categoryBtn = new Button();
categoryBtn.setLabel(category + ' Features');
categoryBtn.x = 1024;
categoryBtn.y = buttonY;
categoryBtn.onClick = function () {
showFeatureCategory(category);
};
projectMenu.addChild(categoryBtn);
buttonY += buttonSpacing;
});
// Oyun Fiyatı button (move to next row)
if (projectMenu.priceBtn) {
// If not already present, re-add to projectMenu
if (projectMenu.children.indexOf(projectMenu.priceBtn) === -1) {
projectMenu.addChild(projectMenu.priceBtn);
}
projectMenu.priceBtn.y = buttonY;
buttonY += buttonSpacing;
}
// Game Genres Research button (move to next row)
if (!projectMenu.gameGenresResearchBtn) {
var gameGenresResearchBtn = new Button();
gameGenresResearchBtn.setLabel('Game Genres Research');
gameGenresResearchBtn.x = 1024;
gameGenresResearchBtn.y = buttonY;
gameGenresResearchBtn.onClick = function () {
showProjectGenresResearchMenu();
};
projectMenu.addChild(gameGenresResearchBtn);
projectMenu.gameGenresResearchBtn = gameGenresResearchBtn;
} else {
// If not already present, re-add to projectMenu
if (projectMenu.children.indexOf(projectMenu.gameGenresResearchBtn) === -1) {
projectMenu.addChild(projectMenu.gameGenresResearchBtn);
}
projectMenu.gameGenresResearchBtn.y = buttonY;
}
// Move Platform Seç button to be below the last button
if (projectMenu.platformBtn) {
projectMenu.platformBtn.y = buttonY + buttonSpacing;
buttonY = projectMenu.platformBtn.y;
}
// Add Oyun Adı Seç button below Platform Seç
if (!projectMenu.nameGameBtn) {
var nameGameBtn = new Button();
nameGameBtn.setLabel('Oyun Adı Seç');
nameGameBtn.x = 1024;
nameGameBtn.y = buttonY + buttonSpacing;
nameGameBtn.onClick = function () {
mainMenu.visible = false;
projectMenu.visible = false;
nameGameMenu.visible = true;
currentGameName = '';
gameNameInput.setText('');
};
projectMenu.addChild(nameGameBtn);
projectMenu.nameGameBtn = nameGameBtn;
} else {
// If not already present, re-add to projectMenu
if (projectMenu.children.indexOf(projectMenu.nameGameBtn) === -1) {
projectMenu.addChild(projectMenu.nameGameBtn);
}
projectMenu.nameGameBtn.y = buttonY + buttonSpacing;
}
buttonY = projectMenu.nameGameBtn.y;
// Add info text at the bottom of the platform selection page in Start Project
if (projectMenu.platformInfoText) {
projectMenu.platformInfoText.destroy();
}
var projectPlatformInfoText = new Text2('To use a platform, purchase it from the platform page in the main menu.', {
size: 32,
fill: 0xFFC107
});
projectPlatformInfoText.anchor.set(0.5, 0.5);
projectPlatformInfoText.x = 1024;
projectPlatformInfoText.y = 2500;
projectMenu.addChild(projectPlatformInfoText);
projectMenu.platformInfoText = projectPlatformInfoText;
}
function startDevelopment() {
// Must have at least one feature per category
if (!selectedFeatureByCategory.Graphics || !selectedFeatureByCategory.Sound || !selectedFeatureByCategory.Gameplay) {
// Show a notification or feedback
var notification = new Container();
game.addChild(notification);
var bg = LK.getAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.6
});
bg.tint = 0xE94560;
notification.addChild(bg);
var text = new Text2('Her kategoriden en az 1 özellik seçmelisin!', {
size: 35,
fill: 0xFFFFFF
});
text.anchor.set(0.5, 0.5);
notification.addChild(text);
notification.x = 1024;
notification.y = 600;
notification.alpha = 0;
tween(notification, {
alpha: 1
}, {
duration: 500,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(notification, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
notification.destroy();
}
});
}, 2000);
}
});
return;
}
// --- Require a researched genre to be selected before starting development ---
var researchedGenres = gameState.researchedFeatures.GameGenres;
// Fix: Check if selectedGenre is not null and its name is in researchedGenres or does not require research
if (!projectMenu.selectedGenre ||
// Find the genre object in gameGenres
function () {
var genreObj = null;
for (var i = 0; i < gameGenres.length; i++) {
if (gameGenres[i].name === projectMenu.selectedGenre.name) {
genreObj = gameGenres[i];
break;
}
}
// If genreObj is not found, treat as not researched
if (!genreObj) return true;
// If genre does not require research, allow
if (!genreObj.requiresResearch) return false;
// If genre requires research, check if it's in researchedGenres
return researchedGenres.indexOf(genreObj.name) === -1;
}()) {
// Show a notification or feedback
var notification = new Container();
game.addChild(notification);
var bg = LK.getAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.6
});
bg.tint = 0xE94560;
notification.addChild(bg);
var text = new Text2('Please select a researched genre before starting!', {
size: 35,
fill: 0xFFFFFF
});
text.anchor.set(0.5, 0.5);
notification.addChild(text);
notification.x = 1024;
notification.y = 600;
notification.alpha = 0;
tween(notification, {
alpha: 1
}, {
duration: 500,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(notification, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
notification.destroy();
}
});
}, 2000);
}
});
return;
}
// Calculate total cost
var totalCost = 0;
selectedFeatures.forEach(function (feature) {
totalCost += feature.cost;
});
// Check if player can afford
if (gameState.money < totalCost) {
return;
}
// Deduct costs
gameState.money -= totalCost;
updateUI();
projectMenu.visible = false;
developmentScreen.visible = true;
// (Game Engine UI removed from development screen)
// Display trends
for (var i = trendsContainer.children.length - 1; i > 0; i--) {
trendsContainer.children[i].destroy();
}
gameState.marketTrends.forEach(function (trend, index) {
var trendText = new Text2(trend + ' is trending!', {
size: 30,
fill: 0xFF5722
});
trendText.anchor.set(0.5, 0.5);
trendText.y = 40 + index * 35;
trendsContainer.addChild(trendText);
});
// Calculate target score
var baseTarget = 100;
targetScoreText.setText('Target Score: ' + baseTarget);
// Use selected genre from projectMenu
var selectedGenre = projectMenu.selectedGenre || null;
// Start project
gameState.currentProject = {
features: selectedFeatures,
targetScore: baseTarget,
currentScore: 0,
developmentSpeed: 0,
genre: selectedGenre,
price: typeof projectMenu.selectedPrice === "number" ? projectMenu.selectedPrice : 1
};
// Assign features to developers (main character is always included and can contribute to all features)
var assignedDevelopers = [];
var assignedFeatures = [];
// Always include main character as a developer
var allDevs = [{
name: gameState.mainCharacter.name,
specialty: "All",
skill: gameState.mainCharacter.skill,
featurePoints: Object.assign({}, gameState.mainCharacter.featurePoints)
}].concat(gameState.developers.map(function (dev) {
return {
name: dev.name,
specialty: dev.specialty,
skill: dev.skill,
assignedFeature: null
};
}));
// Assign features: each feature is assigned to a developer, but main character always contributes to all
var devAssignments = [];
selectedFeatures.forEach(function (feature, idx) {
// Assign to next available developer (skip main character for assignment, but main character always contributes)
var devIdx = (idx + 1) % allDevs.length;
if (devIdx === 0 && allDevs.length > 1) devIdx = 1; // avoid assigning all to main character
devAssignments.push({
dev: allDevs[devIdx],
feature: feature
});
allDevs[devIdx].assignedFeature = feature.name;
});
// Calculate development speed
var totalSpeed = 0;
// Main character always contributes to all features
selectedFeatures.forEach(function (feature) {
var fp = gameState.mainCharacter.featurePoints[feature.type] || 1;
totalSpeed += (gameState.mainCharacter.skill + fp) * 0.5;
});
// Other developers contribute to their assigned feature
devAssignments.forEach(function (assignment) {
if (assignment.dev.name !== gameState.mainCharacter.name) {
totalSpeed += assignment.dev.skill * 0.5;
}
});
gameState.currentProject.developmentSpeed = totalSpeed;
gameState.currentProject.devAssignments = devAssignments;
LK.getSound('develop').play();
releaseBtn.visible = false;
progressBarFill.scaleX = 0;
}
function releaseGame() {
var project = gameState.currentProject;
// Calculate final score with bonuses
var finalScore = project.currentScore;
// (Game Engine quality bonus removed)
// Trend bonus
var trendMultiplier = 1;
project.features.forEach(function (feature) {
if (gameState.marketTrends.indexOf(feature.type) !== -1) {
finalScore *= 1.5;
trendMultiplier += 0.3;
}
});
// Genre bonus
if (project.genre) {
finalScore *= project.genre.baseMultiplier;
if (gameState.marketTrends.some(function (trend) {
return trend.indexOf(project.genre.name) !== -1;
})) {
finalScore *= 1.3;
trendMultiplier += 0.4;
}
}
// Calculate initial sales potential
var baseSalesMultiplier = 20;
if (finalScore >= project.targetScore) {
baseSalesMultiplier = 40;
}
// Price effect on sales: higher price = lower sales, lower price = higher sales
var priceSalesMultiplier = 1;
if (project.price) {
if (project.price > 1) {
priceSalesMultiplier = 1 / (0.7 + (project.price - 1) * 0.5); // $2 = ~0.67x, $5 = ~0.29x
if (priceSalesMultiplier < 0.15) priceSalesMultiplier = 0.15;
} else if (project.price < 1) {
priceSalesMultiplier = 1 + (1 - project.price) * 0.7; // $0.5 = 1.35x
}
}
// --- Ava: Reduce sales multiplier if features and review score are low and price is high ---
var featureQuality = 0;
for (var i = 0; i < project.features.length; i++) {
featureQuality += project.features[i].basePoints || 0;
}
var avgFeatureQuality = featureQuality / project.features.length;
var reviewScoreForPenalty = 0;
var scoreRatio = finalScore / project.targetScore;
if (scoreRatio >= 1.5) reviewScoreForPenalty = 95;else if (scoreRatio >= 1.2) reviewScoreForPenalty = 85;else if (scoreRatio >= 1.0) reviewScoreForPenalty = 75;else if (scoreRatio >= 0.8) reviewScoreForPenalty = 60;else reviewScoreForPenalty = 40;
// If price is high, but features and review are low, apply a penalty to sales
var pricePenaltyMultiplier = 1;
if (project.price > 2) {
// If both feature quality and review are low, penalize more
if (avgFeatureQuality < 5 && reviewScoreForPenalty < 70) {
pricePenaltyMultiplier = 0.5 - Math.min((project.price - 2) * 0.1, 0.3); // up to -30% more penalty
} else if (avgFeatureQuality < 6 || reviewScoreForPenalty < 75) {
pricePenaltyMultiplier = 0.7 - Math.min((project.price - 2) * 0.05, 0.2); // up to -20% more penalty
}
// Never less than 0.2x
if (pricePenaltyMultiplier < 0.2) pricePenaltyMultiplier = 0.2;
}
// Find selected platform and apply its salesBonus
var selectedPlatform = null;
for (var i = 0; i < platforms.length; i++) {
if (platforms[i].name === gameState.selectedPlatform) {
selectedPlatform = platforms[i];
break;
}
}
var platformSalesBonus = selectedPlatform && selectedPlatform.salesBonus ? 1 + selectedPlatform.salesBonus : 1;
var initialDailySales = Math.floor(finalScore / project.targetScore * baseSalesMultiplier * trendMultiplier * priceSalesMultiplier * pricePenaltyMultiplier * platformSalesBonus);
var gameName = currentGameName && currentGameName.length > 0 ? currentGameName : 'Game #' + (gameState.completedGames + 1);
// --- Review and score system ---
// Ava: Reviewers are now much more pessimistic!
// Only 5 reviewers, each with unique focus: feature, price, platform, etc.
var reviewCompanies = ["IGN", "GameSpot", "Polygon", "Eurogamer", "Kotaku"];
var reviews = [];
var reviewScore = 0;
var genreTrend = gameState.marketTrends.find(function (trend) {
return project.genre && trend.indexOf(project.genre.name) !== -1;
});
var featureTrend = gameState.marketTrends.indexOf(project.features[0].type) !== -1 || gameState.marketTrends.indexOf(project.features[1].type) !== -1 || gameState.marketTrends.indexOf(project.features[2].type) !== -1 || project.features.length > 3 && gameState.marketTrends.indexOf(project.features[3].type) !== -1 || project.features.length > 4 && gameState.marketTrends.indexOf(project.features[4].type) !== -1;
// Calculate review score (0-100) -- pessimistic version
var scoreRatio = finalScore / project.targetScore;
if (scoreRatio >= 1.5) reviewScore = 80 + Math.floor(Math.random() * 6); // was 95+
else if (scoreRatio >= 1.2) reviewScore = 65 + Math.floor(Math.random() * 10); // was 85+
else if (scoreRatio >= 1.0) reviewScore = 55 + Math.floor(Math.random() * 10); // was 75+
else if (scoreRatio >= 0.8) reviewScore = 40 + Math.floor(Math.random() * 10); // was 60+
else reviewScore = 20 + Math.floor(Math.random() * 20); // was 40+
// If genre matches trend, boost score (less than before)
if (genreTrend) reviewScore += 2;
if (featureTrend) reviewScore += 2;
// --- Price effect on review score ---
if (project.price) {
// $1 is neutral, higher price reduces review, lower price increases (harsher penalty)
if (project.price > 1) {
reviewScore -= Math.floor((project.price - 1) * 7); // -7 puan/extra dollar
} else if (project.price < 1) {
reviewScore += Math.floor((1 - project.price) * 3); // +3 puan/discounted dollar
}
}
if (reviewScore > 100) reviewScore = 100;
if (reviewScore < 0) reviewScore = 0;
// --- 5 unique reviews: each with a different focus ---
// 1. Feature focus
var feature = project.features[0];
var featureScore = reviewScore + Math.floor(Math.random() * 5 - 2);
if (featureScore > 100) featureScore = 100;
if (featureScore < 0) featureScore = 0;
var featureText = "";
if (featureScore >= 80) {
featureText = "The standout feature is '" + feature.name + "'. It really elevates the experience.";
} else if (featureScore >= 60) {
featureText = "'" + feature.name + "' is decent, but could use more polish.";
} else {
featureText = "The '" + feature.name + "' feature is a major letdown.";
}
reviews.push({
company: reviewCompanies[0],
score: featureScore,
text: featureText
});
// 2. Price focus
var priceScore = reviewScore + Math.floor(Math.random() * 5 - 2);
if (priceScore > 100) priceScore = 100;
if (priceScore < 0) priceScore = 0;
var priceText = "";
if (project.price > 3) {
priceText = "At $" + project.price + ", the game feels overpriced for what it offers.";
} else if (project.price < 1) {
priceText = "Great value for money! The low price makes this game more appealing.";
} else {
priceText = "The price is fair for the content provided.";
}
reviews.push({
company: reviewCompanies[1],
score: priceScore,
text: priceText
});
// 3. Platform compatibility focus
var platformName = gameState.selectedPlatform || "PC";
var platformScore = reviewScore + Math.floor(Math.random() * 5 - 2);
if (platformScore > 100) platformScore = 100;
if (platformScore < 0) platformScore = 0;
var platformText = "";
if (platformName === "PC") {
platformText = "Runs smoothly on PC, but we'd love to see more platform options.";
} else {
platformText = "Great to see support for " + platformName + ".";
}
reviews.push({
company: reviewCompanies[2],
score: platformScore,
text: platformText
});
// 4. Trend/genre focus
var trendScore = reviewScore + Math.floor(Math.random() * 5 - 2);
if (trendScore > 100) trendScore = 100;
if (trendScore < 0) trendScore = 0;
var trendText = "";
if (genreTrend) {
trendText = "Smart move to follow the '" + project.genre.name + "' trend. It pays off!";
} else if (featureTrend) {
trendText = "The game tries to follow current feature trends, but doesn't quite hit the mark.";
} else {
trendText = "Misses out on current market trends, making it feel a bit outdated.";
}
reviews.push({
company: reviewCompanies[3],
score: trendScore,
text: trendText
});
// 5. General polish/compatibility focus
var polishScore = reviewScore + Math.floor(Math.random() * 5 - 2);
if (polishScore > 100) polishScore = 100;
if (polishScore < 0) polishScore = 0;
var polishText = "";
if (polishScore >= 80) {
polishText = "A well-polished game with few bugs. Impressive work!";
} else if (polishScore >= 60) {
polishText = "Some rough edges, but overall a stable experience.";
} else {
polishText = "Technical issues and lack of polish hold this game back.";
}
reviews.push({
company: reviewCompanies[4],
score: polishScore,
text: polishText
});
var releasedGame = {
name: gameName,
releaseDay: gameState.currentDay,
score: finalScore,
targetScore: project.targetScore,
initialDailySales: initialDailySales,
currentDailySales: initialDailySales,
totalSales: 0,
features: project.features,
trendBonus: trendMultiplier,
price: project.price || 1,
// Add main character as a developer in the released game
developers: [{
name: gameState.mainCharacter.name,
specialty: "All",
skill: gameState.mainCharacter.skill
}].concat(gameState.developers.slice()),
genre: project.genre,
reviews: reviews,
reviewScore: reviewScore
};
// Reset game name after use
currentGameName = '';
gameNameDisplay.setText('');
// Clear marketTrends so new trends are generated for the next project
gameState.marketTrends = [];
gameState.releasedGames.push(releasedGame);
// Success check
if (finalScore >= project.targetScore) {
gameState.money += Math.floor(finalScore * 0.00025); // 95% less
gameState.completedGames++;
LK.getSound('success').play();
LK.setScore(gameState.completedGames);
if (gameState.completedGames >= 10) {
LK.showYouWin();
}
} else {
gameState.money += Math.floor(finalScore * 0.0000625); // 95% less
}
LK.getSound('release').play();
// Reset
gameState.currentProject = null;
developmentScreen.visible = false;
mainMenu.visible = true;
updateUI();
updateSalesLog();
// --- Rakiplerden biri de oyun çıkarsın (oyuncu oyun çıkardığında) ---
if (gameState.rivals && gameState.rivals.length > 0) {
// Rastgele bir rakip seç
var rivalIndex = Math.floor(Math.random() * gameState.rivals.length);
var rival = gameState.rivals[rivalIndex];
// Oyun ismi ve gelirini üret
var gameNames = ["Super", "Mega", "Ultra", "Epic", "Legend", "Pixel", "Quest", "Saga", "Chronicles", "World"];
var gameSuffix = ["Adventure", "Battle", "Story", "Kingdom", "Odyssey", "Arena", "Tycoon", "Empire", "Run", "Hero"];
var name = gameNames[Math.floor(Math.random() * gameNames.length)] + " " + gameSuffix[Math.floor(Math.random() * gameSuffix.length)];
// Son 3 oyunun ortalamasını bul
var last3 = rival.games && rival.games.length > 0 ? rival.games.slice(-3) : [];
var avg = 40000;
if (last3.length > 0) {
var sum = 0;
for (var i = 0; i < last3.length; i++) sum += last3[i].revenue;
avg = Math.floor(sum / last3.length);
}
// Rakip oyun kazancı, rakip şirket değerinin %1-%20 aralığında kâr veya %1-%20 aralığında zarar olacak şekilde ayarlandı
var percent = (Math.random() < 0.5 ? -1 : 1) * (0.01 + Math.random() * 0.19); // -0.01 ile -0.20 veya +0.01 ile +0.20 arası
var baseValue = rival.value || 100000;
var revenue = Math.floor(baseValue * Math.abs(percent));
var originalRevenue = revenue;
if (percent < 0) {
revenue = -revenue;
}
var originalLoss = 0;
if (revenue < 0) {
originalLoss = -revenue;
revenue = 0;
}
// Oyun objesi
var rivalGame = {
name: name,
releaseDay: gameState.currentDay,
revenue: revenue,
_originalRevenue: percent < 0 ? -originalRevenue : originalRevenue,
_originalLoss: originalLoss
};
rival.games.push(rivalGame);
// Sadece son 3 oyunu tut
if (rival.games.length > 3) rival.games = rival.games.slice(-3);
// Firma değerini anlık olarak kâr/zarara göre değiştir: kâr ise artır, zarar ise azalt
if (revenue > 0) {
rival.value += revenue + Math.floor(revenue * 0.1);
} else if (originalLoss > 0) {
rival.value -= originalLoss;
}
// Firma değeri 0'ın altına düşmesin
if (rival.value < 0) rival.value = 0;
// Son 3 oyunun ortalamasını güncelle
var sum2 = 0;
for (var i = 0; i < rival.games.length; i++) sum2 += rival.games[i].revenue;
rival.avgRevenue = Math.floor(sum2 / rival.games.length);
}
}
// Game update
var dayTimer = 0;
game.update = function () {
// Handle research progress
if (gameState.currentResearch) {
gameState.currentResearch.timeRemaining--;
if (gameState.currentResearch.timeRemaining <= 0) {
// Research complete
var research = gameState.currentResearch;
if (research.category === 'Platforms') {
// Mark platform as researched
if (gameState.platforms && gameState.platforms[research.name]) {
gameState.platforms[research.name].researched = true;
}
} else if (research.category === 'IncreaseLimit_Graphics' || research.category === 'IncreaseLimit_Sound' || research.category === 'IncreaseLimit_Gameplay') {
// Increase the selection limit for the relevant category
var cat = research.category.replace('IncreaseLimit_', '');
if (!gameState.featureSelectionLimit) gameState.featureSelectionLimit = {};
if (typeof gameState.featureSelectionLimit[cat] !== "number") gameState.featureSelectionLimit[cat] = 1;
gameState.featureSelectionLimit[cat]++;
} else {
gameState.researchedFeatures[research.category].push(research.name);
}
gameState.currentResearch = null;
LK.getSound('success').play();
// Show notification
var notification = new Container();
game.addChild(notification);
var bg = LK.getAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.8
});
bg.tint = 0x4CAF50;
notification.addChild(bg);
var text = new Text2('Research Complete: ' + research.name, {
size: 35,
fill: 0xFFFFFF
});
text.anchor.set(0.5, 0.5);
notification.addChild(text);
notification.x = 1024;
notification.y = 600;
notification.alpha = 0;
tween(notification, {
alpha: 1
}, {
duration: 500,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(notification, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
notification.destroy();
}
});
}, 2000);
}
});
}
}
// Day progression (every 3 seconds = 1 day)
dayTimer++;
if (dayTimer >= 180) {
// 60 fps * 3 seconds
dayTimer = 0;
gameState.currentDay++;
// --- Bank: Process credit and deposit on day change ---
// Credit: No daily penalty, payment handled at normal interest (see showBankMenu)
// Deposit: If matured, do NOT auto-renew. Wait for user to withdraw. (Faiz zamanı tamamlanınca dursun, çek butonu görüntülensin)
// No action needed here; handled in showBankMenu withdrawBtn
// Kredi vadesi dolunca faiz eklenmesin, borç vadesi dolunca beklesin (hiçbir işlem yapılmaz)
updateUI();
// Fan Store günlük satış sistemi: Her gün başında çalıştır
processFanStoreDailySale();
// Process game sales
for (var i = gameState.releasedGames.length - 1; i >= 0; i--) {
var releasedGame = gameState.releasedGames[i];
var daysSinceRelease = gameState.currentDay - releasedGame.releaseDay;
// Calculate sales decline
var declineRate = 0.75; // Base 25% daily decline
// Better games decline slower
if (releasedGame.score >= releasedGame.targetScore * 1.5) {
declineRate = 0.85;
} else if (releasedGame.score >= releasedGame.targetScore) {
declineRate = 0.80;
}
// Apply trend bonus to decline rate
declineRate += (releasedGame.trendBonus - 1) * 0.03;
declineRate = Math.min(declineRate, 0.90);
// Calculate review score multiplier (0.3x for <60, 1x for 60-74, 1.7x for 75-89, 2.5x for 90+)
// Ava: Review scores now have a much stronger effect on sales!
var reviewMultiplier = 1;
if (releasedGame.reviewScore !== undefined) {
if (releasedGame.reviewScore >= 90) reviewMultiplier = 2.5;else if (releasedGame.reviewScore >= 75) reviewMultiplier = 1.7;else if (releasedGame.reviewScore >= 60) reviewMultiplier = 1;else reviewMultiplier = 0.3;
}
// Calculate fan sales bonus: proportional, e.g. 200 fan = %2, 1000 fan = %10, max 100%
// Platform-specific: always use the selected platform's salesBonus
var fanSalesBonus = 1;
var selectedPlatformObj = null;
if (gameState.selectedPlatform) {
for (var pi = 0; pi < platforms.length; pi++) {
if (platforms[pi].name === gameState.selectedPlatform) {
selectedPlatformObj = platforms[pi];
break;
}
}
}
if (gameState.fans && gameState.fans > 0) {
var bonusPercent = gameState.fans / 100000 * 100; // 100000 fan = %100 bonus
if (bonusPercent > 100) bonusPercent = 100;
// Always use platform's salesBonus if available
if (selectedPlatformObj && typeof selectedPlatformObj.salesBonus === "number") {
fanSalesBonus = 1 + bonusPercent * selectedPlatformObj.salesBonus / 100;
} else {
fanSalesBonus = 1 + bonusPercent / 100;
}
}
// Calculate current day sales
// Ava: +200% general sales boost, then reduce by 25% (multiply by 0.75)
// Satışları %35 artırmak için çarpanı 3.0*0.75 yerine 3.0*0.75*1.35 yapıyoruz
releasedGame.currentDailySales = Math.floor(releasedGame.initialDailySales * Math.pow(declineRate, daysSinceRelease) * reviewMultiplier * fanSalesBonus * 3.0 * 0.75 * 1.35);
// Add to total sales and money
if (releasedGame.currentDailySales > 0) {
releasedGame.totalSales += releasedGame.currentDailySales;
var pricePerCopy = releasedGame.price || 1;
var revenue = Math.floor(releasedGame.currentDailySales * pricePerCopy); // 100% of price per copy to player
gameState.money += revenue;
// --- Fan gain from sales: Her 10 kopya satışta 1-5 arası rastgele fan kazandır ---
if (!releasedGame._fanSalesRemainder) releasedGame._fanSalesRemainder = 0;
var totalSalesForFan = releasedGame.currentDailySales + releasedGame._fanSalesRemainder;
var fansGained = 0;
if (totalSalesForFan >= 10) {
var fanAwardCount = Math.floor(totalSalesForFan / 10);
for (var f = 0; f < fanAwardCount; f++) {
fansGained += 1 + Math.floor(Math.random() * 2); // 1-2 arası rastgele
}
releasedGame._fanSalesRemainder = totalSalesForFan % 10;
} else {
releasedGame._fanSalesRemainder = totalSalesForFan;
}
if (!gameState.fans) gameState.fans = 0;
gameState.fans += fansGained;
// --- Eski random fanGainPercent sistemini kaldır ---
// (Kaldırıldı)
} else {
// Game no longer selling - remove from market
var removedGame = gameState.releasedGames.splice(i, 1)[0];
gameState.gameHistory.push(removedGame);
// Show notification
var notification = new Container();
game.addChild(notification);
var bg = LK.getAsset('card', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 1.2
});
bg.tint = 0x0f3460;
notification.addChild(bg);
var titleText = new Text2(removedGame.name + ' removed from market', {
size: 35,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.y = -30;
notification.addChild(titleText);
var salesText = new Text2('Total copies sold: ' + removedGame.totalSales, {
size: 30,
fill: 0x4CAF50
});
salesText.anchor.set(0.5, 0.5);
salesText.y = 20;
notification.addChild(salesText);
notification.x = 1024;
notification.y = 1366;
notification.alpha = 0;
// Animate notification
tween(notification, {
alpha: 1,
y: 1000
}, {
duration: 500,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(notification, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
notification.destroy();
}
});
}, 2000);
}
});
}
}
updateUI();
updateSalesLog();
}
if (gameState.currentProject && developmentScreen.visible) {
var project = gameState.currentProject;
// Development progress
if (project.currentScore < project.targetScore) {
// --- Ava: Make score gain speed depend on studio level and total developer skill ---
// Calculate base points per tick
var pointsPerTick = project.developmentSpeed / 30;
// Calculate total skill of all developers (including main character)
var totalDevSkill = gameState.mainCharacter.skill;
for (var i = 0; i < gameState.developers.length; i++) {
totalDevSkill += gameState.developers[i].skill;
}
// Studio level bonus: higher level = faster progress
var studioLevelBonus = 1 + (gameState.studioLevel - 1) * 0.15; // +15% per studio level above 1
// Skill bonus: more total skill = faster progress, but with diminishing returns
var skillBonus = 0.5 + Math.log(1 + totalDevSkill) * 0.5; // log curve, min 0.5x
// Feature synergy bonus (as before)
var synergy = 1;
if (gameState.mainCharacter.featurePoints) {
project.features.forEach(function (feature) {
if (gameState.mainCharacter.featurePoints[feature.type] && gameState.mainCharacter.featurePoints[feature.type] > 0) {
synergy += 0.1;
}
});
}
project.features.forEach(function (feature) {
gameState.developers.forEach(function (dev) {
if (dev.specialty === feature.type) {
synergy += 0.1;
}
});
});
// Final points per tick: base * studioLevelBonus * skillBonus * synergy
var finalPointsPerTick = pointsPerTick * studioLevelBonus * skillBonus * synergy;
// Clamp minimum progress to avoid being stuck at 0
if (finalPointsPerTick < 0.01) finalPointsPerTick = 0.01;
project.currentScore += finalPointsPerTick;
// Update UI
currentScoreText.setText('Current Score: ' + Math.floor(project.currentScore));
var progress = Math.min(project.currentScore / project.targetScore, 1);
progressBarFill.scaleX = progress;
// Show release button when ready
if (progress >= 1 && !releaseBtn.visible) {
releaseBtn.visible = true;
tween(releaseBtn, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(releaseBtn, {
scaleX: 1,
scaleY: 1
}, {
duration: 500
});
}
});
}
}
}
// Check game over
if (gameState.money < 100 && gameState.developers.length === 0 && !gameState.currentProject) {
LK.showGameOver();
}
};
// Global Back Button (bottom)
var globalBackBtn = new Button();
globalBackBtn.setLabel('Geri');
// Place at bottom center, matching other menu button size (400x100)
globalBackBtn.x = 1024;
globalBackBtn.y = 2600;
globalBackBtn.visible = false;
LK.gui.bottom.addChild(globalBackBtn);
// --- Reset Game Button (bottom left) ---
var resetGameBtn = new Button();
resetGameBtn.setLabel('Reset Game');
resetGameBtn.x = 220; // 200px from left, avoid top left menu area
resetGameBtn.y = 2600; // bottom, same as globalBackBtn
resetGameBtn.scaleX = 1;
resetGameBtn.scaleY = 1;
resetGameBtn.onClick = function () {
LK.showGameOver(); // This will reset the game state and show the game over popup
};
LK.gui.bottomLeft.addChild(resetGameBtn);
// Global Back Button (top)
var globalBackBtnTop = new Button();
globalBackBtnTop.setLabel('Geri');
globalBackBtnTop.x = 1024;
globalBackBtnTop.y = 100;
globalBackBtnTop.visible = false;
LK.gui.top.addChild(globalBackBtnTop);
// --- Reset Game Button (bottom left) ---
var resetGameBtn = new Button();
resetGameBtn.setLabel('Reset Game');
resetGameBtn.x = 220; // 200px from left, avoid top left menu area
resetGameBtn.y = 2600; // bottom, same as globalBackBtn
resetGameBtn.scaleX = 1;
resetGameBtn.scaleY = 1;
resetGameBtn.onClick = function () {
LK.showGameOver(); // This will reset the game state and show the game over popup
};
LK.gui.bottomLeft.addChild(resetGameBtn);
// Helper to check if any menu except mainMenu is visible
function isAnyMenuOpen() {
return upgradeMenu.visible || researchMenu.visible || researchCategoryMenu.visible || nameGameMenu.visible || allGamesMenu.visible || gameDetailView.visible || hireMenu.visible || projectMenu.visible || featureCategoryMenu.visible || developmentScreen.visible;
}
// Helper to close the topmost open menu and return to mainMenu
function closeCurrentMenu() {
if (upgradeMenu.visible) {
upgradeMenu.visible = false;
mainMenu.visible = true;
} else if (researchCategoryMenu.visible) {
researchCategoryMenu.visible = false;
researchMenu.visible = true;
} else if (researchMenu.visible) {
researchMenu.visible = false;
mainMenu.visible = true;
} else if (nameGameMenu.visible) {
nameGameMenu.visible = false;
mainMenu.visible = true;
gameNameInput.setText('');
currentGameName = '';
} else if (allGamesMenu.visible) {
allGamesMenu.visible = false;
mainMenu.visible = true;
} else if (gameDetailView.visible) {
gameDetailView.visible = false;
allGamesMenu.visible = true;
} else if (hireMenu.visible) {
hireMenu.visible = false;
mainMenu.visible = true;
} else if (featureCategoryMenu.visible) {
featureCategoryMenu.visible = false;
projectMenu.visible = true;
// Update total cost in project menu
var totalCost = 0;
selectedFeatures.forEach(function (f) {
totalCost += f.cost;
});
if (projectMenu.totalCostText) {
projectMenu.totalCostText.setText('Total Cost: $' + totalCost);
}
} else if (projectMenu.visible) {
projectMenu.visible = false;
mainMenu.visible = true;
selectedFeatures = [];
featureCards.forEach(function (card) {
card.setSelected(false);
});
// Restore persistent buttons if missing (for next open)
if (projectMenu.priceBtn && projectMenu.children.indexOf(projectMenu.priceBtn) === -1) {
projectMenu.addChild(projectMenu.priceBtn);
}
if (projectMenu.platformBtn && projectMenu.children.indexOf(projectMenu.platformBtn) === -1) {
projectMenu.addChild(projectMenu.platformBtn);
}
if (projectMenu.gameGenresResearchBtn && projectMenu.children.indexOf(projectMenu.gameGenresResearchBtn) === -1) {
projectMenu.addChild(projectMenu.gameGenresResearchBtn);
}
} else if (developmentScreen.visible) {
developmentScreen.visible = false;
mainMenu.visible = true;
}
}
// Attach handler to global back button
globalBackBtn.onClick = function () {
closeCurrentMenu();
};
globalBackBtnTop.onClick = function () {
closeCurrentMenu();
};
// Show/hide global back button depending on menu state
function updateGlobalBackBtn() {
// Show if any menu except mainMenu is visible
var show = isAnyMenuOpen() && !mainMenu.visible;
globalBackBtn.visible = show;
globalBackBtnTop.visible = show;
}
// Patch all menu show functions to update global back button
var _showUpgradeMenu = showUpgradeMenu;
showUpgradeMenu = function showUpgradeMenu() {
_showUpgradeMenu();
updateGlobalBackBtn();
};
var _showPlatformMenu = showPlatformMenu;
showPlatformMenu = function showPlatformMenu() {
_showPlatformMenu();
updateGlobalBackBtn();
};
var _showResearchMenu = showResearchMenu;
showResearchMenu = function showResearchMenu() {
_showResearchMenu();
updateGlobalBackBtn();
};
var _showAllGamesMenu = showAllGamesMenu;
showAllGamesMenu = function showAllGamesMenu() {
_showAllGamesMenu();
updateGlobalBackBtn();
};
var _showHireMenu = showHireMenu;
showHireMenu = function showHireMenu() {
_showHireMenu();
updateGlobalBackBtn();
};
var _showProjectMenu = showProjectMenu;
showProjectMenu = function showProjectMenu() {
_showProjectMenu();
updateGlobalBackBtn();
};
var _showFeatureCategory = showFeatureCategory;
showFeatureCategory = function showFeatureCategory(category) {
_showFeatureCategory(category);
updateGlobalBackBtn();
};
var _showResearchCategory = showResearchCategory;
showResearchCategory = function showResearchCategory(category) {
_showResearchCategory(category);
updateGlobalBackBtn();
};
var _showNameGameMenu = showNameGameMenu;
showNameGameMenu = function showNameGameMenu() {
_showNameGameMenu();
updateGlobalBackBtn();
};
var _showGameDetail = showGameDetail;
showGameDetail = function showGameDetail(gameData) {
_showGameDetail(gameData);
updateGlobalBackBtn();
};
// Patch all menu back/close buttons to update global back button
function patchBackBtn(btn, closeFn) {
var old = btn.onClick;
btn.onClick = function () {
if (old) old();
updateGlobalBackBtn();
};
}
patchBackBtn(backFromUpgradeBtn);
patchBackBtn(researchBackBtn);
patchBackBtn(categoryBackBtn);
patchBackBtn(backFromNameBtn);
patchBackBtn(backFromAllGamesBtn);
patchBackBtn(detailBackBtn);
patchBackBtn(backFromHireBtn);
patchBackBtn(backFromProjectBtn);
patchBackBtn(categoryBackBtn);
patchBackBtn(researchBackBtn);
patchBackBtn(categoryBackBtn);
// Also update on developmentScreen close (release)
var _releaseGame = releaseGame;
releaseGame = function releaseGame() {
_releaseGame();
updateGlobalBackBtn();
};
// Also update on game update (in case of state changes)
var _updateUI = updateUI;
updateUI = function updateUI() {
_updateUI();
updateGlobalBackBtn();
};
// Initialize
updateUI();
updateGlobalBackBtn();