예제 #1
0
        private void GetPresetFromXml(XmlNode node, HandlingPreset preset)
        {
            foreach (XmlNode item in node.ChildNodes)
            {
                if (item.NodeType != XmlNodeType.Element)
                {
                    continue;
                }

                string fieldName = item.Name;
                Type   fieldType = FieldType.GetFieldType(fieldName);

                XmlElement elem = (XmlElement)item;

                if (fieldType == FieldType.FloatType)
                {
                    preset.Fields[fieldName] = float.Parse(elem.GetAttribute("value"));
                }/*
                  * else if (fieldType == FieldType.IntType)
                  * {
                  * preset.Fields[fieldName] = int.Parse(elem.GetAttribute("value"));
                  * }*/
                else if (fieldType == FieldType.Vector3Type)
                {
                    float x = float.Parse(elem.GetAttribute("x"));
                    float y = float.Parse(elem.GetAttribute("y"));
                    float z = float.Parse(elem.GetAttribute("z"));
                    preset.Fields[fieldName] = new Vector3(x, y, z);
                }/*
                  * else if (fieldType == FieldType.StringType)
                  * {
                  * preset.Fields[fieldName] = elem.InnerText;
                  * }*/
            }
        }
        /// <summary>
        /// Updates the <see cref="CurrentVehicle"/> and the <see cref="CurrentPreset"/>
        /// </summary>
        /// <returns></returns>
        private async Task GetCurrentVehicle()
        {
            PlayerPed = PlayerPedId();

            if (IsPedInAnyVehicle(PlayerPed, false))
            {
                int vehicle = GetVehiclePedIsIn(PlayerPed, false);

                if (VehiclesPermissions.IsVehicleAllowed(vehicle) && GetPedInVehicleSeat(vehicle, -1) == PlayerPed && !IsEntityDead(vehicle))
                {
                    // Update current vehicle and get its preset
                    if (vehicle != CurrentVehicle)
                    {
                        CurrentVehicle = vehicle;
                        CurrentPreset  = CreateHandlingPreset(CurrentVehicle);
                        PresetChanged?.Invoke(this, EventArgs.Empty);
                    }
                }
                else
                {
                    // If current vehicle isn't a car or player isn't driving current vehicle or vehicle is dead
                    CurrentVehicle = -1;
                    CurrentPreset  = null;
                }
            }
            else
            {
                // If player isn't in any vehicle
                CurrentVehicle = -1;
                CurrentPreset  = null;
            }

            await Task.FromResult(0);
        }
        /// <summary>
        /// Updates the decorators on the <paramref name="vehicle"/> with updated values from the <paramref name="preset"/>
        /// </summary>
        /// <param name="vehicle"></param>
        private void UpdateVehicleDecorators(int vehicle, HandlingPreset preset)
        {
            if (!DoesEntityExist(vehicle))
            {
                return;
            }

            foreach (var item in preset.Fields)
            {
                string  fieldName  = item.Key;
                Type    fieldType  = HandlingInfo.FieldsInfo[fieldName].Type;
                dynamic fieldValue = item.Value;

                string  defDecorName = $"{fieldName}_def";
                dynamic defaultValue = preset.DefaultFields[fieldName];

                if (fieldType == FieldType.FloatType)
                {
                    UpdateFloatDecorator(vehicle, fieldName, fieldValue, defaultValue);
                    UpdateFloatDecorator(vehicle, defDecorName, defaultValue, fieldValue);
                }
                else if (fieldType == FieldType.IntType)
                {
                    UpdateIntDecorator(vehicle, fieldName, fieldValue, defaultValue);
                    UpdateIntDecorator(vehicle, defDecorName, defaultValue, fieldValue);
                }
                else if (fieldType == FieldType.Vector3Type)
                {
                    fieldValue   = (Vector3)fieldValue;
                    defaultValue = (Vector3)defaultValue;

                    string decorX        = $"{fieldName}_x";
                    string defDecorNameX = $"{decorX}_def";
                    string decorY        = $"{fieldName}_y";
                    string defDecorNameY = $"{decorY}_def";
                    string decorZ        = $"{fieldName}_z";
                    string defDecorNameZ = $"{decorZ}_def";

                    UpdateFloatDecorator(vehicle, decorX, fieldValue.X, defaultValue.X);
                    UpdateFloatDecorator(vehicle, defDecorNameX, defaultValue.X, fieldValue.X);

                    UpdateFloatDecorator(vehicle, decorY, fieldValue.Y, defaultValue.Y);
                    UpdateFloatDecorator(vehicle, defDecorNameY, defaultValue.Y, fieldValue.Y);

                    UpdateFloatDecorator(vehicle, decorZ, fieldValue.Z, defaultValue.Z);
                    UpdateFloatDecorator(vehicle, defDecorNameZ, defaultValue.Z, fieldValue.Z);
                }
            }
        }
