public static void DoBehaviorForPawn(JobDriver_Wait driver) { var hunter = driver.pawn; if (!AllowToolController.Instance.Handles.PartyHuntSetting || !WorldSettings.PawnIsPartyHunting(hunter)) { return; } var verb = hunter.TryGetAttackVerb(null, !hunter.IsColonist); if (hunter.Faction != null && driver.job.def == JobDefOf.Wait_Combat && AllowToolUtility.PawnCapableOfViolence(hunter) && !hunter.stances.FullBodyBusy) { // fire at target if (hunter.drafter.FireAtWill) { // fudge melee range for easier target acquisition var weaponRange = verb.verbProps.IsMeleeAttack ? 2 : verb.verbProps.range; var target = TryFindHuntingTarget(hunter, verb.verbProps.minRange, weaponRange, HuntingTargetAttackFilter); if (target != null) { hunter.TryStartAttack(target); ResetAutoUndraftTimer(hunter.drafter); if (target.Dead && WorldSettings.UnforbidDrops) { target.Corpse?.SetForbidden(false, false); } } } // finish off targets. Wait for everyone to finish firing to avoid catching stray bullets if (!hunter.stances.FullBodyBusy && WorldSettings.AutoFinishOff && CanDoCommonerWork(hunter) && !AnyHuntingPartyMembersInCombat(hunter, MaxPartyMemberDistance)) { // try mark a downed animal var target = TryFindHuntingTarget(hunter, 0, MaxFinishOffDistance, HuntingTargetFinishFilter); if (target != null) { target.ToggleDesignation(AllowToolDefOf.FinishOffDesignation, true); } // query work giver for finish off job in range var job = WorkGiver_FinishOff.CreateInstance().TryGetJobInRange(hunter, MaxFinishOffDistance); if (job != null) { hunter.jobs.StartJob(job, JobCondition.Ongoing, null, true); if (hunter.jobs.curDriver is JobDriver_FinishOff jdfo && WorldSettings.UnforbidDrops) { jdfo.UnforbidBody = true; } // return to starting position hunter.jobs.jobQueue.EnqueueFirst(JobMaker.MakeJob(JobDefOf.Goto, hunter.Position)); } } } }
protected override IEnumerable <Toil> MakeNewToils() { if (job.playerForced) { TargetA.Thing.ToggleDesignation(AllowToolDefOf.FinishOffDesignation, true); } AddFailCondition(JobHasFailed); yield return(Toils_Misc.ThrowColonistAttackingMote(TargetIndex.A)); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch)); Thing skullMote = null; yield return(new Toil { initAction = () => { var victim = job.targetA.Thing as Pawn; skullMote = TryMakeSkullMote(victim, VictimSkullMoteChance); AllowToolDefOf.EffecterWeaponGlint.Spawn().Trigger(pawn, job.targetA.Thing); }, defaultDuration = PrepareSwingDuration, defaultCompleteMode = ToilCompleteMode.Delay }); yield return(new Toil { initAction = () => { var victim = job.targetA.Thing as Pawn; if (victim == null || job.verbToUse == null) { return; } job.verbToUse.TryStartCastOn(victim); DoSocialImpact(victim); DoExecution(pawn, victim); if (skullMote != null && !skullMote.Destroyed) { skullMote.Destroy(); } // look for a target of opportunity nearby before moving on // needed by drafted hunters. Their finish off job was not work-related, so they need to be fed a new opportunity job manually if (!job.playerForced) { var opportunityJob = WorkGiver_FinishOff.CreateInstance().TryGetJobInRange(pawn, OpportunityTargetMaxRange); if (opportunityJob != null) { pawn.jobs.jobQueue.EnqueueFirst(opportunityJob); } } }, defaultCompleteMode = ToilCompleteMode.Instant }); }