这对吗

This commit is contained in:
2025-11-25 15:29:35 +08:00
parent d608f1a07c
commit 79a02f99e0
11 changed files with 529 additions and 182 deletions

View File

@@ -58,17 +58,20 @@ namespace WulaFallenEmpire
return graphic;
}
// 完全重写 DrawAt 方法,实现自定义渲染系统
protected override void DrawAt(Vector3 drawLoc, bool flip = false)
{
// 不调用基类的 DrawAt完全自定义渲染
// 更新悬浮动画
UpdateHoverAnimation();
// 绘制所有配置的图形层
DrawGraphicLayers(drawLoc, flip);
// 新增:绘制护盾
var shieldComp = this.GetComp<ThingComp_AreaShield>();
if (shieldComp != null)
{
shieldComp.PostDraw();
}
}
// 绘制所有图形层

View File

@@ -40,10 +40,6 @@ namespace WulaFallenEmpire
if (validFlyOvers.Count == 0)
{
if (throwMessages)
{
Messages.Message(Props.facilityNotFoundMessage, parent.pawn, MessageTypeDefOf.RejectInput);
}
return false;
}
@@ -87,7 +83,6 @@ namespace WulaFallenEmpire
{
// 如果指定了特定的 FlyOver 定义,只检查该定义的物体
allFlyOvers = parent.pawn.Map.listerThings.ThingsOfDef(Props.flyOverDef);
Log.Message($"[RequireFlyOverFacility] Checking specific FlyOverDef: {Props.flyOverDef.defName}, found: {allFlyOvers.Count}");
}
else
{
@@ -102,7 +97,6 @@ namespace WulaFallenEmpire
allFlyOvers.Add(thing);
}
}
Log.Message($"[RequireFlyOverFacility] Checking all FlyOver types, found: {allFlyOvers.Count}");
}
foreach (var thing in allFlyOvers)
@@ -119,12 +113,10 @@ namespace WulaFallenEmpire
if (!facilitiesComp.HasFacility(Props.requiredFacility))
{
Log.Message($"[RequireFlyOverFacility] FlyOver at {flyOver.Position} missing facility: {Props.requiredFacility}. Has: {string.Join(", ", facilitiesComp.GetActiveFacilities())}");
continue;
}
validFlyOvers.Add(flyOver);
Log.Message($"[RequireFlyOverFacility] Found valid FlyOver at {flyOver.Position} with facility: {Props.requiredFacility}");
}
}
@@ -144,7 +136,6 @@ namespace WulaFallenEmpire
var selectedFlyOver = availableFlyOvers.FirstOrDefault();
if (selectedFlyOver != null)
{
Log.Message($"[RequireFlyOverFacility] Skill executed using FlyOver at {selectedFlyOver.Position} with facility: {Props.requiredFacility}");
}
}

View File

