Files
ArachnaeSwarm/Source/ArachnaeSwarm/WorkGivers/WorkGiver_FeedWithHoney.cs
ProjectKoi-Kalo\Kalo 782a7b43b8 fix(feed-with-honey): avoid modified-collection crash in workgiver scan
- 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
2026-02-22 01:47:35 +08:00

174 lines
6.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
}
}
}