diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll
index cbb52f7..17fbb9f 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 a00d02d..a06cfcb 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_Building.xml b/1.6/1.6/Defs/Thing_building/ARA_Building.xml
index 55794e0..ab9ca02 100644
--- a/1.6/1.6/Defs/Thing_building/ARA_Building.xml
+++ b/1.6/1.6/Defs/Thing_building/ARA_Building.xml
@@ -52,6 +52,54 @@
Insect
-->
+
+ ARA_InsectCreepFloor
+
+ 由阿拉克涅虫族所铺设的由真菌、甲壳素分泌物混合得到的地面,性质类似于阿拉克涅菌毯,不过可以在支撑结构上蔓延,以作为虫群的逆重飞船地基。
+ ArachnaeSwarm/Terrain/Surfaces/ARA_InsectCreep
+ (0.95, 0.95, 0.93, 1)
+ (209, 207, 184)
+ 0
+ FadeRough
+ 399
+ ConstructMetal
+ true
+ ARA_Buildings
+ true
+ true
+ Misc9
+
+ ARA_Base_Technology
+
+
+ ARA_Creep
+ Substructure
+
+
+ 0
+ 0.25
+ 0
+ 0
+ 100
+
+
+ 1
+ 2
+ 2
+
+ 1000
+ true
+ Walkable
+ 1
+
+ ARA_Creep
+ Substructure
+
+
+ PlaceWorker_InSubstructureFootprint
+ PlaceWorker_BuildingsValidOverSubstructure
+
+
ARA_InsectCreepTile
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 9cb13bf..705fdcd 100644
--- a/1.6/1.6/Defs/Thing_building/ARA_Ootheca.xml
+++ b/1.6/1.6/Defs/Thing_building/ARA_Ootheca.xml
@@ -430,18 +430,24 @@
0.2
0.5
-
+
- 0
- 10
- 0
- 5
- true
+ 25.0
ARA_InsectJelly
+ 虫蜜
+ true
+ true
+ 5
+ true
+
+
+
+ ARA_NutrientNetworkTower
+
diff --git a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/ARA_QueuedIncubator.xml b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/ARA_QueuedIncubator.xml
index 76daf5d..cfaca0a 100644
--- a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/ARA_QueuedIncubator.xml
+++ b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/ARA_QueuedIncubator.xml
@@ -41,6 +41,8 @@
呼叫一只幼虫来激活下一个订单(还有{0}个等待中)
幼虫工作中
一只幼虫正在操作孵化器(还有{0}个订单等待)
+ 幼虫激活中
+ 幼虫赶路中
选择孵化目标
diff --git a/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompQueuedInteractiveProducerWithFlux.cs b/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompQueuedInteractiveProducerWithFlux.cs
index e25e34c..968578f 100644
--- a/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompQueuedInteractiveProducerWithFlux.cs
+++ b/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompQueuedInteractiveProducerWithFlux.cs
@@ -8,23 +8,35 @@ using Verse.AI;
namespace ArachnaeSwarm
{
- // 带状态和品质的物品订单(与 Building_Ootheca 统一的累计进度模式)
- public class QueuedItemOrder : IExposable
+ // 带状态和品质的物品订单(实现 IIncubationState 接口)
+ public class QueuedItemOrder : IExposable, IIncubationState
{
public ProcessDef process;
public string tempThingDefName;
public OrderStatus status = OrderStatus.WaitingForLarva;
- // 进度系统(累计模式,与 Building_Ootheca 统一)
- public float incubationProgress = 0f;
- public float incubationDuration = 0f;
+ // 进度系统
+ private float _incubationProgress = 0f;
+ private float _incubationDuration = 0f;
- // 通量品质系统
- public float qualityProgress = 0f;
- public float qualityTotal = 0f;
+ // 品质系统
+ private float _qualityProgress = 0f;
+ private float _qualityTotal = 0f;
- public float ProgressPercent => incubationDuration > 0 ? incubationProgress / incubationDuration : 0f;
- public float QualityPercent => qualityTotal > 0 ? qualityProgress / qualityTotal : 0f;
+ // IIncubationState 接口实现
+ public float IncubationProgress { get => _incubationProgress; set => _incubationProgress = value; }
+ public float IncubationDuration => _incubationDuration;
+ public float QualityProgress { get => _qualityProgress; set => _qualityProgress = value; }
+ public float QualityTotal => _qualityTotal;
+
+ public float ProgressPercent => _incubationDuration > 0 ? _incubationProgress / _incubationDuration : 0f;
+ public float QualityPercent => _qualityTotal > 0 ? _qualityProgress / _qualityTotal : 0f;
+
+ public void SetDuration(float duration)
+ {
+ _incubationDuration = duration;
+ _qualityTotal = duration;
+ }
public void ExposeData()
{
@@ -34,10 +46,10 @@ namespace ArachnaeSwarm
}
Scribe_Values.Look(ref tempThingDefName, "thingDefName");
Scribe_Values.Look(ref status, "status", OrderStatus.WaitingForLarva);
- Scribe_Values.Look(ref incubationProgress, "incubationProgress", 0f);
- Scribe_Values.Look(ref incubationDuration, "incubationDuration", 0f);
- Scribe_Values.Look(ref qualityProgress, "qualityProgress", 0f);
- Scribe_Values.Look(ref qualityTotal, "qualityTotal", 0f);
+ Scribe_Values.Look(ref _incubationProgress, "incubationProgress", 0f);
+ Scribe_Values.Look(ref _incubationDuration, "incubationDuration", 0f);
+ Scribe_Values.Look(ref _qualityProgress, "qualityProgress", 0f);
+ Scribe_Values.Look(ref _qualityTotal, "qualityTotal", 0f);
}
}
@@ -259,11 +271,7 @@ namespace ArachnaeSwarm
if (waitingOrder != null)
{
waitingOrder.status = OrderStatus.Incubating;
- // 使用累计进度模式(与 Building_Ootheca 统一)
- waitingOrder.incubationDuration = waitingOrder.process.productionTicks;
- waitingOrder.incubationProgress = 0f;
- waitingOrder.qualityTotal = waitingOrder.incubationDuration;
- waitingOrder.qualityProgress = 0f;
+ waitingOrder.SetDuration(waitingOrder.process.productionTicks);
}
assignedLarvae.Remove(larva);
@@ -301,36 +309,20 @@ namespace ArachnaeSwarm
FuelComp.ConsumeFuel(fuelPerTick);
}
- // 进度和品质处理(与 Building_Ootheca 统一)
+ // 进度和品质处理(调用统一工具方法)
+ float speedFactor = 1f + (FacilitiesComp?.GetStatOffset(StatDef.Named("ARA_IncubationSpeedFactor")) ?? 0f);
+ bool isDormant = IsDormant || !hasFuel;
+
foreach (var order in orders.Where(o => o.status == OrderStatus.Incubating))
{
- if (IsDormant)
- {
- // 休眠时:不推进进度,品质衰减
- float qualityDecay = (order.qualityTotal * 0.1f) / 60000f;
- order.qualityProgress = Mathf.Max(0f, order.qualityProgress - qualityDecay);
- }
- else
- {
- // 正常工作:推进进度和品质
- float speedFactor = 1f + (FacilitiesComp?.GetStatOffset(StatDef.Named("ARA_IncubationSpeedFactor")) ?? 0f);
- float fluxSpeed = speedFactor * FluxEfficiency * 5f;
-
- // 进度推进(累计模式)
- order.incubationProgress += fluxSpeed;
-
- // 品质增长 - 低活性时品质增长更快
- float qualityBonus = 1f + (1f - neutronFlux) * 0.5f;
- float qualityGain = speedFactor * qualityBonus;
- order.qualityProgress = Mathf.Min(order.qualityProgress + qualityGain, order.qualityTotal);
- }
+ IncubatorUtils.TickIncubation(order, speedFactor, neutronFlux, isDormant);
}
- // 完成检查(进度达到持续时间时完成)
+ // 完成检查
orders.RemoveAll(order =>
{
if (order.status == OrderStatus.Incubating &&
- order.incubationProgress >= order.incubationDuration)
+ IncubatorUtils.IsIncubationComplete(order))
{
FinishProduction(order);
return true;
diff --git a/Source/ArachnaeSwarm/Building_Comps/ARA_SpawnPawnFromList/CompQueuedPawnSpawnerWithFlux.cs b/Source/ArachnaeSwarm/Building_Comps/ARA_SpawnPawnFromList/CompQueuedPawnSpawnerWithFlux.cs
index 7e98a46..27106ad 100644
--- a/Source/ArachnaeSwarm/Building_Comps/ARA_SpawnPawnFromList/CompQueuedPawnSpawnerWithFlux.cs
+++ b/Source/ArachnaeSwarm/Building_Comps/ARA_SpawnPawnFromList/CompQueuedPawnSpawnerWithFlux.cs
@@ -25,31 +25,43 @@ namespace ArachnaeSwarm
public string estimatedQuality;
}
- // 带状态和品质的督虫订单
- public class QueuedPawnOrder : IExposable
+ // 带状态和品质的督虫订单(实现 IIncubationState 接口)
+ public class QueuedPawnOrder : IExposable, IIncubationState
{
public IncubationConfig config;
public OrderStatus status = OrderStatus.WaitingForLarva;
// 进度系统(与 Building_Ootheca 统一)
- public float incubationProgress = 0f;
- public float incubationDuration = 0f;
+ private float _incubationProgress = 0f;
+ private float _incubationDuration = 0f;
// 品质系统
- public float qualityProgress = 0f;
- public float qualityTotal = 0f;
+ private float _qualityProgress = 0f;
+ private float _qualityTotal = 0f;
- public float ProgressPercent => incubationDuration > 0 ? incubationProgress / incubationDuration : 0f;
- public float QualityPercent => qualityTotal > 0 ? qualityProgress / qualityTotal : 0f;
+ // IIncubationState 接口实现
+ public float IncubationProgress { get => _incubationProgress; set => _incubationProgress = value; }
+ public float IncubationDuration => _incubationDuration;
+ public float QualityProgress { get => _qualityProgress; set => _qualityProgress = value; }
+ public float QualityTotal => _qualityTotal;
+
+ public float ProgressPercent => _incubationDuration > 0 ? _incubationProgress / _incubationDuration : 0f;
+ public float QualityPercent => _qualityTotal > 0 ? _qualityProgress / _qualityTotal : 0f;
+
+ public void SetDuration(float duration)
+ {
+ _incubationDuration = duration;
+ _qualityTotal = duration; // 品质总量与孵化时间相同
+ }
public void ExposeData()
{
Scribe_Deep.Look(ref config, "config");
Scribe_Values.Look(ref status, "status", OrderStatus.WaitingForLarva);
- Scribe_Values.Look(ref incubationProgress, "incubationProgress", 0f);
- Scribe_Values.Look(ref incubationDuration, "incubationDuration", 0f);
- Scribe_Values.Look(ref qualityProgress, "qualityProgress", 0f);
- Scribe_Values.Look(ref qualityTotal, "qualityTotal", 0f);
+ Scribe_Values.Look(ref _incubationProgress, "incubationProgress", 0f);
+ Scribe_Values.Look(ref _incubationDuration, "incubationDuration", 0f);
+ Scribe_Values.Look(ref _qualityProgress, "qualityProgress", 0f);
+ Scribe_Values.Look(ref _qualityTotal, "qualityTotal", 0f);
}
}
@@ -180,8 +192,8 @@ namespace ArachnaeSwarm
private float GetRemainingTicks(QueuedPawnOrder order)
{
- if (order.status != OrderStatus.Incubating || order.incubationDuration <= 0) return 0f;
- float remaining = order.incubationDuration - order.incubationProgress;
+ if (order.status != OrderStatus.Incubating || order.IncubationDuration <= 0) return 0f;
+ float remaining = order.IncubationDuration - order.IncubationProgress;
float speedFactor = 1f + (FacilitiesComp?.GetStatOffset(StatDef.Named("ARA_IncubationSpeedFactor")) ?? 0f);
float fluxSpeed = speedFactor * FluxEfficiency * 5f;
return fluxSpeed > 0 ? remaining / fluxSpeed : remaining;
@@ -275,11 +287,7 @@ namespace ArachnaeSwarm
if (waitingOrder != null && waitingOrder.config != null)
{
waitingOrder.status = OrderStatus.Incubating;
- // 使用累计进度模式(与 Building_Ootheca 统一)
- waitingOrder.incubationDuration = waitingOrder.config.daysRequired * 60000f;
- waitingOrder.incubationProgress = 0f;
- waitingOrder.qualityTotal = waitingOrder.incubationDuration;
- waitingOrder.qualityProgress = 0f;
+ waitingOrder.SetDuration(waitingOrder.config.daysRequired * 60000f);
}
assignedLarvae.Remove(larva);
@@ -316,36 +324,20 @@ namespace ArachnaeSwarm
FuelComp.ConsumeFuel(fuelPerTick);
}
- // 进度和品质处理(与 Building_Ootheca 统一)
+ // 进度和品质处理(调用统一工具方法)
+ float speedFactor = 1f + (FacilitiesComp?.GetStatOffset(StatDef.Named("ARA_IncubationSpeedFactor")) ?? 0f);
+ bool isDormant = IsDormant || !hasFuel;
+
foreach (var order in orders.Where(o => o.status == OrderStatus.Incubating))
{
- if (IsDormant)
- {
- // 休眠时:不推进进度,品质衰减
- float qualityDecay = (order.qualityTotal * 0.1f) / 60000f;
- order.qualityProgress = Mathf.Max(0f, order.qualityProgress - qualityDecay);
- }
- else
- {
- // 正常工作:推进进度和品质
- float speedFactor = 1f + (FacilitiesComp?.GetStatOffset(StatDef.Named("ARA_IncubationSpeedFactor")) ?? 0f);
- float fluxSpeed = speedFactor * FluxEfficiency * 5f;
-
- // 进度推进(累计模式)
- order.incubationProgress += fluxSpeed;
-
- // 品质增长 - 低活性时品质增长更快
- float qualityBonus = 1f + (1f - neutronFlux) * 0.5f;
- float qualityGain = speedFactor * qualityBonus;
- order.qualityProgress = Mathf.Min(order.qualityProgress + qualityGain, order.qualityTotal);
- }
+ IncubatorUtils.TickIncubation(order, speedFactor, neutronFlux, isDormant);
}
- // 完成检查(进度达到持续时间时完成)
+ // 完成检查
orders.RemoveAll(order =>
{
if (order.status == OrderStatus.Incubating &&
- order.incubationProgress >= order.incubationDuration)
+ IncubatorUtils.IsIncubationComplete(order))
{
CompleteOrder(order);
return true;
diff --git a/Source/ArachnaeSwarm/Buildings/Building_EquipmentOotheca/Building_EquipmentOotheca.cs b/Source/ArachnaeSwarm/Buildings/Building_EquipmentOotheca/Building_EquipmentOotheca.cs
index eaa0eda..e425fbe 100644
--- a/Source/ArachnaeSwarm/Buildings/Building_EquipmentOotheca/Building_EquipmentOotheca.cs
+++ b/Source/ArachnaeSwarm/Buildings/Building_EquipmentOotheca/Building_EquipmentOotheca.cs
@@ -135,13 +135,12 @@ namespace ArachnaeSwarm
}
else
{
- // 正常状态:应用活性效率
+ // 进度增长
float fluxSpeed = SpeedMultiplier * FluxEfficiency * 5f;
incubationProgress += fluxSpeed;
- // 品质独立增长
- float qualityBonus = 1f + (1f - neutronFlux) * 0.5f;
- float qualityGain = SpeedMultiplier * QualityMultiplier * qualityBonus;
+ // 品质增长(新公式:50%通量时与进度同步)
+ float qualityGain = IncubatorUtils.CalculateQualityGainNew(fluxSpeed, neutronFlux);
qualityProgress = Mathf.Min(qualityProgress + qualityGain, qualityTotal);
}
@@ -404,21 +403,53 @@ namespace ArachnaeSwarm
yield return new Gizmo_EquipmentIncubationProgress(this);
yield return new Gizmo_NeutronFlux(this);
- if (!isIncubating && EquipmentIncubatorData?.SelectedConfig?.IsResearchComplete == true)
+ var config = EquipmentIncubatorData?.SelectedConfig;
+
+ // 添加订单按钮
+ if (!isIncubating && assignedLarva == null)
{
yield return new Command_Action
{
- defaultLabel = "呼叫幼虫",
- icon = ContentFinder.Get("ArachnaeSwarm/UI/Commands/ARA_CallLarva", false),
- action = CallLarva
+ defaultLabel = "ARA_Gizmo_AddOrder".Translate(config != null ? 1 : 0, 1),
+ defaultDesc = "ARA_Gizmo_AddOrderDesc_Item".Translate(),
+ icon = ContentFinder.Get("ArachnaeSwarm/UI/Commands/ARA_NodeSwarmIcon", false),
+ action = () => EquipmentIncubatorData?.ShowFloatMenu()
};
}
+ // 呼叫幼虫按钮逻辑
+ if (!isIncubating && config != null && config.IsResearchComplete)
+ {
+ if (assignedLarva == null)
+ {
+ yield return new Command_Action
+ {
+ defaultLabel = "ARA_Gizmo_CallLarva".Translate(),
+ defaultDesc = BuildCallLarvaDescription(config),
+ icon = ContentFinder.Get("ArachnaeSwarm/UI/Commands/ARA_CallLarva", false),
+ action = CallLarva
+ };
+ }
+ else
+ {
+ string statusText = larvaOperateTicksRemaining > 0
+ ? "ARA_Gizmo_LarvaActivating".Translate()
+ : "ARA_Gizmo_LarvaOnTheWay".Translate();
+ yield return new Command_Action
+ {
+ defaultLabel = statusText,
+ defaultDesc = "ARA_Gizmo_LarvaWorkingDesc".Translate(0),
+ icon = ContentFinder.Get("ArachnaeSwarm/UI/Commands/ARA_CallLarva", false),
+ Disabled = true
+ };
+ }
+ }
+
if (isIncubating)
{
yield return new Command_Action
{
- defaultLabel = "取消孵化",
+ defaultLabel = "ARA_OothecaIncubator.CancelIncubation".Translate(),
icon = ContentFinder.Get("UI/Commands/Cancel", false),
action = CancelIncubation
};
diff --git a/Source/ArachnaeSwarm/Buildings/Building_EquipmentOotheca/CompProperties_EquipmentIncubatorData.cs b/Source/ArachnaeSwarm/Buildings/Building_EquipmentOotheca/CompProperties_EquipmentIncubatorData.cs
index 2192694..ec87fa8 100644
--- a/Source/ArachnaeSwarm/Buildings/Building_EquipmentOotheca/CompProperties_EquipmentIncubatorData.cs
+++ b/Source/ArachnaeSwarm/Buildings/Building_EquipmentOotheca/CompProperties_EquipmentIncubatorData.cs
@@ -320,6 +320,36 @@ namespace ArachnaeSwarm
{
return selectedIndex;
}
+
+ // 显示目标选择菜单
+ public void ShowFloatMenu()
+ {
+ var configs = IncubationConfigs;
+ if (configs == null || configs.Count == 0) return;
+
+ List options = new List();
+
+ for (int i = 0; i < configs.Count; i++)
+ {
+ var cfg = configs[i];
+ int index = i;
+
+ string label = cfg.thingDef.LabelCap;
+ if (cfg.requiredResearch != null && !cfg.requiredResearch.IsFinished)
+ {
+ label += " (" + "ARA_Menu_RequiresResearch".Translate(cfg.requiredResearch.LabelCap) + ")";
+ options.Add(new FloatMenuOption(label, null));
+ }
+ else
+ {
+ label += " (" + "ARA_Menu_Days".Translate(cfg.DaysRequired.ToString("F1")) + ")";
+ options.Add(new FloatMenuOption(label, () => SwitchToConfig(index)));
+ }
+ }
+
+ if (options.Count > 0)
+ Find.WindowStack.Add(new FloatMenu(options, "ARA_Menu_SelectProductionTarget".Translate()));
+ }
// 存档加载
public override void PostExposeData()
diff --git a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Building_Ootheca.cs b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Building_Ootheca.cs
index 95e0639..60df022 100644
--- a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Building_Ootheca.cs
+++ b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Building_Ootheca.cs
@@ -240,11 +240,12 @@ namespace ArachnaeSwarm
}
else
{
+ // 进度增长
float fluxSpeed = SpeedMultiplier * FluxEfficiency * 5f;
incubationProgress += fluxSpeed;
- float qualityBonus = 1f + (1f - neutronFlux) * 0.5f;
- float qualityGain = SpeedMultiplier * QualityMultiplier * qualityBonus;
+ // 品质增长(新公式:50%通量时与进度同步)
+ float qualityGain = IncubatorUtils.CalculateQualityGainNew(fluxSpeed, neutronFlux);
qualityProgress = Mathf.Min(qualityProgress + qualityGain, qualityTotal);
}
@@ -408,17 +409,49 @@ namespace ArachnaeSwarm
yield return new Gizmo_NeutronFlux(this);
var config = IncubatorData?.SelectedConfig;
- if (!isIncubating && config != null && config.IsResearchComplete)
+
+ // 添加订单按钮(未孵化且未选目标,或已选目标但支持切换)
+ if (!isIncubating && assignedLarva == null)
{
yield return new Command_Action
{
- defaultLabel = "ARA_OothecaIncubator.CallLarva".Translate(),
- defaultDesc = BuildCallLarvaDescription(config),
- icon = ContentFinder.Get("ArachnaeSwarm/UI/Commands/ARA_CallLarva", false),
- action = CallLarva
+ defaultLabel = "ARA_Gizmo_AddOrder".Translate(config != null ? 1 : 0, 1),
+ defaultDesc = "ARA_Gizmo_AddOrderDesc_Pawn".Translate(),
+ icon = ContentFinder.Get("ArachnaeSwarm/UI/Commands/ARA_NodeSwarmIcon", false),
+ action = () => IncubatorData?.ShowFloatMenu()
};
}
+ // 呼叫幼虫按钮逻辑
+ if (!isIncubating && config != null && config.IsResearchComplete)
+ {
+ if (assignedLarva == null)
+ {
+ // 无幼虫,可以呼叫
+ yield return new Command_Action
+ {
+ defaultLabel = "ARA_Gizmo_CallLarva".Translate(),
+ defaultDesc = BuildCallLarvaDescription(config),
+ icon = ContentFinder.Get("ArachnaeSwarm/UI/Commands/ARA_CallLarva", false),
+ action = CallLarva
+ };
+ }
+ else
+ {
+ // 幼虫在路上或工作中
+ string statusText = larvaOperateTicksRemaining > 0
+ ? "ARA_Gizmo_LarvaActivating".Translate()
+ : "ARA_Gizmo_LarvaOnTheWay".Translate();
+ yield return new Command_Action
+ {
+ defaultLabel = statusText,
+ defaultDesc = "ARA_Gizmo_LarvaWorkingDesc".Translate(0),
+ icon = ContentFinder.Get("ArachnaeSwarm/UI/Commands/ARA_CallLarva", false),
+ Disabled = true
+ };
+ }
+ }
+
if (isIncubating)
{
yield return new Command_Action
diff --git a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/CompProperties_IncubatorData.cs b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/CompProperties_IncubatorData.cs
index ea634f1..19d3700 100644
--- a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/CompProperties_IncubatorData.cs
+++ b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/CompProperties_IncubatorData.cs
@@ -384,6 +384,36 @@ namespace ArachnaeSwarm
{
return selectedIndex;
}
+
+ // 显示目标选择菜单
+ public void ShowFloatMenu()
+ {
+ var configs = IncubationConfigs;
+ if (configs == null || configs.Count == 0) return;
+
+ List options = new List();
+
+ 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 += " (" + "ARA_Menu_RequiresResearch".Translate(cfg.requiredResearch.LabelCap) + ")";
+ options.Add(new FloatMenuOption(label, null));
+ }
+ else
+ {
+ label += " (" + "ARA_Menu_Days".Translate(cfg.daysRequired.ToString("F1")) + ")";
+ options.Add(new FloatMenuOption(label, () => SwitchToConfig(index)));
+ }
+ }
+
+ if (options.Count > 0)
+ Find.WindowStack.Add(new FloatMenu(options, "ARA_Menu_SelectIncubationTarget".Translate()));
+ }
// 存档加载
public override void PostExposeData()
diff --git a/Source/ArachnaeSwarm/Buildings/IncubatorUtils.cs b/Source/ArachnaeSwarm/Buildings/IncubatorUtils.cs
index f370a52..42fe6a7 100644
--- a/Source/ArachnaeSwarm/Buildings/IncubatorUtils.cs
+++ b/Source/ArachnaeSwarm/Buildings/IncubatorUtils.cs
@@ -6,12 +6,67 @@ using Verse;
namespace ArachnaeSwarm
{
+ ///
+ /// 孵化状态数据接口 - 所有孵化系统共用
+ ///
+ public interface IIncubationState
+ {
+ float IncubationProgress { get; set; }
+ float IncubationDuration { get; }
+ float QualityProgress { get; set; }
+ float QualityTotal { get; }
+ }
+
///
/// 孵化器通用工具类
/// 统一核心算法,保持各孵化器行为一致
///
public static class IncubatorUtils
{
+ // ============================================
+ // 核心 Tick 方法(各孵化器调用此方法)
+ // ============================================
+
+ ///
+ /// 执行单tick的孵化进度和品质更新(核心方法)
+ /// 所有孵化器应调用此方法以保持行为一致
+ ///
+ /// 孵化状态(实现 IIncubationState 接口)
+ /// 速度倍率(来自设施等)
+ /// 当前通量值 0-1
+ /// 是否休眠(通量过低或无燃料)
+ /// 本tick的进度增量(用于判断完成)
+ public static float TickIncubation(IIncubationState state, float speedMultiplier, float neutronFlux, bool isDormant)
+ {
+ if (isDormant)
+ {
+ // 休眠时:进度不增长,品质衰减
+ float qualityDecay = CalculateQualityDecay(state.QualityTotal);
+ state.QualityProgress = Mathf.Max(0f, state.QualityProgress - qualityDecay);
+ return 0f;
+ }
+ else
+ {
+ // 正常工作:进度和品质同步增长
+ float fluxEfficiency = GetFluxEfficiency(neutronFlux);
+ float progressGain = CalculateProgressGain(speedMultiplier, fluxEfficiency);
+ float qualityGain = CalculateQualityGainNew(progressGain, neutronFlux);
+
+ state.IncubationProgress += progressGain;
+ state.QualityProgress = Mathf.Min(state.QualityProgress + qualityGain, state.QualityTotal);
+
+ return progressGain;
+ }
+ }
+
+ ///
+ /// 检查孵化是否完成
+ ///
+ public static bool IsIncubationComplete(IIncubationState state)
+ {
+ return state.IncubationProgress >= state.IncubationDuration;
+ }
+
// ============================================
// 通量系统
// ============================================
@@ -34,16 +89,16 @@ namespace ArachnaeSwarm
}
///
- /// 获取模式名称
+ /// 获取模式名称(使用翻译键)
///
public static string GetFluxModeName(FluxMode mode)
{
return mode switch
{
- FluxMode.Manual => "手动",
- FluxMode.Quality => "品质",
- FluxMode.Balance => "平衡",
- FluxMode.Speed => "速度",
+ FluxMode.Manual => "ARA_FluxMode_Manual".Translate(),
+ FluxMode.Quality => "ARA_FluxMode_Quality".Translate(),
+ FluxMode.Balance => "ARA_FluxMode_Balance".Translate(),
+ FluxMode.Speed => "ARA_FluxMode_Speed".Translate(),
_ => "?"
};
}
@@ -64,13 +119,38 @@ namespace ArachnaeSwarm
}
// ============================================
- // 品质系统
+ // 进度系统
// ============================================
///
- /// 计算品质增长(低通量时增长更快)
- /// 公式:qualityGain = speedFactor * (1 + (1 - flux) * 0.5)
+ /// 计算单tick的进度增量
+ /// 公式:progressGain = speedMultiplier * fluxEfficiency * 5
///
+ public static float CalculateProgressGain(float speedMultiplier, float fluxEfficiency)
+ {
+ return speedMultiplier * fluxEfficiency * 5f;
+ }
+
+ // ============================================
+ // 品质系统(新公式:50%通量时与进度同步)
+ // ============================================
+
+ ///
+ /// 计算单tick的品质增量(新公式)
+ /// 核心:50%通量时品质增长 = 进度增长(1:1同步)
+ /// 公式:qualityGain = progressGain × 2 × (1 - neutronFlux)
+ ///
+ public static float CalculateQualityGainNew(float progressGain, float neutronFlux)
+ {
+ // qualityCoeff: 0%通量=2.0, 25%通量=1.5, 50%通量=1.0, 75%通量=0.5, 100%通量=0
+ float qualityCoeff = 2f * (1f - neutronFlux);
+ return progressGain * qualityCoeff;
+ }
+
+ ///
+ /// [已废弃] 旧品质计算公式
+ ///
+ [System.Obsolete("Use CalculateQualityGainNew instead")]
public static float CalculateQualityGain(float neutronFlux, float speedFactor)
{
float qualityBonus = 1f + (1f - neutronFlux) * 0.5f;