This commit is contained in:
Tourswen
2025-12-18 00:44:50 +08:00
parent c686546abb
commit 3f73c7024f
50 changed files with 2258 additions and 1002 deletions

View File

@@ -1,7 +1,148 @@
{
"Version": 1,
"WorkspaceRootPath": "D:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\",
"Documents": [],
"WorkspaceRootPath": "E:\\SteamLibrary\\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\\building_comps\\ara_buildingterrainspawn\\compdelayedterrainspawn.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\ara_buildingterrainspawn\\compdelayedterrainspawn.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\\needs\\need_honeyproduction.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:needs\\need_honeyproduction.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\\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:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\ara_hediffdefof.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:ara_hediffdefof.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\\workgivers\\workgiver_refuel_nutrition.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:workgivers\\workgiver_refuel_nutrition.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\\jobs\\jobdriver_feedwithhoney\\jobdriver_feedwithhoney.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:jobs\\jobdriver_feedwithhoney\\jobdriver_feedwithhoney.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\\workgivers\\workgiver_extracthoney.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:workgivers\\workgiver_extracthoney.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\\workgivers\\workgiver_stripchitin.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:workgivers\\workgiver_stripchitin.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\\jobs\\jobdriver_feedwithhoney\\jobdriver_extracthoney.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:jobs\\jobdriver_feedwithhoney\\jobdriver_extracthoney.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\\jobs\\jobdriver_feedwithhoney\\thinknode_jobgiver_extracthoney.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:jobs\\jobdriver_feedwithhoney\\thinknode_jobgiver_extracthoney.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\\jobs\\jobdriver_swarmmaintain\\jobdriver_swarmmaintain.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:jobs\\jobdriver_swarmmaintain\\jobdriver_swarmmaintain.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\\verbs\\cleave\\compcleave.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:verbs\\cleave\\compcleave.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_swarmmaintenance\\comp_swarmmaintenance.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\ara_swarmmaintenance\\comp_swarmmaintenance.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\\needs\\need_chitinarmor.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:needs\\need_chitinarmor.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\\workgivers\\workgiver_swarmmaintain.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:workgivers\\workgiver_swarmmaintain.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\\buildings\\building_dormancyvat\\building_dormancyvat.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:buildings\\building_dormancyvat\\building_dormancyvat.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\\buildings\\building_researchblueprintreader\\building_researchblueprintreader.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:buildings\\building_researchblueprintreader\\building_researchblueprintreader.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\\roomrole\\roomroleworker_incubator.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:roomrole\\roomroleworker_incubator.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\\jobs\\jobdriver_stripchitin\\jobdriver_stripchitin.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:jobs\\jobdriver_stripchitin\\jobdriver_stripchitin.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\\jobs\\jobdriver_stripchitin\\compproperties_chitinstripping.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:jobs\\jobdriver_stripchitin\\compproperties_chitinstripping.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\\jobs\\jobdriver_stripchitin\\comp_chitinstripping.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:jobs\\jobdriver_stripchitin\\comp_chitinstripping.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\\verbs\\verb_shootselfunderfoot.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:verbs\\verb_shootselfunderfoot.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\\hediffs\\ara_hediffcomp_topturret\\hediffcomp_topturret.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:hediffs\\ara_hediffcomp_topturret\\hediffcomp_topturret.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_compinteractiveproducer\\compresearchproducer.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\ara_compinteractiveproducer\\compresearchproducer.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_corpseconverter\\compcorpseconverter.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\ara_corpseconverter\\compcorpseconverter.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_corpseconverter\\compproperties_corpseconverter.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\ara_corpseconverter\\compproperties_corpseconverter.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_terrainchanger\\compterrainchanger.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\ara_terrainchanger\\compterrainchanger.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_terrainchanger\\compproperties_terrainchanger.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\ara_terrainchanger\\compproperties_terrainchanger.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\\wula_mutifuelspawner\\comprefuelablenutrition_withkey.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:building_comps\\wula_mutifuelspawner\\comprefuelablenutrition_withkey.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\\buildings\\building_ootheca\\compproperties_incubatordata.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:buildings\\building_ootheca\\compproperties_incubatordata.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\\buildings\\building_ootheca\\oothecaincubatorextension.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:buildings\\building_ootheca\\oothecaincubatorextension.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\\buildings\\building_ootheca\\building_ootheca.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:buildings\\building_ootheca\\building_ootheca.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\\buildings\\building_equipmentootheca\\compproperties_equipmentincubatordata.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:buildings\\building_equipmentootheca\\compproperties_equipmentincubatordata.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\\buildings\\building_equipmentootheca\\building_equipmentootheca.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{EAE0DB6B-E282-C812-7F5A-6D13E9D24581}|ArachnaeSwarm.csproj|solutionrelative:buildings\\building_equipmentootheca\\building_equipmentootheca.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_Building_RefuelingVat\\Building_RefuelingVat.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:Building_Comps\\ARA_Building_RefuelingVat\\Building_RefuelingVat.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
}
],
"DocumentGroupContainers": [
{
"Orientation": 0,
@@ -9,11 +150,433 @@
"DocumentGroups": [
{
"DockedWidth": 200,
"SelectedChildIndex": -1,
"SelectedChildIndex": 1,
"Children": [
{
"$type": "Bookmark",
"Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}"
},
{
"$type": "Document",
"DocumentIndex": 0,
"Title": "CompDelayedTerrainSpawn.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_BuildingTerrainSpawn\\CompDelayedTerrainSpawn.cs",
"RelativeDocumentMoniker": "Building_Comps\\ARA_BuildingTerrainSpawn\\CompDelayedTerrainSpawn.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_BuildingTerrainSpawn\\CompDelayedTerrainSpawn.cs",
"RelativeToolTip": "Building_Comps\\ARA_BuildingTerrainSpawn\\CompDelayedTerrainSpawn.cs",
"ViewState": "AgIAACMAAAAAAAAAAAAQwDoAAAAJAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-17T15:47:19.767Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 4,
"Title": "WorkGiver_Refuel_Nutrition.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\WorkGivers\\WorkGiver_Refuel_Nutrition.cs",
"RelativeDocumentMoniker": "WorkGivers\\WorkGiver_Refuel_Nutrition.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\WorkGivers\\WorkGiver_Refuel_Nutrition.cs",
"RelativeToolTip": "WorkGivers\\WorkGiver_Refuel_Nutrition.cs",
"ViewState": "AgIAAAAAAAAAAAAAAADwvwAAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-17T13:59:44.439Z"
},
{
"$type": "Document",
"DocumentIndex": 2,
"Title": "WorkGiver_FeedWithHoney.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\WorkGivers\\WorkGiver_FeedWithHoney.cs",
"RelativeDocumentMoniker": "WorkGivers\\WorkGiver_FeedWithHoney.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\WorkGivers\\WorkGiver_FeedWithHoney.cs",
"RelativeToolTip": "WorkGivers\\WorkGiver_FeedWithHoney.cs",
"ViewState": "AgIAAB0AAAAAAAAAAAAQwD0AAAAQAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-17T13:59:28.915Z"
},
{
"$type": "Document",
"DocumentIndex": 7,
"Title": "WorkGiver_StripChitin.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\WorkGivers\\WorkGiver_StripChitin.cs",
"RelativeDocumentMoniker": "WorkGivers\\WorkGiver_StripChitin.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\WorkGivers\\WorkGiver_StripChitin.cs",
"RelativeToolTip": "WorkGivers\\WorkGiver_StripChitin.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAABMAAAAZAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-17T13:33:53.307Z"
},
{
"$type": "Document",
"DocumentIndex": 6,
"Title": "WorkGiver_ExtractHoney.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\WorkGivers\\WorkGiver_ExtractHoney.cs",
"RelativeDocumentMoniker": "WorkGivers\\WorkGiver_ExtractHoney.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\WorkGivers\\WorkGiver_ExtractHoney.cs",
"RelativeToolTip": "WorkGivers\\WorkGiver_ExtractHoney.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAgwB0AAAAyAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-17T13:33:29.75Z"
},
{
"$type": "Document",
"DocumentIndex": 3,
"Title": "ARA_HediffDefOf.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\ARA_HediffDefOf.cs",
"RelativeDocumentMoniker": "ARA_HediffDefOf.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\ARA_HediffDefOf.cs",
"RelativeToolTip": "ARA_HediffDefOf.cs",
"ViewState": "AgIAAAAAAAAAAAAAAADwvxIAAAAkAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-15T17:32:18.493Z"
},
{
"$type": "Document",
"DocumentIndex": 1,
"Title": "Need_HoneyProduction.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Needs\\Need_HoneyProduction.cs",
"RelativeDocumentMoniker": "Needs\\Need_HoneyProduction.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Needs\\Need_HoneyProduction.cs",
"RelativeToolTip": "Needs\\Need_HoneyProduction.cs",
"ViewState": "AgIAAGIAAAAAAAAAAAAkwG4AAAAJAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-17T13:17:51.898Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 8,
"Title": "JobDriver_ExtractHoney.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_FeedWithHoney\\JobDriver_ExtractHoney.cs",
"RelativeDocumentMoniker": "Jobs\\JobDriver_FeedWithHoney\\JobDriver_ExtractHoney.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_FeedWithHoney\\JobDriver_ExtractHoney.cs",
"RelativeToolTip": "Jobs\\JobDriver_FeedWithHoney\\JobDriver_ExtractHoney.cs",
"ViewState": "AgIAAA8AAAAAAAAAAAAAwCYAAAAlAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-17T13:26:42.845Z"
},
{
"$type": "Document",
"DocumentIndex": 9,
"Title": "ThinkNode_JobGiver_ExtractHoney.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_FeedWithHoney\\ThinkNode_JobGiver_ExtractHoney.cs",
"RelativeDocumentMoniker": "Jobs\\JobDriver_FeedWithHoney\\ThinkNode_JobGiver_ExtractHoney.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_FeedWithHoney\\ThinkNode_JobGiver_ExtractHoney.cs",
"RelativeToolTip": "Jobs\\JobDriver_FeedWithHoney\\ThinkNode_JobGiver_ExtractHoney.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAABQAAAAcAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-17T13:25:27.255Z"
},
{
"$type": "Document",
"DocumentIndex": 10,
"Title": "JobDriver_SwarmMaintain.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_SwarmMaintain\\JobDriver_SwarmMaintain.cs",
"RelativeDocumentMoniker": "Jobs\\JobDriver_SwarmMaintain\\JobDriver_SwarmMaintain.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_SwarmMaintain\\JobDriver_SwarmMaintain.cs",
"RelativeToolTip": "Jobs\\JobDriver_SwarmMaintain\\JobDriver_SwarmMaintain.cs",
"ViewState": "AgIAAAAAAAAAAAAAAADwvxcAAAAJAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-17T13:32:29.359Z"
},
{
"$type": "Document",
"DocumentIndex": 5,
"Title": "JobDriver_FeedWithHoney.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_FeedWithHoney\\JobDriver_FeedWithHoney.cs",
"RelativeDocumentMoniker": "Jobs\\JobDriver_FeedWithHoney\\JobDriver_FeedWithHoney.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_FeedWithHoney\\JobDriver_FeedWithHoney.cs",
"RelativeToolTip": "Jobs\\JobDriver_FeedWithHoney\\JobDriver_FeedWithHoney.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAgAAAAoAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-17T13:43:47.266Z"
},
{
"$type": "Document",
"DocumentIndex": 11,
"Title": "CompCleave.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Verbs\\Cleave\\CompCleave.cs",
"RelativeDocumentMoniker": "Verbs\\Cleave\\CompCleave.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Verbs\\Cleave\\CompCleave.cs",
"RelativeToolTip": "Verbs\\Cleave\\CompCleave.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAABEAAAAkAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-17T13:40:25.528Z"
},
{
"$type": "Document",
"DocumentIndex": 12,
"Title": "Comp_SwarmMaintenance.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_SwarmMaintenance\\Comp_SwarmMaintenance.cs",
"RelativeDocumentMoniker": "Building_Comps\\ARA_SwarmMaintenance\\Comp_SwarmMaintenance.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_SwarmMaintenance\\Comp_SwarmMaintenance.cs",
"RelativeToolTip": "Building_Comps\\ARA_SwarmMaintenance\\Comp_SwarmMaintenance.cs",
"ViewState": "AgIAAKYAAAAAAAAAAAAQwH0AAAAQAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-17T13:35:29.771Z"
},
{
"$type": "Document",
"DocumentIndex": 13,
"Title": "Need_ChitinArmor.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Needs\\Need_ChitinArmor.cs",
"RelativeDocumentMoniker": "Needs\\Need_ChitinArmor.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Needs\\Need_ChitinArmor.cs",
"RelativeToolTip": "Needs\\Need_ChitinArmor.cs",
"ViewState": "AgIAAAMAAAAAAAAAAADwvwAAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-17T13:23:16.771Z"
},
{
"$type": "Document",
"DocumentIndex": 14,
"Title": "WorkGiver_SwarmMaintain.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\WorkGivers\\WorkGiver_SwarmMaintain.cs",
"RelativeDocumentMoniker": "WorkGivers\\WorkGiver_SwarmMaintain.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\WorkGivers\\WorkGiver_SwarmMaintain.cs",
"RelativeToolTip": "WorkGivers\\WorkGiver_SwarmMaintain.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAF0AAAAcAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-17T13:13:35.358Z"
},
{
"$type": "Document",
"DocumentIndex": 15,
"Title": "Building_DormancyVat.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_DormancyVat\\Building_DormancyVat.cs",
"RelativeDocumentMoniker": "Buildings\\Building_DormancyVat\\Building_DormancyVat.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_DormancyVat\\Building_DormancyVat.cs",
"RelativeToolTip": "Buildings\\Building_DormancyVat\\Building_DormancyVat.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAOcAAAAjAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-17T11:50:41.189Z"
},
{
"$type": "Document",
"DocumentIndex": 16,
"Title": "Building_ResearchBlueprintReader.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_ResearchBlueprintReader\\Building_ResearchBlueprintReader.cs",
"RelativeDocumentMoniker": "Buildings\\Building_ResearchBlueprintReader\\Building_ResearchBlueprintReader.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_ResearchBlueprintReader\\Building_ResearchBlueprintReader.cs",
"RelativeToolTip": "Buildings\\Building_ResearchBlueprintReader\\Building_ResearchBlueprintReader.cs",
"ViewState": "AgIAAPQAAAAAAAAAAAAywAoBAABrAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-17T10:38:40.669Z"
},
{
"$type": "Document",
"DocumentIndex": 18,
"Title": "JobDriver_StripChitin.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_StripChitin\\JobDriver_StripChitin.cs",
"RelativeDocumentMoniker": "Jobs\\JobDriver_StripChitin\\JobDriver_StripChitin.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_StripChitin\\JobDriver_StripChitin.cs",
"RelativeToolTip": "Jobs\\JobDriver_StripChitin\\JobDriver_StripChitin.cs",
"ViewState": "AgIAAD4AAAAAAAAAAAAAAE0AAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-16T15:50:38.09Z"
},
{
"$type": "Document",
"DocumentIndex": 20,
"Title": "Comp_ChitinStripping.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_StripChitin\\Comp_ChitinStripping.cs",
"RelativeDocumentMoniker": "Jobs\\JobDriver_StripChitin\\Comp_ChitinStripping.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_StripChitin\\Comp_ChitinStripping.cs",
"RelativeToolTip": "Jobs\\JobDriver_StripChitin\\Comp_ChitinStripping.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAoAAABWAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-16T15:49:51.675Z"
},
{
"$type": "Document",
"DocumentIndex": 21,
"Title": "Verb_ShootSelfUnderfoot.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Verbs\\Verb_ShootSelfUnderfoot.cs",
"RelativeDocumentMoniker": "Verbs\\Verb_ShootSelfUnderfoot.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Verbs\\Verb_ShootSelfUnderfoot.cs",
"RelativeToolTip": "Verbs\\Verb_ShootSelfUnderfoot.cs",
"ViewState": "AgIAAJAAAAAAAAAAAAAcwJwAAAAoAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-16T15:07:22.127Z"
},
{
"$type": "Document",
"DocumentIndex": 22,
"Title": "HediffComp_TopTurret.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_HediffComp_TopTurret\\HediffComp_TopTurret.cs",
"RelativeDocumentMoniker": "Hediffs\\ARA_HediffComp_TopTurret\\HediffComp_TopTurret.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Hediffs\\ARA_HediffComp_TopTurret\\HediffComp_TopTurret.cs",
"RelativeToolTip": "Hediffs\\ARA_HediffComp_TopTurret\\HediffComp_TopTurret.cs",
"ViewState": "AgIAACcBAAAAAAAAAAAkwD0BAAAjAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-16T14:52:46.325Z"
},
{
"$type": "Document",
"DocumentIndex": 17,
"Title": "RoomRoleWorker_Incubator.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\RoomRole\\RoomRoleWorker_Incubator.cs",
"RelativeDocumentMoniker": "RoomRole\\RoomRoleWorker_Incubator.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\RoomRole\\RoomRoleWorker_Incubator.cs",
"RelativeToolTip": "RoomRole\\RoomRoleWorker_Incubator.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAUAAAABAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-16T14:32:31.389Z"
},
{
"$type": "Document",
"DocumentIndex": 19,
"Title": "CompProperties_ChitinStripping.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_StripChitin\\CompProperties_ChitinStripping.cs",
"RelativeDocumentMoniker": "Jobs\\JobDriver_StripChitin\\CompProperties_ChitinStripping.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Jobs\\JobDriver_StripChitin\\CompProperties_ChitinStripping.cs",
"RelativeToolTip": "Jobs\\JobDriver_StripChitin\\CompProperties_ChitinStripping.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAABcAAAAtAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-16T15:50:04.277Z"
},
{
"$type": "Document",
"DocumentIndex": 23,
"Title": "CompResearchProducer.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_CompInteractiveProducer\\CompResearchProducer.cs",
"RelativeDocumentMoniker": "Building_Comps\\ARA_CompInteractiveProducer\\CompResearchProducer.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_CompInteractiveProducer\\CompResearchProducer.cs",
"RelativeToolTip": "Building_Comps\\ARA_CompInteractiveProducer\\CompResearchProducer.cs",
"ViewState": "AgIAAAAAAAAAAAAAAADwvy0AAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-16T14:29:05.969Z"
},
{
"$type": "Document",
"DocumentIndex": 24,
"Title": "CompCorpseConverter.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_CorpseConverter\\CompCorpseConverter.cs",
"RelativeDocumentMoniker": "Building_Comps\\ARA_CorpseConverter\\CompCorpseConverter.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_CorpseConverter\\CompCorpseConverter.cs",
"RelativeToolTip": "Building_Comps\\ARA_CorpseConverter\\CompCorpseConverter.cs",
"ViewState": "AgIAABwDAAAAAAAAAAAIwCoDAAARAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-16T12:23:40.696Z"
},
{
"$type": "Document",
"DocumentIndex": 25,
"Title": "CompProperties_CorpseConverter.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_CorpseConverter\\CompProperties_CorpseConverter.cs",
"RelativeDocumentMoniker": "Building_Comps\\ARA_CorpseConverter\\CompProperties_CorpseConverter.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_CorpseConverter\\CompProperties_CorpseConverter.cs",
"RelativeToolTip": "Building_Comps\\ARA_CorpseConverter\\CompProperties_CorpseConverter.cs",
"ViewState": "AgIAAAAAAAAAAAAAAADwvwAAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-16T12:23:39.636Z"
},
{
"$type": "Document",
"DocumentIndex": 28,
"Title": "CompRefuelableNutrition_WithKey.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\WULA_MutiFuelSpawner\\CompRefuelableNutrition_WithKey.cs",
"RelativeDocumentMoniker": "Building_Comps\\WULA_MutiFuelSpawner\\CompRefuelableNutrition_WithKey.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\WULA_MutiFuelSpawner\\CompRefuelableNutrition_WithKey.cs",
"RelativeToolTip": "Building_Comps\\WULA_MutiFuelSpawner\\CompRefuelableNutrition_WithKey.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAACUAAABAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-16T10:38:33.135Z"
},
{
"$type": "Document",
"DocumentIndex": 26,
"Title": "CompTerrainChanger.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_TerrainChanger\\CompTerrainChanger.cs",
"RelativeDocumentMoniker": "Building_Comps\\ARA_TerrainChanger\\CompTerrainChanger.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_TerrainChanger\\CompTerrainChanger.cs",
"RelativeToolTip": "Building_Comps\\ARA_TerrainChanger\\CompTerrainChanger.cs",
"ViewState": "AgIAAK0CAAAAAAAAAAAcwPYCAAAMAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-16T10:30:16.921Z"
},
{
"$type": "Document",
"DocumentIndex": 27,
"Title": "CompProperties_TerrainChanger.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_TerrainChanger\\CompProperties_TerrainChanger.cs",
"RelativeDocumentMoniker": "Building_Comps\\ARA_TerrainChanger\\CompProperties_TerrainChanger.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_TerrainChanger\\CompProperties_TerrainChanger.cs",
"RelativeToolTip": "Building_Comps\\ARA_TerrainChanger\\CompProperties_TerrainChanger.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-16T10:30:15.601Z"
},
{
"$type": "Document",
"DocumentIndex": 34,
"Title": "Building_RefuelingVat.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_Building_RefuelingVat\\Building_RefuelingVat.cs",
"RelativeDocumentMoniker": "Building_Comps\\ARA_Building_RefuelingVat\\Building_RefuelingVat.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Building_Comps\\ARA_Building_RefuelingVat\\Building_RefuelingVat.cs",
"RelativeToolTip": "Building_Comps\\ARA_Building_RefuelingVat\\Building_RefuelingVat.cs",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-16T10:28:54.756Z"
},
{
"$type": "Document",
"DocumentIndex": 29,
"Title": "CompProperties_IncubatorData.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_Ootheca\\CompProperties_IncubatorData.cs",
"RelativeDocumentMoniker": "Buildings\\Building_Ootheca\\CompProperties_IncubatorData.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_Ootheca\\CompProperties_IncubatorData.cs",
"RelativeToolTip": "Buildings\\Building_Ootheca\\CompProperties_IncubatorData.cs",
"ViewState": "AgIAANcAAAAAAAAAAIA1wPoAAAAxAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-16T04:37:03.042Z"
},
{
"$type": "Document",
"DocumentIndex": 30,
"Title": "OothecaIncubatorExtension.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_Ootheca\\OothecaIncubatorExtension.cs",
"RelativeDocumentMoniker": "Buildings\\Building_Ootheca\\OothecaIncubatorExtension.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_Ootheca\\OothecaIncubatorExtension.cs",
"RelativeToolTip": "Buildings\\Building_Ootheca\\OothecaIncubatorExtension.cs",
"ViewState": "AgIAAAAAAAAAAAAAAADwvxUAAABBAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-16T04:36:59.394Z"
},
{
"$type": "Document",
"DocumentIndex": 33,
"Title": "Building_EquipmentOotheca.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_EquipmentOotheca\\Building_EquipmentOotheca.cs",
"RelativeDocumentMoniker": "Buildings\\Building_EquipmentOotheca\\Building_EquipmentOotheca.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_EquipmentOotheca\\Building_EquipmentOotheca.cs",
"RelativeToolTip": "Buildings\\Building_EquipmentOotheca\\Building_EquipmentOotheca.cs",
"ViewState": "AgIAACcAAAAAAAAAAAAAADoDAABSAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-15T18:22:14.171Z"
},
{
"$type": "Document",
"DocumentIndex": 31,
"Title": "Building_Ootheca.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_Ootheca\\Building_Ootheca.cs",
"RelativeDocumentMoniker": "Buildings\\Building_Ootheca\\Building_Ootheca.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_Ootheca\\Building_Ootheca.cs",
"RelativeToolTip": "Buildings\\Building_Ootheca\\Building_Ootheca.cs",
"ViewState": "AgIAALcCAAAAAAAAAAAewNgCAAAVAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-15T18:22:12.217Z"
},
{
"$type": "Document",
"DocumentIndex": 32,
"Title": "CompProperties_EquipmentIncubatorData.cs",
"DocumentMoniker": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_EquipmentOotheca\\CompProperties_EquipmentIncubatorData.cs",
"RelativeDocumentMoniker": "Buildings\\Building_EquipmentOotheca\\CompProperties_EquipmentIncubatorData.cs",
"ToolTip": "E:\\SteamLibrary\\steamapps\\common\\RimWorld\\Mods\\ArachnaeSwarm\\Source\\ArachnaeSwarm\\Buildings\\Building_EquipmentOotheca\\CompProperties_EquipmentIncubatorData.cs",
"RelativeToolTip": "Buildings\\Building_EquipmentOotheca\\CompProperties_EquipmentIncubatorData.cs",
"ViewState": "AgIAAA4AAAAAAAAAAADwvyYAAAAaAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-12-15T17:55:40.041Z"
}
]
}

View File

@@ -21,6 +21,9 @@ namespace ArachnaeSwarm
public static JobDef ARA_OperateIncubator;
public static JobDef ARA_OperateEquipmentIncubator;
public static JobDef ARA_SwarmMaintain;
public static JobDef ARA_ExtractHoney;
public static JobDef ARA_StripChitin;
public static JobDef ARA_FeedWithHoney;
static ARA_JobDefOf()
{

View File

@@ -114,6 +114,8 @@
<Compile Include="Abilities\CompAbilityEffect_RandomHediff.cs" />
<Compile Include="Abilities\CompAbilityEffect_TransformCorpse.cs" />
<Compile Include="Buildings\Building_ArachnaeGravEngine.cs" />
<Compile Include="Buildings\Building_DormancyVat\Building_DormancyVat.cs" />
<Compile Include="Buildings\Building_DormancyVat\DefModExtension_DormancyVat.cs" />
<Compile Include="Buildings\Building_EquipmentOotheca\Building_EquipmentOotheca.cs" />
<Compile Include="Buildings\Building_EquipmentOotheca\CompProperties_EquipmentIncubatorData.cs" />
<Compile Include="Buildings\Building_EquipmentOotheca\ITab_EquipmentOotheca_Incubation.cs" />
@@ -131,6 +133,9 @@
<Compile Include="HarmonyPatches\DestroyRemovesResearch\CompDestroyRemovesResearch.cs" />
<Compile Include="HarmonyPatches\DestroyRemovesResearch\CompProperties_DestroyRemovesResearch.cs" />
<Compile Include="HarmonyPatches\Patch_ResearchManager_AddRemoveMethod.cs" />
<Compile Include="Pawn_Comps\ARA_SwarmMaintainer\CompProperties_SwarmMaintainer.cs" />
<Compile Include="Pawn_Comps\ARA_SwarmMaintainer\Comp_SwarmMaintainer.cs" />
<Compile Include="RoomRole\RoomRoleWorker_JellyVat.cs" />
<Compile Include="RoomRole\RoomRoleWorker_Incubator.cs" />
<Compile Include="Buildings\Building_TurretGunHasSpeed.cs" />
<Compile Include="Buildings\Building_RefuelingVat\Building_RefuelingVat.cs" />
@@ -256,6 +261,8 @@
<Compile Include="Building_Comps\CompNutritionToFuelConverter.cs" />
<Compile Include="Building_Comps\CompAutoEjector.cs" />
<Compile Include="Jobs\JobDriver_Refuel_Nutrition.cs" />
<Compile Include="WorkGivers\WorkGiver_ExtractHoney.cs" />
<Compile Include="WorkGivers\WorkGiver_FeedWithHoney.cs" />
<Compile Include="WorkGivers\WorkGiver_Refuel_Nutrition.cs" />
<Compile Include="Hediffs\ARA_ConfigurableMutant\Hediff_ConfigurableMutant.cs" />
<Compile Include="Hediffs\ARA_ConfigurableMutant\Hediff_NecroticVirus_Configurable.cs" />
@@ -371,6 +378,8 @@
<Compile Include="PowerArmor\CompPowerArmorStation.cs" />
<Compile Include="PowerArmor\Gizmo_StructurePanel.cs" />
<Compile Include="PowerArmor\JobDriver_EnterPowerArmor.cs" />
<Compile Include="WorkGivers\WorkGiver_StripChitin.cs" />
<Compile Include="WorkGivers\WorkGiver_SwarmMaintain.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="Jobs\JobDriver_SuperCarry\SuperCarryExtension.cs" />

View File

@@ -64,7 +64,7 @@ namespace ArachnaeSwarm
/// <returns>如果地形有 ARA_Creep 标签则返回 true</returns>
private bool HasCreepTag(TerrainDef terrain)
{
return terrain.tags != null && terrain.tags.Contains("ARA_Creep");
return terrain.tags != null && terrain.tags.Contains("ARA_Creep") || terrain.tags.Contains("ARA_Incubator_Nutrient_Solution");
}
// NOTICE: There is NO CompTick() method here. This component does not perform any updates after it has spawned.

View File

@@ -19,13 +19,10 @@ namespace ArachnaeSwarm
// 维护度达到多少时开始显示警告(百分比)
public float warningThreshold = 0.3f;
// 可维护的种族列表
public List<ThingDef> allowedRaces;
// 可维护的种族列表现在由WorkGiver处理
// public List<ThingDef> allowedRaces;
// 检查分配工作的间隔ticks
public int assignJobCheckInterval = 600; // 10秒
// 维护度低于多少时开始寻找维护者(百分比)
// 维护度低于多少时开始需要维护工作(百分比
public float maintenanceThresholdForJob = 0.9f;
public CompProperties_SwarmMaintenance()

View File

@@ -18,19 +18,14 @@ namespace ArachnaeSwarm
// 上次更新维护度的时间
private int lastMaintenanceTick = -99999;
// 上次检查分配工作的时间
private int lastJobCheckTick = -99999;
// 当维护度为0时每秒受到的伤害计时器
private int nextDamageTick = -99999;
// 是否正在寻找维护者
private bool seekingMaintainer = false;
// 找不到维护者的提示信息
private string noMaintainerWarning = "";
// 警告计时器
private int lastWarningTick = -99999;
private const int WarningDuration = 2500; // 警告显示41.67秒
private const int WarningInterval = 2500; // 警告间隔时间
private const float CriticalWarningThreshold = 0.3f; // 警告阈值(百分比)
private bool lastWarningState = false;
// 属性访问
public float CurrentMaintenance => currentMaintenance;
@@ -46,7 +41,6 @@ namespace ArachnaeSwarm
base.Initialize(props);
currentMaintenance = Props.maxMaintenance; // 初始时满维护度
lastMaintenanceTick = Find.TickManager.TicksGame;
lastJobCheckTick = Find.TickManager.TicksGame;
}
// 序列化
@@ -55,11 +49,9 @@ namespace ArachnaeSwarm
base.PostExposeData();
Scribe_Values.Look(ref currentMaintenance, "currentMaintenance", Props.maxMaintenance);
Scribe_Values.Look(ref lastMaintenanceTick, "lastMaintenanceTick", -99999);
Scribe_Values.Look(ref lastJobCheckTick, "lastJobCheckTick", -99999);
Scribe_Values.Look(ref nextDamageTick, "nextDamageTick", -99999);
Scribe_Values.Look(ref seekingMaintainer, "seekingMaintainer", false);
Scribe_Values.Look(ref noMaintainerWarning, "noMaintainerWarning", "");
Scribe_Values.Look(ref lastWarningTick, "lastWarningTick", -99999);
Scribe_Values.Look(ref lastWarningState, "lastWarningState", false);
}
// 每tick更新
@@ -76,11 +68,11 @@ namespace ArachnaeSwarm
lastMaintenanceTick = currentTick;
}
// 定期检查是否需要分配维护工作
if (currentTick - lastJobCheckTick >= Props.assignJobCheckInterval)
// 检查是否需要显示警告
if (currentTick - lastWarningTick >= WarningInterval)
{
CheckAndAssignMaintenanceJob();
lastJobCheckTick = currentTick;
CheckWarning();
lastWarningTick = currentTick;
}
// 如果维护度为0每秒造成伤害
@@ -89,12 +81,6 @@ namespace ArachnaeSwarm
ApplyDamageWhenEmpty();
nextDamageTick = currentTick + 60; // 60ticks = 1秒
}
// 更新警告信息显示时间
if (currentTick - lastWarningTick >= WarningDuration)
{
noMaintainerWarning = "";
}
}
// 更新维护度递减
@@ -112,6 +98,39 @@ namespace ArachnaeSwarm
currentMaintenance = 0f;
}
// 检查是否需要显示警告
private void CheckWarning()
{
if (parent == null || parent.Destroyed || parent.Map == null)
return;
bool isCritical = MaintenancePercentage <= CriticalWarningThreshold;
// 如果状态改变,显示警告
if (isCritical && !lastWarningState)
{
ShowMaintenanceWarning();
lastWarningState = true;
}
else if (!isCritical && lastWarningState)
{
lastWarningState = false;
}
}
// 显示维护警告
private void ShowMaintenanceWarning()
{
if (parent == null)
return;
// 添加警告标记
if (parent.Spawned)
{
MoteMaker.ThrowText(parent.DrawPos, parent.Map, "ARA_SwarmMaintenance.NeedsMaintenance".Translate(), Color.yellow);
}
}
// 当维护度为0时应用伤害
private void ApplyDamageWhenEmpty()
{
@@ -130,188 +149,53 @@ namespace ArachnaeSwarm
));
}
// 检查并分配维护工作
private void CheckAndAssignMaintenanceJob()
{
if (parent == null || parent.Map == null || parent.Faction == null)
return;
// 如果不需要维护,重置状态
if (!NeedsMaintenance)
{
seekingMaintainer = false;
return;
}
// 如果正在寻找维护者,尝试分配工作
if (!seekingMaintainer)
{
seekingMaintainer = true;
}
// 尝试寻找符合条件的Pawn
Pawn maintainer = FindAvailableMaintainer();
if (maintainer != null)
{
// 分配维护工作
AssignMaintenanceJobTo(maintainer);
seekingMaintainer = false;
noMaintainerWarning = "";
}
else
{
// 记录找不到维护者的警告
if (noMaintainerWarning == "")
{
noMaintainerWarning = "ARA_SwarmMaintenance.NoMaintainerFound".Translate();
lastWarningTick = Find.TickManager.TicksGame;
}
}
}
// 寻找可用的维护者
private Pawn FindAvailableMaintainer()
{
if (parent.Map == null || parent.Faction == null)
return null;
// 查找地图中所有属于玩家阵营的Pawn
List<Pawn> allPawns = parent.Map.mapPawns.SpawnedPawnsInFaction(parent.Faction);
foreach (Pawn pawn in allPawns)
{
if (CanPawnMaintain(pawn))
{
return pawn;
}
}
return null;
}
// 判断Pawn是否可以维护
private bool CanPawnMaintain(Pawn pawn)
{
if (pawn == null || pawn.Dead || pawn.Downed || pawn.InMentalState)
return false;
// 检查种族是否在允许列表中
if (Props.allowedRaces != null && Props.allowedRaces.Count > 0)
{
if (!Props.allowedRaces.Contains(pawn.def))
return false;
}
// 检查Pawn是否处于GotoWander或Wait_Wander状态
if (!IsPawnWandering(pawn))
return false;
// 检查Pawn是否已经有维护工作
if (HasMaintenanceJob(pawn))
return false;
return true;
}
// 检查Pawn是否处于漫游状态
private bool IsPawnWandering(Pawn pawn)
{
if (pawn.jobs == null || pawn.jobs.curJob == null)
return false;
Job curJob = pawn.jobs.curJob;
// 检查是否是漫游工作
if (curJob.def == JobDefOf.GotoWander || curJob.def == JobDefOf.Wait_Wander)
{
return true;
}
return false;
}
// 检查Pawn是否已经有维护工作
private bool HasMaintenanceJob(Pawn pawn)
{
if (pawn.jobs == null)
return false;
// 检查当前工作是否是维护工作
if (pawn.jobs.curJob != null && pawn.jobs.curJob.def == ARA_JobDefOf.ARA_SwarmMaintain)
{
return true;
}
// 检查工作队列中是否有维护工作
if (pawn.jobs.jobQueue != null && pawn.jobs.jobQueue.Count > 0)
{
foreach (QueuedJob queuedJob in pawn.jobs.jobQueue)
{
if (queuedJob.job.def == ARA_JobDefOf.ARA_SwarmMaintain)
{
return true;
}
}
}
return false;
}
// 为Pawn分配维护工作
private void AssignMaintenanceJobTo(Pawn pawn)
{
if (pawn == null || pawn.jobs == null)
return;
// 创建维护工作
Job job = JobMaker.MakeJob(ARA_JobDefOf.ARA_SwarmMaintain, parent);
job.expiryInterval = 30000; // 工作过期时间
job.ignoreForbidden = false;
// 记录Pawn原来的工作以便恢复
Job oldJob = pawn.jobs.curJob;
// 将工作添加到队列末尾
pawn.jobs.TryTakeOrderedJob(job, JobTag.MiscWork);
// 如果Pawn原来在漫游我们可以在维护工作完成后恢复漫游状态
if (oldJob != null && (oldJob.def == JobDefOf.GotoWander || oldJob.def == JobDefOf.Wait_Wander))
{
// 我们可以在维护工作完成后添加一个恢复漫游的工作
// 这里暂时不做处理因为维护工作完成后Pawn会回到空闲状态
// 如果需要更精细的控制可以在JobDriver_SwarmMaintain完成时添加漫游工作
}
}
// 添加维护度
public void AddMaintenance(float amount)
{
currentMaintenance += amount;
if (currentMaintenance > MaxMaintenance)
currentMaintenance = MaxMaintenance;
// 维护后重置警告状态
lastWarningState = false;
}
// 重置维护度
public void ResetMaintenance()
{
currentMaintenance = MaxMaintenance;
lastWarningState = false;
}
// 获取可维护的优先级用于WorkGiver排序
public float GetMaintenancePriority()
{
// 维护度越低,优先级越高
return 1f - MaintenancePercentage;
}
// 在建筑信息面板中追加维护信息
public override string CompInspectStringExtra()
{
// 基础信息
string text = "ARA_SwarmMaintenance.MaintenanceLevel".Translate(currentMaintenance.ToString("F1"), MaxMaintenance.ToString("F1"), MaintenancePercentage.ToString("P1"));
string text = "ARA_SwarmMaintenance.MaintenanceLevel".Translate(
currentMaintenance.ToString("F1"),
MaxMaintenance.ToString("F1"),
MaintenancePercentage.ToString("P1"));
// 添加维护度递减信息
text += "\n" + "ARA_SwarmMaintenance.DailyDecay".Translate(Props.maintenanceDecayPerDay.ToString("F1"));
// 显示找不到维护者的警告
if (noMaintainerWarning != "")
// 显示维护状态
if (NeedsMaintenance)
{
text += "\n<color=orange>" + noMaintainerWarning + "</color>";
text += "\n" + "ARA_SwarmMaintenance.NeedsMaintenance".Translate();
}
// 显示警告信息
if (IsCritical)
{
text += "\n<color=orange>" + "ARA_SwarmMaintenance.CriticalLevel".Translate() + "</color>";
}
return text;
@@ -323,58 +207,9 @@ namespace ArachnaeSwarm
// 只在玩家控制下显示
if (parent.Faction?.IsPlayer == true)
{
// 调试按钮:手动触发寻找维护者 - 仅在GodMode下显示
// 调试按钮 - 仅在GodMode下显示
if (DebugSettings.godMode)
{
yield return new Command_Action
{
defaultLabel = "Debug: Find Maintainer",
action = () =>
{
Pawn maintainer = FindAvailableMaintainer();
if (maintainer != null)
{
Messages.Message($"找到维护者: {maintainer.LabelShort} (当前工作: {maintainer.jobs.curJob?.def.defName ?? ""})", MessageTypeDefOf.PositiveEvent);
AssignMaintenanceJobTo(maintainer);
}
else
{
Messages.Message("未找到符合条件的空闲维护者", MessageTypeDefOf.NegativeEvent);
// 列出所有符合条件的Pawn及其状态
List<Pawn> allPawns = parent.Map.mapPawns.SpawnedPawnsInFaction(parent.Faction);
List<string> pawnStatus = new List<string>();
foreach (Pawn pawn in allPawns)
{
if (Props.allowedRaces != null && Props.allowedRaces.Count > 0 && !Props.allowedRaces.Contains(pawn.def))
continue;
string status = $"{pawn.LabelShort}: ";
if (pawn.Dead) status += "死亡";
else if (pawn.Downed) status += "倒地";
else if (pawn.InMentalState) status += "精神崩溃";
else if (pawn.jobs?.curJob != null)
{
status += $"{pawn.jobs.curJob.def.defName}";
if (HasMaintenanceJob(pawn)) status += " (已有维护工作)";
}
else
{
status += "空闲";
}
pawnStatus.Add(status);
}
if (pawnStatus.Count > 0)
{
Messages.Message("符合条件的Pawn状态:\n" + string.Join("\n", pawnStatus), MessageTypeDefOf.SilentInput);
}
}
}
};
yield return new Command_Action
{
defaultLabel = "Debug: Reset Maintenance",
@@ -392,6 +227,15 @@ namespace ArachnaeSwarm
defaultLabel = "Debug: Reduce to 0",
action = () => currentMaintenance = 0f
};
yield return new Command_Action
{
defaultLabel = "Debug: Show Priority",
action = () =>
{
Messages.Message($"维护优先级: {GetMaintenancePriority():F2}", MessageTypeDefOf.SilentInput);
}
};
}
}
}

