aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp2
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h7
-rwxr-xr-xsrc/server/game/Battlegrounds/Zones/BattlegroundAV.cpp59
-rwxr-xr-xsrc/server/game/Battlegrounds/Zones/BattlegroundAV.h4
-rwxr-xr-xsrc/server/game/Chat/Channels/Channel.h9
-rwxr-xr-xsrc/server/game/Combat/HostileRefManager.cpp7
-rwxr-xr-xsrc/server/game/Combat/ThreatManager.cpp16
-rwxr-xr-xsrc/server/game/DataStores/DBCfmt.h2
-rwxr-xr-xsrc/server/game/Entities/Creature/GossipDef.cpp2
-rwxr-xr-xsrc/server/game/Entities/Player/Player.cpp34
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp39
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.h2
-rwxr-xr-xsrc/server/game/Globals/ObjectMgr.cpp8
-rwxr-xr-xsrc/server/game/Miscellaneous/Language.h1
-rwxr-xr-xsrc/server/game/Server/Protocol/Handlers/ChannelHandler.cpp18
-rwxr-xr-xsrc/server/game/Spells/Auras/SpellAuraEffects.cpp17
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp50
-rwxr-xr-xsrc/server/game/Spells/SpellEffects.cpp1
-rw-r--r--src/server/game/Spells/SpellInfo.cpp5
-rw-r--r--src/server/game/Spells/SpellInfo.h5
-rwxr-xr-xsrc/server/game/Spells/SpellMgr.cpp56
-rwxr-xr-xsrc/server/game/Spells/SpellMgr.h11
-rwxr-xr-xsrc/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp1
-rw-r--r--src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp57
-rw-r--r--src/server/scripts/Northrend/VaultOfArchavon/vault_of_archavon.h11
-rwxr-xr-xsrc/server/scripts/World/achievement_scripts.cpp45
26 files changed, 361 insertions, 108 deletions
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index 0de13280376..680c0815c6b 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -692,6 +692,8 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
return;
me->DoFleeToGetAssistance();
+ if (e.action.flee.withEmote)
+ sCreatureTextMgr->SendChatString(me, sObjectMgr->GetTrinityStringForDBCLocale(LANG_FLEE), CHAT_MSG_MONSTER_EMOTE);
sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_FLEE_FOR_ASSIST: Creature %u DoFleeToGetAssistance", me->GetGUIDLow());
break;
}
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index d6235b05667..de60737f3b6 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -383,7 +383,7 @@ enum SMART_ACTION
SMART_ACTION_SET_EVENT_PHASE = 22, // Phase
SMART_ACTION_INC_EVENT_PHASE = 23, // Value (may be negative to decrement phase, should not be 0)
SMART_ACTION_EVADE = 24, // No Params
- SMART_ACTION_FLEE_FOR_ASSIST = 25, // No Params
+ SMART_ACTION_FLEE_FOR_ASSIST = 25, // With Emote
SMART_ACTION_CALL_GROUPEVENTHAPPENS = 26, // QuestID
SMART_ACTION_CALL_CASTEDCREATUREORGO = 27, // CreatureId, SpellId
SMART_ACTION_REMOVEAURASFROMSPELL = 28, // Spellid
@@ -854,6 +854,11 @@ struct SmartAction
struct
{
+ uint32 withEmote;
+ } flee;
+
+ struct
+ {
uint32 param1;
uint32 param2;
uint32 param3;
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
index b01385e6536..d5dbdca976f 100755
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
@@ -1491,3 +1491,62 @@ void BattlegroundAV::ResetBGSubclass()
DelCreature(i);
}
+
+bool BattlegroundAV::IsBothMinesControlledByTeam(uint32 team) const
+{
+ for (uint8 mine = 0; mine < 2; mine++)
+ if (m_Mine_Owner[mine] != team)
+ return false;
+
+ return true;
+}
+
+bool BattlegroundAV::IsAllTowersControlledAndCaptainAlive(uint32 team) const
+{
+ if (team == ALLIANCE)
+ {
+ for (BG_AV_Nodes i = BG_AV_NODES_DUNBALDAR_SOUTH; i <= BG_AV_NODES_STONEHEART_BUNKER; ++i) // alliance towers controlled
+ {
+ if (m_Nodes[i].State == POINT_CONTROLED)
+ {
+ if (m_Nodes[i].Owner != ALLIANCE)
+ return false;
+ }
+ else
+ return false;
+ }
+
+ for (BG_AV_Nodes i = BG_AV_NODES_ICEBLOOD_TOWER; i <= BG_AV_NODES_FROSTWOLF_WTOWER; ++i) // horde towers destroyed
+ if (m_Nodes[i].State != POINT_DESTROYED)
+ return false;
+
+ if (!m_CaptainAlive[0])
+ return false;
+
+ return true;
+ }
+ else if (team == HORDE)
+ {
+ for (BG_AV_Nodes i = BG_AV_NODES_ICEBLOOD_TOWER; i <= BG_AV_NODES_FROSTWOLF_WTOWER; ++i) // horde towers controlled
+ {
+ if (m_Nodes[i].State == POINT_CONTROLED)
+ {
+ if (m_Nodes[i].Owner != HORDE)
+ return false;
+ }
+ else
+ return false;
+ }
+
+ for (BG_AV_Nodes i = BG_AV_NODES_DUNBALDAR_SOUTH; i <= BG_AV_NODES_STONEHEART_BUNKER; ++i) // alliance towers destroyed
+ if (m_Nodes[i].State != POINT_DESTROYED)
+ return false;
+
+ if (!m_CaptainAlive[1])
+ return false;
+
+ return true;
+ }
+
+ return false;
+} \ No newline at end of file
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h
index 5832a0f87c5..83fd559fdd4 100755
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h
@@ -1563,6 +1563,10 @@ class BattlegroundAV : public Battleground
virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player);
+ /* achievement req. */
+ bool IsBothMinesControlledByTeam(uint32 team) const;
+ bool IsAllTowersControlledAndCaptainAlive(uint32 team) const;
+
private:
virtual void PostUpdateImpl(uint32 diff);
diff --git a/src/server/game/Chat/Channels/Channel.h b/src/server/game/Chat/Channels/Channel.h
index 12f26022f59..c5466d65d3f 100755
--- a/src/server/game/Chat/Channels/Channel.h
+++ b/src/server/game/Chat/Channels/Channel.h
@@ -95,12 +95,13 @@ enum ChannelDBCFlags
CHANNEL_DBC_FLAG_INITIAL = 0x00001, // General, Trade, LocalDefense, LFG
CHANNEL_DBC_FLAG_ZONE_DEP = 0x00002, // General, Trade, LocalDefense, GuildRecruitment
CHANNEL_DBC_FLAG_GLOBAL = 0x00004, // WorldDefense
- CHANNEL_DBC_FLAG_TRADE = 0x00008, // Trade
- CHANNEL_DBC_FLAG_CITY_ONLY = 0x00010, // Trade, GuildRecruitment
- CHANNEL_DBC_FLAG_CITY_ONLY2 = 0x00020, // Trade, GuildRecruitment
+ CHANNEL_DBC_FLAG_TRADE = 0x00008, // Trade, LFG
+ CHANNEL_DBC_FLAG_CITY_ONLY = 0x00010, // Trade, GuildRecruitment, LFG
+ CHANNEL_DBC_FLAG_CITY_ONLY2 = 0x00020, // Trade, GuildRecruitment, LFG
CHANNEL_DBC_FLAG_DEFENSE = 0x10000, // LocalDefense, WorldDefense
CHANNEL_DBC_FLAG_GUILD_REQ = 0x20000, // GuildRecruitment
- CHANNEL_DBC_FLAG_LFG = 0x40000 // LookingForGroup
+ CHANNEL_DBC_FLAG_LFG = 0x40000, // LFG
+ CHANNEL_DBC_FLAG_UNK1 = 0x80000, // General
};
enum ChannelMemberFlags
diff --git a/src/server/game/Combat/HostileRefManager.cpp b/src/server/game/Combat/HostileRefManager.cpp
index 5d9e7d671c8..47e9a1d2508 100755
--- a/src/server/game/Combat/HostileRefManager.cpp
+++ b/src/server/game/Combat/HostileRefManager.cpp
@@ -40,10 +40,9 @@ void HostileRefManager::threatAssist(Unit* victim, float baseThreat, SpellInfo c
threat /= getSize();
while (ref)
{
- if (victim == getOwner())
- ref->addThreat(threat); // It is faster to modify the threat durectly if possible
- else
- ref->getSource()->addThreat(victim, threat);
+ if (ThreatCalcHelper::isValidProcess(victim, ref->getSource()->getOwner(), threatSpell))
+ ref->getSource()->doAddThreat(victim, threat);
+
ref = ref->next();
}
}
diff --git a/src/server/game/Combat/ThreatManager.cpp b/src/server/game/Combat/ThreatManager.cpp
index bf3650f611e..858ef057baf 100755
--- a/src/server/game/Combat/ThreatManager.cpp
+++ b/src/server/game/Combat/ThreatManager.cpp
@@ -36,8 +36,14 @@ float ThreatCalcHelper::calcThreat(Unit* hatedUnit, Unit* /*hatingUnit*/, float
{
if (threatSpell)
{
- if (threatSpell->AttributesEx & SPELL_ATTR1_NO_THREAT)
- return 0.0f;
+ if (SpellThreatEntry const* threatEntry = sSpellMgr->GetSpellThreatEntry(threatSpell->Id))
+ if (threatEntry->pctMod != 1.0f)
+ threat *= threatEntry->pctMod;
+
+ // Energize is not affected by Mods
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; i++)
+ if (threatSpell->Effects[i].Effect == SPELL_EFFECT_ENERGIZE || threatSpell->Effects[i].ApplyAuraName == SPELL_AURA_PERIODIC_ENERGIZE)
+ return threat;
if (Player* modOwner = hatedUnit->GetSpellModOwner())
modOwner->ApplySpellMod(threatSpell->Id, SPELLMOD_THREAT, threat);
@@ -46,7 +52,7 @@ float ThreatCalcHelper::calcThreat(Unit* hatedUnit, Unit* /*hatingUnit*/, float
return hatedUnit->ApplyTotalThreatModifier(threat, schoolMask);
}
-bool ThreatCalcHelper::isValidProcess(Unit* hatedUnit, Unit* hatingUnit, SpellInfo const* /*threatSpell*/)
+bool ThreatCalcHelper::isValidProcess(Unit* hatedUnit, Unit* hatingUnit, SpellInfo const* threatSpell)
{
//function deals with adding threat and adding players and pets into ThreatList
//mobs, NPCs, guards have ThreatList and HateOfflineList
@@ -68,6 +74,10 @@ bool ThreatCalcHelper::isValidProcess(Unit* hatedUnit, Unit* hatingUnit, SpellIn
if (!hatedUnit->isAlive() || !hatingUnit->isAlive())
return false;
+ // spell not causing threat
+ if (threatSpell && threatSpell->AttributesEx & SPELL_ATTR1_NO_THREAT)
+ return false;
+
ASSERT(hatingUnit->GetTypeId() == TYPEID_UNIT);
return true;
diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h
index 8f7ce9d8df3..0728a2f838e 100755
--- a/src/server/game/DataStores/DBCfmt.h
+++ b/src/server/game/DataStores/DBCfmt.h
@@ -99,7 +99,7 @@ const std::string CustomSpellDifficultyfmt="ppppp";
const std::string CustomSpellDifficultyIndex="id";
const char SpellDurationfmt[]="niii";
const char SpellEntryfmt[]="niiiiiiiiiiiixixiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiixxfffxx";
-const std::string CustomSpellEntryfmt="pappppppppaapapapaaaaaaaaaaapaaapapppppppaaaaapaapaaaaaaaaaaaaaaaaaappppppppppppppppppppppppppppppppppppaaaaaapppppppppaaapppppppppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaappppppppapppaaaaappaaaaaaa";
+const std::string CustomSpellEntryfmt="papppppppppppapapaaaaaaaaaaapaaapapppppppaaaaapaapaaaaaaaaaaaaaaaaaappppppppppppppppppppppppppppppppppppaaaaaapppppppppaaapppppppppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaappppppppapppaaaaappaaaaaaa";
const std::string CustomSpellEntryIndex = "Id";
const char SpellFocusObjectfmt[]="nxxxxxxxxxxxxxxxxx";
const char SpellItemEnchantmentfmt[]="nxiiiiiixxxiiissssssssssssssssxiiiiiii";
diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp
index e17f8163bff..0d91b476fdd 100755
--- a/src/server/game/Entities/Creature/GossipDef.cpp
+++ b/src/server/game/Entities/Creature/GossipDef.cpp
@@ -441,7 +441,7 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
data << uint32(quest->GetRepObjectiveFaction()); // shown in quest log as part of quest objective
data << uint32(quest->GetRepObjectiveValue()); // shown in quest log as part of quest objective
- data << uint32(quest->GetRepObjectiveFaction2()); // shown in quest log as part of quest objective OPOSITE faction
+ data << uint32(quest->GetRepObjectiveFaction2()); // shown in quest log as part of quest objective OPPOSITE faction
data << uint32(quest->GetRepObjectiveValue2()); // shown in quest log as part of quest objective OPPOSITE faction
data << uint32(quest->GetNextQuestInChain()); // client will request this quest from NPC, if not 0
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 8742deb2eb5..e0adb99bc37 100755
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -5522,14 +5522,14 @@ void Player::RepopAtGraveyard()
bool Player::CanJoinConstantChannelInZone(ChatChannelsEntry const* channel, AreaTableEntry const* zone)
{
- if (channel->flags & CHANNEL_DBC_FLAG_ZONE_DEP)
- {
- if (zone->flags & AREA_FLAG_ARENA_INSTANCE)
- return false;
+ if (channel->flags & CHANNEL_DBC_FLAG_ZONE_DEP && zone->flags & AREA_FLAG_ARENA_INSTANCE)
+ return false;
- if ((channel->flags & CHANNEL_DBC_FLAG_CITY_ONLY) && !(zone->flags & AREA_FLAG_CAPITAL))
- return false;
- }
+ if ((channel->flags & CHANNEL_DBC_FLAG_CITY_ONLY) && (!(zone->flags & AREA_FLAG_SLAVE_CAPITAL)))
+ return false;
+
+ if ((channel->flags & CHANNEL_DBC_FLAG_GUILD_REQ) && GetGuildId())
+ return false;
return true;
}
@@ -5577,12 +5577,6 @@ void Player::UpdateLocalChannels(uint32 newZone)
{
if (ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(i))
{
- if (!(channel->flags & CHANNEL_DBC_FLAG_ZONE_DEP))
- continue; // Not zone dependent, don't handle it here
-
- if ((channel->flags & CHANNEL_DBC_FLAG_GUILD_REQ) && GetGuildId())
- continue; // Should not join to these channels automatically
-
Channel* usedChannel = NULL;
for (JoinedChannelsList::iterator itr = m_channels.begin(); itr != m_channels.end(); ++itr)
@@ -14636,10 +14630,6 @@ bool Player::CanCompleteQuest(uint32 quest_id)
if (repFacId && GetReputationMgr().GetReputation(repFacId) < qInfo->GetRepObjectiveValue())
return false;
- uint32 repFacId2 = qInfo->GetRepObjectiveFaction2();
- if (repFacId2 && GetReputationMgr().GetReputation(repFacId2) < qInfo->GetRepObjectiveValue2())
- return false;
-
return true;
}
}
@@ -15272,6 +15262,16 @@ bool Player::SatisfyQuestReputation(Quest const* qInfo, bool msg)
SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ);
return false;
}
+
+ // ReputationObjective2 does not seem to be an objective requirement but a requirement
+ // to be able to accept the quest
+ uint32 fIdObj = qInfo->GetRepObjectiveFaction2();
+ if (fIdObj && GetReputationMgr().GetReputation(fIdObj) >= qInfo->GetRepObjectiveValue2())
+ {
+ if (msg)
+ SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ);
+ return false;
+ }
return true;
}
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 4cea8f56005..be46e9b1ffb 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -791,12 +791,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
victim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_DIRECT_DAMAGE, spellProto ? spellProto->Id : 0);
if (victim->GetTypeId() != TYPEID_PLAYER)
- {
- if (spellProto && IsDamageToThreatSpell(spellProto))
- victim->AddThreat(this, damage * 2.0f, damageSchoolMask, spellProto);
- else
victim->AddThreat(this, (float)damage, damageSchoolMask, spellProto);
- }
else // victim is a player
{
// random durability for items (HIT TAKEN)
@@ -6603,6 +6598,13 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
return true;
}
}
+ // Misdirection
+ if (dummySpell->Id == 34477)
+ {
+ triggered_spell_id = 35079; // 4 sec buff on self
+ target = this;
+ break;
+ }
break;
}
case SPELLFAMILY_PALADIN:
@@ -10334,6 +10336,9 @@ void Unit::EnergizeBySpell(Unit* victim, uint32 spellID, uint32 damage, Powers p
SendEnergizeSpellLog(victim, spellID, damage, powerType);
// needs to be called after sending spell log
victim->ModifyPower(powerType, damage);
+
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
+ victim->getHostileRefManager().threatAssist(this, float(damage) * 0.5f, spellInfo);
}
uint32 Unit::SpellDamageBonus(Unit* victim, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack)
@@ -11622,30 +11627,6 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) cons
return false;
}
-bool Unit::IsDamageToThreatSpell(SpellInfo const* spellInfo) const
-{
- if (!spellInfo)
- return false;
-
- switch(spellInfo->SpellFamilyName)
- {
- case SPELLFAMILY_WARLOCK:
- if (spellInfo->SpellFamilyFlags[0] == 0x100) // Searing Pain
- return true;
- break;
- case SPELLFAMILY_SHAMAN:
- if (spellInfo->SpellFamilyFlags[0] == SPELLFAMILYFLAG_SHAMAN_FROST_SHOCK)
- return true;
- break;
- case SPELLFAMILY_DEATHKNIGHT:
- if (spellInfo->SpellFamilyFlags[1] == 0x20000000) // Rune Strike
- return true;
- break;
- }
-
- return false;
-}
-
void Unit::MeleeDamageBonus(Unit* victim, uint32 *pdamage, WeaponAttackType attType, SpellInfo const* spellProto)
{
if (!victim)
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index e777f16b99a..fb41914d6f7 100755
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1572,8 +1572,6 @@ class Unit : public WorldObject
void SendPlaySpellVisual(uint32 id);
void SendPlaySpellImpact(uint64 guid, uint32 id);
- bool IsDamageToThreatSpell(SpellInfo const* spellInfo) const;
-
void DeMorph();
void SendAttackStateUpdate(CalcDamageInfo *damageInfo);
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index e1b37c121a7..62b2ce0c440 100755
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -3931,28 +3931,28 @@ void ObjectMgr::LoadQuests()
// no changes, quest can't be done for this requirement
}
- if (!qinfo->RepObjectiveFaction && qinfo->RepObjectiveValue > 0)
+ if (!qinfo->RepObjectiveFaction && qinfo->RepObjectiveValue != 0)
{
sLog->outErrorDb("Quest %u has `RepObjectiveValue` = %d but `RepObjectiveFaction` is 0, value has no effect",
qinfo->GetQuestId(), qinfo->RepObjectiveValue);
// warning
}
- if (!qinfo->RepObjectiveFaction2 && qinfo->RepObjectiveValue2 > 0)
+ if (!qinfo->RepObjectiveFaction2 && qinfo->RepObjectiveValue2 != 0)
{
sLog->outErrorDb("Quest %u has `RepObjectiveValue2` = %d but `RepObjectiveFaction2` is 0, value has no effect",
qinfo->GetQuestId(), qinfo->RepObjectiveValue2);
// warning
}
- if (!qinfo->RequiredMinRepFaction && qinfo->RequiredMinRepValue > 0)
+ if (!qinfo->RequiredMinRepFaction && qinfo->RequiredMinRepValue != 0)
{
sLog->outErrorDb("Quest %u has `RequiredMinRepValue` = %d but `RequiredMinRepFaction` is 0, value has no effect",
qinfo->GetQuestId(), qinfo->RequiredMinRepValue);
// warning
}
- if (!qinfo->RequiredMaxRepFaction && qinfo->RequiredMaxRepValue > 0)
+ if (!qinfo->RequiredMaxRepFaction && qinfo->RequiredMaxRepValue != 0)
{
sLog->outErrorDb("Quest %u has `RequiredMaxRepValue` = %d but `RequiredMaxRepFaction` is 0, value has no effect",
qinfo->GetQuestId(), qinfo->RequiredMaxRepValue);
diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h
index e824a3cf5da..9e8a4b17f84 100755
--- a/src/server/game/Miscellaneous/Language.h
+++ b/src/server/game/Miscellaneous/Language.h
@@ -943,6 +943,7 @@ enum TrinityStrings
LANG_GOINFO_LOOTID = 5028,
LANG_COMMAND_LOOKUP_MAX_RESULTS = 5029,
// Room for more Trinity strings 5030-9999
+ LANG_FLEE = 5030,
// Level requirement notifications
LANG_SAY_REQ = 6604,
diff --git a/src/server/game/Server/Protocol/Handlers/ChannelHandler.cpp b/src/server/game/Server/Protocol/Handlers/ChannelHandler.cpp
index 0ccfce64045..3f9609bc0e0 100755
--- a/src/server/game/Server/Protocol/Handlers/ChannelHandler.cpp
+++ b/src/server/game/Server/Protocol/Handlers/ChannelHandler.cpp
@@ -26,21 +26,15 @@ void WorldSession::HandleJoinChannel(WorldPacket& recvPacket)
uint32 channel_id;
uint8 unknown1, unknown2;
std::string channelname, pass;
+ ChatChannelsEntry const* channel;
recvPacket >> channel_id;
if (channel_id)
{
- ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(channel_id);
+ channel = sChatChannelsStore.LookupEntry(channel_id);
if (!channel)
return;
-
- AreaTableEntry const* current_zone = GetAreaEntryByAreaID(_player->GetZoneId());
- if (!current_zone)
- return;
-
- if (!_player->CanJoinConstantChannelInZone(channel, current_zone))
- return;
}
recvPacket >> unknown1 >> unknown2;
@@ -50,6 +44,14 @@ void WorldSession::HandleJoinChannel(WorldPacket& recvPacket)
return;
recvPacket >> pass;
+
+ AreaTableEntry const* current_zone = GetAreaEntryByAreaID(_player->GetZoneId());
+ if (!current_zone)
+ return;
+
+ if (!_player->CanJoinConstantChannelInZone(channel, current_zone))
+ return;
+
if (ChannelMgr* cMgr = channelMgr(_player->GetTeam()))
{
cMgr->team = _player->GetTeam();
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 8b68bff0a56..0fe54f2f2e8 100755
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -4927,22 +4927,18 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
case SPELLFAMILY_PRIEST:
// Vampiric Touch
if (m_spellInfo->SpellFamilyFlags[1] & 0x0400 && aurApp->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL && GetEffIndex() == 0)
- {
if (AuraEffect const* aurEff = GetBase()->GetEffect(1))
{
int32 damage = aurEff->GetAmount() * 8;
// backfire damage
target->CastCustomSpell(target, 64085, &damage, NULL, NULL, true, NULL, NULL, GetCasterGUID());
}
- }
break;
case SPELLFAMILY_WARLOCK:
// Haunt
if (m_spellInfo->SpellFamilyFlags[1] & 0x40000)
- {
if (caster)
target->CastCustomSpell(caster, 48210, &m_amount, 0, 0, true, NULL, this, GetCasterGUID());
- }
break;
case SPELLFAMILY_DRUID:
// Lifebloom
@@ -4965,9 +4961,16 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
}
break;
case SPELLFAMILY_HUNTER:
- // Misdirection
- if (GetId() == 34477)
- target->SetReducedThreatPercent(0, 0);
+ switch (GetId())
+ {
+ case 34477: // Misdirection
+ if (aurApp->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE)
+ target->SetReducedThreatPercent(0, 0);
+ break;
+ case 35079: // Misdirection proc
+ target->SetReducedThreatPercent(0, 0);
+ break;
+ }
break;
case SPELLFAMILY_DEATHKNIGHT:
// Summon Gargoyle (Dismiss Gargoyle at remove)
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index ed36a4ae208..5642df13d8a 100755
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -2335,7 +2335,7 @@ void Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur)
}
else
{
- sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: unknown target coordinates for spell ID %u", m_spellInfo->Id);
+ sLog->outError("SPELL: unknown target coordinates for spell ID %u", m_spellInfo->Id);
Unit* target = NULL;
if (uint64 guid = m_caster->GetUInt64Value(UNIT_FIELD_TARGET))
target = ObjectAccessor::GetUnit(*m_caster, guid);
@@ -4536,20 +4536,53 @@ void Spell::TakeReagents()
void Spell::HandleThreatSpells()
{
- if (!m_targets.GetUnitTarget())
+ if (m_UniqueTargetInfo.empty())
return;
- if (!m_targets.GetUnitTarget()->CanHaveThreatList())
+ if ((m_spellInfo->AttributesEx & SPELL_ATTR1_NO_THREAT) ||
+ (m_spellInfo->AttributesEx3 & SPELL_ATTR3_NO_INITIAL_AGGRO))
return;
- uint16 threat = sSpellMgr->GetSpellThreat(m_spellInfo->Id);
+ float threat = 0.0f;
+ if (SpellThreatEntry const* threatEntry = sSpellMgr->GetSpellThreatEntry(m_spellInfo->Id))
+ {
+ if (threatEntry->apPctMod != 0.0f)
+ threat += threatEntry->apPctMod * m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
+
+ threat += threatEntry->flatMod;
+ }
+ else if ((m_spellInfo->AttributesCu & SPELL_ATTR0_CU_NO_INITIAL_THREAT) == 0)
+ threat += m_spellInfo->SpellLevel;
- if (!threat)
+ // past this point only multiplicative effects occur
+ if (threat == 0.0f)
return;
- m_targets.GetUnitTarget()->AddThreat(m_caster, float(threat));
+ // since 2.0.1 threat from positive effects also is distributed among all targets, so the overall caused threat is at most the defined bonus
+ threat /= m_UniqueTargetInfo.size();
+
+ for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
+ {
+ if (ihit->missCondition != SPELL_MISS_NONE)
+ continue;
+
+ Unit* target = ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
+ if (!target)
+ continue;
+
+ // positive spells distribute threat among all units that are in combat with target, like healing
+ if (m_spellInfo->_IsPositiveSpell())
+ target->getHostileRefManager().threatAssist(m_caster, threat, m_spellInfo);
+ // for negative spells threat gets distributed among affected targets
+ else
+ {
+ if (!target->CanHaveThreatList())
+ continue;
- sLog->outStaticDebug("Spell %u, rank %u, added an additional %i threat", m_spellInfo->Id, m_spellInfo->GetRank(), threat);
+ target->AddThreat(m_caster, threat, m_spellInfo->GetSchoolMask(), m_spellInfo);
+ }
+ }
+ sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell %u, added an additional %f threat for %s %u target(s)", m_spellInfo->Id, threat, m_spellInfo->_IsPositiveSpell() ? "assisting" : "harming", uint32(m_UniqueTargetInfo.size()));
}
void Spell::HandleEffects(Unit *pUnitTarget, Item *pItemTarget, GameObject *pGOTarget, uint32 i)
@@ -4723,7 +4756,8 @@ SpellCastResult Spell::CheckCast(bool strict)
}
{
- SpellCastResult castResult = m_spellInfo->CheckExplicitTarget(m_caster, m_targets.GetObjectTarget());
+ // Check explicit target for m_originalCaster - todo: get rid of such workarounds
+ SpellCastResult castResult = m_spellInfo->CheckExplicitTarget(m_originalCaster ? m_originalCaster : m_caster, m_targets.GetObjectTarget(), m_targets.GetItemTarget());
if (castResult != SPELL_CAST_OK)
return castResult;
}
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 93f9640b92a..8dd1cc0242d 100755
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -3275,6 +3275,7 @@ void Spell::EffectDistract(SpellEffIndex /*effIndex*/)
unitTarget->SetOrientation(angle);
unitTarget->StopMoving();
unitTarget->GetMotionMaster()->MoveDistract(damage * IN_MILLISECONDS);
+ unitTarget->SendMovementFlagUpdate();
}
}
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 04e90d2083b..3e374b62cd1 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -1721,13 +1721,14 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, Unit const* target, b
return SPELL_CAST_OK;
}
-SpellCastResult SpellInfo::CheckExplicitTarget(Unit const* caster, WorldObject const* target) const
+SpellCastResult SpellInfo::CheckExplicitTarget(Unit const* caster, WorldObject const* target, Item const* itemTarget) const
{
uint32 neededTargets = GetExplicitTargetMask();
if (!target)
{
if (neededTargets & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_GAMEOBJECT_MASK | TARGET_FLAG_CORPSE_MASK))
- return SPELL_FAILED_BAD_TARGETS;
+ if (!(neededTargets & TARGET_FLAG_GAMEOBJECT_ITEM) || !itemTarget)
+ return SPELL_FAILED_BAD_TARGETS;
return SPELL_CAST_OK;
}
diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h
index 69f160cbb0f..b79e50db001 100644
--- a/src/server/game/Spells/SpellInfo.h
+++ b/src/server/game/Spells/SpellInfo.h
@@ -24,6 +24,7 @@
class Unit;
class Player;
+class Item;
class Spell;
class SpellInfo;
struct SpellChainNode;
@@ -186,7 +187,7 @@ enum SpellCustomAttributes
SPELL_ATTR0_CU_CONE_BACK = 0x00000002,
SPELL_ATTR0_CU_CONE_LINE = 0x00000004,
SPELL_ATTR0_CU_SHARE_DAMAGE = 0x00000008,
- SPELL_ATTR0_CU_NONE1 = 0x00000010, // UNUSED
+ SPELL_ATTR0_CU_NO_INITIAL_THREAT = 0x00000010,
SPELL_ATTR0_CU_NONE2 = 0x00000020, // UNUSED
SPELL_ATTR0_CU_AURA_CC = 0x00000040,
SPELL_ATTR0_CU_DIRECT_DAMAGE = 0x00000100,
@@ -442,7 +443,7 @@ public:
SpellCastResult CheckShapeshift(uint32 form) const;
SpellCastResult CheckLocation(uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player = NULL) const;
SpellCastResult CheckTarget(Unit const* caster, Unit const* target, bool implicit = true) const;
- SpellCastResult CheckExplicitTarget(Unit const* caster, WorldObject const* target) const;
+ SpellCastResult CheckExplicitTarget(Unit const* caster, WorldObject const* target, Item const* itemTarget = NULL) const;
bool CheckTargetCreatureType(Unit const* target) const;
SpellSchoolMask GetSchoolMask() const;
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 3b546a94bfa..85139061303 100755
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -965,13 +965,19 @@ SpellBonusEntry const* SpellMgr::GetSpellBonusData(uint32 spellId) const
return NULL;
}
-uint16 SpellMgr::GetSpellThreat(uint32 spellid) const
+SpellThreatEntry const* SpellMgr::GetSpellThreatEntry(uint32 spellID) const
{
- SpellThreatMap::const_iterator itr = mSpellThreatMap.find(spellid);
- if (itr == mSpellThreatMap.end())
- return 0;
-
- return itr->second;
+ SpellThreatMap::const_iterator itr = mSpellThreatMap.find(spellID);
+ if (itr != mSpellThreatMap.end())
+ return &itr->second;
+ else
+ {
+ uint32 firstSpell = GetFirstSpellInChain(spellID);
+ SpellThreatMap::const_iterator itr = mSpellThreatMap.find(firstSpell);
+ if (itr != mSpellThreatMap.end())
+ return &itr->second;
+ }
+ return NULL;
}
SkillLineAbilityMapBounds SpellMgr::GetSkillLineAbilityMapBounds(uint32 spell_id) const
@@ -1940,8 +1946,8 @@ void SpellMgr::LoadSpellThreats()
uint32 count = 0;
- // 0 1
- QueryResult result = WorldDatabase.Query("SELECT entry, Threat FROM spell_threat");
+ // 0 1 2 3
+ QueryResult result = WorldDatabase.Query("SELECT entry, flatMod, pctMod, apPctMod FROM spell_threat");
if (!result)
{
sLog->outString(">> Loaded 0 aggro generating spells");
@@ -1954,7 +1960,6 @@ void SpellMgr::LoadSpellThreats()
Field *fields = result->Fetch();
uint32 entry = fields[0].GetUInt32();
- uint16 Threat = fields[1].GetUInt16();
if (!GetSpellInfo(entry))
{
@@ -1962,12 +1967,16 @@ void SpellMgr::LoadSpellThreats()
continue;
}
- mSpellThreatMap[entry] = Threat;
+ SpellThreatEntry ste;
+ ste.flatMod = fields[1].GetInt16();
+ ste.pctMod = fields[2].GetFloat();
+ ste.apPctMod = fields[3].GetFloat();
- ++count;
+ mSpellThreatMap[entry] = ste;
+ count++;
} while (result->NextRow());
- sLog->outString(">> Loaded %u aggro generating spells in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+ sLog->outString(">> Loaded %u SpellThreatEntries in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
sLog->outString();
}
@@ -2634,6 +2643,18 @@ void SpellMgr::LoadSpellCustomAttr()
case SPELL_AURA_MOD_STUN:
spellInfo->AttributesCu |= SPELL_ATTR0_CU_AURA_CC;
break;
+ case SPELL_AURA_PERIODIC_HEAL:
+ case SPELL_AURA_PERIODIC_DAMAGE:
+ case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
+ case SPELL_AURA_PERIODIC_LEECH:
+ case SPELL_AURA_PERIODIC_MANA_LEECH:
+ case SPELL_AURA_PERIODIC_HEALTH_FUNNEL:
+ case SPELL_AURA_PERIODIC_ENERGIZE:
+ case SPELL_AURA_OBS_MOD_HEALTH:
+ case SPELL_AURA_OBS_MOD_POWER:
+ case SPELL_AURA_POWER_BURN:
+ spellInfo->AttributesCu |= SPELL_ATTR0_CU_NO_INITIAL_THREAT;
+ break;
}
switch (spellInfo->Effects[j].Effect)
@@ -2646,6 +2667,16 @@ void SpellMgr::LoadSpellCustomAttr()
case SPELL_EFFECT_HEAL:
spellInfo->AttributesCu |= SPELL_ATTR0_CU_DIRECT_DAMAGE;
break;
+ case SPELL_EFFECT_POWER_DRAIN:
+ case SPELL_EFFECT_POWER_BURN:
+ case SPELL_EFFECT_HEAL_MAX_HEALTH:
+ case SPELL_EFFECT_HEALTH_LEECH:
+ case SPELL_EFFECT_HEAL_PCT:
+ case SPELL_EFFECT_ENERGIZE_PCT:
+ case SPELL_EFFECT_ENERGIZE:
+ case SPELL_EFFECT_HEAL_MECHANICAL:
+ spellInfo->AttributesCu |= SPELL_ATTR0_CU_NO_INITIAL_THREAT;
+ break;
case SPELL_EFFECT_CHARGE:
case SPELL_EFFECT_CHARGE_DEST:
case SPELL_EFFECT_JUMP:
@@ -3032,6 +3063,7 @@ void SpellMgr::LoadDbcDataCorrections()
case 57761: // Fireball!
case 39805: // Lightning Overload
case 64823: // Item - Druid T8 Balance 4P Bonus
+ case 34477: // Misdirection
case 44401: // Missile Barrage
spellInfo->procCharges = 1;
break;
diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h
index e8ac3ce9862..64d21b7c3a5 100755
--- a/src/server/game/Spells/SpellMgr.h
+++ b/src/server/game/Spells/SpellMgr.h
@@ -349,7 +349,14 @@ enum SpellGroupStackRule
typedef std::map<SpellGroup, SpellGroupStackRule> SpellGroupStackMap;
-typedef std::map<uint32, uint16> SpellThreatMap;
+struct SpellThreatEntry
+{
+ int32 flatMod; // flat threat-value for this Spell - default: 0
+ float pctMod; // threat-multiplier for this Spell - default: 1.0f
+ float apPctMod; // Pct of AP that is added as Threat - default: 0.0f
+};
+
+typedef std::map<uint32, SpellThreatEntry> SpellThreatMap;
// Spell script target related declarations (accessed using SpellMgr functions)
enum SpellScriptTargetType
@@ -603,7 +610,7 @@ class SpellMgr
SpellBonusEntry const* GetSpellBonusData(uint32 spellId) const;
// Spell threat table
- uint16 GetSpellThreat(uint32 spellid) const;
+ SpellThreatEntry const* GetSpellThreatEntry(uint32 spellID) const;
SkillLineAbilityMapBounds GetSkillLineAbilityMapBounds(uint32 spell_id) const;
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp
index 91cd8dee55c..7566d9bc410 100755
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp
@@ -85,7 +85,6 @@ class instance_trial_of_the_crusader : public InstanceMapScript
EventStage = 0;
TributeChestGUID = 0;
- DataDamageTwin = 0;
MainGateDoorGUID = 0;
EastPortcullisGUID = 0;
diff --git a/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp
index 904566e13a4..8d668011f9a 100644
--- a/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp
+++ b/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp
@@ -41,6 +41,9 @@ class instance_archavon : public InstanceMapScript
{
EmalonGUID = 0;
ToravonGUID = 0;
+ ArchavonDeath = 0;
+ EmalonDeath = 0;
+ KoralonDeath = 0;
}
void OnCreatureCreate(Creature* creature)
@@ -73,9 +76,63 @@ class instance_archavon : public InstanceMapScript
return 0;
}
+ bool SetBossState(uint32 type, EncounterState state)
+ {
+ if (!InstanceScript::SetBossState(type, state))
+ return false;
+
+ if (state != DONE)
+ return true;
+
+ switch (type)
+ {
+ case DATA_ARCHAVON:
+ ArchavonDeath = time(NULL);
+ break;
+ case DATA_EMALON:
+ EmalonDeath = time(NULL);
+ break;
+ case DATA_KORALON:
+ KoralonDeath = time(NULL);
+ break;
+ default:
+ return true;
+ }
+
+ // on every death of Archavon, Emalon and Koralon check our achievement
+ DoCastSpellOnPlayers(SPELL_EARTH_WIND_FIRE_ACHIEVEMENT_CHECK);
+
+ return true;
+ }
+
+ bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target*/, uint32 /*miscvalue1*/)
+ {
+ switch (criteria_id)
+ {
+ case CRITERIA_EARTH_WIND_FIRE_10:
+ case CRITERIA_EARTH_WIND_FIRE_25:
+ if (ArchavonDeath && EmalonDeath && KoralonDeath)
+ {
+ // instance difficulty check is already done in db (achievement_criteria_data)
+ // int() for Visual Studio, compile errors with abs(time_t)
+ return (abs(int(ArchavonDeath-EmalonDeath)) < MINUTE && \
+ abs(int(EmalonDeath-KoralonDeath)) < MINUTE && \
+ abs(int(KoralonDeath-ArchavonDeath)) < MINUTE);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return false;
+ }
+
private:
uint64 EmalonGUID;
uint64 ToravonGUID;
+ time_t ArchavonDeath;
+ time_t EmalonDeath;
+ time_t KoralonDeath;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const
diff --git a/src/server/scripts/Northrend/VaultOfArchavon/vault_of_archavon.h b/src/server/scripts/Northrend/VaultOfArchavon/vault_of_archavon.h
index 4aa01e58f5f..04f50d3adeb 100644
--- a/src/server/scripts/Northrend/VaultOfArchavon/vault_of_archavon.h
+++ b/src/server/scripts/Northrend/VaultOfArchavon/vault_of_archavon.h
@@ -36,4 +36,15 @@ enum Data
#define MAX_ENCOUNTER 4
+enum AchievementCriteriaIds
+{
+ CRITERIA_EARTH_WIND_FIRE_10 = 12018,
+ CRITERIA_EARTH_WIND_FIRE_25 = 12019,
+};
+
+enum AchievementSpells
+{
+ SPELL_EARTH_WIND_FIRE_ACHIEVEMENT_CHECK = 68308,
+};
+
#endif
diff --git a/src/server/scripts/World/achievement_scripts.cpp b/src/server/scripts/World/achievement_scripts.cpp
index db09c12da0b..af966e3e22e 100755
--- a/src/server/scripts/World/achievement_scripts.cpp
+++ b/src/server/scripts/World/achievement_scripts.cpp
@@ -21,6 +21,7 @@
#include "BattlegroundWS.h"
#include "BattlegroundIC.h"
#include "BattlegroundSA.h"
+#include "BattlegroundAV.h"
#include "Vehicle.h"
class achievement_storm_glory : public AchievementCriteriaScript
@@ -207,6 +208,48 @@ public:
}
};
+class achievement_everything_counts : public AchievementCriteriaScript
+{
+ public:
+ achievement_everything_counts() : AchievementCriteriaScript("achievement_everything_counts") { }
+
+ bool OnCheck(Player* source, Unit* /*target*/)
+ {
+ Battleground* bg = source->GetBattleground();
+ if (!bg)
+ return false;
+
+ if (source->GetBattlegroundTypeId() != BATTLEGROUND_AV)
+ return false;
+
+ if (static_cast<BattlegroundAV*>(bg)->IsBothMinesControlledByTeam(source->GetTeam()))
+ return true;
+
+ return false;
+ }
+};
+
+class achievement_bg_av_perfection : public AchievementCriteriaScript
+{
+ public:
+ achievement_bg_av_perfection() : AchievementCriteriaScript("achievement_bg_av_perfection") { }
+
+ bool OnCheck(Player* source, Unit* /*target*/)
+ {
+ Battleground* bg = source->GetBattleground();
+ if (!bg)
+ return false;
+
+ if (source->GetBattlegroundTypeId() != BATTLEGROUND_AV)
+ return false;
+
+ if (static_cast<BattlegroundAV*>(bg)->IsAllTowersControlledAndCaptainAlive(source->GetTeam()))
+ return true;
+
+ return false;
+ }
+};
+
class achievement_wg_didnt_stand_a_chance : public AchievementCriteriaScript
{
public:
@@ -269,6 +312,8 @@ void AddSC_achievement_scripts()
new achievement_bg_sa_artillery();
new achievement_sickly_gazelle();
new achievement_wg_didnt_stand_a_chance();
+ new achievement_everything_counts();
+ new achievement_bg_av_perfection();
new achievement_arena_kills("achievement_arena_2v2_kills", ARENA_TYPE_2v2);
new achievement_arena_kills("achievement_arena_3v3_kills", ARENA_TYPE_3v3);
new achievement_arena_kills("achievement_arena_5v5_kills", ARENA_TYPE_5v5);