Загрузка данных


using System;
using System.Windows.Forms;
using GTA;
using GTA.Native;

public class NativeVehicleCamera : Script
{
    // ОПУСТИЛИ ВЫСОТУ НА 40 СМ (было 0.90, стало 0.50)
    private float _heightOffset = 0.50f; 
    private bool _wasInCar = false;
    private int _lastViewMode = 0;
    private ScriptSettings _config;

    public NativeVehicleCamera()
    {
        _config = ScriptSettings.Load("scripts\\CameraOffsets.ini");
        KeyDown += OnKeyDown;
        Tick += OnTick;
        GTA.UI.Notification.Show("~g~[v3] Нативная камера (0.50) загружена!");
    }

    private void OnTick(object sender, EventArgs e)
    {
        var vehicle = Game.Player.Character.CurrentVehicle;

        if (vehicle == null) 
        {
            if (_wasInCar) 
            {
                // Возвращаем стандартную камеру при выходе
                Function.Call((Hash)0x5C90EA32, 1, 0.0f, 0.0f, 0.0f);
                _wasInCar = false;
            }
            return; 
        }

        bool isTarget = (vehicle.Model.Hash == Game.GenerateHash("jzx100") || 
                         vehicle.Model.Hash == Game.GenerateHash("mk2100"));

        if (isTarget)
        {
            int currentViewMode = Function.Call<int>(Hash.GET_FOLLOW_VEHICLE_CAM_VIEW_MODE);

            // Применяем смещение ТОЛЬКО когда сели в машину или переключили вид (V)
            // Это защищает игру от зависания
            if (!_wasInCar || currentViewMode != _lastViewMode)
            {
                if (!_wasInCar)
                {
                    string modelName = GetModelName(vehicle);
                    // Загружаем сохраненную высоту (по умолчанию 0.50)
                    _heightOffset = _config.GetValue<float>("Offsets", modelName, 0.50f);
                    _wasInCar = true;
                }

                _lastViewMode = currentViewMode;

                if (currentViewMode != 4) // Если не первое лицо
                {
                    Function.Call((Hash)0x5C90EA32, 1, 0.0f, 0.0f, _heightOffset);
                }
                else
                {
                    Function.Call((Hash)0x5C90EA32, 1, 0.0f, 0.0f, 0.0f);
                }
            }
        }
        else
        {
            if (_wasInCar) 
            {
                Function.Call((Hash)0x5C90EA32, 1, 0.0f, 0.0f, 0.0f);
                _wasInCar = false;
            }
        }
    }

    private void OnKeyDown(object sender, KeyEventArgs e)
    {
        var vehicle = Game.Player.Character.CurrentVehicle;
        if (vehicle == null) return;
        
        bool isTarget = (vehicle.Model.Hash == Game.GenerateHash("jzx100") || 
                         vehicle.Model.Hash == Game.GenerateHash("mk2100"));
        if (!isTarget) return;

        if (e.KeyCode == Keys.NumPad9)
        {
            _heightOffset += 0.05f;
            SaveHeight(vehicle);
            GTA.UI.Notification.Show("~g~Высота: " + _heightOffset.ToString("F2")); 
            // Мгновенно применяем новую высоту
            Function.Call((Hash)0x5C90EA32, 1, 0.0f, 0.0f, _heightOffset);
        }
        else if (e.KeyCode == Keys.NumPad3)
        {
            _heightOffset -= 0.05f;
            SaveHeight(vehicle);
            GTA.UI.Notification.Show("~y~Высота: " + _heightOffset.ToString("F2")); 
            // Мгновенно применяем новую высоту
            Function.Call((Hash)0x5C90EA32, 1, 0.0f, 0.0f, _heightOffset);
        }
    }

    private string GetModelName(Vehicle vehicle)
    {
        if (vehicle.Model.Hash == Game.GenerateHash("jzx100")) return "jzx100";
        return "mk2100"; 
    }

    private void SaveHeight(Vehicle vehicle)
    {
        _config.SetValue<float>("Offsets", GetModelName(vehicle), _heightOffset);
        _config.Save();
    }
}