protected virtual void Explode()
        {
            Map map = base.Map;
            //this.Destroy(DestroyMode.Vanish);
            ProjectilePropertiesCE propsCE = def.projectile as ProjectilePropertiesCE;

            GenExplosion.DoExplosion(ExactPosition.ToIntVec3(),
                                     map,
                                     this.def.projectile.explosionRadius,
                                     this.def.projectile.damageDef,
                                     this.launcher,
                                     this.def.projectile.soundExplode,
                                     this.def,
                                     this.equipmentDef,
                                     this.def.projectile.postExplosionSpawnThingDef,
                                     this.def.projectile.explosionSpawnChance,
                                     1,
                                     propsCE != null && propsCE.damageAdjacentTiles,
                                     this.def.projectile.preExplosionSpawnThingDef,
                                     this.def.projectile.explosionSpawnChance,
                                     1);

            //This code was disabled because it didn't run under previous circumstances. Could be enabled if necessary

            /*
             * if (map != null && base.ExactPosition.ToIntVec3().IsValid)
             * {
             *  ThrowBigExplode(base.ExactPosition + Gen.RandomHorizontalVector(def.projectile.explosionRadius * 0.5f), base.Map, def.projectile.explosionRadius * 0.4f);
             * }
             */

            base.Impact(null); // base.Impact() handles this.Destroy() and comp.Explode()
        }
        protected virtual void Explode()
        {
            ExplosionCE explosion = GenSpawn.Spawn(CE_ThingDefOf.ExplosionCE, ExactPosition.ToIntVec3(), Map) as ExplosionCE;

            explosion.height     = ExactPosition.y;
            explosion.radius     = def.projectile.explosionRadius;
            explosion.damType    = def.projectile.damageDef;
            explosion.instigator = launcher;
            explosion.damAmount  = def.projectile.GetDamageAmount(1);
            explosion.weapon     = equipmentDef;
            explosion.projectile = def;
            explosion.preExplosionSpawnThingDef            = def.projectile.preExplosionSpawnThingDef;
            explosion.preExplosionSpawnChance              = def.projectile.preExplosionSpawnChance;
            explosion.preExplosionSpawnThingCount          = def.projectile.preExplosionSpawnThingCount;
            explosion.postExplosionSpawnThingDef           = def.projectile.postExplosionSpawnThingDef;
            explosion.postExplosionSpawnChance             = def.projectile.postExplosionSpawnChance;
            explosion.postExplosionSpawnThingCount         = def.projectile.postExplosionSpawnThingCount;
            explosion.applyDamageToExplosionCellsNeighbors = def.projectile.applyDamageToExplosionCellsNeighbors;
            explosion.chanceToStartFire = def.projectile.explosionChanceToStartFire;
            explosion.damageFalloff     = def.projectile.explosionDamageFalloff;
            explosion.StartExplosion(def.projectile.soundExplode);
            explosion.armorPenetration = explosion.damAmount * 0.1f;

            //This code was disabled because it didn't run under previous circumstances. Could be enabled if necessary

            /*
             * if (map != null && base.ExactPosition.ToIntVec3().IsValid)
             * {
             *  ThrowBigExplode(base.ExactPosition + Gen.RandomHorizontalVector(def.projectile.explosionRadius * 0.5f), base.Map, def.projectile.explosionRadius * 0.4f);
             * }
             */

            base.Impact(null); // base.Impact() handles this.Destroy() and comp.Explode()
        }
Пример #3
0
        public override void Tick()
        {
            base.Tick();
            if (outRange())
            {
                hitThings.Clear();
                Destroy();
                return;
            }

            var ts = Map.thingGrid.ThingsAt(ExactPosition.ToIntVec3());

            foreach (var t in ts)
            {
                if ((t is not Pawn || t == launcher) && t is not Building)
                {
                    continue;
                }

                if (hitThings.Contains(t))
                {
                    continue;
                }

                //  Log.Warning(this.hitThings+" not contains "+t);
                aImpact(t);
                hitThings.Add(t);
            }
        }
