Skip to content

Commit 8be3de2

Browse files
NtscNtsc
Ntsc
authored and
Ntsc
committed
* New EventAI Events (EVENT_T_TARGET_HP, EVENT_T_TARGET_CASTING). New Cast flags (CAST_NO_MELEE_IF_OOM, CAST_FORCE_TARGET_SELF). Please read EventAI.txt
* Prevent crash in C'thun if no instance script. Boss will just not react to anything if instance script not set. * Possibly fix Karathress. * Add triggered bool to CanCast function. git-svn-id: https://scriptdev2.svn.sourceforge.net/svnroot/scriptdev2@383 5f9c896b-1e26-0410-94da-f77f675e2462
1 parent 22bd808 commit 8be3de2

File tree

7 files changed

+108
-43
lines changed

7 files changed

+108
-43
lines changed

docs/EventAI.txt

+6-2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ Params are always read from Param1, then Param2, then Param3.
6363
11 EVENT_T_RANGE MinDist, MaxDist, TimeUnitlRepeat Expires when the highest threat target distance is greater than (Param1) and less than (Param2). Repeats every (Param3) or never if Param3 = 0.
6464
12 EVENT_T_OOC_LOS NoHostile, NoFriendly, TimeUntilRepeat Expires when a Player moves within visible distance to creature. Does not expire for Hostile Players if (Param1) is not 0. Does not expire for Friendly Players if (Param2) is not 0. Will repeat every (Param3) or never if Param3 = 0. Does not expire for creatures or pet or when the creature is in combat.
6565
13 EVENT_T_SPAWNED NONE Expires at initial spawn and at creature respawn (useful for setting ranged movement type)
66+
14 EVENT_T_TARGET_HP HPMax%, HPMin%, TimeUntilRepeat Expires when Current Target's HP is between (Param1) and (Param2). Will repeat every (Param3) or never repeat if Param3 = 0.
67+
15 EVENT_T_TARGET_CASTING TimeUntilRepeat Expires when the player is casting a spell. Will repeat every (Param1) or never repeat if Param1 = 0.
6668

6769
-----------------------------------------
6870
Action Types
@@ -128,9 +130,11 @@ Cast Flags
128130
-----------------------------------------
129131
Below is the list of current Cast Flags that EventAI's spell casting can handle.
130132
Cast flags are handled bitwise. Bit 0 is Interrupt Previous, bit 1 is triggered, etc.
131-
So for example the number "3"(11 in binary) would mean that this cast should both interrupt previous and triggered spell.
133+
So for example the number "3"(11 in binary) would mean that this cast has both CAST_INTURRUPT_PREVIOUS and CAST_TRIGGERED.
132134

