CHUAN2 DEV ENGINE
996 正版授权研发中心 · 360 授权合作教学中心 · 抖音传奇直播合作授权 · 快手推广运营商授权
OFFICIAL LICENSED ACADEMY 查验官方授权证书 →
// 威海旷世互娱教学基地 · 技术文章
进阶实战游戏功能996引擎

蚀骨蛊:一层比一层深的毒,叠八层烧穿骨

2026-10-01 04:09 作者:996 技术组 996引擎Lua教程传奇脚本进阶实战游戏功能996引擎

【游戏功能】

叠层伤害到底该怎么叠?加法派一层加三点,十层才见真章;乘法派一层乘一成,三层就敢叫板——两种叠法写出来的完全是两个技能。今天拆的蚀骨蛊站在乘法派这一边:一蛊一层、一层活六秒、蛊毒一秒一跳,跳数等于层数乘三——八层满蛊的时候一秒二十四,比大多数普攻都疼。这篇的核心代码按引擎技能脚本的全规格走:配置表、蛊虫飞行构件、逐层到期的层表、定时器、调试按钮。

一、效果演示:八颗点,一条上坡

演示场点「下蛊!」,一枚紫蛊拖着尾线钉在怪身上,血条上方八颗层点亮起第一颗——每颗层点自带六秒的小倒计时,先叠的先到期。蛊毒一秒一跳:一层跳三、三层跳九、八层跳二十四,跳的数字一层比一层大,怪身上的紫色裂纹也一层比一层密。你的任务是按着按钮把八层全部喂上去——中途手停,层点一颗颗暗掉,跳数跟着一层层掉下来。演示里故意停手两秒再补蛊,看层点的到期和补层刷新在同一颗点上的接力——这套层表的手感全在那颗点里。

demo
 fx-bonerot

二、底层原理:一张逐层到期的层表加一条乘法跳

机制的账本是一张层表。每次命中往表里压一个六秒的倒计时对象,表长就是层数;每帧倒序扫表逐个减秒、到期出表;蛊毒的跳秒计时独立于层表——每一整秒结算一次,跳数等于当时的表长乘三。乘法跳是这套机制和加法系分家的地方:加法系的跳数恒定、层数只决定跳多久,玩家叠层的动力是"磨";乘法系的跳数跟着层数涨,玩家叠层的动力是"滚"——越叠每秒越疼,八层的一秒顶一层八秒。层各自到期是第三根柱子:新蛊压进来的新层救不了旧层,断蛊的惩罚是逐层掉、不是清盘,玩家掉一层补一层还能续命,清盘式的层表会让手残党直接弃疗。

三、核心代码:完整模块(上·骨架)

lua
--------------------------------------------------------------------------------
-- @file        BoneRot.lua
-- @brief       蚀骨蛊 —— 一层比一层深的毒,叠八层烧穿骨
--              客户端表现模块:配置表 / 层表 / 乘法跳结算 / 定时器
--------------------------------------------------------------------------------

local BoneRot = {}

--------------------------------------------------------------------------------
-- 配置与常量
--------------------------------------------------------------------------------
local CONST = {
    ROT_CAP       = 8,          -- 八层封顶
    ROT_LIFE      = 6.0,        -- 每层六秒
    ROT_TICK      = 1.0,        -- 一秒一跳
    DMG_PER_STACK = 3,          -- 每层跳三
    CAST_CD       = 2.2,        -- 下蛊冷却
    BUG_FLY       = 0.30,       -- 蛊虫飞行

    -- 颜色
    COLOR_ROT     = "#a371f7",  -- 蛊紫
    COLOR_DEEP    = "#4a2a7a",  -- 深紫
    COLOR_BONE    = "#e6edf3",  -- 骨白

    ZORDER_GROUND = 118,
    ZORDER_BUG    = 134,
    ZORDER_EFFECT = 135,

    AUTOINC_BASE  = 923000,
}

--------------------------------------------------------------------------------
-- 模块内部状态
--------------------------------------------------------------------------------
local _stacks   = {}            -- 层表:每个元素一个六秒倒计时
local _bugs     = {}            -- 飞行中的蛊虫
local _tickT    = 0             -- 跳秒计时
local _cdLeft   = 0
local _scheduler = nil
local _autoInc  = 0

local m_cos = math.cos
local m_sin = math.sin

--------------------------------------------------------------------------------
-- 辅助函数
--------------------------------------------------------------------------------
local function GenID(prefix)
    _autoInc = _autoInc + 1
    return string.format("%s_%d", prefix or "BRT", CONST.AUTOINC_BASE + _autoInc)
end

