目录
- 概述
- 定义
- 核心机制
- 1. 处理函数
- 2. 相关的召唤效果
- 数据库配置
- spell_effect 表 | SpellEffect.db2
- SummonProperties.db2 配置
- 脚本注册与使用
- 基本脚本注册方式
- 在脚本加载器中注册
- 使用场景
- 1. BOSS 战机制
- 2. 职业召唤系统
- 3. 功能性召唤
- 4. 任务相关召唤
- 代码示例
- 示例 1: Boss 战召唤小怪
- 示例 2: 战场宠物召唤
- 示例 3: 自定义召唤属性
- 示例 4: 多目标召唤
- 示例 5: 召唤并绑定 AI
- 最佳实践
- 1. 选择合适的召唤类型
- 2. 设置合理的持续时间
- 3. 考虑召唤位置
- 4. 处理召唤失败
- 5. 管理召唤物生命周期
- 调试与故障排除
- 常见问题
- 日志调试
- 性能考虑
- 1. 批量召唤
- 2. 内存管理
- 3. 网络同步
- 4. AI 负载
- 扩展与自定义
- 自定义召唤逻辑
- 动态召唤控制
- 注意事项
- 1. 数据库/DB2配置
- 2. 脚本注册
- 3. 空值检查
- 4. 线程安全
- 5. 性能影响
- 总结
概述
SPELL_EFFECT_SUMMON主要用于实现技能召唤功能。当玩家或 NPC 施放具有此效果的技能时,会在指定位置召唤出生物、物体或其他实体。
主要特点:
- 是 TrinityCore 中实现召唤系统的核心
- 召唤生物、守护者、载具、图腾等各种游戏对象,广泛应用于 BOSS 战机制、召唤宠物、临时守卫、载具召唤等
- 支持多种召唤类型和属性配置
定义
SPELL_EFFECT_SUMMON在SharedDefines.h中定义为SpellEffectName枚举的第 28 个值
核心机制
1. 处理函数
SPELL_EFFECT_SUMMON的处理函数在SpellEffects.cpp中的EffectSummonType():
voidSpell::EffectSummonType(){if(effectHandleMode!=SPELL_EFFECT_HANDLE_LAUNCH)return;uint32 entry=effectInfo->MiscValue;if(!entry)return;SummonPropertiesEntryconst*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){case64:case61:case1101:case66:case648:case2301:case1061:case1261:case629:case181:case715:case1562:case833:case1161:case713:numSummons=(damage>0)?damage:1;break;default:numSummons=1;break;}// 根据召唤类型执行不同的召唤逻辑switch(properties->Control){caseSUMMON_CATEGORY_WILD:caseSUMMON_CATEGORY_ALLY:SummonGuardian(effectInfo,entry,properties,numSummons,privateObjectOwner);break;caseSUMMON_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: 装备槽位(如果是装备类召唤)
脚本注册与使用
基本脚本注册方式
classspell_example_summon:publicSpellScript{PrepareSpellScript(spell_example_summon);voidHandleSummon(SpellEffIndex effIndex){// 自定义召唤逻辑PreventHitDefaultEffect(effIndex);// 获取效果信息if(SpellEffectInfoconst*effect=GetEffectInfo(effIndex)){uint32 creatureEntry=effect->MiscValue;// 生物模板 IDuint32 summonPropID=effect->MiscValueB;// 召唤属性 ID// 执行自定义召唤逻辑// ...}}voidRegister()override{OnEffectLaunch+=SpellEffectFn(spell_example_summon::HandleSummon,EFFECT_0,SPELL_EFFECT_SUMMON);}};在脚本加载器中注册
voidAddSC_example_summon(){RegisterSpellScript(spell_example_summon);}使用场景
1. BOSS 战机制
- 召唤援军
- 阶段转换
- 特殊技能载体
2. 职业召唤系统
- 术士宠物:使用
SPELL_EFFECT_SUMMON_PET - 猎人宠物:类似机制但可能有特殊处理
- 死亡骑士食尸鬼:特定模板和属性
3. 功能性召唤
- 工程学机械:临时召唤修理机器人等
- 载具系统:召唤可骑乘的载具
- 图腾召唤:萨满图腾的特殊处理
4. 任务相关召唤
- 任务物品:召唤任务所需的 NPC 或物体
- 剧情触发:过场动画中的角色召唤
代码示例
示例 1: Boss 战召唤小怪
classspell_putricide_mutated_transformation:publicSpellScript{PrepareSpellScript(spell_putricide_mutated_transformation);voidHandleSummon(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);}voidRegister()override{OnEffectLaunch+=SpellEffectFn(spell_putricide_mutated_transformation::HandleSummon,EFFECT_0,SPELL_EFFECT_SUMMON);}};示例 2: 战场宠物召唤
classspell_summon_battle_pet:publicSpellScript{PrepareSpellScript(spell_summon_battle_pet);voidHandleSummon(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);}voidRegister()override{OnEffectLaunch+=SpellEffectFn(spell_summon_battle_pet::HandleSummon,EFFECT_0,SPELL_EFFECT_SUMMON);}};示例 3: 自定义召唤属性
classspell_custom_summon_properties:publicSpellScript{PrepareSpellScript(spell_custom_summon_properties);voidHandleSummon(SpellEffIndex effIndex){PreventHitDefaultEffect(effIndex);Unit*caster=GetCaster();Position pos=GetHitDest()->GetPosition();if(!caster)return;TempSummonType summonType=TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;Millisecondsduration(60000);if(caster->GetMap()->IsHeroic()){duration=Milliseconds(120000);// 英雄模式延长持续时间}caster->SummonCreature(NPC_CUSTOM_SUMMON,pos,summonType,duration);}voidRegister()override{OnEffectLaunch+=SpellEffectFn(spell_custom_summon_properties::HandleSummon,EFFECT_0,SPELL_EFFECT_SUMMON);}};示例 4: 多目标召唤
classspell_summon_multiple_targets:publicSpellScript{PrepareSpellScript(spell_summon_multiple_targets);voidHandleSummon(SpellEffIndex effIndex){PreventHitDefaultEffect(effIndex);Unit*caster=GetCaster();if(!caster)return;// 在目标位置召唤多个单位Position pos=GetHitDest()->GetPosition();// 召唤 3 个单位for(inti=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);}}voidRegister()override{OnEffectLaunch+=SpellEffectFn(spell_summon_multiple_targets::HandleSummon,EFFECT_0,SPELL_EFFECT_SUMMON);}};示例 5: 召唤并绑定 AI
classspell_summon_with_ai:publicSpellScript{PrepareSpellScript(spell_summon_with_ai);voidHandleSummon(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){// 设置召唤物的 AIsummoned->SetFaction(caster->GetFaction());summoned->SetReactState(REACT_DEFENSIVE);// 如果是玩家召唤的,可以绑定到玩家if(Player*player=caster->ToPlayer()){summoned->SetOwnerGUID(player->GetGUID());}}}voidRegister()override{OnEffectLaunch+=SpellEffectFn(spell_summon_with_ai::HandleSummon,EFFECT_0,SPELL_EFFECT_SUMMON);}};最佳实践
1. 选择合适的召唤类型
根据需求选择正确的召唤类型:
// 临时召唤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. 设置合理的持续时间
根据场景设置合适的持续时间:
// 短暂召唤(如战斗辅助)Millisecondsduration(30000);// 30 秒// 持续召唤(如 BOSS 战)Millisecondsduration(600000);// 10 分钟// 永久召唤(直到死亡)Millisecondsduration(0);// 0 表示永久3. 考虑召唤位置
确保召唤位置安全且合理:
voidHandleSummon(SpellEffIndex effIndex){Unit*caster=GetCaster();Position pos=GetHitDest()->GetPosition();// 检查位置是否有效floatgroundZ=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. 处理召唤失败
始终处理召唤失败的情况:
voidHandleSummon(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. 管理召唤物生命周期
合理管理召唤物的生命周期:
voidHandleSummon(SpellEffIndex effIndex){Unit*caster=GetCaster();Creature*summoned=caster->SummonCreature(entry,pos,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,duration);if(summoned){// 设置召唤物会在一定时间后自动消失summoned->DespawnOrUnsummon(duration);}}调试与故障排除
常见问题
召唤物未出现
- 检查
EffectMiscValue是否为有效的 creature_template.entry - 验证
EffectMiscValueB对应的 SummonProperties 条目存在 - 确认施法者有权限在该位置召唤
- 检查
召唤物立即消失
- 检查持续时间计算是否正确
- 验证召唤属性的 Flags 设置
- 确认地图支持该类型的召唤
召唤位置错误
- 检查
EffectImplicitTargetA的目标选择 - 验证施法者的朝向和位置数据
- 考虑碰撞检测和地面高度
- 检查
日志调试
voidHandleSummon(SpellEffIndex effIndex){TC_LOG_INFO("scripts","Summoning creature entry {} with properties {}",effectInfo->MiscValue,effectInfo->MiscValueB);// 执行召唤逻辑}性能考虑
1. 批量召唤
对于需要召唤多个单位的技能,合理设置numSummons:
// 使用数据库配置的召唤数量,而不是在脚本中循环// 效率更高2. 内存管理
及时清理临时召唤物,避免内存泄漏:
// 使用合适的召唤类型TEMPSUMMON_TIMED_OR_DEAD_DESPAWN// 超时或死亡后消失TEMPSUMMON_CORPSE_DESPAWN// 死亡后尸体消失3. 网络同步
大量召唤时注意网络包大小和处理频率:
// 避免在短时间内召唤大量单位// 可以使用延迟召唤4. AI 负载
过多召唤物可能影响服务器性能,需要合理限制:
// 限制最大召唤数量if(caster->GetGuardianCount()>=MAX_GUARDIANS)return;扩展与自定义
自定义召唤逻辑
可以通过继承SpellScript并重写相关方法来添加自定义行为:
classcustom_summon_script:publicSpellScript{voidCustomSummonHandling(){// 修改召唤位置// 设置特殊属性// 绑定额外效果// 自定义 AI 行为}};动态召唤控制
根据战斗状态动态调整召唤参数:
voidDynamicSummonAdjustment(){if(IsHeroicMode())duration*=2;// 英雄模式延长持续时间if(caster->GetHealthPct()<30.0f)numSummons=2;// 低血量时召唤更多援军}注意事项
1. 数据库/DB2配置
确保法术在数据库/DB2中正确配置:
-- Effect=28 (SPELL_EFFECT_SUMMON)UPDATEspell_effectSETEffect=28,EffectMiscValue=CREATURE_ENTRY,EffectMiscValueB=SUMMON_PROPERTIES_IDWHEREid=YOUR_SPELL_ID;2. 脚本注册
必须在脚本加载器中注册:
voidAddSC_custom_summon(){RegisterSpellScript(spell_custom_summon);}3. 空值检查
始终检查关键指针:
voidHandleSummon(SpellEffIndex/*effIndex*/){Unit*caster=GetCaster();if(!caster)return;// 安全的逻辑代码}4. 线程安全
注意 TrinityCore 是多线程的,确保代码是线程安全的:
- 避免静态变量
- 使用线程安全的数据结构
- 注意对象生命周期
5. 性能影响
召唤物会增加服务器负载:
- 限制召唤数量
- 合理设置持续时间
- 及时清理不需要的召唤物
总结
SPELL_EFFECT_SUMMON是 TrinityCore 中实现召唤功能的强大工具,通过合理配置数据库字段和脚本逻辑,可以实现从简单的宠物召唤到复杂的 BOSS 战机制等各种功能。关键在于理解各个参数的作用关系,并根据具体需求选择合适的召唤类型和属性配置。
关键要点:
SPELL_EFFECT_SUMMON用于召唤各种游戏对象- 需要正确配置
EffectMiscValue和EffectMiscValueB - 支持通过
SpellScript进行深度定制 - 广泛应用于 BOSS 战、职业召唤、功能召唤等场景
- 注意性能、线程安全和召唤物生命周期管理