protected override bool TryCastShot()
        {
            Pawn casterPawn = this.CasterPawn;

            if (casterPawn == null)
            {
                return(false);
            }
            foreach (CompUseEffect compUseEffect in base.EquipmentSource.GetComps <CompUseEffect>())
            {
                if (compUseEffect.CanBeUsedBy(casterPawn, out string failReason))
                {
                    compUseEffect.DoEffect(casterPawn);
                }
                else
                {
                    Messages.Message(failReason, casterPawn, MessageTypeDefOf.NegativeEvent, false);
                }
            }
            CompReloadable reloadableCompSource = base.ReloadableCompSource;

            if (reloadableCompSource != null)
            {
                reloadableCompSource.UsedOnce();
            }
            return(true);
        }
        // TryCastShotFrom(muzzlePos)
        public bool TryCastShotFrom(Vector3 muzzlePos)
        {
            if (!TryFindCEShootLineFromTo(caster.Position, currentTarget, out var shootLine))
            {
                return(false);
            }
            if (projectilePropsCE.pelletCount < 1)
            {
                Log.Error(EquipmentSource.LabelCap + " tried firing with pelletCount less than 1.");
                return(false);
            }
            ShiftVecReport report = ShiftVecReportFor(currentTarget);
            bool           pelletMechanicsOnly = false;

            numShotsFired = (int)AccessTools.Field(typeof(Verb_LaunchProjectileCE), "numShotsFired").GetValue(this);
            shotAngle     = (float)AccessTools.Field(typeof(Verb_LaunchProjectileCE), "shotAngle").GetValue(this);
            shotRotation  = (float)AccessTools.Field(typeof(Verb_LaunchProjectileCE), "shotRotation").GetValue(this);
            shotSpeed     = (float)AccessTools.Field(typeof(Verb_LaunchProjectileCE), "shotSpeed").GetValue(this);
            for (int i = 0; i < projectilePropsCE.pelletCount; i++)
            {
                ProjectileCE projectile = (ProjectileCE)ThingMaker.MakeThing(Projectile, null);
                GenSpawn.Spawn(projectile, shootLine.Source, caster.Map);
                ShiftTarget(report, pelletMechanicsOnly);

                //New aiming algorithm
                projectile.canTargetSelf = false;

                var targDist = (muzzlePos.ToIntVec3().ToIntVec2.ToVector2Shifted() - currentTarget.Cell.ToIntVec2.ToVector2Shifted()).magnitude;
                if (targDist <= 2)
                {
                    targDist *= 2;                      // Double to account for divide by 4 in ProjectileCE minimum collision distance calculations
                }
                //	projectile.minCollisionSqr = Mathf.Pow(targDist, 2);
                projectile.intendedTarget = currentTarget.Thing;
                projectile.mount          = caster.Position.GetThingList(caster.Map).FirstOrDefault(t => t is Pawn && t != caster);
                projectile.AccuracyFactor = report.accuracyFactor * report.swayDegrees * ((numShotsFired + 1) * 0.75f);
                projectile.Launch(
                    Shooter,                        //Shooter instead of caster to give turret operators' records the damage/kills obtained
                    new Vector2(muzzlePos.x, muzzlePos.z),
                    shotAngle,
                    shotRotation,
                    ShotHeight,
                    ShotSpeed,
                    EquipmentSource
                    );
                pelletMechanicsOnly = true;
            }
            /// Log.Message("Fired from "+caster.ThingID+" at "+ShotHeight); ///
            pelletMechanicsOnly = false;
            numShotsFired++;
            if (CompAmmo != null && !CompAmmo.CanBeFiredNow)
            {
                CompAmmo?.TryStartReload();
            }
            if (CompReloadable != null)
            {
                CompReloadable.UsedOnce();
            }
            return(true);
        }
예제 #3
0
        public static void EMP(CompReloadable comp)
        {
            if (comp == null || !comp.CanBeUsed)
            {
                return;
            }
            ThingWithComps parent = comp.parent;
            Pawn           wearer = comp.Wearer;

            GenExplosion.DoExplosion(wearer.Position, wearer.Map, parent.GetStatValue(AvaliDefs.ExplodeEMPRadius, true), DamageDefOf.EMP, (Thing)null, -1, -1f, (SoundDef)null, (ThingDef)null, (ThingDef)null, (Thing)null, (ThingDef)null, 0.0f, 1, false, (ThingDef)null, 0.0f, 1, 0.0f, false, new float?(), (List <Thing>)null);
            comp.UsedOnce();
        }
