feat: 为燃料补充槽添加收容失效自毁系统和Pawn追踪功能
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -109,6 +109,36 @@
|
||||
</deathAction>
|
||||
</race>
|
||||
<comps>
|
||||
<li Class="ArachnaeSwarm.CompProperties_AdvancedTraining">
|
||||
<trainables>
|
||||
<li>
|
||||
<trainable>Obedience</trainable>
|
||||
<trainInstantly>true</trainInstantly>
|
||||
<setWanted>true</setWanted>
|
||||
</li>
|
||||
<li>
|
||||
<trainable>Release</trainable>
|
||||
<trainInstantly>true</trainInstantly>
|
||||
<setWanted>true</setWanted>
|
||||
</li>
|
||||
<li>
|
||||
<trainable>Rescue</trainable>
|
||||
<trainInstantly>true</trainInstantly>
|
||||
<setWanted>true</setWanted>
|
||||
</li>
|
||||
<li>
|
||||
<trainable>Tameness</trainable>
|
||||
<trainInstantly>true</trainInstantly>
|
||||
<setWanted>true</setWanted>
|
||||
</li>
|
||||
<li>
|
||||
<trainable>Haul</trainable>
|
||||
<trainInstantly>true</trainInstantly>
|
||||
<setWanted>true</setWanted>
|
||||
</li>
|
||||
</trainables>
|
||||
<disableAllSkillDecay>true</disableAllSkillDecay> <!-- 阻止这个动物的所有技能衰减 -->
|
||||
</li>
|
||||
<li Class="ArachnaeSwarm.CompProperties_HediffGiver">
|
||||
<hediffs>
|
||||
<li>ARA_HiveMindWorker</li>
|
||||
|
||||
@@ -41,4 +41,19 @@
|
||||
<ResearchManager_TotalBuildings>所有建筑:{0}</ResearchManager_TotalBuildings>
|
||||
<ResearchManager_ActiveResearch>进行中研究:{0}</ResearchManager_ActiveResearch>
|
||||
<ResearchManager_ProjectStatus>{0}:{1}个活跃建筑 / {2}个总建筑</ResearchManager_ProjectStatus>
|
||||
|
||||
<!-- Gizmo_ResearchProgress.cs -->
|
||||
<ARA_ResearchProgress_NoProject>未选择项目</ARA_ResearchProgress_NoProject>
|
||||
<ARA_ResearchProgress_Completed>✓ 研究完成</ARA_ResearchProgress_Completed>
|
||||
<ARA_ResearchProgress_Researching>⚡ 研究中...</ARA_ResearchProgress_Researching>
|
||||
<ARA_ResearchProgress_Paused>⏸ 已暂停</ARA_ResearchProgress_Paused>
|
||||
<ARA_ResearchProgress_SelectProject>点击选择项目</ARA_ResearchProgress_SelectProject>
|
||||
<ARA_ResearchProgress_TooltipTitle>【研究蓝图解读器】</ARA_ResearchProgress_TooltipTitle>
|
||||
<ARA_ResearchProgress_TooltipProject>当前项目:{0}</ARA_ResearchProgress_TooltipProject>
|
||||
<ARA_ResearchProgress_TooltipProgress>进度:{0} / {1}</ARA_ResearchProgress_TooltipProgress>
|
||||
<ARA_ResearchProgress_TooltipPercentage>完成度:{0}</ARA_ResearchProgress_TooltipPercentage>
|
||||
<ARA_ResearchProgress_TooltipCompleted>研究已完成!</ARA_ResearchProgress_TooltipCompleted>
|
||||
<ARA_ResearchProgress_TooltipTimeRemaining>预计剩余时间:{0}</ARA_ResearchProgress_TooltipTimeRemaining>
|
||||
<ARA_ResearchProgress_TooltipPaused>研究已暂停(无电力或其他原因)</ARA_ResearchProgress_TooltipPaused>
|
||||
<ARA_ResearchProgress_TooltipNoProject>尚未选择研究项目。\n点击"选择研究项目"按钮开始。</ARA_ResearchProgress_TooltipNoProject>
|
||||
</LanguageData>
|
||||
|
||||
@@ -572,7 +572,8 @@ namespace ArachnaeSwarm
|
||||
{
|
||||
yield return gizmo;
|
||||
}
|
||||
// 选择殖民者的操作
|
||||
|
||||
// 合并后的统一按钮:选择人员
|
||||
var command_Action = new Command_Action
|
||||
{
|
||||
defaultLabel = "InsertPerson".Translate() + "...",
|
||||
@@ -583,10 +584,17 @@ namespace ArachnaeSwarm
|
||||
List<FloatMenuOption> list = new List<FloatMenuOption>();
|
||||
foreach (Pawn p in base.Map.mapPawns.AllPawnsSpawned)
|
||||
{
|
||||
if (p != null && !p.Destroyed && CanAcceptPawn(p).Accepted)
|
||||
{
|
||||
list.Add(new FloatMenuOption(p.LabelCap, () => SelectPawn(p), p, Color.white));
|
||||
}
|
||||
if (p == null || p.Destroyed || !CanAcceptPawn(p).Accepted)
|
||||
continue;
|
||||
|
||||
// 根据 pawn 类型显示不同的标签
|
||||
string label = p.LabelCap;
|
||||
if (p.IsPrisonerOfColony)
|
||||
label += " (" + "Prisoner".Translate() + ")";
|
||||
else if (p.IsSlaveOfColony)
|
||||
label += " (" + "Slave".Translate() + ")";
|
||||
|
||||
list.Add(new FloatMenuOption(label, () => HandlePawnSelection(p), p, Color.white));
|
||||
}
|
||||
if (!list.Any())
|
||||
{
|
||||
@@ -600,49 +608,26 @@ namespace ArachnaeSwarm
|
||||
command_Action.Disable("NoViablePawns".Translate());
|
||||
}
|
||||
yield return command_Action;
|
||||
|
||||
// 指派搬运囚犯/奴隶的操作
|
||||
var command_CarryPrisoner = new Command_Action
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理 pawn 选择:如果是殖民者则直接走进去,如果是囚犯/奴隶则显示搬运者选择菜单
|
||||
/// </summary>
|
||||
private void HandlePawnSelection(Pawn pawn)
|
||||
{
|
||||
if (pawn == null || pawn.Destroyed)
|
||||
return;
|
||||
|
||||
// 如果是囚犯或奴隶,需要选择搬运者
|
||||
if (pawn.IsPrisonerOfColony || pawn.IsSlaveOfColony)
|
||||
{
|
||||
defaultLabel = "AssignCarryPrisoner".Translate() + "...",
|
||||
defaultDesc = "AssignCarryPrisonerDesc".Translate(),
|
||||
icon = ContentFinder<Texture2D>.Get("UI/Commands/Attack"),
|
||||
action = () =>
|
||||
{
|
||||
List<FloatMenuOption> list = new List<FloatMenuOption>();
|
||||
|
||||
// 获取所有可接受的囚犯和奴隶
|
||||
foreach (Pawn p in base.Map.mapPawns.AllPawnsSpawned)
|
||||
{
|
||||
if (p != null && !p.Destroyed && CanAcceptPawn(p).Accepted && (p.IsPrisonerOfColony || p.IsSlaveOfColony))
|
||||
{
|
||||
list.Add(new FloatMenuOption(
|
||||
p.LabelCap + " (" + (p.IsPrisonerOfColony ? "Prisoner" : "Slave") + ")",
|
||||
() => AssignCarrierForPrisoner(p),
|
||||
p,
|
||||
Color.white
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if (!list.Any())
|
||||
{
|
||||
list.Add(new FloatMenuOption("NoPrisonersOrSlaves".Translate(), null));
|
||||
}
|
||||
Find.WindowStack.Add(new FloatMenu(list));
|
||||
}
|
||||
};
|
||||
|
||||
// 检查是否有可用的囚犯/奴隶
|
||||
bool hasPrisonersOrSlaves = base.Map.mapPawns.AllPawnsSpawned
|
||||
.Any(p => p != null && !p.Destroyed && CanAcceptPawn(p).Accepted && (p.IsPrisonerOfColony || p.IsSlaveOfColony));
|
||||
|
||||
if (!hasPrisonersOrSlaves)
|
||||
{
|
||||
command_CarryPrisoner.Disable("NoPrisonersOrSlaves".Translate());
|
||||
AssignCarrierForPrisoner(pawn);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 殖民者可以自己走进去
|
||||
SelectPawn(pawn);
|
||||
}
|
||||
|
||||
yield return command_CarryPrisoner;
|
||||
}
|
||||
|
||||
public override string GetInspectString()
|
||||
|
||||
@@ -249,6 +249,9 @@ namespace ArachnaeSwarm
|
||||
yield return gizmo;
|
||||
}
|
||||
|
||||
// 研究进度 Gizmo
|
||||
yield return new Gizmo_ResearchProgress(this);
|
||||
|
||||
// 选择研究按钮
|
||||
var selectCmd = new Command_Action();
|
||||
selectCmd.defaultLabel = "ResearchBlueprintReader_SelectProject".Translate();
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
// File: Gizmo_ResearchProgress.cs
|
||||
// 研究蓝图解读器的研究进度 Gizmo
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
[StaticConstructorOnStartup]
|
||||
public class Gizmo_ResearchProgress : Gizmo
|
||||
{
|
||||
private readonly Building_ResearchBlueprintReader reader;
|
||||
|
||||
// 尺寸常量
|
||||
private const float Width = 180f;
|
||||
private const float GizmoHeight = 75f;
|
||||
private const float Padding = 6f;
|
||||
private const float BarHeight = 18f;
|
||||
|
||||
// 材质颜色
|
||||
private static readonly Texture2D ProgressBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.3f, 0.6f, 0.9f, 0.9f));
|
||||
private static readonly Texture2D CompletedBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.2f, 0.8f, 0.3f, 0.9f));
|
||||
private static readonly Texture2D PausedBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.7f, 0.7f, 0.3f, 0.9f));
|
||||
private static readonly Texture2D EmptyBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.15f, 0.15f, 0.15f, 0.8f));
|
||||
|
||||
public Gizmo_ResearchProgress(Building_ResearchBlueprintReader reader)
|
||||
{
|
||||
this.reader = reader;
|
||||
Order = -130f; // 在其他 Gizmo 之后
|
||||
}
|
||||
|
||||
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, GetWidth(maxWidth), GizmoHeight);
|
||||
Widgets.DrawWindowBackground(rect);
|
||||
|
||||
Rect innerRect = rect.ContractedBy(Padding);
|
||||
float curY = innerRect.y;
|
||||
|
||||
var storedResearch = reader.StoredResearch;
|
||||
|
||||
// === 第一行:标题 ===
|
||||
Text.Font = GameFont.Small;
|
||||
Text.Anchor = TextAnchor.MiddleLeft;
|
||||
GUI.color = Color.white;
|
||||
Rect titleRect = new Rect(innerRect.x, curY, innerRect.width, 18f);
|
||||
|
||||
string title;
|
||||
if (storedResearch != null)
|
||||
{
|
||||
title = storedResearch.LabelCap.RawText ?? storedResearch.defName;
|
||||
// 截断过长的标题
|
||||
title = title.Truncate(innerRect.width - 4f);
|
||||
}
|
||||
else
|
||||
{
|
||||
title = "ARA_ResearchProgress_NoProject".Translate();
|
||||
}
|
||||
Widgets.Label(titleRect, title);
|
||||
curY += 20f;
|
||||
|
||||
// === 第二行:状态信息 ===
|
||||
Text.Font = GameFont.Tiny;
|
||||
Text.Anchor = TextAnchor.MiddleLeft;
|
||||
Rect statusRect = new Rect(innerRect.x, curY, innerRect.width, 14f);
|
||||
|
||||
if (storedResearch != null)
|
||||
{
|
||||
string statusText;
|
||||
if (storedResearch.IsFinished)
|
||||
{
|
||||
GUI.color = new Color(0.3f, 0.9f, 0.3f);
|
||||
statusText = "ARA_ResearchProgress_Completed".Translate();
|
||||
}
|
||||
else if (reader.IsResearching)
|
||||
{
|
||||
GUI.color = new Color(0.5f, 0.8f, 1f);
|
||||
statusText = "ARA_ResearchProgress_Researching".Translate();
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.color = new Color(0.9f, 0.7f, 0.2f);
|
||||
statusText = "ARA_ResearchProgress_Paused".Translate();
|
||||
}
|
||||
Widgets.Label(statusRect, statusText);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.color = new Color(0.5f, 0.5f, 0.5f);
|
||||
Widgets.Label(statusRect, "ARA_ResearchProgress_SelectProject".Translate());
|
||||
}
|
||||
curY += 15f;
|
||||
|
||||
// === 第三行:进度条 ===
|
||||
GUI.color = Color.white;
|
||||
Rect barRect = new Rect(innerRect.x, curY, innerRect.width, BarHeight);
|
||||
|
||||
// 背景
|
||||
GUI.DrawTexture(barRect, EmptyBarTex);
|
||||
|
||||
if (storedResearch != null)
|
||||
{
|
||||
float percentage = storedResearch.baseCost > 0
|
||||
? Mathf.Clamp01(reader.Progress / storedResearch.baseCost)
|
||||
: 0f;
|
||||
|
||||
// 根据状态选择颜色
|
||||
Texture2D barTex;
|
||||
if (storedResearch.IsFinished)
|
||||
barTex = CompletedBarTex;
|
||||
else if (reader.IsResearching)
|
||||
barTex = ProgressBarTex;
|
||||
else
|
||||
barTex = PausedBarTex;
|
||||
|
||||
// 填充条
|
||||
Rect fillRect = new Rect(barRect.x, barRect.y, barRect.width * percentage, barRect.height);
|
||||
GUI.DrawTexture(fillRect, barTex);
|
||||
|
||||
// 百分比文字
|
||||
Text.Font = GameFont.Tiny;
|
||||
Text.Anchor = TextAnchor.MiddleCenter;
|
||||
GUI.color = Color.white;
|
||||
|
||||
string progressText = $"{reader.Progress:F0} / {storedResearch.baseCost:F0}";
|
||||
Widgets.Label(barRect, progressText);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 无项目时显示空状态
|
||||
Text.Font = GameFont.Tiny;
|
||||
Text.Anchor = TextAnchor.MiddleCenter;
|
||||
GUI.color = new Color(0.5f, 0.5f, 0.5f);
|
||||
Widgets.Label(barRect, "---");
|
||||
}
|
||||
|
||||
// === 工具提示 ===
|
||||
if (Mouse.IsOver(rect))
|
||||
{
|
||||
Widgets.DrawHighlight(rect);
|
||||
TooltipHandler.TipRegion(rect, GetTooltip());
|
||||
}
|
||||
|
||||
GUI.color = Color.white;
|
||||
Text.Anchor = TextAnchor.UpperLeft;
|
||||
Text.Font = GameFont.Small;
|
||||
|
||||
return new GizmoResult(GizmoState.Clear);
|
||||
}
|
||||
|
||||
private string GetTooltip()
|
||||
{
|
||||
var sb = new System.Text.StringBuilder();
|
||||
var storedResearch = reader.StoredResearch;
|
||||
|
||||
sb.AppendLine("ARA_ResearchProgress_TooltipTitle".Translate());
|
||||
sb.AppendLine();
|
||||
|
||||
if (storedResearch != null)
|
||||
{
|
||||
sb.AppendLine("ARA_ResearchProgress_TooltipProject".Translate(storedResearch.LabelCap));
|
||||
sb.AppendLine("ARA_ResearchProgress_TooltipProgress".Translate(
|
||||
reader.Progress.ToString("F0"),
|
||||
storedResearch.baseCost.ToString("F0")));
|
||||
|
||||
float percentage = storedResearch.baseCost > 0
|
||||
? reader.Progress / storedResearch.baseCost
|
||||
: 0f;
|
||||
sb.AppendLine("ARA_ResearchProgress_TooltipPercentage".Translate(percentage.ToStringPercent()));
|
||||
sb.AppendLine();
|
||||
|
||||
if (storedResearch.IsFinished)
|
||||
{
|
||||
sb.AppendLine("<color=green>" + "ARA_ResearchProgress_TooltipCompleted".Translate() + "</color>");
|
||||
}
|
||||
else if (reader.IsResearching)
|
||||
{
|
||||
// 计算剩余时间
|
||||
float remaining = storedResearch.baseCost - reader.Progress;
|
||||
var ext = reader.def.GetModExtension<ResearchBlueprintReaderExtension>();
|
||||
float speed = ext?.researchSpeed ?? 10f;
|
||||
int ticksRemaining = Mathf.CeilToInt(remaining / speed * 60f);
|
||||
string timeStr = ticksRemaining.ToStringTicksToPeriod(allowSeconds: true, shortForm: true);
|
||||
|
||||
sb.AppendLine("<color=#88ccff>" + "ARA_ResearchProgress_TooltipTimeRemaining".Translate(timeStr) + "</color>");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine("<color=yellow>" + "ARA_ResearchProgress_TooltipPaused".Translate() + "</color>");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine("ARA_ResearchProgress_TooltipNoProject".Translate());
|
||||
}
|
||||
|
||||
return sb.ToString().TrimEndNewlines();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user