public override void calculatePositions(List <Aircraft> aircrafts, Main main)
        {
            base.calculatePositions(aircrafts, main);

            float interval = 0.05f;
            float maximum  = 4;

            for (float i = 0; i <= maximum; i += interval)
            {
                AircraftPosition position = new AircraftPosition()
                {
                    time      = positions[positions.Count - 1].time + interval,
                    latitude  = positions[positions.Count - 1].latitude,
                    longitude = positions[positions.Count - 1].longitude,
                    altitude  = (int)(positions[positions.Count - 1].altitude),
                    roll      = 0,
                    pitch     = 0,
                    yaw       = 0
                };

                int[] heights = getHeightArray();

                int intSecond         = (int)Math.Floor(i);
                int interpolateHeight = heights[intSecond] + (int)((heights[intSecond + 1] - heights[intSecond]) * (i - intSecond));
                position.radius = interpolateHeight;

                positions.Add(position);
            }
        }
Example #2
0
        public override void calculatePositions(List <Aircraft> aircrafts, Main main)
        {
            base.calculatePositions(aircrafts, main);

            AircraftPosition parentPosition = parent.getPosition(time);

            double speed   = parentPosition.tas / 216000;      // Original speed in knots. final in degrees/sec
            double speedFt = parentPosition.tas / 3600 * 1852; // Original speed in knots. final in metres/sec

            positions[0].latitude  = parentPosition.latitude;
            positions[0].longitude = parentPosition.longitude;
            positions[0].altitude  = parentPosition.altitude;

            //int timeout = 30;
            float interval = 0.1f;

            for (float i = 0; true; i += interval)
            {
                AircraftPosition position = new AircraftPosition()
                {
                    time      = positions[positions.Count - 1].time + interval,
                    latitude  = positions[positions.Count - 1].latitude + speed * interval * Math.Cos(positions[positions.Count - 1].pitch * Math.PI / 180.0f) * Math.Cos(positions[positions.Count - 1].yaw * Math.PI / 180),
                    longitude = positions[positions.Count - 1].longitude + speed * interval * Math.Cos(positions[positions.Count - 1].pitch * Math.PI / 180.0f) * Math.Sin(positions[positions.Count - 1].yaw * Math.PI / 180),
                    altitude  = (int)(positions[positions.Count - 1].altitude + (speedFt * interval * Math.Sin(positions[positions.Count - 1].pitch * Math.PI / 180.0f)) - 9.807 * i * interval),
                    roll      = 0,
                    pitch     = positions[positions.Count - 1].pitch,
                    yaw       = positions[positions.Count - 1].yaw
                };

                if (position.altitude < impactAltitude)
                {
                    position.altitude = impactAltitude;
                    positions.Add(position);

                    ExplosionEvent impactEvent = new ExplosionEvent()
                    {
                        time      = position.time,
                        latitude  = position.latitude,
                        longitude = position.longitude,
                        altitude  = impactAltitude,
                        roll      = 0,
                        pitch     = 0,
                        yaw       = 0
                    };
                    impactEvent.type = BaseEvent.TYPE_EXPLOSION;
                    impactEvent.calculatePositions(null, main);

                    parent.hits.Add(impactEvent);
                    return;
                }


                positions.Add(position);
            }
        }