예제 #4
0
        protected override bool TryCastShot()
        {
            if (!ModLister.RoyaltyInstalled)
            {
                Log.ErrorOnce("Items with jump capability are a Royalty-specific game system. If you want to use this code please check ModLister.RoyaltyInstalled before calling it. See rules on the Ludeon forum for more info.", 550187797);
                return(false);
            }
#pragma warning disable CS0436 // Type conflicts with imported type
            CompReloadable reloadableCompSource = base.ReloadableCompSource;
#pragma warning restore CS0436 // Type conflicts with imported type
            Pawn casterPawn = CasterPawn;
            if (casterPawn == null || reloadableCompSource == null || !reloadableCompSource.CanBeUsed)
            {
                return(false);
            }
            //	Log.Message("reloadableCompSource " + reloadableCompSource.Props.chargeNoun);
            IntVec3            cell           = currentTarget.Cell;
            Map                map            = casterPawn.Map;
            CompReloadableDual reloadableDual = reloadableCompSource as CompReloadableDual;
            if (reloadableDual != null)
            {
                if (this.verbProps.label == reloadableDual.Props.chargeNoun)
                {
                    reloadableDual.UsedOnce();
                    //	Log.Message("reloadableDual UsedOnce " + reloadableDual.RemainingCharges);
                }
                else
                if (this.verbProps.label == reloadableDual.Props.chargeNounSecondry)
                {
                    reloadableDual.UsedOnceSecondry();
                    //	Log.Message("reloadableDual UsedOnceSecondry " + reloadableDual.RemainingChargesSecondry);
                }
            }
            else
            {
                if (this.verbProps.label == reloadableCompSource.Props.chargeNoun)
                {
                    reloadableCompSource.UsedOnce();
                    //	Log.Message("reloadableCompSource UsedOnce " + reloadableCompSource.RemainingCharges);
                }
            }
            PawnFlyer pawnFlyer = PawnFlyer.MakeFlyer(verbProps.defaultProjectile ?? ThingDefOf.PawnJumper, casterPawn, cell);
            if (pawnFlyer != null)
            {
                GenSpawn.Spawn(pawnFlyer, cell, map);
                return(true);
            }
            return(false);
        }
예제 #5
0
        protected override (bool success, Vector3 launchPos, float angle) TryCastShotInternal()
        {
            IntVec3 exitTarget = caster.Position.CellFromDistAngle(Building_Artillery.MaxMapDistance, heading);

            if (!target.HasWorldObject && !target.HasThing)
            {
                return(false, Vector3.zero, 0);
            }
            ThingDef projectile = Projectile;

            if (projectile is null)
            {
                return(false, Vector3.zero, 0);
            }
            bool flag = TryFindShootLineFromTo(caster.Position, exitTarget, out ShootLine shootLine);

            if (verbProps.stopBurstWithoutLos && !flag)
            {
                return(false, Vector3.zero, 0);
            }
            if (EquipmentSource != null)
            {
                CompChangeableProjectile comp = EquipmentSource.GetComp <CompChangeableProjectile>();
                if (comp != null)
                {
                    comp.Notify_ProjectileLaunched();
                }
                CompReloadable comp2 = EquipmentSource.GetComp <CompReloadable>();
                if (comp2 != null)
                {
                    comp2.UsedOnce();
                }
            }
            Thing        launcher     = caster;
            Thing        equipment    = EquipmentSource;
            CompMannable compMannable = caster.TryGetComp <CompMannable>();

            if (compMannable != null && compMannable.ManningPawn != null)
            {
                launcher  = compMannable.ManningPawn;
                equipment = caster;
            }
            Vector3    launchPos   = caster.DrawPos;
            Projectile projectile2 = (Projectile)GenSpawn.Spawn(projectile, caster.Position, caster.Map, WipeMode.Vanish);

            if (projectile2.AllComps.NullOrEmpty())
            {
                AccessTools.Field(typeof(ThingWithComps), "comps").SetValue(projectile2, new List <ThingComp>());
            }

            projectile2.AllComps.Add(new CompProjectileExitMap(CasterTWC)
            {
                airDefenseDef = AntiAircraftDefOf.FlakProjectile,
                target        = target.WorldObject as AerialVehicleInFlight,
                spawnPos      = Building_Artillery.RandomWorldPosition(caster.Map.Tile, 1).FirstOrDefault()
            });
            if (caster.def.GetModExtension <ProjectilePropertiesDefModExtension>() is ProjectilePropertiesDefModExtension projectileProps)
            {
                projectile2.AllComps.Add(new CompTurretProjectileProperties(CasterTWC)
                {
                    speed    = projectileProps.speed > 0 ? projectileProps.speed : projectile2.def.projectile.speed,
                    hitflag  = ProjectileHitFlags.IntendedTarget,
                    hitflags = null
                });
            }
            ThrowDebugText("ToHit" + (canHitNonTargetPawnsNow ? "\nchntp" : ""));
            launchPos += new Vector3(VerbProps.shootOffset.x, 0, VerbProps.shootOffset.y).RotatedBy(heading);
            projectile2.Launch(launcher, launchPos, exitTarget, exitTarget, ProjectileHitFlags.IntendedTarget, equipment);
            ThrowDebugText("Hit\nDest", shootLine.Dest);
            return(true, launchPos, heading);
        }
