【游戏功能】
先抛一个坑:两只怪为什么要一齐扑上来?真实的打斗里两个打手不会同时抡拳——总得有人虚位、有人进手,一齐扑上是武行的大忌。可战场上的怪不懂这个,两只一齐出手、一齐走位、一齐压过来,玩家在夹缝里连招都按不出来。轮岗纹的答案是把武行的规矩借过来:排岗——同一拍只许一只出手,另一只在旁边歇着,三秒一轮换。这篇把整套模块拆开:配置表、排岗表、轮休判定、换岗演出、定时器、调试按钮,一段一段照抄能跑。
一、效果演示:两只怪轮着出手,总有一只在歇
演示场两只怪照常一齐扑上来。点「轮岗!」:一圈青色的纹排开——十秒排岗期。这一拍起,怪群被编了岗:左边那只出手,头顶亮"岗"字;右边那只当场站定,头顶浮"休"字——爪子抬到一半也得放下。三秒一到换岗:出手的去歇着,歇着的接岗出手。十秒里两班倒,玩家的挨打密度直接砍半。演示里试两笔账:排岗期的挨打节奏和没排岗的一齐扑——同样的两只怪,一齐来是左右开弓,排了岗是单手慢拳。轮岗纹教的是分而治之:打不过一齐上的,就让它俩排队上。
fx-shiftduty
二、底层原理:一张排岗表加一次轮休判定
模块的机关是一对搭档。排岗表:开纹那一拍把视野里的怪挨个编号入册——同一拍只允许一岗出手,在册的每只怪都领到自己的班次。轮休判定:轮到歇岗的那只被暂时按住——爪子抬不起来、脚步挪不动,整只怪像被点了睡穴,三秒后换岗钟响才放出来。和眩晕类控制的分野在"轮休是排班不是点穴":眩晕把怪定死不看同伴,轮休是按岗表的规矩轮流来——你歇的时候它在打,你打的时候它歇着,怪群的总出手被岗表切成了单行道。
岗表为什么三秒一换?换得太勤怪群变成快闪轮打,玩家还是两头挨;换得太慢排岗退化成单挑另一只罚站,三秒刚好是"接岗的有威胁、歇岗的看得见"的节奏。
三、核心代码:完整模块(上·骨架)
-- @file ShiftDuty.lua
-- 轮岗纹 —— 两只怪轮着出手,总有一只在歇
local ShiftDuty = {}
local CONST = {
CREST_LIFE = 10.0,
CREST_CD = 4.0,
TURN_LIFE = 3.0,
COLOR_DUTY = "#588878",
COLOR_DEEP = "#1e3a2e",
COLOR_GHOST = "#b0d8c0",
ZORDER_DUTY = 133,
ZORDER_FX = 135,
AUTOINC_BASE = 1102000,
}
local _crestT = 0
local _cdLeft = 0
local _turnT = 0
local _dutyID = 0
local _restID = 0
local _crestFx = nil
local _scheduler = nil
local _autoInc = 0
local function GenID(prefix)
_autoInc = _autoInc + 1
return string.format("%s_%d", prefix or "SFD",
CONST.AUTOINC_BASE + _autoInc)
end
local function GetActorPos(id)
if not id then return nil end
local x = SL:GetValue("ACTOR_POSITION_X", id)
local y = SL:GetValue("ACTOR_POSITION_Y", id)
if not x or not y then return nil end
return { x = x, y = y }
end
local function SafeRemove(node)
if node and not GUI:Widget_IsNull(node) then
GUI:removeFromParent(node)
end
end
local function ShowTip(msg)
if msg and msg ~= "" then SL:ShowSystemTips(msg) end
end
function ShiftDuty.OnDuty(tid)
return _crestT > 0 and tid == _dutyID
end
function ShiftDuty.OnRest(tid)
return _crestT > 0 and tid == _restID
end
四、核心代码:完整模块(下·轮休判定与换岗钟)
-- 轮休判定:歇岗的那一只整只按住
SL:RegisterLUAEvent(LUA_EVENT_ACTION_CHECK, "SFD_Rest", function(tid)
if ShiftDuty.OnRest(tid) then
return false
end
return true
end)
-- 换岗钟:三秒一响,出手的去歇,歇着的接岗
local function ShiftTurn()
if not SL:GetValue("ACTOR_ALIVE", _restID) then
ShowTip("歇岗的那只倒了——岗白排了")
return
end
_dutyID, _restID = _restID, _dutyID
SL:TipAbove(_dutyID, "岗")
SL:TipAbove(_restID, "休")
SL:PlayShiftFx(_dutyID)
end
function ShiftDuty.Cast()
if _cdLeft > 0 or _crestT > 0 then return end
local tid = SL:GetValue("MARK_TARGET_ID")
if not tid then return end
local other = SL:FindNearMonster(tid, 300)
if not other then
ShowTip("就一只怪——排什么岗")
return
end
_cdLeft = CONST.CREST_CD
_crestT = CONST.CREST_LIFE
_turnT = CONST.TURN_LIFE
_dutyID = tid
_restID = other
SL:TipAbove(tid, "岗")
SL:TipAbove(other, "休")
SafeRemove(_crestFx)
_crestFx = GUI:Layout_Create(GUI:Attach_SceneF(),
GenID("Duty"), 0, 0, 0, 0, false)
GUI:setLocalZOrder(_crestFx, CONST.ZORDER_DUTY)
SL:PlayDutyUpFx(tid)
ShowTip("排岗了——一只出手一只歇,三秒一轮")
end
-- 定时器:纹成倒计时与换岗钟驱动
if not _scheduler then
_scheduler = SL:Schedule(function(dt)
_cdLeft = math.max(0, _cdLeft - dt)
if _crestT > 0 then
_crestT = _crestT - dt
_turnT = _turnT - dt
if _turnT <= 0 then
_turnT = CONST.TURN_LIFE
ShiftTurn()
end
local a = GetActorPos(_dutyID)
local b = GetActorPos(_restID)
if _crestFx and a and b then
GUI:setPosition(_crestFx,
(a.x + b.x) / 2, (a.y + b.y) / 2 - 140)
end
if _crestT <= 0 then
SafeRemove(_crestFx)
ShowTip("岗撤了——两只一齐扑上来了")
end
end
end, 0.02)
end
SL:ScheduleOnce(function()
SL:BindDebugButton("轮岗", function()
ShiftDuty.Cast()
end)
ShowTip("技能已加载: 轮岗纹 (调试按钮触发)")
end, 1.0)
function ShiftDuty.Unload()
if _scheduler then SL:Unschedule(_scheduler) end
SL:UnregisterLUAEvent(LUA_EVENT_ACTION_CHECK, "SFD_Rest")
SafeRemove(_crestFx)
_crestT = 0
end
return ShiftDuty
五、机制问答
问:歇岗的那只死了怎么办?
答:岗白排——换岗钟找不到接岗的,岗表当场作废,两只变一只的局排岗没有意义。
问:排岗期能引第三只怪进来吗?
答:进不了册——岗表只认开纹那一刻在册的两只,第三只是编外人员,照常出手,排岗前先清场。
问:换岗的瞬间两只都在出手怎么办?
答:打完这拍再换——换岗认的是下一次出手的许可,在途的那一爪不受岗表管辖,不会出现爪挥一半被收回。
问:歇岗的怪会走位吗?
答:不会——轮休是整只按住,脚步爪子一起停,它站的位置就是歇岗前的位置,三秒后从原地接岗。
问:排岗对头目有效吗?
答:无效——大体型的怪不吃岗表,说明栏写明"头目免排",能排的只有成对的小怪。
六、调参指南与商业服怎么用
第四笔是换岗的钟点:三秒一换对怪的出手间隔是"接岗即有威胁"的节奏——换得太快成快闪轮打,太慢另一只罚站太久,三秒是岗表的心跳。第三笔是轮休的深度:整只按住是满轮休——只按爪子不按脚步的半轮休版本,歇岗的怪贴着你转悠照样闹心,要歇就歇全的。第二笔是入册的口径:开纹那一刻在场的两只入册——半路进来的编外怪是排岗的漏,也是玩家利用的口子,口径要写死在说明里。第一笔是岗牌的可见:出手头顶"岗"、歇着头顶"休"——两块牌就是岗表的告示,玩家看牌就知道下一拍谁出手,预判有了落点。常见坑三个:歇岗判定漏了移动导致歇岗的怪照样贴脸;换岗钟在怪死亡后空转;岗牌跟画在怪被击退后飘到了半空。
商业服里轮岗纹是"武行班"的规矩:别人怕围殴,他给围殴的怪排班——商城里岗牌的样式做成品级,木牌、铜牌、武行金牌,那一对挂在怪头顶的岗休字牌就是武行班的班表。运营落地还有两笔:一段是排班教学——教一句"两只一起上不可怕,可怕的是你不会排班",流派第一课是立规矩;一段是排岗榜——按排岗期少挨的刀数排名,规矩立得最正的人有碑。变体做成三班倒:三只怪轮着出手——从两班倒到三班倒,武行班的班表越排越严。这一篇的演示和整套模块照抄能跑,改的就是 CONST 那张表。
写完留一句给做群控系的同学:轮岗纹卖的是"让它们排队"——那对挂在头顶的岗休字牌和三秒一响的换岗钟,是把围殴改写成轮流单挑的第一张班表。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
接手二开的兄弟几乎都撞过同一堵墙:玩家嫌走路"一格一格像机器人",老板拍板要"丝滑移动",改服务端速度?不对。改客户端动画帧…
【游戏功能】 先看一个熟场面:法师的火球特效挂在怪的脚后跟上,明明技能说明写着"焚烧其面",火星子却在地上打滚。群里有位策划…
【游戏功能】 上周有个开服的老板在群里发了一段录屏:他的战士明明刀刀都砍中了,观众却一片"这刀挥空了吧"。他原话是"判定日志…
【游戏功能】 先说结论放在开头:怪的皮一会儿绿一会儿红,不是美术换了几套贴图,是染色系统在怪身上盖了一层"色镜"。开服群里有…
前两天群里有个架设的朋友问了个需求:中毒的人要变绿、每两秒掉一次血、毒还能叠五层,问是不是要在服务端把整套状态机重写。我说你…
【游戏功能】 先抛一个坑:五口钟一模一样大,为什么一口比一口疼?先后次序动不得吗?倒过来敲会怎样?这篇把编钟纹整套写法拆开:…