【游戏功能】
隐身为什么总是逃生技?影遁偏要它当进攻技:化进影子里六秒它的刀全落空——但自动现身的那一刀不加成,只有你亲手按「现身!」主动出影,那一刀才加五成。逃避和进攻的差价,就写在这两颗按钮的缝隙里。逃避和进攻的差价,就写在这两颗按钮的缝隙里——影子里待着是安全,跳出来才是刀。这篇的核心代码照引擎技能脚本的全规格写:配置表、化影构件、现身状态机、定时器、调试按钮。
一、效果演示:六秒的无敌,一颗按钮的抉择
演示场点「影遁!」:玩家化成一团半透明的影——大怪的刀一刀一刀全落空,落空的虚刀穿过你的身影消失在身后。六秒的倒计时挂在头顶,这时候有两条路:什么都不按,六秒一到自动现身——那一刀灰字不加成;或者在倒计时里按「现身!」——你主动从影子里跃出,现身斩三十、白光大字,比自动现身多出一半的账。演示里试两条路各走一次:同样的六秒影子,手动出和自动出的差距就是一颗按钮的自觉。
fx-shadowfade
二、底层原理:一个透明态加一条主动现身通道
模块的机关是一对不对等的出口。透明态:影遁的六秒里怪的攻击判定直接绕过玩家——不是减伤是穿身,弹道从影子上穿过去消失。主动现身通道:「现身!」按下,倒计时清零、那一刀挂五成加成——加成是给"主动选择"的奖金,不是给"隐身结束"的补偿。自动现身的通道走的是倒计时归零的分支——同一帧现身,主动的加五成、被动的加零,出口不同账就不同。这套分野的意义在于教玩家:机制给的东西要主动拿,等着它过期是拿不到全款的。
三、核心代码:完整模块(上·骨架)
--------------------------------------------------------------------------------
-- @file ShadowFade.lua
-- @brief 影遁 —— 化进影子里,六秒无踪,现身一刀加成
-- 客户端表现模块:配置表 / 化影构件 / 现身状态机 / 定时器
--------------------------------------------------------------------------------
local ShadowFade = {}
--------------------------------------------------------------------------------
-- 配置与常量
--------------------------------------------------------------------------------
local CONST = {
FADE_LIFE = 6.0, -- 影遁六秒
FADE_CD = 8.0, -- 冷却八秒
ACTIVE_DMG = 30, -- 主动现身斩三十
PASSIVE_DMG = 12, -- 自动现身十二
ACTIVE_AMP = 1.5, -- 主动加五成
-- 颜色
COLOR_FADE = "#6a8fa8", -- 影青
COLOR_DEEP = "#3a3a52", -- 影黑
COLOR_GHOST = "#e8f0ff", -- 现身白
ZORDER_GROUND = 118,
ZORDER_FADE = 128,
ZORDER_EFFECT = 135,
AUTOINC_BASE = 962000,
}
--------------------------------------------------------------------------------
-- 模块内部状态
--------------------------------------------------------------------------------
local _fadeT = 0 -- 影遁余时
local _charged = 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 "SFD", CONST.AUTOINC_BASE + _autoInc)
end
local function GetMyPos()
local x = SL:GetValue("ACTOR_POSITION_X", SL:GetValue("USER_ID"))
local y = SL:GetValue("ACTOR_POSITION_Y", SL:GetValue("USER_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
---化影构件:周身半透明影化滤镜
local function CreateFadeFx()
local mp = GetMyPos()
if not mp then return end
local node = GUI:Layout_Create(GUI:Attach_SceneF(), GenID("Fx"),
mp.x, mp.y - 46, 0, 0, false)
GUI:setLocalZOrder(node, CONST.ZORDER_FADE)
for i = 1, 20 do
local a1 = (i - 1) / 20 * 6.28
local a2 = i / 20 * 6.28
GUI:DrawLine_Create(node, string.format("f_%d", i), 0, 0, 2,
m_cos(a1) * 26, m_sin(a1) * 48, m_cos(a2) * 26, m_sin(a2) * 48,
CONST.COLOR_FADE, 160)
end
return node
end
骨架的三处立规。_charged 是主动出影的旗标——按现身按钮才置真,自动出影的分支根本不碰这个字段,两条通道各写各的出口就不可能串账。化影构件的透明度调到一百六——影化要"半透明不消失",全透明的版本玩家找不到自己。FADE_LIFE 与 FADE_CD 的差是两秒——六秒的影子配八秒的冷却,两秒的真空让影遁不能常驻。
四、核心代码:完整模块(下·定时器与现身分流)
--------------------------------------------------------------------------------
-- 影遁入口
--------------------------------------------------------------------------------
function ShadowFade.Cast()
if _cdLeft > 0 or _fadeT > 0 then return end
_cdLeft = CONST.FADE_CD
_fadeT = CONST.FADE_LIFE
_charged = false
CreateFadeFx()
ShowTip("化影了——它的刀落空,现身那一刀想加成就手动出")
end
--------------------------------------------------------------------------------
-- 现身分流:主动加成 / 被动白板
--------------------------------------------------------------------------------
local function Emerge(active)
_fadeT = 0
local vd = active and CONST.ACTIVE_DMG or CONST.PASSIVE_DMG
SL:ActorHurt(SL:GetValue("MARK_TARGET_ID"), vd)
SL:TipAbove(SL:GetValue("MARK_TARGET_ID"), "-" .. vd)
if active then
SL:ScreenShake(4, 0.22)
end
_charged = false
end
function ShadowFade.EmergeNow()
if _fadeT <= 0 then return end
_charged = true
Emerge(true)
end
--------------------------------------------------------------------------------
-- 定时器:影遁余时与被动现身
--------------------------------------------------------------------------------
if not _scheduler then
_scheduler = SL:Schedule(function(dt)
_cdLeft = math.max(0, _cdLeft - dt)
if _fadeT <= 0 then return end
_fadeT = _fadeT - dt
if _fadeT <= 0 then
Emerge(false)
ShowTip("自动现身——这一刀不加成,手动的才有")
end
end, 0.02)
end
SL:RegisterLUAEvent(LUA_EVENT_MONSTER_SWING, "SFD_Swing", function()
if _fadeT > 0 then
ShowTip("落空")
return
end
end)
SL:ScheduleOnce(function()
ShowTip("技能已加载: 影遁 (调试按钮触发)")
end, 1.0)
return ShadowFade
下半场的现身分流写在 Emerge 的一个参数里:active 真则三十假则十二——两条通道共用一套落地代码、只拆一个数字,拆数字之外的任何区别都是冗余。被动现身的定时器分支在倒计时归零时调用 Emerge(false),主动现身的按钮调 Emerge(true)——两条路殊途同归到同一个出口,账面永远干净。两条路殊途同归到同一个出口,账面永远干净。影化期的移动也是自由的——化影不禁走位,边影遁边挪窝的玩法是影遁的高阶用法。怪的出手钩子里的"落空"提示也要响——影遁期的每一记虚刀都有回声,无声的免伤让玩家不知道影子还有效。
五、调参指南与商业服怎么用
调参三笔账。主动三十对被动十二是二点五的主动奖金——奖金过三倍玩家永远等手动,自动现身沦为摆设;低于一点五,玩家懒得按第二下。影遁六秒对冷却八秒留两秒真空——真空期的裸打逼玩家在影子里就把输出做完,六秒的影子不浪费。主动加成的目标必须锁定当前仇恨对象——现身斩打向谁要在出影那一刻定死,中途换目标的版本现身斩会落空。常见坑三个:影化期玩家被范围技能打死,透明态没挡住范围判定;自动现身的加成数值写成了主动的,玩家看不出区别就不按了;影化期按第二颗按钮没有任何反馈,玩家不知道影遁还在不在。
商业服里影遁是"操作流刺客"的核心课:手动现身的加成写进技能说明的加粗行,会按的和不会按的打同一只怪差三成输出——教学的价值从第一场战斗就开始收。商城里影化的滤镜做成品级——灰影、蓝影、紫影,影化的透明度就是影流的排面。变体做成影遁连锁:影遁期间每击杀一只小怪续一秒——会杀的刺客影子里六秒变十秒,连续击杀的爽感写在倒计时上。变体做成影遁连锁:影遁期间每击杀一只小怪续一秒——会杀的刺客影子里六秒变十秒,连续击杀的爽感写在倒计时上。现身斩的方向也可以做指向性——朝哪边现身斩就朝哪边劈,现身的落点就是下一轮走位的起点。这一篇的演示和整套模块照抄能跑,改的就是 CONST 那张表。
写完留一句给做隐身系的同学:影遁卖的是"主动出影的选择权"——六秒的影子人人有,加五成的现身只留给按了按钮的那个人。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【游戏功能】 控制技能的镜像问题是:锁住了怪,自己是不是也闲着?影锁把这道两难摆上台面:影锁四秒,它动不了、你也动不了——它…
【游戏功能】 打断为什么只有"清读条"一种?震魂偏要反过来——不清招、不断势,打在它读条半途的那一劲顺着招震进腑——中劲十秒…
【游戏功能】 蜂群为什么总是一只一只出?蜂王偏要让它们进化:放一只蜂王出来,杀掉小怪喂它——喂三只升一阶,三阶蜂王的毒刺一秒…
【游戏功能】 技能为什么总是不扣自己的血?血刃偏要反着来:开着血刃的每一刀先扣自己二血、命中回三血——净赚一但要打得中,空刀…
【游戏功能】 bn.t = bn.t - dt ——一行旗面倒计时的代码,撑起了破军旗全部的紧迫感:旗立三秒、圈内加攻三成,…
【游戏功能】 淬毒为什么要一毒到底?淬毒刃偏要一层一层叠:一刀淬一层毒、毒层一秒六地烂,六层封顶之后一刀下去毒伤三十六——叠…