This commit is contained in:
2025-12-26 18:45:10 +08:00
parent 592600a6e8
commit 51275a9bdd
11 changed files with 994 additions and 98 deletions

Binary file not shown.

View File

@@ -216,4 +216,163 @@
</li>
</stages>
</HediffDef>
<!-- ==================== 额外差特质Bad Pool ==================== -->
<HediffDef>
<defName>ARA_Incubator_5_Flaw_Hediffs</defName>
<label>肌肉萎缩</label>
<description>急速的孵化使得该阿拉克涅督虫的肌肉组织发育不全,力量远低于正常个体。\n\n由于较差的孵化质量阿拉克涅督虫获得了这个不利突变。</description>
<hediffClass>HediffWithComps</hediffClass>
<isBad>false</isBad>
<defaultLabelColor>(0.9, 0.2 , 0.1)</defaultLabelColor>
<scenarioCanAdd>true</scenarioCanAdd>
<stages>
<li>
<statFactors>
<MeleeDamageFactor>0.5</MeleeDamageFactor>
<CarryingCapacity>0.6</CarryingCapacity>
</statFactors>
</li>
</stages>
</HediffDef>
<HediffDef>
<defName>ARA_Incubator_6_Flaw_Hediffs</defName>
<label>凝血障碍</label>
<description>急速的孵化导致该阿拉克涅督虫的凝血机制异常,一旦受伤就会大量失血。\n\n由于较差的孵化质量阿拉克涅督虫获得了这个不利突变。</description>
<hediffClass>HediffWithComps</hediffClass>
<isBad>false</isBad>
<defaultLabelColor>(0.9, 0.2 , 0.1)</defaultLabelColor>
<scenarioCanAdd>true</scenarioCanAdd>
<stages>
<li>
<totalBleedFactor>3.0</totalBleedFactor>
</li>
</stages>
</HediffDef>
<HediffDef>
<defName>ARA_Incubator_7_Flaw_Hediffs</defName>
<label>骨质疏松</label>
<description>急速的孵化使得该阿拉克涅督虫的内骨骼异常脆弱,更容易受到致命伤害。\n\n由于较差的孵化质量阿拉克涅督虫获得了这个不利突变。</description>
<hediffClass>HediffWithComps</hediffClass>
<isBad>false</isBad>
<defaultLabelColor>(0.9, 0.2 , 0.1)</defaultLabelColor>
<scenarioCanAdd>true</scenarioCanAdd>
<stages>
<li>
<statFactors>
<IncomingDamageFactor>1.5</IncomingDamageFactor>
</statFactors>
</li>
</stages>
</HediffDef>
<HediffDef>
<defName>ARA_Incubator_8_Flaw_Hediffs</defName>
<label>免疫缺陷</label>
<description>急速的孵化使得该阿拉克涅督虫的免疫系统发育不良,对疾病的抵抗力极差。\n\n由于较差的孵化质量阿拉克涅督虫获得了这个不利突变。</description>
<hediffClass>HediffWithComps</hediffClass>
<isBad>false</isBad>
<defaultLabelColor>(0.9, 0.2 , 0.1)</defaultLabelColor>
<scenarioCanAdd>true</scenarioCanAdd>
<stages>
<li>
<statFactors>
<ImmunityGainSpeed>0.5</ImmunityGainSpeed>
</statFactors>
</li>
</stages>
</HediffDef>
<!-- ==================== 精英特质Elite Pool- 普通特质增强版 ==================== -->
<!-- 致密甲壳 增强版 -->
<HediffDef>
<defName>ARA_Incubator_Elite_Regeneration</defName>
<label>超密甲壳</label>
<description>该阿拉克涅督虫的甲壳密度远超常规个体,几乎坚不可摧,同时还具有优秀的热抗性。\n\n由于极佳的孵化质量阿拉克涅督虫获得了这个稀有突变。</description>
<hediffClass>HediffWithComps</hediffClass>
<isBad>false</isBad>
<defaultLabelColor>(0.8, 0.6, 0.0)</defaultLabelColor>
<scenarioCanAdd>true</scenarioCanAdd>
<stages>
<li>
<statOffsets>
<ArmorRating_Blunt>1.0</ArmorRating_Blunt>
<ArmorRating_Sharp>1.0</ArmorRating_Sharp>
<ArmorRating_Heat>0.8</ArmorRating_Heat>
</statOffsets>
</li>
</stages>
</HediffDef>
<!-- 行动激素 增强版 -->
<HediffDef>
<defName>ARA_Incubator_Elite_AdaptiveArmor</defName>
<label>超级激素</label>
<description>该阿拉克涅督虫的腺体异常发达,持续分泌高浓度激素,使其处于极度亢奋状态,攻击速度惊人。\n\n由于极佳的孵化质量阿拉克涅督虫获得了这个稀有突变。</description>
<hediffClass>HediffWithComps</hediffClass>
<isBad>false</isBad>
<defaultLabelColor>(0.8, 0.6, 0.0)</defaultLabelColor>
<scenarioCanAdd>true</scenarioCanAdd>
<stages>
<li>
<statOffsets>
<MoveSpeed>1.5</MoveSpeed>
</statOffsets>
<statFactors>
<MeleeCooldownFactor>0.4</MeleeCooldownFactor>
<RangedCooldownFactor>0.5</RangedCooldownFactor>
</statFactors>
</li>
</stages>
</HediffDef>
<!-- 强壮肌肉 增强版 -->
<HediffDef>
<defName>ARA_Incubator_Elite_BerserkGlands</defName>
<label>完美肌肉</label>
<description>该阿拉克涅督虫的肌肉组织经过完美发育,力量远超同类,近战攻击威力惊人,负重能力也大幅提升。\n\n由于极佳的孵化质量阿拉克涅督虫获得了这个稀有突变。</description>
<hediffClass>HediffWithComps</hediffClass>
<isBad>false</isBad>
<defaultLabelColor>(0.8, 0.6, 0.0)</defaultLabelColor>
<scenarioCanAdd>true</scenarioCanAdd>
<stages>
<li>
<statFactors>
<MeleeDamageFactor>5</MeleeDamageFactor>
<CarryingCapacity>3</CarryingCapacity>
</statFactors>
</li>
</stages>
</HediffDef>
<!-- 中枢强化 增强版 -->
<HediffDef>
<defName>ARA_Incubator_Elite_PsychicResonance</defName>
<label>终极意识</label>
<description>该阿拉克涅督虫的神经系统经过完美发育,意识、视觉、听觉等各项感知能力都大幅超越同类。\n\n由于极佳的孵化质量阿拉克涅督虫获得了这个稀有突变。</description>
<hediffClass>HediffWithComps</hediffClass>
<isBad>false</isBad>
<defaultLabelColor>(0.8, 0.6, 0.0)</defaultLabelColor>
<scenarioCanAdd>true</scenarioCanAdd>
<stages>
<li>
<capMods>
<li>
<capacity>Consciousness</capacity>
<offset>0.5</offset>
</li>
<li>
<capacity>Sight</capacity>
<offset>0.5</offset>
</li>
<li>
<capacity>Hearing</capacity>
<offset>0.5</offset>
</li>
</capMods>
</li>
</stages>
</HediffDef>
</Defs>

