Ejemplo n.º 1
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            this.FailOnDestroyedOrNull(iPrisoner);
            this.FailOnDestroyedOrNull(iSacrificeBuilding);
            this.FailOnAggroMentalState(iPrisoner);

            yield return(Toils_Goto.GotoThing(iPrisoner, PathEndMode.OnCell));

            yield return(Toils_Haul.StartCarryThing(iPrisoner, true, false));

            yield return(Toils_Goto.GotoThing(iSacrificeBuilding, SacrificeSpot.InteractionCell));

            yield return(Toils_Reserve.Release(iPrisoner));

            var doSacrificePrisoner = new Toil
            {
                socialMode = RandomSocialMode.Off,
            };

            doSacrificePrisoner.initAction = () =>
            {
                Sacrificer.carryTracker.TryDropCarriedThing(SacrificeSpot.InteractionCell, ThingPlaceMode.Direct, out var thing, null);
                Prisoner.jobs.StartJob(JobMaker.MakeJob(Defs.PrisonerWait));
            };
            doSacrificePrisoner.AddFailCondition(() => Prisoner.Dead);
            doSacrificePrisoner.defaultCompleteMode = ToilCompleteMode.Never;
            doSacrificePrisoner.AddPreTickAction(() =>
            {
                --TicksLeft;
                if (TicksLeft <= 0)
                {
                    ReadyForNextToil();
                }
            });
            yield return(doSacrificePrisoner.WithProgressBar(iPawn, () => (TicksMax - (float)TicksLeft) / TicksMax));

            var afterSacrificePrisoner = new Toil
            {
                defaultCompleteMode = ToilCompleteMode.Instant,
                initAction          = () =>
                {
                    var heartBpr = Prisoner.RaceProps.body.AllParts.Find(bpr => bpr.def.defName == "Heart");
                    var dInfo    = new DamageInfo(Defs.HeartExtraction, 99999f, armorPenetration: 999f, hitPart: heartBpr);
                    Prisoner.Kill(dInfo);
                    ThoughtUtility.GiveThoughtsForPawnExecuted(Prisoner, Sacrificer, PawnExecutionKind.GenericBrutal);

                    // Apply negative relations modifier.
                    if (pawn.Faction != null && Prisoner.Faction != null)
                    {
                        Faction          playerFaction   = pawn.Faction;
                        Faction          prisonerFaction = Prisoner.Faction;
                        string           reason          = "GoodwillChangedReason_RemovedBodyPart".Translate(heartBpr.Label);
                        GlobalTargetInfo?LookTargets     = pawn;
                        playerFaction.TryAffectGoodwillWith(prisonerFaction, -25);
                    }

                    // Apply thoughts to pawns.
                    foreach (var mapPawn in Map.mapPawns.FreeColonistsAndPrisoners)
                    {
                        if (mapPawn.IsPrisoner)
                        {
                            mapPawn.needs.mood.thoughts.memories.TryGainMemory(Defs.SacrificedFear);
                        }
                        else if (mapPawn.IsColonist && (mapPawn.IsRevia() || mapPawn.IsSkarnite()))
                        {
                            mapPawn.needs.mood.thoughts.memories.TryGainMemory(Defs.SacrificedPositive);
                        }
                        else if (mapPawn.IsColonist &&
                                 !(mapPawn.IsCannibal() || mapPawn.IsPsychopath() || mapPawn.IsBloodlust()))
                        {
                            mapPawn.needs.mood.thoughts.memories.TryGainMemory(Defs.SacrificedNegative);
                        }
                    }

                    // Spawn the product, or handle one of the other effects.
                    // Find a good spot to spawn the product.
                    IntVec3 spawnPos = CellFinder.FindNoWipeSpawnLocNear(
                        Prisoner.Position,
                        Map,
                        Defs.Bloodstone,
                        Rot4.Random, 6, pos =>
                    {
                        return
                        ((pos.x < Prisoner.Position.x - 1 || pos.x > Prisoner.Position.x + 1) &&
                         // F**k you Tynan. Learn your coordinates!
                         (pos.z < Prisoner.Position.z - 1 || pos.z > Prisoner.Position.z + 1));
                    });

                    if (Map.GameConditionManager.ConditionIsActive(Defs.Eclipse))
                    {
                        var missingParts = pawn.health.hediffSet.GetMissingPartsCommonAncestors();
                        if (missingParts.Count > 0)
                        {
                            var missing = missingParts.RandomElement();
                            pawn.health.hediffSet.hediffs.Remove(missing);
                            var maxHp = missing.Part.def.GetMaxHealth(pawn);

                            var injuryHediff   = pawn.health.AddHediff(HediffDefOf.Cut, missing.Part, new DamageInfo(DamageDefOf.Rotting, 1.0f, 10000.00f));
                            var permHediffComp = injuryHediff.TryGetComp <HediffComp_GetsPermanent>();
                            injuryHediff.Severity      = maxHp / 2.0f;
                            permHediffComp.IsPermanent = true;
                        }
                        else
                        {
                            var thing = GenSpawn.Spawn(Defs.Bloodstone, spawnPos, Map);
                            thing.stackCount += 2;
                        }
                    }
                    else if (Map.GameConditionManager.ConditionIsActive(Defs.SolarFlare))
                    {
                        var permInjuries = pawn.health.hediffSet.hediffs.Where(h => h.IsPermanent() && !(h is Hediff_MissingPart)).ToList();
                        if (permInjuries.Count > 0)
                        {
                            var randomInjury = permInjuries.RandomElement();
                            randomInjury.Severity -= randomInjury.Part.depth == BodyPartDepth.Inside ? 2.0f : 4.0f;
                        }
                        else
                        {
                            var thing = GenSpawn.Spawn(Defs.Bloodstone, spawnPos, Map);
                            thing.stackCount += 1;
                        }
                    }
                    else
                    {
                        var thing = GenSpawn.Spawn(Defs.Bloodstone, spawnPos, Map);
                    }

                    var bloodthirst = Sacrificer.needs.TryGetNeed <BloodthirstNeed>();
                    if (bloodthirst != null)
                    {
                        bloodthirst.CurLevel += 0.80f * Prisoner.BodySize;
                    }
                    TaleRecorder.RecordTale(Defs.TaleSacrificed, new[] { Sacrificer, Prisoner });

                    // Find a good spot to move the prisoner corpse.
                    IntVec3 movePos = CellFinder.FindNoWipeSpawnLocNear(
                        Prisoner.Position,
                        Map,
                        Prisoner.Corpse.def,
                        Rot4.Random, 6, pos =>
                    {
                        return
                        ((pos.x < Prisoner.Position.x - 1 || pos.x > Prisoner.Position.x + 1) &&
                         // F**k you Tynan. Learn your coordinates!
                         (pos.z < Prisoner.Position.z - 1 || pos.z > Prisoner.Position.z + 1));
                    });
                    Prisoner.Corpse.Position = movePos;
                }
            };

            yield return(afterSacrificePrisoner);
        }