Merge branch 'master' of https://git.ra3battle.cn/Kalospacer/ArachnaeSwarm
This commit is contained in:
@@ -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<JobDef>.GetNamed("ARA_StartInteractiveProduction"), parent);
|
||||
|
||||
@@ -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<JobDef>.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<ProcessDef>();
|
||||
|
||||
Reference in New Issue
Block a user