/// <summary>
        /// Creates a preset for the <paramref name="vehicle"/> to edit it locally
        /// </summary>
        /// <param name="vehicle"></param>
        /// <returns></returns>
        private VstancerPreset CreatePreset(int vehicle)
        {
            int wheelsCount = GetVehicleNumberOfWheels(vehicle);
            int frontCount  = wheelsCount / 2;

            if (frontCount % 2 != 0)
            {
                frontCount -= 1;
            }

            // Get default values first
            float off_f_def = DecorExistOn(vehicle, decor_off_f_def) ? DecorGetFloat(vehicle, decor_off_f_def) : GetVehicleWheelXOffset(vehicle, 0);
            float rot_f_def = DecorExistOn(vehicle, decor_rot_f_def) ? DecorGetFloat(vehicle, decor_rot_f_def) : GetVehicleWheelXrot(vehicle, 0);
            float off_r_def = DecorExistOn(vehicle, decor_off_r_def) ? DecorGetFloat(vehicle, decor_off_r_def) : GetVehicleWheelXOffset(vehicle, frontCount);
            float rot_r_def = DecorExistOn(vehicle, decor_rot_r_def) ? DecorGetFloat(vehicle, decor_rot_r_def) : GetVehicleWheelXrot(vehicle, frontCount);

            float off_f = DecorExistOn(vehicle, decor_off_f) ? DecorGetFloat(vehicle, decor_off_f) : off_f_def;
            float rot_f = DecorExistOn(vehicle, decor_rot_f) ? DecorGetFloat(vehicle, decor_rot_f) : rot_f_def;
            float off_r = DecorExistOn(vehicle, decor_off_r) ? DecorGetFloat(vehicle, decor_off_r) : off_r_def;
            float rot_r = DecorExistOn(vehicle, decor_rot_r) ? DecorGetFloat(vehicle, decor_rot_r) : rot_r_def;

            VstancerPreset preset = new VstancerPreset(wheelsCount, rot_f, rot_r, off_f, off_r, rot_f_def, rot_r_def, off_f_def, off_r_def);

            return(preset);
        }
 /// <summary>
 /// Refreshes the <paramref name="vehicle"/> with values from the <paramref name="preset"/>
 /// </summary>
 private async void RefreshVehicleUsingPreset(int vehicle, VstancerPreset preset)
 {
     if (DoesEntityExist(vehicle))
     {
         int wheelsCount = preset.WheelsCount;
         for (int index = 0; index < wheelsCount; index++)
         {
             SetVehicleWheelXOffset(vehicle, index, preset.OffsetX[index]);
             SetVehicleWheelXrot(vehicle, index, preset.RotationY[index]);
         }
     }
     await Delay(0);
 }
        /// <summary>
        /// Updates the decorators on the <paramref name="vehicle"/> with updated values from the <paramref name="preset"/>
        /// </summary>
        /// <param name="vehicle"></param>
        private async void UpdateVehicleDecorators(int vehicle, VstancerPreset preset)
        {
            float[] DefaultOffsetX   = preset.DefaultOffsetX;
            float[] DefaultRotationY = preset.DefaultRotationY;
            float[] OffsetX          = preset.OffsetX;
            float[] RotationY        = preset.RotationY;
            int     frontCount       = preset.FrontWheelsCount;

            UpdateFloatDecorator(vehicle, decor_off_f_def, DefaultOffsetX[0], OffsetX[0]);
            UpdateFloatDecorator(vehicle, decor_rot_f_def, DefaultRotationY[0], RotationY[0]);
            UpdateFloatDecorator(vehicle, decor_off_r_def, DefaultOffsetX[frontCount], OffsetX[frontCount]);
            UpdateFloatDecorator(vehicle, decor_rot_r_def, DefaultRotationY[frontCount], RotationY[frontCount]);

            UpdateFloatDecorator(vehicle, decor_off_f, OffsetX[0], DefaultOffsetX[0]);
            UpdateFloatDecorator(vehicle, decor_rot_f, RotationY[0], DefaultRotationY[0]);
            UpdateFloatDecorator(vehicle, decor_off_r, OffsetX[frontCount], DefaultOffsetX[frontCount]);
            UpdateFloatDecorator(vehicle, decor_rot_r, RotationY[frontCount], DefaultRotationY[frontCount]);

            await Delay(0);
        }
        /// <summary>
        /// The main task of the script
        /// </summary>
        /// <returns></returns>
        private async Task VstancerTask()
        {
            currentTime = (GetGameTimer() - lastTime);

            playerPed = PlayerPedId();

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

                if (IsThisModelACar((uint)GetEntityModel(vehicle)) && GetPedInVehicleSeat(vehicle, -1) == playerPed && !IsEntityDead(vehicle))
                {
                    // Update current vehicle and get its preset
                    if (vehicle != currentVehicle)
                    {
                        currentPreset  = CreatePreset(vehicle);
                        currentVehicle = vehicle;
                        InitialiseMenu();
                    }
                }
                else
                {
                    // If current vehicle isn't a car or player isn't driving current vehicle or vehicle is dead
                    currentPreset  = null;
                    currentVehicle = -1;
                }
            }
            else
            {
                // If player isn't in any vehicle
                currentPreset  = null;
                currentVehicle = -1;
            }

            // Check if current vehicle needs to be refreshed
            if (currentVehicle != -1 && currentPreset != null)
            {
                if (currentPreset.IsEdited)
                {
                    RefreshVehicleUsingPreset(currentVehicle, currentPreset);
                }
            }

            // Check if decorators needs to be updated
            if (currentTime > timer)
            {
                if (currentVehicle != -1 && currentPreset != null)
                {
                    UpdateVehicleDecorators(currentVehicle, currentPreset);
                }

                vehicles = new VehicleList();

                lastTime = GetGameTimer();
            }

            // Refreshes the iterated vehicles
            RefreshVehicles(vehicles.Except(new List <int> {
                currentVehicle
            }));

            await Delay(0);
        }
        public Vstancer()
        {
            ResourceName = GetCurrentResourceName();
            Debug.WriteLine($"{ScriptName}: Script by Neos7");

            RegisterDecorators();
            LoadConfig();

            currentTime    = GetGameTimer();
            lastTime       = currentTime;
            currentVehicle = -1;
            currentPreset  = null;
            vehicles       = Enumerable.Empty <int>();

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

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

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

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

            RegisterCommand("vstancer_decorators", new Action <int, dynamic>((source, args) =>
            {
                if (args.Count < 1)
                {
                    PrintDecoratorsInfo(currentVehicle);
                }
                else
                {
                    if (int.TryParse(args[0], out int value))
                    {
                        PrintDecoratorsInfo(value);
                    }
                    else
                    {
                        Debug.WriteLine($"{ScriptName}: Error parsing entity handle {args[0]} as int");
                    }
                }
            }), false);

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

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

            // In the constructor of a class that inherits BaseScript.
            EventHandlers.Add("VSTANCE:MenuControl", new Action(EventMenuControl));

            Tick += HandleMenu;
            Tick += VstancerTask;
        }