397 lines
13 KiB
C#
397 lines
13 KiB
C#
// File: Need_HoneyProduction.cs
|
||
using RimWorld;
|
||
using UnityEngine;
|
||
using Verse;
|
||
|
||
namespace ArachnaeSwarm
|
||
{
|
||
public class HoneyProductionExtension : DefModExtension
|
||
{
|
||
// 蜜罐生产的基础转化率(相对于食物流失的百分比)
|
||
public float baseConversionRate = 0.5f;
|
||
|
||
// 最大蜜罐容量(可选,覆盖默认值)
|
||
public float maxHoneyCapacity = 1f;
|
||
|
||
// 是否启用蜜罐生产
|
||
public bool enableHoneyProduction = true;
|
||
|
||
// 生产速率乘数(影响生产速度)
|
||
public float productionSpeedFactor = 1f;
|
||
|
||
// 蜜罐类别对应的生产效率(可选,覆盖默认值)
|
||
public float fullProductionEfficiency = 1.5f;
|
||
public float highProductionEfficiency = 1.2f;
|
||
public float mediumProductionEfficiency = 1f;
|
||
public float lowProductionEfficiency = 0.5f;
|
||
public float emptyProductionEfficiency = 0f;
|
||
|
||
// 生产间隔(ticks,可选覆盖默认值)
|
||
public int productionInterval = 150;
|
||
|
||
public static HoneyProductionExtension Get(Pawn pawn)
|
||
{
|
||
if (pawn?.def?.GetModExtension<HoneyProductionExtension>() is HoneyProductionExtension ext)
|
||
return ext;
|
||
return null;
|
||
}
|
||
|
||
// 获取转化率
|
||
public float GetConversionRate()
|
||
{
|
||
return baseConversionRate * productionSpeedFactor;
|
||
}
|
||
}
|
||
|
||
public class Need_HoneyProduction : Need
|
||
{
|
||
// 基础流失速率(与食物需要对应)
|
||
private const float BaseHoneyGainPerTick = 2.6666667E-05f * 0.5f; // 食物流失速率的50%作为默认值
|
||
|
||
// 用于存储对食物需要的引用
|
||
private Need_Food cachedFoodNeed;
|
||
|
||
// 当前类别
|
||
private HoneyProductionCategory curCategoryInt = HoneyProductionCategory.Empty;
|
||
|
||
// 上次满的时间点
|
||
private int lastFullTick = -99999;
|
||
|
||
// 缓存的ModExtension
|
||
private HoneyProductionExtension cachedExtension;
|
||
|
||
// 蜜罐的最大容量 - 优先使用ModExtension的值
|
||
public override float MaxLevel
|
||
{
|
||
get
|
||
{
|
||
var ext = GetExtension();
|
||
if (ext != null && ext.maxHoneyCapacity > 0)
|
||
{
|
||
return ext.maxHoneyCapacity;
|
||
}
|
||
return FoodNeed?.MaxLevel ?? 1f;
|
||
}
|
||
}
|
||
|
||
// 当前类别
|
||
public HoneyProductionCategory CurCategory => curCategoryInt;
|
||
|
||
// 是否满仓
|
||
public bool IsFull => CurCategory == HoneyProductionCategory.Full;
|
||
|
||
// 是否为空
|
||
public bool IsEmpty => CurCategory == HoneyProductionCategory.Empty;
|
||
|
||
// 当前类别对应的生产效率
|
||
public float ProductionEfficiency
|
||
{
|
||
get
|
||
{
|
||
var ext = GetExtension();
|
||
|
||
// 如果有扩展定义,使用扩展的值
|
||
if (ext != null)
|
||
{
|
||
switch (curCategoryInt)
|
||
{
|
||
case HoneyProductionCategory.Full:
|
||
return ext.fullProductionEfficiency;
|
||
case HoneyProductionCategory.High:
|
||
return ext.highProductionEfficiency;
|
||
case HoneyProductionCategory.Medium:
|
||
return ext.mediumProductionEfficiency;
|
||
case HoneyProductionCategory.Low:
|
||
return ext.lowProductionEfficiency;
|
||
case HoneyProductionCategory.Empty:
|
||
return ext.emptyProductionEfficiency;
|
||
default:
|
||
return 0f;
|
||
}
|
||
}
|
||
|
||
// 默认值
|
||
switch (curCategoryInt)
|
||
{
|
||
case HoneyProductionCategory.Full:
|
||
return 1.0f;
|
||
case HoneyProductionCategory.High:
|
||
return 0.8f;
|
||
case HoneyProductionCategory.Medium:
|
||
return 0.5f;
|
||
case HoneyProductionCategory.Low:
|
||
return 0.3f;
|
||
case HoneyProductionCategory.Empty:
|
||
return 0f;
|
||
default:
|
||
return 0f;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 获取扩展
|
||
private HoneyProductionExtension GetExtension()
|
||
{
|
||
if (cachedExtension == null && pawn != null)
|
||
{
|
||
cachedExtension = pawn.def?.GetModExtension<HoneyProductionExtension>();
|
||
}
|
||
return cachedExtension;
|
||
}
|
||
|
||
// 是否启用蜜罐生产
|
||
private bool IsEnabled
|
||
{
|
||
get
|
||
{
|
||
var ext = GetExtension();
|
||
return ext == null || ext.enableHoneyProduction; // 默认启用
|
||
}
|
||
}
|
||
|
||
// 获取食物需要的引用
|
||
private Need_Food FoodNeed
|
||
{
|
||
get
|
||
{
|
||
if (cachedFoodNeed == null)
|
||
{
|
||
cachedFoodNeed = pawn.needs?.TryGetNeed<Need_Food>();
|
||
}
|
||
return cachedFoodNeed;
|
||
}
|
||
}
|
||
|
||
public Need_HoneyProduction(Pawn newPawn) : base(newPawn)
|
||
{
|
||
// 初始化时设置为空
|
||
curLevelInt = 0f;
|
||
threshPercents = new System.Collections.Generic.List<float>
|
||
{
|
||
0.25f, // Low -> Medium
|
||
0.5f, // Medium -> High
|
||
0.75f // High -> Full
|
||
};
|
||
}
|
||
|
||
public override void ExposeData()
|
||
{
|
||
base.ExposeData();
|
||
Scribe_Values.Look(ref lastFullTick, "lastFullTick", -99999);
|
||
}
|
||
|
||
public override void NeedInterval()
|
||
{
|
||
// 如果不启用,直接返回
|
||
if (!IsEnabled)
|
||
return;
|
||
|
||
// 检查是否需要冻结(与食物需要类似的条件)
|
||
if (IsFrozen)
|
||
{
|
||
return;
|
||
}
|
||
|
||
// 获取食物需要的流失速率
|
||
float foodFallRate = GetFoodFallRate();
|
||
|
||
// 获取转化率(从ModExtension或使用默认值)
|
||
float conversionRate = GetExtension()?.GetConversionRate() ?? 0.5f;
|
||
|
||
// 蜜罐的增长速率 = 食物流失速率 × 转化率
|
||
float honeyGainRate = foodFallRate * conversionRate;
|
||
|
||
// 获取生产间隔
|
||
int interval = GetExtension()?.productionInterval ?? 150;
|
||
|
||
// 应用间隔
|
||
CurLevel += honeyGainRate * interval;
|
||
|
||
// 确保不超过最大容量
|
||
if (CurLevel > MaxLevel)
|
||
CurLevel = MaxLevel;
|
||
|
||
// 更新类别
|
||
UpdateCategory();
|
||
|
||
// 记录满的时间
|
||
if (IsFull)
|
||
{
|
||
lastFullTick = Find.TickManager.TicksGame;
|
||
}
|
||
}
|
||
|
||
// 获取食物流失速率
|
||
private float GetFoodFallRate()
|
||
{
|
||
if (FoodNeed == null)
|
||
{
|
||
// 如果没有食物需要,使用默认值
|
||
return BaseHoneyGainPerTick / 0.5f; // 反向计算基础食物流失速率
|
||
}
|
||
|
||
// 获取当前食物类别对应的流失速率
|
||
return FoodNeed.FoodFallPerTick;
|
||
}
|
||
|
||
// 更新类别
|
||
private void UpdateCategory()
|
||
{
|
||
float percentage = CurLevelPercentage;
|
||
|
||
if (percentage >= 0.75f)
|
||
curCategoryInt = HoneyProductionCategory.Full;
|
||
else if (percentage >= 0.5f)
|
||
curCategoryInt = HoneyProductionCategory.High;
|
||
else if (percentage >= 0.25f)
|
||
curCategoryInt = HoneyProductionCategory.Medium;
|
||
else if (percentage > 0f)
|
||
curCategoryInt = HoneyProductionCategory.Low;
|
||
else
|
||
curCategoryInt = HoneyProductionCategory.Empty;
|
||
}
|
||
|
||
// 提取蜂蜜(减少蜜罐存量)
|
||
public void ExtractHoney(float amount)
|
||
{
|
||
CurLevel -= amount;
|
||
if (CurLevel < 0f)
|
||
CurLevel = 0f;
|
||
UpdateCategory();
|
||
}
|
||
|
||
// 强制清空蜜罐
|
||
public void EmptyHoney()
|
||
{
|
||
CurLevel = 0f;
|
||
curCategoryInt = HoneyProductionCategory.Empty;
|
||
}
|
||
|
||
// 重置到初始状态
|
||
public override void SetInitialLevel()
|
||
{
|
||
// 初始为空
|
||
CurLevel = 0f;
|
||
curCategoryInt = HoneyProductionCategory.Empty;
|
||
}
|
||
|
||
// 获取提示字符串
|
||
public override string GetTipString()
|
||
{
|
||
string text = (LabelCap + ": " + CurLevelPercentage.ToStringPercent()).Colorize(ColoredText.TipSectionTitleColor);
|
||
text += "\n" + def.description;
|
||
text += $"\n{"ARA_HoneyProduction.Efficiency".Translate()} {ProductionEfficiency.ToStringPercent()}";
|
||
|
||
// 获取每tick的速率
|
||
float foodFallPerTick = GetFoodFallRate();
|
||
float conversionRate = GetExtension()?.GetConversionRate() ?? 0.5f;
|
||
float honeyGainPerTick = foodFallPerTick * conversionRate;
|
||
|
||
// 转换为每秒:1秒 = 60tick
|
||
float foodFallPerSecond = foodFallPerTick * 60f;
|
||
float honeyGainPerSecond = honeyGainPerTick * 60f;
|
||
|
||
text += $"\n{"ARA_HoneyProduction.FoodDrainRate".Translate()}: {foodFallPerSecond:0.#####}/ {"LetterSecond".Translate()}";
|
||
text += $"\n{"ARA_HoneyProduction.HoneyGainRate".Translate()}: {honeyGainPerSecond:0.#####}/ {"LetterSecond".Translate()}";
|
||
|
||
// 显示转化率信息
|
||
if (GetExtension() != null)
|
||
{
|
||
text += $"\n{"ARA_HoneyProduction.ConversionRate".Translate()}: {conversionRate:P1}";
|
||
if (GetExtension().productionSpeedFactor != 1f)
|
||
{
|
||
text += $"\n{"ARA_HoneyProduction.SpeedFactor".Translate()}: {GetExtension().productionSpeedFactor:F2}";
|
||
}
|
||
}
|
||
|
||
if (IsFull)
|
||
{
|
||
text += $"\n\n{"ARA_HoneyProduction.FullWarning".Translate()}";
|
||
}
|
||
|
||
// 显示是否启用
|
||
if (!IsEnabled)
|
||
{
|
||
text += $"\n\n<color=orange>{"ARA_HoneyProduction.Disabled".Translate()}</color>";
|
||
}
|
||
|
||
return text;
|
||
}
|
||
|
||
// 获取类别标签
|
||
public string GetCategoryLabel()
|
||
{
|
||
switch (curCategoryInt)
|
||
{
|
||
case HoneyProductionCategory.Full:
|
||
return "ARA_HoneyProduction.Full".Translate();
|
||
case HoneyProductionCategory.High:
|
||
return "ARA_HoneyProduction.High".Translate();
|
||
case HoneyProductionCategory.Medium:
|
||
return "ARA_HoneyProduction.Medium".Translate();
|
||
case HoneyProductionCategory.Low:
|
||
return "ARA_HoneyProduction.Low".Translate();
|
||
case HoneyProductionCategory.Empty:
|
||
return "ARA_HoneyProduction.Empty".Translate();
|
||
default:
|
||
return "Unknown";
|
||
}
|
||
}
|
||
|
||
// 在UI上绘制
|
||
public override void DrawOnGUI(Rect rect, int maxThresholdMarkers = int.MaxValue, float customMargin = -1f, bool drawArrows = true, bool doTooltip = true, Rect? rectForTooltip = null, bool drawLabel = true)
|
||
{
|
||
// 如果不启用,不显示
|
||
if (!IsEnabled)
|
||
return;
|
||
|
||
if (threshPercents == null)
|
||
{
|
||
threshPercents = new System.Collections.Generic.List<float>
|
||
{
|
||
0.25f, 0.5f, 0.75f
|
||
};
|
||
}
|
||
|
||
base.DrawOnGUI(rect, maxThresholdMarkers, customMargin, false, doTooltip, rectForTooltip, drawLabel);
|
||
}
|
||
|
||
// 是否冻结
|
||
protected override bool IsFrozen
|
||
{
|
||
get
|
||
{
|
||
// 如果基础条件冻结,则蜜罐生产也冻结
|
||
if (base.IsFrozen)
|
||
return true;
|
||
|
||
// 如果生物死亡,则冻结
|
||
if (pawn.Dead)
|
||
return true;
|
||
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// GUI变化箭头(总是显示增长)
|
||
public override int GUIChangeArrow => IsEnabled ? 1 : 0;
|
||
|
||
// 调试调整百分比
|
||
protected override void OffsetDebugPercent(float offsetPercent)
|
||
{
|
||
base.OffsetDebugPercent(offsetPercent);
|
||
UpdateCategory();
|
||
}
|
||
}
|
||
|
||
// 蜜罐生产类别
|
||
public enum HoneyProductionCategory
|
||
{
|
||
Empty, // 空仓
|
||
Low, // 低存量(0-25%)
|
||
Medium, // 中存量(25-50%)
|
||
High, // 高存量(50-75%)
|
||
Full // 满仓(75-100%)
|
||
}
|
||
}
|