Files
WulaFallenEmpireRW/Source/WulaFallenEmpire/HediffComp/HediffCompProperties_DisappearWithEffect .cs
2025-11-18 17:30:12 +08:00

280 lines
9.4 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.Sound;
namespace WulaFallenEmpire
{
// HediffCompProperties 定义
public class HediffCompProperties_DisappearWithEffect : HediffCompProperties_Disappears
{
public FleckDef fleckDef; // 要播放的特效
public float fleckScale = 1f; // 特效缩放
public bool dropEquipment = false; // 是否掉落装备false = 直接销毁)
public bool destroyCorpse = true; // 是否销毁尸体
public bool playSound = true; // 是否播放音效
public SoundDef soundDef; // 自定义音效
public HediffCompProperties_DisappearWithEffect()
{
compClass = typeof(HediffComp_DisappearWithEffect);
}
}
// HediffComp 实现
public class HediffComp_DisappearWithEffect : HediffComp
{
public HediffCompProperties_DisappearWithEffect Props =>
(HediffCompProperties_DisappearWithEffect)props;
private int ticksUntilDisappear = -1;
private bool triggered = false;
public override void CompPostMake()
{
base.CompPostMake();
if (Props.disappearsAfterTicks != null)
{
ticksUntilDisappear = Props.disappearsAfterTicks.RandomInRange;
}
}
// 重写 CompPostTick 方法,在到达指定 tick 时触发效果
public override void CompPostTick(ref float severityAdjustment)
{
base.CompPostTick(ref severityAdjustment);
if (triggered || Pawn == null || Pawn.Destroyed) return;
// 检查是否到达消失时间
if (ticksUntilDisappear > 0)
{
ticksUntilDisappear--;
if (ticksUntilDisappear <= 0)
{
TriggerDisappearEffect();
}
}
// 如果 pawn 已经死亡,立即触发效果
else if (Pawn.Dead)
{
TriggerDisappearEffect();
}
}
// 处理 pawn 死亡事件 - 修复参数问题
public override void Notify_PawnDied(DamageInfo? dinfo, Hediff culprit = null)
{
base.Notify_PawnDied(dinfo, culprit);
if (!triggered)
{
TriggerDisappearEffect();
}
}
// 触发消失效果的核心方法
private void TriggerDisappearEffect()
{
if (triggered || Pawn == null || Pawn.Map == null || Pawn.Destroyed)
return;
triggered = true;
try
{
// 记录位置
IntVec3 position = Pawn.Position;
Map map = Pawn.Map;
// 1. 清除所有装备
ClearAllEquipment(map);
// 2. 播放特效
PlayFleckEffect(position, map);
// 3. 播放音效
PlaySoundEffect(position, map);
// 4. 发送消失消息(如果配置了)
SendDisappearMessage();
// 5. 删除 pawn
DestroyPawn();
Log.Message($"[DisappearWithEffect] Pawn {Pawn.LabelCap} disappeared at {position}");
}
catch (System.Exception ex)
{
Log.Error($"[DisappearWithEffect] Error in TriggerDisappearEffect: {ex}");
}
}
// 清除所有装备 - 修复参数问题
private void ClearAllEquipment(Map map)
{
if (Pawn.equipment == null && Pawn.apparel == null && Pawn.inventory == null)
return;
// 清除装备(武器)
if (Pawn.equipment != null)
{
var allEquipment = Pawn.equipment.AllEquipmentListForReading.ListFullCopy();
foreach (var thing in allEquipment)
{
if (Props.dropEquipment)
{
// 掉落装备 - 修复类型转换问题
ThingWithComps droppedWeapon;
Pawn.equipment.TryDropEquipment(thing, out droppedWeapon, Pawn.Position, true);
}
else
{
// 直接销毁装备
thing.Destroy(DestroyMode.Vanish);
}
}
}
// 清除 apparel服装
if (Pawn.apparel != null)
{
var wornApparel = Pawn.apparel.WornApparel.ListFullCopy();
foreach (var apparel in wornApparel)
{
if (Props.dropEquipment)
{
// 掉落服装
Apparel droppedApparel;
Pawn.apparel.TryDrop(apparel, out droppedApparel, Pawn.Position, true);
}
else
{
// 直接销毁服装
apparel.Destroy(DestroyMode.Vanish);
}
}
}
// 清除 inventory物品栏
if (Pawn.inventory != null)
{
var innerContainer = Pawn.inventory.innerContainer.InnerListForReading.ListFullCopy();
foreach (var thing in innerContainer)
{
if (Props.dropEquipment)
{
// 掉落物品
Thing droppedThing;
Pawn.inventory.innerContainer.TryDrop(thing, Pawn.Position, map, ThingPlaceMode.Near, out droppedThing);
}
else
{
// 直接销毁物品
thing.Destroy(DestroyMode.Vanish);
}
}
}
}
// 播放特效
private void PlayFleckEffect(IntVec3 position, Map map)
{
FleckDef fleckToUse = Props.fleckDef ?? FleckDefOf.PsycastAreaEffect;
// 在 pawn 位置播放特效
FleckMaker.Static(position, map, fleckToUse, Props.fleckScale);
// 额外在周围格子上播放特效,增强视觉效果
for (int i = 0; i < 8; i++)
{
IntVec3 nearbyCell = position + GenAdj.AdjacentCells[i];
if (nearbyCell.InBounds(map))
{
FleckMaker.Static(nearbyCell, map, fleckToUse, Props.fleckScale * 0.7f);
}
}
}
// 播放音效 - 修复音效播放问题
private void PlaySoundEffect(IntVec3 position, Map map)
{
if (!Props.playSound) return;
SoundDef soundToUse = Props.soundDef ?? SoundDefOf.PsycastPsychicPulse;
// 使用 SoundStarter 播放音效
SoundInfo soundInfo = SoundInfo.InMap(new TargetInfo(position, map));
soundToUse.PlayOneShot(soundInfo);
}
// 发送消失消息
private void SendDisappearMessage()
{
var disappearProps = props as HediffCompProperties_Disappears;
if (disappearProps?.messageOnDisappear != null)
{
Messages.Message(disappearProps.messageOnDisappear.Translate(Pawn.LabelShort),
Pawn, MessageTypeDefOf.NeutralEvent);
}
if (disappearProps?.letterLabelOnDisappear != null &&
disappearProps?.letterTextOnDisappear != null &&
Pawn.Faction == Faction.OfPlayer)
{
Find.LetterStack.ReceiveLetter(
disappearProps.letterLabelOnDisappear.Translate(Pawn.LabelShort),
disappearProps.letterTextOnDisappear.Translate(Pawn.LabelShort),
LetterDefOf.NeutralEvent,
new LookTargets(Pawn)
);
}
}
// 删除 pawn
private void DestroyPawn()
{
if (Pawn.Dead && Props.destroyCorpse)
{
// 如果是尸体,直接销毁
Pawn.Destroy();
}
else if (!Pawn.Dead)
{
// 如果是活着的 pawn先杀死再销毁
Pawn.Kill(null, this.parent);
if (Props.destroyCorpse)
{
Pawn.Destroy();
}
}
}
// 重写 CompTipStringExtra 显示额外信息
public override string CompTipStringExtra
{
get
{
if (ticksUntilDisappear > 0 && Props.showRemainingTime)
{
return "DisappearWithEffect_TimeRemaining".Translate(
ticksUntilDisappear.ToStringTicksToPeriod(Props.canUseDecimalsShortForm));
}
return null;
}
}
// 重写 CompDebugString 用于调试
public override string CompDebugString()
{
return $"Will disappear in: {ticksUntilDisappear} ticks (Triggered: {triggered})";
}
// 序列化数据
public override void CompExposeData()
{
base.CompExposeData();
Scribe_Values.Look(ref ticksUntilDisappear, "ticksUntilDisappear", -1);
Scribe_Values.Look(ref triggered, "triggered", false);
}
}
}