Make Lady Liadrin's Midnight gossip do the summon, movie, and skip.
Fix skyriding
This commit is contained in:
@@ -36101,3 +36101,17 @@ bool Player::IsTankPlayer()
|
||||
{
|
||||
return GetRoleForGroup() == ROLE_TANK;
|
||||
}
|
||||
|
||||
void Player::UpdateDynamicFlight(bool apply)
|
||||
{
|
||||
if (apply)
|
||||
{
|
||||
if (!HasAuraType(SPELL_AURA_ADV_FLYING))
|
||||
AddAura(SPELL_DYNAMIC_FLIGHT, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (HasAuraType(SPELL_AURA_ADV_FLYING))
|
||||
RemoveAura(SPELL_DYNAMIC_FLIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1854,6 +1854,12 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
|
||||
void ResetSeasonalQuestStatus(uint16 event_id, time_t eventStartTime);
|
||||
|
||||
//WowCommunity
|
||||
enum DragonRidingSpells
|
||||
{
|
||||
SPELL_DYNAMIC_FLIGHT = 406095,
|
||||
SPELL_DRAGONRIDER_ENERGY = 372771
|
||||
};
|
||||
|
||||
void UpdateWeeklyRewardsPeriod();
|
||||
static uint32 GetRoleBySpecializationId(uint32 specializationId);
|
||||
uint32 GetRoleForGroup() const;
|
||||
@@ -3966,6 +3972,7 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
|
||||
void ForceCompleteQuest(uint32 quest_id);
|
||||
int32 GetQuestObjectiveProgress(uint32 questId, int8 storageIndex) const;
|
||||
void PlayConversation(uint32 conversationId);
|
||||
void UpdateDynamicFlight(bool apply = false);
|
||||
//WowCommunity
|
||||
};
|
||||
|
||||
|
||||
@@ -9247,6 +9247,10 @@ void Unit::SetFlightCapabilityID(int32 flightCapabilityId, bool clientUpdate)
|
||||
|
||||
SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::FlightCapabilityID), flightCapabilityId);
|
||||
|
||||
// GlideEventSpeedDivisor scales movement speed when the client evaluates which GlideEvent to play.
|
||||
// 1.0 is the neutral default; 0.0 would cause divide-by-zero on the client.
|
||||
SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::GlideEventSpeedDivisor), 1.0f);
|
||||
|
||||
UpdateAdvFlyingSpeed(ADV_FLYING_AIR_FRICTION, clientUpdate);
|
||||
UpdateAdvFlyingSpeed(ADV_FLYING_MAX_VEL, clientUpdate);
|
||||
UpdateAdvFlyingSpeed(ADV_FLYING_LIFT_COEFFICIENT, clientUpdate);
|
||||
@@ -9262,7 +9266,7 @@ void Unit::SetFlightCapabilityID(int32 flightCapabilityId, bool clientUpdate)
|
||||
UpdateAdvFlyingSpeed(ADV_FLYING_LAUNCH_SPEED_COEFFICIENT, clientUpdate);
|
||||
}
|
||||
|
||||
void Unit::UpdateAdvFlyingSpeed(AdvFlyingRateTypeSingle speedType, bool clientUpdate)
|
||||
void Unit::UpdateAdvFlyingSpeed(AdvFlyingRateTypeSingle speedType, bool clientUpdate, bool force /*= false*/)
|
||||
{
|
||||
FlightCapabilityEntry const* flightCapabilityEntry = sFlightCapabilityStore.LookupEntry(GetFlightCapabilityID());
|
||||
if (!flightCapabilityEntry)
|
||||
@@ -9305,7 +9309,7 @@ void Unit::UpdateAdvFlyingSpeed(AdvFlyingRateTypeSingle speedType, bool clientUp
|
||||
ApplyPct(newValue, pos);
|
||||
}
|
||||
|
||||
if (m_advFlyingSpeed[speedType] == newValue)
|
||||
if (!force && m_advFlyingSpeed[speedType] == newValue)
|
||||
return;
|
||||
|
||||
m_advFlyingSpeed[speedType] = newValue;
|
||||
@@ -9323,7 +9327,7 @@ void Unit::UpdateAdvFlyingSpeed(AdvFlyingRateTypeSingle speedType, bool clientUp
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::UpdateAdvFlyingSpeed(AdvFlyingRateTypeRange speedType, bool clientUpdate)
|
||||
void Unit::UpdateAdvFlyingSpeed(AdvFlyingRateTypeRange speedType, bool clientUpdate, bool force /*= false*/)
|
||||
{
|
||||
FlightCapabilityEntry const* flightCapabilityEntry = sFlightCapabilityStore.LookupEntry(GetFlightCapabilityID());
|
||||
if (!flightCapabilityEntry)
|
||||
@@ -9362,7 +9366,7 @@ void Unit::UpdateAdvFlyingSpeed(AdvFlyingRateTypeRange speedType, bool clientUpd
|
||||
}
|
||||
}
|
||||
|
||||
if (m_advFlyingSpeed[speedType] == min && m_advFlyingSpeed[speedType + 1] == max)
|
||||
if (!force && m_advFlyingSpeed[speedType] == min && m_advFlyingSpeed[speedType + 1] == max)
|
||||
return;
|
||||
|
||||
m_advFlyingSpeed[speedType] = min;
|
||||
@@ -15785,3 +15789,25 @@ void Unit::RestoreDeferredDashGravity()
|
||||
|
||||
SetDisableGravity(false);
|
||||
}
|
||||
|
||||
void Unit::SendAdvFlyingSpeedBurst()
|
||||
{
|
||||
// The complete FlightCapability parameter burst, in the retail order (sniff 66709: sent on every
|
||||
// mount-engage, strictly AFTER SMSG_MOVE_SET_CAN_ADV_FLY). The client only accepts/keeps the
|
||||
// physics params once the adv-fly state is enabled, and the change-suppression in
|
||||
// UpdateAdvFlyingSpeed would swallow most of it - m_advFlyingSpeed is pre-seeded with
|
||||
// FlightCapability fallback row 1 - so force all 13.
|
||||
UpdateAdvFlyingSpeed(ADV_FLYING_AIR_FRICTION, true, true);
|
||||
UpdateAdvFlyingSpeed(ADV_FLYING_MAX_VEL, true, true);
|
||||
UpdateAdvFlyingSpeed(ADV_FLYING_LIFT_COEFFICIENT, true, true);
|
||||
UpdateAdvFlyingSpeed(ADV_FLYING_DOUBLE_JUMP_VEL_MOD, true, true);
|
||||
UpdateAdvFlyingSpeed(ADV_FLYING_GLIDE_START_MIN_HEIGHT, true, true);
|
||||
UpdateAdvFlyingSpeed(ADV_FLYING_ADD_IMPULSE_MAX_SPEED, true, true);
|
||||
UpdateAdvFlyingSpeed(ADV_FLYING_BANKING_RATE, true, true);
|
||||
UpdateAdvFlyingSpeed(ADV_FLYING_PITCHING_RATE_DOWN, true, true);
|
||||
UpdateAdvFlyingSpeed(ADV_FLYING_PITCHING_RATE_UP, true, true);
|
||||
UpdateAdvFlyingSpeed(ADV_FLYING_TURN_VELOCITY_THRESHOLD, true, true);
|
||||
UpdateAdvFlyingSpeed(ADV_FLYING_SURFACE_FRICTION, true, true);
|
||||
UpdateAdvFlyingSpeed(ADV_FLYING_OVER_MAX_DECELERATION, true, true);
|
||||
UpdateAdvFlyingSpeed(ADV_FLYING_LAUNCH_SPEED_COEFFICIENT, true, true);
|
||||
}
|
||||
|
||||
@@ -1752,8 +1752,9 @@ class TC_GAME_API Unit : public WorldObject
|
||||
float GetAdvFlyingSpeed(AdvFlyingRateTypeSingle speedType) const { return m_advFlyingSpeed[speedType]; }
|
||||
float GetAdvFlyingSpeedMin(AdvFlyingRateTypeRange speedType) const { return m_advFlyingSpeed[speedType]; }
|
||||
float GetAdvFlyingSpeedMax(AdvFlyingRateTypeRange speedType) const { return m_advFlyingSpeed[speedType + 1]; }
|
||||
void UpdateAdvFlyingSpeed(AdvFlyingRateTypeSingle speedType, bool clientUpdate);
|
||||
void UpdateAdvFlyingSpeed(AdvFlyingRateTypeRange speedType, bool clientUpdate);
|
||||
void UpdateAdvFlyingSpeed(AdvFlyingRateTypeSingle speedType, bool clientUpdate, bool force = false);
|
||||
void UpdateAdvFlyingSpeed(AdvFlyingRateTypeRange speedType, bool clientUpdate, bool force = false);
|
||||
void SendAdvFlyingSpeedBurst();
|
||||
|
||||
void FollowerAdded(AbstractFollower* f);
|
||||
void FollowerRemoved(AbstractFollower* f);
|
||||
|
||||
@@ -2917,6 +2917,16 @@ void AuraEffect::HandleAuraMounted(AuraApplication const* aurApp, uint8 mode, bo
|
||||
target->SetCanAdvFly(true);
|
||||
target->SetCanDoubleJump(true);
|
||||
target->SetFlightCapabilityID(1, true);
|
||||
// The client keeps adv-fly physics params only if they arrive after
|
||||
// SET_CAN_ADV_FLY - force the complete burst now that it is enabled.
|
||||
target->SendAdvFlyingSpeedBurst();
|
||||
// Apply the Dynamic Flight aura - retail receives it from the selected
|
||||
// mount capability; if a generic capability was chosen instead, drop its
|
||||
// speed aura so mounted speed comes only from 406095.
|
||||
if (MountCapabilityEntry const* mountCapability = sMountCapabilityStore.LookupEntry(GetAmountAsInt()))
|
||||
if (mountCapability->ModSpellAuraID > 0 && uint32(mountCapability->ModSpellAuraID) != SPELL_DYNAMIC_FLIGHT)
|
||||
target->RemoveAurasDueToSpell(mountCapability->ModSpellAuraID, target->GetGUID());
|
||||
player->UpdateDynamicFlight(true);
|
||||
// Cast Vigor aura - required by CasterAuraSpell check for active abilities
|
||||
if (!player->HasAura(372773))
|
||||
player->CastSpell(player, 372773, true);
|
||||
@@ -2953,6 +2963,9 @@ void AuraEffect::HandleAuraMounted(AuraApplication const* aurApp, uint8 mode, bo
|
||||
target->SetFlightCapabilityID(0, true);
|
||||
// Remove Vigor aura on dismount
|
||||
target->RemoveAura(372773);
|
||||
// Remove the Dynamic Flight aura if it was force-applied on mount
|
||||
if (Player* player = target->ToPlayer())
|
||||
player->UpdateDynamicFlight(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3083,13 +3096,22 @@ void AuraEffect::HandleAuraCanTurnWhileFalling(AuraApplication const* aurApp, ui
|
||||
|
||||
void AuraEffect::HandleModAdvFlying(AuraApplication const* aurApp, uint8 mode, bool apply) const
|
||||
{
|
||||
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
|
||||
if (!(mode & AURA_EFFECT_HANDLE_REAL))
|
||||
return;
|
||||
|
||||
Unit* target = aurApp->GetTarget();
|
||||
target->SetCanDoubleJump(apply || target->HasAura(SPELL_DH_DOUBLE_JUMP));
|
||||
target->SetCanFly(apply);
|
||||
target->SetCanAdvFly(apply);
|
||||
Player* player = aurApp->GetTarget()->ToPlayer();
|
||||
if (!player)
|
||||
return;
|
||||
|
||||
player->SetCanDoubleJump(apply || player->HasAura(SPELL_DH_DOUBLE_JUMP));
|
||||
player->SetCanFly(apply);
|
||||
player->SetCanAdvFly(apply);
|
||||
|
||||
// Retail delivers the full FlightCapability parameter burst right after SET_CAN_ADV_FLY on every
|
||||
// engage (sniff 66709). Sending it earlier is useless: the client only accepts/keeps the physics
|
||||
// params once the adv-fly state is enabled.
|
||||
if (apply)
|
||||
player->SendAdvFlyingSpeedBurst();
|
||||
}
|
||||
|
||||
void AuraEffect::HandleIgnoreMovementForces(AuraApplication const* aurApp, uint8 mode, bool apply) const
|
||||
|
||||
@@ -15,18 +15,200 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "DB2Stores.h"
|
||||
#include "GossipDef.h"
|
||||
#include "LootItemType.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "Player.h"
|
||||
#include "QuestDef.h"
|
||||
#include "QuestMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "SpellScript.h"
|
||||
#include "Util.h"
|
||||
#include "midnight_zone_ai.h"
|
||||
#include <initializer_list>
|
||||
#include <string_view>
|
||||
|
||||
namespace Scripts::QuelThalas::IsleOfQuelDanasMidnight
|
||||
{
|
||||
namespace Quests
|
||||
{
|
||||
static constexpr uint32 Midnight = 91281;
|
||||
static constexpr uint32 VoiceFromTheLight = 88719;
|
||||
static constexpr uint32 LightLastStand = 86852;
|
||||
}
|
||||
|
||||
|
||||
namespace Credits
|
||||
{
|
||||
static constexpr uint32 ImageOfLiadrin = 241677;
|
||||
static constexpr uint32 SpeakWithImage = 241691; // [DNT] Kill Credit, objective 1 of 88719
|
||||
static constexpr uint32 TravelToQuelDanas = 239653; // [DNT] Kill Credit, objective 2 of 88719
|
||||
}
|
||||
|
||||
namespace Spells
|
||||
{
|
||||
// Item 239151 force-casts 1227747. Gossip aura 1260860 is the same dummy/root pair.
|
||||
// Neither effect carries a destination. Map 2858 is "12.0 Quel'Danas Scenario"
|
||||
// (UiMap 2432). The arrival point is quest 88719's travel coordinate, and Z comes
|
||||
// from the quest ender POI on that map (11148, -4485, 79).
|
||||
static constexpr uint32 MapQuelDanasScenario = 2858;
|
||||
static constexpr float ArrivalX = 11124.7f;
|
||||
static constexpr float ArrivalY = -4509.5f;
|
||||
static constexpr float ArrivalZ = 79.0f;
|
||||
static constexpr float ArrivalO = 0.805f;
|
||||
|
||||
// points_of_interest 8566. Area 16333 Sanctum of Light is on continent 0,
|
||||
// the same map this database uses for Silvermoon.
|
||||
static constexpr float SanctumX = 8457.0302734375f;
|
||||
static constexpr float SanctumY = -4610.58984375f;
|
||||
static constexpr float SanctumZ = 48.25709915161132812f;
|
||||
}
|
||||
|
||||
namespace Movies
|
||||
{
|
||||
// Spell 1278217 "[SUN] Play Movie" plays Movie.db2 1048.
|
||||
static constexpr uint32 Intercession = 1048;
|
||||
}
|
||||
|
||||
namespace Gossip
|
||||
{
|
||||
static constexpr int32 SummonToQuelDanas = 133523;
|
||||
// Campaign.db2 335 "Midnight Expansion Intro Skip" (quest lines 5811 and 6130).
|
||||
static constexpr uint32 IntroSkipCampaign = 335;
|
||||
static constexpr uint32 IntroSkipQuests[] =
|
||||
{
|
||||
91281, 88719, 86769, 86770, 89271, 86780, 86805, 89012,
|
||||
86806, 86807, 91274, 86834, 86811, 86848, 86849, 86850, 86852,
|
||||
86733, 86734, 86735, 86736, 86737
|
||||
};
|
||||
}
|
||||
|
||||
static bool HasOptionFlag(GossipOptionFlags flags, GossipOptionFlags flag)
|
||||
{
|
||||
return (static_cast<int32>(flags) & static_cast<int32>(flag)) != 0;
|
||||
}
|
||||
|
||||
static bool TextHas(std::string_view text, std::initializer_list<std::string_view> needles)
|
||||
{
|
||||
for (std::string_view needle : needles)
|
||||
if (StringContainsStringI(text, needle))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void CreditCreature(Player* player, uint32 entry, ObjectGuid guid = ObjectGuid::Empty)
|
||||
{
|
||||
player->KilledMonsterCredit(entry, guid);
|
||||
player->TalkedToCreature(entry, guid);
|
||||
}
|
||||
|
||||
static void OfferQuest(Player* player, uint32 questId, Object* giver)
|
||||
{
|
||||
if (player->GetQuestStatus(questId) != QUEST_STATUS_NONE)
|
||||
return;
|
||||
|
||||
Quest const* quest = sObjectMgr->GetQuestTemplate(questId);
|
||||
if (!quest || !player->CanTakeQuest(quest, false))
|
||||
return;
|
||||
|
||||
player->AddQuestAndCheckCompletion(quest, giver);
|
||||
}
|
||||
|
||||
static void TurnInIfComplete(Player* player, uint32 questId, Object* giver)
|
||||
{
|
||||
Quest const* quest = sObjectMgr->GetQuestTemplate(questId);
|
||||
if (!quest || player->GetQuestStatus(questId) != QUEST_STATUS_COMPLETE)
|
||||
return;
|
||||
|
||||
if (player->CanRewardQuest(quest, false))
|
||||
player->RewardQuest(quest, LootItemType::Item, 0, giver, true);
|
||||
}
|
||||
|
||||
static void AdvanceSummonQuests(Player* player, Creature* image)
|
||||
{
|
||||
Object* giver = image ? static_cast<Object*>(image) : static_cast<Object*>(player);
|
||||
ObjectGuid imageGuid = image ? image->GetGUID() : ObjectGuid::Empty;
|
||||
|
||||
OfferQuest(player, Quests::Midnight, giver);
|
||||
if (player->GetQuestStatus(Quests::Midnight) == QUEST_STATUS_INCOMPLETE)
|
||||
CreditCreature(player, Credits::ImageOfLiadrin, imageGuid);
|
||||
|
||||
TurnInIfComplete(player, Quests::Midnight, giver);
|
||||
|
||||
OfferQuest(player, Quests::VoiceFromTheLight, giver);
|
||||
if (player->GetQuestStatus(Quests::VoiceFromTheLight) == QUEST_STATUS_INCOMPLETE)
|
||||
CreditCreature(player, Credits::SpeakWithImage);
|
||||
}
|
||||
|
||||
static bool TeleportIfMapExists(Player* player, uint32 mapId, float x, float y, float z, float orientation)
|
||||
{
|
||||
if (!sMapStore.LookupEntry(mapId))
|
||||
return false;
|
||||
|
||||
return player->TeleportTo(mapId, x, y, z, orientation);
|
||||
}
|
||||
|
||||
static void TravelToQuelDanas(Player* player, Creature* image)
|
||||
{
|
||||
AdvanceSummonQuests(player, image);
|
||||
player->PlayerTalkClass->SendCloseGossip();
|
||||
|
||||
if (!TeleportIfMapExists(player, Spells::MapQuelDanasScenario, Spells::ArrivalX, Spells::ArrivalY, Spells::ArrivalZ, Spells::ArrivalO))
|
||||
return;
|
||||
|
||||
if (player->GetQuestStatus(Quests::VoiceFromTheLight) == QUEST_STATUS_INCOMPLETE)
|
||||
CreditCreature(player, Credits::TravelToQuelDanas);
|
||||
}
|
||||
|
||||
static void PlayIntercession(Player* player, GossipMenuItem const* item)
|
||||
{
|
||||
player->PlayerTalkClass->SendCloseGossip();
|
||||
|
||||
if (item->SpellID)
|
||||
player->CastSpell(player, uint32(*item->SpellID), true);
|
||||
|
||||
if (sMovieStore.LookupEntry(Movies::Intercession))
|
||||
player->SendMovieStart(Movies::Intercession);
|
||||
}
|
||||
|
||||
static void SkipIntroduction(Player* player)
|
||||
{
|
||||
player->PlayerTalkClass->SendCloseGossip();
|
||||
QuestMgr::SkipCampaignForPlayer(Gossip::IntroSkipCampaign, player);
|
||||
|
||||
for (uint32 questId : Gossip::IntroSkipQuests)
|
||||
{
|
||||
uint32 single[] = { questId };
|
||||
player->SkipQuests(single);
|
||||
}
|
||||
|
||||
TeleportIfMapExists(player, 0, Spells::SanctumX, Spells::SanctumY, Spells::SanctumZ, 0.0f);
|
||||
}
|
||||
|
||||
// 1227747 / 1260860 - Light's Summons. Server-side teleport; the spell itself only fades and roots.
|
||||
class spell_midnight_lights_summons : public SpellScript
|
||||
{
|
||||
void HandleTeleport(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Player* player = GetHitPlayer())
|
||||
TravelToQuelDanas(player, nullptr);
|
||||
}
|
||||
|
||||
void PreventStuckAura(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
PreventHitAura();
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_midnight_lights_summons::HandleTeleport, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_midnight_lights_summons::PreventStuckAura, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_midnight_lights_summons::PreventStuckAura, EFFECT_2, SPELL_EFFECT_APPLY_AURA);
|
||||
}
|
||||
};
|
||||
|
||||
// 241677 - Image of Lady Liadrin (Wowhead: Midnight / A Voice from the Light)
|
||||
struct npc_image_of_lady_liadrin_midnight : public ScriptedAI
|
||||
{
|
||||
@@ -36,6 +218,51 @@ struct npc_image_of_lady_liadrin_midnight : public ScriptedAI
|
||||
{
|
||||
return Scripts::QuelThalas::MidnightZones::GossipCreditMidnightObjective(me, player);
|
||||
}
|
||||
|
||||
bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
|
||||
{
|
||||
GossipMenuItem const* item = player->PlayerTalkClass->GetGossipMenu().GetItemByIndex(gossipListId);
|
||||
if (!item)
|
||||
return false;
|
||||
|
||||
std::string_view text = item->OptionText;
|
||||
bool const summon = item->GossipOptionID == Gossip::SummonToQuelDanas
|
||||
|| HasOptionFlag(item->Flags, GossipOptionFlags::QuestLabelPrepend)
|
||||
|| TextHas(text, { "summon me", "beschw" });
|
||||
bool const movie = HasOptionFlag(item->Flags, GossipOptionFlags::PlayMovieLabelPrepend)
|
||||
|| TextHas(text, { "Sunwell", "Sonnenbrunnen" });
|
||||
bool const skip = TextHas(text, { "Sanctum of Light", "Sanktum", "Skip the Midnight", "Einführung" });
|
||||
bool const heard = TextHas(text, { "heard this tale", "Geschichte" });
|
||||
|
||||
if (summon && !skip)
|
||||
{
|
||||
TravelToQuelDanas(player, me);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (movie)
|
||||
{
|
||||
PlayIntercession(player, item);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (skip)
|
||||
{
|
||||
SkipIntroduction(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (heard)
|
||||
{
|
||||
if (player->GetQuestStatus(Quests::Midnight) == QUEST_STATUS_INCOMPLETE)
|
||||
CreditCreature(player, Credits::ImageOfLiadrin, me->GetGUID());
|
||||
|
||||
player->PlayerTalkClass->SendCloseGossip();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// 241575 - Speak with Liadrin to begin the ritual (Wowhead: Light's Last Stand)
|
||||
@@ -59,4 +286,5 @@ void AddSC_zone_isle_of_queldanas_midnight()
|
||||
|
||||
RegisterCreatureAI(npc_image_of_lady_liadrin_midnight);
|
||||
RegisterCreatureAI(npc_liadrin_lights_last_stand);
|
||||
RegisterSpellScript(spell_midnight_lights_summons);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user