威胁系统(Threat System)概述
目录
核心组件
工作原理
实现逻辑
工作流程
注意事项
威胁系统是MMORPG游戏中怪物选择攻击目标的核心机制。在TrinityCore中,威胁系统负责管理生物(Creature)的攻击目标选择,确保生物能够根据威胁值选择合适的攻击目标。
核心组件
威胁系统主要由两个类组成:
- ThreatManager - 管理单位的威胁列表
- ThreatReference - 威胁列表中的单个条目,包含威胁值和其他相关信息
工作原理
-
威胁条目管理:每个ThreatReference对象存储在以下位置:
- 被威胁单位(所有者)的(未)排序威胁列表中
- 威胁制造者(受害者)的"被我威胁"列表中
-
威胁值计算:威胁值通过AddThreat方法添加,会考虑各种修饰符,如:
- 法术特定的威胁修饰符
- 特定伤害类型的威胁修饰符(如神圣、火焰等)
- 临时修饰符(来自光环效果)
-
目标选择:通过ReselectVictim方法,根据威胁值选择新的目标,遵循以下优先级:
- 在线状态(在线 > 压制 > 离线)
- 嘲讽状态(嘲讽 > 正常 > 去嘲讽)
- 威胁值大小
-
威胁重定向:系统支持威胁重定向,允许将一部分威胁转移到其他单位上,这在某些技能(如嘲讽、保护性技能)中使用。
实现逻辑
-
数据结构
- 使用boost::heap::fibonacci_heap来维护排序的威胁列表
- 使用std::unordered_map存储未排序的威胁引用
-
威胁状态
- ONLINE_STATE_ONLINE:正常状态,目标有效且可攻击
- ONLINE_STATE_SUPPRESSED:目标可攻击但不适宜(如免疫效果或控制技能)
- ONLINE_STATE_OFFLINE:目标无效(如不在范围内或无敌状态)
-
嘲讽状态
- TAUNT_STATE_TAUNT:强制攻击该目标
- TAUNT_STATE_NONE:正常状态
- TAUNT_STATE_DETAUNT:降低该目标的威胁优先级
-
更新机制
- 威胁列表每秒更新一次(THREAT_UPDATE_INTERVAL)
- 通过UpdateVictim方法重新选择目标
工作流程
1. 系统初始化
威胁系统在生物创建时初始化:
- ThreatManager对象作为Unit类的成员变量被创建
- 在Creature::Create方法中调用ThreatManager::Initialize()方法
- 通过ThreatManager::CanHaveThreatList()方法检查该单位是否可以拥有威胁列表(只有特定类型的生物可以拥有威胁列表)
2. 威胁生成
当单位受到伤害或受到其他影响时,会生成威胁:
- 通过Unit::AddThreat()方法(实际上调用ThreatManager::AddThreat())添加威胁
- 系统首先检查是否可以跳过威胁生成:
- 如果法术有SPELL_ATTR1_NO_THREAT属性,则不生成威胁
- 如果生物未处于战斗状态且法术有SPELL_ATTR2_NO_INITIAL_THREAT属性,则不生成初始威胁
- 处理特殊情况:
- 如果目标在载具上,威胁会转移到载具上
- 如果目标是私人对象(个人副本中的单位),威胁会转移到召唤者身上
- 如果单位无法拥有威胁列表,则仅设置战斗状态而不创建威胁引用
3. 威胁修饰符计算
在添加威胁值之前,系统会根据多种因素调整威胁值:
- 应用法术特定的威胁修饰符
- 应用学校特定的威胁修饰符(如神圣、火焰等)
- 应用临时修饰符(来自光环效果)
4. 威胁重定向
系统支持威胁重定向机制:
- 检查目标是否有威胁重定向效果
- 如果有,则将一部分威胁转移到指定的单位
- 这在嘲讽技能等机制中使用
5. 威胁引用创建/更新
- 如果目标已在威胁列表中,更新其威胁值
- 如果目标不在威胁列表中,创建新的ThreatReference对象
- 将威胁引用添加到所有相关数据结构中
6. 威胁列表维护
威胁系统维护多个数据结构来管理威胁列表:
- _myThreatListEntries:未排序的威胁引用映射(通过GUID索引)
- _sortedThreatList:使用斐波那契堆维护的排序威胁列表
- _threatenedByMe:该单位威胁其他单位的引用列表
7. 目标选择
系统定期更新当前目标:
- 每秒调用一次ThreatManager::UpdateVictim()方法
- 调用ThreatManager::ReselectVictim()方法选择新目标
- 目标选择遵循以下优先级:
- 固定目标(Fixate)优先
- 在线状态(在线 > 压制 > 离线)
- 嘲讽状态(嘲讽 > 正常 > 去嘲讽)
- 威胁值大小
8. 特殊状态处理
威胁系统处理多种特殊状态:
- 压制状态(Suppressed):当目标受到控制技能影响时,会被标记为压制状态
- 离线状态(Offline):当目标不在范围内或不可见时,会被标记为离线状态
- 嘲讽/去嘲讽状态:通过特定技能改变单位的威胁优先级
9. 客户端同步
威胁系统会将威胁列表变化同步到客户端:
- 当威胁列表发生变化时,设置_needClientUpdate标志
- 在更新周期中,通过SendThreatListToClients()方法将变化发送到客户端
10. AI通知
威胁系统会通知AI有关威胁列表的变化:
- 当单位的在线状态发生变化时,会注册AI更新
- 在更新周期结束时,调用ProcessAIUpdates()方法通知AI
注意事项
-
单位类型限制
- 只有生物(Creature)可以拥有威胁列表
- 宠物、图腾和触发器不能拥有威胁列表
- 玩家召唤的随从不能拥有威胁列表
-
迭代器失效
- 修改威胁引用时,迭代器可能会失效
- 建议使用GetModifiableThreatList()方法获取可修改的威胁列表副本
-
战斗状态一致性
- 威胁和战斗状态紧密相关
- 添加威胁会自动设置战斗状态
-
威胁修饰符
- 多种光环效果可以修改威胁值
- 法术可以有特定的威胁修饰符
-
网络同步
- 威胁列表变化会通过网络同步给客户端
- 客户端显示的威胁列表需定期更新