整理
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
using RimWorld;
|
||||
using RimWorld.Planet;
|
||||
using Verse;
|
||||
using UnityEngine;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ArachnaeSwarm
|
||||
{
|
||||
public class CompAbilityEffect_Possess : CompAbilityEffect, ICompAbilityEffectOnJumpCompleted
|
||||
{
|
||||
public new CompProperties_AbilityPossess Props => (CompProperties_AbilityPossess)props;
|
||||
|
||||
public override bool Valid(LocalTargetInfo target, bool throwMessages = false)
|
||||
{
|
||||
Pawn targetPawn = target.Pawn;
|
||||
if (targetPawn == null) return false;
|
||||
|
||||
if (!targetPawn.RaceProps.Humanlike)
|
||||
{
|
||||
if (throwMessages) Messages.Message("ARA_MustBeHumanlike".Translate(), targetPawn, MessageTypeDefOf.RejectInput, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (targetPawn.health.hediffSet.HasHediff(HediffDef.Named("ARA_Possession")))
|
||||
{
|
||||
if (throwMessages) Messages.Message("ARA_AlreadyPossessed".Translate(targetPawn.LabelShort), targetPawn, MessageTypeDefOf.RejectInput, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Props.raceBlacklist.Contains(targetPawn.def))
|
||||
{
|
||||
if (throwMessages) Messages.Message("ARA_CannotPossessRace".Translate(targetPawn.def.label), targetPawn, MessageTypeDefOf.RejectInput, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.Valid(target, throwMessages);
|
||||
}
|
||||
|
||||
public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
|
||||
{
|
||||
base.Apply(target, dest);
|
||||
DoPossession(this.parent.pawn, target.Pawn);
|
||||
}
|
||||
|
||||
private void DoPossession(Pawn caster, Pawn targetPawn)
|
||||
{
|
||||
if (targetPawn == null || caster == null) return;
|
||||
|
||||
Log.Message($"[夺舍] 开始执行。施法者: {caster.LabelShort}, 目标: {targetPawn.LabelShort}");
|
||||
|
||||
// 1. 捕获原宿主的完整数据,用于死亡后恢复尸体
|
||||
OriginalPawnData originalHostData = new OriginalPawnData();
|
||||
originalHostData.CaptureData(targetPawn);
|
||||
Log.Message($"[夺舍] 已捕获原始宿主 {targetPawn.LabelShort} 的完整数据。");
|
||||
|
||||
// 2. 备份原宿主的技能,用于后续合并
|
||||
var originalTargetSkills = new Dictionary<SkillDef, (int level, Passion passion)>();
|
||||
if (targetPawn.skills != null)
|
||||
{
|
||||
foreach (var skill in targetPawn.skills.skills)
|
||||
{
|
||||
originalTargetSkills[skill.def] = (skill.levelInt, skill.passion);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 准备抱脸虫和Hediff
|
||||
Pawn originalCaster = PawnGenerator.GeneratePawn(caster.kindDef, caster.Faction);
|
||||
PawnDataUtility.TransferSoul(caster, originalCaster); // 确保克隆体有完全一致的数据
|
||||
Hediff_Possession hediff = (Hediff_Possession)HediffMaker.MakeHediff(HediffDef.Named("ARA_Possession"), targetPawn);
|
||||
hediff.originalHostData = originalHostData; // 将宿主数据存入Hediff
|
||||
|
||||
// 4. 将抱脸虫存入Hediff
|
||||
if (hediff.casterContainer.TryAdd(originalCaster, true))
|
||||
{
|
||||
Log.Message($"[夺舍] 成功将 {caster.LabelShort} 的原始副本存入Hediff。");
|
||||
|
||||
// 5. 灵魂转移,此时 targetPawn 的技能被 caster 的技能覆盖
|
||||
PawnDataUtility.TransferSoul(caster, targetPawn);
|
||||
|
||||
// 夺舍成功后,原始的抱脸虫应该消失
|
||||
if (!caster.Destroyed)
|
||||
{
|
||||
caster.Destroy(DestroyMode.Vanish);
|
||||
}
|
||||
|
||||
// 6. 技能合并:在灵魂转移后,直接在最终的身体 (targetPawn) 上进行合并
|
||||
if (targetPawn.skills != null)
|
||||
{
|
||||
Log.Message("[夺舍] 开始合并技能...");
|
||||
foreach (var skillRecord in targetPawn.skills.skills)
|
||||
{
|
||||
if (originalTargetSkills.TryGetValue(skillRecord.def, out var originalSkill))
|
||||
{
|
||||
// 比较等级
|
||||
if (originalSkill.level > skillRecord.levelInt)
|
||||
{
|
||||
skillRecord.levelInt = originalSkill.level;
|
||||
}
|
||||
// 比较热情
|
||||
if (originalSkill.passion > skillRecord.passion)
|
||||
{
|
||||
skillRecord.passion = originalSkill.passion;
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.Message("[夺舍] 技能合并完成。");
|
||||
}
|
||||
|
||||
// 7. 将Hediff添加到最终身体上
|
||||
targetPawn.health.AddHediff(hediff);
|
||||
|
||||
if (Props.hediffToApplyOnSuccess != null)
|
||||
{
|
||||
targetPawn.health.AddHediff(Props.hediffToApplyOnSuccess, null, null);
|
||||
Log.Message($"[夺舍] 成功为 {targetPawn.LabelShort} 添加额外Hediff: {Props.hediffToApplyOnSuccess.defName}");
|
||||
}
|
||||
Log.Message($"[夺舍] {targetPawn.LabelShort} (原 {caster.LabelShort}) 夺舍完成。");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error($"[夺舍] 无法将 {caster.LabelShort} 的副本存入Hediff。中止操作。");
|
||||
if(originalCaster != null && !originalCaster.Destroyed) originalCaster.Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnJumpCompleted(IntVec3 JUMPINPOS_UNUSED, LocalTargetInfo landingTarget)
|
||||
{
|
||||
Pawn caster = this.parent.pawn;
|
||||
if (caster == null || !(landingTarget.Thing is Pawn targetPawn)) return;
|
||||
|
||||
Verb bestMeleeVerb = caster.meleeVerbs.TryGetMeleeVerb(targetPawn);
|
||||
if (bestMeleeVerb == null)
|
||||
{
|
||||
Log.Warning($"[Possess] Caster {caster.LabelShort} has no melee verb.");
|
||||
return;
|
||||
}
|
||||
|
||||
float damageAmount = bestMeleeVerb.verbProps.AdjustedMeleeDamageAmount(bestMeleeVerb, caster);
|
||||
float armorPenetration = bestMeleeVerb.verbProps.AdjustedArmorPenetration(bestMeleeVerb, caster);
|
||||
DamageDef damageDef = bestMeleeVerb.verbProps.meleeDamageDef;
|
||||
|
||||
var dinfo = new DamageInfo(damageDef, damageAmount, armorPenetration, -1, caster);
|
||||
DamageWorker.DamageResult damageResult = targetPawn.TakeDamage(dinfo);
|
||||
Log.Message($"[Possess] Dealt {damageResult.totalDamageDealt} damage to {targetPawn.LabelShort} using {damageDef.defName}.");
|
||||
|
||||
if (damageResult.totalDamageDealt > 0)
|
||||
{
|
||||
float baseChance = Props.successChance.RandomInRange;
|
||||
float bonusFromDamage = damageResult.totalDamageDealt * Props.successChanceBonusPerDamage;
|
||||
float finalChance = Mathf.Clamp01(baseChance + bonusFromDamage);
|
||||
Log.Message($"[Possess] Base chance: {baseChance}, Bonus: {bonusFromDamage}, Final chance: {finalChance}");
|
||||
|
||||
if (Rand.Chance(finalChance))
|
||||
{
|
||||
Log.Message($"[Possess] Success! Applying possession effect.");
|
||||
DoPossession(caster, targetPawn);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Message($"[Possess] Failed possession check.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user