local function GetActorPos(actorID)
    if not actorID then return nil end
    local x = SL:GetValue("ACTOR_POSITION_X", actorID)
    local y = SL:GetValue("ACTOR_POSITION_Y", actorID)
    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 CreateRotBurst(x, y, stacks)
    local node = GUI:Layout_Create(GUI:Attach_SceneF(), GenID("Burst"), x, y, 0, 0, false)
    GUI:setLocalZOrder(node, CONST.ZORDER_EFFECT)
    local r = 18 + stacks * 2.5
    for i = 1, 12 do
        local a1 = (i - 1) / 12 * 6.28
        local a2 = i / 12 * 6.28
        GUI:DrawLine_Create(node, string.format("r_%d", i), 0, 0, 2,
            m_cos(a1) * r, m_sin(a1) * r * 0.4, m_cos(a2) * r, m_sin(a2) * r * 0.4,
            CONST.COLOR_ROT, 190)
    end
    GUI:runAction(node, GUI:ActionSequence(
        GUI:ActionFadeOut(0.32),
        GUI:CallFunc(function() SafeRemove(node) end)
    ))
end

骨架的三处定调。_stacks 是倒计时对象的数组而不是"层数加统一计时"——八层八个闹钟才是这套机制的账本,统一计时的版本补一层等于全员续命,乘法跳就成了永动。层点上限、层寿命、跳秒间隔、每层跳数四个数全在 CONST 表里互相牵制,改一个要心算另外三个。CreateRotBurst 的半径跟着层数走——命中光效一圈比一圈大,层数不用念,光圈自己会报数。

四、核心代码:完整模块(下·定时器与乘法跳)

lua
--------------------------------------------------------------------------------
-- 层表维护
--------------------------------------------------------------------------------
local function Rot_Apply()
    if #_stacks >= CONST.ROT_CAP then
        table.remove(_stacks, 1)          -- 满层挤掉最老的一层
    end
    table.insert(_stacks, CONST.ROT_LIFE)
    return #_stacks
end

local function Rot_Update(dt)
    for i = #_stacks, 1, -1 do
        _stacks[i] = _stacks[i] - dt
        if _stacks[i] <= 0 then
            table.remove(_stacks, i)      -- 到期的层自己散
        end
    end
end

