This commit is contained in:
2025-12-23 17:56:14 +08:00
parent 1264f6009e
commit 23302daac7
12 changed files with 358 additions and 114 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -52,6 +52,54 @@
<li>Insect</li>
</tags> -->
</TerrainDef>
<TerrainDef ParentName="FloorBase" MayRequire="Ludeon.RimWorld.Odyssey">
<defName>ARA_InsectCreepFloor</defName>
<label>阿拉克涅强固菌毯</label>
<description>由阿拉克涅虫族所铺设的由真菌、甲壳素分泌物混合得到的地面,性质类似于阿拉克涅菌毯,不过可以在支撑结构上蔓延,以作为虫群的逆重飞船地基。</description>
<texturePath>ArachnaeSwarm/Terrain/Surfaces/ARA_InsectCreep</texturePath>
<pollutionTintColor>(0.95, 0.95, 0.93, 1)</pollutionTintColor>
<color>(209, 207, 184)</color>
<fertility>0</fertility>
<edgeType>FadeRough</edgeType>
<renderPrecedence>399</renderPrecedence>
<constructEffect>ConstructMetal</constructEffect>
<isPaintable>true</isPaintable>
<designationCategory>ARA_Buildings</designationCategory>
<isFoundation>true</isFoundation>
<preventCraters>true</preventCraters>
<designationHotKey>Misc9</designationHotKey>
<researchPrerequisites>
<li>ARA_Base_Technology</li>
</researchPrerequisites>
<affordances>
<li>ARA_Creep</li>
<li>Substructure</li>
</affordances>
<statBases>
<Beauty>0</Beauty>
<CleaningTimeFactor>0.25</CleaningTimeFactor>
<Cleanliness>0</Cleanliness>
<Flammability>0</Flammability>
<WorkToBuild>100</WorkToBuild>
</statBases>
<costList>
<GravlitePanel>1</GravlitePanel>
<Steel>2</Steel>
<ARA_Carapace>2</ARA_Carapace>
</costList>
<uiOrder>1000</uiOrder>
<requireInspectedGravEngine>true</requireInspectedGravEngine>
<terrainAffordanceNeeded>Walkable</terrainAffordanceNeeded>
<resourcesFractionWhenDeconstructed>1</resourcesFractionWhenDeconstructed>
<tags>
<li>ARA_Creep</li>
<li>Substructure</li>
</tags>
<placeWorkers>
<li>PlaceWorker_InSubstructureFootprint</li>
<li>PlaceWorker_BuildingsValidOverSubstructure</li>
</placeWorkers>
</TerrainDef>
<TerrainDef ParentName="FloorBase">
<defName>ARA_InsectCreepTile</defName>
<label>阿拉克涅菌毯砖</label>

View File

