Merge remote-tracking branch 'acore/master' into test-staging
This commit is contained in:
@@ -612,6 +612,15 @@ AllowLoggingIPAddressesInDatabase = 1
|
||||
|
||||
Allow.IP.Based.Action.Logging = 0
|
||||
|
||||
#
|
||||
# LogSpamReports
|
||||
# Description: Allow logging spam reports from players in the chat, mail or calendar into the database.
|
||||
# Default: 1 - (Enabled)
|
||||
# 0 - (Disabled)
|
||||
#
|
||||
|
||||
LogSpamReports = 1
|
||||
|
||||
#
|
||||
# Appender config values: Given an appender "name"
|
||||
# Appender.name
|
||||
|
||||
@@ -353,6 +353,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
||||
PrepareStatement(CHAR_UPD_REM_AT_LOGIN_FLAG, "UPDATE characters set at_login = at_login & ~ ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_ALL_AT_LOGIN_FLAGS, "UPDATE characters SET at_login = at_login | ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_BUG_REPORT, "INSERT INTO bugreport (type, content) VALUES(?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_SPAM_REPORT, "INSERT INTO spam_reports (SpamType, SpammerGuid, Unk1, MailIdOrMessageType, ChannelId, SecondsSinceMessage, Description, Time) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_PETITION_NAME, "UPDATE petition SET name = ? WHERE petition_id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_PETITION_SIGNATURE, "INSERT INTO petition_sign (ownerguid, petition_id, playerguid, player_account) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_ACCOUNT_ONLINE, "UPDATE characters SET online = 0 WHERE account = ?", CONNECTION_ASYNC);
|
||||
|
||||
@@ -277,6 +277,7 @@ enum CharacterDatabaseStatements : uint32
|
||||
CHAR_UPD_REM_AT_LOGIN_FLAG,
|
||||
CHAR_UPD_ALL_AT_LOGIN_FLAGS,
|
||||
CHAR_INS_BUG_REPORT,
|
||||
CHAR_INS_SPAM_REPORT,
|
||||
CHAR_UPD_PETITION_NAME,
|
||||
CHAR_INS_PETITION_SIGNATURE,
|
||||
CHAR_UPD_ACCOUNT_ONLINE,
|
||||
|
||||
@@ -23,8 +23,9 @@ PossessedAI::PossessedAI(Creature* c) : CreatureAI(c) { me->SetReactState(REACT_
|
||||
NullCreatureAI::NullCreatureAI(Creature* c) : CreatureAI(c)
|
||||
{
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
// TODO: Remove once WorldObject casting is ported (triggers won't create combat refs from spell casts)
|
||||
me->SetIsCombatDisallowed(true);
|
||||
// TODO: Remove once WorldObject spell casting is ported (triggers won't create combat refs from spell casts)
|
||||
if (me->IsTrigger())
|
||||
me->SetIsCombatDisallowed(true);
|
||||
}
|
||||
|
||||
int32 NullCreatureAI::Permissible(Creature const* creature)
|
||||
|
||||
@@ -44,6 +44,7 @@ SmartAI::SmartAI(Creature* c) : CreatureAI(c)
|
||||
mCanRepeatPath = false;
|
||||
|
||||
mEvadeDisabled = false;
|
||||
mSuppressEvade = false;
|
||||
|
||||
mCanAutoAttack = true;
|
||||
|
||||
@@ -698,6 +699,9 @@ void SmartAI::MovementInform(uint32 MovementType, uint32 Data)
|
||||
|
||||
void SmartAI::EnterEvadeMode(EvadeReason /*why*/)
|
||||
{
|
||||
if (mSuppressEvade)
|
||||
return;
|
||||
|
||||
if (mEvadeDisabled)
|
||||
{
|
||||
GetScript()->ProcessEventsFor(SMART_EVENT_EVADE);
|
||||
|
||||
@@ -181,6 +181,7 @@ public:
|
||||
void SetSwim(bool swim = true);
|
||||
|
||||
void SetEvadeDisabled(bool disable = true);
|
||||
void SetSuppressEvade(bool suppress) { mSuppressEvade = suppress; }
|
||||
|
||||
void SetInvincibilityHpLevel(uint32 level) { mInvincibilityHpLevel = level; }
|
||||
|
||||
@@ -249,6 +250,7 @@ private:
|
||||
uint32 GetWPCount() { return mWayPoints ? mWayPoints->Nodes.size() : 0; }
|
||||
bool mCanRepeatPath;
|
||||
bool mEvadeDisabled;
|
||||
bool mSuppressEvade;
|
||||
bool mCanAutoAttack;
|
||||
bool mForcedPaused;
|
||||
uint32 mInvincibilityHpLevel;
|
||||
|
||||
@@ -1039,7 +1039,16 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
if (!me)
|
||||
break;
|
||||
|
||||
// Suppress evade during script-initiated combat stop so
|
||||
// JustExitedCombat does not trigger EnterEvadeMode.
|
||||
if (SmartAI* sai = CAST_AI(SmartAI, me->AI()))
|
||||
sai->SetSuppressEvade(true);
|
||||
|
||||
me->CombatStop(true);
|
||||
|
||||
if (SmartAI* sai = CAST_AI(SmartAI, me->AI()))
|
||||
sai->SetSuppressEvade(false);
|
||||
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_CALL_GROUPEVENTHAPPENS:
|
||||
|
||||
@@ -745,6 +745,13 @@ void BattlegroundIC::HandleContestedNodes(ICNodePoint* nodePoint)
|
||||
(*itr)->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
}
|
||||
else if (nodePoint->nodeType == NODE_TYPE_REFINERY || nodePoint->nodeType == NODE_TYPE_QUARRY)
|
||||
{
|
||||
// nodePoint->faction is the assaulting team (set before this call);
|
||||
// remove the siege damage buff from the team that previously controlled the node.
|
||||
uint32 auraSpellId = (nodePoint->nodeType == NODE_TYPE_REFINERY) ? SPELL_OIL_REFINERY : SPELL_QUARRY;
|
||||
RemoveAuraOnTeam(auraSpellId, GetOtherTeamId(nodePoint->faction));
|
||||
}
|
||||
else if (nodePoint->nodeType == NODE_TYPE_WORKSHOP)
|
||||
{
|
||||
DelObject(BG_IC_GO_SEAFORIUM_BOMBS_1);
|
||||
|
||||
@@ -663,6 +663,8 @@ bool Creature::UpdateEntry(uint32 Entry, const CreatureData* data, bool changele
|
||||
ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true);
|
||||
}
|
||||
|
||||
SetIsCombatDisallowed(cInfo->HasFlagsExtra(CREATURE_FLAG_EXTRA_CANNOT_ENTER_COMBAT));
|
||||
|
||||
SetDetectionDistance(cInfo->detection_range);
|
||||
|
||||
// Update movement
|
||||
|
||||
@@ -56,7 +56,7 @@ enum CreatureFlagsExtra : uint32
|
||||
CREATURE_FLAG_EXTRA_GHOST_VISIBILITY = 0x00000400, // creature will only be visible to dead players
|
||||
CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK = 0x00000800, // creature will use offhand attacks
|
||||
CREATURE_FLAG_EXTRA_NO_SELL_VENDOR = 0x00001000, // players can't sell items to this vendor
|
||||
CREATURE_FLAG_EXTRA_IGNORE_COMBAT = 0x00002000,
|
||||
CREATURE_FLAG_EXTRA_CANNOT_ENTER_COMBAT = 0x00002000, // creature is not allowed to enter combat
|
||||
CREATURE_FLAG_EXTRA_WORLDEVENT = 0x00004000, // custom flag for world event creatures (left room for merging)
|
||||
CREATURE_FLAG_EXTRA_GUARD = 0x00008000, // Creature is guard
|
||||
CREATURE_FLAG_EXTRA_IGNORE_FEIGN_DEATH = 0x00010000, // creature ignores feign death
|
||||
|
||||
@@ -44,7 +44,7 @@ AC_API_EXPORT EnumText EnumUtils<CreatureFlagsExtra>::ToString(CreatureFlagsExtr
|
||||
case CREATURE_FLAG_EXTRA_GHOST_VISIBILITY: return { "CREATURE_FLAG_EXTRA_GHOST_VISIBILITY", "CREATURE_FLAG_EXTRA_GHOST_VISIBILITY", "creature will only be visible to dead players" };
|
||||
case CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK: return { "CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK", "CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK", "/ @todo: Implement CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK (creature will use offhand attacks)" };
|
||||
case CREATURE_FLAG_EXTRA_NO_SELL_VENDOR: return { "CREATURE_FLAG_EXTRA_NO_SELL_VENDOR", "CREATURE_FLAG_EXTRA_NO_SELL_VENDOR", "players can't sell items to this vendor" };
|
||||
case CREATURE_FLAG_EXTRA_IGNORE_COMBAT: return { "CREATURE_FLAG_EXTRA_IGNORE_COMBAT", "CREATURE_FLAG_EXTRA_IGNORE_COMBAT", "" };
|
||||
case CREATURE_FLAG_EXTRA_CANNOT_ENTER_COMBAT: return { "CREATURE_FLAG_EXTRA_CANNOT_ENTER_COMBAT", "CREATURE_FLAG_EXTRA_CANNOT_ENTER_COMBAT", "creature is not allowed to enter combat" };
|
||||
case CREATURE_FLAG_EXTRA_WORLDEVENT: return { "CREATURE_FLAG_EXTRA_WORLDEVENT", "CREATURE_FLAG_EXTRA_WORLDEVENT", "custom flag for world event creatures (left room for merging)" };
|
||||
case CREATURE_FLAG_EXTRA_GUARD: return { "CREATURE_FLAG_EXTRA_GUARD", "CREATURE_FLAG_EXTRA_GUARD", "Creature is guard" };
|
||||
case CREATURE_FLAG_EXTRA_IGNORE_FEIGN_DEATH: return { "CREATURE_FLAG_EXTRA_IGNORE_FEIGN_DEATH", "CREATURE_FLAG_EXTRA_IGNORE_FEIGN_DEATH", "creature ignores feign death" };
|
||||
@@ -88,7 +88,7 @@ AC_API_EXPORT CreatureFlagsExtra EnumUtils<CreatureFlagsExtra>::FromIndex(std::s
|
||||
case 10: return CREATURE_FLAG_EXTRA_GHOST_VISIBILITY;
|
||||
case 11: return CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK;
|
||||
case 12: return CREATURE_FLAG_EXTRA_NO_SELL_VENDOR;
|
||||
case 13: return CREATURE_FLAG_EXTRA_IGNORE_COMBAT;
|
||||
case 13: return CREATURE_FLAG_EXTRA_CANNOT_ENTER_COMBAT;
|
||||
case 14: return CREATURE_FLAG_EXTRA_WORLDEVENT;
|
||||
case 15: return CREATURE_FLAG_EXTRA_GUARD;
|
||||
case 16: return CREATURE_FLAG_EXTRA_IGNORE_FEIGN_DEATH;
|
||||
@@ -129,7 +129,7 @@ AC_API_EXPORT std::size_t EnumUtils<CreatureFlagsExtra>::ToIndex(CreatureFlagsEx
|
||||
case CREATURE_FLAG_EXTRA_GHOST_VISIBILITY: return 10;
|
||||
case CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK: return 11;
|
||||
case CREATURE_FLAG_EXTRA_NO_SELL_VENDOR: return 12;
|
||||
case CREATURE_FLAG_EXTRA_IGNORE_COMBAT: return 13;
|
||||
case CREATURE_FLAG_EXTRA_CANNOT_ENTER_COMBAT: return 13;
|
||||
case CREATURE_FLAG_EXTRA_WORLDEVENT: return 14;
|
||||
case CREATURE_FLAG_EXTRA_GUARD: return 15;
|
||||
case CREATURE_FLAG_EXTRA_IGNORE_FEIGN_DEATH: return 16;
|
||||
|
||||
@@ -13049,7 +13049,7 @@ PartyResult Player::CanUninviteFromGroup(ObjectGuid targetPlayerGUID) const
|
||||
if (state == lfg::LFG_STATE_FINISHED_DUNGEON)
|
||||
return ERR_PARTY_LFG_BOOT_DUNGEON_COMPLETE;
|
||||
|
||||
if (grp->isRollLootActive())
|
||||
if (grp->isRollLootActive() && ObjectAccessor::FindConnectedPlayer(targetPlayerGUID))
|
||||
return ERR_PARTY_LFG_BOOT_LOOT_ROLLS;
|
||||
|
||||
/// @todo: Should also be sent when anyone has recently left combat, with an aprox ~5 seconds timer.
|
||||
|
||||
@@ -5697,6 +5697,9 @@ void Unit::RemoveAllAurasExceptType(AuraType type)
|
||||
// Xinef: We should not remove passive auras on evade, if npc has player owner (scripted one cast auras)
|
||||
void Unit::RemoveEvadeAuras()
|
||||
{
|
||||
if (IsCharmedOwnedByPlayerOrPlayer())
|
||||
return;
|
||||
|
||||
for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();)
|
||||
{
|
||||
Aura const* aura = iter->second->GetBase();
|
||||
@@ -6768,7 +6771,7 @@ void Unit::ProcSkillsAndAuras(Unit* actor, Unit* victim, uint32 procAttacker, ui
|
||||
}
|
||||
else if (healInfo && healInfo->GetHeal())
|
||||
spellTypeMask = PROC_SPELL_TYPE_HEAL;
|
||||
else if (damageInfo && damageInfo->GetDamage())
|
||||
else if (damageInfo && (damageInfo->GetDamage() || damageInfo->GetAbsorb()))
|
||||
spellTypeMask = PROC_SPELL_TYPE_DAMAGE;
|
||||
else if (procSpellInfo)
|
||||
spellTypeMask = PROC_SPELL_TYPE_NO_DMG_HEAL;
|
||||
|
||||
@@ -607,35 +607,7 @@ bool Group::RemoveMember(ObjectGuid guid, const RemoveMethod& method /*= GROUP_R
|
||||
}
|
||||
|
||||
// Remove player from loot rolls
|
||||
for (Rolls::iterator it = RollId.begin(); it != RollId.end();)
|
||||
{
|
||||
Roll* roll = *it;
|
||||
Roll::PlayerVote::iterator itr2 = roll->playerVote.find(guid);
|
||||
if (itr2 == roll->playerVote.end())
|
||||
{
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (itr2->second == GREED || itr2->second == DISENCHANT)
|
||||
--roll->totalGreed;
|
||||
else if (itr2->second == NEED)
|
||||
--roll->totalNeed;
|
||||
else if (itr2->second == PASS)
|
||||
--roll->totalPass;
|
||||
|
||||
if (itr2->second != NOT_VALID)
|
||||
--roll->totalPlayersRolling;
|
||||
|
||||
roll->playerVote.erase(itr2);
|
||||
|
||||
// Xinef: itr can be erased inside
|
||||
// Xinef: player is removed from all vote lists so it will not pass above playerVote == playerVote.end statement during second iteration
|
||||
if (CountRollVote(guid, roll->itemGUID, MAX_ROLL_TYPE))
|
||||
it = RollId.begin();
|
||||
else
|
||||
++it;
|
||||
}
|
||||
RemovePlayerFromRolls(guid);
|
||||
|
||||
// Update subgroups
|
||||
member_witerator slot = _getMemberWSlot(guid);
|
||||
@@ -1429,6 +1401,37 @@ void Group::EndRoll(Loot* pLoot, Map* allowedMap)
|
||||
}
|
||||
}
|
||||
|
||||
void Group::RemovePlayerFromRolls(ObjectGuid guid)
|
||||
{
|
||||
for (Rolls::iterator it = RollId.begin(); it != RollId.end();)
|
||||
{
|
||||
Roll* roll = *it;
|
||||
Roll::PlayerVote::iterator itr2 = roll->playerVote.find(guid);
|
||||
if (itr2 == roll->playerVote.end())
|
||||
{
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (itr2->second == GREED || itr2->second == DISENCHANT)
|
||||
--roll->totalGreed;
|
||||
else if (itr2->second == NEED)
|
||||
--roll->totalNeed;
|
||||
else if (itr2->second == PASS)
|
||||
--roll->totalPass;
|
||||
|
||||
if (itr2->second != NOT_VALID)
|
||||
--roll->totalPlayersRolling;
|
||||
|
||||
roll->playerVote.erase(itr2);
|
||||
|
||||
if (CountRollVote(guid, roll->itemGUID, MAX_ROLL_TYPE))
|
||||
it = RollId.begin();
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void Group::CountTheRoll(Rolls::iterator rollI, Map* allowedMap)
|
||||
{
|
||||
Roll* roll = *rollI;
|
||||
|
||||
@@ -302,6 +302,7 @@ public:
|
||||
void CountTheRoll(Rolls::iterator roll, Map* allowedMap);
|
||||
bool CountRollVote(ObjectGuid playerGUID, ObjectGuid Guid, uint8 Choise);
|
||||
void EndRoll(Loot* loot, Map* allowedMap);
|
||||
void RemovePlayerFromRolls(ObjectGuid guid);
|
||||
|
||||
Rolls GetRolls() const { return RollId; }
|
||||
|
||||
|
||||
@@ -754,11 +754,21 @@ void WorldSession::HandleCalendarEventModeratorStatus(WorldPacket& recvData)
|
||||
|
||||
void WorldSession::HandleCalendarComplain(WorldPackets::Calendar::CalendarComplain& packet)
|
||||
{
|
||||
ObjectGuid guid = _player->GetGUID();
|
||||
if (sWorld->getBoolConfig(CONFIG_LOGSPAMREPORTS))
|
||||
{
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_SPAM_REPORT);
|
||||
|
||||
LOG_DEBUG("network", "CMSG_CALENDAR_COMPLAIN [{}] EventId [{}] guid [{}]", guid.ToString(), packet.EventId, packet.ComplainGuid.ToString());
|
||||
stmt->SetData(0, 2); // SpamType 2 = Calendar
|
||||
stmt->SetData(1, packet.ComplainGuid.GetCounter());
|
||||
stmt->SetData(2, 0);
|
||||
stmt->SetData(3, 0);
|
||||
stmt->SetData(4, 0);
|
||||
stmt->SetData(5, 0);
|
||||
stmt->SetData(6, "EventId: " + std::to_string(packet.EventId));
|
||||
stmt->SetData(7, GameTime::GetGameTime().count());
|
||||
|
||||
// what to do with complains?
|
||||
CharacterDatabase.Execute(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleCalendarGetNumPending(WorldPacket& /*recvData*/)
|
||||
|
||||
@@ -1157,8 +1157,21 @@ void WorldSession::HandleComplainOpcode(WorldPackets::Misc::Complain& packet)
|
||||
// Complaint Received message
|
||||
SendPacket(WorldPackets::Misc::ComplainResult().Write());
|
||||
|
||||
LOG_DEBUG("network", "REPORT SPAM: type {}, {}, unk1 {}, unk2 {}, unk3 {}, unk4 {}, message {}",
|
||||
packet.SpamType, packet.SpammerGuid.ToString(), packet.Unk1, packet.Unk2, packet.Unk3, packet.Unk4, packet.Description);
|
||||
if (sWorld->getBoolConfig(CONFIG_LOGSPAMREPORTS))
|
||||
{
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_SPAM_REPORT);
|
||||
|
||||
stmt->SetData(0, packet.SpamType);
|
||||
stmt->SetData(1, packet.SpammerGuid.GetCounter());
|
||||
stmt->SetData(2, packet.Unk1);
|
||||
stmt->SetData(3, packet.MailIdOrMessageType);
|
||||
stmt->SetData(4, packet.ChannelId);
|
||||
stmt->SetData(5, packet.SecondsSinceMessage);
|
||||
stmt->SetData(6, packet.Description);
|
||||
stmt->SetData(7, GameTime::GetGameTime().count());
|
||||
|
||||
CharacterDatabase.Execute(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleRealmSplitOpcode(WorldPacket& recv_data)
|
||||
|
||||
@@ -142,6 +142,8 @@ bool WorldSession::SendLearnNewTaxiNode(Creature* unit)
|
||||
update << uint8(1);
|
||||
SendPacket(&update);
|
||||
|
||||
sScriptMgr->OnPlayerLearnTaxiNode(GetPlayer(), curloc);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@@ -154,6 +156,8 @@ void WorldSession::SendDiscoverNewTaxiNode(uint32 nodeid)
|
||||
{
|
||||
WorldPacket msg(SMSG_NEW_TAXI_PATH, 0);
|
||||
SendPacket(&msg);
|
||||
|
||||
sScriptMgr->OnPlayerLearnTaxiNode(GetPlayer(), nodeid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -405,10 +405,10 @@ LootItem::LootItem(LootStoreItem const& li)
|
||||
randomSuffix = GenerateEnchSuffixFactor(itemid);
|
||||
randomPropertyId = Item::GenerateItemRandomPropertyId(itemid);
|
||||
count = 0;
|
||||
is_looted = 0;
|
||||
is_blocked = 0;
|
||||
is_underthreshold = 0;
|
||||
is_counted = 0;
|
||||
is_looted = false;
|
||||
is_blocked = false;
|
||||
is_underthreshold = false;
|
||||
is_counted = false;
|
||||
rollWinnerGUID = ObjectGuid::Empty;
|
||||
groupid = li.groupid;
|
||||
}
|
||||
|
||||
@@ -1445,6 +1445,10 @@ enum AcoreStrings
|
||||
LANG_DEBUG_FACTIONCHANGE_GOLD_FAIL = 30122,
|
||||
LANG_DEBUG_FACTIONCHANGE_GOLD_OK = 30123,
|
||||
LANG_DEBUG_FACTIONCHANGE_GOLD_NOLIMIT = 30124,
|
||||
LANG_DEBUG_FACTIONCHANGE_NA = 30125
|
||||
LANG_DEBUG_FACTIONCHANGE_NA = 30125,
|
||||
|
||||
// Achievement commands
|
||||
LANG_ACHIEVEMENT_ADD_ONLINE = 30126,
|
||||
LANG_ACHIEVEMENT_ADD_OFFLINE = 30127
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -367,6 +367,7 @@ bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* creature, uint32 di
|
||||
creature->StopMoving();
|
||||
_lastSplineId = 0;
|
||||
_smoothSplineLaunched = false;
|
||||
_hasBeenStalled = true;
|
||||
}
|
||||
|
||||
// Set home position to current position.
|
||||
|
||||
@@ -931,6 +931,11 @@ void ScriptMgr::OnPlayerGetReputationPriceDiscount(Player const* player, Faction
|
||||
CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_GET_REPUTATION_PRICE_DISCOUNT, script->OnPlayerGetReputationPriceDiscount(player, factionTemplate, discount));
|
||||
}
|
||||
|
||||
void ScriptMgr::OnPlayerLearnTaxiNode(Player const* player, uint32 nodeId)
|
||||
{
|
||||
CALL_ENABLED_HOOKS(PlayerScript, PLAYERHOOK_ON_LEARN_TAXI_NODE, script->OnPlayerLearnTaxiNode(player, nodeId));
|
||||
}
|
||||
|
||||
PlayerScript::PlayerScript(const char* name, std::vector<uint16> enabledHooks)
|
||||
: ScriptObject(name, PLAYERHOOK_END)
|
||||
{
|
||||
|
||||
@@ -216,6 +216,7 @@ enum PlayerHook
|
||||
PLAYERHOOK_ON_SEND_LIST_INVENTORY,
|
||||
PLAYERHOOK_ON_GIVE_REPUTATION,
|
||||
PLAYERHOOK_ON_GET_REPUTATION_PRICE_DISCOUNT,
|
||||
PLAYERHOOK_ON_LEARN_TAXI_NODE,
|
||||
PLAYERHOOK_END
|
||||
};
|
||||
|
||||
@@ -827,6 +828,14 @@ public:
|
||||
* @param discount Float value of the discount, as a multiplier of the base price
|
||||
*/
|
||||
virtual void OnPlayerGetReputationPriceDiscount(Player const* /*player*/, FactionTemplateEntry const* /*factionTemplate*/, float& /*discount*/) {}
|
||||
|
||||
/**
|
||||
* @brief This hook is called when a player learns a new flight path node.
|
||||
*
|
||||
* @param player Contains information about the Player
|
||||
* @param nodeId The id of the learned taxi node
|
||||
*/
|
||||
virtual void OnPlayerLearnTaxiNode(Player const* /*player*/, uint32 /*nodeId*/) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -487,6 +487,7 @@ public: /* PlayerScript */
|
||||
void OnPlayerSendListInventory(Player* player, ObjectGuid vendorGuid, uint32& vendorEntry);
|
||||
void OnPlayerGetReputationPriceDiscount(Player const* player, Creature const* creature, float& discount);
|
||||
void OnPlayerGetReputationPriceDiscount(Player const* player, FactionTemplateEntry const* factionTemplate, float& discount);
|
||||
void OnPlayerLearnTaxiNode(Player const* player, uint32 nodeId);
|
||||
|
||||
// Anti cheat
|
||||
void AnticheatSetCanFlybyServer(Player* player, bool apply);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "CalendarPackets.h"
|
||||
#include "Packet.h"
|
||||
|
||||
void WorldPackets::Calendar::GetEvent::Read()
|
||||
{
|
||||
|
||||
@@ -149,14 +149,14 @@ void WorldPackets::Misc::Complain::Read()
|
||||
{
|
||||
case 0:
|
||||
_worldPacket >> Unk1; // const 0
|
||||
_worldPacket >> Unk2; // probably mail id
|
||||
_worldPacket >> Unk3; // const 0
|
||||
_worldPacket >> MailIdOrMessageType; // probably mail id
|
||||
_worldPacket >> ChannelId; // const 0
|
||||
break;
|
||||
case 1:
|
||||
_worldPacket >> Unk1; // probably language
|
||||
_worldPacket >> Unk2; // message type?
|
||||
_worldPacket >> Unk3; // probably channel id
|
||||
_worldPacket >> Unk4; // unk random value
|
||||
_worldPacket >> MailIdOrMessageType;
|
||||
_worldPacket >> ChannelId;
|
||||
_worldPacket >> SecondsSinceMessage;
|
||||
_worldPacket >> Description; // spam description string (messagetype, channel name, player name, message)
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -218,13 +218,13 @@ namespace WorldPackets
|
||||
|
||||
void Read() override;
|
||||
|
||||
uint8 SpamType = 0; // 0 - mail, 1 - chat
|
||||
uint8 SpamType = 0; // 0 - mail, 1 - chat
|
||||
ObjectGuid SpammerGuid;
|
||||
uint32 Unk1 = 0;
|
||||
uint32 Unk2 = 0;
|
||||
uint32 Unk3 = 0;
|
||||
uint32 Unk4 = 0;
|
||||
std::string Description = "";
|
||||
uint32 Unk1 = 0;
|
||||
uint32 MailIdOrMessageType = 0;
|
||||
uint32 ChannelId = 0;
|
||||
uint32 SecondsSinceMessage = 0;
|
||||
std::string Description = "";
|
||||
};
|
||||
|
||||
class ComplainResult final : public ServerPacket
|
||||
|
||||
@@ -731,6 +731,10 @@ void WorldSession::LogoutPlayer(bool save)
|
||||
// a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected) d) LeaveGroupOnLogout is enabled
|
||||
if (_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && !_player->GetGroup()->isLFGGroup() && m_Socket && sWorld->getBoolConfig(CONFIG_LEAVE_GROUP_ON_LOGOUT))
|
||||
_player->RemoveFromGroup();
|
||||
// Remove player from active loot rolls in LFG groups (player stays in group but should not block rolls)
|
||||
else if (Group* group = _player->GetGroup())
|
||||
if (group->isLFGGroup())
|
||||
group->RemovePlayerFromRolls(_player->GetGUID());
|
||||
|
||||
// pussywizard: checked second time after being removed from a group
|
||||
if (!_player->IsBeingTeleportedFar() && !_player->m_InstanceValid && !_player->IsGameMaster())
|
||||
|
||||
@@ -2471,6 +2471,11 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
|
||||
|
||||
TempSummonType summonType = (duration <= 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
|
||||
|
||||
Unit* summoner = m_originalCaster;
|
||||
if (summoner->IsPet())
|
||||
if (Unit* owner = summoner->GetOwner())
|
||||
summoner = owner;
|
||||
|
||||
for (uint32 count = 0; count < numSummons; ++count)
|
||||
{
|
||||
Position pos;
|
||||
@@ -2480,7 +2485,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
|
||||
// randomize position for multiple summons
|
||||
pos = m_caster->GetRandomPoint(*destTarget, radius);
|
||||
|
||||
summon = m_originalCaster->SummonCreature(entry, pos, summonType, duration, 0, nullptr, personalSpawn);
|
||||
summon = summoner->SummonCreature(entry, pos, summonType, duration, 0, nullptr, personalSpawn);
|
||||
if (!summon)
|
||||
continue;
|
||||
|
||||
|
||||
@@ -603,6 +603,8 @@ void WorldConfig::BuildConfigCache()
|
||||
|
||||
SetConfigValue<bool>(CONFIG_IP_BASED_ACTION_LOGGING, "Allow.IP.Based.Action.Logging", false);
|
||||
|
||||
SetConfigValue<bool>(CONFIG_LOGSPAMREPORTS, "LogSpamReports", true);
|
||||
|
||||
// Whether to use LoS from game objects
|
||||
SetConfigValue<bool>(CONFIG_CHECK_GOBJECT_LOS, "CheckGameObjectLoS", true);
|
||||
|
||||
|
||||
@@ -112,6 +112,7 @@ enum ServerConfigs
|
||||
CONFIG_ENABLE_CONTINENT_TRANSPORT_PRELOADING,
|
||||
CONFIG_MINIGOB_MANABONK,
|
||||
CONFIG_IP_BASED_ACTION_LOGGING,
|
||||
CONFIG_LOGSPAMREPORTS,
|
||||
CONFIG_CALCULATE_CREATURE_ZONE_AREA_DATA,
|
||||
CONFIG_CALCULATE_GAMEOBJECT_ZONE_AREA_DATA,
|
||||
CONFIG_CHECK_GOBJECT_LOS,
|
||||
|
||||
@@ -15,8 +15,10 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "AchievementMgr.h"
|
||||
#include "Chat.h"
|
||||
#include "CommandScript.h"
|
||||
#include "Language.h"
|
||||
#include "Player.h"
|
||||
|
||||
using namespace Acore::ChatCommands;
|
||||
@@ -30,7 +32,7 @@ public:
|
||||
{
|
||||
static ChatCommandTable achievementCommandTable =
|
||||
{
|
||||
{ "add", HandleAchievementAddCommand, SEC_GAMEMASTER, Console::No },
|
||||
{ "add", HandleAchievementAddCommand, SEC_GAMEMASTER, Console::Yes },
|
||||
{ "checkall", HandleAchievementCheckAllCommand, SEC_ADMINISTRATOR, Console::Yes }
|
||||
};
|
||||
static ChatCommandTable commandTable =
|
||||
@@ -40,15 +42,27 @@ public:
|
||||
return commandTable;
|
||||
}
|
||||
|
||||
static bool HandleAchievementAddCommand(ChatHandler* handler, AchievementEntry const* achievementEntry)
|
||||
static bool HandleAchievementAddCommand(ChatHandler* handler, AchievementEntry const* achievementEntry, Optional<PlayerIdentifier> player)
|
||||
{
|
||||
Player* target = handler->getSelectedPlayer();
|
||||
if (!target)
|
||||
if (!player)
|
||||
player = PlayerIdentifier::FromTargetOrSelf(handler);
|
||||
|
||||
if (!player)
|
||||
{
|
||||
handler->SendErrorMessage(LANG_NO_CHAR_SELECTED);
|
||||
handler->SendErrorMessage(LANG_PLAYER_NOT_FOUND);
|
||||
return false;
|
||||
}
|
||||
target->CompletedAchievement(achievementEntry);
|
||||
|
||||
if (player->IsConnected())
|
||||
{
|
||||
player->GetConnectedPlayer()->CompletedAchievement(achievementEntry);
|
||||
handler->PSendSysMessage(LANG_ACHIEVEMENT_ADD_ONLINE, achievementEntry->ID, achievementEntry->name[0], player->GetName());
|
||||
}
|
||||
else
|
||||
{
|
||||
sAchievementMgr->CompletedAchievementForOfflinePlayer(player->GetGUID().GetCounter(), achievementEntry);
|
||||
handler->PSendSysMessage(LANG_ACHIEVEMENT_ADD_OFFLINE, achievementEntry->ID, achievementEntry->name[0], player->GetName());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
-54
@@ -452,59 +452,6 @@ private:
|
||||
uint32 _mightyBlowTimer;
|
||||
};
|
||||
|
||||
// npc_lokhtos_darkbargainer
|
||||
enum LokhtosItems
|
||||
{
|
||||
ITEM_THRORIUM_BROTHERHOOD_CONTRACT = 18628,
|
||||
ITEM_SULFURON_INGOT = 17203
|
||||
};
|
||||
|
||||
enum LokhtosQuests
|
||||
{
|
||||
QUEST_A_BINDING_CONTRACT = 7604
|
||||
};
|
||||
|
||||
enum LokhtosSpells
|
||||
{
|
||||
SPELL_CREATE_THORIUM_BROTHERHOOD_CONTRACT_DND = 23059
|
||||
};
|
||||
|
||||
struct npc_lokhtos_darkbargainer : public ScriptedAI
|
||||
{
|
||||
npc_lokhtos_darkbargainer(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void sGossipSelect(Player* player, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
if (action == GOSSIP_ACTION_INFO_DEF + 1)
|
||||
{
|
||||
CloseGossipMenuFor(player);
|
||||
player->CastSpell(player, SPELL_CREATE_THORIUM_BROTHERHOOD_CONTRACT_DND, false);
|
||||
}
|
||||
if (action == GOSSIP_ACTION_TRADE)
|
||||
player->GetSession()->SendListInventory(me->GetGUID());
|
||||
}
|
||||
|
||||
void sGossipHello(Player* player) override
|
||||
{
|
||||
if (me->IsQuestGiver())
|
||||
player->PrepareQuestMenu(me->GetGUID());
|
||||
|
||||
if (me->IsVendor() && player->GetReputationRank(59) >= REP_FRIENDLY)
|
||||
AddGossipItemFor(player, 4781, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
|
||||
|
||||
if (player->GetQuestRewardStatus(QUEST_A_BINDING_CONTRACT) != 1 &&
|
||||
!player->HasItemCount(ITEM_THRORIUM_BROTHERHOOD_CONTRACT, 1, true) &&
|
||||
player->HasItemCount(ITEM_SULFURON_INGOT))
|
||||
AddGossipItemFor(player, 4781, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
|
||||
if (player->GetReputationRank(59) < REP_FRIENDLY)
|
||||
SendGossipMenuFor(player, 3673, me->GetGUID());
|
||||
else
|
||||
SendGossipMenuFor(player, 3677, me->GetGUID());
|
||||
}
|
||||
};
|
||||
|
||||
// npc_rocknot
|
||||
enum RocknotSays
|
||||
{
|
||||
@@ -641,7 +588,6 @@ void AddSC_blackrock_depths()
|
||||
new at_ring_of_law();
|
||||
RegisterBlackrockDepthsCreatureAI(npc_grimstone);
|
||||
RegisterBlackrockDepthsCreatureAI(npc_phalanx);
|
||||
RegisterBlackrockDepthsCreatureAI(npc_lokhtos_darkbargainer);
|
||||
RegisterBlackrockDepthsCreatureAI(npc_rocknot);
|
||||
RegisterBlackrockDepthsCreatureAI(brd_ironhand_guardian);
|
||||
}
|
||||
|
||||
+7
-45
@@ -95,13 +95,7 @@ enum Events
|
||||
|
||||
enum Misc
|
||||
{
|
||||
TEXT_ID_SUMMON_1 = 4995,
|
||||
TEXT_ID_SUMMON_2 = 5011,
|
||||
TEXT_ID_SUMMON_3 = 5012,
|
||||
|
||||
GOSSIP_ITEM_SUMMON_1 = 4093,
|
||||
GOSSIP_ITEM_SUMMON_2 = 4109,
|
||||
GOSSIP_ITEM_SUMMON_3 = 4108,
|
||||
MENU_ID_RAGNAROS_SUMMON = 4108,
|
||||
|
||||
FACTION_MAJORDOMO_FRIENDLY = 1080,
|
||||
SUMMON_GROUP_ADDS = 1,
|
||||
@@ -507,46 +501,14 @@ struct boss_majordomo : public BossAI
|
||||
}
|
||||
}
|
||||
|
||||
void sGossipHello(Player* player) override
|
||||
void sGossipSelect(Player* player, uint32 menuId, uint32 /*gossipListId*/) override
|
||||
{
|
||||
AddGossipItemFor(player, GOSSIP_ITEM_SUMMON_1, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
|
||||
SendGossipMenuFor(player, TEXT_ID_SUMMON_1, me->GetGUID());
|
||||
}
|
||||
|
||||
void sGossipSelect(Player* player, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
switch (action)
|
||||
if (menuId == MENU_ID_RAGNAROS_SUMMON)
|
||||
{
|
||||
case GOSSIP_ACTION_INFO_DEF:
|
||||
{
|
||||
AddGossipItemFor(player, GOSSIP_ITEM_SUMMON_2, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
SendGossipMenuFor(player, TEXT_ID_SUMMON_2, me->GetGUID());
|
||||
break;
|
||||
}
|
||||
case GOSSIP_ACTION_INFO_DEF+1:
|
||||
{
|
||||
AddGossipItemFor(player, GOSSIP_ITEM_SUMMON_2, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
|
||||
SendGossipMenuFor(player, TEXT_ID_SUMMON_2, me->GetGUID());
|
||||
break;
|
||||
}
|
||||
case GOSSIP_ACTION_INFO_DEF+2:
|
||||
{
|
||||
AddGossipItemFor(player, GOSSIP_ITEM_SUMMON_3, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
|
||||
SendGossipMenuFor(player, TEXT_ID_SUMMON_3, me->GetGUID());
|
||||
break;
|
||||
}
|
||||
case GOSSIP_ACTION_INFO_DEF+3:
|
||||
{
|
||||
CloseGossipMenuFor(player);
|
||||
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
Talk(SAY_RAG_SUM_1, player);
|
||||
DoAction(ACTION_START_RAGNAROS_INTRO);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
CloseGossipMenuFor(player);
|
||||
break;
|
||||
CloseGossipMenuFor(player);
|
||||
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
Talk(SAY_RAG_SUM_1, player);
|
||||
DoAction(ACTION_START_RAGNAROS_INTRO);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ struct boss_moroes : public BossAI
|
||||
_vanished = true;
|
||||
Talk(SAY_SPECIAL);
|
||||
DoCastSelf(SPELL_VANISH);
|
||||
me->SetImmuneToAll(true);
|
||||
me->SetImmuneToAll(true, true);
|
||||
scheduler.Schedule(5s, 7s, [this](TaskContext)
|
||||
{
|
||||
me->SetImmuneToAll(false);
|
||||
|
||||
@@ -187,7 +187,6 @@ struct boss_kalecgos : public BossAI
|
||||
me->SetRegeneratingHealth(false);
|
||||
me->RemoveAllAuras();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->CombatStop();
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
}, 1s);
|
||||
|
||||
@@ -296,39 +296,8 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
/*######
|
||||
## npc_augustus_the_touched
|
||||
######*/
|
||||
|
||||
class npc_augustus_the_touched : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_augustus_the_touched() : CreatureScript("npc_augustus_the_touched") { }
|
||||
|
||||
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
if (action == GOSSIP_ACTION_TRADE)
|
||||
player->GetSession()->SendListInventory(creature->GetGUID());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
if (creature->IsQuestGiver())
|
||||
player->PrepareQuestMenu(creature->GetGUID());
|
||||
|
||||
if (creature->IsVendor() && player->GetQuestRewardStatus(6164))
|
||||
AddGossipItemFor(player, GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
|
||||
|
||||
SendGossipMenuFor(player, player->GetGossipTextId(creature), creature->GetGUID());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_eastern_plaguelands()
|
||||
{
|
||||
new npc_eris_hevenfire();
|
||||
new npc_balance_of_light_and_shadow();
|
||||
new npc_augustus_the_touched();
|
||||
}
|
||||
|
||||
@@ -293,63 +293,6 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
/*######
|
||||
## npc_parqual_fintallas
|
||||
######*/
|
||||
|
||||
enum ParqualFintallas
|
||||
{
|
||||
SPELL_MARK_OF_SHAME = 6767,
|
||||
QUEST_ID_TEST_OF_LORE = 6628,
|
||||
GOSSIP_MENU_ID_TEST_OF_LORE = 4764,
|
||||
GOSSIP_TEXTID_PARQUAL_FINTALLAS = 5821,
|
||||
GOSSIP_TEXTID_TEST_OF_LORE = 5822,
|
||||
};
|
||||
|
||||
class npc_parqual_fintallas : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_parqual_fintallas() : CreatureScript("npc_parqual_fintallas") { }
|
||||
|
||||
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
if (action == GOSSIP_ACTION_INFO_DEF + 1)
|
||||
{
|
||||
CloseGossipMenuFor(player);
|
||||
creature->CastSpell(player, SPELL_MARK_OF_SHAME, false);
|
||||
}
|
||||
if (action == GOSSIP_ACTION_INFO_DEF + 2)
|
||||
{
|
||||
CloseGossipMenuFor(player);
|
||||
player->AreaExploredOrEventHappens(6628);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
if (creature->IsQuestGiver())
|
||||
{
|
||||
player->PrepareQuestMenu(creature->GetGUID());
|
||||
}
|
||||
|
||||
if (player->GetQuestStatus(QUEST_ID_TEST_OF_LORE) == QUEST_STATUS_INCOMPLETE && !player->HasAura(SPELL_MARK_OF_SHAME))
|
||||
{
|
||||
AddGossipItemFor(player, GOSSIP_MENU_ID_TEST_OF_LORE, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
AddGossipItemFor(player, GOSSIP_MENU_ID_TEST_OF_LORE, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
AddGossipItemFor(player, GOSSIP_MENU_ID_TEST_OF_LORE, 3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
|
||||
SendGossipMenuFor(player, GOSSIP_TEXTID_TEST_OF_LORE, creature->GetGUID());
|
||||
}
|
||||
else
|
||||
{
|
||||
SendGossipMenuFor(player, GOSSIP_TEXTID_PARQUAL_FINTALLAS, creature->GetGUID());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/*######
|
||||
## ALLIANCE
|
||||
#######*/
|
||||
@@ -4037,7 +3980,6 @@ void AddSC_undercity()
|
||||
{
|
||||
new npc_lady_sylvanas_windrunner();
|
||||
new npc_highborne_lamenter();
|
||||
new npc_parqual_fintallas();
|
||||
|
||||
new npc_varian_wrynn();
|
||||
new npc_thrall_bfu();
|
||||
|
||||
@@ -78,6 +78,7 @@ struct boss_falric : public BossAI
|
||||
me->m_Events.AddEventAtOffset([this]()
|
||||
{
|
||||
_startingFight = false;
|
||||
me->SetImmuneToPC(false);
|
||||
me->SetInCombatWithZone();
|
||||
}, 8s);
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@ struct boss_marwyn : public BossAI
|
||||
me->m_Events.AddEventAtOffset([this]()
|
||||
{
|
||||
_startingFight = false;
|
||||
me->SetImmuneToPC(false);
|
||||
me->SetInCombatWithZone();
|
||||
}, 8s);
|
||||
}
|
||||
|
||||
+27
-43
@@ -1499,7 +1499,6 @@ enum eFightEvents
|
||||
EVENT_LK_SUMMON_LA,
|
||||
EVENT_LK_SUMMON_NEXT_ICE_WALL,
|
||||
EVENT_SAY_OPENING,
|
||||
EVENT_DECREASE_REQ_COUNT_BY_100,
|
||||
};
|
||||
|
||||
struct npc_hor_lich_king : public NullCreatureAI
|
||||
@@ -1515,13 +1514,14 @@ struct npc_hor_lich_king : public NullCreatureAI
|
||||
EventMap events;
|
||||
SummonList summons;
|
||||
uint8 currentWall;
|
||||
uint8 reqKillCount;
|
||||
uint8 summonsCount;
|
||||
uint8 div2;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
currentWall = 0;
|
||||
reqKillCount = 0;
|
||||
summonsCount = 0;
|
||||
div2 = 0;
|
||||
events.Reset();
|
||||
events.RescheduleEvent(EVENT_LK_CHECK_COMBAT, 1s);
|
||||
}
|
||||
@@ -1529,24 +1529,21 @@ struct npc_hor_lich_king : public NullCreatureAI
|
||||
{
|
||||
if (action == ACTION_START_LK_FIGHT_REAL)
|
||||
events.ScheduleEvent(EVENT_LK_START_FOLLOWING, 1500ms);
|
||||
else if ((action == ACTION_INFORM_TRASH_DIED && reqKillCount) || action == ACTION_CHECK_TRASH_DIED)
|
||||
}
|
||||
|
||||
void WallCompleted()
|
||||
{
|
||||
++currentWall;
|
||||
instance->SetData(ACTION_DELETE_ICE_WALL, 1);
|
||||
if (currentWall <= 3)
|
||||
{
|
||||
if ((action == ACTION_CHECK_TRASH_DIED && reqKillCount == 0) || (action == ACTION_INFORM_TRASH_DIED && (--reqKillCount) == 0))
|
||||
{
|
||||
events.CancelEvent(EVENT_DECREASE_REQ_COUNT_BY_100); // just in case, magic happens sometimes
|
||||
++currentWall;
|
||||
instance->SetData(ACTION_DELETE_ICE_WALL, 1);
|
||||
if (currentWall <= 3)
|
||||
{
|
||||
events.ScheduleEvent(EVENT_LK_SUMMON_NEXT_ICE_WALL, 1s);
|
||||
events.ScheduleEvent(EVENT_LK_SUMMON, currentWall == 3 ? 11s : 7500ms);
|
||||
}
|
||||
else
|
||||
me->RemoveAura(SPELL_REMORSELESS_WINTER);
|
||||
if (Creature* c = instance->GetCreature(NPC_SYLVANAS_PART2))
|
||||
c->AI()->DoAction(ACTION_INFORM_WALL_DESTROYED);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_LK_SUMMON_NEXT_ICE_WALL, 1s);
|
||||
events.ScheduleEvent(EVENT_LK_SUMMON, currentWall == 3 ? 11s : 7500ms);
|
||||
}
|
||||
else
|
||||
me->RemoveAura(SPELL_REMORSELESS_WINTER);
|
||||
if (Creature* c = instance->GetCreature(NPC_SYLVANAS_PART2))
|
||||
c->AI()->DoAction(ACTION_INFORM_WALL_DESTROYED);
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 /*id*/) override
|
||||
@@ -1569,17 +1566,14 @@ struct npc_hor_lich_king : public NullCreatureAI
|
||||
else if (currentWall == 4)
|
||||
{
|
||||
Talk(SAY_LK_NOWHERE_TO_RUN);
|
||||
instance->SetData(DATA_LICH_KING, DONE);
|
||||
instance->SetBossState(DATA_LICH_KING, DONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* s) override
|
||||
{
|
||||
|
||||
++reqKillCount;
|
||||
if (events.HasTimeUntilEvent(EVENT_DECREASE_REQ_COUNT_BY_100))
|
||||
events.RescheduleEvent(EVENT_DECREASE_REQ_COUNT_BY_100, 10s);
|
||||
++summonsCount;
|
||||
summons.Summon(s);
|
||||
s->SetHomePosition(PathWaypoints[WP_STOP[currentWall + 1]]);
|
||||
s->GetMotionMaster()->MovePoint(0, PathWaypoints[WP_STOP[currentWall + 1]]);
|
||||
@@ -1592,6 +1586,14 @@ struct npc_hor_lich_king : public NullCreatureAI
|
||||
s->SetHomePosition(PathWaypoints[WP_STOP[currentWall + 1]]);
|
||||
}
|
||||
|
||||
void SummonedCreatureDies(Creature* /*summon*/, Unit* /*killer*/) override
|
||||
{
|
||||
if (!summonsCount)
|
||||
return;
|
||||
if (--summonsCount == 0)
|
||||
WallCompleted();
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature* s) override
|
||||
{
|
||||
summons.Despawn(s);
|
||||
@@ -1623,7 +1625,7 @@ struct npc_hor_lich_king : public NullCreatureAI
|
||||
{
|
||||
me->GetMotionMaster()->MovementExpired();
|
||||
me->StopMoving();
|
||||
reqKillCount = 255;
|
||||
summonsCount = 255;
|
||||
leader->InterruptNonMeleeSpells(true);
|
||||
me->CastSpell(leader, SPELL_HARVEST_SOUL);
|
||||
events.ScheduleEvent(EVENT_LK_KILL_LEADER, 3s);
|
||||
@@ -1720,15 +1722,6 @@ struct npc_hor_lich_king : public NullCreatureAI
|
||||
events.ScheduleEvent(EVENT_LK_SUMMON_LA, 17s + 700ms);
|
||||
break;
|
||||
}
|
||||
if (currentWall <= 3)
|
||||
{
|
||||
reqKillCount = 100;
|
||||
events.RescheduleEvent(EVENT_DECREASE_REQ_COUNT_BY_100, 10s);
|
||||
}
|
||||
break;
|
||||
case EVENT_DECREASE_REQ_COUNT_BY_100:
|
||||
reqKillCount = (reqKillCount <= 100 ? 0 : reqKillCount - 100);
|
||||
DoAction(ACTION_CHECK_TRASH_DIED);
|
||||
break;
|
||||
case EVENT_LK_SUMMON_GHOULS:
|
||||
DoCastAOE(SPELL_SUMMON_RAGING_GHOULS);
|
||||
@@ -2003,9 +1996,6 @@ struct npc_hor_raging_ghoul : public ScriptedAI
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
me->SetCorpseDelay(10);
|
||||
if (InstanceScript* instance = me->GetInstanceScript())
|
||||
if (Creature* lichKing = instance->GetCreature(NPC_LICH_KING_BOSS))
|
||||
lichKing->AI()->DoAction(ACTION_INFORM_TRASH_DIED);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2059,9 +2049,6 @@ struct npc_hor_risen_witch_doctor : public ScriptedAI
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
me->SetCorpseDelay(10);
|
||||
if (InstanceScript* instance = me->GetInstanceScript())
|
||||
if (Creature* lichKing = instance->GetCreature(NPC_LICH_KING_BOSS))
|
||||
lichKing->AI()->DoAction(ACTION_INFORM_TRASH_DIED);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2110,9 +2097,6 @@ struct npc_hor_lumbering_abomination : public ScriptedAI
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
me->SetCorpseDelay(10);
|
||||
if (InstanceScript* instance = me->GetInstanceScript())
|
||||
if (Creature* lichKing = instance->GetCreature(NPC_LICH_KING_BOSS))
|
||||
lichKing->AI()->DoAction(ACTION_INFORM_TRASH_DIED);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -27,14 +27,22 @@
|
||||
|
||||
enum Data
|
||||
{
|
||||
DATA_INTRO,
|
||||
// Boss encounters (indices for SetBossState)
|
||||
DATA_FALRIC,
|
||||
DATA_MARWYN,
|
||||
DATA_LICH_KING,
|
||||
MAX_ENCOUNTER,
|
||||
|
||||
// Non-boss data (SetData/GetData only)
|
||||
DATA_INTRO,
|
||||
DATA_FROSTSWORN_GENERAL,
|
||||
DATA_LK_INTRO,
|
||||
DATA_LICH_KING,
|
||||
DATA_BATTERED_HILT,
|
||||
MAX_ENCOUNTER,
|
||||
DATA_WAVE_NUMBER,
|
||||
DATA_LK_BATTLE,
|
||||
DATA_SHIP_CAPTAIN,
|
||||
|
||||
// Actions
|
||||
ACTION_SHOW_TRASH,
|
||||
ACTION_SPIRITUAL_REFLECTIONS_COPY,
|
||||
ACTION_SPIRITUAL_REFLECTIONS_ACTIVATE,
|
||||
@@ -42,9 +50,6 @@ enum Data
|
||||
ACTION_START_LK_FIGHT,
|
||||
ACTION_STOP_LK_FIGHT,
|
||||
ACTION_DELETE_ICE_WALL,
|
||||
DATA_WAVE_NUMBER,
|
||||
DATA_LK_BATTLE,// in progress
|
||||
DATA_SHIP_CAPTAIN,
|
||||
};
|
||||
|
||||
enum Creatures
|
||||
@@ -249,8 +254,6 @@ enum hMisc
|
||||
ACTION_START_INTRO,
|
||||
ACTION_SKIP_INTRO,
|
||||
ACTION_START_LK_FIGHT_REAL,
|
||||
ACTION_INFORM_TRASH_DIED,
|
||||
ACTION_CHECK_TRASH_DIED,
|
||||
ACTION_INFORM_WALL_DESTROYED,
|
||||
|
||||
QUEST_DELIVRANCE_FROM_THE_PIT_A2 = 24710,
|
||||
|
||||
+2
-3
@@ -468,6 +468,7 @@ public:
|
||||
leader->AI()->DoAction(ACTION_START_INTRO);
|
||||
break;
|
||||
case ACTION_START_LK_FIGHT:
|
||||
SetBossState(DATA_LICH_KING, IN_PROGRESS);
|
||||
_isLichKingFightActive = true;
|
||||
DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_RETREATING_TIMED_EVENT);
|
||||
DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_RETREATING_TIMED_EVENT);
|
||||
@@ -516,15 +517,13 @@ public:
|
||||
lichKing->SetSpeed(MOVE_RUN, lichKing->GetCreatureTemplate()->speed_run);
|
||||
}
|
||||
_isLichKingFightActive = false;
|
||||
SetBossState(DATA_LICH_KING, FAIL);
|
||||
_outroTimer = 0;
|
||||
_outroStep = 0;
|
||||
[[fallthrough]];
|
||||
case ACTION_DELETE_ICE_WALL:
|
||||
HandleGameObject(GO_ICE_WALL, true);
|
||||
break;
|
||||
case DATA_LICH_KING:
|
||||
SetBossState(DATA_LICH_KING, static_cast<EncounterState>(data));
|
||||
break;
|
||||
case DATA_BATTERED_HILT:
|
||||
{
|
||||
if (GetPersistentData(PERSISTENT_DATA_BATTERED_HILT))
|
||||
|
||||
@@ -688,14 +688,14 @@ public:
|
||||
if (_instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != IN_PROGRESS)
|
||||
return;
|
||||
|
||||
// Blizzlike: ship wipes when all players are in cannons (vehicles) with nobody on deck
|
||||
// See: azerothcore/azerothcore-wotlk#17856
|
||||
bool playerOnDeck = false;
|
||||
me->GetMap()->DoForAllPlayers([&](Player* player)
|
||||
{
|
||||
if (!player->GetVehicle() && player->IsAlive())
|
||||
playerOnDeck = true;
|
||||
});
|
||||
|
||||
// Wipe if no player is on the deck
|
||||
if (!playerOnDeck)
|
||||
{
|
||||
// Script runs on enemy ship. We want to kill our ship.
|
||||
|
||||
@@ -653,6 +653,8 @@ public:
|
||||
_lastTalkTimeBuff = 0;
|
||||
_bFrostmournePhase = false;
|
||||
_bFordringMustFallYell = false;
|
||||
me->SetRegeneratingHealth(true);
|
||||
me->SetIsCombatDisallowed(false);
|
||||
|
||||
_Reset();
|
||||
DoAction(ACTION_RESTORE_LIGHT);
|
||||
@@ -792,12 +794,15 @@ public:
|
||||
if (_phase == PHASE_THREE && HealthBelowPct(10) && !me->HasUnitState(UNIT_STATE_CASTING))
|
||||
{
|
||||
_phase = PHASE_OUTRO;
|
||||
me->SetRegeneratingHealth(false);
|
||||
me->SetIsCombatDisallowed(true);
|
||||
EntryCheckPredicate pred(NPC_STRANGULATE_VEHICLE);
|
||||
summons.DoAction(ACTION_TELEPORT_BACK, pred);
|
||||
events.Reset();
|
||||
summons.DespawnAll();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->AttackStop();
|
||||
me->CombatStop(true);
|
||||
me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_FURY_OF_FROSTMOURNE);
|
||||
me->InterruptNonMeleeSpells(true);
|
||||
me->CastSpell((Unit*)nullptr, SPELL_FURY_OF_FROSTMOURNE, false);
|
||||
@@ -1253,6 +1258,9 @@ public:
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
{
|
||||
if (_phase == PHASE_OUTRO || _phase == PHASE_FROSTMOURNE)
|
||||
return;
|
||||
|
||||
EntryCheckPredicate pred(NPC_STRANGULATE_VEHICLE);
|
||||
summons.DoAction(ACTION_TELEPORT_BACK, pred);
|
||||
instance->SetBossState(DATA_THE_LICH_KING, FAIL);
|
||||
|
||||
@@ -341,18 +341,12 @@ public:
|
||||
_done = true;
|
||||
Talk(SAY_VALITHRIA_SUCCESS);
|
||||
_instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
_instance->DoRemoveAurasDueToSpellOnPlayers(70766);
|
||||
me->RemoveAurasDueToSpell(SPELL_CORRUPTION_VALITHRIA);
|
||||
me->CastSpell(me, SPELL_ACHIEVEMENT_CHECK, true);
|
||||
me->CastSpell((Unit*)nullptr, SPELL_DREAMWALKERS_RAGE, false);
|
||||
_events.Reset();
|
||||
_events.ScheduleEvent(EVENT_DREAM_SLIP, 3500ms);
|
||||
_instance->SetBossState(DATA_VALITHRIA_DREAMWALKER, DONE);
|
||||
|
||||
if (Creature* trigger = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_TRIGGER)))
|
||||
trigger->AI()->EnterEvadeMode();
|
||||
if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_LICH_KING)))
|
||||
lichKing->AI()->Reset();
|
||||
lichKing->AI()->EnterEvadeMode();
|
||||
}
|
||||
else if (!_over75PercentTalkDone && me->HealthAbovePctHealed(75, heal))
|
||||
{
|
||||
@@ -361,11 +355,8 @@ public:
|
||||
}
|
||||
else if (_instance->GetBossState(DATA_VALITHRIA_DREAMWALKER) == NOT_STARTED)
|
||||
{
|
||||
if (Creature* trigger = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_TRIGGER)))
|
||||
{
|
||||
trigger->AI()->DoAction(ACTION_ENTER_COMBAT);
|
||||
_instance->SetBossState(DATA_VALITHRIA_DREAMWALKER, IN_PROGRESS);
|
||||
}
|
||||
if (Creature* archmage = me->FindNearestCreature(NPC_RISEN_ARCHMAGE, 30.0f))
|
||||
DoZoneInCombat(archmage); // archmage chain will put trigger in combat
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,7 +379,7 @@ public:
|
||||
Talk(SAY_VALITHRIA_DEATH);
|
||||
_instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me);
|
||||
if (Creature* trigger = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_TRIGGER)))
|
||||
trigger->AI()->EnterEvadeMode();
|
||||
trigger->AI()->DoAction(ACTION_DEATH);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -404,6 +395,8 @@ public:
|
||||
me->SetDisplayId(11686);
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->DespawnOrUnsummon(4s);
|
||||
if (Creature* trigger = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_TRIGGER)))
|
||||
Unit::Kill(me, trigger);
|
||||
if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_LICH_KING)))
|
||||
lichKing->CastSpell(lichKing, SPELL_SPAWN_CHEST, false);
|
||||
_instance->SetData(DATA_WEEKLY_QUEST_ID, 0); // show hidden npc if necessary
|
||||
@@ -434,13 +427,8 @@ public:
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
// does not enter combat
|
||||
if (_instance->GetBossState(DATA_VALITHRIA_DREAMWALKER) == NOT_STARTED)
|
||||
{
|
||||
uint32 startingHealth = me->GetMaxHealth() * 0.5f;
|
||||
if (me->GetHealth() != startingHealth) // healing when boss cannot be engaged (lower spire not finished, cheating) doesn't start the fight, prevent winning this way
|
||||
me->SetHealth(startingHealth);
|
||||
if (_instance->GetBossState(DATA_VALITHRIA_DREAMWALKER) != IN_PROGRESS)
|
||||
return;
|
||||
}
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
@@ -508,31 +496,26 @@ public:
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
events.Reset();
|
||||
summons.DespawnAll();
|
||||
if (instance->GetBossState(DATA_VALITHRIA_DREAMWALKER) != DONE)
|
||||
instance->SetBossState(DATA_VALITHRIA_DREAMWALKER, NOT_STARTED);
|
||||
_Reset();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
checkTimer = 5000;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* target) override
|
||||
void JustEnteredCombat(Unit* target) override
|
||||
{
|
||||
if (IsEngaged())
|
||||
return;
|
||||
|
||||
if (!instance->CheckRequiredBosses(DATA_VALITHRIA_DREAMWALKER, target->ToPlayer()))
|
||||
{
|
||||
me->setActive(true);
|
||||
EnterEvadeMode();
|
||||
EnterEvadeMode(EVADE_REASON_SEQUENCE_BREAK);
|
||||
instance->DoCastSpellOnPlayers(LIGHT_S_HAMMER_TELEPORT);
|
||||
return;
|
||||
}
|
||||
if (instance->GetBossState(DATA_VALITHRIA_DREAMWALKER) == DONE)
|
||||
{
|
||||
me->CombatStop();
|
||||
return;
|
||||
}
|
||||
|
||||
EngagementStart(target);
|
||||
|
||||
me->setActive(true);
|
||||
me->SetInCombatWithZone();
|
||||
DoZoneInCombat();
|
||||
instance->SetBossState(DATA_VALITHRIA_DREAMWALKER, IN_PROGRESS);
|
||||
if (Creature* valithria = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_VALITHRIA_DREAMWALKER)))
|
||||
valithria->AI()->DoAction(ACTION_ENTER_COMBAT);
|
||||
@@ -547,66 +530,31 @@ public:
|
||||
(*itr)->AI()->DoAction(ACTION_ENTER_COMBAT);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* target) override
|
||||
{
|
||||
if (target->IsPlayer())
|
||||
BossAI::AttackStart(target);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER) override
|
||||
{
|
||||
CreatureAI::EnterEvadeMode(why);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
||||
|
||||
bool CanAIAttack(Unit const* target) const override
|
||||
void JustExitedCombat() override
|
||||
{
|
||||
return target->IsPlayer();
|
||||
}
|
||||
EngagementOver();
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
if (instance->GetBossState(DATA_VALITHRIA_DREAMWALKER) != DONE)
|
||||
DoAction(ACTION_DEATH); // setActive(false) in ValithriaDespawner
|
||||
else
|
||||
_JustReachedHome();
|
||||
me->setActive(false);
|
||||
|
||||
if (!me->IsAlive())
|
||||
return;
|
||||
if (instance->GetBossState(DATA_VALITHRIA_DREAMWALKER) == DONE)
|
||||
return;
|
||||
DoAction(ACTION_DEATH);
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_DEATH)
|
||||
{
|
||||
instance->SetBossState(DATA_VALITHRIA_DREAMWALKER, NOT_STARTED);
|
||||
me->m_Events.AddEventAtOffset(new ValithriaDespawner(me), 5s);
|
||||
else if (action == ACTION_ENTER_COMBAT)
|
||||
{
|
||||
if (!me->IsInCombat())
|
||||
me->SetInCombatWithZone();
|
||||
if (Creature* lichKing = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_VALITHRIA_LICH_KING)))
|
||||
lichKing->AI()->EnterEvadeMode();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!me->IsInCombat())
|
||||
return;
|
||||
|
||||
if (checkTimer <= diff)
|
||||
{
|
||||
checkTimer = 3000;
|
||||
me->SetInCombatWithZone();
|
||||
for (ThreatReference const* ref : me->GetThreatMgr().GetUnsortedThreatList())
|
||||
{
|
||||
if (Unit* target = ref->GetVictim())
|
||||
if (target->IsAlive() && target->IsPlayer() && me->GetExactDist(target) < 200.0f && !target->IsImmunedToDamageOrSchool(SPELL_SCHOOL_MASK_ALL))
|
||||
return;
|
||||
}
|
||||
EnterEvadeMode();
|
||||
}
|
||||
else
|
||||
checkTimer -= diff;
|
||||
}
|
||||
|
||||
private:
|
||||
uint16 checkTimer;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
@@ -712,7 +660,7 @@ public:
|
||||
struct npc_risen_archmageAI : public ScriptedAI
|
||||
{
|
||||
npc_risen_archmageAI(Creature* creature) : ScriptedAI(creature),
|
||||
_instance(creature->GetInstanceScript())
|
||||
_instance(creature->GetInstanceScript()), _isInitialArchmage(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -725,23 +673,34 @@ public:
|
||||
{
|
||||
_events.Reset();
|
||||
_events.ScheduleEvent(EVENT_FROSTBOLT_VOLLEY, 5s, 15s);
|
||||
_events.ScheduleEvent(EVENT_MANA_VOID, 15s, 25s);
|
||||
_events.ScheduleEvent(EVENT_MANA_VOID, 20s, 25s);
|
||||
_events.ScheduleEvent(EVENT_COLUMN_OF_FROST, 10s, 20s);
|
||||
_isInitialArchmage = me->GetSpawnId() != 0;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*target*/) override
|
||||
void JustEnteredCombat(Unit* who) override
|
||||
{
|
||||
me->FinishSpell(CURRENT_CHANNELED_SPELL, false);
|
||||
me->SetInCombatWithZone();
|
||||
if (me->GetSpawnId())
|
||||
if (IsEngaged())
|
||||
return;
|
||||
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
|
||||
EngagementStart(who);
|
||||
|
||||
if (_isInitialArchmage)
|
||||
{
|
||||
if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_LICH_KING)))
|
||||
DoZoneInCombat(lichKing);
|
||||
|
||||
if (Creature* trigger = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VALITHRIA_TRIGGER)))
|
||||
trigger->AI()->DoAction(ACTION_ENTER_COMBAT);
|
||||
DoZoneInCombat(trigger);
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
if (action == ACTION_ENTER_COMBAT && !me->IsInCombat())
|
||||
me->SetInCombatWithZone();
|
||||
if (action == ACTION_ENTER_COMBAT)
|
||||
DoZoneInCombat();
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summon) override
|
||||
@@ -754,10 +713,8 @@ public:
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!me->IsInCombat())
|
||||
if (me->GetSpawnId())
|
||||
if (!me->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|
||||
me->CastSpell(me, SPELL_CORRUPTION, true);
|
||||
if (!me->IsInCombat() && me->IsAlive() && _isInitialArchmage && !me->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|
||||
DoCastSelf(SPELL_CORRUPTION);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
@@ -796,6 +753,7 @@ public:
|
||||
private:
|
||||
EventMap _events;
|
||||
InstanceScript* _instance;
|
||||
bool _isInitialArchmage;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
|
||||
@@ -345,11 +345,17 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 corpseDelay = creature->GetCorpseDelay();
|
||||
uint32 respawnDelay = creature->GetRespawnDelay();
|
||||
creature->SetCorpseDelay(1);
|
||||
creature->SetRespawnDelay(2);
|
||||
|
||||
if (CreatureData const* data = creature->GetCreatureData())
|
||||
creature->SetPosition(data->posX, data->posY, data->posZ, data->orientation);
|
||||
creature->DespawnOrUnsummon();
|
||||
|
||||
creature->SetRespawnTime(5);
|
||||
creature->SetCorpseDelay(corpseDelay);
|
||||
creature->SetRespawnDelay(respawnDelay);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -730,7 +736,7 @@ public:
|
||||
{
|
||||
me->SetReactState(REACT_DEFENSIVE);
|
||||
_didUnderTenPercentText = false;
|
||||
_wipeCheckTimer = 3000;
|
||||
_wipeCheckTimer = 1000;
|
||||
_handledWP4 = false;
|
||||
|
||||
_events.Reset();
|
||||
@@ -868,6 +874,27 @@ public:
|
||||
|
||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (!_wipeCheckTimer)
|
||||
{
|
||||
_wipeCheckTimer = 1000;
|
||||
Player* player = nullptr;
|
||||
Acore::AnyPlayerInObjectRangeCheck check(me, 60.0f);
|
||||
Acore::PlayerSearcher<Acore::AnyPlayerInObjectRangeCheck> searcher(me, player, check);
|
||||
Cell::VisitObjects(me, searcher, 60.0f);
|
||||
// wipe
|
||||
if (!player)
|
||||
{
|
||||
damage *= 100;
|
||||
if (damage >= me->GetHealth())
|
||||
{
|
||||
FrostwingGauntletRespawner respawner;
|
||||
Acore::CreatureWorker<FrostwingGauntletRespawner> worker(me, respawner);
|
||||
Cell::VisitObjects(me, worker, 333.0f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (HealthBelowPct(10))
|
||||
{
|
||||
if (!_didUnderTenPercentText)
|
||||
@@ -885,37 +912,21 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateEscortAI(uint32 /*diff*/) override {}
|
||||
void UpdateEscortAI(uint32 diff) override
|
||||
{
|
||||
if (_wipeCheckTimer <= diff)
|
||||
_wipeCheckTimer = 0;
|
||||
else
|
||||
_wipeCheckTimer -= diff;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
npc_escortAI::UpdateAI(diff);
|
||||
|
||||
//Position pos = me->GetHomePosition();
|
||||
if (!me->isActiveObject()/* && me->GetExactDist(&pos) < 5.0f*/) // during event
|
||||
if (!me->isActiveObject())
|
||||
return;
|
||||
|
||||
if (_wipeCheckTimer <= diff)
|
||||
{
|
||||
_wipeCheckTimer = 3000;
|
||||
|
||||
Player* player = nullptr;
|
||||
Acore::AnyPlayerInObjectRangeCheck check(me, 140.0f);
|
||||
Acore::PlayerSearcher<Acore::AnyPlayerInObjectRangeCheck> searcher(me, player, check);
|
||||
Cell::VisitObjects(me, searcher, 140.0f);
|
||||
// wipe
|
||||
if (!player || me->GetExactDist(4357.0f, 2606.0f, 350.0f) > 125.0f)
|
||||
{
|
||||
//Talk(SAY_CROK_DEATH);
|
||||
FrostwingGauntletRespawner respawner;
|
||||
Acore::CreatureWorker<FrostwingGauntletRespawner> worker(me, respawner);
|
||||
Cell::VisitObjects(me, worker, 333.0f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
_wipeCheckTimer -= diff;
|
||||
|
||||
UpdateVictim();
|
||||
|
||||
_events.Update(diff);
|
||||
@@ -968,7 +979,7 @@ public:
|
||||
bool CanAIAttack(Unit const* target) const override
|
||||
{
|
||||
// do not see targets inside Frostwing Halls when we are not there
|
||||
return !target->IsPlayer() && (me->GetPositionY() > 2660.0f) == (target->GetPositionY() > 2660.0f) && target->GetEntry() != NPC_SINDRAGOSA;
|
||||
return (me->GetPositionY() > 2660.0f) == (target->GetPositionY() > 2660.0f);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -995,18 +1006,30 @@ public:
|
||||
|
||||
struct boss_sister_svalnaAI : public BossAI
|
||||
{
|
||||
boss_sister_svalnaAI(Creature* creature) : BossAI(creature, DATA_SISTER_SVALNA)
|
||||
boss_sister_svalnaAI(Creature* creature) : BossAI(creature, DATA_SISTER_SVALNA),
|
||||
_isEventInProgress(false)
|
||||
{
|
||||
}
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
if (!me->isDead())
|
||||
Reset();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
me->SetImmuneToAll(true);
|
||||
me->SetReactState(REACT_DEFENSIVE);
|
||||
_isEventInProgress = false;
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
_JustReachedHome();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetCanFly(true);
|
||||
me->SetDisableGravity(true);
|
||||
me->SendMovementFlagUpdate();
|
||||
me->SetDisableGravity(false);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
@@ -1080,6 +1103,8 @@ public:
|
||||
break;
|
||||
case ACTION_START_GAUNTLET:
|
||||
me->setActive(true);
|
||||
me->SetImmuneToAll(true);
|
||||
_isEventInProgress = true;
|
||||
events.ScheduleEvent(EVENT_SVALNA_START, 25s);
|
||||
break;
|
||||
case ACTION_RESURRECT_CAPTAINS:
|
||||
@@ -1106,16 +1131,21 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void JustExitedCombat() override
|
||||
{
|
||||
if (_isEventInProgress)
|
||||
return;
|
||||
CreatureAI::JustExitedCombat();
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
if (type != EFFECT_MOTION_TYPE || id != POINT_LAND)
|
||||
return;
|
||||
|
||||
_isEventInProgress = false;
|
||||
me->setActive(false);
|
||||
me->SetImmuneToAll(false);
|
||||
me->SetCanFly(false);
|
||||
me->SetDisableGravity(false);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
DoZoneInCombat(nullptr, 150.0f);
|
||||
}
|
||||
|
||||
void SpellHitTarget(Unit* target, SpellInfo const* spell) override
|
||||
@@ -1140,43 +1170,51 @@ public:
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!me->isActiveObject())
|
||||
if (!UpdateVictim() && !_isEventInProgress)
|
||||
return;
|
||||
|
||||
UpdateVictim();
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
switch (events.ExecuteEvent())
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_SVALNA_START:
|
||||
Talk(SAY_SVALNA_EVENT_START);
|
||||
break;
|
||||
case EVENT_SVALNA_RESURRECT:
|
||||
Talk(SAY_SVALNA_RESURRECT_CAPTAINS);
|
||||
me->CastSpell(me, SPELL_REVIVE_CHAMPION, false);
|
||||
break;
|
||||
case EVENT_SVALNA_COMBAT:
|
||||
Talk(SAY_SVALNA_AGGRO);
|
||||
break;
|
||||
case EVENT_IMPALING_SPEAR:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, false, -SPELL_IMPALING_SPEAR))
|
||||
{
|
||||
DoCast(me, SPELL_AETHER_SHIELD);
|
||||
me->AddAura(70203, me);
|
||||
DoCast(target, SPELL_IMPALING_SPEAR);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_IMPALING_SPEAR, 20s, 25s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SVALNA_START:
|
||||
Talk(SAY_SVALNA_EVENT_START);
|
||||
break;
|
||||
case EVENT_SVALNA_RESURRECT:
|
||||
Talk(SAY_SVALNA_RESURRECT_CAPTAINS);
|
||||
me->CastSpell(me, SPELL_REVIVE_CHAMPION, false);
|
||||
break;
|
||||
case EVENT_SVALNA_COMBAT:
|
||||
me->SetReactState(REACT_DEFENSIVE);
|
||||
Talk(SAY_SVALNA_AGGRO);
|
||||
break;
|
||||
case EVENT_IMPALING_SPEAR:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, false, -SPELL_IMPALING_SPEAR))
|
||||
{
|
||||
DoCast(me, SPELL_AETHER_SHIELD);
|
||||
me->AddAura(70203, me);
|
||||
DoCast(target, SPELL_IMPALING_SPEAR);
|
||||
}
|
||||
events.ScheduleEvent(EVENT_IMPALING_SPEAR, 20s, 25s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
bool _isEventInProgress;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
|
||||
@@ -113,8 +113,6 @@ Position const FirstWaveLocations[FIRST_WAVE_SIZE] =
|
||||
{ 481.388f, -507.109f, 104.724f, 3.26377f },
|
||||
};
|
||||
|
||||
Position const SecondaryWavesInitialPoint = { 478.743f, -505.576f, 104.724f };
|
||||
|
||||
enum GraufPoints
|
||||
{
|
||||
POINT_BREACH = 0,
|
||||
@@ -122,11 +120,19 @@ enum GraufPoints
|
||||
POINT_RIGHT = 2,
|
||||
};
|
||||
|
||||
uint32 const PATH_INITIAL = 2689300;
|
||||
uint32 const PATH_RIGHT = 2689301;
|
||||
uint32 const PATH_LEFT = 2689302;
|
||||
enum GraufPaths
|
||||
{
|
||||
PATH_INITIAL = 2689300,
|
||||
PATH_RIGHT = 2689301,
|
||||
PATH_LEFT = 2689302,
|
||||
PATH_BREACH_RIGHT = 2689303,
|
||||
PATH_BREACH_LEFT = 2689304,
|
||||
PATH_GAUNTLET_ADDS = 2669000,
|
||||
};
|
||||
|
||||
float const BreachFacing = 2.670354f;
|
||||
float const BreathFacingRight = 3.124139f;
|
||||
float const BreathFacingLeft = 3.228859f;
|
||||
|
||||
enum Events
|
||||
{
|
||||
@@ -139,6 +145,7 @@ enum Events
|
||||
// Grauf
|
||||
EVENT_GRAUF_START = 10,
|
||||
EVENT_GRAUF_LEAVE_BREACH = 11,
|
||||
EVENT_GRAUF_BREATH_START = 12,
|
||||
EVENT_GRAUF_REMOVE_AURA = 13,
|
||||
};
|
||||
|
||||
@@ -193,7 +200,10 @@ public:
|
||||
case NPC_YMIRJAR_WITCH_DOCTOR:
|
||||
case NPC_YMIRJAR_HARPOONER:
|
||||
if (_firstWaveSummoned)
|
||||
summon->GetMotionMaster()->MovePoint(1, SecondaryWavesInitialPoint);
|
||||
{
|
||||
summon->LoadPath(PATH_GAUNTLET_ADDS);
|
||||
summon->GetMotionMaster()->MoveWaypoint(PATH_GAUNTLET_ADDS, false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -404,6 +414,7 @@ public:
|
||||
_summons.DespawnAll();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetSpeedRate(MOVE_RUN, 2.5f);
|
||||
_flyingToSide = false;
|
||||
}
|
||||
|
||||
void DoAction(int32 param) override
|
||||
@@ -430,9 +441,19 @@ public:
|
||||
{
|
||||
if (type == ESCORT_MOTION_TYPE && me->movespline->Finalized())
|
||||
{
|
||||
me->SetFacingTo(BreachFacing);
|
||||
Talk(EMOTE_ON_RANGE);
|
||||
_events.ScheduleEvent(EVENT_GRAUF_LEAVE_BREACH, 10s);
|
||||
if (_flyingToSide)
|
||||
{
|
||||
_flyingToSide = false;
|
||||
me->SetFacingTo(_lastSide == POINT_LEFT ? BreathFacingLeft : BreathFacingRight);
|
||||
Talk(EMOTE_DEEP_BREATH);
|
||||
_events.ScheduleEvent(EVENT_GRAUF_BREATH_START, 2s);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->SetFacingTo(BreachFacing);
|
||||
Talk(EMOTE_ON_RANGE);
|
||||
_events.ScheduleEvent(EVENT_GRAUF_LEAVE_BREACH, 10s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,16 +464,20 @@ public:
|
||||
{
|
||||
case EVENT_GRAUF_LEAVE_BREACH:
|
||||
_lastSide = RAND(POINT_LEFT, POINT_RIGHT);
|
||||
me->GetMotionMaster()->MovePath(_lastSide == POINT_LEFT ? PATH_LEFT : PATH_RIGHT, FORCED_MOVEMENT_RUN);
|
||||
|
||||
if (_lastSide == POINT_LEFT)
|
||||
DoCast(me, SPELL_FREEZING_CLOUD_LEFT_PERIODIC);
|
||||
else
|
||||
DoCast(me, SPELL_FREEZING_CLOUD_RIGHT_PERIODIC);
|
||||
|
||||
_flyingToSide = true;
|
||||
me->GetMotionMaster()->MovePath(
|
||||
_lastSide == POINT_LEFT ? PATH_BREACH_LEFT : PATH_BREACH_RIGHT,
|
||||
FORCED_MOVEMENT_RUN);
|
||||
break;
|
||||
case EVENT_GRAUF_BREATH_START:
|
||||
me->GetMotionMaster()->MovePath(
|
||||
_lastSide == POINT_LEFT ? PATH_LEFT : PATH_RIGHT,
|
||||
FORCED_MOVEMENT_RUN);
|
||||
DoCast(me, _lastSide == POINT_LEFT
|
||||
? SPELL_FREEZING_CLOUD_LEFT_PERIODIC
|
||||
: SPELL_FREEZING_CLOUD_RIGHT_PERIODIC);
|
||||
if (Creature* skadi = _instance->GetCreature(DATA_SKADI_THE_RUTHLESS))
|
||||
skadi->AI()->DoAction(ACTION_DRAKE_BREATH);
|
||||
|
||||
_events.ScheduleEvent(EVENT_GRAUF_REMOVE_AURA, 10s);
|
||||
break;
|
||||
case EVENT_GRAUF_REMOVE_AURA:
|
||||
@@ -480,6 +505,7 @@ public:
|
||||
EventMap _events;
|
||||
SummonList _summons;
|
||||
uint8 _lastSide = POINT_LEFT;
|
||||
bool _flyingToSide = false;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -507,7 +533,7 @@ class spell_skadi_launch_harpoon : public SpellScript
|
||||
}
|
||||
};
|
||||
|
||||
// 50255 - Poisoned Spear
|
||||
// 50255, 59331 - Poisoned Spear
|
||||
class spell_skadi_poisoned_spear : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_skadi_poisoned_spear);
|
||||
|
||||
@@ -157,8 +157,7 @@ public:
|
||||
{
|
||||
if (pSummoned)
|
||||
{
|
||||
pSummoned->GetMotionMaster()->MoveFollow(me, 0.0f, 0.0f);
|
||||
pSummoned->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
pSummoned->GetMotionMaster()->MoveFollow(me, 0.0f, 0.0f, MOTION_SLOT_ACTIVE, true, false);
|
||||
spheres.Summon(pSummoned);
|
||||
if (pInstance)
|
||||
pInstance->SetGuidData(DATA_ADD_TRASH_MOB, pSummoned->GetGUID());
|
||||
|
||||
@@ -239,50 +239,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/*######
|
||||
## npc_iruk
|
||||
######*/
|
||||
|
||||
enum Iruk
|
||||
{
|
||||
GOSSIP_MENU_ID_NPC_IRUK = 9280,
|
||||
GOSSIP_OPTION_SEARCH_CORPSE = 0,
|
||||
NPC_TEXT_THIS_YOUNG_TUSKARR = 12585,
|
||||
|
||||
QUEST_SPIRITS_WATCH_OVER_US = 11961,
|
||||
|
||||
SPELL_CREATE_TOTEM_OF_ISSLIRUK = 46816
|
||||
};
|
||||
|
||||
class npc_iruk : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_iruk() : CreatureScript("npc_iruk") { }
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
if (player->GetQuestStatus(QUEST_SPIRITS_WATCH_OVER_US) == QUEST_STATUS_INCOMPLETE)
|
||||
AddGossipItemFor(player, GOSSIP_MENU_ID_NPC_IRUK, GOSSIP_OPTION_SEARCH_CORPSE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
|
||||
SendGossipMenuFor(player, NPC_TEXT_THIS_YOUNG_TUSKARR, creature->GetGUID());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
|
||||
if (action == GOSSIP_ACTION_INFO_DEF + 1)
|
||||
{
|
||||
player->CastSpell(player, SPELL_CREATE_TOTEM_OF_ISSLIRUK, true);
|
||||
CloseGossipMenuFor(player);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/*######
|
||||
## npc_nerubar_victim
|
||||
######*/
|
||||
@@ -1379,7 +1335,6 @@ void AddSC_borean_tundra()
|
||||
RegisterSpellScript(spell_q11919_q11940_drake_hunt_aura);
|
||||
new npc_sinkhole_kill_credit();
|
||||
new npc_khunok_the_behemoth();
|
||||
new npc_iruk();
|
||||
new npc_nerubar_victim();
|
||||
new npc_lurgglbr();
|
||||
RegisterSpellScript(spell_arcane_chains_character_force_cast);
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "Player.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptedEscortAI.h"
|
||||
#include "ScriptedGossip.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellScript.h"
|
||||
|
||||
@@ -227,73 +226,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/*######
|
||||
## npc_razael_and_lyana
|
||||
######*/
|
||||
|
||||
enum Razael
|
||||
{
|
||||
QUEST_REPORTS_FROM_THE_FIELD = 11221,
|
||||
NPC_RAZAEL = 23998,
|
||||
NPC_LYANA = 23778,
|
||||
GOSSIP_TEXTID_RAZAEL1 = 11562,
|
||||
GOSSIP_TEXTID_RAZAEL2 = 11564,
|
||||
GOSSIP_TEXTID_LYANA1 = 11586,
|
||||
GOSSIP_TEXTID_LYANA2 = 11588
|
||||
};
|
||||
|
||||
class npc_razael_and_lyana : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_razael_and_lyana() : CreatureScript("npc_razael_and_lyana") { }
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
if (creature->IsQuestGiver())
|
||||
player->PrepareQuestMenu(creature->GetGUID());
|
||||
|
||||
if (player->GetQuestStatus(QUEST_REPORTS_FROM_THE_FIELD) == QUEST_STATUS_INCOMPLETE)
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_RAZAEL:
|
||||
if (!player->GetReqKillOrCastCurrentCount(QUEST_REPORTS_FROM_THE_FIELD, NPC_RAZAEL))
|
||||
{
|
||||
AddGossipItemFor(player, 8870, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
SendGossipMenuFor(player, GOSSIP_TEXTID_RAZAEL1, creature->GetGUID());
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case NPC_LYANA:
|
||||
if (!player->GetReqKillOrCastCurrentCount(QUEST_REPORTS_FROM_THE_FIELD, NPC_LYANA))
|
||||
{
|
||||
AddGossipItemFor(player, 8879, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
|
||||
SendGossipMenuFor(player, GOSSIP_TEXTID_LYANA1, creature->GetGUID());
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
SendGossipMenuFor(player, player->GetGossipTextId(creature), creature->GetGUID());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
switch (action)
|
||||
{
|
||||
case GOSSIP_ACTION_INFO_DEF + 1:
|
||||
SendGossipMenuFor(player, GOSSIP_TEXTID_RAZAEL2, creature->GetGUID());
|
||||
player->TalkedToCreature(NPC_RAZAEL, creature->GetGUID());
|
||||
break;
|
||||
case GOSSIP_ACTION_INFO_DEF + 2:
|
||||
SendGossipMenuFor(player, GOSSIP_TEXTID_LYANA2, creature->GetGUID());
|
||||
player->TalkedToCreature(NPC_LYANA, creature->GetGUID());
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
enum RodinLightningSpells
|
||||
{
|
||||
SPELL_RODIN_LIGHTNING_START = 44787,
|
||||
@@ -490,7 +422,6 @@ void AddSC_howling_fjord()
|
||||
new npc_attracted_reef_bull();
|
||||
new npc_apothecary_hanes();
|
||||
new npc_plaguehound_tracker();
|
||||
new npc_razael_and_lyana();
|
||||
RegisterCreatureAI(npc_rodin_lightning_enabler);
|
||||
RegisterSpellScript(spell_hawk_hunting);
|
||||
RegisterSpellScript(spell_the_cleansing_shrine_cast);
|
||||
|
||||
@@ -387,64 +387,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/*######
|
||||
## avatar_of_freya
|
||||
######*/
|
||||
|
||||
enum Freya
|
||||
{
|
||||
QUEST_FREYA_PACT = 12621,
|
||||
|
||||
SPELL_FREYA_CONVERSATION = 52045,
|
||||
|
||||
GOSSIP_AVATAR_MENU_1 = 9720,
|
||||
GOSSIP_AVATAR_MENU_2 = 9721,
|
||||
GOSSIP_AVATAR_MENU_3 = 9722,
|
||||
|
||||
GOSSIP_TEXTID_AVATAR_1 = 13303,
|
||||
GOSSIP_TEXTID_AVATAR_2 = 13304,
|
||||
GOSSIP_TEXTID_AVATAR_3 = 13305,
|
||||
};
|
||||
|
||||
class npc_avatar_of_freya : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_avatar_of_freya() : CreatureScript("npc_avatar_of_freya") { }
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
if (creature->IsQuestGiver())
|
||||
player->PrepareQuestMenu(creature->GetGUID());
|
||||
|
||||
if (player->GetQuestStatus(QUEST_FREYA_PACT) == QUEST_STATUS_INCOMPLETE)
|
||||
AddGossipItemFor(player, GOSSIP_AVATAR_MENU_1, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
|
||||
SendGossipMenuFor(player, GOSSIP_TEXTID_AVATAR_1, creature);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
switch (action)
|
||||
{
|
||||
case GOSSIP_ACTION_INFO_DEF+1:
|
||||
AddGossipItemFor(player, GOSSIP_AVATAR_MENU_2, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
|
||||
SendGossipMenuFor(player, GOSSIP_TEXTID_AVATAR_2, creature);
|
||||
break;
|
||||
case GOSSIP_ACTION_INFO_DEF+2:
|
||||
AddGossipItemFor(player, GOSSIP_AVATAR_MENU_3, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
|
||||
SendGossipMenuFor(player, GOSSIP_TEXTID_AVATAR_3, creature);
|
||||
break;
|
||||
case GOSSIP_ACTION_INFO_DEF+3:
|
||||
player->CastSpell(player, SPELL_FREYA_CONVERSATION, true);
|
||||
CloseGossipMenuFor(player);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/*######
|
||||
## npc_bushwhacker
|
||||
######*/
|
||||
@@ -1187,7 +1129,6 @@ void AddSC_sholazar_basin()
|
||||
new go_pressure_valve();
|
||||
new go_brazier();
|
||||
new npc_vekjik();
|
||||
new npc_avatar_of_freya();
|
||||
new npc_bushwhacker();
|
||||
new npc_engineer_helice();
|
||||
new npc_adventurous_dwarf();
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "ScriptedEscortAI.h"
|
||||
#include "ScriptedGossip.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellScriptLoader.h"
|
||||
@@ -339,56 +338,6 @@ class spell_q13007_iron_colossus : public SpellScript
|
||||
}
|
||||
};
|
||||
|
||||
/*######
|
||||
## npc_roxi_ramrocket
|
||||
######*/
|
||||
|
||||
enum RoxiRamrocket
|
||||
{
|
||||
SPELL_MECHANO_HOG = 60866,
|
||||
SPELL_MEKGINEERS_CHOPPER = 60867
|
||||
};
|
||||
|
||||
class npc_roxi_ramrocket : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_roxi_ramrocket() : CreatureScript("npc_roxi_ramrocket") { }
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
//Quest Menu
|
||||
if (creature->IsQuestGiver())
|
||||
player->PrepareQuestMenu(creature->GetGUID());
|
||||
|
||||
//Trainer Menu
|
||||
if (creature->IsTrainer())
|
||||
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, GOSSIP_TEXT_TRAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRAIN);
|
||||
|
||||
//Vendor Menu
|
||||
if (creature->IsVendor())
|
||||
if (player->HasSpell(SPELL_MECHANO_HOG) || player->HasSpell(SPELL_MEKGINEERS_CHOPPER))
|
||||
AddGossipItemFor(player, GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
|
||||
|
||||
SendGossipMenuFor(player, player->GetGossipTextId(creature), creature->GetGUID());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
switch (action)
|
||||
{
|
||||
case GOSSIP_ACTION_TRAIN:
|
||||
player->GetSession()->SendTrainerList(creature);
|
||||
break;
|
||||
case GOSSIP_ACTION_TRADE:
|
||||
player->GetSession()->SendListInventory(creature->GetGUID());
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/*######
|
||||
## npc_brunnhildar_prisoner
|
||||
######*/
|
||||
@@ -1386,7 +1335,6 @@ void AddSC_storm_peaks()
|
||||
new npc_iron_watcher();
|
||||
new npc_time_lost_proto_drake();
|
||||
RegisterSpellScript(spell_q13007_iron_colossus);
|
||||
new npc_roxi_ramrocket();
|
||||
new npc_brunnhildar_prisoner();
|
||||
new npc_freed_protodrake();
|
||||
new npc_icefang();
|
||||
|
||||
@@ -83,6 +83,9 @@ public:
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
if (_defeated)
|
||||
return;
|
||||
|
||||
faction_Timer = 8000;
|
||||
envelopingWinds_Timer = 9000;
|
||||
shock_Timer = 5000;
|
||||
@@ -93,6 +96,15 @@ public:
|
||||
Talk(SAY_SUMMON);
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
if (_defeated)
|
||||
{
|
||||
Talk(SAY_FREE);
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_QUESTGIVER);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (faction_Timer)
|
||||
@@ -110,12 +122,11 @@ public:
|
||||
|
||||
if (HealthBelowPct(30))
|
||||
{
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_QUESTGIVER);
|
||||
_defeated = true;
|
||||
me->RemoveAllAuras();
|
||||
me->GetThreatMgr().ClearAllThreat();
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
me->CombatStop(true);
|
||||
Talk(SAY_FREE);
|
||||
me->GetThreatMgr().ClearAllThreat();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -140,6 +151,7 @@ public:
|
||||
uint32 faction_Timer;
|
||||
uint32 envelopingWinds_Timer;
|
||||
uint32 shock_Timer;
|
||||
bool _defeated = false;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "Group.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptedGossip.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellScriptLoader.h"
|
||||
|
||||
@@ -657,98 +656,6 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
/*######
|
||||
## npc_drake_dealer_hurlunk
|
||||
######*/
|
||||
|
||||
class npc_drake_dealer_hurlunk : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_drake_dealer_hurlunk() : CreatureScript("npc_drake_dealer_hurlunk") { }
|
||||
|
||||
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
if (action == GOSSIP_ACTION_TRADE)
|
||||
player->GetSession()->SendListInventory(creature->GetGUID());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
if (creature->IsVendor() && player->GetReputationRank(1015) == REP_EXALTED)
|
||||
AddGossipItemFor(player, GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
|
||||
|
||||
SendGossipMenuFor(player, player->GetGossipTextId(creature), creature->GetGUID());
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/*######
|
||||
## npc_flanis_swiftwing_and_kagrosh
|
||||
######*/
|
||||
|
||||
enum Flanis : uint32
|
||||
{
|
||||
QUEST_THE_FATE_OF_FLANIS = 10583,
|
||||
ITEM_FLAUNISS_PACK = 30658,
|
||||
GOSSIP_MENU_FLANIS = 8356,
|
||||
};
|
||||
|
||||
enum Kagrosh : uint32
|
||||
{
|
||||
QUEST_THE_FATE_OF_KAGROSH = 10601,
|
||||
ITEM_KAGROSHS_PACK = 30659,
|
||||
GOSSIP_MENU_KAGROSH = 8371,
|
||||
};
|
||||
|
||||
class npcs_flanis_swiftwing_and_kagrosh : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npcs_flanis_swiftwing_and_kagrosh() : CreatureScript("npcs_flanis_swiftwing_and_kagrosh") { }
|
||||
|
||||
bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
if (action == GOSSIP_ACTION_INFO_DEF + 1)
|
||||
{
|
||||
ItemPosCountVec dest;
|
||||
uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_FLAUNISS_PACK, 1, nullptr);
|
||||
if (msg == EQUIP_ERR_OK)
|
||||
{
|
||||
player->StoreNewItem(dest, ITEM_FLAUNISS_PACK, true);
|
||||
}
|
||||
}
|
||||
if (action == GOSSIP_ACTION_INFO_DEF + 2)
|
||||
{
|
||||
ItemPosCountVec dest;
|
||||
uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_KAGROSHS_PACK, 1, nullptr);
|
||||
if (msg == EQUIP_ERR_OK)
|
||||
{
|
||||
player->StoreNewItem(dest, ITEM_KAGROSHS_PACK, true);
|
||||
}
|
||||
}
|
||||
|
||||
CloseGossipMenuFor(player);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
if (player->GetQuestStatus(QUEST_THE_FATE_OF_FLANIS) == QUEST_STATUS_INCOMPLETE && !player->HasItemCount(ITEM_FLAUNISS_PACK, 1, true))
|
||||
AddGossipItemFor(player, GOSSIP_MENU_FLANIS, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
if (player->GetQuestStatus(QUEST_THE_FATE_OF_KAGROSH) == QUEST_STATUS_INCOMPLETE && !player->HasItemCount(ITEM_KAGROSHS_PACK, 1, true))
|
||||
AddGossipItemFor(player, GOSSIP_MENU_KAGROSH, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
|
||||
|
||||
SendGossipMenuFor(player, player->GetGossipTextId(creature), creature->GetGUID());
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/*####
|
||||
# npc_karynaku
|
||||
####*/
|
||||
@@ -2219,8 +2126,6 @@ void AddSC_shadowmoon_valley()
|
||||
new npc_mature_netherwing_drake();
|
||||
RegisterCreatureAI(npc_enslaved_netherwing_drake);
|
||||
new npc_dragonmaw_peon();
|
||||
new npc_drake_dealer_hurlunk();
|
||||
new npcs_flanis_swiftwing_and_kagrosh();
|
||||
new npc_karynaku();
|
||||
new npc_lord_illidan_stormrage();
|
||||
new go_crystal_prison();
|
||||
|
||||
@@ -20,101 +20,6 @@
|
||||
#include "Player.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptedEscortAI.h"
|
||||
#include "ScriptedGossip.h"
|
||||
|
||||
/*
|
||||
##################################################
|
||||
Shattrath City Flask Vendors provides flasks to people exalted with 3 fActions:
|
||||
Haldor the Compulsive
|
||||
Arcanist Xorith
|
||||
Both sell special flasks for use in Outlands 25man raids only,
|
||||
purchasable for one Mark of Illidari each
|
||||
Purchase requires exalted reputation with Scryers/Aldor, Cenarion Expedition and The Sha'tar
|
||||
##################################################
|
||||
*/
|
||||
|
||||
class npc_shattrathflaskvendors : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_shattrathflaskvendors() : CreatureScript("npc_shattrathflaskvendors") { }
|
||||
|
||||
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
if (action == GOSSIP_ACTION_TRADE)
|
||||
player->GetSession()->SendListInventory(creature->GetGUID());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
if (creature->GetEntry() == 23484)
|
||||
{
|
||||
// Aldor vendor
|
||||
if (creature->IsVendor() && (player->GetReputationRank(932) == REP_EXALTED) && (player->GetReputationRank(935) == REP_EXALTED) && (player->GetReputationRank(942) == REP_EXALTED))
|
||||
{
|
||||
AddGossipItemFor(player, GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
|
||||
SendGossipMenuFor(player, 11085, creature->GetGUID());
|
||||
}
|
||||
else
|
||||
{
|
||||
SendGossipMenuFor(player, 11083, creature->GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
if (creature->GetEntry() == 23483)
|
||||
{
|
||||
// Scryers vendor
|
||||
if (creature->IsVendor() && (player->GetReputationRank(934) == REP_EXALTED) && (player->GetReputationRank(935) == REP_EXALTED) && (player->GetReputationRank(942) == REP_EXALTED))
|
||||
{
|
||||
AddGossipItemFor(player, GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
|
||||
SendGossipMenuFor(player, 11085, creature->GetGUID());
|
||||
}
|
||||
else
|
||||
{
|
||||
SendGossipMenuFor(player, 11084, creature->GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/*######
|
||||
# npc_zephyr
|
||||
######*/
|
||||
|
||||
enum Zephyr : int32
|
||||
{
|
||||
GOSSIP_MENU_ZEPHYR = 9205,
|
||||
SPELL_TELEPORT_CAVERNS_OF_TIME = 37778,
|
||||
};
|
||||
|
||||
class npc_zephyr : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_zephyr() : CreatureScript("npc_zephyr") { }
|
||||
|
||||
bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
ClearGossipMenuFor(player);
|
||||
if (action == GOSSIP_ACTION_INFO_DEF + 1)
|
||||
player->CastSpell(player, SPELL_TELEPORT_CAVERNS_OF_TIME, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
if (player->GetReputationRank(989) >= REP_REVERED)
|
||||
AddGossipItemFor(player, GOSSIP_MENU_ZEPHYR, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
|
||||
SendGossipMenuFor(player, player->GetGossipTextId(creature), creature->GetGUID());
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/*######
|
||||
# npc_kservant
|
||||
@@ -415,8 +320,6 @@ struct npc_shattrath_daily_quest : public NullCreatureAI
|
||||
|
||||
void AddSC_shattrath_city()
|
||||
{
|
||||
new npc_shattrathflaskvendors();
|
||||
new npc_zephyr();
|
||||
new npc_kservant();
|
||||
RegisterCreatureAI(npc_shattrath_daily_quest);
|
||||
}
|
||||
|
||||
@@ -314,11 +314,7 @@ public:
|
||||
|
||||
struct npc_training_dummy : NullCreatureAI
|
||||
{
|
||||
npc_training_dummy(Creature* creature) : NullCreatureAI(creature)
|
||||
{
|
||||
// TODO: Remove once WorldObject casting is ported
|
||||
me->SetIsCombatDisallowed(false);
|
||||
}
|
||||
npc_training_dummy(Creature* creature) : NullCreatureAI(creature) { }
|
||||
|
||||
void JustEnteredCombat(Unit* who) override
|
||||
{
|
||||
@@ -363,8 +359,6 @@ struct npc_target_dummy : NullCreatureAI
|
||||
{
|
||||
npc_target_dummy(Creature* creature) : NullCreatureAI(creature)
|
||||
{
|
||||
// TODO: Remove once WorldObject casting is ported
|
||||
me->SetIsCombatDisallowed(false);
|
||||
_deathTimer = 15s;
|
||||
}
|
||||
|
||||
|
||||
@@ -1360,8 +1360,6 @@ inline constexpr uint64 IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK =
|
||||
(UI64LIT(1) << MECHANIC_SNARE) |
|
||||
(UI64LIT(1) << MECHANIC_STUN) |
|
||||
(UI64LIT(1) << MECHANIC_FREEZE) |
|
||||
(UI64LIT(1) << MECHANIC_SILENCE) |
|
||||
(UI64LIT(1) << MECHANIC_DISARM) |
|
||||
(UI64LIT(1) << MECHANIC_KNOCKOUT) |
|
||||
(UI64LIT(1) << MECHANIC_POLYMORPH) |
|
||||
(UI64LIT(1) << MECHANIC_BANISH) |
|
||||
|
||||
Reference in New Issue
Block a user