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

背刺:绕到它身后,刀刀双倍

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

【游戏功能】

正面拼刀是武夫的浪漫,背刺是刺客的算术:同样的刀,从背后进就是双倍——它面朝左你站右,二十四的金字刀刀见血;它一转身,你手里就是一把白给的木刀。同样的刀,从背后进就是双倍——它面朝左你站右,二十四的金字刀刀见血;它一转身,你手里就是一把白给的木刀。位置就是伤害,这句话在背刺身上是字面意思。这篇的核心代码照引擎技能脚本的全规格写:配置表、朝向判定构件、绕后步状态机、定时器、调试按钮。

一、效果演示:它的背后,是你的加成区

演示场点「绕后!」:玩家化作紫影绕到怪身后五十四步处落定——怪的朝向还没转过来,你的每一刀都是二十四的双倍金字,头顶挂出"背后 · 双倍"。头顶挂出"背后 · 双倍",紫色的判定环同时套在怪脚下——环在、双倍在;环灭、双倍熄。怪的朝向每帧追着你转——它转身的半拍里你的双倍还在,转完的瞬间头顶变灰"面朝右",你的刀当场变回十二的白板。绕后步冷却五秒,转身和绕后永远在抢时间。演示里盯两处:怪的朝向字从左变右的那一帧就是双倍失效的帧;绕后步的残影是紫色的——绕后的路要让人看得见,看得见的绕后才叫技术。

demo
 fx-backstab

二、底层原理:一份朝向判定加一次侧向位移

模块的机关是一对搭档。朝向判定:怪的朝向字段和玩家的相对位置做叉乘式的比对——怪面朝右、玩家在怪的左侧,即"在背后";这个判定每帧跑,转身的第一帧双倍就失效。侧向位移:绕后步不是传送到背后,是从当前位置划一条弧线插到怪的另一侧——弧线插值让绕后有"绕"的动作,瞬移的版本是换位不是绕后。双倍的写在攻击结算出口:正面刀十二、背后刀二十四,同一个出口按判定结果分两档——判定与结算同帧,转身的瞬间数字当场变白。

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

lua
--------------------------------------------------------------------------------
-- @file        BackStab.lua
-- @brief       背刺 —— 绕到它身后,刀刀双倍
--              客户端表现模块:配置表 / 朝向判定构件 / 绕后步状态机 / 定时器
--------------------------------------------------------------------------------

local BackStab = {}

--------------------------------------------------------------------------------
-- 配置与常量
--------------------------------------------------------------------------------
local CONST = {
    BEHIND_BAND   = 70,         -- 背后判定带七十步
    CRIT_AMP      = 2.0,        -- 背后双倍
    BASE_DMG      = 12,         -- 正面十二
    STEP_LIFE     = 0.3,        -- 绕后步零点三秒
    STEP_CD       = 5.0,        -- 绕后冷却五秒
    STEP_OFFSET   = 54,         -- 落在它身后五十四步

    -- 颜色
    COLOR_STAB    = "#a89ae0",  -- 背刺青
    COLOR_DEEP    = "#3a2a6e",  -- 深紫
    COLOR_GHOST   = "#ece4ff",  -- 刃白

    ZORDER_GROUND = 118,
    ZORDER_STEP   = 133,
    ZORDER_EFFECT = 135,

    AUTOINC_BASE  = 958000,
}

--------------------------------------------------------------------------------
-- 模块内部状态
--------------------------------------------------------------------------------
local _stepT      = 0              -- 绕后步余时
local _stepFrom   = 0
local _stepTo     = 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 "BST", 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 CreateBehindRing(x)
    local node = GUI:Layout_Create(GUI:Attach_SceneF(), GenID("Ring"), x, 6, 0, 0, false)
    GUI:setLocalZOrder(node, CONST.ZORDER_STEP)
    for i = 1, 22 do
        local a1 = (i - 1) / 22 * 6.28
        local a2 = i / 22 * 6.28
        GUI:DrawLine_Create(node, string.format("r_%d", i), 0, 0, 2.5,
            m_cos(a1) * 34, m_sin(a1) * 12, m_cos(a2) * 34, m_sin(a2) * 12,
            CONST.COLOR_STAB, 210)
    end
    return node
end

骨架的三处立规。背后判定带七十步——判定带是"怪的转向来不及反应"的距离,带外站着的玩家不叫绕后叫远程。双倍系数二点零写在常量里不写死在结算——三倍背刺的调参只动这一个数。判定圈构件挂在怪的脚下——背后区是怪的属性不是玩家的,圈跟着怪走,玩家站进去才算数。

四、核心代码:完整模块(下·定时器与背后结算)