@@ -0,0 +1,403 @@
using RimWorld;
using Verse;
using System.Collections.Generic;
using UnityEngine;
namespace WulaFallenEmpire
{
public class CompGiveHediffsInRange : ThingComp
{
private CompProperties_GiveHediffsInRange Props => (CompProperties_GiveHediffsInRange)props;
// 跟踪受影响的pawn和他们的Hediff
private Dictionary<Pawn, Hediff> affectedPawns = new Dictionary<Pawn, Hediff>();
// 效果实例缓存
private Dictionary<Pawn, Effecter> effecters = new Dictionary<Pawn, Effecter>();
public override void CompTick()
{
base.CompTick();
if (parent == null || !parent.Spawned || parent.Map == null)
return;
// 使用间隔检查优化性能
if (Find.TickManager.TicksGame % Props.checkIntervalTicks != 0)
return;
UpdateAffectedPawns();
}
private void UpdateAffectedPawns()
{
if (Props.hediff == null) return;
// 获取范围内的所有pawn
List<Pawn> pawnsInRange = GetPawnsInRange();
// 处理新进入范围的pawn
foreach (var pawn in pawnsInRange)
{
if (!affectedPawns.ContainsKey(pawn) && ShouldAffectPawn(pawn))
{
AddHediffToPawn(pawn);
}
}
// 处理离开范围的pawn
var pawnsToRemove = new List<Pawn>();
foreach (var kvp in affectedPawns)
{
if (!pawnsInRange.Contains(kvp.Key) || !ShouldAffectPawn(kvp.Key))
{
pawnsToRemove.Add(kvp.Key);
}
else
{
// 更新持续时间的Hediff
UpdateHediffDuration(kvp.Key, kvp.Value);
}
}
foreach (var pawn in pawnsToRemove)
{
RemoveHediffFromPawn(pawn);
}
}
private List<Pawn> GetPawnsInRange()
{
var pawns = new List<Pawn>();
if (parent?.Map == null) return pawns;
var map = parent.Map;
var center = parent.Position;
// 使用网格搜索优化性能
foreach (var thing in map.listerThings.ThingsInGroup(ThingRequestGroup.Pawn))
{
if (thing is Pawn pawn &&
pawn.Position.DistanceTo(center) <= Props.range &&
pawn.Spawned)
{
pawns.Add(pawn);
}
}
return pawns;
}
/// <summary>
/// 检查pawn是否应该受到效果影响
/// </summary>
private bool ShouldAffectPawn(Pawn pawn)
{
if (pawn == null || pawn.Dead || pawn.Destroyed)
return false;
// 派系检查
if (Props.onlyPawnsInSameFaction && pawn.Faction != parent.Faction)
return false;
// 种族类型检查
if (Props.requireHumanlike && !pawn.RaceProps.Humanlike)
return false;
if (Props.requireAnimal && !pawn.RaceProps.Animal)
return false;
if (Props.requireMechanoid && !pawn.RaceProps.IsMechanoid)
return false;
// 特定种族检查
if (Props.allowedRaces != null && Props.allowedRaces.Count > 0)
{
if (!Props.allowedRaces.Contains(pawn.def))
return false;
}
// 排除种族检查
if (Props.excludedRaces != null && Props.excludedRaces.Count > 0)
{
if (Props.excludedRaces.Contains(pawn.def))
return false;
}
// 修复:安全的派系关系检查
if (parent.Faction != null && pawn.Faction != null)
{
// 避免检查同一派系与自身的关系
if (parent.Faction == pawn.Faction)
{
// 同一派系,视为盟友
if (!Props.affectAllies)
return false;
}
else
{
try
{
FactionRelationKind relation = parent.Faction.RelationKindWith(pawn.Faction);
if (!Props.affectAllies && relation == FactionRelationKind.Ally)
return false;
if (!Props.affectEnemies && relation == FactionRelationKind.Hostile)
return false;
if (!Props.affectNeutrals && relation == FactionRelationKind.Neutral)
return false;
}
catch (System.Exception ex)
{
Log.Warning($"检查派系关系时出错: {ex.Message}");
// 出错时保守处理,不施加效果
return false;
}
}
}
else
{
// 如果建筑或pawn没有派系根据设置处理
if (parent.Faction == null && pawn.Faction == null)
{
// 两者都没有派系,视为中立
if (!Props.affectNeutrals)
return false;
}
else if (pawn.Faction == null)
{
// pawn没有派系野生动物等视为中立
if (!Props.affectNeutrals)
return false;
}
}
// 囚犯和奴隶检查
if (!Props.affectPrisoners && pawn.IsPrisoner)
return false;
if (!Props.affectSlaves && pawn.IsSlave)
return false;
return true;
}
private void AddHediffToPawn(Pawn pawn)
{
try
{
// 检查pawn是否已经有这个Hediff
Hediff existingHediff = pawn.health.hediffSet.GetFirstHediffOfDef(Props.hediff);
if (existingHediff != null)
{
// 如果已经有相同的Hediff更新它而不是创建新的
affectedPawns[pawn] = existingHediff;
UpdateHediffDuration(pawn, existingHediff);
return;
}
// 添加Hediff
Hediff newHediff = HediffMaker.MakeHediff(Props.hediff, pawn);
newHediff.Severity = Props.initialSeverity;
// 设置持续时间(如果有)
if (Props.hediffDurationTicks > 0)
{
var comp = newHediff.TryGetComp<HediffComp_Disappears>();
if (comp != null)
{
comp.ticksToDisappear = Props.hediffDurationTicks;
}
}
pawn.health.AddHediff(newHediff);
affectedPawns[pawn] = newHediff;
// 创建视觉效果
CreateEffectForPawn(pawn);
// 记录日志(可选,调试时使用)
// Log.Message($"给予 {pawn.LabelShort} ({pawn.def.defName}) Hediff: {Props.hediff.defName}");
}
catch (System.Exception ex)
{
Log.Warning($"无法给 {pawn.LabelShort} 添加Hediff: {ex.Message}");
}
}
private void RemoveHediffFromPawn(Pawn pawn)
{
if (affectedPawns.TryGetValue(pawn, out var hediff))
{
try
{
// 安全地移除Hediff
if (pawn.health.hediffSet.hediffs.Contains(hediff))
{
pawn.health.RemoveHediff(hediff);
}
}
catch (System.Exception ex)
{
Log.Warning($"移除 {pawn.LabelShort} 的Hediff时出错: {ex.Message}");
}
affectedPawns.Remove(pawn);
}
// 移除视觉效果
RemoveEffectForPawn(pawn);
}
private void UpdateHediffDuration(Pawn pawn, Hediff hediff)
{
if (Props.hediffDurationTicks > 0)
{
var comp = hediff.TryGetComp<HediffComp_Disappears>();
if (comp != null)
{
// 重置持续时间,让效果持续
comp.ticksToDisappear = Props.hediffDurationTicks;
}
}
}
private void CreateEffectForPawn(Pawn pawn)
{
if (Props.mote != null)
{
try
{
// 创建持续的视觉效果
var effecterDef = DefDatabase<EffecterDef>.GetNamedSilentFail(Props.mote.defName + "_Effecter");
if (effecterDef != null)
{
var effecter = effecterDef.Spawn();
effecters[pawn] = effecter;
}
else
{
// 如果没有对应的EffecterDef直接创建Mote
MoteMaker.MakeStaticMote(pawn.Position, pawn.Map, Props.mote, 1f);
}
}
catch (System.Exception ex)
{
Log.Warning($"创建视觉效果时出错: {ex.Message}");
}
}
}
private void RemoveEffectForPawn(Pawn pawn)
{
if (effecters.TryGetValue(pawn, out var effecter))
{
try
{
effecter.Cleanup();
}
catch (System.Exception ex)
{
Log.Warning($"清理视觉效果时出错: {ex.Message}");
}
effecters.Remove(pawn);
}
}
public override void CompTickRare()
{
base.CompTickRare();
// 更新视觉效果
var effectersToRemove = new List<Pawn>();
foreach (var kvp in effecters)
{
if (kvp.Key != null && kvp.Key.Spawned && affectedPawns.ContainsKey(kvp.Key))
{
try
{
kvp.Value.EffectTick(kvp.Key, kvp.Key);
}
catch (System.Exception ex)
{
Log.Warning($"更新视觉效果时出错: {ex.Message}");
effectersToRemove.Add(kvp.Key);
}
}
else
{
effectersToRemove.Add(kvp.Key);
}
}
// 清理无效的效果器
foreach (var pawn in effectersToRemove)
{
RemoveEffectForPawn(pawn);
}
}
public override void PostDeSpawn(Map map, DestroyMode mode = DestroyMode.Vanish)
{
base.PostDeSpawn(map);
CleanupAllEffects();
}
public override void PostDestroy(DestroyMode mode, Map previousMap)
{
base.PostDestroy(mode, previousMap);
CleanupAllEffects();
}
/// <summary>
/// 清理所有效果
/// </summary>
private void CleanupAllEffects()
{
// 移除所有Hediff
var pawnsToRemove = new List<Pawn>(affectedPawns.Keys);
foreach (var pawn in pawnsToRemove)
{
RemoveHediffFromPawn(pawn);
}
affectedPawns.Clear();
// 清理所有视觉效果
var effectersToRemove = new List<Pawn>(effecters.Keys);
foreach (var pawn in effectersToRemove)
{
RemoveEffectForPawn(pawn);
}
effecters.Clear();
}
// 调试方法:显示影响范围
public override void PostDraw()
{
base.PostDraw();
if (Find.Selector.IsSelected(parent))
{
try
{
GenDraw.DrawRadiusRing(parent.Position, Props.range, Color.green);
}
catch (System.Exception ex)
{
Log.Warning($"绘制范围环时出错: {ex.Message}");
}
}
}
// 获取当前受影响的pawn数量用于显示
public int GetAffectedPawnCount()
{
return affectedPawns.Count;
}
// 获取受影响的pawn列表用于调试
public IEnumerable<Pawn> GetAffectedPawns()
{
return affectedPawns.Keys;
}
}
}

