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

水镜式:挨的刀存进镜里,连本带利还回去

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

【游戏功能】

挨打还能赚钱?水镜式的答案是:挨的刀七成存进镜里不扣血、三成照常疼,六秒后点「还镜」,存量乘一点五放成水炮——连本带利,它自己出的力。这篇的核心代码照引擎技能脚本的全规格写:配置表、水镜构件、存储队列、释放清算、定时器、调试按钮。

一、效果演示:六秒存账,一炮清账

演示场点「水镜!」:一圈水色的光环把玩家罩住,头顶亮出"镜 六秒 · 存 零"。大怪的两秒一刀照常拍过来:三十点的刀当场只掉九——灰色小字,另外二十一并进头顶的"存"读数,水环跟着亮一格——存字一跳,玩家就知道这一刀没白挨。水环跟着亮一格——存字一跳,玩家就知道这一刀没白挨。存储读数叠到封顶的那一刻要有提醒——镜满之后挨的刀全是实价,满仓不提示的版本玩家白挨三刀才发现。「还镜!」一点:水炮轰出去,存量乘一点五——存六十还九十,深青色的水柱连底带顶贯穿它。水柱连底带顶贯穿它——水炮的动画要和普攻的刀光彻底分家,一炮一清账。演示里试两条路:挨满六秒自动还,和存到六十提前还——前者的账厚、后者的拍子准,两种还法都是这门镜的用法。

demo
 fx-watermirror

二、底层原理:一份拆账入口加一个存储读数

模块的账本是一对分账器。入账侧:扣血入口的钩子把每一刀拆成两半——三成当场结、七成压进存储读数,存储封顶一百二,防爆仓。出账侧:「还镜」或者镜到期自动清算,存储乘一点五一次放出去,读数清零。拆账的分寸是全套机制的性格:当场三成让玩家"仍会疼",七成入镜让玩家"值得挨"——两成的当场份额再低,玩家就成了无敌的充电桩;七成的存储再高,镜就变成永动炮台。两成的当场份额再低,玩家就成了无敌的充电桩;七成的存储再高,镜就变成永动炮台。提前还镜的价值在"掐拍":怪的蓄力大招落地前抢先放一炮,伤害与打断的双重收益只有会算账的玩家拿得到。到期自动还是保底清算:六秒到了不管存多少(满二十起还)都自动出膛,攒着不还的玩家不会被利息拖死。攒着不还的玩家不会被利息拖死。水炮的射程也要写清——还镜的水柱打的是当前目标,目标切了水炮跟着切,瞄着谁存就冲着谁放。

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

lua
--------------------------------------------------------------------------------
-- @file        WaterMirror.lua
-- @brief       水镜式 —— 挨的刀存进镜里,连本带利还回去
--              客户端表现模块:配置表 / 水镜构件 / 存储读数 / 定时器
--------------------------------------------------------------------------------

local WaterMirror = {}

--------------------------------------------------------------------------------
-- 配置与常量
--------------------------------------------------------------------------------
local CONST = {
    MIRROR_LIFE   = 6.0,        -- 镜开六秒
    MIRROR_CD     = 10.0,       -- 冷却十秒
    NOW_CUT       = 0.3,        -- 当场三成
    STORE_CAP     = 120,        -- 存储封顶一百二
    RELEASE_MIN   = 20,         -- 二十起还
    RELEASE_RATE  = 1.5,        -- 还镜乘一点五

    -- 颜色
    COLOR_WATER   = "#5ab8d8",  -- 水青
    COLOR_DEEP    = "#1a4a5e",  -- 深青
    COLOR_GHOST   = "#c5ecf5",  -- 水白

    ZORDER_GROUND = 118,
    ZORDER_MIRROR = 134,
    ZORDER_EFFECT = 135,

    AUTOINC_BASE  = 940000,
}

--------------------------------------------------------------------------------
-- 模块内部状态
--------------------------------------------------------------------------------
local _mirrorT   = 0              -- 镜的余时
local _stored    = 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 "WTM", 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 CreateMirrorNode()
    local mp = GetActorPos(SL:GetValue("USER_ID"))
    if not mp then return end
    local node = GUI:Layout_Create(GUI:Attach_SceneF(), GenID("Mir"),
        mp.x, mp.y - 46, 0, 0, false)
    GUI:setLocalZOrder(node, CONST.ZORDER_MIRROR)
    for i = 1, 26 do
        local a1 = (i - 1) / 26 * 6.28
        local a2 = i / 26 * 6.28
        GUI:DrawLine_Create(node, string.format("m_%d", i), 0, 0, 2,
            m_cos(a1) * 26, m_sin(a1) * 46, m_cos(a2) * 26, m_sin(a2) * 46,
            CONST.COLOR_WATER, 190)
    end
    return node
