Exemplo n.º 1
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            //--Log.Message("[RJW] JobDriver_BestialityForMale::MakeNewToils() called");
            //Rand.PopState();
            //Rand.PushState(RJW_Multiplayer.PredictableSeed());
            duration              = (int)(2500.0f * Rand.Range(0.50f, 0.90f));
            ticks_between_hearts  = Rand.RangeInclusive(70, 130);
            ticks_between_hits    = Rand.Range(xxx.config.min_ticks_between_hits, xxx.config.max_ticks_between_hits);
            ticks_between_thrusts = 100;

            if (xxx.is_bloodlust(pawn))
            {
                ticks_between_hits = (int)(ticks_between_hits * 0.75);
            }
            if (xxx.is_brawler(pawn))
            {
                ticks_between_hits = (int)(ticks_between_hits * 0.90);
            }

            //this.FailOn (() => (!animal.health.capacities.CanBeAwake) || (!comfort_prisoners.is_designated (animal)));
            // Fail if someone else reserves the prisoner before the pawn arrives or colonist can't reach animal
            this.FailOn(() => !pawn.CanReserveAndReach(animal, PathEndMode.Touch, Danger.Deadly));
            this.FailOn(() => animal.HostileTo(pawn));
            this.FailOnDespawnedNullOrForbidden(target_animal);
            this.FailOn(() => pawn.Drafted);
            yield return(Toils_Reserve.Reserve(target_animal, 1, 0));

            //Log.Message("[RJW] JobDriver_BestialityForMale::MakeNewToils() - moving towards animal");
            yield return(Toils_Goto.GotoThing(target_animal, PathEndMode.Touch));

            yield return(Toils_Interpersonal.WaitToBeAbleToInteract(pawn));

            yield return(Toils_Interpersonal.GotoInteractablePosition(target_animal));

            if (xxx.is_kind(pawn) ||
                (xxx.CTIsActive && xxx.has_traits(pawn) && pawn.story.traits.HasTrait(TraitDef.Named("RCT_AnimalLover"))))
            {
                yield return(TalkToAnimal(pawn, animal));

                yield return(TalkToAnimal(pawn, animal));
            }
            if (Rand.Chance(0.6f))
            {
                yield return(TalkToAnimal(pawn, animal));
            }
            yield return(Toils_Goto.GotoThing(target_animal, PathEndMode.OnCell));

            SexUtility.RapeAttemptAlert(pawn, animal);

            Toil rape = new Toil();

            rape.initAction = delegate
            {
                //--Log.Message("[RJW] JobDriver_BestialityForMale::MakeNewToils() - reserving animal");

                //--Log.Message("[RJW] JobDriver_BestialityForMale::MakeNewToils() - Setting animal job driver");
                if (!(animal.jobs.curDriver is JobDriver_GettinRaped dri))
                {
                    //wild animals may flee or attack
                    if (pawn.Faction != animal.Faction && animal.RaceProps.wildness > Rand.Range(0.22f, 1.0f) &&
                        !(pawn.TicksPerMoveCardinal < (animal.TicksPerMoveCardinal / 2) && !animal.Downed && xxx.is_not_dying(animal)))
                    {
                        animal.jobs.StopAll();                         // Wake up if sleeping.

                        float aggro = animal.kindDef.RaceProps.manhunterOnTameFailChance;
                        if (animal.kindDef.RaceProps.predator)
                        {
                            aggro += 0.2f;
                        }
                        else
                        {
                            aggro -= 0.1f;
                        }

                        if (Rand.Chance(aggro) && animal.CanSee(pawn))
                        {
                            animal.rotationTracker.FaceTarget(pawn);
                            LifeStageUtility.PlayNearestLifestageSound(animal, (ls) => ls.soundAngry, 1.4f);
                            MoteMaker.ThrowMetaIcon(animal.Position, animal.Map, ThingDefOf.Mote_IncapIcon);
                            MoteMaker.ThrowMetaIcon(pawn.Position, pawn.Map, ThingDefOf.Mote_ColonistFleeing);                             //red '!'
                            animal.mindState.mentalStateHandler.TryStartMentalState(MentalStateDefOf.Manhunter);
                            if (animal.kindDef.RaceProps.herdAnimal && Rand.Chance(0.2f))
                            {                             // 20% chance of turning the whole herd hostile...
                                List <Pawn> packmates = animal.Map.mapPawns.AllPawnsSpawned.Where(x =>
                                                                                                  x != animal && x.def == animal.def && x.Faction == animal.Faction &&
                                                                                                  x.Position.InHorDistOf(animal.Position, 24f) && x.CanSee(animal)).ToList();

                                foreach (Pawn packmate in packmates)
                                {
                                    packmate.mindState.mentalStateHandler.TryStartMentalState(MentalStateDefOf.Manhunter);
                                }
                            }
                            Messages.Message(pawn.Name.ToStringShort + " is being attacked by " + xxx.get_pawnname(animal) + ".", pawn, MessageTypeDefOf.ThreatSmall);
                        }
                        else
                        {
                            MoteMaker.ThrowMetaIcon(animal.Position, animal.Map, ThingDefOf.Mote_ColonistFleeing);
                            LifeStageUtility.PlayNearestLifestageSound(animal, (ls) => ls.soundCall);
                            animal.mindState.StartFleeingBecauseOfPawnAction(pawn);
                            animal.mindState.mentalStateHandler.TryStartMentalState(DefDatabase <MentalStateDef> .GetNamed("PanicFlee"));
                        }
                        pawn.jobs.EndCurrentJob(JobCondition.Incompletable);
                    }
                    else
                    {
                        Job gettin_bred = new Job(xxx.gettin_bred, pawn, animal);
                        animal.jobs.StartJob(gettin_bred, JobCondition.InterruptForced, null, true);
                        (animal.jobs.curDriver as JobDriver_GettinRaped)?.increase_time(duration);
                    }
                }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            //Rand.PopState();
            //Rand.PushState(RJW_Multiplayer.PredictableSeed());
            duration              = (int)(2000.0f * Rand.Range(0.50f, 0.90f));
            ticks_between_hearts  = Rand.RangeInclusive(70, 130);
            ticks_between_hits    = Rand.Range(xxx.config.min_ticks_between_hits, xxx.config.max_ticks_between_hits);
            ticks_between_thrusts = 100;
            bool pawnHasPenis = Genital_Helper.has_penis(pawn) || Genital_Helper.has_penis_infertile(pawn);

            if (xxx.is_bloodlust(pawn))
            {
                ticks_between_hits = (int)(ticks_between_hits * 0.75);
            }
            if (xxx.is_brawler(pawn))
            {
                ticks_between_hits = (int)(ticks_between_hits * 0.90);
            }

            //--Log.Message("JobDriver_ComfortPrisonerRapin::MakeNewToils() - setting fail conditions");
            this.FailOnDespawnedNullOrForbidden(iprisoner);
            //this.FailOn(() => (!Target.health.capacities.CanBeAwake) || (!comfort_prisoners.is_designated(Target)));//this is wrong
            this.FailOn(() => (!Target.IsDesignatedComfort()));
            this.FailOn(() => !pawn.CanReserve(Target, xxx.max_rapists_per_prisoner, 0));             // Fail if someone else reserves the prisoner before the pawn arrives
            this.FailOn(() => pawn.Drafted);
            yield return(Toils_Goto.GotoThing(iprisoner, PathEndMode.OnCell));

            SexUtility.RapeAttemptAlert(pawn, Target);

            Toil rape = new Toil();

            rape.initAction = delegate
            {
                //--Log.Message("JobDriver_ComfortPrisonerRapin::MakeNewToils() - reserving prisoner");
                //pawn.Reserve(Target, comfort_prisoners.max_rapists_per_prisoner, 0);
                if (!pawnHasPenis)
                {
                    Target.rotationTracker.Face(pawn.DrawPos);
                }

                //--Log.Message("JobDriver_ComfortPrisonerRapin::MakeNewToils() - Setting victim job driver");
                JobDriver_GettinRaped dri = Target.jobs.curDriver as JobDriver_GettinRaped;
                if (dri == null)
                {
                    Job          gettin_raped = new Job(xxx.gettin_raped, pawn, Target);
                    Building_Bed Bed          = null;
                    //Log.Message(xxx.get_pawnname(pawn) + " LayingInBed:" + pawn.GetPosture());
                    //Log.Message(xxx.get_pawnname(Target) + " LayingInBed:" + Target.GetPosture());
                    if (Target.GetPosture() == PawnPosture.LayingInBed)
                    {
                        Bed = Target.CurrentBed();
                        //Log.Message(xxx.get_pawnname(Target) + ": bed:" + Bed);
                    }

                    Target.jobs.StartJob(gettin_raped, JobCondition.InterruptForced, null, false, true, null);
                    (Target.jobs.curDriver as JobDriver_GettinRaped)?.increase_time(duration);
                    if (Bed != null)
                    {
                        (Target.jobs.curDriver as JobDriver_GettinRaped)?.set_bed(Bed);
                    }
                }
                else
                {
                    dri.rapist_count += 1;
                    dri.increase_time(duration);
                }
            };
            rape.tickAction = delegate
            {
                if (pawn.IsHashIntervalTick(ticks_between_hearts))
                {
                    MoteMaker.ThrowMetaIcon(pawn.Position, pawn.Map, ThingDefOf.Mote_Heart);
                }
                if (pawn.IsHashIntervalTick(ticks_between_thrusts))
                {
                    xxx.sexTick(pawn, Target);
                }
                if (pawn.IsHashIntervalTick(ticks_between_hits))
                {
                    roll_to_hit(pawn, Target);
                }
                xxx.reduce_rest(Target, 1);
                xxx.reduce_rest(pawn, 2);
            };
            rape.AddFinishAction(delegate
            {
                //Log.Message("JobDriver_ComfortPrisonerRapin::MakeNewToils() - Clearing victim job");
                if (Target.jobs?.curDriver is JobDriver_GettinRaped)
                {
                    //Log.Message("JobDriver_ComfortPrisonerRapin::MakeNewToils() - Victim present");
                    (Target.jobs.curDriver as JobDriver_GettinRaped).rapist_count -= 1;
                }
            });
            rape.defaultCompleteMode = ToilCompleteMode.Delay;
            rape.defaultDuration     = duration;
            yield return(rape);

            yield return(new Toil
            {
                initAction = delegate
                {
                    // Trying to add some interactions and social logs
                    SexUtility.ProcessSex(pawn, Target, true);
                    Target.records.Increment(xxx.GetRapedAsComfortPrisoner);
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            });
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            //Rand.PopState();
            //Rand.PushState(RJW_Multiplayer.PredictableSeed());
            int duration              = (int)(2000.0f * Rand.Range(0.50f, 0.90f));
            int ticks_between_hearts  = Rand.RangeInclusive(70, 130);
            int ticks_between_hits    = Rand.Range(xxx.config.min_ticks_between_hits, xxx.config.max_ticks_between_hits);
            int ticks_between_thrusts = 100;

            //--Log.Message("JobDriver_ComfortPrisonerRapin::MakeNewToils() - setting fail conditions");
            this.FailOnDespawnedNullOrForbidden(PartnerIndex);
            this.FailOn(() => !pawn.CanReserve(Target, BreederHelper.max_animals_at_once, 0));                                      // Fail if someone else reserves the target before the animal arrives.
            this.FailOn(() => !pawn.CanReach(Target, PathEndMode.Touch, Danger.Some));                                              // Fail if animal cannot reach target.
            this.FailOn(() => !(Target.IsDesignatedBreeding() || (RJWSettings.animal_on_animal_enabled && xxx.is_animal(Target)))); // Fail if not designated and not animal-on-animal
            this.FailOn(() => Target.CurJob == null);
            this.FailOn(() => pawn.Drafted);

            // Path to target
            yield return(Toils_Goto.GotoThing(PartnerIndex, PathEndMode.OnCell));

            SexUtility.RapeAttemptAlert(pawn, Target);

            // Breed target
            var breed = new Toil();

            breed.initAction = delegate
            {
                //Log.Message("JobDriver_ComfortPrisonerRapin::MakeNewToils() - Setting victim job driver");
                Job currentJob = Target.jobs.curJob;

                if (currentJob.def != xxx.gettin_raped)
                {
                    Job          gettin_raped = new Job(xxx.gettin_raped, pawn, Target);
                    Building_Bed Bed          = null;
                    //Log.Message(xxx.get_pawnname(pawn) + " LayingInBed:" + pawn.GetPosture());
                    //Log.Message(xxx.get_pawnname(Target) + " LayingInBed:" + Target.GetPosture());
                    if (Target.GetPosture() == PawnPosture.LayingInBed)
                    {
                        Bed = Target.CurrentBed();
                        //Log.Message(xxx.get_pawnname(Target) + ": bed:" + Bed);
                    }

                    Target.jobs.StartJob(gettin_raped, JobCondition.InterruptForced);

                    //var dri = Target.jobs.curDriver as JobDriver_GettinRaped;
                    //if (xxx.is_animal(pawn) && xxx.is_animal(Target)) // No alert spam for animal-on-animal
                    //dri.disable_alert = true;

                    (Target.jobs.curDriver as JobDriver_GettinRaped).increase_time(duration);
                    if (Bed != null)
                    {
                        (Target.jobs.curDriver as JobDriver_GettinRaped)?.set_bed(Bed);
                    }
                }
                else
                {
                    if (Target.jobs.curDriver is JobDriver_GettinRaped dri)
                    {
                        dri.rapist_count += 1;
                        dri.increase_time(duration);
                    }
                }
            };

            breed.tickAction = delegate
            {
                if (pawn.IsHashIntervalTick(ticks_between_hearts))
                {
                    MoteMaker.ThrowMetaIcon(pawn.Position, pawn.Map, ThingDefOf.Mote_Heart);
                }
                if (pawn.IsHashIntervalTick(ticks_between_thrusts))
                {
                    xxx.sexTick(pawn, Target);
                }
                if (!xxx.is_zoophile(Target) && pawn.IsHashIntervalTick(ticks_between_hits))
                {
                    roll_to_hit(pawn, Target);
                }

                if (!Target.Dead)
                {
                    xxx.reduce_rest(Target, 1);
                }
                xxx.reduce_rest(pawn, 2);

                if (Genital_Helper.has_penis(pawn) || Genital_Helper.has_penis_infertile(pawn))
                {
                    // Face same direction, most of animal sex is likely doggystyle.
                    Target.Rotation = pawn.Rotation;
                }
            };

            breed.AddFinishAction(delegate
            {
                if ((Target.jobs != null) &&
                    (Target.jobs.curDriver != null) &&
                    (Target.jobs.curDriver as JobDriver_GettinRaped != null))
                {
                    (Target.jobs.curDriver as JobDriver_GettinRaped).rapist_count -= 1;
                }
                pawn.stances.StaggerFor(Rand.Range(0, 50));
                Target.stances.StaggerFor(Rand.Range(10, 300));
            });

            breed.defaultCompleteMode = ToilCompleteMode.Delay;
            breed.defaultDuration     = duration;
            yield return(breed);

            yield return(new Toil
            {
                initAction = delegate
                {
                    //Log.Message("JobDriver_Breeding::MakeNewToils() - Calling aftersex");
                    //// Trying to add some interactions and social logs
                    bool violent = !(pawn.relations.DirectRelationExists(PawnRelationDefOf.Bond, Target) ||
                                     (xxx.is_animal(pawn) && (pawn.RaceProps.wildness - pawn.RaceProps.petness + 0.18f) > Rand.Range(0.36f, 1.8f)));
                    SexUtility.ProcessSex(pawn, Target, violent);
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            });
        }
Exemplo n.º 4
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            //Rand.PopState();
            //Rand.PushState(RJW_Multiplayer.PredictableSeed());
            //Log.Message("[RJW]" + this.GetType().ToString() + "::MakeNewToils() called");
            duration              = (int)(2000.0f * Rand.Range(0.50f, 0.90f));
            ticks_between_hearts  = Rand.RangeInclusive(70, 130);
            ticks_between_hits    = Rand.Range(xxx.config.min_ticks_between_hits, xxx.config.max_ticks_between_hits);
            ticks_between_thrusts = 100;

            if (xxx.is_bloodlust(pawn))
            {
                ticks_between_hits = (int)(ticks_between_hits * 0.75);
            }
            if (xxx.is_brawler(pawn))
            {
                ticks_between_hits = (int)(ticks_between_hits * 0.90);
            }

            this.FailOnDespawnedNullOrForbidden(iTarget);
            this.FailOn(() => !pawn.CanReserve(Target, xxx.max_rapists_per_prisoner, 0));             // Fail if someone else reserves the prisoner before the pawn arrives
            this.FailOn(() => pawn.IsFighting());
            this.FailOn(() => Target.IsFighting());
            this.FailOn(() => pawn.Drafted);
            yield return(Toils_Goto.GotoThing(iTarget, PathEndMode.OnCell));

            SexUtility.RapeAttemptAlert(pawn, Target);

            //Log.Message("[RJW] JobDriver_Rape::make toils() called");
            var rape = new Toil();

            rape.initAction = delegate
            {
                //Log.Message("[RJW]" + this.GetType().ToString() + "::initAction() called");
                //pawn.Reserve(Target, comfort_prisoners.max_rapists_per_prisoner, 0);
                //if (!pawnHasPenis)
                //	Target.rotationTracker.Face(pawn.DrawPos);
                JobDriver_GettinRaped dri = Target.jobs.curDriver as JobDriver_GettinRaped;
                if (dri == null)
                {
                    Job          gettin_raped = new Job(xxx.gettin_raped, pawn, Target);
                    Building_Bed Bed          = null;
                    //Log.Message(xxx.get_pawnname(pawn) + " LayingInBed:" + pawn.GetPosture());
                    //Log.Message(xxx.get_pawnname(Target) + " LayingInBed:" + Target.GetPosture());
                    if (Target.GetPosture() == PawnPosture.LayingInBed)
                    {
                        Bed = Target.CurrentBed();
                        //Log.Message(xxx.get_pawnname(Target) + ": bed:" + Bed);
                    }
                    Target.jobs.StartJob(gettin_raped, JobCondition.InterruptForced, null, false, true, null);
                    (Target.jobs.curDriver as JobDriver_GettinRaped)?.increase_time(duration);
                    if (Bed != null)
                    {
                        (Target.jobs.curDriver as JobDriver_GettinRaped)?.set_bed(Bed);
                    }
                }
                else
                {
                    dri.rapist_count += 1;
                    dri.increase_time(duration);
                }
                rape.FailOn(() => Target.CurJob == null || Target.CurJob.def != xxx.gettin_raped || Target.IsFighting() || pawn.IsFighting());
            };
            rape.tickAction = delegate
            {
                //Log.Message("[RJW] JobDriver_Rape::tickAction() called");
                if (pawn.IsHashIntervalTick(ticks_between_hearts))
                {
                    MoteMaker.ThrowMetaIcon(pawn.Position, pawn.Map, ThingDefOf.Mote_Heart);
                }
                if (pawn.IsHashIntervalTick(ticks_between_thrusts))
                {
                    xxx.sexTick(pawn, Target, false);
                }
                if (pawn.IsHashIntervalTick(ticks_between_hits))
                {
                    roll_to_hit(pawn, Target);
                }
                xxx.reduce_rest(Target, 1);
                xxx.reduce_rest(pawn, 2);
            };
            rape.AddFinishAction(delegate
            {
                if (Target.jobs?.curDriver is JobDriver_GettinRaped)
                {
                    (Target.jobs.curDriver as JobDriver_GettinRaped).rapist_count -= 1;
                }
            });
            rape.defaultCompleteMode = ToilCompleteMode.Delay;
            rape.defaultDuration     = duration;
            yield return(rape);

            yield return(new Toil
            {
                initAction = delegate
                {
                    //Log.Message("[RJW] JobDriver_Rape::aftersex() called");
                    //// Trying to add some interactions and social logs
                    SexUtility.ProcessSex(pawn, Target, true);
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            });
        }