Exemplo n.º 1
0
            public static void Postfix(ref TargetAimer __instance)
            {
                try
                {
                    Visible  target   = __instance.Target;
                    FireData fireData = __instance.GetComponentInParent <FireData>();
                    if (fireData != null && __instance.HasTarget && target.IsNotNull() && !Singleton.Manager <ManPauseGame> .inst.IsPaused && ((target.type == ObjectTypes.Vehicle && target.tank.IsNotNull()) || (target.type == ObjectTypes.Block && target.block.IsNotNull())))
                    {
                        TankBlock block = (TankBlock)ProjectilePatch.m_Block.GetValue(__instance);
                        Tank      tank  = (bool)(UnityEngine.Object)block ? block.tank : (Tank)null;

                        string        name      = block ? block.name : "UNKNOWN";
                        TimedFuseData timedFuse = __instance.GetComponentInParent <TimedFuseData>();

                        bool enemyWeapon = tank == null || !ManSpawn.IsPlayerTeam(tank.Team);

                        if (((enemyWeapon && WeaponAimSettings.EnemyLead) || (!enemyWeapon && WeaponAimSettings.PlayerLead)) && !(fireData is FireDataShotgun) && fireData.m_MuzzleVelocity > 0.0f)
                        {
                            Vector3     AimPointVector = (Vector3)ProjectilePatch.m_TargetPosition.GetValue(__instance);
                            Vector3     relDist        = AimPointVector - __instance.transform.position;
                            WeaponRound bulletPrefab   = fireData.m_BulletPrefab;

                            bool useGravity = false;
                            if (bulletPrefab != null && bulletPrefab is Projectile projectile && projectile.rbody != null)
                            {
                                if (projectile is MissileProjectile missileProjectile)
                                {
                                    useGravity = missileProjectile.rbody.useGravity || WeaponAimSettings.BallisticMissile;
                                }
                                else
                                {
                                    useGravity = projectile.rbody.useGravity;
                                }
                            }

                            Rigidbody rbodyTank = __instance.GetComponentInParent <Tank>().rbody;

                            Vector3 angularToggle    = rbodyTank.angularVelocity;
                            Vector3 relativeVelocity = (__instance.Target.rbody ? __instance.Target.rbody.velocity : Vector3.zero) - (rbodyTank.velocity + angularToggle);

                            float   time = relDist.magnitude / fireData.m_MuzzleVelocity;
                            Vector3 relativeAcceleration = target.type == ObjectTypes.Vehicle ? TargetManager.GetAcceleration(target.tank) : Vector3.zero;

                            if (useGravity)
                            {
                                relativeAcceleration -= Physics.gravity;
                            }

                            float   exactTime    = BallisticEquations.SolveBallisticArc(__instance.transform.position, fireData.m_MuzzleVelocity, AimPointVector, relativeVelocity, relativeAcceleration);
                            Vector3 adjIntercept = AimPointVector + (relativeVelocity * time);
                            if (exactTime != Mathf.Infinity)
                            {
                                time         = exactTime;
                                adjIntercept = AimPointVector + (relativeVelocity * time) + ((relativeAcceleration + (useGravity ? Physics.gravity : Vector3.zero)) / 2 * time * time);
                            }

                            if (timedFuse != null)
                            {
                                timedFuse.m_FuseTime = time;
                            }

                            ProjectilePatch.m_TargetPosition.SetValue(__instance, adjIntercept);
                        }
                        // Either disabled for enemy, or is a beam weapon
                        else
                        {
                            if (timedFuse != null)
                            {
                                timedFuse.m_FuseTime = 0.0f;
                            }
                        }
                    }
                }
                catch (NullReferenceException exception)
                {
                    Console.WriteLine("[WeaponAimMod] TargetAimer.UpdateTarget PATCH FAILED");
                    Console.WriteLine(exception.Message);
                }
            }
