diff --git a/src/Corporation/Actions.ts b/src/Corporation/Actions.ts index 81521f9ac..fc7e33bfb 100644 --- a/src/Corporation/Actions.ts +++ b/src/Corporation/Actions.ts @@ -420,28 +420,31 @@ export function MakeProduct( division.products.set(product.name, product); } -export function Research(division: Division, researchName: CorpResearchName): void { +export function Research(researchingDivision: Division, researchName: CorpResearchName): void { const corp = Player.corporation; if (!corp) return; - const researchTree = IndustryResearchTrees[division.type]; - if (researchTree === undefined) throw new Error(`No research tree for industry '${division.type}'`); + const researchTree = IndustryResearchTrees[researchingDivision.type]; + if (researchTree === undefined) throw new Error(`No research tree for industry '${researchingDivision.type}'`); const research = ResearchMap[researchName]; - if (division.researched.has(researchName)) return; - if (division.researchPoints < research.cost) + if (researchingDivision.researched.has(researchName)) return; + if (researchingDivision.researchPoints < research.cost) { throw new Error(`You do not have enough Scientific Research for ${research.name}`); - division.researchPoints -= research.cost; + } + researchingDivision.researchPoints -= research.cost; // Get the Node from the Research Tree and set its 'researched' property researchTree.research(researchName); - division.researched.add(researchName); - - // I couldn't figure out where else to put this so that warehouse size would get updated instantly - // whether research is done by script or UI. All other stats gets calculated in every cycle - // Warehouse size gets updated only when something increases it. - if (researchName == "Drones - Transport") { - for (const warehouse of getRecordValues(division.warehouses)) { - warehouse.updateSize(corp, division); + // All divisions of the same type as the researching division get the new research. + for (const division of corp.divisions.values()) { + if (division.type !== researchingDivision.type) continue; + division.researched.add(researchName); + // Handle researches that need to have their effects manually applied here. + // Warehouse size needs to be updated here because it is not recalculated during normal processing. + if (researchName == "Drones - Transport") { + for (const warehouse of getRecordValues(division.warehouses)) { + warehouse.updateSize(corp, division); + } } } } diff --git a/src/Corporation/Division.ts b/src/Corporation/Division.ts index d03939cbb..0b1e4c2a2 100644 --- a/src/Corporation/Division.ts +++ b/src/Corporation/Division.ts @@ -16,6 +16,7 @@ import { CorpMaterialName, CorpResearchName, CorpStateName } from "@nsdefs"; import { JSONMap, JSONSet } from "../Types/Jsonable"; import { PartialRecord, getRecordEntries, getRecordKeys, getRecordValues } from "../Types/Record"; import { Material } from "./Material"; +import { getKeyList } from "../utils/helpers/getKeyList"; interface DivisionParams { name: string; @@ -30,6 +31,9 @@ export class Division { researched = new JSONSet(); requiredMaterials: PartialRecord = {}; + // Not included in save file. Just used for tracking whether research tree has been updated since game load. + treeInitialized = false; + //An array of the name of materials being produced producedMaterials: CorpMaterialName[] = []; @@ -1031,8 +1035,13 @@ export class Division { } updateResearchTree(): void { + if (this.treeInitialized) return; const researchTree = IndustryResearchTrees[this.type]; + // Need to populate the tree in case we are loading a game. for (const research of this.researched) researchTree.research(research); + // Also need to load researches from the tree in case we are making a new division. + for (const research of researchTree.researched) this.researched.add(research); + this.treeInitialized = true; } // Get multipliers from Research @@ -1098,13 +1107,15 @@ export class Division { /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { - return Generic_toJSON("Division", this); + return Generic_toJSON("Division", this, Division.includedKeys); } /** Initializes a Industry object from a JSON save state. */ static fromJSON(value: IReviverValue): Division { - return Generic_fromJSON(Division, value.data); + return Generic_fromJSON(Division, value.data, Division.includedKeys); } + + static includedKeys = getKeyList(Division, { removedKeys: ["treeInitialized"] }); } constructorsForReviver.Division = Division; diff --git a/src/Corporation/ResearchTree.ts b/src/Corporation/ResearchTree.ts index 11d830fbb..b9518f7c4 100644 --- a/src/Corporation/ResearchTree.ts +++ b/src/Corporation/ResearchTree.ts @@ -217,9 +217,7 @@ export class ResearchTree { // Marks a Node as researched research(name: CorpResearchName): void { - if (this.root == null) { - return; - } + if (!this.root || this.researched.has(name)) return; const queue: Node[] = []; queue.push(this.root); @@ -233,9 +231,7 @@ export class ResearchTree { return; } - for (let i = 0; i < node.children.length; ++i) { - queue.push(node.children[i]); - } + queue.push(...node.children); } console.warn(`ResearchTree.research() did not find the specified Research node for: ${name}`); diff --git a/src/SaveObject.tsx b/src/SaveObject.tsx index e75d7030b..bd4e766d6 100755 --- a/src/SaveObject.tsx +++ b/src/SaveObject.tsx @@ -652,6 +652,7 @@ function evaluateVersionCompatibility(ver: string | number): void { // Prior to v2.2.0, sleeve shock was 0 to 100 internally but displayed as 100 to 0. This unifies them as 100 to 0. for (const sleeve of Player.sleeves) sleeve.shock = 100 - sleeve.shock; } + // Some 2.3 changes are actually in BaseServer.js fromJSONBase function if (ver < 31) { Terminal.warn("Migrating to 2.3.0, loading with no scripts."); for (const server of GetAllServers()) { @@ -680,6 +681,20 @@ function evaluateVersionCompatibility(ver: string | number): void { } // End 2.3 changes } + //2.3 hotfix changes and 2.3.1 changes + if (ver < 32) { + // Due to a bug from before 2.3, some scripts have the wrong server listed. In 2.3 this caused issues. + for (const server of GetAllServers()) { + for (const script of server.scripts.values()) { + if (script.server !== server.hostname) { + console.warn( + `Detected script ${script.filename} on ${server.hostname} with incorrect server property: ${script.server}. Repairing.`, + ); + script.server = server.hostname; + } + } + } + } } function loadGame(saveString: string): boolean {