diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll
index ef6ef20..58bb077 100644
Binary files a/1.6/1.6/Assemblies/ArachnaeSwarm.dll and b/1.6/1.6/Assemblies/ArachnaeSwarm.dll differ
diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.pdb b/1.6/1.6/Assemblies/ArachnaeSwarm.pdb
index f966b8d..19a9f7f 100644
Binary files a/1.6/1.6/Assemblies/ArachnaeSwarm.pdb and b/1.6/1.6/Assemblies/ArachnaeSwarm.pdb differ
diff --git a/1.6/1.6/Defs/Thing_building/ARA_NutrientNetworkBuilding.xml b/1.6/1.6/Defs/Thing_building/ARA_NutrientNetworkBuilding.xml
index c65c706..a097ed0 100644
--- a/1.6/1.6/Defs/Thing_building/ARA_NutrientNetworkBuilding.xml
+++ b/1.6/1.6/Defs/Thing_building/ARA_NutrientNetworkBuilding.xml
@@ -60,6 +60,7 @@
ARA_Acidling_AutoMortar
CatastropheMissileSilo
ARA_AutoSniperCannon
+ ARA_Pawn_Ootheca
80
10
diff --git a/1.6/1.6/Defs/Thing_building/ARA_Ootheca.xml b/1.6/1.6/Defs/Thing_building/ARA_Ootheca.xml
index 8e599b4..e051f02 100644
--- a/1.6/1.6/Defs/Thing_building/ARA_Ootheca.xml
+++ b/1.6/1.6/Defs/Thing_building/ARA_Ootheca.xml
@@ -151,9 +151,7 @@
25
-
- ArachnaeSwarm.PlaceWorker_CustomRadius
-
+
100
@@ -162,15 +160,27 @@
0.2
0.5
-
- 5
- (0.5, 1, 1)
- 0
- true
-
- 这个卵在孵化过程中的吸收半径,确保这些地格中铺满阿拉克涅营养液,并且没有其他的卵,以获得最佳的孵化速度和孵化质量。
- false
+
+
+
+ 25.0
+
+
+ ARA_InsectJelly
+
+
+ 虫蜜
+ true
+ true
+ 5
+ true
+
+
+ ARA_NutrientNetworkTower
+
+
+
0
diff --git a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
index f073ec6..a762a77 100644
--- a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
+++ b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj
@@ -124,6 +124,7 @@
+
diff --git a/Source/ArachnaeSwarm/Building_Comps/ARA_SwarmMaintenance/Comp_SwarmMaintenance.cs b/Source/ArachnaeSwarm/Building_Comps/ARA_SwarmMaintenance/Comp_SwarmMaintenance.cs
index 4572354..dea2e06 100644
--- a/Source/ArachnaeSwarm/Building_Comps/ARA_SwarmMaintenance/Comp_SwarmMaintenance.cs
+++ b/Source/ArachnaeSwarm/Building_Comps/ARA_SwarmMaintenance/Comp_SwarmMaintenance.cs
@@ -88,9 +88,27 @@ namespace ArachnaeSwarm
{
if (parent == null || parent.Map == null)
return;
-
- // 计算递减量:每天递减量转换为每2500tick(约0.347天)的递减量
- float decayAmount = Props.maintenanceDecayPerDay * (2500f / 60000f);
+
+ // 计算基础递减量:每天递减量转换为每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;
currentMaintenance -= decayAmount;
// 确保不低于0
diff --git a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Building_Ootheca.cs b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Building_Ootheca.cs
index 821d7fb..3e7d70e 100644
--- a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Building_Ootheca.cs
+++ b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Building_Ootheca.cs
@@ -33,6 +33,42 @@ namespace ArachnaeSwarm
private float qualityProgress = 0f;
private float qualityTotal = 0f;
+ // ======= 中子通量系统 =======
+ private float neutronFlux = 0.5f; // 0-1, 默认50%
+ private bool autoFluxMode = true; // 自动模式
+ private CompRefuelableNutrition fuelComp; // 燃料组件缓存
+ private Comp_SwarmMaintenance maintenanceComp; // 维护组件缓存
+
+ // 孵化活性公开属性(非孵化时锁定为0)
+ public float NeutronFlux => isIncubating ? neutronFlux : 0f;
+ public float RawFlux => neutronFlux; // 原始值用于 Gizmo 显示
+ public bool AutoFluxMode => autoFluxMode;
+
+ // 获取燃料组件
+ public CompRefuelableNutrition FuelComp => fuelComp ?? (fuelComp = this.TryGetComp());
+ public Comp_SwarmMaintenance MaintenanceComp => maintenanceComp ?? (maintenanceComp = this.TryGetComp());
+
+ // 孵化活性效率曲线(非线性:flux² 使低活性效率极低)
+ public float FluxEfficiency => NeutronFlux * NeutronFlux;
+
+ // 是否处于休眠状态(无燃料或活性为0)
+ public bool IsDormant => NeutronFlux < 0.01f || (FuelComp != null && !FuelComp.HasFuel);
+
+ // 是否正在孵化(公开属性)
+ public bool IsIncubating => isIncubating;
+
+ // 设置中子通量
+ public void SetNeutronFlux(float value)
+ {
+ neutronFlux = Mathf.Clamp01(value);
+ }
+
+ // 切换自动模式
+ public void ToggleAutoMode()
+ {
+ autoFluxMode = !autoFluxMode;
+ }
+
// 缓存的ModExtension
private OothecaIncubatorExtension cachedExtension;
@@ -81,38 +117,18 @@ namespace ArachnaeSwarm
public string GetSpeedFactorsDescription()
{
var builder = new StringBuilder();
-
- builder.AppendLine("ARA_OothecaIncubator.SpeedFactors".Translate());
+ builder.AppendLine("速度因子");
builder.AppendLine();
- // 1. 检查是否在孵化间中
+ // 检查是否在孵化间中
bool inIncubatorRoom = IsInIncubatorRoom();
if (Ext.requiresIncubatorRoom)
{
- builder.AppendLine(inIncubatorRoom ?
- "ARA_OothecaIncubator.InIncubatorRoom".Translate() :
- "ARA_OothecaIncubator.NotInIncubatorRoom".Translate());
+ builder.AppendLine(inIncubatorRoom ? "✓ 在孵化间中" : "✗ 不在孵化间中");
}
- // 2. 检查营养液数量
- int nutrientSolutionCount = CountNearbyNutrientSolutions();
- if (nutrientSolutionCount > 0)
- {
- builder.AppendLine("ARA_OothecaIncubator.NutrientSolutions".Translate(
- nutrientSolutionCount,
- nutrientSolutionCount * Ext.nutrientSolutionBonusPerTile * 100));
- }
- else
- {
- builder.AppendLine("ARA_OothecaIncubator.NoNutrientSolutionsNearby".Translate());
- }
-
- // 显示检测半径
builder.AppendLine();
- builder.AppendLine("ARA_OothecaIncubator.NutrientDetectionRadius".Translate(Ext.nutrientSolutionRadius));
-
- builder.AppendLine();
- builder.AppendLine("ARA_OothecaIncubator.TotalSpeedMultiplier".Translate(SpeedMultiplier.ToStringPercent()));
+ builder.AppendLine("总速度倍率: " + SpeedMultiplier.ToStringPercent());
return builder.ToString().TrimEndNewlines();
}
@@ -422,22 +438,25 @@ public override string GetInspectString()
// Gizmos
public override IEnumerable GetGizmos()
{
+ // 过滤掉拆除按钮
foreach (var gizmo in base.GetGizmos())
{
+ // 跳过拆除相关的 Gizmo
+ if (gizmo is Command_Action cmd && cmd.defaultLabel != null &&
+ (cmd.defaultLabel.ToString().Contains("拆除") || cmd.defaultLabel.ToString().Contains("Deconstruct")))
+ continue;
+
yield return gizmo;
}
// 只有玩家派系才显示Gizmo
if (Faction == Faction.OfPlayer)
{
- // 始终显示双进度条Gizmo(内部会自动处理非孵化状态的显示)
+ // 始终显示双进度条Gizmo
yield return new Gizmo_IncubationProgress(this);
- // 不在孵化中时才显示切换目标按钮
- if (!isIncubating && IncubatorData?.IncubationConfigs?.Count > 0)
- {
- yield return CreateTargetSwitchGizmo();
- }
+ // 中子通量控制 Gizmo
+ yield return new Gizmo_NeutronFlux(this);
// 不在孵化中且研究完成时才显示呼叫按钮
var config = IncubatorData?.SelectedConfig;
@@ -661,40 +680,181 @@ public override string GetInspectString()
}
// 孵化进度 - 使用override而不是new
- protected override void Tick()
+protected override void Tick()
+{
+ base.Tick();
+
+ // 减少操作剩余时间(仅用于显示)
+ if (larvaOperateTicksRemaining > 0)
+ {
+ larvaOperateTicksRemaining--;
+ }
+
+ // 只有在孵化过程中才消耗资源和自动调节
+ if (isIncubating)
+ {
+ // 自动模式计算(每250ticks更新一次)
+ if (autoFluxMode && Find.TickManager.TicksGame % 250 == 0)
{
- base.Tick();
+ CalculateAutoFlux();
+ }
+
+ // 消耗虫蜜(基于孵化活性)
+ if (FuelComp != null && neutronFlux > 0.01f)
+ {
+ // 基础消耗:50虫蜜/天 在100%活性,非线性
+ float baseConsumptionPerDay = 50f * FluxEfficiency;
+ float consumptionPerTick = baseConsumptionPerDay / 60000f;
+ FuelComp.ConsumeFuel(consumptionPerTick);
+ }
+ }
+
+ // 更新孵化进度和质量进度
+ if (isIncubating)
+ {
+ // 更新乘数
+ if (lastMultiplierUpdateTick < 0 || Find.TickManager.TicksGame - lastMultiplierUpdateTick >= MultiplierUpdateInterval)
+ {
+ UpdateSpeedMultiplier();
+ UpdateQualityMultiplier();
+ }
+
+ // 检查是否休眠
+ if (IsDormant)
+ {
+ // 休眠状态:品质进度下降
+ float qualityDecayPerTick = 0.1f / 60000f; // 每天下降10%
+ qualityProgress = Mathf.Max(0, qualityProgress - qualityDecayPerTick * incubationDuration);
- // 减少操作剩余时间(仅用于显示)
- if (larvaOperateTicksRemaining > 0)
+ // 品质归零 → 破坏卵
+ if (qualityProgress <= 0 && qualityTotal > 0)
{
- larvaOperateTicksRemaining--;
- // 注意:孵化启动现在由JobDriver触发,这里只更新显示
- }
-
- // 更新孵化进度和质量进度
- if (isIncubating)
- {
- // 更新质量乘数(与速度乘数同步更新)
- if (lastMultiplierUpdateTick < 0 || Find.TickManager.TicksGame - lastMultiplierUpdateTick >= MultiplierUpdateInterval)
- {
- UpdateSpeedMultiplier();
- UpdateQualityMultiplier();
- }
-
- // 应用速度乘数
- float currentSpeed = SpeedMultiplier;
- incubationProgress += currentSpeed;
-
- // 质量进度与速度同步增长,但乘以质量乘数
- qualityProgress += currentSpeed * QualityMultiplier;
-
- if (incubationProgress >= incubationDuration)
- {
- CompleteIncubation();
- }
+ Messages.Message("卵囊因品质归零而损坏!", this, MessageTypeDefOf.NegativeEvent);
+ Destroy(DestroyMode.KillFinalize);
+ return;
}
}
+ else
+ {
+ // 正常状态:应用中子通量效率(100%通量时5倍速度)
+ float fluxSpeed = SpeedMultiplier * FluxEfficiency * 5f;
+ incubationProgress += fluxSpeed;
+
+ // 质量进度也受中子通量影响
+ float fluxQuality = QualityMultiplier * FluxEfficiency * 5f;
+ qualityProgress += fluxSpeed * fluxQuality;
+ }
+
+ if (incubationProgress >= incubationDuration)
+ {
+ CompleteIncubation();
+ }
+ }
+}
+
+// 自动模式:智能计算最优中子通量
+// 目标:在资源允许的情况下,尽可能快速完成孵化
+private void CalculateAutoFlux()
+{
+ if (!autoFluxMode) return;
+
+ float targetFlux = 1.0f; // 默认100%
+
+ // === 策略1:根据孵化剩余时间优化 ===
+ if (isIncubating && incubationDuration > 0)
+ {
+ float remainingProgress = incubationDuration - incubationProgress;
+ float remainingDays = remainingProgress / (60000f * SpeedMultiplier);
+
+ // 计算虫蜜能维持多少天(按当前通量)
+ float fuelDays = float.MaxValue;
+ if (FuelComp != null && FuelComp.Fuel > 0)
+ {
+ // 消耗率 = 50 * flux² 每天
+ float currentConsumption = 50f * neutronFlux * neutronFlux;
+ fuelDays = currentConsumption > 0 ? FuelComp.Fuel / currentConsumption : float.MaxValue;
+ }
+
+ // 计算维护能维持多少天
+ float maintenanceDays = float.MaxValue;
+ if (MaintenanceComp != null)
+ {
+ float maintenance = MaintenanceComp.CurrentMaintenance;
+ float decayPerDay = MaintenanceComp.Props.maintenanceDecayPerDay;
+ maintenanceDays = decayPerDay > 0 ? maintenance / decayPerDay : float.MaxValue;
+ }
+
+ // 找到瓶颈资源
+ float minResourceDays = Mathf.Min(fuelDays, maintenanceDays);
+
+ // 安全边际:资源至少要能维持 剩余孵化天数 + 0.5天
+ float requiredDays = remainingDays + 0.5f;
+
+ if (minResourceDays < requiredDays && minResourceDays > 0)
+ {
+ // 资源不足,需要降低通量
+ // 用二分法找到刚好能完成孵化的通量
+ float lowFlux = 0.1f;
+ float highFlux = neutronFlux;
+
+ for (int i = 0; i < 8; i++) // 8次迭代足够精确
+ {
+ float midFlux = (lowFlux + highFlux) / 2f;
+ float testEfficiency = midFlux * midFlux;
+ float testSpeed = SpeedMultiplier * testEfficiency * 5f;
+ float testDays = testSpeed > 0 ? remainingProgress / (testSpeed * 60000f) : float.MaxValue;
+
+ // 计算该通量下资源能维持多久
+ float testFuelDays = FuelComp != null && FuelComp.Fuel > 0
+ ? FuelComp.Fuel / (50f * testEfficiency + 0.01f)
+ : float.MaxValue;
+
+ if (testFuelDays >= testDays + 0.5f)
+ lowFlux = midFlux; // 可以更高
+ else
+ highFlux = midFlux; // 需要更低
+ }
+
+ targetFlux = lowFlux;
+ }
+ }
+
+ // === 策略2:紧急保护 ===
+ // 虫蜜极低时紧急降速
+ if (FuelComp != null && FuelComp.Fuel < 5f)
+ {
+ targetFlux = Mathf.Min(targetFlux, 0.3f);
+ }
+
+ // 维护极低时紧急降速
+ if (MaintenanceComp != null)
+ {
+ float maintenancePercent = MaintenanceComp.CurrentMaintenance / MaintenanceComp.Props.maxMaintenance;
+ if (maintenancePercent < 0.15f)
+ {
+ targetFlux = Mathf.Min(targetFlux, 0.2f);
+ }
+ }
+
+ // === 策略3:资源充足时全速 ===
+ bool fuelAbundant = FuelComp == null || FuelComp.Fuel > FuelComp.Props.fuelCapacity * 0.8f;
+ bool maintenanceAbundant = MaintenanceComp == null ||
+ MaintenanceComp.CurrentMaintenance > MaintenanceComp.Props.maxMaintenance * 0.7f;
+
+ if (fuelAbundant && maintenanceAbundant)
+ {
+ targetFlux = 1.0f;
+ }
+
+ // 平滑调节(避免突变,每次最多调整5%)
+ float adjustSpeed = 0.05f;
+ if (neutronFlux < targetFlux)
+ neutronFlux = Mathf.Min(neutronFlux + adjustSpeed, targetFlux);
+ else if (neutronFlux > targetFlux)
+ neutronFlux = Mathf.Max(neutronFlux - adjustSpeed, targetFlux);
+
+ neutronFlux = Mathf.Clamp(neutronFlux, 0.05f, 1.0f); // 最低5%防止完全停止
+}
// 应用质量效果到生成的pawn
private void ApplyQualityEffects(Pawn pawn, float qualityPercent)
@@ -862,23 +1022,17 @@ public override string GetInspectString()
return count;
}
- // 更新速度乘数
+ // 更新速度乘数(已移除营养液逻辑,后续将使用 CompRefuelableNutrition)
private void UpdateSpeedMultiplier()
{
float multiplier = 1.0f;
- // 1. 检查是否在孵化间中(如果要求)
+ // 检查是否在孵化间中(如果要求)
if (Ext.requiresIncubatorRoom && !IsInIncubatorRoom())
{
- multiplier *= Ext.speedPenaltyOutsideIncubator; // 应用惩罚
+ multiplier *= Ext.speedPenaltyOutsideIncubator;
}
- // 2. 计算周围营养液的加成
- int nutrientSolutionCount = CountNearbyNutrientSolutions();
- float nutrientBonus = 1.0f + (nutrientSolutionCount * Ext.nutrientSolutionBonusPerTile);
-
- multiplier *= nutrientBonus;
-
speedMultiplier = multiplier;
lastMultiplierUpdateTick = Find.TickManager.TicksGame;
}
@@ -927,6 +1081,10 @@ public override string GetInspectString()
Scribe_Values.Look(ref qualityMultiplier, "qualityMultiplier", 1.0f);
Scribe_Values.Look(ref qualityProgress, "qualityProgress", 0f);
Scribe_Values.Look(ref qualityTotal, "qualityTotal", 0f);
+
+ // 中子通量系统
+ Scribe_Values.Look(ref neutronFlux, "neutronFlux", 0.5f);
+ Scribe_Values.Look(ref autoFluxMode, "autoFluxMode", true);
}
}
}
diff --git a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Gizmo_IncubationProgress.cs b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Gizmo_IncubationProgress.cs
index ba13d53..f3a0a2d 100644
--- a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Gizmo_IncubationProgress.cs
+++ b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Gizmo_IncubationProgress.cs
@@ -27,7 +27,7 @@ namespace ArachnaeSwarm
public Gizmo_IncubationProgress(Building_Ootheca ootheca)
{
this.ootheca = ootheca;
- Order = -100f; // 显示在左侧
+ Order = -99f; // 在通量 Gizmo 之后显示
}
public override float GetWidth(float maxWidth)
@@ -37,8 +37,8 @@ namespace ArachnaeSwarm
public override GizmoResult GizmoOnGUI(Vector2 topLeft, float maxWidth, GizmoRenderParms parms)
{
- // 主矩形区域(向上偏移以容纳更高的内容)
- Rect rect = new Rect(topLeft.x, topLeft.y - 55f, GetWidth(maxWidth), 130f);
+ // 主矩形区域
+ Rect rect = new Rect(topLeft.x, topLeft.y - 25f, GetWidth(maxWidth), 100f);
Widgets.DrawWindowBackground(rect);
// 内部区域
diff --git a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Gizmo_NeutronFlux.cs b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Gizmo_NeutronFlux.cs
new file mode 100644
index 0000000..b7eb1a7
--- /dev/null
+++ b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Gizmo_NeutronFlux.cs
@@ -0,0 +1,252 @@
+// File: Gizmo_NeutronFlux.cs
+// 竖向滑动条样式的孵化活性调节 Gizmo(带刻度和可拖动光标)
+using UnityEngine;
+using Verse;
+
+namespace ArachnaeSwarm
+{
+ [StaticConstructorOnStartup]
+ public class Gizmo_NeutronFlux : Gizmo
+ {
+ private readonly Building_Ootheca ootheca;
+
+ // 尺寸常量
+ private const float Width = 100f;
+ private const float GizmoHeight = 140f; // 增加高度与信息面板齐平
+ private const float Padding = 6f;
+
+ // 材质
+ private static readonly Texture2D FluxBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.9f, 0.5f, 0.1f, 0.9f));
+ private static readonly Texture2D EmptyBarTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.15f, 0.15f, 0.15f, 0.8f));
+ private static readonly Texture2D AutoOnTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.2f, 0.7f, 0.2f, 0.9f));
+ private static readonly Texture2D AutoOffTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.5f, 0.3f, 0.3f, 0.7f));
+ 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));
+
+ private bool isDragging = false;
+
+ public Gizmo_NeutronFlux(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 - 65f, GetWidth(maxWidth), GizmoHeight);
+ Widgets.DrawWindowBackground(rect);
+
+ Rect innerRect = rect.ContractedBy(Padding);
+
+ // === 标题行 ===
+ Text.Font = GameFont.Small;
+ Text.Anchor = TextAnchor.MiddleLeft;
+ Rect titleRect = new Rect(innerRect.x, innerRect.y, innerRect.width - 24f, 18f);
+ Widgets.Label(titleRect, "活性");
+
+ // === 右上角自动模式按钮 ===
+ float buttonSize = 20f;
+ Rect autoRect = new Rect(innerRect.xMax - buttonSize, innerRect.y, buttonSize, buttonSize);
+ GUI.DrawTexture(autoRect, ootheca.AutoFluxMode ? AutoOnTex : AutoOffTex);
+ Widgets.DrawBox(autoRect, 1);
+
+ Text.Font = GameFont.Tiny;
+ Text.Anchor = TextAnchor.MiddleCenter;
+ GUI.color = Color.white;
+ Widgets.Label(autoRect, ootheca.AutoFluxMode ? "A" : "M");
+
+ if (Widgets.ButtonInvisible(autoRect))
+ {
+ ootheca.ToggleAutoMode();
+ }
+
+ // === 竖向滑动条 ===
+ float barWidth = 32f;
+ float barHeight = 90f; // 增加高度
+ float barX = innerRect.x + 8f;
+ float barY = innerRect.y + 24f;
+ Rect barRect = new Rect(barX, barY, barWidth, barHeight);
+
+ // 非孵化时显示灰色锁定状态
+ bool isLocked = !ootheca.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 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;
+ GUI.DrawTexture(fillRect, FluxBarTex);
+ GUI.color = Color.white;
+
+ // 绘制刻度线(10格)
+ for (int i = 1; i < 10; i++)
+ {
+ float tickY = barRect.y + barRect.height * (1f - i / 10f);
+ float tickWidth = (i == 5) ? barRect.width * 0.6f : barRect.width * 0.3f;
+ Rect tickRect = new Rect(barRect.x, tickY - 0.5f, tickWidth, 1f);
+ GUI.DrawTexture(tickRect, TickMarkTex);
+ }
+
+ // 绘制边框
+ Widgets.DrawBox(barRect, 1);
+
+ // === 可拖动光标(三角形指示器)===
+ float cursorY = barRect.yMax - fillHeight;
+ float cursorWidth = 12f;
+ float cursorHeight = 14f;
+ Rect cursorRect = new Rect(barRect.xMax + 2f, cursorY - cursorHeight / 2f, cursorWidth, cursorHeight);
+
+ // 绘制三角形光标(指向左边)
+ GUI.color = isDragging ? new Color(1f, 0.8f, 0.3f, 1f) : new Color(0.9f, 0.9f, 0.9f, 1f);
+ for (int i = 0; i < 7; i++)
+ {
+ float w = cursorWidth * (1f - Mathf.Abs(i - 3) / 4f);
+ float y = cursorY - 3.5f + i;
+ Rect lineRect = new Rect(cursorRect.x, y, w, 1f);
+ GUI.DrawTexture(lineRect, CursorTex);
+ }
+ GUI.color = Color.white;
+
+ // === 拖动交互(包括光标区域)===
+ Rect interactRect = new Rect(barRect.x - 5f, barRect.y - 5f, barRect.width + cursorWidth + 15f, barRect.height + 10f);
+
+ if (Event.current.type == EventType.MouseDown && interactRect.Contains(Event.current.mousePosition))
+ {
+ isDragging = true;
+ UpdateFluxFromMouse(barRect);
+ Event.current.Use();
+ }
+ if (Event.current.type == EventType.MouseUp)
+ {
+ isDragging = false;
+ }
+ if (isDragging && (Event.current.type == EventType.MouseDrag || Event.current.type == EventType.Repaint))
+ {
+ if (Event.current.type == EventType.MouseDrag)
+ {
+ UpdateFluxFromMouse(barRect);
+ Event.current.Use();
+ }
+ }
+
+ // === 右侧信息显示 ===
+ float infoX = barRect.xMax + 18f;
+ float infoWidth = innerRect.xMax - infoX;
+
+ Text.Font = GameFont.Small;
+ Text.Anchor = TextAnchor.MiddleLeft;
+
+ // 百分比(大字)
+ GUI.color = ootheca.IsDormant ? Color.red : Color.white;
+ Rect percentRect = new Rect(infoX, barRect.y, infoWidth, 20f);
+ Widgets.Label(percentRect, (ootheca.NeutronFlux * 100f).ToString("0") + "%");
+
+ Text.Font = GameFont.Tiny;
+
+ // 效率
+ GUI.color = new Color(0.7f, 0.7f, 0.7f);
+ Rect effRect = new Rect(infoX, barRect.y + 22f, infoWidth, 14f);
+ 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") + "%");
+
+ // 速度倍率
+ GUI.color = new Color(0.7f, 0.7f, 0.7f);
+ float speedMultiplier = ootheca.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);
+ GUI.color = speedMultiplier >= 1f ? new Color(0.5f, 1f, 0.5f) : new Color(1f, 0.7f, 0.5f);
+ Widgets.Label(speedValRect, speedMultiplier.ToString("0.0") + "x");
+
+ GUI.color = Color.white;
+ Text.Anchor = TextAnchor.UpperLeft;
+ Text.Font = GameFont.Small;
+
+ // 工具提示
+ if (Mouse.IsOver(rect))
+ {
+ Widgets.DrawHighlight(rect);
+ TooltipHandler.TipRegion(rect, GetTooltip());
+ }
+
+ return new GizmoResult(GizmoState.Clear);
+ }
+
+ private void UpdateFluxFromMouse(Rect barRect)
+ {
+ float mouseY = Event.current.mousePosition.y;
+ float percent = 1f - (mouseY - barRect.y) / barRect.height;
+ ootheca.SetNeutronFlux(Mathf.Clamp01(percent));
+ }
+
+ private string GetTooltip()
+ {
+ var sb = new System.Text.StringBuilder();
+
+ // 标题
+ sb.AppendLine("【孵化活性控制器】");
+ sb.AppendLine();
+
+ // 当前状态
+ sb.AppendLine("═══ 当前状态 ═══");
+ sb.AppendLine($"活性: {(ootheca.NeutronFlux * 100f):0}%");
+ sb.AppendLine($"效率: {(ootheca.FluxEfficiency * 100f):0}% (活性²)");
+ sb.AppendLine($"孵化速度: {(ootheca.FluxEfficiency * 5f):0.0}x");
+ sb.AppendLine($"模式: {(ootheca.AutoFluxMode ? "自动" : "手动")}");
+ sb.AppendLine();
+
+ // 效率说明
+ sb.AppendLine("═══ 效率曲线 ═══");
+ sb.AppendLine("活性与效率呈非线性关系:");
+ sb.AppendLine(" 20% 活性 → 4% 效率 (0.2x速度)");
+ sb.AppendLine(" 50% 活性 → 25% 效率 (1.25x速度)");
+ sb.AppendLine(" 70% 活性 → 49% 效率 (2.45x速度)");
+ sb.AppendLine(" 100% 活性 → 100% 效率 (5x速度)");
+ sb.AppendLine();
+
+ // 消耗说明
+ sb.AppendLine("═══ 资源消耗 ═══");
+ float dailyFuelConsumption = 50f * ootheca.FluxEfficiency;
+ sb.AppendLine($"虫蜜消耗: {dailyFuelConsumption:0.0}/天");
+ sb.AppendLine("(基础50/天 × 效率)");
+ sb.AppendLine();
+
+ // 操作说明
+ sb.AppendLine("═══ 操作指南 ═══");
+ sb.AppendLine("• 拖动滑块或光标调节通量");
+ sb.AppendLine("• 右上角[A/M]切换模式");
+ sb.AppendLine("• 自动模式智能平衡资源和速度");
+ sb.AppendLine();
+
+ // 警告
+ sb.AppendLine("═══ 注意事项 ═══");
+ sb.AppendLine("• 通量为0时进入休眠状态");
+ sb.AppendLine("• 休眠时品质持续下降");
+ sb.AppendLine("• 品质归零卵囊将被破坏");
+ sb.AppendLine("• 虫蜜耗尽也会进入休眠");
+
+ if (ootheca.IsDormant)
+ {
+ sb.AppendLine();
+ sb.AppendLine("════════════════");
+ sb.AppendLine("⚠ 当前处于休眠状态!");
+ sb.AppendLine("品质正在下降!");
+ sb.AppendLine("════════════════");
+ }
+
+ return sb.ToString().TrimEndNewlines();
+ }
+ }
+}