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

掠影:突进留影线,影子替你守三秒

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

【游戏功能】

突进的遗产是什么?多数突进留的是残影——好看,但不伤人。掠影给残影装了牙:突进穿身二十,身后留一道三秒的影线,线上一秒十、谁过谁挨——你的走位从这一刻起是地图的一部分。这篇的核心代码照引擎技能脚本的全规格写:配置表、影线构件、线段判定、定时器、调试按钮。

一、效果演示:穿身二十,影线三秒

演示场点「掠影!」:玩家化作一道蓝白残影穿过大怪——穿身的中点炸出二十的数字;落地的同时,从起手点到落点拉起一道半透明的蓝白影线,头顶挂出"影线 三秒"。怪回身追你,追的路上正好横穿影线——一秒十的扣数跟着它的脚步一路跳。三秒影散,线上干干净净。演示里试两个走法:把怪引到影线正中再突进,它一来一回横穿两趟;或者贴着影线边缘站桩输出——影线的存在改变了它追你的路线,改线就是控场——你走过的路成了它绕不开的税,影线的三秒就是税单的期限。改线就是控场——你走过的路成了它绕不开的税,影线的三秒就是税单的期限。掠影的落点也写在机制里——穿身停在怪身后七十步,落点、起手点、怪的位置三点连线,影线自动变成一道拦在怪撤退路上的闸。

demo
 fx-shadowline

二、底层原理:一段区间记录加一份线段跳表

模块的账本是一段区间配一张跳表。区间侧:突进起手与落点两个横坐标记成一段区间,落点定型的瞬间区间入表——影线的地理就是这两个数字。跳表侧:每秒醒一次,查怪的横坐标是否落在任一影线的区间内——落在线上跳十、线外不动。和地刺的分野在生成方式上:地刺的线是技能画出来的固定几何,影线的线是玩家突进"跑"出来的——线的位置等于玩家上一秒的走位,地图的改写权在脚下。地图的改写权在脚下。影线的重叠规则也要交代:两条影线十字相交,交叠区一秒二十——玩家自己布的交叉阵自己受益,走位的历史第一次可以复利。影线三秒到期自动出表——三秒的寿命让影线是"临时的沟",不是永久的墙。

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

lua
--------------------------------------------------------------------------------
-- @file        ShadowLine.lua
-- @brief       掠影 —— 突进留影线,影子替你守三秒
--              客户端表现模块:配置表 / 影线构件 / 区间跳表 / 定时器
--------------------------------------------------------------------------------

local ShadowLine = {}

--------------------------------------------------------------------------------
-- 配置与常量
--------------------------------------------------------------------------------
local CONST = {
    LINE_LIFE     = 3.0,        -- 影线三秒
    LINE_CD       = 6.0,        -- 掠影冷却
    FLY_LIFE      = 0.36,       -- 突进零点三六秒
    PASS_DMG      = 20,         -- 穿身二十
    LINE_DPS      = 10,         -- 线上一秒十
    STOP_OFFSET   = 70,         -- 穿身停在身后七十步

    -- 颜色
    COLOR_LINE    = "#9ab8e8",  -- 掠影蓝
    COLOR_DEEP    = "#2a3a6e",  -- 深蓝
    COLOR_GHOST   = "#dce8fa",  -- 影白

    ZORDER_GROUND = 118,
    ZORDER_LINE   = 120,
    ZORDER_EFFECT = 135,

    AUTOINC_BASE  = 957000,
}

--------------------------------------------------------------------------------
-- 模块内部状态
--------------------------------------------------------------------------------
local _lines     = {}            -- 影线表
local _flyT      = 0             -- 突进余时
local _flyFrom   = 0
local _flyTo     = 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 "SHL", 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 CreateLineNode(x1, x2)
    local node = GUI:Layout_Create(GUI:Attach_SceneF(), GenID("Line"),
        math.min(x1, x2), 0, 0, 0, false)
    GUI:setLocalZOrder(node, CONST.ZORDER_LINE)
    local w = math.abs(x2 - x1)
    for i = 0, math.floor(w / 24) do
        GUI:DrawLine_Create(node, "seg_" .. i, 0, 0, 10, i * 24, 0, i * 24 + 18, 0,
            CONST.COLOR_LINE, 120)
    end
    return node
end

骨架的三处立规。影线表存区间不存逐格——一段两个数字,判定一次区间比较,逐格铺判定的版本格子一多跳表就肿。影线构件按二十四步一段的分段横线铺——分段的光带比整条光带更像"影子拖过的痕"。落点停在怪的身后七十步——穿身的定义是"从它身上过",停在脸上是撞人不是掠影。

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

lua
--------------------------------------------------------------------------------
-- 掠影突进
--------------------------------------------------------------------------------
function ShadowLine.Cast()
    if _cdLeft > 0 or _flyT > 0 then return end
    local mp = GetActorPos(SL:GetValue("USER_ID"))
    local tp = GetActorPos(SL:GetValue("MARK_TARGET_ID"))
    if not mp or not tp then return end
    _cdLeft = CONST.LINE_CD
    _flyT = CONST.FLY_LIFE
    _flyFrom = mp.x
    _flyTo = tp.x + CONST.STOP_OFFSET
    ShowTip("掠出去——穿身二十,影线留三秒")
end

--------------------------------------------------------------------------------
-- 影线的跳表结算
--------------------------------------------------------------------------------
local function Lines_Tick(tid, tp)
    for i = 1, #_lines do
        local ln = _lines[i]
        if tp.x > ln.x1 and tp.x < ln.x2 then
            SL:ActorHurt(tid, CONST.LINE_DPS)
            SL:TipAbove(tid, "-" .. CONST.LINE_DPS)
            return
        end
    end
