Esempio n. 1
0
 public static bool Prefix(ref GimbalAimer __instance, out float __state)
 {
     __state = __instance.aimClampMaxPercent;
     if (WeaponAimSettings.OctantAim)
     {
         __instance.aimClampMaxPercent = Mathf.Min(0.10f, __instance.aimClampMaxPercent);
     }
     return(true);
 }
Esempio n. 2
0
 public static void Postfix(ref GimbalAimer __instance, float __state)
 {
     __instance.aimClampMaxPercent = __state;
 }
Esempio n. 3
0
        public Visible GetFirstVisibleTechIsEnemy(int[] octants, Limits limits, TankBlock block, GimbalAimer XGimbal, GimbalAimer YGimbal, Func <Vector3, Vector3> aimDelegate)
        {
            Visible overallBest = null;

            bool hasX = limits.XConstraints[0] != limits.XConstraints[1];
            bool hasY = limits.YConstraints[0] != limits.YConstraints[1];

            List <int> sortedOctantId = new List <int>();

            int[] indices = new int[octants.Length];
            for (int i = 0; i < octants.Length; i++)
            {
                indices[i] = 0;
                if (this.m_Visibles[octants[i]].Count > 0)
                {
                    sortedOctantId.Add(i);
                }
            }
            sortedOctantId.Sort((int a, int b) => (int)(this.m_Visibles[octants[a]][indices[a]].distSq * 1000f - this.m_Visibles[octants[b]][indices[b]].distSq * 1000f));

            // Continuously keep a sorted list of visibles to go through
            while (sortedOctantId.Count > 0)
            {
                int currentOctantId = sortedOctantId[0];
                sortedOctantId.RemoveAt(0);

                int octant = octants[currentOctantId];
                int index  = indices[currentOctantId];

                // Check if targetable. If it is, then return it
                Visible.ConeFiltered filteredVisible = this.m_Visibles[octant][index];
                if (filteredVisible.visible != null)
                {
                    Visible visible = filteredVisible.visible;
                    Tank    tank    = filteredVisible.visible.tank;

                    bool    canAim      = true;
                    Vector3 targetWorld = tank.transform.position;
                    if (aimDelegate != null)
                    {
                        targetWorld = aimDelegate(targetWorld);
                    }

                    float leeway = Mathf.Max(5.0f, (float)Math.Atan2(tank.blockBounds.size.magnitude / 2, (targetWorld - block.transform.position).magnitude) * Mathf.Rad2Deg);
                    float YAngle = 0f, XAngle = 0f;
                    if (hasY && YGimbal)
                    {
                        Vector3 targetRelative = YGimbal.transform.parent.InverseTransformDirection(targetWorld - YGimbal.transform.position);
                        YAngle = Mathf.Atan2(targetRelative.x, targetRelative.z) * Mathf.Rad2Deg;
                        canAim = YAngle >= limits.YConstraints[0] - leeway && YAngle <= limits.YConstraints[1] + leeway;
                    }
                    if (canAim && hasX && XGimbal)
                    {
                        Vector3 targetRelative = XGimbal.transform.parent.InverseTransformDirection(targetWorld - XGimbal.transform.position);
                        XAngle = Mathf.Atan2(-targetRelative.y, targetRelative.z) * Mathf.Rad2Deg;
                        canAim = XAngle >= limits.XConstraints[0] - leeway && XAngle <= limits.XConstraints[1] + leeway;
                    }

                    if (canAim)
                    {
                        RaycastHit raycastHit;
                        float      length         = Mathf.Max(block.tank.blockBounds.size.magnitude, 1f);
                        Vector3    barrelRelative = limits.localToBarrel + limits.localToGimbal + limits.localToBlock;

                        Vector3 ray = (targetWorld - block.transform.position).normalized;

                        if (!Physics.Raycast(block.transform.position + (ray * barrelRelative.magnitude), ray, out raycastHit, length, Globals.inst.layerTank.mask, QueryTriggerInteraction.Ignore) || raycastHit.rigidbody != block.tank.rbody)
                        {
                            float sqrMagnitude = (base.Tech.trans.position - tank.trans.position).sqrMagnitude;
                            return(visible);
                        }
                    }
                }

                indices[currentOctantId]++;
                // If stuff left in visibles, add to sorted list
                if (this.m_Visibles[octant].Count > index + 1)
                {
                    int sortIndex = sortedOctantId.BinarySearch(currentOctantId, (int a, int b) => (int)(this.m_Visibles[octants[a]][indices[a]].distSq * 1000f - this.m_Visibles[octants[b]][indices[b]].distSq * 1000f));
                    if (sortIndex < 0)
                    {
                        sortIndex = ~sortIndex;
                    }
                    sortedOctantId.Insert(sortIndex, currentOctantId);
                }
            }
            return(overallBest);
        }
Esempio n. 4
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);
        }