lua
--------------------------------------------------------------------------------
-- 朝向判定:怪面朝右玩家在左即背后
--------------------------------------------------------------------------------
local function IsBehind(myX, foeX, foeDir)
    if foeDir == 2 and myX < foeX - 10 then return true end
    if foeDir == 6 and myX > foeX + 10 then return true end
    return false
end

--------------------------------------------------------------------------------
-- 绕后步
--------------------------------------------------------------------------------
function BackStab.Step()
    if _cdLeft > 0 or _stepT > 0 then return end
    local tp = GetActorPos(SL:GetValue("MARK_TARGET_ID"))
    local mp = GetActorPos(SL:GetValue("USER_ID"))
    if not tp or not mp then return end
    _cdLeft = CONST.STEP_CD
    _stepT = CONST.STEP_LIFE
    _stepFrom = mp.x
    _stepTo = tp.x + (mp.x > tp.x and CONST.STEP_OFFSET or -CONST.STEP_OFFSET)
    ShowTip("绕后——抢它转身的半拍")
end

--------------------------------------------------------------------------------
-- 定时器:绕后步推进与背刺结算
--------------------------------------------------------------------------------
if not _scheduler then
    _scheduler = SL:Schedule(function(dt)
        _cdLeft = math.max(0, _cdLeft - dt)
        if _stepT > 0 then
            _stepT = _stepT - dt
            local k = 1 - math.max(0, _stepT) / CONST.STEP_LIFE
            local mp = GetActorPos(SL:GetValue("USER_ID"))
            if mp then
                SL:FlyActorTo(_stepFrom + (_stepTo - _stepFrom) * k)
                SL:DropGhost()
            end
            if _stepT <= 0 then
                _stepT = 0
            end
            return
        end
        _atkT = (_atkT or 1.2) - dt
        if _atkT <= 0 then
            _atkT = 1.2
            local myID = SL:GetValue("USER_ID")
            local mp = GetActorPos(myID)
            local tid = SL:GetValue("MARK_TARGET_ID")
            local tp = tid and GetActorPos(tid)
            if mp and tp and IsBehind(mp.x, tp.x, SL:GetValue("ACTOR_DIR", tid)) then
                local vd = CONST.BASE_DMG * CONST.CRIT_AMP
                SL:ActorHurt(tid, vd)
                SL:TipAbove(tid, "-" .. vd)
                SL:ScreenShake(3, 0.16)
            else
                SL:ActorHurt(tid, CONST.BASE_DMG)
            end
        end
    end, 0.02)
end

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

return BackStab

下半场的判定有两处小骨法。IsBehind 的比对留了十步的余量——贴着怪的侧身时判定不抖,抖动的背后判定会让双倍一帧有一帧没有。绕后步的落点按玩家的当前侧动态选边——mp.x > tp.x 决定往左绕还是往右绕,绕后步永远走短边,绕大圈的版本是对走位的嘲弄。

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

调参三笔账。双倍对正面十二是"位置税"的定价——背刺的双倍要压在正面输出的一倍以上、两倍半以下,一倍半玩家懒得绕,两倍半正面刀成了白给。背刺的双倍要压在正面输出的一倍以上、两倍半以下,一倍半玩家懒得绕,两倍半正面刀成了白给。绕后步的残影也要和正面走位的脚印区分——紫色的绕后影是技术的签名,灰色的走路印谁都有。绕后步五秒对怪转身零点五秒是"抢得到"的窗口——转身快的怪需要更快的绕后步,转身慢的怪背刺白给,怪和技的匹配就是难度。判定带七十步对绕后落点五十四步是"落点必在带内"的保证——落点在判定带外的版本,绕过去了刀却是白板。常见坑三个:朝向判定的余量没留,贴身绕后判定抖成闪灯;绕后步的弧线穿过怪的模型,穿模的绕后比正面拼刀还脏;背后双倍的数字颜色和暴击一样红,玩家分不清是位置收益还是运气暴击。

商业服里背刺是"刺客职业"的身份证明:位置收益的数字直接写在职业技能里,刺客的输出一半靠手一半靠脑——站位的脑子就是刺客的卖相。背刺是"刺客职业"的身份证明:位置收益直接写进职业技能,刺客的输出一半靠手一半靠脑——站位的脑子就是刺客的卖相。绕后步的冷却也别做得太顺:五秒的冷却逼玩家在"绕后"和"拼刀"之间做选择,选了才叫刺客。商城里绕后步的残影皮肤卖得最好——紫影、青影、黑影,绕后的一瞬就是职业的海报。变体做成背刺教条:连续背刺三次触发"割喉"终结——位置的连击把绕后从一次位移升成一套流程。这一篇的演示和整套模块照抄能跑,改的就是 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 技术组