View File

@@ -0,0 +1,180 @@
<?xml version="1.0" encoding="utf-8"?>
<Defs>
<!--
分层特质奖励配置 Def
定义特质池和品质阶段规则,可被多个孵化建筑共享
品质范围0-150%
-->
<ArachnaeSwarm.TieredHediffRewardDef>
<defName>ARA_DefaultIncubatorRewards</defName>
<label>默认孵化奖励配置</label>
<description>阿拉克涅虫群的默认孵化特质奖励规则。根据孵化品质分为7个阶段不同阶段从不同特质池中抽取奖励。品质上限150%。</description>
<!-- ==================== 特质池定义 ==================== -->
<hediffPools>
<!-- 差特质池 (阶段1-3使用) -->
<li>
<poolId>bad</poolId>
<label>劣质特质</label>
<hediffs>
<li>ARA_Incubator_1_Flaw_Hediffs</li>
<li>ARA_Incubator_2_Flaw_Hediffs</li>
<li>ARA_Incubator_3_Flaw_Hediffs</li>
<li>ARA_Incubator_4_Flaw_Hediffs</li>
<li>ARA_Incubator_5_Flaw_Hediffs</li>
<li>ARA_Incubator_6_Flaw_Hediffs</li>
<li>ARA_Incubator_7_Flaw_Hediffs</li>
<li>ARA_Incubator_8_Flaw_Hediffs</li>
</hediffs>
</li>
<!-- 正常/好特质池 (阶段3-7使用) -->
<li>
<poolId>normal</poolId>
<label>普通特质</label>
<hediffs>
<li>ARA_Incubator_1_Reward_Hediffs</li>
<li>ARA_Incubator_2_Reward_Hediffs</li>
<li>ARA_Incubator_3_Reward_Hediffs</li>
<li>ARA_Incubator_4_Reward_Hediffs</li>
<li>ARA_Incubator_5_Reward_Hediffs</li>
<li>ARA_Incubator_6_Reward_Hediffs</li>
<li>ARA_Incubator_7_Reward_Hediffs</li>
<li>ARA_Incubator_8_Reward_Hediffs</li>
</hediffs>
</li>
<!-- 高级/精英特质池 (阶段6-7使用) -->
<li>
<poolId>elite</poolId>
<label>精英特质</label>
<hediffs>
<li>ARA_Incubator_Elite_Regeneration</li>
<li>ARA_Incubator_Elite_AdaptiveArmor</li>
<li>ARA_Incubator_Elite_BerserkGlands</li>
<li>ARA_Incubator_Elite_PsychicResonance</li>
</hediffs>
</li>
</hediffPools>
<!-- ==================== 7个品质阶段 (0-150%) ==================== -->
<qualityTiers>
<!-- 阶段10-20% - 2个差特质 -->
<li>
<tier>1</tier>
<minQuality>0.00</minQuality>
<maxQuality>0.20</maxQuality>
<tierLabel>极差</tierLabel>
<messageKey>ARA_Tier_Bad</messageKey>
<drawRules>
<li>
<poolId>bad</poolId>
<count>3</count>
</li>
</drawRules>
</li>
<!-- 阶段220-40% - 1个差特质 -->
<li>
<tier>2</tier>
<minQuality>0.20</minQuality>
<maxQuality>0.40</maxQuality>
<tierLabel>较差</tierLabel>
<messageKey>ARA_Tier_Poor</messageKey>
<drawRules>
<li>
<poolId>bad</poolId>
<count>2</count>
</li>
</drawRules>
</li>
<!-- 阶段340-60% - 1个好特质 + 1个差特质 -->
<li>
<tier>3</tier>
<minQuality>0.40</minQuality>
<maxQuality>0.60</maxQuality>
<tierLabel>普通</tierLabel>
<messageKey>ARA_Tier_Normal</messageKey>
<drawRules>
<li>
<poolId>normal</poolId>
<count>1</count>
</li>
<li>
<poolId>bad</poolId>
<count>1</count>
</li>
</drawRules>
</li>
<!-- 阶段460-80% - 2个好特质 -->
<li>
<tier>4</tier>
<minQuality>0.60</minQuality>
<maxQuality>0.80</maxQuality>
<tierLabel>良好</tierLabel>
<messageKey>ARA_Tier_Good</messageKey>
<drawRules>
<li>
<poolId>normal</poolId>
<count>2</count>
</li>
</drawRules>
</li>
<!-- 阶段580-120% - 3个好特质 -->
<li>
<tier>5</tier>
<minQuality>0.80</minQuality>
<maxQuality>1.20</maxQuality>
<tierLabel>极佳</tierLabel>
<messageKey>ARA_Tier_Excellent</messageKey>
<drawRules>
<li>
<poolId>normal</poolId>
<count>3</count>
</li>
</drawRules>
</li>
<!-- 阶段6120-140% - 3个好特质 + 1个高级特质 -->
<li>
<tier>6</tier>
<minQuality>1.20</minQuality>
<maxQuality>1.40</maxQuality>
<tierLabel>大师</tierLabel>
<messageKey>ARA_Tier_Elite</messageKey>
<drawRules>
<li>
<poolId>normal</poolId>
<count>3</count>
</li>
<li>
<poolId>elite</poolId>
<count>1</count>
</li>
</drawRules>
</li>
<!-- 阶段7140-150% - 3个好特质 + 2个高级特质 -->
<li>
<tier>7</tier>
<minQuality>1.40</minQuality>
<maxQuality>1.51</maxQuality> <!-- 略大于1.5以包含150% -->
<tierLabel>传奇</tierLabel>
<messageKey>ARA_Tier_Legendary</messageKey>
<drawRules>
<li>
<poolId>normal</poolId>
<count>3</count>
</li>
<li>
<poolId>elite</poolId>
<count>2</count>
</li>
</drawRules>
</li>
</qualityTiers>
</ArachnaeSwarm.TieredHediffRewardDef>
</Defs>

