You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FiveM Lua漂移排行榜Bug:如何通过玩家ID对比避免重复占位

FiveM漂移排行榜重复玩家问题修复方案

问题描述

开发的漂移排行榜存在Bug:未正确校验玩家ID,导致同一玩家可占据榜单多个名次。例如玩家A以10分位居榜首、玩家B以5分排第二时,玩家A只要跑出7分的中间分数,就会同时占据第二名位置。

问题根源

  1. 原checkLeaderboard函数直接将旧条目设为nil,导致数组出现空洞,ipairs遍历不彻底,旧条目可能残留
  2. 榜单更新逻辑混乱:空榜单单独处理、遍历插入时机不对,导致删除旧条目后仍可能重复添加
  3. GetPlacement函数未处理11、12、13这类特殊数字,会出现“12nd”的错误表述

修复步骤

  • 彻底移除玩家旧榜单条目:遍历榜单时用table.remove删除旧条目,而非设为nil,保证数组连续性
  • 统一榜单更新流程:不管榜单是否为空,先删除玩家所有旧条目,再根据新分数决定插入位置
  • 修复排名后缀逻辑:处理11-13的特殊情况,避免错误的后缀

修复后完整代码

LEADERBOARD_CLEAR_TIME = 15 -- 单位:分钟

local Players = {}
local Leaderboards = {}

RegisterCommand('cleardriftscores', function(source)
    if IsPlayerAceAllowed(source, 'drift') then -- Ace权限校验
        clearLeaderboard()
    end
end)

RegisterNetEvent("SaveScore")
AddEventHandler("SaveScore", function(client, data)
    local identifier = GetPlayerIdentifier(source, 0)
    local playerName = GetPlayerName(source)
    local newScore = data.curScore

    -- 更新个人最佳成绩
    if Players[identifier] then
        if Players[identifier].pb < newScore then
            local oldScore = Players[identifier].pb
            Players[identifier].pb = newScore
            chatMessage(source, string.format("恭喜!你刷新了个人漂移链最高分:从^2%s^0提升到^2%s^0!", oldScore, newScore))
        end
    else
        Players[identifier] = { pb = newScore }
    end

    -- 先移除该玩家在榜单中的所有旧条目
    removePlayerFromLeaderboard(identifier)

    -- 插入新分数到正确位置
    local inserted = false
    for k, v in ipairs(Leaderboards) do
        if v.score < newScore then
            table.insert(Leaderboards, k, { score = newScore, name = playerName, id = identifier })
            chatMessage(-1, string.format("^2%s^0以^2%s^0的分数超越了^2%s^0的^2%s^0!当前排名第^2%s^0", playerName, newScore, v.name, v.score, GetPlacement(k)))
            inserted = true
            break
        end
    end

    -- 如果没找到比自己低的分数,就插在最后
    if not inserted then
        table.insert(Leaderboards, { score = newScore, name = playerName, id = identifier })
        local placement = #Leaderboards
        if placement == 1 then
            chatMessage(-1, string.format("^2%s^0开启了本次漂移排行榜,分数为^2%s^0!", playerName, newScore))
        else
            chatMessage(-1, string.format("^2%s^0提交了^2%s^0的漂移分数,当前排名第^2%s^0", playerName, newScore, GetPlacement(placement)))
        end
    end

    -- 保持榜单按分数降序排列(兜底逻辑)
    table.sort(Leaderboards, function(a, b)
        return a.score > b.score
    end)
end)

function chatMessage(target, msg)
    TriggerClientEvent('chat:addMessage', target or -1, {
        color = { 255, 0, 0},
        multiline = true,
        args = {"[漂移排行榜] ", msg}
    })
end

-- 移除玩家在榜单中的所有条目
function removePlayerFromLeaderboard(identifier)
    -- 倒序遍历,避免删除元素后索引错乱
    for k = #Leaderboards, 1, -1 do
        if Leaderboards[k].id == identifier then
            table.remove(Leaderboards, k)
        end
    end
end

-- 修复后的排名后缀函数
function GetPlacement(number)
    local lastTwoDigits = number % 100
    -- 处理11、12、13的特殊情况
    if lastTwoDigits >= 11 and lastTwoDigits <= 13 then
        return number .. 'th'
    end

    local lastDigit = number % 10
    local placement = 'th'
    if lastDigit == 1 then
        placement = 'st'
    elseif lastDigit == 2 then
        placement = 'nd'
    elseif lastDigit == 3 then
        placement = 'rd'
    end
    return number .. placement
end

function clearLeaderboard()
    Leaderboards = {}
    chatMessage(-1, "漂移排行榜已清空!")
end

-- 排行榜自动重置线程
Citizen.CreateThread(function()
    while true do
        while #Leaderboards == 0 do
            Citizen.Wait(0)
        end
        -- 提前5分钟提醒
        Citizen.Wait((LEADERBOARD_CLEAR_TIME * 60 * 1000) - (5 * 60 * 1000))
        chatMessage(-1, "漂移排行榜将在5分钟后清空!")
        Citizen.Wait(3 * 60 * 1000)
        chatMessage(-1, "漂移排行榜将在2分钟后清空!")
        Citizen.Wait(1 * 60 * 1000)
        chatMessage(-1, "漂移排行榜将在1分钟后清空!")
        Citizen.Wait(1 * 60 * 1000)
        clearLeaderboard()
    end
end)

内容的提问来源于stack exchange,提问作者Gavino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 03:45:42