zc
This commit is contained in:
@@ -118,9 +118,11 @@
|
||||
<Compile Include="Buildings\Building_DormancyVat\DefModExtension_DormancyVat.cs" />
|
||||
<Compile Include="Buildings\Building_EquipmentOotheca\Building_EquipmentOotheca.cs" />
|
||||
<Compile Include="Buildings\Building_EquipmentOotheca\CompProperties_EquipmentIncubatorData.cs" />
|
||||
<Compile Include="Buildings\Building_EquipmentOotheca\Gizmo_EquipmentIncubationProgress.cs" />
|
||||
<Compile Include="Buildings\Building_EquipmentOotheca\ITab_EquipmentOotheca_Incubation.cs" />
|
||||
<Compile Include="Buildings\Building_EquipmentOotheca\JobDriver_OperateEquipmentIncubator.cs" />
|
||||
<Compile Include="Buildings\Building_Incubatable.cs" />
|
||||
<Compile Include="Buildings\IFluxController.cs" />
|
||||
<Compile Include="Buildings\Building_Ootheca\Building_Ootheca.cs" />
|
||||
<Compile Include="Buildings\Building_Ootheca\CompProperties_IncubatorData.cs" />
|
||||
<Compile Include="Buildings\Building_Ootheca\Gizmo_IncubationProgress.cs" />
|
||||
|
||||
@@ -8,7 +8,7 @@ using System;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class Building_EquipmentOotheca : Building
|
||||
public class Building_EquipmentOotheca : Building, IFluxController
|
||||
{
|
||||
// 引用组件
|
||||
public CompEquipmentIncubatorData EquipmentIncubatorData => this.TryGetComp<CompEquipmentIncubatorData>();
|
||||
@@ -33,27 +33,75 @@ namespace ArachnaeSwarm
|
||||
private float qualityProgress = 0f;
|
||||
private float qualityTotal = 0f;
|
||||
|
||||
// === 简化后的营养液系统:只用于速度加成,不消耗 ===
|
||||
private int totalNutrientCost = 0; // 总共需要的营养液地块数量(仅用于信息显示)
|
||||
private int currentNutrientCount = 0; // 当前周围存在的营养液数量
|
||||
// ======= 孵化活性系统 =======
|
||||
private float neutronFlux = 0.5f; // 0-1, 默认50%
|
||||
private FluxMode fluxMode = FluxMode.Balance; // 默认平衡模式
|
||||
private CompRefuelableNutrition fuelComp; // 燃料组件缓存
|
||||
private Comp_SwarmMaintenance maintenanceComp; // 维护组件缓存
|
||||
|
||||
// 缓存的ModExtension
|
||||
private OothecaIncubatorExtension cachedExtension;
|
||||
// 孵化活性公开属性
|
||||
public float NeutronFlux => isIncubating ? neutronFlux : 0f;
|
||||
public float RawFlux => neutronFlux;
|
||||
public FluxMode CurrentFluxMode => fluxMode;
|
||||
public bool IsAutoMode => fluxMode != FluxMode.Manual;
|
||||
public bool IsIncubating => isIncubating;
|
||||
|
||||
// 获取ModExtension的辅助属性
|
||||
public OothecaIncubatorExtension Ext
|
||||
// 获取燃料组件
|
||||
public CompRefuelableNutrition FuelComp => fuelComp ?? (fuelComp = this.TryGetComp<CompRefuelableNutrition>());
|
||||
public Comp_SwarmMaintenance MaintenanceComp => maintenanceComp ?? (maintenanceComp = this.TryGetComp<Comp_SwarmMaintenance>());
|
||||
|
||||
// 孵化活性效率曲线(非线性:flux²)
|
||||
public float FluxEfficiency => NeutronFlux * NeutronFlux;
|
||||
|
||||
// 是否处于休眠状态
|
||||
public bool IsDormant => NeutronFlux < 0.01f || (FuelComp != null && !FuelComp.HasFuel);
|
||||
|
||||
// 设置活性值
|
||||
public void SetNeutronFlux(float value)
|
||||
{
|
||||
get
|
||||
neutronFlux = Mathf.Clamp01(value);
|
||||
}
|
||||
|
||||
// 切换模式
|
||||
public void CycleFluxMode()
|
||||
{
|
||||
fluxMode = (FluxMode)(((int)fluxMode + 1) % 4);
|
||||
}
|
||||
|
||||
public void SetFluxMode(FluxMode mode)
|
||||
{
|
||||
fluxMode = mode;
|
||||
}
|
||||
|
||||
public string GetModeName()
|
||||
{
|
||||
switch (fluxMode)
|
||||
{
|
||||
if (cachedExtension == null)
|
||||
{
|
||||
cachedExtension = def.GetModExtension<OothecaIncubatorExtension>() ?? OothecaIncubatorExtension.Default;
|
||||
}
|
||||
return cachedExtension;
|
||||
case FluxMode.Manual: return "手动";
|
||||
case FluxMode.Quality: return "品质";
|
||||
case FluxMode.Balance: return "平衡";
|
||||
case FluxMode.Speed: return "速度";
|
||||
default: return "?";
|
||||
}
|
||||
}
|
||||
|
||||
// 属性访问器
|
||||
public string GetModeShort()
|
||||
{
|
||||
switch (fluxMode)
|
||||
{
|
||||
case FluxMode.Manual: return "M";
|
||||
case FluxMode.Quality: return "Q";
|
||||
case FluxMode.Balance: return "B";
|
||||
case FluxMode.Speed: return "S";
|
||||
default: return "?";
|
||||
}
|
||||
}
|
||||
|
||||
// 孵化进度百分比(给 Gizmo 用)
|
||||
public float IncubationProgress => incubationDuration > 0 ? incubationProgress / incubationDuration : 0f;
|
||||
public float QualityPercent => qualityTotal > 0 ? qualityProgress / qualityTotal : 0f;
|
||||
|
||||
// 速度乘数
|
||||
public float SpeedMultiplier
|
||||
{
|
||||
get
|
||||
@@ -69,21 +117,27 @@ namespace ArachnaeSwarm
|
||||
// 质量属性
|
||||
public float QualityMultiplier => qualityMultiplier;
|
||||
public float QualityProgress => qualityProgress;
|
||||
public float QualityPercent => qualityTotal > 0 ? qualityProgress / qualityTotal : 0f;
|
||||
|
||||
// 营养液加成属性
|
||||
public int CurrentNutrientCount => currentNutrientCount;
|
||||
public float NutrientSpeedBonus => currentNutrientCount * Ext.nutrientSolutionBonusPerTile;
|
||||
// 临时保留:营养液相关字段(后续清理)
|
||||
private int totalNutrientCost = 0;
|
||||
private int currentNutrientCount = 0;
|
||||
private OothecaIncubatorExtension cachedExtension;
|
||||
|
||||
// 进度百分比
|
||||
public float AdjustedProgressPercent
|
||||
public OothecaIncubatorExtension Ext
|
||||
{
|
||||
get
|
||||
{
|
||||
if (incubationDuration <= 0) return 0f;
|
||||
return incubationProgress / incubationDuration;
|
||||
if (cachedExtension == null)
|
||||
cachedExtension = def.GetModExtension<OothecaIncubatorExtension>() ?? OothecaIncubatorExtension.Default;
|
||||
return cachedExtension;
|
||||
}
|
||||
}
|
||||
|
||||
// 营养液速度加成(临时保留)
|
||||
public float NutrientSpeedBonus => currentNutrientCount * Ext.nutrientSolutionBonusPerTile;
|
||||
|
||||
// 进度百分比
|
||||
public float AdjustedProgressPercent => incubationDuration > 0 ? incubationProgress / incubationDuration : 0f;
|
||||
|
||||
// === 简化的初始化营养液方法 ===
|
||||
private void InitializeNutrientInfo()
|
||||
@@ -108,7 +162,7 @@ namespace ArachnaeSwarm
|
||||
UpdateNutrientCount();
|
||||
}
|
||||
|
||||
// === 简化的Tick方法 ===
|
||||
// === Tick方法(带活性系统)===
|
||||
protected override void Tick()
|
||||
{
|
||||
base.Tick();
|
||||
@@ -126,12 +180,45 @@ namespace ArachnaeSwarm
|
||||
UpdateSpeedMultiplier();
|
||||
UpdateQualityMultiplier();
|
||||
}
|
||||
|
||||
float currentSpeed = SpeedMultiplier;
|
||||
|
||||
// 始终增加进度(不再有营养液不足的暂停)
|
||||
incubationProgress += currentSpeed;
|
||||
qualityProgress += currentSpeed * QualityMultiplier;
|
||||
|
||||
// 自动模式计算
|
||||
if (IsAutoMode && Find.TickManager.TicksGame % 250 == 0)
|
||||
{
|
||||
CalculateAutoFlux();
|
||||
}
|
||||
|
||||
// 消耗虫蜜(基于孵化活性)
|
||||
if (FuelComp != null && neutronFlux > 0.01f)
|
||||
{
|
||||
float fuelPerTick = (50f * FluxEfficiency) / 60000f;
|
||||
FuelComp.ConsumeFuel(fuelPerTick);
|
||||
}
|
||||
|
||||
// 休眠状态处理
|
||||
if (IsDormant)
|
||||
{
|
||||
// 休眠时品质下降(10%/天)
|
||||
float qualityDecay = (qualityTotal * 0.1f) / 60000f;
|
||||
qualityProgress = Mathf.Max(0f, qualityProgress - qualityDecay);
|
||||
|
||||
if (qualityProgress <= 0 && qualityTotal > 0)
|
||||
{
|
||||
Messages.Message("制造舱因品质归零而损坏!", this, MessageTypeDefOf.NegativeEvent);
|
||||
Destroy(DestroyMode.KillFinalize);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 正常状态:应用活性效率
|
||||
float fluxSpeed = SpeedMultiplier * FluxEfficiency * 5f;
|
||||
incubationProgress += fluxSpeed;
|
||||
|
||||
// 品质独立增长
|
||||
float qualityBonus = 1f + (1f - neutronFlux) * 0.5f;
|
||||
float qualityGain = SpeedMultiplier * QualityMultiplier * qualityBonus;
|
||||
qualityProgress = Mathf.Min(qualityProgress + qualityGain, qualityTotal);
|
||||
}
|
||||
|
||||
if (incubationProgress >= incubationDuration)
|
||||
{
|
||||
@@ -139,6 +226,57 @@ namespace ArachnaeSwarm
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 自动模式算法
|
||||
private void CalculateAutoFlux()
|
||||
{
|
||||
if (fluxMode == FluxMode.Manual) return;
|
||||
|
||||
float targetFlux = 0.5f;
|
||||
float incubationPercent = incubationDuration > 0 ? incubationProgress / incubationDuration : 0f;
|
||||
float qualityPercent = qualityTotal > 0 ? qualityProgress / qualityTotal : 0f;
|
||||
float gap = qualityPercent - incubationPercent;
|
||||
|
||||
switch (fluxMode)
|
||||
{
|
||||
case FluxMode.Quality:
|
||||
if (qualityPercent >= 0.98f) targetFlux = 1.0f;
|
||||
else if (gap > 0.2f) targetFlux = 0.6f;
|
||||
else if (gap > 0.1f) targetFlux = 0.45f;
|
||||
else if (gap > 0f) targetFlux = 0.35f;
|
||||
else targetFlux = 0.2f;
|
||||
break;
|
||||
|
||||
case FluxMode.Speed:
|
||||
if (qualityPercent >= 0.95f) targetFlux = 1.0f;
|
||||
else if (qualityPercent < 0.3f && incubationPercent > 0.5f) targetFlux = 0.7f;
|
||||
else if (qualityPercent < 0.2f && incubationPercent > 0.7f) targetFlux = 0.5f;
|
||||
else targetFlux = 1.0f;
|
||||
break;
|
||||
|
||||
case FluxMode.Balance:
|
||||
default:
|
||||
if (qualityPercent >= 0.95f) targetFlux = 1.0f;
|
||||
else if (gap > 0.15f) targetFlux = 0.8f;
|
||||
else if (gap > 0.05f) targetFlux = 0.6f;
|
||||
else if (gap > -0.05f) targetFlux = 0.5f;
|
||||
else if (gap > -0.15f) targetFlux = 0.35f;
|
||||
else targetFlux = 0.2f;
|
||||
break;
|
||||
}
|
||||
|
||||
// 资源保护
|
||||
if (FuelComp != null && FuelComp.Fuel < 2f)
|
||||
targetFlux = Mathf.Min(targetFlux, 0.2f);
|
||||
if (MaintenanceComp != null && MaintenanceComp.CurrentMaintenance / MaintenanceComp.Props.maxMaintenance < 0.15f)
|
||||
targetFlux = Mathf.Min(targetFlux, 0.15f);
|
||||
|
||||
// 平滑调节
|
||||
float adjustSpeed = 0.03f;
|
||||
if (neutronFlux < targetFlux) neutronFlux = Mathf.Min(neutronFlux + adjustSpeed, targetFlux);
|
||||
else if (neutronFlux > targetFlux) neutronFlux = Mathf.Max(neutronFlux - adjustSpeed, targetFlux);
|
||||
neutronFlux = Mathf.Clamp(neutronFlux, 0.1f, 1.0f);
|
||||
}
|
||||
|
||||
// === 获取速度因子描述 ===
|
||||
public string GetSpeedFactorsDescription()
|
||||
@@ -565,18 +703,30 @@ namespace ArachnaeSwarm
|
||||
// === Gizmos ===
|
||||
public override IEnumerable<Gizmo> GetGizmos()
|
||||
{
|
||||
// 过滤掉拆除按钮和半径显示
|
||||
foreach (var gizmo in base.GetGizmos())
|
||||
{
|
||||
// 跳过拆除和半径相关的 Gizmo
|
||||
if (gizmo is Command_Action cmd && cmd.defaultLabel != null)
|
||||
{
|
||||
string label = cmd.defaultLabel.ToString();
|
||||
if (label.Contains("拆除") || label.Contains("Deconstruct") ||
|
||||
label.Contains("半径") || label.Contains("Radius"))
|
||||
continue;
|
||||
}
|
||||
yield return gizmo;
|
||||
}
|
||||
|
||||
// 只有玩家派系才显示Gizmo
|
||||
if (Faction == Faction.OfPlayer)
|
||||
{
|
||||
if (!isIncubating && EquipmentIncubatorData?.IncubationConfigs?.Count > 0)
|
||||
{
|
||||
yield return CreateTargetSwitchGizmo();
|
||||
}
|
||||
// 始终显示双进度条Gizmo
|
||||
yield return new Gizmo_EquipmentIncubationProgress(this);
|
||||
|
||||
// 始终显示活性 Gizmo
|
||||
yield return new Gizmo_NeutronFlux(this);
|
||||
|
||||
// 不在孵化中且研究完成时才显示呼叫按钮
|
||||
var config = EquipmentIncubatorData?.SelectedConfig;
|
||||
if (!isIncubating && config != null && config.IsResearchComplete)
|
||||
{
|
||||
@@ -590,6 +740,7 @@ namespace ArachnaeSwarm
|
||||
};
|
||||
}
|
||||
|
||||
// 如果正在孵化,显示取消按钮
|
||||
if (isIncubating)
|
||||
{
|
||||
yield return new Command_Action
|
||||
@@ -978,6 +1129,10 @@ namespace ArachnaeSwarm
|
||||
Scribe_Values.Look(ref qualityTotal, "qualityTotal", 0f);
|
||||
Scribe_Values.Look(ref totalNutrientCost, "totalNutrientCost", 0);
|
||||
Scribe_Values.Look(ref currentNutrientCount, "currentNutrientCount", 0);
|
||||
|
||||
// 孵化活性系统
|
||||
Scribe_Values.Look(ref neutronFlux, "neutronFlux", 0.5f);
|
||||
Scribe_Values.Look(ref fluxMode, "fluxMode", FluxMode.Balance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,239 @@
|
||||
// File: Gizmo_EquipmentIncubationProgress.cs
|
||||
// 装备孵化进度 Gizmo - 与 Gizmo_IncubationProgress 样式完全一致
|
||||
using System.Collections.Generic;
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
[StaticConstructorOnStartup]
|
||||
public class Gizmo_EquipmentIncubationProgress : Gizmo
|
||||
{
|
||||
private readonly Building_EquipmentOotheca building;
|
||||
|
||||
// 尺寸常量(与 Gizmo_IncubationProgress 相同)
|
||||
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;
|
||||
|
||||
// 进度条材质(与 Gizmo_IncubationProgress 相同)
|
||||
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_EquipmentIncubationProgress(Building_EquipmentOotheca building)
|
||||
{
|
||||
this.building = building;
|
||||
Order = -99f; // 在通量 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 - 25f, GetWidth(maxWidth), 100f);
|
||||
Widgets.DrawWindowBackground(rect);
|
||||
|
||||
// 内部区域
|
||||
Rect innerRect = rect.ContractedBy(Padding);
|
||||
float curY = innerRect.y;
|
||||
|
||||
// 状态判断
|
||||
bool isIncubating = building.isIncubating;
|
||||
bool hasLarva = building.assignedLarva != null;
|
||||
var config = building.EquipmentIncubatorData?.SelectedConfig;
|
||||
|
||||
// === 标题(可点击切换目标) ===
|
||||
Text.Font = GameFont.Small;
|
||||
Rect titleRect = new Rect(innerRect.x, curY, innerRect.width, Text.LineHeight);
|
||||
|
||||
string title;
|
||||
if (isIncubating && building.incubatingThingDef != null)
|
||||
title = building.incubatingThingDef.LabelCap;
|
||||
else if (config != null)
|
||||
title = config.thingDef.LabelCap;
|
||||
else
|
||||
title = "选择孵化目标...";
|
||||
|
||||
// 标题按钮(只有非孵化状态可点击)
|
||||
bool canSwitch = !isIncubating && !hasLarva && building.EquipmentIncubatorData?.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,
|
||||
"孵化进度:", building.IncubationProgress, IncubationBarTex);
|
||||
|
||||
curY += Spacing;
|
||||
|
||||
// 品质进度标签
|
||||
DrawLabeledProgressBar(ref curY, innerRect.x, innerRect.width,
|
||||
"品质进度:", building.QualityPercent, QualityBarTex);
|
||||
}
|
||||
else if (hasLarva)
|
||||
{
|
||||
Text.Font = GameFont.Tiny;
|
||||
GUI.color = new Color(0.9f, 0.9f, 0.5f);
|
||||
string statusText = building.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 = $"速度:{building.SpeedMultiplier.ToStringPercent()} 质量:{building.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 = building.EquipmentIncubatorData?.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;
|
||||
|
||||
// 获取物品图标
|
||||
Texture2D icon = cfg.thingDef?.uiIcon;
|
||||
|
||||
string label = cfg.thingDef.LabelCap;
|
||||
if (cfg.requiredResearch != null && !cfg.requiredResearch.IsFinished)
|
||||
{
|
||||
label += $" (需要: {cfg.requiredResearch.LabelCap})";
|
||||
options.Add(new FloatMenuOption(label, null, icon, Color.white)); // 禁用但有图标
|
||||
}
|
||||
else
|
||||
{
|
||||
label += $" ({cfg.daysRequired}天)";
|
||||
options.Add(new FloatMenuOption(label, () =>
|
||||
{
|
||||
building.EquipmentIncubatorData.SwitchToConfig(index);
|
||||
}, icon, Color.white));
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
bool isIncubating = building.isIncubating;
|
||||
|
||||
if (isIncubating && building.incubatingThingDef != null)
|
||||
{
|
||||
// 孵化中状态
|
||||
sb.AppendLine("【孵化中】");
|
||||
sb.AppendLine("目标: " + building.incubatingThingDef.LabelCap);
|
||||
sb.AppendLine("孵化进度: " + building.IncubationProgress.ToStringPercent());
|
||||
sb.AppendLine("品质进度: " + building.QualityPercent.ToStringPercent());
|
||||
|
||||
float remaining = building.incubationDuration - building.incubationProgress;
|
||||
if (remaining > 0)
|
||||
{
|
||||
sb.AppendLine("剩余时间: " + ((int)remaining).ToStringTicksToPeriod());
|
||||
}
|
||||
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("速度: " + building.SpeedMultiplier.ToStringPercent());
|
||||
sb.AppendLine("质量: " + building.QualityMultiplier.ToStringPercent());
|
||||
}
|
||||
else
|
||||
{
|
||||
// 空闲状态
|
||||
var config = building.EquipmentIncubatorData?.SelectedConfig;
|
||||
if (config != null)
|
||||
{
|
||||
sb.AppendLine("【就绪】");
|
||||
sb.AppendLine("目标: " + config.thingDef.LabelCap);
|
||||
sb.AppendLine("孵化时间: " + config.daysRequired + " 天");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine("【未选择目标】");
|
||||
sb.AppendLine("点击上方标题选择孵化目标");
|
||||
}
|
||||
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("当前速度加成: " + building.SpeedMultiplier.ToStringPercent());
|
||||
sb.AppendLine("当前质量加成: " + building.QualityMultiplier.ToStringPercent());
|
||||
}
|
||||
|
||||
return sb.ToString().TrimEndNewlines();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ using Verse.AI;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class Building_Ootheca : Building
|
||||
public class Building_Ootheca : Building, IFluxController
|
||||
{
|
||||
// 引用组件
|
||||
public CompIncubatorData IncubatorData => this.TryGetComp<CompIncubatorData>();
|
||||
@@ -19,7 +19,7 @@ namespace ArachnaeSwarm
|
||||
public float incubationDuration = 0f;
|
||||
public PawnKindDef incubatingPawnKind = null;
|
||||
|
||||
// 幼虫交互相关 - 设为public以便ITab访问
|
||||
// 幼虫交互相关
|
||||
public Pawn assignedLarva = null;
|
||||
public int larvaOperateTicksRemaining = 0;
|
||||
|
||||
@@ -39,15 +39,6 @@ namespace ArachnaeSwarm
|
||||
private CompRefuelableNutrition fuelComp; // 燃料组件缓存
|
||||
private Comp_SwarmMaintenance maintenanceComp; // 维护组件缓存
|
||||
|
||||
// 活性模式枚举
|
||||
public enum FluxMode
|
||||
{
|
||||
Manual, // 手动:完全手动控制
|
||||
Quality, // 品质优先:低活性,追求高品质
|
||||
Balance, // 平衡:自动平衡速度和品质
|
||||
Speed // 速度优先:高活性,快速孵化
|
||||
}
|
||||
|
||||
// 孵化活性公开属性(非孵化时锁定为0)
|
||||
public float NeutronFlux => isIncubating ? neutronFlux : 0f;
|
||||
public float RawFlux => neutronFlux; // 原始值用于 Gizmo 显示
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// File: Gizmo_NeutronFlux.cs
|
||||
// 竖向滑动条样式的孵化活性调节 Gizmo(带刻度和可拖动光标)
|
||||
// 竖向滑动条样式的孵化活性调节 Gizmo(带刻度)
|
||||
// 支持实现 IFluxController 接口的所有建筑
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
@@ -8,11 +9,12 @@ namespace ArachnaeSwarm
|
||||
[StaticConstructorOnStartup]
|
||||
public class Gizmo_NeutronFlux : Gizmo
|
||||
{
|
||||
private readonly Building_Ootheca ootheca;
|
||||
private readonly IFluxController controller;
|
||||
private readonly Thing parentThing; // 用于获取 Thing 属性
|
||||
|
||||
// 尺寸常量
|
||||
private const float Width = 100f;
|
||||
private const float GizmoHeight = 140f; // 增加高度与信息面板齐平
|
||||
private const float GizmoHeight = 140f;
|
||||
private const float Padding = 6f;
|
||||
|
||||
// 材质
|
||||
@@ -23,10 +25,12 @@ namespace ArachnaeSwarm
|
||||
private static readonly Texture2D TickMarkTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.4f, 0.4f, 0.4f, 0.8f));
|
||||
private static readonly Texture2D CursorTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.9f, 0.9f, 0.9f, 1f));
|
||||
|
||||
public Gizmo_NeutronFlux(Building_Ootheca ootheca)
|
||||
// 构造函数接受接口
|
||||
public Gizmo_NeutronFlux(IFluxController controller)
|
||||
{
|
||||
this.ootheca = ootheca;
|
||||
Order = -100f; // 最先显示
|
||||
this.controller = controller;
|
||||
this.parentThing = controller as Thing;
|
||||
Order = -100f;
|
||||
}
|
||||
|
||||
public override float GetWidth(float maxWidth)
|
||||
@@ -54,12 +58,12 @@ namespace ArachnaeSwarm
|
||||
|
||||
// 根据模式显示不同颜色
|
||||
Color modeColor;
|
||||
switch (ootheca.CurrentFluxMode)
|
||||
switch (controller.CurrentFluxMode)
|
||||
{
|
||||
case Building_Ootheca.FluxMode.Manual: modeColor = new Color(0.5f, 0.5f, 0.5f, 0.9f); break;
|
||||
case Building_Ootheca.FluxMode.Quality: modeColor = new Color(0.3f, 0.6f, 0.9f, 0.9f); break;
|
||||
case Building_Ootheca.FluxMode.Balance: modeColor = new Color(0.2f, 0.7f, 0.2f, 0.9f); break;
|
||||
case Building_Ootheca.FluxMode.Speed: modeColor = new Color(0.9f, 0.5f, 0.2f, 0.9f); break;
|
||||
case FluxMode.Manual: modeColor = new Color(0.5f, 0.5f, 0.5f, 0.9f); break;
|
||||
case FluxMode.Quality: modeColor = new Color(0.3f, 0.6f, 0.9f, 0.9f); break;
|
||||
case FluxMode.Balance: modeColor = new Color(0.2f, 0.7f, 0.2f, 0.9f); break;
|
||||
case FluxMode.Speed: modeColor = new Color(0.9f, 0.5f, 0.2f, 0.9f); break;
|
||||
default: modeColor = Color.gray; break;
|
||||
}
|
||||
|
||||
@@ -69,11 +73,11 @@ namespace ArachnaeSwarm
|
||||
Text.Font = GameFont.Tiny;
|
||||
Text.Anchor = TextAnchor.MiddleCenter;
|
||||
GUI.color = Color.white;
|
||||
Widgets.Label(modeRect, ootheca.GetModeShort());
|
||||
Widgets.Label(modeRect, controller.GetModeShort());
|
||||
|
||||
if (Widgets.ButtonInvisible(modeRect))
|
||||
{
|
||||
ootheca.CycleFluxMode();
|
||||
controller.CycleFluxMode();
|
||||
}
|
||||
|
||||
// === 竖向计量条 ===
|
||||
@@ -84,14 +88,14 @@ namespace ArachnaeSwarm
|
||||
Rect barRect = new Rect(barX, barY, barWidth, barHeight);
|
||||
|
||||
// 非孵化时显示灰色锁定状态
|
||||
bool isLocked = !ootheca.IsIncubating;
|
||||
bool isLocked = !controller.IsIncubating;
|
||||
|
||||
// 绘制背景
|
||||
GUI.color = isLocked ? new Color(0.3f, 0.3f, 0.3f, 0.5f) : Color.white;
|
||||
GUI.DrawTexture(barRect, EmptyBarTex);
|
||||
|
||||
// 绘制填充(从底部向上)- 使用 RawFlux 显示预设值
|
||||
float displayFlux = ootheca.RawFlux;
|
||||
float displayFlux = controller.RawFlux;
|
||||
float fillHeight = barRect.height * displayFlux;
|
||||
Rect fillRect = new Rect(barRect.x, barRect.yMax - fillHeight, barRect.width, fillHeight);
|
||||
GUI.color = isLocked ? new Color(0.5f, 0.35f, 0.1f, 0.5f) : Color.white;
|
||||
@@ -150,9 +154,9 @@ namespace ArachnaeSwarm
|
||||
Text.Anchor = TextAnchor.MiddleLeft;
|
||||
|
||||
// 百分比(大字)
|
||||
GUI.color = ootheca.IsDormant ? Color.red : Color.white;
|
||||
GUI.color = controller.IsDormant ? Color.red : Color.white;
|
||||
Rect percentRect = new Rect(infoX, barRect.y, infoWidth, 20f);
|
||||
Widgets.Label(percentRect, (ootheca.NeutronFlux * 100f).ToString("0") + "%");
|
||||
Widgets.Label(percentRect, (controller.NeutronFlux * 100f).ToString("0") + "%");
|
||||
|
||||
Text.Font = GameFont.Tiny;
|
||||
|
||||
@@ -162,11 +166,11 @@ namespace ArachnaeSwarm
|
||||
Widgets.Label(effRect, "效率");
|
||||
Rect effValRect = new Rect(infoX, barRect.y + 36f, infoWidth, 14f);
|
||||
GUI.color = Color.white;
|
||||
Widgets.Label(effValRect, (ootheca.FluxEfficiency * 100f).ToString("0") + "%");
|
||||
Widgets.Label(effValRect, (controller.FluxEfficiency * 100f).ToString("0") + "%");
|
||||
|
||||
// 速度倍率
|
||||
GUI.color = new Color(0.7f, 0.7f, 0.7f);
|
||||
float speedMultiplier = ootheca.FluxEfficiency * 5f;
|
||||
float speedMultiplier = controller.FluxEfficiency * 5f;
|
||||
Rect speedRect = new Rect(infoX, barRect.y + 54f, infoWidth, 14f);
|
||||
Widgets.Label(speedRect, "速度");
|
||||
Rect speedValRect = new Rect(infoX, barRect.y + 68f, infoWidth, 14f);
|
||||
@@ -190,7 +194,7 @@ namespace ArachnaeSwarm
|
||||
private void UpdateFluxFromMouse(Rect barRect, float mouseY)
|
||||
{
|
||||
float percent = 1f - (mouseY - barRect.y) / barRect.height;
|
||||
ootheca.SetNeutronFlux(Mathf.Clamp01(percent));
|
||||
controller.SetNeutronFlux(Mathf.Clamp01(percent));
|
||||
}
|
||||
|
||||
private string GetTooltip()
|
||||
@@ -206,24 +210,24 @@ namespace ArachnaeSwarm
|
||||
sb.AppendLine();
|
||||
|
||||
// 当前状态
|
||||
sb.AppendLine($"当前活性: {(ootheca.RawFlux * 100f):0}%");
|
||||
sb.AppendLine($"孵化速度: {(ootheca.FluxEfficiency * 5f):0.0}x");
|
||||
sb.AppendLine($"当前活性: {(controller.RawFlux * 100f):0}%");
|
||||
sb.AppendLine($"孵化速度: {(controller.FluxEfficiency * 5f):0.0}x");
|
||||
sb.AppendLine();
|
||||
|
||||
// 模式说明
|
||||
sb.AppendLine($"模式: {ootheca.GetModeName()}");
|
||||
switch (ootheca.CurrentFluxMode)
|
||||
sb.AppendLine($"模式: {controller.GetModeName()}");
|
||||
switch (controller.CurrentFluxMode)
|
||||
{
|
||||
case Building_Ootheca.FluxMode.Manual:
|
||||
case FluxMode.Manual:
|
||||
sb.AppendLine(" 手动调节活性");
|
||||
break;
|
||||
case Building_Ootheca.FluxMode.Quality:
|
||||
case FluxMode.Quality:
|
||||
sb.AppendLine(" 低活性,追求品质");
|
||||
break;
|
||||
case Building_Ootheca.FluxMode.Balance:
|
||||
case FluxMode.Balance:
|
||||
sb.AppendLine(" 自动平衡速度和品质");
|
||||
break;
|
||||
case Building_Ootheca.FluxMode.Speed:
|
||||
case FluxMode.Speed:
|
||||
sb.AppendLine(" 高活性,快速孵化");
|
||||
break;
|
||||
}
|
||||
@@ -232,7 +236,7 @@ namespace ArachnaeSwarm
|
||||
// 操作
|
||||
sb.AppendLine("点击拖动调节 | 右上角切换模式");
|
||||
|
||||
if (ootheca.IsDormant)
|
||||
if (controller.IsDormant)
|
||||
{
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("<color=red>⚠ 休眠中,品质下降!</color>");
|
||||
|
||||
37
Source/ArachnaeSwarm/Buildings/IFluxController.cs
Normal file
37
Source/ArachnaeSwarm/Buildings/IFluxController.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
/// <summary>
|
||||
/// 共享接口:孵化活性控制器
|
||||
/// Building_Ootheca 和 Building_EquipmentOotheca 都实现此接口
|
||||
/// </summary>
|
||||
public interface IFluxController
|
||||
{
|
||||
// 活性值
|
||||
float NeutronFlux { get; }
|
||||
float RawFlux { get; }
|
||||
float FluxEfficiency { get; }
|
||||
|
||||
// 模式
|
||||
FluxMode CurrentFluxMode { get; }
|
||||
bool IsAutoMode { get; }
|
||||
bool IsIncubating { get; }
|
||||
bool IsDormant { get; }
|
||||
|
||||
// 方法
|
||||
void SetNeutronFlux(float value);
|
||||
void CycleFluxMode();
|
||||
string GetModeName();
|
||||
string GetModeShort();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 活性模式枚举(共享)
|
||||
/// </summary>
|
||||
public enum FluxMode
|
||||
{
|
||||
Manual, // 手动:完全手动控制
|
||||
Quality, // 品质优先:低活性,追求高品质
|
||||
Balance, // 平衡:自动平衡速度和品质
|
||||
Speed // 速度优先:高活性,快速孵化
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user