Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
228 changes: 228 additions & 0 deletions src/machines.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1816,4 +1816,232 @@ machines["Eye of Harmony"] = {
choices.overclocks = Math.min(Math.max(choices.overclocks, 0), 24);
},
info: "NOTE: Power input/output not calculated"
}

const FOG_MODULE_BASE_PARALLEL : Map<string, number> = new Map([
["Helioflare Power Forge", 1024],
]);

function getFogRawHeat(crafter:string, choices:{[key:string]:number}) {
const fuelFactor = choices.fuelFactor;
let logBase = 1.5;
let baseHeat = 12601;
if (choices.upgrade_SEFCP == 1) {
logBase = (crafter === "Helioflux Power Forge") ? 1.12 : 1.18;
}
return baseHeat + Math.floor((Math.log(fuelFactor) / Math.log(logBase) * 1000));
}

function getFogHeatForOC(crafter: string, choices:{[key:string]:number}, rawHeat: number) {
let actualHeat = 0;

if (choices.upgrade_NDPE == 1) {
const exponent = (crafter === "Helioflux Power Forge") ? 0.85 : 0.8;
actualHeat = (rawHeat > 30000) ? Math.floor(30000 + Math.pow(rawHeat - 30000, exponent)) : rawHeat;
} else if (choices.upgrade_CNTI == 1) {
actualHeat = Math.min(rawHeat, 30000);
} else {
actualHeat = Math.min(rawHeat, 15000);
}

return actualHeat;
}

function getFogEffectiveFuelFactor(fuelFactor: number) {
if (fuelFactor <= 43) {
return fuelFactor;
} else {
return 43 + Math.floor(Math.pow((fuelFactor - 43), 0.4));
}
}

function getFogModuleParallel(crafter: string, recipeModel: RecipeModel, choices:{[key:string]:number}) {
const fuelFactor = choices.fuelFactor;
const upgradeCount = choices.upgradeCount;
const heat = getFogRawHeat(crafter, choices);
const baseParallel = FOG_MODULE_BASE_PARALLEL.get(crafter) || 1;

let fuelFactorMultiplier = 1;
let heatMultiplier = 1;
let upgradeAmountMultiplier = 1;
let node53 = (choices.upgrade_CTCDD == 1) ? 2 : 1;
let isMoltenOrSmeltingWithUpgrade =
(crafter === "Helioflux Melting Core")
|| (crafter === "Helioflux Power Forge" && choices.upgrade_DOP == 1);

if (choices.upgrade_SA == 1) {
fuelFactorMultiplier = 1 + getFogEffectiveFuelFactor(fuelFactor) / 15.0;
if (choices.upgrade_TCT == 1) {
fuelFactorMultiplier *= isMoltenOrSmeltingWithUpgrade ? 3 : 2;
}
}

if (choices.upgrade_EPEC == 1) {
const divisor = isMoltenOrSmeltingWithUpgrade ? 15000 : 25000;
heatMultiplier = 1 + heat / divisor;
}

if (choices.upgrade_POS == 1) {
const divisor = isMoltenOrSmeltingWithUpgrade ? 5 : 8;
upgradeAmountMultiplier = 1 + upgradeCount / divisor;
}

let totalBonuses = node53 * fuelFactorMultiplier * heatMultiplier * upgradeAmountMultiplier;

if (crafter === "Heliofusion Exoticizer") {
totalBonuses = (choices.upgrade_PA == 1) ? Math.sqrt(totalBonuses) : 1;
}

const maxParallel = Math.floor(baseParallel * totalBonuses);

return maxParallel;
}

function getFogModuleSpeed(crafter: string, recipeModel: RecipeModel, choices:{[key:string]:number}) {
const heat = getFogRawHeat(crafter, choices);

let durationModifier = 1;

if (choices.upgrade_IGCC == 1) {
durationModifier = Math.pow(heat, -0.01);
}

if (choices.upgrade_DOR == 1) {
const parallels = getFogModuleParallel(crafter, recipeModel, choices);
const exponent = (crafter === "Heliothermal Plasma Fabricator") ? 0.02 : 0.012;
durationModifier /= Math.pow(parallels, exponent);
}

if (crafter === "Heliofusion Exoticizer") {
durationModifier = (choices.upgrade_PA == 1) ? Math.sqrt(durationModifier) : 1;
}

return 1 / durationModifier;
}

