【游戏功能】
穿透技能为什么总被设计成"穿一只"?影枪偏要穿到底——从你的脚下贯穿到屏尾,线上所有目标各挨六十,穿身的那一帧紫光炸开。这篇的核心代码照引擎技能脚本的全规格写:配置表、影枪弹道、多目标判定、定时器、调试按钮。
一、效果演示:一道紫光,线上全倒
演示场点「影枪!」:一道紫色光束从你脚下贯穿到屏尾——线上大怪和小怪各挨六十,穿身的那一帧紫光炸开、震屏。两条命加起来一千,一枪六十一笔清了。演示里试把小怪挪到怪身后——线上两个都挨;把小怪挪到走廊外——只有大怪挨。影枪的线就是一条走廊,站在线上就要交过路费。影枪的线就是一条走廊,站在线上就要交过路费——走廊的宽度是弹道带的纵高,走廊的长度是施法者的射程极限。影枪的线就是一条走廊,站在线上就要交过路费。穿身的那一帧紫光炸开是全技能最亮的一帧——炸开的亮度就是线产出的信心的亮度。
fx-shadowspear
二、底层原理:一条贯穿弹道加一份多目标表
模块的机关是一对搭档。弹道侧:影枪不是投射物,是一条从施法者到屏尾的即时射线影枪不是投射物,是一条从施法者到屏尾的即时贯穿射线——射线自身带四帧的渐隐动画。多目标侧:出膛的那一帧,扫一遍场上所有单位——横坐标在施法者右侧且纵坐标在弹道带内的全部结算六十。和分裂箭的分野:分裂箭出三支独立的投射物,影枪扫的是一条线上的所有活物——分裂箭打"扇面里的"、影枪打"线上的"。分裂箭打"扇面里的"、影枪打"线上的",投射系的两条路线在覆盖形状上分了家。影枪的弹道渐隐也要做——四帧渐隐从亮到无,影枪不是常驻激光是一次性的贯穿。
三、核心代码:完整模块(上·骨架)
-- @file ShadowSpear.lua
-- 影枪 —— 一道暗影穿身过,线上全挨
local ShadowSpear = {}
local CONST = {
SPEAR_CD = 4.0,
SPEAR_DMG = 60,
SPEAR_RANGE = 500,
SPEAR_HEIGHT = 40,
COLOR_SPEAR = "#9a7ab8",
COLOR_DEEP = "#2a1a4a",
COLOR_GHOST = "#e0d8f8",
ZORDER_FX = 135,
AUTOINC_BASE = 969000,
}
local _cdLeft = 0
local _spearT = 0
local _scheduler = nil
local _autoInc = 0
local function GenID(prefix)
_autoInc = _autoInc + 1
return string.format("%s_%d", prefix or "SSP",
CONST.AUTOINC_BASE + _autoInc)
end
local function GetActorPos(id)
if not id then return nil end
local x = SL:GetValue("ACTOR_POSITION_X", id)
local y = SL:GetValue("ACTOR_POSITION_Y", id)
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
四、核心代码:完整模块(下·定时器与多目标)
-- 影枪入口
function ShadowSpear.Cast()
if _cdLeft > 0 then return end
_cdLeft = CONST.SPEAR_CD
_spearT = 0.4
local myID = SL:GetValue("USER_ID")
local mp = GetActorPos(myID)
if not mp then return end
for _, id in ipairs(SL:GetAllActorsInView()) do
if id ~= myID then
local tp = GetActorPos(id)
if tp and math.abs(tp.y - mp.y) <= CONST.SPEAR_HEIGHT
and tp.x > mp.x then
SL:ActorHurt(id, CONST.SPEAR_DMG)
SL:TipAbove(id, "-" .. CONST.SPEAR_DMG)
end
end
end
ShowTip("影枪出去了——线上全挨")
end
if not _scheduler then
_scheduler = SL:Schedule(function(dt)
_cdLeft = math.max(0, _cdLeft - dt)
if _spearT > 0 then
_spearT = _spearT - dt
end
end, 0.02)
end
SL:ScheduleOnce(function()
ShowTip("技能已加载: 影枪 (调试按钮触发)")
end, 1.0)
return ShadowSpear
五、调参指南与商业服怎么用
调参三笔账。伤害六十对冷却四秒是每秒十五的线产——线产要压在单体输出的一倍以内,影枪是清线技不是主输出。贯穿高度四十步是"线上"的窄门——太高变成面伤害,太低只打一条缝。弹道渐隐四帧是演出——四帧走完影枪消失,拖太久反而挡视野。常见坑三个:贯穿没排除自己,影枪把施法者也扫了;纵坐标判定用了绝对值导致身后的也中;弹道动画和伤害不同帧,光到了血没掉。弹道动画和伤害不同帧,光到了血没掉。影枪的弹道是即时判定的——出膛的那一帧所有目标同时扣血、同时蹦数字、同时弹闪白——同帧结算就是贯穿技的公信力。影枪的弹道是即时判定的——出膛的那一帧所有目标同时扣血、同时蹦数字、同时弹闪白——同帧结算就是贯穿技的公信力。贯穿的弹道特效也要做穿透的分层——弹道本体、弹道边缘光晕、弹道经过地面的紫光。
商业服里影枪是"清线流派"的门面:据点战的走廊、攻城战的通道、防守战的窄巷——影枪的每一处战场都是一条线。据点战的走廊、攻城战的通道、防守战的窄巷——影枪的每一处战场都是一条线,线的价值由地形决定不由数值决定。影枪是"清线流派"的门面:据点战的走廊、攻城战的通道、防守战的窄巷——影枪的每一处战场都是一条线。影枪和双桩雷阵的交叉也值得一试:先立双桩画走廊、再开影枪补伤害,两条线的走廊变成两条线的刑场。商城里影枪的弹道皮肤做成品级——紫枪、蓝枪、暗金枪,弹道的颜色就是清线流派的海报。弹道的颜色就是清线流派的海报。影枪的贯穿还可以做成多层——第一层打小怪、第二层穿大怪、第三层穿屏尾——三层贯穿的弹道就是影枪的终阶形态。变体做成影枪贯穿蓄力:按住蓄力,蓄越久线越宽——从线变成面,清线的极致就是面清。从线变成面,清线的终极形态就是面清——面清的影枪已经不是技能是地图的清扫模式了。清线的极致就是面清——面清的影枪已经不是技能是地图事件的触发器了。变体做成影枪贯穿蓄力:按住蓄力,蓄越久线越宽——从线变成面,清线的极致就是面清。贯穿的判定也别忘了写——影枪的纵高四步、怪的碰撞盒八步,判定取交叠区间——碰撞盒和弹道带的交叉就是命中的真相。这一篇的演示和整套模块照抄能跑,改的就是 CONST 那张表。
写完留一句给做穿透系的同学:影枪卖的是"线上的公平"影枪卖的是线上的公平——不管你是头目还是小怪,站在线上就交六十,不多不少。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【游戏功能】 控制技能的镜像问题是:锁住了怪,自己是不是也闲着?影锁把这道两难摆上台面:影锁四秒,它动不了、你也动不了——它…
【游戏功能】 打断为什么只有"清读条"一种?震魂偏要反过来——不清招、不断势,打在它读条半途的那一劲顺着招震进腑——中劲十秒…
【游戏功能】 蜂群为什么总是一只一只出?蜂王偏要让它们进化:放一只蜂王出来,杀掉小怪喂它——喂三只升一阶,三阶蜂王的毒刺一秒…
【游戏功能】 技能为什么总是不扣自己的血?血刃偏要反着来:开着血刃的每一刀先扣自己二血、命中回三血——净赚一但要打得中,空刀…
【游戏功能】 bn.t = bn.t - dt ——一行旗面倒计时的代码,撑起了破军旗全部的紧迫感:旗立三秒、圈内加攻三成,…
【游戏功能】 淬毒为什么要一毒到底?淬毒刃偏要一层一层叠:一刀淬一层毒、毒层一秒六地烂,六层封顶之后一刀下去毒伤三十六——叠…