feat: 新增阿拉克涅虫卵囊及其孵化系统,包括营养液、维护机制和孵化质量奖励。

This commit is contained in:
2025-12-23 13:16:13 +08:00
parent def05a2de0
commit a0f90cf71a
10 changed files with 317 additions and 477 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -145,10 +145,7 @@
</li>
</modExtensions>
<!-- ITab配置 -->
<inspectorTabs>
<li>ArachnaeSwarm.ITab_Ootheca_Incubation</li>
</inspectorTabs>
<costList>
<ARA_InsectJelly>25</ARA_InsectJelly>

View File

@@ -28,7 +28,7 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<OutputPath>..\..\1.6\1.6\Assemblies\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
@@ -123,7 +123,7 @@
<Compile Include="Buildings\Building_Incubatable.cs" />
<Compile Include="Buildings\Building_Ootheca\Building_Ootheca.cs" />
<Compile Include="Buildings\Building_Ootheca\CompProperties_IncubatorData.cs" />
<Compile Include="Buildings\Building_Ootheca\ITab_Ootheca_Incubation.cs" />
<Compile Include="Buildings\Building_Ootheca\Gizmo_IncubationProgress.cs" />
<Compile Include="Buildings\Building_Ootheca\JobDriver_OperateIncubator.cs" />
<Compile Include="Buildings\Building_Ootheca\OothecaIncubatorExtension.cs" />
<Compile Include="Buildings\Building_ResearchBlueprintReader\Building_ResearchBlueprintReader.cs" />

View File

@@ -333,53 +333,42 @@ namespace ArachnaeSwarm
Destroy();
}
// 显示额外信息(简化版本,只显示速率,不显示因子
// 显示额外信息(方案A孵化信息在前维护信息在后
public override string GetInspectString()
{
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();
builder.AppendLine("正在孵化: " + incubatingPawnKind.LabelCap);
builder.AppendLine("进度: " + progressPercent.ToStringPercent());
// 显示剩余时间
string timeText = "ARA_OothecaIncubator.TimeRemaining".Translate() + ": " + daysRemaining.ToString("F1") + " " + "ARA_OothecaIncubator.Days".Translate();
string timeText = "剩余时间: " + daysRemaining.ToString("F1") + " ";
if (hoursRemaining > 0.1f && daysRemaining < 1f)
{
timeText += " (" + hoursRemaining.ToString("F1") + " " + "ARA_OothecaIncubator.Hours".Translate() + ")";
timeText += " (" + hoursRemaining.ToString("F1") + " 小时)";
}
builder.Append(timeText);
builder.AppendLine(timeText);
// 显示速度和质量(简化版本)
builder.AppendLine();
builder.Append("ARA_OothecaIncubator.Speed".Translate() + ": " + SpeedMultiplier.ToStringPercent() + ", " +
"ARA_OothecaIncubator.Quality".Translate() + ": " + QualityMultiplier.ToStringPercent());
// 显示速度和质量
builder.Append("速度: " + SpeedMultiplier.ToStringPercent() + " | 质量: " + 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());
builder.Append("幼虫激活中: " + secondsRemaining.ToString("F1") + " 秒");
}
else
{
builder.Append("ARA_OothecaIncubator.LarvaOnWay".Translate());
builder.Append("幼虫赶路中...");
}
}
else if (!isIncubating)
@@ -387,16 +376,19 @@ namespace ArachnaeSwarm
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());
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();
}
@@ -438,6 +430,9 @@ namespace ArachnaeSwarm
// 只有玩家派系才显示Gizmo
if (Faction == Faction.OfPlayer)
{
// 始终显示双进度条Gizmo内部会自动处理非孵化状态的显示
yield return new Gizmo_IncubationProgress(this);
// 不在孵化中时才显示切换目标按钮
if (!isIncubating && IncubatorData?.IncubationConfigs?.Count > 0)
{

View File

@@ -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<FloatMenuOption> options = new List<FloatMenuOption>();
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();
}
}
}

View File

@@ -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<RoomStatDef>.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);
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;