View File

@@ -149,52 +149,16 @@
</li>
<li Class="ArachnaeSwarm.CompProperties_IncubatorData">
<!-- 按钮和菜单配置 -->
<defaultIndex>0</defaultIndex>
<!-- 引用分层奖励配置 Def -->
<rewardDef>ARA_DefaultIncubatorRewards</rewardDef>
<!-- UI 配置 -->
<buttonLabel>孵化···</buttonLabel>
<buttonDesc>选择孵化的阿拉克涅督虫···</buttonDesc>
<menuTitle>孵化菜单</menuTitle>
<defaultIconPath>ArachnaeSwarm/UI/Commands/ARA_NodeSwarmIcon</defaultIconPath>
<!-- 全局Hediff奖励所有配置共享 -->
<globalExtraHediffs>
<li>ARA_Incubator_1_Reward_Hediffs</li>
<li>ARA_Incubator_2_Reward_Hediffs</li>
<li>ARA_Incubator_3_Reward_Hediffs</li>
<li>ARA_Incubator_4_Reward_Hediffs</li>
<li>ARA_Incubator_5_Reward_Hediffs</li>
<li>ARA_Incubator_6_Reward_Hediffs</li>
<li>ARA_Incubator_7_Reward_Hediffs</li>
<li>ARA_Incubator_8_Reward_Hediffs</li>
</globalExtraHediffs>
<globalHediffRewards>
<li Class="ArachnaeSwarm.QualityHediffReward">
<qualityThreshold>0.30</qualityThreshold>
<hediffCount>1</hediffCount>
<giveAllHediffs>false</giveAllHediffs>
<messageKey>ARA_QualityReward_1Hediff</messageKey>
</li>
<li Class="ArachnaeSwarm.QualityHediffReward">
<qualityThreshold>0.50</qualityThreshold>
<hediffCount>2</hediffCount>
<giveAllHediffs>false</giveAllHediffs>
<messageKey>ARA_QualityReward_2Hediff</messageKey>
</li>
<li Class="ArachnaeSwarm.QualityHediffReward">
<qualityThreshold>0.85</qualityThreshold>
<hediffCount>3</hediffCount>
<giveAllHediffs>false</giveAllHediffs>
<messageKey>ARA_QualityReward_3Hediff</messageKey>
</li>
<li Class="ArachnaeSwarm.QualityHediffReward">
<qualityThreshold>0.99</qualityThreshold>
<hediffCount>4</hediffCount>
<giveAllHediffs>false</giveAllHediffs>
<messageKey>ARA_QualityReward_4Hediff</messageKey>
</li>
</globalHediffRewards>
<!-- 孵化配置列表 -->
<incubationConfigs>
<li>
<pawnKind>ArachnaeNode_Race_ShieldHead</pawnKind>
@@ -621,45 +585,10 @@
<!-- b. 孵化配置数据组件(提供可孵化单位列表) -->
<li Class="ArachnaeSwarm.CompProperties_IncubatorData">
<!-- 全局Hediff奖励所有配置共享 -->
<globalExtraHediffs>
<li>ARA_Incubator_1_Reward_Hediffs</li>
<li>ARA_Incubator_2_Reward_Hediffs</li>
<li>ARA_Incubator_3_Reward_Hediffs</li>
<li>ARA_Incubator_4_Reward_Hediffs</li>
<li>ARA_Incubator_5_Reward_Hediffs</li>
<li>ARA_Incubator_6_Reward_Hediffs</li>
<li>ARA_Incubator_7_Reward_Hediffs</li>
<li>ARA_Incubator_8_Reward_Hediffs</li>
</globalExtraHediffs>
<globalHediffRewards>
<li Class="ArachnaeSwarm.QualityHediffReward">
<qualityThreshold>0.30</qualityThreshold>
<hediffCount>1</hediffCount>
<giveAllHediffs>false</giveAllHediffs>
<messageKey>ARA_QualityReward_1Hediff</messageKey>
</li>
<li Class="ArachnaeSwarm.QualityHediffReward">
<qualityThreshold>0.50</qualityThreshold>
<hediffCount>2</hediffCount>
<giveAllHediffs>false</giveAllHediffs>
<messageKey>ARA_QualityReward_2Hediff</messageKey>
</li>
<li Class="ArachnaeSwarm.QualityHediffReward">
<qualityThreshold>0.85</qualityThreshold>
<hediffCount>3</hediffCount>
<giveAllHediffs>false</giveAllHediffs>
<messageKey>ARA_QualityReward_3Hediff</messageKey>
</li>
<li Class="ArachnaeSwarm.QualityHediffReward">
<qualityThreshold>0.99</qualityThreshold>
<hediffCount>4</hediffCount>
<giveAllHediffs>false</giveAllHediffs>
<messageKey>ARA_QualityReward_4Hediff</messageKey>
</li>
</globalHediffRewards>
<!-- 引用分层奖励配置 Def -->
<rewardDef>ARA_DefaultIncubatorRewards</rewardDef>
<!-- 孵化配置列表 -->
<incubationConfigs>
<li>
<pawnKind>ArachnaeNode_Race_ShieldHead</pawnKind>

