예제 #1
0
        public static void Prefix(Verb_LaunchProjectile __instance, List <IntVec3> ___tempLeanShootSources, List <IntVec3> ___tempDestList, LocalTargetInfo ___currentTarget, ref bool __result)
        {
            //ZLogger.Message("__instance.caster: " + __instance.caster, true);
            //ZLogger.Message("__instance.caster.Map: " + __instance.caster.Map, true);
            //ZLogger.Message("__instance.caster.Map.Tile: " + __instance.caster.Map.Tile, true);
            //
            //ZLogger.Message("___currentTarget.Thing: " + ___currentTarget.Thing, true);
            //ZLogger.Message("___currentTarget.Thing?.Map: " + ___currentTarget.Thing?.Map, true);
            //ZLogger.Message("___currentTarget.Thing?.Map.Tile: " + ___currentTarget.Thing?.Map.Tile, true);

            if (__instance.caster.Map != ___currentTarget.Thing?.Map && __instance.caster.Map.Tile == ___currentTarget.Thing?.Map?.Tile)
            {
                var ind1 = ZUtils.ZTracker.GetZIndexFor(__instance.caster.Map);
                var ind2 = ZUtils.ZTracker.GetZIndexFor(___currentTarget.Thing.Map);
                if (ind1 > ind2)
                {
                    teleportBack = true;
                    targetOldMap = ___currentTarget.Thing.Map;
                    ZUtils.TeleportThing(___currentTarget.Thing, __instance.caster.Map, ___currentTarget.Thing.Position);
                    RoofAndFloorPatches.Patch_SpawnSetup.doTeleport = false;
                }
                else if (ind1 < ind2)
                {
                    teleportBack = true;
                    casterOldMap = __instance.caster.Map;
                    ZUtils.TeleportThing(__instance.caster, ___currentTarget.Thing.Map, __instance.caster.Position);
                    RoofAndFloorPatches.Patch_SpawnSetup.doTeleport = false;
                }
            }
        }
        public static void Upgradeable_Projectile_Postfix(ref Verb_LaunchProjectile __instance, ref ThingDef __result)
        {
            if (__instance.EquipmentSource != null)
            {
                if (!__instance.EquipmentSource.AllComps.NullOrEmpty())
                {
                    if (__instance.EquipmentSource.GetComp <CompUpgradeableProjectile>() != null && __instance.verbProps.defaultProjectile == __result)
                    {
                        if (__instance.EquipmentSource.GetComp <CompUpgradeableProjectile>() is CompUpgradeableProjectile upgradeableProjectile)
                        {
                            if (__instance.CasterPawn.Faction != null)
                            {
                                bool flag = upgradeableProjectile.researchDef != null;
                                if (flag)
                                {
                                    if (__instance.CasterPawn.Faction == Faction.OfPlayer && upgradeableProjectile.researchDef.IsFinished)
                                    {
                                        __result = upgradeableProjectile.projectileDef;
                                        return;
                                    }
                                }
                                else
                                {
                                    if (upgradeableProjectile.factionDefs.Contains(__instance.CasterPawn.Faction.def))
                                    {
                                        __result = upgradeableProjectile.projectileDef;
                                        return;
                                    }
                                }
                            }
                        }
                    }

                    /*
                     * if (__instance.EquipmentSource.GetComp<CompSlotLoadable.CompSlotLoadable>() != null && __instance.verbProps.defaultProjectile == __result)
                     * {
                     *  Log.Message(string.Format("{0} CompSlotLoadable != null", __instance.EquipmentSource));
                     *  if (__instance.EquipmentSource.GetComp<CompSlotLoadable.CompSlotLoadable>() is CompSlotLoadable.CompSlotLoadable slotLoadable)
                     *  {
                     *      if (!slotLoadable.Slots.NullOrEmpty())
                     *      {
                     *          Log.Message(string.Format("{0} Slots, Occupied: {1} Empty: {2}, Total: {3}", __instance.EquipmentSource, slotLoadable.Slots.FindAll(x => x.SlotOccupant != null).Count, slotLoadable.Slots.FindAll(x => x.SlotOccupant == null).Count, slotLoadable.Slots.Count));
                     *          foreach (CompSlotLoadable.SlotLoadable slot in slotLoadable.Slots.FindAll(x => x.SlotOccupant != null))
                     *          {
                     *              CompSlotLoadable.CompSlottedBonus slottedBonus = slot.SlotOccupant.TryGetComp<CompSlotLoadable.CompSlottedBonus>();
                     *              Log.Message(string.Format("{0}'s Slot at {1} with: {2} slottedBonus: {3}", __instance.EquipmentSource, slotLoadable.Slots.IndexOf(slot), slot.SlotOccupant, slottedBonus!=null));
                     *              if (slottedBonus != null)
                     *              {
                     *                  Log.Message(string.Format("{0} slottedBonus: {1}", __instance.EquipmentSource, slottedBonus));
                     *                  __result = slottedBonus.Props.projectileReplacer;
                     *                  break;
                     *              }
                     *          }
                     *      }
                     *  }
                     * }
                     */
                }
            }
        }
