diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll index 674f98b..92a21e3 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_Abilities.xml b/1.6/1.6/Defs/AbilityDefs/ARA_Abilities.xml index aeea6af..42bc198 100644 --- a/1.6/1.6/Defs/AbilityDefs/ARA_Abilities.xml +++ b/1.6/1.6/Defs/AbilityDefs/ARA_Abilities.xml @@ -91,6 +91,36 @@ + + ARA_Suicide_Ability + + 只要一声令下,阿拉克涅虫族随时可以为了虫巢的大业立刻死去 + ArachnaeSwarm/UI/Abilities/ARA_Suicide_Ability + 1 + false + 9900 + true + false + AcidSpray_Warmup + + Verb_CastAbility + 24 + 15 + AcidSpray_Resolve + false + false + + true + + + +
  • + +
  • Brain
  • + + +
    +
    @@ -532,6 +562,45 @@ --> + + ARA_Baneling_Suicide_Ability + + 阿拉克涅爆裂种在不使强腐蚀酸活化的情况下发生自爆,这种自爆只会造成轻微的伤害,不会产生酸雾,但是依然留下相同面积的菌毯。 + ArachnaeSwarm/UI/Abilities/ARA_Suicide_Ability + 1 + false + 9900 + true + false + AcidSpray_Warmup + + 3.9 + + + Verb_CastAbility + 24 + 2 + AcidSpray_Resolve + false + false + + true + + + +
  • + 1 + ARA_AcidBomb + 3.9 + 0 +
  • +
  • + +
  • Brain
  • + + +
    +
    ARA_Smokepop_Creeper_Ability_On @@ -1592,33 +1661,4 @@ - - ARA_Suicide_Ability - - 只要一声令下,阿拉克涅虫族随时可以为了虫巢的大业立刻死去 - ArachnaeSwarm/UI/Abilities/ARA_Suicide_Ability - 1 - false - 9900 - true - AcidSpray_Warmup - - Verb_CastAbility - 24 - 15 - AcidSpray_Resolve - false - false - - true - - - -
  • - -
  • Brain
  • - - -
    -
    \ No newline at end of file diff --git a/1.6/1.6/Defs/EvolutionDefs/ARA_Evolution.xml b/1.6/1.6/Defs/EvolutionDefs/ARA_Evolution.xml index 12b2151..50a23dd 100644 --- a/1.6/1.6/Defs/EvolutionDefs/ARA_Evolution.xml +++ b/1.6/1.6/Defs/EvolutionDefs/ARA_Evolution.xml @@ -63,6 +63,15 @@
  • ARA_Myrmecocystus_Production_Fuel
  • +
  • + +
  • + ArachnaeBase_Race_Scavenger + 2 + 5000 +
  • + + diff --git a/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml b/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml index bd66035..c38db40 100644 --- a/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml +++ b/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml @@ -549,6 +549,9 @@ + +
  • ARA_Baneling_Suicide_Ability
  • +
    diff --git a/1.6/1.6/Defs/ThingDef_Races/ARA_RaceNodeSwarm.xml b/1.6/1.6/Defs/ThingDef_Races/ARA_RaceNodeSwarm.xml index 4268ff6..906288a 100644 --- a/1.6/1.6/Defs/ThingDef_Races/ARA_RaceNodeSwarm.xml +++ b/1.6/1.6/Defs/ThingDef_Races/ARA_RaceNodeSwarm.xml @@ -779,18 +779,6 @@
  • true ARA_RaceBaseSwarmProduceSwitchHediff - ARA_InsectJelly - 1 - 1 - 1 - 9999 - -
  • - ArachnaeBase_Race_Scavenger - 2 - 5000 -
  • - CocoonDestroyed
  • @@ -1446,16 +1434,11 @@
  • true ARA_RaceBaseSwarmProduceSwitchHediff - ARA_InsectJelly - 1 - 1 - 1 - 9999
  • ArachnaeBase_Race_Baneling 6 - 800 + 600
  • CocoonDestroyed diff --git a/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/.suo b/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/.suo index b83d73e..ce9243d 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 f262da8..5c0ff76 100644 --- a/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/DocumentLayout.json +++ b/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/DocumentLayout.json @@ -3,27 +3,47 @@ "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_automechcarrier\\compproducedbymechcarrier.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:pawn_comps\\ara_automechcarrier\\compproducedbymechcarrier.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\\hediffs\\ara_productionqueue\\hediffcompproperties_productionqueue.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:hediffs\\ara_productionqueue\\hediffcompproperties_productionqueue.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_automechcarrier\\compautomechcarrier.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\\hediffs\\ara_productionqueue\\hediffcomp_productionqueue.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:hediffs\\ara_productionqueue\\hediffcomp_productionqueue.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_automechcarrier\\compproperties_automechcarrier.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:pawn_comps\\ara_automechcarrier\\compproperties_automechcarrier.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_automechcarrier\\compautomechcarrier.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:pawn_comps\\ara_automechcarrier\\compautomechcarrier.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\\damage\\damagedefextension_terraincover.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_automechcarrier\\compproducedbymechcarrier.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:pawn_comps\\ara_automechcarrier\\compproducedbymechcarrier.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\\eventsystem\\compopencustomui.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:eventsystem\\compopencustomui.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_GatherUnit\\CompAbilityEffect_GatherUnit.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:Abilities\\ARA_GatherUnit\\CompAbilityEffect_GatherUnit.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\\damage\\damagedefextension_terraincover.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:damage\\damagedefextension_terraincover.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\\damage\\damageworker_explosionwithterrain.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\\damage\\damageworker_explosionwithterrain.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:damage\\damageworker_explosionwithterrain.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\\buildings\\building_arachnaegravengine.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\\buildings\\building_arachnaegravengine.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:buildings\\building_arachnaegravengine.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\\jobs\\jobdriver_extracthoney\\thinknode_conditionalshouldextract.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\\jobs\\jobdriver_extracthoney\\thinknode_conditionalshouldextract.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:jobs\\jobdriver_extracthoney\\thinknode_conditionalshouldextract.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, { @@ -77,6 +97,10 @@ { "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\workgivers\\workgiver_feedwithhoney.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:workgivers\\workgiver_feedwithhoney.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\AutoMechCarrierUtils.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:Pawn_Comps\\ARA_AutoMechCarrier\\AutoMechCarrierUtils.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" } ], "DocumentGroupContainers": [ @@ -86,41 +110,116 @@ "DocumentGroups": [ { "DockedWidth": 200, - "SelectedChildIndex": 0, + "SelectedChildIndex": 1, "Children": [ - { - "$type": "Document", - "DocumentIndex": 0, - "Title": "CompProducedByMechCarrier.cs", - "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\CompProducedByMechCarrier.cs", - "RelativeDocumentMoniker": "Pawn_Comps\\ARA_AutoMechCarrier\\CompProducedByMechCarrier.cs", - "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\CompProducedByMechCarrier.cs", - "RelativeToolTip": "Pawn_Comps\\ARA_AutoMechCarrier\\CompProducedByMechCarrier.cs", - "ViewState": "AgIAABgAAAAAAAAAAAAkwHIAAAAAAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-01-22T03:56:26.73Z", - "EditorCaption": "" - }, { "$type": "Bookmark", "Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}" }, + { + "$type": "Document", + "DocumentIndex": 0, + "Title": "HediffCompProperties_ProductionQueue.cs", + "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_ProductionQueue\\HediffCompProperties_ProductionQueue.cs", + "RelativeDocumentMoniker": "Hediffs\\ARA_ProductionQueue\\HediffCompProperties_ProductionQueue.cs", + "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_ProductionQueue\\HediffCompProperties_ProductionQueue.cs", + "RelativeToolTip": "Hediffs\\ARA_ProductionQueue\\HediffCompProperties_ProductionQueue.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAMAAAASAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-01-22T09:30:17.721Z", + "EditorCaption": "" + }, { "$type": "Document", "DocumentIndex": 1, + "Title": "HediffComp_ProductionQueue.cs", + "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_ProductionQueue\\HediffComp_ProductionQueue.cs", + "RelativeDocumentMoniker": "Hediffs\\ARA_ProductionQueue\\HediffComp_ProductionQueue.cs", + "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_ProductionQueue\\HediffComp_ProductionQueue.cs", + "RelativeToolTip": "Hediffs\\ARA_ProductionQueue\\HediffComp_ProductionQueue.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAOEAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-01-22T09:01:06.335Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 2, + "Title": "CompProperties_AutoMechCarrier.cs", + "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\CompProperties_AutoMechCarrier.cs", + "RelativeDocumentMoniker": "Pawn_Comps\\ARA_AutoMechCarrier\\CompProperties_AutoMechCarrier.cs", + "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\CompProperties_AutoMechCarrier.cs", + "RelativeToolTip": "Pawn_Comps\\ARA_AutoMechCarrier\\CompProperties_AutoMechCarrier.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAAACUAAAAdAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-01-22T09:00:42.285Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 5, + "Title": "CompOpenCustomUI.cs", + "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\EventSystem\\CompOpenCustomUI.cs", + "RelativeDocumentMoniker": "EventSystem\\CompOpenCustomUI.cs", + "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\EventSystem\\CompOpenCustomUI.cs", + "RelativeToolTip": "EventSystem\\CompOpenCustomUI.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-01-22T08:22:11.975Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 6, + "Title": "CompAbilityEffect_GatherUnit.cs", + "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_GatherUnit\\CompAbilityEffect_GatherUnit.cs", + "RelativeDocumentMoniker": "Abilities\\ARA_GatherUnit\\CompAbilityEffect_GatherUnit.cs", + "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Abilities\\ARA_GatherUnit\\CompAbilityEffect_GatherUnit.cs", + "RelativeToolTip": "Abilities\\ARA_GatherUnit\\CompAbilityEffect_GatherUnit.cs", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-01-22T07:31:57.322Z" + }, + { + "$type": "Document", + "DocumentIndex": 3, "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", "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\CompAutoMechCarrier.cs", "RelativeToolTip": "Pawn_Comps\\ARA_AutoMechCarrier\\CompAutoMechCarrier.cs", - "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "ViewState": "AgIAAEgCAAAAAAAAAAAewFsCAAAMAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "WhenOpened": "2026-01-22T03:56:27.144Z", "EditorCaption": "" }, { "$type": "Document", - "DocumentIndex": 3, + "DocumentIndex": 24, + "Title": "AutoMechCarrierUtils.cs", + "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\AutoMechCarrierUtils.cs", + "RelativeDocumentMoniker": "Pawn_Comps\\ARA_AutoMechCarrier\\AutoMechCarrierUtils.cs", + "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\AutoMechCarrierUtils.cs", + "RelativeToolTip": "Pawn_Comps\\ARA_AutoMechCarrier\\AutoMechCarrierUtils.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAAABgAAABBAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-01-22T07:07:38.083Z" + }, + { + "$type": "Document", + "DocumentIndex": 4, + "Title": "CompProducedByMechCarrier.cs", + "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\CompProducedByMechCarrier.cs", + "RelativeDocumentMoniker": "Pawn_Comps\\ARA_AutoMechCarrier\\CompProducedByMechCarrier.cs", + "ToolTip": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_AutoMechCarrier\\CompProducedByMechCarrier.cs", + "RelativeToolTip": "Pawn_Comps\\ARA_AutoMechCarrier\\CompProducedByMechCarrier.cs", + "ViewState": "AgIAACsAAAAAAAAAAAAUwEAAAAArAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-01-22T03:56:26.73Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 8, "Title": "DamageWorker_ExplosionWithTerrain.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Damage\\DamageWorker_ExplosionWithTerrain.cs", "RelativeDocumentMoniker": "Damage\\DamageWorker_ExplosionWithTerrain.cs", @@ -128,12 +227,11 @@ "RelativeToolTip": "Damage\\DamageWorker_ExplosionWithTerrain.cs", "ViewState": "AgIAAAAAAAAAAAAAAAAAAFAAAAAbAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-01-22T03:13:00.366Z", - "EditorCaption": "" + "WhenOpened": "2026-01-22T03:13:00.366Z" }, { "$type": "Document", - "DocumentIndex": 4, + "DocumentIndex": 9, "Title": "Building_ArachnaeGravEngine.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_ArachnaeGravEngine.cs", "RelativeDocumentMoniker": "Buildings\\Building_ArachnaeGravEngine.cs", @@ -141,12 +239,11 @@ "RelativeToolTip": "Buildings\\Building_ArachnaeGravEngine.cs", "ViewState": "AgIAAAAAAAAAAAAAAAAAAAgAAAAXAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-01-22T03:12:54.988Z", - "EditorCaption": "" + "WhenOpened": "2026-01-22T03:12:54.988Z" }, { "$type": "Document", - "DocumentIndex": 2, + "DocumentIndex": 7, "Title": "DamageDefExtension_TerrainCover.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Damage\\DamageDefExtension_TerrainCover.cs", "RelativeDocumentMoniker": "Damage\\DamageDefExtension_TerrainCover.cs", @@ -154,12 +251,11 @@ "RelativeToolTip": "Damage\\DamageDefExtension_TerrainCover.cs", "ViewState": "AgIAAAAAAAAAAAAAAAAAAAcAAAAwAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-01-22T03:12:51.315Z", - "EditorCaption": "" + "WhenOpened": "2026-01-22T03:12:51.315Z" }, { "$type": "Document", - "DocumentIndex": 5, + "DocumentIndex": 10, "Title": "ThinkNode_ConditionalShouldExtract.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_ExtractHoney\\ThinkNode_ConditionalShouldExtract.cs", "RelativeDocumentMoniker": "Jobs\\JobDriver_ExtractHoney\\ThinkNode_ConditionalShouldExtract.cs", @@ -167,12 +263,11 @@ "RelativeToolTip": "Jobs\\JobDriver_ExtractHoney\\ThinkNode_ConditionalShouldExtract.cs", "ViewState": "AgIAACMAAAAAAAAAAAAewEwAAAANAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-01-21T16:03:09.823Z", - "EditorCaption": "" + "WhenOpened": "2026-01-21T16:03:09.823Z" }, { "$type": "Document", - "DocumentIndex": 6, + "DocumentIndex": 11, "Title": "JobGiver_ExtractHoney.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_ExtractHoney\\JobGiver_ExtractHoney.cs", "RelativeDocumentMoniker": "Jobs\\JobDriver_ExtractHoney\\JobGiver_ExtractHoney.cs", @@ -184,7 +279,7 @@ }, { "$type": "Document", - "DocumentIndex": 9, + "DocumentIndex": 14, "Title": "CompHoneyProduction_Animal.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_HoneyProduction_Animal\\CompHoneyProduction_Animal.cs", "RelativeDocumentMoniker": "Pawn_Comps\\ARA_HoneyProduction_Animal\\CompHoneyProduction_Animal.cs", @@ -196,7 +291,7 @@ }, { "$type": "Document", - "DocumentIndex": 10, + "DocumentIndex": 15, "Title": "CompAdvancedTraining.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Pawn_Comps\\ARA_TrainingWork\\CompAdvancedTraining.cs", "RelativeDocumentMoniker": "Pawn_Comps\\ARA_TrainingWork\\CompAdvancedTraining.cs", @@ -208,7 +303,7 @@ }, { "$type": "Document", - "DocumentIndex": 8, + "DocumentIndex": 13, "Title": "Need_HoneyProduction.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Needs\\Need_HoneyProduction.cs", "RelativeDocumentMoniker": "Needs\\Need_HoneyProduction.cs", @@ -220,7 +315,7 @@ }, { "$type": "Document", - "DocumentIndex": 11, + "DocumentIndex": 16, "Title": "ThinkNode_ConditionalAnimalShouldDoCleaningWork.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_Clean\\ThinkNode_ConditionalAnimalShouldDoCleaningWork.cs", "RelativeDocumentMoniker": "Jobs\\JobDriver_Clean\\ThinkNode_ConditionalAnimalShouldDoCleaningWork.cs", @@ -232,7 +327,7 @@ }, { "$type": "Document", - "DocumentIndex": 7, + "DocumentIndex": 12, "Title": "JobDriver_ExtractHoney.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_ExtractHoney\\JobDriver_ExtractHoney.cs", "RelativeDocumentMoniker": "Jobs\\JobDriver_ExtractHoney\\JobDriver_ExtractHoney.cs", @@ -244,7 +339,7 @@ }, { "$type": "Document", - "DocumentIndex": 15, + "DocumentIndex": 20, "Title": "JobGiver_Cleaner.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_Clean\\JobGiver_Cleaner.cs", "RelativeDocumentMoniker": "Jobs\\JobDriver_Clean\\JobGiver_Cleaner.cs", @@ -256,7 +351,7 @@ }, { "$type": "Document", - "DocumentIndex": 14, + "DocumentIndex": 19, "Title": "WorkGiver_ArachnaeClean.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\WorkGivers\\WorkGiver_ArachnaeClean.cs", "RelativeDocumentMoniker": "WorkGivers\\WorkGiver_ArachnaeClean.cs", @@ -268,7 +363,7 @@ }, { "$type": "Document", - "DocumentIndex": 12, + "DocumentIndex": 17, "Title": "JobGiver_Grower.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_Plant\\JobGiver_Grower.cs", "RelativeDocumentMoniker": "Jobs\\JobDriver_Plant\\JobGiver_Grower.cs", @@ -280,7 +375,7 @@ }, { "$type": "Document", - "DocumentIndex": 13, + "DocumentIndex": 18, "Title": "ThinkNode_ConditionalAnimalShouldDoGrowingWork.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_Plant\\ThinkNode_ConditionalAnimalShouldDoGrowingWork.cs", "RelativeDocumentMoniker": "Jobs\\JobDriver_Plant\\ThinkNode_ConditionalAnimalShouldDoGrowingWork.cs", @@ -292,7 +387,7 @@ }, { "$type": "Document", - "DocumentIndex": 17, + "DocumentIndex": 22, "Title": "WorkGiver_ExtractHoney.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\WorkGivers\\WorkGiver_ExtractHoney.cs", "RelativeDocumentMoniker": "WorkGivers\\WorkGiver_ExtractHoney.cs", @@ -304,7 +399,7 @@ }, { "$type": "Document", - "DocumentIndex": 18, + "DocumentIndex": 23, "Title": "WorkGiver_FeedWithHoney.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\WorkGivers\\WorkGiver_FeedWithHoney.cs", "RelativeDocumentMoniker": "WorkGivers\\WorkGiver_FeedWithHoney.cs", @@ -316,7 +411,7 @@ }, { "$type": "Document", - "DocumentIndex": 16, + "DocumentIndex": 21, "Title": "ARA_DefOf.cs", "DocumentMoniker": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\ARA_DefOf.cs", "RelativeDocumentMoniker": "ARA_DefOf.cs", diff --git a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj index 0e93099..4728668 100644 --- a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj +++ b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj @@ -286,6 +286,8 @@ + + diff --git a/Source/ArachnaeSwarm/Hediffs/ARA_ProductionQueue/HediffCompProperties_ProductionQueue.cs b/Source/ArachnaeSwarm/Hediffs/ARA_ProductionQueue/HediffCompProperties_ProductionQueue.cs new file mode 100644 index 0000000..6745385 --- /dev/null +++ b/Source/ArachnaeSwarm/Hediffs/ARA_ProductionQueue/HediffCompProperties_ProductionQueue.cs @@ -0,0 +1,313 @@ +using RimWorld; +using System.Collections.Generic; +using Verse; +using System.Linq; + +namespace ArachnaeSwarm +{ + /// + /// HediffComp_ProductionQueue的属性类 + /// + public class HediffCompProperties_ProductionQueue : HediffCompProperties + { + // 生产队列定义 + public List productionQueue = new List(); + + // 生产队列是否可以通过代码动态修改 + public bool allowDynamicModification = true; + + // 是否启用调试日志 + public bool debugLogging = false; + + // ===== 新增:控制信息显示的字段 ===== + // 是否在Hediff描述中显示生产能力信息 + public bool showProductionInfoInHediff = true; + + // 信息标题(可翻译) + public string infoTitle = "ProductionQueue_InfoTitle"; // 默认值 + + // 信息格式字符串(可翻译) + // 可用变量: {UNIT} - 单位名称, {COUNT} - 可生产数量 + public string infoFormat = "ProductionQueue_InfoFormat"; // 默认值 + + // 当生产队列为空时显示的信息(可翻译) + public string emptyQueueInfo = "ProductionQueue_EmptyInfo"; + + // 信息分隔符(可翻译) + public string infoSeparator = "\n"; + + // 是否在信息中显示单位成本(如果设置了成本) + public bool showCostInInfo = true; + + // 成本信息格式(可翻译) + public string costInfoFormat = "ProductionQueue_CostFormat"; // {COST} - 成本数量 + + // 是否在信息中显示冷却时间(如果设置了冷却时间) + public bool showCooldownInInfo = false; + + // 冷却时间信息格式(可翻译) + public string cooldownInfoFormat = "ProductionQueue_CooldownFormat"; // {COOLDOWN} - 冷却时间描述 + + // 是否显示条件信息(如果条目有条件限制) + public bool showConditionInfo = false; + + // 条件已满足时的信息(可翻译) + public string conditionMetInfo = "ProductionQueue_ConditionMet"; + + // 条件未满足时的信息(可翻译) + public string conditionNotMetInfo = "ProductionQueue_ConditionNotMet"; + + // 是否在信息末尾添加额外说明(如果有customInfo字段) + public bool showCustomInfo = true; + + // 自定义信息格式(可翻译) + public string customInfoFormat = "ProductionQueue_CustomInfoFormat"; // {CUSTOMINFO} - 自定义信息 + + public HediffCompProperties_ProductionQueue() + { + compClass = typeof(HediffComp_ProductionQueue); + } + + public override IEnumerable ConfigErrors(HediffDef parentDef) + { + foreach (var error in base.ConfigErrors(parentDef)) + { + yield return error; + } + + // 验证生产队列 + if (productionQueue == null || productionQueue.Count == 0) + { + yield return $"{parentDef.defName}: HediffCompProperties_ProductionQueue的生产队列为空"; + } + else + { + for (int i = 0; i < productionQueue.Count; i++) + { + var entry = productionQueue[i]; + if (entry.pawnKind == null) + { + yield return $"{parentDef.defName}: 生产队列条目 {i} 缺少pawnKind定义"; + } + if (entry.count <= 0) + { + yield return $"{parentDef.defName}: 生产队列条目 {entry.pawnKind?.defName ?? "未知"} 的数量必须大于0"; + } + } + } + } + + /// + /// 获取生产能力信息的字符串 + /// + public string GetProductionInfoString(Pawn pawn = null) + { + // 如果不显示信息,返回空字符串 + if (!showProductionInfoInHediff || productionQueue == null || productionQueue.Count == 0) + { + return ""; + } + + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + + // 添加标题 + if (!string.IsNullOrEmpty(infoTitle)) + { + sb.AppendLine(infoTitle.Translate()); + } + + bool hasAnyEntry = false; + + foreach (var entry in productionQueue) + { + if (entry.pawnKind == null) + continue; + + // 检查条件是否满足 + bool conditionsMet = true; + string conditionReason = ""; + + if (pawn != null && !entry.conditions.NullOrEmpty()) + { + // 检查所有条件 + foreach (var condition in entry.conditions) + { + string reason; + if (!condition.IsMet(out reason)) + { + conditionsMet = false; + conditionReason = reason; + break; + } + } + } + + // 构建条目信息 + string entryInfo = BuildEntryInfo(entry, pawn, conditionsMet, conditionReason); + if (!string.IsNullOrEmpty(entryInfo)) + { + sb.Append(entryInfo); + sb.Append(infoSeparator); + hasAnyEntry = true; + } + } + + // 如果没有有效的条目 + if (!hasAnyEntry) + { + return emptyQueueInfo.Translate(); + } + + // 移除最后一个分隔符 + if (sb.Length > 0 && sb.ToString().EndsWith(infoSeparator)) + { + sb.Length -= infoSeparator.Length; + } + + return sb.ToString(); + } + + /// + /// 构建单个条目的信息 + /// + private string BuildEntryInfo(PawnProductionEntry entry, Pawn pawn, bool conditionsMet, string conditionReason) + { + // 如果条件不满足且设置了隐藏不可用的条目,返回空字符串 + if (!conditionsMet && !showConditionInfo) + { + return ""; + } + + System.Text.StringBuilder entrySb = new System.Text.StringBuilder(); + + // 基本格式:单位名称 x 数量 + string baseInfo = infoFormat.Translate( + "UNIT".Translate(entry.pawnKind.LabelCap), + "COUNT".Translate(entry.count) + ); + + entrySb.Append(baseInfo); + + // 添加成本信息 + if (showCostInInfo && entry.cost.HasValue && entry.cost.Value > 0) + { + string costInfo = costInfoFormat.Translate("COST".Translate(entry.cost.Value)); + entrySb.Append(" ").Append(costInfo); + } + + // 添加冷却时间信息 + if (showCooldownInInfo && entry.cooldownTicks.HasValue && entry.cooldownTicks.Value > 0) + { + string cooldownDesc = entry.cooldownTicks.Value.ToStringTicksToPeriod(); + string cooldownInfo = cooldownInfoFormat.Translate("COOLDOWN".Translate(cooldownDesc)); + entrySb.Append(" ").Append(cooldownInfo); + } + + // 添加条件状态信息 + if (showConditionInfo) + { + if (conditionsMet) + { + string metInfo = conditionMetInfo.Translate(); + entrySb.Append(" ").Append(metInfo); + } + else + { + string notMetInfo = conditionNotMetInfo.Translate("REASON".Translate(conditionReason)); + entrySb.Append(" ").Append(notMetInfo); + } + } + + // 添加自定义信息 + if (showCustomInfo && !string.IsNullOrEmpty(entry.customInfo)) + { + string customInfo = customInfoFormat.Translate("CUSTOMINFO".Translate(entry.customInfo)); + entrySb.Append(" ").Append(customInfo); + } + + return entrySb.ToString(); + } + + /// + /// 合并多个生产队列 + /// + public static List MergeProductionQueues(List> queues) + { + var mergedQueue = new List(); + var entryMap = new Dictionary(); + + foreach (var queue in queues) + { + if (queue == null) + continue; + + foreach (var entry in queue) + { + if (entry.pawnKind == null) + continue; + + if (entryMap.TryGetValue(entry.pawnKind, out var existingEntry)) + { + // 合并相同PawnKindDef的条目 + existingEntry.count += entry.count; + + // 使用较小的成本(如果有指定) + if (entry.cost.HasValue && (!existingEntry.cost.HasValue || entry.cost.Value < existingEntry.cost.Value)) + { + existingEntry.cost = entry.cost; + } + + // 使用较短的冷却时间(如果有指定) + if (entry.cooldownTicks.HasValue && (!existingEntry.cooldownTicks.HasValue || entry.cooldownTicks.Value < existingEntry.cooldownTicks.Value)) + { + existingEntry.cooldownTicks = entry.cooldownTicks; + } + } + else + { + // 创建新条目 + var newEntry = new PawnProductionEntry + { + pawnKind = entry.pawnKind, + count = entry.count, + cost = entry.cost, + cooldownTicks = entry.cooldownTicks, + conditions = entry.conditions?.ToList(), // 复制条件列表 + customInfo = entry.customInfo + }; + entryMap[entry.pawnKind] = newEntry; + mergedQueue.Add(newEntry); + } + } + } + + return mergedQueue; + } + + /// + /// 获取配置统计信息 + /// + public string GetConfigInfo() + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + sb.AppendLine("=== HediffCompProperties_ProductionQueue 配置 ==="); + sb.AppendLine($"显示生产信息: {showProductionInfoInHediff}"); + sb.AppendLine($"显示成本信息: {showCostInInfo}"); + sb.AppendLine($"显示冷却信息: {showCooldownInInfo}"); + sb.AppendLine($"显示条件信息: {showConditionInfo}"); + sb.AppendLine($"显示自定义信息: {showCustomInfo}"); + sb.AppendLine($"允许动态修改: {allowDynamicModification}"); + sb.AppendLine($"生产队列条目数: {productionQueue?.Count ?? 0}"); + + if (productionQueue != null && productionQueue.Count > 0) + { + foreach (var entry in productionQueue) + { + sb.AppendLine($" • {entry.pawnKind?.defName ?? "NULL"}: {entry.count} 个"); + } + } + + return sb.ToString(); + } + } +} diff --git a/Source/ArachnaeSwarm/Hediffs/ARA_ProductionQueue/HediffComp_ProductionQueue.cs b/Source/ArachnaeSwarm/Hediffs/ARA_ProductionQueue/HediffComp_ProductionQueue.cs new file mode 100644 index 0000000..113dedf --- /dev/null +++ b/Source/ArachnaeSwarm/Hediffs/ARA_ProductionQueue/HediffComp_ProductionQueue.cs @@ -0,0 +1,273 @@ +using RimWorld; +using System.Collections.Generic; +using Verse; + +namespace ArachnaeSwarm +{ + /// + /// 定义生产队列的HediffComp + /// 允许通过Hediff为CompAutoMechCarrier提供生产队列定义 + /// + public class HediffComp_ProductionQueue : HediffComp + { + public HediffCompProperties_ProductionQueue Props => + (HediffCompProperties_ProductionQueue)props; + + /// + /// 获取Hediff的描述信息(显示在Hediff详情中) + /// + public override string CompTipStringExtra + { + get + { + // 获取生产能力信息 + string productionInfo = GetProductionInfoString(); + + if (!string.IsNullOrEmpty(productionInfo)) + { + return productionInfo; + } + + return base.CompTipStringExtra; + } + } + + /// + /// 获取Hediff的完整描述信息 + /// + public override string CompDescriptionExtra + { + get + { + // 也可以在这里添加生产能力信息 + string productionInfo = GetProductionInfoString(); + + if (!string.IsNullOrEmpty(productionInfo)) + { + // 将生产能力信息添加到描述中 + string baseDescription = base.CompDescriptionExtra ?? ""; + + if (!string.IsNullOrEmpty(baseDescription)) + { + return baseDescription + "\n\n" + productionInfo; + } + else + { + return productionInfo; + } + } + + return base.CompDescriptionExtra; + } + } + + /// + /// 获取生产能力信息字符串 + /// + public string GetProductionInfoString() + { + if (Props == null) + return ""; + + // 获取当前Pawn(如果适用) + Pawn pawn = null; + if (parent != null && parent.pawn != null) + { + pawn = parent.pawn; + } + + return Props.GetProductionInfoString(pawn); + } + + /// + /// 获取生产队列定义 + /// + public List GetProductionQueue() + { + return Props?.productionQueue ?? new List(); + } + + /// + /// 获取可用的生产队列 + /// 可以根据条件进行过滤 + /// + public List GetAvailableProductionQueue(Pawn pawn) + { + var queue = GetProductionQueue(); + var availableQueue = new List(); + + foreach (var entry in queue) + { + // 检查前置条件 + if (CheckEntryConditions(entry, pawn)) + { + availableQueue.Add(entry); + } + } + + return availableQueue; + } + + /// + /// 检查条目条件是否满足 + /// + private bool CheckEntryConditions(PawnProductionEntry entry, Pawn pawn) + { + // 检查自定义条件 + if (!entry.conditions.NullOrEmpty()) + { + foreach (var condition in entry.conditions) + { + string reason; + if (!condition.IsMet(out reason)) + { + return false; + } + } + } + + return true; + } + + /// + /// 根据PawnKindDef查找生产队列条目 + /// + public PawnProductionEntry GetEntryForPawnKind(PawnKindDef pawnKindDef) + { + var queue = GetProductionQueue(); + return queue?.Find(entry => entry.pawnKind == pawnKindDef); + } + + /// + /// 添加新的生产队列条目 + /// + public void AddProductionEntry(PawnProductionEntry entry) + { + var queue = GetProductionQueue(); + if (queue == null) + return; + + queue.Add(entry); + } + + /// + /// 移除生产队列条目 + /// + public bool RemoveProductionEntry(PawnKindDef pawnKindDef) + { + var queue = GetProductionQueue(); + if (queue == null) + return false; + + return queue.RemoveAll(entry => entry.pawnKind == pawnKindDef) > 0; + } + + /// + /// 更新生产队列条目 + /// + public bool UpdateProductionEntry(PawnKindDef pawnKindDef, PawnProductionEntry newEntry) + { + var queue = GetProductionQueue(); + if (queue == null) + return false; + + for (int i = 0; i < queue.Count; i++) + { + if (queue[i].pawnKind == pawnKindDef) + { + queue[i] = newEntry; + return true; + } + } + + return false; + } + + /// + /// 获取调试信息 + /// + public string GetDebugInfo() + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + sb.AppendLine($"=== HediffComp_ProductionQueue 调试信息 ==="); + sb.AppendLine($"Hediff: {parent.def.defName}"); + sb.AppendLine($"显示生产信息: {Props.showProductionInfoInHediff}"); + sb.AppendLine($"生产队列条目数: {GetProductionQueue()?.Count ?? 0}"); + + // 显示生产信息字符串 + string productionInfo = GetProductionInfoString(); + if (!string.IsNullOrEmpty(productionInfo)) + { + sb.AppendLine($"生产信息:\n{productionInfo}"); + } + + var queue = GetProductionQueue(); + if (queue != null && queue.Count > 0) + { + sb.AppendLine($"详细条目:"); + foreach (var entry in queue) + { + sb.AppendLine($" • {entry.pawnKind?.label ?? "NULL"}: {entry.count} 个"); + if (entry.cost.HasValue) + sb.AppendLine($" 成本: {entry.cost.Value}"); + if (entry.cooldownTicks.HasValue) + sb.AppendLine($" 冷却时间: {entry.cooldownTicks.Value.ToStringTicksToPeriod()}"); + if (!string.IsNullOrEmpty(entry.customInfo)) + sb.AppendLine($" 自定义信息: {entry.customInfo}"); + } + } + else + { + sb.AppendLine(" 生产队列为空"); + } + + return sb.ToString(); + } + + /// + /// 获取统计信息 + /// + public string GetStatistics() + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + + var queue = GetProductionQueue(); + if (queue != null && queue.Count > 0) + { + sb.AppendLine($"此状态提供以下生产能力:"); + + foreach (var entry in queue) + { + if (entry.pawnKind == null) + continue; + + string entryInfo = $" • {entry.pawnKind.label}: 最多 {entry.count} 个"; + + if (entry.cost.HasValue) + { + entryInfo += $", 每个消耗 {entry.cost.Value} 资源"; + } + + if (entry.cooldownTicks.HasValue) + { + string cooldownDesc = entry.cooldownTicks.Value.ToStringTicksToPeriod(); + entryInfo += $", 冷却时间 {cooldownDesc}"; + } + + if (!string.IsNullOrEmpty(entry.customInfo)) + { + entryInfo += $" ({entry.customInfo})"; + } + + sb.AppendLine(entryInfo); + } + } + else + { + sb.AppendLine("此状态不提供生产能力"); + } + + return sb.ToString(); + } + } +} diff --git a/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/CompAutoMechCarrier.cs b/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/CompAutoMechCarrier.cs index d550143..8e13249 100644 --- a/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/CompAutoMechCarrier.cs +++ b/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/CompAutoMechCarrier.cs @@ -53,9 +53,234 @@ namespace ArachnaeSwarm } #endregion + #region Custom Follow Position + private IntVec3? customFollowPosition = null; + private Map customFollowPositionMap = null; + private object customPositionLock = new object(); + + /// + /// 获取或设置自定义跟随位置 + /// 如果此位置不为空,生成的单位将以此位置而非父单位位置为跟随中心点 + /// + public IntVec3? CustomFollowPosition + { + get + { + lock (customPositionLock) + { + return customFollowPosition; + } + } + set + { + lock (customPositionLock) + { + customFollowPosition = value; + if (value.HasValue && parent != null && parent.Spawned) + { + customFollowPositionMap = parent.Map; + } + else + { + customFollowPositionMap = null; + } + + // 通知所有已生成的单位更新他们的跟随位置 + NotifyFollowPositionChanged(); + } + } + } + + /// + /// 检查自定义位置是否有效(位置不为空且在正确的地图上) + /// + public bool HasValidCustomFollowPosition + { + get + { + if (!customFollowPosition.HasValue || customFollowPositionMap == null) + return false; + + // 如果父单位已销毁或不在同一地图,自定义位置也无效 + if (parent == null || parent.Destroyed || !parent.Spawned) + return false; + + return customFollowPositionMap == parent.Map; + } + } + + /// + /// 获取有效的跟随位置 + /// 优先返回自定义位置,如果无效则返回父单位位置 + /// + public IntVec3 GetEffectiveFollowPosition() + { + if (HasValidCustomFollowPosition) + { + return customFollowPosition.Value; + } + + // 返回父单位位置 + if (parent != null && parent.Spawned) + { + if (parent is Building building) + { + return building.InteractionCell; + } + return parent.Position; + } + + return IntVec3.Invalid; + } + + /// + /// 获取跟随位置的地图 + /// + public Map GetFollowPositionMap() + { + if (HasValidCustomFollowPosition) + { + return customFollowPositionMap; + } + + if (parent != null && parent.Spawned) + { + return parent.Map; + } + + return null; + } + + /// + /// 通知所有已生成的单位跟随位置已改变 + /// + private void NotifyFollowPositionChanged() + { + if (SpawnedPawns == null || !SpawnedPawns.Any()) + return; + + // 清理无效的Pawn引用 + SpawnedPawns.RemoveAll(p => p == null || p.Destroyed); + + // 通知每个Pawn的CompProducedByMechCarrier + foreach (Pawn spawnedPawn in SpawnedPawns) + { + if (spawnedPawn == null || spawnedPawn.Destroyed || !spawnedPawn.Spawned) + continue; + + var producedComp = spawnedPawn.TryGetComp(); + if (producedComp != null) + { + producedComp.TryUpdateProducerStatus(); + } + } + } + + /// + /// 清空自定义跟随位置 + /// + public void ClearCustomFollowPosition() + { + CustomFollowPosition = null; + } + + /// + /// 设置自定义跟随位置 + /// + /// 新的跟随位置 + /// 是否设置成功 + public bool SetCustomFollowPosition(IntVec3 position) + { + if (parent == null || !parent.Spawned) + return false; + + if (!position.InBounds(parent.Map)) + return false; + + CustomFollowPosition = position; + return true; + } + + /// + /// 临时设置自定义跟随位置(在一段时间后自动清除) + /// + /// 临时位置 + /// 持续时间(tick) + public void SetTemporaryFollowPosition(IntVec3 position, int durationTicks) + { + if (!SetCustomFollowPosition(position)) + return; + + // 启动定时器清除临时位置 + StartPositionClearTimer(durationTicks); + } + + private void StartPositionClearTimer(int durationTicks) + { + // 这里可以使用TickManager来安排定时清除 + // 简单实现:记录时间并在Tick中检查 + temporaryPositionExpiryTick = Find.TickManager.TicksGame + durationTicks; + } + #endregion + + #region Temporary Position Timer + private int temporaryPositionExpiryTick = -1; + + private void CheckTemporaryPositionExpiry() + { + if (temporaryPositionExpiryTick > 0 && + Find.TickManager.TicksGame >= temporaryPositionExpiryTick && + customFollowPosition.HasValue) + { + ClearCustomFollowPosition(); + temporaryPositionExpiryTick = -1; + } + } + #endregion + public CompProperties_AutoMechCarrier AutoProps => (CompProperties_AutoMechCarrier)props; - private int TotalPawnCapacity => AutoProps.productionQueue.Sum(e => e.count); + // 缓存的合并生产队列 + private List cachedProductionQueue = null; + private int lastProductionQueueUpdateTick = -1; + private const int PRODUCTION_QUEUE_CACHE_TICKS = 30; // 30 tick缓存 + + /// + /// 获取合并后的生产队列 + /// 包括从HediffComp扫描的和动态添加的 + /// + public List GetProductionQueue() + { + // 使用缓存提高性能 + if (cachedProductionQueue != null && + Find.TickManager.TicksGame - lastProductionQueueUpdateTick < PRODUCTION_QUEUE_CACHE_TICKS) + { + return cachedProductionQueue; + } + + // 获取Pawn引用 + var pawn = parent as Pawn; + + // 从AutoProps获取合并后的生产队列 + cachedProductionQueue = AutoProps.GetMergedProductionQueue(pawn); + lastProductionQueueUpdateTick = Find.TickManager.TicksGame; + + return cachedProductionQueue; + } + + /// + /// 强制刷新生产队列缓存 + /// + public void RefreshProductionQueue() + { + cachedProductionQueue = null; + lastProductionQueueUpdateTick = -1; + } + + /// + /// 获取总容量 + /// + private int TotalPawnCapacity => GetProductionQueue().Sum(e => e.count); private int LiveSpawnedPawnsCount(PawnKindDef kind) { @@ -70,7 +295,11 @@ namespace ArachnaeSwarm if (CooldownTicksRemaining > 0) return "CooldownTime".Translate() + " " + CooldownTicksRemaining.ToStringSecondsFromTicks(); - PawnProductionEntry entry = AutoProps.productionQueue.First(e => e.pawnKind == kind); + var productionQueue = GetProductionQueue(); + PawnProductionEntry entry = productionQueue.FirstOrDefault(e => e.pawnKind == kind); + if (entry == null) + return "生产队列中未找到指定的PawnKindDef"; + int cost = entry.cost ?? Props.costPerPawn; if (!AutoProps.freeProduction && InnerContainer.TotalStackCountOfDef(Props.fixedIngredient) < cost) @@ -100,7 +329,22 @@ namespace ArachnaeSwarm // 初始化生产者信息 producedComp.Initialize(parent, this); - GenSpawn.Spawn(pawn, parent.Position, parent.Map); + // 生成位置:使用自定义跟随位置(如果有效),否则使用父单位位置 + IntVec3 spawnPosition; + Map spawnMap; + + if (HasValidCustomFollowPosition) + { + spawnPosition = customFollowPosition.Value; + spawnMap = customFollowPositionMap; + } + else + { + spawnPosition = parent.Position; + spawnMap = parent.Map; + } + + GenSpawn.Spawn(pawn, spawnPosition, spawnMap); SpawnedPawns.Add(pawn); if (parent is Pawn p && p.GetLord() != null) @@ -108,7 +352,8 @@ namespace ArachnaeSwarm if (!AutoProps.freeProduction) { - PawnProductionEntry entry = AutoProps.productionQueue.First(e => e.pawnKind == kind); + var productionQueue = GetProductionQueue(); + PawnProductionEntry entry = productionQueue.First(e => e.pawnKind == kind); int costLeft = entry.cost ?? Props.costPerPawn; List things = new List(InnerContainer); @@ -121,7 +366,7 @@ namespace ArachnaeSwarm } } - PawnProductionEntry spawnEntry = AutoProps.productionQueue.First(e => e.pawnKind == kind); + var spawnEntry = GetProductionQueue().First(e => e.pawnKind == kind); CooldownTicksRemaining = spawnEntry.cooldownTicks ?? Props.cooldownTicks; if (Props.spawnedMechEffecter != null) @@ -140,6 +385,9 @@ namespace ArachnaeSwarm public override void CompTick() { base.CompTick(); + + // 检查临时位置是否过期 + CheckTemporaryPositionExpiry(); if (parent.IsHashIntervalTick(60)) // 每秒检查一次 { @@ -149,9 +397,16 @@ namespace ArachnaeSwarm return; // 有Hediff,停止生产 } + // 获取当前生产队列 + var productionQueue = GetProductionQueue(); + if (productionQueue == null || productionQueue.Count == 0) + { + return; // 生产队列为空,不进行生产 + } + // 1. 先检查是否满员 bool isFull = true; - foreach (var entry in AutoProps.productionQueue) + foreach (var entry in productionQueue) { if (LiveSpawnedPawnsCount(entry.pawnKind) < entry.count) { @@ -169,7 +424,7 @@ namespace ArachnaeSwarm if (CooldownTicksRemaining > 0) return; // 3. 寻找空位并生产 - foreach (var entry in AutoProps.productionQueue) + foreach (var entry in productionQueue) { if (LiveSpawnedPawnsCount(entry.pawnKind) < entry.count) { @@ -183,6 +438,89 @@ namespace ArachnaeSwarm } } + /// + /// 添加动态生产队列条目 + /// + public bool AddProductionEntry(PawnProductionEntry entry) + { + if (entry == null || entry.pawnKind == null) + return false; + + AutoProps.AddDynamicProductionEntry(entry); + RefreshProductionQueue(); + + if (AutoProps.debugLogging) + Log.Message($"[CompAutoMechCarrier] 添加生产队列条目: {entry.pawnKind.label} x{entry.count}"); + + return true; + } + + /// + /// 移除动态生产队列条目 + /// + public bool RemoveProductionEntry(PawnKindDef pawnKindDef) + { + if (pawnKindDef == null) + return false; + + bool result = AutoProps.RemoveDynamicProductionEntry(pawnKindDef); + if (result) + { + RefreshProductionQueue(); + + if (AutoProps.debugLogging) + Log.Message($"[CompAutoMechCarrier] 移除生产队列条目: {pawnKindDef.label}"); + } + + return result; + } + + /// + /// 更新动态生产队列条目 + /// + public bool UpdateProductionEntry(PawnKindDef pawnKindDef, PawnProductionEntry newEntry) + { + if (pawnKindDef == null || newEntry == null) + return false; + + bool result = AutoProps.UpdateDynamicProductionEntry(pawnKindDef, newEntry); + if (result) + { + RefreshProductionQueue(); + + if (AutoProps.debugLogging) + Log.Message($"[CompAutoMechCarrier] 更新生产队列条目: {pawnKindDef.label}"); + } + + return result; + } + + /// + /// 清除所有动态生产队列 + /// + public void ClearDynamicProductionQueue() + { + AutoProps.ClearDynamicProductionQueue(); + RefreshProductionQueue(); + + if (AutoProps.debugLogging) + Log.Message("[CompAutoMechCarrier] 清除所有动态生产队列"); + } + + /// + /// 扫描Hediff并更新生产队列 + /// + public void ScanAndUpdateProductionQueue() + { + RefreshProductionQueue(); + + if (AutoProps.debugLogging) + { + var productionQueue = GetProductionQueue(); + Log.Message($"[CompAutoMechCarrier] 扫描Hediff完成,生产队列条目数: {productionQueue.Count}"); + } + } + public override IEnumerable CompGetGizmosExtra() { // 移除所有Gizmo逻辑 @@ -194,9 +532,16 @@ namespace ArachnaeSwarm SpawnedPawns.RemoveAll(p => p == null || p.Destroyed); string text = "Pawns: " + SpawnedPawns.Count + " / " + TotalPawnCapacity; - foreach (var entry in AutoProps.productionQueue) + var productionQueue = GetProductionQueue(); + foreach (var entry in productionQueue) { text += $"\n- {entry.pawnKind.LabelCap}: {LiveSpawnedPawnsCount(entry.pawnKind)} / {entry.count}"; + + // 显示自定义信息 + if (entry.customInfo != null) + { + text += $" ({entry.customInfo})"; + } } if (CooldownTicksRemaining > 0) @@ -208,7 +553,93 @@ namespace ArachnaeSwarm { text += "\n" + base.CompInspectStringExtra(); } + + // 显示自定义跟随位置信息 + if (HasValidCustomFollowPosition) + { + text += $"\nCustom Follow Position: {customFollowPosition.Value}"; + if (temporaryPositionExpiryTick > 0) + { + int remainingTicks = temporaryPositionExpiryTick - Find.TickManager.TicksGame; + if (remainingTicks > 0) + { + text += $"\nTemporary Position (expires in: {remainingTicks.ToStringSecondsFromTicks()})"; + } + } + } + return text; } + + /// + /// 获取调试信息 + /// + public string GetDebugInfo() + { + var pawn = parent as Pawn; + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + sb.AppendLine("=== CompAutoMechCarrier 调试信息 ==="); + + // CompAutoMechCarrier基本信息 + sb.AppendLine($"父单位: {parent?.LabelCap ?? "NULL"}"); + sb.AppendLine($"自定义跟随位置: {CustomFollowPosition}"); + sb.AppendLine($"有效跟随位置: {GetEffectiveFollowPosition()}"); + sb.AppendLine($"临时位置过期tick: {temporaryPositionExpiryTick}"); + + // 已生成的Pawn + sb.AppendLine($"已生成Pawn数: {SpawnedPawns?.Count ?? 0}"); + if (SpawnedPawns != null && SpawnedPawns.Count > 0) + { + foreach (var spawnedPawn in SpawnedPawns) + { + if (spawnedPawn != null && !spawnedPawn.Destroyed) + { + sb.AppendLine($" • {spawnedPawn.LabelCap} ({spawnedPawn.kindDef?.label ?? "未知"})"); + } + } + } + + // 冷却时间 + sb.AppendLine($"冷却时间剩余: {CooldownTicksRemaining}"); + + return sb.ToString(); + } + + public override void PostExposeData() + { + base.PostExposeData(); + + // 保存自定义跟随位置 + Scribe_Values.Look(ref customFollowPosition, "customFollowPosition"); + Scribe_Values.Look(ref temporaryPositionExpiryTick, "temporaryPositionExpiryTick", -1); + + // 注意:Map不能直接序列化,需要在PostLoadInit中重新获取 + if (Scribe.mode == LoadSaveMode.LoadingVars) + { + customFollowPositionMap = parent?.Map; + } + } + + public override void PostSpawnSetup(bool respawningAfterLoad) + { + base.PostSpawnSetup(respawningAfterLoad); + + // 确保地图引用正确 + if (respawningAfterLoad) + { + customFollowPositionMap = parent?.Map; + + // 如果自定义位置无效,清除它 + if (customFollowPosition.HasValue && + (customFollowPositionMap == null || + !customFollowPosition.Value.InBounds(customFollowPositionMap))) + { + ClearCustomFollowPosition(); + } + } + + // 初始化生产队列缓存 + RefreshProductionQueue(); + } } -} \ No newline at end of file +} diff --git a/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/CompProperties_AutoMechCarrier.cs b/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/CompProperties_AutoMechCarrier.cs index a1fe812..a64ff52 100644 --- a/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/CompProperties_AutoMechCarrier.cs +++ b/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/CompProperties_AutoMechCarrier.cs @@ -12,8 +12,14 @@ namespace ArachnaeSwarm // 如果单位拥有这个Hediff,则停止生产 public HediffDef disableHediff; - // 定义生产队列 - public List productionQueue = new List(); + // 从HediffComp获取的生产队列(通过代码动态设置) + public List DynamicProductionQueue = new List(); + + // 是否启用调试日志 + public bool debugLogging = false; + + // 扫描Hediff并获取生产队列 + public bool ScanHediffsForProductionQueue = true; public CompProperties_AutoMechCarrier() { @@ -28,27 +34,132 @@ namespace ArachnaeSwarm yield return error; } - if (productionQueue.NullOrEmpty()) - { - yield return "CompProperties_AutoMechCarrier must have at least one entry in productionQueue."; - } + // 不再要求必须有生产队列,因为可以通过HediffComp动态添加 + // 生产队列可以在运行时动态设置 } public override void ResolveReferences(ThingDef parentDef) { base.ResolveReferences(parentDef); + // Prevent division by zero if costPerPawn is not set, which the base game AI might try to access. if (costPerPawn <= 0) { costPerPawn = 1; } - // 如果spawnPawnKind为空(因为我们用了新的队列系统), - // 就从队列里取第一个作为“假”值,以防止基类方法在生成Gizmo标签时出错。 - if (spawnPawnKind == null && !productionQueue.NullOrEmpty()) + // 如果spawnPawnKind为空,我们不再设置默认值 + // 因为现在生产队列是动态的 + } + + /// + /// 获取合并后的生产队列 + /// 包括从HediffComp扫描的和动态添加的 + /// + public List GetMergedProductionQueue(Pawn pawn) + { + var queuesToMerge = new List>(); + + // 1. 添加动态生产队列 + if (DynamicProductionQueue != null && DynamicProductionQueue.Count > 0) { - spawnPawnKind = productionQueue[0].pawnKind; + queuesToMerge.Add(DynamicProductionQueue); } + + // 2. 扫描HediffComp获取生产队列 + if (ScanHediffsForProductionQueue && pawn != null && pawn.health != null) + { + var hediffQueues = GetProductionQueueFromHediffs(pawn); + if (hediffQueues != null && hediffQueues.Count > 0) + { + queuesToMerge.Add(hediffQueues); + } + } + + // 合并所有队列 + return HediffCompProperties_ProductionQueue.MergeProductionQueues(queuesToMerge); + } + + /// + /// 从HediffComp获取生产队列 + /// + private List GetProductionQueueFromHediffs(Pawn pawn) + { + var productionQueue = new List(); + + if (pawn == null || pawn.health == null || pawn.health.hediffSet == null) + return productionQueue; + + // 扫描所有Hediff,查找具有HediffComp_ProductionQueue的 + foreach (var hediff in pawn.health.hediffSet.hediffs) + { + if (hediff == null) + continue; + + // 检查Hediff是否包含HediffComp_ProductionQueue + var productionComp = hediff.TryGetComp(); + if (productionComp != null) + { + var queueFromHediff = productionComp.GetAvailableProductionQueue(pawn); + if (queueFromHediff != null && queueFromHediff.Count > 0) + { + productionQueue.AddRange(queueFromHediff); + } + } + } + + return productionQueue; + } + + /// + /// 添加动态生产队列条目 + /// + public void AddDynamicProductionEntry(PawnProductionEntry entry) + { + if (DynamicProductionQueue == null) + DynamicProductionQueue = new List(); + + DynamicProductionQueue.Add(entry); + } + + /// + /// 移除动态生产队列条目 + /// + public bool RemoveDynamicProductionEntry(PawnKindDef pawnKindDef) + { + if (DynamicProductionQueue == null) + return false; + + return DynamicProductionQueue.RemoveAll(entry => entry.pawnKind == pawnKindDef) > 0; + } + + /// + /// 更新动态生产队列条目 + /// + public bool UpdateDynamicProductionEntry(PawnKindDef pawnKindDef, PawnProductionEntry newEntry) + { + if (DynamicProductionQueue == null) + return false; + + for (int i = 0; i < DynamicProductionQueue.Count; i++) + { + if (DynamicProductionQueue[i].pawnKind == pawnKindDef) + { + DynamicProductionQueue[i] = newEntry; + return true; + } + } + + return false; + } + + /// + /// 清除所有动态生产队列 + /// + public void ClearDynamicProductionQueue() + { + if (DynamicProductionQueue != null) + DynamicProductionQueue.Clear(); } } -} \ No newline at end of file +} diff --git a/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/PawnProductionEntry.cs b/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/PawnProductionEntry.cs index b8e8c9e..6d709c0 100644 --- a/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/PawnProductionEntry.cs +++ b/Source/ArachnaeSwarm/Pawn_Comps/ARA_AutoMechCarrier/PawnProductionEntry.cs @@ -1,4 +1,7 @@ +using RimWorld; +using System.Collections.Generic; using Verse; +using System.Linq; namespace ArachnaeSwarm { @@ -19,5 +22,98 @@ namespace ArachnaeSwarm // Optional: specific cost for this entry. If not set, the parent comp's costPerPawn is used. public int? cost; + + // Optional: custom information for display + public string customInfo; + + // Optional: conditions that must be met for this entry to be available + public List conditions; + + // Optional: priority (lower number = higher priority) + public int priority = 0; + + // Optional: weight for random selection (if multiple entries can be produced simultaneously) + public float weight = 1.0f; + + // Optional: whether this entry is enabled (can be toggled) + public bool enabled = true; + + // Optional: tech requirements + public ResearchProjectDef requiredResearch; + + // Optional: required skill level (if parent is a pawn) + public SkillDef requiredSkill; + public int requiredSkillLevel = 0; + + /// + /// 检查所有条件是否满足 + /// + public bool AreConditionsMet(Pawn pawn, out string reason) + { + reason = ""; + + // 检查是否启用 + if (!enabled) + { + reason = "此生产条目已禁用"; + return false; + } + + // 检查科技需求 + if (requiredResearch != null && !requiredResearch.IsFinished) + { + reason = $"需要研究: {requiredResearch.label}"; + return false; + } + + // 检查技能需求 + if (requiredSkill != null && pawn != null && pawn.skills != null) + { + var skill = pawn.skills.GetSkill(requiredSkill); + if (skill == null || skill.Level < requiredSkillLevel) + { + reason = $"需要{requiredSkill.label}技能等级: {requiredSkillLevel}"; + return false; + } + } + + // 检查自定义条件 + if (!conditions.NullOrEmpty()) + { + foreach (var condition in conditions) + { + string conditionReason; + if (!condition.IsMet(out conditionReason)) + { + reason = conditionReason; + return false; + } + } + } + + return true; + } + + /// + /// 复制条目 + /// + public PawnProductionEntry Copy() + { + return new PawnProductionEntry + { + pawnKind = pawnKind, + count = count, + cooldownTicks = cooldownTicks, + cost = cost, + customInfo = customInfo, + conditions = conditions?.ToList(), // 深拷贝条件列表 + priority = priority, + weight = weight, + enabled = enabled, + requiredResearch = requiredResearch, + requiredSkill = requiredSkill, + requiredSkillLevel = requiredSkillLevel + }; + } } -} \ No newline at end of file +}