文章目录
- 一、简介
- 1)大怪物的AI主要涉及两个类:BossAI和WorldBossAI
- 2)普通小怪的AI,基本继承类:ScriptedAI
- 3)传奇怪物的AI,继承CreatureAI类
- 4)人物AI,PlayerAI类
- 5)PassiveAI(被动AI):
- 6)PossessedAI(被占据AI):
- 7)NullCreatureAI(空生物AI):
- 8)CritterAI(小动物AI):
- 9)TriggerAI(触发器AI)
- 10)AggressorAI(攻击者AI):
- 11)CombatAI(战斗AI):
- 12)CasterAI(施法者AI):
- 13)ArcherAI(弓箭手AI):
- 14)TurretAI(炮塔AI):
- 15)VehicleAI(载具AI):
- 16)TotemAI (图腾AI)
- 17)GuardAI(守卫AI)
- 18)NullGameObjectAI(空游戏对象AI):
- 19)GameObjectAI(游戏对象AI):
- 20)SmartGameObjectAI(智能游戏对象AI):
- 二、怪物类AI (ScriptedAI)
- 三、GuardAI(守卫AI)
本文是主讲怪物方向的AI
一、简介
1)大怪物的AI主要涉及两个类:BossAI和WorldBossAI
①继承顺序
BossAI
和WorldBossAI
都继承来自ScriptedAI类
ScriptedAI
类继承来自CreatureAI类,
Creature
类继承来自UnitAI类
②个例举例(继承BossAI)
<1>科林·狄尔布鲁(Coren Direbrew)
struct boss_coren_direbrew : public BossAI
<2>烟网女王(Mother Smolderweb)
struct boss_mother_smolderweb : public BossAI
<3>巨龙之王维姆萨拉克(Overlord Wyrmthalak)
struct boss_overlord_wyrmthalak : public BossAI
③WorldBossAI继承举例
1)Azuregos(艾索雷葛斯)
struct boss_azuregos : public WorldBossAI
2)翡翠龙(emerald_dragon)
struct emerald_dragonAI : public WorldBossAI
2)普通小怪的AI,基本继承类:ScriptedAI
①分别举例说明:
1)暮光志愿者AI
struct npc_twilight_volunteer : public ScriptedAI
2)Millhouse Manastorm(米尔豪斯·法力风暴)
struct npc_millhouse_manastorm : public ScriptedAI
3)传奇怪物的AI,继承CreatureAI类
①the lich king巫妖王的全部AI
②Valithria Dreamwalker (瓦莉瑟瑞娅·梦行者) 的全部AI
③Algalon the Observer(奥尔加隆,观察者之眼)
④Sister Svalna(斯瓦尔娜修女)
4)人物AI,PlayerAI类
5)PassiveAI(被动AI):
- 说明
PassiveAI类通常用于实现无攻击性的NPC或生物的行为。这些NPC通常不会主动攻击玩家或其他生物,而是表现出一种被动的行为,如漫游、站立、交谈等。PassiveAI类的目的是为了让这些NPC在游戏中营造出更真实、更丰富的环境。
6)PossessedAI(被占据AI):
- 说明
PossessedAI类用于实现被玩家控制的角色的行为。这些角色可以是玩家角色的宠物、召唤物或其他受玩家操控的单位。PossessedAI类的作用是让这些角色能够响应玩家的指令,并执行相应的行动和技能。
7)NullCreatureAI(空生物AI):
- 说明
NullCreatureAI类通常用于实现没有具体行为和功能的生物。这些生物可能只是作为环境装饰或背景元素存在,没有实际的交互或行为逻辑。NullCreatureAI类的作用是为这些生物提供一个空的AI实现,使其在游戏中存在但不参与实际的游戏机制。
8)CritterAI(小动物AI):
- 说明
CritterAI类用于实现小动物(Critter)的行为。小动物通常是一些无害的生物,如松鼠、兔子等。CritterAI类的目的是为这些小动物提供一些随机动作和行为,增加游戏世界的真实感和活力。
9)TriggerAI(触发器AI)
- 说明
监测游戏中的触发器或事件,并在满足特定条件时执行相应的行为。触发器可以是游戏中的特定区域、玩家的行动、特定时间点等。当触发器被激活时,TriggerAI会根据预设的条件和行为定义来决定角色或NPC的反应。
10)AggressorAI(攻击者AI):
- 说明
AggressorAI用于定义攻击性NPC的行为逻辑。这些NPC通常是敌对的角色,会主动寻找并攻击玩家或其他目标。AggressorAI负责定义NPC的攻击目标选择、攻击方式、技能使用等行为。它使NPC能够主动发起攻击并进行战斗。
11)CombatAI(战斗AI):
- 说明
CombatAI用于实现战斗相关的NPC行为逻辑。它与AggressorAI类似,但更广泛地适用于各种类型的战斗角色。CombatAI负责定义NPC在战斗中的行为,包括攻击、防御、移动、技能使用等。它使NPC能够在战斗中表现出合理的战术和行动。
12)CasterAI(施法者AI):
- 说明
CasterAI用于实现施法型NPC的行为逻辑。这些NPC通常使用法术或技能进行攻击。CasterAI负责定义NPC施法的选择和顺序,以及如何应对不同的战斗情况。它使NPC能够根据具体情况选择合适的法术或技能,并在战斗中以施法者的身份进行攻击。
13)ArcherAI(弓箭手AI):
- 说明
ArcherAI用于实现弓箭手类型的NPC的行为逻辑。这些NPC使用远程武器(如弓箭)进行攻击。ArcherAI负责定义NPC在战斗中的射击策略、目标选择和攻击方式。它使NPC能够以弓箭手的身份进行远程攻击,并采取合适的战术进行射击。
14)TurretAI(炮塔AI):
- 说明
TurretAI用于实现炮塔或防御设施的行为逻辑。这些炮塔通常是固定在特定位置上的防御装置,用于攻击敌人。TurretAI负责定义炮塔的目标选择、攻击方式和射击频率等行为。它使炮塔能够自动识别并攻击敌人,提供防御和控制区域的能力。
15)VehicleAI(载具AI):
- 说明
VehicleAI用于实现游戏中的载具(如飞机、坦克、船只等)的行为逻辑。VehicleAI负责定义载具的移动、攻击、防御等行为。它使载具能够根据玩家的操控或AI指令进行移动和战斗,并提供特定类型载具的独特功能和能力。
16)TotemAI (图腾AI)
- 说明
在游戏中,图腾通常代表着特殊的力量或能力,可能具有各种不同的效果,如增益效果、伤害效果、治疗效果等
17)GuardAI(守卫AI)
- 说明
管理和控制守卫角色在游戏中的行为和动作,确保它们有效地执行守卫任务。守卫角色通常被安排在特定位置或区域,负责保护该区域免受敌对角色或其他威胁的侵犯。
18)NullGameObjectAI(空游戏对象AI):
- 说明
NullGameObjectAI是一个在游戏中代表空或无效游戏对象的AI类。它通常用于处理游戏中可能出现的空对象或无效对象的情况。NullGameObjectAI的作用是提供一种处理这些情况的机制,以避免潜在的错误或异常情况。
19)GameObjectAI(游戏对象AI):
- 说明
GameObjectAI是一个通用的游戏对象AI类,用于管理和控制游戏中的普通游戏对象的行为和交互。它可以处理游戏对象的移动、碰撞、状态变化等方面的逻辑,并根据游戏规则和设计来控制游戏对象的行为。
20)SmartGameObjectAI(智能游戏对象AI):
- 说明
SmartGameObjectAI是一个更高级的游戏对象AI类,具有更复杂和智能化的行为和决策能力。它可以根据游戏环境和条件进行推理和决策,并采取相应的行动。智能游戏对象AI通常用于实现游戏中的敌对角色、队友角色或其他具有复杂行为的角色。
二、怪物类AI (ScriptedAI)
1)jedoga_shadowseeker暗影追寻者副本怪物AI
npc_twilight_volunteer和boss_jedoga_shadowseeker是作为两种怪物的AI注册在这个副本脚本里面
- 副本事件枚举
enum JedogaEvents
{
EVENT_INTRO_SAY = 1, --表示介绍对话事件。
EVENT_START_FIGHT_1, --表示战斗开始事件 1
EVENT_START_FIGHT_2, --表示战斗开始事件 2
EVENT_CYCLONE_STRIKE, --表示飓风打击事件
EVENT_LIGHTNING_BOLT, --表示闪电箭事件
EVENT_THUNDERSHOCK, --表示雷霆震击事件
EVENT_START_PHASE_TWO, --表示第二阶段开始事件
EVENT_FLY_DELAY, --表示飞行延迟事件
EVENT_END_PHASE_TWO, --表示第二阶段结束事件
EVENT_CHOOSE_VOLUNTEER, --表示选择志愿者事件
EVENT_SUMMON_VOLUNTEER --表示召唤志愿者事件
};
- boss阶段
enum JedogaPhases
{
PHASE_INTRO = 0,
PHASE_ONE,
PHASE_TWO,
PHASE_THREE
};
enum EncounterState
{
NOT_STARTED = 0,
IN_PROGRESS = 1,
FAIL = 2,
DONE = 3, --副本机制结束
SPECIAL = 4,
TO_BE_DECIDED = 5
};
NOT_STARTED (值为0): 表示战斗或遭遇尚未开始的状态。
IN_PROGRESS (值为1): 表示战斗或遭遇正在进行中的状态。
FAIL (值为2): 表示战斗或遭遇失败的状态。
DONE (值为3): 表示战斗或遭遇成功完成的状态。
SPECIAL (值为4): 表示战斗或遭遇的特殊状态。
TO_BE_DECIDED (值为5): 表示战斗或遭遇的状态尚待决定
(1)boss_jedoga_shadowseeker类
- 总结共写了几种函数
1)构造函数
boss_jedoga_shadowseeker(Creature* creature) : BossAI(creature, DATA_JEDOGA_SHADOWSEEKER), _volunteerWork(true) { }
2)重写reset函数
void Reset() override
3)重写JustEngagedWith函数
void JustEngagedWith(Unit* who) override
4)重写EnterEvadeMode函数
void EnterEvadeMode(EvadeReason /*why*/) override
5)有obj死亡
void KilledUnit(Unit* Victim) override
6)boss死亡事件
void JustDied(Unit* /*killer*/) override
7)获取是否志愿者是否死亡数据
uint32 GetData(uint32 type) const override
8)伤害发生事件
void DamageTaken(Unit* /*done_by*/, uint32& /*damage*/, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
9)行动函数-处理对应行动
void DoAction(int32 action) override
10)召唤事件
void JustSummoned(Creature* summon) override
11)召唤物死亡事件
void SummonedCreatureDies(Creature* summon, Unit* killer) override
12)移动事件
void MovementInform(uint32 type, uint32 pointId) override
13)处理事件(每帧处理)
void UpdateAI(uint32 diff) override
- 成员变量
private:
bool _volunteerWork;
GuidVector _volunteerGUIDS;
ObjectGuid _selectedVolunteerGUID;
GuidUnorderedSet _initiateGUIDS;
①团灭重置或是boss转阶段函数-reset
//boss_jedoga_shadowseeker类的函数
void Reset() override
{
_Reset();
events.SetPhase(PHASE_INTRO);
me->SetReactState(REACT_PASSIVE);
std::list<TempSummon*> summoned;
me->SummonCreatureGroup(SUMMON_GROUP_INITIATES, &summoned);
for (TempSummon* value : summoned)
_initiateGUIDS.insert(value->GetGUID());
if (TempSummon* controller = me->SummonCreature(NPC_JEDOGA_CONTROLLER, JedogaControllerPositions[0], TEMPSUMMON_MANUAL_DESPAWN))
controller->CastSpell(me, SPELL_BEAM_VISUAL_JEDOGA);
if (TempSummon* controller = me->SummonCreature(NPC_JEDOGA_CONTROLLER, JedogaControllerPositions[1], TEMPSUMMON_MANUAL_DESPAWN))
controller->CastSpell(me, SPELL_BEAM_VISUAL_JEDOGA);
events.ScheduleEvent(EVENT_INTRO_SAY, Minutes(2), 0, PHASE_INTRO);
}
void BossAI::_Reset()
{
if (!me->IsAlive())
return;
me->SetCombatPulseDelay(0);
me->ResetLootMode();
events.Reset();
summons.DespawnAll();
scheduler.CancelAll();
if (instance && instance->GetBossState(_bossId) != DONE)
instance->SetBossState(_bossId, NOT_STARTED);
}
<1>std::list<TempSummon*> summoned;这里会将根据配置里面的怪物数量读取对应召唤物放到容器里面
<2>召唤两个怪物id为NPC_JEDOGA_CONTROLLER的怪物在位置0和位置1,然后这两个怪物释放光束技能(SPELL_BEAM_VISUAL_JEDOGA,这个两个怪物在调用unsummon后会被销毁)
if (TempSummon* controller = me->SummonCreature(NPC_JEDOGA_CONTROLLER, JedogaControllerPositions[0], TEMPSUMMON_MANUAL_DESPAWN))
controller->CastSpell(me, SPELL_BEAM_VISUAL_JEDOGA);
if (TempSummon* controller = me->SummonCreature(NPC_JEDOGA_CONTROLLER, JedogaControllerPositions[1], TEMPSUMMON_MANUAL_DESPAWN))
controller->CastSpell(me, SPELL_BEAM_VISUAL_JEDOGA);
<3> 启动定时器,每隔两分钟启动说话事件
-------事件注册
events.ScheduleEvent(EVENT_INTRO_SAY, Minutes(2), 0, PHASE_INTRO);
------事件触发(如果boss状态是结束状态,那么副本结束,给场景玩家发送布教)
case EVENT_INTRO_SAY:
if (instance->GetBossState(DATA_PRINCE_TALDARAM) == DONE)
Talk(SAY_PREACHING);
events.Repeat(Minutes(2));
break;
②这可能是玩家进入某块boss视野的区域,处理 BOSS 与玩家或其他单位刚刚发生接触时的行为调用的函数
void JustEngagedWith(Unit* who) override
{
me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL);
me->RemoveAurasDueToSpell(SPELL_RANDOM_LIGHTNING_VISUAL);
me->SummonCreatureGroup(SUMMON_GROUP_WORSHIPPERS);
BossAI::JustEngagedWith(who);
Talk(SAY_AGGRO);
events.SetPhase(PHASE_ONE);
for (JedogaVolunteerPositionPair const& posPair : JedogaVolunteerSpotPositions)
{
if (TempSummon* volunteer = me->SummonCreature(NPC_TWILIGHT_VOLUNTEER, posPair.first, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3s))
{
volunteer->GetMotionMaster()->MovePoint(POINT_INITIAL_POSITION, posPair.second);
_volunteerGUIDS.push_back(volunteer->GetGUID());
}
}
}
<1>移除与 SPELL_SPHERE_VISUAL 相关的光环效果。
<2>移除与 SPELL_RANDOM_LIGHTNING_VISUAL 相关的光环效果。
<3>召唤一组崇拜者(worshippers)的生物
<4>触发一个攻击的语音对话(aggro)。
<5>设置 BOSS 的战斗阶段(phase)为第一阶段(PHASE_ONE)
<6>按照配置读取怪物id为NPC_TWILIGHT_VOLUNTEER的坐标,将怪物移动到目标地点
③逃跑触发的函数(销毁所有召唤物,然后设置boss状态为挑战失败)
_EnterEvadeMode里面会冷却boss所有技能,停止战斗状态,设置攻击目标为空,去除身上的buff
void EnterEvadeMode(EvadeReason /*why*/) override
{
summons.DespawnAll();
_EnterEvadeMode();
_DespawnAtEvade(Seconds(15));
}
④有obj被杀掉调用这个,如果被杀的是玩家,那么boss就说点嚣张的话
void KilledUnit(Unit* Victim) override
{
if (Victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
⑤boss被杀调用的事件
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_DEATH);
}
⑥获得特定数据(志愿者还在工作就返回1)
uint32 GetData(uint32 type) const override
{
if (type == DATA_VOLUNTEER_WORK)
return _volunteerWork ? 1 : 0;
return 0;
}
⑦伤害发生调用的函数
- 说明
伤害发生的时候,如果boss伤害少于55%,而且boss处于第一阶段,
那么
<1>boss进入下阶段,
<2>重置boss状态,
<3>1s后开启事件2
void DamageTaken(Unit* /*done_by*/, uint32& /*damage*/, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
{
if (HealthBelowPct(55) && events.IsInPhase(PHASE_ONE))
{
events.Reset();
events.SetPhase(PHASE_TWO);
events.ScheduleEvent(EVENT_START_PHASE_TWO, 1s);
}
}
---------------------------
阶段二事件:EVENT_START_PHASE_TWO
移动到特定地点,设置无敌状态,不能攻击玩家,移动到特定地点
case EVENT_START_PHASE_TWO:
me->SetReactState(REACT_PASSIVE);
me->AttackStop();
me->InterruptNonMeleeSpells(true);
me->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
me->GetMotionMaster()->MovePoint(POINT_PHASE_TWO, JedogaGroundPosition);
break;
⑧召唤事件
若召唤物是WORSHIPPER则让其处于跪倒状态
void JustSummoned(Creature* summon) override
{
if (summon->GetEntry() == NPC_TWILIGHT_WORSHIPPER)
{
summon->SetStandState(UNIT_STAND_STATE_KNEEL);
summons.Summon(summon);
return;
}
BossAI::JustSummoned(summon);
}
⑨召唤物死亡
<1>如果死亡的召唤物是初始的召唤物,boss释放SPELL_HOVER_FALL_1技能,1s后执行EVENT_START_FIGHT_1事件
<2>如果死亡的召唤物是志愿者召唤物,改变志愿者的工作状态,如果是阶段二则转变到阶段三,启动阶段二结束事件EVENT_END_PHASE_TWO
void SummonedCreatureDies(Creature* summon, Unit* killer) override
{
if (summon->GetEntry() == NPC_TWILIGHT_INITIATE)
{
_initiateGUIDS.erase(summon->GetGUID());
if (_initiateGUIDS.empty())
{
DoCastSelf(SPELL_HOVER_FALL_1);
me->SetAnimTier(AnimTier::Ground);
events.ScheduleEvent(EVENT_START_FIGHT_1, Seconds(1));
}
}
else if (summon->GetEntry() == NPC_TWILIGHT_VOLUNTEER)
{
_volunteerWork = false;
if (events.IsInPhase(PHASE_TWO))
{
events.SetPhase(PHASE_THREE);
events.RescheduleEvent(EVENT_END_PHASE_TWO, Seconds(1));
}
events.RescheduleEvent(EVENT_SUMMON_VOLUNTEER, Seconds(10));
}
BossAI::SummonedCreatureDies(summon, killer);
}
⑩移动事件
<1>若不是按照点移动或是按照特效移动(就是飞行特效)那就返回
<2>去除UNIT_FLAG_UNINTERACTIBLE标志
具体来说,当一个单位具有UNIT_FLAG_UNINTERACTIBLE
标志时,其他单位或玩家无法与该单位进行交互。这意味着玩家无法与该单位进行对话、攻击、施放法术等互动行为
<3>boss设置REACT_AGGRESSIVE
,当一个单位的行为反应状态设置为REACT_AGGRESSIVE时,该单位将主动攻击其他单位,即使这些单位没有主动攻击它。这意味着该单位会对附近的敌对单位发起攻击,并对它们进行战斗。
<4>循环释放技能
void MovementInform(uint32 type, uint32 pointId) override
{
if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE)
return;
switch (pointId)
{
case POINT_GROUND:
me->RemoveUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
me->SetReactState(REACT_AGGRESSIVE);
DoZoneInCombat();
events.ScheduleEvent(EVENT_CYCLONE_STRIKE, 3s);
events.ScheduleEvent(EVENT_LIGHTNING_BOLT, 7s);
events.ScheduleEvent(EVENT_THUNDERSHOCK, 12s);
break;
case POINT_PHASE_TWO:
events.ScheduleEvent(EVENT_FLY_DELAY, 2s);
break;
case POINT_PHASE_TWO_FLY:
events.ScheduleEvent(EVENT_CHOOSE_VOLUNTEER, 2s);
break;
default:
break;
}
}
十一、主逻辑处理(每帧处理对应事件)
<1>每帧调用UpdateAI,这里会把事件都执行一遍
<2>事件执行结束会调用DoMeleeAttackIfReady进行正反手近战普通攻击
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() && !events.IsInPhase(PHASE_INTRO))
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_INTRO_SAY:
if (instance->GetBossState(DATA_PRINCE_TALDARAM) == DONE)
Talk(SAY_PREACHING);
events.Repeat(Minutes(2));
break;
case EVENT_START_FIGHT_1:
me->RemoveAurasDueToSpell(SPELL_BEAM_VISUAL_JEDOGA);
events.ScheduleEvent(EVENT_START_FIGHT_2, Seconds(1));
break;
case EVENT_START_FIGHT_2:
summons.DespawnEntry(NPC_JEDOGA_CONTROLLER);
me->SetDisableGravity(false);
me->GetMotionMaster()->MoveLand(POINT_GROUND, JedogaGroundPosition);
break;
case EVENT_START_PHASE_TWO:
me->SetReactState(REACT_PASSIVE);
me->AttackStop();
me->InterruptNonMeleeSpells(true);
me->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
me->GetMotionMaster()->MovePoint(POINT_PHASE_TWO, JedogaGroundPosition);
break;
case EVENT_FLY_DELAY:
me->SetDisableGravity(true);
me->GetMotionMaster()->MoveTakeoff(POINT_PHASE_TWO_FLY, JedogaFlyPosition);
break;
case EVENT_CHOOSE_VOLUNTEER:
if (TempSummon* controller = me->SummonCreature(NPC_JEDOGA_CONTROLLER, JedogaControllerPositions[2], TEMPSUMMON_MANUAL_DESPAWN))
{
me->SetFacingToObject(controller);
controller->CastSpell(controller, SPELL_SACRIFICE_VISUAL);
}
Talk(SAY_CHOOSE);
if (_volunteerGUIDS.empty())
break;
_selectedVolunteerGUID = Trinity::Containers::SelectRandomContainerElement(_volunteerGUIDS);
if (Creature* volunteer = ObjectAccessor::GetCreature(*me, _selectedVolunteerGUID))
volunteer->AI()->DoAction(ACTION_CHOSEN);
break;
case EVENT_SUMMON_VOLUNTEER:
{
uint32 pos = std::distance(_volunteerGUIDS.begin(), std::find(_volunteerGUIDS.begin(), _volunteerGUIDS.end(), _selectedVolunteerGUID));
if (pos < JedogaVolunteerSpotPositions.size())
{
JedogaVolunteerPositionPair const& posPair = JedogaVolunteerSpotPositions.at(pos);
if (TempSummon* volunteer = me->SummonCreature(NPC_TWILIGHT_VOLUNTEER, posPair.first, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3s))
volunteer->GetMotionMaster()->MovePoint(POINT_INITIAL_POSITION, posPair.second);
}
break;
}
case EVENT_END_PHASE_TWO:
summons.DespawnEntry(NPC_JEDOGA_CONTROLLER);
DoCastSelf(SPELL_HOVER_FALL_2);
me->SetDisableGravity(false);
me->GetMotionMaster()->MoveLand(POINT_GROUND, JedogaGroundPosition);
break;
case EVENT_CYCLONE_STRIKE:
DoCastSelf(SPELL_CYCLONE_STRIKE);
events.Repeat(Seconds(15), Seconds(30));
break;
case EVENT_LIGHTNING_BOLT:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
DoCast(target, SPELL_LIGHTNING_BOLT);
events.Repeat(Seconds(15), Seconds(30));
break;
case EVENT_THUNDERSHOCK:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
DoCast(target, SPELL_THUNDERSHOCK);
events.Repeat(Seconds(15), Seconds(30));
break;
default:
break;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
(2)npc_twilight_volunteer类
三、GuardAI(守卫AI)
1)平常守卫
(1)主要函数和类
- 主要类
struct npc_guard_generic : public GuardAI
- 主要函数
1、构造函数
npc_guard_generic(Creature* creature) : GuardAI(creature)
2、
void Reset() override
3、
void DoReplyToTextEmote(uint32 emote)
4、
void ReceiveEmote(Player* player, uint32 textEmote) override
5、
void JustEngagedWith(Unit* who) override
6、
void UpdateAI(uint32 diff) override
- 主要成员变量
private:
TaskScheduler _scheduler;
TaskScheduler _combatScheduler;
2)沙塔斯城守卫(Shattrath Faction)
(1)主要函数和类
- 主要类
struct npc_guard_shattrath_faction: public GuardAI
- 主要函数
1、构造函数
npc_guard_shattrath_faction(Creature* creature) : GuardAI(creature)
2、重置函数
void Reset() override
3、与单位交互(比如攻击、施法、交互等。)
void JustEngagedWith(Unit* /*who*/) override
4、每帧更新游戏逻辑
void UpdateAI(uint32 diff) override
5、
void ScheduleVanish()
- 成员变量
private:
TaskScheduler _scheduler;