Example #3
0
        public override void calculatePositions(List <Aircraft> aircrafts, Main main)
        {
            base.calculatePositions(aircrafts, main);

            double speed   = 0.4789244 / 60;
            double speedFt = 2910 * 0.3048;

            // 1.2º de pitch acima do eixo do avião

            int   timeout  = int.Parse(main.combatGunsBulletTimeout.EditValue.ToString());
            float interval = 0.1f;

            for (float i = 0; i < timeout; i += interval)
            {
                AircraftPosition position = new AircraftPosition()
                {
                    time      = positions[positions.Count - 1].time + interval,
                    latitude  = positions[positions.Count - 1].latitude + speed * interval * Math.Cos(positions[positions.Count - 1].pitch * Math.PI / 180.0f) * Math.Cos(positions[positions.Count - 1].yaw * Math.PI / 180),
                    longitude = positions[positions.Count - 1].longitude + speed * interval * Math.Cos(positions[positions.Count - 1].pitch * Math.PI / 180.0f) * Math.Sin(positions[positions.Count - 1].yaw * Math.PI / 180),
                    altitude  = (int)(positions[positions.Count - 1].altitude + (speedFt * interval * Math.Sin(positions[positions.Count - 1].pitch * Math.PI / 180.0f)) - 9.807 * i * interval),
                    roll      = 0,
                    pitch     = positions[positions.Count - 1].pitch,
                    yaw       = positions[positions.Count - 1].yaw
                };

                foreach (Aircraft aircraft in aircrafts)
                {
                    if (aircraft == parent) // Don't shoot yourself
                    {
                        continue;
                    }

                    AircraftPosition targetPosition = aircraft.getPosition(position.time);
                    double           distance       = Math.Sqrt(Math.Pow((targetPosition.longitude - position.longitude), 2) + Math.Pow(targetPosition.latitude - position.latitude, 2)) * 60 * 1852; // in metres

                    // Explode if distance < 20
                    int threshold = int.Parse(main.combatGunsTargetEffectiveRadius.EditValue.ToString());
                    if (distance < threshold)
                    {
                        aircraft.hits.Add(new BaseEvent()
                        {
                            time      = targetPosition.time,
                            latitude  = targetPosition.latitude,
                            longitude = targetPosition.longitude,
                            altitude  = targetPosition.altitude,
                            type      = TYPE_INGUN,
                            parent    = parent
                        });

                        return;
                    }
                }
                positions.Add(position);
            }
        }
Example #4
0
        public override void calculatePositions(List <Aircraft> aircrafts, Main main)
        {
            base.calculatePositions(aircrafts, main);

            float interval = 1f;

            for (float i = 0; i < int.Parse(main.combatECMTimeout.EditValue.ToString()); i += interval)
            {
                AircraftPosition position = new AircraftPosition()
                {
                    time      = positions[positions.Count - 1].time + interval,
                    latitude  = positions[positions.Count - 1].latitude,
                    longitude = positions[positions.Count - 1].longitude,
                    altitude  = (int)(positions[positions.Count - 1].altitude),
                    roll      = 0,
                    pitch     = 0,
                    yaw       = 0
                };

                positions.Add(position);
            }
        }
