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

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

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

【游戏功能】

测试组报过一口邪门的单:头目的读条明明被打断过,技能照样出了膛——查了半天不是打断失效,是打断只"清了"不"冻",怪在冷却的空档里重新抬手,读条从半截续上。真正的镇压不是打断,是让读条停在那儿不许动。镇魂碑干的就是这件事:碑圈里的读条整体冻结。核心代码照引擎技能脚本的全规格写:配置表、碑体构件、读条冻结状态机、定时器、调试按钮。

一、效果演示:一块碑,一条冻住的血槽

演示场里大怪每七秒凝一记六十点的大招,头顶升起两秒的读条——读条走满,红弧横扫六十。点「镇魂碑!」:一块石碑轰然立在怪身侧,紫蓝色的镇域虚线圈开,读条上的"凝大招…"当场变成"读条冻结"——进度条停在原地,怪僵着手维持凝功的姿态,纹丝不能进。碑化之前,它的大招就是一条永远走不完的血槽——镇住的不只是一招,是它全部的威慑。演示里可以试两种站位:碑落在怪脚下,读条当场冻住;碑落远了,读条照走——镇域只认圈内的魂,圈外的读条它管不着。

demo
 fx-soulstele

二、底层原理:一条读条通道加一个冻结覆盖层

模块的机关是一对状态。怪的大招自带两秒的凝功通道:chanT 从二秒往下走,走满放雷。镇魂碑立起一块六秒的镇域:域内的怪,通道的时间推进被整体跳过——注意是"跳过推进"而不是"清零"——冻结撤掉的瞬间读条从原刻度续走。这正是它和打断系的分野:打断清账、镇压冻账,清了账的怪换个时间照样出招,冻了账的怪在大招的账本上原地踏步。镇域的判定以碑为圆心横宽九十步——碑立在哪,哪一片的读条都得停。

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

lua
--------------------------------------------------------------------------------
-- @file        SoulStele.lua
-- @brief       镇魂碑 —— 立碑镇住它,大招读不完
--              客户端表现模块:配置表 / 碑体构件 / 读条冻结 / 定时器
--------------------------------------------------------------------------------

local SoulStele = {}

--------------------------------------------------------------------------------
-- 配置与常量
--------------------------------------------------------------------------------
local CONST = {
    STELE_LIFE    = 6.0,        -- 碑立六秒
    STELE_CD      = 10.0,       -- 立碑冷却
    STELE_RANGE   = 90,         -- 镇域横宽九十
    ULTI_GAP      = 7.0,        -- 大招七秒一凝
    ULTI_CHANNEL  = 2.0,        -- 读条两秒
    ULTI_DMG      = 60,         -- 大招六十

    -- 颜色
    COLOR_STELE   = "#8b9cf5",  -- 碑紫蓝
    COLOR_DEEP    = "#3a3a7a",  -- 深蓝
    COLOR_GHOST   = "#cdd4ff",  -- 碑白

    ZORDER_GROUND = 118,
    ZORDER_STELE  = 130,
    ZORDER_EFFECT = 135,

    AUTOINC_BASE  = 932000,
}

--------------------------------------------------------------------------------
-- 模块内部状态
--------------------------------------------------------------------------------
local _steleT    = 0              -- 碑的余时
local _steleX    = 0
local _cdLeft    = 0
local _ultiT     = CONST.ULTI_GAP
local _chanT     = 0              -- 读条余量
local _frozen    = 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 "SST", 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 CreateSteleNode(x, y)
    local node = GUI:Layout_Create(GUI:Attach_SceneF(), GenID("Stele"), x, y, 0, 0, false)
    GUI:setLocalZOrder(node, CONST.ZORDER_STELE)
    GUI:DrawLine_Create(node, "body_l", 0, 0, 16, -8, 0, -8, -58, CONST.COLOR_DEEP, 230)
    GUI:DrawLine_Create(node, "body_r", 0, 0, 16, 8, 0, 8, -58, CONST.COLOR_DEEP, 230)
    GUI:DrawLine_Create(node, "cap", 0, 0, 10, -12, -58, 12, -58, CONST.COLOR_GHOST, 240)
    GUI:Text_Create(node, "word", 0, -30, 14, CONST.COLOR_GHOST, "镇魂")
    return node
end

骨架的三处立规。_frozen 是覆盖层的开关而不是通道的属性——冻结是碑施加给通道的外部状态,写在通道自己的字段里,碑一化冻结就成了无主状态。读条余量 _chanT 与冻结分开存放是全套机关的底座:冻的是"推进"、不是"进度"。碑体构件三件一套——碑身两笔厚线、碑额一道亮线、碑文竖排——碑的样子要有分量,没有分量的碑镇不住大招。碑文竖排是老规矩——横排的碑文像告示牌,竖排的碑文才像一块有年头的碑。

