* Rename InstanceData to InstanceScript
* Rename *mgr to their new names in scripts project * Mass convert all the scripts (NEEDS THOROUGH TESTING, because it was done automatically) Please, report bugs on issue tracker. --HG-- branch : trunk rename : src/server/game/Instances/InstanceData.cpp => src/server/game/Instances/InstanceScript.cpp rename : src/server/game/Instances/InstanceData.h => src/server/game/Instances/InstanceScript.h
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -50,319 +50,323 @@ EndScriptData */
|
||||
#define DATA_CRYSTALS 6
|
||||
|
||||
#define CREATURE_FEL_CRYSTAL 24722
|
||||
|
||||
struct boss_selin_fireheartAI : public ScriptedAI
|
||||
␍class boss_selin_fireheart : public CreatureScript
|
||||
{
|
||||
boss_selin_fireheartAI(Creature* c) : ScriptedAI(c)
|
||||
{
|
||||
pInstance = c->GetInstanceData();
|
||||
public:
|
||||
boss_selin_fireheart() : CreatureScript("boss_selin_fireheart") { }
|
||||
|
||||
Crystals.clear();
|
||||
//GUIDs per instance is static, so we only need to load them once.
|
||||
if (pInstance)
|
||||
CreatureAI* GetAI(Creature* pCreature) const
|
||||
{
|
||||
return new boss_selin_fireheartAI (pCreature);
|
||||
};
|
||||
|
||||
struct boss_selin_fireheartAI : public ScriptedAI
|
||||
{
|
||||
boss_selin_fireheartAI(Creature* c) : ScriptedAI(c)
|
||||
{
|
||||
uint32 size = pInstance->GetData(DATA_FEL_CRYSTAL_SIZE);
|
||||
for (uint8 i = 0; i < size; ++i)
|
||||
pInstance = c->GetInstanceScript();
|
||||
|
||||
Crystals.clear();
|
||||
//GUIDs per instance is static, so we only need to load them once.
|
||||
if (pInstance)
|
||||
{
|
||||
uint64 guid = pInstance->GetData64(DATA_FEL_CRYSTAL);
|
||||
sLog.outDebug("TSCR: Selin: Adding Fel Crystal %u to list", guid);
|
||||
Crystals.push_back(guid);
|
||||
uint32 size = pInstance->GetData(DATA_FEL_CRYSTAL_SIZE);
|
||||
for (uint8 i = 0; i < size; ++i)
|
||||
{
|
||||
uint64 guid = pInstance->GetData64(DATA_FEL_CRYSTAL);
|
||||
sLog.outDebug("TSCR: Selin: Adding Fel Crystal %u to list", guid);
|
||||
Crystals.push_back(guid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ScriptedInstance* pInstance;
|
||||
InstanceScript* pInstance;
|
||||
|
||||
std::list<uint64> Crystals;
|
||||
std::list<uint64> Crystals;
|
||||
|
||||
uint32 DrainLifeTimer;
|
||||
uint32 DrainManaTimer;
|
||||
uint32 FelExplosionTimer;
|
||||
uint32 DrainCrystalTimer;
|
||||
uint32 EmpowerTimer;
|
||||
uint32 DrainLifeTimer;
|
||||
uint32 DrainManaTimer;
|
||||
uint32 FelExplosionTimer;
|
||||
uint32 DrainCrystalTimer;
|
||||
uint32 EmpowerTimer;
|
||||
|
||||
bool IsDraining;
|
||||
bool DrainingCrystal;
|
||||
bool IsDraining;
|
||||
bool DrainingCrystal;
|
||||
|
||||
uint64 CrystalGUID; // This will help us create a pointer to the crystal we are draining. We store GUIDs, never units in case unit is deleted/offline (offline if player of course).
|
||||
uint64 CrystalGUID; // This will help us create a pointer to the crystal we are draining. We store GUIDs, never units in case unit is deleted/offline (offline if player of course).
|
||||
|
||||
void Reset()
|
||||
{
|
||||
if (pInstance)
|
||||
void Reset()
|
||||
{
|
||||
//for (uint8 i = 0; i < CRYSTALS_NUMBER; ++i)
|
||||
if (pInstance)
|
||||
{
|
||||
//for (uint8 i = 0; i < CRYSTALS_NUMBER; ++i)
|
||||
for (std::list<uint64>::const_iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr)
|
||||
{
|
||||
//Unit* pUnit = Unit::GetUnit(*me, FelCrystals[i]);
|
||||
Unit* pUnit = Unit::GetUnit(*me, *itr);
|
||||
if (pUnit)
|
||||
{
|
||||
if (!pUnit->isAlive())
|
||||
CAST_CRE(pUnit)->Respawn(); // Let the core handle setting death state, etc.
|
||||
|
||||
// Only need to set unselectable flag. You can't attack unselectable units so non_attackable flag is not necessary here.
|
||||
pUnit->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
}
|
||||
|
||||
pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR), true);
|
||||
// Open the big encounter door. Close it in Aggro and open it only in JustDied(and here)
|
||||
// Small door opened after event are expected to be closed by default
|
||||
// Set Inst data for encounter
|
||||
pInstance->SetData(DATA_SELIN_EVENT, NOT_STARTED);
|
||||
} else sLog.outError(ERROR_INST_DATA);
|
||||
|
||||
DrainLifeTimer = 3000 + rand()%4000;
|
||||
DrainManaTimer = DrainLifeTimer + 5000;
|
||||
FelExplosionTimer = 2100;
|
||||
DrainCrystalTimer = 10000 + rand()%5000;
|
||||
DrainCrystalTimer = 20000 + rand()%5000;
|
||||
EmpowerTimer = 10000;
|
||||
|
||||
IsDraining = false;
|
||||
DrainingCrystal = false;
|
||||
CrystalGUID = 0;
|
||||
}
|
||||
|
||||
void SelectNearestCrystal()
|
||||
{
|
||||
if (Crystals.empty())
|
||||
return;
|
||||
|
||||
//float ShortestDistance = 0;
|
||||
CrystalGUID = 0;
|
||||
Unit* pCrystal = NULL;
|
||||
Unit* CrystalChosen = NULL;
|
||||
//for (uint8 i = 0; i < CRYSTALS_NUMBER; ++i)
|
||||
for (std::list<uint64>::const_iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr)
|
||||
{
|
||||
//Unit* pUnit = Unit::GetUnit(*me, FelCrystals[i]);
|
||||
Unit* pUnit = Unit::GetUnit(*me, *itr);
|
||||
if (pUnit)
|
||||
pCrystal = NULL;
|
||||
//pCrystal = Unit::GetUnit(*me, FelCrystals[i]);
|
||||
pCrystal = Unit::GetUnit(*me, *itr);
|
||||
if (pCrystal && pCrystal->isAlive())
|
||||
{
|
||||
if (!pUnit->isAlive())
|
||||
CAST_CRE(pUnit)->Respawn(); // Let the core handle setting death state, etc.
|
||||
|
||||
// Only need to set unselectable flag. You can't attack unselectable units so non_attackable flag is not necessary here.
|
||||
pUnit->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
}
|
||||
|
||||
pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR), true);
|
||||
// Open the big encounter door. Close it in Aggro and open it only in JustDied(and here)
|
||||
// Small door opened after event are expected to be closed by default
|
||||
// Set Inst data for encounter
|
||||
pInstance->SetData(DATA_SELIN_EVENT, NOT_STARTED);
|
||||
} else sLog.outError(ERROR_INST_DATA);
|
||||
|
||||
DrainLifeTimer = 3000 + rand()%4000;
|
||||
DrainManaTimer = DrainLifeTimer + 5000;
|
||||
FelExplosionTimer = 2100;
|
||||
DrainCrystalTimer = 10000 + rand()%5000;
|
||||
DrainCrystalTimer = 20000 + rand()%5000;
|
||||
EmpowerTimer = 10000;
|
||||
|
||||
IsDraining = false;
|
||||
DrainingCrystal = false;
|
||||
CrystalGUID = 0;
|
||||
}
|
||||
|
||||
void SelectNearestCrystal()
|
||||
{
|
||||
if (Crystals.empty())
|
||||
return;
|
||||
|
||||
//float ShortestDistance = 0;
|
||||
CrystalGUID = 0;
|
||||
Unit* pCrystal = NULL;
|
||||
Unit* CrystalChosen = NULL;
|
||||
//for (uint8 i = 0; i < CRYSTALS_NUMBER; ++i)
|
||||
for (std::list<uint64>::const_iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr)
|
||||
{
|
||||
pCrystal = NULL;
|
||||
//pCrystal = Unit::GetUnit(*me, FelCrystals[i]);
|
||||
pCrystal = Unit::GetUnit(*me, *itr);
|
||||
if (pCrystal && pCrystal->isAlive())
|
||||
{
|
||||
// select nearest
|
||||
if (!CrystalChosen || me->GetDistanceOrder(pCrystal, CrystalChosen, false))
|
||||
{
|
||||
CrystalGUID = pCrystal->GetGUID();
|
||||
CrystalChosen = pCrystal; // Store a copy of pCrystal so we don't need to recreate a pointer to closest crystal for the movement and yell.
|
||||
}
|
||||
}
|
||||
}
|
||||
if (CrystalChosen)
|
||||
{
|
||||
DoScriptText(SAY_ENERGY, me);
|
||||
DoScriptText(EMOTE_CRYSTAL, me);
|
||||
|
||||
CrystalChosen->CastSpell(CrystalChosen, SPELL_FEL_CRYSTAL_COSMETIC, true);
|
||||
|
||||
float x, y, z; // coords that we move to, close to the crystal.
|
||||
CrystalChosen->GetClosePoint(x, y, z, me->GetObjectSize(), CONTACT_DISTANCE);
|
||||
|
||||
me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
me->GetMotionMaster()->MovePoint(1, x, y, z);
|
||||
DrainingCrystal = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ShatterRemainingCrystals()
|
||||
{
|
||||
if (Crystals.empty())
|
||||
return;
|
||||
|
||||
//for (uint8 i = 0; i < CRYSTALS_NUMBER; ++i)
|
||||
for (std::list<uint64>::const_iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr)
|
||||
{
|
||||
//Creature* pCrystal = (Unit::GetCreature(*me, FelCrystals[i]));
|
||||
Creature* pCrystal = Unit::GetCreature(*me, *itr);
|
||||
if (pCrystal && pCrystal->isAlive())
|
||||
pCrystal->Kill(pCrystal);
|
||||
}
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/)
|
||||
{
|
||||
DoScriptText(SAY_AGGRO, me);
|
||||
|
||||
if (pInstance)
|
||||
pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR), false);
|
||||
//Close the encounter door, open it in JustDied/Reset
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/)
|
||||
{
|
||||
DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id)
|
||||
{
|
||||
if (type == POINT_MOTION_TYPE && id == 1)
|
||||
{
|
||||
Unit* CrystalChosen = Unit::GetUnit(*me, CrystalGUID);
|
||||
if (CrystalChosen && CrystalChosen->isAlive())
|
||||
{
|
||||
// Make the crystal attackable
|
||||
// We also remove NON_ATTACKABLE in case the database has it set.
|
||||
CrystalChosen->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE);
|
||||
CrystalChosen->CastSpell(me, SPELL_MANA_RAGE, true);
|
||||
IsDraining = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make an error message in case something weird happened here
|
||||
sLog.outError("TSCR: Selin Fireheart unable to drain crystal as the crystal is either dead or despawned");
|
||||
DrainingCrystal = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/)
|
||||
{
|
||||
DoScriptText(SAY_DEATH, me);
|
||||
|
||||
if (!pInstance)
|
||||
return;
|
||||
|
||||
pInstance->SetData(DATA_SELIN_EVENT, DONE); // Encounter complete!
|
||||
pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR), true); // Open the encounter door
|
||||
pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_DOOR), true); // Open the door leading further in
|
||||
ShatterRemainingCrystals();
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (!DrainingCrystal)
|
||||
{
|
||||
uint32 maxPowerMana = me->GetMaxPower(POWER_MANA);
|
||||
if (maxPowerMana && ((me->GetPower(POWER_MANA)*100 / maxPowerMana) < 10))
|
||||
{
|
||||
if (DrainLifeTimer <= diff)
|
||||
{
|
||||
DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DRAIN_LIFE);
|
||||
DrainLifeTimer = 10000;
|
||||
} else DrainLifeTimer -= diff;
|
||||
|
||||
// Heroic only
|
||||
if (IsHeroic())
|
||||
{
|
||||
if (DrainManaTimer <= diff)
|
||||
// select nearest
|
||||
if (!CrystalChosen || me->GetDistanceOrder(pCrystal, CrystalChosen, false))
|
||||
{
|
||||
DoCast(SelectUnit(SELECT_TARGET_RANDOM, 1), SPELL_DRAIN_MANA);
|
||||
DrainManaTimer = 10000;
|
||||
} else DrainManaTimer -= diff;
|
||||
}
|
||||
}
|
||||
|
||||
if (FelExplosionTimer <= diff)
|
||||
{
|
||||
if (!me->IsNonMeleeSpellCasted(false))
|
||||
{
|
||||
DoCast(me, SPELL_FEL_EXPLOSION);
|
||||
FelExplosionTimer = 2000;
|
||||
}
|
||||
} else FelExplosionTimer -= diff;
|
||||
|
||||
// If below 10% mana, start recharging
|
||||
maxPowerMana = me->GetMaxPower(POWER_MANA);
|
||||
if (maxPowerMana && ((me->GetPower(POWER_MANA)*100 / maxPowerMana) < 10))
|
||||
{
|
||||
if (DrainCrystalTimer <= diff)
|
||||
{
|
||||
SelectNearestCrystal();
|
||||
if (IsHeroic())
|
||||
DrainCrystalTimer = 10000 + rand()%5000;
|
||||
else
|
||||
DrainCrystalTimer = 20000 + rand()%5000;
|
||||
} else DrainCrystalTimer -= diff;
|
||||
}
|
||||
|
||||
}else
|
||||
{
|
||||
if (IsDraining)
|
||||
{
|
||||
if (EmpowerTimer <= diff)
|
||||
{
|
||||
IsDraining = false;
|
||||
DrainingCrystal = false;
|
||||
|
||||
DoScriptText(SAY_EMPOWERED, me);
|
||||
|
||||
Unit* CrystalChosen = Unit::GetUnit(*me, CrystalGUID);
|
||||
if (CrystalChosen && CrystalChosen->isAlive())
|
||||
// Use Deal Damage to kill it, not setDeathState.
|
||||
CrystalChosen->Kill(CrystalChosen);
|
||||
|
||||
CrystalGUID = 0;
|
||||
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->GetMotionMaster()->MoveChase(me->getVictim());
|
||||
} else EmpowerTimer -= diff;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady(); // No need to check if we are draining crystal here, as the spell has a stun.
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI_boss_selin_fireheart(Creature* pCreature)
|
||||
{
|
||||
return new boss_selin_fireheartAI (pCreature);
|
||||
};
|
||||
|
||||
struct mob_fel_crystalAI : public ScriptedAI
|
||||
{
|
||||
mob_fel_crystalAI(Creature *c) : ScriptedAI(c) {}
|
||||
|
||||
void Reset() {}
|
||||
void EnterCombat(Unit* /*who*/) {}
|
||||
void AttackStart(Unit* /*who*/) {}
|
||||
void MoveInLineOfSight(Unit* /*who*/) {}
|
||||
void UpdateAI(const uint32 /*diff*/) {}
|
||||
|
||||
void JustDied(Unit* /*killer*/)
|
||||
{
|
||||
if (ScriptedInstance* pInstance = me->GetInstanceData())
|
||||
{
|
||||
Creature* Selin = (Unit::GetCreature(*me, pInstance->GetData64(DATA_SELIN)));
|
||||
if (Selin && Selin->isAlive())
|
||||
{
|
||||
if (CAST_AI(boss_selin_fireheartAI, Selin->AI())->CrystalGUID == me->GetGUID())
|
||||
{
|
||||
// Set this to false if we are the Creature that Selin is draining so his AI flows properly
|
||||
CAST_AI(boss_selin_fireheartAI, Selin->AI())->DrainingCrystal = false;
|
||||
CAST_AI(boss_selin_fireheartAI, Selin->AI())->IsDraining = false;
|
||||
CAST_AI(boss_selin_fireheartAI, Selin->AI())->EmpowerTimer = 10000;
|
||||
if (Selin->getVictim())
|
||||
{
|
||||
Selin->AI()->AttackStart(Selin->getVictim());
|
||||
Selin->GetMotionMaster()->MoveChase(Selin->getVictim());
|
||||
CrystalGUID = pCrystal->GetGUID();
|
||||
CrystalChosen = pCrystal; // Store a copy of pCrystal so we don't need to recreate a pointer to closest crystal for the movement and yell.
|
||||
}
|
||||
}
|
||||
}
|
||||
} else sLog.outError(ERROR_INST_DATA);
|
||||
}
|
||||
if (CrystalChosen)
|
||||
{
|
||||
DoScriptText(SAY_ENERGY, me);
|
||||
DoScriptText(EMOTE_CRYSTAL, me);
|
||||
|
||||
CrystalChosen->CastSpell(CrystalChosen, SPELL_FEL_CRYSTAL_COSMETIC, true);
|
||||
|
||||
float x, y, z; // coords that we move to, close to the crystal.
|
||||
CrystalChosen->GetClosePoint(x, y, z, me->GetObjectSize(), CONTACT_DISTANCE);
|
||||
|
||||
me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
me->GetMotionMaster()->MovePoint(1, x, y, z);
|
||||
DrainingCrystal = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ShatterRemainingCrystals()
|
||||
{
|
||||
if (Crystals.empty())
|
||||
return;
|
||||
|
||||
//for (uint8 i = 0; i < CRYSTALS_NUMBER; ++i)
|
||||
for (std::list<uint64>::const_iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr)
|
||||
{
|
||||
//Creature* pCrystal = (Unit::GetCreature(*me, FelCrystals[i]));
|
||||
Creature* pCrystal = Unit::GetCreature(*me, *itr);
|
||||
if (pCrystal && pCrystal->isAlive())
|
||||
pCrystal->Kill(pCrystal);
|
||||
}
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/)
|
||||
{
|
||||
DoScriptText(SAY_AGGRO, me);
|
||||
|
||||
if (pInstance)
|
||||
pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR), false);
|
||||
//Close the encounter door, open it in JustDied/Reset
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/)
|
||||
{
|
||||
DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id)
|
||||
{
|
||||
if (type == POINT_MOTION_TYPE && id == 1)
|
||||
{
|
||||
Unit* CrystalChosen = Unit::GetUnit(*me, CrystalGUID);
|
||||
if (CrystalChosen && CrystalChosen->isAlive())
|
||||
{
|
||||
// Make the crystal attackable
|
||||
// We also remove NON_ATTACKABLE in case the database has it set.
|
||||
CrystalChosen->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE);
|
||||
CrystalChosen->CastSpell(me, SPELL_MANA_RAGE, true);
|
||||
IsDraining = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make an error message in case something weird happened here
|
||||
sLog.outError("TSCR: Selin Fireheart unable to drain crystal as the crystal is either dead or despawned");
|
||||
DrainingCrystal = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/)
|
||||
{
|
||||
DoScriptText(SAY_DEATH, me);
|
||||
|
||||
if (!pInstance)
|
||||
return;
|
||||
|
||||
pInstance->SetData(DATA_SELIN_EVENT, DONE); // Encounter complete!
|
||||
pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR), true); // Open the encounter door
|
||||
pInstance->HandleGameObject(pInstance->GetData64(DATA_SELIN_DOOR), true); // Open the door leading further in
|
||||
ShatterRemainingCrystals();
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (!DrainingCrystal)
|
||||
{
|
||||
uint32 maxPowerMana = me->GetMaxPower(POWER_MANA);
|
||||
if (maxPowerMana && ((me->GetPower(POWER_MANA)*100 / maxPowerMana) < 10))
|
||||
{
|
||||
if (DrainLifeTimer <= diff)
|
||||
{
|
||||
DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DRAIN_LIFE);
|
||||
DrainLifeTimer = 10000;
|
||||
} else DrainLifeTimer -= diff;
|
||||
|
||||
// Heroic only
|
||||
if (IsHeroic())
|
||||
{
|
||||
if (DrainManaTimer <= diff)
|
||||
{
|
||||
DoCast(SelectUnit(SELECT_TARGET_RANDOM, 1), SPELL_DRAIN_MANA);
|
||||
DrainManaTimer = 10000;
|
||||
} else DrainManaTimer -= diff;
|
||||
}
|
||||
}
|
||||
|
||||
if (FelExplosionTimer <= diff)
|
||||
{
|
||||
if (!me->IsNonMeleeSpellCasted(false))
|
||||
{
|
||||
DoCast(me, SPELL_FEL_EXPLOSION);
|
||||
FelExplosionTimer = 2000;
|
||||
}
|
||||
} else FelExplosionTimer -= diff;
|
||||
|
||||
// If below 10% mana, start recharging
|
||||
maxPowerMana = me->GetMaxPower(POWER_MANA);
|
||||
if (maxPowerMana && ((me->GetPower(POWER_MANA)*100 / maxPowerMana) < 10))
|
||||
{
|
||||
if (DrainCrystalTimer <= diff)
|
||||
{
|
||||
SelectNearestCrystal();
|
||||
if (IsHeroic())
|
||||
DrainCrystalTimer = 10000 + rand()%5000;
|
||||
else
|
||||
DrainCrystalTimer = 20000 + rand()%5000;
|
||||
} else DrainCrystalTimer -= diff;
|
||||
}
|
||||
|
||||
}else
|
||||
{
|
||||
if (IsDraining)
|
||||
{
|
||||
if (EmpowerTimer <= diff)
|
||||
{
|
||||
IsDraining = false;
|
||||
DrainingCrystal = false;
|
||||
|
||||
DoScriptText(SAY_EMPOWERED, me);
|
||||
|
||||
Unit* CrystalChosen = Unit::GetUnit(*me, CrystalGUID);
|
||||
if (CrystalChosen && CrystalChosen->isAlive())
|
||||
// Use Deal Damage to kill it, not setDeathState.
|
||||
CrystalChosen->Kill(CrystalChosen);
|
||||
|
||||
CrystalGUID = 0;
|
||||
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->GetMotionMaster()->MoveChase(me->getVictim());
|
||||
} else EmpowerTimer -= diff;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady(); // No need to check if we are draining crystal here, as the spell has a stun.
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
CreatureAI* GetAI_mob_fel_crystal(Creature* pCreature)
|
||||
␍class mob_fel_crystal : public CreatureScript
|
||||
{
|
||||
return new mob_fel_crystalAI (pCreature);
|
||||
public:
|
||||
mob_fel_crystal() : CreatureScript("mob_fel_crystal") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* pCreature) const
|
||||
{
|
||||
return new mob_fel_crystalAI (pCreature);
|
||||
};
|
||||
|
||||
struct mob_fel_crystalAI : public ScriptedAI
|
||||
{
|
||||
mob_fel_crystalAI(Creature *c) : ScriptedAI(c) {}
|
||||
|
||||
void Reset() {}
|
||||
void EnterCombat(Unit* /*who*/) {}
|
||||
void AttackStart(Unit* /*who*/) {}
|
||||
void MoveInLineOfSight(Unit* /*who*/) {}
|
||||
void UpdateAI(const uint32 /*diff*/) {}
|
||||
|
||||
void JustDied(Unit* /*killer*/)
|
||||
{
|
||||
if (InstanceScript* pInstance = me->GetInstanceScript())
|
||||
{
|
||||
Creature* Selin = (Unit::GetCreature(*me, pInstance->GetData64(DATA_SELIN)));
|
||||
if (Selin && Selin->isAlive())
|
||||
{
|
||||
if (CAST_AI(boss_selin_fireheart::boss_selin_fireheartAI, Selin->AI())->CrystalGUID == me->GetGUID())
|
||||
{
|
||||
// Set this to false if we are the Creature that Selin is draining so his AI flows properly
|
||||
CAST_AI(boss_selin_fireheart::boss_selin_fireheartAI, Selin->AI())->DrainingCrystal = false;
|
||||
CAST_AI(boss_selin_fireheart::boss_selin_fireheartAI, Selin->AI())->IsDraining = false;
|
||||
CAST_AI(boss_selin_fireheart::boss_selin_fireheartAI, Selin->AI())->EmpowerTimer = 10000;
|
||||
if (Selin->getVictim())
|
||||
{
|
||||
Selin->AI()->AttackStart(Selin->getVictim());
|
||||
Selin->GetMotionMaster()->MoveChase(Selin->getVictim());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else sLog.outError(ERROR_INST_DATA);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
void AddSC_boss_selin_fireheart()
|
||||
{
|
||||
Script *newscript;
|
||||
|
||||
newscript = new Script;
|
||||
newscript->Name = "boss_selin_fireheart";
|
||||
newscript->GetAI = &GetAI_boss_selin_fireheart;
|
||||
newscript->RegisterSelf();
|
||||
|
||||
newscript = new Script;
|
||||
newscript->Name = "mob_fel_crystal";
|
||||
newscript->GetAI = &GetAI_mob_fel_crystal;
|
||||
newscript->RegisterSelf();
|
||||
new boss_selin_fireheart();
|
||||
new mob_fel_crystal();
|
||||
}
|
||||
|
||||
|
||||
@@ -58,171 +58,176 @@ enum eEnums
|
||||
INTERVAL_MODIFIER = 15,
|
||||
INTERVAL_SWITCH = 6
|
||||
};
|
||||
|
||||
struct boss_vexallusAI : public ScriptedAI
|
||||
␍class boss_vexallus : public CreatureScript
|
||||
{
|
||||
boss_vexallusAI(Creature *c) : ScriptedAI(c)
|
||||
public:
|
||||
boss_vexallus() : CreatureScript("boss_vexallus") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* pCreature) const
|
||||
{
|
||||
pInstance = c->GetInstanceData();
|
||||
}
|
||||
return new boss_vexallusAI (pCreature);
|
||||
};
|
||||
|
||||
ScriptedInstance* pInstance;
|
||||
|
||||
uint32 ChainLightningTimer;
|
||||
uint32 ArcaneShockTimer;
|
||||
uint32 OverloadTimer;
|
||||
uint32 IntervalHealthAmount;
|
||||
bool Enraged;
|
||||
|
||||
void Reset()
|
||||
struct boss_vexallusAI : public ScriptedAI
|
||||
{
|
||||
ChainLightningTimer = 8000;
|
||||
ArcaneShockTimer = 5000;
|
||||
OverloadTimer = 1200;
|
||||
IntervalHealthAmount = 1;
|
||||
Enraged = false;
|
||||
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_VEXALLUS_EVENT, NOT_STARTED);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit * /*victim*/)
|
||||
{
|
||||
DoScriptText(SAY_KILL, me);
|
||||
}
|
||||
|
||||
void JustDied(Unit * /*victim*/)
|
||||
{
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_VEXALLUS_EVENT, DONE);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit * /*who*/)
|
||||
{
|
||||
DoScriptText(SAY_AGGRO, me);
|
||||
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_VEXALLUS_EVENT, IN_PROGRESS);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature *summoned)
|
||||
{
|
||||
if (Unit *temp = SelectUnit(SELECT_TARGET_RANDOM, 0))
|
||||
summoned->GetMotionMaster()->MoveFollow(temp,0,0);
|
||||
|
||||
//spells are SUMMON_TYPE_GUARDIAN, so using setOwner should be ok
|
||||
summoned->CastSpell(summoned,SPELL_ENERGY_BOLT,false,0,0,me->GetGUID());
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (!Enraged)
|
||||
boss_vexallusAI(Creature *c) : ScriptedAI(c)
|
||||
{
|
||||
//used for check, when Vexallus cast adds 85%, 70%, 55%, 40%, 25%
|
||||
if ((me->GetHealth()*100 / me->GetMaxHealth()) <= (100-(INTERVAL_MODIFIER*IntervalHealthAmount)))
|
||||
pInstance = c->GetInstanceScript();
|
||||
}
|
||||
|
||||
InstanceScript* pInstance;
|
||||
|
||||
uint32 ChainLightningTimer;
|
||||
uint32 ArcaneShockTimer;
|
||||
uint32 OverloadTimer;
|
||||
uint32 IntervalHealthAmount;
|
||||
bool Enraged;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
ChainLightningTimer = 8000;
|
||||
ArcaneShockTimer = 5000;
|
||||
OverloadTimer = 1200;
|
||||
IntervalHealthAmount = 1;
|
||||
Enraged = false;
|
||||
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_VEXALLUS_EVENT, NOT_STARTED);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit * /*victim*/)
|
||||
{
|
||||
DoScriptText(SAY_KILL, me);
|
||||
}
|
||||
|
||||
void JustDied(Unit * /*victim*/)
|
||||
{
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_VEXALLUS_EVENT, DONE);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit * /*who*/)
|
||||
{
|
||||
DoScriptText(SAY_AGGRO, me);
|
||||
|
||||
if (pInstance)
|
||||
pInstance->SetData(DATA_VEXALLUS_EVENT, IN_PROGRESS);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature *summoned)
|
||||
{
|
||||
if (Unit *temp = SelectUnit(SELECT_TARGET_RANDOM, 0))
|
||||
summoned->GetMotionMaster()->MoveFollow(temp,0,0);
|
||||
|
||||
//spells are SUMMON_TYPE_GUARDIAN, so using setOwner should be ok
|
||||
summoned->CastSpell(summoned,SPELL_ENERGY_BOLT,false,0,0,me->GetGUID());
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (!Enraged)
|
||||
{
|
||||
//increase amount, unless we're at 10%, then we switch and return
|
||||
if (IntervalHealthAmount == INTERVAL_SWITCH)
|
||||
//used for check, when Vexallus cast adds 85%, 70%, 55%, 40%, 25%
|
||||
if ((me->GetHealth()*100 / me->GetMaxHealth()) <= (100-(INTERVAL_MODIFIER*IntervalHealthAmount)))
|
||||
{
|
||||
Enraged = true;
|
||||
return;
|
||||
}
|
||||
else
|
||||
++IntervalHealthAmount;
|
||||
//increase amount, unless we're at 10%, then we switch and return
|
||||
if (IntervalHealthAmount == INTERVAL_SWITCH)
|
||||
{
|
||||
Enraged = true;
|
||||
return;
|
||||
}
|
||||
else
|
||||
++IntervalHealthAmount;
|
||||
|
||||
DoScriptText(SAY_ENERGY, me);
|
||||
DoScriptText(EMOTE_DISCHARGE_ENERGY, me);
|
||||
DoScriptText(SAY_ENERGY, me);
|
||||
DoScriptText(EMOTE_DISCHARGE_ENERGY, me);
|
||||
|
||||
if (IsHeroic())
|
||||
{
|
||||
DoCast(me, H_SPELL_SUMMON_PURE_ENERGY1, false);
|
||||
DoCast(me, H_SPELL_SUMMON_PURE_ENERGY2, false);
|
||||
}
|
||||
else
|
||||
DoCast(me, SPELL_SUMMON_PURE_ENERGY, false);
|
||||
if (IsHeroic())
|
||||
{
|
||||
DoCast(me, H_SPELL_SUMMON_PURE_ENERGY1, false);
|
||||
DoCast(me, H_SPELL_SUMMON_PURE_ENERGY2, false);
|
||||
}
|
||||
else
|
||||
DoCast(me, SPELL_SUMMON_PURE_ENERGY, false);
|
||||
|
||||
//below are workaround summons, remove when summoning spells w/implicitTarget 73 implemented in the core
|
||||
me->SummonCreature(NPC_PURE_ENERGY, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0);
|
||||
|
||||
if (IsHeroic())
|
||||
//below are workaround summons, remove when summoning spells w/implicitTarget 73 implemented in the core
|
||||
me->SummonCreature(NPC_PURE_ENERGY, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0);
|
||||
|
||||
if (IsHeroic())
|
||||
me->SummonCreature(NPC_PURE_ENERGY, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0);
|
||||
}
|
||||
|
||||
if (ChainLightningTimer <= diff)
|
||||
{
|
||||
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
|
||||
DoCast(pTarget, SPELL_CHAIN_LIGHTNING);
|
||||
|
||||
ChainLightningTimer = 8000;
|
||||
} else ChainLightningTimer -= diff;
|
||||
|
||||
if (ArcaneShockTimer <= diff)
|
||||
{
|
||||
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
|
||||
if (pTarget)
|
||||
DoCast(pTarget, SPELL_ARCANE_SHOCK);
|
||||
|
||||
ArcaneShockTimer = 8000;
|
||||
} else ArcaneShockTimer -= diff;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (OverloadTimer <= diff)
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_OVERLOAD);
|
||||
|
||||
OverloadTimer = 2000;
|
||||
} else OverloadTimer -= diff;
|
||||
}
|
||||
|
||||
if (ChainLightningTimer <= diff)
|
||||
{
|
||||
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
|
||||
DoCast(pTarget, SPELL_CHAIN_LIGHTNING);
|
||||
|
||||
ChainLightningTimer = 8000;
|
||||
} else ChainLightningTimer -= diff;
|
||||
|
||||
if (ArcaneShockTimer <= diff)
|
||||
{
|
||||
if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0))
|
||||
if (pTarget)
|
||||
DoCast(pTarget, SPELL_ARCANE_SHOCK);
|
||||
|
||||
ArcaneShockTimer = 8000;
|
||||
} else ArcaneShockTimer -= diff;
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (OverloadTimer <= diff)
|
||||
{
|
||||
DoCast(me->getVictim(), SPELL_OVERLOAD);
|
||||
};
|
||||
|
||||
OverloadTimer = 2000;
|
||||
} else OverloadTimer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI_boss_vexallus(Creature* pCreature)
|
||||
␍class mob_pure_energy : public CreatureScript
|
||||
{
|
||||
return new boss_vexallusAI (pCreature);
|
||||
};
|
||||
public:
|
||||
mob_pure_energy() : CreatureScript("mob_pure_energy") { }
|
||||
|
||||
struct mob_pure_energyAI : public ScriptedAI
|
||||
{
|
||||
mob_pure_energyAI(Creature *c) : ScriptedAI(c) {}
|
||||
|
||||
void Reset() {}
|
||||
|
||||
void JustDied(Unit* slayer)
|
||||
CreatureAI* GetAI(Creature* pCreature) const
|
||||
{
|
||||
if (Unit *temp = me->GetOwner())
|
||||
return new mob_pure_energyAI (pCreature);
|
||||
};
|
||||
|
||||
struct mob_pure_energyAI : public ScriptedAI
|
||||
{
|
||||
mob_pure_energyAI(Creature *c) : ScriptedAI(c) {}
|
||||
|
||||
void Reset() {}
|
||||
|
||||
void JustDied(Unit* slayer)
|
||||
{
|
||||
if (temp && temp->isAlive())
|
||||
slayer->CastSpell(slayer, SPELL_ENERGY_FEEDBACK, true, 0, 0, temp->GetGUID());
|
||||
if (Unit *temp = me->GetOwner())
|
||||
{
|
||||
if (temp && temp->isAlive())
|
||||
slayer->CastSpell(slayer, SPELL_ENERGY_FEEDBACK, true, 0, 0, temp->GetGUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnterCombat(Unit * /*who*/) {}
|
||||
void MoveInLineOfSight(Unit * /*who*/) {}
|
||||
void AttackStart(Unit * /*who*/) {}
|
||||
void EnterCombat(Unit * /*who*/) {}
|
||||
void MoveInLineOfSight(Unit * /*who*/) {}
|
||||
void AttackStart(Unit * /*who*/) {}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
CreatureAI* GetAI_mob_pure_energy(Creature* pCreature)
|
||||
{
|
||||
return new mob_pure_energyAI (pCreature);
|
||||
};
|
||||
|
||||
void AddSC_boss_vexallus()
|
||||
{
|
||||
Script *newscript;
|
||||
|
||||
newscript = new Script;
|
||||
newscript->Name = "boss_vexallus";
|
||||
newscript->GetAI = &GetAI_boss_vexallus;
|
||||
newscript->RegisterSelf();
|
||||
|
||||
newscript = new Script;
|
||||
newscript->Name = "mob_pure_energy";
|
||||
newscript->GetAI = &GetAI_mob_pure_energy;
|
||||
newscript->RegisterSelf();
|
||||
new boss_vexallus();
|
||||
new mob_pure_energy();
|
||||
}
|
||||
|
||||
+147
-146
@@ -34,174 +34,175 @@ EndScriptData */
|
||||
2 - Priestess Delrissa
|
||||
3 - Kael'thas Sunstrider
|
||||
*/
|
||||
|
||||
struct instance_magisters_terrace : public ScriptedInstance
|
||||
␍class instance_magisters_terrace : public InstanceMapScript
|
||||
{
|
||||
instance_magisters_terrace(Map* pMap) : ScriptedInstance(pMap) {Initialize();}
|
||||
public:
|
||||
instance_magisters_terrace() : InstanceMapScript("instance_magisters_terrace") { }
|
||||
|
||||
uint32 m_auiEncounter[MAX_ENCOUNTER];
|
||||
uint32 DelrissaDeathCount;
|
||||
|
||||
std::list<uint64> FelCrystals;
|
||||
std::list<uint64>::const_iterator CrystalItr;
|
||||
|
||||
uint64 SelinGUID;
|
||||
uint64 DelrissaGUID;
|
||||
uint64 VexallusDoorGUID;
|
||||
uint64 SelinDoorGUID;
|
||||
uint64 SelinEncounterDoorGUID;
|
||||
uint64 DelrissaDoorGUID;
|
||||
uint64 KaelDoorGUID;
|
||||
uint64 KaelStatue[2];
|
||||
|
||||
bool InitializedItr;
|
||||
|
||||
void Initialize()
|
||||
InstanceScript* GetInstanceData_InstanceMapScript(Map* pMap)
|
||||
{
|
||||
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
|
||||
|
||||
FelCrystals.clear();
|
||||
|
||||
DelrissaDeathCount = 0;
|
||||
|
||||
SelinGUID = 0;
|
||||
DelrissaGUID = 0;
|
||||
VexallusDoorGUID = 0;
|
||||
SelinDoorGUID = 0;
|
||||
SelinEncounterDoorGUID = 0;
|
||||
DelrissaDoorGUID = 0;
|
||||
KaelDoorGUID = 0;
|
||||
KaelStatue[0] = 0;
|
||||
KaelStatue[1] = 0;
|
||||
|
||||
InitializedItr = false;
|
||||
return new instance_magisters_terrace_InstanceMapScript(pMap);
|
||||
}
|
||||
|
||||
bool IsEncounterInProgress() const
|
||||
struct instance_magisters_terrace_InstanceMapScript : public InstanceScript
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
|
||||
if (m_auiEncounter[i] == IN_PROGRESS)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
instance_magisters_terrace_InstanceMapScript(Map* pMap) : InstanceScript(pMap) {Initialize();}
|
||||
|
||||
uint32 GetData(uint32 identifier)
|
||||
{
|
||||
switch(identifier)
|
||||
uint32 m_auiEncounter[MAX_ENCOUNTER];
|
||||
uint32 DelrissaDeathCount;
|
||||
|
||||
std::list<uint64> FelCrystals;
|
||||
std::list<uint64>::const_iterator CrystalItr;
|
||||
|
||||
uint64 SelinGUID;
|
||||
uint64 DelrissaGUID;
|
||||
uint64 VexallusDoorGUID;
|
||||
uint64 SelinDoorGUID;
|
||||
uint64 SelinEncounterDoorGUID;
|
||||
uint64 DelrissaDoorGUID;
|
||||
uint64 KaelDoorGUID;
|
||||
uint64 KaelStatue[2];
|
||||
|
||||
bool InitializedItr;
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
case DATA_SELIN_EVENT: return m_auiEncounter[0];
|
||||
case DATA_VEXALLUS_EVENT: return m_auiEncounter[1];
|
||||
case DATA_DELRISSA_EVENT: return m_auiEncounter[2];
|
||||
case DATA_KAELTHAS_EVENT: return m_auiEncounter[3];
|
||||
case DATA_DELRISSA_DEATH_COUNT: return DelrissaDeathCount;
|
||||
case DATA_FEL_CRYSTAL_SIZE: return FelCrystals.size();
|
||||
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
|
||||
|
||||
FelCrystals.clear();
|
||||
|
||||
DelrissaDeathCount = 0;
|
||||
|
||||
SelinGUID = 0;
|
||||
DelrissaGUID = 0;
|
||||
VexallusDoorGUID = 0;
|
||||
SelinDoorGUID = 0;
|
||||
SelinEncounterDoorGUID = 0;
|
||||
DelrissaDoorGUID = 0;
|
||||
KaelDoorGUID = 0;
|
||||
KaelStatue[0] = 0;
|
||||
KaelStatue[1] = 0;
|
||||
|
||||
InitializedItr = false;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SetData(uint32 identifier, uint32 data)
|
||||
{
|
||||
switch(identifier)
|
||||
bool IsEncounterInProgress() const
|
||||
{
|
||||
case DATA_SELIN_EVENT: m_auiEncounter[0] = data; break;
|
||||
case DATA_VEXALLUS_EVENT:
|
||||
if (data == DONE)
|
||||
DoUseDoorOrButton(VexallusDoorGUID);
|
||||
m_auiEncounter[1] = data;
|
||||
break;
|
||||
case DATA_DELRISSA_EVENT:
|
||||
if (data == DONE)
|
||||
DoUseDoorOrButton(DelrissaDoorGUID);
|
||||
if (data == IN_PROGRESS)
|
||||
DelrissaDeathCount = 0;
|
||||
m_auiEncounter[2] = data;
|
||||
break;
|
||||
case DATA_KAELTHAS_EVENT: m_auiEncounter[3] = data; break;
|
||||
|
||||
case DATA_DELRISSA_DEATH_COUNT:
|
||||
if (data == SPECIAL)
|
||||
++DelrissaDeathCount;
|
||||
else
|
||||
DelrissaDeathCount = 0;
|
||||
break;
|
||||
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
|
||||
if (m_auiEncounter[i] == IN_PROGRESS)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* pCreature, bool /*add*/)
|
||||
{
|
||||
switch(pCreature->GetEntry())
|
||||
uint32 GetData(uint32 identifier)
|
||||
{
|
||||
case 24723: SelinGUID = pCreature->GetGUID(); break;
|
||||
case 24560: DelrissaGUID = pCreature->GetGUID(); break;
|
||||
case 24722: FelCrystals.push_back(pCreature->GetGUID()); break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnGameObjectCreate(GameObject* pGo, bool /*add*/)
|
||||
{
|
||||
switch(pGo->GetEntry())
|
||||
{
|
||||
case 187896: VexallusDoorGUID = pGo->GetGUID(); break;
|
||||
//SunwellRaid Gate 02
|
||||
case 187979: SelinDoorGUID = pGo->GetGUID(); break;
|
||||
//Assembly Chamber Door
|
||||
case 188065: SelinEncounterDoorGUID = pGo->GetGUID(); break;
|
||||
case 187770: DelrissaDoorGUID = pGo->GetGUID(); break;
|
||||
case 188064: KaelDoorGUID = pGo->GetGUID(); break;
|
||||
case 188165: KaelStatue[0] = pGo->GetGUID(); break;
|
||||
case 188166: KaelStatue[1] = pGo->GetGUID(); break;
|
||||
}
|
||||
}
|
||||
|
||||
uint64 GetData64(uint32 identifier)
|
||||
{
|
||||
switch(identifier)
|
||||
{
|
||||
case DATA_SELIN: return SelinGUID;
|
||||
case DATA_DELRISSA: return DelrissaGUID;
|
||||
case DATA_VEXALLUS_DOOR: return VexallusDoorGUID;
|
||||
case DATA_SELIN_DOOR: return SelinDoorGUID;
|
||||
case DATA_SELIN_ENCOUNTER_DOOR: return SelinEncounterDoorGUID;
|
||||
case DATA_DELRISSA_DOOR: return DelrissaDoorGUID;
|
||||
case DATA_KAEL_DOOR: return KaelDoorGUID;
|
||||
case DATA_KAEL_STATUE_LEFT: return KaelStatue[0];
|
||||
case DATA_KAEL_STATUE_RIGHT: return KaelStatue[1];
|
||||
|
||||
case DATA_FEL_CRYSTAL:
|
||||
switch(identifier)
|
||||
{
|
||||
if (FelCrystals.empty())
|
||||
{
|
||||
sLog.outError("TSCR: Magisters Terrace: No Fel Crystals loaded in Inst Data");
|
||||
return 0;
|
||||
}
|
||||
case DATA_SELIN_EVENT: return m_auiEncounter[0];
|
||||
case DATA_VEXALLUS_EVENT: return m_auiEncounter[1];
|
||||
case DATA_DELRISSA_EVENT: return m_auiEncounter[2];
|
||||
case DATA_KAELTHAS_EVENT: return m_auiEncounter[3];
|
||||
case DATA_DELRISSA_DEATH_COUNT: return DelrissaDeathCount;
|
||||
case DATA_FEL_CRYSTAL_SIZE: return FelCrystals.size();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!InitializedItr)
|
||||
{
|
||||
CrystalItr = FelCrystals.begin();
|
||||
InitializedItr = true;
|
||||
}
|
||||
void SetData(uint32 identifier, uint32 data)
|
||||
{
|
||||
switch(identifier)
|
||||
{
|
||||
case DATA_SELIN_EVENT: m_auiEncounter[0] = data; break;
|
||||
case DATA_VEXALLUS_EVENT:
|
||||
if (data == DONE)
|
||||
DoUseDoorOrButton(VexallusDoorGUID);
|
||||
m_auiEncounter[1] = data;
|
||||
break;
|
||||
case DATA_DELRISSA_EVENT:
|
||||
if (data == DONE)
|
||||
DoUseDoorOrButton(DelrissaDoorGUID);
|
||||
if (data == IN_PROGRESS)
|
||||
DelrissaDeathCount = 0;
|
||||
m_auiEncounter[2] = data;
|
||||
break;
|
||||
case DATA_KAELTHAS_EVENT: m_auiEncounter[3] = data; break;
|
||||
|
||||
uint64 guid = *CrystalItr;
|
||||
++CrystalItr;
|
||||
return guid;
|
||||
case DATA_DELRISSA_DEATH_COUNT:
|
||||
if (data == SPECIAL)
|
||||
++DelrissaDeathCount;
|
||||
else
|
||||
DelrissaDeathCount = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* pCreature, bool /*add*/)
|
||||
{
|
||||
switch(pCreature->GetEntry())
|
||||
{
|
||||
case 24723: SelinGUID = pCreature->GetGUID(); break;
|
||||
case 24560: DelrissaGUID = pCreature->GetGUID(); break;
|
||||
case 24722: FelCrystals.push_back(pCreature->GetGUID()); break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnGameObjectCreate(GameObject* pGo, bool /*add*/)
|
||||
{
|
||||
switch(pGo->GetEntry())
|
||||
{
|
||||
case 187896: VexallusDoorGUID = pGo->GetGUID(); break;
|
||||
//SunwellRaid Gate 02
|
||||
case 187979: SelinDoorGUID = pGo->GetGUID(); break;
|
||||
//Assembly Chamber Door
|
||||
case 188065: SelinEncounterDoorGUID = pGo->GetGUID(); break;
|
||||
case 187770: DelrissaDoorGUID = pGo->GetGUID(); break;
|
||||
case 188064: KaelDoorGUID = pGo->GetGUID(); break;
|
||||
case 188165: KaelStatue[0] = pGo->GetGUID(); break;
|
||||
case 188166: KaelStatue[1] = pGo->GetGUID(); break;
|
||||
}
|
||||
}
|
||||
|
||||
uint64 GetData64(uint32 identifier)
|
||||
{
|
||||
switch(identifier)
|
||||
{
|
||||
case DATA_SELIN: return SelinGUID;
|
||||
case DATA_DELRISSA: return DelrissaGUID;
|
||||
case DATA_VEXALLUS_DOOR: return VexallusDoorGUID;
|
||||
case DATA_SELIN_DOOR: return SelinDoorGUID;
|
||||
case DATA_SELIN_ENCOUNTER_DOOR: return SelinEncounterDoorGUID;
|
||||
case DATA_DELRISSA_DOOR: return DelrissaDoorGUID;
|
||||
case DATA_KAEL_DOOR: return KaelDoorGUID;
|
||||
case DATA_KAEL_STATUE_LEFT: return KaelStatue[0];
|
||||
case DATA_KAEL_STATUE_RIGHT: return KaelStatue[1];
|
||||
|
||||
case DATA_FEL_CRYSTAL:
|
||||
{
|
||||
if (FelCrystals.empty())
|
||||
{
|
||||
sLog.outError("TSCR: Magisters Terrace: No Fel Crystals loaded in Inst Data");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!InitializedItr)
|
||||
{
|
||||
CrystalItr = FelCrystals.begin();
|
||||
InitializedItr = true;
|
||||
}
|
||||
|
||||
uint64 guid = *CrystalItr;
|
||||
++CrystalItr;
|
||||
return guid;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
InstanceData* GetInstanceData_instance_magisters_terrace(Map* pMap)
|
||||
{
|
||||
return new instance_magisters_terrace(pMap);
|
||||
}
|
||||
|
||||
void AddSC_instance_magisters_terrace()
|
||||
{
|
||||
Script *newscript;
|
||||
|
||||
newscript = new Script;
|
||||
newscript->Name = "instance_magisters_terrace";
|
||||
newscript->GetInstanceData = &GetInstanceData_instance_magisters_terrace;
|
||||
newscript->RegisterSelf();
|
||||
new instance_magisters_terrace();
|
||||
}
|
||||
|
||||
|
||||
@@ -50,127 +50,129 @@ const float afKaelLandPoint[] = {225.045, -276.236, -5.434};
|
||||
#define GOSSIP_ITEM_KAEL_5 "What would Kil'jaeden want with a mortal woman?"
|
||||
|
||||
// This is friendly keal that appear after used Orb.
|
||||
// If we assume DB handle summon, summon appear somewhere outside the platform where Orb is
|
||||
struct npc_kalecgosAI : public ScriptedAI
|
||||
// If we assume DB handle summon, summon appear somewhere outside the platform where Orb is␍class npc_kalecgos : public CreatureScript
|
||||
{
|
||||
npc_kalecgosAI(Creature* pCreature) : ScriptedAI(pCreature) {}
|
||||
public:
|
||||
npc_kalecgos() : CreatureScript("npc_kalecgos") { }
|
||||
|
||||
uint32 m_uiTransformTimer;
|
||||
|
||||
void Reset()
|
||||
bool OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction)
|
||||
{
|
||||
m_uiTransformTimer = 0;
|
||||
|
||||
// we must assume he appear as dragon somewhere outside the platform of orb, and then move directly to here
|
||||
if (me->GetEntry() != NPC_KAEL)
|
||||
me->GetMotionMaster()->MovePoint(POINT_ID_LAND, afKaelLandPoint[0], afKaelLandPoint[1], afKaelLandPoint[2]);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 uiType, uint32 uiPointId)
|
||||
{
|
||||
if (uiType != POINT_MOTION_TYPE)
|
||||
return;
|
||||
|
||||
if (uiPointId == POINT_ID_LAND)
|
||||
m_uiTransformTimer = MINUTE*IN_MILLISECONDS;
|
||||
}
|
||||
|
||||
// some targeting issues with the spell, so use this workaround as temporary solution
|
||||
void DoWorkaroundForQuestCredit()
|
||||
{
|
||||
Map* pMap = me->GetMap();
|
||||
|
||||
if (!pMap || pMap->IsHeroic())
|
||||
return;
|
||||
|
||||
Map::PlayerList const &lList = pMap->GetPlayers();
|
||||
|
||||
if (lList.isEmpty())
|
||||
return;
|
||||
|
||||
SpellEntry const* pSpell = GetSpellStore()->LookupEntry(SPELL_ORB_KILL_CREDIT);
|
||||
|
||||
for (Map::PlayerList::const_iterator i = lList.begin(); i != lList.end(); ++i)
|
||||
switch(uiAction)
|
||||
{
|
||||
if (Player* pPlayer = i->getSource())
|
||||
case GOSSIP_ACTION_INFO_DEF:
|
||||
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
pPlayer->SEND_GOSSIP_MENU(12500, pCreature->GetGUID());
|
||||
break;
|
||||
case GOSSIP_ACTION_INFO_DEF+1:
|
||||
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
|
||||
pPlayer->SEND_GOSSIP_MENU(12502, pCreature->GetGUID());
|
||||
break;
|
||||
case GOSSIP_ACTION_INFO_DEF+2:
|
||||
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
|
||||
pPlayer->SEND_GOSSIP_MENU(12606, pCreature->GetGUID());
|
||||
break;
|
||||
case GOSSIP_ACTION_INFO_DEF+3:
|
||||
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
|
||||
pPlayer->SEND_GOSSIP_MENU(12607, pCreature->GetGUID());
|
||||
break;
|
||||
case GOSSIP_ACTION_INFO_DEF+4:
|
||||
pPlayer->SEND_GOSSIP_MENU(12608, pCreature->GetGUID());
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnGossipHello(Player* pPlayer, Creature* pCreature)
|
||||
{
|
||||
if (pCreature->isQuestGiver())
|
||||
pPlayer->PrepareQuestMenu(pCreature->GetGUID());
|
||||
|
||||
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
|
||||
pPlayer->SEND_GOSSIP_MENU(12498, pCreature->GetGUID());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CreatureAI* GetAI(Creature* pCreature) const
|
||||
{
|
||||
return new npc_kalecgosAI(pCreature);
|
||||
}
|
||||
|
||||
struct npc_kalecgosAI : public ScriptedAI
|
||||
{
|
||||
npc_kalecgosAI(Creature* pCreature) : ScriptedAI(pCreature) {}
|
||||
|
||||
uint32 m_uiTransformTimer;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
m_uiTransformTimer = 0;
|
||||
|
||||
// we must assume he appear as dragon somewhere outside the platform of orb, and then move directly to here
|
||||
if (me->GetEntry() != NPC_KAEL)
|
||||
me->GetMotionMaster()->MovePoint(POINT_ID_LAND, afKaelLandPoint[0], afKaelLandPoint[1], afKaelLandPoint[2]);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 uiType, uint32 uiPointId)
|
||||
{
|
||||
if (uiType != POINT_MOTION_TYPE)
|
||||
return;
|
||||
|
||||
if (uiPointId == POINT_ID_LAND)
|
||||
m_uiTransformTimer = MINUTE*IN_MILLISECONDS;
|
||||
}
|
||||
|
||||
// some targeting issues with the spell, so use this workaround as temporary solution
|
||||
void DoWorkaroundForQuestCredit()
|
||||
{
|
||||
Map* pMap = me->GetMap();
|
||||
|
||||
if (!pMap || pMap->IsHeroic())
|
||||
return;
|
||||
|
||||
Map::PlayerList const &lList = pMap->GetPlayers();
|
||||
|
||||
if (lList.isEmpty())
|
||||
return;
|
||||
|
||||
SpellEntry const* pSpell = GetSpellStore()->LookupEntry(SPELL_ORB_KILL_CREDIT);
|
||||
|
||||
for (Map::PlayerList::const_iterator i = lList.begin(); i != lList.end(); ++i)
|
||||
{
|
||||
if (pSpell && pSpell->EffectMiscValue[0])
|
||||
pPlayer->KilledMonsterCredit(pSpell->EffectMiscValue[0], 0);
|
||||
if (Player* pPlayer = i->getSource())
|
||||
{
|
||||
if (pSpell && pSpell->EffectMiscValue[0])
|
||||
pPlayer->KilledMonsterCredit(pSpell->EffectMiscValue[0], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(const uint32 uiDiff)
|
||||
{
|
||||
if (m_uiTransformTimer)
|
||||
void UpdateAI(const uint32 uiDiff)
|
||||
{
|
||||
if (m_uiTransformTimer <= uiDiff)
|
||||
if (m_uiTransformTimer)
|
||||
{
|
||||
DoCast(me, SPELL_ORB_KILL_CREDIT, false);
|
||||
DoWorkaroundForQuestCredit();
|
||||
if (m_uiTransformTimer <= uiDiff)
|
||||
{
|
||||
DoCast(me, SPELL_ORB_KILL_CREDIT, false);
|
||||
DoWorkaroundForQuestCredit();
|
||||
|
||||
// Transform and update entry, now ready for quest/read gossip
|
||||
DoCast(me, SPELL_TRANSFORM_TO_KAEL, false);
|
||||
me->UpdateEntry(NPC_KAEL);
|
||||
// Transform and update entry, now ready for quest/read gossip
|
||||
DoCast(me, SPELL_TRANSFORM_TO_KAEL, false);
|
||||
me->UpdateEntry(NPC_KAEL);
|
||||
|
||||
m_uiTransformTimer = 0;
|
||||
} else m_uiTransformTimer -= uiDiff;
|
||||
m_uiTransformTimer = 0;
|
||||
} else m_uiTransformTimer -= uiDiff;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
CreatureAI* GetAI_npc_kalecgos(Creature* pCreature)
|
||||
{
|
||||
return new npc_kalecgosAI(pCreature);
|
||||
}
|
||||
|
||||
bool GossipHello_npc_kalecgos(Player* pPlayer, Creature* pCreature)
|
||||
{
|
||||
if (pCreature->isQuestGiver())
|
||||
pPlayer->PrepareQuestMenu(pCreature->GetGUID());
|
||||
|
||||
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
|
||||
pPlayer->SEND_GOSSIP_MENU(12498, pCreature->GetGUID());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GossipSelect_npc_kalecgos(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction)
|
||||
{
|
||||
switch(uiAction)
|
||||
{
|
||||
case GOSSIP_ACTION_INFO_DEF:
|
||||
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
pPlayer->SEND_GOSSIP_MENU(12500, pCreature->GetGUID());
|
||||
break;
|
||||
case GOSSIP_ACTION_INFO_DEF+1:
|
||||
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
|
||||
pPlayer->SEND_GOSSIP_MENU(12502, pCreature->GetGUID());
|
||||
break;
|
||||
case GOSSIP_ACTION_INFO_DEF+2:
|
||||
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
|
||||
pPlayer->SEND_GOSSIP_MENU(12606, pCreature->GetGUID());
|
||||
break;
|
||||
case GOSSIP_ACTION_INFO_DEF+3:
|
||||
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
|
||||
pPlayer->SEND_GOSSIP_MENU(12607, pCreature->GetGUID());
|
||||
break;
|
||||
case GOSSIP_ACTION_INFO_DEF+4:
|
||||
pPlayer->SEND_GOSSIP_MENU(12608, pCreature->GetGUID());
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddSC_magisters_terrace()
|
||||
{
|
||||
Script *newscript;
|
||||
|
||||
newscript = new Script;
|
||||
newscript->Name = "npc_kalecgos";
|
||||
newscript->GetAI = &GetAI_npc_kalecgos;
|
||||
newscript->pGossipHello = &GossipHello_npc_kalecgos;
|
||||
newscript->pGossipSelect = &GossipSelect_npc_kalecgos;
|
||||
newscript->RegisterSelf();
|
||||
new npc_kalecgos();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user