1
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
public class CompProperties_AbilityRequiresNonHostility : CompProperties_AbilityEffect
|
||||
{
|
||||
public FactionDef factionDef;
|
||||
|
||||
public CompProperties_AbilityRequiresNonHostility()
|
||||
{
|
||||
compClass = typeof(CompAbilityEffect_RequiresNonHostility);
|
||||
}
|
||||
}
|
||||
|
||||
public class CompAbilityEffect_RequiresNonHostility : CompAbilityEffect
|
||||
{
|
||||
public new CompProperties_AbilityRequiresNonHostility Props => (CompProperties_AbilityRequiresNonHostility)props;
|
||||
|
||||
public override bool GizmoDisabled(out string reason)
|
||||
{
|
||||
Pawn pawn = parent.pawn;
|
||||
if (pawn == null || pawn.Faction == null || Props.factionDef == null)
|
||||
{
|
||||
reason = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 查找指定派系
|
||||
Faction targetFaction = Find.FactionManager.FirstFactionOfDef(Props.factionDef);
|
||||
if (targetFaction == null)
|
||||
{
|
||||
reason = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查是否敌对
|
||||
if (pawn.Faction.HostileTo(targetFaction))
|
||||
{
|
||||
reason = "WULA_AbilityRequiresNonHostility".Translate(Props.factionDef);
|
||||
return true;
|
||||
}
|
||||
|
||||
reason = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,13 +21,10 @@ namespace WulaFallenEmpire
|
||||
#region 静态图标定义(使用原版MapPortal的图标)
|
||||
|
||||
/// <summary>查看口袋地图图标</summary>
|
||||
private static readonly Texture2D ViewPocketMapTex = ContentFinder<Texture2D>.Get("UI/Commands/ViewCave");
|
||||
|
||||
/// <summary>取消进入图标</summary>
|
||||
private static readonly Texture2D CancelEnterTex = ContentFinder<Texture2D>.Get("UI/Designators/Cancel");
|
||||
private static readonly Texture2D ViewPocketMapTex = ContentFinder<Texture2D>.Get("Wula/UI/Commands/WULA_View_ArmedShuttle_Pocket");
|
||||
|
||||
/// <summary>默认进入图标</summary>
|
||||
private static readonly Texture2D DefaultEnterTex = ContentFinder<Texture2D>.Get("UI/Commands/LoadTransporter");
|
||||
private static readonly Texture2D DefaultEnterTex = ContentFinder<Texture2D>.Get("Wula/UI/Commands/WULA_Enter_ArmedShuttle_Pocket");
|
||||
|
||||
#endregion
|
||||
#region 口袋空间字段
|
||||
|
||||
@@ -10,16 +10,61 @@ namespace WulaFallenEmpire
|
||||
|
||||
protected override bool Satisfied(Pawn pawn)
|
||||
{
|
||||
if (pawn == null || pawn.Dead || pawn.Downed)
|
||||
return false;
|
||||
try
|
||||
{
|
||||
if (pawn == null || pawn.Dead || pawn.Downed)
|
||||
return false;
|
||||
|
||||
// 检查是否有自主机械组件
|
||||
var comp = pawn.GetComp<CompAutonomousMech>();
|
||||
if (comp == null)
|
||||
return false;
|
||||
// 检查是否有自主机械组件
|
||||
var comp = pawn.GetComp<CompAutonomousMech>();
|
||||
if (comp == null)
|
||||
return false;
|
||||
|
||||
// 检查当前工作模式是否匹配要求
|
||||
return comp.CurrentWorkMode == requiredMode;
|
||||
// 检查当前工作模式是否匹配要求
|
||||
if (comp.CurrentWorkMode != requiredMode)
|
||||
return false;
|
||||
|
||||
// 额外的安全检查:确保pawn有工作设置
|
||||
if (pawn.workSettings == null)
|
||||
{
|
||||
Log.Warning($"[WULA] {pawn.LabelShort} has no workSettings in ThinkNode_ConditionalAutonomousWorkMode");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查是否启用了工作
|
||||
if (!pawn.workSettings.EverWork)
|
||||
{
|
||||
Log.Warning($"[WULA] {pawn.LabelShort} has EverWork=false in ThinkNode_ConditionalAutonomousWorkMode");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查是否有工作给予器
|
||||
var workGivers = pawn.workSettings.WorkGiversInOrderNormal;
|
||||
if (workGivers == null || workGivers.Count == 0)
|
||||
{
|
||||
Log.Warning($"[WULA] {pawn.LabelShort} has no work givers in ThinkNode_ConditionalAutonomousWorkMode");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查是否为机械体且具有机械体能力
|
||||
if (pawn.RaceProps.IsMechanoid)
|
||||
{
|
||||
// 检查是否有操纵能力
|
||||
var manipulation = pawn.health?.capacities?.GetLevel(PawnCapacityDefOf.Manipulation);
|
||||
if (manipulation < 0.1f)
|
||||
{
|
||||
Log.Warning($"[WULA] {pawn.LabelShort} has insufficient manipulation capacity: {manipulation}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log.Error($"[WULA] Exception in ThinkNode_ConditionalAutonomousWorkMode.Satisfied for pawn {pawn?.LabelShort}: {ex}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ namespace WulaFallenEmpire
|
||||
public SlateRef<Map> map;
|
||||
public SlateRef<bool> sendMessageOnSuccess = true;
|
||||
public SlateRef<bool> sendMessageOnFailure = true;
|
||||
public SlateRef<bool> allowThickRoof = false;
|
||||
public SlateRef<bool> allowThinRoof = true;
|
||||
|
||||
protected override bool TestRunInt(Slate slate)
|
||||
{
|
||||
@@ -35,13 +37,6 @@ namespace WulaFallenEmpire
|
||||
return false;
|
||||
}
|
||||
|
||||
var compProps = thingDef.GetValue(slate).comps?.OfType<CompProperties_PrefabSkyfallerCaller>().FirstOrDefault();
|
||||
if (compProps == null)
|
||||
{
|
||||
Log.Warning($"[QuestNode] ThingDef {thingDef.GetValue(slate).defName} does not have CompProperties_PrefabSkyfallerCaller");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -56,6 +51,8 @@ namespace WulaFallenEmpire
|
||||
Map targetMap = map.GetValue(slate) ?? Find.CurrentMap;
|
||||
bool doSendMessageOnSuccess = sendMessageOnSuccess.GetValue(slate);
|
||||
bool doSendMessageOnFailure = sendMessageOnFailure.GetValue(slate);
|
||||
bool targetAllowThickRoof = allowThickRoof.GetValue(slate);
|
||||
bool targetAllowThinRoof = allowThinRoof.GetValue(slate);
|
||||
|
||||
if (targetThingDef == null)
|
||||
{
|
||||
@@ -69,18 +66,10 @@ namespace WulaFallenEmpire
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取组件属性
|
||||
var compProps = targetThingDef.comps?.OfType<CompProperties_PrefabSkyfallerCaller>().FirstOrDefault();
|
||||
if (compProps == null)
|
||||
{
|
||||
Log.Error($"[QuestNode] ThingDef {targetThingDef.defName} does not have CompProperties_PrefabSkyfallerCaller");
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Message($"[QuestNode] Attempting to spawn {targetSpawnCount} {targetThingDef.defName} on map {targetMap}");
|
||||
|
||||
// 执行生成
|
||||
int successCount = SpawnThingsAtValidLocations(targetThingDef, targetFaction, targetSpawnCount, targetMap);
|
||||
int successCount = SpawnThingsAtValidLocations(targetThingDef, targetFaction, targetSpawnCount, targetMap, targetAllowThickRoof, targetAllowThinRoof);
|
||||
|
||||
// 发送结果消息
|
||||
if (successCount > 0)
|
||||
@@ -108,23 +97,16 @@ namespace WulaFallenEmpire
|
||||
/// <summary>
|
||||
/// 在有效位置生成多个建筑
|
||||
/// </summary>
|
||||
private int SpawnThingsAtValidLocations(ThingDef thingDef, Faction faction, int spawnCount, Map targetMap)
|
||||
private int SpawnThingsAtValidLocations(ThingDef thingDef, Faction faction, int spawnCount, Map targetMap, bool allowThickRoof, bool allowThinRoof)
|
||||
{
|
||||
int successCount = 0;
|
||||
int attempts = 0;
|
||||
const int maxAttempts = 100; // 最大尝试次数
|
||||
|
||||
var compProps = thingDef.comps.OfType<CompProperties_PrefabSkyfallerCaller>().FirstOrDefault();
|
||||
if (compProps == null)
|
||||
{
|
||||
Log.Error($"[QuestNode] Could not find CompProperties_PrefabSkyfallerCaller for {thingDef.defName}");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < spawnCount && attempts < maxAttempts; i++)
|
||||
{
|
||||
attempts++;
|
||||
IntVec3 spawnPos = FindSpawnPositionForSkyfaller(targetMap, thingDef, compProps);
|
||||
IntVec3 spawnPos = FindSpawnPositionForSkyfaller(targetMap, thingDef, allowThickRoof, allowThinRoof);
|
||||
|
||||
if (spawnPos.IsValid)
|
||||
{
|
||||
@@ -152,7 +134,7 @@ namespace WulaFallenEmpire
|
||||
/// <summary>
|
||||
/// 查找适合Skyfaller空投的位置
|
||||
/// </summary>
|
||||
private IntVec3 FindSpawnPositionForSkyfaller(Map map, ThingDef thingDef, CompProperties_SkyfallerCaller compProps)
|
||||
private IntVec3 FindSpawnPositionForSkyfaller(Map map, ThingDef thingDef, bool allowThickRoof, bool allowThinRoof)
|
||||
{
|
||||
var potentialCells = new List<IntVec3>();
|
||||
|
||||
@@ -160,7 +142,7 @@ namespace WulaFallenEmpire
|
||||
var baseCells = GetOpenAreaCellsNearBase(map, thingDef.Size);
|
||||
foreach (var cell in baseCells)
|
||||
{
|
||||
if (IsValidForSkyfallerDrop(map, cell, thingDef, compProps))
|
||||
if (IsValidForSkyfallerDrop(map, cell, thingDef, allowThickRoof, allowThinRoof))
|
||||
{
|
||||
potentialCells.Add(cell);
|
||||
}
|
||||
@@ -176,7 +158,7 @@ namespace WulaFallenEmpire
|
||||
var openAreas = FindOpenAreas(map, thingDef.Size, 500);
|
||||
foreach (var cell in openAreas)
|
||||
{
|
||||
if (IsValidForSkyfallerDrop(map, cell, thingDef, compProps))
|
||||
if (IsValidForSkyfallerDrop(map, cell, thingDef, allowThickRoof, allowThinRoof))
|
||||
{
|
||||
potentialCells.Add(cell);
|
||||
}
|
||||
@@ -197,7 +179,7 @@ namespace WulaFallenEmpire
|
||||
Rand.Range(thingDef.Size.z, map.Size.z - thingDef.Size.z)
|
||||
);
|
||||
|
||||
if (randomCell.InBounds(map) && IsValidForSkyfallerDrop(map, randomCell, thingDef, compProps))
|
||||
if (randomCell.InBounds(map) && IsValidForSkyfallerDrop(map, randomCell, thingDef, allowThickRoof, allowThinRoof))
|
||||
{
|
||||
potentialCells.Add(randomCell);
|
||||
}
|
||||
@@ -216,7 +198,7 @@ namespace WulaFallenEmpire
|
||||
/// <summary>
|
||||
/// 基于Skyfaller实际行为的有效性检查
|
||||
/// </summary>
|
||||
private bool IsValidForSkyfallerDrop(Map map, IntVec3 cell, ThingDef thingDef, CompProperties_SkyfallerCaller compProps)
|
||||
private bool IsValidForSkyfallerDrop(Map map, IntVec3 cell, ThingDef thingDef, bool allowThickRoof, bool allowThinRoof)
|
||||
{
|
||||
// 1. 检查边界
|
||||
if (!cell.InBounds(map))
|
||||
@@ -230,11 +212,11 @@ namespace WulaFallenEmpire
|
||||
if (!occupiedCell.InBounds(map))
|
||||
return false;
|
||||
|
||||
// 3. 检查厚岩顶 - 绝对不允许
|
||||
// 3. 检查厚岩顶 - 绝对不允许(除非明确允许)
|
||||
RoofDef roof = occupiedCell.GetRoof(map);
|
||||
if (roof != null && roof.isThickRoof)
|
||||
{
|
||||
if (!compProps.allowThickRoof)
|
||||
if (!allowThickRoof)
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -274,7 +256,7 @@ namespace WulaFallenEmpire
|
||||
// 6. 检查薄岩顶和普通屋顶的条件
|
||||
if (roof != null && !roof.isThickRoof)
|
||||
{
|
||||
if (!compProps.allowThinRoof)
|
||||
if (!allowThinRoof)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
using System.Collections.Generic;
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
using Verse.AI;
|
||||
|
||||
namespace WulaFallenEmpire
|
||||
{
|
||||
// 扩展方法,用于检查特定种族
|
||||
public static class WorkGiverExtensions
|
||||
{
|
||||
// 检查是否为指定种族
|
||||
public static bool IsRace(this Pawn pawn, string raceDefName)
|
||||
{
|
||||
return pawn.def.defName == raceDefName;
|
||||
}
|
||||
|
||||
// 检查是否为指定种族之一
|
||||
public static bool IsAnyRace(this Pawn pawn, params string[] raceDefNames)
|
||||
{
|
||||
string pawnRace = pawn.def.defName;
|
||||
foreach (string race in raceDefNames)
|
||||
{
|
||||
if (pawnRace == race)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 使用扩展方法的子类
|
||||
public class WorkGiver_DeepDrill_WulaCatConstructor : WorkGiver_DeepDrill
|
||||
{
|
||||
private const string AllowedRace = "Mech_WULA_Cat_Constructor";
|
||||
|
||||
public override bool ShouldSkip(Pawn pawn, bool forced = false)
|
||||
{
|
||||
|
||||
// 检查种族
|
||||
if (!pawn.IsRace(AllowedRace))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// 调用基类方法
|
||||
bool shouldSkip = base.ShouldSkip(pawn, forced);
|
||||
|
||||
return shouldSkip;
|
||||
}
|
||||
|
||||
public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false)
|
||||
{
|
||||
// 检查种族
|
||||
if (!pawn.IsRace(AllowedRace))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 调用基类方法
|
||||
bool hasJob = base.HasJobOnThing(pawn, t, forced);
|
||||
|
||||
return hasJob;
|
||||
}
|
||||
|
||||
// 可选:自定义工作优先级
|
||||
public override float GetPriority(Pawn pawn, TargetInfo t)
|
||||
{
|
||||
if (!pawn.IsRace(AllowedRace))
|
||||
{
|
||||
return 0f; // 不是允许的种族,优先级为0
|
||||
}
|
||||
|
||||
// 如果是允许的种族,提高优先级
|
||||
float basePriority = base.GetPriority(pawn, t);
|
||||
return basePriority * 1.5f; // 提高50%优先级
|
||||
}
|
||||
|
||||
// 可选:提供自定义的工作描述
|
||||
public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false)
|
||||
{
|
||||
if (!pawn.IsRace(AllowedRace))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Job job = base.JobOnThing(pawn, t, forced);
|
||||
if (job != null)
|
||||
{
|
||||
// 可以在这里添加自定义标签或其他修改
|
||||
job.playerForced = forced;
|
||||
}
|
||||
|
||||
return job;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,6 +74,7 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="Ability\CompAbilityEffect_LaunchMultiProjectile.cs" />
|
||||
<Compile Include="Ability\CompAbilityEffect_ResearchPrereq.cs" />
|
||||
<Compile Include="Ability\CompAbilityEffect_RequiresNonHostility.cs" />
|
||||
<Compile Include="Ability\WULA_AbilityAreaDestruction\CompAbilityEffect_AreaDestruction.cs" />
|
||||
<Compile Include="Ability\WULA_AbilityAreaDestruction\CompProperties_AbilityAreaDestruction.cs" />
|
||||
<Compile Include="Ability\WULA_AbilityBombardment\CompAbilityEffect_Bombardment.cs" />
|
||||
@@ -359,6 +360,7 @@
|
||||
<Compile Include="Verb\MeleeAttack_Cleave\Verb_MeleeAttack_Cleave.cs" />
|
||||
<Compile Include="Verb\Verb_ShootShotgunWithOffset.cs" />
|
||||
<Compile Include="Verb\Verb_ShootWithOffset.cs" />
|
||||
<Compile Include="WorkGiver\WorkGiver_DeepDrill_WulaConstructor.cs" />
|
||||
<Compile Include="WulaFallenEmpireMod.cs" />
|
||||
<Compile Include="WulaDefOf.cs" />
|
||||
<Compile Include="HediffComp\HediffComp_DamageResponse.cs" />
|
||||
|
||||
Reference in New Issue
Block a user