133135
(bit# Internal Name Discription)
134136
0 CAST_INTURRUPT_PREVIOUS Interrupts any previous spell casting (basicaly makes sure that this spell goes off)
135137
1 CAST_TRIGGERED Forces the spell to be instant cast and require no mana/reagents.
136-
2 CAST_FORCE_CAST Forces spell to cast even if the player is possibly out of range or the creature is possibly out of mana
138+
2 CAST_FORCE_CAST Forces spell to cast even if the target is possibly out of range or the creature is possibly out of mana
139+
3 CAST_NO_MELEE_IF_OOM Prevents creature from entering melee if out of mana or out of range
140+
4 CAST_FORCE_TARGET_SELF Forces the target to cast this spell on itself

include/sc_creature.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -325,18 +325,18 @@ SpellEntry const* ScriptedAI::SelectSpell(Unit* Target, int32 School, int32 Mech
325325
return Spell[rand()%SpellCount];
326326
}
327327

328-
bool ScriptedAI::CanCast(Unit* Target, SpellEntry const *Spell)
328+
bool ScriptedAI::CanCast(Unit* Target, SpellEntry const *Spell, bool Triggered)
329329
{
330330
//No target so we can't cast
331331
if (!Target || !Spell)
332332
return false;
333333

334334
//Silenced so we can't cast
335-
if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
335+
if (!Triggered && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
336336
return false;
337337

338338
//Check for power
339-
if (m_creature->GetPower((Powers)Spell->powerType) < Spell->manaCost)
339+
if (!Triggered && m_creature->GetPower((Powers)Spell->powerType) < Spell->manaCost)
340340
return false;
341341

342342
SpellRangeEntry const *TempRange = NULL;

include/sc_creature.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ struct MANGOS_DLL_DECL ScriptedAI : public CreatureAI
157157
SpellEntry const* SelectSpell(Unit* Target, int32 School, int32 Mechanic, SelectTarget Targets, uint32 PowerCostMin, uint32 PowerCostMax, float RangeMin, float RangeMax, SelectEffect Effect);
158158

159159
//Checks if you can cast the specified spell
160-
bool CanCast(Unit* Target, SpellEntry const *Spell);
160+
bool CanCast(Unit* Target, SpellEntry const *Spell, bool Triggered = false);
161161
};
162162

163163

scripts/creature/mob_event_ai.cpp

+68-6
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,10 @@ struct MANGOS_DLL_DECL Mob_EventAI : public ScriptedAI
8787
if ( m_creature->Attack(pTarget) )
8888
{
8989
if (Follow)
90+
{
91+
m_creature->GetMotionMaster()->Clear(false);
9092
m_creature->GetMotionMaster()->Mutate(new TargetedMovementGenerator<Creature>(*pTarget, AttackDistance, AttackAngle));
93+
}
9194

9295
m_creature->AddThreat(pTarget, 0.0f);
9396
m_creature->resetAttackTimer();
@@ -251,6 +254,33 @@ struct MANGOS_DLL_DECL Mob_EventAI : public ScriptedAI
251254
{
252255
}
253256
break;
257+
case EVENT_T_TARGET_HP:
258+
{
259+
if (!InCombat || !m_creature->getVictim() || !m_creature->getVictim()->GetMaxHealth())
260+
return;
261+
262+
uint32 perc = (m_creature->getVictim()->GetHealth()*100) / m_creature->getVictim()->GetMaxHealth();
263+
264+
if (perc > param1 || perc < param2)
265+
return;
266+
267+
//Prevent repeat for param3 time, or disable if param3 not set
268+
if (param3)
269+
pHolder.Time = param3;
270+
else pHolder.Enabled = false;
271+
}
272+
break;
273+
case EVENT_T_TARGET_CASTING:
274+
{
275+
if (!InCombat || !m_creature->getVictim() || !m_creature->getVictim()->IsNonMeleeSpellCasted(false, false, true))
276+
return;
277+
278+
//Prevent repeat for param1 time, or disable if param3 not set
279+
if (param1)
280+
pHolder.Time = param1;
281+
else pHolder.Enabled = false;
282+
}
283+
break;
254284
default:
255285
error_log("Event type missing from ProcessEvent() Switch . Type = %d", pHolder.Event.event_type);
256286
break;
@@ -383,20 +413,45 @@ struct MANGOS_DLL_DECL Mob_EventAI : public ScriptedAI
383413
case ACTION_T_CAST:
384414
{
385415
Unit* target = GetTargetByType(param2, pActionInvoker);
416+
Unit* caster = m_creature;
386417

387418
if (!target)
388419
return;
389420

390-
if (param3 & CAST_INTURRUPT_PREVIOUS || !m_creature->IsNonMeleeSpellCasted(false))
421+
//Cast is always triggered if target is forced to cast on self
422+
if (param3 & CAST_FORCE_TARGET_SELF)
391423
{
392-
m_creature->InterruptNonMeleeSpells(false);
424+
param3 |= CAST_TRIGGERED;
425+
caster = target;
426+
}
427+
428+
//Interrupt any previous spell
429+
if (caster->IsNonMeleeSpellCasted(false) && param3 & CAST_INTURRUPT_PREVIOUS)
430+
caster->InterruptNonMeleeSpells(false);
393431

394-
const SpellEntry* tSpell = GetSpellStore()->LookupEntry(param1);
432+
//Cast only if not casting or if spell is triggered
433+
if (param3 & CAST_TRIGGERED || !caster->IsNonMeleeSpellCasted(false))
434+
{
435+
const SpellEntry* tSpell = GetSpellStore()->LookupEntry(param1);
395436

437+
//Verify that spell exists
396438
if (tSpell)
397439
{
398-
if ((param3 & CAST_FORCE_CAST) || CanCast(target, tSpell))
399-
m_creature->CastSpell(target, param1, (param3 & CAST_TRIGGERED));
440+
//Check if cannot cast spell
441+
if (!(param3 & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST)) &&
442+
!CanCast(target, tSpell, (param3 & CAST_TRIGGERED)))
443+
{
444+
//Melee current victim if flag not set
445+
if (!(param3 & CAST_NO_MELEE_IF_OOM))
446+
{
447+
AttackDistance = 0;
448+
AttackAngle = 0;
449+
450+
m_creature->GetMotionMaster()->Clear(false);
451+
m_creature->GetMotionMaster()->Mutate(new TargetedMovementGenerator<Creature>(*m_creature->getVictim(), AttackDistance, AttackAngle));
452+
}
453+
454+
}else caster->CastSpell(target, param1, (param3 & CAST_TRIGGERED));
400455

401456
}else error_log("SD2: EventAI creature %d attempt to cast spell that doesn't exist %d", m_creature->GetCreatureInfo()->Entry, param1);
402457
}
@@ -498,11 +553,16 @@ struct MANGOS_DLL_DECL Mob_EventAI : public ScriptedAI
498553

499554
case ACTION_T_COMBAT_MOVEMENT:
500555
{
556+
CombatMovementEnabled = param1;
557+
501558
//Allow movement (create new targeted movement gen if none exist already)
502-
if (param1)
559+
if (CombatMovementEnabled)
503560
{
504561
if (m_creature->GetMotionMaster()->top()->GetMovementGeneratorType() != TARGETED_MOTION_TYPE)
562+
{
563+
m_creature->GetMotionMaster()->Clear(false);
505564
m_creature->GetMotionMaster()->Mutate(new TargetedMovementGenerator<Creature>(*m_creature->getVictim(), AttackDistance, AttackAngle));
565+
}
506566
}
507567
else
508568
if (m_creature->GetMotionMaster()->top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE)
@@ -921,6 +981,8 @@ struct MANGOS_DLL_DECL Mob_EventAI : public ScriptedAI
921981
case EVENT_T_TIMER_OOC_SINGLE:
922982
case EVENT_T_MANA:
923983
case EVENT_T_HP:
984+
case EVENT_T_TARGET_HP:
985+
case EVENT_T_TARGET_CASTING:
924986
ProcessEvent(*i);
925987
break;
926988
}

scripts/creature/mob_event_ai.h

+7-3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ enum Event_Types
3333
EVENT_T_RANGE = 11, //MinDist, MaxDist, TimeUnitlRepeat
3434
EVENT_T_OOC_LOS = 12, //NoHostile, NoFriendly, TimeUntilRepeat
3535
EVENT_T_SPAWNED = 13, //NONE
36+
EVENT_T_TARGET_HP = 14, //HPMax%, HPMin%, TimeUntilRepeat
37+
EVENT_T_TARGET_CASTING = 15, //TimeUntilRepeat
3638

3739
EVENT_T_END,
3840
};
@@ -93,9 +95,11 @@ enum Target
9395

9496
enum CastFlags
9597
{
96-
CAST_INTURRUPT_PREVIOUS = 0x01,
97-
CAST_TRIGGERED = 0x02,
98-
CAST_FORCE_CAST = 0x04,
98+
CAST_INTURRUPT_PREVIOUS = 0x01, //Interrupt any spell casting
99+
CAST_TRIGGERED = 0x02, //Triggered (this makes spell cost zero mana and have no cast time)
100+
CAST_FORCE_CAST = 0x04, //Forces cast even if creature is out of mana or out of range
101+
CAST_NO_MELEE_IF_OOM = 0x08, //Prevents creature from entering melee if out of mana or out of range
102+
CAST_FORCE_TARGET_SELF = 0x10, //Forces the target to cast this spell on itself
99103
};
100104

101105
struct EventAI_Event

scripts/zone/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp

+3-26
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ struct MANGOS_DLL_DECL boss_fathomlord_karathressAI : public ScriptedAI
133133

134134
void GetAdvisors()
135135
{
136+
if(!pInstance)
137+
return;
138+
136139
Advisors[0] = pInstance->GetData64(DATA_SHARKKIS);
137140
Advisors[1] = pInstance->GetData64(DATA_TIDALVESS);
138141
Advisors[3] = pInstance->GetData64(DATA_CARIBDIS);
@@ -306,32 +309,6 @@ struct MANGOS_DLL_DECL boss_fathomguard_sharkkisAI : public ScriptedAI
306309
}
307310
}
308311

309-
void MoveInLineOfSight(Unit *who)
310-
{
311-
if (!who || m_creature->getVictim())
312-
return;
313-
314-
if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who))
315-
{
316-
float attackRadius = m_creature->GetAttackDistance(who);
317-
if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who))
318-
{
319-
if(who->HasStealthAura())
320-
who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
321-
322-
DoStartAttackAndMovement(who);
323-
if(!InCombat)
324-
{
325-
if(pInstance)
326-
{
327-
pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID());
328-
pInstance->SetData(DATA_KARATHRESSEVENT, 1);
329-
}
330-
}
331-
}
332-
}
333-
}
334-
335312
void UpdateAI(const uint32 diff)
336313
{
337314
//Only if not incombat check if the event is started

scripts/zone/temple_of_ahnqiraj/boss_cthun.cpp

+20-2
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,8 @@ struct MANGOS_DLL_DECL eye_of_cthunAI : public Scripted_NoMovementAI
188188
m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NOT_ATTACKABLE | UNIT_FLAG_ANIMATION_FROZEN);
189189