예제 #6
0
        /// <summary>
        /// Fires a projectile using the new aiming system
        /// </summary>
        /// <returns>True for successful shot, false otherwise</returns>
        public override bool TryCastShot()
        {
            if (!TryFindCEShootLineFromTo(caster.Position, currentTarget, out var shootLine))
            {
                return(false);
            }
            if (projectilePropsCE.pelletCount < 1)
            {
                Log.Error(EquipmentSource.LabelCap + " tried firing with pelletCount less than 1.");
                return(false);
            }
            bool instant = false;

            float spreadDegrees = 0;
            float aperatureSize = 0;

            if (Projectile.projectile is ProjectilePropertiesCE pprop)
            {
                instant       = pprop.isInstant;
                spreadDegrees = (EquipmentSource?.GetStatValue(StatDef.Named("ShotSpread")) ?? 0) * pprop.spreadMult;
                aperatureSize = 0.03f;
            }

            ShiftVecReport report = ShiftVecReportFor(currentTarget);
            bool           pelletMechanicsOnly = false;

            for (int i = 0; i < projectilePropsCE.pelletCount; i++)
            {
                ProjectileCE projectile = (ProjectileCE)ThingMaker.MakeThing(Projectile, null);
                GenSpawn.Spawn(projectile, shootLine.Source, caster.Map);
                ShiftTarget(report, pelletMechanicsOnly, instant);

                //New aiming algorithm
                projectile.canTargetSelf = false;

                var targetDistance = (sourceLoc - currentTarget.Cell.ToIntVec2.ToVector2Shifted()).magnitude;
                projectile.minCollisionDistance = GetMinCollisionDistance(targetDistance);
                projectile.intendedTarget       = currentTarget;
                projectile.mount          = caster.Position.GetThingList(caster.Map).FirstOrDefault(t => t is Pawn && t != caster);
                projectile.AccuracyFactor = report.accuracyFactor * report.swayDegrees * ((numShotsFired + 1) * 0.75f);

                if (instant)
                {
                    var   shotHeight = ShotHeight;
                    float tsa        = AdjustShotHeight(caster, currentTarget, ref shotHeight);
                    projectile.RayCast(
                        Shooter,
                        verbProps,
                        sourceLoc,
                        shotAngle + tsa,
                        shotRotation,
                        shotHeight,
                        ShotSpeed,
                        spreadDegrees,
                        aperatureSize,
                        EquipmentSource);
                }
                else
                {
                    projectile.Launch(
                        Shooter,                  //Shooter instead of caster to give turret operators' records the damage/kills obtained
                        sourceLoc,
                        shotAngle,
                        shotRotation,
                        ShotHeight,
                        ShotSpeed,
                        EquipmentSource);
                }
                pelletMechanicsOnly = true;
            }

            /*
             * Notify the lighting tracker that shots fired with muzzle flash value of VerbPropsCE.muzzleFlashScale
             */
            LightingTracker.Notify_ShotsFiredAt(caster.Position, intensity: VerbPropsCE.muzzleFlashScale);

            pelletMechanicsOnly = false;
            numShotsFired++;
            if (CompAmmo != null && !CompAmmo.CanBeFiredNow)
            {
                CompAmmo?.TryStartReload();
            }
            if (CompReloadable != null)
            {
                CompReloadable.UsedOnce();
            }
            return(true);
        }
