This commit is contained in:
Tourswen
2025-12-07 03:07:50 +08:00
parent 8a158d1ced
commit f1956d5961
43 changed files with 1079 additions and 426 deletions

View File

@@ -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;
}
}
}

View File

@@ -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

View File

@@ -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;
}
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}
}

View File

@@ -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" />