double coreSat = (double) saturation.value / (double) maxSaturation.value; //1 = Max Saturation
double negCSat = (1D - coreSat) * 99D; //99 = Min Saturation. I believe this tops out at 99 because at 100 things would overflow and break.
double temp50 = Math.min((temperature.value / MAX_TEMPERATURE) * 50, 99); //50 = Max Temp. Why? TBD
double tFuel = convertedFuel.value + reactableFuel.value; //Total Fuel.
double convLVL = ((convertedFuel.value / tFuel) * 1.3D) - 0.3D; //Conversion Level sets how much the current conversion level boosts power gen. Range: -0.3 to 1.0
//region ============= Temperature Calculation =============
double tempOffset = 444.7; //Adjusts where the temp falls to at 100% saturation
//The exponential temperature rise which increases as the core saturation goes down
double tempRiseExpo = (negCSat * negCSat * negCSat) / (100 - negCSat) + tempOffset; //This is just terrible... I cant believe i wrote this stuff... //作者稍纵即逝的良知 --CRMP
//This is used to add resistance as the temp rises because the hotter something gets the more energy it takes to get it hotter
double tempRiseResist = (temp50 * temp50 * temp50 * temp50) / (100 - temp50);
//^ Mostly Correct... The hotter an object gets the faster it dissipates heat into its surroundings to the more energy it takes to compensate for that energy loss.
//This puts all the numbers together and gets the value to raise or lower the temp by this tick. This is dealing with very big numbers so the result is divided by 10000
double riseAmount = (tempRiseExpo - (tempRiseResist * (1D - convLVL)) + convLVL * 1000) / 10000;
//Apply energy calculations.
if (reactorState.value == ReactorState.STOPPING && convLVL < 1) {
if (temperature.value <= 2001) {
reactorState.value = ReactorState.COOLING;
startupInitialized.value = false;
return;
}
if (saturation.value >= maxSaturation.value * 0.99D && reactableFuel.value > 0D) {
temperature.value -= 1D - convLVL;
}
else {
temperature.value += riseAmount * 10;
}
}
else {
temperature.value += riseAmount * 10;
}
//endregion ================================================
//region ============= Energy Calculation =============
int baseMaxRFt = (int) ((maxSaturation.value / 1000D) * DEConfig.reactorOutputMultiplier * 1.5D);
int maxRFt = (int) (baseMaxRFt * (1D + (convLVL * 2)));
generationRate.value = (1D - coreSat) * maxRFt;
saturation.value += generationRate.value;
//endregion ===========================================
//region ============= Shield Calculation =============
tempDrainFactor.value = temperature.value > 8000 ? 1 +((temperature.value - 8000) * (temperature.value - 8000) * 0.0000025) : temperature.value > 2000 ? 1 : temperature.value > 1000 ? (temperature.value - 1000) / 1000 :0;
fieldDrain.value = (int) Math.min(tempDrainFactor.value * Math.max(0.01, (1D - coreSat)) * (baseMaxRFt / 10.923556), (double) Integer.MAX_VALUE); //<(baseMaxRFt/make smaller to increase field power drain)
double fieldNegPercent = 1D - (shieldCharge.value / maxShieldCharge.value);
fieldInputRate.value = fieldDrain.value / fieldNegPercent;
shieldCharge.value -= Math.min(fieldDrain.value, shieldCharge.value);
//endregion ===========================================
//region ============== Fuel Calculation ==============
fuelUseRate.value = tempDrainFactor.value * (1D - coreSat) * (0.001 * DEConfig.reactorFuelUsageMultiplier); //<Last number is base fuel usage rate
if (reactableFuel.value > 0) {
convertedFuel.value += fuelUseRate.value;
reactableFuel.value -= fuelUseRate.value;
}
//endregion ===========================================
//region Explosion
if ((shieldCharge.value <= 0) && temperature.value > 2000 && reactorState.value != ReactorState.BEYOND_HOPE) {
reactorState.value = ReactorState.BEYOND_HOPE;
for (int i = 0; i < componentPositions.length; i++) {
ManagedVec3I v = componentPositions[i];
if (v.vec.sum() > 0) {
BlockPos p = getOffsetPos(v.vec).offset(EnumFacing.getFront(i).getOpposite());
world.newExplosion(null, p.getX() + 0.5, p.getY() + 0.5, p.getZ() + 0.5, 4, true, true);
}
}
}
//endregion ======
//Worst case it rolls back a second
if (tick % 20 == 0) {
markDirty();
}
}