A weird error when I try to select a random pawn

Started by battlemage64, December 20, 2017, 09:19:10 PM

Previous topic - Next topic

battlemage64

I'm trying to write a function that selects a random pawn. Here's the error:

RimWorld 0.18.1722 rev1206
Verse.Log:Message(String)
RimWorld.VersionControl:LogVersionNumber()
Verse.Root:CheckGlobalInit()
Verse.Root:Start()
Verse.Root_Entry:Start()

Loading game from file WoMDs Test with mods Core and People Can Change
Verse.Log:Message(String)
Verse.SavedGameLoader:LoadGameFromSaveFile(String)
Verse.Root_Play:<Start>m__0()
Verse.LongEventHandler:RunEventFromAnotherThread(Action)
Verse.LongEventHandler:<UpdateCurrentAsynchronousEvent>m__1()

Exception filling window for Verse.Dialog_DebugOptionListLister: System.TypeLoadException: Could not load type 'System.Collections.Generic.List`1' from assembly 'System.Collections, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
  at PCC_Code.Worker_BecomeBloodlust.TryExecuteWorker (RimWorld.IncidentParms parms) [0x00000] in <filename unknown>:0
  at RimWorld.IncidentWorker.TryExecute (RimWorld.IncidentParms parms) [0x00000] in <filename unknown>:0
  at Verse.Dialog_DebugActionsMenu+<DoExecuteIncidentDebugAction>c__AnonStorey48+<DoExecuteIncidentDebugAction>c__AnonStorey49.<>m__0 () [0x00000] in <filename unknown>:0
  at Verse.Dialog_DebugOptionLister.DebugAction (System.String label, System.Action action) [0x00000] in <filename unknown>:0
  at Verse.Dialog_DebugOptionListLister.DoListingItems () [0x00000] in <filename unknown>:0
  at Verse.Dialog_OptionLister.DoWindowContents (Rect inRect) [0x00000] in <filename unknown>:0
  at Verse.Window+<WindowOnGUI>c__AnonStorey0.<>m__0 (Int32 x) [0x00000] in <filename unknown>:0
Verse.Log:Error(String)
Verse.<WindowOnGUI>c__AnonStorey0:<>m__0(Int32)
UnityEngine.GUI:CallWindowDelegate(WindowFunction, Int32, Int32, GUISkin, Int32, Single, Single, GUIStyle)

Here's the function (with the using statements because it seems to have something to do with that):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Verse;
using Verse.AI;
using Verse.Sound;
using RimWorld;

private Pawn GetRandPawn(IIncidentTarget target)
        {
            Map map = target as Map;
            if (map != null) {
                List<Pawn> listofpawns = map.mapPawns.AllPawnsSpawned;
                IntRange pawnlistindices = new IntRange(0, listofpawns.Count - 1);
                int pawnnum = pawnlistindices.RandomInRange;
                return listofpawns[pawnnum];
            }
            return null;
        }

I have no idea what the error means, but if anyone has a fix or a better method of selecting a random pawn, please help.
I love to mod and boy am I bad at it

BrokenValkyrie

It looks like the code selects all pawn, not just human. Judging by the error it looks like its trying to invoke blood lust on a non human pawn. Are you able to use AllPawnsSpawnedCount to confirm if it list all pawn not just human?

Jaxxa

This might help, I meant to find this for your last post, but hadn't got around to posting it yet.

I think this should give you all the Pawns of the players faction.
IEnumerable<Pawn> pawns = map.mapPawns.PawnsInFaction(Faction.OfPlayer);

I dont know if that will include owned animals or just colonists.

Then you will want to get a random value like you are already doing out of that enumeration.

battlemage64

BrokenValkyrie: Thanks, that seems likely to be the problem.

Jaxxa: Thanks, I'll use that as my new system since the old one is selecting animals.
I love to mod and boy am I bad at it

battlemage64

I tried many, many different ways of sorting out animals from colonists and I don't think that's the problem. The error says that it's not loading the "list" type; is there some reason that it couldn't load/create a list? It says TypeLoadException so it seems like it can't create a list<pawn>. Any reason why it couldn't?

Again, if anyone has a better way to select colonists (one that actually WORKS), I would love to hear it.
I love to mod and boy am I bad at it

Jaxxa

The code that I put up might be returning a IEnumerable.

Try adding .ToList() after it.

It might be helpful if you put your code on GitHub so we can see the context of what you are trying.

battlemage64

I don't know what GitHub is, so that'll have to wait.

Using the line List<Pawn> allpawns = map.mapPawns.SpawnedPawnsInFaction(Faction.OfPlayer).ToList(); didn't make a difference. I get the same error, and I have no idea still what it means. Here's my C# code in full if you want to look:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using Verse;
using Verse.AI;
using Verse.Sound;
using RimWorld;

namespace PCC_Code
{
   
    public class Worker_BecomeBloodlust : IncidentWorker // eventually will become Worker_ChangeTrait, hopefully
    {
        protected override bool TryExecuteWorker(IncidentParms parms)
        {
            Debug.Log("Changing trait...");
            Pawn pawntochange = this.GetRandPawn(parms.target);
            if (pawntochange == null) {
                return true;
            }
            SetTrait(pawntochange, "bloodlust");
            return true;
        }
        private Pawn GetRandPawn(IIncidentTarget target)
        {
            Debug.Log("Finding target...");
            Map map = target as Map;
            if (map != null) {
                Debug.Log("Got map");
                List<Pawn> allpawns = map.mapPawns.SpawnedPawnsInFaction(Faction.OfPlayer).ToList();
                Debug.Log("Got allpawns");
                List<Pawn> listofpawns = new List<Pawn>();
                Debug.Log("Created listofpawns");
                foreach (Pawn pawn in allpawns) {
                    if (pawn.IsColonist && !pawn.NonHumanlikeOrWildMan()) {
                        listofpawns.Add(pawn);
                        Debug.Log("Added colonist:");
                        Debug.Log(pawn.Name);
                    }
                }
                Debug.Log("Colonists sorted!");
                IntRange pawnlistindices = new IntRange(0, listofpawns.Count - 1);
                Debug.Log("Got pawnlistindices");
                int pawnnum = pawnlistindices.RandomInRange;
                Debug.Log("Got pawnnum");
                return listofpawns[pawnnum];
            }
            return null;
        }
        private int SetTrait(Pawn pawn, string trait) // string not a TraitDefOf because TDO is static and statics can't be parameters :(
        {
            TraitDef traitdeftouse = TraitDefOf.Bloodlust;
            if (trait == "bloodlust") {
                traitdeftouse = TraitDefOf.Bloodlust;
            }
            pawn.story.traits.GainTrait(new Trait(traitdeftouse));
            return 0;
        }
    }
}
I love to mod and boy am I bad at it

battlemage64

Okay, I've done extremely extensive testing (well, pretty intensive) and the problem is definitely with the one line you gave me. I can get map.mapPawns perfectly fine, and everything after that line works, but no matter what I try to load from map.mapPawns, I get the error, whether it's an IEnumerable<Pawn> or a List<Pawn>. It seems like when I get map.mapPawns, it's supposed to have some data in it but it doesn't. Also, when I comment out all of GetRandPawn, it works fine but doesn't actually log any of my Debug.Log() calls.
I love to mod and boy am I bad at it