diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll index 83a59e0..e6f8894 100644 Binary files a/1.6/1.6/Assemblies/ArachnaeSwarm.dll and b/1.6/1.6/Assemblies/ArachnaeSwarm.dll differ diff --git a/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_HiveMind.xml b/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_HiveMind.xml index 81ca1f7..f6af277 100644 --- a/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_HiveMind.xml +++ b/1.6/1.6/Defs/HediffDefs/ARA_Hediffs_HiveMind.xml @@ -2,12 +2,12 @@ ARA_HiveMindMaster - + 虫群意识的中心节点, 作为主脑统御整个阿拉克涅虫群. ArachnaeSwarm.Hediff_HiveMindMaster (0.8, 0.3, 0.8) false - true + false 100
  • @@ -31,12 +31,12 @@ ARA_HiveMindDrone - - 阿拉克涅工蜂通过心灵与阿拉克涅女皇种相链接。如果女皇死亡,工蜂也将停止生命活动。 + + 阿拉克涅督虫通过心灵与阿拉克涅女皇种相链接。如果女皇死亡,督虫也将停止生命活动。 ArachnaeSwarm.Hediff_HiveMindDrone (0.6, 0.4, 0.8) false - true + false
  • 6400 @@ -65,4 +65,18 @@
  • + + + ARA_HiveMindWorker + + 阿拉克涅辅虫通过心灵与阿拉克涅督虫种相链接。如果督虫死亡,辅虫也将停止生命活动。 + HediffWithComps + (0.6, 0.4, 0.8) + false + false + + + + +
    \ No newline at end of file diff --git a/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml b/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml index 07f9872..1bf30e4 100644 --- a/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml +++ b/1.6/1.6/Defs/PawnKindDef/ARA_PawnKinds.xml @@ -40,12 +40,12 @@ - -
  • - ARA_Creep - 2.0 -
  • -
    + +
  • + ARA_Creep + 2.0 +
  • +
    ARA_ArachnaeQueen @@ -101,12 +101,12 @@ - -
  • - ARA_Creep - 2.0 -
  • -
    + +
  • + ARA_Creep + 2.0 +
  • +
    ArachnaeNode_Race_Myrmecocystus @@ -182,6 +182,9 @@ 8.0 + +
  • ARA_HiveMindWorker
  • +
    ArachnaeBase_Race_Slavey @@ -271,4 +274,27 @@ + + + ArachnaeBase_Race_Maid + + ArachnaeBase_Race_Maid + +
  • + + Things/Pawn/Animal/Spelopede/Spelopede + 1 + (156,148,125) + + (0.4, 0.5, 0.37) + (0,0,-0.15) + + + + Things/Pawn/Animal/Spelopede/Dessicated_Spelopede + 1 + +
  • +
    +
    \ No newline at end of file diff --git a/1.6/1.6/Defs/ThingDef_Races/ARA_RaceBaseSwarm.xml b/1.6/1.6/Defs/ThingDef_Races/ARA_RaceBaseSwarm.xml index 130db61..dd9ee0e 100644 --- a/1.6/1.6/Defs/ThingDef_Races/ARA_RaceBaseSwarm.xml +++ b/1.6/1.6/Defs/ThingDef_Races/ARA_RaceBaseSwarm.xml @@ -183,4 +183,27 @@ + + + ArachnaeBase_Race_Maid + + 阿拉克涅辅虫之一,智力低下,可以执行清洁工作,注定在度过短暂的时光后死亡。 + + +
  • ARA_Cleaning
  • +
    +
    + +
  • + +
  • + ARA_Cleaning + true + true +
  • + + true + +
    +
    \ No newline at end of file diff --git a/1.6/1.6/Defs/ThinkTreeDefs/ARA_ThinkTrees.xml b/1.6/1.6/Defs/ThinkTreeDefs/ARA_ThinkTrees.xml index 3218afc..5b65f4d 100644 --- a/1.6/1.6/Defs/ThinkTreeDefs/ARA_ThinkTrees.xml +++ b/1.6/1.6/Defs/ThinkTreeDefs/ARA_ThinkTrees.xml @@ -332,6 +332,13 @@
  • + + +
  • + +
  • + +
  • diff --git a/1.6/1.6/Defs/TrainableDefs/ARA_Cleaning.xml b/1.6/1.6/Defs/TrainableDefs/ARA_Cleaning.xml new file mode 100644 index 0000000..8ed9fcc --- /dev/null +++ b/1.6/1.6/Defs/TrainableDefs/ARA_Cleaning.xml @@ -0,0 +1,22 @@ + + + + + ARA_Cleaning + + 允许该生物执行清洁任务。 + + true + + + 5 + Advanced + + + 3 + + + 100 + + + \ No newline at end of file diff --git a/Source/ArachnaeSwarm/ARA_TrainingWork/JobClean/ARA_TrainableDefOf_Cleaning.cs b/Source/ArachnaeSwarm/ARA_TrainingWork/JobClean/ARA_TrainableDefOf_Cleaning.cs new file mode 100644 index 0000000..1ec09fe --- /dev/null +++ b/Source/ArachnaeSwarm/ARA_TrainingWork/JobClean/ARA_TrainableDefOf_Cleaning.cs @@ -0,0 +1,16 @@ +using Verse; +using RimWorld; + +namespace ArachnaeSwarm +{ + [DefOf] + public static class ARA_TrainableDefOf_Cleaning + { + public static TrainableDef ARA_Cleaning; + + static ARA_TrainableDefOf_Cleaning() + { + DefOfHelper.EnsureInitializedInCtor(typeof(ARA_TrainableDefOf_Cleaning)); + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/ARA_TrainingWork/JobClean/JobGiver_Cleaner.cs b/Source/ArachnaeSwarm/ARA_TrainingWork/JobClean/JobGiver_Cleaner.cs new file mode 100644 index 0000000..f99aedb --- /dev/null +++ b/Source/ArachnaeSwarm/ARA_TrainingWork/JobClean/JobGiver_Cleaner.cs @@ -0,0 +1,50 @@ +using Verse; +using Verse.AI; +using RimWorld; + +namespace ArachnaeSwarm +{ + public class JobGiver_Cleaner : ThinkNode_JobGiver + { + private WorkGiver_ArachnaeClean _workGiver; + + public override void ResolveReferences() + { + base.ResolveReferences(); + // We instantiate our custom WorkGiver here. + // It doesn't need a Def because it's not a standard game WorkGiver. + _workGiver = new WorkGiver_ArachnaeClean(); + } + + protected override Job TryGiveJob(Pawn pawn) + { + if (_workGiver == null) + { + Log.ErrorOnce("JobGiver_Cleaner's WorkGiver is null. ResolveReferences was not called.", 91354); + return null; + } + + // The WorkGiver will handle both filth and snow. + // We just need to find the closest potential job. + // The logic is simplified here; the real work is in the WorkGiver. + + // Find the closest filth to clean + Thing closestFilth = _workGiver.FindClosestFilth(pawn); + if (closestFilth != null) + { + Job filthJob = _workGiver.JobOnThing(pawn, closestFilth); + if (filthJob != null) return filthJob; + } + + // If no filth, find the closest snow/sand to clear + IntVec3 closestSnowCell = _workGiver.FindClosestSnow(pawn); + if (closestSnowCell.IsValid) + { + Job snowJob = _workGiver.JobOnCell(pawn, closestSnowCell); + if (snowJob != null) return snowJob; + } + + return null; + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/ARA_TrainingWork/JobClean/ThinkNode_ConditionalAnimalShouldDoCleaningWork.cs b/Source/ArachnaeSwarm/ARA_TrainingWork/JobClean/ThinkNode_ConditionalAnimalShouldDoCleaningWork.cs new file mode 100644 index 0000000..b94475a --- /dev/null +++ b/Source/ArachnaeSwarm/ARA_TrainingWork/JobClean/ThinkNode_ConditionalAnimalShouldDoCleaningWork.cs @@ -0,0 +1,21 @@ +using Verse; +using Verse.AI; +using RimWorld; + +namespace ArachnaeSwarm +{ + public class ThinkNode_ConditionalAnimalShouldDoCleaningWork : ThinkNode_Conditional + { + protected override bool Satisfied(Pawn pawn) + { + if (pawn.training == null) + { + return false; + } + + // Check if the animal has learned and is set to perform "Cleaning" + return pawn.training.HasLearned(ARA_TrainableDefOf_Cleaning.ARA_Cleaning) && + pawn.training.GetWanted(ARA_TrainableDefOf_Cleaning.ARA_Cleaning); + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/ARA_TrainingWork/JobClean/WorkGiver_ArachnaeClean.cs b/Source/ArachnaeSwarm/ARA_TrainingWork/JobClean/WorkGiver_ArachnaeClean.cs new file mode 100644 index 0000000..ddfb1c6 --- /dev/null +++ b/Source/ArachnaeSwarm/ARA_TrainingWork/JobClean/WorkGiver_ArachnaeClean.cs @@ -0,0 +1,82 @@ +using System.Collections.Generic; +using Verse; +using Verse.AI; +using RimWorld; + +namespace ArachnaeSwarm +{ + public class WorkGiver_ArachnaeClean : WorkGiver_Scanner + { + private const int MinTicksSinceThickened = 600; + + public override PathEndMode PathEndMode => PathEndMode.Touch; + + // --- Filth Cleaning Logic --- + + public Thing FindClosestFilth(Pawn pawn) + { + return GenClosest.ClosestThing_Global( + pawn.Position, + pawn.Map.listerFilthInHomeArea.FilthInHomeArea, + maxDistance: 9999f, + validator: t => HasJobOnThing(pawn, t) + ); + } + + public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) + { + if (!(t is Filth filth)) return false; + if (!filth.Map.areaManager.Home[filth.Position]) return false; + if (filth.Fogged() || !pawn.CanReserve(t, 1, -1, null, forced)) return false; + if (filth.TicksSinceThickened < MinTicksSinceThickened) return false; + return true; + } + + public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) + { + Job job = JobMaker.MakeJob(JobDefOf.Clean); + job.AddQueuedTarget(TargetIndex.A, t); + + // Simplified multi-clean logic from original WorkGiver_CleanFilth + int num = 15; + for (int i = 0; i < 100; i++) + { + IntVec3 c = t.Position + GenRadial.RadialPattern[i]; + if (c.InBounds(pawn.Map)) + { + List thingList = c.GetThingList(pawn.Map); + foreach(var thing in thingList) + { + if (thing != t && HasJobOnThing(pawn, thing, forced)) + { + job.AddQueuedTarget(TargetIndex.A, thing); + } + } + } + if (job.GetTargetQueue(TargetIndex.A).Count >= num) break; + } + return job; + } + + // --- Snow Clearing Logic --- + + public IntVec3 FindClosestSnow(Pawn pawn) + { + return CellFinder.RandomClosewalkCellNear(pawn.Position, pawn.Map, 100, + c => HasJobOnCell(pawn, c) && pawn.CanReach(c, PathEndMode.Touch, Danger.Deadly)); + } + + public override bool HasJobOnCell(Pawn pawn, IntVec3 c, bool forced = false) + { + if (pawn.Map.snowGrid.GetDepth(c) < 0.2f) return false; + if (!pawn.Map.areaManager.SnowOrSandClear[c]) return false; // Must be in the clear zone + if (!pawn.CanReserve(c, 1, -1, null, forced)) return false; + return true; + } + + public override Job JobOnCell(Pawn pawn, IntVec3 c, bool forced = false) + { + return JobMaker.MakeJob(JobDefOf.ClearSnow, c); + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj index 32f2be4..4532ea1 100644 --- a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj +++ b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj @@ -118,6 +118,12 @@ + + + + + +