Esempio n. 5
0
        public static int[] GetOctants(Limits limits, GimbalAimer parentGimbal, TankBlock block)
        {
            Vector3 up      = block.transform.up;
            Vector3 forward = block.transform.forward;

            if (parentGimbal)
            {
                Quaternion localRotation   = (Quaternion)restingOrientation.GetValue(parentGimbal);
                Quaternion currentRotation = parentGimbal.transform.localRotation;
                Quaternion reverseCurrent  = Quaternion.Inverse(currentRotation);
                up      = (reverseCurrent * parentGimbal.transform.up);
                forward = (reverseCurrent * parentGimbal.transform.forward);
            }

            Transform tankTransform = block.tank.transform;

            float rightTest = up.Dot(tankTransform.right);
            float frontTest = up.Dot(tankTransform.forward);
            float topTest   = up.Dot(tankTransform.up);

            float xTest, yTest;

            int[] leftPair;
            int[] rightPair;

            int[] topQuad;
            int[] bottomQuad;

            if (rightTest > 0.5) // On the right
            {
                xTest = forward.Dot(tankTransform.forward);
                yTest = forward.Dot(tankTransform.up);

                topQuad = new int[4] {
                    4, 5, 6, 7
                };
                bottomQuad = new int[4] {
                    0, 1, 2, 3
                };

                if (xTest > 0.5) // right
                {
                    DebugPrint(block, $"{block.name} ON RIGHT FACING RIGHT");
                    leftPair = new int[2] {
                        2, 6
                    };
                    rightPair = new int[2] {
                        0, 4
                    };
                }
                else if (yTest > 0.5) // up
                {
                    DebugPrint(block, $"{block.name} ON RIGHT FACING FRONT");
                    leftPair = new int[2] {
                        0, 4
                    };
                    rightPair = new int[2] {
                        1, 5
                    };
                }
                else if (xTest < -0.5) // left
                {
                    DebugPrint(block, $"{block.name} ON RIGHT FACING LEFT");
                    leftPair = new int[2] {
                        1, 5
                    };
                    rightPair = new int[2] {
                        3, 7
                    };
                }
                else // down
                {
                    DebugPrint(block, $"{block.name} ON RIGHT FACING BACK");
                    leftPair = new int[2] {
                        3, 7
                    };
                    rightPair = new int[2] {
                        2, 6
                    };
                }
            }
            else if (rightTest < -0.5) // On the left
            {
                xTest = -forward.Dot(tankTransform.forward);
                yTest = forward.Dot(tankTransform.up);

                bottomQuad = new int[4] {
                    4, 5, 6, 7
                };
                topQuad = new int[4] {
                    0, 1, 2, 3
                };

                if (xTest > 0.5) // right
                {
                    DebugPrint(block, $"{block.name} ON LEFT FACING RIGHT");
                    rightPair = new int[2] {
                        2, 6
                    };
                    leftPair = new int[2] {
                        0, 4
                    };
                }
                else if (yTest > 0.5) // up
                {
                    DebugPrint(block, $"{block.name} ON LEFT FACING FRONT");
                    rightPair = new int[2] {
                        0, 4
                    };
                    leftPair = new int[2] {
                        1, 5
                    };
                }
                else if (xTest < -0.5) // left
                {
                    DebugPrint(block, $"{block.name} ON LEFT FACING LEFT");
                    rightPair = new int[2] {
                        1, 5
                    };
                    leftPair = new int[2] {
                        3, 7
                    };
                }
                else // down
                {
                    DebugPrint(block, $"{block.name} ON LEFT FACING BACK");
                    rightPair = new int[2] {
                        3, 7
                    };
                    leftPair = new int[2] {
                        2, 6
                    };
                }
            }
            else if (frontTest > 0.5) // On the front
            {
                xTest = forward.Dot(tankTransform.right);
                yTest = forward.Dot(tankTransform.up);

                topQuad = new int[4] {
                    1, 3, 5, 7
                };
                bottomQuad = new int[4] {
                    0, 2, 4, 6
                };

                if (xTest > 0.5) // right
                {
                    DebugPrint(block, $"{block.name} ON FRONT FACING RIGHT");
                    leftPair = new int[2] {
                        6, 7
                    };
                    rightPair = new int[2] {
                        4, 5
                    };
                }
                else if (yTest > 0.5) // up
                {
                    DebugPrint(block, $"{block.name} ON FRONT FACING FRONT");
                    leftPair = new int[2] {
                        4, 5
                    };
                    rightPair = new int[2] {
                        0, 1
                    };
                }
                else if (xTest < -0.5) // left
                {
                    DebugPrint(block, $"{block.name} ON FRONT FACING LEFT");
                    leftPair = new int[2] {
                        0, 1
                    };
                    rightPair = new int[2] {
                        2, 3
                    };
                }
                else // down
                {
                    DebugPrint(block, $"{block.name} ON FRONT FACING BACK");
                    leftPair = new int[2] {
                        2, 3
                    };
                    rightPair = new int[2] {
                        6, 7
                    };
                }
            }
            else if (frontTest < -0.5) // On the back
            {
                xTest = -forward.Dot(tankTransform.right);
                yTest = forward.Dot(tankTransform.up);

                bottomQuad = new int[4] {
                    1, 3, 5, 7
                };
                topQuad = new int[4] {
                    0, 2, 4, 6
                };

                if (xTest > 0.5) // right
                {
                    DebugPrint(block, $"{block.name} ON BACK FACING RIGHT");
                    rightPair = new int[2] {
                        6, 7
                    };
                    leftPair = new int[2] {
                        4, 5
                    };
                }
                else if (yTest > 0.5) // up
                {
                    DebugPrint(block, $"{block.name} ON BACK FACING FRONT");
                    rightPair = new int[2] {
                        4, 5
                    };
                    leftPair = new int[2] {
                        0, 1
                    };
                }
                else if (xTest < -0.5) // left
                {
                    DebugPrint(block, $"{block.name} ON BACK FACING LEFT");
                    rightPair = new int[2] {
                        0, 1
                    };
                    leftPair = new int[2] {
                        2, 3
                    };
                }
                else // down
                {
                    DebugPrint(block, $"{block.name} ON BACK FACING BACK");
                    rightPair = new int[2] {
                        2, 3
                    };
                    leftPair = new int[2] {
                        6, 7
                    };
                }
            }
            else if (topTest > 0.5) // On the top
            {
                xTest      = forward.Dot(tankTransform.right);
                yTest      = forward.Dot(tankTransform.forward);
                bottomQuad = new int[4] {
                    0, 1, 4, 5
                };
                topQuad = new int[4] {
                    2, 3, 6, 7
                };

                if (xTest > 0.5) // right
                {
                    DebugPrint(block, $"{block.name} ON TOP FACING RIGHT");
                    leftPair = new int[2] {
                        3, 1
                    };
                    rightPair = new int[2] {
                        2, 0
                    };
                }
                else if (yTest > 0.5) // up
                {
                    DebugPrint(block, $"{block.name} ON TOP FACING FRONT");
                    leftPair = new int[2] {
                        2, 0
                    };
                    rightPair = new int[2] {
                        6, 4
                    };
                }
                else if (xTest < -0.5) // left
                {
                    DebugPrint(block, $"{block.name} ON TOP FACING LEFT");
                    leftPair = new int[2] {
                        6, 4
                    };
                    rightPair = new int[2] {
                        7, 5
                    };
                }
                else // down
                {
                    DebugPrint(block, $"{block.name} ON TOP FACING BACK");
                    leftPair = new int[2] {
                        7, 5
                    };
                    rightPair = new int[2] {
                        3, 1
                    };
                }
            }
            else // On the bottom
            {
                xTest   = -forward.Dot(tankTransform.right);
                yTest   = forward.Dot(tankTransform.forward);
                topQuad = new int[4] {
                    0, 1, 4, 5
                };
                bottomQuad = new int[4] {
                    2, 3, 6, 7
                };

                if (xTest > 0.5) // right
                {
                    DebugPrint(block, $"{block.name} ON BOTTOM FACING RIGHT");
                    rightPair = new int[2] {
                        3, 1
                    };
                    leftPair = new int[2] {
                        2, 0
                    };
                }
                else if (yTest > 0.5) // up
                {
                    DebugPrint(block, $"{block.name} ON BOTTOM FACING FRONT");
                    rightPair = new int[2] {
                        2, 0
                    };
                    leftPair = new int[2] {
                        6, 4
                    };
                }
                else if (xTest < -0.5) // left
                {
                    DebugPrint(block, $"{block.name} ON BOTTOM FACING LEFT");
                    rightPair = new int[2] {
                        6, 4
                    };
                    leftPair = new int[2] {
                        7, 5
                    };
                }
                else // down
                {
                    DebugPrint(block, $"{block.name} ON BOTTOM FACING BACK");
                    rightPair = new int[2] {
                        7, 5
                    };
                    leftPair = new int[2] {
                        3, 1
                    };
                }
            }

            List <int> octants = new List <int>()
            {
                0, 1, 2, 3, 4, 5, 6, 7
            };

            if (limits.YConstraints[0] != limits.YConstraints[1])
            {
                if (limits.YConstraints[0] >= -90)
                {
                    foreach (int octant in leftPair)
                    {
                        octants.Remove(octant);
                    }
                }
                if (limits.YConstraints[1] <= 90)
                {
                    foreach (int octant in rightPair)
                    {
                        octants.Remove(octant);
                    }
                }
            }
            if (limits.XConstraints[0] != limits.XConstraints[1])
            {
                if (limits.XConstraints[0] >= 0)
                {
                    foreach (int octant in bottomQuad)
                    {
                        octants.Remove(octant);
                    }
                }
                if (limits.XConstraints[1] <= 0)
                {
                    foreach (int octant in topQuad)
                    {
                        octants.Remove(octant);
                    }
                }
            }

            return(octants.ToArray());
        }