static bool Prefix(ref JobGiver_Manhunter __instance, ref Job __result, ref Pawn pawn) { //Log.Warning("Detected Animal Attack"); bool hasRangedVerb = false; //Log.Warning("Trying to fire at pawn"); List <Verb> verbList = pawn.verbTracker.AllVerbs; //Log.Warning("Got list of verb"); List <Verb> rangeList = new List <Verb>(); for (int i = 0; i < verbList.Count; i++) { //Log.Warning("Checkity"); //It corresponds with verbs anyway if (verbList[i].verbProps.range > 1.1f) { rangeList.Add(verbList[i]); hasRangedVerb = true; } //Log.Warning("Added Ranged Verb"); } //Log.Warning("got list of ranged verb"); //If there is no ranged verb just return; if (hasRangedVerb == false) { return(true); } Verb rangeVerb = rangeList.RandomElementByWeight((Verb rangeItem) => rangeItem.verbProps.commonality); if (rangeVerb == null) { Log.Warning("Can't get random range verb"); return(true); } //Log.Warning("Range verb detected"); Thing target = (Thing)ARA_AttackTargetFinder.BestAttackTarget((IAttackTargetSearcher)pawn, TargetScanFlags.NeedThreat | TargetScanFlags.NeedReachable, (Predicate <Thing>)(x => x is Pawn || x is Building), 0.0f, 9999, new IntVec3(), float.MaxValue, false); //Seek thing hiding in embrasure. if (target == null) { target = (Thing)ARA_AttackTargetFinder.BestAttackTarget((IAttackTargetSearcher)pawn, TargetScanFlags.NeedThreat, (Predicate <Thing>)(x => x is Pawn || x is Building), 0.0f, 9999, new IntVec3(), float.MaxValue, false); } //Use normal manhunter //Can't check for target if it doesn't exist duh //Log.Warning("CurrentEffectiveVerb " + pawn.CurrentEffectiveVerb); /* * Log.Warning("Effective Range " + pawn.CurrentEffectiveVerb.verbProps.range); * if (!pawn.CurrentEffectiveVerb.verbProps.MeleeRange) * { * Log.Warning("Not melee range"); * } */ bool targetInSight = false; Thing shootable = null; if (target == null) { shootable = (Thing)ARA_AttackTargetFinder.BestShootTargetFromCurrentPosition(pawn, (Predicate <Thing>)(x => x is Pawn || x is Building), rangeVerb.verbProps.range, rangeVerb.verbProps.minRange, TargetScanFlags.NeedThreat | TargetScanFlags.NeedLOSToPawns | TargetScanFlags.LOSBlockableByGas); //Log.Warning("Shootable found, " + shootable); if (shootable == null) { //Log.Warning("No target in line of site"); return(true); } targetInSight = true; } else if (target.Position.DistanceTo(pawn.Position) < rangeVerb.verbProps.minRange || target.Position.AdjacentTo8Way(pawn.Position)) { //Log.Warning("Target too close, melee!"); //Core code can't handle animal anymore if (pawn.CanReach(target, PathEndMode.Touch, Danger.Deadly, false)) { //Log.Warning("Melee Attack"); __result = new Job(JobDefOf.AttackMelee, target) { maxNumMeleeAttacks = 1, expiryInterval = Rand.Range(420, 900), attackDoorIfTargetLost = false }; return(false); } else { return(true); } } //Log.Warning("Got target"); //Formally range attack job //if (target != null && pawn.CanReach(target, PathEndMode.Touch, Danger.Deadly, false)) //Log.Warning("Ranged verb selected, range of " + verb.verbProps.range); IntVec3 intVec; //Log.Warning("Trying to shoot"); //Searches for target within range again. if (!targetInSight) { //Log.Warning("No target"); shootable = (Thing)ARA_AttackTargetFinder.BestShootTargetFromCurrentPosition(pawn, (Predicate <Thing>)(x => x is Pawn || x is Building), rangeVerb.verbProps.range, rangeVerb.verbProps.minRange, TargetScanFlags.NeedThreat | TargetScanFlags.NeedLOSToPawns | TargetScanFlags.LOSBlockableByGas); } if (shootable != null) { //Log.Warning("Got Shootable"); if (target.Position.DistanceTo(pawn.Position) < rangeVerb.verbProps.minRange || target.Position.AdjacentTo8Way(pawn.Position)) { //Log.Warning("Target too close, melee!"); //Core code can't handle animal anymore if (pawn.CanReach(target, PathEndMode.Touch, Danger.Deadly, false)) { //Log.Warning("Melee Attack"); __result = new Job(JobDefOf.AttackMelee, target) { maxNumMeleeAttacks = 1, expiryInterval = Rand.Range(420, 900), attackDoorIfTargetLost = false }; return(false); } else { //Log.Warning("Target too close and I can't melee right away"); return(true); } } //Log.Warning("Trying initiate job"); __result = new Job(DefDatabase <JobDef> .GetNamed("AA_AlphaAnimalRangeAttack"), shootable, JobGiver_AIFightEnemy.ExpiryInterval_ShooterSucceeded.RandomInRange, true) { verbToUse = rangeVerb }; //Log.Warning("Succesfully created job"); return(false); } //Target is not null if (target != null) { //Can't shoot at target from current position. Find a new position bool canShootCondition = false; //Log.Warning("Try casting"); canShootCondition = CastPositionFinder.TryFindCastPosition(new CastPositionRequest { caster = pawn, target = target, verb = rangeVerb, maxRangeFromTarget = 9999, wantCoverFromTarget = false }, out intVec); if (!canShootCondition) { //Log.Warning("Can't find place to shoot at target"); return(true); } //Log.Warning("Going"); //Go to new destination //Protection againt not being able to find target. if (pawn.Position == intVec) { //Log.Warning(pawn + " already at position to shoot, but target not selected to shoot."); __result = new Job(JobDefOf.Wait, 100); return(false); } __result = new Job(JobDefOf.Goto, intVec) { expiryInterval = JobGiver_AIFightEnemy.ExpiryInterval_ShooterSucceeded.RandomInRange, checkOverrideOnExpire = true }; return(false); } //Log.Warning("Hit end condition"); return(true); }
static bool Prefix(ref JobGiver_Manhunter __instance, ref Job __result, ref Pawn pawn) { //Log.Warning("Man hunter detected"); if (!pawn.RaceProps.Animal) { return(true); } bool hasRangedVerb = false; List <Verb> verbList = pawn.verbTracker.AllVerbs; List <Verb> rangeList = new List <Verb>(); for (int i = 0; i < verbList.Count; i++) { //Log.Warning("Checkity"); //It corresponds with verbs anyway if (!verbList[i].verbProps.IsMeleeAttack) { rangeList.Add(verbList[i]); hasRangedVerb = true; //Log.Warning("Added Ranged Verb"); } } if (hasRangedVerb == false) { // Log.Warning("I don't have range verb"); return(true); } // this.SetCurMeleeVerb(updatedAvailableVerbsList.RandomElementByWeight((VerbEntry ve) => ve.SelectionWeight).verb); Verb rangeVerb = rangeList.RandomElementByWeight((Verb rangeItem) => rangeItem.verbProps.commonality); if (rangeVerb == null) { //Log.Warning("Can't get random range verb"); return(true); } //Seek enemy in conventional way. Thing enemyTarget = (Thing)ARA_AttackTargetFinder.BestAttackTarget((IAttackTargetSearcher)pawn, TargetScanFlags.NeedThreat | TargetScanFlags.NeedReachable, (Predicate <Thing>)(x => x is Pawn || x is Building), 0.0f, 9999, new IntVec3(), float.MaxValue, false); //Seek thing hiding in embrasure. if (enemyTarget == null) { enemyTarget = (Thing)ARA_AttackTargetFinder.BestAttackTarget((IAttackTargetSearcher)pawn, TargetScanFlags.NeedThreat, (Predicate <Thing>)(x => x is Pawn || x is Building), 0.0f, 9999, new IntVec3(), float.MaxValue, false); } if (enemyTarget == null) { //Log.Warning("I can't find anything to fight."); return(true); } //Check if enemy directly next to pawn if (enemyTarget.Position.DistanceTo(pawn.Position) < rangeVerb.verbProps.minRange) { //If adjacent melee attack if (enemyTarget.Position.AdjacentTo8Way(pawn.Position)) { __result = new Job(JobDefOf.AttackMelee, enemyTarget) { maxNumMeleeAttacks = 1, expiryInterval = Rand.Range(420, 900), attackDoorIfTargetLost = false }; return(false); } return(true); } //Log.Warning("got list of ranged verb"); //Log.Warning("Attempting flag"); bool flag1 = (double)CoverUtility.CalculateOverallBlockChance(pawn.Position, enemyTarget.Position, pawn.Map) > 0.00999999977648258; bool flag2 = pawn.Position.Standable(pawn.Map); bool flag3 = rangeVerb.CanHitTarget(enemyTarget); bool flag4 = (pawn.Position - enemyTarget.Position).LengthHorizontalSquared < 25; if (flag1 && flag2 && flag3 || flag4 && flag3) { //Log.Warning("Shooting"); __result = new Job(DefDatabase <JobDef> .GetNamed("PI_AnimalRangeAttack"), enemyTarget, JobGiver_AIFightEnemy.ExpiryInterval_ShooterSucceeded.RandomInRange, true) { verbToUse = rangeVerb }; return(false); } IntVec3 dest; bool canShootCondition = false; canShootCondition = CastPositionFinder.TryFindCastPosition(new CastPositionRequest { caster = pawn, target = enemyTarget, verb = rangeVerb, maxRangeFromTarget = rangeVerb.verbProps.range, wantCoverFromTarget = false, maxRegions = 50 }, out dest); if (!canShootCondition) { //Log.Warning("I can't move to shooting position"); return(true); } if (dest == pawn.Position) { //Log.Warning("I will stay here and attack"); __result = new Job(DefDatabase <JobDef> .GetNamed("PI_AnimalRangeAttack"), enemyTarget, JobGiver_AIFightEnemy.ExpiryInterval_ShooterSucceeded.RandomInRange, true) { verbToUse = rangeVerb }; return(false); } //Log.Warning("Going to new place"); __result = new Job(JobDefOf.Goto, (LocalTargetInfo)dest) { expiryInterval = JobGiver_AIFightEnemy.ExpiryInterval_ShooterSucceeded.RandomInRange, checkOverrideOnExpire = true }; return(false); }