Пример #4
0
        //Unmodified
        public override void Tick()
        {
            base.Tick();
            if (landed)
            {
                return;
            }
            Vector3 exactPosition = ExactPosition;

            ticksToImpact--;
            if (!ExactPosition.InBounds(base.Map))
            {
                ticksToImpact++;
                Position = ExactPosition.ToIntVec3();
                Destroy(DestroyMode.Vanish);
                return;
            }
            Vector3 exactPosition2 = ExactPosition;

            if (!def.projectile.flyOverhead && canFreeIntercept &&
                CheckForFreeInterceptBetween(exactPosition, exactPosition2))
            {
                return;
            }
            Position = ExactPosition.ToIntVec3();
            if (ticksToImpact == 60f && Find.TickManager.CurTimeSpeed == TimeSpeed.Normal &&
                def.projectile.soundImpactAnticipate != null)
            {
                def.projectile.soundImpactAnticipate.PlayOneShot(this);
            }
            if (ticksToImpact <= 0)
            {
                if (DestinationCell.InBounds(base.Map))
                {
                    Position = DestinationCell;
                }
                ImpactSomething();
                return;
            }
            if (ambientSustainer != null)
            {
                ambientSustainer.Maintain();
            }
            // attack shooting expression
            if (this.launcher is Building_TurretGunCR == false)
            {
                if (Rand.Value > 0.7 &&
                    this.launcher.def.race.Humanlike &&
                    !robotBodyList.Contains(this.launcher.def.race.body.defName) &&
                    Gen.IsHashIntervalTick(launcher, Rand.Range(280, 700)))
                {
                    AGAIN : string rndswear = RulePackDef.Named("AttackMote").Rules.RandomElement().Generate();
                    if (rndswear == "[swear]" || rndswear == "" || rndswear == " ")
                    {
                        goto AGAIN;
                    }
                    MoteMaker.ThrowText(launcher.Position.ToVector3Shifted(), this.launcher.Map, rndswear);
                }
            }
        }
Пример #5
0
        //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);
        }
Пример #6
0
        //Removed minimum collision distance
        private bool CheckForCollisionBetween()
        {
            var lastPosIV3 = LastPos.ToIntVec3();
            var newPosIV3  = ExactPosition.ToIntVec3();

            List <Thing> list = base.Map.listerThings.ThingsInGroup(ThingRequestGroup.ProjectileInterceptor);

            for (int i = 0; i < list.Count; i++)
            {
                if (CheckIntercept(list[i], list[i].TryGetComp <CompProjectileInterceptor>()))
                {
                    this.Destroy(DestroyMode.Vanish);
                    return(true);
                }
            }

            #region Sanity checks
            if (ticksToImpact == 0 || def.projectile.flyOverhead)
            {
                return(false);
            }

            if (!lastPosIV3.InBounds(Map) || !newPosIV3.InBounds(Map))
            {
                return(false);
            }

            if (Controller.settings.DebugDrawInterceptChecks)
            {
                Map.debugDrawer.FlashLine(lastPosIV3, newPosIV3);
            }
            #endregion

            // Iterate through all cells between the last and the new position
            // INCLUDING[!!!] THE LAST AND NEW POSITIONS!
            var cells = GenSight.PointsOnLineOfSight(lastPosIV3, newPosIV3).Union(new[] { lastPosIV3, newPosIV3 }).Distinct().OrderBy(x => (x.ToVector3Shifted() - LastPos).MagnitudeHorizontalSquared());

            //Order cells by distance from the last position
            foreach (var cell in cells)
            {
                if (CheckCellForCollision(cell))
                {
                    return(true);
                }

                if (Controller.settings.DebugDrawInterceptChecks)
                {
                    Map.debugDrawer.FlashCell(cell, 1, "o");
                }
            }

            return(false);
        }
