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;