feat: 新增虫群维护系统、营养网络塔及多种阿拉克涅建筑

This commit is contained in:
2025-12-25 13:57:06 +08:00
parent 1ed168a70c
commit 1473651a66
11 changed files with 233 additions and 97 deletions

View File

@@ -146,6 +146,7 @@
<Compile Include="Pawn_Comps\ARA_DratfableAnimals\CompProperties_DratfableAnimals.cs" />
<Compile Include="Pawn_Comps\ARA_SwarmMaintainer\CompProperties_SwarmMaintainer.cs" />
<Compile Include="Pawn_Comps\ARA_SwarmMaintainer\Comp_SwarmMaintainer.cs" />
<Compile Include="Building_Comps\ARA_SwarmMaintenance\Gizmo_SwarmMaintenance.cs" />
<Compile Include="Pawn_Comps\ARA_DratfableAnimals\BeastUnit.cs" />
<Compile Include="RoomRole\RoomRoleWorker_JellyVat.cs" />
<Compile Include="RoomRole\RoomRoleWorker_Incubator.cs" />

View File

@@ -90,25 +90,7 @@ namespace ArachnaeSwarm
return;
// 计算基础递减量每天递减量转换为每2500tick约0.0417天)的递减量
float baseDecayAmount = Props.maintenanceDecayPerDay * (2500f / 60000f);
// 检查是否为卵囊建筑,并根据孵化状态调整消耗
float decayMultiplier = 1f;
if (parent is Building_Ootheca ootheca)
{
if (!ootheca.IsIncubating)
{
// 未孵化时维护消耗减少80%
decayMultiplier = 0.2f;
}
else
{
// 孵化时根据活性调整(活性越高消耗越多)
decayMultiplier = 0.5f + ootheca.FluxEfficiency * 0.5f;
}
}
float decayAmount = baseDecayAmount * decayMultiplier;
float decayAmount = Props.maintenanceDecayPerDay * (2500f / 60000f);
currentMaintenance -= decayAmount;
// 确保不低于0
@@ -185,6 +167,41 @@ namespace ArachnaeSwarm
lastWarningState = false;
}
// 手动呼叫最近的维护者
public void CallMaintainer()
{
if (parent.Map == null) return;
Pawn bestPawn = null;
float minDist = float.MaxValue;
foreach (Pawn pawn in parent.Map.mapPawns.FreeColonistsSpawned)
{
var maintainerComp = pawn.TryGetComp<Comp_SwarmMaintainer>();
if (maintainerComp != null && !pawn.Downed && !pawn.Dead &&
pawn.CanReserveAndReach(parent, PathEndMode.Touch, Danger.Some))
{
float dist = pawn.Position.DistanceToSquared(parent.Position);
if (dist < minDist)
{
minDist = dist;
bestPawn = pawn;
}
}
}
if (bestPawn != null)
{
Job job = JobMaker.MakeJob(ARA_JobDefOf.ARA_SwarmMaintain, parent);
bestPawn.jobs.TryTakeOrderedJob(job, JobTag.Misc);
Messages.Message("ARA_Msg_MaintainerCalled".Translate(bestPawn.LabelShort), parent, MessageTypeDefOf.PositiveEvent);
}
else
{
Messages.Message("ARA_Msg_NoMaintainerAvailable".Translate(), MessageTypeDefOf.RejectInput);
}
}
// 获取可维护的优先级用于WorkGiver排序
public float GetMaintenancePriority()
{
@@ -220,33 +237,21 @@ namespace ArachnaeSwarm
return text;
}
// 获取实际每日消耗(考虑孵化活性)
// 获取实际每日消耗
private float GetActualDecayPerDay()
{
float baseDecay = Props.maintenanceDecayPerDay;
float multiplier = 1f;
if (parent is Building_Ootheca ootheca)
{
if (!ootheca.IsIncubating)
{
multiplier = 0.2f;
}
else
{
multiplier = 0.5f + ootheca.FluxEfficiency * 0.5f;
}
}
return baseDecay * multiplier;
return Props.maintenanceDecayPerDay;
}
// 获取Gizmos命令按钮- 只保留调试功能
// 获取Gizmos命令按钮
public override IEnumerable<Gizmo> CompGetGizmosExtra()
{
// 只在玩家控制下显示
if (parent.Faction?.IsPlayer == true)
{
// 维护度计量条
yield return new Gizmo_SwarmMaintenance(this);
// 调试按钮 - 仅在GodMode下显示
if (DebugSettings.godMode)
{

View File

@@ -0,0 +1,146 @@
// File: Gizmo_SwarmMaintenance.cs
// 虫群建筑维护度计量条 Gizmo
using UnityEngine;
using Verse;
namespace ArachnaeSwarm
{
[StaticConstructorOnStartup]
public class Gizmo_SwarmMaintenance : Gizmo
{
private readonly Comp_SwarmMaintenance comp;
private readonly Thing parentThing;
// 尺寸常量
private const float Width = 140f;
private const float GizmoHeight = 75f;
private const float Padding = 6f;
private const float BarHeight = 18f;
// 材质颜色
private static readonly Texture2D FullBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.2f, 0.8f, 0.3f, 0.9f));
private static readonly Texture2D MediumBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.9f, 0.7f, 0.2f, 0.9f));
private static readonly Texture2D LowBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.9f, 0.3f, 0.2f, 0.9f));
private static readonly Texture2D EmptyBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.15f, 0.15f, 0.15f, 0.8f));
public Gizmo_SwarmMaintenance(Comp_SwarmMaintenance comp)
{
this.comp = comp;
this.parentThing = comp.parent;
Order = -120f; // 在活性和进度条之后,交互按钮之前
}
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;
// === 第一行:标题 + 按钮 ===
Text.Font = GameFont.Small;
Text.Anchor = TextAnchor.MiddleLeft;
GUI.color = Color.white;
Rect titleRect = new Rect(innerRect.x, curY, innerRect.width - 26f, 18f);
Widgets.Label(titleRect, "ARA_SwarmMaintenance_Title".Translate());
// 右上角呼叫按钮
Rect btnRect = new Rect(innerRect.xMax - 20f, curY - 1f, 20f, 20f);
if (Widgets.ButtonImage(btnRect, ContentFinder<Texture2D>.Get("ArachnaeSwarm/UI/Commands/ARA_CallLarva", false)))
{
comp.CallMaintainer();
}
TooltipHandler.TipRegion(btnRect, "ARA_Gizmo_CallMaintainer".Translate());
curY += 20f;
// === 第二行:消耗信息 ===
Text.Font = GameFont.Tiny;
Text.Anchor = TextAnchor.MiddleLeft;
GUI.color = new Color(0.7f, 0.7f, 0.7f);
Rect decayRect = new Rect(innerRect.x, curY, innerRect.width, 14f);
string decayText = "ARA_SwarmMaintenance_DailyDecay_Short".Translate(comp.Props.maintenanceDecayPerDay.ToString("F1"));
Widgets.Label(decayRect, decayText);
curY += 15f;
// === 第三行:进度条 ===
float percentage = comp.MaintenancePercentage;
Rect barRect = new Rect(innerRect.x, curY, innerRect.width, BarHeight);
// 背景
GUI.color = Color.white;
GUI.DrawTexture(barRect, EmptyBarTex);
// 根据百分比选择颜色
Texture2D barTex;
if (percentage > 0.6f)
barTex = FullBarTex;
else if (percentage > 0.3f)
barTex = MediumBarTex;
else
barTex = LowBarTex;
// 填充条
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;
Widgets.Label(barRect, percentage.ToStringPercent());
// === 工具提示 ===
Rect tooltipRect = new Rect(rect.x, rect.y, rect.width, rect.height);
tooltipRect.xMax -= 24f; // 排除按钮区域
if (Mouse.IsOver(tooltipRect))
{
Widgets.DrawHighlight(rect);
TooltipHandler.TipRegion(tooltipRect, 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();
sb.AppendLine("ARA_SwarmMaintenance_TooltipTitle".Translate());
sb.AppendLine();
sb.AppendLine("ARA_SwarmMaintenance_TooltipCurrent".Translate(
comp.CurrentMaintenance.ToString("F1"),
comp.MaxMaintenance.ToString("F1")));
sb.AppendLine("ARA_SwarmMaintenance_TooltipDecay".Translate(comp.Props.maintenanceDecayPerDay.ToString("F1")));
sb.AppendLine();
if (comp.IsCritical)
{
sb.AppendLine("<color=orange>" + "ARA_SwarmMaintenance_TooltipCritical".Translate() + "</color>");
}
else if (comp.NeedsMaintenance)
{
sb.AppendLine("<color=yellow>" + "ARA_SwarmMaintenance_TooltipNeedsMaintenance".Translate() + "</color>");
}
else
{
sb.AppendLine("<color=green>" + "ARA_SwarmMaintenance_TooltipGood".Translate() + "</color>");
}
sb.AppendLine();
sb.AppendLine("ARA_SwarmMaintenance_TooltipHint".Translate());
return sb.ToString().TrimEndNewlines();
}
}
}