伤害结算前的窗口是战斗的收口裁决点:吸血的回血、反伤的弹回、减伤的触发全在攻击前的那一瞬。attackdamage 触发在人物攻击前的节点,战斗的衍生机制都挂在这个钩子上。
---attackdamage: 人物攻击前触发
function attackdamage(self, Target, Hiter, MagicId)
local player = class(self)
if not player then return end
-- 吸血属性:伤害的 8% 转化为生命
local lifesteal = tonumber(getplayvar(self, 2, "Lifesteal")) or 0
if lifesteal > 0 and Target then
local heal = math.floor(MagicId * 0 + lifesteal)
humanhp(self, "+", heal)
sendmsg(self, 1, "吸血回复 " .. heal .. " 点")
end
end
攻击前触发的时机是衍生机制的天堂:吸血按攻击者的属性折算回血、反伤把即将受到的伤害记账、破防标记在结算前打上。吸血的来源是装备的词条与内功的加成,属性的叠加走统一的面板聚合——吸血的总量有上限(每次不超过最大生命的 2%),生存的滚雪球被上限按住。
---反伤:受击方的回弹标记
function Damage.thorns(actor, attacker, dmg)
local player = class(actor)
if not player then return end
local thorns = tonumber(getplayvar(actor, 2, "Thorns")) or 0
if thorns <= 0 or not attacker then return end
-- 反伤为受到伤害的 15%,不超过 200 点
local back = math.min(math.floor(dmg * 0.15), 200)
setplayvar(attacker, 2, "PendingThorns", back, 0)
sendmsg(actor, 1, "反伤预备 " .. back .. " 点")
end
反伤的实现借攻击前的窗口记账:受击方的反伤属性把回弹的伤害记到攻击者的待结算槽,攻击结算时一并处理——反伤不触发反伤的递归(回弹的伤不进 attackdamage),循环的地狱在规则里被明确禁止。攻击前的修正与攻击后的统计是两条链:修正管这次伤害的形态,统计管战斗的总账(伤害统计、连击计数),两条链在同一触发的不同分支里各走各路。战报的完整性靠前置钩子喂料:每一次修正(吸血多少、反伤多少)都进战斗日志,复盘的颗粒度到每一次挥刀。
吸血与反伤的触发流水抽样核对,属性面板与实际结算的偏差不超 1%;反伤的递归保护测试,构造互反的双方验证不进入死循环。
吸血曾经按攻击力而非最终伤害计算,堆攻击的收益双重放大,口径统一为最终伤害。反伤的回弹曾经触发受击方的反伤,两块反弹的镜子互相弹到天荒地老,递归的禁止条款写进文档。触发的执行曾经阻塞了伤害结算,钩子里的慢查询让全场攻击卡顿,钩子内禁 IO 的纪律立下。
吸血与反伤的上限、比例进技能与装备表,数值的调整不改代码。触发的钩子保持轻量:禁数据库、禁广播风暴,衍生的通知走异步队列。战斗的统计与修正分链,统计的账不受修正的影响。
本文由 996 技术组基于 996 引擎官方知识库与浮生梦老师课程体系整理。团队长期从事传奇类引擎 Lua 后端逻辑、客户端界面与商业版本交付,内容以官方知识库与真实项目为出处,按版本持续修订。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
学员常见误区 Lua函数可返回多个值,学员用固定变量数接收时如果变量少于返回值,多余返回值被静默丢弃;如果变量多于返回值,多…
设计初衷 行会建筑的死穴是一次全解锁:会员没有逐步建设的过程感。梯度设计让每栋建筑都有前置条件和资源门槛。 数值模型 建筑分…
设计初衷 婚姻系统的属性加成是社交玩法的经济锚点:加成太弱没人结婚,太强则"为了属性被迫结婚"扭曲了社交本质。婚姻边界的设计…
设计初衷 宝箱类玩法的信任危机都源于同一句话:"概率是不是骗人的。"期望公示把概率从事后争议变成事前契约:奖池概率表全量公示…
设计初衷 流拍物(拍卖未成交的退回物品)堆积在卖家背包里成为死资产:低价值物流拍后无人问津,高价值物流拍后卖家不愿降价重拍。…
业务场景 沙巴克战功榜每周结算,玩家提交战功前不知道"再打多少能进前 10、前 10 的奖励是什么"。名次预览:输入自己的战…