예제 #1
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
                }
            }
        }
예제 #6
0
        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);
        }
예제 #7
0
        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);
                }
            }
        }
예제 #8
0
        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);
        }
예제 #9
0
        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);
            }
        }
예제 #10
0
        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);
        }
예제 #11
0
        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);
            }
        }
예제 #12
0
        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);
        }
예제 #17
0
        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;
                        }
                    }
                }
            }
        }
예제 #18
0
        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);
        }
예제 #19
0
        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
                            }
                        }
                    }
                }
            }
        }
예제 #20
0
        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);
        }
예제 #21
0
        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);
        }