feat: 新增带通量控制、队列孵化和品质系统的督虫生成组件及相关UI。
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -8,18 +8,22 @@ using Verse.AI;
|
|||||||
|
|
||||||
namespace ArachnaeSwarm
|
namespace ArachnaeSwarm
|
||||||
{
|
{
|
||||||
// 带状态和品质的物品订单(通量品质系统)
|
// 带状态和品质的物品订单(与 Building_Ootheca 统一的累计进度模式)
|
||||||
public class QueuedItemOrder : IExposable
|
public class QueuedItemOrder : IExposable
|
||||||
{
|
{
|
||||||
public ProcessDef process;
|
public ProcessDef process;
|
||||||
public string tempThingDefName;
|
public string tempThingDefName;
|
||||||
public OrderStatus status = OrderStatus.WaitingForLarva;
|
public OrderStatus status = OrderStatus.WaitingForLarva;
|
||||||
public int productionUntilTick = -1;
|
|
||||||
|
// 进度系统(累计模式,与 Building_Ootheca 统一)
|
||||||
|
public float incubationProgress = 0f;
|
||||||
|
public float incubationDuration = 0f;
|
||||||
|
|
||||||
// 通量品质系统
|
// 通量品质系统
|
||||||
public float qualityProgress = 0f;
|
public float qualityProgress = 0f;
|
||||||
public float qualityTotal = 0f;
|
public float qualityTotal = 0f;
|
||||||
|
|
||||||
|
public float ProgressPercent => incubationDuration > 0 ? incubationProgress / incubationDuration : 0f;
|
||||||
public float QualityPercent => qualityTotal > 0 ? qualityProgress / qualityTotal : 0f;
|
public float QualityPercent => qualityTotal > 0 ? qualityProgress / qualityTotal : 0f;
|
||||||
|
|
||||||
public void ExposeData()
|
public void ExposeData()
|
||||||
@@ -30,7 +34,8 @@ namespace ArachnaeSwarm
|
|||||||
}
|
}
|
||||||
Scribe_Values.Look(ref tempThingDefName, "thingDefName");
|
Scribe_Values.Look(ref tempThingDefName, "thingDefName");
|
||||||
Scribe_Values.Look(ref status, "status", OrderStatus.WaitingForLarva);
|
Scribe_Values.Look(ref status, "status", OrderStatus.WaitingForLarva);
|
||||||
Scribe_Values.Look(ref productionUntilTick, "productionUntilTick", -1);
|
Scribe_Values.Look(ref incubationProgress, "incubationProgress", 0f);
|
||||||
|
Scribe_Values.Look(ref incubationDuration, "incubationDuration", 0f);
|
||||||
Scribe_Values.Look(ref qualityProgress, "qualityProgress", 0f);
|
Scribe_Values.Look(ref qualityProgress, "qualityProgress", 0f);
|
||||||
Scribe_Values.Look(ref qualityTotal, "qualityTotal", 0f);
|
Scribe_Values.Look(ref qualityTotal, "qualityTotal", 0f);
|
||||||
}
|
}
|
||||||
@@ -159,10 +164,8 @@ namespace ArachnaeSwarm
|
|||||||
|
|
||||||
private float GetProgress(QueuedItemOrder order)
|
private float GetProgress(QueuedItemOrder order)
|
||||||
{
|
{
|
||||||
if (order.status != OrderStatus.Incubating || order.process == null) return 0f;
|
// 使用累计进度模式
|
||||||
int totalTicks = order.process.productionTicks;
|
return order.ProgressPercent;
|
||||||
int elapsed = totalTicks - order.productionUntilTick;
|
|
||||||
return totalTicks > 0 ? Mathf.Clamp01((float)elapsed / totalTicks) : 0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private QualityCategory GetQualityCategory(QueuedItemOrder order)
|
private QualityCategory GetQualityCategory(QueuedItemOrder order)
|
||||||
@@ -253,8 +256,10 @@ namespace ArachnaeSwarm
|
|||||||
if (waitingOrder != null)
|
if (waitingOrder != null)
|
||||||
{
|
{
|
||||||
waitingOrder.status = OrderStatus.Incubating;
|
waitingOrder.status = OrderStatus.Incubating;
|
||||||
waitingOrder.productionUntilTick = waitingOrder.process.productionTicks;
|
// 使用累计进度模式(与 Building_Ootheca 统一)
|
||||||
waitingOrder.qualityTotal = waitingOrder.process.productionTicks;
|
waitingOrder.incubationDuration = waitingOrder.process.productionTicks;
|
||||||
|
waitingOrder.incubationProgress = 0f;
|
||||||
|
waitingOrder.qualityTotal = waitingOrder.incubationDuration;
|
||||||
waitingOrder.qualityProgress = 0f;
|
waitingOrder.qualityProgress = 0f;
|
||||||
}
|
}
|
||||||
assignedLarvae.Remove(larva);
|
assignedLarvae.Remove(larva);
|
||||||
@@ -286,50 +291,43 @@ namespace ArachnaeSwarm
|
|||||||
CalculateAutoFlux();
|
CalculateAutoFlux();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 消耗燃料
|
// 消耗燃料(只有活性>0时)
|
||||||
if (IsIncubating && FuelComp != null && neutronFlux > 0.01f)
|
if (IsIncubating && FuelComp != null && neutronFlux > 0.01f)
|
||||||
{
|
{
|
||||||
float fuelPerTick = (80f * FluxEfficiency * IncubatingCount) / 60000f;
|
float fuelPerTick = (80f * FluxEfficiency * IncubatingCount) / 60000f;
|
||||||
FuelComp.ConsumeFuel(fuelPerTick);
|
FuelComp.ConsumeFuel(fuelPerTick);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理正在生产的订单
|
// 进度和品质处理(与 Building_Ootheca 统一)
|
||||||
if (hasFuel && !IsDormant)
|
foreach (var order in orders.Where(o => o.status == OrderStatus.Incubating))
|
||||||
{
|
{
|
||||||
|
if (IsDormant)
|
||||||
|
{
|
||||||
|
// 休眠时:不推进进度,品质衰减
|
||||||
|
float qualityDecay = (order.qualityTotal * 0.1f) / 60000f;
|
||||||
|
order.qualityProgress = Mathf.Max(0f, order.qualityProgress - qualityDecay);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 正常工作:推进进度和品质
|
||||||
float speedFactor = 1f + (FacilitiesComp?.GetStatOffset(StatDef.Named("ARA_IncubationSpeedFactor")) ?? 0f);
|
float speedFactor = 1f + (FacilitiesComp?.GetStatOffset(StatDef.Named("ARA_IncubationSpeedFactor")) ?? 0f);
|
||||||
float fluxSpeed = speedFactor * FluxEfficiency * 5f;
|
float fluxSpeed = speedFactor * FluxEfficiency * 5f;
|
||||||
|
|
||||||
foreach (var order in orders.Where(o => o.status == OrderStatus.Incubating && o.productionUntilTick > 0))
|
// 进度推进(累计模式)
|
||||||
{
|
order.incubationProgress += fluxSpeed;
|
||||||
// 进度推进
|
|
||||||
float extraProgress = fluxSpeed - 1f;
|
|
||||||
if (extraProgress > 0)
|
|
||||||
{
|
|
||||||
int extraTicks = Mathf.FloorToInt(extraProgress);
|
|
||||||
if (Rand.Value < (extraProgress - extraTicks)) extraTicks++;
|
|
||||||
order.productionUntilTick = Mathf.Max(0, order.productionUntilTick - extraTicks);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 通量品质系统:低通量时品质增长快
|
// 品质增长 - 低活性时品质增长更快
|
||||||
float qualityBonus = 1f + (1f - neutronFlux) * 0.5f;
|
float qualityBonus = 1f + (1f - neutronFlux) * 0.5f;
|
||||||
float qualityGain = speedFactor * qualityBonus;
|
float qualityGain = speedFactor * qualityBonus;
|
||||||
order.qualityProgress = Mathf.Min(order.qualityProgress + qualityGain, order.qualityTotal);
|
order.qualityProgress = Mathf.Min(order.qualityProgress + qualityGain, order.qualityTotal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (IsDormant)
|
|
||||||
{
|
|
||||||
// 休眠时品质下降
|
|
||||||
foreach (var order in orders.Where(o => o.status == OrderStatus.Incubating))
|
|
||||||
{
|
|
||||||
float qualityDecay = (order.qualityTotal * 0.1f) / 60000f;
|
|
||||||
order.qualityProgress = Mathf.Max(0f, order.qualityProgress - qualityDecay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 完成订单
|
// 完成检查(进度达到持续时间时完成)
|
||||||
orders.RemoveAll(order =>
|
orders.RemoveAll(order =>
|
||||||
{
|
{
|
||||||
if (order.status == OrderStatus.Incubating && order.productionUntilTick == 0)
|
if (order.status == OrderStatus.Incubating &&
|
||||||
|
order.incubationProgress >= order.incubationDuration)
|
||||||
{
|
{
|
||||||
FinishProduction(order);
|
FinishProduction(order);
|
||||||
return true;
|
return true;
|
||||||
@@ -447,17 +445,23 @@ namespace ArachnaeSwarm
|
|||||||
var options = new List<FloatMenuOption>();
|
var options = new List<FloatMenuOption>();
|
||||||
foreach (var process in Processes)
|
foreach (var process in Processes)
|
||||||
{
|
{
|
||||||
|
Texture2D icon = process.thingDef?.uiIcon;
|
||||||
|
string label = process.thingDef.LabelCap;
|
||||||
|
|
||||||
if (process.requiredResearch != null && !process.requiredResearch.IsFinished)
|
if (process.requiredResearch != null && !process.requiredResearch.IsFinished)
|
||||||
{
|
{
|
||||||
options.Add(new FloatMenuOption(process.thingDef.LabelCap + " (需要研究: " + process.requiredResearch.LabelCap + ")", null));
|
label += $" (需要研究: {process.requiredResearch.LabelCap})";
|
||||||
|
options.Add(new FloatMenuOption(label, null, icon, Color.white));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var capturedProcess = process;
|
var capturedProcess = process;
|
||||||
options.Add(new FloatMenuOption(process.thingDef.LabelCap, () => {
|
float days = capturedProcess.productionTicks / 60000f;
|
||||||
|
label += $" ({days:F1}天)";
|
||||||
|
options.Add(new FloatMenuOption(label, () => {
|
||||||
AddOrder(capturedProcess);
|
AddOrder(capturedProcess);
|
||||||
if (orders.Count < Props.productionQueueLimit) ShowOrderMenu();
|
if (orders.Count < Props.productionQueueLimit) ShowOrderMenu();
|
||||||
}));
|
}, icon, Color.white));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,21 +28,26 @@ namespace ArachnaeSwarm
|
|||||||
// 带状态和品质的督虫订单
|
// 带状态和品质的督虫订单
|
||||||
public class QueuedPawnOrder : IExposable
|
public class QueuedPawnOrder : IExposable
|
||||||
{
|
{
|
||||||
public IncubationConfig config; // 使用 IncubationConfig 而不是 QueuedPawnSpawnEntry
|
public IncubationConfig config;
|
||||||
public OrderStatus status = OrderStatus.WaitingForLarva;
|
public OrderStatus status = OrderStatus.WaitingForLarva;
|
||||||
public int spawnUntilTick = -1;
|
|
||||||
|
// 进度系统(与 Building_Ootheca 统一)
|
||||||
|
public float incubationProgress = 0f;
|
||||||
|
public float incubationDuration = 0f;
|
||||||
|
|
||||||
// 品质系统
|
// 品质系统
|
||||||
public float qualityProgress = 0f;
|
public float qualityProgress = 0f;
|
||||||
public float qualityTotal = 0f;
|
public float qualityTotal = 0f;
|
||||||
|
|
||||||
|
public float ProgressPercent => incubationDuration > 0 ? incubationProgress / incubationDuration : 0f;
|
||||||
public float QualityPercent => qualityTotal > 0 ? qualityProgress / qualityTotal : 0f;
|
public float QualityPercent => qualityTotal > 0 ? qualityProgress / qualityTotal : 0f;
|
||||||
|
|
||||||
public void ExposeData()
|
public void ExposeData()
|
||||||
{
|
{
|
||||||
Scribe_Deep.Look(ref config, "config");
|
Scribe_Deep.Look(ref config, "config");
|
||||||
Scribe_Values.Look(ref status, "status", OrderStatus.WaitingForLarva);
|
Scribe_Values.Look(ref status, "status", OrderStatus.WaitingForLarva);
|
||||||
Scribe_Values.Look(ref spawnUntilTick, "spawnUntilTick", -1);
|
Scribe_Values.Look(ref incubationProgress, "incubationProgress", 0f);
|
||||||
|
Scribe_Values.Look(ref incubationDuration, "incubationDuration", 0f);
|
||||||
Scribe_Values.Look(ref qualityProgress, "qualityProgress", 0f);
|
Scribe_Values.Look(ref qualityProgress, "qualityProgress", 0f);
|
||||||
Scribe_Values.Look(ref qualityTotal, "qualityTotal", 0f);
|
Scribe_Values.Look(ref qualityTotal, "qualityTotal", 0f);
|
||||||
}
|
}
|
||||||
@@ -154,8 +159,8 @@ namespace ArachnaeSwarm
|
|||||||
status = order.status,
|
status = order.status,
|
||||||
progress = prodProgress,
|
progress = prodProgress,
|
||||||
qualityProgress = order.QualityPercent,
|
qualityProgress = order.QualityPercent,
|
||||||
remainingTime = order.status == OrderStatus.Incubating && order.spawnUntilTick > 0
|
remainingTime = order.status == OrderStatus.Incubating
|
||||||
? (order.spawnUntilTick - Find.TickManager.TicksGame).ToStringTicksToPeriod()
|
? ((int)GetRemainingTicks(order)).ToStringTicksToPeriod()
|
||||||
: "等待中",
|
: "等待中",
|
||||||
estimatedQuality = GetEstimatedQuality(order.QualityPercent)
|
estimatedQuality = GetEstimatedQuality(order.QualityPercent)
|
||||||
});
|
});
|
||||||
@@ -165,11 +170,17 @@ namespace ArachnaeSwarm
|
|||||||
|
|
||||||
private float GetProgress(QueuedPawnOrder order)
|
private float GetProgress(QueuedPawnOrder order)
|
||||||
{
|
{
|
||||||
if (order.status != OrderStatus.Incubating || order.spawnUntilTick <= 0 || order.config == null) return 0f;
|
// 使用累计进度模式
|
||||||
int totalTicks = Mathf.RoundToInt(order.config.daysRequired * 60000);
|
return order.ProgressPercent;
|
||||||
int startTick = order.spawnUntilTick - totalTicks;
|
}
|
||||||
int elapsed = Find.TickManager.TicksGame - startTick;
|
|
||||||
return totalTicks > 0 ? Mathf.Clamp01((float)elapsed / totalTicks) : 0f;
|
private float GetRemainingTicks(QueuedPawnOrder order)
|
||||||
|
{
|
||||||
|
if (order.status != OrderStatus.Incubating || order.incubationDuration <= 0) return 0f;
|
||||||
|
float remaining = order.incubationDuration - order.incubationProgress;
|
||||||
|
float speedFactor = 1f + (FacilitiesComp?.GetStatOffset(StatDef.Named("ARA_IncubationSpeedFactor")) ?? 0f);
|
||||||
|
float fluxSpeed = speedFactor * FluxEfficiency * 5f;
|
||||||
|
return fluxSpeed > 0 ? remaining / fluxSpeed : remaining;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetEstimatedQuality(float qualityPercent)
|
private string GetEstimatedQuality(float qualityPercent)
|
||||||
@@ -260,9 +271,10 @@ namespace ArachnaeSwarm
|
|||||||
if (waitingOrder != null && waitingOrder.config != null)
|
if (waitingOrder != null && waitingOrder.config != null)
|
||||||
{
|
{
|
||||||
waitingOrder.status = OrderStatus.Incubating;
|
waitingOrder.status = OrderStatus.Incubating;
|
||||||
int totalTicks = Mathf.RoundToInt(waitingOrder.config.daysRequired * 60000);
|
// 使用累计进度模式(与 Building_Ootheca 统一)
|
||||||
waitingOrder.spawnUntilTick = Find.TickManager.TicksGame + totalTicks;
|
waitingOrder.incubationDuration = waitingOrder.config.daysRequired * 60000f;
|
||||||
waitingOrder.qualityTotal = totalTicks;
|
waitingOrder.incubationProgress = 0f;
|
||||||
|
waitingOrder.qualityTotal = waitingOrder.incubationDuration;
|
||||||
waitingOrder.qualityProgress = 0f;
|
waitingOrder.qualityProgress = 0f;
|
||||||
}
|
}
|
||||||
assignedLarvae.Remove(larva);
|
assignedLarvae.Remove(larva);
|
||||||
@@ -293,38 +305,43 @@ namespace ArachnaeSwarm
|
|||||||
CalculateAutoFlux();
|
CalculateAutoFlux();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 消耗燃料(只有活性>0时)
|
||||||
if (IsIncubating && FuelComp != null && neutronFlux > 0.01f)
|
if (IsIncubating && FuelComp != null && neutronFlux > 0.01f)
|
||||||
{
|
{
|
||||||
float fuelPerTick = (50f * FluxEfficiency * IncubatingCount) / 60000f;
|
float fuelPerTick = (50f * FluxEfficiency * IncubatingCount) / 60000f;
|
||||||
FuelComp.ConsumeFuel(fuelPerTick);
|
FuelComp.ConsumeFuel(fuelPerTick);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasFuel && !IsDormant)
|
// 进度和品质处理(与 Building_Ootheca 统一)
|
||||||
|
foreach (var order in orders.Where(o => o.status == OrderStatus.Incubating))
|
||||||
{
|
{
|
||||||
|
if (IsDormant)
|
||||||
|
{
|
||||||
|
// 休眠时:不推进进度,品质衰减
|
||||||
|
float qualityDecay = (order.qualityTotal * 0.1f) / 60000f;
|
||||||
|
order.qualityProgress = Mathf.Max(0f, order.qualityProgress - qualityDecay);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 正常工作:推进进度和品质
|
||||||
float speedFactor = 1f + (FacilitiesComp?.GetStatOffset(StatDef.Named("ARA_IncubationSpeedFactor")) ?? 0f);
|
float speedFactor = 1f + (FacilitiesComp?.GetStatOffset(StatDef.Named("ARA_IncubationSpeedFactor")) ?? 0f);
|
||||||
float fluxSpeed = speedFactor * FluxEfficiency * 5f;
|
float fluxSpeed = speedFactor * FluxEfficiency * 5f;
|
||||||
|
|
||||||
foreach (var order in orders.Where(o => o.status == OrderStatus.Incubating))
|
// 进度推进(累计模式)
|
||||||
{
|
order.incubationProgress += fluxSpeed;
|
||||||
float extraProgress = fluxSpeed - 1f;
|
|
||||||
if (extraProgress > 0)
|
|
||||||
{
|
|
||||||
int extraTicks = Mathf.FloorToInt(extraProgress);
|
|
||||||
if (Rand.Value < (extraProgress - extraTicks)) extraTicks++;
|
|
||||||
order.spawnUntilTick -= extraTicks;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// 品质增长 - 低活性时品质增长更快
|
||||||
float qualityBonus = 1f + (1f - neutronFlux) * 0.5f;
|
float qualityBonus = 1f + (1f - neutronFlux) * 0.5f;
|
||||||
float qualityGain = speedFactor * qualityBonus;
|
float qualityGain = speedFactor * qualityBonus;
|
||||||
order.qualityProgress = Mathf.Min(order.qualityProgress + qualityGain, order.qualityTotal);
|
order.qualityProgress = Mathf.Min(order.qualityProgress + qualityGain, order.qualityTotal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 完成检查(进度达到持续时间时完成)
|
||||||
orders.RemoveAll(order =>
|
orders.RemoveAll(order =>
|
||||||
{
|
{
|
||||||
if (order.status == OrderStatus.Incubating &&
|
if (order.status == OrderStatus.Incubating &&
|
||||||
order.spawnUntilTick > 0 &&
|
order.incubationProgress >= order.incubationDuration)
|
||||||
Find.TickManager.TicksGame >= order.spawnUntilTick)
|
|
||||||
{
|
{
|
||||||
CompleteOrder(order);
|
CompleteOrder(order);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
using RimWorld;
|
using RimWorld;
|
||||||
using Verse;
|
using Verse;
|
||||||
using Verse.Sound; // Ensure this is present
|
using Verse.Sound;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace ArachnaeSwarm
|
namespace ArachnaeSwarm
|
||||||
{
|
{
|
||||||
@@ -73,5 +74,35 @@ namespace ArachnaeSwarm
|
|||||||
!(gizmo is Designator_Build designator && designator.PlacingDef == ThingDefOf.Hopper)
|
!(gizmo is Designator_Build designator && designator.PlacingDef == ThingDefOf.Hopper)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 覆盖 GetInspectString 以隐藏电力和进料口相关的提示
|
||||||
|
public override string GetInspectString()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
// 只显示燃料信息,不显示电力相关信息
|
||||||
|
if (nutritionComp != null && dispenserProps != null)
|
||||||
|
{
|
||||||
|
float fuel = nutritionComp.Fuel;
|
||||||
|
float cost = dispenserProps.nutritionCostPerDispense;
|
||||||
|
int mealsAvailable = (int)(fuel / cost);
|
||||||
|
sb.AppendLine($"可制作: {mealsAvailable} 份");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加其他 Comp 的信息,但排除 CompPower 类型
|
||||||
|
foreach (var comp in AllComps)
|
||||||
|
{
|
||||||
|
// 跳过电力相关的组件
|
||||||
|
if (comp is CompPower) continue;
|
||||||
|
|
||||||
|
string compString = comp.CompInspectStringExtra();
|
||||||
|
if (!compString.NullOrEmpty())
|
||||||
|
{
|
||||||
|
sb.AppendLine(compString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString().TrimEndNewlines();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
using RimWorld;
|
using RimWorld;
|
||||||
using Verse;
|
using Verse;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace ArachnaeSwarm
|
namespace ArachnaeSwarm
|
||||||
{
|
{
|
||||||
@@ -167,4 +168,20 @@ namespace ArachnaeSwarm
|
|||||||
return bestDispenser;
|
return bestDispenser;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Patch to exclude our custom dispenser from the "needs hopper" alert.
|
||||||
|
/// The Alert checks all ThingsInGroup(ThingRequestGroup.FoodDispenser) and warns if they don't have adjacent hoppers.
|
||||||
|
/// We filter out our custom dispenser from the result.
|
||||||
|
/// </summary>
|
||||||
|
[HarmonyPatch(typeof(Alert_PasteDispenserNeedsHopper), "BadDispensers", MethodType.Getter)]
|
||||||
|
public static class Patch_AlertPasteDispenserNeedsHopper
|
||||||
|
{
|
||||||
|
[HarmonyPostfix]
|
||||||
|
public static void Postfix(ref List<Thing> __result)
|
||||||
|
{
|
||||||
|
// Remove all instances of our custom dispenser from the "bad" list
|
||||||
|
__result.RemoveAll(t => t is Building_ARANutrientDispenser);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -60,7 +60,7 @@ namespace ArachnaeSwarm
|
|||||||
else if (config != null)
|
else if (config != null)
|
||||||
title = config.thingDef.LabelCap;
|
title = config.thingDef.LabelCap;
|
||||||
else
|
else
|
||||||
title = "选择孵化目标...";
|
title = "选择生产目标...";
|
||||||
|
|
||||||
// 标题按钮(只有非孵化状态可点击)
|
// 标题按钮(只有非孵化状态可点击)
|
||||||
bool canSwitch = !isIncubating && !hasLarva && building.EquipmentIncubatorData?.IncubationConfigs?.Count > 0;
|
bool canSwitch = !isIncubating && !hasLarva && building.EquipmentIncubatorData?.IncubationConfigs?.Count > 0;
|
||||||
@@ -225,12 +225,8 @@ namespace ArachnaeSwarm
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
sb.AppendLine("【未选择目标】");
|
sb.AppendLine("【未选择目标】");
|
||||||
sb.AppendLine("点击上方标题选择孵化目标");
|
sb.AppendLine("点击上方标题选择生产目标");
|
||||||
}
|
}
|
||||||
|
|
||||||
sb.AppendLine();
|
|
||||||
sb.AppendLine("当前速度加成: " + building.SpeedMultiplier.ToStringPercent());
|
|
||||||
sb.AppendLine("当前质量加成: " + building.QualityMultiplier.ToStringPercent());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.ToString().TrimEndNewlines();
|
return sb.ToString().TrimEndNewlines();
|
||||||
|
|||||||
@@ -94,15 +94,27 @@ namespace ArachnaeSwarm
|
|||||||
// === 订单列表 ===
|
// === 订单列表 ===
|
||||||
if (orderCount > 0)
|
if (orderCount > 0)
|
||||||
{
|
{
|
||||||
float listHeight = Mathf.Min(visibleCount, orderCount) * (BarHeight + Spacing + 14f);
|
float itemHeight = BarHeight + Spacing + 14f;
|
||||||
Rect listRect = new Rect(innerRect.x, curY, innerRect.width, listHeight);
|
float listHeight = Mathf.Min(visibleCount, orderCount) * itemHeight;
|
||||||
|
float totalContentHeight = orderCount * itemHeight;
|
||||||
|
bool needsScrollbar = orderCount > MaxVisibleOrders;
|
||||||
|
|
||||||
if (orderCount > MaxVisibleOrders && Mouse.IsOver(listRect))
|
float scrollbarWidth = needsScrollbar ? 12f : 0f;
|
||||||
|
Rect listRect = new Rect(innerRect.x, curY, innerRect.width - scrollbarWidth, listHeight);
|
||||||
|
|
||||||
|
// 滚动条
|
||||||
|
if (needsScrollbar)
|
||||||
{
|
{
|
||||||
float scrollMax = (orderCount - MaxVisibleOrders) * (BarHeight + Spacing + 14f);
|
Rect scrollbarRect = new Rect(innerRect.xMax - scrollbarWidth, curY, scrollbarWidth, listHeight);
|
||||||
scrollPosition -= Event.current.delta.y * 0.5f;
|
float scrollMax = totalContentHeight - listHeight;
|
||||||
|
scrollPosition = GUI.VerticalScrollbar(scrollbarRect, scrollPosition, listHeight, 0f, totalContentHeight);
|
||||||
|
|
||||||
|
if (Mouse.IsOver(listRect))
|
||||||
|
{
|
||||||
|
scrollPosition -= Event.current.delta.y * 1.5f;
|
||||||
scrollPosition = Mathf.Clamp(scrollPosition, 0f, scrollMax);
|
scrollPosition = Mathf.Clamp(scrollPosition, 0f, scrollMax);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GUI.BeginClip(listRect);
|
GUI.BeginClip(listRect);
|
||||||
float drawY = -scrollPosition;
|
float drawY = -scrollPosition;
|
||||||
@@ -110,14 +122,13 @@ namespace ArachnaeSwarm
|
|||||||
for (int i = 0; i < orderCount; i++)
|
for (int i = 0; i < orderCount; i++)
|
||||||
{
|
{
|
||||||
var order = orders[i];
|
var order = orders[i];
|
||||||
float itemHeight = BarHeight + 14f;
|
Rect itemRect = new Rect(0, drawY, listRect.width, itemHeight - Spacing);
|
||||||
Rect itemRect = new Rect(0, drawY, listRect.width, itemHeight);
|
|
||||||
|
|
||||||
if (itemRect.yMax > 0 && itemRect.y < listRect.height)
|
if (itemRect.yMax > 0 && itemRect.y < listRect.height)
|
||||||
{
|
{
|
||||||
DrawOrderItem(itemRect, order, i);
|
DrawOrderItem(itemRect, order, i);
|
||||||
}
|
}
|
||||||
drawY += itemHeight + Spacing;
|
drawY += itemHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
GUI.EndClip();
|
GUI.EndClip();
|
||||||
|
|||||||
@@ -224,10 +224,6 @@ namespace ArachnaeSwarm
|
|||||||
sb.AppendLine("【未选择目标】");
|
sb.AppendLine("【未选择目标】");
|
||||||
sb.AppendLine("点击上方标题选择孵化目标");
|
sb.AppendLine("点击上方标题选择孵化目标");
|
||||||
}
|
}
|
||||||
|
|
||||||
sb.AppendLine();
|
|
||||||
sb.AppendLine("当前速度加成: " + ootheca.SpeedMultiplier.ToStringPercent());
|
|
||||||
sb.AppendLine("当前质量加成: " + ootheca.QualityMultiplier.ToStringPercent());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.ToString().TrimEndNewlines();
|
return sb.ToString().TrimEndNewlines();
|
||||||
|
|||||||
@@ -97,16 +97,29 @@ namespace ArachnaeSwarm
|
|||||||
// === 订单列表 ===
|
// === 订单列表 ===
|
||||||
if (orderCount > 0)
|
if (orderCount > 0)
|
||||||
{
|
{
|
||||||
float listHeight = Mathf.Min(visibleCount, orderCount) * (BarHeight + Spacing + 14f);
|
float itemHeight = BarHeight + Spacing + 14f;
|
||||||
Rect listRect = new Rect(innerRect.x, curY, innerRect.width, listHeight);
|
float listHeight = Mathf.Min(visibleCount, orderCount) * itemHeight;
|
||||||
|
float totalContentHeight = orderCount * itemHeight;
|
||||||
|
bool needsScrollbar = orderCount > MaxVisibleOrders;
|
||||||
|
|
||||||
// 滚动支持
|
float scrollbarWidth = needsScrollbar ? 12f : 0f;
|
||||||
if (orderCount > MaxVisibleOrders && Mouse.IsOver(listRect))
|
Rect listRect = new Rect(innerRect.x, curY, innerRect.width - scrollbarWidth, listHeight);
|
||||||
|
Rect viewRect = new Rect(0, 0, listRect.width, totalContentHeight);
|
||||||
|
|
||||||
|
// 滚动条区域
|
||||||
|
if (needsScrollbar)
|
||||||
{
|
{
|
||||||
float scrollMax = (orderCount - MaxVisibleOrders) * (BarHeight + Spacing + 14f);
|
Rect scrollbarRect = new Rect(innerRect.xMax - scrollbarWidth, curY, scrollbarWidth, listHeight);
|
||||||
scrollPosition -= Event.current.delta.y * 0.5f;
|
float scrollMax = totalContentHeight - listHeight;
|
||||||
|
scrollPosition = GUI.VerticalScrollbar(scrollbarRect, scrollPosition, listHeight, 0f, totalContentHeight);
|
||||||
|
|
||||||
|
// 也支持滚轮
|
||||||
|
if (Mouse.IsOver(listRect))
|
||||||
|
{
|
||||||
|
scrollPosition -= Event.current.delta.y * 1.5f;
|
||||||
scrollPosition = Mathf.Clamp(scrollPosition, 0f, scrollMax);
|
scrollPosition = Mathf.Clamp(scrollPosition, 0f, scrollMax);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GUI.BeginClip(listRect);
|
GUI.BeginClip(listRect);
|
||||||
float drawY = -scrollPosition;
|
float drawY = -scrollPosition;
|
||||||
@@ -114,14 +127,13 @@ namespace ArachnaeSwarm
|
|||||||
for (int i = 0; i < orderCount; i++)
|
for (int i = 0; i < orderCount; i++)
|
||||||
{
|
{
|
||||||
var order = orders[i];
|
var order = orders[i];
|
||||||
float itemHeight = BarHeight + 14f;
|
Rect itemRect = new Rect(0, drawY, listRect.width, itemHeight - Spacing);
|
||||||
Rect itemRect = new Rect(0, drawY, listRect.width, itemHeight);
|
|
||||||
|
|
||||||
if (itemRect.yMax > 0 && itemRect.y < listRect.height)
|
if (itemRect.yMax > 0 && itemRect.y < listRect.height)
|
||||||
{
|
{
|
||||||
DrawOrderItem(itemRect, order, i);
|
DrawOrderItem(itemRect, order, i);
|
||||||
}
|
}
|
||||||
drawY += itemHeight + Spacing;
|
drawY += itemHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
GUI.EndClip();
|
GUI.EndClip();
|
||||||
|
|||||||
Reference in New Issue
Block a user