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

燕回式:突进穿它一遭,原路飞回起手点

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

【游戏功能】

突进出去了,回不回得来?多数突进的答案是"不回"——人留在怪堆里听天由命。燕回式给突进装了归途:穿身而过去时一刀二十五,悬半拍,原路飞回起手点再补十五——来去两程都是刀,起手点就是落脚点。这篇的核心代码照引擎技能脚本的全规格写:配置表、燕返构件、三段飞行状态机、定时器、调试按钮。

一、效果演示:去一刀,回一刀

演示场点「燕回!」:玩家化作一道残影向怪穿身而过——穿身的瞬间二十五的大字炸开,残影一路拖到怪身后六十步处悬停;残影一路拖到怪身后六十步处悬停——悬停点的青环亮起就是"该回了"的路标;悬停的半拍里脚下亮起一圈返航的青环;随即原路飞回,回程再补十五,落回起手的那块地——从头到尾位移清零,账面却多了四十。演示里注意两处:悬停的半拍是留给怪的攻击空档,站得准的玩家连它抬手都躲过;回程的路线和去程完全重合——同一片残影走两遍,燕回的味道就在这条重叠的线上。燕回的味道就在这条重叠的线上。两程的刀色也要分——去程的主刀青白、回程的补刀淡青,去重回轻写在颜色里。同一片残影走两遍,燕回的味道就在这条重叠的线上。残影的密度也要分层——去程三影、回程四影,回程多一层影,回头的决心才看得见。

demo
 fx-returnfly

二、底层原理:一台三段飞行状态机加一个原点锚

模块的机关是一台三段状态机配一枚锚。去程段:从起手点向穿身点匀速推进、每帧掉残影、过身即结算去程伤害;悬停段:零点四秒的原地定格,脚下亮返航环——这半拍既是演出也是节奏的呼吸口;回程段:从穿身点向原点锚飞回、结算回程伤害、落地清状态。原点锚是全模块的筋骨:起手的坐标在按下按钮那一刻写进锚里,回程的目标永远读锚不读实时位置——锚读实时的版本,玩家飞出去后挪一步,回程就落到第二步的位置,"燕回"变"燕漂"。

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

lua
--------------------------------------------------------------------------------
-- @file        ReturnFly.lua
-- @brief       燕回式 —— 突进穿它一遭,原路飞回起手点
--              客户端表现模块:配置表 / 燕返构件 / 三段飞行 / 定时器
--------------------------------------------------------------------------------

local ReturnFly = {}

--------------------------------------------------------------------------------
-- 配置与常量
--------------------------------------------------------------------------------
local CONST = {
    FLY_LIFE      = 0.32,       -- 去程零点三二秒
    HOVER_LIFE    = 0.40,       -- 悬停零点四秒
    BACK_LIFE     = 0.28,       -- 回程零点二八秒
    FLY_CD        = 7.0,        -- 冷却七秒
    GO_DMG        = 25,         -- 去程二十五
    BACK_DMG      = 15,         -- 回程十五
    PAST_OFFSET   = 60,         -- 穿身而过停在身后六十步

    -- 颜色
    COLOR_FLY     = "#7fd8c8",  -- 燕青
    COLOR_DEEP    = "#1f6f5f",  -- 深青
    COLOR_GHOST   = "#d8f5ec",  -- 燕白

    ZORDER_GROUND = 118,
    ZORDER_FLY    = 134,
    ZORDER_EFFECT = 135,

    AUTOINC_BASE  = 946000,
}

--------------------------------------------------------------------------------
-- 模块内部状态
--------------------------------------------------------------------------------
local _phase     = 0              -- 0待机 1去程 2悬停 3回程
local _phaseT    = 0
local _anchorX   = 0              -- 起手锚
local _exitX     = 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 "RFY", 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 CreateBackRing(x)
    local node = GUI:Layout_Create(GUI:Attach_SceneF(), GenID("Back"), x, 6, 0, 0, false)
    GUI:setLocalZOrder(node, CONST.ZORDER_GROUND)
    for i = 1, 20 do
        local a1 = (i - 1) / 20 * 6.28
        local a2 = i / 20 * 6.28
        GUI:DrawLine_Create(node, string.format("r_%d", i), 0, 0, 2,
            m_cos(a1) * 22, m_sin(a1) * 7, m_cos(a2) * 22, m_sin(a2) * 7,
            CONST.COLOR_FLY, 210)
    end
    GUI:runAction(node, GUI:ActionSequence(
        GUI:ActionFadeIn(0.12),
        GUI:ActionFadeOut(0.28),
        GUI:CallFunc(function() SafeRemove(node) end)
    ))
    return node
end

骨架的三处立规。三段各配各的时长——去程比回程长零点零四秒,去重回轻的节奏感全在这点差值里。_phase 用数字三态不用字符串——飞行状态机的三段每帧都要判断,数字比较比字符串比对省一拍。返航环构件自带淡入淡出的动作序列——构件自己走完自己收,状态机不用管它的死活。

四、核心代码:完整模块(下·定时器与三段飞行)

lua
--------------------------------------------------------------------------------
-- 两程的结算
--------------------------------------------------------------------------------
local function Fly_Strike(dmg, isGo)
    local tid = SL:GetValue("MARK_TARGET_ID")
    SL:ActorHurt(tid, dmg)
    SL:TipAbove(tid, "-" .. dmg)
    SL:PlaySweepArc(isGo)
end

--------------------------------------------------------------------------------
-- 燕回入口:写锚、出去
--------------------------------------------------------------------------------
function ReturnFly.Cast()
    if _cdLeft > 0 or _phase ~= 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.FLY_CD
    _anchorX = mp.x
    _exitX = tp.x + CONST.PAST_OFFSET
    _phase = 1
    _phaseT = CONST.FLY_LIFE
    ShowTip("燕出去——穿身一刀,悬半拍再回")
