mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-13 09:17:18 +00:00
Merge branch 'azerothcore:master' into Playerbot
This commit is contained in:
@@ -52,13 +52,13 @@ void LoginDatabaseConnection::DoPrepareStatements()
|
||||
PrepareStatement(LOGIN_DEL_EXPIRED_IP_BANS, "DELETE FROM ip_banned WHERE unbandate<>bandate AND unbandate<=UNIX_TIMESTAMP()", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_UPD_EXPIRED_ACCOUNT_BANS, "UPDATE account_banned SET active = 0 WHERE active = 1 AND unbandate<>bandate AND unbandate<=UNIX_TIMESTAMP()", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_SEL_IP_BANNED, "SELECT * FROM ip_banned WHERE ip = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_INS_IP_AUTO_BANNED, "INSERT INTO ip_banned (ip, bandate, unbandate, bannedby, banreason) VALUES (?, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+?, 'Trinity realmd', 'Failed login autoban')", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_INS_IP_AUTO_BANNED, "INSERT INTO ip_banned (ip, bandate, unbandate, bannedby, banreason) VALUES (?, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+?, 'realmd', 'Failed login autoban')", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_SEL_IP_BANNED_ALL, "SELECT ip, bandate, unbandate, bannedby, banreason FROM ip_banned WHERE (bandate = unbandate OR unbandate > UNIX_TIMESTAMP()) ORDER BY unbandate", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_IP_BANNED_BY_IP, "SELECT ip, bandate, unbandate, bannedby, banreason FROM ip_banned WHERE (bandate = unbandate OR unbandate > UNIX_TIMESTAMP()) AND ip LIKE CONCAT('%%', ?, '%%') ORDER BY unbandate", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_BANNED, "SELECT bandate, unbandate FROM account_banned WHERE id = ? AND active = 1", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_BANNED_ALL, "SELECT account.id, username FROM account, account_banned WHERE account.id = account_banned.id AND active = 1 GROUP BY account.id", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_BANNED_BY_USERNAME, "SELECT account.id, username FROM account, account_banned WHERE account.id = account_banned.id AND active = 1 AND username LIKE CONCAT('%%', ?, '%%') GROUP BY account.id", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_INS_ACCOUNT_AUTO_BANNED, "INSERT INTO account_banned VALUES (?, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+?, 'Trinity realmd', 'Failed login autoban', 1)", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_INS_ACCOUNT_AUTO_BANNED, "INSERT INTO account_banned VALUES (?, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+?, 'realmd', 'Failed login autoban', 1)", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_DEL_ACCOUNT_BANNED, "DELETE FROM account_banned WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_UPD_LOGON, "UPDATE account SET salt = ?, verifier = ? WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_UPD_LOGONPROOF, "UPDATE account SET session_key = ?, last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE username = ?", CONNECTION_SYNCH);
|
||||
|
||||
@@ -544,7 +544,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
if (IsUnit(target))
|
||||
{
|
||||
me->GetThreatMgr().ModifyThreatByPercent(target->ToUnit(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC);
|
||||
LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_THREAT_SINGLE_PCT: Creature guidLow {} modify threat for unit {}, value %i",
|
||||
LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_THREAT_SINGLE_PCT: Creature guidLow {} modify threat for unit {}, value {}",
|
||||
me->GetGUID().ToString(), target->GetGUID().ToString(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ void LoadM2Cameras(std::string const& dataPath)
|
||||
// Reject if not at least the size of the header
|
||||
if (static_cast<uint32>(fileSize) < sizeof(M2Header))
|
||||
{
|
||||
LOG_ERROR("server.loading", "Camera file %s is damaged. File is smaller than header size", filename.string().c_str());
|
||||
LOG_ERROR("server.loading", "Camera file {} is damaged. File is smaller than header size", filename.string().c_str());
|
||||
m2file.close();
|
||||
continue;
|
||||
}
|
||||
@@ -220,7 +220,7 @@ void LoadM2Cameras(std::string const& dataPath)
|
||||
// Check file has correct magic (MD20)
|
||||
if (strcmp(fileCheck, "MD20"))
|
||||
{
|
||||
LOG_ERROR("server.loading", "Camera file %s is damaged. File identifier not found", filename.string().c_str());
|
||||
LOG_ERROR("server.loading", "Camera file {} is damaged. File identifier not found", filename.string().c_str());
|
||||
m2file.close();
|
||||
continue;
|
||||
}
|
||||
@@ -240,14 +240,14 @@ void LoadM2Cameras(std::string const& dataPath)
|
||||
|
||||
if (header->ofsCameras + sizeof(M2Camera) > static_cast<uint32>(fileSize))
|
||||
{
|
||||
LOG_ERROR("server.loading", "Camera file %s is damaged. Camera references position beyond file end", filename.string().c_str());
|
||||
LOG_ERROR("server.loading", "Camera file {} is damaged. Camera references position beyond file end", filename.string().c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get camera(s) - Main header, then dump them.
|
||||
M2Camera const* cam = reinterpret_cast<M2Camera const*>(buffer.data() + header->ofsCameras);
|
||||
if (!readCamera(cam, fileSize, header, dbcentry))
|
||||
LOG_ERROR("server.loading", "Camera file %s is damaged. Camera references position beyond file end", filename.string().c_str());
|
||||
LOG_ERROR("server.loading", "Camera file {} is damaged. Camera references position beyond file end", filename.string().c_str());
|
||||
}
|
||||
|
||||
LOG_INFO("server.loading", ">> Loaded {} Cinematic Waypoint Sets in {} ms", (uint32)sFlyByCameraStore.size(), GetMSTimeDiffToNow(oldMSTime));
|
||||
|
||||
@@ -2446,12 +2446,6 @@ 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_IGNORE_ASSISTANCE_CALL = 0x02000000, // Creatures are not aggroed by other mobs assistance functions
|
||||
CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE = 0x02000000, // Prevent creatures from calling for assistance on initial aggro
|
||||
CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI = 0x04000000, // Load both ENTRY and GUID specific SAI
|
||||
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_IGNORE_ASSISTANCE_CALL: return { "CREATURE_FLAG_EXTRA_IGNORE_ASSISTANCE_CALL", "Creatures are not aggroed by other mobs assistance functions", "" };
|
||||
case CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE: return { "CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE", "Creature does not call for assistance on initial aggro", "" };
|
||||
case CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI: return { "CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI", "Creature entry SAI won't be overriden by GUID SAI", "" };
|
||||
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_IGNORE_ASSISTANCE_CALL;
|
||||
case 25: return CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE;
|
||||
case 26: return CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI;
|
||||
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_IGNORE_ASSISTANCE_CALL: return 25;
|
||||
case CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE: return 25;
|
||||
case CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI: return 26;
|
||||
case CREATURE_FLAG_EXTRA_UNUSED_28: return 27;
|
||||
case CREATURE_FLAG_EXTRA_DUNGEON_BOSS: return 28;
|
||||
|
||||
@@ -10385,7 +10385,11 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
|
||||
|
||||
creature->SendAIReaction(AI_REACTION_HOSTILE);
|
||||
|
||||
creature->CallAssistance();
|
||||
/// @todo: Implement aggro range, detection range and assistance range templates
|
||||
if (!(creature->ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE))
|
||||
{
|
||||
creature->CallAssistance();
|
||||
}
|
||||
creature->SetAssistanceTimer(sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_PERIOD));
|
||||
|
||||
SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
|
||||
|
||||
@@ -953,20 +953,20 @@ void WorldSession::HandlePetSpellAutocastOpcode(WorldPackets::Pet::PetSpellAutoc
|
||||
Creature* checkPet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, packet.PetGUID);
|
||||
if (!checkPet)
|
||||
{
|
||||
LOG_ERROR("entities.pet", "WorldSession::HandlePetSpellAutocastOpcode: Pet %s not found.", packet.PetGUID.ToString().c_str());
|
||||
LOG_ERROR("entities.pet", "WorldSession::HandlePetSpellAutocastOpcode: Pet {} not found.", packet.PetGUID.ToString().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(packet.SpellID);
|
||||
if (!spellInfo)
|
||||
{
|
||||
LOG_ERROR("spells.pet", "WorldSession::HandlePetSpellAutocastOpcode: Unknown spell id %u used by %s.", packet.SpellID, packet.PetGUID.ToString().c_str());
|
||||
LOG_ERROR("spells.pet", "WorldSession::HandlePetSpellAutocastOpcode: Unknown spell id {} used by {}.", packet.SpellID, packet.PetGUID.ToString().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (checkPet != _player->GetGuardianPet() && checkPet != _player->GetCharm())
|
||||
{
|
||||
LOG_ERROR("entities.pet", "WorldSession::HandlePetSpellAutocastOpcode: %s isn't pet of player %s (%s).",
|
||||
LOG_ERROR("entities.pet", "WorldSession::HandlePetSpellAutocastOpcode: {} isn't pet of player {} ({}).",
|
||||
packet.PetGUID.ToString().c_str(), GetPlayer()->GetName().c_str(), GetPlayer()->GetGUID().ToString().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -505,7 +505,7 @@ void FlightPathMovementGenerator::PreloadEndGrid()
|
||||
// Load the grid
|
||||
if (endMap)
|
||||
{
|
||||
LOG_DEBUG("misc", "Preloading grid ({}, {}) for map %u at node index {}/{}", _endGridX, _endGridY, _endMapId, _preloadTargetNode, (uint32)(i_path.size() - 1));
|
||||
LOG_DEBUG("misc", "Preloading grid ({}, {}) for map {} at node index {}/{}", _endGridX, _endGridY, _endMapId, _preloadTargetNode, (uint32)(i_path.size() - 1));
|
||||
endMap->LoadGrid(_endGridX, _endGridY);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -782,7 +782,7 @@ bool WorldSession::ValidateHyperlinksAndMaybeKick(std::string_view str)
|
||||
if (Acore::Hyperlinks::CheckAllLinks(str))
|
||||
return true;
|
||||
|
||||
LOG_ERROR("network", "Player {}{} sent a message with an invalid link:\n%.*s", GetPlayer()->GetName(),
|
||||
LOG_ERROR("network", "Player {} {} sent a message with an invalid link:\n%.*s", GetPlayer()->GetName(),
|
||||
GetPlayer()->GetGUID().ToString(), STRING_VIEW_FMT_ARG(str));
|
||||
|
||||
if (sWorld->getIntConfig(CONFIG_CHAT_STRICT_LINK_CHECKING_KICK))
|
||||
|
||||
@@ -56,261 +56,249 @@ float VorpilPosition[3] = {-253.548f, -263.646f, 17.0864f};
|
||||
//x, y, z, and orientation
|
||||
float VoidPortalCoords[5][4] =
|
||||
{
|
||||
{-208.411f, -263.652f, 17.086313f, 3.121870040893554687f}, //portal A 33566
|
||||
{-261.676f, -297.69f, 17.087011f, 1.360249996185302734f}, //portal B 33614
|
||||
{-282.272f, -240.432f, 12.683899f, 5.580170154571533203f}, //portal C 33615
|
||||
{-291.833f, -268.595f, 12.682545f, 0.047733999788761138f}, //portal D 33567
|
||||
{-303.966f, -255.759f, 12.683404f, 6.012829780578613281f} //portal E 33616
|
||||
{-208.411f, -263.652f, 17.086313f, 3.121870040893554687f}, //portal A 33566
|
||||
{-261.676f, -297.69f, 17.087011f, 1.360249996185302734f}, //portal B 33614
|
||||
{-282.272f, -240.432f, 12.683899f, 5.580170154571533203f}, //portal C 33615
|
||||
{-291.833f, -268.595f, 12.682545f, 0.047733999788761138f}, //portal D 33567
|
||||
{-303.966f, -255.759f, 12.683404f, 6.012829780578613281f} //portal E 33616
|
||||
};
|
||||
|
||||
class boss_grandmaster_vorpil : public CreatureScript
|
||||
struct boss_grandmaster_vorpil : public BossAI
|
||||
{
|
||||
public:
|
||||
boss_grandmaster_vorpil() : CreatureScript("boss_grandmaster_vorpil") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
boss_grandmaster_vorpil(Creature* creature) : BossAI(creature, DATA_GRANDMASTER_VORPIL)
|
||||
{
|
||||
return GetShadowLabyrinthAI<boss_grandmaster_vorpilAI>(creature);
|
||||
instance = creature->GetInstanceScript();
|
||||
sayIntro = false;
|
||||
}
|
||||
|
||||
struct boss_grandmaster_vorpilAI : public ScriptedAI
|
||||
InstanceScript* instance;
|
||||
bool sayIntro, sayHelp;
|
||||
int count = 0;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
boss_grandmaster_vorpilAI(Creature* creature) : ScriptedAI(creature), summons(me)
|
||||
sayHelp = false;
|
||||
events.Reset();
|
||||
summons.DespawnAll();
|
||||
if (instance)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
sayIntro = false;
|
||||
instance->SetData(DATA_GRANDMASTER_VORPIL_EVENT, NOT_STARTED);
|
||||
}
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
EventMap events;
|
||||
SummonList summons;
|
||||
|
||||
bool sayIntro, sayHelp;
|
||||
|
||||
int count = 0;
|
||||
|
||||
void Reset() override
|
||||
void summonPortals()
|
||||
{
|
||||
for (uint8 i = 0; i < 5; ++i)
|
||||
{
|
||||
sayHelp = false;
|
||||
events.Reset();
|
||||
summons.DespawnAll();
|
||||
|
||||
if (instance)
|
||||
instance->SetData(DATA_GRANDMASTERVORPILEVENT, NOT_STARTED);
|
||||
me->SummonCreature(NPC_VOID_PORTAL, VoidPortalCoords[i][0], VoidPortalCoords[i][1], VoidPortalCoords[i][2], VoidPortalCoords[i][3], TEMPSUMMON_CORPSE_DESPAWN, 3000000);
|
||||
}
|
||||
}
|
||||
|
||||
void summonPortals()
|
||||
void spawnVoidTraveler()
|
||||
{
|
||||
uint8 pos = urand(0, 4);
|
||||
me->SummonCreature(NPC_VOID_TRAVELER, VoidPortalCoords[pos][0], VoidPortalCoords[pos][1], VoidPortalCoords[pos][2], VoidPortalCoords[pos][3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000);
|
||||
if (!sayHelp)
|
||||
{
|
||||
for (uint8 i = 0; i < 5; ++i)
|
||||
me->SummonCreature(NPC_VOID_PORTAL, VoidPortalCoords[i][0], VoidPortalCoords[i][1], VoidPortalCoords[i][2], VoidPortalCoords[i][3], TEMPSUMMON_CORPSE_DESPAWN, 3000000);
|
||||
Talk(SAY_HELP);
|
||||
sayHelp = true;
|
||||
}
|
||||
}
|
||||
|
||||
void spawnVoidTraveler()
|
||||
int counterVoidSpawns(int count)
|
||||
{
|
||||
int timer = 0;
|
||||
switch(count)
|
||||
{
|
||||
uint8 pos = urand(0, 4);
|
||||
me->SummonCreature(NPC_VOID_TRAVELER, VoidPortalCoords[pos][0], VoidPortalCoords[pos][1], VoidPortalCoords[pos][2], VoidPortalCoords[pos][3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000);
|
||||
if (!sayHelp)
|
||||
{
|
||||
Talk(SAY_HELP);
|
||||
sayHelp = true;
|
||||
}
|
||||
case 1:
|
||||
case 2:
|
||||
timer = 13300;
|
||||
break;
|
||||
case 3:
|
||||
timer = 12100;
|
||||
break;
|
||||
case 4:
|
||||
timer = 10900;
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
timer = 9700;
|
||||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
timer = 7200;
|
||||
break;
|
||||
case 9:
|
||||
timer = 6000;
|
||||
break;
|
||||
default:
|
||||
timer = 4800;
|
||||
}
|
||||
return timer;
|
||||
}
|
||||
|
||||
int counterVoidSpawns(int count)
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
summons.Summon(summon);
|
||||
if (summon->GetEntry() == NPC_VOID_TRAVELER)
|
||||
{
|
||||
int timer = 0;
|
||||
switch(count)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
timer = 13300;
|
||||
break;
|
||||
case 3:
|
||||
timer = 12100;
|
||||
break;
|
||||
case 4:
|
||||
timer = 10900;
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
timer = 9700;
|
||||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
timer = 7200;
|
||||
break;
|
||||
case 9:
|
||||
timer = 6000;
|
||||
break;
|
||||
default:
|
||||
timer = 4800;
|
||||
}
|
||||
return timer;
|
||||
summon->AI()->SetGUID(me->GetGUID());
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
else if (summon->GetEntry() == NPC_VOID_PORTAL)
|
||||
{
|
||||
summons.Summon(summon);
|
||||
if (summon->GetEntry() == NPC_VOID_TRAVELER)
|
||||
summon->AI()->SetGUID(me->GetGUID());
|
||||
else if (summon->GetEntry() == NPC_VOID_PORTAL)
|
||||
summon->CastSpell(summon, SPELL_VOID_PORTAL_VISUAL, false);
|
||||
summon->CastSpell(summon, SPELL_VOID_PORTAL_VISUAL, false);
|
||||
}
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_SLAY);
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
summons.DespawnAll();
|
||||
if (instance)
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
summons.DespawnAll();
|
||||
|
||||
if (instance)
|
||||
instance->SetData(DATA_GRANDMASTERVORPILEVENT, DONE);
|
||||
instance->SetData(DATA_GRANDMASTER_VORPIL_EVENT, DONE);
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
summonPortals();
|
||||
events.ScheduleEvent(EVENT_SPELL_SHADOWBOLT, urand(9700, 20000));
|
||||
events.ScheduleEvent(EVENT_SPELL_DRAWSHADOWS, 36400);
|
||||
events.ScheduleEvent(EVENT_SUMMON_TRAVELER, 10900);
|
||||
if (IsHeroic())
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
summonPortals();
|
||||
|
||||
events.ScheduleEvent(EVENT_SPELL_SHADOWBOLT, urand(9700, 20000));
|
||||
events.ScheduleEvent(EVENT_SPELL_DRAWSHADOWS, 36400);
|
||||
events.ScheduleEvent(EVENT_SUMMON_TRAVELER, 10900);
|
||||
if (IsHeroic())
|
||||
{
|
||||
events.ScheduleEvent(EVENT_SPELL_BANISH, urand(17000, 28000));
|
||||
}
|
||||
if (instance)
|
||||
{
|
||||
instance->SetData(DATA_GRANDMASTERVORPILEVENT, IN_PROGRESS);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_SPELL_BANISH, urand(17000, 28000));
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
if (instance)
|
||||
{
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
|
||||
if (!sayIntro && who->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
Talk(SAY_INTRO);
|
||||
sayIntro = true;
|
||||
}
|
||||
instance->SetData(DATA_GRANDMASTER_VORPIL_EVENT, IN_PROGRESS);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
if (!sayIntro && who->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
Talk(SAY_INTRO);
|
||||
sayIntro = true;
|
||||
}
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SPELL_SHADOWBOLT:
|
||||
me->CastSpell(me, SPELL_SHADOWBOLT_VOLLEY, false);
|
||||
events.RepeatEvent(urand(9700, 20000));
|
||||
break;
|
||||
case EVENT_SPELL_BANISH:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 30, false))
|
||||
me->CastSpell(target, SPELL_BANISH, false);
|
||||
events.RepeatEvent(urand(17000, 28000));
|
||||
break;
|
||||
case EVENT_SUMMON_TRAVELER:
|
||||
spawnVoidTraveler();
|
||||
count++;
|
||||
events.RepeatEvent(counterVoidSpawns(count));
|
||||
break;
|
||||
case EVENT_SPELL_DRAWSHADOWS:
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
switch (events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SPELL_SHADOWBOLT:
|
||||
DoCastAOE(SPELL_SHADOWBOLT_VOLLEY);
|
||||
events.RepeatEvent(urand(9700, 20000));
|
||||
break;
|
||||
case EVENT_SPELL_BANISH:
|
||||
DoCastRandomTarget(SPELL_BANISH, 0, 30.0f, true);
|
||||
events.RepeatEvent(urand(17000, 28000));
|
||||
break;
|
||||
case EVENT_SUMMON_TRAVELER:
|
||||
spawnVoidTraveler();
|
||||
count++;
|
||||
events.RepeatEvent(counterVoidSpawns(count));
|
||||
break;
|
||||
case EVENT_SPELL_DRAWSHADOWS:
|
||||
{
|
||||
DoCastSelf(SPELL_DRAW_SHADOWS, true);
|
||||
Map* map = me->GetMap();
|
||||
Map::PlayerList const& PlayerList = map->GetPlayers();
|
||||
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
|
||||
{
|
||||
me->CastSpell(me, SPELL_DRAW_SHADOWS, true);
|
||||
Map* map = me->GetMap();
|
||||
Map::PlayerList const& PlayerList = map->GetPlayers();
|
||||
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
|
||||
if (Player* player = i->GetSource())
|
||||
if (player->IsAlive() && !player->HasAura(SPELL_BANISH))
|
||||
player->TeleportTo(me->GetMapId(), VorpilPosition[0], VorpilPosition[1], VorpilPosition[2], 0, TELE_TO_NOT_LEAVE_COMBAT);
|
||||
|
||||
me->NearTeleportTo(VorpilPosition[0], VorpilPosition[1], VorpilPosition[2], 0.0f);
|
||||
events.ScheduleEvent(EVENT_SPELL_RAIN_OF_FIRE, 1000);
|
||||
events.RepeatEvent(urand(36400, 44950));
|
||||
break;
|
||||
if (Player* player = i->GetSource())
|
||||
{
|
||||
if (player->IsAlive() && !player->HasAura(SPELL_BANISH))
|
||||
{
|
||||
player->TeleportTo(me->GetMapId(), VorpilPosition[0], VorpilPosition[1], VorpilPosition[2], 0, TELE_TO_NOT_LEAVE_COMBAT);
|
||||
}
|
||||
}
|
||||
}
|
||||
case EVENT_SPELL_RAIN_OF_FIRE:
|
||||
me->CastSpell(me, DUNGEON_MODE(SPELL_RAIN_OF_FIRE_N, SPELL_RAIN_OF_FIRE_H));
|
||||
events.DelayEvents(6000);
|
||||
me->NearTeleportTo(VorpilPosition[0], VorpilPosition[1], VorpilPosition[2], 0.0f);
|
||||
events.ScheduleEvent(EVENT_SPELL_RAIN_OF_FIRE, 1000);
|
||||
events.RepeatEvent(urand(36400, 44950));
|
||||
break;
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
case EVENT_SPELL_RAIN_OF_FIRE:
|
||||
DoCastSelf(DUNGEON_MODE(SPELL_RAIN_OF_FIRE_N, SPELL_RAIN_OF_FIRE_H));
|
||||
events.DelayEvents(6000);
|
||||
break;
|
||||
}
|
||||
};
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
class npc_voidtraveler : public CreatureScript
|
||||
struct npc_voidtraveler : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
npc_voidtraveler() : CreatureScript("npc_voidtraveler") { }
|
||||
npc_voidtraveler(Creature* creature) : ScriptedAI(creature) {}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
ObjectGuid VorpilGUID;
|
||||
uint32 moveTimer;
|
||||
bool sacrificed;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
return GetShadowLabyrinthAI<npc_voidtravelerAI>(creature);
|
||||
moveTimer = 1000;
|
||||
sacrificed = false;
|
||||
}
|
||||
|
||||
struct npc_voidtravelerAI : public ScriptedAI
|
||||
void SetGUID(ObjectGuid guid, int32) override
|
||||
{
|
||||
npc_voidtravelerAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
moveTimer = 1000;
|
||||
sacrificed = false;
|
||||
}
|
||||
VorpilGUID = guid;
|
||||
}
|
||||
|
||||
ObjectGuid VorpilGUID;
|
||||
uint32 moveTimer;
|
||||
bool sacrificed;
|
||||
|
||||
void SetGUID(ObjectGuid guid, int32) override
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
moveTimer += diff;
|
||||
if (moveTimer >= 1000)
|
||||
{
|
||||
VorpilGUID = guid;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
moveTimer += diff;
|
||||
if (moveTimer >= 1000)
|
||||
moveTimer = 0;
|
||||
Creature* Vorpil = ObjectAccessor::GetCreature(*me, VorpilGUID);
|
||||
if (!Vorpil)
|
||||
{
|
||||
moveTimer = 0;
|
||||
Creature* Vorpil = ObjectAccessor::GetCreature(*me, VorpilGUID);
|
||||
if (!Vorpil)
|
||||
{
|
||||
me->DespawnOrUnsummon();
|
||||
return;
|
||||
}
|
||||
me->GetMotionMaster()->MoveFollow(Vorpil, 0.0f, 0.0f);
|
||||
me->DespawnOrUnsummon();
|
||||
return;
|
||||
}
|
||||
me->GetMotionMaster()->MoveFollow(Vorpil, 0.0f, 0.0f);
|
||||
|
||||
if (sacrificed)
|
||||
{
|
||||
me->AddAura(DUNGEON_MODE(SPELL_EMPOWERING_SHADOWS_N, SPELL_EMPOWERING_SHADOWS_H), Vorpil);
|
||||
Vorpil->ModifyHealth(int32(Vorpil->CountPctFromMaxHealth(4)));
|
||||
me->CastSpell(me, SPELL_SHADOW_NOVA, true);
|
||||
me->KillSelf();
|
||||
return;
|
||||
}
|
||||
if (sacrificed)
|
||||
{
|
||||
Vorpil->AddAura(DUNGEON_MODE(SPELL_EMPOWERING_SHADOWS_N, SPELL_EMPOWERING_SHADOWS_H), Vorpil);
|
||||
Vorpil->ModifyHealth(int32(Vorpil->CountPctFromMaxHealth(4)));
|
||||
DoCastAOE(SPELL_SHADOW_NOVA, true);
|
||||
me->KillSelf();
|
||||
return;
|
||||
}
|
||||
|
||||
if (me->IsWithinDist(Vorpil, 3.0f))
|
||||
{
|
||||
me->CastSpell(me, SPELL_SACRIFICE, false);
|
||||
sacrificed = true;
|
||||
moveTimer = 500;
|
||||
}
|
||||
if (me->IsWithinDist(Vorpil, 3.0f))
|
||||
{
|
||||
DoCastSelf(SPELL_SACRIFICE);
|
||||
sacrificed = true;
|
||||
moveTimer = 500;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_grandmaster_vorpil()
|
||||
{
|
||||
new boss_grandmaster_vorpil();
|
||||
new npc_voidtraveler();
|
||||
RegisterShadowLabyrinthCreatureAI(boss_grandmaster_vorpil);
|
||||
RegisterShadowLabyrinthCreatureAI(npc_voidtraveler);
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
break;
|
||||
case SCREAMING_HALL_DOOR:
|
||||
m_uiScreamingHallDoorGUID = go->GetGUID();
|
||||
if (m_auiEncounter[DATA_GRANDMASTERVORPILEVENT] == DONE)
|
||||
if (m_auiEncounter[DATA_GRANDMASTER_VORPIL_EVENT] == DONE)
|
||||
go->SetGoState(GO_STATE_ACTIVE);
|
||||
break;
|
||||
}
|
||||
@@ -116,7 +116,7 @@ public:
|
||||
m_auiEncounter[type] = uiData;
|
||||
break;
|
||||
|
||||
case DATA_GRANDMASTERVORPILEVENT:
|
||||
case DATA_GRANDMASTER_VORPIL_EVENT:
|
||||
if (uiData == DONE)
|
||||
DoUseDoorOrButton(m_uiScreamingHallDoorGUID);
|
||||
m_auiEncounter[type] = uiData;
|
||||
|
||||
@@ -30,10 +30,11 @@ enum slData
|
||||
TYPE_RITUALISTS = 0,
|
||||
TYPE_HELLMAW = 1,
|
||||
DATA_BLACKHEARTTHEINCITEREVENT = 2,
|
||||
DATA_GRANDMASTERVORPILEVENT = 3,
|
||||
DATA_MURMUR = 4,
|
||||
DATA_MURMUREVENT = 5,
|
||||
MAX_ENCOUNTER = 6
|
||||
DATA_GRANDMASTER_VORPIL = 3,
|
||||
DATA_GRANDMASTER_VORPIL_EVENT = 4,
|
||||
DATA_MURMUR = 5,
|
||||
DATA_MURMUREVENT = 6,
|
||||
MAX_ENCOUNTER = 7
|
||||
};
|
||||
|
||||
enum slNPCandGO
|
||||
|
||||
@@ -625,19 +625,19 @@ class spell_item_feast : public SpellScript
|
||||
{
|
||||
case SPELL_GREAT_FEAST:
|
||||
if (BroadcastText const* bct = sObjectMgr->GetBroadcastText(GREAT_FEAST_BROADCAST_TEXT_ID_PREPARE))
|
||||
player->TextEmote(bct->GetText(loc_idx, player->getGender()).c_str(), player);
|
||||
player->TextEmote(bct->GetText(loc_idx, player->getGender()), player);
|
||||
break;
|
||||
case SPELL_FISH_FEAST:
|
||||
if (BroadcastText const* bct = sObjectMgr->GetBroadcastText(FISH_FEAST_BROADCAST_TEXT_ID_PREPARE))
|
||||
player->TextEmote(bct->GetText(loc_idx, player->getGender()).c_str(), player);
|
||||
player->TextEmote(bct->GetText(loc_idx, player->getGender()), player);
|
||||
break;
|
||||
case SPELL_SMALL_FEAST:
|
||||
if (BroadcastText const* bct = sObjectMgr->GetBroadcastText(SMALL_FEAST_BROADCAST_TEXT_ID_PREPARE))
|
||||
player->TextEmote(bct->GetText(loc_idx, player->getGender()).c_str(), player);
|
||||
player->TextEmote(bct->GetText(loc_idx, player->getGender()), player);
|
||||
break;
|
||||
case SPELL_GIGANTIC_FEAST:
|
||||
if (BroadcastText const* bct = sObjectMgr->GetBroadcastText(GIGANTIC_FEAST_BROADCAST_TEXT_ID_PREPARE))
|
||||
player->TextEmote(bct->GetText(loc_idx, player->getGender()).c_str(), player);
|
||||
player->TextEmote(bct->GetText(loc_idx, player->getGender()), player);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user