Files
ArachnaeSwarm/Source/ArachnaeSwarm/Abilities/CompAbilityEffect_RandomHediff.cs
2025-10-22 17:30:39 +08:00

451 lines
15 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 System.Collections.Generic;
using System.Linq;
using System.Text;
using Verse;
namespace ArachnaeSwarm
{
public class CompAbilityEffect_RandomHediff : CompAbilityEffect_WithDuration
{
public new CompProperties_AbilityRandomHediff Props => (CompProperties_AbilityRandomHediff)props;
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
{
base.Apply(target, dest);
if (!Props.ignoreSelf || target.Pawn != parent.pawn)
{
if (!Props.onlyApplyToSelf && Props.applyToTarget)
{
ApplyInner(target.Pawn, parent.pawn);
}
if (Props.applyToSelf || Props.onlyApplyToSelf)
{
ApplyInner(parent.pawn, target.Pawn);
}
}
}
protected void ApplyInner(Pawn target, Pawn other)
{
if (target == null)
{
return;
}
if (TryResist(target))
{
MoteMaker.ThrowText(target.DrawPos, target.Map, "Resisted".Translate());
return;
}
// 随机选择一个 hediff
var selectedHediffEntry = SelectRandomHediffEntry(target);
if (selectedHediffEntry == null)
{
// 没有可用的 hediff
if (Props.showNoValidHediffMessage && PawnUtility.ShouldSendNotificationAbout(parent.pawn))
{
Messages.Message("ARA_NoValidHediffAvailable".Translate(), target, MessageTypeDefOf.NeutralEvent);
}
return;
}
var hediffDef = selectedHediffEntry.hediffDef;
// 检查是否允许重复施加这里应该不会执行到因为CanApplyOn已经检查过
if (!Props.allowMultipleHediffs && target.health.hediffSet.HasHediff(hediffDef))
{
if (Props.showAlreadyHasHediffMessage && PawnUtility.ShouldSendNotificationAbout(parent.pawn))
{
Messages.Message("ARA_TargetAlreadyHasHediff".Translate(target.LabelShort, hediffDef.label),
target, MessageTypeDefOf.NeutralEvent);
}
return;
}
// 替换现有 hediff如果配置
if (Props.replaceExisting)
{
Hediff existingHediff = target.health.hediffSet.GetFirstHediffOfDef(hediffDef);
if (existingHediff != null)
{
target.health.RemoveHediff(existingHediff);
}
}
// 创建并应用 hediff
Hediff hediff = HediffMaker.MakeHediff(hediffDef, target, Props.onlyBrain ? target.health.hediffSet.GetBrain() : null);
// 设置持续时间
HediffComp_Disappears disappearsComp = hediff.TryGetComp<HediffComp_Disappears>();
if (disappearsComp != null)
{
disappearsComp.ticksToDisappear = GetDurationSeconds(target).SecondsToTicks();
}
// 设置严重程度
float severity = selectedHediffEntry.severity >= 0f ? selectedHediffEntry.severity : Props.severity;
if (severity >= 0f)
{
hediff.Severity = severity;
}
// 处理链接 hediff
HediffComp_Link linkComp = hediff.TryGetComp<HediffComp_Link>();
if (linkComp != null)
{
linkComp.other = other;
linkComp.drawConnection = target == parent.pawn;
}
target.health.AddHediff(hediff);
// 显示施加的消息
if (Props.showAppliedMessage && PawnUtility.ShouldSendNotificationAbout(parent.pawn))
{
Messages.Message("ARA_HediffApplied".Translate(parent.pawn.LabelShort, hediffDef.label, target.LabelShort),
target, MessageTypeDefOf.PositiveEvent);
}
}
/// <summary>
/// 根据权重和科技要求随机选择一个 hediff
/// </summary>
private HediffEntry SelectRandomHediffEntry(Pawn target)
{
var availableEntries = new List<HediffEntry>();
var availableWeights = new List<float>();
foreach (var entry in Props.hediffEntries)
{
// 检查科技要求
if (entry.requiredResearchProject != null && !entry.requiredResearchProject.IsFinished)
{
continue;
}
// 检查其他条件
if (!CheckHediffConditions(entry, target))
{
continue;
}
// 如果不允许重复施加,检查目标是否已经有这个 hediff
if (!Props.allowMultipleHediffs && target.health.hediffSet.HasHediff(entry.hediffDef))
{
continue;
}
availableEntries.Add(entry);
availableWeights.Add(entry.weight);
}
if (availableEntries.Count == 0)
{
return null;
}
// 使用权重随机选择
return availableEntries.RandomElementByWeight(entry => entry.weight);
}
/// <summary>
/// 获取所有可用的 hediff 条目(用于显示)
/// </summary>
private List<HediffEntry> GetAvailableHediffEntries(Pawn target = null)
{
var availableEntries = new List<HediffEntry>();
foreach (var entry in Props.hediffEntries)
{
// 检查科技要求
if (entry.requiredResearchProject != null && !entry.requiredResearchProject.IsFinished)
{
continue;
}
// 如果有目标,检查目标条件
if (target != null && !CheckHediffConditions(entry, target))
{
continue;
}
// 如果不允许重复施加,检查目标是否已经有这个 hediff
if (target != null && !Props.allowMultipleHediffs && target.health.hediffSet.HasHediff(entry.hediffDef))
{
continue;
}
availableEntries.Add(entry);
}
return availableEntries;
}
/// <summary>
/// 检查目标是否已经有任何列表中的 hediff用于CanApplyOn
/// </summary>
private bool TargetHasAnyListedHediff(Pawn target)
{
if (target == null || Props.allowMultipleHediffs)
return false;
foreach (var entry in Props.hediffEntries)
{
// 检查科技要求
if (entry.requiredResearchProject != null && !entry.requiredResearchProject.IsFinished)
{
continue;
}
// 检查其他条件
if (!CheckHediffConditions(entry, target))
{
continue;
}
// 如果目标已经有这个 hediff返回 true
if (target.health.hediffSet.HasHediff(entry.hediffDef))
{
return true;
}
}
return false;
}
/// <summary>
/// 检查 hediff 的额外条件
/// </summary>
private bool CheckHediffConditions(HediffEntry entry, Pawn target)
{
if (entry.onlyApplyToLiving && (target.Dead || target.Destroyed))
return false;
if (entry.onlyApplyToNonMechanoid && target.RaceProps.IsMechanoid)
return false;
if (entry.onlyApplyToOrganic && !target.RaceProps.IsFlesh)
return false;
return true;
}
/// <summary>
/// 检查目标是否在黑名单中
/// </summary>
private bool IsTargetBlacklisted(Pawn target)
{
if (target == null || Props.blacklistHediffs.NullOrEmpty())
return false;
foreach (var hediffDef in Props.blacklistHediffs)
{
if (target.health.hediffSet.HasHediff(hediffDef))
{
return true;
}
}
return false;
}
protected virtual bool TryResist(Pawn pawn)
{
if (Props.resistChance > 0f)
{
float resistChance = Props.resistChance;
if (pawn != null && pawn.health != null)
{
resistChance *= pawn.GetStatValue(StatDefOf.ToxicResistance);
}
return Rand.Chance(resistChance);
}
return false;
}
public override bool AICanTargetNow(LocalTargetInfo target)
{
if (parent.pawn.Faction == Faction.OfPlayer)
{
return false;
}
if (target.Pawn == null)
return false;
// 检查目标是否在黑名单中
if (IsTargetBlacklisted(target.Pawn))
return false;
// 检查目标是否已经有任何列表中的 hediff
if (TargetHasAnyListedHediff(target.Pawn))
return false;
// 检查是否有至少一个可用的 hediff
return SelectRandomHediffEntry(target.Pawn) != null;
}
public override bool CanApplyOn(LocalTargetInfo target, LocalTargetInfo dest)
{
if (!base.CanApplyOn(target, dest))
return false;
if (target.Pawn == null)
return false;
// 检查目标是否在黑名单中
if (IsTargetBlacklisted(target.Pawn))
return false;
// 检查目标是否已经有任何列表中的 hediff
if (TargetHasAnyListedHediff(target.Pawn))
return false;
// 检查是否有至少一个可用的 hediff
return SelectRandomHediffEntry(target.Pawn) != null;
}
public override string ExtraLabelMouseAttachment(LocalTargetInfo target)
{
StringBuilder sb = new StringBuilder();
if (target.Pawn == null)
{
// 没有具体目标时的显示
sb.AppendLine("ARA_AbilityReady".Translate());
sb.AppendLine();
// 显示所有可能的 hediff不考虑目标限制
var availableEntries = GetAvailableHediffEntries();
if (availableEntries.Any())
{
sb.AppendLine("ARA_PossibleEffects".Translate());
foreach (var entry in availableEntries)
{
sb.AppendLine($" • {entry.hediffDef.label} ({entry.weight:F1})");
}
}
}
else
{
// 检查黑名单
if (IsTargetBlacklisted(target.Pawn))
{
sb.AppendLine("ARA_TargetBlacklisted".Translate());
return sb.ToString().TrimEndNewlines();
}
// 检查目标是否已经有任何列表中的 hediff
if (TargetHasAnyListedHediff(target.Pawn))
{
sb.AppendLine("ARA_TargetAlreadyHasHediff".Translate());
return sb.ToString().TrimEndNewlines();
}
// 有具体目标时的显示
var availableEntries = GetAvailableHediffEntries(target.Pawn);
if (availableEntries.Any())
{
// 显示所有可能的 hediff
var hediffNames = availableEntries.Select(e => e.hediffDef.label).ToArray();
string hediffList = string.Join(", ", hediffNames);
sb.AppendLine("ARA_PotentialHediffs".Translate(hediffList));
// 显示抵抗几率信息
if (Props.resistChance > 0f)
{
float actualResistChance = Props.resistChance * target.Pawn.GetStatValue(StatDefOf.ToxicResistance);
sb.AppendLine("ARA_ResistChance".Translate(actualResistChance.ToStringPercent()));
}
}
else
{
sb.AppendLine("ARA_NoValidHediff".Translate());
}
}
return sb.ToString().TrimEndNewlines();
}
public override void DrawEffectPreview(LocalTargetInfo target)
{
base.DrawEffectPreview(target);
// 可选:在地图上绘制额外的预览效果
if (target.IsValid && target.Pawn != null)
{
// 检查黑名单
if (IsTargetBlacklisted(target.Pawn))
{
// 可以在这里绘制红色轮廓表示目标无效
return;
}
// 检查目标是否已经有任何列表中的 hediff
if (TargetHasAnyListedHediff(target.Pawn))
{
// 可以在这里绘制红色轮廓表示目标无效
return;
}
var selectedEntry = SelectRandomHediffEntry(target.Pawn);
if (selectedEntry != null)
{
// 在目标上方显示预览效果
GenDraw.DrawTargetHighlight(target);
}
}
}
}
public class CompProperties_AbilityRandomHediff : CompProperties_AbilityEffect
{
public List<HediffEntry> hediffEntries;
// 基础属性(从原版继承)
public bool ignoreSelf = true;
public bool onlyApplyToSelf = false;
public bool applyToTarget = true;
public bool applyToSelf = false;
public bool replaceExisting = false;
public bool onlyBrain = false;
public float severity = -1f;
// 新添加的属性
public bool allowMultipleHediffs = false;
public float resistChance = 0f;
public bool showAppliedMessage = true;
public bool showAlreadyHasHediffMessage = true;
public bool showNoValidHediffMessage = true;
// 黑名单功能:拥有这些 hediff 的目标无法成为目标
public List<HediffDef> blacklistHediffs;
public CompProperties_AbilityRandomHediff()
{
compClass = typeof(CompAbilityEffect_RandomHediff);
}
}
public class HediffEntry
{
public HediffDef hediffDef;
public float weight = 1f;
public ResearchProjectDef requiredResearchProject;
public float severity = -1f; // 如果为负值,则使用 CompProperties 中的 severity
// 额外的条件
public bool onlyApplyToLiving = true;
public bool onlyApplyToNonMechanoid = true;
public bool onlyApplyToOrganic = true;
}
}