修反复割除

This commit is contained in:
2025-09-03 13:26:48 +08:00
parent 9a8b90be82
commit a98b4d2612
3 changed files with 128 additions and 93 deletions

Binary file not shown.

View File

@@ -13,13 +13,14 @@ namespace ArachnaeSwarm
protected override Job TryGiveJob(Pawn pawn) protected override Job TryGiveJob(Pawn pawn)
{ {
// 懒加载 WorkGiver 实例,确保 DefOf 已被初始化
if (_workGiverHarvest == null) if (_workGiverHarvest == null)
{ {
_workGiverHarvest = WorkGiverDefOf.GrowerHarvest.Worker as WorkGiver_GrowerHarvest; _workGiverHarvest = DefDatabase<WorkGiverDef>.GetNamed("GrowerHarvest").Worker as WorkGiver_GrowerHarvest;
_workGiverPlantsCut = WorkGiverDefOf.PlantsCut.Worker as WorkGiver_Scanner; _workGiverPlantsCut = DefDatabase<WorkGiverDef>.GetNamed("PlantsCut").Worker as WorkGiver_Scanner;
_workGiverArachnaeSow = new WorkGiver_ArachnaeSow(); _workGiverArachnaeSow = new WorkGiver_ArachnaeSow();
if (_workGiverHarvest == null || _workGiverPlantsCut == null) if (_workGiverHarvest == null || _workGiverPlantsCut == null || _workGiverArachnaeSow == null)
{ {
Log.ErrorOnce("JobGiver_Grower: Failed to get a required WorkGiver. DefOfs might not be initialized.", 123458); Log.ErrorOnce("JobGiver_Grower: Failed to get a required WorkGiver. DefOfs might not be initialized.", 123458);
return null; return null;
@@ -30,21 +31,29 @@ namespace ArachnaeSwarm
IntVec3 bestHarvestCell = FindClosestHarvestableCell(pawn); IntVec3 bestHarvestCell = FindClosestHarvestableCell(pawn);
if (bestHarvestCell.IsValid) if (bestHarvestCell.IsValid)
{ {
return _workGiverHarvest.JobOnCell(pawn, bestHarvestCell); Job harvestJob = _workGiverHarvest.JobOnCell(pawn, bestHarvestCell);
if (harvestJob != null)
{
return harvestJob;
}
} }
// 2. 其次处理手动指定的砍伐/收获任务 // 2. 其次处理手动指定的砍伐/收获任务
Thing bestCuttable = FindClosestWorkableThing(pawn, _workGiverPlantsCut); Thing bestCuttable = FindClosestWorkableThing(pawn, _workGiverPlantsCut);
if (bestCuttable != null) if (bestCuttable != null)
{ {
return _workGiverPlantsCut.JobOnThing(pawn, bestCuttable); Job cutJob = _workGiverPlantsCut.JobOnThing(pawn, bestCuttable);
if (cutJob != null)
{
return cutJob;
}
} }
// 3. 最后播种(自动,并清理障碍 // 3. 最后处理播种或清理障碍(由 WorkGiver_ArachnaeSow 处理
(IntVec3 bestSowCell, ThingDef plantToSow) = FindClosestSowableCellAndPlant(pawn, _workGiverArachnaeSow); Job sowOrClearJob = FindClosestSowableOrClearJob(pawn, _workGiverArachnaeSow);
if (bestSowCell.IsValid && plantToSow != null) if (sowOrClearJob != null)
{ {
return _workGiverArachnaeSow.JobOnCell(pawn, bestSowCell); return sowOrClearJob;
} }
return null; return null;
@@ -86,11 +95,16 @@ namespace ArachnaeSwarm
return bestCell; return bestCell;
} }
private (IntVec3, ThingDef) FindClosestSowableCellAndPlant(Pawn pawn, WorkGiver_ArachnaeSow scanner) // 修改后的方法:寻找最近的播种或清理 Job
private Job FindClosestSowableOrClearJob(Pawn pawn, WorkGiver_ArachnaeSow scanner)
{ {
IntVec3 bestCell = IntVec3.Invalid; IntVec3 bestClearCell = IntVec3.Invalid;
ThingDef bestPlantToSow = null; Job bestClearJob = null;
float bestDistSq = float.MaxValue; float bestClearDistSq = float.MaxValue;
IntVec3 bestSowCell = IntVec3.Invalid;
Job bestSowJob = null;
float bestSowDistSq = float.MaxValue;
foreach (Zone zone in pawn.Map.zoneManager.AllZones) foreach (Zone zone in pawn.Map.zoneManager.AllZones)
{ {
@@ -102,31 +116,43 @@ namespace ArachnaeSwarm
foreach (IntVec3 cell in growingZone.Cells) foreach (IntVec3 cell in growingZone.Cells)
{ {
float distSq = pawn.Position.DistanceToSquared(cell); float distSq = pawn.Position.DistanceToSquared(cell);
if (distSq < bestDistSq && pawn.CanReach(cell, PathEndMode.ClosestTouch, Danger.Deadly)) if (pawn.CanReach(cell, PathEndMode.ClosestTouch, Danger.Deadly))
{ {
if (scanner.HasJobOnCell(pawn, cell)) Job potentialJob = scanner.JobOnCell(pawn, cell);
if (potentialJob != null)
{ {
bestDistSq = distSq; if (potentialJob.def == JobDefOf.CutPlant || potentialJob.def == JobDefOf.HaulToContainer || potentialJob.def == JobDefOf.HaulToCell)
bestCell = cell; {
bestPlantToSow = wantedPlant; if (distSq < bestClearDistSq)
{
bestClearDistSq = distSq;
bestClearJob = potentialJob;
}
}
else if (potentialJob.def == JobDefOf.Sow)
{
if (distSq < bestSowDistSq)
{
bestSowDistSq = distSq;
bestSowJob = potentialJob;
} }
} }
} }
} }
} }
return (bestCell, bestPlantToSow); }
}
// 优先返回清理 Job
if (bestClearJob != null)
{
return bestClearJob;
}
// 其次返回播种 Job
if (bestSowJob != null)
{
return bestSowJob;
}
return null;
} }
} }
} }
[DefOf]
public static class WorkGiverDefOf
{
public static WorkGiverDef GrowerHarvest;
public static WorkGiverDef PlantsCut;
static WorkGiverDefOf()
{
DefOfHelper.EnsureInitializedInCtor(typeof(WorkGiverDefOf));
}
}

