mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-26 15:16:24 +00:00
Merge branch 'azerothcore:master' into Playerbot
This commit is contained in:
@@ -499,7 +499,7 @@ void DBUpdater<T>::ApplyFile(DatabaseWorkerPool<T>& pool, std::string const& hos
|
||||
std::string const& password, std::string const& port_or_socket, std::string const& database, std::string const& ssl, Path const& path)
|
||||
{
|
||||
std::vector<std::string> args;
|
||||
args.reserve(7);
|
||||
args.reserve(9);
|
||||
|
||||
// CLI Client connection info
|
||||
args.emplace_back("-h" + host);
|
||||
@@ -549,13 +549,17 @@ void DBUpdater<T>::ApplyFile(DatabaseWorkerPool<T>& pool, std::string const& hos
|
||||
|
||||
#endif
|
||||
|
||||
// Execute sql file
|
||||
args.emplace_back("-e");
|
||||
args.emplace_back(Acore::StringFormat("BEGIN; SOURCE %s; COMMIT;", path.generic_string().c_str()));
|
||||
|
||||
// Database
|
||||
if (!database.empty())
|
||||
args.emplace_back(database);
|
||||
|
||||
// Invokes a mysql process which doesn't leak credentials to logs
|
||||
int const ret = Acore::StartProcess(DBUpdaterUtil::GetCorrectedMySQLExecutable(), args,
|
||||
"sql.updates", path.generic_string(), true);
|
||||
"sql.updates", "", true);
|
||||
|
||||
if (ret != EXIT_SUCCESS)
|
||||
{
|
||||
|
||||
@@ -60,8 +60,23 @@ void TotemAI::UpdateAI(uint32 /*diff*/)
|
||||
if (me->ToTotem()->GetTotemType() != TOTEM_ACTIVE)
|
||||
return;
|
||||
|
||||
if (!me->IsAlive() || me->IsNonMeleeSpellCast(false))
|
||||
if (!me->IsAlive())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (me->IsNonMeleeSpellCast(false))
|
||||
{
|
||||
if (Unit* victim = ObjectAccessor::GetUnit(*me, i_victimGuid))
|
||||
{
|
||||
if (!victim || !victim->IsAlive())
|
||||
{
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Search spell
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(me->ToTotem()->GetSpell());
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "Formulas.h"
|
||||
#include "GameGraveyard.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "Group.h"
|
||||
#include "GroupMgr.h"
|
||||
#include "MapMgr.h"
|
||||
#include "MiscPackets.h"
|
||||
#include "Object.h"
|
||||
@@ -1151,6 +1151,7 @@ void Battleground::AddOrSetPlayerToCorrectBgGroup(Player* player, TeamId teamId)
|
||||
group = new Group;
|
||||
SetBgRaid(teamId, group);
|
||||
group->Create(player);
|
||||
sGroupMgr->AddGroup(group);
|
||||
}
|
||||
else if (group->IsMember(playerGuid))
|
||||
{
|
||||
|
||||
@@ -12062,6 +12062,8 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
|
||||
{
|
||||
case 4415: // Increased Rejuvenation Healing
|
||||
case 4953:
|
||||
DoneTotal += (*i)->GetAmount() / 5; // 5 ticks of Rejuvenation
|
||||
break;
|
||||
case 3736: // Hateful Totem of the Third Wind / Increased Lesser Healing Wave / LK Arena (4/5/6) Totem of the Third Wind / Savage Totem of the Third Wind
|
||||
DoneTotal += (*i)->GetAmount();
|
||||
break;
|
||||
@@ -16143,9 +16145,13 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
|
||||
{
|
||||
if (SpellModifier* mod = triggeredByAura->GetSpellModifier())
|
||||
{
|
||||
if (mod->op == SPELLMOD_CASTING_TIME && procSpell && (procSpell->GetTriggeredCastFlags() & TRIGGERED_CAST_DIRECTLY) != 0)
|
||||
if (mod->op == SPELLMOD_CASTING_TIME && mod->value < 0 && procSpell)
|
||||
{
|
||||
break;
|
||||
// Skip instant spells
|
||||
if (procSpellInfo->CalcCastTime() <= 0 || (procSpell->GetTriggeredCastFlags() & TRIGGERED_CAST_DIRECTLY) != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
takeCharges = true;
|
||||
|
||||
@@ -4361,6 +4361,24 @@ void SpellMgr::LoadSpellInfoCorrections()
|
||||
spellInfo->AttributesEx3 |= SPELL_ATTR3_ALWAYS_HIT;
|
||||
});
|
||||
|
||||
// Death's Respite
|
||||
ApplySpellFix({ 67731, 68305 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
spellInfo->AttributesEx3 |= SPELL_ATTR3_SUPRESS_TARGET_PROCS;
|
||||
});
|
||||
|
||||
// Wyvern Sting DoT
|
||||
ApplySpellFix({ 24131, 24134, 24135 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ENEMY);
|
||||
});
|
||||
|
||||
// Feed Pet
|
||||
ApplySpellFix({ 1539, 51284 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
spellInfo->Attributes |= SPELL_ATTR0_ALLOW_WHILE_SITTING;
|
||||
});
|
||||
|
||||
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
|
||||
{
|
||||
SpellInfo* spellInfo = mSpellInfoMap[i];
|
||||
|
||||
@@ -126,6 +126,15 @@ struct boss_ayamiss : public BossAI
|
||||
}
|
||||
|
||||
}, 1s);
|
||||
|
||||
_scheduler.Schedule(5s, 8s, [this](TaskContext context) {
|
||||
DoCastVictim(SPELL_LASH);
|
||||
context.Repeat(8s, 15s);
|
||||
}).Schedule(16s, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_THRASH);
|
||||
context.Repeat();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,17 +219,6 @@ struct boss_ayamiss : public BossAI
|
||||
me->SetDisableGravity(false);
|
||||
me->GetMotionMaster()->MovePath(me->GetEntry() * 10, false);
|
||||
DoResetThreat();
|
||||
|
||||
_scheduler.Schedule(5s, 8s, [this](TaskContext context) {
|
||||
DoCastVictim(SPELL_LASH);
|
||||
context.Repeat(8s, 15s);
|
||||
}).Schedule(16s, [this](TaskContext context)
|
||||
{
|
||||
DoCastSelf(SPELL_THRASH);
|
||||
context.Repeat();
|
||||
});
|
||||
|
||||
_scheduler.DelayAll(5s);
|
||||
_scheduler.CancelGroup(PHASE_AIR);
|
||||
}
|
||||
|
||||
@@ -271,6 +269,7 @@ struct npc_hive_zara_larva : public ScriptedAI
|
||||
if (Creature* ayamiss = _instance->GetCreature(DATA_AYAMISS))
|
||||
{
|
||||
ayamiss->AI()->JustSummoned(summon);
|
||||
summon->SetInCombatWithZone();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ struct boss_buru : public BossAI
|
||||
|
||||
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (attacker->GetEntry() == NPC_BURU_EGG)
|
||||
if (attacker && attacker->GetEntry() == NPC_BURU_EGG)
|
||||
{
|
||||
me->LowerPlayerDamageReq(damage);
|
||||
}
|
||||
|
||||
@@ -35,9 +35,12 @@ enum Yells
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_DISARM = 6713,
|
||||
SPELL_FRENZY = 8269,
|
||||
SPELL_THUNDERCRASH = 25599
|
||||
SPELL_DISARM = 6713,
|
||||
SPELL_FRENZY = 8269,
|
||||
SPELL_THUNDERCRASH = 25599,
|
||||
|
||||
// Server-side
|
||||
SPELL_CENARION_REPUTATION = 26342
|
||||
};
|
||||
|
||||
enum Events
|
||||
@@ -51,12 +54,6 @@ struct boss_rajaxx : public BossAI
|
||||
{
|
||||
boss_rajaxx(Creature* creature) : BossAI(creature, DATA_RAJAXX) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
enraged = false;
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
@@ -67,6 +64,26 @@ struct boss_rajaxx : public BossAI
|
||||
andorov->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_VENDOR);
|
||||
andorov->ForceValuesUpdateAtIndex(UNIT_NPC_FLAGS);
|
||||
}
|
||||
|
||||
std::list<Creature*> creatureList;
|
||||
me->GetCreatureListWithEntryInGrid(creatureList, NPC_KALDOREI_ELITE, 200.0f);
|
||||
creatureList.remove_if([&](Creature* creature) -> bool { return !creature->IsAlive(); });
|
||||
|
||||
me->GetMap()->DoForAllPlayers([&, creatureList](Player* player)
|
||||
{
|
||||
for (uint8 i = 0; i < creatureList.size(); ++i)
|
||||
{
|
||||
player->CastSpell(player, SPELL_CENARION_REPUTATION, true);
|
||||
}
|
||||
|
||||
if (Creature* andorov = instance->instance->GetCreature(instance->GetGuidData(DATA_ANDOROV)))
|
||||
{
|
||||
if (andorov->IsAlive())
|
||||
{
|
||||
player->CastSpell(player, SPELL_CENARION_REPUTATION, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*victim*/) override
|
||||
@@ -105,8 +122,6 @@ struct boss_rajaxx : public BossAI
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
private:
|
||||
bool enraged;
|
||||
};
|
||||
|
||||
class spell_rajaxx_thundercrash : public SpellScript
|
||||
@@ -183,7 +198,6 @@ struct npc_general_andorov : public npc_escortAI
|
||||
kaldoreielitist->SetImmuneToNPC(true);
|
||||
kaldoreielitist->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
kaldoreielitist->SetReactState(REACT_PASSIVE);
|
||||
kaldoreielitist->SetFaction(FACTION_ESCORT_H_ACTIVE);
|
||||
CAST_AI(SmartAI, kaldoreielitist->AI())->SetFollow(me, 2.5f, 0.f + i * (M_PI / 2));
|
||||
}
|
||||
}
|
||||
@@ -246,13 +260,16 @@ struct npc_general_andorov : public npc_escortAI
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
_summons.DespawnAll();
|
||||
|
||||
if (Creature* rajaxx = instance->GetCreature(DATA_RAJAXX))
|
||||
if (killer->GetEntry() == NPC_RAJAXX)
|
||||
{
|
||||
rajaxx->AI()->Talk(SAY_KILLS_ANDOROV);
|
||||
if (Creature* rajaxx = instance->GetCreature(DATA_RAJAXX))
|
||||
{
|
||||
rajaxx->AI()->Talk(SAY_KILLS_ANDOROV);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,7 +347,7 @@ struct npc_general_andorov : public npc_escortAI
|
||||
{
|
||||
case EVENT_BASH:
|
||||
DoCastVictim(SPELL_BASH);
|
||||
events.ScheduleEvent(EVENT_BASH, urand(12, 15) * IN_MILLISECONDS);
|
||||
events.ScheduleEvent(EVENT_BASH, urand(25, 38) * IN_MILLISECONDS);
|
||||
break;
|
||||
case EVENT_COMMAND_AURA:
|
||||
DoCastSelf(SPELL_AURA_OF_COMMAND, true);
|
||||
|
||||
@@ -28,22 +28,6 @@ EndScriptData */
|
||||
#include "TaskScheduler.h"
|
||||
#include "temple_of_ahnqiraj.h"
|
||||
|
||||
enum Phases
|
||||
{
|
||||
PHASE_NOT_STARTED = 0,
|
||||
|
||||
// Main Phase 1 - EYE
|
||||
PHASE_EYE_GREEN_BEAM = 1,
|
||||
PHASE_EYE_RED_BEAM = 2,
|
||||
|
||||
// Main Phase 2 - CTHUN
|
||||
PHASE_CTHUN_TRANSITION = 3,
|
||||
PHASE_CTHUN_STOMACH = 4,
|
||||
PHASE_CTHUN_WEAK = 5,
|
||||
|
||||
PHASE_CTHUN_DONE = 6,
|
||||
};
|
||||
|
||||
enum Spells
|
||||
{
|
||||
// ***** Main Phase 1 ********
|
||||
|
||||
@@ -148,8 +148,30 @@ class spell_huhuran_wyvern_sting : public AuraScript
|
||||
}
|
||||
};
|
||||
|
||||
// 26052 - Poison Bolt
|
||||
class spell_huhuran_poison_bolt : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_huhuran_poison_bolt);
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
uint32 const maxTargets = GetSpellInfo()->MaxAffectedTargets;
|
||||
if (targets.size() > maxTargets)
|
||||
{
|
||||
targets.sort(Acore::ObjectDistanceOrderPred(GetCaster()));
|
||||
targets.resize(maxTargets);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_huhuran_poison_bolt::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_huhuran()
|
||||
{
|
||||
RegisterTempleOfAhnQirajCreatureAI(boss_huhuran);
|
||||
RegisterSpellScript(spell_huhuran_wyvern_sting);
|
||||
RegisterSpellScript(spell_huhuran_poison_bolt);
|
||||
}
|
||||
|
||||
@@ -112,6 +112,8 @@ struct boss_skeram : public BossAI
|
||||
{
|
||||
_JustDied();
|
||||
Talk(SAY_DEATH);
|
||||
|
||||
instance->HandleGameObject(instance->GetGuidData(AQ40_DOOR_3), true);
|
||||
}
|
||||
else
|
||||
me->RemoveCorpse();
|
||||
@@ -146,9 +148,7 @@ struct boss_skeram : public BossAI
|
||||
events.ScheduleEvent(EVENT_ARCANE_EXPLOSION, 8s, 18s);
|
||||
break;
|
||||
case EVENT_FULLFILMENT:
|
||||
/// @todo For some weird reason boss does not cast this
|
||||
// Spell actually works, tested in duel
|
||||
DoCast(SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true), SPELL_TRUE_FULFILLMENT, false);
|
||||
DoCast(SelectTarget(SelectTargetMethod::MinDistance, 1, 0.0f, true), SPELL_TRUE_FULFILLMENT, false);
|
||||
events.ScheduleEvent(EVENT_FULLFILMENT, 20s, 30s);
|
||||
break;
|
||||
case EVENT_BLINK:
|
||||
|
||||
@@ -91,6 +91,8 @@ struct boss_twinemperorsAI : public BossAI
|
||||
me->ClearUnitState(UNIT_STATE_STUNNED);
|
||||
DontYellWhenDead = false;
|
||||
EnrageTimer = 15 * 60000;
|
||||
|
||||
instance->HandleGameObject(instance->GetGuidData(AQ40_DOOR_1), true);
|
||||
}
|
||||
|
||||
Creature* GetOtherBoss()
|
||||
@@ -127,6 +129,9 @@ struct boss_twinemperorsAI : public BossAI
|
||||
}
|
||||
if (!DontYellWhenDead) // I hope AI is not threaded
|
||||
DoPlaySoundToSet(me, IAmVeklor() ? SOUND_VL_DEATH : SOUND_VN_DEATH);
|
||||
|
||||
instance->HandleGameObject(instance->GetGuidData(AQ40_DOOR_1), true);
|
||||
instance->HandleGameObject(instance->GetGuidData(AQ40_DOOR_2), true);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
@@ -150,6 +155,8 @@ struct boss_twinemperorsAI : public BossAI
|
||||
otherAI->DoZoneInCombat();
|
||||
}
|
||||
}
|
||||
|
||||
instance->HandleGameObject(instance->GetGuidData(AQ40_DOOR_1), false);
|
||||
}
|
||||
|
||||
void SpellHit(Unit* caster, SpellInfo const* entry) override
|
||||
|
||||
@@ -42,6 +42,7 @@ public:
|
||||
instance_temple_of_ahnqiraj_InstanceMapScript(Map* map) : InstanceScript(map)
|
||||
{
|
||||
LoadObjectData(creatureData, nullptr);
|
||||
doorGUIDs.fill(ObjectGuid::Empty);
|
||||
SetBossNumber(MAX_BOSS_NUMBER);
|
||||
}
|
||||
|
||||
@@ -55,6 +56,10 @@ public:
|
||||
ObjectGuid VeklorGUID;
|
||||
ObjectGuid VeknilashGUID;
|
||||
ObjectGuid ViscidusGUID;
|
||||
ObjectGuid CThunGUID;
|
||||
GuidVector CThunGraspGUIDs;
|
||||
std::array<ObjectGuid, 3> doorGUIDs;
|
||||
|
||||
uint32 BugTrioDeathCount;
|
||||
uint32 CthunPhase;
|
||||
|
||||
@@ -73,6 +78,10 @@ public:
|
||||
{
|
||||
case NPC_SKERAM:
|
||||
SkeramGUID = creature->GetGUID();
|
||||
if (!creature->IsAlive())
|
||||
{
|
||||
HandleGameObject(doorGUIDs[2], true);
|
||||
}
|
||||
break;
|
||||
case NPC_VEM:
|
||||
VemGUID = creature->GetGUID();
|
||||
@@ -85,6 +94,10 @@ public:
|
||||
break;
|
||||
case NPC_VEKLOR:
|
||||
VeklorGUID = creature->GetGUID();
|
||||
if (!creature->IsAlive())
|
||||
{
|
||||
HandleGameObject(doorGUIDs[1], true);
|
||||
}
|
||||
break;
|
||||
case NPC_VEKNILASH:
|
||||
VeknilashGUID = creature->GetGUID();
|
||||
@@ -96,11 +109,70 @@ public:
|
||||
if (GetBossState(DATA_OURO) != DONE)
|
||||
creature->Respawn();
|
||||
break;
|
||||
case NPC_CTHUN:
|
||||
CThunGUID = creature->GetGUID();
|
||||
if (!creature->IsAlive())
|
||||
{
|
||||
for (ObjectGuid const& guid : CThunGraspGUIDs)
|
||||
{
|
||||
if (GameObject* cthunGrasp = instance->GetGameObject(guid))
|
||||
{
|
||||
cthunGrasp->DespawnOrUnsummon(1s);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
InstanceScript::OnCreatureCreate(creature);
|
||||
}
|
||||
|
||||
void OnGameObjectCreate(GameObject* go) override
|
||||
{
|
||||
switch (go->GetEntry())
|
||||
{
|
||||
case AQ40_DOOR_1:
|
||||
doorGUIDs[0] = go->GetGUID();
|
||||
break;
|
||||
case AQ40_DOOR_2:
|
||||
doorGUIDs[1] = go->GetGUID();
|
||||
if (Creature* veklor = instance->GetCreature(VeklorGUID))
|
||||
{
|
||||
if (!veklor->IsAlive())
|
||||
{
|
||||
HandleGameObject(go->GetGUID(), true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AQ40_DOOR_3:
|
||||
doorGUIDs[2] = go->GetGUID();
|
||||
if (Creature* skeram = instance->GetCreature(SkeramGUID))
|
||||
{
|
||||
if (!skeram->IsAlive())
|
||||
{
|
||||
HandleGameObject(go->GetGUID(), true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GO_CTHUN_GRASP:
|
||||
CThunGraspGUIDs.push_back(go->GetGUID());
|
||||
if (Creature* CThun = instance->GetCreature(CThunGUID))
|
||||
{
|
||||
if (!CThun->IsAlive())
|
||||
{
|
||||
go->DespawnOrUnsummon(1s);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
InstanceScript::OnGameObjectCreate(go);
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 type) const override
|
||||
{
|
||||
switch (type)
|
||||
@@ -142,6 +214,12 @@ public:
|
||||
return VeknilashGUID;
|
||||
case DATA_VISCIDUS:
|
||||
return ViscidusGUID;
|
||||
case AQ40_DOOR_1:
|
||||
return doorGUIDs[0];
|
||||
case AQ40_DOOR_2:
|
||||
return doorGUIDs[1];
|
||||
case AQ40_DOOR_3:
|
||||
return doorGUIDs[2];
|
||||
}
|
||||
return ObjectGuid::Empty;
|
||||
}
|
||||
@@ -164,6 +242,16 @@ public:
|
||||
break;
|
||||
case DATA_CTHUN_PHASE:
|
||||
CthunPhase = data;
|
||||
if (data == PHASE_CTHUN_DONE)
|
||||
{
|
||||
for (ObjectGuid const& guid : CThunGraspGUIDs)
|
||||
{
|
||||
if (GameObject* cthunGrasp = instance->GetGameObject(guid))
|
||||
{
|
||||
cthunGrasp->DespawnOrUnsummon(1s);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "temple_of_ahnqiraj.h"
|
||||
#include "TaskScheduler.h"
|
||||
|
||||
@@ -150,7 +151,40 @@ private:
|
||||
bool _enraged;
|
||||
};
|
||||
|
||||
enum NPCs
|
||||
{
|
||||
NPC_VEKNISS_DRONE = 15300
|
||||
};
|
||||
|
||||
class spell_aggro_drones : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_aggro_drones);
|
||||
|
||||
void HandleDummy(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
if (Creature* target = GetHitCreature())
|
||||
{
|
||||
if (target->GetEntry() == NPC_VEKNISS_DRONE)
|
||||
{
|
||||
if (Unit* victim = caster->GetVictim())
|
||||
{
|
||||
target->AI()->AttackStart(victim);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_aggro_drones::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_temple_of_ahnqiraj()
|
||||
{
|
||||
RegisterTempleOfAhnQirajCreatureAI(npc_anubisath_defender);
|
||||
RegisterSpellScript(spell_aggro_drones);
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ enum DataTypes
|
||||
|
||||
enum Creatures
|
||||
{
|
||||
NPC_CTHUN = 15727,
|
||||
NPC_EYE_OF_CTHUN = 15589,
|
||||
NPC_CTHUN_PORTAL = 15896,
|
||||
NPC_CLAW_TENTACLE = 15725,
|
||||
@@ -79,6 +80,30 @@ enum Creatures
|
||||
NPC_SARTURA = 15516
|
||||
};
|
||||
|
||||
enum ObjectsAQ40
|
||||
{
|
||||
AQ40_DOOR_1 = 180634,
|
||||
AQ40_DOOR_2 = 180635,
|
||||
AQ40_DOOR_3 = 180636,
|
||||
GO_CTHUN_GRASP = 180745
|
||||
};
|
||||
|
||||
enum CThunPhases
|
||||
{
|
||||
PHASE_NOT_STARTED = 0,
|
||||
|
||||
// Main Phase 1 - EYE
|
||||
PHASE_EYE_GREEN_BEAM = 1,
|
||||
PHASE_EYE_RED_BEAM = 2,
|
||||
|
||||
// Main Phase 2 - CTHUN
|
||||
PHASE_CTHUN_TRANSITION = 3,
|
||||
PHASE_CTHUN_STOMACH = 4,
|
||||
PHASE_CTHUN_WEAK = 5,
|
||||
|
||||
PHASE_CTHUN_DONE = 6
|
||||
};
|
||||
|
||||
template <class AI, class T>
|
||||
inline AI* GetTempleOfAhnQirajAI(T* obj)
|
||||
{
|
||||
|
||||
@@ -633,6 +633,264 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
enum WintergardeGryphon
|
||||
{
|
||||
SPELL_RESCUE_VILLAGER = 48363,
|
||||
SPELL_DROP_OFF_VILLAGER = 48397,
|
||||
SPELL_RIDE_VEHICLE = 43671,
|
||||
|
||||
NPC_HELPLESS_VILLAGER_A = 27315,
|
||||
NPC_HELPLESS_VILLAGER_B = 27336,
|
||||
|
||||
EVENT_VEHICLE_GET = 1,
|
||||
EVENT_TAKE_OFF = 2,
|
||||
EVENT_GET_VILLAGER = 3,
|
||||
|
||||
EVENT_PHASE_FEAR = 1,
|
||||
EVENT_PHASE_VEHICLE = 2,
|
||||
|
||||
POINT_LAND = 1,
|
||||
POINT_TAKE_OFF = 2,
|
||||
|
||||
QUEST_FLIGHT_OF_THE_WINTERGARDE_DEFENDER = 12237,
|
||||
GO_TEMP_GRYPHON_STATION = 188679,
|
||||
AREA_WINTERGARDE_KEEP = 4177
|
||||
};
|
||||
|
||||
class npc_wintergarde_gryphon : public VehicleAI
|
||||
{
|
||||
public:
|
||||
npc_wintergarde_gryphon(Creature* creature) : VehicleAI(creature)
|
||||
{
|
||||
creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
me->DespawnOrUnsummon(3s, 0s);
|
||||
}
|
||||
|
||||
void IsSummonedBy(Unit* summoner) override
|
||||
{
|
||||
me->SetFacingToObject(summoner);
|
||||
Position pos = summoner->GetPosition();
|
||||
me->GetMotionMaster()->MovePoint(POINT_LAND, pos);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
if (type == POINT_MOTION_TYPE && id == POINT_LAND)
|
||||
events.ScheduleEvent(EVENT_VEHICLE_GET, 0s);
|
||||
}
|
||||
|
||||
void PassengerBoarded(Unit* passenger, int8 seatId, bool apply) override
|
||||
{
|
||||
if (!apply && seatId == 0)
|
||||
{
|
||||
// left the vehicle with a passenger will result in despawn
|
||||
if (Vehicle* gryphon = me->GetVehicleKit())
|
||||
if (Unit* villager = gryphon->GetPassenger(1))
|
||||
{
|
||||
if (villager->GetTypeId() != TYPEID_UNIT)
|
||||
return;
|
||||
|
||||
if (Creature* seat = villager->ToCreature())
|
||||
{
|
||||
seat->ExitVehicle();
|
||||
seat->DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
|
||||
me->RemoveVehicleKit(); // not Crash (;
|
||||
events.ScheduleEvent(EVENT_TAKE_OFF, 2s);
|
||||
me->CastSpell(passenger, VEHICLE_SPELL_PARACHUTE, true);
|
||||
}
|
||||
}
|
||||
|
||||
Creature* getVillager() { return ObjectAccessor::GetCreature(*me, villagerGUID); }
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
events.Update(diff);
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_VEHICLE_GET:
|
||||
{
|
||||
me->SetDisableGravity(false);
|
||||
me->SetHover(false);
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
break;
|
||||
}
|
||||
case EVENT_TAKE_OFF:
|
||||
{
|
||||
me->DespawnOrUnsummon(4050);
|
||||
me->SetOrientation(2.5f);
|
||||
me->SetSpeedRate(MOVE_FLIGHT, 1.0f);
|
||||
Position pos = me->GetPosition();
|
||||
Position offset = { 14.0f, 14.0f, 16.0f, 0.0f };
|
||||
pos.RelocateOffset(offset);
|
||||
me->GetMotionMaster()->MovePoint(POINT_TAKE_OFF, pos);
|
||||
break;
|
||||
}
|
||||
case EVENT_GET_VILLAGER:
|
||||
{
|
||||
if (getVillager())
|
||||
{
|
||||
getVillager()->GetMotionMaster()->MovePoint(0, 3660.0f, -706.4f, 215.0f);
|
||||
getVillager()->DespawnOrUnsummon(7s, 0s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
|
||||
{
|
||||
if (spell->Id != SPELL_DROP_OFF_VILLAGER)
|
||||
return;
|
||||
|
||||
if (Vehicle* gryphon = me->GetVehicleKit())
|
||||
if (Unit* villager = gryphon->GetPassenger(1))
|
||||
{
|
||||
villager->ExitVehicle();
|
||||
villager->GetMotionMaster()->Clear(false);
|
||||
villager->GetMotionMaster()->MoveIdle();
|
||||
villager->SetCanFly(false); // prevents movement in flight
|
||||
villagerGUID = villager->GetGUID();
|
||||
villager->HandleEmoteCommand(EMOTE_ONESHOT_CHEER);
|
||||
events.ScheduleEvent(EVENT_GET_VILLAGER, 3s);
|
||||
}
|
||||
}
|
||||
private:
|
||||
ObjectGuid villagerGUID;
|
||||
};
|
||||
|
||||
class spell_q12237_rescue_villager : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_q12237_rescue_villager);
|
||||
|
||||
SpellCastResult CheckCast()
|
||||
{
|
||||
Player* owner = GetCaster()->GetCharmerOrOwnerPlayerOrPlayerItself();
|
||||
|
||||
if (!owner)
|
||||
return SPELL_FAILED_DONT_REPORT;
|
||||
|
||||
SpellCustomErrors extension = SPELL_CUSTOM_ERROR_NONE;
|
||||
SpellCastResult result = SPELL_CAST_OK;
|
||||
|
||||
if (GetCaster()->GetAreaId() == AREA_WINTERGARDE_KEEP)
|
||||
{
|
||||
extension = SPELL_CUSTOM_ERROR_MUST_BE_NEAR_HELPLESS_VILLAGER;
|
||||
result = SPELL_FAILED_CUSTOM_ERROR;
|
||||
}
|
||||
|
||||
if (!GetCaster()->FindNearestCreature(NPC_HELPLESS_VILLAGER_A, 5.0f) && !GetCaster()->FindNearestCreature(NPC_HELPLESS_VILLAGER_B, 5.0f))
|
||||
{
|
||||
extension = SPELL_CUSTOM_ERROR_MUST_BE_NEAR_HELPLESS_VILLAGER;
|
||||
result = SPELL_FAILED_CUSTOM_ERROR;
|
||||
}
|
||||
|
||||
if (GetCaster()->FindNearestGameObject(GO_TEMP_GRYPHON_STATION, 15.0f))
|
||||
{
|
||||
extension = SPELL_CUSTOM_ERROR_NEED_HELPLESS_VILLAGER;
|
||||
result = SPELL_FAILED_CUSTOM_ERROR;
|
||||
}
|
||||
|
||||
if (GetCaster()->HasAura(SPELL_RIDE_VEHICLE))
|
||||
result = SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW;
|
||||
|
||||
if (result != SPELL_CAST_OK)
|
||||
{
|
||||
Spell::SendCastResult(owner, GetSpellInfo(), 0, result, extension);
|
||||
return result;
|
||||
}
|
||||
|
||||
return SPELL_CAST_OK;
|
||||
}
|
||||
|
||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* target = GetHitUnit())
|
||||
target->CastSpell(GetCaster(), uint32(GetEffectValue()), true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_q12237_rescue_villager::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
OnCheckCast += SpellCheckCastFn(spell_q12237_rescue_villager::CheckCast);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_q12237_drop_off_villager : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_q12237_drop_off_villager);
|
||||
|
||||
SpellCastResult CheckCast()
|
||||
{
|
||||
Player* master = GetCaster()->GetCharmerOrOwnerPlayerOrPlayerItself();
|
||||
|
||||
if (!master)
|
||||
return SPELL_FAILED_DONT_REPORT;
|
||||
|
||||
SpellCustomErrors extension = SPELL_CUSTOM_ERROR_NONE;
|
||||
SpellCastResult result = SPELL_CAST_OK;
|
||||
|
||||
if (!GetCaster()->FindNearestGameObject(GO_TEMP_GRYPHON_STATION, 10.0f))
|
||||
result = SPELL_FAILED_REQUIRES_SPELL_FOCUS;
|
||||
|
||||
if (!GetCaster()->HasAura(SPELL_RIDE_VEHICLE))
|
||||
{
|
||||
extension = SPELL_CUSTOM_ERROR_NO_PASSENGER;
|
||||
result = SPELL_FAILED_CUSTOM_ERROR;
|
||||
}
|
||||
|
||||
if (result != SPELL_CAST_OK)
|
||||
{
|
||||
Spell::SendCastResult(master, GetSpellInfo(), 0, result, extension);
|
||||
return result;
|
||||
}
|
||||
|
||||
return SPELL_CAST_OK;
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnCheckCast += SpellCheckCastFn(spell_q12237_drop_off_villager::CheckCast);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_call_wintergarde_gryphon : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_call_wintergarde_gryphon);
|
||||
|
||||
void SetDest(SpellDestination& dest)
|
||||
{
|
||||
// Adjust effect summon position
|
||||
Position const offset = { 0.0f, 0.0f, 9.0f, 0.0f };
|
||||
dest.RelocateOffset(offset);
|
||||
}
|
||||
|
||||
SpellCastResult CheckRequirement()
|
||||
{
|
||||
if (Player* playerCaster = GetCaster()->ToPlayer())
|
||||
{
|
||||
if (playerCaster->GetQuestStatus(QUEST_FLIGHT_OF_THE_WINTERGARDE_DEFENDER) == QUEST_STATUS_INCOMPLETE)
|
||||
return SPELL_CAST_OK;
|
||||
}
|
||||
return SPELL_FAILED_DONT_REPORT;
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnCheckCast += SpellCheckCastFn(spell_call_wintergarde_gryphon::CheckRequirement);
|
||||
OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_call_wintergarde_gryphon::SetDest, EFFECT_0, TARGET_DEST_CASTER_FRONT);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_heated_battle : public CreatureScript
|
||||
{
|
||||
public:
|
||||
@@ -2009,6 +2267,10 @@ void AddSC_dragonblight()
|
||||
new npc_future_you();
|
||||
new npc_mindless_ghoul();
|
||||
new npc_injured_7th_legion_soldier();
|
||||
RegisterCreatureAI(npc_wintergarde_gryphon);
|
||||
RegisterSpellScript(spell_q12237_rescue_villager);
|
||||
RegisterSpellScript(spell_q12237_drop_off_villager);
|
||||
RegisterSpellScript(spell_call_wintergarde_gryphon);
|
||||
new npc_heated_battle();
|
||||
new spell_q12478_frostmourne_cavern();
|
||||
new spell_q12243_fire_upon_the_waters();
|
||||
|
||||
@@ -1150,6 +1150,27 @@ class spell_dru_berserk : public SpellScript
|
||||
}
|
||||
};
|
||||
|
||||
// 24905 - Moonkin Form (Passive)
|
||||
class spell_dru_moonkin_form_passive_proc : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_dru_moonkin_form_passive_proc);
|
||||
|
||||
bool CheckProc(ProcEventInfo& eventInfo)
|
||||
{
|
||||
if (SpellInfo const* spellInfo = eventInfo.GetSpellInfo())
|
||||
{
|
||||
return !spellInfo->IsAffectingArea();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckProc += AuraCheckProcFn(spell_dru_moonkin_form_passive_proc::CheckProc);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_druid_spell_scripts()
|
||||
{
|
||||
RegisterSpellScript(spell_dru_bear_form_passive);
|
||||
@@ -1185,4 +1206,5 @@ void AddSC_druid_spell_scripts()
|
||||
RegisterSpellScript(spell_dru_typhoon);
|
||||
RegisterSpellScript(spell_dru_t10_restoration_4p_bonus);
|
||||
RegisterSpellScript(spell_dru_wild_growth);
|
||||
RegisterSpellScript(spell_dru_moonkin_form_passive_proc);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user