wip: fix debuff corruption bug — debuffs no longer degrade boost multipliers on each updateRates() call; persist playTime across sessions
This commit is contained in:
44
game.js
44
game.js
@@ -1017,17 +1017,23 @@ function updateRates() {
|
||||
G.userRate = 0; G.impactRate = 0; G.rescuesRate = 0; G.opsRate = 0; G.trustRate = 0;
|
||||
G.creativityRate = 0; G.harmonyRate = 0;
|
||||
|
||||
// Apply building rates
|
||||
// Snapshot base boosts BEFORE debuffs modify them
|
||||
// Without this, debuffs permanently degrade boost multipliers on each updateRates() call
|
||||
let _codeBoost = G.codeBoost, _computeBoost = G.computeBoost;
|
||||
let _knowledgeBoost = G.knowledgeBoost, _userBoost = G.userBoost;
|
||||
let _impactBoost = G.impactBoost;
|
||||
|
||||
// Apply building rates using snapshot boosts (immune to debuff mutation)
|
||||
for (const def of BDEF) {
|
||||
const count = G.buildings[def.id] || 0;
|
||||
if (count > 0 && def.rates) {
|
||||
for (const [resource, baseRate] of Object.entries(def.rates)) {
|
||||
if (resource === 'code') G.codeRate += baseRate * count * G.codeBoost;
|
||||
else if (resource === 'compute') G.computeRate += baseRate * count * G.computeBoost;
|
||||
else if (resource === 'knowledge') G.knowledgeRate += baseRate * count * G.knowledgeBoost;
|
||||
else if (resource === 'user') G.userRate += baseRate * count * G.userBoost;
|
||||
else if (resource === 'impact') G.impactRate += baseRate * count * G.impactBoost;
|
||||
else if (resource === 'rescues') G.rescuesRate += baseRate * count * G.impactBoost;
|
||||
if (resource === 'code') G.codeRate += baseRate * count * _codeBoost;
|
||||
else if (resource === 'compute') G.computeRate += baseRate * count * _computeBoost;
|
||||
else if (resource === 'knowledge') G.knowledgeRate += baseRate * count * _knowledgeBoost;
|
||||
else if (resource === 'user') G.userRate += baseRate * count * _userBoost;
|
||||
else if (resource === 'impact') G.impactRate += baseRate * count * _impactBoost;
|
||||
else if (resource === 'rescues') G.rescuesRate += baseRate * count * _impactBoost;
|
||||
else if (resource === 'ops') G.opsRate += baseRate * count;
|
||||
else if (resource === 'trust') G.trustRate += baseRate * count;
|
||||
else if (resource === 'creativity') G.creativityRate += baseRate * count;
|
||||
@@ -1108,15 +1114,24 @@ function updateRates() {
|
||||
// Swarm Protocol: buildings auto-code based on click power
|
||||
if (G.swarmFlag === 1) {
|
||||
const totalBuildings = Object.values(G.buildings).reduce((a, b) => a + b, 0);
|
||||
const clickPower = getClickPower();
|
||||
G.swarmRate = totalBuildings * clickPower;
|
||||
// Compute click power using snapshot boost to avoid debuff mutation
|
||||
const _clickPower = (1 + Math.floor(G.buildings.autocoder * 0.5) + Math.max(0, (G.phase - 1)) * 2) * _codeBoost;
|
||||
G.swarmRate = totalBuildings * _clickPower;
|
||||
G.codeRate += G.swarmRate;
|
||||
}
|
||||
|
||||
// Apply persistent debuffs from active events
|
||||
// Apply persistent debuffs to rates (NOT to global boost fields — prevents corruption)
|
||||
if (G.activeDebuffs && G.activeDebuffs.length > 0) {
|
||||
for (const debuff of G.activeDebuffs) {
|
||||
if (debuff.applyFn) debuff.applyFn();
|
||||
switch (debuff.id) {
|
||||
case 'runner_stuck': G.codeRate *= 0.5; break;
|
||||
case 'ezra_offline': G.userRate *= 0.3; break;
|
||||
case 'unreviewed_merge': G.trustRate -= 2; break;
|
||||
case 'api_rate_limit': G.computeRate *= 0.5; break;
|
||||
case 'bilbo_vanished': G.creativityRate = 0; break;
|
||||
case 'memory_leak': G.computeRate *= 0.7; G.opsRate -= 10; break;
|
||||
case 'community_drama': G.harmonyRate -= 0.5; G.codeRate *= 0.7; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1182,6 +1197,7 @@ function tick() {
|
||||
}
|
||||
|
||||
G.tick += dt;
|
||||
G.playTime += dt;
|
||||
|
||||
// Sprint ability
|
||||
tickSprint(dt);
|
||||
@@ -2047,7 +2063,7 @@ function renderStats() {
|
||||
set('st-drift', (G.drift || 0).toString());
|
||||
set('st-resolved', (G.totalEventsResolved || 0).toString());
|
||||
|
||||
const elapsed = Math.floor((Date.now() - G.startedAt) / 1000);
|
||||
const elapsed = Math.floor(G.playTime || (Date.now() - G.startedAt) / 1000);
|
||||
const m = Math.floor(elapsed / 60);
|
||||
const s = elapsed % 60;
|
||||
set('st-time', `${m}:${s.toString().padStart(2, '0')}`);
|
||||
@@ -2685,6 +2701,7 @@ function saveGame() {
|
||||
swarmRate: G.swarmRate || 0,
|
||||
strategicFlag: G.strategicFlag || 0,
|
||||
projectsCollapsed: G.projectsCollapsed !== false,
|
||||
playTime: G.playTime || 0,
|
||||
savedAt: Date.now()
|
||||
};
|
||||
|
||||
@@ -2716,7 +2733,8 @@ function loadGame() {
|
||||
'drift', 'driftEnding', 'beaconEnding', 'pendingAlignment',
|
||||
'lastEventAt', 'totalEventsResolved', 'buyAmount',
|
||||
'sprintActive', 'sprintTimer', 'sprintCooldown',
|
||||
'swarmFlag', 'swarmRate', 'strategicFlag', 'projectsCollapsed'
|
||||
'swarmFlag', 'swarmRate', 'strategicFlag', 'projectsCollapsed',
|
||||
'playTime'
|
||||
];
|
||||
|
||||
G.isLoading = true;
|
||||
|
||||
Reference in New Issue
Block a user