internal static void CanGetThought_Patch(ref Pawn pawn, ref ThoughtDef def, ref bool __result) { // Toddlers and younger can't get these thoughts if (pawn.ageTracker.CurLifeStageIndex <= 1 && ChildrenUtility.RaceUsesChildren(pawn)) { List <ThoughtDef> thoughtlist = new List <ThoughtDef> { ThoughtDefOf.AteWithoutTable, ThoughtDefOf.KnowPrisonerDiedInnocent, ThoughtDefOf.KnowPrisonerSold, ThoughtDefOf.Naked, ThoughtDefOf.SleepDisturbed, ThoughtDefOf.SleptOnGround, ThoughtDef.Named("CabinFever"), //ThoughtDef.Named("SharedBedroom") }; foreach (ThoughtDef thought in thoughtlist) { if (def == thought) { __result = false; } } } }
// // Methods // protected override ThoughtState CurrentStateInternal(Pawn p) { if (p.ageTracker.CurLifeStageIndex > AgeStage.Toddler || !ChildrenUtility.RaceUsesChildren(p)) { return(false); } Pawn mother = p.relations.GetFirstDirectRelationPawn(PawnRelationDefOf.Parent, x => x.gender == Gender.Female); Pawn father = p.relations.GetFirstDirectRelationPawn(PawnRelationDefOf.Parent, x => x.gender == Gender.Male); if (ArePawnsNear(p, mother) && ArePawnsNear(p, father)) { return(ThoughtState.ActiveAtStage(2)); } else if (ArePawnsNear(p, mother)) { return(ThoughtState.ActiveAtStage(0)); } else if (ArePawnsNear(p, father)) { return(ThoughtState.ActiveAtStage(1)); } else { return(false); } }
internal static void Notify_EquipmentAdded_Patch(ref ThingWithComps eq, ref Pawn_EquipmentTracker __instance) { Pawn pawn = __instance.ParentHolder as Pawn; if (pawn != null && ChildrenUtility.RaceUsesChildren(pawn) && eq.def.BaseMass > ChildrenUtility.ChildMaxWeaponMass(pawn) && pawn.ageTracker.CurLifeStageIndex <= AgeStage.Child && pawn.Faction.IsPlayer) { Messages.Message("MessageWeaponTooLarge".Translate(new object[] { eq.def.label, ((Pawn)__instance.ParentHolder).NameStringShort }), MessageTypeDefOf.CautionInput); } }
internal static void SBD(ref Pawn_HealthTracker __instance, ref bool __result) { Pawn pawn = (Pawn)AccessTools.Field(typeof(Pawn_HealthTracker), "pawn").GetValue(__instance); if (ChildrenUtility.RaceUsesChildren(pawn) && pawn.ageTracker.CurLifeStageIndex <= 2) { __result = __instance.hediffSet.PainTotal > 0.4f || !__instance.capacities.CanBeAwake || !__instance.capacities.CapableOf(PawnCapacityDefOf.Moving); } }
// // Fields // // // Methods // public override IEnumerable <BodyPartRecord> GetPartsToApplyOn(Pawn pawn, RecipeDef recipe) { BodyPartRecord part = pawn.RaceProps.body.corePart; if (recipe.appliedOnFixedBodyParts[0] != null) { part = pawn.RaceProps.body.AllParts.Find(x => x.def == recipe.appliedOnFixedBodyParts[0]); } if (part != null && ChildrenUtility.RaceUsesChildren(pawn) && pawn.gender == Gender.Female && pawn.ageTracker.CurLifeStageIndex >= AgeStage.Teenager) { yield return(part); } }
public static T FailOnBaby <T>(this T f) where T : IJobEndable { f.AddEndCondition(delegate { // return JobCondition.Incompletable; if (f.GetActor().ageTracker.CurLifeStageIndex <= 1 && ChildrenUtility.RaceUsesChildren(f.GetActor())) { return(JobCondition.Incompletable); } else { return(JobCondition.Ongoing); } }); return(f); }
internal static void _GeneratePawn(ref PawnGenerationRequest request, ref Pawn __result) { Pawn pawn = __result; if (pawn.ageTracker.CurLifeStageIndex <= AgeStage.Child && ChildrenUtility.RaceUsesChildren(pawn)) { // hostile children on/off if (!BnC_Settings.option_hostile_children_raider && Faction.OfPlayerSilentFail != null) { if (pawn.Faction != null && pawn.HostileTo(Faction.OfPlayer)) { Log.Message("[From BnC] hostile children growup : " + pawn.LabelIndefinite()); ChildrenUtility.GrowupHostileChild(ref request, ref pawn); return; } } // give innocence trait ChildrenUtility.Give_Innocent_trait(ref pawn); // give backstory if (pawn.ageTracker.CurLifeStageIndex == 2 && pawn.ageTracker.AgeBiologicalYears < 8 && ChildrenUtility.IsHumanlikeChild(pawn)) { pawn.story.childhood = BackstoryDatabase.allBackstories["CustomBackstory_NA_Childhood"]; } if (pawn.ageTracker.CurLifeStageIndex == AgeStage.Baby) { // if rjw is on return if (AnotherModCheck.RJW_On) { return; } } // Children hediff being injected pawn.health.AddHediff(HediffDef.Named("BabyState"), null, null); Hediff_Baby babystate = (Hediff_Baby)pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("BabyState")); if (babystate != null) { for (int i = 0; i != pawn.ageTracker.CurLifeStageIndex + 1; i++) { babystate.GrowUpTo(i, true); } } } }
internal static void TryCastShot_Patch(ref Verb_Shoot __instance) { Pawn pawn = __instance.CasterPawn; if (pawn != null && ChildrenUtility.RaceUsesChildren(pawn) && pawn.ageTracker.CurLifeStageIndex <= AgeStage.Child) { // The weapon is too heavy and the child will (likely) drop it when trying to fire if (__instance.ownerEquipment.def.BaseMass > ChildrenUtility.ChildMaxWeaponMass(pawn)) { ThingWithComps benis; pawn.equipment.TryDropEquipment(__instance.ownerEquipment, out benis, pawn.Position, false); float recoilForce = (__instance.ownerEquipment.def.BaseMass - 3); if (recoilForce > 0) { string[] hitPart = { "Torso", "LeftShoulder", "LeftArm", "LeftHand", "RightShoulder", "RightArm", "RightHand", "Head", "Neck", "LeftEye", "RightEye", "Nose", }; int hits = Rand.Range(1, 4); while (hits > 0) { pawn.TakeDamage(new DamageInfo(DamageDefOf.Blunt, (int)((recoilForce + Rand.Range(0f, 3f)) / hits), -1, __instance.ownerEquipment, ChildrenUtility.GetPawnBodyPart(pawn, hitPart.RandomElement <String> ()), null)); hits--; } } } } }
// // Methods // protected override ThoughtState CurrentStateInternal(Pawn p) { // Does not affect babies and toddlers if (p.ageTracker.CurLifeStageIndex < 2 || p.health.capacities.GetLevel(PawnCapacityDefOf.Hearing) <= 0.1f) { return(ThoughtState.Inactive); } // Find all crying babies in the vicinity int cryingBabies = 0; foreach (Pawn mapPawn in p.MapHeld.mapPawns.AllPawnsSpawned) { if (ChildrenUtility.RaceUsesChildren(mapPawn) && mapPawn.ageTracker.CurLifeStageIndex == 0 && mapPawn.health.hediffSet.HasHediff(HediffDef.Named("UnhappyBaby")) && mapPawn.PositionHeld.InHorDistOf(p.PositionHeld, 24) && mapPawn.PositionHeld.GetRoomOrAdjacent(mapPawn.MapHeld).ContainedAndAdjacentThings.Contains(p)) { cryingBabies += 1; } } if (cryingBabies > 0) { if (cryingBabies == 1) { return(ThoughtState.ActiveAtStage(0)); } else if (cryingBabies <= 3) { return(ThoughtState.ActiveAtStage(1)); } else if (cryingBabies >= 4) { return(ThoughtState.ActiveAtStage(2)); } } return(ThoughtState.Inactive); }
internal static void ResolveAgeGraphics(PawnGraphicSet graphics) { LongEventHandler.ExecuteWhenFinished(delegate { //if (!graphics.pawn.RaceProps.Humanlike) { if (!ChildrenUtility.RaceUsesChildren(graphics.pawn)) { return; } // Beards String beard = ""; if (graphics.pawn.story.hairDef != null) { if (graphics.pawn.story.hairDef.hairTags.Contains("Beard")) { if (graphics.pawn.apparel.BodyPartGroupIsCovered(BodyPartGroupDefOf.UpperHead) && !graphics.pawn.story.hairDef.hairTags.Contains("DrawUnderHat")) { beard = "_BeardOnly"; } if (graphics.pawn.ageTracker.CurLifeStageIndex <= AgeStage.Teenager) { graphics.hairGraphic = GraphicDatabase.Get <Graphic_Multi> (DefDatabase <HairDef> .GetNamed("Mop").texPath, ShaderDatabase.Cutout, Vector2.one, graphics.pawn.story.hairColor); } else { graphics.hairGraphic = GraphicDatabase.Get <Graphic_Multi> (graphics.pawn.story.hairDef.texPath + beard, ShaderDatabase.Cutout, Vector2.one, graphics.pawn.story.hairColor); } } else { graphics.hairGraphic = GraphicDatabase.Get <Graphic_Multi> (graphics.pawn.story.hairDef.texPath, ShaderDatabase.Cutout, Vector2.one, graphics.pawn.story.hairColor); } } // Reroute the graphics for children // For babies and toddlers if (graphics.pawn.ageTracker.CurLifeStageIndex <= AgeStage.Baby) { string toddler_hair = "Boyish"; if (graphics.pawn.gender == Gender.Female) { toddler_hair = "Girlish"; } graphics.hairGraphic = GraphicDatabase.Get <Graphic_Multi> ("Things/Pawn/Humanlike/Children/Hairs/Child_" + toddler_hair, ShaderDatabase.Cutout, Vector2.one, graphics.pawn.story.hairColor); graphics.headGraphic = GraphicDatabase.Get <Graphic_Multi> ("Things/Pawn/Humanlike/null", ShaderDatabase.Cutout, Vector2.one, Color.white); // The pawn is a baby if (graphics.pawn.ageTracker.CurLifeStageIndex == AgeStage.Baby) { graphics.nakedGraphic = GraphicDatabase.Get <Graphic_Single> ("Things/Pawn/Humanlike/Children/Bodies/Newborn", ShaderDatabase.CutoutSkin, Vector2.one, graphics.pawn.story.SkinColor); } } // The pawn is a toddler if (graphics.pawn.ageTracker.CurLifeStageIndex == AgeStage.Toddler) { string upright = ""; if (graphics.pawn.ageTracker.AgeBiologicalYears >= 1) { upright = "Upright"; } graphics.nakedGraphic = GraphicDatabase.Get <Graphic_Multi> ("Things/Pawn/Humanlike/Children/Bodies/Toddler" + upright, ShaderDatabase.CutoutSkin, Vector2.one, graphics.pawn.story.SkinColor); } // The pawn is a child else if (graphics.pawn.ageTracker.CurLifeStageIndex == AgeStage.Child) { graphics.nakedGraphic = Children_Drawing.GetChildBodyGraphics(graphics, ShaderDatabase.CutoutSkin, graphics.pawn.story.SkinColor); graphics.headGraphic = Children_Drawing.GetChildHeadGraphics(graphics, ShaderDatabase.CutoutSkin, graphics.pawn.story.SkinColor); } }); }
public static IEnumerable <Pawn> BedCandidates(Building_Bed bed) { if (bed.def.defName.Contains("Crib")) { IEnumerable <Pawn> candidates = bed.Map.mapPawns.FreeColonists.Where(x => x.ageTracker.CurLifeStageIndex <= 2 && x.Faction == Faction.OfPlayer && ChildrenUtility.RaceUsesChildren(x)); return(candidates); } else { return(bed.Map.mapPawns.FreeHumanlikesOfFaction(Faction.OfPlayer)); } }
public static T FailOnBaby <T>(this T f) where T : JobDriver { f.AddEndCondition(delegate { // return JobCondition.Incompletable; //CompBabyGear compBabyGear = f.job.GetTarget(TargetIndex.A).Thing.TryGetComp<CompBabyGear>(); Pawn personDressing = f.GetActor(); if (f.GetActor().ageTracker.CurLifeStageIndex <= 1 && f.job.GetTarget(TargetIndex.A).Thing.TryGetComp <CompBabyGear>() == null && ChildrenUtility.RaceUsesChildren(f.GetActor())) { Messages.Message("MessageAdultClothesOnBaby".Translate(new object[] { personDressing.Name.ToStringShort }), personDressing, MessageTypeDefOf.CautionInput); return(JobCondition.Incompletable); } //tried testing for bool "isBabyGear" but that caused a null error exception, so I switched to just testing if comp was null, will look into later if (f.GetActor().ageTracker.CurLifeStageIndex > 1 && f.job.GetTarget(TargetIndex.A).Thing.TryGetComp <CompBabyGear>() != null) { Messages.Message("MessageBabyClothesOnAdult".Translate(new object[] { personDressing.LabelShort }), personDressing, MessageTypeDefOf.CautionInput); return(JobCondition.Incompletable); } else { return(JobCondition.Ongoing); } }); return(f); }
static void TryGiveJob_Patch(JobGiver_OptimizeApparel __instance, ref Job __result, Pawn pawn) { if (__result != null) { // Stop the game from automatically allocating pawns Wear jobs they cannot fulfil if ((pawn.ageTracker.CurLifeStageIndex <= AgeStage.Toddler && __result.targetA.Thing.TryGetComp <CompBabyGear>() == null && ChildrenUtility.RaceUsesChildren(pawn)) || (pawn.ageTracker.CurLifeStageIndex >= AgeStage.Child && __result.targetA.Thing.TryGetComp <CompBabyGear>() != null)) { __result = null; } } else { // makes pawn to remove baby clothes when too old for them. List <Apparel> wornApparel = pawn.apparel.WornApparel; if (pawn.ageTracker.CurLifeStageIndex >= AgeStage.Child) { for (int i = wornApparel.Count - 1; i >= 0; i--) { CompBabyGear compBabyGear = wornApparel[i].TryGetComp <CompBabyGear>(); if (compBabyGear != null) { __result = new Job(JobDefOf.RemoveApparel, wornApparel[i]) { haulDroppedApparel = true }; return; } } } } }
internal static void TryToImpregnate(Pawn initiator, Pawn partner) { // Lesbian/gay couples. Those cases should never result in pregnancy if (initiator.gender == partner.gender) { return; } // One of the two is sterile, so don't continue foreach (Pawn pawn in new List <Pawn> { initiator, partner }) { if (pawn.health.hediffSet.HasHediff(HediffDef.Named("Sterile"))) { return; } } Pawn male = initiator.gender == Gender.Male? initiator: partner; Pawn female = initiator.gender == Gender.Female ? initiator : partner; // Only humans can be impregnated for now if (!ChildrenUtility.RaceUsesChildren(female)) { return; } BodyPartRecord torso = female.RaceProps.body.AllParts.Find(x => x.def == BodyPartDefOf.Torso); HediffDef contraceptive = HediffDef.Named("Contraceptive"); // Make sure the woman is not pregnanct and not using a contraceptive if (female.health.hediffSet.HasHediff(HediffDefOf.Pregnant, torso) || female.health.hediffSet.HasHediff(contraceptive, null) || male.health.hediffSet.HasHediff(contraceptive, null)) { return; } // Check the pawn's age to see how likely it is she can carry a fetus // 25 and below is guaranteed, 50 and above is impossible, 37.5 is 50% chance float preg_chance = Math.Max(1 - (Math.Max(female.ageTracker.AgeBiologicalYearsFloat - 25, 0) / 25), 0) * 0.33f; // For debug testing //float preg_chance = 1; if (preg_chance < Rand.Value) { if (Prefs.DevMode) { Log.Message("Impregnation failed. Chance was " + preg_chance); } return; } if (Prefs.DevMode) { Log.Message("Impregnation succeeded. Chance was " + preg_chance); } // Spawn a bunch of hearts. Sharp eyed players may notice this means impregnation occurred. for (int i = 0; i <= 3; i++) { MoteMaker.ThrowMetaIcon(male.Position, male.MapHeld, ThingDefOf.Mote_Heart); MoteMaker.ThrowMetaIcon(female.Position, male.MapHeld, ThingDefOf.Mote_Heart); } // Do the actual impregnation. We apply it to the torso because Remove_Hediff in operations doesn't work on WholeBody (null body part) // for whatever reason. female.health.AddHediff(Hediff_HumanPregnancy.Create(female, male), torso); }