private bool DoesTargetPawnAcceptAdvance() { //if (xxx.config.always_accept_whores) // return true; //Log.Message("[RJW]JobDriver_InvitingVisitors::DoesTargetPawnAcceptAdvance() is called"); if (PawnUtility.EnemiesAreNearby(TargetPawn)) { //Log.Message("[RJW]JobDriver_InvitingVisitors::DoesTargetPawnAcceptAdvance() fail - enemy near"); return(false); } if (!allowedJobs.Contains(TargetPawn.jobs.curJob.def)) { //Log.Message("[RJW]JobDriver_InvitingVisitors::DoesTargetPawnAcceptAdvance() fail - not allowed job"); return(false); } //Log.Message("Will try " + WhoringHelper.WillPawnTryHookup(TargetPawn)); //Log.Message("Appeal " + WhoringHelper.IsHookupAppealing(TargetPawn, W***e)); //Log.Message("Afford " + WhoringHelper.CanAfford(TargetPawn, W***e)); //Log.Message("Need sex " + (xxx.need_some_sex(TargetPawn) >= 1)); W***e.skills.Learn(SkillDefOf.Social, 1.2f); return(WhoringHelper.WillPawnTryHookup(TargetPawn) && WhoringHelper.IsHookupAppealing(TargetPawn, W***e) && WhoringHelper.CanAfford(TargetPawn, W***e) && xxx.need_some_sex(TargetPawn) >= 1f); }
static string DrawWhoring(Pawn pawn, Rect row) { string price; if (pawn.ageTracker.AgeBiologicalYears < RJWSettings.sex_minimum_age) { price = "Inapplicable (too young)"; } else if (pawn.ownership.OwnedRoom == null) { if (Current.ProgramState == ProgramState.Playing) { price = WhoringHelper.WhoreMinPrice(pawn) + " - " + WhoringHelper.WhoreMaxPrice(pawn) + " (base, needs suitable bedroom)"; } else { price = WhoringHelper.WhoreMinPrice(pawn) + " - " + WhoringHelper.WhoreMaxPrice(pawn) + " (base, modified by bedroom quality)"; } } else if (xxx.is_animal(pawn)) { price = "Incapable of whoring"; } else { price = WhoringHelper.WhoreMinPrice(pawn) + " - " + WhoringHelper.WhoreMaxPrice(pawn); } Widgets.Label(row, "WhorePrice".Translate() + price); if (Mouse.IsOver(row)) { Widgets.DrawHighlight(row); } return(price); }
private bool DoesTargetPawnAcceptAdvance() { if (RJWSettings.DebugWhoring) { Log.Message($"JobDriver_InvitingVisitors::DoesTargetPawnAcceptAdvance() - {xxx.get_pawnname(TargetPawn)}"); } //if (RJWSettings.WildMode) return true; if (PawnUtility.EnemiesAreNearby(TargetPawn)) { if (RJWSettings.DebugWhoring) { Log.Message($" fail - enemy near"); } return(false); } if (!allowedJobs.Contains(TargetPawn.jobs.curJob.def)) { if (RJWSettings.DebugWhoring) { Log.Message($" fail - not allowed job"); } return(false); } if (RJWSettings.DebugWhoring) { Log.Message("Will try hookup " + WhoringHelper.WillPawnTryHookup(TargetPawn)); Log.Message("Is w***e appealing " + WhoringHelper.IsHookupAppealing(TargetPawn, W***e)); Log.Message("Can afford w***e " + WhoringHelper.CanAfford(TargetPawn, W***e)); Log.Message("Need sex " + (xxx.need_some_sex(TargetPawn) >= 1)); } if (WhoringHelper.WillPawnTryHookup(TargetPawn) && WhoringHelper.IsHookupAppealing(TargetPawn, W***e) && WhoringHelper.CanAfford(TargetPawn, W***e) && xxx.need_some_sex(TargetPawn) >= 1f) { W***e.skills.Learn(SkillDefOf.Social, 1.2f); return(true); } return(false); }
internal bool RelationCheckPass(Pawn client) { //Rand.PopState(); //Rand.PushState(RJW_Multiplayer.PredictableSeed()); if (xxx.isSingleOrPartnerNotHere(client) || xxx.is_lecher(client) || Rand.Value < 0.9f) { if (client != LovePartnerRelationUtility.ExistingLovePartner(w***e)) { //Exception for prisoners to account for PrisonerWhoreSexualEmergencyTree, which allows prisoners to try to hook up with anyone who's around (mostly other prisoners or warden) return((client != w***e) & (client.Map == w***e.Map) && (client.Faction == w***e.Faction || w***e.IsPrisoner) && (client.IsColonist || w***e.IsPrisoner) && WhoringHelper.IsHookupAppealing(w***e, client)); } } return(false); }
public static Pawn FindAttractivePawn(Pawn w***e, out int price) { price = 0; if (w***e == null || xxx.is_asexual(w***e)) { if (RJWSettings.DebugWhoring) { Log.Message($" {xxx.get_pawnname(w***e)} is asexual, abort"); } return(null); } //Rand.PopState(); //Rand.PushState(RJW_Multiplayer.PredictableSeed()); FindAttractivePawnHelper client = new FindAttractivePawnHelper { w***e = w***e }; price = WhoringHelper.PriceOfWhore(w***e); int priceOfWhore = price; IntVec3 pos = w***e.Position; IEnumerable <Pawn> potentialClients = w***e.Map.mapPawns.AllPawnsSpawned; potentialClients = potentialClients.Where(x => x != w***e && !x.IsForbidden(w***e) && !x.HostileTo(w***e) && !x.IsPrisoner && x.Position.DistanceTo(pos) < 100 && w***e.CanReserveAndReach(x, PathEndMode.ClosestTouch, Danger.Some, 1) && xxx.is_healthy_enough(x)); potentialClients = potentialClients.Except(potentialClients.Where(client.TraitCheckFail)); if (!potentialClients.Any()) { return(null); } if (RJWSettings.DebugWhoring) { Log.Message($" FindAttractivePawn number of all potential clients {potentialClients.Count()}"); } List <Pawn> valid_targets = new List <Pawn>(); foreach (Pawn target in potentialClients) { if (xxx.can_path_to_target(w***e, target.Position)) { valid_targets.Add(target); } } IEnumerable <Pawn> guestsSpawned = valid_targets.Where(x => x.Faction != w***e.Faction && WhoringHelper.CanAfford(x, w***e, priceOfWhore) && !MemoryChecker(x, ThoughtDef.Named("RJWFailedSolicitation")) && x != LovePartnerRelationUtility.ExistingLovePartner(w***e)); if (guestsSpawned.Any()) { if (RJWSettings.DebugWhoring) { Log.Message($" FindAttractivePawn number of all acceptable Guests {guestsSpawned.Count()}"); } return(guestsSpawned.RandomElement()); } return(null); //use casual sex for colonist hooking if (RJWSettings.DebugWhoring) { Log.Message($" FindAttractivePawn found no guests, trying colonists"); } if (!WhoringHelper.WillPawnTryHookup(w***e)) // will hookup colonists? { return(null); } IEnumerable <Pawn> freeColonists = valid_targets.Where(x => x.Faction == w***e.Faction && Roll_to_skip(x, w***e)); if (RJWSettings.DebugWhoring) { Log.Message($" FindAttractivePawn number of free colonists {freeColonists.Count()}"); } freeColonists = freeColonists.Where(x => client.RelationCheckPass(x) && !MemoryChecker(x, ThoughtDef.Named("RJWTurnedDownWhore"))); if (freeColonists.Any()) { if (RJWSettings.DebugWhoring) { Log.Message($" FindAttractivePawn number of all acceptable Colonists {freeColonists.Count()}"); } return(freeColonists.RandomElement()); } return(null); }
protected override IEnumerable <Toil> MakeNewToils() { //Log.Message("[RJW]JobDriver_WhoreIsServingVisitors::MakeNewToils() - making toils"); this.FailOnDespawnedOrNull(PartnerInd); this.FailOnDespawnedNullOrForbidden(BedInd); //Log.Message("[RJW]JobDriver_WhoreIsServingVisitors::MakeNewToils() fail conditions check " + (Actor is null) + " " + !xxx.CanUse(Actor, Bed) + " " + !Actor.CanReserve(Partner)); this.FailOn(() => Actor is null || !xxx.CanUse(Actor, Bed) || !Actor.CanReserve(Partner)); this.FailOn(() => pawn.Drafted); int price = WhoringHelper.PriceOfWhore(Actor); yield return(Toils_Reserve.Reserve(PartnerInd, 1, 0)); //yield return Toils_Reserve.Reserve(BedInd, Bed.SleepingSlotsCount, 0); bool partnerHasPenis = Genital_Helper.has_penis(Partner) || Genital_Helper.has_penis_infertile(Partner); Toil gotoWhoreBed = new Toil { initAction = delegate { //Log.Message("[RJW]JobDriver_WhoreIsServingVisitors::MakeNewToils() - gotoWhoreBed initAction is called"); Actor.pather.StartPath(WhoreSleepSpot, PathEndMode.OnCell); Partner.jobs.StopAll(); Partner.pather.StartPath(WhoreSleepSpot, PathEndMode.Touch); }, tickAction = delegate { if (Partner.IsHashIntervalTick(150)) { Partner.pather.StartPath(Actor, PathEndMode.Touch); //Log.Message(xxx.get_pawnname(Partner) + ": I'm following the w***e"); } }, defaultCompleteMode = ToilCompleteMode.PatherArrival }; gotoWhoreBed.FailOnWhorebedNoLongerUsable(BedInd, Bed); yield return(gotoWhoreBed); Toil waitInBed = new Toil { initAction = delegate { //Rand.PopState(); //Rand.PushState(RJW_Multiplayer.PredictableSeed()); //Log.Message("JobDriver_WhoreIsServingVisitors::MakeNewToils() - waitInBed, initAction is called"); ticksLeftThisToil = 5000; ticks_left = (int)(2000.0f * Rand.Range(0.30f, 1.30f)); //Actor.pather.StopDead(); //Let's just make w****s standing at the bed //JobDriver curDriver = Actor.jobs.curDriver; //curDriver.layingDown = LayingDownState.LayingInBed; //curDriver.asleep = false; var gettin_loved = new Job(xxx.gettin_loved, Actor, Bed); Partner.jobs.StartJob(gettin_loved, JobCondition.InterruptForced); }, tickAction = delegate { Actor.GainComfortFromCellIfPossible(); if (IsInOrByBed(Bed, Partner)) { //Log.Message("JobDriver_WhoreIsServingVisitors::MakeNewToils() - waitInBed, tickAction pass"); ticksLeftThisToil = 0; } }, defaultCompleteMode = ToilCompleteMode.Delay, }; waitInBed.FailOn(() => pawn.GetRoom() == null); yield return(waitInBed); bool canAfford = WhoringHelper.CanAfford(Partner, Actor, price); if (canAfford) { Toil loveToil = new Toil { initAction = delegate { //Actor.jobs.curDriver.ticksLeftThisToil = 1200; //Using ticks_left to control the time of sex //--Log.Message("JobDriver_WhoreIsServingVisitors::MakeNewToils() - loveToil, setting initAction"); /* * //Hoge: W***e is just work. no feel cheatedOnMe. * if (xxx.HasNonPolyPartner(Actor)) * { * Pawn pawn = LovePartnerRelationUtility.ExistingLovePartner(Actor); * if (((Partner != pawn) && !pawn.Dead) && ((pawn.Map == Actor.Map) || (Rand.Value < 0.15))) * { * pawn.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.CheatedOnMe, Actor); * } * } */ if (xxx.HasNonPolyPartnerOnCurrentMap(Partner)) { Pawn lover = LovePartnerRelationUtility.ExistingLovePartner(Partner); //Rand.PopState(); //Rand.PushState(RJW_Multiplayer.PredictableSeed()); // We have to do a few other checks because the pawn might have multiple lovers and ExistingLovePartner() might return the wrong one if (lover != null && Actor != lover && !lover.Dead && (lover.Map == Partner.Map || Rand.Value < 0.25)) { lover.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.CheatedOnMe, Partner); } } if (!partnerHasPenis) { Actor.rotationTracker.Face(Partner.DrawPos); } }, defaultCompleteMode = ToilCompleteMode.Never, //Changed from Delay }; loveToil.AddPreTickAction(delegate { //Actor.Reserve(Partner, 1, 0); --ticks_left; xxx.reduce_rest(Partner); xxx.reduce_rest(Actor, 2); if (ticks_left <= 0) { ReadyForNextToil(); } else if (pawn.IsHashIntervalTick(ticks_between_hearts)) { MoteMaker.ThrowMetaIcon(Actor.Position, Actor.Map, ThingDefOf.Mote_Heart); } Actor.GainComfortFromCellIfPossible(); Partner.GainComfortFromCellIfPossible(); }); loveToil.AddFinishAction(delegate { //Log.Message("[RJW] JobDriver_WhoreIsServingVisitors::MakeNewToils() - finished loveToil"); //// Trying to add some interactions and social logs //xxx.processAnalSex(Partner, Actor, ref isAnalSex, partnerHasPenis); }); loveToil.AddFailCondition(() => Partner.Dead || !IsInOrByBed(Bed, Partner)); loveToil.socialMode = RandomSocialMode.Off; yield return(loveToil); Toil afterSex = new Toil { initAction = delegate { // Adding interactions, social logs, etc SexUtility.ProcessSex(Actor, Partner, false, false, true); //--Log.Message("JobDriver_WhoreIsServingVisitors::MakeNewToils() - Partner should pay the price now in afterSex.initAction"); int remainPrice = WhoringHelper.PayPriceToWhore(Partner, price, Actor); /*if (remainPrice <= 0) * { * --Log.Message("JobDriver_WhoreIsServingVisitors::MakeNewToils() - Paying price is success"); * } * else * { * --Log.Message("JobDriver_WhoreIsServingVisitors::MakeNewToils() - Paying price failed"); * }*/ xxx.UpdateRecords(Actor, price - remainPrice); var thought = (Actor.IsPrisoner) ? thought_captive : thought_free; pawn.needs.mood.thoughts.memories.TryGainMemory(thought); if (SexUtility.ConsiderCleaning(pawn)) { LocalTargetInfo cum = pawn.PositionHeld.GetFirstThing <Filth>(pawn.Map); Job clean = new Job(JobDefOf.Clean); clean.AddQueuedTarget(TargetIndex.A, cum); pawn.jobs.jobQueue.EnqueueFirst(clean); } }, defaultCompleteMode = ToilCompleteMode.Instant }; yield return(afterSex); } }
public void SexualityCard(Rect rect, Pawn pawn) { CompRJW comp = pawn.TryGetComp <CompRJW>(); if (pawn == null || comp == null) { return; } Text.Font = GameFont.Medium; Rect rect1 = new Rect(8f, 4f, rect.width - 8f, rect.height - 20f); Widgets.Label(rect1, "RJW"); //rjw Text.Font = GameFont.Tiny; float num = rect1.y + 40f; Rect row1 = new Rect(10f, num, rect.width - 8f, 24f); //sexuality Rect row2 = new Rect(10f, num + 24, rect.width - 8f, 24f); //quirks Rect row3 = new Rect(10f, num + 48, rect.width - 8f, 24f); //w***e price //Rect sexuality_button = new Rect(10f, rect1.height - 0f, rect.width - 8f, 24f);//change sex pref Rect button1 = new Rect(10f, rect1.height - 10f, rect.width - 8f, 24f); //re sexualize Rect button2 = new Rect(10f, rect1.height - 34f, rect.width - 8f, 24f); //archtech toggle Rect button3 = new Rect(10f, rect1.height - 58f, rect.width - 8f, 24f); //breast Rect button4 = new Rect(10f, rect1.height - 82f, rect.width - 8f, 24f); //anus Rect button5 = new Rect(10f, rect1.height - 106f, rect.width - 8f, 24f); //v****a Rect button6 = new Rect(10f, rect1.height - 130f, rect.width - 8f, 24f); //penis 1 Rect button7 = new Rect(10f, rect1.height - 154f, rect.width - 8f, 24f); //penis 2 string price; string sexuality; // Check for Rational Romance consistency, in case the player adds it mid-game or adds traits (such as with Prepare Carefully) if (xxx.RomanceDiversifiedIsActive || pawn.story.traits.HasTrait(TraitDefOf.Gay)) { if (RJWPreferenceSettings.sexuality_distribution == RJWPreferenceSettings.Rjw_sexuality.RationalRomance) { CompRJW.RRTraitCheck(pawn); } } switch (CompRJW.Comp(pawn).orientation) { case Orientation.Asexual: sexuality = "Asexual"; break; case Orientation.Bisexual: sexuality = "Bisexual"; break; case Orientation.Heterosexual: sexuality = "Hetero"; break; case Orientation.Homosexual: sexuality = "Gay"; break; case Orientation.LeaningHeterosexual: sexuality = "Bisexual, leaning hetero"; break; case Orientation.LeaningHomosexual: sexuality = "Bisexual, leaning gay"; break; case Orientation.MostlyHeterosexual: sexuality = "Mostly hetero"; break; case Orientation.MostlyHomosexual: sexuality = "Mostly gay"; break; case Orientation.Pansexual: sexuality = "Pansexual"; break; default: sexuality = "None"; break; } //allow to change own hero sexuality if (RJWPreferenceSettings.sexuality_distribution == RJWPreferenceSettings.Rjw_sexuality.RimJobWorld && Current.ProgramState == ProgramState.Playing && pawn.IsDesignatedHero() && pawn.IsHeroOwner()) { if (Widgets.ButtonText(row1, "Sexuality: " + sexuality)) { Find.WindowStack.Add(new FloatMenu(new List <FloatMenuOption>() { new FloatMenuOption("Asexual", (() => Change_orientation(pawn, Orientation.Asexual)), MenuOptionPriority.Default), new FloatMenuOption("Pansexual", (() => Change_orientation(pawn, Orientation.Pansexual)), MenuOptionPriority.Default), new FloatMenuOption("Heterosexual", (() => Change_orientation(pawn, Orientation.Heterosexual)), MenuOptionPriority.Default), new FloatMenuOption("MostlyHeterosexual", (() => Change_orientation(pawn, Orientation.MostlyHeterosexual)), MenuOptionPriority.Default), new FloatMenuOption("LeaningHeterosexual", (() => Change_orientation(pawn, Orientation.LeaningHeterosexual)), MenuOptionPriority.Default), new FloatMenuOption("Bisexual", (() => Change_orientation(pawn, Orientation.Bisexual)), MenuOptionPriority.Default), new FloatMenuOption("LeaningHomosexual", (() => Change_orientation(pawn, Orientation.LeaningHomosexual)), MenuOptionPriority.Default), new FloatMenuOption("MostlyHomosexual", (() => Change_orientation(pawn, Orientation.MostlyHomosexual)), MenuOptionPriority.Default), new FloatMenuOption("Homosexual", (() => Change_orientation(pawn, Orientation.Homosexual)), MenuOptionPriority.Default), })); } } else { Widgets.Label(row1, "Sexuality: " + sexuality); if (Mouse.IsOver(row1)) { Widgets.DrawHighlight(row1); } } string quirklist = CompRJW.Comp(pawn).quirks.ToString(); Widgets.Label(row2, "Quirks".Translate() + quirklist); if (Mouse.IsOver(row2)) { Widgets.DrawHighlight(row2); if (quirklist == "None") { TooltipHandler.TipRegion(row2, "NoQuirks".Translate()); } else { StringBuilder tooltip = new StringBuilder(); if (quirklist.Contains("Breeder")) { tooltip.AppendLine("BreederQuirk".Translate()); } if (quirklist.Contains("Endytophile")) { tooltip.AppendLine("EndytophileQuirk".Translate()); } if (quirklist.Contains("Exhibitionist")) { tooltip.AppendLine("ExhibitionistQuirk".Translate()); } if (quirklist.Contains("Fertile")) { tooltip.AppendLine("FertileQuirk".Translate()); } if (quirklist.Contains("Gerontophile")) { tooltip.AppendLine("GerontophileQuirk".Translate()); } if (quirklist.Contains("Impregnation fetish")) { tooltip.AppendLine("ImpregnationFetishQuirk".Translate()); } if (quirklist.Contains("Incubator")) { tooltip.AppendLine("IncubatorQuirk".Translate()); } if (quirklist.Contains("Infertile")) { tooltip.AppendLine("InfertileQuirk".Translate()); } if (quirklist.Contains("Messy")) { tooltip.AppendLine("MessyQuirk".Translate()); } if (quirklist.Contains("Podophile")) { tooltip.AppendLine("PodophileQuirk".Translate()); } if (quirklist.Contains("Pregnancy fetish")) { tooltip.AppendLine("PregnancyFetishQuirk".Translate()); } if (quirklist.Contains("Sapiosexual")) { tooltip.AppendLine("SapiosexualQuirk".Translate()); } if (quirklist.Contains("Somnophile")) { tooltip.AppendLine("SomnophileQuirk".Translate()); } if (quirklist.Contains("Teratophile")) { tooltip.AppendLine("TeratophileQuirk".Translate()); } if (quirklist.Contains("Vigorous")) { tooltip.AppendLine("VigorousQuirk".Translate()); } TooltipHandler.TipRegion(row2, tooltip.ToString()); } } if (RJWSettings.sex_minimum_age > pawn.ageTracker.AgeBiologicalYears) { price = "Inapplicable (too young)"; } else if (pawn.ownership.OwnedRoom == null) { if (Current.ProgramState == ProgramState.Playing) { price = WhoringHelper.WhoreMinPrice(pawn) + " - " + WhoringHelper.WhoreMaxPrice(pawn) + " (base, needs suitable bedroom)"; } else { price = WhoringHelper.WhoreMinPrice(pawn) + " - " + WhoringHelper.WhoreMaxPrice(pawn) + " (base, modified by bedroom quality)"; } } else if (xxx.is_animal(pawn)) { price = "Incapable of whoring"; } else { price = WhoringHelper.WhoreMinPrice(pawn) + " - " + WhoringHelper.WhoreMaxPrice(pawn); } Widgets.Label(row3, "WhorePrice".Translate() + price); if (Mouse.IsOver(row3)) { Widgets.DrawHighlight(row3); } // TODO: Add translations. or not if (Prefs.DevMode || Current.ProgramState != ProgramState.Playing) { if (Widgets.ButtonText(button1, Current.ProgramState != ProgramState.Playing ? "Reroll sexuality" : "[DEV] Reroll sexuality")) { Re_sexualize(pawn); } } if (pawn.health.hediffSet.HasHediff(Genital_Helper.archotech_penis) || pawn.health.hediffSet.HasHediff(Genital_Helper.archotech_vagina)) { if (pawn.health.hediffSet.HasHediff(HediffDef.Named("ImpregnationBlocker"))) { if (Widgets.ButtonText(button2, "[Archotech genitalia] Enable reproduction")) { Change_Archotechmode(pawn); } } else if (!pawn.health.hediffSet.HasHediff(HediffDef.Named("FertilityEnhancer"))) { if (Widgets.ButtonText(button2, "[Archotech genitalia] Enchance fertility")) { Change_Archotechmode(pawn); } } else if (Widgets.ButtonText(button2, "[Archotech genitalia] Disable reproduction")) { Change_Archotechmode(pawn); } } // TODO: add mp synchronizers // TODO: clean that mess // TODO: add demon toggles if (MP.IsInMultiplayer) { return; } if (xxx.is_slime(pawn) && (pawn.IsColonistPlayerControlled || pawn.IsPrisonerOfColony)) { BodyPartRecord bpr_genitalia = Genital_Helper.get_genitals(pawn); BodyPartRecord bpr_breasts = Genital_Helper.get_breasts(pawn); BodyPartRecord bpr_anus = Genital_Helper.get_anus(pawn); BodyPartRecord bpr = null; HediffDef hed = null; if (Widgets.ButtonText(button3, "Morph breasts")) { Find.WindowStack.Add(new FloatMenu(new List <FloatMenuOption>() { new FloatMenuOption("none", (() => Breasts = breasts.none), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.featureless_chest.label.CapitalizeFirst(), (() => Breasts = breasts.featureless_chest), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.flat_breasts.label.CapitalizeFirst(), (() => Breasts = breasts.flat_breasts), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.small_breasts.label.CapitalizeFirst(), (() => Breasts = breasts.small_breasts), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.average_breasts.label.CapitalizeFirst(), (() => Breasts = breasts.average_breasts), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.large_breasts.label.CapitalizeFirst(), (() => Breasts = breasts.large_breasts), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.huge_breasts.label.CapitalizeFirst(), (() => Breasts = breasts.huge_breasts), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.slime_breasts.label.CapitalizeFirst(), (() => Breasts = breasts.slime_breasts), MenuOptionPriority.Default), })); } switch (Breasts) { case breasts.none: bpr = bpr_breasts; break; case breasts.featureless_chest: bpr = bpr_breasts; hed = Genital_Helper.featureless_chest; break; case breasts.flat_breasts: bpr = bpr_breasts; hed = Genital_Helper.flat_breasts; break; case breasts.small_breasts: bpr = bpr_breasts; hed = Genital_Helper.small_breasts; break; case breasts.average_breasts: bpr = bpr_breasts; hed = Genital_Helper.average_breasts; break; case breasts.large_breasts: bpr = bpr_breasts; hed = Genital_Helper.large_breasts; break; case breasts.huge_breasts: bpr = bpr_breasts; hed = Genital_Helper.huge_breasts; break; case breasts.slime_breasts: bpr = bpr_breasts; hed = Genital_Helper.slime_breasts; break; default: break; } if (Widgets.ButtonText(button4, "Morph anus")) { Find.WindowStack.Add(new FloatMenu(new List <FloatMenuOption>() { new FloatMenuOption("none", (() => Anuses = anuses.none), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.micro_anus.label.CapitalizeFirst(), (() => Anuses = anuses.micro_anus), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.tight_anus.label.CapitalizeFirst(), (() => Anuses = anuses.tight_anus), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.average_anus.label.CapitalizeFirst(), (() => Anuses = anuses.average_anus), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.loose_anus.label.CapitalizeFirst(), (() => Anuses = anuses.loose_anus), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.gaping_anus.label.CapitalizeFirst(), (() => Anuses = anuses.gaping_anus), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.slime_anus.label.CapitalizeFirst(), (() => Anuses = anuses.slime_anus), MenuOptionPriority.Default), })); } switch (Anuses) { case anuses.none: bpr = bpr_anus; break; case anuses.micro_anus: bpr = bpr_anus; hed = Genital_Helper.micro_anus; break; case anuses.tight_anus: bpr = bpr_anus; hed = Genital_Helper.tight_anus; break; case anuses.average_anus: bpr = bpr_anus; hed = Genital_Helper.average_anus; break; case anuses.loose_anus: bpr = bpr_anus; hed = Genital_Helper.loose_anus; break; case anuses.gaping_anus: bpr = bpr_anus; hed = Genital_Helper.gaping_anus; break; case anuses.slime_anus: bpr = bpr_anus; hed = Genital_Helper.slime_anus; break; default: break; } if (Widgets.ButtonText(button5, "Morph v****a")) { Find.WindowStack.Add(new FloatMenu(new List <FloatMenuOption>() { new FloatMenuOption("none", (() => Vaginas = vaginas.none), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.micro_vagina.label.CapitalizeFirst(), (() => Vaginas = vaginas.micro_vagina), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.tight_vagina.label.CapitalizeFirst(), (() => Vaginas = vaginas.tight_vagina), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.average_vagina.label.CapitalizeFirst(), (() => Vaginas = vaginas.average_vagina), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.loose_vagina.label.CapitalizeFirst(), (() => Vaginas = vaginas.loose_vagina), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.gaping_vagina.label.CapitalizeFirst(), (() => Vaginas = vaginas.gaping_vagina), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.slime_vagina.label.CapitalizeFirst(), (() => Vaginas = vaginas.slime_vagina), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.feline_vagina.label.CapitalizeFirst(), (() => Vaginas = vaginas.feline_vagina), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.canine_vagina.label.CapitalizeFirst(), (() => Vaginas = vaginas.canine_vagina), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.equine_vagina.label.CapitalizeFirst(), (() => Vaginas = vaginas.equine_vagina), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.dragon_vagina.label.CapitalizeFirst(), (() => Vaginas = vaginas.dragon_vagina), MenuOptionPriority.Default), })); } switch (Vaginas) { case vaginas.none: bpr = bpr_genitalia; break; case vaginas.micro_vagina: bpr = bpr_genitalia; hed = Genital_Helper.micro_vagina; break; case vaginas.tight_vagina: bpr = bpr_genitalia; hed = Genital_Helper.tight_vagina; break; case vaginas.average_vagina: bpr = bpr_genitalia; hed = Genital_Helper.average_vagina; break; case vaginas.loose_vagina: bpr = bpr_genitalia; hed = Genital_Helper.loose_vagina; break; case vaginas.gaping_vagina: bpr = bpr_genitalia; hed = Genital_Helper.gaping_vagina; break; case vaginas.slime_vagina: bpr = bpr_genitalia; hed = Genital_Helper.slime_vagina; break; case vaginas.feline_vagina: bpr = bpr_genitalia; hed = Genital_Helper.feline_vagina; break; case vaginas.canine_vagina: bpr = bpr_genitalia; hed = Genital_Helper.canine_vagina; break; case vaginas.equine_vagina: bpr = bpr_genitalia; hed = Genital_Helper.equine_vagina; break; case vaginas.dragon_vagina: bpr = bpr_genitalia; hed = Genital_Helper.dragon_vagina; break; default: break; } if (Widgets.ButtonText(button6, "Morph penis")) { Find.WindowStack.Add(new FloatMenu(new List <FloatMenuOption>() { new FloatMenuOption("none", (() => Penises = penises.none), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.micro_penis.label.CapitalizeFirst(), (() => Penises = penises.micro_penis), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.small_penis.label.CapitalizeFirst(), (() => Penises = penises.small_penis), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.average_penis.label.CapitalizeFirst(), (() => Penises = penises.average_penis), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.big_penis.label.CapitalizeFirst(), (() => Penises = penises.big_penis), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.huge_penis.label.CapitalizeFirst(), (() => Penises = penises.huge_penis), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.slime_penis.label.CapitalizeFirst(), (() => Penises = penises.slime_penis), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.feline_penis.label.CapitalizeFirst(), (() => Penises = penises.feline_penis), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.canine_penis.label.CapitalizeFirst(), (() => Penises = penises.canine_penis), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.equine_penis.label.CapitalizeFirst(), (() => Penises = penises.equine_penis), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.dragon_penis.label.CapitalizeFirst(), (() => Penises = penises.dragon_penis), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.raccoon_penis.label.CapitalizeFirst(), (() => Penises = penises.raccoon_penis), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.hemipenis.label.CapitalizeFirst(), (() => Penises = penises.hemipenis), MenuOptionPriority.Default), new FloatMenuOption(Genital_Helper.crocodilian_penis.label.CapitalizeFirst(), (() => Penises = penises.crocodilian_penis), MenuOptionPriority.Default), })); } switch (Penises) { case penises.none: bpr = bpr_genitalia; break; case penises.micro_penis: bpr = bpr_genitalia; hed = Genital_Helper.micro_penis; break; case penises.small_penis: bpr = bpr_genitalia; hed = Genital_Helper.small_penis; break; case penises.average_penis: bpr = bpr_genitalia; hed = Genital_Helper.average_penis; break; case penises.big_penis: bpr = bpr_genitalia; hed = Genital_Helper.big_penis; break; case penises.huge_penis: bpr = bpr_genitalia; hed = Genital_Helper.huge_penis; break; case penises.slime_penis: bpr = bpr_genitalia; hed = Genital_Helper.slime_penis; break; case penises.feline_penis: bpr = bpr_genitalia; hed = Genital_Helper.feline_penis; break; case penises.canine_penis: bpr = bpr_genitalia; hed = Genital_Helper.canine_penis; break; case penises.equine_penis: bpr = bpr_genitalia; hed = Genital_Helper.equine_penis; break; case penises.dragon_penis: bpr = bpr_genitalia; hed = Genital_Helper.dragon_penis; break; case penises.raccoon_penis: bpr = bpr_genitalia; hed = Genital_Helper.raccoon_penis; break; case penises.hemipenis: bpr = bpr_genitalia; hed = Genital_Helper.hemipenis; break; case penises.crocodilian_penis: bpr = bpr_genitalia; hed = Genital_Helper.crocodilian_penis; break; default: break; } if (bpr != null) { //Log.Message("start "); if (bpr != bpr_genitalia) { if (pawn.needs.TryGetNeed <Need_Food>().CurLevel > 0.5f) { pawn.needs.food.CurLevel -= 0.5f; pawn.health.RestorePart(bpr); if (hed != null) { pawn.health.AddHediff(hed, bpr); } } Anuses = anuses.selectone; Breasts = breasts.selectone; } else if (bpr == bpr_genitalia && Vaginas != vaginas.selectone) { if (pawn.needs.TryGetNeed <Need_Food>().CurLevel > 0.5f) { pawn.needs.food.CurLevel -= 0.5f; List <Hediff> list = new List <Hediff>(); foreach (Hediff heddif in pawn.health.hediffSet.hediffs.Where(x => x.Part == bpr && x.def.defName.ToLower().Contains("v****a"))) { list.Add(heddif); } foreach (Hediff heddif in list) { pawn.health.hediffSet.hediffs.Remove(heddif); } if (hed != null) { pawn.health.AddHediff(hed, bpr); } } Vaginas = vaginas.selectone; } else if (bpr == bpr_genitalia && Penises != penises.selectone) { if (pawn.needs.TryGetNeed <Need_Food>().CurLevel > 0.5f) { pawn.needs.food.CurLevel -= 0.5f; List <Hediff> list = new List <Hediff>(); foreach (Hediff heddif in pawn.health.hediffSet.hediffs.Where(x => x.Part == bpr && x.def.defName.ToLower().Contains("penis") || x.def.defName.ToLower().Contains("tentacle"))) { list.Add(heddif); } foreach (Hediff heddif in list) { pawn.health.hediffSet.hediffs.Remove(heddif); } if (hed != null) { pawn.health.AddHediff(hed, bpr); } } Penises = penises.selectone; } //Log.Message("end "); } } }
protected override IEnumerable <Toil> MakeNewToils() { //Log.Message("[RJW]JobDriver_WhoreIsServingVisitors::MakeNewToils() - making toils"); setup_ticks(); this.FailOnDespawnedOrNull(iTarget); this.FailOnDespawnedNullOrForbidden(iBed); //Log.Message("[RJW]JobDriver_WhoreIsServingVisitors::MakeNewToils() fail conditions check " + !xxx.CanUse(pawn, Bed) + " " + !pawn.CanReserve(Partner)); this.FailOn(() => !xxx.CanUse(pawn, Bed) || !pawn.CanReserve(Partner)); this.FailOn(() => pawn.Drafted); this.FailOn(() => Partner.IsFighting()); this.FailOn(() => !Partner.CanReach(pawn, PathEndMode.Touch, Danger.Deadly)); yield return(Toils_Reserve.Reserve(iTarget, 1, 0)); //yield return Toils_Reserve.Reserve(BedInd, Bed.SleepingSlotsCount, 0); //Log.Message("[RJW]JobDriver_WhoreIsServingVisitors::MakeNewToils() - generate toils"); Toil gotoBed = new Toil(); gotoBed.defaultCompleteMode = ToilCompleteMode.PatherArrival; gotoBed.FailOnWhorebedNoLongerUsable(iBed, Bed); gotoBed.AddFailCondition(() => Partner.Downed); gotoBed.FailOn(() => !Partner.CanReach(Bed, PathEndMode.Touch, Danger.Deadly)); gotoBed.initAction = delegate { //Log.Message("[RJW]JobDriver_WhoreIsServingVisitors::MakeNewToils() - gotoWhoreBed initAction is called"); pawn.pather.StartPath(SleepSpot, PathEndMode.OnCell); Partner.jobs.StopAll(); Job job = JobMaker.MakeJob(JobDefOf.GotoMindControlled, SleepSpot); Partner.jobs.StartJob(job, JobCondition.InterruptForced); }; yield return(gotoBed); ticks_left = (int)(2000.0f * Rand.Range(0.30f, 1.30f)); Toil waitInBed = new Toil(); waitInBed.initAction = delegate { ticksLeftThisToil = 5000; }; waitInBed.tickAction = delegate { pawn.GainComfortFromCellIfPossible(); if (IsInOrByBed(Bed, Partner) && pawn.PositionHeld == Partner.PositionHeld) { ReadyForNextToil(); } }; waitInBed.defaultCompleteMode = ToilCompleteMode.Delay; yield return(waitInBed); Toil StartPartnerJob = new Toil(); StartPartnerJob.defaultCompleteMode = ToilCompleteMode.Instant; StartPartnerJob.socialMode = RandomSocialMode.Off; StartPartnerJob.initAction = delegate { //Log.Message("[RJW]JobDriver_WhoreIsServingVisitors::MakeNewToils() - StartPartnerJob"); var gettin_loved = JobMaker.MakeJob(xxx.gettin_loved, pawn, Bed); Partner.jobs.StartJob(gettin_loved, JobCondition.InterruptForced); }; yield return(StartPartnerJob); Toil loveToil = new Toil(); loveToil.AddFailCondition(() => Partner.Dead || Partner.CurJobDef != xxx.gettin_loved); loveToil.defaultCompleteMode = ToilCompleteMode.Never; loveToil.socialMode = RandomSocialMode.Off; loveToil.handlingFacing = true; loveToil.initAction = delegate { //Log.Message("[RJW]JobDriver_WhoreIsServingVisitors::MakeNewToils() - loveToil"); // TODO: replace this quick n dirty way CondomUtility.GetCondomFromRoom(pawn); // Try to use w***e's condom first, then client's usedCondom = CondomUtility.TryUseCondom(pawn) || CondomUtility.TryUseCondom(Partner); Start(); if (xxx.HasNonPolyPartnerOnCurrentMap(Partner)) { Pawn lover = LovePartnerRelationUtility.ExistingLovePartner(Partner); // We have to do a few other checks because the pawn might have multiple lovers and ExistingLovePartner() might return the wrong one if (lover != null && pawn != lover && !lover.Dead && (lover.Map == Partner.Map || Rand.Value < 0.25)) { lover.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.CheatedOnMe, Partner); } } }; loveToil.AddPreTickAction(delegate { --ticks_left; if (pawn.IsHashIntervalTick(ticks_between_hearts)) { if (xxx.is_nympho(pawn)) { ThrowMetaIcon(pawn.Position, pawn.Map, ThingDefOf.Mote_Heart); } else { ThrowMetaIcon(pawn.Position, pawn.Map, xxx.mote_noheart); } } SexUtility.reduce_rest(Partner, 1); SexUtility.reduce_rest(pawn, 2); if (ticks_left <= 0) { ReadyForNextToil(); } }); loveToil.AddFinishAction(delegate { End(); }); yield return(loveToil); Toil afterSex = new Toil { initAction = delegate { // Adding interactions, social logs, etc SexUtility.ProcessSex(pawn, Partner, usedCondom: usedCondom, whoring: isWhoring, sextype: sexType); if (!(Partner.IsColonist && (pawn.IsPrisonerOfColony || pawn.IsColonist))) { int price = WhoringHelper.PriceOfWhore(pawn); //--Log.Message("JobDriver_WhoreIsServingVisitors::MakeNewToils() - Partner should pay the price now in afterSex.initAction"); int remainPrice = WhoringHelper.PayPriceToWhore(Partner, price, pawn); /*if (remainPrice <= 0) * { * --Log.Message("JobDriver_WhoreIsServingVisitors::MakeNewToils() - Paying price is success"); * } * else * { * --Log.Message("JobDriver_WhoreIsServingVisitors::MakeNewToils() - Paying price failed"); * }*/ xxx.UpdateRecords(pawn, price - remainPrice); } var thought = (pawn.IsPrisoner || xxx.is_slave(pawn)) ? thought_captive : thought_free; pawn.needs.mood.thoughts.memories.TryGainMemory(thought); if (SexUtility.ConsiderCleaning(pawn)) { LocalTargetInfo cum = pawn.PositionHeld.GetFirstThing <Filth>(pawn.Map); Job clean = JobMaker.MakeJob(JobDefOf.Clean); clean.AddQueuedTarget(TargetIndex.A, cum); pawn.jobs.jobQueue.EnqueueFirst(clean); } }, defaultCompleteMode = ToilCompleteMode.Instant }; yield return(afterSex); }