生命值 Health
生命值是角色和生物承受伤害的核心属性;当前值降至最低生命值时会触发濒死或死亡事件。玩家的初始生命上限来自角色初始化,伤害还会依次受到护甲、抗性、无敌状态、外部减伤与生命上限惩罚影响。
概述
生命值由 components/health.lua 管理。组件保存当前生命值、基础上限、最低生命值、无敌状态、生命上限惩罚、吸收与减伤修正,并通过 DoDelta 统一处理生命值变化。
玩家在初始化时添加生命组件,并将生命上限设为 150;如果世界设置提供玩家承伤倍率,还会把 1 注册为外部吸收修正。其他生物可以在自己的 prefab 中设置不同的生命上限、最低生命值和伤害限制。
生命上限与当前值
基本计算
组件的默认基础值是由组件内部初始化的默认值,但玩家不会使用这个默认值,而是在 player_common.lua 中调用 SetMaxHealth 设置为 150。SetMaxHealth 会同时把当前生命值设为新的上限,然后刷新生命值界面。
生命上限惩罚以比例保存。有效生命上限为:
有效上限 = 基础生命上限 × (1 − 生命上限惩罚)
当前生命值不能超过有效上限。当前生命值低于有效上限时,IsHurt() 返回真;生命值百分比则按当前生命值除以基础上限计算,代码另提供按有效上限计算的百分比接口。
当前版本启用生命上限惩罚,惩罚上限为 75%。这意味着复活、某些死亡或复活道具产生的惩罚会压低可用上限,而不是直接造成等量的当前生命值伤害。
伤害处理顺序
战斗伤害
通过战斗组件受到攻击时,处理顺序大致如下:
combat.lua先确认目标没有死亡,并处理闪避、伤害重定向等效果。inventory.lua检查装备上的抗性与护甲。能完全抵抗该次伤害的装备会直接使伤害归零;否则先应用伤害类型抗性。- 护甲吸收普通伤害。多件护甲中,实际生命值减免使用最高的吸收比例;被吸收的伤害会按各护甲的吸收值分摊到耐久损耗。
- 位面伤害等特殊伤害会单独经过对应的防御处理,剩余伤害与普通伤害合并。
Health:DoDelta执行无敌检查、生命组件自身的吸收与外部减伤修正,并将最终结果写入当前生命值。
护甲减伤不是生命组件直接完成的;生命组件接收的是经过 Inventory:ApplyDamage 处理后的伤害。除装备护甲外,生命组件还支持外部吸收修正、外部固定减伤修正以及每次受伤上限。若设置了单次最大伤害,负向变化会被限制在该上限以内。
非战斗伤害与恢复
火焰伤害由生命组件专门处理:组件会追踪着火状态,并按火焰倍率计算伤害;连续火焰伤害还受到每秒上限 120 的限制。生命组件也支持按周期恢复,以及由外部来源注册的多组周期恢复;恢复在死亡后不会继续执行。
饥饿、温度、黑暗、溺水以及其他环境系统可以通过 DoDelta 或生命惩罚接口改变生命值。health.lua 明确提供了温度和饥饿的非致死开关,但当前调谐值 NONLETHAL_TEMPERATURE、NONLETHAL_HUNGER 与 NONLETHAL_DARKNESS 均为关闭状态;因此不能仅凭这些开关推断当前世界中某种环境伤害一定不会致死。
无敌与伤害免疫
Health:IsInvincible() 在以下任一条件成立时返回真:
- 生命组件的
invincible标志为真; - 角色状态图带有
temp_invincible状态标签。
普通 DoDelta 在无敌时会直接返回,不改变生命值;玩家处于传送状态时也会跳过普通生命变化。战斗组件在把攻击交给生命组件前同样会检查无敌状态。
玩家加载保护会设置 SetInvincible(true),同时添加 notarget 与 spawnprotection 标签并关闭物理;保护解除时先恢复物理,随后经过 1 秒级?(未在代码中以该单位定义)不应这样理解——源码实际使用的是固定延迟 1.5 秒。由于该局部常量无法用 TUNING 占位符表达,加载保护解除延迟为 1.5 秒;随后才移除保护标签并关闭无敌。
Kill() 会尝试将生命值降至零,但普通路径仍会受到无敌影响;ForceKill() 使用忽略无敌的参数,可绕过无敌。两者都属于源码接口,不代表正常游戏玩法中的可用道具或操作。
濒死、死亡与尸体
生命值变化经过 SetVal 时,会先把数值限制在有效生命上限以内;低于或等于最低生命值时,会把当前生命值设为最低生命值并触发 minhealth 事件。
当生命值从正数降至零或更低时,组件会:
- 记录造成死亡的来源;
- 向世界发送
entity_death事件,并向实体发送death事件; - 根据实体是否能够成为尸体,决定进入尸体流程还是淡出并移除;
- 更新玩家或敌人的击杀进度统计。
玩家的死亡后续由 player_common.lua 按配置处理:启用鬼魂时监听 makeplayerghost、respawnfromghost 与 ghostdissipated;使用可复活尸体时则监听 respawnfromcorpse 和 playerdied。因此“生命值归零”是死亡事件的触发点,之后是否成为鬼魂、尸体或直接结束由玩家配置与对应事件处理决定。
复活与生命上限惩罚
玩家成为鬼魂后,带有 reviver 标签的复活物品可以被接收。使用复活物品时,源码会消耗该物品并发送 respawnfromghost 事件;除带有免除惩罚标签的复活来源,通常还会增加生命上限惩罚 25%。生命上限惩罚会被限制在 75% 以内。
玩家复活后具体的当前生命值恢复方式由对应的玩家复活事件处理;本页确认的是复活入口会应用生命上限惩罚,而不是把该惩罚当作一次普通伤害。生命上限惩罚可以通过生命组件的 SetPenalty、DeltaPenalty 与保存数据继续存在。
可验证的实用建议
- 先提高有效生命上限,再看当前生命值。 生命上限惩罚会降低可用上限;复活后生命条变短不等于护甲失效。
- 护甲应在真正承伤前穿戴。 战斗伤害会先经过装备抗性与护甲吸收,再进入生命组件;没有装备在身上时,生命组件不会替你计算护甲减伤。
- 不要把无敌和闪避混为一谈。 闪避在战斗组件中处理;无敌则由生命组件和状态标签判断。加载保护期间还会同时设置
notarget与spawnprotection。 - 着火时应尽快停止持续伤害来源。 火焰伤害会被生命组件按时间持续处理,并受
120的每秒上限约束;上限不是免伤。 - 复活资源应视为有长期代价的资源。 普通复活会增加
25%的生命上限惩罚,并且总惩罚不能超过75%。 - 当目标已经死亡时继续攻击没有意义。
Combat:GetAttacked会在目标生命组件判定死亡后直接返回。
代码参考
scripts/components/health.lua:生命值存储、上限惩罚、无敌、火焰伤害、周期恢复、SetVal、DoDelta、死亡事件。scripts/components/combat.lua:攻击命中、闪避、伤害类型修正、特殊伤害以及把最终伤害交给生命组件。scripts/components/inventory.lua:装备抗性、护甲吸收、特殊伤害防御与护甲耐久损耗。scripts/prefabs/player_common.lua:玩家生命组件初始化、玩家加载保护、鬼魂复活入口与事件监听。scripts/tuning.lua:玩家生命上限、玩家承伤倍率、火焰伤害上限、复活生命上限惩罚和非致死开关。