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

同归爆:烧到只剩一口气,炸它一整片

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

【游戏功能】

数值组复盘过一场灭团:全队血量健康、输出达标,灭在头目百分之五的血线上——事后逐帧回放,答案是一发没人喊过的同归爆:战士把两千血烧到剩一,一口气炸出一整片六千,怪倒了,他也倒在了下一拍的普攻里。指挥的复盘里只写下了一句:这一发,该喊的。今天这篇拆同归爆——把血当炸药点的机制,代码照引擎技能脚本的全规格来,一节不缺。

一、效果演示:一秒点火,半屏清账

演示场点「同归!」:玩家脚下先炸开一圈红圈预警——一秒的点火期,红圈一圈圈收拢,火粒往身上卷;点火结束的瞬间,整条血烧到剩一,烧掉多少血就按三倍炸出去:三百血炸九百,半屏之内的大怪直接吃满,震屏、闪红、双层冲击环全套伺候。炸完的你只剩一口血、周身发红发虚——大怪的下一记普攻都可能是最后一根稻草。演示里可以试两种血量点火:满血点火炸九百但接下来的仗步步惊心,压到半血点火炸四百五、炸完还能打——什么时候点火,就是这门爆发的全部算术——早了亏杠杆,晚了没命点。

demo
 fx-lastblaze

二、底层原理:一条点火通道加一次血雷换算

模块的机关是三段。点火段:一秒的预热通道,通道里玩家不可移动、红色预警圈画给所有人看——同归爆不是瞬发,点火期是给队友的信号、也是给玩家的反悔窗(本模块的反悔窗做成了不可退:点了就炸,狠就狠在这里)。换算段:通道结束时读当前血量,烧到剩一,烧掉的差额乘三就是伤害——乘三是这套机制的杠杆,杠杆的高低直接决定它是一场仗的底牌还是常规输出。清算段:炸出的范围伤害按距离全额给主目标,玩家自己进入"虚脱态"——血上限不发虚、但被怪的普攻一碰就见底。三段共用模块唯一的一条定时器节拍,点火、清算、虚脱三本账不并表,各走各的分段。

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

lua
--------------------------------------------------------------------------------
-- @file        LastBlaze.lua
-- @brief       同归爆 —— 烧到只剩一口气,炸它一整片
--              客户端表现模块:配置表 / 预警圈构件 / 血雷换算 / 定时器
--------------------------------------------------------------------------------

local LastBlaze = {}

--------------------------------------------------------------------------------
-- 配置与常量
--------------------------------------------------------------------------------
local CONST = {
    FUSE_LIFE     = 1.0,        -- 点火一秒
    BLAZE_CD      = 15.0,       -- 冷却十五秒
    LEFT_HP       = 1,          -- 炸完剩一
    BLAZE_RATE    = 3.0,        -- 烧一炸三
    BLAZE_RADIUS  = 160,        -- 半屏火圈

    -- 颜色
    COLOR_BLAZE   = "#f85149",  -- 烈焰
    COLOR_DEEP    = "#7a1d1d",  -- 余烬
    COLOR_FLASH   = "#ffe08a",  -- 爆白

    ZORDER_GROUND = 118,
    ZORDER_WARN   = 119,
    ZORDER_EFFECT = 135,

    AUTOINC_BASE  = 929000,
}

--------------------------------------------------------------------------------
-- 模块内部状态
--------------------------------------------------------------------------------
local _fuseT     = 0              -- 点火余时
local _cdLeft    = 0
local _burning   = false
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 "LBZ", CONST.AUTOINC_BASE + _autoInc)
end