// TODO: use actual voltage instead of voltage tier approximation.
function getFogVoltage(crafter: string, recipeModel: RecipeModel, choices:{[key:string]:number}) {
const fuelFactor = choices.fuelFactor;
const ringCount = choices.ringCount;
let voltage = 2e9;

if (choices.upgrade_GISS == 1) {
voltage += getFogEffectiveFuelFactor(fuelFactor) * 1e8;
}

if (choices.upgrade_NGMS == 1) {
voltage *= Math.pow(4, ringCount);
}

return voltage;
}

function getFogVoltageTier(crafter: string, recipeModel: RecipeModel, choices:{[key:string]:number}) {
const voltage = getFogVoltage(crafter, recipeModel, choices);
const parallels = getFogModuleParallel(crafter, recipeModel, choices);
const power = voltage * parallels * 4;
for (let i = 0; i < voltageTier.length; ++i) {
if (voltageTier[i].voltage > power) {
return i - 1;
}
}
return voltageTier.length - 1;
}

function getFogModulePowerMultiplier(crafter: string, recipeModel: RecipeModel, choices:{[key:string]:number}) {
const rawHeat = getFogRawHeat("Helioflare Power Forge", choices);
const heatForOC = getFogHeatForOC("Helioflare Power Forge", choices, rawHeat);
const recipeHeat = recipeModel.recipe?.gtRecipe.specialValue ?? 0;
const discounts = Math.floor((heatForOC - recipeHeat) / 900);
const base = (choices.upgrade_IMKG == 1) ? 0.92 : 0.95;
return Math.pow(base, discounts);
}

machines["Helioflare Power Forge"] = {
speed: (recipeModel, choices) => getFogModuleSpeed("Helioflare Power Forge", recipeModel, choices),
power: (recipeModel, choices) => getFogModulePowerMultiplier("Helioflare Power Forge", recipeModel, choices),
parallels: (recipeModel, choices) => getFogModuleParallel("Helioflare Power Forge", recipeModel, choices),
choices: {
fuelFactor: {
description: "Fuel factor",
min: 1
},
upgradeCount: {
description: "Upgrade count",
min: 1
},
ringCount: {
description: "Ring count",
min: 1
},
upgrade_DOP: {
description: "DOP",
choices: ["No", "Yes"]
},
upgrade_CTCDD: {
description: "CTCDD",
choices: ["No", "Yes"]
},
upgrade_SA: {
description: "SA",
choices: ["No", "Yes"]
},
upgrade_EPEC: {
description: "EPEC",
choices: ["No", "Yes"]
},
upgrade_POS: {
description: "POS",
choices: ["No", "Yes"]
},
upgrade_PA: {
description: "PA",
choices: ["No", "Yes"]
},
upgrade_TCT: {
description: "TCT",
choices: ["No", "Yes"]
},
upgrade_NDPE: {
description: "NDPE",
choices: ["No", "Yes"]
},
upgrade_CNTI: {
description: "CNTI",
choices: ["No", "Yes"]
},
upgrade_SEFCP: {
description: "SEFCP",
choices: ["No", "Yes"]
},
upgrade_IGCC: {
description: "IGCC",
choices: ["No", "Yes"]
},
upgrade_DOR: {
description: "DOR",
choices: ["No", "Yes"]
},
upgrade_GISS: {
description: "GISS",
choices: ["No", "Yes"]
},
upgrade_NGMS: {
description: "NGMS",
choices: ["No", "Yes"]
},
upgrade_IMKG: {
description: "IMKG",
choices: ["No", "Yes"]
}
},
fixedVoltageTier: (recipeModel, choices) => getFogVoltageTier("Helioflare Power Forge", recipeModel, choices),
// TODO: normal overclock factor
overclocker: (recipeModel, choices) => {
const rawHeat = getFogRawHeat("Helioflare Power Forge", choices);
const heatForOC = getFogHeatForOC("Helioflare Power Forge", choices, rawHeat);
const recipeHeat = recipeModel.recipe?.gtRecipe.specialValue ?? 0;
const maxPerfectOverclocks = Math.floor((heatForOC - recipeHeat) / 1800);
return StandardOverclocker.perfectThenNormal(maxPerfectOverclocks);
}
}