diff --git a/server/src/systems/PowerDrawSystem.ts b/server/src/systems/PowerDrawSystem.ts new file mode 100644 index 00000000..6f2cc533 --- /dev/null +++ b/server/src/systems/PowerDrawSystem.ts @@ -0,0 +1,75 @@ +import {Entity, System} from "../utils/ecs"; + +/** + * There's a subtle distinction between powerDraw and requestedPower + * - powerDraw is how much power the system is currently pulling based + * on it's current workload. + * - requestedPower is an artificial limit placed by the crew that keeps + * the power draw at or below that limit. + */ + +export class PowerDrawSystem extends System { + test(entity: Entity) { + return !!entity.components.power && !!entity.components.isShipSystem; + } + update(entity: Entity) { + const systemType = entity.components.isShipSystem; + const power = entity.components.power; + const efficiency = entity.components.efficiency?.efficiency || 1; + const efficiencyMultiple = 1 / efficiency; + if (!systemType?.type || !power) return; + const {maxSafePower, requiredPower} = power; + let powerDraw = 0; + switch (systemType.type) { + case "warpEngines": { + if (!entity.components.isWarpEngines) return; + const {currentWarpFactor, warpFactorCount} = + entity.components.isWarpEngines; + if (currentWarpFactor === 0) break; + const warpEngineUse = currentWarpFactor / warpFactorCount; + powerDraw = + (maxSafePower - requiredPower) * warpEngineUse + requiredPower; + break; + } + case "impulseEngines": { + if (!entity.components.isImpulseEngines) return; + const {cruisingSpeed, targetSpeed} = entity.components.isImpulseEngines; + if (targetSpeed === 0) break; + const impulseEngineUse = targetSpeed / cruisingSpeed; + powerDraw = + (maxSafePower - requiredPower) * impulseEngineUse + requiredPower; + break; + } + case "thrusters": { + if (!entity.components.isThrusters) return; + const {direction, rotationDelta, thrusting} = + entity.components.isThrusters; + if (!thrusting) break; + const directionOutput = Math.hypot( + direction.x, + direction.y, + direction.z + ); + const rotationOutput = Math.hypot( + rotationDelta.x, + rotationDelta.y, + rotationDelta.z + ); + const totalOutput = directionOutput + rotationOutput; + powerDraw = + (maxSafePower - requiredPower) * totalOutput + requiredPower; + break; + } + case "generic": + powerDraw = power.requestedPower; + break; + default: + return; + } + + // Limit the power draw to the requested power, so we never go over it. + entity.updateComponent("power", { + powerDraw: Math.min(power.requestedPower, powerDraw * efficiencyMultiple), + }); + } +} diff --git a/server/src/systems/index.ts b/server/src/systems/index.ts index 4e94da49..ede20b21 100644 --- a/server/src/systems/index.ts +++ b/server/src/systems/index.ts @@ -22,6 +22,7 @@ import {FilterInventorySystem} from "./FilterInventorySystem"; import {ReactorHeatSystem} from "./ReactorHeatSystem"; import {HeatToCoolantSystem} from "./HeatToCoolantSystem"; import {HeatDispersionSystem} from "./HeatDispersionSystem"; +import {PowerDrawSystem} from "./PowerDrawSystem"; import {PowerGridSystem} from "./PowerGridSystem"; const systems = [ @@ -33,6 +34,7 @@ const systems = [ TimerSystem, ReactorFuelSystem, ReactorHeatSystem, + PowerDrawSystem, PowerGridSystem, AutoRotateSystem, AutoThrustSystem,