From 8630ae659caeefda3c8516d39043da9b11bef519 Mon Sep 17 00:00:00 2001 From: Alex Anderson Date: Fri, 3 Mar 2023 19:21:40 -0500 Subject: [PATCH] feat: Add a simulation for calculating the power used by a ship system. --- server/src/systems/PowerDrawSystem.ts | 75 +++++++++++++++++++++++++++ server/src/systems/index.ts | 2 + 2 files changed, 77 insertions(+) create mode 100644 server/src/systems/PowerDrawSystem.ts 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 91ad274d..f3bbdc29 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"; const systems = [ FilterInventorySystem, @@ -32,6 +33,7 @@ const systems = [ TimerSystem, ReactorFuelSystem, ReactorHeatSystem, + PowerDrawSystem, AutoRotateSystem, AutoThrustSystem, ThrusterSystem,