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 战、职业召唤、功能召唤等场景
  • 注意性能、线程安全和召唤物生命周期管理
相关推荐
向前V1 小时前
Flutter for OpenHarmony轻量级开源记事本App实战:笔记编辑器
开发语言·笔记·python·flutter·游戏·开源·编辑器
CoderJia程序员甲3 小时前
GitHub 热榜项目 - 日榜(2026-01-24)
git·ai·开源·llm·github
lbb 小魔仙4 小时前
【Harmonyos】开源鸿蒙跨平台训练营DAY3:HarmonyOS + Flutter + Dio:从零实现跨平台数据清单应用完整指南
flutter·开源·harmonyos
兆龙电子单片机设计4 小时前
【STM32项目开源】STM32单片机智能台灯控制系统-机智云
stm32·单片机·嵌入式硬件·物联网·开源·毕业设计
Aaron_9454 小时前
Dify:开源 LLM 应用开发平台的全面解析与实战指南
开源
互联网Ai好者7 小时前
米柚AI搜索(MiYo.AI):实时智能搜索聚合平台开源推荐
人工智能·开源
冬奇Lab7 小时前
一天一个开源项目(第2篇):Remotion - 用 React 程序化创建视频
react.js·开源·音视频
信创天地8 小时前
信创运维核心技术:国产化软硬件适配与故障排查全解析
运维·人工智能·开源·dubbo·运维开发·risc-v
时光慢煮12 小时前
打造跨端博客分类与标签组件:Flutter × OpenHarmony 实战
flutter·开源·openharmony
Github掘金计划18 小时前
Claude Work 开源平替来了:让 AI 代理从“终端命令“变成“产品体验“
人工智能·开源