private bool TryCollideWithRoof(IntVec3 cell) { if (!cell.Roofed(Map)) { return(false); } var bounds = CE_Utility.GetBoundsFor(cell, cell.GetRoof(Map)); float dist; if (!bounds.IntersectRay(ShotLine, out dist)) { return(false); } if (dist * dist > ExactMinusLastPos.sqrMagnitude) { return(false); } var point = ShotLine.GetPoint(dist); ExactPosition = point; landed = true; if (DebugViewSettings.drawInterceptChecks) { MoteMaker.ThrowText(cell.ToVector3Shifted(), Map, "x", Color.red); } Impact(null); return(true); }
/// <summary> /// Tries to impact the thing based on whether it intersects the given flight path. Trees have RNG chance to not collide even on intersection. /// </summary> /// <param name="thing">What to impact</param> /// <returns>True if impact occured, false otherwise</returns> private bool TryCollideWith(Thing thing) { if (thing == launcher && !canTargetSelf) { return(false); } var bounds = CE_Utility.GetBoundsFor(thing); float dist; if (!bounds.IntersectRay(ShotLine, out dist)) { return(false); } if (dist * dist > ExactMinusLastPos.sqrMagnitude) { return(false); } // Trees and bushes have RNG chance to collide var plant = thing as Plant; if (plant != null) { //TODO: Remove fillPercent dependency because all fillPercents on trees are 0.25 //Prevents trees near the shooter (e.g the shooter's cover) to be hit float chance = thing.def.fillPercent * ((thing.Position - OriginIV3).LengthHorizontal / 40); if (Controller.settings.DebugShowTreeCollisionChance) { MoteMaker.ThrowText(thing.Position.ToVector3Shifted(), thing.Map, chance.ToString()); } if (!Rand.Chance(chance)) { return(false); } } var point = ShotLine.GetPoint(dist); if (!point.InBounds(this.Map)) { Log.Error("TryCollideWith out of bounds point from ShotLine: obj " + thing.ThingID + ", proj " + this.ThingID + ", dist " + dist + ", point " + point); } ExactPosition = point; landed = true; if (DebugViewSettings.drawInterceptChecks) { MoteMaker.ThrowText(thing.Position.ToVector3Shifted(), thing.Map, "x", Color.red); } Impact(thing); return(true); }
/// <summary> /// Tries to impact the thing based on whether it intersects the given flight path. Trees have RNG chance to not collide even on intersection. /// </summary> /// <param name="thing">What to impact</param> /// <returns>True if impact occured, false otherwise</returns> private bool TryCollideWith(Thing thing) { if (thing == launcher && !canTargetSelf) { return(false); } var bounds = CE_Utility.GetBoundsFor(thing); if (!bounds.IntersectRay(ShotLine, out var dist)) { return(false); } if (dist * dist > ExactMinusLastPos.sqrMagnitude) { return(false); } // Trees and bushes have RNG chance to collide if (thing is Plant) { //Prevents trees near the shooter (e.g the shooter's cover) to be hit var accuracyFactor = def.projectile.alwaysFreeIntercept ? 1 : (thing.Position - OriginIV3).LengthHorizontal / 40 * AccuracyFactor; var chance = thing.def.fillPercent * accuracyFactor; if (Controller.settings.DebugShowTreeCollisionChance) { MoteMaker.ThrowText(thing.Position.ToVector3Shifted(), thing.Map, chance.ToString()); } if (!Rand.Chance(chance)) { return(false); } } var point = ShotLine.GetPoint(dist); if (!point.InBounds(Map)) { Log.Error("TryCollideWith out of bounds point from ShotLine: obj " + thing.ThingID + ", proj " + ThingID + ", dist " + dist + ", point " + point); } ExactPosition = point; landed = true; if (Controller.settings.DebugDrawInterceptChecks) { MoteMaker.ThrowText(thing.Position.ToVector3Shifted(), thing.Map, "x", Color.red); } Impact(thing); return(true); }
/// <summary> /// Tries to impact the thing based on whether it intersects the given flight path. Trees have RNG chance to not collide even on intersection. /// </summary> /// <param name="thing">What to impact</param> /// <returns>True if impact occured, false otherwise</returns> private bool TryCollideWith(Thing thing) { if (thing == launcher && !canTargetSelf) { return(false); } var bounds = CE_Utility.GetBoundsFor(thing); float dist; if (!bounds.IntersectRay(ShotLine, out dist)) { return(false); } if (dist * dist > ExactMinusLastPos.sqrMagnitude) { return(false); } // Trees and bushes have RNG chance to collide var plant = thing as Plant; if (plant != null) { //TODO: Remove fillPercent dependency because all fillPercents on trees are 0.25 //Prevents trees near the shooter (e.g the shooter's cover) to be hit //Dependence to catch the tree from armorPenetration. Large calibers have less chance. var propsCE = def.projectile as ProjectilePropertiesCE; float penetrationAmount = propsCE == null ? 0.1f : propsCE.armorPenetration; //Every projectile, which not use flyoverhead, require armorPenetration stat for calculating collision. float penetrationmultiplier = Mathf.Clamp(((thing.def.fillPercent * 3.2f) - penetrationAmount), 0.05f, 1f); // 2.5-3.5 good values for 0.20-0.30 fillpercent. float rangemultiplier = ((thing.Position - OriginIV3).LengthHorizontal / 15); // 10-20 is fine for prevent to shoot near tree. float chance = penetrationmultiplier * (rangemultiplier < 1f ? rangemultiplier : 1f); // when projectile reach 15 cells distance, we set limit for multiplier bcs chances to hit greatly increased. if (Controller.settings.DebugShowTreeCollisionChance) { MoteMaker.ThrowText(thing.Position.ToVector3Shifted(), thing.Map, chance.ToString()); } if (!Rand.Chance(chance)) { return(false); } } var point = ShotLine.GetPoint(dist); if (!point.InBounds(this.Map)) { Log.Error("TryCollideWith out of bounds point from ShotLine: obj " + thing.ThingID + ", proj " + this.ThingID + ", dist " + dist + ", point " + point); } ExactPosition = point; if (intendedTarget != null) { var fulldistance = (intendedTarget.Position - OriginIV3).LengthHorizontalSquared; var traveleddistance = (thing.Position - OriginIV3).LengthHorizontalSquared; var requireddisttotarget = fulldistance - traveleddistance; if (thing is Building && thing.def.fillPercent > 0.5f) { // Log.Message("fulldist: " + fulldistance.ToString() + " traveled: " + traveleddistance.ToString() + " required: " + requireddisttotarget.ToString()); if (traveleddistance < requireddisttotarget) { return(false); } } } landed = true; // if (Controller.settings.DebugDrawInterceptChecks) MoteMaker.ThrowText(thing.Position.ToVector3Shifted(), thing.Map, "x", Color.red); Impact(thing); return(true); }