public SexProps(Pawn pawn, Pawn partner, xxx.rjwSextype sexType, bool violent) { Pawn = pawn; Partner = partner; SexType = sexType; Violent = violent; }
/// <summary> /// Harmony postfix method for SexUtility.ProcessSex. It calculates and applies damage and other effects /// </summary> /// <param name="pawn">Pawn 1 (rapist, w***e etc.)</param> /// <param name="partner">Pawn 2 (victim, client etc.)</param> /// <param name="rape">True if it's a non-consensual sex</param> /// <param name="sextype">Sex type (only Vaginal, Anal and Double Penetration are supported ATM)</param> public static void SexUtility_Prefix(Pawn pawn, Pawn partner, bool rape, xxx.rjwSextype sextype) { Log("* Initiator *"); LogPawnData(pawn); Log("* Partner *"); LogPawnData(partner); PenetrationUtility.ProcessPenetrations(pawn, partner, rape, sextype); }
public static int CountSatisfiedQuirks(Pawn pawn, Pawn partner, xxx.rjwSextype sexType, bool violent) { var props = new SexProps(pawn, partner, sexType, violent); var satisfies = All.Where(quirk => quirk.SexSatisfiesFunc != null && pawn.Has(quirk) && quirk.SexSatisfiesFunc(props)); return(satisfies.Count()); }
/// <summary> /// This method discovers all penetrations in the sex act and applies respective damage /// </summary> /// <param name="p1"></param> /// <param name="p2"></param> /// <param name="rape"></param> /// <param name="sextype"></param> /// <returns>Empty list if no eligible penetrations found, or an element for each penetration (can be DP etc.)</returns> public static void ProcessPenetrations(Pawn p1, Pawn p2, bool rape, xxx.rjwSextype sextype) { Dyspareunia.Log("Checking " + sextype + (rape ? " rape" : " sex") + " between " + p1.Label + " and " + p2.Label + "."); switch (sextype) { case xxx.rjwSextype.Vaginal: if (Dyspareunia.HasPenetratingOrgan(p1) && Genital_Helper.has_vagina(p2)) { ApplyDamage(Genital_Helper.get_penis_all(p1), Dyspareunia.GetVagina(p2), rape); } else { ApplyDamage(Genital_Helper.get_penis_all(p2), Dyspareunia.GetVagina(p1), false); } break; case xxx.rjwSextype.Anal: if (Dyspareunia.HasPenetratingOrgan(p1) && Genital_Helper.has_anus(p2)) { ApplyDamage(Genital_Helper.get_penis_all(p1), Dyspareunia.GetAnus(p2), rape); } else { ApplyDamage(Genital_Helper.get_penis_all(p2), Dyspareunia.GetAnus(p1), false); } break; case xxx.rjwSextype.Oral: // Oral penetration not supported ATM break; case xxx.rjwSextype.DoublePenetration: if (Genital_Helper.has_multipenis(p1) && Genital_Helper.has_vagina(p2) && Genital_Helper.has_anus(p2)) { ApplyDamage(Genital_Helper.get_penis_all(p1), Dyspareunia.GetVagina(p2), rape); ApplyDamage(Genital_Helper.get_penis_all(p1), Dyspareunia.GetAnus(p2), rape); } else { ApplyDamage(Genital_Helper.get_penis_all(p2), Dyspareunia.GetVagina(p1), false); ApplyDamage(Genital_Helper.get_penis_all(p2), Dyspareunia.GetAnus(p1), false); } break; case xxx.rjwSextype.Fingering: if (Genital_Helper.has_vagina(p2) || Genital_Helper.has_anus(p2)) { ApplyDamage(p1, GetFingerSize(p1), Dyspareunia.GetVagina(p2) ?? Dyspareunia.GetAnus(p2), rape); } else { ApplyDamage(p2, GetFingerSize(p2), Dyspareunia.GetVagina(p1) ?? Dyspareunia.GetAnus(p1), false); } break; case xxx.rjwSextype.Fisting: if (Genital_Helper.has_vagina(p2) || Genital_Helper.has_anus(p2)) { ApplyDamage(p1, GetHandSize(p1), Dyspareunia.GetVagina(p2) ?? Dyspareunia.GetAnus(p2), rape); } else { ApplyDamage(p2, GetHandSize(p2), Dyspareunia.GetVagina(p1) ?? Dyspareunia.GetAnus(p1), false); } break; case xxx.rjwSextype.MechImplant: Dyspareunia.Log("Processing mech implant sex between " + p1.Label + " and " + p2.Label); if (p1.kindDef.race.defName.ContainsAny("Mech_Centipede", "Mech_Lancer", "Mech_Scyther", "Mech_Crawler", "Mech_Skullywag", "Mech_Flamebot", "Mech_Mammoth", "Mech_Assaulter")) { ApplyDamage(p1, p1.BodySize, Dyspareunia.GetVagina(p2) ?? Dyspareunia.GetAnus(p2), rape); } else { ApplyDamage(p2, p2.BodySize, Dyspareunia.GetVagina(p1) ?? Dyspareunia.GetAnus(p1), false); } break; } }
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()); //dispenser of the seed if (Genital_Helper.has_penis(pawn) || xxx.is_mechanoid(pawn) || xxx.is_insect(pawn)) { giver = pawn; receiver = partner; } else if (partner != null && (Genital_Helper.has_penis(partner) || xxx.is_mechanoid(partner) || xxx.is_insect(partner))) { giver = partner; 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; } //calculate s***n amount: Need sexNeed = giver.needs.AllNeeds.Find(x => string.Equals(x.def.defName, "Sex")); float horniness = 1f; if (sexNeed != null) //non-humans don't have it - therefore just use the default value { horniness = 1f - sexNeed.CurLevel; } float ageScale = Math.Min(80 / SexUtility.ScaleToHumanAge(giver), 1.0f); //calculation lifted from rjw float cumAmount = horniness * giver.BodySize * ageScale * RJWSettings.cum_on_body_amount_adjust; ; if (xxx.has_quirk(giver, "Messy")) { cumAmount *= 1.5f; } //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 } } } } } }
///<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.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.health.hediffSet.HasHediff(HediffDef.Named("RJW_pregnancy")) || f****d.health.hediffSet.HasHediff(HediffDef.Named("RJW_pregnancy_beast")) || f****d.health.hediffSet.HasHediff(HediffDef.Named("Pregnant"))) { 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); } if (!(Genital_Helper.has_penis(f****r) && Genital_Helper.has_vagina(f****d)) && !(Genital_Helper.has_penis(f****d) && Genital_Helper.has_vagina(f****r))) { 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"); } //new pregnancy Hediff_MechanoidPregnancy.Create(partner, pawn); Hediff_MechanoidPregnancy hediff = (Hediff_MechanoidPregnancy)partner.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy_mech")); if (RJWSettings.DevMode) { Log.Message("[RJW] removing other pregnancies"); } if (partner.health.hediffSet.HasHediff(HediffDef.Named("RJW_pregnancy"))) { partner.health.RemoveHediff(partner.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy"))); } if (partner.health.hediffSet.HasHediff(HediffDef.Named("RJW_pregnancy_beast"))) { partner.health.RemoveHediff(partner.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("RJW_pregnancy_beast"))); } if (partner.health.hediffSet.HasHediff(HediffDef.Named("Pregnant"))) { partner.health.RemoveHediff(partner.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("Pregnant"))); } 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) if (Genital_Helper.has_vagina(partner) && (Genital_Helper.has_ovipositorF(pawn) || (Genital_Helper.has_ovipositorM(pawn) || (Genital_Helper.has_penis(pawn) && 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) && (Genital_Helper.has_ovipositorF(partner) || (Genital_Helper.has_ovipositorM(partner) || (Genital_Helper.has_penis(partner) && 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(pawn) && Genital_Helper.has_vagina(partner) && 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) && Genital_Helper.has_penis(partner) && CanImpregnate(partner, pawn, sextype)) { if (RJWSettings.DevMode) { Log.Message(" impregnate reverse"); } Doimpregnate(partner, pawn); } }
public static bool Prefix(SexProps props) { xxx.rjwSextype sextype = props.sexType; Pawn pawn = props.pawn; Pawn partner = props.partner; if (sextype == xxx.rjwSextype.Vaginal) { var pawnpartBPR = Genital_Helper.get_genitalsBPR(pawn); var maleparts = Genital_Helper.get_PartsHediffList(pawn, pawnpartBPR); var partnerpartBPR = Genital_Helper.get_genitalsBPR(partner); var femaleparts = Genital_Helper.get_PartsHediffList(partner, partnerpartBPR); Pawn female = null, male = null; if (Genital_Helper.has_vagina(partner, femaleparts)) { female = partner; male = pawn; } else if (Genital_Helper.has_vagina(pawn, maleparts)) { female = pawn; femaleparts = maleparts; male = partner; maleparts = Genital_Helper.get_PartsHediffList(partner, partnerpartBPR); } else { return(true); } if (female.IsAnimal() && !Configurations.EnableAnimalCycle) { return(true); } HediffComp_Menstruation comp = female.GetMenstruationComp(); if (comp != null) { if (Genital_Helper.has_penis_fertile(male, maleparts) && PregnancyHelper.CanImpregnate(male, female, sextype)) { PregnancyHelper.Doimpregnate(male, female); return(false); } else if (Genital_Helper.has_ovipositorM(male, maleparts)) { comp.CumIn(male, Rand.Range(0.5f, 3.0f) * RJWSettings.cum_on_body_amount_adjust * male.BodySize, 1.0f); } else { comp.CumIn(male, male.GetCumVolume(maleparts), 0); } } //if (Genital_Helper.has_vagina(partner, partnerparts)) //{ // if (partner.IsAnimal() && !Configurations.EnableAnimalCycle) return true; // HediffComp_Menstruation comp = Utility.GetMenstruationComp(partner); // if (comp != null) // { // if (Genital_Helper.has_penis_fertile(pawn, pawnparts) && PregnancyHelper.CanImpregnate(pawn, partner, sextype)) // { // PregnancyHelper.Doimpregnate(pawn, partner); // return false; // } // else comp.CumIn(pawn, pawn.GetCumVolume(), 0); // } //} //else if (Genital_Helper.has_vagina(pawn, pawnparts)) //{ // if (pawn.IsAnimal() && !Configurations.EnableAnimalCycle) return true; // HediffComp_Menstruation comp = Utility.GetMenstruationComp(pawn); // if (comp != null) // { // if (Genital_Helper.has_penis_fertile(partner, partnerparts) && PregnancyHelper.CanImpregnate(partner, pawn, sextype)) // { // PregnancyHelper.Doimpregnate(partner, pawn); // return false; // } // else comp.CumIn(partner, partner.GetCumVolume(), 0); // } //} } return(true); }