//Modified collision with downed pawns private void ImpactSomething() { if (BlockerRegistry.ImpactSomethingCallback(this, launcher)) { this.Destroy(); return; } var pos = ExactPosition.ToIntVec3(); //Not modified, just mortar code if (def.projectile.flyOverhead) { var roofDef = Map.roofGrid.RoofAt(pos); if (roofDef != null) { if (roofDef.isThickRoof) { def.projectile.soundHitThickRoof.PlayOneShot(new TargetInfo(pos, Map)); Destroy(); return; } if (pos.GetEdifice(Map) == null || pos.GetEdifice(Map).def.Fillage != FillCategory.Full) { RoofCollapserImmediate.DropRoofInCells(pos, Map); } } } // FIXME : Early opt-out Thing thing = pos.GetFirstPawn(Map); if (thing != null && TryCollideWith(thing)) { return; } var list = Map.thingGrid.ThingsListAt(pos).Where(t => t is Pawn || t.def.Fillage != FillCategory.None).ToList(); if (list.Count > 0) { foreach (var thing2 in list) { if (TryCollideWith(thing2)) { return; } } } ExactPosition = ExactPosition; landed = true; Impact(null); }
/// <summary> /// Checks whether a collision occurs along flight path within this cell. /// </summary> /// <param name="cell">Where to check for collisions in</param> /// <returns>True if collision occured, false otherwise</returns> private bool CheckCellForCollision(IntVec3 cell) { if (BlockerRegistry.CheckCellForCollisionCallback(this, cell, launcher)) { this.ticksToImpact = 0; this.landed = true; this.Impact(null); return(true); } var roofChecked = false; var justWallsRoofs = false; //Check for minimum PAWN collision distance float distFromOrigin = cell.DistanceToSquared(OriginIV3); bool skipCollision = !def.projectile.alwaysFreeIntercept && (minCollisionSqr <= 1f ? distFromOrigin < 1f : distFromOrigin <= Mathf.Min(144f, minCollisionSqr / 4)); var mainThingList = new List <Thing>(Map.thingGrid.ThingsListAtFast(cell)) .Where(t => justWallsRoofs ? t.def.Fillage == FillCategory.Full : (t is Pawn || t.def.Fillage != FillCategory.None)).ToList(); //Find pawns in adjacent cells and append them to main list if (!justWallsRoofs) { var adjList = new List <IntVec3>(); adjList.AddRange(GenAdj.CellsAdjacentCardinal(cell, Rot4.FromAngleFlat(shotRotation), new IntVec2(collisionCheckSize, 0)).ToList()); //Iterate through adjacent cells and find all the pawns foreach (var curCell in adjList) { if (curCell != cell && curCell.InBounds(Map)) { mainThingList.AddRange(Map.thingGrid.ThingsListAtFast(curCell) .Where(x => x is Pawn)); if (Controller.settings.DebugDrawInterceptChecks) { Map.debugDrawer.FlashCell(curCell, 0.7f); } } } } //If the last position is above the wallCollisionHeight, we should check for roof intersections first if (LastPos.y > CollisionVertical.WallCollisionHeight) { if (TryCollideWithRoof(cell)) { return(true); } roofChecked = true; } foreach (var thing in mainThingList.Distinct().OrderBy(x => (x.DrawPos - LastPos).sqrMagnitude)) { if ((thing == launcher || thing == mount) && !canTargetSelf) { continue; } // Check for collision if ((!skipCollision || thing == intendedTarget) && TryCollideWith(thing)) { return(true); } // Apply suppression. The height here is NOT that of the bullet in CELL, // it is the height at the END OF THE PATH. This is because SuppressionRadius // is not considered an EXACT limit. if (!justWallsRoofs && ExactPosition.y < SuppressionRadius) { var pawn = thing as Pawn; if (pawn != null) { ApplySuppression(pawn); } } } //Finally check for intersecting with a roof (again). if (!roofChecked && TryCollideWithRoof(cell)) { return(true); } return(false); }