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

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

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

【游戏功能】

local a, b = math.min(x1, x2), math.max(x1, x2)——一行把两根桩的坐标排成走廊的写法,藏着双桩雷阵全部的地理:两根桩立起来,桩与桩之间就是一条通电的走廊,怪走在走廊里一秒挨一道雷——桩的位置由你定,走廊的走向由你摆。核心代码照引擎技能脚本的全规格写:配置表、桩体构件、走廊判定、定时器、调试按钮。

一、效果演示:两次立桩,一条走廊

演示场点第一次「立桩!」,玩家身前一百四十步处立起第一根桩——桩顶一颗电光珠一闪一闪;再点第二次,三百三十步处立起第二根——两桩之间"轰"地拉起一条电弧,地表蒙上一层紫光:雷区贯通了。大怪追着你跑,一头扎进走廊——紫光里一秒一道雷,叮叮当当往它身上招呼。八秒桩化,走廊断电,再立再连——断电的空档里怪的冲锋会兑现,补桩的手速就是防守的成色。演示里可以试三种摆法,每一种都是一张新的地图:横着摆在你的身前当护界河、竖着摆在怪的要路当电网门、斜着摆在半场当定向雷——同一对桩,三种地理,三种打法。

demo
 fx-twinpillar

二、底层原理:两根桩加一条线段判定

模块的账本是一对桩加一条线段。桩各自带八秒寿命,场上至多两根——第三根立不进来,等旧的化掉。走廊的判定只有三步:取两桩横坐标排成小大两端、怪的横坐标落在两端之间即算入廊、入廊者每秒挨一道雷。判定用"横坐标区间"而不是"点到线的距离"——这条简化是刻意的:雷区的可怕在于"只要在桩之间就挨劈",纵深方向不设宽度,走廊才像一堵电网墙。桩的寿命各自独立,先立的先化——走廊会在战斗中段突然断电,玩家得学会补桩。补桩的顺序也有讲究:先化的那根补上,走廊原样接通;补错位置,走廊整个改道,雷区的地理全凭这两次落点。

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

lua
--------------------------------------------------------------------------------
-- @file        TwinPillar.lua
-- @brief       引雷双桩 —— 两桩立起来,桩间就是雷区
--              客户端表现模块:配置表 / 桩体构件 / 走廊判定 / 定时器
--------------------------------------------------------------------------------

local TwinPillar = {}

--------------------------------------------------------------------------------
-- 配置与常量
--------------------------------------------------------------------------------
local CONST = {
    PILLAR_LIFE   = 8.0,        -- 桩立八秒
    PILLAR_CD     = 3.0,        -- 立桩冷却
    PILLAR_MAX    = 2,          -- 场上至多两根
    GAP_ONE       = 140,        -- 首桩在前一百四十步
    GAP_TWO       = 330,        -- 次桩在前三百三十步
    ZAP_GAP       = 1.0,        -- 走廊一秒一道雷
    ZAP_DMG       = 10,         -- 一道雷十点

    -- 颜色
    COLOR_BOLT    = "#d2a8ff",  -- 电紫
    COLOR_DEEP    = "#4a2a7a",  -- 深紫
    COLOR_GHOST   = "#efe4ff",  -- 电白

    ZORDER_GROUND = 118,
    ZORDER_PILLAR = 130,
    ZORDER_EFFECT = 135,

    AUTOINC_BASE  = 933000,
}

--------------------------------------------------------------------------------
-- 模块内部状态
--------------------------------------------------------------------------------
local _pillars   = {}            -- 桩表:至多两根
local _zapT      = 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 "TWP", 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 CreatePillarNode(x, y)
    local node = GUI:Layout_Create(GUI:Attach_SceneF(), GenID("Pil"), x, y, 0, 0, false)
    GUI:setLocalZOrder(node, CONST.ZORDER_PILLAR)
    GUI:DrawLine_Create(node, "rod", 0, 0, 12, 0, 0, 0, -44, CONST.COLOR_DEEP, 240)
    GUI:DrawLine_Create(node, "tip", 0, 0, 6, 0, -44, 0, -52, CONST.COLOR_GHOST, 240)
    return node
end

骨架先立两条桩规。桩表至多两根的封顶写在立桩入口——第三根的请求在入口就拦下,走廊的几何不允许第三点插嘴。首桩与次桩的落点距离在 CONST 里各立一行——两桩的间距就是雷区的长度,摆多远是玩家的地理课,代码只负责把两根桩立直。桩顶的电光珠一闪一闪是走廊通电的信号灯——珠亮着,走廊活着;珠灭了,走廊就是两根木头。

