Загрузка данных
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;
}
}
}