View File

@@ -0,0 +1,40 @@
using RimWorld;
using Verse;
using System.Collections.Generic;
namespace WulaFallenEmpire
{
public class CompProperties_GiveHediffsInRange : CompProperties
{
public float range = 10f;
public TargetingParameters targetingParameters;
public HediffDef hediff;
public ThingDef mote;
public bool hideMoteWhenNotDrafted;
public float initialSeverity = 1f;
public bool onlyPawnsInSameFaction = true;
// 新增:种族筛选
public List<ThingDef> allowedRaces;
public List<ThingDef> excludedRaces;
public bool requireHumanlike = false;
public bool requireAnimal = false;
public bool requireMechanoid = false;
// 新增:效果控制
public bool affectAllies = true;
public bool affectEnemies = true;
public bool affectNeutrals = true;
public bool affectPrisoners = false;
public bool affectSlaves = false;
// 新增:间隔控制
public int checkIntervalTicks = 60;
public int hediffDurationTicks = -1; // -1 表示永久
public CompProperties_GiveHediffsInRange()
{
compClass = typeof(CompGiveHediffsInRange);
}
}
}

View File

@@ -261,6 +261,8 @@
<Compile Include="ThingComp\WULA_AreaShield\ThingComp_AreaShield.cs" />
<Compile Include="ThingComp\WULA_CustomUniqueWeapon\CompCustomUniqueWeapon.cs" />
<Compile Include="ThingComp\WULA_CustomUniqueWeapon\CompProperties_CustomUniqueWeapon.cs" />
<Compile Include="ThingComp\WULA_GiveHediffsInRange\CompGiveHediffsInRange.cs" />
<Compile Include="ThingComp\WULA_GiveHediffsInRange\CompProperties_GiveHediffsInRange.cs" />
<Compile Include="ThingComp\WULA_MechRepairKit\CompUseEffect_FixAllHealthConditions.cs" />
<Compile Include="ThingComp\WULA_MechRepairKit\Recipe_AdministerWulaMechRepairKit.cs" />
<Compile Include="ThingComp\WULA_PeriodicGameCondition\CompPeriodicGameCondition.cs" />