diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll index 945b1d3..5cfb952 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/AbilityDefs/ARA_Psy_Abilities.xml b/1.6/1.6/Defs/AbilityDefs/ARA_Psy_Abilities.xml index 37a25f8..f89ea50 100644 --- a/1.6/1.6/Defs/AbilityDefs/ARA_Psy_Abilities.xml +++ b/1.6/1.6/Defs/AbilityDefs/ARA_Psy_Abilities.xml @@ -1,5 +1,161 @@ + + ARA_Neurotyrant_Upgrade + + 灵吸种以 + ArachnaeSwarm/UI/Abilities/ARA_PsychicBrainburn + 210 + false + false + 1 + true + false + + Verb_CastAbility + 0 + 0 + + true + + + +
  • + + +
  • + DD_Lantern_Shield_Adv_Wider + 1 + + DivineDiurganate/UI/Abilities/DD_Lantern_Shield_Adv_Wider + (1, 1, 1, 1) + 1 + (1, 1, 1, 0) +
  • +
  • + DD_Lantern_Shield_Adv_Longer + 1 + + DivineDiurganate/UI/Abilities/DD_Lantern_Shield_Adv_Longer + (1, 1, 1, 1) + 1 + (1, 1, 1, 0) +
  • +
  • + DD_Lantern_Shield_Adv_Extrabuff + 1 + + DivineDiurganate/UI/Abilities/DD_Lantern_Shield_Adv_Extrabuff + (1, 1, 1, 1) + 1 + (1, 1, 1, 0) +
  • + + + 3 + true + false + DD_MyCustomGacha_Title + true + true + DD_Upgrade_Lantern_Selected + + + (0.1, 0.1, 0.12, 1) + (0.2, 0.2, 0.25, 1) + (0.3, 0.3, 0.35, 1) + (0.9, 0.8, 0.5, 1) + +
    +
    + + + ARA_Neurotyrant_Harvest + + 灵吸种抽干目标的智识,转化为进化点点数。 + ArachnaeSwarm/UI/Abilities/ARA_Fighter_Invisibility_Execution + 30 + true + false + true + Mote_HoraxSmallSpellWarmup + HoraxianAbilityCasting + AnomalyAbilityWarmup + CastAbilityOnThingMelee + true + + Verb_CastAbilityTouch + false + -1 + 10 + + false + false + false + + + +
  • + + 50 + 50 + 200 + 1.0 + false + + 50 + false + + + true + true + true + + + 9999 + Burn + + true + true + 1 + Burn + true + + + + TraumaSavant + Anesthetic + true + ARA_SwarmSpell_ResearchHarvest_Message + true +
  • +
  • + + + 1 + 2 + + true + Psychic Load Cost + true + + + + + + true + 99999 + ARA_SwarmSpell_Overdrive + true +
  • +
    +
    + ARA_Neurotyrant_PsychicBrainburn diff --git a/1.6/1.6/Defs/ResearchProjectDefs/ARA_ResearchProjects.xml b/1.6/1.6/Defs/ResearchProjectDefs/ARA_ResearchProjects.xml index 4a45731..d0e20b5 100644 --- a/1.6/1.6/Defs/ResearchProjectDefs/ARA_ResearchProjects.xml +++ b/1.6/1.6/Defs/ResearchProjectDefs/ARA_ResearchProjects.xml @@ -9,7 +9,7 @@ Medieval ARA_ResearchTab - 1 + 999 0 2500 ARA_InteractiveEggSac_Techprint diff --git a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/ArachnaeSwarm_Keys.xml b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/ArachnaeSwarm_Keys.xml index 39b5ec2..f886609 100644 --- a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/ArachnaeSwarm_Keys.xml +++ b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/ArachnaeSwarm_Keys.xml @@ -135,4 +135,7 @@ 区域伤害关闭 将{0}只{1}加入辅虫孵化序列 + + {0} 从 {1} 身上收割了 {2} 虫群进化点 + {0} 吸取了 {1} 的精华,获得了 {2} 进化点 \ No newline at end of file diff --git a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/GizmoLabels.xml b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/GizmoLabels.xml index 67464cd..8b510f9 100644 --- a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/GizmoLabels.xml +++ b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/GizmoLabels.xml @@ -21,39 +21,39 @@ Spell - 虫群研究点 + 虫群进化点 储存: {0} / {1} - 虫群研究点label - 虫群研究点text + 虫群进化点 + 虫群进化点是独属于阿拉克涅灵吸种的特殊资源,灵吸种可以通过吞噬失去行动能力的俘虏以获取进化点,并将其投入至个人能力的升级或研究虫群的特殊科技。 - 灵能负荷 + 神经束负荷 负荷量: {0} / {1} 术法等级 目前的等级: {0} 灵能负荷最大值: 10 × {0} (术法等级) - 警告: 高灵能负荷! - 警告: 灵能负荷逼近极限! - 灵能负荷label - 灵能负荷text + 警告: 高神经束负荷! + 警告: 神经束负荷逼近极限! + 神经束负荷 + 神经束负荷是评估于阿拉克涅灵吸种使用虫群灵能法术导致的神经束负载程度——作为移动的法术炮台,灵吸种可以近乎无限地释放各种虫群灵能法术,代价就是有可能因此烧毁自己的大脑,必须在负载过大时将其作为心灵熵排出。 - 虫群术法label - 虫群术法text + 虫群灵能法术 + 虫群灵能法术 将鼠标放在指示条以进一步查看详细信息 - {0} 的虫群术法系统不可用 + {0} 的虫群灵能法术系统不可用 - [超载] 虫群术法系统 + [超载] 虫群灵能法术 {0}/{1} (+{2}) - 灵能负载 [超载] - 警告: 灵能负载超过容量! - 警告: 单位处于超载状态,冷却系统已锁定! + 神经束负荷 [超载] + 警告: 神经束负荷超过容量! + 警告: 单位处于超载状态,无法自行冷却! {0}s - 冷却系统 + 神经束冷却 剩余时间: {0}秒 - 冷却结束后,每2秒减少1点负载 - 冷却结束后将自动减少负载 + 冷却结束后,每2秒减少1点负荷 + 冷却结束后将自动减少神经束负荷 \ No newline at end of file diff --git a/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/.suo b/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/.suo index 7d6e919..d88f388 100644 Binary files a/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/.suo and b/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/.suo differ diff --git a/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/DocumentLayout.json b/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/DocumentLayout.json index 24c2a2e..ee58c26 100644 --- a/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/DocumentLayout.json +++ b/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/DocumentLayout.json @@ -3,12 +3,20 @@ "WorkspaceRootPath": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\", "Documents": [ { - "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\pawn_comps\\ara_swarmspellholder\\gizmo_swarmspellstatus.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:pawn_comps\\ara_swarmspellholder\\gizmo_swarmspellstatus.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\abilities\\ara_psychicresearchharvest\\compabilityeffect_psychicresearchharvest.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_psychicresearchharvest\\compabilityeffect_psychicresearchharvest.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, { - "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\powerarmor\\ara_powerarmor.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:powerarmor\\ara_powerarmor.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\abilities\\ara_psychicresearchharvest\\compproperties_abilitypsychicresearchharvest.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_psychicresearchharvest\\compproperties_abilitypsychicresearchharvest.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\pawn_comps\\ara_fighter_invisible\\compfighterinvisible.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:pawn_comps\\ara_fighter_invisible\\compfighterinvisible.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\pawn_comps\\ara_swarmspellholder\\gizmo_swarmspellstatus.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:pawn_comps\\ara_swarmspellholder\\gizmo_swarmspellstatus.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, { "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\pawn_comps\\ara_swarmspellholder\\comp_swarmspellholder.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", @@ -19,20 +27,36 @@ "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:pawn_comps\\ara_swarmspellholder\\swarmspellutility.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, { - "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\pawncapacityworker\\pawncapacityworker_psychicstange.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:pawncapacityworker\\pawncapacityworker_psychicstange.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\abilities\\ara_psychicloadcost\\compproperties_abilitypsychicloadcost.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_psychicloadcost\\compproperties_abilitypsychicloadcost.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, { - "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\ara_defof.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:ara_defof.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\abilities\\ara_hediffgacha\\compabilityeffect_hediffgacha.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_hediffgacha\\compabilityeffect_hediffgacha.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\abilities\\ara_hediffrestriction\\compabilityeffect_hediffrestriction.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_hediffrestriction\\compabilityeffect_hediffrestriction.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\abilities\\ara_hediffgacha\\window_hediffselection.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_hediffgacha\\window_hediffselection.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, { "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\abilities\\ara_psychicloadcost\\compabilityeffect_psychicloadcost.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_psychicloadcost\\compabilityeffect_psychicloadcost.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, { - "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\abilities\\ara_psychicloadcost\\compproperties_abilitypsychicloadcost.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:abilities\\ara_psychicloadcost\\compproperties_abilitypsychicloadcost.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\powerarmor\\ara_powerarmor.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:powerarmor\\ara_powerarmor.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|d:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\pawncapacityworker\\pawncapacityworker_psychicstange.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:pawncapacityworker\\pawncapacityworker_psychicstange.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\ara_defof.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:ara_defof.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, { "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\abilities\\psychicbrainburn\\compabilityeffect_psychicbrainburn.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", @@ -50,7 +74,7 @@ "DocumentGroups": [ { "DockedWidth": 200, - "SelectedChildIndex": 3, + "SelectedChildIndex": 2, "Children": [ { "$type": "Bookmark", @@ -59,6 +83,149 @@ { "$type": "Document", "DocumentIndex": 1, + "Title": "CompProperties_AbilityPsychicResearchHarvest.cs", + "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_PsychicResearchHarvest\\CompProperties_AbilityPsychicResearchHarvest.cs", + "RelativeDocumentMoniker": "Abilities\\ARA_PsychicResearchHarvest\\CompProperties_AbilityPsychicResearchHarvest.cs", + "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_PsychicResearchHarvest\\CompProperties_AbilityPsychicResearchHarvest.cs", + "RelativeToolTip": "Abilities\\ARA_PsychicResearchHarvest\\CompProperties_AbilityPsychicResearchHarvest.cs", + "ViewState": "AgIAAAoAAAAAAAAAAAArwHsAAAAVAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-02-04T03:35:18.266Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 0, + "Title": "CompAbilityEffect_PsychicResearchHarvest.cs", + "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_PsychicResearchHarvest\\CompAbilityEffect_PsychicResearchHarvest.cs", + "RelativeDocumentMoniker": "Abilities\\ARA_PsychicResearchHarvest\\CompAbilityEffect_PsychicResearchHarvest.cs", + "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_PsychicResearchHarvest\\CompAbilityEffect_PsychicResearchHarvest.cs", + "RelativeToolTip": "Abilities\\ARA_PsychicResearchHarvest\\CompAbilityEffect_PsychicResearchHarvest.cs", + "ViewState": "AgIAAEwBAAAAAAAAAAAAAHABAAAIAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-02-04T03:35:17.441Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 2, + "Title": "CompFighterInvisible.cs", + "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_Fighter_Invisible\\CompFighterInvisible.cs", + "RelativeDocumentMoniker": "Pawn_Comps\\ARA_Fighter_Invisible\\CompFighterInvisible.cs", + "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_Fighter_Invisible\\CompFighterInvisible.cs", + "RelativeToolTip": "Pawn_Comps\\ARA_Fighter_Invisible\\CompFighterInvisible.cs", + "ViewState": "AgIAACsAAAAAAAAAAAAgwC4AAAARAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-02-04T03:24:18.669Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 7, + "Title": "CompAbilityEffect_HediffGacha.cs", + "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_HediffGacha\\CompAbilityEffect_HediffGacha.cs", + "RelativeDocumentMoniker": "Abilities\\ARA_HediffGacha\\CompAbilityEffect_HediffGacha.cs", + "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_HediffGacha\\CompAbilityEffect_HediffGacha.cs", + "RelativeToolTip": "Abilities\\ARA_HediffGacha\\CompAbilityEffect_HediffGacha.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAA0AAAAuAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-02-04T02:49:20.179Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 6, + "Title": "CompProperties_AbilityPsychicLoadCost.cs", + "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_PsychicLoadCost\\CompProperties_AbilityPsychicLoadCost.cs", + "RelativeDocumentMoniker": "Abilities\\ARA_PsychicLoadCost\\CompProperties_AbilityPsychicLoadCost.cs", + "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_PsychicLoadCost\\CompProperties_AbilityPsychicLoadCost.cs", + "RelativeToolTip": "Abilities\\ARA_PsychicLoadCost\\CompProperties_AbilityPsychicLoadCost.cs", + "ViewState": "AgIAAAsAAAAAAAAAAADwvyUAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-01-30T08:22:38.845Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 5, + "Title": "SwarmSpellUtility.cs", + "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_SwarmSpellHolder\\SwarmSpellUtility.cs", + "RelativeDocumentMoniker": "Pawn_Comps\\ARA_SwarmSpellHolder\\SwarmSpellUtility.cs", + "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_SwarmSpellHolder\\SwarmSpellUtility.cs", + "RelativeToolTip": "Pawn_Comps\\ARA_SwarmSpellHolder\\SwarmSpellUtility.cs", + "ViewState": "AgIAANEAAAAAAAAAAAAqwPMAAAANAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-01-30T07:25:10.449Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 4, + "Title": "Comp_SwarmSpellHolder.cs", + "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_SwarmSpellHolder\\Comp_SwarmSpellHolder.cs", + "RelativeDocumentMoniker": "Pawn_Comps\\ARA_SwarmSpellHolder\\Comp_SwarmSpellHolder.cs", + "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_SwarmSpellHolder\\Comp_SwarmSpellHolder.cs", + "RelativeToolTip": "Pawn_Comps\\ARA_SwarmSpellHolder\\Comp_SwarmSpellHolder.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAAACkAAAAkAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-01-30T07:11:59.797Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 3, + "Title": "Gizmo_SwarmSpellStatus.cs", + "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_SwarmSpellHolder\\Gizmo_SwarmSpellStatus.cs", + "RelativeDocumentMoniker": "Pawn_Comps\\ARA_SwarmSpellHolder\\Gizmo_SwarmSpellStatus.cs", + "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_SwarmSpellHolder\\Gizmo_SwarmSpellStatus.cs", + "RelativeToolTip": "Pawn_Comps\\ARA_SwarmSpellHolder\\Gizmo_SwarmSpellStatus.cs", + "ViewState": "AgIAAIAAAAAAAAAAAAAIwIsAAAATAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-01-30T08:20:07.463Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 8, + "Title": "CompAbilityEffect_HediffRestriction.cs", + "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_HediffRestriction\\CompAbilityEffect_HediffRestriction.cs", + "RelativeDocumentMoniker": "Abilities\\ARA_HediffRestriction\\CompAbilityEffect_HediffRestriction.cs", + "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_HediffRestriction\\CompAbilityEffect_HediffRestriction.cs", + "RelativeToolTip": "Abilities\\ARA_HediffRestriction\\CompAbilityEffect_HediffRestriction.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAMAAAAXAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-02-04T02:49:22.868Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 9, + "Title": "Window_HediffSelection.cs", + "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_HediffGacha\\Window_HediffSelection.cs", + "RelativeDocumentMoniker": "Abilities\\ARA_HediffGacha\\Window_HediffSelection.cs", + "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_HediffGacha\\Window_HediffSelection.cs", + "RelativeToolTip": "Abilities\\ARA_HediffGacha\\Window_HediffSelection.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAsAAAAVAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-02-04T02:49:27.428Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 10, + "Title": "CompAbilityEffect_PsychicLoadCost.cs", + "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_PsychicLoadCost\\CompAbilityEffect_PsychicLoadCost.cs", + "RelativeDocumentMoniker": "Abilities\\ARA_PsychicLoadCost\\CompAbilityEffect_PsychicLoadCost.cs", + "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_PsychicLoadCost\\CompAbilityEffect_PsychicLoadCost.cs", + "RelativeToolTip": "Abilities\\ARA_PsychicLoadCost\\CompAbilityEffect_PsychicLoadCost.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAFkAAABWAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-01-30T08:16:09.317Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 11, "Title": "ARA_PowerArmor.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\PowerArmor\\ARA_PowerArmor.cs", "RelativeDocumentMoniker": "PowerArmor\\ARA_PowerArmor.cs", @@ -71,7 +238,7 @@ }, { "$type": "Document", - "DocumentIndex": 4, + "DocumentIndex": 12, "Title": "PawnCapacityWorker_PsychicStange.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\PawnCapacityWorker\\PawnCapacityWorker_PsychicStange.cs", "RelativeDocumentMoniker": "PawnCapacityWorker\\PawnCapacityWorker_PsychicStange.cs", @@ -84,20 +251,7 @@ }, { "$type": "Document", - "DocumentIndex": 0, - "Title": "Gizmo_SwarmSpellStatus.cs", - "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_SwarmSpellHolder\\Gizmo_SwarmSpellStatus.cs", - "RelativeDocumentMoniker": "Pawn_Comps\\ARA_SwarmSpellHolder\\Gizmo_SwarmSpellStatus.cs", - "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_SwarmSpellHolder\\Gizmo_SwarmSpellStatus.cs", - "RelativeToolTip": "Pawn_Comps\\ARA_SwarmSpellHolder\\Gizmo_SwarmSpellStatus.cs", - "ViewState": "AgIAABQAAAAAAAAAAAAAAB4AAABDAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-01-30T08:20:07.463Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 8, + "DocumentIndex": 14, "Title": "CompAbilityEffect_PsychicBrainburn.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\PsychicBrainburn\\CompAbilityEffect_PsychicBrainburn.cs", "RelativeDocumentMoniker": "Abilities\\PsychicBrainburn\\CompAbilityEffect_PsychicBrainburn.cs", @@ -109,7 +263,7 @@ }, { "$type": "Document", - "DocumentIndex": 5, + "DocumentIndex": 13, "Title": "ARA_DefOf.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\ARA_DefOf.cs", "RelativeDocumentMoniker": "ARA_DefOf.cs", @@ -121,57 +275,7 @@ }, { "$type": "Document", - "DocumentIndex": 3, - "Title": "SwarmSpellUtility.cs", - "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_SwarmSpellHolder\\SwarmSpellUtility.cs", - "RelativeDocumentMoniker": "Pawn_Comps\\ARA_SwarmSpellHolder\\SwarmSpellUtility.cs", - "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_SwarmSpellHolder\\SwarmSpellUtility.cs", - "RelativeToolTip": "Pawn_Comps\\ARA_SwarmSpellHolder\\SwarmSpellUtility.cs", - "ViewState": "AgIAAPMAAAAAAAAAAAAAAPMAAAANAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-01-30T07:25:10.449Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 2, - "Title": "Comp_SwarmSpellHolder.cs", - "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_SwarmSpellHolder\\Comp_SwarmSpellHolder.cs", - "RelativeDocumentMoniker": "Pawn_Comps\\ARA_SwarmSpellHolder\\Comp_SwarmSpellHolder.cs", - "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_SwarmSpellHolder\\Comp_SwarmSpellHolder.cs", - "RelativeToolTip": "Pawn_Comps\\ARA_SwarmSpellHolder\\Comp_SwarmSpellHolder.cs", - "ViewState": "AgIAANUCAAAAAAAAAAAWwCgDAAArAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-01-30T07:11:59.797Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 6, - "Title": "CompAbilityEffect_PsychicLoadCost.cs", - "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_PsychicLoadCost\\CompAbilityEffect_PsychicLoadCost.cs", - "RelativeDocumentMoniker": "Abilities\\ARA_PsychicLoadCost\\CompAbilityEffect_PsychicLoadCost.cs", - "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_PsychicLoadCost\\CompAbilityEffect_PsychicLoadCost.cs", - "RelativeToolTip": "Abilities\\ARA_PsychicLoadCost\\CompAbilityEffect_PsychicLoadCost.cs", - "ViewState": "AgIAAEgAAAAAAAAAAAApwFkAAABWAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-01-30T08:16:09.317Z" - }, - { - "$type": "Document", - "DocumentIndex": 7, - "Title": "CompProperties_AbilityPsychicLoadCost.cs", - "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_PsychicLoadCost\\CompProperties_AbilityPsychicLoadCost.cs", - "RelativeDocumentMoniker": "Abilities\\ARA_PsychicLoadCost\\CompProperties_AbilityPsychicLoadCost.cs", - "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_PsychicLoadCost\\CompProperties_AbilityPsychicLoadCost.cs", - "RelativeToolTip": "Abilities\\ARA_PsychicLoadCost\\CompProperties_AbilityPsychicLoadCost.cs", - "ViewState": "AgIAAAsAAAAAAAAAAADwvyUAAAAAAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-01-30T08:22:38.845Z" - }, - { - "$type": "Document", - "DocumentIndex": 9, + "DocumentIndex": 15, "Title": "CompAutoMechCarrier.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\CompAutoMechCarrier.cs", "RelativeDocumentMoniker": "Pawn_Comps\\ARA_AutoMechCarrier\\CompAutoMechCarrier.cs", diff --git a/Source/ArachnaeSwarm/Abilities/ARA_HediffGacha/CompAbilityEffect_HediffGacha.cs b/Source/ArachnaeSwarm/Abilities/ARA_HediffGacha/CompAbilityEffect_HediffGacha.cs new file mode 100644 index 0000000..08c7a6b --- /dev/null +++ b/Source/ArachnaeSwarm/Abilities/ARA_HediffGacha/CompAbilityEffect_HediffGacha.cs @@ -0,0 +1,354 @@ +using System.Collections.Generic; +using System.Linq; +using RimWorld; +using Verse; +using UnityEngine; + +namespace ArachnaeSwarm +{ + /// + /// Hediff抽卡技能效果组件 + /// 对目标释放后,从Hediff池中随机抽取指定数量的Hediff让玩家选择 + /// 选择完成后,目标获得选中的Hediff + /// + public class CompAbilityEffect_HediffGacha : CompAbilityEffect + { + // 缓存目标,用于窗口选择后的回调 + private Pawn cachedTarget; + + public new CompProperties_AbilityHediffGacha Props => + (CompProperties_AbilityHediffGacha)props; + + public override void Apply(LocalTargetInfo target, LocalTargetInfo dest) + { + base.Apply(target, dest); + + // 验证目标 + if (!target.IsValid || target.Pawn == null) + return; + + Pawn targetPawn = target.Pawn; + cachedTarget = targetPawn; + + // 从Hediff池中随机抽取(现在返回HediffPoolEntry列表) + List drawnEntries = DrawHediffsFromPool(Props.choiceCount); + + if (drawnEntries.NullOrEmpty()) + { + Log.Warning("[DivineDiurganate] HediffGacha: No valid hediffs drawn from pool!"); + return; + } + + // 打开选择窗口(传递HediffPoolEntry列表,而不是HediffDef列表) + Window_HediffSelection window = new Window_HediffSelection( + drawnEntries, + targetPawn, + OnHediffSelected, + Props.windowTitle, + Props.allowCancel + ); + + Find.WindowStack.Add(window); + } + + /// + /// 从Hediff池中随机抽取指定数量的Hediff条目 + /// + private List DrawHediffsFromPool(int count) + { + if (Props.hediffPool.NullOrEmpty()) + { + Log.Error("[DivineDiurganate] HediffGacha: hediffPool is empty!"); + return null; + } + + // 复制池子以便进行无重复抽取 + List availablePool = Props.hediffPool.ListFullCopy(); + List result = new List(); + + // 如果池子不足以抽取指定数量,则取池子的全部 + int actualCount = System.Math.Min(count, availablePool.Count); + + for (int i = 0; i < actualCount; i++) + { + if (availablePool.Count == 0) + break; + + // 根据权重随机选择 + HediffPoolEntry selected; + if (Props.useWeights) + { + selected = availablePool.RandomElementByWeight(e => e.weight); + } + else + { + selected = availablePool.RandomElement(); + } + + if (selected?.hediff != null) + { + result.Add(selected); + + // 从池子中移除已选择的,确保不重复 + if (!Props.allowDuplicates) + { + availablePool.Remove(selected); + } + } + } + + return result; + } + + /// + /// 玩家选择Hediff后的回调 + /// + private void OnHediffSelected(HediffDef selectedHediff) + { + if (selectedHediff == null || cachedTarget == null || cachedTarget.Dead) + { + Log.Warning("[DivineDiurganate] HediffGacha: Invalid selection or target is dead"); + return; + } + + // 为目标添加Hediff + ApplyHediffToTarget(cachedTarget, selectedHediff); + + // 播放特效(如果有) + if (Props.selectionFleck != null && cachedTarget.Map != null) + { + FleckMaker.Static(cachedTarget.Position, cachedTarget.Map, Props.selectionFleck); + } + + // 显示消息(如果配置启用) + if (Props.showSelectionMessage) + { + string message = Props.selectionMessageKey.NullOrEmpty() + ? "DD_HediffGacha_Selected".Translate(cachedTarget.LabelShortCap, selectedHediff.LabelCap) + : Props.selectionMessageKey.Translate(cachedTarget.LabelShortCap, selectedHediff.LabelCap); + + Messages.Message(message, cachedTarget, MessageTypeDefOf.PositiveEvent); + } + + // 清空缓存 + cachedTarget = null; + } + + /// + /// 将Hediff应用到目标 + /// + private void ApplyHediffToTarget(Pawn target, HediffDef hediffDef) + { + if (target == null || hediffDef == null) + return; + + // 如果已有该Hediff且设置为替换,则先移除 + if (Props.replaceExisting) + { + Hediff existingHediff = target.health.hediffSet.GetFirstHediffOfDef(hediffDef); + if (existingHediff != null) + { + target.health.RemoveHediff(existingHediff); + } + } + + // 创建新的Hediff + BodyPartRecord targetPart = null; + if (Props.onlyBrain) + { + targetPart = target.health.hediffSet.GetBrain(); + } + + Hediff hediff = HediffMaker.MakeHediff(hediffDef, target, targetPart); + + // 设置严重度(如果有指定) + if (Props.initialSeverity >= 0f) + { + hediff.Severity = Props.initialSeverity; + } + + // 设置持续时间(如果Hediff支持) + HediffComp_Disappears disappearsComp = hediff.TryGetComp(); + if (disappearsComp != null && Props.durationSeconds > 0) + { + disappearsComp.ticksToDisappear = (int)(Props.durationSeconds * 60f); + } + + // 添加Hediff + target.health.AddHediff(hediff); + } + + public override bool Valid(LocalTargetInfo target, bool throwMessages = false) + { + if (!base.Valid(target, throwMessages)) + return false; + + // 验证目标是Pawn + if (target.Pawn == null) + { + if (throwMessages) + Messages.Message("DD_HediffGacha_NeedPawnTarget".Translate(), + MessageTypeDefOf.RejectInput); + return false; + } + + // 验证Hediff池不为空 + if (Props.hediffPool.NullOrEmpty()) + { + if (throwMessages) + Messages.Message("DD_HediffGacha_EmptyPool".Translate(), + MessageTypeDefOf.RejectInput); + return false; + } + + return true; + } + + public override bool CanApplyOn(LocalTargetInfo target, LocalTargetInfo dest) + { + return target.Pawn != null && !Props.hediffPool.NullOrEmpty(); + } + } + + /// + /// Hediff池条目 - 包含Hediff定义和权重 + /// + public class HediffPoolEntry + { + /// + /// Hediff定义 + /// + public HediffDef hediff; + + /// + /// 抽取权重(仅在useWeights为true时生效) + /// + public float weight = 1f; + + /// + /// 可选的描述覆盖(用于在选择界面显示自定义描述) + /// + public string descriptionOverride; + + /// + /// 自定义图标路径(可选的,如果不设置则使用Hediff默认图标) + /// + public string iconPath; + + /// + /// 自定义图标颜色(可选的,如果不设置则使用默认白色) + /// + public Color? iconColor; + + /// + /// 图标缩放(默认1.0) + /// + public float iconScale = 1.0f; + + /// + /// 图标是否带有背景(默认true) + /// + public bool iconHasBackground = true; + + /// + /// 图标背景颜色(可选的) + /// + public Color? iconBackgroundColor; + } + + /// + /// Hediff抽卡技能属性 + /// + public class CompProperties_AbilityHediffGacha : CompProperties_AbilityEffect + { + /// + /// Hediff池 - 可供抽取的Hediff列表 + /// + public List hediffPool; + + /// + /// 每次抽取的选项数量(默认3个,即三选一) + /// + public int choiceCount = 3; + + /// + /// 是否使用权重进行随机抽取 + /// + public bool useWeights = true; + + /// + /// 是否允许抽取重复的Hediff + /// + public bool allowDuplicates = false; + + /// + /// 窗口标题翻译键 + /// + public string windowTitle = "DD_HediffGacha_Title"; + + /// + /// 是否允许取消选择 + /// + public bool allowCancel = false; + + /// + /// 选择后的特效 + /// + public FleckDef selectionFleck; + + /// + /// 是否显示选择消息 + /// + public bool showSelectionMessage = true; + + /// + /// 选择消息的翻译键(可选,默认使用DD_HediffGacha_Selected) + /// + public string selectionMessageKey; + + /// + /// Hediff初始严重度(负数表示使用默认值) + /// + public float initialSeverity = -1f; + + /// + /// Hediff持续时间(秒,0表示永久) + /// + public float durationSeconds = 0f; + + /// + /// 是否只应用到大脑 + /// + public bool onlyBrain = false; + + /// + /// 是否替换已存在的相同Hediff + /// + public bool replaceExisting = true; + + /// + /// 卡片默认背景颜色(用于没有自定义图标背景的卡片) + /// + public Color cardDefaultBackground = new Color(0.15f, 0.15f, 0.18f); + + /// + /// 卡片悬停背景颜色 + /// + public Color cardHoverBackground = new Color(0.25f, 0.25f, 0.3f); + + /// + /// 卡片默认边框颜色 + /// + public Color cardDefaultBorder = new Color(0.4f, 0.4f, 0.4f); + + /// + /// 卡片悬停边框颜色 + /// + public Color cardHoverBorder = new Color(0.8f, 0.7f, 0.4f); + + public CompProperties_AbilityHediffGacha() + { + compClass = typeof(CompAbilityEffect_HediffGacha); + } + } +} diff --git a/Source/ArachnaeSwarm/Abilities/ARA_HediffGacha/Window_HediffSelection.cs b/Source/ArachnaeSwarm/Abilities/ARA_HediffGacha/Window_HediffSelection.cs new file mode 100644 index 0000000..08796c4 --- /dev/null +++ b/Source/ArachnaeSwarm/Abilities/ARA_HediffGacha/Window_HediffSelection.cs @@ -0,0 +1,425 @@ +using System; +using System.Collections.Generic; +using RimWorld; +using UnityEngine; +using Verse; +using Verse.Sound; + +namespace ArachnaeSwarm +{ + /// + /// Hediff选择窗口 - 展示多个Hediff选项供玩家选择 + /// 类似卡牌游戏的选择界面风格 + /// + public class Window_HediffSelection : Window + { + // 选项列表(现在使用HediffPoolEntry) + private readonly List hediffEntries; + + // 目标Pawn(用于显示) + private readonly Pawn targetPawn; + + // 选择回调 + private readonly Action onSelect; + + // 窗口标题 + private readonly string titleKey; + + // 是否允许取消 + private readonly bool allowCancel; + + // 属性引用(用于获取卡片颜色配置) + private CompProperties_AbilityHediffGacha props; + + // 动画相关 + private float openAnimProgress = 0f; + private const float OpenAnimDuration = 0.3f; + + // 悬停的选项索引 + private int hoveredIndex = -1; + + // 图标缓存 + private Dictionary iconCache = new Dictionary(); + + // 卡片尺寸和布局 + private const float CardWidth = 200f; + private const float CardHeight = 280f; + private const float CardSpacing = 20f; + private const float TitleHeight = 50f; + private const float BottomPadding = 60f; + + public override Vector2 InitialSize + { + get + { + int count = hediffEntries != null ? hediffEntries.Count : 0; + float totalWidth = count * CardWidth + (count - 1) * CardSpacing + 60f; + float totalHeight = TitleHeight + CardHeight + BottomPadding + 40f; + return new Vector2(Mathf.Max(totalWidth, 500f), totalHeight); + } + } + + public Window_HediffSelection( + List entries, + Pawn target, + Action selectCallback, + string title = "DD_HediffGacha_Title", + bool canCancel = false, + CompProperties_AbilityHediffGacha properties = null) + { + hediffEntries = entries ?? new List(); + targetPawn = target; + onSelect = selectCallback; + titleKey = title; + allowCancel = canCancel; + props = properties; + + // 窗口设置 + doCloseButton = false; + doCloseX = allowCancel; + absorbInputAroundWindow = true; + closeOnClickedOutside = false; + closeOnCancel = allowCancel; + forcePause = true; + layer = WindowLayer.Dialog; + + // 打开动画 + openAnimProgress = 0f; + } + + public override void DoWindowContents(Rect inRect) + { + // 更新动画 + if (openAnimProgress < 1f) + { + openAnimProgress += Time.deltaTime / OpenAnimDuration; + openAnimProgress = Mathf.Clamp01(openAnimProgress); + } + + // 绘制标题 + DrawTitle(inRect); + + // 绘制目标信息 + DrawTargetInfo(inRect); + + // 绘制Hediff卡片 + DrawHediffCards(inRect); + + // 绘制底部提示 + DrawBottomHint(inRect); + } + + private void DrawTitle(Rect inRect) + { + Text.Font = GameFont.Medium; + Text.Anchor = TextAnchor.MiddleCenter; + + string title = titleKey.Translate(); + Rect titleRect = new Rect(0f, 5f, inRect.width, 35f); + + // 标题淡入效果 + GUI.color = new Color(1f, 1f, 1f, openAnimProgress); + Widgets.Label(titleRect, title); + GUI.color = Color.white; + + Text.Anchor = TextAnchor.UpperLeft; + Text.Font = GameFont.Small; + } + + private void DrawTargetInfo(Rect inRect) + { + if (targetPawn == null) + return; + + Text.Font = GameFont.Small; + Text.Anchor = TextAnchor.MiddleCenter; + + string targetInfo = "DD_HediffGacha_TargetInfo".Translate(targetPawn.LabelShortCap); + Rect infoRect = new Rect(0f, 38f, inRect.width, 20f); + + GUI.color = new Color(0.8f, 0.8f, 0.8f, openAnimProgress); + Widgets.Label(infoRect, targetInfo); + GUI.color = Color.white; + + Text.Anchor = TextAnchor.UpperLeft; + } + + private void DrawHediffCards(Rect inRect) + { + if (hediffEntries.NullOrEmpty()) + return; + + int count = hediffEntries.Count; + float totalCardsWidth = count * CardWidth + (count - 1) * CardSpacing; + float startX = (inRect.width - totalCardsWidth) / 2f; + float cardY = TitleHeight + 15f; + + for (int i = 0; i < count; i++) + { + float cardX = startX + i * (CardWidth + CardSpacing); + + // 卡片动画偏移(从下方飞入) + float animDelay = i * 0.1f; + float cardAnimProgress = Mathf.Clamp01((openAnimProgress - animDelay) / (1f - animDelay)); + float yOffset = (1f - cardAnimProgress) * 50f; + + Rect cardRect = new Rect(cardX, cardY + yOffset, CardWidth, CardHeight); + + // 设置透明度 + GUI.color = new Color(1f, 1f, 1f, cardAnimProgress); + + DrawHediffCard(cardRect, hediffEntries[i], i); + + GUI.color = Color.white; + } + } + + private void DrawHediffCard(Rect rect, HediffPoolEntry entry, int index) + { + if (entry?.hediff == null) + return; + + bool isHovered = Mouse.IsOver(rect); + + // 悬停效果 + if (isHovered) + { + hoveredIndex = index; + rect = rect.ExpandedBy(5f); + } + else if (hoveredIndex == index) + { + hoveredIndex = -1; + } + + // 绘制卡片背景(使用自定义颜色或默认颜色) + Color bgColor; + if (entry.iconHasBackground && entry.iconBackgroundColor.HasValue) + { + bgColor = entry.iconBackgroundColor.Value; + } + else + { + bgColor = isHovered + ? (props != null ? props.cardHoverBackground : new Color(0.25f, 0.25f, 0.3f)) + : (props != null ? props.cardDefaultBackground : new Color(0.15f, 0.15f, 0.18f)); + } + + Widgets.DrawBoxSolid(rect, bgColor); + + // 绘制边框(使用自定义颜色或默认颜色) + Color borderColor = isHovered + ? (props != null ? props.cardHoverBorder : new Color(0.8f, 0.7f, 0.4f)) + : (props != null ? props.cardDefaultBorder : new Color(0.4f, 0.4f, 0.4f)); + + Widgets.DrawBox(rect, 2, Texture2D.whiteTexture); + GUI.color = borderColor; + Widgets.DrawBox(rect, 2); + GUI.color = Color.white; + + float padding = 10f; + float contentWidth = rect.width - padding * 2; + float currentY = rect.y + padding; + + // 绘制Hediff图标 + Rect iconRect = new Rect(rect.x + (rect.width - 64f) / 2f, currentY, 64f, 64f); + + // 应用图标缩放 + if (entry.iconScale != 1.0f && entry.iconScale > 0) + { + float scaledSize = 64f * entry.iconScale; + iconRect = new Rect( + rect.x + (rect.width - scaledSize) / 2f, + currentY, + scaledSize, + scaledSize + ); + } + + DrawHediffIcon(iconRect, entry); + currentY += (entry.iconScale != 1.0f ? 64f * entry.iconScale : 64f) + 10f; + + // 绘制Hediff名称 + Text.Font = GameFont.Medium; + Text.Anchor = TextAnchor.MiddleCenter; + + Rect nameRect = new Rect(rect.x + padding, currentY, contentWidth, 30f); + string hediffName = entry.hediff.LabelCap; + Widgets.Label(nameRect, hediffName); + currentY += 35f; + + // 绘制分隔线 + Widgets.DrawLineHorizontal(rect.x + padding, currentY, contentWidth); + currentY += 10f; + + // 绘制Hediff描述(优先使用自定义描述) + Text.Font = GameFont.Tiny; + Text.Anchor = TextAnchor.UpperCenter; + + float descHeight = CardHeight - (currentY - rect.y) - 50f; + Rect descRect = new Rect(rect.x + padding, currentY, contentWidth, descHeight); + + string description = !string.IsNullOrEmpty(entry.descriptionOverride) + ? entry.descriptionOverride + : entry.hediff.Description; + + if (description.Length > 200) + { + description = description.Substring(0, 197) + "..."; + } + + GUI.color = new Color(0.8f, 0.8f, 0.8f); + Widgets.Label(descRect, description); + GUI.color = Color.white; + currentY += descHeight + 5f; + + // 绘制选择按钮 + Text.Font = GameFont.Small; + Text.Anchor = TextAnchor.MiddleCenter; + + Rect buttonRect = new Rect(rect.x + padding + 10f, rect.yMax - 40f, contentWidth - 20f, 30f); + + if (Widgets.ButtonText(buttonRect, "DD_HediffGacha_Select".Translate())) + { + SoundDefOf.Click.PlayOneShotOnCamera(); + SelectHediff(entry.hediff); + } + + Text.Anchor = TextAnchor.UpperLeft; + Text.Font = GameFont.Small; + + // 悬停时显示完整工具提示 + if (isHovered) + { + string tooltip = entry.hediff.LabelCap + "\n\n" + + (!string.IsNullOrEmpty(entry.descriptionOverride) + ? entry.descriptionOverride + : entry.hediff.Description); + TooltipHandler.TipRegion(rect, tooltip); + } + } + + private void DrawHediffIcon(Rect rect, HediffPoolEntry entry) + { + if (entry == null || entry.hediff == null) + return; + + Texture2D icon = null; + + // 1. 首先尝试使用自定义图标路径 + if (!string.IsNullOrEmpty(entry.iconPath)) + { + // 检查缓存 + if (!iconCache.TryGetValue(entry.iconPath, out icon)) + { + icon = ContentFinder.Get(entry.iconPath, false); + if (icon != null) + { + iconCache[entry.iconPath] = icon; + } + } + } + + // 3. 如果还是没有,根据Hediff是好是坏选择不同的默认图标 + if (icon == null) + { + string iconPath = entry.hediff.isBad + ? "UI/Icons/Medical/Plague" + : "UI/Icons/Medical/BandageIcon"; + + if (!iconCache.TryGetValue(iconPath, out icon)) + { + icon = ContentFinder.Get(iconPath, false); + if (icon != null) + { + iconCache[iconPath] = icon; + } + } + } + + // 4. 如果还是没有,尝试其他备选图标 + if (icon == null) + { + string fallbackPath = "UI/Icons/Medical/Vaccinate"; + if (!iconCache.TryGetValue(fallbackPath, out icon)) + { + icon = ContentFinder.Get(fallbackPath, false); + if (icon != null) + { + iconCache[fallbackPath] = icon; + } + } + } + + // 绘制图标 + if (icon != null) + { + // 应用自定义颜色(如果有) + GUI.color = entry.iconColor.HasValue ? entry.iconColor.Value : Color.white; + GUI.DrawTexture(rect, icon); + GUI.color = Color.white; + } + else + { + // 绘制一个带颜色的占位符 + Color placeholderColor = entry.hediff.isBad + ? new Color(0.5f, 0.2f, 0.2f) + : new Color(0.2f, 0.5f, 0.3f); + + // 使用自定义颜色(如果有) + if (entry.iconColor.HasValue) + { + placeholderColor = entry.iconColor.Value; + } + + Widgets.DrawBoxSolid(rect, placeholderColor); + Text.Anchor = TextAnchor.MiddleCenter; + Text.Font = GameFont.Medium; + GUI.color = Color.white; + Widgets.Label(rect, entry.hediff.LabelCap.ToString().Substring(0, 1).ToUpper()); + Text.Anchor = TextAnchor.UpperLeft; + } + } + + private void DrawBottomHint(Rect inRect) + { + Text.Font = GameFont.Tiny; + Text.Anchor = TextAnchor.MiddleCenter; + GUI.color = new Color(0.6f, 0.6f, 0.6f, openAnimProgress); + + string hint = allowCancel + ? "DD_HediffGacha_HintWithCancel".Translate() + : "DD_HediffGacha_Hint".Translate(); + + Rect hintRect = new Rect(0f, inRect.height - 25f, inRect.width, 20f); + Widgets.Label(hintRect, hint); + + GUI.color = Color.white; + Text.Anchor = TextAnchor.UpperLeft; + Text.Font = GameFont.Small; + } + + private void SelectHediff(HediffDef hediff) + { + onSelect?.Invoke(hediff); + Close(); + } + + public override void OnCancelKeyPressed() + { + if (allowCancel) + { + onSelect?.Invoke(null); + base.OnCancelKeyPressed(); + } + // 如果不允许取消,则忽略ESC键 + } + + public override void PreClose() + { + base.PreClose(); + // 清理图标缓存 + iconCache.Clear(); + } + } +} diff --git a/Source/ArachnaeSwarm/Abilities/ARA_PsychicResearchHarvest/CompAbilityEffect_PsychicResearchHarvest.cs b/Source/ArachnaeSwarm/Abilities/ARA_PsychicResearchHarvest/CompAbilityEffect_PsychicResearchHarvest.cs new file mode 100644 index 0000000..4ac1355 --- /dev/null +++ b/Source/ArachnaeSwarm/Abilities/ARA_PsychicResearchHarvest/CompAbilityEffect_PsychicResearchHarvest.cs @@ -0,0 +1,453 @@ +using RimWorld; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine; +using Verse; + +namespace ArachnaeSwarm +{ + /// + /// 灵能科研点收割技能效果 + /// 从目标身上收割灵能科研点,并摧毁目标的意识来源器官 + /// + public class CompAbilityEffect_PsychicResearchHarvest : CompAbilityEffect + { + #region 属性 + public new CompProperties_AbilityPsychicResearchHarvest Props => + (CompProperties_AbilityPsychicResearchHarvest)props; + #endregion + + #region 应用效果 + public override void Apply(LocalTargetInfo target, LocalTargetInfo dest) + { + base.Apply(target, dest); + + Pawn caster = parent.pawn; + Pawn targetPawn = target.Pawn; + + if (caster == null || targetPawn == null || targetPawn.Dead || targetPawn.Downed) + { + Log.Warning("[虫群术法] 灵能科研点收割: 施法者或目标无效"); + return; + } + + // 获取施法者的术法持有组件 + Comp_SwarmSpellHolder spellHolder = caster.TryGetComp(); + if (spellHolder == null || !spellHolder.IsSystemInitialized) + { + Messages.Message("ARA_SwarmSpell_NoSpellHolder".Translate(caster.LabelShortCap), + MessageTypeDefOf.RejectInput); + return; + } + + // 计算应获得的科研点 + float researchPoints = CalculateResearchPoints(targetPawn); + + // 添加到施法者的科研点 + bool success = spellHolder.AddPsychicResearchPoints(researchPoints, "收割目标灵能"); + + // 摧毁目标的意识来源器官 + DestroyConsciousnessSourceParts(targetPawn); + + // 显示效果和消息 + ShowEffectsAndMessages(caster, targetPawn, researchPoints, success); + } + #endregion + + #region 计算科研点 + /// + /// 计算从目标身上可收割的灵能科研点 + /// + private float CalculateResearchPoints(Pawn targetPawn) + { + float baseAmount = Props.baseAmount; + float intelligenceMultiplier = Props.intelligenceMultiplier; + float consciousnessMultiplier = Props.consciousnessMultiplier; + + // 获取目标的智识(Intellectual)技能等级 + // 如果没有智识技能(比如动物),视为1 + float intelligenceValue = 1f; + if (targetPawn.skills != null) + { + SkillRecord intellectualSkill = targetPawn.skills.GetSkill(SkillDefOf.Intellectual); + if (intellectualSkill != null) + { + // 使用技能等级(0-20)作为智识值 + intelligenceValue = intellectualSkill.Level; + if (intelligenceValue <= 0) intelligenceValue = 1f; + } + } + + // 获取目标的意识(Consciousness)能力值 + float consciousnessValue = targetPawn.health.capacities.GetLevel(PawnCapacityDefOf.Consciousness); + if (consciousnessValue < 0) consciousnessValue = 0; + + // 计算公式:基础数 + (智识 * 智识倍率) + (意识 * 意识倍率) + float researchPoints = baseAmount + + (intelligenceValue * intelligenceMultiplier) + + (consciousnessValue * consciousnessMultiplier); + + // 应用乘数 + researchPoints *= Props.overallMultiplier; + + // 应用随机范围(如果有) + if (Props.useRandomRange) + { + researchPoints = researchPoints * Props.randomRange.RandomInRange; + } + + // 确保最小值 + researchPoints = Mathf.Max(researchPoints, Props.minimumAmount); + + return researchPoints; + } + + /// + /// 获取计算过程的描述(用于工具提示) + /// + private string GetCalculationDescription(Pawn targetPawn) + { + StringBuilder sb = new StringBuilder(); + + // 获取智识技能等级 + float intelligenceValue = 1f; + if (targetPawn.skills != null) + { + SkillRecord intellectualSkill = targetPawn.skills.GetSkill(SkillDefOf.Intellectual); + if (intellectualSkill != null) + { + intelligenceValue = intellectualSkill.Level; + if (intelligenceValue <= 0) intelligenceValue = 1f; + } + } + + // 获取意识能力值 + float consciousnessValue = targetPawn.health.capacities.GetLevel(PawnCapacityDefOf.Consciousness); + if (consciousnessValue < 0) consciousnessValue = 0; + + sb.AppendLine("计算公式:"); + sb.AppendLine($"基础值: {Props.baseAmount:F1}"); + sb.AppendLine($"智识技能等级({intelligenceValue:F1}) × 智识倍率({Props.intelligenceMultiplier:F1}) = {intelligenceValue * Props.intelligenceMultiplier:F1}"); + sb.AppendLine($"意识能力值({consciousnessValue:P0}) × 意识倍率({Props.consciousnessMultiplier:F1}) = {consciousnessValue * Props.consciousnessMultiplier:F1}"); + sb.AppendLine($"总计: {Props.baseAmount + (intelligenceValue * Props.intelligenceMultiplier) + (consciousnessValue * Props.consciousnessMultiplier):F1}"); + + if (Props.useRandomRange) + { + sb.AppendLine($"随机范围: {Props.randomRange.min:F1} - {Props.randomRange.max:F1}"); + } + + if (Props.overallMultiplier != 1f) + { + sb.AppendLine($"全局乘数: ×{Props.overallMultiplier:F1}"); + } + + return sb.ToString(); + } + #endregion + + #region 摧毁意识来源器官 + /// + /// 摧毁目标的所有意识来源器官 + /// + private void DestroyConsciousnessSourceParts(Pawn targetPawn) + { + if (targetPawn == null || targetPawn.Dead || targetPawn.Downed) + return; + + try + { + // 获取所有意识来源部位 + var consciousnessParts = targetPawn.health.hediffSet.GetNotMissingParts() + .Where(part => part.def.tags?.Contains(BodyPartTagDefOf.ConsciousnessSource) == true) + .ToList(); + + if (consciousnessParts.Count == 0) + { + return; + } + + int destroyedCount = 0; + + foreach (var part in consciousnessParts) + { + // 尝试用最高优先级的方式摧毁部位 + if (TryDestroyBodyPart(targetPawn, part)) + { + destroyedCount++; + + // 显示伤害效果 + if (Props.destroyFleck != null && targetPawn.Map != null) + { + FleckMaker.Static(targetPawn.Position, targetPawn.Map, Props.destroyFleck); + } + } + } + + // 如果摧毁了任何意识来源器官,应用惩罚效果 + if (destroyedCount > 0) + { + ApplyConsciousnessPenalty(targetPawn); + } + } + catch (System.Exception ex) + { + Log.Error($"[虫群术法] 摧毁意识来源器官时出错: {ex.Message}\n{ex.StackTrace}"); + } + } + + /// + /// 尝试摧毁身体部位 + /// + private bool TryDestroyBodyPart(Pawn pawn, BodyPartRecord part) + { + try + { + // 方法1:直接伤害(最可靠) + float damageAmount = part.def.GetMaxHealth(pawn) * Props.partDestructionDamageMult; + + DamageInfo damage = new DamageInfo( + Props.destroyDamageType ?? DamageDefOf.Burn, + damageAmount, + armorPenetration: 999f, + instigator: parent.pawn, + hitPart: part, + category: DamageInfo.SourceCategory.ThingOrUnknown + ); + + pawn.TakeDamage(damage); + + // 方法2:如果部位仍然存在,尝试强制移除 + if (!pawn.health.hediffSet.PartIsMissing(part)) + { + // 施加更大的伤害确保摧毁 + DamageInfo finalDamage = new DamageInfo( + Props.destroyDamageType ?? DamageDefOf.Burn, + 99999f, + armorPenetration: 999f, + instigator: parent.pawn, + hitPart: part + ); + pawn.TakeDamage(finalDamage); + + // 如果还是不行,尝试添加部件缺失Hediff + if (!pawn.health.hediffSet.PartIsMissing(part)) + { + pawn.health.AddHediff(HediffDefOf.MissingBodyPart, part); + } + } + + return true; + } + catch (System.Exception ex) + { + Log.Error($"[虫群术法] 摧毁部位 {part.Label} 时出错: {ex.Message}"); + return false; + } + } + + /// + /// 应用意识来源器官被摧毁的惩罚 + /// + private void ApplyConsciousnessPenalty(Pawn pawn) + { + // 显示效果 + if (Props.penaltyEffecter != null) + { + Effecter effecter = Props.penaltyEffecter.Spawn(); + effecter.Trigger(new TargetInfo(pawn.Position, pawn.Map), new TargetInfo(pawn.Position, pawn.Map)); + effecter.Cleanup(); + } + } + #endregion + + #region 视觉效果和消息 + /// + /// 显示效果和消息 + /// + private void ShowEffectsAndMessages(Pawn caster, Pawn target, float researchPoints, bool success) + { + // 显示收割效果 + if (Props.harvestEffecter != null) + { + Effecter effecter = Props.harvestEffecter.Spawn(); + effecter.Trigger(new TargetInfo(caster.Position, caster.Map), new TargetInfo(target.Position, target.Map)); + effecter.Cleanup(); + } + + // 显示收获消息 + if (Props.showHarvestMessage) + { + string message; + if (Props.customHarvestMessageKey.NullOrEmpty()) + { + message = "ARA_SwarmSpell_ResearchHarvest".Translate( + caster.LabelShortCap, + target.LabelShortCap, + researchPoints.ToString("F1")); + } + else + { + message = Props.customHarvestMessageKey.Translate( + caster.LabelShortCap, + target.LabelShortCap, + researchPoints.ToString("F1")); + } + + Messages.Message(message, caster, MessageTypeDefOf.PositiveEvent); + } + } + #endregion + + #region 验证和工具提示 + public override bool Valid(LocalTargetInfo target, bool throwMessages = false) + { + if (!base.Valid(target, throwMessages)) + return false; + + Pawn targetPawn = target.Pawn; + if (targetPawn == null) + { + if (throwMessages) + Messages.Message("需要选择一个目标单位", MessageTypeDefOf.RejectInput); + return false; + } + + // 检查目标是否活着且没有倒下(如果技能不允许对倒下单位使用) + if (!Props.canTargetDowned && targetPawn.Downed) + { + if (throwMessages) + Messages.Message("目标已经倒下,无法收割", MessageTypeDefOf.RejectInput); + return false; + } + + // 检查目标是否有意识来源器官(可选检查) + if (Props.requireConsciousnessSource) + { + var consciousnessParts = targetPawn.health.hediffSet.GetNotMissingParts() + .Where(part => part.def.tags?.Contains(BodyPartTagDefOf.ConsciousnessSource) == true) + .ToList(); + + if (consciousnessParts.Count == 0) + { + if (throwMessages) + Messages.Message("目标没有可收割的意识来源器官", MessageTypeDefOf.RejectInput); + return false; + } + } + + // 检查施法者是否有术法组件且科研点未满 + Pawn caster = parent.pawn; + if (caster != null) + { + Comp_SwarmSpellHolder spellHolder = caster.TryGetComp(); + if (spellHolder == null) + { + if (throwMessages) + Messages.Message("施法者没有灵能术法系统", MessageTypeDefOf.RejectInput); + return false; + } + + if (!spellHolder.IsSystemInitialized) + { + if (throwMessages) + Messages.Message("灵能术法系统未初始化", MessageTypeDefOf.RejectInput); + return false; + } + + // 检查科研点是否已满 + if (!Props.allowOverflow && spellHolder.PsychicResearchPoints >= spellHolder.MaxPsychicResearchPoints) + { + if (throwMessages) + Messages.Message("灵能科研点已达上限,无法收割", MessageTypeDefOf.RejectInput); + return false; + } + } + + return true; + } + #endregion + + #region AI 行为 + public override bool AICanTargetNow(LocalTargetInfo target) + { + Pawn caster = parent.pawn; + if (caster == null) + return false; + + Pawn targetPawn = target.Pawn; + if (targetPawn == null || targetPawn.Dead || (targetPawn.Downed && !Props.canTargetDowned)) + return false; + + // 检查施法者是否有术法组件 + Comp_SwarmSpellHolder spellHolder = caster.TryGetComp(); + if (spellHolder == null || !spellHolder.IsSystemInitialized) + return false; + + // AI不会在科研点已满时使用此技能 + if (!Props.allowOverflow && spellHolder.PsychicResearchPoints >= spellHolder.MaxPsychicResearchPoints) + return false; + + // AI倾向于选择智识和意识高的目标 + float predictedPoints = CalculateResearchPoints(targetPawn); + + // 计算收益评估 + float benefitScore = predictedPoints / spellHolder.MaxPsychicResearchPoints; + + // AI考虑目标的威胁程度 + float threatScore = targetPawn.Downed ? 0f : (targetPawn.kindDef.combatPower / 100f); + + // 综合评分:收益高、威胁低的目标优先 + float totalScore = benefitScore - (threatScore * 0.3f); + + return totalScore > 0.2f && base.AICanTargetNow(target); + } + #endregion + + #region 调试和工具方法 + /// + /// 获取目标意识来源器官的数量 + /// + public int GetTargetConsciousnessPartCount(Pawn target) + { + if (target == null || target.Dead || target.Downed) + return 0; + + return target.health.hediffSet.GetNotMissingParts() + .Count(part => part.def.tags?.Contains(BodyPartTagDefOf.ConsciousnessSource) == true); + } + + /// + /// 获取技能影响的详细描述 + /// + public string GetDetailedEffectDescription(Pawn target) + { + StringBuilder sb = new StringBuilder(); + + int partCount = GetTargetConsciousnessPartCount(target); + float predictedPoints = CalculateResearchPoints(target); + + sb.AppendLine("灵能科研点收割效果预测:"); + sb.AppendLine($"目标: {target.LabelCap}"); + sb.AppendLine($"意识来源器官: {partCount} 个"); + sb.AppendLine($"预计收割科研点: {predictedPoints:F1}"); + + if (partCount > 0) + { + sb.AppendLine(); + sb.AppendLine("将被摧毁的部位:"); + var parts = target.health.hediffSet.GetNotMissingParts() + .Where(part => part.def.tags?.Contains(BodyPartTagDefOf.ConsciousnessSource) == true) + .ToList(); + + foreach (var part in parts) + { + sb.AppendLine($" • {part.LabelCap} (健康: {target.health.hediffSet.GetPartHealth(part):F0}/{part.def.GetMaxHealth(target):F0})"); + } + } + + return sb.ToString(); + } + #endregion + } +} diff --git a/Source/ArachnaeSwarm/Abilities/ARA_PsychicResearchHarvest/CompProperties_AbilityPsychicResearchHarvest.cs b/Source/ArachnaeSwarm/Abilities/ARA_PsychicResearchHarvest/CompProperties_AbilityPsychicResearchHarvest.cs new file mode 100644 index 0000000..aec4d39 --- /dev/null +++ b/Source/ArachnaeSwarm/Abilities/ARA_PsychicResearchHarvest/CompProperties_AbilityPsychicResearchHarvest.cs @@ -0,0 +1,157 @@ +using RimWorld; +using UnityEngine; +using Verse; + +namespace ArachnaeSwarm +{ + /// + /// 灵能科研点收割技能属性 + /// + public class CompProperties_AbilityPsychicResearchHarvest : CompProperties_AbilityEffect + { + #region 科研点计算字段 + /// + /// 基础收割量 + /// + public float baseAmount = 100f; + + /// + /// 智识倍率 + /// + public float intelligenceMultiplier = 50f; + + /// + /// 意识倍率 + /// + public float consciousnessMultiplier = 100f; + + /// + /// 全局乘数 + /// + public float overallMultiplier = 1f; + + /// + /// 是否使用随机范围 + /// + public bool useRandomRange = false; + + /// + /// 随机范围(乘数) + /// + public FloatRange randomRange = new FloatRange(0.8f, 1.2f); + + /// + /// 最低收割量(确保至少收获这么多) + /// + public float minimumAmount = 10f; + + /// + /// 是否允许科研点溢出(超过上限) + /// + public bool allowOverflow = false; + #endregion + + #region 目标选择和验证字段 + /// + /// 是否可以对倒下的目标使用 + /// + public bool canTargetDowned = false; + + /// + /// 是否要求目标必须有意识来源器官 + /// + public bool requireConsciousnessSource = true; + + /// + /// 在工具提示中显示详细计算 + /// + public bool showDetailedCalculation = true; + #endregion + + #region 器官摧毁字段 + /// + /// 部位摧毁伤害倍数(基于部位最大生命值) + /// + public float partDestructionDamageMult = 2.0f; + + /// + /// 摧毁部位使用的伤害类型 + /// + public DamageDef destroyDamageType = null; + + /// + /// 摧毁部位时的特效 + /// + public FleckDef destroyFleck = null; + + /// + /// 是否显示器官摧毁消息 + /// + public bool showDestroyMessage = true; + + /// + /// 是否可能杀死目标 + /// + public bool canKillTarget = false; + + /// + /// 完全摧毁意识来源器官时的杀死几率 + /// + public float killChanceOnCompleteDestruction = 0.3f; + + /// + /// 杀死目标时使用的伤害类型 + /// + public DamageDef killDamageType = null; + + /// + /// 是否显示杀死消息 + /// + public bool showKillMessage = true; + #endregion + + #region 效果和消息字段 + /// + /// 收割时的特效 + /// + public EffecterDef harvestEffecter = null; + + /// + /// 惩罚效果 + /// + public EffecterDef penaltyEffecter = null; + + /// + /// 意识惩罚Hediff + /// + public HediffDef consciousnessPenaltyHediff = null; + + /// + /// 失去意识Hediff + /// + public HediffDef unconsciousnessHediff = null; + + /// + /// 是否显示收割消息 + /// + public bool showHarvestMessage = true; + + /// + /// 自定义收割消息翻译键 + /// + public string customHarvestMessageKey = null; + + /// + /// 是否显示目标受损消息 + /// + public bool showTargetDamageMessage = true; + #endregion + + #region 构造函数 + public CompProperties_AbilityPsychicResearchHarvest() + { + compClass = typeof(CompAbilityEffect_PsychicResearchHarvest); + } + #endregion + } +} diff --git a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj index ef3330e..7d60eed 100644 --- a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj +++ b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj @@ -34,8 +34,12 @@ 4 + + + +