Ludeon Forums

RimWorld => Mods => Help => Topic started by: battlemage64 on January 01, 2018, 10:26:47 AM

Title: How do I have an incident select a random pawn target?
Post by: battlemage64 on January 01, 2018, 10:26:47 AM
How do I have an incident target a specific random pawn like mental breaks, disease or self-tame do? I saw a system that looked promising from the code for disease where it uses (IIncidentTarget as Map).mapPawns.FreeColonistsAndPrisoners, but this doesn't work for me (at all, I couldn't get anything with Map.mapPawns to work). Is there built-in code for this, or can anyone tell me how to get a random pawn?
Title: Re: How do I have an incident select a random pawn target?
Post by: BrokenValkyrie on January 01, 2018, 11:27:09 AM
It would be useful to know how your code doesn't work. Did the incident fire but no colonist were selected? Was there any error? Regardless I thinks its best if you post your incidentWorker code.

It looks like you are on the right track otherwise.
Title: Re: How do I have an incident select a random pawn target?
Post by: battlemage64 on January 01, 2018, 03:05:17 PM
I discussed why my current code isn't working and posted my code here:

https://ludeon.com/forums/index.php?topic=37788.0

As for firing, whenever I try to get a list of colonists somewhere in my code, it gives an error when I trigger it through dev mode. When I remove/comment that one line, it works fine (but of course nothing happens because the incident has no target). There is an error that claims it can't load a type (either List<Pawn> or IEnumerable<Pawn>) from assembly System.Collections. The same code is used for disease incidents, I checked the source code. Even so, nothing I try has worked.
Title: Re: How do I have an incident select a random pawn target?
Post by: BrokenValkyrie on January 02, 2018, 03:22:49 AM
Are you able to upload the source code/project file minus assembly files. I can try take a crack at the problem.
Title: Re: How do I have an incident select a random pawn target?
Post by: battlemage64 on January 02, 2018, 07:18:56 PM
Okay, here's my mod files. They're attached to this post as a .zip. Good luck and thanks!

[attachment deleted by admin: too old]
Title: Re: How do I have an incident select a random pawn target?
Post by: BrokenValkyrie on January 03, 2018, 11:28:54 PM
I had to create a new project to compile it. There nothing wrong with the code, it worked without issue. I think the issue is environmental which we didn't consider. What IDE are you using to develop the code? Are you using .NET 3.5?

I am providing compiled assembly and source code in the attachment. I'm currently using xamarin studio and will be providing source code in that IDE format, but I think other IDE are able to open it.

I added in game message that tells you who has the trait change and added check against pawn with duplicate blood lust.

There is a couple of log warning checks I've added, most of them can be commented out until needed.


using System.Collections.Generic;
using Verse;
using RimWorld;
using System;

namespace PCC_Code
{

public class Worker_BecomeBloodlust : IncidentWorker
{
protected override bool TryExecuteWorker(IncidentParms parms)
{
Pawn pawntochange = this.GetRandPawn(parms.target);
if (pawntochange == null)
{
Log.Warning("Can't get pawn to change");
return true;
}
this.SetTrait(pawntochange, "bloodlust");
return true;
}
private Pawn GetRandPawn(IIncidentTarget target)
{
Map map = target as Map;
if (map != null)
{
IEnumerable<Pawn> allpawns = map.mapPawns.FreeColonistsAndPrisoners;
List<Pawn> listofpawns = new List<Pawn>();


if (allpawns == null)
{
Log.Warning("Cannot fire incident, could not get list of pawn.");
return null;
}

foreach (Pawn pawn in allpawns)
{
if (pawn.IsColonist && !pawn.NonHumanlikeOrWildMan())
{
if (!pawn.story.traits.HasTrait(TraitDefOf.Bloodlust))
{
listofpawns.Add(pawn);
}
//Debug message, comment this out.
else
{
Log.Warning("Colonist already have blood lust.");
}


}
}
IntRange pawnlistindices = new IntRange(0, listofpawns.Count - 1);
int pawnnum = pawnlistindices.RandomInRange;
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));

String bloodLustGain = pawn.Name + " has gained blood lust.";
Messages.Message(bloodLustGain, MessageTypeDefOf.NeutralEvent);
return 0;
}
}
}


[attachment deleted by admin: too old]
Title: Re: How do I have an incident select a random pawn target?
Post by: battlemage64 on January 04, 2018, 08:40:05 AM
I use Visual Studio for Mac (basically a port of Xamarin).

Your code worked perfectly, despite using the same line that keeps giving an error for me. In fact, no matter what I try I can't get your code to not work. I checked the settings and found that I'm set to .NET 2.0 and the dropdown is grayed out for me, whereas your project can be any version. I'm pretty sure that's the problem, but I don't know how to change it to 3.5. Why would the project be forced to be 2.0? is my project the wrong type? I chose Class Library C# when I created the project. Is that wrong? Your project's settings panel looks totally different from mine, but I don't know how to get mine to look like yours. Attached are screenshots of each of our Project Options > Build > General windows.

[attachment deleted by admin: too old]
Title: Re: How do I have an incident select a random pawn target?
Post by: battlemage64 on January 04, 2018, 08:55:02 AM
Never mind! The problem was that I used Class Library not Library when I made the project. I fixed that and the mod works perfectly fine now! Thank you so much for helping! You're amazing!
Title: Re: How do I have an incident select a random pawn target?
Post by: BrokenValkyrie on January 04, 2018, 10:10:16 AM
I'm glad you got it all sort out.