protected override IEnumerable <Toil> MakeNewToils() { //fail if can't do violence base.AddFailCondition(delegate { return(this.pawn.WorkTagIsDisabled(WorkTags.Violent)); }); this.jobStartTick = Find.TickManager.TicksGame; Func <bool> designationValidator = () => !( // Dummy must have the any designation TargetThingA.HasDesignation(CombatTrainingDefOf.TrainCombatDesignation) || // Dummy must have the melee designation, and the pawn has a melee weapon held TargetThingA.HasDesignation(CombatTrainingDefOf.TrainCombatDesignationMeleeOnly) && pawn.equipment.Primary.def.IsMeleeWeapon || // Dummy must have the ranged designation, and the pawn has a ranged weapon held TargetThingA.HasDesignation(CombatTrainingDefOf.TrainCombatDesignationRangedOnly) && pawn.equipment.Primary.def.IsRangedWeapon || // Dummy must have any designation, and the pawn is unarmed. (TargetThingA.HasDesignation(CombatTrainingDefOf.TrainCombatDesignation) || TargetThingA.HasDesignation(CombatTrainingDefOf.TrainCombatDesignationMeleeOnly) || TargetThingA.HasDesignation(CombatTrainingDefOf.TrainCombatDesignationRangedOnly)) && pawn.equipment.Primary == null); //make sure thing has train combat designation if (designationValidator()) { yield break; } // Make sure our dummy isn't already in use this.FailOnSomeonePhysicallyInteracting(TargetIndex.A); //fail if dummy is despawned null or forbidden this.FailOnDespawnedNullOrForbidden(TargetIndex.A); /**** START SWITCH TO TRAINING WEAPON ****/ //Pick up a training weapon if one is nearby. Remember previous weapon ThingWithComps startingEquippedWeapon = this.pawn.equipment.Primary; ThingWithComps trainingWeapon = null; if (startingEquippedWeapon == null || !startingEquippedWeapon.def.IsWithinCategory(CombatTrainingDefOf.TrainingWeapons)) { trainingWeapon = GetNearestTrainingWeapon(startingEquippedWeapon); if (trainingWeapon != null && !trainingWeapon.IsForbidden(pawn)) { //reserve training weapon, goto, and equip if (this.Map.reservationManager.CanReserve(this.pawn, trainingWeapon, 1, -1, null, false)) { this.pawn.Reserve(trainingWeapon, this.job, 1, -1, null, true); this.job.SetTarget(TargetIndex.B, trainingWeapon); yield return(Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.B)); yield return(CreateEquipToil(TargetIndex.B)); } //reserve previous weapon and set as target c if (this.Map.reservationManager.CanReserve(this.pawn, startingEquippedWeapon, 1, -1, null, false)) { this.pawn.Reserve(startingEquippedWeapon, this.job, 1, -1, null, true); this.job.SetTarget(TargetIndex.C, startingEquippedWeapon); } } } Toil reequipStartingWeaponLabel = Toils_General.Label(); /**** END SWITCH TO TRAINING WEAPON ****/ //set the job's attack verb to melee or shooting - needed to gotoCastPosition or stack overflow occurs yield return(Toils_Combat.TrySetJobToUseAttackVerb(TargetIndex.A)); //based on attack verb, go to cast position Toil gotoCastPos = Toils_Combat.GotoCastPosition(TargetIndex.A, true, 0.95f).EndOnDespawnedOrNull(TargetIndex.A); yield return(gotoCastPos); //try going to new cast position if the target can't be hit from current position yield return(Toils_Jump.JumpIfTargetNotHittable(TargetIndex.A, gotoCastPos)); //training loop - jump if done training -> cast verb -> jump to done training //if done training jumnp to reequipStartingWeaponLabel Toil doneTraining = Toils_Jump.JumpIf(reequipStartingWeaponLabel, delegate { if (LearningSaturated()) { return(true); } else { return(Dummy.Destroyed || Find.TickManager.TicksGame > this.jobStartTick + 5000 || designationValidator()); } }); yield return(doneTraining); Toil castVerb = Toils_Combat.CastVerb(TargetIndex.A, false); castVerb.AddFinishAction(delegate { LearnAttackSkill(); }); yield return(castVerb); yield return(Toils_Jump.Jump(doneTraining)); yield return(reequipStartingWeaponLabel); //gain room buff yield return(Toils_General.Do(delegate { TryGainCombatTrainingRoomThought(); })); //equip strating weapon if (trainingWeapon != null && startingEquippedWeapon != null) { yield return(Toils_Goto.GotoThing(TargetIndex.C, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.C)); yield return(CreateEquipToil(TargetIndex.C)); } yield break; }