Пример #7
0
        protected virtual void Impact(Thing hitThing)
        {
            CompExplosiveCE comp = this.TryGetComp <CompExplosiveCE>();

            if (comp != null && ExactPosition.ToIntVec3().IsValid)
            {
                comp.Explode(launcher, ExactPosition, Find.CurrentMap);
            }

            //Spawn things if not an explosive but preExplosionSpawnThingDef != null
            if (Controller.settings.EnableAmmoSystem &&
                Controller.settings.ReuseNeolithicProjectiles &&
                comp == null &&
                Position.IsValid &&
                def.projectile.preExplosionSpawnChance > 0 &&
                def.projectile.preExplosionSpawnThingDef != null &&
                Rand.Value < def.projectile.preExplosionSpawnChance)
            {
                var thingDef = def.projectile.preExplosionSpawnThingDef;

                if (thingDef.IsFilth && Position.Walkable(this.Map))
                {
                    FilthMaker.MakeFilth(Position, Map, thingDef, 1);
                }
                else
                {
                    Thing reusableAmmo = ThingMaker.MakeThing(thingDef, null);
                    reusableAmmo.stackCount = 1;
                    reusableAmmo.SetForbidden(true, false);
                    GenPlace.TryPlaceThing(reusableAmmo, Position, Map, ThingPlaceMode.Near, null);
                    LessonAutoActivator.TeachOpportunity(CE_ConceptDefOf.CE_ReusableNeolithicProjectiles, reusableAmmo, OpportunityType.GoodToKnow);
                }
            }

            // Opt-out for things without explosionRadius
            if (def.projectile.explosionRadius > 0 && ExactPosition.y < SuppressionRadius)
            {
                // Apply suppression around impact area
                var suppressThings = GenRadial.RadialDistinctThingsAround(ExactPosition.ToIntVec3(), Map, SuppressionRadius + def.projectile.explosionRadius, true);
                foreach (Thing thing in suppressThings)
                {
                    Pawn pawn = thing as Pawn;
                    if (pawn != null)
                    {
                        ApplySuppression(pawn);
                    }
                }
            }

            Destroy();
        }
Пример #8
0
        public override void Tick()
        {
            if (AllComps != null)
            {
                int i     = 0;
                int count = AllComps.Count;
                while (i < count)
                {
                    AllComps[i].CompTick();
                    i++;
                }
            }
            if (landed)
            {
                return;
            }
            Vector3 exactPosition = ExactPosition;

            ticksToImpact--;
            if (!ExactPosition.InBounds(Map))
            {
                ticksToImpact++;
                Position = ExactPosition.ToIntVec3();
                Destroy(DestroyMode.Vanish);
                return;
            }
            Vector3 exactPosition2 = ExactPosition;

            if (CheckForFreeInterceptBetween(exactPosition, exactPosition2))
            {
                return;
            }
            Position = ExactPosition.ToIntVec3();
            if (ticksToImpact == 60 && Find.TickManager.CurTimeSpeed == TimeSpeed.Normal && this.def.projectile.soundImpactAnticipate != null)
            {
                def.projectile.soundImpactAnticipate.PlayOneShot(this);
            }
            if (ticksToImpact <= 0)
            {
                if (DestinationCell.InBounds(Map))
                {
                    Position = DestinationCell;
                }
                ImpactSomething();
                return;
            }
            if (ambientSustainer != null)
            {
                ambientSustainer.Maintain();
            }
        }
Пример #9
0
        public override void Tick()
        {
            base.Tick();
            if (landed)
            {
                return;
            }
            LastPos = ExactPosition;
            ticksToImpact--;
            if (!ExactPosition.InBounds(Map))
            {
                Position = LastPos.ToIntVec3();
                Destroy();
                return;
            }
            if (CheckForCollisionBetween())
            {
                return;
            }
            Position = ExactPosition.ToIntVec3();
            if (ticksToImpact == 60 && Find.TickManager.CurTimeSpeed == TimeSpeed.Normal &&
                def.projectile.soundImpactAnticipate != null)
            {
                def.projectile.soundImpactAnticipate.PlayOneShot(this);
            }
            //TODO : It appears that the final steps in the arc (past ticksToImpact == 0) don't CheckForCollisionBetween.
            if (ticksToImpact <= 0)
            {
                ImpactSomething();
                return;
            }
            if (ambientSustainer != null)
            {
                ambientSustainer.Maintain();
            }

            if (def.HasModExtension <TrailerProjectileExtension>())
            {
                var trailer = def.GetModExtension <TrailerProjectileExtension>();
                if (trailer != null)
                {
                    if (ticksToImpact % trailer.trailerMoteInterval == 0)
                    {
                        for (int i = 0; i < trailer.motesThrown; i++)
                        {
                            TrailThrower.ThrowSmoke(DrawPos, trailer.trailMoteSize, Map, trailer.trailMoteDef);
                        }
                    }
                }
            }
        }
