diff --git a/index.html b/index.html index b93bfe2..8465522 100644 --- a/index.html +++ b/index.html @@ -1731,6 +1731,7 @@ document.getElementById('dev-win-slider')?.addEventListener('input', function() } Gamestate.updateButtonText = function() { + let end = document.getElementById('end'); if (!end) return; if (this.stage === "Fortify") { end.textContent = "Deploy Troops"; end.style.opacity = "0.5"; end.style.pointerEvents = "none"; @@ -1738,14 +1739,12 @@ Gamestate.updateButtonText = function() { else if (this.stage === "Battle") { end.textContent = "End Attack Phase"; end.style.opacity = "1"; end.style.pointerEvents = "auto"; } -else if (this.stage === "Maneuver") { - if(this.commandersEnabled && this.player.alive && this.player.commander) { - end.textContent = this.hasManeuvered ? "End Moves" : "Skip Move"; - } else { - end.textContent = "End Turn"; - } + else if (this.stage === "Maneuver") { + // If Commanders are on, it says Next Phase. Otherwise, End Turn. + let nextStr = (this.commandersEnabled && this.player.alive && this.player.commander) ? "Next Phase" : "End Turn"; + end.textContent = this.hasManeuvered ? nextStr : "Skip Move"; end.style.opacity = "1"; end.style.pointerEvents = "auto"; - } + } else if (this.stage === "Commander Phase") { end.textContent = "End Turn"; end.style.opacity = "1"; end.style.pointerEvents = "auto"; } @@ -2269,32 +2268,57 @@ Gamestate.updateInfo = function(){ if (this.player.areas.length <= 5) { hpFill.style.background = "#ff0000"; hpFill.style.boxShadow = "0 0 10px rgba(255, 0, 0, 0.8)"; } else { hpFill.style.background = "var(--pip-color)"; hpFill.style.boxShadow = "var(--pip-glow)"; } - let apPercentage = 0; +let apPercentage = 0; + let shouldAutoSkip = false; // The Turbo Sensor + if (this.stage === "Fortify") { - let maxReserve = Math.max(this.player.reserve + this.playerTroopsPlaced, 1); apPercentage = (this.player.reserve / maxReserve) * 100; + let maxReserve = Math.max(this.player.reserve + this.playerTroopsPlaced, 1); + apPercentage = (this.player.reserve / maxReserve) * 100; } else if (this.stage === "Battle") { - let currentStrikeForce = 0; let validAttacks = 0; let ownedTerritories = this.countries.filter(c => c.owner === this.player.name); + let currentStrikeForce = 0; + let validAttacks = 0; let ownedTerritories = this.countries.filter(c => c.owner === this.player.name); ownedTerritories.forEach(t => { if (t.army > 1) { let hasEnemyNeighbor = t.neighbours.some(n => { let nc = this.countries.find(x => x.name === n); return nc && nc.owner !== this.player.name && !nc.isCrater; }); if (hasEnemyNeighbor) { currentStrikeForce += (t.army - 1); validAttacks++; } } }); - if (validAttacks === 0) apPercentage = 0; + if (validAttacks === 0) { + apPercentage = 0; + shouldAutoSkip = true; // No valid attacks left! + } else { if (this.lastStage !== "Battle") this.initialStrikeForce = currentStrikeForce; if (currentStrikeForce > (this.initialStrikeForce || 1)) this.initialStrikeForce = currentStrikeForce; apPercentage = Math.min(100, (currentStrikeForce / Math.max(this.initialStrikeForce, 1)) * 100); } } else if (this.stage === "Maneuver") { - let canManeuver = false; let ownedTerritories = this.countries.filter(c => c.owner === this.player.name); + let canManeuver = false; + let ownedTerritories = this.countries.filter(c => c.owner === this.player.name); for (let t of ownedTerritories) { if (t.army > 1 && t.neighbours.some(n => { let nc = this.countries.find(x => x.name === n); return nc && nc.owner === this.player.name; })) { canManeuver = true; break; } } apPercentage = canManeuver ? (this.maneuverSource ? 0 : 100) : 0; } else if (this.stage === "Commander Phase" && this.commandersEnabled && this.player.commander) { apPercentage = (this.player.commander.ap / 2) * 100; + if (this.player.commander.ap <= 0) shouldAutoSkip = true; // Out of AP! } else apPercentage = 0; apFill.style.width = apPercentage + "%"; + + // --- TURBO MODE AUTO-SKIP ENGINE --- + let turbo = document.getElementById('turbo-toggle') && document.getElementById('turbo-toggle').checked; + if (turbo && shouldAutoSkip && !this.aiTurn) { + if (!this.autoSkipTimer) { + this.autoSkipTimer = setTimeout(() => { + this.autoSkipTimer = null; + if (!this.aiTurn && (this.stage === "Battle" || this.stage === "Commander Phase")) { + if (Gamestate.logAction) Gamestate.logAction("[ TURBO ] AP Depleted. Auto-advancing phase...", true); + this.handleEndTurn(); + } + }, 1200); // 1.2 second delay so you can read the final combat logs + } + } else { + if (this.autoSkipTimer) { clearTimeout(this.autoSkipTimer); this.autoSkipTimer = null; } + } if (apPercentage <= 0) { apFill.style.opacity = "0"; apFill.style.visibility = "hidden"; } else { apFill.style.opacity = "1"; apFill.style.visibility = "visible"; } if (hpPercentage <= 0) { hpFill.style.opacity = "0"; hpFill.style.visibility = "hidden"; } else { hpFill.style.opacity = "1"; hpFill.style.visibility = "visible"; } } else if (!this.player.alive && hpFill && apFill) { @@ -2863,13 +2887,15 @@ country.army += moveAmount; let sourceMap = document.getElementById(`${this.prevCountry.name}`); let destMap = document.getElementById(`${country.name}`); if (sourceMap && sourceMap.nextElementSibling) sourceMap.nextElementSibling.textContent = this.prevCountry.army; - if (destMap && destMap.nextElementSibling) destMap.nextElementSibling.textContent = country.army; +if (destMap && destMap.nextElementSibling) destMap.nextElementSibling.textContent = country.army; if(this.commandersEnabled && this.player.commander && this.player.commander.loc === this.prevCountry.name && e.shiftKey) { this.player.commander.loc = country.name; - this.player.commander.siegeTurns = 0; // Reset subversion timer - this.logAction(`Commander escorted to ${formatTerritoryName(country.name)}.`); + if (Gamestate.logAction) this.logAction(`Commander escorted to ${formatTerritoryName(country.name)}.`); } + + this.hasManeuvered = true; + this.updateButtonText(); // <--- This forces the button to change! this.updateInfo(); } } @@ -3255,11 +3281,13 @@ if (infoName[i-1]) infoName[i-1].parentElement.classList.remove('highlight'); if(this.commandersEnabled && this.players[i].commander) { let loc = this.countries.find(c => c.name === this.players[i].commander.loc); - if(loc && loc.owner === this.players[i].name) { let regen = loc.isSilo ? 4 : 2; this.players[i].commander.hp = Math.min(100, this.players[i].commander.hp + regen); } + if(loc && loc.owner === this.players[i].name) { let regen = loc.isSilo ? 4 : 2; this.players[i].commander.hp = Math.min(100, this.players[i].commander.hp + regen); + } -// FIX: Refill the AI Commander's Action Points every turn! + // FIX: Refill the AI Commander's Action Points & Combat Fatigue every turn! this.players[i].commander.ap = 2; - this.players[i].commander.hasBeenAmbushed = false; // Reset attack limit + this.players[i].commander.hasBeenAmbushed = false; + this.players[i].commander.hasFought = false; // Wakes the AI up! } this.updateInfo(); @@ -3337,22 +3365,32 @@ Gamestate.aiManeuver = function(i){ }); enemyCmdrs.sort((a,b) => a.commander.hp - b.commander.hp); - // PRIORITY 4: RETREAT (HP < 35%) - if (player.commander.hp < 35 && friendlyNeighbors.length > 0) { - let safeSpots = friendlyNeighbors.filter(c => !c.neighbours.some(n => { - let nc = this.countries.find(x=>x.name===n); return nc && nc.owner !== player.name; - })); - if (safeSpots.length === 0) safeSpots = friendlyNeighbors; - let silo = safeSpots.find(c => this.nukesEnabled && c.isSilo); - safeSpots.sort((a,b) => b.army - a.army); - let retreatTarget = silo ? silo : safeSpots[0]; - - if (retreatTarget.name !== cmdrLoc.name && (retreatTarget.army > cmdrLoc.army || silo)) { - player.commander.loc = retreatTarget.name; +// PRIORITY 4: RETREAT (HP < 35%) + if (player.commander.hp < 35) { + if (friendlyNeighbors.length > 0) { + let safeSpots = friendlyNeighbors.filter(c => !c.neighbours.some(n => { + let nc = this.countries.find(x=>x.name===n); return nc && nc.owner !== player.name; + })); + if (safeSpots.length === 0) safeSpots = friendlyNeighbors; + let silo = safeSpots.find(c => this.nukesEnabled && c.isSilo); + safeSpots.sort((a,b) => b.army - a.army); + let retreatTarget = silo ? silo : safeSpots[0]; + + if (retreatTarget.name !== cmdrLoc.name && (retreatTarget.army > cmdrLoc.army || silo)) { + player.commander.loc = retreatTarget.name; + player.commander.ap -= 1; movedOrAction = true; + player.commander.siegeTurns = 0; + if (Gamestate.logAction) Gamestate.logAction(`VIP MOVEMENT: ${player.name}'s Commander retreats to ${formatTerritoryName(retreatTarget.name)}.`); + continue; + } + } else if (neighbors.length > 0) { + // DESPERATE ESCAPE: Completely surrounded! Run anywhere to survive! + let escapeRoute = neighbors[Math.floor(Math.random() * neighbors.length)]; + player.commander.loc = escapeRoute.name; player.commander.ap -= 1; movedOrAction = true; player.commander.siegeTurns = 0; - if (Gamestate.logAction) Gamestate.logAction(`VIP MOVEMENT: ${player.name}'s Commander retreats to ${formatTerritoryName(retreatTarget.name)}.`); - continue; + if (Gamestate.logAction) Gamestate.logAction(`VIP MOVEMENT: ${player.name}'s stranded Commander desperately flees to ${formatTerritoryName(escapeRoute.name)}!`); + continue; } }