105 lines
4.0 KiB
C#
105 lines
4.0 KiB
C#
using RimWorld;
|
|
using Verse;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
using System.Text;
|
|
|
|
namespace ArachnaeSwarm
|
|
{
|
|
public class CompNutrientProvider : CompFacility
|
|
{
|
|
private CompRefuelableNutrition selfRefuelable;
|
|
|
|
public override void PostSpawnSetup(bool respawningAfterLoad)
|
|
{
|
|
base.PostSpawnSetup(respawningAfterLoad);
|
|
selfRefuelable = parent.GetComp<CompRefuelableNutrition>();
|
|
}
|
|
|
|
public override string CompInspectStringExtra()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
float efficiency = Mathf.Clamp(parent.GetStatValue(StatDef.Named("NutrientTransmissionEfficiency")), 0f, 0.1f);
|
|
sb.AppendLine("生物质传输效率".Translate() + ": " + efficiency.ToStringPercent());
|
|
|
|
sb.AppendLine("链接的建筑".Translate() + ":");
|
|
|
|
if (LinkedBuildings.NullOrEmpty())
|
|
{
|
|
sb.AppendLine(" (" + "None".Translate() + ")");
|
|
}
|
|
else
|
|
{
|
|
foreach (var building in LinkedBuildings)
|
|
{
|
|
var comp = (building as ThingWithComps)?.GetComp<CompRefuelableNutrition>();
|
|
if (comp != null)
|
|
{
|
|
bool needsFuel = NeedsFuel(comp);
|
|
sb.AppendLine($" - {building.LabelCap}: {comp.Fuel:F0}/{comp.Props.fuelCapacity:F0} (目标: {comp.TargetFuelLevel:F0}) -> {(needsFuel ? "需要" : "不需要")}");
|
|
}
|
|
}
|
|
}
|
|
|
|
return sb.ToString().TrimEnd();
|
|
}
|
|
|
|
public override void CompTick()
|
|
{
|
|
base.CompTick();
|
|
// Log.Message($"[NutrientProvider] CompTick called for {parent.Label}."); // This will be too spammy
|
|
|
|
if (!parent.IsHashIntervalTick(250))
|
|
{
|
|
return;
|
|
}
|
|
|
|
Log.Message($"[NutrientProvider] Rare Tick Logic executing for {parent.Label}.");
|
|
|
|
if (selfRefuelable == null || !selfRefuelable.HasFuel)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var targetBuilding = LinkedBuildings
|
|
.Select(b => new { Building = b, Comp = (b as ThingWithComps)?.GetComp<CompRefuelableNutrition>() })
|
|
.Where(x => x.Comp != null && NeedsFuel(x.Comp))
|
|
.OrderBy(x => x.Comp.Fuel / x.Comp.Props.fuelCapacity)
|
|
.FirstOrDefault();
|
|
|
|
if (targetBuilding != null)
|
|
{
|
|
var consumerComp = targetBuilding.Comp;
|
|
float desiredLevel = GetDesiredFuelLevel(consumerComp);
|
|
float fuelNeeded = desiredLevel - consumerComp.Fuel;
|
|
float fuelToTransfer = Mathf.Min(fuelNeeded, selfRefuelable.Fuel);
|
|
|
|
float efficiency = Mathf.Clamp(parent.GetStatValue(StatDef.Named("NutrientTransmissionEfficiency")), 0f, 0.1f);
|
|
float finalCost = fuelToTransfer * (1 - efficiency);
|
|
|
|
Log.Message($"[NutrientProvider] Found target: {targetBuilding.Building.Label}. Fuel: {consumerComp.Fuel:F0}/{consumerComp.Props.fuelCapacity:F0}. Needs: {fuelNeeded:F2}. Transferring: {fuelToTransfer:F2}. Final cost: {finalCost:F2}");
|
|
|
|
selfRefuelable.ConsumeFuel(finalCost);
|
|
consumerComp.ReceiveFuel(fuelToTransfer);
|
|
}
|
|
}
|
|
|
|
private bool NeedsFuel(CompRefuelableNutrition comp)
|
|
{
|
|
if (comp == null) return false;
|
|
return comp.Fuel < GetDesiredFuelLevel(comp);
|
|
}
|
|
|
|
private float GetDesiredFuelLevel(CompRefuelableNutrition comp)
|
|
{
|
|
// If target is 0 (initial default) or max (UI default), treat as "fill to full".
|
|
if (comp.TargetFuelLevel <= 0.01f || comp.TargetFuelLevel >= comp.Props.fuelCapacity * 0.99f)
|
|
{
|
|
return comp.Props.fuelCapacity;
|
|
}
|
|
// Otherwise, respect the player's custom setting.
|
|
return comp.TargetFuelLevel;
|
|
}
|
|
}
|
|
} |