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

对咒和纹:它念三音你跟三音,跟对炸回去

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

【游戏功能】

单行代码拆解:先看一行代码:它念的 == 你跟的——对咒玩法的全部胜负就这一行等式。怪起咒时两块石碑按它的调子依次亮三下,你照着同样的顺序跟点三下:等式成立,咒反炸它一身;等式破了,它把你跟错的音吞下去回血。这篇把对咒和纹整套写法拆开:起咒亮碑、跟音记账、等式判定、错咒反噬,一段一段照抄能跑。

一、效果演示

演示场左右两块石碑立在祭坛边。怪不定时起咒——两碑按它的调子依次亮三下,比如"左左右"。亮完进入跟音窗口五秒:照着亮法点「左碑」「右碑」。三音全对,咒原路炸回去——三十点外加它僵住一秒半;跟错一个音或超时,它把你跟错的咒吞了,回血三十。跟音的面板挂在头顶,几音、几秒,全都明着来。

mermaid
flowchart TD
A[怪起咒] --> B[双碑依次亮三下]
B --> C[跟音窗口五秒]
C --> D[照顺序点碑]
D --> E{三音全对吗}
E -- 对 --> F[反咒三十 它僵住]
E -- 错或超时 --> G[它吞咒回血三十]
F --> H[冷却再等下一咒]
G --> H
demo
 fx-crest-countercharm

二、底层原理

对咒系统的机关是"听音记账"——怪的咒是一串三音的序列,双碑亮的是题目,跟点的三下是答卷,等式成立才炸。那行等式代码里藏着这套玩法的全部公平:亮的顺序明着走、跟音的窗口明着数、判定的等式只认顺序——没有任何暗账。跟音用记忆不用反应:碑亮得多快不追人,五秒的窗口容你回想,难的是记不是手速。
错咒的反噬是这套玩法的獠牙:跟错不是白跟,是把你跟错的咒喂给怪——它回血三十。错有代价,对的赏才够味:反咒三十加一秒半僵住,等于白赚一轮输出窗口。咒的冷却六秒一循环,怪不定时起咒,玩家的注意力得一直挂在碑上——挂着的注意力就是这套玩法要的投入。幂尔框架这边亮碑走预告口,跟音收在按钮口里记账,等式判定在第三音落下的那一拍执行。

这套玩法的代码量不到一百二十行,难的不是亮碑而是等式的干净——亮什么、跟什么、判什么,全是一条序列从头到尾。

再看跟错为什么罚它回血而不是罚玩家掉血——回血的版本,错的代价落在怪的身上:它更强了,玩家更难了,难的方向正对着失误的原因。罚玩家掉血的版本,错音和挨爪混进同一本血账,玩家分不清哪口血是错咒扣的。惩罚要长着失误的模样:记错音就喂怪,账面一目了然,下次跟音自然竖起耳朵。

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

lua
-- @file CrestCountercharm.lua
-- 对咒和纹 —— 它念三音你跟三音 跟对炸回去

local CrestCountercharm = {}

local CONST = {
    CHANT_LEN     = 3,
    INPUT_WINDOW  = 5,
    COUNTER_DMG   = 30,
    MISS_HEAL     = 30,
    STUN_TIME     = 1.5,
    CHANT_CD      = 6,

    AUTOINC_BASE  = 1203500,
}

local _seq      = {}
local _phase    = 0
local _showI    = 0
local _flash    = 0
local _win      = 0
local _input    = {}
local _stun     = 0
local _autoInc  = 0

local function ShowTip(msg)
    if msg and msg ~= "" then SL:ShowSystemTips(msg) end
end

local function GenID()
    _autoInc = _autoInc + 1
    return CONST.AUTOINC_BASE + _autoInc
end

function CrestCountercharm.Phase() return _phase end

四、核心代码:完整模块(下·推进与卸载)