View File

@@ -0,0 +1,459 @@
using RimWorld;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Verse;
using Verse.AI;
namespace ArachnaeSwarm
{
[StaticConstructorOnStartup]
public class Building_DormancyVat : Building_Enterable, IThingHolder, IThingHolderWithDrawnPawn
{
private Graphic cachedTopGraphic;
// IThingHolderWithDrawnPawn implementation
public float HeldPawnDrawPos_Y => DrawPos.y + 0.03658537f;
public float HeldPawnBodyAngle => base.Rotation.AsAngle;
public PawnPosture HeldPawnPosture => PawnPosture.LayingOnGroundFaceUp;
private Graphic TopGraphic
{
get
{
if (cachedTopGraphic == null)
{
var modExtension = def.GetModExtension<DefModExtension_DormancyVat>();
if (modExtension != null && !modExtension.topGraphicPath.NullOrEmpty())
{
cachedTopGraphic = GraphicDatabase.Get(modExtension.graphicClass, modExtension.topGraphicPath, ShaderDatabase.Transparent, def.graphicData.drawSize, Color.white, Color.white);
}
}
return cachedTopGraphic;
}
}
public override Vector3 PawnDrawOffset => Vector3.zero;
public override void SpawnSetup(Map map, bool respawningAfterLoad)
{
base.SpawnSetup(map, respawningAfterLoad);
}
public override void DeSpawn(DestroyMode mode = DestroyMode.Vanish)
{
if (mode != DestroyMode.WillReplace)
{
if (selectedPawn != null && innerContainer.Contains(selectedPawn))
{
Finish(); // 弹出里面的pawn
}
}
base.DeSpawn(mode);
}
protected override void Tick()
{
base.Tick();
if (selectedPawn != null && (selectedPawn.Destroyed || !innerContainer.Contains(selectedPawn)))
{
OnStop();
return;
}
if (base.Working && selectedPawn != null)
{
// 检查pawn是否死亡
if (selectedPawn.Dead || selectedPawn.Destroyed)
{
Finish(); // 弹出死亡的pawn
return;
}
// 休眠Vat不产生任何效果只需保持pawn在里面
}
}
public override AcceptanceReport CanAcceptPawn(Pawn pawn)
{
if (base.Working)
{
return "DormancyVat_Occupied".Translate();
}
if (selectedPawn != null && selectedPawn != pawn)
{
return "DormancyVat_WaitingForArachnae".Translate(selectedPawn.Named("PAWN"));
}
// 只允许虫族成员进入
bool isArachnaeMember =
pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindDrone);
if (!isArachnaeMember)
{
return "DormancyVat_OnlyArachnaeAllowed".Translate(pawn.Named("PAWN"));
}
// 不允许已经死亡的pawn
if (pawn.Dead)
{
return "DormancyVat_CannotAcceptDeadPawn".Translate(pawn.Named("PAWN"));
}
// 允许殖民者、囚犯和奴隶,但必须是虫族成员
bool isColonist = pawn.IsColonist;
bool isPrisoner = pawn.IsPrisonerOfColony;
bool isSlave = pawn.IsSlaveOfColony;
return (isColonist || isPrisoner || isSlave) && !pawn.IsQuestLodger();
}
public override void TryAcceptPawn(Pawn pawn)
{
if (!CanAcceptPawn(pawn).Accepted)
{
return;
}
selectedPawn = pawn;
bool deselected = pawn.DeSpawnOrDeselect();
if (innerContainer.TryAddOrTransfer(pawn))
{
startTick = Find.TickManager.TicksGame;
}
if (deselected)
{
Find.Selector.Select(pawn, playSound: false, forceDesignatorDeselect: false);
}
}
private void Finish()
{
if (selectedPawn != null)
{
try
{
// 检查pawn是否还活着
if (selectedPawn.Dead)
{
Notify_PawnRemoved();
// 对死亡的pawn将其尸体弹出
bool ejected = false;
if (innerContainer.Contains(selectedPawn))
{
ejected = innerContainer.TryDrop(selectedPawn, InteractionCell, base.Map, ThingPlaceMode.Near, 1, out var _);
}
if (!ejected && innerContainer.Contains(selectedPawn))
{
var adjacentCells = GenAdj.CellsAdjacent8Way(this).Where(c => c.Walkable(base.Map) && c.InBounds(base.Map)).ToList();
if (adjacentCells.Count > 0)
{
IntVec3 randomCell = adjacentCells.RandomElement();
ejected = innerContainer.TryDrop(selectedPawn, randomCell, base.Map, ThingPlaceMode.Direct, 1, out var _);
}
}
if (!ejected && innerContainer.Contains(selectedPawn))
{
innerContainer.Remove(selectedPawn);
GenPlace.TryPlaceThing(selectedPawn, this.Position, base.Map, ThingPlaceMode.Near);
}
}
else
{
Notify_PawnRemoved();
// 对活着的pawn安全弹出
bool ejected = false;
if (innerContainer.Contains(selectedPawn))
{
ejected = innerContainer.TryDrop(selectedPawn, InteractionCell, base.Map, ThingPlaceMode.Near, 1, out var _);
}
if (!ejected && innerContainer.Contains(selectedPawn))
{
var adjacentCells = GenAdj.CellsAdjacent8Way(this).Where(c => c.Walkable(base.Map) && c.InBounds(base.Map)).ToList();
if (adjacentCells.Count > 0)
{
IntVec3 randomCell = adjacentCells.RandomElement();
ejected = innerContainer.TryDrop(selectedPawn, randomCell, base.Map, ThingPlaceMode.Direct, 1, out var _);
}
}
if (!ejected && innerContainer.Contains(selectedPawn))
{
innerContainer.Remove(selectedPawn);
GenPlace.TryPlaceThing(selectedPawn, this.Position, base.Map, ThingPlaceMode.Near);
}
}
}
catch (Exception ex)
{
Log.Error("DormancyVat_ErrorEjecting".Translate(selectedPawn.Label) + ": " + ex.ToString());
}
finally
{
OnStop();
}
}
}
private void OnStop()
{
if (selectedPawn != null)
{
if (innerContainer.Contains(selectedPawn))
{
innerContainer.Remove(selectedPawn);
}
}
selectedPawn = null;
startTick = -1;
}
private void Notify_PawnRemoved()
{
// 可以在这里添加音效
// SoundDefOf.GrowthVat_Open.PlayOneShot(SoundInfo.InMap(this));
}
public override IEnumerable<Gizmo> GetGizmos()
{
// 基础Gizmos
foreach (Gizmo gizmo in base.GetGizmos())
{
yield return gizmo;
}
if (base.Working)
{
// 休眠Vat工作时显示"弹出"按钮
Command_Action ejectCommand = new Command_Action
{
defaultLabel = "DormancyVat_EjectButton".Translate(),
defaultDesc = "DormancyVat_EjectButtonDesc".Translate(),
icon = ContentFinder<Texture2D>.Get("UI/Commands/Cancel", false),
action = () => Finish()
};
yield return ejectCommand;
}
else
{
// 选择虫族成员的操作
Command_Action command_Action = new Command_Action
{
defaultLabel = "DormancyVat_InsertButton".Translate() + "...",
defaultDesc = "DormancyVat_InsertButtonDesc".Translate(),
icon = ContentFinder<Texture2D>.Get("ArachnaeSwarm/UI/Commands/ARA_InsertPawn", false),
action = () =>
{
List<FloatMenuOption> list = new List<FloatMenuOption>();
foreach (Pawn p in base.Map.mapPawns.AllPawnsSpawned)
{
if (CanAcceptPawn(p).Accepted)
{
string pawnType = "";
if (p.IsColonist) pawnType = "DormancyVat_Colonist".Translate();
else if (p.IsPrisoner) pawnType = "DormancyVat_Prisoner".Translate();
else if (p.IsSlave) pawnType = "DormancyVat_Slave".Translate();
list.Add(new FloatMenuOption(
p.LabelCap + " (" + pawnType + ")",
() => SelectPawn(p),
p,
Color.white
));
}
}
if (!list.Any())
{
list.Add(new FloatMenuOption("DormancyVat_NoArachnaeAvailable".Translate(), null));
}
Find.WindowStack.Add(new FloatMenu(list));
}
};
if (!base.AnyAcceptablePawns)
{
command_Action.Disable("DormancyVat_NoArachnaeAvailable".Translate());
}
yield return command_Action;
}
}
private string GetArachnaeType(Pawn pawn)
{
if (pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindMaster))
return "DormancyVat_ArachnaeType_Master".Translate();
else if (pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindDrone))
return "DormancyVat_ArachnaeType_Drone".Translate();
else if (pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindWorker))
return "DormancyVat_ArachnaeType_Worker".Translate();
else
return "DormancyVat_ArachnaeType_Unknown".Translate();
}
public override string GetInspectString()
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(base.GetInspectString());
if (base.Working && selectedPawn != null)
{
stringBuilder.AppendLineIfNotEmpty().Append("DormancyVat_Contains".Translate() + ": " + selectedPawn.NameShortColored.Resolve());
stringBuilder.AppendLineIfNotEmpty().Append("DormancyVat_TypeLabel".Translate() + ": " + GetArachnaeType(selectedPawn));
// 显示休眠时间
if (startTick > 0)
{
int ticksInVat = Find.TickManager.TicksGame - startTick;
int days = ticksInVat / 60000;
int hours = (ticksInVat % 60000) / 2500;
stringBuilder.AppendLineIfNotEmpty().Append("DormancyVat_DormancyTime".Translate() + $": {days}" + "DormancyVat_Days".Translate() + $"{hours}" + "DormancyVat_Hours".Translate());
}
// 显示健康状态
stringBuilder.AppendLineIfNotEmpty().Append("DormancyVat_HealthStatus".Translate() + ": " + selectedPawn.health.summaryHealth.SummaryHealthPercent.ToStringPercent());
}
else if (selectedPawn != null)
{
stringBuilder.AppendLineIfNotEmpty().Append("DormancyVat_WaitingForArachnae".Translate(selectedPawn.Named("PAWN")).Resolve());
}
return stringBuilder.ToString();
}
public override IEnumerable<FloatMenuOption> GetFloatMenuOptions(Pawn selPawn)
{
foreach (FloatMenuOption floatMenuOption in base.GetFloatMenuOptions(selPawn))
{
yield return floatMenuOption;
}
if (!selPawn.CanReach(this, PathEndMode.InteractionCell, Danger.Deadly))
{
yield return new FloatMenuOption("DormancyVat_CannotEnter".Translate(this) + ": " + "DormancyVat_NoPath".Translate().CapitalizeFirst(), null);
yield break;
}
AcceptanceReport acceptanceReport = CanAcceptPawn(selPawn);
if (acceptanceReport.Accepted)
{
yield return FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("DormancyVat_Enter".Translate(this), () => SelectPawn(selPawn)), selPawn, this);
}
else if (!acceptanceReport.Reason.NullOrEmpty())
{
yield return new FloatMenuOption("DormancyVat_CannotEnter".Translate(this) + ": " + acceptanceReport.Reason.CapitalizeFirst(), null);
}
}
public override void DynamicDrawPhaseAt(DrawPhase phase, Vector3 drawLoc, bool flip = false)
{
if (base.Working && selectedPawn != null && innerContainer.Contains(selectedPawn))
{
selectedPawn.Drawer.renderer.DynamicDrawPhaseAt(phase, drawLoc + PawnDrawOffset, null, neverAimWeapon: true);
}
base.DynamicDrawPhaseAt(phase, drawLoc, flip);
}
protected override void DrawAt(Vector3 drawLoc, bool flip = false)
{
base.DrawAt(drawLoc, flip);
// 绘制顶部图形(如果存在)
if (TopGraphic != null)
{
TopGraphic.Draw(DrawPos + Altitudes.AltIncVect * 2f, base.Rotation, this);
}
}
public Job CreateCarryJobForMember(Pawn member, Pawn carrier)
{
if (member == null || carrier == null)
return null;
if (!CanAcceptPawn(member).Accepted)
return null;
// 创建搬运工作定义
JobDef carryJobDef = DefDatabase<JobDef>.GetNamed("ARA_CarryMemberToDormancyVat");
if (carryJobDef == null)
return null;
Job job = JobMaker.MakeJob(carryJobDef, member, this);
job.count = 1;
return job;
}
public IEnumerable<Pawn> GetAvailableCarriers()
{
foreach (Pawn pawn in base.Map.mapPawns.AllPawnsSpawned)
{
// 检查是否是虫群成员
if (pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindDrone) ||
pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindWorker) ||
pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindMaster))
{
// 检查是否能够工作且不是囚犯
if (pawn.workSettings != null && pawn.workSettings.WorkIsActive(WorkTypeDefOf.Hauling) &&
!pawn.Downed && !pawn.IsPrisoner && pawn.CanReach(this, PathEndMode.InteractionCell, Danger.Some))
{
yield return pawn;
}
}
}
}
public void AssignCarrierForMember(Pawn member)
{
if (member == null)
return;
// 获取可用的搬运者
var availableCarriers = GetAvailableCarriers().ToList();
if (!availableCarriers.Any())
{
Messages.Message("DormancyVat_NoAvailableCarriers".Translate(), MessageTypeDefOf.RejectInput);
return;
}
// 创建浮动菜单选择搬运者
List<FloatMenuOption> options = new List<FloatMenuOption>();
foreach (Pawn carrier in availableCarriers)
{
options.Add(new FloatMenuOption(
carrier.LabelCap + " (" + GetArachnaeType(carrier) + ")",
() =>
{
Job carryJob = CreateCarryJobForMember(member, carrier);
if (carryJob != null)
{
carrier.jobs.TryTakeOrderedJob(carryJob, JobTag.MiscWork);
Messages.Message("DormancyVat_CarrierAssigned".Translate(carrier.LabelShort, member.LabelShort), MessageTypeDefOf.NeutralEvent);
}
},
carrier,
Color.white
));
}
if (options.Any())
{
Find.WindowStack.Add(new FloatMenu(options));
}
else
{
Messages.Message("DormancyVat_NoAvailableCarriers".Translate(), MessageTypeDefOf.RejectInput);
}
}
// 保存和加载数据
public override void ExposeData()
{
base.ExposeData();
}
}
}