예제 #3
0
        /*[HarmonyPatch(typeof(Verb_LaunchProjectile), "HighlightFieldRadiusAroundTarget")]
         * static class Harmony_Verb_LaunchProjectile_HighlightFieldRadiusAroundTarget
         * {
         *  static bool Prefix(ref float __result, Verb_LaunchProjectile __instance, LocalTargetInfo ___currentTarget, out bool needLOSToCenter)
         *  {
         *      if (__instance.verbProps.forcedMissRadius < 0.5f || __instance.verbProps.requireLineOfSight)
         *      {
         *          // Assuming this is not a mortar-like thing
         *          // Perform vanilla logic
         *          needLOSToCenter = true;
         *          return true;
         *      }
         *      if (!Settings.showAccuracyRadius)
         *      {
         *          needLOSToCenter = true;
         *          return true;
         *      }
         *      else
         *      {
         *          needLOSToCenter = false;
         *
         *          float missRadius = GetAdjustedForcedMissRadius(__instance, ___currentTarget);
         *          if (missRadius < 1)
         *          {
         *              missRadius = 1f;
         *          }
         *          __result = missRadius;
         *
         *          // Skip normal execution, we will draw our own overlay
         *          return false;
         *      }
         *  }
         * }*/

        static float GetAdjustedForcedMissRadius(Verb_LaunchProjectile shootVerb, LocalTargetInfo ___currentTarget)
        {
            if (shootVerb.verbProps.forcedMissRadius < 0.5f || shootVerb.verbProps.requireLineOfSight)
            {
                return(0);
            }
            else
            {
                Pawn         shooterPawn  = null;
                CompMannable compMannable = shootVerb.caster.TryGetComp <CompMannable>();
                if (compMannable != null && compMannable.ManningPawn != null)
                {
                    shooterPawn = compMannable.ManningPawn;
                }
                else
                {
                    shooterPawn = shootVerb.CasterPawn;
                }
                // Grab default forced miss radius for this particular weapon
                float missRadiusForShot = shootVerb.verbProps.forcedMissRadius;
                float skillMultiplier   = 1f;
                // We want to multiply this forced miss radius by our pawn's skill modifier
                if (shooterPawn != null && shooterPawn.skills != null)
                {
                    int totalSkill    = 0;
                    int skillsTotaled = 0;
                    if (Settings.intellectualAffectsMortarAccuracy)
                    {
                        totalSkill += shooterPawn.skills.GetSkill(SkillDefOf.Intellectual).Level;
                        skillsTotaled++;
                    }
                    if (Settings.shootingAffectsMortarAccuracy)
                    {
                        totalSkill += shooterPawn.skills.GetSkill(SkillDefOf.Shooting).Level;
                        skillsTotaled++;
                    }

                    if (skillsTotaled > 0)
                    {
                        // get average skill
                        int averageSkill = (int)(((float)totalSkill) / skillsTotaled);
                        skillMultiplier = 1 - ((averageSkill - SkillRecord.MinLevel) * (Settings.maxSkillSpreadReduction - Settings.minSkillSpreadReduction) / (SkillRecord.MaxLevel - SkillRecord.MinLevel) + Settings.minSkillSpreadReduction);
                    }
                }
                // Weather should affect shot no matter what the skill is
                if (Settings.weatherAffectsMortarAccuracy)
                {
                    missRadiusForShot = (missRadiusForShot * skillMultiplier) + ((1 - shootVerb.caster.Map.weatherManager.CurWeatherAccuracyMultiplier) * missRadiusForShot);
                }
                else
                {
                    missRadiusForShot = (missRadiusForShot * skillMultiplier);
                }

                // TODO: this is wrong. __curentTarget.Cell is origin when we are hovering over it, preview is incorrect
                return(VerbUtility.CalculateAdjustedForcedMiss(missRadiusForShot, ___currentTarget.Cell - shootVerb.caster.Position));
            }
        }
            public static void Prefix(Verb_LaunchProjectile __instance)
            {
                var projectileClass = __instance.GetProjectile()?.thingClass;

                if (projectileClass != null && typeof(TeslaProjectile).IsAssignableFrom(projectileClass))
                {
                    ShotReport_HitReportFor.accuracy = true;
                }
            }