예제 #4
0
        private static XmlDocument GetXmlFromPreset(HandlingPreset preset)
        {
            XmlDocument doc          = new XmlDocument();
            XmlElement  handlingItem = doc.CreateElement("Item");

            handlingItem.SetAttribute("type", "CHandlingData");

            foreach (var item in preset.Fields)
            {
                string     fieldName  = item.Key;
                dynamic    fieldValue = item.Value;
                XmlElement field      = doc.CreateElement(fieldName);

                Type fieldType = HandlingInfo.FieldsInfo[fieldName].Type;
                if (fieldType == FieldType.FloatType)
                {
                    var value = (float)fieldValue;
                    field.SetAttribute("value", value.ToString());
                }
                else if (fieldType == FieldType.IntType)
                {
                    var value = (int)fieldValue;
                    field.SetAttribute("value", value.ToString());
                }
                else if (fieldType == FieldType.Vector3Type)
                {
                    var value = (Vector3)(fieldValue);
                    field.SetAttribute("x", value.X.ToString());
                    field.SetAttribute("y", value.Y.ToString());
                    field.SetAttribute("z", value.Z.ToString());
                }
                else if (fieldType == FieldType.StringType)
                {
                    field.InnerText = fieldValue;
                }
                else
                {
                }
                handlingItem.AppendChild(field);
            }
            doc.AppendChild(handlingItem);

            return(doc);
        }
예제 #5
0
        private static bool SavePresetAsKVP(string name, HandlingPreset preset)
        {
            if (string.IsNullOrEmpty(name))
            {
                return(false);
            }

            string kvpName = $"{kvpPrefix}{name}";

            //Key already used
            if (GetResourceKvpString(kvpName) != null)
            {
                return(false);
            }

            var xml = GetXmlFromPreset(preset);

            xml["Item"].SetAttribute("presetName", name);
            SetResourceKvp(kvpName, xml.OuterXml);
            return(true);
        }
예제 #6
0
        private void ReadServerPresets(string filename = "HandlingPresets.xml")
        {
            string strings = null;

            try
            {
                strings = LoadResourceFile(ResourceName, filename);
                strings = Helpers.RemoveByteOrderMarks(strings);
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(strings);

                foreach (XmlElement node in doc["CHandlingDataMgr"]["HandlingData"].ChildNodes)
                {
                    if (node.NodeType != XmlNodeType.Element)
                    {
                        continue;
                    }

                    if (node.HasAttribute("presetName"))
                    {
                        string         name   = node.GetAttribute("presetName");
                        HandlingPreset preset = new HandlingPreset();

                        GetPresetFromXml(node, preset);
                        ServerPresets[name] = preset;
                    }
                }
                CitizenFX.Core.Debug.WriteLine($"{ScriptName}: Loaded {filename}, found {ServerPresets.Count} server presets.");
            }
            catch (Exception e)
            {
                CitizenFX.Core.Debug.WriteLine(e.Message);
                CitizenFX.Core.Debug.WriteLine(e.StackTrace);
                CitizenFX.Core.Debug.WriteLine($"{ScriptName}: Error loading {filename}");
            }
        }