Пример #10
0
        // Token: 0x060026E7 RID: 9959 RVA: 0x00127F60 File Offset: 0x00126360
        protected override void Impact(Thing hitThing)
        {
            var map = Map;

            base.Impact(hitThing);
            var battleLogEntry_RangedImpact = new BattleLogEntry_RangedImpact(launcher, hitThing,
                                                                              intendedTarget.Thing, equipmentDef, def, targetCoverDef);

            Find.BattleLog.Add(battleLogEntry_RangedImpact);
            if (hitThing != null)
            {
                var   damageDef        = def.projectile.damageDef;
                float amount           = DamageAmount;
                var   armorPenetration = ArmorPenetration;
                var   y          = ExactRotation.eulerAngles.y;
                var   instigator = launcher;
                var   thingDef   = equipmentDef;
                var   dinfo      = new DamageInfo(damageDef, amount, armorPenetration, y, instigator, null, thingDef,
                                                  DamageInfo.SourceCategory.ThingOrUnknown, intendedTarget.Thing);
                hitThing.TakeDamage(dinfo).AssociateWithLog(battleLogEntry_RangedImpact);
                if (hitThing is Pawn {
                    stances : { }
                } pawn&& pawn.BodySize <= def.projectile.StoppingPower + 0.001f)
                {
                    pawn.stances.StaggerFor(95);
                }
            }

            //else
            //{
            var fire = (Fire)ThingMaker.MakeThing(ThingDefOf.Fire);

            fire.fireSize = 0.1f;
            if (map.thingGrid.ThingAt(ExactPosition.ToIntVec3(), ThingDefOf.Fire) != null)
            {
                ((Fire)map.thingGrid.ThingAt(ExactPosition.ToIntVec3(), ThingDefOf.Fire)).fireSize += 0.1f;
            }
            else
            {
                GenSpawn.Spawn(fire, ExactPosition.ToIntVec3(), map, Rot4.North);
            }


            // }
        }
 protected override void Impact(Thing hitThing)
 {
     // Snap to target so we hit multi-tile pawns with our explosion
     if (hitThing is Pawn)
     {
         var newPos = hitThing.DrawPos;
         newPos.y      = ExactPosition.y;
         ExactPosition = newPos;
         Position      = ExactPosition.ToIntVec3();
     }
     if (def.projectile.explosionDelay == 0)
     {
         Explode();
         return;
     }
     landed            = true;
     ticksToDetonation = def.projectile.explosionDelay;
     GenExplosion.NotifyNearbyPawnsOfDangerousExplosive(this, this.def.projectile.damageDef, this.launcher?.Faction);
 }
Пример #12
0
        public override void Tick()
        {
            base.Tick();
            if (landed)
            {
                return;
            }
            Vector3 exactPosition = ExactPosition;

            ticksToImpact--;
            if (!ExactPosition.InBounds(base.Map))
            {
                ticksToImpact++;
                base.Position = ExactPosition.ToIntVec3();
                Destroy();
                return;
            }
            Vector3 exactPosition2 = ExactPosition;

            if (CheckForFreeInterceptBetween(exactPosition, exactPosition2))
            {
                return;
            }
            base.Position = ExactPosition.ToIntVec3();
            if (ticksToImpact == 60 && Find.TickManager.CurTimeSpeed == TimeSpeed.Normal && def.projectile.soundImpactAnticipate != null)
            {
                def.projectile.soundImpactAnticipate.PlayOneShot(this);
            }
            if (ticksToImpact <= 0)
            {
                if (DestinationCell.InBounds(base.Map))
                {
                    base.Position = DestinationCell;
                }
                ImpactSomething();
            }
            else if (ambientSustainer != null)
            {
                ambientSustainer.Maintain();
            }
        }
Пример #13
0
        public override void Tick()
        {
            base.Tick();
            if (!Spawned)
            {
                return;
            }

            if (!ExactPosition.InBounds(Map))
            {
                return;
            }

            foreach (var th in Map.thingGrid.ThingsAt(ExactPosition.ToIntVec3()))
            {
                if (th is Pawn)
                {
                    aImpact(th);
                }
            }
        }
