diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll
index 73c3c33..b0df8b6 100644
Binary files a/1.6/1.6/Assemblies/ArachnaeSwarm.dll and b/1.6/1.6/Assemblies/ArachnaeSwarm.dll differ
diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.pdb b/1.6/1.6/Assemblies/ArachnaeSwarm.pdb
new file mode 100644
index 0000000..5fd76ef
Binary files /dev/null and b/1.6/1.6/Assemblies/ArachnaeSwarm.pdb differ
diff --git a/1.6/1.6/Defs/Thing_building/ARA_Ootheca.xml b/1.6/1.6/Defs/Thing_building/ARA_Ootheca.xml
index 7a93ebf..8e599b4 100644
--- a/1.6/1.6/Defs/Thing_building/ARA_Ootheca.xml
+++ b/1.6/1.6/Defs/Thing_building/ARA_Ootheca.xml
@@ -145,10 +145,7 @@
-
-
- ArachnaeSwarm.ITab_Ootheca_Incubation
-
+
25
diff --git a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
index 2301366..f073ec6 100644
--- a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
+++ b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
@@ -28,7 +28,7 @@
pdbonly
true
- bin\Release\
+ ..\..\1.6\1.6\Assemblies\
TRACE
prompt
4
@@ -123,7 +123,7 @@
-
+
diff --git a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Building_Ootheca.cs b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Building_Ootheca.cs
index 2acbaa6..821d7fb 100644
--- a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Building_Ootheca.cs
+++ b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Building_Ootheca.cs
@@ -333,73 +333,65 @@ namespace ArachnaeSwarm
Destroy();
}
- // 显示额外信息(简化版本,只显示速率,不显示因子)
- public override string GetInspectString()
+ // 显示额外信息(方案A:孵化信息在前,维护信息在后)
+public override string GetInspectString()
+{
+ var builder = new StringBuilder();
+
+ // === 第一部分:孵化状态 ===
+ if (isIncubating && incubatingPawnKind != null)
+ {
+ float progressPercent = AdjustedProgressPercent;
+ float daysRemaining = GetRemainingDays();
+ float hoursRemaining = GetRemainingHours();
+
+ builder.AppendLine("正在孵化: " + incubatingPawnKind.LabelCap);
+ builder.AppendLine("进度: " + progressPercent.ToStringPercent());
+
+ // 显示剩余时间
+ string timeText = "剩余时间: " + daysRemaining.ToString("F1") + " 天";
+ if (hoursRemaining > 0.1f && daysRemaining < 1f)
{
- var baseString = base.GetInspectString();
- var builder = new StringBuilder();
-
- if (!string.IsNullOrEmpty(baseString))
- {
- builder.Append(baseString);
- }
-
- if (isIncubating && incubatingPawnKind != null)
- {
- float progressPercent = AdjustedProgressPercent;
- float daysRemaining = GetRemainingDays();
- float hoursRemaining = GetRemainingHours();
-
- if (builder.Length > 0) builder.AppendLine();
- builder.Append("ARA_OothecaIncubator.Incubating".Translate() + ": " + incubatingPawnKind.LabelCap);
- builder.AppendLine();
- builder.Append("ARA_OothecaIncubator.Progress".Translate() + ": " + progressPercent.ToStringPercent());
- builder.AppendLine();
-
- // 显示剩余时间
- string timeText = "ARA_OothecaIncubator.TimeRemaining".Translate() + ": " + daysRemaining.ToString("F1") + " " + "ARA_OothecaIncubator.Days".Translate();
- if (hoursRemaining > 0.1f && daysRemaining < 1f)
- {
- timeText += " (" + hoursRemaining.ToString("F1") + " " + "ARA_OothecaIncubator.Hours".Translate() + ")";
- }
- builder.Append(timeText);
-
- // 显示速度和质量(简化版本)
- builder.AppendLine();
- builder.Append("ARA_OothecaIncubator.Speed".Translate() + ": " + SpeedMultiplier.ToStringPercent() + ", " +
- "ARA_OothecaIncubator.Quality".Translate() + ": " + QualityMultiplier.ToStringPercent());
- }
- else if (assignedLarva != null)
- {
- if (builder.Length > 0) builder.AppendLine();
- if (larvaOperateTicksRemaining > 0)
- {
- float secondsRemaining = larvaOperateTicksRemaining / 60f;
- builder.Append("ARA_OothecaIncubator.LarvaOperating".Translate() + ": " + secondsRemaining.ToString("F1") + " " + "ARA_OothecaIncubator.SRemaining".Translate());
- }
- else
- {
- builder.Append("ARA_OothecaIncubator.LarvaOnWay".Translate());
- }
- }
- else if (!isIncubating)
- {
- var config = IncubatorData?.SelectedConfig;
- if (config != null)
- {
- if (builder.Length > 0) builder.AppendLine();
- builder.Append("ARA_OothecaIncubator.Target".Translate() + ": " + config.pawnKind.LabelCap);
-
- // 只显示当前乘数,不显示条件详情
- builder.AppendLine();
- builder.Append("ARA_OothecaIncubator.SpeedMultiplier".Translate() + ": " + SpeedMultiplier.ToStringPercent() + ", " +
- "ARA_OothecaIncubator.QualityMultiplier".Translate() + ": " + QualityMultiplier.ToStringPercent());
- }
- }
-
- return builder.ToString().TrimEndNewlines();
+ timeText += " (" + hoursRemaining.ToString("F1") + " 小时)";
}
+ builder.AppendLine(timeText);
+ // 显示速度和质量
+ builder.Append("速度: " + SpeedMultiplier.ToStringPercent() + " | 质量: " + QualityMultiplier.ToStringPercent());
+ }
+ else if (assignedLarva != null)
+ {
+ if (larvaOperateTicksRemaining > 0)
+ {
+ float secondsRemaining = larvaOperateTicksRemaining / 60f;
+ builder.Append("幼虫激活中: " + secondsRemaining.ToString("F1") + " 秒");
+ }
+ else
+ {
+ builder.Append("幼虫赶路中...");
+ }
+ }
+ else if (!isIncubating)
+ {
+ var config = IncubatorData?.SelectedConfig;
+ if (config != null)
+ {
+ builder.AppendLine("孵化目标: " + config.pawnKind.LabelCap);
+ builder.Append("速度: " + SpeedMultiplier.ToStringPercent() + " | 质量: " + QualityMultiplier.ToStringPercent());
+ }
+ }
+
+ // === 第二部分:基类信息(包括维护度等) ===
+ var baseString = base.GetInspectString();
+ if (!string.IsNullOrEmpty(baseString))
+ {
+ if (builder.Length > 0) builder.AppendLine();
+ builder.Append(baseString);
+ }
+
+ return builder.ToString().TrimEndNewlines();
+}
+
// 获取剩余时间(ticks)
public float GetRemainingTicks()
{
@@ -438,6 +430,9 @@ namespace ArachnaeSwarm
// 只有玩家派系才显示Gizmo
if (Faction == Faction.OfPlayer)
{
+ // 始终显示双进度条Gizmo(内部会自动处理非孵化状态的显示)
+ yield return new Gizmo_IncubationProgress(this);
+
// 不在孵化中时才显示切换目标按钮
if (!isIncubating && IncubatorData?.IncubationConfigs?.Count > 0)
{
diff --git a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Gizmo_IncubationProgress.cs b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Gizmo_IncubationProgress.cs
new file mode 100644
index 0000000..039aa95
--- /dev/null
+++ b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Gizmo_IncubationProgress.cs
@@ -0,0 +1,226 @@
+// File: Gizmo_IncubationProgress.cs
+// 类似原版 Refuelable 的双进度条 Gizmo,显示孵化进度和品质
+using System.Collections.Generic;
+using RimWorld;
+using UnityEngine;
+using Verse;
+
+namespace ArachnaeSwarm
+{
+ [StaticConstructorOnStartup]
+ public class Gizmo_IncubationProgress : Gizmo
+ {
+ private readonly Building_Ootheca ootheca;
+
+ // 尺寸常量
+ private const float Width = 180f;
+ private const float BarHeight = 14f;
+ private const float LabelHeight = 14f;
+ private const float Spacing = 4f;
+ private const float Padding = 8f;
+
+ // 进度条材质
+ private static readonly Texture2D IncubationBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.2f, 0.7f, 0.2f, 0.8f));
+ private static readonly Texture2D QualityBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.2f, 0.5f, 0.9f, 0.8f));
+ private static readonly Texture2D EmptyBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.1f, 0.1f, 0.1f, 0.5f));
+
+ public Gizmo_IncubationProgress(Building_Ootheca ootheca)
+ {
+ this.ootheca = ootheca;
+ Order = -100f; // 显示在左侧
+ }
+
+ public override float GetWidth(float maxWidth)
+ {
+ return Mathf.Min(Width, maxWidth);
+ }
+
+ public override GizmoResult GizmoOnGUI(Vector2 topLeft, float maxWidth, GizmoRenderParms parms)
+ {
+ // 主矩形区域(向上偏移以容纳更高的内容)
+ Rect rect = new Rect(topLeft.x, topLeft.y - 55f, GetWidth(maxWidth), 130f);
+ Widgets.DrawWindowBackground(rect);
+
+ // 内部区域
+ Rect innerRect = rect.ContractedBy(Padding);
+ float curY = innerRect.y;
+
+ // 状态判断
+ bool isIncubating = ootheca.isIncubating;
+ bool hasLarva = ootheca.assignedLarva != null;
+ var config = ootheca.IncubatorData?.SelectedConfig;
+
+ // === 标题(可点击切换目标) ===
+ Text.Font = GameFont.Small;
+ Rect titleRect = new Rect(innerRect.x, curY, innerRect.width, Text.LineHeight);
+
+ string title;
+ if (isIncubating && ootheca.incubatingPawnKind != null)
+ title = ootheca.incubatingPawnKind.LabelCap;
+ else if (config != null)
+ title = config.pawnKind.LabelCap;
+ else
+ title = "选择孵化目标...";
+
+ // 标题按钮(只有非孵化状态可点击)
+ bool canSwitch = !isIncubating && !hasLarva && ootheca.IncubatorData?.IncubationConfigs?.Count > 0;
+ if (canSwitch)
+ {
+ // 绘制按钮背景
+ if (Mouse.IsOver(titleRect))
+ {
+ Widgets.DrawHighlight(titleRect);
+ }
+
+ if (Widgets.ButtonInvisible(titleRect))
+ {
+ ShowTargetSwitchMenu();
+ }
+
+ // 带下划线的标题(表示可点击)
+ GUI.color = new Color(0.7f, 0.9f, 1f);
+ Widgets.Label(titleRect, title.Truncate(titleRect.width - 10f) + " ▼");
+ GUI.color = Color.white;
+ }
+ else
+ {
+ Widgets.Label(titleRect, title.Truncate(titleRect.width));
+ }
+ curY += Text.LineHeight + Spacing;
+
+ // === 内容绘制 ===
+ if (isIncubating)
+ {
+ // 孵化进度标签
+ DrawLabeledProgressBar(ref curY, innerRect.x, innerRect.width,
+ "孵化进度:", ootheca.AdjustedProgressPercent, IncubationBarTex);
+
+ curY += Spacing;
+
+ // 品质进度标签
+ DrawLabeledProgressBar(ref curY, innerRect.x, innerRect.width,
+ "品质进度:", ootheca.QualityPercent, QualityBarTex);
+ }
+ else if (hasLarva)
+ {
+ Text.Font = GameFont.Tiny;
+ GUI.color = new Color(0.9f, 0.9f, 0.5f);
+ string statusText = ootheca.larvaOperateTicksRemaining > 0 ? "幼虫激活中..." : "幼虫赶路中...";
+ Widgets.Label(new Rect(innerRect.x, curY, innerRect.width, 30f), statusText);
+ GUI.color = Color.white;
+ }
+ else
+ {
+ Text.Font = GameFont.Tiny;
+ GUI.color = new Color(0.7f, 0.7f, 0.7f);
+ string statusText = (config != null && config.IsResearchComplete) ? "就绪 - 点击上方切换目标" : "需要研究";
+ Widgets.Label(new Rect(innerRect.x, curY, innerRect.width, 20f), statusText);
+ curY += 20f;
+
+ string stats = $"速度:{ootheca.SpeedMultiplier.ToStringPercent()} 质量:{ootheca.QualityMultiplier.ToStringPercent()}";
+ Widgets.Label(new Rect(innerRect.x, curY, innerRect.width, 16f), stats);
+ GUI.color = Color.white;
+ }
+
+ // === 工具提示 ===
+ if (Mouse.IsOver(rect) && !Mouse.IsOver(titleRect))
+ {
+ Widgets.DrawHighlight(rect);
+ TooltipHandler.TipRegion(rect, GetTooltip());
+ }
+
+ Text.Font = GameFont.Small;
+ return new GizmoResult(GizmoState.Clear);
+ }
+
+ private void ShowTargetSwitchMenu()
+ {
+ var configs = ootheca.IncubatorData?.IncubationConfigs;
+ if (configs == null || configs.Count == 0) return;
+
+ List options = new List();
+
+ for (int i = 0; i < configs.Count; i++)
+ {
+ var cfg = configs[i];
+ int index = i;
+
+ string label = cfg.pawnKind.LabelCap;
+ if (cfg.requiredResearch != null && !cfg.requiredResearch.IsFinished)
+ {
+ label += $" (需要: {cfg.requiredResearch.LabelCap})";
+ options.Add(new FloatMenuOption(label, null)); // 禁用
+ }
+ else
+ {
+ label += $" ({cfg.daysRequired}天)";
+ options.Add(new FloatMenuOption(label, () =>
+ {
+ ootheca.IncubatorData.SwitchToConfig(index);
+ }));
+ }
+ }
+
+ Find.WindowStack.Add(new FloatMenu(options));
+ }
+
+ // 带标签的进度条
+ private void DrawLabeledProgressBar(ref float curY, float x, float width, string label, float percent, Texture2D barTex)
+ {
+ // 标签
+ Text.Font = GameFont.Tiny;
+ GUI.color = new Color(0.8f, 0.8f, 0.8f);
+ Widgets.Label(new Rect(x, curY, width, LabelHeight), label);
+ GUI.color = Color.white;
+ curY += LabelHeight;
+
+ // 进度条
+ Rect barRect = new Rect(x, curY, width, BarHeight);
+ Widgets.FillableBar(barRect, percent, barTex, EmptyBarTex, true);
+
+ // 百分比文字
+ Text.Font = GameFont.Tiny;
+ Text.Anchor = TextAnchor.MiddleCenter;
+ Widgets.Label(barRect, percent.ToStringPercent("0"));
+ Text.Anchor = TextAnchor.UpperLeft;
+ curY += BarHeight;
+ }
+
+ private string GetTooltip()
+ {
+ var sb = new System.Text.StringBuilder();
+
+ // 孵化目标
+ if (ootheca.incubatingPawnKind != null)
+ {
+ sb.AppendLine("正在孵化: " + ootheca.incubatingPawnKind.LabelCap);
+ }
+
+ // 进度信息
+ sb.AppendLine();
+ sb.AppendLine("孵化进度: " + ootheca.AdjustedProgressPercent.ToStringPercent());
+ sb.AppendLine("品质进度: " + ootheca.QualityPercent.ToStringPercent());
+
+ // 剩余时间
+ float daysRemaining = ootheca.GetRemainingDays();
+ if (daysRemaining > 0 && daysRemaining < float.MaxValue)
+ {
+ sb.AppendLine();
+ sb.AppendLine("剩余时间: " + daysRemaining.ToString("F1") + " 天");
+ }
+
+ // 速度和质量乘数
+ sb.AppendLine();
+ sb.AppendLine("速度倍率: " + ootheca.SpeedMultiplier.ToStringPercent());
+ sb.AppendLine("质量倍率: " + ootheca.QualityMultiplier.ToStringPercent());
+
+ // 详细因子
+ sb.AppendLine();
+ sb.AppendLine(ootheca.GetSpeedFactorsDescription());
+ sb.AppendLine();
+ sb.AppendLine(ootheca.GetQualityFactorsDescription());
+
+ return sb.ToString().TrimEndNewlines();
+ }
+ }
+}
diff --git a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/ITab_Ootheca_Incubation.cs b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/ITab_Ootheca_Incubation.cs
deleted file mode 100644
index 6185841..0000000
--- a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/ITab_Ootheca_Incubation.cs
+++ /dev/null
@@ -1,369 +0,0 @@
-using UnityEngine;
-using Verse;
-using System.Collections.Generic;
-using System.Linq;
-using RimWorld;
-using Verse.Sound;
-
-namespace ArachnaeSwarm
-{
- public class ITab_Ootheca_Incubation : ITab
- {
- private const float BarHeight = 20f;
- private const float Margin = 10f;
- private const float LabelHeight = 30f;
- private const float SmallLabelHeight = 20f;
- private const float ButtonHeight = 25f;
- private const float TabWidth = 320f;
- private const float TabHeight = 420f; // 增加标签页高度以容纳更多间距
-
- private Vector2 scrollPosition = Vector2.zero;
- private const float ViewHeight = 450f; // 增加滚动区域高度
-
- public override bool IsVisible
- {
- get
- {
- // 只显示给玩家派系
- return SelThing.Faction == Faction.OfPlayer;
- }
- }
-
- public ITab_Ootheca_Incubation()
- {
- size = new Vector2(TabWidth, TabHeight);
- labelKey = "IncubationTab";
- tutorTag = "Incubation";
- }
-
- protected override void FillTab()
- {
-
- Rect rect = new Rect(0f, 0f, size.x, size.y).ContractedBy(Margin);
- Widgets.DrawMenuSection(rect);
- Building_Ootheca ootheca = SelThing as Building_Ootheca;
- if (ootheca == null)
- {
- Widgets.Label(rect, "NotAnOotheca".Translate());
- return;
- }
- rect = rect.ContractedBy(5f);
-
- // 创建一个可滚动区域
- Rect viewRect = new Rect(0f, 0f, rect.width - 16f, ViewHeight);
- Rect scrollRect = new Rect(rect.x, rect.y, rect.width, rect.height);
-
- Widgets.BeginScrollView(scrollRect, ref scrollPosition, viewRect);
-
- float curY = 0f;
-
- // 显示标题
- Rect titleRect = new Rect(0f, curY, viewRect.width, LabelHeight);
- string title = "IncubationProgress".Translate();
- Text.Font = GameFont.Medium;
- Widgets.Label(titleRect, title);
- Text.Font = GameFont.Small;
- curY += LabelHeight + 15f;
- // 显示速度和质量乘数按钮
- float buttonWidth = (viewRect.width - 10f) / 2f;
-
- // 速度按钮
- Rect speedButtonRect = new Rect(0f, curY, buttonWidth, ButtonHeight);
- string speedText = "Speed".Translate() + ": " + ootheca.SpeedMultiplier.ToStringPercent();
-
- // 设置按钮颜色
- Color speedColor = Color.white;
- if (ootheca.SpeedMultiplier != 1.0f)
- {
- speedColor = ootheca.SpeedMultiplier > 1.0f ?
- new Color(0.2f, 0.8f, 0.2f) :
- new Color(0.8f, 0.8f, 0.2f);
- }
-
- // 绘制速度按钮
- if (Widgets.ButtonText(speedButtonRect, speedText, true, true, speedColor))
- {
- // 按钮点击操作(可选)
- // 可以在这里显示详细信息的窗口
- }
-
- // 为速度按钮添加工具提示
- TooltipHandler.TipRegion(speedButtonRect, () => ootheca.GetSpeedFactorsDescription(), 987654321);
-
- // 质量按钮
- Rect qualityButtonRect = new Rect(buttonWidth + 10f, curY, buttonWidth, ButtonHeight);
- string qualityText = "Quality".Translate() + ": " + ootheca.QualityMultiplier.ToStringPercent();
-
- // 设置按钮颜色
- Color qualityColor = Color.white;
- float qualityMultiplier = ootheca.QualityMultiplier;
- if (qualityMultiplier != 1.0f)
- {
- if (qualityMultiplier > 0.9f)
- qualityColor = new Color(0.2f, 0.8f, 0.2f);
- else if (qualityMultiplier > 0.7f)
- qualityColor = new Color(0.8f, 0.8f, 0.2f);
- else if (qualityMultiplier > 0.5f)
- qualityColor = new Color(0.9f, 0.6f, 0.2f);
- else
- qualityColor = new Color(0.8f, 0.2f, 0.2f);
- }
-
- // 绘制质量按钮
- if (Widgets.ButtonText(qualityButtonRect, qualityText, true, true, qualityColor))
- {
- // 按钮点击操作(可选)
- // 可以在这里显示详细信息的窗口
- }
-
- // 为质量按钮添加工具提示
- TooltipHandler.TipRegion(qualityButtonRect, () => ootheca.GetQualityFactorsDescription(), 987654322);
-
- curY += ButtonHeight + 25f; // 增加按钮与目标显示之间的间距
-
- // 如果在孵化中,显示进度条
- if (ootheca.isIncubating && ootheca.incubatingPawnKind != null)
- {
- // 使用调整后的进度百分比
- float progressPercent = ootheca.AdjustedProgressPercent;
- float qualityPercent = ootheca.QualityPercent;
-
- // 获取调整后的剩余时间
- float daysRemaining = ootheca.GetRemainingDays();
- float hoursRemaining = ootheca.GetRemainingHours();
-
- // 显示目标
- Rect targetRect = new Rect(0f, curY, viewRect.width, SmallLabelHeight);
- Widgets.Label(targetRect, "Target".Translate() + ": " + ootheca.incubatingPawnKind.LabelCap);
-
- curY += SmallLabelHeight + 20f;
-
- // 显示孵化进度条
- Rect progressBarRect = new Rect(0f, curY, viewRect.width, BarHeight);
-
- // 在进度条正上方居中添加标签
- Rect progressLabelRect = new Rect(progressBarRect.x, progressBarRect.y - 20, progressBarRect.width, 18);
- Text.Anchor = TextAnchor.MiddleCenter;
- GUI.color = new Color(0.9f, 0.9f, 0.9f, 1f);
- Widgets.Label(progressLabelRect, "IncubationProgressLabel".Translate());
- Text.Anchor = TextAnchor.UpperLeft;
- GUI.color = Color.white;
-
- // 绘制进度条
- Widgets.FillableBar(progressBarRect, progressPercent, SolidColorMaterials.NewSolidColorTexture(new Color(0.2f, 0.8f, 0.2f, 0.5f)));
- Widgets.FillableBarChangeArrows(progressBarRect, progressPercent);
-
- // 进度条文字(百分比)
- string progressText = $"{progressPercent:P0}";
- Text.Anchor = TextAnchor.MiddleCenter;
- Widgets.Label(progressBarRect, progressText);
- Text.Anchor = TextAnchor.UpperLeft;
-
- curY += BarHeight + 30f; // 增加孵化条与质量条之间的间距
-
- // 显示质量进度条
- Rect qualityBarRect = new Rect(0f, curY, viewRect.width, BarHeight);
-
- // 在质量进度条正上方居中添加标签
- Rect qualityLabelRect = new Rect(qualityBarRect.x, qualityBarRect.y - 20, qualityBarRect.width, 18);
- Text.Anchor = TextAnchor.MiddleCenter;
- GUI.color = new Color(0.9f, 0.9f, 0.9f, 1f);
- Widgets.Label(qualityLabelRect, "QualityProgress".Translate());
- Text.Anchor = TextAnchor.UpperLeft;
- GUI.color = Color.white;
-
- // 绘制质量进度条
- Widgets.FillableBar(qualityBarRect, qualityPercent, SolidColorMaterials.NewSolidColorTexture(new Color(0.1f, 0.4f, 0.8f, 0.5f)));
-
- // 质量进度条文字(百分比)
- string qualityProgressText = $"{qualityPercent:P0}";
- Text.Anchor = TextAnchor.MiddleCenter;
- Widgets.Label(qualityBarRect, qualityProgressText);
- Text.Anchor = TextAnchor.UpperLeft;
-
- // 在质量进度条上显示目标质量百分比
- Rect targetQualityRect = new Rect(qualityBarRect.x + qualityBarRect.width - 40, qualityBarRect.y, 40, BarHeight);
- GUI.color = new Color(0.8f, 0.8f, 0.8f, 0.7f);
- Text.Anchor = TextAnchor.MiddleRight;
- Widgets.Label(targetQualityRect, $"{ootheca.QualityMultiplier:P0}");
- Text.Anchor = TextAnchor.UpperLeft;
- GUI.color = Color.white;
-
- curY += BarHeight + 25f; // 增加质量条与剩余时间之间的间距
-
- // 显示剩余时间
- Rect timeRect = new Rect(0f, curY, viewRect.width, SmallLabelHeight);
- string timeText = "ARA_OothecaIncubator.TimeRemaining".Translate() + ": " + daysRemaining.ToString("F1") + " " + "Days".Translate();
- if (hoursRemaining > 0.1f && daysRemaining < 1f)
- {
- timeText += " (" + hoursRemaining.ToString("F1") + " " + "Hours".Translate() + ")";
- }
- Widgets.Label(timeRect, timeText);
- }
- else if (ootheca.assignedLarva != null)
- {
- // 如果有幼虫正在路上或操作中
- Rect statusRect = new Rect(0f, curY, viewRect.width, SmallLabelHeight * 2);
- if (ootheca.larvaOperateTicksRemaining > 0)
- {
- float secondsRemaining = ootheca.larvaOperateTicksRemaining / 60f;
- Widgets.Label(statusRect, "LarvaIsActivatingOotheca".Translate() + "\n" +
- secondsRemaining.ToString("F1") + " " + "SecondsRemaining".Translate());
- }
- else
- {
- Widgets.Label(statusRect, "LarvaIsOnTheWay".Translate());
- }
-
- // 为幼虫状态增加一些间距
- curY += SmallLabelHeight * 2 + 15f;
-
- // 不在孵化中时,也显示目标配置
- var config = ootheca.IncubatorData?.SelectedConfig;
- if (config != null)
- {
- curY += 10f;
- Rect targetRect = new Rect(0f, curY, viewRect.width, SmallLabelHeight * 3);
- string targetText = "ReadyToIncubate".Translate() + "\n" + config.pawnKind.LabelCap;
-
- if (!config.IsResearchComplete && config.requiredResearch != null)
- {
- targetText += "\n" + "(" + "Requires".Translate() + ": " + config.requiredResearch.LabelCap + ")";
- }
-
- Widgets.Label(targetRect, targetText);
- }
- }
- else
- {
- // 不在孵化中,显示当前选择的目标
- var config = ootheca.IncubatorData?.SelectedConfig;
- if (config != null)
- {
- Rect targetRect = new Rect(0f, curY, viewRect.width, SmallLabelHeight * 3);
- string targetText = "ReadyToIncubate".Translate() + "\n" + config.pawnKind.LabelCap;
-
- if (!config.IsResearchComplete && config.requiredResearch != null)
- {
- targetText += "\n" + "(" + "Requires".Translate() + ": " + config.requiredResearch.LabelCap + ")";
- }
-
- Widgets.Label(targetRect, targetText);
-
- // 为静态显示增加一些底部间距
- curY += SmallLabelHeight * 3 + 10f;
- }
- else
- {
- Rect noTargetRect = new Rect(0f, curY, viewRect.width, SmallLabelHeight);
- Widgets.Label(noTargetRect, "NoIncubationTargetSelected".Translate());
-
- curY += SmallLabelHeight + 10f;
- }
- }
-
- // 添加一些底部空白区域,让布局看起来不那么拥挤
- curY += 20f;
-
- // 更新滚动区域的实际高度
- viewRect.height = curY;
-
- Widgets.EndScrollView();
- }
-
- // 检查是否在孵化间中(ITab内部使用)
- private bool IsInIncubatorRoom(Building_Ootheca ootheca)
- {
- var room = ootheca.GetRoom();
- if (room == null) return false;
-
- return room.Role != null && room.Role.defName == "ARA_Incubator_Room";
- }
-
- // 计算周围4格内的营养液数量(ITab内部使用)
- private int CountNearbyNutrientSolutions(Building_Ootheca ootheca)
- {
- var map = ootheca.Map;
- if (map == null) return 0;
-
- int count = 0;
- int radius = 4; // 4格半径
- var position = ootheca.Position;
-
- // 检查周围4格范围内的所有单元格
- for (int x = -radius; x <= radius; x++)
- {
- for (int y = -radius; y <= radius; y++)
- {
- IntVec3 cell = position + new IntVec3(x, 0, y);
-
- // 检查单元格是否在地图内
- if (cell.InBounds(map))
- {
- // 检查地形是否为营养液
- TerrainDef terrain = map.terrainGrid.TerrainAt(cell);
- if (terrain != null && terrain.defName == "ARA_Incubator_Nutrient_Solution")
- {
- count++;
- }
- }
- }
- }
-
- return count;
- }
-
- // 计算房间质量因子(ITab内部使用)
- private float GetRoomQualityFactor(Building_Ootheca ootheca)
- {
- var room = ootheca.GetRoom();
- if (room == null) return 1.0f;
-
- // 获取房间的ARA_IncubatorQualityFactor统计值
- var statDef = DefDatabase.GetNamedSilentFail("ARA_IncubatorQualityFactor");
- if (statDef != null)
- {
- return room.GetStat(statDef);
- }
-
- return 1.0f;
- }
-
- // 计算附近其他Ootheca的数量(ITab内部使用)
- private int CountNearbyOtherOothecas(Building_Ootheca ootheca)
- {
- var map = ootheca.Map;
- if (map == null) return 0;
-
- int count = 0;
- var position = ootheca.Position;
- var room = ootheca.GetRoom();
-
- // 查找地图上所有的Ootheca
- var allOothecas = map.listerThings.ThingsOfDef(ootheca.def);
-
- foreach (var thing in allOothecas)
- {
- // 排除自己
- if (thing == ootheca) continue;
-
- // 检查是否在同一个房间或附近(10格内)
- float distance = thing.Position.DistanceTo(position);
- var otherRoom = thing.GetRoom();
-
- if ((room != null && room == otherRoom) || distance <= 10f)
- {
- count++;
- }
- }
-
- return count;
- }
-
- protected override void UpdateSize()
- {
- // 固定大小
- size = new Vector2(TabWidth, TabHeight);
- }
- }
-}
diff --git a/Source/ArachnaeSwarm/Pawn_Comps/ARA_TrainingWork/JobPlant/JobGiver_Grower.cs b/Source/ArachnaeSwarm/Pawn_Comps/ARA_TrainingWork/JobPlant/JobGiver_Grower.cs
index 0e42089..b6dcc87 100644
--- a/Source/ArachnaeSwarm/Pawn_Comps/ARA_TrainingWork/JobPlant/JobGiver_Grower.cs
+++ b/Source/ArachnaeSwarm/Pawn_Comps/ARA_TrainingWork/JobPlant/JobGiver_Grower.cs
@@ -95,64 +95,43 @@ namespace ArachnaeSwarm
return bestCell;
}
- // 修改后的方法:寻找最近的播种或清理 Job
+ // 修改后的方法:寻找最近的播种或清理 Job(原版逻辑:找最近可工作格子)
private Job FindClosestSowableOrClearJob(Pawn pawn, WorkGiver_ArachnaeSow scanner)
{
- IntVec3 bestClearCell = IntVec3.Invalid;
- Job bestClearJob = null;
- float bestClearDistSq = float.MaxValue;
-
- IntVec3 bestSowCell = IntVec3.Invalid;
- Job bestSowJob = null;
- float bestSowDistSq = float.MaxValue;
+ IntVec3 bestCell = IntVec3.Invalid;
+ Job bestJob = null;
+ float bestDistSq = float.MaxValue;
foreach (Zone zone in pawn.Map.zoneManager.AllZones)
{
if (zone is Zone_Growing growingZone)
{
+ // 检查种植区是否允许播种
+ if (!growingZone.allowSow)
+ continue;
+
ThingDef wantedPlant = growingZone.GetPlantDefToGrow();
if (wantedPlant == null) continue;
foreach (IntVec3 cell in growingZone.Cells)
{
float distSq = pawn.Position.DistanceToSquared(cell);
- if (pawn.CanReach(cell, PathEndMode.ClosestTouch, Danger.Deadly))
+ // 只考虑比当前最佳更近的格子
+ if (distSq < bestDistSq && pawn.CanReach(cell, PathEndMode.ClosestTouch, Danger.Deadly))
{
Job potentialJob = scanner.JobOnCell(pawn, cell);
if (potentialJob != null)
{
- if (potentialJob.def == JobDefOf.CutPlant || potentialJob.def == JobDefOf.HaulToContainer || potentialJob.def == JobDefOf.HaulToCell)
- {
- if (distSq < bestClearDistSq)
- {
- bestClearDistSq = distSq;
- bestClearJob = potentialJob;
- }
- }
- else if (potentialJob.def == JobDefOf.Sow)
- {
- if (distSq < bestSowDistSq)
- {
- bestSowDistSq = distSq;
- bestSowJob = potentialJob;
- }
- }
+ // 原版逻辑:找最近的可工作格子,不区分任务类型优先级
+ bestDistSq = distSq;
+ bestJob = potentialJob;
+ bestCell = cell;
}
}
}
}
}
- // 优先返回清理 Job
- if (bestClearJob != null)
- {
- return bestClearJob;
- }
- // 其次返回播种 Job
- if (bestSowJob != null)
- {
- return bestSowJob;
- }
- return null;
+ return bestJob;
}
}
}
\ No newline at end of file
diff --git a/Source/ArachnaeSwarm/Pawn_Comps/ARA_TrainingWork/JobPlant/ThinkNode_ConditionalAnimalShouldDoGrowingWork.cs b/Source/ArachnaeSwarm/Pawn_Comps/ARA_TrainingWork/JobPlant/ThinkNode_ConditionalAnimalShouldDoGrowingWork.cs
index c577380..7a7aec5 100644
--- a/Source/ArachnaeSwarm/Pawn_Comps/ARA_TrainingWork/JobPlant/ThinkNode_ConditionalAnimalShouldDoGrowingWork.cs
+++ b/Source/ArachnaeSwarm/Pawn_Comps/ARA_TrainingWork/JobPlant/ThinkNode_ConditionalAnimalShouldDoGrowingWork.cs
@@ -35,4 +35,4 @@ namespace ArachnaeSwarm
return canSow;
}
}
-}
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/Source/ArachnaeSwarm/Pawn_Comps/ARA_TrainingWork/JobPlant/WorkGiver_ArachnaeSow.cs b/Source/ArachnaeSwarm/Pawn_Comps/ARA_TrainingWork/JobPlant/WorkGiver_ArachnaeSow.cs
index 6ff01b2..f10783c 100644
--- a/Source/ArachnaeSwarm/Pawn_Comps/ARA_TrainingWork/JobPlant/WorkGiver_ArachnaeSow.cs
+++ b/Source/ArachnaeSwarm/Pawn_Comps/ARA_TrainingWork/JobPlant/WorkGiver_ArachnaeSow.cs
@@ -70,7 +70,7 @@ namespace ArachnaeSwarm
for (int i = 0; i < thingList.Count; i++)
{
Thing thing = thingList[i];
- if (thing.def == wantedPlantDef)
+ if (thing.def == wantedPlantDefLocal)
{
return null;
}
@@ -122,6 +122,10 @@ namespace ArachnaeSwarm
{
return null;
}
+ if (!PlantUtility.PawnWillingToCutPlant_Job(plant, pawn))
+ {
+ return null;
+ }
return JobMaker.MakeJob(JobDefOf.CutPlant, plant);
}
// 如果地块上的植物是我们想要种植的植物,并且它阻碍了相邻播种,则不割除
@@ -155,6 +159,10 @@ namespace ArachnaeSwarm
{
return null;
}
+ if (!PlantUtility.PawnWillingToCutPlant_Job(plant2, pawn))
+ {
+ return null;
+ }
if (PlantUtility.TreeMarkedForExtraction(plant2))
{
return null;
@@ -202,6 +210,10 @@ namespace ArachnaeSwarm
{
return null;
}
+ if (!PlantUtility.PawnWillingToCutPlant_Job(thing3, pawn))
+ {
+ return null;
+ }
if (PlantUtility.TreeMarkedForExtraction(thing3))
{
return null;