View File

@@ -466,7 +466,7 @@ namespace ArachnaeSwarm
}
float progress = (float)ticksUnderOptimalConditions / _selectedProcess.productionTicks;
float finalQualityPercent = Mathf.Clamp01(progress - temperaturePenaltyPercent);
float finalQualityPercent = Mathf.Clamp(progress - temperaturePenaltyPercent, 0f, 1.5f);
QualityCategory finalQuality = QualityCategory.Awful;
foreach (var threshold in Props.qualityThresholds.OrderByDescending(q => q.threshold))
@@ -766,7 +766,7 @@ namespace ArachnaeSwarm
if (Props.qualityThresholds != null && Props.qualityThresholds.Count > 0)
{
var qualityDetails = GetEstimatedQualityDetails();
float qualityProgress = Mathf.Clamp01(qualityDetails.baseScore - qualityDetails.penalty);
float qualityProgress = Mathf.Clamp(qualityDetails.baseScore - qualityDetails.penalty, 0f, 1.5f);
drawPos.y += 0.2f;

View File

@@ -208,7 +208,7 @@ namespace ArachnaeSwarm
return (QualityCategory.Normal, 0f, 0f);
}
float progress = (order.process.productionTicks > 0) ? (float)order.ticksUnderOptimalConditions / order.process.productionTicks : 1f;
float finalQualityPercent = Mathf.Clamp01(progress - order.temperaturePenaltyPercent);
float finalQualityPercent = Mathf.Clamp(progress - order.temperaturePenaltyPercent, 0f, 1.5f);
QualityCategory finalQuality = QualityCategory.Awful;
foreach (var threshold in Props.qualityThresholds.OrderByDescending(q => q.threshold))
{

View File

@@ -365,18 +365,22 @@ namespace ArachnaeSwarm
private void ApplyQualityEffects(Pawn pawn, float qualityPercent, IncubationConfig config)
{
// 应用 Hediff 奖励
if (config != null && config.extraHediffs != null)
// 使用新的分层奖励系统(优先)或回退到旧系统
List<HediffDef> rewardHediffs = IncubatorDataComp?.DrawRewardsForQuality(qualityPercent);
// 如果新系统没有返回结果,回退到旧系统
if ((rewardHediffs == null || rewardHediffs.Count == 0) && config?.extraHediffs != null)
{
var rewardHediffs = config.GetRewardHediffs(qualityPercent);
if (rewardHediffs != null)
rewardHediffs = config.GetRewardHediffs(qualityPercent);
}
if (rewardHediffs != null)
{
foreach (var hediffDef in rewardHediffs)
{
foreach (var hediffDef in rewardHediffs)
if (hediffDef != null)
{
if (hediffDef != null)
{
pawn.health.AddHediff(hediffDef);
}
pawn.health.AddHediff(hediffDef);
}
}
}

View File

@@ -0,0 +1,263 @@
// File: Building_Comps/ARA_TieredHediffReward/CompTieredIncubatorData.cs
// 分层孵化器数据组件
using System.Collections.Generic;
using System.Text;
using RimWorld;
using UnityEngine;
using Verse;
namespace ArachnaeSwarm
{
/// <summary>
/// 分层孵化器组件属性 - 只需引用 TieredHediffRewardDef
/// </summary>
public class CompProperties_TieredIncubatorData : CompProperties
{
// === 孵化配置 ===
/// <summary>孵化配置列表(可孵化的 PawnKind</summary>
public List<IncubationConfig> incubationConfigs = new List<IncubationConfig>();
/// <summary>默认选择索引</summary>
public int defaultIndex = 0;
// === UI 配置 ===
/// <summary>按钮标签翻译键</summary>
public string buttonLabel = "IncubatorButtonLabel";
/// <summary>按钮描述翻译键</summary>
public string buttonDesc = "IncubatorButtonDesc";
/// <summary>菜单标题翻译键</summary>
public string menuTitle = "IncubatorMenuTitle";
/// <summary>默认图标路径</summary>
public string defaultIconPath = "UI/Commands/Default";
// === 引用奖励 Def ===
/// <summary>分层奖励配置的 Def 引用</summary>
public TieredHediffRewardDef rewardDef;
public CompProperties_TieredIncubatorData()
{
compClass = typeof(CompTieredIncubatorData);
}
public override void ResolveReferences(ThingDef parentDef)
{
base.ResolveReferences(parentDef);
if (incubationConfigs == null)
incubationConfigs = new List<IncubationConfig>();
}
public override IEnumerable<string> ConfigErrors(ThingDef parentDef)
{
foreach (var error in base.ConfigErrors(parentDef))
yield return error;
if (rewardDef == null)
yield return "rewardDef is null - no tiered hediff reward configuration";
if (incubationConfigs == null || incubationConfigs.Count == 0)
yield return "incubationConfigs is empty";
}
}
/// <summary>
/// 分层孵化器数据组件 - 管理当前选择状态和奖励抽取
/// </summary>
public class CompTieredIncubatorData : ThingComp
{
// === 属性访问 ===
private CompProperties_TieredIncubatorData Props => (CompProperties_TieredIncubatorData)props;
// === 状态 ===
/// <summary>当前选择的配置索引 (-1 表示未选择)</summary>
private int selectedIndex = -1;
// === 公开属性 ===
/// <summary>获取孵化配置列表</summary>
public List<IncubationConfig> IncubationConfigs => Props?.incubationConfigs ?? new List<IncubationConfig>();
/// <summary>获取奖励 Def</summary>
public TieredHediffRewardDef RewardDef => Props?.rewardDef;
/// <summary>获取当前选中的配置</summary>
public IncubationConfig SelectedConfig
{
get
{
var configs = IncubationConfigs;
if (configs.Count == 0) return null;
// 未选择时返回 null
if (selectedIndex == -1)
return null;
if (selectedIndex < 0 || selectedIndex >= configs.Count)
return null;
return configs[selectedIndex];
}
}
/// <summary>获取当前选择的 PawnKind</summary>
public PawnKindDef SelectedPawnKind => SelectedConfig?.pawnKind;
/// <summary>获取当前选择的索引</summary>
public int GetSelectedIndex() => selectedIndex;
// === 方法 ===
/// <summary>
/// 切换到指定配置 (-1 表示清除选择)
/// </summary>
public void SwitchToConfig(int index)
{
if (index == -1)
{
selectedIndex = -1;
}
else if (index >= 0 && index < IncubationConfigs.Count)
{
selectedIndex = index;
}
}
/// <summary>
/// 检查配置是否可用(研究是否完成)
/// </summary>
public bool IsConfigAvailable(int index)
{
if (index < 0 || index >= IncubationConfigs.Count)
return false;
var config = IncubationConfigs[index];
return config?.IsResearchComplete ?? false;
}
/// <summary>
/// 根据品质抽取 Hediff 奖励
/// </summary>
public List<HediffDef> DrawRewardsForQuality(float quality)
{
if (RewardDef == null)
{
Log.Warning($"[CompTieredIncubatorData] No rewardDef configured for {parent.def.defName}");
return new List<HediffDef>();
}
return RewardDef.DrawRewardsForQuality(quality);
}
/// <summary>
/// 获取品质对应的阶段信息
/// </summary>
public QualityTier GetTierForQuality(float quality)
{
return RewardDef?.GetTierForQuality(quality);
}
/// <summary>
/// 显示目标选择浮动菜单
/// </summary>
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()));
}
/// <summary>
/// 获取奖励系统的描述文本
/// </summary>
public string GetRewardSystemDescription()
{
if (RewardDef == null)
return null;
var builder = new StringBuilder();
builder.AppendLine("ARA_TieredReward_Title".Translate());
builder.AppendLine();
// 显示各阶段信息
if (RewardDef.qualityTiers != null)
{
foreach (var tier in RewardDef.qualityTiers)
{
string qualityRange = $"{tier.minQuality:P0} - {tier.maxQuality:P0}";
builder.AppendLine($" {tier.tierLabel ?? $"{tier.tier}"}: {qualityRange}");
if (tier.drawRules != null)
{
foreach (var rule in tier.drawRules)
{
var pool = RewardDef.GetPool(rule.poolId);
string poolLabel = pool?.label ?? rule.poolId;
builder.AppendLine($" - {poolLabel} x{rule.count}");
}
}
}
}
return builder.ToString().TrimEndNewlines();
}
// === 存档 ===
public override void PostExposeData()
{
base.PostExposeData();
Scribe_Values.Look(ref selectedIndex, "selectedIndex", -1);
if (Scribe.mode == LoadSaveMode.PostLoadInit)
{
// 验证索引有效性
if (selectedIndex >= IncubationConfigs.Count)
selectedIndex = Mathf.Clamp(Props.defaultIndex, 0, IncubationConfigs.Count - 1);
}
}
// === 检查面板 ===
public override string CompInspectStringExtra()
{
var current = SelectedConfig;
if (current != null)
{
string status = "ARA_Status_Target".Translate(current.pawnKind.LabelCap);
if (current.requiredResearch != null && !current.requiredResearch.IsFinished)
{
status += " (" + "ARA_Menu_RequiresResearch".Translate(current.requiredResearch.LabelCap) + ")";
}
return status;
}
return null;
}
}
}

