Files
ArachnaeSwarm/Source/ArachnaeSwarm/Building_Comps/CompRefuelableNutrition.cs
2025-10-15 15:40:34 +08:00

119 lines
3.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Collections.Generic;
using RimWorld;
using UnityEngine;
using Verse;
namespace ArachnaeSwarm
{
public class CompProperties_RefuelableNutrition : CompProperties_Refuelable
{
public bool silent = false;
public CompProperties_RefuelableNutrition()
{
compClass = typeof(CompRefuelableNutrition);
this.targetFuelLevelConfigurable = true;
this.showAllowAutoRefuelToggle = true;
}
public override IEnumerable<StatDrawEntry> SpecialDisplayStats(StatRequest req)
{
if (silent)
{
yield break; // If silent, return nothing.
}
foreach (var stat in base.SpecialDisplayStats(req))
{
yield return stat;
}
}
}
[StaticConstructorOnStartup]
public class CompRefuelableNutrition : CompRefuelable, IFuelSource
{
public float currentConsumptionRate = 0f;
public float NutritionStored => Fuel;
public new CompProperties_RefuelableNutrition Props => (CompProperties_RefuelableNutrition)props;
public override void CompTick()
{
// 调用基类的Tick让它处理真空等情况。
// 基类的燃料消耗逻辑将因为 fuelConsumptionRate 为0而无效。
base.CompTick();
// 我们自己的动态消耗逻辑
if (currentConsumptionRate > 0 && HasFuel)
{
float consumptionPerTick = currentConsumptionRate / 60000f;
ConsumeFuel(consumptionPerTick);
}
}
public new void Refuel(List<Thing> fuelThings)
{
float fuelNeeded = TargetFuelLevel - Fuel;
if (fuelNeeded < 0.001f) return;
float totalNutritionGained = 0;
var thingsToProcess = new List<Thing>(fuelThings);
foreach (var thing in thingsToProcess)
{
if (fuelNeeded <= 0) break;
float nutritionPerUnit = thing.GetStatValue(StatDefOf.Nutrition);
if (nutritionPerUnit <= 0) continue;
int numToTake = Mathf.CeilToInt(fuelNeeded / nutritionPerUnit);
numToTake = Mathf.Min(numToTake, thing.stackCount);
float nutritionFromThis = numToTake * nutritionPerUnit;
base.Refuel(nutritionFromThis);
totalNutritionGained += nutritionFromThis;
thing.SplitOff(numToTake).Destroy();
fuelNeeded = TargetFuelLevel - Fuel;
}
// Let the job driver handle the message. This component should only handle logic.
}
public void ReceiveFuel(float amount)
{
base.Refuel(amount);
}
public override string CompInspectStringExtra()
{
string fuelLabel = string.IsNullOrEmpty(Props.FuelLabel) ? "Nutrition" : Props.FuelLabel;
string text = fuelLabel + ": " + Fuel.ToStringDecimalIfSmall() + " / " + Props.fuelCapacity.ToStringDecimalIfSmall();
if (currentConsumptionRate > 0f && HasFuel)
{
int numTicks = (int)(Fuel / (currentConsumptionRate / 60000f));
text += " (" + numTicks.ToStringTicksToPeriod() + ")";
}
else if (!HasFuel && !Props.outOfFuelMessage.NullOrEmpty())
{
text += "\n" + Props.outOfFuelMessage;
}
if (Props.targetFuelLevelConfigurable)
{
text += "\n" + "ConfiguredTargetFuelLevel".Translate(TargetFuelLevel.ToStringDecimalIfSmall());
}
return text;
}
public new void Notify_UsedThisTick()
{
if (Props.consumeFuelOnlyWhenUsed)
{
ConsumeFuel(Props.fuelConsumptionRate / 60000f);
}
}
}
}