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


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

public class SedanCabinCamera : Script
{
    private Camera _carCamera;
    private float _heightOffset = 1.2f; 
    private bool _wasInCar = false;
    private float _currentHeadingOffset = 0.0f;
    private float _currentPitch = 15.0f; 
    
    private ScriptSettings _config; 

    public SedanCabinCamera()
    {
        _config = ScriptSettings.Load("scripts\\CameraOffsets.ini");
        KeyDown += OnKeyDown;
        Tick += OnTick;
        UI.Notify("~g~Скрипт камеры (v2) успешно загружен!");
    }

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

        // Если мы не в машине - удаляем камеру и выходим
        if (vehicle == null) 
        { 
            RemoveCamera(); 
            _wasInCar = false; 
            return; 
        }

        // Проверяем, что это Марк или Чайзер
        bool isTarget = (vehicle.Model.Hash == Game.GenerateHash("jzx100") || 
                         vehicle.Model.Hash == Game.GenerateHash("mk2100"));
        
        if (!isTarget) 
        { 
            RemoveCamera(); 
            _wasInCar = false; 
            return; 
        }

        // При посадке в машину загружаем сохраненную высоту
        if (!_wasInCar)
        {
            UI.Notify("~b~Обнаружена машина: " + vehicle.Model.ToString());
            string modelName = GetModelName(vehicle);
            _heightOffset = _config.GetValue<float>("Offsets", modelName, 1.2f);
            _wasInCar = true;
        }

        // Если включили вид от первого лица - отключаем скрипт
        if (Function.Call<int>(Hash.GET_FOLLOW_VEHICLE_CAM_VIEW_MODE) == 4) 
        { 
            RemoveCamera(); 
            return; 
        }

        // Создаем камеру, если ее нет
        if (_carCamera == null || !_carCamera.Exists())
        {
            _carCamera = World.CreateCamera(vehicle.Position, vehicle.Rotation, 60f);
            _currentHeadingOffset = 0.0f; 
            _currentPitch = 15.0f; 
        }

        // 1. ЧИТАЕМ МЫШЬ (без автовозврата)
        float lookLR = Function.Call<float>(Hash.GET_CONTROL_NORMAL, 0, 2);
        float lookUD = Function.Call<float>(Hash.GET_CONTROL_NORMAL, 0, 3);

        // 2. ВРАЩАЕМ КАМЕРУ
        _currentHeadingOffset -= lookLR * 3.0f; 
        _currentPitch += lookUD * 2.0f;         

        // Ограничители (чтобы не смотрела под землю или в зенит)
        _currentHeadingOffset = Math.Max(-180.0f, Math.Min(180.0f, _currentHeadingOffset));
        _currentPitch = Math.Max(-30.0f, Math.Min(80.0f, _currentPitch));

        // 3. МАТЕМАТИКА ОРБИТЫ (вокруг точки)
        float finalHeading = vehicle.Heading + _currentHeadingOffset;
        
        // Переводим углы в радианы
        float radH = finalHeading * (float)(Math.PI / 180.0);
        float radP = _currentPitch * (float)(Math.PI / 180.0);
        float dist = 4.25f; // Твоя дистанция

        // Невидимый центр, вокруг которого летает камера (машина + высота)
        Vector3 center = vehicle.Position + new Vector3(0, 0, _heightOffset);

        // Вычисляем позицию камеры по сфере
        float camX = center.X - (float)Math.Sin(radH) * dist * (float)Math.Cos(radP);
        float camY = center.Y - (float)Math.Cos(radH) * dist * (float)Math.Cos(radP);
        float camZ = center.Z + (float)Math.Sin(radP) * dist;

        _carCamera.Position = new Vector3(camX, camY, camZ);

        // 4. КАМЕРА ВСЕГДА СМОТРИТ В ЦЕНТР (на машину)
        _carCamera.PointAt(center);

        World.RenderingCamera = _carCamera;
        Function.Call(Hash.RENDER_SCRIPT_CAMS, true, false, 0, true, 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);
            UI.Notify("~g~Высота: " + _heightOffset.ToString("F2")); 
        }
        else if (e.KeyCode == Keys.NumPad3)
        {
            _heightOffset -= 0.05f;
            SaveHeight(vehicle);
            UI.Notify("~y~Высота: " + _heightOffset.ToString("F2")); 
        }
    }

    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();
    }

    private void RemoveCamera()
    {
        if (_carCamera != null && _carCamera.Exists())
        {
            World.RenderingCamera = null;
            Function.Call(Hash.RENDER_SCRIPT_CAMS, false, false, 0, true, false);
            Function.Call(Hash.DESTROY_CAM, _carCamera.Handle, true); 
            _carCamera = null;
        }
    }
}