private ushort GetClosestTarget(ushort hearseID, ref HashSet <ushort> targets, bool immediateOnly, SearchDirection immediateDirection)
        {
            Vehicle hearse = Singleton <VehicleManager> .instance.m_vehicles.m_buffer[hearseID];

            Building[] buildings = Singleton <BuildingManager> .instance.m_buildings.m_buffer;

            List <ushort> removals = new List <ushort>();

            ushort target = hearse.m_targetBuilding;

            if (_master.ContainsKey(target) && _master[target].IsValid && _master[target].Hearse != hearseID)
            {
                target = 0;
            }

            bool  targetProblematic = false;
            float distance          = float.PositiveInfinity;

            Vector3 velocity = hearse.GetLastFrameVelocity();
            Vector3 position = hearse.GetLastFramePosition();

            double bearing = double.PositiveInfinity;
            double facing  = Math.Atan2(velocity.z, velocity.x);

            if (targets.Contains(target))
            {
                if (!SkylinesOverwatch.Data.Instance.IsBuildingWithDead(target))
                {
                    removals.Add(target);
                    target = 0;
                }
                else
                {
                    targetProblematic = (buildings[target].m_problems & Notification.Problem.Death) != Notification.Problem.None;

                    Vector3 a = buildings[target].m_position;

                    distance = (a - position).sqrMagnitude;

                    bearing = Math.Atan2(a.z - position.z, a.x - position.x);
                }
            }
            else if (!immediateOnly)
            {
                target = 0;
            }

            foreach (ushort id in targets)
            {
                if (target == id)
                {
                    continue;
                }

                if (!SkylinesOverwatch.Data.Instance.IsBuildingWithDead(id))
                {
                    removals.Add(id);
                    continue;
                }

                if (_master.ContainsKey(id) && _master[id].IsValid && !_master[id].IsChallengable)
                {
                    continue;
                }

                Vector3 p = buildings[id].m_position;
                float   d = (p - position).sqrMagnitude;

                bool candidateProblematic = (buildings[id].m_problems & Notification.Problem.Death) != Notification.Problem.None;

                double angle = Helper.GetAngleDifference(facing, Math.Atan2(p.z - position.z, p.x - position.x));

                bool isImmediate = IsImmediate(d, angle, immediateDirection);

                #region debug

                string bname = Singleton <BuildingManager> .instance.GetBuildingName(id, new InstanceID { Building = id });

                string vname = Singleton <VehicleManager> .instance.GetVehicleName(hearseID);

                if (bname.Contains("##") && vname.Contains("##"))
                {
                    Helper.Instance.NotifyPlayer(String.Format("{0} :: {1} :: {2} :: {3}", d, angle, immediateDirection, isImmediate));
                }

                #endregion

                if (_master.ContainsKey(id) && _master[id].IsValid && _master[id].IsChallengable)
                {
                    if (d > distance)
                    {
                        continue;
                    }

                    if (d > _master[id].Distance)
                    {
                        continue;
                    }

                    if (!isImmediate)
                    {
                        continue;
                    }
                }
                else
                {
                    if (immediateOnly && !isImmediate)
                    {
                        continue;
                    }

                    if (targetProblematic && !candidateProblematic)
                    {
                        continue;
                    }

                    if (!targetProblematic && candidateProblematic)
                    {
                        // No additonal conditions at the moment. Problematic buildings always have priority over nonproblematic buildings
                    }
                    else
                    {
                        if (d > distance)
                        {
                            continue;
                        }

                        if (isImmediate)
                        {
                            // If it's that close, no need to further qualify its priority
                        }
                        else if (IsAlongTheWay(d, angle))
                        {
                            // If it's in the general direction the vehicle is facing, it's good enough
                        }
                        else if (!double.IsPositiveInfinity(bearing))
                        {
                            angle = Helper.GetAngleDifference(bearing, Math.Atan2(p.z - position.z, p.x - position.x));

                            if (IsAlongTheWay(d, angle))
                            {
                                // If it's in the general direction along the vehicle's target path, we will have to settle for it at this point
                            }
                            else
                            {
                                continue;
                            }
                        }
                        else
                        {
                            // If it's not closeby and not in the direction the vehicle is facing, but our vehicle also has no bearing, we will take whatever is out there
                        }
                    }
                }

                target            = id;
                targetProblematic = candidateProblematic;
                distance          = d;
            }

            foreach (ushort id in removals)
            {
                _master.Remove(id);
                targets.Remove(id);
            }

            return(target);
        }
