Editing individual pawns rather than all pawns of that type.

Started by Shivo, January 05, 2017, 10:36:24 AM

Previous topic - Next topic

Shivo

Hello! I have been messing around with rimworld modding for the past couple of days, writing small mods to make sure I understand how events/buildings/pawns/etc work. When I was messing around with the incidents, I tried to make it so that one animal got extremely hungry for meat for a few days, making him eat the other animals around him.

I did the following (using the manhunter single incident as a kind of guide) :

    internal class IncidentWorker_SavageAnimal : IncidentWorker
    {
        public override bool TryExecute(IncidentParms parms)
        {
            Map map = (Map)parms.target;
            int maxPoints = 150;
            List<Pawn> list = (from p in map.mapPawns.AllPawnsSpawned
                               where p.RaceProps.Animal && p.kindDef.combatPower >= (float)maxPoints && IncidentWorker_AnimalInsanityMass.AnimalUsable(p)
                               select p).ToList<Pawn>();
            if(list.Count == 0)
            {
                return false;
            }
            Pawn pawn = list.RandomElement<Pawn>();
            pawn.RaceProps.baseHungerRate = (float)10.0;
            pawn.RaceProps.wildness = (float).99;
            pawn.RaceProps.predator = true;
            pawn.RaceProps.foodType = FoodTypeFlags.CarnivoreAnimalStrict;
            pawn.RaceProps.manhunterOnDamageChance = 1;
            pawn.RaceProps.manhunterOnTameFailChance = 1;
            pawn.RaceProps.baseBodySize = 1;
            pawn.needs.food.CurLevelPercentage = (float).20;
            pawn.needs.rest.CurLevelPercentage = 20;

            string text = pawn.Label.CapitalizeFirst() + " has gained an insatiable taste for meat. Be careful or it may eat all of the animals in the area.";
            Find.LetterStack.ReceiveLetter("Animal Bloodlust", text, LetterType.BadUrgent, pawn, null);
            return true;
    }
}


So this worked great. An animal at random would start eating other animals immediately and would continue until killed.

Now my issue: This didn't just change the one pawn (like I thought it would), this changed ALL pawns of that type. So if it hit a turkey, all turkeys become carnivores and extra hungry. And I believe that it changes them forever on that save. So even new turkeys would have those traits.

My question: How do I just choose to affect just a single animal pawn for a limited amount of time?

Thanks in advance!

RawCode

public RaceProperties RaceProps
{
get
{
return this.def.race;
}
}

reason, why your modification affect entire def and not specific pawn.

well, there are two types of data, pointer\reference and value.

if we have 100 objects of same type, instead of embedding copy of type definition into each object, we pass reference to prototype and store prototype in predefined place.
if you change prototype, all objects will change, they hold reference to data, not data itself.

if you change reference, but only for specific object, only that object will change.

in short - you will need "man eating" version of each animal predefined or generated at runtime.
after that, you change "type" of specific pawn to proper "maneating" (dog to man_eating_dog, and not dog to man_eating_monkey)

it's possible to implement "custom" pawns by hooking each method, that expose type information and return information based off current instance, still, you will need to trick every method in chain to accept custom data instead of trying to read actual def from database.

Shivo

Ah, that makes sense. I figured that something like that was the issue.

So on runtime, I would need to programmatically create new defs of the man-eating version of all of the animals?

Thanks for the help!