【游戏功能】
蓄力技的两难:蓄久了被打断、蓄短了不够疼。蓄光炮把蓄力做成了自动档:按一下开始蓄,三秒蓄满自动出膛——一秒十五、两秒三十、三秒六十,蓄越久炮越粗;中途被怪拍中蓄力中断光散,三秒的耐心前功尽弃。这篇的核心代码照引擎技能脚本的全规格写:配置表、光球构件、蓄力等级状态机、定时器、调试按钮。
一、效果演示:三秒的光球,三档的炮
演示场点「蓄光!」:掌心亮起一颗小光球——光球一秒比一秒大,头顶的蓄力读数"一阶 蓄 0.8/3"跟着走。蓄满三秒光球自动出膛——三阶光炮六十点贯穿大怪,金色的光弧从玩家直贯到怪身,震屏闪白全套伺候。中途被怪的刀拍中蓄力中断——光球当场散掉,提示"蓄力被打断——光散了"。演示里试两档:蓄一秒手动松开打十五的速攻、蓄满三秒打六十的重炮——同一颗光球,两种出手节奏。
fx-lightorb
二、底层原理:一条蓄力曲线加一次自动出膛
模块的机关是一对搭档。蓄力侧:按「蓄光!」进入蓄力态——蓄力计时每帧递增,蓄力的等级按计时切档:一秒一阶、两秒二阶、三秒三阶封顶。自动出膛:三秒蓄满的那一帧自动结算三阶伤害——手动档不设了,三秒就是封顶线,蓄满不出反而浪费拍子。打断侧:怪的攻击命中蓄力中的玩家时,蓄力当场清零、冷却进账——蓄力态是"可以被打断的状态",打断的威慑就是这套机制的张力。三档伤害十五/三十/六十的等比递增让"多蓄一秒"永远值得——等比的设计让蓄力的每一秒都有明确的边际收益。
三、核心代码:完整模块(上·骨架)
--------------------------------------------------------------------------------
-- @file LightOrb.lua
-- @brief 蓄光炮 —— 三秒蓄满一炮贯穿,蓄越久炮越粗
-- 客户端表现模块:配置表 / 光球构件 / 蓄力等级状态机 / 定时器
--------------------------------------------------------------------------------
local LightOrb = {}
--------------------------------------------------------------------------------
-- 配置与常量
--------------------------------------------------------------------------------
local CONST = {
CHARGE_MAX = 3.0, -- 蓄满三秒
CHARGE_CD = 5.0, -- 冷却五秒
L1_DMG = 15, -- 一阶十五
L2_DMG = 30, -- 二阶三十
L3_DMG = 60, -- 三阶六十
AUTO_FIRE = true, -- 蓄满自动出
-- 颜色
COLOR_ORB = "#f0d860", -- 光金
COLOR_DEEP = "#6b5a10", -- 深金
COLOR_GHOST = "#fff8d8", -- 光白
ZORDER_GROUND = 118,
ZORDER_ORB = 134,
ZORDER_EFFECT = 135,
AUTOINC_BASE = 966000,
}
--------------------------------------------------------------------------------
-- 模块内部状态
--------------------------------------------------------------------------------
local _chgT = 0 -- 蓄力计时
local _charging = false -- 蓄力态
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 "LOR", 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 CreateOrbNode(level)
local node = GUI:Layout_Create(GUI:Attach_SceneF(), GenID("Orb"), 0, 0, 0, 0, false)
GUI:setLocalZOrder(node, CONST.ZORDER_ORB)
local r = level * 7
for i = 1, 16 do
local a1 = (i - 1) / 16 * 6.28
local a2 = i / 16 * 6.28
GUI:DrawLine_Create(node, string.format("o_%d", i), 0, 0, 2,
m_cos(a1) * r, m_sin(a1) * r, m_cos(a2) * r, m_sin(a2) * r,
CONST.COLOR_GHOST, 220)
end
return node
end
骨架的三处立规。蓄力计时 _chgT 从零递增到 CHARGE_MAX——递增制不是递减制,蓄力是"攒"不是"耗",方向反了手感就反了。光球构件按等级画尺寸——一阶小、三阶大,球的大小就是蓄力的进度条。AUTO_FIRE 开关立在配置表——关掉它就要手动松开出膛,开关的语义从"自动出"变成了"手动放",两种手感一个字段切换。
四、核心代码:完整模块(下·定时器与蓄力等级)
--------------------------------------------------------------------------------
-- 蓄力入口与等级判定
--------------------------------------------------------------------------------
function LightOrb.Cast()
if _cdLeft > 0 or _charging then return end
_charging = true
_chgT = 0
ShowTip("蓄了——三秒满膛自动出,蓄多久打多疼")
end
local function GetLevel()
if _chgT >= 2.0 then return 3 end
if _chgT >= 1.0 then return 2 end
return 1
end
local function GetDmg(level)
local d = { [1] = CONST.L1_DMG, [2] = CONST.L2_DMG, [3] = CONST.L3_DMG }
return d[level]
end
--------------------------------------------------------------------------------
-- 出膛结算
--------------------------------------------------------------------------------
local function Orb_Fire(level)
local tid = SL:GetValue("MARK_TARGET_ID")
local vd = GetDmg(level)
SL:ActorHurt(tid, vd)
SL:TipAbove(tid, "-" .. vd)
SL:PlayLightBeam(level)
SL:ScreenShake(2 + level * 1.6, 0.14 + level * 0.06)
_charging = false
_chgT = 0
_cdLeft = CONST.CHARGE_CD
end
--------------------------------------------------------------------------------
-- 定时器:蓄力推进与打断
--------------------------------------------------------------------------------
if not _scheduler then
_scheduler = SL:Schedule(function(dt)
_cdLeft = math.max(0, _cdLeft - dt)
if not _charging then return end
_chgT = _chgT + dt
if CONST.AUTO_FIRE and _chgT >= CONST.CHARGE_MAX then
Orb_Fire(3)
return
end
end, 0.02)
end
SL:RegisterLUAEvent(LUA_EVENT_LOCAL_HURT, "LOR_Hurt", function(data)
if data and data.raw and _charging then
_charging = false
_chgT = 0
_cdLeft = CONST.CHARGE_CD
ShowTip("蓄力被打断——光散了,下次找它换弹的空档")
end
end)
SL:ScheduleOnce(function()
ShowTip("技能已加载: 蓄光炮 (调试按钮触发)")
end, 1.0)
return LightOrb
下半场的三处见功夫。蓄力的等级判定按档位区间从高到低——先判三阶再判二阶,最后兜底一阶,判定的顺序就是档位的优先级。打断钩子把蓄力、计时、冷却三件事一口气清——蓄力被打断的光散了、拍子归零了、冷却进了,三件事一口气做完,残账不隔夜。打断钩子把蓄力、计时、冷却三件事一口气清——蓄力被打断的光散了、拍子归零了、冷却进了,三件事一口气做完,残账不隔夜。打断的提示也要说话——"蓄力被打断"四个字比无声的光散清楚十倍,玩家才知道该重新按。自动出膛在定时器的蓄力分支里查 AUTO_FIRE——蓄满的当口直接调 Orb_Fire(3),三阶封顶不问玩家。
五、调参指南与商业服怎么用
调参三笔账。三档十五/三十/六十是等比翻倍——等比设计让"多蓄一秒"的边际收益恒定,蓄力不会出现"第二秒不值"的断崖。蓄满三秒对怪的攻击周期两秒半是"必然被打断一次"的设计——蓄力永远面临被打断的风险,掐断的时机就是掐怪攻击间隙的手法。蓄力永远面临被打断的风险,掐断的时机就是掐怪攻击间隙的手法。蓄力期的移动也要限制——蓄力中走位变慢不能禁走,走慢不禁走的分寸让蓄力有代价但不至于站桩。冷却五秒对蓄力三秒留两秒真空——真空期裸打,真空越短蓄光炮的循环越顺滑。常见坑三个:蓄力期怪的近战不打断蓄力只有远程打断,打断规则不对称;蓄满自动出膛的判定读了玩家的攻击键状态,蓄满了还等玩家松手;三档的光球视觉尺寸一样大,蓄了几秒看不出。
商业服里蓄光炮是"法师流派"的招牌手法:蓄力的读条光环做成品级——法师的蓄力光环按装备升档,蓄光炮的手法就是法师流派的武学展示。蓄光炮是"法师流派"的招牌手法:蓄力的读条光环按装备升档——法师的每一次蓄光都是武学展示,蓄力条的光效就是装备的倒影。商城里蓄光炮的蓄力光球做成品级——白光、金光、星辉光,蓄力光球的质感就是法师的排面。变体做成蓄力分裂:三阶光炮出膛后裂成三束小光弹散射——蓄力的终点连接分裂的起点,两个机制交叉出一条连招链。这一篇的演示和整套模块照抄能跑,改的就是 CONST 那张表。
写完留一句给做蓄力系的同学:蓄光炮卖的是"等的回报"——三秒的光球从掌心长到拳头大,蓄满那一瞬出膛的六十点,是给玩家耐心的全部利息。蓄光炮卖的是"等的回报"——三秒的光球从掌心长到拳头大,蓄满那一瞬出膛的六十点,是给玩家耐心的全部利息。光球的蓄力进度也要读得出来——球从掌心大小长到脑袋大小,球的大小就是蓄力的进度条,比数字直观。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【游戏功能】 控制技能的镜像问题是:锁住了怪,自己是不是也闲着?影锁把这道两难摆上台面:影锁四秒,它动不了、你也动不了——它…
【游戏功能】 打断为什么只有"清读条"一种?震魂偏要反过来——不清招、不断势,打在它读条半途的那一劲顺着招震进腑——中劲十秒…
【游戏功能】 蜂群为什么总是一只一只出?蜂王偏要让它们进化:放一只蜂王出来,杀掉小怪喂它——喂三只升一阶,三阶蜂王的毒刺一秒…
【游戏功能】 技能为什么总是不扣自己的血?血刃偏要反着来:开着血刃的每一刀先扣自己二血、命中回三血——净赚一但要打得中,空刀…
【游戏功能】 bn.t = bn.t - dt ——一行旗面倒计时的代码,撑起了破军旗全部的紧迫感:旗立三秒、圈内加攻三成,…
【游戏功能】 淬毒为什么要一毒到底?淬毒刃偏要一层一层叠:一刀淬一层毒、毒层一秒六地烂,六层封顶之后一刀下去毒伤三十六——叠…