local function Rot_DotTick(targetID)
    if #_stacks <= 0 then return end
    local vd = #_stacks * CONST.DMG_PER_STACK
    local tp = GetActorPos(targetID)
    if tp then
        SL:ActorHurt(targetID, vd)
        SL:TipAbove(targetID, "-" .. vd)
        if #_stacks >= 5 then
            SL:PlayBoneCrack(targetID, #_stacks)
        end
    end
end

--------------------------------------------------------------------------------
-- 蛊虫飞行与命中
--------------------------------------------------------------------------------
local function Bug_Update(bug, dt)
    local tp = GetActorPos(bug.targetID)
    if not tp then
        return false
    end
    bug.x = bug.x + (tp.x - bug.x) * math.min(1, 7 * dt)
    bug.life = bug.life - dt
    if math.abs(bug.x - tp.x) < 16 or bug.life <= 0 then
        local stacks = Rot_Apply()
        CreateRotBurst(tp.x, tp.y, stacks)
        SL:TipAbove(bug.targetID, "蛊" .. stacks .. "层")
        return false
    end
    return true
end

--------------------------------------------------------------------------------
-- 公共接口
--------------------------------------------------------------------------------
function BoneRot.Cast(myID, targetID)
    if _cdLeft > 0 then return end
    if #_stacks >= CONST.ROT_CAP then return end
    _cdLeft = CONST.CAST_CD
    local mp = GetActorPos(myID)
    if mp then
        table.insert(_bugs, { x = mp.x + 16, y = mp.y - 58, targetID = targetID,
            life = CONST.BUG_FLY * 3 })
    end
end

--------------------------------------------------------------------------------
-- 定时器与调试
--------------------------------------------------------------------------------
if not _scheduler then
    _scheduler = SL:Schedule(function(dt)
        _cdLeft = math.max(0, _cdLeft - dt)
        Rot_Update(dt)
        _tickT = _tickT + dt
        if _tickT >= CONST.ROT_TICK then
            _tickT = _tickT - CONST.ROT_TICK
            Rot_DotTick(SL:GetValue("MARK_TARGET_ID"))
        end
        for i = #_bugs, 1, -1 do
            if not Bug_Update(_bugs[i], dt) then
                table.remove(_bugs, i)
            end
        end
    end, 0.02)
end

SL:ScheduleOnce(function()
    ShowTip("技能已加载: 蚀骨蛊 (调试按钮触发)")
end, 1.0)

SL:RegisterLUAEvent(LUA_EVENT_ACTOR_DEAD, "BRT_Dead", function(data)
    if data and data.id == SL:GetValue("MARK_TARGET_ID") then
        _stacks, _bugs = {}, {}
    end
end)

return BoneRot

下半场的节拍器还是那条唯一的定时器,但它同时喂四张嘴:冷却、层表、跳秒、蛊虫——_tickT 这个跳秒累加器是乘法跳的心脏,攒满一秒放一次 Rot_DotTick,跳数现场数表长,层数在跳的瞬间是几就乘几,绝不用上一次的缓存。满层的挤法写在 Rot_Apply 里:挤掉最老的一层而不是拒绝新蛊,玩家的每一箭都有下落,账面不吞粮。死亡钩子把层表和虫表一次清空——怪死了蛊还活着追下一具尸体的版本,是层表模块最经典的闹鬼。

五、调参指南与商业服怎么用

调参先算一笔满蛊账:八层乘三是二十四一跳,八秒满蛊期理论产值一百九十二——把它和玩家十秒普攻产值对表,占四成上下是蛊系的甜区。层寿命六秒对下蛊冷却两点二秒是"手速合格线":合格的手能维持五层以上,不合格的在三到四层晃——层数曲线就是玩家操作水平的实时心电图。跳秒一秒是痛苦的可读周期,半秒一跳数字糊脸,两秒一跳蛊就没了牙。层点的到期顺序要和层表严格一致——先叠的先到期写在视觉上,玩家看层点就知道该补哪一颗。常见坑三个:满层挤旧层时忘了把对应特效的层点同步移位,账本和画面各说各话;死亡钩子只清了层表漏了飞行中的蛊,蛊追着尸体满天飞;跳秒计时没有在层表归零时复位,第一层新蛊要等上一次跳秒的剩余时间,首跳延迟半拍。

商业服里蚀骨蛊是"操作流"门派的招牌:装备垫底的手速党靠八层蛊打出装备党的伤害,操作的价值第一次有了跳数做证据。行会玩法里它是集火发令枪——指挥喊"蛊满",全队的爆发技能按八层那一秒齐射。变体做成蛊品阶:青蛊八层、血蛊十二层、蛊母叠完全场跳,一条层表养三档付费。江湖里它还是下毒流的身份证:八层蛊叠满的瞬间报出跳数,跳数就是这门手艺的段位。这一篇的演示和整套模块照抄能跑,改的就是 CONST 那张表。

写完留一句给做叠层系的同学:层表卖的是"每层都有名字"——层点的每一颗到期都清清楚楚,玩家的手速才有地方使。

作者履历与出处

本文由 996 技术组基于 996 引擎官方知识库与浮生梦老师课程体系整理。团队长期从事传奇类引擎 Lua 后端逻辑、客户端界面与商业版本交付,内容以官方知识库与真实项目为出处,按版本持续修订。

← 返回文章地图返回研学路径

幂尔框架 · 实战干货 · 接口调用

LATEST ARTICLES

全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →

进阶实战游戏功能

偷影:偷走它的影子,没了影子的怪刀都虚

【游戏功能】 if _shadowT 0 then spd = noShadow and 12 or 24 end ——一行…

2026-10-01 06:03 996 技术组
进阶实战游戏功能

魂卫:杀一葬一,魂火替你出手

【游戏功能】 魂卫的全机制就一句:杀掉小怪化一盏魂火跟着你走,每盏魂火两秒自动劈最近的大怪一口八点,至多三盏——「引魂!」按…

2026-10-01 06:03 996 技术组
进阶实战游戏功能

纸人替灾:贴一个纸人,下一道咒它替你挨

【游戏功能】 一道咒飞过来,硬吃是四秒里一秒十的钝疼——有没有第三条路?纸人替灾给的就是第三条路:贴一个纸人在身后,八秒里头…

2026-10-01 06:03 996 技术组
进阶实战游戏功能

水镜式:挨的刀存进镜里,连本带利还回去

【游戏功能】 挨打还能赚钱?水镜式的答案是:挨的刀七成存进镜里不扣血、三成照常疼,六秒后点「还镜」,存量乘一点五放成水炮——…

2026-10-01 06:03 996 技术组
进阶实战游戏功能

弹反镜:架起一面镜,箭从哪来回哪去

【游戏功能】 if _mirrorT 0 then SL:TipAboveMe("免疫") return end ——一道写…

2026-10-01 06:03 996 技术组
进阶实战游戏功能

缩地阵:圈越缩越小,逼它和你贴身

【游戏功能】 远近战的矛盾怎么解?远战的答案是把怪挡在射程外,近战的答案是把人拖进射程内——缩地阵给的第三个答案最蛮横:圈只…

2026-10-01 06:03 996 技术组