Skip to content

响应系统:主动方、被动方与两条效果链 ​

响应用于在伤害、技能阶段、投射物命中、单位死亡等时机检查条件、修改本次行为,或执行附加效果。配置反伤、受击自疗、吸血和死亡复活时,先分别确定原事件中的双方、响应挂载对象,以及附加效果的施法者与目标。

原事件中的主动方与被动方 ​

ResponseContext.Attacker 和 Defender 描述引发响应的事件,不是响应附加效果自身的 Caster 和 Target。例如 A 伤害 B,主动方是 A,被动方是 B;B 的反伤效果则通常由 B 对 A 执行。

响应类型主动方 Attacker被动方 DefenderIncomingContext
伤害 GameDataResponseDamage伤害效果的施法者伤害效果的目标EffectDamage,可从 ResponseContextDamage 读取 Damage 和 EffectDamage
技能阶段 GameDataResponseAbilityStage施法单位技能指令目标技能指令;另有 Ability、Stage、AbilityTarget
移动器命中 GameDataResponseMoverImpact移动器上下文的施法者本次命中目标Mover;投射物发射效果可读 LaunchEffect
死亡 GameDataResponseUnitDeath击杀者;没有击杀者时回退死亡单位死亡单位死亡单位;击杀者另读 Killer / KillerUnit

Defender 可以是位置等 ITarget,不要一律强转为 Unit。死亡响应的 IncomingContext 也不是致死伤害效果,不能将它强转为 EffectDamage。

Location 选择响应侧,附加效果默认指向另一方 ​

GameDataResponse.Location 默认为 ResponseLocation.Defender。它决定宿主以原事件中的哪一方触发响应;伤害、技能阶段和死亡响应都遵循这条规则。附加效果的默认目标按下表确定:

Location一般挂载位置ResponseEffect 的默认目标
Attacker主动方单位或其技能、Buff本次事件的 Defender
Defender被动方单位或其技能、Buff本次事件的 Attacker

Location = Defender 不表示给自己执行效果。 它很适合“受击后反伤攻击者”;“受击后治疗自己”还需在治疗节点显式选择目标。Location 也不会把响应成本转交给另一方:成本始终由响应宿主 Host 支付。

死亡响应中,Location = Defender 匹配 Host 自身死亡;Location = Attacker 匹配 Host 作为 Killer 击杀单位。无击杀者时不触发主动方响应;上下文的 Attacker 回退为死亡单位只用于目标解析,不会将死亡单位视为击杀者。若明确由单位击杀自己,则同一宿主分别满足两侧条件。

引发响应的效果链与响应附加效果链 ​

以 A 攻击 B、B 身上直接挂载被动方伤害响应为例:

text
A 的伤害效果链:Caster=A,伤害节点 Target=B
    |
    | 引发 B 的响应,IncomingContext 指向该伤害节点
    v
B 的响应附加效果链:Caster=B,根节点 DefaultTarget=A
    |
    +-- 默认目标的伤害节点:Target=A(反伤)
    +-- 显式选择 Caster 的治疗节点:Target=B(自疗)

两条链的上下文含义不同:

字段在响应附加效果中的含义
Caster来自响应 Owner 的执行上下文;不是自动沿用引发响应的施法者
DefaultTarget传给本节点的默认目标;根节点默认是事件另一方,子节点通常继承父节点的已解析目标
Target本节点按 TargetLocation 与 TargetType 解析后的实际目标
MainTarget创建响应附加效果共享数据时记录的主目标;改某个节点的目标不会自动改它
Shared.ResponseContext本次响应的上下文,可读取原事件的双方与具体响应信息
Shared.ResponseContext.IncomingContext引发响应的来源;它的 Caster/Target 仍属于原事件

响应附加效果由 Owner 创建,并携带响应上下文。不要把它当成原伤害节点直接 ExecuteChild 的延续,也不要假定它继承原树的施法者、主目标、局部变量或可按名称查找的祖先节点。需要原事件信息时,显式读取 Shared.ResponseContext,再按具体类型读取伤害、技能、命中或死亡信息。

例如在响应附加效果公式中读取原伤害:

csharp
#if SERVER
Amount = effect => effect.Shared.ResponseContext is ResponseContextDamage context
    ? context.Damage.Current * 0.2
    : 0,
#endif