View File

@@ -0,0 +1,11 @@
using System;
using Verse;
namespace ArachnaeSwarm
{
public class DefModExtension_DormancyVat : DefModExtension
{
public string topGraphicPath;
public Type graphicClass = typeof(Graphic_Multi); // 如果在XML中没有指定默认使用Graphic_Multi
}
}

View File

@@ -1,4 +1,5 @@
// File: Buildings/Building_ResearchBlueprintReader.cs
using AlienRace;
using RimWorld;
using System;
using System.Collections.Generic;
@@ -150,7 +151,7 @@ namespace ArachnaeSwarm
isResearching = false;
// 发送消息
Messages.Message($"科技研究完成: {storedResearch.LabelCap}",
Messages.Message("ResearchBlueprintReader_ResearchCompleted".Translate(storedResearch.LabelCap),
MessageTypeDefOf.PositiveEvent);
Log.Message($"[ResearchBlueprintReader] Research completed: {storedResearch.defName}");
@@ -174,7 +175,7 @@ namespace ArachnaeSwarm
{
if (IsLocked)
{
Messages.Message("建筑已锁定储存科技,无法开始新研究",
Messages.Message("ResearchBlueprintReader_LockedBuilding".Translate(),
MessageTypeDefOf.RejectInput);
return;
}
@@ -185,7 +186,7 @@ namespace ArachnaeSwarm
// 检查前置条件
if (!AreAllPrerequisitesCompleted(project))
{
Messages.Message("未满足前置科技条件",
Messages.Message("ResearchBlueprintReader_PrerequisitesNotMet".Translate(),
MessageTypeDefOf.RejectInput);
return;
}
@@ -202,7 +203,7 @@ namespace ArachnaeSwarm
manager.RegisterResearch(this, project);
}
Messages.Message($"开始研究: {project.LabelCap}(已绑定)",
Messages.Message("ResearchBlueprintReader_ResearchStarted".Translate(project.LabelCap),
MessageTypeDefOf.NeutralEvent);
}
@@ -233,7 +234,7 @@ namespace ArachnaeSwarm
isResearching = false;
researchStartTime = 0;
Messages.Message($"建筑已解锁: {project.LabelCap}",
Messages.Message("ResearchBlueprintReader_BuildingUnlocked".Translate(project.LabelCap),
MessageTypeDefOf.NeutralEvent);
}
}
@@ -261,37 +262,23 @@ namespace ArachnaeSwarm
if (IsLocked)
{
var unlockCmd = new Command_Action();
unlockCmd.defaultLabel = "解锁建筑";
unlockCmd.defaultDesc = "释放储存的科技,允许重新研究";
unlockCmd.icon = ContentFinder<Texture2D>.Get("UI/Designators/Unlock", false);
unlockCmd.defaultLabel = "ResearchBlueprintReader_UnlockBuilding".Translate();
unlockCmd.defaultDesc = "ResearchBlueprintReader_UnlockBuildingDesc".Translate();
unlockCmd.icon = ContentFinder<Texture2D>.Get("ArachnaeSwarm/UI/Abilities/ARA_Ability_Morph", false);
unlockCmd.action = delegate
{
UnlockBuilding();
};
yield return unlockCmd;
// 显示储存信息
var infoCmd = new Command_Action();
infoCmd.defaultLabel = $"储存: {storedResearch.LabelCap}";
infoCmd.defaultDesc = "点击查看详细信息";
infoCmd.icon = ContentFinder<Texture2D>.Get("UI/Designators/Info", false);
infoCmd.action = delegate
{
Messages.Message($"此建筑储存着: {storedResearch.LabelCap}\n" +
$"状态: {(storedResearch.IsFinished ? "" : "")}\n" +
$"描述: {storedResearch.description.StripTags()}",
MessageTypeDefOf.NeutralEvent);
};
yield return infoCmd;
yield break; // 锁定状态下不显示其他按钮
}
// 选择研究按钮
var selectCmd = new Command_Action();
selectCmd.defaultLabel = "选择研究项目";
selectCmd.defaultDesc = "选择要研究的科技项目(一旦选择将永久绑定)";
selectCmd.icon = ContentFinder<Texture2D>.Get("UI/Designators/Research", false);
selectCmd.defaultLabel = "ResearchBlueprintReader_SelectProject".Translate();
selectCmd.defaultDesc = "ResearchBlueprintReader_SelectProjectDesc".Translate();
selectCmd.icon = ContentFinder<Texture2D>.Get("ArachnaeSwarm/UI/Abilities/ARA_EggSpew_Techprint", false);
selectCmd.action = delegate
{
ShowResearchMenu();
@@ -302,8 +289,8 @@ namespace ArachnaeSwarm
if (DebugSettings.godMode && storedResearch != null && !storedResearch.IsFinished)
{
var debugCmd = new Command_Action();
debugCmd.defaultLabel = "调试: 强制完成";
debugCmd.defaultDesc = "立即完成当前研究";
debugCmd.defaultLabel = "ResearchBlueprintReader_DebugComplete".Translate();
debugCmd.defaultDesc = "ResearchBlueprintReader_DebugCompleteDesc".Translate();
debugCmd.icon = ContentFinder<Texture2D>.Get("UI/Designators/Dev", false);
debugCmd.action = delegate
{
@@ -320,7 +307,7 @@ namespace ArachnaeSwarm
var araTab = DefDatabase<ResearchTabDef>.GetNamedSilentFail("ARA_ResearchTab");
if (araTab == null)
{
Messages.Message("ARA_ResearchTab未找到", MessageTypeDefOf.RejectInput);
Messages.Message("ResearchBlueprintReader_TabNotFound".Translate(), MessageTypeDefOf.RejectInput);
return;
}
@@ -330,7 +317,7 @@ namespace ArachnaeSwarm
if (availableProjects.Count == 0)
{
Messages.Message("没有可用的科技项目", MessageTypeDefOf.NeutralEvent);
Messages.Message("ResearchBlueprintReader_NoProjectsAvailable".Translate(), MessageTypeDefOf.NeutralEvent);
return;
}
@@ -351,9 +338,9 @@ namespace ArachnaeSwarm
{
bool missingHidden = HasMissingHiddenPrerequisites(project);
if (missingHidden)
label = $"<color=#ff9900>{label} [需要隐藏前置]</color>";
label = $"<color=#ff9900>{label} [{"ResearchBlueprintReader_HiddenPrerequisite".Translate()}]</color>";
else
label = $"<color=#999999>{label} [需要前置条件]</color>";
label = $"<color=#999999>{label} [{"ResearchBlueprintReader_PrerequisitesNeeded".Translate()}]</color>";
}
var option = new FloatMenuOption(label, () => StartResearch(project))
@@ -373,7 +360,7 @@ namespace ArachnaeSwarm
catch (Exception ex)
{
Log.Error($"[ResearchBlueprintReader] Error in ShowResearchMenu: {ex}");
Messages.Message($"显示研究菜单时出错: {ex.Message}",
Messages.Message("ResearchBlueprintReader_MenuError".Translate(ex.Message),
MessageTypeDefOf.NegativeEvent);
}
}
@@ -423,9 +410,9 @@ namespace ArachnaeSwarm
builder.AppendLine(project.description.StripTags());
builder.AppendLine();
builder.AppendLine($"成本: {project.baseCost}");
builder.AppendLine($"所需蓝图数量: {project.techprintCount}");
builder.AppendLine($"当前全球进度: {Find.ResearchManager.GetProgress(project):F0}/{project.baseCost:F0}");
builder.AppendLine("ResearchBlueprintReader_ProjectCost".Translate() + $": {project.baseCost}");
builder.AppendLine("ResearchBlueprintReader_BlueprintCount".Translate() + $": {project.techprintCount}");
builder.AppendLine("ResearchBlueprintReader_CurrentProgress".Translate() + $": {Find.ResearchManager.GetProgress(project):F0}/{project.baseCost:F0}");
// 检查所有未完成的前置(包括隐藏的)
List<ResearchProjectDef> missingPrereqs = new List<ResearchProjectDef>();
@@ -453,7 +440,7 @@ namespace ArachnaeSwarm
if (missingPrereqs.Count > 0)
{
builder.AppendLine();
builder.AppendLine("<color=#ff9999>缺失的前置科技:</color>");
builder.AppendLine("<color=#ff9999>" + "ResearchBlueprintReader_MissingPrerequisites".Translate() + ":</color>");
foreach (var prereq in missingPrereqs)
{
@@ -462,7 +449,7 @@ namespace ArachnaeSwarm
project.hiddenPrerequisites.Contains(prereq);
if (isHidden)
builder.AppendLine($" • {label} <color=#ffcc00>[隐藏前置]</color>");
builder.AppendLine($" • {label} <color=#ffcc00>[{"ResearchBlueprintReader_MissingHiddenPrerequisites".Translate()}]</color>");
else
builder.AppendLine($" • {label}");
}
@@ -482,29 +469,31 @@ namespace ArachnaeSwarm
{
if (storedResearch.IsFinished)
{
builder.AppendLine($"<color=#00ff00>✓ 已研究: {storedResearch.LabelCap}</color>");
builder.AppendLine("<color=#00ff00>" + "ResearchBlueprintReader_StatusCompleted".Translate(storedResearch.LabelCap) + "</color>");
}
else
{
builder.AppendLine($"<color=#ff9900>🔒 正在研究: {storedResearch.LabelCap}</color>");
builder.AppendLine($"本建筑进度: {progress:F0}/{storedResearch.baseCost:F0} ({(progress / storedResearch.baseCost * 100):F1}%)");
builder.Append($"全球进度: {Find.ResearchManager.GetProgress(storedResearch):F0}/{storedResearch.baseCost:F0}");
builder.AppendLine("<color=#ff9900>" + "ResearchBlueprintReader_StatusResearching".Translate(storedResearch.LabelCap) + "</color>");
builder.AppendLine("ResearchBlueprintReader_BuildingProgress".Translate(
progress, storedResearch.baseCost, (progress / storedResearch.baseCost * 100)));
builder.Append("ResearchBlueprintReader_GlobalProgress".Translate(
Find.ResearchManager.GetProgress(storedResearch), storedResearch.baseCost));
// 显示研究速度
builder.AppendLine();
builder.Append($"研究速度: {ResearchSpeed:F1}/秒");
builder.Append("ResearchBlueprintReader_ResearchSpeed".Translate(ResearchSpeed));
if (researchStartTime > 0)
{
int days = (Find.TickManager.TicksGame - researchStartTime) / 60000;
builder.AppendLine();
builder.Append($"已研究时间: {days}天");
builder.Append("ResearchBlueprintReader_ResearchTime".Translate(days));
}
}
}
else
{
builder.Append("未选择研究项目");
builder.Append("ResearchBlueprintReader_NoProjectSelected".Translate());
}
return builder.ToString().TrimEndNewlines();

View File

@@ -179,7 +179,7 @@ namespace ArachnaeSwarm
Utilities.ResearchRemover.RemoveResearchProject(project, false);
// 发送消息
Messages.Message($"科技已丢失: {project.LabelCap}",
Messages.Message("ResearchManager_ResearchLost".Translate(project.LabelCap),
MessageTypeDefOf.NegativeEvent);
Log.Message($"[ResearchManager] Successfully removed research project: {project.defName}");
@@ -287,14 +287,15 @@ namespace ArachnaeSwarm
return;
}
Log.Message($"=== 研究管理器状态 ===");
Log.Message($"所有建筑: {Instance.allReaders.Count}");
Log.Message($"进行中研究: {Instance.researchBuildings.Count}");
Log.Message("ResearchManager_StatusTitle".Translate());
Log.Message("ResearchManager_TotalBuildings".Translate(Instance.allReaders.Count));
Log.Message("ResearchManager_ActiveResearch".Translate(Instance.researchBuildings.Count));
foreach (var kvp in Instance.researchBuildings)
{
int activeBuildings = kvp.Value.Count(b => b != null && !b.Destroyed);
Log.Message($" {kvp.Key.defName}: {activeBuildings}个活跃建筑 / {kvp.Value.Count}个总建筑");
Log.Message("ResearchManager_ProjectStatus".Translate(
kvp.Key.defName, activeBuildings, kvp.Value.Count));
}
}

View File

@@ -132,12 +132,6 @@ namespace ArachnaeSwarm.Utilities
// 7. 重新应用所有mod取消该科技的效果
manager.ReapplyAllMods();
// 8. 发送通知
Messages.Message("ResearchRemovedMessage".Translate(projectDef.LabelCap), MessageTypeDefOf.NeutralEvent);
// 9. 发送信号
Find.SignalManager.SendSignal(new Signal("ResearchRemoved", projectDef.defName));
Log.Message($"[ResearchRemover] Successfully removed research project: {projectDef.defName}");
return true;
}

View File

@@ -18,8 +18,9 @@ namespace ArachnaeSwarm
public override bool TryMakePreToilReservations(bool errorOnFailed)
{
// 只需要保留目标位置
return pawn.Reserve(job.targetA, job, 1, -1, null, errorOnFailed);
// 原地工作,不需要保留特定单元格
// 我们只保留自己的位置作为工作位置
return pawn.Reserve(pawn, job, 1, -1, null, errorOnFailed);
}
protected override IEnumerable<Toil> MakeNewToils()
@@ -27,15 +28,13 @@ namespace ArachnaeSwarm
// 确保自身有蜜罐需求且达到挤出阈值
this.FailOn(() => HoneyNeed == null || !CanExtract(HoneyNeed));
// Toil 1: 移动到目标位置
yield return Toils_Goto.GotoCell(TargetIndex.A, PathEndMode.Touch);
// Toil 2: 执行挤出工作
// Toil 1: 原地执行挤出工作
Toil extractToil = new Toil
{
initAction = delegate
{
// 初始化挤出动作
pawn.pather.StopDead();
},
tickAction = delegate
{
@@ -45,7 +44,7 @@ namespace ArachnaeSwarm
defaultDuration = ExtractDurationTicks
};
// 添加特效和音效
// 添加特效和音效(在原地显示)
extractToil.WithEffect(() => ExtractEffect, TargetIndex.A);
extractToil.PlaySustainerOrSound(() => ExtractSound);
@@ -55,12 +54,13 @@ namespace ArachnaeSwarm
ExtractHoney();
});
// 进度条显示在Pawn自己身上
extractToil.WithProgressBar(TargetIndex.A,
() => extractToil.actor.jobs.curDriver.ticksLeftThisToil / (float)ExtractDurationTicks);
yield return extractToil;
// Toil 3: 完成后的清理
// Toil 2: 完成后的清理
yield return new Toil
{
initAction = delegate
@@ -69,7 +69,8 @@ namespace ArachnaeSwarm
// 如果蜜罐存量达到阈值,可以安排下一个挤出工作
if (HoneyNeed != null && CanExtract(HoneyNeed))
{
pawn.jobs.jobQueue.EnqueueLast(CreateExtractJob());
// 不再创建新工作让WorkGiver系统处理
// 这样可以避免无限循环
}
},
defaultCompleteMode = ToilCompleteMode.Instant
@@ -121,36 +122,14 @@ namespace ArachnaeSwarm
Thing jelly = ThingMaker.MakeThing(DefDatabase<ThingDef>.GetNamed("ARA_InsectJelly"));
jelly.stackCount = jellyCount;
// 尝试将虫蜜放在目标位置
GenPlace.TryPlaceThing(jelly, job.targetA.Cell, pawn.Map, ThingPlaceMode.Near);
// 在Pawn当前位置放置虫蜜
GenPlace.TryPlaceThing(jelly, pawn.Position, pawn.Map, ThingPlaceMode.Near);
// 减少蜜罐存量
HoneyNeed.ExtractHoney(jellyCount);
// 播放视觉反馈
MoteMaker.ThrowText(job.targetA.Cell.ToVector3Shifted(), pawn.Map,"ARA_ExtractHoney_Message".Translate(jellyCount));
}
// 创建挤出工作的辅助方法
private Job CreateExtractJob()
{
// 寻找最近的空地
IntVec3 targetCell = FindNearestEmptyCell(pawn.Position, pawn.Map);
Job job = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("ARA_ExtractHoney"), targetCell);
return job;
}
// 寻找最近的空单元格
private IntVec3 FindNearestEmptyCell(IntVec3 from, Map map)
{
if (CellFinder.TryFindBestPawnStandCell(pawn, out IntVec3 cell, false))
{
return cell;
}
// 如果找不到最佳位置,使用原位置
return from;
MoteMaker.ThrowText(pawn.DrawPos, pawn.Map, "ARA_ExtractHoney_Message".Translate(jellyCount));
}
}
}

