
player_sprint = {}

local pl = {}
local function check_player(player)
    local pi = pl[player]
    if not pi then pi = {}; pl[player] = pi end
    return pi
end

function player_sprint.is_sprinting(player)
  local pi = check_player(player)
  return pi.is_sprinting
end

function player_sprint.to_walk(player)
  local pi = check_player(player)
  pi.is_sprinting = false
  pi.is_sneaking = false
  playerphysics.remove_physics_factor(player, "speed", "player_sprint")
  aom_util.unset_fov(player, "player_sprint")
end

local function sneak_allowed(player)
  local node = core.get_node(player:get_pos())
  local ndef = core.registered_nodes[node.name]
  if ndef.climbable then return false end
  return true
end

function player_sprint.on_step(dtime)
  for _, player in pairs(core.get_connected_players()) do
    local pi = check_player(player)

    local ct = player_info.get(player)
    if not ct then return end

    if pi.is_sprinting and not ct.can_sprint then
      player_sprint.to_walk(player)
    end

    if ct.is_sneaking and sneak_allowed(player) and not pi.is_sneaking then
      playerphysics.add_physics_factor(player, "speed", "player_sprint:sneak", 0.6)
      pi.is_sneaking = true
    elseif (not ct.is_sneaking) and pi.is_sneaking then
      playerphysics.remove_physics_factor(player, "speed", "player_sprint:sneak")
      pi.is_sneaking = false
    end

    if ct.can_sprint and (ct.just_pressed.aux1 or ct.just_pressed.up
     or ct.just_released.aux1 or ct.just_released.up) then
      if (not pi.is_sprinting) and ct.ctrl.up and ct.ctrl.aux1 and ct.can_sprint then
        playerphysics.add_physics_factor(player, "speed", "player_sprint", 1.5)
        pi.is_sprinting = true
        aom_util.set_fov(player, {
            tag = "player_sprint",
            fov = 1.07,
            is_multiplier = true,
            transition_time = 0.1 })
      elseif pi.is_sprinting then
        player_sprint.to_walk(player)
      end
    end
  end
end

core.register_on_dieplayer(player_sprint.to_walk)
core.register_on_joinplayer(player_sprint.to_walk)

core.register_globalstep(player_sprint.on_step)
