local sampev  = require 'lib.samp.events'
local mad     = require 'MoonAdditions'

-- Configuration
local config = {
  recoil = {
    strength = 0.025,
    recoverySpeed = 0.1
  },
  animation = {
    duration = 0.15,
    holdTime = 0.1
  }
}

-- State
local state = {
  cursor = {
    x = 0,
    y = 0
  },
  firing = {
    isActive = false,
    startTime = nil,
    startPosition = { x = 0, y = 0 },
    targetPosition = { x = 0, y = 0 },
    holdTimeStart = nil,
    hasHoldingTimeStarted = false
  },
  time = {
    last = nil
  }
}

-- Helper Functions
local function normalizeAngle(angle)
  return ((angle + math.pi) % (2 * math.pi)) - math.pi
end

local function lerp(startValue, endValue, progress)
  return startValue + (endValue - startValue) * progress
end

-- Main loop
function main()
  repeat
    wait(0)
  until isSampAvailable()
  wait(-1)
end

-- Event Handlers
function sampev.onSendBulletSync()
  state.firing = {
    isActive = true,
    startTime = os.clock(),
    startPosition = { x = state.cursor.x, y = state.cursor.y },
    targetPosition = {
      x = state.cursor.x + config.recoil.strength,
      y = state.cursor.y + (math.random() * config.recoil.strength - config.recoil.strength / 2) * 0.1
    },
    holdTimeStart = nil,
    hasHoldingTimeStarted = false
  }
end

function onD3DPresent()
  local currentTime = os.clock()
  local deltaTime = currentTime - (state.time.last or currentTime)
  state.time.last = currentTime

  local camera = {
    x = normalizeAngle(representIntAsFloat(readMemory(11989576, 4, false))),
    z = normalizeAngle(representIntAsFloat(readMemory(11989592, 4, false)))
  }

  local errorX, errorY = 0, 0

  if state.firing.isActive then
    local elapsedTime = currentTime - state.firing.startTime
    local progress = 0.75 + math.min(elapsedTime / config.animation.duration, 1) * 0.25
    progress = math.min(progress, 1)  -- Ensure progress does not exceed 1

    local targetX = lerp(state.firing.startPosition.x, state.firing.targetPosition.x, progress)
    local targetY = lerp(state.firing.startPosition.y, state.firing.targetPosition.y, progress)

    errorX = targetX - state.cursor.x
    errorY = targetY - state.cursor.y

    if progress >= 1 then
      if not state.firing.hasHoldingTimeStarted then
        state.firing.holdTimeStart = currentTime
        state.firing.hasHoldingTimeStarted = true
      else
        if currentTime - state.firing.holdTimeStart >= config.animation.holdTime then
          state.firing.isActive = false
        end
      end
    end
  else
    errorX = math.max(-state.cursor.x, -(deltaTime * config.recoil.recoverySpeed))
    errorY = math.max(-state.cursor.y, -(deltaTime * config.recoil.recoverySpeed))
  end

  state.cursor.x = state.cursor.x + errorX
  state.cursor.y = state.cursor.y + errorY
  setCameraPositionUnfixed(camera.x + errorX, camera.z + errorY)
  
    




    mad.draw_text("Cursor Position: (" .. string.format("%.2f", state.cursor.x) .. ", " .. string.format("%.2f", state.cursor.y) .. ")", 750, 439, mad.font_style.SUBTITLES, 0.3, 0.6, mad.font_align.LEFT, 2000, true, false, 255, 255, 255, 255, 1, 0, 30, 30, 30, 120)
    mad.draw_text("Firing Active: " .. tostring(state.firing.isActive), 750, 439 + 20, mad.font_style.SUBTITLES, 0.3, 0.6, mad.font_align.LEFT, 2000, true, false, 255, 255, 255, 255, 1, 0, 30, 30, 30, 120)
    mad.draw_text("Firing Start Time: " .. (state.firing.startTime or "N/A"), 750, 439 + 40, mad.font_style.SUBTITLES, 0.3, 0.6, mad.font_align.LEFT, 2000, true, false, 255, 255, 255, 255, 1, 0, 30, 30, 30, 120)
    mad.draw_text("Animation Progress: " .. string.format("%.2f", (state.firing.isActive and (os.clock() - state.firing.startTime) / config.animation.duration or 0)), 750, 439 + 60, mad.font_style.SUBTITLES, 0.3, 0.6, mad.font_align.LEFT, 2000, true, false, 255, 255, 255, 255, 1, 0, 30, 30, 30, 120)
    mad.draw_text("Hold Time Start: " .. (state.firing.holdTimeStart or "N/A"), 750, 439 + 80, mad.font_style.SUBTITLES, 0.3, 0.6, mad.font_align.LEFT, 2000, true, false, 255, 255, 255, 255, 1, 0, 30, 30, 30, 120)
    mad.draw_text("Last Update Time: " .. string.format("%.2f", state.time.last), 750, 439 + 100, mad.font_style.SUBTITLES, 0.3, 0.6, mad.font_align.LEFT, 2000, true, false, 255, 255, 255, 255, 1, 0, 30, 30, 30, 120)
    mad.draw_text("Camera Position: (" .. string.format("%.2f", camera.x) .. ", " .. string.format("%.2f", camera.z) .. ")", 750, 439 + 120, mad.font_style.SUBTITLES, 0.3, 0.6, mad.font_align.LEFT, 2000, true, false, 255, 255, 255, 255, 1, 0, 30, 30, 30, 120)
end

function draw_text(str, x, y, r, g, b)
        mad.draw_text(str, x, y, mad.font_style.SUBTITLES, 0.4, 0.7, mad.font_align.LEFT, 2000, true, false, r, g, b, 255, 1, 0, 30, 30, 30, 120)
end


добавь больше отладочной инфы. добавь рендер буквы Х на месте где должен быть оригинальный(несмещенный) прицел