예제 #5
0
 public static bool get_Projectile_Prefix(Verb_LaunchProjectile __instance, ref ThingDef __result)
 {
     if (__instance is Verb_UseAbility)
     {
         __result = __instance.verbProps.defaultProjectile;
         return(false);
     }
     return(true);
 }
        public static void Upgradeable_Projectile_Postfix(ref Verb_LaunchProjectile __instance, ref ThingDef __result)
        {
            if (__instance.EquipmentSource != null)
            {
                if (!__instance.EquipmentSource.AllComps.NullOrEmpty())
                {
                    if (__instance.EquipmentSource.GetComp <CompUpgradeableProjectile>() != null && __instance.verbProps.defaultProjectile == __result)
                    {
                        if (__instance.EquipmentSource.GetComp <CompUpgradeableProjectile>() is CompUpgradeableProjectile upgradeableProjectile)
                        {
                            if (__instance.CasterPawn.Faction != null)
                            {
                                bool flag = upgradeableProjectile.researchDef != null;
                                if (flag)
                                {
                                    if (__instance.CasterPawn.Faction == Faction.OfPlayer && upgradeableProjectile.researchDef.IsFinished)
                                    {
                                        __result = upgradeableProjectile.projectileDef;
                                        return;
                                    }
                                }
                                else
                                {
                                    if (upgradeableProjectile.factionDefs.Contains(__instance.CasterPawn.Faction.def))
                                    {
                                        __result = upgradeableProjectile.projectileDef;
                                        return;
                                    }
                                }
                            }
                        }
                    }

                    if (__instance.EquipmentSource.GetComp <CompSlotLoadable.CompSlotLoadable>() != null && __instance.verbProps.defaultProjectile == __result)
                    {
                        if (__instance.EquipmentSource.GetComp <CompSlotLoadable.CompSlotLoadable>() is CompSlotLoadable.CompSlotLoadable slotLoadable)
                        {
                            if (!slotLoadable.Slots.NullOrEmpty())
                            {
                                foreach (CompSlotLoadable.SlotLoadable slot in slotLoadable.Slots.FindAll(x => x.SlotOccupant != null))
                                {
                                    CompSlotLoadable.CompSlottedBonus slottedBonus = slot.SlotOccupant.TryGetComp <CompSlotLoadable.CompSlottedBonus>();
                                    if (slottedBonus != null)
                                    {
                                        __result = slottedBonus.Props.projectileReplacer;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
예제 #7
0
 private static void Postfix(ref bool __result, Verb_LaunchProjectile __instance)
 {
     if (__instance is Verb_Shoot verb)
     {
         var comp = verb.EquipmentSource?.GetComp <CompGunWithMagazines>();
         if (__result && comp?.Enabled is true)
         {
             __result = comp.CurrentAmmo > 0;
         }
     }
 }
        internal static string ShotCalculationTipString(Thing target)
        {
            StringBuilder stringBuilder = new StringBuilder();

            if (Find.Selector.SingleSelectedThing != null)
            {
                Pawn pawn = Find.Selector.SingleSelectedThing as Pawn;
                if (pawn != null && pawn != target && pawn.equipment != null && pawn.equipment.Primary != null)
                {
                    Verb_LaunchProjectile verb_LaunchProjectile = pawn.equipment.PrimaryEq.PrimaryVerb as Verb_LaunchProjectile;
                    if (verb_LaunchProjectile != null)
                    {
                        stringBuilder.AppendLine();
                        stringBuilder.Append("ShotBy".Translate(new object[]
                        {
                            pawn.LabelBaseShort
                        }) + ":");
                        if (verb_LaunchProjectile.CanHitTarget(target))
                        {
                            HitReport hitReport = verb_LaunchProjectile.HitReportFor(target);
                            stringBuilder.Append(hitReport.GetTextReadout());
                        }
                        else
                        {
                            stringBuilder.Append("CannotHit".Translate());
                        }
                    }
                    // Append CR tooltip
                    else
                    {
                        Verb_LaunchProjectileCR verbCR = pawn.equipment.PrimaryEq.PrimaryVerb as Verb_LaunchProjectileCR;
                        if (verbCR != null)
                        {
                            stringBuilder.AppendLine();
                            stringBuilder.Append("ShotBy".Translate(new object[] { pawn.LabelBaseShort }) + ":\n");
                            if (verbCR.CanHitTarget(target))
                            {
                                ShiftVecReport report = verbCR.ShiftVecReportFor(target);
                                stringBuilder.Append(report.GetTextReadout());
                            }
                            else
                            {
                                stringBuilder.Append("CannotHit".Translate());
                            }
                        }
                    }
                }
            }
            return(stringBuilder.ToString());
        }
예제 #9
0
 public static bool WarmupComplete_Ranged_PreFix(Verb_LaunchProjectile __instance)
 {
     if (Utility.Eligable(__instance) && SettingsHelper.LatestVersion.NeedAmmo)
     {
         if (__instance.CasterPawn.IsColonistPlayerControlled)
         {
             return(!Utility.TryFire(__instance, out ThingDef thing));
         }
         else if (SettingsHelper.LatestVersion.NPCNeedAmmo)
         {
             return(!Utility.TryFire(__instance, out ThingDef thing));
         }
     }
     return(true);
 }
예제 #10
0
 public static void Postfix(Verb_LaunchProjectile __instance, List <IntVec3> ___tempLeanShootSources, List <IntVec3> ___tempDestList, LocalTargetInfo ___currentTarget, ref bool __result)
 {
     if (teleportBack)
     {
         if (targetOldMap != null)
         {
             ZUtils.TeleportThing(___currentTarget.Thing, targetOldMap, ___currentTarget.Thing.Position);
             targetOldMap = null;
             RoofAndFloorPatches.Patch_SpawnSetup.doTeleport = true;
         }
         else if (casterOldMap != null)
         {
             ZUtils.TeleportThing(__instance.caster, casterOldMap, __instance.caster.Position);
             casterOldMap = null;
             RoofAndFloorPatches.Patch_SpawnSetup.doTeleport = true;
         }
     }
 }
예제 #11
0
        public static Vector3 MuzzlePosition(Vector3 DrawPos, Verb_LaunchProjectile instance, Thing equipment, Thing launcher)
        {
            Vector3 result = DrawPos;

            if (equipment == null || !AMAMod.settings.AllowMuzzlePosition)
            {
                return(result);
            }
            Vector3 destination = instance.CurrentTarget.Cell.ToVector3Shifted();
            float   aimAngle    = 0f;

            if ((destination - result).MagnitudeHorizontalSquared() > 0.001f)
            {
                aimAngle = (destination - result).AngleFlat();
            }
            IDrawnWeaponWithRotation rotation = equipment as IDrawnWeaponWithRotation;

            if (rotation != null)
            {
                //    Log.Message(gunOG + " is IDrawnWeaponWithRotation with RotationOffset: "+ gunOG.RotationOffset);
                aimAngle += rotation.RotationOffset;
            }
            if (equipment.def.HasComp(typeof(OgsCompOversizedWeapon.CompOversizedWeapon)))
            {
                OgsCompOversizedWeapon.CompOversizedWeapon compOversized = equipment.TryGetCompFast <OgsCompOversizedWeapon.CompOversizedWeapon>();
                if (compOversized != null)
                {
                    bool    DualWeapon     = compOversized.Props != null && compOversized.Props.isDualWeapon;
                    Vector3 offsetMainHand = default(Vector3);
                    Vector3 offsetOffHand  = default(Vector3);
                    float   offHandAngle   = aimAngle;
                    float   mainHandAngle  = aimAngle;

                    OversizedUtil.SetAnglesAndOffsets(equipment, equipment as ThingWithComps, aimAngle, launcher, ref offsetMainHand, ref offsetOffHand, ref offHandAngle, ref mainHandAngle, true, DualWeapon && !compOversized.FirstAttack);
                    Vector3 vector = DualWeapon && !compOversized.FirstAttack ? offsetOffHand : offsetMainHand;
                    //    Vector3 vector = compOversized.AdjustRenderOffsetFromDir(equippable.PrimaryVerb.CasterPawn, !compOversized.FirstAttack);
                    result += vector;
                }
            }
            result = equipment.MuzzlePositionFor(result, aimAngle);
            return(result);
        }
예제 #12
0
        // RimWorld.Verb_MeleeAttack
        public static void get_Projectile_PostFix(Verb_LaunchProjectile __instance, ref ThingDef __result)
        {
            //__result = null;
            var EquipmentSource = __instance.EquipmentSource;

            if (EquipmentSource != null)
            {
                //Log.Message("1");
                var comp = EquipmentSource.AllComps.FirstOrDefault(x => x is OgsCompSlotLoadable.CompSlotLoadable);
                if (comp != null)
                {
                    //Log.Message("2");
                    var compSlotLoadable = comp as OgsCompSlotLoadable.CompSlotLoadable;
                    if (compSlotLoadable.Slots != null && compSlotLoadable.Slots.Count > 0)
                    {
                        //Log.Message("3");
                        var statSlots = compSlotLoadable.Slots.FindAll(z =>
                                                                       !z.IsEmpty() && ((OgsCompSlotLoadable.SlotLoadableDef)z.def).doesChangeStats);
                        if (statSlots != null && statSlots.Count > 0)
                        {
                            foreach (var slot in statSlots)
                            {
                                //Log.Message("5");
                                var slotBonus = slot.SlotOccupant.def.GetModExtension <SlottedBonusExtension>();
                                if (slotBonus != null)
                                {
                                    //Log.Message("6");
                                    var superClass = __instance.GetType().BaseType;
                                    if (slotBonus.projectileReplacer != null)
                                    {
                                        __result = slotBonus.projectileReplacer;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
예제 #13
0
 static void Postfix(Verb_LaunchProjectile __instance)
 {
     __instance.EquipmentSource?.BroadcastCompSignal("FiredShot");
 }
예제 #14
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);
            }
예제 #15
0
        public static bool Patch_Verb_LaunchProjectile_GetProjectile(ref ThingDef __result, Verb_LaunchProjectile __instance)
        {
            if (__instance.EquipmentSource != null)
            {
                SocketComp comp = __instance.EquipmentSource.GetComp <SocketComp>();
                if (comp != null && comp.SocketedRunes.FirstOrDefault(runeComp => runeComp.RuneProps.replacedProjectile != null) is RuneComp rune)
                {
                    __result = rune.RuneProps.replacedProjectile;
                    return(false);
                }
            }

            return(true);
        }
예제 #16
0
        public static float CalculateAdjustedForcedMiss(float forcedMiss, IntVec3 vector, Verb_LaunchProjectile instance)
        {
            float num = (float)vector.LengthHorizontalSquared;

            if (num < instance.verbProps.range * 0.25f)
            {
                return(0f);
            }
            if (num < instance.verbProps.range * 0.5f)
            {
                return(forcedMiss * 0.5f);
            }
            if (num < instance.verbProps.range * 0.75f)
            {
                return(forcedMiss * 0.8f);
            }
            return(forcedMiss);
        }
예제 #17
0
 static void Prefix(Verb_LaunchProjectile __instance)
 {
     __instance.EquipmentSource?.BroadcastCompSignal("AboutToFireShot");
 }
예제 #18
0
        public static void ExtraProjectiles(Projectile projectile2, Thing launcher, Vector3 origin, LocalTargetInfo usedTarget, LocalTargetInfo intendedTarget, ProjectileHitFlags hitFlags, bool preventFriendlyFire, 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, preventFriendlyFire, 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, preventFriendlyFire, equipment, targetCoverDef);
                }
            }
        }
 public static void HighlightFieldRadiusAroundTarget_CustomExplosiveProjectile_Postfix(ref Verb_LaunchProjectile __instance, ref float __result)
 {
     if (__instance.Projectile != null)
     {
         if (__instance.Projectile.thingClass == typeof(Projectile_ExplosiveOG))
         {
             ThingDef_BulletExplosiveOG bulletExplosiveOG = (ThingDef_BulletExplosiveOG)__instance.Projectile;
             if (bulletExplosiveOG.explosionradius != 0)
             {
                 __result = bulletExplosiveOG.explosionradius;
             }
         }
     }
 }