【游戏功能】
移动组又交来一笔灵异报错:一只头目的行走动画在没有任何攻击命中的时段里突然切成僵硬定格,三秒后自己恢复——动画状态机的日志里查不到切换来源。逐帧翻录像才找到那只看不见的手:玩家在打它的"平衡槽",槽满的一摔把它的行走状态机整段顶掉,三秒倒地结束后状态机才爬回原路。报错不是故障,是摔。今天这篇把绊摔按引擎脚本的全规格拆开:配置表、平衡槽构件、气绝状态机、定时器、调试按钮。
一、效果演示:一条黄槽,三秒地板
演示场里大怪的血条下多挂一条黄色小槽——平衡槽一百点。你的普攻每一刀削八点,刀刀在槽上闪一下;点「绊摔!」一脚削三十,摔踢自带蓝色弧光和半屏震。槽攒满的瞬间:怪当场撂倒——身形压扁贴地、头顶挂出"倒地加倍 三秒",你的刀在这三秒里每一口翻倍;三秒一到它灰头土脸地爬起,槽清零重攒。槽还有脾气:两秒没被削,它自己每秒回五点——攒了一半去躲技能,回来发现槽漏了一截。演示里摔一次看倒地加倍的输出窗口,再故意停手看槽的回漏,两条规矩都走一遍——削槽的手感和回漏的脾气,一轮就能摸透。
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 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【游戏功能】 if _shadowT 0 then spd = noShadow and 12 or 24 end ——一行…
【游戏功能】 魂卫的全机制就一句:杀掉小怪化一盏魂火跟着你走,每盏魂火两秒自动劈最近的大怪一口八点,至多三盏——「引魂!」按…
【游戏功能】 一道咒飞过来,硬吃是四秒里一秒十的钝疼——有没有第三条路?纸人替灾给的就是第三条路:贴一个纸人在身后,八秒里头…
【游戏功能】 挨打还能赚钱?水镜式的答案是:挨的刀七成存进镜里不扣血、三成照常疼,六秒后点「还镜」,存量乘一点五放成水炮——…
【游戏功能】 if _mirrorT 0 then SL:TipAboveMe("免疫") return end ——一道写…
【游戏功能】 远近战的矛盾怎么解?远战的答案是把怪挡在射程外,近战的答案是把人拖进射程内——缩地阵给的第三个答案最蛮横:圈只…