Пример #14
0
        //Unmodified
        public override void Tick()
        {
            base.Tick();
            if (landed)
            {
                return;
            }
            Vector2 lastExactPosition = Vec2Position;

            ticksToImpact--;
            if (!ExactPosition.InBounds(base.Map))
            {
                ticksToImpact++;
                Position = ExactPosition.ToIntVec3();
                Destroy(DestroyMode.Vanish);
                return;
            }
            heightOutdated = true;
            if (ticksToImpact >= 0 &&
                !def.projectile.flyOverhead &&
                CheckForCollisionBetween(lastExactPosition, Vec2Position))
            {
                return;
            }
            Position = ExactPosition.ToIntVec3();
            if (ticksToImpact == 60 && Find.TickManager.CurTimeSpeed == TimeSpeed.Normal &&
                def.projectile.soundImpactAnticipate != null)
            {
                def.projectile.soundImpactAnticipate.PlayOneShot(this);
            }
            if (ticksToImpact <= 0)
            {
                ImpactSomething();
                return;
            }
            if (ambientSustainer != null)
            {
                ambientSustainer.Maintain();
            }
        }
Пример #15
0
 public override void Tick()
 {
     base.Tick();
     if (landed)
     {
         return;
     }
     LastPos = ExactPosition;
     ticksToImpact--;
     if (!ExactPosition.InBounds(base.Map))
     {
         Position = LastPos.ToIntVec3();
         Destroy(DestroyMode.Vanish);
         return;
     }
     if (ticksToImpact >= 0 &&
         !def.projectile.flyOverhead &&
         CheckForCollisionBetween())
     {
         return;
     }
     Position = ExactPosition.ToIntVec3();
     if (ticksToImpact == 60 && Find.TickManager.CurTimeSpeed == TimeSpeed.Normal &&
         def.projectile.soundImpactAnticipate != null)
     {
         def.projectile.soundImpactAnticipate.PlayOneShot(this);
     }
     //TODO : It appears that the final steps in the arc (past ticksToImpact == 0) don't CheckForCollisionBetween.
     if (ticksToImpact <= 0)
     {
         ImpactSomething();
         return;
     }
     if (ambientSustainer != null)
     {
         ambientSustainer.Maintain();
     }
 }
Пример #16
0
        //Removed minimum collision distance
        private bool CheckForCollisionBetween()
        {
            var lastPosIV3 = LastPos.ToIntVec3();
            var newPosIV3  = ExactPosition.ToIntVec3();

            #region Sanity checks
            if (!lastPosIV3.InBounds(base.Map) || !newPosIV3.InBounds(base.Map))
            {
                return(false);
            }

            if (DebugViewSettings.drawInterceptChecks)
            {
                Map.debugDrawer.FlashLine(lastPosIV3, newPosIV3);
            }
            #endregion

            // Iterate through all cells between the last and the new position
            // INCLUDING[!!!] THE LAST AND NEW POSITIONS!
            var cells = GenSight.PointsOnLineOfSight(lastPosIV3, newPosIV3).Union(new [] { lastPosIV3, newPosIV3 }).Distinct().OrderBy(x => (x.ToVector3Shifted() - LastPos).MagnitudeHorizontalSquared());

            //Order cells by distance from the last position
            foreach (IntVec3 cell in cells)
            {
                if (CheckCellForCollision(cell))
                {
                    return(true);
                }

                if (DebugViewSettings.drawInterceptChecks)
                {
                    Map.debugDrawer.FlashCell(cell, 1, "o");
                }
            }

            return(false);
        }
Пример #17
0
        protected virtual void Explode()
        {
            Map map = base.Map;
            //this.Destroy(DestroyMode.Vanish);
            ProjectilePropertiesCE propsCE = def.projectile as ProjectilePropertiesCE;

            GenExplosion.DoExplosion(ExactPosition.ToIntVec3(),
                                     map,
                                     def.projectile.explosionRadius,
                                     def.projectile.damageDef,
                                     launcher,
                                     def.projectile.damageAmountBase,
                                     def.projectile.soundExplode,
                                     equipmentDef,
                                     def,
                                     def.projectile.postExplosionSpawnThingDef,
                                     def.projectile.postExplosionSpawnChance,
                                     def.projectile.postExplosionSpawnThingCount,
                                     def.projectile.applyDamageToExplosionCellsNeighbors,
                                     def.projectile.preExplosionSpawnThingDef,
                                     def.projectile.preExplosionSpawnChance,
                                     def.projectile.preExplosionSpawnThingCount,
                                     def.projectile.explosionChanceToStartFire,
                                     def.projectile.explosionDealMoreDamageAtCenter);

            //This code was disabled because it didn't run under previous circumstances. Could be enabled if necessary

            /*
             * if (map != null && base.ExactPosition.ToIntVec3().IsValid)
             * {
             *  ThrowBigExplode(base.ExactPosition + Gen.RandomHorizontalVector(def.projectile.explosionRadius * 0.5f), base.Map, def.projectile.explosionRadius * 0.4f);
             * }
             */

            base.Impact(null); // base.Impact() handles this.Destroy() and comp.Explode()
        }