View File

@@ -12,16 +12,27 @@ namespace ArachnaeSwarm
private const float FoodTransferPerTick = 0.01f; // 每tick传输的食物量
private Pawn TargetPawn => job.targetA.Pawn;
private Need_HoneyProduction HoneyNeed => pawn.needs?.TryGetNeed<Need_HoneyProduction>();
// 获取喂食者的蜜罐需求
private Need_HoneyProduction FeederHoneyNeed => pawn.needs?.TryGetNeed<Need_HoneyProduction>();
// 获取目标的食物需求
private Need_Food TargetFoodNeed => TargetPawn.needs?.TryGetNeed<Need_Food>();
// 使用喂养效果 - 参考Toils_Ingest中的用法
// 检查目标是否有蜜罐需求
private Need_HoneyProduction TargetHoneyNeed => TargetPawn.needs?.TryGetNeed<Need_HoneyProduction>();
// 使用喂养效果
private static readonly EffecterDef FeedEffect = ARA_EffecterDefOf.EatVegetarian;
private static readonly SoundDef FeedSound = SoundDefOf.RawMeat_Eat;
public override bool TryMakePreToilReservations(bool errorOnFailed)
{
if (TargetPawn == null || TargetFoodNeed == null || HoneyNeed == null)
if (TargetPawn == null || TargetFoodNeed == null || FeederHoneyNeed == null)
return false;
// 检查目标是否有蜜罐需求,如果有则不能喂食
if (TargetHoneyNeed != null)
return false;
// 保留目标pawn的位置以便接近
@@ -32,13 +43,16 @@ namespace ArachnaeSwarm
{
// 确保目标有效
this.FailOnDespawnedOrNull(TargetIndex.A);
this.FailOn(() => TargetPawn.Dead || TargetFoodNeed == null || HoneyNeed == null);
this.FailOn(() => TargetPawn.Dead || TargetFoodNeed == null || FeederHoneyNeed == null);
// 额外检查:目标不能有蜜罐需求
this.FailOn(() => TargetHoneyNeed != null);
// Toil 1: 移动到目标面前
yield return Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch)
.FailOnDespawnedOrNull(TargetIndex.A);
// Toil 2: 进行喂养工作参考Toils_Ingest中的效果添加方式
// Toil 2: 进行喂养工作
Toil feedToil = new Toil
{
initAction = delegate
@@ -48,7 +62,7 @@ namespace ArachnaeSwarm
tickAction = delegate
{
// 每tick检查是否还能继续喂养
if (HoneyNeed.CurLevel <= 0 || TargetFoodNeed.CurLevelPercentage >= 1.0f)
if (FeederHoneyNeed.CurLevel <= 0 || TargetFoodNeed.CurLevelPercentage >= 1.0f)
{
ReadyForNextToil();
return;
@@ -56,7 +70,7 @@ namespace ArachnaeSwarm
// 计算本次tick传输的量
float transferAmount = FoodTransferPerTick;
float honeyAvailable = HoneyNeed.CurLevel;
float honeyAvailable = FeederHoneyNeed.CurLevel;
// 确保不超过蜜罐存量
if (transferAmount > honeyAvailable)
@@ -68,14 +82,14 @@ namespace ArachnaeSwarm
transferAmount = targetFoodSpace;
// 执行传输
HoneyNeed.ExtractHoney(transferAmount);
FeederHoneyNeed.ExtractHoney(transferAmount);
TargetFoodNeed.CurLevel += transferAmount;
},
defaultCompleteMode = ToilCompleteMode.Delay,
defaultDuration = FeedDurationTicks
};
// 添加特效和音效参考Toils_Ingest.AddIngestionEffects
// 添加特效和音效
feedToil.WithEffect(() => FeedEffect, TargetIndex.A);
feedToil.PlaySustainerOrSound(() => FeedSound);
@@ -91,12 +105,12 @@ namespace ArachnaeSwarm
yield return feedToil;
// 修改移除了第三个Toil中的提示消息只剩下一个简单的完成Toil
// 完成Toil
yield return new Toil
{
initAction = delegate
{
// 这里可以放置任何清理代码,但不要显示消息
// 清理代码
},
defaultCompleteMode = ToilCompleteMode.Instant
};

View File

@@ -37,8 +37,8 @@ namespace ArachnaeSwarm
public override bool TryMakePreToilReservations(bool errorOnFailed)
{
// 只需要保留目标位置
return pawn.Reserve(job.targetA, job, 1, -1, null, errorOnFailed);
// 原地工作,不需要保留特定单元格
return pawn.Reserve(pawn, job, 1, -1, null, errorOnFailed);
}
protected override IEnumerable<Toil> MakeNewToils()
@@ -49,15 +49,13 @@ namespace ArachnaeSwarm
this.FailOn(() => !StripComp.CanStripNow(pawn));
this.FailOn(() => !StripComp.CanStripChitin); // 检查开关
// Toil 1: 移动到目标位置
yield return Toils_Goto.GotoCell(TargetIndex.A, PathEndMode.Touch);
// Toil 2: 执行剥离工作
// Toil 1: 原地执行剥离工作
Toil stripToil = new Toil
{
initAction = delegate
{
// 初始化剥离动作
pawn.pather.StopDead();
},
tickAction = delegate
{
@@ -77,13 +75,13 @@ namespace ArachnaeSwarm
StripChitin();
});
// 进度条显示在Pawn自己身上
stripToil.WithProgressBar(TargetIndex.A,
() => stripToil.actor.jobs.curDriver.ticksLeftThisToil / (float)StripDurationTicks,
interpolateBetweenActorAndTarget: true);
() => stripToil.actor.jobs.curDriver.ticksLeftThisToil / (float)StripDurationTicks);
yield return stripToil;
// Toil 3: 完成后的清理
// Toil 2: 完成后的清理
yield return new Toil
{
initAction = delegate
@@ -91,11 +89,7 @@ namespace ArachnaeSwarm
// 记录剥离时间
StripComp?.NotifyStripped();
// 如果甲壳存量仍然达到阈值,可以安排下一个剥离工作
if (ChitinNeed != null && StripComp != null && StripComp.CanStripNow(pawn))
{
pawn.jobs.jobQueue.EnqueueLast(CreateStripJob());
}
// 不再自动安排下一个工作让WorkGiver系统处理
},
defaultCompleteMode = ToilCompleteMode.Instant
};
@@ -124,37 +118,15 @@ namespace ArachnaeSwarm
Thing carapace = ThingMaker.MakeThing(carapaceDef);
carapace.stackCount = stripCount;
// 尝试将甲壳放在目标位置
GenPlace.TryPlaceThing(carapace, job.targetA.Cell, pawn.Map, ThingPlaceMode.Near);
// 在Pawn当前位置放置甲壳
GenPlace.TryPlaceThing(carapace, pawn.Position, pawn.Map, ThingPlaceMode.Near);
// 减少甲壳存量
ChitinNeed.ReduceChitin(stripCount);
// 播放视觉反馈
MoteMaker.ThrowText(job.targetA.Cell.ToVector3Shifted(), pawn.Map,
MoteMaker.ThrowText(pawn.DrawPos, pawn.Map,
"ARA_StripChitin_Message".Translate(stripCount));
}
// 创建剥离工作的辅助方法
private Job CreateStripJob()
{
// 寻找最近的空地
IntVec3 targetCell = FindNearestEmptyCell(pawn.Position, pawn.Map);
Job job = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("ARA_StripChitin"), targetCell);
return job;
}
// 寻找最近的空单元格
private IntVec3 FindNearestEmptyCell(IntVec3 from, Map map)
{
if (CellFinder.TryFindBestPawnStandCell(pawn, out IntVec3 cell, false))
{
return cell;
}
// 如果找不到最佳位置,使用原位置
return from;
}
}
}

