///<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); }
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); } }
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); }
//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 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); }
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 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 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); }