【游戏功能】
穿透技能为什么总被设计成"穿一只"?影枪偏要穿到底——从你的脚下贯穿到屏尾,线上所有目标各挨六十,穿身的那一帧紫光炸开。这篇的核心代码照引擎技能脚本的全规格写:配置表、影枪弹道、多目标判定、定时器、调试按钮。
一、效果演示:一道紫光,线上全倒
演示场点「影枪!」:一道紫色光束从你脚下贯穿到屏尾——线上大怪和小怪各挨六十,穿身的那一帧紫光炸开、震屏。两条命加起来一千,一枪六十一笔清了。演示里试把小怪挪到怪身后——线上两个都挨;把小怪挪到走廊外——只有大怪挨。影枪的线就是一条走廊,站在线上就要交过路费。影枪的线就是一条走廊,站在线上就要交过路费——走廊的宽度是弹道带的纵高,走廊的长度是施法者的射程极限。影枪的线就是一条走廊,站在线上就要交过路费。穿身的那一帧紫光炸开是全技能最亮的一帧——炸开的亮度就是线产出的信心的亮度。
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 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【游戏功能】 蓄力技为什么总是单发?影炮偏要贯穿全屏:蓄一秒射一道暗影弹道穿全屏——线上所有目标各挨五十五,弹道从你脚下贯穿…
【游戏功能】 灼烧为什么总烧在皮肤上?灼心偏要烧进心里:心被灼了六秒——六秒里怪每出一招就自损八,出得越多损得越多。这篇的核…
【游戏功能】 魂卫为什么只有三盏就不能多了?魂蜂偏要做成可以积累的:杀掉小怪化一盏魂蜂跟着你走,至多三盏——三盏魂蜂各自两秒…
【游戏功能】 镜墙为什么只能反弹不能冰冻?霜镜偏要双管齐下:弹道撞上霜镜原路画回去——回程的弹道还带着冰冻效果,扎中怪怪也冻…
【游戏功能】 单体射击为什么打不动厚血怪?穿心刺给的答案是:箭伤八加穿心伤,穿心伤等于最大血量百分之六——血越厚的怪越疼。这…
【游戏功能】 影刺的全机制就一句话:化影绕到它身后,从背刺出的那一刀双倍二十四——正面十二、背后二十四,它一转身就变白板。这…