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("example", 750, 439)
  mad.draw_text("example", 750, 439 + 20)
  mad.draw_text("example", 750, 439 + 40)
  mad.draw_text("example", 750, 439 + -20)
  mad.draw_text("example", 750, 439 + -40)
end



поменяй в конце ```  mad.draw_text("example", 750, 439)
  mad.draw_text("example", 750, 439 + 20)
  mad.draw_text("example", 750, 439 + 40)
  mad.draw_text("example", 750, 439 + -20)
  mad.draw_text("example", 750, 439 + -40)``` на выводы дебаг информации, как можн больше.