diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll index c65fc0c..826b867 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/Defs/HediffDefs/ARA_Hediffs_BodyPart.xml b/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_BodyPart.xml index ac1af08..b875f56 100644 --- a/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_BodyPart.xml +++ b/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_BodyPart.xml @@ -5,7 +5,7 @@ true - + ArachnaeFighter_Swarm_Claws_Part 战士种虫镰 @@ -51,7 +51,7 @@ - + ArachnaeNode_Race_Myrmecocystus_Tail_Part 蜜罐种虫尾 @@ -146,7 +146,7 @@ - + ArachnaeNode_Race_Skyraider_Wings_Part 空天种翼翅 diff --git a/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_HiveMind.xml b/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_HiveMind.xml index 1652ecb..974d4be 100644 --- a/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_HiveMind.xml +++ b/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_HiveMind.xml @@ -195,7 +195,7 @@ Hediff_High (0.6, 0.8, 0.9) 0.01 - 0 + 0.01 阿拉克涅虫族记录寿命的hediff,正常情况下你不应该看见这个。 diff --git a/1.6/1.6/Defs/Thing_Misc/Weapons/ARA_Weapon.xml b/1.6/1.6/Defs/Thing_Misc/Weapons/ARA_Weapon.xml index 0d1d63d..9218828 100644 --- a/1.6/1.6/Defs/Thing_Misc/Weapons/ARA_Weapon.xml +++ b/1.6/1.6/Defs/Thing_Misc/Weapons/ARA_Weapon.xml @@ -1333,7 +1333,7 @@ 0.3 0.5 450 - 15 + 0.5
  • diff --git a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/ARA_InteractiveProducer_Keys.xml b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/ARA_InteractiveProducer_Keys.xml index e607442..673639b 100644 --- a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/ARA_InteractiveProducer_Keys.xml +++ b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/ARA_InteractiveProducer_Keys.xml @@ -7,7 +7,8 @@ 安全范围 无法开始生产 无燃料 - 开始生产 {0}({1} 营养) + 开始生产 {0} + ({0} 营养) 取消生产 停止当前的生产流程。 正在生产 {0} @@ -23,4 +24,6 @@ 孵化 {0} 茧正在稳定中:{0} + + 正在生产: \ No newline at end of file diff --git a/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompInteractiveProducer.cs b/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompInteractiveProducer.cs index 2cd67c4..76ab88b 100644 --- a/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompInteractiveProducer.cs +++ b/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompInteractiveProducer.cs @@ -307,17 +307,16 @@ namespace ArachnaeSwarm // 获取营养需求 - 直接从 ProcessDef 中读取 float nutritionCost = process.totalNutritionNeeded; + string label = "StartProduction".Translate(process.thingDef.label) + " " + "ARA_ProductionCost".Translate(nutritionCost.ToString("F0")); + if (process.requiredResearch != null && !process.requiredResearch.IsFinished) { - // 修改:在未研究完成的情况下也显示营养需求 - string disabledText = "StartProduction".Translate(process.thingDef.label, nutritionCost.ToString("F1")) + - " (" + "Requires".Translate() + ": " + process.requiredResearch.label + ")"; + string disabledText = label + " (" + "Requires".Translate() + ": " + process.requiredResearch.label + ")"; yield return new FloatMenuOption(disabledText, null); } else { - // 修改:使用新的翻译键显示营养需求 - yield return new FloatMenuOption("StartProduction".Translate(process.thingDef.label, nutritionCost.ToString("F1")), () => + yield return new FloatMenuOption(label, () => { this._selectedProcess = process; Job job = JobMaker.MakeJob(DefDatabase.GetNamed("ARA_StartInteractiveProduction"), parent); diff --git a/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompQueuedInteractiveProducer.cs b/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompQueuedInteractiveProducer.cs index df3d84b..864e0d1 100644 --- a/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompQueuedInteractiveProducer.cs +++ b/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompQueuedInteractiveProducer.cs @@ -108,13 +108,15 @@ namespace ArachnaeSwarm foreach (var process in Processes) { + string label = "StartProduction".Translate(process.thingDef.label) + " " + "ARA_ProductionCost".Translate(process.totalNutritionNeeded.ToString("F0")); + if (process.requiredResearch != null && !process.requiredResearch.IsFinished) { - yield return new FloatMenuOption("StartProduction".Translate(process.thingDef.label) + " (" + "Requires".Translate() + ": " + process.requiredResearch.label + ")", null); + yield return new FloatMenuOption(label + " (" + "Requires".Translate() + ": " + process.requiredResearch.label + ")", null); } else { - yield return new FloatMenuOption("StartProduction".Translate(process.thingDef.label), () => + yield return new FloatMenuOption(label, () => { this.selectedProcess = process; Job job = JobMaker.MakeJob(DefDatabase.GetNamed("ARA_AddProcessToQueueJob"), parent); @@ -134,33 +136,32 @@ namespace ArachnaeSwarm public override void CompTick() { base.CompTick(); + var producingOrders = productionOrders.Where(o => o.productionUntilTick > 0).ToList(); bool hasFuel = FuelComp?.HasFuel ?? true; - float ambientTemperature = parent.AmbientTemperature; - bool isTempSafe = ambientTemperature >= Props.minSafeTemperature && ambientTemperature <= Props.maxSafeTemperature; - foreach(var order in producingOrders) + if (hasFuel) { - // 关键修复:检查时间戳有效性 - if (order.productionUntilTick <= 0) - { - Log.Error($"Invalid productionUntilTick: {order.productionUntilTick} for {order.process?.thingDef?.defName}. Skipping."); - continue; - } + float ambientTemperature = parent.AmbientTemperature; + bool isTempSafe = ambientTemperature >= Props.minSafeTemperature && ambientTemperature <= Props.maxSafeTemperature; - if(hasFuel && isTempSafe) + foreach(var order in producingOrders) { - order.ticksUnderOptimalConditions++; + order.productionUntilTick--; // 倒计时 + + if (isTempSafe) + { + order.ticksUnderOptimalConditions++; + } + else + { + float tempDelta = (ambientTemperature > Props.maxSafeTemperature) ? ambientTemperature - Props.maxSafeTemperature : Props.minSafeTemperature - ambientTemperature; + order.temperaturePenaltyPercent = Mathf.Min(1f, order.temperaturePenaltyPercent + tempDelta * Props.penaltyPerDegreePerTick); + } } - if (!isTempSafe) - { - float tempDelta = (ambientTemperature > Props.maxSafeTemperature) ? ambientTemperature - Props.maxSafeTemperature : Props.minSafeTemperature - ambientTemperature; - order.temperaturePenaltyPercent = Mathf.Min(1f, order.temperaturePenaltyPercent + tempDelta * Props.penaltyPerDegreePerTick); - } - // 修复:移除原来的 order.productionUntilTick++ 逻辑 - // 没有燃料时暂停生产 } - + // 如果没有燃料,则上面的代码块不执行,productionUntilTick自然就暂停了 + if (FuelComp != null) { float totalConsumptionRatePerDay = 0f; @@ -168,7 +169,7 @@ namespace ArachnaeSwarm { foreach (var order in producingOrders) { - if (order.process.totalNutritionNeeded > 0 && order.process.productionTicks > 0) + if (order.process != null && order.process.totalNutritionNeeded > 0 && order.process.productionTicks > 0) { totalConsumptionRatePerDay += (order.process.totalNutritionNeeded / order.process.productionTicks) * 60000f; } @@ -179,10 +180,10 @@ namespace ArachnaeSwarm productionOrders.RemoveAll(order => { - if (order.productionUntilTick > 0 && Find.TickManager.TicksGame >= order.productionUntilTick) + if (order.productionUntilTick == 0) { FinishProduction(order); - return true; + return true; } return false; }); @@ -195,14 +196,14 @@ namespace ArachnaeSwarm { float speedFactor = 1f + (FacilitiesComp?.GetStatOffset(StatDef.Named("ARA_IncubationSpeedFactor")) ?? 0f); int modifiedDelay = (int)(waitingOrder.process.productionTicks / speedFactor); - waitingOrder.productionUntilTick = Find.TickManager.TicksGame + modifiedDelay; + waitingOrder.productionUntilTick = modifiedDelay; } } } private (QualityCategory quality, float baseScore, float penalty) GetEstimatedQualityDetails(QueuedProcessOrder order) { - if (order == null || Props.qualityThresholds.NullOrEmpty()) + if (order == null || order.process == null || Props.qualityThresholds.NullOrEmpty()) { return (QualityCategory.Normal, 0f, 0f); } @@ -217,6 +218,10 @@ namespace ArachnaeSwarm break; } } + if (finalQuality == QualityCategory.Awful && Props.qualityThresholds.Any()) + { + finalQuality = Props.qualityThresholds.OrderBy(q => q.threshold).First().quality; + } return (finalQuality, progress, order.temperaturePenaltyPercent); } @@ -253,25 +258,37 @@ namespace ArachnaeSwarm int producingCount = productionOrders.Count(o => o.productionUntilTick > 0); int queuedCount = productionOrders.Count - producingCount; - sb.AppendLine($"生产槽位: {producingCount} / {Props.productionQueueLimit}"); - if (queuedCount > 0) sb.AppendLine($"等待队列: {queuedCount}"); + sb.AppendLine("ProductionSlots".Translate(producingCount, Props.productionQueueLimit)); + if (queuedCount > 0) sb.AppendLine("ProductionQueue".Translate(queuedCount)); if (FacilitiesComp != null) { float speedFactor = 1f + FacilitiesComp.GetStatOffset(StatDef.Named("ARA_IncubationSpeedFactor")); - if (speedFactor != 1f) sb.AppendLine($"生产速度: {speedFactor.ToStringPercent()}"); + if (speedFactor != 1f) sb.AppendLine("ProductionSpeed".Translate() + $": {speedFactor.ToStringPercent()}"); } - var producingNow = productionOrders.Where(o => o.productionUntilTick > 0).OrderBy(o => o.productionUntilTick); + var producingNow = productionOrders.Where(o => o.productionUntilTick > 0).OrderBy(o => o.productionUntilTick).ToList(); if (producingNow.Any()) { - sb.AppendLine("正在生产:"); - foreach (var order in producingNow) + sb.AppendLine("ARA_ProducingListTitle".Translate()); + for (int i = 0; i < producingNow.Count; i++) { + var order = producingNow[i]; if (order.process == null) continue; - int remainingTicks = order.productionUntilTick - Find.TickManager.TicksGame; + + sb.AppendLine($" {i + 1}. {order.process.thingDef.LabelCap}:"); + + float progress = 1f - (float)order.productionUntilTick / (float)order.process.productionTicks; + int remainingTicks = order.productionUntilTick; + + sb.AppendLine(" " + "Progress".Translate() + ": " + GetProgressBar(progress) + " " + progress.ToStringPercent("F0")); + sb.AppendLine(" " + "TimeLeft".Translate() + ": " + remainingTicks.ToStringTicksToPeriod()); + var qualityDetails = GetEstimatedQualityDetails(order); - sb.AppendLine($" - {order.process.thingDef.LabelCap}: {remainingTicks.ToStringTicksToPeriod(true, false, true, true)} (品质: {qualityDetails.quality.GetLabel()})"); + sb.AppendLine(" " + "EstimatedQuality".Translate() + ": " + qualityDetails.quality.GetLabel()); + sb.AppendLine(" " + "QualityProgress".Translate() + ": " + + GetQualityProgressBar(qualityDetails.baseScore, qualityDetails.penalty) + " " + + (qualityDetails.baseScore - qualityDetails.penalty).ToStringPercent("F0")); } } else if (queuedCount == 0) @@ -328,20 +345,11 @@ namespace ArachnaeSwarm // 关键修复:检查加载后的时间戳有效性 if (order.productionUntilTick > 0) { - // 如果生产结束时间已经过去,立即完成生产 - if (Find.TickManager.TicksGame >= order.productionUntilTick) + // 倒计时模式下,不再需要复杂的加载后时间戳检查 + // 只需要确保值不是负数即可 + if (order.productionUntilTick < 0) { - Log.Warning($"Production time already passed for {order.tempThingDefName}. Finishing immediately."); - FinishProduction(order); - return true; - } - // 如果时间戳异常(比如超过游戏当前时间太多),重新计算 - else if (order.productionUntilTick - Find.TickManager.TicksGame > order.process.productionTicks * 10) - { - Log.Warning($"Abnormal production time detected for {order.tempThingDefName}. Recalculating."); - float speedFactor = 1f + (FacilitiesComp?.GetStatOffset(StatDef.Named("ARA_IncubationSpeedFactor")) ?? 0f); - int modifiedDelay = (int)(order.process.productionTicks / speedFactor); - order.productionUntilTick = Find.TickManager.TicksGame + modifiedDelay; + order.productionUntilTick = -1; // 重置为等待状态 } } @@ -376,6 +384,32 @@ namespace ArachnaeSwarm } } + private string GetProgressBar(float progress, int barLength = 20) + { + int filledLength = Mathf.RoundToInt(progress * barLength); + StringBuilder bar = new StringBuilder(); + bar.Append("["); + bar.Append(new string('█', filledLength)); + bar.Append(new string('-', barLength - filledLength)); + bar.Append("]"); + return bar.ToString(); + } + + private string GetQualityProgressBar(float baseScore, float penalty, int barLength = 20) + { + int baseLength = Mathf.RoundToInt(baseScore * barLength); + int penaltyLength = Mathf.RoundToInt(penalty * barLength); + int actualLength = Mathf.Max(0, baseLength - penaltyLength); + + StringBuilder bar = new StringBuilder(); + bar.Append("["); + bar.Append(new string('█', actualLength)); + bar.Append(new string('░', baseLength - actualLength)); + bar.Append(new string('-', barLength - baseLength)); + bar.Append("]"); + return bar.ToString(); + } + private void BuildProcessList() { _cachedProcesses = new List();