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[买下 入账]
G --> H[摊收 下一场]
F --> H
H --> A
demo
 fx-crest-merchant

二、底层原理

行商系统的机关是"空档市集"——怪倒的三秒是天然的做生意的时间:钱从怪身上掉,货在空档里摆,买定的东西立刻上这一场的身。市集的生命周期卡得死:三秒开、三秒收,与换怪的自然间隙严丝合缝,不占战斗一拍。三件货每场随机重摆——重摆让每一次开摊都开一次小盲盒,挑货的三秒里玩家算的是"这场我最缺哪一件"。
换看加买定的两段操作是刻意拆开的:一个按钮轮看、一个按钮买定,手指不用在三个货位上横跳。钱的两文定价也有讲究:一只怪掉两文、一件货卖两文,一杀一购,节奏咬死——钱多了玩家攒着跳过两场再买,节奏就散了。幂尔框架这边货表每场重洗收在开摊口子里,买定的效果直接改战斗的取值函数,买完下一刀就见效。

这套玩法的代码量不到一百行,难的不是摆摊而是把三秒掐准——摊开在空档里才叫市集,拖进战斗里就是路障。

再看买定的效果为什么当场生效而不等下一场——市集的乐趣在"买完立刻不一样":买重刀,下一刀就是新价;买血囊,气血条当场涨一截。生效越快,买的那一下越像"给自己换了个打法",生效越慢越像发了笔死工资。空档市集卖的本来就不是数值,是"这一场换个活法"的选择权——慢生效卖的是数值,快生效卖的才是选择。

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

lua
-- @file CrestMerchant.lua
-- 行商换纹 —— 怪倒摊子摆开 三选一别挑花眼

local CrestMerchant = {}

local CONST = {
    STALL_TIME    = 3,
    COST          = 2,
    WARE_N        = 3,

    AUTOINC_BASE  = 1203200,
}

local WARE_NAME = { "重刀", "血囊", "汲血" }

local _coin     = 2
local _open     = false
local _left     = 0
local _wares    = { 1, 2, 3 }
local _sel      = 1
local _atk      = 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 CrestMerchant.Coin() return _coin end
function CrestMerchant.Dmg() return 14 + _atk end

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

lua
-- 开摊: 货表重洗
function CrestMerchant.Open()
    _coin = _coin + 2
    for i = CONST.WARE_N, 2, -1 do
        local j = math.random(i)
        _wares[i], _wares[j] = _wares[j], _wares[i]
    end
    _sel = 1
    _open = true
    _left = CONST.STALL_TIME
    ShowTip("摊子摆开——两文一件")
end

-- 换看与买定
function CrestMerchant.Cycle()
    _sel = _sel % CONST.WARE_N + 1
    ShowTip("看第" .. _sel .. "件:"
        .. WARE_NAME[_wares[_sel]])
end

function CrestMerchant.Buy()
    if not _open then return end
    if _coin < CONST.COST then
        ShowTip("钱不够——摊主摇扇送客")
        return
    end
    _coin = _coin - CONST.COST
    ShowTip(WARE_NAME[_wares[_sel]] .. "入手!")
    _open = false
end

if not _ticker then
    _ticker = SL:Schedule(function(dt)
        if not _open then return end
        _left = _left - dt
        if _left <= 0 then
            _open = false
            ShowTip("摊主收摊——下一场再来")
        end
    end, 0.05)
end

SL:ScheduleOnce(function()
    SL:BindDebugButton("换看", function() CrestMerchant.Cycle() end)
    SL:BindDebugButton("买下", function() CrestMerchant.Buy() end)
    ShowTip("技能已加载: 行商换纹")
end, 1.0)

function CrestMerchant.Unload()
    if _ticker then SL:Unschedule(_ticker) end
    _open = false
end

return CrestMerchant

五、机制问答

问:空档市集的三秒为什么卡得死?
答:摊开在空档里才叫市集——拖进战斗就是路障,收摊的秒表不容还价。

问:货表为什么每场重洗?
答:每场开一次小盲盒——固定摆法的摊子第三场就被摸成背版。

问:换看和买定为什么拆成两个按钮?
答:一个轮看一个买定——手指不用在货位上横跳,三秒才够挑完。

问:钱为什么一杀刚够一购?
答:节奏咬死——攒钱跳场的空档就散了,一杀一购最紧。

问:买定的效果为什么当场生效?
答:卖的是选择权不是死工资——下一刀就见效,买的这才像换了个活法。

六、调参与实战怎么用

参数层面三个量——摊位时长、货价、掉钱量。三秒配一杀一购是呼吸的甜点位,摊期与换怪间隙对齐才算无感插入。货的三味也要拉开用途:一件管输出、一件管身板、一件管续航,挑的纠结才真,三件同味的摊子扫一眼就走。实战里这套空档市集的骨架能搬去行商背包、黑市摊位、战后军需,全是掉钱、摆货、限时购一条线。常见坑两个:摊期拖进战斗成路障;货表不重洗,摊子被背版。

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

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

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

写完留一句给做市集系的同学:玩家逛的不是摊是空档——三秒开收掐得准,发呆的间隙自己会长出玩法。

作者履历与出处

本文由 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 技术组