View File

@@ -0,0 +1,280 @@
// File: Defs/TieredHediffRewardDef.cs
// 分层特质奖励系统 - Def 定义
using System.Collections.Generic;
using RimWorld;
using UnityEngine;
using Verse;
namespace ArachnaeSwarm
{
/// <summary>
/// 特质池 - 定义一组可抽取的 Hediff
/// </summary>
public class HediffPool
{
/// <summary>池ID如 "bad", "normal", "elite"</summary>
public string poolId;
/// <summary>显示名称,如 "劣质特质"</summary>
public string label;
/// <summary>池中的 Hediff 列表</summary>
public List<HediffDef> hediffs = new List<HediffDef>();
/// <summary>
/// 从池中随机抽取指定数量的 Hediff
/// </summary>
/// <param name="count">抽取数量</param>
/// <param name="allowDuplicates">是否允许重复</param>
/// <returns>抽取的 Hediff 列表</returns>
public List<HediffDef> DrawRandom(int count, bool allowDuplicates = false)
{
var result = new List<HediffDef>();
if (hediffs == null || hediffs.Count == 0 || count <= 0)
return result;
if (allowDuplicates)
{
// 允许重复:直接随机抽取
for (int i = 0; i < count; i++)
{
result.Add(hediffs.RandomElement());
}
}
else
{
// 不允许重复:从可用列表中移除已抽取的
var available = new List<HediffDef>(hediffs);
int actualCount = Mathf.Min(count, available.Count);
for (int i = 0; i < actualCount; i++)
{
var selected = available.RandomElement();
result.Add(selected);
available.Remove(selected);
}
}
return result;
}
}
/// <summary>
/// 从池中抽取的规则
/// </summary>
public class PoolDrawRule
{
/// <summary>从哪个池抽取池ID</summary>
public string poolId;
/// <summary>抽取数量</summary>
public int count = 1;
/// <summary>是否允许重复抽取同一个 Hediff</summary>
public bool allowDuplicates = false;
}
/// <summary>
/// 品质阶段配置 - 定义某个品质范围内的抽取规则
/// </summary>
public class QualityTier
{
/// <summary>阶段编号 (1-7)</summary>
public int tier;
/// <summary>最低品质阈值 (0-1),包含</summary>
public float minQuality;
/// <summary>最高品质阈值 (0-1),不包含(除非是最后一个阶段)</summary>
public float maxQuality;
/// <summary>阶段标签,如 "劣质", "普通", "传奇"</summary>
public string tierLabel;
/// <summary>消息翻译键,孵化完成时显示</summary>
public string messageKey;
/// <summary>该阶段的抽取规则列表(可从多个池抽取)</summary>
public List<PoolDrawRule> drawRules = new List<PoolDrawRule>();
/// <summary>
/// 检查品质值是否属于该阶段
/// </summary>
public bool Contains(float quality)
{
return quality >= minQuality && quality < maxQuality;
}
}
/// <summary>
/// 分层特质奖励配置的 Def 类
/// 定义特质池和品质阶段规则,可被多个建筑共享
/// </summary>
public class TieredHediffRewardDef : Def
{
// === 特质池定义 ===
/// <summary>所有特质池列表</summary>
public List<HediffPool> hediffPools = new List<HediffPool>();
// === 品质阶段定义 ===
/// <summary>所有品质阶段列表</summary>
public List<QualityTier> qualityTiers = new List<QualityTier>();
// === 缓存 ===
private Dictionary<string, HediffPool> poolCache;
/// <summary>
/// 配置错误检查
/// </summary>
public override IEnumerable<string> ConfigErrors()
{
foreach (var error in base.ConfigErrors())
yield return error;
if (hediffPools == null || hediffPools.Count == 0)
yield return "hediffPools is empty";
if (qualityTiers == null || qualityTiers.Count == 0)
yield return "qualityTiers is empty";
// 检查池ID是否重复
var poolIds = new HashSet<string>();
foreach (var pool in hediffPools)
{
if (string.IsNullOrEmpty(pool.poolId))
yield return "A hediffPool has empty poolId";
else if (!poolIds.Add(pool.poolId))
yield return $"Duplicate poolId: {pool.poolId}";
}
// 检查阶段配置
foreach (var tier in qualityTiers)
{
if (tier.minQuality >= tier.maxQuality)
yield return $"Tier {tier.tier}: minQuality ({tier.minQuality}) >= maxQuality ({tier.maxQuality})";
if (tier.drawRules != null)
{
foreach (var rule in tier.drawRules)
{
if (!poolIds.Contains(rule.poolId))
yield return $"Tier {tier.tier}: references unknown poolId '{rule.poolId}'";
}
}
}
}
/// <summary>
/// 解析引用后的初始化
/// </summary>
public override void ResolveReferences()
{
base.ResolveReferences();
// 构建池缓存
poolCache = new Dictionary<string, HediffPool>();
if (hediffPools != null)
{
foreach (var pool in hediffPools)
{
if (!string.IsNullOrEmpty(pool.poolId))
{
poolCache[pool.poolId] = pool;
}
}
}
// 按 minQuality 排序阶段
qualityTiers?.Sort((a, b) => a.minQuality.CompareTo(b.minQuality));
}
/// <summary>
/// 根据池ID获取特质池
/// </summary>
public HediffPool GetPool(string poolId)
{
if (poolCache != null && poolCache.TryGetValue(poolId, out var pool))
return pool;
return hediffPools?.Find(p => p.poolId == poolId);
}
/// <summary>
/// 根据品质百分比获取对应阶段
/// </summary>
public QualityTier GetTierForQuality(float quality)
{
if (qualityTiers == null || qualityTiers.Count == 0)
return null;
// 限制在 0-1.5 范围 (支持150%品质上限)
quality = Mathf.Clamp(quality, 0f, 1.5f);
foreach (var tier in qualityTiers)
{
if (tier.Contains(quality))
return tier;
}
// 如果是 100%,返回最后一个阶段
if (quality >= 1f)
return qualityTiers[qualityTiers.Count - 1];
return null;
}
/// <summary>
/// 根据品质抽取 Hediff 奖励
/// </summary>
/// <param name="quality">品质值 (0-1)</param>
/// <returns>抽取的 Hediff 列表</returns>
public List<HediffDef> DrawRewardsForQuality(float quality)
{
var result = new List<HediffDef>();
var tier = GetTierForQuality(quality);
if (tier?.drawRules == null)
return result;
foreach (var rule in tier.drawRules)
{
var pool = GetPool(rule.poolId);
if (pool == null)
{
Log.Warning($"[TieredHediffReward] Pool '{rule.poolId}' not found in def '{defName}'");
continue;
}
var drawn = pool.DrawRandom(rule.count, rule.allowDuplicates);
result.AddRange(drawn);
}
return result;
}
/// <summary>
/// 获取品质阶段的描述文本
/// </summary>
public string GetTierDescription(float quality)
{
var tier = GetTierForQuality(quality);
if (tier == null)
return null;
return tier.tierLabel ?? $"阶段 {tier.tier}";
}
/// <summary>
/// 获取品质阶段的消息
/// </summary>
public string GetTierMessage(float quality)
{
var tier = GetTierForQuality(quality);
if (tier == null || string.IsNullOrEmpty(tier.messageKey))
return null;
return tier.messageKey.Translate();
}
}
}

