protected override Job TryGiveJob(Pawn pawn) { // Most checks are done in ThinkNode_ConditionalNecro. // filter out necro for nymphs if (!RJWSettings.necrophilia_enabled) { return(null); } if (pawn.Drafted) { return(null); } //--Log.Message("[RJW] JobGiver_ViolateCorpse::TryGiveJob for ( " + xxx.get_pawnname(pawn) + " )"); if (SexUtility.ReadyForLovin(pawn) || xxx.is_hornyorfrustrated(pawn)) { //--Log.Message("[RJW] JobGiver_ViolateCorpse::TryGiveJob, can love "); if (!xxx.can_rape(pawn)) { return(null); } var target = find_corpse(pawn, pawn.Map); //--Log.Message("[RJW] JobGiver_ViolateCorpse::TryGiveJob - target is " + (target == null ? "NULL" : "Found")); if (target != null) { return(JobMaker.MakeJob(xxx.RapeCorpse, target)); } // Ticks should only be increased after successful sex. } return(null); }
protected override Job TryGiveJob(Pawn pawn) { //--Log.Message("[RJW] JobGiver_DoFappin::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) called"); if (pawn.Drafted) { return(null); } if (!xxx.can_be_fucked(pawn) && !xxx.can_fuck(pawn)) { return(null); } // W****s only fap if frustrated, unless imprisoned. if ((SexUtility.ReadyForLovin(pawn) && (!xxx.is_whore(pawn) || pawn.IsPrisoner)) || xxx.is_frustrated(pawn)) { if (pawn.jobs.curDriver is JobDriver_LayDown && RJWPreferenceSettings.FapInBed) { Building_Bed bed = ((JobDriver_LayDown)pawn.jobs.curDriver).Bed; if (bed != null) { return(new Job(xxx.fappin, bed)); } } else if ((xxx.is_frustrated(pawn) || xxx.has_quirk(pawn, "Exhibitionist")) && RJWPreferenceSettings.FapEverywhere) { return(new Job(xxx.quickfap, FindFapLocation(pawn))); } } return(null); }
protected override Job TryGiveJob(Pawn pawn) { //Log.Message("[RJW] JobGiver_AIRapePrisoner::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) called "); if (!xxx.can_rape(pawn)) { return(null); } if (SexUtility.ReadyForLovin(pawn) || xxx.is_hornyorfrustrated(pawn)) { // don't allow pawns marked as comfort prisoners to rape others if (xxx.is_healthy(pawn)) { Pawn prisoner = find_victim(pawn, pawn.Map); if (prisoner != null) { //--Log.Message("[RJW] JobGiver_RandomRape::TryGiveJob( " + xxx.get_pawnname(p) + " ) - found victim " + xxx.get_pawnname(prisoner)); return(JobMaker.MakeJob(xxx.RapeRandom, prisoner)); } } } return(null); }
protected override Job TryGiveJob(Pawn pawn) { //Log.Message("[RJW] JobGiver_ComfortPrisonerRape::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) called0"); if (!RJWSettings.WildMode) { // don't allow pawns marked as comfort prisoners to rape others if (!xxx.is_healthy(pawn) || pawn.IsDesignatedComfort() || (!SexUtility.ReadyForLovin(pawn) && !xxx.is_frustrated(pawn))) { return(null); } } if (pawn.Drafted) { return(null); } //Log.Message("[RJW] JobGiver_ComfortPrisonerRape::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) called1"); if (!xxx.can_rape(pawn)) { return(null); } // It's unnecessary to include other job checks. Pawns seem to only look for new jobs when between jobs or layind down idle. if (!(pawn.jobs.curJob == null || pawn.jobs.curJob.def == JobDefOf.LayDown)) { return(null); } //--Log.Message("[RJW] JobGiver_ComfortPrisonerRape::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) called2"); // Faction check. if (!(pawn.Faction?.IsPlayer ?? false) && !pawn.IsPrisonerOfColony) { return(null); } Pawn target = find_prisoner_to_rape(pawn, pawn.Map); //--Log.Message("[RJW] JobGiver_ComfortPrisonerRape::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) called3 - (" + ((target == null) ? "no target found" : xxx.get_pawnname(target))+") is the prisoner"); if (target == null) { return(null); } //Log.Message("giving job to " + pawner + " with target " + target); if (xxx.is_animal(target)) { return(new Job(xxx.bestiality, target)); } else { return(new Job(xxx.comfort_prisoner_rapin, target)); } }
protected override Job TryGiveJob(Pawn pawn) { // Most things are now checked in the ThinkNode_ConditionalWhore. if (pawn.Drafted) { return(null); } if (MP.IsInMultiplayer) { return(null); //fix error someday, maybe } //Log.Message("[RJW] JobGiver_WhoreInvitingVisitors::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) called"); if (!SexUtility.ReadyForLovin(pawn)) { //W****s need rest too, but this'll reduxe the wait a bit every it triggers. pawn.mindState.canLovinTick -= 40; return(null); } Building_Bed whorebed = xxx.FindBed(pawn); if (whorebed == null || !xxx.CanUse(pawn, whorebed)) { return(null); } int price; Pawn client = FindAttractivePawn(pawn, out price); if (client == null) { return(null); } if (!client.CanReach(whorebed, PathEndMode.OnCell, Danger.Some)) { return(null); } //Log.Message("[RJW] JobGiver_WhoreInvitingVisitors::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) is w***e, " + xxx.get_pawnname(client) + " is client."); //whorebed.priceOfWhore = price; return(new Job(xxx.whore_inviting_visitors, client, whorebed)); }
protected override Job TryGiveJob(Pawn pawn) { if (pawn.Drafted) { return(null); } // Most checks are now done in ThinkNode_ConditionalBestiality DebugText("[RJW] JobGiver_Bestiality::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) called"); if (!SexUtility.ReadyForLovin(pawn) && !xxx.is_frustrated(pawn)) { return(null); } Pawn target = BreederHelper.find_breeder_animal(pawn, pawn.Map); DebugText("[RJW] JobGiver_Bestiality::TryGiveJob - target is " + (target == null ? "no target found" : xxx.get_pawnname(target))); if (target == null) { return(null); } if (xxx.can_rape(pawn)) { return(new Job(xxx.bestiality, target)); } Building_Bed bed = pawn.ownership.OwnedBed; if (!xxx.can_be_fucked(pawn) || bed == null || !target.CanReach(bed, PathEndMode.OnCell, Danger.Some) || target.Downed) { return(null); } // TODO: Should rename this to BestialityInBed or somesuch, since it's not limited to females. return(new Job(xxx.bestialityForFemale, target, bed, bed.SleepPosOfAssignedPawn(pawn))); }
protected override Job TryGiveJob(Pawn animal) { //Log.Message("[RJW] JobGiver_Breed::TryGiveJob( " + xxx.get_pawnname(animal) + " ) called0" + (SexUtility.ReadyForLovin(animal))); if (!SexUtility.ReadyForLovin(animal)) { return(null); } if (xxx.is_healthy(animal) && xxx.can_rape(animal)) { //search for desiganted target to sex if (animal.IsDesignatedBreedingAnimal()) { Pawn designated_target = BreederHelper.find_designated_breeder(animal, animal.Map); if (designated_target != null) { return(JobMaker.MakeJob(xxx.animalBreed, designated_target)); } } } return(null); }
protected override Job TryGiveJob(Pawn pawn) { if (pawn.Drafted) { return(null); } // Most checks are now done in ThinkNode_ConditionalBestiality if (!SexUtility.ReadyForLovin(pawn) && !xxx.is_frustrated(pawn)) { return(null); } Pawn target = BreederHelper.find_breeder_animal(pawn, pawn.Map); if (target == null) { return(null); } if (xxx.can_rape(pawn)) { return(JobMaker.MakeJob(xxx.bestiality, target)); } Building_Bed bed = pawn.ownership.OwnedBed; if (!xxx.can_be_fucked(pawn) || bed == null || !target.CanReach(bed, PathEndMode.OnCell, Danger.Some) || target.Downed) { return(null); } // TODO: Should rename this to BestialityInBed or somesuch, since it's not limited to females. return(JobMaker.MakeJob(xxx.bestialityForFemale, target, bed)); }
protected override Job TryGiveJob(Pawn pawn) { // Most things are now checked in the ThinkNode_ConditionalWhore. if (pawn.Drafted) { return(null); } if (MP.IsInMultiplayer) { return(null); //fix error someday, maybe } if (!SexUtility.ReadyForLovin(pawn)) { //W****s need rest too, but this'll reduxe the wait a bit every it triggers. pawn.mindState.canLovinTick -= 40; return(null); } if (RJWSettings.DebugWhoring) { Log.Message($"[RJW] JobGiver_WhoreInvitingVisitors.TryGiveJob:({xxx.get_pawnname(pawn)})"); } Building_Bed whorebed = xxx.FindBed(pawn); if (whorebed == null || !xxx.CanUse(pawn, whorebed)) { if (RJWSettings.DebugWhoring) { Log.Message($" {xxx.get_pawnname(pawn)} has no bed or can use it"); } return(null); } int price; Pawn client = FindAttractivePawn(pawn, out price); if (client == null) { if (RJWSettings.DebugWhoring) { Log.Message($" no clients found"); } return(null); } if (RJWSettings.DebugWhoring) { Log.Message($" {xxx.get_pawnname(client)} is client"); } if (!client.CanReach(whorebed, PathEndMode.OnCell, Danger.Some)) { if (RJWSettings.DebugWhoring) { Log.Message($" {xxx.get_pawnname(client)} cant reach bed"); } return(null); } //whorebed.priceOfWhore = price; return(JobMaker.MakeJob(xxx.whore_inviting_visitors, client, whorebed)); }
protected override Job TryGiveJob(Pawn pawn) { //Log.Message("[RJW] JobGiver_RapeEnemy::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) called0"); //Log.Message("[RJW] JobGiver_RapeEnemy::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) 0 " + SexUtility.ReadyForLovin(pawn)); //Log.Message("[RJW] JobGiver_RapeEnemy::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) 1 " + (xxx.need_some_sex(pawn) <= 1f)); //Log.Message("[RJW] JobGiver_RapeEnemy::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) 2 " + !(SexUtility.ReadyForLovin(pawn) || xxx.need_some_sex(pawn) <= 1f)); //Log.Message("[RJW] JobGiver_RapeEnemy::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) 1 " + Find.TickManager.TicksGame); //Log.Message("[RJW] JobGiver_RapeEnemy::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) 2 " + pawn.mindState.canLovinTick); if (pawn.Drafted) { return(null); } if (pawn.health.hediffSet.HasHediff(HediffDef.Named("Hediff_RapeEnemyCD")) || !pawn.health.capacities.CanBeAwake || !(SexUtility.ReadyForLovin(pawn) || xxx.need_some_sex(pawn) <= 1f)) { //if (pawn.health.hediffSet.HasHediff(HediffDef.Named("Hediff_RapeEnemyCD")) || !pawn.health.capacities.CanBeAwake || (SexUtility.ReadyForLovin(pawn) || xxx.is_human(pawn) ? xxx.need_some_sex(pawn) <= 1f : false)) return(null); } if (!xxx.can_rape(pawn)) { return(null); } //Log.Message("[RJW] JobGiver_RapeEnemy::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) can rape"); JobDef_RapeEnemy rapeEnemyJobDef = null; int?highestPriority = null; foreach (JobDef_RapeEnemy job in DefDatabase <JobDef_RapeEnemy> .AllDefs) { if (job.CanUseThisJobForPawn(pawn)) { if (highestPriority == null) { rapeEnemyJobDef = job; highestPriority = job.priority; } else if (job.priority > highestPriority) { rapeEnemyJobDef = job; highestPriority = job.priority; } } } //Log.Message("[RJW] JobGiver_RapeEnemy::ChoosedJobDef( " + xxx.get_pawnname(pawn) + " ) - " + rapeEnemyJobDef.ToString() + " choosed"); Pawn victim = rapeEnemyJobDef?.FindVictim(pawn, pawn.Map); //Log.Message("[RJW] JobGiver_RapeEnemy::FoundVictim( " + xxx.get_pawnname(victim) + " )"); //prevents 10 job stacks error, no idea whats the prob with JobDriver_Rape //if (victim != null) pawn.health.AddHediff(HediffDef.Named("Hediff_RapeEnemyCD"), null, null, null); return(victim != null ? new Job(rapeEnemyJobDef, victim) : null); /* * else * { * //--Log.Message("[RJW]" + this.GetType().ToString() + "::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) - unable to find victim"); * pawn.mindState.canLovinTick = Find.TickManager.TicksGame + Rand.Range(75, 150); * } */ //else { //--Log.Message("[RJW] JobGiver_RapeEnemy::TryGiveJob( " + xxx.get_pawnname(pawn) + " ) - too fast to play next"); } }
protected override Job TryGiveJob(Pawn pawn) { if (!RJWHookupSettings.HookupsEnabled) { return(null); } if (pawn.Drafted) { return(null); } if (!SexUtility.ReadyForHookup(pawn)) { return(null); } // We increase the time right away to prevent the fairly expensive check from happening too frequently SexUtility.IncreaseTicksToNextHookup(pawn); // If the pawn is a w***e, or recently had sex, skip the job unless they're really horny if (!xxx.is_frustrated(pawn) && (xxx.is_whore(pawn) || !SexUtility.ReadyForLovin(pawn))) { return(null); } // This check attempts to keep groups leaving the map, like guests or traders, from turning around to hook up if (pawn.mindState?.duty?.def == DutyDefOf.TravelOrLeave) { // TODO: Some guest pawns keep the TravelOrLeave duty the whole time, I think the ones assigned to guard the pack animals. // That's probably ok, though it wasn't the intention. if (RJWSettings.DebugLogJoinInBed) { Log.Message($"[RJW] JoinInBed.TryGiveJob:({xxx.get_pawnname(pawn)}): has TravelOrLeave, no time for lovin!"); } return(null); } if (pawn.CurJob == null || pawn.CurJob.def == JobDefOf.LayDown) { //--Log.Message(" checking pawn and abilities"); if (xxx.can_fuck(pawn) || xxx.can_be_fucked(pawn)) { //--Log.Message(" finding partner"); Pawn partner = find_pawn_to_fuck(pawn, pawn.Map); //--Log.Message(" checking partner"); if (partner == null) { return(null); } // Can never be null, since find checks for bed. Building_Bed bed = partner.CurrentBed(); // Interrupt current job. if (pawn.CurJob != null && pawn.jobs.curDriver != null) { pawn.jobs.curDriver.EndJobWith(JobCondition.InterruptForced); } //--Log.Message(" returning job"); return(new Job(DefDatabase <JobDef> .GetNamed("JoinInBed"), pawn, partner, bed)); } } return(null); }
/// <summary> Checks all of our potential partners to see if anyone's eligible, returning the most attractive and convenient one. </summary> protected static Pawn FindBestPartner(Pawn pawn, List <Pawn> targets, bool pawnCanPickAnyone, bool pawnIsNympho) { string pawnName = xxx.get_pawnname(pawn); Pawn best_fuckee = null; float best_fuckability_score = 0; foreach (Pawn targetPawn in targets) { if (RJWSettings.DebugLogJoinInBed) { Log.Message($"[RJW] FindBestPartner({pawnName}): checking hookup {xxx.get_pawnname(targetPawn)}"); } // Check to see if the mod settings for hookups allow this pairing if (!pawnCanPickAnyone && !HookupAllowedViaSettings(pawn, targetPawn)) { continue; } // Check for homewrecking (banging a pawn who's in a relationship) if (!xxx.is_animal(targetPawn) && xxx.HasNonPolyPartnerOnCurrentMap(targetPawn)) { if (RJWHookupSettings.NymphosCanHomewreck && pawnIsNympho && xxx.is_frustrated(pawn)) { // Hookup allowed... rip colony mood } else if (RJWHookupSettings.NymphosCanHomewreckReverse && xxx.is_nympho(targetPawn) && xxx.is_frustrated(targetPawn)) { // Hookup allowed... rip colony mood } else { if (RJWSettings.DebugLogJoinInBed) { Log.Message($"[RJW] FindBestPartner({pawnName}): not hooking up with {xxx.get_pawnname(targetPawn)} to avoid homewrecking"); } continue; } } // If the pawn has had sex recently and isn't horny right now, skip them. if (!SexUtility.ReadyForLovin(targetPawn) && !xxx.is_horny(targetPawn)) { if (RJWSettings.DebugLogJoinInBed) { Log.Message($"[RJW] FindBestPartner({pawnName}): hookup {xxx.get_pawnname(targetPawn)} isn't ready for lovin'"); } continue; } if (RJWSettings.DebugLogJoinInBed) { Log.Message($"[RJW] FindBestPartner({pawnName}): hookup {xxx.get_pawnname(targetPawn)} is sufficiently single"); } if (!xxx.is_animal(targetPawn)) { float relations = pawn.relations.OpinionOf(targetPawn); if (relations < RJWHookupSettings.MinimumRelationshipToHookup) { if (!(relations > 0 && xxx.is_nympho(pawn))) { if (RJWSettings.DebugLogJoinInBed) { Log.Message($"[RJW] FindBestPartner({pawnName}): hookup {xxx.get_pawnname(targetPawn)}, i dont like them:({relations})"); } continue; } } relations = targetPawn.relations.OpinionOf(pawn); if (relations < RJWHookupSettings.MinimumRelationshipToHookup) { if (!(relations > 0 && xxx.is_nympho(targetPawn))) { if (RJWSettings.DebugLogJoinInBed) { Log.Message($"[RJW] FindBestPartner({pawnName}): hookup {xxx.get_pawnname(targetPawn)}, dont like me:({relations})"); } continue; } } float attraction = pawn.relations.SecondaryRomanceChanceFactor(targetPawn); if (attraction < RJWHookupSettings.MinimumAttractivenessToHookup) { if (!(attraction > 0 && xxx.is_nympho(pawn))) { if (RJWSettings.DebugLogJoinInBed) { Log.Message($"[RJW] FindBestPartner({pawnName}): hookup {xxx.get_pawnname(targetPawn)}, i dont find them attractive:({attraction})"); } continue; } } attraction = targetPawn.relations.SecondaryRomanceChanceFactor(pawn); if (attraction < RJWHookupSettings.MinimumAttractivenessToHookup) { if (!(attraction > 0 && xxx.is_nympho(targetPawn))) { if (RJWSettings.DebugLogJoinInBed) { Log.Message($"[RJW] FindBestPartner({pawnName}): hookup {xxx.get_pawnname(targetPawn)}, doesnt find me attractive:({attraction})"); } continue; } } } // Check to see if the two pawns are willing to bang, and if so remember how much attractive we find them float fuckability = 0f; if (pawn.CanReserveAndReach(targetPawn, PathEndMode.OnCell, Danger.Some, 1, 0) && targetPawn.CanReserve(pawn, 1, 0) && roll_to_skip(pawn, targetPawn, out fuckability)) // do NOT check pawnIgnoresRules here - these checks, particularly roll_to_skip, are critical { int dis = pawn.Position.DistanceToSquared(targetPawn.Position); if (dis <= 4) { // Right next to me (in my bed)? You'll do. if (RJWSettings.DebugLogJoinInBed) { Log.Message($"[RJW] FindBestPartner({pawnName}): hookup {xxx.get_pawnname(targetPawn)} is right next to me. we'll bang, ok?"); } best_fuckability_score = 1.0e6f; best_fuckee = targetPawn; } else if (dis > MaxDistanceSquaredToFuck) { // too far if (RJWSettings.DebugLogJoinInBed) { Log.Message($"[RJW] FindBestPartner({pawnName}): hookup {xxx.get_pawnname(targetPawn)} is too far... distance:{dis} max:{MaxDistanceSquaredToFuck}"); } continue; } else { // scaling fuckability by distance may give us more varied results and give the less attractive folks a chance float fuckability_score = fuckability / GenMath.Sqrt(GenMath.Sqrt(dis)); if (RJWSettings.DebugLogJoinInBed) { Log.Message($"[RJW] FindBestPartner({pawnName}): hookup {xxx.get_pawnname(targetPawn)} is totally bangable. attraction: {fuckability}, score:{fuckability_score}"); } if (fuckability_score > best_fuckability_score) { best_fuckee = targetPawn; best_fuckability_score = fuckability_score; } } } } if (best_fuckee == null) { if (RJWSettings.DebugLogJoinInBed) { Log.Message($"[RJW] FindBestPartner({pawnName}): couldn't find anyone to bang"); } } else { if (RJWSettings.DebugLogJoinInBed) { Log.Message($"[RJW] FindBestPartner({pawnName}): found rando {xxx.get_pawnname(best_fuckee)} with score {best_fuckability_score}"); } } return(best_fuckee); }
protected override Job TryGiveJob(Pawn animal) { //Log.Message("[RJW] JobGiver_Breed::TryGiveJob( " + xxx.get_pawnname(animal) + " ) called0" + (SexUtility.ReadyForLovin(animal))); if (!SexUtility.ReadyForLovin(animal)) { return(null); } if (xxx.is_healthy(animal) && xxx.can_rape(animal)) { //Log.Message("[RJW] JobGiver_Breed::TryGiveJob( " + xxx.get_pawnname(animal) + " ) called2"); List <Pawn> valid_targets = new List <Pawn>(); //search for desiganted target to sex if (animal.IsDesignatedBreedingAnimal()) { Pawn designated_target = BreederHelper.find_designated_breeder(animal, animal.Map); if (designated_target != null) { valid_targets.Add(designated_target); } } //some weird shit happens, animal tries to rape and fails, needs investigation someday /* * //search for animal to sex * if (RJWSettings.animal_on_animal_enabled) * { * //Using bestiality target finder, since it works best for this. * //search for same race mate * if (!valid_targets.Any()) * { * Pawn animal_target = BreederHelper.find_breeder_animal(animal, animal.Map); * if (animal_target != null) * { * valid_targets.Add(animal_target); * } * } * * //search for any other animal/human to sex * if (!valid_targets.Any()) * { * Pawn animal_target = BreederHelper.find_breeder_animal(animal, animal.Map, false); * if (animal_target != null) * { * valid_targets.Add(animal_target); * } * } * * } */ //Log.Message("[RJW] JobGiver_Breed::TryGiveJob( " + xxx.get_pawnname(animal) + " ) called3 - (" + ((target == null) ? "no target found" : xxx.get_pawnname(target))+") is the prisoner"); if (valid_targets != null && valid_targets.Any()) { //Rand.PopState(); //Rand.PushState(RJW_Multiplayer.PredictableSeed()); var target = valid_targets.RandomElement(); //Log.Message("Target: " + xxx.get_pawnname(target)); return(new Job(DefDatabase <JobDef> .GetNamed("Breed"), target, animal)); } } return(null); }