【游戏功能】
if _shadowT > 0 then spd = noShadow and 12 or 24 end——一行腿速减半的分支,藏着偷影全部的诗意:把它的影子偷到你脚下,没了影子的怪刀软一半、腿慢一半,你的刀加两成——影子牵着走,它发虚你发壮。这篇的核心代码照引擎技能脚本的全规格写:配置表、影子构件、三态影子状态机、定时器、调试按钮。
一、效果演示:一道影子,爬过半场
演示场点「偷影!」:怪脚下的深色影子被连根拽出——影子贴着地面爬过半场,一根细线牵着,一路掉着灰屑,最后铺在你的脚下。从这一刻起怪变了:脚下只剩一圈虚线描的空壳,出手慢了一倍、刀软一半——每口从十四掉到七,连走路都像在水里蹚;你脚下踩着它的影子,普攻加两成——十二变十四。六秒后影子自己爬回去,怪缓过神来,第一爪就是报复。第一爪就是报复——报复那一下是实价的,玩家散影前的最后一件事该是退半步。演示里看三处:影子爬行时拖着的灰屑、怪脚下那圈"无影"的虚线空壳、影子爬回时越走越快的步伐——三处都是这套机制的表情。三处都是这套机制的表情,少了哪一处,偷影就少三分味道。
fx-shadowsteal
二、底层原理:一台三态影子状态机加两份属性改写
模块的机关是一台三态状态机。自有态:影子长在怪脚下,一切照旧。爬行态:偷影的瞬间影子脱离怪身、向玩家爬行——爬行的影子是独立的地面构件,爬速固定,爬到玩家脚下切换。偷走态:影子铺在玩家脚下六秒,怪的攻速腿速各砍一半、玩家的攻击加两成;影子在谁脚下,两份改写就落在谁头上。六秒一到影子自动爬回,怪的属性复原。属性改写只在偷走态生效是全模块的边界:爬行途中影子已经是"你的",怪身上的削弱却要等影子落地才挂——影子爬的这半场路,是怪最后的体面。影子爬的这半场路,是怪最后的体面。偷影的落点也讲究:影子铺在玩家脚下而不是悬在半空——影子是地上的事,贴地爬行的每一寸都算数。
三、核心代码:完整模块(上·骨架)
--------------------------------------------------------------------------------
-- @file ShadowSteal.lua
-- @brief 偷影 —— 偷走它的影子,没了影子的怪刀都虚
-- 客户端表现模块:配置表 / 影子构件 / 三态状态机 / 定时器
--------------------------------------------------------------------------------
local ShadowSteal = {}
--------------------------------------------------------------------------------
-- 配置与常量
--------------------------------------------------------------------------------
local CONST = {
SHADOW_LIFE = 6.0, -- 偷影六秒
SHADOW_CD = 12.0, -- 冷却十二秒
TRAVEL_SPEED = 3.0, -- 影子爬行插值
FOE_CUT = 0.5, -- 无影的它刀腿各半
MY_AMP = 1.2, -- 你加两成
-- 颜色
COLOR_SHADOW = "#7a8fa8", -- 影青
COLOR_DEEP = "#3a4050", -- 影灰
COLOR_GHOST = "#c8d0e0", -- 影白
ZORDER_GROUND = 118,
ZORDER_SHADOW = 117,
ZORDER_EFFECT = 135,
AUTOINC_BASE = 943000,
}
--------------------------------------------------------------------------------
-- 模块内部状态
--------------------------------------------------------------------------------
local _state = "own" -- own / travel / stolen
local _shadowX = 0 -- 爬行态影子的横坐标
local _shadowT = 0 -- 偷走态余时
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 "SST", 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 CreateShadowNode(x)
local node = GUI:Layout_Create(GUI:Attach_SceneF(), GenID("Shd"), x, 6, 0, 0, false)
GUI:setLocalZOrder(node, CONST.ZORDER_SHADOW)
for i = 1, 18 do
local a1 = (i - 1) / 18 * 6.28
local a2 = i / 18 * 6.28
GUI:DrawLine_Create(node, string.format("s_%d", i), 0, 0, 4,
m_cos(a1) * 26, m_sin(a1) * 8, m_cos(a2) * 26, m_sin(a2) * 8,
CONST.COLOR_DEEP, 210)
end
return node
end
骨架的三处立规。状态字段用字符串三态不用两个布尔——三态互斥,两个布尔能组合出四个非法态。影子的层级压到地面层之下——影子是地里的事,压在单位脚底下才不穿帮。影子构件十八段折线画扁椭圆——影子是扁的,纵轴压到四分之一,画成竖椭圆就成了一滩水。
四、核心代码:完整模块(下·定时器与三态状态机)
--------------------------------------------------------------------------------
-- 偷影入口
--------------------------------------------------------------------------------
function ShadowSteal.Cast(targetX)
if _cdLeft > 0 or _state ~= "own" then return end
_cdLeft = CONST.SHADOW_CD
_state = "travel"
_shadowX = targetX
ShowTip("影子拽出来了——看着它爬到你脚下")
end
--------------------------------------------------------------------------------
-- 属性改写:偷走态的两本账
--------------------------------------------------------------------------------
local function FoeFactor()
if _state == "stolen" then return CONST.FOE_CUT end
return 1.0
end
local function MyFactor()
if _state == "stolen" then return CONST.MY_AMP end
return 1.0
end
--------------------------------------------------------------------------------
-- 定时器:三态状态机
--------------------------------------------------------------------------------
if not _scheduler then
_scheduler = SL:Schedule(function(dt)
_cdLeft = math.max(0, _cdLeft - dt)
local mp = GetActorPos(SL:GetValue("USER_ID"))
local tp = GetActorPos(SL:GetValue("MARK_TARGET_ID"))
if _state == "travel" then
if not mp then return end
_shadowX = _shadowX + (mp.x - _shadowX) * math.min(1, CONST.TRAVEL_SPEED * dt)
SL:MoveNode(SL:GetShadowNode(), _shadowX, 6)
if math.abs(_shadowX - mp.x) < 8 then
_state = "stolen"
_shadowT = CONST.SHADOW_LIFE
SL:TipAbove(SL:GetValue("MARK_TARGET_ID"), "发虚!")
ShowTip("影子到手——它刀软一半腿慢一半,你加两成")
end
elseif _state == "stolen" then
_shadowT = _shadowT - dt
SL:MoveNode(SL:GetShadowNode(), mp and mp.x or _shadowX, 6)
if _shadowT <= 0 then
_state = "own"
ShowTip("影子爬回去了——它缓过劲了")
end
end
if tp then
SL:SetActorSpeedAmp(SL:GetValue("MARK_TARGET_ID"),
_state == "stolen" and CONST.FOE_CUT or 1.0)
end
SL:SetNextAttackAmp(MyFactor())
end, 0.02)
end
SL:RegisterLUAEvent(LUA_EVENT_SCENE_CLEAR, "SST_Clear", function()
_state = "own"
SL:SetNextAttackAmp(1.0)
end)
SL:ScheduleOnce(function()
ShowTip("技能已加载: 偷影 (调试按钮触发)")
end, 1.0)
return ShadowSteal
下半场三态各管一段。爬行态的影子用插值系数三点零追玩家——影子爬得比人慢半拍,这半拍的爬行就是机制的演出高潮;追上即切偷走态、属性改写同帧挂上。偷走态每帧把怪的腿速系数压到零点五、把玩家的下一刀乘一点二——两份改写都走统一的系数出口,散影时系数复原回一,一帧都不多压。场景清空把状态机推回自有态——影子回去了,加成清了,下一场从"各自有影"起步。
五、调参指南与商业服怎么用
调参三笔账。无影的刀腿各半对六秒是"白给窗口"的尺寸——六秒里怪的威胁只剩四分之一,玩家的爆发技能全部压进这六秒;窗口拉到十秒,头目战变成站桩表演。爬行插值三点零是演出的黄金速——影子爬太快要不到"仪式感",太慢玩家等得发慌,半场爬两秒上下正好。你的加成两成对它的削弱五成是不对称设计——削它比你加成更狠,机制的账更偏向"偷影是削弱技",玩家的加成是顺手赚的。常见坑三个:爬行途中怪死亡,影子爬到一半悬在半路——爬行态也要处理目标死亡;偷走态怪的影子空壳没有视觉,玩家分不清偷没偷上;玩家死亡影子瞬移回家,虚影闪一下。
商业服里偷影是"影流"门派的镇派:影流职业的强度全在这道影上——偷影的成功率、持续、削幅做成影流修行的三重课业,门派贵的理由写在影子爬行的速度里。攻城战里它是士气机制的反面:头目没了影子,全队加两成的账写在每个人的刀上。变体做成影子反偷:怪也可能偷玩家的影子——被偷影的玩家屏幕边缘发灰,夺回影子的打法成了新的攻防题。变体做成影子反偷:怪也可能偷玩家的影子——被偷影的玩家屏幕边缘发灰,夺回影子的打法成了新的攻防题。影子的归属权还能做成收集线:偷过十种怪的影子点亮影鉴,收藏玩法从影子里长出来。这一篇的演示和整套模块照抄能跑,改的就是 CONST 那张表。
写完留一句给做影系的同学:偷影卖的是"名正言顺的虚弱"——它脚下那圈空壳虚线,是全游戏最体面的削弱提示。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【游戏功能】 怪的仇恨为什么永远追着你?因为它看得见你。迷魂香把"看得见"这三个字没收了:一炉香落在它脚下,烟圈六秒——圈里…
【游戏功能】 连击值攒着有什么用?多数战斗的答案是攒个伤害加成——气势给了第二个答案:攒的是一支军队的士气。每一刀涨十二点、…
【游戏功能】 一道割裂挂上去,一秒一跳——它站着跳四,追你的时候崩成八:伤口一动就崩,跑得越快掉得越凶。崩血把"放风筝"从走…
【游戏功能】 突进出去了,回不回得来?多数突进的答案是"不回"——人留在怪堆里听天由命。燕回式给突进装了归途:穿身而过去时一…
【游戏功能】 读条变红的那一秒,全世界都在等一个决定。破招式把这一秒做成整场战斗的心跳:怪交替出红劈和蓝刺,红劈读条时按下破…
【游戏功能】 出招的顺序算不算伤害?大多数战斗里不算——三招乱按和按谱出,账面一个样。连招谱把顺序变成了伤害本身:「劈→撩→…