feat: 新增阿拉克涅虫卵囊及其孵化系统,包括营养液、维护机制和孵化质量奖励。
This commit is contained in:
Binary file not shown.
BIN
1.6/1.6/Assemblies/ArachnaeSwarm.pdb
Normal file
BIN
1.6/1.6/Assemblies/ArachnaeSwarm.pdb
Normal file
Binary file not shown.
@@ -145,10 +145,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</modExtensions>
|
</modExtensions>
|
||||||
|
|
||||||
<!-- ITab配置 -->
|
|
||||||
<inspectorTabs>
|
|
||||||
<li>ArachnaeSwarm.ITab_Ootheca_Incubation</li>
|
|
||||||
</inspectorTabs>
|
|
||||||
|
|
||||||
<costList>
|
<costList>
|
||||||
<ARA_InsectJelly>25</ARA_InsectJelly>
|
<ARA_InsectJelly>25</ARA_InsectJelly>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<DebugType>pdbonly</DebugType>
|
<DebugType>pdbonly</DebugType>
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
<OutputPath>bin\Release\</OutputPath>
|
<OutputPath>..\..\1.6\1.6\Assemblies\</OutputPath>
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
@@ -123,7 +123,7 @@
|
|||||||
<Compile Include="Buildings\Building_Incubatable.cs" />
|
<Compile Include="Buildings\Building_Incubatable.cs" />
|
||||||
<Compile Include="Buildings\Building_Ootheca\Building_Ootheca.cs" />
|
<Compile Include="Buildings\Building_Ootheca\Building_Ootheca.cs" />
|
||||||
<Compile Include="Buildings\Building_Ootheca\CompProperties_IncubatorData.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\JobDriver_OperateIncubator.cs" />
|
||||||
<Compile Include="Buildings\Building_Ootheca\OothecaIncubatorExtension.cs" />
|
<Compile Include="Buildings\Building_Ootheca\OothecaIncubatorExtension.cs" />
|
||||||
<Compile Include="Buildings\Building_ResearchBlueprintReader\Building_ResearchBlueprintReader.cs" />
|
<Compile Include="Buildings\Building_ResearchBlueprintReader\Building_ResearchBlueprintReader.cs" />
|
||||||
|
|||||||
@@ -333,53 +333,42 @@ namespace ArachnaeSwarm
|
|||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 显示额外信息(简化版本,只显示速率,不显示因子)
|
// 显示额外信息(方案A:孵化信息在前,维护信息在后)
|
||||||
public override string GetInspectString()
|
public override string GetInspectString()
|
||||||
{
|
{
|
||||||
var baseString = base.GetInspectString();
|
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(baseString))
|
// === 第一部分:孵化状态 ===
|
||||||
{
|
|
||||||
builder.Append(baseString);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isIncubating && incubatingPawnKind != null)
|
if (isIncubating && incubatingPawnKind != null)
|
||||||
{
|
{
|
||||||
float progressPercent = AdjustedProgressPercent;
|
float progressPercent = AdjustedProgressPercent;
|
||||||
float daysRemaining = GetRemainingDays();
|
float daysRemaining = GetRemainingDays();
|
||||||
float hoursRemaining = GetRemainingHours();
|
float hoursRemaining = GetRemainingHours();
|
||||||
|
|
||||||
if (builder.Length > 0) builder.AppendLine();
|
builder.AppendLine("正在孵化: " + incubatingPawnKind.LabelCap);
|
||||||
builder.Append("ARA_OothecaIncubator.Incubating".Translate() + ": " + incubatingPawnKind.LabelCap);
|
builder.AppendLine("进度: " + progressPercent.ToStringPercent());
|
||||||
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();
|
string timeText = "剩余时间: " + daysRemaining.ToString("F1") + " 天";
|
||||||
if (hoursRemaining > 0.1f && daysRemaining < 1f)
|
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("速度: " + SpeedMultiplier.ToStringPercent() + " | 质量: " + QualityMultiplier.ToStringPercent());
|
||||||
builder.Append("ARA_OothecaIncubator.Speed".Translate() + ": " + SpeedMultiplier.ToStringPercent() + ", " +
|
|
||||||
"ARA_OothecaIncubator.Quality".Translate() + ": " + QualityMultiplier.ToStringPercent());
|
|
||||||
}
|
}
|
||||||
else if (assignedLarva != null)
|
else if (assignedLarva != null)
|
||||||
{
|
{
|
||||||
if (builder.Length > 0) builder.AppendLine();
|
|
||||||
if (larvaOperateTicksRemaining > 0)
|
if (larvaOperateTicksRemaining > 0)
|
||||||
{
|
{
|
||||||
float secondsRemaining = larvaOperateTicksRemaining / 60f;
|
float secondsRemaining = larvaOperateTicksRemaining / 60f;
|
||||||
builder.Append("ARA_OothecaIncubator.LarvaOperating".Translate() + ": " + secondsRemaining.ToString("F1") + " " + "ARA_OothecaIncubator.SRemaining".Translate());
|
builder.Append("幼虫激活中: " + secondsRemaining.ToString("F1") + " 秒");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
builder.Append("ARA_OothecaIncubator.LarvaOnWay".Translate());
|
builder.Append("幼虫赶路中...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!isIncubating)
|
else if (!isIncubating)
|
||||||
@@ -387,16 +376,19 @@ namespace ArachnaeSwarm
|
|||||||
var config = IncubatorData?.SelectedConfig;
|
var config = IncubatorData?.SelectedConfig;
|
||||||
if (config != null)
|
if (config != null)
|
||||||
{
|
{
|
||||||
if (builder.Length > 0) builder.AppendLine();
|
builder.AppendLine("孵化目标: " + config.pawnKind.LabelCap);
|
||||||
builder.Append("ARA_OothecaIncubator.Target".Translate() + ": " + config.pawnKind.LabelCap);
|
builder.Append("速度: " + SpeedMultiplier.ToStringPercent() + " | 质量: " + QualityMultiplier.ToStringPercent());
|
||||||
|
|
||||||
// 只显示当前乘数,不显示条件详情
|
|
||||||
builder.AppendLine();
|
|
||||||
builder.Append("ARA_OothecaIncubator.SpeedMultiplier".Translate() + ": " + SpeedMultiplier.ToStringPercent() + ", " +
|
|
||||||
"ARA_OothecaIncubator.QualityMultiplier".Translate() + ": " + QualityMultiplier.ToStringPercent());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// === 第二部分:基类信息(包括维护度等) ===
|
||||||
|
var baseString = base.GetInspectString();
|
||||||
|
if (!string.IsNullOrEmpty(baseString))
|
||||||
|
{
|
||||||
|
if (builder.Length > 0) builder.AppendLine();
|
||||||
|
builder.Append(baseString);
|
||||||
|
}
|
||||||
|
|
||||||
return builder.ToString().TrimEndNewlines();
|
return builder.ToString().TrimEndNewlines();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -438,6 +430,9 @@ namespace ArachnaeSwarm
|
|||||||
// 只有玩家派系才显示Gizmo
|
// 只有玩家派系才显示Gizmo
|
||||||
if (Faction == Faction.OfPlayer)
|
if (Faction == Faction.OfPlayer)
|
||||||
{
|
{
|
||||||
|
// 始终显示双进度条Gizmo(内部会自动处理非孵化状态的显示)
|
||||||
|
yield return new Gizmo_IncubationProgress(this);
|
||||||
|
|
||||||
// 不在孵化中时才显示切换目标按钮
|
// 不在孵化中时才显示切换目标按钮
|
||||||
if (!isIncubating && IncubatorData?.IncubationConfigs?.Count > 0)
|
if (!isIncubating && IncubatorData?.IncubationConfigs?.Count > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -95,64 +95,43 @@ namespace ArachnaeSwarm
|
|||||||
return bestCell;
|
return bestCell;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改后的方法:寻找最近的播种或清理 Job
|
// 修改后的方法:寻找最近的播种或清理 Job(原版逻辑:找最近可工作格子)
|
||||||
private Job FindClosestSowableOrClearJob(Pawn pawn, WorkGiver_ArachnaeSow scanner)
|
private Job FindClosestSowableOrClearJob(Pawn pawn, WorkGiver_ArachnaeSow scanner)
|
||||||
{
|
{
|
||||||
IntVec3 bestClearCell = IntVec3.Invalid;
|
IntVec3 bestCell = IntVec3.Invalid;
|
||||||
Job bestClearJob = null;
|
Job bestJob = null;
|
||||||
float bestClearDistSq = float.MaxValue;
|
float bestDistSq = float.MaxValue;
|
||||||
|
|
||||||
IntVec3 bestSowCell = IntVec3.Invalid;
|
|
||||||
Job bestSowJob = null;
|
|
||||||
float bestSowDistSq = float.MaxValue;
|
|
||||||
|
|
||||||
foreach (Zone zone in pawn.Map.zoneManager.AllZones)
|
foreach (Zone zone in pawn.Map.zoneManager.AllZones)
|
||||||
{
|
{
|
||||||
if (zone is Zone_Growing growingZone)
|
if (zone is Zone_Growing growingZone)
|
||||||
{
|
{
|
||||||
|
// 检查种植区是否允许播种
|
||||||
|
if (!growingZone.allowSow)
|
||||||
|
continue;
|
||||||
|
|
||||||
ThingDef wantedPlant = growingZone.GetPlantDefToGrow();
|
ThingDef wantedPlant = growingZone.GetPlantDefToGrow();
|
||||||
if (wantedPlant == null) continue;
|
if (wantedPlant == null) continue;
|
||||||
|
|
||||||
foreach (IntVec3 cell in growingZone.Cells)
|
foreach (IntVec3 cell in growingZone.Cells)
|
||||||
{
|
{
|
||||||
float distSq = pawn.Position.DistanceToSquared(cell);
|
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);
|
Job potentialJob = scanner.JobOnCell(pawn, cell);
|
||||||
if (potentialJob != null)
|
if (potentialJob != null)
|
||||||
{
|
{
|
||||||
if (potentialJob.def == JobDefOf.CutPlant || potentialJob.def == JobDefOf.HaulToContainer || potentialJob.def == JobDefOf.HaulToCell)
|
// 原版逻辑:找最近的可工作格子,不区分任务类型优先级
|
||||||
{
|
bestDistSq = distSq;
|
||||||
if (distSq < bestClearDistSq)
|
bestJob = potentialJob;
|
||||||
{
|
bestCell = cell;
|
||||||
bestClearDistSq = distSq;
|
|
||||||
bestClearJob = potentialJob;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (potentialJob.def == JobDefOf.Sow)
|
|
||||||
{
|
|
||||||
if (distSq < bestSowDistSq)
|
|
||||||
{
|
|
||||||
bestSowDistSq = distSq;
|
|
||||||
bestSowJob = potentialJob;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return bestJob;
|
||||||
}
|
|
||||||
// 优先返回清理 Job
|
|
||||||
if (bestClearJob != null)
|
|
||||||
{
|
|
||||||
return bestClearJob;
|
|
||||||
}
|
|
||||||
// 其次返回播种 Job
|
|
||||||
if (bestSowJob != null)
|
|
||||||
{
|
|
||||||
return bestSowJob;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,7 +70,7 @@ namespace ArachnaeSwarm
|
|||||||
for (int i = 0; i < thingList.Count; i++)
|
for (int i = 0; i < thingList.Count; i++)
|
||||||
{
|
{
|
||||||
Thing thing = thingList[i];
|
Thing thing = thingList[i];
|
||||||
if (thing.def == wantedPlantDef)
|
if (thing.def == wantedPlantDefLocal)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -122,6 +122,10 @@ namespace ArachnaeSwarm
|
|||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (!PlantUtility.PawnWillingToCutPlant_Job(plant, pawn))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return JobMaker.MakeJob(JobDefOf.CutPlant, plant);
|
return JobMaker.MakeJob(JobDefOf.CutPlant, plant);
|
||||||
}
|
}
|
||||||
// 如果地块上的植物是我们想要种植的植物,并且它阻碍了相邻播种,则不割除
|
// 如果地块上的植物是我们想要种植的植物,并且它阻碍了相邻播种,则不割除
|
||||||
@@ -155,6 +159,10 @@ namespace ArachnaeSwarm
|
|||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (!PlantUtility.PawnWillingToCutPlant_Job(plant2, pawn))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (PlantUtility.TreeMarkedForExtraction(plant2))
|
if (PlantUtility.TreeMarkedForExtraction(plant2))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@@ -202,6 +210,10 @@ namespace ArachnaeSwarm
|
|||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (!PlantUtility.PawnWillingToCutPlant_Job(thing3, pawn))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (PlantUtility.TreeMarkedForExtraction(thing3))
|
if (PlantUtility.TreeMarkedForExtraction(thing3))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
Reference in New Issue
Block a user