User prompt
hala you yazıyor onu düzet sadece seçtiğim takım olsun
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'name')' in or related to this line: 'opponentTeam.name = leagueTeams[oppIdx].name;' Line Number: 2216
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'name')' in or related to this line: 'var oppName = leagueTeams[oppIdx].name;' Line Number: 915
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'played')' in or related to this line: 'homeTeam.played += 1;' Line Number: 855
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'realSquad')' in or related to this line: 'if (homeTeam.realSquad) {' Line Number: 773
User prompt
takım seçince ligde 2 tane oluyor seçtiğim takımı ligden sil ve sadece benim takımım olsun
User prompt
takımı seçtikten sonra seçtiğim takımı league 1 yerinde maviyle gösterki belli olsun
User prompt
oyuna girince takım seçmek olsun ligdeki tüm takımlardan birini seçelim ve onunla oynayalım bu seçim yerini gösterirken ekrana hiçbişey koyma herhangi bir lig takımı seçtikten sonra herşey ekrana gelsin ve o takımla oynamaya devam edelim
User prompt
şampiyonlar ligi yazısını gelince boş bir ekrana koy çünkü görünmüyor boş bi ekrana gelince tam ortada olsun
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'attack')' in or related to this line: 'var atkChance = atkP.attack + randomInt(0, atkP.stamina);' Line Number: 831
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'seasonsRemaining')' in or related to this line: 'var seasonsTxt = typeof p.seasonsRemaining === "number" && p.seasonsRemaining !== null ? " (" + p.seasonsRemaining + "s)" : "";' Line Number: 242
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot set properties of undefined (setting 'inSquad')' in or related to this line: 'allPlayers[i].inSquad = false;' Line Number: 183
User prompt
Please fix the bug: 'PLAYER_MAX_VALUE is not defined' in or related to this line: 'var val = Math.floor((atk + def + sta) / 3) + randomInt(PLAYER_MIN_VALUE + 2, PLAYER_MAX_VALUE - 5);' Line Number: 168
User prompt
Please add a Champions League-style tournament to the game. At the end of each season, the top 4 teams in the league should qualify for the next season's Champions League. This tournament should run alongside the regular league season and include knockout rounds or group stages with other qualified teams. Winning it should reward extra prize money and prestige.
User prompt
Recreate the FIFA Ultimate Team draft screen, but make the layout clean, spaced out, and visually organized by player positions. Do not overlap any cards. Every card should be clearly separated, aligned properly based on its role in the 4-3-3 (Attacking) formation. Forwards at the top, midfielders in the middle, defenders and goalkeeper at the bottom. Use clean lines and generous spacing. Each player card must be fully visible and readable — no cards should cover others. Add the START DRAFT button clearly at the bottom center, with enough breathing room around it. Keep the card designs FIFA-style (ICON, TOTY, etc.), but focus on clean composition and visual clarity. Do not sacrifice layout for fancy styling. The final result should feel like a polished in-game draft interface: clean, pro-level, and easy to understand at a glance.
User prompt
Please fix the bug: 'Uncaught TypeError: card.swapChildren is not a function' in or related to this line: 'card.swapChildren(border, bg);' Line Number: 1054
User prompt
Ultimate FIFA Draft Prompt – Clean UI, Player-by-Player Reveal, No Mess Build a FIFA-style Ultimate Team Draft system with a clean, minimal user interface. Use the 4-3-3 (Attacking) formation. The UI should be smooth and easy to navigate — no clutter, no dropdown hell, no hidden menus. Each position in the squad must be shown one by one, not all at once. Start with the goalkeeper, then move through the defenders, midfielders, and forwards — just like in a real draft experience. For each position, show 3 player cards side-by-side (visually styled like FUT cards), clearly labeled with their name, rating, card type (ICON, TOTY, etc.), and stats (pace, shooting, passing, etc.). After showing the 3 options, automatically pick the best-fitting player based on chemistry, traits, preferred foot, and fit with the chosen playstyle (fast-paced passing and wing-focused attacks). Add a single big “START DRAFT” button at the bottom of the screen that launches the process — no multiple clicks or hidden interactions. Each draft step should feel smooth and satisfying, with clean transitions between positions. At the end, display the full squad visually, and provide a short but sharp analysis of the team’s strengths, chemistry, weaknesses, and how it would play in-game. Don’t overcomplicate. Don’t overdecorate. Just make it look elite, smart, and easy to use — like something a real player would want to interact with.
User prompt
Build a FIFA-style Ultimate Team draft system using the 4-3-3 (Attacking) formation. Make the interface clean, straightforward, and focused. I don’t want clutter or unnecessary complexity. Every position must show 3 high-tier player options (preferably ICON and TOTY cards), with one being selected automatically based on chemistry, stats, and fit for a fast-paced, quick-passing, wing-based playstyle. Make sure the draft logic considers: chemistry links, preferred foot, work rates, skill moves, and player traits (like finesse shot, outside foot, etc.). I want a fully built squad by the end, with proper roles filled and good in-game synergy. Do not bury the functionality under dropdowns or multiple clicks. Put a big, visible “Start Draft” button at the bottom of the screen that kicks off the draft. The button should be impossible to miss. I’m not here to click around for half an hour — this should feel like a clean, smooth draft flow from beginning to end. After the draft finishes, give a brief analysis of the final team: chemistry, strengths, weak spots, and how it would ideally play in-game. Keep your tone clear and focused — don’t fluff things up. This is about efficiency, clarity, and delivering a killer squad-building experience.
User prompt
do that in game
User prompt
put youth academy and transfer market in mainb
User prompt
make league 2 table more right
Code edit (1 edits merged)
Please save this source code
User prompt
After playing a match, the Youth Academy and Transfer Market sections disappear from the interface. Please fix this bug so that both features remain visible and accessible after a match is played.
User prompt
matches are so many scores make it lower
User prompt
Everything in the game is very messy and disorganized. Please clean up and fix the entire layout so it's clear, structured, and easy to use.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a3d2f }); /**** * Game Code ****/ // Player class: represents a footballer // --- CONSTANTS --- var Player = function Player(name, attack, defense, stamina, value, seasonsRemaining) { var self = {}; self.name = name; self.attack = attack; self.defense = defense; self.stamina = stamina; self.value = value; self.maxStamina = stamina; self.inSquad = false; // true if in starting 5 self.seasonsRemaining = typeof seasonsRemaining === "number" ? seasonsRemaining : null; // null for non-transfer players, or integer for transfer market return self; }; // Team class: holds a list of players var Team = function Team(name, players) { var self = {}; self.name = name; self.players = players; // array of Player return self; }; var SQUAD_SIZE = 5; var BENCH_SIZE = 3; var INITIAL_BUDGET = 100; var PLAYER_MIN_VALUE = 10; var PLAYER_MAX_VALUE = 40; // --- GLOBALS --- var allPlayers = []; // All players owned by user var squad = []; // Starting 5 var bench = []; // Bench 3 var transferList = []; // Players available to buy var budget = INITIAL_BUDGET; var opponentTeam = null; var matchInProgress = false; var matchLog = []; var matchResult = null; var selectedPlayerIdx = null; // For swapping var selectedBenchIdx = null; // For swapping var infoText = null; var budgetText = null; var matchText = null; var transferText = null; var transferBtns = []; var swapBtns = []; var playBtn = null; var nextBtn = null; var sellBtns = []; var buyBtns = []; var squadLabels = []; var benchLabels = []; var opponentLabels = []; var guiY = 0; // --- YOUTH ACADEMY --- var youthAcademy = []; // Array of young players waiting for promotion/sale var youthLabels = []; var promoteBtns = []; var sellYouthBtns = []; var youthTimer = null; var YOUTH_TIMER_INTERVAL = 10000; // 10 seconds for demo (tweak as needed) var YOUTH_MAX = 3; // Max youth in academy at once // --- TRANSFER OFFERS SYSTEM --- // Each offer: {player: Player, offerValue: number, club: string} var transferOffers = []; var offerLabels = []; var acceptOfferBtns = []; var rejectOfferBtns = []; var OFFER_TIMER = null; var OFFER_INTERVAL = 15000; // 15 seconds for demo var OFFER_CLUBS = ["Galatasaray", "Fenerbahce", "Besiktas", "Trabzonspor", "Basaksehir", "Sivasspor", "Konyaspor", "Antalyaspor", "Alanyaspor", "Denizlispor"]; // --- UTILS --- function randomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } function randomName() { var first = ["Ahmet", "Mehmet", "Mustafa", "Ali", "Hüseyin", "Hasan", "Cesur", "Osman", "Yusuf", "Murat", "Emre", "Burak", "Fatih", "Serkan", "Onur", "Barış", "Cem", "Eren", "Kaan", "Deniz", "Çınar", "Aziz", "Ege", "Miraç"]; var last = ["Yılmaz", "Kaya", "Demir", "Şahin", "Çelik", "Yıldız", "Yıldırım", "Aydın", "Öztürk", "Arslan", "Doğan", "Kılıç", "Aslan", "Polat", "Koç", "Kurt", "Özdemir", "Aksoy", "Güneş", "Bozkurt", "Bozbalak", "Sakız", "Fizikli"]; return first[randomInt(0, first.length - 1)] + " " + last[randomInt(0, last.length - 1)]; } function makeRandomPlayer() { var atk = randomInt(5, 15); var def = randomInt(5, 15); var sta = randomInt(10, 20); var val = Math.floor((atk + def + sta) / 3) + randomInt(PLAYER_MIN_VALUE, PLAYER_MAX_VALUE); return new Player(randomName(), atk, def, sta, val); } // Real-life Turkish Super Lig squads (2023/24, main players, 5 per team for demo) var realSquads = { "Galatasaray": [new Player("Mauro Icardi", 18, 8, 16, 40), new Player("Dries Mertens", 16, 7, 15, 36), new Player("Lucas Torreira", 10, 16, 17, 34), new Player("Kerem Aktürkoğlu", 15, 8, 15, 32), new Player("Fernando Muslera", 7, 18, 16, 35)], "Fenerbahce": [new Player("Edin Dzeko", 17, 7, 15, 38), new Player("Dusan Tadic", 16, 8, 15, 36), new Player("Fred", 12, 14, 16, 33), new Player("Sebastian Szymanski", 15, 9, 15, 32), new Player("Dominik Livakovic", 6, 17, 16, 34)], "Besiktas": [new Player("Cenk Tosun", 16, 7, 15, 34), new Player("Rachid Ghezzal", 15, 8, 14, 32), new Player("Salih Uçan", 12, 13, 15, 30), new Player("Omar Colley", 8, 16, 15, 31), new Player("Mert Günok", 6, 17, 15, 30)], "Trabzonspor": [new Player("Edin Visca", 15, 8, 15, 32), new Player("Anastasios Bakasetas", 15, 9, 15, 32), new Player("Uğurcan Çakır", 6, 17, 16, 33), new Player("Enis Bardhi", 14, 8, 14, 29), new Player("Joaquin Fernandez", 8, 15, 14, 28)], "Basaksehir": [new Player("Danijel Aleksic", 14, 8, 14, 28), new Player("Leo Duarte", 8, 15, 14, 27), new Player("Serdar Gürler", 13, 8, 14, 27), new Player("Mahmut Tekdemir", 9, 14, 14, 26), new Player("Volkan Babacan", 6, 16, 14, 25)], "Sivasspor": [new Player("Mustapha Yatabare", 14, 8, 14, 27), new Player("Max Gradel", 13, 8, 14, 27), new Player("Hakan Arslan", 10, 13, 14, 25), new Player("Uğur Çiftçi", 8, 14, 14, 24), new Player("Ali Şaşal Vural", 6, 16, 14, 24)], "Konyaspor": [new Player("Sokol Cikalleshi", 14, 8, 14, 27), new Player("Amir Hadziahmetovic", 11, 13, 14, 25), new Player("Guilherme", 10, 13, 14, 25), new Player("Francisco Calvo", 8, 15, 14, 25), new Player("Ibrahim Sehic", 6, 16, 14, 24)], "Antalyaspor": [new Player("Haji Wright", 14, 8, 14, 27), new Player("Fernando", 11, 13, 14, 25), new Player("Bünyamin Balcı", 10, 13, 14, 24), new Player("Veysel Sarı", 8, 15, 14, 24), new Player("Helton Leite", 6, 16, 14, 24)], "Alanyaspor": [new Player("Efecan Karaca", 14, 8, 14, 27), new Player("Famara Diedhiou", 13, 8, 14, 26), new Player("Yusuf Özdemir", 10, 13, 14, 24), new Player("Fidan Aliti", 8, 15, 14, 24), new Player("Runar Runarsson", 6, 16, 14, 24)], "Denizlispor": [new Player("Ömer Şişmanoğlu", 13, 8, 14, 25), new Player("Mustafa Yumlu", 8, 15, 14, 24), new Player("Gökhan Süzen", 10, 13, 14, 23), new Player("Oğuz Yılmaz", 8, 14, 14, 23), new Player("Adam Stachowiak", 6, 16, 14, 23)] }; function makeOpponentTeam() { // List of realistic Turkish club names var clubNames = ["Denizlispor", "Sivasspor", "Galatasaray", "Fenerbahce", "Trabzonspor", "Besiktas", "Basaksehir", "Konyaspor", "Antalyaspor", "Alanyaspor"]; // Pick a random club name for the opponent var clubName = clubNames[randomInt(0, clubNames.length - 1)]; var oppPlayers; if (realSquads[clubName]) { // Use real squad, clone to avoid reference issues oppPlayers = []; for (var i = 0; i < SQUAD_SIZE; i++) { var p = realSquads[clubName][i]; oppPlayers.push(clonePlayer(p)); } } else { // Fallback to random oppPlayers = []; for (var i = 0; i < SQUAD_SIZE; i++) { oppPlayers.push(makeRandomPlayer()); } } return new Team(clubName, oppPlayers); } function clonePlayer(p) { return new Player(p.name, p.attack, p.defense, p.stamina, p.value, p.seasonsRemaining); } // --- INIT DATA --- function initPlayers() { allPlayers = []; for (var i = 0; i < SQUAD_SIZE + BENCH_SIZE; i++) { // For initial squad, generate lower stats (attack, defense, stamina) var atk = randomInt(4, 8); var def = randomInt(4, 8); var sta = randomInt(8, 13); var val = Math.floor((atk + def + sta) / 3) + randomInt(PLAYER_MIN_VALUE, PLAYER_MIN_VALUE + 5); allPlayers.push(new Player(randomName(), atk, def, sta, val)); } updateSquadAndBench(); } function updateSquadAndBench() { squad = []; bench = []; // Ensure squad has at most SQUAD_SIZE players and bench has remaining for (var i = 0; i < allPlayers.length; i++) { if (i < SQUAD_SIZE) { allPlayers[i].inSquad = true; // Ensure we don't add more than SQUAD_SIZE players to the squad if (squad.length < SQUAD_SIZE) { squad.push(allPlayers[i]); } else { // If somehow we have too many players marked as squad, put them on bench allPlayers[i].inSquad = false; bench.push(allPlayers[i]); } } else { allPlayers[i].inSquad = false; bench.push(allPlayers[i]); } } // If allPlayers has less than SQUAD_SIZE, squad will naturally have fewer players. // No need to fill empty slots, the updateSquadLabels function handles this. } function initTransferList() { transferList = []; // List of latest, highest-valued real-world football players (2024, top market values, demo) var topPlayers = [new Player("Kylian Mbappé", 20, 12, 19, 180), new Player("Erling Haaland", 21, 10, 18, 170), new Player("Jude Bellingham", 18, 14, 18, 150), new Player("Vinícius Júnior", 19, 12, 18, 150), new Player("Phil Foden", 17, 13, 17, 130), new Player("Bukayo Saka", 17, 12, 17, 120), new Player("Rodri", 14, 18, 17, 120), new Player("Jamal Musiala", 17, 12, 17, 120), new Player("Victor Osimhen", 19, 10, 17, 110), new Player("Florian Wirtz", 16, 12, 17, 110), new Player("Pedri", 15, 13, 17, 100), new Player("Declan Rice", 13, 17, 17, 100), new Player("Harry Kane", 20, 10, 16, 100), new Player("Martin Ødegaard", 16, 13, 16, 100), new Player("Rafael Leão", 18, 10, 16, 90), new Player("Khvicha Kvaratskhelia", 17, 11, 16, 90), new Player("Josko Gvardiol", 10, 18, 16, 90), new Player("Gavi", 14, 14, 16, 90), new Player("Alejandro Balde", 12, 15, 16, 80), new Player("William Saliba", 9, 18, 16, 80), new Player("Son Heung Min", 19, 11, 17, 110)]; // Always show 6 random top players in the transfer market, no duplicates var usedIdx = []; for (var i = 0; i < 6; i++) { var idx; do { idx = randomInt(0, topPlayers.length - 1); } while (usedIdx.indexOf(idx) !== -1); usedIdx.push(idx); // When adding to transferList, set seasonsRemaining=3 for transfer market players var p = topPlayers[idx]; transferList.push(new Player(p.name, p.attack, p.defense, p.stamina, p.value, 3)); } } // --- UI HELPERS --- function clearArray(arr) { while (arr.length > 0) { var el = arr.pop(); if (el && el.destroy) { el.destroy(); } } } function makeLabel(txt, x, y, size, color) { // Consistent font, color, and size for all labels var t = new Text2(txt, { size: size || 60, fill: color || "#fff", font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" }); t.x = x; t.y = y; t.anchor = t.anchor || { set: function set() {} }; return t; } function updateBudgetText() { if (budgetText) { budgetText.setText("Budget: $" + budget + "M"); budgetText.anchor && budgetText.anchor.set && budgetText.anchor.set(0.5, 0); } } function showInfo(msg) { if (infoText) { infoText.setText(msg); infoText.anchor && infoText.anchor.set && infoText.anchor.set(0.5, 0); } } function updateSquadLabels() { clearArray(squadLabels); // Centered squad section var sectionWidth = 1100; var sectionX = (2048 - sectionWidth) / 2; var startY = guiY + 260; var rowSpacing = 64; var swapBtnX = sectionX + sectionWidth - 220; var sellBtnX = sectionX + sectionWidth - 100; for (var i = 0; i < SQUAD_SIZE; i++) { var p = squad[i]; var rowY = startY + i * rowSpacing; if (!p) { var t = makeLabel(i + 1 + ". Empty Slot", sectionX + 40, rowY, 48, "#aaaaaa"); t.anchor.set(0, 0); game.addChild(t); squadLabels.push(t); continue; } var seasonsTxt = typeof p.seasonsRemaining === "number" && p.seasonsRemaining !== null ? " (" + p.seasonsRemaining + "s)" : ""; var t = makeLabel(i + 1 + ". " + p.name + " [A:" + p.attack + " D:" + p.defense + " S:" + p.stamina + "]" + seasonsTxt, sectionX + 40, rowY, 48, "#ffe066"); t.anchor.set(0, 0); game.addChild(t); squadLabels.push(t); // Add swap button var btn = makeLabel("↔", swapBtnX, rowY, 48, "#fff"); btn.idx = i; btn.anchor.set(0.5, 0); btn.interactive = true; btn.down = function (x, y, obj) { selectedPlayerIdx = obj.idx; if (selectedPlayerIdx !== null && squad[selectedPlayerIdx]) { showInfo("Tap a bench player to swap with " + squad[selectedPlayerIdx].name); } else { showInfo("Tap a bench player to swap."); } }; game.addChild(btn); swapBtns.push(btn); // Add sell button var sellBtn = makeLabel("Sell", sellBtnX, rowY, 40, "#ff7675"); sellBtn.idx = i; sellBtn.anchor.set(0.5, 0); sellBtn.interactive = true; sellBtn.down = function (idxCopy) { return function (x, y, obj) { var idx = idxCopy; var p = squad[idx]; if (!p) { showInfo("Player not available."); return; } var allIdx = allPlayers.indexOf(p); if (allIdx !== -1) { budget += p.value; allPlayers.splice(allIdx, 1); updateSquadAndBench(); updateBudgetText(); showInfo("Sold " + p.name + " for $" + p.value + "M"); refreshUI(); } else { showInfo("Player not found in squad."); } }; }(i); game.addChild(sellBtn); sellBtns.push(sellBtn); } } function updateBenchLabels() { clearArray(benchLabels); // Centered bench section below squad var sectionWidth = 1100; var sectionX = (2048 - sectionWidth) / 2; var startY = guiY + 260 + SQUAD_SIZE * 64 + 40; var rowSpacing = 64; for (var i = 0; i < BENCH_SIZE; i++) { var p = bench[i]; var rowY = startY + i * rowSpacing; if (!p) { var t = makeLabel("B" + (i + 1) + ". Empty Slot", sectionX + 40, rowY, 48, "#aaaaaa"); t.anchor.set(0, 0); game.addChild(t); benchLabels.push(t); continue; } var seasonsTxt = typeof p.seasonsRemaining === "number" && p.seasonsRemaining !== null ? " (" + p.seasonsRemaining + "s)" : ""; var t = makeLabel("B" + (i + 1) + ". " + p.name + " [A:" + p.attack + " D:" + p.defense + " S:" + p.stamina + "]" + seasonsTxt, sectionX + 40, rowY, 48, "#b2bec3"); t.anchor.set(0, 0); game.addChild(t); benchLabels.push(t); t.idx = i; t.interactive = true; t.down = function (x, y, obj) { if (selectedPlayerIdx !== null) { var sIdx = selectedPlayerIdx; var bIdx = obj.idx; if (squad[sIdx] && bench[bIdx]) { var temp = squad[sIdx]; squad[sIdx] = bench[bIdx]; bench[bIdx] = temp; } else if (!squad[sIdx] && bench[bIdx]) { squad[sIdx] = bench[bIdx]; bench[bIdx] = undefined; } else if (squad[sIdx] && !bench[bIdx]) { bench[bIdx] = squad[sIdx]; squad[sIdx] = undefined; } else { selectedPlayerIdx = null; showInfo("Cannot swap with empty slots."); refreshUI(); return; } allPlayers = []; for (var j = 0; j < squad.length; j++) { if (squad[j]) allPlayers.push(squad[j]); } for (var j = 0; j < bench.length; j++) { if (bench[j]) allPlayers.push(bench[j]); } updateSquadAndBench(); selectedPlayerIdx = null; showInfo("Swapped players."); refreshUI(); } }; } } function updateTransferLabels() { clearArray(transferBtns); clearArray(buyBtns); // --- Centered Transfer Market Layout --- // Calculate center X for the section var sectionWidth = 1100; var sectionX = (2048 - sectionWidth) / 2; var rowHeight = 64; var sectionHeight = (transferList.length + 1) * rowHeight + 120; var startY = 400; // Start well below the top for visual balance // Remove old transferText if present if (transferText) { transferText.destroy(); } // Centered header transferText = makeLabel("Transfer Market", 2048 / 2, startY - 90, 56, "#00b894"); transferText.anchor.set(0.5, 0); // Center header horizontally game.addChild(transferText); // Calculate X positions for player info and buy button var playerInfoX = sectionX + 40; var buyBtnX = sectionX + sectionWidth - 180; for (var i = 0; i < transferList.length; i++) { var p = transferList[i]; // Centered row Y var rowY = startY + i * rowHeight; // Player info label, left-aligned in section var t = makeLabel(p.name + " [A:" + p.attack + " D:" + p.defense + " S:" + p.stamina + "] $" + p.value + "M", playerInfoX, rowY, 44, "#fff"); t.anchor.set(0, 0); // Left align in section game.addChild(t); transferBtns.push(t); // Buy button, right-aligned in section var buyBtn = makeLabel("Buy", buyBtnX, rowY, 40, "#00b894"); buyBtn.idx = i; buyBtn.interactive = true; buyBtn.down = function (idxCopy) { return function (x, y, obj) { var idx = idxCopy; var p = transferList[idx]; if (!p) { showInfo("Player not available."); return; } if (budget < p.value) { showInfo("Not enough budget!"); return; } // Allow buying a player as long as the total number of players is less than the maximum allowed if (allPlayers.length >= SQUAD_SIZE + BENCH_SIZE) { showInfo("Squad full! Sell a player first."); return; } budget -= p.value; // When buying, always set seasonsRemaining=3 allPlayers.push(new Player(p.name, p.attack, p.defense, p.stamina, p.value, 3)); updateSquadAndBench(); updateBudgetText(); showInfo("Bought " + p.name + " for $" + p.value + "M"); // Remove from transfer list, add new transferList.splice(idx, 1, makeRandomPlayer()); refreshUI(); }; }(i); game.addChild(buyBtn); buyBtns.push(buyBtn); } } function updateOpponentLabels() { clearArray(opponentLabels); // Position opponent section at bottom-left (for reference, but now only for opponent info) var oppStartY = 2048 - (SQUAD_SIZE + 2) * 120 - 200; // increased row height and more margin for opponent section if (oppStartY < guiY + 1800) { oppStartY = guiY + 1800; } // push down if needed for more space // --- League Table: show all teams, slightly larger, and moved to the left --- // Place league table just above the opponent section, but below the transfer market var leagueWidth = 600; // slightly larger var leagueX = 80; // move to the left side of the screen var leagueY = oppStartY - 650; // place above opponent section, below transfer market if (leagueY < guiY + 600) leagueY = guiY + 600; var leagueHeader = makeLabel("League Table", leagueX, leagueY, 54, "#fdcb6e"); // slightly larger font game.addChild(leagueHeader); opponentLabels.push(leagueHeader); // Sort league by points, then goal difference, then goals for var sortedLeague = leagueTeams.slice().sort(function (a, b) { if (b.points !== a.points) { return b.points - a.points; } var gdA = a.goalsFor - a.goalsAgainst; var gdB = b.goalsFor - b.goalsAgainst; if (gdB !== gdA) { return gdB - gdA; } return b.goalsFor - a.goalsFor; }); for (var i = 0; i < sortedLeague.length; i++) { var team = sortedLeague[i]; var color = team.name === "You" ? "#00cec9" : "#fff"; var gd = team.goalsFor - team.goalsAgainst; var labelTxt = i + 1 + ". " + team.name + " Pts:" + team.points + " GP:" + team.played + " W:" + team.wins + " D:" + team.draws + " L:" + team.losses + " GD:" + gd; var teamLabel = makeLabel(labelTxt, leagueX, leagueY + 70 + i * 48, 38, color); // slightly larger font and spacing game.addChild(teamLabel); opponentLabels.push(teamLabel); } // Now show Transfer Market section below league table (replacing Next Opponent) var transferHeader = makeLabel("Transfer Market", 80, oppStartY, 56, "#00b894"); game.addChild(transferHeader); opponentLabels.push(transferHeader); var transferY = oppStartY + 80; var transferRowHeight = 48; for (var i = 0; i < transferList.length; i++) { var p = transferList[i]; var t = makeLabel(p.name + " [A:" + p.attack + " D:" + p.defense + " S:" + p.stamina + "] $" + p.value + "M", 80, transferY + i * transferRowHeight, 40, "#fff"); game.addChild(t); opponentLabels.push(t); } } function clearMatchText() { if (matchText) { matchText.destroy(); matchText = null; } } function showMatchLog() { clearMatchText(); var log = matchLog.join("\n"); matchText = new Text2(log, { size: 48, fill: "#fff", wordWrap: true, wordWrapWidth: 1800 }); // Position match summary directly underneath the Play Match button var playBtnX = 2048 / 2 - 200; // Same as playBtn X var playBtnY = 2048 - 200; // Same as playBtn Y matchText.x = playBtnX; matchText.y = playBtnY + 180; // 180px below Play Match button for extra separation game.addChild(matchText); } function clearAllUI() { clearArray(squadLabels); clearArray(benchLabels); clearArray(transferBtns); clearArray(buyBtns); clearArray(swapBtns); clearArray(sellBtns); clearArray(opponentLabels); // --- YOUTH ACADEMY UI --- clearArray(youthLabels); clearArray(promoteBtns); clearArray(sellYouthBtns); if (transferText) { transferText.destroy(); } transferText = null; // --- CLEAR TRANSFER OFFER UI --- clearArray(offerLabels); clearArray(acceptOfferBtns); clearArray(rejectOfferBtns); clearMatchText(); if (playBtn) { playBtn.destroy(); } playBtn = null; if (nextBtn) { nextBtn.destroy(); } nextBtn = null; } // --- LEAGUE SYSTEM --- // League teams: user + 10 Turkish clubs var leagueClubNames = ["Denizlispor", "Sivasspor", "Galatasaray", "Fenerbahce", "Trabzonspor", "Besiktas", "Basaksehir", "Konyaspor", "Antalyaspor", "Alanyaspor"]; var leagueTeams = []; // [{name, points, played, wins, draws, losses, goalsFor, goalsAgainst}] var leagueFixtures = []; // [{homeIdx, awayIdx}] var currentFixtureIdx = 0; var userTeamIdx = 0; // always 0 function initLeague() { leagueTeams = []; // User team leagueTeams.push({ name: "You", points: 0, played: 0, wins: 0, draws: 0, losses: 0, goalsFor: 0, goalsAgainst: 0 }); // Opponent clubs for (var i = 0; i < leagueClubNames.length; i++) { var clubName = leagueClubNames[i]; leagueTeams.push({ name: clubName, points: 0, played: 0, wins: 0, draws: 0, losses: 0, goalsFor: 0, goalsAgainst: 0, // Attach real squad if available for league simulation realSquad: realSquads[clubName] ? realSquads[clubName].map(function (p) { return clonePlayer(p); }) : null }); } // Generate fixtures: each team plays every other team twice (home/away) leagueFixtures = []; var n = leagueTeams.length; for (var i = 0; i < n; i++) { for (var j = 0; j < n; j++) { if (i !== j) { // Only add each pair twice (home/away) if (i < j) { leagueFixtures.push({ homeIdx: i, awayIdx: j }); leagueFixtures.push({ homeIdx: j, awayIdx: i }); } } } } // Shuffle fixtures for variety for (var k = leagueFixtures.length - 1; k > 0; k--) { var r = randomInt(0, k); var temp = leagueFixtures[k]; leagueFixtures[k] = leagueFixtures[r]; leagueFixtures[r] = temp; } currentFixtureIdx = 0; } function getCurrentOpponentIdx() { // Find the next fixture where user is home or away for (var i = currentFixtureIdx; i < leagueFixtures.length; i++) { var f = leagueFixtures[i]; if (f.homeIdx === userTeamIdx || f.awayIdx === userTeamIdx) { return f.homeIdx === userTeamIdx ? f.awayIdx : f.homeIdx; } } return null; } function getCurrentFixture() { for (var i = currentFixtureIdx; i < leagueFixtures.length; i++) { var f = leagueFixtures[i]; if (f.homeIdx === userTeamIdx || f.awayIdx === userTeamIdx) { return { idx: i, fixture: f }; } } return null; } function advanceFixture() { // Move to next user fixture for (var i = currentFixtureIdx + 1; i < leagueFixtures.length; i++) { var f = leagueFixtures[i]; if (f.homeIdx === userTeamIdx || f.awayIdx === userTeamIdx) { currentFixtureIdx = i; return; } } // No more fixtures: season over currentFixtureIdx = leagueFixtures.length; } function isSeasonOver() { // If all user fixtures played for (var i = currentFixtureIdx; i < leagueFixtures.length; i++) { var f = leagueFixtures[i]; if (f.homeIdx === userTeamIdx || f.awayIdx === userTeamIdx) { return false; } } return true; } // --- GAME LOGIC --- function simulateMatch() { matchLog = []; matchResult = null; matchInProgress = true; // --- Add a random number of youth players after each match --- var numNewYouth = randomInt(0, 3); if (youthAcademy.length < YOUTH_MAX && numNewYouth > 0) { for (var i = 0; i < numNewYouth; i++) { if (youthAcademy.length >= YOUTH_MAX) break; // Don't add more than max // Generate a young player (attributes 1-10) var atk = randomInt(1, 10); var def = randomInt(1, 10); var sta = randomInt(1, 10); // Calculate base stat sum and average var statSum = atk + def + sta; var statAvg = Math.floor(statSum / 3); // Most players: value 1-5M, some: 6-10M, all <= 10M var val; if (Math.random() < 0.8) { val = Math.max(1, Math.min(5, statAvg + randomInt(0, 1))); } else { val = Math.max(6, Math.min(10, statAvg + randomInt(2, 4))); if (val < 6) val = 5; } if (val > 10) val = 10; // Cap value at 10M for youth academy players var p = new Player(randomName(), atk, def, sta, val, null); youthAcademy.push(p); } if (numNewYouth === 1) { showInfo("A new youth player has joined your academy!"); } else if (numNewYouth > 1) { showInfo(numNewYouth + " new youth players have joined your academy!"); } refreshUI(); } // Find all fixtures for this matchday (all teams play one match) if (currentFixtureIdx >= leagueFixtures.length) { matchLog.push("Season is over!"); showMatchLog(); matchInProgress = false; return; } // Gather all fixtures for this matchday (each team plays once) var nTeams = leagueTeams.length; var matchdayFixtures = []; var teamsPlayed = {}; for (var i = currentFixtureIdx; i < leagueFixtures.length; i++) { var f = leagueFixtures[i]; if (!teamsPlayed[f.homeIdx] && !teamsPlayed[f.awayIdx]) { matchdayFixtures.push({ idx: i, fixture: f }); teamsPlayed[f.homeIdx] = true; teamsPlayed[f.awayIdx] = true; if (Object.keys(teamsPlayed).length >= nTeams) { break; } } } // Simulate all matches in this matchday var userMatchIdx = -1; for (var m = 0; m < matchdayFixtures.length; m++) { var fixtureObj = matchdayFixtures[m]; var fixture = fixtureObj.fixture; var homeIdx = fixture.homeIdx; var awayIdx = fixture.awayIdx; var homeTeam = leagueTeams[homeIdx]; var awayTeam = leagueTeams[awayIdx]; // Prepare teams var homePlayers, awayPlayers; if (homeIdx === userTeamIdx) { homePlayers = squad; } else { // Use real squad if available, else generate random team if (homeTeam.realSquad) { homePlayers = []; for (var i = 0; i < SQUAD_SIZE; i++) { homePlayers.push(clonePlayer(homeTeam.realSquad[i])); } } else { homePlayers = []; for (var i = 0; i < SQUAD_SIZE; i++) { homePlayers.push(makeRandomPlayer()); } } } if (awayIdx === userTeamIdx) { awayPlayers = squad; } else { if (awayTeam.realSquad) { awayPlayers = []; for (var i = 0; i < SQUAD_SIZE; i++) { awayPlayers.push(clonePlayer(awayTeam.realSquad[i])); } } else { awayPlayers = []; for (var i = 0; i < SQUAD_SIZE; i++) { awayPlayers.push(makeRandomPlayer()); } } } // Calculate stats // Determine team strengths var homeStrength = 0; for (var i = 0; i < homePlayers.length; i++) { homeStrength += homePlayers[i].attack + homePlayers[i].defense + homePlayers[i].stamina; } var awayStrength = 0; for (var i = 0; i < awayPlayers.length; i++) { awayStrength += awayPlayers[i].attack + awayPlayers[i].defense + awayPlayers[i].stamina; } var homeGoals = 0, awayGoals = 0; // Simulate match based on strength and randomness // A simple model: higher strength means more chances to score // Reduce number of chances and scoring probability for more realistic scores var homeChances = Math.max(1, Math.floor(homeStrength / 40) + randomInt(-1, 1)); // Fewer chances, less randomness var awayChances = Math.max(1, Math.floor(awayStrength / 40) + randomInt(-1, 1)); // Fewer chances, less randomness for (var i = 0; i < homeChances; i++) { if (Math.random() < 0.38) { // Lower chance to score per chance homeGoals++; } } for (var i = 0; i < awayChances; i++) { if (Math.random() < 0.38) { // Lower chance to score per chance awayGoals++; } } for (var turn = 0; turn < 5; turn++) { // Home attack (for match log details) var atkP = homePlayers[turn]; var defP = awayPlayers[turn]; // Check if players are defined before accessing their properties if (!atkP || !defP) { // Skip this turn if a player is missing continue; } var atkChance = atkP.attack + randomInt(0, atkP.stamina); var defChance = defP.defense + randomInt(0, defP.stamina); if (atkChance > defChance + 3) { //homeGoals++; // Already accounted for in overall simulation } else if (defChance > atkChance + 5) { // Defensive action (for match log details) } // Away attack (for match log details) var oAtkP = awayPlayers[turn]; var oDefP = homePlayers[turn]; // Check if players are defined before accessing their properties if (!oAtkP || !oDefP) { // Skip this turn if a player is missing continue; } var oAtkChance = oAtkP.attack + randomInt(0, oAtkP.stamina); var oDefChance = oDefP.defense + randomInt(0, oDefP.stamina); if (oAtkChance > oDefChance + 3) { //awayGoals++; // Already accounted for in overall simulation } else if (oDefChance > oAtkChance + 5) { // Defensive action (for match log details) } } // Update league table homeTeam.played += 1; awayTeam.played += 1; homeTeam.goalsFor += homeGoals; homeTeam.goalsAgainst += awayGoals; awayTeam.goalsFor += awayGoals; awayTeam.goalsAgainst += homeGoals; if (homeGoals > awayGoals) { homeTeam.points += 3; homeTeam.wins += 1; awayTeam.losses += 1; } else if (homeGoals < awayGoals) { awayTeam.points += 3; awayTeam.wins += 1; homeTeam.losses += 1; } else { homeTeam.points += 1; awayTeam.points += 1; homeTeam.draws += 1; awayTeam.draws += 1; } // If this is the user's match, log details and handle rewards if (homeIdx === userTeamIdx || awayIdx === userTeamIdx) { userMatchIdx = m; var userGoals = homeIdx === userTeamIdx ? homeGoals : awayGoals; var oppGoals = homeIdx === userTeamIdx ? awayGoals : homeGoals; var oppIdx = homeIdx === userTeamIdx ? awayIdx : homeIdx; var oppName = leagueTeams[oppIdx].name; for (var turn = 0; turn < 5; turn++) { // User attack var atkP = squad[turn]; var defP = homeIdx === userTeamIdx ? awayPlayers[turn] : homePlayers[turn]; // Check if players are defined before accessing their properties if (!atkP || !defP) { // Skip this turn if a player is missing continue; } var atkChance = atkP.attack + randomInt(0, atkP.stamina); var defChance = defP.defense + randomInt(0, defP.stamina); if (atkChance > defChance + 5 && Math.random() < 0.5) { // Harder to score, require bigger difference and add randomness matchLog.push("Minute " + (turn * 18 + 5) + ": " + atkP.name + " scores!"); } else if (defChance > atkChance + 3) { matchLog.push("Minute " + (turn * 18 + 8) + ": " + defP.name + " makes a key tackle."); } // Opponent attack var oAtkP = homeIdx === userTeamIdx ? awayPlayers[turn] : homePlayers[turn]; var oDefP = squad[turn]; // Check if players are defined before accessing their properties if (!oAtkP || !oDefP) { // Skip this turn if a player is missing continue; } var oAtkChance = oAtkP.attack + randomInt(0, oAtkP.stamina); var oDefChance = oDefP.defense + randomInt(0, oDefP.stamina); if (oAtkChance > oDefChance + 5 && Math.random() < 0.5) { // Harder to score, require bigger difference and add randomness matchLog.push("Minute " + (turn * 18 + 12) + ": " + oAtkP.name + " scores!"); } else if (oDefChance > oAtkChance + 3) { matchLog.push("Minute " + (turn * 18 + 15) + ": " + oDefP.name + " blocks a shot."); } } matchLog.push("Full Time: You " + userGoals + " - " + oppGoals + " " + oppName); // Rewards if (userGoals > oppGoals) { matchResult = "win"; matchLog.push("You win! +$20M"); budget += 20; } else if (userGoals < oppGoals) { matchResult = "lose"; matchLog.push("You lose."); } else { matchResult = "draw"; matchLog.push("Draw. +$5M"); budget += 5; } } } // Advance fixture pointer by number of fixtures played this matchday currentFixtureIdx += matchdayFixtures.length; // Restore stamina a bit after match for (var i = 0; i < homePlayers.length; i++) { if (homeIdx === userTeamIdx) { homePlayers[i].stamina = Math.max(0, homePlayers[i].stamina - randomInt(3, 6)); // Decrease stamina after playing homePlayers[i].stamina = Math.min(homePlayers[i].maxStamina, homePlayers[i].stamina + randomInt(1, 3)); // Partial recovery } } for (var i = 0; i < awayPlayers.length; i++) { if (awayIdx === userTeamIdx) { awayPlayers[i].stamina = Math.max(0, awayPlayers[i].stamina - randomInt(3, 6)); // Decrease stamina after playing awayPlayers[i].stamina = Math.min(awayPlayers[i].maxStamina, awayPlayers[i].stamina + randomInt(1, 3)); // Partial recovery } } updateBudgetText(); showMatchLog(); matchInProgress = false; } function refreshUI() { clearAllUI(); // --- UI LAYOUT OVERHAUL: Clean, structured, and visually balanced --- // 1. Title, Budget, Info (centered, consistent spacing) var titleY = 40; var budgetY = titleY + 100; var infoY = budgetY + 70; // Title var title = new Text2("Mini Football Manager", { size: 90, fill: 0x00CEC9, font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" }); title.x = 2048 / 2; title.y = titleY; title.anchor.set(0.5, 0); game.addChild(title); // Budget if (!budgetText) { budgetText = new Text2("Budget: $" + budget + "M", { size: 60, fill: "#fff", font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" }); } budgetText.x = 2048 / 2; budgetText.y = budgetY; budgetText.anchor.set(0.5, 0); game.addChild(budgetText); // Info if (!infoText) { infoText = new Text2("", { size: 54, fill: 0xFDCB6E, font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" }); } infoText.x = 2048 / 2; infoText.y = infoY; infoText.anchor.set(0.5, 0); game.addChild(infoText); // 2. Squad Section (centered, consistent spacing) var squadSectionY = infoY + 80; guiY = squadSectionY - 220; // for legacy code compatibility updateSquadLabels(); // 3. Bench Section (centered, below squad) updateBenchLabels(); // 4. Transfer Market Section (centered, below bench) updateTransferLabels(); // 5. League Table & Opponent Section (left side, vertically aligned) updateOpponentLabels(); // 6. Youth Academy & Transfer Offers (right side, vertically aligned) // Place youth academy and offers in a right column, visually balanced clearArray(youthLabels); clearArray(promoteBtns); clearArray(sellYouthBtns); var rightColX = 2048 - 1100 - 80; // right margin var rightColY = squadSectionY; var youthHeader = makeLabel("Youth Academy", rightColX + 550, rightColY, 54, "#81ecec"); youthHeader.anchor.set(0.5, 0); game.addChild(youthHeader); youthLabels.push(youthHeader); for (var i = 0; i < youthAcademy.length; i++) { var yp = youthAcademy[i]; var rowY = rightColY + 70 + i * 60; var t = makeLabel(yp.name + " [A:" + yp.attack + " D:" + yp.defense + " S:" + yp.stamina + "] $" + yp.value + "M", rightColX + 40, rowY, 40, "#fff"); t.anchor.set(0, 0); game.addChild(t); youthLabels.push(t); // Promote button var promoteBtn = makeLabel("Promote", rightColX + 700, rowY, 36, "#00b894"); promoteBtn.idx = i; promoteBtn.interactive = true; promoteBtn.down = function (idxCopy) { return function (x, y, obj) { var idx = idxCopy; var p = youthAcademy[idx]; if (!p) { showInfo("No youth player to promote."); return; } if (allPlayers.length >= SQUAD_SIZE + BENCH_SIZE) { showInfo("Squad full! Sell a player first."); return; } allPlayers.push(new Player(p.name, p.attack, p.defense, p.stamina, p.value, null)); updateSquadAndBench(); showInfo("Promoted " + p.name + " to your team!"); youthAcademy.splice(idx, 1); refreshUI(); }; }(i); game.addChild(promoteBtn); promoteBtns.push(promoteBtn); // Sell button var sellBtn = makeLabel("Sell", rightColX + 850, rowY, 36, "#fdcb6e"); sellBtn.idx = i; sellBtn.interactive = true; sellBtn.down = function (idxCopy) { return function (x, y, obj) { var idx = idxCopy; var p = youthAcademy[idx]; if (!p) { showInfo("No youth player to sell."); return; } budget += p.value; updateBudgetText(); showInfo("Sold " + p.name + " for $" + p.value + "M"); youthAcademy.splice(idx, 1); refreshUI(); }; }(i); game.addChild(sellBtn); sellYouthBtns.push(sellBtn); } // Transfer Offers (below youth academy) clearArray(offerLabels); clearArray(acceptOfferBtns); clearArray(rejectOfferBtns); var offerY = rightColY + 70 + Math.max(1, youthAcademy.length) * 60 + 40; if (transferOffers.length > 0) { var offerHeader = makeLabel("Transfer Offers", rightColX + 550, offerY, 54, "#fdcb6e"); offerHeader.anchor.set(0.5, 0); game.addChild(offerHeader); offerLabels.push(offerHeader); for (var i = 0; i < transferOffers.length; i++) { var offer = transferOffers[i]; var p = offer.player; var rowY = offerY + 70 + i * 60; var txt = offer.club + " offers $" + offer.offerValue + "M for " + p.name; var t = makeLabel(txt, rightColX + 40, rowY, 40, "#fff"); t.anchor.set(0, 0); game.addChild(t); offerLabels.push(t); // Accept button var acceptBtn = makeLabel("Accept", rightColX + 700, rowY, 36, "#00b894"); acceptBtn.idx = i; acceptBtn.interactive = true; acceptBtn.down = function (idxCopy) { return function (x, y, obj) { var idx = idxCopy; var offer = transferOffers[idx]; var p = offer.player; var allIdx = allPlayers.indexOf(p); if (allIdx !== -1) { budget += offer.offerValue; allPlayers.splice(allIdx, 1); updateSquadAndBench(); updateBudgetText(); showInfo("Sold " + p.name + " to " + offer.club + " for $" + offer.offerValue + "M"); transferOffers.splice(idx, 1); refreshUI(); } else { showInfo("Player not found."); } }; }(i); game.addChild(acceptBtn); acceptOfferBtns.push(acceptBtn); // Reject button var rejectBtn = makeLabel("Reject", rightColX + 850, rowY, 36, "#ff7675"); rejectBtn.idx = i; rejectBtn.interactive = true; rejectBtn.down = function (idxCopy) { return function (x, y, obj) { var idx = idxCopy; var offer = transferOffers[idx]; showInfo("Rejected offer for " + offer.player.name + "."); transferOffers.splice(idx, 1); refreshUI(); }; }(i); game.addChild(rejectBtn); rejectOfferBtns.push(rejectBtn); } } // 7. Play Match and Next Match buttons (bottom center, always visible) var playBtnX = 2048 / 2 - 200; var playBtnY = 2732 - 320; playBtn = makeLabel("Play Match", playBtnX, playBtnY, 70, "#00cec9"); playBtn.interactive = true; playBtn.down = function (x, y, obj) { if (matchInProgress) { return; } simulateMatch(); playBtn.destroy(); playBtn = null; // Next match button (bottom middle, below Play Match) var nextBtnX = 2048 / 2 - 200; var nextBtnY = playBtnY + 120; nextBtn = makeLabel("Next Match", nextBtnX, nextBtnY, 60, "#fdcb6e"); nextBtn.interactive = true; nextBtn.down = function (x, y, obj) { for (var i = 0; i < allPlayers.length; i++) { allPlayers[i].stamina = Math.min(allPlayers[i].maxStamina, allPlayers[i].stamina + randomInt(1, 3)); } if (isSeasonOver()) { // ... (season end logic unchanged) // For brevity, call newGame() to reset for new season newGame(); } else { var oppIdx = getCurrentOpponentIdx(); if (oppIdx !== null) { opponentTeam = makeOpponentTeam(); opponentTeam.name = leagueTeams[oppIdx].name; } clearMatchText(); nextBtn.destroy(); nextBtn = null; refreshUI(); } }; game.addChild(nextBtn); }; game.addChild(playBtn); // 8. Nav Buttons (bottom, evenly spaced) showNavButtons(); // 9. Update budget and info updateBudgetText(); showInfo("Pick lineup, buy/sell, then Play Match!"); } // --- INIT UI --- var currentScreen = "main"; // "main", "transfer", "league", "youth" var navBtns = []; function showScreen(screen) { currentScreen = screen; clearAllUI(); // Always show nav buttons showNavButtons(); if (screen === "main") { updateSquadLabels(); updateBenchLabels(); updateOpponentLabels(); updateBudgetText(); showInfo("Pick lineup, buy/sell, then Play Match!"); // Play Match button var playBtnX = 2048 / 2 - 200; var playBtnY = 2048 - 200; playBtn = makeLabel("Play Match", playBtnX, playBtnY, 70, "#00cec9"); playBtn.interactive = true; playBtn.down = function (x, y, obj) { if (matchInProgress) return; simulateMatch(); playBtn.destroy(); playBtn = null; // Next match button var nextBtnX = 2048 / 2 - 200; var nextBtnY = playBtnY + 120; nextBtn = makeLabel("Next Match", nextBtnX, nextBtnY, 60, "#fdcb6e"); nextBtn.interactive = true; nextBtn.down = function (x, y, obj) { // Restore stamina a bit for (var i = 0; i < allPlayers.length; i++) { allPlayers[i].stamina = Math.min(allPlayers[i].maxStamina, allPlayers[i].stamina + randomInt(1, 3)); } // Check if season is over if (isSeasonOver()) { // Calculate final league position for user var sortedLeague = leagueTeams.slice().sort(function (a, b) { if (b.points !== a.points) return b.points - a.points; var gdA = a.goalsFor - a.goalsAgainst; var gdB = b.goalsFor - b.goalsAgainst; if (gdB !== gdA) return gdB - gdA; return b.goalsFor - a.goalsFor; }); var userFinalPos = 1; for (var i = 0; i < sortedLeague.length; i++) { if (sortedLeague[i].name === "You") { userFinalPos = i + 1; break; } } // Prize money by position var prize = 5; if (userFinalPos === 1) prize = 50;else if (userFinalPos === 2) prize = 30;else if (userFinalPos === 3) prize = 20;else if (userFinalPos === 4) prize = 10; // Award prize budget += prize; // Champions League logic if (userFinalPos === 1) { // User qualifies for Champions League // Simulate a simple 8-team knockout tournament var clTeams = [{ name: "You", players: squad.slice() }, { name: "Real Madrid", players: [makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer()] }, { name: "Manchester City", players: [makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer()] }, { name: "Bayern Munich", players: [makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer()] }, { name: "Barcelona", players: [makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer()] }, { name: "PSG", players: [makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer()] }, { name: "Juventus", players: [makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer()] }, { name: "Liverpool", players: [makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer()] }]; // Shuffle teams for random draw for (var i = clTeams.length - 1; i > 0; i--) { var j = randomInt(0, i); var temp = clTeams[i]; clTeams[i] = clTeams[j]; clTeams[j] = temp; } // Find user index var userCLIdx = -1; for (var i = 0; i < clTeams.length; i++) { if (clTeams[i].name === "You") { userCLIdx = i; break; } } var clLog = []; var roundNames = ["Quarterfinals", "Semifinals", "Final"]; var roundPrize = [20, 30, 50]; // QF, SF, Winner var userAlive = true; var userRound = 0; var userCLPlace = "Winner"; var clPrize = 0; var clOppName = ""; var clOppScore = 0, userScore = 0; var clTeamsLeft = clTeams.slice(); for (var round = 0; round < 3 && userAlive; round++) { clLog.push("Champions League " + roundNames[round] + ":"); var nextRoundTeams = []; for (var m = 0; m < clTeamsLeft.length; m += 2) { var t1 = clTeamsLeft[m]; var t2 = clTeamsLeft[m + 1]; // Simulate match var t1Strength = 0, t2Strength = 0; for (var k = 0; k < 5; k++) { t1Strength += t1.players[k].attack + t1.players[k].defense + t1.players[k].stamina; t2Strength += t2.players[k].attack + t2.players[k].defense + t2.players[k].stamina; } var t1Goals = Math.max(0, Math.floor(t1Strength / 45) + randomInt(0, 1)); var t2Goals = Math.max(0, Math.floor(t2Strength / 45) + randomInt(0, 1)); // If draw, random winner if (t1Goals === t2Goals) { if (Math.random() < 0.5) t1Goals++;else t2Goals++; } clLog.push(t1.name + " " + t1Goals + " - " + t2Goals + " " + t2.name); if (t1.name === "You" || t2.name === "You") { userScore = t1.name === "You" ? t1Goals : t2Goals; clOppScore = t1.name === "You" ? t2Goals : t1Goals; clOppName = t1.name === "You" ? t2.name : t1.name; if (userScore > clOppScore) { clLog.push("You advance to the next round!"); clPrize += roundPrize[round]; userRound = round + 1; nextRoundTeams.push(t1.name === "You" ? t1 : t2); } else { clLog.push("You are eliminated by " + clOppName + "!"); userAlive = false; userCLPlace = round === 0 ? "Quarterfinalist" : round === 1 ? "Semifinalist" : "Finalist"; } } else { // Winner advances nextRoundTeams.push(t1Goals > t2Goals ? t1 : t2); } } clTeamsLeft = nextRoundTeams; } if (userAlive) { clLog.push("Congratulations! You are the Champions League Winner!"); clPrize += 50; userCLPlace = "Winner"; } if (clPrize > 0) { budget += clPrize; clLog.push("Champions League prize: $" + clPrize + "M"); } showInfo("Season finished! You placed #1 and qualified for the Champions League!\n" + "Champions League result: " + userCLPlace + ". Prize: $" + (prize + clPrize) + "M. Table resets for new season."); updateBudgetText(); matchLog = matchLog.concat(clLog); showMatchLog(); } else { showInfo("Season finished! You placed #" + userFinalPos + ". Prize: $" + prize + "M. Table resets for new season."); updateBudgetText(); } // Decrement seasonsRemaining for transfer market players, remove those at 0 for (var i = allPlayers.length - 1; i >= 0; i--) { var p = allPlayers[i]; if (typeof p.seasonsRemaining === "number" && p.seasonsRemaining !== null) { p.seasonsRemaining--; if (p.seasonsRemaining <= 0) { allPlayers.splice(i, 1); showInfo("Player " + p.name + " has retired/left after 3 seasons."); } } } updateSquadAndBench(); // --- Generate up to 3 transfer offers for squad/bench players at end of season --- transferOffers = []; var candidates = squad.concat(bench).slice(); for (var i = candidates.length - 1; i > 0; i--) { var j = randomInt(0, i); var temp = candidates[i]; candidates[i] = candidates[j]; candidates[j] = temp; } var offersToMake = Math.min(3, candidates.length); for (var i = 0; i < offersToMake; i++) { var p = candidates[i]; var offerVal = Math.floor(p.value * (randomInt(90, 120) / 100)); var club = OFFER_CLUBS[randomInt(0, OFFER_CLUBS.length - 1)]; transferOffers.push({ player: p, offerValue: offerVal, club: club }); } if (transferOffers.length > 0) { showInfo("You have received " + transferOffers.length + " transfer offer(s) for your players!"); } initLeague(); initTransferList(); var oppIdx = getCurrentOpponentIdx(); if (oppIdx !== null) { opponentTeam = makeOpponentTeam(); opponentTeam.name = leagueTeams[oppIdx].name; } clearMatchText(); nextBtn.destroy(); nextBtn = null; showScreen("main"); return; } // Next opponent in league var oppIdx = getCurrentOpponentIdx(); if (oppIdx !== null) { opponentTeam = makeOpponentTeam(); opponentTeam.name = leagueTeams[oppIdx].name; } clearMatchText(); nextBtn.destroy(); nextBtn = null; showScreen("main"); }; game.addChild(nextBtn); }; game.addChild(playBtn); } else if (screen === "transfer") { // --- Centered Transfer Market Layout --- clearArray(transferBtns); clearArray(buyBtns); var sectionWidth = 1100; var sectionX = (2048 - sectionWidth) / 2; var rowHeight = 64; var sectionHeight = (transferList.length + 1) * rowHeight + 120; var startY = 400; // Start well below the top for visual balance // Remove old transferText if present if (transferText) { transferText.destroy(); } transferText = makeLabel("Transfer Market", 2048 / 2, startY - 90, 56, "#00b894"); transferText.anchor.set(0.5, 0); // Center header horizontally game.addChild(transferText); // Calculate X positions for player info and buy button var playerInfoX = sectionX + 40; var buyBtnX = sectionX + sectionWidth - 180; for (var i = 0; i < transferList.length; i++) { var p = transferList[i]; // Centered row Y var rowY = startY + i * rowHeight; // Player info label, left-aligned in section var t = makeLabel(p.name + " [A:" + p.attack + " D:" + p.defense + " S:" + p.stamina + "] $" + p.value + "M", playerInfoX, rowY, 44, "#fff"); t.anchor.set(0, 0); // Left align in section game.addChild(t); transferBtns.push(t); // Buy button, right-aligned in section var buyBtn = makeLabel("Buy", buyBtnX, rowY, 40, "#00b894"); buyBtn.idx = i; buyBtn.interactive = true; buyBtn.down = function (idxCopy) { return function (x, y, obj) { var idx = idxCopy; var p = transferList[idx]; if (!p) { showInfo("Player not available."); return; } if (budget < p.value) { showInfo("Not enough budget!"); return; } // Allow buying a player as long as the total number of players is less than the maximum allowed if (allPlayers.length >= SQUAD_SIZE + BENCH_SIZE) { showInfo("Squad full! Sell a player first."); return; } budget -= p.value; // When buying, always set seasonsRemaining=3 allPlayers.push(new Player(p.name, p.attack, p.defense, p.stamina, p.value, 3)); updateSquadAndBench(); updateBudgetText(); showInfo("Bought " + p.name + " for $" + p.value + "M"); // Remove from transfer list, add new transferList.splice(idx, 1, makeRandomPlayer()); showScreen("transfer"); }; }(i); game.addChild(buyBtn); buyBtns.push(buyBtn); } updateBudgetText(); showInfo("Buy top players for your team!"); } else if (screen === "league") { updateOpponentLabels(); showInfo("Check the league table and your next opponent."); } else if (screen === "youth") { // Only show youth academy and transfer offers clearArray(youthLabels); clearArray(promoteBtns); clearArray(sellYouthBtns); // --- Centered Youth Academy Layout --- var sectionWidth = 1100; var youthX = (2048 - sectionWidth) / 2; var rowHeight = 64; var youthY = 400; // Centered header var youthHeader = makeLabel("Youth Academy", 2048 / 2, youthY, 54, "#81ecec"); youthHeader.anchor.set(0.5, 0); game.addChild(youthHeader); youthLabels.push(youthHeader); // Calculate X positions for player info and buttons var playerInfoX = youthX + 40; var promoteBtnX = youthX + sectionWidth - 320; var sellBtnX = youthX + sectionWidth - 160; for (var i = 0; i < youthAcademy.length; i++) { var yp = youthAcademy[i]; var rowY = youthY + 70 + i * rowHeight; var t = makeLabel(yp.name + " [A:" + yp.attack + " D:" + yp.defense + " S:" + yp.stamina + "] $" + yp.value + "M", playerInfoX, rowY, 40, "#fff"); t.anchor.set(0, 0); game.addChild(t); youthLabels.push(t); // Promote button var promoteBtn = makeLabel("Promote", promoteBtnX, rowY, 36, "#00b894"); promoteBtn.idx = i; promoteBtn.interactive = true; promoteBtn.down = function (idxCopy) { return function (x, y, obj) { var idx = idxCopy; var p = youthAcademy[idx]; if (!p) { showInfo("No youth player to promote."); return; } // Allow promoting a player as long as the total number of players is less than the maximum allowed if (allPlayers.length >= SQUAD_SIZE + BENCH_SIZE) { showInfo("Squad full! Sell a player first."); return; } allPlayers.push(new Player(p.name, p.attack, p.defense, p.stamina, p.value, null)); updateSquadAndBench(); showInfo("Promoted " + p.name + " to your team!"); youthAcademy.splice(idx, 1); showScreen("youth"); }; }(i); game.addChild(promoteBtn); promoteBtns.push(promoteBtn); // Sell button var sellBtn = makeLabel("Sell", sellBtnX, rowY, 36, "#fdcb6e"); sellBtn.idx = i; sellBtn.interactive = true; sellBtn.down = function (idxCopy) { return function (x, y, obj) { var idx = idxCopy; var p = youthAcademy[idx]; if (!p) { showInfo("No youth player to sell."); return; } budget += p.value; updateBudgetText(); showInfo("Sold " + p.name + " for $" + p.value + "M"); youthAcademy.splice(idx, 1); showScreen("youth"); }; }(i); game.addChild(sellBtn); sellYouthBtns.push(sellBtn); } // Transfer offers clearArray(offerLabels); clearArray(acceptOfferBtns); clearArray(rejectOfferBtns); var offerX = youthX + 40; var offerY = youthY + 70 + Math.max(1, youthAcademy.length) * rowHeight + 40; if (transferOffers.length > 0) { var offerHeader = makeLabel("Transfer Offers", 2048 / 2, offerY, 54, "#fdcb6e"); offerHeader.anchor.set(0.5, 0); game.addChild(offerHeader); offerLabels.push(offerHeader); for (var i = 0; i < transferOffers.length; i++) { var offer = transferOffers[i]; var p = offer.player; var rowY = offerY + 70 + i * rowHeight; var txt = offer.club + " offers $" + offer.offerValue + "M for " + p.name; var t = makeLabel(txt, offerX, rowY, 40, "#fff"); t.anchor.set(0, 0); game.addChild(t); offerLabels.push(t); // Accept button var acceptBtn = makeLabel("Accept", promoteBtnX, rowY, 36, "#00b894"); acceptBtn.idx = i; acceptBtn.interactive = true; acceptBtn.down = function (idxCopy) { return function (x, y, obj) { var idx = idxCopy; var offer = transferOffers[idx]; var p = offer.player; var allIdx = allPlayers.indexOf(p); if (allIdx !== -1) { budget += offer.offerValue; allPlayers.splice(allIdx, 1); updateSquadAndBench(); updateBudgetText(); showInfo("Sold " + p.name + " to " + offer.club + " for $" + offer.offerValue + "M"); transferOffers.splice(idx, 1); showScreen("youth"); } else { showInfo("Player not found."); } }; }(i); game.addChild(acceptBtn); acceptOfferBtns.push(acceptBtn); // Reject button var rejectBtn = makeLabel("Reject", sellBtnX, rowY, 36, "#ff7675"); rejectBtn.idx = i; rejectBtn.interactive = true; rejectBtn.down = function (idxCopy) { return function (x, y, obj) { var idx = idxCopy; var offer = transferOffers[idx]; showInfo("Rejected offer for " + offer.player.name + "."); transferOffers.splice(idx, 1); showScreen("youth"); }; }(i); game.addChild(rejectBtn); rejectOfferBtns.push(rejectBtn); } } updateBudgetText(); showInfo("Manage your youth academy and transfer offers."); } } function showNavButtons() { clearArray(navBtns); // Button positions - bottom of screen, evenly spaced, consistent style var btnY = 2732 - 100; // 100px from bottom edge for safe area var btnCount = 4; var btnWidth = 320; var btnSpacing = 60; var totalWidth = btnCount * btnWidth + (btnCount - 1) * btnSpacing; var btnXStart = Math.max(60, (2048 - totalWidth) / 2); var btns = [{ label: "Main", screen: "main", color: 0x00CEC9 }, { label: "Transfer Market", screen: "transfer", color: 0x00B894 }, { label: "League Table", screen: "league", color: 0xFDCB6E }, { label: "Youth Academy", screen: "youth", color: 0x81ECEC }]; for (var i = 0; i < btns.length; i++) { var b = btns[i]; var btnX = btnXStart + i * (btnWidth + btnSpacing); var navBtn = new Text2(b.label, { size: 48, fill: b.color, font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" }); navBtn.x = btnX + btnWidth / 2; navBtn.y = btnY; navBtn.anchor.set(0.5, 0.5); navBtn.interactive = true; navBtn.screen = b.screen; navBtn.down = function (screenName) { return function (x, y, obj) { showScreen(screenName); }; }(b.screen); game.addChild(navBtn); navBtns.push(navBtn); } } function initUI() { guiY = 0; // Title (centered, consistent font) var title = new Text2("Mini Football Manager", { size: 90, fill: 0x00CEC9, font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" }); title.x = 2048 / 2; title.y = guiY + 40; title.anchor.set(0.5, 0); game.addChild(title); // Budget (centered below title) budgetText = new Text2("Budget: $" + budget + "M", { size: 60, fill: "#fff", font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" }); budgetText.x = 2048 / 2; budgetText.y = guiY + 140; budgetText.anchor.set(0.5, 0); game.addChild(budgetText); // Info (centered below budget) infoText = new Text2("", { size: 54, fill: 0xFDCB6E, font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" }); infoText.x = 2048 / 2; infoText.y = guiY + 210; infoText.anchor.set(0.5, 0); game.addChild(infoText); showScreen("main"); } // --- GAME START --- function newGame() { budget = INITIAL_BUDGET; initLeague(); initPlayers(); initTransferList(); // --- YOUTH ACADEMY RESET --- youthAcademy = []; if (youthTimer) { LK.clearInterval(youthTimer); youthTimer = null; } // --- TRANSFER OFFERS RESET --- transferOffers = []; if (OFFER_TIMER) { LK.clearInterval(OFFER_TIMER); OFFER_TIMER = null; } clearArray(offerLabels); clearArray(acceptOfferBtns); clearArray(rejectOfferBtns); // Set first opponent in league var oppIdx = getCurrentOpponentIdx(); if (oppIdx !== null) { opponentTeam = makeOpponentTeam(); opponentTeam.name = leagueTeams[oppIdx].name; } else { opponentTeam = makeOpponentTeam(); } matchInProgress = false; matchLog = []; matchResult = null; selectedPlayerIdx = null; selectedBenchIdx = null; initUI(); } newGame(); // --- END ---
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a3d2f
});
/****
* Game Code
****/
// Player class: represents a footballer
// --- CONSTANTS ---
var Player = function Player(name, attack, defense, stamina, value, seasonsRemaining) {
var self = {};
self.name = name;
self.attack = attack;
self.defense = defense;
self.stamina = stamina;
self.value = value;
self.maxStamina = stamina;
self.inSquad = false; // true if in starting 5
self.seasonsRemaining = typeof seasonsRemaining === "number" ? seasonsRemaining : null; // null for non-transfer players, or integer for transfer market
return self;
};
// Team class: holds a list of players
var Team = function Team(name, players) {
var self = {};
self.name = name;
self.players = players; // array of Player
return self;
};
var SQUAD_SIZE = 5;
var BENCH_SIZE = 3;
var INITIAL_BUDGET = 100;
var PLAYER_MIN_VALUE = 10;
var PLAYER_MAX_VALUE = 40;
// --- GLOBALS ---
var allPlayers = []; // All players owned by user
var squad = []; // Starting 5
var bench = []; // Bench 3
var transferList = []; // Players available to buy
var budget = INITIAL_BUDGET;
var opponentTeam = null;
var matchInProgress = false;
var matchLog = [];
var matchResult = null;
var selectedPlayerIdx = null; // For swapping
var selectedBenchIdx = null; // For swapping
var infoText = null;
var budgetText = null;
var matchText = null;
var transferText = null;
var transferBtns = [];
var swapBtns = [];
var playBtn = null;
var nextBtn = null;
var sellBtns = [];
var buyBtns = [];
var squadLabels = [];
var benchLabels = [];
var opponentLabels = [];
var guiY = 0;
// --- YOUTH ACADEMY ---
var youthAcademy = []; // Array of young players waiting for promotion/sale
var youthLabels = [];
var promoteBtns = [];
var sellYouthBtns = [];
var youthTimer = null;
var YOUTH_TIMER_INTERVAL = 10000; // 10 seconds for demo (tweak as needed)
var YOUTH_MAX = 3; // Max youth in academy at once
// --- TRANSFER OFFERS SYSTEM ---
// Each offer: {player: Player, offerValue: number, club: string}
var transferOffers = [];
var offerLabels = [];
var acceptOfferBtns = [];
var rejectOfferBtns = [];
var OFFER_TIMER = null;
var OFFER_INTERVAL = 15000; // 15 seconds for demo
var OFFER_CLUBS = ["Galatasaray", "Fenerbahce", "Besiktas", "Trabzonspor", "Basaksehir", "Sivasspor", "Konyaspor", "Antalyaspor", "Alanyaspor", "Denizlispor"];
// --- UTILS ---
function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function randomName() {
var first = ["Ahmet", "Mehmet", "Mustafa", "Ali", "Hüseyin", "Hasan", "Cesur", "Osman", "Yusuf", "Murat", "Emre", "Burak", "Fatih", "Serkan", "Onur", "Barış", "Cem", "Eren", "Kaan", "Deniz", "Çınar", "Aziz", "Ege", "Miraç"];
var last = ["Yılmaz", "Kaya", "Demir", "Şahin", "Çelik", "Yıldız", "Yıldırım", "Aydın", "Öztürk", "Arslan", "Doğan", "Kılıç", "Aslan", "Polat", "Koç", "Kurt", "Özdemir", "Aksoy", "Güneş", "Bozkurt", "Bozbalak", "Sakız", "Fizikli"];
return first[randomInt(0, first.length - 1)] + " " + last[randomInt(0, last.length - 1)];
}
function makeRandomPlayer() {
var atk = randomInt(5, 15);
var def = randomInt(5, 15);
var sta = randomInt(10, 20);
var val = Math.floor((atk + def + sta) / 3) + randomInt(PLAYER_MIN_VALUE, PLAYER_MAX_VALUE);
return new Player(randomName(), atk, def, sta, val);
}
// Real-life Turkish Super Lig squads (2023/24, main players, 5 per team for demo)
var realSquads = {
"Galatasaray": [new Player("Mauro Icardi", 18, 8, 16, 40), new Player("Dries Mertens", 16, 7, 15, 36), new Player("Lucas Torreira", 10, 16, 17, 34), new Player("Kerem Aktürkoğlu", 15, 8, 15, 32), new Player("Fernando Muslera", 7, 18, 16, 35)],
"Fenerbahce": [new Player("Edin Dzeko", 17, 7, 15, 38), new Player("Dusan Tadic", 16, 8, 15, 36), new Player("Fred", 12, 14, 16, 33), new Player("Sebastian Szymanski", 15, 9, 15, 32), new Player("Dominik Livakovic", 6, 17, 16, 34)],
"Besiktas": [new Player("Cenk Tosun", 16, 7, 15, 34), new Player("Rachid Ghezzal", 15, 8, 14, 32), new Player("Salih Uçan", 12, 13, 15, 30), new Player("Omar Colley", 8, 16, 15, 31), new Player("Mert Günok", 6, 17, 15, 30)],
"Trabzonspor": [new Player("Edin Visca", 15, 8, 15, 32), new Player("Anastasios Bakasetas", 15, 9, 15, 32), new Player("Uğurcan Çakır", 6, 17, 16, 33), new Player("Enis Bardhi", 14, 8, 14, 29), new Player("Joaquin Fernandez", 8, 15, 14, 28)],
"Basaksehir": [new Player("Danijel Aleksic", 14, 8, 14, 28), new Player("Leo Duarte", 8, 15, 14, 27), new Player("Serdar Gürler", 13, 8, 14, 27), new Player("Mahmut Tekdemir", 9, 14, 14, 26), new Player("Volkan Babacan", 6, 16, 14, 25)],
"Sivasspor": [new Player("Mustapha Yatabare", 14, 8, 14, 27), new Player("Max Gradel", 13, 8, 14, 27), new Player("Hakan Arslan", 10, 13, 14, 25), new Player("Uğur Çiftçi", 8, 14, 14, 24), new Player("Ali Şaşal Vural", 6, 16, 14, 24)],
"Konyaspor": [new Player("Sokol Cikalleshi", 14, 8, 14, 27), new Player("Amir Hadziahmetovic", 11, 13, 14, 25), new Player("Guilherme", 10, 13, 14, 25), new Player("Francisco Calvo", 8, 15, 14, 25), new Player("Ibrahim Sehic", 6, 16, 14, 24)],
"Antalyaspor": [new Player("Haji Wright", 14, 8, 14, 27), new Player("Fernando", 11, 13, 14, 25), new Player("Bünyamin Balcı", 10, 13, 14, 24), new Player("Veysel Sarı", 8, 15, 14, 24), new Player("Helton Leite", 6, 16, 14, 24)],
"Alanyaspor": [new Player("Efecan Karaca", 14, 8, 14, 27), new Player("Famara Diedhiou", 13, 8, 14, 26), new Player("Yusuf Özdemir", 10, 13, 14, 24), new Player("Fidan Aliti", 8, 15, 14, 24), new Player("Runar Runarsson", 6, 16, 14, 24)],
"Denizlispor": [new Player("Ömer Şişmanoğlu", 13, 8, 14, 25), new Player("Mustafa Yumlu", 8, 15, 14, 24), new Player("Gökhan Süzen", 10, 13, 14, 23), new Player("Oğuz Yılmaz", 8, 14, 14, 23), new Player("Adam Stachowiak", 6, 16, 14, 23)]
};
function makeOpponentTeam() {
// List of realistic Turkish club names
var clubNames = ["Denizlispor", "Sivasspor", "Galatasaray", "Fenerbahce", "Trabzonspor", "Besiktas", "Basaksehir", "Konyaspor", "Antalyaspor", "Alanyaspor"];
// Pick a random club name for the opponent
var clubName = clubNames[randomInt(0, clubNames.length - 1)];
var oppPlayers;
if (realSquads[clubName]) {
// Use real squad, clone to avoid reference issues
oppPlayers = [];
for (var i = 0; i < SQUAD_SIZE; i++) {
var p = realSquads[clubName][i];
oppPlayers.push(clonePlayer(p));
}
} else {
// Fallback to random
oppPlayers = [];
for (var i = 0; i < SQUAD_SIZE; i++) {
oppPlayers.push(makeRandomPlayer());
}
}
return new Team(clubName, oppPlayers);
}
function clonePlayer(p) {
return new Player(p.name, p.attack, p.defense, p.stamina, p.value, p.seasonsRemaining);
}
// --- INIT DATA ---
function initPlayers() {
allPlayers = [];
for (var i = 0; i < SQUAD_SIZE + BENCH_SIZE; i++) {
// For initial squad, generate lower stats (attack, defense, stamina)
var atk = randomInt(4, 8);
var def = randomInt(4, 8);
var sta = randomInt(8, 13);
var val = Math.floor((atk + def + sta) / 3) + randomInt(PLAYER_MIN_VALUE, PLAYER_MIN_VALUE + 5);
allPlayers.push(new Player(randomName(), atk, def, sta, val));
}
updateSquadAndBench();
}
function updateSquadAndBench() {
squad = [];
bench = [];
// Ensure squad has at most SQUAD_SIZE players and bench has remaining
for (var i = 0; i < allPlayers.length; i++) {
if (i < SQUAD_SIZE) {
allPlayers[i].inSquad = true;
// Ensure we don't add more than SQUAD_SIZE players to the squad
if (squad.length < SQUAD_SIZE) {
squad.push(allPlayers[i]);
} else {
// If somehow we have too many players marked as squad, put them on bench
allPlayers[i].inSquad = false;
bench.push(allPlayers[i]);
}
} else {
allPlayers[i].inSquad = false;
bench.push(allPlayers[i]);
}
}
// If allPlayers has less than SQUAD_SIZE, squad will naturally have fewer players.
// No need to fill empty slots, the updateSquadLabels function handles this.
}
function initTransferList() {
transferList = [];
// List of latest, highest-valued real-world football players (2024, top market values, demo)
var topPlayers = [new Player("Kylian Mbappé", 20, 12, 19, 180), new Player("Erling Haaland", 21, 10, 18, 170), new Player("Jude Bellingham", 18, 14, 18, 150), new Player("Vinícius Júnior", 19, 12, 18, 150), new Player("Phil Foden", 17, 13, 17, 130), new Player("Bukayo Saka", 17, 12, 17, 120), new Player("Rodri", 14, 18, 17, 120), new Player("Jamal Musiala", 17, 12, 17, 120), new Player("Victor Osimhen", 19, 10, 17, 110), new Player("Florian Wirtz", 16, 12, 17, 110), new Player("Pedri", 15, 13, 17, 100), new Player("Declan Rice", 13, 17, 17, 100), new Player("Harry Kane", 20, 10, 16, 100), new Player("Martin Ødegaard", 16, 13, 16, 100), new Player("Rafael Leão", 18, 10, 16, 90), new Player("Khvicha Kvaratskhelia", 17, 11, 16, 90), new Player("Josko Gvardiol", 10, 18, 16, 90), new Player("Gavi", 14, 14, 16, 90), new Player("Alejandro Balde", 12, 15, 16, 80), new Player("William Saliba", 9, 18, 16, 80), new Player("Son Heung Min", 19, 11, 17, 110)];
// Always show 6 random top players in the transfer market, no duplicates
var usedIdx = [];
for (var i = 0; i < 6; i++) {
var idx;
do {
idx = randomInt(0, topPlayers.length - 1);
} while (usedIdx.indexOf(idx) !== -1);
usedIdx.push(idx);
// When adding to transferList, set seasonsRemaining=3 for transfer market players
var p = topPlayers[idx];
transferList.push(new Player(p.name, p.attack, p.defense, p.stamina, p.value, 3));
}
}
// --- UI HELPERS ---
function clearArray(arr) {
while (arr.length > 0) {
var el = arr.pop();
if (el && el.destroy) {
el.destroy();
}
}
}
function makeLabel(txt, x, y, size, color) {
// Consistent font, color, and size for all labels
var t = new Text2(txt, {
size: size || 60,
fill: color || "#fff",
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
});
t.x = x;
t.y = y;
t.anchor = t.anchor || {
set: function set() {}
};
return t;
}
function updateBudgetText() {
if (budgetText) {
budgetText.setText("Budget: $" + budget + "M");
budgetText.anchor && budgetText.anchor.set && budgetText.anchor.set(0.5, 0);
}
}
function showInfo(msg) {
if (infoText) {
infoText.setText(msg);
infoText.anchor && infoText.anchor.set && infoText.anchor.set(0.5, 0);
}
}
function updateSquadLabels() {
clearArray(squadLabels);
// Centered squad section
var sectionWidth = 1100;
var sectionX = (2048 - sectionWidth) / 2;
var startY = guiY + 260;
var rowSpacing = 64;
var swapBtnX = sectionX + sectionWidth - 220;
var sellBtnX = sectionX + sectionWidth - 100;
for (var i = 0; i < SQUAD_SIZE; i++) {
var p = squad[i];
var rowY = startY + i * rowSpacing;
if (!p) {
var t = makeLabel(i + 1 + ". Empty Slot", sectionX + 40, rowY, 48, "#aaaaaa");
t.anchor.set(0, 0);
game.addChild(t);
squadLabels.push(t);
continue;
}
var seasonsTxt = typeof p.seasonsRemaining === "number" && p.seasonsRemaining !== null ? " (" + p.seasonsRemaining + "s)" : "";
var t = makeLabel(i + 1 + ". " + p.name + " [A:" + p.attack + " D:" + p.defense + " S:" + p.stamina + "]" + seasonsTxt, sectionX + 40, rowY, 48, "#ffe066");
t.anchor.set(0, 0);
game.addChild(t);
squadLabels.push(t);
// Add swap button
var btn = makeLabel("↔", swapBtnX, rowY, 48, "#fff");
btn.idx = i;
btn.anchor.set(0.5, 0);
btn.interactive = true;
btn.down = function (x, y, obj) {
selectedPlayerIdx = obj.idx;
if (selectedPlayerIdx !== null && squad[selectedPlayerIdx]) {
showInfo("Tap a bench player to swap with " + squad[selectedPlayerIdx].name);
} else {
showInfo("Tap a bench player to swap.");
}
};
game.addChild(btn);
swapBtns.push(btn);
// Add sell button
var sellBtn = makeLabel("Sell", sellBtnX, rowY, 40, "#ff7675");
sellBtn.idx = i;
sellBtn.anchor.set(0.5, 0);
sellBtn.interactive = true;
sellBtn.down = function (idxCopy) {
return function (x, y, obj) {
var idx = idxCopy;
var p = squad[idx];
if (!p) {
showInfo("Player not available.");
return;
}
var allIdx = allPlayers.indexOf(p);
if (allIdx !== -1) {
budget += p.value;
allPlayers.splice(allIdx, 1);
updateSquadAndBench();
updateBudgetText();
showInfo("Sold " + p.name + " for $" + p.value + "M");
refreshUI();
} else {
showInfo("Player not found in squad.");
}
};
}(i);
game.addChild(sellBtn);
sellBtns.push(sellBtn);
}
}
function updateBenchLabels() {
clearArray(benchLabels);
// Centered bench section below squad
var sectionWidth = 1100;
var sectionX = (2048 - sectionWidth) / 2;
var startY = guiY + 260 + SQUAD_SIZE * 64 + 40;
var rowSpacing = 64;
for (var i = 0; i < BENCH_SIZE; i++) {
var p = bench[i];
var rowY = startY + i * rowSpacing;
if (!p) {
var t = makeLabel("B" + (i + 1) + ". Empty Slot", sectionX + 40, rowY, 48, "#aaaaaa");
t.anchor.set(0, 0);
game.addChild(t);
benchLabels.push(t);
continue;
}
var seasonsTxt = typeof p.seasonsRemaining === "number" && p.seasonsRemaining !== null ? " (" + p.seasonsRemaining + "s)" : "";
var t = makeLabel("B" + (i + 1) + ". " + p.name + " [A:" + p.attack + " D:" + p.defense + " S:" + p.stamina + "]" + seasonsTxt, sectionX + 40, rowY, 48, "#b2bec3");
t.anchor.set(0, 0);
game.addChild(t);
benchLabels.push(t);
t.idx = i;
t.interactive = true;
t.down = function (x, y, obj) {
if (selectedPlayerIdx !== null) {
var sIdx = selectedPlayerIdx;
var bIdx = obj.idx;
if (squad[sIdx] && bench[bIdx]) {
var temp = squad[sIdx];
squad[sIdx] = bench[bIdx];
bench[bIdx] = temp;
} else if (!squad[sIdx] && bench[bIdx]) {
squad[sIdx] = bench[bIdx];
bench[bIdx] = undefined;
} else if (squad[sIdx] && !bench[bIdx]) {
bench[bIdx] = squad[sIdx];
squad[sIdx] = undefined;
} else {
selectedPlayerIdx = null;
showInfo("Cannot swap with empty slots.");
refreshUI();
return;
}
allPlayers = [];
for (var j = 0; j < squad.length; j++) {
if (squad[j]) allPlayers.push(squad[j]);
}
for (var j = 0; j < bench.length; j++) {
if (bench[j]) allPlayers.push(bench[j]);
}
updateSquadAndBench();
selectedPlayerIdx = null;
showInfo("Swapped players.");
refreshUI();
}
};
}
}
function updateTransferLabels() {
clearArray(transferBtns);
clearArray(buyBtns);
// --- Centered Transfer Market Layout ---
// Calculate center X for the section
var sectionWidth = 1100;
var sectionX = (2048 - sectionWidth) / 2;
var rowHeight = 64;
var sectionHeight = (transferList.length + 1) * rowHeight + 120;
var startY = 400; // Start well below the top for visual balance
// Remove old transferText if present
if (transferText) {
transferText.destroy();
}
// Centered header
transferText = makeLabel("Transfer Market", 2048 / 2, startY - 90, 56, "#00b894");
transferText.anchor.set(0.5, 0); // Center header horizontally
game.addChild(transferText);
// Calculate X positions for player info and buy button
var playerInfoX = sectionX + 40;
var buyBtnX = sectionX + sectionWidth - 180;
for (var i = 0; i < transferList.length; i++) {
var p = transferList[i];
// Centered row Y
var rowY = startY + i * rowHeight;
// Player info label, left-aligned in section
var t = makeLabel(p.name + " [A:" + p.attack + " D:" + p.defense + " S:" + p.stamina + "] $" + p.value + "M", playerInfoX, rowY, 44, "#fff");
t.anchor.set(0, 0); // Left align in section
game.addChild(t);
transferBtns.push(t);
// Buy button, right-aligned in section
var buyBtn = makeLabel("Buy", buyBtnX, rowY, 40, "#00b894");
buyBtn.idx = i;
buyBtn.interactive = true;
buyBtn.down = function (idxCopy) {
return function (x, y, obj) {
var idx = idxCopy;
var p = transferList[idx];
if (!p) {
showInfo("Player not available.");
return;
}
if (budget < p.value) {
showInfo("Not enough budget!");
return;
}
// Allow buying a player as long as the total number of players is less than the maximum allowed
if (allPlayers.length >= SQUAD_SIZE + BENCH_SIZE) {
showInfo("Squad full! Sell a player first.");
return;
}
budget -= p.value;
// When buying, always set seasonsRemaining=3
allPlayers.push(new Player(p.name, p.attack, p.defense, p.stamina, p.value, 3));
updateSquadAndBench();
updateBudgetText();
showInfo("Bought " + p.name + " for $" + p.value + "M");
// Remove from transfer list, add new
transferList.splice(idx, 1, makeRandomPlayer());
refreshUI();
};
}(i);
game.addChild(buyBtn);
buyBtns.push(buyBtn);
}
}
function updateOpponentLabels() {
clearArray(opponentLabels);
// Position opponent section at bottom-left (for reference, but now only for opponent info)
var oppStartY = 2048 - (SQUAD_SIZE + 2) * 120 - 200; // increased row height and more margin for opponent section
if (oppStartY < guiY + 1800) {
oppStartY = guiY + 1800;
} // push down if needed for more space
// --- League Table: show all teams, slightly larger, and moved to the left ---
// Place league table just above the opponent section, but below the transfer market
var leagueWidth = 600; // slightly larger
var leagueX = 80; // move to the left side of the screen
var leagueY = oppStartY - 650; // place above opponent section, below transfer market
if (leagueY < guiY + 600) leagueY = guiY + 600;
var leagueHeader = makeLabel("League Table", leagueX, leagueY, 54, "#fdcb6e"); // slightly larger font
game.addChild(leagueHeader);
opponentLabels.push(leagueHeader);
// Sort league by points, then goal difference, then goals for
var sortedLeague = leagueTeams.slice().sort(function (a, b) {
if (b.points !== a.points) {
return b.points - a.points;
}
var gdA = a.goalsFor - a.goalsAgainst;
var gdB = b.goalsFor - b.goalsAgainst;
if (gdB !== gdA) {
return gdB - gdA;
}
return b.goalsFor - a.goalsFor;
});
for (var i = 0; i < sortedLeague.length; i++) {
var team = sortedLeague[i];
var color = team.name === "You" ? "#00cec9" : "#fff";
var gd = team.goalsFor - team.goalsAgainst;
var labelTxt = i + 1 + ". " + team.name + " Pts:" + team.points + " GP:" + team.played + " W:" + team.wins + " D:" + team.draws + " L:" + team.losses + " GD:" + gd;
var teamLabel = makeLabel(labelTxt, leagueX, leagueY + 70 + i * 48, 38, color); // slightly larger font and spacing
game.addChild(teamLabel);
opponentLabels.push(teamLabel);
}
// Now show Transfer Market section below league table (replacing Next Opponent)
var transferHeader = makeLabel("Transfer Market", 80, oppStartY, 56, "#00b894");
game.addChild(transferHeader);
opponentLabels.push(transferHeader);
var transferY = oppStartY + 80;
var transferRowHeight = 48;
for (var i = 0; i < transferList.length; i++) {
var p = transferList[i];
var t = makeLabel(p.name + " [A:" + p.attack + " D:" + p.defense + " S:" + p.stamina + "] $" + p.value + "M", 80, transferY + i * transferRowHeight, 40, "#fff");
game.addChild(t);
opponentLabels.push(t);
}
}
function clearMatchText() {
if (matchText) {
matchText.destroy();
matchText = null;
}
}
function showMatchLog() {
clearMatchText();
var log = matchLog.join("\n");
matchText = new Text2(log, {
size: 48,
fill: "#fff",
wordWrap: true,
wordWrapWidth: 1800
});
// Position match summary directly underneath the Play Match button
var playBtnX = 2048 / 2 - 200; // Same as playBtn X
var playBtnY = 2048 - 200; // Same as playBtn Y
matchText.x = playBtnX;
matchText.y = playBtnY + 180; // 180px below Play Match button for extra separation
game.addChild(matchText);
}
function clearAllUI() {
clearArray(squadLabels);
clearArray(benchLabels);
clearArray(transferBtns);
clearArray(buyBtns);
clearArray(swapBtns);
clearArray(sellBtns);
clearArray(opponentLabels);
// --- YOUTH ACADEMY UI ---
clearArray(youthLabels);
clearArray(promoteBtns);
clearArray(sellYouthBtns);
if (transferText) {
transferText.destroy();
}
transferText = null;
// --- CLEAR TRANSFER OFFER UI ---
clearArray(offerLabels);
clearArray(acceptOfferBtns);
clearArray(rejectOfferBtns);
clearMatchText();
if (playBtn) {
playBtn.destroy();
}
playBtn = null;
if (nextBtn) {
nextBtn.destroy();
}
nextBtn = null;
}
// --- LEAGUE SYSTEM ---
// League teams: user + 10 Turkish clubs
var leagueClubNames = ["Denizlispor", "Sivasspor", "Galatasaray", "Fenerbahce", "Trabzonspor", "Besiktas", "Basaksehir", "Konyaspor", "Antalyaspor", "Alanyaspor"];
var leagueTeams = []; // [{name, points, played, wins, draws, losses, goalsFor, goalsAgainst}]
var leagueFixtures = []; // [{homeIdx, awayIdx}]
var currentFixtureIdx = 0;
var userTeamIdx = 0; // always 0
function initLeague() {
leagueTeams = [];
// User team
leagueTeams.push({
name: "You",
points: 0,
played: 0,
wins: 0,
draws: 0,
losses: 0,
goalsFor: 0,
goalsAgainst: 0
});
// Opponent clubs
for (var i = 0; i < leagueClubNames.length; i++) {
var clubName = leagueClubNames[i];
leagueTeams.push({
name: clubName,
points: 0,
played: 0,
wins: 0,
draws: 0,
losses: 0,
goalsFor: 0,
goalsAgainst: 0,
// Attach real squad if available for league simulation
realSquad: realSquads[clubName] ? realSquads[clubName].map(function (p) {
return clonePlayer(p);
}) : null
});
}
// Generate fixtures: each team plays every other team twice (home/away)
leagueFixtures = [];
var n = leagueTeams.length;
for (var i = 0; i < n; i++) {
for (var j = 0; j < n; j++) {
if (i !== j) {
// Only add each pair twice (home/away)
if (i < j) {
leagueFixtures.push({
homeIdx: i,
awayIdx: j
});
leagueFixtures.push({
homeIdx: j,
awayIdx: i
});
}
}
}
}
// Shuffle fixtures for variety
for (var k = leagueFixtures.length - 1; k > 0; k--) {
var r = randomInt(0, k);
var temp = leagueFixtures[k];
leagueFixtures[k] = leagueFixtures[r];
leagueFixtures[r] = temp;
}
currentFixtureIdx = 0;
}
function getCurrentOpponentIdx() {
// Find the next fixture where user is home or away
for (var i = currentFixtureIdx; i < leagueFixtures.length; i++) {
var f = leagueFixtures[i];
if (f.homeIdx === userTeamIdx || f.awayIdx === userTeamIdx) {
return f.homeIdx === userTeamIdx ? f.awayIdx : f.homeIdx;
}
}
return null;
}
function getCurrentFixture() {
for (var i = currentFixtureIdx; i < leagueFixtures.length; i++) {
var f = leagueFixtures[i];
if (f.homeIdx === userTeamIdx || f.awayIdx === userTeamIdx) {
return {
idx: i,
fixture: f
};
}
}
return null;
}
function advanceFixture() {
// Move to next user fixture
for (var i = currentFixtureIdx + 1; i < leagueFixtures.length; i++) {
var f = leagueFixtures[i];
if (f.homeIdx === userTeamIdx || f.awayIdx === userTeamIdx) {
currentFixtureIdx = i;
return;
}
}
// No more fixtures: season over
currentFixtureIdx = leagueFixtures.length;
}
function isSeasonOver() {
// If all user fixtures played
for (var i = currentFixtureIdx; i < leagueFixtures.length; i++) {
var f = leagueFixtures[i];
if (f.homeIdx === userTeamIdx || f.awayIdx === userTeamIdx) {
return false;
}
}
return true;
}
// --- GAME LOGIC ---
function simulateMatch() {
matchLog = [];
matchResult = null;
matchInProgress = true;
// --- Add a random number of youth players after each match ---
var numNewYouth = randomInt(0, 3);
if (youthAcademy.length < YOUTH_MAX && numNewYouth > 0) {
for (var i = 0; i < numNewYouth; i++) {
if (youthAcademy.length >= YOUTH_MAX) break; // Don't add more than max
// Generate a young player (attributes 1-10)
var atk = randomInt(1, 10);
var def = randomInt(1, 10);
var sta = randomInt(1, 10);
// Calculate base stat sum and average
var statSum = atk + def + sta;
var statAvg = Math.floor(statSum / 3);
// Most players: value 1-5M, some: 6-10M, all <= 10M
var val;
if (Math.random() < 0.8) {
val = Math.max(1, Math.min(5, statAvg + randomInt(0, 1)));
} else {
val = Math.max(6, Math.min(10, statAvg + randomInt(2, 4)));
if (val < 6) val = 5;
}
if (val > 10) val = 10; // Cap value at 10M for youth academy players
var p = new Player(randomName(), atk, def, sta, val, null);
youthAcademy.push(p);
}
if (numNewYouth === 1) {
showInfo("A new youth player has joined your academy!");
} else if (numNewYouth > 1) {
showInfo(numNewYouth + " new youth players have joined your academy!");
}
refreshUI();
}
// Find all fixtures for this matchday (all teams play one match)
if (currentFixtureIdx >= leagueFixtures.length) {
matchLog.push("Season is over!");
showMatchLog();
matchInProgress = false;
return;
}
// Gather all fixtures for this matchday (each team plays once)
var nTeams = leagueTeams.length;
var matchdayFixtures = [];
var teamsPlayed = {};
for (var i = currentFixtureIdx; i < leagueFixtures.length; i++) {
var f = leagueFixtures[i];
if (!teamsPlayed[f.homeIdx] && !teamsPlayed[f.awayIdx]) {
matchdayFixtures.push({
idx: i,
fixture: f
});
teamsPlayed[f.homeIdx] = true;
teamsPlayed[f.awayIdx] = true;
if (Object.keys(teamsPlayed).length >= nTeams) {
break;
}
}
}
// Simulate all matches in this matchday
var userMatchIdx = -1;
for (var m = 0; m < matchdayFixtures.length; m++) {
var fixtureObj = matchdayFixtures[m];
var fixture = fixtureObj.fixture;
var homeIdx = fixture.homeIdx;
var awayIdx = fixture.awayIdx;
var homeTeam = leagueTeams[homeIdx];
var awayTeam = leagueTeams[awayIdx];
// Prepare teams
var homePlayers, awayPlayers;
if (homeIdx === userTeamIdx) {
homePlayers = squad;
} else {
// Use real squad if available, else generate random team
if (homeTeam.realSquad) {
homePlayers = [];
for (var i = 0; i < SQUAD_SIZE; i++) {
homePlayers.push(clonePlayer(homeTeam.realSquad[i]));
}
} else {
homePlayers = [];
for (var i = 0; i < SQUAD_SIZE; i++) {
homePlayers.push(makeRandomPlayer());
}
}
}
if (awayIdx === userTeamIdx) {
awayPlayers = squad;
} else {
if (awayTeam.realSquad) {
awayPlayers = [];
for (var i = 0; i < SQUAD_SIZE; i++) {
awayPlayers.push(clonePlayer(awayTeam.realSquad[i]));
}
} else {
awayPlayers = [];
for (var i = 0; i < SQUAD_SIZE; i++) {
awayPlayers.push(makeRandomPlayer());
}
}
}
// Calculate stats
// Determine team strengths
var homeStrength = 0;
for (var i = 0; i < homePlayers.length; i++) {
homeStrength += homePlayers[i].attack + homePlayers[i].defense + homePlayers[i].stamina;
}
var awayStrength = 0;
for (var i = 0; i < awayPlayers.length; i++) {
awayStrength += awayPlayers[i].attack + awayPlayers[i].defense + awayPlayers[i].stamina;
}
var homeGoals = 0,
awayGoals = 0;
// Simulate match based on strength and randomness
// A simple model: higher strength means more chances to score
// Reduce number of chances and scoring probability for more realistic scores
var homeChances = Math.max(1, Math.floor(homeStrength / 40) + randomInt(-1, 1)); // Fewer chances, less randomness
var awayChances = Math.max(1, Math.floor(awayStrength / 40) + randomInt(-1, 1)); // Fewer chances, less randomness
for (var i = 0; i < homeChances; i++) {
if (Math.random() < 0.38) {
// Lower chance to score per chance
homeGoals++;
}
}
for (var i = 0; i < awayChances; i++) {
if (Math.random() < 0.38) {
// Lower chance to score per chance
awayGoals++;
}
}
for (var turn = 0; turn < 5; turn++) {
// Home attack (for match log details)
var atkP = homePlayers[turn];
var defP = awayPlayers[turn];
// Check if players are defined before accessing their properties
if (!atkP || !defP) {
// Skip this turn if a player is missing
continue;
}
var atkChance = atkP.attack + randomInt(0, atkP.stamina);
var defChance = defP.defense + randomInt(0, defP.stamina);
if (atkChance > defChance + 3) {
//homeGoals++; // Already accounted for in overall simulation
} else if (defChance > atkChance + 5) {
// Defensive action (for match log details)
}
// Away attack (for match log details)
var oAtkP = awayPlayers[turn];
var oDefP = homePlayers[turn];
// Check if players are defined before accessing their properties
if (!oAtkP || !oDefP) {
// Skip this turn if a player is missing
continue;
}
var oAtkChance = oAtkP.attack + randomInt(0, oAtkP.stamina);
var oDefChance = oDefP.defense + randomInt(0, oDefP.stamina);
if (oAtkChance > oDefChance + 3) {
//awayGoals++; // Already accounted for in overall simulation
} else if (oDefChance > oAtkChance + 5) {
// Defensive action (for match log details)
}
}
// Update league table
homeTeam.played += 1;
awayTeam.played += 1;
homeTeam.goalsFor += homeGoals;
homeTeam.goalsAgainst += awayGoals;
awayTeam.goalsFor += awayGoals;
awayTeam.goalsAgainst += homeGoals;
if (homeGoals > awayGoals) {
homeTeam.points += 3;
homeTeam.wins += 1;
awayTeam.losses += 1;
} else if (homeGoals < awayGoals) {
awayTeam.points += 3;
awayTeam.wins += 1;
homeTeam.losses += 1;
} else {
homeTeam.points += 1;
awayTeam.points += 1;
homeTeam.draws += 1;
awayTeam.draws += 1;
}
// If this is the user's match, log details and handle rewards
if (homeIdx === userTeamIdx || awayIdx === userTeamIdx) {
userMatchIdx = m;
var userGoals = homeIdx === userTeamIdx ? homeGoals : awayGoals;
var oppGoals = homeIdx === userTeamIdx ? awayGoals : homeGoals;
var oppIdx = homeIdx === userTeamIdx ? awayIdx : homeIdx;
var oppName = leagueTeams[oppIdx].name;
for (var turn = 0; turn < 5; turn++) {
// User attack
var atkP = squad[turn];
var defP = homeIdx === userTeamIdx ? awayPlayers[turn] : homePlayers[turn];
// Check if players are defined before accessing their properties
if (!atkP || !defP) {
// Skip this turn if a player is missing
continue;
}
var atkChance = atkP.attack + randomInt(0, atkP.stamina);
var defChance = defP.defense + randomInt(0, defP.stamina);
if (atkChance > defChance + 5 && Math.random() < 0.5) {
// Harder to score, require bigger difference and add randomness
matchLog.push("Minute " + (turn * 18 + 5) + ": " + atkP.name + " scores!");
} else if (defChance > atkChance + 3) {
matchLog.push("Minute " + (turn * 18 + 8) + ": " + defP.name + " makes a key tackle.");
}
// Opponent attack
var oAtkP = homeIdx === userTeamIdx ? awayPlayers[turn] : homePlayers[turn];
var oDefP = squad[turn];
// Check if players are defined before accessing their properties
if (!oAtkP || !oDefP) {
// Skip this turn if a player is missing
continue;
}
var oAtkChance = oAtkP.attack + randomInt(0, oAtkP.stamina);
var oDefChance = oDefP.defense + randomInt(0, oDefP.stamina);
if (oAtkChance > oDefChance + 5 && Math.random() < 0.5) {
// Harder to score, require bigger difference and add randomness
matchLog.push("Minute " + (turn * 18 + 12) + ": " + oAtkP.name + " scores!");
} else if (oDefChance > oAtkChance + 3) {
matchLog.push("Minute " + (turn * 18 + 15) + ": " + oDefP.name + " blocks a shot.");
}
}
matchLog.push("Full Time: You " + userGoals + " - " + oppGoals + " " + oppName);
// Rewards
if (userGoals > oppGoals) {
matchResult = "win";
matchLog.push("You win! +$20M");
budget += 20;
} else if (userGoals < oppGoals) {
matchResult = "lose";
matchLog.push("You lose.");
} else {
matchResult = "draw";
matchLog.push("Draw. +$5M");
budget += 5;
}
}
}
// Advance fixture pointer by number of fixtures played this matchday
currentFixtureIdx += matchdayFixtures.length;
// Restore stamina a bit after match
for (var i = 0; i < homePlayers.length; i++) {
if (homeIdx === userTeamIdx) {
homePlayers[i].stamina = Math.max(0, homePlayers[i].stamina - randomInt(3, 6)); // Decrease stamina after playing
homePlayers[i].stamina = Math.min(homePlayers[i].maxStamina, homePlayers[i].stamina + randomInt(1, 3)); // Partial recovery
}
}
for (var i = 0; i < awayPlayers.length; i++) {
if (awayIdx === userTeamIdx) {
awayPlayers[i].stamina = Math.max(0, awayPlayers[i].stamina - randomInt(3, 6)); // Decrease stamina after playing
awayPlayers[i].stamina = Math.min(awayPlayers[i].maxStamina, awayPlayers[i].stamina + randomInt(1, 3)); // Partial recovery
}
}
updateBudgetText();
showMatchLog();
matchInProgress = false;
}
function refreshUI() {
clearAllUI();
// --- UI LAYOUT OVERHAUL: Clean, structured, and visually balanced ---
// 1. Title, Budget, Info (centered, consistent spacing)
var titleY = 40;
var budgetY = titleY + 100;
var infoY = budgetY + 70;
// Title
var title = new Text2("Mini Football Manager", {
size: 90,
fill: 0x00CEC9,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
});
title.x = 2048 / 2;
title.y = titleY;
title.anchor.set(0.5, 0);
game.addChild(title);
// Budget
if (!budgetText) {
budgetText = new Text2("Budget: $" + budget + "M", {
size: 60,
fill: "#fff",
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
});
}
budgetText.x = 2048 / 2;
budgetText.y = budgetY;
budgetText.anchor.set(0.5, 0);
game.addChild(budgetText);
// Info
if (!infoText) {
infoText = new Text2("", {
size: 54,
fill: 0xFDCB6E,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
});
}
infoText.x = 2048 / 2;
infoText.y = infoY;
infoText.anchor.set(0.5, 0);
game.addChild(infoText);
// 2. Squad Section (centered, consistent spacing)
var squadSectionY = infoY + 80;
guiY = squadSectionY - 220; // for legacy code compatibility
updateSquadLabels();
// 3. Bench Section (centered, below squad)
updateBenchLabels();
// 4. Transfer Market Section (centered, below bench)
updateTransferLabels();
// 5. League Table & Opponent Section (left side, vertically aligned)
updateOpponentLabels();
// 6. Youth Academy & Transfer Offers (right side, vertically aligned)
// Place youth academy and offers in a right column, visually balanced
clearArray(youthLabels);
clearArray(promoteBtns);
clearArray(sellYouthBtns);
var rightColX = 2048 - 1100 - 80; // right margin
var rightColY = squadSectionY;
var youthHeader = makeLabel("Youth Academy", rightColX + 550, rightColY, 54, "#81ecec");
youthHeader.anchor.set(0.5, 0);
game.addChild(youthHeader);
youthLabels.push(youthHeader);
for (var i = 0; i < youthAcademy.length; i++) {
var yp = youthAcademy[i];
var rowY = rightColY + 70 + i * 60;
var t = makeLabel(yp.name + " [A:" + yp.attack + " D:" + yp.defense + " S:" + yp.stamina + "] $" + yp.value + "M", rightColX + 40, rowY, 40, "#fff");
t.anchor.set(0, 0);
game.addChild(t);
youthLabels.push(t);
// Promote button
var promoteBtn = makeLabel("Promote", rightColX + 700, rowY, 36, "#00b894");
promoteBtn.idx = i;
promoteBtn.interactive = true;
promoteBtn.down = function (idxCopy) {
return function (x, y, obj) {
var idx = idxCopy;
var p = youthAcademy[idx];
if (!p) {
showInfo("No youth player to promote.");
return;
}
if (allPlayers.length >= SQUAD_SIZE + BENCH_SIZE) {
showInfo("Squad full! Sell a player first.");
return;
}
allPlayers.push(new Player(p.name, p.attack, p.defense, p.stamina, p.value, null));
updateSquadAndBench();
showInfo("Promoted " + p.name + " to your team!");
youthAcademy.splice(idx, 1);
refreshUI();
};
}(i);
game.addChild(promoteBtn);
promoteBtns.push(promoteBtn);
// Sell button
var sellBtn = makeLabel("Sell", rightColX + 850, rowY, 36, "#fdcb6e");
sellBtn.idx = i;
sellBtn.interactive = true;
sellBtn.down = function (idxCopy) {
return function (x, y, obj) {
var idx = idxCopy;
var p = youthAcademy[idx];
if (!p) {
showInfo("No youth player to sell.");
return;
}
budget += p.value;
updateBudgetText();
showInfo("Sold " + p.name + " for $" + p.value + "M");
youthAcademy.splice(idx, 1);
refreshUI();
};
}(i);
game.addChild(sellBtn);
sellYouthBtns.push(sellBtn);
}
// Transfer Offers (below youth academy)
clearArray(offerLabels);
clearArray(acceptOfferBtns);
clearArray(rejectOfferBtns);
var offerY = rightColY + 70 + Math.max(1, youthAcademy.length) * 60 + 40;
if (transferOffers.length > 0) {
var offerHeader = makeLabel("Transfer Offers", rightColX + 550, offerY, 54, "#fdcb6e");
offerHeader.anchor.set(0.5, 0);
game.addChild(offerHeader);
offerLabels.push(offerHeader);
for (var i = 0; i < transferOffers.length; i++) {
var offer = transferOffers[i];
var p = offer.player;
var rowY = offerY + 70 + i * 60;
var txt = offer.club + " offers $" + offer.offerValue + "M for " + p.name;
var t = makeLabel(txt, rightColX + 40, rowY, 40, "#fff");
t.anchor.set(0, 0);
game.addChild(t);
offerLabels.push(t);
// Accept button
var acceptBtn = makeLabel("Accept", rightColX + 700, rowY, 36, "#00b894");
acceptBtn.idx = i;
acceptBtn.interactive = true;
acceptBtn.down = function (idxCopy) {
return function (x, y, obj) {
var idx = idxCopy;
var offer = transferOffers[idx];
var p = offer.player;
var allIdx = allPlayers.indexOf(p);
if (allIdx !== -1) {
budget += offer.offerValue;
allPlayers.splice(allIdx, 1);
updateSquadAndBench();
updateBudgetText();
showInfo("Sold " + p.name + " to " + offer.club + " for $" + offer.offerValue + "M");
transferOffers.splice(idx, 1);
refreshUI();
} else {
showInfo("Player not found.");
}
};
}(i);
game.addChild(acceptBtn);
acceptOfferBtns.push(acceptBtn);
// Reject button
var rejectBtn = makeLabel("Reject", rightColX + 850, rowY, 36, "#ff7675");
rejectBtn.idx = i;
rejectBtn.interactive = true;
rejectBtn.down = function (idxCopy) {
return function (x, y, obj) {
var idx = idxCopy;
var offer = transferOffers[idx];
showInfo("Rejected offer for " + offer.player.name + ".");
transferOffers.splice(idx, 1);
refreshUI();
};
}(i);
game.addChild(rejectBtn);
rejectOfferBtns.push(rejectBtn);
}
}
// 7. Play Match and Next Match buttons (bottom center, always visible)
var playBtnX = 2048 / 2 - 200;
var playBtnY = 2732 - 320;
playBtn = makeLabel("Play Match", playBtnX, playBtnY, 70, "#00cec9");
playBtn.interactive = true;
playBtn.down = function (x, y, obj) {
if (matchInProgress) {
return;
}
simulateMatch();
playBtn.destroy();
playBtn = null;
// Next match button (bottom middle, below Play Match)
var nextBtnX = 2048 / 2 - 200;
var nextBtnY = playBtnY + 120;
nextBtn = makeLabel("Next Match", nextBtnX, nextBtnY, 60, "#fdcb6e");
nextBtn.interactive = true;
nextBtn.down = function (x, y, obj) {
for (var i = 0; i < allPlayers.length; i++) {
allPlayers[i].stamina = Math.min(allPlayers[i].maxStamina, allPlayers[i].stamina + randomInt(1, 3));
}
if (isSeasonOver()) {
// ... (season end logic unchanged)
// For brevity, call newGame() to reset for new season
newGame();
} else {
var oppIdx = getCurrentOpponentIdx();
if (oppIdx !== null) {
opponentTeam = makeOpponentTeam();
opponentTeam.name = leagueTeams[oppIdx].name;
}
clearMatchText();
nextBtn.destroy();
nextBtn = null;
refreshUI();
}
};
game.addChild(nextBtn);
};
game.addChild(playBtn);
// 8. Nav Buttons (bottom, evenly spaced)
showNavButtons();
// 9. Update budget and info
updateBudgetText();
showInfo("Pick lineup, buy/sell, then Play Match!");
}
// --- INIT UI ---
var currentScreen = "main"; // "main", "transfer", "league", "youth"
var navBtns = [];
function showScreen(screen) {
currentScreen = screen;
clearAllUI();
// Always show nav buttons
showNavButtons();
if (screen === "main") {
updateSquadLabels();
updateBenchLabels();
updateOpponentLabels();
updateBudgetText();
showInfo("Pick lineup, buy/sell, then Play Match!");
// Play Match button
var playBtnX = 2048 / 2 - 200;
var playBtnY = 2048 - 200;
playBtn = makeLabel("Play Match", playBtnX, playBtnY, 70, "#00cec9");
playBtn.interactive = true;
playBtn.down = function (x, y, obj) {
if (matchInProgress) return;
simulateMatch();
playBtn.destroy();
playBtn = null;
// Next match button
var nextBtnX = 2048 / 2 - 200;
var nextBtnY = playBtnY + 120;
nextBtn = makeLabel("Next Match", nextBtnX, nextBtnY, 60, "#fdcb6e");
nextBtn.interactive = true;
nextBtn.down = function (x, y, obj) {
// Restore stamina a bit
for (var i = 0; i < allPlayers.length; i++) {
allPlayers[i].stamina = Math.min(allPlayers[i].maxStamina, allPlayers[i].stamina + randomInt(1, 3));
}
// Check if season is over
if (isSeasonOver()) {
// Calculate final league position for user
var sortedLeague = leagueTeams.slice().sort(function (a, b) {
if (b.points !== a.points) return b.points - a.points;
var gdA = a.goalsFor - a.goalsAgainst;
var gdB = b.goalsFor - b.goalsAgainst;
if (gdB !== gdA) return gdB - gdA;
return b.goalsFor - a.goalsFor;
});
var userFinalPos = 1;
for (var i = 0; i < sortedLeague.length; i++) {
if (sortedLeague[i].name === "You") {
userFinalPos = i + 1;
break;
}
}
// Prize money by position
var prize = 5;
if (userFinalPos === 1) prize = 50;else if (userFinalPos === 2) prize = 30;else if (userFinalPos === 3) prize = 20;else if (userFinalPos === 4) prize = 10;
// Award prize
budget += prize;
// Champions League logic
if (userFinalPos === 1) {
// User qualifies for Champions League
// Simulate a simple 8-team knockout tournament
var clTeams = [{
name: "You",
players: squad.slice()
}, {
name: "Real Madrid",
players: [makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer()]
}, {
name: "Manchester City",
players: [makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer()]
}, {
name: "Bayern Munich",
players: [makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer()]
}, {
name: "Barcelona",
players: [makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer()]
}, {
name: "PSG",
players: [makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer()]
}, {
name: "Juventus",
players: [makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer()]
}, {
name: "Liverpool",
players: [makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer(), makeRandomPlayer()]
}];
// Shuffle teams for random draw
for (var i = clTeams.length - 1; i > 0; i--) {
var j = randomInt(0, i);
var temp = clTeams[i];
clTeams[i] = clTeams[j];
clTeams[j] = temp;
}
// Find user index
var userCLIdx = -1;
for (var i = 0; i < clTeams.length; i++) {
if (clTeams[i].name === "You") {
userCLIdx = i;
break;
}
}
var clLog = [];
var roundNames = ["Quarterfinals", "Semifinals", "Final"];
var roundPrize = [20, 30, 50]; // QF, SF, Winner
var userAlive = true;
var userRound = 0;
var userCLPlace = "Winner";
var clPrize = 0;
var clOppName = "";
var clOppScore = 0,
userScore = 0;
var clTeamsLeft = clTeams.slice();
for (var round = 0; round < 3 && userAlive; round++) {
clLog.push("Champions League " + roundNames[round] + ":");
var nextRoundTeams = [];
for (var m = 0; m < clTeamsLeft.length; m += 2) {
var t1 = clTeamsLeft[m];
var t2 = clTeamsLeft[m + 1];
// Simulate match
var t1Strength = 0,
t2Strength = 0;
for (var k = 0; k < 5; k++) {
t1Strength += t1.players[k].attack + t1.players[k].defense + t1.players[k].stamina;
t2Strength += t2.players[k].attack + t2.players[k].defense + t2.players[k].stamina;
}
var t1Goals = Math.max(0, Math.floor(t1Strength / 45) + randomInt(0, 1));
var t2Goals = Math.max(0, Math.floor(t2Strength / 45) + randomInt(0, 1));
// If draw, random winner
if (t1Goals === t2Goals) {
if (Math.random() < 0.5) t1Goals++;else t2Goals++;
}
clLog.push(t1.name + " " + t1Goals + " - " + t2Goals + " " + t2.name);
if (t1.name === "You" || t2.name === "You") {
userScore = t1.name === "You" ? t1Goals : t2Goals;
clOppScore = t1.name === "You" ? t2Goals : t1Goals;
clOppName = t1.name === "You" ? t2.name : t1.name;
if (userScore > clOppScore) {
clLog.push("You advance to the next round!");
clPrize += roundPrize[round];
userRound = round + 1;
nextRoundTeams.push(t1.name === "You" ? t1 : t2);
} else {
clLog.push("You are eliminated by " + clOppName + "!");
userAlive = false;
userCLPlace = round === 0 ? "Quarterfinalist" : round === 1 ? "Semifinalist" : "Finalist";
}
} else {
// Winner advances
nextRoundTeams.push(t1Goals > t2Goals ? t1 : t2);
}
}
clTeamsLeft = nextRoundTeams;
}
if (userAlive) {
clLog.push("Congratulations! You are the Champions League Winner!");
clPrize += 50;
userCLPlace = "Winner";
}
if (clPrize > 0) {
budget += clPrize;
clLog.push("Champions League prize: $" + clPrize + "M");
}
showInfo("Season finished! You placed #1 and qualified for the Champions League!\n" + "Champions League result: " + userCLPlace + ". Prize: $" + (prize + clPrize) + "M. Table resets for new season.");
updateBudgetText();
matchLog = matchLog.concat(clLog);
showMatchLog();
} else {
showInfo("Season finished! You placed #" + userFinalPos + ". Prize: $" + prize + "M. Table resets for new season.");
updateBudgetText();
}
// Decrement seasonsRemaining for transfer market players, remove those at 0
for (var i = allPlayers.length - 1; i >= 0; i--) {
var p = allPlayers[i];
if (typeof p.seasonsRemaining === "number" && p.seasonsRemaining !== null) {
p.seasonsRemaining--;
if (p.seasonsRemaining <= 0) {
allPlayers.splice(i, 1);
showInfo("Player " + p.name + " has retired/left after 3 seasons.");
}
}
}
updateSquadAndBench();
// --- Generate up to 3 transfer offers for squad/bench players at end of season ---
transferOffers = [];
var candidates = squad.concat(bench).slice();
for (var i = candidates.length - 1; i > 0; i--) {
var j = randomInt(0, i);
var temp = candidates[i];
candidates[i] = candidates[j];
candidates[j] = temp;
}
var offersToMake = Math.min(3, candidates.length);
for (var i = 0; i < offersToMake; i++) {
var p = candidates[i];
var offerVal = Math.floor(p.value * (randomInt(90, 120) / 100));
var club = OFFER_CLUBS[randomInt(0, OFFER_CLUBS.length - 1)];
transferOffers.push({
player: p,
offerValue: offerVal,
club: club
});
}
if (transferOffers.length > 0) {
showInfo("You have received " + transferOffers.length + " transfer offer(s) for your players!");
}
initLeague();
initTransferList();
var oppIdx = getCurrentOpponentIdx();
if (oppIdx !== null) {
opponentTeam = makeOpponentTeam();
opponentTeam.name = leagueTeams[oppIdx].name;
}
clearMatchText();
nextBtn.destroy();
nextBtn = null;
showScreen("main");
return;
}
// Next opponent in league
var oppIdx = getCurrentOpponentIdx();
if (oppIdx !== null) {
opponentTeam = makeOpponentTeam();
opponentTeam.name = leagueTeams[oppIdx].name;
}
clearMatchText();
nextBtn.destroy();
nextBtn = null;
showScreen("main");
};
game.addChild(nextBtn);
};
game.addChild(playBtn);
} else if (screen === "transfer") {
// --- Centered Transfer Market Layout ---
clearArray(transferBtns);
clearArray(buyBtns);
var sectionWidth = 1100;
var sectionX = (2048 - sectionWidth) / 2;
var rowHeight = 64;
var sectionHeight = (transferList.length + 1) * rowHeight + 120;
var startY = 400; // Start well below the top for visual balance
// Remove old transferText if present
if (transferText) {
transferText.destroy();
}
transferText = makeLabel("Transfer Market", 2048 / 2, startY - 90, 56, "#00b894");
transferText.anchor.set(0.5, 0); // Center header horizontally
game.addChild(transferText);
// Calculate X positions for player info and buy button
var playerInfoX = sectionX + 40;
var buyBtnX = sectionX + sectionWidth - 180;
for (var i = 0; i < transferList.length; i++) {
var p = transferList[i];
// Centered row Y
var rowY = startY + i * rowHeight;
// Player info label, left-aligned in section
var t = makeLabel(p.name + " [A:" + p.attack + " D:" + p.defense + " S:" + p.stamina + "] $" + p.value + "M", playerInfoX, rowY, 44, "#fff");
t.anchor.set(0, 0); // Left align in section
game.addChild(t);
transferBtns.push(t);
// Buy button, right-aligned in section
var buyBtn = makeLabel("Buy", buyBtnX, rowY, 40, "#00b894");
buyBtn.idx = i;
buyBtn.interactive = true;
buyBtn.down = function (idxCopy) {
return function (x, y, obj) {
var idx = idxCopy;
var p = transferList[idx];
if (!p) {
showInfo("Player not available.");
return;
}
if (budget < p.value) {
showInfo("Not enough budget!");
return;
}
// Allow buying a player as long as the total number of players is less than the maximum allowed
if (allPlayers.length >= SQUAD_SIZE + BENCH_SIZE) {
showInfo("Squad full! Sell a player first.");
return;
}
budget -= p.value;
// When buying, always set seasonsRemaining=3
allPlayers.push(new Player(p.name, p.attack, p.defense, p.stamina, p.value, 3));
updateSquadAndBench();
updateBudgetText();
showInfo("Bought " + p.name + " for $" + p.value + "M");
// Remove from transfer list, add new
transferList.splice(idx, 1, makeRandomPlayer());
showScreen("transfer");
};
}(i);
game.addChild(buyBtn);
buyBtns.push(buyBtn);
}
updateBudgetText();
showInfo("Buy top players for your team!");
} else if (screen === "league") {
updateOpponentLabels();
showInfo("Check the league table and your next opponent.");
} else if (screen === "youth") {
// Only show youth academy and transfer offers
clearArray(youthLabels);
clearArray(promoteBtns);
clearArray(sellYouthBtns);
// --- Centered Youth Academy Layout ---
var sectionWidth = 1100;
var youthX = (2048 - sectionWidth) / 2;
var rowHeight = 64;
var youthY = 400;
// Centered header
var youthHeader = makeLabel("Youth Academy", 2048 / 2, youthY, 54, "#81ecec");
youthHeader.anchor.set(0.5, 0);
game.addChild(youthHeader);
youthLabels.push(youthHeader);
// Calculate X positions for player info and buttons
var playerInfoX = youthX + 40;
var promoteBtnX = youthX + sectionWidth - 320;
var sellBtnX = youthX + sectionWidth - 160;
for (var i = 0; i < youthAcademy.length; i++) {
var yp = youthAcademy[i];
var rowY = youthY + 70 + i * rowHeight;
var t = makeLabel(yp.name + " [A:" + yp.attack + " D:" + yp.defense + " S:" + yp.stamina + "] $" + yp.value + "M", playerInfoX, rowY, 40, "#fff");
t.anchor.set(0, 0);
game.addChild(t);
youthLabels.push(t);
// Promote button
var promoteBtn = makeLabel("Promote", promoteBtnX, rowY, 36, "#00b894");
promoteBtn.idx = i;
promoteBtn.interactive = true;
promoteBtn.down = function (idxCopy) {
return function (x, y, obj) {
var idx = idxCopy;
var p = youthAcademy[idx];
if (!p) {
showInfo("No youth player to promote.");
return;
}
// Allow promoting a player as long as the total number of players is less than the maximum allowed
if (allPlayers.length >= SQUAD_SIZE + BENCH_SIZE) {
showInfo("Squad full! Sell a player first.");
return;
}
allPlayers.push(new Player(p.name, p.attack, p.defense, p.stamina, p.value, null));
updateSquadAndBench();
showInfo("Promoted " + p.name + " to your team!");
youthAcademy.splice(idx, 1);
showScreen("youth");
};
}(i);
game.addChild(promoteBtn);
promoteBtns.push(promoteBtn);
// Sell button
var sellBtn = makeLabel("Sell", sellBtnX, rowY, 36, "#fdcb6e");
sellBtn.idx = i;
sellBtn.interactive = true;
sellBtn.down = function (idxCopy) {
return function (x, y, obj) {
var idx = idxCopy;
var p = youthAcademy[idx];
if (!p) {
showInfo("No youth player to sell.");
return;
}
budget += p.value;
updateBudgetText();
showInfo("Sold " + p.name + " for $" + p.value + "M");
youthAcademy.splice(idx, 1);
showScreen("youth");
};
}(i);
game.addChild(sellBtn);
sellYouthBtns.push(sellBtn);
}
// Transfer offers
clearArray(offerLabels);
clearArray(acceptOfferBtns);
clearArray(rejectOfferBtns);
var offerX = youthX + 40;
var offerY = youthY + 70 + Math.max(1, youthAcademy.length) * rowHeight + 40;
if (transferOffers.length > 0) {
var offerHeader = makeLabel("Transfer Offers", 2048 / 2, offerY, 54, "#fdcb6e");
offerHeader.anchor.set(0.5, 0);
game.addChild(offerHeader);
offerLabels.push(offerHeader);
for (var i = 0; i < transferOffers.length; i++) {
var offer = transferOffers[i];
var p = offer.player;
var rowY = offerY + 70 + i * rowHeight;
var txt = offer.club + " offers $" + offer.offerValue + "M for " + p.name;
var t = makeLabel(txt, offerX, rowY, 40, "#fff");
t.anchor.set(0, 0);
game.addChild(t);
offerLabels.push(t);
// Accept button
var acceptBtn = makeLabel("Accept", promoteBtnX, rowY, 36, "#00b894");
acceptBtn.idx = i;
acceptBtn.interactive = true;
acceptBtn.down = function (idxCopy) {
return function (x, y, obj) {
var idx = idxCopy;
var offer = transferOffers[idx];
var p = offer.player;
var allIdx = allPlayers.indexOf(p);
if (allIdx !== -1) {
budget += offer.offerValue;
allPlayers.splice(allIdx, 1);
updateSquadAndBench();
updateBudgetText();
showInfo("Sold " + p.name + " to " + offer.club + " for $" + offer.offerValue + "M");
transferOffers.splice(idx, 1);
showScreen("youth");
} else {
showInfo("Player not found.");
}
};
}(i);
game.addChild(acceptBtn);
acceptOfferBtns.push(acceptBtn);
// Reject button
var rejectBtn = makeLabel("Reject", sellBtnX, rowY, 36, "#ff7675");
rejectBtn.idx = i;
rejectBtn.interactive = true;
rejectBtn.down = function (idxCopy) {
return function (x, y, obj) {
var idx = idxCopy;
var offer = transferOffers[idx];
showInfo("Rejected offer for " + offer.player.name + ".");
transferOffers.splice(idx, 1);
showScreen("youth");
};
}(i);
game.addChild(rejectBtn);
rejectOfferBtns.push(rejectBtn);
}
}
updateBudgetText();
showInfo("Manage your youth academy and transfer offers.");
}
}
function showNavButtons() {
clearArray(navBtns);
// Button positions - bottom of screen, evenly spaced, consistent style
var btnY = 2732 - 100; // 100px from bottom edge for safe area
var btnCount = 4;
var btnWidth = 320;
var btnSpacing = 60;
var totalWidth = btnCount * btnWidth + (btnCount - 1) * btnSpacing;
var btnXStart = Math.max(60, (2048 - totalWidth) / 2);
var btns = [{
label: "Main",
screen: "main",
color: 0x00CEC9
}, {
label: "Transfer Market",
screen: "transfer",
color: 0x00B894
}, {
label: "League Table",
screen: "league",
color: 0xFDCB6E
}, {
label: "Youth Academy",
screen: "youth",
color: 0x81ECEC
}];
for (var i = 0; i < btns.length; i++) {
var b = btns[i];
var btnX = btnXStart + i * (btnWidth + btnSpacing);
var navBtn = new Text2(b.label, {
size: 48,
fill: b.color,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
});
navBtn.x = btnX + btnWidth / 2;
navBtn.y = btnY;
navBtn.anchor.set(0.5, 0.5);
navBtn.interactive = true;
navBtn.screen = b.screen;
navBtn.down = function (screenName) {
return function (x, y, obj) {
showScreen(screenName);
};
}(b.screen);
game.addChild(navBtn);
navBtns.push(navBtn);
}
}
function initUI() {
guiY = 0;
// Title (centered, consistent font)
var title = new Text2("Mini Football Manager", {
size: 90,
fill: 0x00CEC9,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
});
title.x = 2048 / 2;
title.y = guiY + 40;
title.anchor.set(0.5, 0);
game.addChild(title);
// Budget (centered below title)
budgetText = new Text2("Budget: $" + budget + "M", {
size: 60,
fill: "#fff",
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
});
budgetText.x = 2048 / 2;
budgetText.y = guiY + 140;
budgetText.anchor.set(0.5, 0);
game.addChild(budgetText);
// Info (centered below budget)
infoText = new Text2("", {
size: 54,
fill: 0xFDCB6E,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
});
infoText.x = 2048 / 2;
infoText.y = guiY + 210;
infoText.anchor.set(0.5, 0);
game.addChild(infoText);
showScreen("main");
}
// --- GAME START ---
function newGame() {
budget = INITIAL_BUDGET;
initLeague();
initPlayers();
initTransferList();
// --- YOUTH ACADEMY RESET ---
youthAcademy = [];
if (youthTimer) {
LK.clearInterval(youthTimer);
youthTimer = null;
}
// --- TRANSFER OFFERS RESET ---
transferOffers = [];
if (OFFER_TIMER) {
LK.clearInterval(OFFER_TIMER);
OFFER_TIMER = null;
}
clearArray(offerLabels);
clearArray(acceptOfferBtns);
clearArray(rejectOfferBtns);
// Set first opponent in league
var oppIdx = getCurrentOpponentIdx();
if (oppIdx !== null) {
opponentTeam = makeOpponentTeam();
opponentTeam.name = leagueTeams[oppIdx].name;
} else {
opponentTeam = makeOpponentTeam();
}
matchInProgress = false;
matchLog = [];
matchResult = null;
selectedPlayerIdx = null;
selectedBenchIdx = null;
initUI();
}
newGame();
// --- END ---