View File

@@ -9,7 +9,7 @@ namespace ArachnaeSwarm
public class JobDriver_SwarmMaintain : JobDriver
{
// 工作完成后增加的维护度
public const float MaintenancePerWork = 25f;
public const float MaintenancePerWork = 100f;
// 工作时间ticks
private const int WorkDuration = 600; // 10秒

View File

@@ -1,52 +1,16 @@
// File: Need_HoneyProduction.cs
using RimWorld;
using UnityEngine;
using Verse;
namespace ArachnaeSwarm
{
public class HoneyProductionExtension : DefModExtension
{
// 蜜罐生产的基础转化率(相对于食物流失的百分比)
public float baseConversionRate = 0.5f;
// 最大蜜罐容量(可选,覆盖默认值)
public float maxHoneyCapacity = 1f;
// 是否启用蜜罐生产
public bool enableHoneyProduction = true;
// 生产速率乘数(影响生产速度)
public float productionSpeedFactor = 1f;
// 蜜罐类别对应的生产效率(可选,覆盖默认值)
public float fullProductionEfficiency = 1.5f;
public float highProductionEfficiency = 1.2f;
public float mediumProductionEfficiency = 1f;
public float lowProductionEfficiency = 0.5f;
public float emptyProductionEfficiency = 0f;
// 生产间隔ticks可选覆盖默认值
public int productionInterval = 150;
public static HoneyProductionExtension Get(Pawn pawn)
{
if (pawn?.def?.GetModExtension<HoneyProductionExtension>() is HoneyProductionExtension ext)
return ext;
return null;
}
// 获取转化率
public float GetConversionRate()
{
return baseConversionRate * productionSpeedFactor;
}
}
public class Need_HoneyProduction : Need
{
// 转化率:多少食物流失转换为蜂蜜
public float ConversionRate = 10f;
// 基础流失速率(与食物需要对应)
private const float BaseHoneyGainPerTick = 2.6666667E-05f * 0.5f; // 食物流失速率的50%作为默认值
private const float BaseHoneyGainPerTick = 2.6666667E-05f;
// 用于存储对食物需要的引用
private Need_Food cachedFoodNeed;
@@ -54,25 +18,8 @@ namespace ArachnaeSwarm
// 当前类别
private HoneyProductionCategory curCategoryInt = HoneyProductionCategory.Empty;
// 上次满的时间点
private int lastFullTick = -99999;
// 缓存的ModExtension
private HoneyProductionExtension cachedExtension;
// 蜜罐的最大容量 - 优先使用ModExtension的值
public override float MaxLevel
{
get
{
var ext = GetExtension();
if (ext != null && ext.maxHoneyCapacity > 0)
{
return ext.maxHoneyCapacity;
}
return FoodNeed?.MaxLevel ?? 1f;
}
}
// 最大容量 - 跟随食物需求的最大容量
public override float MaxLevel => FoodNeed?.MaxLevel ?? 1f;
// 当前类别
public HoneyProductionCategory CurCategory => curCategoryInt;
@@ -83,72 +30,6 @@ namespace ArachnaeSwarm
// 是否为空
public bool IsEmpty => CurCategory == HoneyProductionCategory.Empty;
// 当前类别对应的生产效率
public float ProductionEfficiency
{
get
{
var ext = GetExtension();
// 如果有扩展定义,使用扩展的值
if (ext != null)
{
switch (curCategoryInt)
{
case HoneyProductionCategory.Full:
return ext.fullProductionEfficiency;
case HoneyProductionCategory.High:
return ext.highProductionEfficiency;
case HoneyProductionCategory.Medium:
return ext.mediumProductionEfficiency;
case HoneyProductionCategory.Low:
return ext.lowProductionEfficiency;
case HoneyProductionCategory.Empty:
return ext.emptyProductionEfficiency;
default:
return 0f;
}
}
// 默认值
switch (curCategoryInt)
{
case HoneyProductionCategory.Full:
return 1.0f;
case HoneyProductionCategory.High:
return 0.8f;
case HoneyProductionCategory.Medium:
return 0.5f;
case HoneyProductionCategory.Low:
return 0.3f;
case HoneyProductionCategory.Empty:
return 0f;
default:
return 0f;
}
}
}
// 获取扩展
private HoneyProductionExtension GetExtension()
{
if (cachedExtension == null && pawn != null)
{
cachedExtension = pawn.def?.GetModExtension<HoneyProductionExtension>();
}
return cachedExtension;
}
// 是否启用蜜罐生产
private bool IsEnabled
{
get
{
var ext = GetExtension();
return ext == null || ext.enableHoneyProduction; // 默认启用
}
}
// 获取食物需要的引用
private Need_Food FoodNeed
{
@@ -174,19 +55,9 @@ namespace ArachnaeSwarm
};
}
public override void ExposeData()
{
base.ExposeData();
Scribe_Values.Look(ref lastFullTick, "lastFullTick", -99999);
}
public override void NeedInterval()
{
// 如果不启用,直接返回
if (!IsEnabled)
return;
// 检查是否需要冻结(与食物需要类似的条件)
// 检查是否需要冻结
if (IsFrozen)
{
return;
@@ -195,17 +66,11 @@ namespace ArachnaeSwarm
// 获取食物需要的流失速率
float foodFallRate = GetFoodFallRate();
// 获取转化率从ModExtension或使用默认值
float conversionRate = GetExtension()?.GetConversionRate() ?? 0.5f;
// 蜜罐的增长速率 = 食物流失速率 × 转化率
float honeyGainRate = foodFallRate * conversionRate;
// 获取生产间隔
int interval = GetExtension()?.productionInterval ?? 150;
float honeyGainRate = foodFallRate * ConversionRate;
// 应用间隔
CurLevel += honeyGainRate * interval;
CurLevel += honeyGainRate * 150; // 150 ticks间隔
// 确保不超过最大容量
if (CurLevel > MaxLevel)
@@ -213,12 +78,6 @@ namespace ArachnaeSwarm
// 更新类别
UpdateCategory();
// 记录满的时间
if (IsFull)
{
lastFullTick = Find.TickManager.TicksGame;
}
}
// 获取食物流失速率
@@ -227,7 +86,7 @@ namespace ArachnaeSwarm
if (FoodNeed == null)
{
// 如果没有食物需要,使用默认值
return BaseHoneyGainPerTick / 0.5f; // 反向计算基础食物流失速率
return BaseHoneyGainPerTick;
}
// 获取当前食物类别对应的流失速率
@@ -275,49 +134,6 @@ namespace ArachnaeSwarm
curCategoryInt = HoneyProductionCategory.Empty;
}
// 获取提示字符串
public override string GetTipString()
{
string text = (LabelCap + ": " + CurLevelPercentage.ToStringPercent()).Colorize(ColoredText.TipSectionTitleColor);
text += "\n" + def.description;
text += $"\n{"ARA_HoneyProduction.Efficiency".Translate()} {ProductionEfficiency.ToStringPercent()}";
// 获取每tick的速率
float foodFallPerTick = GetFoodFallRate();
float conversionRate = GetExtension()?.GetConversionRate() ?? 0.5f;
float honeyGainPerTick = foodFallPerTick * conversionRate;
// 转换为每秒1秒 = 60tick
float foodFallPerSecond = foodFallPerTick * 60f;
float honeyGainPerSecond = honeyGainPerTick * 60f;
text += $"\n{"ARA_HoneyProduction.FoodDrainRate".Translate()}: {foodFallPerSecond:0.#####}/ {"LetterSecond".Translate()}";
text += $"\n{"ARA_HoneyProduction.HoneyGainRate".Translate()}: {honeyGainPerSecond:0.#####}/ {"LetterSecond".Translate()}";
// 显示转化率信息
if (GetExtension() != null)
{
text += $"\n{"ARA_HoneyProduction.ConversionRate".Translate()}: {conversionRate:P1}";
if (GetExtension().productionSpeedFactor != 1f)
{
text += $"\n{"ARA_HoneyProduction.SpeedFactor".Translate()}: {GetExtension().productionSpeedFactor:F2}";
}
}
if (IsFull)
{
text += $"\n\n{"ARA_HoneyProduction.FullWarning".Translate()}";
}
// 显示是否启用
if (!IsEnabled)
{
text += $"\n\n<color=orange>{"ARA_HoneyProduction.Disabled".Translate()}</color>";
}
return text;
}
// 获取类别标签
public string GetCategoryLabel()
{
@@ -338,24 +154,6 @@ namespace ArachnaeSwarm
}
}
// 在UI上绘制
public override void DrawOnGUI(Rect rect, int maxThresholdMarkers = int.MaxValue, float customMargin = -1f, bool drawArrows = true, bool doTooltip = true, Rect? rectForTooltip = null, bool drawLabel = true)
{
// 如果不启用,不显示
if (!IsEnabled)
return;
if (threshPercents == null)
{
threshPercents = new System.Collections.Generic.List<float>
{
0.25f, 0.5f, 0.75f
};
}
base.DrawOnGUI(rect, maxThresholdMarkers, customMargin, false, doTooltip, rectForTooltip, drawLabel);
}
// 是否冻结
protected override bool IsFrozen
{
@@ -374,7 +172,7 @@ namespace ArachnaeSwarm
}
// GUI变化箭头总是显示增长
public override int GUIChangeArrow => IsEnabled ? 1 : 0;
public override int GUIChangeArrow => 1;
// 调试调整百分比
protected override void OffsetDebugPercent(float offsetPercent)

View File

@@ -0,0 +1,28 @@
using RimWorld;
using Verse;
namespace ArachnaeSwarm
{
public class CompProperties_SwarmMaintainer : CompProperties
{
// 是否在信息面板显示调试信息
public bool showDebugInfo = false;
// 维护工作的优先级(相对其他工作)
public int workPriority = 50;
// 维护技能类型(可选)
public SkillDef relevantSkill = SkillDefOf.Construction;
// 最小技能等级(可选)
public int minimumSkillLevel = 0;
// 是否必须有虫群意识hediff
public bool requiresHiveMind = true;
public CompProperties_SwarmMaintainer()
{
compClass = typeof(Comp_SwarmMaintainer);
}
}
}

View File

@@ -0,0 +1,55 @@
using RimWorld;
using Verse;
using System.Collections.Generic;
namespace ArachnaeSwarm
{
public class Comp_SwarmMaintainer : ThingComp
{
// 属性访问器
public CompProperties_SwarmMaintainer Props => (CompProperties_SwarmMaintainer)props;
// 简单的属性访问
public bool CanMaintainSwarmBuildings => true; // 默认都可以维护
// 维护效率(可选)
public float MaintenanceEfficiency
{
get
{
// 可以根据Pawn的技能或其他属性调整效率
if (parent is Pawn pawn)
{
// 如果有建造技能,效率更高
if (pawn.skills != null)
{
return 1.0f + (pawn.skills.GetSkill(SkillDefOf.Construction).Level * 0.02f);
}
}
return 1.0f; // 默认效率
}
}
// 组件不需要复杂的逻辑,主要用于标记
public override void PostSpawnSetup(bool respawningAfterLoad)
{
base.PostSpawnSetup(respawningAfterLoad);
}
public override void PostExposeData()
{
base.PostExposeData();
// 这个组件不需要保存额外数据
}
// 可选:提供一些简单的调试信息
public override string CompInspectStringExtra()
{
if (Props.showDebugInfo && DebugSettings.godMode)
{
return $"虫群维护者 (效率: {MaintenanceEfficiency:P0})";
}
return null;
}
}
}

View File

@@ -0,0 +1,51 @@
using System.Collections.Generic;
using RimWorld;
using Verse;
namespace ArachnaeSwarm
{
public class RoomRoleWorker_JellyVat : RoomRoleWorker
{
// 孵化间的评分 - 比重很小设为10分实验室是60分
private const float ScorePerJellyVat = 100f;
// 最低分数要求 - 需要至少1个孵化器才能成为孵化间
private const float MinimumScore = 10f;
public override float GetScore(Room room)
{
int JellyVatCount = 0;
// 检查房间内和相邻的所有建筑
List<Thing> containedAndAdjacentThings = room.ContainedAndAdjacentThings;
for (int i = 0; i < containedAndAdjacentThings.Count; i++)
{
Thing thing = containedAndAdjacentThings[i];
// 检查建筑的工作台房间角色是否为ARA_JellyVat_Room
if (thing.def.building?.workTableRoomRole != null &&
thing.def.building.workTableRoomRole.defName == "ARA_JellyVat_Room")
{
JellyVatCount++;
}
}
// 如果有孵化器,返回分数
float score = ScorePerJellyVat * JellyVatCount;
// 必须有至少一个孵化器才能成为孵化间
return JellyVatCount > 0 ? score : 0f;
}
public override float GetScoreDeltaIfBuildingPlaced(Room room, ThingDef buildingDef)
{
// 如果放置的建筑具有ARA_JellyVat_Room工作台房间角色返回分数增量
if (buildingDef.building?.workTableRoomRole != null &&
buildingDef.building.workTableRoomRole.defName == "ARA_JellyVat_Room")
{
return ScorePerJellyVat;
}
return 0f;
}
}
}

View File

@@ -0,0 +1,117 @@
using RimWorld;
using System.Collections.Generic;
using Verse;
using Verse.AI;
namespace ArachnaeSwarm
{
public class WorkGiver_ExtractHoney : WorkGiver_Scanner
{
public override PathEndMode PathEndMode => PathEndMode.Touch;
public override Danger MaxPathDanger(Pawn pawn)
{
return Danger.None;
}
// 扫描所有虫族成员,检查是否需要挤出蜂蜜
public override IEnumerable<Thing> PotentialWorkThingsGlobal(Pawn pawn)
{
// 返回所有有蜂蜜需求的虫族Pawn
IReadOnlyList<Pawn> allPawns = pawn.Map.mapPawns.AllPawnsSpawned;
List<Thing> workThings = new List<Thing>();
foreach (Pawn potentialPawn in allPawns)
{
// 只检查玩家阵营的虫族成员
if (potentialPawn.Faction == Faction.OfPlayer &&
HasHoneyNeed(potentialPawn))
{
workThings.Add(potentialPawn);
}
}
return workThings;
}
public override bool ShouldSkip(Pawn pawn, bool forced = false)
{
// 检查Pawn是否属于玩家阵营
if (pawn.Faction != Faction.OfPlayer)
return true;
// 检查Pawn是否是虫族成员
if (!IsSwarmMember(pawn))
return true;
// 检查Pawn是否能够工作
if (pawn.Dead || pawn.Downed || pawn.InMentalState)
return true;
// 检查Pawn是否正在执行其他挤出工作
if (pawn.CurJobDef == ARA_JobDefOf.ARA_ExtractHoney)
return true;
return false;
}
public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false)
{
// 如果目标不是Pawn返回false
if (t == null || !(t is Pawn targetPawn))
return false;
// 检查是否是挤出自己的蜂蜜
if (targetPawn != pawn)
return false; // 只能挤出自己的蜂蜜
// 检查目标Pawn是否有蜂蜜需求
Need_HoneyProduction honeyNeed = targetPawn.needs?.TryGetNeed<Need_HoneyProduction>();
if (honeyNeed == null)
return false;
// 检查是否可以挤出
return CanExtractNow(honeyNeed);
}
public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false)
{
if (t == null || !(t is Pawn targetPawn) || targetPawn != pawn)
return null;
// 创建挤出工作使用Pawn自身作为目标
Job job = JobMaker.MakeJob(ARA_JobDefOf.ARA_ExtractHoney, pawn);
job.count = 1;
return job;
}
// 检查是否有蜂蜜需求
private bool HasHoneyNeed(Pawn pawn)
{
return pawn.needs?.TryGetNeed<Need_HoneyProduction>() != null;
}
// 检查是否可以立即挤出
private bool CanExtractNow(Need_HoneyProduction honeyNeed)
{
// 如果MaxLevel大于1.5需要超过80%储量才考虑挤蜜
if (honeyNeed.MaxLevel > 1.5f)
{
return honeyNeed.CurLevelPercentage > 0.8f;
}
// 否则在大于1时挤蜜
else
{
return honeyNeed.CurLevel >= 1.0f;
}
}
// 检查是否是虫族成员
private bool IsSwarmMember(Pawn pawn)
{
return pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindMaster) ||
pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindDrone) ||
pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindWorker);
}
}
}

