Esempio n. 1
0
        public static void Postfix(Verb __instance, IntVec3 root, LocalTargetInfo targ, ref ShootLine resultingLine, ref bool __result)
        {
            if (teleportBack)
            {
                if (oldMap1 != null)
                {
                    ZUtils.TeleportThing(targ.Thing, oldMap1, targ.Thing.Position);
                    oldMap1 = null;
                }
                else if (oldMap2 != null)
                {
                    ZUtils.TeleportThing(__instance.caster, oldMap2, __instance.caster.Position);
                    oldMap2 = null;
                }

                if (__result)
                {
                    if (ind1 > ind2 && !IsVoidsEverywhereInShootingLine(resultingLine, __instance.caster.Map, __instance.caster, targ.Thing))
                    {
                        __result = false;
                    }
                    else if (ind1 < ind2 && !IsVoidsEverywhereInShootingLineInBackWard(resultingLine, targ.Thing.Map, __instance.caster, targ.Thing))
                    {
                        __result = false;
                    }
                }

                ind1         = 0;
                ind2         = 0;
                teleportBack = false;
            }
        }
 internal static bool Prefix(Verb __instance, ref bool __result, IntVec3 root, LocalTargetInfo targ, ref ShootLine resultingLine)
 {
     if (__instance is Verb_LaunchProjectileCE launchVerbCE)
     {
         __result = launchVerbCE.TryFindCEShootLineFromTo(root, targ, out resultingLine);
         return(false);
     }
     return(true);
 }
Esempio n. 3
0
        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)
            {
                // 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);
        }
Esempio n. 4
0
 public static void Prefix(Verb __instance, IntVec3 root, LocalTargetInfo targ, ref ShootLine resultingLine, ref bool __result)
 {
     if (__instance.caster?.Map != targ.Thing?.Map && __instance.caster?.Map?.Tile == targ.Thing?.Map?.Tile)
     {
         ind1 = ZUtils.ZTracker.GetZIndexFor(__instance.caster.Map);
         ind2 = ZUtils.ZTracker.GetZIndexFor(targ.Thing.Map);
         if (ind1 > ind2)
         {
             teleportBack = true;
             oldMap1      = targ.Thing.Map;
             ZUtils.TeleportThing(targ.Thing, __instance.caster.Map, targ.Thing.Position);
         }
         else if (ind1 < ind2)
         {
             teleportBack = true;
             oldMap2      = __instance.caster.Map;
             ZUtils.TeleportThing(__instance.caster, targ.Thing.Map, __instance.caster.Position);
         }
     }
 }
Esempio n. 5
0
            static bool AddShieldCheck(ref bool __result, Verb __instance, IntVec3 root, LocalTargetInfo targ, ref ShootLine resultingLine)
            {
                if (ShieldBlocks(__instance.caster, __instance, root, targ))
                {
                    __result      = false;
                    resultingLine = new ShootLine();
                    return(false);
                }

                return(true);
            }
Esempio n. 6
0
 private bool TryFindShootLineFromTo(IntVec3 root, LocalTargetInfo targ, out ShootLine resultingLine)
 {
     resultingLine = new ShootLine(root, targ.Cell);
     return(false);
 }
Esempio n. 7
0
 public void Notify_WarmingCastAlongLine(ShootLine newShootLine, IntVec3 ShootPosition)
 {
     shootSourceOffset = newShootLine.Source - actor.Position;
 }
        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.MeleeRange)
            {
                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 (ProjectileDef.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);
        }
Esempio n. 9
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);
            }
 // Token: 0x060041D3 RID: 16851 RVA: 0x001E066F File Offset: 0x001DEA6F
 public void Notify_WarmingCastAlongLine(ShootLine newShootLine, IntVec3 ShootPosition)
 {
     this.leaner.Notify_WarmingCastAlongLine(newShootLine, ShootPosition);
 }