예제 #7
0
            //[HarmonyPrefix]
            static bool Prefix(ref bool __result, Verb_LaunchProjectile __instance, LocalTargetInfo ___currentTarget)
            {
                if (__instance.verbProps.forcedMissRadius < 0.5f || __instance.verbProps.requireLineOfSight)
                {
                    // Assuming this is not a mortar-like thing
                    // Perform vanilla logic
                    return(true);
                }
                else
                {
                    // Perform the same vanilla checks
                    if (___currentTarget.HasThing && ___currentTarget.Thing.Map != __instance.caster.Map)
                    {
                        __result = false;
                        return(false);
                    }
                    ThingDef projectile = __instance.Projectile;
                    if (projectile == null)
                    {
                        __result = false;
                        return(false);
                    }
                    ShootLine shootLine = default(ShootLine);
                    bool      flag      = __instance.TryFindShootLineFromTo(__instance.caster.Position, ___currentTarget, out shootLine);
                    if (__instance.verbProps.stopBurstWithoutLos && !flag)
                    {
                        __result = false;
                        return(false);
                    }

                    // Vanilla checks pass, we can shoot
                    if (__instance.EquipmentSource != null)
                    {
                        CompChangeableProjectile comp = __instance.EquipmentSource.GetComp <CompChangeableProjectile>();
                        if (comp != null)
                        {
                            comp.Notify_ProjectileLaunched();
                        }
                        CompReloadable comp2 = __instance.EquipmentSource.GetComp <CompReloadable>();
                        if (comp2 != null)
                        {
                            comp2.UsedOnce();
                        }
                    }

                    Thing        launcher     = __instance.caster;
                    Thing        equipment    = __instance.EquipmentSource;
                    CompMannable compMannable = __instance.caster.TryGetComp <CompMannable>();
                    if (compMannable != null && compMannable.ManningPawn != null)
                    {
                        launcher  = compMannable.ManningPawn;
                        equipment = __instance.caster;
                        // Earn skills
                        if (compMannable.ManningPawn.skills != null)
                        {
                            int skillsAffectingAccuracy = 0;
                            if (Settings.intellectualAffectsMortarAccuracy)
                            {
                                skillsAffectingAccuracy++;
                            }
                            if (Settings.shootingAffectsMortarAccuracy)
                            {
                                skillsAffectingAccuracy++;
                            }

                            float skillXP = __instance.verbProps.AdjustedFullCycleTime(__instance, __instance.CasterPawn) * 100;
                            skillXP  = Mathf.Clamp(skillXP, 0, 200);
                            skillXP /= skillsAffectingAccuracy;

                            if (Settings.intellectualAffectsMortarAccuracy)
                            {
                                compMannable.ManningPawn.skills.Learn(SkillDefOf.Intellectual, skillXP, false);
                            }
                            if (Settings.shootingAffectsMortarAccuracy)
                            {
                                compMannable.ManningPawn.skills.Learn(SkillDefOf.Shooting, skillXP, false);
                            }
                        }
                    }

                    Vector3    drawPos     = __instance.caster.DrawPos;
                    Projectile projectile2 = (Projectile)GenSpawn.Spawn(projectile, shootLine.Source, __instance.caster.Map, WipeMode.Vanish);

                    // If targetting a pawn
                    if (Settings.targetLeading)
                    {
                        if (___currentTarget != null && ___currentTarget.Thing != null && ___currentTarget.Thing is Pawn targetPawn && targetPawn.pather.curPath != null)
                        {
                            List <IntVec3> nodes = new List <IntVec3>(targetPawn.pather.curPath.NodesReversed);
                            nodes.Reverse();
                            // Purge outdated nodes from list
                            for (int i = 0; i < nodes.Count; i++)
                            {
                                if (nodes[i] == targetPawn.Position)
                                {
                                    // Remove all previous nodes
                                    nodes.RemoveRange(0, i);
                                    //Log.Message("Removed " + i + " entries. First node is now " + nodes[0].ToString());
                                    break;
                                }
                            }
                            // Path of target pawn from current to destination
                            // Need travel speed of pawn, estimate Vec3 they will be in based on travel speed of our projectile
                            float targetMoveSpeed     = targetPawn.GetStatValue(StatDefOf.MoveSpeed);
                            float projectileMoveSpeed = projectile.projectile.speed;

                            // Estimate position target will be in after this amount of time
                            IntVec3 bestTarget     = targetPawn.Position;
                            float   bestTimeOffset = float.MaxValue;
                            //Log.Message("Default time offset = " + Mathf.Abs(((targetPawn.Position - caster.Position).LengthHorizontal) / projectileMoveSpeed));
                            float accumulatedTargetTime = 0f;

                            IntVec3 previousPosition = targetPawn.Position;
                            foreach (IntVec3 pathPosition in nodes)
                            {
                                float projectileDistanceFromTarget     = (pathPosition - __instance.caster.Position).LengthHorizontal;
                                float timeForProjectileToReachPosition = projectileDistanceFromTarget / projectileMoveSpeed;

                                //float pawnDistanceFromTarget = (pathPosition - targetPawn.Position).LengthHorizontal;
                                //float timeForPawnToReachPosition = pawnDistanceFromTarget / targetMoveSpeed;

                                float pawnDistanceFromLastPositionToHere         = (pathPosition - previousPosition).LengthHorizontal;
                                float timeForPawnToReachPositionFromLastPosition = pawnDistanceFromLastPositionToHere / targetMoveSpeed;
                                accumulatedTargetTime += timeForPawnToReachPositionFromLastPosition;

                                float timeOffset = Mathf.Abs(timeForProjectileToReachPosition - accumulatedTargetTime);
                                if (timeOffset < bestTimeOffset)
                                {
                                    bestTarget     = pathPosition;
                                    bestTimeOffset = timeOffset;
                                    //Log.Message("Position " + pathPosition.ToString() + " is better. Time offset is " + timeOffset);
                                }
                                else
                                {
                                    //Log.Message("Position " + pathPosition.ToString() + " is not better. Time offset is " + timeOffset);
                                }

                                previousPosition = pathPosition;
                            }
                            //Log.Message("Initial target cell = " + currentTarget.Cell.ToString() + " and new target is " + bestTarget.ToString());
                            ___currentTarget = new LocalTargetInfo(bestTarget);
                        }
                    }

                    float adjustedForcedMissRadius        = GetAdjustedForcedMissRadius(__instance, ___currentTarget);
                    ProjectileHitFlags projectileHitFlags = ProjectileHitFlags.All;
                    IntVec3            targetPosition     = ___currentTarget.Cell;
                    //if (adjustedForcedMissRadius > 0.5f)
                    {
                        if (MP.enabled)
                        {
                            Rand.PushState();
                        }

                        // Calculate random target position using a uniform distribution
                        float randomCircleArea     = Rand.Range(0, Mathf.PI * adjustedForcedMissRadius * adjustedForcedMissRadius);
                        float radiusOfRandomCircle = Mathf.Sqrt(randomCircleArea / Mathf.PI);
                        float randomAngle          = Rand.Range(0, 2 * Mathf.PI);
                        targetPosition = new IntVec3(
                            (int)(targetPosition.x + radiusOfRandomCircle * Mathf.Cos(randomAngle)),
                            targetPosition.y,
                            (int)(targetPosition.z + radiusOfRandomCircle * Mathf.Sin(randomAngle))
                            );

                        if (MP.enabled)
                        {
                            Rand.PopState();
                        }
                    }

                    //Log.Message("Final target is " + c.ToString());
                    projectile2.Launch(launcher, drawPos, targetPosition, ___currentTarget, projectileHitFlags, equipment, null);
                }
                __result = true;
                return(false);
            }
