284 lines
9.9 KiB
C#
284 lines
9.9 KiB
C#
// File: Comps/Comp_SwarmMaintenance.cs
|
||
using System.Collections.Generic;
|
||
using RimWorld;
|
||
using UnityEngine;
|
||
using Verse;
|
||
using Verse.AI;
|
||
|
||
namespace ArachnaeSwarm
|
||
{
|
||
public class Comp_SwarmMaintenance : ThingComp
|
||
{
|
||
// 属性访问器
|
||
public CompProperties_SwarmMaintenance Props => (CompProperties_SwarmMaintenance)props;
|
||
|
||
// 当前维护度
|
||
private float currentMaintenance;
|
||
|
||
// 上次更新维护度的时间
|
||
private int lastMaintenanceTick = -99999;
|
||
|
||
// 当维护度为0时,每秒受到的伤害计时器
|
||
private int nextDamageTick = -99999;
|
||
|
||
// 警告计时器
|
||
private int lastWarningTick = -99999;
|
||
private const int WarningInterval = 2500; // 警告间隔时间
|
||
private const float CriticalWarningThreshold = 0.3f; // 警告阈值(百分比)
|
||
private bool lastWarningState = false;
|
||
|
||
// 属性访问
|
||
public float CurrentMaintenance => currentMaintenance;
|
||
public float MaxMaintenance => Props.maxMaintenance;
|
||
public float MaintenancePercentage => currentMaintenance / MaxMaintenance;
|
||
public bool NeedsMaintenance => currentMaintenance < MaxMaintenance * Props.maintenanceThresholdForJob;
|
||
public bool IsCritical => currentMaintenance <= MaxMaintenance * Props.warningThreshold;
|
||
public bool IsEmpty => currentMaintenance <= 0f;
|
||
|
||
// 初始化
|
||
public override void Initialize(CompProperties props)
|
||
{
|
||
base.Initialize(props);
|
||
currentMaintenance = Props.maxMaintenance; // 初始时满维护度
|
||
lastMaintenanceTick = Find.TickManager.TicksGame;
|
||
}
|
||
|
||
// 序列化
|
||
public override void PostExposeData()
|
||
{
|
||
base.PostExposeData();
|
||
Scribe_Values.Look(ref currentMaintenance, "currentMaintenance", Props.maxMaintenance);
|
||
Scribe_Values.Look(ref lastMaintenanceTick, "lastMaintenanceTick", -99999);
|
||
Scribe_Values.Look(ref nextDamageTick, "nextDamageTick", -99999);
|
||
Scribe_Values.Look(ref lastWarningTick, "lastWarningTick", -99999);
|
||
Scribe_Values.Look(ref lastWarningState, "lastWarningState", false);
|
||
}
|
||
|
||
// 每tick更新
|
||
public override void CompTick()
|
||
{
|
||
base.CompTick();
|
||
|
||
int currentTick = Find.TickManager.TicksGame;
|
||
|
||
// 每2500tick(约41.67秒)更新一次维护度递减
|
||
if (currentTick - lastMaintenanceTick >= 2500)
|
||
{
|
||
UpdateMaintenanceDecay();
|
||
lastMaintenanceTick = currentTick;
|
||
}
|
||
|
||
// 检查是否需要显示警告
|
||
if (currentTick - lastWarningTick >= WarningInterval)
|
||
{
|
||
CheckWarning();
|
||
lastWarningTick = currentTick;
|
||
}
|
||
|
||
// 如果维护度为0,每秒造成伤害
|
||
if (currentMaintenance <= 0f && currentTick >= nextDamageTick)
|
||
{
|
||
ApplyDamageWhenEmpty();
|
||
nextDamageTick = currentTick + 60; // 60ticks = 1秒
|
||
}
|
||
}
|
||
|
||
// 更新维护度递减
|
||
private void UpdateMaintenanceDecay()
|
||
{
|
||
if (parent == null || parent.Map == null)
|
||
return;
|
||
|
||
// 计算基础递减量:每天递减量转换为每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
|
||
if (currentMaintenance < 0f)
|
||
currentMaintenance = 0f;
|
||
}
|
||
|
||
// 检查是否需要显示警告
|
||
private void CheckWarning()
|
||
{
|
||
if (parent == null || parent.Destroyed || parent.Map == null)
|
||
return;
|
||
|
||
bool isCritical = MaintenancePercentage <= CriticalWarningThreshold;
|
||
|
||
// 如果状态改变,显示警告
|
||
if (isCritical && !lastWarningState)
|
||
{
|
||
ShowMaintenanceWarning();
|
||
lastWarningState = true;
|
||
}
|
||
else if (!isCritical && lastWarningState)
|
||
{
|
||
lastWarningState = false;
|
||
}
|
||
}
|
||
|
||
// 显示维护警告
|
||
private void ShowMaintenanceWarning()
|
||
{
|
||
if (parent == null)
|
||
return;
|
||
|
||
// 添加警告标记
|
||
if (parent.Spawned)
|
||
{
|
||
MoteMaker.ThrowText(parent.DrawPos, parent.Map, "ARA_SwarmMaintenance.NeedsMaintenance".Translate(), Color.yellow);
|
||
}
|
||
}
|
||
|
||
// 当维护度为0时应用伤害
|
||
private void ApplyDamageWhenEmpty()
|
||
{
|
||
if (parent == null || parent.Destroyed)
|
||
return;
|
||
|
||
// 每秒造成伤害
|
||
float damageAmount = Props.damagePerSecondWhenEmpty;
|
||
|
||
// 应用伤害到建筑
|
||
parent.TakeDamage(new DamageInfo(
|
||
DamageDefOf.Deterioration,
|
||
damageAmount,
|
||
armorPenetration: 999f, // 高穿甲,确保能造成伤害
|
||
instigator: null
|
||
));
|
||
}
|
||
|
||
// 添加维护度
|
||
public void AddMaintenance(float amount)
|
||
{
|
||
currentMaintenance += amount;
|
||
if (currentMaintenance > MaxMaintenance)
|
||
currentMaintenance = MaxMaintenance;
|
||
|
||
// 维护后重置警告状态
|
||
lastWarningState = false;
|
||
}
|
||
|
||
// 重置维护度
|
||
public void ResetMaintenance()
|
||
{
|
||
currentMaintenance = MaxMaintenance;
|
||
lastWarningState = false;
|
||
}
|
||
|
||
// 获取可维护的优先级(用于WorkGiver排序)
|
||
public float GetMaintenancePriority()
|
||
{
|
||
// 维护度越低,优先级越高
|
||
return 1f - MaintenancePercentage;
|
||
}
|
||
|
||
// 在建筑信息面板中追加维护信息
|
||
public override string CompInspectStringExtra()
|
||
{
|
||
// 基础信息
|
||
string text = "ARA_SwarmMaintenance.MaintenanceLevel".Translate(
|
||
currentMaintenance.ToString("F1"),
|
||
MaxMaintenance.ToString("F1"),
|
||
MaintenancePercentage.ToString("P1"));
|
||
|
||
// 计算实际每日消耗
|
||
float actualDecayPerDay = GetActualDecayPerDay();
|
||
text += "\n" + "ARA_SwarmMaintenance.DailyDecay".Translate(actualDecayPerDay.ToString("F1"));
|
||
|
||
// 显示维护状态
|
||
if (NeedsMaintenance)
|
||
{
|
||
text += "\n" + "ARA_SwarmMaintenance.NeedsMaintenance".Translate();
|
||
}
|
||
|
||
// 显示警告信息
|
||
if (IsCritical)
|
||
{
|
||
text += "\n<color=orange>" + "ARA_SwarmMaintenance.CriticalLevel".Translate() + "</color>";
|
||
}
|
||
|
||
return text;
|
||
}
|
||
|
||
// 获取实际每日消耗(考虑孵化活性)
|
||
private float GetActualDecayPerDay()
|
||
{
|
||
float baseDecay = Props.maintenanceDecayPerDay;
|
||
float multiplier = 1f;
|
||
|
||
if (parent is Building_Ootheca ootheca)
|
||
{
|
||
if (!ootheca.IsIncubating)
|
||
{
|
||
multiplier = 0.2f;
|
||
}
|
||
else
|
||
{
|
||
multiplier = 0.5f + ootheca.FluxEfficiency * 0.5f;
|
||
}
|
||
}
|
||
|
||
return baseDecay * multiplier;
|
||
}
|
||
|
||
// 获取Gizmos(命令按钮)- 只保留调试功能
|
||
public override IEnumerable<Gizmo> CompGetGizmosExtra()
|
||
{
|
||
// 只在玩家控制下显示
|
||
if (parent.Faction?.IsPlayer == true)
|
||
{
|
||
// 调试按钮 - 仅在GodMode下显示
|
||
if (DebugSettings.godMode)
|
||
{
|
||
yield return new Command_Action
|
||
{
|
||
defaultLabel = "Debug: Reset Maintenance",
|
||
action = () => ResetMaintenance()
|
||
};
|
||
|
||
yield return new Command_Action
|
||
{
|
||
defaultLabel = "Debug: Reduce 50%",
|
||
action = () => currentMaintenance = MaxMaintenance * 0.5f
|
||
};
|
||
|
||
yield return new Command_Action
|
||
{
|
||
defaultLabel = "Debug: Reduce to 0",
|
||
action = () => currentMaintenance = 0f
|
||
};
|
||
|
||
yield return new Command_Action
|
||
{
|
||
defaultLabel = "Debug: Show Priority",
|
||
action = () =>
|
||
{
|
||
Messages.Message($"维护优先级: {GetMaintenancePriority():F2}", MessageTypeDefOf.SilentInput);
|
||
}
|
||
};
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|