Example #5
0
        public Aircraft getLock(AircraftPosition selfPosition, List <Aircraft> aircrafts)
        {
            int fov = 30;

            foreach (Aircraft aircraft in aircrafts)
            {
                if (aircraft == this)
                {
                    continue;
                }

                AircraftPosition targetPosition = aircraft.getPosition(selfPosition.time);

                double yaw = Math.Atan2((targetPosition.longitude - selfPosition.longitude), (targetPosition.latitude - selfPosition.latitude)) * 180.0f / Math.PI;
                // TODO calculate pitch too

                if (Math.Abs(yaw - selfPosition.yaw) <= fov)
                {
                    return(aircraft);
                }
            }

            return(null);
        }
        public static void writeACMIFile(String path, List <Aircraft> aircrafts, Main main)
        {
            CalculateEventPositions(aircrafts, main);
            CalculateKills(aircrafts, main);

            var csv = new StringBuilder();

            csv.AppendLine("FileType=text/acmi/tacview");
            csv.AppendLine("FileVersion=2.1");
            csv.AppendLine("Author=Jean Knapp");

            // TODO set mission title
            if (main.titleEditBar.EditValue != null)
            {
                csv.AppendLine("Title=" + main.titleEditBar.EditValue.ToString());
            }

            // TODO set mission category (i.e. Close air support)
            if (main.categoryEditBar.EditValue != null)
            {
                csv.AppendLine("Category=" + main.categoryEditBar.EditValue.ToString());
            }

            // TODO set reference time
            if (main.dateEditBar.EditValue != null)
            {
                csv.AppendLine("0,ReferenceTime=" + main.dateEditBar.EditValue.ToString() + "T00:00:00Z");
            }
            else
            {
                csv.AppendLine("0,ReferenceTime=2000-01-01T00:00:00Z");
            }

            int eventId = 1;

            for (int id = 0; id < aircrafts.Count; id++)
            {
                Aircraft aircraft = aircrafts[id];

                String aircraftIdHex = (eventId).ToString("X7");
                eventId++;
                aircraft.hexId = aircraftIdHex;

                for (int i = 0; i < aircraft.positions.Count; i++)
                {
                    AircraftPosition position = aircraft.positions[i];

                    csv.AppendLine(string.Format("#{0}", position.time.ToString()));

                    // First line representing the aircraft should be complete
                    if (i == 0)
                    {
                        var newLine = string.Format("{0},T={1}|{2}|{3}|{4}|{5}|{6},Name={7},Type={8},ShortName={9},LongName={10},CallSign={11},Registration={12},Pilot={13},Group={14},Country={15},Coalition={16},Color={17},Shape={18}",
                                                    aircraftIdHex,
                                                    position.longitude.ToString(),
                                                    position.latitude.ToString(),
                                                    position.altitude.ToString(),
                                                    position.roll.ToString(),
                                                    position.pitch.ToString(),
                                                    position.yaw.ToString(),
                                                    "A-29",
                                                    "Air+FixedWing",
                                                    "A-29",
                                                    "A-29 Super Tucano",
                                                    aircraft.callSign,
                                                    aircraft.tailnumber,
                                                    aircraft.pilot,
                                                    aircraft.group,
                                                    "br",
                                                    aircraft.coalition,
                                                    aircraft.color,
                                                    "FixedWing.Tex2.obj"
                                                    );
                        csv.AppendLine(newLine);
                    }
                    else
                    {
                        var newLine = string.Format("{0},T={1}|{2}|{3}|{4}|{5}|{6},FuelWeight={7}",
                                                    aircraftIdHex,
                                                    position.longitude.ToString(),
                                                    position.latitude.ToString(),
                                                    position.altitude.ToString(),
                                                    position.roll.ToString(),
                                                    position.pitch.ToString(),
                                                    position.yaw.ToString(),
                                                    position.fuel.ToString()
                                                    );
                        csv.AppendLine(newLine);
                    }
                }

                // Events
                for (int i = 0; i < aircraft.events.Count; i++)
                {
                    BaseEvent ev = aircraft.events[i];

                    String eventIdHex = (eventId).ToString("X7");
                    eventId++;

                    for (int pos = 0; pos < ev.positions.Count; pos++)
                    {
                        AircraftPosition position = ev.positions[pos];

                        var timeLine = string.Format("#{0}",
                                                     position.time.ToString()
                                                     );
                        csv.AppendLine(timeLine);

                        if (pos == 0)
                        {
                            switch (ev.type)
                            {
                            case BaseEvent.TYPE_AIM9L:
                            {
                                var newLine = string.Format("{0},T={1}|{2}|{3}|{4}|{5}|{6},Name={7},Type={8},ShortName={9},LongName={10},Color={11},Label={12}",
                                                            eventIdHex,
                                                            position.longitude.ToString(),
                                                            position.latitude.ToString(),
                                                            position.altitude.ToString(),
                                                            position.roll.ToString(),
                                                            position.pitch.ToString(),
                                                            position.yaw.ToString(),
                                                            "AIM9L",
                                                            "Missile",
                                                            "AIM9L",
                                                            "AIM9L Sidewinder",
                                                            aircraft.color,
                                                            (position.locked != null ? "Locked on " + position.locked.pilot : (position.label != null ? position.label : "No lock"))
                                                            );
                                csv.AppendLine(newLine);
                            }
                            break;

                            case BaseEvent.TYPE_INGUN:
                            {
                                var newLine = string.Format("{0},T={1}|{2}|{3}|{4}|{5}|{6},Name={7},Type={8},ShortName={9},Color={10}",
                                                            eventIdHex,
                                                            position.longitude.ToString(),
                                                            position.latitude.ToString(),
                                                            position.altitude.ToString(),
                                                            position.roll.ToString(),
                                                            position.pitch.ToString(),
                                                            position.yaw.ToString(),
                                                            ".50cal",
                                                            "Bullet",
                                                            ".50cal",
                                                            aircraft.color
                                                            );
                                csv.AppendLine(newLine);
                            }
                            break;

                            case BaseEvent.TYPE_ECM:
                            {
                                var newLine = string.Format("{0},T={1}|{2}|{3},Type={4}",
                                                            eventIdHex,
                                                            ev.longitude.ToString(),
                                                            ev.latitude.ToString(),
                                                            ev.altitude.ToString(),
                                                            "Flare"
                                                            );
                                csv.AppendLine(newLine);

                                csv.AppendLine(string.Format("0,Event=Message|{0}|{1} used ECM",
                                                             eventIdHex,
                                                             "A-29 (" + aircraft.pilot + ")"
                                                             ));
                            }
                            break;

                            case BaseEvent.TYPE_MK82:
                            {
                                var newLine = string.Format("{0},T={1}|{2}|{3}|{4}|{5}|{6},Name={7},Type={8},ShortName={9},Color={10}",
                                                            eventIdHex,
                                                            position.longitude.ToString(),
                                                            position.latitude.ToString(),
                                                            position.altitude.ToString(),
                                                            position.roll.ToString(),
                                                            position.pitch.ToString(),
                                                            position.yaw.ToString(),
                                                            "MK-82",
                                                            "Bomb",
                                                            "MK-82",
                                                            aircraft.color
                                                            );
                                csv.AppendLine(newLine);
                            }
                            break;
                            }
                        }
                        else
                        {
                            var newLine = string.Format("{0},T={1}|{2}|{3}|{4}|{5}|{6},Label={7}",
                                                        eventIdHex,
                                                        position.longitude.ToString(),
                                                        position.latitude.ToString(),
                                                        position.altitude.ToString(),
                                                        position.roll.ToString(),
                                                        position.pitch.ToString(),
                                                        position.yaw.ToString(),
                                                        (position.locked != null ? "Locked on " + position.locked.pilot : (position.label != null ? position.label : "No lock"))
                                                        );
                            csv.AppendLine(newLine);
                        }
                    }
                    csv.AppendLine("-" + eventIdHex);
                }
            }

            // Aircraft hits
            int currentHits = 0;
            int hitTimeout  = int.Parse(main.combatHitTimeout.EditValue.ToString());
            int hitsToKill  = int.Parse(main.combatGunsHitsToKill.EditValue.ToString());

            for (int id = 0; id < aircrafts.Count; id++)
            {
                Aircraft aircraft = aircrafts[id];
                for (int i = 0; i < aircraft.hits.Count; i++)
                {
                    BaseEvent ev = aircraft.hits[i];

                    switch (ev.type)
                    {
                    case BaseEvent.TYPE_INGUN:
                    {
                        currentHits++;

                        String eventIdHex = (eventId).ToString("X7");
                        eventId++;

                        // Add hit object
                        var timeLine = string.Format("#{0}",
                                                     ev.time.ToString()
                                                     );
                        csv.AppendLine(timeLine);

                        var newLine = string.Format("{0},T={1}|{2}|{3},Type={4},Radius=2",
                                                    eventIdHex,
                                                    ev.longitude.ToString(),
                                                    ev.latitude.ToString(),
                                                    ev.altitude.ToString(),
                                                    "Explosion"
                                                    );
                        csv.AppendLine(newLine);

                        if (i >= aircraft.hits.Count - 1 || aircraft.hits[i + 1].type != BaseEvent.TYPE_INGUN || aircraft.hits[i + 1].time >= ev.time + hitTimeout)
                        {
                            csv.AppendLine(string.Format("0,Event=Message|{0}|{1} has been hit by x{2} .50cal",
                                                         aircraft.hexId,
                                                         "A-29 (" + aircraft.pilot + ")",
                                                         currentHits
                                                         ));

                            if (currentHits < hitsToKill)
                            {
                                //aircraft.deaths += 1;
                                //ev.parent.kills += 1;

                                csv.AppendLine(string.Format("0,Event=Message|{0}|{1} has been killed by {2}",
                                                             aircraft.hexId,
                                                             "A-29 (" + aircraft.pilot + ")",
                                                             "A-29 (" + ev.parent.pilot + ")"
                                                             ));
                            }

                            currentHits = 0;
                        }


                        // Kill hit object
                        timeLine = string.Format("#{0}",
                                                 (ev.time + 1).ToString()
                                                 );
                        csv.AppendLine(timeLine);

                        newLine = string.Format("-{0}",
                                                eventIdHex
                                                );
                        csv.AppendLine(newLine);
                    }
                    break;

                    case BaseEvent.TYPE_AIM9L:
                    {
                        //aircraft.deaths += 1;
                        //ev.parent.kills += 1;
                        currentHits = 0;

                        // Add hit object
                        var timeLine = string.Format("#{0}",
                                                     ev.time.ToString()
                                                     );
                        csv.AppendLine(timeLine);

                        csv.AppendLine(string.Format("0,Event=Message|{0}|{1} has been killed by {2}",
                                                     aircraft.hexId,
                                                     "A-29 (" + aircraft.pilot + ")",
                                                     "A-29 (" + ev.parent.pilot + ")"
                                                     ));
                    }
                    break;

                    case BaseEvent.TYPE_EXPLOSION:
                    {
                        String eventIdHex = (eventId).ToString("X7");
                        eventId++;

                        for (int pos = 0; pos < ev.positions.Count; pos++)
                        {
                            AircraftPosition position = ev.positions[pos];

                            var timeLine = string.Format("#{0}",
                                                         position.time.ToString()
                                                         );
                            csv.AppendLine(timeLine);

                            if (pos == 0)
                            {
                                var newLine = string.Format("{0},T={1}|{2}|{3},Type={4},Radius={5}",
                                                            eventIdHex,
                                                            ev.longitude.ToString(),
                                                            ev.latitude.ToString(),
                                                            ev.altitude.ToString(),
                                                            "Explosion",
                                                            position.radius
                                                            );
                                csv.AppendLine(newLine);

                                csv.AppendLine(string.Format("0,Event=Message|{0}|Explosion!",
                                                             eventIdHex,
                                                             "A-29 (" + aircraft.pilot + ")"
                                                             ));
                            }
                            else
                            {
                                var newLine = string.Format("{0},T={1}|{2}|{3},Radius={4}",
                                                            eventIdHex,
                                                            position.longitude.ToString(),
                                                            position.latitude.ToString(),
                                                            position.altitude.ToString(),
                                                            position.radius
                                                            );
                                csv.AppendLine(newLine);
                            }
                        }
                        csv.AppendLine("-" + eventIdHex);
                    }
                    break;
                    }
                }
            }

            // Scores
            for (int id = 0; id < aircrafts.Count; id++)
            {
                Aircraft aircraft = aircrafts[id];
                var      timeLine = string.Format("#{0}",
                                                  aircraft.positions[aircraft.positions.Count - 1].time.ToString()
                                                  );
                csv.AppendLine(timeLine);

                csv.AppendLine(string.Format("0,Event=Message|{0}|{1} score: {2} kills\\, {3} assists\\, {4} deaths",
                                             aircraft.hexId,
                                             "A-29 (" + aircraft.pilot + ")",
                                             aircraft.kills,
                                             aircraft.assists,
                                             aircraft.deaths
                                             ));
            }

            // Threats
            for (int id = 0; id < main.Threats.Count; id++)
            {
                GroundThreat threat = main.Threats[id];

                String aircraftIdHex = (eventId).ToString("X7");
                eventId++;
                threat.hexId = aircraftIdHex;

                for (int i = 0; i < threat.positions.Count; i++)
                {
                    AircraftPosition position = threat.positions[i];

                    var timeLine = string.Format("#{0}",
                                                 position.time.ToString()
                                                 );
                    csv.AppendLine(timeLine);

                    if (i == 0)
                    {
                        var newLine = string.Format("{0},T={1}|{2}|{3},Name={4},Type={5},ShortName={6},LongName={7},EngagementRange={8},Color={9}",
                                                    aircraftIdHex,
                                                    position.longitude.ToString(),
                                                    position.latitude.ToString(),
                                                    0,
                                                    (threat.Name != "" ? threat.Name : "Avoidance Area"),
                                                    "AntiAircraft",
                                                    (threat.Name != "" ? threat.Name : "AVD"),
                                                    (threat.Name != "" ? threat.Name : "Avoidance Area"),
                                                    threat.radius,
                                                    "Red"
                                                    );
                        csv.AppendLine(newLine);
                    }
                }
            }

            //after your loop
            File.WriteAllText(path, csv.ToString());

            Process fileopener = new Process();

            fileopener.StartInfo.FileName  = "explorer";
            fileopener.StartInfo.Arguments = "\"" + path + "\"";
            fileopener.Start();
        }
