So, I'm working on a mod (http://ludeon.com/forums/index.php?topic=3794.0) which involves making the age of colonists increase over time. At the moment, I have it working by way of custom Job Packages... but I noticed the code isn't running when the colonists are in states of not performing jobs (i.e. sleeping). Is there a better port of entry for custom classes that would be on a more global scope?
I use the Tick() method for age that's the simplest way for me.
namespace TestTubeBabies
{
public class JobGiver_Aging : ThinkNode_JobGiver
{
private bool Aged;
protected override Job TryGiveTerminalJob(Pawn pawn)
{
Aging();
return null;
}
private void Aging()
{
if (Aged == false)
{
if (GenTime.HourInt == 12)
{
List<Pawn> list = (
from p in Find.ListerPawns.FreeColonists
select p).ToList<Pawn>();
foreach (Pawn pawn in list)
{
int randomDeath = UnityEngine.Random.Range(75, 95);
pawn.age = pawn.age + 1;
if (pawn.age >= randomDeath)
{
pawn.health = -1;
}
else if (pawn.age >= 70)
{
pawn.story.hairColor = Color.Lerp(pawn.story.hairColor, Color.white, 1);
pawn.def.race.walkSpeed = 0.25f;
}
else if (pawn.age >= 60)
{
pawn.story.hairColor = Color.Lerp(pawn.story.hairColor, Color.grey, 1);
pawn.def.race.walkSpeed = 0.5f;
}
else if (pawn.age >= 50)
{
pawn.def.race.walkSpeed = 0.75f;
}
}
Aged = true;
}
}
if (GenTime.HourInt == 13)
{
Aged = false;
}
}
}
}
^ I'm trying to find a place for that Aging() method outside of the AI code, so it'll be running in the background no matter what's going on in the game. The problem is the only defs I see that list a class are the ThinkTrees and the MapGenerator... both of which are only called during certain times. Is it possible to just list a class in something like the grass, which will probably always be running in the background?
Edit: Or is there anything in the game that can't be destroyed, which could just sit and process code in the background? Something I could instantiate a class for?
Hmm its only my theory, but Door key is a equipment that dont take a slot if i did understand it correctly, or atleast not any visible slot. So you could just make a kinda equipment that is given to colonist if he is/becomes ofcolony, and put most of aging code there based on ticker. Not sure if it would be shown in game, but if it would having a item named smelly socks wouldnt give out :D
Quote from: mrofa on August 08, 2014, 01:39:40 PM
Hmm its only my theory, but Door key is a equipment that dont take a slot if i did understand it correctly, or atleast not any visible slot. So you could just make a kinda equipment that is given to colonist if he is/becomes ofcolony, and put most of aging code there based on ticker. Not sure if it would be shown in game, but if it would having a item named smelly socks wouldnt give out :D
That's actually a good thought, especially since each colonist should have their own instance of it. I would have thought to make an object like a record computer or something, with insanely high health to keep track of everyone's things but the door key is A.) Instantiated as soon as a colonist arrives and B.) each colonist carries an their own instance so key age = colonist age. (that is until they die and the key keeps getting older while they're already dead).
You dont need to use healt for the object in the first place, even in xml you can set to UseStandartHealth to false making objects have no health.
Delivering it to pawns its not a problem, in worst case scenario he can just add it to them in xml.
And if pawn dies object can destroy itself easily simple in case of equipent class:
If (owner.IsDead || owner.IsCorpse || owner.IsSquieerl)
{
this.Destroy();
}
the test tube baby should be a building that has a tick() method and thats where you put that Aging() method when age = 0 then the building is either destroyed or emptied then a pawn will spawn. then make a custom pawn class for the child and use the tick() method to put that aging() method again. :)
Embedding the code in the Door Key of each colonist sounds like a pretty viable option... so I gave it a shot, and here's what I have so far (see attachment). I have the ThingDef for the key setup and each colonist is starting with the new modified key, which is using a class inherited from the core Door Key:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RimWorld;
using Verse;
using UnityEngine;
namespace TestTubeBabies
{
public class DoorKey : ThingWithComponents
{
private bool Aged;
private void Aging()
{
Log.Message("test");
if (Aged == false)
{
if (GenTime.HourInt == 0)
{
List<Pawn> list = (
from p in Find.ListerPawns.FreeColonists
select p).ToList<Pawn>();
foreach (Pawn pawn2 in list)
{
if (pawn2.inventory.container.Contains(this))
{
int randomDeath = UnityEngine.Random.Range(75, 95);
pawn2.age = pawn2.age + 1;
if (pawn2.age >= randomDeath)
{
pawn2.health = -1;
}
else if (pawn2.age >= 70)
{
pawn2.story.hairColor = Color.Lerp(pawn2.story.hairColor, Color.white, 1);
pawn2.def.race.walkSpeed = 0.25f;
}
else if (pawn2.age >= 60)
{
pawn2.story.hairColor = Color.Lerp(pawn2.story.hairColor, Color.grey, 1);
pawn2.def.race.walkSpeed = 0.5f;
}
else if (pawn2.age >= 50)
{
pawn2.def.race.walkSpeed = 0.75f;
}
}
}
Aged = true;
}
}
if (GenTime.HourInt == 1)
{
Aged = false;
}
}
}
}
I put a 'Log.Message("test")' just inside the method to make sure it's running... but alas, I'm never seeing "test" show up in the log in-game. I also tried overriding the Tick() method from the ThingWithComponents class and had a Log of "test" just within that, but still got nothing. Any clues as to what I'm doing wrong, or should be doing?
[attachment deleted by admin: too old]
I had the same issues with adding thoughts to apparel.
It seems that as soon as the equipment is 'equipped' it won't do anymore ticks..
Quote from: Haplo on August 09, 2014, 11:17:37 AM
It seems that as soon as the equipment is 'equipped' it won't do anymore ticks..
It certainly does seem that way. Did you ever find a workaround?
Well again this is my theory but i did see while making a weapon something named VerbTick, didnt test it thrugh so not sure if it will work like a ticker. Another workaround might to make your own ticker based on game time.
Quote from: Argain on August 09, 2014, 11:29:58 AM
...
It certainly does seem that way. Did you ever find a workaround?
Nope, I've left it for now. I've searched a bit around, but didn't find a valid solution for the thought gain.
One way would be to modify the pawn itself. That would be the 'easiest' I think, but I don't like to modify base stuff like that, as it won't be compatible with other mods that also change them...
The easiest for you would be a watch building (invisible). This way you'd have a reliable ticker source.
The only problem would be the placement, as it still is a building, even if it is invisible.
Maybe you could place it in the lower right corner, whenever there isn't one and when your pawn spawns.
Or you DO modify the pawn itself..
Alright guys, here's my workaround: I made a new class that inherits from Pawn, called Colonist, which overrides all Human Pawns. Within the Colonist class, I overrided the Tick() method and embedded my Aging() method within it. This allowed me to set the aging to each pawn personally without having to reference a list of them all, but has the side-effect of making -every- human in the game be aging now lol I haven't tested this to see how it affects other faction members, nor have any clue if the game is tracking them in the background to update their Tick() methods, but at the moment... it works really really well. If you guys wanna test it or use this workaround for anything else, here's the source and stuff attached below.
[attachment deleted by admin: too old]
Quote from: Haplo on August 09, 2014, 12:02:19 PM
Or you DO modify the pawn itself..
Yeah, it's the easier option. I can live with the mod not being compatible with everything else lol
I'm a little sad this didn't result in an actual form of code running on a global-scope, but w/e... considering the issue resolved. The idea of an invisible building in the corner of the map running code is probably the best solution for someone who really needs global-scope code, and just modifying the MapGenerator def to have it spawn on map generation.
yep thats how ive done it. the lazy way. :))
but it shouldn't age every pawn if you make a new pawn class? how come every pawn ages? did you want all the colonists to age too?
Quote from: minami26 on August 10, 2014, 03:35:28 AM
how come every pawn ages? did you want all the colonists to age too?
I modded the Races_Humanoid.xml file to use my new custom class, and since all the colonists are considered 'human'... they all end up using it. Making everyone age was indeed intentional.