【游戏功能】
会自回血的头目,该先砍它还是先断它的奶?这道题在大多数战斗里没有答案,因为玩家手里没有"断奶"这个动作——重伤印把答案发到每个人手上:一道印拍上去,六秒里它的一切回血对折,奶到一半的伤口重新裂开。这篇的核心代码照引擎技能脚本的全规格写:配置表、封印构件、回血折算钩子、定时器、调试按钮,一个模块从头讲到尾。
一、效果演示:一道印,两本账
演示场里大怪每三秒自回一口:绿色加数一跳十八,血条肉眼可见地回涨——不盖章的仗,你的输出有四成在给它洗澡。点「重伤印!」:一枚红印从玩家手中拍出,钉在怪胸口,红光炸开、"重伤印!"三个大字压顶——之后的六秒,同样的自回只跳九,加数从绿变成灰白,头顶还挂出"断奶"的小字和倒计时。演示里做一组对照:先不盖章砍十秒,血线爬回去三成;盖章再砍十秒,血线一路向下不回头。这道印不增加你的一滴输出,它只是把战斗的坡度从上坡改回下坡。
fx-gravewound
二、底层原理:一个治疗折算钩子加一份封印倒计时
模块的机关是一对搭档。封印对象挂在怪身上:六秒倒计时、一份"折一半"的系数;怪的一切回血在入账前先过折算钩子——钩子查封印表,查到就把治疗量乘零点五再入账,查不到原额放行。折算钩子的位置是全模块的咽喉:它必须写在所有回血入口的汇合处——自回、吸血、队友奶、药水,全部从这一个口子过——写在自回入口里的版本只断自回不断药水,玩家很快会发现"盖章了它还在吃月饼"。封印到期的出表走倒计时自减,揭印的那一帧要有一拍提示,玩家才知道该拍下一张了。
三、核心代码:完整模块(上·骨架)
--------------------------------------------------------------------------------
-- @file GraveWound.lua
-- @brief 重伤印 —— 一道印拍上去,它的奶断一截
-- 客户端表现模块:配置表 / 封印构件 / 治疗折算 / 定时器
--------------------------------------------------------------------------------
local GraveWound = {}
--------------------------------------------------------------------------------
-- 配置与常量
--------------------------------------------------------------------------------
local CONST = {
MARK_LIFE = 6.0, -- 盖印六秒
MARK_CD = 5.0, -- 拍印冷却
HEAL_CUT = 0.5, -- 回血折半
SEAL_TEXT = "断奶",
-- 颜色
COLOR_MARK = "#f85149", -- 印红
COLOR_DEEP = "#7a1d1d", -- 深红
COLOR_GHOST = "#ffc9c9", -- 印白
ZORDER_GROUND = 118,
ZORDER_SEAL = 134,
ZORDER_EFFECT = 135,
AUTOINC_BASE = 927000,
}
--------------------------------------------------------------------------------
-- 模块内部状态
--------------------------------------------------------------------------------
local _markT = 0 -- 封印倒计时
local _markUnit = nil -- 被盖印的单位
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 "GVW", 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 CreateSeal(x, y)
local node = GUI:Layout_Create(GUI:Attach_SceneF(), GenID("Seal"), x, y, 0, 0, false)
GUI:setLocalZOrder(node, CONST.ZORDER_SEAL)
GUI:DrawLine_Create(node, "frame_l", 0, 0, 2.5, -14, -14, -14, 14, CONST.COLOR_MARK, 220)
GUI:DrawLine_Create(node, "frame_r", 0, 0, 2.5, 14, -14, 14, 14, CONST.COLOR_MARK, 220)
GUI:DrawLine_Create(node, "frame_t", 0, 0, 2.5, -14, -14, 14, -14, CONST.COLOR_MARK, 220)
GUI:DrawLine_Create(node, "frame_b", 0, 0, 2.5, -14, 14, 14, 14, CONST.COLOR_MARK, 220)
GUI:Text_Create(node, "txt", -8, -8, 16, CONST.COLOR_MARK, "伤")
return node
end
骨架的三处立规。_markUnit 和倒计时绑在一个状态里——封印是"盖在某只怪身上"的,单存时间的版本换目标就张冠李戴。封印构件做成"方框加字"的朴素样——印就是印,花哨的光效反而把它演成了伤害技能。折半系数 HEAL_CUT 用零点五不用零点二——断奶要断得玩家看得见血条的变化,看不见变化的削弱等于没写。
四、核心代码:完整模块(下·定时器与治疗折算)
--------------------------------------------------------------------------------
-- 治疗折算:一切回血的汇合口
--------------------------------------------------------------------------------
local function OnUnitHeal(unitID, amount)
if _markT > 0 and _markUnit == unitID then
local cut = math.round(amount * CONST.HEAL_CUT)
SL:TipAbove(unitID, "断奶")
return cut
end
return amount
end
--------------------------------------------------------------------------------
-- 拍印与到期
--------------------------------------------------------------------------------
local function Seal_Apply(targetID)
_markT = CONST.MARK_LIFE
_markUnit = targetID
local tp = GetActorPos(targetID)
if tp then
local node = CreateSeal(tp.x, tp.y - 88)
SL:TipAbove(targetID, "重伤印!")
return node
end
end
function GraveWound.Cast(myID, targetID)
if _cdLeft > 0 then return end
if _markT > 0 then return end
_cdLeft = CONST.MARK_CD
Seal_Apply(targetID)
end
--------------------------------------------------------------------------------
-- 定时器与调试
--------------------------------------------------------------------------------
if not _scheduler then
_scheduler = SL:Schedule(function(dt)
_cdLeft = math.max(0, _cdLeft - dt)
if _markT > 0 then
_markT = _markT - dt
if _markT <= 0 then
_markUnit = nil
ShowTip("印揭了——下一张跟上")
end
end
end, 0.02)
end
SL:RegisterLUAEvent(LUA_EVENT_UNIT_HEAL, "GVW_Heal", function(data)
if data and data.unitID and data.amount then
return OnUnitHeal(data.unitID, data.amount)
end
end)
SL:RegisterLUAEvent(LUA_EVENT_ACTOR_DEAD, "GVW_Dead", function(data)
if data and data.id == _markUnit then
_markT = 0
_markUnit = nil
end
end)
SL:ScheduleOnce(function()
ShowTip("技能已加载: 重伤印 (调试按钮触发)")
end, 1.0)
return GraveWound
折半的粒度也有讲究:按整口折还是按每次跳数折,写在钩子里的算法要一次定死——两处折算叠加的版本,回血会被折成负数,负数治疗在账面上是伤害。下半场的咽喉在 OnUnitHeal:折算写在事件回调的返回值里,引擎把返回值当作最终入账——写在本模块内部自建回血表里的版本,管得住自己写的自回,管不住引擎和队友的奶。死亡钩子同时清时间和单位——死人身上的封印不清,下一只刷新的同模型怪会莫名挨半张旧印。拍印入口的双重拦截(冷却加已有封印)都拦在改状态之前,重拍覆盖剩余时间的写法会让封印变成常驻。
五、调参指南与商业服怎么用
调参三笔账。折半对六秒是"奶量少十二"的标准窗口——大怪三秒一跳十八,六秒正好吞掉两跳,账面差二十四,够玩家看见坡度;折得再狠就要配更短的印效,否则头目战变成无脑挂机。冷却五秒对印效六秒留了一秒的空窗——空窗里血条会爬一小截,这截爬升是玩家按下一张印的闹钟。折算系数对吸血类同样生效是题中应有之义——盖章的怪吸血也折半,重伤印天然克制喂养流。常见坑三个:折算只写了自回入口漏了吸血入口;封印特效不跟怪移动,怪走两步印悬在半空;拍印没有已有封印拦截,连拍两印时长叠加成常驻断奶。封印的特效节点也要跟着倒计时走——印揭了字还挂在怪胸口,玩家会以为断奶还在生效。
商业服里重伤印是"战术消耗品"的样板:印纸做成品级,下品印六秒折半、上品印八秒折七成,头目战的消耗账从此多一页。行会玩法里它是治疗职业的正规克制——奶妈之间的战争先从"谁先被盖印"打起,职业对抗的层次感多了一层。变体做成团队印:一张印全队共享冷却,指挥喊"盖印"的时机就是团战的拍子。再进一步做成印纸连携:队伍里三张重伤印同时在场,第三张的折半升折七成——凑印的行会配置有了新的讲究。这一篇的演示和整套模块照抄能跑,改的就是 CONST 那张表。
写完留一句给做削弱系的同学:断奶类机制卖的是"坡度"——盖章前后血条的方向一变,玩家就再也不会忘记这道印。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【游戏功能】 安全巡检扫出一笔可疑的挂账:玩家的"周围单位结算"列表里,同一只怪每零点八秒出现一次,可战斗记录里玩家根本没出…
【游戏功能】 困灵阵的全机制就一句:阵落在它脚下,八秒里它就是圈中之物——敢跨出圈沿,一步吃十五还被弹回去,你在圈外安安稳稳…
【游戏功能】 先泼油还是先点火?这道题答错的代价是一地白烧的火——灯点在空地上,怪还没踩上来,四秒的火一点没沾着它的毛。火油…
【游戏功能】 寻路组收到一笔诡异的工单:怪物巡逻到某个坐标段必卡三秒,像踩了看不见的门槛——排查两小时,发现那段路上有一个上…
【游戏功能】 local a, b = math.min(x1, x2), math.max(x1, x2) ——一行把两根…
【游戏功能】 测试组报过一口邪门的单:头目的读条明明被打断过,技能照样出了膛——查了半天不是打断失效,是打断只"清了"不"冻…