diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll
index 2f0a627..bd681c5 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_Incubator_Reward.xml b/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_Incubator_Reward.xml
index 8808eaa..c8af12d 100644
--- a/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_Incubator_Reward.xml
+++ b/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_Incubator_Reward.xml
@@ -216,4 +216,163 @@
+
+
+
+ ARA_Incubator_5_Flaw_Hediffs
+
+ 急速的孵化使得该阿拉克涅督虫的肌肉组织发育不全,力量远低于正常个体。\n\n由于较差的孵化质量,阿拉克涅督虫获得了这个不利突变。
+ HediffWithComps
+ false
+ (0.9, 0.2 , 0.1)
+ true
+
+
+
+ 0.5
+ 0.6
+
+
+
+
+
+
+ ARA_Incubator_6_Flaw_Hediffs
+
+ 急速的孵化导致该阿拉克涅督虫的凝血机制异常,一旦受伤就会大量失血。\n\n由于较差的孵化质量,阿拉克涅督虫获得了这个不利突变。
+ HediffWithComps
+ false
+ (0.9, 0.2 , 0.1)
+ true
+
+
+ 3.0
+
+
+
+
+
+ ARA_Incubator_7_Flaw_Hediffs
+
+ 急速的孵化使得该阿拉克涅督虫的内骨骼异常脆弱,更容易受到致命伤害。\n\n由于较差的孵化质量,阿拉克涅督虫获得了这个不利突变。
+ HediffWithComps
+ false
+ (0.9, 0.2 , 0.1)
+ true
+
+
+
+ 1.5
+
+
+
+
+
+
+ ARA_Incubator_8_Flaw_Hediffs
+
+ 急速的孵化使得该阿拉克涅督虫的免疫系统发育不良,对疾病的抵抗力极差。\n\n由于较差的孵化质量,阿拉克涅督虫获得了这个不利突变。
+ HediffWithComps
+ false
+ (0.9, 0.2 , 0.1)
+ true
+
+
+
+ 0.5
+
+
+
+
+
+
+
+
+ ARA_Incubator_Elite_Regeneration
+
+ 该阿拉克涅督虫的甲壳密度远超常规个体,几乎坚不可摧,同时还具有优秀的热抗性。\n\n由于极佳的孵化质量,阿拉克涅督虫获得了这个稀有突变。
+ HediffWithComps
+ false
+ (0.8, 0.6, 0.0)
+ true
+
+
+
+ 1.0
+ 1.0
+ 0.8
+
+
+
+
+
+
+
+ ARA_Incubator_Elite_AdaptiveArmor
+
+ 该阿拉克涅督虫的腺体异常发达,持续分泌高浓度激素,使其处于极度亢奋状态,攻击速度惊人。\n\n由于极佳的孵化质量,阿拉克涅督虫获得了这个稀有突变。
+ HediffWithComps
+ false
+ (0.8, 0.6, 0.0)
+ true
+
+
+
+ 1.5
+
+
+ 0.4
+ 0.5
+
+
+
+
+
+
+
+ ARA_Incubator_Elite_BerserkGlands
+
+ 该阿拉克涅督虫的肌肉组织经过完美发育,力量远超同类,近战攻击威力惊人,负重能力也大幅提升。\n\n由于极佳的孵化质量,阿拉克涅督虫获得了这个稀有突变。
+ HediffWithComps
+ false
+ (0.8, 0.6, 0.0)
+ true
+
+
+
+ 5
+ 3
+
+
+
+
+
+
+
+ ARA_Incubator_Elite_PsychicResonance
+
+ 该阿拉克涅督虫的神经系统经过完美发育,意识、视觉、听觉等各项感知能力都大幅超越同类。\n\n由于极佳的孵化质量,阿拉克涅督虫获得了这个稀有突变。
+ HediffWithComps
+ false
+ (0.8, 0.6, 0.0)
+ true
+
+
+
+
+ Consciousness
+ 0.5
+
+
+ Sight
+ 0.5
+
+
+ Hearing
+ 0.5
+
+
+
+
+
\ No newline at end of file
diff --git a/1.6/1.6/Defs/MiscSettingDefs/ARA_TieredHediffRewards.xml b/1.6/1.6/Defs/MiscSettingDefs/ARA_TieredHediffRewards.xml
new file mode 100644
index 0000000..6405530
--- /dev/null
+++ b/1.6/1.6/Defs/MiscSettingDefs/ARA_TieredHediffRewards.xml
@@ -0,0 +1,180 @@
+
+
+
+
+ ARA_DefaultIncubatorRewards
+
+ 阿拉克涅虫群的默认孵化特质奖励规则。根据孵化品质分为7个阶段,不同阶段从不同特质池中抽取奖励。品质上限150%。
+
+
+
+
+
+ bad
+
+
+ ARA_Incubator_1_Flaw_Hediffs
+ ARA_Incubator_2_Flaw_Hediffs
+ ARA_Incubator_3_Flaw_Hediffs
+ ARA_Incubator_4_Flaw_Hediffs
+ ARA_Incubator_5_Flaw_Hediffs
+ ARA_Incubator_6_Flaw_Hediffs
+ ARA_Incubator_7_Flaw_Hediffs
+ ARA_Incubator_8_Flaw_Hediffs
+
+
+
+
+
+ normal
+
+
+ ARA_Incubator_1_Reward_Hediffs
+ ARA_Incubator_2_Reward_Hediffs
+ ARA_Incubator_3_Reward_Hediffs
+ ARA_Incubator_4_Reward_Hediffs
+ ARA_Incubator_5_Reward_Hediffs
+ ARA_Incubator_6_Reward_Hediffs
+ ARA_Incubator_7_Reward_Hediffs
+ ARA_Incubator_8_Reward_Hediffs
+
+
+
+
+
+ elite
+
+
+ ARA_Incubator_Elite_Regeneration
+ ARA_Incubator_Elite_AdaptiveArmor
+ ARA_Incubator_Elite_BerserkGlands
+ ARA_Incubator_Elite_PsychicResonance
+
+
+
+
+
+
+
+
+ 1
+ 0.00
+ 0.20
+ 极差
+ ARA_Tier_Bad
+
+
+ bad
+ 3
+
+
+
+
+
+
+ 2
+ 0.20
+ 0.40
+ 较差
+ ARA_Tier_Poor
+
+
+ bad
+ 2
+
+
+
+
+
+
+ 3
+ 0.40
+ 0.60
+ 普通
+ ARA_Tier_Normal
+
+
+ normal
+ 1
+
+
+ bad
+ 1
+
+
+
+
+
+
+ 4
+ 0.60
+ 0.80
+ 良好
+ ARA_Tier_Good
+
+
+ normal
+ 2
+
+
+
+
+
+
+ 5
+ 0.80
+ 1.20
+ 极佳
+ ARA_Tier_Excellent
+
+
+ normal
+ 3
+
+
+
+
+
+
+ 6
+ 1.20
+ 1.40
+ 大师
+ ARA_Tier_Elite
+
+
+ normal
+ 3
+
+
+ elite
+ 1
+
+
+
+
+
+
+ 7
+ 1.40
+ 1.51
+ 传奇
+ ARA_Tier_Legendary
+
+
+ normal
+ 3
+
+
+ elite
+ 2
+
+
+
+
+
+
diff --git a/1.6/1.6/Defs/Thing_building/ARA_Ootheca.xml b/1.6/1.6/Defs/Thing_building/ARA_Ootheca.xml
index 24c62cd..1b6a34a 100644
--- a/1.6/1.6/Defs/Thing_building/ARA_Ootheca.xml
+++ b/1.6/1.6/Defs/Thing_building/ARA_Ootheca.xml
@@ -149,52 +149,16 @@
-
- 0
+
+ ARA_DefaultIncubatorRewards
+
+
孵化···
选择孵化的阿拉克涅督虫···
孵化菜单
ArachnaeSwarm/UI/Commands/ARA_NodeSwarmIcon
-
-
-
- ARA_Incubator_1_Reward_Hediffs
- ARA_Incubator_2_Reward_Hediffs
- ARA_Incubator_3_Reward_Hediffs
- ARA_Incubator_4_Reward_Hediffs
- ARA_Incubator_5_Reward_Hediffs
- ARA_Incubator_6_Reward_Hediffs
- ARA_Incubator_7_Reward_Hediffs
- ARA_Incubator_8_Reward_Hediffs
-
-
-
-
- 0.30
- 1
- false
- ARA_QualityReward_1Hediff
-
-
- 0.50
- 2
- false
- ARA_QualityReward_2Hediff
-
-
- 0.85
- 3
- false
- ARA_QualityReward_3Hediff
-
-
- 0.99
- 4
- false
- ARA_QualityReward_4Hediff
-
-
+
ArachnaeNode_Race_ShieldHead
@@ -621,45 +585,10 @@
-
-
- ARA_Incubator_1_Reward_Hediffs
- ARA_Incubator_2_Reward_Hediffs
- ARA_Incubator_3_Reward_Hediffs
- ARA_Incubator_4_Reward_Hediffs
- ARA_Incubator_5_Reward_Hediffs
- ARA_Incubator_6_Reward_Hediffs
- ARA_Incubator_7_Reward_Hediffs
- ARA_Incubator_8_Reward_Hediffs
-
-
-
-
- 0.30
- 1
- false
- ARA_QualityReward_1Hediff
-
-
- 0.50
- 2
- false
- ARA_QualityReward_2Hediff
-
-
- 0.85
- 3
- false
- ARA_QualityReward_3Hediff
-
-
- 0.99
- 4
- false
- ARA_QualityReward_4Hediff
-
-
+
+ ARA_DefaultIncubatorRewards
+
ArachnaeNode_Race_ShieldHead
diff --git a/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompInteractiveProducer.cs b/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompInteractiveProducer.cs
index c4719bf..1e32b39 100644
--- a/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompInteractiveProducer.cs
+++ b/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompInteractiveProducer.cs
@@ -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;
diff --git a/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompQueuedInteractiveProducer.cs b/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompQueuedInteractiveProducer.cs
index 63e1854..6ecc402 100644
--- a/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompQueuedInteractiveProducer.cs
+++ b/Source/ArachnaeSwarm/Building_Comps/ARA_CompInteractiveProducer/CompQueuedInteractiveProducer.cs
@@ -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))
{
diff --git a/Source/ArachnaeSwarm/Building_Comps/ARA_SpawnPawnFromList/CompQueuedPawnSpawnerWithFlux.cs b/Source/ArachnaeSwarm/Building_Comps/ARA_SpawnPawnFromList/CompQueuedPawnSpawnerWithFlux.cs
index f599339..5295c93 100644
--- a/Source/ArachnaeSwarm/Building_Comps/ARA_SpawnPawnFromList/CompQueuedPawnSpawnerWithFlux.cs
+++ b/Source/ArachnaeSwarm/Building_Comps/ARA_SpawnPawnFromList/CompQueuedPawnSpawnerWithFlux.cs
@@ -365,18 +365,22 @@ namespace ArachnaeSwarm
private void ApplyQualityEffects(Pawn pawn, float qualityPercent, IncubationConfig config)
{
- // 应用 Hediff 奖励
- if (config != null && config.extraHediffs != null)
+ // 使用新的分层奖励系统(优先)或回退到旧系统
+ List 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);
}
}
}
diff --git a/Source/ArachnaeSwarm/Building_Comps/ARA_TieredHediffReward/CompTieredIncubatorData.cs b/Source/ArachnaeSwarm/Building_Comps/ARA_TieredHediffReward/CompTieredIncubatorData.cs
new file mode 100644
index 0000000..122a1cc
--- /dev/null
+++ b/Source/ArachnaeSwarm/Building_Comps/ARA_TieredHediffReward/CompTieredIncubatorData.cs
@@ -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
+{
+ ///
+ /// 分层孵化器组件属性 - 只需引用 TieredHediffRewardDef
+ ///
+ public class CompProperties_TieredIncubatorData : CompProperties
+ {
+ // === 孵化配置 ===
+ /// 孵化配置列表(可孵化的 PawnKind)
+ public List incubationConfigs = new List();
+
+ /// 默认选择索引
+ public int defaultIndex = 0;
+
+ // === UI 配置 ===
+ /// 按钮标签翻译键
+ public string buttonLabel = "IncubatorButtonLabel";
+
+ /// 按钮描述翻译键
+ public string buttonDesc = "IncubatorButtonDesc";
+
+ /// 菜单标题翻译键
+ public string menuTitle = "IncubatorMenuTitle";
+
+ /// 默认图标路径
+ public string defaultIconPath = "UI/Commands/Default";
+
+ // === 引用奖励 Def ===
+ /// 分层奖励配置的 Def 引用
+ public TieredHediffRewardDef rewardDef;
+
+ public CompProperties_TieredIncubatorData()
+ {
+ compClass = typeof(CompTieredIncubatorData);
+ }
+
+ public override void ResolveReferences(ThingDef parentDef)
+ {
+ base.ResolveReferences(parentDef);
+
+ if (incubationConfigs == null)
+ incubationConfigs = new List();
+ }
+
+ public override IEnumerable 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";
+ }
+ }
+
+ ///
+ /// 分层孵化器数据组件 - 管理当前选择状态和奖励抽取
+ ///
+ public class CompTieredIncubatorData : ThingComp
+ {
+ // === 属性访问 ===
+ private CompProperties_TieredIncubatorData Props => (CompProperties_TieredIncubatorData)props;
+
+ // === 状态 ===
+ /// 当前选择的配置索引 (-1 表示未选择)
+ private int selectedIndex = -1;
+
+ // === 公开属性 ===
+
+ /// 获取孵化配置列表
+ public List IncubationConfigs => Props?.incubationConfigs ?? new List();
+
+ /// 获取奖励 Def
+ public TieredHediffRewardDef RewardDef => Props?.rewardDef;
+
+ /// 获取当前选中的配置
+ 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];
+ }
+ }
+
+ /// 获取当前选择的 PawnKind
+ public PawnKindDef SelectedPawnKind => SelectedConfig?.pawnKind;
+
+ /// 获取当前选择的索引
+ public int GetSelectedIndex() => selectedIndex;
+
+ // === 方法 ===
+
+ ///
+ /// 切换到指定配置 (-1 表示清除选择)
+ ///
+ public void SwitchToConfig(int index)
+ {
+ if (index == -1)
+ {
+ selectedIndex = -1;
+ }
+ else if (index >= 0 && index < IncubationConfigs.Count)
+ {
+ selectedIndex = index;
+ }
+ }
+
+ ///
+ /// 检查配置是否可用(研究是否完成)
+ ///
+ public bool IsConfigAvailable(int index)
+ {
+ if (index < 0 || index >= IncubationConfigs.Count)
+ return false;
+
+ var config = IncubationConfigs[index];
+ return config?.IsResearchComplete ?? false;
+ }
+
+ ///
+ /// 根据品质抽取 Hediff 奖励
+ ///
+ public List DrawRewardsForQuality(float quality)
+ {
+ if (RewardDef == null)
+ {
+ Log.Warning($"[CompTieredIncubatorData] No rewardDef configured for {parent.def.defName}");
+ return new List();
+ }
+
+ return RewardDef.DrawRewardsForQuality(quality);
+ }
+
+ ///
+ /// 获取品质对应的阶段信息
+ ///
+ public QualityTier GetTierForQuality(float quality)
+ {
+ return RewardDef?.GetTierForQuality(quality);
+ }
+
+ ///
+ /// 显示目标选择浮动菜单
+ ///
+ public void ShowFloatMenu()
+ {
+ var configs = IncubationConfigs;
+ if (configs == null || configs.Count == 0) return;
+
+ List options = new List();
+
+ 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()));
+ }
+
+ ///
+ /// 获取奖励系统的描述文本
+ ///
+ 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;
+ }
+ }
+}
diff --git a/Source/ArachnaeSwarm/Building_Comps/ARA_TieredHediffReward/TieredHediffRewardDef.cs b/Source/ArachnaeSwarm/Building_Comps/ARA_TieredHediffReward/TieredHediffRewardDef.cs
new file mode 100644
index 0000000..ee113e0
--- /dev/null
+++ b/Source/ArachnaeSwarm/Building_Comps/ARA_TieredHediffReward/TieredHediffRewardDef.cs
@@ -0,0 +1,280 @@
+// File: Defs/TieredHediffRewardDef.cs
+// 分层特质奖励系统 - Def 定义
+using System.Collections.Generic;
+using RimWorld;
+using UnityEngine;
+using Verse;
+
+namespace ArachnaeSwarm
+{
+ ///
+ /// 特质池 - 定义一组可抽取的 Hediff
+ ///
+ public class HediffPool
+ {
+ /// 池ID,如 "bad", "normal", "elite"
+ public string poolId;
+
+ /// 显示名称,如 "劣质特质"
+ public string label;
+
+ /// 池中的 Hediff 列表
+ public List hediffs = new List();
+
+ ///
+ /// 从池中随机抽取指定数量的 Hediff
+ ///
+ /// 抽取数量
+ /// 是否允许重复
+ /// 抽取的 Hediff 列表
+ public List DrawRandom(int count, bool allowDuplicates = false)
+ {
+ var result = new List();
+
+ 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(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;
+ }
+ }
+
+ ///
+ /// 从池中抽取的规则
+ ///
+ public class PoolDrawRule
+ {
+ /// 从哪个池抽取(池ID)
+ public string poolId;
+
+ /// 抽取数量
+ public int count = 1;
+
+ /// 是否允许重复抽取同一个 Hediff
+ public bool allowDuplicates = false;
+ }
+
+ ///
+ /// 品质阶段配置 - 定义某个品质范围内的抽取规则
+ ///
+ public class QualityTier
+ {
+ /// 阶段编号 (1-7)
+ public int tier;
+
+ /// 最低品质阈值 (0-1),包含
+ public float minQuality;
+
+ /// 最高品质阈值 (0-1),不包含(除非是最后一个阶段)
+ public float maxQuality;
+
+ /// 阶段标签,如 "劣质", "普通", "传奇"
+ public string tierLabel;
+
+ /// 消息翻译键,孵化完成时显示
+ public string messageKey;
+
+ /// 该阶段的抽取规则列表(可从多个池抽取)
+ public List drawRules = new List();
+
+ ///
+ /// 检查品质值是否属于该阶段
+ ///
+ public bool Contains(float quality)
+ {
+ return quality >= minQuality && quality < maxQuality;
+ }
+ }
+
+ ///
+ /// 分层特质奖励配置的 Def 类
+ /// 定义特质池和品质阶段规则,可被多个建筑共享
+ ///
+ public class TieredHediffRewardDef : Def
+ {
+ // === 特质池定义 ===
+ /// 所有特质池列表
+ public List hediffPools = new List();
+
+ // === 品质阶段定义 ===
+ /// 所有品质阶段列表
+ public List qualityTiers = new List();
+
+ // === 缓存 ===
+ private Dictionary poolCache;
+
+ ///
+ /// 配置错误检查
+ ///
+ public override IEnumerable 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();
+ 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}'";
+ }
+ }
+ }
+ }
+
+ ///
+ /// 解析引用后的初始化
+ ///
+ public override void ResolveReferences()
+ {
+ base.ResolveReferences();
+
+ // 构建池缓存
+ poolCache = new Dictionary();
+ 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));
+ }
+
+ ///
+ /// 根据池ID获取特质池
+ ///
+ public HediffPool GetPool(string poolId)
+ {
+ if (poolCache != null && poolCache.TryGetValue(poolId, out var pool))
+ return pool;
+
+ return hediffPools?.Find(p => p.poolId == poolId);
+ }
+
+ ///
+ /// 根据品质百分比获取对应阶段
+ ///
+ 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;
+ }
+
+ ///
+ /// 根据品质抽取 Hediff 奖励
+ ///
+ /// 品质值 (0-1)
+ /// 抽取的 Hediff 列表
+ public List DrawRewardsForQuality(float quality)
+ {
+ var result = new List();
+ 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;
+ }
+
+ ///
+ /// 获取品质阶段的描述文本
+ ///
+ public string GetTierDescription(float quality)
+ {
+ var tier = GetTierForQuality(quality);
+ if (tier == null)
+ return null;
+
+ return tier.tierLabel ?? $"阶段 {tier.tier}";
+ }
+
+ ///
+ /// 获取品质阶段的消息
+ ///
+ public string GetTierMessage(float quality)
+ {
+ var tier = GetTierForQuality(quality);
+ if (tier == null || string.IsNullOrEmpty(tier.messageKey))
+ return null;
+
+ return tier.messageKey.Translate();
+ }
+ }
+}
diff --git a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Building_Ootheca.cs b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Building_Ootheca.cs
index 05adacb..e6c472e 100644
--- a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Building_Ootheca.cs
+++ b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/Building_Ootheca.cs
@@ -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 rewardHediffs = config.GetRewardHediffs(qualityPercent);
+ // 使用新的分层奖励系统(优先)或回退到旧系统
+ List 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);
}
}
diff --git a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/CompProperties_IncubatorData.cs b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/CompProperties_IncubatorData.cs
index a887979..0028688 100644
--- a/Source/ArachnaeSwarm/Buildings/Building_Ootheca/CompProperties_IncubatorData.cs
+++ b/Source/ArachnaeSwarm/Buildings/Building_Ootheca/CompProperties_IncubatorData.cs
@@ -247,7 +247,10 @@ namespace ArachnaeSwarm
public string menuTitle = "IncubatorMenuTitle"; // 菜单标题翻译键
public string defaultIconPath = "UI/Commands/Default";
- // === 新增:全局Hediff奖励(所有配置共享)===
+ // === 新增:分层奖励Def引用(推荐使用)===
+ public TieredHediffRewardDef rewardDef;
+
+ // === 旧版:全局Hediff奖励(保留向后兼容)===
public List globalExtraHediffs = new List();
public List globalHediffRewards = new List();
@@ -336,6 +339,9 @@ namespace ArachnaeSwarm
// 公开获取孵化配置列表的方法
public List IncubationConfigs => Props?.incubationConfigs ?? new List();
+ // 获取奖励 Def(新系统)
+ public TieredHediffRewardDef RewardDef => Props?.rewardDef;
+
// 获取当前选择的配置
public IncubationConfig SelectedConfig
{
@@ -493,5 +499,73 @@ namespace ArachnaeSwarm
return builder.ToString().TrimEndNewlines();
}
+
+ // === 新增:使用分层系统抽取奖励 ===
+
+ ///
+ /// 根据品质抽取 Hediff 奖励(优先使用新的分层系统)
+ ///
+ /// 品质值 (0-1.5,支持150%上限)
+ /// 抽取的 Hediff 列表
+ public List DrawRewardsForQuality(float quality)
+ {
+ // 优先使用新的分层奖励系统
+ if (RewardDef != null)
+ {
+ return RewardDef.DrawRewardsForQuality(quality);
+ }
+
+ // 回退到旧系统
+ var config = SelectedConfig;
+ if (config != null)
+ {
+ return config.GetRewardHediffs(quality);
+ }
+
+ return new List();
+ }
+
+ ///
+ /// 获取品质对应的阶段信息(仅新系统可用)
+ ///
+ public QualityTier GetTierForQuality(float quality)
+ {
+ return RewardDef?.GetTierForQuality(quality);
+ }
+
+ ///
+ /// 获取奖励系统的描述文本
+ ///
+ 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();
+ }
}
}