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); }
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); } }
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); }