野外科举上线两周被答题脚本屠榜:固定题库被整理成答案表,脚本 20 秒答完 10 题满分,前 20 名全是机器人,真人玩家场均得分不到一半。答题活动封装:多场次调度加四层防作弊(题序乱序、选项乱序、时限压缩、异常时长检测),脚本的优势被压到与手速快的人类持平。
场次调度与乱序出题:每场从题库随机抽题、选项乱序。示例代码如下:
local questionBank = {
{ q = "祖玛教主的据点是哪一层", opts = { "祖玛七层", "沃玛三层", "封魔谷" }, ans = 1 },
{ q = "裁决之杖的攻击上限通常是", opts = { "0-38", "0-30", "0-45" }, ans = 1 },
}
local function shuffleOpts(q)
local order = {}
for i = 1, #q.opts do
order[i] = i
end
for i = #order, 2, -1 do
local j = math.random(i)
order[i], order[j] = order[j], order[i]
end
local opts, ans = {}, 0
for newIdx, oldIdx in ipairs(order) do
opts[newIdx] = q.opts[oldIdx]
if oldIdx == q.ans then
ans = newIdx
end
end
return { q = q.q, opts = opts, ans = ans }
end
local function startRound(actor)
actor = getplayerbyname(actor)
local picked = {}
for i = 1, 10 do
picked[i] = shuffleOpts(questionBank[math.random(#questionBank)])
end
setplayvar(actor, "HUMAN", "QuizPaper", "active", 0)
setplayvar(actor, "HUMAN", "QuizStart", os.time(), 1)
sendmsg(actor, 1, "科举第一题已出,每题限时 20 秒。")
return picked
end
异常时长检测示例代码如下:
local function isSuspicious(startTs, qCount)
local used = os.time() - startTs
return used < qCount * 2
end
10 题用时低于 20 秒(平均每题 2 秒)标记为脚本嫌疑,成绩进入复核。
shuffleOpts 用 Fisher-Yates 打乱选项序,答案下标随选项一起映射到新位置——乱序后正确答案的位置每次不同,答案表失效。setplayvar 的 QuizStart 记录开考时间戳用于时长审计。题库从 40 题里每场随机抽 10 题,同场不重复由抽题去重保证。giveitem 按名次发奖,复核通过才发放。
答题防作弊踩过三个坑:一是只乱序选项没乱序题序,脚本按题干前缀匹配照样全对,题序与选项序必须双层乱序;二是答案下标在乱序时忘了映射,新序第一项永远是答案,玩家两场就摸出规律——乱序函数要对 ans 做同步映射并自测 100 次分布;三是异常检测只看总时长,脚本放慢到每题 5 秒就绕过检测,加第二道指标:选项停留方差(人类每题停留时间波动大,脚本恒定),双指标联合判定。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
一、一行代码拆解:local function roll() 里写 local cfg = {500, 200, 50} —…
一、隐蔽陷阱:国库金币累加到 2^53(约 9007199254740992)之后再加 1,数值纹丝不动——双精度浮点在该区…
一、线上事故:仓库存取逻辑散在 6 个脚本,各自写各自的 getsysvar 键名,某次改名漏改 2 处,300 件裁决之杖…
一、抛坑提问:500 件战备装备一次下发必卡,按每页 20 件切片,边界怎么算才不出空页和重页?起点 (page-1) 20…
一、抛坑提问:校验失败在工具函数里 error,日志却指向工具函数那一行,排查总要翻两层。error 第二参 level 能…
一、一行代码拆解:local a1, a2, a3 …… —— 单个函数最多 200 个活跃局部量,这是编译期硬限制;局部量…