View File

@@ -341,7 +341,8 @@ namespace ArachnaeSwarm
// 品质增长新公式50%通量时与进度同步)
float qualityGain = IncubatorUtils.CalculateQualityGainNew(fluxSpeed, neutronFlux);
qualityProgress = Mathf.Min(qualityProgress + qualityGain, qualityTotal);
// 不限制上限允许超过100%最高150%
qualityProgress += qualityGain;
}
if (incubationProgress >= incubationDuration)
@@ -405,10 +406,8 @@ namespace ArachnaeSwarm
private void ApplyHediffRewards(Pawn pawn, float qualityPercent)
{
var config = IncubatorData?.SelectedConfig;
if (config == null) return;
List<HediffDef> rewardHediffs = config.GetRewardHediffs(qualityPercent);
// 使用新的分层奖励系统(优先)或回退到旧系统
List<HediffDef> rewardHediffs = IncubatorData?.DrawRewardsForQuality(qualityPercent);
if (rewardHediffs == null || rewardHediffs.Count == 0) return;
int appliedCount = 0;
@@ -424,9 +423,17 @@ namespace ArachnaeSwarm
if (appliedCount > 0)
{
string message = config.GetRewardMessage(qualityPercent);
// 使用分层系统的消息
var tier = IncubatorData?.GetTierForQuality(qualityPercent);
string message = null;
if (tier != null && !string.IsNullOrEmpty(tier.messageKey))
{
message = tier.messageKey.Translate(pawn.LabelShortCap, appliedCount);
}
if (string.IsNullOrEmpty(message))
{
message = "ARA_QualityReward_Default".Translate(pawn.LabelShortCap, appliedCount);
}
Messages.Message(message, pawn, MessageTypeDefOf.PositiveEvent);
}
}