这只决定数值,不会自动将效果目标改为受伤单位。公式参数若是 ResponseContext,是在读取响应事件;参数若是 Effect,effect.Caster 和 effect.Target 是当前附加效果的施法者与实际目标。

Host、Owner 与 Caster ​

Response.Host 是承载响应的单位,Response.Owner 是提供这条响应配置的对象。二者可能不同:

响应配置来源HostOwner附加效果的 Caster 来源
单位 Responses该单位该单位该单位
技能 Responses技能宿主单位技能实例技能宿主单位
Buff ResponsesBuff 宿主单位Buff 实例Buff 当前叠层保存的施加上下文,可能是另一单位

所以 TargetLocation.Caster 适合单位直接挂载响应时的“作用于自己”。Buff 响应中它可能指向 Buff 施加者,不能一律当成 Buff 宿主;需要宿主或死亡单位时,从 Shared.ResponseContext.Response.Host 或具体响应上下文显式取得。Buff 自身保存的创建链也不等于这次触发响应的伤害链。

三种常见配置 ​

受击反伤 ​

把伤害响应挂在 B 上,Location = Defender。附加伤害效果保留 TargetLocation.Default 时目标为攻击者 A;单位直接挂载时附加效果施法者为 B。反伤数值可以从 ResponseContextDamage.Damage 读取。

受击自疗 ​

同样在 B 上挂被动方响应,但治疗效果显式设置:

csharp
TargetLocation = new() { Value = TargetLocation.Caster },
TargetType = TargetType.Unit,

这样目标是 B 自己。若来自 Buff,先核对施加者与宿主,按上一节选择对象。

死亡后延迟复活自己 ​

在单位上直接挂 GameDataResponseUnitDeath,ResponseEffect 指向延迟效果,延迟结束后执行复活效果。两个节点都可显式指向 Caster:

json
{
  "Root": {
    "$type": "GameCore.Execution.Data.GameDataEffectPersistDelay",
    "Amount": "00:00:05",
    "TargetLocation": { "Value": "Caster" },
    "TargetType": "Unit",
    "FinalEffect": "$this.Revive"
  },
  "Revive": {
    "$type": "GameCore.Execution.Data.GameDataEffectUnitRevive",
    "TargetLocation": { "Value": "Caster" },
    "TargetType": "Unit"
  }
}

此片段是效果表,还需把死亡响应的 ResponseEffect 链接到它的 Root,并将响应挂入目标单位的 Responses。DeathRemovalDelay 需要覆盖复活等待时间,且不能使用会立即销毁实体的死亡类型。

Unit.Revive() 和复活效果只恢复存活状态,不自动补满生命值;按玩法另配生命恢复效果或生命值修改。

若保留默认目标,怪物杀死主角时,复活效果会指向怪物;直接 unit.Kill() 没有击杀者时,主动方回退为主角自己,两种测试便会表现不同。这不能单凭“主角没复活”判定为死亡响应未触发。

JSON、代码生成与排查 ​

数编 JSON 的枚举使用名称字符串,例如 "Location": "Defender"、"Value": "Caster"、"TargetType": "Unit"。不要用 C# 枚举的底层数字代替名称;生成器可能省略这类赋值,效果便使用默认值。C# 定义则使用对应枚举成员。

排查“响应没有生效”时按下列顺序核对:

  1. 核对源 JSON、继承后的有效值、生成代码及本局实际加载的配置。若生成结果出现 // Value = 1 或 // TargetType = 1,赋值没有生效;支持的编辑器版本还会给出 GDATA001 诊断。修源数据并重新生成,不手改生成代码。
  2. 确认响应实际挂载到预期 Host/Owner,并核对响应侧、激活状态、条件、概率与成本。
  3. 分别记录原事件 Attacker/Defender 和附加效果 Caster/DefaultTarget/Target 的对象身份。收到死亡事件只证明死亡发生,不能证明复活节点选中了死亡单位。
  4. 区分响应未执行、附加效果验证失败、效果成功但目标选错。LogExecutionFailure 记录效果执行失败;对活单位执行复活是无变化的成功调用,不会因此打印失败日志。
  5. 死亡复活同时测试“脚本直接 Kill”与“另一单位伤害致死”。若采用代码事件作为临时复活通路,恢复数编方案时避免两条通路同时执行。

运行期证据收集见从配置到运行证据与行为问题排查 Skill。效果树的一般目标规则见效果系统。