예제 #8
0
        protected virtual (bool success, Vector3 launchPos, float angle) TryCastShotInternal()
        {
            if (currentTarget.HasThing && currentTarget.Thing.Map != caster.Map)
            {
                return(false, Vector3.zero, 0);
            }
            ThingDef projectile = Projectile;

            if (projectile == null)
            {
                return(false, Vector3.zero, 0);
            }
            ShootLine shootLine;
            bool      flag = TryFindShootLineFromTo(caster.Position, currentTarget, out shootLine);

            if (verbProps.stopBurstWithoutLos && !flag)
            {
                return(false, Vector3.zero, 0);
            }
            if (EquipmentSource != null)
            {
                CompChangeableProjectile comp = EquipmentSource.GetComp <CompChangeableProjectile>();
                if (comp != null)
                {
                    comp.Notify_ProjectileLaunched();
                }
                CompReloadable comp2 = EquipmentSource.GetComp <CompReloadable>();
                if (comp2 != null)
                {
                    comp2.UsedOnce();
                }
            }
            Thing        launcher     = caster;
            Thing        equipment    = EquipmentSource;
            CompMannable compMannable = caster.TryGetComp <CompMannable>();

            if (compMannable != null && compMannable.ManningPawn != null)
            {
                launcher  = compMannable.ManningPawn;
                equipment = caster;
            }
            Vector3    launchPos   = caster.DrawPos;
            float      angle       = launchPos.AngleToPoint(currentTarget.CenterVector3);
            Projectile projectile2 = (Projectile)GenSpawn.Spawn(projectile, shootLine.Source, caster.Map, WipeMode.Vanish);

            if (caster.def.GetModExtension <ProjectilePropertiesDefModExtension>() is ProjectilePropertiesDefModExtension projectileProps)
            {
                projectile2.AllComps.Insert(0, new CompTurretProjectileProperties(CasterTWC)
                {
                    speed    = projectileProps.speed > 0 ? projectileProps.speed : projectile2.def.projectile.speed,
                    hitflag  = projectileProps.projectileHitFlag,
                    hitflags = projectileProps.hitFlagDef
                });
            }
            if (verbProps.forcedMissRadius > 0.5f)
            {
                float num = VerbUtility.CalculateAdjustedForcedMiss(verbProps.forcedMissRadius, currentTarget.Cell - caster.Position);
                if (num > 0.5f)
                {
                    int max  = GenRadial.NumCellsInRadius(num);
                    int num2 = Rand.Range(0, max);
                    if (num2 > 0)
                    {
                        IntVec3 c = currentTarget.Cell + GenRadial.RadialPattern[num2];
                        launchPos += new Vector3(VerbProps.shootOffset.x, 0, VerbProps.shootOffset.y).RotatedBy(angle);
                        ThrowDebugText("ToRadius");
                        ThrowDebugText("Rad\nDest", c);
                        ProjectileHitFlags projectileHitFlags = ProjectileHitFlags.NonTargetWorld;
                        if (Rand.Chance(0.5f))
                        {
                            projectileHitFlags = ProjectileHitFlags.All;
                        }
                        if (!canHitNonTargetPawnsNow)
                        {
                            projectileHitFlags &= ~ProjectileHitFlags.NonTargetPawns;
                        }
                        projectile2.Launch(launcher, launchPos, c, currentTarget, projectileHitFlags, equipment, null);
                        return(true, launchPos, angle);
                    }
                }
            }
            ShotReport shotReport            = ShotReport.HitReportFor(caster, this, currentTarget);
            Thing      randomCoverToMissInto = shotReport.GetRandomCoverToMissInto();
            ThingDef   targetCoverDef        = (randomCoverToMissInto != null) ? randomCoverToMissInto.def : null;

            if (!Rand.Chance(shotReport.AimOnTargetChance_IgnoringPosture))
            {
                shootLine.ChangeDestToMissWild(shotReport.AimOnTargetChance_StandardTarget);
                ThrowDebugText("ToWild" + (canHitNonTargetPawnsNow ? "\nchntp" : ""));
                ThrowDebugText("Wild\nDest", shootLine.Dest);
                ProjectileHitFlags projectileHitFlags2 = ProjectileHitFlags.NonTargetWorld;
                if (Rand.Chance(0.5f) && canHitNonTargetPawnsNow)
                {
                    projectileHitFlags2 |= ProjectileHitFlags.NonTargetPawns;
                }
                launchPos += new Vector3(VerbProps.shootOffset.x, 0, VerbProps.shootOffset.y).RotatedBy(angle);
                projectile2.Launch(launcher, launchPos, shootLine.Dest, currentTarget, projectileHitFlags2, equipment, targetCoverDef);
                return(true, launchPos, angle);
            }
            if (currentTarget.Thing != null && currentTarget.Thing.def.category == ThingCategory.Pawn && !Rand.Chance(shotReport.PassCoverChance))
            {
                ThrowDebugText("ToCover" + (canHitNonTargetPawnsNow ? "\nchntp" : ""));
                ThrowDebugText("Cover\nDest", randomCoverToMissInto.Position);
                ProjectileHitFlags projectileHitFlags3 = ProjectileHitFlags.NonTargetWorld;
                if (canHitNonTargetPawnsNow)
                {
                    projectileHitFlags3 |= ProjectileHitFlags.NonTargetPawns;
                }
                launchPos += new Vector3(VerbProps.shootOffset.x, 0, VerbProps.shootOffset.y).RotatedBy(angle);
                projectile2.Launch(launcher, launchPos, randomCoverToMissInto, currentTarget, projectileHitFlags3, equipment, targetCoverDef);
                return(true, launchPos, angle);
            }
            ProjectileHitFlags projectileHitFlags4 = ProjectileHitFlags.IntendedTarget;

            if (canHitNonTargetPawnsNow)
            {
                projectileHitFlags4 |= ProjectileHitFlags.NonTargetPawns;
            }
            if (!currentTarget.HasThing || currentTarget.Thing.def.Fillage == FillCategory.Full)
            {
                projectileHitFlags4 |= ProjectileHitFlags.NonTargetWorld;
            }
            ThrowDebugText("ToHit" + (canHitNonTargetPawnsNow ? "\nchntp" : ""));

            if (currentTarget.Thing != null)
            {
                angle      = launchPos.AngleToPoint(currentTarget.CenterVector3);
                launchPos += new Vector3(VerbProps.shootOffset.x, 0, VerbProps.shootOffset.y).RotatedBy(angle);
                projectile2.Launch(launcher, launchPos, currentTarget, currentTarget, projectileHitFlags4, equipment, targetCoverDef);
                ThrowDebugText("Hit\nDest", currentTarget.Cell);
            }
            else
            {
                angle      = launchPos.AngleToPoint(shootLine.Dest.ToVector3Shifted());
                launchPos += new Vector3(VerbProps.shootOffset.x, 0, VerbProps.shootOffset.y).RotatedBy(angle);
                projectile2.Launch(launcher, launchPos, shootLine.Dest, currentTarget, projectileHitFlags4, equipment, targetCoverDef);
                ThrowDebugText("Hit\nDest", shootLine.Dest);
            }
            return(true, launchPos, angle);
        }
        protected override bool TryCastShot()
        {
            if (this.currentTarget.HasThing && this.currentTarget.Thing.Map != this.caster.Map)
            {
                return(false);
            }
            ThingDef projectile = this.Projectile;

            if (projectile == null)
            {
                return(false);
            }
            ShootLine shootLine;
            bool      flag = base.TryFindShootLineFromTo(this.caster.Position, this.currentTarget, out shootLine);

            if (this.verbProps.stopBurstWithoutLos && !flag)
            {
                return(false);
            }
            if (base.EquipmentSource != null)
            {
                CompChangeableProjectile comp = base.EquipmentSource.GetComp <CompChangeableProjectile>();
                if (comp != null)
                {
                    comp.Notify_ProjectileLaunched();
                }
                CompReloadable comp2 = base.EquipmentSource.GetComp <CompReloadable>();
                if (comp2 != null)
                {
                    comp2.UsedOnce();
                }
            }
            Thing        launcher     = this.caster;
            Thing        equipment    = base.EquipmentSource;
            CompMannable compMannable = this.caster.TryGetComp <CompMannable>();

            if (compMannable != null && compMannable.ManningPawn != null)
            {
                launcher  = compMannable.ManningPawn;
                equipment = this.caster;
            }
            Vector3 drawPos      = this.caster.DrawPos;
            var     casterTurret = caster as Building_TurretGun;
            Thing   gun          = null;

            if (casterTurret != null)
            {
                gun = casterTurret.gun;
            }
            var        newSource    = ApplyOffset(shootLine.Source, shootLine.Dest);
            var        newSourceVec = newSource.ToVector3();
            Projectile projectile2  = (Projectile)GenSpawn.Spawn(projectile, this.caster.Position, this.caster.Map, WipeMode.Vanish);


            if (this.verbProps.ForcedMissRadius > 0.5f)
            {
                float num = VerbUtility.CalculateAdjustedForcedMiss(this.verbProps.ForcedMissRadius, this.currentTarget.Cell - this.caster.Position);
                if (num > 0.5f)
                {
                    int max  = GenRadial.NumCellsInRadius(num);
                    int num2 = Rand.Range(0, max);
                    if (num2 > 0)
                    {
                        IntVec3 c = this.currentTarget.Cell + GenRadial.RadialPattern[num2];
                        this.ThrowDebugText("ToRadius");
                        this.ThrowDebugText("Rad\nDest", c);
                        ProjectileHitFlags projectileHitFlags = ProjectileHitFlags.NonTargetWorld;
                        if (Rand.Chance(0.5f))
                        {
                            projectileHitFlags = ProjectileHitFlags.All;
                        }
                        if (!this.canHitNonTargetPawnsNow)
                        {
                            projectileHitFlags &= ~ProjectileHitFlags.NonTargetPawns;
                        }
                        projectile2.Launch(launcher, newSourceVec, c, this.currentTarget, projectileHitFlags, false, equipment, null);
                        return(true);
                    }
                }
            }
            ShotReport shotReport            = ShotReport.HitReportFor(this.caster, this, this.currentTarget);
            Thing      randomCoverToMissInto = shotReport.GetRandomCoverToMissInto();
            ThingDef   targetCoverDef        = (randomCoverToMissInto != null) ? randomCoverToMissInto.def : null;

            if (!Rand.Chance(shotReport.AimOnTargetChance_IgnoringPosture))
            {
                shootLine.ChangeDestToMissWild(shotReport.AimOnTargetChance_StandardTarget);
                this.ThrowDebugText("ToWild" + (this.canHitNonTargetPawnsNow ? "\nchntp" : ""));
                this.ThrowDebugText("Wild\nDest", shootLine.Dest);
                ProjectileHitFlags projectileHitFlags2 = ProjectileHitFlags.NonTargetWorld;
                if (Rand.Chance(0.5f) && this.canHitNonTargetPawnsNow)
                {
                    projectileHitFlags2 |= ProjectileHitFlags.NonTargetPawns;
                }
                projectile2.Launch(launcher, newSourceVec, shootLine.Dest, this.currentTarget, projectileHitFlags2, false, equipment, targetCoverDef);
                return(true);
            }
            if (this.currentTarget.Thing != null && this.currentTarget.Thing.def.category == ThingCategory.Pawn && !Rand.Chance(shotReport.PassCoverChance))
            {
                this.ThrowDebugText("ToCover" + (this.canHitNonTargetPawnsNow ? "\nchntp" : ""));
                this.ThrowDebugText("Cover\nDest", randomCoverToMissInto.Position);
                ProjectileHitFlags projectileHitFlags3 = ProjectileHitFlags.NonTargetWorld;
                if (this.canHitNonTargetPawnsNow)
                {
                    projectileHitFlags3 |= ProjectileHitFlags.NonTargetPawns;
                }
                projectile2.Launch(launcher, newSourceVec, randomCoverToMissInto, this.currentTarget, projectileHitFlags3, false, equipment, targetCoverDef);
                return(true);
            }
            ProjectileHitFlags projectileHitFlags4 = ProjectileHitFlags.IntendedTarget;

            if (this.canHitNonTargetPawnsNow)
            {
                projectileHitFlags4 |= ProjectileHitFlags.NonTargetPawns;
            }
            if (!this.currentTarget.HasThing || this.currentTarget.Thing.def.Fillage == FillCategory.Full)
            {
                projectileHitFlags4 |= ProjectileHitFlags.NonTargetWorld;
            }
            this.ThrowDebugText("ToHit" + (this.canHitNonTargetPawnsNow ? "\nchntp" : ""));
            if (this.currentTarget.Thing != null)
            {
                projectile2.Launch(launcher, newSourceVec, this.currentTarget, this.currentTarget, projectileHitFlags4, false, equipment, targetCoverDef);
                this.ThrowDebugText("Hit\nDest", this.currentTarget.Cell);
            }
            else
            {
                projectile2.Launch(launcher, newSourceVec, shootLine.Dest, this.currentTarget, projectileHitFlags4, false, equipment, targetCoverDef);
                this.ThrowDebugText("Hit\nDest", shootLine.Dest);
            }
            return(true);
        }