View File

@@ -247,7 +247,10 @@ namespace ArachnaeSwarm
public string menuTitle = "IncubatorMenuTitle"; // 菜单标题翻译键
public string defaultIconPath = "UI/Commands/Default";
// === 新增:全局Hediff奖励所有配置共享===
// === 新增:分层奖励Def引用推荐使用===
public TieredHediffRewardDef rewardDef;
// === 旧版全局Hediff奖励保留向后兼容===
public List<HediffDef> globalExtraHediffs = new List<HediffDef>();
public List<QualityHediffReward> globalHediffRewards = new List<QualityHediffReward>();
@@ -336,6 +339,9 @@ namespace ArachnaeSwarm
// 公开获取孵化配置列表的方法
public List<IncubationConfig> IncubationConfigs => Props?.incubationConfigs ?? new List<IncubationConfig>();
// 获取奖励 Def新系统
public TieredHediffRewardDef RewardDef => Props?.rewardDef;
// 获取当前选择的配置
public IncubationConfig SelectedConfig
{
@@ -493,5 +499,73 @@ namespace ArachnaeSwarm
return builder.ToString().TrimEndNewlines();
}
// === 新增:使用分层系统抽取奖励 ===
/// <summary>
/// 根据品质抽取 Hediff 奖励(优先使用新的分层系统)
/// </summary>
/// <param name="quality">品质值 (0-1.5支持150%上限)</param>
/// <returns>抽取的 Hediff 列表</returns>
public List<HediffDef> DrawRewardsForQuality(float quality)
{
// 优先使用新的分层奖励系统
if (RewardDef != null)
{
return RewardDef.DrawRewardsForQuality(quality);
}
// 回退到旧系统
var config = SelectedConfig;
if (config != null)
{
return config.GetRewardHediffs(quality);
}
return new List<HediffDef>();
}
/// <summary>
/// 获取品质对应的阶段信息(仅新系统可用)
/// </summary>
public QualityTier GetTierForQuality(float quality)
{
return RewardDef?.GetTierForQuality(quality);
}
/// <summary>
/// 获取奖励系统的描述文本
/// </summary>
public string GetRewardSystemDescription()
{
if (RewardDef == null)
return GetHediffRewardDescription(); // 回退到旧描述
var builder = new StringBuilder();
builder.AppendLine("ARA_TieredReward_Title".Translate());
builder.AppendLine();
// 显示各阶段信息
if (RewardDef.qualityTiers != null)
{
foreach (var tier in RewardDef.qualityTiers)
{
string qualityRange = $"{tier.minQuality:P0} - {tier.maxQuality:P0}";
builder.AppendLine($" {tier.tierLabel ?? $"{tier.tier}"}: {qualityRange}");
if (tier.drawRules != null)
{
foreach (var rule in tier.drawRules)
{
var pool = RewardDef.GetPool(rule.poolId);
string poolLabel = pool?.label ?? rule.poolId;
builder.AppendLine($" - {poolLabel} x{rule.count}");
}
}
}
}
return builder.ToString().TrimEndNewlines();
}
}
}