四、核心代码:完整模块(下·定时器与读条冻结)

lua
--------------------------------------------------------------------------------
-- 立碑与镇域判定
--------------------------------------------------------------------------------
local function InZone(mx)
    if _steleT <= 0 then return false end
    return math.abs(mx - _steleX) <= CONST.STELE_RANGE
end

function SoulStele.Cast(x)
    if _cdLeft > 0 or _steleT > 0 then return end
    _cdLeft = CONST.STELE_CD
    _steleT = CONST.STELE_LIFE
    _steleX = x
    CreateSteleNode(x, SL:GetValue("ACTOR_POSITION_Y", SL:GetValue("USER_ID")) + 2)
    ShowTip("碑立了——把它引进圈里")
end

--------------------------------------------------------------------------------
-- 大招通道:冻结覆盖层
--------------------------------------------------------------------------------
local function Ulti_Update(dt, mx)
    _frozen = InZone(mx)
    if _chanT > 0 then
        if not _frozen then
            _chanT = _chanT - dt
            if _chanT <= 0 then
                SL:UltiBlast(mx)
                ShowTip("大招出膛了——六十,下块碑立快点")
            end
        end
        return
    end
    _ultiT = _ultiT - dt
    if _ultiT <= 0 then
        _ultiT = CONST.ULTI_GAP
        _chanT = CONST.ULTI_CHANNEL
        ShowTip(_frozen and "它凝大招了——碑镇着,读条冻住" or "它凝大招了——两秒后六十点")
    end
end

--------------------------------------------------------------------------------
-- 定时器与调试
--------------------------------------------------------------------------------
if not _scheduler then
    _scheduler = SL:Schedule(function(dt)
        _cdLeft = math.max(0, _cdLeft - dt)
        if _steleT > 0 then
            _steleT = _steleT - dt
        end
        local mp = GetActorPos(SL:GetValue("USER_ID"))
        Ulti_Update(dt, mp and mp.x + 340 or 0)
    end, 0.02)
end

SL:RegisterLUAEvent(LUA_EVENT_SCENE_CLEAR, "SST_Clear", function()
    _steleT, _chanT, _ultiT, _frozen = 0, 0, CONST.ULTI_GAP, false
end)

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

return SoulStele

下半场两处见功夫。冻结的实现在 Ulti_Update 的分支顺序里:先判 _frozen,冻着就整段跳过推进——通道的每一帧都在问一句"碑还在吗",碑在,两秒的读条就两秒两秒地停。冻结解除的续走是这套机制的德行:进度从原刻度续,玩家抢在碑化前多冻一秒,大招就晚一秒——镇域的时间是玩家一秒一秒买来的。碑化与冻结解除必须同帧——碑的残影还在飘、读条已经复活,这两帧的错位就是玩家投诉的原图。场景清空钩子把大招周期一并复原,新的一场仗从满周期重新数起,一个数字都不带过去。

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

调参三笔账。镇域六秒对大招周期七秒——贴着周期立碑,大招能被冻过整个读条期再余一秒;镇域短于读条的两倍,冻结就成了薛定谔的镇。横宽九十步是碑的"管辖范围"——范围外的读条照走,逼玩家把碑立在怪的脚下而不是自己的脚边,立碑的位置感就是这个技能的全部操作。大招六十对读条两秒:读条越短越难冻,三秒以上的读条配六秒的碑就是白送镇域。常见坑三个:冻结期怪的普攻还在走,冻大招不冻普攻要写清楚;碑立远了镇域圈不沾怪,读条照走,玩家的第一反应是碑坏了——立碑的落点提示要做一圈落点预览;碑化瞬间冻结立刻解除,读条从原刻度续,玩家以为读条清了;镇域圈不随怪移动,怪走出圈读条复活。

商业服里镇魂碑是"攻坚战"的门槛石:会立碑的队把头目的大招冻成摆设,不会立的队每七秒交一次学费——同一只头目两种难度。行会攻城里它是城门守护者:守方立碑冻攻方的冲锋号,攻方拆碑的战术围绕一块石头展开。变体做成碑文品级:下品碑冻大招、上品碑连普攻一起冻慢,碑的种类多一个,攻坚战法厚一页。再进一步做成双碑共鸣:两块碑距离五十步内同时在场,镇域横宽翻倍——碑与碑的几何也是攻略。这一篇的演示和整套模块照抄能跑,改的就是 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 技术组