lua
-- 跟音: 记账到第三音开判
function CrestCountercharm.Note(stone)
    if _phase ~= 2 then
        ShowTip(_phase == 1 and "还在听它念——别抢拍" or "碑没亮——等它起咒")
        return
    end
    _input[#_input + 1] = stone
    if #_input >= CONST.CHANT_LEN then
        local ok = true
        for i = 1, CONST.CHANT_LEN do
            if _input[i] ~= _seq[i] then ok = false break end
        end
        _phase = 0
        _input = {}
        if ok then
            _stun = CONST.STUN_TIME
            ShowTip("跟对三音——反咒" .. CONST.COUNTER_DMG .. "!")
        else
            ShowTip("跟错了——它吞咒回血" .. CONST.MISS_HEAL)
        end
    end
end

if not _ticker then
    _ticker = SL:Schedule(function(dt)
        if _stun > 0 then _stun = _stun - dt end
        if _phase == 0 then
            if _stun <= 0 then
                _cd = _cd - dt
                if _cd <= 0 then
                    _cd = CONST.CHANT_CD
                    _phase = 1
                    _showI = 0
                    _seq = {}
                    for i = 1, CONST.CHANT_LEN do
                        _seq[i] = math.random(2)
                    end
                    ShowTip("它起咒了——看碑上亮的顺序")
                end
            end
        elseif _phase == 1 then
            _flash = _flash - dt
            if _flash <= 0 then
                _flash = 0.8
                _showI = _showI + 1
                if _showI > CONST.CHANT_LEN then
                    _phase = 2
                    _win = CONST.INPUT_WINDOW
                    _input = {}
                    ShowTip("到你了——照亮的顺序跟")
                end
            end
        elseif _phase == 2 then
            _win = _win - dt
            if _win <= 0 then
                _phase = 0
                _input = {}
                ShowTip("音散了——白跟")
            end
        end
    end, 0.05)
end

SL:ScheduleOnce(function()
    SL:BindDebugButton("左碑", function() CrestCountercharm.Note(1) end)
    SL:BindDebugButton("右碑", function() CrestCountercharm.Note(2) end)
    ShowTip("技能已加载: 对咒和纹")
end, 1.0)

function CrestCountercharm.Unload()
    if _ticker then SL:Unschedule(_ticker) end
    _phase = 0
end

return CrestCountercharm

五、机制问答

问:对咒的胜负为什么就一行等式?
答:亮的顺序明走、跟的窗口明数、判定只认序列——没有任何暗账。

问:跟音为什么靠记忆不靠手速?
答:碑亮不追人、五秒容回想——难的是记不是手,反应流抢不了这门戏。

问:跟错为什么罚它回血不罚玩家掉血?
答:惩罚要长着失误的模样——错音喂怪,账面正对失误的原因,下次自然竖耳。

问:反噬的僵住一秒半值多少?
答:白赚一轮输出窗口——对的赏要配得上错的痛,等式才两头都有分量。

问:咒的冷却六秒管什么?
答:注意力一直挂在碑上——挂着的投入就是这套玩法要的门票。

六、调参与实战怎么用

参数层面三个量——咒的长度、跟音窗口、错咒反噬。三音是记得住的长度:五音变考据两音变拍手。实战里这套听音记账的骨架能搬去音律对答、符咒反吟、图腾跟拍,全是亮序列、记账、等式判一条线。常见坑两个:序列暗走玩家看不清;错咒罚玩家掉血,失误和挨打混一本账。

补充一个设计层面的思考——战斗之外的空档也是玩法:怪倒之后的三秒、换场的间隙、回合之间的喘口,这些空档塞进不同的经营与选择,战斗的呼吸就完整了。空档里给的选择要短平快:三秒能看完、一点能买定,拖泥带水的空档玩法会让玩家跳过它,跳过等于白做。

补充一个维护层面的思考——概率展示类的状态(扣着的碗、没亮的碑、随机摆的货)要在每一局开始时重洗、结束时清点:上一局剩下什么这一局还摆什么,玩家很快就能摸出固定套路,随机的乐趣就成了背版。重洗的口子收在开局一处,清点写在卸载一行,谁也别留尾巴。

补充一个工程层面的思考——跨阶段的账(预支的债、记下的仇、买断的货)要在阶段切换的口子上自检一遍:换怪了、重开了、演出的半路了,凡是账还挂在已经不存在的对象上,就地作废。自检一行换来的是账本永远只认还活着的对象,幽灵账无处落脚。

写完留一句给做跟音系的同学:玩家跟的是三音也是那行等式——亮得明、记得清、判得公,咒才会乖乖炸回它自己身上。

作者履历与出处

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

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

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

LATEST ARTICLES

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

进阶实战游戏功能

走一格为什么是半秒?拆开996引擎走路状态机

接手二开的兄弟几乎都撞过同一堵墙:玩家嫌走路"一格一格像机器人",老板拍板要"丝滑移动",改服务端速度?不对。改客户端动画帧…

2026-10-03 05:31 996 技术组
进阶实战游戏功能

特效总挂在脚后跟上?挂点表选对一行顶十行

【游戏功能】 先看一个熟场面:法师的火球特效挂在怪的脚后跟上,明明技能说明写着"焚烧其面",火星子却在地上打滚。群里有位策划…

2026-10-03 05:30 996 技术组
进阶实战游戏功能

刀刀都判命中,玩家为什么喊挥空?命中表现差的那一拍

【游戏功能】 上周有个开服的老板在群里发了一段录屏:他的战士明明刀刀都砍中了,观众却一片"这刀挥空了吧"。他原话是"判定日志…

2026-10-03 05:30 996 技术组
进阶实战游戏功能

怪的皮一会儿绿一会儿红?状态染色的色号表就三列

【游戏功能】 先说结论放在开头:怪的皮一会儿绿一会儿红,不是美术换了几套贴图,是染色系统在怪身上盖了一层"色镜"。开服群里有…

2026-10-03 05:30 996 技术组
进阶实战游戏功能

996引擎Buff系统解剖:中毒变绿、冰冻发白是怎么挂上去的

前两天群里有个架设的朋友问了个需求:中毒的人要变绿、每两秒掉一次血、毒还能叠五层,问是不是要在服务端把整套状态机重写。我说你…

2026-10-03 05:25 996 技术组
进阶实战游戏功能

编钟纹:五口钟排着敲,一口更比一口疼

【游戏功能】 先抛一个坑:五口钟一模一样大,为什么一口比一口疼?先后次序动不得吗?倒过来敲会怎样?这篇把编钟纹整套写法拆开:…

2026-10-03 05:01 996 技术组