- Snapshot `AllPawnsSpawned` with `ToList()` before iteration in `WorkGiver_FeedWithHoney` - Apply the same fix in both `ArachnaeSwarm` and `KalospacerRWLib` - Add `otherPawn.CurJob != null` guard to prevent potential NRE during target checks
174 lines
6.3 KiB
C#
174 lines
6.3 KiB
C#
using RimWorld;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
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)
|
||
{
|
||
List<Pawn> allPawns = pawn.Map.mapPawns.AllPawnsSpawned.ToList();
|
||
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 && pawn.needs?.TryGetNeed<Need_Food>().CurLevelPercentage <= 0.25f;
|
||
}
|
||
|
||
// 检查是否是虫族成员
|
||
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移动以喂食
|
||
List<Pawn> allPawns = pawn.Map.mapPawns.AllPawnsSpawned.ToList();
|
||
foreach (Pawn otherPawn in allPawns)
|
||
{
|
||
if (otherPawn != pawn &&
|
||
otherPawn.CurJobDef == ARA_JobDefOf.ARA_FeedWithHoney &&
|
||
otherPawn.CurJob != null &&
|
||
otherPawn.CurJob.targetA.Thing == pawn)
|
||
{
|
||
return false; // 已经有人正在喂食这个Pawn
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
}
|
||
}
|