示例#2
0
        private ushort GetClosestTarget(ushort vehicleID, ref HashSet <ushort> targets, bool immediateOnly, SearchDirection immediateDirection)
        {
            Vehicle vehicle = Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleID];

            Building[] buildings = Singleton <BuildingManager> .instance.m_buildings.m_buffer;

            List <ushort> removals = new List <ushort>();

            ushort target = vehicle.m_targetBuilding;

            if (_master.ContainsKey(target) && _master[target].IsValid && _master[target].Vehicle != vehicleID)
            {
                target = 0;
            }
            int   targetProblematicLevel = 0;
            float targetdistance         = float.PositiveInfinity;
            float distance = float.PositiveInfinity;

            Vector3 velocity = vehicle.GetLastFrameVelocity();
            Vector3 position = vehicle.GetLastFramePosition();

            double bearing = double.PositiveInfinity;
            double facing  = Math.Atan2(velocity.z, velocity.x);

            if (targets.Contains(target))
            {
                if (!Helper.IsBuildingWithDead(target))
                {
                    removals.Add(target);
                    target = 0;
                }
                else
                {
                    if ((buildings[target].m_problems & Notification.Problem.Death) != Notification.Problem.None)
                    {
                        if (Identity.ModConf.PrioritizeTargetWithRedSigns && (buildings[target].m_problems & Notification.Problem.MajorProblem) != Notification.Problem.None)
                        {
                            targetProblematicLevel = 2;
                        }
                        else
                        {
                            targetProblematicLevel = 1;
                        }
                    }

                    Vector3 a = buildings[target].m_position;

                    targetdistance = distance = (a - position).sqrMagnitude;

                    bearing = Math.Atan2(a.z - position.z, a.x - position.x);
                }
            }
            else if (!immediateOnly)
            {
                target = 0;
            }

            foreach (ushort id in targets)
            {
                if (target == id)
                {
                    continue;
                }

                if (!Helper.IsBuildingWithDead(id))
                {
                    removals.Add(id);
                    continue;
                }

                if (_master.ContainsKey(id) && _master[id].IsValid && !_master[id].IsChallengable)
                {
                    continue;
                }

                if (_master.ContainsKey(id) && _master[id].IsValid && _master[id].Vehicle != vehicleID)
                {
                    Vehicle vehicle2 = Singleton <VehicleManager> .instance.m_vehicles.m_buffer[_master[id].Vehicle];
                    if (vehicle2.m_flags.IsFlagSet(Vehicle.Flags.Spawned) && vehicle2.m_path != 0 &&
                        Singleton <PathManager> .instance.m_pathUnits.m_buffer[vehicle2.m_path].m_nextPathUnit == 0)
                    {
                        byte b = vehicle2.m_pathPositionIndex;
                        if (b == 255)
                        {
                            b = 0;
                        }
                        if ((b & 1) == 0)
                        {
                            b += 1;
                        }
                        if ((b >> 1) + 1 >= Singleton <PathManager> .instance.m_pathUnits.m_buffer[vehicle2.m_path].m_positionCount)
                        {
                            continue;
                        }
                    }
                }

                Vector3 p = buildings[id].m_position;
                float   d = (p - position).sqrMagnitude;

                int candidateProblematicLevel = 0;
                if ((buildings[id].m_problems & Notification.Problem.Death) != Notification.Problem.None)
                {
                    if (Identity.ModConf.PrioritizeTargetWithRedSigns && (buildings[id].m_problems & Notification.Problem.MajorProblem) != Notification.Problem.None)
                    {
                        candidateProblematicLevel = 2;
                    }
                    else
                    {
                        candidateProblematicLevel = 1;
                    }
                }

                if (_oldtargets.ContainsKey(vehicleID) && _oldtargets[vehicleID].Count > 5 && targetProblematicLevel >= candidateProblematicLevel)
                {
                    continue;
                }

                if (_master.ContainsKey(id) && _master[id].IsValid && _master[id].IsChallengable)
                {
                    if (targetProblematicLevel > candidateProblematicLevel)
                    {
                        continue;
                    }

                    if (d > targetdistance * 0.9)
                    {
                        continue;
                    }

                    if (d > distance)
                    {
                        continue;
                    }

                    if (d > _master[id].Distance * 0.9)
                    {
                        continue;
                    }

                    double angle = Helper.GetAngleDifference(facing, Math.Atan2(p.z - position.z, p.x - position.x));

                    int immediateLevel = GetImmediateLevel(d, angle, immediateDirection);

                    if (immediateLevel == 0)
                    {
                        continue;
                    }

                    if (_oldtargets.ContainsKey(vehicleID) && _oldtargets[vehicleID].Contains(id))
                    {
                        continue;
                    }
                }
                else
                {
                    double angle          = Helper.GetAngleDifference(facing, Math.Atan2(p.z - position.z, p.x - position.x));
                    int    immediateLevel = GetImmediateLevel(d, angle, immediateDirection);

                    if (immediateOnly && immediateLevel == 0)
                    {
                        continue;
                    }

                    if (_oldtargets.ContainsKey(vehicleID) && _oldtargets[vehicleID].Contains(id))
                    {
                        continue;
                    }

                    if (targetProblematicLevel > candidateProblematicLevel)
                    {
                        continue;
                    }

                    if (targetProblematicLevel < candidateProblematicLevel)
                    {
                        // No additonal conditions at the moment. Problematic buildings always have priority over nonproblematic buildings
                    }
                    else
                    {
                        if (d > targetdistance * 0.9)
                        {
                            continue;
                        }

                        if (d > distance)
                        {
                            continue;
                        }

                        if (immediateLevel > 0)
                        {
                            // If it's that close, no need to further qualify its priority
                        }
                        else if (IsAlongTheWay(d, angle))
                        {
                            // If it's in the general direction the vehicle is facing, it's good enough
                        }
                        else if (!double.IsPositiveInfinity(bearing))
                        {
                            if (IsAlongTheWay(d, Helper.GetAngleDifference(bearing, Math.Atan2(p.z - position.z, p.x - position.x))))
                            {
                                // If it's in the general direction along the vehicle's target path, we will have to settle for it at this point
                            }
                            else
                            {
                                continue;
                            }
                        }
                        else
                        {
                            // If it's not closeby and not in the direction the vehicle is facing, but our vehicle also has no bearing, we will take whatever is out there
                        }
                    }
                }

                target = id;
                targetProblematicLevel = candidateProblematicLevel;
                distance = d;
            }

            foreach (ushort id in removals)
            {
                _master.Remove(id);
                targets.Remove(id);
            }

            return(target);
        }