public virtual bool CanHitTarget(LocalTargetInfo target, bool sightCheck) { if (target.IsValid && target.Cell.DistanceTo(this.pawn.Position) < this.GetRangeForPawn()) { if ((this.targetParams.canTargetLocations && this.targetParams.CanTarget(new TargetInfo(target.Cell, this.Caster.Map))) || this.targetParams.CanTarget(target.ToTargetInfo(this.Caster.Map))) { if (!sightCheck) { return(true); } if (GenSight.LineOfSight(this.pawn.Position, target.Cell, this.pawn.Map)) { return(true); } List <IntVec3> tempSourceList = new List <IntVec3>(); ShootLeanUtility.LeanShootingSourcesFromTo(this.pawn.Position, target.Cell, this.pawn.Map, tempSourceList); if (tempSourceList.Any(ivc => GenSight.LineOfSight(ivc, target.Cell, this.pawn.Map))) { return(true); } } } return(false); }
public static bool CanSee(ref bool __result, Thing seer, Thing target, Func <IntVec3, bool> validator = null) { List <IntVec3> tempDestList = new List <IntVec3>(); List <IntVec3> tempSourceList = new List <IntVec3>(); ShootLeanUtility.CalcShootableCellsOf(tempDestList, target); for (int index = 0; index < tempDestList.Count; ++index) { if (GenSight.LineOfSight(seer.Position, tempDestList[index], seer.Map, true, validator, 0, 0)) { __result = true; return(false); } } ShootLeanUtility.LeanShootingSourcesFromTo(seer.Position, target.Position, seer.Map, tempSourceList); for (int index1 = 0; index1 < tempSourceList.Count; ++index1) { for (int index2 = 0; index2 < tempDestList.Count; ++index2) { if (GenSight.LineOfSight(tempSourceList[index1], tempDestList[index2], seer.Map, true, validator, 0, 0)) { __result = true; return(false); } } } __result = false; return(false); }
/// <summary> /// LocalTargetInfo friendly variant of AttackTargetFinder.CanSee() /// </summary> /// <param name="caster">Line caster source.</param> /// <param name="target">Target we want to check whether we can see or not.</param> /// <param name="skipFirstCell">Skip the first cell from source?</param> /// <param name="validator">Validator for obstacles, presumably.</param> /// <returns>True if we got Line of Sight, false if not.</returns> public static bool LineOfSightLocalTarget(Thing caster, LocalTargetInfo target, bool skipFirstCell = false, Func <IntVec3, bool> validator = null) { //Use default function if we has a Thing. //To-do: Get this to work without null errors. /*if (target.HasThing && caster != null && target != null) * { * if (target.Thing == caster) * return true; * * //Log.Message("AttackTargetFinder.CanSee(" + caster?.Map.GetUniqueLoadID() + ", " + target.Thing?.Map.GetUniqueLoadID() + ")"); * * return AttackTargetFinder.CanSee(caster, target.Thing); * }*/ //Use homebrewed cariant for just a position. ShootLeanUtility.LeanShootingSourcesFromTo(caster.Position, target.Cell, caster.Map, tempSourceList); //See if we can get target from any source cell. if (tempSourceList.Count > 0) { foreach (IntVec3 sourceCell in tempSourceList) { if (GenSight.LineOfSight(sourceCell, target.Cell, caster.Map, skipFirstCell, validator)) { return(true); } } } return(false); }
public new bool CanHitFromCellIgnoringRange(IntVec3 sourceCell, LocalTargetInfo targ, out IntVec3 goodDest) { if (targ.Thing != null) { if (targ.Thing.Map != this.Caster.Map) { goodDest = IntVec3.Invalid; return(false); } ShootLeanUtility.CalcShootableCellsOf(Verb_ShootCompMountedCE.tempDestList, targ.Thing); for (int i = 0; i < Verb_ShootCompMountedCE.tempDestList.Count; i++) { if (this.CanHitCellFromCellIgnoringRange(sourceCell, Verb_ShootCompMountedCE.tempDestList[i], targ.Thing.def.Fillage == FillCategory.Full)) { goodDest = Verb_ShootCompMountedCE.tempDestList[i]; return(true); } } } else if (this.CanHitCellFromCellIgnoringRange(sourceCell, targ.Cell, false)) { goodDest = targ.Cell; return(true); } goodDest = IntVec3.Invalid; return(false); }
private static bool CanHitFromCellIgnoringRange2(Verb __instance, IntVec3 sourceCell, LocalTargetInfo targ, out IntVec3 goodDest) { if (targ.Thing != null) { if (targ.Thing.Map != __instance.caster.Map) { goodDest = IntVec3.Invalid; return(false); } List <IntVec3> tempDestList = new List <IntVec3>(); ShootLeanUtility.CalcShootableCellsOf(tempDestList, targ.Thing); for (int i = 0; i < tempDestList.Count; i++) { if (CanHitCellFromCellIgnoringRange(__instance, sourceCell, tempDestList[i], targ.Thing.def.Fillage == FillCategory.Full)) { goodDest = tempDestList[i]; return(true); } } } else if (CanHitCellFromCellIgnoringRange(__instance, sourceCell, targ.Cell)) { goodDest = targ.Cell; return(true); } goodDest = IntVec3.Invalid; return(false); }
public static bool CanHitFromCellIgnoringRange(Verb __instance, ref bool __result, IntVec3 sourceCell, LocalTargetInfo targ, out IntVec3 goodDest) { if (targ.Thing != null) { if (targ.Thing.Map != __instance.caster.Map) { goodDest = IntVec3.Invalid; __result = false; return(false); } List <IntVec3> tempDestList = new List <IntVec3>(); ShootLeanUtility.CalcShootableCellsOf(tempDestList, targ.Thing); for (int index = 0; index < tempDestList.Count; ++index) { if (CanHitCellFromCellIgnoringRange(__instance, sourceCell, tempDestList[index], targ.Thing.def.Fillage == FillCategory.Full)) { goodDest = tempDestList[index]; __result = true; return(false); } } } else if (CanHitCellFromCellIgnoringRange(__instance, sourceCell, targ.Cell, false)) { goodDest = targ.Cell; __result = true; return(false); } goodDest = IntVec3.Invalid; __result = false; return(false); }
// Verse.Verb // Token: 0x060022E2 RID: 8930 RVA: 0x000D4A4C File Offset: 0x000D2C4C public new bool TryFindShootLineFromTo(IntVec3 root, LocalTargetInfo targ, out ShootLine resultingLine) { if (targ.HasThing && targ.Thing.Map != this.Caster.Map) { resultingLine = default(ShootLine); return(false); } if (this.verbProps.IsMeleeAttack || this.EffectiveRange <= 1.42f) { resultingLine = new ShootLine(root, targ.Cell); return(ReachabilityImmediate.CanReachImmediate(root, targ, this.Caster.Map, PathEndMode.Touch, null)); } CellRect cellRect = targ.HasThing ? targ.Thing.OccupiedRect() : CellRect.SingleCell(targ.Cell); float num = this.verbProps.EffectiveMinRange(targ, this.Caster); float num2 = cellRect.ClosestDistSquaredTo(root); if (num2 > this.EffectiveRange * this.EffectiveRange || num2 < num * num) { resultingLine = new ShootLine(root, targ.Cell); return(false); } if (!this.verbProps.requireLineOfSight) { resultingLine = new ShootLine(root, targ.Cell); return(true); } if (this.CasterIsPawn) { if (this.CanHitFromCellIgnoringRange(root, targ, out IntVec3 dest)) { resultingLine = new ShootLine(root, dest); return(true); } ShootLeanUtility.LeanShootingSourcesFromTo(root, cellRect.ClosestCellTo(root), this.Caster.Map, Verb_ShootCompMountedCE.tempLeanShootSources); for (int i = 0; i < Verb_ShootCompMountedCE.tempLeanShootSources.Count; i++) { IntVec3 intVec = Verb_ShootCompMountedCE.tempLeanShootSources[i]; if (this.CanHitFromCellIgnoringRange(intVec, targ, out dest)) { resultingLine = new ShootLine(intVec, dest); return(true); } } } else { IntVec2 size = new IntVec2(Caster.def.size.x + 1, Caster.def.size.z + 1); foreach (IntVec3 intVec2 in GenAdj.OccupiedRect(Caster.Position, Caster.Rotation, size)) { if (this.CanHitFromCellIgnoringRange(intVec2, targ, out IntVec3 dest)) { resultingLine = new ShootLine(intVec2, dest); return(true); } } } resultingLine = new ShootLine(root, targ.Cell); return(false); }
public bool TryFindCEShootLineFromTo(IntVec3 root, LocalTargetInfo targ, out ShootLine resultingLine) { if (targ.HasThing && targ.Thing.Map != caster.Map) { resultingLine = default(ShootLine); return(false); } if (verbProps.range <= ShootTuning.MeleeRange) // If this verb has a MAX range up to melee range (NOT a MIN RANGE!) { resultingLine = new ShootLine(root, targ.Cell); return(ReachabilityImmediate.CanReachImmediate(root, targ, caster.Map, PathEndMode.Touch, null)); } CellRect cellRect = (!targ.HasThing) ? CellRect.SingleCell(targ.Cell) : targ.Thing.OccupiedRect(); float num = cellRect.ClosestDistSquaredTo(root); if (num > verbProps.range * verbProps.range || num < verbProps.minRange * verbProps.minRange) { resultingLine = new ShootLine(root, targ.Cell); return(false); } //if (!this.verbProps.NeedsLineOfSight) This method doesn't consider the currently loaded projectile if (Projectile.projectile.flyOverhead) { resultingLine = new ShootLine(root, targ.Cell); return(true); } // First check current cell for early opt-out IntVec3 dest; var shotSource = root.ToVector3Shifted(); shotSource.y = ShotHeight; if (CanHitFromCellIgnoringRange(shotSource, targ, out dest)) { resultingLine = new ShootLine(root, dest); return(true); } // For pawns, calculate possible lean locations if (CasterIsPawn) { // Next check lean sources ShootLeanUtility.LeanShootingSourcesFromTo(root, cellRect.ClosestCellTo(root), caster.Map, tempLeanShootSources); foreach (var leanLoc in tempLeanShootSources) { var leanOffset = (leanLoc - root).ToVector3() * 0.5f; if (CanHitFromCellIgnoringRange(shotSource + leanOffset, targ, out dest)) { resultingLine = new ShootLine(leanLoc, dest); return(true); } } } resultingLine = new ShootLine(root, targ.Cell); return(false); }
private bool CanHitFromCellIgnoringRange(IntVec3 sourceCell, LocalTargetInfo targ, out IntVec3 goodDest) { if (targ.Thing != null) { if (targ.Thing.Map != this.caster.Map) { goodDest = IntVec3.Invalid; return(false); } // (ProfoundDarkness) I only ever see this code execute for the target, not the shooter... // (ProfoundDarkness) I don't know what I'm doing here so basically if the target has a structure next to them assume they will lean, rather than a more precise and accurate // test. // If the target is near something they might have to lean around to shoot then calculate their leans. // NOTE: CellsAdjacent8Way includes the check for if a location is in map bounds so can use CanBeSeenOverFast. The alternative is fast 8way and slow (bounds checking) CanBeSeenOver. if ((targ.Thing as Pawn)?.CurJob?.def != CE_JobDefOf.HunkerDown && GenAdjFast.AdjacentCells8Way(targ.Thing).FirstOrDefault(c => !c.CanBeSeenOver(targ.Thing.Map)) != null) { ShootLeanUtility.CalcShootableCellsOf(tempDestList, targ.Thing); } else // otherwise just assume that the target won't lean... { tempDestList.Clear(); tempDestList.Add(targ.Cell); } for (int i = 0; i < tempDestList.Count; i++) { if (this.CanHitCellFromCellIgnoringRange(sourceCell, tempDestList[i], targ.Thing, targ.Thing.def.Fillage == FillCategory.Full)) { // if any of the locations the target is at or can lean to for shooting can be shot by the shooter then lets have the shooter shoot. goodDest = tempDestList[i]; return(true); } } } else if (this.CanHitCellFromCellIgnoringRange(sourceCell, targ.Cell, targ.Thing)) { goodDest = targ.Cell; return(true); } goodDest = IntVec3.Invalid; return(false); }
public void AdjustForLeaning() { if (HasClearShotFrom(Origin)) { return; } // If we got this far the shot is possible, but there is no straight LoS. // Must be shooting around a corner, so we need to use a different origin. var leaningPositions = new List <IntVec3>(); ShootLeanUtility.LeanShootingSourcesFromTo(Origin, Target, CasterMap, leaningPositions); foreach (var leaningPosition in leaningPositions) { if (HasClearShotFrom(leaningPosition)) { Origin = leaningPosition; return; } } }
public bool CanHitTarget(LocalTargetInfo target) { if (def.royalAid.targetingRequireLOS && !GenSight.LineOfSight(caller.Position, target.Cell, map, skipFirstCell: true)) { bool flag = false; ShootLeanUtility.LeanShootingSourcesFromTo(caller.Position, target.Cell, map, tempSourceList); for (int i = 0; i < tempSourceList.Count; i++) { if (GenSight.LineOfSight(tempSourceList[i], target.Cell, map, skipFirstCell: true)) { flag = true; break; } } if (!flag) { return(false); } } return(true); }
public static bool HasLoSFromTo(IntVec3 root, LocalTargetInfo targ, Thing caster, float minRange, float maxRange) { float range = (targ.Cell - root).LengthHorizontal; if (targ.HasThing && targ.Thing.Map != caster.Map) { return(false); } if (range <= minRange || range >= maxRange) { return(false); } CellRect cellRect = (!targ.HasThing) ? CellRect.SingleCell(targ.Cell) : targ.Thing.OccupiedRect(); if (caster is Pawn) { if (GenSight.LineOfSight(caster.Position, targ.Cell, caster.Map, skipFirstCell: true)) { return(true); } List <IntVec3> tempLeanShootSources = new List <IntVec3>(); ShootLeanUtility.LeanShootingSourcesFromTo(root, cellRect.ClosestCellTo(root), caster.Map, tempLeanShootSources); for (int i = 0; i < tempLeanShootSources.Count; i++) { IntVec3 intVec = tempLeanShootSources[i]; if (GenSight.LineOfSight(intVec, targ.Cell, caster.Map, skipFirstCell: true)) { return(true); } } } else { if (GenSight.LineOfSight(root, targ.Cell, caster.Map, skipFirstCell: true)) { return(true); } } return(false); }
public static bool CanSee(this Thing seer, Thing target, Func <IntVec3, bool> validator = null) { ShootLeanUtility.CalcShootableCellsOf(tempDestList, target); for (int i = 0; i < tempDestList.Count; i++) { if (GenSight.LineOfSight(seer.Position, tempDestList[i], seer.Map, skipFirstCell: true, validator)) { return(true); } } ShootLeanUtility.LeanShootingSourcesFromTo(seer.Position, target.Position, seer.Map, tempSourceList); for (int j = 0; j < tempSourceList.Count; j++) { for (int k = 0; k < tempDestList.Count; k++) { if (GenSight.LineOfSight(tempSourceList[j], tempDestList[k], seer.Map, skipFirstCell: true, validator)) { return(true); } } } return(false); }
public static bool CanSee(this Thing seer, Thing target, Func <IntVec3, bool> validator = null) { // Log.Messageage(seer+" CanSee "+ target+"?"); ShootLeanUtility.CalcShootableCellsOf(tempDestList, target); for (int i = 0; i < tempDestList.Count; i++) { if (GenSight.LineOfSight(seer.Position, tempDestList[i], seer.Map, skipFirstCell: true, validator)) { return(true); } } ShootLeanUtility.LeanShootingSourcesFromTo(seer.Position, target.Position, seer.Map, tempSourceList); if (seer is Building) { IntVec2 size = new IntVec2(seer.def.Size.x + 2, seer.def.Size.z + 2); foreach (IntVec3 intVec2 in GenAdj.OccupiedRect(seer.Position, seer.Rotation, size)) { if (!tempSourceList.Contains(intVec2)) { tempSourceList.Add(intVec2); } } } for (int j = 0; j < tempSourceList.Count; j++) { for (int k = 0; k < tempDestList.Count; k++) { if (GenSight.LineOfSight(tempSourceList[j], tempDestList[k], seer.Map, skipFirstCell: true, validator)) { return(true); } } } // Log.Messageage(seer + " CanSee " + target + ": FALSE"); return(false); }
/* * public bool CanSeeTarget(LocalTargetInfo targ) * { * var glow = targ.Thing.Map.glowGrid.GameGlowAt(targ.Cell); * var glowmultiplier = Mathf.Lerp(1, 5, Mathf.Clamp(glow * 5f, 0f, 1f)); * * float lengthToTarget = Mathf.Abs((targ.Cell - caster.Position).LengthHorizontal); * if (targ.Thing.Map.glowGrid.GameGlowAt(targ.Cell) <= 0.2f) * { * Log.Message("target: " + targ.Thing + " glow: " + glow.ToString() + " glowmult: " + glowmultiplier.ToString()); * if (lengthToTarget > glowmultiplier) * { * Log.Message("cant see: " + targ.Thing.ToString()); * return false; * } * } * return true; * } */ public bool TryFindCEShootLineFromTo(IntVec3 root, LocalTargetInfo targ, out ShootLine resultingLine) { // Log.Message("root: " + root.ToString() + " target: " + targ.Thing.ToString() + " pos: " + targ.Cell.ToString()); if (targ.HasThing && targ.Thing.Map != this.caster.Map) { resultingLine = default(ShootLine); // Log.Message("shootline false: 1" + " line: " + resultingLine.ToString()); return(false); } // Log.Message("effminrange: " + this.verbProps.EffectiveMinRange(targ, this.caster).ToString() + " meleerange: " + ShootTuning.MeleeRange); if (this.verbProps.IsMeleeAttack) { resultingLine = new ShootLine(root, targ.Cell); var ri = ReachabilityImmediate.CanReachImmediate(root, targ, this.caster.Map, PathEndMode.Touch, null); // Log.Message("ri: " + ri.ToString() + " line: " + resultingLine.ToString()); return(ri); } CellRect cellRect = (!targ.HasThing) ? CellRect.SingleCell(targ.Cell) : targ.Thing.OccupiedRect(); float num = cellRect.ClosestDistSquaredTo(root); if (num > this.verbProps.range * this.verbProps.range || num < this.verbProps.minRange * this.verbProps.minRange) { resultingLine = new ShootLine(root, targ.Cell); // Log.Message("shootline false: 2" + " line: " + resultingLine.ToString()); return(false); } //if (!this.verbProps.NeedsLineOfSight) This method doesn't consider the currently loaded projectile if (Projectile.projectile.flyOverhead) { resultingLine = new ShootLine(root, targ.Cell); // Log.Message("shootline true: 3" + " line: " + resultingLine.ToString()); return(true); } if (this.CasterIsPawn) { IntVec3 dest; ShootLeanUtility.LeanShootingSourcesFromTo(root, cellRect.ClosestCellTo(root), this.caster.Map, tempLeanShootSources); if (tempLeanShootSources.Count < 2) { if (this.CanHitFromCellIgnoringRange(root, root, targ, out dest)) { resultingLine = new ShootLine(root, dest); // Log.Message("shootline true: 4" + " line: " + resultingLine.ToString()); return(true); } } if (tempLeanShootSources.Count >= 2) { int bestZ = 0; int bestX = 0; int cachedbz = -1; int cachedbx = -1; // Log.Message("pawn: " + CasterPawn.ToString() + " pawn pos: " + root.ToString() + " target: " + targ.Thing.ToString() + " target pos: " + targ.Cell.ToString()); foreach (var bsp in tempLeanShootSources) { var bz = Mathf.Abs(bsp.z - targ.Cell.z); if (cachedbz < 0 || (bz < cachedbz)) { cachedbz = bz; bestZ = bsp.z; } var bx = Mathf.Abs(bsp.x - targ.Cell.x); if (cachedbx < 0 || (bx < cachedbx)) { cachedbx = bx; bestX = bsp.x; } } bestshootposition = new IntVec3(bestX, root.y, bestZ); // Log.Message("bestshootposition: " + bestshootposition.ToString()); if (this.CanHitFromCellIgnoringRange(bestshootposition, root, targ, out dest)) { resultingLine = new ShootLine(bestshootposition, dest); // Log.Message("shootline true: 5" + " line: " + resultingLine.ToString()); return(true); } } else { for (int i = 0; i < tempLeanShootSources.Count; i++) { IntVec3 intVec = tempLeanShootSources[i]; if (this.CanHitFromCellIgnoringRange(intVec, root, targ, out dest)) { resultingLine = new ShootLine(intVec, dest); // Log.Message("shootline true: 6" + " line: " + resultingLine.ToString()); return(true); } } } } else { CellRect.CellRectIterator iterator = this.caster.OccupiedRect().GetIterator(); while (!iterator.Done()) { IntVec3 current = iterator.Current; IntVec3 dest; if (this.CanHitFromCellIgnoringRange(current, root, targ, out dest)) { resultingLine = new ShootLine(current, dest); // Log.Message("shootline true: 7: " + " line: " + resultingLine.ToString()); return(true); } iterator.MoveNext(); } } resultingLine = new ShootLine(root, targ.Cell); // Log.Message("shootline false: 8" + " line: " + resultingLine.ToString()); return(false); }
public static bool TryFindShootLineFromTo(Verb __instance, ref bool __result, IntVec3 root, LocalTargetInfo targ, out ShootLine resultingLine) { if (targ.HasThing && targ.Thing.Map != __instance.caster.Map) { resultingLine = default; __result = false; return(false); } if (__instance.verbProps.IsMeleeAttack || __instance.verbProps.range <= 1.42f) { resultingLine = new ShootLine(root, targ.Cell); __result = ReachabilityImmediate.CanReachImmediate(root, targ, __instance.caster.Map, PathEndMode.Touch, null); return(false); } CellRect cellRect = targ.HasThing ? targ.Thing.OccupiedRect() : CellRect.SingleCell(targ.Cell); float num = __instance.verbProps.EffectiveMinRange(targ, __instance.caster); float num2 = cellRect.ClosestDistSquaredTo(root); if (num2 > __instance.verbProps.range * __instance.verbProps.range || num2 < num * num) { resultingLine = new ShootLine(root, targ.Cell); __result = false; return(false); } if (!__instance.verbProps.requireLineOfSight) { resultingLine = new ShootLine(root, targ.Cell); __result = true; return(false); } IntVec3 goodDest; if (__instance.CasterIsPawn) { if (CanHitFromCellIgnoringRange2(__instance, root, targ, out goodDest)) { resultingLine = new ShootLine(root, goodDest); __result = true; return(false); } List <IntVec3> tempLeanShootSources = new List <IntVec3>(); //ADDED ShootLeanUtility.LeanShootingSourcesFromTo( root, cellRect.ClosestCellTo(root), __instance.caster.Map, tempLeanShootSources); //CHANGED tempLeanShootSources for (int i = 0; i < tempLeanShootSources.Count; i++) //CHANGED tempLeanShootSources { IntVec3 intVec = tempLeanShootSources[i]; //CHANGED tempLeanShootSources if (CanHitFromCellIgnoringRange2(__instance, intVec, targ, out goodDest)) { resultingLine = new ShootLine(intVec, goodDest); __result = true; return(false); } } } else { foreach (IntVec3 item in __instance.caster.OccupiedRect()) { if (CanHitFromCellIgnoringRange2(__instance, item, targ, out goodDest)) { resultingLine = new ShootLine(item, goodDest); __result = true; return(false); } } } resultingLine = new ShootLine(root, targ.Cell); __result = false; return(false); }
public new bool TryFindShootLineFromTo(IntVec3 root, LocalTargetInfo targ, out ShootLine resultingLine) { // Log.Message("Verb_MeleeAttackDamage_Polearm TryFindShootLineFromTo"); if (targ.HasThing && targ.Thing.Map != this.caster.Map) { resultingLine = default(ShootLine); return(false); } /* * if (this.verbProps.IsMeleeAttack || this.EffectiveRange <= 1.42f) * { * resultingLine = new ShootLine(root, targ.Cell); * * return this.CanReachImmediate(root, targ, this.caster.Map, PathEndMode.Touch, null); * } */ CellRect cellRect = targ.HasThing ? targ.Thing.OccupiedRect() : CellRect.SingleCell(targ.Cell); float num = this.verbProps.EffectiveMinRange(targ, this.caster); float num2 = cellRect.ClosestDistSquaredTo(root); if (num2 > this.EffectiveRange * this.EffectiveRange || num2 < num * num) { resultingLine = new ShootLine(root, targ.Cell); return(false); } if (!this.verbProps.requireLineOfSight) { resultingLine = new ShootLine(root, targ.Cell); return(true); } if (this.CasterIsPawn) { if (this.CanHitFromCellIgnoringRange(root, targ, out IntVec3 dest)) { resultingLine = new ShootLine(root, dest); return(true); } ShootLeanUtility.LeanShootingSourcesFromTo(root, cellRect.ClosestCellTo(root), this.caster.Map, Verb_MeleeAttackDamage_Polearm.tempLeanShootSources); for (int i = 0; i < Verb_MeleeAttackDamage_Polearm.tempLeanShootSources.Count; i++) { IntVec3 intVec = Verb_MeleeAttackDamage_Polearm.tempLeanShootSources[i]; if (this.CanHitFromCellIgnoringRange(intVec, targ, out dest)) { resultingLine = new ShootLine(intVec, dest); return(true); } } } else { foreach (IntVec3 intVec2 in this.caster.OccupiedRect()) { if (this.CanHitFromCellIgnoringRange(intVec2, targ, out IntVec3 dest)) { resultingLine = new ShootLine(intVec2, dest); return(true); } } } resultingLine = new ShootLine(root, targ.Cell); return(false); }
public bool TryFindCEShootLineFromTo(IntVec3 root, LocalTargetInfo targ, out ShootLine resultingLine) { if (targ.HasThing && targ.Thing.Map != caster.Map) { resultingLine = default(ShootLine); return(false); } if (verbProps.range <= ShootTuning.MeleeRange) // If this verb has a MAX range up to melee range (NOT a MIN RANGE!) { resultingLine = new ShootLine(root, targ.Cell); return(ReachabilityImmediate.CanReachImmediate(root, targ, caster.Map, PathEndMode.Touch, null)); } CellRect cellRect = (!targ.HasThing) ? CellRect.SingleCell(targ.Cell) : targ.Thing.OccupiedRect(); float num = cellRect.ClosestDistSquaredTo(root); if (num > verbProps.range * verbProps.range || num < verbProps.minRange * verbProps.minRange) { resultingLine = new ShootLine(root, targ.Cell); return(false); } //if (!this.verbProps.NeedsLineOfSight) This method doesn't consider the currently loaded projectile if (Projectile.projectile.flyOverhead) { resultingLine = new ShootLine(root, targ.Cell); return(true); } // First check current cell for early opt-out IntVec3 dest; var shotSource = root.ToVector3Shifted(); shotSource.y = ShotHeight; // Adjust for multi-tile turrets if (caster.def.building?.IsTurret ?? false) { shotSource = ShotSource; } if (CanHitFromCellIgnoringRange(shotSource, targ, out dest)) { resultingLine = new ShootLine(root, dest); return(true); } // For pawns, calculate possible lean locations if (CasterIsPawn) { ShootLeanUtility.LeanShootingSourcesFromTo(root, cellRect.ClosestCellTo(root), caster.Map, tempLeanShootSources); foreach (var leanLoc in tempLeanShootSources.OrderBy(c => c.DistanceTo(targ.Cell))) { var leanOffset = (leanLoc - root).ToVector3() * 0.51f; //using exactly 0.5f makes it always round up, which causes issues if offset is negative, when adding leanOffset to shotSource. Setting to 0.51f to fix. if (CanHitFromCellIgnoringRange(shotSource + leanOffset, targ, out dest)) { resultingLine = new ShootLine(leanLoc, dest); return(true); } } } resultingLine = new ShootLine(root, targ.Cell); return(false); }
public bool TryFindCEShootLineFromTo(IntVec3 root, LocalTargetInfo targ, out ShootLine resultingLine) { if (targ.HasThing && targ.Thing.Map != this.caster.Map) { resultingLine = default(ShootLine); return(false); } if (this.verbProps.range <= ShootTuning.MeleeRange) // If this verb has a MAX range up to melee range (NOT a MIN RANGE!) { resultingLine = new ShootLine(root, targ.Cell); return(ReachabilityImmediate.CanReachImmediate(root, targ, this.caster.Map, PathEndMode.Touch, null)); } CellRect cellRect = (!targ.HasThing) ? CellRect.SingleCell(targ.Cell) : targ.Thing.OccupiedRect(); float num = cellRect.ClosestDistSquaredTo(root); if (num > this.verbProps.range * this.verbProps.range || num < this.verbProps.minRange * this.verbProps.minRange) { resultingLine = new ShootLine(root, targ.Cell); return(false); } //if (!this.verbProps.NeedsLineOfSight) This method doesn't consider the currently loaded projectile if (Projectile.projectile.flyOverhead) { resultingLine = new ShootLine(root, targ.Cell); return(true); } if (this.CasterIsPawn) { IntVec3 dest; if (this.CanHitFromCellIgnoringRange(root, targ, out dest)) { resultingLine = new ShootLine(root, dest); return(true); } ShootLeanUtility.LeanShootingSourcesFromTo(root, cellRect.ClosestCellTo(root), this.caster.Map, tempLeanShootSources); for (int i = 0; i < tempLeanShootSources.Count; i++) { IntVec3 intVec = tempLeanShootSources[i]; if (this.CanHitFromCellIgnoringRange(intVec, targ, out dest)) { resultingLine = new ShootLine(intVec, dest); return(true); } } } else { CellRect.CellRectIterator iterator = this.caster.OccupiedRect().GetIterator(); while (!iterator.Done()) { IntVec3 current = iterator.Current; IntVec3 dest; if (this.CanHitFromCellIgnoringRange(current, targ, out dest)) { resultingLine = new ShootLine(current, dest); return(true); } iterator.MoveNext(); } } resultingLine = new ShootLine(root, targ.Cell); return(false); }