@@ -430,18 +430,24 @@
<warningThreshold>0.2</warningThreshold>
<maintenanceThresholdForJob>0.5</maintenanceThresholdForJob>
</li>
<!-- 虫蜜燃料组件(孵化活性系统 -->
<!-- 虫蜜燃料系统 -->
<li Class="ArachnaeSwarm.CompProperties_RefuelableNutrition">
<fuelConsumptionRate>0</fuelConsumptionRate>
<fuelCapacity>10</fuelCapacity>
<initialFuelPercent>0</initialFuelPercent>
<initialConfigurableTargetFuelLevel>5</initialConfigurableTargetFuelLevel>
<showAllowAutoRefuelToggle>true</showAllowAutoRefuelToggle>
<fuelCapacity>25.0</fuelCapacity>
<fuelFilter>
<thingDefs>
<li>ARA_InsectJelly</li>
</thingDefs>
</fuelFilter>
<fuelGizmoLabel>虫蜜</fuelGizmoLabel>
<showAllowAutoRefuelToggle>true</showAllowAutoRefuelToggle>
<targetFuelLevelConfigurable>true</targetFuelLevelConfigurable>
<initialConfigurableTargetFuelLevel>5</initialConfigurableTargetFuelLevel>
<consumeFuelOnlyWhenUsed>true</consumeFuelOnlyWhenUsed>
</li>
<li Class="CompProperties_AffectedByFacilities">
<linkableFacilities>
<li>ARA_NutrientNetworkTower</li>
</linkableFacilities>
</li>
<li Class="ArachnaeSwarm.CompProperties_EquipmentIncubatorData">
<!-- autoScanThingDefs默认为true会自动扫描所有ThingDef -->

View File

@@ -41,6 +41,8 @@
<ARA_Gizmo_CallLarvaDesc>呼叫一只幼虫来激活下一个订单(还有{0}个等待中)</ARA_Gizmo_CallLarvaDesc>
<ARA_Gizmo_LarvaWorking>幼虫工作中</ARA_Gizmo_LarvaWorking>
<ARA_Gizmo_LarvaWorkingDesc>一只幼虫正在操作孵化器(还有{0}个订单等待)</ARA_Gizmo_LarvaWorkingDesc>
<ARA_Gizmo_LarvaActivating>幼虫激活中</ARA_Gizmo_LarvaActivating>
<ARA_Gizmo_LarvaOnTheWay>幼虫赶路中</ARA_Gizmo_LarvaOnTheWay>
<!-- 菜单 -->
<ARA_Menu_SelectIncubationTarget>选择孵化目标</ARA_Menu_SelectIncubationTarget>

View File

@@ -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;

View File

@@ -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;

View File

@@ -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<Texture2D>.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<Texture2D>.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<Texture2D>.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<Texture2D>.Get("ArachnaeSwarm/UI/Commands/ARA_CallLarva", false),
Disabled = true
};
}
}
if (isIncubating)
{
yield return new Command_Action
{
defaultLabel = "取消孵化",
defaultLabel = "ARA_OothecaIncubator.CancelIncubation".Translate(),
icon = ContentFinder<Texture2D>.Get("UI/Commands/Cancel", false),
action = CancelIncubation
};

View File

@@ -320,6 +320,36 @@ namespace ArachnaeSwarm
{
return selectedIndex;
}
// 显示目标选择菜单
public void ShowFloatMenu()
{
var configs = 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;
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()

View File

@@ -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<Texture2D>.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<Texture2D>.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<Texture2D>.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<Texture2D>.Get("ArachnaeSwarm/UI/Commands/ARA_CallLarva", false),
Disabled = true
};
}
}
if (isIncubating)
{
yield return new Command_Action

View File

@@ -384,6 +384,36 @@ namespace ArachnaeSwarm
{
return selectedIndex;
}
// 显示目标选择菜单
public void ShowFloatMenu()
{
var configs = 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;
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()

View File

@@ -6,12 +6,67 @@ using Verse;
namespace ArachnaeSwarm
{
/// <summary>
/// 孵化状态数据接口 - 所有孵化系统共用
/// </summary>
public interface IIncubationState
{
float IncubationProgress { get; set; }
float IncubationDuration { get; }
float QualityProgress { get; set; }
float QualityTotal { get; }
}
/// <summary>
/// 孵化器通用工具类
/// 统一核心算法,保持各孵化器行为一致
/// </summary>
public static class IncubatorUtils
{
// ============================================
// 核心 Tick 方法(各孵化器调用此方法)
// ============================================
/// <summary>
/// 执行单tick的孵化进度和品质更新核心方法
/// 所有孵化器应调用此方法以保持行为一致
/// </summary>
/// <param name="state">孵化状态(实现 IIncubationState 接口)</param>
/// <param name="speedMultiplier">速度倍率(来自设施等)</param>
/// <param name="neutronFlux">当前通量值 0-1</param>
/// <param name="isDormant">是否休眠(通量过低或无燃料)</param>
/// <returns>本tick的进度增量用于判断完成</returns>
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;
}
}
/// <summary>
/// 检查孵化是否完成
/// </summary>
public static bool IsIncubationComplete(IIncubationState state)
{
return state.IncubationProgress >= state.IncubationDuration;
}
// ============================================
// 通量系统
// ============================================
@@ -34,16 +89,16 @@ namespace ArachnaeSwarm
}
/// <summary>
/// 获取模式名称
/// 获取模式名称(使用翻译键)
/// </summary>
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
}
// ============================================
// 品质系统
// 进度系统
// ============================================
/// <summary>
/// 计算品质增长(低通量时增长更快)
/// 公式:qualityGain = speedFactor * (1 + (1 - flux) * 0.5)
/// 计算单tick的进度增量
/// 公式:progressGain = speedMultiplier * fluxEfficiency * 5
/// </summary>
public static float CalculateProgressGain(float speedMultiplier, float fluxEfficiency)
{
return speedMultiplier * fluxEfficiency * 5f;
}
// ============================================
// 品质系统新公式50%通量时与进度同步)
// ============================================
/// <summary>
/// 计算单tick的品质增量新公式
/// 核心50%通量时品质增长 = 进度增长1:1同步
/// 公式qualityGain = progressGain × 2 × (1 - neutronFlux)
/// </summary>
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;
}
/// <summary>
/// [已废弃] 旧品质计算公式
/// </summary>
[System.Obsolete("Use CalculateQualityGainNew instead")]
public static float CalculateQualityGain(float neutronFlux, float speedFactor)
{
float qualityBonus = 1f + (1f - neutronFlux) * 0.5f;