Пример #18
0
        public virtual void RayCast(Thing launcher, VerbProperties verbProps, Vector2 origin, float shotAngle, float shotRotation, float shotHeight = 0f, float shotSpeed = -1f, float spreadDegrees = 0f, float aperatureSize = 0.03f, Thing equipment = null)
        {
            float magicSpreadFactor        = Mathf.Sin(0.06f / 2 * Mathf.Deg2Rad) + aperatureSize;
            float magicLaserDamageConstant = 1 / (magicSpreadFactor * magicSpreadFactor * 3.14159f);

            ProjectilePropertiesCE pprops = def.projectile as ProjectilePropertiesCE;

            shotRotation = Mathf.Deg2Rad * shotRotation + (float)(3.14159 / 2.0f);
            Vector3 direction   = new Vector3(Mathf.Cos(shotRotation) * Mathf.Cos(shotAngle), Mathf.Sin(shotAngle), Mathf.Sin(shotRotation) * Mathf.Cos(shotAngle));
            Vector3 origin3     = new Vector3(origin.x, shotHeight, origin.y);
            Map     map         = launcher.Map;
            Vector3 destination = direction * verbProps.range + origin3;

            this.shotAngle    = shotAngle;
            this.shotHeight   = shotHeight;
            this.shotRotation = shotRotation;
            this.launcher     = launcher;
            this.origin       = origin;
            equipmentDef      = equipment?.def ?? null;
            Ray   ray          = new Ray(origin3, direction);
            var   lbce         = this as LaserBeamCE;
            float spreadRadius = Mathf.Sin(spreadDegrees / 2.0f * Mathf.Deg2Rad);

            LaserGunDef defWeapon = equipmentDef as LaserGunDef;
            Vector3     muzzle    = ray.GetPoint((defWeapon == null ? 0.9f : defWeapon.barrelLength));
            var         it_bounds = CE_Utility.GetBoundsFor(intendedTarget);

            for (int i = 1; i < verbProps.range; i++)
            {
                float spreadArea = (i * spreadRadius + aperatureSize) * (i * spreadRadius + aperatureSize) * 3.14159f;
                if (pprops.damageFalloff)
                {
                    lbce.DamageModifier = 1 / (magicLaserDamageConstant * spreadArea);
                }

                Vector3 tp = ray.GetPoint(i);
                if (tp.y > CollisionVertical.WallCollisionHeight)
                {
                    break;
                }
                if (tp.y < 0)
                {
                    destination   = tp;
                    landed        = true;
                    ExactPosition = tp;
                    Position      = ExactPosition.ToIntVec3();
                    break;
                }
                foreach (Thing thing in Map.thingGrid.ThingsListAtFast(tp.ToIntVec3()))
                {
                    if (this == thing)
                    {
                        continue;
                    }
                    var bounds = CE_Utility.GetBoundsFor(thing);
                    if (!bounds.IntersectRay(ray, out var dist))
                    {
                        continue;
                    }
                    if (i < 2 && thing != intendedTarget)
                    {
                        continue;
                    }

                    if (thing is Plant plant)
                    {
                        if (!Rand.Chance(thing.def.fillPercent * plant.Growth))
                        {
                            continue;
                        }
                    }
                    else if (thing is Building)
                    {
                        if (!Rand.Chance(thing.def.fillPercent))
                        {
                            continue;
                        }
                    }
                    ExactPosition = tp;
                    destination   = tp;
                    landed        = true;
                    LastPos       = destination;
                    ExactPosition = destination;
                    Position      = ExactPosition.ToIntVec3();

                    lbce.SpawnBeam(muzzle, destination);

                    lbce.Impact(thing, muzzle);

                    return;
                }
            }
            if (lbce != null)
            {
                lbce.SpawnBeam(muzzle, destination);
                Destroy(DestroyMode.Vanish);
                return;
            }
        }