end

骨架的三处立规。存储读数 _stored 是数字不是表——拆账只进不出,一笔总数就够,逐笔明细是化劲那类分期机制才需要的东西。STORE_CAP 一百二封顶防爆仓——六秒里挨四刀就满,满仓后继续挨的刀按实价扣,玩家立刻明白该还镜了。玩家立刻明白该还镜了,还镜的按钮这时候也该亮起来。水环构件椭圆纵轴比横轴长——罩人的镜是竖着的环,贴地的阵才是扁的。

四、核心代码:完整模块(下·定时器与存储清算)

lua
--------------------------------------------------------------------------------
-- 拆账入口:七成存三成疼
--------------------------------------------------------------------------------
local function Hurt_Split(raw)
    local store = math.round(raw * 0.7)
    local now = raw - store
    _stored = math.min(CONST.STORE_CAP, _stored + store)
    SL:PlayerHurt(now)
    SL:TipAboveMe("存" .. store)
end

--------------------------------------------------------------------------------
-- 还镜清算
--------------------------------------------------------------------------------
local function Mirror_Release(targetID)
    if _stored < CONST.RELEASE_MIN then
        ShowTip("镜里才" .. _stored .. "点——二十起还")
        return
    end
    local vd = math.round(_stored * CONST.RELEASE_RATE)
    _stored = 0
    SL:WaterBlast(targetID, vd)
    SL:TipAbove(targetID, "-" .. vd)
    _mirrorT = math.min(_mirrorT, 0.5)
end

--------------------------------------------------------------------------------
-- 画镜与到期
--------------------------------------------------------------------------------
function WaterMirror.Cast()
    if _cdLeft > 0 or _mirrorT > 0 then return end
    _cdLeft = CONST.MIRROR_CD
    _mirrorT = CONST.MIRROR_LIFE
    _stored = 0
    CreateMirrorNode()
    ShowTip("镜开了——六秒里挨的刀七成存镜")
end

--------------------------------------------------------------------------------
-- 定时器:镜寿、拆账与自动清算
--------------------------------------------------------------------------------
if not _scheduler then
    _scheduler = SL:Schedule(function(dt)
        _cdLeft = math.max(0, _cdLeft - dt)
        if _mirrorT <= 0 then return end
        _mirrorT = _mirrorT - dt
        if _mirrorT <= 0 then
            local tid = SL:GetValue("MARK_TARGET_ID")
            if tid and _stored >= CONST.RELEASE_MIN then
                Mirror_Release(tid)
                ShowTip("镜到时自动还了")
            else
                ShowTip("镜散了——存得太少,白开")
            end
        end
    end, 0.02)
end

SL:RegisterLUAEvent(LUA_EVENT_LOCAL_HURT, "WTM_Hurt", function(data)
    if data and data.raw and _mirrorT > 0 then
        Hurt_Split(data.raw)
    end
end)

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

return WaterMirror

下半场的两处见功夫。拆账钩子的第一行先查镜开着没有——镜散后挨的刀走实价,这条写在事件订阅的过滤里,拆账函数自身不必重复判断。到期自动清算时 _stored 不足二十的处理是礼貌——存得太少的自动还反而是浪费,提示一句"白开"让玩家下次学乖;清算完 _mirrorT 清零,镜与读数同时归零,账面永远只有一份真相。

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

调参三笔账。当场三成对存储七成是"疼但不致命"的分账线——当场份额超过五成,玩家挨刀照样掉血如流水,存镜的意义减半;低于两成,坦克玩家开着镜站在怪堆里当充电宝。释放乘一点五是利息线——利息高过普攻的两倍,玩家会故意挨打刷镜,机制变成自虐换伤害的算术游戏;一点五上下是安全区。镜寿六秒对冷却十秒留四秒真空——真空里玩家裸挨,这段裸挨的疼就是学会掐镜期的学费。常见坑三个:拆账钩子把治疗也拆了,奶一口存半口;存储满仓后的实价刀没有提示,玩家不知道镜满了;自动清算的目标在镜开之后切换,水炮打向了旧目标。

商业服里水镜式是"坦克流"的第二春:开镜站桩挨打、关镜一炮清场的循环,坦克玩家第一次有了自己的输出循环。比武场里它是心理战的镜像:对手打你越狠,还回去的越疼——收着打怕你存、放开打怕炸,两难的对手最有意思。变体做成水镜传承:还镜的水炮溅射治疗队友——挨打的价值再翻一层,坦克的勋章挂在队友的血条上。这一篇的演示和整套模块照抄能跑,改的就是 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 技术组