end

--------------------------------------------------------------------------------
-- 定时器:突进推进与跳表
--------------------------------------------------------------------------------
if not _scheduler then
    _scheduler = SL:Schedule(function(dt)
        _cdLeft = math.max(0, _cdLeft - dt)
        local mp = GetActorPos(SL:GetValue("USER_ID"))
        if _flyT > 0 then
            _flyT = _flyT - dt
            local k = 1 - math.max(0, _flyT) / CONST.FLY_LIFE
            SL:FlyActorTo(_flyFrom + (_flyTo - _flyFrom) * k)
            if k >= 0.5 and not _struck then
                _struck = true
                local tid = SL:GetValue("MARK_TARGET_ID")
                local tp = tid and GetActorPos(tid)
                if tp and math.abs(tp.x - SL:GetValue("ACTOR_POSITION_X", SL:GetValue("USER_ID"))) < 60 then
                    SL:ActorHurt(tid, CONST.PASS_DMG)
                    SL:TipAbove(tid, "-" .. CONST.PASS_DMG)
                end
            end
            if _flyT <= 0 then
                local node = CreateLineNode(_flyFrom, _flyTo)
                table.insert(_lines, { x1 = math.min(_flyFrom, _flyTo),
                    x2 = math.max(_flyFrom, _flyTo), t = CONST.LINE_LIFE, node = node })
            end
            return
        end
        for i = #_lines, 1, -1 do
            _lines[i].t = _lines[i].t - dt
            if _lines[i].t <= 0 then
                SafeRemove(_lines[i].node)
                table.remove(_lines, i)
            end
        end
        local tid = SL:GetValue("MARK_TARGET_ID")
        local tp = tid and GetActorPos(tid)
        if tp then
            Lines_Tick(tid, tp)
        end
    end, 0.02)
end

SL:RegisterLUAEvent(LUA_EVENT_SCENE_CLEAR, "SHL_Clear", function()
    for i = #_lines, 1, -1 do SafeRemove(_lines[i].node) end
    _lines = {}
end)

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

return ShadowLine

下半场的跳表一次只结算一条线——怪的横坐标落在两段重叠影线的交叠区也只扣一次,return 在首个命中后即出,双线交叠的重复扣血就是这段代码防住的事。突进落点的入表写在飞完的那一帧——影线从落点定型的瞬间开始计时,飞行的途中不占表,三秒的寿命不偷跑。

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

调参三笔账。线上一秒十对穿身二十是"过一次顶两跳"的账——穿身的即时报酬要高于线上白站,玩家才有动力去穿而不是去站;调换过来影线就变成站桩光环。影线三秒对掠影冷却六秒是半程覆盖——冷却减半的版本场上一半是影线,怪的走位彻底被玩家的历史走位殖民。停点身后七十步对怪的攻击距离三十步是安全的穿身落点——停得太近穿身变成送背,太远回程支援慢。常见坑三个:影线区间没做正序整理,反身掠影的区间左右颠倒判定失效;跳表逐线扫描不做去重,交叠双线双倍扣;影线与玩家的自身忽略没写,自己过自己的线也挨扣。

商业服里掠影是"走位美学"的放大器:影线的颜色按职业谱系卖——蓝影刺客、红影狂刀、金影剑圣,走位的轨迹成了职业的签名。据点战里它是控路口的地基:两条交叉的影线守一个补给点,交叉区的重叠伤害就是路口的税。变体做成影线共鸣:两条影线十字相交时交叠区伤害翻倍——玩家自己布的十字阵就是自己的杀阵。这一篇的演示和整套模块照抄能跑,改的就是 CONST 那张表。

写完留一句给做轨迹系的同学:掠影卖的是"走过的路会咬人"——你上一秒的走位成为它下一秒的禁区,地图从此记得你来过。地图从此记得你来过。影线的透明度随寿命衰减——三秒的线从亮到暗一步步淡出,淡出的过程就是倒计时,比读秒的数字更直觉。

作者履历与出处

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

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

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

LATEST ARTICLES

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

进阶实战游戏功能

影锁:影锁绑你绑它,锁期拼刀

【游戏功能】 控制技能的镜像问题是:锁住了怪,自己是不是也闲着?影锁把这道两难摆上台面:影锁四秒,它动不了、你也动不了——它…

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

震魂:震魂入体叠加出招自损

【游戏功能】 打断为什么只有"清读条"一种?震魂偏要反过来——不清招、不断势,打在它读条半途的那一劲顺着招震进腑——中劲十秒…

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

蜂王:喂小怪蜂王进化,三阶蜂王蜇翻全场

【游戏功能】 蜂群为什么总是一只一只出?蜂王偏要让它们进化:放一只蜂王出来,杀掉小怪喂它——喂三只升一阶,三阶蜂王的毒刺一秒…

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

血刃:每刀扣血换吸血,血刀双刃

【游戏功能】 技能为什么总是不扣自己的血?血刃偏要反着来:开着血刃的每一刀先扣自己二血、命中回三血——净赚一但要打得中,空刀…

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

破军旗:旗立三秒圈内加攻,旗倒攻散

【游戏功能】 bn.t = bn.t - dt ——一行旗面倒计时的代码,撑起了破军旗全部的紧迫感:旗立三秒、圈内加攻三成,…

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

淬毒刃:淬毒三刀叠一层,一层毒过一秒六

【游戏功能】 淬毒为什么要一毒到底?淬毒刃偏要一层一层叠:一刀淬一层毒、毒层一秒六地烂,六层封顶之后一刀下去毒伤三十六——叠…

2026-10-01 10:00 996 技术组