Removing kidnapped pawns from world pawns

Started by Wanderer_joins, July 20, 2019, 06:39:21 AM

Previous topic - Next topic

Wanderer_joins

Hi,

I've given a try a while ago for a mod to rescue kidnapped pawns (Kidnapped colonist camp).
There is a reported issue with pawns not being correctly removed from world pawns. I've looked into a similar vanilla incident (ransom demand) and couldn't see where the pawns were removed. I concluded they were automatically removed thanks to the KidnappedPawnsTracker:


{
public class KidnappedPawnsTracker : IExposable
{
private Faction faction;

private List<Pawn> kidnappedPawns = new List<Pawn>();

private const int TryRecruitInterval = 15051;

private const float RecruitMTBDays = 30f;

public List<Pawn> KidnappedPawnsListForReading
{
get
{
return this.kidnappedPawns;
}
}

public KidnappedPawnsTracker(Faction faction)
{
this.faction = faction;
}

public void ExposeData()
{
if (Scribe.mode == LoadSaveMode.Saving)
{
this.kidnappedPawns.RemoveAll((Pawn x) => x.Destroyed);
}
Scribe_Collections.Look<Pawn>(ref this.kidnappedPawns, "kidnappedPawns", LookMode.Reference, new object[0]);
}

public void Kidnap(Pawn pawn, Pawn kidnapper)
{
if (this.kidnappedPawns.Contains(pawn))
{
Log.Error("Tried to kidnap already kidnapped pawn " + pawn, false);
return;
}
if (pawn.Faction == this.faction)
{
Log.Error("Tried to kidnap pawn with the same faction: " + pawn, false);
return;
}
pawn.PreKidnapped(kidnapper);
if (pawn.Spawned)
{
pawn.DeSpawn(DestroyMode.Vanish);
}
this.kidnappedPawns.Add(pawn);
if (!Find.WorldPawns.Contains(pawn))
{
Find.WorldPawns.PassToWorld(pawn, PawnDiscardDecideMode.Decide);
if (!Find.WorldPawns.Contains(pawn))
{
Log.Error("WorldPawns discarded kidnapped pawn.", false);
this.kidnappedPawns.Remove(pawn);
}
}
if (pawn.Faction == Faction.OfPlayer)
{
BillUtility.Notify_ColonistUnavailable(pawn);
}
}

public void RemoveKidnappedPawn(Pawn pawn)
{
if (!this.kidnappedPawns.Remove(pawn))
{
Log.Warning("Tried to remove kidnapped pawn " + pawn + " but he's not here.", false);
}
}

public void LogKidnappedPawns()
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine(this.faction.Name + ":");
for (int i = 0; i < this.kidnappedPawns.Count; i++)
{
stringBuilder.AppendLine(this.kidnappedPawns[i].Name.ToStringFull);
}
Log.Message(stringBuilder.ToString(), false);
}

public void KidnappedPawnsTrackerTick()
{
for (int i = this.kidnappedPawns.Count - 1; i >= 0; i--)
{
if (this.kidnappedPawns[i].DestroyedOrNull())
{
this.kidnappedPawns.RemoveAt(i);
}
}
if (Find.TickManager.TicksGame % 15051 == 0)
{
for (int j = this.kidnappedPawns.Count - 1; j >= 0; j--)
{
if (Rand.MTBEventOccurs(30f, 60000f, 15051f))
{
this.kidnappedPawns[j].SetFaction(this.faction, null);
this.kidnappedPawns.RemoveAt(j);
}
}
}
}
}
}


But i may have misinterpreted the code. Does anyone have an idea how i could check for kidnapped pawns and remove spawned pawns from the list?

Thank you,

Edit: i'm narrowing down the issue and thinks the magic happens here in vanilla. Unfortunately, I can't see what exactly the code is for this letter and have to use a work around to fix the issue:

public class ChoiceLetter_RansomDemand : ChoiceLetter
{
public Map map;

public Faction faction;

public Pawn kidnapped;

public int fee;

public override IEnumerable<DiaOption> Choices
{
get
{
ChoiceLetter_RansomDemand.<>c__Iterator0 <>c__Iterator = new ChoiceLetter_RansomDemand.<>c__Iterator0();
<>c__Iterator.$this = this;
ChoiceLetter_RansomDemand.<>c__Iterator0 expr_0E = <>c__Iterator;
expr_0E.$PC = -2;
return expr_0E;
}
}