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(); 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(); 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); } } /// /// 根据权重和科技要求随机选择一个 hediff /// private HediffEntry SelectRandomHediffEntry(Pawn target) { var availableEntries = new List(); var availableWeights = new List(); 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); } /// /// 获取所有可用的 hediff 条目(用于显示) /// private List GetAvailableHediffEntries(Pawn target = null) { var availableEntries = new List(); 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; } /// /// 检查目标是否已经有任何列表中的 hediff(用于CanApplyOn) /// 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; } /// /// 检查 hediff 的额外条件 /// 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; } /// /// 检查目标是否在黑名单中 /// 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 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 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; } }