예제 #7
0
        /// <summary>
        /// Creates a preset for the <paramref name="vehicle"/> to edit it locally
        /// </summary>
        /// <param name="vehicle"></param>
        /// <returns></returns>
        private HandlingPreset CreateHandlingPreset(int vehicle)
        {
            Dictionary <string, dynamic> defaultFields = new Dictionary <string, dynamic>();
            Dictionary <string, dynamic> fields        = new Dictionary <string, dynamic>();

            foreach (var item in HandlingInfo.FieldsInfo)
            {
                string fieldName    = item.Key;
                string className    = item.Value.ClassName;
                Type   fieldType    = item.Value.Type;
                string defDecorName = $"{fieldName}_def";

                if (fieldType == FieldType.FloatType)
                {
                    var defaultValue = DecorExistOn(vehicle, defDecorName) ? DecorGetFloat(vehicle, defDecorName) : GetVehicleHandlingFloat(vehicle, className, fieldName);
                    defaultFields[fieldName] = defaultValue;
                    fields[fieldName]        = DecorExistOn(vehicle, fieldName) ? DecorGetFloat(vehicle, fieldName) : defaultValue;
                }/*
                  * else if (fieldType == FieldType.IntType)
                  * {
                  * var defaultValue = DecorExistOn(vehicle, defDecorName) ? DecorGetInt(vehicle, defDecorName) : GetVehicleHandlingInt(vehicle, className, fieldName);
                  * defaultFields[fieldName] = defaultValue;
                  * fields[fieldName] = DecorExistOn(vehicle, fieldName) ? DecorGetInt(vehicle, fieldName) : defaultValue;
                  * }*/
                else if (fieldType == FieldType.Vector3Type)
                {
                    Vector3 vec = GetVehicleHandlingVector(vehicle, className, fieldName);

                    string decorX = $"{fieldName}_x";
                    string decorY = $"{fieldName}_y";
                    string decorZ = $"{fieldName}_z";

                    string defDecorNameX = $"{decorX}_def";
                    string defDecorNameY = $"{decorY}_def";
                    string defDecorNameZ = $"{decorZ}_def";

                    if (DecorExistOn(vehicle, defDecorNameX))
                    {
                        vec.X = DecorGetFloat(vehicle, defDecorNameX);
                    }
                    if (DecorExistOn(vehicle, defDecorNameY))
                    {
                        vec.Y = DecorGetFloat(vehicle, defDecorNameY);
                    }
                    if (DecorExistOn(vehicle, defDecorNameZ))
                    {
                        vec.Z = DecorGetFloat(vehicle, defDecorNameZ);
                    }

                    defaultFields[fieldName] = vec;

                    if (DecorExistOn(vehicle, decorX))
                    {
                        vec.X = DecorGetFloat(vehicle, decorX);
                    }
                    if (DecorExistOn(vehicle, decorY))
                    {
                        vec.Y = DecorGetFloat(vehicle, decorY);
                    }
                    if (DecorExistOn(vehicle, decorZ))
                    {
                        vec.Z = DecorGetFloat(vehicle, decorZ);
                    }

                    fields[fieldName] = vec;
                }
            }

            HandlingPreset preset = new HandlingPreset(defaultFields, fields);

            return(preset);
        }
