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