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); } } }
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); }
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); }
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}"); } }
/// <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); }
/// <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; }