fix(Scripts/ZulGurub): Renataki - improvements: (#11967)

Added missing spells and events.
Removed invalid spells
Corrected event timers
Fixes #11620
Fixes #11621
This commit is contained in:
UltraNix
2022-06-16 16:39:09 +02:00
committed by GitHub
parent 97511abe1e
commit 117a18c961
4 changed files with 189 additions and 98 deletions
+1
View File
@@ -196,6 +196,7 @@ public:
virtual bool CanSeeAlways(WorldObject const* /*obj*/) { return false; } virtual bool CanSeeAlways(WorldObject const* /*obj*/) { return false; }
virtual bool CanBeSeen(Player const* /*seer*/) { return true; } virtual bool CanBeSeen(Player const* /*seer*/) { return true; }
virtual bool CanAlwaysBeDetectable(WorldObject const* /*seer*/) { return false; }
virtual void PetStopAttack() { } virtual void PetStopAttack() { }
@@ -1809,6 +1809,21 @@ bool Creature::CanAlwaysSee(WorldObject const* obj) const
return false; return false;
} }
bool Creature::IsAlwaysDetectableFor(WorldObject const* seer) const
{
if (Unit::IsAlwaysDetectableFor(seer))
{
return true;
}
if (IsAIEnabled && AI()->CanAlwaysBeDetectable(seer))
{
return true;
}
return false;
}
bool Creature::CanStartAttack(Unit const* who) const bool Creature::CanStartAttack(Unit const* who) const
{ {
if (IsCivilian()) if (IsCivilian())
@@ -444,6 +444,7 @@ protected:
[[nodiscard]] bool IsInvisibleDueToDespawn() const override; [[nodiscard]] bool IsInvisibleDueToDespawn() const override;
bool CanAlwaysSee(WorldObject const* obj) const override; bool CanAlwaysSee(WorldObject const* obj) const override;
bool IsAlwaysDetectableFor(WorldObject const* seer) const override;
private: private:
void ForcedDespawn(uint32 timeMSToDespawn = 0, Seconds forcedRespawnTimer = 0s); void ForcedDespawn(uint32 timeMSToDespawn = 0, Seconds forcedRespawnTimer = 0s);
@@ -28,13 +28,20 @@ EndScriptData */
enum Spells enum Spells
{ {
SPELL_AMBUSH = 34794, SPELL_VANISH = 24699,
SPELL_THOUSANDBLADES = 34799 SPELL_AMBUSH = 24337,
SPELL_GOUGE = 24698,
SPELL_THOUSAND_BLADES = 24649,
SPELL_THRASH = 3417,
SPELL_ENRAGE = 8269
}; };
enum Misc enum Events
{ {
EQUIP_ID_MAIN_HAND = 0 //was item display id 31818, but this id does not exist EVENT_VANISH = 1,
EVENT_AMBUSH = 2,
EVENT_GOUGE = 3,
EVENT_THOUSAND_BLADES = 4
}; };
class boss_renataki : public CreatureScript class boss_renataki : public CreatureScript
@@ -46,36 +53,67 @@ public:
{ {
boss_renatakiAI(Creature* creature) : BossAI(creature, DATA_EDGE_OF_MADNESS) { } boss_renatakiAI(Creature* creature) : BossAI(creature, DATA_EDGE_OF_MADNESS) { }
uint32 Invisible_Timer;
uint32 Ambush_Timer;
uint32 Visible_Timer;
uint32 Aggro_Timer;
uint32 ThousandBlades_Timer;
bool Invisible;
bool Ambushed;
void Reset() override void Reset() override
{ {
_Reset(); _Reset();
Invisible_Timer = urand(8000, 18000); me->SetReactState(REACT_AGGRESSIVE);
Ambush_Timer = 3000; _enraged = false;
Visible_Timer = 4000; _thousandBladesCount = urand(2, 5);
Aggro_Timer = urand(15000, 25000); _thousandBladesTargets.clear();
ThousandBlades_Timer = urand(4000, 8000); _dynamicFlags = me->GetDynamicFlags();
Invisible = false;
Ambushed = false;
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
} }
void EnterCombat(Unit* /*who*/) override void EnterCombat(Unit* /*who*/) override
{ {
_EnterCombat(); _EnterCombat();
events.ScheduleEvent(EVENT_VANISH, 23s, 25s);
events.ScheduleEvent(EVENT_GOUGE, 5s, 10s);
events.ScheduleEvent(EVENT_THOUSAND_BLADES, 15s, 20s);
DoCastSelf(SPELL_THRASH, true);
}
void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) override
{
if (!_enraged && HealthBelowPct(30))
{
me->TextEmote("%s becomes enraged", me, false);
DoCast(me, SPELL_ENRAGE);
_enraged = true;
}
}
bool CanAIAttack(Unit const* target) const override
{
if (me->GetThreatMgr().getThreatList().size() > 1 && me->GetThreatMgr().getOnlineContainer().getMostHated()->getTarget() == target)
return !target->HasAura(SPELL_GOUGE);
return true;
}
bool CanBeSeen(Player const* /*player*/) override
{
return me->GetReactState() == REACT_AGGRESSIVE;
}
bool CanSeeAlways(WorldObject const* obj) override
{
if (me->GetReactState() == REACT_PASSIVE)
{
return obj->ToCreature() && obj->ToCreature()->IsPet();
}
return false;
}
bool CanAlwaysBeDetectable(WorldObject const* seer) override
{
if (me->GetReactState() == REACT_PASSIVE)
{
return seer->ToCreature() && seer->ToCreature()->IsPet();
}
return false;
} }
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
@@ -83,86 +121,122 @@ public:
if (!UpdateVictim()) if (!UpdateVictim())
return; return;
//Invisible_Timer events.Update(diff);
if (Invisible_Timer <= diff)
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{ {
me->InterruptSpell(CURRENT_GENERIC_SPELL); switch (eventId)
SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
me->SetDisplayId(11686);
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
Invisible = true;
Invisible_Timer = urand(15000, 30000);
}
else Invisible_Timer -= diff;
if (Invisible)
{ {
if (Ambush_Timer <= diff) case EVENT_VANISH:
{ me->SetReactState(REACT_PASSIVE);
Unit* target = SelectTarget(SelectTargetMethod::Random, 0); _dynamicFlags = me->GetDynamicFlags();
if (target) me->RemoveDynamicFlag(UNIT_DYNFLAG_TRACK_UNIT);
DoCastSelf(SPELL_VANISH);
events.DelayEvents(5s);
events.ScheduleEvent(EVENT_AMBUSH, 5s);
events.ScheduleEvent(EVENT_VANISH, 38s, 45s);
return;
case EVENT_AMBUSH:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1))
{ {
me->NearTeleportTo(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), me->GetOrientation()); me->NearTeleportTo(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), me->GetOrientation());
DoCast(target, SPELL_AMBUSH); DoCast(target, SPELL_AMBUSH, true);
} }
me->SetDynamicFlag(_dynamicFlags);
Ambushed = true; me->RemoveAurasDueToSpell(SPELL_VANISH);
Ambush_Timer = 3000; me->SetReactState(REACT_AGGRESSIVE);
} break;
else Ambush_Timer -= diff; case EVENT_GOUGE:
} DoCastAOE(SPELL_GOUGE);
events.ScheduleEvent(EVENT_GOUGE, 10s, 15s);
if (Ambushed) return;
case EVENT_THOUSAND_BLADES:
{ {
if (Visible_Timer <= diff) if (_thousandBladesTargets.empty())
{ {
me->InterruptSpell(CURRENT_GENERIC_SPELL); std::vector<Unit*> targetList;
ThreatContainer::StorageType const& threatlist = me->GetThreatMgr().getThreatList();
me->SetDisplayId(15268); for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
Invisible = false;
Visible_Timer = 4000;
}
else Visible_Timer -= diff;
}
//Resetting some aggro so he attacks other gamers
if (!Invisible)
{ {
if (Aggro_Timer <= diff) if (Unit* target = (*itr)->getTarget())
{ {
Unit* target = SelectTarget(SelectTargetMethod::Random, 1); if (target->IsAlive() && target->IsWithinDist2d(me, 100.f))
if (DoGetThreat(me->GetVictim()))
{ {
DoModifyThreatPercent(me->GetVictim(), -50); targetList.push_back(target);
}
}
} }
if (target) if (!targetList.empty())
{ {
AttackStart(target); Acore::Containers::RandomShuffle(targetList);
}
Aggro_Timer = urand(7000, 20000); // First get ranged targets
} for (Unit* target : targetList)
else Aggro_Timer -= diff;
if (ThousandBlades_Timer <= diff)
{ {
DoCastVictim(SPELL_THOUSANDBLADES); if (!target->IsWithinMeleeRange(me))
ThousandBlades_Timer = urand(7000, 12000); {
_thousandBladesTargets.push_back(target);
} }
else ThousandBlades_Timer -= diff;
} }
if (_thousandBladesTargets.size() < _thousandBladesCount)
{
// if still not enough, get melee targets
for (Unit* target : targetList)
{
if (target->IsWithinMeleeRange(me))
{
_thousandBladesTargets.push_back(target);
}
}
}
if (!_thousandBladesTargets.empty())
{
Acore::Containers::RandomResize(_thousandBladesTargets, _thousandBladesCount);
}
}
}
if (!_thousandBladesTargets.empty())
{
std::vector<Unit*>::iterator itr = _thousandBladesTargets.begin();
std::advance(itr, urand(0, _thousandBladesTargets.size() - 1));
if (Unit* target = *itr)
{
DoCast(target, SPELL_THOUSAND_BLADES, false);
}
_thousandBladesTargets.erase(itr);
events.ScheduleEvent(EVENT_THOUSAND_BLADES, 500ms);
}
else
{
_thousandBladesCount = urand(2, 5);
events.ScheduleEvent(EVENT_THOUSAND_BLADES, 15s, 22s);
}
break;
}
default:
break;
}
}
if (me->GetReactState() == REACT_AGGRESSIVE)
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
private:
bool _enraged;
uint32 _dynamicFlags;
uint8 _thousandBladesCount;
std::vector<Unit*> _thousandBladesTargets;
}; };
CreatureAI* GetAI(Creature* creature) const override CreatureAI* GetAI(Creature* creature) const override