View File

@@ -0,0 +1,171 @@
using RimWorld;
using System.Collections.Generic;
using Verse;
using Verse.AI;
namespace ArachnaeSwarm
{
public class WorkGiver_FeedWithHoney : WorkGiver_Scanner
{
public override PathEndMode PathEndMode => PathEndMode.Touch;
public override Danger MaxPathDanger(Pawn pawn)
{
return Danger.None;
}
// 扫描所有需要喂食的Pawn没有蜜罐需求但需要食物的虫族成员
public override IEnumerable<Thing> PotentialWorkThingsGlobal(Pawn pawn)
{
IReadOnlyList<Pawn> allPawns = pawn.Map.mapPawns.AllPawnsSpawned;
List<Thing> workThings = new List<Thing>();
foreach (Pawn potentialPawn in allPawns)
{
// 只检查玩家阵营的Pawn
if (potentialPawn.Faction == Faction.OfPlayer &&
!potentialPawn.Dead &&
!potentialPawn.Downed &&
!HasHoneyNeed(potentialPawn) && // 不能有蜜罐需求
HasFoodNeed(potentialPawn) && // 必须有食物需求
IsFeedingAllowed(potentialPawn)) // 其他条件检查
{
workThings.Add(potentialPawn);
}
}
return workThings;
}
public override bool ShouldSkip(Pawn pawn, bool forced = false)
{
// 检查Pawn是否属于玩家阵营
if (pawn.Faction != Faction.OfPlayer)
return true;
// 检查Pawn是否是虫族成员
if (!IsSwarmMember(pawn))
return true;
// 检查Pawn是否能够工作
if (pawn.Dead || pawn.Downed || pawn.InMentalState)
return true;
// 检查Pawn是否有蜂蜜需求
if (!HasHoneyNeed(pawn))
return true;
// 检查Pawn的蜜罐是否有足够的蜂蜜
Need_HoneyProduction honeyNeed = pawn.needs?.TryGetNeed<Need_HoneyProduction>();
if (honeyNeed == null || honeyNeed.CurLevel <= 0.25)
return true;
// 检查Pawn是否正在执行其他喂食工作
if (pawn.CurJobDef == ARA_JobDefOf.ARA_FeedWithHoney)
return true;
return false;
}
public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false)
{
// 如果目标不是Pawn返回false
if (t == null || !(t is Pawn targetPawn))
return false;
// 检查目标是否有效
if (targetPawn.Dead || targetPawn.Downed)
return false;
// 检查目标是否是喂食者自己
if (targetPawn == pawn)
return false; // 不能喂食自己
// 检查目标是否有蜜罐需求
if (HasHoneyNeed(targetPawn))
return false; // 不能喂食有蜜罐需求的目标
// 检查目标是否有食物需求
Need_Food targetFoodNeed = targetPawn.needs?.TryGetNeed<Need_Food>();
if (targetFoodNeed == null)
return false;
// 检查目标是否已经吃饱
if (targetFoodNeed.CurLevelPercentage >= 0.95f) // 95%以上算吃饱
return false;
// 检查喂食者是否有蜂蜜需求
Need_HoneyProduction feederHoneyNeed = pawn.needs?.TryGetNeed<Need_HoneyProduction>();
if (feederHoneyNeed == null)
return false;
// 检查喂食者是否有足够的蜂蜜
if (feederHoneyNeed.CurLevel <= 0)
return false;
// 检查Pawn是否可以到达目标
if (!pawn.CanReserveAndReach(targetPawn, PathEndMode.Touch, pawn.NormalMaxDanger(), 1, -1, null, forced))
return false;
return true;
}
public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false)
{
if (t == null || !(t is Pawn targetPawn))
return null;
// 创建喂食工作
Job job = JobMaker.MakeJob(ARA_JobDefOf.ARA_FeedWithHoney, targetPawn);
job.count = 1;
return job;
}
// 检查是否有蜂蜜需求
private bool HasHoneyNeed(Pawn pawn)
{
return pawn.needs?.TryGetNeed<Need_HoneyProduction>() != null;
}
// 检查是否有食物需求
private bool HasFoodNeed(Pawn pawn)
{
return pawn.needs?.TryGetNeed<Need_Food>() != null;
}
// 检查是否是虫族成员
private bool IsSwarmMember(Pawn pawn)
{
return pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindMaster) ||
pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindDrone) ||
pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindWorker);
}
// 检查是否允许喂食
private bool IsFeedingAllowed(Pawn pawn)
{
// 可以添加额外的条件,比如:
// - 是否处于特殊状态
// - 是否有特殊的Hediff阻止喂食
// - 是否正在被喂食等
// 检查是否正在被其他虫族喂食
if (pawn.jobs?.curDriver is JobDriver_FeedWithHoney)
return false;
// 检查是否有其他虫族正在向这个Pawn移动以喂食
IReadOnlyList<Pawn> allPawns = pawn.Map.mapPawns.AllPawnsSpawned;
foreach (Pawn otherPawn in allPawns)
{
if (otherPawn != pawn &&
otherPawn.CurJobDef == ARA_JobDefOf.ARA_FeedWithHoney &&
otherPawn.CurJob.targetA.Thing == pawn)
{
return false; // 已经有人正在喂食这个Pawn
}
}
return true;
}
}
}