local function GetMyPos()
    local x = SL:GetValue("ACTOR_POSITION_X", SL:GetValue("USER_ID"))
    local y = SL:GetValue("ACTOR_POSITION_Y", SL:GetValue("USER_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 CreateWarnRing()
    local mp = GetMyPos()
    if not mp then return end
    local node = GUI:Layout_Create(GUI:Attach_SceneF(), GenID("Warn"),
        mp.x, mp.y - 30, 0, 0, false)
    GUI:setLocalZOrder(node, CONST.ZORDER_WARN)
    for i = 1, 36 do
        local a1 = (i - 1) / 36 * 6.28
        local a2 = i / 36 * 6.28
        GUI:DrawLine_Create(node, string.format("w_%d", i), 0, 0, 3,
            m_cos(a1) * CONST.BLAZE_RADIUS, m_sin(a1) * CONST.BLAZE_RADIUS * 0.4,
            m_cos(a2) * CONST.BLAZE_RADIUS, m_sin(a2) * CONST.BLAZE_RADIUS * 0.4,
            CONST.COLOR_BLAZE, 180)
    end
    GUI:setScale(node, 1.0)
    GUI:runAction(node, GUI:ActionSequence(
        GUI:ActionScaleTo(CONST.FUSE_LIFE, 0.12, 0.12),
        GUI:CallFunc(function() SafeRemove(node) end)
    ))
    return node
end

骨架的三处立规。_burning 布尔加 _fuseT 倒计时成对出现——点火期的一切判定先查布尔再查余时,两个都查的版本永远不会在点火中途再点一次火。预警圈的收缩用动作序列的 ActionScaleTo 直接从一缩到零点一二——圈收拢的速度就是倒计时,玩家读圈比读数字快。BLAZE_RATE 用三不用二:二倍的杠杆配十五秒冷却,机制会沦为常规输出;三倍加"剩一口"的代价,它才是一场仗只有一发的那声雷。

四、核心代码:完整模块(下·定时器与血雷换算)

lua
--------------------------------------------------------------------------------
-- 点火与清算
--------------------------------------------------------------------------------
local function Blaze_Ignite(warnBag)
    _burning = true
    _fuseT = CONST.FUSE_LIFE
    warnBag[#warnBag + 1] = CreateWarnRing()
    ShowTip("点了——一秒后炸,半屏都是火")
end

local function Blaze_Detonate(targetID)
    local myID = SL:GetValue("USER_ID")
    local hp = SL:GetValue("ACTOR_HP", myID)
    local spent = (hp or 0) - CONST.LEFT_HP
    if spent <= 0 then
        _burning = false
        return
    end
    SL:SetHp(myID, CONST.LEFT_HP)
    local vd = math.round(spent * CONST.BLAZE_RATE)
    local mp = GetMyPos()
    local tp = GetActorPos(targetID)
    if tp and mp and math.abs(tp.x - mp.x) <= CONST.BLAZE_RADIUS then
        SL:ActorHurt(targetID, vd)
        SL:TipAbove(targetID, "-" .. vd)
    end
    SL:PlayBlazeBurst(mp.x, mp.y)
    SL:ScreenShake(7, 0.42)
    SL:EnterWeakState(myID, CONST.BLAZE_CD)
    ShowTip("炸了" .. vd .. "——你现在比它先脆,撤着打")
    _burning = false
end

--------------------------------------------------------------------------------
-- 公共接口
--------------------------------------------------------------------------------
function LastBlaze.Cast(targetID, warnBag)
    if _cdLeft > 0 or _burning then return end
    local hp = SL:GetValue("ACTOR_HP", SL:GetValue("USER_ID"))
    if not hp or hp <= 30 then
        ShowTip("血不够烧——留着这口喘气")
        return
    end
    Blaze_Ignite(warnBag)
    SL:ScheduleOnce(function()
        Blaze_Detonate(targetID)
    end, CONST.FUSE_LIFE)
end

--------------------------------------------------------------------------------
-- 定时器与调试
--------------------------------------------------------------------------------
if not _scheduler then
    _scheduler = SL:Schedule(function(dt)
        _cdLeft = math.max(0, _cdLeft - dt)
    end, 0.02)
end

SL:RegisterLUAEvent(LUA_EVENT_ACTOR_DEAD, "LBZ_Dead", function(data)
    if data and data.id == SL:GetValue("USER_ID") and _burning then
        _burning = false
    end
end)

SL:ScheduleOnce(function()
    ShowTip("技能已加载: 同归爆 (调试按钮触发)")
end, 1.0)

return LastBlaze

下半场的清算链是全模块的雷管:Blaze_Detonate 的顺序是读血、烧血、算雷、落雷、进虚脱——五步一步都不能换,先落雷后烧血的版本玩家能炸出不属于自己的血。点火的延时清算挂 ScheduleOnce 一条延时任务,点火一秒到点即炸——把清算写在模块定时器的分支里也可以,但延时任务让"点火"和"炸"在代码上隔着一整段,想改引信只动一处。死亡钩子把燃烧旗标按灭——点火期被怪的刀先撂倒,雷就不响了,人死账清。

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

调参的雷管在三处。乘三是杠杆的甜区:烧三百炸九百,一发顶三十秒普攻——杠杆拉到四倍以上,玩家会刻意养血不点,机制变成挂在墙上的装饰;两倍以下,没人值得为它烧到剩一。点火一秒是勇气的成本:瞬发的同归是逃生技的反面教材,两秒的点火又长到怪必然打断——一秒卡在"反应得过来、犹豫来不及"的窄缝里。剩一口的虚脱态要配一条退出通道——药水、治疗、脱战回血都行,没有退出通道的虚脱态就是判死刑。常见坑三个:点火期玩家死亡,雷按原计划炸出,死人放雷的账面成了笑话;虚脱态没有视觉标注,队友不知道该护着谁;血量刚好剩一的时候点火,零差额的雷空响一声。点火期的移动封锁也要在演示里演明白——红圈收拢的那一秒里玩家的位移键是灰的,这秒的不能动就是引信的分量。

商业服里同归爆是"热血时刻"的制造商:世界头目战的最后一成血,全场同归爆齐鸣的那一帧就是宣传片的截帧。行会攻城里它是破门队员的勋章——烧光自己炸开城门,战报里这行永远加粗。变体做成血雷品级:下品乘二点五、上品乘四,血雷的定价就是玩命的价格。这一篇的演示和整套模块照抄能跑,要改的就是 CONST 那一张表。

写完留一句给做爆发系的同学:同归卖的是"最后一发"的分量——血雷的换算写在明处,玩家点火的每一根手指才有底气。

作者履历与出处

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

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

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

LATEST ARTICLES

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

进阶实战游戏功能

剑环:三柄飞剑绕着转,贴身就挨削

【游戏功能】 安全巡检扫出一笔可疑的挂账:玩家的"周围单位结算"列表里,同一只怪每零点八秒出现一次,可战斗记录里玩家根本没出…

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

困灵阵:画个圈关住它,出圈的腿会疼

【游戏功能】 困灵阵的全机制就一句:阵落在它脚下,八秒里它就是圈中之物——敢跨出圈沿,一步吃十五还被弹回去,你在圈外安安稳稳…

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

火油阵:先泼油再点灯,两步烧一条线

【游戏功能】 先泼油还是先点火?这道题答错的代价是一地白烧的火——灯点在空地上,怪还没踩上来,四秒的火一点没沾着它的毛。火油…

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

冰壁垒:一堵墙横在地上,谁也过不去

【游戏功能】 寻路组收到一笔诡异的工单:怪物巡逻到某个坐标段必卡三秒,像踩了看不见的门槛——排查两小时,发现那段路上有一个上…

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

双桩雷阵:两桩立起来,桩间就是雷区

【游戏功能】 local a, b = math.min(x1, x2), math.max(x1, x2) ——一行把两根…

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

镇魂碑:立碑镇住它,大招读不完

【游戏功能】 测试组报过一口邪门的单:头目的读条明明被打断过,技能照样出了膛——查了半天不是打断失效,是打断只"清了"不"冻…

2026-10-01 05:08 996 技术组