예제 #8
0
        /// <summary>
        /// Refreshes the handling for the <paramref name="vehicle"/> using the <paramref name="preset"/>.
        /// </summary>
        /// <param name="vehicle"></param>
        /// <param name="preset"></param>
        private void RefreshVehicleUsingPreset(int vehicle, HandlingPreset preset)
        {
            if (!DoesEntityExist(vehicle))
            {
                return;
            }

            foreach (var item in preset.Fields)
            {
                string  fieldName  = item.Key;
                dynamic fieldValue = item.Value;

                var fieldsInfo = HandlingInfo.FieldsInfo;
                if (!fieldsInfo.TryGetValue(fieldName, out BaseFieldInfo fieldInfo))
                {
                    if (Debug)
                    {
                        CitizenFX.Core.Debug.WriteLine($"{ScriptName}: No fieldInfo definition found for {fieldName}");
                    }
                    continue;
                }

                Type   fieldType = fieldInfo.Type;
                string className = fieldInfo.ClassName;

                if (fieldType == FieldType.FloatType)
                {
                    var value = GetVehicleHandlingFloat(vehicle, className, fieldName);
                    if (Math.Abs(value - fieldValue) > FloatPrecision)
                    {
                        SetVehicleHandlingFloat(vehicle, className, fieldName, fieldValue);

                        if (Debug)
                        {
                            CitizenFX.Core.Debug.WriteLine($"{ScriptName}: {fieldName} updated from {value} to {fieldValue}");
                        }
                    }
                }

                else if (fieldType == FieldType.IntType)
                {
                    var value = GetVehicleHandlingInt(vehicle, className, fieldName);
                    if (value != fieldValue)
                    {
                        SetVehicleHandlingInt(vehicle, className, fieldName, fieldValue);

                        if (Debug)
                        {
                            CitizenFX.Core.Debug.WriteLine($"{ScriptName}: {fieldName} updated from {value} to {fieldValue}");
                        }
                    }
                }

                else if (fieldType == FieldType.Vector3Type)
                {
                    var value = GetVehicleHandlingVector(vehicle, className, fieldName);
                    if (value != fieldValue) // TODO: Check why this is bugged
                    {
                        SetVehicleHandlingVector(vehicle, className, fieldName, fieldValue);

                        if (Debug)
                        {
                            CitizenFX.Core.Debug.WriteLine($"{ScriptName}: {fieldName} updated from {value} to {fieldValue}");
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Default constructor
        /// </summary>
        public HandlingEditor()
        {
            // If the resource name is not the expected one ...
            if (GetCurrentResourceName() != ResourceName)
            {
                CitizenFX.Core.Debug.WriteLine($"{ScriptName}: Invalid resource name, be sure the resource name is {ResourceName}");
                return;
            }

            LastTime       = GetGameTimer();
            CurrentPreset  = null;
            CurrentVehicle = -1;
            Vehicles       = Enumerable.Empty <int>();
            ServerPresets  = new Dictionary <string, HandlingPreset>();

            LoadConfig();
            ReadFieldInfo();
            ReadServerPresets();
            RegisterDecorators();
            ReadVehiclePermissions();

            #region Register Commands

            RegisterCommand("handling_range", new Action <int, dynamic>((source, args) =>
            {
                if (args.Count < 1)
                {
                    CitizenFX.Core.Debug.WriteLine($"{ScriptName}: Missing float argument");
                    return;
                }

                if (float.TryParse(args[0], out float value))
                {
                    ScriptRange = value;
                    CitizenFX.Core.Debug.WriteLine($"{ScriptName}: Received new {nameof(ScriptRange)} value {value}");
                }
                else
                {
                    CitizenFX.Core.Debug.WriteLine($"{ScriptName}: Error parsing {args[0]} as float");
                }
            }), false);

            RegisterCommand("handling_debug", new Action <int, dynamic>((source, args) =>
            {
                if (args.Count < 1)
                {
                    CitizenFX.Core.Debug.WriteLine($"{ScriptName}: Missing bool argument");
                    return;
                }

                if (bool.TryParse(args[0], out bool value))
                {
                    Debug = value;
                    CitizenFX.Core.Debug.WriteLine($"{ScriptName}: Received new {nameof(Debug)} value {value}");
                }
                else
                {
                    CitizenFX.Core.Debug.WriteLine($"{ScriptName}: Error parsing {args[0]} as bool");
                }
            }), false);

            RegisterCommand("handling_decorators", new Action <int, dynamic>((source, args) =>
            {
                if (args.Count < 1)
                {
                    PrintDecorators(CurrentVehicle);
                }
                else
                {
                    if (int.TryParse(args[0], out int value))
                    {
                        PrintDecorators(value);
                    }
                    else
                    {
                        CitizenFX.Core.Debug.WriteLine($"{ScriptName}: Error parsing {args[0]} as int");
                    }
                }
            }), false);

            RegisterCommand("handling_print", new Action <int, dynamic>((source, args) =>
            {
                PrintVehiclesWithDecorators(Vehicles);
            }), false);

            RegisterCommand("handling_preset", new Action <int, dynamic>((source, args) =>
            {
                if (CurrentPreset != null)
                {
                    CitizenFX.Core.Debug.WriteLine(CurrentPreset.ToString());
                }
                else
                {
                    CitizenFX.Core.Debug.WriteLine($"{ScriptName}: Current preset doesn't exist");
                }
            }), false);

            RegisterCommand("handling_xml", new Action <int, dynamic>((source, args) =>
            {
                if (CurrentPreset != null)
                {
                    CitizenFX.Core.Debug.WriteLine(GetXmlFromPreset(CurrentPreset).OuterXml);
                }
                else
                {
                    CitizenFX.Core.Debug.WriteLine($"{ScriptName}: Current preset doesn't exist");
                }
            }), false);

            #endregion

            // Create the script for the menu
            _handlingMenu = new HandlingMenu(this);

            if (_handlingMenu != null)
            {
                RegisterScript(_handlingMenu);
            }

            #region GUI Events Handling

            _handlingMenu.MenuApplyPersonalPresetButtonPressed  += GUI_MenuApplyPersonalPresetButtonPressed;
            _handlingMenu.MenuApplyServerPresetButtonPressed    += GUI_MenuApplyServerPresetButtonPressed;
            _handlingMenu.MenuSavePersonalPresetButtonPressed   += GUI_MenuSavePersonalPresetButtonPressed;
            _handlingMenu.MenuDeletePersonalPresetButtonPressed += GUI_MenuDeletePersonalPresetButtonPressed;
            _handlingMenu.MenuResetPresetButtonPressed          += GUI_MenuResetPresetButtonPressed;
            _handlingMenu.MenuPresetValueChanged += GUI_MenuPresetValueChanged;

            #endregion

            Tick += GetCurrentVehicle;
            Tick += ScriptTask;
        }