Esempio n. 11
0
 public static bool Prefix(Verb __instance, IntVec3 root, LocalTargetInfo targ, out ShootLine resultingLine, ref bool __result)
 {
     if (__instance.verbProps.IsMeleeAttack)
     {
         resultingLine = new ShootLine(root, targ.Cell);
         __result      = ReachabilityImmediate.CanReachImmediate(root, targ, __instance.caster.Map, PathEndMode.Touch, null);
         return(false);
     }
     if (__instance.verbProps.verbClass.ToString() == "Wizardry.Verb_BLOS")
     {
         //Ignores line of sight
         resultingLine = new ShootLine(root, targ.Cell);
         __result      = true;
         return(false);
     }
     resultingLine = default(ShootLine);
     __result      = true;
     return(true);
 }
        public bool FireProjectile()
        {
            if (base.currentTarget.HasThing && base.currentTarget.Thing.Map != base.caster.Map)
            {
                return(false);
            }
            ThingDef projectile = this.Projectile;

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

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

            if (compMannable != null && compMannable.ManningPawn != null)
            {
                launcher  = compMannable.ManningPawn;
                equipment = base.caster;
                // Earn skills
                if (compMannable.ManningPawn.skills != null)
                {
                    int skillsAffectingAccuracy = 0;
                    if (Settings.intellectualAffectsMortarAccuracy)
                    {
                        skillsAffectingAccuracy++;
                    }
                    if (Settings.shootingAffectsMortarAccuracy)
                    {
                        skillsAffectingAccuracy++;
                    }

                    float skillXP = verbProps.AdjustedFullCycleTime(this, CasterPawn) * 100;
                    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     = base.caster.DrawPos;
            Projectile projectile2 = (Projectile)GenSpawn.Spawn(projectile, shootLine.Source, base.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 - 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);
                }
            }

            if (base.verbProps.forcedMissRadius > 0.5f)
            {
                float adjustedForcedMissRadius        = GetAdjustedForcedMissRadius();
                ProjectileHitFlags projectileHitFlags = ProjectileHitFlags.All;
                IntVec3            targetPosition     = currentTarget.Cell;
                if (adjustedForcedMissRadius > 0.5f)
                {
                    int max = GenRadial.NumCellsInRadius(adjustedForcedMissRadius);

                    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, base.currentTarget, projectileHitFlags, equipment, null);
                return(true);
            }
            ShotReport shotReport            = ShotReport.HitReportFor(base.caster, this, base.currentTarget);
            Thing      randomCoverToMissInto = shotReport.GetRandomCoverToMissInto();
            ThingDef   targetCoverDef        = (randomCoverToMissInto == null) ? null : randomCoverToMissInto.def;

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

            if (base.canHitNonTargetPawnsNow)
            {
                projectileHitFlags4 |= ProjectileHitFlags.NonTargetPawns;
            }
            if (!base.currentTarget.HasThing || base.currentTarget.Thing.def.Fillage == FillCategory.Full)
            {
                projectileHitFlags4 |= ProjectileHitFlags.NonTargetWorld;
            }
            this.ThrowDebugText("ToHit" + ((!base.canHitNonTargetPawnsNow) ? string.Empty : "\nchntp"));
            if (base.currentTarget.Thing != null)
            {
                projectile2.Launch(launcher, drawPos, base.currentTarget, base.currentTarget, projectileHitFlags4, equipment, targetCoverDef);
                this.ThrowDebugText("Hit\nDest", base.currentTarget.Cell);
            }
            else
            {
                projectile2.Launch(launcher, drawPos, shootLine.Dest, base.currentTarget, projectileHitFlags4, equipment, targetCoverDef);
                this.ThrowDebugText("Hit\nDest", shootLine.Dest);
            }
            return(true);
        }
        // Token: 0x06003B77 RID: 15223 RVA: 0x001BFC0C File Offset: 0x001BE00C
        protected override IEnumerable <Toil> MakeNewToils()
        {
            yield return(Toils_General.DoAtomic(delegate
            {
                Pawn pawn = this.job.targetA.Thing as Pawn;
                if (pawn != null && pawn.Downed && this.pawn.mindState.duty != null && this.pawn.mindState.duty.attackDownedIfStarving && this.pawn.Starving())
                {
                    this.job.killIncappedTarget = true;
                }
            }));

            yield return(Toils_Misc.ThrowColonistAttackingMote(TargetIndex.A));

            //
            yield return(new Toil()
            {
                initAction = () =>
                {
                    Pawn actor = this.GetActor();
                    Vector3 drawPos = actor.DrawPos;
                    var shootLine = new ShootLine(actor.PositionHeld, pawn.PositionHeld);
                    Projectile projectile2 = (Projectile)GenSpawn.Spawn(ThingDef.Named("LotRD_Dragonfireblast"), shootLine.Source, actor.Map, WipeMode.Vanish);
                    if (Rand.Value > 0.9f)
                    {
                        //Log.Message("Miss");
                        int num = Rand.Range(2, 3);
                        int max = GenRadial.NumCellsInRadius(num);
                        int num2 = Rand.Range(0, max);
                        if (num2 > 0)
                        {
                            IntVec3 c = pawn.PositionHeld + GenRadial.RadialPattern[num2];
                            ProjectileHitFlags projectileHitFlags = ProjectileHitFlags.NonTargetWorld;
                            if (Rand.Chance(0.5f))
                            {
                                projectileHitFlags = ProjectileHitFlags.All;
                            }
                            projectile2.Launch(actor, drawPos, c, pawn, projectileHitFlags, null, null);
                            return;
                        }
                    }
                    var covers = CoverUtility.CalculateCoverGiverSet(job.targetA, actor.Position, actor.Map);
                    covers.TryRandomElementByWeight((CoverInfo c) => c.BlockChance, out CoverInfo coverInfo);
                    ThingDef targetCoverDef = (coverInfo.Thing == null) ? null : coverInfo.Thing.def;

                    if (pawn != null)
                    {
                        projectile2.Launch(actor, drawPos + new Vector3(0, 0, 3), pawn, pawn, ProjectileHitFlags.All, null, targetCoverDef);
                    }
                    else
                    {
                        projectile2.Launch(actor, drawPos + new Vector3(0, 0, 3), shootLine.Dest, pawn, ProjectileHitFlags.All, null, targetCoverDef);
                    }

                    // Sends a wave outwards of flames
                    Vector2 behindVector = pawn.Rotation.AsVector2;
                    var behind = new IntVec3((int)behindVector.x, 0, (int)behindVector.y);
                    int rand = Rand.Range(6, 12);
                    //Log.Message("Pawn position: " + pawn.PositionHeld.x.ToString() + " " + pawn.PositionHeld.z.ToString());
                    for (int i = 0; i < rand; i++)
                    {
                        IntVec3 adjustment = new IntVec3((int)pawn.PositionHeld.x + (int)behind.x + i, pawn.PositionHeld.y, (int)pawn.PositionHeld.z + (int)behind.z + i);
                        //Log.Message("Fire position: " + adjustment.x.ToString() + " " + adjustment.z.ToString());
                        if (!adjustment.IsValid)
                        {
                            continue;
                        }
                        Projectile projectileNew = (Projectile)GenSpawn.Spawn(ThingDef.Named("LotRD_Dragonfireblast"), shootLine.Source, actor.Map, WipeMode.Vanish);
                        var headoffset = (actor.Rotation == Rot4.West) ? -3.75f : 3.75f;
                        projectileNew.Launch(actor, drawPos + new Vector3(0, 0, 1.5f) + new Vector3(actor.Rotation.AsVector2.x + headoffset, 0, actor.Rotation.AsVector2.y), adjustment, pawn, ProjectileHitFlags.All, null, targetCoverDef);
                    }
                }
            });
        public static void ExtraProjectiles(Projectile projectile2, Thing launcher, Vector3 origin, LocalTargetInfo usedTarget, LocalTargetInfo intendedTarget, ProjectileHitFlags hitFlags, Thing equipment, ThingDef targetCoverDef, ShootLine shootLine, Verb_LaunchProjectile instance)
        {
            IDrawnWeaponWithRotation weapon = null;
            Pawn pawn = launcher as Pawn;

            if (pawn != null && pawn.equipment != null)
            {
                weapon = pawn.equipment.Primary as IDrawnWeaponWithRotation;
            }
            if (weapon == null)
            {
                Building_LaserGun turret = launcher as Building_LaserGun;
                if (turret != null)
                {
                    weapon = turret.gun as IDrawnWeaponWithRotation;
                }
            }
            if (weapon != null)
            {
                float angle = (usedTarget.CenterVector3 - origin).AngleFlat() - (intendedTarget.CenterVector3 - origin).AngleFlat();
                weapon.RotationOffset = (angle + 180) % 360 - 180;
            }
            projectile2.Launch(launcher, origin, usedTarget, intendedTarget, hitFlags, equipment, targetCoverDef);
            int           extras = 0;
            IAdvancedVerb Props  = instance.verbProps as IAdvancedVerb;

            if (Props != null)
            {
                extras = Props.ScattershotCount;
            }
            else
            {
                ScattershotProjectileExtension ext = projectile2.def.GetModExtensionFast <ScattershotProjectileExtension>();
                if (ext != null && ext.projectileCount.HasValue)
                {
                    extras = ext.projectileCount.Value;
                }
            }
            if (extras > 0)
            {
                for (int i = 0; i < extras; i++)
                {
                    Projectile projectile3 = (Projectile)GenSpawn.Spawn(projectile2.def, shootLine.Source, launcher.Map, WipeMode.Vanish);
                    projectile3.Launch(launcher, origin, usedTarget, intendedTarget, hitFlags, equipment, targetCoverDef);
                }
            }
        }
        // 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)
            {
                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, Verb_ShootCompMounted.tempLeanShootSources);
                for (int i = 0; i < Verb_ShootCompMounted.tempLeanShootSources.Count; i++)
                {
                    IntVec3 intVec = Verb_ShootCompMounted.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))
                {
                    IntVec3 dest;
                    if (this.CanHitFromCellIgnoringRange(intVec2, targ, out dest))
                    {
                        resultingLine = new ShootLine(intVec2, dest);
                        return(true);
                    }
                }
            }
            resultingLine = new ShootLine(root, targ.Cell);
            return(false);
        }