mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-25 06:36:24 +00:00
Merge branch 'azerothcore:master' into Playerbot
This commit is contained in:
@@ -106,6 +106,11 @@ void EventMap::Repeat(Milliseconds time)
|
||||
RepeatEvent(time.count());
|
||||
}
|
||||
|
||||
void EventMap::Repeat(Milliseconds minTime, Milliseconds maxTime)
|
||||
{
|
||||
RepeatEvent(randtime(minTime, maxTime).count());
|
||||
}
|
||||
|
||||
uint32 EventMap::ExecuteEvent()
|
||||
{
|
||||
while (!Empty())
|
||||
|
||||
@@ -182,12 +182,9 @@ public:
|
||||
void RescheduleEvent(uint32 eventId, Milliseconds minTime, Milliseconds maxTime, uint32 group = 0, uint32 phase = 0);
|
||||
|
||||
/**
|
||||
* @name RescheduleEvent
|
||||
* @brief Cancels the given event and reschedules it.
|
||||
* @param eventId The id of the event.
|
||||
* @param time The time in milliseconds until the event occurs.
|
||||
* @param group The group which the event is associated to. Has to be between 1 and 8. 0 means it has no group.
|
||||
* @param phase The phase in which the event can occur. Has to be between 1 and 8. 0 means it can occur in all phases.
|
||||
* @name RepeatEvent
|
||||
* @brief Repeats the most recently executed event.
|
||||
* @param time Time until the event occurs as std::chrono type.
|
||||
*/
|
||||
void RepeatEvent(uint32 time);
|
||||
|
||||
@@ -198,6 +195,15 @@ public:
|
||||
*/
|
||||
void Repeat(Milliseconds time);
|
||||
|
||||
/**
|
||||
|
||||
* @name RepeatEvent
|
||||
* @brief Repeats the most recently executed event.
|
||||
* @param minTime The minimum time until the event occurs as std::chrono type.
|
||||
* @param maxTime The maximum time until the event occurs as std::chrono type.
|
||||
*/
|
||||
void Repeat(Milliseconds minTime, Milliseconds maxTime);
|
||||
|
||||
/**
|
||||
* @name ExecuteEvent
|
||||
* @brief Returns the next event to execute and removes it from map.
|
||||
|
||||
@@ -2424,6 +2424,12 @@ bool Creature::CanAssistTo(Unit const* u, Unit const* enemy, bool checkfaction /
|
||||
if (GetCharmerOrOwnerGUID())
|
||||
return false;
|
||||
|
||||
// Check for ignore assistance extra flag
|
||||
if (m_creatureInfo->HasFlagsExtra(CREATURE_FLAG_EXTRA_IGNORE_ASSISTANCE_CALL))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// only from same creature faction
|
||||
if (checkfaction)
|
||||
{
|
||||
|
||||
@@ -71,7 +71,7 @@ enum CreatureFlagsExtra : uint32
|
||||
CREATURE_FLAG_EXTRA_AVOID_AOE = 0x00400000, // pussywizard: ignored by aoe attacks (for icc blood prince council npc - Dark Nucleus)
|
||||
CREATURE_FLAG_EXTRA_NO_DODGE = 0x00800000, // xinef: target cannot dodge
|
||||
CREATURE_FLAG_EXTRA_MODULE = 0x01000000,
|
||||
CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE = 0x02000000, // Creatures do not call periodically assistance in combat
|
||||
CREATURE_FLAG_EXTRA_IGNORE_ASSISTANCE_CALL = 0x02000000, // Creatures are not aggroed by other mobs assistance functions
|
||||
CREATURE_FLAG_EXTRA_UNUSED_27 = 0x04000000,
|
||||
CREATURE_FLAG_EXTRA_UNUSED_28 = 0x08000000,
|
||||
CREATURE_FLAG_EXTRA_DUNGEON_BOSS = 0x10000000, // creature is a dungeon boss (SET DYNAMICALLY, DO NOT ADD IN DB)
|
||||
|
||||
@@ -56,7 +56,7 @@ AC_API_EXPORT EnumText EnumUtils<CreatureFlagsExtra>::ToString(CreatureFlagsExtr
|
||||
case CREATURE_FLAG_EXTRA_AVOID_AOE: return { "CREATURE_FLAG_EXTRA_AVOID_AOE", "CREATURE_FLAG_EXTRA_AVOID_AOE", "pussywizard: ignored by aoe attacks (for icc blood prince council npc - Dark Nucleus)" };
|
||||
case CREATURE_FLAG_EXTRA_NO_DODGE: return { "CREATURE_FLAG_EXTRA_NO_DODGE", "CREATURE_FLAG_EXTRA_NO_DODGE", "xinef: target cannot dodge" };
|
||||
case CREATURE_FLAG_EXTRA_MODULE: return { "CREATURE_FLAG_EXTRA_MODULE", "CREATURE_FLAG_EXTRA_MODULE", "Used by module creatures to avoid blizzlike checks." };
|
||||
case CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE: return { "CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE", "Creatures do not call periodically assistance in combat", "" };
|
||||
case CREATURE_FLAG_EXTRA_IGNORE_ASSISTANCE_CALL: return { "CREATURE_FLAG_EXTRA_IGNORE_ASSISTANCE_CALL", "Creatures are not aggroed by other mobs assistance functions", "" };
|
||||
case CREATURE_FLAG_EXTRA_UNUSED_27: return { "CREATURE_FLAG_EXTRA_UNUSED_27", "CREATURE_FLAG_EXTRA_UNUSED_27", "" };
|
||||
case CREATURE_FLAG_EXTRA_UNUSED_28: return { "CREATURE_FLAG_EXTRA_UNUSED_28", "CREATURE_FLAG_EXTRA_UNUSED_28", "" };
|
||||
case CREATURE_FLAG_EXTRA_DUNGEON_BOSS: return { "CREATURE_FLAG_EXTRA_DUNGEON_BOSS", "CREATURE_FLAG_EXTRA_DUNGEON_BOSS", "creature is a dungeon boss (SET DYNAMICALLY, DO NOT ADD IN DB)" };
|
||||
@@ -100,7 +100,7 @@ AC_API_EXPORT CreatureFlagsExtra EnumUtils<CreatureFlagsExtra>::FromIndex(size_t
|
||||
case 22: return CREATURE_FLAG_EXTRA_AVOID_AOE;
|
||||
case 23: return CREATURE_FLAG_EXTRA_NO_DODGE;
|
||||
case 24: return CREATURE_FLAG_EXTRA_MODULE;
|
||||
case 25: return CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE;
|
||||
case 25: return CREATURE_FLAG_EXTRA_IGNORE_ASSISTANCE_CALL;
|
||||
case 26: return CREATURE_FLAG_EXTRA_UNUSED_27;
|
||||
case 27: return CREATURE_FLAG_EXTRA_UNUSED_28;
|
||||
case 28: return CREATURE_FLAG_EXTRA_DUNGEON_BOSS;
|
||||
@@ -141,7 +141,7 @@ AC_API_EXPORT size_t EnumUtils<CreatureFlagsExtra>::ToIndex(CreatureFlagsExtra v
|
||||
case CREATURE_FLAG_EXTRA_AVOID_AOE: return 22;
|
||||
case CREATURE_FLAG_EXTRA_NO_DODGE: return 23;
|
||||
case CREATURE_FLAG_EXTRA_MODULE: return 24;
|
||||
case CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE: return 25;
|
||||
case CREATURE_FLAG_EXTRA_IGNORE_ASSISTANCE_CALL: return 25;
|
||||
case CREATURE_FLAG_EXTRA_UNUSED_27: return 26;
|
||||
case CREATURE_FLAG_EXTRA_UNUSED_28: return 27;
|
||||
case CREATURE_FLAG_EXTRA_DUNGEON_BOSS: return 28;
|
||||
|
||||
@@ -10031,12 +10031,8 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
|
||||
|
||||
creature->SendAIReaction(AI_REACTION_HOSTILE);
|
||||
|
||||
CreatureTemplate const* cInfo = creature->GetCreatureTemplate();
|
||||
if (!cInfo || !cInfo->HasFlagsExtra(CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE))
|
||||
{
|
||||
creature->CallAssistance();
|
||||
creature->SetAssistanceTimer(sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_PERIOD));
|
||||
}
|
||||
creature->CallAssistance();
|
||||
creature->SetAssistanceTimer(sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_PERIOD));
|
||||
|
||||
SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
|
||||
}
|
||||
|
||||
@@ -344,6 +344,9 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId)
|
||||
ASSERT(seat->second.IsEmpty());
|
||||
}
|
||||
|
||||
if (!seat->second.SeatInfo)
|
||||
return false;
|
||||
|
||||
LOG_DEBUG("vehicles", "Unit {} enter vehicle entry {} id {} ({}) seat {}",
|
||||
unit->GetName(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUID().ToString(), (int32)seat->first);
|
||||
|
||||
|
||||
@@ -3258,33 +3258,23 @@ void Spell::DoTriggersOnSpellHit(Unit* unit, uint8 effMask)
|
||||
{
|
||||
if (CanExecuteTriggersOnHit(effMask, i->triggeredByAura) && roll_chance_i(i->chance))
|
||||
{
|
||||
m_caster->CastSpell(unit, i->triggeredSpell->Id, true);
|
||||
LOG_DEBUG("spells.aura", "Spell {} triggered spell {} by SPELL_AURA_ADD_TARGET_TRIGGER aura", m_spellInfo->Id, i->triggeredSpell->Id);
|
||||
|
||||
// SPELL_AURA_ADD_TARGET_TRIGGER auras shouldn't trigger auras without duration
|
||||
// set duration of current aura to the triggered spell
|
||||
if (i->triggeredSpell->GetDuration() == -1)
|
||||
{
|
||||
// get duration from aura-only once
|
||||
if (!_duration)
|
||||
{
|
||||
Aura* aur = unit->GetAura(m_spellInfo->Id, m_caster->GetGUID());
|
||||
_duration = aur ? aur->GetDuration() : -1;
|
||||
}
|
||||
|
||||
if (Aura* triggeredAur = unit->GetAura(i->triggeredSpell->Id, m_caster->GetGUID()))
|
||||
{
|
||||
triggeredAur->SetDuration(std::max(triggeredAur->GetDuration(), _duration));
|
||||
// get duration from aura-only once
|
||||
if (!_duration)
|
||||
{
|
||||
Aura* aur = unit->GetAura(m_spellInfo->Id, m_caster->GetGUID());
|
||||
_duration = aur ? aur->GetDuration() : -1;
|
||||
}
|
||||
triggeredAur->SetDuration(_duration);
|
||||
}
|
||||
else
|
||||
{
|
||||
AuraEffect const* triggeringAuraEffect = m_caster->GetAuraEffect(i->triggeredByAura->Id, i->triggeredByEffIdx);
|
||||
m_caster->CastCustomSpell(i->triggeredSpell->Id, SPELLVALUE_AURA_DURATION, _duration, unit, true, nullptr, triggeringAuraEffect);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AuraEffect const* triggeringAuraEffect = m_caster->GetAuraEffect(i->triggeredByAura->Id, i->triggeredByEffIdx);
|
||||
m_caster->CastSpell(unit, i->triggeredSpell, true, nullptr, triggeringAuraEffect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4409,6 +4409,12 @@ void SpellMgr::LoadSpellInfoCorrections()
|
||||
spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(27);
|
||||
});
|
||||
|
||||
// Rental Racing Ram
|
||||
ApplySpellFix({ 43883 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
spellInfo->AuraInterruptFlags &= ~AURA_INTERRUPT_FLAG_NOT_ABOVEWATER;
|
||||
});
|
||||
|
||||
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
|
||||
{
|
||||
SpellInfo* spellInfo = mSpellInfoMap[i];
|
||||
|
||||
@@ -70,6 +70,7 @@ enum Spells
|
||||
// Tentacles
|
||||
SPELL_SUBMERGE_VISUAL = 26234,
|
||||
SPELL_BIRTH = 26262,
|
||||
SPELL_ROCKY_GROUND_IMPACT = 26271,
|
||||
|
||||
// Areatriggers
|
||||
SPELL_SPIT_OUT = 25383,
|
||||
@@ -186,9 +187,9 @@ struct boss_eye_of_cthun : public BossAI
|
||||
|
||||
void EnterCombat(Unit* who) override
|
||||
{
|
||||
DoZoneInCombat();
|
||||
ScheduleTasks();
|
||||
BossAI::EnterCombat(who);
|
||||
_beamTarget = who->GetGUID();
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
@@ -222,11 +223,29 @@ struct boss_eye_of_cthun : public BossAI
|
||||
_scheduler.
|
||||
Schedule(3s, [this](TaskContext task)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_GREEN_BEAM);
|
||||
if (task.GetRepeatCounter() < 3)
|
||||
{
|
||||
if (Unit* target = ObjectAccessor::GetUnit(*me, _beamTarget))
|
||||
{
|
||||
DoCast(target, SPELL_GREEN_BEAM);
|
||||
}
|
||||
|
||||
task.Repeat();
|
||||
}
|
||||
else
|
||||
{
|
||||
_scheduler.Schedule(5s, [this](TaskContext task)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_GREEN_BEAM);
|
||||
|
||||
task.SetGroup(GROUP_BEAM_PHASE);
|
||||
task.Repeat(3s);
|
||||
});
|
||||
}
|
||||
|
||||
task.SetGroup(GROUP_BEAM_PHASE);
|
||||
task.Repeat();
|
||||
})
|
||||
.Schedule(12s, [this](TaskContext task)
|
||||
.Schedule(8s, [this](TaskContext task)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
|
||||
{
|
||||
@@ -324,48 +343,32 @@ struct boss_eye_of_cthun : public BossAI
|
||||
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
switch (instance->GetData(DATA_CTHUN_PHASE))
|
||||
//Only if it will kill
|
||||
if (damage < me->GetHealth())
|
||||
return;
|
||||
|
||||
//Fake death in phase 0 or 1 (green beam or dark glare phase)
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
|
||||
//Remove Red coloration from c'thun
|
||||
me->RemoveAurasDueToSpell(SPELL_RED_COLORATION);
|
||||
|
||||
//Reset to normal emote state and prevent select and attack
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
|
||||
|
||||
//Remove Target field
|
||||
me->SetTarget();
|
||||
|
||||
me->SetHealth(0);
|
||||
damage = 0;
|
||||
|
||||
me->InterruptNonMeleeSpells(true);
|
||||
me->RemoveAllAuras();
|
||||
_scheduler.CancelAll();
|
||||
|
||||
if (Creature* cthun = instance->GetCreature(DATA_CTHUN))
|
||||
{
|
||||
case PHASE_EYE_GREEN_BEAM:
|
||||
case PHASE_EYE_RED_BEAM:
|
||||
//Only if it will kill
|
||||
if (damage < me->GetHealth())
|
||||
return;
|
||||
|
||||
//Fake death in phase 0 or 1 (green beam or dark glare phase)
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
|
||||
//Remove Red coloration from c'thun
|
||||
me->RemoveAurasDueToSpell(SPELL_RED_COLORATION);
|
||||
|
||||
//Reset to normal emote state and prevent select and attack
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
|
||||
|
||||
//Remove Target field
|
||||
me->SetTarget();
|
||||
|
||||
me->SetHealth(0);
|
||||
damage = 0;
|
||||
|
||||
me->InterruptNonMeleeSpells(true);
|
||||
me->RemoveAllAuras();
|
||||
_scheduler.CancelAll();
|
||||
|
||||
if (Creature* cthun = instance->GetCreature(DATA_CTHUN))
|
||||
{
|
||||
cthun->AI()->DoAction(ACTION_START_PHASE_TWO);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PHASE_CTHUN_DONE:
|
||||
//Allow death here
|
||||
return;
|
||||
|
||||
default:
|
||||
//Prevent death in these phases
|
||||
damage = 0;
|
||||
return;
|
||||
cthun->AI()->DoAction(ACTION_START_PHASE_TWO);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,6 +379,7 @@ private:
|
||||
bool ClockWise;
|
||||
|
||||
uint32 _eyeTentacleCounter;
|
||||
ObjectGuid _beamTarget;
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
@@ -424,7 +428,7 @@ struct boss_cthun : public BossAI
|
||||
//Spawn flesh tentacle
|
||||
for (uint8 i = 0; i < 2; i++)
|
||||
{
|
||||
me->SummonCreature(NPC_FLESH_TENTACLE, FleshTentaclePos[i], TEMPSUMMON_CORPSE_DESPAWN);
|
||||
me->SummonCreature(NPC_FLESH_TENTACLE, FleshTentaclePos[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000);
|
||||
}
|
||||
|
||||
ScheduleTasks();
|
||||
@@ -457,25 +461,27 @@ struct boss_cthun : public BossAI
|
||||
}
|
||||
|
||||
context.Repeat(30s);
|
||||
}).Schedule(15s, [this](TaskContext context)
|
||||
}).Schedule(8s, [this](TaskContext context)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, -SPELL_DIGESTIVE_ACID))
|
||||
{
|
||||
//Spawn claw tentacle on the random target
|
||||
if (Creature* spawned = me->SummonCreature(NPC_GIANT_CLAW_TENTACLE, *target, TEMPSUMMON_CORPSE_DESPAWN, 500))
|
||||
if (spawned->AI())
|
||||
spawned->AI()->AttackStart(target);
|
||||
{
|
||||
spawned->AI()->AttackStart(target);
|
||||
}
|
||||
}
|
||||
|
||||
context.Repeat(1min);
|
||||
}).Schedule(15s, [this](TaskContext context)
|
||||
}).Schedule(38s, [this](TaskContext context)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, -SPELL_DIGESTIVE_ACID))
|
||||
{
|
||||
//Spawn claw tentacle on the random target
|
||||
if (Creature* spawned = me->SummonCreature(NPC_GIANT_EYE_TENTACLE, *target, TEMPSUMMON_CORPSE_DESPAWN, 500))
|
||||
if (spawned->AI())
|
||||
spawned->AI()->AttackStart(target);
|
||||
{
|
||||
spawned->AI()->AttackStart(target);
|
||||
}
|
||||
}
|
||||
|
||||
context.Repeat(1min);
|
||||
@@ -536,6 +542,8 @@ struct boss_cthun : public BossAI
|
||||
{
|
||||
++_fleshTentaclesKilled;
|
||||
|
||||
creature->CastSpell(creature, SPELL_ROCKY_GROUND_IMPACT, true);
|
||||
|
||||
if (_fleshTentaclesKilled > 1)
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
@@ -580,6 +588,14 @@ struct npc_eye_tentacle : public ScriptedAI
|
||||
{
|
||||
portal->SetReactState(REACT_PASSIVE);
|
||||
_portalGUID = portal->GetGUID();
|
||||
|
||||
if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit())
|
||||
{
|
||||
if (Creature* creature = summoner->ToCreature())
|
||||
{
|
||||
creature->AI()->JustSummoned(portal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetCombatMovement(false);
|
||||
@@ -643,6 +659,14 @@ struct npc_claw_tentacle : public ScriptedAI
|
||||
{
|
||||
portal->SetReactState(REACT_PASSIVE);
|
||||
_portalGUID = portal->GetGUID();
|
||||
|
||||
if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit())
|
||||
{
|
||||
if (Creature* creature = summoner->ToCreature())
|
||||
{
|
||||
creature->AI()->JustSummoned(portal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -702,6 +726,14 @@ struct npc_giant_claw_tentacle : public ScriptedAI
|
||||
{
|
||||
portal->SetReactState(REACT_PASSIVE);
|
||||
_portalGUID = portal->GetGUID();
|
||||
|
||||
if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit())
|
||||
{
|
||||
if (Creature* creature = summoner->ToCreature())
|
||||
{
|
||||
creature->AI()->JustSummoned(portal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -835,6 +867,14 @@ struct npc_giant_eye_tentacle : public ScriptedAI
|
||||
{
|
||||
portal->SetReactState(REACT_PASSIVE);
|
||||
_portalGUID = portal->GetGUID();
|
||||
|
||||
if (Unit* summoner = me->ToTempSummon()->GetSummonerUnit())
|
||||
{
|
||||
if (Creature* creature = summoner->ToCreature())
|
||||
{
|
||||
creature->AI()->JustSummoned(portal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -931,9 +971,12 @@ public:
|
||||
|
||||
bool OnTrigger(Player* player, AreaTrigger const* /*at*/) override
|
||||
{
|
||||
if (Creature* trigger = player->FindNearestCreature(NPC_TRIGGER, 15.0f))
|
||||
if (InstanceScript* instance = player->GetInstanceScript())
|
||||
{
|
||||
trigger->CastSpell(player, SPELL_SPIT_OUT, true);
|
||||
if (Creature* cthun = instance->GetCreature(DATA_CTHUN))
|
||||
{
|
||||
cthun->CastSpell(player, SPELL_SPIT_OUT, true);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -35,8 +35,7 @@ enum Spells
|
||||
SPELL_WYVERN_STING = 26180,
|
||||
SPELL_ACID_SPIT = 26050,
|
||||
SPELL_WYVERN_STING_DAMAGE = 26233,
|
||||
SPELL_POISON_BOLT = 26052,
|
||||
SPELL_HARD_ENRAGE = 26662
|
||||
SPELL_POISON_BOLT = 26052
|
||||
};
|
||||
|
||||
enum Events
|
||||
@@ -54,18 +53,18 @@ struct boss_huhuran : public BossAI
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
BossAI::Reset();
|
||||
_berserk = false;
|
||||
_hardEnrage = false;
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_FRENZY, urand(25000, 35000));
|
||||
events.ScheduleEvent(EVENT_WYVERN_STING, urand(18000, 28000));
|
||||
events.ScheduleEvent(EVENT_ACID_SPIT, 8000);
|
||||
events.ScheduleEvent(EVENT_NOXIOUS_POISON, urand(10000, 20000));
|
||||
events.ScheduleEvent(EVENT_HARD_ENRAGE, 300000);
|
||||
events.ScheduleEvent(EVENT_FRENZY, 12s, 21s);
|
||||
events.ScheduleEvent(EVENT_WYVERN_STING, 25s, 43s);
|
||||
events.ScheduleEvent(EVENT_ACID_SPIT, 1s, 20s);
|
||||
events.ScheduleEvent(EVENT_NOXIOUS_POISON, 10s, 22s);
|
||||
events.ScheduleEvent(EVENT_HARD_ENRAGE, 5min);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override
|
||||
@@ -74,6 +73,7 @@ struct boss_huhuran : public BossAI
|
||||
{
|
||||
DoCastSelf(SPELL_BERSERK, true);
|
||||
me->TextEmote(EMOTE_BERSERK);
|
||||
events.CancelEvent(EVENT_FRENZY);
|
||||
_berserk = true;
|
||||
}
|
||||
}
|
||||
@@ -91,39 +91,43 @@ struct boss_huhuran : public BossAI
|
||||
case EVENT_FRENZY:
|
||||
DoCastSelf(SPELL_FRENZY, true);
|
||||
Talk(EMOTE_FRENZY_KILL);
|
||||
events.RepeatEvent(urand(25000, 35000));
|
||||
events.Repeat(12s, 21s);
|
||||
break;
|
||||
case EVENT_WYVERN_STING:
|
||||
me->CastCustomSpell(SPELL_WYVERN_STING, SPELLVALUE_MAX_TARGETS, 10, me, true);
|
||||
events.RepeatEvent(urand(15000, 32000));
|
||||
events.Repeat(25s, 43s);
|
||||
break;
|
||||
case EVENT_ACID_SPIT:
|
||||
DoCastVictim(SPELL_ACID_SPIT);
|
||||
events.RepeatEvent(urand(5000, 10000));
|
||||
events.Repeat(1s, 20s);
|
||||
break;
|
||||
case EVENT_NOXIOUS_POISON:
|
||||
DoCastRandomTarget(SPELL_NOXIOUS_POISON, 0, 100, true);
|
||||
events.RepeatEvent(urand(12000, 24000));
|
||||
DoCastRandomTarget(SPELL_NOXIOUS_POISON, 0, 100.f, true);
|
||||
events.Repeat(10s, 22s);
|
||||
break;
|
||||
case EVENT_HARD_ENRAGE:
|
||||
if (!_hardEnrage)
|
||||
{
|
||||
DoCastSelf(SPELL_HARD_ENRAGE, true);
|
||||
DoCastSelf(SPELL_BERSERK, true);
|
||||
events.CancelEvent(EVENT_FRENZY);
|
||||
_hardEnrage = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
DoCastAOE(SPELL_POISON_BOLT);
|
||||
}
|
||||
events.RepeatEvent(3000);
|
||||
events.Repeat(2s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
private:
|
||||
bool _berserk;
|
||||
bool _hardEnrage;
|
||||
|
||||
private:
|
||||
bool _berserk;
|
||||
bool _hardEnrage;
|
||||
};
|
||||
|
||||
// 26180 - Wyvern Sting
|
||||
|
||||
@@ -49,14 +49,15 @@ enum events
|
||||
EVENT_SPELL_BERSERK = 4,
|
||||
EVENT_SARTURA_AGGRO_RESET = 5,
|
||||
EVENT_SARTURA_AGGRO_RESET_END = 6,
|
||||
EVENT_SARTURA_SUNDERING_CLEAVE = 7,
|
||||
|
||||
// Sartura's Royal Guard
|
||||
EVENT_GUARD_WHIRLWIND = 7,
|
||||
EVENT_GUARD_WHIRLWIND_RANDOM = 8,
|
||||
EVENT_GUARD_WHIRLWIND_END = 9,
|
||||
EVENT_GUARD_KNOCKBACK = 10,
|
||||
EVENT_GUARD_AGGRO_RESET = 11,
|
||||
EVENT_GUARD_AGGRO_RESET_END = 12
|
||||
EVENT_GUARD_WHIRLWIND = 8,
|
||||
EVENT_GUARD_WHIRLWIND_RANDOM = 9,
|
||||
EVENT_GUARD_WHIRLWIND_END = 10,
|
||||
EVENT_GUARD_KNOCKBACK = 11,
|
||||
EVENT_GUARD_AGGRO_RESET = 12,
|
||||
EVENT_GUARD_AGGRO_RESET_END = 13
|
||||
};
|
||||
|
||||
struct boss_sartura : public BossAI
|
||||
@@ -96,9 +97,10 @@ struct boss_sartura : public BossAI
|
||||
{
|
||||
BossAI::EnterCombat(who);
|
||||
Talk(SAY_AGGRO);
|
||||
events.ScheduleEvent(EVENT_SARTURA_WHIRLWIND, 30000);
|
||||
events.ScheduleEvent(EVENT_SARTURA_WHIRLWIND, 12s, 22s);
|
||||
events.ScheduleEvent(EVENT_SARTURA_AGGRO_RESET, urand(45000, 55000));
|
||||
events.ScheduleEvent(EVENT_SPELL_BERSERK, 10 * 60000);
|
||||
events.ScheduleEvent(EVENT_SARTURA_SUNDERING_CLEAVE, 2400ms, 3s);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
@@ -121,14 +123,6 @@ struct boss_sartura : public BossAI
|
||||
}
|
||||
}
|
||||
|
||||
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->Id != SPELL_SUNDERING_CLEAVE)
|
||||
return;
|
||||
|
||||
me->RemoveAura(SPELL_SUNDERING_CLEAVE);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
@@ -161,7 +155,7 @@ struct boss_sartura : public BossAI
|
||||
case EVENT_SARTURA_WHIRLWIND_END:
|
||||
events.CancelEvent(EVENT_SARTURA_WHIRLWIND_RANDOM);
|
||||
whirlwind = false;
|
||||
events.ScheduleEvent(EVENT_SARTURA_WHIRLWIND, urand(25000, 40000));
|
||||
events.ScheduleEvent(EVENT_SARTURA_WHIRLWIND, 5s, 11s);
|
||||
break;
|
||||
case EVENT_SARTURA_AGGRO_RESET:
|
||||
if (aggroReset == false)
|
||||
@@ -203,6 +197,18 @@ struct boss_sartura : public BossAI
|
||||
berserked = true;
|
||||
}
|
||||
break;
|
||||
case EVENT_SARTURA_SUNDERING_CLEAVE:
|
||||
if (whirlwind)
|
||||
{
|
||||
Milliseconds whirlwindTimer = events.GetTimeUntilEvent(EVENT_SARTURA_WHIRLWIND_END);
|
||||
events.RescheduleEvent(EVENT_SARTURA_SUNDERING_CLEAVE, whirlwindTimer + 500ms);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoCastVictim(SPELL_SUNDERING_CLEAVE, false);
|
||||
events.RescheduleEvent(EVENT_SARTURA_SUNDERING_CLEAVE, 2400ms, 3s);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -233,17 +239,9 @@ struct npc_sartura_royal_guard : public ScriptedAI
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_GUARD_WHIRLWIND, 30000);
|
||||
events.ScheduleEvent(EVENT_GUARD_WHIRLWIND, 6s, 10s);
|
||||
events.ScheduleEvent(EVENT_GUARD_AGGRO_RESET, urand(45000, 55000));
|
||||
events.ScheduleEvent(EVENT_GUARD_KNOCKBACK, 10000);
|
||||
}
|
||||
|
||||
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->Id != SPELL_SUNDERING_CLEAVE)
|
||||
return;
|
||||
|
||||
me->RemoveAura(SPELL_SUNDERING_CLEAVE);
|
||||
events.ScheduleEvent(EVENT_GUARD_KNOCKBACK, 12s, 16s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
@@ -261,7 +259,7 @@ struct npc_sartura_royal_guard : public ScriptedAI
|
||||
DoCastSelf(SPELL_GUARD_WHIRLWIND);
|
||||
whirlwind = true;
|
||||
events.ScheduleEvent(EVENT_GUARD_WHIRLWIND_RANDOM, urand(3000, 7000));
|
||||
events.ScheduleEvent(EVENT_GUARD_WHIRLWIND_END, 15000);
|
||||
events.ScheduleEvent(EVENT_GUARD_WHIRLWIND_END, 8s);
|
||||
break;
|
||||
case EVENT_GUARD_WHIRLWIND_RANDOM:
|
||||
if (whirlwind == true)
|
||||
@@ -278,7 +276,7 @@ struct npc_sartura_royal_guard : public ScriptedAI
|
||||
case EVENT_GUARD_WHIRLWIND_END:
|
||||
events.CancelEvent(EVENT_GUARD_WHIRLWIND_RANDOM);
|
||||
whirlwind = false;
|
||||
events.ScheduleEvent(EVENT_GUARD_WHIRLWIND, urand(25000, 40000));
|
||||
events.ScheduleEvent(EVENT_GUARD_WHIRLWIND, 500ms, 9s);
|
||||
break;
|
||||
case EVENT_GUARD_AGGRO_RESET:
|
||||
if (aggroReset == true)
|
||||
@@ -315,7 +313,7 @@ struct npc_sartura_royal_guard : public ScriptedAI
|
||||
break;
|
||||
case EVENT_GUARD_KNOCKBACK:
|
||||
DoCastVictim(SPELL_GUARD_KNOCKBACK);
|
||||
events.RepeatEvent(urand(10000, 20000));
|
||||
events.Repeat(21s, 37s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user