diff --git a/index20.html b/index20.html
index d274602..a073895 100644
--- a/index20.html
+++ b/index20.html
@@ -1883,6 +1883,119 @@ Gamestate.showCodePopup = function() {
}
}
+// --- INVENTORY & BOBBLEHEAD SYSTEM ---
+Gamestate.bobbleheads = [
+ { key: 's', name: 'STRENGTH BOBBLEHEAD', found: false, cooldown: 0, totalCooldown: 5, bonus: 0.10, desc: 'Grants +10% attack odds for 1 turn.' },
+ { key: 'p', name: 'PERCEPTION BOBBLEHEAD', found: false, cooldown: 0, totalCooldown: 8, desc: 'Reveals all enemy territories for 1 turn.' },
+ { key: 'e', name: 'ENDURANCE BOBBLEHEAD', found: false, cooldown: 0, totalCooldown: 5, bonus: 0.10, desc: 'Reduces defender losses by 10% for 1 turn.' },
+ { key: 'c', name: 'CHARISMA BOBBLEHEAD', found: false, cooldown: 0, totalCooldown: 10, desc: 'Your next Bottle Cap trade-in yields maximum troops.' },
+ { key: 'i', name: 'INTELLIGENCE BOBBLEHEAD', found: false, cooldown: 0, totalCooldown: 8, desc: 'Reveals all rival leaderboard data for 1 turn.' },
+ { key: 'a', name: 'AGILITY BOBBLEHEAD', found: false, cooldown: 0, totalCooldown: 6, bonus: 1, desc: 'Grants one extra army maneuver this turn.' },
+ { key: 'l', name: 'LUCK BOBBLEHEAD', found: false, cooldown: 0, totalCooldown: 7, bonus: 3, desc: 'Triples the chance to find loot for 1 turn.' }
+];
+
+Gamestate.setupInventory = function() {
+ const invModal = document.getElementById('inventory-modal');
+ const navInv = document.getElementById('nav-inv');
+ const navMap = document.getElementById('nav-map');
+ const closeInvBtn = document.getElementById('close-inv-btn');
+
+ if (!invModal || !navInv) return;
+
+ navInv.addEventListener('click', () => {
+ invModal.style.display = 'flex';
+ navInv.classList.remove('inv-pulse');
+ navInv.classList.add('map-active');
+ if (navMap) navMap.classList.remove('map-active');
+ if (this.renderInventory) this.renderInventory();
+ });
+
+ if (closeInvBtn) {
+ closeInvBtn.addEventListener('click', () => {
+ invModal.style.display = 'none';
+ navInv.classList.remove('map-active');
+ if (navMap) navMap.classList.add('map-active');
+ });
+ }
+
+ this.bobbleheads.forEach(item => {
+ const btn = document.querySelector(`#bobblehead-${item.key} .bobble-activate-btn`);
+ if (btn) {
+ btn.addEventListener('click', () => {
+ if(this.activateBobblehead) this.activateBobblehead(item.key);
+ });
+ }
+ });
+};
+
+Gamestate.renderInventory = function() {
+ const stimpakCountEl = document.getElementById('inv-stimpak-count');
+ if (stimpakCountEl && this.player && this.player.commander) {
+ stimpakCountEl.textContent = this.player.commander.stimpaks;
+ }
+
+ let foundCount = 0;
+ this.bobbleheads.forEach(item => {
+ const itemDiv = document.getElementById(`bobblehead-${item.key}`);
+ if (!itemDiv) return;
+ const btn = itemDiv.querySelector('.bobble-activate-btn');
+ const cooldownEl = itemDiv.querySelector('.cooldown-timer');
+
+ if (item.found) {
+ itemDiv.classList.add('found');
+ foundCount++;
+ if (item.cooldown > 0) {
+ if (btn) btn.style.display = 'none';
+ if (cooldownEl) {
+ cooldownEl.style.display = 'block';
+ cooldownEl.textContent = `ON COOLDOWN: ${item.cooldown} TURNS`;
+ }
+ } else {
+ if (btn) {
+ btn.disabled = false;
+ btn.style.display = 'block';
+ btn.textContent = '[ ACTIVATE ]';
+ }
+ if (cooldownEl) cooldownEl.style.display = 'none';
+ }
+ } else {
+ itemDiv.classList.remove('found');
+ if (btn) {
+ btn.disabled = true;
+ btn.style.display = 'block';
+ btn.textContent = '[ NOT FOUND ]';
+ }
+ if (cooldownEl) cooldownEl.style.display = 'none';
+ }
+ });
+
+ const bonusDiv = document.getElementById('special-set-bonus');
+ if (bonusDiv) {
+ bonusDiv.textContent = `FULL SET BONUS [ ${foundCount} / 7 ]`;
+ bonusDiv.style.opacity = (foundCount === 7) ? '1' : '0.5';
+ }
+
+ const activateBonusBtn = document.getElementById('special-set-activate');
+ if (activateBonusBtn) activateBonusBtn.disabled = (foundCount !== 7);
+};
+
+Gamestate.activateBobblehead = async function(itemKey) {
+ const item = this.bobbleheads.find(i => i.key === itemKey);
+ if (!item || !item.found || item.cooldown > 0) return;
+
+ item.cooldown = item.totalCooldown;
+ let logMessage = `[ BOBBLEHEAD ] ${item.name} activated! ${item.desc}`;
+
+ if (item.key === 'a') {
+ this.hasManeuvered = false; // Grant an extra maneuver
+ }
+
+ await this.logAction(logMessage, true);
+ if (this.renderInventory) this.renderInventory();
+ this.updateInfo();
+};
+
+
Gamestate.init = function(){
if (winModal) winModal.style.display = "none";
if (!map) return;
@@ -1967,8 +2080,9 @@ document.getElementById('secret-dev-key')?.addEventListener('click', (e) => {
this.showToast("Dev: +100 Troops (Deploy Phase Active)");
});
document.getElementById('dev-heal')?.addEventListener('click', () => { if(this.player.commander) this.player.commander.hp = 100; this.updateInfo(); this.showToast("Dev: Commander Healed"); });
- document.getElementById('dev-storm')?.addEventListener('click', () => { this.radstorm.cooldown = 1; this.processRadstorm(); document.getElementById('dev-modal').style.display = 'none'; });
+ document.getElementById('dev-storm')?.addEventListener('click', () => { this.radstorm.cooldown = 1; this.processRadstorm();
+ // --- NEW DEV PERK BUTTON ---
document.getElementById('dev-perk')?.addEventListener('click', () => {
if (!Gamestate.bobbleheads) return;
let unfoundItems = Gamestate.bobbleheads.filter(item => !item.found);
@@ -1988,7 +2102,11 @@ document.getElementById('secret-dev-key')?.addEventListener('click', (e) => {
});
document.getElementById('dev-win-slider')?.addEventListener('input', function() {
+ let val = parseInt(this.value);
+ if (val === -1) {
+ document.getElementById('dev-modal').style.display = 'none'; });
+ document.getElementById('dev-win-slider')?.addEventListener('input', function() {
let val = parseInt(this.value);
if (val === -1) {
document.getElementById('dev-win-val').textContent = "NORMAL";
@@ -2014,10 +2132,8 @@ document.getElementById('secret-dev-key')?.addEventListener('click', (e) => {
if (Gamestate.showToast) Gamestate.showToast("Dev Override: UI forced to " + theme.toUpperCase());
});
- if (this.setupInventory) this.setupInventory();
}
-
Gamestate.updateButtonText = function() {
if (!end) return;
if (this.stage === "Fortify") {
@@ -3148,123 +3264,11 @@ Gamestate.maneuver = async function(e){
this.prevCountry = country;
}
-// --- INVENTORY & BOBBLEHEAD SYSTEM ---
-Gamestate.bobbleheads = [
- { key: 's', name: 'STRENGTH BOBBLEHEAD', found: false, cooldown: 0, totalCooldown: 5, bonus: 0.10, desc: 'Grants +10% attack odds for 1 turn.' },
- { key: 'p', name: 'PERCEPTION BOBBLEHEAD', found: false, cooldown: 0, totalCooldown: 8, desc: 'Reveals all enemy territories for 1 turn.' },
- { key: 'e', name: 'ENDURANCE BOBBLEHEAD', found: false, cooldown: 0, totalCooldown: 5, bonus: 0.10, desc: 'Reduces defender losses by 10% for 1 turn.' },
- { key: 'c', name: 'CHARISMA BOBBLEHEAD', found: false, cooldown: 0, totalCooldown: 10, desc: 'Your next Bottle Cap trade-in yields maximum troops.' },
- { key: 'i', name: 'INTELLIGENCE BOBBLEHEAD', found: false, cooldown: 0, totalCooldown: 8, desc: 'Reveals all rival leaderboard data for 1 turn.' },
- { key: 'a', name: 'AGILITY BOBBLEHEAD', found: false, cooldown: 0, totalCooldown: 6, bonus: 1, desc: 'Grants one extra army maneuver this turn.' },
- { key: 'l', name: 'LUCK BOBBLEHEAD', found: false, cooldown: 0, totalCooldown: 7, bonus: 3, desc: 'Triples the chance to find loot for 1 turn.' }
-];
-
-Gamestate.setupInventory = function() {
- const invModal = document.getElementById('inventory-modal');
- const navInv = document.getElementById('nav-inv');
- const navMap = document.getElementById('nav-map');
- const closeInvBtn = document.getElementById('close-inv-btn');
-
- if (!invModal || !navInv) return;
-
- navInv.addEventListener('click', () => {
- invModal.style.display = 'flex';
- navInv.classList.remove('inv-pulse');
- navInv.classList.add('map-active');
- if (navMap) navMap.classList.remove('map-active');
- this.renderInventory();
- });
-
- if (closeInvBtn) {
- closeInvBtn.addEventListener('click', () => {
- invModal.style.display = 'none';
- navInv.classList.remove('map-active');
- if (navMap) navMap.classList.add('map-active');
- });
- }
-
- this.bobbleheads.forEach(item => {
- const btn = document.querySelector(`#bobblehead-${item.key} .bobble-activate-btn`);
- if (btn) {
- btn.addEventListener('click', () => this.activateBobblehead(item.key));
- }
- });
-};
-
-Gamestate.renderInventory = function() {
- const stimpakCountEl = document.getElementById('inv-stimpak-count');
- if (stimpakCountEl && this.player && this.player.commander) {
- stimpakCountEl.textContent = this.player.commander.stimpaks;
- }
-
- let foundCount = 0;
- this.bobbleheads.forEach(item => {
- const itemDiv = document.getElementById(`bobblehead-${item.key}`);
- if (!itemDiv) return;
- const btn = itemDiv.querySelector('.bobble-activate-btn');
- const cooldownEl = itemDiv.querySelector('.cooldown-timer');
-
- if (item.found) {
- itemDiv.classList.add('found');
- foundCount++;
- if (item.cooldown > 0) {
- if (btn) btn.style.display = 'none';
- if (cooldownEl) {
- cooldownEl.style.display = 'block';
- cooldownEl.textContent = `ON COOLDOWN: ${item.cooldown} TURNS`;
- }
- } else {
- if (btn) {
- btn.disabled = false;
- btn.style.display = 'block';
- btn.textContent = '[ ACTIVATE ]';
- }
- if (cooldownEl) cooldownEl.style.display = 'none';
- }
- } else {
- itemDiv.classList.remove('found');
- if (btn) {
- btn.disabled = true;
- btn.style.display = 'block';
- btn.textContent = '[ NOT FOUND ]';
- }
- if (cooldownEl) cooldownEl.style.display = 'none';
- }
- });
-
- const bonusDiv = document.getElementById('special-set-bonus');
- if (bonusDiv) {
- bonusDiv.textContent = `FULL SET BONUS [ ${foundCount} / 7 ]`;
- bonusDiv.style.opacity = (foundCount === 7) ? '1' : '0.5';
- }
-
- const activateBonusBtn = document.getElementById('special-set-activate');
- if (activateBonusBtn) activateBonusBtn.disabled = (foundCount !== 7);
-};
-
-Gamestate.activateBobblehead = async function(itemKey) {
- const item = this.bobbleheads.find(i => i.key === itemKey);
- if (!item || !item.found || item.cooldown > 0) return;
-
- item.cooldown = item.totalCooldown;
- let logMessage = `[ BOBBLEHEAD ] ${item.name} activated! ${item.desc}`;
-
- if (item.key === 'a') {
- this.hasManeuvered = false; // Grant an extra maneuver
- }
-
- await this.logAction(logMessage, true);
- this.renderInventory();
- this.updateInfo();
-};
-
Gamestate.useStimpak = async function() {
if(this.stage !== "Commander Phase" || !this.commandersEnabled || !this.player.commander) return;
if(this.player.commander.ap <= 0 || this.player.commander.stimpaks <= 0 || this.player.commander.hp >= 100) return;
this.player.commander.stimpaks -= 1; this.player.commander.ap -= 1; this.player.commander.hp = Math.min(100, this.player.commander.hp + 20);
- await this.logAction("[ MEDICAL ] Commander injected a Stimpak. Recovered 20 HP.", true);
- if (this.renderInventory) this.renderInventory();
- this.updateInfo();
+ await this.logAction("[ MEDICAL ] Commander injected a Stimpak. Recovered 20 HP.", true); this.updateInfo();
}
Gamestate.initiateNukeSequence = function() {
@@ -3488,17 +3492,10 @@ for(let i = 1; i <= this.players.length; i++){
}
}
- this.turn += 1;
+this.turn += 1;
this.aiTurn = false;
await this.logAction(`--- DAY ${this.turn} BEGINS ---`, true);
- // BOBBLEHEAD COOLDOWNS
- if (this.bobbleheads) {
- this.bobbleheads.forEach(item => {
- if (item.cooldown > 0) item.cooldown--;
- });
- }
-
if(this.diplomacy.spiteTurns > 0) {
this.diplomacy.spiteTurns--;
if(this.diplomacy.spiteTurns <= 0) {
@@ -3636,43 +3633,23 @@ if (infoName[i-1]) infoName[i-1].parentElement.classList.remove('highlight');
this.aiManeuver(i);
- if (this.player.conqueredThisTurn) {
- let newCap = deck.length > 0 ? deck.pop() : { country: "Wasteland Salvage", type: "Wild" };
- this.player.cards.push(newCap);
-
- let luckItem = this.bobbleheads && this.bobbleheads.find(i => i.key === 'l' && i.cooldown > 0);
- const luckModifier = luckItem ? (luckItem.bonus / 10) : 0; // 30% if luck active, else 0%
-
- if (this.bobbleheads && Math.random() < (0.05 + luckModifier)) { // 5% base chance
- let unfoundItems = this.bobbleheads.filter(item => !item.found);
- if (unfoundItems.length > 0) {
- let foundItem = unfoundItems[Math.floor(Math.random() * unfoundItems.length)];
- foundItem.found = true;
- let navInv = document.getElementById('nav-inv');
- if (navInv) navInv.classList.add('inv-pulse');
- await this.logAction(`[ LOOT FOUND! ] You discovered a '${foundItem.name}'!`, true);
- } else {
- // If all found, fallback to Stimpaks/Codes
- if(this.commandersEnabled && this.player.commander && this.player.commander.stimpaks < 3 && Math.random() < 0.15) {
- this.player.commander.stimpaks++; await this.logAction("SCAVENGED: Found a rare Stimpak in the ruins!");
- } else if (this.nukesEnabled && this.player.codes < 4 && this.globalCodes > 0 && Math.random() < 0.15) {
- this.player.codes++; this.globalCodes--; this.showCodePopup(); await this.logAction("SCAVENGED: Recovered a heavily encrypted Launch Code Fragment!", true);
- } else {
- if (this.getBestTrade(this.player.cards)) await this.logAction("STASH FULL: Enough Caps collected to hire more troops.");
- else await this.logAction("SCAVENGED: Found a Bottle Cap after securing enemy territory.");
- }
+ if (this.players[i].conqueredThisTurn) {
+ let newCap = deck.length > 0 ? deck.pop() : { country: "Wasteland Salvage", type: "Wild" };
+ this.players[i].cards.push(newCap); this.players[i].conqueredThisTurn = false;
+ if (this.nukesEnabled && this.players[i].codes < 4 && this.globalCodes > 0 && Math.random() < 0.15) { this.players[i].codes++; this.globalCodes--; }
+ if (this.commandersEnabled && this.players[i].commander && this.players[i].commander.stimpaks < 1 && Math.random() < 0.15) { this.players[i].commander.stimpaks++; }
}
- } else if (this.commandersEnabled && this.player.commander && this.player.commander.stimpaks < 3 && Math.random() < 0.15) { // Stimpak limit increased to 3
- this.player.commander.stimpaks++;
- await this.logAction("SCAVENGED: Found a rare Stimpak in the ruins!");
- } else if (this.nukesEnabled && this.player.codes < 4 && this.globalCodes > 0 && Math.random() < 0.15) {
- this.player.codes++; this.globalCodes--; this.showCodePopup(); await this.logAction("SCAVENGED: Recovered a heavily encrypted Launch Code Fragment!", true);
- } else {
- if (this.getBestTrade(this.player.cards)) await this.logAction("STASH FULL: Enough Caps collected to hire more troops.");
- else await this.logAction("SCAVENGED: Found a Bottle Cap after securing enemy territory.");
- }
- this.updateInfo();
- }
+
+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); }
+
+ // FIX: Refill the AI Commander's Action Points every turn!
+ this.players[i].commander.ap = 2;
+ }
+
+ this.updateInfo();
+ }
}
}