排行榜结算前玩家不知道"自己能拿第几名、和前一名差多少"——预期不透明导致两种极端:领先者躺平不冲、落后者觉得无望直接放弃。名次预览:输入当前积分,返回预计名次、与前一名的差距、追平需要的最少积分——把预期变成数字,玩家的冲刺决策有据可依。
名次定位与差距计算:读排行榜快照,定位自己排名并计算与前一名的差值。示例代码如下:
local function previewRank(actor, myPts)
actor = getplayerbyname(actor)
local board = tostring(getsysvar("WarPtsBoard") or "")
local higher, closestAbove = 0, nil
for e in string.gmatch(board, "[^|]+") do
local pts = tonumber(string.match(e, ":(%d+)$") or "0")
if pts > myPts then
higher = higher + 1
if closestAbove == nil or pts < closestAbove then
closestAbove = pts
end
end
end
local rank = higher + 1
local gap = closestAbove and (closestAbove - myPts) or 0
sendmsg(actor, 1, "预计第 " .. rank .. " 名,距前一名差 " .. gap .. " 分。")
return rank, gap
end
奖励映射:按名次段位返回对应奖励预览,让玩家知道冲到目标名次能拿什么。示例代码如下:
local REWARDS = { { min = 1, desc = "金条x5+限定称号" }, { min = 10, desc = "金条x2" }, { min = 50, desc = "金创药x5" } }
local function showRewardPreview(actor, rank)
actor = getplayerbyname(actor)
for _, r in ipairs(REWARDS) do
if rank <= r.min then
sendmsg(actor, 1, "第 " .. r.min .. " 名内可获得:" .. r.desc)
return
end
end
sendmsg(actor, 1, "当前名次暂无奖励,继续加油!")
end
WarPtsBoard 全局变量存"名字:战功"竖线分隔的榜单快照,预览只读快照不打扰结算。string.match(e, ":(%d+)$") 锚定行尾取数字,防名字里的数字干扰。REWARDS 档位表按 min 升序排列,showRewardPreview 与结算发奖共用同一张表——预览与结算的口径单点化,避免"预览说 5 根、结算发 2 根"的口径分裂。
名次预览踩过三个坑:一是预览读实时榜而结算读一小时前的快照,两个口径差出十几名,预览与结算必须同源(都用快照);二是档位表无序存放,前 10 名的档位排在第 50 名档位后面,先匹配先得的逻辑把高奖发给了低名次,档位表必须按 min 升序初始化;三是并列战功的先后没定义,两个第 9 名都以为自己是第 9,并列时按达成时间先者优先并公示规则。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
设计初衷 背包无限装:药水带一百瓶、材料囤到爆——负重没有成本,背包管理沦为无脑囤积。负重系统设计:每件物品带重量,总负重超…
设计初衷 装备栏有武器位没有副手位:副手要么没用、要么变成第二武器直接双倍攻击——副手的定位从来没人讲清。副手装备设计:主手…
底层原理 对不同类型的节点执行不同操作(战绩流水里的击杀、阵亡、助攻各有统计口径),把操作散在类型判断里,每加一种操作就要改…
底层原理 行会的战力由成员战力组成、成员战力由装备组成——"整体"与"部分"要能用同一个接口对待:问行会战力与问成员战力是同…
设计初衷 输出成长只有堆攻击一条路:攻击加成稀释严重(基础 2000 再加 200 体感无几),成长反馈越来越钝。增伤属性设…
业务场景 驻地守御靠玩家人肉站桩:离线时段防务真空。箭塔守御封装:驻地点位部署箭塔(帮会资金建造),箭塔自动索敌(优先最近、…