考察任务
This commit is contained in:
112
Source/WulaFallenEmpire/Job/JobDriver_InspectBuilding.cs
Normal file
112
Source/WulaFallenEmpire/Job/JobDriver_InspectBuilding.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using System.Collections.Generic;
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
using Verse.AI;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class JobDriver_InspectBuilding : JobDriver
|
||||
{
|
||||
private const TargetIndex BuildingIndex = TargetIndex.A;
|
||||
|
||||
private int ticksLeft;
|
||||
|
||||
// 定义考察效果 - 可以使用现有的效果或创建自定义效果
|
||||
private static readonly EffecterDef InspectEffect = EffecterDefOf.Research; // 使用研究效果作为临时替代
|
||||
private static readonly SoundDef InspectSound = SoundDefOf.Interact_CleanFilth; // 使用建造声音作为临时替代
|
||||
|
||||
public override bool TryMakePreToilReservations(bool errorOnFailed)
|
||||
{
|
||||
// 预订目标建筑
|
||||
return pawn.Reserve(job.targetA, job, 1, 1, null, errorOnFailed);
|
||||
}
|
||||
|
||||
protected override IEnumerable<Toil> MakeNewToils()
|
||||
{
|
||||
// 失败条件
|
||||
this.FailOnDestroyedOrNull(BuildingIndex);
|
||||
this.FailOnDespawnedOrNull(BuildingIndex);
|
||||
this.FailOn(() => !pawn.health.capacities.CapableOf(PawnCapacityDefOf.Moving));
|
||||
|
||||
// 第一步:前往目标建筑
|
||||
yield return Toils_Goto.GotoCell(BuildingIndex, PathEndMode.Touch)
|
||||
.FailOnSomeonePhysicallyInteracting(BuildingIndex);
|
||||
|
||||
// 第二步:进行考察(带动画效果)
|
||||
Toil inspectToil = CreateInspectionToil();
|
||||
yield return inspectToil;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建带动画效果的考察工作
|
||||
/// </summary>
|
||||
private Toil CreateInspectionToil()
|
||||
{
|
||||
Toil inspectToil = new Toil();
|
||||
|
||||
inspectToil.initAction = () =>
|
||||
{
|
||||
ticksLeft = job.expiryInterval;
|
||||
|
||||
// 记录日志
|
||||
if (Prefs.DevMode)
|
||||
{
|
||||
Log.Message($"[JobDriver_InspectBuilding] {pawn.Name} started inspecting {TargetThingA.Label} for {ticksLeft} ticks");
|
||||
}
|
||||
};
|
||||
|
||||
inspectToil.tickAction = () =>
|
||||
{
|
||||
ticksLeft--;
|
||||
|
||||
// 每 tick 检查是否完成
|
||||
if (ticksLeft <= 0)
|
||||
{
|
||||
ReadyForNextToil();
|
||||
}
|
||||
};
|
||||
|
||||
inspectToil.defaultCompleteMode = ToilCompleteMode.Delay;
|
||||
inspectToil.defaultDuration = job.expiryInterval;
|
||||
|
||||
// 添加动画效果
|
||||
inspectToil.WithEffect(InspectEffect, BuildingIndex);
|
||||
|
||||
// 添加音效
|
||||
inspectToil.PlaySustainerOrSound(() => InspectSound);
|
||||
|
||||
// 添加进度条(可选)
|
||||
inspectToil.WithProgressBar(BuildingIndex,
|
||||
() => 1f - ((float)ticksLeft / job.expiryInterval),
|
||||
interpolateBetweenActorAndTarget: true);
|
||||
|
||||
inspectToil.AddFinishAction(() =>
|
||||
{
|
||||
// 考察完成后的处理
|
||||
OnInspectionComplete();
|
||||
});
|
||||
|
||||
return inspectToil;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 考察完成时的处理
|
||||
/// </summary>
|
||||
private void OnInspectionComplete()
|
||||
{
|
||||
// 可以在这里添加考察完成后的效果
|
||||
// 例如:增加技能经验、触发事件等
|
||||
|
||||
if (Prefs.DevMode)
|
||||
{
|
||||
Log.Message($"[JobDriver_InspectBuilding] {pawn.Name} completed inspection of {TargetThingA.Label}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void ExposeData()
|
||||
{
|
||||
base.ExposeData();
|
||||
Scribe_Values.Look(ref ticksLeft, "ticksLeft", 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
307
Source/WulaFallenEmpire/Job/JobGiver_InspectBuilding.cs
Normal file
307
Source/WulaFallenEmpire/Job/JobGiver_InspectBuilding.cs
Normal file
@@ -0,0 +1,307 @@
|
||||
using RimWorld;
|
||||
using RimWorld.Planet;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Verse;
|
||||
using Verse.AI;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class JobGiver_InspectBuilding : ThinkNode_JobGiver
|
||||
{
|
||||
// 检查间隔(ticks)
|
||||
private const int CheckInterval = 120; // 2秒检查一次
|
||||
|
||||
// 最大考察距离
|
||||
private const float MaxDistance = 20f;
|
||||
|
||||
// 默认最小间隔(ticks)- 5分钟
|
||||
private const int DefaultMinIntervalTicks = 300 * 60; // 5分钟 * 60秒/分钟 * 60ticks/秒
|
||||
|
||||
// 存储每个 Pawn 的最后考察时间
|
||||
private static Dictionary<Pawn, int> lastInspectionTicks = new Dictionary<Pawn, int>();
|
||||
|
||||
protected override Job TryGiveJob(Pawn pawn)
|
||||
{
|
||||
// 检查 Pawn 是否有效
|
||||
if (pawn == null || pawn.Destroyed || !pawn.Spawned || pawn.Map == null)
|
||||
return null;
|
||||
|
||||
// 检查 Pawn 是否能够工作
|
||||
if (pawn.Downed || pawn.InMentalState || !pawn.health.capacities.CanBeAwake)
|
||||
return null;
|
||||
|
||||
// 检查 Pawn 是否能够移动
|
||||
if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Moving))
|
||||
return null;
|
||||
|
||||
// 检查背景故事是否为军团背景
|
||||
if (!HasLegionBackstory(pawn))
|
||||
return null;
|
||||
|
||||
// 检查是否已经有工作
|
||||
if (pawn.CurJob != null && pawn.CurJob.def == JobDefOf_WULA.WULA_InspectBuilding)
|
||||
return null;
|
||||
|
||||
// 检查冷却时间
|
||||
if (!CanInspectNow(pawn))
|
||||
return null;
|
||||
|
||||
// 寻找合适的考察目标
|
||||
Thing inspectionTarget = FindRandomInspectionTarget(pawn);
|
||||
if (inspectionTarget == null)
|
||||
return null;
|
||||
|
||||
// 创建考察工作
|
||||
Job job = JobMaker.MakeJob(JobDefOf_WULA.WULA_InspectBuilding, inspectionTarget);
|
||||
job.expiryInterval = Rand.Range(300, 600); // 5-10秒的随机时间
|
||||
job.checkOverrideOnExpire = true;
|
||||
|
||||
// 记录开始考察时间
|
||||
RecordInspectionStart(pawn);
|
||||
|
||||
// 记录调试信息
|
||||
if (Prefs.DevMode)
|
||||
{
|
||||
Log.Message($"[JobGiver_InspectBuilding] Assigned inspection job to {pawn.Name} at {inspectionTarget.Label}");
|
||||
}
|
||||
|
||||
return job;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查 Pawn 是否具有军团背景故事
|
||||
/// </summary>
|
||||
private bool HasLegionBackstory(Pawn pawn)
|
||||
{
|
||||
if (pawn.story == null)
|
||||
return false;
|
||||
|
||||
// 检查成年背景故事是否为军团背景
|
||||
if (pawn.story.Adulthood != null && pawn.story.Adulthood.identifier == "WULA_Adult_Backstory_Legion")
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查 Pawn 是否可以开始新的考察(冷却时间检查)
|
||||
/// </summary>
|
||||
private bool CanInspectNow(Pawn pawn)
|
||||
{
|
||||
// 获取设置的最小间隔时间
|
||||
int minIntervalTicks = GetMinInspectionIntervalTicks();
|
||||
|
||||
// 如果 Pawn 没有记录,说明可以立即开始
|
||||
if (!lastInspectionTicks.ContainsKey(pawn))
|
||||
return true;
|
||||
|
||||
int lastTick = lastInspectionTicks[pawn];
|
||||
int currentTick = Find.TickManager.TicksGame;
|
||||
int elapsedTicks = currentTick - lastTick;
|
||||
|
||||
// 检查是否已经过了最小间隔时间
|
||||
bool canInspect = elapsedTicks >= minIntervalTicks;
|
||||
|
||||
if (Prefs.DevMode && !canInspect)
|
||||
{
|
||||
int remainingTicks = minIntervalTicks - elapsedTicks;
|
||||
float remainingSeconds = remainingTicks / 60f;
|
||||
Log.Message($"[JobGiver_InspectBuilding] {pawn.Name} must wait {remainingSeconds:F1} seconds before next inspection");
|
||||
}
|
||||
|
||||
return canInspect;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 记录 Pawn 开始考察的时间
|
||||
/// </summary>
|
||||
private void RecordInspectionStart(Pawn pawn)
|
||||
{
|
||||
lastInspectionTicks[pawn] = Find.TickManager.TicksGame;
|
||||
|
||||
if (Prefs.DevMode)
|
||||
{
|
||||
Log.Message($"[JobGiver_InspectBuilding] Recorded inspection start for {pawn.Name} at tick {lastInspectionTicks[pawn]}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取最小考察间隔时间(ticks)
|
||||
/// </summary>
|
||||
private int GetMinInspectionIntervalTicks()
|
||||
{
|
||||
// 这里可以从 Mod 设置中获取值
|
||||
// 暂时返回默认值,您可以根据需要修改
|
||||
return DefaultMinIntervalTicks;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 随机寻找合适的考察目标
|
||||
/// </summary>
|
||||
private Thing FindRandomInspectionTarget(Pawn pawn)
|
||||
{
|
||||
// 获取地图上所有符合条件的建筑
|
||||
List<Thing> validBuildings = new List<Thing>();
|
||||
|
||||
// 遍历地图上的所有建筑
|
||||
foreach (Thing thing in pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.BuildingArtificial))
|
||||
{
|
||||
if (IsValidInspectionTarget(thing, pawn))
|
||||
{
|
||||
validBuildings.Add(thing);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有找到合适的建筑,返回null
|
||||
if (validBuildings.Count == 0)
|
||||
{
|
||||
if (Prefs.DevMode)
|
||||
{
|
||||
Log.Message($"[JobGiver_InspectBuilding] No valid inspection targets found for {pawn.Name}");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 随机选择一个建筑
|
||||
Thing selectedBuilding = validBuildings.RandomElement();
|
||||
|
||||
if (Prefs.DevMode)
|
||||
{
|
||||
Log.Message($"[JobGiver_InspectBuilding] Randomly selected {selectedBuilding.Label} from {validBuildings.Count} valid targets");
|
||||
}
|
||||
|
||||
return selectedBuilding;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否有效的考察目标
|
||||
/// </summary>
|
||||
private bool IsValidInspectionTarget(Thing thing, Pawn pawn)
|
||||
{
|
||||
// 基本检查
|
||||
if (thing == null || thing.Destroyed)
|
||||
return false;
|
||||
|
||||
// 检查是否玩家拥有
|
||||
if (thing.Faction != Faction.OfPlayer)
|
||||
return false;
|
||||
|
||||
// 检查是否可到达
|
||||
if (!pawn.CanReach(thing, PathEndMode.Touch, Danger.None))
|
||||
return false;
|
||||
|
||||
// 排除一些不适合的建筑类型
|
||||
if (thing.def.IsFrame || thing.def.IsBlueprint)
|
||||
return false;
|
||||
|
||||
// 确保建筑是完整的
|
||||
if (thing is Building building && (building.IsBurning() || building.IsBrokenDown()))
|
||||
return false;
|
||||
|
||||
// 确保不是禁止进入的区域
|
||||
if (thing.IsForbidden(pawn))
|
||||
return false;
|
||||
|
||||
// 确保没有其他 Pawn 正在考察这个建筑
|
||||
if (IsBeingInspectedByOther(thing, pawn))
|
||||
return false;
|
||||
|
||||
// 排除墙壁建筑
|
||||
if (IsWall(thing))
|
||||
return false;
|
||||
|
||||
// 距离检查(可选,但为了性能考虑可以保留)
|
||||
if (pawn.Position.DistanceTo(thing.Position) > MaxDistance)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否为墙壁
|
||||
/// </summary>
|
||||
private bool IsWall(Thing thing)
|
||||
{
|
||||
// 检查建筑的 def 中是否有 isWall 标签
|
||||
if (thing.def?.building != null && thing.def.building.isWall)
|
||||
{
|
||||
if (Prefs.DevMode)
|
||||
{
|
||||
Log.Message($"[JobGiver_InspectBuilding] Excluding wall: {thing.Label}");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 额外的检查:通过 defName 或标签判断
|
||||
if (thing.def?.defName == "Wall" ||
|
||||
(thing.def?.thingCategories?.Any(c => c.defName == "Walls") ?? false))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否有其他 Pawn 正在考察这个建筑
|
||||
/// </summary>
|
||||
private bool IsBeingInspectedByOther(Thing thing, Pawn currentPawn)
|
||||
{
|
||||
foreach (Pawn otherPawn in thing.Map.mapPawns.AllPawnsSpawned)
|
||||
{
|
||||
if (otherPawn != currentPawn &&
|
||||
otherPawn.CurJob != null &&
|
||||
otherPawn.CurJob.def == JobDefOf_WULA.WULA_InspectBuilding &&
|
||||
otherPawn.CurJob.targetA.Thing == thing)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理不再存在的 Pawn 的记录
|
||||
/// </summary>
|
||||
public static void CleanupInspectionRecords()
|
||||
{
|
||||
List<Pawn> toRemove = new List<Pawn>();
|
||||
|
||||
foreach (var pair in lastInspectionTicks)
|
||||
{
|
||||
if (pair.Key.Destroyed || !pair.Key.Spawned)
|
||||
{
|
||||
toRemove.Add(pair.Key);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Pawn pawn in toRemove)
|
||||
{
|
||||
lastInspectionTicks.Remove(pawn);
|
||||
}
|
||||
|
||||
if (Prefs.DevMode && toRemove.Count > 0)
|
||||
{
|
||||
Log.Message($"[JobGiver_InspectBuilding] Cleaned up {toRemove.Count} inspection records");
|
||||
}
|
||||
}
|
||||
|
||||
public class InspectionCleanupComponent : WorldComponent
|
||||
{
|
||||
private int lastCleanupTick = 0;
|
||||
private const int CleanupIntervalTicks = 6000; // 每100秒清理一次
|
||||
public InspectionCleanupComponent(World world) : base(world) { }
|
||||
public override void WorldComponentTick()
|
||||
{
|
||||
base.WorldComponentTick();
|
||||
int currentTick = Find.TickManager.TicksGame;
|
||||
if (currentTick - lastCleanupTick > CleanupIntervalTicks)
|
||||
{
|
||||
JobGiver_InspectBuilding.CleanupInspectionRecords();
|
||||
lastCleanupTick = currentTick;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
221
Source/WulaFallenEmpire/QuestNodes/QuestNode_AddInspectionJob.cs
Normal file
221
Source/WulaFallenEmpire/QuestNodes/QuestNode_AddInspectionJob.cs
Normal file
@@ -0,0 +1,221 @@
|
||||
using RimWorld;
|
||||
using RimWorld.QuestGen;
|
||||
using Verse;
|
||||
using Verse.AI;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class QuestNode_AddInspectionJob : QuestNode
|
||||
{
|
||||
public SlateRef<Pawn> pawn; // 直接接收 Pawn 对象
|
||||
|
||||
public SlateRef<JobDef> inspectionJobDef; // 考察工作定义
|
||||
public SlateRef<float> inspectionDuration; // 考察停留时间(秒)
|
||||
public SlateRef<bool> requirePlayerOwned; // 是否要求玩家拥有
|
||||
public SlateRef<bool> requireAccessible; // 是否要求可到达
|
||||
|
||||
protected override bool TestRunInt(Slate slate)
|
||||
{
|
||||
if (inspectionJobDef.GetValue(slate) == null)
|
||||
{
|
||||
Log.Error("[QuestNode_AddInspectionJob] inspectionJobDef is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void RunInt()
|
||||
{
|
||||
Slate slate = QuestGen.slate;
|
||||
|
||||
// 直接获取 Pawn 对象
|
||||
Pawn pawnValue = pawn.GetValue(slate);
|
||||
if (pawnValue == null)
|
||||
{
|
||||
Log.Error("[QuestNode_AddInspectionJob] pawn is null");
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查 Pawn 是否有效且已生成
|
||||
if (!IsPawnValidAndSpawned(pawnValue))
|
||||
{
|
||||
// 如果 Pawn 无效或未生成,记录调试信息但不报错
|
||||
if (QuestGen.slate.Get<bool>("debugLogging", false))
|
||||
{
|
||||
Log.Message($"[QuestNode_AddInspectionJob] Pawn {pawnValue.Name} is not ready for job assignment (Destroyed: {pawnValue.Destroyed}, Spawned: {pawnValue.Spawned}, Map: {pawnValue.Map?.Index ?? -1})");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取工作定义
|
||||
JobDef jobDef = inspectionJobDef.GetValue(slate) ?? JobDefOf.Wait;
|
||||
|
||||
// 创建并分配工作
|
||||
Job job = CreateInspectionJob(pawnValue, jobDef, slate);
|
||||
if (job != null)
|
||||
{
|
||||
pawnValue.jobs.TryTakeOrderedJob(job, JobTag.Misc);
|
||||
|
||||
if (QuestGen.slate.Get<bool>("debugLogging", false))
|
||||
{
|
||||
Log.Message($"[QuestNode_AddInspectionJob] Assigned inspection job to {pawnValue.Name} at position {pawnValue.Position}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (QuestGen.slate.Get<bool>("debugLogging", false))
|
||||
{
|
||||
Log.Message($"[QuestNode_AddInspectionJob] Failed to create inspection job for {pawnValue.Name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查 Pawn 是否有效且已生成
|
||||
/// </summary>
|
||||
private bool IsPawnValidAndSpawned(Pawn pawn)
|
||||
{
|
||||
if (pawn == null || pawn.Destroyed)
|
||||
return false;
|
||||
|
||||
if (!pawn.Spawned)
|
||||
return false;
|
||||
|
||||
if (pawn.Map == null)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建考察工作
|
||||
/// </summary>
|
||||
private Job CreateInspectionJob(Pawn pawn, JobDef jobDef, Slate slate)
|
||||
{
|
||||
// 寻找合适的考察目标
|
||||
Thing inspectionTarget = FindInspectionTarget(pawn, slate);
|
||||
if (inspectionTarget == null)
|
||||
{
|
||||
if (QuestGen.slate.Get<bool>("debugLogging", false))
|
||||
{
|
||||
Log.Message($"[QuestNode_AddInspectionJob] No valid inspection target found for {pawn.Name} on map {pawn.Map}");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 创建工作
|
||||
Job job = JobMaker.MakeJob(jobDef, inspectionTarget);
|
||||
|
||||
// 设置停留时间(转换为 ticks)
|
||||
float duration = inspectionDuration.GetValue(slate);
|
||||
if (duration > 0)
|
||||
{
|
||||
job.expiryInterval = (int)(duration * 60f); // 秒转换为 ticks
|
||||
}
|
||||
else
|
||||
{
|
||||
job.expiryInterval = Rand.Range(180, 300); // 3-5 秒的随机时间
|
||||
}
|
||||
|
||||
// 设置工作标签
|
||||
job.def.joyDuration = job.expiryInterval;
|
||||
|
||||
if (QuestGen.slate.Get<bool>("debugLogging", false))
|
||||
{
|
||||
Log.Message($"[QuestNode_AddInspectionJob] Created inspection job for {pawn.Name} at {inspectionTarget.Label} (Position: {inspectionTarget.Position})");
|
||||
}
|
||||
|
||||
return job;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 寻找考察目标
|
||||
/// </summary>
|
||||
private Thing FindInspectionTarget(Pawn pawn, Slate slate)
|
||||
{
|
||||
bool requirePlayerOwnedValue = requirePlayerOwned.GetValue(slate);
|
||||
bool requireAccessibleValue = requireAccessible.GetValue(slate);
|
||||
|
||||
if (QuestGen.slate.Get<bool>("debugLogging", false))
|
||||
{
|
||||
Log.Message($"[QuestNode_AddInspectionJob] Searching for inspection target for {pawn.Name}");
|
||||
Log.Message($"[QuestNode_AddInspectionJob] Require player owned: {requirePlayerOwnedValue}, Require accessible: {requireAccessibleValue}");
|
||||
}
|
||||
|
||||
// 寻找玩家拥有的建筑
|
||||
Thing target = GenClosest.ClosestThingReachable(
|
||||
pawn.Position,
|
||||
pawn.Map,
|
||||
ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial),
|
||||
PathEndMode.Touch,
|
||||
TraverseParms.For(pawn),
|
||||
maxDistance: 50f,
|
||||
validator: (Thing t) => IsValidInspectionTarget(t, pawn, requirePlayerOwnedValue, requireAccessibleValue)
|
||||
);
|
||||
|
||||
if (QuestGen.slate.Get<bool>("debugLogging", false))
|
||||
{
|
||||
if (target != null)
|
||||
{
|
||||
Log.Message($"[QuestNode_AddInspectionJob] Found target: {target.Label} at {target.Position}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Message($"[QuestNode_AddInspectionJob] No target found within range");
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否有效的考察目标
|
||||
/// </summary>
|
||||
private bool IsValidInspectionTarget(Thing thing, Pawn pawn, bool requirePlayerOwned, bool requireAccessible)
|
||||
{
|
||||
// 基本检查
|
||||
if (thing == null || thing.Destroyed)
|
||||
return false;
|
||||
|
||||
// 检查是否玩家拥有
|
||||
if (requirePlayerOwned && thing.Faction != Faction.OfPlayer)
|
||||
{
|
||||
if (QuestGen.slate.Get<bool>("debugLogging", false) && thing.Faction != null)
|
||||
{
|
||||
Log.Message($"[QuestNode_AddInspectionJob] Target {thing.Label} faction: {thing.Faction.Name}, required: Player");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查是否可到达
|
||||
if (requireAccessible && !pawn.CanReach(thing, PathEndMode.Touch, Danger.None))
|
||||
{
|
||||
if (QuestGen.slate.Get<bool>("debugLogging", false))
|
||||
{
|
||||
Log.Message($"[QuestNode_AddInspectionJob] Target {thing.Label} at {thing.Position} is not reachable by {pawn.Name}");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 排除一些不适合的建筑类型
|
||||
if (thing.def.IsFrame || thing.def.IsBlueprint)
|
||||
return false;
|
||||
|
||||
// 确保建筑是完整的
|
||||
if (thing is Building building && (building.IsBurning() || building.IsBrokenDown()))
|
||||
return false;
|
||||
|
||||
// 确保不是禁止进入的区域
|
||||
if (thing.IsForbidden(pawn))
|
||||
return false;
|
||||
|
||||
if (QuestGen.slate.Get<bool>("debugLogging", false))
|
||||
{
|
||||
Log.Message($"[QuestNode_AddInspectionJob] Target {thing.Label} at {thing.Position} is valid");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using RimWorld;
|
||||
using RimWorld.Planet;
|
||||
using RimWorld.QuestGen;
|
||||
using Verse;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class QuestNode_GeneratePawnWithCustomization : QuestNode
|
||||
{
|
||||
[NoTranslate]
|
||||
public SlateRef<string> storeAs;
|
||||
|
||||
[NoTranslate]
|
||||
public SlateRef<string> addToList;
|
||||
|
||||
[NoTranslate]
|
||||
public SlateRef<IEnumerable<string>> addToLists;
|
||||
|
||||
public SlateRef<PawnKindDef> kindDef;
|
||||
|
||||
public SlateRef<Faction> faction;
|
||||
|
||||
public SlateRef<bool> forbidAnyTitle;
|
||||
|
||||
public SlateRef<bool> ensureNonNumericName;
|
||||
|
||||
public SlateRef<IEnumerable<TraitDef>> forcedTraits;
|
||||
|
||||
public SlateRef<IEnumerable<TraitDef>> prohibitedTraits;
|
||||
|
||||
public SlateRef<Pawn> extraPawnForExtraRelationChance;
|
||||
|
||||
public SlateRef<float> relationWithExtraPawnChanceFactor;
|
||||
|
||||
public SlateRef<bool?> allowAddictions;
|
||||
|
||||
public SlateRef<float> biocodeWeaponChance;
|
||||
|
||||
public SlateRef<float> biocodeApparelChance;
|
||||
|
||||
public SlateRef<bool> mustBeCapableOfViolence;
|
||||
|
||||
public SlateRef<bool> isChild;
|
||||
|
||||
public SlateRef<bool> allowPregnant;
|
||||
|
||||
public SlateRef<Gender?> fixedGender;
|
||||
|
||||
public SlateRef<bool> giveDependentDrugs;
|
||||
|
||||
// 只保留自定义背景故事功能
|
||||
public SlateRef<BackstoryDef> childhoodBackstory;
|
||||
public SlateRef<BackstoryDef> adulthoodBackstory;
|
||||
public SlateRef<bool> useCustomBackstories;
|
||||
|
||||
private const int MinExpertSkill = 11;
|
||||
|
||||
protected override bool TestRunInt(Slate slate)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected virtual DevelopmentalStage GetDevelopmentalStage(Slate slate)
|
||||
{
|
||||
if (!Find.Storyteller.difficulty.ChildrenAllowed || !isChild.GetValue(slate))
|
||||
{
|
||||
return DevelopmentalStage.Adult;
|
||||
}
|
||||
return DevelopmentalStage.Child;
|
||||
}
|
||||
|
||||
protected override void RunInt()
|
||||
{
|
||||
Slate slate = QuestGen.slate;
|
||||
PawnKindDef value = kindDef.GetValue(slate);
|
||||
Faction value2 = faction.GetValue(slate);
|
||||
bool flag = allowAddictions.GetValue(slate) ?? true;
|
||||
bool value3 = allowPregnant.GetValue(slate);
|
||||
IEnumerable<TraitDef> value4 = forcedTraits.GetValue(slate);
|
||||
IEnumerable<TraitDef> value5 = prohibitedTraits.GetValue(slate);
|
||||
float value6 = biocodeWeaponChance.GetValue(slate);
|
||||
bool value7 = mustBeCapableOfViolence.GetValue(slate);
|
||||
Pawn value8 = extraPawnForExtraRelationChance.GetValue(slate);
|
||||
float value9 = relationWithExtraPawnChanceFactor.GetValue(slate);
|
||||
Gender? value10 = fixedGender.GetValue(slate);
|
||||
float value11 = biocodeApparelChance.GetValue(slate);
|
||||
DevelopmentalStage developmentalStage = GetDevelopmentalStage(slate);
|
||||
|
||||
// 获取自定义背景故事设置
|
||||
BackstoryDef childhoodBackstoryValue = childhoodBackstory.GetValue(slate);
|
||||
BackstoryDef adulthoodBackstoryValue = adulthoodBackstory.GetValue(slate);
|
||||
bool useCustomBackstoriesValue = useCustomBackstories.GetValue(slate);
|
||||
|
||||
PawnGenerationRequest request = new PawnGenerationRequest(
|
||||
value, value2, PawnGenerationContext.NonPlayer, null,
|
||||
forceGenerateNewPawn: false, allowDead: false, allowDowned: false,
|
||||
canGeneratePawnRelations: true, value7, 1f, forceAddFreeWarmLayerIfNeeded: false,
|
||||
allowGay: true, value3, allowFood: true, flag, inhabitant: false,
|
||||
certainlyBeenInCryptosleep: false, forceRedressWorldPawnIfFormerColonist: false,
|
||||
worldPawnFactionDoesntMatter: false, value6, value11, value8, value9,
|
||||
null, null, value4, value5, null, null, null, value10, null, null, null,
|
||||
null, forceNoIdeo: false, forceNoBackstory: false, forbidAnyTitle: false,
|
||||
forceDead: false, null, null, null, null, null, 0f, developmentalStage);
|
||||
|
||||
request.BiocodeApparelChance = biocodeApparelChance.GetValue(slate);
|
||||
request.ForbidAnyTitle = forbidAnyTitle.GetValue(slate);
|
||||
|
||||
Pawn pawn = PawnGenerator.GeneratePawn(request);
|
||||
|
||||
// 确保名字不是数字(如果设置了)
|
||||
if (ensureNonNumericName.GetValue(slate) && (pawn.Name == null || pawn.Name.Numerical))
|
||||
{
|
||||
pawn.Name = PawnBioAndNameGenerator.GeneratePawnName(pawn);
|
||||
}
|
||||
|
||||
// 应用自定义背景故事
|
||||
if (useCustomBackstoriesValue)
|
||||
{
|
||||
ApplyCustomBackstories(pawn, childhoodBackstoryValue, adulthoodBackstoryValue);
|
||||
}
|
||||
|
||||
if (giveDependentDrugs.GetValue(slate) && ModsConfig.BiotechActive && pawn.genes != null)
|
||||
{
|
||||
foreach (Gene item in pawn.genes.GenesListForReading)
|
||||
{
|
||||
if (item.Active)
|
||||
{
|
||||
Gene_ChemicalDependency dep = item as Gene_ChemicalDependency;
|
||||
if (dep != null && DefDatabase<ThingDef>.AllDefs.Where((ThingDef x) => x.IsDrug && x.GetCompProperties<CompProperties_Drug>().chemical == dep.def.chemical).TryRandomElementByWeight((ThingDef x) => x.generateCommonality, out var result))
|
||||
{
|
||||
Thing thing = ThingMaker.MakeThing(result);
|
||||
thing.stackCount = Rand.Range(1, 3);
|
||||
pawn.inventory.innerContainer.TryAddOrTransfer(thing);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (storeAs.GetValue(slate) != null)
|
||||
{
|
||||
QuestGen.slate.Set(storeAs.GetValue(slate), pawn);
|
||||
}
|
||||
|
||||
if (addToList.GetValue(slate) != null)
|
||||
{
|
||||
QuestGenUtility.AddToOrMakeList(QuestGen.slate, addToList.GetValue(slate), pawn);
|
||||
}
|
||||
|
||||
if (addToLists.GetValue(slate) != null)
|
||||
{
|
||||
foreach (string item2 in addToLists.GetValue(slate))
|
||||
{
|
||||
QuestGenUtility.AddToOrMakeList(QuestGen.slate, item2, pawn);
|
||||
}
|
||||
}
|
||||
|
||||
QuestGen.AddToGeneratedPawns(pawn);
|
||||
if (!pawn.IsWorldPawn())
|
||||
{
|
||||
Find.WorldPawns.PassToWorld(pawn);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 应用自定义背景故事
|
||||
/// </summary>
|
||||
private void ApplyCustomBackstories(Pawn pawn, BackstoryDef childhood, BackstoryDef adulthood)
|
||||
{
|
||||
if (childhood != null)
|
||||
{
|
||||
pawn.story.Childhood = childhood;
|
||||
}
|
||||
|
||||
if (adulthood != null)
|
||||
{
|
||||
pawn.story.Adulthood = adulthood;
|
||||
}
|
||||
|
||||
// 重新计算技能,因为背景故事会影响技能
|
||||
if (pawn.skills != null)
|
||||
{
|
||||
pawn.skills.Notify_SkillDisablesChanged();
|
||||
}
|
||||
|
||||
// 重新计算工作类型
|
||||
if (pawn.workSettings != null)
|
||||
{
|
||||
pawn.workSettings.Notify_DisabledWorkTypesChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using RimWorld;
|
||||
using System.Collections.Generic;
|
||||
using Verse;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class StorytellerCompProperties_SimpleTechnologyTrigger : StorytellerCompProperties
|
||||
{
|
||||
// 必需配置
|
||||
public ResearchProjectDef technology; // 要检测的科技
|
||||
public IncidentDef incident; // 要触发的事件
|
||||
|
||||
// 时间配置
|
||||
public float fireAfterDaysPassed = 0f; // 游戏开始后多少天开始检测
|
||||
public float checkIntervalDays = 5f; // 检查间隔(天)
|
||||
|
||||
// 任务相关配置
|
||||
public QuestScriptDef questDef; // 关联的任务定义(可选)
|
||||
public bool preventDuplicateQuests = true; // 防止重复任务
|
||||
|
||||
// 派系关系校验 - 新增字段
|
||||
public FactionDef requiredFaction; // 必须存在的派系
|
||||
public bool requireNonHostileRelation = true; // 是否要求非敌对关系(默认true)
|
||||
public bool requireFactionExists = true; // 是否要求派系必须存在(默认true)
|
||||
|
||||
// 调试配置
|
||||
public bool debugLogging = false; // 启用调试日志
|
||||
|
||||
// 派系过滤(可选)
|
||||
public List<FactionDef> factionTypeWhitelist;
|
||||
public List<FactionDef> factionTypeBlacklist;
|
||||
public bool useFactionFilter = false;
|
||||
public FactionFilterDefaultBehavior defaultBehavior = FactionFilterDefaultBehavior.Allow;
|
||||
|
||||
public StorytellerCompProperties_SimpleTechnologyTrigger()
|
||||
{
|
||||
compClass = typeof(StorytellerComp_SimpleTechnologyTrigger);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,308 @@
|
||||
using RimWorld;
|
||||
using System.Collections.Generic;
|
||||
using Verse;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using RimWorld.Planet;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class StorytellerComp_SimpleTechnologyTrigger : StorytellerComp
|
||||
{
|
||||
private StorytellerCompProperties_SimpleTechnologyTrigger SimpleProps =>
|
||||
(StorytellerCompProperties_SimpleTechnologyTrigger)props;
|
||||
|
||||
// 重新实现基类的私有属性
|
||||
private static int IntervalsPassed => Find.TickManager.TicksGame / 1000;
|
||||
|
||||
public override IEnumerable<FiringIncident> MakeIntervalIncidents(IIncidentTarget target)
|
||||
{
|
||||
// 检查基础条件(天数)
|
||||
if (IntervalsPassed <= SimpleProps.fireAfterDaysPassed * 60)
|
||||
yield break;
|
||||
|
||||
// 检查是否满足周期
|
||||
if (!PassesIntervalCheck())
|
||||
yield break;
|
||||
|
||||
// 检查派系关系条件 - 新增检查
|
||||
if (!PassesRequiredFactionCheck())
|
||||
yield break;
|
||||
|
||||
// 检查派系过滤条件
|
||||
if (!PassesFactionFilter(target))
|
||||
yield break;
|
||||
|
||||
// 检查科技条件
|
||||
if (!PassesTechnologyCheck())
|
||||
yield break;
|
||||
|
||||
// 检查是否防止重复任务
|
||||
if (SimpleProps.preventDuplicateQuests && HasActiveQuest())
|
||||
yield break;
|
||||
|
||||
// 触发事件
|
||||
IncidentDef techIncident = SimpleProps.incident;
|
||||
if (techIncident.TargetAllowed(target))
|
||||
{
|
||||
if (SimpleProps.debugLogging)
|
||||
{
|
||||
Log.Message($"[SimpleTechnologyTrigger] Triggering incident {techIncident.defName} for technology {SimpleProps.technology.defName}");
|
||||
}
|
||||
|
||||
yield return new FiringIncident(techIncident, this, GenerateParms(techIncident.category, target));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查必需派系关系条件 - 新增方法
|
||||
/// </summary>
|
||||
private bool PassesRequiredFactionCheck()
|
||||
{
|
||||
// 如果没有配置必需派系,直接通过
|
||||
if (SimpleProps.requiredFaction == null)
|
||||
return true;
|
||||
|
||||
// 查找派系
|
||||
Faction requiredFactionInstance = Find.FactionManager.FirstFactionOfDef(SimpleProps.requiredFaction);
|
||||
|
||||
// 检查派系是否存在
|
||||
if (SimpleProps.requireFactionExists)
|
||||
{
|
||||
if (requiredFactionInstance == null || requiredFactionInstance.defeated)
|
||||
{
|
||||
if (SimpleProps.debugLogging)
|
||||
{
|
||||
Log.Message($"[SimpleTechnologyTrigger] Required faction {SimpleProps.requiredFaction.defName} does not exist or is defeated");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查派系关系
|
||||
if (SimpleProps.requireNonHostileRelation && requiredFactionInstance != null)
|
||||
{
|
||||
Faction playerFaction = Faction.OfPlayer;
|
||||
if (requiredFactionInstance.HostileTo(playerFaction))
|
||||
{
|
||||
if (SimpleProps.debugLogging)
|
||||
{
|
||||
Log.Message($"[SimpleTechnologyTrigger] Required faction {SimpleProps.requiredFaction.defName} is hostile to player");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (SimpleProps.debugLogging)
|
||||
{
|
||||
Log.Message($"[SimpleTechnologyTrigger] Required faction {SimpleProps.requiredFaction.defName} check passed");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否满足触发周期
|
||||
/// </summary>
|
||||
private bool PassesIntervalCheck()
|
||||
{
|
||||
// 简单的周期检查:每 X 天检查一次
|
||||
int currentInterval = IntervalsPassed;
|
||||
int checkInterval = (int)(SimpleProps.checkIntervalDays * 60);
|
||||
|
||||
// 如果检查间隔为0,则每个间隔都检查
|
||||
if (checkInterval <= 0)
|
||||
return true;
|
||||
|
||||
return currentInterval % checkInterval == 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查科技条件
|
||||
/// </summary>
|
||||
private bool PassesTechnologyCheck()
|
||||
{
|
||||
if (SimpleProps.technology == null)
|
||||
{
|
||||
Log.Error("[SimpleTechnologyTrigger] No technology specified in props");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 简单检查科技是否已研究完成
|
||||
bool hasTechnology = SimpleProps.technology.IsFinished;
|
||||
|
||||
if (SimpleProps.debugLogging)
|
||||
{
|
||||
Log.Message($"[SimpleTechnologyTrigger] Technology {SimpleProps.technology.defName} research status: {hasTechnology}");
|
||||
}
|
||||
|
||||
return hasTechnology;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查派系过滤条件
|
||||
/// </summary>
|
||||
private bool PassesFactionFilter(IIncidentTarget target)
|
||||
{
|
||||
// 如果不启用派系过滤,直接通过
|
||||
if (!SimpleProps.useFactionFilter)
|
||||
return true;
|
||||
|
||||
// 获取目标的派系
|
||||
Faction faction = GetTargetFaction(target);
|
||||
if (faction == null)
|
||||
return false;
|
||||
|
||||
// 检查黑名单
|
||||
if (SimpleProps.factionTypeBlacklist != null &&
|
||||
SimpleProps.factionTypeBlacklist.Contains(faction.def))
|
||||
{
|
||||
if (SimpleProps.debugLogging)
|
||||
{
|
||||
Log.Message($"[SimpleTechnologyTrigger] Faction {faction.def.defName} is in blacklist");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查白名单
|
||||
if (SimpleProps.factionTypeWhitelist != null &&
|
||||
SimpleProps.factionTypeWhitelist.Count > 0)
|
||||
{
|
||||
bool inWhitelist = SimpleProps.factionTypeWhitelist.Contains(faction.def);
|
||||
|
||||
switch (SimpleProps.defaultBehavior)
|
||||
{
|
||||
case FactionFilterDefaultBehavior.Allow:
|
||||
// 白名单模式:在白名单中或默认允许
|
||||
if (SimpleProps.debugLogging && !inWhitelist)
|
||||
{
|
||||
Log.Message($"[SimpleTechnologyTrigger] Faction {faction.def.defName} not in whitelist, but default behavior is Allow");
|
||||
}
|
||||
return true;
|
||||
case FactionFilterDefaultBehavior.Deny:
|
||||
// 白名单模式:只有在白名单中才允许
|
||||
if (inWhitelist)
|
||||
{
|
||||
if (SimpleProps.debugLogging)
|
||||
{
|
||||
Log.Message($"[SimpleTechnologyTrigger] Faction {faction.def.defName} is in whitelist");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SimpleProps.debugLogging)
|
||||
{
|
||||
Log.Message($"[SimpleTechnologyTrigger] Faction {faction.def.defName} not in whitelist and default behavior is Deny");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有设置白名单,根据默认行为决定
|
||||
switch (SimpleProps.defaultBehavior)
|
||||
{
|
||||
case FactionFilterDefaultBehavior.Allow:
|
||||
if (SimpleProps.debugLogging)
|
||||
{
|
||||
Log.Message($"[SimpleTechnologyTrigger] No whitelist, default behavior is Allow");
|
||||
}
|
||||
return true;
|
||||
case FactionFilterDefaultBehavior.Deny:
|
||||
if (SimpleProps.debugLogging)
|
||||
{
|
||||
Log.Message($"[SimpleTechnologyTrigger] No whitelist, default behavior is Deny");
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取目标的派系
|
||||
/// </summary>
|
||||
private Faction GetTargetFaction(IIncidentTarget target)
|
||||
{
|
||||
if (target is Map map)
|
||||
{
|
||||
return map.ParentFaction ?? Faction.OfPlayer;
|
||||
}
|
||||
else if (target is World world)
|
||||
{
|
||||
return Faction.OfPlayer;
|
||||
}
|
||||
else if (target is Caravan caravan)
|
||||
{
|
||||
return caravan.Faction;
|
||||
}
|
||||
|
||||
return Faction.OfPlayer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否存在活跃的相同任务
|
||||
/// </summary>
|
||||
private bool HasActiveQuest()
|
||||
{
|
||||
if (SimpleProps.questDef == null)
|
||||
return false;
|
||||
|
||||
bool hasActiveQuest = Find.QuestManager.QuestsListForReading.Any((Quest q) =>
|
||||
q.root == SimpleProps.questDef && !q.Historical);
|
||||
|
||||
if (SimpleProps.debugLogging && hasActiveQuest)
|
||||
{
|
||||
Log.Message($"[SimpleTechnologyTrigger] Active quest {SimpleProps.questDef.defName} found, skipping trigger");
|
||||
}
|
||||
|
||||
return hasActiveQuest;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 调试方法:显示当前科技触发状态
|
||||
/// </summary>
|
||||
public string GetSimpleTechnologyTriggerStatus()
|
||||
{
|
||||
StringBuilder status = new StringBuilder();
|
||||
status.AppendLine($"Simple Technology Trigger: {SimpleProps.technology?.defName ?? "NULL"}");
|
||||
status.AppendLine($"Research Status: {(PassesTechnologyCheck() ? "✅ COMPLETED" : "❌ NOT COMPLETED")}");
|
||||
status.AppendLine($"Required Faction: {SimpleProps.requiredFaction?.defName ?? "NONE"}");
|
||||
status.AppendLine($"Faction Relation: {(PassesRequiredFactionCheck() ? "✅ VALID" : "❌ INVALID")}");
|
||||
status.AppendLine($"Check Interval: {SimpleProps.checkIntervalDays} days");
|
||||
status.AppendLine($"Current Interval: {IntervalsPassed}");
|
||||
status.AppendLine($"Next Check: {GetNextCheckInterval()} intervals");
|
||||
status.AppendLine($"Can Trigger Now: {PassesIntervalCheck() && PassesTechnologyCheck() && PassesRequiredFactionCheck()}");
|
||||
|
||||
// 详细派系信息
|
||||
if (SimpleProps.requiredFaction != null)
|
||||
{
|
||||
Faction faction = Find.FactionManager.FirstFactionOfDef(SimpleProps.requiredFaction);
|
||||
if (faction != null)
|
||||
{
|
||||
status.AppendLine($"Required Faction Status: {(faction.defeated ? "DEFEATED" : "ACTIVE")}");
|
||||
status.AppendLine($"Relation with Player: {(faction.HostileTo(Faction.OfPlayer) ? "HOSTILE" : "NON-HOSTILE")}");
|
||||
}
|
||||
else
|
||||
{
|
||||
status.AppendLine($"Required Faction Status: NOT FOUND IN GAME");
|
||||
}
|
||||
}
|
||||
|
||||
return status.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算下一次检查的间隔
|
||||
/// </summary>
|
||||
private int GetNextCheckInterval()
|
||||
{
|
||||
int checkInterval = (int)(SimpleProps.checkIntervalDays * 60);
|
||||
if (checkInterval <= 0) return 0;
|
||||
|
||||
int currentInterval = IntervalsPassed;
|
||||
return ((currentInterval / checkInterval) + 1) * checkInterval;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ namespace WulaFallenEmpire
|
||||
{
|
||||
public static JobDef WULA_EnterMaintenancePod;
|
||||
public static JobDef WULA_HaulToMaintenancePod;
|
||||
public static JobDef WULA_InspectBuilding;
|
||||
|
||||
static JobDefOf_WULA()
|
||||
{
|
||||
|
||||
@@ -177,6 +177,8 @@
|
||||
<Compile Include="HediffComp\HediffCompProperties_SwitchableHediff.cs" />
|
||||
<Compile Include="HediffComp\WULA_HediffDamgeShield\DRMDamageShield.cs" />
|
||||
<Compile Include="HediffComp\WULA_HediffDamgeShield\Hediff_DamageShield.cs" />
|
||||
<Compile Include="Job\JobDriver_InspectBuilding.cs" />
|
||||
<Compile Include="Job\JobGiver_InspectBuilding.cs" />
|
||||
<Compile Include="Pawn\Comp_MultiTurretGun.cs" />
|
||||
<Compile Include="Pawn\Comp_PawnRenderExtra.cs" />
|
||||
<Compile Include="Pawn\WULA_AutoMechCarrier\CompAutoMechCarrier.cs" />
|
||||
@@ -228,14 +230,18 @@
|
||||
<Compile Include="Pawn\WULA_Maintenance\Need_Maintenance.cs" />
|
||||
<Compile Include="Pawn\WULA_Maintenance\WorkGiver_DoMaintenance.cs" />
|
||||
<Compile Include="Placeworker\CompProperties_CustomRadius.cs" />
|
||||
<Compile Include="QuestNodes\QuestNode_AddInspectionJob.cs" />
|
||||
<Compile Include="QuestNodes\QuestNode_CheckGlobalResource.cs" />
|
||||
<Compile Include="QuestNodes\QuestNode_GeneratePawnWithCustomization.cs" />
|
||||
<Compile Include="QuestNodes\QuestNode_Hyperlinks.cs" />
|
||||
<Compile Include="QuestNodes\QuestPart_GlobalResourceCheck.cs" />
|
||||
<Compile Include="Stat\StatWorker_Energy.cs" />
|
||||
<Compile Include="Stat\StatWorker_Maintenance.cs" />
|
||||
<Compile Include="Stat\StatWorker_NanoRepair.cs" />
|
||||
<Compile Include="Storyteller\StorytellerCompProperties_ImportantQuestWithFactionFilter.cs" />
|
||||
<Compile Include="Storyteller\StorytellerComp_ImportantQuestWithFactionFilter.cs" />
|
||||
<Compile Include="Storyteller\WULA_ImportantQuestWithFactionFilter\StorytellerCompProperties_ImportantQuestWithFactionFilter.cs" />
|
||||
<Compile Include="Storyteller\WULA_ImportantQuestWithFactionFilter\StorytellerComp_ImportantQuestWithFactionFilter.cs" />
|
||||
<Compile Include="Storyteller\WULA_SimpleTechnologyTrigger\StorytellerCompProperties_SimpleTechnologyTrigger.cs" />
|
||||
<Compile Include="Storyteller\WULA_SimpleTechnologyTrigger\StorytellerComp_SimpleTechnologyTrigger.cs" />
|
||||
<Compile Include="ThingComp\CompAndPatch_GiveHediffOnShot.cs" />
|
||||
<Compile Include="ThingComp\CompApparelInterceptor.cs" />
|
||||
<Compile Include="ThingComp\CompPsychicScaling.cs" />
|
||||
|
||||
Reference in New Issue
Block a user