View File

@@ -53,7 +53,7 @@ namespace ArachnaeSwarm
return null; return null;
} }
// 直接计算 wantedPlantDef,不再依赖静态字段 // 直接计算 wantedPlantDef
ThingDef wantedPlantDefLocal = WorkGiver_Grower.CalculateWantedPlantDef(c, map); ThingDef wantedPlantDefLocal = WorkGiver_Grower.CalculateWantedPlantDef(c, map);
if (wantedPlantDefLocal == null) if (wantedPlantDefLocal == null)
{ {
@@ -105,7 +105,10 @@ namespace ArachnaeSwarm
return null; return null;
} }
Plant plant = c.GetPlant(map); Plant plant = c.GetPlant(map);
if (plant != null && plant.def.plant.blockAdjacentSow) if (plant != null) // 只要地块上有植物
{
// 如果地块上的植物不是我们想要种植的植物,就割除
if (plant.def != wantedPlantDefLocal)
{ {
if (!pawn.CanReserve(plant, 1, -1, null, forced) || plant.IsForbidden(pawn)) if (!pawn.CanReserve(plant, 1, -1, null, forced) || plant.IsForbidden(pawn))
{ {
@@ -119,22 +122,30 @@ namespace ArachnaeSwarm
{ {
return null; return null;
} }
if (!PlantUtility.PawnWillingToCutPlant_Job(plant, pawn)) return JobMaker.MakeJob(JobDefOf.CutPlant, plant);
}
// 如果地块上的植物是我们想要种植的植物,并且它阻碍了相邻播种,则不割除
// 因为它已经是我们想要种植的植物了
if (plant.def.plant.blockAdjacentSow)
{ {
return null; return null;
} }
return JobMaker.MakeJob(JobDefOf.CutPlant, plant);
} }
Thing thing2 = PlantUtility.AdjacentSowBlocker(wantedPlantDefLocal, c, map); Thing thing2 = PlantUtility.AdjacentSowBlocker(wantedPlantDefLocal, c, map);
if (thing2 != null) if (thing2 != null)
{ {
if (thing2 is Plant plant2 && pawn.CanReserveAndReach(plant2, PathEndMode.Touch, Danger.Deadly, 1, -1, null, forced) && !plant2.IsForbidden(pawn)) if (thing2 is Plant plant2)
{
// 如果阻碍播种的是植物,并且不是我们想要种植的植物,就割除
if (plant2.def != wantedPlantDefLocal)
{
if (pawn.CanReserveAndReach(plant2, PathEndMode.Touch, Danger.Deadly, 1, -1, null, forced) && !plant2.IsForbidden(pawn))
{ {
IPlantToGrowSettable plantToGrowSettable = plant2.Position.GetPlantToGrowSettable(plant2.Map); IPlantToGrowSettable plantToGrowSettable = plant2.Position.GetPlantToGrowSettable(plant2.Map);
if (plantToGrowSettable == null || plantToGrowSettable.GetPlantDefToGrow() != plant2.def) if (plantToGrowSettable == null || plantToGrowSettable.GetPlantDefToGrow() != plant2.def)
{ {
Zone_Growing zone_Growing2 = c.GetZone(map) as Zone_Growing; Zone_Growing zone_Growing2 = c.GetZone(map) as Zone_Growing;
Zone_Growing zone_Growing3 = plant2.Position.GetZone(map) as Zone_Growing; Zone_Growing zone_Growing3 = c.GetZone(map) as Zone_Growing;
if ((zone_Growing2 != null && !zone_Growing2.allowCut) || (zone_Growing3 != null && !zone_Growing3.allowCut && plant2.def == zone_Growing3.GetPlantDefToGrow())) if ((zone_Growing2 != null && !zone_Growing2.allowCut) || (zone_Growing3 != null && !zone_Growing3.allowCut && plant2.def == zone_Growing3.GetPlantDefToGrow()))
{ {
return null; return null;
@@ -148,13 +159,11 @@ namespace ArachnaeSwarm
{ {
return null; return null;
} }
if (!PlantUtility.PawnWillingToCutPlant_Job(plant2, pawn))
{
return null;
}
return JobMaker.MakeJob(JobDefOf.CutPlant, plant2); return JobMaker.MakeJob(JobDefOf.CutPlant, plant2);
} }
if (thing2.def.EverHaulable) }
}
else if (thing2.def.EverHaulable)
{ {
return HaulAIUtility.HaulAsideJobFor(pawn, thing2); return HaulAIUtility.HaulAsideJobFor(pawn, thing2);
} }
@@ -177,6 +186,9 @@ namespace ArachnaeSwarm
return null; return null;
} }
if (thing3.def.category == ThingCategory.Plant) if (thing3.def.category == ThingCategory.Plant)
{
// 如果阻碍播种的是植物,并且不是我们想要种植的植物,就割除
if (thing3.def != wantedPlantDefLocal)
{ {
if (thing3.IsForbidden(pawn)) if (thing3.IsForbidden(pawn))
{ {
@@ -186,11 +198,7 @@ namespace ArachnaeSwarm
{ {
return null; return null;
} }
if (!forced && plant.TryGetComp<CompPlantPreventCutting>(out var comp3) && comp3.PreventCutting) if (!forced && thing3.TryGetComp<CompPlantPreventCutting>(out var comp3) && comp3.PreventCutting)
{
return null;
}
if (!PlantUtility.PawnWillingToCutPlant_Job(thing3, pawn))
{ {
return null; return null;
} }
@@ -200,7 +208,8 @@ namespace ArachnaeSwarm
} }
return JobMaker.MakeJob(JobDefOf.CutPlant, thing3); return JobMaker.MakeJob(JobDefOf.CutPlant, thing3);
} }
if (thing3.def.EverHaulable) }
else if (thing3.def.EverHaulable)
{ {
return HaulAIUtility.HaulAsideJobFor(pawn, thing3); return HaulAIUtility.HaulAsideJobFor(pawn, thing3);
} }