196 lines
7.0 KiB
Lua
196 lines
7.0 KiB
Lua
-- ============================================================
|
|
-- 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 .. "%")
|