Exemplo n.º 2
0
        public static bool Prefix(ref TargetAimer __instance, ref float rotateSpeed)
        {
            TankBlock block = (TankBlock)m_Block.GetValue(__instance);

            // Has a target
            if (WeaponAimSettings.OctantAim && block && block.tank && __instance.HasTarget)
            {
                Tank tank        = block.tank;
                bool enemyWeapon = !ManSpawn.IsPlayerTeam(tank.Team);

                if (enemyWeapon && WeaponAimSettings.EnemyLead || !enemyWeapon && WeaponAimSettings.PlayerLead)
                {
                    Vector3 targetWorld = (Vector3)m_TargetPosition.GetValue(__instance);
                    Func <Vector3, Vector3> aimDelegate = (Func <Vector3, Vector3>)AimDelegate.GetValue(__instance);
                    if (__instance.HasTarget && aimDelegate != null)
                    {
                        targetWorld = aimDelegate(targetWorld);
                    }

                    // Check if we can aim
                    List <GimbalAimer> gimbalAimers = (List <GimbalAimer>)m_GimbalAimers.GetValue(__instance);
                    bool canAim = true;
                    foreach (GimbalAimer aimer in gimbalAimers)
                    {
                        if (__instance.Target && canAim)
                        {
                            canAim = aimer.CanAim(targetWorld);
                            if (!canAim)
                            {
                                break;
                            }
                        }
                    }

                    // If we can aim, is all good - continue as normal (will do aim calculation for gimbals twice)
                    if (canAim)
                    {
                        return(true);
                    }

                    IModuleWeapon moduleWeapon = block.GetComponent <IModuleWeapon>();

                    OctantVision octantVision = tank.GetComponent <OctantVision>();
                    if (octantVision && gimbalAimers.Count > 0)
                    {
                        float[] XConstraints = new float[2];
                        float[] YConstraints = new float[2];

                        GimbalAimer XGimbal    = null;
                        GimbalAimer YGimbal    = null;
                        GimbalAimer FreeGimbal = null;

                        bool free = false;
                        foreach (GimbalAimer aimer in gimbalAimers)
                        {
                            if (aimer.rotationAxis == GimbalAimer.AxisConstraint.X)
                            {
                                XConstraints = aimer.rotationLimits;
                                XGimbal      = aimer;
                            }
                            else if (aimer.rotationAxis == GimbalAimer.AxisConstraint.Y)
                            {
                                YConstraints = aimer.rotationLimits;
                                YGimbal      = aimer;
                            }
                            else
                            {
                                FreeGimbal = aimer;
                                free       = true;
                                break;
                            }
                        }
                        int[] octants;
                        if (free)
                        {
                            octants = new int[8] {
                                0, 1, 2, 3, 4, 5, 6, 7
                            };
                            OctantVision.Limits limits = new OctantVision.Limits
                            {
                                localToBlock  = block.trans.InverseTransformPoint(FreeGimbal.transform.position),
                                localToGimbal = Vector3.zero,
                                localToBarrel = Vector3.zero,

                                XConstraints = new float[2],
                                YConstraints = new float[2]
                            };
                            Visible betterTarget = octantVision.GetFirstVisibleTechIsEnemy(octants, limits, block, null, null, aimDelegate);
                            if (betterTarget)
                            {
                                Target.SetValue(__instance, betterTarget);
                                UpdateTarget.Invoke(__instance, null);
                            }
                        }
                        else if (XGimbal || YGimbal)
                        {
                            if (moduleWeapon != null)
                            {
                                GimbalAimer parentGimbal = null;
                                GimbalAimer childGimbal  = null;
                                if (XGimbal)
                                {
                                    if (YGimbal)
                                    {
                                        if (YGimbal.transform.IsChildOf(XGimbal.transform))
                                        {
                                            parentGimbal = XGimbal;
                                            childGimbal  = YGimbal;
                                        }
                                        else
                                        {
                                            parentGimbal = YGimbal;
                                            childGimbal  = XGimbal;
                                        }
                                    }
                                    else
                                    {
                                        parentGimbal = XGimbal;
                                    }
                                }
                                else
                                {
                                    parentGimbal = YGimbal;
                                }

                                Vector3 gimbalBlockLocalPosition = block.trans.InverseTransformPoint(parentGimbal.transform.position);
                                Vector3 gimbalLocalPosition      = Vector3.zero;
                                if (parentGimbal && childGimbal)
                                {
                                    gimbalLocalPosition = parentGimbal.transform.InverseTransformPoint(childGimbal.transform.position);
                                }

                                Vector3     fireLocalPosition = Vector3.zero;
                                GimbalAimer localChildGimbal  = childGimbal ? childGimbal : parentGimbal;
                                if (moduleWeapon is ModuleWeaponGun moduleWeaponGun)
                                {
                                    CannonBarrel[] cannonBarrels = (CannonBarrel[])m_CannonBarrels.GetValue(moduleWeaponGun);
                                    foreach (CannonBarrel cannonBarrel in cannonBarrels)
                                    {
                                        fireLocalPosition += localChildGimbal.transform.InverseTransformPoint(cannonBarrel.projectileSpawnPoint.position);
                                    }
                                    fireLocalPosition /= cannonBarrels.Length;
                                }
                                else if (moduleWeapon is ModuleWeaponFlamethrower moduleWeaponFlamethrower)
                                {
                                    fireLocalPosition = localChildGimbal.transform.InverseTransformPoint(moduleWeaponFlamethrower.GetFireTransform().position);
                                }

                                OctantVision.Limits limits = new OctantVision.Limits
                                {
                                    localToBlock  = gimbalBlockLocalPosition,
                                    localToGimbal = gimbalLocalPosition,
                                    localToBarrel = fireLocalPosition,

                                    XConstraints = XConstraints,
                                    YConstraints = YConstraints
                                };
                                octants = OctantVision.GetOctants(limits, parentGimbal, block);

                                Visible betterTarget = octantVision.GetFirstVisibleTechIsEnemy(octants, limits, block, XGimbal, YGimbal, aimDelegate);
                                if (betterTarget != null)
                                {
                                    Target.SetValue(__instance, betterTarget);
                                    UpdateTarget.Invoke(__instance, null);
                                }
                            }
                        }
                    }
                }
            }
            return(true);
        }