Building_MechanoidTerraformer class.
Inheritance: Building
        public override bool HasJobOnThing(Pawn pawn, Thing t)
        {
            if ((t is Building_MechanoidTerraformer) == false)
            {
                return(false);
            }

            Building_MechanoidTerraformer terraformer = t as Building_MechanoidTerraformer;

            if (pawn.Dead ||
                pawn.Downed ||
                pawn.IsBurning())
            {
                return(false);
            }
            if ((terraformer.reverseEngineeringState == Building_MechanoidTerraformer.ReverseEngineeringState.Studying) &&
                (pawn.skills.GetSkill(SkillDefOf.Research).level >= Building_MechanoidTerraformer.minResearchLevelToStudyArtifact) &&
                pawn.CanReserveAndReach(terraformer, this.pathEndMode, Danger.Some) &&
                (terraformer.studyIsPaused == false) &&
                (terraformer.studyCounter < Building_MechanoidTerraformer.studyCounterTargetValue))
            {
                return(true);
            }
            else if ((terraformer.reverseEngineeringState == Building_MechanoidTerraformer.ReverseEngineeringState.ReroutingPower) &&
                     (pawn.skills.GetSkill(SkillDefOf.Research).level >= Building_MechanoidTerraformer.minResearchLevelToReroutePower) &&
                     pawn.CanReserveAndReach(terraformer, this.pathEndMode, Danger.Some) &&
                     (terraformer.reroutingIsPaused == false) &&
                     (terraformer.reroutingCounter < Building_MechanoidTerraformer.reroutingCounterTargetValue))
            {
                return(true);
            }
            else if ((terraformer.reverseEngineeringState == Building_MechanoidTerraformer.ReverseEngineeringState.ExtractingWeatherController) &&
                     (pawn.skills.GetSkill(SkillDefOf.Research).level >= Building_MechanoidTerraformer.minResearchLevelToExtractWeatherController) &&
                     pawn.CanReserveAndReach(terraformer, this.pathEndMode, Danger.Some) &&
                     (terraformer.extractionIsPaused == false) &&
                     (terraformer.extractionCounter < Building_MechanoidTerraformer.extractionCounterTargetValue))
            {
                return(true);
            }
            return(false);
        }
        public override Job JobOnThing(Pawn pawn, Thing t)
        {
            Job job = new Job();
            Building_MechanoidTerraformer terraformer = t as Building_MechanoidTerraformer;

            switch (terraformer.reverseEngineeringState)
            {
            case Building_MechanoidTerraformer.ReverseEngineeringState.Studying:
                job = new Job(DefDatabase <JobDef> .GetNamed(Util_MechanoidTerraformer.JobDefName_StudyStrangeArtifact), terraformer);
                break;

            case Building_MechanoidTerraformer.ReverseEngineeringState.ReroutingPower:
                job = new Job(DefDatabase <JobDef> .GetNamed(Util_MechanoidTerraformer.JobDefName_ReroutePower), terraformer);
                break;

            case Building_MechanoidTerraformer.ReverseEngineeringState.ExtractingWeatherController:
                job = new Job(DefDatabase <JobDef> .GetNamed(Util_MechanoidTerraformer.JobDefName_ExtractWeatherController), terraformer);
                break;
            }
            return(job);
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            Passion     passion            = Passion.None;
            const float skillGainPerTick   = 0.15f;
            float       skillGainFactor    = 0f;
            int         extractionDuration = 0;

            float statValue = this.pawn.GetStatValue(StatDefOf.ResearchSpeed, true);

            extractionDuration = (int)Math.Round((double)(1200f / statValue));

            yield return(Toils_Reserve.Reserve(terraformerIndex));

            yield return(Toils_Goto.GotoCell(terraformerIndex, PathEndMode.InteractionCell).FailOnDestroyed(terraformerIndex));

            Toil extractionToil = new Toil()
            {
                initAction = () =>
                {
                    passion = this.pawn.skills.MaxPassionOfRelevantSkillsFor(WorkTypeDefOf.Research);
                    if (passion == Passion.None)
                    {
                        skillGainFactor = 0.3f;
                    }
                    else if (passion == Passion.Minor)
                    {
                        skillGainFactor = 1f;
                    }
                    else
                    {
                        skillGainFactor = 1.5f;
                    }
                },
                tickAction = () =>
                {
                    this.pawn.skills.Learn(SkillDefOf.Research, skillGainPerTick * skillGainFactor);
                },
                defaultCompleteMode = ToilCompleteMode.Delay,
                defaultDuration     = extractionDuration
            };

            yield return(extractionToil.FailOnDestroyed(terraformerIndex));

            yield return(Toils_Reserve.Release(terraformerIndex));

            Toil incrementExtractionCounterToil = new Toil()
            {
                initAction = () =>
                {
                    Building_MechanoidTerraformer terraformer = this.TargetThingA as Building_MechanoidTerraformer;
                    terraformer.extractionCounter++;
                    if (terraformer.extractionCounter >= Building_MechanoidTerraformer.extractionCounterTargetValue)
                    {
                        terraformer.FinishWeatherControllerExtraction();
                    }
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            };

            yield return(incrementExtractionCounterToil);
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            Passion     passion          = Passion.None;
            const float skillGainPerTick = 0.15f;
            float       skillGainFactor  = 0f;
            int         studyDuration    = 0;

            float statValue = this.pawn.GetStatValue(StatDefOf.ResearchSpeed, true);

            studyDuration = (int)Math.Round((double)(1200f / statValue));

            yield return(Toils_Reserve.Reserve(terraformerIndex));

            yield return(Toils_Goto.GotoCell(terraformerIndex, PathEndMode.InteractionCell).FailOnDestroyed(terraformerIndex));

            Toil studyToil = new Toil()
            {
                initAction = () =>
                {
                    passion = this.pawn.skills.MaxPassionOfRelevantSkillsFor(WorkTypeDefOf.Research);
                    if (passion == Passion.None)
                    {
                        skillGainFactor = 0.3f;
                    }
                    else if (passion == Passion.Minor)
                    {
                        skillGainFactor = 1f;
                    }
                    else
                    {
                        skillGainFactor = 1.5f;
                    }
                },
                tickAction = () =>
                {
                    this.pawn.skills.Learn(SkillDefOf.Research, skillGainPerTick * skillGainFactor);
                },
                defaultCompleteMode = ToilCompleteMode.Delay,
                defaultDuration     = studyDuration
            };

            yield return(studyToil);

            Toil incrementStudyCounterToil = new Toil()
            {
                initAction = () =>
                {
                    Building_MechanoidTerraformer terraformer = this.TargetThingA as Building_MechanoidTerraformer;
                    terraformer.studyCounter++;
                    if (terraformer.studyCounter >= Building_MechanoidTerraformer.studyCounterTargetValue)
                    {
                        string herHisOrIts = "its";
                        if (pawn.gender == Gender.Female)
                        {
                            herHisOrIts = "her";
                        }
                        else if (pawn.gender == Gender.Male)
                        {
                            herHisOrIts = "his";
                        }
                        string studyReportHeader = "   " + pawn.Name.ToStringShort + " has finished the study of the strange artifact. "
                                                   + herHisOrIts.CapitalizeFirst() + " report is quite alarming!\n\n\n"
                                                   + "### Study references ###\n\n"
                                                   + "Date: " + GenDate.DateFullStringAt(Find.TickManager.TicksAbs) + "\n"
                                                   + "Researcher: " + pawn.Name.ToStringFull + "\n\n";
                        terraformer.DisplayStudyReport(studyReportHeader);
                        terraformer.def.label = "Mechanoid terraformer";
                        terraformer.reverseEngineeringState            = Building_MechanoidTerraformer.ReverseEngineeringState.StudyCompleted;
                        Building_MechanoidTerraformer.studyIsCompleted = true;
                    }
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            };

            yield return(incrementStudyCounterToil);

            yield return(Toils_Reserve.Release(terraformerIndex));
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            yield return(Toils_Reserve.Reserve(terraformerIndex));

            yield return(Toils_Goto.GotoCell(terraformerIndex, PathEndMode.InteractionCell).FailOnDestroyed(terraformerIndex));

            yield return(Toils_General.Wait(1500).FailOnDestroyed(terraformerIndex));

            Toil beaconDisablingResultToil = new Toil()
            {
                initAction = () =>
                {
                    string     eventTitle       = "";
                    string     eventText        = "";
                    float      raidPointsFactor = 1f;
                    int        dropsNumber      = 0;
                    LetterType letterType       = LetterType.BadUrgent;

                    Building_MechanoidTerraformer terraformer = this.TargetThingA as Building_MechanoidTerraformer;
                    terraformer.invasionIsDone = true;

                    string sheHeOrIt   = "it";
                    string herHimOrIt  = "it";
                    string herHisOrIts = "its";
                    if (pawn.gender == Gender.Female)
                    {
                        sheHeOrIt   = "she";
                        herHisOrIts = "her";
                        herHimOrIt  = "her";
                    }
                    else if (pawn.gender == Gender.Male)
                    {
                        sheHeOrIt   = "he";
                        herHisOrIts = "his";
                        herHimOrIt  = "him";
                    }

                    if ((this.pawn.skills.GetSkill(SkillDefOf.Research).TotallyDisabled == true) ||
                        (this.pawn.skills.GetSkill(SkillDefOf.Research).level < 3))
                    {
                        eventTitle = "Invasion";
                        eventText  = "   " + this.pawn.Name.ToStringShort + " has tried to disable the terraformer beacon but technology is not " + herHisOrIts + " big passion... "
                                     + sheHeOrIt.CapitalizeFirst() + " just pressed on every button alerting by the way every nearby mechanoid shuttles.\n\n"
                                     + "Be prepared to welcome some nasty and numerous visitors from nearby mechanoid hives!";

                        raidPointsFactor = 1.4f;
                        dropsNumber      = 5;
                        letterType       = LetterType.BadUrgent;
                    }
                    else if (this.pawn.skills.GetSkill(SkillDefOf.Research).level == 20)
                    {
                        eventTitle = "Beacon disabled";
                        eventText  = "   " + this.pawn.Name.ToStringShort + " is a real crack in alien technology. Disabling the terraformer beacon was just another game for " + herHimOrIt + "\n\n"
                                     + "You have nothing to fear from it anymore.";

                        raidPointsFactor = 0f;
                        dropsNumber      = 0;
                        letterType       = LetterType.Good;
                    }
                    else
                    {
                        float rand = Rand.Value * 100;
                        if (rand < this.pawn.skills.GetSkill(SkillDefOf.Research).level *chanceToSucceedPerResearchLevel)
                        {
                            // Disable sucessfull.
                            eventTitle = "Beacon disabled";
                            eventText  = "   Even if " + this.pawn.Name.ToStringShort + " is not the best about alien technology, " + sheHeOrIt + " successfully disabled the terraformer beacon!\n\n"
                                         + "You have nothing to fear from it anymore.";

                            raidPointsFactor = 0f;
                            dropsNumber      = 0;
                            letterType       = LetterType.Good;
                        }
                        else
                        {
                            // Bad luck.
                            eventTitle = "Invasion";
                            eventText  = "   " + this.pawn.Name.ToStringShort + " has some knowledge about alien technology but " + sheHeOrIt + " still failed at properly disabling the terraformer beacon.\n\n"
                                         + "Be prepared to welcome the incoming terrafomer defending force.";

                            raidPointsFactor = 0.4f;
                            dropsNumber      = 2;
                            letterType       = LetterType.BadUrgent;
                        }
                    }
                    terraformer.LaunchInvasion(eventTitle, eventText, raidPointsFactor, dropsNumber, letterType);
                },
                defaultCompleteMode = ToilCompleteMode.Instant
            };

            yield return(beaconDisablingResultToil);

            yield return(Toils_Reserve.Release(terraformerIndex));
        }