/// <summary> /// operation - move part data from thing to hediff /// </summary> public static Hediff recipePartAdder(RecipeDef recipe, Pawn pawn, BodyPartRecord part, List <Thing> ingredients) { Hediff hd = HediffMaker.MakeHediff(recipe.addsHediff, pawn, part); Thing thing = ingredients.Find(x => x.def.defName == recipe.addsHediff.defName); CompThingBodyPart CompThing = thing.TryGetComp <rjw.CompThingBodyPart>(); CompHediffBodyPart CompHediff = hd.TryGetComp <rjw.CompHediffBodyPart>(); if (CompHediff != null && CompThing != null) { if (CompThing.SizeBase > 0) { CompHediff.FluidType = CompThing.FluidType; CompHediff.FluidAmmount = CompThing.FluidAmmount; CompHediff.FluidModifier = CompThing.FluidModifier; CompHediff.SizeBase = CompThing.SizeBase; CompHediff.SizeOwner = CompThing.SizeOwner; CompHediff.RaceOwner = CompThing.RaceOwner; CompHediff.PreviousOwner = CompThing.PreviousOwner; CompHediff.Eggs = CompThing.Eggs; CompHediff.updatesize(); } else //not initialised things, drop pods, trader? //TODO: figure out how to populate rjw parts at gen { hd = MakePart(hd.def, pawn, part); } } return(hd); }
public void InitComp(Pawn pawn = null) { var def = DefDatabase <HediffDef> .GetNamed(parent.def.defName); //pick random pawn to create temp hediff pawn = PawnsFinder.AllMaps_FreeColonistsAndPrisonersSpawned.RandomElement(); //pawn = PawnsFinder.All_AliveOrDead.RandomElement(); //TODO: maybe some day add immobilizing size? Hediff hd = HediffMaker.MakeHediff(def, pawn); CompHediffBodyPart CompHediff = hd.TryGetComp <CompHediffBodyPart>(); if (CompHediff != null) { CompHediff.initComp(pawn); CompHediff.updatesize(); FluidType = CompHediff.FluidType; FluidAmmount = CompHediff.FluidAmmount; FluidModifier = CompHediff.FluidModifier; Size = CompHediff.Size; SizeBase = CompHediff.SizeBase; SizeOwner = CompHediff.SizeOwner; RaceOwner = "Unknown"; PreviousOwner = "Unknown"; Eggs = CompHediff.Eggs; } }
public override void PostAdd(DamageInfo?dinfo) { foreach (Hediff hed in pawn.health.hediffSet.hediffs.Where(x => x.Part != null && x.Part == Part && (x is Hediff_PartBaseNatural || x is Hediff_PartBaseArtifical)).ToList()) { CompHediffBodyPart CompHediff = hed.TryGetComp <rjw.CompHediffBodyPart>(); if (CompHediff != null) { CompHediff.SizeBase = this.def.initialSeverity; CompHediff.initComp(reroll: true); CompHediff.updatesize(); } } pawn.health.RemoveHediff(this); }
/// <summary> /// generate part hediff /// </summary> public static Hediff MakePart(HediffDef def, Pawn pawn, BodyPartRecord bpr) { //Log.Message("SexPartAdder::PartMaker ( " + xxx.get_pawnname(pawn) + " ) " + def.defName); Hediff hd = HediffMaker.MakeHediff(def, pawn, bpr); //Log.Message("SexPartAdder::PartMaker ( " + xxx.get_pawnname(pawn) + " ) " + hd.def.defName); CompHediffBodyPart compHediff = hd.TryGetComp <CompHediffBodyPart>(); if (compHediff != null) { //Log.Message("SexPartAdder::PartMaker init comps"); compHediff.initComp(pawn); compHediff.updatesize(); } return(hd); }
/// <summary> /// operation - move part data from hediff to thing /// </summary> public static Thing recipePartRemover(Hediff hd) { Thing thing = ThingMaker.MakeThing(hd.def.spawnThingOnRemoved); CompThingBodyPart CompThing = thing.TryGetComp <rjw.CompThingBodyPart>(); CompHediffBodyPart CompHediff = hd.TryGetComp <rjw.CompHediffBodyPart>(); if (CompThing != null && CompHediff != null) { CompThing.FluidType = CompHediff.FluidType; CompThing.FluidAmmount = CompHediff.FluidAmmount; CompThing.FluidModifier = CompHediff.FluidModifier; CompThing.Size = CompHediff.Size; CompThing.SizeBase = CompHediff.SizeBase; CompThing.SizeOwner = CompHediff.SizeOwner; CompThing.RaceOwner = CompHediff.RaceOwner; CompThing.PreviousOwner = xxx.get_pawnname(CompHediff.Pawn); CompThing.Eggs = CompHediff.Eggs; } return(thing); }
public override void PostAdd(DamageInfo?dinfo) { foreach (Hediff hed in pawn.health.hediffSet.hediffs.Where(x => x.Part != null && x.Part == Part && (x is Hediff_PartBaseNatural || x is Hediff_PartBaseArtifical)).ToList()) { CompHediffBodyPart CompHediff = hed.TryGetComp <rjw.CompHediffBodyPart>(); if (CompHediff != null) { //Log.Message(" Hediff_PartsSizeChanger: " + hed.Label); //Log.Message(" Hediff_PartsSizeChanger: " + hed.Severity); //Log.Message(" Hediff_PartsSizeChanger: " + CompHediff.SizeBase); //Log.Message(" Hediff_PartsSizeChanger: " + "-----"); //Log.Message(" Hediff_PartsSizeChanger: " + this.Label); //Log.Message(" Hediff_PartsSizeChanger: " + this.Severity); CompHediff.SizeBase = this.CurStage.minSeverity; CompHediff.initComp(reroll: true); CompHediff.updatesize(); //Log.Message(" Hediff_PartsSizeChanger: " + "-----"); //Log.Message(" Hediff_PartsSizeChanger: " + hed.Label); //Log.Message(" Hediff_PartsSizeChanger: " + hed.Severity); //Log.Message(" Hediff_PartsSizeChanger: " + CompHediff.SizeBase); } } pawn.health.RemoveHediff(this); }
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 } } } } } }