Files
ArachnaeSwarm/Source/ArachnaeSwarm/Possession/PawnDataUtility.cs
2025-09-04 23:02:54 +08:00

161 lines
6.9 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 System.Collections.Generic;
using System.Linq;
using RimWorld;
using Verse;
namespace ArachnaeSwarm
{
public static class PawnDataUtility
{
public static void TransferSoul(Pawn soulSource, Pawn bodyTarget)
{
if (soulSource == null || bodyTarget == null)
{
Log.Error("Cannot transfer soul: source or target is null.");
return;
}
Log.Message($"Beginning soul transfer from {soulSource.LabelShort} to {bodyTarget.LabelShort}.");
// --- 1. Core Identity ---
bodyTarget.Name = soulSource.Name;
bodyTarget.story.Childhood = soulSource.story.Childhood;
bodyTarget.story.Adulthood = soulSource.story.Adulthood;
if (bodyTarget.story.traits != null) bodyTarget.story.traits.allTraits.Clear();
if (soulSource.story.traits != null)
{
foreach (Trait trait in soulSource.story.traits.allTraits)
{
bodyTarget.story.traits.GainTrait(trait);
}
}
if (bodyTarget.Faction != soulSource.Faction)
{
bodyTarget.SetFaction(soulSource.Faction, soulSource);
}
// --- 2. Growth & Experience ---
if (bodyTarget.skills != null) bodyTarget.skills.skills.Clear();
if (soulSource.skills != null)
{
foreach (SkillRecord skill in soulSource.skills.skills)
{
SkillRecord newSkill = new SkillRecord(bodyTarget, skill.def)
{
levelInt = skill.levelInt,
xpSinceLastLevel = skill.xpSinceLastLevel,
passion = skill.passion
};
bodyTarget.skills.skills.Add(newSkill);
}
}
if (bodyTarget.records != null && soulSource.records != null)
{
foreach (RecordDef recordDef in DefDatabase<RecordDef>.AllDefs)
{
// 根据您的指示,我们不再处理时间类型的记录,以避免警告
if (recordDef.type == RecordType.Time)
{
continue;
}
float sourceValue = soulSource.records.GetValue(recordDef);
bodyTarget.records.AddTo(recordDef, sourceValue - bodyTarget.records.GetValue(recordDef));
}
}
// --- 3. Mind & Settings ---
if (bodyTarget.needs?.mood?.thoughts?.memories != null)
{
bodyTarget.needs.mood.thoughts.memories.Memories.Clear();
}
if (soulSource.needs?.mood?.thoughts?.memories != null)
{
foreach (Thought_Memory memory in soulSource.needs.mood.thoughts.memories.Memories)
{
bodyTarget.needs.mood.thoughts.memories.TryGainMemory(memory);
}
}
if (soulSource.workSettings != null && bodyTarget.workSettings != null)
{
bodyTarget.workSettings.EnableAndInitialize();
foreach (WorkTypeDef workDef in DefDatabase<WorkTypeDef>.AllDefs)
{
// 在设置优先级之前检查目标Pawn是否禁用了该工作类型
if (!bodyTarget.WorkTypeIsDisabled(workDef))
{
bodyTarget.workSettings.SetPriority(workDef, soulSource.workSettings.GetPriority(workDef));
}
}
}
if (soulSource.timetable != null && bodyTarget.timetable != null)
{
bodyTarget.timetable.times = new List<TimeAssignmentDef>(soulSource.timetable.times);
}
if (soulSource.playerSettings != null && bodyTarget.playerSettings != null)
{
bodyTarget.playerSettings.hostilityResponse = soulSource.playerSettings.hostilityResponse;
bodyTarget.playerSettings.medCare = soulSource.playerSettings.medCare;
bodyTarget.playerSettings.selfTend = soulSource.playerSettings.selfTend;
}
if (soulSource.outfits != null && bodyTarget.outfits != null) bodyTarget.outfits.CurrentApparelPolicy = soulSource.outfits.CurrentApparelPolicy;
if (soulSource.drugs != null && bodyTarget.drugs != null) bodyTarget.drugs.CurrentPolicy = soulSource.drugs.CurrentPolicy;
if (soulSource.foodRestriction != null && bodyTarget.foodRestriction != null) bodyTarget.foodRestriction.CurrentFoodPolicy = soulSource.foodRestriction.CurrentFoodPolicy;
// Ownership is claimed on the Building, not the pawn. We can't directly transfer this.
// if (soulSource.ownership != null && bodyTarget.ownership != null)
// {
// // This requires finding the bed and calling bed.SetOwner(pawn)
// }
// --- 4. DLC & Social ---
if (ModsConfig.IdeologyActive && soulSource.ideo != null && bodyTarget.ideo != null)
{
bodyTarget.ideo.SetIdeo(soulSource.ideo.Ideo);
// Can't set certainty directly, but setting the ideo resets it.
}
if (ModsConfig.RoyaltyActive && soulSource.royalty != null && bodyTarget.royalty != null)
{
// Clear existing royalty status from the target body
bodyTarget.royalty.AllTitlesForReading.Clear();
// Transfer titles
foreach(var title in soulSource.royalty.AllTitlesForReading)
{
bodyTarget.royalty.SetTitle(title.faction, title.def, true, false, false);
}
// Transfer permits
if(soulSource.royalty.AllFactionPermits != null)
{
foreach (var permit in soulSource.royalty.AllFactionPermits)
{
bodyTarget.royalty.AddPermit(permit.Permit, permit.Faction);
}
}
// Abilities are handled by the titles and should update automatically.
bodyTarget.royalty.UpdateAvailableAbilities();
}
if (soulSource.relations != null && bodyTarget.relations != null)
{
bodyTarget.relations.ClearAllRelations();
foreach (DirectPawnRelation relation in soulSource.relations.DirectRelations.Where(r => !r.def.familyByBloodRelation).ToList())
{
bodyTarget.relations.AddDirectRelation(relation.def, relation.otherPawn);
}
}
// --- 5. Finalization ---
bodyTarget.Drawer.renderer.SetAllGraphicsDirty();
Log.Message("Soul transfer complete.");
}
}
}