【游戏功能】
移动组又交来一笔灵异报错:一只头目的行走动画在没有任何攻击命中的时段里突然切成僵硬定格,三秒后自己恢复——动画状态机的日志里查不到切换来源。逐帧翻录像才找到那只看不见的手:玩家在打它的"平衡槽",槽满的一摔把它的行走状态机整段顶掉,三秒倒地结束后状态机才爬回原路。报错不是故障,是摔。今天这篇把绊摔按引擎脚本的全规格拆开:配置表、平衡槽构件、气绝状态机、定时器、调试按钮。
一、效果演示:一条黄槽,三秒地板
演示场里大怪的血条下多挂一条黄色小槽——平衡槽一百点。你的普攻每一刀削八点,刀刀在槽上闪一下;点「绊摔!」一脚削三十,摔踢自带蓝色弧光和半屏震。槽攒满的瞬间:怪当场撂倒——身形压扁贴地、头顶挂出"倒地加倍 三秒",你的刀在这三秒里每一口翻倍;三秒一到它灰头土脸地爬起,槽清零重攒。槽还有脾气:两秒没被削,它自己每秒回五点——攒了一半去躲技能,回来发现槽漏了一截。演示里摔一次看倒地加倍的输出窗口,再故意停手看槽的回漏,两条规矩都走一遍——削槽的手感和回漏的脾气,一轮就能摸透。
fx-poisebreak
二、底层原理:一条平衡槽加一套气绝状态机
模块的账本是一槽一态。平衡槽是怪的属性:普攻削八、摔削三十,命中即削、当场见槽;槽的回漏有自己的脾气——两秒的宽限期里削一下就重新计满宽限,宽限过了每秒回五,这条回漏曲线防止平衡槽被"存"着当爆发用。气绝态是槽满的兑现:倒地三秒、受击翻倍、自身行动全停,三秒一到爬起、槽清零重攒。两套系统的交接在槽满那一帧——削槽的代码只管加数,满槽的瞬间把怪推进气绝态的活儿由状态机自己接手,削槽的代码永远不需要知道"倒地"是什么。
三、核心代码:完整模块(上·骨架)
--------------------------------------------------------------------------------
-- @file PoiseBreak.lua
-- @brief 绊摔 —— 攒满它的气绝槽,一摔撂倒
-- 客户端表现模块:配置表 / 平衡槽构件 / 气绝状态机 / 定时器
--------------------------------------------------------------------------------
local PoiseBreak = {}
--------------------------------------------------------------------------------
-- 配置与常量
--------------------------------------------------------------------------------
local CONST = {
POISE_CAP = 100, -- 平衡槽一百
HIT_POISE = 8, -- 普攻削八
TRIP_POISE = 30, -- 一摔削三十
TRIP_CD = 6.0, -- 摔的冷却
REGEN_DELAY = 2.0, -- 两秒不削才开始回
REGEN_RATE = 5.0, -- 每秒回五
DOWN_LIFE = 3.0, -- 倒地三秒
DOWN_AMP = 2.0, -- 倒地受击翻倍
-- 颜色
COLOR_POISE = "#79c0ff", -- 摔蓝
COLOR_DEEP = "#1f4f8f", -- 深蓝
COLOR_GHOST = "#c8e1ff", -- 残白
ZORDER_GROUND = 118,
ZORDER_BAR = 130,
ZORDER_EFFECT = 135,
AUTOINC_BASE = 930000,
}
--------------------------------------------------------------------------------
-- 模块内部状态
--------------------------------------------------------------------------------
local _poise = 0 -- 当前平衡
local _regenT = 0 -- 宽限计时
local _downT = 0 -- 倒地余时
local _tripCd = 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 "PBS", 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 CreateBarNode(targetID)
local tp = GetActorPos(targetID)
if not tp then return end
local node = GUI:Layout_Create(GUI:Attach_SceneF(), GenID("Bar"),
tp.x - 36, tp.y - 136, 0, 0, false)
GUI:setLocalZOrder(node, CONST.ZORDER_BAR)
GUI:DrawLine_Create(node, "bg", 0, 0, 6, 0, 0, 72, 0, "#30363d", 255)
GUI:DrawLine_Create(node, "fg", 0, 0, 6, 0, 0, 1, 0, CONST.COLOR_POISE, 230)
return node
end
骨架的三处立规。平衡槽是怪的属性不是玩家的增益——削的是它的平衡,槽的读数、回漏、清零全部长在它身上。槽条构件的底条和前条分两个节点写,前条的长度每帧重设——血条复用件和平衡槽共用一张皮,但账不能共用。DOWN_AMP 用二倍不用一点五——倒地三秒是玩家攒了一整条槽换来的,翻倍的窗口要爽到值回票价。
四、核心代码:完整模块(下·定时器与气绝状态机)
--------------------------------------------------------------------------------
-- 削槽与倒地
--------------------------------------------------------------------------------
local function Poise_Cut(targetID, v)
if _downT > 0 then return end
_poise = math.min(CONST.POISE_CAP, _poise + v)
_regenT = 0
if _poise >= CONST.POISE_CAP then
Poise_Down(targetID)
end
end
local function Poise_Down(targetID)
_poise = 0
_downT = CONST.DOWN_LIFE
SL:PlayKnockdown(targetID)
SL:TipAbove(targetID, "撂倒!")
SL:ScreenShake(5, 0.30)
end
--------------------------------------------------------------------------------
-- 摔的入口
--------------------------------------------------------------------------------
function PoiseBreak.Trip(myID, targetID)
if _tripCd > 0 or _downT > 0 then return end
_tripCd = CONST.TRIP_CD
SL:PlayTripAnim(myID)
SL:ScheduleOnce(function()
SL:ActorHurt(targetID, 10)
Poise_Cut(targetID, CONST.TRIP_POISE)
end, 0.18)
end
--------------------------------------------------------------------------------
-- 定时器:宽限回漏与倒地计时
--------------------------------------------------------------------------------
if not _scheduler then
_scheduler = SL:Schedule(function(dt)
_tripCd = math.max(0, _tripCd - dt)
if _downT > 0 then
_downT = _downT - dt
if _downT <= 0 then
ShowTip("它爬起来了——平衡槽重新攒")
end
return
end
_regenT = _regenT + dt
if _regenT >= CONST.REGEN_DELAY and _poise > 0 then
_poise = math.max(0, _poise - CONST.REGEN_RATE * dt)
end
end, 0.02)
end
--------------------------------------------------------------------------------
-- 命中钩子与调试
--------------------------------------------------------------------------------
SL:RegisterLUAEvent(LUA_EVENT_LOCAL_HIT, "PBS_Hit", function(data)
if data and data.isNormal and data.targetID then
Poise_Cut(data.targetID, CONST.HIT_POISE)
end
end)
SL:RegisterLUAEvent(LUA_EVENT_SCENE_CLEAR, "PBS_Clear", function()
_poise, _downT, _regenT = 0, 0, 0
end)
SL:ScheduleOnce(function()
ShowTip("技能已加载: 绊摔 (调试按钮触发)")
end, 1.0)
return PoiseBreak
下半场的状态机是一条单行道:_downT 大于零的每一帧,模块只做倒计时、其余全跳过——倒地的怪不吃削槽、不进宽限回漏,气绝期的一切平衡账都冻结,三秒后清零重来。宽限回漏的计时器 _regenT 在每次削槽时归零——宽限是"连续施压"的奖励,停手两秒它就开始自己站回来,这条曲线逼着玩家把输出拍子连成串。命中钩子只认普攻——技能削槽的版本,平衡槽会被大招流水冲垮,普攻削槽、摔里的大额削槽才是这套体系的拍子。倒地期间怪的受击硬直也要关掉——倒地的三秒是纯输出窗口,一硬直一硬直地数着打就浪费了翻倍的含金量。
五、调参指南与商业服怎么用
调参三笔账。普攻八点对一百的槽是十二刀半起步、一摔补三十——理论七刀加一摔撂倒,对一点二秒的普攻是八秒左右的攒槽期,比大多数头目的出招周期短一截,玩家能掐着摔。倒地三秒对翻倍伤害是这套机制的甜点:三秒翻倍窗口的产值要盖过攒槽的全部成本,玩家才肯为槽而打;倒地一秒半的版本槽就白攒了。回漏每秒五对宽限两秒是存槽的惩罚线——攒六十的槽停手五秒漏光,这条线告诉玩家:平衡槽是流水不是存款。常见坑三个:倒地的怪还在挨削槽判定,槽爬满又摔一次,躺下起不来;宽限计时在摔的大额削槽后没有归零,摔完立刻开始回漏;倒地结束的起身动画和受击动画叠帧。
商业服里绊摔是"重武器职业"的翻身仗:重锤大剑的攻速劣势被削槽效率补平,武器的"破平衡"词条第一次有了和攻击力同台的价值。副本里它是全队的发令枪——槽满摔倒的三秒就是全队爆发技能的齐射口令,指挥的拍子从血条挪到了黄条。变体做成破平衡竞技:玩家的平衡槽也会被怪削,谁先摔谁吃亏,攻防两端的平衡博弈做成一场。这一篇的演示和整套模块照抄能跑,改的就是 CONST 那张表。
写完留一句给做气绝系的同学:平衡槽卖的是"把它打趴下"的实感——回漏曲线画得越紧,玩家连成串的输出越像一套拳。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【游戏功能】 安全巡检扫出一笔可疑的挂账:玩家的"周围单位结算"列表里,同一只怪每零点八秒出现一次,可战斗记录里玩家根本没出…
【游戏功能】 困灵阵的全机制就一句:阵落在它脚下,八秒里它就是圈中之物——敢跨出圈沿,一步吃十五还被弹回去,你在圈外安安稳稳…
【游戏功能】 先泼油还是先点火?这道题答错的代价是一地白烧的火——灯点在空地上,怪还没踩上来,四秒的火一点没沾着它的毛。火油…
【游戏功能】 寻路组收到一笔诡异的工单:怪物巡逻到某个坐标段必卡三秒,像踩了看不见的门槛——排查两小时,发现那段路上有一个上…
【游戏功能】 local a, b = math.min(x1, x2), math.max(x1, x2) ——一行把两根…
【游戏功能】 测试组报过一口邪门的单:头目的读条明明被打断过,技能照样出了膛——查了半天不是打断失效,是打断只"清了"不"冻…