end

--------------------------------------------------------------------------------
-- 定时器:三段推进
--------------------------------------------------------------------------------
if not _scheduler then
    _scheduler = SL:Schedule(function(dt)
        _cdLeft = math.max(0, _cdLeft - dt)
        if _phase == 0 then return end
        if _phase == 1 then
            _phaseT = _phaseT - dt
            local k = 1 - math.max(0, _phaseT) / CONST.FLY_LIFE
            SL:FlyActorTo(_anchorX + (_exitX - _anchorX) * k)
            SL:DropGhost()
            if k >= 0.55 and not _struck then
                _struck = true
                Fly_Strike(CONST.GO_DMG, true)
            end
            if _phaseT <= 0 then
                _phase = 2
                _phaseT = CONST.HOVER_LIFE
                _struck = false
                CreateBackRing(_exitX)
            end
        elseif _phase == 2 then
            _phaseT = _phaseT - dt
            if _phaseT <= 0 then
                _phase = 3
                _phaseT = CONST.BACK_LIFE
            end
        elseif _phase == 3 then
            _phaseT = _phaseT - dt
            local k = 1 - math.max(0, _phaseT) / CONST.BACK_LIFE
            SL:FlyActorTo(_exitX + (_anchorX - _exitX) * k)
            SL:DropGhost()
            if k >= 0.5 and not _struck then
                _struck = true
                Fly_Strike(CONST.BACK_DMG, false)
            end
            if _phaseT <= 0 then
                _phase = 0
                _struck = false
                SL:FlyActorTo(_anchorX)
            end
        end
    end, 0.02)
end

SL:RegisterLUAEvent(LUA_EVENT_SCENE_CLEAR, "RFY_Clear", function()
    _phase = 0
    _struck = false
end)

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

return ReturnFly

下半场的两处见功夫。_struck 单程一记的旗标写在三段的换段处清——去程那刀只结一次、回程那刀另起一页,一程双刀的毛病全在这个旗标漏清。回程落地的最后一步强制 FlyActorTo(_anchorX) 贴回锚点——插值算出的位置和锚点差半步的版本,落脚点漂移会在十次燕回里攒出半个身位的误差,老玩家一眼就看出"回不到原地"。

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

调参三笔账。去程二十五对回程十五是"主去副回"的账——回程伤害超过去程,燕回就变成回旋镖;两程合计四十对突进类技能的两倍冷却周期,值不值七秒冷却玩家自己算。悬停零点四秒是大招空档的呼吸口——压到零点二秒演出太赶,放到零点八秒足够怪的反击落到悬停的玩家头上,悬停变成悬赏。悬停变成悬赏。去程的刀要落在穿身的中点而不是落点——穿身的定义就是"从它身上过",刀口落在过身的半途才叫穿过。穿身停在身后六十步——停得越远回程路线越长、越安全,停得近了回程等于二进怪堆,六十步是"敢穿"和"白穿"的分界。常见坑三个:去程的结算旗标没清,回程又结一次去程的账;悬停期间怪的位移带着玩家跑,锚和实际位置脱钩;落地没贴锚点,燕回十次漂移半屏。

商业服里燕回式是"刺客流"的招牌位移:进去打一套、原路回来的干净利落,刺客玩家的操作集锦全靠这一手撑门面。商城里燕回的残影皮肤是快消品——青燕、赤燕、紫燕,残影的颜色就是出手的排面。变体做成燕回标记:回程必经起手点,起手点可以提前布置成陷阱——去是刀、回是雷,位移技能长成了布局技能。这一篇的演示和整套模块照抄能跑,改的就是 CONST 那张表。

写完留一句给做位移系的同学:燕回卖的是"有去有回"的干净燕回这一式卖的是"有去有回"的干净——锚点钉住的那一寸,是位移技能唯一的信用。锚点钉住的那一寸,是位移技能唯一的信用。穿身点的位置也有学问——停在怪身后六十步,怪的转身需要一个拍子,这一拍就是回程的护身符。

作者履历与出处

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

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

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

LATEST ARTICLES

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

进阶实战游戏功能

迷魂香:一炉香点着,圈里的怪掉头打转

【游戏功能】 怪的仇恨为什么永远追着你?因为它看得见你。迷魂香把"看得见"这三个字没收了:一炉香落在它脚下,烟圈六秒——圈里…

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

气势:连击涨势 挨打掉势 提气回血五十

【游戏功能】 连击值攒着有什么用?多数战斗的答案是攒个伤害加成——气势给了第二个答案:攒的是一支军队的士气。每一刀涨十二点、…

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

崩血:伤口一动就崩,跑得越快掉血越凶

【游戏功能】 一道割裂挂上去,一秒一跳——它站着跳四,追你的时候崩成八:伤口一动就崩,跑得越快掉得越凶。崩血把"放风筝"从走…

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

燕回式:突进穿它一遭,原路飞回起手点

【游戏功能】 突进出去了,回不回得来?多数突进的答案是"不回"——人留在怪堆里听天由命。燕回式给突进装了归途:穿身而过去时一…

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

破招式:它抡重刀你抢半拍,招克招

【游戏功能】 读条变红的那一秒,全世界都在等一个决定。破招式把这一秒做成整场战斗的心跳:怪交替出红劈和蓝刺,红劈读条时按下破…

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

连招谱:三招按谱出,谱尾一击翻倍

【游戏功能】 出招的顺序算不算伤害?大多数战斗里不算——三招乱按和按谱出,账面一个样。连招谱把顺序变成了伤害本身:「劈→撩→…

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