aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/authserver/Server/AuthSession.cpp2
-rw-r--r--src/server/database/Updater/DBUpdater.cpp2
-rw-r--r--src/server/game/Entities/Creature/TemporarySummon.h5
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp2
-rw-r--r--src/server/game/Entities/Player/Player.cpp141
-rw-r--r--src/server/game/Entities/Player/Player.h17
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp6
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp5
-rw-r--r--src/server/game/Entities/Unit/Unit.h1
-rw-r--r--src/server/game/Groups/Group.cpp45
-rw-r--r--src/server/game/Groups/Group.h1
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp7
-rw-r--r--src/server/game/Maps/Map.cpp2
-rw-r--r--src/server/game/Maps/MapInstanced.cpp4
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp6
-rw-r--r--src/server/game/Spells/Spell.cpp17
-rw-r--r--src/server/scripts/Commands/cs_learn.cpp2
-rw-r--r--src/server/scripts/Kalimdor/zone_moonglade.cpp1
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp1
-rw-r--r--src/server/scripts/Outland/zone_shadowmoon_valley.cpp4
-rw-r--r--src/server/scripts/Spells/spell_dk.cpp306
-rw-r--r--src/server/scripts/World/npc_taxi.cpp118
22 files changed, 482 insertions, 213 deletions
diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp
index bcb1dd3fddc..60e9b734b13 100644
--- a/src/server/authserver/Server/AuthSession.cpp
+++ b/src/server/authserver/Server/AuthSession.cpp
@@ -540,7 +540,7 @@ bool AuthSession::HandleLogonProof()
packet << uint8(3);
packet << uint8(0);
SendPacket(packet);
- return false;
+ return true;
}
}
diff --git a/src/server/database/Updater/DBUpdater.cpp b/src/server/database/Updater/DBUpdater.cpp
index 529e236d1ed..170954a86f4 100644
--- a/src/server/database/Updater/DBUpdater.cpp
+++ b/src/server/database/Updater/DBUpdater.cpp
@@ -311,7 +311,7 @@ bool DBUpdater<T>::Populate(DatabaseWorkerPool<T>& pool)
}
case LOCATION_DOWNLOAD:
{
- TC_LOG_ERROR("sql.updates", ">> File \"%s\" is missing, download it from \"http://www.trinitycore.org/f/files/category/1-database/\"" \
+ TC_LOG_ERROR("sql.updates", ">> File \"%s\" is missing, download it from \"https://github.com/TrinityCore/TrinityCore/releases\"" \
" and place it in your server directory.", base.filename().generic_string().c_str());
break;
}
diff --git a/src/server/game/Entities/Creature/TemporarySummon.h b/src/server/game/Entities/Creature/TemporarySummon.h
index afca851974a..6d058f405a8 100644
--- a/src/server/game/Entities/Creature/TemporarySummon.h
+++ b/src/server/game/Entities/Creature/TemporarySummon.h
@@ -72,9 +72,10 @@ class Minion : public TempSummon
Unit* GetOwner() const { return m_owner; }
float GetFollowAngle() const override { return m_followAngle; }
void SetFollowAngle(float angle) { m_followAngle = angle; }
- bool IsPetGhoul() const {return GetEntry() == 26125;} // Ghoul may be guardian or pet
- bool IsSpiritWolf() const {return GetEntry() == 29264;} // Spirit wolf from feral spirits
+ bool IsPetGhoul() const { return GetEntry() == 26125; } // Ghoul may be guardian or pet
+ bool IsSpiritWolf() const { return GetEntry() == 29264; } // Spirit wolf from feral spirits
bool IsGuardianPet() const;
+ bool IsRisenAlly() const { return GetEntry() == 30230; }
protected:
Unit* const m_owner;
float m_followAngle;
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 9aabed67243..6f0b9f89e44 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -1803,6 +1803,8 @@ void GameObject::CastSpell(Unit* target, uint32 spellId, bool triggered /*= true
if (Unit* owner = GetOwner())
{
trigger->setFaction(owner->getFaction());
+ if (owner->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE))
+ trigger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
// needed for GO casts for proper target validation checks
trigger->SetOwnerGUID(owner->GetGUID());
trigger->CastSpell(target ? target : trigger, spellInfo, triggered, nullptr, nullptr, owner->GetGUID());
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 14b555adde9..4fdf25e41c3 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -1242,6 +1242,9 @@ void Player::Update(uint32 p_time)
if (charmer->GetTypeId() == TYPEID_UNIT && charmer->IsAlive())
UpdateCharmedAI();
+ if (GetAI() && IsAIEnabled)
+ GetAI()->UpdateAI(p_time);
+
// Update items that have just a limited lifetime
if (now > m_Last_tick)
UpdateItemDuration(uint32(now - m_Last_tick));
@@ -1476,8 +1479,8 @@ void Player::Update(uint32 p_time)
_pendingBindTimer -= p_time;
}
- // not auto-free ghost from body in instances
- if (m_deathTimer > 0 && !GetBaseMap()->Instanceable() && !HasAuraType(SPELL_AURA_PREVENT_RESURRECTION))
+ // not auto-free ghost from body in instances or if its affected by risen ally
+ if (m_deathTimer > 0 && !GetBaseMap()->Instanceable() && !HasAuraType(SPELL_AURA_PREVENT_RESURRECTION) && !IsGhouled())
{
if (p_time >= m_deathTimer)
{
@@ -2157,7 +2160,7 @@ bool Player::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) co
return true;
if (spellInfo->Effects[index].IsEffect(SPELL_EFFECT_ATTACK_ME))
return true;
-
+
return Unit::IsImmunedToSpellEffect(spellInfo, index);
}
@@ -4731,6 +4734,32 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness)
}
}
+void Player::SendGhoulResurrectRequest(Player* target)
+{
+ target->m_ghoulResurrectPlayerGUID = GetGUID();
+
+ WorldPacket data(SMSG_RESURRECT_REQUEST, 8 + 4 + 1 + 1);
+ data << uint64(GetGUID());
+ data << uint32(0);
+ data << uint8(0);
+ data << uint8(0);
+ target->GetSession()->SendPacket(&data);
+}
+
+void Player::GhoulResurrect()
+{
+ CastSpell(this, 46619 /*SPELL_DK_RAISE_ALLY*/, true, nullptr, nullptr, m_ghoulResurrectPlayerGUID);
+
+ m_ghoulResurrectPlayerGUID = ObjectGuid::Empty;
+}
+
+void Player::RemoveGhoul()
+{
+ if (IsGhouled())
+ if (Creature* ghoul = ObjectAccessor::GetCreature(*this, m_ghoulResurrectGhoulGUID))
+ ghoul->DespawnOrUnsummon(); // Raise Ally aura will handle unauras
+}
+
void Player::KillPlayer()
{
if (IsFlying() && !GetTransport())
@@ -18594,31 +18623,6 @@ void Player::SendSavedInstances()
}
}
-/// convert the player's binds to the group
-void Player::ConvertInstancesToGroup(Player* player, Group* group, bool switchLeader)
-{
- // copy all binds to the group, when changing leader it's assumed the character
- // will not have any solo binds
-
- for (uint8 i = 0; i < MAX_DIFFICULTY; ++i)
- {
- for (BoundInstancesMap::iterator itr = player->m_boundInstances[i].begin(); itr != player->m_boundInstances[i].end();)
- {
- if (!switchLeader || !group->GetBoundInstance(itr->second.save->GetDifficulty(), itr->first))
- group->BindToInstance(itr->second.save, itr->second.perm, false);
-
- // permanent binds are not removed
- if (switchLeader && !itr->second.perm)
- {
- // increments itr in call
- player->UnbindInstance(itr, Difficulty(i), false);
- }
- else
- ++itr;
- }
- }
-}
-
bool Player::Satisfy(AccessRequirement const* ar, uint32 target_map, bool report)
{
if (!IsGameMaster() && ar)
@@ -18707,7 +18711,7 @@ bool Player::CheckInstanceValidity(bool /*isLogin*/)
// game masters' instances are always valid
if (IsGameMaster())
return true;
-
+
// non-instances are always valid
Map* map = GetMap();
if (!map || !map->IsDungeon())
@@ -20181,6 +20185,12 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent)
void Player::StopCastingCharm()
{
+ if (IsGhouled())
+ {
+ RemoveGhoul();
+ return;
+ }
+
Unit* charm = GetCharm();
if (!charm)
return;
@@ -21533,6 +21543,14 @@ void Player::setResurrectRequestData(ObjectGuid guid, uint32 mapId, float X, flo
m_resurrectHealth = health;
m_resurrectMana = mana;
}
+
+void Player::clearResurrectRequestData()
+{
+ setResurrectRequestData(ObjectGuid::Empty, 0, 0.0f, 0.0f, 0.0f, 0, 0);
+
+ m_ghoulResurrectPlayerGUID = ObjectGuid::Empty;
+ m_ghoulResurrectGhoulGUID = ObjectGuid::Empty;
+}
//slot to be excluded while counting
bool Player::EnchantmentFitsRequirements(uint32 enchantmentcondition, int8 slot)
{
@@ -22627,46 +22645,16 @@ void Player::LearnQuestRewardedSpells(Quest const* quest)
if (!found)
return;
- // prevent learn non first rank unknown profession and second specialization for same profession)
uint32 learned_0 = spellInfo->Effects[0].TriggerSpell;
- if (sSpellMgr->GetSpellRank(learned_0) > 1 && !HasSpell(learned_0))
+ if (!HasSpell(learned_0))
{
SpellInfo const* learnedInfo = sSpellMgr->GetSpellInfo(learned_0);
if (!learnedInfo)
return;
- // not have first rank learned (unlearned prof?)
- if (!HasSpell(learnedInfo->GetFirstRankSpell()->Id))
- return;
-
- SpellsRequiringSpellMapBounds spellsRequired = sSpellMgr->GetSpellsRequiredForSpellBounds(learned_0);
- for (SpellsRequiringSpellMap::const_iterator itr2 = spellsRequired.first; itr2 != spellsRequired.second; ++itr2)
- {
- uint32 profSpell = itr2->second;
-
- // specialization
- if (learnedInfo->Effects[0].Effect == SPELL_EFFECT_TRADE_SKILL && learnedInfo->Effects[1].Effect == 0 && profSpell)
- {
- // search other specialization for same prof
- for (PlayerSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
- {
- if (itr->second->state == PLAYERSPELL_REMOVED || itr->first == learned_0)
- continue;
-
- SpellInfo const* itrInfo = sSpellMgr->GetSpellInfo(itr->first);
- if (!itrInfo)
- return;
-
- // compare only specializations
- if (itrInfo->Effects[0].Effect != SPELL_EFFECT_TRADE_SKILL || itrInfo->Effects[1].Effect != 0)
- continue;
-
- // compare same chain spells
- if (sSpellMgr->IsSpellRequiringSpell(itr->first, profSpell))
- return;
- }
- }
- }
+ // profession specialization can be re-learned from npc
+ if (learnedInfo->Effects[0].Effect == SPELL_EFFECT_TRADE_SKILL && learnedInfo->Effects[1].Effect == 0 && !learnedInfo->SpellLevel)
+ return;
}
CastSpell(this, spell_id, true);
@@ -23465,6 +23453,8 @@ uint32 Player::GetBaseWeaponSkillValue(WeaponAttackType attType) const
void Player::ResurrectUsingRequestData()
{
+ RemoveGhoul();
+
/// Teleport before resurrecting by player, otherwise the player might get attacked from creatures near his corpse
TeleportTo(m_resurrectMap, m_resurrectX, m_resurrectY, m_resurrectZ, GetOrientation());
@@ -23909,6 +23899,31 @@ void Player::SetViewpoint(WorldObject* target, bool apply)
//WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0);
//GetSession()->SendPacket(&data);
}
+
+ // HACK: Make sure update for PLAYER_FARSIGHT is received before SMSG_PET_SPELLS to properly hide "Release spirit" dialog
+ if (target->GetTypeId() == TYPEID_UNIT && static_cast<Unit*>(target)->HasUnitTypeMask(UNIT_MASK_MINION) && static_cast<Minion*>(target)->IsRisenAlly())
+ {
+ if (apply)
+ {
+ UpdateDataMapType update_players;
+ BuildUpdate(update_players);
+ WorldPacket packet;
+ for (UpdateDataMapType::iterator iter = update_players.begin(); iter != update_players.end(); ++iter)
+ {
+ iter->second.BuildPacket(&packet);
+ iter->first->GetSession()->SendPacket(&packet);
+ packet.clear();
+ }
+ }
+ else
+ {
+ m_deathTimer = 6 * MINUTE * IN_MILLISECONDS;
+
+ // Reset "Release spirit" timer clientside
+ WorldPacket data(SMSG_FORCED_DEATH_UPDATE);
+ SendDirectMessage(&data);
+ }
+ }
}
WorldObject* Player::GetViewpoint() const
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 0072ec4125f..e7af827e9c7 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1576,7 +1576,7 @@ class Player : public Unit, public GridObject<Player>
void UpdatePotionCooldown(Spell* spell = NULL);
void setResurrectRequestData(ObjectGuid guid, uint32 mapId, float X, float Y, float Z, uint32 health, uint32 mana);
- void clearResurrectRequestData() { setResurrectRequestData(ObjectGuid::Empty, 0, 0.0f, 0.0f, 0.0f, 0, 0); }
+ void clearResurrectRequestData();
bool isResurrectRequestedBy(ObjectGuid guid) const { return !m_resurrectGUID.IsEmpty() && m_resurrectGUID == guid; }
bool isResurrectRequested() const { return !m_resurrectGUID.IsEmpty(); }
void ResurrectUsingRequestData();
@@ -1770,6 +1770,15 @@ class Player : public Unit, public GridObject<Player>
void ResurrectPlayer(float restore_percent, bool applySickness = false);
void BuildPlayerRepop();
void RepopAtGraveyard();
+ void SendGhoulResurrectRequest(Player* target);
+ bool IsValidGhoulResurrectRequest(ObjectGuid guid)
+ {
+ return !m_ghoulResurrectPlayerGUID.IsEmpty() && m_ghoulResurrectPlayerGUID == guid;
+ }
+ void GhoulResurrect();
+ void SetGhoulResurrectGhoulGUID(ObjectGuid guid) { m_ghoulResurrectGhoulGUID = guid; }
+ ObjectGuid GetGhoulResurrectGhoulGUID() { return m_ghoulResurrectGhoulGUID; }
+ void RemoveGhoul();
void DurabilityLossAll(double percent, bool inventory);
void DurabilityLoss(Item* item, double percent);
@@ -2116,7 +2125,6 @@ class Player : public Unit, public GridObject<Player>
bool HasPendingBind() const { return _pendingBindId > 0; }
void SendRaidInfo();
void SendSavedInstances();
- static void ConvertInstancesToGroup(Player* player, Group* group, bool switchLeader);
bool Satisfy(AccessRequirement const* ar, uint32 target_map, bool report = false);
bool CheckInstanceValidity(bool /*isLogin*/);
bool CheckInstanceCount(uint32 instanceId) const;
@@ -2404,6 +2412,9 @@ class Player : public Unit, public GridObject<Player>
float m_resurrectX, m_resurrectY, m_resurrectZ;
uint32 m_resurrectHealth, m_resurrectMana;
+ ObjectGuid m_ghoulResurrectPlayerGUID;
+ ObjectGuid m_ghoulResurrectGhoulGUID;
+
WorldSession* m_session;
typedef std::list<Channel*> JoinedChannelsList;
@@ -2503,7 +2514,7 @@ class Player : public Unit, public GridObject<Player>
bool IsHasDelayedTeleport() const { return m_bHasDelayedTeleport; }
void SetDelayedTeleportFlag(bool setting) { m_bHasDelayedTeleport = setting; }
void ScheduleDelayedOperation(uint32 operation) { if (operation < DELAYED_END) m_DelayedOperations |= operation; }
-
+
bool IsInstanceLoginGameMasterException() const;
MapReference m_mapRef;
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index 775a3c96c46..a8e13a9f7db 100644
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -499,7 +499,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
if (getClass() == CLASS_SHAMAN || getClass() == CLASS_PALADIN) // mental quickness
UpdateSpellDamageAndHealingBonus();
- if (pet && pet->IsPetGhoul()) // At melee attack power change for DK pet
+ if (pet && (pet->IsPetGhoul() || pet->IsRisenAlly())) // At melee attack power change for DK pet
pet->UpdateAttackPowerAndDamage();
if (guardian && guardian->IsSpiritWolf()) // At melee attack power change for Shaman feral spirit
@@ -1113,7 +1113,7 @@ bool Guardian::UpdateStats(Stats stat)
Unit* owner = GetOwner();
// Handle Death Knight Glyphs and Talents
float mod = 0.75f;
- if (IsPetGhoul() && (stat == STAT_STAMINA || stat == STAT_STRENGTH))
+ if ((IsPetGhoul() || IsRisenAlly()) && (stat == STAT_STAMINA || stat == STAT_STRENGTH))
{
if (stat == STAT_STAMINA)
mod = 0.3f; // Default Owner's Stamina scale
@@ -1329,7 +1329,7 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged)
bonusAP = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.22f * mod;
SetBonusDamage(int32(owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.1287f * mod));
}
- else if (IsPetGhoul()) //ghouls benefit from deathknight's attack power (may be summon pet or not)
+ else if (IsPetGhoul() || IsRisenAlly()) //ghouls benefit from deathknight's attack power (may be summon pet or not)
{
bonusAP = owner->GetTotalAttackPowerValue(BASE_ATTACK) * 0.22f;
SetBonusDamage(int32(owner->GetTotalAttackPowerValue(BASE_ATTACK) * 0.1287f));
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index fcd2535dad9..261f4faf1a8 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -9395,7 +9395,7 @@ void Unit::SetMinion(Minion *minion, bool apply)
minion->SetSpeed(UnitMoveType(i), m_speed_rate[i], true);
// Ghoul pets have energy instead of mana (is anywhere better place for this code?)
- if (minion->IsPetGhoul())
+ if (minion->IsPetGhoul() || minion->IsRisenAlly())
minion->setPowerType(POWER_ENERGY);
// Send infinity cooldown - client does that automatically but after relog cooldown needs to be set again
@@ -13625,6 +13625,9 @@ void Unit::RemoveFromWorld()
RemoveAreaAurasDueToLeaveWorld();
+ if (IsCharmed())
+ RemoveCharmedBy(nullptr);
+
if (GetCharmerGUID())
{
TC_LOG_FATAL("entities.unit", "Unit %u has charmer guid when removed from world", GetEntry());
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 8fc93f24351..90d312f422a 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1598,6 +1598,7 @@ class Unit : public WorldObject
bool IsAlive() const { return (m_deathState == ALIVE); }
bool isDying() const { return (m_deathState == JUST_DIED); }
bool isDead() const { return (m_deathState == DEAD || m_deathState == CORPSE); }
+ bool IsGhouled() const { return HasAura(46619 /*SPELL_DK_RAISE_ALLY*/); }
DeathState getDeathState() const { return m_deathState; }
virtual void setDeathState(DeathState s); // overwrited in Creature/Player/Pet
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index d0e70eb3dbb..8ebc71b0146 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -148,10 +148,9 @@ bool Group::Create(Player* leader)
CharacterDatabase.Execute(stmt);
+ Group::ConvertLeaderInstancesToGroup(leader, this, false);
ASSERT(AddMember(leader)); // If the leader can't be added to a new group because it appears full, something is clearly wrong.
-
- Player::ConvertInstancesToGroup(leader, this, false);
}
else if (!AddMember(leader))
return false;
@@ -375,9 +374,7 @@ bool Group::AddMember(Player* player)
player->SetGroup(this, subGroup);
// if the same group invites the player back, cancel the homebind timer
- InstanceGroupBind* bind = GetBoundInstance(player);
- if (bind && bind->save->GetInstanceId() == player->GetInstanceId())
- player->m_InstanceValid = true;
+ player->m_InstanceValid = player->CheckInstanceValidity(false);
if (!isRaidGroup()) // reset targetIcons for non-raid-groups
{
@@ -654,7 +651,7 @@ void Group::ChangeLeader(ObjectGuid newLeaderGuid)
}
// Copy the permanent binds from the new leader to the group
- Player::ConvertInstancesToGroup(newLeader, this, true);
+ Group::ConvertLeaderInstancesToGroup(newLeader, this, true);
// Update the group leader
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GROUP_LEADER);
@@ -680,6 +677,42 @@ void Group::ChangeLeader(ObjectGuid newLeaderGuid)
BroadcastPacket(&data, true);
}
+/// convert the player's binds to the group
+void Group::ConvertLeaderInstancesToGroup(Player* player, Group* group, bool switchLeader)
+{
+ // copy all binds to the group, when changing leader it's assumed the character
+ // will not have any solo binds
+ for (uint8 i = 0; i < MAX_DIFFICULTY; ++i)
+ {
+ for (Player::BoundInstancesMap::iterator itr = player->m_boundInstances[i].begin(); itr != player->m_boundInstances[i].end();)
+ {
+ if (!switchLeader || !group->GetBoundInstance(itr->second.save->GetDifficulty(), itr->first))
+ group->BindToInstance(itr->second.save, itr->second.perm, false);
+
+ // permanent binds are not removed
+ if (switchLeader && !itr->second.perm)
+ {
+ // increments itr in call
+ player->UnbindInstance(itr, Difficulty(i), false);
+ }
+ else
+ ++itr;
+ }
+ }
+
+ /* if group leader is in a non-raid dungeon map and nobody is actually bound to this map then the group can "take over" the instance *
+ * (example: two-player group disbanded by disconnect where the player reconnects within 60 seconds and the group is reformed) */
+ if (Map* playerMap = player->GetMap())
+ if (!switchLeader && playerMap->IsNonRaidDungeon())
+ if (InstanceSave* save = sInstanceSaveMgr->GetInstanceSave(playerMap->GetInstanceId()))
+ if (save->GetGroupCount() == 0 && save->GetPlayerCount() == 0)
+ {
+ TC_LOG_DEBUG("maps", "Group::ConvertLeaderInstancesToGroup: Group for player %s is taking over unbound instance map %d with Id %d", player->GetName().c_str(), playerMap->GetId(), playerMap->GetInstanceId());
+ // if nobody is saved to this, then the save wasn't permanent
+ group->BindToInstance(save, false, false);
+ }
+}
+
void Group::Disband(bool hideDestroy /* = false */)
{
sScriptMgr->OnGroupDisband(this);
diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h
index 4d2ee57c9b2..42fd9b582e8 100644
--- a/src/server/game/Groups/Group.h
+++ b/src/server/game/Groups/Group.h
@@ -194,6 +194,7 @@ class Group
bool AddMember(Player* player);
bool RemoveMember(ObjectGuid guid, const RemoveMethod &method = GROUP_REMOVEMETHOD_DEFAULT, ObjectGuid kicker = ObjectGuid::Empty, const char* reason = NULL);
void ChangeLeader(ObjectGuid guid);
+ static void ConvertLeaderInstancesToGroup(Player* player, Group* group, bool switchLeader);
void SetLootMethod(LootMethod method);
void SetLooterGuid(ObjectGuid guid);
void SetMasterLooterGuid(ObjectGuid guid);
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index e4ee057d6ea..758d5af83f7 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -71,6 +71,7 @@ void WorldSession::HandleRepopRequestOpcode(WorldPacket& recvData)
}
//this is spirit release confirm?
+ GetPlayer()->RemoveGhoul();
GetPlayer()->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
GetPlayer()->BuildPlayerRepop();
GetPlayer()->RepopAtGraveyard();
@@ -776,6 +777,12 @@ void WorldSession::HandleResurrectResponseOpcode(WorldPacket& recvData)
return;
}
+ if (GetPlayer()->IsValidGhoulResurrectRequest(guid))
+ {
+ GetPlayer()->GhoulResurrect();
+ return;
+ }
+
if (!GetPlayer()->isResurrectRequestedBy(guid))
return;
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 27fb55bb4da..a2cb84359f2 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -3030,7 +3030,7 @@ bool InstanceMap::AddPlayerToMap(Player* player)
{
if (group)
{
- // solo saves should be reset when entering a group
+ // solo saves should have been reset when the map was loaded
InstanceGroupBind* groupBind = group->GetBoundInstance(this);
if (playerBind && playerBind->save != mapSave)
{
diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp
index 74d490bf941..47b9b376b1e 100644
--- a/src/server/game/Maps/MapInstanced.cpp
+++ b/src/server/game/Maps/MapInstanced.cpp
@@ -163,7 +163,11 @@ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player, u
{
groupBind = group->GetBoundInstance(this);
if (groupBind)
+ {
+ // solo saves should be reset when entering a group's instance
+ player->UnbindInstance(GetId(), player->GetDifficulty(IsRaid()));
pSave = groupBind->save;
+ }
}
}
if (pSave)
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index fbe5febdbb1..3fa16cf4517 100644
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -1042,6 +1042,12 @@ std::vector<ChatCommand> ScriptMgr::GetChatCommands()
table.insert(table.end(), cmds.begin(), cmds.end());
}
+ // Sort commands in alphabetical order
+ std::sort(table.begin(), table.end(), [](const ChatCommand& a, const ChatCommand&b)
+ {
+ return strcmp(a.Name, b.Name) < 0;
+ });
+
return table;
}
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 0cfcf05c4b5..aed7c0db043 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -4207,21 +4207,16 @@ void Spell::SendResurrectRequest(Player* target)
{
// get resurrector name for creature resurrections, otherwise packet will be not accepted
// for player resurrections the name is looked up by guid
- std::string const sentName(m_caster->GetTypeId() == TYPEID_PLAYER
- ? ""
- : m_caster->GetNameForLocaleIdx(target->GetSession()->GetSessionDbLocaleIndex()));
+ std::string const sentName(m_caster->GetTypeId() == TYPEID_PLAYER ?
+ "" : m_caster->GetNameForLocaleIdx(target->GetSession()->GetSessionDbLocaleIndex()));
- WorldPacket data(SMSG_RESURRECT_REQUEST, (8+4+sentName.size()+1+1+1+4));
+ WorldPacket data(SMSG_RESURRECT_REQUEST, 8 + 4 + sentName.size() + 1 + 1 + 1);
data << uint64(m_caster->GetGUID());
data << uint32(sentName.size() + 1);
-
data << sentName;
- data << uint8(0); // null terminator
-
- data << uint8(m_caster->GetTypeId() == TYPEID_PLAYER ? 0 : 1); // "you'll be afflicted with resurrection sickness"
+ data << uint8(m_caster->IsSpiritHealer()); // "you'll be afflicted with resurrection sickness"
// override delay sent with SMSG_CORPSE_RECLAIM_DELAY, set instant resurrection for spells with this attribute
- if (m_spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_RESURRECTION_TIMER))
- data << uint32(0);
+ data << uint8(!m_spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_RESURRECTION_TIMER));
target->GetSession()->SendPacket(&data);
}
@@ -5512,7 +5507,7 @@ SpellCastResult Spell::CheckPetCast(Unit* target)
// dead owner (pets still alive when owners ressed?)
if (Unit* owner = m_caster->GetCharmerOrOwner())
- if (!owner->IsAlive())
+ if (!owner->IsAlive() && !owner->IsGhouled())
return SPELL_FAILED_CASTER_DEAD;
if (!target && m_targets.GetUnitTarget())
diff --git a/src/server/scripts/Commands/cs_learn.cpp b/src/server/scripts/Commands/cs_learn.cpp
index 9098bc13096..9b553ca4791 100644
--- a/src/server/scripts/Commands/cs_learn.cpp
+++ b/src/server/scripts/Commands/cs_learn.cpp
@@ -72,7 +72,7 @@ public:
static bool HandleLearnCommand(ChatHandler* handler, char const* args)
{
- Player* targetPlayer = handler->getSelectedPlayer();
+ Player* targetPlayer = handler->getSelectedPlayerOrSelf();
if (!targetPlayer)
{
diff --git a/src/server/scripts/Kalimdor/zone_moonglade.cpp b/src/server/scripts/Kalimdor/zone_moonglade.cpp
index 083662df7ba..fbcea958429 100644
--- a/src/server/scripts/Kalimdor/zone_moonglade.cpp
+++ b/src/server/scripts/Kalimdor/zone_moonglade.cpp
@@ -25,7 +25,6 @@ EndScriptData */
/* ContentData
npc_bunthen_plainswind
-npc_great_bear_spirit
npc_silva_filnaveth
npc_clintar_spirit
npc_clintar_dreamwalker
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
index 31dd7de96ca..fafe3113835 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
@@ -236,6 +236,7 @@ class boss_professor_putricide : public CreatureScript
summons.DespawnAll();
SetPhase(PHASE_COMBAT_1);
_experimentState = EXPERIMENT_STATE_OOZE;
+ me->SetReactState(REACT_DEFENSIVE);
me->SetWalk(false);
if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE)
me->GetMotionMaster()->MovementExpired();
diff --git a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp
index 7f5d2b95dc0..7ea87a3c0c4 100644
--- a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp
+++ b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp
@@ -560,6 +560,10 @@ public:
me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
} else PoisonTimer -= diff;
}
+ if (!UpdateVictim())
+ return;
+
+ DoMeleeAttackIfReady();
}
};
};
diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp
index 59caf4b7f7b..3cea620559a 100644
--- a/src/server/scripts/Spells/spell_dk.cpp
+++ b/src/server/scripts/Spells/spell_dk.cpp
@@ -22,6 +22,7 @@
*/
#include "Player.h"
+#include "UnitAI.h"
#include "ScriptMgr.h"
#include "SpellScript.h"
#include "SpellAuraEffects.h"
@@ -63,7 +64,10 @@ enum DeathKnightSpells
SPELL_DK_UNHOLY_PRESENCE = 48265,
SPELL_DK_UNHOLY_PRESENCE_TRIGGERED = 49772,
SPELL_DK_WILL_OF_THE_NECROPOLIS_TALENT_R1 = 49189,
- SPELL_DK_WILL_OF_THE_NECROPOLIS_AURA_R1 = 52284
+ SPELL_DK_WILL_OF_THE_NECROPOLIS_AURA_R1 = 52284,
+ SPELL_DK_RAISE_ALLY_INITIAL = 61999,
+ SPELL_DK_RAISE_ALLY = 46619,
+ SPELL_DK_GHOUL_THRASH = 47480
};
enum DeathKnightSpellIcons
@@ -1699,6 +1703,303 @@ public:
}
};
+enum RaiseAllyMisc
+{
+ TEXT_RISE_ALLY = 33055,
+
+ SPELL_DK_RISEN_GHOUL_SELF_STUN = 47466,
+ SPELL_DK_RISEN_GHOUL_SPAWN__IN = 47448,
+ SPELL_DK_SUMMON_HEAL = 36492,
+ SPELL_DK_DEATH_KNIGHT_RUNE_WEAPON_SCALING_02 = 51906,
+ SPELL_DK_DEATH_KNIGHT_PET_SCALING_01 = 54566,
+ SPELL_DK_DEATH_KNIGHT_PET_SCALING_03 = 61697,
+ SPELL_DK_MIRROR_NAME = 62224,
+ SPELL_DK_MIRROR_NAME_TRIGGERED = 62214,
+ SPELL_DK_PET_SCALING___MASTER_SPELL_03___INTELLECT_SPIRIT_RESILIENCE = 67557,
+ SPELL_DK_PET_SCALING___MASTER_SPELL_06___SPELL_HIT_EXPERTISE_SPELL_PENETRATION = 67561,
+
+ SPELL_GHOUL_FRENZY = 62218,
+
+ NPC_RISEN_ALLY = 30230
+};
+
+// 61999 - Raise Ally Initial
+class spell_dk_raise_ally_initial : public SpellScriptLoader
+{
+public:
+ spell_dk_raise_ally_initial() : SpellScriptLoader("spell_dk_raise_ally_initial") { }
+
+ class spell_dk_raise_ally_initial_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_dk_raise_ally_initial_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_DK_RAISE_ALLY_INITIAL))
+ return false;
+ return true;
+ }
+
+ SpellCastResult CheckCast()
+ {
+ // Raise Ally cannot be casted on alive players
+ Unit* target = GetExplTargetUnit();
+ if (!target)
+ return SPELL_FAILED_NO_VALID_TARGETS;
+ if (target->IsAlive())
+ return SPELL_FAILED_TARGET_NOT_DEAD;
+ if (Player* playerCaster = GetCaster()->ToPlayer())
+ if (playerCaster->InArena())
+ return SPELL_FAILED_NOT_IN_ARENA;
+ if (target->IsGhouled())
+ return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW;
+
+ return SPELL_CAST_OK;
+ }
+
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ Player* caster = GetCaster()->ToPlayer();
+ Player* target = GetHitPlayer();
+ if (caster && target)
+ caster->SendGhoulResurrectRequest(target);
+ }
+
+ void Register() override
+ {
+ OnCheckCast += SpellCheckCastFn(spell_dk_raise_ally_initial_SpellScript::CheckCast);
+ OnEffectHitTarget += SpellEffectFn(spell_dk_raise_ally_initial_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_dk_raise_ally_initial_SpellScript();
+ }
+};
+
+class player_ghoulAI : public PlayerAI
+{
+ public:
+ player_ghoulAI(Player* player, ObjectGuid ghoulGUID) : PlayerAI(player), _ghoulGUID(ghoulGUID) { }
+
+ void UpdateAI(uint32 /*diff*/) override
+ {
+ if (Creature* ghoul = ObjectAccessor::GetCreature(*me, _ghoulGUID))
+ {
+ if (!ghoul->IsAlive())
+ me->RemoveAura(SPELL_DK_RAISE_ALLY);
+ }
+ else
+ me->RemoveAura(SPELL_DK_RAISE_ALLY);
+ }
+
+ private:
+ ObjectGuid _ghoulGUID;
+};
+
+// 46619 - Raise Ally
+class spell_dk_raise_ally : public SpellScriptLoader
+{
+public:
+ spell_dk_raise_ally() : SpellScriptLoader("spell_dk_raise_ally") { }
+
+ class spell_dk_raise_ally_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_dk_raise_ally_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_DK_RAISE_ALLY))
+ return false;
+ return true;
+ }
+
+ void SendText()
+ {
+ Player* caster = GetCaster()->ToPlayer();
+ Unit* original = GetOriginalCaster();
+ if (caster && original)
+ original->Whisper(TEXT_RISE_ALLY, caster, true);
+ }
+
+ void HandleSummon(SpellEffIndex effIndex)
+ {
+ PreventHitDefaultEffect(effIndex);
+
+ Unit* caster = GetCaster();
+ Unit* originalCaster = GetOriginalCaster();
+ if (!originalCaster)
+ return;
+
+ uint32 entry = uint32(GetSpellInfo()->Effects[effIndex].MiscValue);
+
+ //! HACK - StatSystem needs further develop to enable update on Puppet stats
+ // Using same summon properties as Raise Dead 46585 (Guardian) - EffectMiscValueB = 829
+ SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(829);
+
+ uint32 duration = uint32(GetSpellInfo()->GetDuration());
+ Position pos = caster->GetPosition();
+
+ TempSummon* summon = originalCaster->GetMap()->SummonCreature(entry, pos, properties, duration, originalCaster, GetSpellInfo()->Id);
+ if (!summon)
+ return;
+
+ //! Leaving this here as it's necessary if statsystem problem is solved
+ /*
+ Default SUMMON_CATEGORY_PUPPET behaviour sets possesor as originalCaster,
+ in this case we need caster as possesor and originalCaster as owner
+ */
+ //summon->RemoveCharmedBy(NULL);
+
+ summon->SetCharmedBy(caster, CHARM_TYPE_POSSESS);
+
+ summon->CastSpell(summon, SPELL_DK_RISEN_GHOUL_SELF_STUN, true);
+ summon->CastSpell(summon, SPELL_DK_RISEN_GHOUL_SPAWN__IN, true);
+ summon->CastSpell(summon, SPELL_DK_SUMMON_HEAL, true);
+ summon->CastSpell(caster, SPELL_DK_MIRROR_NAME, true);
+ caster->CastSpell(summon, SPELL_DK_MIRROR_NAME_TRIGGERED, true);
+ summon->CastSpell(summon, SPELL_DK_DEATH_KNIGHT_RUNE_WEAPON_SCALING_02, true);
+ summon->CastSpell(summon, SPELL_DK_DEATH_KNIGHT_PET_SCALING_01, true);
+ summon->CastSpell(summon, SPELL_DK_DEATH_KNIGHT_PET_SCALING_03, true);
+ summon->CastSpell(summon, SPELL_DK_PET_SCALING___MASTER_SPELL_03___INTELLECT_SPIRIT_RESILIENCE, true);
+ summon->CastSpell(summon, SPELL_DK_PET_SCALING___MASTER_SPELL_06___SPELL_HIT_EXPERTISE_SPELL_PENETRATION, true);
+
+ // SMSG_POWER_UPDATE is sent
+ summon->SetMaxPower(POWER_ENERGY, 100);
+
+ if (Player* player = GetCaster()->ToPlayer())
+ player->SetGhoulResurrectGhoulGUID(summon->GetGUID());
+ }
+
+ void Register() override
+ {
+ AfterHit += SpellHitFn(spell_dk_raise_ally_SpellScript::SendText);
+ OnEffectHit += SpellEffectFn(spell_dk_raise_ally_SpellScript::HandleSummon, EFFECT_0, SPELL_EFFECT_SUMMON);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_dk_raise_ally_SpellScript();
+ }
+
+ class spell_dk_raise_ally_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_dk_raise_ally_AuraScript);
+
+ public:
+ spell_dk_raise_ally_AuraScript()
+ {
+ oldAI = nullptr;
+ oldAIState = false;
+ }
+
+ private:
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_DK_RAISE_ALLY))
+ return false;
+ return true;
+ }
+
+ void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Player* player = GetTarget()->ToPlayer();
+ if (!player || player->GetGhoulResurrectGhoulGUID().IsEmpty())
+ return;
+
+ oldAI = player->GetAI();
+ oldAIState = player->IsAIEnabled;
+ player->SetAI(new player_ghoulAI(player, player->GetGhoulResurrectGhoulGUID()));
+ player->IsAIEnabled = true;
+ }
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Player* player = GetTarget()->ToPlayer();
+ if (!player)
+ return;
+
+ player->IsAIEnabled = oldAIState;
+ UnitAI* thisAI = player->GetAI();
+ player->SetAI(oldAI);
+ delete thisAI;
+
+ // Dismiss ghoul if necessary
+ if (Creature* ghoul = ObjectAccessor::GetCreature(*player, player->GetGhoulResurrectGhoulGUID()))
+ {
+ ghoul->RemoveCharmedBy(nullptr);
+ ghoul->DespawnOrUnsummon(1000);
+ }
+
+ player->SetGhoulResurrectGhoulGUID(ObjectGuid::Empty);
+ player->RemoveAura(SPELL_GHOUL_FRENZY);
+ }
+
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_dk_raise_ally_AuraScript::OnApply, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ AfterEffectRemove += AuraEffectRemoveFn(spell_dk_raise_ally_AuraScript::OnRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
+
+ UnitAI* oldAI;
+ bool oldAIState;
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_dk_raise_ally_AuraScript();
+ }
+};
+
+// 47480 - Thrash
+class spell_dk_ghoul_thrash : public SpellScriptLoader
+{
+public:
+ spell_dk_ghoul_thrash() : SpellScriptLoader("spell_dk_ghoul_thrash") { }
+
+ class spell_dk_ghoul_thrash_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_dk_ghoul_thrash_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_DK_GHOUL_THRASH))
+ return false;
+ return true;
+ }
+
+ void CalcDamage()
+ {
+ if (Aura* aur = GetCaster()->GetAura(SPELL_GHOUL_FRENZY))
+ {
+ int32 damage = GetHitDamage();
+ damage += int32(GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK) * 0.05f * aur->GetStackAmount());
+ aur->Remove();
+ SetHitDamage(damage);
+ }
+
+ /*
+ Also remove aura from charmer
+ SPELL_GHOUL_FRENZY (62218) - Targets (1, 27) (TARGET_UNIT_CASTER, TARGET_UNIT_MASTER)
+ */
+ if (Unit* charmer = GetCaster()->GetCharmer())
+ charmer->RemoveAura(SPELL_GHOUL_FRENZY);
+ }
+
+ void Register() override
+ {
+ OnHit += SpellHitFn(spell_dk_ghoul_thrash_SpellScript::CalcDamage);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_dk_ghoul_thrash_SpellScript();
+ }
+};
+
void AddSC_deathknight_spell_scripts()
{
new spell_dk_anti_magic_shell_raid();
@@ -1729,4 +2030,7 @@ void AddSC_deathknight_spell_scripts()
new spell_dk_vampiric_blood();
new spell_dk_will_of_the_necropolis();
new spell_dk_death_grip_initial();
+ new spell_dk_raise_ally_initial();
+ new spell_dk_raise_ally();
+ new spell_dk_ghoul_thrash();
}
diff --git a/src/server/scripts/World/npc_taxi.cpp b/src/server/scripts/World/npc_taxi.cpp
index c982a07f5a4..a200ba545d8 100644
--- a/src/server/scripts/World/npc_taxi.cpp
+++ b/src/server/scripts/World/npc_taxi.cpp
@@ -33,20 +33,7 @@ EndScriptData
#define GOSSIP_SUSURRUS "I am ready."
#define GOSSIP_NETHER_DRAKE "I'm ready to fly! Take me up, dragon!"
#define GOSSIP_BRAZEN "I am ready to go to Durnholde Keep."
-#define GOSSIP_IRONWING "I'd like to take a flight around Stormwind Harbor."
-#define GOSSIP_DABIREE1 "Fly me to Murketh and Shaadraz Gateways"
-#define GOSSIP_DABIREE2 "Fly me to Shatter Point"
-#define GOSSIP_WINDBELLOW1 "Fly me to The Abyssal Shelf"
-#define GOSSIP_WINDBELLOW2 "Fly me to Honor Point"
-#define GOSSIP_BRACK1 "Fly me to Murketh and Shaadraz Gateways"
-#define GOSSIP_BRACK2 "Fly me to The Abyssal Shelf"
-#define GOSSIP_BRACK3 "Fly me to Spinebreaker Post"
-#define GOSSIP_IRENA "Fly me to Skettis please"
-#define GOSSIP_CLOUDBREAKER1 "Speaking of action, I've been ordered to undertake an air strike."
-#define GOSSIP_CLOUDBREAKER2 "I need to intercept the Dawnblade reinforcements."
-#define GOSSIP_DRAGONHAWK "<Ride the dragonhawk to Sun's Reach>"
#define GOSSIP_VERONIA "Fly me to Manaforge Coruu please"
-#define GOSSIP_DEESAK "Fly me to Ogri'la please"
#define GOSSIP_CRIMSONWING "<Ride the gryphons to Survey Alcaz Island>"
class npc_taxi : public CreatureScript
@@ -72,64 +59,11 @@ public:
case 18725: // Old Hillsbrad Foothills - Brazen
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BRAZEN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
break;
- case 29154: // Stormwind City - Thargold Ironwing
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_IRONWING, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
- break;
- case 19409: // Hellfire Peninsula - Wing Commander Dabir'ee
- //Mission: The Murketh and Shaadraz Gateways
- if (player->GetQuestStatus(10146) == QUEST_STATUS_INCOMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DABIREE1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
-
- //Shatter Point
- if (!player->GetQuestRewardStatus(10340))
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DABIREE2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
- break;
- case 20235: // Hellfire Peninsula - Gryphoneer Windbellow
- //Mission: The Abyssal Shelf || Return to the Abyssal Shelf
- if (player->GetQuestStatus(10163) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(10346) == QUEST_STATUS_INCOMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WINDBELLOW1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6);
-
- //Go to the Front
- if (player->GetQuestStatus(10382) != QUEST_STATUS_NONE && !player->GetQuestRewardStatus(10382))
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WINDBELLOW2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7);
- break;
- case 19401: // Hellfire Peninsula - Wing Commander Brack
- //Mission: The Murketh and Shaadraz Gateways
- if (player->GetQuestStatus(10129) == QUEST_STATUS_INCOMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BRACK1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8);
-
- //Mission: The Abyssal Shelf || Return to the Abyssal Shelf
- if (player->GetQuestStatus(10162) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(10347) == QUEST_STATUS_INCOMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BRACK2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9);
-
- //Spinebreaker Post
- if (player->GetQuestStatus(10242) == QUEST_STATUS_COMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BRACK3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10);
- break;
- case 23413: // Blade's Edge Mountains - Skyguard Handler Irena
- if (player->GetReputationRank(1031) >= REP_HONORED)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_IRENA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11);
- break;
- case 25059: // Isle of Quel'Danas - Ayren Cloudbreaker
- if (player->GetQuestStatus(11532) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(11533) == QUEST_STATUS_INCOMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CLOUDBREAKER1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12);
-
- if (player->GetQuestStatus(11542) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(11543) == QUEST_STATUS_INCOMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CLOUDBREAKER2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13);
- break;
- case 25236: // Isle of Quel'Danas - Unrestrained Dragonhawk
- if (player->GetQuestStatus(11542) == QUEST_STATUS_COMPLETE || player->GetQuestStatus(11543) == QUEST_STATUS_COMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DRAGONHAWK, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 14);
- break;
case 20162: // Netherstorm - Veronia
//Behind Enemy Lines
if (player->GetQuestStatus(10652) != QUEST_STATUS_REWARDED)
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_VERONIA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 15);
break;
- case 23415: // Terokkar Forest - Skyguard Handler Deesak
- if (player->GetReputationRank(1031) >= REP_HONORED)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DEESAK, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 16);
- break;
case 23704: // Dustwallow Marsh - Cassa Crimsonwing
if (player->GetQuestStatus(11142) == QUEST_STATUS_INCOMPLETE)
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CRIMSONWING, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+25);
@@ -163,62 +97,10 @@ public:
player->ActivateTaxiPathTo(534); //TaxiPath 534
}
break;
- case GOSSIP_ACTION_INFO_DEF + 3:
- player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player, 53335, true); //TaxiPath 1041 (Stormwind Harbor)
- break;
- case GOSSIP_ACTION_INFO_DEF + 4:
- player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player, 33768, true); //TaxiPath 585 (Gateways Murket and Shaadraz)
- break;
- case GOSSIP_ACTION_INFO_DEF + 5:
- player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player, 35069, true); //TaxiPath 612 (Taxi - Hellfire Peninsula - Expedition Point to Shatter Point)
- break;
- case GOSSIP_ACTION_INFO_DEF + 6:
- player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player, 33899, true); //TaxiPath 589 (Aerial Assault Flight (Alliance))
- break;
- case GOSSIP_ACTION_INFO_DEF + 7:
- player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player, 35065, true); //TaxiPath 607 (Taxi - Hellfire Peninsula - Shatter Point to Beach Head)
- break;
- case GOSSIP_ACTION_INFO_DEF + 8:
- player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player, 33659, true); //TaxiPath 584 (Gateways Murket and Shaadraz)
- break;
- case GOSSIP_ACTION_INFO_DEF + 9:
- player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player, 33825, true); //TaxiPath 587 (Aerial Assault Flight (Horde))
- break;
- case GOSSIP_ACTION_INFO_DEF + 10:
- player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player, 34578, true); //TaxiPath 604 (Taxi - Reaver's Fall to Spinebreaker Ridge)
- break;
- case GOSSIP_ACTION_INFO_DEF + 11:
- player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player, 41278, true); //TaxiPath 706
- break;
- case GOSSIP_ACTION_INFO_DEF + 12:
- player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player, 45071, true); //TaxiPath 779
- break;
- case GOSSIP_ACTION_INFO_DEF + 13:
- player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player, 45113, true); //TaxiPath 784
- break;
- case GOSSIP_ACTION_INFO_DEF + 14:
- player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player, 45353, true); //TaxiPath 788
- break;
case GOSSIP_ACTION_INFO_DEF + 15:
player->CLOSE_GOSSIP_MENU();
player->CastSpell(player, 34905, true); //TaxiPath 606
break;
- case GOSSIP_ACTION_INFO_DEF + 16:
- player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player, 41279, true); //TaxiPath 705 (Taxi - Skettis to Skyguard Outpost)
- break;
case GOSSIP_ACTION_INFO_DEF + 25:
player->CLOSE_GOSSIP_MENU();
player->CastSpell(player, 42295, true);