190190
//Reset Phase
191-
pInst->SetData(DATA_CTHUN_PHASE, 0);
191+
if (pInst)
192+
pInst->SetData(DATA_CTHUN_PHASE, 0);
192193
}
193194

194195
void Aggro(Unit *who)
@@ -216,6 +217,10 @@ struct MANGOS_DLL_DECL eye_of_cthunAI : public Scripted_NoMovementAI
216217
if (!m_creature->SelectHostilTarget() || !m_creature->getVictim())
217218
return;
218219

220+
//No instance
221+
if (!pInst)
222+
return;
223+
219224
switch (pInst->GetData(DATA_CTHUN_PHASE))
220225
{
221226

@@ -384,6 +389,10 @@ struct MANGOS_DLL_DECL eye_of_cthunAI : public Scripted_NoMovementAI
384389

385390
void DamageTaken(Unit *done_by, uint32 &damage)
386391
{
392+
//No instance
393+
if (!pInst)
394+
return;
395+
387396
switch (pInst->GetData(DATA_CTHUN_PHASE))
388397
{
389398
case 0:
@@ -499,7 +508,8 @@ struct MANGOS_DLL_DECL cthunAI : public Scripted_NoMovementAI
499508
m_creature->RemoveAurasDueToSpell(SPELL_TRANSFORM);
500509
m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NOT_ATTACKABLE);
501510

502-
pInst->SetData(DATA_CTHUN_PHASE, 0);
511+
if (pInst)
512+
pInst->SetData(DATA_CTHUN_PHASE, 0);
503513
}
504514

505515
void Aggro(Unit *who)
@@ -611,6 +621,10 @@ struct MANGOS_DLL_DECL cthunAI : public Scripted_NoMovementAI
611621

612622
m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0);
613623

624+
//No instance
625+
if (!pInst)
626+
return;
627+
614628
switch (pInst->GetData(DATA_CTHUN_PHASE))
615629
{
616630
//Transition phase
@@ -893,6 +907,10 @@ struct MANGOS_DLL_DECL cthunAI : public Scripted_NoMovementAI
893907

894908
void DamageTaken(Unit *done_by, uint32 &damage)
895909
{
910+
//No instance
911+
if (!pInst)
912+
return;
913+
896914
switch (pInst->GetData(DATA_CTHUN_PHASE))
897915
{
898916
case 3:

0 commit comments

Comments
 (0)