#pragma once #include "CoreMinimal.h" #include "Core/DescentHandle.h" #include "Core/DescentWorldSubsystem.h" #include "DescentBio.generated.h" class ADescentCarrier; class ADescentCharacter; class UInstancedStaticMeshComponent; class UMaterialInstanceDynamic; class UStaticMeshComponent; /** The numbers of the biomass reserve (M8, requirements U2, U3; DESIGN_UE.md section 6.9). 1 FU = 25 points of nutrition = 10 minutes of life. */ namespace Descent::Bio { constexpr double CapFU = 20.0, StartFU = 6.0; constexpr double NutritionPerFU = 25.0; constexpr double EmptyBelowFU = 0.1; constexpr double JackTotalSec = 4.8, FeedFromSec = 1.0, FeedToSec = 4.1; constexpr double JackFeeCr = 12.0; constexpr double PieceFU = 0.05, PipeFeedEverySec = 0.1, PipeSpeedMps = 6.0; /** What a jack-in does: the nutrition it ends at and the reserve it uses. */ THEDESCENT_API void FeedPlan(double Nutrition, double ReserveFU, double& OutTarget, double& OutUsedFU); /** FU of one fauna item ("silverfin", "lanternfish", "jelly", "polyp"); 0 for anything else. */ THEDESCENT_API double FaunaValue(FName Item); THEDESCENT_API const TArray& BioPipeRouteM(); } /** The carrier's finite nutrient reserve: the wall ports draw from it, collected fauna refills it (through the bio pipe from a docked Tender, or by hand at the vat). */ UCLASS() class THEDESCENT_API UDescentBioSubsystem : public UDescentWorldSubsystem { GENERATED_BODY() public: static UDescentBioSubsystem* Get(const UWorld* World); virtual void OnWorldBeginPlay(UWorld& InWorld) override; virtual void Deinitialize() override; double ReserveFU = Descent::Bio::StartFU; /** Adds to the reserve up to the capacity; returns what went in. */ double AddFU(double Fu); /** E at a wall port: the 4.8 s plug sequence (the arm plays it). Refused when the reserve is empty or the player is full. */ bool BeginJackIn(ADescentCharacter* User, const FVector& PortLocalM, double PortYawDeg, FString* OutWhyNot = nullptr); bool IsJackActive() const { return JackT >= 0.0; } double JackTime() const { return JackT; } /** E at the vat: loads the fauna the player carries. Returns the FU loaded (0: nothing to load, the window opens instead). */ double UseVat(ADescentCharacter* User); /** E at a bed or bunk: +2 h, refinery +120 s, health 100, nutrition -10 (not below 8), Tenders charged and repaired, autosave. */ void Sleep(ADescentCharacter* User); int32 PortRefused = 0, Feeds = 0, Sleeps = 0; double PipedFU = 0.0, HandFU = 0.0, LastUsedFU = 0.0; int32 PipePieces() const { return Pieces.Num(); } private: void Step(double Dt); void EnsureVisuals(); void UpdateVisuals(); double JackT = -1.0, JackN0 = 0.0, JackTarget = 0.0, JackUsed = 0.0; TWeakObjectPtr JackUser; TArray Pieces; double FeedTimer = 0.0; FDescentHandle StepHandle; UPROPERTY(Transient) TObjectPtr Visual; UPROPERTY(Transient) TObjectPtr Liquid; UPROPERTY(Transient) TObjectPtr PieceMesh; UPROPERTY(Transient) TArray> RingMIDs; };