四、核心代码:完整模块(下·定时器与走廊判定)

lua
--------------------------------------------------------------------------------
-- 走廊判定:横坐标区间
--------------------------------------------------------------------------------
local function InCorridor(x)
    if #_pillars < 2 then return false end
    local a = math.min(_pillars[1].x, _pillars[2].x)
    local b = math.max(_pillars[1].x, _pillars[2].x)
    return x >= a and x <= b
end

--------------------------------------------------------------------------------
-- 立桩
--------------------------------------------------------------------------------
function TwinPillar.Cast(myX)
    if _cdLeft > 0 then return end
    if #_pillars >= CONST.PILLAR_MAX then return end
    _cdLeft = CONST.PILLAR_CD
    local px = myX + (#_pillars == 0 and CONST.GAP_ONE or CONST.GAP_TWO)
    table.insert(_pillars, { x = px, node = CreatePillarNode(px, 0), t = CONST.PILLAR_LIFE })
    if #_pillars == 2 then
        ShowTip("走廊通了——引它进来走两步")
    else
        ShowTip("第一根立了——再立一根凑成走廊")
    end
end

--------------------------------------------------------------------------------
-- 定时器:雷的节拍与桩的寿命
--------------------------------------------------------------------------------
if not _scheduler then
    _scheduler = SL:Schedule(function(dt)
        _cdLeft = math.max(0, _cdLeft - dt)
        for i = #_pillars, 1, -1 do
            local p = _pillars[i]
            p.t = p.t - dt
            if p.t <= 0 then
                SafeRemove(p.node)
                table.remove(_pillars, i)
                ShowTip("桩化了一根——走廊断了,重立")
            end
        end
        if #_pillars == 2 then
            _zapT = _zapT + dt
            if _zapT >= CONST.ZAP_GAP then
                _zapT = _zapT - CONST.ZAP_GAP
                local tid = SL:GetValue("MARK_TARGET_ID")
                local tp = tid and GetActorPos(tid)
                if tp and InCorridor(tp.x) then
                    SL:ActorHurt(tid, CONST.ZAP_DMG)
                    SL:TipAbove(tid, "-" .. CONST.ZAP_DMG)
                end
            end
        end
    end, 0.02)
end

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

SL:ScheduleOnce(function()
    ShowTip("技能已加载: 引雷双桩 (调试按钮触发)")
end, 1.0)

return TwinPillar

下半场两处见功夫。走廊判定 InCorridor 只接受横坐标一个参数——雷区是"桩之间的整段空间",纵深的宽容是机制的慷慨,判得越细走廊越窄,玩家的摆桩就越没有意义。雷的节拍挂在两桩齐全的条件里——单桩不放电,这条写死在分支里:半条走廊不叫走廊。桩化时先收节点再出表,走廊断电的提示跟着出表走,玩家读到的每一条提示都对应一次真实的地理变化。雷的落点特效要踩着怪的头顶而不是走廊的中心——雷认怪不认地,劈在空地中央的雷再亮也是哑雷。

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

调参三笔账。雷一秒一道十点对走廊八秒寿命,走完全程的理论产值八十——产值要压在玩家普攻同期产值的五成以内,走廊是辅助阵地不是主炮。桩寿八秒对立桩冷却三秒,走廊中段必然断电一次——这个断电逼玩家补桩,地理是活的。两桩间距一百四十与三百三十步的默认摆位是"护界河"打法——商业服里可以开放摆桩自由度,摆桩地理直接决定玩法深度,一局一个阵型。常见坑三个:两桩立在同一横坐标,走廊零宽度永不放电,玩家以为机制坏了;桩化出表时节点没跟着收,半空挂着幽灵桩;雷的节拍不查两桩齐全,单桩也在偷偷放电。摆桩的间距还有一课:两桩立得太近,走廊窄成一扇门,怪一步就跨过去;立得太远超出一屏,走廊两头顾不过来——一百四十与三百三十的默认摆位是一屏内的甜区,摆桩地理的手感要从这两行起步。

商业服里引雷双桩是"守点玩法"的地基:据点战里两桩一立就是一道关门,攻方的每一步都要交雷税。副本里它是引导走位的教鞭——走廊摆在怪的要路上,玩家的风筝路线被一根紫线牵着走。变体做成桩阵连携:双桩走廊与冻结桩交叉,走廊里的怪边挨雷边被冻,两套地理叠出一个刑房。这一篇的演示和整套模块照抄能跑,改的就是 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 技术组