View File

@@ -0,0 +1,95 @@
using RimWorld;
using System.Collections.Generic;
using Verse;
using Verse.AI;
namespace ArachnaeSwarm
{
public class WorkGiver_StripChitin : WorkGiver_Scanner
{
public override PathEndMode PathEndMode => PathEndMode.Touch;
public override Danger MaxPathDanger(Pawn pawn)
{
return Danger.None;
}
// 扫描所有有甲壳剥离组件的虫族成员
public override IEnumerable<Thing> PotentialWorkThingsGlobal(Pawn pawn)
{
IReadOnlyList<Pawn> allPawns = pawn.Map.mapPawns.AllPawnsSpawned;
List<Thing> workThings = new List<Thing>();
foreach (Pawn potentialPawn in allPawns)
{
// 检查是否有甲壳剥离组件
if (potentialPawn.TryGetComp<Comp_ChitinStripping>() != null &&
potentialPawn.Faction == Faction.OfPlayer)
{
workThings.Add(potentialPawn);
}
}
return workThings;
}
public override bool ShouldSkip(Pawn pawn, bool forced = false)
{
// 检查Pawn是否属于玩家阵营
if (pawn.Faction != Faction.OfPlayer)
return true;
// 检查Pawn是否是虫族成员
if (!IsSwarmMember(pawn))
return true;
// 检查Pawn是否能够工作
if (pawn.Dead || pawn.Downed || pawn.InMentalState)
return true;
// 检查Pawn是否正在执行其他剥离工作
if (pawn.CurJobDef == ARA_JobDefOf.ARA_StripChitin)
return true;
return false;
}
public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false)
{
// 如果目标不是Pawn返回false
if (t == null || !(t is Pawn targetPawn))
return false;
// 检查是否是剥离自己的甲壳
if (targetPawn != pawn)
return false; // 只能剥离自己的甲壳
// 获取剥离组件
Comp_ChitinStripping stripComp = targetPawn.TryGetComp<Comp_ChitinStripping>();
if (stripComp == null)
return false;
// 检查是否可以立即剥离
return stripComp.CanStripNow(pawn) && stripComp.CanStripChitin;
}
public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false)
{
if (t == null || !(t is Pawn targetPawn) || targetPawn != pawn)
return null;
// 创建剥离工作使用Pawn自身作为目标
Job job = JobMaker.MakeJob(ARA_JobDefOf.ARA_StripChitin, pawn);
job.count = 1;
return job;
}
// 检查是否是虫族成员
private bool IsSwarmMember(Pawn pawn)
{
return pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindMaster) ||
pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindDrone) ||
pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindWorker);
}
}
}

