#pragma once #include "CoreMinimal.h" #include "Core/DescentWorldSubsystem.h" #include "DescentOreSubsystem.generated.h" /** The mutable state of one ore vein (the vein itself is static data in FDescentWorldDef::Deposits). */ struct FDescentDepositState { int32 Removed = 0; // removed core samples toward the next chunk int32 Mined = 0; // loose chunks freed so far (<= the deposit's Yield) }; /** * Ore deposit state (DESIGN_UE.md sections 2.12, 9.4 `ore`). Milestone M1 covers the counters: the terrain reports * every rock sample it removes inside a vein; every DepositSamplesPerChunk of them free one chunk of ore * (`Mined++`, `OnOreFreed`), until the vein's yield is used up and its glow leaves the rock. Loose ore chunks, * suction and crystals belong to the mining milestone and subscribe to `OnOreFreed`. */ UCLASS() class THEDESCENT_API UDescentOreSubsystem : public UDescentWorldSubsystem { GENERATED_BODY() public: static UDescentOreSubsystem* Get(const UWorld* World); /** Broadcast with the deposit index and the position (metres) of the sample that completed a chunk. */ DECLARE_MULTICAST_DELEGATE_TwoParams(FOnOreFreed, int32 /*Deposit*/, const FVector& /*PosM*/); FOnOreFreed OnOreFreed; int32 NumDeposits() const; bool IsExhausted(int32 Deposit) const; int32 GetMined(int32 Deposit) const; int64 GetMinedTotal() const { return MinedTotal; } /** Called by the terrain for each core sample that went from rock to water inside vein `Deposit`. */ void NoteSampleRemoved(int32 Deposit, const FVector& PosM); /** `ore.query`: the result of the last Descent.World.NearestDeposit. */ struct FQuery { bool bValid = false; int32 Index = -1; FVector PosM = FVector::ZeroVector; FVector NormalM = FVector::ZeroVector; int32 Type = 0; int32 Yield = 0; int32 Mined = 0; }; FQuery LastQuery; /** Fills LastQuery for the deposit nearest to PosM (TypeFilter -1 = any). Returns false if none. */ bool QueryNearest(const FVector& PosM, int32 TypeFilter); /** Saving (section 6.12): the per-deposit counters. */ void GetState(TArray& OutMined, TArray& OutRemoved) const; void SetState(const TArray& InMined, const TArray& InRemoved); /** Forgets all counters (tests). */ void ResetState(); private: void EnsureStates() const; mutable TArray States; int64 MinedTotal = 0; };