Example #7
0
        public override void calculatePositions(List <Aircraft> aircrafts, Main main)
        {
            base.calculatePositions(aircrafts, main);

            double speed   = 0.4629603 / 60;
            double speedFt = 2813.32 * 0.3048;

            float fov      = float.Parse(main.combatMissileFOV.EditValue.ToString());
            float interval = 0.05f;
            int   timeout  = int.Parse(main.combatMissileTimeout.EditValue.ToString());

            for (float i = 0; i < timeout; i += interval)
            {
                AircraftPosition position = new AircraftPosition()
                {
                    time      = positions[positions.Count - 1].time + interval,
                    latitude  = positions[positions.Count - 1].latitude + speed * interval * Math.Cos(positions[positions.Count - 1].pitch * Math.PI / 180.0f) * Math.Cos(positions[positions.Count - 1].yaw * Math.PI / 180),
                    longitude = positions[positions.Count - 1].longitude + speed * interval * Math.Cos(positions[positions.Count - 1].pitch * Math.PI / 180.0f) * Math.Sin(positions[positions.Count - 1].yaw * Math.PI / 180),
                    altitude  = (int)(positions[positions.Count - 1].altitude + speedFt * interval * Math.Sin(positions[positions.Count - 1].pitch * Math.PI / 180.0f)),
                    roll      = 0,
                    pitch     = positions[positions.Count - 1].pitch,
                    yaw       = positions[positions.Count - 1].yaw,
                    locked    = null
                };

                //position.label = "" + (int)position.yaw;

                bool targetLocked = false;

                foreach (Aircraft aircraft in aircrafts)
                {
                    if (aircraft == parent) // Don't shoot yourself
                    {
                        continue;
                    }

                    List <AircraftPosition> positions = new List <AircraftPosition>();

                    foreach (BaseEvent ev in aircraft.events.Where(n => n.type == BaseEvent.TYPE_ECM))
                    {
                        AircraftPosition evPosition = ev.getPosition(position.time);
                        if (evPosition != null)
                        {
                            positions.Add(evPosition);
                        }
                    }

                    AircraftPosition tPosition = aircraft.getPosition(position.time);
                    positions.Add(tPosition);

                    for (int j = 0; j < positions.Count; j++)
                    {
                        AircraftPosition targetPosition = positions[j];
                        double           yaw            = Math.Atan2((targetPosition.longitude - position.longitude), (targetPosition.latitude - position.latitude)) * 180.0f / Math.PI;
                        double           distance       = Math.Sqrt(Math.Pow((targetPosition.longitude - position.longitude), 2) + Math.Pow(targetPosition.latitude - position.latitude, 2)) * 60 * 1852; // in metres
                        double           height         = targetPosition.altitude - position.altitude;                                                                                                    // in metres

                        double d3Distance = Math.Sqrt(Math.Pow(distance, 2) + Math.Pow(height, 2));

                        // Explode if distance < 150
                        int threshold = int.Parse(main.combatMissileTriggerDistance.EditValue.ToString());
                        if (d3Distance < threshold && j == positions.Count - 1)
                        {
                            aircraft.hits.Add(new BaseEvent()
                            {
                                time      = position.time,
                                latitude  = position.latitude,
                                longitude = position.longitude,
                                altitude  = position.altitude,
                                type      = TYPE_AIM9L,
                                parent    = parent
                            });
                            return;
                        }

                        if (yaw < 0)
                        {
                            yaw += 360;
                        }

                        // TODO calculate pitch too

                        if (Math.Abs(yaw - position.yaw) <= fov / 2)
                        {
                            double pitch = Math.Atan2(height, distance) * 180 / Math.PI;
                            if (Math.Abs(pitch - position.pitch) <= fov / 2)
                            {
                                position.yaw   = yaw;
                                position.pitch = pitch;

                                if (j < positions.Count - 1)
                                {
                                    // Locked on ECM
                                    position.locked = null;
                                    position.label  = "Jammed by ECM";
                                }
                                else
                                {
                                    // Locked on aircraft
                                    position.locked = aircraft;
                                }

                                targetLocked = true;
                                break;
                            }
                        }
                    }

                    if (targetLocked)
                    {
                        break;
                    }
                }
                positions.Add(position);
            }
        }
        public static void ReadACDATFile(Aircraft aircraft, String path)
        {
            XmlDocument doc = new XmlDocument();

            doc.Load(path);

            foreach (XmlNode recordNode in doc.SelectSingleNode("AC_DATA").ChildNodes)
            {
                // Required stuff
                float time = (float)Math.Truncate(int.Parse(recordNode.SelectSingleNode("UTC").InnerText) / 10.0f) / 100.0f;    // Time is recorded in milliseconds

                XmlNode acNode    = recordNode.SelectSingleNode("AC");
                double  longitude = double.Parse(acNode.SelectSingleNode("Long").InnerText) * 180; // Longitude is recorded from -1 to 1.
                double  latitude  = double.Parse(acNode.SelectSingleNode("LAT").InnerText) * 180;  // Latitude is recorded from -0.5 to 0.5.
                int     altitude  = (int)Math.Truncate(double.Parse(acNode.SelectSingleNode("SYS_Alt").InnerText) * 0.3048);
                double  roll      = double.Parse(acNode.SelectSingleNode("Roll").InnerText);
                double  pitch     = double.Parse(acNode.SelectSingleNode("Pitch").InnerText);
                double  yaw       = double.Parse(acNode.SelectSingleNode("True_Head").InnerText);

                // Extra stuff - TODO should I remove this to load the file faster?

                double magHead  = double.Parse(acNode.SelectSingleNode("Mag_Head").InnerText);
                double trueHead = double.Parse(acNode.SelectSingleNode("True_Head").InnerText);
                int    tas      = (int)double.Parse(acNode.SelectSingleNode("TAS").InnerText);
                double mach     = double.Parse(acNode.SelectSingleNode("MACH").InnerText);
                int    fuel     = (int)(int.Parse(acNode.SelectSingleNode("Fuel").InnerText) * 0.804); // Fuel is recorded in litres
                int    msMode   = (int)(int.Parse(acNode.SelectSingleNode("MS_Mode").InnerText));
                int    acMode   = (int)(int.Parse(acNode.SelectSingleNode("AC_Mode").InnerText));

                String casStr = acNode.SelectSingleNode("CAS").InnerText;
                int    cas    = (casStr.Length > 0 ? (int)double.Parse(casStr) : 0); // CAS can be empty and throw an error

                String aoaStr = acNode.SelectSingleNode("True_AOA").InnerText;
                double aoa    = (aoaStr.Length > 0 ? double.Parse(aoaStr) : 0); // AOA can be empty and throw an error

                String aglStr = acNode.SelectSingleNode("RALT_Alt").InnerText;
                int    agl    = (aglStr.Length > 0 ? int.Parse(aglStr) : 0); // AGL can be empty and throw an error

                AircraftPosition aircraftPosition = new AircraftPosition
                {
                    // Required stuff
                    time      = time,
                    longitude = longitude,
                    latitude  = latitude,
                    altitude  = altitude,
                    roll      = roll,
                    pitch     = pitch,
                    yaw       = yaw,

                    // Extra stuff - TODO should I remove it to save space?
                    magHead  = magHead,
                    trueHead = trueHead,
                    tas      = tas,
                    cas      = cas,
                    mach     = mach,
                    aoa      = aoa,
                    fuel     = fuel,
                    agl      = agl,
                    msMode   = msMode,
                    acMode   = acMode
                };

                aircraft.positions.Add(aircraftPosition);
            }
        }
        public static void ReadEVENTSFile(Aircraft aircraft, String path, Main main)
        {
            XmlDocument doc = new XmlDocument();

            doc.Load(path);

            foreach (XmlNode acNode in doc.SelectSingleNode("EVENT").ChildNodes)
            {
                float time = (float)Math.Truncate(int.Parse(acNode.SelectSingleNode("UTC").InnerText) / 10.0f) / 100.0f;

                if (acNode.Name == "MARK")
                {
                    // TODO register marks
                    continue;
                }

                double longitude = double.Parse(acNode.SelectSingleNode("LONG").InnerText) * 180;
                double latitude  = double.Parse(acNode.SelectSingleNode("LAT").InnerText) * 180;
                int    altitude  = (int)Math.Truncate(double.Parse(acNode.SelectSingleNode("SYS_Alt").InnerText) * 0.3048);
                double roll      = double.Parse(acNode.SelectSingleNode("Roll").InnerText);
                double pitch     = double.Parse(acNode.SelectSingleNode("Pitch").InnerText);
                double yaw       = double.Parse(acNode.SelectSingleNode("True_Heading").InnerText);

                String weaponType = acNode.SelectSingleNode("Weapon_Type").InnerText;

                switch (weaponType)
                {
                case "AIM9L":
                {
                    MissileEvent aircraftEvent = new MissileEvent
                    {
                        time      = time,
                        longitude = longitude,
                        latitude  = latitude,
                        altitude  = altitude,
                        roll      = roll,
                        pitch     = pitch,
                        yaw       = yaw,
                        parent    = aircraft
                    };

                    aircraftEvent.type = BaseEvent.TYPE_AIM9L;

                    aircraft.events.Add(aircraftEvent);
                }
                break;

                case "INGUN":
                {
                    float quantity = 0;
                    if (acNode.SelectSingleNode("Quantity") != null)
                    {
                        quantity = int.Parse(acNode.SelectSingleNode("Quantity").InnerText);
                    }
                    else if (acNode.SelectSingleNode("No_of_Bullets") != null)
                    {
                        quantity = int.Parse(acNode.SelectSingleNode("No_of_Bullets").InnerText);
                    }
                    else
                    {
                        continue;
                    }

                    float rate          = 1025.0f / 60.0f; // per second;
                    float separation    = 3.93f;           // Distance between the two machineguns;
                    float focalDistance = 300;             // Distance the bullets should cross

                    for (float q = 0; q < quantity; q++)
                    {
                        float qTime = time + q / (rate * 2);

                        AircraftPosition aircraftPosition = aircraft.getPosition(qTime);

                        // TODO - I should create two separate machineguns for a more realistic ballistic calculation

                        // Center "double barrel" machinegun
                        GunsEvent aircraftEvent = new GunsEvent
                        {
                            time      = qTime,
                            longitude = aircraftPosition.longitude,
                            latitude  = aircraftPosition.latitude,
                            altitude  = aircraftPosition.altitude,
                            roll      = aircraftPosition.roll,
                            pitch     = aircraftPosition.pitch + 2.5 * Math.Cos(aircraftPosition.roll * Math.PI / 180),
                            yaw       = aircraftPosition.yaw + 2.5 * Math.Sin(aircraftPosition.roll * Math.PI / 180),
                            parent    = aircraft
                        };

                        aircraftEvent.type = BaseEvent.TYPE_INGUN;

                        aircraft.events.Add(aircraftEvent);
                    }
                }
                break;

                case "EX11":
                {
                    if (main.ecmConvertBex.Checked)
                    {
                        float quantity = 6.0f;
                        float rate     = 2.0f;      // per second;

                        for (float q = 0; q < quantity; q++)
                        {
                            float qTime = time + q / rate;

                            AircraftPosition aircraftPosition = aircraft.getPosition(qTime);

                            ECMEvent aircraftEvent = new ECMEvent
                            {
                                time      = qTime,
                                longitude = aircraftPosition.longitude,
                                latitude  = aircraftPosition.latitude,
                                altitude  = aircraftPosition.altitude,
                                roll      = aircraftPosition.roll,
                                pitch     = aircraftPosition.pitch + 2.5 * Math.Cos(aircraftPosition.roll * Math.PI / 180),
                                yaw       = aircraftPosition.yaw + 2.5 * Math.Sin(aircraftPosition.roll * Math.PI / 180),
                                parent    = aircraft
                            };

                            aircraftEvent.type = BaseEvent.TYPE_ECM;

                            aircraft.events.Add(aircraftEvent);
                        }
                    }
                }
                break;

                case "FG230":
                {
                    MK82Event aircraftEvent = new MK82Event
                    {
                        time      = time,
                        longitude = longitude,
                        latitude  = latitude,
                        altitude  = altitude,
                        roll      = roll,
                        pitch     = pitch,
                        yaw       = yaw,
                        parent    = aircraft
                    };

                    aircraftEvent.type = BaseEvent.TYPE_MK82;

                    int tas = int.Parse(acNode.SelectSingleNode("TAS").InnerText);
                    aircraftEvent.tas            = tas;
                    aircraftEvent.impactAltitude = (int)Math.Truncate(double.Parse(acNode.SelectSingleNode("Tgt_Alt").InnerText) * 0.3048);

                    aircraft.events.Add(aircraftEvent);
                }
                break;

                case "FG120":
                {
                    MK82Event aircraftEvent = new MK82Event
                    {
                        time      = time,
                        longitude = longitude,
                        latitude  = latitude,
                        altitude  = altitude,
                        roll      = roll,
                        pitch     = pitch,
                        yaw       = yaw,
                        parent    = aircraft
                    };

                    aircraftEvent.type = BaseEvent.TYPE_MK81;

                    aircraft.events.Add(aircraftEvent);
                }
                break;
                }
            }
        }