View File

@@ -0,0 +1,110 @@
using RimWorld;
using System.Collections.Generic;
using Verse;
using Verse.AI;
namespace ArachnaeSwarm
{
public class WorkGiver_SwarmMaintain : WorkGiver_Scanner
{
public override PathEndMode PathEndMode => PathEndMode.Touch;
public override Danger MaxPathDanger(Pawn pawn)
{
return Danger.Some;
}
public override IEnumerable<Thing> PotentialWorkThingsGlobal(Pawn pawn)
{
// 获取所有需要维护的建筑
List<Thing> allThings = pawn.Map.listerThings.AllThings;
List<Thing> maintenanceThings = new List<Thing>();
foreach (Thing thing in allThings)
{
if (thing.TryGetComp<Comp_SwarmMaintenance>() != null)
{
maintenanceThings.Add(thing);
}
}
return maintenanceThings;
}
public override bool ShouldSkip(Pawn pawn, bool forced = false)
{
// 检查Pawn是否属于玩家阵营
if (pawn.Faction != Faction.OfPlayer)
return true;
// 检查Pawn是否有虫群维护者组件
var maintainerComp = pawn.TryGetComp<Comp_SwarmMaintainer>();
if (maintainerComp == null)
return true;
// 检查组件配置要求
var props = maintainerComp.Props;
if (props != null)
{
// 如果要求必须有虫群意识hediff
if (props.requiresHiveMind && !IsSwarmMember(pawn))
return true;
// 检查最小技能等级要求
if (props.minimumSkillLevel > 0 && pawn.skills != null)
{
var skill = pawn.skills.GetSkill(props.relevantSkill);
if (skill == null || skill.Level < props.minimumSkillLevel)
return true;
}
}
// 检查Pawn是否能够工作
if (pawn.Dead || pawn.Downed || pawn.InMentalState)
return true;
// 检查Pawn是否有能力进行维护工作
if (pawn.WorkTagIsDisabled(WorkTags.ManualSkilled))
return true;
return false;
}
public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false)
{
if (t == null || t.Destroyed || !t.Spawned)
return false;
// 检查Pawn是否可以到达建筑
if (!pawn.CanReserveAndReach(t, PathEndMode.Touch, pawn.NormalMaxDanger(), 1, -1, null, forced))
return false;
// 获取维护组件
Comp_SwarmMaintenance comp = t.TryGetComp<Comp_SwarmMaintenance>();
if (comp == null)
return false;
// 检查建筑是否需要维护
return comp.NeedsMaintenance;
}
public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false)
{
if (t == null || t.Destroyed)
return null;
// 创建维护工作
Job job = JobMaker.MakeJob(ARA_JobDefOf.ARA_SwarmMaintain, t);
job.count = 1;
return job;
}
private bool IsSwarmMember(Pawn pawn)
{
// 检查Pawn是否是虫群成员
return pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindMaster) ||
pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindDrone) ||
pawn.health.hediffSet.HasHediff(ARA_HediffDefOf.ARA_HiveMindWorker);
}
}
}