diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll index b37308f..edb3697 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/JobDefs/ARA_Jobs_Nutrition.xml b/1.6/1.6/Defs/JobDefs/ARA_Jobs_Nutrition.xml new file mode 100644 index 0000000..bef6bf4 --- /dev/null +++ b/1.6/1.6/Defs/JobDefs/ARA_Jobs_Nutrition.xml @@ -0,0 +1,11 @@ + + + + + ARA_Refuel_Nutrition + ArachnaeSwarm.JobDriver_Refuel_Nutrition + 正在为 TargetA 补充营养。 + true + + + \ No newline at end of file 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 b82ef6c..0fd9a36 100644 --- a/1.6/1.6/Defs/ThingDef_Races/ARA_RaceNodeSwarm.xml +++ b/1.6/1.6/Defs/ThingDef_Races/ARA_RaceNodeSwarm.xml @@ -1628,6 +1628,53 @@ + + +
  • HairColor
  • +
  • Melanin
  • +
  • BodyType
  • +
  • Ears
  • +
  • Nose
  • +
  • Voice
  • +
  • Headbone
  • +
  • Head
  • +
  • Jaw
  • +
    + + +
  • EyeColor
  • +
  • Tail
  • +
  • BeardStyle
  • +
  • Fur
  • +
    + + +
  • Furskin
  • +
  • Brow_Heavy
  • +
    + + +
  • Dirtmole
  • +
  • Genie
  • +
  • Hussar
  • +
  • Sanguophage
  • +
  • Neanderthal
  • +
  • Pigskin
  • +
  • Impid
  • +
  • Waster
  • +
  • Yttakin
  • +
  • Highmate
  • +
    + + + + true + + +
  • ARA_InsectJelly
  • +
  • ARA_NutrientPasteMeal
  • +
  • ARA_PheromoneSolvent
  • +
    true
    diff --git a/1.6/1.6/Defs/Thing_building/ARA_Building.xml b/1.6/1.6/Defs/Thing_building/ARA_Building.xml index d0114d4..f856ded 100644 --- a/1.6/1.6/Defs/Thing_building/ARA_Building.xml +++ b/1.6/1.6/Defs/Thing_building/ARA_Building.xml @@ -499,80 +499,7 @@ - - ARA_MorphableResearchBench - - - 以阿拉克涅织域种为核心形成的活体结构,是推进虫群高级研究的必须建筑。该建筑无法建造,只能通过阿拉克涅织域种变形得到。 - ArachnaeSwarm.Building_Morphable - Normal - (2,2) - - ArachnaeSwarm/Building/ARA_MorphableResearchBench - Graphic_Single - CutoutComplex - (2.5,2.5) - - Building - Impassable - false - 0.8 - 0 - ARA_Creep - - 1000 - 2800 - 1.0 - 1.0 - - 2600 - Item - - Laboratory - 0.8 - false - - - -
  • - ARA_InsectCreep - 3 -
  • -
  • - ResearchSpeedFactor -
  • -
  • - - 1.0 - - - 离开织座 - - - 使织域种离开织座,恢复移动状态。 - - ArachnaeSwarm/UI/Abilities/ARA_Ability_Morph -
  • -
  • - - -
  • ARA_InsectJelly
  • - - - 2.0 - false - 虫蜜 - 没有营养 - -
  • - -
  • ARA_NutrientNetworkTower
  • - - -
    -
    - + ARA_SmartThermostat @@ -643,93 +570,4 @@ - - ARA_JellyVat - - 一个阿拉克涅虫族活体组织,可以充分利用活体钜菌的溶解能力,通过消化生物质,来分泌出营养丰富的阿拉克涅虫蜜。 - Building - - ArachnaeSwarm/Building/ARA_JellyVat - Graphic_Single - CutoutComplex - (2.2,2.2) - - (1.6, 0.5, 1.6) - (0,0,-0.1) - - - -
  • ARA_Technology_6GUT
  • -
    - (2,2) - Normal - - 0 - - 150 - 25 - - false - 0 - Building - PassThroughOnly - ARA_Creep - 50 - - 250 - 2800 - 1.0 - - -
  • PlaceWorker_PreventInteractionSpotOverlap
  • -
    - 0.8 - (0,0,-1) - true - ARA_Buildings - 2600 - Item - - Laboratory - 0.8 - - ARA_Creep - -
  • -
  • - - 120000 - 120000 - - -
  • - ARA_InsectJelly - 60 -
  • - - true - -
  • - Biomass - 生物质 - - -
  • MeatRaw
  • -
  • PlantFoodRaw
  • - - -
  • Milk
  • -
  • InsectJelly
  • -
    - - 50 - 30 - true - -
  • - ARA_InsectCreep - 6 -
  • -
    -
    \ No newline at end of file diff --git a/1.6/1.6/Defs/Thing_building/ARA_NutrientNetworkBuilding.xml b/1.6/1.6/Defs/Thing_building/ARA_NutrientNetworkBuilding.xml index 1c4e8e6..cf4cefa 100644 --- a/1.6/1.6/Defs/Thing_building/ARA_NutrientNetworkBuilding.xml +++ b/1.6/1.6/Defs/Thing_building/ARA_NutrientNetworkBuilding.xml @@ -54,22 +54,6 @@ 80 10 0.9 - - - -
  • - -
  • ARA_BioforgeIncubator
  • -
  • ARA_BioforgeIncubator_Thing
  • -
  • ARA_GrowthVat
  • -
  • ARA_MorphableResearchBench
  • -
  • ARANutrientDispenser
  • -
  • ARA_WormholePortal_A
  • -
  • ARA_Acidling_AutoMortar
  • -
  • CatastropheMissileSilo
  • -
  • ARA_AutoSniperCannon
  • - - 80 ArachnaeSwarm/Building/Nutrition_Pie @@ -192,7 +176,7 @@
  • ARA_NutrientNetworkTower
  • - +
  • ARA_InsectCreep 6 @@ -511,4 +495,221 @@
  • + + + ARA_MorphableResearchBench + + + 以阿拉克涅织域种为核心形成的活体结构,是推进虫群高级研究的必须建筑。该建筑无法建造,只能通过阿拉克涅织域种变形得到。 + ArachnaeSwarm.Building_Morphable + Normal + RealtimeOnly + (2,2) + + ArachnaeSwarm/Building/ARA_MorphableResearchBench + Graphic_Single + CutoutComplex + (3,3) + (0, 0, 0.25) + + Building + Impassable + false + 0.8 + 0 + ARA_Creep + + 1000 + 2800 + 1.0 + 1.0 + + 2600 + Item + + Laboratory + 0.8 + false + + + +
  • + ARA_InsectCreep + 3 +
  • +
  • + ResearchSpeedFactor +
  • +
  • + 5.9 + 300 + true + true + (0.5, 0.3, 0.9, 0.5) + BulletShieldGenerator_Reactivate + BulletShield_Ambience + 1 + true + true + true +
  • +
  • + + 1.0 + + + 离开织座 + + + 使织域种离开织座,恢复移动状态。 + + ArachnaeSwarm/UI/Abilities/ARA_Ability_Morph +
  • +
  • + + +
  • ARA_InsectJelly
  • + + + 2.0 + false + 虫蜜 + 没有营养 + +
  • + +
  • ARA_NutrientNetworkTower
  • + + +
    +
    + + + ARA_JellyVat + + 一个阿拉克涅虫族活体组织,可以充分利用活体钜菌的溶解能力,通过消化生物质,来分泌出营养丰富的阿拉克涅虫蜜。 + Building + + ArachnaeSwarm/Building/ARA_JellyVat + Graphic_Single + CutoutComplex + (2.2,2.2) + + (1.6, 0.5, 1.6) + (0,0,-0.1) + + + +
  • ARA_Technology_6GUT
  • +
    + (2,2) + Normal + + 0 + + 150 + 25 + + false + 0 + Building + PassThroughOnly + ARA_Creep + 50 + + 250 + 2800 + 1.0 + + +
  • PlaceWorker_PreventInteractionSpotOverlap
  • +
    + 0.8 + (0,0,-1) + true + ARA_Buildings + 2600 + Item + + Laboratory + 0.8 + + ARA_Creep + +
  • + + +
  • + Biomass + 生物质 + 生物质 + + +
  • MeatRaw
  • +
  • PlantFoodRaw
  • + + +
  • Milk
  • +
  • InsectJelly
  • +
    + + 50 + 0 + true + + true + true + +
  • + 虫蜜 + 虫蜜 + + 100.0 + 0 + true + + + +
  • ARA_InsectJelly
  • + + + + true + true + true + +
  • + 200 + 1 + 2000 + 1 +
  • + + +
  • + + CompRefuelable + + 0.99 +
  • + +
  • + ARA_InsectCreep + 6 +
  • +
    +
    \ No newline at end of file diff --git a/1.6/1.6/Defs/Thing_building/ARA_SwarmTurret.xml b/1.6/1.6/Defs/Thing_building/ARA_SwarmTurret.xml index 6504763..80715f5 100644 --- a/1.6/1.6/Defs/Thing_building/ARA_SwarmTurret.xml +++ b/1.6/1.6/Defs/Thing_building/ARA_SwarmTurret.xml @@ -299,8 +299,9 @@ Heavy
  • -
  • - 100 +
  • + nutrition + 5.0
  • ARA_InsectJelly
  • @@ -451,8 +452,9 @@ Heavy
  • -
  • - 20 +
  • + nutrition + 5.0
  • ARA_InsectJelly
  • @@ -623,8 +625,9 @@ Normal -
  • - 10 +
  • + nutrition + 5.0
  • ARA_InsectJelly
  • diff --git a/1.6/1.6/Defs/WorkGiverDefs/ARA_WorkGivers.xml b/1.6/1.6/Defs/WorkGiverDefs/ARA_WorkGivers.xml new file mode 100644 index 0000000..725e3a7 --- /dev/null +++ b/1.6/1.6/Defs/WorkGiverDefs/ARA_WorkGivers.xml @@ -0,0 +1,14 @@ + + + + ARA_Refuel_Nutrition + + ArachnaeSwarm.WorkGiver_Refuel_Nutrition + Hauling + 60 + 补充 + 补充 + true + false + + \ No newline at end of file diff --git a/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/.suo b/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/.suo index 10cd203..0dc2f96 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 8b315da..c99f45a 100644 --- a/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/DocumentLayout.json +++ b/Source/ArachnaeSwarm/.vs/ArachnaeSwarm/v17/DocumentLayout.json @@ -1,22 +1,29 @@ { "Version": 1, - "WorkspaceRootPath": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\", + "WorkspaceRootPath": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\", "Documents": [ { - "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|e:\\steamlibrary\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\thingcomp_guardianpsyfield.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:thingcomp_guardianpsyfield.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|c:\\steam\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\jobs\\jobdriver_supercarry\\floatmenuoptionprovider_supercarry.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:jobs\\jobdriver_supercarry\\floatmenuoptionprovider_supercarry.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, { - "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\building_comps\\ara_nutrientvat\\building_nutrientvat.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|c:\\steam\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\thing_comps\\ara_thingcomp_guardianpsyfield\\harmony_projectileinterceptor.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:thing_comps\\ara_thingcomp_guardianpsyfield\\harmony_projectileinterceptor.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|c:\\steam\\steamapps\\common\\rimworld\\mods\\arachnaeswarm\\source\\arachnaeswarm\\thing_comps\\ara_thingcomp_guardianpsyfield\\thingcomp_guardianpsyfield.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:thing_comps\\ara_thingcomp_guardianpsyfield\\thingcomp_guardianpsyfield.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\building_comps\\ara_nutrientvat\\building_nutrientvat.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\ara_nutrientvat\\building_nutrientvat.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, { - "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\building_comps\\ara_nutrientnetwork\\compnutrientprovider.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\building_comps\\ara_nutrientnetwork\\compnutrientprovider.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\ara_nutrientnetwork\\compnutrientprovider.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, { - "AbsoluteMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\building_comps\\ara_nutrientnetwork\\complinedrawer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\ara_nutrientnetwork\\complinedrawer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_NutrientNetwork\\CompLineDrawer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" } ], "DocumentGroupContainers": [ @@ -35,23 +42,49 @@ { "$type": "Document", "DocumentIndex": 0, + "Title": "FloatMenuOptionProvider_SuperCarry.cs", + "DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_SuperCarry\\FloatMenuOptionProvider_SuperCarry.cs", + "RelativeDocumentMoniker": "Jobs\\JobDriver_SuperCarry\\FloatMenuOptionProvider_SuperCarry.cs", + "ToolTip": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_SuperCarry\\FloatMenuOptionProvider_SuperCarry.cs", + "RelativeToolTip": "Jobs\\JobDriver_SuperCarry\\FloatMenuOptionProvider_SuperCarry.cs", + "ViewState": "AQIAAAAAAAAAAAAAAADwvwAAAAAAAAAA", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2025-10-04T07:00:14.106Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 1, + "Title": "Harmony_ProjectileInterceptor.cs", + "DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Thing_Comps\\ARA_ThingComp_GuardianPsyField\\Harmony_ProjectileInterceptor.cs", + "RelativeDocumentMoniker": "Thing_Comps\\ARA_ThingComp_GuardianPsyField\\Harmony_ProjectileInterceptor.cs", + "ToolTip": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Thing_Comps\\ARA_ThingComp_GuardianPsyField\\Harmony_ProjectileInterceptor.cs", + "RelativeToolTip": "Thing_Comps\\ARA_ThingComp_GuardianPsyField\\Harmony_ProjectileInterceptor.cs", + "ViewState": "AQIAAAAAAAAAAAAAAADwvwAAAAAAAAAA", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2025-10-04T07:00:14.029Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 2, "Title": "ThingComp_GuardianPsyField.cs", - "DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\ThingComp_GuardianPsyField.cs", - "RelativeDocumentMoniker": "ThingComp_GuardianPsyField.cs", - "ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\ThingComp_GuardianPsyField.cs", - "RelativeToolTip": "ThingComp_GuardianPsyField.cs", - "ViewState": "AgIAAAAAAAAAAAAAAAAAAAoAAAAgAAAAAAAAAA==", + "DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Thing_Comps\\ARA_ThingComp_GuardianPsyField\\ThingComp_GuardianPsyField.cs", + "RelativeDocumentMoniker": "Thing_Comps\\ARA_ThingComp_GuardianPsyField\\ThingComp_GuardianPsyField.cs", + "ToolTip": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Thing_Comps\\ARA_ThingComp_GuardianPsyField\\ThingComp_GuardianPsyField.cs", + "RelativeToolTip": "Thing_Comps\\ARA_ThingComp_GuardianPsyField\\ThingComp_GuardianPsyField.cs", + "ViewState": "AQIAAAAAAAAAAAAAAADwvwAAAAAAAAAA", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "WhenOpened": "2025-10-02T16:24:06.176Z", "EditorCaption": "" }, { "$type": "Document", - "DocumentIndex": 1, + "DocumentIndex": 3, "Title": "Building_NutrientVat.cs", - "DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_NutrientVat\\Building_NutrientVat.cs", + "DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_NutrientVat\\Building_NutrientVat.cs", "RelativeDocumentMoniker": "Building_Comps\\ARA_NutrientVat\\Building_NutrientVat.cs", - "ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_NutrientVat\\Building_NutrientVat.cs", + "ToolTip": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_NutrientVat\\Building_NutrientVat.cs", "RelativeToolTip": "Building_Comps\\ARA_NutrientVat\\Building_NutrientVat.cs", "ViewState": "AgIAAF8AAAAAAAAAAAAswJkBAAANAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", @@ -59,11 +92,11 @@ }, { "$type": "Document", - "DocumentIndex": 2, + "DocumentIndex": 4, "Title": "CompNutrientProvider.cs", - "DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_NutrientNetwork\\CompNutrientProvider.cs", + "DocumentMoniker": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_NutrientNetwork\\CompNutrientProvider.cs", "RelativeDocumentMoniker": "Building_Comps\\ARA_NutrientNetwork\\CompNutrientProvider.cs", - "ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_NutrientNetwork\\CompNutrientProvider.cs", + "ToolTip": "C:\\Steam\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_NutrientNetwork\\CompNutrientProvider.cs", "RelativeToolTip": "Building_Comps\\ARA_NutrientNetwork\\CompNutrientProvider.cs", "ViewState": "AgIAAAAAAAAAAAAAAAAAABkAAAAZAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", @@ -71,12 +104,10 @@ }, { "$type": "Document", - "DocumentIndex": 3, + "DocumentIndex": 5, "Title": "CompLineDrawer.cs", "DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_NutrientNetwork\\CompLineDrawer.cs", - "RelativeDocumentMoniker": "Building_Comps\\ARA_NutrientNetwork\\CompLineDrawer.cs", "ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_NutrientNetwork\\CompLineDrawer.cs", - "RelativeToolTip": "Building_Comps\\ARA_NutrientNetwork\\CompLineDrawer.cs", "ViewState": "AgIAAAAAAAAAAAAAAAAAABkAAAAAAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "WhenOpened": "2025-10-02T15:11:03.083Z" diff --git a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj index 1409dca..06637fc 100644 --- a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj +++ b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj @@ -128,7 +128,6 @@ - @@ -146,6 +145,9 @@ + + + @@ -171,13 +173,13 @@ - - + + - - + + @@ -250,9 +252,9 @@ - - - + + + diff --git a/Source/ArachnaeSwarm/Building_Comps/ARA_NutrientNetwork/CompLineDrawer.cs b/Source/ArachnaeSwarm/Building_Comps/ARA_NutrientNetwork/CompLineDrawer.cs deleted file mode 100644 index f5c7d8a..0000000 --- a/Source/ArachnaeSwarm/Building_Comps/ARA_NutrientNetwork/CompLineDrawer.cs +++ /dev/null @@ -1,172 +0,0 @@ -using RimWorld; -using Verse; -using UnityEngine; -using System.Collections.Generic; -using System.Linq; - -namespace ArachnaeSwarm -{ - public class CompProperties_LineDrawer : CompProperties - { - public List linkableBuildings; - public float maxDistance = 999f; - public string lineTexturePath = "Things/Special/Power/Wire"; - - public CompProperties_LineDrawer() - { - compClass = typeof(CompLineDrawer); - } - } - - public class CompLineDrawer : ThingComp - { - private CompProperties_LineDrawer Props => (CompProperties_LineDrawer)props; - private List linkedBuildings = new List(); - private Material lineMat; - - private Material LineMat - { - get - { - if (lineMat == null) - { - lineMat = MaterialPool.MatFrom(Props.lineTexturePath, ShaderDatabase.Transparent, Color.white); - } - return lineMat; - } - } - - public override void PostSpawnSetup(bool respawningAfterLoad) - { - base.PostSpawnSetup(respawningAfterLoad); - FindAndLinkBuildings(); - } - - public override void CompTick() - { - base.CompTick(); - if (parent.IsHashIntervalTick(120)) - { - FindAndLinkBuildings(); - } - } - - private void FindAndLinkBuildings() - { - int previousCount = linkedBuildings.Count; - - linkedBuildings.Clear(); - if (Props.linkableBuildings.NullOrEmpty()) return; - - var potentialTargets = parent.Map.listerBuildings.allBuildingsColonist.Where(b => - b != parent && - Props.linkableBuildings.Contains(b.def) && - parent.Position.DistanceTo(b.Position) <= Props.maxDistance && - HasLineOfSight(parent, b) // 新增:检查视线 - ); - - linkedBuildings.AddRange(potentialTargets); - - if (linkedBuildings.Count != previousCount) - { - parent.Map.mapDrawer.MapMeshDirty(parent.Position, MapMeshFlagDefOf.Things, true, false); - } - } - - // 修复后的方法:检查两点之间是否有墙体遮挡 - private bool HasLineOfSight(Thing from, Thing to) - { - IntVec3 fromPos = from.Position; - IntVec3 toPos = to.Position; - - // 如果两个建筑在同一位置,直接返回true - if (fromPos == toPos) return true; - - // 使用更兼容的视线检查方法 - if (!GenSight.LineOfSight(fromPos, toPos, parent.Map)) - { - return false; - } - - // 额外检查:确保路径上没有阻挡视线的建筑 - foreach (IntVec3 cell in GetLineCells(fromPos, toPos)) - { - // 跳过起点和终点 - if (cell == fromPos || cell == toPos) continue; - - // 检查该单元格是否有阻挡视线的建筑 - List things = parent.Map.thingGrid.ThingsListAt(cell); - foreach (Thing thing in things) - { - // 如果是建筑且阻挡视线 - if (thing.def.passability == Traversability.Impassable && - thing.def.category == ThingCategory.Building && - !IsPassableBuilding(thing.def)) // 排除可通行的建筑类型 - { - return false; - } - } - } - - return true; - } - - // 获取两点之间的直线上的所有单元格 - private IEnumerable GetLineCells(IntVec3 start, IntVec3 end) - { - // 使用简单的Bresenham直线算法 - int x0 = start.x; - int y0 = start.z; - int x1 = end.x; - int y1 = end.z; - - int dx = Mathf.Abs(x1 - x0); - int dy = Mathf.Abs(y1 - y0); - int sx = x0 < x1 ? 1 : -1; - int sy = y0 < y1 ? 1 : -1; - int err = dx - dy; - - while (true) - { - yield return new IntVec3(x0, 0, y0); - - if (x0 == x1 && y0 == y1) break; - - int e2 = 2 * err; - if (e2 > -dy) - { - err -= dy; - x0 += sx; - } - if (e2 < dx) - { - err += dx; - y0 += sy; - } - } - } - - // 检查建筑类型是否允许管线通过 - private bool IsPassableBuilding(ThingDef def) - { - // 门、栅栏门等可通行的建筑不算阻挡 - return def.IsDoor || - def.passability == Traversability.PassThroughOnly || - def.passability == Traversability.Standable; - } - - public override void PostPrintOnto(SectionLayer layer) - { - base.PostPrintOnto(layer); - foreach (var building in linkedBuildings) - { - Vector3 center = (this.parent.TrueCenter() + this.parent.Graphic.DrawOffset(this.parent.Rotation) + building.TrueCenter() + building.Graphic.DrawOffset(building.Rotation)) / 2f; - center.y = AltitudeLayer.SmallWire.AltitudeFor(); - Vector3 v = building.TrueCenter() - this.parent.TrueCenter(); - Vector2 size = new Vector2(1f, v.MagnitudeHorizontal()); - float rot = v.AngleFlat(); - Printer_Plane.PrintPlane(layer, center, size, this.LineMat, rot); - } - } - } -} diff --git a/Source/ArachnaeSwarm/Building_Comps/ARA_NutrientNetwork/CompNutrientProvider.cs b/Source/ArachnaeSwarm/Building_Comps/ARA_NutrientNetwork/CompNutrientProvider.cs index ea11cb1..3043bd1 100644 --- a/Source/ArachnaeSwarm/Building_Comps/ARA_NutrientNetwork/CompNutrientProvider.cs +++ b/Source/ArachnaeSwarm/Building_Comps/ARA_NutrientNetwork/CompNutrientProvider.cs @@ -11,6 +11,19 @@ namespace ArachnaeSwarm { private CompRefuelableNutrition selfRefuelable; private new CompProperties_NutrientProvider Props => (CompProperties_NutrientProvider)props; + private Material lineMat; + + private Material LineMat + { + get + { + if (lineMat == null) + { + lineMat = MaterialPool.MatFrom(Props.lineTexturePath, ShaderDatabase.Transparent, Color.white); + } + return lineMat; + } + } public override void PostSpawnSetup(bool respawningAfterLoad) { @@ -102,5 +115,20 @@ namespace ArachnaeSwarm } return comp.TargetFuelLevel; } + + public override void PostPrintOnto(SectionLayer layer) + { + base.PostPrintOnto(layer); + foreach (var building in LinkedBuildings) + { + if (building == null) continue; + Vector3 center = (this.parent.TrueCenter() + this.parent.Graphic.DrawOffset(this.parent.Rotation) + building.TrueCenter() + building.Graphic.DrawOffset(building.Rotation)) / 2f; + center.y = AltitudeLayer.SmallWire.AltitudeFor(); + Vector3 v = building.TrueCenter() - this.parent.TrueCenter(); + Vector2 size = new Vector2(1f, v.MagnitudeHorizontal()); + float rot = v.AngleFlat(); + Printer_Plane.PrintPlane(layer, center, size, this.LineMat, rot); + } + } } } \ No newline at end of file diff --git a/Source/ArachnaeSwarm/Building_Comps/ARA_NutrientNetwork/CompProperties_NutrientProvider.cs b/Source/ArachnaeSwarm/Building_Comps/ARA_NutrientNetwork/CompProperties_NutrientProvider.cs index 34a1764..7a47931 100644 --- a/Source/ArachnaeSwarm/Building_Comps/ARA_NutrientNetwork/CompProperties_NutrientProvider.cs +++ b/Source/ArachnaeSwarm/Building_Comps/ARA_NutrientNetwork/CompProperties_NutrientProvider.cs @@ -5,6 +5,8 @@ namespace ArachnaeSwarm public class CompProperties_NutrientProvider : CompProperties_Facility { public float maxEfficiency = 0.9f; + public string lineTexturePath = "Things/Special/Power/Wire"; + public CompProperties_NutrientProvider() { compClass = typeof(CompNutrientProvider); diff --git a/Source/ArachnaeSwarm/Building_Comps/CompAutoEjector.cs b/Source/ArachnaeSwarm/Building_Comps/CompAutoEjector.cs new file mode 100644 index 0000000..411fa1a --- /dev/null +++ b/Source/ArachnaeSwarm/Building_Comps/CompAutoEjector.cs @@ -0,0 +1,58 @@ +using System; +using System.Linq; +using RimWorld; +using Verse; + +namespace ArachnaeSwarm +{ + // Properties for the new component + public class CompProperties_AutoEjector : CompProperties + { + public int checkInterval = 250; // Check roughly every 4 seconds + public float ejectAtPercent = 1.0f; // Eject when fuel reaches this percentage of max capacity (1.0 = 100%) + public Type targetComp = typeof(CompRefuelable); // The specific CompRefuelable class to target, can be overridden in XML + + public CompProperties_AutoEjector() + { + this.compClass = typeof(CompAutoEjector); + } + } + + // The component logic + public class CompAutoEjector : ThingComp + { + private CompProperties_AutoEjector Props => (CompProperties_AutoEjector)this.props; + private CompRefuelable refuelableComp; + + public override void PostSpawnSetup(bool respawningAfterLoad) + { + base.PostSpawnSetup(respawningAfterLoad); + + // Find the specific refuelable component specified in XML + this.refuelableComp = this.parent.GetComps() + .FirstOrDefault(comp => comp.GetType() == this.Props.targetComp); + + if (this.refuelableComp == null) + { + Log.Warning($"[ArachnaeSwarm] CompAutoEjector on {parent.def.defName} could not find a CompRefuelable of type '{this.Props.targetComp.FullName}' to monitor."); + } + } + + public override void CompTick() + { + base.CompTick(); + + // Check if we have a valid refuelable comp and it's time to check + if (this.refuelableComp != null && + this.parent.IsHashIntervalTick(this.Props.checkInterval)) + { + // Check if fuel has reached or exceeded the configured percentage of the MAX capacity + if (this.refuelableComp.FuelPercentOfMax >= this.Props.ejectAtPercent) + { + // Call the public EjectFuel() method. + this.refuelableComp.EjectFuel(); + } + } + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/Building_Comps/CompRefuelableNutrition.cs b/Source/ArachnaeSwarm/Building_Comps/CompRefuelableNutrition.cs index 3d0283c..e9e153f 100644 --- a/Source/ArachnaeSwarm/Building_Comps/CompRefuelableNutrition.cs +++ b/Source/ArachnaeSwarm/Building_Comps/CompRefuelableNutrition.cs @@ -63,10 +63,7 @@ namespace ArachnaeSwarm fuelNeeded = TargetFuelLevel - Fuel; } - if (totalNutritionGained > 0 && Props.fuelGizmoLabel != null) - { - Messages.Message("MessageRefueled".Translate(parent.LabelShort, totalNutritionGained.ToString("0.##"), Props.fuelGizmoLabel), parent, MessageTypeDefOf.PositiveEvent); - } + // Let the job driver handle the message. This component should only handle logic. } public void ReceiveFuel(float amount) diff --git a/Source/ArachnaeSwarm/Building_Comps/WULA_MutiFuelSpawner/CompRefuelableWithKey.cs b/Source/ArachnaeSwarm/Building_Comps/WULA_MutiFuelSpawner/CompRefuelableWithKey.cs index 39e4107..388ebda 100644 --- a/Source/ArachnaeSwarm/Building_Comps/WULA_MutiFuelSpawner/CompRefuelableWithKey.cs +++ b/Source/ArachnaeSwarm/Building_Comps/WULA_MutiFuelSpawner/CompRefuelableWithKey.cs @@ -1,5 +1,7 @@ using RimWorld; using Verse; +using System.Reflection; +using HarmonyLib; namespace ArachnaeSwarm { @@ -17,6 +19,36 @@ namespace ArachnaeSwarm { public new CompProperties_RefuelableWithKey Props => (CompProperties_RefuelableWithKey)props; + public override void PostExposeData() + { + string prefix = Props.saveKeysPrefix; + if (prefix.NullOrEmpty()) + { + Log.ErrorOnce($"CompRefuelableWithKey on {parent.def.defName} has a null or empty saveKeysPrefix. Defaulting to standard save.", GetHashCode()); + base.PostExposeData(); + return; + } + + FieldInfo fuelField = AccessTools.Field(typeof(CompRefuelable), "fuel"); + FieldInfo configuredTargetFuelLevelField = AccessTools.Field(typeof(CompRefuelable), "configuredTargetFuelLevel"); + FieldInfo allowAutoRefuelField = AccessTools.Field(typeof(CompRefuelable), "allowAutoRefuel"); + + float currentFuel = (float)fuelField.GetValue(this); + float currentConfiguredLevel = (float)configuredTargetFuelLevelField.GetValue(this); + bool currentAllowAuto = (bool)allowAutoRefuelField.GetValue(this); + + Scribe_Values.Look(ref currentFuel, prefix + "_fuel", 0f); + Scribe_Values.Look(ref currentConfiguredLevel, prefix + "_configuredTargetFuelLevel", -1f); + Scribe_Values.Look(ref currentAllowAuto, prefix + "_allowAutoRefuel", true); + + if (Scribe.mode == LoadSaveMode.LoadingVars) + { + fuelField.SetValue(this, currentFuel); + configuredTargetFuelLevelField.SetValue(this, currentConfiguredLevel); + allowAutoRefuelField.SetValue(this, currentAllowAuto); + } + } + public new void Notify_UsedThisTick() { if (Props.consumeFuelOnlyWhenUsed) diff --git a/Source/ArachnaeSwarm/JobDriver_CarryPrisonerToNutrientVat.cs b/Source/ArachnaeSwarm/Jobs/JobDriver_CarryPrisonerToNutrientVat.cs similarity index 100% rename from Source/ArachnaeSwarm/JobDriver_CarryPrisonerToNutrientVat.cs rename to Source/ArachnaeSwarm/Jobs/JobDriver_CarryPrisonerToNutrientVat.cs diff --git a/Source/ArachnaeSwarm/Jobs/JobDriver_Refuel_Nutrition.cs b/Source/ArachnaeSwarm/Jobs/JobDriver_Refuel_Nutrition.cs new file mode 100644 index 0000000..f048094 --- /dev/null +++ b/Source/ArachnaeSwarm/Jobs/JobDriver_Refuel_Nutrition.cs @@ -0,0 +1,88 @@ +using System.Collections.Generic; +using RimWorld; +using Verse; +using Verse.AI; + +namespace ArachnaeSwarm +{ + public class JobDriver_Refuel_Nutrition : JobDriver + { + private const TargetIndex RefuelableInd = TargetIndex.A; + private const TargetIndex FuelInd = TargetIndex.B; + private const int RefuelingDuration = 240; + + protected Thing Refuelable => job.GetTarget(RefuelableInd).Thing; + + // --- KEY CHANGE HERE --- + // We specifically target CompRefuelableNutrition and its children. + protected CompRefuelableNutrition RefuelableComp => Refuelable.TryGetComp(); + + protected Thing Fuel => job.GetTarget(FuelInd).Thing; + + public override bool TryMakePreToilReservations(bool errorOnFailed) + { + if (pawn.Reserve(Refuelable, job, 1, -1, null, errorOnFailed)) + { + return pawn.Reserve(Fuel, job, 1, -1, null, errorOnFailed); + } + return false; + } + + protected override IEnumerable MakeNewToils() + { + this.FailOnDespawnedNullOrForbidden(RefuelableInd); + AddEndCondition(() => !RefuelableComp.IsFull ? JobCondition.Ongoing : JobCondition.Succeeded); + AddFailCondition(() => !job.playerForced && !RefuelableComp.ShouldAutoRefuelNowIgnoringFuelPct); + AddFailCondition(() => !RefuelableComp.allowAutoRefuel && !job.playerForced); + + yield return Toils_General.DoAtomic(delegate + { + job.count = RefuelableComp.GetFuelCountToFullyRefuel(); + }); + + Toil reserveFuel = Toils_Reserve.Reserve(FuelInd); + yield return reserveFuel; + yield return Toils_Goto.GotoThing(FuelInd, PathEndMode.ClosestTouch) + .FailOnDespawnedNullOrForbidden(FuelInd) + .FailOnSomeonePhysicallyInteracting(FuelInd); + yield return Toils_Haul.StartCarryThing(FuelInd, putRemainderInQueue: false, subtractNumTakenFromJobCount: true) + .FailOnDestroyedNullOrForbidden(FuelInd); + yield return Toils_Haul.CheckForGetOpportunityDuplicate(reserveFuel, FuelInd, TargetIndex.None, takeFromValidStorage: true); + yield return Toils_Goto.GotoThing(RefuelableInd, PathEndMode.Touch); + yield return Toils_General.Wait(RefuelingDuration) + .FailOnDestroyedNullOrForbidden(FuelInd) + .FailOnDestroyedNullOrForbidden(RefuelableInd) + .FailOnCannotTouch(RefuelableInd, PathEndMode.Touch) + .WithProgressBarToilDelay(RefuelableInd); + + // Use our custom Refuel toil for CompRefuelableNutrition + yield return FinalizeRefueling_Nutrition(); + } + + // Custom Finalize Toil that uses the specific Refuel method from CompRefuelableNutrition + public Toil FinalizeRefueling_Nutrition() + { + Toil toil = new Toil(); + toil.initAction = delegate() + { + Pawn actor = toil.GetActor(); + Job curJob = actor.jobs.curJob; + Thing refuelableThing = curJob.GetTarget(RefuelableInd).Thing; + CompRefuelableNutrition refuelableComp = refuelableThing.TryGetComp(); + + if (actor.carryTracker.CarriedThing == null) + { + Log.Error(actor + " is not carrying anything to refuel with."); + // The correct way to end the job from within a Toil's action. + actor.jobs.EndCurrentJob(JobCondition.Incompletable); + return; + } + + // Call the specific Refuel method from our custom component + refuelableComp.Refuel(new List { actor.carryTracker.CarriedThing }); + }; + toil.defaultCompleteMode = ToilCompleteMode.Instant; + return toil; + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/FloatMenuOptionProvider_SuperCarry.cs b/Source/ArachnaeSwarm/Jobs/JobDriver_SuperCarry/FloatMenuOptionProvider_SuperCarry.cs similarity index 100% rename from Source/ArachnaeSwarm/FloatMenuOptionProvider_SuperCarry.cs rename to Source/ArachnaeSwarm/Jobs/JobDriver_SuperCarry/FloatMenuOptionProvider_SuperCarry.cs diff --git a/Source/ArachnaeSwarm/JobDriver_SuperCarry.cs b/Source/ArachnaeSwarm/Jobs/JobDriver_SuperCarry/JobDriver_SuperCarry.cs similarity index 100% rename from Source/ArachnaeSwarm/JobDriver_SuperCarry.cs rename to Source/ArachnaeSwarm/Jobs/JobDriver_SuperCarry/JobDriver_SuperCarry.cs diff --git a/Source/ArachnaeSwarm/SuperCarryExtension.cs b/Source/ArachnaeSwarm/Jobs/JobDriver_SuperCarry/SuperCarryExtension.cs similarity index 100% rename from Source/ArachnaeSwarm/SuperCarryExtension.cs rename to Source/ArachnaeSwarm/Jobs/JobDriver_SuperCarry/SuperCarryExtension.cs diff --git a/Source/ArachnaeSwarm/Harmony_ProjectileInterceptor.cs b/Source/ArachnaeSwarm/Thing_Comps/ARA_ThingComp_GuardianPsyField/Harmony_ProjectileInterceptor.cs similarity index 100% rename from Source/ArachnaeSwarm/Harmony_ProjectileInterceptor.cs rename to Source/ArachnaeSwarm/Thing_Comps/ARA_ThingComp_GuardianPsyField/Harmony_ProjectileInterceptor.cs diff --git a/Source/ArachnaeSwarm/Hediff_DynamicInterceptor.cs b/Source/ArachnaeSwarm/Thing_Comps/ARA_ThingComp_GuardianPsyField/Hediff_DynamicInterceptor.cs similarity index 100% rename from Source/ArachnaeSwarm/Hediff_DynamicInterceptor.cs rename to Source/ArachnaeSwarm/Thing_Comps/ARA_ThingComp_GuardianPsyField/Hediff_DynamicInterceptor.cs diff --git a/Source/ArachnaeSwarm/ThingComp_GuardianPsyField.cs b/Source/ArachnaeSwarm/Thing_Comps/ARA_ThingComp_GuardianPsyField/ThingComp_GuardianPsyField.cs similarity index 100% rename from Source/ArachnaeSwarm/ThingComp_GuardianPsyField.cs rename to Source/ArachnaeSwarm/Thing_Comps/ARA_ThingComp_GuardianPsyField/ThingComp_GuardianPsyField.cs diff --git a/Source/ArachnaeSwarm/WorkGivers/WorkGiver_Refuel_Nutrition.cs b/Source/ArachnaeSwarm/WorkGivers/WorkGiver_Refuel_Nutrition.cs new file mode 100644 index 0000000..215efd5 --- /dev/null +++ b/Source/ArachnaeSwarm/WorkGivers/WorkGiver_Refuel_Nutrition.cs @@ -0,0 +1,70 @@ +using System.Collections.Generic; +using System.Linq; +using RimWorld; +using Verse; +using Verse.AI; + +namespace ArachnaeSwarm +{ + public class WorkGiver_Refuel_Nutrition : WorkGiver_Scanner + { + public override ThingRequest PotentialWorkThingRequest => ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial); + + public override PathEndMode PathEndMode => PathEndMode.Touch; + + public override IEnumerable PotentialWorkThingsGlobal(Pawn pawn) + { + // Find all buildings that have our special component. + return pawn.Map.listerBuildings.allBuildingsColonist.Where(b => + b.GetComp() != null); + } + + public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) + { + var building = t as Building; + if (building == null) return false; + + // --- KEY CHANGE HERE --- + // Target the specific nutrition component + var refuelableComp = building.GetComp(); + if (refuelableComp == null || refuelableComp.IsFull) return false; + + if (!refuelableComp.ShouldAutoRefuelNow && !forced) return false; + + if (building.IsForbidden(pawn) || !pawn.CanReserve(building, 1, -1, null, forced)) return false; + + var fuel = FindBestFuel(pawn, refuelableComp); + if (fuel == null) + { + JobFailReason.Is("NoFuelToRefuel".Translate(refuelableComp.Props.fuelFilter.Summary)); + return false; + } + + return true; + } + + public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) + { + var building = t as Building; + var refuelableComp = building.GetComp(); + var fuel = FindBestFuel(pawn, refuelableComp); + + // Return our custom Job + return new Job(DefDatabase.GetNamed("ARA_Refuel_Nutrition"), building, fuel); + } + + private Thing FindBestFuel(Pawn pawn, CompRefuelable refuelable) + { + var fuelFilter = refuelable.Props.fuelFilter; + return GenClosest.ClosestThingReachable( + pawn.Position, + pawn.Map, + ThingRequest.ForGroup(ThingRequestGroup.HaulableEver), + PathEndMode.ClosestTouch, + TraverseParms.For(pawn), + 9999f, + thing => !thing.IsForbidden(pawn) && fuelFilter.Allows(thing) && pawn.CanReserve(thing) + ); + } + } +} \ No newline at end of file diff --git a/CatastropheMissileSilo_Implementation_Plan.md b/Source/Documents/CatastropheMissileSilo_Implementation_Plan.md similarity index 100% rename from CatastropheMissileSilo_Implementation_Plan.md rename to Source/Documents/CatastropheMissileSilo_Implementation_Plan.md diff --git a/Railgun_System_Documentation.md b/Source/Documents/Railgun_System_Documentation.md similarity index 100% rename from Railgun_System_Documentation.md rename to Source/Documents/Railgun_System_Documentation.md