zfc
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
using RimWorld;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class CompProperties_QueuedInteractiveProducerWithFlux : CompProperties_QueuedInteractiveProducer
|
||||
{
|
||||
public CompProperties_QueuedInteractiveProducerWithFlux()
|
||||
{
|
||||
compClass = typeof(CompQueuedInteractiveProducerWithFlux);
|
||||
}
|
||||
}
|
||||
|
||||
public class CompQueuedInteractiveProducerWithFlux : CompQueuedInteractiveProducer, IFluxController
|
||||
{
|
||||
// === 通量系统字段 ===
|
||||
private float neutronFlux = 0.5f;
|
||||
private FluxMode fluxMode = FluxMode.Balance;
|
||||
|
||||
// === 接口实现 ===
|
||||
public float NeutronFlux => neutronFlux;
|
||||
public float RawFlux => neutronFlux;
|
||||
public FluxMode CurrentFluxMode => fluxMode;
|
||||
public float FluxEfficiency => IFluxController.GetEfficiency(neutronFlux);
|
||||
public bool IsAutoMode => fluxMode != FluxMode.Manual;
|
||||
public bool IsIncubating => IsAnyOrderActive;
|
||||
public bool IsDormant => neutronFlux < 0.05f;
|
||||
|
||||
public void SetNeutronFlux(float value) => neutronFlux = Mathf.Clamp01(value);
|
||||
public void CycleFluxMode() => fluxMode = (FluxMode)(((int)fluxMode + 1) % 4);
|
||||
|
||||
public string GetModeName() => fluxMode switch {
|
||||
FluxMode.Manual => "手动",
|
||||
FluxMode.Quality => "品质",
|
||||
FluxMode.Balance => "平衡",
|
||||
FluxMode.Speed => "速度",
|
||||
_ => "?"
|
||||
};
|
||||
|
||||
public string GetModeShort() => fluxMode switch {
|
||||
FluxMode.Manual => "M",
|
||||
FluxMode.Quality => "Q",
|
||||
FluxMode.Balance => "B",
|
||||
FluxMode.Speed => "S",
|
||||
_ => "?"
|
||||
};
|
||||
|
||||
private bool IsAnyOrderActive => productionOrders.Any(o => o.productionUntilTick > 0);
|
||||
|
||||
// 覆盖 Tick 逻辑
|
||||
public override void CompTick()
|
||||
{
|
||||
float hasFuelVal = FuelComp?.Fuel ?? 10f;
|
||||
bool hasFuel = hasFuelVal > 0.01f;
|
||||
|
||||
// 自动模式
|
||||
if (IsAutoMode && parent.IsHashIntervalTick(250) && IsAnyOrderActive)
|
||||
{
|
||||
CalculateAutoFlux();
|
||||
}
|
||||
|
||||
if (IsAnyOrderActive)
|
||||
{
|
||||
// 消耗燃料
|
||||
if (FuelComp != null && neutronFlux > 0.01f)
|
||||
{
|
||||
float fuelPerTick = (80f * FluxEfficiency) / 60000f; // 物品孵化池消耗略高
|
||||
FuelComp.ConsumeFuel(fuelPerTick);
|
||||
}
|
||||
|
||||
if (hasFuel)
|
||||
{
|
||||
float ambientTemperature = parent.AmbientTemperature;
|
||||
bool isTempSafe = ambientTemperature >= Props.minSafeTemperature && ambientTemperature <= Props.maxSafeTemperature;
|
||||
|
||||
// 计算通量速度倍率:100%活性时5倍速度
|
||||
float speedFactor = 1f + (FacilitiesComp?.GetStatOffset(StatDef.Named("ARA_IncubationSpeedFactor")) ?? 0f);
|
||||
float fluxSpeed = speedFactor * FluxEfficiency * 5f;
|
||||
|
||||
foreach (var order in productionOrders.Where(o => o.productionUntilTick > 0))
|
||||
{
|
||||
// 1. 进度推进(受通量倍率影响)
|
||||
// 由于基类逻辑是每 Tick 递减,我们这里手动控制递减量
|
||||
float progressStep = fluxSpeed;
|
||||
int ticksToSubtract = Mathf.FloorToInt(progressStep);
|
||||
if (Rand.Value < (progressStep - ticksToSubtract)) ticksToSubtract++;
|
||||
order.productionUntilTick = Mathf.Max(0, order.productionUntilTick - ticksToSubtract);
|
||||
|
||||
// 2. 品质累积(基础:每 Tick 增加 1)
|
||||
// 注意:如果 fluxSpeed > 1,生产变快,但品质累积速度不变,
|
||||
// 这样总的 ticksUnderOptimalConditions 就会减少,从而降低品质分数。
|
||||
// 这完美地实现了“速度越快,品质越低”的平衡逻辑。
|
||||
if (!IsDormant)
|
||||
{
|
||||
if (isTempSafe)
|
||||
{
|
||||
order.ticksUnderOptimalConditions++;
|
||||
}
|
||||
else
|
||||
{
|
||||
float tempDelta = (ambientTemperature > Props.maxSafeTemperature) ? ambientTemperature - Props.maxSafeTemperature : Props.minSafeTemperature - ambientTemperature;
|
||||
order.temperaturePenaltyPercent = Mathf.Min(1f, order.temperaturePenaltyPercent + tempDelta * Props.penaltyPerDegreePerTick);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 休眠状态下品质会缓慢衰减
|
||||
order.ticksUnderOptimalConditions = Mathf.Max(0, order.ticksUnderOptimalConditions - 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理订单完成和消耗率更新(UI用)
|
||||
UpdateLogic();
|
||||
}
|
||||
|
||||
private void UpdateLogic()
|
||||
{
|
||||
// 完成订单
|
||||
productionOrders.RemoveAll(order =>
|
||||
{
|
||||
if (order.productionUntilTick == 0)
|
||||
{
|
||||
FinishProduction(order);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// 启动新订单
|
||||
int currentlyProducingCount = productionOrders.Count(o => o.productionUntilTick > 0);
|
||||
if (currentlyProducingCount < Props.productionQueueLimit)
|
||||
{
|
||||
var waitingOrder = productionOrders.FirstOrDefault(o => o.productionUntilTick == -1);
|
||||
if (waitingOrder != null)
|
||||
{
|
||||
// 初始 Tick 数,会被后续 Tick 动态加速
|
||||
waitingOrder.productionUntilTick = waitingOrder.process.productionTicks;
|
||||
}
|
||||
}
|
||||
|
||||
// 更新燃料消耗率显示
|
||||
if (FuelComp != null)
|
||||
{
|
||||
float totalConsumption = 0f;
|
||||
if (IsAnyOrderActive && NeutronFlux > 0.01f)
|
||||
{
|
||||
totalConsumption = currentlyProducingCount * 80f * FluxEfficiency;
|
||||
}
|
||||
FuelComp.currentConsumptionRate = totalConsumption;
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateAutoFlux()
|
||||
{
|
||||
if (fluxMode == FluxMode.Manual) return;
|
||||
|
||||
float targetFlux = 0.5f;
|
||||
|
||||
// 简单逻辑:平衡模式趋向于 0.5;品质模式倾向于 0.1;速度模式倾向于 1.0
|
||||
switch (fluxMode)
|
||||
{
|
||||
case FluxMode.Speed: targetFlux = 1.0f; break;
|
||||
case FluxMode.Quality: targetFlux = 0.1f; break;
|
||||
case FluxMode.Balance:
|
||||
default: targetFlux = 0.5f; break;
|
||||
}
|
||||
|
||||
// 资源保护
|
||||
if (FuelComp != null && FuelComp.Fuel < 50f) targetFlux = Mathf.Min(targetFlux, 0.2f);
|
||||
|
||||
neutronFlux = Mathf.Lerp(neutronFlux, targetFlux, 0.05f);
|
||||
}
|
||||
|
||||
public override IEnumerable<Gizmo> CompGetGizmosExtra()
|
||||
{
|
||||
foreach (var g in base.CompGetGizmosExtra()) yield return g;
|
||||
if (parent.Faction == Faction.OfPlayer)
|
||||
{
|
||||
yield return new Gizmo_NeutronFlux(this);
|
||||
}
|
||||
}
|
||||
|
||||
public override void PostExposeData()
|
||||
{
|
||||
base.PostExposeData();
|
||||
Scribe_Values.Look(ref neutronFlux, "neutronFlux", 0.5f);
|
||||
Scribe_Values.Look(ref fluxMode, "fluxMode", FluxMode.Balance);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
using RimWorld;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class CompProperties_QueuedPawnSpawnerWithFlux : CompProperties_QueuedPawnSpawner
|
||||
{
|
||||
public CompProperties_QueuedPawnSpawnerWithFlux()
|
||||
{
|
||||
compClass = typeof(CompQueuedPawnSpawnerWithFlux);
|
||||
}
|
||||
}
|
||||
|
||||
public class CompQueuedPawnSpawnerWithFlux : CompQueuedPawnSpawner, IFluxController
|
||||
{
|
||||
// === 通量系统字段 ===
|
||||
private float neutronFlux = 0.5f;
|
||||
private FluxMode fluxMode = FluxMode.Balance;
|
||||
|
||||
// === 接口实现 ===
|
||||
public float NeutronFlux => neutronFlux;
|
||||
public float RawFlux => neutronFlux;
|
||||
public FluxMode CurrentFluxMode => fluxMode;
|
||||
public float FluxEfficiency => IFluxController.GetEfficiency(neutronFlux);
|
||||
public bool IsAutoMode => fluxMode != FluxMode.Manual;
|
||||
public bool IsIncubating => IsAnyOrderActive;
|
||||
public bool IsDormant => neutronFlux < 0.05f;
|
||||
|
||||
public void SetNeutronFlux(float value) => neutronFlux = Mathf.Clamp01(value);
|
||||
public void CycleFluxMode() => fluxMode = (FluxMode)(((int)fluxMode + 1) % 4);
|
||||
|
||||
public string GetModeName() => fluxMode switch {
|
||||
FluxMode.Manual => "手动",
|
||||
FluxMode.Quality => "品质",
|
||||
FluxMode.Balance => "平衡",
|
||||
FluxMode.Speed => "速度",
|
||||
_ => "?"
|
||||
};
|
||||
|
||||
public string GetModeShort() => fluxMode switch {
|
||||
FluxMode.Manual => "M",
|
||||
FluxMode.Quality => "Q",
|
||||
FluxMode.Balance => "B",
|
||||
FluxMode.Speed => "S",
|
||||
_ => "?"
|
||||
};
|
||||
|
||||
// 辅助属性
|
||||
private bool IsAnyOrderActive => productionOrders.Any(o => o.spawnUntilTick > 0);
|
||||
|
||||
// 覆盖 Tick 逻辑以处理通量效果
|
||||
public override void CompTick()
|
||||
{
|
||||
// 注意:我们直接重写逻辑,而不是仅仅调用 base.CompTick,
|
||||
// 这样我们可以更精确地控制进度增加速度。
|
||||
|
||||
bool hasFuel = FuelComp?.HasFuel ?? true;
|
||||
|
||||
// 自动模式调节
|
||||
if (IsAutoMode && parent.IsHashIntervalTick(250) && IsAnyOrderActive)
|
||||
{
|
||||
CalculateAutoFlux();
|
||||
}
|
||||
|
||||
if (IsAnyOrderActive)
|
||||
{
|
||||
// 消耗燃料(基于通量效率)
|
||||
if (FuelComp != null && neutronFlux > 0.01f)
|
||||
{
|
||||
float fuelPerTick = (50f * FluxEfficiency) / 60000f;
|
||||
FuelComp.ConsumeFuel(fuelPerTick);
|
||||
}
|
||||
|
||||
if (!hasFuel)
|
||||
{
|
||||
// 没燃料时进度停滞
|
||||
}
|
||||
else if (IsDormant)
|
||||
{
|
||||
// 休眠逻辑:目前排队组件暂不支持品质损耗,仅停滞
|
||||
}
|
||||
else
|
||||
{
|
||||
// 正常孵化:受通量加速影响
|
||||
float speedFactor = 1f + (FacilitiesComp?.GetStatOffset(StatDef.Named("ARA_IncubationSpeedFactor")) ?? 0f);
|
||||
float fluxSpeed = speedFactor * FluxEfficiency * 5f;
|
||||
|
||||
// 更新所有激活订单的进度
|
||||
// 由于基类逻辑是基于 TickManager.TicksGame 的(spawnUntilTick),
|
||||
// 我们需要手动调整这个目标 Tick 来实现加速。
|
||||
//
|
||||
// 复杂点:基类认为每 Tick 进度 +1。我们要实现每 Tick 进度 +fluxSpeed。
|
||||
// 所以我们每 Tick 实际上让目标 Tick 靠近当前 Tick (fluxSpeed - 1) 个单位。
|
||||
foreach (var order in productionOrders.Where(o => o.spawnUntilTick > 0))
|
||||
{
|
||||
// 计算需要减少的剩余时间量
|
||||
float extraProgress = fluxSpeed - 1f;
|
||||
// 我们通过增加一个随机概率或累积器来处理小数
|
||||
// 这里简单处理:直接修改 spawnUntilTick
|
||||
// (注意:如果 fluxSpeed < 1,spawnUntilTick 会延后)
|
||||
if (extraProgress > 0)
|
||||
{
|
||||
// 实际应该减少的值。如果 fluxSpeed=5,则每 tick 应该减少 5 tick 的等待时间。
|
||||
// 基类自然减少了 1,我们额外减少 4。
|
||||
int extraTicks = Mathf.FloorToInt(extraProgress);
|
||||
if (Rand.Value < (extraProgress - extraTicks)) extraTicks++;
|
||||
order.spawnUntilTick -= extraTicks;
|
||||
}
|
||||
else if (extraProgress < 0)
|
||||
{
|
||||
// 减速逻辑
|
||||
float delayExtra = 1f - fluxSpeed;
|
||||
int delayTicks = Mathf.FloorToInt(delayExtra);
|
||||
if (Rand.Value < (delayExtra - delayTicks)) delayTicks++;
|
||||
order.spawnUntilTick += delayTicks;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理订单完成和启动新订单(逻辑基本同基类,但我们需要确保燃料消耗正常更新)
|
||||
TickProductionLogic();
|
||||
}
|
||||
|
||||
private void TickProductionLogic()
|
||||
{
|
||||
// 完成订单
|
||||
productionOrders.RemoveAll(order =>
|
||||
{
|
||||
if (order.spawnUntilTick > 0 && Find.TickManager.TicksGame >= order.spawnUntilTick)
|
||||
{
|
||||
Pawn pawn = PawnGenerator.GeneratePawn(new PawnGenerationRequest(order.entry.pawnKind, parent.Faction));
|
||||
if (pawn != null) GenPlace.TryPlaceThing(pawn, parent.Position, parent.Map, ThingPlaceMode.Near);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// 启动待办订单
|
||||
int currentlyProducingCount = productionOrders.Count(o => o.spawnUntilTick > 0);
|
||||
if (currentlyProducingCount < Props.productionQueueLimit)
|
||||
{
|
||||
var waitingOrder = productionOrders.FirstOrDefault(o => o.spawnUntilTick == -1);
|
||||
if (waitingOrder != null)
|
||||
{
|
||||
// 初始目标 Tick,之后会在 CompTick 中被通量系统动态调整
|
||||
waitingOrder.spawnUntilTick = Find.TickManager.TicksGame + waitingOrder.entry.delayTicks;
|
||||
}
|
||||
}
|
||||
|
||||
// 更新燃料消耗显示(UI用)
|
||||
if (FuelComp != null)
|
||||
{
|
||||
float totalConsumptionPerDay = 0f;
|
||||
if (IsAnyOrderActive && NeutronFlux > 0.01f)
|
||||
{
|
||||
// 基础:每激活一个槽位在 100% 活性下消耗 50/天?
|
||||
// 或者统一由组件控制
|
||||
totalConsumptionPerDay = currentlyProducingCount * 50f * FluxEfficiency;
|
||||
}
|
||||
FuelComp.currentConsumptionRate = totalConsumptionPerDay;
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateAutoFlux()
|
||||
{
|
||||
if (fluxMode == FluxMode.Manual) return;
|
||||
|
||||
// 排队组件目前主要影响速度。平衡模式下,如果燃料充足,保持中等偏高速度。
|
||||
float targetFlux = 0.5f;
|
||||
|
||||
switch (fluxMode)
|
||||
{
|
||||
case FluxMode.Speed: targetFlux = 1.0f; break;
|
||||
case FluxMode.Quality: targetFlux = 0.2f; break; // 排队组件目前无品质机制,所以此模式意义较小
|
||||
case FluxMode.Balance:
|
||||
default: targetFlux = 0.6f; break;
|
||||
}
|
||||
|
||||
// 资源保护
|
||||
if (FuelComp != null && FuelComp.Fuel < 20f) targetFlux = Mathf.Min(targetFlux, 0.3f);
|
||||
|
||||
neutronFlux = Mathf.Lerp(neutronFlux, targetFlux, 0.05f);
|
||||
}
|
||||
|
||||
public override IEnumerable<Gizmo> CompGetGizmosExtra()
|
||||
{
|
||||
foreach (var g in base.CompGetGizmosExtra()) yield return g;
|
||||
|
||||
if (parent.Faction == Faction.OfPlayer)
|
||||
{
|
||||
// 注意:进度 Gizmo 由 Building 负责显示,
|
||||
// 但如果是通用 Building 挂载此组件,可能需要在此提供。
|
||||
// 鉴于目前是特定 Building 类,我们暂不在此重复,保持现有的逻辑。
|
||||
// 不过,我们需要确保通量控制 Gizmo 可用。
|
||||
yield return new Gizmo_NeutronFlux(this);
|
||||
}
|
||||
}
|
||||
|
||||
public override void PostExposeData()
|
||||
{
|
||||
base.PostExposeData();
|
||||
Scribe_Values.Look(ref neutronFlux, "neutronFlux", 0.5f);
|
||||
Scribe_Values.Look(ref fluxMode, "fluxMode", FluxMode.Balance);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,5 +115,14 @@ namespace ArachnaeSwarm
|
||||
ConsumeFuel(Props.fuelConsumptionRate / 60000f);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ShouldAutoRefuelNow =>
|
||||
allowAutoRefuel && TargetFuelLevel > 0.01f && (Fuel < TargetFuelLevel * 0.75f || Fuel == 0f);
|
||||
|
||||
public override bool ShouldAutoRefuelNowIgnoringFuelPct =>
|
||||
allowAutoRefuel && TargetFuelLevel > 0.01f && Fuel < TargetFuelLevel;
|
||||
|
||||
// 覆盖基类属性,确保 WorkGiver 扫描时拦截
|
||||
public new float TargetFuelLevel => allowAutoRefuel ? base.TargetFuelLevel : 0f;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user