SPELL_EFFECT_SUMMON (28) 用法详解

目录

    • 概述
    • 定义
    • 核心机制
      • [1. 处理函数](#1. 处理函数)
      • [2. 相关的召唤效果](#2. 相关的召唤效果)
    • 数据库配置
      • [spell_effect 表 | SpellEffect.db2](#spell_effect 表 | SpellEffect.db2)
      • [SummonProperties.db2 配置](#SummonProperties.db2 配置)
    • 脚本注册与使用
    • 使用场景
      • [1. BOSS 战机制](#1. BOSS 战机制)
      • [2. 职业召唤系统](#2. 职业召唤系统)
      • [3. 功能性召唤](#3. 功能性召唤)
      • [4. 任务相关召唤](#4. 任务相关召唤)
    • 代码示例
      • [示例 1: Boss 战召唤小怪](#示例 1: Boss 战召唤小怪)
      • [示例 2: 战场宠物召唤](#示例 2: 战场宠物召唤)
      • [示例 3: 自定义召唤属性](#示例 3: 自定义召唤属性)
      • [示例 4: 多目标召唤](#示例 4: 多目标召唤)
      • [示例 5: 召唤并绑定 AI](#示例 5: 召唤并绑定 AI)
    • 最佳实践
      • [1. 选择合适的召唤类型](#1. 选择合适的召唤类型)
      • [2. 设置合理的持续时间](#2. 设置合理的持续时间)
      • [3. 考虑召唤位置](#3. 考虑召唤位置)
      • [4. 处理召唤失败](#4. 处理召唤失败)
      • [5. 管理召唤物生命周期](#5. 管理召唤物生命周期)
    • 调试与故障排除
    • 性能考虑
      • [1. 批量召唤](#1. 批量召唤)
      • [2. 内存管理](#2. 内存管理)
      • [3. 网络同步](#3. 网络同步)
      • [4. AI 负载](#4. AI 负载)
    • 扩展与自定义
    • 注意事项
      • [1. 数据库/DB2配置](#1. 数据库/DB2配置)
      • [2. 脚本注册](#2. 脚本注册)
      • [3. 空值检查](#3. 空值检查)
      • [4. 线程安全](#4. 线程安全)
      • [5. 性能影响](#5. 性能影响)
    • 总结

概述

SPELL_EFFECT_SUMMON 主要用于实现技能召唤功能。当玩家或 NPC 施放具有此效果的技能时,会在指定位置召唤出生物、物体或其他实体。

主要特点:

  • 是 TrinityCore 中实现召唤系统的核心
  • 召唤生物、守护者、载具、图腾等各种游戏对象,广泛应用于 BOSS 战机制、召唤宠物、临时守卫、载具召唤等
  • 支持多种召唤类型和属性配置

定义

SPELL_EFFECT_SUMMONSharedDefines.h 中定义为 SpellEffectName 枚举的第 28 个值

核心机制

1. 处理函数

SPELL_EFFECT_SUMMON 的处理函数在 SpellEffects.cpp 中的 EffectSummonType()

cpp 复制代码
void Spell::EffectSummonType()
{
    if (effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH)
        return;

    uint32 entry = effectInfo->MiscValue;
    if (!entry)
        return;

    SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(effectInfo->MiscValueB);
    if (!properties)
    {
        TC_LOG_ERROR("spells", "EffectSummonType: Unhandled summon type {}.", effectInfo->MiscValueB);
        return;
    }

    // 确定召唤者
    WorldObject* caster = m_caster;
    if (m_originalCaster)
        caster = m_originalCaster;

    // 计算持续时间
    Milliseconds duration = Milliseconds(m_spellInfo->CalcDuration(caster));

    // 确定召唤数量
    uint32 numSummons;
    switch (effectInfo->MiscValueB)
    {
        case 64: case 61: case 1101: case 66: case 648: case 2301:
        case 1061: case 1261: case 629: case 181: case 715:
        case 1562: case 833: case 1161: case 713:
            numSummons = (damage > 0) ? damage : 1;
            break;
        default:
            numSummons = 1;
            break;
    }

    // 根据召唤类型执行不同的召唤逻辑
    switch (properties->Control)
    {
        case SUMMON_CATEGORY_WILD:
        case SUMMON_CATEGORY_ALLY:
            SummonGuardian(effectInfo, entry, properties, numSummons, privateObjectOwner);
            break;
        case SUMMON_CATEGORY_VEHICLE:
            summon = unitCaster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, unitCaster, m_spellInfo->Id);
            break;
        // ... 其他情况处理
    }
}

2. 相关的召唤效果

TrinityCore 中还有其他相关的召唤效果:

效果名称 用途
SPELL_EFFECT_SUMMON 28 通用召唤
SPELL_EFFECT_SUMMON_PET 56 召唤宠物
SPELL_EFFECT_SUMMON_OBJECT_WILD 76 召唤野生物体
SPELL_EFFECT_SUMMON_PLAYER 85 召唤玩家
SPELL_EFFECT_SUMMON_OBJECT_SLOT1 104 槽位 1 物体召唤
SPELL_EFFECT_SUMMON_PERSONAL_GAMEOBJECT 171 个人游戏对象召唤

数据库配置

spell_effect 表 | SpellEffect.db2

要使用 SPELL_EFFECT_SUMMON,需要在 spell_effect 表或 SpellEffect.db2中配置以下关键字段:

字段 说明 示例值
Effect 效果类型 28 (SPELL_EFFECT_SUMMON)
EffectMiscValue 召唤生物的 entry ID creature_template.entry
EffectMiscValueB 召唤属性 ID 参考 SummonProperties.dbc
EffectApplyAuraName 通常为 0 0
EffectAmplitude 效果振幅 根据需求设置
EffectChainTarget 连锁目标数 0
EffectDieSides 伤害骰子面数 1
EffectBasePoints 基础点数 召唤数量或等级相关
EffectMechanic 机制类型 0
EffectImplicitTargetA 目标 A 取决于召唤位置
EffectImplicitTargetB 目标 B 通常为 0

SummonProperties.db2 配置

EffectMiscValueB 对应 SummonProperties.db2 中的条目,用于控制召唤的行为特性:

  • Control: 控制类型(宠物、守卫、载具等)
  • Flags: 特殊标志位
  • Title: 召唤物标题/类型
  • Slot: 装备槽位(如果是装备类召唤)

脚本注册与使用

基本脚本注册方式

cpp 复制代码
class spell_example_summon : public SpellScript
{
    PrepareSpellScript(spell_example_summon);

    void HandleSummon(SpellEffIndex effIndex)
    {
        // 自定义召唤逻辑
        PreventHitDefaultEffect(effIndex);

        // 获取效果信息
        if (SpellEffectInfo const* effect = GetEffectInfo(effIndex))
        {
            uint32 creatureEntry = effect->MiscValue;  // 生物模板 ID
            uint32 summonPropID = effect->MiscValueB; // 召唤属性 ID

            // 执行自定义召唤逻辑
            // ...
        }
    }

    void Register() override
    {
        OnEffectLaunch += SpellEffectFn(spell_example_summon::HandleSummon, EFFECT_0, SPELL_EFFECT_SUMMON);
    }
};

在脚本加载器中注册

cpp 复制代码
void AddSC_example_summon()
{
    RegisterSpellScript(spell_example_summon);
}

使用场景

1. BOSS 战机制

  • 召唤援军
  • 阶段转换
  • 特殊技能载体

2. 职业召唤系统

  • 术士宠物:使用 SPELL_EFFECT_SUMMON_PET
  • 猎人宠物:类似机制但可能有特殊处理
  • 死亡骑士食尸鬼:特定模板和属性

3. 功能性召唤

  • 工程学机械:临时召唤修理机器人等
  • 载具系统:召唤可骑乘的载具
  • 图腾召唤:萨满图腾的特殊处理

4. 任务相关召唤

  • 任务物品:召唤任务所需的 NPC 或物体
  • 剧情触发:过场动画中的角色召唤

代码示例

示例 1: Boss 战召唤小怪

cpp 复制代码
class spell_putricide_mutated_transformation : public SpellScript
{
    PrepareSpellScript(spell_putricide_mutated_transformation);

    void HandleSummon(SpellEffIndex effIndex)
    {
        // 阻止默认召唤效果
        PreventHitDefaultEffect(effIndex);

        Unit* caster = GetCaster();
        Position pos = GetHitDest()->GetPosition();

        if (!caster)
            return;

        // 召唤突变体
        caster->SummonCreature(NPC_MUTATED_ABOMINATION, pos, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000);
    }

    void Register() override
    {
        OnEffectLaunch += SpellEffectFn(spell_putricide_mutated_transformation::HandleSummon, EFFECT_0, SPELL_EFFECT_SUMMON);
    }
};

示例 2: 战场宠物召唤

cpp 复制代码
class spell_summon_battle_pet : public SpellScript
{
    PrepareSpellScript(spell_summon_battle_pet);

    void HandleSummon(SpellEffIndex effIndex)
    {
        PreventHitDefaultEffect(effIndex);

        Unit* caster = GetCaster();
        if (!caster)
            return;

        Position pos = caster->GetPosition();
        caster->SummonCreature(NPC_BATTLE_PET, pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1000);
    }

    void Register() override
    {
        OnEffectLaunch += SpellEffectFn(spell_summon_battle_pet::HandleSummon, EFFECT_0, SPELL_EFFECT_SUMMON);
    }
};

示例 3: 自定义召唤属性

cpp 复制代码
class spell_custom_summon_properties : public SpellScript
{
    PrepareSpellScript(spell_custom_summon_properties);

    void HandleSummon(SpellEffIndex effIndex)
    {
        PreventHitDefaultEffect(effIndex);

        Unit* caster = GetCaster();
        Position pos = GetHitDest()->GetPosition();

        if (!caster)
            return;

        TempSummonType summonType = TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
        Milliseconds duration(60000);

        if (caster->GetMap()->IsHeroic())
        {
            duration = Milliseconds(120000); // 英雄模式延长持续时间
        }

        caster->SummonCreature(NPC_CUSTOM_SUMMON, pos, summonType, duration);
    }

    void Register() override
    {
        OnEffectLaunch += SpellEffectFn(spell_custom_summon_properties::HandleSummon, EFFECT_0, SPELL_EFFECT_SUMMON);
    }
};

示例 4: 多目标召唤

cpp 复制代码
class spell_summon_multiple_targets : public SpellScript
{
    PrepareSpellScript(spell_summon_multiple_targets);

    void HandleSummon(SpellEffIndex effIndex)
    {
        PreventHitDefaultEffect(effIndex);

        Unit* caster = GetCaster();
        if (!caster)
            return;

        // 在目标位置召唤多个单位
        Position pos = GetHitDest()->GetPosition();

        // 召唤 3 个单位
        for (int i = 0; i < 3; ++i)
        {
            Position offset = pos;
            offset.m_positionX += frand(-2.0f, 2.0f);
            offset.m_positionY += frand(-2.0f, 2.0f);

            caster->SummonCreature(NPC_MINION, offset, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000);
        }
    }

    void Register() override
    {
        OnEffectLaunch += SpellEffectFn(spell_summon_multiple_targets::HandleSummon, EFFECT_0, SPELL_EFFECT_SUMMON);
    }
};

示例 5: 召唤并绑定 AI

cpp 复制代码
class spell_summon_with_ai : public SpellScript
{
    PrepareSpellScript(spell_summon_with_ai);

    void HandleSummon(SpellEffIndex effIndex)
    {
        PreventHitDefaultEffect(effIndex);

        Unit* caster = GetCaster();
        Position pos = GetHitDest()->GetPosition();

        if (!caster)
            return;

        Creature* summoned = caster->SummonCreature(NPC_SUMMONED_GUARDIAN, pos, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000);

        if (summoned)
        {
            // 设置召唤物的 AI
            summoned->SetFaction(caster->GetFaction());
            summoned->SetReactState(REACT_DEFENSIVE);

            // 如果是玩家召唤的,可以绑定到玩家
            if (Player* player = caster->ToPlayer())
            {
                summoned->SetOwnerGUID(player->GetGUID());
            }
        }
    }

    void Register() override
    {
        OnEffectLaunch += SpellEffectFn(spell_summon_with_ai::HandleSummon, EFFECT_0, SPELL_EFFECT_SUMMON);
    }
};

最佳实践

1. 选择合适的召唤类型

根据需求选择正确的召唤类型:

cpp 复制代码
// 临时召唤
caster->SummonCreature(entry, pos, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, duration);

// 宠物类型(持续存在直到死亡或解散)
caster->SummonCreature(entry, pos, TEMPSUMMON_CORPSE_DESPAWN, 0);

// 玩家宠物
caster->SummonCreature(entry, pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 0);

2. 设置合理的持续时间

根据场景设置合适的持续时间:

cpp 复制代码
// 短暂召唤(如战斗辅助)
Milliseconds duration(30000); // 30 秒

// 持续召唤(如 BOSS 战)
Milliseconds duration(600000); // 10 分钟

// 永久召唤(直到死亡)
Milliseconds duration(0); // 0 表示永久

3. 考虑召唤位置

确保召唤位置安全且合理:

cpp 复制代码
void HandleSummon(SpellEffIndex effIndex)
{
    Unit* caster = GetCaster();
    Position pos = GetHitDest()->GetPosition();

    // 检查位置是否有效
    float groundZ = caster->GetMap()->GetHeight(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ());
    if (groundZ > INVALID_HEIGHT)
    {
        pos.m_positionZ = groundZ; // 调整到地面高度
    }

    caster->SummonCreature(entry, pos, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, duration);
}

4. 处理召唤失败

始终处理召唤失败的情况:

cpp 复制代码
void HandleSummon(SpellEffIndex effIndex)
{
    Unit* caster = GetCaster();
    if (!caster)
        return;

    Position pos = GetHitDest()->GetPosition();

    Creature* summoned = caster->SummonCreature(entry, pos, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, duration);

    if (!summoned)
    {
        TC_LOG_ERROR("scripts", "Failed to summon creature {}", entry);
        return;
    }

    // 成功召唤后的处理
}

5. 管理召唤物生命周期

合理管理召唤物的生命周期:

cpp 复制代码
void HandleSummon(SpellEffIndex effIndex)
{
    Unit* caster = GetCaster();
    Creature* summoned = caster->SummonCreature(entry, pos, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, duration);

    if (summoned)
    {
        // 设置召唤物会在一定时间后自动消失
        summoned->DespawnOrUnsummon(duration);
    }
}

调试与故障排除

常见问题

  1. 召唤物未出现

    • 检查 EffectMiscValue 是否为有效的 creature_template.entry
    • 验证 EffectMiscValueB 对应的 SummonProperties 条目存在
    • 确认施法者有权限在该位置召唤
  2. 召唤物立即消失

    • 检查持续时间计算是否正确
    • 验证召唤属性的 Flags 设置
    • 确认地图支持该类型的召唤
  3. 召唤位置错误

    • 检查 EffectImplicitTargetA 的目标选择
    • 验证施法者的朝向和位置数据
    • 考虑碰撞检测和地面高度

日志调试

cpp 复制代码
void HandleSummon(SpellEffIndex effIndex)
{
    TC_LOG_INFO("scripts", "Summoning creature entry {} with properties {}",
        effectInfo->MiscValue, effectInfo->MiscValueB);

    // 执行召唤逻辑
}

性能考虑

1. 批量召唤

对于需要召唤多个单位的技能,合理设置 numSummons

cpp 复制代码
// 使用数据库配置的召唤数量,而不是在脚本中循环
// 效率更高

2. 内存管理

及时清理临时召唤物,避免内存泄漏:

cpp 复制代码
// 使用合适的召唤类型
TEMPSUMMON_TIMED_OR_DEAD_DESPAWN  // 超时或死亡后消失
TEMPSUMMON_CORPSE_DESPAWN          // 死亡后尸体消失

3. 网络同步

大量召唤时注意网络包大小和处理频率:

cpp 复制代码
// 避免在短时间内召唤大量单位
// 可以使用延迟召唤

4. AI 负载

过多召唤物可能影响服务器性能,需要合理限制:

cpp 复制代码
// 限制最大召唤数量
if (caster->GetGuardianCount() >= MAX_GUARDIANS)
    return;

扩展与自定义

自定义召唤逻辑

可以通过继承 SpellScript 并重写相关方法来添加自定义行为:

cpp 复制代码
class custom_summon_script : public SpellScript
{
    void CustomSummonHandling()
    {
        // 修改召唤位置
        // 设置特殊属性
        // 绑定额外效果
        // 自定义 AI 行为
    }
};

动态召唤控制

根据战斗状态动态调整召唤参数:

cpp 复制代码
void DynamicSummonAdjustment()
{
    if (IsHeroicMode())
        duration *= 2;  // 英雄模式延长持续时间

    if (caster->GetHealthPct() < 30.0f)
        numSummons = 2; // 低血量时召唤更多援军
}

注意事项

1. 数据库/DB2配置

确保法术在数据库/DB2中正确配置:

sql 复制代码
-- Effect=28 (SPELL_EFFECT_SUMMON)
UPDATE spell_effect
SET Effect = 28,
    EffectMiscValue = CREATURE_ENTRY,
    EffectMiscValueB = SUMMON_PROPERTIES_ID
WHERE id = YOUR_SPELL_ID;

2. 脚本注册

必须在脚本加载器中注册:

cpp 复制代码
void AddSC_custom_summon()
{
    RegisterSpellScript(spell_custom_summon);
}

3. 空值检查

始终检查关键指针:

cpp 复制代码
void HandleSummon(SpellEffIndex /*effIndex*/)
{
    Unit* caster = GetCaster();
    if (!caster)
        return;

    // 安全的逻辑代码
}

4. 线程安全

注意 TrinityCore 是多线程的,确保代码是线程安全的:

  • 避免静态变量
  • 使用线程安全的数据结构
  • 注意对象生命周期

5. 性能影响

召唤物会增加服务器负载:

  • 限制召唤数量
  • 合理设置持续时间
  • 及时清理不需要的召唤物

总结

SPELL_EFFECT_SUMMON 是 TrinityCore 中实现召唤功能的强大工具,通过合理配置数据库字段和脚本逻辑,可以实现从简单的宠物召唤到复杂的 BOSS 战机制等各种功能。关键在于理解各个参数的作用关系,并根据具体需求选择合适的召唤类型和属性配置。

关键要点:

  • SPELL_EFFECT_SUMMON 用于召唤各种游戏对象
  • 需要正确配置 EffectMiscValueEffectMiscValueB
  • 支持通过 SpellScript 进行深度定制
  • 广泛应用于 BOSS 战、职业召唤、功能召唤等场景
  • 注意性能、线程安全和召唤物生命周期管理
相关推荐
一只大侠的侠35 分钟前
React Native开源鸿蒙跨平台训练营 Day16自定义 useForm 高性能验证
flutter·开源·harmonyos
IvorySQL1 小时前
PostgreSQL 分区表的 ALTER TABLE 语句执行机制解析
数据库·postgresql·开源
一只大侠的侠2 小时前
Flutter开源鸿蒙跨平台训练营 Day11从零开发商品详情页面
flutter·开源·harmonyos
一只大侠的侠2 小时前
React Native开源鸿蒙跨平台训练营 Day18自定义useForm表单管理实战实现
flutter·开源·harmonyos
一只大侠的侠2 小时前
React Native开源鸿蒙跨平台训练营 Day20自定义 useValidator 实现高性能表单验证
flutter·开源·harmonyos
晚霞的不甘3 小时前
Flutter for OpenHarmony 可视化教学:A* 寻路算法的交互式演示
人工智能·算法·flutter·架构·开源·音视频
晚霞的不甘4 小时前
Flutter for OpenHarmony 实现计算几何:Graham Scan 凸包算法的可视化演示
人工智能·算法·flutter·架构·开源·音视频
猫头虎4 小时前
OpenClaw-VSCode:在 VS Code 里玩转 OpenClaw,远程管理+SSH 双剑合璧
ide·vscode·开源·ssh·github·aigc·ai编程
一只大侠的侠4 小时前
Flutter开源鸿蒙跨平台训练营 Day12从零开发通用型登录页面
flutter·开源·harmonyos
wenzhangli74 小时前
OoderAgent 企业版 2.0 发布的意义:一次生态战略的全面升级
人工智能·开源