【游戏功能】
上一版留了个只在你自己的房间里能复现的怪事:双生纹在怪倒下的那一帧偶尔整个消失——不跳、不报错、日志干净。翻了三天才逮到:怪的死亡判定和纹的跳迁判卡在同一帧里跑,死亡先把目标清了,纹的跳迁再找目标时手里攥着个空,纹就跟着尸体一起灭了。修法是把跳迁判提到死亡结算的同一拍之前——机制没错,是帧序错了。这篇把双生纹整套模块拆开:配置表、纹的驻留、死亡监听、跳迁结算、帧序修正、定时器、调试按钮,一段一段照抄能跑。
一、效果演示:纹不随尸灭,跳去下一只
演示场先来一只怪。点「跳纹!」:一枚血红的三角纹烙在它头顶——十二秒的驻留期。把这只怪打死,倒地的那一拍纹没有跟着消失——血光一闪,纹跳到了远处第二只怪头上,驻留期接着走。再把第二只也打死,这一拍纹左右张望发现没处可跳——当场熄灭。演示里试两笔账:一枚纹管两只怪的账,和每只怪单独烙纹的账——跳一次省一次的手续。双生纹教的是连坐:纹认的是"这一窝",不是"这一只"。
fx-twinjump
二、底层原理:一道死亡监听加一次跳迁结算
模块的机关是一对搭档。死亡监听:纹驻留期里盯着当前宿主的存活位——宿主一倒,监听当场触发,这就是那次"纹随尸灭"事故里缺失的第一环:监听必须挂在死亡结算完成之前。跳迁结算:触发的那一拍在搜索圈里找下一只活怪——找得到就把纹搬过去,驻留期原封不动接着走;找不到纹就地熄灭。和标记类机制的分野在"双生纹的宿主是可变的":普通标记烙死在一只怪身上,死了就完了;双生纹的纹是活的,宿主只是它暂时落脚的地方——纹属于这场仗,不属于哪一只怪。
跳迁为什么保留剩余时长而不是重置?重置的版本一枚纹能无限接力,猎杀节奏一快纹就永动;保留时长的版本跳一次短一截——你杀得越快纹剩得越少,猎手的效率上限被时长这根缰绳拴着,连坐有账可算。
三、核心代码:完整模块(上·骨架)
-- @file TwinJump.lua
-- 双生纹 —— 纹不随尸灭,跳去下一只
local TwinJump = {}
local CONST = {
CREST_LIFE = 12.0,
CREST_CD = 4.0,
SEARCH_RANGE = 400,
COLOR_JUMP = "#b85868",
COLOR_DEEP = "#481828",
COLOR_GHOST = "#f0c0c8",
ZORDER_JUMP = 133,
ZORDER_FX = 135,
AUTOINC_BASE = 1087000,
}
local _crestT = 0
local _hostID = 0
local _cdLeft = 0
local _crestFx = nil
local _scheduler = nil
local _autoInc = 0
local function GenID(prefix)
_autoInc = _autoInc + 1
return string.format("%s_%d", prefix or "TNJ",
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
local function HostAlive()
return _hostID ~= 0
and SL:GetValue("ACTOR_ALIVE", _hostID)
end
四、核心代码:完整模块(下·死亡监听与跳迁结算)
-- 跳迁结算:宿主倒下的同一拍找下一只
local function TryJump()
if _crestT <= 0 or HostAlive() then return end
local next = SL:FindNearMonster(_hostID, CONST.SEARCH_RANGE)
SafeRemove(_crestFx)
if not next then
ShowTip("纹没处跳了——跟着这只一起灭了")
_crestT = 0
_hostID = 0
return
end
SL:PlayJumpOutFx(_hostID)
_hostID = next
SL:PlayJumpInFx(next)
_crestFx = GUI:Layout_Create(GUI:Attach_SceneF(),
GenID("Crest"), 0, 0, 0, 0, false)
GUI:setLocalZOrder(_crestFx, CONST.ZORDER_JUMP)
ShowTip("纹跳走了——落到下一只头上")
end
SL:RegisterLUAEvent(LUA_EVENT_MONSTER_DEAD, "TNJ_Jump",
function(deadID)
if deadID == _hostID then TryJump() end
end)
function TwinJump.Cast()
if _cdLeft > 0 or _crestT > 0 then return end
local tid = SL:GetValue("MARK_TARGET_ID")
if not tid then return end
_cdLeft = CONST.CREST_CD
_crestT = CONST.CREST_LIFE
_hostID = tid
SafeRemove(_crestFx)
_crestFx = GUI:Layout_Create(GUI:Attach_SceneF(),
GenID("Crest"), 0, 0, 0, 0, false)
GUI:setLocalZOrder(_crestFx, CONST.ZORDER_JUMP)
SL:PlayCrestMarkFx(tid)
ShowTip("双生纹烙上了——它死了纹就跳下一只")
end
-- 定时器:驻留倒计时与纹的跟脚
if not _scheduler then
_scheduler = SL:Schedule(function(dt)
_cdLeft = math.max(0, _cdLeft - dt)
TryJump()
if _crestT > 0 and _hostID ~= 0 then
_crestT = _crestT - dt
local hp = GetActorPos(_hostID)
if _crestFx and hp then
GUI:setPosition(_crestFx, hp.x, hp.y - 162)
end
if _crestT <= 0 then
SafeRemove(_crestFx)
ShowTip("纹光散了——没等到下一只")
end
end
end, 0.02)
end
SL:ScheduleOnce(function()
SL:BindDebugButton("跳纹", function()
TwinJump.Cast()
end)
ShowTip("技能已加载: 双生纹 (调试按钮触发)")
end, 1.0)
function TwinJump.Unload()
if _scheduler then SL:Unschedule(_scheduler) end
SL:UnregisterLUAEvent(LUA_EVENT_MONSTER_DEAD, "TNJ_Jump")
SafeRemove(_crestFx)
_crestT = 0
end
return TwinJump
五、机制问答
问:跳迁会保留剩余时长吗?
答:保留——纹跳过去带走的是没走完的驻留期,不重置不续命,你杀得越快纹剩得越少,连坐的效率有上限。
问:第二只怪在搜索圈外怎么办?
答:纹就地熄灭——搜索圈是跳迁的射程,圈外无宿主,纹跟着旧宿主一起灭,不隔空跳、不提前挂起。
问:跳迁会选中头目吗?
答:会——纹认活怪不认体重,跳到头目身上照样驻留,这对猎手是福利也是陷阱:头目的血配剩余的短时长,往往跳过去就散。
问:两只怪同帧死亡纹跳谁?
答:谁都不跳——同帧双杀没有"下一只"的单数答案,纹直接熄灭,这种极端局按没有同伴处理。
问:纹驻留期的宿主被驱散清纹怎么办?
答:清不掉——双生纹不是挂在怪身上的增益,是挂在战场上的活纹,净化剥的是怪的好处,动不了纹本身。
六、调参指南与商业服怎么用
第四笔是搜索圈的半径:四百步是"这一窝"的口径——圈太小两只怪站位稍开就断链,圈太大纹会跳到八竿子打不着的远处怪身上,演出和仇恨全乱。第三笔是驻留的总长:十二秒对两场小架是"够走一跳"的预算——太短纹撑不到第一次跳,太长变成整场常驻。第二笔是跳迁的帧序:跳迁判必须压在死亡结算的同拍之前——那场"纹随尸灭"的怪事就是帧序错了,机制写对帧写错照样翻车。第一笔是跳的演出:旧宿主身上的血光和新宿主身上的落纹要一先一后——跳要有方向感,玩家得看得出纹是"从哪跳到了哪"。常见坑三个:跳迁后纹环的跟脚还是旧宿主的坐标飘在尸体上方;同帧双杀的判定走了先到先得导致另一只怪头上挂着幽灵纹;驻留到期和宿主死亡同帧的双重结算把纹熄了两次。
商业服里双生纹是"猎户庄"的连坐契:别人的纹管一只,他的纹管一窝——商城里三角纹的样式做成品级,麻纹、银纹、赤金纹,那枚在怪群头顶跳来跳去的血红三角就是猎户庄的箭靶。运营落地还有两笔:一段是聚怪教学——教一句"把这一窝引到一处,一枚纹管到底",流派第一课是赶山;一段是连坐榜——按一枚纹消灭的怪数排名,一纹串三只的人挂碑。变体做成三生纹:纹可连跳两次——从一纹两怪到一纹三怪,猎户庄的箭越来越长。这一篇的演示和整套模块照抄能跑,改的就是 CONST 那张表。
写完留一句给做标记系的同学:双生纹卖的是"纹比命长"——那枚在怪群头顶跳来跳去的三角,是把标记从贴纸改成活物的一场驯化。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
接手二开的兄弟几乎都撞过同一堵墙:玩家嫌走路"一格一格像机器人",老板拍板要"丝滑移动",改服务端速度?不对。改客户端动画帧…
【游戏功能】 先看一个熟场面:法师的火球特效挂在怪的脚后跟上,明明技能说明写着"焚烧其面",火星子却在地上打滚。群里有位策划…
【游戏功能】 上周有个开服的老板在群里发了一段录屏:他的战士明明刀刀都砍中了,观众却一片"这刀挥空了吧"。他原话是"判定日志…
【游戏功能】 先说结论放在开头:怪的皮一会儿绿一会儿红,不是美术换了几套贴图,是染色系统在怪身上盖了一层"色镜"。开服群里有…
前两天群里有个架设的朋友问了个需求:中毒的人要变绿、每两秒掉一次血、毒还能叠五层,问是不是要在服务端把整套状态机重写。我说你…
【游戏功能】 先抛一个坑:五口钟一模一样大,为什么一口比一口疼?先后次序动不得吗?倒过来敲会怎样?这篇把编钟纹整套写法拆开:…