Files
ArachnaeSwarm/Source/ArachnaeSwarm/Jobs/JobDriver_FollowProducer/JobGiver_AIFollowProducer.cs
Tourswen 99c1d87210 11
2026-01-21 00:27:36 +08:00

126 lines
4.7 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 Verse;
using Verse.AI;
using UnityEngine;
namespace ArachnaeSwarm
{
public class JobGiver_AIFollowProducer : JobGiver_AIFollowPawn
{
public const float DefaultFollowRadius = 3f;
public const float ExtendedFollowRadius = 10f;
protected override int FollowJobExpireInterval => 200;
protected override Pawn GetFollowee(Pawn pawn)
{
// 获取生产者Comp
CompProducedByMechCarrier producerComp = pawn.TryGetComp<CompProducedByMechCarrier>();
if (producerComp == null || !producerComp.HasValidProducer)
return null;
Thing producer = producerComp.Producer;
// 如果生产者是Pawn返回它但需要检查征召状态
if (producer is Pawn pawnProducer)
{
// 只在生产者被征召时才返回
return pawnProducer.Drafted ? pawnProducer : null;
}
// 对于非Pawn生产者返回null我们将使用自定义逻辑
return null;
}
protected override float GetRadius(Pawn pawn)
{
// 如果有特殊需求,可以调整跟随半径
CompProducedByMechCarrier producerComp = pawn.TryGetComp<CompProducedByMechCarrier>();
if (producerComp == null || !producerComp.HasValidProducer)
return DefaultFollowRadius;
// 如果生产者是建筑,可能需要更大的跟随半径
if (producerComp.Producer is Building)
return ExtendedFollowRadius;
return DefaultFollowRadius;
}
// 重写以支持非Pawn生产者
protected override Job TryGiveJob(Pawn pawn)
{
CompProducedByMechCarrier producerComp = pawn.TryGetComp<CompProducedByMechCarrier>();
if (producerComp == null || !producerComp.HasValidProducer)
return null;
Thing producer = producerComp.Producer;
// 如果生产者是Pawn检查征召状态
if (producer is Pawn pawnProducer)
{
// 只在生产者被征召时才跟随
if (!pawnProducer.Drafted)
return null;
// 使用基类逻辑
return base.TryGiveJob(pawn);
}
// 对于非Pawn生产者创建自定义跟随逻辑
return CreateFollowNonPawnJob(pawn, producer);
}
private Job CreateFollowNonPawnJob(Pawn pawn, Thing producer)
{
if (producer == null || producer.Destroyed)
return null;
// 检查是否已经在跟随半径内
float radius = GetRadius(pawn);
if (pawn.Position.DistanceTo(producer.Position) <= radius)
{
// 已经在范围内,不需要移动
return null;
}
// 创建移动到生产者附近的工作
IntVec3 targetCell = GetFollowTargetCell(pawn, producer, radius);
if (!targetCell.IsValid || !pawn.CanReach(targetCell, PathEndMode.OnCell, Danger.Deadly))
return null;
Job job = JobMaker.MakeJob(JobDefOf.Goto, targetCell);
job.expiryInterval = FollowJobExpireInterval;
job.checkOverrideOnExpire = true;
return job;
}
private IntVec3 GetFollowTargetCell(Pawn pawn, Thing producer, float radius)
{
// 获取生产者位置附近的随机单元格
IntVec3 producerPos = producer.Position;
// 在半径范围内寻找可到达的单元格
for (int i = 0; i < 20; i++)
{
// 修复:正确生成偏移量
Vector2 randomOffset = Random.insideUnitCircle * (radius * 0.5f);
IntVec3 candidate = producerPos + new IntVec3(Mathf.RoundToInt(randomOffset.x), 0, Mathf.RoundToInt(randomOffset.y));
if (candidate.InBounds(pawn.Map) &&
candidate.Walkable(pawn.Map) &&
pawn.CanReach(candidate, PathEndMode.OnCell, Danger.Deadly))
{
return candidate;
}
}
// 如果找不到合适的单元格,返回生产者的交互单元格
if (producer is Building building)
return building.InteractionCell;
return producerPos;
}
}
}