private void ProcessElectricity(Part partObj, float time)
{
if (ProcessorMode == ProcessorModes.OFF) return;
double volumePower = 0;
if (shared.VolumeMgr.CheckCurrentVolumeRange())
{
// If the current volume is in range, check the capacity and calculate power
var volume = shared.VolumeMgr.CurrentVolume;
if (volume.Name == "Archive")
{
volumePower = ARCHIVE_EFFECTIVE_BYTES * ECPerBytePerSecond;
}
else
{
volumePower = volume.Capacity * ECPerBytePerSecond;
}
}
else
{
// if the volume isn't in range, assume it doesn't consume any power
volumePower = 0;
}
if (ProcessorMode == ProcessorModes.STARVED)
{
// If the processor is STARVED, check to see if there is enough EC to turn it back on.
var request = averagePower.Mean; // use the average power draw as a baseline of the power needed to restart.
if (request > 0)
{
var available = partObj.RequestResource("ElectricCharge", request);
if (available / request > 0.5)
{
SetMode(ProcessorModes.READY);
}
// Since we're just checking to see if there is enough power to restart, return
// the consumed EC. The actual demand value will be drawn on the next update after
// the cpu boots. This should give the ship a chance to collect a little more EC
// before the cpu actually boots.
partObj.RequestResource("ElectricCharge", -available);
}
else
{
// If there is no historical power request, simply turn the processor back on. This
// should not be possible, since it means that some how the processor got set to
// the STARVED mode, even though no power was requested.
SetMode(ProcessorModes.READY);
}
RequiredPower = (float)request; // Make sure RequiredPower matches the average.
}
else
{
// Because the processor is not STARVED, evaluate the power requirement based on actual operation.
// For EC drain purposes, always pretend atleast 1 instruction happened, so idle drain isn't quite zero:
int instructions = System.Math.Max(shared.Cpu.InstructionsThisUpdate, 1);
var request = volumePower * time + instructions * ECPerInstruction;
if (request > 0)
{
// only check the available EC if the request is greater than 0EC. If the request value
// is zero, then available will always be zero and it appears that mono/.net treat
// "0 / 0" as equaling "0", which prevents us from checking the ratio. Since getting
// "0" available of "0" requested is a valid state, the processor mode is only evaluated
// if request is greater than zero.
var available = partObj.RequestResource("ElectricCharge", request);
if (available / request < 0.5)
{
// 0.5 is an arbitrary ratio for triggering the STARVED mode. It allows for some
// fluctuation away from the exact requested EC, ando adds some fuzzy math to how
// we deal with the descreet physics frames. Essentially if there was enough power
// to run for half of a physics frame, the processor stays on.
SetMode(ProcessorModes.STARVED);
}
}
// Set RequiredPower to the average requested power. This should help "de-bounce" the value
// so that it doesn't fluctuate wildly (between 0.2 and 0.000001 in a single frame for example)
RequiredPower = (float)averagePower.Update(request) / TimeWarp.fixedDeltaTime;
}
}