-- ============================================================ -- mercyv-stamina | Client -- ============================================================ local currentStamina = Config.StartStamina local isJogForced = false local lastSprintTime = 0 local regenBlocked = false -- ============================================================ -- Hilfsfunktionen -- ============================================================ local function log(msg) if Config.ShowDebug then print("^3[mercyv-stamina]^7 " .. tostring(msg)) end end local function clamp(val, minVal, maxVal) return math.max(minVal, math.min(maxVal, val)) end local function getStamina() return currentStamina end -- ============================================================ -- Vanilla Stamina neutralisieren -- ============================================================ local function suppressVanilla() if not Config.DisableVanilla then return end RestorePlayerStamina(PlayerId(), 100.0) SetRunSprintMultiplierForPlayer(PlayerId(), 1.0) end -- ============================================================ -- Jog-Modus steuern -- ============================================================ local function enableJog() if isJogForced then return end isJogForced = true SetPedMovementClipset(PlayerPedId(), Config.JogClipset, 0.3) log("Jog aktiviert | Stamina: " .. math.floor(currentStamina) .. "%") TriggerServerEvent("mercyv-stamina:log", "jog_start", math.floor(currentStamina)) end local function disableJog() if not isJogForced then return end isJogForced = false ResetPedMovementClipset(PlayerPedId(), 0.3) log("Jog deaktiviert | Stamina: " .. math.floor(currentStamina) .. "%") TriggerServerEvent("mercyv-stamina:log", "jog_stop", math.floor(currentStamina)) end -- ============================================================ -- Sprint-Erkennung -- ============================================================ local function isSprinting() local ped = PlayerPedId() -- Nicht im Fahrzeug + Sprint-Taste gedrückt + Charakter bewegt sich return not IsPedInAnyVehicle(ped, false) and IsControlPressed(0, 21) -- INPUT_SPRINT and IsPedRunning(ped) end -- ============================================================ -- Haupt-Loop -- ============================================================ CreateThread(function() while true do Wait(Config.TickInterval) local ped = PlayerPedId() local inVehicle = IsPedInAnyVehicle(ped, false) -- Vanilla immer unterdrücken solange aktiviert suppressVanilla() if not inVehicle then local sprinting = isSprinting() -- Stamina verringern beim Sprinten (nur wenn nicht schon im Jog-Modus) if sprinting and not isJogForced then currentStamina = clamp(currentStamina - Config.StaminaDrain, 0, 100) lastSprintTime = GetGameTimer() regenBlocked = true log("Sprinten | Stamina: " .. string.format("%.1f", currentStamina) .. "%") end -- Regen-Delay prüfen if regenBlocked and (GetGameTimer() - lastSprintTime) >= Config.RegenDelay then regenBlocked = false end -- Stamina regenerieren (Fuß) if not sprinting and not regenBlocked then currentStamina = clamp(currentStamina + Config.StaminaRegen, 0, 100) end -- Jog-Modus einschalten wenn Schwellwert unterschritten if currentStamina <= Config.JogThreshold then enableJog() end -- Jog-Modus ausschalten wenn genug Stamina regeneriert (Hysterese) if isJogForced and currentStamina >= (Config.JogThreshold + Config.JogHysteresis) then disableJog() end else -- Im Fahrzeug: schnellere Regen, kein Jog if not regenBlocked then currentStamina = clamp( currentStamina + (Config.StaminaRegen * Config.VehicleRegenMultiplier), 0, 100 ) end -- Jog zurücksetzen falls noch aktiv disableJog() end end end) -- ============================================================ -- Chat-Befehl: /stamina [0-100] -- ============================================================ if Config.AllowCommand then RegisterCommand("stamina", function(source, args) local val = tonumber(args[1]) if not val then TriggerEvent("chat:addMessage", { color = { 255, 200, 50 }, args = { "mercyv-stamina", "Nutzung: /stamina [" .. Config.CommandMin .. "-" .. Config.CommandMax .. "]" } }) TriggerEvent("chat:addMessage", { color = { 200, 200, 200 }, args = { "mercyv-stamina", "Aktueller Jog-Schwellwert: " .. Config.JogThreshold .. "% | Aktuelle Stamina: " .. math.floor(currentStamina) .. "%" } }) return end if val < Config.CommandMin or val > Config.CommandMax then TriggerEvent("chat:addMessage", { color = { 255, 80, 80 }, args = { "mercyv-stamina", "Wert muss zwischen " .. Config.CommandMin .. " und " .. Config.CommandMax .. " liegen." } }) return end Config.JogThreshold = val TriggerEvent("chat:addMessage", { color = { 100, 220, 130 }, args = { "mercyv-stamina", "Jog-Schwellwert auf " .. val .. "% gesetzt. (Rückkehr zum Sprint ab " .. (val + Config.JogHysteresis) .. "%)" } }) log("JogThreshold via Befehl geändert → " .. val .. "%") end, false) end -- ============================================================ -- Netzwerk-Events (von anderen Scripts aufrufbar) -- ============================================================ -- Stamina auffüllen: TriggerEvent("mercyv-stamina:refill", 50) RegisterNetEvent("mercyv-stamina:refill") AddEventHandler("mercyv-stamina:refill", function(amount) local old = currentStamina currentStamina = clamp(currentStamina + (tonumber(amount) or 100), 0, 100) log("Refill: +" .. tostring(amount) .. " | " .. string.format("%.1f", old) .. "% → " .. string.format("%.1f", currentStamina) .. "%") end) -- Stamina direkt setzen: TriggerEvent("mercyv-stamina:set", 75) RegisterNetEvent("mercyv-stamina:set") AddEventHandler("mercyv-stamina:set", function(amount) currentStamina = clamp(tonumber(amount) or 100, 0, 100) log("Stamina gesetzt auf: " .. string.format("%.1f", currentStamina) .. "%") end) -- Aktuellen Wert abrufen (callback-basiert für andere Scripts) -- Beispiel: exports["mercyv-stamina"]:GetStamina() exports("GetStamina", getStamina) -- Jog-Status abrufen exports("IsJogging", function() return isJogForced end) log("Client geladen | JogThreshold: " .. Config.JogThreshold .. "% | Stamina Start: " .. Config.StartStamina .. "%")