public static bool AndroidVaginaFertility(Pawn pawn) { //androids only fertile with archotech parts BodyPartRecord Part = Genital_Helper.get_genitalsBPR(pawn); return(pawn.health.hediffSet.hediffs.Any((Hediff hed) => (hed.Part == Part) && (hed.def == Genital_Helper.archotech_vagina) )); }
//Plant Insect eggs/mech chips/other preg mod hediff? public static bool PlantSomething(HediffDef def, Pawn target, bool isToAnal = false, int amount = 1) { if (def == null) { return(false); } if (!isToAnal && !Genital_Helper.has_vagina(target)) { return(false); } if (isToAnal && !Genital_Helper.has_anus(target)) { return(false); } BodyPartRecord Part = (isToAnal) ? Genital_Helper.get_anusBPR(target) : Genital_Helper.get_genitalsBPR(target); if (Part != null || Part.parts.Count != 0) { //killoff normal preg if (!isToAnal) { if (RJWSettings.DevMode) { Log.Message("[RJW] removing other pregnancies"); } var preg = GetPregnancy(target); if (preg != null) { if (preg is Hediff_BasePregnancy) { (preg as Hediff_BasePregnancy).Kill(); } else { target.health.RemoveHediff(preg); } } } for (int i = 0; i < amount; i++) { if (RJWSettings.DevMode) { Log.Message("[RJW] planting something weird"); } target.health.AddHediff(def, Part); } return(true); } return(false); }
public static void add_genitals(Pawn pawn, Pawn parent = null, Gender gender = Gender.None) { //--Log.Message("Genital_Helper::add_genitals( " + xxx.get_pawnname(pawn) + " ) called"); BodyPartRecord partBPR = Genital_Helper.get_genitalsBPR(pawn); var parts = Genital_Helper.get_PartsHediffList(pawn, partBPR); //--Log.Message("Genital_Helper::add_genitals( " + xxx.get_pawnname(pawn) + " ) - checking genitals"); if (partBPR == null) { //--Log.Message("[RJW] add_genitals( " + xxx.get_pawnname(pawn) + " ) doesn't have a genitals"); return; } else if (pawn.health.hediffSet.PartIsMissing(partBPR)) { //--Log.Message("[RJW] add_genitals( " + xxx.get_pawnname(pawn) + " ) had a genital but was removed."); return; } if (Genital_Helper.has_genitals(pawn, parts) && gender == Gender.None) //allow to add gender specific genitals(futa) { //--Log.Message("[RJW] add_genitals( " + xxx.get_pawnname(pawn) + " ) already has genitals"); return; } HediffDef part; // maybe add some check based on bodysize of pawn for genitals size limit //Log.Message("Genital_Helper::add_genitals( " + pawn.RaceProps.baseBodySize + " ) - 1"); //Log.Message("Genital_Helper::add_genitals( " + pawn.kindDef.race.size. + " ) - 2"); part = (IsAddingPenis(pawn, gender)) ? Genital_Helper.generic_penis : Genital_Helper.generic_vagina; if (Genital_Helper.has_vagina(pawn, parts) && part == Genital_Helper.generic_vagina) { //--Log.Message("[RJW] add_genitals( " + xxx.get_pawnname(pawn) + " ) already has v****a"); return; } if ((Genital_Helper.has_penis_fertile(pawn, parts) || Genital_Helper.has_penis_infertile(pawn, parts)) && part == Genital_Helper.generic_penis) { //--Log.Message("[RJW] add_genitals( " + xxx.get_pawnname(pawn) + " ) already has penis"); return; } //override race genitals if (part == Genital_Helper.generic_vagina && pawn.TryAddRacePart(SexPartType.FemaleGenital)) { return; } if (part == Genital_Helper.generic_penis && pawn.TryAddRacePart(SexPartType.MaleGenital)) { return; } LegacySexPartAdder.AddGenitals(pawn, parent, gender, partBPR, part); }
public static void Postfix(ref Job __result, Pawn pawn) { //Log.Message("[RJW]patches_lovin::JobGiver_Mate fail, try rjw for " + xxx.get_pawnname(pawn)); var partBPR = Genital_Helper.get_genitalsBPR(pawn); var parts = Genital_Helper.get_PartsHediffList(pawn, partBPR); if (!(Genital_Helper.has_penis_fertile(pawn, parts) || Genital_Helper.has_penis_infertile(pawn, parts)) || !pawn.ageTracker.CurLifeStage.reproductive) { //Log.Message("[RJW]patches_lovin::JobGiver_Mate " + xxx.get_pawnname(pawn) + ", has no penis " + (Genital_Helper.has_penis(pawn) || Genital_Helper.has_penis_infertile(pawn))); //Log.Message("[RJW]patches_lovin::JobGiver_Mate " + xxx.get_pawnname(pawn) + ", not reproductive " + !pawn.ageTracker.CurLifeStage.reproductive); return; } Predicate <Thing> validator = delegate(Thing t) { Pawn pawn3 = t as Pawn; var valid = !pawn3.Downed && pawn3 != pawn && pawn3.CanCasuallyInteractNow() && !pawn3.IsForbidden(pawn) && !pawn3.HostileTo(pawn) && PawnUtility.FertileMateTarget(pawn, pawn3); if (!valid && pawn3 != pawn) { //Log.Message("[RJW]patches_lovin::JobGiver_Mate " + xxx.get_pawnname(pawn3) + ", not valid"); //Log.Message("[RJW]patches_lovin::JobGiver_Mate Downed " + pawn3.Downed); //Log.Message("[RJW]patches_lovin::JobGiver_Mate CanCasuallyInteractNow " + pawn3.CanCasuallyInteractNow()); //Log.Message("[RJW]patches_lovin::JobGiver_Mate IsForbidden " + pawn3.IsForbidden(pawn)); //Log.Message("[RJW]patches_lovin::JobGiver_Mate FertileMateTarget " + PawnUtility.FertileMateTarget(pawn, pawn3)); } return(valid); }; ThingRequest request = ThingRequest.ForDef(pawn.def); // mate sames species if (RJWSettings.WildMode) // go wild xD { request = ThingRequest.ForGroup(ThingRequestGroup.Pawn); // mate everyone } //add animal check? Pawn pawn2 = (Pawn)GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, request, PathEndMode.Touch, TraverseParms.For(pawn), 30f, validator); if (pawn2 == null) { //Log.Message("[RJW]patches_lovin::JobGiver_Mate " + xxx.get_pawnname(pawn) + ", no valid partner found"); return; } //__result = JobMaker.MakeJob(xxx.animalBreed, pawn2); __result = JobMaker.MakeJob(JobDefOf.Mate, pawn2); //Log.Message("[RJW]patches_lovin::JobGiver_Mate " + xxx.get_pawnname(pawn) + ", female " + xxx.get_pawnname(pawn2) + ", job " + __result); }
public override IEnumerable <BodyPartRecord> GetPartsToApplyOn(Pawn p, RecipeDef r) { //dont add artifical - peg, hydraulics, bionics, archo, ovi if (r.addsHediff.addedPartProps?.solid ?? false) { yield break; } //dont add if artifical parts present if (p.health.hediffSet.hediffs.Any((Hediff hed) => (hed.Part != null) && r.appliedOnFixedBodyParts.Contains(hed.Part.def) && (hed.def.addedPartProps?.solid ?? false))) { yield break; } var partBPR = Genital_Helper.get_genitalsBPR(p); var parts = Genital_Helper.get_PartsHediffList(p, partBPR); //dont add if no ovi //if (Genital_Helper.has_ovipositorF(p, parts) || Genital_Helper.has_ovipositorM(p, parts)) // yield break; //dont add if same part type not present yet if (!Genital_Helper.has_vagina(p, parts) && r.defName.ToLower().Contains("v****a")) { yield break; } if (!Genital_Helper.has_penis_fertile(p, parts) && r.defName.ToLower().Contains("penis")) { yield break; } //cant install parts when part blocked, on slimes, on demons bool blocked = (xxx.is_slime(p) || //|| xxx.is_demon(p) (Genital_Helper.genitals_blocked(p) && r.appliedOnFixedBodyParts.Contains(xxx.genitalsDef)) || (Genital_Helper.anus_blocked(p) && r.appliedOnFixedBodyParts.Contains(xxx.anusDef)) || (Genital_Helper.breasts_blocked(p) && r.appliedOnFixedBodyParts.Contains(xxx.breastsDef))); foreach (BodyPartRecord part in base.GetPartsToApplyOn(p, r)) { if (r.appliedOnFixedBodyParts.Contains(part.def) && !blocked) { yield return(part); } } }
public static Sex GetSex(Pawn pawn) { var partBPR = Genital_Helper.get_genitalsBPR(pawn); var parts = Genital_Helper.get_PartsHediffList(pawn, partBPR); bool has_vagina = Genital_Helper.has_vagina(pawn, parts); bool has_penis = Genital_Helper.has_penis_fertile(pawn, parts); bool has_penis_infertile = Genital_Helper.has_penis_infertile(pawn, parts); bool has_breasts = Genital_Helper.has_breasts(pawn); bool has_male_breasts = Genital_Helper.has_male_breasts(pawn); //BodyType? bt = pawn.story?.bodyType; //if (bt != null) // bt = BodyType.Undefined; Sex res; if (has_vagina && !has_penis && !has_penis_infertile) { res = Sex.female; } else if (has_vagina && (has_penis || has_penis_infertile)) { res = Sex.futa; } else if ((has_penis || has_penis_infertile) && has_breasts && !has_male_breasts) { res = Sex.trap; } else if (has_penis || has_penis_infertile) //probably should change this later { res = Sex.male; } else if (pawn.gender == Gender.Male) { res = Sex.male; } else if (pawn.gender == Gender.Female) { res = Sex.female; } else { res = Sex.none; } return(res); }
public override IEnumerable <BodyPartRecord> GetPartsToApplyOn(Pawn p, RecipeDef r) { var partBPR = Genital_Helper.get_genitalsBPR(p); var parts = Genital_Helper.get_PartsHediffList(p, partBPR); bool blocked = Genital_Helper.genitals_blocked(p) || xxx.is_slime(p); //|| xxx.is_demon(p); bool has_vag = Genital_Helper.has_vagina(p, parts); bool has_cock = Genital_Helper.has_penis_fertile(p, parts) || Genital_Helper.has_penis_infertile(p, parts) || Genital_Helper.has_ovipositorF(p, parts); foreach (BodyPartRecord part in base.GetPartsToApplyOn(p, r)) { if (r.appliedOnFixedBodyParts.Contains(part.def) && !blocked && (!has_vag && has_cock)) { yield return(part); } } }
static float fall_per_tick(Pawn pawn) { var partBPR = Genital_Helper.get_genitalsBPR(pawn); var parts = Genital_Helper.get_PartsHediffList(pawn, partBPR); var fall_per_tick = //def.fallPerDay * decay_per_day * brokenbodyfactor(pawn) * druggedfactor(pawn) * diseasefactor(pawn) * agefactor(pawn) * (((Genital_Helper.has_penis_fertile(pawn, parts) || Genital_Helper.has_penis_infertile(pawn, parts)) && Genital_Helper.has_vagina(pawn, parts)) ? 2.0f : 1.0f) / 60000.0f; //--Log.Message("[RJW]Need_Sex::NeedInterval is called - pawn is " + xxx.get_pawnname(pawn) + " is has both genders " + (Genital_Helper.has_penis(pawn) && Genital_Helper.has_vagina(pawn))); //Log.Message("[RJW] " + xxx.get_pawnname(pawn) + "'s sex need stats:: fall_per_tick: " + fall_per_tick + ", sex_need_factor_from_lifestage: " + sex_need_factor_from_lifestage(pawn) ); return(fall_per_tick); }
static void Change_Archotechmode(Pawn pawn) { BodyPartRecord genitalia = Genital_Helper.get_genitalsBPR(pawn); Hediff blocker = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("ImpregnationBlocker")); Hediff enhancer = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("FertilityEnhancer")); if (blocker != null) { pawn.health.RemoveHediff(blocker); } else if (enhancer == null) { pawn.health.AddHediff(HediffDef.Named("FertilityEnhancer"), genitalia); } else { if (enhancer != null) { pawn.health.RemoveHediff(enhancer); } pawn.health.AddHediff(HediffDef.Named("ImpregnationBlocker"), genitalia); } }
public static Pawn find_designated_breeder(Pawn pawn, Map m) { if (!DesignatorsData.rjwBreeding.Any()) { return(null); } DebugText("BreederHelper::find_designated_breeder( " + xxx.get_pawnname(pawn) + " ) called"); float min_fuckability = 0.10f; // Don't rape pawns with <10% fuckability float avg_fuckability = 0f; // Average targets fuckability, choose target higher than that var valid_targets = new Dictionary <Pawn, float>(); // Valid pawns and their fuckability Pawn chosentarget = null; // Final target pawn if (pawn.Faction == null) // HostileTo causes error on fresh colony(w/o name) { return(null); } IEnumerable <Pawn> targets = DesignatorsData.rjwBreeding.Where(x => x != pawn && xxx.is_not_dying(x) && xxx.can_get_raped(x) && !x.IsForbidden(pawn) && !x.Suspended && !x.HostileTo(pawn) && !(x.IsPregnant() && xxx.is_animal(x)) && pawn.CanReserveAndReach(x, PathEndMode.Touch, Danger.Some, max_animals_at_once) && ((RJWSettings.bestiality_enabled && xxx.is_human(x)) || (RJWSettings.animal_on_animal_enabled && xxx.is_animal(x))) ); foreach (Pawn target in targets) { if (!xxx.can_path_to_target(pawn, target.Position)) { continue; // too far } var partBPR = Genital_Helper.get_genitalsBPR(pawn); var parts = Genital_Helper.get_PartsHediffList(pawn, partBPR); var fuc = SexAppraiser.would_fuck(pawn, target, invert_opinion: true, ignore_gender: (Genital_Helper.has_penis_fertile(pawn, parts) || Genital_Helper.has_penis_infertile(pawn, parts) || xxx.is_insect(pawn))); DebugText("BreederHelper::find_designated_breeder( " + xxx.get_pawnname(pawn) + " -> " + xxx.get_pawnname(target) + " (" + fuc.ToString() + " / " + min_fuckability.ToString() + ")"); if (fuc > min_fuckability) { valid_targets.Add(target, fuc); } } if (valid_targets.Any()) { //avg_fuckability = valid_targets.Average(x => x.Value); // choose pawns to f**k with above average fuckability var valid_targetsFilteredAnimals = valid_targets.Where(x => x.Value >= avg_fuckability); if (valid_targetsFilteredAnimals.Any()) { chosentarget = valid_targetsFilteredAnimals.RandomElement().Key; } } return(chosentarget); }
public static bool CheckPreference(Pawn pawn, Pawn partner) { if (RJWPreferenceSettings.sexuality_distribution == RJWPreferenceSettings.Rjw_sexuality.Vanilla) { if (xxx.has_traits(pawn)) { VanillaTraitCheck(pawn); } if (xxx.has_traits(partner)) { VanillaTraitCheck(partner); } } if (RJWPreferenceSettings.sexuality_distribution == RJWPreferenceSettings.Rjw_sexuality.SYRIndividuality) { CopyIndividualitySexuality(pawn); CopyIndividualitySexuality(partner); } if (RJWPreferenceSettings.sexuality_distribution == RJWPreferenceSettings.Rjw_sexuality.Psychology) { if (RJWPreferenceSettings.sexuality_distribution == RJWPreferenceSettings.Rjw_sexuality.Psychology) { CopyPsychologySexuality(pawn); } CopyPsychologySexuality(partner); } //if (xxx.is_mechanoid(pawn)) // return false; Orientation ori = Orientation.None; try { ori = Comp(pawn).orientation; } catch { //Log.Message("[RJW]Error, pawn:" + pawn + " doesnt have orientation comp, modded race?"); return(false); } if (ori == Orientation.Pansexual || ori == Orientation.Bisexual) { return(true); } if (ori == Orientation.Asexual) { return(false); } var pawnpartBPR = Genital_Helper.get_genitalsBPR(pawn); var pawnparts = Genital_Helper.get_PartsHediffList(pawn, pawnpartBPR); var pawn_has_vagina = Genital_Helper.has_vagina(pawn, pawnparts); var pawn_has_penis_fertile = Genital_Helper.has_penis_fertile(pawn, pawnparts); var pawn_has_penis_infertile = Genital_Helper.has_penis_infertile(pawn, pawnparts); var partnerpartBPR = Genital_Helper.get_genitalsBPR(partner); var partnerparts = Genital_Helper.get_PartsHediffList(partner, partnerpartBPR); var partner_has_vagina = Genital_Helper.has_vagina(partner, partnerparts); var partner_has_penis_fertile = Genital_Helper.has_penis_fertile(partner, partnerparts); var partner_has_penis_infertile = Genital_Helper.has_penis_infertile(partner, partnerparts); bool isHetero = (pawn_has_vagina && (partner_has_penis_fertile || partner_has_penis_infertile)) || (partner_has_vagina && (pawn_has_penis_fertile || pawn_has_penis_infertile)); bool isHomo = (pawn_has_vagina && partner_has_vagina) || ((partner_has_penis_fertile || partner_has_penis_infertile) && (pawn_has_penis_fertile || pawn_has_penis_infertile)); if (isHetero && isHomo) { // Oh you crazy futas. We could probably do a check against the pawn's gender, but eh. They've got so many parts available, they'll find something to do. return(true); } //Rand.PopState(); //Rand.PushState(RJW_Multiplayer.PredictableSeed()); switch (ori) { case Orientation.Heterosexual: return(!isHomo); case Orientation.MostlyHeterosexual: return(!isHomo || Rand.Chance(0.2f)); case Orientation.LeaningHeterosexual: return(!isHomo || Rand.Chance(0.6f)); case Orientation.LeaningHomosexual: return(!isHetero || Rand.Chance(0.6f)); case Orientation.MostlyHomosexual: return(!isHetero || Rand.Chance(0.2f)); case Orientation.Homosexual: return(!isHetero); default: Log.Error("RJW::ERROR - tried to check preference for undetermined sexuality."); return(false); } }
static float GetCatchChance(Pawn pawn, std_def sd) { var bodyPartRecord = std.GetRelevantBodyPartRecord(pawn, sd); float artificialFactor = 1f; if (bodyPartRecord == null && pawn.health.hediffSet.HasDirectlyAddedPartFor(Genital_Helper.get_genitalsBPR(pawn))) { artificialFactor = .15f; } else if (pawn.health.hediffSet.HasDirectlyAddedPartFor(bodyPartRecord)) { artificialFactor = 0f; } return(sd.catch_chance * artificialFactor); }
///<summary>For checking normal pregnancy, should not for egg implantion or such.</summary> public static bool CanImpregnate(Pawn f****r, Pawn f****d, xxx.rjwSextype sextype = xxx.rjwSextype.Vaginal) { if (f****r == null || f****d == null) { return(false); } if (RJWSettings.DevMode) { Log.Message("Rimjobworld::CanImpregnate checks (" + sextype + "):: " + xxx.get_pawnname(f****r) + " + " + xxx.get_pawnname(f****d) + ":"); } if (sextype == xxx.rjwSextype.MechImplant && !RJWPregnancySettings.mechanoid_pregnancy_enabled) { if (RJWSettings.DevMode) { Log.Message(" mechanoid 'pregnancy' disabled"); } return(false); } if (!(sextype == xxx.rjwSextype.Vaginal || sextype == xxx.rjwSextype.DoublePenetration)) { if (RJWSettings.DevMode) { Log.Message(" sextype cannot result in pregnancy"); } return(false); } if (AndroidsCompatibility.IsAndroid(f****r) && AndroidsCompatibility.IsAndroid(f****d)) { if (RJWSettings.DevMode) { Log.Message(xxx.get_pawnname(f****d) + " androids cant breed/reproduce androids"); } return(false); } if ((f****r.IsUnsexyRobot() || f****d.IsUnsexyRobot()) && !(sextype == xxx.rjwSextype.MechImplant)) { if (RJWSettings.DevMode) { Log.Message(" unsexy robot cant be pregnant"); } return(false); } if (!f****r.RaceHasPregnancy()) { if (RJWSettings.DevMode) { Log.Message(xxx.get_pawnname(f****d) + " filtered race that cant be pregnant"); } return(false); } if (!f****d.RaceHasPregnancy()) { if (RJWSettings.DevMode) { Log.Message(xxx.get_pawnname(f****r) + " filtered race that cant impregnate"); } return(false); } if (f****d.IsPregnant()) { if (RJWSettings.DevMode) { Log.Message(" already pregnant."); } return(false); } if ((from x in f****d.health.hediffSet.GetHediffs <Hediff_InsectEgg>() where x.def == DefDatabase <HediffDef_InsectEgg> .GetNamed(x.def.defName) select x).Any()) { if (RJWSettings.DevMode) { Log.Message(xxx.get_pawnname(f****d) + " cant get pregnant while eggs inside"); } return(false); } var pawnpartBPR = Genital_Helper.get_genitalsBPR(f****r); var pawnparts = Genital_Helper.get_PartsHediffList(f****r, pawnpartBPR); var partnerpartBPR = Genital_Helper.get_genitalsBPR(f****d); var partnerparts = Genital_Helper.get_PartsHediffList(f****d, partnerpartBPR); if (!(Genital_Helper.has_penis_fertile(f****r, pawnparts) && Genital_Helper.has_vagina(f****d, partnerparts)) && !(Genital_Helper.has_penis_fertile(f****d, partnerparts) && Genital_Helper.has_vagina(f****r, pawnparts))) { if (RJWSettings.DevMode) { Log.Message(" missing genitals for impregnation"); } return(false); } if (f****r.health.capacities.GetLevel(xxx.reproduction) <= 0 || f****d.health.capacities.GetLevel(xxx.reproduction) <= 0) { if (RJWSettings.DevMode) { Log.Message(" one (or both) pawn(s) infertile"); } return(false); } if (xxx.is_human(f****d) && xxx.is_human(f****r) && (RJWPregnancySettings.humanlike_impregnation_chance == 0 || !RJWPregnancySettings.humanlike_pregnancy_enabled)) { if (RJWSettings.DevMode) { Log.Message(" human pregnancy chance set to 0% or pregnancy disabled."); } return(false); } else if (((xxx.is_animal(f****r) && xxx.is_human(f****d)) || (xxx.is_human(f****r) && xxx.is_animal(f****d))) && !RJWPregnancySettings.bestial_pregnancy_enabled) { if (RJWSettings.DevMode) { Log.Message(" bestiality pregnancy chance set to 0% or pregnancy disabled."); } return(false); } else if (xxx.is_animal(f****d) && xxx.is_animal(f****r) && (RJWPregnancySettings.animal_impregnation_chance == 0 || !RJWPregnancySettings.animal_pregnancy_enabled)) { if (RJWSettings.DevMode) { Log.Message(" animal-animal pregnancy chance set to 0% or pregnancy disabled."); } return(false); } else if (f****r.def.defName != f****d.def.defName && (RJWPregnancySettings.interspecies_impregnation_modifier <= 0.0f && !RJWPregnancySettings.complex_interspecies)) { if (RJWSettings.DevMode) { Log.Message(" interspecies pregnancy disabled."); } return(false); } return(true); }
//called by aftersex (including rape, breed, etc) //called by mcevent //pawn - "father"; partner = mother public static void impregnate(Pawn pawn, Pawn partner, xxx.rjwSextype sextype = xxx.rjwSextype.None) { if (RJWSettings.DevMode) { Log.Message("Rimjobworld::impregnate(" + sextype + "):: " + xxx.get_pawnname(pawn) + " + " + xxx.get_pawnname(partner) + ":"); } //"mech" pregnancy if (sextype == xxx.rjwSextype.MechImplant) { if (RJWPregnancySettings.mechanoid_pregnancy_enabled) { if (RJWSettings.DevMode) { Log.Message(" mechanoid pregnancy"); } // removing old pregnancies if (RJWSettings.DevMode) { Log.Message("[RJW] removing other pregnancies"); } var preg = GetPregnancy(partner); if (preg != null) { if (preg is Hediff_BasePregnancy) { (preg as Hediff_BasePregnancy).Kill(); } else { partner.health.RemoveHediff(preg); } } // new pregnancy Hediff_MechanoidPregnancy hediff = Hediff_BasePregnancy.Create <Hediff_MechanoidPregnancy>(partner, pawn); return; /* * // Not an actual pregnancy. This implants mechanoid tech into the target. * //may lead to pregnancy * //old "chip pregnancies", maybe integrate them somehow? * //Rand.PopState(); * //Rand.PushState(RJW_Multiplayer.PredictableSeed()); * HediffDef_MechImplants egg = (from x in DefDatabase<HediffDef_MechImplants>.AllDefs select x).RandomElement(); * if (egg != null) * { * if (RJWSettings.DevMode) Log.Message(" planting MechImplants:" + egg.ToString()); * PlantSomething(egg, partner, !Genital_Helper.has_vagina(partner), 1); * return; * } * else * { * if (RJWSettings.DevMode) Log.Message(" no mech implant found"); * }*/ } return; } // Sextype can result in pregnancy. if (!(sextype == xxx.rjwSextype.Vaginal || sextype == xxx.rjwSextype.DoublePenetration)) { return; } //Log.Message("[RJW] RaceImplantEggs()" + pawn.RaceImplantEggs()); //"insect" pregnancy //straight, female (partner) recives egg insertion from other/sex starter (pawn) var pawnpartBPR = Genital_Helper.get_genitalsBPR(pawn); var pawnparts = Genital_Helper.get_PartsHediffList(pawn, pawnpartBPR); var partnerpartBPR = Genital_Helper.get_genitalsBPR(partner); var partnerparts = Genital_Helper.get_PartsHediffList(partner, partnerpartBPR); if (Genital_Helper.has_vagina(partner, partnerparts) && (Genital_Helper.has_ovipositorF(pawn, pawnparts) || (Genital_Helper.has_ovipositorM(pawn, pawnparts) || (Genital_Helper.has_penis_fertile(pawn, pawnparts) && pawn.RaceImplantEggs()))) ) { DoEgg(pawn, partner); return; } //reverse, female (pawn) starts sex/passive bestiality and fills herself with eggs - this is likely f****d up and needs fixing at jobdriver, processsex and aftersex levels else if (Genital_Helper.has_vagina(pawn, pawnparts) && (Genital_Helper.has_ovipositorF(partner, partnerparts) || (Genital_Helper.has_ovipositorM(partner, partnerparts) || (Genital_Helper.has_penis_fertile(partner, partnerparts) && pawn.RaceImplantEggs()))) ) { DoEgg(partner, pawn); return; } //"normal" and "beastial" pregnancy if (RJWSettings.DevMode) { Log.Message(" 'normal' pregnancy checks"); } //futa-futa docking? //if (CanImpregnate(partner, pawn, sextype) && CanImpregnate(pawn, partner, sextype)) //{ //Log.Message("[RJW] futa-futa docking..."); //return; //Doimpregnate(pawn, partner); //Doimpregnate(partner, pawn); //} //normal, when female is passive/recives interaction if (Genital_Helper.has_penis_fertile(pawn, pawnparts) && Genital_Helper.has_vagina(partner, partnerparts) && CanImpregnate(pawn, partner, sextype)) { if (RJWSettings.DevMode) { Log.Message(" impregnate forward"); } Doimpregnate(pawn, partner); } //reverse, when female active/starts interaction else if (Genital_Helper.has_vagina(pawn, pawnparts) && Genital_Helper.has_penis_fertile(partner, partnerparts) && CanImpregnate(partner, pawn, sextype)) { if (RJWSettings.DevMode) { Log.Message(" impregnate reverse"); } Doimpregnate(partner, pawn); } }
public static void DoEgg(Pawn pawn, Pawn partner) { if (RJWPregnancySettings.insect_pregnancy_enabled) { if (RJWSettings.DevMode) { Log.Message(" insect pregnancy"); } //female "insect" plant eggs //futa "insect" 50% plant eggs if ((Genital_Helper.has_ovipositorF(pawn) && !Genital_Helper.has_ovipositorM(pawn)) || (Genital_Helper.has_ovipositorF(pawn) && Genital_Helper.has_ovipositorM(pawn) && Rand.Value > 0.5f)) { float maxeggssize = (partner.BodySize / 5) * (xxx.has_quirk(partner, "Incubator") ? 2f : 1f) * (Genital_Helper.has_ovipositorF(partner) ? 2f : 0.5f); float eggedsize = 0; foreach (Hediff_InsectEgg egg in partner.health.hediffSet.GetHediffs <Hediff_InsectEgg>()) { if (egg.father != null) { eggedsize += egg.father.RaceProps.baseBodySize / 5; } else { eggedsize += egg.implanter.RaceProps.baseBodySize / 5; } } if (RJWSettings.DevMode) { Log.Message(" determine " + xxx.get_pawnname(partner) + " size of eggs inside: " + eggedsize + ", max: " + maxeggssize); } var eggs = pawn.health.hediffSet.GetHediffs <Hediff_InsectEgg>() .ToList(); var partnerGenitals = Genital_Helper.get_genitalsBPR(partner); while (eggs.Any() && eggedsize < maxeggssize) { var egg = eggs.First(); eggs.Remove(egg); pawn.health.RemoveHediff(egg); partner.health.AddHediff(egg, partnerGenitals); egg.Implanter(pawn); eggedsize += egg.eggssize; } //TODO: add widget toggle for bind all/neutral/hostile pawns if (pawn.HostileTo(partner)) { //if (!pawn.IsColonist) if (!partner.health.hediffSet.HasHediff(HediffDef.Named("RJW_Cocoon"))) { //if (!partner.health.hediffSet.HasHediff(HediffDef.Named("RJW_Cocoon")) && pawn.Faction != partner.Faction) //if (!partner.health.hediffSet.HasHediff(HediffDef.Named("RJW_Cocoon")) && pawn.Faction != partner.Faction && pawn.HostileTo(partner)) partner.health.AddHediff(HediffDef.Named("RJW_Cocoon")); } } } //male "insect" fertilize eggs else if (!pawn.health.hediffSet.HasHediff(xxx.sterilized)) { foreach (var egg in (from x in partner.health.hediffSet.GetHediffs <Hediff_InsectEgg>() where x.IsParent(pawn) select x)) { egg.Fertilize(pawn); } } return; } }
public override float CalculateCapacityLevel(HediffSet diffSet, List <PawnCapacityUtility.CapacityImpactor> impactors = null) { Pawn pawn = diffSet.pawn; var partBPR = Genital_Helper.get_genitalsBPR(pawn); var parts = Genital_Helper.get_PartsHediffList(pawn, partBPR); if (!Genital_Helper.has_penis_fertile(pawn, parts) && !Genital_Helper.has_vagina(pawn, parts)) { return(0); } if (Genital_Helper.has_ovipositorF(pawn, parts) || Genital_Helper.has_ovipositorM(pawn, parts)) { return(0); } //Log.Message("[RJW]PawnCapacityWorker_Fertility::CalculateCapacityLevel is called for: " + xxx.get_pawnname(pawn)); RaceProperties race = diffSet.pawn.RaceProps; if (!pawn.RaceHasFertility()) { //Log.Message(" Fertility_filter, no fertility for : " + pawn.kindDef.defName); return(0f); } //androids only fertile with archotech parts if (AndroidsCompatibility.IsAndroid(pawn) && !(AndroidsCompatibility.AndroidPenisFertility(pawn) || AndroidsCompatibility.AndroidVaginaFertility(pawn))) { //Log.Message(" Android has no archotech genitals set fertility to 0 for: " + pawn.kindDef.defName); return(0f); } //archotech always fertile mode if (pawn.health.hediffSet.HasHediff(HediffDef.Named("FertilityEnhancer"))) { //Log.Message(" has archotech FertilityEnhancer set fertility to 100%"); return(1f); } float startAge = 0f; //raise fertility float startMaxAge = 0f; //max fertility float endAge = race.lifeExpectancy * (RJWPregnancySettings.fertility_endage_male * 0.7f); // Age when males start to lose potency. float zeroFertility = race.lifeExpectancy * RJWPregnancySettings.fertility_endage_male; // Age when fertility hits 0%. if (xxx.is_female(pawn)) { if (xxx.is_animal(pawn)) { endAge = race.lifeExpectancy * (RJWPregnancySettings.fertility_endage_female_animal * 0.6f); zeroFertility = race.lifeExpectancy * RJWPregnancySettings.fertility_endage_female_animal; } else { endAge = race.lifeExpectancy * (RJWPregnancySettings.fertility_endage_female_humanlike * 0.6f); // Age when fertility begins to drop. zeroFertility = race.lifeExpectancy * RJWPregnancySettings.fertility_endage_female_humanlike; // Age when fertility hits 0%. } } foreach (LifeStageAge lifestage in race.lifeStageAges) { if (lifestage.def.reproductive) { //presumably teen stage if (startAge == 0f && startMaxAge == 0f) { startAge = lifestage.minAge; startMaxAge = (Mathf.Max(startAge + (startAge + endAge) * 0.08f, startAge)); } //presumably adult stage else { if (startMaxAge > lifestage.minAge) { startMaxAge = lifestage.minAge; } } } } //Log.Message(" Fertility ages for " + pawn.Name + " are: " + startAge + ", " + startMaxAge + ", " + endAge + ", " + endMaxAge); float result = PawnCapacityUtility.CalculateTagEfficiency(diffSet, BodyPartTagDefOf.RJW_Fertility, 1f, FloatRange.ZeroToOne, impactors); result *= GenMath.FlatHill(startAge, startMaxAge, endAge, zeroFertility, pawn.ageTracker.AgeBiologicalYearsFloat); //Log.Message("[RJW]PawnCapacityWorker_Fertility::CalculateCapacityLevel result is: " + result); return(result); }
public override void Tick() { ageTicks++; if (!pawn.IsHashIntervalTick(10000)) // run every ~3min { return; } var partBase = def as HediffDef_PartBase; if (partBase != null) { if (partBase.produceEggs) { var IsPlayerFaction = pawn.Faction?.IsPlayer ?? false; //colonists/animals if (pawn.Map.IsPlayerHome || IsPlayerFaction || pawn.IsPrisonerOfColony) { ageTicks++; if (nextEggTick < 0) { nextEggTick = Rand.Range(partBase.minEggTick, partBase.maxEggTick); return; } if (pawn.health.capacities.GetLevel(PawnCapacityDefOf.Moving) <= 0.5) { return; } if (nextEggTick > 0 && ageTicks >= nextEggTick) { float maxEggsSize = (pawn.BodySize / 5) * (xxx.has_quirk(pawn, "Incubator") ? 2f : 1f) * (Genital_Helper.has_ovipositorF(pawn) ? 2f : 0.5f); float eggedsize = 0; foreach (var ownEgg in pawn.health.hediffSet.GetHediffs <Hediff_InsectEgg>()) { if (ownEgg.father != null) { eggedsize += ownEgg.father.RaceProps.baseBodySize / 5; } else { eggedsize += ownEgg.implanter.RaceProps.baseBodySize / 5; } } if (RJWSettings.DevMode) { Log.Message($"{xxx.get_pawnname(pawn)} filled with {eggedsize} out of max capacity of {maxEggsSize} eggs."); } if (eggedsize < maxEggsSize) { HediffDef_InsectEgg egg = null; string defname = ""; while (egg == null) { if (defname == "") { if (RJWSettings.DevMode) { Log.Message(" trying to find " + pawn.kindDef.defName + " egg"); } defname = pawn.kindDef.defName; } else { if (RJWSettings.DevMode) { Log.Message(" no " + defname + " egg found, defaulting to Unknown egg"); } defname = "Unknown"; } //Rand.PopState(); //Rand.PushState(RJW_Multiplayer.PredictableSeed()); egg = (from x in DefDatabase <HediffDef_InsectEgg> .AllDefs where x.IsParent(defname) select x) .RandomElement(); } if (RJWSettings.DevMode) { Log.Message("I choose you " + egg + "!"); } var genitals = Genital_Helper.get_genitalsBPR(pawn); if (genitals != null) { var addedEgg = pawn.health.AddHediff(egg, genitals) as Hediff_InsectEgg; addedEgg?.Implanter(pawn); } } // Reset for next egg. ageTicks = 0; nextEggTick = -1; } } } } }
protected override float MtbHours(Pawn pawn) { var base_mtb = xxx.config.comfort_prisoner_rape_mtbh_mul; //Default 4.0 float desire_factor; { var need_sex = pawn.needs.TryGetNeed <Need_Sex>(); if (need_sex != null) { if (need_sex.CurLevel <= need_sex.thresh_frustrated()) { desire_factor = 0.10f; } else if (need_sex.CurLevel <= need_sex.thresh_horny()) { desire_factor = 0.50f; } else { desire_factor = 1.00f; } } else { desire_factor = 1.00f; } } float personality_factor; { personality_factor = 1.0f; if (xxx.has_traits(pawn)) { // Most of the checks are done in the SexAppraiser.would_rape method. personality_factor = 1.0f; if (!RJWSettings.rape_beating) { if (xxx.is_bloodlust(pawn)) { personality_factor *= 0.5f; } } if (xxx.is_nympho(pawn)) { personality_factor *= 0.5f; } else if (xxx.is_prude(pawn) || pawn.story.traits.HasTrait(TraitDefOf.BodyPurist)) { personality_factor *= 2f; } if (xxx.is_rapist(pawn)) { personality_factor *= 0.5f; } if (xxx.is_psychopath(pawn)) { personality_factor *= 0.75f; } else if (xxx.is_kind(pawn)) { personality_factor *= 5.0f; } float rapeCount = pawn.records.GetValue(xxx.CountOfRapedHumanlikes) + pawn.records.GetValue(xxx.CountOfRapedAnimals) + pawn.records.GetValue(xxx.CountOfRapedInsects) + pawn.records.GetValue(xxx.CountOfRapedOthers); // Pawns with few or no rapes are more reluctant to rape CPs. if (rapeCount < 3.0f) { personality_factor *= 1.5f; } } } float fun_factor; { if ((pawn.needs.joy != null) && (xxx.is_rapist(pawn) || xxx.is_psychopath(pawn))) { fun_factor = Mathf.Clamp01(0.50f + pawn.needs.joy.CurLevel); } else { fun_factor = 1.00f; } } float animal_factor = 1.0f; if (xxx.is_animal(pawn)) { var partBPR = Genital_Helper.get_genitalsBPR(pawn); var parts = Genital_Helper.get_PartsHediffList(pawn, partBPR); // Much slower for female animals. animal_factor = (Genital_Helper.has_penis_fertile(pawn, parts) || Genital_Helper.has_penis_infertile(pawn, parts)) ? 2.5f : 6f; } //if (xxx.is_animal(pawn)) { Log.Message("Chance for " + pawn + " : " + base_mtb * desire_factor * personality_factor * fun_factor * animal_factor); } return(base_mtb * desire_factor * personality_factor * fun_factor * animal_factor); }
public static void calculateAndApplySemen(Pawn pawn, Pawn partner, xxx.rjwSextype sextype) { if (!RJWSettings.cum_on_body) { return; } Pawn giver, receiver; //Rand.PopState(); //Rand.PushState(RJW_Multiplayer.PredictableSeed()); List <Hediff> giverparts; var pawnparts = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_genitalsBPR(pawn)); var partnerparts = Genital_Helper.get_PartsHediffList(partner, Genital_Helper.get_genitalsBPR(partner)); //dispenser of the seed if (Genital_Helper.has_penis_fertile(pawn, pawnparts) || xxx.is_mechanoid(pawn) || xxx.is_insect(pawn)) { giver = pawn; giverparts = pawnparts; receiver = partner; } else if (partner != null && (Genital_Helper.has_penis_fertile(partner, partnerparts) || xxx.is_mechanoid(partner) || xxx.is_insect(partner))) { giver = partner; giverparts = partnerparts; receiver = pawn; } else //female on female or genderless - no s***n dispensed; maybe add futa support? { return; } //slimes do not waste fluids? //if (xxx.is_slime(giver)) return; //determine entity: int entityType = SemenHelper.CUM_NORMAL; if (xxx.is_mechanoid(giver)) { entityType = SemenHelper.CUM_MECHA; } else if (xxx.is_insect(giver)) { entityType = SemenHelper.CUM_INSECT; } //get pawn genitalia: BodyPartRecord genitals; if (xxx.is_mechanoid(giver)) { genitals = giver.RaceProps.body.AllParts.Find(x => string.Equals(x.def.defName, "MechGenitals")); } else //insects, animals, humans { genitals = giver.RaceProps.body.AllParts.Find(x => x.def == SemenHelper.genitalsDef); } //no cum without genitals if (genitals == null) { return; } float cumAmount = giver.BodySize; //fallback for mechanoinds and w/e without hediffs float horniness = 1f; float ageScale = Math.Min(80 / SexUtility.ScaleToHumanAge(giver), 1.0f); //calculation lifted from rjw if (xxx.is_mechanoid(giver) && giverparts.NullOrEmpty()) { //use default above } else if (giverparts.NullOrEmpty()) { return; } else { var penisHediff = giverparts.FindAll((Hediff hed) => hed.def.defName.ToLower().Contains("penis")).InRandomOrder().FirstOrDefault(); if (penisHediff == null) { penisHediff = giverparts.FindAll((Hediff hed) => hed.def.defName.ToLower().Contains("ovipositorf")).InRandomOrder().FirstOrDefault(); } if (penisHediff == null) { penisHediff = giverparts.FindAll((Hediff hed) => hed.def.defName.ToLower().Contains("ovipositorm")).InRandomOrder().FirstOrDefault(); } if (penisHediff == null) { penisHediff = giverparts.FindAll((Hediff hed) => hed.def.defName.ToLower().Contains("tentacle")).InRandomOrder().FirstOrDefault(); } if (penisHediff != null) { cumAmount = penisHediff.Severity * giver.BodySize; CompHediffBodyPart chdf = penisHediff.TryGetComp <rjw.CompHediffBodyPart>(); if (chdf != null) { cumAmount = chdf.FluidAmmount * chdf.FluidModifier; } Need sexNeed = giver?.needs?.AllNeeds.Find(x => string.Equals(x.def.defName, "Sex")); if (sexNeed != null) //non-humans don't have it - therefore just use the default value { horniness = 1f - sexNeed.CurLevel; } } else { //something is wrong... v****a? return; } } cumAmount = cumAmount * horniness * ageScale * RJWSettings.cum_on_body_amount_adjust; cumAmount /= 100; //TODO: SemenHelper Autofellatio //if no partner -> masturbation, apply some cum on self: //if (partner == null && sextype == xxx.rjwSextype.Autofellatio) //{ // if (!xxx.is_slime(giver)) // SemenHelper.cumOn(giver, BodyPartDefOf.Jaw, cumAmount, giver); // return; //} if (partner == null && sextype == xxx.rjwSextype.Masturbation) { if (!xxx.is_slime(giver)) { SemenHelper.cumOn(giver, genitals, cumAmount * 0.3f, giver); //pawns are usually not super-messy -> only apply 30% } return; } else if (partner != null) { List <BodyPartRecord> targetParts = new List <BodyPartRecord>(); //which to apply s***n on IEnumerable <BodyPartRecord> availableParts = SemenHelper.getAvailableBodyParts(receiver); BodyPartRecord randomPart; //not always needed switch (sextype) { case rjw.xxx.rjwSextype.Anal: targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == SemenHelper.anusDef)); break; case rjw.xxx.rjwSextype.Boobjob: targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == SemenHelper.chestDef)); break; case rjw.xxx.rjwSextype.DoublePenetration: targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == SemenHelper.anusDef)); targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == SemenHelper.genitalsDef)); break; case rjw.xxx.rjwSextype.Fingering: cumAmount = 0; break; case rjw.xxx.rjwSextype.Fisting: cumAmount = 0; break; case rjw.xxx.rjwSextype.Footjob: //random part: availableParts.TryRandomElement <BodyPartRecord>(out randomPart); targetParts.Add(randomPart); break; case rjw.xxx.rjwSextype.Handjob: //random part: availableParts.TryRandomElement <BodyPartRecord>(out randomPart); targetParts.Add(randomPart); break; case rjw.xxx.rjwSextype.Masturbation: cumAmount *= 2f; break; case rjw.xxx.rjwSextype.MechImplant: //one of the openings: int random = Rand.Range(0, 3); if (random == 0) { targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == SemenHelper.genitalsDef)); } else if (random == 1) { targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == SemenHelper.anusDef)); } else if (random == 2) { targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == BodyPartDefOf.Jaw)); } break; case rjw.xxx.rjwSextype.MutualMasturbation: //random availableParts.TryRandomElement <BodyPartRecord>(out randomPart); targetParts.Add(randomPart); break; case rjw.xxx.rjwSextype.None: cumAmount = 0; break; case rjw.xxx.rjwSextype.Oral: targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == BodyPartDefOf.Jaw)); break; case rjw.xxx.rjwSextype.Scissoring: //I guess if it came to here, a male must be involved? targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == SemenHelper.genitalsDef)); break; case rjw.xxx.rjwSextype.Vaginal: targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == SemenHelper.genitalsDef)); break; } if (cumAmount > 0) { if (xxx.is_slime(receiver)) { //slime absorb cum //this needs balancing, since cumamount ranges 0-10(?) which is fine for cum/hentai but not very realistic for feeding //using TransferNutrition for now //Log.Message("cumAmount " + cumAmount); //float nutrition_amount = cumAmount/10; Need_Food need = need = giver.needs.TryGetNeed <Need_Food>(); if (need == null) { //Log.Message("xxx::TransferNutrition() " + xxx.get_pawnname(pawn) + " doesn't track nutrition in itself, probably shouldn't feed the others"); return; } if (receiver?.needs?.TryGetNeed <Need_Food>() != null) { //Log.Message("xxx::TransferNutrition() " + xxx.get_pawnname(partner) + " can receive"); float nutrition_amount = Math.Min(need.MaxLevel / 15f, need.CurLevel); //body size is taken into account implicitly by need.MaxLevel receiver.needs.food.CurLevel += nutrition_amount; } } else { SemenHelper.cumOn(giver, genitals, cumAmount * 0.3f, giver, entityType); //cum on self - smaller amount foreach (BodyPartRecord bpr in targetParts) { if (bpr != null) { SemenHelper.cumOn(receiver, bpr, cumAmount, giver, entityType); //cum on partner } } } } } }
public static Pawn find_breeder_animal(Pawn pawn, Map m) { DebugText("BreederHelper::find_breeder_animal( " + xxx.get_pawnname(pawn) + " ) called"); float min_fuckability = 0.10f; // Don't rape pawns with <10% fuckability float avg_fuckability = 0f; // Average targets fuckability, choose target higher than that var valid_targets = new Dictionary <Pawn, float>(); // Valid pawns and their fuckability Pawn chosentarget = null; // Final target pawn //Pruning initial pawn list. IEnumerable <Pawn> targets = m.mapPawns.AllPawnsSpawned.Where(x => x != pawn && xxx.is_animal(x) && xxx.can_get_raped(x) && !x.IsForbidden(pawn) && !x.Suspended && !x.HostileTo(pawn) && pawn.CanReserveAndReach(x, PathEndMode.Touch, Danger.Some, max_animals_at_once) //&& SameRace ? pawn.kindDef.race == x.kindDef.race : true ); if (targets.Any()) { var partBPR = Genital_Helper.get_genitalsBPR(pawn); var parts = Genital_Helper.get_PartsHediffList(pawn, partBPR); //filter pawns for female, who can f**k her //not sure if faction check should be but w/e if (!Genital_Helper.has_penis_fertile(pawn, parts) && !Genital_Helper.has_penis_infertile(pawn, parts) && (Genital_Helper.has_vagina(pawn, parts) || Genital_Helper.has_anus(pawn))) { targets = targets.Where(x => xxx.can_fuck(x) && x.Faction == pawn.Faction); } //for humans, animals dont have need - always = 3f //if not horny, seek only targets with safe temp if (xxx.need_some_sex(pawn) < 3.0f) { targets = targets.Where(x => pawn.CanReach(x, PathEndMode.Touch, Danger.None)); } //Used for interspecies animal-on-animal. //Animals will only go for targets they can see. if (xxx.is_animal(pawn)) { targets = targets.Where(x => pawn.CanSee(x) && pawn.def.defName != x.def.defName); } else { // Pickier about the targets if the pawn has no prior experience. if (pawn.records.GetValue(xxx.CountOfSexWithAnimals) < 3 && !xxx.is_zoophile(pawn)) { min_fuckability *= 2f; } if (xxx.is_frustrated(pawn)) { // Less picky when frustrated... min_fuckability *= 0.6f; } else if (!xxx.is_hornyorfrustrated(pawn)) { // ...and far more picky when satisfied. min_fuckability *= 2.5f; } } } DebugText("[RJW]BreederHelper::find_breeder_animal::" + targets.Count() + " targets found on map."); if (!targets.Any()) { return(null); //None found. } foreach (Pawn target in targets) { DebugText("[RJW]BreederHelper::find_breeder_animal::Checking target " + target.kindDef.race.defName.ToLower()); if (!xxx.can_path_to_target(pawn, target.Position)) { continue; // too far } float fuc = SexAppraiser.would_fuck_animal(pawn, target); // 0.0 to ~3.0, orientation checks etc. if (!(fuc > min_fuckability)) { continue; } DebugText("Adding target" + target.kindDef.race.defName.ToLower()); valid_targets.Add(target, fuc); } DebugText(valid_targets.Count() + " valid targets found on map."); //Rand.PopState(); //Rand.PushState(RJW_Multiplayer.PredictableSeed()); if (valid_targets.Any()) { avg_fuckability = valid_targets.Average(x => x.Value); // choose pawns to f**k with above average fuckability var valid_targetsFilteredAnimals = valid_targets.Where(x => x.Value >= avg_fuckability); if (valid_targetsFilteredAnimals.Any()) { chosentarget = valid_targetsFilteredAnimals.RandomElement().Key; } } return(chosentarget); }
public static float would_fuck_animal(Pawn pawn, Pawn target, bool invert_opinion = false, bool ignore_bleeding = false, bool ignore_gender = false) { float wildness_modifier = 1.0f; List <float> size_preference = new List <float>() { pawn.BodySize * 0.75f, pawn.BodySize * 1.6f }; float fuc = would_fuck(pawn, target, invert_opinion, ignore_bleeding, ignore_gender); // 0.0 to ~3.0, orientation checks etc. if (fuc < 0.1f) { // Would not f**k return(0); } if (xxx.has_quirk(pawn, "Teratophile")) { // Teratophiles prefer more 'monstrous' partners. size_preference[0] = pawn.BodySize * 0.8f; size_preference[1] = pawn.BodySize * 2.0f; wildness_modifier = 0.3f; } if (pawn.health.hediffSet.HasHediff(HediffDef.Named("AlcoholHigh"))) { wildness_modifier = 0.5f; //Drunk and making poor judgments. size_preference[1] *= 1.5f; } else if (pawn.health.hediffSet.HasHediff(HediffDef.Named("YayoHigh"))) { wildness_modifier = 0.2f; //This won't end well. size_preference[1] *= 2.5f; } var partBPR = Genital_Helper.get_genitalsBPR(pawn); var parts = Genital_Helper.get_PartsHediffList(pawn, partBPR); if (Genital_Helper.has_vagina(pawn, parts) || Genital_Helper.has_anus(pawn)) { if (!(Genital_Helper.has_penis_fertile(pawn, parts) || Genital_Helper.has_penis_infertile(pawn, parts))) { size_preference[1] = pawn.BodySize * 1.3f; } } if (xxx.is_animal(pawn)) { size_preference[1] = pawn.BodySize * 1.3f; wildness_modifier = 0.4f; } else { if (pawn.story.traits.HasTrait(TraitDefOf.Tough) || pawn.story.traits.HasTrait(TraitDefOf.Brawler)) { size_preference[1] += 0.2f; wildness_modifier -= 0.2f; } else if (pawn.story.traits.HasTrait(TraitDef.Named("Wimp"))) { size_preference[0] -= 0.2f; size_preference[1] -= 0.2f; wildness_modifier += 0.25f; } } float wildness = target.RaceProps.wildness; // 0.0 to 1.0 float petness = target.RaceProps.petness; // 0.0 to 1.0 float distance = pawn.Position.DistanceToSquared(target.Position); //Log.Message("[RJW]would_fuck_animal:: base: " + fuc + ", wildness: " + wildness + ", petness: " + petness + ", distance: " + distance); fuc = fuc + fuc * petness - fuc * wildness * wildness_modifier; if (fuc < 0.1f) { // Would not f**k return(0); } // Adjust by distance, nearby targets preferred. fuc *= 1.0f - Mathf.Max(distance / 10000, 0.1f); // Adjust by size difference. if (target.BodySize < size_preference[0]) { fuc *= Mathf.Lerp(0.1f, size_preference[0], target.BodySize); } else if (target.BodySize > size_preference[1]) { fuc *= Mathf.Lerp(size_preference[1] * 10, size_preference[1], target.BodySize); } if (target.Faction != pawn.Faction) { //Log.Message("[RJW]would_fuck_animal(NT):: base: " + fuc + ", bound1: " + fuc * 0.75f); //Log.Message("[RJW]would_fuck_animal(NT):: base: " + fuc + ", bound2: " + fuc + 0.25f); fuc *= 0.75f; // Less likely to target wild animals. } else if (pawn.relations.DirectRelationExists(PawnRelationDefOf.Bond, target)) { //Log.Message("[RJW]would_fuck_animal(T):: base: " + fuc + ", bound1: " + fuc * 1.25f); //Log.Message("[RJW]would_fuck_animal(T):: base: " + fuc + ", bound2: " + fuc + 0.25f); fuc *= 1.25f; // Bonded animals preferred. } return(fuc); }