aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/game/CreatureEventAIMgr.cpp3
-rw-r--r--src/game/DestinationHolderImp.h2
-rw-r--r--src/game/Group.cpp2
-rw-r--r--src/game/ItemHandler.cpp26
-rw-r--r--src/game/Level3.cpp7
-rw-r--r--src/game/Player.cpp157
-rw-r--r--src/game/Player.h7
-rw-r--r--src/game/PointMovementGenerator.cpp3
-rw-r--r--src/game/SharedDefines.h5
-rw-r--r--src/game/SkillDiscovery.cpp2
-rw-r--r--src/game/Spell.cpp30
-rw-r--r--src/game/SpellAuras.cpp2
-rw-r--r--src/game/SpellEffects.cpp36
-rw-r--r--src/game/SpellMgr.cpp41
-rw-r--r--src/game/Unit.cpp142
15 files changed, 259 insertions, 206 deletions
diff --git a/src/game/CreatureEventAIMgr.cpp b/src/game/CreatureEventAIMgr.cpp
index 38cc84177e4..18db935536b 100644
--- a/src/game/CreatureEventAIMgr.cpp
+++ b/src/game/CreatureEventAIMgr.cpp
@@ -473,9 +473,8 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
action.morph.modelId = 0;
}
}
-
- break;
}
+ break;
case ACTION_T_SOUND:
if (!sSoundEntriesStore.LookupEntry(action.sound.soundId))
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SoundID %u.", i, j+1, action.sound.soundId);
diff --git a/src/game/DestinationHolderImp.h b/src/game/DestinationHolderImp.h
index d50d8c3e727..c84ce19a96d 100644
--- a/src/game/DestinationHolderImp.h
+++ b/src/game/DestinationHolderImp.h
@@ -142,7 +142,7 @@ DestinationHolder<TRAVELLER>::UpdateTraveller(TRAVELLER &traveller, uint32 diff,
i_fromZ = z;
}
- if( traveller.GetTraveller().GetPositionX() != x || traveller.GetTraveller().GetPositionY() != y )
+ if( traveller.GetTraveller().GetPositionX() != x || traveller.GetTraveller().GetPositionY() != y || traveller.GetTraveller().GetPositionZ() != z)
{
float ori = traveller.GetTraveller().GetAngle(x, y);
traveller.Relocation(x, y, z, ori);
diff --git a/src/game/Group.cpp b/src/game/Group.cpp
index 9db043b28f1..8a02afa25d2 100644
--- a/src/game/Group.cpp
+++ b/src/game/Group.cpp
@@ -1510,7 +1510,7 @@ void Group::ResetInstances(uint8 method, Player* SendMsgTo)
bool isEmpty = true;
// if the map is loaded, reset it
Map *map = MapManager::Instance().FindMap(p->GetMapId(), p->GetInstanceId());
- if(map && map->IsDungeon())
+ if(map && map->IsDungeon() && !(method == INSTANCE_RESET_GROUP_DISBAND && !p->CanReset()))
{
if(p->CanReset())
isEmpty = ((InstanceMap*)map)->Reset(method);
diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp
index cf762dd0cb2..d886cda742b 100644
--- a/src/game/ItemHandler.cpp
+++ b/src/game/ItemHandler.cpp
@@ -674,7 +674,31 @@ void WorldSession::HandleBuyItemInSlotOpcode( WorldPacket & recv_data )
recv_data >> vendorguid >> item >> slot >> bagguid >> bagslot >> count;
- GetPlayer()->BuyItemFromVendor(vendorguid,item,count,bagguid,bagslot);
+ uint8 bag = NULL_BAG; // init for case invalid bagGUID
+
+ // find bag slot by bag guid
+ if (bagguid == _player->GetGUID())
+ bag = INVENTORY_SLOT_BAG_0;
+ else
+ {
+ for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END;++i)
+ {
+ if (Bag *pBag = (Bag*)_player->GetItemByPos(INVENTORY_SLOT_BAG_0,i))
+ {
+ if (bagguid == pBag->GetGUID())
+ {
+ bag = i;
+ break;
+ }
+ }
+ }
+ }
+
+ // bag not found, cheating?
+ if (bag == NULL_BAG)
+ return;
+
+ GetPlayer()->BuyItemFromVendor(vendorguid,item,count,bag,bagslot);
}
void WorldSession::HandleBuyItemOpcode( WorldPacket & recv_data )
diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp
index ba956ac38f4..a099aa8f66c 100644
--- a/src/game/Level3.cpp
+++ b/src/game/Level3.cpp
@@ -1640,6 +1640,9 @@ bool ChatHandler::HandleUnLearnCommand(const char* args)
else
SendSysMessage(LANG_FORGET_SPELL);
+ if(GetTalentSpellCost(spell_id))
+ target->SendTalentsInfoData(false);
+
return true;
}
@@ -2582,6 +2585,10 @@ bool ChatHandler::HandleLearnCommand(const char* args)
else
targetPlayer->learnSpell(spell,false);
+ uint32 first_spell = spellmgr.GetFirstSpellInChain(spell);
+ if(GetTalentSpellCost(first_spell))
+ targetPlayer->SendTalentsInfoData(false);
+
return true;
}
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index 15dc3c69bd8..a3f784ac292 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -2992,7 +2992,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
if(!rankSpellId || rankSpellId==spell_id)
continue;
- removeSpell(rankSpellId);
+ removeSpell(rankSpellId,false,false);
}
}
}
@@ -3268,7 +3268,7 @@ void Player::learnSpell(uint32 spell_id, bool dependent)
GetSession()->SendPacket(&data);
}
-void Player::removeSpell(uint32 spell_id, bool disabled, bool update_action_bar_for_low_rank)
+void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank)
{
PlayerSpellMap::iterator itr = m_spells.find(spell_id);
if (itr == m_spells.end())
@@ -3288,7 +3288,7 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool update_action_bar_
SpellsRequiringSpellMap const& reqMap = spellmgr.GetSpellsRequiringSpell();
SpellsRequiringSpellMap::const_iterator itr2 = reqMap.find(spell_id);
for (uint32 i=reqMap.count(spell_id);i>0;i--,itr2++)
- removeSpell(itr2->second,disabled);
+ removeSpell(itr2->second,disabled,false);
// re-search, it can be corrupted in prev loop
itr = m_spells.find(spell_id);
@@ -3417,15 +3417,17 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool update_action_bar_
{
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id);
- // if talent then lesser rank also talent and need learn
+ // if talent then lesser rank also talent and need learn
if(talentCosts)
{
- //learnSpell (prev_id,false);
+ // I cannot see why mangos has these lines.
+ //if(learn_low_rank)
+ // learnSpell (prev_id,false);
}
- // if ranked non-stackable spell: need activate lesser rank and update dendence state
+ // if ranked non-stackable spell: need activate lesser rank and update dendence state
else if(cur_active && !SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0)
{
- // need manually update dependence state (learn spell ignore like attempts)
+ // need manually update dependence state (learn spell ignore like attempts)
PlayerSpellMap::iterator prev_itr = m_spells.find(prev_id);
if (prev_itr != m_spells.end())
{
@@ -3437,19 +3439,16 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool update_action_bar_
}
// now re-learn if need re-activate
- if(cur_active && !prev_itr->second->active)
+ if(cur_active && !prev_itr->second->active && learn_low_rank)
{
if(addSpell(prev_id,true,false,prev_itr->second->dependent,prev_itr->second->disabled))
{
- if(update_action_bar_for_low_rank)
- {
- // downgrade spell ranks in spellbook and action bar
- WorldPacket data(SMSG_SUPERCEDED_SPELL, 4 + 4);
- data << uint32(spell_id);
- data << uint32(prev_id);
- GetSession()->SendPacket( &data );
- prev_activate = true;
- }
+ // downgrade spell ranks in spellbook and action bar
+ WorldPacket data(SMSG_SUPERCEDED_SPELL, 4 + 4);
+ data << uint32(spell_id);
+ data << uint32(prev_id);
+ GetSession()->SendPacket( &data );
+ prev_activate = true;
}
}
}
@@ -3473,6 +3472,7 @@ void Player::RemoveSpellCooldown( uint32 spell_id, bool update /* = false */ )
SendClearCooldown(spell_id, this);
}
+// I am not sure which one is more efficient
void Player::RemoveCategoryCooldown( uint32 cat )
{
SpellCategoryStore::const_iterator i_scstore = sSpellCategoryStore.find(cat);
@@ -3481,6 +3481,22 @@ void Player::RemoveCategoryCooldown( uint32 cat )
RemoveSpellCooldown(*i_scset, true);
}
+void Player::RemoveSpellCategoryCooldown(uint32 cat, bool update /* = false */)
+{
+ SpellCategoryStore::const_iterator ct = sSpellCategoryStore.find(cat);
+ if (ct == sSpellCategoryStore.end())
+ return;
+
+ const SpellCategorySet& ct_set = ct->second;
+ for (SpellCooldowns::const_iterator i = m_spellCooldowns.begin(); i != m_spellCooldowns.end();)
+ {
+ if (ct_set.find(i->first) != ct_set.end())
+ RemoveSpellCooldown((i++)->first, update);
+ else
+ ++i;
+ }
+}
+
void Player::RemoveArenaSpellCooldowns()
{
// remove cooldowns on spells that has < 15 min CD
@@ -3664,7 +3680,13 @@ bool Player::resetTalents(bool no_cost)
uint32 itrFirstId = spellmgr.GetFirstSpellInChain(itr->first);
// unlearn if first rank is talent or learned by talent
- if (itrFirstId == talentInfo->RankID[j] || spellmgr.IsSpellLearnToSpell(talentInfo->RankID[j],itrFirstId))
+ if (itrFirstId == talentInfo->RankID[j])
+ {
+ removeSpell(itr->first,!IsPassiveSpell(itr->first),false);
+ itr = GetSpellMap().begin();
+ continue;
+ }
+ else if (spellmgr.IsSpellLearnToSpell(talentInfo->RankID[j],itrFirstId))
{
removeSpell(itr->first,!IsPassiveSpell(itr->first));
itr = GetSpellMap().begin();
@@ -17849,20 +17871,20 @@ void Player::InitDataForForm(bool reapplyMods)
}
// Return true is the bought item has a max count to force refresh of window by caller
-bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint64 bagguid, uint8 slot)
+bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint8 bag, uint8 slot)
{
// cheating attempt
- if(count < 1) count = 1;
+ if (count < 1) count = 1;
// cheating attempt
if(slot > MAX_BAG_SIZE && slot !=NULL_SLOT)
return false;
- if(!isAlive())
+ if (!isAlive())
return false;
ItemPrototype const *pProto = objmgr.GetItemPrototype( item );
- if( !pProto )
+ if (!pProto)
{
SendBuyError( BUY_ERR_CANT_FIND_ITEM, NULL, item, 0);
return false;
@@ -17884,7 +17906,7 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
}
size_t vendor_slot = vItems->FindItemSlot(item);
- if(vendor_slot >= vItems->GetItemCount())
+ if (vendor_slot >= vItems->GetItemCount())
{
SendBuyError( BUY_ERR_CANT_FIND_ITEM, pCreature, item, 0);
return false;
@@ -17893,39 +17915,39 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
VendorItem const* crItem = vItems->m_items[vendor_slot];
// check current item amount if it limited
- if( crItem->maxcount != 0 )
+ if (crItem->maxcount != 0)
{
- if(pCreature->GetVendorItemCurrentCount(crItem) < pProto->BuyCount * count )
+ if (pCreature->GetVendorItemCurrentCount(crItem) < pProto->BuyCount * count )
{
SendBuyError( BUY_ERR_ITEM_ALREADY_SOLD, pCreature, item, 0);
return false;
}
}
- if( uint32(GetReputationRank(pProto->RequiredReputationFaction)) < pProto->RequiredReputationRank)
+ if (uint32(GetReputationRank(pProto->RequiredReputationFaction)) < pProto->RequiredReputationRank)
{
SendBuyError( BUY_ERR_REPUTATION_REQUIRE, pCreature, item, 0);
return false;
}
- if(crItem->ExtendedCost)
+ if (crItem->ExtendedCost)
{
ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost);
- if(!iece)
+ if (!iece)
{
sLog.outError("Item %u have wrong ExtendedCost field value %u", pProto->ItemId, crItem->ExtendedCost);
return false;
}
// honor points price
- if(GetHonorPoints() < (iece->reqhonorpoints * count))
+ if (GetHonorPoints() < (iece->reqhonorpoints * count))
{
SendEquipError(EQUIP_ERR_NOT_ENOUGH_HONOR_POINTS, NULL, NULL);
return false;
}
// arena points price
- if(GetArenaPoints() < (iece->reqarenapoints * count))
+ if (GetArenaPoints() < (iece->reqarenapoints * count))
{
SendEquipError(EQUIP_ERR_NOT_ENOUGH_ARENA_POINTS, NULL, NULL);
return false;
@@ -17955,69 +17977,38 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
// reputation discount
price = uint32(floor(price * GetReputationPriceDiscount(pCreature)));
- if( GetMoney() < price )
+ if (GetMoney() < price)
{
SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, item, 0);
return false;
}
- uint8 bag = 0; // init for case invalid bagGUID
-
- if (bagguid != NULL_BAG && slot != NULL_SLOT)
- {
- if( bagguid == GetGUID() )
- {
- bag = INVENTORY_SLOT_BAG_0;
- }
- else
- {
- for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END;i++)
- {
- if( Bag *pBag = (Bag*)GetItemByPos(INVENTORY_SLOT_BAG_0,i) )
- {
- if( bagguid == pBag->GetGUID() )
- {
- // slot is counted from 0 but BagSize from 1
- if(slot+1 > pBag->GetBagSize())
- {
- sLog.outDebug("CHEATING ATTEMPT slot > bagSize in BuyItemFromVendor playerGUID: "I64FMT" name: %s slot: %u", GetGUID(), GetName(), slot);
- return false;
- }
- if(slot < pBag->GetBagSlot() && !pBag->GetItemByPos(slot))
- bag = i;
- break;
- }
- }
- }
- }
- }
-
- if( IsInventoryPos( bag, slot ) || (bagguid == NULL_BAG && slot == NULL_SLOT) )
+ if ((bag == NULL_BAG && slot == NULL_SLOT) || IsInventoryPos(bag, slot))
{
ItemPosCountVec dest;
uint8 msg = CanStoreNewItem( bag, slot, dest, item, pProto->BuyCount * count );
- if( msg != EQUIP_ERR_OK )
+ if (msg != EQUIP_ERR_OK)
{
SendEquipError( msg, NULL, NULL );
return false;
}
ModifyMoney( -(int32)price );
- if(crItem->ExtendedCost) // case for new honor system
+ if (crItem->ExtendedCost) // case for new honor system
{
ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost);
- if(iece->reqhonorpoints)
+ if (iece->reqhonorpoints)
ModifyHonorPoints( - int32(iece->reqhonorpoints * count));
- if(iece->reqarenapoints)
+ if (iece->reqarenapoints)
ModifyArenaPoints( - int32(iece->reqarenapoints * count));
for (uint8 i = 0; i < 5; ++i)
{
- if(iece->reqitem[i])
+ if (iece->reqitem[i])
DestroyItemCount(iece->reqitem[i], (iece->reqitemcount[i] * count), true);
}
}
- if(Item *it = StoreNewItem( dest, item, true ))
+ if (Item *it = StoreNewItem( dest, item, true ))
{
uint32 new_count = pCreature->UpdateVendorItemCurrentCount(crItem,pProto->BuyCount * count);
@@ -18031,9 +18022,9 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
SendNewItem(it, pProto->BuyCount*count, true, false, false);
}
}
- else if( IsEquipmentPos( bag, slot ) )
+ else if (IsEquipmentPos(bag, slot))
{
- if(pProto->BuyCount * count != 1)
+ if (pProto->BuyCount * count != 1)
{
SendEquipError( EQUIP_ERR_ITEM_CANT_BE_EQUIPPED, NULL, NULL );
return false;
@@ -18041,19 +18032,19 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
uint16 dest;
uint8 msg = CanEquipNewItem( slot, dest, item, false );
- if( msg != EQUIP_ERR_OK )
+ if (msg != EQUIP_ERR_OK)
{
SendEquipError( msg, NULL, NULL );
return false;
}
ModifyMoney( -(int32)price );
- if(crItem->ExtendedCost) // case for new honor system
+ if (crItem->ExtendedCost) // case for new honor system
{
ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(crItem->ExtendedCost);
- if(iece->reqhonorpoints)
+ if (iece->reqhonorpoints)
ModifyHonorPoints( - int32(iece->reqhonorpoints));
- if(iece->reqarenapoints)
+ if (iece->reqarenapoints)
ModifyArenaPoints( - int32(iece->reqarenapoints));
for (uint8 i = 0; i < 5; ++i)
{
@@ -18062,7 +18053,7 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
}
}
- if(Item *it = EquipNewItem( dest, item, true ))
+ if (Item *it = EquipNewItem( dest, item, true ))
{
uint32 new_count = pCreature->UpdateVendorItemCurrentCount(crItem,pProto->BuyCount * count);
@@ -18084,7 +18075,7 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
return false;
}
- return crItem->maxcount!=0;
+ return crItem->maxcount != 0;
}
uint32 Player::GetMaxPersonalArenaRatingRequirement()
@@ -19106,7 +19097,7 @@ void Player::resetSpells()
PlayerSpellMap smap = GetSpellMap();
for(PlayerSpellMap::const_iterator iter = smap.begin();iter != smap.end(); ++iter)
- removeSpell(iter->first); // only iter->first can be accessed, object by iter->second can be deleted already
+ removeSpell(iter->first,false,false); // only iter->first can be accessed, object by iter->second can be deleted already
learnDefaultSpells();
learnQuestRewardedSpells();
@@ -19167,8 +19158,10 @@ void Player::learnQuestRewardedSpells(Quest const* quest)
if(!learnedInfo)
return;
+ uint32 profSpell = spellmgr.GetSpellRequired(learned_0);
+
// specialization
- if(learnedInfo->Effect[0]==SPELL_EFFECT_TRADE_SKILL && learnedInfo->Effect[1]==0)
+ if(learnedInfo->Effect[0]==SPELL_EFFECT_TRADE_SKILL && learnedInfo->Effect[1]==0 && profSpell)
{
// search other specialization for same prof
for(PlayerSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
@@ -19185,11 +19178,7 @@ void Player::learnQuestRewardedSpells(Quest const* quest)
continue;
// compare same chain spells
- if(spellmgr.GetFirstSpellInChain(itr->first) != first_spell)
- continue;
-
- // now we have 2 specialization, learn possible only if found is lesser specialization rank
- if(!spellmgr.IsHighRankOfSpell(learned_0,itr->first))
+ if (spellmgr.GetSpellRequired(itr->first) == profSpell)
return;
}
}
diff --git a/src/game/Player.h b/src/game/Player.h
index 38de51033c3..17563688da6 100644
--- a/src/game/Player.h
+++ b/src/game/Player.h
@@ -1126,7 +1126,7 @@ class TRINITY_DLL_SPEC Player : public Unit
return mainItem && mainItem->GetProto()->InventoryType == INVTYPE_2HWEAPON && !CanTitanGrip();
}
void SendNewItem( Item *item, uint32 count, bool received, bool created, bool broadcast = false );
- bool BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint64 bagguid, uint8 slot);
+ bool BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint8 bag, uint8 slot);
float GetReputationPriceDiscount( Creature const* pCreature ) const;
Player* GetTrader() const { return pTrader; }
@@ -1395,7 +1395,7 @@ class TRINITY_DLL_SPEC Player : public Unit
void SendInitialSpells();
bool addSpell(uint32 spell_id, bool active, bool learning, bool dependent, bool disabled);
void learnSpell(uint32 spell_id, bool dependent);
- void removeSpell(uint32 spell_id, bool disabled = false, bool update_action_bar_for_low_rank = false);
+ void removeSpell(uint32 spell_id, bool disabled = false, bool learn_low_rank = true);
void resetSpells();
void learnDefaultSpells();
void learnQuestRewardedSpells();
@@ -1437,6 +1437,8 @@ class TRINITY_DLL_SPEC Player : public Unit
PlayerSpellMap const& GetSpellMap() const { return m_spells; }
PlayerSpellMap & GetSpellMap() { return m_spells; }
+ SpellCooldowns const& GetSpellCooldownMap() const { return m_spellCooldowns; }
+
void AddSpellMod(SpellModifier* mod, bool apply);
bool IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell * spell = NULL);
template <class T> T ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell * spell = NULL);
@@ -1463,6 +1465,7 @@ class TRINITY_DLL_SPEC Player : public Unit
void SendCooldownEvent(SpellEntry const *spellInfo, uint32 itemId = 0, Spell* spell = NULL);
void ProhibitSpellScholl(SpellSchoolMask idSchoolMask, uint32 unTimeMs );
void RemoveSpellCooldown(uint32 spell_id, bool update = false);
+ void RemoveSpellCategoryCooldown(uint32 cat, bool update = false);
void SendClearCooldown( uint32 spell_id, Unit* target );
void RemoveCategoryCooldown(uint32 cat);
diff --git a/src/game/PointMovementGenerator.cpp b/src/game/PointMovementGenerator.cpp
index ed057854aaa..24baa4939b4 100644
--- a/src/game/PointMovementGenerator.cpp
+++ b/src/game/PointMovementGenerator.cpp
@@ -32,7 +32,8 @@ void PointMovementGenerator<T>::Initialize(T &unit)
unit.StopMoving();
unit.clearUnitState(UNIT_STAT_MOVING);
Traveller<T> traveller(unit);
- i_destinationHolder.SetDestination(traveller,i_x,i_y,i_z, !unit.hasUnitState(UNIT_STAT_JUMPING));
+ // knockback effect has UNIT_STAT_JUMPING set,so if here we disable sentmonstermove there will be creature position sync problem between client and server
+ i_destinationHolder.SetDestination(traveller,i_x,i_y,i_z, true /* !unit.hasUnitState(UNIT_STAT_JUMPING)*/);
if (unit.GetTypeId() == TYPEID_UNIT && ((Creature*)&unit)->canFly())
unit.AddUnitMovementFlag(MOVEMENTFLAG_FLYING);
diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h
index 35e16f9d6bf..13d02702bb8 100644
--- a/src/game/SharedDefines.h
+++ b/src/game/SharedDefines.h
@@ -251,6 +251,7 @@ enum SpellCategory
#define SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY 0x20000000 // 29 unaffected by invulnerability (hmm possible not...)
#define SPELL_ATTR_BREAKABLE_BY_DAMAGE 0x40000000 // 30 breakable by damage?
#define SPELL_ATTR_CANT_CANCEL 0x80000000 // 31 positive aura can't be canceled
+
#define SPELL_ATTR_EX_DISMISS_PET 0x00000001 // 0 dismiss pet and not allow to summon new one?
#define SPELL_ATTR_EX_DRAIN_ALL_POWER 0x00000002 // 1 use all power (Only paladin Lay of Hands and Bunyanize)
#define SPELL_ATTR_EX_CHANNELED_1 0x00000004 // 2 channeled target
@@ -324,7 +325,7 @@ enum SpellCategory
#define SPELL_ATTR_EX3_UNK4 0x00000010 // 4 Druid Rebirth only this spell have this flag
#define SPELL_ATTR_EX3_UNK5 0x00000020 // 5
#define SPELL_ATTR_EX3_UNK6 0x00000040 // 6
-#define SPELL_ATTR_EX3_UNK7 0x00000080 // 7 separate stack for every caster
+#define SPELL_ATTR_EX3_STACKS_FOR_DIFFERENT_CASTERS 0x00000080 // 7 separate stack for every caster
#define SPELL_ATTR_EX3_PLAYERS_ONLY 0x00000100 // 8 Player only?
#define SPELL_ATTR_EX3_TRIGGERED_CAN_TRIGGER_2 0x00000200 // 9 triggered from effect?
#define SPELL_ATTR_EX3_MAIN_HAND 0x00000400 // 10 Main hand weapon required
@@ -336,7 +337,7 @@ enum SpellCategory
#define SPELL_ATTR_EX3_UNK16 0x00010000 // 16 no triggers effects that trigger on casting a spell??
#define SPELL_ATTR_EX3_NO_INITIAL_AGGRO 0x00020000 // 17 Soothe Animal, 39758, Mind Soothe
#define SPELL_ATTR_EX3_UNK18 0x00040000 // 18
-#define SPELL_ATTR_EX3_UNK19 0x00080000 // 19 spells triggered by spell with this flag can't proc caster auras and can proc from triggered (swings too - 20178)
+#define SPELL_ATTR_EX3_DISABLE_PROC 0x00080000 // 19 during aura proc no spells can trigger (20178, 20375)
#define SPELL_ATTR_EX3_DEATH_PERSISTENT 0x00100000 // 20 Death persistent spells
#define SPELL_ATTR_EX3_UNK21 0x00200000 // 21
#define SPELL_ATTR_EX3_REQ_WAND 0x00400000 // 22 Req wand
diff --git a/src/game/SkillDiscovery.cpp b/src/game/SkillDiscovery.cpp
index 2116e554a9f..837d39d4067 100644
--- a/src/game/SkillDiscovery.cpp
+++ b/src/game/SkillDiscovery.cpp
@@ -37,7 +37,7 @@ struct SkillDiscoveryEntry
SkillDiscoveryEntry()
: spellId(0), reqSkillValue(0), chance(0) {}
- SkillDiscoveryEntry(uint16 _spellId, uint32 req_skill_val, float _chance)
+ SkillDiscoveryEntry(uint32 _spellId, uint32 req_skill_val, float _chance)
: spellId(_spellId), reqSkillValue(req_skill_val), chance(_chance) {}
};
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index a0cd094a27b..8864c5f683f 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -809,27 +809,21 @@ void Spell::prepareDataForTriggerSystem(AuraEffect * triggeredByAura)
m_canTrigger=false;
}
- if (m_IsTriggeredSpell &&
- (m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_TRIGGERED_CAN_TRIGGER ||
- m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_TRIGGERED_CAN_TRIGGER_2))
- m_procEx |= PROC_EX_INTERNAL_CANT_PROC;
- else if (m_IsTriggeredSpell)
- m_procEx |= PROC_EX_INTERNAL_TRIGGERED;
-
+ // Ranged autorepeat attack is set as triggered spell - ignore it
+ if (!(m_procAttacker & PROC_FLAG_SUCCESSFUL_RANGED_HIT))
+ {
+ if (m_IsTriggeredSpell &&
+ (m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_TRIGGERED_CAN_TRIGGER ||
+ m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_TRIGGERED_CAN_TRIGGER_2))
+ m_procEx |= PROC_EX_INTERNAL_CANT_PROC;
+ else if (m_IsTriggeredSpell)
+ m_procEx |= PROC_EX_INTERNAL_TRIGGERED;
+ }
// Totem casts require spellfamilymask defined in spell_proc_event to proc
if (m_originalCaster && m_caster != m_originalCaster && m_caster->GetTypeId()==TYPEID_UNIT && ((Creature*)m_caster)->isTotem() && m_caster->IsControlledByPlayer())
{
m_procEx |= PROC_EX_INTERNAL_REQ_FAMILY;
}
- // Check done for judgements to make them not trigger seal effects
- else if (m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_UNK1)
- {
- // Rogue poisons
- if (m_spellInfo->SpellFamilyName && m_spellInfo->SpellFamilyFlags)
- m_procEx |= PROC_EX_INTERNAL_REQ_FAMILY;
- else
- m_canTrigger=false;
- }
}
}
@@ -1359,7 +1353,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask, bool
// Now Reduce spell duration using data received at spell hit
int32 duration = Aur->GetAuraMaxDuration();
int32 limitduration = GetDiminishingReturnsLimitDuration(m_diminishGroup,aurSpellInfo);
- unitTarget->ApplyDiminishingToDuration(m_diminishGroup, duration, m_caster, m_diminishLevel,limitduration);
+ unitTarget->ApplyDiminishingToDuration(m_diminishGroup, duration, caster, m_diminishLevel,limitduration);
Aur->setDiminishGroup(m_diminishGroup);
duration = caster->ModSpellDuration(aurSpellInfo, unit, duration, Aur->IsPositive());
@@ -2831,8 +2825,6 @@ void Spell::cast(bool skipCheck)
{
if (m_spellInfo->Mechanic == MECHANIC_BANDAGE) // Bandages
m_preCastSpell = 11196; // Recently Bandaged
- else if(m_spellInfo->SpellIconID == 1662 && m_spellInfo->AttributesEx & 0x20)
- m_preCastSpell = 23230; // Blood Fury - Healing Reduction
break;
}
case SPELLFAMILY_DRUID:
diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp
index e28e3c1b656..84755b8036e 100644
--- a/src/game/SpellAuras.cpp
+++ b/src/game/SpellAuras.cpp
@@ -960,7 +960,7 @@ void Aura::SendAuraUpdate()
data << uint32(GetId());
data << uint8(m_auraFlags);
data << uint8(m_auraLevel);
- data << uint8(m_stackAmount > 1 ? m_stackAmount : m_procCharges);
+ data << uint8(m_stackAmount > 1 ? m_stackAmount : (m_procCharges) ? m_procCharges : 1);
if(!(m_auraFlags & AFLAG_CASTER))
{
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp
index 67b87d7c93e..d8828e3f26b 100644
--- a/src/game/SpellEffects.cpp
+++ b/src/game/SpellEffects.cpp
@@ -1328,21 +1328,19 @@ void Spell::EffectDummy(uint32 i)
return;
// immediately finishes the cooldown on Frost spells
- const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
- for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
+ const SpellCooldowns& cm = ((Player *)m_caster)->GetSpellCooldownMap();
+ for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
{
- if (itr->second->state == PLAYERSPELL_REMOVED)
- continue;
-
- uint32 classspell = itr->first;
- SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
if( spellInfo->SpellFamilyName == SPELLFAMILY_MAGE &&
(GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) &&
spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0 )
{
- ((Player*)m_caster)->RemoveSpellCooldown(classspell, true);
+ ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first, true);
}
+ else
+ ++itr;
}
return;
}
@@ -1619,14 +1617,15 @@ void Spell::EffectDummy(uint32 i)
return;
//immediately finishes the cooldown on certain Rogue abilities
- const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
- for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
+ const SpellCooldowns& cm = ((Player *)m_caster)->GetSpellCooldownMap();
+ for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
{
- uint32 classspell = itr->first;
- SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags[1] & 0x00000240 || spellInfo->SpellFamilyFlags[0] & 0x00000860))
- ((Player*)m_caster)->RemoveSpellCooldown(classspell,true);
+ ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first,true);
+ else
+ ++itr;
}
return;
}
@@ -1646,14 +1645,15 @@ void Spell::EffectDummy(uint32 i)
return;
//immediately finishes the cooldown for hunter abilities
- const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
- for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
+ const SpellCooldowns& cm = ((Player*)m_caster)->GetSpellCooldownMap();
+ for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
{
- uint32 classspell = itr->first;
- SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 )
- ((Player*)m_caster)->RemoveSpellCooldown(classspell,true);
+ ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first,true);
+ else
+ ++itr;
}
return;
}
diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp
index 32759951f84..4ec9ff516d1 100644
--- a/src/game/SpellMgr.cpp
+++ b/src/game/SpellMgr.cpp
@@ -2586,6 +2586,16 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellEntry const* spellproto
// Explicit Diminishing Groups
switch(spellproto->SpellFamilyName)
{
+ case SPELLFAMILY_MAGE:
+ {
+ // Frostbite 0x80000000
+ if (spellproto->SpellFamilyFlags[1] & 0x80000000)
+ return DIMINISHING_TRIGGER_ROOT;
+ // Frost Nova / Freeze (Water Elemental)
+ else if (spellproto->SpellIconID == 193)
+ return DIMINISHING_CONTROL_ROOT;
+ break;
+ }
case SPELLFAMILY_ROGUE:
{
// Sap 0x80 Gouge 0x8
@@ -2597,6 +2607,9 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellEntry const* spellproto
// Cheap Shot
else if (spellproto->SpellFamilyFlags[0] & 0x400)
return DIMINISHING_CHEAPSHOT_POUNCE;
+ // Crippling poison - Limit to 10 seconds in PvP (No SpellFamilyFlags)
+ else if (spellproto->SpellIconID == 163)
+ return DIMINISHING_LIMITONLY;
break;
}
case SPELLFAMILY_WARLOCK:
@@ -2610,9 +2623,6 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellEntry const* spellproto
// Howl of Terror
else if (spellproto->SpellFamilyFlags[1] & 0x8)
return DIMINISHING_FEAR_BLIND;
- // Seduction
- else if (spellproto->SpellFamilyFlags[1] & 0x40000000)
- return DIMINISHING_CHARM;
break;
}
case SPELLFAMILY_DRUID:
@@ -2626,13 +2636,9 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellEntry const* spellproto
//Entangling Roots: to force natures grasp proc to be control root
else if (spellproto->SpellFamilyFlags[0] & 0x00000200)
return DIMINISHING_CONTROL_ROOT;
- break;
- }
- case SPELLFAMILY_MAGE:
- {
- // Frostbite
- if (spellproto->SpellFamilyFlags[1] & 0x80000000)
- return DIMINISHING_TRIGGER_ROOT;
+ // Faerie Fire
+ else if (spellproto->SpellFamilyFlags[0] & 0x400)
+ return DIMINISHING_LIMITONLY;
break;
}
case SPELLFAMILY_WARRIOR:
@@ -2715,6 +2721,13 @@ int32 GetDiminishingReturnsLimitDuration(DiminishingGroup group, SpellEntry cons
return 6000;
break;
}
+ case SPELLFAMILY_DRUID:
+ {
+ // Faerie Fire - limit to 40 seconds in PvP (3.1)
+ if (spellproto->SpellFamilyFlags[0] & 0x400)
+ return 40000;
+ break;
+ }
default:
break;
}
@@ -2754,9 +2767,9 @@ DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group)
case DIMINISHING_CONTROL_STUN:
case DIMINISHING_TRIGGER_STUN:
case DIMINISHING_CHEAPSHOT_POUNCE:
- case DIMINISHING_FEAR_BLIND:
case DIMINISHING_CYCLONE:
return DRTYPE_ALL;
+ case DIMINISHING_FEAR_BLIND:
case DIMINISHING_CONTROL_ROOT:
case DIMINISHING_TRIGGER_ROOT:
case DIMINISHING_CHARM:
@@ -2842,7 +2855,7 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2, bool
SpellSpecific spellId_spec_2 = GetSpellSpecific(spellId_2);
if (spellId_spec_1 && spellId_spec_2)
if (IsSingleFromSpellSpecificPerTarget(spellId_spec_1, spellId_spec_2)
- ||(IsSingleFromSpellSpecificPerCaster(spellId_spec_1, spellId_spec_2) && sameCaster))
+ ||(sameCaster && IsSingleFromSpellSpecificPerCaster(spellId_spec_1, spellId_spec_2)))
return true;
if(spellInfo_1->SpellFamilyName != spellInfo_2->SpellFamilyName)
@@ -2883,7 +2896,7 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2, bool
spellId_1 = GetLastSpellInChain(spellId_1);
// Hack for Incanter's Absorption
- if (spellId_1 == spellId_2 && spellId_1 == 44413)
+ if (spellId_1 == spellId_2 && (spellId_1 == 44413 || (!sameCaster && spellInfo_1->AttributesEx3 & SPELL_ATTR_EX3_STACKS_FOR_DIFFERENT_CASTERS)))
return false;
if (spellId_1 == spellId_2)
@@ -2917,7 +2930,7 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2, bool
|| spellInfo_1->EffectMiscValue[i] != spellInfo_2->EffectMiscValue[i]) // paladin resist aura
return false; // need itemtype check? need an example to add that check
- return true;
+ return (!(!sameCaster && spellInfo_1->AttributesEx3 & SPELL_ATTR_EX3_STACKS_FOR_DIFFERENT_CASTERS));
}
bool IsDispelableBySpell(SpellEntry const * dispelSpell, uint32 spellId, bool def)
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index 33a6c55433f..e2872012842 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -211,6 +211,10 @@ void Unit::Update( uint32 p_time )
m_Events.Update( p_time );
_UpdateSpells( p_time );
+ // If this is set during update SetCantProc(false) call is missing somewhere in the code
+ // Having this would prevent spells from being proced, so let's crash
+ assert(!m_procDeep)
+
if (CanHaveThreatList() && getThreatManager().isNeedUpdateToClient(p_time))
SendThreatListUpdate();
@@ -2785,11 +2789,9 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit *pVictim, SpellEntry const *spell)
tmp += resist_chance;
if (roll < tmp)
return SPELL_MISS_RESIST;
-
- // Ranged attack cannot be parry/dodge only deflect
- // Check damage class instead of attack type to correctly handle judgements
- // - they are meele, but can't be dodged/parried/deflected because of ranged dmg class
- if (spell->DmgClass == SPELL_DAMAGE_CLASS_RANGED)
+
+ // Ranged attacks can only miss, resist and deflect
+ if (attType == RANGED_ATTACK)
{
// only if in front
if (pVictim->HasInArc(M_PI,this))
@@ -4858,6 +4860,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
uint32 triggered_spell_id = 0;
Unit* target = pVictim;
int32 basepoints0 = 0;
+ uint64 originalCaster = 0;
// Master of subtlety (checked here because ranks have different spellfamilynames)
if (dummySpell->Id == 31223 || dummySpell->Id == 31221 || dummySpell->Id == 31222)
@@ -6588,6 +6591,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
// Earth Shield
if(dummySpell->SpellFamilyFlags[1] & 0x00000400)
{
+ // 3.0.8: Now correctly uses the Shaman's own spell critical strike chance to determine the chance of a critical heal.
+ originalCaster = triggeredByAura->GetCasterGUID();
basepoints0 = triggerAmount;
target = this;
triggered_spell_id = 379;
@@ -6951,9 +6956,9 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
return false;
if(basepoints0)
- CastCustomSpell(target,triggered_spell_id,&basepoints0,NULL,NULL,true,castItem,triggeredByAura);
+ CastCustomSpell(target,triggered_spell_id,&basepoints0,NULL,NULL,true,castItem,triggeredByAura, originalCaster);
else
- CastSpell(target,triggered_spell_id,true,castItem,triggeredByAura);
+ CastSpell(target,triggered_spell_id,true,castItem,triggeredByAura, originalCaster);
if( cooldown && GetTypeId()==TYPEID_PLAYER )
((Player*)this)->AddSpellCooldown(triggered_spell_id,0,time(NULL) + cooldown);
@@ -7789,9 +7794,9 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig
// Sword and Board
case 50227:
{
- // remove cooldown of Shield Slam
+ // Remove cooldown on Shield Slam
if (GetTypeId()==TYPEID_PLAYER)
- ((Player*)this)->RemoveCategoryCooldown(1209);
+ ((Player*)this)->RemoveSpellCategoryCooldown(1209, true);
break;
}
case 63375: // Improved Stormstrike
@@ -9496,8 +9501,9 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM
float crit_chance = 0.0f;
switch(spellProto->DmgClass)
{
- case SPELL_DAMAGE_CLASS_NONE:
- return false;
+ case SPELL_DAMAGE_CLASS_NONE: // Exception for earth shield
+ if (spellProto->Id != 379) // We need more spells to find a general way (if there is any)
+ return false;
case SPELL_DAMAGE_CLASS_MAGIC:
{
if (schoolMask & SPELL_SCHOOL_MASK_NORMAL)
@@ -10526,6 +10532,7 @@ void Unit::SetInCombatState(bool PvP, Unit* enemy)
if(GetTypeId() != TYPEID_PLAYER)
{
//if(GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_IDLE) != IDLE_MOTION_TYPE)
+ if (((Creature *)this)->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
((Creature*)this)->SetHomePosition(GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
if(enemy)
{
@@ -11291,7 +11298,7 @@ Unit* Creature::SelectVictim()
// it in combat but attacker not make any damage and not enter to aggro radius to have record in threat list
// for example at owner command to pet attack some far away creature
// Note: creature not have targeted movement generator but have attacker in this case
- if(m_attackers.size())
+ if(m_attackers.size() && m_ThreatManager.isThreatListEmpty()) //there are some cases null target are always returned,so creature evade can not be called at all. such as pull creature at a distance beyond the attackdist to the attacker
return NULL;
/*if( GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE )
{
@@ -11532,7 +11539,7 @@ void Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration,Un
if(duration == -1 || group == DIMINISHING_NONE || caster->IsFriendlyTo(this) )
return;
- // test pet/charm masters instead pets/charmeds
+ // test pet/charm masters instead pets/charmeds
Unit const* targetOwner = GetCharmerOrOwner();
Unit const* casterOwner = caster->GetCharmerOrOwner();
@@ -11549,7 +11556,7 @@ void Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration,Un
float mod = 1.0f;
// Some diminishings applies to mobs too (for example, Stun)
- if((GetDiminishingReturnsGroupType(group) == DRTYPE_PLAYER && (targetOwner ? targetOwner->GetTypeId():GetTypeId()) == TYPEID_PLAYER) || GetDiminishingReturnsGroupType(group) == DRTYPE_ALL)
+ if((GetDiminishingReturnsGroupType(group) == DRTYPE_PLAYER && (targetOwner ? (targetOwner->GetTypeId() == TYPEID_PLAYER) : (GetTypeId() == TYPEID_PLAYER))) || GetDiminishingReturnsGroupType(group) == DRTYPE_ALL)
{
DiminishingLevels diminish = Level;
switch(diminish)
@@ -12636,6 +12643,9 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
if (GetTypeId() == TYPEID_PLAYER && i->spellProcEvent && i->spellProcEvent->cooldown)
cooldown = i->spellProcEvent->cooldown;
+ if (spellInfo->AttributesEx3 & SPELL_ATTR_EX3_DISABLE_PROC)
+ SetCantProc(true);
+
// This bool is needed till separate aura effect procs are still here
bool handled = false;
if (HandleAuraProc(pTarget, damage, i->aura, procSpell, procFlag, procExtra, cooldown, &handled))
@@ -12660,8 +12670,8 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
{
sLog.outDebug("ProcDamageAndSpell: casting spell %u (triggered by %s aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
// Don`t drop charge or add cooldown for not started trigger
- if (!HandleProcTriggerSpell(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
- continue;
+ if (HandleProcTriggerSpell(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
+ takeCharges=true;
break;
}
case SPELL_AURA_PROC_TRIGGER_DAMAGE:
@@ -12679,47 +12689,57 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
case SPELL_AURA_DUMMY:
{
sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s dummy aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
- if (!HandleDummyAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
- continue;
- if (procDebug & 1)
- sLog.outError("Dummy aura of spell %d procs twice from one effect!",spellInfo->Id);
- procDebug |= 1;
+ if (HandleDummyAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
+ {
+ takeCharges=true;
+ if (procDebug & 1)
+ sLog.outError("Dummy aura of spell %d procs twice from one effect!",spellInfo->Id);
+ procDebug |= 1;
+ }
break;
}
case SPELL_AURA_OBS_MOD_ENERGY:
sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
- if (!HandleObsModEnergyAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
- continue;
- if (procDebug & 2)
- sLog.outError("ObsModEnergy aura of spell %d procs twice from one effect!",spellInfo->Id);
- procDebug |= 2;
+ if (HandleObsModEnergyAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
+ {
+ takeCharges=true;
+ if (procDebug & 2)
+ sLog.outError("ObsModEnergy aura of spell %d procs twice from one effect!",spellInfo->Id);
+ procDebug |= 2;
+ }
break;
case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN:
sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
- if (!HandleModDamagePctTakenAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
- continue;
- if (procDebug & 16)
- sLog.outError("ModDamagePctTaken aura of spell %d procs twice from one effect!",spellInfo->Id);
- procDebug |= 16;
+ if (HandleModDamagePctTakenAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
+ {
+ takeCharges=true;
+ if (procDebug & 16)
+ sLog.outError("ModDamagePctTaken aura of spell %d procs twice from one effect!",spellInfo->Id);
+ procDebug |= 16;
+ }
break;
case SPELL_AURA_MOD_HASTE:
{
sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s haste aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
- if (!HandleHasteAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
- continue;
- if (procDebug & 4)
- sLog.outError("Haste aura of spell %d procs twice from one effect!",spellInfo->Id);
- procDebug |= 4;
+ if (HandleHasteAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
+ {
+ takeCharges=true;
+ if (procDebug & 4)
+ sLog.outError("Haste aura of spell %d procs twice from one effect!",spellInfo->Id);
+ procDebug |= 4;
+ }
break;
}
case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS:
{
sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
- if (!HandleOverrideClassScriptAuraProc(pTarget, damage, triggeredByAura, procSpell, cooldown))
- continue;
- if (procDebug & 8)
- sLog.outError("OverrideClassScripts aura of spell %d procs twice from one effect!",spellInfo->Id);
- procDebug |= 8;
+ if (HandleOverrideClassScriptAuraProc(pTarget, damage, triggeredByAura, procSpell, cooldown))
+ {
+ takeCharges=true;
+ if (procDebug & 8)
+ sLog.outError("OverrideClassScripts aura of spell %d procs twice from one effect!",spellInfo->Id);
+ procDebug |= 8;
+ }
break;
}
case SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE:
@@ -12742,46 +12762,46 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
{
sLog.outDebug("ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
- if (!HandleProcTriggerSpell(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
- continue;
+ if (HandleProcTriggerSpell(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
+ takeCharges=true;
break;
}
case SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK:
// Skip melee hits or instant cast spells
- if (procSpell == NULL || GetSpellCastTime(procSpell) == 0)
- continue;
+ if (procSpell && GetSpellCastTime(procSpell) != 0)
+ takeCharges=true;
break;
case SPELL_AURA_REFLECT_SPELLS_SCHOOL:
// Skip Melee hits and spells ws wrong school
- if (procSpell == NULL || (triggeredByAura->GetMiscValue() & procSpell->SchoolMask) == 0)
- continue;
+ if (procSpell && (triggeredByAura->GetMiscValue() & procSpell->SchoolMask)) // School check
+ takeCharges=true;
break;
case SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT:
case SPELL_AURA_MOD_POWER_COST_SCHOOL:
// Skip melee hits and spells ws wrong school or zero cost
- if (procSpell == NULL ||
- (procSpell->manaCost == 0 && procSpell->ManaCostPercentage == 0) || // Cost check
+ if (procSpell &&
+ (procSpell->manaCost != 0 || procSpell->ManaCostPercentage != 0) && // Cost check
(triggeredByAura->GetMiscValue() & procSpell->SchoolMask) == 0) // School check
- continue;
+ takeCharges=true;
break;
case SPELL_AURA_MECHANIC_IMMUNITY:
// Compare mechanic
- if (procSpell==NULL || procSpell->Mechanic != triggeredByAura->GetMiscValue())
- continue;
+ if (procSpell && procSpell->Mechanic == triggeredByAura->GetMiscValue())
+ takeCharges=true;
break;
case SPELL_AURA_MOD_MECHANIC_RESISTANCE:
// Compare mechanic
- if (procSpell==NULL || procSpell->Mechanic != triggeredByAura->GetMiscValue())
- continue;
+ if (procSpell && procSpell->Mechanic == triggeredByAura->GetMiscValue())
+ takeCharges=true;
break;
case SPELL_AURA_MOD_DAMAGE_FROM_CASTER:
// Compare casters
- if (triggeredByAura->GetCasterGUID() != pTarget->GetGUID())
- continue;
+ if (triggeredByAura->GetCasterGUID() == pTarget->GetGUID())
+ takeCharges=true;
break;
case SPELL_AURA_MOD_SPELL_CRIT_CHANCE:
- if (!procSpell)
- continue;
+ if (procSpell)
+ takeCharges=true;
break;
// These auras may not have charges - that means they have chance to remove based on dmg
case SPELL_AURA_MOD_FEAR:
@@ -12795,6 +12815,8 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
if (roll_chance_f(chance))
RemoveAura(i->aura);
}
+ else
+ takeCharges=true;
break;
/*case SPELL_AURA_ADD_FLAT_MODIFIER:
case SPELL_AURA_ADD_PCT_MODIFIER:
@@ -12802,15 +12824,17 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
break;*/
default:
// nothing do, just charges counter
+ takeCharges=true;
break;
}
- takeCharges=true;
}
// Remove charge (aura can be removed by triggers)
if(useCharges && takeCharges)
{
i->aura->DropAuraCharge();
}
+ if (spellInfo->AttributesEx3 & SPELL_ATTR_EX3_DISABLE_PROC)
+ SetCantProc(false);
}
// Cleanup proc requirements