static void Addsemen(Pawn pawn)
        {
            //Log.Message("add s***n button is pressed for " + pawn);

            if (!pawn.Dead && pawn.records != null)
            {
                //get all acceptable body parts:
                IEnumerable <BodyPartRecord> filteredParts = SemenHelper.getAvailableBodyParts(pawn);

                //select random part:
                BodyPartRecord randomPart;
                //filteredParts.TryRandomElement<BodyPartRecord>(out randomPart);
                //for testing - choose either genitals or anus:
                //Rand.PopState();
                //Rand.PushState(RJW_Multiplayer.PredictableSeed());
                if (Rand.Value > 0.5f)
                {
                    randomPart = pawn.RaceProps.body.AllParts.Find(x => x.def == xxx.anusDef);
                }
                else
                {
                    randomPart = pawn.RaceProps.body.AllParts.Find(x => x.def == xxx.genitalsDef);
                }

                if (randomPart != null)
                {
                    SemenHelper.cumOn(pawn, randomPart, 0.2f, null, SemenHelper.CUM_NORMAL);
                }
            }
            ;
        }
Ejemplo n.º 2
0
        public override bool TryMergeWith(Hediff other)
        {
            //if a new S***n hediff is added to the same body part, they are combined. if severity reaches more than 1, spillover to other body parts occurs

            Hediff_Semen hediff_Semen = other as Hediff_Semen;

            if (hediff_Semen != null && hediff_Semen.def == this.def && hediff_Semen.Part == base.Part && this.def.injuryProps.canMerge)
            {
                semenType = hediff_Semen.semenType;                //take over new creature color

                float totalAmount = hediff_Semen.Severity + this.Severity;
                if (totalAmount > 1.0f)
                {
                    BodyPartDef spillOverTo = SemenHelper.spillover(this.Part.def);                    //SemenHelper saves valid other body parts for spillover
                    if (spillOverTo != null)
                    {
                        //Rand.PopState();
                        //Rand.PushState(RJW_Multiplayer.PredictableSeed());
                        IEnumerable <BodyPartRecord> availableParts = SemenHelper.getAvailableBodyParts(pawn);           //gets all non missing, valid body parts
                        IEnumerable <BodyPartRecord> filteredParts  = availableParts.Where(x => x.def == spillOverTo);   //filters again for valid spill target
                        BodyPartRecord spillPart = filteredParts.RandomElement <BodyPartRecord>();                       //then pick one
                        if (spillPart != null)
                        {
                            SemenHelper.cumOn(pawn, spillPart, totalAmount - this.Severity, null, semenType);
                        }
                    }
                }

                return(base.TryMergeWith(other));
            }
            return(false);
        }
Ejemplo n.º 3
0
        //get valid body parts for a specific pawn
        public static IEnumerable <BodyPartRecord> getAvailableBodyParts(Pawn pawn)
        {
            //get all non-missing body parts:
            IEnumerable <BodyPartRecord> bodyParts = pawn.health.hediffSet.GetNotMissingParts(BodyPartHeight.Undefined, BodyPartDepth.Outside, null, null);
            BodyPartRecord anus = pawn.def.race.body.AllParts.Find(bpr => string.Equals(bpr.def.defName, "Anus"));            //not found by above function since depth is "inside"

            if (anus != null)
            {
                bodyParts = bodyParts.Add(anus);
            }

            //filter for allowed body parts (e.g. no single fingers/toes):
            List <BodyPartDef> filterParts = SemenHelper.getAllowedBodyParts();

            IEnumerable <BodyPartRecord> filteredParts = bodyParts.Where(item1 => filterParts.Any(item2 => item2.Equals(item1.def)));

            return(filteredParts);
        }
Ejemplo n.º 4
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());

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